diff --git a/storage/bdb/LICENSE b/storage/bdb/LICENSE
index 1cd727bfd981d17ed7cb20025c2cad5d8c1e9a68..8cb10e79bf8aed31413ac1dec2da56bb56ceed45 100644
--- a/storage/bdb/LICENSE
+++ b/storage/bdb/LICENSE
@@ -1,16 +1,16 @@
 /*-
- * $Id: LICENSE,v 11.9 2002/01/11 15:51:10 bostic Exp $
+ * $Id: LICENSE,v 11.12 2004/03/30 20:49:44 bostic Exp $
  */
 
 The following is the license that applies to this copy of the Berkeley DB
 software.  For a license to use the Berkeley DB software under conditions
 other than those described here, or to purchase support for this software,
-please contact Sleepycat Software by email at db@sleepycat.com, or on the
-Web at http://www.sleepycat.com.
+please contact Sleepycat Software by email at info@sleepycat.com, or on
+the Web at http://www.sleepycat.com.
 
 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 /*
- * Copyright (c) 1990-2002
+ * Copyright (c) 1990-2004
  *	Sleepycat Software.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/storage/bdb/btree/bt_compare.c b/storage/bdb/btree/bt_compare.c
index cbe2a1a71706ab0fb7baabe8279971e137c8ae25..81ffe098b10724cf5c76254124bd7884ba611a60 100644
--- a/storage/bdb/btree/bt_compare.c
+++ b/storage/bdb/btree/bt_compare.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -38,14 +38,12 @@
  * 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.
+ *
+ * $Id: bt_compare.c,v 11.20 2004/02/21 15:54:44 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: bt_compare.c,v 11.17 2002/03/27 04:30:42 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #endif
@@ -204,8 +202,12 @@ __bam_defpfx(dbp, a, b)
 			return (cnt);
 
 	/*
-	 * We know that a->size must be <= b->size, or they wouldn't be
-	 * in this order.
+	 * They match up to the smaller of the two sizes.
+	 * Collate the longer after the shorter.
 	 */
-	return (a->size < b->size ? a->size + 1 : a->size);
+	if (a->size < b->size)
+		return (a->size + 1);
+	if (b->size < a->size)
+		return (b->size + 1);
+	return (b->size);
 }
diff --git a/storage/bdb/btree/bt_conv.c b/storage/bdb/btree/bt_conv.c
index 4264b62ffdd3ab6f48872f88a7399e7eadf3d0ef..39a9d825388061a478df9825fd5eea9d3b2f7539 100644
--- a/storage/bdb/btree/bt_conv.c
+++ b/storage/bdb/btree/bt_conv.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: bt_conv.c,v 11.15 2004/01/28 03:35:48 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: bt_conv.c,v 11.13 2002/08/06 06:11:12 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #endif
diff --git a/storage/bdb/btree/bt_curadj.c b/storage/bdb/btree/bt_curadj.c
index 50d3d422e495ff3a5a9cc3b46380e96eaebd2b5c..477f00b8ff8a1844bd9eb6d870e584ef282da55f 100644
--- a/storage/bdb/btree/bt_curadj.c
+++ b/storage/bdb/btree/bt_curadj.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: bt_curadj.c,v 11.37 2004/03/13 14:11:33 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: bt_curadj.c,v 11.30 2002/07/03 19:03:48 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #endif
@@ -21,30 +19,6 @@ static const char revid[] = "$Id: bt_curadj.c,v 11.30 2002/07/03 19:03:48 bostic
 
 static int __bam_opd_cursor __P((DB *, DBC *, db_pgno_t, u_int32_t, u_int32_t));
 
-#ifdef DEBUG
-/*
- * __bam_cprint --
- *	Display the current internal cursor.
- *
- * PUBLIC: void __bam_cprint __P((DBC *));
- */
-void
-__bam_cprint(dbc)
-	DBC *dbc;
-{
-	BTREE_CURSOR *cp;
-
-	cp = (BTREE_CURSOR *)dbc->internal;
-
-	fprintf(stderr, "\tinternal: ovflsize: %lu", (u_long)cp->ovflsize);
-	if (dbc->dbtype == DB_RECNO)
-		fprintf(stderr, " recno: %lu", (u_long)cp->recno);
-	if (F_ISSET(cp, C_DELETED))
-		fprintf(stderr, " (deleted)");
-	fprintf(stderr, "\n");
-}
-#endif
-
 /*
  * Cursor adjustments are logged if they are for subtransactions.  This is
  * because it's possible for a subtransaction to adjust cursors which will
@@ -98,6 +72,19 @@ __bam_ca_delete(dbp, pgno, indx, delete)
 		    dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
 			cp = (BTREE_CURSOR *)dbc->internal;
 			if (cp->pgno == pgno && cp->indx == indx) {
+				/*
+				 * [#8032] This assert is checking
+				 * for possible race conditions where we
+				 * hold a cursor position without a lock.
+				 * Unfortunately, there are paths in the
+				 * Btree code that do not satisfy these
+				 * conditions. None of them are known to
+				 * be a problem, but this assert should
+				 * be re-activated when the Btree stack
+				 * code is re-written.
+				DB_ASSERT(!STD_LOCKING(dbc) ||
+				    cp->lock_mode != DB_LOCK_NG);
+				 */
 				if (delete)
 					F_SET(cp, C_DELETED);
 				else
@@ -192,7 +179,10 @@ __bam_ca_di(my_dbc, pgno, indx, adjust)
 			if (cp->pgno == pgno && cp->indx >= indx) {
 				/* Cursor indices should never be negative. */
 				DB_ASSERT(cp->indx != 0 || adjust > 0);
-
+				/* [#8032]
+				DB_ASSERT(!STD_LOCKING(dbc) ||
+				    cp->lock_mode != DB_LOCK_NG);
+				*/
 				cp->indx += adjust;
 				if (my_txn != NULL && dbc->txn != my_txn)
 					found = 1;
@@ -203,8 +193,8 @@ __bam_ca_di(my_dbc, pgno, indx, adjust)
 	MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
 
 	if (found != 0 && DBC_LOGGING(my_dbc)) {
-		if ((ret = __bam_curadj_log(dbp, my_dbc->txn,
-		    &lsn, 0, DB_CA_DI, pgno, 0, 0, adjust, indx, 0)) != 0)
+		if ((ret = __bam_curadj_log(dbp, my_dbc->txn, &lsn, 0,
+		    DB_CA_DI, pgno, 0, 0, (u_int32_t)adjust, indx, 0)) != 0)
 			return (ret);
 	}
 
@@ -319,6 +309,10 @@ loop:		MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
 				continue;
 
 			MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
+			/* [#8032]
+			DB_ASSERT(!STD_LOCKING(dbc) ||
+			    orig_cp->lock_mode != DB_LOCK_NG);
+			*/
 			if ((ret = __bam_opd_cursor(dbp,
 			    dbc, first, tpgno, ti)) !=0)
 				return (ret);
@@ -388,7 +382,7 @@ loop:		MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
 			    != ti)
 				continue;
 			MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
-			if ((ret = orig_cp->opd->c_close(orig_cp->opd)) != 0)
+			if ((ret = __db_c_close(orig_cp->opd)) != 0)
 				return (ret);
 			orig_cp->opd = NULL;
 			orig_cp->indx = fi;
@@ -442,6 +436,10 @@ __bam_ca_rsplit(my_dbc, fpgno, tpgno)
 				continue;
 			if (dbc->internal->pgno == fpgno) {
 				dbc->internal->pgno = tpgno;
+				/* [#8032]
+				DB_ASSERT(!STD_LOCKING(dbc) ||
+				    dbc->internal->lock_mode != DB_LOCK_NG);
+				*/
 				if (my_txn != NULL && dbc->txn != my_txn)
 					found = 1;
 			}
@@ -506,6 +504,10 @@ __bam_ca_split(my_dbc, ppgno, lpgno, rpgno, split_indx, cleft)
 				continue;
 			cp = dbc->internal;
 			if (cp->pgno == ppgno) {
+				/* [#8032]
+				DB_ASSERT(!STD_LOCKING(dbc) ||
+				    cp->lock_mode != DB_LOCK_NG);
+				*/
 				if (my_txn != NULL && dbc->txn != my_txn)
 					found = 1;
 				if (cp->indx < split_indx) {
diff --git a/storage/bdb/btree/bt_cursor.c b/storage/bdb/btree/bt_cursor.c
index 14d90e8873d430e76d1e02928cf809b8872abb24..82d6cc43556b303215f203909ab568002bb35347 100644
--- a/storage/bdb/btree/bt_cursor.c
+++ b/storage/bdb/btree/bt_cursor.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: bt_cursor.c,v 11.190 2004/09/22 21:46:32 ubell Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: bt_cursor.c,v 11.147 2002/08/13 20:46:07 ubell Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -22,6 +20,7 @@ static const char revid[] = "$Id: bt_cursor.c,v 11.147 2002/08/13 20:46:07 ubell
 #include "dbinc/db_shash.h"
 #include "dbinc/btree.h"
 #include "dbinc/lock.h"
+#include "dbinc/mp.h"
 
 static int  __bam_bulk __P((DBC *, DBT *, u_int32_t));
 static int  __bam_c_close __P((DBC *, db_pgno_t, int *));
@@ -52,28 +51,28 @@ static int  __bam_isopd __P((DBC *, db_pgno_t *));
  * don't -- we don't duplicate locks when we duplicate cursors if we are
  * running in a transaction environment as there's no point if locks are
  * never discarded.  This means that the cursor may or may not hold a lock.
- * In the case where we are decending the tree we always want to
- * unlock the held interior page so we use ACQUIRE_COUPLE.
+ * In the case where we are descending the tree we always want to unlock
+ * the held interior page so we use ACQUIRE_COUPLE.
  */
 #undef	ACQUIRE
-#define	ACQUIRE(dbc, mode, lpgno, lock, fpgno, pagep, ret) {		\
+#define	ACQUIRE(dbc, mode, lpgno, lock, fpgno, pagep, ret) do {		\
 	DB_MPOOLFILE *__mpf = (dbc)->dbp->mpf;				\
 	if ((pagep) != NULL) {						\
-		ret = __mpf->put(__mpf, pagep, 0);			\
+		ret = __memp_fput(__mpf, pagep, 0);			\
 		pagep = NULL;						\
 	} else								\
 		ret = 0;						\
 	if ((ret) == 0 && STD_LOCKING(dbc))				\
 		ret = __db_lget(dbc, LCK_COUPLE, lpgno, mode, 0, &(lock));\
 	if ((ret) == 0)							\
-		ret = __mpf->get(__mpf, &(fpgno), 0, &(pagep));		\
-}
+		ret = __memp_fget(__mpf, &(fpgno), 0, &(pagep));	\
+} while (0)
 
 #undef	ACQUIRE_COUPLE
-#define	ACQUIRE_COUPLE(dbc, mode, lpgno, lock, fpgno, pagep, ret) {	\
+#define	ACQUIRE_COUPLE(dbc, mode, lpgno, lock, fpgno, pagep, ret) do {	\
 	DB_MPOOLFILE *__mpf = (dbc)->dbp->mpf;				\
 	if ((pagep) != NULL) {						\
-		ret = __mpf->put(__mpf, pagep, 0);			\
+		ret = __memp_fput(__mpf, pagep, 0);			\
 		pagep = NULL;						\
 	} else								\
 		ret = 0;						\
@@ -81,34 +80,38 @@ static int  __bam_isopd __P((DBC *, db_pgno_t *));
 		ret = __db_lget(dbc,					\
 		    LCK_COUPLE_ALWAYS, lpgno, mode, 0, &(lock));	\
 	if ((ret) == 0)							\
-		ret = __mpf->get(__mpf, &(fpgno), 0, &(pagep));		\
-}
+		ret = __memp_fget(__mpf, &(fpgno), 0, &(pagep));	\
+} while (0)
 
 /* Acquire a new page/lock for a cursor. */
 #undef	ACQUIRE_CUR
-#define	ACQUIRE_CUR(dbc, mode, p, ret) {				\
+#define	ACQUIRE_CUR(dbc, mode, p, ret) do {				\
 	BTREE_CURSOR *__cp = (BTREE_CURSOR *)(dbc)->internal;		\
+	if (p != __cp->pgno)						\
+		__cp->pgno = PGNO_INVALID;				\
 	ACQUIRE(dbc, mode, p, __cp->lock, p, __cp->page, ret);		\
 	if ((ret) == 0) {						\
 		__cp->pgno = p;						\
 		__cp->lock_mode = (mode);				\
 	}								\
-}
+} while (0)
 
 /*
  * Acquire a new page/lock for a cursor and release the previous.
- * This is typically used when decending a tree and we do not
+ * This is typically used when descending a tree and we do not
  * want to hold the interior nodes locked.
  */
 #undef	ACQUIRE_CUR_COUPLE
-#define	ACQUIRE_CUR_COUPLE(dbc, mode, p, ret) {				\
+#define	ACQUIRE_CUR_COUPLE(dbc, mode, p, ret) do {			\
 	BTREE_CURSOR *__cp = (BTREE_CURSOR *)(dbc)->internal;		\
+	if (p != __cp->pgno)						\
+		__cp->pgno = PGNO_INVALID;				\
 	ACQUIRE_COUPLE(dbc, mode, p, __cp->lock, p, __cp->page, ret);	\
 	if ((ret) == 0) {						\
 		__cp->pgno = p;						\
 		__cp->lock_mode = (mode);				\
 	}								\
-}
+} while (0)
 
 /*
  * Acquire a write lock if we don't already have one.
@@ -117,7 +120,7 @@ static int  __bam_isopd __P((DBC *, db_pgno_t *));
  * See ACQUIRE macro on why we handle cursors that don't have locks.
  */
 #undef	ACQUIRE_WRITE_LOCK
-#define	ACQUIRE_WRITE_LOCK(dbc, ret) {					\
+#define	ACQUIRE_WRITE_LOCK(dbc, ret) do {				\
 	BTREE_CURSOR *__cp = (BTREE_CURSOR *)(dbc)->internal;		\
 	ret = 0;							\
 	if (STD_LOCKING(dbc) &&						\
@@ -126,34 +129,27 @@ static int  __bam_isopd __P((DBC *, db_pgno_t *));
 	    LOCK_ISSET(__cp->lock) ? LCK_COUPLE : 0,			\
 	    __cp->pgno, DB_LOCK_WRITE, 0, &__cp->lock)) == 0)		\
 		__cp->lock_mode = DB_LOCK_WRITE;			\
-}
+} while (0)
 
-/* Discard the current page/lock. */
-#undef	DISCARD
-#define	DISCARD(dbc, ldiscard, lock, pagep, ret) {			\
+/* Discard the current page/lock for a cursor. */
+#undef	DISCARD_CUR
+#define	DISCARD_CUR(dbc, ret) do {					\
+	BTREE_CURSOR *__cp = (BTREE_CURSOR *)(dbc)->internal;		\
 	DB_MPOOLFILE *__mpf = (dbc)->dbp->mpf;				\
 	int __t_ret;							\
-	if ((pagep) != NULL) {						\
-		ret = __mpf->put(__mpf, pagep, 0);			\
-		pagep = NULL;						\
+	if ((__cp->page) != NULL) {					\
+		__t_ret = __memp_fput(__mpf, __cp->page, 0);		\
+		__cp->page = NULL;					\
 	} else								\
-		ret = 0;						\
-	if (ldiscard)							\
-		__t_ret = __LPUT((dbc), lock);				\
-	else								\
-		__t_ret = __TLPUT((dbc), lock);				\
+		__t_ret = 0;						\
 	if (__t_ret != 0 && (ret) == 0)					\
 		ret = __t_ret;						\
-}
-
-/* Discard the current page/lock for a cursor. */
-#undef	DISCARD_CUR
-#define	DISCARD_CUR(dbc, ret) {						\
-	BTREE_CURSOR *__cp = (BTREE_CURSOR *)(dbc)->internal;		\
-	DISCARD(dbc, 0, __cp->lock, __cp->page, ret);			\
-	if ((ret) == 0)							\
+	__t_ret = __TLPUT((dbc), __cp->lock);				\
+	if (__t_ret != 0 && (ret) == 0)					\
+		ret = __t_ret;						\
+	if ((ret) == 0 && !LOCK_ISSET(__cp->lock))			\
 		__cp->lock_mode = DB_LOCK_NG;				\
-}
+} while (0)
 
 /* If on-page item is a deleted record. */
 #undef	IS_DELETED
@@ -205,12 +201,12 @@ __bam_c_init(dbc, dbtype)
 
 	/* Initialize methods. */
 	dbc->c_close = __db_c_close;
-	dbc->c_count = __db_c_count;
-	dbc->c_del = __db_c_del;
-	dbc->c_dup = __db_c_dup;
-	dbc->c_get = dbc->c_real_get = __db_c_get;
-	dbc->c_pget = __db_c_pget;
-	dbc->c_put = __db_c_put;
+	dbc->c_count = __db_c_count_pp;
+	dbc->c_del = __db_c_del_pp;
+	dbc->c_dup = __db_c_dup_pp;
+	dbc->c_get = __db_c_get_pp;
+	dbc->c_pget = __db_c_pget_pp;
+	dbc->c_put = __db_c_put_pp;
 	if (dbtype == DB_BTREE) {
 		dbc->c_am_bulk = __bam_bulk;
 		dbc->c_am_close = __bam_c_close;
@@ -312,7 +308,7 @@ __bam_c_close(dbc, root_pgno, rmroot)
 	DBC *dbc_opd, *dbc_c;
 	DB_MPOOLFILE *mpf;
 	PAGE *h;
-	int cdb_lock, ret, t_ret;
+	int cdb_lock, ret;
 
 	dbp = dbc->dbp;
 	mpf = dbp->mpf;
@@ -392,6 +388,9 @@ __bam_c_close(dbc, root_pgno, rmroot)
 			if (__ram_ca_delete(dbp, cp->root) == 0)
 				goto lock;
 			goto done;
+		case DB_HASH:
+		case DB_QUEUE:
+		case DB_UNKNOWN:
 		default:
 			return (__db_unknown_type(dbp->dbenv,
 				"__bam_c_close", dbc->dbtype));
@@ -406,10 +405,10 @@ __bam_c_close(dbc, root_pgno, rmroot)
 		 * We will not have been provided a root page number.  Acquire
 		 * one from the primary database.
 		 */
-		if ((ret = mpf->get(mpf, &cp->pgno, 0, &h)) != 0)
+		if ((ret = __memp_fget(mpf, &cp->pgno, 0, &h)) != 0)
 			goto err;
 		root_pgno = GET_BOVERFLOW(dbp, h, cp->indx + O_INDX)->pgno;
-		if ((ret = mpf->put(mpf, h, 0)) != 0)
+		if ((ret = __memp_fput(mpf, h, 0)) != 0)
 			goto err;
 
 		dbc_c = dbc_opd;
@@ -423,9 +422,12 @@ __bam_c_close(dbc, root_pgno, rmroot)
 			if (__ram_ca_delete(dbp, cp_opd->root) == 0)
 				goto lock;
 			goto done;
+		case DB_HASH:
+		case DB_QUEUE:
+		case DB_UNKNOWN:
 		default:
-			return (__db_unknown_type(dbp->dbenv,
-				"__bam_c_close", dbc->dbtype));
+			return (__db_unknown_type(
+			   dbp->dbenv, "__bam_c_close", dbc->dbtype));
 		}
 	}
 	goto done;
@@ -436,55 +438,41 @@ lock:	cp_c = (BTREE_CURSOR *)dbc_c->internal;
 	 * If this is CDB, upgrade the lock if necessary.  While we acquired
 	 * the write lock to logically delete the record, we released it when
 	 * we returned from that call, and so may not be holding a write lock
-	 * at the moment.  NB: to get here in CDB we must either be holding a
-	 * write lock or be the only cursor that is permitted to acquire write
-	 * locks.  The reason is that there can never be more than a single CDB
-	 * write cursor (that cursor cannot be dup'd), and so that cursor must
-	 * be closed and the item therefore deleted before any other cursor
-	 * could acquire a reference to this item.
-	 *
-	 * Note that dbc may be an off-page dup cursor;  this is the sole
-	 * instance in which an OPD cursor does any locking, but it's necessary
-	 * because we may be closed by ourselves without a parent cursor
-	 * handy, and we have to do a lock upgrade on behalf of somebody.
-	 * If this is the case, the OPD has been given the parent's locking
-	 * info in __db_c_get--the OPD is also a WRITEDUP.
+	 * at the moment.
 	 */
 	if (CDB_LOCKING(dbp->dbenv)) {
-		if (F_ISSET(dbc, DBC_WRITEDUP | DBC_WRITECURSOR)) {
-			if ((ret = dbp->dbenv->lock_get(
-			    dbp->dbenv, dbc->locker, DB_LOCK_UPGRADE,
-			    &dbc->lock_dbt, DB_LOCK_WRITE, &dbc->mylock)) != 0)
+		if (F_ISSET(dbc, DBC_WRITECURSOR)) {
+			if ((ret = __lock_get(dbp->dbenv,
+			    dbc->locker, DB_LOCK_UPGRADE, &dbc->lock_dbt,
+			    DB_LOCK_WRITE, &dbc->mylock)) != 0)
 				goto err;
 			cdb_lock = 1;
 		}
-		if ((ret = mpf->get(mpf, &cp_c->pgno, 0, &cp_c->page)) != 0)
-			goto err;
-
 		goto delete;
 	}
 
 	/*
 	 * The variable dbc_c has been initialized to reference the cursor in
-	 * which we're going to do the delete.  Initialize the cursor's page
-	 * and lock structures as necessary.
+	 * which we're going to do the delete.  Initialize the cursor's lock
+	 * structures as necessary.
 	 *
 	 * First, we may not need to acquire any locks.  If we're in case #3,
 	 * that is, the primary database isn't a btree database, our caller
 	 * is responsible for acquiring any necessary locks before calling us.
 	 */
-	if (F_ISSET(dbc, DBC_OPD)) {
-		if ((ret = mpf->get(mpf, &cp_c->pgno, 0, &cp_c->page)) != 0)
-			goto err;
+	if (F_ISSET(dbc, DBC_OPD))
 		goto delete;
-	}
 
 	/*
-	 * Otherwise, acquire a write lock.  If the cursor that did the initial
-	 * logical deletion (and which had a write lock) is not the same as the
-	 * cursor doing the physical deletion (which may have only ever had a
-	 * read lock on the item), we need to upgrade.  The confusion comes as
-	 * follows:
+	 * Otherwise, acquire a write lock on the primary database's page.
+	 *
+	 * Lock the primary database page, regardless of whether we're deleting
+	 * an item on a primary database page or an off-page duplicates page.
+	 *
+	 * If the cursor that did the initial logical deletion (and had a write
+	 * lock) is not the same cursor doing the physical deletion (which may
+	 * have only ever had a read lock on the item), we need to upgrade to a
+	 * write lock.  The confusion comes as follows:
 	 *
 	 *	C1	created, acquires item read lock
 	 *	C2	dup C1, create C2, also has item read lock.
@@ -494,29 +482,37 @@ lock:	cp_c = (BTREE_CURSOR *)dbc_c->internal;
 	 *
 	 * If we're in a TXN, we know that C2 will be able to acquire the write
 	 * lock, because no locker other than the one shared by C1 and C2 can
-	 * acquire a write lock -- the original write lock C1 acquire was never
+	 * acquire a write lock -- the original write lock C1 acquired was never
 	 * discarded.
 	 *
 	 * If we're not in a TXN, it's nastier.  Other cursors might acquire
 	 * read locks on the item after C1 closed, discarding its write lock,
 	 * and such locks would prevent C2 from acquiring a read lock.  That's
-	 * OK, though, we'll simply wait until we can acquire a read lock, or
+	 * OK, though, we'll simply wait until we can acquire a write lock, or
 	 * we'll deadlock.  (Which better not happen, since we're not in a TXN.)
 	 *
-	 * Lock the primary database page, regardless of whether we're deleting
-	 * an item on a primary database page or an off-page duplicates page.
+	 * There are similar scenarios with dirty reads, where the cursor may
+	 * have downgraded its write lock to a was-write lock.
 	 */
-	ACQUIRE(dbc, DB_LOCK_WRITE,
-	    cp->pgno, cp_c->lock, cp_c->pgno, cp_c->page, ret);
-	if (ret != 0)
-		goto err;
+	if (STD_LOCKING(dbc))
+		if ((ret = __db_lget(dbc,
+		    LCK_COUPLE, cp->pgno, DB_LOCK_WRITE, 0, &cp->lock)) != 0)
+			goto err;
 
 delete:	/*
-	 * If the delete occurred in a btree, delete the on-page physical item
-	 * referenced by the cursor.
+	 * If the delete occurred in a Btree, we're going to look at the page
+	 * to see if the item has to be physically deleted.  Otherwise, we do
+	 * not need the actual page (and it may not even exist, it might have
+	 * been truncated from the file after an allocation aborted).
+	 *
+	 * Delete the on-page physical item referenced by the cursor.
 	 */
-	if (dbc_c->dbtype == DB_BTREE && (ret = __bam_c_physdel(dbc_c)) != 0)
-		goto err;
+	if (dbc_c->dbtype == DB_BTREE) {
+		if ((ret = __memp_fget(mpf, &cp_c->pgno, 0, &cp_c->page)) != 0)
+			goto err;
+		if ((ret = __bam_c_physdel(dbc_c)) != 0)
+			goto err;
+	}
 
 	/*
 	 * If we're not working in an off-page duplicate tree, then we're
@@ -534,13 +530,16 @@ delete:	/*
 	 * in that case.  So, if the off-page duplicate tree is empty at this
 	 * point, we want to remove it.
 	 */
-	if ((ret = mpf->get(mpf, &root_pgno, 0, &h)) != 0)
+	if ((ret = __memp_fget(mpf, &root_pgno, 0, &h)) != 0)
 		goto err;
 	if (NUM_ENT(h) == 0) {
+		DISCARD_CUR(dbc_c, ret);
+		if (ret != 0)
+			goto err;
 		if ((ret = __db_free(dbc, h)) != 0)
 			goto err;
 	} else {
-		if ((ret = mpf->put(mpf, h, 0)) != 0)
+		if ((ret = __memp_fput(mpf, h, 0)) != 0)
 			goto err;
 		goto done;
 	}
@@ -558,7 +557,7 @@ delete:	/*
 	 * the primary page.
 	 */
 	if (dbc_opd != NULL) {
-		if ((ret = mpf->get(mpf, &cp->pgno, 0, &cp->page)) != 0)
+		if ((ret = __memp_fget(mpf, &cp->pgno, 0, &cp->page)) != 0)
 			goto err;
 		if ((ret = __bam_c_physdel(dbc)) != 0)
 			goto err;
@@ -569,14 +568,9 @@ done:	/*
 	 * Discard the page references and locks, and confirm that the stack
 	 * has been emptied.
 	 */
-	if (dbc_opd != NULL) {
-		DISCARD_CUR(dbc_opd, t_ret);
-		if (t_ret != 0 && ret == 0)
-			ret = t_ret;
-	}
-	DISCARD_CUR(dbc, t_ret);
-	if (t_ret != 0 && ret == 0)
-		ret = t_ret;
+	if (dbc_opd != NULL)
+		DISCARD_CUR(dbc_opd, ret);
+	DISCARD_CUR(dbc, ret);
 
 	/* Downgrade any CDB lock we acquired. */
 	if (cdb_lock)
@@ -624,13 +618,14 @@ __bam_c_count(dbc, recnop)
 
 	/*
 	 * Called with the top-level cursor that may reference an off-page
-	 * duplicates page.  If it's a set of on-page duplicates, get the
-	 * page and count.  Otherwise, get the root page of the off-page
-	 * duplicate tree, and use the count.  We don't have to acquire any
-	 * new locks, we have to have a read lock to even get here.
+	 * duplicates tree.  We don't have to acquire any new locks, we have
+	 * to have a read lock to even get here.
 	 */
 	if (cp->opd == NULL) {
-		if ((ret = mpf->get(mpf, &cp->pgno, 0, &cp->page)) != 0)
+		/*
+		 * On-page duplicates, get the page and count.
+		 */
+		if ((ret = __memp_fget(mpf, &cp->pgno, 0, &cp->page)) != 0)
 			return (ret);
 
 		/*
@@ -641,20 +636,47 @@ __bam_c_count(dbc, recnop)
 			if (indx == 0 ||
 			    !IS_DUPLICATE(dbc, indx, indx - P_INDX))
 				break;
-		for (recno = 1, top = NUM_ENT(cp->page) - P_INDX;
-		    indx < top; ++recno, indx += P_INDX)
-			if (!IS_DUPLICATE(dbc, indx, indx + P_INDX))
+		for (recno = 0,
+		    top = NUM_ENT(cp->page) - P_INDX;; indx += P_INDX) {
+			if (!IS_DELETED(dbp, cp->page, indx))
+				++recno;
+			if (indx == top ||
+			    !IS_DUPLICATE(dbc, indx, indx + P_INDX))
 				break;
-		*recnop = recno;
+		}
 	} else {
-		if ((ret =
-		    mpf->get(mpf, &cp->opd->internal->root, 0, &cp->page)) != 0)
+		/*
+		 * Off-page duplicates tree, get the root page of the off-page
+		 * duplicate tree.
+		 */
+		if ((ret = __memp_fget(
+		    mpf, &cp->opd->internal->root, 0, &cp->page)) != 0)
 			return (ret);
 
-		*recnop = RE_NREC(cp->page);
+		/*
+		 * If the page is an internal page use the page's count as it's
+		 * up-to-date and reflects the status of cursors in the tree.
+		 * If the page is a leaf page for unsorted duplicates, use the
+		 * page's count as cursors don't mark items deleted on the page
+		 * and wait, cursor delete items immediately.
+		 * If the page is a leaf page for sorted duplicates, there may
+		 * be cursors on the page marking deleted items -- count.
+		 */
+		if (TYPE(cp->page) == P_LDUP)
+			for (recno = 0, indx = 0,
+			    top = NUM_ENT(cp->page) - O_INDX;; indx += O_INDX) {
+				if (!IS_DELETED(dbp, cp->page, indx))
+					++recno;
+				if (indx == top)
+					break;
+			}
+		else
+			recno = RE_NREC(cp->page);
 	}
 
-	ret = mpf->put(mpf, cp->page, 0);
+	*recnop = recno;
+
+	ret = __memp_fput(mpf, cp->page, 0);
 	cp->page = NULL;
 
 	return (ret);
@@ -721,7 +743,7 @@ __bam_c_del(dbc)
 		B_DSET(GET_BKEYDATA(dbp, cp->page, cp->indx)->type);
 
 	/* Mark the page dirty. */
-	ret = mpf->set(mpf, cp->page, DB_MPOOL_DIRTY);
+	ret = __memp_fset(mpf, cp->page, DB_MPOOL_DIRTY);
 
 err:	/*
 	 * If we've been successful so far and the tree has record numbers,
@@ -733,7 +755,7 @@ err:	/*
 		(void)__bam_stkrel(dbc, 0);
 	} else
 		if (cp->page != NULL &&
-		    (t_ret = mpf->put(mpf, cp->page, 0)) != 0 && ret == 0)
+		    (t_ret = __memp_fput(mpf, cp->page, 0)) != 0 && ret == 0)
 			ret = t_ret;
 
 	cp->page = NULL;
@@ -768,11 +790,11 @@ __bam_c_dup(orig_dbc, new_dbc)
 	 * holding inside a transaction because all the locks are retained
 	 * until the transaction commits or aborts.
 	 */
-	if (LOCK_ISSET(orig->lock) && orig_dbc->txn == NULL) {
+	if (orig_dbc->txn == NULL && LOCK_ISSET(orig->lock))
 		if ((ret = __db_lget(new_dbc,
 		    0, new->pgno, new->lock_mode, 0, &new->lock)) != 0)
 			return (ret);
-	}
+
 	new->ovflsize = orig->ovflsize;
 	new->recno = orig->recno;
 	new->flags = orig->flags;
@@ -819,7 +841,7 @@ __bam_c_get(dbc, key, data, flags, pgnop)
 		 * write lock, but upgrading to a write lock has no better
 		 * chance of succeeding now instead of later, so don't try.
 		 */
-		if ((ret = mpf->get(mpf, &cp->pgno, 0, &cp->page)) != 0)
+		if ((ret = __memp_fget(mpf, &cp->pgno, 0, &cp->page)) != 0)
 			goto err;
 		break;
 	case DB_FIRST:
@@ -1037,9 +1059,8 @@ __bam_bulk(dbc, data, flags)
 	db_indx_t *inp, indx, pg_keyoff;
 	int32_t  *endp, key_off, *offp, *saveoffp;
 	u_int8_t *dbuf, *dp, *np;
-	u_int32_t key_size, size, space;
-	int adj, is_key, need_pg, next_key, no_dup;
-	int pagesize, rec_key, ret;
+	u_int32_t key_size, pagesize, size, space;
+	int adj, is_key, need_pg, next_key, no_dup, rec_key, ret;
 
 	ret = 0;
 	key_off = 0;
@@ -1048,9 +1069,9 @@ __bam_bulk(dbc, data, flags)
 	cp = (BTREE_CURSOR *)dbc->internal;
 
 	/*
-	 * dp tracks the beginging of the page in the buffer.
+	 * dp tracks the beginning of the page in the buffer.
 	 * np is the next place to copy things into the buffer.
-	 * dbuf always stays at the beging of the buffer.
+	 * dbuf always stays at the beginning of the buffer.
 	 */
 	dbuf = data->data;
 	np = dp = dbuf;
@@ -1156,11 +1177,11 @@ next_pg:
 get_key_space:
 						/* Nothing added, then error. */
 						if (offp == endp) {
-							data->size =
-							    ALIGN(size +
-							    pagesize,
-							    sizeof(u_int32_t));
-							return (ENOMEM);
+							data->size = (u_int32_t)
+							    DB_ALIGN(size +
+							    pagesize, 1024);
+							return
+							    (DB_BUFFER_SMALL);
 						}
 						/*
 						 * We need to back up to the
@@ -1191,8 +1212,8 @@ get_key_space:
 					np += size;
 				}
 				key_size = bk->len;
-				key_off = (int32_t)(inp[indx] - HOFFSET(pg)
-				    + dp - dbuf + SSZA(BKEYDATA, data));
+				key_off = (int32_t)((inp[indx] - HOFFSET(pg))
+				    + (dp - dbuf) + SSZA(BKEYDATA, data));
 				pg_keyoff = inp[indx];
 			}
 		}
@@ -1219,8 +1240,8 @@ get_key_space:
 		if (B_TYPE(bk->type) == B_DUPLICATE) {
 			bo = (BOVERFLOW *)bk;
 			if (is_key) {
-				*offp-- = key_off;
-				*offp-- = key_size;
+				*offp-- = (int32_t)key_off;
+				*offp-- = (int32_t)key_size;
 			}
 			/*
 			 * We pass the offset of the current key.
@@ -1231,8 +1252,9 @@ get_key_space:
 			if ((ret = __bam_bulk_duplicates(dbc, bo->pgno,
 			    dbuf, is_key ? offp + P_INDX : NULL,
 			    &offp, &np, &space, no_dup)) != 0) {
-				if (ret == ENOMEM) {
+				if (ret == DB_BUFFER_SMALL) {
 					size = space;
+					space = 0;
 					/* If nothing was added, then error. */
 					if (offp == saveoffp) {
 						offp += 2;
@@ -1253,13 +1275,13 @@ get_key_space:
 				return (ret);
 			space -= size;
 			if (is_key) {
-				*offp-- = key_off;
-				*offp-- = key_size;
+				*offp-- = (int32_t)key_off;
+				*offp-- = (int32_t)key_size;
 			} else if (rec_key)
-				*offp-- = cp->recno;
+				*offp-- = (int32_t)cp->recno;
 			*offp-- = (int32_t)(np - dbuf);
 			np += size;
-			*offp-- = size;
+			*offp-- = (int32_t)size;
 		} else {
 			if (need_pg) {
 				dp = np;
@@ -1291,10 +1313,10 @@ get_space:
 					if (offp >=
 					    (is_key ? &endp[-1] : endp) ||
 					    F_ISSET(dbc, DBC_TRANSIENT)) {
-						data->size = ALIGN(size +
-						    data->ulen - space,
-						    sizeof(u_int32_t));
-						return (ENOMEM);
+						data->size = (u_int32_t)
+						    DB_ALIGN(size +
+						    data->ulen - space, 1024);
+						return (DB_BUFFER_SMALL);
 					}
 					break;
 				}
@@ -1308,12 +1330,12 @@ get_space:
 			 * First add the key info then the data info.
 			 */
 			if (is_key) {
-				*offp-- = key_off;
-				*offp-- = key_size;
+				*offp-- = (int32_t)key_off;
+				*offp-- = (int32_t)key_size;
 			} else if (rec_key)
-				*offp-- = cp->recno;
-			*offp-- = (int32_t)(inp[indx + adj - 1] - HOFFSET(pg)
-			    + dp - dbuf + SSZA(BKEYDATA, data));
+				*offp-- = (int32_t)cp->recno;
+			*offp-- = (int32_t)((inp[indx + adj - 1] - HOFFSET(pg))
+			    + (dp - dbuf) + SSZA(BKEYDATA, data));
 			*offp-- = bk->len;
 		}
 		if (dbc->dbtype == DB_RECNO)
@@ -1324,8 +1346,8 @@ get_space:
 				indx += adj;
 		}
 	/*
-	 * Stop when we either run off the page or we
-	 * move to the next key and we are not returning mulitple keys.
+	 * Stop when we either run off the page or we move to the next key and
+	 * we are not returning multiple keys.
 	 */
 	} while ((indx += adj) < NUM_ENT(pg) &&
 	    (next_key || pg_keyoff == inp[indx]));
@@ -1347,25 +1369,25 @@ get_space:
 	 * interface to fetch the balance.
 	 */
 
-	if (ret == 0 &&
+	if (ret == 0 && indx < pg->entries &&
 	    F_ISSET(dbc, DBC_TRANSIENT) && pg_keyoff == inp[indx]) {
 		data->size = (data->ulen - space) + size;
-		return (ENOMEM);
+		return (DB_BUFFER_SMALL);
 	}
 	/*
 	 * Must leave the index pointing at the last record fetched.
 	 * If we are not fetching keys, we may have stepped to the
 	 * next key.
 	 */
-	if (next_key || pg_keyoff == inp[indx])
+	if (ret == DB_BUFFER_SMALL || next_key || pg_keyoff == inp[indx])
 		cp->indx = indx;
 	else
 		cp->indx = indx - P_INDX;
 
 	if (rec_key == 1)
-		*offp = (u_int32_t) RECNO_OOB;
+		*offp = RECNO_OOB;
 	else
-		*offp = (u_int32_t) -1;
+		*offp = -1;
 	return (0);
 }
 
@@ -1420,9 +1442,9 @@ __bam_bulk_duplicates(dbc, pgno, dbuf, keyoff, offpp, dpp, spacep, no_dup)
 	PAGE *pg;
 	db_indx_t indx, *inp;
 	int32_t *offp;
-	u_int32_t size, space;
+	u_int32_t pagesize, size, space;
 	u_int8_t *dp, *np;
-	int first, need_pg, pagesize, ret, t_ret;
+	int first, need_pg, ret, t_ret;
 
 	ret = 0;
 
@@ -1436,7 +1458,7 @@ __bam_bulk_duplicates(dbc, pgno, dbuf, keyoff, offpp, dpp, spacep, no_dup)
 		cp->opd = opd;
 		if ((ret = opd->c_am_get(opd,
 		    &key, &data, DB_FIRST, NULL)) != 0)
-			return (ret);
+			goto close_opd;
 	}
 
 	pagesize = opd->dbp->pgsize;
@@ -1447,7 +1469,7 @@ __bam_bulk_duplicates(dbc, pgno, dbuf, keyoff, offpp, dpp, spacep, no_dup)
 
 	/*
 	 * np is the next place to put data.
-	 * dp is the begining of the current page in the buffer.
+	 * dp is the beginning of the current page in the buffer.
 	 */
 	np = dp = *dpp;
 	first = 1;
@@ -1474,9 +1496,11 @@ __bam_bulk_duplicates(dbc, pgno, dbuf, keyoff, offpp, dpp, spacep, no_dup)
 
 			/* Did space underflow? */
 			if (space > *spacep) {
-				ret = ENOMEM;
+				ret = DB_BUFFER_SMALL;
 				if (first == 1) {
-					space = *spacep + -(int32_t)space;
+					/* Get the absolute value. */
+					space = -(int32_t)space;
+					space = *spacep + space;
 					if (need_pg)
 						space += pagesize - HOFFSET(pg);
 				}
@@ -1486,10 +1510,8 @@ __bam_bulk_duplicates(dbc, pgno, dbuf, keyoff, offpp, dpp, spacep, no_dup)
 				bo = (BOVERFLOW *)bk;
 				size = bo->tlen;
 				if (size > space) {
-					ret = ENOMEM;
-					if (first == 1) {
-						space = *spacep + size;
-					}
+					ret = DB_BUFFER_SMALL;
+					space = *spacep + size;
 					break;
 				}
 				if (first == 0 && keyoff != NULL) {
@@ -1507,11 +1529,9 @@ __bam_bulk_duplicates(dbc, pgno, dbuf, keyoff, offpp, dpp, spacep, no_dup)
 					dp = np;
 					size = pagesize - HOFFSET(pg);
 					if (space < size) {
-						ret = ENOMEM;
+						ret = DB_BUFFER_SMALL;
 						/* Return space required. */
-						if (first == 1) {
-							space = *spacep + size;
-						}
+						space = *spacep + size;
 						break;
 					}
 					memcpy(dp,
@@ -1525,10 +1545,10 @@ __bam_bulk_duplicates(dbc, pgno, dbuf, keyoff, offpp, dpp, spacep, no_dup)
 					*offp-- = keyoff[-1];
 				}
 				size = bk->len;
-				*offp-- = (int32_t)(inp[indx] - HOFFSET(pg)
-				    + dp - dbuf + SSZA(BKEYDATA, data));
+				*offp-- = (int32_t)((inp[indx] - HOFFSET(pg))
+				    + (dp - dbuf) + SSZA(BKEYDATA, data));
 			}
-			*offp-- = size;
+			*offp-- = (int32_t)size;
 			first = 0;
 			if (no_dup)
 				break;
@@ -1552,7 +1572,7 @@ contin:
 	 * If we ran out of space back up the pointer.
 	 * If we did not return any dups or reached the end, close the opd.
 	 */
-	if (ret == ENOMEM) {
+	if (ret == DB_BUFFER_SMALL) {
 		if (opd->dbtype == DB_RECNO) {
 			if (--cp->recno == 0)
 				goto close_opd;
@@ -1571,7 +1591,10 @@ contin:
 			--cp->recno;
 	} else if (indx == 0 || ret == DB_NOTFOUND) {
 close_opd:
-		opd->c_close(opd);
+		if (ret == DB_NOTFOUND)
+			ret = 0;
+		if ((t_ret = __db_c_close(opd)) != 0 && ret == 0)
+			ret = t_ret;
 		((BTREE_CURSOR *)dbc->internal)->opd = NULL;
 	}
 	if (ret == DB_NOTFOUND)
@@ -1604,7 +1627,7 @@ __bam_getbothc(dbc, data)
 	 * write lock, but upgrading to a write lock has no better
 	 * chance of succeeding now instead of later, so don't try.
 	 */
-	if ((ret = mpf->get(mpf, &cp->pgno, 0, &cp->page)) != 0)
+	if ((ret = __memp_fget(mpf, &cp->pgno, 0, &cp->page)) != 0)
 		return (ret);
 
 	/*
@@ -1626,7 +1649,7 @@ __bam_getbothc(dbc, data)
 			return (DB_NOTFOUND);
 
 		/* Discard the current page, we're going to do a full search. */
-		if ((ret = mpf->put(mpf, cp->page, 0)) != 0)
+		if ((ret = __memp_fput(mpf, cp->page, 0)) != 0)
 			return (ret);
 		cp->page = NULL;
 
@@ -1666,6 +1689,8 @@ __bam_getboth_finddatum(dbc, data, flags)
 	db_indx_t base, lim, top;
 	int cmp, ret;
 
+	COMPQUIET(cmp, 0);
+
 	dbp = dbc->dbp;
 	cp = (BTREE_CURSOR *)dbc->internal;
 
@@ -1762,13 +1787,14 @@ __bam_c_put(dbc, key, data, flags, pgnop)
 	u_int32_t flags;
 	db_pgno_t *pgnop;
 {
+	BTREE *t;
 	BTREE_CURSOR *cp;
 	DB *dbp;
 	DBT dbt;
 	DB_MPOOLFILE *mpf;
 	db_pgno_t root_pgno;
 	u_int32_t iiop;
-	int cmp, exact, ret, stack;
+	int cmp, exact, own, ret, stack;
 	void *arg;
 
 	dbp = dbc->dbp;
@@ -1778,48 +1804,27 @@ __bam_c_put(dbc, key, data, flags, pgnop)
 
 split:	ret = stack = 0;
 	switch (flags) {
+	case DB_CURRENT:
+		if (F_ISSET(cp, C_DELETED))
+			return (DB_NOTFOUND);
+		/* FALLTHROUGH */
+
 	case DB_AFTER:
 	case DB_BEFORE:
-	case DB_CURRENT:
 		iiop = flags;
-
-		/*
-		 * If the Btree has record numbers (and we're not replacing an
-		 * existing record), we need a complete stack so that we can
-		 * adjust the record counts.  The check for flags == DB_CURRENT
-		 * is superfluous but left in for clarity.  (If C_RECNUM is set
-		 * we know that flags must be DB_CURRENT, as DB_AFTER/DB_BEFORE
-		 * are illegal in a Btree unless it's configured for duplicates
-		 * and you cannot configure a Btree for both record renumbering
-		 * and duplicates.)
-		 */
-		if (flags == DB_CURRENT &&
-		    F_ISSET(cp, C_RECNUM) && F_ISSET(cp, C_DELETED)) {
-			if ((ret = __bam_c_getstack(dbc)) != 0)
-				goto err;
-			/*
-			 * Initialize the cursor from the stack.  Don't take
-			 * the page number or page index, they should already
-			 * be set.
-			 */
-			cp->page = cp->csp->page;
-			cp->lock = cp->csp->lock;
-			cp->lock_mode = cp->csp->lock_mode;
-
-			stack = 1;
-			break;
-		}
+		own = 1;
 
 		/* Acquire the current page with a write lock. */
 		ACQUIRE_WRITE_LOCK(dbc, ret);
 		if (ret != 0)
 			goto err;
-		if ((ret = mpf->get(mpf, &cp->pgno, 0, &cp->page)) != 0)
+		if ((ret = __memp_fget(mpf, &cp->pgno, 0, &cp->page)) != 0)
 			goto err;
 		break;
 	case DB_KEYFIRST:
 	case DB_KEYLAST:
 	case DB_NODUPDATA:
+		own = 0;
 		/*
 		 * Searching off-page, sorted duplicate tree: do a tree search
 		 * for the correct item; __bam_c_search returns the smallest
@@ -1954,7 +1959,7 @@ split:	ret = stack = 0;
 		    flags == DB_BEFORE || flags == DB_CURRENT) {
 			memset(&dbt, 0, sizeof(DBT));
 			if ((ret = __db_ret(dbp, cp->page, 0, &dbt,
-			    &dbc->rkey->data, &dbc->rkey->ulen)) != 0)
+			    &dbc->my_rkey.data, &dbc->my_rkey.ulen)) != 0)
 				goto err;
 			arg = &dbt;
 		} else
@@ -1974,6 +1979,19 @@ split:	ret = stack = 0;
 		if (ret != 0)
 			goto err;
 
+		/*
+		 * SR [#6059]
+		 * If we do not own a lock on the page any more, then clear the
+		 * cursor so we don't point at it.  Even if we call __bam_stkrel
+		 * above we still may have entered the routine with the cursor
+		 * positioned to a particular record.  This is in the case
+		 * where C_RECNUM is set.
+		 */
+		if (own == 0) {
+			cp->pgno = PGNO_INVALID;
+			cp->indx = 0;
+		}
+
 		/* Split the tree. */
 		if ((ret = __bam_split(dbc, arg, &root_pgno)) != 0)
 			return (ret);
@@ -1985,6 +2003,33 @@ split:	ret = stack = 0;
 
 err:
 done:	/*
+	 * If we inserted a key into the first or last slot of the tree,
+	 * remember where it was so we can do it more quickly next time.
+	 * If the tree has record numbers, we need a complete stack so
+	 * that we can adjust the record counts, so skipping the tree search
+	 * isn't possible.  For subdatabases we need to be careful that the
+	 * page does not move from one db to another, so we track its LSN.
+	 *
+	 * If there are duplicates and we are inserting into the last slot,
+	 * the cursor will point _to_ the last item, not after it, which
+	 * is why we subtract P_INDX below.
+	 */
+
+	t = dbp->bt_internal;
+	if (ret == 0 && TYPE(cp->page) == P_LBTREE &&
+	    (flags == DB_KEYFIRST || flags == DB_KEYLAST) &&
+	    !F_ISSET(cp, C_RECNUM) &&
+	    (!F_ISSET(dbp, DB_AM_SUBDB) ||
+	    (LOGGING_ON(dbp->dbenv) && !F_ISSET(dbp, DB_AM_NOT_DURABLE))) &&
+	    ((NEXT_PGNO(cp->page) == PGNO_INVALID &&
+	    cp->indx >= NUM_ENT(cp->page) - P_INDX) ||
+	    (PREV_PGNO(cp->page) == PGNO_INVALID && cp->indx == 0))) {
+		t->bt_lpgno = cp->pgno;
+		if (F_ISSET(dbp, DB_AM_SUBDB))
+			t->bt_llsn = LSN(cp->page);
+	} else
+		t->bt_lpgno = PGNO_INVALID;
+	/*
 	 * Discard any pages pinned in the tree and their locks, except for
 	 * the leaf page.  Note, the leaf page participated in any stack we
 	 * acquired, and so we have to adjust the stack as necessary.  If
@@ -1999,8 +2044,15 @@ done:	/*
 	 * flag.  If we're successful, we either moved the cursor or the item
 	 * is no longer deleted.  If we're not successful, then we're just a
 	 * copy, no need to have the flag set.
+	 *
+	 * We may have instantiated off-page duplicate cursors during the put,
+	 * so clear the deleted bit from the off-page duplicate cursor as well.
 	 */
 	F_CLR(cp, C_DELETED);
+	if (cp->opd != NULL) {
+		cp = (BTREE_CURSOR *)cp->opd->internal;
+		F_CLR(cp, C_DELETED);
+	}
 
 	return (ret);
 }
@@ -2021,7 +2073,7 @@ __bam_c_rget(dbc, data)
 	DBT dbt;
 	DB_MPOOLFILE *mpf;
 	db_recno_t recno;
-	int exact, ret;
+	int exact, ret, t_ret;
 
 	dbp = dbc->dbp;
 	mpf = dbp->mpf;
@@ -2032,13 +2084,13 @@ __bam_c_rget(dbc, data)
 	 * Get a copy of the key.
 	 * Release the page, making sure we don't release it twice.
 	 */
-	if ((ret = mpf->get(mpf, &cp->pgno, 0, &cp->page)) != 0)
+	if ((ret = __memp_fget(mpf, &cp->pgno, 0, &cp->page)) != 0)
 		return (ret);
 	memset(&dbt, 0, sizeof(DBT));
 	if ((ret = __db_ret(dbp, cp->page,
-	    cp->indx, &dbt, &dbc->rkey->data, &dbc->rkey->ulen)) != 0)
+	    cp->indx, &dbt, &dbc->my_rkey.data, &dbc->my_rkey.ulen)) != 0)
 		goto err;
-	ret = mpf->put(mpf, cp->page, 0);
+	ret = __memp_fput(mpf, cp->page, 0);
 	cp->page = NULL;
 	if (ret != 0)
 		return (ret);
@@ -2052,7 +2104,8 @@ __bam_c_rget(dbc, data)
 	    &recno, sizeof(recno), &dbc->rdata->data, &dbc->rdata->ulen);
 
 	/* Release the stack. */
-err:	__bam_stkrel(dbc, 0);
+err:	if ((t_ret = __bam_stkrel(dbc, 0)) != 0 && ret == 0)
+		ret = t_ret;
 
 	return (ret);
 }
@@ -2329,7 +2382,7 @@ __bam_c_search(dbc, root_pgno, key, flags, exactp)
 	db_pgno_t bt_lpgno;
 	db_recno_t recno;
 	u_int32_t sflags;
-	int cmp, ret;
+	int cmp, ret, t_ret;
 
 	dbp = dbc->dbp;
 	cp = (BTREE_CURSOR *)dbc->internal;
@@ -2373,12 +2426,8 @@ fast_search:	/*
 		 * If the application has a history of inserting into the first
 		 * or last pages of the database, we check those pages first to
 		 * avoid doing a full search.
-		 *
-		 * If the tree has record numbers, we need a complete stack so
-		 * that we can adjust the record counts, so fast_search isn't
-		 * possible.
 		 */
-		if (F_ISSET(cp, C_RECNUM))
+		if (F_ISSET(dbc, DBC_OPD))
 			goto search;
 
 		/*
@@ -2398,14 +2447,24 @@ fast_search:	/*
 		if (bt_lpgno == PGNO_INVALID)
 			goto search;
 
-		/* Lock and retrieve the page on which we last inserted. */
+		/*
+		 * Lock and retrieve the page on which we last inserted.
+		 *
+		 * The page may not exist: if a transaction created the page
+		 * and then aborted, the page might have been truncated from
+		 * the end of the file.
+		 */
 		h = NULL;
-		ACQUIRE(dbc,
-		    DB_LOCK_WRITE, bt_lpgno, cp->lock, bt_lpgno, h, ret);
-		if (ret != 0)
+		ACQUIRE_CUR(dbc, DB_LOCK_WRITE, bt_lpgno, ret);
+		if (ret != 0) {
+			if (ret == DB_PAGE_NOTFOUND)
+				ret = 0;
 			goto fast_miss;
+		}
 
+		h = cp->page;
 		inp = P_INP(dbp, h);
+
 		/*
 		 * It's okay if the page type isn't right or it's empty, it
 		 * just means that the world changed.
@@ -2413,6 +2472,10 @@ fast_search:	/*
 		if (TYPE(h) != P_LBTREE || NUM_ENT(h) == 0)
 			goto fast_miss;
 
+		/* Verify that this page cannot have moved to another db. */
+		if (F_ISSET(dbp, DB_AM_SUBDB) &&
+		    log_compare(&t->bt_llsn, &LSN(h)) != 0)
+			goto fast_miss;
 		/*
 		 * What we do here is test to see if we're at the beginning or
 		 * end of the tree and if the new item sorts before/after the
@@ -2495,8 +2558,13 @@ fast_hit:	/* Set the exact match flag, we may have found a duplicate. */
 fast_miss:	/*
 		 * This was not the right page, so we do not need to retain
 		 * the lock even in the presence of transactions.
+		 *
+		 * This is also an error path, so ret may have been set.
 		 */
-		DISCARD(dbc, 1, cp->lock, h, ret);
+		DISCARD_CUR(dbc, ret);
+		cp->pgno = PGNO_INVALID;
+		if ((t_ret = __LPUT(dbc, cp->lock)) != 0 && ret == 0)
+			ret = t_ret;
 		if (ret != 0)
 			return (ret);
 
@@ -2515,20 +2583,6 @@ search:		if ((ret = __bam_search(dbc, root_pgno,
 	cp->lock = cp->csp->lock;
 	cp->lock_mode = cp->csp->lock_mode;
 
-	/*
-	 * If we inserted a key into the first or last slot of the tree,
-	 * remember where it was so we can do it more quickly next time.
-	 * If there are duplicates and we are inserting into the last slot,
-	 * the cursor will point _to_ the last item, not after it, which
-	 * is why we subtract P_INDX below.
-	 */
-	if (TYPE(cp->page) == P_LBTREE &&
-	    (flags == DB_KEYFIRST || flags == DB_KEYLAST))
-		t->bt_lpgno =
-		    (NEXT_PGNO(cp->page) == PGNO_INVALID &&
-		    cp->indx >= NUM_ENT(cp->page) - P_INDX) ||
-		    (PREV_PGNO(cp->page) == PGNO_INVALID &&
-		    cp->indx == 0) ? cp->pgno : PGNO_INVALID;
 	return (0);
 }
 
@@ -2550,6 +2604,7 @@ __bam_c_physdel(dbc)
 	int delete_page, empty_page, exact, level, ret;
 
 	dbp = dbc->dbp;
+	memset(&key, 0, sizeof(DBT));
 	mpf = dbp->mpf;
 	cp = (BTREE_CURSOR *)dbc->internal;
 	delete_page = empty_page = ret = 0;
@@ -2586,12 +2641,10 @@ __bam_c_physdel(dbc)
 	 * to temporarily hold this key.  We shouldn't own any returned-data
 	 * memory of interest--if we do, we're in trouble anyway.
 	 */
-	if (delete_page) {
-		memset(&key, 0, sizeof(DBT));
+	if (delete_page)
 		if ((ret = __db_ret(dbp, cp->page,
 		    0, &key, &dbc->my_rkey.data, &dbc->my_rkey.ulen)) != 0)
 			return (ret);
-	}
 
 	/*
 	 * Delete the items.  If page isn't empty, we adjust the cursors.
@@ -2618,6 +2671,10 @@ __bam_c_physdel(dbc)
 	}
 	if ((ret = __bam_ditem(dbc, cp->page, cp->indx)) != 0)
 		return (ret);
+
+	/* Clear the deleted flag, the item is gone. */
+	F_CLR(cp, C_DELETED);
+
 	if (!empty_page)
 		if ((ret = __bam_ca_di(dbc, PGNO(cp->page), cp->indx, -1)) != 0)
 			return (ret);
@@ -2702,7 +2759,7 @@ __bam_c_physdel(dbc)
 		if ((ret =
 		    __db_lget(dbc, 0, pgno, DB_LOCK_WRITE, 0, &lock)) != 0)
 			break;
-		if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
+		if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
 			break;
 		BT_STK_PUSH(dbp->dbenv, cp, h, 0, lock, DB_LOCK_WRITE, ret);
 		if (ret != 0)
@@ -2716,6 +2773,8 @@ __bam_c_physdel(dbc)
 	 * If everything worked, delete the stack, otherwise, release the
 	 * stack and page locks without further damage.
 	 */
+	if (ret == 0)
+		DISCARD_CUR(dbc, ret);
 	if (ret == 0)
 		ret = __bam_dpages(dbc, cp->sp);
 	else
@@ -2748,13 +2807,13 @@ __bam_c_getstack(dbc)
 	 * routine has to already hold a read lock on the page, so there
 	 * is no additional lock to acquire.
 	 */
-	if ((ret = mpf->get(mpf, &cp->pgno, 0, &h)) != 0)
+	if ((ret = __memp_fget(mpf, &cp->pgno, 0, &h)) != 0)
 		return (ret);
 
 	/* Get a copy of a key from the page. */
 	memset(&dbt, 0, sizeof(DBT));
 	if ((ret = __db_ret(dbp,
-	    h, 0, &dbt, &dbc->rkey->data, &dbc->rkey->ulen)) != 0)
+	    h, 0, &dbt, &dbc->my_rkey.data, &dbc->my_rkey.ulen)) != 0)
 		goto err;
 
 	/* Get a write-locked stack for the page. */
@@ -2763,7 +2822,7 @@ __bam_c_getstack(dbc)
 	    &dbt, S_KEYFIRST, 1, NULL, &exact);
 
 err:	/* Discard the key and the page. */
-	if ((t_ret = mpf->put(mpf, h, 0)) != 0 && ret == 0)
+	if ((t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
 		ret = t_ret;
 
 	return (ret);
diff --git a/storage/bdb/btree/bt_delete.c b/storage/bdb/btree/bt_delete.c
index 8c76ead29224b8500c1fd6c936307fc3b392b051..018c8ef496bc959eb9530e1cae04f4deebed7c11 100644
--- a/storage/bdb/btree/bt_delete.c
+++ b/storage/bdb/btree/bt_delete.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -38,14 +38,12 @@
  * 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.
+ *
+ * $Id: bt_delete.c,v 11.49 2004/02/27 12:38:28 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: bt_delete.c,v 11.44 2002/07/03 19:03:49 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -57,6 +55,7 @@ static const char revid[] = "$Id: bt_delete.c,v 11.44 2002/07/03 19:03:49 bostic
 #include "dbinc/db_shash.h"
 #include "dbinc/btree.h"
 #include "dbinc/lock.h"
+#include "dbinc/mp.h"
 
 /*
  * __bam_ditem --
@@ -161,7 +160,7 @@ __bam_ditem(dbc, h, indx)
 	/* Delete the item and mark the page dirty. */
 	if ((ret = __db_ditem(dbc, h, indx, nbytes)) != 0)
 		return (ret);
-	if ((ret = mpf->set(mpf, h, DB_MPOOL_DIRTY)) != 0)
+	if ((ret = __memp_fset(mpf, h, DB_MPOOL_DIRTY)) != 0)
 		return (ret);
 
 	return (0);
@@ -211,7 +210,7 @@ __bam_adjindx(dbc, h, indx, indx_copy, is_insert)
 			memmove(&inp[indx], &inp[indx + O_INDX],
 			    sizeof(db_indx_t) * (NUM_ENT(h) - indx));
 	}
-	if ((ret = mpf->set(mpf, h, DB_MPOOL_DIRTY)) != 0)
+	if ((ret = __memp_fset(mpf, h, DB_MPOOL_DIRTY)) != 0)
 		return (ret);
 
 	return (0);
@@ -260,9 +259,10 @@ __bam_dpages(dbc, stack_epg)
 	 */
 	ret = 0;
 	for (epg = cp->sp; epg < stack_epg; ++epg) {
-		if ((t_ret = mpf->put(mpf, epg->page, 0)) != 0 && ret == 0)
+		if ((t_ret = __memp_fput(mpf, epg->page, 0)) != 0 && ret == 0)
+			ret = t_ret;
+		if ((t_ret = __TLPUT(dbc, epg->lock)) != 0 && ret == 0)
 			ret = t_ret;
-		(void)__TLPUT(dbc, epg->lock);
 	}
 	if (ret != 0)
 		goto err;
@@ -276,7 +276,7 @@ __bam_dpages(dbc, stack_epg)
 	 * It will deadlock here.  Before we unlink the subtree, we relink the
 	 * leaf page chain.
 	 */
-	if ((ret = __db_relink(dbc, DB_REM_PAGE, cp->csp->page, NULL, 1)) != 0)
+	if ((ret = __bam_relink(dbc, cp->csp->page, NULL)) != 0)
 		goto err;
 
 	/*
@@ -295,9 +295,11 @@ __bam_dpages(dbc, stack_epg)
 	pgno = PGNO(epg->page);
 	nitems = NUM_ENT(epg->page);
 
-	if ((ret = mpf->put(mpf, epg->page, 0)) != 0)
+	ret = __memp_fput(mpf, epg->page, 0);
+	if ((t_ret = __TLPUT(dbc, epg->lock)) != 0 && ret == 0)
+		ret = t_ret;
+	if (ret != 0)
 		goto err_inc;
-	(void)__TLPUT(dbc, epg->lock);
 
 	/* Free the rest of the pages in the stack. */
 	while (++epg <= cp->csp) {
@@ -314,18 +316,19 @@ __bam_dpages(dbc, stack_epg)
 				goto err;
 		}
 
-		if ((ret = __db_free(dbc, epg->page)) != 0) {
-			epg->page = NULL;
+		ret = __db_free(dbc, epg->page);
+		epg->page = NULL;
+		if ((t_ret = __TLPUT(dbc, epg->lock)) != 0 && ret == 0)
+			ret = t_ret;
+		if (ret != 0)
 			goto err_inc;
-		}
-		(void)__TLPUT(dbc, epg->lock);
 	}
 
 	if (0) {
 err_inc:	++epg;
 err:		for (; epg <= cp->csp; ++epg) {
 			if (epg->page != NULL)
-				(void)mpf->put(mpf, epg->page, 0);
+				(void)__memp_fput(mpf, epg->page, 0);
 			(void)__TLPUT(dbc, epg->lock);
 		}
 		BT_STK_CLR(cp);
@@ -354,7 +357,7 @@ err:		for (; epg <= cp->csp; ++epg) {
 		if ((ret =
 		    __db_lget(dbc, 0, pgno, DB_LOCK_WRITE, 0, &p_lock)) != 0)
 			goto stop;
-		if ((ret = mpf->get(mpf, &pgno, 0, &parent)) != 0)
+		if ((ret = __memp_fget(mpf, &pgno, 0, &parent)) != 0)
 			goto stop;
 
 		if (NUM_ENT(parent) != 1)
@@ -384,7 +387,7 @@ err:		for (; epg <= cp->csp; ++epg) {
 		if ((ret =
 		    __db_lget(dbc, 0, pgno, DB_LOCK_WRITE, 0, &c_lock)) != 0)
 			goto stop;
-		if ((ret = mpf->get(mpf, &pgno, 0, &child)) != 0)
+		if ((ret = __memp_fget(mpf, &pgno, 0, &child)) != 0)
 			goto stop;
 
 		/* Log the change. */
@@ -423,9 +426,9 @@ err:		for (; epg <= cp->csp; ++epg) {
 			RE_NREC_SET(parent, rcnt);
 
 		/* Mark the pages dirty. */
-		if ((ret = mpf->set(mpf, parent, DB_MPOOL_DIRTY)) != 0)
+		if ((ret = __memp_fset(mpf, parent, DB_MPOOL_DIRTY)) != 0)
 			goto stop;
-		if ((ret = mpf->set(mpf, child, DB_MPOOL_DIRTY)) != 0)
+		if ((ret = __memp_fset(mpf, child, DB_MPOOL_DIRTY)) != 0)
 			goto stop;
 
 		/* Adjust the cursors. */
@@ -446,15 +449,125 @@ err:		for (; epg <= cp->csp; ++epg) {
 		if (0) {
 stop:			done = 1;
 		}
-		(void)__TLPUT(dbc, p_lock);
+		if ((t_ret = __TLPUT(dbc, p_lock)) != 0 && ret == 0)
+			ret = t_ret;
 		if (parent != NULL &&
-		    (t_ret = mpf->put(mpf, parent, 0)) != 0 && ret == 0)
+		    (t_ret = __memp_fput(mpf, parent, 0)) != 0 && ret == 0)
+			ret = t_ret;
+		if ((t_ret = __TLPUT(dbc, c_lock)) != 0 && ret == 0)
 			ret = t_ret;
-		(void)__TLPUT(dbc, c_lock);
 		if (child != NULL &&
-		    (t_ret = mpf->put(mpf, child, 0)) != 0 && ret == 0)
+		    (t_ret = __memp_fput(mpf, child, 0)) != 0 && ret == 0)
 			ret = t_ret;
 	}
 
 	return (ret);
 }
+
+/*
+ * __bam_relink --
+ *	Relink around a deleted page.
+ *
+ * PUBLIC: int __bam_relink __P((DBC *, PAGE *, PAGE **));
+ */
+int
+__bam_relink(dbc, pagep, new_next)
+	DBC *dbc;
+	PAGE *pagep, **new_next;
+{
+	DB *dbp;
+	PAGE *np, *pp;
+	DB_LOCK npl, ppl;
+	DB_LSN *nlsnp, *plsnp, ret_lsn;
+	DB_MPOOLFILE *mpf;
+	int ret, t_ret;
+
+	dbp = dbc->dbp;
+	np = pp = NULL;
+	LOCK_INIT(npl);
+	LOCK_INIT(ppl);
+	nlsnp = plsnp = NULL;
+	mpf = dbp->mpf;
+	ret = 0;
+
+	/*
+	 * Retrieve and lock the one/two pages.  For a remove, we may need
+	 * two pages (the before and after).  For an add, we only need one
+	 * because, the split took care of the prev.
+	 */
+	if (pagep->next_pgno != PGNO_INVALID) {
+		if ((ret = __db_lget(dbc,
+		    0, pagep->next_pgno, DB_LOCK_WRITE, 0, &npl)) != 0)
+			goto err;
+		if ((ret = __memp_fget(mpf, &pagep->next_pgno, 0, &np)) != 0) {
+			ret = __db_pgerr(dbp, pagep->next_pgno, ret);
+			goto err;
+		}
+		nlsnp = &np->lsn;
+	}
+	if (pagep->prev_pgno != PGNO_INVALID) {
+		if ((ret = __db_lget(dbc,
+		    0, pagep->prev_pgno, DB_LOCK_WRITE, 0, &ppl)) != 0)
+			goto err;
+		if ((ret = __memp_fget(mpf, &pagep->prev_pgno, 0, &pp)) != 0) {
+			ret = __db_pgerr(dbp, pagep->prev_pgno, ret);
+			goto err;
+		}
+		plsnp = &pp->lsn;
+	}
+
+	/* Log the change. */
+	if (DBC_LOGGING(dbc)) {
+		if ((ret = __bam_relink_log(dbp, dbc->txn, &ret_lsn, 0,
+		    pagep->pgno, &pagep->lsn, pagep->prev_pgno, plsnp,
+		    pagep->next_pgno, nlsnp)) != 0)
+			goto err;
+	} else
+		LSN_NOT_LOGGED(ret_lsn);
+	if (np != NULL)
+		np->lsn = ret_lsn;
+	if (pp != NULL)
+		pp->lsn = ret_lsn;
+	pagep->lsn = ret_lsn;
+
+	/*
+	 * Modify and release the two pages.
+	 *
+	 * !!!
+	 * The parameter new_next gets set to the page following the page we
+	 * are removing.  If there is no following page, then new_next gets
+	 * set to NULL.
+	 */
+	if (np != NULL) {
+		np->prev_pgno = pagep->prev_pgno;
+		if (new_next == NULL)
+			ret = __memp_fput(mpf, np, DB_MPOOL_DIRTY);
+		else {
+			*new_next = np;
+			ret = __memp_fset(mpf, np, DB_MPOOL_DIRTY);
+		}
+		if ((t_ret = __TLPUT(dbc, npl)) != 0 && ret == 0)
+			ret = t_ret;
+		if (ret != 0)
+			goto err;
+	} else if (new_next != NULL)
+		*new_next = NULL;
+
+	if (pp != NULL) {
+		pp->next_pgno = pagep->next_pgno;
+		ret = __memp_fput(mpf, pp, DB_MPOOL_DIRTY);
+		if ((t_ret = __TLPUT(dbc, ppl)) != 0 && ret == 0)
+			ret = t_ret;
+		if (ret != 0)
+			goto err;
+	}
+	return (0);
+
+err:	if (np != NULL)
+		(void)__memp_fput(mpf, np, 0);
+	(void)__TLPUT(dbc, npl);
+	if (pp != NULL)
+		(void)__memp_fput(mpf, pp, 0);
+	(void)__TLPUT(dbc, ppl);
+	return (ret);
+}
diff --git a/storage/bdb/btree/bt_method.c b/storage/bdb/btree/bt_method.c
index aa27ed6bab9fb318a4064da4f906b915ced95e0f..0b67da91efec0affd57e880d9a7df187fc4a8cb0 100644
--- a/storage/bdb/btree/bt_method.c
+++ b/storage/bdb/btree/bt_method.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: bt_method.c,v 11.38 2004/09/22 03:31:26 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: bt_method.c,v 11.29 2002/04/21 13:17:04 margo Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #endif
@@ -20,15 +18,15 @@ static const char revid[] = "$Id: bt_method.c,v 11.29 2002/04/21 13:17:04 margo
 #include "dbinc/btree.h"
 #include "dbinc/qam.h"
 
-static int __bam_set_bt_compare
-	       __P((DB *, int (*)(DB *, const DBT *, const DBT *)));
 static int __bam_set_bt_maxkey __P((DB *, u_int32_t));
 static int __bam_set_bt_minkey __P((DB *, u_int32_t));
 static int __bam_set_bt_prefix
 	       __P((DB *, size_t(*)(DB *, const DBT *, const DBT *)));
+static int __ram_get_re_delim __P((DB *, int *));
 static int __ram_set_re_delim __P((DB *, int));
 static int __ram_set_re_len __P((DB *, u_int32_t));
 static int __ram_set_re_pad __P((DB *, int));
+static int __ram_get_re_source __P((DB *, const char **));
 static int __ram_set_re_source __P((DB *, const char *));
 
 /*
@@ -55,6 +53,7 @@ __bam_db_create(dbp)
 
 	dbp->set_bt_compare = __bam_set_bt_compare;
 	dbp->set_bt_maxkey = __bam_set_bt_maxkey;
+	dbp->get_bt_minkey = __bam_get_bt_minkey;
 	dbp->set_bt_minkey = __bam_set_bt_minkey;
 	dbp->set_bt_prefix = __bam_set_bt_prefix;
 
@@ -62,9 +61,13 @@ __bam_db_create(dbp)
 	t->re_delim = '\n';
 	t->re_eof = 1;
 
+	dbp->get_re_delim = __ram_get_re_delim;
 	dbp->set_re_delim = __ram_set_re_delim;
+	dbp->get_re_len = __ram_get_re_len;
 	dbp->set_re_len = __ram_set_re_len;
+	dbp->get_re_pad = __ram_get_re_pad;
 	dbp->set_re_pad = __ram_set_re_pad;
+	dbp->get_re_source = __ram_get_re_source;
 	dbp->set_re_source = __ram_set_re_source;
 
 	return (0);
@@ -99,6 +102,37 @@ __bam_db_close(dbp)
 	return (0);
 }
 
+/*
+ * __bam_map_flags --
+ *	Map Btree specific flags from public to the internal values.
+ *
+ * PUBLIC: void __bam_map_flags __P((DB *, u_int32_t *, u_int32_t *));
+ */
+void
+__bam_map_flags(dbp, inflagsp, outflagsp)
+	DB *dbp;
+	u_int32_t *inflagsp, *outflagsp;
+{
+	COMPQUIET(dbp, NULL);
+
+	if (FLD_ISSET(*inflagsp, DB_DUP)) {
+		FLD_SET(*outflagsp, DB_AM_DUP);
+		FLD_CLR(*inflagsp, DB_DUP);
+	}
+	if (FLD_ISSET(*inflagsp, DB_DUPSORT)) {
+		FLD_SET(*outflagsp, DB_AM_DUP | DB_AM_DUPSORT);
+		FLD_CLR(*inflagsp, DB_DUPSORT);
+	}
+	if (FLD_ISSET(*inflagsp, DB_RECNUM)) {
+		FLD_SET(*outflagsp, DB_AM_RECNUM);
+		FLD_CLR(*inflagsp, DB_RECNUM);
+	}
+	if (FLD_ISSET(*inflagsp, DB_REVSPLITOFF)) {
+		FLD_SET(*outflagsp, DB_AM_REVSPLITOFF);
+		FLD_CLR(*inflagsp, DB_REVSPLITOFF);
+	}
+}
+
 /*
  * __bam_set_flags --
  *	Set Btree specific flags.
@@ -113,50 +147,31 @@ __bam_set_flags(dbp, flagsp)
 	u_int32_t flags;
 
 	flags = *flagsp;
-	if (LF_ISSET(DB_DUP | DB_DUPSORT | DB_RECNUM | DB_REVSPLITOFF)) {
+	if (LF_ISSET(DB_DUP | DB_DUPSORT | DB_RECNUM | DB_REVSPLITOFF))
 		DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_flags");
 
-		/*
-		 * The DB_DUP and DB_DUPSORT flags are shared by the Hash
-		 * and Btree access methods.
-		 */
-		if (LF_ISSET(DB_DUP | DB_DUPSORT))
-			DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE | DB_OK_HASH);
-
-		if (LF_ISSET(DB_RECNUM | DB_REVSPLITOFF))
-			DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
-
-		if (LF_ISSET(DB_DUP | DB_DUPSORT)) {
-			/* DB_DUP/DB_DUPSORT is incompatible with DB_RECNUM. */
-			if (F_ISSET(dbp, DB_AM_RECNUM))
-				goto incompat;
-
-			if (LF_ISSET(DB_DUPSORT)) {
-				if (dbp->dup_compare == NULL)
-					dbp->dup_compare = __bam_defcmp;
-				F_SET(dbp, DB_AM_DUPSORT);
-			}
-
-			F_SET(dbp, DB_AM_DUP);
-			LF_CLR(DB_DUP | DB_DUPSORT);
-		}
-
-		if (LF_ISSET(DB_RECNUM)) {
-			/* DB_RECNUM is incompatible with DB_DUP/DB_DUPSORT. */
-			if (F_ISSET(dbp, DB_AM_DUP))
-				goto incompat;
-
-			F_SET(dbp, DB_AM_RECNUM);
-			LF_CLR(DB_RECNUM);
-		}
-
-		if (LF_ISSET(DB_REVSPLITOFF)) {
-			F_SET(dbp, DB_AM_REVSPLITOFF);
-			LF_CLR(DB_REVSPLITOFF);
-		}
-
-		*flagsp = flags;
-	}
+	/*
+	 * The DB_DUP and DB_DUPSORT flags are shared by the Hash
+	 * and Btree access methods.
+	 */
+	if (LF_ISSET(DB_DUP | DB_DUPSORT))
+		DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE | DB_OK_HASH);
+
+	if (LF_ISSET(DB_RECNUM | DB_REVSPLITOFF))
+		DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
+
+	/* DB_DUP/DB_DUPSORT is incompatible with DB_RECNUM. */
+	if (LF_ISSET(DB_DUP | DB_DUPSORT) && F_ISSET(dbp, DB_AM_RECNUM))
+		goto incompat;
+
+	/* DB_RECNUM is incompatible with DB_DUP/DB_DUPSORT. */
+	if (LF_ISSET(DB_RECNUM) && F_ISSET(dbp, DB_AM_DUP))
+		goto incompat;
+
+	if (LF_ISSET(DB_DUPSORT) && dbp->dup_compare == NULL)
+		dbp->dup_compare = __bam_defcmp;
+
+	__bam_map_flags(dbp, flagsp, &dbp->flags);
 	return (0);
 
 incompat:
@@ -166,15 +181,18 @@ incompat:
 /*
  * __bam_set_bt_compare --
  *	Set the comparison function.
+ *
+ * PUBLIC: int __bam_set_bt_compare
+ * PUBLIC:         __P((DB *, int (*)(DB *, const DBT *, const DBT *)));
  */
-static int
+int
 __bam_set_bt_compare(dbp, func)
 	DB *dbp;
 	int (*func) __P((DB *, const DBT *, const DBT *));
 {
 	BTREE *t;
 
-	DB_ILLEGAL_AFTER_OPEN(dbp, "set_bt_compare");
+	DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_bt_compare");
 	DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
 
 	t = dbp->bt_internal;
@@ -201,7 +219,7 @@ __bam_set_bt_maxkey(dbp, bt_maxkey)
 {
 	BTREE *t;
 
-	DB_ILLEGAL_AFTER_OPEN(dbp, "set_bt_maxkey");
+	DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_bt_maxkey");
 	DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
 
 	t = dbp->bt_internal;
@@ -215,6 +233,26 @@ __bam_set_bt_maxkey(dbp, bt_maxkey)
 	return (0);
 }
 
+/*
+ * __db_get_bt_minkey --
+ *	Get the minimum keys per page.
+ *
+ * PUBLIC: int __bam_get_bt_minkey __P((DB *, u_int32_t *));
+ */
+int
+__bam_get_bt_minkey(dbp, bt_minkeyp)
+	DB *dbp;
+	u_int32_t *bt_minkeyp;
+{
+	BTREE *t;
+
+	DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
+
+	t = dbp->bt_internal;
+	*bt_minkeyp = t->bt_minkey;
+	return (0);
+}
+
 /*
  * __bam_set_bt_minkey --
  *	Set the minimum keys per page.
@@ -226,7 +264,7 @@ __bam_set_bt_minkey(dbp, bt_minkey)
 {
 	BTREE *t;
 
-	DB_ILLEGAL_AFTER_OPEN(dbp, "set_bt_minkey");
+	DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_bt_minkey");
 	DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
 
 	t = dbp->bt_internal;
@@ -251,7 +289,7 @@ __bam_set_bt_prefix(dbp, func)
 {
 	BTREE *t;
 
-	DB_ILLEGAL_AFTER_OPEN(dbp, "set_bt_prefix");
+	DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_bt_prefix");
 	DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
 
 	t = dbp->bt_internal;
@@ -260,6 +298,29 @@ __bam_set_bt_prefix(dbp, func)
 	return (0);
 }
 
+/*
+ * __ram_map_flags --
+ *	Map Recno specific flags from public to the internal values.
+ *
+ * PUBLIC: void __ram_map_flags __P((DB *, u_int32_t *, u_int32_t *));
+ */
+void
+__ram_map_flags(dbp, inflagsp, outflagsp)
+	DB *dbp;
+	u_int32_t *inflagsp, *outflagsp;
+{
+	COMPQUIET(dbp, NULL);
+
+	if (FLD_ISSET(*inflagsp, DB_RENUMBER)) {
+		FLD_SET(*outflagsp, DB_AM_RENUMBER);
+		FLD_CLR(*inflagsp, DB_RENUMBER);
+	}
+	if (FLD_ISSET(*inflagsp, DB_SNAPSHOT)) {
+		FLD_SET(*outflagsp, DB_AM_SNAPSHOT);
+		FLD_CLR(*inflagsp, DB_SNAPSHOT);
+	}
+}
+
 /*
  * __ram_set_flags --
  *	Set Recno specific flags.
@@ -276,21 +337,27 @@ __ram_set_flags(dbp, flagsp)
 	flags = *flagsp;
 	if (LF_ISSET(DB_RENUMBER | DB_SNAPSHOT)) {
 		DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_flags");
-
 		DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO);
+	}
 
-		if (LF_ISSET(DB_RENUMBER)) {
-			F_SET(dbp, DB_AM_RENUMBER);
-			LF_CLR(DB_RENUMBER);
-		}
+	__ram_map_flags(dbp, flagsp, &dbp->flags);
+	return (0);
+}
 
-		if (LF_ISSET(DB_SNAPSHOT)) {
-			F_SET(dbp, DB_AM_SNAPSHOT);
-			LF_CLR(DB_SNAPSHOT);
-		}
+/*
+ * __db_get_re_delim --
+ *	Get the variable-length input record delimiter.
+ */
+static int
+__ram_get_re_delim(dbp, re_delimp)
+	DB *dbp;
+	int *re_delimp;
+{
+	BTREE *t;
 
-		*flagsp = flags;
-	}
+	DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO);
+	t = dbp->bt_internal;
+	*re_delimp = t->re_delim;
 	return (0);
 }
 
@@ -305,7 +372,7 @@ __ram_set_re_delim(dbp, re_delim)
 {
 	BTREE *t;
 
-	DB_ILLEGAL_AFTER_OPEN(dbp, "set_re_delim");
+	DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_re_delim");
 	DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO);
 
 	t = dbp->bt_internal;
@@ -316,6 +383,40 @@ __ram_set_re_delim(dbp, re_delim)
 	return (0);
 }
 
+/*
+ * __db_get_re_len --
+ *	Get the variable-length input record length.
+ *
+ * PUBLIC: int __ram_get_re_len __P((DB *, u_int32_t *));
+ */
+int
+__ram_get_re_len(dbp, re_lenp)
+	DB *dbp;
+	u_int32_t *re_lenp;
+{
+	BTREE *t;
+	QUEUE *q;
+
+	DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO);
+
+	/*
+	 * This has to work for all access methods, before or after opening the
+	 * database.  When the record length is set with __ram_set_re_len, the
+	 * value in both the BTREE and QUEUE structs will be correct.
+	 * Otherwise, this only makes sense after the database in opened, in
+	 * which case we know the type.
+	 */
+	if (dbp->type == DB_QUEUE) {
+		q = dbp->q_internal;
+		*re_lenp = q->re_len;
+	} else {
+		t = dbp->bt_internal;
+		*re_lenp = t->re_len;
+	}
+
+	return (0);
+}
+
 /*
  * __ram_set_re_len --
  *	Set the variable-length input record length.
@@ -328,7 +429,7 @@ __ram_set_re_len(dbp, re_len)
 	BTREE *t;
 	QUEUE *q;
 
-	DB_ILLEGAL_AFTER_OPEN(dbp, "set_re_len");
+	DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_re_len");
 	DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO);
 
 	t = dbp->bt_internal;
@@ -342,6 +443,40 @@ __ram_set_re_len(dbp, re_len)
 	return (0);
 }
 
+/*
+ * __db_get_re_pad --
+ *	Get the fixed-length record pad character.
+ *
+ * PUBLIC: int __ram_get_re_pad __P((DB *, int *));
+ */
+int
+__ram_get_re_pad(dbp, re_padp)
+	DB *dbp;
+	int *re_padp;
+{
+	BTREE *t;
+	QUEUE *q;
+
+	DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO);
+
+	/*
+	 * This has to work for all access methods, before or after opening the
+	 * database.  When the record length is set with __ram_set_re_pad, the
+	 * value in both the BTREE and QUEUE structs will be correct.
+	 * Otherwise, this only makes sense after the database in opened, in
+	 * which case we know the type.
+	 */
+	if (dbp->type == DB_QUEUE) {
+		q = dbp->q_internal;
+		*re_padp = q->re_pad;
+	} else {
+		t = dbp->bt_internal;
+		*re_padp = t->re_pad;
+	}
+
+	return (0);
+}
+
 /*
  * __ram_set_re_pad --
  *	Set the fixed-length record pad character.
@@ -354,7 +489,7 @@ __ram_set_re_pad(dbp, re_pad)
 	BTREE *t;
 	QUEUE *q;
 
-	DB_ILLEGAL_AFTER_OPEN(dbp, "set_re_pad");
+	DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_re_pad");
 	DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO);
 
 	t = dbp->bt_internal;
@@ -368,6 +503,24 @@ __ram_set_re_pad(dbp, re_pad)
 	return (0);
 }
 
+/*
+ * __db_get_re_source --
+ *	Get the backing source file name.
+ */
+static int
+__ram_get_re_source(dbp, re_sourcep)
+	DB *dbp;
+	const char **re_sourcep;
+{
+	BTREE *t;
+
+	DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO);
+
+	t = dbp->bt_internal;
+	*re_sourcep = t->re_source;
+	return (0);
+}
+
 /*
  * __ram_set_re_source --
  *	Set the backing source file name.
@@ -379,7 +532,7 @@ __ram_set_re_source(dbp, re_source)
 {
 	BTREE *t;
 
-	DB_ILLEGAL_AFTER_OPEN(dbp, "set_re_source");
+	DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_re_source");
 	DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO);
 
 	t = dbp->bt_internal;
diff --git a/storage/bdb/btree/bt_open.c b/storage/bdb/btree/bt_open.c
index 24da41e9893128ba8d90c8a3beab5d0e7ade8f5b..e890c5dd75dbcd5b539bfef798cbd8a803bd0526 100644
--- a/storage/bdb/btree/bt_open.c
+++ b/storage/bdb/btree/bt_open.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -38,18 +38,15 @@
  * 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.
+ *
+ * $Id: bt_open.c,v 11.92 2004/04/29 14:39:47 ubell Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: bt_open.c,v 11.76 2002/09/04 19:06:42 margo Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
-#include <limits.h>
 #include <string.h>
 #endif
 
@@ -61,6 +58,7 @@ static const char revid[] = "$Id: bt_open.c,v 11.76 2002/09/04 19:06:42 margo Ex
 #include "dbinc/db_shash.h"
 #include "dbinc/lock.h"
 #include "dbinc/log.h"
+#include "dbinc/mp.h"
 #include "dbinc/fop.h"
 
 static void __bam_init_meta __P((DB *, BTMETA *, db_pgno_t, DB_LSN *));
@@ -85,10 +83,6 @@ __bam_open(dbp, txn, name, base_pgno, flags)
 	COMPQUIET(name, NULL);
 	t = dbp->bt_internal;
 
-	/* Initialize the remaining fields/methods of the DB. */
-	dbp->key_range = __bam_key_range;
-	dbp->stat = __bam_stat;
-
 	/*
 	 * We don't permit the user to specify a prefix routine if they didn't
 	 * also specify a comparison routine, they can't know enough about our
@@ -290,6 +284,7 @@ __bam_read_root(dbp, txn, base_pgno, flags)
 	DB_MPOOLFILE *mpf;
 	int ret, t_ret;
 
+	COMPQUIET(flags, 0);
 	meta = NULL;
 	t = dbp->bt_internal;
 	LOCK_INIT(metalock);
@@ -297,14 +292,14 @@ __bam_read_root(dbp, txn, base_pgno, flags)
 	ret = 0;
 
 	/* Get a cursor.  */
-	if ((ret = dbp->cursor(dbp, txn, &dbc, 0)) != 0)
+	if ((ret = __db_cursor(dbp, txn, &dbc, 0)) != 0)
 		return (ret);
 
 	/* Get the metadata page. */
 	if ((ret =
 	    __db_lget(dbc, 0, base_pgno, DB_LOCK_READ, 0, &metalock)) != 0)
 		goto err;
-	if ((ret = mpf->get(mpf, &base_pgno, 0, (PAGE **)&meta)) != 0)
+	if ((ret = __memp_fget(mpf, &base_pgno, 0, &meta)) != 0)
 		goto err;
 
 	/*
@@ -315,16 +310,18 @@ __bam_read_root(dbp, txn, base_pgno, flags)
 	 * Otherwise, we'd better be in recovery or abort, in which case the
 	 * metadata page will be created/initialized elsewhere.
 	 */
-	DB_ASSERT(meta->dbmeta.magic != 0 ||
-	    IS_RECOVERING(dbp->dbenv) || F_ISSET(dbp, DB_AM_RECOVER));
-
-	t->bt_maxkey = meta->maxkey;
-	t->bt_minkey = meta->minkey;
-	t->re_pad = meta->re_pad;
-	t->re_len = meta->re_len;
-
-	t->bt_meta = base_pgno;
-	t->bt_root = meta->root;
+	if (meta->dbmeta.magic == DB_BTREEMAGIC) {
+		t->bt_maxkey = meta->maxkey;
+		t->bt_minkey = meta->minkey;
+		t->re_pad = (int)meta->re_pad;
+		t->re_len = meta->re_len;
+
+		t->bt_meta = base_pgno;
+		t->bt_root = meta->root;
+	} else {
+		DB_ASSERT(IS_RECOVERING(dbp->dbenv) ||
+		     F_ISSET(dbp, DB_AM_RECOVER));
+	}
 
 	/*
 	 * !!!
@@ -337,21 +334,14 @@ __bam_read_root(dbp, txn, base_pgno, flags)
 	 */
 	t->bt_lpgno = PGNO_INVALID;
 
-	/* We must initialize last_pgno, it could be stale. */
-	if (!LF_ISSET(DB_RDONLY) && dbp->meta_pgno == PGNO_BASE_MD) {
-		mpf->last_pgno(mpf, &meta->dbmeta.last_pgno);
-		ret = mpf->put(mpf, meta, DB_MPOOL_DIRTY);
-	} else
-		ret = mpf->put(mpf, meta, 0);
-	meta = NULL;
-
 err:	/* Put the metadata page back. */
-	if (meta != NULL && (t_ret = mpf->put(mpf, meta, 0)) != 0 && ret == 0)
+	if (meta != NULL &&
+	    (t_ret = __memp_fput(mpf, meta, 0)) != 0 && ret == 0)
 		ret = t_ret;
 	if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0)
 		ret = t_ret;
 
-	if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
+	if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
 		ret = t_ret;
 	return (ret);
 }
@@ -408,7 +398,7 @@ __bam_init_meta(dbp, meta, pgno, lsnp)
 	meta->maxkey = t->bt_maxkey;
 	meta->minkey = t->bt_minkey;
 	meta->re_len = t->re_len;
-	meta->re_pad = t->re_pad;
+	meta->re_pad = (u_int32_t)t->re_pad;
 }
 
 /*
@@ -418,8 +408,8 @@ __bam_init_meta(dbp, meta, pgno, lsnp)
  * This code appears more complex than it is because of the two cases (named
  * and unnamed).  The way to read the code is that for each page being created,
  * there are three parts: 1) a "get page" chunk (which either uses malloc'd
- * memory or calls mpf->get), 2) the initialization, and 3) the "put page"
- * chunk which either does a fop write or an mpf->put.
+ * memory or calls __memp_fget), 2) the initialization, and 3) the "put page"
+ * chunk which either does a fop write or an __memp_fput.
  *
  * PUBLIC: int __bam_new_file __P((DB *, DB_TXN *, DB_FH *, const char *));
  */
@@ -445,78 +435,84 @@ __bam_new_file(dbp, txn, fhp, name)
 	mpf = dbp->mpf;
 	root = NULL;
 	meta = NULL;
-	memset(&pdbt, 0, sizeof(pdbt));
-
-	/* Build meta-data page. */
+	buf = NULL;
 
 	if (name == NULL) {
+		/* Build the meta-data page. */
 		pgno = PGNO_BASE_MD;
-		ret = mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &meta);
+		if ((ret =
+		    __memp_fget(mpf, &pgno, DB_MPOOL_CREATE, &meta)) != 0)
+			return (ret);
+		LSN_NOT_LOGGED(lsn);
+		__bam_init_meta(dbp, meta, PGNO_BASE_MD, &lsn);
+		meta->root = 1;
+		meta->dbmeta.last_pgno = 1;
+		ret = __memp_fput(mpf, meta, DB_MPOOL_DIRTY);
+		meta = NULL;
+		if (ret != 0)
+			goto err;
+
+		/* Build the root page. */
+		pgno = 1;
+		if ((ret =
+		    __memp_fget(mpf, &pgno, DB_MPOOL_CREATE, &root)) != 0)
+			goto err;
+		P_INIT(root, dbp->pgsize, 1, PGNO_INVALID, PGNO_INVALID,
+		    LEAFLEVEL, dbp->type == DB_RECNO ? P_LRECNO : P_LBTREE);
+		LSN_NOT_LOGGED(root->lsn);
+		ret = __memp_fput(mpf, root, DB_MPOOL_DIRTY);
+		root = NULL;
+		if (ret != 0)
+			goto err;
 	} else {
+		memset(&pdbt, 0, sizeof(pdbt));
+
+		/* Build the meta-data page. */
 		pginfo.db_pagesize = dbp->pgsize;
 		pginfo.flags =
 		    F_ISSET(dbp, (DB_AM_CHKSUM | DB_AM_ENCRYPT | DB_AM_SWAP));
 		pginfo.type = dbp->type;
 		pdbt.data = &pginfo;
 		pdbt.size = sizeof(pginfo);
-		ret = __os_calloc(dbp->dbenv, 1, dbp->pgsize, &buf);
+		if ((ret = __os_calloc(dbenv, 1, dbp->pgsize, &buf)) != 0)
+			return (ret);
 		meta = (BTMETA *)buf;
-	}
-	if (ret != 0)
-		return (ret);
-
-	LSN_NOT_LOGGED(lsn);
-	__bam_init_meta(dbp, meta, PGNO_BASE_MD, &lsn);
-	meta->root = 1;
-	meta->dbmeta.last_pgno = 1;
-
-	if (name == NULL)
-		ret = mpf->put(mpf, meta, DB_MPOOL_DIRTY);
-	else {
+		LSN_NOT_LOGGED(lsn);
+		__bam_init_meta(dbp, meta, PGNO_BASE_MD, &lsn);
+		meta->root = 1;
+		meta->dbmeta.last_pgno = 1;
 		if ((ret = __db_pgout(dbenv, PGNO_BASE_MD, meta, &pdbt)) != 0)
 			goto err;
-		ret = __fop_write(dbenv,
-		    txn, name, DB_APP_DATA, fhp, 0, buf, dbp->pgsize, 1);
-	}
-	if (ret != 0)
-		goto err;
-	meta = NULL;
-
-	/* Now build root page. */
-	if (name == NULL) {
-		pgno = 1;
-		if ((ret = mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &root)) != 0)
+		if ((ret = __fop_write(dbenv, txn, name, DB_APP_DATA, fhp,
+		    dbp->pgsize, 0, 0, buf, dbp->pgsize, 1, F_ISSET(
+		    dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0)) != 0)
 			goto err;
-	} else {
+		meta = NULL;
+
+		/* Build the root page. */
 #ifdef DIAGNOSTIC
-		memset(buf, 0, dbp->pgsize);
+		memset(buf, CLEAR_BYTE, dbp->pgsize);
 #endif
 		root = (PAGE *)buf;
-	}
-
-	P_INIT(root, dbp->pgsize, 1, PGNO_INVALID, PGNO_INVALID,
-	    LEAFLEVEL, dbp->type == DB_RECNO ? P_LRECNO : P_LBTREE);
-	LSN_NOT_LOGGED(root->lsn);
-
-	if (name == NULL)
-		ret = mpf->put(mpf, root, DB_MPOOL_DIRTY);
-	else {
+		P_INIT(root, dbp->pgsize, 1, PGNO_INVALID, PGNO_INVALID,
+		    LEAFLEVEL, dbp->type == DB_RECNO ? P_LRECNO : P_LBTREE);
+		LSN_NOT_LOGGED(root->lsn);
 		if ((ret = __db_pgout(dbenv, root->pgno, root, &pdbt)) != 0)
 			goto err;
-		ret = __fop_write(dbenv, txn,
-		    name, DB_APP_DATA, fhp, dbp->pgsize, buf, dbp->pgsize, 1);
+		if ((ret = __fop_write(dbenv, txn, name, DB_APP_DATA, fhp,
+		    dbp->pgsize, 1, 0, buf, dbp->pgsize, 1, F_ISSET(
+		    dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0)) != 0)
+			goto err;
+		root = NULL;
 	}
-	if (ret != 0)
-		goto err;
-	root = NULL;
 
-err:	if (name != NULL)
+err:	if (buf != NULL)
 		__os_free(dbenv, buf);
 	else {
 		if (meta != NULL)
-			(void)mpf->put(mpf, meta, 0);
+			(void)__memp_fput(mpf, meta, 0);
 		if (root != NULL)
-			(void)mpf->put(mpf, root, 0);
+			(void)__memp_fput(mpf, root, 0);
 	}
 	return (ret);
 }
@@ -547,7 +543,7 @@ __bam_new_subdb(mdbp, dbp, txn)
 	meta = NULL;
 	root = NULL;
 
-	if ((ret = mdbp->cursor(mdbp, txn,
+	if ((ret = __db_cursor(mdbp, txn,
 	    &dbc, CDB_LOCKING(dbenv) ?  DB_WRITECURSOR : 0)) != 0)
 		return (ret);
 
@@ -555,7 +551,8 @@ __bam_new_subdb(mdbp, dbp, txn)
 	if ((ret = __db_lget(dbc,
 	    0, dbp->meta_pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
 		goto err;
-	if ((ret = mpf->get(mpf, &dbp->meta_pgno, DB_MPOOL_CREATE, &meta)) != 0)
+	if ((ret =
+	    __memp_fget(mpf, &dbp->meta_pgno, DB_MPOOL_CREATE, &meta)) != 0)
 		goto err;
 
 	/* Build meta-data page. */
@@ -582,24 +579,23 @@ __bam_new_subdb(mdbp, dbp, txn)
 		goto err;
 
 	/* Release the metadata and root pages. */
-	if ((ret = mpf->put(mpf, meta, DB_MPOOL_DIRTY)) != 0)
+	if ((ret = __memp_fput(mpf, meta, DB_MPOOL_DIRTY)) != 0)
 		goto err;
 	meta = NULL;
-	if ((ret = mpf->put(mpf, root, DB_MPOOL_DIRTY)) != 0)
+	if ((ret = __memp_fput(mpf, root, DB_MPOOL_DIRTY)) != 0)
 		goto err;
 	root = NULL;
 err:
 	if (meta != NULL)
-		if ((t_ret = mpf->put(mpf, meta, 0)) != 0 && ret == 0)
+		if ((t_ret = __memp_fput(mpf, meta, 0)) != 0 && ret == 0)
 			ret = t_ret;
 	if (root != NULL)
-		if ((t_ret = mpf->put(mpf, root, 0)) != 0 && ret == 0)
-			ret = t_ret;
-	if (LOCK_ISSET(metalock))
-		if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0)
+		if ((t_ret = __memp_fput(mpf, root, 0)) != 0 && ret == 0)
 			ret = t_ret;
+	if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0)
+		ret = t_ret;
 	if (dbc != NULL)
-		if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
+		if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
 			ret = t_ret;
 	return (ret);
 }
diff --git a/storage/bdb/btree/bt_put.c b/storage/bdb/btree/bt_put.c
index 39bd2024e76164fcb22da0fc491235c30d94ef4a..128b16a82f088acf1574dfc9d702701af5da8d36 100644
--- a/storage/bdb/btree/bt_put.c
+++ b/storage/bdb/btree/bt_put.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -38,14 +38,12 @@
  * 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.
+ *
+ * $Id: bt_put.c,v 11.80 2004/10/29 17:33:25 ubell Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: bt_put.c,v 11.69 2002/08/06 06:11:12 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -54,7 +52,9 @@ static const char revid[] = "$Id: bt_put.c,v 11.69 2002/08/06 06:11:12 bostic Ex
 
 #include "db_int.h"
 #include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
 #include "dbinc/btree.h"
+#include "dbinc/mp.h"
 
 static int __bam_build
 	       __P((DBC *, u_int32_t, DBT *, PAGE *, u_int32_t, u_int32_t));
@@ -76,6 +76,7 @@ __bam_iitem(dbc, key, data, op, flags)
 	DBT *key, *data;
 	u_int32_t op, flags;
 {
+	DB_ENV *dbenv;
 	BKEYDATA *bk, bk_tmp;
 	BTREE *t;
 	BTREE_CURSOR *cp;
@@ -90,6 +91,7 @@ __bam_iitem(dbc, key, data, op, flags)
 	COMPQUIET(bk, NULL);
 
 	dbp = dbc->dbp;
+	dbenv = dbp->dbenv;
 	mpf = dbp->mpf;
 	cp = (BTREE_CURSOR *)dbc->internal;
 	t = dbp->bt_internal;
@@ -102,10 +104,8 @@ __bam_iitem(dbc, key, data, op, flags)
 	 * anything other simple overwrite.
 	 */
 	if (F_ISSET(dbp, DB_AM_FIXEDLEN) &&
-	    F_ISSET(data, DB_DBT_PARTIAL) && data->dlen != data->size) {
-		data_size = data->size;
-		goto len_err;
-	}
+	    F_ISSET(data, DB_DBT_PARTIAL) && data->size != data->dlen)
+		return (__db_rec_repl(dbenv, data->size, data->dlen));
 
 	/*
 	 * Figure out how much space the data will take, including if it's a
@@ -119,12 +119,8 @@ __bam_iitem(dbc, key, data, op, flags)
 	    __bam_partsize(dbp, op, data, h, indx) : data->size;
 	padrec = 0;
 	if (F_ISSET(dbp, DB_AM_FIXEDLEN)) {
-		if (data_size > t->re_len) {
-len_err:		__db_err(dbp->dbenv,
-			    "Length improper for fixed length record %lu",
-			    (u_long)data_size);
-			return (EINVAL);
-		}
+		if (data_size > t->re_len)
+			return (__db_rec_toobig(dbenv, data_size, t->re_len));
 
 		/* Records that are deleted anyway needn't be padded out. */
 		if (!LF_ISSET(BI_DELETED) && data_size < t->re_len) {
@@ -158,8 +154,8 @@ len_err:		__db_err(dbp->dbenv,
 		    dbp->dup_compare, &cmp)) != 0)
 			return (ret);
 		if (cmp != 0) {
-			__db_err(dbp->dbenv,
-			    "Current data differs from put data");
+			__db_err(dbenv,
+		"Existing data sorts differently from put data");
 			return (EINVAL);
 		}
 	}
@@ -218,19 +214,14 @@ len_err:		__db_err(dbp->dbenv,
 			needed += need_bytes - have_bytes;
 		break;
 	default:
-		return (__db_unknown_flag(dbp->dbenv, "__bam_iitem", op));
+		return (__db_unknown_flag(dbenv, "DB->put", op));
 	}
 
 	/*
 	 * If there's not enough room, or the user has put a ceiling on the
 	 * number of keys permitted in the page, split the page.
-	 *
-	 * XXX
-	 * The t->bt_maxkey test here may be insufficient -- do we have to
-	 * check in the btree split code, so we don't undo it there!?!?
 	 */
-	if (P_FREESPACE(dbp, h) < needed ||
-	    (t->bt_maxkey != 0 && NUM_ENT(h) > t->bt_maxkey))
+	if (P_FREESPACE(dbp, h) < needed)
 		return (DB_NEEDSPLIT);
 
 	/*
@@ -294,23 +285,24 @@ len_err:		__db_err(dbp->dbenv,
 		  * we deadlock or fail while deleting the overflow item or
 		  * replacing the non-overflow item, a subsequent cursor close
 		  * will try and remove the item because the cursor's delete
-		  * flag is set
+		  * flag is set.
 		  */
 		(void)__bam_ca_delete(dbp, PGNO(h), indx, 0);
 
 		if (TYPE(h) == P_LBTREE) {
 			++indx;
 			dupadjust = 1;
+		}
 
-			/*
-			 * In a Btree deleted records aren't counted (deleted
-			 * records are counted in a Recno because all accesses
-			 * are based on record number).  If it's a Btree and
-			 * it's a DB_CURRENT operation overwriting a previously
-			 * deleted record, increment the record count.
-			 */
+		/*
+		 * In a Btree deleted records aren't counted (deleted records
+		 * are counted in a Recno because all accesses are based on
+		 * record number).  If it's a Btree and it's a DB_CURRENT
+		 * operation overwriting a previously deleted record, increment
+		 * the record count.
+		 */
+		if (TYPE(h) == P_LBTREE || TYPE(h) == P_LDUP)
 			was_deleted = B_DISSET(bk->type);
-		}
 
 		/*
 		 * 4. Delete and re-add the data item.
@@ -331,7 +323,7 @@ len_err:		__db_err(dbp->dbenv,
 		replace = 1;
 		break;
 	default:
-		return (__db_unknown_flag(dbp->dbenv, "__bam_iitem", op));
+		return (__db_unknown_flag(dbenv, "DB->put", op));
 	}
 
 	/* Add the data. */
@@ -360,7 +352,7 @@ len_err:		__db_err(dbp->dbenv,
 		if (ret != 0)
 			return (ret);
 	}
-	if ((ret = mpf->set(mpf, h, DB_MPOOL_DIRTY)) != 0)
+	if ((ret = __memp_fset(mpf, h, DB_MPOOL_DIRTY)) != 0)
 		return (ret);
 
 	/*
@@ -648,7 +640,7 @@ __bam_ritem(dbc, h, indx, data)
 		if (p == t)			/* First index is fast. */
 			inp[indx] += nbytes;
 		else {				/* Else, shift the page. */
-			memmove(p + nbytes, p, t - p);
+			memmove(p + nbytes, p, (size_t)(t - p));
 
 			/* Adjust the indices' offsets. */
 			off = inp[indx];
@@ -700,12 +692,16 @@ __bam_dup_convert(dbc, h, indx)
 	 */
 	while (indx > 0 && inp[indx] == inp[indx - P_INDX])
 		indx -= P_INDX;
-	for (cnt = 0, sz = 0, first = indx;; ++cnt, indx += P_INDX) {
-		if (indx >= NUM_ENT(h) || inp[first] != inp[indx])
-			break;
-		bk = GET_BKEYDATA(dbp, h, indx);
-		sz += B_TYPE(bk->type) == B_KEYDATA ?
-		    BKEYDATA_PSIZE(bk->len) : BOVERFLOW_PSIZE;
+
+	/* Count the key once. */
+	bk = GET_BKEYDATA(dbp, h, indx);
+	sz = B_TYPE(bk->type) == B_KEYDATA ?
+	    BKEYDATA_PSIZE(bk->len) : BOVERFLOW_PSIZE;
+
+	/* Sum up all the data items. */
+	for (cnt = 0, first = indx;
+	    indx < NUM_ENT(h) && inp[first] == inp[indx];
+	    ++cnt, indx += P_INDX) {
 		bk = GET_BKEYDATA(dbp, h, indx + O_INDX);
 		sz += B_TYPE(bk->type) == B_KEYDATA ?
 		    BKEYDATA_PSIZE(bk->len) : BOVERFLOW_PSIZE;
@@ -800,14 +796,14 @@ __bam_dup_convert(dbc, h, indx)
 	    B_DUPLICATE, dp->pgno, h, first + 1, NULL)) != 0)
 		goto err;
 
-	/* Adjust cursors for all the above movments. */
+	/* Adjust cursors for all the above movements. */
 	if ((ret = __bam_ca_di(dbc,
-	    PGNO(h), first + P_INDX, first + P_INDX - indx)) != 0)
+	    PGNO(h), first + P_INDX, (int)(first + P_INDX - indx))) != 0)
 		goto err;
 
-	return (mpf->put(mpf, dp, DB_MPOOL_DIRTY));
+	return (__memp_fput(mpf, dp, DB_MPOOL_DIRTY));
 
-err:	(void)mpf->put(mpf, dp, 0);
+err:	(void)__memp_fput(mpf, dp, 0);
 	return (ret);
 }
 
diff --git a/storage/bdb/btree/bt_rec.c b/storage/bdb/btree/bt_rec.c
index b6443547aa5e4fc79b57c0f4f7e50653a8a92157..e3fa7363c1d4abb91224ea2fadbef39dda59aedb 100644
--- a/storage/bdb/btree/bt_rec.c
+++ b/storage/bdb/btree/bt_rec.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: bt_rec.c,v 11.70 2004/09/24 00:43:12 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: bt_rec.c,v 11.57 2002/08/06 16:53:53 ubell Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -23,6 +21,7 @@ static const char revid[] = "$Id: bt_rec.c,v 11.57 2002/08/06 16:53:53 ubell Exp
 #include "dbinc/btree.h"
 #include "dbinc/lock.h"
 #include "dbinc/log.h"
+#include "dbinc/mp.h"
 
 #define	IS_BTREE_PAGE(pagep)						\
 	(TYPE(pagep) == P_IBTREE ||					\
@@ -50,7 +49,7 @@ __bam_split_recover(dbenv, dbtp, lsnp, op, info)
 	PAGE *_lp, *lp, *np, *pp, *_rp, *rp, *sp;
 	db_pgno_t pgno, root_pgno;
 	u_int32_t ptype;
-	int cmp, l_update, p_update, r_update, rc, ret, ret_l, rootsplit, t_ret;
+	int cmp, l_update, p_update, r_update, rc, ret, rootsplit, t_ret;
 
 	COMPQUIET(info, NULL);
 	REC_PRINT(__bam_split_print);
@@ -82,50 +81,40 @@ __bam_split_recover(dbenv, dbtp, lsnp, op, info)
 	pgno = PGNO(sp);
 	root_pgno = argp->root_pgno;
 	rootsplit = root_pgno != PGNO_INVALID;
-	if ((ret_l = mpf->get(mpf, &argp->left, 0, &lp)) != 0)
-		lp = NULL;
-	if (mpf->get(mpf, &argp->right, 0, &rp) != 0)
-		rp = NULL;
+	REC_FGET(mpf, argp->left, &lp, right);
+right:	REC_FGET(mpf, argp->right, &rp, redo);
 
-	if (DB_REDO(op)) {
+redo:	if (DB_REDO(op)) {
 		l_update = r_update = p_update = 0;
 		/*
 		 * Decide if we need to resplit the page.
 		 *
-		 * If this is a root split, then the root has to exist, it's
-		 * the page we're splitting and it gets modified.  If this is
-		 * not a root split, then the left page has to exist, for the
-		 * same reason.
+		 * If this is a root split, then the root has to exist unless
+		 * we have truncated it due to a future deallocation.
 		 */
 		if (rootsplit) {
-			if ((ret = mpf->get(mpf, &pgno, 0, &pp)) != 0) {
-				__db_pgerr(file_dbp, pgno, ret);
-				pp = NULL;
-				goto out;
-			}
-			cmp = log_compare(&LSN(pp), &LSN(argp->pg.data));
-			CHECK_LSN(op, cmp, &LSN(pp), &LSN(argp->pg.data));
+			REC_FGET(mpf, root_pgno, &pp, do_left);
+			cmp =
+			    log_compare(&LSN(pp), &LSN(argp->pg.data));
+			CHECK_LSN(op,
+			    cmp, &LSN(pp), &LSN(argp->pg.data));
 			p_update = cmp  == 0;
-		} else if (lp == NULL) {
-			__db_pgerr(file_dbp, argp->left, ret_l);
-			goto out;
 		}
 
-		if (lp != NULL) {
+do_left:	if (lp != NULL) {
 			cmp = log_compare(&LSN(lp), &argp->llsn);
 			CHECK_LSN(op, cmp, &LSN(lp), &argp->llsn);
 			if (cmp == 0)
 				l_update = 1;
-		} else
-			l_update = 1;
+		}
 
 		if (rp != NULL) {
 			cmp = log_compare(&LSN(rp), &argp->rlsn);
 			CHECK_LSN(op, cmp, &LSN(rp), &argp->rlsn);
 			if (cmp == 0)
 				r_update = 1;
-		} else
-			r_update = 1;
+		}
+
 		if (!p_update && !l_update && !r_update)
 			goto check_next;
 
@@ -158,32 +147,18 @@ __bam_split_recover(dbenv, dbtp, lsnp, op, info)
 		    NUM_ENT(sp))) != 0)
 			goto out;
 
-		/* If the left child is wrong, update it. */
-		if (lp == NULL && (ret = mpf->get(
-		    mpf, &argp->left, DB_MPOOL_CREATE, &lp)) != 0) {
-			__db_pgerr(file_dbp, argp->left, ret);
-			lp = NULL;
-			goto out;
-		}
 		if (l_update) {
 			memcpy(lp, _lp, file_dbp->pgsize);
 			lp->lsn = *lsnp;
-			if ((ret = mpf->put(mpf, lp, DB_MPOOL_DIRTY)) != 0)
+			if ((ret = __memp_fput(mpf, lp, DB_MPOOL_DIRTY)) != 0)
 				goto out;
 			lp = NULL;
 		}
 
-		/* If the right child is wrong, update it. */
-		if (rp == NULL && (ret = mpf->get(
-		    mpf, &argp->right, DB_MPOOL_CREATE, &rp)) != 0) {
-			__db_pgerr(file_dbp, argp->right, ret);
-			rp = NULL;
-			goto out;
-		}
 		if (r_update) {
 			memcpy(rp, _rp, file_dbp->pgsize);
 			rp->lsn = *lsnp;
-			if ((ret = mpf->put(mpf, rp, DB_MPOOL_DIRTY)) != 0)
+			if ((ret = __memp_fput(mpf, rp, DB_MPOOL_DIRTY)) != 0)
 				goto out;
 			rp = NULL;
 		}
@@ -205,11 +180,11 @@ __bam_split_recover(dbenv, dbtp, lsnp, op, info)
 
 			P_INIT(pp, file_dbp->pgsize, root_pgno,
 			    PGNO_INVALID, PGNO_INVALID, _lp->level + 1, ptype);
-			RE_NREC_SET(pp, rc ?  __bam_total(file_dbp, _lp) +
+			RE_NREC_SET(pp, rc ? __bam_total(file_dbp, _lp) +
 			    __bam_total(file_dbp, _rp) : 0);
 
 			pp->lsn = *lsnp;
-			if ((ret = mpf->put(mpf, pp, DB_MPOOL_DIRTY)) != 0)
+			if ((ret = __memp_fput(mpf, pp, DB_MPOOL_DIRTY)) != 0)
 				goto out;
 			pp = NULL;
 		}
@@ -221,11 +196,19 @@ check_next:	/*
 		 * previous-page pointer updated to our new page.  The next
 		 * page must exist because we're redoing the operation.
 		 */
-		if (!rootsplit && !IS_ZERO_LSN(argp->nlsn)) {
-			if ((ret = mpf->get(mpf, &argp->npgno, 0, &np)) != 0) {
-				__db_pgerr(file_dbp, argp->npgno, ret);
-				np = NULL;
-				goto out;
+		if (!rootsplit && argp->npgno != PGNO_INVALID) {
+			if ((ret =
+			    __memp_fget(mpf, &argp->npgno, 0, &np)) != 0) {
+				if (ret != DB_PAGE_NOTFOUND
+#ifndef HAVE_FTRUNCATE
+				    || DB_REDO(op)
+#endif
+				    ) {
+					ret = __db_pgerr(
+					    file_dbp, argp->npgno, ret);
+					goto out;
+				} else
+					goto done;
 			}
 			cmp = log_compare(&LSN(np), &argp->nlsn);
 			CHECK_LSN(op, cmp, &LSN(np), &argp->nlsn);
@@ -233,7 +216,7 @@ check_next:	/*
 				PREV_PGNO(np) = argp->right;
 				np->lsn = *lsnp;
 				if ((ret =
-				    mpf->put(mpf, np, DB_MPOOL_DIRTY)) != 0)
+				    __memp_fput(mpf, np, DB_MPOOL_DIRTY)) != 0)
 					goto out;
 				np = NULL;
 			}
@@ -246,13 +229,13 @@ check_next:	/*
 		 * the adds onto the page that caused the split, and there's
 		 * really no undo-ing to be done.
 		 */
-		if ((ret = mpf->get(mpf, &pgno, 0, &pp)) != 0) {
+		if ((ret = __memp_fget(mpf, &pgno, 0, &pp)) != 0) {
 			pp = NULL;
 			goto lrundo;
 		}
 		if (log_compare(lsnp, &LSN(pp)) == 0) {
 			memcpy(pp, argp->pg.data, argp->pg.size);
-			if ((ret = mpf->put(mpf, pp, DB_MPOOL_DIRTY)) != 0)
+			if ((ret = __memp_fput(mpf, pp, DB_MPOOL_DIRTY)) != 0)
 				goto out;
 			pp = NULL;
 		}
@@ -270,7 +253,7 @@ lrundo:		if ((rootsplit && lp != NULL) || rp != NULL) {
 			    log_compare(lsnp, &LSN(lp)) == 0) {
 				lp->lsn = argp->llsn;
 				if ((ret =
-				    mpf->put(mpf, lp, DB_MPOOL_DIRTY)) != 0)
+				    __memp_fput(mpf, lp, DB_MPOOL_DIRTY)) != 0)
 					goto out;
 				lp = NULL;
 			}
@@ -278,7 +261,7 @@ lrundo:		if ((rootsplit && lp != NULL) || rp != NULL) {
 			    log_compare(lsnp, &LSN(rp)) == 0) {
 				rp->lsn = argp->rlsn;
 				if ((ret =
-				    mpf->put(mpf, rp, DB_MPOOL_DIRTY)) != 0)
+				    __memp_fput(mpf, rp, DB_MPOOL_DIRTY)) != 0)
 					goto out;
 				rp = NULL;
 			}
@@ -292,15 +275,16 @@ lrundo:		if ((rootsplit && lp != NULL) || rp != NULL) {
 		 * possible that the next-page never existed, we ignore it as
 		 * if there's nothing to undo.
 		 */
-		if (!rootsplit && !IS_ZERO_LSN(argp->nlsn)) {
-			if ((ret = mpf->get(mpf, &argp->npgno, 0, &np)) != 0) {
+		if (!rootsplit && argp->npgno != PGNO_INVALID) {
+			if ((ret =
+			    __memp_fget(mpf, &argp->npgno, 0, &np)) != 0) {
 				np = NULL;
 				goto done;
 			}
 			if (log_compare(lsnp, &LSN(np)) == 0) {
 				PREV_PGNO(np) = argp->left;
 				np->lsn = argp->nlsn;
-				if (mpf->put(mpf, np, DB_MPOOL_DIRTY))
+				if (__memp_fput(mpf, np, DB_MPOOL_DIRTY))
 					goto out;
 				np = NULL;
 			}
@@ -311,13 +295,13 @@ done:	*lsnp = argp->prev_lsn;
 	ret = 0;
 
 out:	/* Free any pages that weren't dirtied. */
-	if (pp != NULL && (t_ret = mpf->put(mpf, pp, 0)) != 0 && ret == 0)
+	if (pp != NULL && (t_ret = __memp_fput(mpf, pp, 0)) != 0 && ret == 0)
 		ret = t_ret;
-	if (lp != NULL && (t_ret = mpf->put(mpf, lp, 0)) != 0 && ret == 0)
+	if (lp != NULL && (t_ret = __memp_fput(mpf, lp, 0)) != 0 && ret == 0)
 		ret = t_ret;
-	if (np != NULL && (t_ret = mpf->put(mpf, np, 0)) != 0 && ret == 0)
+	if (np != NULL && (t_ret = __memp_fput(mpf, np, 0)) != 0 && ret == 0)
 		ret = t_ret;
-	if (rp != NULL && (t_ret = mpf->put(mpf, rp, 0)) != 0 && ret == 0)
+	if (rp != NULL && (t_ret = __memp_fput(mpf, rp, 0)) != 0 && ret == 0)
 		ret = t_ret;
 
 	/* Free any allocated space. */
@@ -362,18 +346,18 @@ __bam_rsplit_recover(dbenv, dbtp, lsnp, op, info)
 
 	/* Fix the root page. */
 	pgno = root_pgno = argp->root_pgno;
-	if ((ret = mpf->get(mpf, &pgno, 0, &pagep)) != 0) {
-		/* The root page must always exist if we are going forward. */
-		if (DB_REDO(op)) {
-			__db_pgerr(file_dbp, pgno, ret);
+	if ((ret = __memp_fget(mpf, &pgno, 0, &pagep)) != 0) {
+		if (ret != DB_PAGE_NOTFOUND
+#ifndef HAVE_FTRUNCATE
+		     || DB_REDO(op)
+#endif
+		     ) {
+			ret = __db_pgerr(file_dbp, pgno, ret);
 			goto out;
-		}
-		/* This must be the root of an OPD tree. */
-		DB_ASSERT(root_pgno !=
-		    ((BTREE *)file_dbp->bt_internal)->bt_root);
-		ret = 0;
-		goto do_page;
+		} else
+			goto do_page;
 	}
+
 	modified = 0;
 	cmp_n = log_compare(lsnp, &LSN(pagep));
 	cmp_p = log_compare(&LSN(pagep), &argp->rootlsn);
@@ -395,7 +379,7 @@ __bam_rsplit_recover(dbenv, dbtp, lsnp, op, info)
 		pagep->lsn = argp->rootlsn;
 		modified = 1;
 	}
-	if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+	if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
 		goto out;
 
 do_page:
@@ -404,11 +388,16 @@ do_page:
 	 * page never made it to disk, so if we're undo-ing and the page
 	 * doesn't exist, it's okay and there's nothing further to do.
 	 */
-	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
-		if (DB_UNDO(op))
+	if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
+		if (ret != DB_PAGE_NOTFOUND
+#ifndef HAVE_FTRUNCATE
+		     || DB_REDO(op)
+#endif
+		     ) {
+			ret = __db_pgerr(file_dbp, argp->pgno, ret);
+			goto out;
+		} else
 			goto done;
-		__db_pgerr(file_dbp, argp->pgno, ret);
-		goto out;
 	}
 	modified = 0;
 	(void)__ua_memcpy(&copy_lsn, &LSN(argp->pgdbt.data), sizeof(DB_LSN));
@@ -424,7 +413,7 @@ do_page:
 		memcpy(pagep, argp->pgdbt.data, argp->pgdbt.size);
 		modified = 1;
 	}
-	if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+	if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
 		goto out;
 	pagep = NULL;
 
@@ -432,7 +421,7 @@ done:	*lsnp = argp->prev_lsn;
 	ret = 0;
 
 out:	if (pagep != NULL)
-		(void)mpf->put(mpf, pagep, 0);
+		(void)__memp_fput(mpf, pagep, 0);
 	REC_CLOSE;
 }
 
@@ -464,11 +453,16 @@ __bam_adj_recover(dbenv, dbtp, lsnp, op, info)
 	REC_INTRO(__bam_adj_read, 1);
 
 	/* Get the page; if it never existed and we're undoing, we're done. */
-	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
-		if (DB_UNDO(op))
+	if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
+		if (ret != DB_PAGE_NOTFOUND
+#ifndef HAVE_FTRUNCATE
+		     || DB_REDO(op)
+#endif
+		     ) {
+			ret = __db_pgerr(file_dbp, argp->pgno, ret);
+			goto out;
+		} else
 			goto done;
-		__db_pgerr(file_dbp, argp->pgno, ret);
-		goto out;
 	}
 
 	modified = 0;
@@ -492,7 +486,7 @@ __bam_adj_recover(dbenv, dbtp, lsnp, op, info)
 		LSN(pagep) = argp->lsn;
 		modified = 1;
 	}
-	if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+	if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
 		goto out;
 	pagep = NULL;
 
@@ -500,7 +494,7 @@ done:	*lsnp = argp->prev_lsn;
 	ret = 0;
 
 out:	if (pagep != NULL)
-		(void)mpf->put(mpf, pagep, 0);
+		(void)__memp_fput(mpf, pagep, 0);
 	REC_CLOSE;
 }
 
@@ -533,11 +527,16 @@ __bam_cadjust_recover(dbenv, dbtp, lsnp, op, info)
 	REC_INTRO(__bam_cadjust_read, 1);
 
 	/* Get the page; if it never existed and we're undoing, we're done. */
-	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
-		if (DB_UNDO(op))
+	if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
+		if (ret != DB_PAGE_NOTFOUND
+#ifndef HAVE_FTRUNCATE
+		     || DB_REDO(op)
+#endif
+		     ) {
+			ret = __db_pgerr(file_dbp, argp->pgno, ret);
+			goto out;
+		} else
 			goto done;
-		__db_pgerr(file_dbp, argp->pgno, ret);
-		goto out;
 	}
 
 	modified = 0;
@@ -576,7 +575,7 @@ __bam_cadjust_recover(dbenv, dbtp, lsnp, op, info)
 		LSN(pagep) = argp->lsn;
 		modified = 1;
 	}
-	if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+	if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
 		goto out;
 	pagep = NULL;
 
@@ -584,7 +583,7 @@ done:	*lsnp = argp->prev_lsn;
 	ret = 0;
 
 out:	if (pagep != NULL)
-		(void)mpf->put(mpf, pagep, 0);
+		(void)__memp_fput(mpf, pagep, 0);
 	REC_CLOSE;
 }
 
@@ -617,11 +616,16 @@ __bam_cdel_recover(dbenv, dbtp, lsnp, op, info)
 	REC_INTRO(__bam_cdel_read, 1);
 
 	/* Get the page; if it never existed and we're undoing, we're done. */
-	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
-		if (DB_UNDO(op))
+	if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
+		if (ret != DB_PAGE_NOTFOUND
+#ifndef HAVE_FTRUNCATE
+		     || DB_REDO(op)
+#endif
+		     ) {
+			ret = __db_pgerr(file_dbp, argp->pgno, ret);
+			goto out;
+		} else
 			goto done;
-		__db_pgerr(file_dbp, argp->pgno, ret);
-		goto out;
 	}
 
 	modified = 0;
@@ -645,7 +649,7 @@ __bam_cdel_recover(dbenv, dbtp, lsnp, op, info)
 		LSN(pagep) = argp->lsn;
 		modified = 1;
 	}
-	if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+	if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
 		goto out;
 	pagep = NULL;
 
@@ -653,7 +657,7 @@ done:	*lsnp = argp->prev_lsn;
 	ret = 0;
 
 out:	if (pagep != NULL)
-		(void)mpf->put(mpf, pagep, 0);
+		(void)__memp_fput(mpf, pagep, 0);
 	REC_CLOSE;
 }
 
@@ -688,11 +692,16 @@ __bam_repl_recover(dbenv, dbtp, lsnp, op, info)
 	REC_INTRO(__bam_repl_read, 1);
 
 	/* Get the page; if it never existed and we're undoing, we're done. */
-	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
-		if (DB_UNDO(op))
+	if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
+		if (ret != DB_PAGE_NOTFOUND
+#ifndef HAVE_FTRUNCATE
+		     || DB_REDO(op)
+#endif
+		     ) {
+			ret = __db_pgerr(file_dbp, argp->pgno, ret);
+			goto out;
+		} else
 			goto done;
-		__db_pgerr(file_dbp, argp->pgno, ret);
-		goto out;
 	}
 	bk = GET_BKEYDATA(file_dbp, pagep, argp->indx);
 
@@ -753,7 +762,7 @@ __bam_repl_recover(dbenv, dbtp, lsnp, op, info)
 		LSN(pagep) = argp->lsn;
 		modified = 1;
 	}
-	if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+	if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
 		goto out;
 	pagep = NULL;
 
@@ -761,7 +770,7 @@ done:	*lsnp = argp->prev_lsn;
 	ret = 0;
 
 out:	if (pagep != NULL)
-		(void)mpf->put(mpf, pagep, 0);
+		(void)__memp_fput(mpf, pagep, 0);
 	REC_CLOSE;
 }
 
@@ -792,10 +801,13 @@ __bam_root_recover(dbenv, dbtp, lsnp, op, info)
 	REC_PRINT(__bam_root_print);
 	REC_INTRO(__bam_root_read, 0);
 
-	if ((ret = mpf->get(mpf, &argp->meta_pgno, 0, &meta)) != 0) {
-		/* The metadata page must always exist on redo. */
-		if (DB_REDO(op)) {
-			__db_pgerr(file_dbp, argp->meta_pgno, ret);
+	if ((ret = __memp_fget(mpf, &argp->meta_pgno, 0, &meta)) != 0) {
+		if (ret != DB_PAGE_NOTFOUND
+#ifndef HAVE_FTRUNCATE
+		     || DB_REDO(op)
+#endif
+		     ) {
+			ret = __db_pgerr(file_dbp, argp->meta_pgno, ret);
 			goto out;
 		} else
 			goto done;
@@ -816,7 +828,7 @@ __bam_root_recover(dbenv, dbtp, lsnp, op, info)
 		meta->dbmeta.lsn = argp->meta_lsn;
 		modified = 1;
 	}
-	if ((ret = mpf->put(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+	if ((ret = __memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
 		goto out;
 	meta = NULL;
 
@@ -824,7 +836,7 @@ done:	*lsnp = argp->prev_lsn;
 	ret = 0;
 
 out:	if (meta != NULL)
-		(void)mpf->put(mpf, meta, 0);
+		(void)__memp_fput(mpf, meta, 0);
 	REC_CLOSE;
 }
 
@@ -851,6 +863,7 @@ __bam_curadj_recover(dbenv, dbtp, lsnp, op, info)
 	int ret;
 
 	COMPQUIET(info, NULL);
+	COMPQUIET(mpf, NULL);
 
 	REC_PRINT(__bam_curadj_print);
 	REC_INTRO(__bam_curadj_read, 0);
@@ -859,7 +872,7 @@ __bam_curadj_recover(dbenv, dbtp, lsnp, op, info)
 	if (op != DB_TXN_ABORT)
 		goto done;
 
-	switch(argp->mode) {
+	switch (argp->mode) {
 	case DB_CA_DI:
 		if ((ret = __bam_ca_di(dbc, argp->from_pgno,
 		    argp->from_indx, -(int)argp->first_indx)) != 0)
@@ -911,6 +924,7 @@ __bam_rcuradj_recover(dbenv, dbtp, lsnp, op, info)
 	int ret, t_ret;
 
 	COMPQUIET(info, NULL);
+	COMPQUIET(mpf, NULL);
 	rdbc = NULL;
 
 	REC_PRINT(__bam_rcuradj_print);
@@ -931,8 +945,7 @@ __bam_rcuradj_recover(dbenv, dbtp, lsnp, op, info)
 	 * state into __ram_ca, and this way we don't need to make
 	 * this function know anything about how offpage dups work.
 	 */
-	if ((ret =
-	    __db_icursor(file_dbp,
+	if ((ret = __db_cursor_int(file_dbp,
 		NULL, DB_RECNO, argp->root, 0, DB_LOCK_INVALIDID, &rdbc)) != 0)
 		goto out;
 
@@ -940,7 +953,7 @@ __bam_rcuradj_recover(dbenv, dbtp, lsnp, op, info)
 	F_SET(cp, C_RENUMBER);
 	cp->recno = argp->recno;
 
-	switch(argp->mode) {
+	switch (argp->mode) {
 	case CA_DELETE:
 		/*
 		 * The way to undo a delete is with an insert.  Since
@@ -949,7 +962,7 @@ __bam_rcuradj_recover(dbenv, dbtp, lsnp, op, info)
 		F_SET(cp, C_DELETED);
 		F_SET(cp, C_RENUMBER);	/* Just in case. */
 		cp->order = argp->order;
-		__ram_ca(rdbc, CA_ICURRENT);
+		(void)__ram_ca(rdbc, CA_ICURRENT);
 		break;
 	case CA_IAFTER:
 	case CA_IBEFORE:
@@ -960,12 +973,157 @@ __bam_rcuradj_recover(dbenv, dbtp, lsnp, op, info)
 		 */
 		F_CLR(cp, C_DELETED);
 		cp->order = INVALID_ORDER;
-		__ram_ca(rdbc, CA_DELETE);
+		(void)__ram_ca(rdbc, CA_DELETE);
 		break;
 	}
 
 done:	*lsnp = argp->prev_lsn;
-out:	if (rdbc != NULL && (t_ret = rdbc->c_close(rdbc)) != 0 && ret == 0)
+out:	if (rdbc != NULL && (t_ret = __db_c_close(rdbc)) != 0 && ret == 0)
 		ret = t_ret;
 	REC_CLOSE;
 }
+
+/*
+ * __bam_relink_recover --
+ *	Recovery function for relink.
+ *
+ * PUBLIC: int __bam_relink_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__bam_relink_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__bam_relink_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	pagep = NULL;
+	COMPQUIET(info, NULL);
+	REC_PRINT(__bam_relink_print);
+	REC_INTRO(__bam_relink_read, 1);
+
+	/*
+	 * There are up to three pages we need to check -- the page, and the
+	 * previous and next pages, if they existed.  For a page add operation,
+	 * the current page is the result of a split and is being recovered
+	 * elsewhere, so all we need do is recover the next page.
+	 */
+	if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
+		if (ret != DB_PAGE_NOTFOUND
+#ifndef HAVE_FTRUNCATE
+		     || DB_REDO(op)
+#endif
+		     ) {
+			ret = __db_pgerr(file_dbp, argp->pgno, ret);
+			goto out;
+		} else
+			goto next2;
+	}
+	modified = 0;
+
+	cmp_p = log_compare(&LSN(pagep), &argp->lsn);
+	CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn);
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Redo the relink. */
+		pagep->lsn = *lsnp;
+		modified = 1;
+	} else if (log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) {
+		/* Undo the relink. */
+		pagep->next_pgno = argp->next;
+		pagep->prev_pgno = argp->prev;
+
+		pagep->lsn = argp->lsn;
+		modified = 1;
+	}
+	if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+		goto out;
+	pagep = NULL;
+
+next2: if ((ret = __memp_fget(mpf, &argp->next, 0, &pagep)) != 0) {
+		if (ret != DB_PAGE_NOTFOUND
+#ifndef HAVE_FTRUNCATE
+		     || DB_REDO(op)
+#endif
+		     ) {
+			ret = __db_pgerr(file_dbp, argp->next, ret);
+			goto out;
+		} else
+			goto prev;
+	}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+	cmp_p = log_compare(&LSN(pagep), &argp->lsn_next);
+	CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn_next);
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Redo the remove or undo the add. */
+		pagep->prev_pgno = argp->prev;
+
+		modified = 1;
+	} else if (cmp_n == 0 && DB_UNDO(op)) {
+		/* Undo the remove or redo the add. */
+		pagep->prev_pgno = argp->pgno;
+
+		modified = 1;
+	}
+	if (modified == 1) {
+		if (DB_UNDO(op))
+			pagep->lsn = argp->lsn_next;
+		else
+			pagep->lsn = *lsnp;
+	}
+	if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+		goto out;
+	pagep = NULL;
+
+prev: if ((ret = __memp_fget(mpf, &argp->prev, 0, &pagep)) != 0) {
+		if (ret != DB_PAGE_NOTFOUND
+#ifndef HAVE_FTRUNCATE
+		     || DB_REDO(op)
+#endif
+		     ) {
+			ret = __db_pgerr(file_dbp, argp->prev, ret);
+			goto out;
+		} else
+			goto done;
+	}
+
+	modified = 0;
+	cmp_p = log_compare(&LSN(pagep), &argp->lsn_prev);
+	CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn_prev);
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Redo the relink. */
+		pagep->next_pgno = argp->next;
+
+		modified = 1;
+	} else if (log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) {
+		/* Undo the relink. */
+		pagep->next_pgno = argp->pgno;
+
+		modified = 1;
+	}
+	if (modified == 1) {
+		if (DB_UNDO(op))
+			pagep->lsn = argp->lsn_prev;
+		else
+			pagep->lsn = *lsnp;
+	}
+	if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+		goto out;
+	pagep = NULL;
+
+done:	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	if (pagep != NULL)
+		(void)__memp_fput(mpf, pagep, 0);
+	REC_CLOSE;
+}
diff --git a/storage/bdb/btree/bt_reclaim.c b/storage/bdb/btree/bt_reclaim.c
index ae4554ea7d606b024c79905da7ed280813e96a20..ee722a30f15cbb5af663a8698e0c0a6329ac5d7f 100644
--- a/storage/bdb/btree/bt_reclaim.c
+++ b/storage/bdb/btree/bt_reclaim.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1998-2002
+ * Copyright (c) 1998-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: bt_reclaim.c,v 11.15 2004/01/28 03:35:49 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: bt_reclaim.c,v 11.11 2002/03/29 20:46:26 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -36,7 +34,7 @@ __bam_reclaim(dbp, txn)
 	int ret, t_ret;
 
 	/* Acquire a cursor. */
-	if ((ret = dbp->cursor(dbp, txn, &dbc, 0)) != 0)
+	if ((ret = __db_cursor(dbp, txn, &dbc, 0)) != 0)
 		return (ret);
 
 	/* Walk the tree, freeing pages. */
@@ -44,7 +42,7 @@ __bam_reclaim(dbp, txn)
 	    DB_LOCK_WRITE, dbc->internal->root, __db_reclaim_callback, dbc);
 
 	/* Discard the cursor. */
-	if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
+	if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
 		ret = t_ret;
 
 	return (ret);
@@ -54,32 +52,23 @@ __bam_reclaim(dbp, txn)
  * __bam_truncate --
  *	Truncate a database.
  *
- * PUBLIC: int __bam_truncate __P((DB *, DB_TXN *, u_int32_t *));
+ * PUBLIC: int __bam_truncate __P((DBC *, u_int32_t *));
  */
 int
-__bam_truncate(dbp, txn, countp)
-	DB *dbp;
-	DB_TXN *txn;
+__bam_truncate(dbc, countp)
+	DBC *dbc;
 	u_int32_t *countp;
 {
-	DBC *dbc;
 	db_trunc_param trunc;
-	int ret, t_ret;
-
-	/* Acquire a cursor. */
-	if ((ret = dbp->cursor(dbp, txn, &dbc, 0)) != 0)
-		return (ret);
+	int ret;
 
 	trunc.count = 0;
 	trunc.dbc = dbc;
+
 	/* Walk the tree, freeing pages. */
 	ret = __bam_traverse(dbc,
 	    DB_LOCK_WRITE, dbc->internal->root, __db_truncate_callback, &trunc);
 
-	/* Discard the cursor. */
-	if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
-		ret = t_ret;
-
 	*countp = trunc.count;
 
 	return (ret);
diff --git a/storage/bdb/btree/bt_recno.c b/storage/bdb/btree/bt_recno.c
index fab684f3a5f0d1ef043c6ad075d563fe05e2e7ba..78f149dd61ccd1f2a500d0757f47699be5baaced 100644
--- a/storage/bdb/btree/bt_recno.c
+++ b/storage/bdb/btree/bt_recno.c
@@ -1,21 +1,17 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: bt_recno.c,v 11.117 2004/03/28 17:01:01 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: bt_recno.c,v 11.106 2002/08/16 04:56:30 ubell Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
-#include <limits.h>
-#include <stdio.h>
 #include <string.h>
 #endif
 
@@ -58,7 +54,7 @@ static int  __ram_update __P((DBC *, db_recno_t, int));
 	}								\
 }
 #define	CD_ISSET(cp)							\
-	(F_ISSET(cp, C_RENUMBER) && F_ISSET(cp, C_DELETED))
+	(F_ISSET(cp, C_RENUMBER) && F_ISSET(cp, C_DELETED) ? 1 : 0)
 
 /*
  * Macros for comparing the ordering of two cursors.
@@ -91,11 +87,13 @@ static int  __ram_update __P((DBC *, db_recno_t, int));
  * After a search, copy the found page into the cursor, discarding any
  * currently held lock.
  */
-#define	STACK_TO_CURSOR(cp) {						\
+#define	STACK_TO_CURSOR(cp, ret) {					\
+	int __t_ret;							\
 	(cp)->page = (cp)->csp->page;					\
 	(cp)->pgno = (cp)->csp->page->pgno;				\
 	(cp)->indx = (cp)->csp->indx;					\
-	(void)__TLPUT(dbc, (cp)->lock);					\
+	if ((__t_ret = __TLPUT(dbc, (cp)->lock)) != 0 && (ret) == 0)	\
+		ret = __t_ret;						\
 	(cp)->lock = (cp)->csp->lock;					\
 	(cp)->lock_mode = (cp)->csp->lock_mode;				\
 }
@@ -122,9 +120,6 @@ __ram_open(dbp, txn, name, base_pgno, flags)
 	COMPQUIET(name, NULL);
 	t = dbp->bt_internal;
 
-	/* Initialize the remaining fields/methods of the DB. */
-	dbp->stat = __bam_stat;
-
 	/* Start up the tree. */
 	if ((ret = __bam_read_root(dbp, txn, base_pgno, flags)) != 0)
 		return (ret);
@@ -143,7 +138,7 @@ __ram_open(dbp, txn, name, base_pgno, flags)
 	/* If we're snapshotting an underlying source file, do it now. */
 	if (F_ISSET(dbp, DB_AM_SNAPSHOT)) {
 		/* Allocate a cursor. */
-		if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0)
+		if ((ret = __db_cursor(dbp, NULL, &dbc, 0)) != 0)
 			return (ret);
 
 		/* Do the snapshot. */
@@ -152,7 +147,7 @@ __ram_open(dbp, txn, name, base_pgno, flags)
 			ret = 0;
 
 		/* Discard the cursor. */
-		if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
+		if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
 			ret = t_ret;
 	}
 
@@ -209,7 +204,7 @@ __ram_c_del(dbc)
 	DB_LSN lsn;
 	DBT hdr, data;
 	EPG *epg;
-	int exact, ret, stack;
+	int exact, ret, stack, t_ret;
 
 	dbp = dbc->dbp;
 	cp = (BTREE_CURSOR *)dbc->internal;
@@ -240,7 +235,9 @@ __ram_c_del(dbc)
 	stack = 1;
 
 	/* Copy the page into the cursor. */
-	STACK_TO_CURSOR(cp);
+	STACK_TO_CURSOR(cp, ret);
+	if (ret != 0)
+		goto err;
 
 	/*
 	 * If re-numbering records, the on-page deleted flag can only mean
@@ -262,7 +259,8 @@ __ram_c_del(dbc)
 		/* Delete the item, adjust the counts, adjust the cursors. */
 		if ((ret = __bam_ditem(dbc, cp->page, cp->indx)) != 0)
 			goto err;
-		__bam_adjust(dbc, -1);
+		if ((ret = __bam_adjust(dbc, -1)) != 0)
+			goto err;
 		if (__ram_ca(dbc, CA_DELETE) > 0 &&
 		    CURADJ_LOG(dbc) && (ret = __bam_rcuradj_log(dbp, dbc->txn,
 		    &lsn, 0, CA_DELETE, cp->root, cp->recno, cp->order)) != 0)
@@ -325,8 +323,8 @@ __ram_c_del(dbc)
 
 	t->re_modified = 1;
 
-err:	if (stack)
-		__bam_stkrel(dbc, STK_CLRDBC);
+err:	if (stack && (t_ret = __bam_stkrel(dbc, STK_CLRDBC)) != 0 && ret == 0)
+		ret = t_ret;
 
 	return (ret);
 }
@@ -388,8 +386,13 @@ retry:	switch (flags) {
 		 * we have to avoid incrementing the record number so that we
 		 * return the right record by virtue of renumbering the tree.
 		 */
-		if (CD_ISSET(cp))
+		if (CD_ISSET(cp)) {
+			/*
+			 * Clear the flag, we've moved off the deleted record.
+			 */
+			CD_CLR(cp);
 			break;
+		}
 
 		if (cp->recno != RECNO_OOB) {
 			++cp->recno;
@@ -494,7 +497,9 @@ retry:	switch (flags) {
 		}
 
 		/* Copy the page into the cursor. */
-		STACK_TO_CURSOR(cp);
+		STACK_TO_CURSOR(cp, ret);
+		if (ret != 0)
+			goto err;
 
 		/*
 		 * If re-numbering records, the on-page deleted flag means this
@@ -607,9 +612,11 @@ __ram_c_put(dbc, key, data, flags, pgnop)
 				return (ret);
 			if (CURADJ_LOG(dbc) &&
 			    (ret = __bam_rcuradj_log(dbp, dbc->txn, &lsn, 0,
-			    CA_ICURRENT, cp->root, cp->recno, cp->order)))
+			    CA_ICURRENT, cp->root, cp->recno, cp->order)) != 0)
 				return (ret);
 			return (0);
+		default:
+			break;
 		}
 
 	/*
@@ -650,7 +657,9 @@ split:	if ((ret = __bam_rsearch(dbc, &cp->recno, S_INSERT, 1, &exact)) != 0)
 	DB_ASSERT(exact || CD_ISSET(cp));
 
 	/* Copy the page into the cursor. */
-	STACK_TO_CURSOR(cp);
+	STACK_TO_CURSOR(cp, ret);
+	if (ret != 0)
+		goto err;
 
 	ret = __bam_iitem(dbc, key, data, iiflags, 0);
 	t_ret = __bam_stkrel(dbc, STK_CLRDBC);
@@ -708,6 +717,8 @@ split:	if ((ret = __bam_rsearch(dbc, &cp->recno, S_INSERT, 1, &exact)) != 0)
 		    CA_ICURRENT, cp->root, cp->recno, cp->order)) != 0)
 			goto err;
 		break;
+	default:
+		break;
 	}
 
 	/* Return the key if we've created a new record. */
@@ -983,7 +994,7 @@ __ram_source(dbp)
 	 * when it comes time to write the database back to the source.
 	 */
 	if ((t->re_fp = fopen(t->re_source, "r")) == NULL) {
-		ret = errno;
+		ret = __os_get_errno();
 		__db_err(dbp->dbenv, "%s: %s", t->re_source, db_strerror(ret));
 		return (ret);
 	}
@@ -1027,7 +1038,7 @@ __ram_writeback(dbp)
 	}
 
 	/* Allocate a cursor. */
-	if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0)
+	if ((ret = __db_cursor(dbp, NULL, &dbc, 0)) != 0)
 		return (ret);
 
 	/*
@@ -1060,13 +1071,13 @@ __ram_writeback(dbp)
 	 */
 	if (t->re_fp != NULL) {
 		if (fclose(t->re_fp) != 0) {
-			ret = errno;
+			ret = __os_get_errno();
 			goto err;
 		}
 		t->re_fp = NULL;
 	}
 	if ((fp = fopen(t->re_source, "w")) == NULL) {
-		ret = errno;
+		ret = __os_get_errno();
 		__db_err(dbenv, "%s: %s", t->re_source, db_strerror(ret));
 		goto err;
 	}
@@ -1088,23 +1099,24 @@ __ram_writeback(dbp)
 	 * and the pad character if we're doing fixed-length records.
 	 */
 	delim = t->re_delim;
-	if (F_ISSET(dbp, DB_AM_FIXEDLEN)) {
-		if ((ret = __os_malloc(dbenv, t->re_len, &pad)) != 0)
-			goto err;
-		memset(pad, t->re_pad, t->re_len);
-	}
 	for (keyno = 1;; ++keyno) {
-		switch (ret = dbp->get(dbp, NULL, &key, &data, 0)) {
+		switch (ret = __db_get(dbp, NULL, &key, &data, 0)) {
 		case 0:
-			if (data.size != 0 && (u_int32_t)fwrite(
-			    data.data, 1, data.size, fp) != data.size)
+			if (data.size != 0 &&
+			    fwrite(data.data, 1, data.size, fp) != data.size)
 				goto write_err;
 			break;
 		case DB_KEYEMPTY:
-			if (F_ISSET(dbp, DB_AM_FIXEDLEN) &&
-			    (u_int32_t)fwrite(pad, 1, t->re_len, fp) !=
-			    t->re_len)
-				goto write_err;
+			if (F_ISSET(dbp, DB_AM_FIXEDLEN)) {
+				if (pad == NULL) {
+					if ((ret = __os_malloc(
+					    dbenv, t->re_len, &pad)) != 0)
+						goto err;
+					memset(pad, t->re_pad, t->re_len);
+				}
+				if (fwrite(pad, 1, t->re_len, fp) != t->re_len)
+					goto write_err;
+			}
 			break;
 		case DB_NOTFOUND:
 			ret = 0;
@@ -1114,8 +1126,8 @@ __ram_writeback(dbp)
 		}
 		if (!F_ISSET(dbp, DB_AM_FIXEDLEN) &&
 		    fwrite(&delim, 1, 1, fp) != 1) {
-write_err:		ret = errno;
-			__db_err(dbp->dbenv,
+write_err:		ret = __os_get_errno();
+			__db_err(dbenv,
 			    "%s: write failed to backing file: %s",
 			    t->re_source, strerror(ret));
 			goto err;
@@ -1125,13 +1137,14 @@ write_err:		ret = errno;
 err:
 done:	/* Close the file descriptor. */
 	if (fp != NULL && fclose(fp) != 0) {
+		t_ret = __os_get_errno();
 		if (ret == 0)
-			ret = errno;
-		__db_err(dbenv, "%s: %s", t->re_source, db_strerror(errno));
+			ret = t_ret;
+		__db_err(dbenv, "%s: %s", t->re_source, db_strerror(t_ret));
 	}
 
 	/* Discard the cursor. */
-	if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
+	if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
 		ret = t_ret;
 
 	/* Discard memory allocated to hold the data items. */
@@ -1259,7 +1272,7 @@ __ram_add(dbc, recnop, data, flags, bi_flags)
 	u_int32_t flags, bi_flags;
 {
 	BTREE_CURSOR *cp;
-	int exact, ret, stack;
+	int exact, ret, stack, t_ret;
 
 	cp = (BTREE_CURSOR *)dbc->internal;
 
@@ -1270,7 +1283,9 @@ retry:	/* Find the slot for insertion. */
 	stack = 1;
 
 	/* Copy the page into the cursor. */
-	STACK_TO_CURSOR(cp);
+	STACK_TO_CURSOR(cp, ret);
+	if (ret != 0)
+		goto err;
 
 	/*
 	 * The application may modify the data based on the selected record
@@ -1320,8 +1335,8 @@ retry:	/* Find the slot for insertion. */
 		goto err;
 	}
 
-err:	if (stack)
-		__bam_stkrel(dbc, STK_CLRDBC);
+err:	if (stack && (t_ret = __bam_stkrel(dbc, STK_CLRDBC)) != 0 && ret == 0)
+		ret = t_ret;
 
 	return (ret);
 }
diff --git a/storage/bdb/btree/bt_rsearch.c b/storage/bdb/btree/bt_rsearch.c
index a75181b44e21bf69fcc3ad659b84a9b19be41fb1..0027ec9e4f32d787d49396198acfb18ddacc1fa3 100644
--- a/storage/bdb/btree/bt_rsearch.c
+++ b/storage/bdb/btree/bt_rsearch.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -35,14 +35,12 @@
  * 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.
+ *
+ * $Id: bt_rsearch.c,v 11.40 2004/07/23 17:21:09 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: bt_rsearch.c,v 11.34 2002/07/03 19:03:50 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #endif
@@ -52,6 +50,7 @@ static const char revid[] = "$Id: bt_rsearch.c,v 11.34 2002/07/03 19:03:50 bosti
 #include "dbinc/btree.h"
 #include "dbinc/db_shash.h"
 #include "dbinc/lock.h"
+#include "dbinc/mp.h"
 
 /*
  * __bam_rsearch --
@@ -77,11 +76,12 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
 	db_lockmode_t lock_mode;
 	db_pgno_t pg;
 	db_recno_t recno, t_recno, total;
-	int ret, stack;
+	int ret, stack, t_ret;
 
 	dbp = dbc->dbp;
 	mpf = dbp->mpf;
 	cp = (BTREE_CURSOR *)dbc->internal;
+	h = NULL;
 
 	BT_STK_CLR(cp);
 
@@ -105,7 +105,7 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
 	lock_mode = stack ? DB_LOCK_WRITE : DB_LOCK_READ;
 	if ((ret = __db_lget(dbc, 0, pg, lock_mode, 0, &lock)) != 0)
 		return (ret);
-	if ((ret = mpf->get(mpf, &pg, 0, &h)) != 0) {
+	if ((ret = __memp_fget(mpf, &pg, 0, &h)) != 0) {
 		/* Did not read it, so we can release the lock */
 		(void)__LPUT(dbc, lock);
 		return (ret);
@@ -122,12 +122,15 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
 	if (!stack &&
 	    ((LF_ISSET(S_PARENT) && (u_int8_t)(stop + 1) >= h->level) ||
 	    (LF_ISSET(S_WRITE) && h->level == LEAFLEVEL))) {
-		(void)mpf->put(mpf, h, 0);
-		(void)__LPUT(dbc, lock);
+		ret = __memp_fput(mpf, h, 0);
+		if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
+			ret = t_ret;
+		if (ret != 0)
+			return (ret);
 		lock_mode = DB_LOCK_WRITE;
 		if ((ret = __db_lget(dbc, 0, pg, lock_mode, 0, &lock)) != 0)
 			return (ret);
-		if ((ret = mpf->get(mpf, &pg, 0, &h)) != 0) {
+		if ((ret = __memp_fget(mpf, &pg, 0, &h)) != 0) {
 			/* Did not read it, so we can release the lock */
 			(void)__LPUT(dbc, lock);
 			return (ret);
@@ -166,9 +169,11 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
 				 * eliminate any concurrency.  A possible fix
 				 * would be to lock the last leaf page instead.
 				 */
-				(void)mpf->put(mpf, h, 0);
-				(void)__TLPUT(dbc, lock);
-				return (DB_NOTFOUND);
+				ret = __memp_fput(mpf, h, 0);
+				if ((t_ret =
+				    __TLPUT(dbc, lock)) != 0 && ret == 0)
+					ret = t_ret;
+				return (ret == 0 ? DB_NOTFOUND : ret);
 			}
 		}
 	}
@@ -200,7 +205,13 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
 					*exactp = 0;
 					if (!LF_ISSET(S_PAST_EOF) ||
 					    recno > t_recno + 1) {
-						ret = DB_NOTFOUND;
+						ret = __memp_fput(mpf, h, 0);
+						h = NULL;
+						if ((t_ret = __TLPUT(dbc,
+						    lock)) != 0 && ret == 0)
+							ret = t_ret;
+						if (ret == 0)
+							ret = DB_NOTFOUND;
 						goto err;
 					}
 				}
@@ -262,6 +273,7 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
 			    cp, h, indx, lock, lock_mode, ret);
 			if (ret != 0)
 				goto err;
+			h = NULL;
 
 			lock_mode = DB_LOCK_WRITE;
 			if ((ret =
@@ -278,7 +290,9 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
 			    (h->level - 1) == LEAFLEVEL)
 				stack = 1;
 
-			(void)mpf->put(mpf, h, 0);
+			if ((ret = __memp_fput(mpf, h, 0)) != 0)
+				goto err;
+			h = NULL;
 
 			lock_mode = stack &&
 			    LF_ISSET(S_WRITE) ? DB_LOCK_WRITE : DB_LOCK_READ;
@@ -289,18 +303,22 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
 				 * is OK because this only happens when we are
 				 * descending the tree holding read-locks.
 				 */
-				__LPUT(dbc, lock);
+				(void)__LPUT(dbc, lock);
 				goto err;
 			}
 		}
 
-		if ((ret = mpf->get(mpf, &pg, 0, &h)) != 0)
+		if ((ret = __memp_fget(mpf, &pg, 0, &h)) != 0)
 			goto err;
 	}
 	/* NOTREACHED */
 
-err:	BT_STK_POP(cp);
+err:	if (h != NULL && (t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
+		ret = t_ret;
+
+	BT_STK_POP(cp);
 	__bam_stkrel(dbc, 0);
+
 	return (ret);
 }
 
@@ -352,7 +370,7 @@ __bam_adjust(dbc, adjust)
 			if (PGNO(h) == root_pgno)
 				RE_NREC_ADJ(h, adjust);
 
-			if ((ret = mpf->set(mpf, h, DB_MPOOL_DIRTY)) != 0)
+			if ((ret = __memp_fset(mpf, h, DB_MPOOL_DIRTY)) != 0)
 				return (ret);
 		}
 	}
@@ -375,7 +393,7 @@ __bam_nrecs(dbc, rep)
 	DB_MPOOLFILE *mpf;
 	PAGE *h;
 	db_pgno_t pgno;
-	int ret;
+	int ret, t_ret;
 
 	dbp = dbc->dbp;
 	mpf = dbp->mpf;
@@ -383,15 +401,16 @@ __bam_nrecs(dbc, rep)
 	pgno = dbc->internal->root;
 	if ((ret = __db_lget(dbc, 0, pgno, DB_LOCK_READ, 0, &lock)) != 0)
 		return (ret);
-	if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
+	if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
 		return (ret);
 
 	*rep = RE_NREC(h);
 
-	(void)mpf->put(mpf, h, 0);
-	(void)__TLPUT(dbc, lock);
+	ret = __memp_fput(mpf, h, 0);
+	if ((t_ret = __TLPUT(dbc, lock)) != 0 && ret == 0)
+		ret = t_ret;
 
-	return (0);
+	return (ret);
 }
 
 /*
diff --git a/storage/bdb/btree/bt_search.c b/storage/bdb/btree/bt_search.c
index 92b2106311dc4d739b597c91fe32b187f7e316f5..4fb07f44694b58f4fa131599f7e33e7b64600ed2 100644
--- a/storage/bdb/btree/bt_search.c
+++ b/storage/bdb/btree/bt_search.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -38,14 +38,12 @@
  * 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.
+ *
+ * $Id: bt_search.c,v 11.50 2004/07/23 17:21:09 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: bt_search.c,v 11.43 2002/07/03 19:03:50 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -57,6 +55,7 @@ static const char revid[] = "$Id: bt_search.c,v 11.43 2002/07/03 19:03:50 bostic
 #include "dbinc/db_shash.h"
 #include "dbinc/btree.h"
 #include "dbinc/lock.h"
+#include "dbinc/mp.h"
 
 /*
  * __bam_search --
@@ -84,12 +83,13 @@ __bam_search(dbc, root_pgno, key, flags, stop, recnop, exactp)
 	db_lockmode_t lock_mode;
 	db_pgno_t pg;
 	db_recno_t recno;
-	int adjust, cmp, deloffset, ret, stack;
+	int adjust, cmp, deloffset, ret, stack, t_ret;
 	int (*func) __P((DB *, const DBT *, const DBT *));
 
 	dbp = dbc->dbp;
 	mpf = dbp->mpf;
 	cp = (BTREE_CURSOR *)dbc->internal;
+	h = NULL;
 	t = dbp->bt_internal;
 	recno = 0;
 
@@ -117,7 +117,7 @@ try_again:
 	lock_mode = stack ? DB_LOCK_WRITE : DB_LOCK_READ;
 	if ((ret = __db_lget(dbc, 0, pg, lock_mode, 0, &lock)) != 0)
 		return (ret);
-	if ((ret = mpf->get(mpf, &pg, 0, &h)) != 0) {
+	if ((ret = __memp_fget(mpf, &pg, 0, &h)) != 0) {
 		/* Did not read it, so we can release the lock */
 		(void)__LPUT(dbc, lock);
 		return (ret);
@@ -134,12 +134,15 @@ try_again:
 	if (!stack &&
 	    ((LF_ISSET(S_PARENT) && (u_int8_t)(stop + 1) >= h->level) ||
 	    (LF_ISSET(S_WRITE) && h->level == LEAFLEVEL))) {
-		(void)mpf->put(mpf, h, 0);
-		(void)__LPUT(dbc, lock);
+		ret = __memp_fput(mpf, h, 0);
+		if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
+			ret = t_ret;
+		if (ret != 0)
+			return (ret);
 		lock_mode = DB_LOCK_WRITE;
 		if ((ret = __db_lget(dbc, 0, pg, lock_mode, 0, &lock)) != 0)
 			return (ret);
-		if ((ret = mpf->get(mpf, &pg, 0, &h)) != 0) {
+		if ((ret = __memp_fget(mpf, &pg, 0, &h)) != 0) {
 			/* Did not read it, so we can release the lock */
 			(void)__LPUT(dbc, lock);
 			return (ret);
@@ -148,8 +151,11 @@ try_again:
 		    (u_int8_t)(stop + 1) >= h->level) ||
 		    (LF_ISSET(S_WRITE) && h->level == LEAFLEVEL))) {
 			/* Someone else split the root, start over. */
-			(void)mpf->put(mpf, h, 0);
-			(void)__LPUT(dbc, lock);
+			ret = __memp_fput(mpf, h, 0);
+			if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
+				ret = t_ret;
+			if (ret != 0)
+				return (ret);
 			goto try_again;
 		}
 		stack = 1;
@@ -197,13 +203,19 @@ try_again:
 		if (TYPE(h) == P_LBTREE || TYPE(h) == P_LDUP) {
 			*exactp = 0;
 
-			if (LF_ISSET(S_EXACT))
-				goto notfound;
+			if (LF_ISSET(S_EXACT)) {
+				ret = DB_NOTFOUND;
+				goto err;
+			}
 
 			if (LF_ISSET(S_STK_ONLY)) {
 				BT_STK_NUM(dbp->dbenv, cp, h, base, ret);
-				__LPUT(dbc, lock);
-				(void)mpf->put(mpf, h, 0);
+				if ((t_ret =
+				    __LPUT(dbc, lock)) != 0 && ret == 0)
+					ret = t_ret;
+				if ((t_ret =
+				    __memp_fput(mpf, h, 0)) != 0 && ret == 0)
+					ret = t_ret;
 				return (ret);
 			}
 
@@ -243,12 +255,17 @@ next:		if (recnop != NULL)
 		if (LF_ISSET(S_STK_ONLY)) {
 			if (stop == h->level) {
 				BT_STK_NUM(dbp->dbenv, cp, h, indx, ret);
-				__LPUT(dbc, lock);
-				(void)mpf->put(mpf, h, 0);
+				if ((t_ret =
+				    __LPUT(dbc, lock)) != 0 && ret == 0)
+					ret = t_ret;
+				if ((t_ret =
+				    __memp_fput(mpf, h, 0)) != 0 && ret == 0)
+					ret = t_ret;
 				return (ret);
 			}
 			BT_STK_NUMPUSH(dbp->dbenv, cp, h, indx, ret);
-			(void)mpf->put(mpf, h, 0);
+			(void)__memp_fput(mpf, h, 0);
+			h = NULL;
 			if ((ret = __db_lget(dbc,
 			    LCK_COUPLE_ALWAYS, pg, lock_mode, 0, &lock)) != 0) {
 				/*
@@ -256,7 +273,7 @@ next:		if (recnop != NULL)
 				 * is OK because it only happens when descending
 				 * the tree holding read-locks.
 				 */
-				__LPUT(dbc, lock);
+				(void)__LPUT(dbc, lock);
 				return (ret);
 			}
 		} else if (stack) {
@@ -272,6 +289,7 @@ next:		if (recnop != NULL)
 			    cp, h, indx, lock, lock_mode, ret);
 			if (ret != 0)
 				goto err;
+			h = NULL;
 
 			lock_mode = DB_LOCK_WRITE;
 			if ((ret =
@@ -288,7 +306,9 @@ next:		if (recnop != NULL)
 			    (h->level - 1) == LEAFLEVEL)
 				stack = 1;
 
-			(void)mpf->put(mpf, h, 0);
+			if ((ret = __memp_fput(mpf, h, 0)) != 0)
+				goto err;
+			h = NULL;
 
 			lock_mode = stack &&
 			    LF_ISSET(S_WRITE) ? DB_LOCK_WRITE : DB_LOCK_READ;
@@ -299,25 +319,17 @@ next:		if (recnop != NULL)
 				 * is OK because this only happens when we are
 				 * descending the tree holding read-locks.
 				 */
-				__LPUT(dbc, lock);
+				(void)__LPUT(dbc, lock);
 				goto err;
 			}
 		}
-		if ((ret = mpf->get(mpf, &pg, 0, &h)) != 0)
+		if ((ret = __memp_fget(mpf, &pg, 0, &h)) != 0)
 			goto err;
 	}
 	/* NOTREACHED */
 
 found:	*exactp = 1;
 
-	/*
-	 * If we're trying to calculate the record number, add in the
-	 * offset on this page and correct for the fact that records
-	 * in the tree are 0-based.
-	 */
-	if (recnop != NULL)
-		*recnop = recno + (indx / P_INDX) + 1;
-
 	/*
 	 * If we got here, we know that we have a Btree leaf or off-page
 	 * duplicates page.  If it's a Btree leaf page, we have to handle
@@ -345,6 +357,7 @@ found:	*exactp = 1;
 	 * not move from the original found key on the basis of the S_DELNO
 	 * flag.)
 	 */
+	DB_ASSERT(recnop == NULL || LF_ISSET(S_DELNO));
 	if (LF_ISSET(S_DELNO)) {
 		deloffset = TYPE(h) == P_LBTREE ? O_INDX : 0;
 		if (LF_ISSET(S_DUPLAST))
@@ -363,29 +376,53 @@ found:	*exactp = 1;
 		 * If we weren't able to find a non-deleted duplicate, return
 		 * DB_NOTFOUND.
 		 */
-		if (B_DISSET(GET_BKEYDATA(dbp, h, indx + deloffset)->type))
-			goto notfound;
+		if (B_DISSET(GET_BKEYDATA(dbp, h, indx + deloffset)->type)) {
+			ret = DB_NOTFOUND;
+			goto err;
+		}
+
+		/*
+		 * Increment the record counter to point to the found element.
+		 * Ignore any deleted key/data pairs.  There doesn't need to
+		 * be any correction for duplicates, as Btree doesn't support
+		 * duplicates and record numbers in the same tree.
+		 */
+		if (recnop != NULL) {
+			DB_ASSERT(TYPE(h) == P_LBTREE);
+
+			for (i = 0; i < indx; i += P_INDX)
+				if (!B_DISSET(
+				    GET_BKEYDATA(dbp, h, i + O_INDX)->type))
+					++recno;
+
+			/* Correct the number for a 0-base. */
+			*recnop = recno + 1;
+		}
 	}
 
 	if (LF_ISSET(S_STK_ONLY)) {
 		BT_STK_NUM(dbp->dbenv, cp, h, indx, ret);
-		__LPUT(dbc, lock);
-		(void)mpf->put(mpf, h, 0);
-	} else {
+		if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
+			ret = t_ret;
+		if ((t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
+			ret = t_ret;
+	} else
 		BT_STK_ENTER(dbp->dbenv, cp, h, indx, lock, lock_mode, ret);
-		if (ret != 0)
-			goto err;
-	}
+	if (ret != 0)
+		goto err;
+
 	return (0);
 
-notfound:
-	/* Keep the page locked for serializability. */
-	(void)mpf->put(mpf, h, 0);
-	(void)__TLPUT(dbc, lock);
-	ret = DB_NOTFOUND;
+err:	if (h != NULL && (t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
+		ret = t_ret;
+
+	/* Keep any not-found page locked for serializability. */
+	if ((t_ret = __TLPUT(dbc, lock)) != 0 && ret == 0)
+		ret = t_ret;
 
-err:	BT_STK_POP(cp);
+	BT_STK_POP(cp);
 	__bam_stkrel(dbc, 0);
+
 	return (ret);
 }
 
@@ -423,7 +460,7 @@ __bam_stkrel(dbc, flags)
 				LOCK_INIT(cp->lock);
 			}
 			if ((t_ret =
-			    mpf->put(mpf, epg->page, 0)) != 0 && ret == 0)
+			    __memp_fput(mpf, epg->page, 0)) != 0 && ret == 0)
 				ret = t_ret;
 			/*
 			 * XXX
@@ -434,10 +471,12 @@ __bam_stkrel(dbc, flags)
 			 */
 			epg->page = NULL;
 		}
-		if (LF_ISSET(STK_NOLOCK))
-			(void)__LPUT(dbc, epg->lock);
-		else
-			(void)__TLPUT(dbc, epg->lock);
+		if (LF_ISSET(STK_NOLOCK)) {
+			if ((t_ret = __LPUT(dbc, epg->lock)) != 0 && ret == 0)
+				ret = t_ret;
+		} else
+			if ((t_ret = __TLPUT(dbc, epg->lock)) != 0 && ret == 0)
+				ret = t_ret;
 	}
 
 	/* Clear the stack, all pages have been released. */
diff --git a/storage/bdb/btree/bt_split.c b/storage/bdb/btree/bt_split.c
index f3302a6905f26936a3c6390e8532c6dab526c275..3e2cb4e6dfb91266406769157cbe81f8d2b1840c 100644
--- a/storage/bdb/btree/bt_split.c
+++ b/storage/bdb/btree/bt_split.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -35,18 +35,15 @@
  * 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.
+ *
+ * $Id: bt_split.c,v 11.66 2004/10/01 13:00:21 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: bt_split.c,v 11.58 2002/07/03 19:03:50 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
-#include <limits.h>
 #include <string.h>
 #endif
 
@@ -54,6 +51,7 @@ static const char revid[] = "$Id: bt_split.c,v 11.58 2002/07/03 19:03:50 bostic
 #include "dbinc/db_page.h"
 #include "dbinc/db_shash.h"
 #include "dbinc/lock.h"
+#include "dbinc/mp.h"
 #include "dbinc/btree.h"
 
 static int __bam_broot __P((DBC *, PAGE *, PAGE *, PAGE *));
@@ -119,7 +117,7 @@ __bam_split(dbc, arg, root_pgnop)
 			arg, S_WRPAIR, level, NULL, &exact) :
 		    __bam_rsearch(dbc,
 			(db_recno_t *)arg, S_WRPAIR, level, &exact))) != 0)
-			return (ret);
+			break;
 
 		if (root_pgnop != NULL)
 			*root_pgnop = cp->csp[0].page->pgno == root_pgno ?
@@ -133,7 +131,7 @@ __bam_split(dbc, arg, root_pgnop)
 		if (2 * B_MAXSIZEONPAGE(cp->ovflsize)
 		    <= (db_indx_t)P_FREESPACE(dbc->dbp, cp->csp[0].page)) {
 			__bam_stkrel(dbc, STK_NOLOCK);
-			return (0);
+			break;
 		}
 		ret = cp->csp[0].page->pgno == root_pgno ?
 		    __bam_root(dbc, &cp->csp[0]) :
@@ -161,10 +159,13 @@ __bam_split(dbc, arg, root_pgnop)
 				dir = UP;
 			break;
 		default:
-			return (ret);
+			goto err;
 		}
 	}
-	/* NOTREACHED */
+
+err:	if (root_pgnop != NULL)
+		*root_pgnop = cp->root;
+	return (ret);
 }
 
 /*
@@ -183,10 +184,11 @@ __bam_root(dbc, cp)
 	PAGE *lp, *rp;
 	db_indx_t split;
 	u_int32_t opflags;
-	int ret;
+	int ret, t_ret;
 
 	dbp = dbc->dbp;
 	mpf = dbp->mpf;
+	lp = rp = NULL;
 
 	/* Yeah, right. */
 	if (cp->page->level >= MAXBTREELEVEL) {
@@ -197,7 +199,6 @@ __bam_root(dbc, cp)
 	}
 
 	/* Create new left and right pages for the split. */
-	lp = rp = NULL;
 	if ((ret = __db_new(dbc, TYPE(cp->page), &lp)) != 0 ||
 	    (ret = __db_new(dbc, TYPE(cp->page), &rp)) != 0)
 		goto err;
@@ -237,24 +238,21 @@ __bam_root(dbc, cp)
 		goto err;
 
 	/* Adjust any cursors. */
-	if ((ret = __bam_ca_split(dbc,
-	    cp->page->pgno, lp->pgno, rp->pgno, split, 1)) != 0)
-		goto err;
+	ret = __bam_ca_split(dbc, cp->page->pgno, lp->pgno, rp->pgno, split, 1);
 
-	/* Success -- write the real pages back to the store. */
-	(void)mpf->put(mpf, cp->page, DB_MPOOL_DIRTY);
-	(void)__TLPUT(dbc, cp->lock);
-	(void)mpf->put(mpf, lp, DB_MPOOL_DIRTY);
-	(void)mpf->put(mpf, rp, DB_MPOOL_DIRTY);
-
-	return (0);
+	/* Success or error: release pages and locks. */
+err:	if ((t_ret =
+	    __memp_fput(mpf, cp->page, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+		ret = t_ret;
+	if ((t_ret = __TLPUT(dbc, cp->lock)) != 0 && ret == 0)
+		ret = t_ret;
+	if (lp != NULL &&
+	    (t_ret = __memp_fput(mpf, lp, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+		ret = t_ret;
+	if (rp != NULL &&
+	    (t_ret = __memp_fput(mpf, rp, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+		ret = t_ret;
 
-err:	if (lp != NULL)
-		(void)mpf->put(mpf, lp, 0);
-	if (rp != NULL)
-		(void)mpf->put(mpf, rp, 0);
-	(void)mpf->put(mpf, cp->page, 0);
-	(void)__TLPUT(dbc, cp->lock);
 	return (ret);
 }
 
@@ -358,7 +356,7 @@ __bam_page(dbc, pp, cp)
 		if ((ret = __db_lget(dbc,
 		    0, NEXT_PGNO(cp->page), DB_LOCK_WRITE, 0, &tplock)) != 0)
 			goto err;
-		if ((ret = mpf->get(mpf, &NEXT_PGNO(cp->page), 0, &tp)) != 0)
+		if ((ret = __memp_fget(mpf, &NEXT_PGNO(cp->page), 0, &tp)) != 0)
 			goto err;
 	}
 
@@ -370,9 +368,13 @@ __bam_page(dbc, pp, cp)
 		goto err;
 
 	/*
-	 * Lock the new page.  We need to do this because someone
-	 * could get here through bt_lpgno if this page was recently
-	 * dealocated.  They can't look at it before we commit.
+	 * Lock the new page.  We need to do this for two reasons: first, the
+	 * fast-lookup code might have a reference to this page in bt_lpgno if
+	 * the page was recently deleted from the tree, and that code doesn't
+	 * walk the tree and so won't encounter the parent's page lock.
+	 * Second, a dirty reader could get to this page via the parent or old
+	 * page after the split is done but before the transaction is committed
+	 * or aborted.
 	 */
 	if ((ret = __db_lget(dbc,
 	    0, PGNO(alloc_rp), DB_LOCK_WRITE, 0, &rplock)) != 0)
@@ -456,20 +458,27 @@ __bam_page(dbc, pp, cp)
 	 * releasing locks on the pages that reference it.  We're finished
 	 * modifying the page so it's not really necessary, but it's neater.
 	 */
-	if ((t_ret = mpf->put(mpf, alloc_rp, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+	if ((t_ret =
+	    __memp_fput(mpf, alloc_rp, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+		ret = t_ret;
+	if ((t_ret = __TLPUT(dbc, rplock)) != 0 && ret == 0)
 		ret = t_ret;
-	(void)__TLPUT(dbc, rplock);
-	if ((t_ret = mpf->put(mpf, pp->page, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+	if ((t_ret =
+	    __memp_fput(mpf, pp->page, DB_MPOOL_DIRTY)) != 0 && ret == 0)
 		ret = t_ret;
-	(void)__TLPUT(dbc, pp->lock);
-	if ((t_ret = mpf->put(mpf, cp->page, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+	if ((t_ret = __TLPUT(dbc, pp->lock)) != 0 && ret == 0)
+		ret = t_ret;
+	if ((t_ret =
+	    __memp_fput(mpf, cp->page, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+		ret = t_ret;
+	if ((t_ret = __TLPUT(dbc, cp->lock)) != 0 && ret == 0)
 		ret = t_ret;
-	(void)__TLPUT(dbc, cp->lock);
 	if (tp != NULL) {
 		if ((t_ret =
-		    mpf->put(mpf, tp, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+		    __memp_fput(mpf, tp, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+			ret = t_ret;
+		if ((t_ret = __TLPUT(dbc, tplock)) != 0 && ret == 0)
 			ret = t_ret;
-		(void)__TLPUT(dbc, tplock);
 	}
 	return (ret);
 
@@ -478,21 +487,21 @@ err:	if (lp != NULL)
 	if (rp != NULL)
 		__os_free(dbp->dbenv, rp);
 	if (alloc_rp != NULL)
-		(void)mpf->put(mpf, alloc_rp, 0);
+		(void)__memp_fput(mpf, alloc_rp, 0);
 	if (tp != NULL)
-		(void)mpf->put(mpf, tp, 0);
+		(void)__memp_fput(mpf, tp, 0);
 
 	/* We never updated the new or next pages, we can release them. */
 	(void)__LPUT(dbc, rplock);
 	(void)__LPUT(dbc, tplock);
 
-	(void)mpf->put(mpf, pp->page, 0);
+	(void)__memp_fput(mpf, pp->page, 0);
 	if (ret == DB_NEEDSPLIT)
 		(void)__LPUT(dbc, pp->lock);
 	else
 		(void)__TLPUT(dbc, pp->lock);
 
-	(void)mpf->put(mpf, cp->page, 0);
+	(void)__memp_fput(mpf, cp->page, 0);
 	if (ret == DB_NEEDSPLIT)
 		(void)__LPUT(dbc, cp->lock);
 	else
diff --git a/storage/bdb/btree/bt_stat.c b/storage/bdb/btree/bt_stat.c
index 4428de98294947d9611cc88e27183899cc13eca6..9d99ee2c422f82b54f189b0bc173f9d05dccec34 100644
--- a/storage/bdb/btree/bt_stat.c
+++ b/storage/bdb/btree/bt_stat.c
@@ -1,19 +1,18 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: bt_stat.c,v 11.78 2004/09/22 03:31:26 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: bt_stat.c,v 11.52 2002/05/30 15:40:27 krinsky Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
+#include <ctype.h>
 #include <string.h>
 #endif
 
@@ -22,33 +21,35 @@ static const char revid[] = "$Id: bt_stat.c,v 11.52 2002/05/30 15:40:27 krinsky
 #include "dbinc/db_shash.h"
 #include "dbinc/btree.h"
 #include "dbinc/lock.h"
-#include "dbinc/log.h"
+#include "dbinc/mp.h"
 
+#ifdef HAVE_STATISTICS
 /*
  * __bam_stat --
  *	Gather/print the btree statistics
  *
- * PUBLIC: int __bam_stat __P((DB *, void *, u_int32_t));
+ * PUBLIC: int __bam_stat __P((DBC *, void *, u_int32_t));
  */
 int
-__bam_stat(dbp, spp, flags)
-	DB *dbp;
+__bam_stat(dbc, spp, flags)
+	DBC *dbc;
 	void *spp;
 	u_int32_t flags;
 {
 	BTMETA *meta;
 	BTREE *t;
 	BTREE_CURSOR *cp;
-	DBC *dbc;
+	DB *dbp;
 	DB_BTREE_STAT *sp;
+	DB_ENV *dbenv;
 	DB_LOCK lock, metalock;
 	DB_MPOOLFILE *mpf;
 	PAGE *h;
 	db_pgno_t pgno;
 	int ret, t_ret, write_meta;
 
-	PANIC_CHECK(dbp->dbenv);
-	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->stat");
+	dbp = dbc->dbp;
+	dbenv = dbp->dbenv;
 
 	meta = NULL;
 	t = dbp->bt_internal;
@@ -57,22 +58,12 @@ __bam_stat(dbp, spp, flags)
 	LOCK_INIT(lock);
 	mpf = dbp->mpf;
 	h = NULL;
-	ret = 0;
-	write_meta = 0;
-
-	/* Check for invalid flags. */
-	if ((ret = __db_statchk(dbp, flags)) != 0)
-		return (ret);
+	ret = write_meta = 0;
 
-	/* Acquire a cursor. */
-	if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0)
-		return (ret);
 	cp = (BTREE_CURSOR *)dbc->internal;
 
-	DEBUG_LWRITE(dbc, NULL, "bam_stat", NULL, NULL, flags);
-
 	/* Allocate and clear the structure. */
-	if ((ret = __os_umalloc(dbp->dbenv, sizeof(*sp), &sp)) != 0)
+	if ((ret = __os_umalloc(dbenv, sizeof(*sp), &sp)) != 0)
 		goto err;
 	memset(sp, 0, sizeof(*sp));
 
@@ -80,7 +71,7 @@ __bam_stat(dbp, spp, flags)
 	pgno = PGNO_BASE_MD;
 	if ((ret = __db_lget(dbc, 0, pgno, DB_LOCK_READ, 0, &metalock)) != 0)
 		goto err;
-	if ((ret = mpf->get(mpf, &pgno, 0, (PAGE **)&meta)) != 0)
+	if ((ret = __memp_fget(mpf, &pgno, 0, &meta)) != 0)
 		goto err;
 
 	if (flags == DB_RECORDCOUNT || flags == DB_CACHED_COUNTS)
@@ -92,11 +83,11 @@ __bam_stat(dbp, spp, flags)
 	for (sp->bt_free = 0, pgno = meta->dbmeta.free; pgno != PGNO_INVALID;) {
 		++sp->bt_free;
 
-		if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
+		if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
 			goto err;
 
 		pgno = h->next_pgno;
-		if ((ret = mpf->put(mpf, h, 0)) != 0)
+		if ((ret = __memp_fput(mpf, h, 0)) != 0)
 			goto err;
 		h = NULL;
 	}
@@ -105,17 +96,19 @@ __bam_stat(dbp, spp, flags)
 	pgno = cp->root;
 	if ((ret = __db_lget(dbc, 0, pgno, DB_LOCK_READ, 0, &lock)) != 0)
 		goto err;
-	if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
+	if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
 		goto err;
 
 	/* Get the levels from the root page. */
 	sp->bt_levels = h->level;
 
 	/* Discard the root page. */
-	if ((ret = mpf->put(mpf, h, 0)) != 0)
-		goto err;
+	ret = __memp_fput(mpf, h, 0);
 	h = NULL;
-	__LPUT(dbc, lock);
+	if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
+		ret = t_ret;
+	if (ret != 0)
+		goto err;
 
 	/* Walk the tree. */
 	if ((ret = __bam_traverse(dbc,
@@ -129,16 +122,18 @@ __bam_stat(dbp, spp, flags)
 	write_meta = !F_ISSET(dbp, DB_AM_RDONLY);
 meta_only:
 	if (t->bt_meta != PGNO_BASE_MD || write_meta != 0) {
-		if ((ret = mpf->put(mpf, meta, 0)) != 0)
-			goto err;
+		ret = __memp_fput(mpf, meta, 0);
 		meta = NULL;
-		__LPUT(dbc, metalock);
+		if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0)
+			ret = t_ret;
+		if (ret != 0)
+			goto err;
 
 		if ((ret = __db_lget(dbc,
 		    0, t->bt_meta, write_meta == 0 ?
 		    DB_LOCK_READ : DB_LOCK_WRITE, 0, &metalock)) != 0)
 			goto err;
-		if ((ret = mpf->get(mpf, &t->bt_meta, 0, (PAGE **)&meta)) != 0)
+		if ((ret = __memp_fget(mpf, &t->bt_meta, 0, &meta)) != 0)
 			goto err;
 	}
 	if (flags == DB_FAST_STAT) {
@@ -147,14 +142,15 @@ meta_only:
 			if ((ret = __db_lget(dbc, 0,
 			    cp->root, DB_LOCK_READ, 0, &lock)) != 0)
 				goto err;
-			if ((ret =
-			    mpf->get(mpf, &cp->root, 0, (PAGE **)&h)) != 0)
+			if ((ret = __memp_fget(mpf, &cp->root, 0, &h)) != 0)
 				goto err;
 
 			sp->bt_nkeys = RE_NREC(h);
 		} else
 			sp->bt_nkeys = meta->dbmeta.key_count;
-		sp->bt_ndata = meta->dbmeta.record_count;
+
+		sp->bt_ndata = dbp->type == DB_RECNO ?
+		   sp->bt_nkeys : meta->dbmeta.record_count;
 	}
 
 	/* Get metadata page statistics. */
@@ -175,21 +171,20 @@ meta_only:
 	*(DB_BTREE_STAT **)spp = sp;
 
 err:	/* Discard the second page. */
-	__LPUT(dbc, lock);
-	if (h != NULL && (t_ret = mpf->put(mpf, h, 0)) != 0 && ret == 0)
+	if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
+		ret = t_ret;
+	if (h != NULL && (t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
 		ret = t_ret;
 
 	/* Discard the metadata page. */
-	__LPUT(dbc, metalock);
-	if (meta != NULL && (t_ret = mpf->put(
-	    mpf, meta, write_meta == 0 ? 0 : DB_MPOOL_DIRTY)) != 0 && ret == 0)
+	if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0)
 		ret = t_ret;
-
-	if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
+	if (meta != NULL && (t_ret = __memp_fput(
+	    mpf, meta, write_meta == 0 ? 0 : DB_MPOOL_DIRTY)) != 0 && ret == 0)
 		ret = t_ret;
 
 	if (ret != 0 && sp != NULL) {
-		__os_ufree(dbp->dbenv, sp);
+		__os_ufree(dbenv, sp);
 		*(DB_BTREE_STAT **)spp = NULL;
 	}
 
@@ -197,104 +192,113 @@ err:	/* Discard the second page. */
 }
 
 /*
- * __bam_traverse --
- *	Walk a Btree database.
+ * __bam_stat_print --
+ *	Display btree/recno statistics.
  *
- * PUBLIC: int __bam_traverse __P((DBC *, db_lockmode_t,
- * PUBLIC:     db_pgno_t, int (*)(DB *, PAGE *, void *, int *), void *));
+ * PUBLIC: int __bam_stat_print __P((DBC *, u_int32_t));
  */
 int
-__bam_traverse(dbc, mode, root_pgno, callback, cookie)
+__bam_stat_print(dbc, flags)
 	DBC *dbc;
-	db_lockmode_t mode;
-	db_pgno_t root_pgno;
-	int (*callback)__P((DB *, PAGE *, void *, int *));
-	void *cookie;
+	u_int32_t flags;
 {
-	BINTERNAL *bi;
-	BKEYDATA *bk;
+	static const FN fn[] = {
+		{ BTM_DUP,	"duplicates" },
+		{ BTM_RECNO,	"recno" },
+		{ BTM_RECNUM,	"record-numbers" },
+		{ BTM_FIXEDLEN,	"fixed-length" },
+		{ BTM_RENUMBER,	"renumber" },
+		{ BTM_SUBDB,	"multiple-databases" },
+		{ BTM_DUPSORT,	"sorted duplicates" },
+		{ 0,		NULL }
+	};
 	DB *dbp;
-	DB_LOCK lock;
-	DB_MPOOLFILE *mpf;
-	PAGE *h;
-	RINTERNAL *ri;
-	db_indx_t indx;
-	int already_put, ret, t_ret;
+	DB_BTREE_STAT *sp;
+	DB_ENV *dbenv;
+	int lorder, ret;
+	const char *s;
 
 	dbp = dbc->dbp;
-	mpf = dbp->mpf;
-	already_put = 0;
+	dbenv = dbp->dbenv;
 
-	if ((ret = __db_lget(dbc, 0, root_pgno, mode, 0, &lock)) != 0)
-		return (ret);
-	if ((ret = mpf->get(mpf, &root_pgno, 0, &h)) != 0) {
-		__LPUT(dbc, lock);
+	if ((ret = __bam_stat(dbc, &sp, 0)) != 0)
 		return (ret);
+
+	if (LF_ISSET(DB_STAT_ALL)) {
+		__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+		__db_msg(dbenv, "Default Btree/Recno database information:");
 	}
 
-	switch (TYPE(h)) {
-	case P_IBTREE:
-		for (indx = 0; indx < NUM_ENT(h); indx += O_INDX) {
-			bi = GET_BINTERNAL(dbp, h, indx);
-			if (B_TYPE(bi->type) == B_OVERFLOW &&
-			    (ret = __db_traverse_big(dbp,
-			    ((BOVERFLOW *)bi->data)->pgno,
-			    callback, cookie)) != 0)
-				goto err;
-			if ((ret = __bam_traverse(
-			    dbc, mode, bi->pgno, callback, cookie)) != 0)
-				goto err;
-		}
-		break;
-	case P_IRECNO:
-		for (indx = 0; indx < NUM_ENT(h); indx += O_INDX) {
-			ri = GET_RINTERNAL(dbp, h, indx);
-			if ((ret = __bam_traverse(
-			    dbc, mode, ri->pgno, callback, cookie)) != 0)
-				goto err;
-		}
+	__db_msg(dbenv, "%lx\tBtree magic number", (u_long)sp->bt_magic);
+	__db_msg(dbenv, "%lu\tBtree version number", (u_long)sp->bt_version);
+
+	(void)__db_get_lorder(dbp, &lorder);
+	switch (lorder) {
+	case 1234:
+		s = "Little-endian";
 		break;
-	case P_LBTREE:
-		for (indx = 0; indx < NUM_ENT(h); indx += P_INDX) {
-			bk = GET_BKEYDATA(dbp, h, indx);
-			if (B_TYPE(bk->type) == B_OVERFLOW &&
-			    (ret = __db_traverse_big(dbp,
-			    GET_BOVERFLOW(dbp, h, indx)->pgno,
-			    callback, cookie)) != 0)
-				goto err;
-			bk = GET_BKEYDATA(dbp, h, indx + O_INDX);
-			if (B_TYPE(bk->type) == B_DUPLICATE &&
-			    (ret = __bam_traverse(dbc, mode,
-			    GET_BOVERFLOW(dbp, h, indx + O_INDX)->pgno,
-			    callback, cookie)) != 0)
-				goto err;
-			if (B_TYPE(bk->type) == B_OVERFLOW &&
-			    (ret = __db_traverse_big(dbp,
-			    GET_BOVERFLOW(dbp, h, indx + O_INDX)->pgno,
-			    callback, cookie)) != 0)
-				goto err;
-		}
+	case 4321:
+		s = "Big-endian";
 		break;
-	case P_LDUP:
-	case P_LRECNO:
-		for (indx = 0; indx < NUM_ENT(h); indx += O_INDX) {
-			bk = GET_BKEYDATA(dbp, h, indx);
-			if (B_TYPE(bk->type) == B_OVERFLOW &&
-			    (ret = __db_traverse_big(dbp,
-			    GET_BOVERFLOW(dbp, h, indx)->pgno,
-			    callback, cookie)) != 0)
-				goto err;
-		}
+	default:
+		s = "Unrecognized byte order";
 		break;
 	}
+	__db_msg(dbenv, "%s\tByte order", s);
+	__db_prflags(dbenv, NULL, sp->bt_metaflags, fn, NULL, "\tFlags");
+	if (dbp->type == DB_BTREE) {
+#ifdef NOT_IMPLEMENTED
+		__db_dl(dbenv, "Maximum keys per-page", (u_long)sp->bt_maxkey);
+#endif
+		__db_dl(dbenv, "Minimum keys per-page", (u_long)sp->bt_minkey);
+	}
+	if (dbp->type == DB_RECNO) {
+		__db_dl(dbenv,
+		    "Fixed-length record size", (u_long)sp->bt_re_len);
+		__db_dl(dbenv,
+		    "%#x\tFixed-length record pad", (u_int)sp->bt_re_pad);
+	}
+	__db_dl(dbenv,
+	    "Underlying database page size", (u_long)sp->bt_pagesize);
+	__db_dl(dbenv, "Number of levels in the tree", (u_long)sp->bt_levels);
+	__db_dl(dbenv, dbp->type == DB_BTREE ?
+	    "Number of unique keys in the tree" :
+	    "Number of records in the tree", (u_long)sp->bt_nkeys);
+	__db_dl(dbenv,
+	    "Number of data items in the tree", (u_long)sp->bt_ndata);
+
+	__db_dl(dbenv,
+	    "Number of tree internal pages", (u_long)sp->bt_int_pg);
+	__db_dl_pct(dbenv,
+	    "Number of bytes free in tree internal pages",
+	    (u_long)sp->bt_int_pgfree,
+	    DB_PCT_PG(sp->bt_int_pgfree, sp->bt_int_pg, sp->bt_pagesize), "ff");
+
+	__db_dl(dbenv,
+	    "Number of tree leaf pages", (u_long)sp->bt_leaf_pg);
+	__db_dl_pct(dbenv, "Number of bytes free in tree leaf pages",
+	    (u_long)sp->bt_leaf_pgfree, DB_PCT_PG(
+	    sp->bt_leaf_pgfree, sp->bt_leaf_pg, sp->bt_pagesize), "ff");
+
+	__db_dl(dbenv,
+	    "Number of tree duplicate pages", (u_long)sp->bt_dup_pg);
+	__db_dl_pct(dbenv,
+	    "Number of bytes free in tree duplicate pages",
+	    (u_long)sp->bt_dup_pgfree,
+	    DB_PCT_PG(sp->bt_dup_pgfree, sp->bt_dup_pg, sp->bt_pagesize), "ff");
+
+	__db_dl(dbenv,
+	    "Number of tree overflow pages", (u_long)sp->bt_over_pg);
+	__db_dl_pct(dbenv, "Number of bytes free in tree overflow pages",
+	    (u_long)sp->bt_over_pgfree, DB_PCT_PG(
+	    sp->bt_over_pgfree, sp->bt_over_pg, sp->bt_pagesize), "ff");
+	__db_dl(dbenv, "Number of empty pages", (u_long)sp->bt_empty_pg);
+
+	__db_dl(dbenv, "Number of pages on the free list", (u_long)sp->bt_free);
+
+	__os_ufree(dbenv, sp);
 
-	ret = callback(dbp, h, cookie, &already_put);
-
-err:	if (!already_put && (t_ret = mpf->put(mpf, h, 0)) != 0 && ret != 0)
-		ret = t_ret;
-	__LPUT(dbc, lock);
-
-	return (ret);
+	return (0);
 }
 
 /*
@@ -326,14 +330,23 @@ __bam_stat_callback(dbp, h, cookie, putp)
 		sp->bt_int_pgfree += P_FREESPACE(dbp, h);
 		break;
 	case P_LBTREE:
+		if (top == 0)
+			++sp->bt_empty_pg;
+
 		/* Correct for on-page duplicates and deleted items. */
 		for (indx = 0; indx < top; indx += P_INDX) {
+			type = GET_BKEYDATA(dbp, h, indx + O_INDX)->type;
+			/* Ignore deleted items. */
+			if (B_DISSET(type))
+				continue;
+
+			/* Ignore duplicate keys. */
 			if (indx + P_INDX >= top ||
 			    inp[indx] != inp[indx + P_INDX])
 				++sp->bt_nkeys;
 
-			type = GET_BKEYDATA(dbp, h, indx + O_INDX)->type;
-			if (!B_DISSET(type) && B_TYPE(type) != B_DUPLICATE)
+			/* Ignore off-page duplicates. */
+			if (B_TYPE(type) != B_DUPLICATE)
 				++sp->bt_ndata;
 		}
 
@@ -341,24 +354,28 @@ __bam_stat_callback(dbp, h, cookie, putp)
 		sp->bt_leaf_pgfree += P_FREESPACE(dbp, h);
 		break;
 	case P_LRECNO:
+		if (top == 0)
+			++sp->bt_empty_pg;
+
 		/*
 		 * If walking a recno tree, then each of these items is a key.
 		 * Otherwise, we're walking an off-page duplicate set.
 		 */
 		if (dbp->type == DB_RECNO) {
-			sp->bt_nkeys += top;
-
 			/*
-			 * Correct for deleted items in non-renumbering
-			 * Recno databases.
+			 * Correct for deleted items in non-renumbering Recno
+			 * databases.
 			 */
-			if (F_ISSET(dbp, DB_AM_RENUMBER))
+			if (F_ISSET(dbp, DB_AM_RENUMBER)) {
+				sp->bt_nkeys += top;
 				sp->bt_ndata += top;
-			else
+			} else
 				for (indx = 0; indx < top; indx += O_INDX) {
 					type = GET_BKEYDATA(dbp, h, indx)->type;
-					if (!B_DISSET(type))
+					if (!B_DISSET(type)) {
 						++sp->bt_ndata;
+						++sp->bt_nkeys;
+					}
 				}
 
 			++sp->bt_leaf_pg;
@@ -371,6 +388,9 @@ __bam_stat_callback(dbp, h, cookie, putp)
 		}
 		break;
 	case P_LDUP:
+		if (top == 0)
+			++sp->bt_empty_pg;
+
 		/* Correct for deleted items. */
 		for (indx = 0; indx < top; indx += O_INDX)
 			if (!B_DISSET(GET_BKEYDATA(dbp, h, indx)->type))
@@ -389,47 +409,84 @@ __bam_stat_callback(dbp, h, cookie, putp)
 	return (0);
 }
 
+/*
+ * __bam_print_cursor --
+ *	Display the current internal cursor.
+ *
+ * PUBLIC: void __bam_print_cursor __P((DBC *));
+ */
+void
+__bam_print_cursor(dbc)
+	DBC *dbc;
+{
+	static const FN fn[] = {
+		{ C_DELETED,	"C_DELETED" },
+		{ C_RECNUM,	"C_RECNUM" },
+		{ C_RENUMBER,	"C_RENUMBER" },
+		{ 0,		NULL }
+	};
+	DB_ENV *dbenv;
+	BTREE_CURSOR *cp;
+
+	dbenv = dbc->dbp->dbenv;
+	cp = (BTREE_CURSOR *)dbc->internal;
+
+	STAT_ULONG("Overflow size", cp->ovflsize);
+	if (dbc->dbtype == DB_RECNO)
+		STAT_ULONG("Recno", cp->recno);
+	STAT_ULONG("Order", cp->order);
+	__db_prflags(dbenv, NULL, cp->flags, fn, NULL, "\tInternal Flags");
+}
+
+#else /* !HAVE_STATISTICS */
+
+int
+__bam_stat(dbc, spp, flags)
+	DBC *dbc;
+	void *spp;
+	u_int32_t flags;
+{
+	COMPQUIET(spp, NULL);
+	COMPQUIET(flags, 0);
+
+	return (__db_stat_not_built(dbc->dbp->dbenv));
+}
+
+int
+__bam_stat_print(dbc, flags)
+	DBC *dbc;
+	u_int32_t flags;
+{
+	COMPQUIET(flags, 0);
+
+	return (__db_stat_not_built(dbc->dbp->dbenv));
+}
+#endif
+
 /*
  * __bam_key_range --
  *	Return proportion of keys relative to given key.  The numbers are
  *	slightly skewed due to on page duplicates.
  *
- * PUBLIC: int __bam_key_range __P((DB *,
- * PUBLIC:     DB_TXN *, DBT *, DB_KEY_RANGE *, u_int32_t));
+ * PUBLIC: int __bam_key_range __P((DBC *, DBT *, DB_KEY_RANGE *, u_int32_t));
  */
 int
-__bam_key_range(dbp, txn, dbt, kp, flags)
-	DB *dbp;
-	DB_TXN *txn;
+__bam_key_range(dbc, dbt, kp, flags)
+	DBC *dbc;
 	DBT *dbt;
 	DB_KEY_RANGE *kp;
 	u_int32_t flags;
 {
 	BTREE_CURSOR *cp;
-	DBC *dbc;
 	EPG *sp;
 	double factor;
-	int exact, ret, t_ret;
-
-	PANIC_CHECK(dbp->dbenv);
-	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->key_range");
+	int exact, ret;
 
-	if (flags != 0)
-		return (__db_ferr(dbp->dbenv, "DB->key_range", 0));
-
-	/* Check for consistent transaction usage. */
-	if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 1)) != 0)
-		return (ret);
-
-	/* Acquire a cursor. */
-	if ((ret = dbp->cursor(dbp, txn, &dbc, 0)) != 0)
-		return (ret);
-
-	DEBUG_LWRITE(dbc, NULL, "bam_key_range", NULL, NULL, 0);
+	COMPQUIET(flags, 0);
 
 	if ((ret = __bam_search(dbc, PGNO_INVALID,
 	    dbt, S_STK_ONLY, 1, NULL, &exact)) != 0)
-		goto err;
+		return (ret);
 
 	cp = (BTREE_CURSOR *)dbc->internal;
 	kp->less = kp->greater = 0.0;
@@ -454,7 +511,7 @@ __bam_key_range(dbp, txn, dbt, kp, flags)
 		else {
 			kp->less += factor * sp->indx / sp->entries;
 			kp->greater += factor *
-			    (sp->entries - sp->indx - 1) / sp->entries;
+			    ((sp->entries - sp->indx) - 1) / sp->entries;
 		}
 		factor *= 1.0/sp->entries;
 	}
@@ -474,7 +531,112 @@ __bam_key_range(dbp, txn, dbt, kp, flags)
 
 	BT_STK_CLR(cp);
 
-err:	if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
+	return (0);
+}
+
+/*
+ * __bam_traverse --
+ *	Walk a Btree database.
+ *
+ * PUBLIC: int __bam_traverse __P((DBC *, db_lockmode_t,
+ * PUBLIC:     db_pgno_t, int (*)(DB *, PAGE *, void *, int *), void *));
+ */
+int
+__bam_traverse(dbc, mode, root_pgno, callback, cookie)
+	DBC *dbc;
+	db_lockmode_t mode;
+	db_pgno_t root_pgno;
+	int (*callback)__P((DB *, PAGE *, void *, int *));
+	void *cookie;
+{
+	BINTERNAL *bi;
+	BKEYDATA *bk;
+	DB *dbp;
+	DB_LOCK lock;
+	DB_MPOOLFILE *mpf;
+	PAGE *h;
+	RINTERNAL *ri;
+	db_indx_t indx, *inp;
+	int already_put, ret, t_ret;
+
+	dbp = dbc->dbp;
+	mpf = dbp->mpf;
+	already_put = 0;
+
+	if ((ret = __db_lget(dbc, 0, root_pgno, mode, 0, &lock)) != 0)
+		return (ret);
+	if ((ret = __memp_fget(mpf, &root_pgno, 0, &h)) != 0) {
+		(void)__TLPUT(dbc, lock);
+		return (ret);
+	}
+
+	switch (TYPE(h)) {
+	case P_IBTREE:
+		for (indx = 0; indx < NUM_ENT(h); indx += O_INDX) {
+			bi = GET_BINTERNAL(dbp, h, indx);
+			if (B_TYPE(bi->type) == B_OVERFLOW &&
+			    (ret = __db_traverse_big(dbp,
+			    ((BOVERFLOW *)bi->data)->pgno,
+			    callback, cookie)) != 0)
+				goto err;
+			if ((ret = __bam_traverse(
+			    dbc, mode, bi->pgno, callback, cookie)) != 0)
+				goto err;
+		}
+		break;
+	case P_IRECNO:
+		for (indx = 0; indx < NUM_ENT(h); indx += O_INDX) {
+			ri = GET_RINTERNAL(dbp, h, indx);
+			if ((ret = __bam_traverse(
+			    dbc, mode, ri->pgno, callback, cookie)) != 0)
+				goto err;
+		}
+		break;
+	case P_LBTREE:
+		inp = P_INP(dbp, h);
+		for (indx = 0; indx < NUM_ENT(h); indx += P_INDX) {
+			bk = GET_BKEYDATA(dbp, h, indx);
+			if (B_TYPE(bk->type) == B_OVERFLOW &&
+			    (indx + P_INDX >= NUM_ENT(h) ||
+			    inp[indx] != inp[indx + P_INDX])) {
+				if ((ret = __db_traverse_big(dbp,
+				    GET_BOVERFLOW(dbp, h, indx)->pgno,
+				    callback, cookie)) != 0)
+					goto err;
+			}
+			bk = GET_BKEYDATA(dbp, h, indx + O_INDX);
+			if (B_TYPE(bk->type) == B_DUPLICATE &&
+			    (ret = __bam_traverse(dbc, mode,
+			    GET_BOVERFLOW(dbp, h, indx + O_INDX)->pgno,
+			    callback, cookie)) != 0)
+				goto err;
+			if (B_TYPE(bk->type) == B_OVERFLOW &&
+			    (ret = __db_traverse_big(dbp,
+			    GET_BOVERFLOW(dbp, h, indx + O_INDX)->pgno,
+			    callback, cookie)) != 0)
+				goto err;
+		}
+		break;
+	case P_LDUP:
+	case P_LRECNO:
+		for (indx = 0; indx < NUM_ENT(h); indx += O_INDX) {
+			bk = GET_BKEYDATA(dbp, h, indx);
+			if (B_TYPE(bk->type) == B_OVERFLOW &&
+			    (ret = __db_traverse_big(dbp,
+			    GET_BOVERFLOW(dbp, h, indx)->pgno,
+			    callback, cookie)) != 0)
+				goto err;
+		}
+		break;
+	default:
+		return (__db_pgfmt(dbp->dbenv, h->pgno));
+	}
+
+	ret = callback(dbp, h, cookie, &already_put);
+
+err:	if (!already_put && (t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
+		ret = t_ret;
+	if ((t_ret = __TLPUT(dbc, lock)) != 0 && ret == 0)
 		ret = t_ret;
 
 	return (ret);
diff --git a/storage/bdb/btree/bt_upgrade.c b/storage/bdb/btree/bt_upgrade.c
index 9f92648d739ef6913fb90ba7adc38c19e578fdf9..f899017897c95717b543515aebf24d34594e83a1 100644
--- a/storage/bdb/btree/bt_upgrade.c
+++ b/storage/bdb/btree/bt_upgrade.c
@@ -1,26 +1,23 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: bt_upgrade.c,v 11.30 2004/01/28 03:35:49 bostic Exp $
  */
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: bt_upgrade.c,v 11.25 2002/08/06 06:11:13 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
-#include <limits.h>
 #include <string.h>
 #endif
 
 #include "db_int.h"
 #include "dbinc/db_page.h"
-#include "dbinc/db_am.h"
 #include "dbinc/db_upgrade.h"
+#include "dbinc/btree.h"
 
 /*
  * __bam_30_btreemeta --
diff --git a/storage/bdb/btree/bt_verify.c b/storage/bdb/btree/bt_verify.c
index 0cf8a47e47657d14d943e288ffcd713c78b5cc37..6b78cbd17eaff9637b45b3c08e32cf5d93695a5a 100644
--- a/storage/bdb/btree/bt_verify.c
+++ b/storage/bdb/btree/bt_verify.c
@@ -1,18 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: bt_verify.c,v 1.76 2002/07/03 19:03:51 bostic Exp $
+ * $Id: bt_verify.c,v 1.97 2004/10/11 18:47:46 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: bt_verify.c,v 1.76 2002/07/03 19:03:51 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -21,8 +17,10 @@ static const char revid[] = "$Id: bt_verify.c,v 1.76 2002/07/03 19:03:51 bostic
 
 #include "db_int.h"
 #include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
 #include "dbinc/db_verify.h"
 #include "dbinc/btree.h"
+#include "dbinc/mp.h"
 
 static int __bam_safe_getdata __P((DB *, PAGE *, u_int32_t, int, DBT *, int *));
 static int __bam_vrfy_inp __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t,
@@ -32,8 +30,6 @@ static int __bam_vrfy_treeorder __P((DB *, db_pgno_t, PAGE *, BINTERNAL *,
 static int __ram_vrfy_inp __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t,
     db_indx_t *, u_int32_t));
 
-#define	OKFLAGS	(DB_AGGRESSIVE | DB_NOORDERCHK | DB_SALVAGE)
-
 /*
  * __bam_vrfy_meta --
  *	Verify the btree-specific part of a metadata page.
@@ -49,15 +45,17 @@ __bam_vrfy_meta(dbp, vdp, meta, pgno, flags)
 	db_pgno_t pgno;
 	u_int32_t flags;
 {
+	DB_ENV *dbenv;
 	VRFY_PAGEINFO *pip;
 	int isbad, t_ret, ret;
 	db_indx_t ovflsize;
 
+	dbenv = dbp->dbenv;
+	isbad = 0;
+
 	if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
 		return (ret);
 
-	isbad = 0;
-
 	/*
 	 * If VRFY_INCOMPLETE is not set, then we didn't come through
 	 * __db_vrfy_pagezero and didn't incompletely
@@ -85,13 +83,13 @@ __bam_vrfy_meta(dbp, vdp, meta, pgno, flags)
 	    ovflsize > B_MINKEY_TO_OVFLSIZE(dbp, DEFMINKEYPAGE, dbp->pgsize)) {
 		pip->bt_minkey = 0;
 		isbad = 1;
-		EPRINT((dbp->dbenv,
+		EPRINT((dbenv,
 	    "Page %lu: nonsensical bt_minkey value %lu on metadata page",
 		    (u_long)pgno, (u_long)meta->minkey));
 	} else
 		pip->bt_minkey = meta->minkey;
 
-	/* bt_maxkey: no constraints (XXX: right?) */
+	/* bt_maxkey: unsupported so no constraints. */
 	pip->bt_maxkey = meta->maxkey;
 
 	/* re_len: no constraints on this (may be zero or huge--we make rope) */
@@ -107,7 +105,7 @@ __bam_vrfy_meta(dbp, vdp, meta, pgno, flags)
 	    meta->root == pgno || !IS_VALID_PGNO(meta->root) ||
 	    (pgno == PGNO_BASE_MD && meta->root != 1)) {
 		isbad = 1;
-		EPRINT((dbp->dbenv,
+		EPRINT((dbenv,
 		    "Page %lu: nonsensical root page %lu on metadata page",
 		    (u_long)pgno, (u_long)meta->root));
 	} else
@@ -124,7 +122,7 @@ __bam_vrfy_meta(dbp, vdp, meta, pgno, flags)
 		 */
 		if (F_ISSET(&meta->dbmeta, BTM_DUP) && pgno == PGNO_BASE_MD) {
 			isbad = 1;
-			EPRINT((dbp->dbenv,
+			EPRINT((dbenv,
 "Page %lu: Btree metadata page has both duplicates and multiple databases",
 			    (u_long)pgno));
 		}
@@ -138,7 +136,7 @@ __bam_vrfy_meta(dbp, vdp, meta, pgno, flags)
 	if (F_ISSET(&meta->dbmeta, BTM_RECNUM))
 		F_SET(pip, VRFY_HAS_RECNUMS);
 	if (F_ISSET(pip, VRFY_HAS_RECNUMS) && F_ISSET(pip, VRFY_HAS_DUPS)) {
-		EPRINT((dbp->dbenv,
+		EPRINT((dbenv,
     "Page %lu: Btree metadata page illegally has both recnums and dups",
 		    (u_long)pgno));
 		isbad = 1;
@@ -149,13 +147,13 @@ __bam_vrfy_meta(dbp, vdp, meta, pgno, flags)
 		dbp->type = DB_RECNO;
 	} else if (F_ISSET(pip, VRFY_IS_RRECNO)) {
 		isbad = 1;
-		EPRINT((dbp->dbenv,
+		EPRINT((dbenv,
     "Page %lu: metadata page has renumber flag set but is not recno",
 		    (u_long)pgno));
 	}
 
 	if (F_ISSET(pip, VRFY_IS_RECNO) && F_ISSET(pip, VRFY_HAS_DUPS)) {
-		EPRINT((dbp->dbenv,
+		EPRINT((dbenv,
 		    "Page %lu: recno metadata page specifies duplicates",
 		    (u_long)pgno));
 		isbad = 1;
@@ -169,7 +167,7 @@ __bam_vrfy_meta(dbp, vdp, meta, pgno, flags)
 		 * database
 		 */
 		isbad = 1;
-		EPRINT((dbp->dbenv,
+		EPRINT((dbenv,
 		    "Page %lu: re_len of %lu in non-fixed-length database",
 		    (u_long)pgno, (u_long)pip->re_len));
 	}
@@ -179,8 +177,10 @@ __bam_vrfy_meta(dbp, vdp, meta, pgno, flags)
 	 * not be and may still be correct.
 	 */
 
-err:	if ((t_ret =
-	    __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
+err:	if ((t_ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0 && ret == 0)
+		ret = t_ret;
+	if (LF_ISSET(DB_SALVAGE) &&
+	   (t_ret = __db_salvage_markdone(vdp, pgno)) != 0 && ret == 0)
 		ret = t_ret;
 	return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
 }
@@ -201,22 +201,21 @@ __ram_vrfy_leaf(dbp, vdp, h, pgno, flags)
 	u_int32_t flags;
 {
 	BKEYDATA *bk;
+	DB_ENV *dbenv;
 	VRFY_PAGEINFO *pip;
 	db_indx_t i;
 	int ret, t_ret, isbad;
 	u_int32_t re_len_guess, len;
 
+	dbenv = dbp->dbenv;
 	isbad = 0;
+
 	if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
 		return (ret);
 
-	if ((ret = __db_fchk(dbp->dbenv,
-	    "__ram_vrfy_leaf", flags, OKFLAGS)) != 0)
-		goto err;
-
 	if (TYPE(h) != P_LRECNO) {
 		/* We should not have been called. */
-		TYPE_ERR_PRINT(dbp->dbenv, "__ram_vrfy_leaf", pgno, TYPE(h));
+		TYPE_ERR_PRINT(dbenv, "__ram_vrfy_leaf", pgno, TYPE(h));
 		DB_ASSERT(0);
 		ret = EINVAL;
 		goto err;
@@ -242,7 +241,7 @@ __ram_vrfy_leaf(dbp, vdp, h, pgno, flags)
 		goto err;
 
 	if (F_ISSET(pip, VRFY_HAS_DUPS)) {
-		EPRINT((dbp->dbenv,
+		EPRINT((dbenv,
 		    "Page %lu: Recno database has dups", (u_long)pgno));
 		ret = DB_VERIFY_BAD;
 		goto err;
@@ -266,7 +265,7 @@ __ram_vrfy_leaf(dbp, vdp, h, pgno, flags)
 			len = bk->len;
 		else {
 			isbad = 1;
-			EPRINT((dbp->dbenv,
+			EPRINT((dbenv,
 			    "Page %lu: nonsensical type for item %lu",
 			    (u_long)pgno, (u_long)i));
 			continue;
@@ -289,8 +288,7 @@ __ram_vrfy_leaf(dbp, vdp, h, pgno, flags)
 	/* Save off record count. */
 	pip->rec_cnt = NUM_ENT(h);
 
-err:	if ((t_ret =
-	    __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
+err:	if ((t_ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0 && ret == 0)
 		ret = t_ret;
 	return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
 }
@@ -310,10 +308,13 @@ __bam_vrfy(dbp, vdp, h, pgno, flags)
 	db_pgno_t pgno;
 	u_int32_t flags;
 {
+	DB_ENV *dbenv;
 	VRFY_PAGEINFO *pip;
 	int ret, t_ret, isbad;
 
+	dbenv = dbp->dbenv;
 	isbad = 0;
+
 	if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
 		return (ret);
 
@@ -324,7 +325,7 @@ __bam_vrfy(dbp, vdp, h, pgno, flags)
 	case P_LDUP:
 		break;
 	default:
-		TYPE_ERR_PRINT(dbp->dbenv, "__bam_vrfy", pgno, TYPE(h));
+		TYPE_ERR_PRINT(dbenv, "__bam_vrfy", pgno, TYPE(h));
 		DB_ASSERT(0);
 		ret = EINVAL;
 		goto err;
@@ -363,7 +364,7 @@ __bam_vrfy(dbp, vdp, h, pgno, flags)
 			isbad = 1;
 		else
 			goto err;
-		EPRINT((dbp->dbenv,
+		EPRINT((dbenv,
 		    "Page %lu: item order check unsafe: skipping",
 		    (u_long)pgno));
 	} else if (!LF_ISSET(DB_NOORDERCHK) && (ret =
@@ -379,8 +380,7 @@ __bam_vrfy(dbp, vdp, h, pgno, flags)
 			goto err;
 	}
 
-err:	if ((t_ret =
-	    __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
+err:	if ((t_ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0 && ret == 0)
 		ret = t_ret;
 	return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
 }
@@ -401,6 +401,7 @@ __ram_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
 	db_indx_t *nentriesp;
 	u_int32_t flags;
 {
+	DB_ENV *dbenv;
 	RINTERNAL *ri;
 	VRFY_CHILDINFO child;
 	VRFY_PAGEINFO *pip;
@@ -409,6 +410,7 @@ __ram_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
 	db_indx_t *inp;
 	u_int8_t *pagelayout, *p;
 
+	dbenv = dbp->dbenv;
 	isbad = 0;
 	memset(&child, 0, sizeof(VRFY_CHILDINFO));
 	nentries = 0;
@@ -418,21 +420,20 @@ __ram_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
 		return (ret);
 
 	if (TYPE(h) != P_IRECNO) {
-		TYPE_ERR_PRINT(dbp->dbenv, "__ram_vrfy_inp", pgno, TYPE(h));
+		TYPE_ERR_PRINT(dbenv, "__ram_vrfy_inp", pgno, TYPE(h));
 		DB_ASSERT(0);
 		ret = EINVAL;
 		goto err;
 	}
 
 	himark = dbp->pgsize;
-	if ((ret =
-	    __os_malloc(dbp->dbenv, dbp->pgsize, &pagelayout)) != 0)
+	if ((ret = __os_malloc(dbenv, dbp->pgsize, &pagelayout)) != 0)
 		goto err;
 	memset(pagelayout, 0, dbp->pgsize);
 	inp = P_INP(dbp, h);
 	for (i = 0; i < NUM_ENT(h); i++) {
 		if ((u_int8_t *)inp + i >= (u_int8_t *)h + himark) {
-			EPRINT((dbp->dbenv,
+			EPRINT((dbenv,
 			    "Page %lu: entries listing %lu overlaps data",
 			    (u_long)pgno, (u_long)i));
 			ret = DB_VERIFY_BAD;
@@ -448,7 +449,7 @@ __ram_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
 		    (u_int8_t *)h) ||
 		    offset > (u_int32_t)(dbp->pgsize - RINTERNAL_SIZE)) {
 			isbad = 1;
-			EPRINT((dbp->dbenv,
+			EPRINT((dbenv,
 			    "Page %lu: bad offset %lu at index %lu",
 			    (u_long)pgno, (u_long)offset, (u_long)i));
 			continue;
@@ -470,7 +471,7 @@ __ram_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
 			if ((ret = __db_vrfy_childput(vdp, pgno, &child)) != 0)
 				goto err;
 		} else {
-			EPRINT((dbp->dbenv,
+			EPRINT((dbenv,
 		"Page %lu: RINTERNAL structure at offset %lu referenced twice",
 			    (u_long)pgno, (u_long)offset));
 			isbad = 1;
@@ -481,14 +482,14 @@ __ram_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
 	    p < pagelayout + dbp->pgsize;
 	    p += RINTERNAL_SIZE)
 		if (*p != 1) {
-			EPRINT((dbp->dbenv,
+			EPRINT((dbenv,
 			    "Page %lu: gap between items at offset %lu",
 			    (u_long)pgno, (u_long)(p - pagelayout)));
 			isbad = 1;
 		}
 
 	if ((db_indx_t)himark != HOFFSET(h)) {
-		EPRINT((dbp->dbenv,
+		EPRINT((dbenv,
 		    "Page %lu: bad HOFFSET %lu, appears to be %lu",
 		    (u_long)pgno, (u_long)(HOFFSET(h)), (u_long)himark));
 		isbad = 1;
@@ -496,14 +497,15 @@ __ram_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
 
 	*nentriesp = nentries;
 
-err:	if ((t_ret =
-	    __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
+err:	if ((t_ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0 && ret == 0)
 		ret = t_ret;
 	if (pagelayout != NULL)
-		__os_free(dbp->dbenv, pagelayout);
+		__os_free(dbenv, pagelayout);
 	return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
 }
 
+typedef enum { VRFY_ITEM_NOTSET=0, VRFY_ITEM_BEGIN, VRFY_ITEM_END } VRFY_ITEM;
+
 /*
  * __bam_vrfy_inp --
  *	Verify that all entries in inp[] array are reasonable;
@@ -520,13 +522,18 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
 {
 	BKEYDATA *bk;
 	BOVERFLOW *bo;
+	DB_ENV *dbenv;
 	VRFY_CHILDINFO child;
+	VRFY_ITEM *pagelayout;
 	VRFY_PAGEINFO *pip;
-	int isbad, initem, isdupitem, ret, t_ret;
-	u_int32_t himark, offset; /* These would be db_indx_ts but for algnmt.*/
+	u_int32_t himark, offset;		/*
+						 * These would be db_indx_ts
+						 * but for alignment.
+						 */
 	u_int32_t i, endoff, nentries;
-	u_int8_t *pagelayout;
+	int isbad, initem, isdupitem, ret, t_ret;
 
+	dbenv = dbp->dbenv;
 	isbad = isdupitem = 0;
 	nentries = 0;
 	memset(&child, 0, sizeof(VRFY_CHILDINFO));
@@ -547,7 +554,7 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
 		 */
 		if (LF_ISSET(DB_SALVAGE))
 			break;
-		TYPE_ERR_PRINT(dbp->dbenv, "__bam_vrfy_inp", pgno, TYPE(h));
+		TYPE_ERR_PRINT(dbenv, "__bam_vrfy_inp", pgno, TYPE(h));
 		DB_ASSERT(0);
 		ret = EINVAL;
 		goto err;
@@ -565,9 +572,9 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
 	 * it and the region immediately after it.
 	 */
 	himark = dbp->pgsize;
-	if ((ret = __os_malloc(dbp->dbenv, dbp->pgsize, &pagelayout)) != 0)
+	if ((ret = __os_calloc(
+	    dbenv, dbp->pgsize, sizeof(pagelayout[0]), &pagelayout)) != 0)
 		goto err;
-	memset(pagelayout, 0, dbp->pgsize);
 	for (i = 0; i < NUM_ENT(h); i++) {
 		switch (ret = __db_vrfy_inpitem(dbp,
 		    h, pgno, i, 1, flags, &himark, &offset)) {
@@ -592,11 +599,9 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
 		 * items have no overlaps or gaps.
 		 */
 		bk = GET_BKEYDATA(dbp, h, i);
-#define	ITEM_BEGIN	1
-#define	ITEM_END	2
-		if (pagelayout[offset] == 0)
-			pagelayout[offset] = ITEM_BEGIN;
-		else if (pagelayout[offset] == ITEM_BEGIN) {
+		if (pagelayout[offset] == VRFY_ITEM_NOTSET)
+			pagelayout[offset] = VRFY_ITEM_BEGIN;
+		else if (pagelayout[offset] == VRFY_ITEM_BEGIN) {
 			/*
 			 * Having two inp entries that point at the same patch
 			 * of page is legal if and only if the page is
@@ -617,8 +622,7 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
 				isdupitem = 1;
 			} else {
 				isbad = 1;
-				EPRINT((dbp->dbenv,
-				    "Page %lu: duplicated item %lu",
+				EPRINT((dbenv, "Page %lu: duplicated item %lu",
 				    (u_long)pgno, (u_long)i));
 			}
 		}
@@ -630,7 +634,7 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
 		 * If the end already has a sign other than 0, do nothing--
 		 * it's an overlap that we'll catch later.
 		 */
-		switch(B_TYPE(bk->type)) {
+		switch (B_TYPE(bk->type)) {
 		case B_KEYDATA:
 			if (TYPE(h) == P_IBTREE)
 				/* It's a BINTERNAL. */
@@ -669,13 +673,12 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
 		 * If this is an onpage duplicate key we've seen before,
 		 * the end had better coincide too.
 		 */
-		if (isdupitem && pagelayout[endoff] != ITEM_END) {
-			EPRINT((dbp->dbenv,
-			    "Page %lu: duplicated item %lu",
+		if (isdupitem && pagelayout[endoff] != VRFY_ITEM_END) {
+			EPRINT((dbenv, "Page %lu: duplicated item %lu",
 			    (u_long)pgno, (u_long)i));
 			isbad = 1;
-		} else if (pagelayout[endoff] == 0)
-			pagelayout[endoff] = ITEM_END;
+		} else if (pagelayout[endoff] == VRFY_ITEM_NOTSET)
+			pagelayout[endoff] = VRFY_ITEM_END;
 		isdupitem = 0;
 
 		/*
@@ -684,8 +687,7 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
 		 */
 		if (B_DISSET(bk->type) && TYPE(h) != P_LRECNO) {
 			isbad = 1;
-			EPRINT((dbp->dbenv,
-			    "Page %lu: item %lu marked deleted",
+			EPRINT((dbenv, "Page %lu: item %lu marked deleted",
 			    (u_long)pgno, (u_long)i));
 		}
 
@@ -704,13 +706,13 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
 		case B_DUPLICATE:
 			if (TYPE(h) == P_IBTREE) {
 				isbad = 1;
-				EPRINT((dbp->dbenv,
+				EPRINT((dbenv,
     "Page %lu: duplicate page referenced by internal btree page at item %lu",
 				    (u_long)pgno, (u_long)i));
 				break;
 			} else if (TYPE(h) == P_LRECNO) {
 				isbad = 1;
-				EPRINT((dbp->dbenv,
+				EPRINT((dbenv,
 	"Page %lu: duplicate page referenced by recno page at item %lu",
 				    (u_long)pgno, (u_long)i));
 				break;
@@ -725,7 +727,7 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
 				/* Make sure tlen is reasonable. */
 				if (bo->tlen > dbp->pgsize * vdp->last_pgno) {
 					isbad = 1;
-					EPRINT((dbp->dbenv,
+					EPRINT((dbenv,
 				"Page %lu: impossible tlen %lu, item %lu",
 					    (u_long)pgno,
 					    (u_long)bo->tlen, (u_long)i));
@@ -736,7 +738,7 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
 			if (!IS_VALID_PGNO(bo->pgno) || bo->pgno == pgno ||
 			    bo->pgno == PGNO_INVALID) {
 				isbad = 1;
-				EPRINT((dbp->dbenv,
+				EPRINT((dbenv,
 			    "Page %lu: offpage item %lu has bad pgno %lu",
 				    (u_long)pgno, (u_long)i, (u_long)bo->pgno));
 				/* Don't save as a child. */
@@ -752,9 +754,8 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
 			break;
 		default:
 			isbad = 1;
-			EPRINT((dbp->dbenv,
-			    "Page %lu: item %lu of invalid type %lu",
-			    (u_long)pgno, (u_long)i));
+			EPRINT((dbenv, "Page %lu: item %lu of invalid type %lu",
+			    (u_long)pgno, (u_long)i, (u_long)B_TYPE(bk->type)));
 			break;
 		}
 	}
@@ -767,75 +768,69 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
 	for (i = himark; i < dbp->pgsize; i++)
 		if (initem == 0)
 			switch (pagelayout[i]) {
-			case 0:
+			case VRFY_ITEM_NOTSET:
 				/* May be just for alignment. */
-				if (i != ALIGN(i, sizeof(u_int32_t)))
+				if (i != DB_ALIGN(i, sizeof(u_int32_t)))
 					continue;
 
 				isbad = 1;
-				EPRINT((dbp->dbenv,
+				EPRINT((dbenv,
 				    "Page %lu: gap between items at offset %lu",
 				    (u_long)pgno, (u_long)i));
 				/* Find the end of the gap */
-				for ( ; pagelayout[i + 1] == 0 &&
+				for (; pagelayout[i + 1] == VRFY_ITEM_NOTSET &&
 				    (size_t)(i + 1) < dbp->pgsize; i++)
 					;
 				break;
-			case ITEM_BEGIN:
+			case VRFY_ITEM_BEGIN:
 				/* We've found an item. Check its alignment. */
-				if (i != ALIGN(i, sizeof(u_int32_t))) {
+				if (i != DB_ALIGN(i, sizeof(u_int32_t))) {
 					isbad = 1;
-					EPRINT((dbp->dbenv,
+					EPRINT((dbenv,
 					    "Page %lu: offset %lu unaligned",
 					    (u_long)pgno, (u_long)i));
 				}
 				initem = 1;
 				nentries++;
 				break;
-			case ITEM_END:
+			case VRFY_ITEM_END:
 				/*
 				 * We've hit the end of an item even though
 				 * we don't think we're in one;  must
 				 * be an overlap.
 				 */
 				isbad = 1;
-				EPRINT((dbp->dbenv,
+				EPRINT((dbenv,
 				    "Page %lu: overlapping items at offset %lu",
 				    (u_long)pgno, (u_long)i));
 				break;
-			default:
-				/* Should be impossible. */
-				DB_ASSERT(0);
-				ret = EINVAL;
-				goto err;
 			}
 		else
 			switch (pagelayout[i]) {
-			case 0:
+			case VRFY_ITEM_NOTSET:
 				/* In the middle of an item somewhere. Okay. */
 				break;
-			case ITEM_END:
+			case VRFY_ITEM_END:
 				/* End of an item; switch to out-of-item mode.*/
 				initem = 0;
 				break;
-			case ITEM_BEGIN:
+			case VRFY_ITEM_BEGIN:
 				/*
 				 * Hit a second item beginning without an
 				 * end.  Overlap.
 				 */
 				isbad = 1;
-				EPRINT((dbp->dbenv,
+				EPRINT((dbenv,
 				    "Page %lu: overlapping items at offset %lu",
 				    (u_long)pgno, (u_long)i));
 				break;
 			}
 
-	(void)__os_free(dbp->dbenv, pagelayout);
+	__os_free(dbenv, pagelayout);
 
 	/* Verify HOFFSET. */
 	if ((db_indx_t)himark != HOFFSET(h)) {
-		EPRINT((dbp->dbenv,
-		    "Page %lu: bad HOFFSET %lu, appears to be %lu",
+		EPRINT((dbenv, "Page %lu: bad HOFFSET %lu, appears to be %lu",
 		    (u_long)pgno, (u_long)HOFFSET(h), (u_long)himark));
 		isbad = 1;
 	}
@@ -843,8 +838,7 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
 err:	if (nentriesp != NULL)
 		*nentriesp = nentries;
 
-	if ((t_ret =
-	    __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
+	if ((t_ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0 && ret == 0)
 		ret = t_ret;
 
 	return ((isbad == 1 && ret == 0) ? DB_VERIFY_BAD : ret);
@@ -876,11 +870,12 @@ __bam_vrfy_itemorder(dbp, vdp, h, pgno, nentries, ovflok, hasdups, flags)
 	int ovflok, hasdups;
 	u_int32_t flags;
 {
-	DBT dbta, dbtb, dup_1, dup_2, *p1, *p2, *tmp;
-	BTREE *bt;
 	BINTERNAL *bi;
 	BKEYDATA *bk;
 	BOVERFLOW *bo;
+	BTREE *bt;
+	DBT dbta, dbtb, dup_1, dup_2, *p1, *p2, *tmp;
+	DB_ENV *dbenv;
 	VRFY_PAGEINFO *pip;
 	db_indx_t i;
 	int cmp, freedup_1, freedup_2, isbad, ret, t_ret;
@@ -900,6 +895,7 @@ __bam_vrfy_itemorder(dbp, vdp, h, pgno, nentries, ovflok, hasdups, flags)
 	} else
 		pip = NULL;
 
+	dbenv = dbp->dbenv;
 	ret = isbad = 0;
 	bo = NULL;			/* Shut up compiler. */
 
@@ -982,7 +978,7 @@ __bam_vrfy_itemorder(dbp, vdp, h, pgno, nentries, ovflok, hasdups, flags)
 #if 0
 			if (i == 0 && bi->len != 0) {
 				isbad = 1;
-				EPRINT((dbp->dbenv,
+				EPRINT((dbenv,
 		"Page %lu: lowest key on internal page of nonzero length",
 				    (u_long)pgno));
 			}
@@ -1004,7 +1000,7 @@ __bam_vrfy_itemorder(dbp, vdp, h, pgno, nentries, ovflok, hasdups, flags)
 			 * This means our caller screwed up and sent us
 			 * an inappropriate page.
 			 */
-			TYPE_ERR_PRINT(dbp->dbenv,
+			TYPE_ERR_PRINT(dbenv,
 			    "__bam_vrfy_itemorder", pgno, TYPE(h))
 			DB_ASSERT(0);
 			ret = EINVAL;
@@ -1040,7 +1036,7 @@ overflow:		if (!ovflok) {
 			if ((ret = __db_goff(dbp,
 			    p2, bo->tlen, bo->pgno, NULL, NULL)) != 0) {
 				isbad = 1;
-				EPRINT((dbp->dbenv,
+				EPRINT((dbenv,
 			    "Page %lu: error %lu in fetching overflow item %lu",
 				    (u_long)pgno, (u_long)ret, (u_long)i));
 			}
@@ -1055,7 +1051,7 @@ overflow:		if (!ovflok) {
 			/* comparison succeeded */
 			if (cmp > 0) {
 				isbad = 1;
-				EPRINT((dbp->dbenv,
+				EPRINT((dbenv,
 				    "Page %lu: out-of-order key at entry %lu",
 				    (u_long)pgno, (u_long)i));
 				/* proceed */
@@ -1070,7 +1066,7 @@ overflow:		if (!ovflok) {
 					F_SET(pip, VRFY_HAS_DUPS);
 				else if (hasdups == 0) {
 					isbad = 1;
-					EPRINT((dbp->dbenv,
+					EPRINT((dbenv,
 	"Page %lu: database with no duplicates has duplicated keys",
 					    (u_long)pgno));
 				}
@@ -1133,24 +1129,22 @@ overflow:		if (!ovflok) {
 						F_SET(pip, VRFY_DUPS_UNSORTED);
 
 					if (freedup_1)
-						__os_ufree(dbp->dbenv,
-						    dup_1.data);
+						__os_ufree(dbenv, dup_1.data);
 					if (freedup_2)
-						__os_ufree(dbp->dbenv,
-						    dup_2.data);
+						__os_ufree(dbenv, dup_2.data);
 				}
 			}
 		}
 	}
 
 err:	if (pip != NULL && ((t_ret =
-	    __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0) && ret == 0)
+	    __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0) && ret == 0)
 		ret = t_ret;
 
 	if (buf1 != NULL)
-		__os_ufree(dbp->dbenv, buf1);
+		__os_ufree(dbenv, buf1);
 	if (buf2 != NULL)
-		__os_ufree(dbp->dbenv, buf2);
+		__os_ufree(dbenv, buf2);
 
 	return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
 }
@@ -1171,11 +1165,13 @@ __bam_vrfy_structure(dbp, vdp, meta_pgno, flags)
 	u_int32_t flags;
 {
 	DB *pgset;
+	DB_ENV *dbenv;
 	VRFY_PAGEINFO *mip, *rip;
 	db_pgno_t root, p;
 	int t_ret, ret;
 	u_int32_t nrecs, level, relen, stflags;
 
+	dbenv = dbp->dbenv;
 	mip = rip = 0;
 	pgset = vdp->pgset;
 
@@ -1185,7 +1181,7 @@ __bam_vrfy_structure(dbp, vdp, meta_pgno, flags)
 	if ((ret = __db_vrfy_pgset_get(pgset, meta_pgno, (int *)&p)) != 0)
 		goto err;
 	if (p != 0) {
-		EPRINT((dbp->dbenv,
+		EPRINT((dbenv,
 		    "Page %lu: btree metadata page observed twice",
 		    (u_long)meta_pgno));
 		ret = DB_VERIFY_BAD;
@@ -1197,7 +1193,7 @@ __bam_vrfy_structure(dbp, vdp, meta_pgno, flags)
 	root = mip->root;
 
 	if (root == 0) {
-		EPRINT((dbp->dbenv,
+		EPRINT((dbenv,
 		    "Page %lu: btree metadata page has no root",
 		    (u_long)meta_pgno));
 		ret = DB_VERIFY_BAD;
@@ -1235,7 +1231,7 @@ __bam_vrfy_structure(dbp, vdp, meta_pgno, flags)
 		 * that should never happen.
 		 */
 		if (mip->re_len > 0 && relen > 0 && mip->re_len != relen) {
-			EPRINT((dbp->dbenv,
+			EPRINT((dbenv,
 			    "Page %lu: recno database has bad re_len %lu",
 			    (u_long)meta_pgno, (u_long)relen));
 			ret = DB_VERIFY_BAD;
@@ -1244,13 +1240,13 @@ __bam_vrfy_structure(dbp, vdp, meta_pgno, flags)
 		ret = 0;
 		break;
 	case P_LDUP:
-		EPRINT((dbp->dbenv,
+		EPRINT((dbenv,
 		    "Page %lu: duplicate tree referenced from metadata page",
 		    (u_long)meta_pgno));
 		ret = DB_VERIFY_BAD;
 		break;
 	default:
-		EPRINT((dbp->dbenv,
+		EPRINT((dbenv,
 	    "Page %lu: btree root of incorrect type %lu on metadata page",
 		    (u_long)meta_pgno, (u_long)rip->type));
 		ret = DB_VERIFY_BAD;
@@ -1258,10 +1254,10 @@ __bam_vrfy_structure(dbp, vdp, meta_pgno, flags)
 	}
 
 err:	if (mip != NULL && ((t_ret =
-	    __db_vrfy_putpageinfo(dbp->dbenv, vdp, mip)) != 0) && ret == 0)
+	    __db_vrfy_putpageinfo(dbenv, vdp, mip)) != 0) && ret == 0)
 		ret = t_ret;
 	if (rip != NULL && ((t_ret =
-	    __db_vrfy_putpageinfo(dbp->dbenv, vdp, rip)) != 0) && ret == 0)
+	    __db_vrfy_putpageinfo(dbenv, vdp, rip)) != 0) && ret == 0)
 		ret = t_ret;
 	return (ret);
 }
@@ -1277,8 +1273,7 @@ err:	if (mip != NULL && ((t_ret =
  * PUBLIC:     void *, u_int32_t, u_int32_t *, u_int32_t *, u_int32_t *));
  */
 int
-__bam_vrfy_subtree(dbp,
-    vdp, pgno, l, r, flags, levelp, nrecsp, relenp)
+__bam_vrfy_subtree(dbp, vdp, pgno, l, r, flags, levelp, nrecsp, relenp)
 	DB *dbp;
 	VRFY_DBINFO *vdp;
 	db_pgno_t pgno;
@@ -1287,19 +1282,21 @@ __bam_vrfy_subtree(dbp,
 {
 	BINTERNAL *li, *ri, *lp, *rp;
 	DB *pgset;
-	DB_MPOOLFILE *mpf;
 	DBC *cc;
+	DB_ENV *dbenv;
+	DB_MPOOLFILE *mpf;
 	PAGE *h;
 	VRFY_CHILDINFO *child;
 	VRFY_PAGEINFO *pip;
 	db_indx_t i;
 	db_pgno_t next_pgno, prev_pgno;
 	db_recno_t child_nrecs, nrecs;
-	u_int32_t child_level, child_relen, level, relen, stflags;
+	u_int32_t child_level, child_relen, j, level, relen, stflags;
 	u_int8_t leaf_type;
 	int (*func) __P((DB *, const DBT *, const DBT *));
 	int isbad, p, ret, t_ret, toplevel;
 
+	dbenv = dbp->dbenv;
 	mpf = dbp->mpf;
 	ret = isbad = 0;
 	nrecs = 0;
@@ -1396,29 +1393,39 @@ __bam_vrfy_subtree(dbp,
 			 * page's next_pgno, and our prev_pgno.
 			 */
 			if (pip->type != vdp->leaf_type) {
-				EPRINT((dbp->dbenv,
+				isbad = 1;
+				EPRINT((dbenv,
 	"Page %lu: unexpected page type %lu found in leaf chain (expected %lu)",
 				    (u_long)pip->pgno, (u_long)pip->type,
 				    (u_long)vdp->leaf_type));
-				isbad = 1;
 			}
-			if (pip->pgno != vdp->next_pgno) {
-				EPRINT((dbp->dbenv,
+
+			/*
+			 * Don't do the prev/next_pgno checks if we've lost
+			 * leaf pages due to another corruption.
+			 */
+			if (!F_ISSET(vdp, VRFY_LEAFCHAIN_BROKEN)) {
+				if (pip->pgno != vdp->next_pgno) {
+					isbad = 1;
+					EPRINT((dbenv,
 	"Page %lu: incorrect next_pgno %lu found in leaf chain (should be %lu)",
-				    (u_long)vdp->prev_pgno,
-				    (u_long)vdp->next_pgno, (u_long)pip->pgno));
-				isbad = 1;
-			}
-			if (pip->prev_pgno != vdp->prev_pgno) {
-bad_prev:			EPRINT((dbp->dbenv,
-	"Page %lu: incorrect prev_pgno %lu found in leaf chain (should be %lu)",
-				    (u_long)pip->pgno, (u_long)pip->prev_pgno,
-				    (u_long)vdp->prev_pgno));
-				isbad = 1;
+					    (u_long)vdp->prev_pgno,
+					    (u_long)vdp->next_pgno,
+					    (u_long)pip->pgno));
+				}
+				if (pip->prev_pgno != vdp->prev_pgno) {
+bad_prev:				isbad = 1;
+					EPRINT((dbenv,
+    "Page %lu: incorrect prev_pgno %lu found in leaf chain (should be %lu)",
+					    (u_long)pip->pgno,
+					    (u_long)pip->prev_pgno,
+					    (u_long)vdp->prev_pgno));
+				}
 			}
 		}
 		vdp->prev_pgno = pip->pgno;
 		vdp->next_pgno = pip->next_pgno;
+		F_CLR(vdp, VRFY_LEAFCHAIN_BROKEN);
 
 		/*
 		 * Overflow pages are common to all three leaf types;
@@ -1447,7 +1454,7 @@ bad_prev:			EPRINT((dbp->dbenv,
 			if (!LF_ISSET(ST_IS_RECNO) &&
 			    !(LF_ISSET(ST_DUPOK) && !LF_ISSET(ST_DUPSORT))) {
 				isbad = 1;
-				EPRINT((dbp->dbenv,
+				EPRINT((dbenv,
 				    "Page %lu: recno leaf page non-recno tree",
 				    (u_long)pgno));
 				goto done;
@@ -1459,7 +1466,7 @@ bad_prev:			EPRINT((dbp->dbenv,
 			 * subtree.
 			 */
 			isbad = 1;
-			EPRINT((dbp->dbenv,
+			EPRINT((dbenv,
 			    "Page %lu: non-recno leaf page in recno tree",
 			    (u_long)pgno));
 			goto done;
@@ -1476,7 +1483,7 @@ bad_prev:			EPRINT((dbp->dbenv,
 			/* If dups aren't allowed in this btree, trouble. */
 			if (!LF_ISSET(ST_DUPOK)) {
 				isbad = 1;
-				EPRINT((dbp->dbenv,
+				EPRINT((dbenv,
 				    "Page %lu: duplicates in non-dup btree",
 				    (u_long)pgno));
 			} else {
@@ -1504,11 +1511,11 @@ bad_prev:			EPRINT((dbp->dbenv,
 						    dbp, vdp, child->pgno, NULL,
 						    NULL, stflags | ST_TOPLEVEL,
 						    NULL, NULL, NULL)) != 0) {
-							if (ret !=
+							if (ret ==
 							    DB_VERIFY_BAD)
-								goto err;
-							else
 								isbad = 1;
+							else
+								goto err;
 						}
 					}
 				}
@@ -1523,10 +1530,10 @@ bad_prev:			EPRINT((dbp->dbenv,
 				 */
 				if (F_ISSET(pip, VRFY_DUPS_UNSORTED) &&
 				    LF_ISSET(ST_DUPSORT)) {
-					EPRINT((dbp->dbenv,
+					isbad = 1;
+					EPRINT((dbenv,
 		    "Page %lu: unsorted duplicate set in sorted-dup database",
 					    (u_long)pgno));
-					isbad = 1;
 				}
 			}
 		}
@@ -1548,12 +1555,21 @@ bad_prev:			EPRINT((dbp->dbenv,
 		 * zeroed);  handle this case specially.
 		 */
 		if (F_ISSET(pip, VRFY_IS_ALLZEROES))
-			ZEROPG_ERR_PRINT(dbp->dbenv,
-			    pgno, "btree or recno page");
+			ZEROPG_ERR_PRINT(dbenv, pgno, "btree or recno page");
 		else
-			EPRINT((dbp->dbenv,
+			EPRINT((dbenv,
 	    "Page %lu: btree or recno page is of inappropriate type %lu",
 			    (u_long)pgno, (u_long)pip->type));
+
+		/*
+		 * We probably lost a leaf page (or more if this was an
+		 * internal page) from our prev/next_pgno chain.  Flag
+		 * that this is expected;  we don't want or need to
+		 * spew error messages about erroneous prev/next_pgnos,
+		 * since that's probably not the real problem.
+		 */
+		F_SET(vdp, VRFY_LEAFCHAIN_BROKEN);
+
 		ret = DB_VERIFY_BAD;
 		goto err;
 	}
@@ -1569,7 +1585,7 @@ bad_prev:			EPRINT((dbp->dbenv,
 	    ret = __db_vrfy_ccnext(cc, &child))
 		if (child->type == V_RECNO) {
 			if (pip->type != P_IRECNO) {
-				TYPE_ERR_PRINT(dbp->dbenv, "__bam_vrfy_subtree",
+				TYPE_ERR_PRINT(dbenv, "__bam_vrfy_subtree",
 				    pgno, pip->type);
 				DB_ASSERT(0);
 				ret = EINVAL;
@@ -1578,10 +1594,10 @@ bad_prev:			EPRINT((dbp->dbenv,
 			if ((ret = __bam_vrfy_subtree(dbp, vdp, child->pgno,
 			    NULL, NULL, flags, &child_level, &child_nrecs,
 			    &child_relen)) != 0) {
-				if (ret != DB_VERIFY_BAD)
-					goto done;
-				else
+				if (ret == DB_VERIFY_BAD)
 					isbad = 1;
+				else
+					goto done;
 			}
 
 			if (LF_ISSET(ST_RELEN)) {
@@ -1594,7 +1610,7 @@ bad_prev:			EPRINT((dbp->dbenv,
 				else if (child_relen > 0 &&
 				    relen != child_relen) {
 					isbad = 1;
-					EPRINT((dbp->dbenv,
+					EPRINT((dbenv,
 			   "Page %lu: recno page returned bad re_len %lu",
 					    (u_long)child->pgno,
 					    (u_long)child_relen));
@@ -1604,19 +1620,54 @@ bad_prev:			EPRINT((dbp->dbenv,
 			}
 			if (LF_ISSET(ST_RECNUM))
 				nrecs += child_nrecs;
-			if (level != child_level + 1) {
+			if (isbad == 0 && level != child_level + 1) {
 				isbad = 1;
-   EPRINT((dbp->dbenv, "Page %lu: recno level incorrect: got %lu, expected %lu",
+				EPRINT((dbenv,
+		"Page %lu: recno level incorrect: got %lu, expected %lu",
 				    (u_long)child->pgno, (u_long)child_level,
 				    (u_long)(level - 1)));
 			}
-		} else if (child->type == V_OVERFLOW &&
-		    (ret = __db_vrfy_ovfl_structure(dbp, vdp,
-		    child->pgno, child->tlen, flags)) != 0) {
-			if (ret == DB_VERIFY_BAD)
+		} else if (child->type == V_OVERFLOW) {
+			/*
+			 * It is possible for one internal page to reference
+			 * a single overflow page twice, if all the items
+			 * in the subtree referenced by slot 0 are deleted,
+			 * then a similar number of items are put back
+			 * before the key that formerly had been in slot 1.
+			 *
+			 * (Btree doesn't look at the key in slot 0, so the
+			 * fact that the key formerly at slot 1 is the "wrong"
+			 * parent of the stuff in the slot 0 subtree isn't
+			 * really incorrect.)
+			 *
+			 * __db_vrfy_ovfl_structure is designed to be
+			 * efficiently called multiple times for multiple
+			 * references;  call it here as many times as is
+			 * appropriate.
+			 */
+
+			/* Otherwise, __db_vrfy_childput would be broken. */
+			DB_ASSERT(child->refcnt >= 1);
+
+			/*
+			 * An overflow referenced more than twice here
+			 * shouldn't happen.
+			 */
+			if (child->refcnt > 2) {
 				isbad = 1;
-			else
-				goto done;
+				EPRINT((dbenv,
+    "Page %lu: overflow page %lu referenced more than twice from internal page",
+				    (u_long)pgno, (u_long)child->pgno));
+			} else
+				for (j = 0; j < child->refcnt; j++)
+					if ((ret = __db_vrfy_ovfl_structure(dbp,
+					    vdp, child->pgno, child->tlen,
+					    flags)) != 0) {
+						if (ret == DB_VERIFY_BAD)
+							isbad = 1;
+						else
+							goto done;
+					}
 		}
 
 	if ((ret = __db_vrfy_ccclose(cc)) != 0)
@@ -1637,12 +1688,12 @@ bad_prev:			EPRINT((dbp->dbenv,
 	 * itself, which must sort lower than all entries on its child;
 	 * ri will be the key to its right, which must sort greater.
 	 */
-	if (h == NULL && (ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
+	if (h == NULL && (ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
 		goto err;
 	for (i = 0; i < pip->entries; i += O_INDX) {
 		li = GET_BINTERNAL(dbp, h, i);
 		ri = (i + O_INDX < pip->entries) ?
-		    GET_BINTERNAL(dbp, h, i + O_INDX) : NULL;
+		    GET_BINTERNAL(dbp, h, i + O_INDX) : rp;
 
 		/*
 		 * The leftmost key is forcibly sorted less than all entries,
@@ -1651,10 +1702,10 @@ bad_prev:			EPRINT((dbp->dbenv,
 		if ((ret = __bam_vrfy_subtree(dbp, vdp, li->pgno,
 		    i == 0 ? NULL : li, ri, flags, &child_level,
 		    &child_nrecs, NULL)) != 0) {
-			if (ret != DB_VERIFY_BAD)
-				goto done;
-			else
+			if (ret == DB_VERIFY_BAD)
 				isbad = 1;
+			else
+				goto done;
 		}
 
 		if (LF_ISSET(ST_RECNUM)) {
@@ -1671,7 +1722,7 @@ bad_prev:			EPRINT((dbp->dbenv,
 			 */
 			if (li->nrecs != child_nrecs) {
 				isbad = 1;
-				EPRINT((dbp->dbenv,
+				EPRINT((dbenv,
 	"Page %lu: item %lu has incorrect record count of %lu, should be %lu",
 				    (u_long)pgno, (u_long)i, (u_long)li->nrecs,
 				    (u_long)child_nrecs));
@@ -1680,7 +1731,7 @@ bad_prev:			EPRINT((dbp->dbenv,
 
 		if (level != child_level + 1) {
 			isbad = 1;
-			EPRINT((dbp->dbenv,
+			EPRINT((dbenv,
 		"Page %lu: Btree level incorrect: got %lu, expected %lu",
 			    (u_long)li->pgno,
 			    (u_long)child_level, (u_long)(level - 1)));
@@ -1710,7 +1761,7 @@ done:	if (F_ISSET(pip, VRFY_INCOMPLETE) && isbad == 0 && ret == 0) {
 		 * isbad == 0, though, it's now safe to do so, as we've
 		 * traversed any child overflow pages.  Do it.
 		 */
-		if (h == NULL && (ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
+		if (h == NULL && (ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
 			goto err;
 		if ((ret = __bam_vrfy_itemorder(dbp,
 		    vdp, h, pgno, 0, 1, 0, flags)) != 0)
@@ -1729,14 +1780,14 @@ done:	if (F_ISSET(pip, VRFY_INCOMPLETE) && isbad == 0 && ret == 0) {
 	 * must have children).
 	 */
 	if (isbad == 0 && ret == 0) {
-		if (h == NULL && (ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
+		if (h == NULL && (ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
 			goto err;
 
 		if (NUM_ENT(h) == 0 && ISINTERNAL(h)) {
-			EPRINT((dbp->dbenv,
+			isbad = 1;
+			EPRINT((dbenv,
 		    "Page %lu: internal page is empty and should not be",
 			    (u_long)pgno));
-			isbad = 1;
 			goto err;
 		}
 	}
@@ -1747,7 +1798,7 @@ done:	if (F_ISSET(pip, VRFY_INCOMPLETE) && isbad == 0 && ret == 0) {
 	 * appropriate--we have a default sort function--verify this.
 	 */
 	if (isbad == 0 && ret == 0 && !LF_ISSET(DB_NOORDERCHK) && lp != NULL) {
-		if (h == NULL && (ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
+		if (h == NULL && (ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
 			goto err;
 
 		/*
@@ -1778,7 +1829,7 @@ done:	if (F_ISSET(pip, VRFY_INCOMPLETE) && isbad == 0 && ret == 0) {
 	 */
 	if (LF_ISSET(ST_RECNUM) && nrecs != pip->rec_cnt && toplevel) {
 		isbad = 1;
-		EPRINT((dbp->dbenv,
+		EPRINT((dbenv,
 		    "Page %lu: bad record count: has %lu records, claims %lu",
 		    (u_long)pgno, (u_long)nrecs, (u_long)pip->rec_cnt));
 	}
@@ -1793,7 +1844,7 @@ done:	if (F_ISSET(pip, VRFY_INCOMPLETE) && isbad == 0 && ret == 0) {
 		goto err;
 	if (p != 0) {
 		isbad = 1;
-		EPRINT((dbp->dbenv, "Page %lu: linked twice", (u_long)pgno));
+		EPRINT((dbenv, "Page %lu: linked twice", (u_long)pgno));
 	} else if ((ret = __db_vrfy_pgset_inc(pgset, pgno)) != 0)
 		goto err;
 
@@ -1803,9 +1854,9 @@ done:	if (F_ISSET(pip, VRFY_INCOMPLETE) && isbad == 0 && ret == 0) {
 		 * PGNO_INVALID.
 		 */
 		if (vdp->next_pgno != PGNO_INVALID) {
-			EPRINT((dbp->dbenv, "Page %lu: unterminated leaf chain",
-			    (u_long)vdp->prev_pgno));
 			isbad = 1;
+			EPRINT((dbenv, "Page %lu: unterminated leaf chain",
+			    (u_long)vdp->prev_pgno));
 		}
 
 err:	if (toplevel) {
@@ -1815,10 +1866,9 @@ err:	if (toplevel) {
 		vdp->leaf_type = leaf_type;
 	}
 
-	if (h != NULL && (t_ret = mpf->put(mpf, h, 0)) != 0 && ret == 0)
+	if (h != NULL && (t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
 		ret = t_ret;
-	if ((t_ret =
-	    __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
+	if ((t_ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0 && ret == 0)
 		ret = t_ret;
 	if (cc != NULL && ((t_ret = __db_vrfy_ccclose(cc)) != 0) && ret == 0)
 		ret = t_ret;
@@ -1848,10 +1898,12 @@ __bam_vrfy_treeorder(dbp, pgno, h, lp, rp, func, flags)
 	u_int32_t flags;
 {
 	BOVERFLOW *bo;
+	DB_ENV *dbenv;
 	DBT dbt;
 	db_indx_t last;
 	int ret, cmp;
 
+	dbenv = dbp->dbenv;
 	memset(&dbt, 0, sizeof(DBT));
 	F_SET(&dbt, DB_DBT_MALLOC);
 	ret = 0;
@@ -1873,8 +1925,7 @@ __bam_vrfy_treeorder(dbp, pgno, h, lp, rp, func, flags)
 		last = NUM_ENT(h) - P_INDX;
 		break;
 	default:
-		TYPE_ERR_PRINT(dbp->dbenv,
-		    "__bam_vrfy_treeorder", pgno, TYPE(h));
+		TYPE_ERR_PRINT(dbenv, "__bam_vrfy_treeorder", pgno, TYPE(h));
 		DB_ASSERT(0);
 		return (EINVAL);
 	}
@@ -1903,27 +1954,27 @@ __bam_vrfy_treeorder(dbp, pgno, h, lp, rp, func, flags)
 				return (ret);
 		} else {
 			DB_ASSERT(0);
-			EPRINT((dbp->dbenv,
+			EPRINT((dbenv,
 			    "Page %lu: unknown type for internal record",
 			    (u_long)PGNO(h)));
 			return (EINVAL);
 		}
 
-		/* On error, fall through, free if neeeded, and return. */
+		/* On error, fall through, free if needed, and return. */
 		if ((ret = __bam_cmp(dbp, &dbt, h, 0, func, &cmp)) == 0) {
 			if (cmp > 0) {
-				EPRINT((dbp->dbenv,
+				EPRINT((dbenv,
 	    "Page %lu: first item on page sorted greater than parent entry",
 				    (u_long)PGNO(h)));
 				ret = DB_VERIFY_BAD;
 			}
 		} else
-			EPRINT((dbp->dbenv,
+			EPRINT((dbenv,
 			    "Page %lu: first item on page had comparison error",
 			    (u_long)PGNO(h)));
 
 		if (dbt.data != lp->data)
-			__os_ufree(dbp->dbenv, dbt.data);
+			__os_ufree(dbenv, dbt.data);
 		if (ret != 0)
 			return (ret);
 	}
@@ -1939,27 +1990,27 @@ __bam_vrfy_treeorder(dbp, pgno, h, lp, rp, func, flags)
 				return (ret);
 		} else {
 			DB_ASSERT(0);
-			EPRINT((dbp->dbenv,
+			EPRINT((dbenv,
 			    "Page %lu: unknown type for internal record",
 			    (u_long)PGNO(h)));
 			return (EINVAL);
 		}
 
-		/* On error, fall through, free if neeeded, and return. */
+		/* On error, fall through, free if needed, and return. */
 		if ((ret = __bam_cmp(dbp, &dbt, h, last, func, &cmp)) == 0) {
 			if (cmp < 0) {
-				EPRINT((dbp->dbenv,
+				EPRINT((dbenv,
 	    "Page %lu: last item on page sorted greater than parent entry",
 				    (u_long)PGNO(h)));
 				ret = DB_VERIFY_BAD;
 			}
 		} else
-			EPRINT((dbp->dbenv,
+			EPRINT((dbenv,
 			    "Page %lu: last item on page had comparison error",
 			    (u_long)PGNO(h)));
 
 		if (dbt.data != rp->data)
-			__os_ufree(dbp->dbenv, dbt.data);
+			__os_ufree(dbenv, dbt.data);
 	}
 
 	return (ret);
@@ -1987,14 +2038,17 @@ __bam_salvage(dbp, vdp, pgno, pgtype, h, handle, callback, key, flags)
 	u_int32_t flags;
 {
 	DBT dbt, unkdbt;
+	DB_ENV *dbenv;
 	BKEYDATA *bk;
 	BOVERFLOW *bo;
+	VRFY_ITEM *pgmap;
 	db_indx_t i, beg, end, *inp;
 	u_int32_t himark;
-	u_int8_t *pgmap;
 	void *ovflbuf;
 	int t_ret, ret, err_ret;
 
+	dbenv = dbp->dbenv;
+
 	/* Shut up lint. */
 	COMPQUIET(end, 0);
 
@@ -2013,15 +2067,12 @@ __bam_salvage(dbp, vdp, pgno, pgtype, h, handle, callback, key, flags)
 	 * Allocate a buffer for overflow items.  Start at one page;
 	 * __db_safe_goff will realloc as needed.
 	 */
-	if ((ret = __os_malloc(dbp->dbenv, dbp->pgsize, &ovflbuf)) != 0)
+	if ((ret = __os_malloc(dbenv, dbp->pgsize, &ovflbuf)) != 0)
 		return (ret);
 
-	if (LF_ISSET(DB_AGGRESSIVE)) {
-		if ((ret =
-		    __os_malloc(dbp->dbenv, dbp->pgsize, &pgmap)) != 0)
-			goto err;
-		memset(pgmap, 0, dbp->pgsize);
-	}
+	if (LF_ISSET(DB_AGGRESSIVE) && (ret =
+	    __os_calloc(dbenv, dbp->pgsize, sizeof(pgmap[0]), &pgmap)) != 0)
+		goto err;
 
 	/*
 	 * Loop through the inp array, spitting out key/data pairs.
@@ -2073,7 +2124,7 @@ __bam_salvage(dbp, vdp, pgno, pgtype, h, handle, callback, key, flags)
 			 */
 			if (key != NULL &&
 			    (i != 0 || !LF_ISSET(SA_SKIPFIRSTKEY)))
-				if ((ret = __db_prdbt(key,
+				if ((ret = __db_vrfy_prdbt(key,
 				    0, " ", handle, callback, 0, vdp)) != 0)
 					err_ret = ret;
 
@@ -2104,7 +2155,8 @@ __bam_salvage(dbp, vdp, pgno, pgtype, h, handle, callback, key, flags)
 				if (!IS_VALID_PGNO(bo->pgno) ||
 				    (i % P_INDX == 0)) {
 					/* Not much to do on failure. */
-					if ((ret = __db_prdbt(&unkdbt, 0, " ",
+					if ((ret =
+					    __db_vrfy_prdbt(&unkdbt, 0, " ",
 					    handle, callback, 0, vdp)) != 0)
 						err_ret = ret;
 					break;
@@ -2117,11 +2169,11 @@ __bam_salvage(dbp, vdp, pgno, pgtype, h, handle, callback, key, flags)
 
 				break;
 			case B_KEYDATA:
-				end =
-				    ALIGN(beg + bk->len, sizeof(u_int32_t)) - 1;
+				end = (db_indx_t)DB_ALIGN(
+				    beg + bk->len, sizeof(u_int32_t)) - 1;
 				dbt.data = bk->data;
 				dbt.size = bk->len;
-				if ((ret = __db_prdbt(&dbt,
+				if ((ret = __db_vrfy_prdbt(&dbt,
 				    0, " ", handle, callback, 0, vdp)) != 0)
 					err_ret = ret;
 				break;
@@ -2132,11 +2184,11 @@ __bam_salvage(dbp, vdp, pgno, pgtype, h, handle, callback, key, flags)
 				    bo->pgno, &dbt, &ovflbuf, flags)) != 0) {
 					err_ret = ret;
 					/* We care about err_ret more. */
-					(void)__db_prdbt(&unkdbt, 0, " ",
+					(void)__db_vrfy_prdbt(&unkdbt, 0, " ",
 					    handle, callback, 0, vdp);
 					break;
 				}
-				if ((ret = __db_prdbt(&dbt,
+				if ((ret = __db_vrfy_prdbt(&dbt,
 				    0, " ", handle, callback, 0, vdp)) != 0)
 					err_ret = ret;
 				break;
@@ -2157,8 +2209,8 @@ __bam_salvage(dbp, vdp, pgno, pgtype, h, handle, callback, key, flags)
 			 * any bogus inp elements and thereby missed stuff.
 			 */
 			if (LF_ISSET(DB_AGGRESSIVE)) {
-				pgmap[beg] = ITEM_BEGIN;
-				pgmap[end] = ITEM_END;
+				pgmap[beg] = VRFY_ITEM_BEGIN;
+				pgmap[end] = VRFY_ITEM_END;
 			}
 		}
 	}
@@ -2168,12 +2220,12 @@ __bam_salvage(dbp, vdp, pgno, pgtype, h, handle, callback, key, flags)
 	 * a datum; fix this imbalance by printing an "UNKNOWN".
 	 */
 	if (pgtype == P_LBTREE && (i % P_INDX == 1) && ((ret =
-	    __db_prdbt(&unkdbt, 0, " ", handle, callback, 0, vdp)) != 0))
+	    __db_vrfy_prdbt(&unkdbt, 0, " ", handle, callback, 0, vdp)) != 0))
 		err_ret = ret;
 
 err:	if (pgmap != NULL)
-		__os_free(dbp->dbenv, pgmap);
-	__os_free(dbp->dbenv, ovflbuf);
+		__os_free(dbenv, pgmap);
+	__os_free(dbenv, ovflbuf);
 
 	/* Mark this page as done. */
 	if ((t_ret = __db_salvage_markdone(vdp, pgno)) != 0)
@@ -2274,7 +2326,7 @@ __bam_meta2pgset(dbp, vdp, btmeta, flags, pgset)
 			err_ret = DB_VERIFY_BAD;
 			goto err;
 		}
-		if ((ret = mpf->get(mpf, &current, 0, &h)) != 0) {
+		if ((ret = __memp_fget(mpf, &current, 0, &h)) != 0) {
 			err_ret = ret;
 			goto err;
 		}
@@ -2303,7 +2355,7 @@ __bam_meta2pgset(dbp, vdp, btmeta, flags, pgset)
 			goto err;
 		}
 
-		if ((ret = mpf->put(mpf, h, 0)) != 0)
+		if ((ret = __memp_fput(mpf, h, 0)) != 0)
 			err_ret = ret;
 		h = NULL;
 	}
@@ -2314,7 +2366,8 @@ __bam_meta2pgset(dbp, vdp, btmeta, flags, pgset)
 	 */
 traverse:
 	while (IS_VALID_PGNO(current) && current != PGNO_INVALID) {
-		if (h == NULL && (ret = mpf->get(mpf, &current, 0, &h)) != 0) {
+		if (h == NULL &&
+		    (ret = __memp_fget(mpf, &current, 0, &h)) != 0) {
 			err_ret = ret;
 			break;
 		}
@@ -2334,13 +2387,13 @@ traverse:
 			goto err;
 
 		current = NEXT_PGNO(h);
-		if ((ret = mpf->put(mpf, h, 0)) != 0)
+		if ((ret = __memp_fput(mpf, h, 0)) != 0)
 			err_ret = ret;
 		h = NULL;
 	}
 
 err:	if (h != NULL)
-		(void)mpf->put(mpf, h, 0);
+		(void)__memp_fput(mpf, h, 0);
 
 	return (ret == 0 ? err_ret : ret);
 }
diff --git a/storage/bdb/btree/btree.src b/storage/bdb/btree/btree.src
index 73f4abac8744254271f1bf2f47fb26475f76dfe0..c4f761de0af37607d591b2594e581010022909b3 100644
--- a/storage/bdb/btree/btree.src
+++ b/storage/bdb/btree/btree.src
@@ -1,17 +1,15 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: btree.src,v 10.35 2002/04/17 19:02:56 krinsky Exp $
+ * $Id: btree.src,v 10.42 2004/06/17 17:35:12 bostic Exp $
  */
 
 PREFIX	__bam
 DBPRIVATE
 
-INCLUDE	#include "db_config.h"
-INCLUDE
 INCLUDE #ifndef NO_SYSTEM_INCLUDES
 INCLUDE #include <sys/types.h>
 INCLUDE
@@ -26,14 +24,9 @@ INCLUDE #include "dbinc/db_dispatch.h"
 INCLUDE #include "dbinc/db_am.h"
 INCLUDE #include "dbinc/btree.h"
 INCLUDE #include "dbinc/log.h"
-INCLUDE #include "dbinc/rep.h"
 INCLUDE #include "dbinc/txn.h"
 INCLUDE
 
-/*
- * NOTE: pg_alloc and pg_free have been moved to db.src, where they belong.
- */
-
 /*
  * BTREE-split: used to log a page split.
  *
@@ -50,14 +43,14 @@ INCLUDE
  */
 BEGIN split		62
 DB	fileid		int32_t		ld
-WRLOCK	left		db_pgno_t	lu
+ARG	left		db_pgno_t	lu
 POINTER	llsn		DB_LSN *	lu
-WRLOCK	right		db_pgno_t	lu
+ARG	right		db_pgno_t	lu
 POINTER	rlsn		DB_LSN *	lu
 ARG	indx		u_int32_t	lu
 ARG	npgno		db_pgno_t	lu
 POINTER	nlsn		DB_LSN *	lu
-WRLOCKNZ root_pgno	db_pgno_t	lu
+ARG	root_pgno	db_pgno_t	lu
 PGDBT	pg		DBT		s
 ARG	opflags		u_int32_t	lu
 END
@@ -74,9 +67,9 @@ END
  */
 BEGIN rsplit		63
 DB	fileid		int32_t		ld
-WRLOCK	pgno		db_pgno_t	lu
+ARG	pgno		db_pgno_t	lu
 PGDBT	pgdbt		DBT		s
-WRLOCK	root_pgno	db_pgno_t	lu
+ARG	root_pgno	db_pgno_t	lu
 ARG	nrec		db_pgno_t	lu
 DBT	rootent		DBT		s
 POINTER rootlsn		DB_LSN *	lu
@@ -93,7 +86,7 @@ END
  */
 BEGIN adj		55
 DB	fileid		int32_t		ld
-WRLOCK	pgno		db_pgno_t	lu
+ARG	pgno		db_pgno_t	lu
 POINTER	lsn		DB_LSN *	lu
 ARG	indx		u_int32_t	lu
 ARG	indx_copy	u_int32_t	lu
@@ -111,7 +104,7 @@ END
  */
 BEGIN cadjust		56
 DB	fileid		int32_t		ld
-WRLOCK	pgno		db_pgno_t	lu
+ARG	pgno		db_pgno_t	lu
 POINTER	lsn		DB_LSN *	lu
 ARG	indx		u_int32_t	lu
 ARG	adjust		int32_t		ld
@@ -127,7 +120,7 @@ END
  */
 BEGIN cdel		57
 DB	fileid		int32_t		ld
-WRLOCK	pgno		db_pgno_t	lu
+ARG	pgno		db_pgno_t	lu
 POINTER	lsn		DB_LSN *	lu
 ARG	indx		u_int32_t	lu
 END
@@ -137,13 +130,16 @@ END
  *
  * pgno:	the page modified.
  * lsn:		the page's original lsn.
+ * indx:	the index to be replaced.
+ * isdeleted:	set if the record was previously deleted.
  * orig:	the original data.
- * new:		the replacement data.
- * duplicate:	the prefix of the replacement that matches the original.
+ * repl:	the replacement data.
+ * prefix:	the prefix of the replacement that matches the original.
+ * suffix:	the suffix of the replacement that matches the original.
  */
 BEGIN repl		58
 DB	fileid		int32_t		ld
-WRLOCK	pgno		db_pgno_t	lu
+ARG	pgno		db_pgno_t	lu
 POINTER	lsn		DB_LSN *	lu
 ARG	indx		u_int32_t	lu
 ARG	isdeleted	u_int32_t	lu
@@ -158,8 +154,8 @@ END
  */
 BEGIN root		59
 DB	fileid		int32_t		ld
-WRLOCK	meta_pgno	db_pgno_t	lu
-WRLOCK	root_pgno	db_pgno_t	lu
+ARG	meta_pgno	db_pgno_t	lu
+ARG	root_pgno	db_pgno_t	lu
 POINTER	meta_lsn	DB_LSN *	lu
 END
 
@@ -206,3 +202,24 @@ ARG	recno		db_recno_t	ld
 /* Order number of the adjustment. */
 ARG	order		u_int32_t	ld
 END
+
+/*
+ * BTREE-relink -- Handles relinking around a deleted leaf page.
+ *
+ */
+BEGIN relink		147
+/* Fileid of db affected. */
+DB	fileid		int32_t		ld
+/* The page being changed. */
+ARG	pgno		db_pgno_t	lu
+/* The page's original lsn. */
+POINTER	lsn		DB_LSN *	lu
+/* The previous page. */
+ARG	prev		db_pgno_t	lu
+/* The previous page's original lsn. */
+POINTER	lsn_prev	DB_LSN *	lu
+/* The next page. */
+ARG	next		db_pgno_t	lu
+/* The previous page's original lsn. */
+POINTER	lsn_next	DB_LSN *	lu
+END
diff --git a/storage/bdb/build_vxworks/db_deadlock/db_deadlock.c b/storage/bdb/build_vxworks/db_deadlock/db_deadlock.c
new file mode 100644
index 0000000000000000000000000000000000000000..32689d203455b65834a6fbd4afc07f1f9bf82652
--- /dev/null
+++ b/storage/bdb/build_vxworks/db_deadlock/db_deadlock.c
@@ -0,0 +1,251 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_deadlock.c,v 11.45 2004/03/24 15:13:12 bostic Exp $
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char copyright[] =
+    "Copyright (c) 1996-2004\nSleepycat Software Inc.  All rights reserved.\n";
+#endif
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#if TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#endif
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#endif
+
+#include "db_int.h"
+
+int db_deadlock_main __P((int, char *[]));
+int db_deadlock_usage __P((void));
+int db_deadlock_version_check __P((const char *));
+
+int
+db_deadlock(args)
+	char *args;
+{
+	int argc;
+	char **argv;
+
+	__db_util_arg("db_deadlock", args, &argc, &argv);
+	return (db_deadlock_main(argc, argv) ? EXIT_FAILURE : EXIT_SUCCESS);
+}
+
+#include <stdio.h>
+#define	ERROR_RETURN	ERROR
+
+int
+db_deadlock_main(argc, argv)
+	int argc;
+	char *argv[];
+{
+	extern char *optarg;
+	extern int optind, __db_getopt_reset;
+	const char *progname = "db_deadlock";
+	DB_ENV  *dbenv;
+	u_int32_t atype;
+	time_t now;
+	u_long secs, usecs;
+	int ch, exitval, ret, verbose;
+	char *home, *logfile, *str;
+
+	if ((ret = db_deadlock_version_check(progname)) != 0)
+		return (ret);
+
+	dbenv = NULL;
+	atype = DB_LOCK_DEFAULT;
+	home = logfile = NULL;
+	secs = usecs = 0;
+	exitval = verbose = 0;
+	__db_getopt_reset = 1;
+	while ((ch = getopt(argc, argv, "a:h:L:t:Vvw")) != EOF)
+		switch (ch) {
+		case 'a':
+			switch (optarg[0]) {
+			case 'e':
+				atype = DB_LOCK_EXPIRE;
+				break;
+			case 'm':
+				atype = DB_LOCK_MAXLOCKS;
+				break;
+			case 'n':
+				atype = DB_LOCK_MINLOCKS;
+				break;
+			case 'o':
+				atype = DB_LOCK_OLDEST;
+				break;
+			case 'W':
+				atype = DB_LOCK_MAXWRITE;
+				break;
+			case 'w':
+				atype = DB_LOCK_MINWRITE;
+				break;
+			case 'y':
+				atype = DB_LOCK_YOUNGEST;
+				break;
+			default:
+				return (db_deadlock_usage());
+				/* NOTREACHED */
+			}
+			if (optarg[1] != '\0')
+				return (db_deadlock_usage());
+			break;
+		case 'h':
+			home = optarg;
+			break;
+		case 'L':
+			logfile = optarg;
+			break;
+		case 't':
+			if ((str = strchr(optarg, '.')) != NULL) {
+				*str++ = '\0';
+				if (*str != '\0' && __db_getulong(
+				    NULL, progname, str, 0, LONG_MAX, &usecs))
+					return (EXIT_FAILURE);
+			}
+			if (*optarg != '\0' && __db_getulong(
+			    NULL, progname, optarg, 0, LONG_MAX, &secs))
+				return (EXIT_FAILURE);
+			if (secs == 0 && usecs == 0)
+				return (db_deadlock_usage());
+
+			break;
+
+		case 'V':
+			printf("%s\n", db_version(NULL, NULL, NULL));
+			return (EXIT_SUCCESS);
+		case 'v':
+			verbose = 1;
+			break;
+		case 'w':			/* Undocumented. */
+			/* Detect every 100ms (100000 us) when polling. */
+			secs = 0;
+			usecs = 100000;
+			break;
+		case '?':
+		default:
+			return (db_deadlock_usage());
+		}
+	argc -= optind;
+	argv += optind;
+
+	if (argc != 0)
+		return (db_deadlock_usage());
+
+	/* Handle possible interruptions. */
+	__db_util_siginit();
+
+	/* Log our process ID. */
+	if (logfile != NULL && __db_util_logset(progname, logfile))
+		goto shutdown;
+
+	/*
+	 * Create an environment object and initialize it for error
+	 * reporting.
+	 */
+	if ((ret = db_env_create(&dbenv, 0)) != 0) {
+		fprintf(stderr,
+		    "%s: db_env_create: %s\n", progname, db_strerror(ret));
+		goto shutdown;
+	}
+
+	dbenv->set_errfile(dbenv, stderr);
+	dbenv->set_errpfx(dbenv, progname);
+
+	if (verbose) {
+		(void)dbenv->set_verbose(dbenv, DB_VERB_DEADLOCK, 1);
+		(void)dbenv->set_verbose(dbenv, DB_VERB_WAITSFOR, 1);
+	}
+
+	/* An environment is required. */
+	if ((ret =
+	    dbenv->open(dbenv, home, DB_INIT_LOCK | DB_USE_ENVIRON, 0)) != 0) {
+		dbenv->err(dbenv, ret, "open");
+		goto shutdown;
+	}
+
+	while (!__db_util_interrupted()) {
+		if (verbose) {
+			(void)time(&now);
+			dbenv->errx(dbenv, "running at %.24s", ctime(&now));
+		}
+
+		if ((ret = dbenv->lock_detect(dbenv, 0, atype, NULL)) != 0) {
+			dbenv->err(dbenv, ret, "DB_ENV->lock_detect");
+			goto shutdown;
+		}
+
+		/* Make a pass every "secs" secs and "usecs" usecs. */
+		if (secs == 0 && usecs == 0)
+			break;
+		__os_sleep(dbenv, secs, usecs);
+	}
+
+	if (0) {
+shutdown:	exitval = 1;
+	}
+
+	/* Clean up the logfile. */
+	if (logfile != NULL)
+		(void)remove(logfile);
+
+	/* Clean up the environment. */
+	if (dbenv != NULL && (ret = dbenv->close(dbenv, 0)) != 0) {
+		exitval = 1;
+		fprintf(stderr,
+		    "%s: dbenv->close: %s\n", progname, db_strerror(ret));
+	}
+
+	/* Resend any caught signal. */
+	__db_util_sigresend();
+
+	return (exitval == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
+}
+
+int
+db_deadlock_usage()
+{
+	(void)fprintf(stderr, "%s\n\t%s\n",
+	    "usage: db_deadlock [-Vv]",
+	    "[-a e | m | n | o | W | w | y] [-h home] [-L file] [-t sec.usec]");
+	return (EXIT_FAILURE);
+}
+
+int
+db_deadlock_version_check(progname)
+	const char *progname;
+{
+	int v_major, v_minor, v_patch;
+
+	/* Make sure we're loaded with the right version of the DB library. */
+	(void)db_version(&v_major, &v_minor, &v_patch);
+	if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) {
+		fprintf(stderr,
+	"%s: version %d.%d doesn't match library version %d.%d\n",
+		    progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
+		    v_major, v_minor);
+		return (EXIT_FAILURE);
+	}
+	return (0);
+}
diff --git a/storage/bdb/build_win32/Berkeley_DB.dsw b/storage/bdb/build_win32/Berkeley_DB.dsw
index 899e31ad58deb9b0bce2186e0cf9417cc885aa9b..8e39c20eff3dc86ff689ec3c406873adf8f1f62b 100644
--- a/storage/bdb/build_win32/Berkeley_DB.dsw
+++ b/storage/bdb/build_win32/Berkeley_DB.dsw
@@ -1,51 +1,9 @@
-Microsoft Developer Studio Workspace File, Format Version 5.00
+Microsoft Developer Studio Workspace File, Format Version 6.00
 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
 
 ###############################################################################
 
-Project: "DB_DLL"=.\db_dll.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "DB_Static"=.\db_static.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "db_archive"=.\db_archive.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-    Begin Project Dependency
-    Project_Dep_Name DB_DLL
-    End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name DB_Static
-    End Project Dependency
-}}}
-
-###############################################################################
-
-Project: "db_buildall"=.\db_buildall.dsp - Package Owner=<4>
+Project: "build_all"=.\build_all.dsp - Package Owner=<4>
 
 Package=<5>
 {{{
@@ -125,11 +83,14 @@ Package=<4>
     Begin Project Dependency
     Project_Dep_Name excxx_tpcb
     End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name db_lib
+    End Project Dependency
 }}}
 
 ###############################################################################
 
-Project: "db_checkpoint"=.\db_checkpoint.dsp - Package Owner=<4>
+Project: "db_archive"=.\db_archive.dsp - Package Owner=<4>
 
 Package=<5>
 {{{
@@ -138,10 +99,22 @@ Package=<5>
 Package=<4>
 {{{
     Begin Project Dependency
-    Project_Dep_Name DB_DLL
+    Project_Dep_Name db_lib
     End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "db_checkpoint"=.\db_checkpoint.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
     Begin Project Dependency
-    Project_Dep_Name DB_Static
+    Project_Dep_Name db_lib
     End Project Dependency
 }}}
 
@@ -158,9 +131,18 @@ Package=<4>
     Begin Project Dependency
     Project_Dep_Name DB_DLL
     End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name DB_Static
-    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "db_dll"=.\db_dll.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
 }}}
 
 ###############################################################################
@@ -174,10 +156,7 @@ Package=<5>
 Package=<4>
 {{{
     Begin Project Dependency
-    Project_Dep_Name DB_DLL
-    End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name DB_Static
+    Project_Dep_Name db_lib
     End Project Dependency
 }}}
 
@@ -198,7 +177,7 @@ Package=<4>
 
 ###############################################################################
 
-Project: "db_load"=.\db_load.dsp - Package Owner=<4>
+Project: "db_lib"=.\db_lib.dsp - Package Owner=<4>
 
 Package=<5>
 {{{
@@ -207,16 +186,16 @@ Package=<5>
 Package=<4>
 {{{
     Begin Project Dependency
-    Project_Dep_Name DB_DLL
+    Project_Dep_Name db_dll
     End Project Dependency
     Begin Project Dependency
-    Project_Dep_Name DB_Static
+    Project_Dep_Name db_static
     End Project Dependency
 }}}
 
 ###############################################################################
 
-Project: "db_printlog"=.\db_printlog.dsp - Package Owner=<4>
+Project: "db_load"=.\db_load.dsp - Package Owner=<4>
 
 Package=<5>
 {{{
@@ -225,10 +204,22 @@ Package=<5>
 Package=<4>
 {{{
     Begin Project Dependency
-    Project_Dep_Name DB_DLL
+    Project_Dep_Name db_lib
     End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "db_printlog"=.\db_printlog.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
     Begin Project Dependency
-    Project_Dep_Name DB_Static
+    Project_Dep_Name db_lib
     End Project Dependency
 }}}
 
@@ -243,10 +234,7 @@ Package=<5>
 Package=<4>
 {{{
     Begin Project Dependency
-    Project_Dep_Name DB_DLL
-    End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name DB_Static
+    Project_Dep_Name db_lib
     End Project Dependency
 }}}
 
@@ -261,15 +249,24 @@ Package=<5>
 Package=<4>
 {{{
     Begin Project Dependency
-    Project_Dep_Name DB_DLL
-    End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name DB_Static
+    Project_Dep_Name db_lib
     End Project Dependency
 }}}
 
 ###############################################################################
 
+Project: "db_static"=.\db_static.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
 Project: "db_tcl"=.\db_tcl.dsp - Package Owner=<4>
 
 Package=<5>
@@ -294,7 +291,7 @@ Package=<5>
 Package=<4>
 {{{
     Begin Project Dependency
-    Project_Dep_Name db_buildall
+    Project_Dep_Name build_all
     End Project Dependency
     Begin Project Dependency
     Project_Dep_Name db_tcl
@@ -312,10 +309,7 @@ Package=<5>
 Package=<4>
 {{{
     Begin Project Dependency
-    Project_Dep_Name DB_DLL
-    End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name DB_Static
+    Project_Dep_Name db_lib
     End Project Dependency
 }}}
 
@@ -330,10 +324,7 @@ Package=<5>
 Package=<4>
 {{{
     Begin Project Dependency
-    Project_Dep_Name DB_DLL
-    End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name DB_Static
+    Project_Dep_Name db_lib
     End Project Dependency
 }}}
 
@@ -348,10 +339,7 @@ Package=<5>
 Package=<4>
 {{{
     Begin Project Dependency
-    Project_Dep_Name DB_DLL
-    End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name DB_Static
+    Project_Dep_Name db_lib
     End Project Dependency
 }}}
 
@@ -366,10 +354,7 @@ Package=<5>
 Package=<4>
 {{{
     Begin Project Dependency
-    Project_Dep_Name DB_Static
-    End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name DB_DLL
+    Project_Dep_Name db_lib
     End Project Dependency
 }}}
 
@@ -384,10 +369,7 @@ Package=<5>
 Package=<4>
 {{{
     Begin Project Dependency
-    Project_Dep_Name DB_DLL
-    End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name DB_Static
+    Project_Dep_Name db_lib
     End Project Dependency
 }}}
 
@@ -402,10 +384,7 @@ Package=<5>
 Package=<4>
 {{{
     Begin Project Dependency
-    Project_Dep_Name DB_DLL
-    End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name DB_Static
+    Project_Dep_Name db_lib
     End Project Dependency
 }}}
 
@@ -420,10 +399,22 @@ Package=<5>
 Package=<4>
 {{{
     Begin Project Dependency
-    Project_Dep_Name DB_DLL
+    Project_Dep_Name db_lib
     End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "ex_repquote"=.\ex_repquote.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
     Begin Project Dependency
-    Project_Dep_Name DB_Static
+    Project_Dep_Name db_lib
     End Project Dependency
 }}}
 
@@ -438,10 +429,7 @@ Package=<5>
 Package=<4>
 {{{
     Begin Project Dependency
-    Project_Dep_Name DB_DLL
-    End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name DB_Static
+    Project_Dep_Name db_lib
     End Project Dependency
 }}}
 
@@ -456,10 +444,7 @@ Package=<5>
 Package=<4>
 {{{
     Begin Project Dependency
-    Project_Dep_Name DB_DLL
-    End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name DB_Static
+    Project_Dep_Name db_lib
     End Project Dependency
 }}}
 
@@ -474,10 +459,7 @@ Package=<5>
 Package=<4>
 {{{
     Begin Project Dependency
-    Project_Dep_Name DB_DLL
-    End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name DB_Static
+    Project_Dep_Name db_lib
     End Project Dependency
 }}}
 
@@ -492,10 +474,7 @@ Package=<5>
 Package=<4>
 {{{
     Begin Project Dependency
-    Project_Dep_Name DB_DLL
-    End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name DB_Static
+    Project_Dep_Name db_lib
     End Project Dependency
 }}}
 
@@ -510,10 +489,7 @@ Package=<5>
 Package=<4>
 {{{
     Begin Project Dependency
-    Project_Dep_Name DB_DLL
-    End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name DB_Static
+    Project_Dep_Name db_lib
     End Project Dependency
 }}}
 
@@ -528,10 +504,7 @@ Package=<5>
 Package=<4>
 {{{
     Begin Project Dependency
-    Project_Dep_Name DB_DLL
-    End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name DB_Static
+    Project_Dep_Name db_lib
     End Project Dependency
 }}}
 
@@ -546,10 +519,7 @@ Package=<5>
 Package=<4>
 {{{
     Begin Project Dependency
-    Project_Dep_Name DB_DLL
-    End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name DB_Static
+    Project_Dep_Name db_lib
     End Project Dependency
 }}}
 
@@ -566,3 +536,4 @@ Package=<3>
 }}}
 
 ###############################################################################
+
diff --git a/storage/bdb/build_win32/app_dsp.src b/storage/bdb/build_win32/app_dsp.src
index ff98d39ec793e5ca6e628591e6ec5f00e0dd1303..cc4d0bab41c3e31b21c347ed4d4ef9a72155ed0b 100644
--- a/storage/bdb/build_win32/app_dsp.src
+++ b/storage/bdb/build_win32/app_dsp.src
@@ -44,7 +44,7 @@ RSC=rc.exe
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /I "../dbinc" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
 # ADD BASE RSC /l 0x409 /d "NDEBUG"
 # ADD RSC /l 0x409 /d "NDEBUG"
 BSC32=bscmake.exe
@@ -68,7 +68,7 @@ LINK32=link.exe
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /I "../dbinc" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
 # ADD BASE RSC /l 0x409 /d "_DEBUG"
 # ADD RSC /l 0x409 /d "_DEBUG"
 BSC32=bscmake.exe
@@ -92,8 +92,8 @@ LINK32=link.exe
 # PROP Intermediate_Dir "Release_static"
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /I "../dbinc" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "." /I ".." /I "../dbinc" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
 # ADD BASE RSC /l 0x409 /d "NDEBUG"
 # ADD RSC /l 0x409 /d "NDEBUG"
 BSC32=bscmake.exe
@@ -117,8 +117,8 @@ LINK32=link.exe
 # PROP Intermediate_Dir "Debug_static"
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /I "../dbinc" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I ".." /I "../dbinc" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
 # ADD BASE RSC /l 0x409 /d "_DEBUG"
 # ADD RSC /l 0x409 /d "_DEBUG"
 BSC32=bscmake.exe
diff --git a/storage/bdb/build_win32/db_test.src b/storage/bdb/build_win32/db_test.src
index 73479d3856ad318fbbb84ae56402ebc13fa71f3a..38e7fcd9b405724f4a4abc1cef11e466118871f9 100644
--- a/storage/bdb/build_win32/db_test.src
+++ b/storage/bdb/build_win32/db_test.src
@@ -42,7 +42,7 @@ RSC=rc.exe
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /I "../dbinc" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
 # ADD BASE RSC /l 0x409 /d "NDEBUG"
 # ADD RSC /l 0x409 /d "NDEBUG"
 BSC32=bscmake.exe
@@ -71,7 +71,7 @@ PostBuild_Cmds=copy Release\*.exe .
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /I "../dbinc" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
 # ADD BASE RSC /l 0x409 /d "_DEBUG"
 # ADD RSC /l 0x409 /d "_DEBUG"
 BSC32=bscmake.exe
diff --git a/storage/bdb/build_win32/dbkill.cpp b/storage/bdb/build_win32/dbkill.cpp
index 23dc87b0e8558b7b46eb3fc18f8b03128e98f062..7be76135ce6a823f7a8710683893f229157853e7 100644
--- a/storage/bdb/build_win32/dbkill.cpp
+++ b/storage/bdb/build_win32/dbkill.cpp
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: dbkill.cpp,v 11.7 2002/01/11 15:51:27 bostic Exp $
+ * $Id: dbkill.cpp,v 11.9 2004/01/28 03:35:52 bostic Exp $
  */
 /*
  * Kill -
diff --git a/storage/bdb/build_win32/dynamic_dsp.src b/storage/bdb/build_win32/dynamic_dsp.src
index a92906a51f42d4f4df91786ef3e5e332cefed542..2229edd3de63d61e2ab69d1bce417d54323f5714 100644
--- a/storage/bdb/build_win32/dynamic_dsp.src
+++ b/storage/bdb/build_win32/dynamic_dsp.src
@@ -43,7 +43,7 @@ RSC=rc.exe
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "." /I ".." /I "../dbinc" /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "." /I ".." /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
 # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
 # ADD BASE RSC /l 0x409 /d "NDEBUG"
@@ -69,7 +69,7 @@ LINK32=link.exe
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /I "../dbinc" /D "DB_CREATE_DLL" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "DB_CREATE_DLL" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /FD /c
 # SUBTRACT CPP /Fr
 # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
diff --git a/storage/bdb/build_win32/java_dsp.src b/storage/bdb/build_win32/java_dsp.src
index 15941bcab674246d7671e7c8a42d436196aa3687..c06cb2b354414bffa5a7098629fafae167e7f995 100644
--- a/storage/bdb/build_win32/java_dsp.src
+++ b/storage/bdb/build_win32/java_dsp.src
@@ -43,7 +43,7 @@ RSC=rc.exe
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "." /I ".." /I "../dbinc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "DB_CREATE_DLL" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "DB_CREATE_DLL" /YX /FD /c
 # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
 # ADD BASE RSC /l 0x409 /d "NDEBUG"
@@ -60,15 +60,15 @@ InputPath=.\Release\libdb_java@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll
 SOURCE="$(InputPath)"
 
 "force_compilation.txt" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
-	mkdir $(ProjDir)\Release\classes 
 	echo compiling Berkeley DB classes 
-	javac -g -d $(ProjDir)/Release/classes -classpath "$(CLASSPATH);$(ProjDir)/Release/classes" ..\java\src\com\sleepycat\db\*.java 
+	mkdir "$(OUTDIR)\classes"
+	javac -O -d "$(OUTDIR)\classes" -classpath "$(OUTDIR)/classes" ..\java\src\com\sleepycat\db\*.java ..\java\src\com\sleepycat\db\internal\*.java ..\java\src\com\sleepycat\bind\*.java ..\java\src\com\sleepycat\bind\serial\*.java ..\java\src\com\sleepycat\bind\tuple\*.java ..\java\src\com\sleepycat\collections\*.java ..\java\src\com\sleepycat\compat\*.java ..\java\src\com\sleepycat\util\*.java
 	echo compiling examples 
-	javac -g -d $(ProjDir)/Release/classes -classpath "$(CLASSPATH);$(ProjDir)/Release/classes" ..\java\src\com\sleepycat\examples\*.java 
+	mkdir "$(OUTDIR)\classes.ex"
+	javac -O -d "$(OUTDIR)\classes.ex" -classpath "$(OUTDIR)\classes;$(OUTDIR)\classes.ex" ..\examples_java\src\com\sleepycat\examples\db\*.java ..\examples_java\src\com\sleepycat\examples\db\GettingStarted\*.java ..\examples_java\src\com\sleepycat\examples\collections\access\*.java ..\examples_java\src\com\sleepycat\examples\collections\hello\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\basic\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\entity\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\tuple\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\sentity\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\marshal\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\factory\*.java
 	echo creating jar files 
-	cd $(ProjDir)\Release\classes 
-	jar cf ../db.jar com\sleepycat\db\*.class 
-	jar cf ../dbexamples.jar com\sleepycat\examples\*.class 
+	jar cf "$(OUTDIR)\db.jar" -C "$(OUTDIR)\classes" .
+	jar cf "$(OUTDIR)\dbexamples.jar" -C "$(OUTDIR)\classes.ex" .
 	echo Java build finished 
 	
 # End Custom Build
@@ -87,7 +87,7 @@ SOURCE="$(InputPath)"
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /I "../dbinc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "DB_CREATE_DLL" /D "_WINDLL" /D "_AFXDLL" /YX"config.h" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "DB_CREATE_DLL" /D "_WINDLL" /D "_AFXDLL" /YX"config.h" /FD /c
 # SUBTRACT CPP /Fr
 # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
@@ -105,17 +105,17 @@ InputPath=.\Debug\libdb_java@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll
 SOURCE="$(InputPath)"
 
 "force_compilation.txt" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
-	mkdir $(ProjDir)\Debug\classes 
 	echo compiling Berkeley DB classes 
-	javac -g -d $(ProjDir)/Debug/classes -classpath "$(CLASSPATH);$(ProjDir)/Debug/classes" ..\java\src\com\sleepycat\db\*.java 
+	mkdir "$(OUTDIR)\classes"
+	javac -g -d "$(OUTDIR)\classes" -classpath "$(OUTDIR)/classes" ..\java\src\com\sleepycat\db\*.java ..\java\src\com\sleepycat\db\internal\*.java ..\java\src\com\sleepycat\bind\*.java ..\java\src\com\sleepycat\bind\serial\*.java ..\java\src\com\sleepycat\bind\tuple\*.java ..\java\src\com\sleepycat\collections\*.java ..\java\src\com\sleepycat\compat\*.java ..\java\src\com\sleepycat\util\*.java
 	echo compiling examples 
-	javac -g -d $(ProjDir)/Debug/classes -classpath "$(CLASSPATH);$(ProjDir)/Debug/classes" ..\java\src\com\sleepycat\examples\*.java 
+	mkdir "$(OUTDIR)\classes.ex"
+	javac -g -d "$(OUTDIR)\classes.ex" -classpath "$(OUTDIR)\classes;$(OUTDIR)\classes.ex" ..\examples_java\src\com\sleepycat\examples\db\*.java ..\examples_java\src\com\sleepycat\examples\db\GettingStarted\*.java ..\examples_java\src\com\sleepycat\examples\collections\access\*.java ..\examples_java\src\com\sleepycat\examples\collections\hello\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\basic\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\entity\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\tuple\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\sentity\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\marshal\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\factory\*.java
 	echo creating jar files 
-	cd $(ProjDir)\Debug\classes 
-	jar cf ../db.jar com\sleepycat\db\*.class 
-	jar cf ../dbexamples.jar com\sleepycat\examples\*.class 
+	jar cf "$(OUTDIR)\db.jar" -C "$(OUTDIR)\classes" .
+	jar cf "$(OUTDIR)\dbexamples.jar" -C "$(OUTDIR)\classes.ex" .
 	echo Java build finished 
-	
+
 # End Custom Build
 
 !ENDIF 
diff --git a/storage/bdb/build_win32/libdb_tcl.def b/storage/bdb/build_win32/libdb_tcl.def
index b6323c66bc6c157c6dac5a1c7fbb457589988af3..5e8386a3591ef8f9983077a9f49ef6c23f5f6a03 100644
--- a/storage/bdb/build_win32/libdb_tcl.def
+++ b/storage/bdb/build_win32/libdb_tcl.def
@@ -1,27 +1,7 @@
-; $Id: libdb_tcl.def,v 11.5 2002/04/03 12:01:27 mjc Exp $
+; $Id: libdb_tcl.def,v 11.7 2002/10/14 23:44:20 mjc Exp $
 
 DESCRIPTION     'Berkeley DB TCL interface Library'
 EXPORTS
 	Db_tcl_Init
-	db_Cmd
-	dbc_Cmd
-	env_Cmd
-	tcl_EnvRemove
-	tcl_LockDetect
-	tcl_LockGet
-	tcl_LockStat
-	tcl_LockVec
-	tcl_LogArchive
-	tcl_LogCompare
-	tcl_LogFile
-	tcl_LogFlush
-	tcl_LogGet
-	tcl_LogPut
-	tcl_LogStat
-	tcl_Mp
-	tcl_MpStat
-	tcl_MpSync
-	tcl_MpTrickle
-	tcl_Txn
-	tcl_TxnCheckpoint
-	tcl_TxnStat
+	_NameToPtr
+
diff --git a/storage/bdb/build_win32/libdbrc.src b/storage/bdb/build_win32/libdbrc.src
index 3e5d8deec6f4b3cb2d22a65d15f15872a26cae4c..4c644ea9f4f9f6216ee36bbef10d82c1b2e9478a 100644
--- a/storage/bdb/build_win32/libdbrc.src
+++ b/storage/bdb/build_win32/libdbrc.src
@@ -20,7 +20,7 @@ BEGIN
             VALUE "FileDescription", "Berkeley DB 3.0 DLL\0"
             VALUE "FileVersion", "%MAJOR%.%MINOR%.%PATCH%\0"
             VALUE "InternalName", "libdb.dll\0"
-            VALUE "LegalCopyright", "Copyright © Sleepycat Software Inc. 1997-2002\0"
+            VALUE "LegalCopyright", "Copyright © Sleepycat Software Inc. 1997-2004\0"
             VALUE "OriginalFilename", "libdb.dll\0"
             VALUE "ProductName", "Sleepycat Software libdb\0"
             VALUE "ProductVersion", "%MAJOR%.%MINOR%.%PATCH%\0"
diff --git a/storage/bdb/build_win32/static_dsp.src b/storage/bdb/build_win32/static_dsp.src
index 0c66c851025c27ccf1f1231f2edbcc470ea8c575..411e8df8d07ac4239d0e615696de9388f7d4e06c 100644
--- a/storage/bdb/build_win32/static_dsp.src
+++ b/storage/bdb/build_win32/static_dsp.src
@@ -40,8 +40,8 @@ RSC=rc.exe
 # PROP Output_Dir "Release_static"
 # PROP Intermediate_Dir "Release_static"
 # PROP Target_Dir ""
-# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "." /I ".." /I "../dbinc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX"config.h" /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "." /I ".." /I "../dbinc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /FD /c
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX"config.h" /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /FD /c
 # ADD BASE RSC /l 0xc09
 # ADD RSC /l 0xc09
 BSC32=bscmake.exe
@@ -63,8 +63,8 @@ LIB32=link.exe -lib
 # PROP Output_Dir "Debug_static"
 # PROP Intermediate_Dir "Debug_static"
 # PROP Target_Dir ""
-# ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I ".." /I "../dbinc" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX"config.h" /FD /c
-# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I ".." /I "../dbinc" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /FD /c
+# ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I ".." /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX"config.h" /FD /c
+# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I ".." /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /FD /c
 # ADD BASE RSC /l 0xc09
 # ADD RSC /l 0xc09
 BSC32=bscmake.exe
diff --git a/storage/bdb/build_win32/tcl_dsp.src b/storage/bdb/build_win32/tcl_dsp.src
index 4de41e6934e0426c459cfdd9836d467ae62c3405..fc7b2177e00dcb93b12ccbadb1f5b20977b9b3da 100644
--- a/storage/bdb/build_win32/tcl_dsp.src
+++ b/storage/bdb/build_win32/tcl_dsp.src
@@ -43,7 +43,7 @@ RSC=rc.exe
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "." /I ".." /I "../dbinc" /D "DB_TCL_SUPPORT" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "DB_CREATE_DLL" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "." /I ".." /D "DB_TCL_SUPPORT" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "DB_CREATE_DLL" /YX /FD /c
 # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
 # ADD BASE RSC /l 0x409 /d "NDEBUG"
@@ -53,7 +53,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
-# ADD LINK32 Release/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib tcl83.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:I386 /out:"Release/libdb_tcl@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll"
+# ADD LINK32 Release/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib tcl84.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:I386 /out:"Release/libdb_tcl@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll"
 
 !ELSEIF  "$(CFG)" == "@project_name@ - Win32 Debug"
 
@@ -69,7 +69,7 @@ LINK32=link.exe
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /I "../dbinc" /D "DB_TCL_SUPPORT" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "DB_CREATE_DLL" /D "_WINDLL" /D "_AFXDLL" /YX"config.h" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "DB_TCL_SUPPORT" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "DB_CREATE_DLL" /D "_WINDLL" /D "_AFXDLL" /YX"config.h" /FD /c
 # SUBTRACT CPP /Fr
 # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
@@ -80,7 +80,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 Debug/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib tcl83d.lib /nologo /base:"0x13000000" /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:"Debug/libdb_tcl@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no
+# ADD LINK32 Debug/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib tcl84g.lib /nologo /base:"0x13000000" /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:"Debug/libdb_tcl@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no
 
 !ENDIF 
 
diff --git a/storage/bdb/clib/getcwd.c b/storage/bdb/clib/getcwd.c
index bae50dfe90ca7ec03aba96f724e7d4e4a340bd72..ec28f1fb63764336821e93bdac91b989ffc7b961 100644
--- a/storage/bdb/clib/getcwd.c
+++ b/storage/bdb/clib/getcwd.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -31,14 +31,12 @@
  * 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.
+ *
+ * $Id: getcwd.c,v 11.15 2004/01/28 03:35:52 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: getcwd.c,v 11.13 2002/02/28 21:27:18 ubell Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #include <sys/stat.h>
diff --git a/storage/bdb/clib/getopt.c b/storage/bdb/clib/getopt.c
index 3f6659ea6e68fa9ca742001bab3d3b5301457a92..527ee69678de5ca2f6ec78be37d79d56b4b148d4 100644
--- a/storage/bdb/clib/getopt.c
+++ b/storage/bdb/clib/getopt.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -31,14 +31,12 @@
  * 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.
+ *
+ * $Id: getopt.c,v 11.9 2004/01/28 03:35:52 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: getopt.c,v 11.7 2002/01/11 15:51:28 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/storage/bdb/clib/memcmp.c b/storage/bdb/clib/memcmp.c
index 979badaef30fcf8a8d32eb545ce591d8050187b4..055a2f5fa9a03a9cf76205c93a7a7698548c9340 100644
--- a/storage/bdb/clib/memcmp.c
+++ b/storage/bdb/clib/memcmp.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -31,14 +31,12 @@
  * 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.
+ *
+ * $Id: memcmp.c,v 11.9 2004/01/28 03:35:52 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: memcmp.c,v 11.7 2002/01/11 15:51:28 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #endif
diff --git a/storage/bdb/clib/memmove.c b/storage/bdb/clib/memmove.c
index 632d50788da43c524f3219795f8851b1a4783284..60ece571d6456e58256c79ac6157e6212a1f4b38 100644
--- a/storage/bdb/clib/memmove.c
+++ b/storage/bdb/clib/memmove.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -31,14 +31,12 @@
  * 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.
+ *
+ * $Id: memmove.c,v 11.8 2004/01/28 03:35:52 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: memmove.c,v 11.6 2002/01/11 15:51:28 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #endif
diff --git a/storage/bdb/clib/raise.c b/storage/bdb/clib/raise.c
index fcf3bbcbd7f103dc1b0794cf3d9cb51f8cae0a24..2f9e8cb800ed2ab5a1641d48aac5790bba41c979 100644
--- a/storage/bdb/clib/raise.c
+++ b/storage/bdb/clib/raise.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: raise.c,v 11.8 2004/01/28 03:35:52 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: raise.c,v 11.6 2002/01/11 15:51:28 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <signal.h>
 #include <unistd.h>
diff --git a/storage/bdb/clib/snprintf.c b/storage/bdb/clib/snprintf.c
index fa1a63425e85f7d6d944812a2be2aa992ddea33a..e1bc5d112444a612729cd11666edc8bad1336786 100644
--- a/storage/bdb/clib/snprintf.c
+++ b/storage/bdb/clib/snprintf.c
@@ -1,24 +1,30 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: snprintf.c,v 11.18 2004/09/22 03:32:43 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: snprintf.c,v 11.10 2002/01/11 15:51:28 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>				/* Declare STDERR_FILENO. */
 #endif
 
 #include "db_int.h"
 
+#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
+static void sprintf_overflow __P((void));
+static int  sprintf_retcharpnt __P((void));
+#endif
+
 /*
  * snprintf --
  *	Bounded version of sprintf.
@@ -29,7 +35,7 @@ static const char revid[] = "$Id: snprintf.c,v 11.10 2002/01/11 15:51:28 bostic
  */
 #ifndef HAVE_SNPRINTF
 int
-#ifdef __STDC__
+#ifdef STDC_HEADERS
 snprintf(char *str, size_t n, const char *fmt, ...)
 #else
 snprintf(str, n, fmt, va_alist)
@@ -41,9 +47,98 @@ snprintf(str, n, fmt, va_alist)
 {
 	static int ret_charpnt = -1;
 	va_list ap;
-	int len;
+	size_t len;
+
+	if (ret_charpnt == -1)
+		ret_charpnt = sprintf_retcharpnt();
+
+#ifdef STDC_HEADERS
+	va_start(ap, fmt);
+#else
+	va_start(ap);
+#endif
+	len = (size_t)vsprintf(str, fmt, ap);
+	if (ret_charpnt)
+		len = strlen(str);
+
+	va_end(ap);
+
+	if (len >= n) {
+		sprintf_overflow();
+		/* NOTREACHED */
+	}
+	return ((int)len);
+}
+#endif
+
+/*
+ * vsnprintf --
+ *	Bounded version of vsprintf.
+ *
+ * PUBLIC: #ifndef HAVE_VSNPRINTF
+ * PUBLIC: int vsnprintf __P((char *, size_t, const char *, va_list));
+ * PUBLIC: #endif
+ */
+#ifndef HAVE_VSNPRINTF
+int
+vsnprintf(str, n, fmt, ap)
+	char *str;
+	size_t n;
+	const char *fmt;
+	va_list ap;
+{
+	static int ret_charpnt = -1;
+	size_t len;
+
+	if (ret_charpnt == -1)
+		ret_charpnt = sprintf_retcharpnt();
 
-	COMPQUIET(n, 0);
+	len = (size_t)vsprintf(str, fmt, ap);
+	if (ret_charpnt)
+		len = strlen(str);
+
+	if (len >= n) {
+		sprintf_overflow();
+		/* NOTREACHED */
+	}
+	return ((int)len);
+}
+#endif
+
+#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
+static void
+sprintf_overflow()
+{
+	/*
+	 * !!!
+	 * We're potentially manipulating strings handed us by the application,
+	 * and on systems without a real snprintf() the sprintf() calls could
+	 * have overflowed the buffer.  We can't do anything about it now, but
+	 * we don't want to return control to the application, we might have
+	 * overwritten the stack with a Trojan horse.  We're not trying to do
+	 * anything recoverable here because systems without snprintf support
+	 * are pretty rare anymore.
+	 */
+#define	OVERFLOW_ERROR	"internal buffer overflow, process ended\n"
+#ifndef	STDERR_FILENO
+#define	STDERR_FILENO	2
+#endif
+	(void)write(STDERR_FILENO, OVERFLOW_ERROR, sizeof(OVERFLOW_ERROR) - 1);
+
+	/* Be polite. */
+	exit(1);
+
+	/* But firm. */
+	abort();
+
+	/* NOTREACHED */
+}
+
+static int
+sprintf_retcharpnt()
+{
+	int ret_charpnt;
+	char buf[10];
 
 	/*
 	 * Some old versions of sprintf return a pointer to the first argument
@@ -53,22 +148,12 @@ snprintf(str, n, fmt, va_alist)
 	 * We do this test at run-time because it's not a test we can do in a
 	 * cross-compilation environment.
 	 */
-	if (ret_charpnt == -1) {
-		char buf[10];
 
-		ret_charpnt =
-		    sprintf(buf, "123") != 3 ||
-		    sprintf(buf, "123456789") != 9 ||
-		    sprintf(buf, "1234") != 4;
-	}
+	ret_charpnt =
+	    (int)sprintf(buf, "123") != 3 ||
+	    (int)sprintf(buf, "123456789") != 9 ||
+	    (int)sprintf(buf, "1234") != 4;
 
-#ifdef __STDC__
-	va_start(ap, fmt);
-#else
-	va_start(ap);
-#endif
-	len = vsprintf(str, fmt, ap);
-	va_end(ap);
-	return (ret_charpnt ? (int)strlen(str) : len);
+	return (ret_charpnt);
 }
 #endif
diff --git a/storage/bdb/clib/strcasecmp.c b/storage/bdb/clib/strcasecmp.c
index d5ce6d76d5ffb4de77a5cd21416901d1a21e3580..e8365c4519a939c671a0d3f99c4ea8d7fe5a87d5 100644
--- a/storage/bdb/clib/strcasecmp.c
+++ b/storage/bdb/clib/strcasecmp.c
@@ -29,14 +29,12 @@
  * 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.
+ *
+ * $Id: strcasecmp.c,v 1.8 2004/01/28 03:35:52 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: strcasecmp.c,v 1.7 2001/11/15 17:51:38 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <string.h>
 #endif
diff --git a/storage/bdb/clib/strdup.c b/storage/bdb/clib/strdup.c
index e68623f1407ec178506efca01ec5d4e44e8e0d42..9c451d3287aa048dbe17d79f18c0de9b3d083638 100644
--- a/storage/bdb/clib/strdup.c
+++ b/storage/bdb/clib/strdup.c
@@ -29,14 +29,12 @@
  * 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.
+ *
+ * $Id: strdup.c,v 1.6 2004/01/28 03:35:52 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: strdup.c,v 1.5 2002/05/01 18:40:05 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
diff --git a/storage/bdb/clib/strerror.c b/storage/bdb/clib/strerror.c
index 06c28946b888a49f24c840e6e7e1e6b9dd593ff5..e0710add26c268ab2984f3bf9d530bb096cf54e6 100644
--- a/storage/bdb/clib/strerror.c
+++ b/storage/bdb/clib/strerror.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -31,14 +31,12 @@
  * 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.
+ *
+ * $Id: strerror.c,v 11.8 2004/01/28 03:35:52 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: strerror.c,v 11.6 2002/01/11 15:51:29 bostic Exp $";
-#endif /* not lint */
-
 /*
  * strerror --
  *	Return the string associated with an errno.
diff --git a/storage/bdb/clib/strtol.c b/storage/bdb/clib/strtol.c
new file mode 100644
index 0000000000000000000000000000000000000000..09e952dc5f859e75db8fb13a0a427641e538899d
--- /dev/null
+++ b/storage/bdb/clib/strtol.c
@@ -0,0 +1,144 @@
+/*-
+ * Copyright (c) 1990, 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.
+ *
+ * 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.
+ *
+ * $Id: strtol.c,v 1.3 2004/10/28 19:27:19 bostic Exp $
+ */
+
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <limits.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#endif
+
+/*
+ * Convert a string to a long integer.
+ *
+ * Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+long
+strtol(nptr, endptr, base)
+	const char * nptr;
+	char ** endptr;
+	int base;
+{
+	const char *s;
+	unsigned long acc;
+	char c;
+	unsigned long cutoff;
+	int neg, any, cutlim;
+
+	/*
+	 * Skip white space and pick up leading +/- sign if any.
+	 * If base is 0, allow 0x for hex and 0 for octal, else
+	 * assume decimal; if base is already 16, allow 0x.
+	 */
+	s = nptr;
+	do {
+		c = *s++;
+	} while (isspace((unsigned char)c));
+	if (c == '-') {
+		neg = 1;
+		c = *s++;
+	} else {
+		neg = 0;
+		if (c == '+')
+			c = *s++;
+	}
+	if ((base == 0 || base == 16) &&
+	    c == '0' && (*s == 'x' || *s == 'X')) {
+		c = s[1];
+		s += 2;
+		base = 16;
+	}
+	if (base == 0)
+		base = c == '0' ? 8 : 10;
+	acc = any = 0;
+	if (base < 2 || base > 36)
+		goto noconv;
+
+	/*
+	 * Compute the cutoff value between legal numbers and illegal
+	 * numbers.  That is the largest legal value, divided by the
+	 * base.  An input number that is greater than this value, if
+	 * followed by a legal input character, is too big.  One that
+	 * is equal to this value may be valid or not; the limit
+	 * between valid and invalid numbers is then based on the last
+	 * digit.  For instance, if the range for longs is
+	 * [-2147483648..2147483647] and the input base is 10,
+	 * cutoff will be set to 214748364 and cutlim to either
+	 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
+	 * a value > 214748364, or equal but the next digit is > 7 (or 8),
+	 * the number is too big, and we will return a range error.
+	 *
+	 * Set 'any' if any `digits' consumed; make it negative to indicate
+	 * overflow.
+	 */
+	cutoff = neg ? (unsigned long)-(LONG_MIN + LONG_MAX) + LONG_MAX
+	    : LONG_MAX;
+	cutlim = cutoff % base;
+	cutoff /= base;
+	for ( ; ; c = *s++) {
+		if (c >= '0' && c <= '9')
+			c -= '0';
+		else if (c >= 'A' && c <= 'Z')
+			c -= 'A' - 10;
+		else if (c >= 'a' && c <= 'z')
+			c -= 'a' - 10;
+		else
+			break;
+		if (c >= base)
+			break;
+		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+			any = -1;
+		else {
+			any = 1;
+			acc *= base;
+			acc += c;
+		}
+	}
+	if (any < 0) {
+		acc = neg ? LONG_MIN : LONG_MAX;
+		errno = ERANGE;
+	} else if (!any) {
+noconv:
+		errno = EINVAL;
+	} else if (neg)
+		acc = -acc;
+	if (endptr != NULL)
+		*endptr = (char *)(any ? s - 1 : nptr);
+	return (acc);
+}
diff --git a/storage/bdb/clib/strtoul.c b/storage/bdb/clib/strtoul.c
new file mode 100644
index 0000000000000000000000000000000000000000..e4356963ba08d3f7aecc47be448147a8b52cd39e
--- /dev/null
+++ b/storage/bdb/clib/strtoul.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 1990, 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.
+ *
+ * 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.
+ *
+ * $Id: strtoul.c,v 1.3 2004/10/28 19:27:19 bostic Exp $
+ */
+
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <limits.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#endif
+
+/*
+ * Convert a string to an unsigned long integer.
+ *
+ * Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+unsigned long
+strtoul(nptr, endptr, base)
+	const char * nptr;
+	char ** endptr;
+	int base;
+{
+	const char *s;
+	unsigned long acc;
+	char c;
+	unsigned long cutoff;
+	int neg, any, cutlim;
+
+	/*
+	 * See strtol for comments as to the logic used.
+	 */
+	s = nptr;
+	do {
+		c = *s++;
+	} while (isspace((unsigned char)c));
+	if (c == '-') {
+		neg = 1;
+		c = *s++;
+	} else {
+		neg = 0;
+		if (c == '+')
+			c = *s++;
+	}
+	if ((base == 0 || base == 16) &&
+	    c == '0' && (*s == 'x' || *s == 'X')) {
+		c = s[1];
+		s += 2;
+		base = 16;
+	}
+	if (base == 0)
+		base = c == '0' ? 8 : 10;
+	acc = any = 0;
+	if (base < 2 || base > 36)
+		goto noconv;
+
+	cutoff = ULONG_MAX / base;
+	cutlim = ULONG_MAX % base;
+	for ( ; ; c = *s++) {
+		if (c >= '0' && c <= '9')
+			c -= '0';
+		else if (c >= 'A' && c <= 'Z')
+			c -= 'A' - 10;
+		else if (c >= 'a' && c <= 'z')
+			c -= 'a' - 10;
+		else
+			break;
+		if (c >= base)
+			break;
+		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+			any = -1;
+		else {
+			any = 1;
+			acc *= base;
+			acc += c;
+		}
+	}
+	if (any < 0) {
+		acc = ULONG_MAX;
+		errno = ERANGE;
+	} else if (!any) {
+noconv:
+		errno = EINVAL;
+	} else if (neg)
+		acc = -acc;
+	if (endptr != NULL)
+		*endptr = (char *)(any ? s - 1 : nptr);
+	return (acc);
+}
diff --git a/storage/bdb/common/crypto_stub.c b/storage/bdb/common/crypto_stub.c
new file mode 100644
index 0000000000000000000000000000000000000000..68f06b4c8a6c621d73dfd3e548edc52ff73daa90
--- /dev/null
+++ b/storage/bdb/common/crypto_stub.c
@@ -0,0 +1,45 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: crypto_stub.c,v 1.4 2004/01/28 03:35:52 bostic Exp $
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+/*
+ * __crypto_region_init --
+ *	Initialize crypto.
+ *
+ *
+ * !!!
+ * We don't put this stub file in the crypto/ directory of the distribution
+ * because that entire directory is removed for non-crypto distributions.
+ *
+ * PUBLIC: int __crypto_region_init __P((DB_ENV *));
+ */
+int
+__crypto_region_init(dbenv)
+	DB_ENV *dbenv;
+{
+	REGENV *renv;
+	REGINFO *infop;
+	int ret;
+
+	infop = dbenv->reginfo;
+	renv = infop->primary;
+	MUTEX_LOCK(dbenv, &renv->mutex);
+	ret = !(renv->cipher_off == INVALID_ROFF);
+	MUTEX_UNLOCK(dbenv, &renv->mutex);
+
+	if (ret == 0)
+		return (0);
+
+	__db_err(dbenv,
+"Encrypted environment: library build did not include cryptography support");
+	return (DB_OPNOTSUP);
+}
diff --git a/storage/bdb/common/db_byteorder.c b/storage/bdb/common/db_byteorder.c
index d42d8e6a9587c7ac081a6d1f84a50fa62a4e72dd..0a48055c8e06d3521636146886c18b451fee8604 100644
--- a/storage/bdb/common/db_byteorder.c
+++ b/storage/bdb/common/db_byteorder.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_byteorder.c,v 11.10 2004/01/28 03:35:52 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_byteorder.c,v 11.8 2002/02/01 18:15:29 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #endif
diff --git a/storage/bdb/common/db_err.c b/storage/bdb/common/db_err.c
index 7c9ee3c4fdea7653fff614e1c128db2414cf9542..6e49e79411cb519b2fd65bac9d1c96d407924dc2 100644
--- a/storage/bdb/common/db_err.c
+++ b/storage/bdb/common/db_err.c
@@ -1,20 +1,17 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_err.c,v 11.123 2004/09/22 03:07:50 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_err.c,v 11.80 2002/07/30 01:21:53 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #endif
@@ -27,6 +24,9 @@ static const char revid[] = "$Id: db_err.c,v 11.80 2002/07/30 01:21:53 bostic Ex
 #include "dbinc/log.h"
 #include "dbinc/txn.h"
 
+static void __db_msgcall __P((const DB_ENV *, const char *, va_list));
+static void __db_msgfile __P((const DB_ENV *, const char *, va_list));
+
 /*
  * __db_fchk --
  *	General flags checking routine.
@@ -76,13 +76,30 @@ __db_ferr(dbenv, name, iscombo)
 	return (EINVAL);
 }
 
+/*
+ * __db_fnl --
+ *	Common flag-needs-locking message.
+ *
+ * PUBLIC: int __db_fnl __P((const DB_ENV *, const char *));
+ */
+int
+__db_fnl(dbenv, name)
+	const DB_ENV *dbenv;
+	const char *name;
+{
+	__db_err(dbenv,
+    "%s: the DB_DIRTY_READ, DB_DEGREE_2 and DB_RMW flags require locking",
+	    name);
+	return (EINVAL);
+}
+
 /*
  * __db_pgerr --
  *	Error when unable to retrieve a specified page.
  *
- * PUBLIC: void __db_pgerr __P((DB *, db_pgno_t, int));
+ * PUBLIC: int __db_pgerr __P((DB *, db_pgno_t, int));
  */
-void
+int
 __db_pgerr(dbp, pgno, errval)
 	DB *dbp;
 	db_pgno_t pgno;
@@ -95,7 +112,7 @@ __db_pgerr(dbp, pgno, errval)
 	 */
 	__db_err(dbp->dbenv,
 	    "unable to create/retrieve page %lu", (u_long)pgno);
-	(void)__db_panic(dbp->dbenv, errval);
+	return (__db_panic(dbp->dbenv, errval));
 }
 
 /*
@@ -113,24 +130,6 @@ __db_pgfmt(dbenv, pgno)
 	return (__db_panic(dbenv, EINVAL));
 }
 
-/*
- * __db_eopnotsup --
- *	Common operation not supported message.
- *
- * PUBLIC: int __db_eopnotsup __P((const DB_ENV *));
- */
-int
-__db_eopnotsup(dbenv)
-	const DB_ENV *dbenv;
-{
-	__db_err(dbenv, "operation not supported");
-#ifdef EOPNOTSUPP
-	return (EOPNOTSUPP);
-#else
-	return (EINVAL);
-#endif
-}
-
 #ifdef DIAGNOSTIC
 /*
  * __db_assert --
@@ -167,7 +166,11 @@ int
 __db_panic_msg(dbenv)
 	DB_ENV *dbenv;
 {
-	__db_err(dbenv, "fatal region error detected; run recovery");
+	__db_err(dbenv, "PANIC: fatal region error detected; run recovery");
+
+	if (dbenv->db_paniccall != NULL)
+		dbenv->db_paniccall(dbenv, DB_RUNRECOVERY);
+
 	return (DB_RUNRECOVERY);
 }
 
@@ -185,8 +188,6 @@ __db_panic(dbenv, errval)
 	if (dbenv != NULL) {
 		PANIC_SET(dbenv, 1);
 
-		dbenv->panic_errval = errval;
-
 		__db_err(dbenv, "PANIC: %s", db_strerror(errval));
 
 		if (dbenv->db_paniccall != NULL)
@@ -222,10 +223,15 @@ char *
 db_strerror(error)
 	int error;
 {
+	char *p;
+
 	if (error == 0)
 		return ("Successful return: 0");
-	if (error > 0)
-		return (strerror(error));
+	if (error > 0) {
+		if ((p = strerror(error)) != NULL)
+			return (p);
+		goto unknown_err;
+	}
 
 	/*
 	 * !!!
@@ -235,6 +241,9 @@ db_strerror(error)
 	 * altered.
 	 */
 	switch (error) {
+	case DB_BUFFER_SMALL:
+		return
+		    ("DB_BUFFER_SMALL: User memory too small for return value");
 	case DB_DONOTINDEX:
 		return ("DB_DONOTINDEX: Secondary index callback returns null");
 	case DB_KEYEMPTY:
@@ -246,8 +255,10 @@ db_strerror(error)
 		    ("DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock");
 	case DB_LOCK_NOTGRANTED:
 		return ("DB_LOCK_NOTGRANTED: Lock not granted");
+	case DB_LOG_BUFFER_FULL:
+		return ("DB_LOG_BUFFER_FULL: In-memory log buffer is full");
 	case DB_NOSERVER:
-		return ("DB_NOSERVER: Fatal error, no server");
+		return ("DB_NOSERVER: Fatal error, no RPC server");
 	case DB_NOSERVER_HOME:
 		return ("DB_NOSERVER_HOME: Home unrecognized at server");
 	case DB_NOSERVER_ID:
@@ -260,25 +271,38 @@ db_strerror(error)
 		return ("DB_PAGE_NOTFOUND: Requested page not found");
 	case DB_REP_DUPMASTER:
 		return ("DB_REP_DUPMASTER: A second master site appeared");
+	case DB_REP_HANDLE_DEAD:
+		return ("DB_REP_HANDLE_DEAD: Handle is no longer valid");
 	case DB_REP_HOLDELECTION:
 		return ("DB_REP_HOLDELECTION: Need to hold an election");
+	case DB_REP_ISPERM:
+		return ("DB_REP_ISPERM: Permanent record written");
 	case DB_REP_NEWMASTER:
 		return ("DB_REP_NEWMASTER: A new master has declared itself");
 	case DB_REP_NEWSITE:
 		return ("DB_REP_NEWSITE: A new site has entered the system");
-	case DB_REP_OUTDATED:
+	case DB_REP_NOTPERM:
+		return ("DB_REP_NOTPERM: Permanent log record not written");
+	case DB_REP_STARTUPDONE:
 		return
-		    ("DB_REP_OUTDATED: Insufficient logs on master to recover");
+	    ("DB_REP_STARTUPDONE: Client completed startup synchronization.");
 	case DB_REP_UNAVAIL:
 		return ("DB_REP_UNAVAIL: Unable to elect a master");
 	case DB_RUNRECOVERY:
 		return ("DB_RUNRECOVERY: Fatal error, run database recovery");
 	case DB_SECONDARY_BAD:
 		return
-	    ("DB_SECONDARY_BAD: Secondary index item missing from primary");
+	    ("DB_SECONDARY_BAD: Secondary index inconsistent with primary");
 	case DB_VERIFY_BAD:
 		return ("DB_VERIFY_BAD: Database verification failed");
-	default: {
+	case DB_VERSION_MISMATCH:
+		return
+	    ("DB_VERSION_MISMATCH: Database environment version mismatch");
+	default:
+		break;
+	}
+
+unknown_err: {
 		/*
 		 * !!!
 		 * Room for a 64-bit number + slop.  This buffer is only used
@@ -290,7 +314,6 @@ db_strerror(error)
 		(void)snprintf(ebuf, sizeof(ebuf), "Unknown error: %d", error);
 		return (ebuf);
 	}
-	}
 }
 
 /*
@@ -298,10 +321,11 @@ db_strerror(error)
  *	Standard DB error routine.  The same as errx, except we don't write
  *	to stderr if no output mechanism was specified.
  *
- * PUBLIC: void __db_err __P((const DB_ENV *, const char *, ...));
+ * PUBLIC: void __db_err __P((const DB_ENV *, const char *, ...))
+ * PUBLIC:    __attribute__ ((__format__ (__printf__, 2, 3)));
  */
 void
-#ifdef __STDC__
+#ifdef STDC_HEADERS
 __db_err(const DB_ENV *dbenv, const char *fmt, ...)
 #else
 __db_err(dbenv, fmt, va_alist)
@@ -328,34 +352,17 @@ __db_errcall(dbenv, error, error_set, fmt, ap)
 	va_list ap;
 {
 	char *p;
-	char errbuf[2048];	/* !!!: END OF THE STACK DON'T TRUST SPRINTF. */
+	char buf[2048];		/* !!!: END OF THE STACK DON'T TRUST SPRINTF. */
 
-	p = errbuf;
+	p = buf;
 	if (fmt != NULL)
-		p += vsnprintf(errbuf, sizeof(errbuf), fmt, ap);
+		p += vsnprintf(buf, sizeof(buf), fmt, ap);
 	if (error_set)
 		p += snprintf(p,
-		    sizeof(errbuf) - (p - errbuf), ": %s", db_strerror(error));
-	/*
-	 * !!!
-	 * We're potentially manipulating strings handed us by the application,
-	 * and on systems without a real snprintf() the sprintf() calls could
-	 * have overflowed the buffer.  We can't do anything about it now, but
-	 * we don't want to return control to the application, we might have
-	 * overwritten the stack with a Trojan horse.  We're not trying to do
-	 * anything recoverable here because systems without snprintf support
-	 * are pretty rare anymore.
-	 */
-	if ((size_t)(p - errbuf) > sizeof(errbuf)) {
-		(void)fprintf(stderr,
-		    "Berkeley DB: error callback interface buffer overflow\n");
-		(void)fflush(stderr);
+		    sizeof(buf) - (size_t)(p - buf), ": %s",
+		    db_strerror(error));
 
-		abort();
-		/* NOTREACHED */
-	}
-
-	dbenv->db_errcall(dbenv->db_errpfx, errbuf);
+	dbenv->db_errcall(dbenv, dbenv->db_errpfx, buf);
 }
 
 /*
@@ -390,15 +397,121 @@ __db_errfile(dbenv, error, error_set, fmt, ap)
 	(void)fflush(fp);
 }
 
+/*
+ * __db_msgadd --
+ *	Aggregate a set of strings into a buffer for the callback API.
+ *
+ * PUBLIC: void __db_msgadd __P((DB_ENV *, DB_MSGBUF *, const char *, ...))
+ * PUBLIC:    __attribute__ ((__format__ (__printf__, 3, 4)));
+ */
+void
+#ifdef STDC_HEADERS
+__db_msgadd(DB_ENV *dbenv, DB_MSGBUF *mbp, const char *fmt, ...)
+#else
+__db_msgadd(dbenv, mbp, fmt, va_alist)
+	DB_ENV *dbenv;
+	DB_MSGBUF *mbp;
+	const char *fmt;
+	va_dcl
+#endif
+{
+	va_list ap;
+	size_t len, olen;
+	char buf[2048];		/* !!!: END OF THE STACK DON'T TRUST SPRINTF. */
+
+#ifdef STDC_HEADERS
+	va_start(ap, fmt);
+#else
+	va_start(ap);
+#endif
+	len = (size_t)vsnprintf(buf, sizeof(buf), fmt, ap);
+
+	va_end(ap);
+
+	/*
+	 * There's a heap buffer in the DB_ENV handle we use to aggregate the
+	 * message chunks.  We maintain a pointer to the buffer, the next slot
+	 * to be filled in in the buffer, and a total buffer length.
+	 */
+	olen = (size_t)(mbp->cur - mbp->buf);
+	if (olen + len >= mbp->len) {
+		if (__os_realloc(dbenv, mbp->len + len + 256, &mbp->buf))
+			return;
+		mbp->len += (len + 256);
+		mbp->cur = mbp->buf + olen;
+	}
+
+	memcpy(mbp->cur, buf, len + 1);
+	mbp->cur += len;
+}
+
+/*
+ * __db_msg --
+ *	Standard DB stat message routine.
+ *
+ * PUBLIC: void __db_msg __P((const DB_ENV *, const char *, ...))
+ * PUBLIC:    __attribute__ ((__format__ (__printf__, 2, 3)));
+ */
+void
+#ifdef STDC_HEADERS
+__db_msg(const DB_ENV *dbenv, const char *fmt, ...)
+#else
+__db_msg(dbenv, fmt, va_alist)
+	const DB_ENV *dbenv;
+	const char *fmt;
+	va_dcl
+#endif
+{
+	DB_REAL_MSG(dbenv, fmt);
+}
+
+/*
+ * __db_msgcall --
+ *	Do the message work for callback functions.
+ */
+static void
+__db_msgcall(dbenv, fmt, ap)
+	const DB_ENV *dbenv;
+	const char *fmt;
+	va_list ap;
+{
+	char buf[2048];		/* !!!: END OF THE STACK DON'T TRUST SPRINTF. */
+
+	(void)vsnprintf(buf, sizeof(buf), fmt, ap);
+
+	dbenv->db_msgcall(dbenv, buf);
+}
+
+/*
+ * __db_msgfile --
+ *	Do the message work for FILE *s.
+ */
+static void
+__db_msgfile(dbenv, fmt, ap)
+	const DB_ENV *dbenv;
+	const char *fmt;
+	va_list ap;
+{
+	FILE *fp;
+
+	fp = dbenv == NULL ||
+	    dbenv->db_msgfile == NULL ? stdout : dbenv->db_msgfile;
+	(void)vfprintf(fp, fmt, ap);
+
+	(void)fprintf(fp, "\n");
+	(void)fflush(fp);
+}
+
 /*
  * __db_logmsg --
  *	Write information into the DB log.
  *
  * PUBLIC: void __db_logmsg __P((const DB_ENV *,
- * PUBLIC:     DB_TXN *, const char *, u_int32_t, const char *, ...));
+ * PUBLIC:     DB_TXN *, const char *, u_int32_t, const char *, ...))
+ * PUBLIC:    __attribute__ ((__format__ (__printf__, 5, 6)));
  */
 void
-#ifdef __STDC__
+#ifdef STDC_HEADERS
 __db_logmsg(const DB_ENV *dbenv,
     DB_TXN *txnid, const char *opname, u_int32_t flags, const char *fmt, ...)
 #else
@@ -418,7 +531,7 @@ __db_logmsg(dbenv, txnid, opname, flags, fmt, va_alist)
 	if (!LOGGING_ON(dbenv))
 		return;
 
-#ifdef __STDC__
+#ifdef STDC_HEADERS
 	va_start(ap, fmt);
 #else
 	va_start(ap);
@@ -429,17 +542,17 @@ __db_logmsg(dbenv, txnid, opname, flags, fmt, va_alist)
 
 	memset(&msgdbt, 0, sizeof(msgdbt));
 	msgdbt.data = __logbuf;
-	msgdbt.size = vsnprintf(__logbuf, sizeof(__logbuf), fmt, ap);
+	msgdbt.size = (u_int32_t)vsnprintf(__logbuf, sizeof(__logbuf), fmt, ap);
+
+	va_end(ap);
 
 	/*
 	 * XXX
 	 * Explicitly discard the const.  Otherwise, we have to const DB_ENV
 	 * references throughout the logging subsystem.
 	 */
-	__db_debug_log(
+	(void)__db_debug_log(
 	    (DB_ENV *)dbenv, txnid, &lsn, flags, &opdbt, -1, &msgdbt, NULL, 0);
-
-	va_end(ap);
 }
 
 /*
@@ -453,7 +566,7 @@ __db_unknown_flag(dbenv, routine, flag)
 	char *routine;
 	u_int32_t flag;
 {
-	__db_err(dbenv, "%s: Unknown flag: 0x%x", routine, flag);
+	__db_err(dbenv, "%s: Unknown flag: %#x", routine, (u_int)flag);
 	DB_ASSERT(0);
 	return (EINVAL);
 }
@@ -469,7 +582,9 @@ __db_unknown_type(dbenv, routine, type)
 	char *routine;
 	DBTYPE type;
 {
-	__db_err(dbenv, "%s: Unknown db type: 0x%x", routine, type);
+	__db_err(dbenv,
+	    "%s: Unexpected DB type: %s", routine, __db_dbtype_to_string(type));
+
 	DB_ASSERT(0);
 	return (EINVAL);
 }
@@ -488,6 +603,7 @@ __db_check_txn(dbp, txn, assoc_lid, read_op)
 	int read_op;
 {
 	DB_ENV *dbenv;
+	int isp, ret;
 
 	dbenv = dbp->dbenv;
 
@@ -522,8 +638,19 @@ __db_check_txn(dbp, txn, assoc_lid, read_op)
 		if (dbp->cur_lid >= TXN_MINIMUM)
 			goto open_err;
 	} else {
-		if (dbp->cur_lid >= TXN_MINIMUM && dbp->cur_lid != txn->txnid)
-			goto open_err;
+		if (F_ISSET(txn, TXN_DEADLOCK)) {
+			__db_err(dbenv,
+			    "Previous deadlock return not resolved");
+			return (EINVAL);
+		}
+		if (dbp->cur_lid >= TXN_MINIMUM &&
+		    dbp->cur_lid != txn->txnid) {
+			if ((ret = __lock_locker_is_parent(dbenv,
+			     dbp->cur_lid, txn->txnid, &isp)) != 0)
+				return (ret);
+			if (!isp)
+				goto open_err;
+		}
 
 		if (!TXN_ON(dbenv))
 			 return (__db_not_txn_env(dbenv));
@@ -577,3 +704,54 @@ __db_not_txn_env(dbenv)
 	__db_err(dbenv, "DB environment not configured for transactions");
 	return (EINVAL);
 }
+
+/*
+ * __db_rec_toobig --
+ *	Fixed record length exceeded error message.
+ *
+ * PUBLIC: int __db_rec_toobig __P((DB_ENV *, u_int32_t, u_int32_t));
+ */
+int
+__db_rec_toobig(dbenv, data_len, fixed_rec_len)
+	DB_ENV *dbenv;
+	u_int32_t data_len, fixed_rec_len;
+{
+	__db_err(dbenv, "%s: length of %lu larger than database's value of %lu",
+	    "Record length error", (u_long)data_len, (u_long)fixed_rec_len);
+	return (EINVAL);
+}
+
+/*
+ * __db_rec_repl --
+ *	Fixed record replacement length error message.
+ *
+ * PUBLIC: int __db_rec_repl __P((DB_ENV *, u_int32_t, u_int32_t));
+ */
+int
+__db_rec_repl(dbenv, data_size, data_dlen)
+	DB_ENV *dbenv;
+	u_int32_t data_size, data_dlen;
+{
+	__db_err(dbenv,
+	    "%s: replacement length %lu differs from replaced length %lu",
+	    "Record length error", (u_long)data_size, (u_long)data_dlen);
+	return (EINVAL);
+}
+
+/*
+ * __db_check_lsn --
+ *	Display the log sequence error message.
+ *
+ * PUBLIC: int __db_check_lsn __P((DB_ENV *, DB_LSN *, DB_LSN *));
+ */
+int
+__db_check_lsn(dbenv, lsn, prev)
+	DB_ENV *dbenv;
+	DB_LSN *lsn, *prev;
+{
+	__db_err(dbenv,
+	    "Log sequence error: page LSN %lu %lu; previous LSN %lu %lu",
+	    (u_long)(lsn)->file, (u_long)(lsn)->offset,
+	    (u_long)(prev)->file, (u_long)(prev)->offset);
+	return (EINVAL);
+}
diff --git a/storage/bdb/common/db_getlong.c b/storage/bdb/common/db_getlong.c
index 6ba8ebfcdaa48f7b834799fdb198e1cc8c657481..be70f0d4a60a443a723084a933231fcb5cc559a4 100644
--- a/storage/bdb/common/db_getlong.c
+++ b/storage/bdb/common/db_getlong.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_getlong.c,v 11.22 2004/10/28 14:43:26 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_getlong.c,v 11.18 2002/03/28 20:13:33 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -26,11 +24,11 @@ static const char revid[] = "$Id: db_getlong.c,v 11.18 2002/03/28 20:13:33 bosti
  *	Return a long value inside of basic parameters.
  *
  * PUBLIC: int __db_getlong
- * PUBLIC:     __P((DB *, const char *, char *, long, long, long *));
+ * PUBLIC:     __P((DB_ENV *, const char *, char *, long, long, long *));
  */
 int
-__db_getlong(dbp, progname, p, min, max, storep)
-	DB *dbp;
+__db_getlong(dbenv, progname, p, min, max, storep)
+	DB_ENV *dbenv;
 	const char *progname;
 	char *p;
 	long min, max, *storep;
@@ -42,38 +40,38 @@ __db_getlong(dbp, progname, p, min, max, storep)
 	val = strtol(p, &end, 10);
 	if ((val == LONG_MIN || val == LONG_MAX) &&
 	    __os_get_errno() == ERANGE) {
-		if (dbp == NULL)
+		if (dbenv == NULL)
 			fprintf(stderr,
 			    "%s: %s: %s\n", progname, p, strerror(ERANGE));
 		else
-			dbp->err(dbp, ERANGE, "%s", p);
+			dbenv->err(dbenv, ERANGE, "%s", p);
 		return (1);
 	}
 	if (p[0] == '\0' || (end[0] != '\0' && end[0] != '\n')) {
-		if (dbp == NULL)
+		if (dbenv == NULL)
 			fprintf(stderr,
 			    "%s: %s: Invalid numeric argument\n", progname, p);
 		else
-			dbp->errx(dbp, "%s: Invalid numeric argument", p);
+			dbenv->errx(dbenv, "%s: Invalid numeric argument", p);
 		return (1);
 	}
 	if (val < min) {
-		if (dbp == NULL)
+		if (dbenv == NULL)
 			fprintf(stderr,
 			    "%s: %s: Less than minimum value (%ld)\n",
 			    progname, p, min);
 		else
-			dbp->errx(dbp,
+			dbenv->errx(dbenv,
 			    "%s: Less than minimum value (%ld)", p, min);
 		return (1);
 	}
 	if (val > max) {
-		if (dbp == NULL)
+		if (dbenv == NULL)
 			fprintf(stderr,
 			    "%s: %s: Greater than maximum value (%ld)\n",
 			    progname, p, max);
 		else
-			dbp->errx(dbp,
+			dbenv->errx(dbenv,
 			    "%s: Greater than maximum value (%ld)", p, max);
 		return (1);
 	}
@@ -86,48 +84,43 @@ __db_getlong(dbp, progname, p, min, max, storep)
  *	Return an unsigned long value inside of basic parameters.
  *
  * PUBLIC: int __db_getulong
- * PUBLIC:     __P((DB *, const char *, char *, u_long, u_long, u_long *));
+ * PUBLIC:     __P((DB_ENV *, const char *, char *, u_long, u_long, u_long *));
  */
 int
-__db_getulong(dbp, progname, p, min, max, storep)
-	DB *dbp;
+__db_getulong(dbenv, progname, p, min, max, storep)
+	DB_ENV *dbenv;
 	const char *progname;
 	char *p;
 	u_long min, max, *storep;
 {
-#if !defined(HAVE_STRTOUL)
-	COMPQUIET(min, 0);
-
-	return (__db_getlong(dbp, progname, p, 0, max, (long *)storep));
-#else
 	u_long val;
 	char *end;
 
 	__os_set_errno(0);
 	val = strtoul(p, &end, 10);
 	if (val == ULONG_MAX && __os_get_errno() == ERANGE) {
-		if (dbp == NULL)
+		if (dbenv == NULL)
 			fprintf(stderr,
 			    "%s: %s: %s\n", progname, p, strerror(ERANGE));
 		else
-			dbp->err(dbp, ERANGE, "%s", p);
+			dbenv->err(dbenv, ERANGE, "%s", p);
 		return (1);
 	}
 	if (p[0] == '\0' || (end[0] != '\0' && end[0] != '\n')) {
-		if (dbp == NULL)
+		if (dbenv == NULL)
 			fprintf(stderr,
 			    "%s: %s: Invalid numeric argument\n", progname, p);
 		else
-			dbp->errx(dbp, "%s: Invalid numeric argument", p);
+			dbenv->errx(dbenv, "%s: Invalid numeric argument", p);
 		return (1);
 	}
 	if (val < min) {
-		if (dbp == NULL)
+		if (dbenv == NULL)
 			fprintf(stderr,
 			    "%s: %s: Less than minimum value (%lu)\n",
 			    progname, p, min);
 		else
-			dbp->errx(dbp,
+			dbenv->errx(dbenv,
 			    "%s: Less than minimum value (%lu)", p, min);
 		return (1);
 	}
@@ -139,16 +132,15 @@ __db_getulong(dbp, progname, p, min, max, storep)
 	 * may not exist on all platforms.
 	 */
 	if (max != 0 && val > max) {
-		if (dbp == NULL)
+		if (dbenv == NULL)
 			fprintf(stderr,
 			    "%s: %s: Greater than maximum value (%lu)\n",
 			    progname, p, max);
 		else
-			dbp->errx(dbp,
+			dbenv->errx(dbenv,
 			    "%s: Greater than maximum value (%lu)", p, max);
 		return (1);
 	}
 	*storep = val;
 	return (0);
-#endif	/* !defined(HAVE_STRTOUL) */
 }
diff --git a/storage/bdb/common/db_idspace.c b/storage/bdb/common/db_idspace.c
index 588ffd9fca99ff8d5683b90552840ddafb092b27..49f2e91377bc29269d323fef0dd3f18055aead1b 100644
--- a/storage/bdb/common/db_idspace.c
+++ b/storage/bdb/common/db_idspace.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
+ * Copyright (c) 2001-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_idspace.c,v 1.9 2004/01/28 03:35:52 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_idspace.c,v 1.5 2002/02/01 18:15:29 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -44,7 +42,8 @@ __db_idcmp(a, b)
  *
  * On input, minp and maxp contain the minimum and maximum valid values for
  * the name space and on return, they contain the minimum and maximum ids
- * available (by finding the biggest gap).
+ * available (by finding the biggest gap).  The minimum can be an inuse
+ * value, but the maximum cannot be.
  *
  * PUBLIC: void __db_idspace __P((u_int32_t *, int, u_int32_t *, u_int32_t *));
  */
@@ -73,7 +72,7 @@ __db_idspace(inuse, n, minp, maxp)
 
 	gap = 0;
 	low = 0;
-	qsort(inuse, n, sizeof(u_int32_t), __db_idcmp);
+	qsort(inuse, (size_t)n, sizeof(u_int32_t), __db_idcmp);
 	for (i = 0; i < n - 1; i++)
 		if ((t = (inuse[i + 1] - inuse[i])) > gap) {
 			gap = t;
@@ -85,9 +84,9 @@ __db_idspace(inuse, n, minp, maxp)
 		/* Do same check as we do in the n == 1 case. */
 		if (inuse[n - 1] != *maxp)
 			*minp = inuse[n - 1];
-		*maxp = inuse[0];
+		*maxp = inuse[0] - 1;
 	} else {
 		*minp = inuse[low];
-		*maxp = inuse[low + 1];
+		*maxp = inuse[low + 1] - 1;
 	}
 }
diff --git a/storage/bdb/common/db_log2.c b/storage/bdb/common/db_log2.c
index cdd87dda11dc4afabee40dd64baaffff4c4c2b15..fcc1a603579164fe5a2eda3fd1144f63aa86199c 100644
--- a/storage/bdb/common/db_log2.c
+++ b/storage/bdb/common/db_log2.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -34,14 +34,12 @@
  * 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.
+ *
+ * $Id: db_log2.c,v 11.9 2004/01/28 03:35:52 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_log2.c,v 11.7 2002/02/01 18:15:30 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #endif
diff --git a/storage/bdb/common/util_arg.c b/storage/bdb/common/util_arg.c
index e034e3bd19488cd91ae029e1585919b1b94f999f..16a17ee28d69078616d33fda142873a3d22d9bc0 100644
--- a/storage/bdb/common/util_arg.c
+++ b/storage/bdb/common/util_arg.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
+ * Copyright (c) 2001-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: util_arg.c,v 1.6 2004/01/28 03:35:52 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: util_arg.c,v 1.4 2002/02/01 18:15:30 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #endif
diff --git a/storage/bdb/common/util_cache.c b/storage/bdb/common/util_cache.c
index 5ca88665cc7e93cb60d215f9cf36de6ba8621bcd..006c34557c911534906bf02dfe5b112476484daf 100644
--- a/storage/bdb/common/util_cache.c
+++ b/storage/bdb/common/util_cache.c
@@ -1,23 +1,20 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2000-2002
+ * Copyright (c) 2000-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: util_cache.c,v 1.8 2004/02/17 16:03:05 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: util_cache.c,v 1.3 2002/04/04 18:50:10 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <stdlib.h>
 
 #include <string.h>
-#include <unistd.h>
 #endif
 
 #include "db_int.h"
@@ -26,59 +23,26 @@ static const char revid[] = "$Id: util_cache.c,v 1.3 2002/04/04 18:50:10 bostic
  * __db_util_cache --
  *	Compute if we have enough cache.
  *
- * PUBLIC: int __db_util_cache __P((DB_ENV *, DB *, u_int32_t *, int *));
+ * PUBLIC: int __db_util_cache __P((DB *, u_int32_t *, int *));
  */
 int
-__db_util_cache(dbenv, dbp, cachep, resizep)
-	DB_ENV *dbenv;
+__db_util_cache(dbp, cachep, resizep)
 	DB *dbp;
 	u_int32_t *cachep;
 	int *resizep;
 {
-	DBTYPE type;
-	DB_BTREE_STAT *bsp;
-	DB_HASH_STAT *hsp;
-	DB_QUEUE_STAT *qsp;
 	u_int32_t pgsize;
 	int ret;
-	void *sp;
+
+	/* Get the current page size. */
+	if ((ret = dbp->get_pagesize(dbp, &pgsize)) != 0)
+		return (ret);
 
 	/*
 	 * The current cache size is in cachep.  If it's insufficient, set the
 	 * the memory referenced by resizep to 1 and set cachep to the minimum
 	 * size needed.
-	 */
-	if ((ret = dbp->get_type(dbp, &type)) != 0) {
-		dbenv->err(dbenv, ret, "DB->get_type");
-		return (ret);
-	}
-
-	if ((ret = dbp->stat(dbp, &sp, DB_FAST_STAT)) != 0) {
-		dbenv->err(dbenv, ret, "DB->stat");
-		return (ret);
-	}
-
-	switch (type) {
-	case DB_QUEUE:
-		qsp = (DB_QUEUE_STAT *)sp;
-		pgsize = qsp->qs_pagesize;
-		break;
-	case DB_HASH:
-		hsp = (DB_HASH_STAT *)sp;
-		pgsize = hsp->hash_pagesize;
-		break;
-	case DB_BTREE:
-	case DB_RECNO:
-		bsp = (DB_BTREE_STAT *)sp;
-		pgsize = bsp->bt_pagesize;
-		break;
-	default:
-		dbenv->err(dbenv, ret, "unknown database type: %d", type);
-		return (EINVAL);
-	}
-	free(sp);
-
-	/*
+	 *
 	 * Make sure our current cache is big enough.  We want at least
 	 * DB_MINPAGECACHE pages in the cache.
 	 */
diff --git a/storage/bdb/common/util_log.c b/storage/bdb/common/util_log.c
index ae215fca64a4e86840c231b1475894df358d77bc..98fd1951c069b9d4b1722f2fd2181ffba74cd620 100644
--- a/storage/bdb/common/util_log.c
+++ b/storage/bdb/common/util_log.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2000-2002
+ * Copyright (c) 2000-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: util_log.c,v 1.14 2004/01/28 03:35:52 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: util_log.c,v 1.11 2002/02/01 18:15:30 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -27,7 +25,6 @@ static const char revid[] = "$Id: util_log.c,v 1.11 2002/02/01 18:15:30 bostic E
 #endif
 
 #include <string.h>
-#include <unistd.h>
 #endif
 
 #include "db_int.h"
diff --git a/storage/bdb/common/util_sig.c b/storage/bdb/common/util_sig.c
index 9714427ad337d9d3646cdb0dbd6057afd6db4c97..53087360ee5baf65e7698de1f6ff3a2c549d6d5e 100644
--- a/storage/bdb/common/util_sig.c
+++ b/storage/bdb/common/util_sig.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2000-2002
+ * Copyright (c) 2000-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: util_sig.c,v 1.9 2004/01/28 03:35:54 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: util_sig.c,v 1.7 2002/02/02 17:04:42 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
diff --git a/storage/bdb/crypto/aes_method.c b/storage/bdb/crypto/aes_method.c
new file mode 100644
index 0000000000000000000000000000000000000000..567e67456674a9fbab5bf2d2bde932130ca5cfde
--- /dev/null
+++ b/storage/bdb/crypto/aes_method.c
@@ -0,0 +1,273 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * Some parts of this code originally written by Adam Stubblefield,
+ * -- astubble@rice.edu.
+ *
+ * $Id: aes_method.c,v 1.20 2004/09/17 22:00:25 mjc Exp $
+ */
+
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/crypto.h"
+#include "dbinc/hmac.h"
+
+static void __aes_err __P((DB_ENV *, int));
+static int __aes_derivekeys __P((DB_ENV *, DB_CIPHER *, u_int8_t *, size_t));
+
+/*
+ * __aes_setup --
+ *	Setup AES functions.
+ *
+ * PUBLIC: int __aes_setup __P((DB_ENV *, DB_CIPHER *));
+ */
+int
+__aes_setup(dbenv, db_cipher)
+	DB_ENV *dbenv;
+	DB_CIPHER *db_cipher;
+{
+	AES_CIPHER *aes_cipher;
+	int ret;
+
+	db_cipher->adj_size = __aes_adj_size;
+	db_cipher->close = __aes_close;
+	db_cipher->decrypt = __aes_decrypt;
+	db_cipher->encrypt = __aes_encrypt;
+	db_cipher->init = __aes_init;
+	if ((ret = __os_calloc(dbenv, 1, sizeof(AES_CIPHER), &aes_cipher)) != 0)
+		return (ret);
+	db_cipher->data = aes_cipher;
+	return (0);
+}
+
+/*
+ * __aes_adj_size --
+ *	Given a size, return an addition amount needed to meet the
+ *	"chunk" needs of the algorithm.
+ *
+ * PUBLIC: u_int __aes_adj_size __P((size_t));
+ */
+u_int
+__aes_adj_size(len)
+	size_t len;
+{
+	if (len % DB_AES_CHUNK == 0)
+		return (0);
+	return (DB_AES_CHUNK - (u_int)(len % DB_AES_CHUNK));
+}
+
+/*
+ * __aes_close --
+ *	Destroy the AES encryption instantiation.
+ *
+ * PUBLIC: int __aes_close __P((DB_ENV *, void *));
+ */
+int
+__aes_close(dbenv, data)
+	DB_ENV *dbenv;
+	void *data;
+{
+	__os_free(dbenv, data);
+	return (0);
+}
+
+/*
+ * __aes_decrypt --
+ *	Decrypt data with AES.
+ *
+ * PUBLIC: int __aes_decrypt __P((DB_ENV *, void *, void *,
+ * PUBLIC:     u_int8_t *, size_t));
+ */
+int
+__aes_decrypt(dbenv, aes_data, iv, cipher, cipher_len)
+	DB_ENV *dbenv;
+	void *aes_data;
+	void *iv;
+	u_int8_t *cipher;
+	size_t cipher_len;
+{
+	AES_CIPHER *aes;
+	cipherInstance c;
+	int ret;
+
+	aes = (AES_CIPHER *)aes_data;
+	if (iv == NULL || cipher == NULL)
+		return (EINVAL);
+	if ((cipher_len % DB_AES_CHUNK) != 0)
+		return (EINVAL);
+	/*
+	 * Initialize the cipher
+	 */
+	if ((ret = __db_cipherInit(&c, MODE_CBC, iv)) < 0) {
+		__aes_err(dbenv, ret);
+		return (EAGAIN);
+	}
+
+	/* Do the decryption */
+	if ((ret = __db_blockDecrypt(&c, &aes->decrypt_ki, cipher,
+	    cipher_len * 8, cipher)) < 0) {
+		__aes_err(dbenv, ret);
+		return (EAGAIN);
+	}
+	return (0);
+}
+
+/*
+ * __aes_encrypt --
+ *	Encrypt data with AES.
+ *
+ * PUBLIC: int __aes_encrypt __P((DB_ENV *, void *, void *,
+ * PUBLIC:     u_int8_t *, size_t));
+ */
+int
+__aes_encrypt(dbenv, aes_data, iv, data, data_len)
+	DB_ENV *dbenv;
+	void *aes_data;
+	void *iv;
+	u_int8_t *data;
+	size_t data_len;
+{
+	AES_CIPHER *aes;
+	cipherInstance c;
+	u_int32_t tmp_iv[DB_IV_BYTES/4];
+	int ret;
+
+	aes = (AES_CIPHER *)aes_data;
+	if (aes == NULL || data == NULL)
+		return (EINVAL);
+	if ((data_len % DB_AES_CHUNK) != 0)
+		return (EINVAL);
+	/*
+	 * Generate the IV here.  We store it in a tmp IV because
+	 * the IV might be stored within the data we are encrypting
+	 * and so we will copy it over to the given location after
+	 * encryption is done.
+	 * We don't do this outside of there because some encryption
+	 * algorithms someone might add may not use IV's and we always
+	 * want on here.
+	 */
+	if ((ret = __db_generate_iv(dbenv, tmp_iv)) != 0)
+		return (ret);
+
+	/*
+	 * Initialize the cipher
+	 */
+	if ((ret = __db_cipherInit(&c, MODE_CBC, (char *)tmp_iv)) < 0) {
+		__aes_err(dbenv, ret);
+		return (EAGAIN);
+	}
+
+	/* Do the encryption */
+	if ((ret = __db_blockEncrypt(&c, &aes->encrypt_ki, data, data_len * 8,
+	    data)) < 0) {
+		__aes_err(dbenv, ret);
+		return (EAGAIN);
+	}
+	memcpy(iv, tmp_iv, DB_IV_BYTES);
+	return (0);
+}
+
+/*
+ * __aes_init --
+ *	Initialize the AES encryption instantiation.
+ *
+ * PUBLIC: int __aes_init __P((DB_ENV *, DB_CIPHER *));
+ */
+int
+__aes_init(dbenv, db_cipher)
+	DB_ENV *dbenv;
+	DB_CIPHER *db_cipher;
+{
+	return (__aes_derivekeys(dbenv, db_cipher, (u_int8_t *)dbenv->passwd,
+	    dbenv->passwd_len));
+}
+
+static int
+__aes_derivekeys(dbenv, db_cipher, passwd, plen)
+	DB_ENV *dbenv;
+	DB_CIPHER *db_cipher;
+	u_int8_t *passwd;
+	size_t plen;
+{
+	SHA1_CTX ctx;
+	AES_CIPHER *aes;
+	int ret;
+	u_int32_t temp[DB_MAC_KEY/4];
+
+	if (passwd == NULL)
+		return (EINVAL);
+
+	aes = (AES_CIPHER *)db_cipher->data;
+
+	/* Derive the crypto keys */
+	__db_SHA1Init(&ctx);
+	__db_SHA1Update(&ctx, passwd, plen);
+	__db_SHA1Update(&ctx, (u_int8_t *)DB_ENC_MAGIC, strlen(DB_ENC_MAGIC));
+	__db_SHA1Update(&ctx, passwd, plen);
+	__db_SHA1Final((u_int8_t *)temp, &ctx);
+
+	if ((ret = __db_makeKey(&aes->encrypt_ki, DIR_ENCRYPT,
+	    DB_AES_KEYLEN, (char *)temp)) != TRUE) {
+		__aes_err(dbenv, ret);
+		return (EAGAIN);
+	}
+	if ((ret = __db_makeKey(&aes->decrypt_ki, DIR_DECRYPT,
+	    DB_AES_KEYLEN, (char *)temp)) != TRUE) {
+		__aes_err(dbenv, ret);
+		return (EAGAIN);
+	}
+	return (0);
+}
+
+/*
+ * __aes_err --
+ *	Handle AES-specific errors.  Codes and messages derived from
+ *	rijndael/rijndael-api-fst.h.
+ */
+static void
+__aes_err(dbenv, err)
+	DB_ENV *dbenv;
+	int err;
+{
+	char *errstr;
+
+	switch (err) {
+	case BAD_KEY_DIR:
+		errstr = "AES key direction is invalid";
+		break;
+	case BAD_KEY_MAT:
+		errstr = "AES key material not of correct length";
+		break;
+	case BAD_KEY_INSTANCE:
+		errstr = "AES key passwd not valid";
+		break;
+	case BAD_CIPHER_MODE:
+		errstr = "AES cipher in wrong state (not initialized)";
+		break;
+	case BAD_BLOCK_LENGTH:
+		errstr = "AES bad block length";
+		break;
+	case BAD_CIPHER_INSTANCE:
+		errstr = "AES cipher instance is invalid";
+		break;
+	case BAD_DATA:
+		errstr = "AES data contents are invalid";
+		break;
+	case BAD_OTHER:
+		errstr = "AES unknown error";
+		break;
+	default:
+		errstr = "AES error unrecognized";
+		break;
+	}
+	__db_err(dbenv, errstr);
+	return;
+}
diff --git a/storage/bdb/crypto/crypto.c b/storage/bdb/crypto/crypto.c
new file mode 100644
index 0000000000000000000000000000000000000000..f753ec3f0fc96afa9718060ca260f26e9d235762
--- /dev/null
+++ b/storage/bdb/crypto/crypto.c
@@ -0,0 +1,385 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * Some parts of this code originally written by Adam Stubblefield
+ * -- astubble@rice.edu
+ *
+ * $Id: crypto.c,v 1.31 2004/10/15 16:59:38 bostic Exp $
+ */
+
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/crypto.h"
+
+/*
+ * __crypto_region_init --
+ *	Initialize crypto.
+ */
+int
+__crypto_region_init(dbenv)
+	DB_ENV *dbenv;
+{
+	REGENV *renv;
+	REGINFO *infop;
+	CIPHER *cipher;
+	DB_CIPHER *db_cipher;
+	char *sh_passwd;
+	int ret;
+
+	db_cipher = dbenv->crypto_handle;
+
+	ret = 0;
+	infop = dbenv->reginfo;
+	renv = infop->primary;
+	MUTEX_LOCK(dbenv, &renv->mutex);
+	if (renv->cipher_off == INVALID_ROFF) {
+		if (!CRYPTO_ON(dbenv))
+			goto err;
+		if (!F_ISSET(infop, REGION_CREATE)) {
+			__db_err(dbenv,
+    "Joining non-encrypted environment with encryption key");
+			ret = EINVAL;
+			goto err;
+		}
+		if (F_ISSET(db_cipher, CIPHER_ANY)) {
+			__db_err(dbenv, "Encryption algorithm not supplied");
+			ret = EINVAL;
+			goto err;
+		}
+		/*
+		 * Must create the shared information.  We need:
+		 * Shared cipher information that contains the passwd.
+		 * After we copy the passwd, we smash and free the one in the
+		 * dbenv.
+		 */
+		if ((ret = __db_shalloc(
+		    infop, sizeof(CIPHER), MUTEX_ALIGN, &cipher)) != 0)
+			goto err;
+		memset(cipher, 0, sizeof(*cipher));
+		if ((ret = __db_shalloc(
+		    infop, dbenv->passwd_len, 0, &sh_passwd)) != 0) {
+			__db_shalloc_free(infop, cipher);
+			goto err;
+		}
+		memset(sh_passwd, 0, dbenv->passwd_len);
+		cipher->passwd = R_OFFSET(infop, sh_passwd);
+		cipher->passwd_len = dbenv->passwd_len;
+		cipher->flags = db_cipher->alg;
+		memcpy(sh_passwd, dbenv->passwd, cipher->passwd_len);
+		renv->cipher_off = R_OFFSET(infop, cipher);
+	} else {
+		if (!CRYPTO_ON(dbenv)) {
+			__db_err(dbenv,
+    "Encrypted environment: no encryption key supplied");
+			ret = EINVAL;
+			goto err;
+		}
+		cipher = R_ADDR(infop, renv->cipher_off);
+		sh_passwd = R_ADDR(infop, cipher->passwd);
+		if ((cipher->passwd_len != dbenv->passwd_len) ||
+		    memcmp(dbenv->passwd, sh_passwd, cipher->passwd_len) != 0) {
+			__db_err(dbenv, "Invalid password");
+			ret = EPERM;
+			goto err;
+		}
+		if (!F_ISSET(db_cipher, CIPHER_ANY) &&
+		    db_cipher->alg != cipher->flags) {
+			__db_err(dbenv,
+    "Environment encrypted using a different algorithm");
+			ret = EINVAL;
+			goto err;
+		}
+		if (F_ISSET(db_cipher, CIPHER_ANY))
+			/*
+			 * We have CIPHER_ANY and we are joining the
+			 * existing env.  Setup our cipher structure
+			 * for whatever algorithm this env has.
+			 */
+			if ((ret = __crypto_algsetup(dbenv, db_cipher,
+			    cipher->flags, 0)) != 0)
+				goto err;
+	}
+	MUTEX_UNLOCK(dbenv, &renv->mutex);
+	ret = db_cipher->init(dbenv, db_cipher);
+
+	/*
+	 * On success, no matter if we allocated it or are using the
+	 * already existing one, we are done with the passwd in the dbenv.
+	 * We smash N-1 bytes so that we don't overwrite the nul.
+	 */
+	memset(dbenv->passwd, 0xff, dbenv->passwd_len-1);
+	__os_free(dbenv, dbenv->passwd);
+	dbenv->passwd = NULL;
+	dbenv->passwd_len = 0;
+
+	if (0) {
+err:		MUTEX_UNLOCK(dbenv, &renv->mutex);
+	}
+	return (ret);
+}
+
+/*
+ * __crypto_dbenv_close --
+ *	Crypto-specific destruction of DB_ENV structure.
+ *
+ * PUBLIC: int __crypto_dbenv_close __P((DB_ENV *));
+ */
+int
+__crypto_dbenv_close(dbenv)
+	DB_ENV *dbenv;
+{
+	DB_CIPHER *db_cipher;
+	int ret;
+
+	ret = 0;
+	db_cipher = dbenv->crypto_handle;
+	if (dbenv->passwd != NULL) {
+		memset(dbenv->passwd, 0xff, dbenv->passwd_len-1);
+		__os_free(dbenv, dbenv->passwd);
+		dbenv->passwd = NULL;
+	}
+	if (!CRYPTO_ON(dbenv))
+		return (0);
+	if (!F_ISSET(db_cipher, CIPHER_ANY))
+		ret = db_cipher->close(dbenv, db_cipher->data);
+	__os_free(dbenv, db_cipher);
+	return (ret);
+}
+
+/*
+ * __crypto_region_destroy --
+ *	Destroy any system resources allocated in the primary region.
+ *
+ * PUBLIC: int __crypto_region_destroy __P((DB_ENV *));
+ */
+int
+__crypto_region_destroy(dbenv)
+	DB_ENV *dbenv;
+{
+	CIPHER *cipher;
+	REGENV *renv;
+	REGINFO *infop;
+
+	infop = dbenv->reginfo;
+	renv = infop->primary;
+	if (renv->cipher_off != INVALID_ROFF) {
+		cipher = R_ADDR(infop, renv->cipher_off);
+		__db_shalloc_free(infop, R_ADDR(infop, cipher->passwd));
+		__db_shalloc_free(infop, cipher);
+	}
+	return (0);
+}
+
+/*
+ * __crypto_algsetup --
+ *	Given a db_cipher structure and a valid algorithm flag, call
+ * the specific algorithm setup function.
+ *
+ * PUBLIC: int __crypto_algsetup __P((DB_ENV *, DB_CIPHER *, u_int32_t, int));
+ */
+int
+__crypto_algsetup(dbenv, db_cipher, alg, do_init)
+	DB_ENV *dbenv;
+	DB_CIPHER *db_cipher;
+	u_int32_t alg;
+	int do_init;
+{
+	int ret;
+
+	ret = 0;
+	if (!CRYPTO_ON(dbenv)) {
+		__db_err(dbenv, "No cipher structure given");
+		return (EINVAL);
+	}
+	F_CLR(db_cipher, CIPHER_ANY);
+	switch (alg) {
+	case CIPHER_AES:
+		db_cipher->alg = CIPHER_AES;
+		ret = __aes_setup(dbenv, db_cipher);
+		break;
+	default:
+		__db_panic(dbenv, EINVAL);
+		/* NOTREACHED */
+	}
+	if (do_init)
+		ret = db_cipher->init(dbenv, db_cipher);
+	return (ret);
+}
+
+/*
+ * __crypto_decrypt_meta --
+ *	Perform decryption on a metapage if needed.
+ *
+ * PUBLIC:  int __crypto_decrypt_meta __P((DB_ENV *, DB *, u_int8_t *, int));
+ */
+int
+__crypto_decrypt_meta(dbenv, dbp, mbuf, do_metachk)
+	DB_ENV *dbenv;
+	DB *dbp;
+	u_int8_t *mbuf;
+	int do_metachk;
+{
+	DB_CIPHER *db_cipher;
+	DB dummydb;
+	DBMETA *meta;
+	size_t pg_off;
+	int ret;
+	u_int8_t *iv;
+
+	/*
+	 * If we weren't given a dbp, we just want to decrypt the page
+	 * on behalf of some internal subsystem, not on behalf of a user
+	 * with a dbp.  Therefore, set up a dummy dbp so that the call
+	 * to P_OVERHEAD below works.
+	 */
+	if (dbp == NULL) {
+		memset(&dummydb, 0, sizeof(DB));
+		dbp = &dummydb;
+	}
+	/*
+	 * Meta-pages may be encrypted for DBMETASIZE bytes.  If
+	 * we have a non-zero IV (that is written after encryption)
+	 * then we decrypt (or error if the user isn't set up for
+	 * security).  We guarantee that the IV space on non-encrypted
+	 * pages will be zero and a zero-IV is illegal for encryption.
+	 * Therefore any non-zero IV means an encrypted database.
+	 * This basically checks the passwd on the file
+	 * if we cannot find a good magic number.
+	 * We walk through all the algorithms we know about attempting
+	 * to decrypt (and possibly byteswap).
+	 *
+	 * !!!
+	 * All method meta pages have the IV and checksum at the
+	 * exact same location, but not in DBMETA, use BTMETA.
+	 */
+	ret = 0;
+	meta = (DBMETA *)mbuf;
+	if (meta->encrypt_alg != 0) {
+		db_cipher = (DB_CIPHER *)dbenv->crypto_handle;
+		if (!F_ISSET(dbp, DB_AM_ENCRYPT)) {
+			if (!CRYPTO_ON(dbenv)) {
+				__db_err(dbenv,
+    "Encrypted database: no encryption flag specified");
+				return (EINVAL);
+			}
+			/*
+			 * User has a correct, secure env, but has
+			 * encountered a database in that env that is
+			 * secure, but user didn't dbp->set_flags.  Since
+			 * it is existing, use encryption if it is that
+			 * way already.
+			 */
+			F_SET(dbp, DB_AM_ENCRYPT|DB_AM_CHKSUM);
+		}
+		/*
+		 * This was checked in set_flags when DB_AM_ENCRYPT was set.
+		 * So it better still be true here.
+		 */
+		DB_ASSERT(CRYPTO_ON(dbenv));
+		if (!F_ISSET(db_cipher, CIPHER_ANY) &&
+		    meta->encrypt_alg != db_cipher->alg) {
+			__db_err(dbenv,
+			    "Database encrypted using a different algorithm");
+			return (EINVAL);
+		}
+		DB_ASSERT(F_ISSET(dbp, DB_AM_CHKSUM));
+		iv = ((BTMETA *)mbuf)->iv;
+		/*
+		 * For ALL pages, we do not encrypt the beginning
+		 * of the page that contains overhead information.
+		 * This is true of meta and all other pages.
+		 */
+		pg_off = P_OVERHEAD(dbp);
+alg_retry:
+		/*
+		 * If they asked for a specific algorithm, then
+		 * use it.  Otherwise walk through those we know.
+		 */
+		if (!F_ISSET(db_cipher, CIPHER_ANY)) {
+			if (do_metachk && (ret = db_cipher->decrypt(dbenv,
+			    db_cipher->data, iv, mbuf + pg_off,
+			    DBMETASIZE - pg_off)))
+				return (ret);
+			if (((BTMETA *)meta)->crypto_magic !=
+			    meta->magic) {
+				__db_err(dbenv, "Invalid password");
+				return (EINVAL);
+			}
+			/*
+			 * Success here.  The algorithm asked for and the one
+			 * on the file match.  We've just decrypted the meta
+			 * page and checked the magic numbers.  They match,
+			 * indicating the password is right.  All is right
+			 * with the world.
+			 */
+			return (0);
+		}
+		/*
+		 * If we get here, CIPHER_ANY must be set.
+		 */
+		ret = __crypto_algsetup(dbenv, db_cipher, meta->encrypt_alg, 1);
+		goto alg_retry;
+	} else if (F_ISSET(dbp, DB_AM_ENCRYPT)) {
+		/*
+		 * They gave us a passwd, but the database is not
+		 * encrypted.  This is an error.  We do NOT want to
+		 * silently allow them to write data in the clear when
+		 * the user set up and expects encrypted data.
+		 *
+		 * This covers at least the following scenario.
+		 * 1.  User creates and sets up an encrypted database.
+		 * 2.  Attacker cannot read the actual data in the database
+		 * because it is encrypted, but can remove/replace the file
+		 * with an empty, unencrypted database file.
+		 * 3.  User sets encryption and we get to this code now.
+		 * If we allowed the file to be used in the clear since
+		 * it is that way on disk, the user would unsuspectingly
+		 * write sensitive data in the clear.
+		 * 4.  Attacker reads data that user thought was encrypted.
+		 *
+		 * Therefore, asking for encryption with a database that
+		 * was not encrypted is an error.
+		 */
+		__db_err(dbenv,
+		    "Unencrypted database with a supplied encryption key");
+		return (EINVAL);
+	}
+	return (ret);
+}
+
+/*
+ * __crypto_set_passwd --
+ *	Get the password from the shared region; and set it in a new
+ * environment handle.  Use this to duplicate environment handles.
+ *
+ * PUBLIC: int __crypto_set_passwd __P((DB_ENV *, DB_ENV *));
+ */
+int
+__crypto_set_passwd(dbenv_src, dbenv_dest)
+	DB_ENV *dbenv_src, *dbenv_dest;
+{
+	CIPHER *cipher;
+	REGENV *renv;
+	REGINFO *infop;
+	char *sh_passwd;
+	int ret;
+
+	ret = 0;
+	infop = dbenv_src->reginfo;
+	renv = infop->primary;
+
+	DB_ASSERT(CRYPTO_ON(dbenv_src));
+
+	cipher = R_ADDR(infop, renv->cipher_off);
+	sh_passwd = R_ADDR(infop, cipher->passwd);
+	return (__dbenv_set_encrypt(dbenv_dest, sh_passwd, DB_ENCRYPT_AES));
+}
diff --git a/storage/bdb/crypto/crypto.html b/storage/bdb/crypto/crypto.html
new file mode 100644
index 0000000000000000000000000000000000000000..9475beb2a2d2d02649df69525e2a3c409cd9af9e
--- /dev/null
+++ b/storage/bdb/crypto/crypto.html
@@ -0,0 +1,639 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <meta name="GENERATOR" content="Mozilla/4.76 [en] (X11; U; FreeBSD 4.3-RELEASE i386) [Netscape]">
+</head>
+<body>
+
+<center>
+<h1>
+&nbsp;Security Interface for Berkeley DB</h1></center>
+
+<center><i>Susan LoVerso</i>
+<br><i>sue@sleepycat.com</i>
+<br><i>Rev 1.6</i>
+<br><i>2002 Feb 26</i></center>
+
+<p>We provide an interface allowing secure access to Berkeley DB.&nbsp;&nbsp;
+Our goal is to allow users to have encrypted secure databases.&nbsp; In
+this document, the term <i>ciphering</i> means the act of encryption or
+decryption.&nbsp; They are equal but opposite actions and the same issues
+apply to both just in the opposite direction.
+<h3>
+Requirements</h3>
+The overriding requirement is to provide a simple mechanism to allow users
+to have a secure database.&nbsp; A secure database means that all of the
+pages of a database will be encrypted, and all of the log files will be
+encrypted.
+<p>Falling out from this work will be a simple mechanism to allow users
+to request that we checksum their data for additional error detection (without
+encryption/decryption).
+<p>We expect that data in process memory or stored in shared memory, potentially
+backed by disk, is not encrypted or secure.
+<h2>
+<a NAME="DB Modifications"></a>DB Method Interface Modifications</h2>
+With a logging environment, all database changes are recorded in the log
+files.&nbsp; Therefore, users requiring secure databases in such environments
+also require secure log files.
+<p>A prior thought had been to allow different passwords on the environment
+and the databases within.&nbsp; However, such a scheme, then requires that
+the password be logged in order for recovery to be able to restore the
+database.&nbsp; Therefore, any application having the password for the
+log could get the password for any databases by reading the log.&nbsp;
+So having a different password on a database does not gain any additional
+security and it makes certain things harder and more complex.&nbsp; Some
+of those more complex things include the need to handle database and env
+passwords differently since they'd need to be stored and accessed from
+different places.&nbsp; Also resolving the issue of how <i>db_checkpoint</i>
+or <i>db_sync</i>, which flush database pages to disk, would find the passwords
+of various databases without any dbps was unsolved.&nbsp; The feature didn't
+gain anything and caused significant pain.&nbsp; Therefore the decision
+is that there will be a single password protecting an environment and all
+the logs and some databases within that environment.&nbsp; We do allow
+users to have a secure environment and clear databases.&nbsp; Users that
+want secure databases within a secure environment must set a flag.
+<p>Users wishing to enable encryption on a database in a secure environment
+or enable just checksumming on their database pages will use new flags
+to <a href="../docs/api_c/db_set_flags.html">DB->set_flags()</a>.&nbsp;
+Providing ciphering over an entire environment is accomplished by adding
+a single environment method: <a href="../docs/api_c/env_set_encrypt.html">DBENV->set_encrypt()</a>.&nbsp;
+Providing encryption for a database (not part of an environment) is accomplished
+by adding a new database method: <a href="../docs/api_c/db_set_encrypt.html">DB->set_encrypt()</a>.
+<p>Both of the <i>set_encrypt</i> methods must be called before their respective
+<i>open</i> calls.&nbsp; The environment method must be before the environment
+open because we must know about security before there is any possibility
+of writing any log records out.&nbsp; The database method must be before
+the database open in order to read the root page.&nbsp; The planned interfaces
+for these methods are:
+<pre>DBENV->set_encrypt(DBENV *dbenv,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* DB_ENV structure */
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char *passwd&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Password */
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u_int32_t flags);&nbsp;&nbsp;&nbsp;&nbsp; /* Flags */</pre>
+
+<pre>DB->set_encrypt(DB *dbp,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* DB structure */
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char *passwd&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Password */
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u_int32_t flags);&nbsp;&nbsp;&nbsp;&nbsp; /* Flags */</pre>
+The flags accepted by these functions are:
+<pre>#define DB_ENCRYPT_AES&nbsp; 0x00000001&nbsp; /* Use the AES encryption algorithm */</pre>
+Passwords are NULL-terminated strings.&nbsp; NULL or zero length strings
+are illegal.&nbsp; These flags enable the checksumming and encryption using
+the particular algorithms we have chosen for this implementation.&nbsp;
+The flags are named such that there is a logical naming pattern if additional
+checksum or encryption algorithms are used. If a user gives a flag of zero,
+it will behave in a manner similar to DB_UNKNOWN. It will be illegal if
+they are creating the environment or database, as an algorithm must be
+specified. If they are joining an existing environment or opening an existing
+database, they will use whatever algorithm is in force at the time.&nbsp;
+Using DB_ENCRYPT_AES automatically implies SHA1 checksumming.
+<p>These functions will perform several initialization steps.&nbsp; We
+will allocate crypto_handle for our env handle and set up our function
+pointers.&nbsp; We will allocate space and copy the password into our env
+handle password area.&nbsp; Similar to <i>DB->set_cachesize</i>, calling
+<i>DB->set_encrypt</i>
+will actually reflect back into the local environment created by DB.
+<p>Lastly, we will add a new flag, DB_OVERWRITE, to the <a href="../docs/api_c/env_remove.html">DBENV->remove</a>
+method.&nbsp; The purpose of this flag is to force all of the memory used
+by the shared regions to be overwritten before removal.&nbsp; We will use
+<i>rm_overwrite</i>,
+a function that overwrites and syncs a file 3 times with varying bit patterns
+to really remove a file.&nbsp; Additionally, this flag will force a sync
+of the overwritten regions to disk, if the regions are backed by the file
+system.&nbsp; That way there is no residual information left in the clear
+in memory or freed disk blocks.&nbsp; Although we expect that this flag
+will be used by customers using security, primarily, its action is not
+dependent on passwords or a secure setup, and so can be used by anyone.
+<h4>
+Initialization of the Environment</h4>
+The setup of the security subsystem will be similar to replication initialization
+since it is a sort of subsystem, but it does not have its own region.&nbsp;
+When the environment handle is created via <i>db_env_create</i>, we initialize
+our <i>set_encrypt</i> method to be the RPC or local version.&nbsp; Therefore
+the <i>__dbenv</i> structure needs a new pointer:
+<pre>&nbsp;&nbsp;&nbsp; void&nbsp;&nbsp;&nbsp; *crypto_handle;&nbsp;&nbsp; /* Security handle */</pre>
+The crypto handle will really point to a new <i>__db_cipher</i> structure
+that will contain a set of functions and a pointer to the in-memory information
+needed by the specific encryption algorithm.&nbsp; It will look like:
+<pre>typedef struct __db_cipher {
+&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (*init)__P((...));&nbsp;&nbsp;&nbsp; /* Alg-specific initialization function */
+&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (*encrypt)__P((...)); /* Alg-specific encryption algorithm */
+&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (*decrypt)__P((...)); /* Alg-specific decryption function */
+&nbsp;&nbsp;&nbsp; void&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *data;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Pointer to alg-specific information (AES_CIPHER) */
+&nbsp;&nbsp;&nbsp; u_int32_t flags;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Cipher flags */
+} DB_CIPHER;</pre>
+
+<pre>#define DB_MAC_KEY&nbsp;&nbsp;&nbsp; 20&nbsp;&nbsp;&nbsp; /* Size of the MAC key */
+typedef struct __aes_cipher {
+&nbsp;&nbsp;&nbsp; keyInstance&nbsp;&nbsp;&nbsp; encrypt_ki;&nbsp;&nbsp; /* Encrypt keyInstance temp. */
+&nbsp;&nbsp;&nbsp; keyInstance&nbsp;&nbsp;&nbsp; decrypt_ki;&nbsp;&nbsp; /* Decrypt keyInstance temp. */
+&nbsp;&nbsp;&nbsp; u_int8_t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mac_key[DB_MAC_KEY]; /* MAC key */
+&nbsp;&nbsp;&nbsp; u_int32_t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flags;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* AES-specific flags */
+} AES_CIPHER;</pre>
+It should be noted that none of these structures have their own mutex.&nbsp;
+We hold the environment region locked while we are creating this, but once
+this is set up, it is read-only forever.
+<p>During <a href="../docs/api_c/env_set_encrypt.html">dbenv->set_encrypt</a>,
+we set the encryption, decryption and checksumming methods to the appropriate
+functions based on the flags.&nbsp; This function will allocate us a crypto
+handle that we store in the <i>__dbenv</i> structure just like all the
+other subsystems.&nbsp; For now, only AES ciphering functions and SHA1
+checksumming functions are supported.&nbsp; Also we will copy the password
+into the <i>__dbenv</i> structure.&nbsp; We ultimately need to keep the
+password in the environment's shared memory region or compare this one
+against the one that is there, if we are joining an existing environment,
+but we do not have it yet because open has not yet been called.&nbsp; We
+will allocate a structure that will be used in initialization and set up
+the function pointers to point to the algorithm-specific functions.
+<p>In the&nbsp; <i>__dbenv_open</i> path, in <i>__db_e_attach</i>, if we
+are creating the region and the <i>dbenv->passwd</i> field is set, we need
+to use the length of the password in the initial computation of the environment's
+size.&nbsp; This guarantees sufficient space for storing the password in
+shared memory.&nbsp; Then we will call a new function to initialize the
+security region, <i>__crypto_region_init</i> in <i>__dbenv_open</i>.&nbsp;
+If we are the creator, we will allocate space in the shared region to store
+the password and copy the password into that space.&nbsp; Or, if we are
+not the creator we will compare the password stored in the dbenv with the
+one in shared memory.&nbsp;&nbsp; Additionally, we will compare the ciphering
+algorithm to the one stored in the shared region.We'll smash the dbenv
+password and free it.&nbsp; If they do not match, we return an error.&nbsp;
+If we are the creator we store the offset into the REGENV structure.&nbsp;
+Then <i>__crypto_region_init&nbsp;</i> will call the initialization function
+set up earlier based on the ciphering algorithm specified.&nbsp; For now
+we will call <i>__aes_init</i>.&nbsp; Additionally this function will allocate
+and set up the per-process state vector for this encryption's IVs.&nbsp;
+See <a href="#Generating the Initialization Vector">Generating the Initialization
+Vector</a> for a detailed description of the IV and state vector.
+<p>In the AES-specific initialization function, <i>__aes_init</i>,&nbsp;
+we will initialize it by calling
+<i>__aes_derivekeys</i> in order to fill
+in the keyInstance and mac_key fields in that structure.&nbsp; The REGENV
+structure will have one additional item
+<pre>&nbsp;&nbsp; roff_t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; passwd_off;&nbsp;&nbsp; /* Offset of passwd */</pre>
+
+<h4>
+Initializing a Database</h4>
+During <a href="../docs/api_c/db_set_encrypt.html">db->set_encrypt</a>,
+we set the encryption, decryption and checksumming methods to the appropriate
+functions based on the flags.&nbsp; Basically, we test that we are not
+in an existing environment and we haven't called open.&nbsp; Then we just
+call through the environment handle to set the password.
+<p>Also, we will need to add a flag in the database meta-data page that
+indicates that the database is encrypted and what its algorithm is.&nbsp;
+This will be used when the meta-page is read after reopening a file. We
+need this information on the meta-page in order to detect a user opening
+a secure database without a password.&nbsp; I propose using the first unused1
+byte (renaming it too) in the meta page for this purpose.
+<p>All pages will not be encrypted for the first 64 bytes of data.&nbsp;
+Database meta-pages will be encrypted on the first 512 bytes only.&nbsp;
+All meta-page types will have an IV and checksum added within the first
+512 bytes as well as a crypto magic number.&nbsp; This will expand the
+size of the meta-page from 256 bytes to 512 bytes. The page in/out routines,
+<i>__db_pgin</i> and <i>__db_pgout</i> know the page type of the page and
+will apply the 512 bytes ciphering to meta pages.&nbsp; In <i>__db_pgout</i>,
+if we have a crypto handle in our (private) environment, we will apply
+ciphering to either the entire page, or the first 512 bytes if it is a
+meta-page.&nbsp; In <i>__db_pgin</i>, we will decrypt if the page we have
+a crypto handle.
+<p>When multiple processes share a database, all must use the same password
+as the database creator. Using an existing database requires several conditions
+to be true.&nbsp; First, if the creator of the database did not create
+with security, then opening later with security is an error.&nbsp; Second,
+if the creator did create it with security, then opening later without
+security is an error.&nbsp; Third, we need to be able to test and check
+that when another process opens a secure database that the password they
+provided is the same as the one in use by the creator.
+<p>When reading the meta-page, in <i>__db_file_setup</i>, we do not go
+through the paging functions, but directly read via <i>__os_read</i>.&nbsp;
+It is at this point that we will determine if the user is configured correctly.&nbsp;
+If the meta-page we read has an IV and checksum, they better have a crypto
+handle.&nbsp; If they have a crypto handle, then the meta-page must have
+an IV and checksum.&nbsp; If both of those are true, we test the password.&nbsp;
+We compare the unencrypted magic number to the newly-decrypted crypto magic
+number and if they are not the same, then we report that the user gave
+us a bad password.
+<p>On a mostly unrelated topic, even when we go to very large pagesizes,
+the meta information will still be within a disk sector.&nbsp; So, after
+talking it over with Keith and Margo, we determined that unencrypted meta-pages
+still will not need a checksum.
+<h3>
+Encryption and Checksum Routines</h3>
+These routines are provided to us by Adam Stubblefield at Rice University
+(astubble@rice.edu).&nbsp; The functional interfaces are:
+<pre>__aes_derivekeys(DB_ENV *dbenv,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* dbenv */
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u_int8_t *passwd,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Password */
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size_t passwd_len,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Length of passwd */
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u_int8_t *mac_key,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 20 byte array to store MAC key */
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keyInstance *encrypt_key,&nbsp;&nbsp; /* Encryption key of passwd */
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keyInstance *decrypt_key);&nbsp; /* Decryption key of passwd */</pre>
+This is the only function requiring the textual user password.&nbsp; From
+the password, this function generates a key used in the checksum function,
+<i>__db_chksum</i>.&nbsp;
+It also fills in <i>keyInstance</i> structures which are then used in the
+encryption and decryption routines.&nbsp; The keyInstance structures must
+already be allocated.&nbsp; These will be stored in the AES_CIPHER structure.
+<pre>&nbsp;__db_chksum(u_int8_t *data,&nbsp;&nbsp;&nbsp; /* Data to checksum */
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size_t data_len,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Length of data */
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u_int8_t *mac_key,&nbsp;&nbsp;&nbsp; /* 20 byte array from __db_derive_keys */
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u_int8_t *checksum);&nbsp; /* 20 byte array to store checksum */</pre>
+This function generates a checksum on the data given.&nbsp; This function
+will do double-duty for users that simply want error detection on their
+pages.&nbsp; When users are using encryption, the <i>mac_key </i>will contain
+the 20-byte key set up in <i>__aes_derivekeys</i>.&nbsp; If they just want
+checksumming, then <i>mac_key</i> will be NULL.&nbsp; According to Adam,
+we can safely use the first N-bytes of the checksum.&nbsp; So for seeding
+the generator for initialization vectors, we'll hash the time and then
+send in the first 4 bytes for the seed.&nbsp; I believe we can probably
+do the same thing for checksumming log records.&nbsp; We can only use 4
+bytes for the checksum in the non-secure case.&nbsp; So when we want to
+verify the log checksum we can compute the mac but just compare the first
+4 bytes to the one we read.&nbsp; All locations where we generate or check
+log record checksums that currently call <i>__ham_func4</i> will now call
+<i>__db_chksum</i>.&nbsp;
+I believe there are 5 such locations,
+<i>__log_put, __log_putr, __log_newfile,
+__log_rep_put
+</i>and<i> __txn_force_abort.</i>
+<pre>__aes_encrypt(DB_ENV *dbenv,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* dbenv */
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keyInstance *key,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Password key instance from __db_derive_keys */
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u_int8_t *iv,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Initialization vector */
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u_int8_t *data,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Data to encrypt */
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size_t data_len);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Length of data to encrypt - 16 byte multiple */</pre>
+This is the function to encrypt data.&nbsp; It will be called to encrypt
+pages and log records.&nbsp; The <i>key</i> instance is initialized in
+<i>__aes_derivekeys</i>.&nbsp;
+The initialization vector, <i>iv</i>, is the 16 byte random value set up
+by the Mersenne Twister pseudo-random generator.&nbsp; Lastly, we pass
+in a pointer to the <i>data</i> to encrypt and its length in <i>data_len</i>.&nbsp;
+The <i>data_len</i> must be a multiple of 16 bytes. The encryption is done
+in-place so that when the encryption code returns our encrypted data is
+in the same location as the original data.
+<pre>__aes_decrypt(DB_ENV *dbenv,&nbsp;&nbsp;&nbsp; /* dbenv */
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keyInstance *key,&nbsp; /* Password key instance from __db_derive_keys */
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u_int8_t *iv,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Initialization vector */
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u_int8_t *data,&nbsp;&nbsp;&nbsp; /* Data to decrypt */
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size_t data_len);&nbsp; /* Length of data to decrypt - 16 byte multiple */</pre>
+This is the function to decrypt the data.&nbsp; It is exactly the same
+as the encryption function except for the action it performs.&nbsp; All
+of the args and issues are the same.&nbsp; It also decrypts in place.
+<h3>
+<a NAME="Generating the Initialization Vector"></a>Generating the Initialization
+Vector</h3>
+Internally, we need to provide a unique initialization vector (IV) of 16
+bytes every time we encrypt any data with the same password.&nbsp; For
+the IV we are planning on using mt19937, the Mersenne Twister, a random
+number generator that has a period of 2**19937-1. This package can be found
+at <a href="http://www.math.keio.ac.jp/~matumoto/emt.html">http://www.math.keio.ac.jp/~matumoto/emt.html</a>.&nbsp;
+Tests show that although it repeats a single integer every once in a while,
+that after several million iterations, it doesn't repeat any 4 integers
+that we'd be stuffing into our 16-byte IV.&nbsp; We plan on seeding this
+generator with the time (tv_sec) hashed through SHA1 when we create the
+environment.&nbsp; This package uses a global state vector that contains
+624 unsigned long integers.&nbsp; We do not allow a 16-byte IV of zero.&nbsp;
+It is simpler just to reject any 4-byte value of 0 and if we get one, just
+call the generator again and get a different number.&nbsp; We need to detect
+holes in files and if we read an IV of zero that is a simple indication
+that we need to check for an entire page of zero.&nbsp; The IVs are stored
+on the page after encryption and are not encrypted themselves so it is
+not possible for an entire encrypted page to be read as all zeroes, unless
+it was a hole in a file.&nbsp; See <a href="#Holes in Files">Holes in Files</a>
+for more details.
+<p>We will not be holding any locks when we need to generate our IV but
+we need to protect access to the state vector and the index.&nbsp; Calls
+to the MT code will come while encrypting some data in <i>__aes_encrypt.</i>&nbsp;&nbsp;
+The MT code will assume that all necessary locks are held in the caller.&nbsp;
+We will have per-process state vectors that are set up when a process begins.&nbsp;
+That way we minimize the contention and only multi-threaded processes need
+acquire locks for the IV.&nbsp; We will have the state vector in the environment
+handle in heap memory, as well as the index and there will be a mutex protecting
+it for threaded access.&nbsp; This will be added to the <i>__dbenv</i>
+structure:
+<pre>&nbsp;&nbsp;&nbsp; DB_MUTEX&nbsp;&nbsp;&nbsp; *mt_mutexp;&nbsp;&nbsp; /* Mersenne Twister mutex */
+&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *mti;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* MT index */
+&nbsp;&nbsp;&nbsp; u_long&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *mt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* MT state vector */</pre>
+This portion of the environment will be initialized at the end of _<i>_dbenv_open</i>,
+right after we initialize the other mutex for the <i>dblist</i>. When we
+allocate the space, we will generate our initial state vector. If we are
+multi-threaded we'll allocate and initialize our mutex also.
+<p>We need to make changes to the MT code to make it work in our namespace
+and&nbsp; to take&nbsp; a pointer to the location of the state vector and
+the index.&nbsp;&nbsp; There will be a wrapper function <i>__db_generate_iv</i>
+that DB will call and it will call the appropriate MT function.&nbsp; I
+am also going to change the default seed to use a hashed time instead of
+a hard coded value.&nbsp; I have looked at other implementations of the
+MT code available on the web site.&nbsp; The C++ version does a hash on
+the current time.&nbsp; I will modify our MT code to seed with the hashed
+time as well.&nbsp; That way the code to seed is contained within the MT
+code and we can just write the wrapper to get an IV.&nbsp; We will not
+be changing the core computational code of MT.
+<h2>
+DB Internal Issues</h2>
+
+<h4>
+When do we Cipher?</h4>
+All of the page ciphering is done in the <i>__db_pgin/__db_pgout</i> functions.&nbsp;
+We will encrypt after the method-specific function on page-out and decrypt
+before the method-specfic function on page-in.&nbsp; We do not hold any
+locks when entering these functions.&nbsp; We determine that we need to
+cipher based on the existence of the encryption flag in the dbp.
+<p>For ciphering log records, the encryption will be done as the first
+thing (or a new wrapper) in <i>__log_put.&nbsp; </i>See <a href="#Log Record Encryption">Log
+Record Encryption</a> for those details.
+<br>&nbsp;
+<h4>
+Page Changes</h4>
+The checksum and IV values will be stored prior to the first index of the
+page.&nbsp; We have a new P_INP macro that replaces use of inp[X] in the
+code. &nbsp;This macro takes a dbp as an argument and determines where
+our first index is based on whether we have DB_AM_CHKSUM and DB_AM_ENCRYPT
+set.&nbsp; If neither is set, then our first index is where it always was.
+&nbsp;If just checksumming is set, then we reserve a 4-byte checksum.&nbsp;
+If encryption is set, then we reserve 36 bytes for our checksum/IV as well
+as some space to get proper alignment to encrypt on a 16-byte boundary.
+<p>Since several paging macros use inp[X] in them, those macros must now
+take a dbp.&nbsp; There are a lot of changes to make all the necessary
+paging macros take a dbp, although these changes are trivial in nature.
+<p>Also, there is a new function <i>__db_chk_meta</i> to perform checksumming
+and decryption checking on meta pages specifically.&nbsp; This function
+is where we check that the database algorithm matches what the user gave
+(or if they set DB_CIPHER_ANY then we set it), and other encryption related
+testing for bad combinations of what is in the file versus what is in the
+user structures.
+<h4>
+Verification</h4>
+The verification code will also need to be updated to deal with secure
+pages.&nbsp; Basically when the verification code reads in the meta page
+it will call <i>__db_chk_meta</i> to perform any checksumming and decryption.
+<h4>
+<a NAME="Holes in Files"></a>Holes in Files</h4>
+Holes in files will be dealt with rather simply.&nbsp; We need to be able
+to distinguish reading a hole in a file from an encrypted page that happened
+to encrypt to all zero's.&nbsp; If we read a hole in a file, we do not
+want to send that empty page through the decryption routine.&nbsp; This
+can be determined simply without incurring the performance penalty of comparing
+every byte on a page on every read until we get a non-zero byte.
+<br>The __db_pgin function is only given an invalid page P_INVALID in this
+case.&nbsp;&nbsp;So, if the page type, which is always unencrypted, is
+P_INVALID, then we do not perform any checksum verification or decryption.
+<h4>
+Errors and Recovery</h4>
+Dealing with a checksum error is tricky.&nbsp; Ultimately, if a checksum
+error occurs it is extremely likely that the user must do catastrophic
+recovery.&nbsp; There is no other failure return other than&nbsp; DB_RUNRECOVERY
+for indicating that the user should run catastrophic recovery.&nbsp; We
+do not want to add a new error return for applications to check because
+a lot of applications already look for and deal with DB_RUNRECOVERY as
+an error condition and we want to fit ourselves into that application model.&nbsp;
+We already indicate to the user that when they get that error, then they
+need to run recovery.&nbsp; If recovery fails, then they need to run catastrophic
+recovery.&nbsp; We need to get ourselves to the point where users will
+run catastrophic recovery.
+<p>If we get a checksum error, then we need to log a message stating a
+checksum error occurred on page N.&nbsp; In <i>__db_pgin</i>, we can check
+if logging is on in the environment.&nbsp; If so, we want to log the message.
+<p>When the application gets the DB_RUNRECOVERY error, they'll have to
+shut down their application and run recovery.&nbsp; When the recovery encounters
+the record indicating checksum failure, then normal recovery will fail
+and the user will have to perform catastrophic recovery.&nbsp; When catastrophic
+recovery encounters that record, it will simply ignore it.
+<h4>
+<a NAME="Log Record Encryption"></a>Log Record Encryption</h4>
+Log records will be ciphered.&nbsp; It might make sense to wrap <i>__log_put</i>
+to encrypt the DBT we send down.&nbsp; The <i>__log_put </i>function is
+where the checksum is computed before acquiring the region lock.&nbsp;
+But also this function is where we call <i>__rep_send_message</i> to send
+the DBT to the replication clients.&nbsp; Therefore, we need the DBT to
+be encrypted prior to there.&nbsp; We also need it encrypted before checksumming.
+I think <i>__log_put </i>will become <i>__log_put_internal</i>, and the
+new <i>__log_put</i> will encrypt if needed and then call <i>__log_put_internal
+</i>(the
+function formerly known as <i>__log_put</i>).&nbsp; Log records are kept
+in a shared memory region buffer prior to going out to disk.&nbsp; Records
+in the buffer will be encrypted.&nbsp; No locks are held at the time we
+will need to encrypt.
+<p>On reading the log, via log cursors, the log code stores log records
+in the log buffer.&nbsp; Records in that buffer will be encrypted, so decryption
+will occur no matter whether we are returning records from the buffer or
+if we are returning log records directly from the disk. Current checksum
+checking is done in
+<i>__log_get_c_int.</i>&nbsp; Decryption will be done
+after the checksum is checked.
+<p>There are currently two nasty issues with encrypted log records.&nbsp;
+The first is that <i>__txn_force_abort</i> overwrites a commit record in
+the log buffer with an abort record.&nbsp; Well, our log buffer will be
+encrypted.&nbsp; Therefore, <i>__txn_force_abort</i> is going to need to
+do encryption of its new record.&nbsp; This can be accomplished by sending
+in the dbenv handle to the function.&nbsp; It is available to us in <i>__log_flush_commit</i>
+and we can just pass it in.&nbsp; I don't like putting log encryption in
+the txn code, but the layering violation is already there.
+<p>The second issue is that the encryption code requires data that is a
+multiple of 16 bytes and log record lengths are variable.&nbsp; We will
+need to pad log records to meet the requirement.&nbsp; Since the callers
+of <i>__log_put</i> set up the given DBT it is a logical place to pad if
+necessary. We will modify the gen_rec.awk script to have all of the generated
+logging functions pad for us if we have a crypto handle. This padding will
+also expand the size of log files. Anyone calling <i>log_put</i> and using
+security from the application will have to pad on their own or it will
+return an error.
+<p>When ciphering the log file, we will need a different header than the
+current one.&nbsp; The current header only has space for a 4 byte checksum.&nbsp;
+Our secure header will need space for the 16 byte IV and 20 byte checksum.&nbsp;
+This will blow up our log files when running securely since every single
+log record header will now consume 32 additional bytes.&nbsp; I believe
+that the log header does not need to be encrypted.&nbsp; It contains an
+offset, a length and our IV and checksum.&nbsp; Our IV and checksum are
+never encrypted.&nbsp; I don't believe there to be any risk in having the
+offset and length in the clear.
+<p>I would prefer not to have two types of log headers that are incompatible
+with each other.&nbsp; It is not acceptable to increase the log headers
+of all users from 12 bytes to 44 bytes.&nbsp; Such a change would also
+make log files incompatible with earlier releases.&nbsp; Worse even, is
+that the <i>cksum</i> field of the header is in between the offset and
+len.&nbsp; It would be really convenient if we could have just made a bigger
+cksum portion without affecting the location of the other fields.&nbsp;
+Oh well.&nbsp; Most customers will not be using encryption and we won't
+make them pay the price of the expanded header.&nbsp; Keith indicates that
+the log file format is changing with the next release so I will move the
+cksum field so it can at least be overlaid.
+<p>One method around this would be to have a single internal header that
+contains all the information both mechanisms need, but when we write out
+the header we choose which pieces to write.&nbsp; By appending the security
+information to the end of the existing structure, and adding a size field,
+we can modify a few places to use the size field to write out only the
+current first 12 bytes, or the entire security header needed.
+<h4>
+Replication</h4>
+Replication clients are going to need to start all of their individual
+environment handles with the same password.&nbsp; The log records are going
+to be sent to the clients decrypted and the clients will have to encrypt
+them on their way to the client log files.&nbsp; We cannot send encrypted
+log records to clients. &nbsp;The reason is that the checksum and IV&nbsp;are
+stored in the log header and the master only sends the log record itself
+to the client. &nbsp;Therefore, the client has no way to decrypt a log
+record from the master. &nbsp;Therefore, anyone wanting to use truly secure
+replication is going to have to have a secure transport mechanism.&nbsp;
+By not encrypting records, clients can theoretically have different passwords
+and DB won't care.
+<p>On the master side we must copy the DBT sent in.&nbsp; We encrypt the
+original and send to clients the clear record.&nbsp; On the client side,
+support for encryption is added into <i>__log_rep_put</i>.
+<h4>
+Sharing the Environment</h4>
+When multiple processes join the environment, all must use the same password
+as the creator.
+<p>Joining an existing environment requires several conditions to be true.&nbsp;
+First, if the creator of the environment did not create with security,
+then joining later with security is an error.&nbsp; Second, if the creator
+did create it with security, then joining later without security is an
+error.&nbsp; Third, we need to be able to test and check that when another
+process joins a secure environment that the password they provided is the
+same as the one in use by the creator.
+<p>The first two scenarios should be fairly trivial to determine, if we
+aren't creating the environment, we can compare what is there with what
+we have.&nbsp; In the third case, the <i>__crypto_region_init</i> function
+will see that the environment region has a valid passwd_off and we'll then
+compare that password to the one we have in our dbenv handle.&nbsp; In
+any case we'll smash the dbenv handle's passwd and free that memory before
+returning whether we have a password match or not.
+<p>We need to store the passwords themselves in the region because multiple
+calls to the <i>__aes_derivekeys </i>function with the same password yields
+different keyInstance contents.&nbsp; Therefore we don't have any way to
+check passwords other than retaining and comparing the actual passwords.
+<h4>
+Other APIs</h4>
+All of the other APIs will need interface enhancements to support the new
+security methods.&nbsp; The Java and C++ interfaces will likely be done
+by Michael Cahill and Sue will implement the Tcl and RPC changes.&nbsp;
+Tcl will need the changes for testing purposes but the interface should
+be public, not test-only.&nbsp; RPC should fully support security.&nbsp;
+The biggest risk that I can see is that the client will send the password
+to the server in the clear.&nbsp; Anyone sniffing the wires or running
+tcpdump or other packet grabbing code could grab that.&nbsp; Someone really
+interested in using security over RPC probably ought to add authentication
+and other measures to the RPC server as well.
+<h4>
+<a NAME="Utilities"></a>Utilities</h4>
+All should take a -P flag to specify a password for the environment or
+password.&nbsp; Those that take an env and a database might need something
+more to distinguish between env passwds and db passwds. Here is what we
+do for each utility:
+<ul>
+<li>
+berkeley_db_svc - Needs -P after each -h specified.</li>
+
+<li>
+db_archive - Needs -P if the env is encrypted.</li>
+
+<li>
+db_checkpoint - Needs -P if the env is encrypted.</li>
+
+<li>
+db_deadlock - No changes</li>
+
+<li>
+db_dump - Needs -P if the env or database is encrypted.</li>
+
+<li>
+db_load - Needs -P if the env or database is encrypted.</li>
+
+<li>
+db_printlog - Needs -P if the env is encrypted.</li>
+
+<li>
+db_recover - Needs -P if the env is encrypted.</li>
+
+<li>
+db_stat - Needs -P if the env or database is encrypted.</li>
+
+<li>
+db_upgrade - Needs -P if the env or database is encrypted.</li>
+
+<li>
+db_verify - Needs -P if the env or database is encrypted.</li>
+</ul>
+
+<h2>
+Testing</h2>
+All testing should be able to be accomplished via Tcl.&nbsp; The following
+tests (and probably others I haven't thought of yet) should be performed:
+<ul>
+<li>
+Basic functionality - basically a test001 but encrypted without an env</li>
+
+<li>
+Basic functionality, w/ env - like the previous test but with an env.</li>
+
+<li>
+Basic functionality, multiple processes - like first test, but make sure
+others can correctly join.</li>
+
+<li>
+Basic functionality, mult. processes - like above test, but initialize/close
+environment/database first so that the next test processes are all joiners
+of an existing env, but creator no longer exists and the shared region
+must be opened.</li>
+
+<li>
+Recovery test - Run recovery over an encrypted environment.</li>
+
+<li>
+Subdb test - Run with subdbs that are encrypted.</li>
+
+<li>
+Utility test - Verify the new options to all the utilities.</li>
+
+<li>
+Error handling - Test the basic setup errors for both env's and databases
+with multiple processes.&nbsp; They are:</li>
+
+<ol>
+<li>
+Attempt to set a NULL or zero-length passwd.</li>
+
+<li>
+Create Env w/ security and attempt to create database w/ its own password.</li>
+
+<li>
+Env/DB creates with security.&nbsp; Proc2 joins without - should get an
+error.</li>
+
+<li>
+Env/DB creates without security.&nbsp; Proc2 joins with - should get an
+error.</li>
+
+<li>
+Env/DB creates with security.&nbsp; Proc2 joins with different password
+- should get an error.</li>
+
+<li>
+Env/DB creates with security.&nbsp; Closes.&nbsp; Proc2 reopens with different
+password - should get an error.</li>
+
+<li>
+Env/DB creates with security.&nbsp; Closes.&nbsp; Tcl overwrites a page
+of the database with garbage.&nbsp; Proc2 reopens with the correct password.&nbsp;
+Code should detect checksum error.</li>
+
+<li>
+Env/DB creates with security.&nbsp; Open a 2nd identical DB with a different
+password.&nbsp; Put the exact same data into both databases.&nbsp; Close.&nbsp;
+Overwrite the identical page of DB1 with the one from DB2.&nbsp; Reopen
+the database with correct DB1 password.&nbsp; Code should detect an encryption
+error on that page.</li>
+</ol>
+</ul>
+
+<h2>
+Risks</h2>
+There are several holes in this design.&nbsp; It is important to document
+them clearly.
+<p>The first is that all of the pages are stored in memory and possibly
+the file system in the clear.&nbsp; The password is stored in the shared
+data regions in the clear.&nbsp; Therefore if an attacker can read the
+process memory, they can do whatever they want.&nbsp; If the attacker can
+read system memory or swap they can access the data as well.&nbsp; Since
+everything in the shared data regions (with the exception of the buffered
+log) will be in the clear, it is important to realize that file backed
+regions will be written in the clear, including the portion of the regions
+containing passwords.&nbsp; We recommend to users that they use system
+memory instead of file backed shared memory.
+</body>
+</html>
diff --git a/storage/bdb/crypto/mersenne/mt19937db.c b/storage/bdb/crypto/mersenne/mt19937db.c
new file mode 100644
index 0000000000000000000000000000000000000000..1c1699db5c3b7dfe8130b1b6acef01cb329583a8
--- /dev/null
+++ b/storage/bdb/crypto/mersenne/mt19937db.c
@@ -0,0 +1,187 @@
+/*
+ * $Id: mt19937db.c,v 1.12 2004/06/14 16:54:27 mjc Exp $
+ */
+#include "db_config.h"
+
+#include "db_int.h"
+#include "dbinc/crypto.h"
+#include "dbinc/hmac.h"
+
+/* A C-program for MT19937: Integer version (1999/10/28)          */
+/*  genrand() generates one pseudorandom unsigned integer (32bit) */
+/* which is uniformly distributed among 0 to 2^32-1  for each     */
+/* call. sgenrand(seed) sets initial values to the working area   */
+/* of 624 words. Before genrand(), sgenrand(seed) must be         */
+/* called once. (seed is any 32-bit integer.)                     */
+/*   Coded by Takuji Nishimura, considering the suggestions by    */
+/* Topher Cooper and Marc Rieffel in July-Aug. 1997.              */
+
+/* This library is free software under the Artistic license:       */
+/* see the file COPYING distributed together with this code.       */
+/* For the verification of the code, its output sequence file      */
+/* mt19937int.out is attached (2001/4/2)                           */
+
+/* Copyright (C) 1997, 1999 Makoto Matsumoto and Takuji Nishimura. */
+/* Any feedback is very welcome. For any question, comments,       */
+/* see http://www.math.keio.ac.jp/matumoto/emt.html or email       */
+/* matumoto@math.keio.ac.jp                                        */
+
+/* REFERENCE                                                       */
+/* M. Matsumoto and T. Nishimura,                                  */
+/* "Mersenne Twister: A 623-Dimensionally Equidistributed Uniform  */
+/* Pseudo-Random Number Generator",                                */
+/* ACM Transactions on Modeling and Computer Simulation,           */
+/* Vol. 8, No. 1, January 1998, pp 3--30.                          */
+
+/* Period parameters */  
+#define N 624
+#define M 397
+#define MATRIX_A 0x9908b0df   /* constant vector a */
+#define UPPER_MASK 0x80000000 /* most significant w-r bits */
+#define LOWER_MASK 0x7fffffff /* least significant r bits */
+
+/* Tempering parameters */   
+#define TEMPERING_MASK_B 0x9d2c5680
+#define TEMPERING_MASK_C 0xefc60000
+#define TEMPERING_SHIFT_U(y)  (y >> 11)
+#define TEMPERING_SHIFT_S(y)  (y << 7)
+#define TEMPERING_SHIFT_T(y)  (y << 15)
+#define TEMPERING_SHIFT_L(y)  (y >> 18)
+
+static void __db_sgenrand __P((unsigned long, unsigned long *, int *));
+#ifdef	NOT_USED
+static void __db_lsgenrand __P((unsigned long *, unsigned long *, int *));
+#endif
+static unsigned long __db_genrand __P((DB_ENV *));
+
+/*
+ * __db_generate_iv --
+ *	Generate an initialization vector (IV)
+ *
+ * PUBLIC: int __db_generate_iv __P((DB_ENV *, u_int32_t *));
+ */
+int
+__db_generate_iv(dbenv, iv)
+	DB_ENV *dbenv;
+	u_int32_t *iv;
+{
+	int i, n, ret;
+
+	ret = 0;
+	n = DB_IV_BYTES / sizeof(u_int32_t);
+	MUTEX_THREAD_LOCK(dbenv, dbenv->mt_mutexp);
+	if (dbenv->mt == NULL) {
+		if ((ret = __os_calloc(dbenv, 1, N*sizeof(unsigned long),
+		    &dbenv->mt)) != 0)
+			return (ret);
+		/* mti==N+1 means mt[N] is not initialized */
+		dbenv->mti = N + 1;
+	}
+	for (i = 0; i < n; i++)
+{
+		/*
+		 * We do not allow 0.  If we get one just try again.
+		 */
+		do {
+			iv[i] = (u_int32_t)__db_genrand(dbenv);
+		} while (iv[i] == 0);
+}
+
+	MUTEX_THREAD_UNLOCK(dbenv, dbenv->mt_mutexp);
+	return (0);
+}
+
+/* Initializing the array with a seed */
+static void
+__db_sgenrand(seed, mt, mtip)
+	unsigned long seed;	
+	unsigned long mt[];
+	int *mtip;
+{
+    int i;
+
+    DB_ASSERT(seed != 0);
+    for (i=0;i<N;i++) {
+         mt[i] = seed & 0xffff0000;
+         seed = 69069 * seed + 1;
+         mt[i] |= (seed & 0xffff0000) >> 16;
+         seed = 69069 * seed + 1;
+    }
+    *mtip = N;
+}
+
+#ifdef	NOT_USED
+/* Initialization by "sgenrand()" is an example. Theoretically,      */
+/* there are 2^19937-1 possible states as an intial state.           */
+/* This function allows to choose any of 2^19937-1 ones.             */
+/* Essential bits in "seed_array[]" is following 19937 bits:         */
+/*  (seed_array[0]&UPPER_MASK), seed_array[1], ..., seed_array[N-1]. */
+/* (seed_array[0]&LOWER_MASK) is discarded.                          */ 
+/* Theoretically,                                                    */
+/*  (seed_array[0]&UPPER_MASK), seed_array[1], ..., seed_array[N-1]  */
+/* can take any values except all zeros.                             */
+static void
+__db_lsgenrand(seed_array, mt, mtip)
+    unsigned long seed_array[]; 
+    unsigned long mt[]; 
+    int *mtip;
+    /* the length of seed_array[] must be at least N */
+{
+    int i;
+
+    for (i=0;i<N;i++) 
+      mt[i] = seed_array[i];
+    *mtip=N;
+}
+#endif
+
+static unsigned long 
+__db_genrand(dbenv)
+	DB_ENV *dbenv;
+{
+    unsigned long y;
+    static unsigned long mag01[2]={0x0, MATRIX_A};
+    /* mag01[x] = x * MATRIX_A  for x=0,1 */
+    u_int32_t secs, seed, usecs;
+
+    /*
+     * We are called with the mt_mutexp locked
+     */
+    if (dbenv->mti >= N) { /* generate N words at one time */
+        int kk;
+
+        if (dbenv->mti == N+1) {  /* if sgenrand() has not been called, */
+		/*
+		 * Seed the generator with the hashed time.  The __db_mac
+		 * function will return 4 bytes if we don't send in a key.
+		 */
+		do {
+			__os_clock(dbenv, &secs, &usecs);
+			__db_chksum((u_int8_t *)&secs, sizeof(secs), NULL,
+			    (u_int8_t *)&seed);
+		} while (seed == 0);
+        	__db_sgenrand((long)seed, dbenv->mt, &dbenv->mti); 
+	}
+
+        for (kk=0;kk<N-M;kk++) {
+            y = (dbenv->mt[kk]&UPPER_MASK)|(dbenv->mt[kk+1]&LOWER_MASK);
+            dbenv->mt[kk] = dbenv->mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1];
+        }
+        for (;kk<N-1;kk++) {
+            y = (dbenv->mt[kk]&UPPER_MASK)|(dbenv->mt[kk+1]&LOWER_MASK);
+            dbenv->mt[kk] = dbenv->mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1];
+        }
+        y = (dbenv->mt[N-1]&UPPER_MASK)|(dbenv->mt[0]&LOWER_MASK);
+        dbenv->mt[N-1] = dbenv->mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1];
+
+        dbenv->mti = 0;
+    }
+  
+    y = dbenv->mt[dbenv->mti++];
+    y ^= TEMPERING_SHIFT_U(y);
+    y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
+    y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
+    y ^= TEMPERING_SHIFT_L(y);
+
+    return y; 
+}
diff --git a/storage/bdb/crypto/rijndael/rijndael-alg-fst.c b/storage/bdb/crypto/rijndael/rijndael-alg-fst.c
new file mode 100644
index 0000000000000000000000000000000000000000..4a251606d28f7028db103a858528b0caf4fc41cb
--- /dev/null
+++ b/storage/bdb/crypto/rijndael/rijndael-alg-fst.c
@@ -0,0 +1,1466 @@
+/**
+ * rijndael-alg-fst.c
+ *
+ * @version 3.0 (December 2000)
+ *
+ * Optimised ANSI C code for the Rijndael cipher (now AES)
+ *
+ * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
+ * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
+ * @author Paulo Barreto <paulo.barreto@terra.com.br>
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "db_config.h"
+
+#include "db_int.h"
+#include "dbinc/crypto.h"
+
+#include "crypto/rijndael/rijndael-alg-fst.h"
+
+/*
+Te0[x] = S [x].[02, 01, 01, 03];
+Te1[x] = S [x].[03, 02, 01, 01];
+Te2[x] = S [x].[01, 03, 02, 01];
+Te3[x] = S [x].[01, 01, 03, 02];
+Te4[x] = S [x].[01, 01, 01, 01];
+
+Td0[x] = Si[x].[0e, 09, 0d, 0b];
+Td1[x] = Si[x].[0b, 0e, 09, 0d];
+Td2[x] = Si[x].[0d, 0b, 0e, 09];
+Td3[x] = Si[x].[09, 0d, 0b, 0e];
+Td4[x] = Si[x].[01, 01, 01, 01];
+*/
+
+static const u32 Te0[256] = {
+    (u_int)0xc66363a5, (u_int)0xf87c7c84, (u_int)0xee777799, (u_int)0xf67b7b8d,
+    (u_int)0xfff2f20d, (u_int)0xd66b6bbd, (u_int)0xde6f6fb1, (u_int)0x91c5c554,
+    (u_int)0x60303050, (u_int)0x02010103, (u_int)0xce6767a9, (u_int)0x562b2b7d,
+    (u_int)0xe7fefe19, (u_int)0xb5d7d762, (u_int)0x4dababe6, (u_int)0xec76769a,
+    (u_int)0x8fcaca45, (u_int)0x1f82829d, (u_int)0x89c9c940, (u_int)0xfa7d7d87,
+    (u_int)0xeffafa15, (u_int)0xb25959eb, (u_int)0x8e4747c9, (u_int)0xfbf0f00b,
+    (u_int)0x41adadec, (u_int)0xb3d4d467, (u_int)0x5fa2a2fd, (u_int)0x45afafea,
+    (u_int)0x239c9cbf, (u_int)0x53a4a4f7, (u_int)0xe4727296, (u_int)0x9bc0c05b,
+    (u_int)0x75b7b7c2, (u_int)0xe1fdfd1c, (u_int)0x3d9393ae, (u_int)0x4c26266a,
+    (u_int)0x6c36365a, (u_int)0x7e3f3f41, (u_int)0xf5f7f702, (u_int)0x83cccc4f,
+    (u_int)0x6834345c, (u_int)0x51a5a5f4, (u_int)0xd1e5e534, (u_int)0xf9f1f108,
+    (u_int)0xe2717193, (u_int)0xabd8d873, (u_int)0x62313153, (u_int)0x2a15153f,
+    (u_int)0x0804040c, (u_int)0x95c7c752, (u_int)0x46232365, (u_int)0x9dc3c35e,
+    (u_int)0x30181828, (u_int)0x379696a1, (u_int)0x0a05050f, (u_int)0x2f9a9ab5,
+    (u_int)0x0e070709, (u_int)0x24121236, (u_int)0x1b80809b, (u_int)0xdfe2e23d,
+    (u_int)0xcdebeb26, (u_int)0x4e272769, (u_int)0x7fb2b2cd, (u_int)0xea75759f,
+    (u_int)0x1209091b, (u_int)0x1d83839e, (u_int)0x582c2c74, (u_int)0x341a1a2e,
+    (u_int)0x361b1b2d, (u_int)0xdc6e6eb2, (u_int)0xb45a5aee, (u_int)0x5ba0a0fb,
+    (u_int)0xa45252f6, (u_int)0x763b3b4d, (u_int)0xb7d6d661, (u_int)0x7db3b3ce,
+    (u_int)0x5229297b, (u_int)0xdde3e33e, (u_int)0x5e2f2f71, (u_int)0x13848497,
+    (u_int)0xa65353f5, (u_int)0xb9d1d168, (u_int)0x00000000, (u_int)0xc1eded2c,
+    (u_int)0x40202060, (u_int)0xe3fcfc1f, (u_int)0x79b1b1c8, (u_int)0xb65b5bed,
+    (u_int)0xd46a6abe, (u_int)0x8dcbcb46, (u_int)0x67bebed9, (u_int)0x7239394b,
+    (u_int)0x944a4ade, (u_int)0x984c4cd4, (u_int)0xb05858e8, (u_int)0x85cfcf4a,
+    (u_int)0xbbd0d06b, (u_int)0xc5efef2a, (u_int)0x4faaaae5, (u_int)0xedfbfb16,
+    (u_int)0x864343c5, (u_int)0x9a4d4dd7, (u_int)0x66333355, (u_int)0x11858594,
+    (u_int)0x8a4545cf, (u_int)0xe9f9f910, (u_int)0x04020206, (u_int)0xfe7f7f81,
+    (u_int)0xa05050f0, (u_int)0x783c3c44, (u_int)0x259f9fba, (u_int)0x4ba8a8e3,
+    (u_int)0xa25151f3, (u_int)0x5da3a3fe, (u_int)0x804040c0, (u_int)0x058f8f8a,
+    (u_int)0x3f9292ad, (u_int)0x219d9dbc, (u_int)0x70383848, (u_int)0xf1f5f504,
+    (u_int)0x63bcbcdf, (u_int)0x77b6b6c1, (u_int)0xafdada75, (u_int)0x42212163,
+    (u_int)0x20101030, (u_int)0xe5ffff1a, (u_int)0xfdf3f30e, (u_int)0xbfd2d26d,
+    (u_int)0x81cdcd4c, (u_int)0x180c0c14, (u_int)0x26131335, (u_int)0xc3ecec2f,
+    (u_int)0xbe5f5fe1, (u_int)0x359797a2, (u_int)0x884444cc, (u_int)0x2e171739,
+    (u_int)0x93c4c457, (u_int)0x55a7a7f2, (u_int)0xfc7e7e82, (u_int)0x7a3d3d47,
+    (u_int)0xc86464ac, (u_int)0xba5d5de7, (u_int)0x3219192b, (u_int)0xe6737395,
+    (u_int)0xc06060a0, (u_int)0x19818198, (u_int)0x9e4f4fd1, (u_int)0xa3dcdc7f,
+    (u_int)0x44222266, (u_int)0x542a2a7e, (u_int)0x3b9090ab, (u_int)0x0b888883,
+    (u_int)0x8c4646ca, (u_int)0xc7eeee29, (u_int)0x6bb8b8d3, (u_int)0x2814143c,
+    (u_int)0xa7dede79, (u_int)0xbc5e5ee2, (u_int)0x160b0b1d, (u_int)0xaddbdb76,
+    (u_int)0xdbe0e03b, (u_int)0x64323256, (u_int)0x743a3a4e, (u_int)0x140a0a1e,
+    (u_int)0x924949db, (u_int)0x0c06060a, (u_int)0x4824246c, (u_int)0xb85c5ce4,
+    (u_int)0x9fc2c25d, (u_int)0xbdd3d36e, (u_int)0x43acacef, (u_int)0xc46262a6,
+    (u_int)0x399191a8, (u_int)0x319595a4, (u_int)0xd3e4e437, (u_int)0xf279798b,
+    (u_int)0xd5e7e732, (u_int)0x8bc8c843, (u_int)0x6e373759, (u_int)0xda6d6db7,
+    (u_int)0x018d8d8c, (u_int)0xb1d5d564, (u_int)0x9c4e4ed2, (u_int)0x49a9a9e0,
+    (u_int)0xd86c6cb4, (u_int)0xac5656fa, (u_int)0xf3f4f407, (u_int)0xcfeaea25,
+    (u_int)0xca6565af, (u_int)0xf47a7a8e, (u_int)0x47aeaee9, (u_int)0x10080818,
+    (u_int)0x6fbabad5, (u_int)0xf0787888, (u_int)0x4a25256f, (u_int)0x5c2e2e72,
+    (u_int)0x381c1c24, (u_int)0x57a6a6f1, (u_int)0x73b4b4c7, (u_int)0x97c6c651,
+    (u_int)0xcbe8e823, (u_int)0xa1dddd7c, (u_int)0xe874749c, (u_int)0x3e1f1f21,
+    (u_int)0x964b4bdd, (u_int)0x61bdbddc, (u_int)0x0d8b8b86, (u_int)0x0f8a8a85,
+    (u_int)0xe0707090, (u_int)0x7c3e3e42, (u_int)0x71b5b5c4, (u_int)0xcc6666aa,
+    (u_int)0x904848d8, (u_int)0x06030305, (u_int)0xf7f6f601, (u_int)0x1c0e0e12,
+    (u_int)0xc26161a3, (u_int)0x6a35355f, (u_int)0xae5757f9, (u_int)0x69b9b9d0,
+    (u_int)0x17868691, (u_int)0x99c1c158, (u_int)0x3a1d1d27, (u_int)0x279e9eb9,
+    (u_int)0xd9e1e138, (u_int)0xebf8f813, (u_int)0x2b9898b3, (u_int)0x22111133,
+    (u_int)0xd26969bb, (u_int)0xa9d9d970, (u_int)0x078e8e89, (u_int)0x339494a7,
+    (u_int)0x2d9b9bb6, (u_int)0x3c1e1e22, (u_int)0x15878792, (u_int)0xc9e9e920,
+    (u_int)0x87cece49, (u_int)0xaa5555ff, (u_int)0x50282878, (u_int)0xa5dfdf7a,
+    (u_int)0x038c8c8f, (u_int)0x59a1a1f8, (u_int)0x09898980, (u_int)0x1a0d0d17,
+    (u_int)0x65bfbfda, (u_int)0xd7e6e631, (u_int)0x844242c6, (u_int)0xd06868b8,
+    (u_int)0x824141c3, (u_int)0x299999b0, (u_int)0x5a2d2d77, (u_int)0x1e0f0f11,
+    (u_int)0x7bb0b0cb, (u_int)0xa85454fc, (u_int)0x6dbbbbd6, (u_int)0x2c16163a,
+};
+static const u32 Te1[256] = {
+    (u_int)0xa5c66363, (u_int)0x84f87c7c, (u_int)0x99ee7777, (u_int)0x8df67b7b,
+    (u_int)0x0dfff2f2, (u_int)0xbdd66b6b, (u_int)0xb1de6f6f, (u_int)0x5491c5c5,
+    (u_int)0x50603030, (u_int)0x03020101, (u_int)0xa9ce6767, (u_int)0x7d562b2b,
+    (u_int)0x19e7fefe, (u_int)0x62b5d7d7, (u_int)0xe64dabab, (u_int)0x9aec7676,
+    (u_int)0x458fcaca, (u_int)0x9d1f8282, (u_int)0x4089c9c9, (u_int)0x87fa7d7d,
+    (u_int)0x15effafa, (u_int)0xebb25959, (u_int)0xc98e4747, (u_int)0x0bfbf0f0,
+    (u_int)0xec41adad, (u_int)0x67b3d4d4, (u_int)0xfd5fa2a2, (u_int)0xea45afaf,
+    (u_int)0xbf239c9c, (u_int)0xf753a4a4, (u_int)0x96e47272, (u_int)0x5b9bc0c0,
+    (u_int)0xc275b7b7, (u_int)0x1ce1fdfd, (u_int)0xae3d9393, (u_int)0x6a4c2626,
+    (u_int)0x5a6c3636, (u_int)0x417e3f3f, (u_int)0x02f5f7f7, (u_int)0x4f83cccc,
+    (u_int)0x5c683434, (u_int)0xf451a5a5, (u_int)0x34d1e5e5, (u_int)0x08f9f1f1,
+    (u_int)0x93e27171, (u_int)0x73abd8d8, (u_int)0x53623131, (u_int)0x3f2a1515,
+    (u_int)0x0c080404, (u_int)0x5295c7c7, (u_int)0x65462323, (u_int)0x5e9dc3c3,
+    (u_int)0x28301818, (u_int)0xa1379696, (u_int)0x0f0a0505, (u_int)0xb52f9a9a,
+    (u_int)0x090e0707, (u_int)0x36241212, (u_int)0x9b1b8080, (u_int)0x3ddfe2e2,
+    (u_int)0x26cdebeb, (u_int)0x694e2727, (u_int)0xcd7fb2b2, (u_int)0x9fea7575,
+    (u_int)0x1b120909, (u_int)0x9e1d8383, (u_int)0x74582c2c, (u_int)0x2e341a1a,
+    (u_int)0x2d361b1b, (u_int)0xb2dc6e6e, (u_int)0xeeb45a5a, (u_int)0xfb5ba0a0,
+    (u_int)0xf6a45252, (u_int)0x4d763b3b, (u_int)0x61b7d6d6, (u_int)0xce7db3b3,
+    (u_int)0x7b522929, (u_int)0x3edde3e3, (u_int)0x715e2f2f, (u_int)0x97138484,
+    (u_int)0xf5a65353, (u_int)0x68b9d1d1, (u_int)0x00000000, (u_int)0x2cc1eded,
+    (u_int)0x60402020, (u_int)0x1fe3fcfc, (u_int)0xc879b1b1, (u_int)0xedb65b5b,
+    (u_int)0xbed46a6a, (u_int)0x468dcbcb, (u_int)0xd967bebe, (u_int)0x4b723939,
+    (u_int)0xde944a4a, (u_int)0xd4984c4c, (u_int)0xe8b05858, (u_int)0x4a85cfcf,
+    (u_int)0x6bbbd0d0, (u_int)0x2ac5efef, (u_int)0xe54faaaa, (u_int)0x16edfbfb,
+    (u_int)0xc5864343, (u_int)0xd79a4d4d, (u_int)0x55663333, (u_int)0x94118585,
+    (u_int)0xcf8a4545, (u_int)0x10e9f9f9, (u_int)0x06040202, (u_int)0x81fe7f7f,
+    (u_int)0xf0a05050, (u_int)0x44783c3c, (u_int)0xba259f9f, (u_int)0xe34ba8a8,
+    (u_int)0xf3a25151, (u_int)0xfe5da3a3, (u_int)0xc0804040, (u_int)0x8a058f8f,
+    (u_int)0xad3f9292, (u_int)0xbc219d9d, (u_int)0x48703838, (u_int)0x04f1f5f5,
+    (u_int)0xdf63bcbc, (u_int)0xc177b6b6, (u_int)0x75afdada, (u_int)0x63422121,
+    (u_int)0x30201010, (u_int)0x1ae5ffff, (u_int)0x0efdf3f3, (u_int)0x6dbfd2d2,
+    (u_int)0x4c81cdcd, (u_int)0x14180c0c, (u_int)0x35261313, (u_int)0x2fc3ecec,
+    (u_int)0xe1be5f5f, (u_int)0xa2359797, (u_int)0xcc884444, (u_int)0x392e1717,
+    (u_int)0x5793c4c4, (u_int)0xf255a7a7, (u_int)0x82fc7e7e, (u_int)0x477a3d3d,
+    (u_int)0xacc86464, (u_int)0xe7ba5d5d, (u_int)0x2b321919, (u_int)0x95e67373,
+    (u_int)0xa0c06060, (u_int)0x98198181, (u_int)0xd19e4f4f, (u_int)0x7fa3dcdc,
+    (u_int)0x66442222, (u_int)0x7e542a2a, (u_int)0xab3b9090, (u_int)0x830b8888,
+    (u_int)0xca8c4646, (u_int)0x29c7eeee, (u_int)0xd36bb8b8, (u_int)0x3c281414,
+    (u_int)0x79a7dede, (u_int)0xe2bc5e5e, (u_int)0x1d160b0b, (u_int)0x76addbdb,
+    (u_int)0x3bdbe0e0, (u_int)0x56643232, (u_int)0x4e743a3a, (u_int)0x1e140a0a,
+    (u_int)0xdb924949, (u_int)0x0a0c0606, (u_int)0x6c482424, (u_int)0xe4b85c5c,
+    (u_int)0x5d9fc2c2, (u_int)0x6ebdd3d3, (u_int)0xef43acac, (u_int)0xa6c46262,
+    (u_int)0xa8399191, (u_int)0xa4319595, (u_int)0x37d3e4e4, (u_int)0x8bf27979,
+    (u_int)0x32d5e7e7, (u_int)0x438bc8c8, (u_int)0x596e3737, (u_int)0xb7da6d6d,
+    (u_int)0x8c018d8d, (u_int)0x64b1d5d5, (u_int)0xd29c4e4e, (u_int)0xe049a9a9,
+    (u_int)0xb4d86c6c, (u_int)0xfaac5656, (u_int)0x07f3f4f4, (u_int)0x25cfeaea,
+    (u_int)0xafca6565, (u_int)0x8ef47a7a, (u_int)0xe947aeae, (u_int)0x18100808,
+    (u_int)0xd56fbaba, (u_int)0x88f07878, (u_int)0x6f4a2525, (u_int)0x725c2e2e,
+    (u_int)0x24381c1c, (u_int)0xf157a6a6, (u_int)0xc773b4b4, (u_int)0x5197c6c6,
+    (u_int)0x23cbe8e8, (u_int)0x7ca1dddd, (u_int)0x9ce87474, (u_int)0x213e1f1f,
+    (u_int)0xdd964b4b, (u_int)0xdc61bdbd, (u_int)0x860d8b8b, (u_int)0x850f8a8a,
+    (u_int)0x90e07070, (u_int)0x427c3e3e, (u_int)0xc471b5b5, (u_int)0xaacc6666,
+    (u_int)0xd8904848, (u_int)0x05060303, (u_int)0x01f7f6f6, (u_int)0x121c0e0e,
+    (u_int)0xa3c26161, (u_int)0x5f6a3535, (u_int)0xf9ae5757, (u_int)0xd069b9b9,
+    (u_int)0x91178686, (u_int)0x5899c1c1, (u_int)0x273a1d1d, (u_int)0xb9279e9e,
+    (u_int)0x38d9e1e1, (u_int)0x13ebf8f8, (u_int)0xb32b9898, (u_int)0x33221111,
+    (u_int)0xbbd26969, (u_int)0x70a9d9d9, (u_int)0x89078e8e, (u_int)0xa7339494,
+    (u_int)0xb62d9b9b, (u_int)0x223c1e1e, (u_int)0x92158787, (u_int)0x20c9e9e9,
+    (u_int)0x4987cece, (u_int)0xffaa5555, (u_int)0x78502828, (u_int)0x7aa5dfdf,
+    (u_int)0x8f038c8c, (u_int)0xf859a1a1, (u_int)0x80098989, (u_int)0x171a0d0d,
+    (u_int)0xda65bfbf, (u_int)0x31d7e6e6, (u_int)0xc6844242, (u_int)0xb8d06868,
+    (u_int)0xc3824141, (u_int)0xb0299999, (u_int)0x775a2d2d, (u_int)0x111e0f0f,
+    (u_int)0xcb7bb0b0, (u_int)0xfca85454, (u_int)0xd66dbbbb, (u_int)0x3a2c1616,
+};
+static const u32 Te2[256] = {
+    (u_int)0x63a5c663, (u_int)0x7c84f87c, (u_int)0x7799ee77, (u_int)0x7b8df67b,
+    (u_int)0xf20dfff2, (u_int)0x6bbdd66b, (u_int)0x6fb1de6f, (u_int)0xc55491c5,
+    (u_int)0x30506030, (u_int)0x01030201, (u_int)0x67a9ce67, (u_int)0x2b7d562b,
+    (u_int)0xfe19e7fe, (u_int)0xd762b5d7, (u_int)0xabe64dab, (u_int)0x769aec76,
+    (u_int)0xca458fca, (u_int)0x829d1f82, (u_int)0xc94089c9, (u_int)0x7d87fa7d,
+    (u_int)0xfa15effa, (u_int)0x59ebb259, (u_int)0x47c98e47, (u_int)0xf00bfbf0,
+    (u_int)0xadec41ad, (u_int)0xd467b3d4, (u_int)0xa2fd5fa2, (u_int)0xafea45af,
+    (u_int)0x9cbf239c, (u_int)0xa4f753a4, (u_int)0x7296e472, (u_int)0xc05b9bc0,
+    (u_int)0xb7c275b7, (u_int)0xfd1ce1fd, (u_int)0x93ae3d93, (u_int)0x266a4c26,
+    (u_int)0x365a6c36, (u_int)0x3f417e3f, (u_int)0xf702f5f7, (u_int)0xcc4f83cc,
+    (u_int)0x345c6834, (u_int)0xa5f451a5, (u_int)0xe534d1e5, (u_int)0xf108f9f1,
+    (u_int)0x7193e271, (u_int)0xd873abd8, (u_int)0x31536231, (u_int)0x153f2a15,
+    (u_int)0x040c0804, (u_int)0xc75295c7, (u_int)0x23654623, (u_int)0xc35e9dc3,
+    (u_int)0x18283018, (u_int)0x96a13796, (u_int)0x050f0a05, (u_int)0x9ab52f9a,
+    (u_int)0x07090e07, (u_int)0x12362412, (u_int)0x809b1b80, (u_int)0xe23ddfe2,
+    (u_int)0xeb26cdeb, (u_int)0x27694e27, (u_int)0xb2cd7fb2, (u_int)0x759fea75,
+    (u_int)0x091b1209, (u_int)0x839e1d83, (u_int)0x2c74582c, (u_int)0x1a2e341a,
+    (u_int)0x1b2d361b, (u_int)0x6eb2dc6e, (u_int)0x5aeeb45a, (u_int)0xa0fb5ba0,
+    (u_int)0x52f6a452, (u_int)0x3b4d763b, (u_int)0xd661b7d6, (u_int)0xb3ce7db3,
+    (u_int)0x297b5229, (u_int)0xe33edde3, (u_int)0x2f715e2f, (u_int)0x84971384,
+    (u_int)0x53f5a653, (u_int)0xd168b9d1, (u_int)0x00000000, (u_int)0xed2cc1ed,
+    (u_int)0x20604020, (u_int)0xfc1fe3fc, (u_int)0xb1c879b1, (u_int)0x5bedb65b,
+    (u_int)0x6abed46a, (u_int)0xcb468dcb, (u_int)0xbed967be, (u_int)0x394b7239,
+    (u_int)0x4ade944a, (u_int)0x4cd4984c, (u_int)0x58e8b058, (u_int)0xcf4a85cf,
+    (u_int)0xd06bbbd0, (u_int)0xef2ac5ef, (u_int)0xaae54faa, (u_int)0xfb16edfb,
+    (u_int)0x43c58643, (u_int)0x4dd79a4d, (u_int)0x33556633, (u_int)0x85941185,
+    (u_int)0x45cf8a45, (u_int)0xf910e9f9, (u_int)0x02060402, (u_int)0x7f81fe7f,
+    (u_int)0x50f0a050, (u_int)0x3c44783c, (u_int)0x9fba259f, (u_int)0xa8e34ba8,
+    (u_int)0x51f3a251, (u_int)0xa3fe5da3, (u_int)0x40c08040, (u_int)0x8f8a058f,
+    (u_int)0x92ad3f92, (u_int)0x9dbc219d, (u_int)0x38487038, (u_int)0xf504f1f5,
+    (u_int)0xbcdf63bc, (u_int)0xb6c177b6, (u_int)0xda75afda, (u_int)0x21634221,
+    (u_int)0x10302010, (u_int)0xff1ae5ff, (u_int)0xf30efdf3, (u_int)0xd26dbfd2,
+    (u_int)0xcd4c81cd, (u_int)0x0c14180c, (u_int)0x13352613, (u_int)0xec2fc3ec,
+    (u_int)0x5fe1be5f, (u_int)0x97a23597, (u_int)0x44cc8844, (u_int)0x17392e17,
+    (u_int)0xc45793c4, (u_int)0xa7f255a7, (u_int)0x7e82fc7e, (u_int)0x3d477a3d,
+    (u_int)0x64acc864, (u_int)0x5de7ba5d, (u_int)0x192b3219, (u_int)0x7395e673,
+    (u_int)0x60a0c060, (u_int)0x81981981, (u_int)0x4fd19e4f, (u_int)0xdc7fa3dc,
+    (u_int)0x22664422, (u_int)0x2a7e542a, (u_int)0x90ab3b90, (u_int)0x88830b88,
+    (u_int)0x46ca8c46, (u_int)0xee29c7ee, (u_int)0xb8d36bb8, (u_int)0x143c2814,
+    (u_int)0xde79a7de, (u_int)0x5ee2bc5e, (u_int)0x0b1d160b, (u_int)0xdb76addb,
+    (u_int)0xe03bdbe0, (u_int)0x32566432, (u_int)0x3a4e743a, (u_int)0x0a1e140a,
+    (u_int)0x49db9249, (u_int)0x060a0c06, (u_int)0x246c4824, (u_int)0x5ce4b85c,
+    (u_int)0xc25d9fc2, (u_int)0xd36ebdd3, (u_int)0xacef43ac, (u_int)0x62a6c462,
+    (u_int)0x91a83991, (u_int)0x95a43195, (u_int)0xe437d3e4, (u_int)0x798bf279,
+    (u_int)0xe732d5e7, (u_int)0xc8438bc8, (u_int)0x37596e37, (u_int)0x6db7da6d,
+    (u_int)0x8d8c018d, (u_int)0xd564b1d5, (u_int)0x4ed29c4e, (u_int)0xa9e049a9,
+    (u_int)0x6cb4d86c, (u_int)0x56faac56, (u_int)0xf407f3f4, (u_int)0xea25cfea,
+    (u_int)0x65afca65, (u_int)0x7a8ef47a, (u_int)0xaee947ae, (u_int)0x08181008,
+    (u_int)0xbad56fba, (u_int)0x7888f078, (u_int)0x256f4a25, (u_int)0x2e725c2e,
+    (u_int)0x1c24381c, (u_int)0xa6f157a6, (u_int)0xb4c773b4, (u_int)0xc65197c6,
+    (u_int)0xe823cbe8, (u_int)0xdd7ca1dd, (u_int)0x749ce874, (u_int)0x1f213e1f,
+    (u_int)0x4bdd964b, (u_int)0xbddc61bd, (u_int)0x8b860d8b, (u_int)0x8a850f8a,
+    (u_int)0x7090e070, (u_int)0x3e427c3e, (u_int)0xb5c471b5, (u_int)0x66aacc66,
+    (u_int)0x48d89048, (u_int)0x03050603, (u_int)0xf601f7f6, (u_int)0x0e121c0e,
+    (u_int)0x61a3c261, (u_int)0x355f6a35, (u_int)0x57f9ae57, (u_int)0xb9d069b9,
+    (u_int)0x86911786, (u_int)0xc15899c1, (u_int)0x1d273a1d, (u_int)0x9eb9279e,
+    (u_int)0xe138d9e1, (u_int)0xf813ebf8, (u_int)0x98b32b98, (u_int)0x11332211,
+    (u_int)0x69bbd269, (u_int)0xd970a9d9, (u_int)0x8e89078e, (u_int)0x94a73394,
+    (u_int)0x9bb62d9b, (u_int)0x1e223c1e, (u_int)0x87921587, (u_int)0xe920c9e9,
+    (u_int)0xce4987ce, (u_int)0x55ffaa55, (u_int)0x28785028, (u_int)0xdf7aa5df,
+    (u_int)0x8c8f038c, (u_int)0xa1f859a1, (u_int)0x89800989, (u_int)0x0d171a0d,
+    (u_int)0xbfda65bf, (u_int)0xe631d7e6, (u_int)0x42c68442, (u_int)0x68b8d068,
+    (u_int)0x41c38241, (u_int)0x99b02999, (u_int)0x2d775a2d, (u_int)0x0f111e0f,
+    (u_int)0xb0cb7bb0, (u_int)0x54fca854, (u_int)0xbbd66dbb, (u_int)0x163a2c16,
+};
+static const u32 Te3[256] = {
+
+    (u_int)0x6363a5c6, (u_int)0x7c7c84f8, (u_int)0x777799ee, (u_int)0x7b7b8df6,
+    (u_int)0xf2f20dff, (u_int)0x6b6bbdd6, (u_int)0x6f6fb1de, (u_int)0xc5c55491,
+    (u_int)0x30305060, (u_int)0x01010302, (u_int)0x6767a9ce, (u_int)0x2b2b7d56,
+    (u_int)0xfefe19e7, (u_int)0xd7d762b5, (u_int)0xababe64d, (u_int)0x76769aec,
+    (u_int)0xcaca458f, (u_int)0x82829d1f, (u_int)0xc9c94089, (u_int)0x7d7d87fa,
+    (u_int)0xfafa15ef, (u_int)0x5959ebb2, (u_int)0x4747c98e, (u_int)0xf0f00bfb,
+    (u_int)0xadadec41, (u_int)0xd4d467b3, (u_int)0xa2a2fd5f, (u_int)0xafafea45,
+    (u_int)0x9c9cbf23, (u_int)0xa4a4f753, (u_int)0x727296e4, (u_int)0xc0c05b9b,
+    (u_int)0xb7b7c275, (u_int)0xfdfd1ce1, (u_int)0x9393ae3d, (u_int)0x26266a4c,
+    (u_int)0x36365a6c, (u_int)0x3f3f417e, (u_int)0xf7f702f5, (u_int)0xcccc4f83,
+    (u_int)0x34345c68, (u_int)0xa5a5f451, (u_int)0xe5e534d1, (u_int)0xf1f108f9,
+    (u_int)0x717193e2, (u_int)0xd8d873ab, (u_int)0x31315362, (u_int)0x15153f2a,
+    (u_int)0x04040c08, (u_int)0xc7c75295, (u_int)0x23236546, (u_int)0xc3c35e9d,
+    (u_int)0x18182830, (u_int)0x9696a137, (u_int)0x05050f0a, (u_int)0x9a9ab52f,
+    (u_int)0x0707090e, (u_int)0x12123624, (u_int)0x80809b1b, (u_int)0xe2e23ddf,
+    (u_int)0xebeb26cd, (u_int)0x2727694e, (u_int)0xb2b2cd7f, (u_int)0x75759fea,
+    (u_int)0x09091b12, (u_int)0x83839e1d, (u_int)0x2c2c7458, (u_int)0x1a1a2e34,
+    (u_int)0x1b1b2d36, (u_int)0x6e6eb2dc, (u_int)0x5a5aeeb4, (u_int)0xa0a0fb5b,
+    (u_int)0x5252f6a4, (u_int)0x3b3b4d76, (u_int)0xd6d661b7, (u_int)0xb3b3ce7d,
+    (u_int)0x29297b52, (u_int)0xe3e33edd, (u_int)0x2f2f715e, (u_int)0x84849713,
+    (u_int)0x5353f5a6, (u_int)0xd1d168b9, (u_int)0x00000000, (u_int)0xeded2cc1,
+    (u_int)0x20206040, (u_int)0xfcfc1fe3, (u_int)0xb1b1c879, (u_int)0x5b5bedb6,
+    (u_int)0x6a6abed4, (u_int)0xcbcb468d, (u_int)0xbebed967, (u_int)0x39394b72,
+    (u_int)0x4a4ade94, (u_int)0x4c4cd498, (u_int)0x5858e8b0, (u_int)0xcfcf4a85,
+    (u_int)0xd0d06bbb, (u_int)0xefef2ac5, (u_int)0xaaaae54f, (u_int)0xfbfb16ed,
+    (u_int)0x4343c586, (u_int)0x4d4dd79a, (u_int)0x33335566, (u_int)0x85859411,
+    (u_int)0x4545cf8a, (u_int)0xf9f910e9, (u_int)0x02020604, (u_int)0x7f7f81fe,
+    (u_int)0x5050f0a0, (u_int)0x3c3c4478, (u_int)0x9f9fba25, (u_int)0xa8a8e34b,
+    (u_int)0x5151f3a2, (u_int)0xa3a3fe5d, (u_int)0x4040c080, (u_int)0x8f8f8a05,
+    (u_int)0x9292ad3f, (u_int)0x9d9dbc21, (u_int)0x38384870, (u_int)0xf5f504f1,
+    (u_int)0xbcbcdf63, (u_int)0xb6b6c177, (u_int)0xdada75af, (u_int)0x21216342,
+    (u_int)0x10103020, (u_int)0xffff1ae5, (u_int)0xf3f30efd, (u_int)0xd2d26dbf,
+    (u_int)0xcdcd4c81, (u_int)0x0c0c1418, (u_int)0x13133526, (u_int)0xecec2fc3,
+    (u_int)0x5f5fe1be, (u_int)0x9797a235, (u_int)0x4444cc88, (u_int)0x1717392e,
+    (u_int)0xc4c45793, (u_int)0xa7a7f255, (u_int)0x7e7e82fc, (u_int)0x3d3d477a,
+    (u_int)0x6464acc8, (u_int)0x5d5de7ba, (u_int)0x19192b32, (u_int)0x737395e6,
+    (u_int)0x6060a0c0, (u_int)0x81819819, (u_int)0x4f4fd19e, (u_int)0xdcdc7fa3,
+    (u_int)0x22226644, (u_int)0x2a2a7e54, (u_int)0x9090ab3b, (u_int)0x8888830b,
+    (u_int)0x4646ca8c, (u_int)0xeeee29c7, (u_int)0xb8b8d36b, (u_int)0x14143c28,
+    (u_int)0xdede79a7, (u_int)0x5e5ee2bc, (u_int)0x0b0b1d16, (u_int)0xdbdb76ad,
+    (u_int)0xe0e03bdb, (u_int)0x32325664, (u_int)0x3a3a4e74, (u_int)0x0a0a1e14,
+    (u_int)0x4949db92, (u_int)0x06060a0c, (u_int)0x24246c48, (u_int)0x5c5ce4b8,
+    (u_int)0xc2c25d9f, (u_int)0xd3d36ebd, (u_int)0xacacef43, (u_int)0x6262a6c4,
+    (u_int)0x9191a839, (u_int)0x9595a431, (u_int)0xe4e437d3, (u_int)0x79798bf2,
+    (u_int)0xe7e732d5, (u_int)0xc8c8438b, (u_int)0x3737596e, (u_int)0x6d6db7da,
+    (u_int)0x8d8d8c01, (u_int)0xd5d564b1, (u_int)0x4e4ed29c, (u_int)0xa9a9e049,
+    (u_int)0x6c6cb4d8, (u_int)0x5656faac, (u_int)0xf4f407f3, (u_int)0xeaea25cf,
+    (u_int)0x6565afca, (u_int)0x7a7a8ef4, (u_int)0xaeaee947, (u_int)0x08081810,
+    (u_int)0xbabad56f, (u_int)0x787888f0, (u_int)0x25256f4a, (u_int)0x2e2e725c,
+    (u_int)0x1c1c2438, (u_int)0xa6a6f157, (u_int)0xb4b4c773, (u_int)0xc6c65197,
+    (u_int)0xe8e823cb, (u_int)0xdddd7ca1, (u_int)0x74749ce8, (u_int)0x1f1f213e,
+    (u_int)0x4b4bdd96, (u_int)0xbdbddc61, (u_int)0x8b8b860d, (u_int)0x8a8a850f,
+    (u_int)0x707090e0, (u_int)0x3e3e427c, (u_int)0xb5b5c471, (u_int)0x6666aacc,
+    (u_int)0x4848d890, (u_int)0x03030506, (u_int)0xf6f601f7, (u_int)0x0e0e121c,
+    (u_int)0x6161a3c2, (u_int)0x35355f6a, (u_int)0x5757f9ae, (u_int)0xb9b9d069,
+    (u_int)0x86869117, (u_int)0xc1c15899, (u_int)0x1d1d273a, (u_int)0x9e9eb927,
+    (u_int)0xe1e138d9, (u_int)0xf8f813eb, (u_int)0x9898b32b, (u_int)0x11113322,
+    (u_int)0x6969bbd2, (u_int)0xd9d970a9, (u_int)0x8e8e8907, (u_int)0x9494a733,
+    (u_int)0x9b9bb62d, (u_int)0x1e1e223c, (u_int)0x87879215, (u_int)0xe9e920c9,
+    (u_int)0xcece4987, (u_int)0x5555ffaa, (u_int)0x28287850, (u_int)0xdfdf7aa5,
+    (u_int)0x8c8c8f03, (u_int)0xa1a1f859, (u_int)0x89898009, (u_int)0x0d0d171a,
+    (u_int)0xbfbfda65, (u_int)0xe6e631d7, (u_int)0x4242c684, (u_int)0x6868b8d0,
+    (u_int)0x4141c382, (u_int)0x9999b029, (u_int)0x2d2d775a, (u_int)0x0f0f111e,
+    (u_int)0xb0b0cb7b, (u_int)0x5454fca8, (u_int)0xbbbbd66d, (u_int)0x16163a2c,
+};
+static const u32 Te4[256] = {
+    (u_int)0x63636363, (u_int)0x7c7c7c7c, (u_int)0x77777777, (u_int)0x7b7b7b7b,
+    (u_int)0xf2f2f2f2, (u_int)0x6b6b6b6b, (u_int)0x6f6f6f6f, (u_int)0xc5c5c5c5,
+    (u_int)0x30303030, (u_int)0x01010101, (u_int)0x67676767, (u_int)0x2b2b2b2b,
+    (u_int)0xfefefefe, (u_int)0xd7d7d7d7, (u_int)0xabababab, (u_int)0x76767676,
+    (u_int)0xcacacaca, (u_int)0x82828282, (u_int)0xc9c9c9c9, (u_int)0x7d7d7d7d,
+    (u_int)0xfafafafa, (u_int)0x59595959, (u_int)0x47474747, (u_int)0xf0f0f0f0,
+    (u_int)0xadadadad, (u_int)0xd4d4d4d4, (u_int)0xa2a2a2a2, (u_int)0xafafafaf,
+    (u_int)0x9c9c9c9c, (u_int)0xa4a4a4a4, (u_int)0x72727272, (u_int)0xc0c0c0c0,
+    (u_int)0xb7b7b7b7, (u_int)0xfdfdfdfd, (u_int)0x93939393, (u_int)0x26262626,
+    (u_int)0x36363636, (u_int)0x3f3f3f3f, (u_int)0xf7f7f7f7, (u_int)0xcccccccc,
+    (u_int)0x34343434, (u_int)0xa5a5a5a5, (u_int)0xe5e5e5e5, (u_int)0xf1f1f1f1,
+    (u_int)0x71717171, (u_int)0xd8d8d8d8, (u_int)0x31313131, (u_int)0x15151515,
+    (u_int)0x04040404, (u_int)0xc7c7c7c7, (u_int)0x23232323, (u_int)0xc3c3c3c3,
+    (u_int)0x18181818, (u_int)0x96969696, (u_int)0x05050505, (u_int)0x9a9a9a9a,
+    (u_int)0x07070707, (u_int)0x12121212, (u_int)0x80808080, (u_int)0xe2e2e2e2,
+    (u_int)0xebebebeb, (u_int)0x27272727, (u_int)0xb2b2b2b2, (u_int)0x75757575,
+    (u_int)0x09090909, (u_int)0x83838383, (u_int)0x2c2c2c2c, (u_int)0x1a1a1a1a,
+    (u_int)0x1b1b1b1b, (u_int)0x6e6e6e6e, (u_int)0x5a5a5a5a, (u_int)0xa0a0a0a0,
+    (u_int)0x52525252, (u_int)0x3b3b3b3b, (u_int)0xd6d6d6d6, (u_int)0xb3b3b3b3,
+    (u_int)0x29292929, (u_int)0xe3e3e3e3, (u_int)0x2f2f2f2f, (u_int)0x84848484,
+    (u_int)0x53535353, (u_int)0xd1d1d1d1, (u_int)0x00000000, (u_int)0xedededed,
+    (u_int)0x20202020, (u_int)0xfcfcfcfc, (u_int)0xb1b1b1b1, (u_int)0x5b5b5b5b,
+    (u_int)0x6a6a6a6a, (u_int)0xcbcbcbcb, (u_int)0xbebebebe, (u_int)0x39393939,
+    (u_int)0x4a4a4a4a, (u_int)0x4c4c4c4c, (u_int)0x58585858, (u_int)0xcfcfcfcf,
+    (u_int)0xd0d0d0d0, (u_int)0xefefefef, (u_int)0xaaaaaaaa, (u_int)0xfbfbfbfb,
+    (u_int)0x43434343, (u_int)0x4d4d4d4d, (u_int)0x33333333, (u_int)0x85858585,
+    (u_int)0x45454545, (u_int)0xf9f9f9f9, (u_int)0x02020202, (u_int)0x7f7f7f7f,
+    (u_int)0x50505050, (u_int)0x3c3c3c3c, (u_int)0x9f9f9f9f, (u_int)0xa8a8a8a8,
+    (u_int)0x51515151, (u_int)0xa3a3a3a3, (u_int)0x40404040, (u_int)0x8f8f8f8f,
+    (u_int)0x92929292, (u_int)0x9d9d9d9d, (u_int)0x38383838, (u_int)0xf5f5f5f5,
+    (u_int)0xbcbcbcbc, (u_int)0xb6b6b6b6, (u_int)0xdadadada, (u_int)0x21212121,
+    (u_int)0x10101010, (u_int)0xffffffff, (u_int)0xf3f3f3f3, (u_int)0xd2d2d2d2,
+    (u_int)0xcdcdcdcd, (u_int)0x0c0c0c0c, (u_int)0x13131313, (u_int)0xecececec,
+    (u_int)0x5f5f5f5f, (u_int)0x97979797, (u_int)0x44444444, (u_int)0x17171717,
+    (u_int)0xc4c4c4c4, (u_int)0xa7a7a7a7, (u_int)0x7e7e7e7e, (u_int)0x3d3d3d3d,
+    (u_int)0x64646464, (u_int)0x5d5d5d5d, (u_int)0x19191919, (u_int)0x73737373,
+    (u_int)0x60606060, (u_int)0x81818181, (u_int)0x4f4f4f4f, (u_int)0xdcdcdcdc,
+    (u_int)0x22222222, (u_int)0x2a2a2a2a, (u_int)0x90909090, (u_int)0x88888888,
+    (u_int)0x46464646, (u_int)0xeeeeeeee, (u_int)0xb8b8b8b8, (u_int)0x14141414,
+    (u_int)0xdededede, (u_int)0x5e5e5e5e, (u_int)0x0b0b0b0b, (u_int)0xdbdbdbdb,
+    (u_int)0xe0e0e0e0, (u_int)0x32323232, (u_int)0x3a3a3a3a, (u_int)0x0a0a0a0a,
+    (u_int)0x49494949, (u_int)0x06060606, (u_int)0x24242424, (u_int)0x5c5c5c5c,
+    (u_int)0xc2c2c2c2, (u_int)0xd3d3d3d3, (u_int)0xacacacac, (u_int)0x62626262,
+    (u_int)0x91919191, (u_int)0x95959595, (u_int)0xe4e4e4e4, (u_int)0x79797979,
+    (u_int)0xe7e7e7e7, (u_int)0xc8c8c8c8, (u_int)0x37373737, (u_int)0x6d6d6d6d,
+    (u_int)0x8d8d8d8d, (u_int)0xd5d5d5d5, (u_int)0x4e4e4e4e, (u_int)0xa9a9a9a9,
+    (u_int)0x6c6c6c6c, (u_int)0x56565656, (u_int)0xf4f4f4f4, (u_int)0xeaeaeaea,
+    (u_int)0x65656565, (u_int)0x7a7a7a7a, (u_int)0xaeaeaeae, (u_int)0x08080808,
+    (u_int)0xbabababa, (u_int)0x78787878, (u_int)0x25252525, (u_int)0x2e2e2e2e,
+    (u_int)0x1c1c1c1c, (u_int)0xa6a6a6a6, (u_int)0xb4b4b4b4, (u_int)0xc6c6c6c6,
+    (u_int)0xe8e8e8e8, (u_int)0xdddddddd, (u_int)0x74747474, (u_int)0x1f1f1f1f,
+    (u_int)0x4b4b4b4b, (u_int)0xbdbdbdbd, (u_int)0x8b8b8b8b, (u_int)0x8a8a8a8a,
+    (u_int)0x70707070, (u_int)0x3e3e3e3e, (u_int)0xb5b5b5b5, (u_int)0x66666666,
+    (u_int)0x48484848, (u_int)0x03030303, (u_int)0xf6f6f6f6, (u_int)0x0e0e0e0e,
+    (u_int)0x61616161, (u_int)0x35353535, (u_int)0x57575757, (u_int)0xb9b9b9b9,
+    (u_int)0x86868686, (u_int)0xc1c1c1c1, (u_int)0x1d1d1d1d, (u_int)0x9e9e9e9e,
+    (u_int)0xe1e1e1e1, (u_int)0xf8f8f8f8, (u_int)0x98989898, (u_int)0x11111111,
+    (u_int)0x69696969, (u_int)0xd9d9d9d9, (u_int)0x8e8e8e8e, (u_int)0x94949494,
+    (u_int)0x9b9b9b9b, (u_int)0x1e1e1e1e, (u_int)0x87878787, (u_int)0xe9e9e9e9,
+    (u_int)0xcececece, (u_int)0x55555555, (u_int)0x28282828, (u_int)0xdfdfdfdf,
+    (u_int)0x8c8c8c8c, (u_int)0xa1a1a1a1, (u_int)0x89898989, (u_int)0x0d0d0d0d,
+    (u_int)0xbfbfbfbf, (u_int)0xe6e6e6e6, (u_int)0x42424242, (u_int)0x68686868,
+    (u_int)0x41414141, (u_int)0x99999999, (u_int)0x2d2d2d2d, (u_int)0x0f0f0f0f,
+    (u_int)0xb0b0b0b0, (u_int)0x54545454, (u_int)0xbbbbbbbb, (u_int)0x16161616,
+};
+static const u32 Td0[256] = {
+    (u_int)0x51f4a750, (u_int)0x7e416553, (u_int)0x1a17a4c3, (u_int)0x3a275e96,
+    (u_int)0x3bab6bcb, (u_int)0x1f9d45f1, (u_int)0xacfa58ab, (u_int)0x4be30393,
+    (u_int)0x2030fa55, (u_int)0xad766df6, (u_int)0x88cc7691, (u_int)0xf5024c25,
+    (u_int)0x4fe5d7fc, (u_int)0xc52acbd7, (u_int)0x26354480, (u_int)0xb562a38f,
+    (u_int)0xdeb15a49, (u_int)0x25ba1b67, (u_int)0x45ea0e98, (u_int)0x5dfec0e1,
+    (u_int)0xc32f7502, (u_int)0x814cf012, (u_int)0x8d4697a3, (u_int)0x6bd3f9c6,
+    (u_int)0x038f5fe7, (u_int)0x15929c95, (u_int)0xbf6d7aeb, (u_int)0x955259da,
+    (u_int)0xd4be832d, (u_int)0x587421d3, (u_int)0x49e06929, (u_int)0x8ec9c844,
+    (u_int)0x75c2896a, (u_int)0xf48e7978, (u_int)0x99583e6b, (u_int)0x27b971dd,
+    (u_int)0xbee14fb6, (u_int)0xf088ad17, (u_int)0xc920ac66, (u_int)0x7dce3ab4,
+    (u_int)0x63df4a18, (u_int)0xe51a3182, (u_int)0x97513360, (u_int)0x62537f45,
+    (u_int)0xb16477e0, (u_int)0xbb6bae84, (u_int)0xfe81a01c, (u_int)0xf9082b94,
+    (u_int)0x70486858, (u_int)0x8f45fd19, (u_int)0x94de6c87, (u_int)0x527bf8b7,
+    (u_int)0xab73d323, (u_int)0x724b02e2, (u_int)0xe31f8f57, (u_int)0x6655ab2a,
+    (u_int)0xb2eb2807, (u_int)0x2fb5c203, (u_int)0x86c57b9a, (u_int)0xd33708a5,
+    (u_int)0x302887f2, (u_int)0x23bfa5b2, (u_int)0x02036aba, (u_int)0xed16825c,
+    (u_int)0x8acf1c2b, (u_int)0xa779b492, (u_int)0xf307f2f0, (u_int)0x4e69e2a1,
+    (u_int)0x65daf4cd, (u_int)0x0605bed5, (u_int)0xd134621f, (u_int)0xc4a6fe8a,
+    (u_int)0x342e539d, (u_int)0xa2f355a0, (u_int)0x058ae132, (u_int)0xa4f6eb75,
+    (u_int)0x0b83ec39, (u_int)0x4060efaa, (u_int)0x5e719f06, (u_int)0xbd6e1051,
+    (u_int)0x3e218af9, (u_int)0x96dd063d, (u_int)0xdd3e05ae, (u_int)0x4de6bd46,
+    (u_int)0x91548db5, (u_int)0x71c45d05, (u_int)0x0406d46f, (u_int)0x605015ff,
+    (u_int)0x1998fb24, (u_int)0xd6bde997, (u_int)0x894043cc, (u_int)0x67d99e77,
+    (u_int)0xb0e842bd, (u_int)0x07898b88, (u_int)0xe7195b38, (u_int)0x79c8eedb,
+    (u_int)0xa17c0a47, (u_int)0x7c420fe9, (u_int)0xf8841ec9, (u_int)0x00000000,
+    (u_int)0x09808683, (u_int)0x322bed48, (u_int)0x1e1170ac, (u_int)0x6c5a724e,
+    (u_int)0xfd0efffb, (u_int)0x0f853856, (u_int)0x3daed51e, (u_int)0x362d3927,
+    (u_int)0x0a0fd964, (u_int)0x685ca621, (u_int)0x9b5b54d1, (u_int)0x24362e3a,
+    (u_int)0x0c0a67b1, (u_int)0x9357e70f, (u_int)0xb4ee96d2, (u_int)0x1b9b919e,
+    (u_int)0x80c0c54f, (u_int)0x61dc20a2, (u_int)0x5a774b69, (u_int)0x1c121a16,
+    (u_int)0xe293ba0a, (u_int)0xc0a02ae5, (u_int)0x3c22e043, (u_int)0x121b171d,
+    (u_int)0x0e090d0b, (u_int)0xf28bc7ad, (u_int)0x2db6a8b9, (u_int)0x141ea9c8,
+    (u_int)0x57f11985, (u_int)0xaf75074c, (u_int)0xee99ddbb, (u_int)0xa37f60fd,
+    (u_int)0xf701269f, (u_int)0x5c72f5bc, (u_int)0x44663bc5, (u_int)0x5bfb7e34,
+    (u_int)0x8b432976, (u_int)0xcb23c6dc, (u_int)0xb6edfc68, (u_int)0xb8e4f163,
+    (u_int)0xd731dcca, (u_int)0x42638510, (u_int)0x13972240, (u_int)0x84c61120,
+    (u_int)0x854a247d, (u_int)0xd2bb3df8, (u_int)0xaef93211, (u_int)0xc729a16d,
+    (u_int)0x1d9e2f4b, (u_int)0xdcb230f3, (u_int)0x0d8652ec, (u_int)0x77c1e3d0,
+    (u_int)0x2bb3166c, (u_int)0xa970b999, (u_int)0x119448fa, (u_int)0x47e96422,
+    (u_int)0xa8fc8cc4, (u_int)0xa0f03f1a, (u_int)0x567d2cd8, (u_int)0x223390ef,
+    (u_int)0x87494ec7, (u_int)0xd938d1c1, (u_int)0x8ccaa2fe, (u_int)0x98d40b36,
+    (u_int)0xa6f581cf, (u_int)0xa57ade28, (u_int)0xdab78e26, (u_int)0x3fadbfa4,
+    (u_int)0x2c3a9de4, (u_int)0x5078920d, (u_int)0x6a5fcc9b, (u_int)0x547e4662,
+    (u_int)0xf68d13c2, (u_int)0x90d8b8e8, (u_int)0x2e39f75e, (u_int)0x82c3aff5,
+    (u_int)0x9f5d80be, (u_int)0x69d0937c, (u_int)0x6fd52da9, (u_int)0xcf2512b3,
+    (u_int)0xc8ac993b, (u_int)0x10187da7, (u_int)0xe89c636e, (u_int)0xdb3bbb7b,
+    (u_int)0xcd267809, (u_int)0x6e5918f4, (u_int)0xec9ab701, (u_int)0x834f9aa8,
+    (u_int)0xe6956e65, (u_int)0xaaffe67e, (u_int)0x21bccf08, (u_int)0xef15e8e6,
+    (u_int)0xbae79bd9, (u_int)0x4a6f36ce, (u_int)0xea9f09d4, (u_int)0x29b07cd6,
+    (u_int)0x31a4b2af, (u_int)0x2a3f2331, (u_int)0xc6a59430, (u_int)0x35a266c0,
+    (u_int)0x744ebc37, (u_int)0xfc82caa6, (u_int)0xe090d0b0, (u_int)0x33a7d815,
+    (u_int)0xf104984a, (u_int)0x41ecdaf7, (u_int)0x7fcd500e, (u_int)0x1791f62f,
+    (u_int)0x764dd68d, (u_int)0x43efb04d, (u_int)0xccaa4d54, (u_int)0xe49604df,
+    (u_int)0x9ed1b5e3, (u_int)0x4c6a881b, (u_int)0xc12c1fb8, (u_int)0x4665517f,
+    (u_int)0x9d5eea04, (u_int)0x018c355d, (u_int)0xfa877473, (u_int)0xfb0b412e,
+    (u_int)0xb3671d5a, (u_int)0x92dbd252, (u_int)0xe9105633, (u_int)0x6dd64713,
+    (u_int)0x9ad7618c, (u_int)0x37a10c7a, (u_int)0x59f8148e, (u_int)0xeb133c89,
+    (u_int)0xcea927ee, (u_int)0xb761c935, (u_int)0xe11ce5ed, (u_int)0x7a47b13c,
+    (u_int)0x9cd2df59, (u_int)0x55f2733f, (u_int)0x1814ce79, (u_int)0x73c737bf,
+    (u_int)0x53f7cdea, (u_int)0x5ffdaa5b, (u_int)0xdf3d6f14, (u_int)0x7844db86,
+    (u_int)0xcaaff381, (u_int)0xb968c43e, (u_int)0x3824342c, (u_int)0xc2a3405f,
+    (u_int)0x161dc372, (u_int)0xbce2250c, (u_int)0x283c498b, (u_int)0xff0d9541,
+    (u_int)0x39a80171, (u_int)0x080cb3de, (u_int)0xd8b4e49c, (u_int)0x6456c190,
+    (u_int)0x7bcb8461, (u_int)0xd532b670, (u_int)0x486c5c74, (u_int)0xd0b85742,
+};
+static const u32 Td1[256] = {
+    (u_int)0x5051f4a7, (u_int)0x537e4165, (u_int)0xc31a17a4, (u_int)0x963a275e,
+    (u_int)0xcb3bab6b, (u_int)0xf11f9d45, (u_int)0xabacfa58, (u_int)0x934be303,
+    (u_int)0x552030fa, (u_int)0xf6ad766d, (u_int)0x9188cc76, (u_int)0x25f5024c,
+    (u_int)0xfc4fe5d7, (u_int)0xd7c52acb, (u_int)0x80263544, (u_int)0x8fb562a3,
+    (u_int)0x49deb15a, (u_int)0x6725ba1b, (u_int)0x9845ea0e, (u_int)0xe15dfec0,
+    (u_int)0x02c32f75, (u_int)0x12814cf0, (u_int)0xa38d4697, (u_int)0xc66bd3f9,
+    (u_int)0xe7038f5f, (u_int)0x9515929c, (u_int)0xebbf6d7a, (u_int)0xda955259,
+    (u_int)0x2dd4be83, (u_int)0xd3587421, (u_int)0x2949e069, (u_int)0x448ec9c8,
+    (u_int)0x6a75c289, (u_int)0x78f48e79, (u_int)0x6b99583e, (u_int)0xdd27b971,
+    (u_int)0xb6bee14f, (u_int)0x17f088ad, (u_int)0x66c920ac, (u_int)0xb47dce3a,
+    (u_int)0x1863df4a, (u_int)0x82e51a31, (u_int)0x60975133, (u_int)0x4562537f,
+    (u_int)0xe0b16477, (u_int)0x84bb6bae, (u_int)0x1cfe81a0, (u_int)0x94f9082b,
+    (u_int)0x58704868, (u_int)0x198f45fd, (u_int)0x8794de6c, (u_int)0xb7527bf8,
+    (u_int)0x23ab73d3, (u_int)0xe2724b02, (u_int)0x57e31f8f, (u_int)0x2a6655ab,
+    (u_int)0x07b2eb28, (u_int)0x032fb5c2, (u_int)0x9a86c57b, (u_int)0xa5d33708,
+    (u_int)0xf2302887, (u_int)0xb223bfa5, (u_int)0xba02036a, (u_int)0x5ced1682,
+    (u_int)0x2b8acf1c, (u_int)0x92a779b4, (u_int)0xf0f307f2, (u_int)0xa14e69e2,
+    (u_int)0xcd65daf4, (u_int)0xd50605be, (u_int)0x1fd13462, (u_int)0x8ac4a6fe,
+    (u_int)0x9d342e53, (u_int)0xa0a2f355, (u_int)0x32058ae1, (u_int)0x75a4f6eb,
+    (u_int)0x390b83ec, (u_int)0xaa4060ef, (u_int)0x065e719f, (u_int)0x51bd6e10,
+    (u_int)0xf93e218a, (u_int)0x3d96dd06, (u_int)0xaedd3e05, (u_int)0x464de6bd,
+    (u_int)0xb591548d, (u_int)0x0571c45d, (u_int)0x6f0406d4, (u_int)0xff605015,
+    (u_int)0x241998fb, (u_int)0x97d6bde9, (u_int)0xcc894043, (u_int)0x7767d99e,
+    (u_int)0xbdb0e842, (u_int)0x8807898b, (u_int)0x38e7195b, (u_int)0xdb79c8ee,
+    (u_int)0x47a17c0a, (u_int)0xe97c420f, (u_int)0xc9f8841e, (u_int)0x00000000,
+    (u_int)0x83098086, (u_int)0x48322bed, (u_int)0xac1e1170, (u_int)0x4e6c5a72,
+    (u_int)0xfbfd0eff, (u_int)0x560f8538, (u_int)0x1e3daed5, (u_int)0x27362d39,
+    (u_int)0x640a0fd9, (u_int)0x21685ca6, (u_int)0xd19b5b54, (u_int)0x3a24362e,
+    (u_int)0xb10c0a67, (u_int)0x0f9357e7, (u_int)0xd2b4ee96, (u_int)0x9e1b9b91,
+    (u_int)0x4f80c0c5, (u_int)0xa261dc20, (u_int)0x695a774b, (u_int)0x161c121a,
+    (u_int)0x0ae293ba, (u_int)0xe5c0a02a, (u_int)0x433c22e0, (u_int)0x1d121b17,
+    (u_int)0x0b0e090d, (u_int)0xadf28bc7, (u_int)0xb92db6a8, (u_int)0xc8141ea9,
+    (u_int)0x8557f119, (u_int)0x4caf7507, (u_int)0xbbee99dd, (u_int)0xfda37f60,
+    (u_int)0x9ff70126, (u_int)0xbc5c72f5, (u_int)0xc544663b, (u_int)0x345bfb7e,
+    (u_int)0x768b4329, (u_int)0xdccb23c6, (u_int)0x68b6edfc, (u_int)0x63b8e4f1,
+    (u_int)0xcad731dc, (u_int)0x10426385, (u_int)0x40139722, (u_int)0x2084c611,
+    (u_int)0x7d854a24, (u_int)0xf8d2bb3d, (u_int)0x11aef932, (u_int)0x6dc729a1,
+    (u_int)0x4b1d9e2f, (u_int)0xf3dcb230, (u_int)0xec0d8652, (u_int)0xd077c1e3,
+    (u_int)0x6c2bb316, (u_int)0x99a970b9, (u_int)0xfa119448, (u_int)0x2247e964,
+    (u_int)0xc4a8fc8c, (u_int)0x1aa0f03f, (u_int)0xd8567d2c, (u_int)0xef223390,
+    (u_int)0xc787494e, (u_int)0xc1d938d1, (u_int)0xfe8ccaa2, (u_int)0x3698d40b,
+    (u_int)0xcfa6f581, (u_int)0x28a57ade, (u_int)0x26dab78e, (u_int)0xa43fadbf,
+    (u_int)0xe42c3a9d, (u_int)0x0d507892, (u_int)0x9b6a5fcc, (u_int)0x62547e46,
+    (u_int)0xc2f68d13, (u_int)0xe890d8b8, (u_int)0x5e2e39f7, (u_int)0xf582c3af,
+    (u_int)0xbe9f5d80, (u_int)0x7c69d093, (u_int)0xa96fd52d, (u_int)0xb3cf2512,
+    (u_int)0x3bc8ac99, (u_int)0xa710187d, (u_int)0x6ee89c63, (u_int)0x7bdb3bbb,
+    (u_int)0x09cd2678, (u_int)0xf46e5918, (u_int)0x01ec9ab7, (u_int)0xa8834f9a,
+    (u_int)0x65e6956e, (u_int)0x7eaaffe6, (u_int)0x0821bccf, (u_int)0xe6ef15e8,
+    (u_int)0xd9bae79b, (u_int)0xce4a6f36, (u_int)0xd4ea9f09, (u_int)0xd629b07c,
+    (u_int)0xaf31a4b2, (u_int)0x312a3f23, (u_int)0x30c6a594, (u_int)0xc035a266,
+    (u_int)0x37744ebc, (u_int)0xa6fc82ca, (u_int)0xb0e090d0, (u_int)0x1533a7d8,
+    (u_int)0x4af10498, (u_int)0xf741ecda, (u_int)0x0e7fcd50, (u_int)0x2f1791f6,
+    (u_int)0x8d764dd6, (u_int)0x4d43efb0, (u_int)0x54ccaa4d, (u_int)0xdfe49604,
+    (u_int)0xe39ed1b5, (u_int)0x1b4c6a88, (u_int)0xb8c12c1f, (u_int)0x7f466551,
+    (u_int)0x049d5eea, (u_int)0x5d018c35, (u_int)0x73fa8774, (u_int)0x2efb0b41,
+    (u_int)0x5ab3671d, (u_int)0x5292dbd2, (u_int)0x33e91056, (u_int)0x136dd647,
+    (u_int)0x8c9ad761, (u_int)0x7a37a10c, (u_int)0x8e59f814, (u_int)0x89eb133c,
+    (u_int)0xeecea927, (u_int)0x35b761c9, (u_int)0xede11ce5, (u_int)0x3c7a47b1,
+    (u_int)0x599cd2df, (u_int)0x3f55f273, (u_int)0x791814ce, (u_int)0xbf73c737,
+    (u_int)0xea53f7cd, (u_int)0x5b5ffdaa, (u_int)0x14df3d6f, (u_int)0x867844db,
+    (u_int)0x81caaff3, (u_int)0x3eb968c4, (u_int)0x2c382434, (u_int)0x5fc2a340,
+    (u_int)0x72161dc3, (u_int)0x0cbce225, (u_int)0x8b283c49, (u_int)0x41ff0d95,
+    (u_int)0x7139a801, (u_int)0xde080cb3, (u_int)0x9cd8b4e4, (u_int)0x906456c1,
+    (u_int)0x617bcb84, (u_int)0x70d532b6, (u_int)0x74486c5c, (u_int)0x42d0b857,
+};
+static const u32 Td2[256] = {
+    (u_int)0xa75051f4, (u_int)0x65537e41, (u_int)0xa4c31a17, (u_int)0x5e963a27,
+    (u_int)0x6bcb3bab, (u_int)0x45f11f9d, (u_int)0x58abacfa, (u_int)0x03934be3,
+    (u_int)0xfa552030, (u_int)0x6df6ad76, (u_int)0x769188cc, (u_int)0x4c25f502,
+    (u_int)0xd7fc4fe5, (u_int)0xcbd7c52a, (u_int)0x44802635, (u_int)0xa38fb562,
+    (u_int)0x5a49deb1, (u_int)0x1b6725ba, (u_int)0x0e9845ea, (u_int)0xc0e15dfe,
+    (u_int)0x7502c32f, (u_int)0xf012814c, (u_int)0x97a38d46, (u_int)0xf9c66bd3,
+    (u_int)0x5fe7038f, (u_int)0x9c951592, (u_int)0x7aebbf6d, (u_int)0x59da9552,
+    (u_int)0x832dd4be, (u_int)0x21d35874, (u_int)0x692949e0, (u_int)0xc8448ec9,
+    (u_int)0x896a75c2, (u_int)0x7978f48e, (u_int)0x3e6b9958, (u_int)0x71dd27b9,
+    (u_int)0x4fb6bee1, (u_int)0xad17f088, (u_int)0xac66c920, (u_int)0x3ab47dce,
+    (u_int)0x4a1863df, (u_int)0x3182e51a, (u_int)0x33609751, (u_int)0x7f456253,
+    (u_int)0x77e0b164, (u_int)0xae84bb6b, (u_int)0xa01cfe81, (u_int)0x2b94f908,
+    (u_int)0x68587048, (u_int)0xfd198f45, (u_int)0x6c8794de, (u_int)0xf8b7527b,
+    (u_int)0xd323ab73, (u_int)0x02e2724b, (u_int)0x8f57e31f, (u_int)0xab2a6655,
+    (u_int)0x2807b2eb, (u_int)0xc2032fb5, (u_int)0x7b9a86c5, (u_int)0x08a5d337,
+    (u_int)0x87f23028, (u_int)0xa5b223bf, (u_int)0x6aba0203, (u_int)0x825ced16,
+    (u_int)0x1c2b8acf, (u_int)0xb492a779, (u_int)0xf2f0f307, (u_int)0xe2a14e69,
+    (u_int)0xf4cd65da, (u_int)0xbed50605, (u_int)0x621fd134, (u_int)0xfe8ac4a6,
+    (u_int)0x539d342e, (u_int)0x55a0a2f3, (u_int)0xe132058a, (u_int)0xeb75a4f6,
+    (u_int)0xec390b83, (u_int)0xefaa4060, (u_int)0x9f065e71, (u_int)0x1051bd6e,
+
+    (u_int)0x8af93e21, (u_int)0x063d96dd, (u_int)0x05aedd3e, (u_int)0xbd464de6,
+    (u_int)0x8db59154, (u_int)0x5d0571c4, (u_int)0xd46f0406, (u_int)0x15ff6050,
+    (u_int)0xfb241998, (u_int)0xe997d6bd, (u_int)0x43cc8940, (u_int)0x9e7767d9,
+    (u_int)0x42bdb0e8, (u_int)0x8b880789, (u_int)0x5b38e719, (u_int)0xeedb79c8,
+    (u_int)0x0a47a17c, (u_int)0x0fe97c42, (u_int)0x1ec9f884, (u_int)0x00000000,
+    (u_int)0x86830980, (u_int)0xed48322b, (u_int)0x70ac1e11, (u_int)0x724e6c5a,
+    (u_int)0xfffbfd0e, (u_int)0x38560f85, (u_int)0xd51e3dae, (u_int)0x3927362d,
+    (u_int)0xd9640a0f, (u_int)0xa621685c, (u_int)0x54d19b5b, (u_int)0x2e3a2436,
+    (u_int)0x67b10c0a, (u_int)0xe70f9357, (u_int)0x96d2b4ee, (u_int)0x919e1b9b,
+    (u_int)0xc54f80c0, (u_int)0x20a261dc, (u_int)0x4b695a77, (u_int)0x1a161c12,
+    (u_int)0xba0ae293, (u_int)0x2ae5c0a0, (u_int)0xe0433c22, (u_int)0x171d121b,
+    (u_int)0x0d0b0e09, (u_int)0xc7adf28b, (u_int)0xa8b92db6, (u_int)0xa9c8141e,
+    (u_int)0x198557f1, (u_int)0x074caf75, (u_int)0xddbbee99, (u_int)0x60fda37f,
+    (u_int)0x269ff701, (u_int)0xf5bc5c72, (u_int)0x3bc54466, (u_int)0x7e345bfb,
+    (u_int)0x29768b43, (u_int)0xc6dccb23, (u_int)0xfc68b6ed, (u_int)0xf163b8e4,
+    (u_int)0xdccad731, (u_int)0x85104263, (u_int)0x22401397, (u_int)0x112084c6,
+    (u_int)0x247d854a, (u_int)0x3df8d2bb, (u_int)0x3211aef9, (u_int)0xa16dc729,
+    (u_int)0x2f4b1d9e, (u_int)0x30f3dcb2, (u_int)0x52ec0d86, (u_int)0xe3d077c1,
+    (u_int)0x166c2bb3, (u_int)0xb999a970, (u_int)0x48fa1194, (u_int)0x642247e9,
+    (u_int)0x8cc4a8fc, (u_int)0x3f1aa0f0, (u_int)0x2cd8567d, (u_int)0x90ef2233,
+    (u_int)0x4ec78749, (u_int)0xd1c1d938, (u_int)0xa2fe8cca, (u_int)0x0b3698d4,
+    (u_int)0x81cfa6f5, (u_int)0xde28a57a, (u_int)0x8e26dab7, (u_int)0xbfa43fad,
+    (u_int)0x9de42c3a, (u_int)0x920d5078, (u_int)0xcc9b6a5f, (u_int)0x4662547e,
+    (u_int)0x13c2f68d, (u_int)0xb8e890d8, (u_int)0xf75e2e39, (u_int)0xaff582c3,
+    (u_int)0x80be9f5d, (u_int)0x937c69d0, (u_int)0x2da96fd5, (u_int)0x12b3cf25,
+    (u_int)0x993bc8ac, (u_int)0x7da71018, (u_int)0x636ee89c, (u_int)0xbb7bdb3b,
+    (u_int)0x7809cd26, (u_int)0x18f46e59, (u_int)0xb701ec9a, (u_int)0x9aa8834f,
+    (u_int)0x6e65e695, (u_int)0xe67eaaff, (u_int)0xcf0821bc, (u_int)0xe8e6ef15,
+    (u_int)0x9bd9bae7, (u_int)0x36ce4a6f, (u_int)0x09d4ea9f, (u_int)0x7cd629b0,
+    (u_int)0xb2af31a4, (u_int)0x23312a3f, (u_int)0x9430c6a5, (u_int)0x66c035a2,
+    (u_int)0xbc37744e, (u_int)0xcaa6fc82, (u_int)0xd0b0e090, (u_int)0xd81533a7,
+    (u_int)0x984af104, (u_int)0xdaf741ec, (u_int)0x500e7fcd, (u_int)0xf62f1791,
+    (u_int)0xd68d764d, (u_int)0xb04d43ef, (u_int)0x4d54ccaa, (u_int)0x04dfe496,
+    (u_int)0xb5e39ed1, (u_int)0x881b4c6a, (u_int)0x1fb8c12c, (u_int)0x517f4665,
+    (u_int)0xea049d5e, (u_int)0x355d018c, (u_int)0x7473fa87, (u_int)0x412efb0b,
+    (u_int)0x1d5ab367, (u_int)0xd25292db, (u_int)0x5633e910, (u_int)0x47136dd6,
+    (u_int)0x618c9ad7, (u_int)0x0c7a37a1, (u_int)0x148e59f8, (u_int)0x3c89eb13,
+    (u_int)0x27eecea9, (u_int)0xc935b761, (u_int)0xe5ede11c, (u_int)0xb13c7a47,
+    (u_int)0xdf599cd2, (u_int)0x733f55f2, (u_int)0xce791814, (u_int)0x37bf73c7,
+    (u_int)0xcdea53f7, (u_int)0xaa5b5ffd, (u_int)0x6f14df3d, (u_int)0xdb867844,
+    (u_int)0xf381caaf, (u_int)0xc43eb968, (u_int)0x342c3824, (u_int)0x405fc2a3,
+    (u_int)0xc372161d, (u_int)0x250cbce2, (u_int)0x498b283c, (u_int)0x9541ff0d,
+    (u_int)0x017139a8, (u_int)0xb3de080c, (u_int)0xe49cd8b4, (u_int)0xc1906456,
+    (u_int)0x84617bcb, (u_int)0xb670d532, (u_int)0x5c74486c, (u_int)0x5742d0b8,
+};
+static const u32 Td3[256] = {
+    (u_int)0xf4a75051, (u_int)0x4165537e, (u_int)0x17a4c31a, (u_int)0x275e963a,
+    (u_int)0xab6bcb3b, (u_int)0x9d45f11f, (u_int)0xfa58abac, (u_int)0xe303934b,
+    (u_int)0x30fa5520, (u_int)0x766df6ad, (u_int)0xcc769188, (u_int)0x024c25f5,
+    (u_int)0xe5d7fc4f, (u_int)0x2acbd7c5, (u_int)0x35448026, (u_int)0x62a38fb5,
+    (u_int)0xb15a49de, (u_int)0xba1b6725, (u_int)0xea0e9845, (u_int)0xfec0e15d,
+    (u_int)0x2f7502c3, (u_int)0x4cf01281, (u_int)0x4697a38d, (u_int)0xd3f9c66b,
+    (u_int)0x8f5fe703, (u_int)0x929c9515, (u_int)0x6d7aebbf, (u_int)0x5259da95,
+    (u_int)0xbe832dd4, (u_int)0x7421d358, (u_int)0xe0692949, (u_int)0xc9c8448e,
+    (u_int)0xc2896a75, (u_int)0x8e7978f4, (u_int)0x583e6b99, (u_int)0xb971dd27,
+    (u_int)0xe14fb6be, (u_int)0x88ad17f0, (u_int)0x20ac66c9, (u_int)0xce3ab47d,
+    (u_int)0xdf4a1863, (u_int)0x1a3182e5, (u_int)0x51336097, (u_int)0x537f4562,
+    (u_int)0x6477e0b1, (u_int)0x6bae84bb, (u_int)0x81a01cfe, (u_int)0x082b94f9,
+    (u_int)0x48685870, (u_int)0x45fd198f, (u_int)0xde6c8794, (u_int)0x7bf8b752,
+    (u_int)0x73d323ab, (u_int)0x4b02e272, (u_int)0x1f8f57e3, (u_int)0x55ab2a66,
+    (u_int)0xeb2807b2, (u_int)0xb5c2032f, (u_int)0xc57b9a86, (u_int)0x3708a5d3,
+    (u_int)0x2887f230, (u_int)0xbfa5b223, (u_int)0x036aba02, (u_int)0x16825ced,
+    (u_int)0xcf1c2b8a, (u_int)0x79b492a7, (u_int)0x07f2f0f3, (u_int)0x69e2a14e,
+    (u_int)0xdaf4cd65, (u_int)0x05bed506, (u_int)0x34621fd1, (u_int)0xa6fe8ac4,
+    (u_int)0x2e539d34, (u_int)0xf355a0a2, (u_int)0x8ae13205, (u_int)0xf6eb75a4,
+    (u_int)0x83ec390b, (u_int)0x60efaa40, (u_int)0x719f065e, (u_int)0x6e1051bd,
+    (u_int)0x218af93e, (u_int)0xdd063d96, (u_int)0x3e05aedd, (u_int)0xe6bd464d,
+    (u_int)0x548db591, (u_int)0xc45d0571, (u_int)0x06d46f04, (u_int)0x5015ff60,
+    (u_int)0x98fb2419, (u_int)0xbde997d6, (u_int)0x4043cc89, (u_int)0xd99e7767,
+    (u_int)0xe842bdb0, (u_int)0x898b8807, (u_int)0x195b38e7, (u_int)0xc8eedb79,
+    (u_int)0x7c0a47a1, (u_int)0x420fe97c, (u_int)0x841ec9f8, (u_int)0x00000000,
+    (u_int)0x80868309, (u_int)0x2bed4832, (u_int)0x1170ac1e, (u_int)0x5a724e6c,
+    (u_int)0x0efffbfd, (u_int)0x8538560f, (u_int)0xaed51e3d, (u_int)0x2d392736,
+    (u_int)0x0fd9640a, (u_int)0x5ca62168, (u_int)0x5b54d19b, (u_int)0x362e3a24,
+    (u_int)0x0a67b10c, (u_int)0x57e70f93, (u_int)0xee96d2b4, (u_int)0x9b919e1b,
+    (u_int)0xc0c54f80, (u_int)0xdc20a261, (u_int)0x774b695a, (u_int)0x121a161c,
+    (u_int)0x93ba0ae2, (u_int)0xa02ae5c0, (u_int)0x22e0433c, (u_int)0x1b171d12,
+    (u_int)0x090d0b0e, (u_int)0x8bc7adf2, (u_int)0xb6a8b92d, (u_int)0x1ea9c814,
+    (u_int)0xf1198557, (u_int)0x75074caf, (u_int)0x99ddbbee, (u_int)0x7f60fda3,
+    (u_int)0x01269ff7, (u_int)0x72f5bc5c, (u_int)0x663bc544, (u_int)0xfb7e345b,
+    (u_int)0x4329768b, (u_int)0x23c6dccb, (u_int)0xedfc68b6, (u_int)0xe4f163b8,
+    (u_int)0x31dccad7, (u_int)0x63851042, (u_int)0x97224013, (u_int)0xc6112084,
+    (u_int)0x4a247d85, (u_int)0xbb3df8d2, (u_int)0xf93211ae, (u_int)0x29a16dc7,
+    (u_int)0x9e2f4b1d, (u_int)0xb230f3dc, (u_int)0x8652ec0d, (u_int)0xc1e3d077,
+    (u_int)0xb3166c2b, (u_int)0x70b999a9, (u_int)0x9448fa11, (u_int)0xe9642247,
+    (u_int)0xfc8cc4a8, (u_int)0xf03f1aa0, (u_int)0x7d2cd856, (u_int)0x3390ef22,
+    (u_int)0x494ec787, (u_int)0x38d1c1d9, (u_int)0xcaa2fe8c, (u_int)0xd40b3698,
+    (u_int)0xf581cfa6, (u_int)0x7ade28a5, (u_int)0xb78e26da, (u_int)0xadbfa43f,
+    (u_int)0x3a9de42c, (u_int)0x78920d50, (u_int)0x5fcc9b6a, (u_int)0x7e466254,
+    (u_int)0x8d13c2f6, (u_int)0xd8b8e890, (u_int)0x39f75e2e, (u_int)0xc3aff582,
+    (u_int)0x5d80be9f, (u_int)0xd0937c69, (u_int)0xd52da96f, (u_int)0x2512b3cf,
+    (u_int)0xac993bc8, (u_int)0x187da710, (u_int)0x9c636ee8, (u_int)0x3bbb7bdb,
+    (u_int)0x267809cd, (u_int)0x5918f46e, (u_int)0x9ab701ec, (u_int)0x4f9aa883,
+    (u_int)0x956e65e6, (u_int)0xffe67eaa, (u_int)0xbccf0821, (u_int)0x15e8e6ef,
+    (u_int)0xe79bd9ba, (u_int)0x6f36ce4a, (u_int)0x9f09d4ea, (u_int)0xb07cd629,
+    (u_int)0xa4b2af31, (u_int)0x3f23312a, (u_int)0xa59430c6, (u_int)0xa266c035,
+    (u_int)0x4ebc3774, (u_int)0x82caa6fc, (u_int)0x90d0b0e0, (u_int)0xa7d81533,
+    (u_int)0x04984af1, (u_int)0xecdaf741, (u_int)0xcd500e7f, (u_int)0x91f62f17,
+    (u_int)0x4dd68d76, (u_int)0xefb04d43, (u_int)0xaa4d54cc, (u_int)0x9604dfe4,
+    (u_int)0xd1b5e39e, (u_int)0x6a881b4c, (u_int)0x2c1fb8c1, (u_int)0x65517f46,
+    (u_int)0x5eea049d, (u_int)0x8c355d01, (u_int)0x877473fa, (u_int)0x0b412efb,
+    (u_int)0x671d5ab3, (u_int)0xdbd25292, (u_int)0x105633e9, (u_int)0xd647136d,
+    (u_int)0xd7618c9a, (u_int)0xa10c7a37, (u_int)0xf8148e59, (u_int)0x133c89eb,
+    (u_int)0xa927eece, (u_int)0x61c935b7, (u_int)0x1ce5ede1, (u_int)0x47b13c7a,
+    (u_int)0xd2df599c, (u_int)0xf2733f55, (u_int)0x14ce7918, (u_int)0xc737bf73,
+    (u_int)0xf7cdea53, (u_int)0xfdaa5b5f, (u_int)0x3d6f14df, (u_int)0x44db8678,
+    (u_int)0xaff381ca, (u_int)0x68c43eb9, (u_int)0x24342c38, (u_int)0xa3405fc2,
+    (u_int)0x1dc37216, (u_int)0xe2250cbc, (u_int)0x3c498b28, (u_int)0x0d9541ff,
+    (u_int)0xa8017139, (u_int)0x0cb3de08, (u_int)0xb4e49cd8, (u_int)0x56c19064,
+    (u_int)0xcb84617b, (u_int)0x32b670d5, (u_int)0x6c5c7448, (u_int)0xb85742d0,
+};
+static const u32 Td4[256] = {
+    (u_int)0x52525252, (u_int)0x09090909, (u_int)0x6a6a6a6a, (u_int)0xd5d5d5d5,
+    (u_int)0x30303030, (u_int)0x36363636, (u_int)0xa5a5a5a5, (u_int)0x38383838,
+    (u_int)0xbfbfbfbf, (u_int)0x40404040, (u_int)0xa3a3a3a3, (u_int)0x9e9e9e9e,
+    (u_int)0x81818181, (u_int)0xf3f3f3f3, (u_int)0xd7d7d7d7, (u_int)0xfbfbfbfb,
+    (u_int)0x7c7c7c7c, (u_int)0xe3e3e3e3, (u_int)0x39393939, (u_int)0x82828282,
+    (u_int)0x9b9b9b9b, (u_int)0x2f2f2f2f, (u_int)0xffffffff, (u_int)0x87878787,
+    (u_int)0x34343434, (u_int)0x8e8e8e8e, (u_int)0x43434343, (u_int)0x44444444,
+    (u_int)0xc4c4c4c4, (u_int)0xdededede, (u_int)0xe9e9e9e9, (u_int)0xcbcbcbcb,
+    (u_int)0x54545454, (u_int)0x7b7b7b7b, (u_int)0x94949494, (u_int)0x32323232,
+    (u_int)0xa6a6a6a6, (u_int)0xc2c2c2c2, (u_int)0x23232323, (u_int)0x3d3d3d3d,
+    (u_int)0xeeeeeeee, (u_int)0x4c4c4c4c, (u_int)0x95959595, (u_int)0x0b0b0b0b,
+    (u_int)0x42424242, (u_int)0xfafafafa, (u_int)0xc3c3c3c3, (u_int)0x4e4e4e4e,
+    (u_int)0x08080808, (u_int)0x2e2e2e2e, (u_int)0xa1a1a1a1, (u_int)0x66666666,
+    (u_int)0x28282828, (u_int)0xd9d9d9d9, (u_int)0x24242424, (u_int)0xb2b2b2b2,
+    (u_int)0x76767676, (u_int)0x5b5b5b5b, (u_int)0xa2a2a2a2, (u_int)0x49494949,
+    (u_int)0x6d6d6d6d, (u_int)0x8b8b8b8b, (u_int)0xd1d1d1d1, (u_int)0x25252525,
+    (u_int)0x72727272, (u_int)0xf8f8f8f8, (u_int)0xf6f6f6f6, (u_int)0x64646464,
+    (u_int)0x86868686, (u_int)0x68686868, (u_int)0x98989898, (u_int)0x16161616,
+    (u_int)0xd4d4d4d4, (u_int)0xa4a4a4a4, (u_int)0x5c5c5c5c, (u_int)0xcccccccc,
+    (u_int)0x5d5d5d5d, (u_int)0x65656565, (u_int)0xb6b6b6b6, (u_int)0x92929292,
+    (u_int)0x6c6c6c6c, (u_int)0x70707070, (u_int)0x48484848, (u_int)0x50505050,
+    (u_int)0xfdfdfdfd, (u_int)0xedededed, (u_int)0xb9b9b9b9, (u_int)0xdadadada,
+    (u_int)0x5e5e5e5e, (u_int)0x15151515, (u_int)0x46464646, (u_int)0x57575757,
+    (u_int)0xa7a7a7a7, (u_int)0x8d8d8d8d, (u_int)0x9d9d9d9d, (u_int)0x84848484,
+    (u_int)0x90909090, (u_int)0xd8d8d8d8, (u_int)0xabababab, (u_int)0x00000000,
+    (u_int)0x8c8c8c8c, (u_int)0xbcbcbcbc, (u_int)0xd3d3d3d3, (u_int)0x0a0a0a0a,
+    (u_int)0xf7f7f7f7, (u_int)0xe4e4e4e4, (u_int)0x58585858, (u_int)0x05050505,
+    (u_int)0xb8b8b8b8, (u_int)0xb3b3b3b3, (u_int)0x45454545, (u_int)0x06060606,
+    (u_int)0xd0d0d0d0, (u_int)0x2c2c2c2c, (u_int)0x1e1e1e1e, (u_int)0x8f8f8f8f,
+    (u_int)0xcacacaca, (u_int)0x3f3f3f3f, (u_int)0x0f0f0f0f, (u_int)0x02020202,
+    (u_int)0xc1c1c1c1, (u_int)0xafafafaf, (u_int)0xbdbdbdbd, (u_int)0x03030303,
+    (u_int)0x01010101, (u_int)0x13131313, (u_int)0x8a8a8a8a, (u_int)0x6b6b6b6b,
+    (u_int)0x3a3a3a3a, (u_int)0x91919191, (u_int)0x11111111, (u_int)0x41414141,
+    (u_int)0x4f4f4f4f, (u_int)0x67676767, (u_int)0xdcdcdcdc, (u_int)0xeaeaeaea,
+    (u_int)0x97979797, (u_int)0xf2f2f2f2, (u_int)0xcfcfcfcf, (u_int)0xcececece,
+    (u_int)0xf0f0f0f0, (u_int)0xb4b4b4b4, (u_int)0xe6e6e6e6, (u_int)0x73737373,
+    (u_int)0x96969696, (u_int)0xacacacac, (u_int)0x74747474, (u_int)0x22222222,
+    (u_int)0xe7e7e7e7, (u_int)0xadadadad, (u_int)0x35353535, (u_int)0x85858585,
+    (u_int)0xe2e2e2e2, (u_int)0xf9f9f9f9, (u_int)0x37373737, (u_int)0xe8e8e8e8,
+    (u_int)0x1c1c1c1c, (u_int)0x75757575, (u_int)0xdfdfdfdf, (u_int)0x6e6e6e6e,
+    (u_int)0x47474747, (u_int)0xf1f1f1f1, (u_int)0x1a1a1a1a, (u_int)0x71717171,
+    (u_int)0x1d1d1d1d, (u_int)0x29292929, (u_int)0xc5c5c5c5, (u_int)0x89898989,
+    (u_int)0x6f6f6f6f, (u_int)0xb7b7b7b7, (u_int)0x62626262, (u_int)0x0e0e0e0e,
+    (u_int)0xaaaaaaaa, (u_int)0x18181818, (u_int)0xbebebebe, (u_int)0x1b1b1b1b,
+    (u_int)0xfcfcfcfc, (u_int)0x56565656, (u_int)0x3e3e3e3e, (u_int)0x4b4b4b4b,
+    (u_int)0xc6c6c6c6, (u_int)0xd2d2d2d2, (u_int)0x79797979, (u_int)0x20202020,
+    (u_int)0x9a9a9a9a, (u_int)0xdbdbdbdb, (u_int)0xc0c0c0c0, (u_int)0xfefefefe,
+    (u_int)0x78787878, (u_int)0xcdcdcdcd, (u_int)0x5a5a5a5a, (u_int)0xf4f4f4f4,
+    (u_int)0x1f1f1f1f, (u_int)0xdddddddd, (u_int)0xa8a8a8a8, (u_int)0x33333333,
+    (u_int)0x88888888, (u_int)0x07070707, (u_int)0xc7c7c7c7, (u_int)0x31313131,
+    (u_int)0xb1b1b1b1, (u_int)0x12121212, (u_int)0x10101010, (u_int)0x59595959,
+    (u_int)0x27272727, (u_int)0x80808080, (u_int)0xecececec, (u_int)0x5f5f5f5f,
+    (u_int)0x60606060, (u_int)0x51515151, (u_int)0x7f7f7f7f, (u_int)0xa9a9a9a9,
+    (u_int)0x19191919, (u_int)0xb5b5b5b5, (u_int)0x4a4a4a4a, (u_int)0x0d0d0d0d,
+    (u_int)0x2d2d2d2d, (u_int)0xe5e5e5e5, (u_int)0x7a7a7a7a, (u_int)0x9f9f9f9f,
+    (u_int)0x93939393, (u_int)0xc9c9c9c9, (u_int)0x9c9c9c9c, (u_int)0xefefefef,
+    (u_int)0xa0a0a0a0, (u_int)0xe0e0e0e0, (u_int)0x3b3b3b3b, (u_int)0x4d4d4d4d,
+    (u_int)0xaeaeaeae, (u_int)0x2a2a2a2a, (u_int)0xf5f5f5f5, (u_int)0xb0b0b0b0,
+    (u_int)0xc8c8c8c8, (u_int)0xebebebeb, (u_int)0xbbbbbbbb, (u_int)0x3c3c3c3c,
+    (u_int)0x83838383, (u_int)0x53535353, (u_int)0x99999999, (u_int)0x61616161,
+    (u_int)0x17171717, (u_int)0x2b2b2b2b, (u_int)0x04040404, (u_int)0x7e7e7e7e,
+    (u_int)0xbabababa, (u_int)0x77777777, (u_int)0xd6d6d6d6, (u_int)0x26262626,
+    (u_int)0xe1e1e1e1, (u_int)0x69696969, (u_int)0x14141414, (u_int)0x63636363,
+    (u_int)0x55555555, (u_int)0x21212121, (u_int)0x0c0c0c0c, (u_int)0x7d7d7d7d,
+};
+static const u32 rcon[] = {
+	0x01000000, 0x02000000, 0x04000000, 0x08000000,
+	0x10000000, 0x20000000, 0x40000000, 0x80000000,
+	0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+
+#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
+
+#ifdef _MSC_VER
+#define GETU32(p) SWAP(*((u32 *)(p)))
+#define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); }
+#else
+#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] <<  8) ^ ((u32)(pt)[3]))
+#define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >>  8); (ct)[3] = (u8)(st); }
+#endif
+
+/**
+ * Expand the cipher key into the encryption key schedule.
+ *
+ * @return	the number of rounds for the given cipher key size.
+ */
+/*
+ * __db_rijndaelKeySetupEnc --
+ *
+ * PUBLIC: int __db_rijndaelKeySetupEnc __P((u32 *, const u8 *, int));
+ */
+int
+__db_rijndaelKeySetupEnc(rk, cipherKey, keyBits)
+	u32 *rk;	/* rk[4*(Nr + 1)] */
+	const u8 *cipherKey;
+	int keyBits;
+{
+   	int i = 0;
+	u32 temp;
+
+	rk[0] = GETU32(cipherKey     );
+	rk[1] = GETU32(cipherKey +  4);
+	rk[2] = GETU32(cipherKey +  8);
+	rk[3] = GETU32(cipherKey + 12);
+	if (keyBits == 128) {
+		for (;;) {
+			temp  = rk[3];
+			rk[4] = rk[0] ^
+				(Te4[(temp >> 16) & 0xff] & 0xff000000) ^
+				(Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^
+				(Te4[(temp      ) & 0xff] & 0x0000ff00) ^
+				(Te4[(temp >> 24)       ] & 0x000000ff) ^
+				rcon[i];
+			rk[5] = rk[1] ^ rk[4];
+			rk[6] = rk[2] ^ rk[5];
+			rk[7] = rk[3] ^ rk[6];
+			if (++i == 10) {
+				return 10;
+			}
+			rk += 4;
+		}
+	}
+	rk[4] = GETU32(cipherKey + 16);
+	rk[5] = GETU32(cipherKey + 20);
+	if (keyBits == 192) {
+		for (;;) {
+			temp = rk[ 5];
+			rk[ 6] = rk[ 0] ^
+				(Te4[(temp >> 16) & 0xff] & 0xff000000) ^
+				(Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^
+				(Te4[(temp      ) & 0xff] & 0x0000ff00) ^
+				(Te4[(temp >> 24)       ] & 0x000000ff) ^
+				rcon[i];
+			rk[ 7] = rk[ 1] ^ rk[ 6];
+			rk[ 8] = rk[ 2] ^ rk[ 7];
+			rk[ 9] = rk[ 3] ^ rk[ 8];
+			if (++i == 8) {
+				return 12;
+			}
+			rk[10] = rk[ 4] ^ rk[ 9];
+			rk[11] = rk[ 5] ^ rk[10];
+			rk += 6;
+		}
+	}
+	rk[6] = GETU32(cipherKey + 24);
+	rk[7] = GETU32(cipherKey + 28);
+	if (keyBits == 256) {
+        for (;;) {
+        	temp = rk[ 7];
+        	rk[ 8] = rk[ 0] ^
+        		(Te4[(temp >> 16) & 0xff] & 0xff000000) ^
+        		(Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^
+        		(Te4[(temp      ) & 0xff] & 0x0000ff00) ^
+        		(Te4[(temp >> 24)       ] & 0x000000ff) ^
+        		rcon[i];
+        	rk[ 9] = rk[ 1] ^ rk[ 8];
+        	rk[10] = rk[ 2] ^ rk[ 9];
+        	rk[11] = rk[ 3] ^ rk[10];
+			if (++i == 7) {
+				return 14;
+			}
+        	temp = rk[11];
+        	rk[12] = rk[ 4] ^
+        		(Te4[(temp >> 24)       ] & 0xff000000) ^
+        		(Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^
+        		(Te4[(temp >>  8) & 0xff] & 0x0000ff00) ^
+        		(Te4[(temp      ) & 0xff] & 0x000000ff);
+        	rk[13] = rk[ 5] ^ rk[12];
+        	rk[14] = rk[ 6] ^ rk[13];
+        	rk[15] = rk[ 7] ^ rk[14];
+
+			rk += 8;
+        }
+	}
+	return 0;
+}
+
+/**
+ * Expand the cipher key into the decryption key schedule.
+ *
+ * @return	the number of rounds for the given cipher key size.
+ */
+/*
+ * __db_rijndaelKeySetupDec --
+ *
+ * PUBLIC: int __db_rijndaelKeySetupDec __P((u32 *, const u8 *, int));
+ */
+int
+__db_rijndaelKeySetupDec(rk, cipherKey, keyBits)
+	u32 *rk;	/* rk[4*(Nr + 1)] */
+	const u8 *cipherKey;
+	int keyBits;
+{
+	int Nr, i, j;
+	u32 temp;
+
+	/* expand the cipher key: */
+	Nr = __db_rijndaelKeySetupEnc(rk, cipherKey, keyBits);
+	/* invert the order of the round keys: */
+	for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) {
+		temp = rk[i    ]; rk[i    ] = rk[j    ]; rk[j    ] = temp;
+		temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
+		temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
+		temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
+	}
+	/* apply the inverse MixColumn transform to all round keys but the first and the last: */
+	for (i = 1; i < Nr; i++) {
+		rk += 4;
+		rk[0] =
+			Td0[Te4[(rk[0] >> 24)       ] & 0xff] ^
+			Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^
+			Td2[Te4[(rk[0] >>  8) & 0xff] & 0xff] ^
+			Td3[Te4[(rk[0]      ) & 0xff] & 0xff];
+		rk[1] =
+			Td0[Te4[(rk[1] >> 24)       ] & 0xff] ^
+			Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^
+			Td2[Te4[(rk[1] >>  8) & 0xff] & 0xff] ^
+			Td3[Te4[(rk[1]      ) & 0xff] & 0xff];
+		rk[2] =
+			Td0[Te4[(rk[2] >> 24)       ] & 0xff] ^
+			Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^
+			Td2[Te4[(rk[2] >>  8) & 0xff] & 0xff] ^
+			Td3[Te4[(rk[2]      ) & 0xff] & 0xff];
+		rk[3] =
+			Td0[Te4[(rk[3] >> 24)       ] & 0xff] ^
+			Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^
+			Td2[Te4[(rk[3] >>  8) & 0xff] & 0xff] ^
+			Td3[Te4[(rk[3]      ) & 0xff] & 0xff];
+	}
+	return Nr;
+}
+
+/*
+ * __db_rijndaelEncrypt --
+ *
+ * PUBLIC: void __db_rijndaelEncrypt __P((u32 *, int, const u8 *, u8 *));
+ */
+void
+__db_rijndaelEncrypt(rk, Nr, pt, ct)
+	u32 *rk;	/* rk[4*(Nr + 1)] */
+	int Nr;
+	const u8 *pt;
+	u8 *ct;
+{
+	u32 s0, s1, s2, s3, t0, t1, t2, t3;
+#ifndef FULL_UNROLL
+    int r;
+#endif /* ?FULL_UNROLL */
+
+    /*
+	 * map byte array block to cipher state
+	 * and add initial round key:
+	 */
+	s0 = GETU32(pt     ) ^ rk[0];
+	s1 = GETU32(pt +  4) ^ rk[1];
+	s2 = GETU32(pt +  8) ^ rk[2];
+	s3 = GETU32(pt + 12) ^ rk[3];
+#ifdef FULL_UNROLL
+    /* round 1: */
+   	t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4];
+   	t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5];
+   	t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6];
+   	t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7];
+   	/* round 2: */
+   	s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8];
+   	s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9];
+   	s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10];
+   	s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11];
+    /* round 3: */
+   	t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12];
+   	t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13];
+   	t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14];
+   	t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15];
+   	/* round 4: */
+   	s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16];
+   	s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17];
+   	s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18];
+   	s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19];
+    /* round 5: */
+   	t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20];
+   	t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21];
+   	t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22];
+   	t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23];
+   	/* round 6: */
+   	s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24];
+   	s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25];
+   	s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26];
+   	s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27];
+    /* round 7: */
+   	t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28];
+   	t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29];
+   	t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30];
+   	t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31];
+   	/* round 8: */
+   	s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32];
+   	s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33];
+   	s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34];
+   	s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35];
+    /* round 9: */
+   	t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36];
+   	t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37];
+   	t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38];
+   	t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39];
+    if (Nr > 10) {
+        /* round 10: */
+        s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40];
+        s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41];
+        s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42];
+        s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43];
+        /* round 11: */
+        t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44];
+        t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45];
+        t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46];
+        t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47];
+        if (Nr > 12) {
+            /* round 12: */
+            s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48];
+            s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49];
+            s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50];
+            s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51];
+            /* round 13: */
+            t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52];
+            t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53];
+            t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54];
+            t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55];
+        }
+    }
+    rk += Nr << 2;
+#else  /* !FULL_UNROLL */
+    /*
+	 * Nr - 1 full rounds:
+	 */
+    r = Nr >> 1;
+    for (;;) {
+        t0 =
+            Te0[(s0 >> 24)       ] ^
+            Te1[(s1 >> 16) & 0xff] ^
+            Te2[(s2 >>  8) & 0xff] ^
+            Te3[(s3      ) & 0xff] ^
+            rk[4];
+        t1 =
+            Te0[(s1 >> 24)       ] ^
+            Te1[(s2 >> 16) & 0xff] ^
+            Te2[(s3 >>  8) & 0xff] ^
+            Te3[(s0      ) & 0xff] ^
+            rk[5];
+        t2 =
+            Te0[(s2 >> 24)       ] ^
+            Te1[(s3 >> 16) & 0xff] ^
+            Te2[(s0 >>  8) & 0xff] ^
+            Te3[(s1      ) & 0xff] ^
+            rk[6];
+        t3 =
+            Te0[(s3 >> 24)       ] ^
+            Te1[(s0 >> 16) & 0xff] ^
+            Te2[(s1 >>  8) & 0xff] ^
+            Te3[(s2      ) & 0xff] ^
+            rk[7];
+
+        rk += 8;
+        if (--r == 0) {
+            break;
+        }
+
+        s0 =
+            Te0[(t0 >> 24)       ] ^
+            Te1[(t1 >> 16) & 0xff] ^
+            Te2[(t2 >>  8) & 0xff] ^
+            Te3[(t3      ) & 0xff] ^
+            rk[0];
+        s1 =
+            Te0[(t1 >> 24)       ] ^
+            Te1[(t2 >> 16) & 0xff] ^
+            Te2[(t3 >>  8) & 0xff] ^
+            Te3[(t0      ) & 0xff] ^
+            rk[1];
+        s2 =
+            Te0[(t2 >> 24)       ] ^
+            Te1[(t3 >> 16) & 0xff] ^
+            Te2[(t0 >>  8) & 0xff] ^
+            Te3[(t1      ) & 0xff] ^
+            rk[2];
+        s3 =
+            Te0[(t3 >> 24)       ] ^
+            Te1[(t0 >> 16) & 0xff] ^
+            Te2[(t1 >>  8) & 0xff] ^
+            Te3[(t2      ) & 0xff] ^
+            rk[3];
+    }
+#endif /* ?FULL_UNROLL */
+    /*
+	 * apply last round and
+	 * map cipher state to byte array block:
+	 */
+	s0 =
+		(Te4[(t0 >> 24)       ] & 0xff000000) ^
+		(Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
+		(Te4[(t2 >>  8) & 0xff] & 0x0000ff00) ^
+		(Te4[(t3      ) & 0xff] & 0x000000ff) ^
+		rk[0];
+	PUTU32(ct     , s0);
+	s1 =
+		(Te4[(t1 >> 24)       ] & 0xff000000) ^
+		(Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
+		(Te4[(t3 >>  8) & 0xff] & 0x0000ff00) ^
+		(Te4[(t0      ) & 0xff] & 0x000000ff) ^
+		rk[1];
+	PUTU32(ct +  4, s1);
+	s2 =
+		(Te4[(t2 >> 24)       ] & 0xff000000) ^
+		(Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
+		(Te4[(t0 >>  8) & 0xff] & 0x0000ff00) ^
+		(Te4[(t1      ) & 0xff] & 0x000000ff) ^
+		rk[2];
+	PUTU32(ct +  8, s2);
+	s3 =
+		(Te4[(t3 >> 24)       ] & 0xff000000) ^
+		(Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
+		(Te4[(t1 >>  8) & 0xff] & 0x0000ff00) ^
+		(Te4[(t2      ) & 0xff] & 0x000000ff) ^
+		rk[3];
+	PUTU32(ct + 12, s3);
+}
+
+/*
+ * __db_rijndaelDecrypt --
+ *
+ * PUBLIC: void __db_rijndaelDecrypt __P((u32 *, int, const u8 *, u8 *));
+ */
+void
+__db_rijndaelDecrypt(rk, Nr, ct, pt)
+	u32 *rk;	/* rk[4*(Nr + 1)] */
+	int Nr;
+	const u8 *ct;
+	u8 *pt;
+{
+	u32 s0, s1, s2, s3, t0, t1, t2, t3;
+#ifndef FULL_UNROLL
+    int r;
+#endif /* ?FULL_UNROLL */
+
+    /*
+	 * map byte array block to cipher state
+	 * and add initial round key:
+	 */
+    s0 = GETU32(ct     ) ^ rk[0];
+    s1 = GETU32(ct +  4) ^ rk[1];
+    s2 = GETU32(ct +  8) ^ rk[2];
+    s3 = GETU32(ct + 12) ^ rk[3];
+#ifdef FULL_UNROLL
+    /* round 1: */
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4];
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5];
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6];
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7];
+    /* round 2: */
+    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8];
+    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9];
+    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10];
+    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11];
+    /* round 3: */
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12];
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13];
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14];
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15];
+    /* round 4: */
+    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16];
+    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17];
+    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18];
+    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19];
+    /* round 5: */
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20];
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21];
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22];
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23];
+    /* round 6: */
+    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24];
+    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25];
+    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26];
+    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27];
+    /* round 7: */
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28];
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29];
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30];
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31];
+    /* round 8: */
+    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32];
+    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33];
+    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34];
+    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35];
+    /* round 9: */
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36];
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37];
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38];
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39];
+    if (Nr > 10) {
+        /* round 10: */
+        s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40];
+        s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41];
+        s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42];
+        s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43];
+        /* round 11: */
+        t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44];
+        t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45];
+        t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46];
+        t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47];
+        if (Nr > 12) {
+            /* round 12: */
+            s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48];
+            s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49];
+            s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50];
+            s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51];
+            /* round 13: */
+            t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52];
+            t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53];
+            t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54];
+            t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55];
+        }
+    }
+	rk += Nr << 2;
+#else  /* !FULL_UNROLL */
+    /*
+     * Nr - 1 full rounds:
+     */
+    r = Nr >> 1;
+    for (;;) {
+        t0 =
+            Td0[(s0 >> 24)       ] ^
+            Td1[(s3 >> 16) & 0xff] ^
+            Td2[(s2 >>  8) & 0xff] ^
+            Td3[(s1      ) & 0xff] ^
+            rk[4];
+        t1 =
+            Td0[(s1 >> 24)       ] ^
+            Td1[(s0 >> 16) & 0xff] ^
+            Td2[(s3 >>  8) & 0xff] ^
+            Td3[(s2      ) & 0xff] ^
+            rk[5];
+        t2 =
+            Td0[(s2 >> 24)       ] ^
+            Td1[(s1 >> 16) & 0xff] ^
+            Td2[(s0 >>  8) & 0xff] ^
+            Td3[(s3      ) & 0xff] ^
+            rk[6];
+        t3 =
+            Td0[(s3 >> 24)       ] ^
+            Td1[(s2 >> 16) & 0xff] ^
+            Td2[(s1 >>  8) & 0xff] ^
+            Td3[(s0      ) & 0xff] ^
+            rk[7];
+
+        rk += 8;
+        if (--r == 0) {
+            break;
+        }
+
+        s0 =
+            Td0[(t0 >> 24)       ] ^
+            Td1[(t3 >> 16) & 0xff] ^
+            Td2[(t2 >>  8) & 0xff] ^
+            Td3[(t1      ) & 0xff] ^
+            rk[0];
+        s1 =
+            Td0[(t1 >> 24)       ] ^
+            Td1[(t0 >> 16) & 0xff] ^
+            Td2[(t3 >>  8) & 0xff] ^
+            Td3[(t2      ) & 0xff] ^
+            rk[1];
+        s2 =
+            Td0[(t2 >> 24)       ] ^
+            Td1[(t1 >> 16) & 0xff] ^
+            Td2[(t0 >>  8) & 0xff] ^
+            Td3[(t3      ) & 0xff] ^
+            rk[2];
+        s3 =
+            Td0[(t3 >> 24)       ] ^
+            Td1[(t2 >> 16) & 0xff] ^
+            Td2[(t1 >>  8) & 0xff] ^
+            Td3[(t0      ) & 0xff] ^
+            rk[3];
+    }
+#endif /* ?FULL_UNROLL */
+    /*
+	 * apply last round and
+	 * map cipher state to byte array block:
+	 */
+   	s0 =
+   		(Td4[(t0 >> 24)       ] & 0xff000000) ^
+   		(Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
+   		(Td4[(t2 >>  8) & 0xff] & 0x0000ff00) ^
+   		(Td4[(t1      ) & 0xff] & 0x000000ff) ^
+   		rk[0];
+	PUTU32(pt     , s0);
+   	s1 =
+   		(Td4[(t1 >> 24)       ] & 0xff000000) ^
+   		(Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
+   		(Td4[(t3 >>  8) & 0xff] & 0x0000ff00) ^
+   		(Td4[(t2      ) & 0xff] & 0x000000ff) ^
+   		rk[1];
+	PUTU32(pt +  4, s1);
+   	s2 =
+   		(Td4[(t2 >> 24)       ] & 0xff000000) ^
+   		(Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
+   		(Td4[(t0 >>  8) & 0xff] & 0x0000ff00) ^
+   		(Td4[(t3      ) & 0xff] & 0x000000ff) ^
+   		rk[2];
+	PUTU32(pt +  8, s2);
+   	s3 =
+   		(Td4[(t3 >> 24)       ] & 0xff000000) ^
+   		(Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
+   		(Td4[(t1 >>  8) & 0xff] & 0x0000ff00) ^
+   		(Td4[(t0      ) & 0xff] & 0x000000ff) ^
+   		rk[3];
+	PUTU32(pt + 12, s3);
+}
+
+#ifdef INTERMEDIATE_VALUE_KAT
+
+/*
+ * __db_rijndaelEncryptRound --
+ *
+ * PUBLIC: void __db_rijndaelEncryptRound __P((const u32 *, int, u8 *, int));
+ */
+void
+__db_rijndaelEncryptRound(rk, Nr, pt, ct)
+	const u32 *rk;	/* rk[4*(Nr + 1)] */
+	int Nr;
+	u8 *block;
+	int rounds;
+{
+	int r;
+	u32 s0, s1, s2, s3, t0, t1, t2, t3;
+
+    /*
+	 * map byte array block to cipher state
+	 * and add initial round key:
+	 */
+	s0 = GETU32(block     ) ^ rk[0];
+	s1 = GETU32(block +  4) ^ rk[1];
+	s2 = GETU32(block +  8) ^ rk[2];
+	s3 = GETU32(block + 12) ^ rk[3];
+    rk += 4;
+
+    /*
+	 * Nr - 1 full rounds:
+	 */
+	for (r = (rounds < Nr ? rounds : Nr - 1); r > 0; r--) {
+		t0 =
+			Te0[(s0 >> 24)       ] ^
+			Te1[(s1 >> 16) & 0xff] ^
+			Te2[(s2 >>  8) & 0xff] ^
+			Te3[(s3      ) & 0xff] ^
+			rk[0];
+		t1 =
+			Te0[(s1 >> 24)       ] ^
+			Te1[(s2 >> 16) & 0xff] ^
+			Te2[(s3 >>  8) & 0xff] ^
+			Te3[(s0      ) & 0xff] ^
+			rk[1];
+		t2 =
+			Te0[(s2 >> 24)       ] ^
+			Te1[(s3 >> 16) & 0xff] ^
+			Te2[(s0 >>  8) & 0xff] ^
+			Te3[(s1      ) & 0xff] ^
+			rk[2];
+		t3 =
+			Te0[(s3 >> 24)       ] ^
+			Te1[(s0 >> 16) & 0xff] ^
+			Te2[(s1 >>  8) & 0xff] ^
+			Te3[(s2      ) & 0xff] ^
+			rk[3];
+
+		s0 = t0;
+		s1 = t1;
+		s2 = t2;
+		s3 = t3;
+		rk += 4;
+
+    }
+
+    /*
+	 * apply last round and
+	 * map cipher state to byte array block:
+	 */
+	if (rounds == Nr) {
+    	t0 =
+    		(Te4[(s0 >> 24)       ] & 0xff000000) ^
+    		(Te4[(s1 >> 16) & 0xff] & 0x00ff0000) ^
+    		(Te4[(s2 >>  8) & 0xff] & 0x0000ff00) ^
+    		(Te4[(s3      ) & 0xff] & 0x000000ff) ^
+    		rk[0];
+    	t1 =
+    		(Te4[(s1 >> 24)       ] & 0xff000000) ^
+    		(Te4[(s2 >> 16) & 0xff] & 0x00ff0000) ^
+    		(Te4[(s3 >>  8) & 0xff] & 0x0000ff00) ^
+    		(Te4[(s0      ) & 0xff] & 0x000000ff) ^
+    		rk[1];
+    	t2 =
+    		(Te4[(s2 >> 24)       ] & 0xff000000) ^
+    		(Te4[(s3 >> 16) & 0xff] & 0x00ff0000) ^
+    		(Te4[(s0 >>  8) & 0xff] & 0x0000ff00) ^
+    		(Te4[(s1      ) & 0xff] & 0x000000ff) ^
+    		rk[2];
+    	t3 =
+    		(Te4[(s3 >> 24)       ] & 0xff000000) ^
+    		(Te4[(s0 >> 16) & 0xff] & 0x00ff0000) ^
+    		(Te4[(s1 >>  8) & 0xff] & 0x0000ff00) ^
+    		(Te4[(s2      ) & 0xff] & 0x000000ff) ^
+    		rk[3];
+		
+		s0 = t0;
+		s1 = t1;
+		s2 = t2;
+		s3 = t3;
+	}
+
+	PUTU32(block     , s0);
+	PUTU32(block +  4, s1);
+	PUTU32(block +  8, s2);
+	PUTU32(block + 12, s3);
+}
+
+/*
+ * __db_rijndaelDecryptRound --
+ *
+ * PUBLIC: void __db_rijndaelDecryptRound __P((const u32 *, int, u8 *, int));
+ */
+void
+__db_rijndaelDecryptRound(rk, Nr, pt, ct)
+	const u32 *rk;	/* rk[4*(Nr + 1)] */
+	int Nr;
+	u8 *block;
+	int rounds;
+{
+	int r;
+	u32 s0, s1, s2, s3, t0, t1, t2, t3;
+
+    /*
+	 * map byte array block to cipher state
+	 * and add initial round key:
+	 */
+	s0 = GETU32(block     ) ^ rk[0];
+	s1 = GETU32(block +  4) ^ rk[1];
+	s2 = GETU32(block +  8) ^ rk[2];
+	s3 = GETU32(block + 12) ^ rk[3];
+    rk += 4;
+
+    /*
+	 * Nr - 1 full rounds:
+	 */
+	for (r = (rounds < Nr ? rounds : Nr) - 1; r > 0; r--) {
+		t0 =
+			Td0[(s0 >> 24)       ] ^
+			Td1[(s3 >> 16) & 0xff] ^
+			Td2[(s2 >>  8) & 0xff] ^
+			Td3[(s1      ) & 0xff] ^
+			rk[0];
+		t1 =
+			Td0[(s1 >> 24)       ] ^
+			Td1[(s0 >> 16) & 0xff] ^
+			Td2[(s3 >>  8) & 0xff] ^
+			Td3[(s2      ) & 0xff] ^
+			rk[1];
+		t2 =
+			Td0[(s2 >> 24)       ] ^
+			Td1[(s1 >> 16) & 0xff] ^
+			Td2[(s0 >>  8) & 0xff] ^
+			Td3[(s3      ) & 0xff] ^
+			rk[2];
+		t3 =
+			Td0[(s3 >> 24)       ] ^
+			Td1[(s2 >> 16) & 0xff] ^
+			Td2[(s1 >>  8) & 0xff] ^
+			Td3[(s0      ) & 0xff] ^
+			rk[3];
+
+		s0 = t0;
+		s1 = t1;
+		s2 = t2;
+		s3 = t3;
+		rk += 4;
+
+    }
+
+    /*
+	 * complete the last round and
+	 * map cipher state to byte array block:
+	 */
+	t0 =
+		(Td4[(s0 >> 24)       ] & 0xff000000) ^
+		(Td4[(s3 >> 16) & 0xff] & 0x00ff0000) ^
+		(Td4[(s2 >>  8) & 0xff] & 0x0000ff00) ^
+		(Td4[(s1      ) & 0xff] & 0x000000ff);
+	t1 =
+		(Td4[(s1 >> 24)       ] & 0xff000000) ^
+		(Td4[(s0 >> 16) & 0xff] & 0x00ff0000) ^
+		(Td4[(s3 >>  8) & 0xff] & 0x0000ff00) ^
+		(Td4[(s2      ) & 0xff] & 0x000000ff);
+	t2 =
+		(Td4[(s2 >> 24)       ] & 0xff000000) ^
+		(Td4[(s1 >> 16) & 0xff] & 0x00ff0000) ^
+		(Td4[(s0 >>  8) & 0xff] & 0x0000ff00) ^
+		(Td4[(s3      ) & 0xff] & 0x000000ff);
+	t3 =
+		(Td4[(s3 >> 24)       ] & 0xff000000) ^
+		(Td4[(s2 >> 16) & 0xff] & 0x00ff0000) ^
+		(Td4[(s1 >>  8) & 0xff] & 0x0000ff00) ^
+		(Td4[(s0      ) & 0xff] & 0x000000ff);
+
+	if (rounds == Nr) {
+	    t0 ^= rk[0];
+	    t1 ^= rk[1];
+	    t2 ^= rk[2];
+	    t3 ^= rk[3];
+	}
+
+	PUTU32(block     , t0);
+	PUTU32(block +  4, t1);
+	PUTU32(block +  8, t2);
+	PUTU32(block + 12, t3);
+}
+
+#endif /* INTERMEDIATE_VALUE_KAT */
diff --git a/storage/bdb/crypto/rijndael/rijndael-alg-fst.h b/storage/bdb/crypto/rijndael/rijndael-alg-fst.h
new file mode 100644
index 0000000000000000000000000000000000000000..fe9ce3814713845c85b47e287b2c0548e0e0d48f
--- /dev/null
+++ b/storage/bdb/crypto/rijndael/rijndael-alg-fst.h
@@ -0,0 +1,40 @@
+/*
+ * $Id: rijndael-alg-fst.h,v 1.2 2002/01/08 18:53:37 sue Exp $
+ */
+/**
+ * rijndael-alg-fst.h
+ *
+ * @version 3.0 (December 2000)
+ *
+ * Optimised ANSI C code for the Rijndael cipher (now AES)
+ *
+ * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
+ * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
+ * @author Paulo Barreto <paulo.barreto@terra.com.br>
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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.
+ */
+#ifndef __RIJNDAEL_ALG_FST_H
+#define __RIJNDAEL_ALG_FST_H
+
+#define MAXKC	(256/32)
+#define MAXKB	(256/8)
+#define MAXNR	14
+
+typedef u_int8_t	u8;	
+typedef u_int16_t	u16;	
+typedef u_int32_t	u32;
+
+#endif /* __RIJNDAEL_ALG_FST_H */
diff --git a/storage/bdb/crypto/rijndael/rijndael-api-fst.c b/storage/bdb/crypto/rijndael/rijndael-api-fst.c
new file mode 100644
index 0000000000000000000000000000000000000000..09475370f6b33b529b8fa174bafdabfa13d51c72
--- /dev/null
+++ b/storage/bdb/crypto/rijndael/rijndael-api-fst.c
@@ -0,0 +1,496 @@
+/**
+ * rijndael-api-fst.c
+ *
+ * @version 2.9 (December 2000)
+ *
+ * Optimised ANSI C code for the Rijndael cipher (now AES)
+ *
+ * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
+ * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
+ * @author Paulo Barreto <paulo.barreto@terra.com.br>
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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.
+ *
+ * Acknowledgements:
+ *
+ * We are deeply indebted to the following people for their bug reports,
+ * fixes, and improvement suggestions to this implementation. Though we
+ * tried to list all contributions, we apologise in advance for any
+ * missing reference.
+ *
+ * Andrew Bales <Andrew.Bales@Honeywell.com>
+ * Markus Friedl <markus.friedl@informatik.uni-erlangen.de>
+ * John Skodon <skodonj@webquill.com>
+ */
+
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/crypto.h"
+
+#include "crypto/rijndael/rijndael-alg-fst.h"
+#include "crypto/rijndael/rijndael-api-fst.h"
+
+/*
+ * __db_makeKey --
+ *
+ * PUBLIC: int __db_makeKey __P((keyInstance *, int, int, char *));
+ */
+int
+__db_makeKey(key, direction, keyLen, keyMaterial)
+	keyInstance *key;
+	int direction;
+	int keyLen;
+	char *keyMaterial;
+{
+	u8 cipherKey[MAXKB];
+	
+	if (key == NULL) {
+		return BAD_KEY_INSTANCE;
+	}
+
+	if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) {
+		key->direction = direction;
+	} else {
+		return BAD_KEY_DIR;
+	}
+
+	if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) {
+		key->keyLen = keyLen;
+	} else {
+		return BAD_KEY_MAT;
+	}
+
+	if (keyMaterial != NULL) {
+		memcpy(cipherKey, keyMaterial, key->keyLen/8);
+	}
+
+	if (direction == DIR_ENCRYPT) {
+		key->Nr = __db_rijndaelKeySetupEnc(key->rk, cipherKey, keyLen);
+	} else {
+		key->Nr = __db_rijndaelKeySetupDec(key->rk, cipherKey, keyLen);
+	}
+	__db_rijndaelKeySetupEnc(key->ek, cipherKey, keyLen);
+	return TRUE;
+}
+
+/*
+ * __db_cipherInit --
+ *
+ * PUBLIC: int __db_cipherInit __P((cipherInstance *, int, char *));
+ */
+int
+__db_cipherInit(cipher, mode, IV)
+	cipherInstance *cipher;
+	int mode;
+	char *IV;
+{
+	if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) {
+		cipher->mode = mode;
+	} else {
+		return BAD_CIPHER_MODE;
+	}
+	if (IV != NULL) {
+	  memcpy(cipher->IV, IV, MAX_IV_SIZE);
+	}
+	return TRUE;
+}
+
+/*
+ * __db_blockEncrypt --
+ *
+ * PUBLIC: int __db_blockEncrypt __P((cipherInstance *, keyInstance *, u_int8_t *,
+ * PUBLIC:    size_t, u_int8_t *));
+ */
+int
+__db_blockEncrypt(cipher, key, input, inputLen, outBuffer)
+	cipherInstance *cipher;
+	keyInstance *key;
+	u_int8_t *input;
+	size_t inputLen;
+	u_int8_t *outBuffer;
+{
+	int i, k, t, numBlocks;
+	u8 block[16], *iv;
+	u32 tmpiv[4];
+
+	if (cipher == NULL ||
+		key == NULL ||
+		key->direction == DIR_DECRYPT) {
+		return BAD_CIPHER_STATE;
+	}
+	if (input == NULL || inputLen <= 0) {
+		return 0; /* nothing to do */
+	}
+
+	numBlocks = (int)(inputLen/128);
+	
+	switch (cipher->mode) {
+	case MODE_ECB:
+		for (i = numBlocks; i > 0; i--) {
+			__db_rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
+			input += 16;
+			outBuffer += 16;
+		}
+		break;
+		
+	case MODE_CBC:
+		iv = cipher->IV;
+		for (i = numBlocks; i > 0; i--) {
+			memcpy(tmpiv, iv, MAX_IV_SIZE);
+			((u32*)block)[0] = ((u32*)input)[0] ^ tmpiv[0];
+			((u32*)block)[1] = ((u32*)input)[1] ^ tmpiv[1];
+			((u32*)block)[2] = ((u32*)input)[2] ^ tmpiv[2];
+			((u32*)block)[3] = ((u32*)input)[3] ^ tmpiv[3];
+			__db_rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
+			iv = outBuffer;
+			input += 16;
+			outBuffer += 16;
+		}
+		break;
+
+    case MODE_CFB1:
+		iv = cipher->IV;
+        for (i = numBlocks; i > 0; i--) {
+			memcpy(outBuffer, input, 16);
+            for (k = 0; k < 128; k++) {
+				__db_rijndaelEncrypt(key->ek, key->Nr, iv, block);
+                outBuffer[k >> 3] ^= (block[0] & (u_int)0x80) >> (k & 7);
+                for (t = 0; t < 15; t++) {
+                	iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
+                }
+               	iv[15] = (iv[15] << 1) | ((outBuffer[k >> 3] >> (7 - (k & 7))) & 1);
+            }
+            outBuffer += 16;
+            input += 16;
+        }
+        break;
+
+	default:
+		return BAD_CIPHER_STATE;
+	}
+	
+	return 128*numBlocks;
+}
+
+/**
+ * Encrypt data partitioned in octets, using RFC 2040-like padding.
+ *
+ * @param   input           data to be encrypted (octet sequence)
+ * @param   inputOctets		input length in octets (not bits)
+ * @param   outBuffer       encrypted output data
+ *
+ * @return	length in octets (not bits) of the encrypted output buffer.
+ */
+/*
+ * __db_padEncrypt --
+ *
+ * PUBLIC: int __db_padEncrypt __P((cipherInstance *, keyInstance *, u_int8_t *,
+ * PUBLIC:    int, u_int8_t *));
+ */
+int
+__db_padEncrypt(cipher, key, input, inputOctets, outBuffer)
+	cipherInstance *cipher;
+	keyInstance *key;
+	u_int8_t *input;
+	int inputOctets;
+	u_int8_t *outBuffer;
+{
+	int i, numBlocks, padLen;
+	u8 block[16], *iv;
+	u32 tmpiv[4];
+
+	if (cipher == NULL ||
+		key == NULL ||
+		key->direction == DIR_DECRYPT) {
+		return BAD_CIPHER_STATE;
+	}
+	if (input == NULL || inputOctets <= 0) {
+		return 0; /* nothing to do */
+	}
+
+	numBlocks = inputOctets/16;
+
+	switch (cipher->mode) {
+	case MODE_ECB:
+		for (i = numBlocks; i > 0; i--) {
+			__db_rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
+			input += 16;
+			outBuffer += 16;
+		}
+		padLen = 16 - (inputOctets - 16*numBlocks);
+		DB_ASSERT(padLen > 0 && padLen <= 16);
+		memcpy(block, input, 16 - padLen);
+		memset(block + 16 - padLen, padLen, padLen);
+		__db_rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
+		break;
+
+	case MODE_CBC:
+		iv = cipher->IV;
+		for (i = numBlocks; i > 0; i--) {
+			memcpy(tmpiv, iv, MAX_IV_SIZE);
+			((u32*)block)[0] = ((u32*)input)[0] ^ tmpiv[0];
+			((u32*)block)[1] = ((u32*)input)[1] ^ tmpiv[1];
+			((u32*)block)[2] = ((u32*)input)[2] ^ tmpiv[2];
+			((u32*)block)[3] = ((u32*)input)[3] ^ tmpiv[3];
+			__db_rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
+			iv = outBuffer;
+			input += 16;
+			outBuffer += 16;
+		}
+		padLen = 16 - (inputOctets - 16*numBlocks);
+		DB_ASSERT(padLen > 0 && padLen <= 16);
+		for (i = 0; i < 16 - padLen; i++) {
+			block[i] = input[i] ^ iv[i];
+		}
+		for (i = 16 - padLen; i < 16; i++) {
+			block[i] = (u_int8_t)padLen ^ iv[i];
+		}
+		__db_rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
+		break;
+
+	default:
+		return BAD_CIPHER_STATE;
+	}
+
+	return 16*(numBlocks + 1);
+}
+
+/*
+ * __db_blockDecrypt --
+ *
+ * PUBLIC: int __db_blockDecrypt __P((cipherInstance *, keyInstance *, u_int8_t *,
+ * PUBLIC:    size_t, u_int8_t *));
+ */
+int
+__db_blockDecrypt(cipher, key, input, inputLen, outBuffer)
+	cipherInstance *cipher;
+	keyInstance *key;
+	u_int8_t *input;
+	size_t inputLen;
+	u_int8_t *outBuffer;
+{
+	int i, k, t, numBlocks;
+	u8 block[16], *iv;
+	u32 tmpiv[4];
+
+	if (cipher == NULL ||
+		key == NULL ||
+		(cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT)) {
+		return BAD_CIPHER_STATE;
+	}
+	if (input == NULL || inputLen <= 0) {
+		return 0; /* nothing to do */
+	}
+
+	numBlocks = (int)(inputLen/128);
+
+	switch (cipher->mode) {
+	case MODE_ECB:
+		for (i = numBlocks; i > 0; i--) {
+			__db_rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
+			input += 16;
+			outBuffer += 16;
+		}
+		break;
+		
+	case MODE_CBC:
+		memcpy(tmpiv, cipher->IV, MAX_IV_SIZE);
+		for (i = numBlocks; i > 0; i--) {
+			__db_rijndaelDecrypt(key->rk, key->Nr, input, block);
+			((u32*)block)[0] ^= tmpiv[0];
+			((u32*)block)[1] ^= tmpiv[1];
+			((u32*)block)[2] ^= tmpiv[2];
+			((u32*)block)[3] ^= tmpiv[3];
+			memcpy(tmpiv, input, 16);
+			memcpy(outBuffer, block, 16);
+			input += 16;
+			outBuffer += 16;
+		}
+		break;
+
+    case MODE_CFB1:
+		iv = cipher->IV;
+        for (i = numBlocks; i > 0; i--) {
+			memcpy(outBuffer, input, 16);
+            for (k = 0; k < 128; k++) {
+				__db_rijndaelEncrypt(key->ek, key->Nr, iv, block);
+                for (t = 0; t < 15; t++) {
+                	iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
+                }
+               	iv[15] = (iv[15] << 1) | ((input[k >> 3] >> (7 - (k & 7))) & 1);
+                outBuffer[k >> 3] ^= (block[0] & (u_int)0x80) >> (k & 7);
+            }
+            outBuffer += 16;
+            input += 16;
+        }
+        break;
+
+	default:
+		return BAD_CIPHER_STATE;
+	}
+	
+	return 128*numBlocks;
+}
+
+/*
+ * __db_padDecrypt --
+ *
+ * PUBLIC: int __db_padDecrypt __P((cipherInstance *, keyInstance *, u_int8_t *,
+ * PUBLIC:    int, u_int8_t *));
+ */
+int
+__db_padDecrypt(cipher, key, input, inputOctets, outBuffer)
+	cipherInstance *cipher;
+	keyInstance *key;
+	u_int8_t *input;
+	int inputOctets;
+	u_int8_t *outBuffer;
+{
+	int i, numBlocks, padLen;
+	u8 block[16];
+	u32 tmpiv[4];
+
+	if (cipher == NULL ||
+		key == NULL ||
+		key->direction == DIR_ENCRYPT) {
+		return BAD_CIPHER_STATE;
+	}
+	if (input == NULL || inputOctets <= 0) {
+		return 0; /* nothing to do */
+	}
+	if (inputOctets % 16 != 0) {
+		return BAD_DATA;
+	}
+
+	numBlocks = inputOctets/16;
+
+	switch (cipher->mode) {
+	case MODE_ECB:
+		/* all blocks but last */
+		for (i = numBlocks - 1; i > 0; i--) {
+			__db_rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
+			input += 16;
+			outBuffer += 16;
+		}
+		/* last block */
+		__db_rijndaelDecrypt(key->rk, key->Nr, input, block);
+		padLen = block[15];
+		if (padLen >= 16) {
+			return BAD_DATA;
+		}
+		for (i = 16 - padLen; i < 16; i++) {
+			if (block[i] != padLen) {
+				return BAD_DATA;
+			}
+		}
+		memcpy(outBuffer, block, 16 - padLen);
+		break;
+		
+	case MODE_CBC:
+		/* all blocks but last */
+		memcpy(tmpiv, cipher->IV, MAX_IV_SIZE);
+		for (i = numBlocks - 1; i > 0; i--) {
+			__db_rijndaelDecrypt(key->rk, key->Nr, input, block);
+			((u32*)block)[0] ^= tmpiv[0];
+			((u32*)block)[1] ^= tmpiv[1];
+			((u32*)block)[2] ^= tmpiv[2];
+			((u32*)block)[3] ^= tmpiv[3];
+			memcpy(tmpiv, input, 16);
+			memcpy(outBuffer, block, 16);
+			input += 16;
+			outBuffer += 16;
+		}
+		/* last block */
+		__db_rijndaelDecrypt(key->rk, key->Nr, input, block);
+		((u32*)block)[0] ^= tmpiv[0];
+		((u32*)block)[1] ^= tmpiv[1];
+		((u32*)block)[2] ^= tmpiv[2];
+		((u32*)block)[3] ^= tmpiv[3];
+		padLen = block[15];
+		if (padLen <= 0 || padLen > 16) {
+			return BAD_DATA;
+		}
+		for (i = 16 - padLen; i < 16; i++) {
+			if (block[i] != padLen) {
+				return BAD_DATA;
+			}
+		}
+		memcpy(outBuffer, block, 16 - padLen);
+		break;
+	
+	default:
+		return BAD_CIPHER_STATE;
+	}
+	
+	return 16*numBlocks - padLen;
+}
+
+#ifdef INTERMEDIATE_VALUE_KAT
+/**
+ *	cipherUpdateRounds:
+ *
+ *	Encrypts/Decrypts exactly one full block a specified number of rounds.
+ *	Only used in the Intermediate Value Known Answer Test.	
+ *
+ *	Returns:
+ *		TRUE - on success
+ *		BAD_CIPHER_STATE - cipher in bad state (e.g., not initialized)
+ */
+/*
+ * __db_cipherUpdateRounds --
+ *
+ * PUBLIC: int __db_cipherUpdateRounds __P((cipherInstance *, keyInstance *,
+ * PUBLIC:    u_int8_t *, int, u_int8_t *, int));
+ */
+int
+__db_cipherUpdateRounds(cipher, key, input, inputLen, outBuffer, rounds)
+	cipherInstance *cipher;
+	keyInstance *key;
+	u_int8_t *input;
+	size_t inputLen;
+	u_int8_t *outBuffer;
+	int rounds;
+{
+	u8 block[16];
+
+	if (cipher == NULL || key == NULL) {
+		return BAD_CIPHER_STATE;
+	}
+
+	memcpy(block, input, 16);
+
+	switch (key->direction) {
+	case DIR_ENCRYPT:
+		__db_rijndaelEncryptRound(key->rk, key->Nr, block, rounds);
+		break;
+		
+	case DIR_DECRYPT:
+		__db_rijndaelDecryptRound(key->rk, key->Nr, block, rounds);
+		break;
+		
+	default:
+		return BAD_KEY_DIR;
+	} 
+
+	memcpy(outBuffer, block, 16);
+	
+	return TRUE;
+}
+#endif /* INTERMEDIATE_VALUE_KAT */
diff --git a/storage/bdb/crypto/rijndael/rijndael-api-fst.h b/storage/bdb/crypto/rijndael/rijndael-api-fst.h
new file mode 100644
index 0000000000000000000000000000000000000000..4137aa25edc871abe4904a43d4901c63eda00d86
--- /dev/null
+++ b/storage/bdb/crypto/rijndael/rijndael-api-fst.h
@@ -0,0 +1,91 @@
+/*
+ * $Id: rijndael-api-fst.h,v 1.5 2003/03/17 19:42:18 bostic Exp $
+ */
+/**
+ * rijndael-api-fst.h
+ *
+ * @version 2.9 (December 2000)
+ *
+ * Optimised ANSI C code for the Rijndael cipher (now AES)
+ *
+ * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
+ * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
+ * @author Paulo Barreto <paulo.barreto@terra.com.br>
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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.
+ *
+ * Acknowledgements:
+ *
+ * We are deeply indebted to the following people for their bug reports,
+ * fixes, and improvement suggestions to this implementation. Though we
+ * tried to list all contributions, we apologise in advance for any
+ * missing reference.
+ *
+ * Andrew Bales <Andrew.Bales@Honeywell.com>
+ * Markus Friedl <markus.friedl@informatik.uni-erlangen.de>
+ * John Skodon <skodonj@webquill.com>
+ */
+
+#ifndef __RIJNDAEL_API_FST_H
+#define __RIJNDAEL_API_FST_H
+
+#include "crypto/rijndael/rijndael-alg-fst.h"
+
+/*  Generic Defines  */
+#define     DIR_ENCRYPT           0 /*  Are we encrpyting?  */
+#define     DIR_DECRYPT           1 /*  Are we decrpyting?  */
+#define     MODE_ECB              1 /*  Are we ciphering in ECB mode?   */
+#define     MODE_CBC              2 /*  Are we ciphering in CBC mode?   */
+#define     MODE_CFB1             3 /*  Are we ciphering in 1-bit CFB mode? */
+#undef	    TRUE
+#define     TRUE                  1
+#undef	    FALSE
+#define     FALSE                 0
+#define     BITSPERBLOCK        128 /* Default number of bits in a cipher block */
+
+/*  Error Codes  */
+#define     BAD_KEY_DIR          -1 /*  Key direction is invalid, e.g., unknown value */
+#define     BAD_KEY_MAT          -2 /*  Key material not of correct length */
+#define     BAD_KEY_INSTANCE     -3 /*  Key passed is not valid */
+#define     BAD_CIPHER_MODE      -4 /*  Params struct passed to cipherInit invalid */
+#define     BAD_CIPHER_STATE     -5 /*  Cipher in wrong state (e.g., not initialized) */
+#define     BAD_BLOCK_LENGTH     -6
+#define     BAD_CIPHER_INSTANCE  -7
+#define     BAD_DATA             -8 /*  Data contents are invalid, e.g., invalid padding */
+#define     BAD_OTHER            -9 /*  Unknown error */
+
+/*  Algorithm-specific Defines  */
+#define     MAX_KEY_SIZE         64 /* # of ASCII char's needed to represent a key */
+#define     MAX_IV_SIZE          16 /* # bytes needed to represent an IV  */
+
+/*  Typedefs  */
+
+/*  The structure for key information */
+typedef struct {
+    u_int8_t  direction;            /* Key used for encrypting or decrypting? */
+    int   keyLen;                   /* Length of the key  */
+    char  keyMaterial[MAX_KEY_SIZE+1];  /* Raw key data in ASCII, e.g., user input or KAT values */
+	int   Nr;                       /* key-length-dependent number of rounds */
+	u32   rk[4*(MAXNR + 1)];        /* key schedule */
+	u32   ek[4*(MAXNR + 1)];        /* CFB1 key schedule (encryption only) */
+} keyInstance;
+
+/*  The structure for cipher information */
+typedef struct {                    /* changed order of the components */
+    u_int8_t  mode;                 /* MODE_ECB, MODE_CBC, or MODE_CFB1 */
+    u_int8_t  IV[MAX_IV_SIZE];      /* A possible Initialization Vector for ciphering */
+} cipherInstance;
+
+#endif /* __RIJNDAEL_API_FST_H */
diff --git a/storage/bdb/cxx/cxx_db.cpp b/storage/bdb/cxx/cxx_db.cpp
index 7e50a9b3f2797386f8543e3a35fcc8cc596d6861..22f1b135d18d341d948b01f48c7b74e2796fb3eb 100644
--- a/storage/bdb/cxx/cxx_db.cpp
+++ b/storage/bdb/cxx/cxx_db.cpp
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: cxx_db.cpp,v 11.87 2004/07/15 18:26:48 ubell Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: cxx_db.cpp,v 11.71 2002/08/26 22:13:36 mjc Exp $";
-#endif /* not lint */
-
 #include <errno.h>
 #include <string.h>
 
@@ -39,25 +37,24 @@ int Db::_name _argspec							\
 									\
 	ret = db->_name _arglist;					\
 	if (!_retok(ret))						\
-		DB_ERROR("Db::" # _name, ret, error_policy());		\
+		DB_ERROR(env_, "Db::" # _name, ret, error_policy());	\
 	return (ret);							\
 }
 
-#define	DB_METHOD_CHECKED(_name, _cleanup, _argspec, _arglist, _retok)	\
+#define	DB_DESTRUCTOR(_name, _argspec, _arglist, _retok)		\
 int Db::_name _argspec							\
 {									\
 	int ret;							\
 	DB *db = unwrap(this);						\
 									\
 	if (!db) {							\
-		DB_ERROR("Db::" # _name, EINVAL, error_policy());	\
+		DB_ERROR(env_, "Db::" # _name, EINVAL, error_policy());	\
 		return (EINVAL);					\
 	}								\
-	if (_cleanup)							\
-		cleanup();						\
+	cleanup();							\
 	ret = db->_name _arglist;					\
 	if (!_retok(ret))						\
-		DB_ERROR("Db::" # _name, ret, error_policy());		\
+		DB_ERROR(env_, "Db::" # _name, ret, error_policy());	\
 	return (ret);							\
 }
 
@@ -92,6 +89,7 @@ void Db::_name _argspec							\
 Db::Db(DbEnv *env, u_int32_t flags)
 :	imp_(0)
 ,	env_(env)
+,	mpf_(0)
 ,	construct_error_(0)
 ,	flags_(0)
 ,	construct_flags_(flags)
@@ -107,7 +105,7 @@ Db::Db(DbEnv *env, u_int32_t flags)
 		flags_ |= DB_CXX_PRIVATE_ENV;
 
 	if ((construct_error_ = initialize()) != 0)
-		DB_ERROR("Db::Db", construct_error_, error_policy());
+		DB_ERROR(env_, "Db::Db", construct_error_, error_policy());
 }
 
 // If the DB handle is still open, we close it.  This is to make stack
@@ -150,7 +148,7 @@ int Db::initialize()
 		return (ret);
 
 	// Associate the DB with this object
-	imp_ = wrap(db);
+	imp_ = db;
 	db->api_internal = this;
 
 	// Create a new DbEnv from a DB_ENV* if it was created locally.
@@ -159,6 +157,10 @@ int Db::initialize()
 	if ((flags_ & DB_CXX_PRIVATE_ENV) != 0)
 		env_ = new DbEnv(db->dbenv, cxx_flags);
 
+	// Create a DbMpoolFile from the DB_MPOOLFILE* in the DB handle.
+	mpf_ = new DbMpoolFile();
+	mpf_->imp_ = db->mpf;
+
 	return (0);
 }
 
@@ -173,7 +175,6 @@ void Db::cleanup()
 
 	if (db != NULL) {
 		// extra safety
-		db->api_internal = 0;
 		imp_ = 0;
 
 		// we must dispose of the DbEnv object if
@@ -187,6 +188,8 @@ void Db::cleanup()
 			delete env_;
 			env_ = 0;
 		}
+
+		delete mpf_;
 	}
 }
 
@@ -215,26 +218,7 @@ int Db::error_policy()
 	}
 }
 
-int Db::close(u_int32_t flags)
-{
-	DB *db = unwrap(this);
-	int ret;
-
-	// after a DB->close (no matter if success or failure),
-	// the underlying DB object must not be accessed,
-	// so we clean up in advance.
-	//
-	cleanup();
-
-	// It's safe to throw an error after the close,
-	// since our error mechanism does not peer into
-	// the DB* structures.
-	//
-	if ((ret = db->close(db, flags)) != 0)
-		DB_ERROR("Db::close", ret, error_policy());
-
-	return (ret);
-}
+DB_DESTRUCTOR(close, (u_int32_t flags), (db, flags), DB_RETOK_STD)
 
 // The following cast implies that Dbc can be no larger than DBC
 DB_METHOD(cursor, (DbTxn *txnid, Dbc **cursorp, u_int32_t flags),
@@ -259,9 +243,7 @@ void Db::errx(const char *format, ...)
 	DB_REAL_ERR(db->dbenv, 0, 0, 1, format);
 }
 
-DB_METHOD(fd, (int *fdp),
-    (db, fdp),
-    DB_RETOK_STD)
+DB_METHOD(fd, (int *fdp), (db, fdp), DB_RETOK_STD)
 
 int Db::get(DbTxn *txnid, Dbt *key, Dbt *value, u_int32_t flags)
 {
@@ -271,10 +253,10 @@ int Db::get(DbTxn *txnid, Dbt *key, Dbt *value, u_int32_t flags)
 	ret = db->get(db, unwrap(txnid), key, value, flags);
 
 	if (!DB_RETOK_DBGET(ret)) {
-		if (ret == ENOMEM && DB_OVERFLOWED_DBT(value))
-			DB_ERROR_DBT("Db::get", value, error_policy());
+		if (ret == DB_BUFFER_SMALL)
+			DB_ERROR_DBT(env_, "Db::get", value, error_policy());
 		else
-			DB_ERROR("Db::get", ret, error_policy());
+			DB_ERROR(env_, "Db::get", ret, error_policy());
 	}
 
 	return (ret);
@@ -286,6 +268,23 @@ int Db::get_byteswapped(int *isswapped)
 	return (db->get_byteswapped(db, isswapped));
 }
 
+DbEnv *Db::get_env()
+{
+	DB *db = (DB *)unwrapConst(this);
+	DB_ENV *dbenv = db->get_env(db);
+	return (dbenv != NULL ? DbEnv::get_DbEnv(dbenv) : NULL);
+}
+
+DbMpoolFile *Db::get_mpf()
+{
+	return (mpf_);
+}
+
+DB_METHOD(get_dbname, (const char **filenamep, const char **dbnamep),
+    (db, filenamep, dbnamep), DB_RETOK_STD)
+
+DB_METHOD(get_open_flags, (u_int32_t *flagsp), (db, flagsp), DB_RETOK_STD)
+
 int Db::get_type(DBTYPE *dbtype)
 {
 	DB *db = (DB *)unwrapConst(this);
@@ -296,13 +295,11 @@ int Db::get_type(DBTYPE *dbtype)
 // or even extra data members, so these casts, although technically
 // non-portable, "should" always be okay.
 DB_METHOD(join, (Dbc **curslist, Dbc **cursorp, u_int32_t flags),
-    (db, (DBC **)curslist, (DBC **)cursorp, flags),
-    DB_RETOK_STD)
+    (db, (DBC **)curslist, (DBC **)cursorp, flags), DB_RETOK_STD)
 
 DB_METHOD(key_range,
     (DbTxn *txnid, Dbt *key, DB_KEY_RANGE *results, u_int32_t flags),
-    (db, unwrap(txnid), key, results, flags),
-    DB_RETOK_STD)
+    (db, unwrap(txnid), key, results, flags), DB_RETOK_STD)
 
 // If an error occurred during the constructor, report it now.
 // Otherwise, call the underlying DB->open method.
@@ -320,7 +317,7 @@ int Db::open(DbTxn *txnid, const char *file, const char *database,
 		    mode);
 
 	if (!DB_RETOK_STD(ret))
-		DB_ERROR("Db::open", ret, error_policy());
+		DB_ERROR(env_, "Db::open", ret, error_policy());
 
 	return (ret);
 }
@@ -335,39 +332,36 @@ int Db::pget(DbTxn *txnid, Dbt *key, Dbt *pkey, Dbt *value, u_int32_t flags)
 	/* The logic here is identical to Db::get - reuse the macro. */
 	if (!DB_RETOK_DBGET(ret)) {
 		if (ret == ENOMEM && DB_OVERFLOWED_DBT(value))
-			DB_ERROR_DBT("Db::pget", value, error_policy());
+			DB_ERROR_DBT(env_, "Db::pget", value, error_policy());
 		else
-			DB_ERROR("Db::pget", ret, error_policy());
+			DB_ERROR(env_, "Db::pget", ret, error_policy());
 	}
 
 	return (ret);
 }
 
-DB_METHOD(put,
-    (DbTxn *txnid, Dbt *key, Dbt *value, u_int32_t flags),
-    (db, unwrap(txnid), key, value, flags),
-    DB_RETOK_DBPUT)
+DB_METHOD(put, (DbTxn *txnid, Dbt *key, Dbt *value, u_int32_t flags),
+    (db, unwrap(txnid), key, value, flags), DB_RETOK_DBPUT)
 
-DB_METHOD_CHECKED(rename, 1,
+DB_DESTRUCTOR(rename,
     (const char *file, const char *database, const char *newname,
     u_int32_t flags),
     (db, file, database, newname, flags), DB_RETOK_STD)
 
-DB_METHOD_CHECKED(remove, 1,
-    (const char *file, const char *database, u_int32_t flags),
+DB_DESTRUCTOR(remove, (const char *file, const char *database, u_int32_t flags),
     (db, file, database, flags), DB_RETOK_STD)
 
-DB_METHOD_CHECKED(truncate, 0,
-    (DbTxn *txnid, u_int32_t *countp, u_int32_t flags),
+DB_METHOD(truncate, (DbTxn *txnid, u_int32_t *countp, u_int32_t flags),
     (db, unwrap(txnid), countp, flags), DB_RETOK_STD)
 
-DB_METHOD_CHECKED(stat, 0,
-    (void *sp, u_int32_t flags), (db, sp, flags), DB_RETOK_STD)
+DB_METHOD(stat, (DbTxn *txnid, void *sp, u_int32_t flags),
+    (db, unwrap(txnid), sp, flags), DB_RETOK_STD)
 
-DB_METHOD_CHECKED(sync, 0,
-    (u_int32_t flags), (db, flags), DB_RETOK_STD)
+DB_METHOD(stat_print, (u_int32_t flags), (db, flags), DB_RETOK_STD)
 
-DB_METHOD_CHECKED(upgrade, 0,
+DB_METHOD(sync, (u_int32_t flags), (db, flags), DB_RETOK_STD)
+
+DB_METHOD(upgrade,
     (const char *name, u_int32_t flags), (db, name, flags), DB_RETOK_STD)
 
 ////////////////////////////////////////////////////////////////////////
@@ -412,7 +406,7 @@ extern "C" _rettype _db_##_name##_intercept_c _cargspec			\
 	Db *cxxthis;							\
 									\
 	DB_ASSERT(cthis != NULL);					\
-	cxxthis = (Db *)cthis->api_internal;				\
+	cxxthis = Db::get_Db(cthis);					\
 	DB_ASSERT(cxxthis != NULL);					\
 	DB_ASSERT(cxxthis->_name##_callback_ != 0);			\
 									\
@@ -503,10 +497,10 @@ extern "C"
 int _verify_callback_c(void *handle, const void *str_arg)
 {
 	char *str;
-	__DB_OSTREAMCLASS *out;
+	__DB_STD(ostream) *out;
 
 	str = (char *)str_arg;
-	out = (__DB_OSTREAMCLASS *)handle;
+	out = (__DB_STD(ostream) *)handle;
 
 	(*out) << str;
 	if (out->fail())
@@ -516,19 +510,26 @@ int _verify_callback_c(void *handle, const void *str_arg)
 }
 
 int Db::verify(const char *name, const char *subdb,
-	       __DB_OSTREAMCLASS *ostr, u_int32_t flags)
+	       __DB_STD(ostream) *ostr, u_int32_t flags)
 {
 	DB *db = unwrap(this);
 	int ret;
 
 	if (!db)
 		ret = EINVAL;
-	else
+	else {
+		// after a DB->verify (no matter if success or failure),
+		// the underlying DB object must not be accessed,
+		// so we clean up in advance.
+		//
+		cleanup();
+
 		ret = __db_verify_internal(db, name, subdb, ostr,
 		    _verify_callback_c, flags);
+	}
 
 	if (!DB_RETOK_STD(ret))
-		DB_ERROR("Db::verify", ret, error_policy());
+		DB_ERROR(env_, "Db::verify", ret, error_policy());
 
 	return (ret);
 }
@@ -537,36 +538,64 @@ DB_METHOD(set_bt_compare, (bt_compare_fcn_type func),
     (db, func), DB_RETOK_STD)
 DB_METHOD(set_bt_maxkey, (u_int32_t bt_maxkey),
     (db, bt_maxkey), DB_RETOK_STD)
+DB_METHOD(get_bt_minkey, (u_int32_t *bt_minkeyp),
+    (db, bt_minkeyp), DB_RETOK_STD)
 DB_METHOD(set_bt_minkey, (u_int32_t bt_minkey),
     (db, bt_minkey), DB_RETOK_STD)
 DB_METHOD(set_bt_prefix, (bt_prefix_fcn_type func),
     (db, func), DB_RETOK_STD)
 DB_METHOD(set_dup_compare, (dup_compare_fcn_type func),
     (db, func), DB_RETOK_STD)
-DB_METHOD(set_encrypt, (const char *passwd, int flags),
+DB_METHOD(get_encrypt_flags, (u_int32_t *flagsp),
+    (db, flagsp), DB_RETOK_STD)
+DB_METHOD(set_encrypt, (const char *passwd, u_int32_t flags),
     (db, passwd, flags), DB_RETOK_STD)
+DB_METHOD_VOID(get_errfile, (FILE **errfilep), (db, errfilep))
 DB_METHOD_VOID(set_errfile, (FILE *errfile), (db, errfile))
+DB_METHOD_VOID(get_errpfx, (const char **errpfx), (db, errpfx))
 DB_METHOD_VOID(set_errpfx, (const char *errpfx), (db, errpfx))
+DB_METHOD(get_flags, (u_int32_t *flagsp), (db, flagsp),
+    DB_RETOK_STD)
 DB_METHOD(set_flags, (u_int32_t flags), (db, flags),
     DB_RETOK_STD)
+DB_METHOD(get_h_ffactor, (u_int32_t *h_ffactorp),
+    (db, h_ffactorp), DB_RETOK_STD)
 DB_METHOD(set_h_ffactor, (u_int32_t h_ffactor),
     (db, h_ffactor), DB_RETOK_STD)
 DB_METHOD(set_h_hash, (h_hash_fcn_type func),
     (db, func), DB_RETOK_STD)
+DB_METHOD(get_h_nelem, (u_int32_t *h_nelemp),
+    (db, h_nelemp), DB_RETOK_STD)
 DB_METHOD(set_h_nelem, (u_int32_t h_nelem),
     (db, h_nelem), DB_RETOK_STD)
+DB_METHOD(get_lorder, (int *db_lorderp), (db, db_lorderp),
+    DB_RETOK_STD)
 DB_METHOD(set_lorder, (int db_lorder), (db, db_lorder),
     DB_RETOK_STD)
+DB_METHOD_VOID(get_msgfile, (FILE **msgfilep), (db, msgfilep))
+DB_METHOD_VOID(set_msgfile, (FILE *msgfile), (db, msgfile))
+DB_METHOD(get_pagesize, (u_int32_t *db_pagesizep),
+    (db, db_pagesizep), DB_RETOK_STD)
 DB_METHOD(set_pagesize, (u_int32_t db_pagesize),
     (db, db_pagesize), DB_RETOK_STD)
+DB_METHOD(get_re_delim, (int *re_delimp),
+    (db, re_delimp), DB_RETOK_STD)
 DB_METHOD(set_re_delim, (int re_delim),
     (db, re_delim), DB_RETOK_STD)
+DB_METHOD(get_re_len, (u_int32_t *re_lenp),
+    (db, re_lenp), DB_RETOK_STD)
 DB_METHOD(set_re_len, (u_int32_t re_len),
     (db, re_len), DB_RETOK_STD)
+DB_METHOD(get_re_pad, (int *re_padp),
+    (db, re_padp), DB_RETOK_STD)
 DB_METHOD(set_re_pad, (int re_pad),
     (db, re_pad), DB_RETOK_STD)
-DB_METHOD(set_re_source, (char *re_source),
+DB_METHOD(get_re_source, (const char **re_source),
+    (db, re_source), DB_RETOK_STD)
+DB_METHOD(set_re_source, (const char *re_source),
     (db, re_source), DB_RETOK_STD)
+DB_METHOD(get_q_extentsize, (u_int32_t *extentsizep),
+    (db, extentsizep), DB_RETOK_STD)
 DB_METHOD(set_q_extentsize, (u_int32_t extentsize),
     (db, extentsize), DB_RETOK_STD)
 
@@ -574,11 +603,16 @@ DB_METHOD_QUIET(set_alloc, (db_malloc_fcn_type malloc_fcn,
     db_realloc_fcn_type realloc_fcn, db_free_fcn_type free_fcn),
     (db, malloc_fcn, realloc_fcn, free_fcn))
 
-void Db::set_errcall(void (*arg)(const char *, char *))
+void Db::set_errcall(void (*arg)(const DbEnv *, const char *, const char *))
 {
 	env_->set_errcall(arg);
 }
 
+void Db::set_msgcall(void (*arg)(const DbEnv *, const char *))
+{
+	env_->set_msgcall(arg);
+}
+
 void *Db::get_app_private() const
 {
 	return unwrapConst(this)->app_private;
@@ -589,17 +623,34 @@ void Db::set_app_private(void *value)
 	unwrap(this)->app_private = value;
 }
 
+DB_METHOD(get_cachesize, (u_int32_t *gbytesp, u_int32_t *bytesp, int *ncachep),
+    (db, gbytesp, bytesp, ncachep), DB_RETOK_STD)
 DB_METHOD(set_cachesize, (u_int32_t gbytes, u_int32_t bytes, int ncache),
     (db, gbytes, bytes, ncache), DB_RETOK_STD)
-DB_METHOD(set_cache_priority, (DB_CACHE_PRIORITY priority),
-    (db, priority), DB_RETOK_STD)
 
 int Db::set_paniccall(void (*callback)(DbEnv *, int))
 {
 	return (env_->set_paniccall(callback));
 }
 
-void Db::set_error_stream(__DB_OSTREAMCLASS *error_stream)
+__DB_STD(ostream) *Db::get_error_stream()
+{
+	return env_->get_error_stream();
+}
+
+void Db::set_error_stream(__DB_STD(ostream) *error_stream)
 {
 	env_->set_error_stream(error_stream);
 }
+
+__DB_STD(ostream) *Db::get_message_stream()
+{
+	return env_->get_message_stream();
+}
+
+void Db::set_message_stream(__DB_STD(ostream) *message_stream)
+{
+	env_->set_message_stream(message_stream);
+}
+
+DB_METHOD_QUIET(get_transactional, (), (db))
diff --git a/storage/bdb/cxx/cxx_dbc.cpp b/storage/bdb/cxx/cxx_dbc.cpp
index 4d5844f922f1ca5cbef770a63eb785f10d207ce1..0ca59735f991d890b49edc982bb15b71544540f2 100644
--- a/storage/bdb/cxx/cxx_dbc.cpp
+++ b/storage/bdb/cxx/cxx_dbc.cpp
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: cxx_dbc.cpp,v 11.59 2004/01/28 03:35:56 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: cxx_dbc.cpp,v 11.55 2002/07/03 21:03:52 bostic Exp $";
-#endif /* not lint */
-
 #include <errno.h>
 #include <string.h>
 
@@ -39,7 +37,8 @@ int Dbc::_name _argspec							\
 									\
 	ret = dbc->c_##_name _arglist;					\
 	if (!_retok(ret))						\
-		DB_ERROR("Dbc::" # _name, ret, ON_ERROR_UNKNOWN);	\
+		DB_ERROR(DbEnv::get_DbEnv(dbc->dbp->dbenv), \
+			"Dbc::" # _name, ret, ON_ERROR_UNKNOWN); \
 	return (ret);							\
 }
 
@@ -67,7 +66,8 @@ int Dbc::dup(Dbc** cursorp, u_int32_t _flags)
 		// The following cast implies that Dbc can be no larger than DBC
 		*cursorp = (Dbc*)new_cursor;
 	else
-		DB_ERROR("Dbc::dup", ret, ON_ERROR_UNKNOWN);
+		DB_ERROR(DbEnv::get_DbEnv(dbc->dbp->dbenv),
+			"Dbc::dup", ret, ON_ERROR_UNKNOWN);
 
 	return (ret);
 }
@@ -81,11 +81,14 @@ int Dbc::get(Dbt* key, Dbt *data, u_int32_t _flags)
 
 	if (!DB_RETOK_DBCGET(ret)) {
 		if (ret == ENOMEM && DB_OVERFLOWED_DBT(key))
-			DB_ERROR_DBT("Dbc::get", key, ON_ERROR_UNKNOWN);
+			DB_ERROR_DBT(DbEnv::get_DbEnv(dbc->dbp->dbenv),
+				"Dbc::get", key, ON_ERROR_UNKNOWN);
 		else if (ret == ENOMEM && DB_OVERFLOWED_DBT(data))
-			DB_ERROR_DBT("Dbc::get", data, ON_ERROR_UNKNOWN);
+			DB_ERROR_DBT(DbEnv::get_DbEnv(dbc->dbp->dbenv),
+				"Dbc::get", data, ON_ERROR_UNKNOWN);
 		else
-			DB_ERROR("Dbc::get", ret, ON_ERROR_UNKNOWN);
+			DB_ERROR(DbEnv::get_DbEnv(dbc->dbp->dbenv),
+				"Dbc::get", ret, ON_ERROR_UNKNOWN);
 	}
 
 	return (ret);
@@ -101,11 +104,14 @@ int Dbc::pget(Dbt* key, Dbt *pkey, Dbt *data, u_int32_t _flags)
 	/* Logic is the same as for Dbc::get - reusing macro. */
 	if (!DB_RETOK_DBCGET(ret)) {
 		if (ret == ENOMEM && DB_OVERFLOWED_DBT(key))
-			DB_ERROR_DBT("Dbc::pget", key, ON_ERROR_UNKNOWN);
+			DB_ERROR_DBT(DbEnv::get_DbEnv(dbc->dbp->dbenv),
+				"Dbc::pget", key, ON_ERROR_UNKNOWN);
 		else if (ret == ENOMEM && DB_OVERFLOWED_DBT(data))
-			DB_ERROR_DBT("Dbc::pget", data, ON_ERROR_UNKNOWN);
+			DB_ERROR_DBT(DbEnv::get_DbEnv(dbc->dbp->dbenv),
+				"Dbc::pget", data, ON_ERROR_UNKNOWN);
 		else
-			DB_ERROR("Dbc::pget", ret, ON_ERROR_UNKNOWN);
+			DB_ERROR(DbEnv::get_DbEnv(dbc->dbp->dbenv),
+				"Dbc::pget", ret, ON_ERROR_UNKNOWN);
 	}
 
 	return (ret);
diff --git a/storage/bdb/cxx/cxx_dbt.cpp b/storage/bdb/cxx/cxx_dbt.cpp
index 7a4224503eee2183ad91bce7b2dadc120c3e8e11..ab89424953380b49e32c3e50a57cf76620e28268 100644
--- a/storage/bdb/cxx/cxx_dbt.cpp
+++ b/storage/bdb/cxx/cxx_dbt.cpp
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: cxx_dbt.cpp,v 11.55 2004/01/28 03:35:56 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: cxx_dbt.cpp,v 11.53 2002/03/27 04:31:14 bostic Exp $";
-#endif /* not lint */
-
 #include <errno.h>
 #include <string.h>
 
diff --git a/storage/bdb/cxx/cxx_env.cpp b/storage/bdb/cxx/cxx_env.cpp
index c78c6e9fa4765bf8b48facb4264b45d3725656f9..988cecb6c978a5d6cade2a6980abea24ee2a2616 100644
--- a/storage/bdb/cxx/cxx_env.cpp
+++ b/storage/bdb/cxx/cxx_env.cpp
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: cxx_env.cpp,v 11.105 2004/09/22 22:20:31 mjc Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: cxx_env.cpp,v 11.88 2002/08/26 22:13:36 mjc Exp $";
-#endif /* not lint */
-
 #include <errno.h>
 #include <stdio.h>              // needed for set_error_stream
 #include <string.h>
@@ -45,7 +43,7 @@ int DbEnv::_name _argspec					  \
 
 #define	DBENV_METHOD(_name, _argspec, _arglist)			  \
 	DBENV_METHOD_ERR(_name, _argspec, _arglist,		  \
-			 DB_ERROR("DbEnv::" # _name, ret, error_policy()))
+	DB_ERROR(this, "DbEnv::" # _name, ret, error_policy()))
 
 #define	DBENV_METHOD_QUIET(_name, _argspec, _arglist)		  \
 int DbEnv::_name _argspec					  \
@@ -63,13 +61,6 @@ void DbEnv::_name _argspec					  \
 	dbenv->_name _arglist;					  \
 }
 
-// This datatype is needed for picky compilers.
-//
-extern "C" {
-	typedef void (*db_errcall_fcn_type)
-		(const char *, char *);
-};
-
 // The reason for a static variable is that some structures
 // (like Dbts) have no connection to any Db or DbEnv, so when
 // errors occur in their methods, we must have some reasonable
@@ -81,8 +72,6 @@ extern "C" {
 //
 static int last_known_error_policy = ON_ERROR_UNKNOWN;
 
-__DB_OSTREAMCLASS *DbEnv::error_stream_ = 0;
-
 // These 'glue' function are declared as extern "C" so they will
 // be compatible with picky compilers that do not allow mixing
 // of function pointers to 'C' functions with function pointers
@@ -101,40 +90,45 @@ void _paniccall_intercept_c(DB_ENV *env, int errval)
 }
 
 extern "C"
-void _stream_error_function_c(const char *prefix, char *message)
+void _stream_error_function_c(const DB_ENV *env,
+			      const char *prefix, const char *message)
 {
-	DbEnv::_stream_error_function(prefix, message);
+	DbEnv::_stream_error_function(env, prefix, message);
+}
+
+extern "C"
+void _stream_message_function_c(const DB_ENV *env, const char *message)
+{
+	DbEnv::_stream_message_function(env, message);
 }
 
 extern "C"
 int _app_dispatch_intercept_c(DB_ENV *env, DBT *dbt,
-			    DB_LSN *lsn, db_recops op)
+			      DB_LSN *lsn, db_recops op)
 {
 	return (DbEnv::_app_dispatch_intercept(env, dbt, lsn, op));
 }
 
 extern "C"
 int _rep_send_intercept_c(DB_ENV *env, const DBT *cntrl,
-			  const DBT *data, int id, u_int32_t flags)
+			  const DBT *data, const DB_LSN *lsn, int id,
+			  u_int32_t flags)
 {
 	return (DbEnv::_rep_send_intercept(env,
-	    cntrl, data, id, flags));
+	    cntrl, data, lsn, id, flags));
 }
 
 void DbEnv::_feedback_intercept(DB_ENV *env, int opcode, int pct)
 {
-	if (env == 0) {
-		DB_ERROR("DbEnv::feedback_callback", EINVAL, ON_ERROR_UNKNOWN);
-		return;
-	}
-	DbEnv *cxxenv = (DbEnv *)env->api1_internal;
+	DbEnv *cxxenv = DbEnv::get_DbEnv(env);
 	if (cxxenv == 0) {
-		DB_ERROR("DbEnv::feedback_callback", EINVAL, ON_ERROR_UNKNOWN);
+		DB_ERROR(0,
+		    "DbEnv::feedback_callback", EINVAL, ON_ERROR_UNKNOWN);
 		return;
 	}
 	if (cxxenv->feedback_callback_ == 0) {
-		DB_ERROR("DbEnv::feedback_callback", EINVAL,
-			 cxxenv->error_policy());
+		DB_ERROR(DbEnv::get_DbEnv(env),
+		    "DbEnv::feedback_callback", EINVAL, cxxenv->error_policy());
 		return;
 	}
 	(*cxxenv->feedback_callback_)(cxxenv, opcode, pct);
@@ -142,39 +136,33 @@ void DbEnv::_feedback_intercept(DB_ENV *env, int opcode, int pct)
 
 void DbEnv::_paniccall_intercept(DB_ENV *env, int errval)
 {
-	if (env == 0) {
-		DB_ERROR("DbEnv::paniccall_callback", EINVAL,
-		    ON_ERROR_UNKNOWN);
-	}
-	DbEnv *cxxenv = (DbEnv *)env->api1_internal;
+	DbEnv *cxxenv = DbEnv::get_DbEnv(env);
 	if (cxxenv == 0) {
-		DB_ERROR("DbEnv::paniccall_callback", EINVAL,
-		    ON_ERROR_UNKNOWN);
+		DB_ERROR(0,
+		    "DbEnv::paniccall_callback", EINVAL, ON_ERROR_UNKNOWN);
+		return;
 	}
 	if (cxxenv->paniccall_callback_ == 0) {
-		DB_ERROR("DbEnv::paniccall_callback", EINVAL,
+		DB_ERROR(cxxenv, "DbEnv::paniccall_callback", EINVAL,
 		    cxxenv->error_policy());
+		return;
 	}
 	(*cxxenv->paniccall_callback_)(cxxenv, errval);
 }
 
 int DbEnv::_app_dispatch_intercept(DB_ENV *env, DBT *dbt,
-				DB_LSN *lsn, db_recops op)
+				   DB_LSN *lsn, db_recops op)
 {
-	if (env == 0) {
-		DB_ERROR("DbEnv::app_dispatch_callback",
-		    EINVAL, ON_ERROR_UNKNOWN);
-		return (EINVAL);
-	}
-	DbEnv *cxxenv = (DbEnv *)env->api1_internal;
+	DbEnv *cxxenv = DbEnv::get_DbEnv(env);
 	if (cxxenv == 0) {
-		DB_ERROR("DbEnv::app_dispatch_callback",
-		    EINVAL, ON_ERROR_UNKNOWN);
+		DB_ERROR(DbEnv::get_DbEnv(env),
+		    "DbEnv::app_dispatch_callback", EINVAL, ON_ERROR_UNKNOWN);
 		return (EINVAL);
 	}
 	if (cxxenv->app_dispatch_callback_ == 0) {
-		DB_ERROR("DbEnv::app_dispatch_callback",
-		    EINVAL, cxxenv->error_policy());
+		DB_ERROR(DbEnv::get_DbEnv(env),
+		    "DbEnv::app_dispatch_callback", EINVAL,
+		    cxxenv->error_policy());
 		return (EINVAL);
 	}
 	Dbt *cxxdbt = (Dbt *)dbt;
@@ -183,22 +171,20 @@ int DbEnv::_app_dispatch_intercept(DB_ENV *env, DBT *dbt,
 }
 
 int DbEnv::_rep_send_intercept(DB_ENV *env, const DBT *cntrl,
-			       const DBT *data, int id, u_int32_t flags)
+			       const DBT *data, const DB_LSN *lsn,
+			       int id, u_int32_t flags)
 {
-
-	if (env == 0) {
-		DB_ERROR("DbEnv::rep_send_callback", EINVAL, ON_ERROR_UNKNOWN);
-		return (EINVAL);
-	}
-	DbEnv *cxxenv = (DbEnv *)env->api1_internal;
+	DbEnv *cxxenv = DbEnv::get_DbEnv(env);
 	if (cxxenv == 0) {
-		DB_ERROR("DbEnv::rep_send_callback", EINVAL, ON_ERROR_UNKNOWN);
+		DB_ERROR(DbEnv::get_DbEnv(env),
+			"DbEnv::rep_send_callback", EINVAL, ON_ERROR_UNKNOWN);
 		return (EINVAL);
 	}
 	const Dbt *cxxcntrl = (const Dbt *)cntrl;
+	const DbLsn *cxxlsn = (const DbLsn *)lsn;
 	Dbt *cxxdata = (Dbt *)data;
 	return ((*cxxenv->rep_send_callback_)(cxxenv,
-	    cxxcntrl, cxxdata, id, flags));
+	    cxxcntrl, cxxdata, cxxlsn, id, flags));
 }
 
 // A truism for the DbEnv object is that there is a valid
@@ -217,6 +203,8 @@ DbEnv::DbEnv(u_int32_t flags)
 :	imp_(0)
 ,	construct_error_(0)
 ,	construct_flags_(flags)
+,	error_stream_(0)
+,	message_stream_(0)
 ,	app_dispatch_callback_(0)
 ,	feedback_callback_(0)
 ,	paniccall_callback_(0)
@@ -225,13 +213,16 @@ DbEnv::DbEnv(u_int32_t flags)
 ,	rep_send_callback_(0)
 {
 	if ((construct_error_ = initialize(0)) != 0)
-		DB_ERROR("DbEnv::DbEnv", construct_error_, error_policy());
+		DB_ERROR(this, "DbEnv::DbEnv", construct_error_,
+		    error_policy());
 }
 
 DbEnv::DbEnv(DB_ENV *env, u_int32_t flags)
 :	imp_(0)
 ,	construct_error_(0)
 ,	construct_flags_(flags)
+,	error_stream_(0)
+,	message_stream_(0)
 ,	app_dispatch_callback_(0)
 ,	feedback_callback_(0)
 ,	paniccall_callback_(0)
@@ -240,7 +231,8 @@ DbEnv::DbEnv(DB_ENV *env, u_int32_t flags)
 ,	rep_send_callback_(0)
 {
 	if ((construct_error_ = initialize(env)) != 0)
-		DB_ERROR("DbEnv::DbEnv", construct_error_, error_policy());
+		DB_ERROR(this, "DbEnv::DbEnv", construct_error_,
+		    error_policy());
 }
 
 // If the DB_ENV handle is still open, we close it.  This is to make stack
@@ -287,7 +279,7 @@ int DbEnv::close(u_int32_t flags)
 	// the DB* structures.
 	//
 	if ((ret = env->close(env, flags)) != 0)
-		DB_ERROR("DbEnv::close", ret, error_policy());
+		DB_ERROR(this, "DbEnv::close", ret, error_policy());
 
 	return (ret);
 }
@@ -334,6 +326,10 @@ void *DbEnv::get_app_private() const
 	return unwrapConst(this)->app_private;
 }
 
+DBENV_METHOD(get_home, (const char **homep), (dbenv, homep))
+DBENV_METHOD(get_open_flags, (u_int32_t *flagsp), (dbenv, flagsp))
+DBENV_METHOD(get_data_dirs, (const char ***dirspp), (dbenv, dirspp))
+
 // used internally during constructor
 // to associate an existing DB_ENV with this DbEnv,
 // or create a new one.
@@ -350,7 +346,7 @@ int DbEnv::initialize(DB_ENV *env)
 		    construct_flags_ & ~DB_CXX_NO_EXCEPTIONS)) != 0)
 			return (ret);
 	}
-	imp_ = wrap(env);
+	imp_ = env;
 	env->api1_internal = this;	// for DB_ENV* to DbEnv* conversion
 	return (0);
 }
@@ -362,7 +358,7 @@ DBENV_METHOD_ERR(lock_get,
     (u_int32_t locker, u_int32_t flags, const Dbt *obj,
     db_lockmode_t lock_mode, DbLock *lock),
     (dbenv, locker, flags, obj, lock_mode, &lock->lock_),
-    DbEnv::runtime_error_lock_get("DbEnv::lock_get", ret,
+    DbEnv::runtime_error_lock_get(this, "DbEnv::lock_get", ret,
 				  DB_LOCK_GET, lock_mode, obj, *lock,
 				  -1, error_policy()))
 DBENV_METHOD(lock_id, (u_int32_t *idp), (dbenv, idp))
@@ -370,11 +366,12 @@ DBENV_METHOD(lock_id_free, (u_int32_t id), (dbenv, id))
 DBENV_METHOD(lock_put, (DbLock *lock), (dbenv, &lock->lock_))
 DBENV_METHOD(lock_stat, (DB_LOCK_STAT **statp, u_int32_t flags),
     (dbenv, statp, flags))
+DBENV_METHOD(lock_stat_print, (u_int32_t flags), (dbenv, flags))
 DBENV_METHOD_ERR(lock_vec,
     (u_int32_t locker, u_int32_t flags, DB_LOCKREQ list[],
     int nlist, DB_LOCKREQ **elist_returned),
     (dbenv, locker, flags, list, nlist, elist_returned),
-    DbEnv::runtime_error_lock_get("DbEnv::lock_vec", ret,
+    DbEnv::runtime_error_lock_get(this, "DbEnv::lock_vec", ret,
 	(*elist_returned)->op, (*elist_returned)->mode,
 	Dbt::get_Dbt((*elist_returned)->obj), DbLock((*elist_returned)->lock),
 	(*elist_returned) - list, error_policy()))
@@ -397,6 +394,7 @@ DBENV_METHOD(log_put, (DbLsn *lsn, const Dbt *data, u_int32_t flags),
     (dbenv, lsn, data, flags))
 DBENV_METHOD(log_stat, (DB_LOG_STAT **spp, u_int32_t flags),
     (dbenv, spp, flags))
+DBENV_METHOD(log_stat_print, (u_int32_t flags), (dbenv, flags))
 
 int DbEnv::memp_fcreate(DbMpoolFile **dbmfp, u_int32_t flags)
 {
@@ -411,9 +409,9 @@ int DbEnv::memp_fcreate(DbMpoolFile **dbmfp, u_int32_t flags)
 
 	if (DB_RETOK_STD(ret)) {
 		*dbmfp = new DbMpoolFile();
-		(*dbmfp)->imp_ = wrap(mpf);
+		(*dbmfp)->imp_ = mpf;
 	} else
-		DB_ERROR("DbMpoolFile::f_create", ret, ON_ERROR_UNKNOWN);
+		DB_ERROR(this, "DbMpoolFile::f_create", ret, ON_ERROR_UNKNOWN);
 
 	return (ret);
 }
@@ -426,9 +424,8 @@ DBENV_METHOD(memp_register,
 DBENV_METHOD(memp_stat,
     (DB_MPOOL_STAT **gsp, DB_MPOOL_FSTAT ***fsp, u_int32_t flags),
     (dbenv, gsp, fsp, flags))
-
+DBENV_METHOD(memp_stat_print, (u_int32_t flags), (dbenv, flags))
 DBENV_METHOD(memp_sync, (DbLsn *sn), (dbenv, sn))
-
 DBENV_METHOD(memp_trickle, (int pct, int *nwrotep), (dbenv, pct, nwrotep))
 
 // If an error occurred during the constructor, report it now.
@@ -445,7 +442,7 @@ int DbEnv::open(const char *db_home, u_int32_t flags, int mode)
 		ret = env->open(env, db_home, flags, mode);
 
 	if (!DB_RETOK_STD(ret))
-		DB_ERROR("DbEnv::open", ret, error_policy());
+		DB_ERROR(this, "DbEnv::open", ret, error_policy());
 
 	return (ret);
 }
@@ -462,7 +459,7 @@ int DbEnv::remove(const char *db_home, u_int32_t flags)
 	cleanup();
 
 	if ((ret = env->remove(env, db_home, flags)) != 0)
-		DB_ERROR("DbEnv::remove", ret, error_policy());
+		DB_ERROR(this, "DbEnv::remove", ret, error_policy());
 
 	return (ret);
 }
@@ -473,7 +470,8 @@ int DbEnv::remove(const char *db_home, u_int32_t flags)
 //   ON_ERROR_RETURN    do nothing here, the caller will return an error
 //   ON_ERROR_UNKNOWN   defer the policy to policy saved in DbEnv::DbEnv
 //
-void DbEnv::runtime_error(const char *caller, int error, int error_policy)
+void DbEnv::runtime_error(DbEnv *env,
+    const char *caller, int error, int error_policy)
 {
 	if (error_policy == ON_ERROR_UNKNOWN)
 		error_policy = last_known_error_policy;
@@ -484,18 +482,28 @@ void DbEnv::runtime_error(const char *caller, int error, int error_policy)
 		case DB_LOCK_DEADLOCK:
 			{
 				DbDeadlockException dl_except(caller);
+				dl_except.set_env(env);
 				throw dl_except;
 			}
 			break;
 		case DB_RUNRECOVERY:
 			{
 				DbRunRecoveryException rr_except(caller);
+				rr_except.set_env(env);
 				throw rr_except;
 			}
 			break;
+		case DB_LOCK_NOTGRANTED:
+			{
+				DbLockNotGrantedException lng_except(caller);
+				lng_except.set_env(env);
+				throw lng_except;
+			}
+			break;
 		default:
 			{
 				DbException except(caller, error);
+				except.set_env(env);
 				throw except;
 			}
 			break;
@@ -505,7 +513,8 @@ void DbEnv::runtime_error(const char *caller, int error, int error_policy)
 
 // Like DbEnv::runtime_error, but issue a DbMemoryException
 // based on the fact that this Dbt is not large enough.
-void DbEnv::runtime_error_dbt(const char *caller, Dbt *dbt, int error_policy)
+void DbEnv::runtime_error_dbt(DbEnv *env,
+    const char *caller, Dbt *dbt, int error_policy)
 {
 	if (error_policy == ON_ERROR_UNKNOWN)
 		error_policy = last_known_error_policy;
@@ -513,6 +522,7 @@ void DbEnv::runtime_error_dbt(const char *caller, Dbt *dbt, int error_policy)
 		// Creating and throwing the object in two separate
 		// statements seems to be necessary for HP compilers.
 		DbMemoryException except(caller, dbt);
+		except.set_env(env);
 		throw except;
 	}
 }
@@ -520,12 +530,13 @@ void DbEnv::runtime_error_dbt(const char *caller, Dbt *dbt, int error_policy)
 // Like DbEnv::runtime_error, but issue a DbLockNotGrantedException,
 // or a regular runtime error.
 // call regular runtime_error if it
-void DbEnv::runtime_error_lock_get(const char *caller, int error,
+void DbEnv::runtime_error_lock_get(DbEnv *env,
+    const char *caller, int error,
     db_lockop_t op, db_lockmode_t mode, const Dbt *obj,
     DbLock lock, int index, int error_policy)
 {
 	if (error != DB_LOCK_NOTGRANTED) {
-		runtime_error(caller, error, error_policy);
+		runtime_error(env, caller, error, error_policy);
 		return;
 	}
 
@@ -536,52 +547,101 @@ void DbEnv::runtime_error_lock_get(const char *caller, int error,
 		// statements seems to be necessary for HP compilers.
 		DbLockNotGrantedException except(caller, op, mode,
 		    obj, lock, index);
+		except.set_env(env);
 		throw except;
 	}
 }
 
-// static method
-char *DbEnv::strerror(int error)
+void DbEnv::_stream_error_function(
+    const DB_ENV *env, const char *prefix, const char *message)
 {
-	return (db_strerror(error));
-}
+	const DbEnv *cxxenv = DbEnv::get_const_DbEnv(env);
+	if (cxxenv == 0) {
+		DB_ERROR(0,
+		    "DbEnv::stream_error", EINVAL, ON_ERROR_UNKNOWN);
+		return;
+	}
 
-void DbEnv::_stream_error_function(const char *prefix, char *message)
-{
-	// HP compilers need the extra casts, we don't know why.
-	if (error_stream_) {
+	if (cxxenv->error_callback_)
+		cxxenv->error_callback_(cxxenv, prefix, message);
+	else if (cxxenv->error_stream_) {
+		// HP compilers need the extra casts, we don't know why.
 		if (prefix) {
-			(*error_stream_) << prefix << (const char *)": ";
-		}
-		if (message) {
-			(*error_stream_) << (const char *)message;
+			(*cxxenv->error_stream_) << prefix;
+			(*cxxenv->error_stream_) << (const char *)": ";
 		}
-		(*error_stream_) << (const char *)"\n";
+		if (message)
+			(*cxxenv->error_stream_) << (const char *)message;
+		(*cxxenv->error_stream_) << (const char *)"\n";
 	}
 }
 
-// set methods
+void DbEnv::_stream_message_function(const DB_ENV *env, const char *message)
+{
+	const DbEnv *cxxenv = DbEnv::get_const_DbEnv(env);
+	if (cxxenv == 0) {
+		DB_ERROR(0,
+		    "DbEnv::stream_message", EINVAL, ON_ERROR_UNKNOWN);
+		return;
+	}
+
+	if (cxxenv->message_callback_)
+		cxxenv->message_callback_(cxxenv, message);
+	else if (cxxenv->message_stream_) {
+		// HP compilers need the extra casts, we don't know why.
+		(*cxxenv->message_stream_) << (const char *)message;
+		(*cxxenv->message_stream_) << (const char *)"\n";
+	}
+}
 
-DBENV_METHOD_VOID(set_errfile, (FILE *errfile), (dbenv, errfile))
-DBENV_METHOD_VOID(set_errpfx, (const char *errpfx), (dbenv, errpfx))
+// static method
+char *DbEnv::strerror(int error)
+{
+	return (db_strerror(error));
+}
 
 // We keep these alphabetical by field name,
 // for comparison with Java's list.
 //
 DBENV_METHOD(set_data_dir, (const char *dir), (dbenv, dir))
-DBENV_METHOD(set_encrypt, (const char *passwd, int flags),
+DBENV_METHOD(get_encrypt_flags, (u_int32_t *flagsp),
+    (dbenv, flagsp))
+DBENV_METHOD(set_encrypt, (const char *passwd, u_int32_t flags),
     (dbenv, passwd, flags))
+DBENV_METHOD_VOID(get_errfile, (FILE **errfilep), (dbenv, errfilep))
+DBENV_METHOD_VOID(set_errfile, (FILE *errfile), (dbenv, errfile))
+DBENV_METHOD_VOID(get_errpfx, (const char **errpfxp), (dbenv, errpfxp))
+DBENV_METHOD_VOID(set_errpfx, (const char *errpfx), (dbenv, errpfx))
+DBENV_METHOD(get_lg_bsize, (u_int32_t *bsizep), (dbenv, bsizep))
 DBENV_METHOD(set_lg_bsize, (u_int32_t bsize), (dbenv, bsize))
+DBENV_METHOD(get_lg_dir, (const char **dirp), (dbenv, dirp))
 DBENV_METHOD(set_lg_dir, (const char *dir), (dbenv, dir))
+DBENV_METHOD(get_lg_max, (u_int32_t *maxp), (dbenv, maxp))
 DBENV_METHOD(set_lg_max, (u_int32_t max), (dbenv, max))
+DBENV_METHOD(get_lg_regionmax, (u_int32_t *regionmaxp), (dbenv, regionmaxp))
 DBENV_METHOD(set_lg_regionmax, (u_int32_t regionmax), (dbenv, regionmax))
+DBENV_METHOD(get_lk_conflicts, (const u_int8_t **lk_conflictsp, int *lk_maxp),
+    (dbenv, lk_conflictsp, lk_maxp))
+DBENV_METHOD(set_lk_conflicts, (u_int8_t *lk_conflicts, int lk_max),
+    (dbenv, lk_conflicts, lk_max))
+DBENV_METHOD(get_lk_detect, (u_int32_t *detectp), (dbenv, detectp))
 DBENV_METHOD(set_lk_detect, (u_int32_t detect), (dbenv, detect))
 DBENV_METHOD(set_lk_max, (u_int32_t max), (dbenv, max))
+DBENV_METHOD(get_lk_max_lockers, (u_int32_t *max_lockersp),
+    (dbenv, max_lockersp))
 DBENV_METHOD(set_lk_max_lockers, (u_int32_t max_lockers), (dbenv, max_lockers))
+DBENV_METHOD(get_lk_max_locks, (u_int32_t *max_locksp), (dbenv, max_locksp))
 DBENV_METHOD(set_lk_max_locks, (u_int32_t max_locks), (dbenv, max_locks))
+DBENV_METHOD(get_lk_max_objects, (u_int32_t *max_objectsp),
+    (dbenv, max_objectsp))
 DBENV_METHOD(set_lk_max_objects, (u_int32_t max_objects), (dbenv, max_objects))
+DBENV_METHOD(get_mp_mmapsize, (size_t *mmapsizep), (dbenv, mmapsizep))
 DBENV_METHOD(set_mp_mmapsize, (size_t mmapsize), (dbenv, mmapsize))
+DBENV_METHOD_VOID(get_msgfile, (FILE **msgfilep), (dbenv, msgfilep))
+DBENV_METHOD_VOID(set_msgfile, (FILE *msgfile), (dbenv, msgfile))
+DBENV_METHOD(get_tmp_dir, (const char **tmp_dirp), (dbenv, tmp_dirp))
 DBENV_METHOD(set_tmp_dir, (const char *tmp_dir), (dbenv, tmp_dir))
+DBENV_METHOD(get_tx_max, (u_int32_t *tx_maxp), (dbenv, tx_maxp))
 DBENV_METHOD(set_tx_max, (u_int32_t tx_max), (dbenv, tx_max))
 
 DBENV_METHOD_QUIET(set_alloc,
@@ -594,40 +654,36 @@ void DbEnv::set_app_private(void *value)
 	unwrap(this)->app_private = value;
 }
 
+DBENV_METHOD(get_cachesize,
+    (u_int32_t *gbytesp, u_int32_t *bytesp, int *ncachep),
+    (dbenv, gbytesp, bytesp, ncachep))
 DBENV_METHOD(set_cachesize,
     (u_int32_t gbytes, u_int32_t bytes, int ncache),
     (dbenv, gbytes, bytes, ncache))
 
-void DbEnv::set_errcall(void (*arg)(const char *, char *))
+void DbEnv::set_errcall(void (*arg)(const DbEnv *, const char *, const char *))
 {
 	DB_ENV *dbenv = unwrap(this);
 
-	// XXX
-	// We are casting from a function ptr declared with C++
-	// linkage to one (same arg types) declared with C
-	// linkage.  It's hard to imagine a pair of C/C++
-	// compilers from the same vendor for which this
-	// won't work.  Unfortunately, we can't use a
-	// intercept function like the others since the
-	// function does not have a (DbEnv*) as one of
-	// the args.  If this causes trouble, we can pull
-	// the same trick we use in Java, namely stuffing
-	// a (DbEnv*) pointer into the prefix.  We're
-	// avoiding this for the moment because it obfuscates.
-	//
-	(*(dbenv->set_errcall))(dbenv, (db_errcall_fcn_type)arg);
+	error_callback_ = arg;
+	error_stream_ = 0;
+
+	dbenv->set_errcall(dbenv, (arg == 0) ? 0 :
+			   _stream_error_function_c);
 }
 
-// Note: This actually behaves a bit like a static function,
-// since DB_ENV.db_errcall has no information about which
-// db_env triggered the call.  A user that has multiple DB_ENVs
-// will simply not be able to have different streams for each one.
-//
-void DbEnv::set_error_stream(__DB_OSTREAMCLASS *stream)
+__DB_STD(ostream) *DbEnv::get_error_stream()
+{
+	return (error_stream_);
+}
+
+void DbEnv::set_error_stream(__DB_STD(ostream) *stream)
 {
 	DB_ENV *dbenv = unwrap(this);
 
 	error_stream_ = stream;
+	error_callback_ = 0;
+
 	dbenv->set_errcall(dbenv, (stream == 0) ? 0 :
 			   _stream_error_function_c);
 }
@@ -638,12 +694,38 @@ int DbEnv::set_feedback(void (*arg)(DbEnv *, int, int))
 
 	feedback_callback_ = arg;
 
-	return ((*(dbenv->set_feedback))(dbenv, _feedback_intercept_c));
+	return (dbenv->set_feedback(dbenv, _feedback_intercept_c));
 }
 
+DBENV_METHOD(get_flags, (u_int32_t *flagsp), (dbenv, flagsp))
 DBENV_METHOD(set_flags, (u_int32_t flags, int onoff), (dbenv, flags, onoff))
-DBENV_METHOD(set_lk_conflicts, (u_int8_t *lk_conflicts, int lk_max),
-    (dbenv, lk_conflicts, lk_max))
+
+void DbEnv::set_msgcall(void (*arg)(const DbEnv *, const char *))
+{
+	DB_ENV *dbenv = unwrap(this);
+
+	message_callback_ = arg;
+	message_stream_ = 0;
+
+	dbenv->set_msgcall(dbenv, (arg == 0) ? 0 :
+			   _stream_message_function_c);
+}
+
+__DB_STD(ostream) *DbEnv::get_message_stream()
+{
+	return (message_stream_);
+}
+
+void DbEnv::set_message_stream(__DB_STD(ostream) *stream)
+{
+	DB_ENV *dbenv = unwrap(this);
+
+	message_stream_ = stream;
+	message_callback_ = 0;
+
+	dbenv->set_msgcall(dbenv, (stream == 0) ? 0 :
+			   _stream_message_function_c);
+}
 
 int DbEnv::set_paniccall(void (*arg)(DbEnv *, int))
 {
@@ -651,14 +733,16 @@ int DbEnv::set_paniccall(void (*arg)(DbEnv *, int))
 
 	paniccall_callback_ = arg;
 
-	return ((*(dbenv->set_paniccall))(dbenv, _paniccall_intercept_c));
+	return (dbenv->set_paniccall(dbenv, _paniccall_intercept_c));
 }
 
 DBENV_METHOD(set_rpc_server,
     (void *cl, char *host, long tsec, long ssec, u_int32_t flags),
     (dbenv, cl, host, tsec, ssec, flags))
+DBENV_METHOD(get_shm_key, (long *shm_keyp), (dbenv, shm_keyp))
 DBENV_METHOD(set_shm_key, (long shm_key), (dbenv, shm_key))
 // Note: this changes from last_known_error_policy to error_policy()
+DBENV_METHOD(get_tas_spins, (u_int32_t *argp), (dbenv, argp))
 DBENV_METHOD(set_tas_spins, (u_int32_t arg), (dbenv, arg))
 
 int DbEnv::set_app_dispatch
@@ -668,14 +752,17 @@ int DbEnv::set_app_dispatch
 	int ret;
 
 	app_dispatch_callback_ = arg;
-	if ((ret = (*(dbenv->set_app_dispatch))(dbenv,
+	if ((ret = dbenv->set_app_dispatch(dbenv,
 	    _app_dispatch_intercept_c)) != 0)
-		DB_ERROR("DbEnv::set_app_dispatch", ret, error_policy());
+		DB_ERROR(this, "DbEnv::set_app_dispatch", ret, error_policy());
 
 	return (ret);
 }
 
+DBENV_METHOD(get_tx_timestamp, (time_t *timestamp), (dbenv, timestamp))
 DBENV_METHOD(set_tx_timestamp, (time_t *timestamp), (dbenv, timestamp))
+DBENV_METHOD(get_verbose, (u_int32_t which, int *onoffp),
+    (dbenv, which, onoffp))
 DBENV_METHOD(set_verbose, (u_int32_t which, int onoff), (dbenv, which, onoff))
 
 int DbEnv::txn_begin(DbTxn *pid, DbTxn **tid, u_int32_t flags)
@@ -688,7 +775,7 @@ int DbEnv::txn_begin(DbTxn *pid, DbTxn **tid, u_int32_t flags)
 	if (DB_RETOK_STD(ret))
 		*tid = new DbTxn(txn);
 	else
-		DB_ERROR("DbEnv::txn_begin", ret, error_policy());
+		DB_ERROR(this, "DbEnv::txn_begin", ret, error_policy());
 
 	return (ret);
 }
@@ -716,20 +803,20 @@ int DbEnv::txn_recover(DbPreplist *preplist, long count,
 		    &c_preplist);
 
 	if (ret != 0) {
-		DB_ERROR("DbEnv::txn_recover", ret, error_policy());
+		DB_ERROR(this, "DbEnv::txn_recover", ret, error_policy());
 		return (ret);
 	}
 
 	if ((ret =
 	    dbenv->txn_recover(dbenv, c_preplist, count, retp, flags)) != 0) {
 		__os_free(dbenv, c_preplist);
-		DB_ERROR("DbEnv::txn_recover", ret, error_policy());
+		DB_ERROR(this, "DbEnv::txn_recover", ret, error_policy());
 		return (ret);
 	}
 
 	for (i = 0; i < *retp; i++) {
 		preplist[i].txn = new DbTxn();
-		preplist[i].txn->imp_ = wrap(c_preplist[i].txn);
+		preplist[i].txn->imp_ = c_preplist[i].txn;
 		memcpy(preplist[i].gid, c_preplist[i].gid,
 		    sizeof(preplist[i].gid));
 	}
@@ -741,9 +828,11 @@ int DbEnv::txn_recover(DbPreplist *preplist, long count,
 
 DBENV_METHOD(txn_stat, (DB_TXN_STAT **statp, u_int32_t flags),
     (dbenv, statp, flags))
+DBENV_METHOD(txn_stat_print, (u_int32_t flags), (dbenv, flags))
 
-int DbEnv::set_rep_transport(u_int32_t myid,
-    int (*f_send)(DbEnv *, const Dbt *, const Dbt *, int, u_int32_t))
+int DbEnv::set_rep_transport(int myid,
+    int (*f_send)(DbEnv *, const Dbt *, const Dbt *, const DbLsn *, int,
+		  u_int32_t))
 {
 	DB_ENV *dbenv = unwrap(this);
 	int ret;
@@ -751,23 +840,26 @@ int DbEnv::set_rep_transport(u_int32_t myid,
 	rep_send_callback_ = f_send;
 	if ((ret = dbenv->set_rep_transport(dbenv,
 	    myid, _rep_send_intercept_c)) != 0)
-		DB_ERROR("DbEnv::set_rep_transport", ret, error_policy());
+		DB_ERROR(this, "DbEnv::set_rep_transport", ret, error_policy());
 
 	return (ret);
 }
 
 DBENV_METHOD(rep_elect,
-    (int nsites, int pri, u_int32_t timeout, int *idp),
-    (dbenv, nsites, pri, timeout, idp))
+    (int nsites,
+    int nvotes, int priority, u_int32_t timeout, int *eidp, u_int32_t flags),
+    (dbenv, nsites, nvotes, priority, timeout, eidp, flags))
 
-int DbEnv::rep_process_message(Dbt *control, Dbt *rec, int *idp)
+int DbEnv::rep_process_message(Dbt *control,
+    Dbt *rec, int *idp, DbLsn *ret_lsnp)
 {
 	DB_ENV *dbenv = unwrap(this);
 	int ret;
 
-	ret = dbenv->rep_process_message(dbenv, control, rec, idp);
+	ret = dbenv->rep_process_message(dbenv, control, rec, idp, ret_lsnp);
 	if (!DB_RETOK_REPPMSG(ret))
-		DB_ERROR("DbEnv::rep_process_message", ret, error_policy());
+		DB_ERROR(this, "DbEnv::rep_process_message", ret,
+		    error_policy());
 
 	return (ret);
 }
@@ -778,10 +870,16 @@ DBENV_METHOD(rep_start,
 
 DBENV_METHOD(rep_stat, (DB_REP_STAT **statp, u_int32_t flags),
     (dbenv, statp, flags))
+DBENV_METHOD(rep_stat_print, (u_int32_t flags), (dbenv, flags))
 
+DBENV_METHOD(get_rep_limit, (u_int32_t *gbytesp, u_int32_t *bytesp),
+    (dbenv, gbytesp, bytesp))
 DBENV_METHOD(set_rep_limit, (u_int32_t gbytes, u_int32_t bytes),
     (dbenv, gbytes, bytes))
 
+DBENV_METHOD(get_timeout,
+    (db_timeout_t *timeoutp, u_int32_t flags),
+    (dbenv, timeoutp, flags))
 DBENV_METHOD(set_timeout,
     (db_timeout_t timeout, u_int32_t flags),
     (dbenv, timeout, flags))
@@ -796,7 +894,5 @@ char *DbEnv::version(int *major, int *minor, int *patch)
 DbEnv *DbEnv::wrap_DB_ENV(DB_ENV *dbenv)
 {
 	DbEnv *wrapped_env = get_DbEnv(dbenv);
-	if (wrapped_env == NULL)
-		wrapped_env = new DbEnv(dbenv, 0);
-	return wrapped_env;
+	return (wrapped_env != NULL) ? wrapped_env : new DbEnv(dbenv, 0);
 }
diff --git a/storage/bdb/cxx/cxx_except.cpp b/storage/bdb/cxx/cxx_except.cpp
index 40fdeae69d69e3a78c9e91808d65034c0069b64c..22eb0eae98bd1b42cd39f199eb092a1a10e992d7 100644
--- a/storage/bdb/cxx/cxx_except.cpp
+++ b/storage/bdb/cxx/cxx_except.cpp
@@ -1,68 +1,20 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: cxx_except.cpp,v 11.28 2004/09/22 03:34:48 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: cxx_except.cpp,v 11.17 2002/08/23 01:07:27 mjc Exp $";
-#endif /* not lint */
-
 #include <string.h>
 #include <errno.h>
 
 #include "db_cxx.h"
 #include "dbinc/cxx_int.h"
 
-// tmpString is used to create strings on the stack
-//
-class tmpString
-{
-public:
-	tmpString(const char *str1,
-		  const char *str2 = 0,
-		  const char *str3 = 0,
-		  const char *str4 = 0,
-		  const char *str5 = 0);
-	~tmpString()                      { delete [] s_; }
-	operator const char *()           { return (s_); }
-
-private:
-	char *s_;
-};
-
-tmpString::tmpString(const char *str1,
-		     const char *str2,
-		     const char *str3,
-		     const char *str4,
-		     const char *str5)
-{
-	size_t len = strlen(str1);
-	if (str2)
-		len += strlen(str2);
-	if (str3)
-		len += strlen(str3);
-	if (str4)
-		len += strlen(str4);
-	if (str5)
-		len += strlen(str5);
-
-	s_ = new char[len+1];
-
-	strcpy(s_, str1);
-	if (str2)
-		strcat(s_, str2);
-	if (str3)
-		strcat(s_, str3);
-	if (str4)
-		strcat(s_, str4);
-	if (str5)
-		strcat(s_, str5);
-}
-
 // Note: would not be needed if we can inherit from exception
 // It does not appear to be possible to inherit from exception
 // with the current Microsoft library (VC5.0).
@@ -80,65 +32,113 @@ static char *dupString(const char *s)
 //                                                                    //
 ////////////////////////////////////////////////////////////////////////
 
-DbException::~DbException()
+DbException::~DbException() throw()
 {
-	if (what_)
-		delete [] what_;
+	delete [] what_;
 }
 
 DbException::DbException(int err)
 :	err_(err)
+,	env_(0)
 {
-	what_ = dupString(db_strerror(err));
+	describe(0, 0);
 }
 
 DbException::DbException(const char *description)
 :	err_(0)
+,	env_(0)
 {
-	what_ = dupString(tmpString(description));
+	describe(0, description);
 }
 
-DbException::DbException(const char *prefix, int err)
+DbException::DbException(const char *description, int err)
 :	err_(err)
+,	env_(0)
 {
-	what_ = dupString(tmpString(prefix, ": ", db_strerror(err)));
+	describe(0, description);
 }
 
-DbException::DbException(const char *prefix1, const char *prefix2, int err)
+DbException::DbException(const char *prefix, const char *description, int err)
 :	err_(err)
+,	env_(0)
 {
-	what_ = dupString(tmpString(prefix1, ": ", prefix2, ": ",
-	    db_strerror(err)));
+	describe(prefix, description);
 }
 
 DbException::DbException(const DbException &that)
-:	err_(that.err_)
+:	__DB_STD(exception)()
+,	what_(dupString(that.what_))
+,	err_(that.err_)
+,	env_(0)
 {
-	what_ = dupString(that.what_);
 }
 
 DbException &DbException::operator = (const DbException &that)
 {
 	if (this != &that) {
 		err_ = that.err_;
-		if (what_)
-			delete [] what_;
-		what_ = 0;           // in case new throws exception
+		delete [] what_;
 		what_ = dupString(that.what_);
 	}
 	return (*this);
 }
 
+void DbException::describe(const char *prefix, const char *description)
+{
+	char msgbuf[1024], *p, *end;
+
+	p = msgbuf;
+	end = msgbuf + sizeof(msgbuf) - 1;
+
+	if (prefix != NULL) {
+		strncpy(p, prefix, (p < end) ? end - p: 0);
+		p += strlen(prefix);
+		strncpy(p, ": ", (p < end) ? end - p: 0);
+		p += 2;
+	}
+	if (description != NULL) {
+		strncpy(p, description, (p < end) ? end - p: 0);
+		p += strlen(description);
+		if (err_ != 0) {
+			strncpy(p, ": ", (p < end) ? end - p: 0);
+			p += 2;
+		}
+	}
+	if (err_ != 0) {
+		strncpy(p, db_strerror(err_), (p < end) ? end - p: 0);
+		p += strlen(db_strerror(err_));
+	}
+
+	/*
+	 * If the result was too long, the buffer will not be null-terminated,
+	 * so we need to fix that here before duplicating it.
+	 */
+	if (p >= end)
+		*end = '\0';
+
+	what_ = dupString(msgbuf);
+}
+
 int DbException::get_errno() const
 {
 	return (err_);
 }
 
-const char *DbException::what() const
+const char *DbException::what() const throw()
 {
 	return (what_);
 }
 
+DbEnv *DbException::get_env() const
+{
+	return env_;
+}
+
+void DbException::set_env(DbEnv *env)
+{
+	env_= env;
+}
+
 ////////////////////////////////////////////////////////////////////////
 //                                                                    //
 //                            DbMemoryException                       //
@@ -146,7 +146,7 @@ const char *DbException::what() const
 ////////////////////////////////////////////////////////////////////////
 
 static const char *memory_err_desc = "Dbt not large enough for available data";
-DbMemoryException::~DbMemoryException()
+DbMemoryException::~DbMemoryException() throw()
 {
 }
 
@@ -156,25 +156,12 @@ DbMemoryException::DbMemoryException(Dbt *dbt)
 {
 }
 
-DbMemoryException::DbMemoryException(const char *description)
-:	DbException(description, ENOMEM)
-,	dbt_(0)
-{
-}
-
 DbMemoryException::DbMemoryException(const char *prefix, Dbt *dbt)
 :	DbException(prefix, memory_err_desc, ENOMEM)
 ,	dbt_(dbt)
 {
 }
 
-DbMemoryException::DbMemoryException(const char *prefix1, const char *prefix2,
-    Dbt *dbt)
-:	DbException(prefix1, prefix2, ENOMEM)
-,	dbt_(dbt)
-{
-}
-
 DbMemoryException::DbMemoryException(const DbMemoryException &that)
 :	DbException(that)
 ,	dbt_(that.dbt_)
@@ -202,7 +189,7 @@ Dbt *DbMemoryException::get_dbt() const
 //                                                                    //
 ////////////////////////////////////////////////////////////////////////
 
-DbDeadlockException::~DbDeadlockException()
+DbDeadlockException::~DbDeadlockException() throw()
 {
 }
 
@@ -230,7 +217,7 @@ DbDeadlockException
 //                                                                    //
 ////////////////////////////////////////////////////////////////////////
 
-DbLockNotGrantedException::~DbLockNotGrantedException()
+DbLockNotGrantedException::~DbLockNotGrantedException() throw()
 {
 	delete lock_;
 }
@@ -243,9 +230,19 @@ DbLockNotGrantedException::DbLockNotGrantedException(const char *prefix,
 ,	op_(op)
 ,	mode_(mode)
 ,	obj_(obj)
+,	lock_(new DbLock(lock))
 ,	index_(index)
 {
-	lock_ = new DbLock(lock);
+}
+
+DbLockNotGrantedException::DbLockNotGrantedException(const char *description)
+:	DbException(description, DB_LOCK_NOTGRANTED)
+,	op_(DB_LOCK_GET)
+,	mode_(DB_LOCK_NG)
+,	obj_(NULL)
+,	lock_(NULL)
+,	index_(0)
+{
 }
 
 DbLockNotGrantedException::DbLockNotGrantedException
@@ -255,7 +252,7 @@ DbLockNotGrantedException::DbLockNotGrantedException
 	op_ = that.op_;
 	mode_ = that.mode_;
 	obj_ = that.obj_;
-	lock_ = new DbLock(*that.lock_);
+	lock_ = (that.lock_ != NULL) ? new DbLock(*that.lock_) : NULL;
 	index_ = that.index_;
 }
 
@@ -267,7 +264,7 @@ DbLockNotGrantedException
 		op_ = that.op_;
 		mode_ = that.mode_;
 		obj_ = that.obj_;
-		lock_ = new DbLock(*that.lock_);
+		lock_ = (that.lock_ != NULL) ? new DbLock(*that.lock_) : NULL;
 		index_ = that.index_;
 	}
 	return (*this);
@@ -298,15 +295,13 @@ int DbLockNotGrantedException::get_index() const
 	return index_;
 }
 
-
-
 ////////////////////////////////////////////////////////////////////////
 //                                                                    //
 //                            DbRunRecoveryException                  //
 //                                                                    //
 ////////////////////////////////////////////////////////////////////////
 
-DbRunRecoveryException::~DbRunRecoveryException()
+DbRunRecoveryException::~DbRunRecoveryException() throw()
 {
 }
 
diff --git a/storage/bdb/cxx/cxx_lock.cpp b/storage/bdb/cxx/cxx_lock.cpp
index 446eba49e275d565e0b16b7135d75f2f91ceef86..d22cf662be7454fc8de0db326f15f0f14e58e169 100644
--- a/storage/bdb/cxx/cxx_lock.cpp
+++ b/storage/bdb/cxx/cxx_lock.cpp
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: cxx_lock.cpp,v 11.19 2004/01/28 03:35:56 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: cxx_lock.cpp,v 11.17 2002/03/27 04:31:16 bostic Exp $";
-#endif /* not lint */
-
 #include <errno.h>
 #include <string.h>
 
diff --git a/storage/bdb/cxx/cxx_logc.cpp b/storage/bdb/cxx/cxx_logc.cpp
index d1fe83dd58b636402983a3bc6014d2adc8d597fb..c5399b531a8d4c21d5399039bc32b64e3ffb5b2e 100644
--- a/storage/bdb/cxx/cxx_logc.cpp
+++ b/storage/bdb/cxx/cxx_logc.cpp
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: cxx_logc.cpp,v 11.13 2004/02/05 02:25:12 mjc Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: cxx_logc.cpp,v 11.8 2002/07/03 21:03:53 bostic Exp $";
-#endif /* not lint */
-
 #include <errno.h>
 #include <string.h>
 
@@ -37,11 +35,12 @@ int DbLogc::close(u_int32_t _flags)
 {
 	DB_LOGC *logc = this;
 	int ret;
+	DbEnv *dbenv2 = DbEnv::get_DbEnv(logc->dbenv);
 
 	ret = logc->close(logc, _flags);
 
 	if (!DB_RETOK_STD(ret))
-		DB_ERROR("DbLogc::close", ret, ON_ERROR_UNKNOWN);
+		DB_ERROR(dbenv2, "DbLogc::close", ret, ON_ERROR_UNKNOWN);
 
 	return (ret);
 }
@@ -55,10 +54,12 @@ int DbLogc::get(DbLsn *lsn, Dbt *data, u_int32_t _flags)
 	ret = logc->get(logc, lsn, data, _flags);
 
 	if (!DB_RETOK_LGGET(ret)) {
-		if (ret == ENOMEM && DB_OVERFLOWED_DBT(data))
-			DB_ERROR_DBT("DbLogc::get", data, ON_ERROR_UNKNOWN);
+		if (ret == DB_BUFFER_SMALL)
+			DB_ERROR_DBT(DbEnv::get_DbEnv(logc->dbenv),
+				"DbLogc::get", data, ON_ERROR_UNKNOWN);
 		else
-			DB_ERROR("DbLogc::get", ret, ON_ERROR_UNKNOWN);
+			DB_ERROR(DbEnv::get_DbEnv(logc->dbenv),
+				"DbLogc::get", ret, ON_ERROR_UNKNOWN);
 	}
 
 	return (ret);
diff --git a/storage/bdb/cxx/cxx_mpool.cpp b/storage/bdb/cxx/cxx_mpool.cpp
index 3eb78d03ff441df46bc84e2e1568c7eb9ccd0641..54747b0926c2e28f6484a0e643353587b55a9ce4 100644
--- a/storage/bdb/cxx/cxx_mpool.cpp
+++ b/storage/bdb/cxx/cxx_mpool.cpp
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: cxx_mpool.cpp,v 11.28 2004/01/28 03:35:56 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: cxx_mpool.cpp,v 11.20 2002/07/03 21:03:53 bostic Exp $";
-#endif /* not lint */
-
 #include <errno.h>
 
 #include "db_cxx.h"
@@ -35,7 +33,8 @@ int DbMpoolFile::_name _argspec						\
 	else								\
 		ret = mpf->_name _arglist;				\
 	if (!_retok(ret))						\
-		DB_ERROR("DbMpoolFile::"#_name, ret, ON_ERROR_UNKNOWN);	\
+		DB_ERROR(DbEnv::get_DbEnv(mpf->dbenv), \
+			"DbMpoolFile::"#_name, ret, ON_ERROR_UNKNOWN);	\
 	return (ret);							\
 }
 
@@ -66,6 +65,7 @@ int DbMpoolFile::close(u_int32_t flags)
 {
 	DB_MPOOLFILE *mpf = unwrap(this);
 	int ret;
+	DbEnv *dbenv = DbEnv::get_DbEnv(mpf->dbenv);
 
 	if (mpf == NULL)
 		ret = EINVAL;
@@ -79,32 +79,51 @@ int DbMpoolFile::close(u_int32_t flags)
 	delete this;
 
 	if (!DB_RETOK_STD(ret))
-		DB_ERROR("DbMpoolFile::close", ret, ON_ERROR_UNKNOWN);
+		DB_ERROR(dbenv, "DbMpoolFile::close", ret, ON_ERROR_UNKNOWN);
 
 	return (ret);
 }
 
 DB_MPOOLFILE_METHOD(get, (db_pgno_t *pgnoaddr, u_int32_t flags, void *pagep),
     (mpf, pgnoaddr, flags, pagep), DB_RETOK_MPGET)
-DB_MPOOLFILE_METHOD_VOID(last_pgno, (db_pgno_t *pgnoaddr), (mpf, pgnoaddr))
 DB_MPOOLFILE_METHOD(open,
     (const char *file, u_int32_t flags, int mode, size_t pagesize),
     (mpf, file, flags, mode, pagesize), DB_RETOK_STD)
 DB_MPOOLFILE_METHOD(put, (void *pgaddr, u_int32_t flags),
     (mpf, pgaddr, flags), DB_RETOK_STD)
-DB_MPOOLFILE_METHOD_VOID(refcnt, (db_pgno_t *pgnoaddr), (mpf, pgnoaddr))
 DB_MPOOLFILE_METHOD(set, (void *pgaddr, u_int32_t flags),
     (mpf, pgaddr, flags), DB_RETOK_STD)
+DB_MPOOLFILE_METHOD(get_clear_len, (u_int32_t *lenp),
+    (mpf, lenp), DB_RETOK_STD)
 DB_MPOOLFILE_METHOD(set_clear_len, (u_int32_t len),
     (mpf, len), DB_RETOK_STD)
+DB_MPOOLFILE_METHOD(get_fileid, (u_int8_t *fileid),
+    (mpf, fileid), DB_RETOK_STD)
 DB_MPOOLFILE_METHOD(set_fileid, (u_int8_t *fileid),
     (mpf, fileid), DB_RETOK_STD)
+DB_MPOOLFILE_METHOD(get_flags, (u_int32_t *flagsp),
+    (mpf, flagsp), DB_RETOK_STD)
+DB_MPOOLFILE_METHOD(set_flags, (u_int32_t flags, int onoff),
+    (mpf, flags, onoff), DB_RETOK_STD)
+DB_MPOOLFILE_METHOD(get_ftype, (int *ftypep),
+    (mpf, ftypep), DB_RETOK_STD)
 DB_MPOOLFILE_METHOD(set_ftype, (int ftype),
     (mpf, ftype), DB_RETOK_STD)
+DB_MPOOLFILE_METHOD(get_lsn_offset, (int32_t *offsetp),
+    (mpf, offsetp), DB_RETOK_STD)
 DB_MPOOLFILE_METHOD(set_lsn_offset, (int32_t offset),
     (mpf, offset), DB_RETOK_STD)
+DB_MPOOLFILE_METHOD(get_maxsize, (u_int32_t *gbytesp, u_int32_t *bytesp),
+    (mpf, gbytesp, bytesp), DB_RETOK_STD)
+DB_MPOOLFILE_METHOD(set_maxsize, (u_int32_t gbytes, u_int32_t bytes),
+    (mpf, gbytes, bytes), DB_RETOK_STD)
+DB_MPOOLFILE_METHOD(get_pgcookie, (DBT *dbt),
+    (mpf, dbt), DB_RETOK_STD)
 DB_MPOOLFILE_METHOD(set_pgcookie, (DBT *dbt),
     (mpf, dbt), DB_RETOK_STD)
-DB_MPOOLFILE_METHOD_VOID(set_unlink, (int ul), (mpf, ul))
+DB_MPOOLFILE_METHOD(get_priority, (DB_CACHE_PRIORITY *priorityp),
+    (mpf, priorityp), DB_RETOK_STD)
+DB_MPOOLFILE_METHOD(set_priority, (DB_CACHE_PRIORITY priority),
+    (mpf, priority), DB_RETOK_STD)
 DB_MPOOLFILE_METHOD(sync, (),
     (mpf), DB_RETOK_STD)
diff --git a/storage/bdb/cxx/cxx_multi.cpp b/storage/bdb/cxx/cxx_multi.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0961f2921b08b9a7ca885681abe43377edd37faf
--- /dev/null
+++ b/storage/bdb/cxx/cxx_multi.cpp
@@ -0,0 +1,65 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: cxx_multi.cpp,v 1.4 2004/01/28 03:35:56 bostic Exp $
+ */
+
+#include "db_config.h"
+
+#include "db_cxx.h"
+
+DbMultipleIterator::DbMultipleIterator(const Dbt &dbt)
+ : data_((u_int8_t*)dbt.get_data()),
+   p_((u_int32_t*)(data_ + dbt.get_size() - sizeof(u_int32_t)))
+{
+}
+
+bool DbMultipleDataIterator::next(Dbt &data)
+{
+	if (*p_ == (u_int32_t)-1) {
+		data.set_data(0);
+		data.set_size(0);
+		p_ = 0;
+	} else {
+		data.set_data(data_ + *p_--);
+		data.set_size(*p_--);
+		if (data.get_size() == 0 && data.get_data() == data_)
+			data.set_data(0);
+	}
+	return (data.get_data() != 0);
+}
+
+bool DbMultipleKeyDataIterator::next(Dbt &key, Dbt &data)
+{
+	if (*p_ == (u_int32_t)-1) {
+		key.set_data(0);
+		key.set_size(0);
+		data.set_data(0);
+		data.set_size(0);
+		p_ = 0;
+	} else {
+		key.set_data(data_ + *p_--);
+		key.set_size(*p_--);
+		data.set_data(data_ + *p_--);
+		data.set_size(*p_--);
+	}
+	return (data.get_data() != 0);
+}
+
+bool DbMultipleRecnoDataIterator::next(db_recno_t &recno, Dbt &data)
+{
+	if (*p_ == (u_int32_t)0) {
+		recno = 0;
+		data.set_data(0);
+		data.set_size(0);
+		p_ = 0;
+	} else {
+		recno = *p_--;
+		data.set_data(data_ + *p_--);
+		data.set_size(*p_--);
+	}
+	return (recno != 0);
+}
diff --git a/storage/bdb/cxx/cxx_seq.cpp b/storage/bdb/cxx/cxx_seq.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..60bc7455b36bb55862a5d5eedac7e8fbeec768ac
--- /dev/null
+++ b/storage/bdb/cxx/cxx_seq.cpp
@@ -0,0 +1,113 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: cxx_seq.cpp,v 11.3 2004/09/23 20:05:08 mjc Exp $
+ */
+
+#include "db_config.h"
+
+#include <errno.h>
+#include <string.h>
+
+#include "db_cxx.h"
+#include "dbinc/cxx_int.h"
+
+#include "db_int.h"
+
+// Helper macro for simple methods that pass through to the
+// underlying C method. It may return an error or raise an exception.
+// Note this macro expects that input _argspec is an argument
+// list element (e.g., "char *arg") and that _arglist is the arguments
+// that should be passed through to the C method (e.g., "(db, arg)")
+//
+#define	DBSEQ_METHOD(_name, _argspec, _arglist, _destructor)		\
+int DbSequence::_name _argspec						\
+{									\
+	int ret;							\
+	DB_SEQUENCE *seq = unwrap(this);				\
+	DbEnv *dbenv = DbEnv::get_DbEnv(seq->seq_dbp->dbenv);		\
+									\
+	ret = seq->_name _arglist;					\
+	if (_destructor)						\
+		imp_ = 0;						\
+	if (!DB_RETOK_STD(ret))						\
+		DB_ERROR(dbenv,						\
+		    "DbSequence::" # _name, ret, ON_ERROR_UNKNOWN);	\
+	return (ret);							\
+}
+
+DbSequence::DbSequence(Db *db, u_int32_t flags)
+:	imp_(0)
+{
+	DB_SEQUENCE *seq;
+	int ret;
+
+	if ((ret = db_sequence_create(&seq, unwrap(db), flags)) != 0)
+		DB_ERROR(db->get_env(), "DbSequence::DbSequence", ret,
+		    ON_ERROR_UNKNOWN);
+	else {
+		imp_ = seq;
+		seq->api_internal = this;
+	}
+}
+
+DbSequence::DbSequence(DB_SEQUENCE *seq)
+:	imp_(seq)
+{
+	seq->api_internal = this;
+}
+
+DbSequence::~DbSequence()
+{
+	DB_SEQUENCE *seq;
+
+	seq = unwrap(this);
+	if (seq != NULL)
+		(void)seq->close(seq, 0);
+}
+
+DBSEQ_METHOD(open, (DbTxn *txnid, Dbt *key, u_int32_t flags),
+    (seq, unwrap(txnid), key, flags), 0)
+DBSEQ_METHOD(initial_value, (db_seq_t value), (seq, value), 0)
+DBSEQ_METHOD(close, (u_int32_t flags), (seq, flags), 1)
+DBSEQ_METHOD(remove, (DbTxn *txnid, u_int32_t flags),
+    (seq, unwrap(txnid), flags), 1)
+DBSEQ_METHOD(stat, (DB_SEQUENCE_STAT **sp, u_int32_t flags),
+    (seq, sp, flags), 0)
+DBSEQ_METHOD(stat_print, (u_int32_t flags), (seq, flags), 0)
+
+DBSEQ_METHOD(get,
+    (DbTxn  *txnid, int32_t delta, db_seq_t *retp, u_int32_t flags),
+    (seq, unwrap(txnid), delta, retp, flags), 0)
+DBSEQ_METHOD(get_cachesize, (int32_t *sizep), (seq, sizep), 0)
+DBSEQ_METHOD(set_cachesize, (int32_t size), (seq, size), 0)
+DBSEQ_METHOD(get_flags, (u_int32_t *flagsp), (seq, flagsp), 0)
+DBSEQ_METHOD(set_flags, (u_int32_t flags), (seq, flags), 0)
+DBSEQ_METHOD(get_range, (db_seq_t *minp, db_seq_t *maxp), (seq, minp, maxp), 0)
+DBSEQ_METHOD(set_range, (db_seq_t min, db_seq_t max), (seq, min, max), 0)
+
+Db *DbSequence::get_db()
+{       
+	DB_SEQUENCE *seq = unwrap(this);
+	DB *db;
+	(void)seq->get_db(seq, &db);
+	return Db::get_Db(db);
+}   
+
+Dbt *DbSequence::get_key()
+{       
+	DB_SEQUENCE *seq = unwrap(this);
+	memset(&key_, 0, sizeof (DBT));
+	(void)seq->get_key(seq, &key_);
+	return Dbt::get_Dbt(&key_);
+}   
+
+// static method
+DbSequence *DbSequence::wrap_DB_SEQUENCE(DB_SEQUENCE *seq)
+{
+	DbSequence *wrapped_seq = get_DbSequence(seq);
+	return (wrapped_seq != NULL) ? wrapped_seq : new DbSequence(seq);
+}
diff --git a/storage/bdb/cxx/cxx_txn.cpp b/storage/bdb/cxx/cxx_txn.cpp
index b04077c0f5b80247a966b0f71d16c7723873535a..89ad7f02b4f52a326ac7b446799796f692db5ac2 100644
--- a/storage/bdb/cxx/cxx_txn.cpp
+++ b/storage/bdb/cxx/cxx_txn.cpp
@@ -1,22 +1,21 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: cxx_txn.cpp,v 11.33 2004/09/22 22:20:31 mjc Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: cxx_txn.cpp,v 11.27 2002/07/20 13:50:11 dda Exp $";
-#endif /* not lint */
-
 #include <errno.h>
 
 #include "db_cxx.h"
 #include "dbinc/cxx_int.h"
 
 #include "db_int.h"
+#include "dbinc/txn.h"
 
 // Helper macro for simple methods that pass through to the
 // underlying C method. It may return an error or raise an exception.
@@ -24,19 +23,20 @@ static const char revid[] = "$Id: cxx_txn.cpp,v 11.27 2002/07/20 13:50:11 dda Ex
 // list element (e.g., "char *arg") and that _arglist is the arguments
 // that should be passed through to the C method (e.g., "(db, arg)")
 //
-#define	DBTXN_METHOD(_name, _delete, _argspec, _arglist)		\
-int DbTxn::_name _argspec						\
-{									\
-	int ret;							\
-	DB_TXN *txn = unwrap(this);					\
-									\
-	ret = txn->_name _arglist;					\
-	/* Weird, but safe if we don't access this again. */		\
-	if (_delete)							\
-		delete this;						\
-	if (!DB_RETOK_STD(ret))						\
-		DB_ERROR("DbTxn::" # _name, ret, ON_ERROR_UNKNOWN);	\
-	return (ret);							\
+#define	DBTXN_METHOD(_name, _delete, _argspec, _arglist)		   \
+int DbTxn::_name _argspec						   \
+{									   \
+	int ret;							   \
+	DB_TXN *txn = unwrap(this);					   \
+	DbEnv *dbenv = DbEnv::get_DbEnv(txn->mgrp->dbenv);		   \
+									   \
+	ret = txn->_name _arglist;					   \
+	/* Weird, but safe if we don't access this again. */		   \
+	if (_delete)							   \
+		delete this;						   \
+	if (!DB_RETOK_STD(ret))						   \
+		DB_ERROR(dbenv, "DbTxn::" # _name, ret, ON_ERROR_UNKNOWN); \
+	return (ret);							   \
 }
 
 // private constructor, never called but needed by some C++ linkers
@@ -46,7 +46,7 @@ DbTxn::DbTxn()
 }
 
 DbTxn::DbTxn(DB_TXN *txn)
-:	imp_(wrap(txn))
+:	imp_(txn)
 {
 	txn->api_internal = this;
 }
@@ -75,7 +75,5 @@ DBTXN_METHOD(set_timeout, 0, (db_timeout_t timeout, u_int32_t flags),
 DbTxn *DbTxn::wrap_DB_TXN(DB_TXN *txn)
 {
 	DbTxn *wrapped_txn = get_DbTxn(txn);
-	if (wrapped_txn == NULL)
-		wrapped_txn = new DbTxn(txn);
-	return wrapped_txn;
+	return (wrapped_txn != NULL) ?  wrapped_txn : new DbTxn(txn);
 }
diff --git a/storage/bdb/db/crdel.src b/storage/bdb/db/crdel.src
index d89fa7a0382fc4a99fff0eca680509f32b67e305..034e7b82f578892e2b11bbf66673783b519052db 100644
--- a/storage/bdb/db/crdel.src
+++ b/storage/bdb/db/crdel.src
@@ -1,17 +1,15 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: crdel.src,v 11.24 2002/04/17 19:02:57 krinsky Exp $
+ * $Id: crdel.src,v 11.29 2004/06/17 17:35:15 bostic Exp $
  */
 
 PREFIX	__crdel
 DBPRIVATE
 
-INCLUDE	#include "db_config.h"
-INCLUDE
 INCLUDE #ifndef NO_SYSTEM_INCLUDES
 INCLUDE #include <sys/types.h>
 INCLUDE
@@ -25,7 +23,6 @@ INCLUDE #include "dbinc/db_page.h"
 INCLUDE #include "dbinc/db_dispatch.h"
 INCLUDE #include "dbinc/db_am.h"
 INCLUDE #include "dbinc/log.h"
-INCLUDE #include "dbinc/rep.h"
 INCLUDE #include "dbinc/txn.h"
 INCLUDE
 
@@ -39,7 +36,7 @@ INCLUDE
  */
 BEGIN metasub		142
 DB	fileid		int32_t		ld
-WRLOCK	pgno		db_pgno_t	lu
+ARG	pgno		db_pgno_t	lu
 PGDBT	page		DBT		s
 POINTER	lsn		DB_LSN *	lu
 END
diff --git a/storage/bdb/db/crdel_rec.c b/storage/bdb/db/crdel_rec.c
index 542a0c358ddd16e279b66c5a05ee21e97342bba5..7ff4fbd06e9a2f8f9899fe16626cc133c66d0f1e 100644
--- a/storage/bdb/db/crdel_rec.c
+++ b/storage/bdb/db/crdel_rec.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: crdel_rec.c,v 11.68 2004/04/29 00:07:55 ubell Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: crdel_rec.c,v 11.64 2002/08/14 20:27:34 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -19,8 +17,10 @@ static const char revid[] = "$Id: crdel_rec.c,v 11.64 2002/08/14 20:27:34 bostic
 
 #include "db_int.h"
 #include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
 #include "dbinc/hash.h"
 #include "dbinc/log.h"
+#include "dbinc/mp.h"
 
 /*
  * __crdel_metasub_recover --
@@ -49,16 +49,10 @@ __crdel_metasub_recover(dbenv, dbtp, lsnp, op, info)
 	REC_PRINT(__crdel_metasub_print);
 	REC_INTRO(__crdel_metasub_read, 0);
 
-	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
-		if (DB_REDO(op)) {
-			if ((ret = mpf->get(mpf,
-			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
-				goto out;
-		} else {
-			*lsnp = argp->prev_lsn;
-			ret = 0;
-			goto out;
-		}
+	if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
+		*lsnp = argp->prev_lsn;
+		ret = 0;
+		goto out;
 	}
 
 	modified = 0;
@@ -84,7 +78,7 @@ __crdel_metasub_recover(dbenv, dbtp, lsnp, op, info)
 		LSN(pagep) = argp->lsn;
 		modified = 1;
 	}
-	if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+	if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
 		goto out;
 	pagep = NULL;
 
@@ -92,6 +86,6 @@ done:	*lsnp = argp->prev_lsn;
 	ret = 0;
 
 out:	if (pagep != NULL)
-		(void)mpf->put(mpf, pagep, 0);
+		(void)__memp_fput(mpf, pagep, 0);
 	REC_CLOSE;
 }
diff --git a/storage/bdb/db/db.c b/storage/bdb/db/db.c
index 986167d5adec9bd0dd9ee7e5314f92397781566c..28aecc09cffde2b44d4b45231f211e13d22343a1 100644
--- a/storage/bdb/db/db.c
+++ b/storage/bdb/db/db.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -35,19 +35,15 @@
  * 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.
+ *
+ * $Id: db.c,v 11.300 2004/10/26 17:38:41 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db.c,v 11.246 2002/08/20 14:40:00 margo Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
-#include <stddef.h>
-#include <stdlib.h>
 #include <string.h>
 #endif
 
@@ -59,14 +55,14 @@ static const char revid[] = "$Id: db.c,v 11.246 2002/08/20 14:40:00 margo Exp $"
 #include "dbinc/hash.h"
 #include "dbinc/lock.h"
 #include "dbinc/log.h"
-#include "dbinc/log.h"
 #include "dbinc/mp.h"
 #include "dbinc/qam.h"
 #include "dbinc/txn.h"
 
 static int __db_disassociate __P((DB *));
-#if CONFIG_TEST
-static void __db_makecopy __P((const char *, const char *));
+
+#ifdef CONFIG_TEST
+static void __db_makecopy __P((DB_ENV *, const char *, const char *));
 static int  __db_testdocopy __P((DB_ENV *, const char *));
 static int  __qam_testdocopy __P((DB *, const char *));
 #endif
@@ -95,6 +91,8 @@ __db_master_open(subdbp, txn, name, flags, mode, dbpp)
 	DB *dbp;
 	int ret;
 
+	*dbpp = NULL;
+
 	/* Open up a handle on the main database. */
 	if ((ret = db_create(&dbp, subdbp->dbenv, 0)) != 0)
 		return (ret);
@@ -105,11 +103,11 @@ __db_master_open(subdbp, txn, name, flags, mode, dbpp)
 	 * Set the pagesize in case we're creating a new database.
 	 * Flag that we're creating a database with subdatabases.
 	 */
-	dbp->type = DB_BTREE;
 	dbp->pgsize = subdbp->pgsize;
 	F_SET(dbp, DB_AM_SUBDB);
 	F_SET(dbp, F_ISSET(subdbp,
-	    DB_AM_RECOVER | DB_AM_SWAP | DB_AM_ENCRYPT | DB_AM_CHKSUM));
+	    DB_AM_RECOVER | DB_AM_SWAP |
+	    DB_AM_ENCRYPT | DB_AM_CHKSUM | DB_AM_NOT_DURABLE));
 
 	/*
 	 * If there was a subdb specified, then we only want to apply
@@ -118,20 +116,18 @@ __db_master_open(subdbp, txn, name, flags, mode, dbpp)
 	 */
 	LF_CLR(DB_EXCL);
 	LF_SET(DB_RDWRMASTER);
-	if ((ret = __db_dbopen(dbp, txn, name, NULL, flags, mode, PGNO_BASE_MD))
-	    != 0)
+	if ((ret = __db_open(dbp,
+	    txn, name, NULL, DB_BTREE, flags, mode, PGNO_BASE_MD)) != 0)
 		goto err;
 
 	/*
-	 * Verify that pagesize is the same on both.
-	 * The items in dbp were now initialized from the meta
-	 * page.  The items in dbp were set in __db_dbopen
-	 * when we either read or created the master file.
-	 * Other items such as checksum and encryption are
-	 * checked when we read the meta-page.  So we do not
-	 * check those here.  However, if the meta-page caused
-	 * chksumming to be turned on and it wasn't already, set
-	 * it here.
+	 * Verify that pagesize is the same on both.  The items in dbp were now
+	 * initialized from the meta page.  The items in dbp were set in
+	 * __db_dbopen when we either read or created the master file.  Other
+	 * items such as checksum and encryption are checked when we read the
+	 * meta-page.  So we do not check those here.  However, if the
+	 * meta-page caused checksumming to be turned on and it wasn't already,
+	 * set it here.
 	 */
 	if (F_ISSET(dbp, DB_AM_CHKSUM))
 		F_SET(subdbp, DB_AM_CHKSUM);
@@ -143,7 +139,7 @@ __db_master_open(subdbp, txn, name, flags, mode, dbpp)
 	}
 err:
 	if (ret != 0 && !F_ISSET(dbp, DB_AM_DISCARD))
-		__db_close_i(dbp, txn, 0);
+		(void)__db_close(dbp, txn, 0);
 	else
 		*dbpp = dbp;
 	return (ret);
@@ -169,7 +165,7 @@ __db_master_update(mdbp, sdbp, txn, subdb, type, action, newname, flags)
 	DB_ENV *dbenv;
 	DBC *dbc, *ndbc;
 	DBT key, data, ndata;
-	PAGE *p;
+	PAGE *p, *r;
 	db_pgno_t t_pgno;
 	int modify, ret, t_ret;
 
@@ -187,7 +183,7 @@ __db_master_update(mdbp, sdbp, txn, subdb, type, action, newname, flags)
 	 * Open up a cursor.  If this is CDB and we're creating the database,
 	 * make it an update cursor.
 	 */
-	if ((ret = mdbp->cursor(mdbp, txn, &dbc,
+	if ((ret = __db_cursor(mdbp, txn, &dbc,
 	    (CDB_LOCKING(dbenv) && modify) ? DB_WRITECURSOR : 0)) != 0)
 		goto err;
 
@@ -208,7 +204,7 @@ __db_master_update(mdbp, sdbp, txn, subdb, type, action, newname, flags)
 	key.size = (u_int32_t)strlen(subdb);
 	F_SET(&data, DB_DBT_MALLOC);
 
-	ret = dbc->c_get(dbc, &key, &data,
+	ret = __db_c_get(dbc, &key, &data,
 	    DB_SET | ((STD_LOCKING(dbc) && modify) ? DB_RMW : 0));
 
 	/*
@@ -231,7 +227,7 @@ __db_master_update(mdbp, sdbp, txn, subdb, type, action, newname, flags)
 		 * Delete the subdatabase entry first;  if this fails,
 		 * we don't want to touch the actual subdb pages.
 		 */
-		if ((ret = dbc->c_del(dbc, 0)) != 0)
+		if ((ret = __db_c_del(dbc, 0)) != 0)
 			goto err;
 
 		/*
@@ -242,9 +238,21 @@ __db_master_update(mdbp, sdbp, txn, subdb, type, action, newname, flags)
 		memcpy(&sdbp->meta_pgno, data.data, sizeof(db_pgno_t));
 		DB_NTOHL(&sdbp->meta_pgno);
 		if ((ret =
-		    mdbp->mpf->get(mdbp->mpf, &sdbp->meta_pgno, 0, &p)) != 0)
+		    __memp_fget(mdbp->mpf, &sdbp->meta_pgno, 0, &p)) != 0)
 			goto err;
 
+		/* Free the root on the master db. */
+		if (TYPE(p) == P_BTREEMETA) {
+			if ((ret = __memp_fget(mdbp->mpf,
+			     &((BTMETA *)p)->root, 0, &r)) != 0)
+				goto err;
+
+			/* Free and put the page. */
+			if ((ret = __db_free(dbc, r)) != 0) {
+				r = NULL;
+				goto err;
+			}
+		}
 		/* Free and put the page. */
 		if ((ret = __db_free(dbc, p)) != 0) {
 			p = NULL;
@@ -264,9 +272,8 @@ __db_master_update(mdbp, sdbp, txn, subdb, type, action, newname, flags)
 		 * for the existence of newname;  it shouldn't appear under
 		 * us since we hold the metadata lock.
 		 */
-		if ((ret = mdbp->cursor(mdbp, txn, &ndbc, 0)) != 0)
+		if ((ret = __db_cursor(mdbp, txn, &ndbc, 0)) != 0)
 			goto err;
-		DB_ASSERT(newname != NULL);
 		key.data = (void *)newname;
 		key.size = (u_int32_t)strlen(newname);
 
@@ -277,7 +284,7 @@ __db_master_update(mdbp, sdbp, txn, subdb, type, action, newname, flags)
 		memset(&ndata, 0, sizeof(ndata));
 		F_SET(&ndata, DB_DBT_USERMEM | DB_DBT_PARTIAL);
 
-		if ((ret = ndbc->c_get(ndbc, &key, &ndata, DB_SET)) == 0) {
+		if ((ret = __db_c_get(ndbc, &key, &ndata, DB_SET)) == 0) {
 			/* A subdb called newname exists.  Bail. */
 			ret = EEXIST;
 			__db_err(dbenv, "rename: database %s exists", newname);
@@ -290,14 +297,14 @@ __db_master_update(mdbp, sdbp, txn, subdb, type, action, newname, flags)
 		 * sole reference to the subdb.  Use the second cursor
 		 * so that the first one continues to point to the old record.
 		 */
-		if ((ret = ndbc->c_put(ndbc, &key, &data, DB_KEYFIRST)) != 0)
+		if ((ret = __db_c_put(ndbc, &key, &data, DB_KEYFIRST)) != 0)
 			goto err;
-		if ((ret = dbc->c_del(dbc, 0)) != 0) {
+		if ((ret = __db_c_del(dbc, 0)) != 0) {
 			/*
 			 * If the delete fails, try to delete the record
 			 * we just put, in case we're not txn-protected.
 			 */
-			(void)ndbc->c_del(ndbc, 0);
+			(void)__db_c_del(ndbc, 0);
 			goto err;
 		}
 
@@ -329,17 +336,6 @@ __db_master_update(mdbp, sdbp, txn, subdb, type, action, newname, flags)
 			goto err;
 		}
 
-		/*
-		 * We need to check against the master lorder here because
-		 * we only want to check this if we are creating.  In the
-		 * case where we don't create we just want to inherit.
-		 */
-		if (F_ISSET(mdbp, DB_AM_SWAP) != F_ISSET(sdbp, DB_AM_SWAP)) {
-			 ret = EINVAL;
-			 __db_err(mdbp->dbenv,
-			    "Different lorder specified on existent file");
-			goto err;
-		}
 		/* Create a subdatabase. */
 		if ((ret = __db_new(dbc,
 		    type == DB_HASH ? P_HASHMETA : P_BTREEMETA, &p)) != 0)
@@ -357,7 +353,7 @@ __db_master_update(mdbp, sdbp, txn, subdb, type, action, newname, flags)
 		memset(&ndata, 0, sizeof(ndata));
 		ndata.data = &t_pgno;
 		ndata.size = sizeof(db_pgno_t);
-		if ((ret = dbc->c_put(dbc, &key, &ndata, DB_KEYLAST)) != 0)
+		if ((ret = __db_c_put(dbc, &key, &ndata, DB_KEYLAST)) != 0)
 			goto err;
 		F_SET(sdbp, DB_AM_CREATED);
 		break;
@@ -371,26 +367,18 @@ done:	/*
 	if (p != NULL) {
 		if (ret == 0) {
 			if ((t_ret =
-			    mdbp->mpf->put(mdbp->mpf, p, DB_MPOOL_DIRTY)) != 0)
-				ret = t_ret;
-			/*
-			 * Since we cannot close this file until after
-			 * transaction commit, we need to sync the dirty
-			 * pages, because we'll read these directly from
-			 * disk to open.
-			 */
-			if ((t_ret = mdbp->sync(mdbp, 0)) != 0 && ret == 0)
+			    __memp_fput(mdbp->mpf, p, DB_MPOOL_DIRTY)) != 0)
 				ret = t_ret;
 		} else
-			(void)mdbp->mpf->put(mdbp->mpf, p, 0);
+			(void)__memp_fput(mdbp->mpf, p, 0);
 	}
 
 	/* Discard the cursor(s) and data. */
 	if (data.data != NULL)
 		__os_ufree(dbenv, data.data);
-	if (dbc != NULL && (t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
+	if (dbc != NULL && (t_ret = __db_c_close(dbc)) != 0 && ret == 0)
 		ret = t_ret;
-	if (ndbc != NULL && (t_ret = ndbc->c_close(ndbc)) != 0 && ret == 0)
+	if (ndbc != NULL && (t_ret = __db_c_close(ndbc)) != 0 && ret == 0)
 		ret = t_ret;
 
 	return (ret);
@@ -404,21 +392,17 @@ done:	/*
  * PUBLIC:     DB_TXN *, const char *, u_int32_t, u_int32_t));
  */
 int
-__db_dbenv_setup(dbp, txn, name, id, flags)
+__db_dbenv_setup(dbp, txn, fname, id, flags)
 	DB *dbp;
 	DB_TXN *txn;
-	const char *name;
-	u_int32_t id;
-	u_int32_t flags;
+	const char *fname;
+	u_int32_t id, flags;
 {
 	DB *ldbp;
-	DBT pgcookie;
 	DB_ENV *dbenv;
 	DB_MPOOL *dbmp;
-	DB_MPOOLFILE *mpf;
-	DB_PGINFO pginfo;
 	u_int32_t maxid;
-	int ftype, ret;
+	int ret;
 
 	dbenv = dbp->dbenv;
 
@@ -427,100 +411,17 @@ __db_dbenv_setup(dbp, txn, name, id, flags)
 		/* Make sure we have at least DB_MINCACHE pages in our cache. */
 		if (dbenv->mp_gbytes == 0 &&
 		    dbenv->mp_bytes < dbp->pgsize * DB_MINPAGECACHE &&
-		    (ret = dbenv->set_cachesize(
+		    (ret = __memp_set_cachesize(
 		    dbenv, 0, dbp->pgsize * DB_MINPAGECACHE, 0)) != 0)
 			return (ret);
 
-		if ((ret = dbenv->open(dbenv, NULL, DB_CREATE |
+		if ((ret = __dbenv_open(dbenv, NULL, DB_CREATE |
 		    DB_INIT_MPOOL | DB_PRIVATE | LF_ISSET(DB_THREAD), 0)) != 0)
 			return (ret);
 	}
 
-	/* Register DB's pgin/pgout functions. */
-	if ((ret = dbenv->memp_register(
-	    dbenv, DB_FTYPE_SET, __db_pgin, __db_pgout)) != 0)
-		return (ret);
-
-	/* Create the DB_MPOOLFILE structure. */
-	if ((ret = dbenv->memp_fcreate(dbenv, &dbp->mpf, 0)) != 0)
-		return (ret);
-	mpf = dbp->mpf;
-
-	/* Set the database's cache priority if we've been given one. */
-	if (dbp->priority != 0 &&
-	    (ret = mpf->set_priority(mpf, dbp->priority)) != 0)
-		return (ret);
-
-	/*
-	 * Open a backing file in the memory pool.
-	 *
-	 * If we need to pre- or post-process a file's pages on I/O, set the
-	 * file type.  If it's a hash file, always call the pgin and pgout
-	 * routines.  This means that hash files can never be mapped into
-	 * process memory.  If it's a btree file and requires swapping, we
-	 * need to page the file in and out.  This has to be right -- we can't
-	 * mmap files that are being paged in and out.
-	 */
-	switch (dbp->type) {
-	case DB_BTREE:
-	case DB_RECNO:
-		ftype = F_ISSET(dbp, DB_AM_SWAP | DB_AM_ENCRYPT | DB_AM_CHKSUM)
-		    ? DB_FTYPE_SET : DB_FTYPE_NOTSET;
-		(void)mpf->set_ftype(mpf, ftype);
-		(void)mpf->set_clear_len(mpf, (CRYPTO_ON(dbenv) ?
-		    dbp->pgsize : DB_PAGE_DB_LEN));
-		break;
-	case DB_HASH:
-		(void)mpf->set_ftype(mpf, DB_FTYPE_SET);
-		(void)mpf->set_clear_len(mpf, (CRYPTO_ON(dbenv) ?
-		    dbp->pgsize : DB_PAGE_DB_LEN));
-		break;
-	case DB_QUEUE:
-		ftype = F_ISSET(dbp, DB_AM_SWAP | DB_AM_ENCRYPT | DB_AM_CHKSUM)
-		    ? DB_FTYPE_SET : DB_FTYPE_NOTSET;
-		(void)mpf->set_ftype(mpf, ftype);
-		(void)mpf->set_clear_len(mpf, (CRYPTO_ON(dbenv) ?
-		    dbp->pgsize : DB_PAGE_QUEUE_LEN));
-		break;
-	case DB_UNKNOWN:
-		/*
-		 * If we're running in the verifier, our database might
-		 * be corrupt and we might not know its type--but we may
-		 * still want to be able to verify and salvage.
-		 *
-		 * If we can't identify the type, it's not going to be safe
-		 * to call __db_pgin--we pretty much have to give up all
-		 * hope of salvaging cross-endianness.  Proceed anyway;
-		 * at worst, the database will just appear more corrupt
-		 * than it actually is, but at best, we may be able
-		 * to salvage some data even with no metadata page.
-		 */
-		if (F_ISSET(dbp, DB_AM_VERIFYING)) {
-			(void)mpf->set_ftype(mpf, DB_FTYPE_NOTSET);
-			(void)mpf->set_clear_len(mpf, DB_PAGE_DB_LEN);
-			break;
-		}
-		/* FALLTHROUGH */
-	default:
-		return (
-		    __db_unknown_type(dbenv, "__db_dbenv_setup", dbp->type));
-	}
-
-	(void)mpf->set_fileid(mpf, dbp->fileid);
-	(void)mpf->set_lsn_offset(mpf, 0);
-
-	pginfo.db_pagesize = dbp->pgsize;
-	pginfo.flags =
-	    F_ISSET(dbp, (DB_AM_CHKSUM | DB_AM_ENCRYPT | DB_AM_SWAP));
-	pginfo.type = dbp->type;
-	pgcookie.data = &pginfo;
-	pgcookie.size = sizeof(DB_PGINFO);
-	(void)mpf->set_pgcookie(mpf, &pgcookie);
-
-	if ((ret = mpf->open(mpf, name,
-	    LF_ISSET(DB_RDONLY | DB_NOMMAP | DB_ODDFILESIZE | DB_TRUNCATE) |
-	    (F_ISSET(dbenv, DB_ENV_DIRECT_DB) ? DB_DIRECT : 0),
-	    0, dbp->pgsize)) != 0)
+	/* Join the underlying cache. */
+	if ((ret = __db_dbenv_mpool(dbp, fname, flags)) != 0)
 		return (ret);
 
 	/*
@@ -541,7 +442,7 @@ __db_dbenv_setup(dbp, txn, name, id, flags)
 	 * still need an FNAME struct, so LOGGING_ON is the correct macro.
 	 */
 	if (LOGGING_ON(dbenv) &&
-	    (ret = __dbreg_setup(dbp, name, id)) != 0)
+	    (ret = __dbreg_setup(dbp, fname, id)) != 0)
 		return (ret);
 
 	/*
@@ -566,8 +467,8 @@ __db_dbenv_setup(dbp, txn, name, id, flags)
 	 */
 	MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
 	for (maxid = 0, ldbp = LIST_FIRST(&dbenv->dblist);
-	    ldbp != NULL; ldbp = LIST_NEXT(dbp, dblistlinks)) {
-		if (name != NULL &&
+	    ldbp != NULL; ldbp = LIST_NEXT(ldbp, dblistlinks)) {
+		if (fname != NULL &&
 		    memcmp(ldbp->fileid, dbp->fileid, DB_FILE_ID_LEN) == 0 &&
 		    ldbp->meta_pgno == dbp->meta_pgno)
 			break;
@@ -577,7 +478,7 @@ __db_dbenv_setup(dbp, txn, name, id, flags)
 
 	/*
 	 * If ldbp is NULL, we didn't find a match, or we weren't
-	 * really looking because name is NULL.  Assign the dbp an
+	 * really looking because fname is NULL.  Assign the dbp an
 	 * adj_fileid one higher than the largest we found, and
 	 * insert it at the head of the master dbp list.
 	 *
@@ -598,46 +499,119 @@ __db_dbenv_setup(dbp, txn, name, id, flags)
 }
 
 /*
- * __db_close --
- *	DB destructor.
+ * __db_dbenv_mpool --
+ *	Set up the underlying environment cache during a db_open.
  *
- * PUBLIC: int __db_close __P((DB *, u_int32_t));
+ * PUBLIC: int __db_dbenv_mpool __P((DB *, const char *, u_int32_t));
  */
 int
-__db_close(dbp, flags)
+__db_dbenv_mpool(dbp, fname, flags)
 	DB *dbp;
+	const char *fname;
 	u_int32_t flags;
 {
 	DB_ENV *dbenv;
+	DBT pgcookie;
+	DB_MPOOLFILE *mpf;
+	DB_PGINFO pginfo;
+	u_int32_t clear_len;
+	int ftype, ret;
+
+	COMPQUIET(mpf, NULL);
 
 	dbenv = dbp->dbenv;
 
-	PANIC_CHECK(dbenv);
+	/*
+	 * If we need to pre- or post-process a file's pages on I/O, set the
+	 * file type.  If it's a hash file, always call the pgin and pgout
+	 * routines.  This means that hash files can never be mapped into
+	 * process memory.  If it's a btree file and requires swapping, we
+	 * need to page the file in and out.  This has to be right -- we can't
+	 * mmap files that are being paged in and out.
+	 */
+	switch (dbp->type) {
+	case DB_BTREE:
+	case DB_RECNO:
+		ftype = F_ISSET(dbp, DB_AM_SWAP | DB_AM_ENCRYPT | DB_AM_CHKSUM)
+		    ? DB_FTYPE_SET : DB_FTYPE_NOTSET;
+		clear_len = CRYPTO_ON(dbenv) ? dbp->pgsize : DB_PAGE_DB_LEN;
+		break;
+	case DB_HASH:
+		ftype = DB_FTYPE_SET;
+		clear_len = CRYPTO_ON(dbenv) ? dbp->pgsize : DB_PAGE_DB_LEN;
+		break;
+	case DB_QUEUE:
+		ftype = F_ISSET(dbp,
+		    DB_AM_SWAP | DB_AM_ENCRYPT | DB_AM_CHKSUM) ?
+		    DB_FTYPE_SET : DB_FTYPE_NOTSET;
+		clear_len = CRYPTO_ON(dbenv) ? dbp->pgsize : DB_PAGE_QUEUE_LEN;
+		break;
+	case DB_UNKNOWN:
+		/*
+		 * If we're running in the verifier, our database might
+		 * be corrupt and we might not know its type--but we may
+		 * still want to be able to verify and salvage.
+		 *
+		 * If we can't identify the type, it's not going to be safe
+		 * to call __db_pgin--we pretty much have to give up all
+		 * hope of salvaging cross-endianness.  Proceed anyway;
+		 * at worst, the database will just appear more corrupt
+		 * than it actually is, but at best, we may be able
+		 * to salvage some data even with no metadata page.
+		 */
+		if (F_ISSET(dbp, DB_AM_VERIFYING)) {
+			ftype = DB_FTYPE_NOTSET;
+			clear_len = DB_PAGE_DB_LEN;
+			break;
+		}
+		/* FALLTHROUGH */
+	default:
+		return (__db_unknown_type(dbenv, "DB->open", dbp->type));
+	}
+
+	mpf = dbp->mpf;
 
-	/* Validate arguments, but as a DB handle destructor, we can't fail. */
-	if (flags != 0 && flags != DB_NOSYNC)
-		(void)__db_ferr(dbenv, "DB->close", 0);
+	(void)__memp_set_clear_len(mpf, clear_len);
+	(void)__memp_set_fileid(mpf, dbp->fileid);
+	(void)__memp_set_ftype(mpf, ftype);
+	(void)__memp_set_lsn_offset(mpf, 0);
 
-	return (__db_close_i(dbp, NULL, flags));
+	pginfo.db_pagesize = dbp->pgsize;
+	pginfo.flags =
+	    F_ISSET(dbp, (DB_AM_CHKSUM | DB_AM_ENCRYPT | DB_AM_SWAP));
+	pginfo.type = dbp->type;
+	pgcookie.data = &pginfo;
+	pgcookie.size = sizeof(DB_PGINFO);
+	(void)__memp_set_pgcookie(mpf, &pgcookie);
+
+	if ((ret = __memp_fopen(mpf, NULL, fname,
+	    LF_ISSET(DB_RDONLY | DB_NOMMAP |
+	    DB_ODDFILESIZE | DB_TRUNCATE) |
+	    (F_ISSET(dbenv, DB_ENV_DIRECT_DB) ? DB_DIRECT : 0) |
+	    (F_ISSET(dbp, DB_AM_NOT_DURABLE) ? DB_TXN_NOT_DURABLE : 0),
+	    0, dbp->pgsize)) != 0)
+		return (ret);
+
+	return (0);
 }
 
 /*
- * __db_close_i --
- *	Internal DB destructor.
+ * __db_close --
+ *	DB->close method.
  *
- * PUBLIC: int __db_close_i __P((DB *, DB_TXN *, u_int32_t));
+ * PUBLIC: int __db_close __P((DB *, DB_TXN *, u_int32_t));
  */
 int
-__db_close_i(dbp, txn, flags)
+__db_close(dbp, txn, flags)
 	DB *dbp;
 	DB_TXN *txn;
 	u_int32_t flags;
 {
 	DB_ENV *dbenv;
-	int ret, t_ret;
+	int db_ref, deferred_close, ret, t_ret;
 
 	dbenv = dbp->dbenv;
-	ret = 0;
+	deferred_close = ret = 0;
 
 	/*
 	 * Validate arguments, but as a DB handle destructor, we can't fail.
@@ -649,29 +623,32 @@ __db_close_i(dbp, txn, flags)
 	if (txn != NULL)
 		(void)__db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0);
 
-	/* Refresh the structure and close any local environment. */
-	if ((t_ret = __db_refresh(dbp, txn, flags)) != 0 && ret == 0)
-		ret = t_ret;
+	/* Refresh the structure and close any underlying resources. */
+	ret = __db_refresh(dbp, txn, flags, &deferred_close);
 
 	/*
-	 * Call the access specific close function.
-	 *
-	 * !!!
-	 * Because of where these functions are called in the DB handle close
-	 * process, these routines can't do anything that would dirty pages or
-	 * otherwise affect closing down the database.  Specifically, we can't
-	 * abort and recover any of the information they control.
+	 * If we've deferred the close because the logging of the close failed,
+	 * return our failure right away without destroying the handle.
 	 */
-	if ((t_ret = __ham_db_close(dbp)) != 0 && ret == 0)
-		ret = t_ret;
-	if ((t_ret = __bam_db_close(dbp)) != 0 && ret == 0)
-		ret = t_ret;
-	if ((t_ret = __qam_db_close(dbp)) != 0 && ret == 0)
-		ret = t_ret;
+	if (deferred_close)
+		return (ret);
 
-	--dbenv->db_ref;
-	if (F_ISSET(dbenv, DB_ENV_DBLOCAL) && dbenv->db_ref == 0 &&
-	    (t_ret = dbenv->close(dbenv, 0)) != 0 && ret == 0)
+	/* !!!
+	 * This code has an apparent race between the moment we read and
+	 * decrement dbenv->db_ref and the moment we check whether it's 0.
+	 * However, if the environment is DBLOCAL, the user shouldn't have a
+	 * reference to the dbenv handle anyway;  the only way we can get
+	 * multiple dbps sharing a local dbenv is if we open them internally
+	 * during something like a subdatabase open.  If any such thing is
+	 * going on while the user is closing the original dbp with a local
+	 * dbenv, someone's already badly screwed up, so there's no reason
+	 * to bother engineering around this possibility.
+	 */
+	MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
+	db_ref = --dbenv->db_ref;
+	MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
+	if (F_ISSET(dbenv, DB_ENV_DBLOCAL) && db_ref == 0 &&
+	    (t_ret = __dbenv_close(dbenv, 0)) != 0 && ret == 0)
 		ret = t_ret;
 
 	/* Free the database handle. */
@@ -689,20 +666,21 @@ __db_close_i(dbp, txn, flags)
  * the actual handle) and during abort processing, we may have a
  * fully opened handle.
  *
- * PUBLIC: int __db_refresh __P((DB *, DB_TXN *, u_int32_t));
+ * PUBLIC: int __db_refresh __P((DB *, DB_TXN *, u_int32_t, int *));
  */
 int
-__db_refresh(dbp, txn, flags)
+__db_refresh(dbp, txn, flags, deferred_closep)
 	DB *dbp;
 	DB_TXN *txn;
 	u_int32_t flags;
+	int *deferred_closep;
 {
 	DB *sdbp;
 	DBC *dbc;
 	DB_ENV *dbenv;
 	DB_LOCKREQ lreq;
 	DB_MPOOL *dbmp;
-	int ret, t_ret;
+	int resync, ret, t_ret;
 
 	ret = 0;
 
@@ -732,9 +710,14 @@ __db_refresh(dbp, txn, flags)
 	 * Sync the underlying access method.  Do before closing the cursors
 	 * because DB->sync allocates cursors in order to write Recno backing
 	 * source text files.
+	 *
+	 * Sync is slow on some systems, notably Solaris filesystems where the
+	 * entire buffer cache is searched.  If we're in recovery, don't flush
+	 * the file, it's not necessary.
 	 */
-	if (!LF_ISSET(DB_NOSYNC) && !F_ISSET(dbp, DB_AM_DISCARD) &&
-	    (t_ret = dbp->sync(dbp, 0)) != 0 && ret == 0)
+	if (!LF_ISSET(DB_NOSYNC) &&
+	    !F_ISSET(dbp, DB_AM_DISCARD | DB_AM_RECOVER) &&
+	    (t_ret = __db_sync(dbp)) != 0 && ret == 0)
 		ret = t_ret;
 
 	/*
@@ -744,8 +727,9 @@ __db_refresh(dbp, txn, flags)
 	 * routine.  Note that any failure on a close is considered "really
 	 * bad" and we just break out of the loop and force forward.
 	 */
+	resync = TAILQ_FIRST(&dbp->active_queue) == NULL ? 0 : 1;
 	while ((dbc = TAILQ_FIRST(&dbp->active_queue)) != NULL)
-		if ((t_ret = dbc->c_close(dbc)) != 0) {
+		if ((t_ret = __db_c_close(dbc)) != 0) {
 			if (ret == 0)
 				ret = t_ret;
 			break;
@@ -759,11 +743,12 @@ __db_refresh(dbp, txn, flags)
 		}
 
 	/*
-	 * Close any outstanding join cursors.  Join cursors destroy
-	 * themselves on close and have no separate destroy routine.
+	 * Close any outstanding join cursors.  Join cursors destroy themselves
+	 * on close and have no separate destroy routine.  We don't have to set
+	 * the resync flag here, because join cursors aren't write cursors.
 	 */
 	while ((dbc = TAILQ_FIRST(&dbp->join_queue)) != NULL)
-		if ((t_ret = dbc->c_close(dbc)) != 0) {
+		if ((t_ret = __db_join_close(dbc)) != 0) {
 			if (ret == 0)
 				ret = t_ret;
 			break;
@@ -773,34 +758,130 @@ __db_refresh(dbp, txn, flags)
 	 * Sync the memory pool, even though we've already called DB->sync,
 	 * because closing cursors can dirty pages by deleting items they
 	 * referenced.
+	 *
+	 * Sync is slow on some systems, notably Solaris filesystems where the
+	 * entire buffer cache is searched.  If we're in recovery, don't flush
+	 * the file, it's not necessary.
 	 */
-	if (!LF_ISSET(DB_NOSYNC) && !F_ISSET(dbp, DB_AM_DISCARD) &&
-	    (t_ret = dbp->mpf->sync(dbp->mpf)) != 0 && ret == 0)
+	if (resync && !LF_ISSET(DB_NOSYNC) &&
+	    !F_ISSET(dbp, DB_AM_DISCARD | DB_AM_RECOVER) &&
+	    (t_ret = __memp_fsync(dbp->mpf)) != 0 && ret == 0)
 		ret = t_ret;
 
+	/*
+	 * At this point, we haven't done anything to render the DB
+	 * handle unusable, at least by a transaction abort.  Take the
+	 * opportunity now to log the file close.  If this log fails
+	 * and we're in a transaction, we have to bail out of the attempted
+	 * close; we'll need a dbp in order to successfully abort the
+	 * transaction, and we can't conjure a new one up because we haven't
+	 * gotten out the dbreg_register record that represents the close.
+	 * In this case, we put off actually closing the dbp until we've
+	 * performed the abort.
+	 */
+	if (LOGGING_ON(dbp->dbenv)) {
+		/*
+		 * Discard the log file id, if any.  We want to log the close
+		 * if and only if this is not a recovery dbp.
+		 */
+		if (F_ISSET(dbp, DB_AM_RECOVER))
+			t_ret = __dbreg_revoke_id(dbp, 0, DB_LOGFILEID_INVALID);
+		else {
+			if ((t_ret = __dbreg_close_id(dbp,
+			    txn, DBREG_CLOSE)) != 0 && txn != NULL) {
+				/*
+				 * We're in a txn and the attempt to log the
+				 * close failed;  let the txn subsystem know
+				 * that we need to destroy this dbp once we're
+				 * done with the abort, then bail from the
+				 * close.
+				 *
+				 * Note that if the attempt to put off the
+				 * close -also- fails--which it won't unless
+				 * we're out of heap memory--we're really
+				 * screwed.  Panic.
+				 */
+				if ((ret =
+				    __txn_closeevent(dbenv, txn, dbp)) != 0)
+					return (__db_panic(dbenv, ret));
+				if (deferred_closep != NULL)
+					*deferred_closep = 1;
+				return (t_ret);
+			}
+		}
+
+		if (ret == 0)
+			ret = t_ret;
+
+		/* Discard the log FNAME. */
+		if ((t_ret = __dbreg_teardown(dbp)) != 0 && ret == 0)
+			ret = t_ret;
+	}
+
 	/* Close any handle we've been holding since the open.  */
 	if (dbp->saved_open_fhp != NULL &&
-	    F_ISSET(dbp->saved_open_fhp, DB_FH_VALID) &&
 	    (t_ret = __os_closehandle(dbenv, dbp->saved_open_fhp)) != 0 &&
 	    ret == 0)
 		ret = t_ret;
 
 never_opened:
 	/*
-	 * We are not releasing the handle lock here because we're about
-	 * to release all locks held by dbp->lid below.  There are two
-	 * ways that we can get in here with a handle_lock, but not a
-	 * dbp->lid.  The first is when our lid has been hijacked by a
-	 * subdb.  The second is when we are a Queue database in the midst
-	 * of a rename.  If the queue file hasn't actually been opened, we
-	 * hijack the main dbp's locker id to do the open so we can get the
-	 * extent files.  In both cases, we needn't free the handle lock
-	 * because it will be freed when the hijacked locker-id is freed.
+	 * Remove this DB handle from the DB_ENV's dblist, if it's been added.
+	 *
+	 * Close our reference to the underlying cache while locked, we don't
+	 * want to race with a thread searching for our underlying cache link
+	 * while opening a DB handle.
+	 */
+	MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
+	if (dbp->dblistlinks.le_prev != NULL) {
+		LIST_REMOVE(dbp, dblistlinks);
+		dbp->dblistlinks.le_prev = NULL;
+	}
+
+	/* Close the memory pool file handle. */
+	if (dbp->mpf != NULL) {
+		if ((t_ret = __memp_fclose(dbp->mpf,
+		    F_ISSET(dbp, DB_AM_DISCARD) ? DB_MPOOL_DISCARD : 0)) != 0 &&
+		    ret == 0)
+			ret = t_ret;
+		dbp->mpf = NULL;
+	}
+
+	MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
+
+	/*
+	 * Call the access specific close function.
+	 *
+	 * We do this here rather than in __db_close as we need to do this when
+	 * aborting an open so that file descriptors are closed and abort of
+	 * renames can succeed on platforms that lock open files (such as
+	 * Windows).  In particular, we need to ensure that all the extents
+	 * associated with a queue are closed so that queue renames can be
+	 * aborted.
+	 *
+	 * It is also important that we do this before releasing the handle
+	 * lock, because dbremove and dbrename assume that once they have the
+	 * handle lock, it is safe to modify the underlying file(s).
+	 *
+	 * !!!
+	 * Because of where these functions are called in the DB handle close
+	 * process, these routines can't do anything that would dirty pages or
+	 * otherwise affect closing down the database.  Specifically, we can't
+	 * abort and recover any of the information they control.
+	 */
+	if ((t_ret = __bam_db_close(dbp)) != 0 && ret == 0)
+		ret = t_ret;
+	if ((t_ret = __ham_db_close(dbp)) != 0 && ret == 0)
+		ret = t_ret;
+	if ((t_ret = __qam_db_close(dbp, dbp->flags)) != 0 && ret == 0)
+		ret = t_ret;
+
+	/*
+	 * !!!
+	 * At this point, the access-method specific information has been
+	 * freed.  From now on, we can use the dbp, but not touch any
+	 * access-method specific data.
 	 */
-	DB_ASSERT(!LOCK_ISSET(dbp->handle_lock) ||
-	    dbp->lid != DB_LOCK_INVALIDID ||
-	    dbp->type == DB_QUEUE ||
-	    F_ISSET(dbp, DB_AM_SUBDB));
 
 	if (dbp->lid != DB_LOCK_INVALIDID) {
 		/* We may have pending trade operations on this dbp. */
@@ -809,21 +890,21 @@ never_opened:
 
 		/* We may be holding the handle lock; release it. */
 		lreq.op = DB_LOCK_PUT_ALL;
+		lreq.obj = NULL;
 		if ((t_ret = __lock_vec(dbenv,
 		    dbp->lid, 0, &lreq, 1, NULL)) != 0 && ret == 0)
 			ret = t_ret;
 
-		if ((t_ret =
-		    dbenv->lock_id_free(dbenv, dbp->lid)) != 0 && ret == 0)
+		if ((t_ret = __lock_id_free(dbenv, dbp->lid)) != 0 && ret == 0)
 			ret = t_ret;
 		dbp->lid = DB_LOCK_INVALIDID;
 		LOCK_INIT(dbp->handle_lock);
 	}
 
 	/* Discard the locker ID allocated as the fileid. */
-	if (F_ISSET(dbp, DB_AM_INMEM) &&
-	    LOCKING_ON(dbenv) && (t_ret = dbenv->lock_id_free(
-	    dbenv, *(u_int32_t *)dbp->fileid)) != 0 && ret == 0)
+	if (F_ISSET(dbp, DB_AM_INMEM) && LOCKING_ON(dbenv) &&
+	    (t_ret = __lock_id_free(dbenv, *(u_int32_t *)dbp->fileid)) != 0 &&
+	    ret == 0)
 		ret = t_ret;
 
 	dbp->type = DB_UNKNOWN;
@@ -835,6 +916,16 @@ never_opened:
 		dbp->mutexp = NULL;
 	}
 
+	/* Discard any memory allocated for the file and database names. */
+	if (dbp->fname != NULL) {
+		__os_free(dbp->dbenv, dbp->fname);
+		dbp->fname = NULL;
+	}
+	if (dbp->dname != NULL) {
+		__os_free(dbp->dbenv, dbp->dname);
+		dbp->dname = NULL;
+	}
+
 	/* Discard any memory used to store returned data. */
 	if (dbp->my_rskey.data != NULL)
 		__os_free(dbp->dbenv, dbp->my_rskey.data);
@@ -848,38 +939,6 @@ never_opened:
 	memset(&dbp->my_rkey, 0, sizeof(DBT));
 	memset(&dbp->my_rdata, 0, sizeof(DBT));
 
-	/*
-	 * Remove this DB handle from the DB_ENV's dblist, if it's been added.
-	 */
-	MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
-	if (dbp->dblistlinks.le_prev != NULL)
-		LIST_REMOVE(dbp, dblistlinks);
-	MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
-	dbp->dblistlinks.le_prev = NULL;
-
-	/* Close the memory pool file handle. */
-	if (dbp->mpf != NULL) {
-		if ((t_ret = dbp->mpf->close(dbp->mpf,
-		    F_ISSET(dbp, DB_AM_DISCARD) ? DB_MPOOL_DISCARD : 0)) != 0 &&
-		    ret == 0)
-			ret = t_ret;
-		dbp->mpf = NULL;
-	}
-
-	if (LOGGING_ON(dbp->dbenv)) {
-		/*
-		 * Discard the log file id, if any.  We want to log the close
-		 * if and only if this is not a recovery dbp.
-		 */
-		if (F_ISSET(dbp, DB_AM_RECOVER))
-			(void)__dbreg_revoke_id(dbp, 0);
-		else
-			(void)__dbreg_close_id(dbp, txn);
-
-		/* Discard the log FNAME. */
-		(void)__dbreg_teardown(dbp);
-	}
-
 	/* Clear out fields that normally get set during open. */
 	memset(dbp->fileid, 0, sizeof(dbp->fileid));
 	dbp->adj_fileid = 0;
@@ -887,6 +946,7 @@ never_opened:
 	dbp->cur_lid = DB_LOCK_INVALIDID;
 	dbp->associate_lid = DB_LOCK_INVALIDID;
 	dbp->cl_id = 0;
+	dbp->open_flags = 0;
 
 	/*
 	 * If we are being refreshed with a txn specified, then we need
@@ -898,13 +958,8 @@ never_opened:
 	if (txn != NULL)
 		LOCK_INIT(dbp->handle_lock);
 
-	F_CLR(dbp, DB_AM_DBM_ERROR);
-	F_CLR(dbp, DB_AM_DISCARD);
-	F_CLR(dbp, DB_AM_INMEM);
-	F_CLR(dbp, DB_AM_RECOVER);
-	F_CLR(dbp, DB_AM_OPEN_CALLED);
-	F_CLR(dbp, DB_AM_RDONLY);
-	F_CLR(dbp, DB_AM_SWAP);
+	/* Reset flags to whatever the user configured. */
+	dbp->flags = dbp->orig_flags;
 
 	return (ret);
 }
@@ -963,72 +1018,68 @@ __db_backup_name(dbenv, name, txn, backup)
 {
 	DB_LSN lsn;
 	size_t len;
-	int plen, ret;
+	int ret;
 	char *p, *retp;
 
+	/*
+	 * Part of the name may be a full path, so we need to make sure that
+	 * we allocate enough space for it, even in the case where we don't
+	 * use the entire filename for the backup name.
+	 */
+	len = strlen(name) + strlen(BACKUP_PREFIX) + MAX_LSN_TO_TEXT;
+	if ((ret = __os_malloc(dbenv, len, &retp)) != 0)
+		return (ret);
+
 	/*
 	 * Create the name.  Backup file names are in one of two forms:
 	 *
 	 *	In a transactional env: __db.LSN(8).LSN(8)
 	 * and
-	 *	in a non-transactional env: __db.FILENAME.
+	 *	in a non-transactional env: __db.FILENAME
 	 *
-	 * If the transaction doesn't have a current LSN, we write
-	 * a dummy log record to force it, so that we ensure that
-	 * all tmp names are unique.
+	 * If the transaction doesn't have a current LSN, we write a dummy
+	 * log record to force it, so we ensure all tmp names are unique.
 	 *
 	 * In addition, the name passed may contain an env-relative path.
 	 * In that case, put the __db. in the right place (in the last
 	 * component of the pathname).
+	 *
+	 * There are four cases here:
+	 *	1. simple path w/out transaction
+	 *	2. simple path + transaction
+	 *	3. multi-component path w/out transaction
+	 *	4. multi-component path + transaction
 	 */
-	if (txn != NULL) {
+	p = __db_rpath(name);
+	if (txn == NULL)
+		if (p == NULL)				/* Case 1. */
+			snprintf(retp, len, "%s%s", BACKUP_PREFIX, name);
+		else					/* Case 3. */
+			snprintf(retp, len, "%.*s%s%s",
+			    (int)(p - name) + 1, name, BACKUP_PREFIX, p + 1);
+	else {
 		if (IS_ZERO_LSN(txn->last_lsn)) {
 			/*
-			 * Write dummy log record.   The two choices for
-			 * dummy log records are __db_noop_log and
-			 * __db_debug_log; unfortunately __db_noop_log requires
-			 * a valid dbp, and we aren't guaranteed to be able
-			 * to pass one in here.
+			 * Write dummy log record.   The two choices for dummy
+			 * log records are __db_noop_log and __db_debug_log;
+			 * unfortunately __db_noop_log requires a valid dbp,
+			 * and we aren't guaranteed to be able to pass one in
+			 * here.
 			 */
-			if ((ret = __db_debug_log(dbenv, txn, &lsn, 0,
-			    NULL, 0, NULL, NULL, 0)) != 0)
+			if ((ret = __db_debug_log(dbenv,
+			    txn, &lsn, 0, NULL, 0, NULL, NULL, 0)) != 0) {
+				__os_free(dbenv, retp);
 				return (ret);
+			}
 		} else
 			lsn = txn->last_lsn;
-	}
 
-	/*
-	 * Part of the name may be a full path, so we need to make sure that
-	 * we allocate enough space for it, even in the case where we don't
-	 * use the entire filename for the backup name.
-	 */
-	len = strlen(name) + strlen(BACKUP_PREFIX) + MAX_LSN_TO_TEXT;
-	    
-	if ((ret = __os_malloc(dbenv, len, &retp)) != 0)
-		return (ret);
-
-	/*
-	 * There are four cases here:
-	 *	1. simple path w/out transaction
-	 *	2. simple path + transaction
-	 *	3. multi-component path w/out transaction
-	 *	4. multi-component path + transaction
-	 */
-	if ((p = __db_rpath(name)) == NULL) {
-		if (txn == NULL)	/* case 1 */
-			snprintf(retp, len, "%s%s.", BACKUP_PREFIX, name);
-		else			/* case 2 */
+		if (p == NULL)				/* Case 2. */
 			snprintf(retp, len,
 			    "%s%x.%x", BACKUP_PREFIX, lsn.file, lsn.offset);
-	} else {
-		plen = (int)(p - name) + 1;
-		p++;
-		if (txn == NULL)	/* case 3 */
-			snprintf(retp, len,
-			    "%.*s%s%s.", plen, name, BACKUP_PREFIX, p);
-		else 			/* case 4 */
-			snprintf(retp, len,
-			    "%.*s%x.%x.", plen, name, lsn.file, lsn.offset);
+		else					/* Case 4. */
+			snprintf(retp, len, "%.*s%x.%x",
+			    (int)(p - name) + 1, name, lsn.file, lsn.offset);
 	}
 
 	*backup = retp;
@@ -1096,12 +1147,12 @@ __db_disassociate(sdbp)
 	return (ret);
 }
 
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 /*
  * __db_testcopy
  *	Create a copy of all backup files and our "main" DB.
  *
- * PUBLIC: #if CONFIG_TEST
+ * PUBLIC: #ifdef CONFIG_TEST
  * PUBLIC: int __db_testcopy __P((DB_ENV *, DB *, const char *));
  * PUBLIC: #endif
  */
@@ -1111,13 +1162,15 @@ __db_testcopy(dbenv, dbp, name)
 	DB *dbp;
 	const char *name;
 {
+	DB_MPOOL *dbmp;
 	DB_MPOOLFILE *mpf;
 
 	DB_ASSERT(dbp != NULL || name != NULL);
 
 	if (name == NULL) {
+		dbmp = dbenv->mp_handle;
 		mpf = dbp->mpf;
-		name = R_ADDR(mpf->dbmp->reginfo, mpf->mfp->path_off);
+		name = R_ADDR(dbmp->reginfo, mpf->mfp->path_off);
 	}
 
 	if (dbp != NULL && dbp->type == DB_QUEUE)
@@ -1168,37 +1221,39 @@ __db_testdocopy(dbenv, name)
 {
 	size_t len;
 	int dircnt, i, ret;
-	char **namesp, *backup, *copy, *dir, *p, *real_name;
-	real_name = NULL;
+	char *backup, *copy, *dir, **namesp, *p, *real_name;
+
+	dircnt = 0;
+	copy = backup = NULL;
+	namesp = NULL;
+
 	/* Get the real backing file name. */
 	if ((ret = __db_appname(dbenv,
 	    DB_APP_DATA, name, 0, NULL, &real_name)) != 0)
 		return (ret);
 
-	copy = backup = NULL;
-	namesp = NULL;
-
 	/*
 	 * Maximum size of file, including adding a ".afterop".
 	 */
 	len = strlen(real_name) + strlen(BACKUP_PREFIX) + MAX_LSN_TO_TEXT + 9;
 
 	if ((ret = __os_malloc(dbenv, len, &copy)) != 0)
-		goto out;
+		goto err;
 
 	if ((ret = __os_malloc(dbenv, len, &backup)) != 0)
-		goto out;
+		goto err;
 
 	/*
 	 * First copy the file itself.
 	 */
 	snprintf(copy, len, "%s.afterop", real_name);
-	__db_makecopy(real_name, copy);
+	__db_makecopy(dbenv, real_name, copy);
 
 	if ((ret = __os_strdup(dbenv, real_name, &dir)) != 0)
-		goto out;
+		goto err;
 	__os_free(dbenv, real_name);
 	real_name = NULL;
+
 	/*
 	 * Create the name.  Backup file names are of the form:
 	 *
@@ -1230,7 +1285,7 @@ __db_testdocopy(dbenv, name)
 #endif
 	__os_free(dbenv, dir);
 	if (ret != 0)
-		goto out;
+		goto err;
 	for (i = 0; i < dircnt; i++) {
 		/*
 		 * Need to check if it is a backup file for this.
@@ -1243,7 +1298,7 @@ __db_testdocopy(dbenv, name)
 		if (strncmp(namesp[i], backup, strlen(backup)) == 0) {
 			if ((ret = __db_appname(dbenv, DB_APP_DATA,
 			    namesp[i], 0, NULL, &real_name)) != 0)
-				goto out;
+				goto err;
 
 			/*
 			 * This should not happen.  Check that old
@@ -1256,13 +1311,13 @@ __db_testdocopy(dbenv, name)
 				continue;
 			}
 			snprintf(copy, len, "%s.afterop", real_name);
-			__db_makecopy(real_name, copy);
+			__db_makecopy(dbenv, real_name, copy);
 			__os_free(dbenv, real_name);
 			real_name = NULL;
 		}
 	}
-out:
-	if (backup != NULL)
+
+err:	if (backup != NULL)
 		__os_free(dbenv, backup);
 	if (copy != NULL)
 		__os_free(dbenv, copy);
@@ -1274,35 +1329,36 @@ out:
 }
 
 static void
-__db_makecopy(src, dest)
+__db_makecopy(dbenv, src, dest)
+	DB_ENV *dbenv;
 	const char *src, *dest;
 {
-	DB_FH rfh, wfh;
+	DB_FH *rfhp, *wfhp;
 	size_t rcnt, wcnt;
 	char *buf;
 
-	memset(&rfh, 0, sizeof(rfh));
-	memset(&wfh, 0, sizeof(wfh));
+	rfhp = wfhp = NULL;
 
-	if (__os_malloc(NULL, 1024, &buf) != 0)
+	if (__os_malloc(dbenv, 1024, &buf) != 0)
 		return;
 
-	if (__os_open(NULL,
-	    src, DB_OSO_RDONLY, __db_omode("rw----"), &rfh) != 0)
+	if (__os_open(dbenv,
+	    src, DB_OSO_RDONLY, __db_omode("rw----"), &rfhp) != 0)
 		goto err;
-	if (__os_open(NULL, dest,
-	    DB_OSO_CREATE | DB_OSO_TRUNC, __db_omode("rw----"), &wfh) != 0)
+	if (__os_open(dbenv, dest,
+	    DB_OSO_CREATE | DB_OSO_TRUNC, __db_omode("rw----"), &wfhp) != 0)
 		goto err;
 
 	for (;;)
-		if (__os_read(NULL, &rfh, buf, 1024, &rcnt) < 0 || rcnt == 0 ||
-		    __os_write(NULL, &wfh, buf, rcnt, &wcnt) < 0)
+		if (__os_read(dbenv, rfhp, buf, 1024, &rcnt) < 0 || rcnt == 0 ||
+		    __os_write(dbenv, wfhp, buf, rcnt, &wcnt) < 0)
 			break;
 
-err:	__os_free(NULL, buf);
-	if (F_ISSET(&rfh, DB_FH_VALID))
-		__os_closehandle(NULL, &rfh);
-	if (F_ISSET(&wfh, DB_FH_VALID))
-		__os_closehandle(NULL, &wfh);
+err:	if (buf != NULL)
+		__os_free(dbenv, buf);
+	if (rfhp != NULL)
+		(void)__os_closehandle(dbenv, rfhp);
+	if (wfhp != NULL)
+		(void)__os_closehandle(dbenv, wfhp);
 }
 #endif
diff --git a/storage/bdb/db/db.src b/storage/bdb/db/db.src
index 414321fcbbd24baaa46a6ad8b228f04953932d13..2cac31a4f52f75627d2ba87c8f5ac4ebe111d409 100644
--- a/storage/bdb/db/db.src
+++ b/storage/bdb/db/db.src
@@ -1,17 +1,15 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: db.src,v 11.18 2002/04/17 19:02:58 krinsky Exp $
+ * $Id: db.src,v 11.28 2004/06/17 17:35:15 bostic Exp $
  */
 
 PREFIX	__db
 DBPRIVATE
 
-INCLUDE	#include "db_config.h"
-INCLUDE
 INCLUDE #ifndef NO_SYSTEM_INCLUDES
 INCLUDE #include <sys/types.h>
 INCLUDE
@@ -25,7 +23,6 @@ INCLUDE #include "dbinc/db_page.h"
 INCLUDE #include "dbinc/db_dispatch.h"
 INCLUDE #include "dbinc/db_am.h"
 INCLUDE #include "dbinc/log.h"
-INCLUDE #include "dbinc/rep.h"
 INCLUDE #include "dbinc/txn.h"
 INCLUDE
 
@@ -48,7 +45,7 @@ INCLUDE
 BEGIN addrem		41
 ARG	opcode		u_int32_t	lu
 DB	fileid		int32_t		ld
-WRLOCK	pgno		db_pgno_t	lu
+ARG	pgno		db_pgno_t	lu
 ARG	indx		u_int32_t	lu
 ARG	nbytes		u_int32_t	lu
 PGDBT	hdr		DBT		s
@@ -74,9 +71,9 @@ END
 BEGIN big		43
 ARG	opcode		u_int32_t	lu
 DB	fileid		int32_t		ld
-WRLOCK	pgno		db_pgno_t	lu
-WRLOCKNZ prev_pgno	db_pgno_t	lu
-WRLOCKNZ next_pgno	db_pgno_t	lu
+ARG	pgno		db_pgno_t	lu
+ARG	prev_pgno	db_pgno_t	lu
+ARG	next_pgno	db_pgno_t	lu
 DBT	dbt		DBT		s
 POINTER	pagelsn		DB_LSN *	lu
 POINTER	prevlsn		DB_LSN *	lu
@@ -93,33 +90,11 @@ END
  */
 BEGIN ovref		44
 DB	fileid		int32_t		ld
-WRLOCK	pgno		db_pgno_t	lu
+ARG	pgno		db_pgno_t	lu
 ARG	adjust		int32_t		ld
 POINTER	lsn		DB_LSN *	lu
 END
 
-/*
- * relink -- Handles relinking around a page.
- *
- * opcode:	indicates if this is an addpage or delete page
- * pgno:	the page being changed.
- * lsn		the page's original lsn.
- * prev:	the previous page.
- * lsn_prev:	the previous page's original lsn.
- * next:	the next page.
- * lsn_next:	the previous page's original lsn.
- */
-BEGIN relink		45
-ARG	opcode		u_int32_t	lu
-DB	fileid		int32_t		ld
-WRLOCK	pgno		db_pgno_t	lu
-POINTER	lsn		DB_LSN *	lu
-WRLOCKNZ prev		db_pgno_t	lu
-POINTER	lsn_prev	DB_LSN *	lu
-WRLOCKNZ next		db_pgno_t	lu
-POINTER	lsn_next	DB_LSN *	lu
-END
-
 /*
  * Debug -- log an operation upon entering an access method.
  * op:		Operation (cursor, c_close, c_get, c_put, c_del,
@@ -142,7 +117,7 @@ END
  */
 BEGIN noop		48
 DB	fileid		int32_t		ld
-WRLOCK	pgno		db_pgno_t	lu
+ARG	pgno		db_pgno_t	lu
 POINTER	prevlsn		DB_LSN *	lu
 END
 
@@ -155,15 +130,17 @@ END
  * pgno:	the page allocated.
  * ptype:	the type of the page allocated.
  * next:	the next page on the free list.
+ * last_pgno:	the last page in the file after this op.
  */
 BEGIN pg_alloc	49
 DB	fileid		int32_t		ld
 POINTER	meta_lsn	DB_LSN *	lu
-WRLOCK	meta_pgno	db_pgno_t	lu
+ARG	meta_pgno	db_pgno_t	lu
 POINTER	page_lsn	DB_LSN *	lu
-WRLOCK	pgno		db_pgno_t	lu
+ARG	pgno		db_pgno_t	lu
 ARG	ptype		u_int32_t	lu
 ARG	next		db_pgno_t	lu
+ARG	last_pgno	db_pgno_t	lu
 END
 
 /*
@@ -174,14 +151,16 @@ END
  * meta_pgno:	the meta-data page number.
  * header:	the header from the free'd page.
  * next:	the previous next pointer on the metadata page.
+ * last_pgno:	the last page in the file before this op.
  */
 BEGIN pg_free		50
 DB	fileid		int32_t		ld
-WRLOCK	pgno		db_pgno_t	lu
+ARG	pgno		db_pgno_t	lu
 POINTER	meta_lsn	DB_LSN *	lu
-WRLOCK	meta_pgno	db_pgno_t	lu
+ARG	meta_pgno	db_pgno_t	lu
 PGDBT	header		DBT		s
 ARG	next		db_pgno_t	lu
+ARG	last_pgno	db_pgno_t	lu
 END
 
 /*
@@ -193,3 +172,67 @@ END
  */
 BEGIN cksum		51
 END
+
+/*
+ * pg_freedata: used to record freeing a page with data on it.
+ *
+ * pgno:	the page being freed.
+ * meta_lsn:	the meta-data page's original lsn.
+ * meta_pgno:	the meta-data page number.
+ * header:	the header and index entries from the free'd page.
+ * data:	the data from the free'd page.
+ * next:	the previous next pointer on the metadata page.
+ * last_pgno:	the last page in the file before this op.
+ */
+BEGIN pg_freedata		52
+DB	fileid		int32_t		ld
+ARG	pgno		db_pgno_t	lu
+POINTER	meta_lsn	DB_LSN *	lu
+ARG	meta_pgno	db_pgno_t	lu
+PGDBT	header		DBT		s
+ARG	next		db_pgno_t	lu
+ARG	last_pgno	db_pgno_t	lu
+PGDBT	data		DBT		s
+END
+
+/*
+ * pg_prepare: used to record an aborted page in a prepared transaction.
+ *
+ * pgno:	the page being freed.
+ */
+BEGIN pg_prepare		53
+DB	fileid		int32_t		ld
+ARG	pgno		db_pgno_t	lu
+END
+
+/*
+ * pg_new: used to record a new page put on the free list.
+ *
+ * pgno:	the page being freed.
+ * meta_lsn:	the meta-data page's original lsn.
+ * meta_pgno:	the meta-data page number.
+ * header:	the header from the free'd page.
+ * next:	the previous next pointer on the metadata page.
+ */
+BEGIN pg_new		54
+DB	fileid		int32_t		ld
+ARG	pgno		db_pgno_t	lu
+POINTER	meta_lsn	DB_LSN *	lu
+ARG	meta_pgno	db_pgno_t	lu
+PGDBT	header		DBT		s
+ARG	next		db_pgno_t	lu
+END
+
+/*
+ * pg_init: used to reinitialize a page during truncate.
+ *
+ * pgno:	the page being initialized.
+ * header:	the header from the page.
+ * data:	data that used to be on the page.
+ */
+BEGIN pg_init		60
+DB	fileid		int32_t		ld
+ARG	pgno		db_pgno_t	lu
+PGDBT	header		DBT		s
+PGDBT	data		DBT		s
+END
diff --git a/storage/bdb/db/db_am.c b/storage/bdb/db/db_am.c
index cf6ef18549b9ec0cb3c3fe3a68222edb73025be5..0e4a864f95ab6a415a3ddb712020715ea4fb1280 100644
--- a/storage/bdb/db/db_am.c
+++ b/storage/bdb/db/db_am.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1998-2002
+ * Copyright (c) 1998-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_am.c,v 11.120 2004/10/07 17:33:32 sue Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_am.c,v 11.96 2002/08/27 15:17:32 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -29,91 +27,16 @@ static const char revid[] = "$Id: db_am.c,v 11.96 2002/08/27 15:17:32 bostic Exp
 
 static int __db_append_primary __P((DBC *, DBT *, DBT *));
 static int __db_secondary_get __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
-static int __db_secondary_close __P((DB *, u_int32_t));
-
-#ifdef DEBUG
-static int __db_cprint_item __P((DBC *));
-#endif
-
-/*
- * __db_cursor --
- *	Allocate and return a cursor.
- *
- * PUBLIC: int __db_cursor __P((DB *, DB_TXN *, DBC **, u_int32_t));
- */
-int
-__db_cursor(dbp, txn, dbcp, flags)
-	DB *dbp;
-	DB_TXN *txn;
-	DBC **dbcp;
-	u_int32_t flags;
-{
-	DB_ENV *dbenv;
-	DBC *dbc;
-	db_lockmode_t mode;
-	u_int32_t op;
-	int ret;
-
-	dbenv = dbp->dbenv;
-
-	PANIC_CHECK(dbenv);
-	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->cursor");
-
-	/* Validate arguments. */
-	if ((ret = __db_cursorchk(dbp, flags)) != 0)
-		return (ret);
-
-	/*
-	 * Check for consistent transaction usage.  For now, assume that
-	 * this cursor might be used for read operations only (in which
-	 * case it may not require a txn).  We'll check more stringently
-	 * in c_del and c_put.  (Note that this all means that the
-	 * read-op txn tests have to be a subset of the write-op ones.)
-	 */
-	if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 1)) != 0)
-		return (ret);
-
-	if ((ret = __db_icursor(dbp,
-	    txn, dbp->type, PGNO_INVALID, 0, DB_LOCK_INVALIDID, dbcp)) != 0)
-		return (ret);
-	dbc = *dbcp;
-
-	/*
-	 * If this is CDB, do all the locking in the interface, which is
-	 * right here.
-	 */
-	if (CDB_LOCKING(dbenv)) {
-		op = LF_ISSET(DB_OPFLAGS_MASK);
-		mode = (op == DB_WRITELOCK) ? DB_LOCK_WRITE :
-		    ((op == DB_WRITECURSOR) ? DB_LOCK_IWRITE : DB_LOCK_READ);
-		if ((ret = dbenv->lock_get(dbenv, dbc->locker, 0,
-		    &dbc->lock_dbt, mode, &dbc->mylock)) != 0) {
-			(void)__db_c_close(dbc);
-			return (ret);
-		}
-		if (op == DB_WRITECURSOR)
-			F_SET(dbc, DBC_WRITECURSOR);
-		if (op == DB_WRITELOCK)
-			F_SET(dbc, DBC_WRITER);
-	}
-
-	if (LF_ISSET(DB_DIRTY_READ) ||
-	    (txn != NULL && F_ISSET(txn, TXN_DIRTY_READ)))
-		F_SET(dbc, DBC_DIRTY_READ);
-	return (0);
-}
 
 /*
- * __db_icursor --
- *	Internal version of __db_cursor.  If dbcp is
- *	non-NULL it is assumed to point to an area to
- *	initialize as a cursor.
+ * __db_cursor_int --
+ *	Internal routine to create a cursor.
  *
- * PUBLIC: int __db_icursor
+ * PUBLIC: int __db_cursor_int
  * PUBLIC:     __P((DB *, DB_TXN *, DBTYPE, db_pgno_t, int, u_int32_t, DBC **));
  */
 int
-__db_icursor(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
+__db_cursor_int(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
 	DB *dbp;
 	DB_TXN *txn;
 	DBTYPE dbtype;
@@ -122,7 +45,7 @@ __db_icursor(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
 	u_int32_t lockerid;
 	DBC **dbcp;
 {
-	DBC *dbc, *adbc;
+	DBC *dbc;
 	DBC_INTERNAL *cp;
 	DB_ENV *dbenv;
 	int allocated, ret;
@@ -131,6 +54,9 @@ __db_icursor(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
 	allocated = 0;
 
 	/*
+	 * If dbcp is non-NULL it is assumed to point to an area to initialize
+	 * as a cursor.
+	 *
 	 * Take one from the free list if it's available.  Take only the
 	 * right type.  With off page dups we may have different kinds
 	 * of cursors on the queue for a single database.
@@ -146,7 +72,7 @@ __db_icursor(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
 	MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
 
 	if (dbc == NULL) {
-		if ((ret = __os_calloc(dbp->dbenv, 1, sizeof(DBC), &dbc)) != 0)
+		if ((ret = __os_calloc(dbenv, 1, sizeof(DBC), &dbc)) != 0)
 			return (ret);
 		allocated = 1;
 		dbc->flags = 0;
@@ -156,28 +82,33 @@ __db_icursor(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
 		/* Set up locking information. */
 		if (LOCKING_ON(dbenv)) {
 			/*
-			 * If we are not threaded, then there is no need to
-			 * create new locker ids.  We know that no one else
-			 * is running concurrently using this DB, so we can
-			 * take a peek at any cursors on the active queue.
+			 * If we are not threaded, we share a locker ID among
+			 * all cursors opened in the environment handle,
+			 * allocating one if this is the first cursor.
+			 *
+			 * This relies on the fact that non-threaded DB handles
+			 * always have non-threaded environment handles, since
+			 * we set DB_THREAD on DB handles created with threaded
+			 * environment handles.
 			 */
-			if (!DB_IS_THREADED(dbp) &&
-			    (adbc = TAILQ_FIRST(&dbp->active_queue)) != NULL)
-				dbc->lid = adbc->lid;
-			else {
-				if ((ret =
-				    dbenv->lock_id(dbenv, &dbc->lid)) != 0)
+			if (!DB_IS_THREADED(dbp)) {
+				if (dbp->dbenv->env_lid == DB_LOCK_INVALIDID &&
+				    (ret =
+				    __lock_id(dbenv,&dbp->dbenv->env_lid)) != 0)
+					goto err;
+				dbc->lid = dbp->dbenv->env_lid;
+			} else {
+				if ((ret = __lock_id(dbenv, &dbc->lid)) != 0)
 					goto err;
 				F_SET(dbc, DBC_OWN_LID);
 			}
 
 			/*
 			 * In CDB, secondary indices should share a lock file
-			 * ID with the primary;  otherwise we're susceptible to
-			 * deadlocks.  We also use __db_icursor rather
-			 * than sdbp->cursor to create secondary update
-			 * cursors in c_put and c_del;  these won't
-			 * acquire a new lock.
+			 * ID with the primary;  otherwise we're susceptible
+			 * to deadlocks.  We also use __db_cursor_int rather
+			 * than __db_cursor to create secondary update cursors
+			 * in c_put and c_del; these won't acquire a new lock.
 			 *
 			 * !!!
 			 * Since this is in the one-time cursor allocation
@@ -185,7 +116,7 @@ __db_icursor(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
 			 * close, all cursors in the secondary when we
 			 * associate.
 			 */
-			if (CDB_LOCKING(dbp->dbenv) &&
+			if (CDB_LOCKING(dbenv) &&
 			    F_ISSET(dbp, DB_AM_SECONDARY))
 				memcpy(dbc->lock.fileid,
 				    dbp->s_primary->fileid, DB_FILE_ID_LEN);
@@ -231,9 +162,9 @@ __db_icursor(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
 			if ((ret = __qam_c_init(dbc)) != 0)
 				goto err;
 			break;
+		case DB_UNKNOWN:
 		default:
-			ret = __db_unknown_type(dbp->dbenv,
-			    "__db_icursor", dbtype);
+			ret = __db_unknown_type(dbenv, "DB->cursor", dbtype);
 			goto err;
 		}
 
@@ -270,10 +201,8 @@ __db_icursor(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
 			dbc->locker = lockerid;
 		else
 			dbc->locker = dbc->lid;
-	} else {
+	} else
 		dbc->locker = txn->txnid;
-		txn->cursors++;
-	}
 
 	/*
 	 * These fields change when we are used as a secondary index, so
@@ -283,7 +212,7 @@ __db_icursor(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
 	 * __db_c_get is used by all access methods, so this should be safe.
 	 */
 	if (F_ISSET(dbp, DB_AM_SECONDARY))
-		dbc->c_get = __db_c_secondary_get;
+		dbc->c_get = __db_c_secondary_get_pp;
 
 	if (is_opd)
 		F_SET(dbc, DBC_OPD);
@@ -310,11 +239,20 @@ __db_icursor(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
 	case DB_HASH:
 	case DB_QUEUE:
 		break;
+	case DB_UNKNOWN:
 	default:
-		ret = __db_unknown_type(dbp->dbenv, "__db_icursor", dbp->type);
+		ret = __db_unknown_type(dbenv, "DB->cursor", dbp->type);
 		goto err;
 	}
 
+	/*
+	 * The transaction keeps track of how many cursors were opened within
+	 * it to catch application errors where the cursor isn't closed when
+	 * the transaction is resolved.
+	 */
+	if (txn != NULL)
+		++txn->cursors;
+
 	MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
 	TAILQ_INSERT_TAIL(&dbp->active_queue, dbc, links);
 	F_SET(dbc, DBC_ACTIVE);
@@ -324,189 +262,7 @@ __db_icursor(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
 	return (0);
 
 err:	if (allocated)
-		__os_free(dbp->dbenv, dbc);
-	return (ret);
-}
-
-#ifdef DEBUG
-/*
- * __db_cprint --
- *	Display the cursor active and free queues.
- *
- * PUBLIC: int __db_cprint __P((DB *));
- */
-int
-__db_cprint(dbp)
-	DB *dbp;
-{
-	DBC *dbc;
-	int ret, t_ret;
-
-	ret = 0;
-	MUTEX_THREAD_LOCK(dbp->dbenv, dbp->mutexp);
-	fprintf(stderr, "Active queue:\n");
-	for (dbc = TAILQ_FIRST(&dbp->active_queue);
-	    dbc != NULL; dbc = TAILQ_NEXT(dbc, links))
-		if ((t_ret = __db_cprint_item(dbc)) != 0 && ret == 0)
-			ret = t_ret;
-	fprintf(stderr, "Free queue:\n");
-	for (dbc = TAILQ_FIRST(&dbp->free_queue);
-	    dbc != NULL; dbc = TAILQ_NEXT(dbc, links))
-		if ((t_ret = __db_cprint_item(dbc)) != 0 && ret == 0)
-			ret = t_ret;
-	MUTEX_THREAD_UNLOCK(dbp->dbenv, dbp->mutexp);
-
-	return (ret);
-}
-
-static
-int __db_cprint_item(dbc)
-	DBC *dbc;
-{
-	static const FN fn[] = {
-		{ DBC_ACTIVE,		"active" },
-		{ DBC_COMPENSATE,	"compensate" },
-		{ DBC_OPD,		"off-page-dup" },
-		{ DBC_RECOVER,		"recover" },
-		{ DBC_RMW,		"read-modify-write" },
-		{ DBC_TRANSIENT,	"transient" },
-		{ DBC_WRITECURSOR,	"write cursor" },
-		{ DBC_WRITEDUP,		"internally dup'ed write cursor" },
-		{ DBC_WRITER,		"short-term write cursor" },
-		{ 0,			NULL }
-	};
-	DB *dbp;
-	DBC_INTERNAL *cp;
-	const char *s;
-
-	dbp = dbc->dbp;
-	cp = dbc->internal;
-
-	s = __db_dbtype_to_string(dbc->dbtype);
-	if (strcmp(s, "UNKNOWN TYPE") == 0) {
-		DB_ASSERT(0);
-		return (1);
-	}
-	fprintf(stderr, "%s/%#0lx: opd: %#0lx\n",
-	    s, P_TO_ULONG(dbc), P_TO_ULONG(cp->opd));
-
-	fprintf(stderr, "\ttxn: %#0lx lid: %lu locker: %lu\n",
-	    P_TO_ULONG(dbc->txn), (u_long)dbc->lid, (u_long)dbc->locker);
-
-	fprintf(stderr, "\troot: %lu page/index: %lu/%lu",
-	    (u_long)cp->root, (u_long)cp->pgno, (u_long)cp->indx);
-
-	__db_prflags(dbc->flags, fn, stderr);
-	fprintf(stderr, "\n");
-
-	switch (dbp->type) {
-	case DB_BTREE:
-		__bam_cprint(dbc);
-		break;
-	case DB_HASH:
-		__ham_cprint(dbc);
-		break;
-	default:
-		break;
-	}
-	return (0);
-}
-#endif /* DEBUG */
-
-/*
- * db_fd --
- *	Return a file descriptor for flock'ing.
- *
- * PUBLIC: int __db_fd __P((DB *, int *));
- */
-int
-__db_fd(dbp, fdp)
-	DB *dbp;
-	int *fdp;
-{
-	DB_FH *fhp;
-	int ret;
-
-	PANIC_CHECK(dbp->dbenv);
-	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->fd");
-
-	/*
-	 * XXX
-	 * Truly spectacular layering violation.
-	 */
-	if ((ret = __mp_xxx_fh(dbp->mpf, &fhp)) != 0)
-		return (ret);
-
-	if (F_ISSET(fhp, DB_FH_VALID)) {
-		*fdp = fhp->fd;
-		return (0);
-	} else {
-		*fdp = -1;
-		__db_err(dbp->dbenv, "DB does not have a valid file handle");
-		return (ENOENT);
-	}
-}
-
-/*
- * __db_get --
- *	Return a key/data pair.
- *
- * PUBLIC: int __db_get __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
- */
-int
-__db_get(dbp, txn, key, data, flags)
-	DB *dbp;
-	DB_TXN *txn;
-	DBT *key, *data;
-	u_int32_t flags;
-{
-	DBC *dbc;
-	int mode, ret, t_ret;
-
-	PANIC_CHECK(dbp->dbenv);
-	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->get");
-
-	if ((ret = __db_getchk(dbp, key, data, flags)) != 0)
-		return (ret);
-
-	/* Check for consistent transaction usage. */
-	if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 1)) != 0)
-		return (ret);
-
-	mode = 0;
-	if (LF_ISSET(DB_DIRTY_READ)) {
-		mode = DB_DIRTY_READ;
-		LF_CLR(DB_DIRTY_READ);
-	}
-	else if (flags == DB_CONSUME || flags == DB_CONSUME_WAIT)
-		mode = DB_WRITELOCK;
-	if ((ret = dbp->cursor(dbp, txn, &dbc, mode)) != 0)
-		return (ret);
-
-	DEBUG_LREAD(dbc, txn, "__db_get", key, NULL, flags);
-
-	/*
-	 * The DBC_TRANSIENT flag indicates that we're just doing a
-	 * single operation with this cursor, and that in case of
-	 * error we don't need to restore it to its old position--we're
-	 * going to close it right away.  Thus, we can perform the get
-	 * without duplicating the cursor, saving some cycles in this
-	 * common case.
-	 *
-	 * SET_RET_MEM indicates that if key and/or data have no DBT
-	 * flags set and DB manages the returned-data memory, that memory
-	 * will belong to this handle, not to the underlying cursor.
-	 */
-	F_SET(dbc, DBC_TRANSIENT);
-	SET_RET_MEM(dbc, dbp);
-
-	if (LF_ISSET(~(DB_RMW | DB_MULTIPLE)) == 0)
-		LF_SET(DB_SET);
-	ret = dbc->c_get(dbc, key, data, flags);
-
-	if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
-		ret = t_ret;
-
+		__os_free(dbenv, dbc);
 	return (ret);
 }
 
@@ -526,36 +282,14 @@ __db_put(dbp, txn, key, data, flags)
 	DBC *dbc;
 	DBT tdata;
 	DB_ENV *dbenv;
-	int ret, t_ret, txn_local;
+	int ret, t_ret;
 
-	dbc = NULL;
 	dbenv = dbp->dbenv;
-	txn_local = 0;
-
-	PANIC_CHECK(dbenv);
-	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->put");
 
-	/* Validate arguments. */
-	if ((ret = __db_putchk(dbp, key, data,
-	    flags, F_ISSET(dbp, DB_AM_DUP) || F_ISSET(key, DB_DBT_DUPOK))) != 0)
+	if ((ret = __db_cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0)
 		return (ret);
 
-	/* Create local transaction as necessary. */
-	if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
-		if ((ret = __db_txn_auto(dbp, &txn)) != 0)
-			return (ret);
-		txn_local = 1;
-		LF_CLR(DB_AUTO_COMMIT);
-	}
-
-	/* Check for consistent transaction usage. */
-	if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0)) != 0)
-		goto err;
-
-	if ((ret = dbp->cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0)
-		goto err;
-
-	DEBUG_LWRITE(dbc, txn, "db_put", key, data, flags);
+	DEBUG_LWRITE(dbc, txn, "DB->put", key, data, flags);
 
 	SET_RET_MEM(dbc, dbp);
 
@@ -594,10 +328,15 @@ __db_put(dbp, txn, key, data, flags)
 			if ((ret = __ram_append(dbc, key, &tdata)) != 0)
 				goto err;
 			break;
+		case DB_BTREE:
+		case DB_HASH:
+		case DB_UNKNOWN:
 		default:
 			/* The interface should prevent this. */
-			DB_ASSERT(0);
-			ret = __db_ferr(dbenv, "__db_put", flags);
+			DB_ASSERT(
+			    dbp->type == DB_QUEUE || dbp->type == DB_RECNO);
+
+			ret = __db_ferr(dbenv, "DB->put", 0);
 			goto err;
 		}
 
@@ -621,7 +360,7 @@ __db_put(dbp, txn, key, data, flags)
 		FREE_IF_NEEDED(dbp, &tdata);
 
 		/* No need for a cursor put;  we're done. */
-		goto err;
+		goto done;
 	case DB_NOOVERWRITE:
 		flags = 0;
 		/*
@@ -636,7 +375,7 @@ __db_put(dbp, txn, key, data, flags)
 		 * If we're doing page-level locking, set the read-modify-write
 		 * flag, we're going to overwrite immediately.
 		 */
-		if ((ret = dbc->c_get(dbc, key, &tdata,
+		if ((ret = __db_c_get(dbc, key, &tdata,
 		    DB_SET | (STD_LOCKING(dbc) ? DB_RMW : 0))) == 0)
 			ret = DB_KEYEXIST;
 		else if (ret == DB_NOTFOUND || ret == DB_KEYEMPTY)
@@ -646,34 +385,27 @@ __db_put(dbp, txn, key, data, flags)
 		/* Fall through to normal cursor put. */
 		break;
 	}
+
 	if (ret == 0)
-		ret = dbc->c_put(dbc,
+		ret = __db_c_put(dbc,
 		    key, data, flags == 0 ? DB_KEYLAST : flags);
 
-err:	/* Close the cursor. */
-	if (dbc != NULL && (t_ret = __db_c_close(dbc)) != 0 && ret == 0)
+err:
+done:	/* Close the cursor. */
+	if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
 		ret = t_ret;
 
-	/* Commit for DB_AUTO_COMMIT. */
-	if (txn_local) {
-		if (ret == 0)
-			ret = txn->commit(txn, 0);
-		else
-			if ((t_ret = txn->abort(txn)) != 0)
-				ret = __db_panic(dbenv, t_ret);
-	}
-
 	return (ret);
 }
 
 /*
- * __db_delete --
+ * __db_del --
  *	Delete the items referenced by a key.
  *
- * PUBLIC: int __db_delete __P((DB *, DB_TXN *, DBT *, u_int32_t));
+ * PUBLIC: int __db_del __P((DB *, DB_TXN *, DBT *, u_int32_t));
  */
 int
-__db_delete(dbp, txn, key, flags)
+__db_del(dbp, txn, key, flags)
 	DB *dbp;
 	DB_TXN *txn;
 	DBT *key;
@@ -681,38 +413,15 @@ __db_delete(dbp, txn, key, flags)
 {
 	DBC *dbc;
 	DBT data, lkey;
-	DB_ENV *dbenv;
 	u_int32_t f_init, f_next;
-	int ret, t_ret, txn_local;
-
-	dbc = NULL;
-	dbenv = dbp->dbenv;
-	txn_local = 0;
-
-	PANIC_CHECK(dbenv);
-	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->del");
-
-	/* Check for invalid flags. */
-	if ((ret = __db_delchk(dbp, key, flags)) != 0)
-		return (ret);
-
-	/* Create local transaction as necessary. */
-	if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
-		if ((ret = __db_txn_auto(dbp, &txn)) != 0)
-			return (ret);
-		txn_local = 1;
-		LF_CLR(DB_AUTO_COMMIT);
-	}
-
-	/* Check for consistent transaction usage. */
-	if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0)) != 0)
-		goto err;
+	int ret, t_ret;
 
 	/* Allocate a cursor. */
-	if ((ret = dbp->cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0)
+	if ((ret = __db_cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0)
 		goto err;
 
-	DEBUG_LWRITE(dbc, txn, "db_delete", key, NULL, flags);
+	DEBUG_LWRITE(dbc, txn, "DB->del", key, NULL, flags);
+	COMPQUIET(flags, 0);
 
 	/*
 	 * Walk a cursor through the key/data pairs, deleting as we go.  Set
@@ -737,7 +446,7 @@ __db_delete(dbp, txn, key, flags)
 	}
 
 	/* Walk through the set of key/data pairs, deleting as we go. */
-	if ((ret = dbc->c_get(dbc, key, &data, f_init)) != 0)
+	if ((ret = __db_c_get(dbc, key, &data, f_init)) != 0)
 		goto err;
 
 	/*
@@ -760,40 +469,29 @@ __db_delete(dbp, txn, key, flags)
 	 * The ordinary AM-independent alternative will work just fine with
 	 * a hash;  it'll just be slower.
 	 */
-	if (dbp->type == DB_HASH) {
+	if (dbp->type == DB_HASH)
 		if (LIST_FIRST(&dbp->s_secondaries) == NULL &&
 		    !F_ISSET(dbp, DB_AM_SECONDARY) &&
 		    dbc->internal->opd == NULL) {
 			ret = __ham_quick_delete(dbc);
-			goto err;
+			goto done;
 		}
-	}
 
 	for (;;) {
-		if ((ret = dbc->c_del(dbc, 0)) != 0)
-			goto err;
-		if ((ret = dbc->c_get(dbc, &lkey, &data, f_next)) != 0) {
-			if (ret == DB_NOTFOUND) {
+		if ((ret = __db_c_del(dbc, 0)) != 0)
+			break;
+		if ((ret = __db_c_get(dbc, &lkey, &data, f_next)) != 0) {
+			if (ret == DB_NOTFOUND)
 				ret = 0;
-				break;
-			}
-			goto err;
+			break;
 		}
 	}
 
+done:
 err:	/* Discard the cursor. */
-	if (dbc != NULL && (t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
+	if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
 		ret = t_ret;
 
-	/* Commit for DB_AUTO_COMMIT. */
-	if (txn_local) {
-		if (ret == 0)
-			ret = txn->commit(txn, 0);
-		else
-			if ((t_ret = txn->abort(txn)) != 0)
-				ret = __db_panic(dbenv, t_ret);
-	}
-
 	return (ret);
 }
 
@@ -801,22 +499,17 @@ err:	/* Discard the cursor. */
  * __db_sync --
  *	Flush the database cache.
  *
- * PUBLIC: int __db_sync __P((DB *, u_int32_t));
+ * PUBLIC: int __db_sync __P((DB *));
  */
 int
-__db_sync(dbp, flags)
+__db_sync(dbp)
 	DB *dbp;
-	u_int32_t flags;
 {
 	int ret, t_ret;
 
-	PANIC_CHECK(dbp->dbenv);
-	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->sync");
-
-	if ((ret = __db_syncchk(dbp, flags)) != 0)
-		return (ret);
+	ret = 0;
 
-	/* Read-only trees never need to be sync'd. */
+	/* If the database was read-only, we're done. */
 	if (F_ISSET(dbp, DB_AM_RDONLY))
 		return (0);
 
@@ -824,13 +517,17 @@ __db_sync(dbp, flags)
 	if (dbp->type == DB_RECNO)
 		ret = __ram_writeback(dbp);
 
-	/* If the tree was never backed by a database file, we're done. */
+	/* If the database was never backed by a database file, we're done. */
 	if (F_ISSET(dbp, DB_AM_INMEM))
-		return (0);
+		return (ret);
+
+	if (dbp->type == DB_QUEUE)
+		ret = __qam_sync(dbp);
+	else
+		/* Flush any dirty pages from the cache to the backing file. */
+		if ((t_ret = __memp_fsync(dbp->mpf)) != 0 && ret == 0)
+			ret = t_ret;
 
-	/* Flush any dirty pages from the cache to the backing file. */
-	if ((t_ret = dbp->mpf->sync(dbp->mpf)) != 0 && ret == 0)
-		ret = t_ret;
 	return (ret);
 }
 
@@ -851,40 +548,11 @@ __db_associate(dbp, txn, sdbp, callback, flags)
 	DB_ENV *dbenv;
 	DBC *pdbc, *sdbc;
 	DBT skey, key, data;
-	int build, ret, t_ret, txn_local;
+	int build, ret, t_ret;
 
 	dbenv = dbp->dbenv;
-
-	PANIC_CHECK(dbenv);
-
-	txn_local = 0;
-	pdbc = NULL;
-
-	memset(&key, 0, sizeof(DBT));
-	memset(&data, 0, sizeof(DBT));
-	memset(&skey, 0, sizeof(DBT));
-
-	if ((ret = __db_associatechk(dbp, sdbp, callback, flags)) != 0)
-		return (ret);
-
-	/*
-	 * Create a local transaction as necessary, check for consistent
-	 * transaction usage, and, if we have no transaction but do have
-	 * locking on, acquire a locker id for the handle lock acquisition.
-	 */
-	if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
-		if ((ret = __db_txn_auto(dbp, &txn)) != 0)
-			return (ret);
-		txn_local = 1;
-	} else if (txn != NULL && !TXN_ON(dbenv))
-		return (__db_not_txn_env(dbenv));
-
-	/*
-	 * Check that if an open transaction is in progress, we're in it,
-	 * for other common transaction errors, and for concurrent associates.
-	 */
-	if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0)) != 0)
-		return (ret);
+	pdbc = sdbc = NULL;
+	ret = 0;
 
 	sdbp->s_callback = callback;
 	sdbp->s_primary = dbp;
@@ -893,23 +561,7 @@ __db_associate(dbp, txn, sdbp, callback, flags)
 	sdbp->get = __db_secondary_get;
 
 	sdbp->stored_close = sdbp->close;
-	sdbp->close = __db_secondary_close;
-
-	/*
-	 * Secondary cursors may have the primary's lock file ID, so we
-	 * need to make sure that no older cursors are lying around
-	 * when we make the transition.
-	 */
-	if (TAILQ_FIRST(&sdbp->active_queue) != NULL ||
-	    TAILQ_FIRST(&sdbp->join_queue) != NULL) {
-		__db_err(dbenv,
-    "Databases may not become secondary indices while cursors are open");
-		ret = EINVAL;
-		goto err;
-	}
-	while ((sdbc = TAILQ_FIRST(&sdbp->free_queue)) != NULL)
-		if ((ret = __db_c_destroy(sdbc)) != 0)
-			goto err;
+	sdbp->close = __db_secondary_close_pp;
 
 	F_SET(sdbp, DB_AM_SECONDARY);
 
@@ -920,19 +572,18 @@ __db_associate(dbp, txn, sdbp, callback, flags)
 	 */
 	build = 0;
 	if (LF_ISSET(DB_CREATE)) {
-		if ((ret = sdbp->cursor(sdbp, txn, &sdbc, 0)) != 0)
+		if ((ret = __db_cursor(sdbp, txn, &sdbc, 0)) != 0)
 			goto err;
 
-		memset(&key, 0, sizeof(DBT));
-		memset(&data, 0, sizeof(DBT));
-
 		/*
 		 * We don't care about key or data;  we're just doing
 		 * an existence check.
 		 */
+		memset(&key, 0, sizeof(DBT));
+		memset(&data, 0, sizeof(DBT));
 		F_SET(&key, DB_DBT_PARTIAL | DB_DBT_USERMEM);
 		F_SET(&data, DB_DBT_PARTIAL | DB_DBT_USERMEM);
-		if ((ret = sdbc->c_real_get(sdbc, &key, &data,
+		if ((ret = __db_c_get(sdbc, &key, &data,
 		    (STD_LOCKING(sdbc) ? DB_RMW : 0) |
 		    DB_FIRST)) == DB_NOTFOUND) {
 			build = 1;
@@ -943,8 +594,12 @@ __db_associate(dbp, txn, sdbp, callback, flags)
 		 * Secondary cursors have special refcounting close
 		 * methods.  Be careful.
 		 */
-		if ((t_ret = __db_c_close(sdbc)) != 0)
+		if ((t_ret = __db_c_close(sdbc)) != 0 && ret == 0)
 			ret = t_ret;
+
+		/* Reset for later error check. */
+		sdbc = NULL;
+
 		if (ret != 0)
 			goto err;
 	}
@@ -976,10 +631,10 @@ __db_associate(dbp, txn, sdbp, callback, flags)
 		 * as the secondary, so they won't conflict.  This should
 		 * be harmless even if we're not using CDB.
 		 */
-		if ((ret = sdbp->cursor(sdbp, txn, &sdbc,
+		if ((ret = __db_cursor(sdbp, txn, &sdbc,
 		    CDB_LOCKING(sdbp->dbenv) ? DB_WRITECURSOR : 0)) != 0)
 			goto err;
-		if ((ret = __db_icursor(dbp,
+		if ((ret = __db_cursor_int(dbp,
 		    txn, dbp->type, PGNO_INVALID, 0, sdbc->locker, &pdbc)) != 0)
 			goto err;
 
@@ -988,15 +643,14 @@ __db_associate(dbp, txn, sdbp, callback, flags)
 
 		memset(&key, 0, sizeof(DBT));
 		memset(&data, 0, sizeof(DBT));
-		while ((ret = pdbc->c_get(pdbc, &key, &data, DB_NEXT)) == 0) {
+		while ((ret = __db_c_get(pdbc, &key, &data, DB_NEXT)) == 0) {
 			memset(&skey, 0, sizeof(DBT));
 			if ((ret = callback(sdbp, &key, &data, &skey)) != 0) {
 				if (ret == DB_DONOTINDEX)
 					continue;
-				else
-					goto err;
+				goto err;
 			}
-			if ((ret = sdbc->c_put(sdbc,
+			if ((ret = __db_c_put(sdbc,
 			    &skey, &key, DB_UPDATE_SECONDARY)) != 0) {
 				FREE_IF_NEEDED(sdbp, &skey);
 				goto err;
@@ -1006,79 +660,16 @@ __db_associate(dbp, txn, sdbp, callback, flags)
 		}
 		if (ret == DB_NOTFOUND)
 			ret = 0;
-
-		if ((ret = sdbc->c_close(sdbc)) != 0)
-			goto err;
 	}
 
-err:	if (pdbc != NULL && (t_ret = pdbc->c_close(pdbc)) != 0 && ret == 0)
+err:	if (sdbc != NULL && (t_ret = __db_c_close(sdbc)) != 0 && ret == 0)
 		ret = t_ret;
 
-	dbp->associate_lid = DB_LOCK_INVALIDID;
-
-	if (txn_local) {
-		if (ret == 0)
-			ret = txn->commit(txn, 0);
-		else
-			if ((t_ret = txn->abort(txn)) != 0)
-				ret = __db_panic(dbenv, t_ret);
-	}
-
-	return (ret);
-}
-
-/*
- * __db_pget --
- *	Return a primary key/data pair given a secondary key.
- *
- * PUBLIC: int __db_pget __P((DB *, DB_TXN *, DBT *, DBT *, DBT *, u_int32_t));
- */
-int
-__db_pget(dbp, txn, skey, pkey, data, flags)
-	DB *dbp;
-	DB_TXN *txn;
-	DBT *skey, *pkey, *data;
-	u_int32_t flags;
-{
-	DBC *dbc;
-	int ret, t_ret;
-
-	PANIC_CHECK(dbp->dbenv);
-	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->pget");
-
-	if ((ret = __db_pgetchk(dbp, skey, pkey, data, flags)) != 0)
-		return (ret);
-
-	if ((ret = dbp->cursor(dbp, txn, &dbc, 0)) != 0)
-		return (ret);
-	SET_RET_MEM(dbc, dbp);
-
-	/*
-	 * The underlying cursor pget will fill in a default DBT for null
-	 * pkeys, and use the cursor's returned-key memory internally to
-	 * store any intermediate primary keys.  However, we've just set
-	 * the returned-key memory to the DB handle's key memory, which
-	 * is unsafe to use if the DB handle is threaded.  If the pkey
-	 * argument is NULL, use the DBC-owned returned-key memory
-	 * instead;  it'll go away when we close the cursor before we
-	 * return, but in this case that's just fine, as we're not
-	 * returning the primary key.
-	 */
-	if (pkey == NULL)
-		dbc->rkey = &dbc->my_rkey;
-
-	DEBUG_LREAD(dbc, txn, "__db_pget", skey, NULL, flags);
+	if (pdbc != NULL && (t_ret = __db_c_close(pdbc)) != 0 && ret == 0)
+		ret = t_ret;
 
-	/*
-	 * The cursor is just a perfectly ordinary secondary database
-	 * cursor.  Call its c_pget() method to do the dirty work.
-	 */
-	if (flags == 0 || flags == DB_RMW)
-		flags |= DB_SET;
-	ret = dbc->c_pget(dbc, skey, pkey, data, flags);
+	dbp->associate_lid = DB_LOCK_INVALIDID;
 
-	if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
-		ret = t_ret;
 	return (ret);
 }
 
@@ -1096,7 +687,7 @@ __db_secondary_get(sdbp, txn, skey, data, flags)
 {
 
 	DB_ASSERT(F_ISSET(sdbp, DB_AM_SECONDARY));
-	return (sdbp->pget(sdbp, txn, skey, NULL, data, flags));
+	return (__db_pget_pp(sdbp, txn, skey, NULL, data, flags));
 }
 
 /*
@@ -1104,8 +695,10 @@ __db_secondary_get(sdbp, txn, skey, data, flags)
  *	Wrapper function for DB->close() which we use on secondaries to
  *	manage refcounting and make sure we don't close them underneath
  *	a primary that is updating.
+ *
+ * PUBLIC: int __db_secondary_close __P((DB *, u_int32_t));
  */
-static int
+int
 __db_secondary_close(sdbp, flags)
 	DB *sdbp;
 	u_int32_t flags;
@@ -1138,7 +731,7 @@ __db_secondary_close(sdbp, flags)
 	 * sdbp->close is this function;  call the real one explicitly if
 	 * need be.
 	 */
-	return (doclose ? __db_close(sdbp, flags) : 0);
+	return (doclose ? __db_close(sdbp, NULL, flags) : 0);
 }
 
 /*
@@ -1179,12 +772,12 @@ __db_append_primary(dbc, key, data)
 		 * correctly-constructed full data item from this partial
 		 * put is on the page waiting for us.
 		 */
-		if ((ret = __db_c_idup(dbc, &pdbc, DB_POSITIONI)) != 0)
+		if ((ret = __db_c_idup(dbc, &pdbc, DB_POSITION)) != 0)
 			return (ret);
 		memset(&pkey, 0, sizeof(DBT));
 		memset(&pdata, 0, sizeof(DBT));
 
-		if ((ret = pdbc->c_get(pdbc, &pkey, &pdata, DB_CURRENT)) != 0)
+		if ((ret = __db_c_get(pdbc, &pkey, &pdata, DB_CURRENT)) != 0)
 			goto err;
 
 		key = &pkey;
@@ -1210,7 +803,7 @@ __db_append_primary(dbc, key, data)
 				goto err;
 		}
 
-		if ((ret = __db_icursor(sdbp, dbc->txn, sdbp->type,
+		if ((ret = __db_cursor_int(sdbp, dbc->txn, sdbp->type,
 		    PGNO_INVALID, 0, dbc->locker, &sdbc)) != 0) {
 			FREE_IF_NEEDED(sdbp, &skey);
 			goto err;
@@ -1230,7 +823,7 @@ __db_append_primary(dbc, key, data)
 		if (!F_ISSET(sdbp, DB_AM_DUP)) {
 			memset(&oldpkey, 0, sizeof(DBT));
 			F_SET(&oldpkey, DB_DBT_MALLOC);
-			ret = sdbc->c_real_get(sdbc, &skey, &oldpkey,
+			ret = __db_c_get(sdbc, &skey, &oldpkey,
 			    DB_SET | (STD_LOCKING(dbc) ? DB_RMW : 0));
 			if (ret == 0) {
 				cmp = __bam_defcmp(sdbp, &oldpkey, key);
@@ -1252,18 +845,18 @@ __db_append_primary(dbc, key, data)
 				goto err1;
 		}
 
-		ret = sdbc->c_put(sdbc, &skey, key, DB_UPDATE_SECONDARY);
+		ret = __db_c_put(sdbc, &skey, key, DB_UPDATE_SECONDARY);
 
 err1:		FREE_IF_NEEDED(sdbp, &skey);
 
-		if ((t_ret = sdbc->c_close(sdbc)) != 0 && ret == 0)
+		if ((t_ret = __db_c_close(sdbc)) != 0 && ret == 0)
 			ret = t_ret;
 
 		if (ret != 0)
 			goto err;
 	}
 
-err:	if (pdbc != NULL && (t_ret = pdbc->c_close(pdbc)) != 0 && ret == 0)
+err:	if (pdbc != NULL && (t_ret = __db_c_close(pdbc)) != 0 && ret == 0)
 		ret = t_ret;
 	if (sdbp != NULL && (t_ret = __db_s_done(sdbp)) != 0 && ret == 0)
 		ret = t_ret;
diff --git a/storage/bdb/db/db_cam.c b/storage/bdb/db/db_cam.c
index 4de3467d4aa8d1b1e94252a5294c1008fc262f4d..075765072d7915ff45c252f810d333c6f0649b97 100644
--- a/storage/bdb/db/db_cam.c
+++ b/storage/bdb/db/db_cam.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2000-2002
+ * Copyright (c) 2000-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_cam.c,v 11.156 2004/09/28 18:07:32 ubell Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_cam.c,v 11.114 2002/09/03 15:44:46 krinsky Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -23,7 +21,7 @@ static const char revid[] = "$Id: db_cam.c,v 11.114 2002/09/03 15:44:46 krinsky
 #include "dbinc/btree.h"
 #include "dbinc/hash.h"
 #include "dbinc/lock.h"
-#include "dbinc/log.h"
+#include "dbinc/mp.h"
 #include "dbinc/qam.h"
 
 static int __db_buildpartial __P((DB *, DBT *, DBT *, DBT *));
@@ -44,7 +42,7 @@ static int __db_wrlock_err __P((DB_ENV *));
 			return (__db_wrlock_err(dbp->dbenv));		\
 									\
 		if (F_ISSET(dbc, DBC_WRITECURSOR) &&			\
-		    (ret = (dbp)->dbenv->lock_get((dbp)->dbenv,		\
+		    (ret = __lock_get((dbp)->dbenv,			\
 		    (dbc)->locker, DB_LOCK_UPGRADE, &(dbc)->lock_dbt,	\
 		    DB_LOCK_WRITE, &(dbc)->mylock)) != 0)		\
 			return (ret);					\
@@ -54,23 +52,9 @@ static int __db_wrlock_err __P((DB_ENV *));
 	if (F_ISSET(dbc, DBC_WRITECURSOR))				\
 		(void)__lock_downgrade(					\
 		    (dbp)->dbenv, &(dbc)->mylock, DB_LOCK_IWRITE, 0);
-/*
- * Copy the lock info from one cursor to another, so that locking
- * in CDB can be done in the context of an internally-duplicated
- * or off-page-duplicate cursor.
- */
-#define	CDB_LOCKING_COPY(dbp, dbc_o, dbc_n)				\
-	if (CDB_LOCKING((dbp)->dbenv) &&				\
-	    F_ISSET((dbc_o), DBC_WRITECURSOR | DBC_WRITEDUP)) { \
-		memcpy(&(dbc_n)->mylock, &(dbc_o)->mylock,		\
-		    sizeof((dbc_o)->mylock));				\
-		/* This lock isn't ours to put--just discard it on close. */ \
-		F_SET((dbc_n), DBC_WRITEDUP);				\
-	}
-
 /*
  * __db_c_close --
- *	Close the cursor.
+ *	DBC->c_close.
  *
  * PUBLIC: int __db_c_close __P((DBC *));
  */
@@ -86,30 +70,14 @@ __db_c_close(dbc)
 
 	dbp = dbc->dbp;
 	dbenv = dbp->dbenv;
-	ret = 0;
-
-	PANIC_CHECK(dbenv);
-
-	/*
-	 * If the cursor is already closed we have a serious problem, and we
-	 * assume that the cursor isn't on the active queue.  Don't do any of
-	 * the remaining cursor close processing.
-	 */
-	if (!F_ISSET(dbc, DBC_ACTIVE)) {
-		if (dbp != NULL)
-			__db_err(dbenv, "Closing already-closed cursor");
-
-		DB_ASSERT(0);
-		return (EINVAL);
-	}
-
 	cp = dbc->internal;
 	opd = cp->opd;
+	ret = 0;
 
 	/*
 	 * Remove the cursor(s) from the active queue.  We may be closing two
 	 * cursors at once here, a top-level one and a lower-level, off-page
-	 * duplicate one.  The acess-method specific cursor close routine must
+	 * duplicate one.  The access-method specific cursor close routine must
 	 * close both of them in a single call.
 	 *
 	 * !!!
@@ -139,23 +107,18 @@ __db_c_close(dbc)
 	 */
 	if (CDB_LOCKING(dbenv)) {
 		/*
-		 * If DBC_WRITEDUP is set, the cursor is an internally
-		 * duplicated write cursor and the lock isn't ours to put.
-		 *
 		 * Also, be sure not to free anything if mylock.off is
 		 * INVALID;  in some cases, such as idup'ed read cursors
 		 * and secondary update cursors, a cursor in a CDB
 		 * environment may not have a lock at all.
 		 */
-		if (!F_ISSET(dbc, DBC_WRITEDUP) && LOCK_ISSET(dbc->mylock)) {
-			if ((t_ret = dbenv->lock_put(
-			    dbenv, &dbc->mylock)) != 0 && ret == 0)
-				ret = t_ret;
-		}
+		if ((t_ret = __LPUT(dbc, dbc->mylock)) != 0 && ret == 0)
+			ret = t_ret;
 
 		/* For safety's sake, since this is going on the free queue. */
 		memset(&dbc->mylock, 0, sizeof(dbc->mylock));
-		F_CLR(dbc, DBC_WRITEDUP);
+		if (opd != NULL)
+			memset(&opd->mylock, 0, sizeof(opd->mylock));
 	}
 
 	if (dbc->txn != NULL)
@@ -213,7 +176,7 @@ __db_c_destroy(dbc)
 	 */
 	if (LOCKING_ON(dbenv) &&
 	    F_ISSET(dbc, DBC_OWN_LID) &&
-	    (t_ret = dbenv->lock_id_free(dbenv, dbc->lid)) != 0 && ret == 0)
+	    (t_ret = __lock_id_free(dbenv, dbc->lid)) != 0 && ret == 0)
 		ret = t_ret;
 
 	__os_free(dbenv, dbc);
@@ -225,17 +188,18 @@ __db_c_destroy(dbc)
  * __db_c_count --
  *	Return a count of duplicate data items.
  *
- * PUBLIC: int __db_c_count __P((DBC *, db_recno_t *, u_int32_t));
+ * PUBLIC: int __db_c_count __P((DBC *, db_recno_t *));
  */
 int
-__db_c_count(dbc, recnop, flags)
+__db_c_count(dbc, recnop)
 	DBC *dbc;
 	db_recno_t *recnop;
-	u_int32_t flags;
 {
-	DB *dbp;
+	DB_ENV *dbenv;
 	int ret;
 
+	dbenv = dbc->dbp->dbenv;
+
 	/*
 	 * Cursor Cleanup Note:
 	 * All of the cursors passed to the underlying access methods by this
@@ -243,14 +207,6 @@ __db_c_count(dbc, recnop, flags)
 	 * So, pages/locks that the cursor references must be resolved by the
 	 * underlying functions.
 	 */
-	dbp = dbc->dbp;
-
-	PANIC_CHECK(dbp->dbenv);
-
-	/* Check for invalid flags. */
-	if ((ret = __db_ccountchk(dbp, flags, IS_INITIALIZED(dbc))) != 0)
-		return (ret);
-
 	switch (dbc->dbtype) {
 	case DB_QUEUE:
 	case DB_RECNO:
@@ -267,16 +223,16 @@ __db_c_count(dbc, recnop, flags)
 		if ((ret = __bam_c_count(dbc, recnop)) != 0)
 			return (ret);
 		break;
+	case DB_UNKNOWN:
 	default:
-		return (__db_unknown_type(dbp->dbenv,
-		    "__db_c_count", dbp->type));
+		return (__db_unknown_type(dbenv, "__db_c_count", dbc->dbtype));
 	}
 	return (0);
 }
 
 /*
  * __db_c_del --
- *	Delete using a cursor.
+ *	DBC->c_del.
  *
  * PUBLIC: int __db_c_del __P((DBC *, u_int32_t));
  */
@@ -287,7 +243,9 @@ __db_c_del(dbc, flags)
 {
 	DB *dbp;
 	DBC *opd;
-	int ret;
+	int ret, t_ret;
+
+	dbp = dbc->dbp;
 
 	/*
 	 * Cursor Cleanup Note:
@@ -296,19 +254,6 @@ __db_c_del(dbc, flags)
 	 * So, pages/locks that the cursor references must be resolved by the
 	 * underlying functions.
 	 */
-	dbp = dbc->dbp;
-
-	PANIC_CHECK(dbp->dbenv);
-
-	/* Check for invalid flags. */
-	if ((ret = __db_cdelchk(dbp, flags, IS_INITIALIZED(dbc))) != 0)
-		return (ret);
-
-	/* Check for consistent transaction usage. */
-	if ((ret = __db_check_txn(dbp, dbc->txn, dbc->locker, 0)) != 0)
-		return (ret);
-
-	DEBUG_LWRITE(dbc, dbc->txn, "db_c_del", NULL, NULL, flags);
 
 	CDB_LOCKING_INIT(dbp, dbc);
 
@@ -346,6 +291,22 @@ __db_c_del(dbc, flags)
 		if ((ret = dbc->c_am_writelock(dbc)) == 0)
 			ret = opd->c_am_del(opd);
 
+	/*
+	 * If this was an update that is supporting dirty reads
+	 * then we may have just swapped our read for a write lock
+	 * which is held by the surviving cursor.  We need
+	 * to explicitly downgrade this lock.  The closed cursor
+	 * may only have had a read lock.
+	 */
+	if (F_ISSET(dbc->dbp, DB_AM_DIRTY) &&
+	    dbc->internal->lock_mode == DB_LOCK_WRITE) {
+		if ((t_ret =
+		    __TLPUT(dbc, dbc->internal->lock)) != 0 && ret == 0)
+			ret = t_ret;
+		if (t_ret == 0)
+			dbc->internal->lock_mode = DB_LOCK_WWRITE;
+	}
+
 done:	CDB_LOCKING_DONE(dbp, dbc);
 
 	return (ret);
@@ -363,48 +324,16 @@ __db_c_dup(dbc_orig, dbcp, flags)
 	DBC **dbcp;
 	u_int32_t flags;
 {
-	DB_ENV *dbenv;
-	DB *dbp;
 	DBC *dbc_n, *dbc_nopd;
 	int ret;
 
-	dbp = dbc_orig->dbp;
-	dbenv = dbp->dbenv;
 	dbc_n = dbc_nopd = NULL;
 
-	PANIC_CHECK(dbp->dbenv);
-
-	/*
-	 * We can never have two write cursors open in CDB, so do not
-	 * allow duplication of a write cursor.
-	 */
-	if (flags != DB_POSITIONI &&
-	    F_ISSET(dbc_orig, DBC_WRITER | DBC_WRITECURSOR)) {
-		__db_err(dbenv, "Cannot duplicate writeable cursor");
-		return (EINVAL);
-	}
-
 	/* Allocate a new cursor and initialize it. */
 	if ((ret = __db_c_idup(dbc_orig, &dbc_n, flags)) != 0)
 		goto err;
 	*dbcp = dbc_n;
 
-	/*
-	 * If we're in CDB, and this isn't an internal duplication (in which
-	 * case we're explicitly overriding CDB locking), the duplicated
-	 * cursor needs its own read lock.  (We know it's not a write cursor
-	 * because we wouldn't have made it this far;  you can't dup them.)
-	 */
-	if (CDB_LOCKING(dbenv) && flags != DB_POSITIONI) {
-		DB_ASSERT(!F_ISSET(dbc_orig, DBC_WRITER | DBC_WRITECURSOR));
-
-		if ((ret = dbenv->lock_get(dbenv, dbc_n->locker, 0,
-		    &dbc_n->lock_dbt, DB_LOCK_READ, &dbc_n->mylock)) != 0) {
-			(void)__db_c_close(dbc_n);
-			return (ret);
-		}
-	}
-
 	/*
 	 * If the cursor references an off-page duplicate tree, allocate a
 	 * new cursor for that tree and initialize it.
@@ -415,15 +344,12 @@ __db_c_dup(dbc_orig, dbcp, flags)
 			goto err;
 		dbc_n->internal->opd = dbc_nopd;
 	}
-
-	/* Copy the dirty read flag to the new cursor. */
-	F_SET(dbc_n, F_ISSET(dbc_orig, DBC_DIRTY_READ));
 	return (0);
 
 err:	if (dbc_n != NULL)
-		(void)dbc_n->c_close(dbc_n);
+		(void)__db_c_close(dbc_n);
 	if (dbc_nopd != NULL)
-		(void)dbc_nopd->c_close(dbc_nopd);
+		(void)__db_c_close(dbc_nopd);
 
 	return (ret);
 }
@@ -447,13 +373,13 @@ __db_c_idup(dbc_orig, dbcp, flags)
 	dbp = dbc_orig->dbp;
 	dbc_n = *dbcp;
 
-	if ((ret = __db_icursor(dbp, dbc_orig->txn, dbc_orig->dbtype,
+	if ((ret = __db_cursor_int(dbp, dbc_orig->txn, dbc_orig->dbtype,
 	    dbc_orig->internal->root, F_ISSET(dbc_orig, DBC_OPD),
 	    dbc_orig->locker, &dbc_n)) != 0)
 		return (ret);
 
-	/* If the user wants the cursor positioned, do it here.  */
-	if (flags == DB_POSITION || flags == DB_POSITIONI) {
+	/* Position the cursor if requested, acquiring the necessary locks. */
+	if (flags == DB_POSITION) {
 		int_n = dbc_n->internal;
 		int_orig = dbc_orig->internal;
 
@@ -478,6 +404,7 @@ __db_c_idup(dbc_orig, dbcp, flags)
 			if ((ret = __ham_c_dup(dbc_orig, dbc_n)) != 0)
 				goto err;
 			break;
+		case DB_UNKNOWN:
 		default:
 			ret = __db_unknown_type(dbp->dbenv,
 			    "__db_c_idup", dbc_orig->dbtype);
@@ -485,16 +412,24 @@ __db_c_idup(dbc_orig, dbcp, flags)
 		}
 	}
 
-	/* Now take care of duping the CDB information. */
-	CDB_LOCKING_COPY(dbp, dbc_orig, dbc_n);
+	/* Copy the locking flags to the new cursor. */
+	F_SET(dbc_n,
+	    F_ISSET(dbc_orig, DBC_WRITECURSOR | DBC_DIRTY_READ | DBC_DEGREE_2));
 
-	/* Copy the dirty read flag to the new cursor. */
-	F_SET(dbc_n, F_ISSET(dbc_orig, DBC_DIRTY_READ));
+	/*
+	 * If we're in CDB and this isn't an offpage dup cursor, then
+	 * we need to get a lock for the duplicated cursor.
+	 */
+	if (CDB_LOCKING(dbp->dbenv) && !F_ISSET(dbc_n, DBC_OPD) &&
+	    (ret = __lock_get(dbp->dbenv, dbc_n->locker, 0,
+	    &dbc_n->lock_dbt, F_ISSET(dbc_orig, DBC_WRITECURSOR) ?
+	    DB_LOCK_IWRITE : DB_LOCK_READ, &dbc_n->mylock)) != 0)
+		goto err;
 
 	*dbcp = dbc_n;
 	return (0);
 
-err:	(void)dbc_n->c_close(dbc_n);
+err:	(void)__db_c_close(dbc_n);
 	return (ret);
 }
 
@@ -528,18 +463,10 @@ __db_c_newopd(dbc_parent, root, oldopd, dbcp)
 	 */
 	*dbcp = oldopd;
 
-	if ((ret = __db_icursor(dbp,
+	if ((ret = __db_cursor_int(dbp,
 	    dbc_parent->txn, dbtype, root, 1, dbc_parent->locker, &opd)) != 0)
 		return (ret);
 
-	/* !!!
-	 * If the parent is a DBC_WRITER, this won't copy anything.  That's
-	 * not actually a problem--we only need lock information in an
-	 * off-page dup cursor in order to upgrade at cursor close time
-	 * if we've done a delete, but WRITERs don't need to upgrade.
-	 */
-	CDB_LOCKING_COPY(dbp, dbc_parent, opd);
-
 	*dbcp = opd;
 
 	/*
@@ -554,7 +481,7 @@ __db_c_newopd(dbc_parent, root, oldopd, dbcp)
 	 * leave the main cursor in our caller with a non-NULL pointer
 	 * to a freed off-page dup cursor.
 	 */
-	if (oldopd != NULL && (ret = oldopd->c_close(oldopd)) != 0)
+	if (oldopd != NULL && (ret = __db_c_close(oldopd)) != 0)
 		return (ret);
 
 	return (0);
@@ -595,13 +522,6 @@ __db_c_get(dbc_arg, key, data, flags)
 	dbc_n = NULL;
 	opd = NULL;
 
-	PANIC_CHECK(dbp->dbenv);
-
-	/* Check for invalid flags. */
-	if ((ret =
-	    __db_cgetchk(dbp, key, data, flags, IS_INITIALIZED(dbc_arg))) != 0)
-		return (ret);
-
 	/* Clear OR'd in additional bits so we can check for flag equality. */
 	tmp_rmw = LF_ISSET(DB_RMW);
 	LF_CLR(DB_RMW);
@@ -612,9 +532,6 @@ __db_c_get(dbc_arg, key, data, flags)
 	multi = LF_ISSET(DB_MULTIPLE|DB_MULTIPLE_KEY);
 	LF_CLR(DB_MULTIPLE|DB_MULTIPLE_KEY);
 
-	DEBUG_LREAD(dbc_arg, dbc_arg->txn, "db_c_get",
-	    flags == DB_SET || flags == DB_SET_RANGE ? key : NULL, NULL, flags);
-
 	/*
 	 * Return a cursor's record number.  It has nothing to do with the
 	 * cursor get code except that it was put into the interface.
@@ -652,7 +569,7 @@ __db_c_get(dbc_arg, key, data, flags)
 	    flags == DB_NEXT || flags == DB_NEXT_DUP || flags == DB_PREV)) {
 		if (tmp_rmw && (ret = dbc_arg->c_am_writelock(dbc_arg)) != 0)
 			return (ret);
-		if ((ret = __db_c_idup(cp->opd, &opd, DB_POSITIONI)) != 0)
+		if ((ret = __db_c_idup(cp->opd, &opd, DB_POSITION)) != 0)
 			return (ret);
 
 		switch (ret =
@@ -666,7 +583,7 @@ __db_c_get(dbc_arg, key, data, flags)
 			 * the parent cursor.
 			 */
 			if (flags == DB_NEXT || flags == DB_PREV) {
-				if ((ret = opd->c_close(opd)) != 0)
+				if ((ret = __db_c_close(opd)) != 0)
 					goto err;
 				opd = NULL;
 				break;
@@ -689,7 +606,7 @@ __db_c_get(dbc_arg, key, data, flags)
 	case DB_NEXT_NODUP:
 	case DB_PREV:
 	case DB_PREV_NODUP:
-		tmp_flags = DB_POSITIONI;
+		tmp_flags = DB_POSITION;
 		break;
 	default:
 		tmp_flags = 0;
@@ -729,6 +646,7 @@ __db_c_get(dbc_arg, key, data, flags)
 		F_SET(dbc_n, DBC_MULTIPLE|DBC_MULTIPLE_KEY);
 		break;
 	case 0:
+	default:
 		break;
 	}
 
@@ -799,7 +717,7 @@ done:	/*
 	cp_n = dbc_n == NULL ? dbc_arg->internal : dbc_n->internal;
 	if (!F_ISSET(key, DB_DBT_ISSET)) {
 		if (cp_n->page == NULL && (ret =
-		    mpf->get(mpf, &cp_n->pgno, 0, &cp_n->page)) != 0)
+		    __memp_fget(mpf, &cp_n->pgno, 0, &cp_n->page)) != 0)
 			goto err;
 
 		if ((ret = __db_ret(dbp, cp_n->page, cp_n->indx,
@@ -818,13 +736,13 @@ done:	/*
 			 * has an open OPD cursor whose state might need to
 			 * be preserved.
 			 */
-			if ((!(multi & DB_MULTIPLE_KEY) && 
+			if ((!(multi & DB_MULTIPLE_KEY) &&
 			    dbc_arg->internal->opd == NULL) ||
 			    F_ISSET(dbc_arg, DBC_TRANSIENT))
 				dbc_n = dbc_arg;
 			else {
 				if ((ret = __db_c_idup(dbc_arg,
-				    &dbc_n, DB_POSITIONI)) != 0)
+				    &dbc_n, DB_POSITION)) != 0)
 					goto err;
 				if ((ret = dbc_n->c_am_get(dbc_n,
 				    key, data, DB_CURRENT, &pgno)) != 0)
@@ -849,7 +767,8 @@ done:	/*
 		 * get set up unless there is an error.  Assume success
 		 * here.  This is the only call to c_am_bulk, and it avoids
 		 * setting it exactly the same everywhere.  If we have an
-		 * ENOMEM error, it'll get overwritten with the needed value.
+		 * DB_BUFFER_SMALL error, it'll get overwritten with the
+		 * needed value.
 		 */
 		data->size = data->ulen;
 		ret = dbc_n->c_am_bulk(dbc_n, data, flags | multi);
@@ -867,6 +786,19 @@ err:	/* Don't pass DB_DBT_ISSET back to application level, error or no. */
 
 	/* Cleanup and cursor resolution. */
 	if (opd != NULL) {
+		/*
+		 * To support dirty reads we must reget the write lock
+		 * if we have just stepped off a deleted record.
+		 * Since the OPD cursor does not know anything
+		 * about the referencing page or cursor we need
+		 * to peek at the OPD cursor and get the lock here.
+		 */
+		if (F_ISSET(dbc_arg->dbp, DB_AM_DIRTY) &&
+		     F_ISSET((BTREE_CURSOR *)
+		     dbc_arg->internal->opd->internal, C_DELETED))
+			if ((t_ret =
+			    dbc_arg->c_am_writelock(dbc_arg)) != 0 && ret != 0)
+				ret = t_ret;
 		if ((t_ret = __db_c_cleanup(
 		    dbc_arg->internal->opd, opd, ret)) != 0 && ret == 0)
 			ret = t_ret;
@@ -893,9 +825,10 @@ __db_c_put(dbc_arg, key, data, flags)
 	DBT *key, *data;
 	u_int32_t flags;
 {
+	DB_ENV *dbenv;
 	DB *dbp, *sdbp;
 	DBC *dbc_n, *oldopd, *opd, *sdbc, *pdbc;
-	DBT olddata, oldpkey, oldskey, newdata, pkey, save_skey, skey, temp;
+	DBT olddata, oldpkey, oldskey, newdata, pkey, skey, temppkey, tempskey;
 	db_pgno_t pgno;
 	int cmp, have_oldrec, ispartial, nodel, re_pad, ret, rmw, t_ret;
 	u_int32_t re_len, size, tmp_flags;
@@ -910,20 +843,19 @@ __db_c_put(dbc_arg, key, data, flags)
 	 * functions.
 	 */
 	dbp = dbc_arg->dbp;
+	dbenv = dbp->dbenv;
 	sdbp = NULL;
 	pdbc = dbc_n = NULL;
 	memset(&newdata, 0, sizeof(DBT));
+	ret = 0;
 
-	PANIC_CHECK(dbp->dbenv);
-
-	/* Check for invalid flags. */
-	if ((ret = __db_cputchk(dbp,
-	    key, data, flags, IS_INITIALIZED(dbc_arg))) != 0)
-		return (ret);
-
-	/* Check for consistent transaction usage. */
-	if ((ret = __db_check_txn(dbp, dbc_arg->txn, dbc_arg->locker, 0)) != 0)
-		return (ret);
+	/*
+	 * We do multiple cursor operations in some cases and subsequently
+	 * access the data DBT information.  Set DB_DBT_MALLOC so we don't risk
+	 * modification of the data between our uses of it.
+	 */
+	memset(&olddata, 0, sizeof(DBT));
+	F_SET(&olddata, DB_DBT_MALLOC);
 
 	/*
 	 * Putting to secondary indices is forbidden;  when we need
@@ -934,10 +866,6 @@ __db_c_put(dbc_arg, key, data, flags)
 	if (flags == DB_UPDATE_SECONDARY)
 		flags = DB_KEYLAST;
 
-	DEBUG_LWRITE(dbc_arg, dbc_arg->txn, "db_c_put",
-	    flags == DB_KEYFIRST || flags == DB_KEYLAST ||
-	    flags == DB_NODUPDATA ? key : NULL, data, flags);
-
 	CDB_LOCKING_INIT(dbp, dbc_arg);
 
 	/*
@@ -1006,7 +934,6 @@ __db_c_put(dbc_arg, key, data, flags)
 	 *    the old secondary in each.
 	 */
 	memset(&pkey, 0, sizeof(DBT));
-	memset(&olddata, 0, sizeof(DBT));
 	have_oldrec = nodel = 0;
 
 	/*
@@ -1033,22 +960,23 @@ __db_c_put(dbc_arg, key, data, flags)
 		 * writing soon enough in the "normal" put code.  In
 		 * transactional databases we'll hold those write locks
 		 * even if we close the cursor we're reading with.
+		 *
+		 * The DB_KEYEMPTY return needs special handling -- if the
+		 * cursor is on a deleted key, we return DB_NOTFOUND.
 		 */
-		ret = dbc_arg->c_get(dbc_arg,
-		    &pkey, &olddata, rmw | DB_CURRENT);
-		if (ret == DB_KEYEMPTY) {
-			nodel = 1;	 /*
-					  * We know we don't need a delete
-					  * in the secondary.
-					  */
-			have_oldrec = 1; /* We've looked for the old record. */
-		} else if (ret != 0)
+		ret = __db_c_get(dbc_arg, &pkey, &olddata, rmw | DB_CURRENT);
+		if (ret == DB_KEYEMPTY)
+			ret = DB_NOTFOUND;
+		if (ret != 0)
 			goto err;
-		else
-			have_oldrec = 1;
 
+		have_oldrec = 1; /* We've looked for the old record. */
 	} else {
-		/* So we can just use &pkey everywhere instead of key. */
+		/*
+		 * Set pkey so we can use &pkey everywhere instead of key.
+		 * If DB_CURRENT is set and there is a key at the current
+		 * location, pkey will be overwritten before it's used.
+		 */
 		pkey.data = key->data;
 		pkey.size = key->size;
 	}
@@ -1069,13 +997,12 @@ __db_c_put(dbc_arg, key, data, flags)
 			/* We should have gotten DB_CURRENT in step 1. */
 			DB_ASSERT(flags != DB_CURRENT);
 
-			ret = pdbc->c_get(pdbc,
-			    &pkey, &olddata, rmw | DB_SET);
+			ret = __db_c_get(pdbc, &pkey, &olddata, rmw | DB_SET);
 			if (ret == DB_KEYEMPTY || ret == DB_NOTFOUND) {
 				nodel = 1;
 				ret = 0;
 			}
-			if ((t_ret = pdbc->c_close(pdbc)) != 0)
+			if ((t_ret = __db_c_close(pdbc)) != 0)
 				ret = t_ret;
 			if (ret != 0)
 				goto err;
@@ -1112,10 +1039,7 @@ __db_c_put(dbc_arg, key, data, flags)
 
 		size = ispartial ? newdata.size : data->size;
 		if (size > re_len) {
-			__db_err(dbp->dbenv,
-			    "Length improper for fixed length record %lu",
-			    (u_long)size);
-			ret = EINVAL;
+			ret = __db_rec_toobig(dbenv, size, re_len);
 			goto err;
 		} else if (size < re_len) {
 			/*
@@ -1129,8 +1053,8 @@ __db_c_put(dbc_arg, key, data, flags)
 			 *
 			 * Either way, realloc is safe.
 			 */
-			if ((ret = __os_realloc(dbp->dbenv, re_len,
-			    &newdata.data)) != 0)
+			if ((ret =
+			    __os_realloc(dbenv, re_len, &newdata.data)) != 0)
 				goto err;
 			if (!ispartial)
 				memcpy(newdata.data, data->data, size);
@@ -1168,15 +1092,6 @@ __db_c_put(dbc_arg, key, data, flags)
 				goto err;
 		}
 
-		/*
-		 * Save the DBT we just got back from the callback function
-		 * off;  we want to pass its value into c_get functions
-		 * that may stomp on a buffer the callback function
-		 * allocated.
-		 */
-		memset(&save_skey, 0, sizeof(DBT));	/* Paranoia. */
-		save_skey = skey;
-
 		/*
 		 * Open a cursor in this secondary.
 		 *
@@ -1185,7 +1100,7 @@ __db_c_put(dbc_arg, key, data, flags)
 		 * or if we're subdatabases that share and want to lock a
 		 * metadata page).
 		 */
-		if ((ret = __db_icursor(sdbp, dbc_arg->txn, sdbp->type,
+		if ((ret = __db_cursor_int(sdbp, dbc_arg->txn, sdbp->type,
 		    PGNO_INVALID, 0, dbc_arg->locker, &sdbc)) != 0)
 			goto err;
 
@@ -1198,7 +1113,7 @@ __db_c_put(dbc_arg, key, data, flags)
 		 * routine won't try to put anything because we don't
 		 * really have a lock.
 		 */
-		if (CDB_LOCKING(sdbp->dbenv)) {
+		if (CDB_LOCKING(dbenv)) {
 			DB_ASSERT(sdbc->mylock.off == LOCK_INVALID);
 			F_SET(sdbc, DBC_WRITER);
 		}
@@ -1219,8 +1134,8 @@ __db_c_put(dbc_arg, key, data, flags)
 		 *	duplicate, because the matching old and new secondaries
 		 *	will prevent us from deleting anything and we'll
 		 *	wind up with two secondary records that point to the
-		 *	same primary key.  Do a c_get(DB_GET_BOTH);  if
-		 *	that returns 0, skip the put.
+		 *	same primary key.  Do a c_get(DB_GET_BOTH);  only
+		 *	do the put if the secondary doesn't exist.
 		 * 3) The secondary doesn't support duplicates at all.
 		 *	In this case, secondary keys must be unique;  if
 		 *	another primary key already exists for this
@@ -1236,13 +1151,13 @@ __db_c_put(dbc_arg, key, data, flags)
 			/* Case 3. */
 			memset(&oldpkey, 0, sizeof(DBT));
 			F_SET(&oldpkey, DB_DBT_MALLOC);
-			ret = sdbc->c_real_get(sdbc,
+			ret = __db_c_get(sdbc,
 			    &skey, &oldpkey, rmw | DB_SET);
 			if (ret == 0) {
 				cmp = __bam_defcmp(sdbp, &oldpkey, &pkey);
-				__os_ufree(sdbp->dbenv, oldpkey.data);
+				__os_ufree(dbenv, oldpkey.data);
 				if (cmp != 0) {
-					__db_err(sdbp->dbenv, "%s%s",
+					__db_err(dbenv, "%s%s",
 			    "Put results in a non-unique secondary key in an ",
 			    "index not configured to support duplicates");
 					ret = EINVAL;
@@ -1250,13 +1165,21 @@ __db_c_put(dbc_arg, key, data, flags)
 				}
 			} else if (ret != DB_NOTFOUND && ret != DB_KEYEMPTY)
 				goto skipput;
-		} else if (!F_ISSET(sdbp, DB_AM_DUPSORT))
+		} else if (!F_ISSET(sdbp, DB_AM_DUPSORT)) {
 			/* Case 2. */
-			if ((ret = sdbc->c_real_get(sdbc,
-			    &skey, &pkey, rmw | DB_GET_BOTH)) == 0)
+			memset(&tempskey, 0, sizeof(DBT));
+			tempskey.data = skey.data;
+			tempskey.size = skey.size;
+			memset(&temppkey, 0, sizeof(DBT));
+			temppkey.data = pkey.data;
+			temppkey.size = pkey.size;
+			ret = __db_c_get(sdbc, &tempskey, &temppkey,
+			    rmw | DB_GET_BOTH);
+			if (ret != DB_NOTFOUND && ret != DB_KEYEMPTY)
 				goto skipput;
+		}
 
-		ret = sdbc->c_put(sdbc, &skey, &pkey, DB_UPDATE_SECONDARY);
+		ret = __db_c_put(sdbc, &skey, &pkey, DB_UPDATE_SECONDARY);
 
 		/*
 		 * We don't know yet whether this was a put-overwrite that
@@ -1266,9 +1189,9 @@ __db_c_put(dbc_arg, key, data, flags)
 		if (ret == DB_KEYEXIST)
 			ret = 0;
 
-skipput:	FREE_IF_NEEDED(sdbp, &save_skey)
+skipput:	FREE_IF_NEEDED(sdbp, &skey)
 
-		if ((t_ret = sdbc->c_close(sdbc)) != 0)
+		if ((t_ret = __db_c_close(sdbc)) != 0 && ret == 0)
 			ret = t_ret;
 
 		if (ret != 0)
@@ -1285,12 +1208,12 @@ skipput:	FREE_IF_NEEDED(sdbp, &save_skey)
 		DB_ASSERT(flags != DB_CURRENT);
 		pkey.data = key->data;
 		pkey.size = key->size;
-		ret = pdbc->c_get(pdbc, &pkey, &olddata, rmw | DB_SET);
+		ret = __db_c_get(pdbc, &pkey, &olddata, rmw | DB_SET);
 		if (ret == DB_KEYEMPTY || ret == DB_NOTFOUND) {
 			nodel = 1;
 			ret = 0;
 		}
-		if ((t_ret = pdbc->c_close(pdbc)) != 0)
+		if ((t_ret = __db_c_close(pdbc)) != 0 && ret == 0)
 			ret = t_ret;
 		if (ret != 0)
 			goto err;
@@ -1323,6 +1246,7 @@ skipput:	FREE_IF_NEEDED(sdbp, &save_skey)
 			else
 				goto err;
 		}
+		memset(&skey, 0, sizeof(DBT));
 		if ((ret = sdbp->s_callback(sdbp,
 		    &pkey, ispartial ? &newdata : data, &skey)) != 0 &&
 		    ret != DB_DONOTINDEX)
@@ -1340,31 +1264,36 @@ skipput:	FREE_IF_NEEDED(sdbp, &save_skey)
 		if (ret == DB_DONOTINDEX ||
 		    ((BTREE *)sdbp->bt_internal)->bt_compare(sdbp,
 		    &oldskey, &skey) != 0) {
-			if ((ret = __db_icursor(sdbp, dbc_arg->txn, sdbp->type,
+			if ((ret = __db_cursor_int(
+			    sdbp, dbc_arg->txn, sdbp->type,
 			    PGNO_INVALID, 0, dbc_arg->locker, &sdbc)) != 0)
 				goto err;
-			if (CDB_LOCKING(sdbp->dbenv)) {
+			if (CDB_LOCKING(dbenv)) {
 				DB_ASSERT(sdbc->mylock.off == LOCK_INVALID);
 				F_SET(sdbc, DBC_WRITER);
 			}
 
 			/*
 			 * Don't let c_get(DB_GET_BOTH) stomp on
-			 * any secondary key value that the callback
-			 * function may have allocated.  Use a temp
-			 * DBT instead.
+			 * our data.  Use a temp DBT instead.
 			 */
-			memset(&temp, 0, sizeof(DBT));
-			temp.data = oldskey.data;
-			temp.size = oldskey.size;
-			if ((ret = sdbc->c_real_get(sdbc,
-			    &temp, &pkey, rmw | DB_GET_BOTH)) == 0)
-				ret = sdbc->c_del(sdbc, DB_UPDATE_SECONDARY);
+			memset(&tempskey, 0, sizeof(DBT));
+			tempskey.data = oldskey.data;
+			tempskey.size = oldskey.size;
+			memset(&temppkey, 0, sizeof(DBT));
+			temppkey.data = pkey.data;
+			temppkey.size = pkey.size;
+			if ((ret = __db_c_get(sdbc,
+			    &tempskey, &temppkey, rmw | DB_GET_BOTH)) == 0)
+				ret = __db_c_del(sdbc, DB_UPDATE_SECONDARY);
+			else if (ret == DB_NOTFOUND)
+				ret = __db_secondary_corrupt(dbp);
 		}
 
 		FREE_IF_NEEDED(sdbp, &skey);
 		FREE_IF_NEEDED(sdbp, &oldskey);
-		if (sdbc != NULL && (t_ret = sdbc->c_close(sdbc)) != 0)
+		if (sdbc != NULL && (t_ret = __db_c_close(sdbc)) != 0 &&
+		    ret == 0)
 			ret = t_ret;
 		if (ret != 0)
 			goto err;
@@ -1401,7 +1330,7 @@ skip_s_update:
 
 		if ((ret = dbc_arg->c_am_writelock(dbc_arg)) != 0)
 			return (ret);
-		if ((ret = __db_c_dup(dbc_arg, &dbc_n, DB_POSITIONI)) != 0)
+		if ((ret = __db_c_dup(dbc_arg, &dbc_n, DB_POSITION)) != 0)
 			goto err;
 		opd = dbc_n->internal->opd;
 		if ((ret = opd->c_am_put(
@@ -1417,9 +1346,9 @@ skip_s_update:
 	 * XXX: MARGO
 	 *
 	tmp_flags = flags == DB_AFTER ||
-	    flags == DB_BEFORE || flags == DB_CURRENT ? DB_POSITIONI : 0;
+	    flags == DB_BEFORE || flags == DB_CURRENT ? DB_POSITION : 0;
 	 */
-	tmp_flags = DB_POSITIONI;
+	tmp_flags = DB_POSITION;
 
 	/*
 	 * If this cursor is going to be closed immediately, we don't
@@ -1457,14 +1386,16 @@ err:	/* Cleanup and cursor resolution. */
 	if ((t_ret = __db_c_cleanup(dbc_arg, dbc_n, ret)) != 0 && ret == 0)
 		ret = t_ret;
 
-	/* If newdata was used, free its buffer. */
+	/* If newdata or olddata were used, free their buffers. */
 	if (newdata.data != NULL)
-		__os_free(dbp->dbenv, newdata.data);
+		__os_free(dbenv, newdata.data);
+	if (olddata.data != NULL)
+		__os_ufree(dbenv, olddata.data);
 
 	CDB_LOCKING_DONE(dbp, dbc_arg);
 
-	if (sdbp != NULL && (t_ret = __db_s_done(sdbp)) != 0)
-		return (t_ret);
+	if (sdbp != NULL && (t_ret = __db_s_done(sdbp)) != 0 && ret == 0)
+		ret = t_ret;
 
 	return (ret);
 }
@@ -1520,16 +1451,17 @@ __db_c_cleanup(dbc, dbc_n, failed)
 
 	/* Discard any pages we're holding. */
 	if (internal->page != NULL) {
-		if ((t_ret = mpf->put(mpf, internal->page, 0)) != 0 && ret == 0)
+		if ((t_ret =
+		    __memp_fput(mpf, internal->page, 0)) != 0 && ret == 0)
 			ret = t_ret;
 		internal->page = NULL;
 	}
 	opd = internal->opd;
 	if (opd != NULL && opd->internal->page != NULL) {
 		if ((t_ret =
-		    mpf->put(mpf, opd->internal->page, 0)) != 0 && ret == 0)
+		    __memp_fput(mpf, opd->internal->page, 0)) != 0 && ret == 0)
 			ret = t_ret;
-		 opd->internal->page = NULL;
+		opd->internal->page = NULL;
 	}
 
 	/*
@@ -1550,15 +1482,15 @@ __db_c_cleanup(dbc, dbc_n, failed)
 		return (ret);
 
 	if (dbc_n->internal->page != NULL) {
-		if ((t_ret =
-		    mpf->put(mpf, dbc_n->internal->page, 0)) != 0 && ret == 0)
+		if ((t_ret = __memp_fput(
+		    mpf, dbc_n->internal->page, 0)) != 0 && ret == 0)
 			ret = t_ret;
 		dbc_n->internal->page = NULL;
 	}
 	opd = dbc_n->internal->opd;
 	if (opd != NULL && opd->internal->page != NULL) {
 		if ((t_ret =
-		    mpf->put(mpf, opd->internal->page, 0)) != 0 && ret == 0)
+		    __memp_fput(mpf, opd->internal->page, 0)) != 0 && ret == 0)
 			ret = t_ret;
 		opd->internal->page = NULL;
 	}
@@ -1588,28 +1520,44 @@ __db_c_cleanup(dbc, dbc_n, failed)
 	 * We might want to consider adding a flag to the cursor, so that any
 	 * subsequent operations other than close just return an error?
 	 */
-	if ((t_ret = dbc_n->c_close(dbc_n)) != 0 && ret == 0)
+	if ((t_ret = __db_c_close(dbc_n)) != 0 && ret == 0)
 		ret = t_ret;
 
+	/*
+	 * If this was an update that is supporting dirty reads
+	 * then we may have just swapped our read for a write lock
+	 * which is held by the surviving cursor.  We need
+	 * to explicitly downgrade this lock.  The closed cursor
+	 * may only have had a read lock.
+	 */
+	if (F_ISSET(dbp, DB_AM_DIRTY) &&
+	    dbc->internal->lock_mode == DB_LOCK_WRITE) {
+		if ((t_ret =
+		    __TLPUT(dbc, dbc->internal->lock)) != 0 && ret == 0)
+			ret = t_ret;
+		if (t_ret == 0)
+			dbc->internal->lock_mode = DB_LOCK_WWRITE;
+	}
+
 	return (ret);
 }
 
 /*
- * __db_c_secondary_get --
+ * __db_c_secondary_get_pp --
  *	This wrapper function for DBC->c_pget() is the DBC->c_get() function
  *	for a secondary index cursor.
  *
- * PUBLIC: int __db_c_secondary_get __P((DBC *, DBT *, DBT *, u_int32_t));
+ * PUBLIC: int __db_c_secondary_get_pp __P((DBC *, DBT *, DBT *, u_int32_t));
  */
 int
-__db_c_secondary_get(dbc, skey, data, flags)
+__db_c_secondary_get_pp(dbc, skey, data, flags)
 	DBC *dbc;
 	DBT *skey, *data;
 	u_int32_t flags;
 {
 
 	DB_ASSERT(F_ISSET(dbc->dbp, DB_AM_SECONDARY));
-	return (dbc->c_pget(dbc, skey, NULL, data, flags));
+	return (__db_c_pget_pp(dbc, skey, NULL, data, flags));
 }
 
 /*
@@ -1627,17 +1575,13 @@ __db_c_pget(dbc, skey, pkey, data, flags)
 	DB *pdbp, *sdbp;
 	DBC *pdbc;
 	DBT *save_rdata, nullpkey;
-	int pkeymalloc, ret, save_pkey_flags, t_ret;
+	u_int32_t save_pkey_flags;
+	int pkeymalloc, ret, t_ret;
 
 	sdbp = dbc->dbp;
 	pdbp = sdbp->s_primary;
 	pkeymalloc = t_ret = 0;
 
-	PANIC_CHECK(sdbp->dbenv);
-	if ((ret = __db_cpgetchk(sdbp,
-	    skey, pkey, data, flags, IS_INITIALIZED(dbc))) != 0)
-		return (ret);
-
 	/*
 	 * The challenging part of this function is getting the behavior
 	 * right for all the various permutations of DBT flags.  The
@@ -1711,7 +1655,7 @@ __db_c_pget(dbc, skey, pkey, data, flags)
 	 * on the flags, but the underlying cursor get will take care of the
 	 * dirty work.)
 	 */
-	if ((ret = dbc->c_real_get(dbc, skey, pkey, flags)) != 0) {
+	if ((ret = __db_c_get(dbc, skey, pkey, flags)) != 0) {
 		/* Restore rskey/rkey/rdata and return. */
 		pkey->flags = save_pkey_flags;
 		dbc->rskey = dbc->rkey;
@@ -1750,13 +1694,13 @@ __db_c_pget(dbc, skey, pkey, data, flags)
 	 * (depending on the comparison function), but this is safe.
 	 *
 	 * !!!
-	 * We need to use __db_icursor here rather than simply calling
+	 * We need to use __db_cursor_int here rather than simply calling
 	 * pdbp->cursor, because otherwise, if we're in CDB, we'll
 	 * allocate a new locker ID and leave ourselves open to deadlocks.
 	 * (Even though we're only acquiring read locks, we'll still block
 	 * if there are any waiters.)
 	 */
-	if ((ret = __db_icursor(pdbp,
+	if ((ret = __db_cursor_int(pdbp,
 	    dbc->txn, pdbp->type, PGNO_INVALID, 0, dbc->locker, &pdbc)) != 0)
 		goto err;
 
@@ -1785,7 +1729,7 @@ __db_c_pget(dbc, skey, pkey, data, flags)
 	 */
 	F_SET(pdbc, DBC_TRANSIENT);
 	SET_RET_MEM(pdbc, dbc);
-	ret = pdbc->c_get(pdbc, pkey, data, DB_SET);
+	ret = __db_c_get(pdbc, pkey, data, DB_SET);
 
 	/*
 	 * If the item wasn't found in the primary, this is a bug;
@@ -1797,7 +1741,7 @@ __db_c_pget(dbc, skey, pkey, data, flags)
 		ret = __db_secondary_corrupt(pdbp);
 
 	/* Now close the primary cursor. */
-	t_ret = pdbc->c_close(pdbc);
+	t_ret = __db_c_close(pdbc);
 
 err:	if (pkeymalloc) {
 		/*
@@ -1858,7 +1802,7 @@ __db_c_pget_recno(sdbc, pkey, data, flags)
 		 */
 		memset(&primary_key, 0, sizeof(DBT));
 		F_SET(&primary_key, DB_DBT_MALLOC);
-		if ((ret = sdbc->c_real_get(sdbc,
+		if ((ret = __db_c_get(sdbc,
 		    &discardme, &primary_key, rmw | DB_CURRENT)) != 0)
 			return (ret);
 
@@ -1866,24 +1810,24 @@ __db_c_pget_recno(sdbc, pkey, data, flags)
 		 * Open a cursor on the primary, set it to the right record,
 		 * and fetch its recno into "data".
 		 *
-		 * (See __db_c_pget for a comment on the use of __db_icursor.)
+		 * (See __db_c_pget for comments on the use of __db_cursor_int.)
 		 *
 		 * SET_RET_MEM so that the secondary DBC owns any returned-data
 		 * memory.
 		 */
-		if ((ret = __db_icursor(pdbp, sdbc->txn,
+		if ((ret = __db_cursor_int(pdbp, sdbc->txn,
 		    pdbp->type, PGNO_INVALID, 0, sdbc->locker, &pdbc)) != 0)
 			goto perr;
 		SET_RET_MEM(pdbc, sdbc);
-		if ((ret = pdbc->c_get(pdbc,
+		if ((ret = __db_c_get(pdbc,
 		    &primary_key, &discardme, rmw | DB_SET)) != 0)
 			goto perr;
 
-		ret = pdbc->c_get(pdbc, &discardme, data, rmw | DB_GET_RECNO);
+		ret = __db_c_get(pdbc, &discardme, data, rmw | DB_GET_RECNO);
 
 perr:		__os_ufree(sdbp->dbenv, primary_key.data);
 		if (pdbc != NULL &&
-		    (t_ret = pdbc->c_close(pdbc)) != 0 && ret == 0)
+		    (t_ret = __db_c_close(pdbc)) != 0 && ret == 0)
 			ret = t_ret;
 		if (ret != 0)
 			return (ret);
@@ -1898,7 +1842,7 @@ perr:		__os_ufree(sdbp->dbenv, primary_key.data);
 	 * If it's not an rbtree, return RECNO_OOB in "pkey".
 	 */
 	if (F_ISSET(sdbp, DB_AM_RECNUM))
-		return (sdbc->c_real_get(sdbc, &discardme, pkey, flags));
+		return (__db_c_get(sdbc, &discardme, pkey, flags));
 	else
 		return (__db_retcopy(dbenv, pkey, &oob,
 		    sizeof(oob), &sdbc->rdata->data, &sdbc->rdata->ulen));
@@ -1924,7 +1868,6 @@ __db_wrlock_err(dbenv)
  *	Note that deleting the primary record will call c_del on all
  *	the secondaries, including this one;  thus, it is not necessary
  *	to execute both this function and an actual delete.
- *
  */
 static int
 __db_c_del_secondary(dbc)
@@ -1944,8 +1887,7 @@ __db_c_del_secondary(dbc)
 	 * the primary.
 	 */
 	F_SET(&skey, DB_DBT_PARTIAL | DB_DBT_USERMEM);
-	if ((ret = dbc->c_real_get(dbc,
-	    &skey, &pkey, DB_CURRENT)) != 0)
+	if ((ret = __db_c_get(dbc, &skey, &pkey, DB_CURRENT)) != 0)
 		return (ret);
 
 	/*
@@ -1959,7 +1901,7 @@ __db_c_del_secondary(dbc)
 	 * anyway.
 	 */
 	pdbp = dbc->dbp->s_primary;
-	if ((ret = __db_icursor(pdbp, dbc->txn,
+	if ((ret = __db_cursor_int(pdbp, dbc->txn,
 	    pdbp->type, PGNO_INVALID, 0, dbc->locker, &pdbc)) != 0)
 		return (ret);
 
@@ -1983,13 +1925,13 @@ __db_c_del_secondary(dbc)
 	 * every record in the secondary should correspond to some record
 	 * in the primary.
 	 */
-	if ((ret = pdbc->c_get(pdbc, &pkey, &skey,
+	if ((ret = __db_c_get(pdbc, &pkey, &skey,
 	    (STD_LOCKING(dbc) ? DB_RMW : 0) | DB_SET)) == 0)
-		ret = pdbc->c_del(pdbc, 0);
+		ret = __db_c_del(pdbc, 0);
 	else if (ret == DB_NOTFOUND)
 		ret = __db_secondary_corrupt(pdbp);
 
-	if ((t_ret = pdbc->c_close(pdbc)) != 0 && ret != 0)
+	if ((t_ret = __db_c_close(pdbc)) != 0 && ret == 0)
 		ret = t_ret;
 
 	return (ret);
@@ -2010,7 +1952,7 @@ __db_c_del_primary(dbc)
 {
 	DB *dbp, *sdbp;
 	DBC *sdbc;
-	DBT data, pkey, skey, temp;
+	DBT data, pkey, skey, temppkey, tempskey;
 	int ret, t_ret;
 
 	dbp = dbc->dbp;
@@ -2023,7 +1965,7 @@ __db_c_del_primary(dbc)
 	 */
 	memset(&pkey, 0, sizeof(DBT));
 	memset(&data, 0, sizeof(DBT));
-	if ((ret = dbc->c_get(dbc, &pkey, &data, DB_CURRENT)) != 0)
+	if ((ret = __db_c_get(dbc, &pkey, &data, DB_CURRENT)) != 0)
 		return (ret);
 
 	for (sdbp = __db_s_first(dbp);
@@ -2047,7 +1989,7 @@ __db_c_del_primary(dbc)
 		}
 
 		/* Open a secondary cursor. */
-		if ((ret = __db_icursor(sdbp, dbc->txn, sdbp->type,
+		if ((ret = __db_cursor_int(sdbp, dbc->txn, sdbp->type,
 		    PGNO_INVALID, 0, dbc->locker, &sdbc)) != 0)
 			goto done;
 		/* See comment above and in __db_c_put. */
@@ -2065,26 +2007,32 @@ __db_c_del_primary(dbc)
 		 *
 		 * !!!
 		 * Don't stomp on any callback-allocated buffer in skey
-		 * when we do a c_get(DB_GET_BOTH);  use a temp DBT instead.
+		 * when we do a c_get(DB_GET_BOTH); use a temp DBT instead.
+		 * Similarly, don't allow pkey to be invalidated when the
+		 * cursor is closed.
 		 */
-		memset(&temp, 0, sizeof(DBT));
-		temp.data = skey.data;
-		temp.size = skey.size;
-		if ((ret = sdbc->c_real_get(sdbc, &temp, &pkey,
+		memset(&tempskey, 0, sizeof(DBT));
+		tempskey.data = skey.data;
+		tempskey.size = skey.size;
+		memset(&temppkey, 0, sizeof(DBT));
+		temppkey.data = pkey.data;
+		temppkey.size = pkey.size;
+		if ((ret = __db_c_get(sdbc, &tempskey, &temppkey,
 		    (STD_LOCKING(dbc) ? DB_RMW : 0) | DB_GET_BOTH)) == 0)
-			ret = sdbc->c_del(sdbc, DB_UPDATE_SECONDARY);
+			ret = __db_c_del(sdbc, DB_UPDATE_SECONDARY);
+		else if (ret == DB_NOTFOUND)
+			ret = __db_secondary_corrupt(dbp);
 
 		FREE_IF_NEEDED(sdbp, &skey);
 
-		if ((t_ret = sdbc->c_close(sdbc)) != 0 || ret != 0) {
-			if (ret == 0)
-				ret = t_ret;
+		if ((t_ret = __db_c_close(sdbc)) != 0 && ret == 0)
+			ret = t_ret;
+		if (ret != 0)
 			goto done;
-		}
 	}
 
 done:	if (sdbp != NULL && (t_ret = __db_s_done(sdbp)) != 0 && ret == 0)
-		return (t_ret);
+		ret = t_ret;
 	return (ret);
 }
 
@@ -2167,7 +2115,7 @@ __db_s_next(sdbpp)
 	/*
 	 * closeme->close() is a wrapper;  call __db_close explicitly.
 	 */
-	ret = closeme != NULL ? __db_close(closeme, 0) : 0;
+	ret = closeme != NULL ? __db_close(closeme, NULL, 0) : 0;
 	return (ret);
 }
 
@@ -2196,7 +2144,7 @@ __db_s_done(sdbp)
 	}
 	MUTEX_THREAD_UNLOCK(pdbp->dbenv, pdbp->mutexp);
 
-	return (doclose ? __db_close(sdbp, 0) : 0);
+	return (doclose ? __db_close(sdbp, NULL, 0) : 0);
 }
 
 /*
diff --git a/storage/bdb/db/db_conv.c b/storage/bdb/db/db_conv.c
index f731c82d85e36760ddf6c1ee9f31150a89da4cf3..b4c5c9a29ec7df10ed73a1b4504c3e7c62d92c0e 100644
--- a/storage/bdb/db/db_conv.c
+++ b/storage/bdb/db/db_conv.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -35,14 +35,12 @@
  * 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.
+ *
+ * $Id: db_conv.c,v 11.45 2004/01/28 03:35:57 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_conv.c,v 11.38 2002/08/15 03:00:13 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -100,6 +98,8 @@ __db_pgin(dbenv, pg, pp, cookie)
 		 */
 		if (FLD_ISSET(((DBMETA *)pp)->metaflags, DBMETA_CHKSUM))
 			F_SET(dbp, DB_AM_CHKSUM);
+		else
+			F_CLR(dbp, DB_AM_CHKSUM);
 		if (((DBMETA *)pp)->encrypt_alg != 0 ||
 		    F_ISSET(dbp, DB_AM_ENCRYPT))
 			is_hmac = 1;
@@ -139,22 +139,25 @@ __db_pgin(dbenv, pg, pp, cookie)
 	 * If there is no configuration problem and we don't get a match,
 	 * it's fatal: panic the system.
 	 */
-	if (F_ISSET(dbp, DB_AM_CHKSUM) && sum_len != 0)
+	if (F_ISSET(dbp, DB_AM_CHKSUM) && sum_len != 0) {
+		if (F_ISSET(dbp, DB_AM_SWAP) && is_hmac == 0)
+			P_32_SWAP(chksum);
 		switch (ret = __db_check_chksum(
 		    dbenv, db_cipher, chksum, pp, sum_len, is_hmac)) {
 		case 0:
 			break;
 		case -1:
 			if (DBENV_LOGGING(dbenv))
-				__db_cksum_log(
+				(void)__db_cksum_log(
 				    dbenv, NULL, &not_used, DB_FLUSH);
 			__db_err(dbenv,
-		    "checksum error: catastrophic recovery required");
+	    "checksum error: page %lu: catastrophic recovery required",
+			    (u_long)pg);
 			return (__db_panic(dbenv, DB_RUNRECOVERY));
 		default:
 			return (ret);
 		}
-
+	}
 	if (F_ISSET(dbp, DB_AM_ENCRYPT)) {
 		DB_ASSERT(db_cipher != NULL);
 		DB_ASSERT(F_ISSET(dbp, DB_AM_CHKSUM));
@@ -330,6 +333,8 @@ __db_pgout(dbenv, pg, pp, cookie)
 			break;
 		}
 		__db_chksum(pp, sum_len, key, chksum);
+		if (F_ISSET(dbp, DB_AM_SWAP) && !F_ISSET(dbp, DB_AM_ENCRYPT))
+			 P_32_SWAP(chksum);
 	}
 	return (0);
 }
@@ -436,6 +441,8 @@ __db_byteswap(dbenv, dbp, pg, h, pagesize, pgin)
 				SWAP32(p);			/* pgno */
 				SWAP32(p);			/* tlen */
 				break;
+			default:
+				return (__db_pgfmt(dbenv, pg));
 			}
 
 		}
@@ -484,6 +491,8 @@ __db_byteswap(dbenv, dbp, pg, h, pagesize, pgin)
 				M_32_SWAP(bo->pgno);
 				M_32_SWAP(bo->tlen);
 				break;
+			default:
+				return (__db_pgfmt(dbenv, pg));
 			}
 
 			if (!pgin)
@@ -509,6 +518,8 @@ __db_byteswap(dbenv, dbp, pg, h, pagesize, pgin)
 				M_32_SWAP(bo->pgno);
 				M_32_SWAP(bo->tlen);
 				break;
+			default:
+				return (__db_pgfmt(dbenv, pg));
 			}
 
 			if (!pgin)
diff --git a/storage/bdb/db/db_dispatch.c b/storage/bdb/db/db_dispatch.c
index 2cf29ec2f338440f4d670125d21ec787ec888ea3..2317f500a7176ec203034b1a669df2eb32364cd6 100644
--- a/storage/bdb/db/db_dispatch.c
+++ b/storage/bdb/db/db_dispatch.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -34,41 +34,43 @@
  * 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.
+ *
+ * $Id: db_dispatch.c,v 11.169 2004/10/27 16:44:26 ubell Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_dispatch.c,v 11.121 2002/09/07 17:36:31 ubell Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
-#include <stddef.h>
 #include <stdlib.h>
 #include <string.h>
 #endif
 
 #include "db_int.h"
 #include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
 #include "dbinc/hash.h"
 #include "dbinc/log.h"
+#include "dbinc/mp.h"
 #include "dbinc/fop.h"
-#include "dbinc/rep.h"
 #include "dbinc/txn.h"
 
+#ifndef HAVE_FTRUNCATE
 static int __db_limbo_fix __P((DB *,
-    DB_TXN *, DB_TXNLIST *, db_pgno_t *, DBMETA *));
-static int __db_limbo_bucket __P((DB_ENV *, DB_TXN *, DB_TXNLIST *));
+    DB_TXN *, DB_TXNLIST *, db_pgno_t *, DBMETA *, db_limbo_state));
+static int __db_limbo_bucket __P((DB_ENV *,
+	     DB_TXN *, DB_TXNLIST *, db_limbo_state));
 static int __db_limbo_move __P((DB_ENV *, DB_TXN *, DB_TXN *, DB_TXNLIST *));
+static int __db_limbo_prepare __P(( DB *, DB_TXN *, DB_TXNLIST *));
 static int __db_lock_move __P((DB_ENV *,
 		u_int8_t *, db_pgno_t, db_lockmode_t, DB_TXN *, DB_TXN *));
-static int __db_default_getpgnos __P((DB_ENV *, DB_LSN *lsnp, void *));
-static int __db_txnlist_find_internal __P((DB_ENV *, void *, db_txnlist_type,
-		u_int32_t, u_int8_t [DB_FILE_ID_LEN], DB_TXNLIST **, int));
 static int __db_txnlist_pgnoadd __P((DB_ENV *, DB_TXNHEAD *,
 		int32_t, u_int8_t [DB_FILE_ID_LEN], char *, db_pgno_t));
+#endif
+static int __db_txnlist_find_internal __P((DB_ENV *,
+    void *, db_txnlist_type, u_int32_t, u_int8_t[DB_FILE_ID_LEN],
+    DB_TXNLIST **, int, u_int32_t *));
 
 /*
  * __db_dispatch --
@@ -94,7 +96,7 @@ __db_dispatch(dbenv, dtab, dtabsize, db, lsnp, redo, info)
 	void *info;
 {
 	DB_LSN prev_lsn;
-	u_int32_t rectype, txnid;
+	u_int32_t rectype, status, txnid;
 	int make_call, ret;
 
 	memcpy(&rectype, db->data, sizeof(rectype));
@@ -133,56 +135,88 @@ __db_dispatch(dbenv, dtab, dtabsize, db, lsnp, redo, info)
 		/* FALLTHROUGH */
 	case DB_TXN_POPENFILES:
 		if (rectype == DB___dbreg_register ||
+		    rectype == DB___txn_child ||
 		    rectype == DB___txn_ckp || rectype == DB___txn_recycle)
 			return (dtab[rectype](dbenv, db, lsnp, redo, info));
 		break;
 	case DB_TXN_BACKWARD_ROLL:
 		/*
-		 * Running full recovery in the backward pass.  If we've
-		 * seen this txnid before and added to it our commit list,
-		 * then we do nothing during this pass, unless this is a child
-		 * commit record, in which case we need to process it.  If
-		 * we've never seen it, then we call the appropriate recovery
-		 * routine.
-		 *
-		 * We need to always undo DB___db_noop records, so that we
-		 * properly handle any aborts before the file was closed.
+		 * Running full recovery in the backward pass. In general,
+		 * we only process records during this pass that belong
+		 * to aborted transactions.  Unfortunately, there are several
+		 * exceptions:
+		 * 1. If this is a meta-record, one not associated with
+		 *    a transaction, then we must always process it.
+		 * 2. If this is a transaction commit/abort, we must
+		 *    always process it, so that we know the status of
+		 *    every transaction.
+		 * 3. If this is a child commit, we need to process it
+		 *    because the outcome of the child transaction depends
+		 *    on the outcome of the parent.
+		 * 4. If this is a dbreg_register record, we must always
+		 *    process is because they contain non-transactional
+		 *    closes that must be properly handled.
+		 * 5. If this is a noop, we must always undo it so that we
+		 *    properly handle any aborts before a file was closed.
+		 * 6. If this a file remove, we need to process it to
+		 *    determine if the on-disk file is the same as the
+		 *    one being described.
+		 */
+		switch (rectype) {
+		/*
+		 * These either do not belong to a transaction or (regop)
+		 * must be processed regardless of the status of the
+		 * transaction.
 		 */
-		switch(rectype) {
 		case DB___txn_regop:
 		case DB___txn_recycle:
 		case DB___txn_ckp:
+			make_call = 1;
+			break;
+		/*
+		 * These belong to a transaction whose status must be
+		 * checked.
+		 */
+		case DB___txn_child:
 		case DB___db_noop:
 		case DB___fop_file_remove:
-		case DB___txn_child:
+		case DB___dbreg_register:
 			make_call = 1;
-			break;
 
-		case DB___dbreg_register:
-			if (txnid == 0) {
-				make_call = 1;
-				break;
-			}
 			/* FALLTHROUGH */
 		default:
-			if (txnid != 0 && (ret =
-			    __db_txnlist_find(dbenv,
-			    info, txnid)) != TXN_COMMIT && ret != TXN_IGNORE) {
-				/*
-				 * If not found then, this is an incomplete
-				 * abort.
-				 */
-				if (ret == TXN_NOTFOUND)
-					return (__db_txnlist_add(dbenv,
-					    info, txnid, TXN_IGNORE, lsnp));
-				make_call = 1;
-				if (ret == TXN_OK &&
-				    (ret = __db_txnlist_update(dbenv,
-				    info, txnid,
-				    rectype == DB___txn_xa_regop ?
-				    TXN_PREPARE : TXN_ABORT, NULL)) != 0)
-					return (ret);
+			if (txnid == 0)
+				break;
+
+			ret = __db_txnlist_find(dbenv, info, txnid, &status);
+
+			/* If not found, this is an incomplete abort.  */
+			if (ret == DB_NOTFOUND)
+				return (__db_txnlist_add(dbenv,
+				    info, txnid, TXN_IGNORE, lsnp));
+			if (ret != 0)
+				return (ret);
+
+			/*
+			 * If we ignore the transaction, ignore the operation
+			 * UNLESS this is a child commit in which case we need
+			 * to make sure that the child also gets marked as
+			 * ignore.
+			 */
+			if (status == TXN_IGNORE && rectype != DB___txn_child) {
+				make_call = 0;
+				break;
 			}
+			if (status == TXN_COMMIT)
+				break;
+
+			/* Set make_call in case we came through default */
+			make_call = 1;
+			if (status == TXN_OK &&
+			    (ret = __db_txnlist_update(dbenv,
+			    info, txnid, rectype == DB___txn_xa_regop ?
+			    TXN_PREPARE : TXN_ABORT, NULL, &status, 0)) != 0)
+				return (ret);
 		}
 		break;
 	case DB_TXN_FORWARD_ROLL:
@@ -193,7 +227,7 @@ __db_dispatch(dbenv, dtab, dtabsize, db, lsnp, redo, info)
 		 * We need to always redo DB___db_noop records, so that we
 		 * properly handle any commits after the file was closed.
 		 */
-		switch(rectype) {
+		switch (rectype) {
 		case DB___txn_recycle:
 		case DB___txn_ckp:
 		case DB___db_noop:
@@ -201,15 +235,28 @@ __db_dispatch(dbenv, dtab, dtabsize, db, lsnp, redo, info)
 			break;
 
 		default:
-			if (txnid != 0 && (ret = __db_txnlist_find(dbenv,
-			    info, txnid)) == TXN_COMMIT)
-				make_call = 1;
-			else if (ret != TXN_IGNORE &&
+			if (txnid != 0) {
+				ret = __db_txnlist_find(dbenv,
+				    info, txnid, &status);
+
+				if (ret == DB_NOTFOUND)
+					/* Break out out of if clause. */
+					;
+				else if (ret != 0)
+					return (ret);
+				else if (status == TXN_COMMIT) {
+					make_call = 1;
+					break;
+				}
+			}
+
+#ifndef HAVE_FTRUNCATE
+			if (status != TXN_IGNORE &&
 			    (rectype == DB___ham_metagroup ||
 			    rectype == DB___ham_groupalloc ||
 			    rectype == DB___db_pg_alloc)) {
 				/*
-				 * Because we cannot undo file extensions
+				 * Because we do not have truncate
 				 * all allocation records must be reprocessed
 				 * during rollforward in case the file was
 				 * just created.  It may not have been
@@ -217,7 +264,9 @@ __db_dispatch(dbenv, dtab, dtabsize, db, lsnp, redo, info)
 				 */
 				make_call = 1;
 				redo = DB_TXN_BACKWARD_ALLOC;
-			} else if (rectype == DB___dbreg_register) {
+			} else
+#endif
+			if (rectype == DB___dbreg_register) {
 				/*
 				 * This may be a transaction dbreg_register.
 				 * If it is, we only make the call on a COMMIT,
@@ -230,45 +279,32 @@ __db_dispatch(dbenv, dtab, dtabsize, db, lsnp, redo, info)
 			}
 		}
 		break;
-	case DB_TXN_GETPGNOS:
-		/*
-		 * If this is one of DB's own log records, we simply
-		 * dispatch.
-		 */
-		if (rectype < DB_user_BEGIN) {
-			make_call = 1;
-			break;
-		}
-
-		/*
-		 * If we're still here, this is a custom record in an
-		 * application that's doing app-specific logging.  Such a
-		 * record doesn't have a getpgno function for the user
-		 * dispatch function to call--the getpgnos functions return
-		 * which pages replication needs to lock using the TXN_RECS
-		 * structure, which is private and not something we want to
-		 * document.
-		 *
-		 * Thus, we leave any necessary locking for the app's
-		 * recovery function to do during the upcoming
-		 * DB_TXN_APPLY.  Fill in default getpgnos info (we need
-		 * a stub entry for every log record that will get
-		 * DB_TXN_APPLY'd) and return success.
-		 */
-		return (__db_default_getpgnos(dbenv, lsnp, info));
+	case DB_TXN_BACKWARD_ALLOC:
 	default:
-		return (__db_unknown_flag(dbenv, "__db_dispatch", redo));
+		return (__db_unknown_flag(
+		    dbenv, "__db_dispatch", (u_int32_t)redo));
 	}
-	/*
-	 * The switch statement uses ret to receive the return value of
-	 * __db_txnlist_find, which returns a large number of different
-	 * statuses, none of which we will be returning.  For safety,
-	 * let's reset this here in case we ever do a "return(ret)"
-	 * below in the future.
-	 */
-	ret = 0;
 
 	if (make_call) {
+		/*
+		 * If the debug flag is set then we are logging
+		 * records for a non-durable update so that they
+		 * may be examined for diagnostic purposes.
+		 * So only make the call if we are printing,
+		 * otherwise we need to extract the previous
+		 * lsn so undo will work properly.
+		 */
+		if (rectype & DB_debug_FLAG) {
+			if (redo == DB_TXN_PRINT)
+				rectype &= ~DB_debug_FLAG;
+			else {
+				memcpy(lsnp,
+				    (u_int8_t *)db->data +
+				    sizeof(rectype) +
+				    sizeof(txnid), sizeof(*lsnp));
+				return (0);
+			}
+		}
 		if (rectype >= DB_user_BEGIN && dbenv->app_dispatch != NULL)
 			return (dbenv->app_dispatch(dbenv, db, lsnp, redo));
 		else {
@@ -338,8 +374,8 @@ __db_txnlist_init(dbenv, low_txn, hi_txn, trunc_lsn, retp)
 	void *retp;
 {
 	DB_TXNHEAD *headp;
-	u_int32_t tmp;
-	int ret, size;
+	u_int32_t size, tmp;
+	int ret;
 
 	/*
 	 * Size a hash table.
@@ -382,11 +418,13 @@ __db_txnlist_init(dbenv, low_txn, hi_txn, trunc_lsn, retp)
 	headp->gen_array[0].generation = 0;
 	headp->gen_array[0].txn_min = TXN_MINIMUM;
 	headp->gen_array[0].txn_max = TXN_MAXIMUM;
-	if (trunc_lsn != NULL)
+	if (trunc_lsn != NULL) {
 		headp->trunc_lsn = *trunc_lsn;
-	else
+		headp->maxlsn = *trunc_lsn;
+	} else {
 		ZERO_LSN(headp->trunc_lsn);
-	ZERO_LSN(headp->maxlsn);
+		ZERO_LSN(headp->maxlsn);
+	}
 	ZERO_LSN(headp->ckplsn);
 
 	*(void **)retp = headp;
@@ -398,14 +436,13 @@ __db_txnlist_init(dbenv, low_txn, hi_txn, trunc_lsn, retp)
  *	Add an element to our transaction linked list.
  *
  * PUBLIC: int __db_txnlist_add __P((DB_ENV *,
- * PUBLIC:     void *, u_int32_t, int32_t, DB_LSN *));
+ * PUBLIC:     void *, u_int32_t, u_int32_t, DB_LSN *));
  */
 int
 __db_txnlist_add(dbenv, listp, txnid, status, lsn)
 	DB_ENV *dbenv;
 	void *listp;
-	u_int32_t txnid;
-	int32_t status;
+	u_int32_t txnid, status;
 	DB_LSN *lsn;
 {
 	DB_TXNHEAD *hp;
@@ -446,10 +483,10 @@ __db_txnlist_remove(dbenv, listp, txnid)
 	u_int32_t txnid;
 {
 	DB_TXNLIST *entry;
+	u_int32_t status;
 
 	return (__db_txnlist_find_internal(dbenv,
-	    listp, TXNLIST_TXNID, txnid,
-	    NULL, &entry, 1) == TXN_NOTFOUND ? TXN_NOTFOUND : TXN_OK);
+	    listp, TXNLIST_TXNID, txnid, NULL, &entry, 1, &status));
 }
 
 /*
@@ -481,8 +518,7 @@ __db_txnlist_ckp(dbenv, listp, ckp_lsn)
 
 /*
  * __db_txnlist_end --
- *	Discard transaction linked list. Print out any error messages
- * for deleted files.
+ *	Discard transaction linked list.
  *
  * PUBLIC: void __db_txnlist_end __P((DB_ENV *, void *));
  */
@@ -493,7 +529,7 @@ __db_txnlist_end(dbenv, listp)
 {
 	DB_TXNHEAD *hp;
 	DB_TXNLIST *p;
-	int i;
+	u_int32_t i;
 
 	if ((hp = (DB_TXNHEAD *)listp) == NULL)
 		return;
@@ -505,6 +541,9 @@ __db_txnlist_end(dbenv, listp)
 			case TXNLIST_LSN:
 				__os_free(dbenv, p->u.l.lsn_array);
 				break;
+			case TXNLIST_DELETE:
+			case TXNLIST_PGNO:
+			case TXNLIST_TXNID:
 			default:
 				/*
 				 * Possibly an incomplete DB_TXNLIST; just
@@ -523,55 +562,67 @@ __db_txnlist_end(dbenv, listp)
 /*
  * __db_txnlist_find --
  *	Checks to see if a txnid with the current generation is in the
- *	txnid list.  This returns TXN_NOTFOUND if the item isn't in the
+ *	txnid list.  This returns DB_NOTFOUND if the item isn't in the
  *	list otherwise it returns (like __db_txnlist_find_internal)
  *	the status of the transaction.  A txnid of 0 means the record
  *	was generated while not in a transaction.
  *
- * PUBLIC: int __db_txnlist_find __P((DB_ENV *, void *, u_int32_t));
+ * PUBLIC: int __db_txnlist_find __P((DB_ENV *,
+ * PUBLIC:     void *, u_int32_t, u_int32_t *));
  */
 int
-__db_txnlist_find(dbenv, listp, txnid)
+__db_txnlist_find(dbenv, listp, txnid, statusp)
 	DB_ENV *dbenv;
 	void *listp;
-	u_int32_t txnid;
+	u_int32_t txnid, *statusp;
 {
 	DB_TXNLIST *entry;
 
 	if (txnid == 0)
-		return (TXN_NOTFOUND);
+		return (DB_NOTFOUND);
+
 	return (__db_txnlist_find_internal(dbenv, listp,
-	    TXNLIST_TXNID, txnid, NULL, &entry, 0));
+	    TXNLIST_TXNID, txnid, NULL, &entry, 0, statusp));
 }
 
 /*
  * __db_txnlist_update --
  *	Change the status of an existing transaction entry.
- *	Returns TXN_NOTFOUND if no such entry exists.
+ *	Returns DB_NOTFOUND if no such entry exists.
  *
  * PUBLIC: int __db_txnlist_update __P((DB_ENV *,
- * PUBLIC:     void *, u_int32_t, u_int32_t, DB_LSN *));
+ * PUBLIC:     void *, u_int32_t, u_int32_t, DB_LSN *, u_int32_t *, int));
  */
 int
-__db_txnlist_update(dbenv, listp, txnid, status, lsn)
+__db_txnlist_update(dbenv, listp, txnid, status, lsn, ret_status, add_ok)
 	DB_ENV *dbenv;
 	void *listp;
-	u_int32_t txnid;
-	u_int32_t status;
+	u_int32_t txnid, status;
 	DB_LSN *lsn;
+	u_int32_t *ret_status;
+	int add_ok;
 {
 	DB_TXNHEAD *hp;
 	DB_TXNLIST *elp;
 	int ret;
 
 	if (txnid == 0)
-		return (TXN_NOTFOUND);
+		return (DB_NOTFOUND);
+
 	hp = (DB_TXNHEAD *)listp;
 	ret = __db_txnlist_find_internal(dbenv,
-	    listp, TXNLIST_TXNID, txnid, NULL, &elp, 0);
+	    listp, TXNLIST_TXNID, txnid, NULL, &elp, 0, ret_status);
 
-	if (ret == TXN_NOTFOUND)
+	if (ret == DB_NOTFOUND && add_ok) {
+		*ret_status = status;
+		return (__db_txnlist_add(dbenv, listp, txnid, status, lsn));
+	}
+	if (ret != 0)
 		return (ret);
+
+	if (*ret_status == TXN_IGNORE)
+		return (0);
+
 	elp->u.t.status = status;
 
 	if (lsn != NULL && IS_ZERO_LSN(hp->maxlsn) && status == TXN_COMMIT)
@@ -583,12 +634,13 @@ __db_txnlist_update(dbenv, listp, txnid, status, lsn)
 /*
  * __db_txnlist_find_internal --
  *	Find an entry on the transaction list.  If the entry is not there or
- *	the list pointer is not initialized we return TXN_NOTFOUND.  If the
+ *	the list pointer is not initialized we return DB_NOTFOUND.  If the
  *	item is found, we return the status.  Currently we always call this
  *	with an initialized list pointer but checking for NULL keeps it general.
  */
 static int
-__db_txnlist_find_internal(dbenv, listp, type, txnid, uid, txnlistp, delete)
+__db_txnlist_find_internal(dbenv,
+    listp, type, txnid, uid, txnlistp, delete, statusp)
 	DB_ENV *dbenv;
 	void *listp;
 	db_txnlist_type type;
@@ -596,16 +648,18 @@ __db_txnlist_find_internal(dbenv, listp, type, txnid, uid, txnlistp, delete)
 	u_int8_t uid[DB_FILE_ID_LEN];
 	DB_TXNLIST **txnlistp;
 	int delete;
+	u_int32_t *statusp;
 {
+	struct __db_headlink *head;
 	DB_TXNHEAD *hp;
 	DB_TXNLIST *p;
-	int32_t generation;
-	u_int32_t hash;
-	struct __db_headlink *head;
-	int i, ret;
+	u_int32_t generation, hash, i;
+	int ret;
+
+	ret = 0;
 
 	if ((hp = (DB_TXNHEAD *)listp) == NULL)
-		return (TXN_NOTFOUND);
+		return (DB_NOTFOUND);
 
 	switch (type) {
 	case TXNLIST_TXNID:
@@ -627,9 +681,10 @@ __db_txnlist_find_internal(dbenv, listp, type, txnid, uid, txnlistp, delete)
 		memcpy(&hash, uid, sizeof(hash));
 		generation = 0;
 		break;
+	case TXNLIST_DELETE:
+	case TXNLIST_LSN:
 	default:
-		DB_ASSERT(0);
-		return (EINVAL);
+		return (__db_panic(dbenv, EINVAL));
 	}
 
 	head = &hp->head[DB_TXNLIST_MASK(hp, hash)];
@@ -642,18 +697,17 @@ __db_txnlist_find_internal(dbenv, listp, type, txnid, uid, txnlistp, delete)
 			if (p->u.t.txnid != txnid ||
 			    generation != p->u.t.generation)
 				continue;
-			ret = p->u.t.status;
+			*statusp = p->u.t.status;
 			break;
 
 		case TXNLIST_PGNO:
 			if (memcmp(uid, p->u.p.uid, DB_FILE_ID_LEN) != 0)
 				continue;
-
-			ret = 0;
 			break;
+		case TXNLIST_DELETE:
+		case TXNLIST_LSN:
 		default:
-			DB_ASSERT(0);
-			ret = EINVAL;
+			return (__db_panic(dbenv, EINVAL));
 		}
 		if (delete == 1) {
 			LIST_REMOVE(p, links);
@@ -667,7 +721,7 @@ __db_txnlist_find_internal(dbenv, listp, type, txnid, uid, txnlistp, delete)
 		return (ret);
 	}
 
-	return (TXN_NOTFOUND);
+	return (DB_NOTFOUND);
 }
 
 /*
@@ -693,18 +747,19 @@ __db_txnlist_gen(dbenv, listp, incr, min, max)
 	 * whenever we take a checkpoint and there are no outstanding
 	 * transactions.  When that happens, we can reset transaction IDs
 	 * back to TXNID_MINIMUM.  Currently we only do the reset
-	 * at then end of recovery.  Recycle records occrur when txnids
+	 * at then end of recovery.  Recycle records occur when txnids
 	 * are exhausted during runtime.  A free range of ids is identified
 	 * and logged.  This code maintains a stack of ranges.  A txnid
 	 * is given the generation number of the first range it falls into
 	 * in the stack.
 	 */
 	hp = (DB_TXNHEAD *)listp;
-	hp->generation += incr;
-	if (incr < 0)
+	if (incr < 0) {
+		--hp->generation;
 		memmove(hp->gen_array, &hp->gen_array[1],
 		    (hp->generation + 1) * sizeof(hp->gen_array[0]));
-	else {
+	} else {
+		++hp->generation;
 		if (hp->generation >= hp->gen_alloc) {
 			hp->gen_alloc *= 2;
 			if ((ret = __os_realloc(dbenv, hp->gen_alloc *
@@ -721,8 +776,8 @@ __db_txnlist_gen(dbenv, listp, incr, min, max)
 }
 
 #define	TXN_BUBBLE(AP, MAX) {						\
-	int __j;							\
 	DB_LSN __tmp;							\
+	u_int32_t __j;							\
 									\
 	for (__j = 0; __j < MAX - 1; __j++)				\
 		if (log_compare(&AP[__j], &AP[__j + 1]) < 0) {		\
@@ -750,7 +805,8 @@ __db_txnlist_lsnadd(dbenv, listp, lsnp, flags)
 {
 	DB_TXNHEAD *hp;
 	DB_TXNLIST *elp;
-	int i, ret;
+	u_int32_t i;
+	int ret;
 
 	hp = (DB_TXNHEAD *)listp;
 
@@ -823,12 +879,15 @@ err:	__db_txnlist_end(dbenv, hp);
 	return (ret);
 }
 
+#ifndef HAVE_FTRUNCATE
 /*
  * __db_add_limbo -- add pages to the limbo list.
  *	Get the file information and call pgnoadd for each page.
  *
+ * PUBLIC: #ifndef HAVE_FTRUNCATE
  * PUBLIC: int __db_add_limbo __P((DB_ENV *,
  * PUBLIC:      void *, int32_t, db_pgno_t, int32_t));
+ * PUBLIC: #endif
  */
 int
 __db_add_limbo(dbenv, info, fileid, pgno, count)
@@ -869,7 +928,7 @@ __db_add_limbo(dbenv, info, fileid, pgno, count)
  * the specific modifications to the free list.
  *
  * If we run out of log space during an abort, then we can't write the
- * compensating transaction, so we abandon the idea of a compenating
+ * compensating transaction, so we abandon the idea of a compensating
  * transaction, and go back to processing how we do during recovery.
  * The reason that this is not the norm is that it's expensive: it requires
  * that we flush any database with an in-question allocation.  Thus if
@@ -889,17 +948,21 @@ __db_add_limbo(dbenv, info, fileid, pgno, count)
  * "create list and write meta-data page" algorithm.  Otherwise, we're in
  * an abort and doing the "use compensating transaction" algorithm.
  *
+ * PUBLIC: #ifndef HAVE_FTRUNCATE
  * PUBLIC: int __db_do_the_limbo __P((DB_ENV *,
- * PUBLIC:     DB_TXN *, DB_TXN *, DB_TXNHEAD *));
+ * PUBLIC:     DB_TXN *, DB_TXN *, DB_TXNHEAD *, db_limbo_state));
+ * PUBLIC: #endif
  */
 int
-__db_do_the_limbo(dbenv, ptxn, txn, hp)
+__db_do_the_limbo(dbenv, ptxn, txn, hp, state)
 	DB_ENV *dbenv;
 	DB_TXN *ptxn, *txn;
 	DB_TXNHEAD *hp;
+	db_limbo_state state;
 {
 	DB_TXNLIST *elp;
-	int h, ret;
+	u_int32_t h;
+	int ret;
 
 	ret = 0;
 	/*
@@ -914,7 +977,8 @@ __db_do_the_limbo(dbenv, ptxn, txn, hp)
 			if ((ret =
 			    __db_limbo_move(dbenv, ptxn, txn, elp)) != 0)
 				goto err;
-		} else if ((ret = __db_limbo_bucket(dbenv, txn, elp)) != 0)
+		} else if ((ret =
+		    __db_limbo_bucket(dbenv, txn, elp, state)) != 0)
 			goto err;
 	}
 
@@ -954,13 +1018,12 @@ __db_lock_move(dbenv, fileid, pgno, mode, ptxn, txn)
 	lock_dbt.data = &lock_obj;
 	lock_dbt.size = sizeof(lock_obj);
 
-	if ((ret = dbenv->lock_get(dbenv,
+	if ((ret = __lock_get(dbenv,
 	    txn->txnid, 0, &lock_dbt, mode, &lock)) == 0) {
 		memset(&req, 0, sizeof(req));
 		req.lock = lock;
 		req.op = DB_LOCK_TRADE;
-
-		ret = dbenv->lock_vec(dbenv, ptxn->txnid, 0, &req, 1, NULL);
+		ret = __lock_vec(dbenv, ptxn->txnid, 0, &req, 1, NULL);
 	}
 	return (ret);
 }
@@ -995,17 +1058,19 @@ __db_limbo_move(dbenv, ptxn, txn, elp)
  * compensating transaction.
  */
 
-#define T_RESTORED(txn)       ((txn) != NULL && F_ISSET(txn, TXN_RESTORED))
+#define	T_RESTORED(txn)       ((txn) != NULL && F_ISSET(txn, TXN_RESTORED))
 static int
-__db_limbo_bucket(dbenv, txn, elp)
+__db_limbo_bucket(dbenv, txn, elp, state)
 	DB_ENV *dbenv;
 	DB_TXN *txn;
 	DB_TXNLIST *elp;
+	db_limbo_state state;
 {
 	DB *dbp;
 	DB_MPOOLFILE *mpf;
 	DBMETA *meta;
 	DB_TXN *ctxn, *t;
+	FNAME *fname;
 	db_pgno_t last_pgno, pgno;
 	int dbp_created, in_retry, ret, t_ret;
 
@@ -1023,8 +1088,11 @@ retry:		dbp_created = 0;
 		 * Pick the transaction in which to potentially
 		 * log compensations.
 		 */
-		if (!in_retry && !IS_RECOVERING(dbenv) && !T_RESTORED(txn)
-		    && (ret = __txn_compensate_begin(dbenv, &ctxn)) != 0)
+		if (state == LIMBO_PREPARE)
+			ctxn = txn;
+		else if (!in_retry && state != LIMBO_RECOVER &&
+		    state != LIMBO_TIMESTAMP && !T_RESTORED(txn) &&
+		    (ret = __txn_compensate_begin(dbenv, &ctxn)) != 0)
 			return (ret);
 
 		/*
@@ -1036,6 +1104,18 @@ retry:		dbp_created = 0;
 		/* First try to get a dbp by fileid. */
 		ret = __dbreg_id_to_db(dbenv, t, &dbp, elp->u.p.fileid, 0);
 
+		/*
+		 * If the file was closed and reopened its id could change.
+		 * Look it up the hard way.
+		 */
+		if (ret == DB_DELETED || ret == ENOENT ||
+		    ((ret == 0 &&
+		    memcmp(elp->u.p.uid, dbp->fileid, DB_FILE_ID_LEN) != 0))) {
+			if ((ret = __dbreg_fid_to_fname(
+			    dbenv->lg_handle, elp->u.p.uid, 0, &fname)) == 0)
+				ret = __dbreg_id_to_db(
+				     dbenv, t, &dbp, fname->id, 0);
+		}
 		/*
 		 * File is being destroyed.  No need to worry about
 		 * dealing with recovery of allocations.
@@ -1056,8 +1136,8 @@ retry:		dbp_created = 0;
 			dbp_created = 1;
 
 			/* It is ok if the file is nolonger there. */
-			dbp->type = DB_UNKNOWN;
-			ret = __db_dbopen(dbp, t, elp->u.p.fname, NULL,
+			ret = __db_open(dbp,
+			    t, elp->u.p.fname, NULL, DB_UNKNOWN,
 			    DB_ODDFILESIZE, __db_omode("rw----"), PGNO_BASE_MD);
 			if (ret == ENOENT)
 				goto next;
@@ -1073,15 +1153,20 @@ retry:		dbp_created = 0;
 		mpf = dbp->mpf;
 		last_pgno = PGNO_INVALID;
 
-		if (ctxn == NULL) {
+		if (meta == NULL && 
+		    (ctxn == NULL || state == LIMBO_COMPENSATE)) {
 			pgno = PGNO_BASE_MD;
-			if ((ret =
-			    mpf->get(mpf, &pgno, 0, (PAGE **)&meta)) != 0)
+			if ((ret = __memp_fget(mpf, &pgno, 0, &meta)) != 0)
 				goto err;
 			last_pgno = meta->free;
 		}
 
-		ret = __db_limbo_fix(dbp, ctxn, elp, &last_pgno, meta);
+		if (state == LIMBO_PREPARE) {
+			if ((ret = __db_limbo_prepare(dbp, ctxn, elp)) != 0)
+				goto err;
+		} else
+			ret = __db_limbo_fix(dbp,
+			     ctxn, elp, &last_pgno, meta, state);
 		/*
 		 * If we were doing compensating transactions, then we are
 		 * going to hope this error was due to running out of space.
@@ -1093,15 +1178,31 @@ retry:		dbp_created = 0;
 			if (ret == DB_RUNRECOVERY || ctxn == NULL)
 				goto err;
 			in_retry = 1;
+			if ((ret = __txn_abort(ctxn)) != 0)
+				goto err;
+			ctxn = NULL;
 			goto retry;
 		}
 
-		if (ctxn != NULL) {
-			ret = ctxn->commit(ctxn, DB_TXN_NOSYNC);
+		if (state == LIMBO_PREPARE)
+			ctxn = NULL;
+
+		else if (ctxn != NULL) {
+			/*
+			 * We only force compensation at the end of recovery.
+			 * We want the txn_commit to be logged so turn
+			 * off the recovery flag briefly.
+			 */
+			if (state == LIMBO_COMPENSATE)
+				F_CLR(
+				    (DB_LOG *)dbenv->lg_handle, DBLOG_RECOVER);
+			ret = __txn_commit(ctxn, DB_TXN_NOSYNC);
 			ctxn = NULL;
+			if (state == LIMBO_COMPENSATE)
+				F_SET(
+				    (DB_LOG *)dbenv->lg_handle, DBLOG_RECOVER);
 			if (ret != 0)
 				goto retry;
-			goto next;
 		}
 
 		/*
@@ -1110,9 +1211,9 @@ retry:		dbp_created = 0;
 		 * we have to write the meta-data page, and if we do, then
 		 * we need to sync it as well.
 		 */
-		if (last_pgno == meta->free) {
+		else if (last_pgno == meta->free) {
 			/* No change to page; just put the page back. */
-			if ((ret = mpf->put(mpf, meta, 0)) != 0)
+			if ((ret = __memp_fput(mpf, meta, 0)) != 0)
 				goto err;
 			meta = NULL;
 		} else {
@@ -1125,35 +1226,55 @@ retry:		dbp_created = 0;
 			 */
 			if (!IS_RECOVERING(dbenv) && !T_RESTORED(txn))
 				__db_err(dbenv, "Flushing free list to disk");
-			if ((ret = mpf->put(mpf, meta, 0)) != 0)
-				goto err;
-			meta = NULL;
-			dbp->sync(dbp, 0);
-			pgno = PGNO_BASE_MD;
-			if ((ret =
-			    mpf->get(mpf, &pgno, 0, (PAGE **)&meta)) != 0)
-				goto err;
-			meta->free = last_pgno;
-			if ((ret = mpf->put(mpf, meta, DB_MPOOL_DIRTY)) != 0)
+			if ((ret = __memp_fput(mpf, meta, 0)) != 0)
 				goto err;
 			meta = NULL;
+			/*
+			 * If the sync fails then we cannot flush the
+			 * newly allocated pages.  That is, the file
+			 * cannot be extended. Don't let the metapage
+			 * point at them.
+			 * We may lose these pages from the file if it
+			 * can be extended later.  If there is never
+			 * space for the pages, then things will be ok.
+			 */
+			if ((ret = __db_sync(dbp)) == 0) {
+				pgno = PGNO_BASE_MD;
+				if ((ret =
+				    __memp_fget(mpf, &pgno, 0, &meta)) != 0)
+					goto err;
+				meta->free = last_pgno;
+				if ((ret = __memp_fput(mpf,
+				     meta, DB_MPOOL_DIRTY)) != 0)
+					goto err;
+				meta = NULL;
+			} else {
+				__db_err(dbenv,
+				    "%s: %s", dbp->fname, db_strerror(ret));
+				__db_err(dbenv, "%s: %s %s", dbp->fname,
+				    "allocation flush failed, some free pages",
+				    "may not appear in the free list");
+				ret = 0;
+			}
 		}
 
 next:
 		/*
 		 * If we get here, either we have processed the list
-		 * or the db file has been deleted or could no be opened.
+		 * or the db file has been deleted or could not be opened.
 		 */
 		if (ctxn != NULL &&
-		    (t_ret = ctxn->abort(ctxn)) != 0 && ret == 0)
+		    (t_ret = __txn_abort(ctxn)) != 0 && ret == 0)
 			ret = t_ret;
 
 		if (dbp_created &&
-		    (t_ret = __db_close_i(dbp, txn, 0)) != 0 && ret == 0)
+		    (t_ret = __db_close(dbp, txn, DB_NOSYNC)) != 0 && ret == 0)
 			ret = t_ret;
 		dbp = NULL;
-		__os_free(dbenv, elp->u.p.fname);
-		__os_free(dbenv, elp->u.p.pgno_array);
+		if (state != LIMBO_PREPARE && state != LIMBO_TIMESTAMP) {
+			__os_free(dbenv, elp->u.p.fname);
+			__os_free(dbenv, elp->u.p.pgno_array);
+		}
 		if (ret == ENOENT)
 			ret = 0;
 		else if (ret != 0)
@@ -1161,7 +1282,7 @@ next:
 	}
 
 err:	if (meta != NULL)
-		(void)mpf->put(mpf, meta, 0);
+		(void)__memp_fput(mpf, meta, 0);
 	return (ret);
 }
 
@@ -1171,37 +1292,46 @@ err:	if (meta != NULL)
  * for a single file.
  */
 static int
-__db_limbo_fix(dbp, ctxn, elp, lastp, meta)
+__db_limbo_fix(dbp, ctxn, elp, lastp, meta, state)
 	DB *dbp;
 	DB_TXN *ctxn;
 	DB_TXNLIST *elp;
 	db_pgno_t *lastp;
 	DBMETA *meta;
+	db_limbo_state state;
 {
 	DBC *dbc;
+	DBT ldbt;
 	DB_MPOOLFILE *mpf;
 	PAGE *freep, *pagep;
 	db_pgno_t next, pgno;
-	int i, put_page, ret, t_ret;
+	u_int32_t i;
+	int ret, t_ret;
 
 	/*
 	 * Loop through the entries for this txnlist element and
 	 * either link them into the free list or write a compensating
 	 * record for each.
 	 */
-	put_page = 0;
-	ret = 0;
-	mpf = dbp->mpf;
 	dbc = NULL;
+	mpf = dbp->mpf;
+	pagep = NULL;
+	ret = 0;
 
 	for (i = 0; i < elp->u.p.nentries; i++) {
 		pgno = elp->u.p.pgno_array[i];
 
-		if ((ret = mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &pagep)) != 0)
-			goto err;
-		put_page = 1;
+		if (pgno == PGNO_INVALID)
+			continue;
+
+		if ((ret =
+		    __memp_fget(mpf, &pgno, DB_MPOOL_CREATE, &pagep)) != 0) {
+			if (ret != ENOSPC)
+				goto err;
+			continue;
+		}
 
-		if (IS_ZERO_LSN(LSN(pagep))) {
+		if (state == LIMBO_COMPENSATE || IS_ZERO_LSN(LSN(pagep))) {
 			if (ctxn == NULL) {
 				/*
 				 * If this is a fatal recovery which
@@ -1211,26 +1341,40 @@ __db_limbo_fix(dbp, ctxn, elp, lastp, meta)
 				for (next = *lastp; next != 0; ) {
 					if (next == pgno)
 						break;
-					if ((ret = mpf->get(mpf,
+					if ((ret = __memp_fget(mpf,
 					    &next, 0, &freep)) != 0)
 						goto err;
 					next = NEXT_PGNO(freep);
 					if ((ret =
-					    mpf->put(mpf, freep, 0)) != 0)
+					    __memp_fput(mpf, freep, 0)) != 0)
 						goto err;
 				}
 
 				if (next != pgno) {
 					P_INIT(pagep, dbp->pgsize, pgno,
 					    PGNO_INVALID, *lastp, 0, P_INVALID);
-					LSN(pagep) = LSN(meta);
+					/* Make the lsn non-zero but generic. */
+					INIT_LSN(LSN(pagep));
 					*lastp = pgno;
 				}
+			} else if (state == LIMBO_COMPENSATE) {
+				/*
+				 * Generate a log record for what we did on the
+				 * LIMBO_TIMESTAMP pass.  All pages here are
+				 * free so P_OVERHEAD is sufficient.
+				 */
+				ZERO_LSN(pagep->lsn);
+				memset(&ldbt, 0, sizeof(ldbt));
+				ldbt.data = pagep;
+				ldbt.size = P_OVERHEAD(dbp);
+				if ((ret = __db_pg_new_log(dbp, ctxn,
+				     &LSN(meta), 0, pagep->pgno,
+				     &LSN(meta), PGNO_BASE_MD,
+				     &ldbt, pagep->next_pgno)) != 0)
+					goto err;
 			} else {
-				P_INIT(pagep, dbp->pgsize, pgno,
-				    PGNO_INVALID, *lastp, 0, P_INVALID);
 				if (dbc == NULL && (ret =
-				    dbp->cursor(dbp, ctxn, &dbc, 0)) != 0)
+				    __db_cursor(dbp, ctxn, &dbc, 0)) != 0)
 						goto err;
 				/*
 				 * If the dbp is compensating (because we
@@ -1240,7 +1384,8 @@ __db_limbo_fix(dbp, ctxn, elp, lastp, meta)
 				 */
 				F_SET(dbc, DBC_COMPENSATE);
 				ret = __db_free(dbc, pagep);
-				put_page = 0;
+				pagep = NULL;
+
 				/*
 				 * On any error, we hope that the error was
 				 * caused due to running out of space, and we
@@ -1252,29 +1397,75 @@ __db_limbo_fix(dbp, ctxn, elp, lastp, meta)
 				 */
 				if (ret != 0) {
 					/* Assume that this is out of space. */
-					(void)dbc->c_close(dbc);
+					(void)__db_c_close(dbc);
 					dbc = NULL;
 					goto err;
 				}
 			}
 		}
+		else
+			elp->u.p.pgno_array[i] = PGNO_INVALID;
 
-		if (put_page == 1) {
-			ret = mpf->put(mpf, pagep, DB_MPOOL_DIRTY);
-			put_page = 0;
+		if (pagep != NULL) {
+			ret = __memp_fput(mpf, pagep, DB_MPOOL_DIRTY);
+			pagep = NULL;
 		}
 		if (ret != 0)
 			goto err;
 	}
 
-err:	if (put_page &&
-	    (t_ret = mpf->put(mpf, pagep, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+err:	if (pagep != NULL &&
+	    (t_ret = __memp_fput(mpf, pagep, DB_MPOOL_DIRTY)) != 0 && ret == 0)
 		ret = t_ret;
-	if (dbc != NULL && (t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
+	if (dbc != NULL && (t_ret = __db_c_close(dbc)) != 0 && ret == 0)
 		ret = t_ret;
 	return (ret);
 }
 
+static int
+__db_limbo_prepare(dbp, txn, elp)
+	DB *dbp;
+	DB_TXN *txn;
+	DB_TXNLIST *elp;
+{
+	DB_LSN lsn;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	db_pgno_t pgno;
+	u_int32_t i;
+	int ret, t_ret;
+
+	/*
+	 * Loop through the entries for this txnlist element and
+	 * output a prepare record for them.
+	 */
+	pagep = NULL;
+	ret = 0;
+	mpf = dbp->mpf;
+
+	for (i = 0; i < elp->u.p.nentries; i++) {
+		pgno = elp->u.p.pgno_array[i];
+
+		if ((ret =
+		    __memp_fget(mpf, &pgno, DB_MPOOL_CREATE, &pagep)) != 0) {
+			if (ret != ENOSPC)
+				return (ret);
+			continue;
+		}
+
+		if (IS_ZERO_LSN(LSN(pagep)))
+			ret = __db_pg_prepare_log(dbp, txn, &lsn, 0, pgno);
+
+		if ((t_ret = __memp_fput(mpf, pagep, 0)) != 0 && ret == 0)
+			ret = t_ret;
+
+		if (ret != 0)
+			return (ret);
+	}
+
+	return (0);
+}
+
 #define	DB_TXNLIST_MAX_PGNO	8		/* A nice even number. */
 
 /*
@@ -1292,23 +1483,26 @@ __db_txnlist_pgnoadd(dbenv, hp, fileid, uid, fname, pgno)
 	db_pgno_t pgno;
 {
 	DB_TXNLIST *elp;
-	u_int32_t hash;
-	int len, ret;
+	size_t len;
+	u_int32_t hash, status;
+	int ret;
 
 	elp = NULL;
 
-	if (__db_txnlist_find_internal(dbenv, hp,
-	    TXNLIST_PGNO, 0, uid, &elp, 0) != 0) {
+	if ((ret = __db_txnlist_find_internal(dbenv, hp,
+	    TXNLIST_PGNO, 0, uid, &elp, 0, &status)) != 0 && ret != DB_NOTFOUND)
+		goto err;
+
+	if (ret == DB_NOTFOUND || status != TXN_OK) {
 		if ((ret =
 		    __os_malloc(dbenv, sizeof(DB_TXNLIST), &elp)) != 0)
 			goto err;
 		memcpy(&hash, uid, sizeof(hash));
 		LIST_INSERT_HEAD(
 		    &hp->head[DB_TXNLIST_MASK(hp, hash)], elp, links);
-		elp->u.p.fileid = fileid;
 		memcpy(elp->u.p.uid, uid, DB_FILE_ID_LEN);
 
-		len = (int)strlen(fname) + 1;
+		len = strlen(fname) + 1;
 		if ((ret = __os_malloc(dbenv, len, &elp->u.p.fname)) != 0)
 			goto err;
 		memcpy(elp->u.p.fname, fname, len);
@@ -1329,42 +1523,14 @@ __db_txnlist_pgnoadd(dbenv, hp, fileid, uid, fname, pgno)
 	}
 
 	elp->u.p.pgno_array[elp->u.p.nentries++] = pgno;
+	/* Update to the latest fileid.  Limbo will find it faster. */
+	elp->u.p.fileid = fileid;
 
 	return (0);
 
-err:	__db_txnlist_end(dbenv, hp);
-	return (ret);
-}
-
-/*
- * __db_default_getpgnos --
- *	Fill in default getpgnos information for an application-specific
- * log record.
- */
-static int
-__db_default_getpgnos(dbenv, lsnp, summary)
-	DB_ENV *dbenv;
-	DB_LSN *lsnp;
-	void *summary;
-{
-	TXN_RECS *t;
-	int ret;
-
-	t = (TXN_RECS *)summary;
-
-	if ((ret = __rep_check_alloc(dbenv, t, 1)) != 0)
-		return (ret);
-
-	t->array[t->npages].flags = LSN_PAGE_NOLOCK;
-	t->array[t->npages].lsn = *lsnp;
-	t->array[t->npages].fid = DB_LOGFILEID_INVALID;
-	memset(&t->array[t->npages].pgdesc, 0,
-	    sizeof(t->array[t->npages].pgdesc));
-
-	t->npages++;
-
-	return (0);
+err:	return (ret);
 }
+#endif
 
 #ifdef DEBUG
 /*
@@ -1379,26 +1545,49 @@ __db_txnlist_print(listp)
 {
 	DB_TXNHEAD *hp;
 	DB_TXNLIST *p;
-	int i;
-	char *stats[] = { "ok", "commit", "prepare", "abort", "notfound",
-	    "ignore", "expected", "unexpected" };
+	u_int32_t i;
+	char *txntype;
 
 	hp = (DB_TXNHEAD *)listp;
 
 	printf("Maxid: %lu Generation: %lu\n",
 	    (u_long)hp->maxid, (u_long)hp->generation);
 	for (i = 0; i < hp->nslots; i++)
-	for (p = LIST_FIRST(&hp->head[i]); p != NULL; p = LIST_NEXT(p, links)) {
-		switch (p->type) {
-		case TXNLIST_TXNID:
+		for (p = LIST_FIRST(&hp->head[i]);
+		    p != NULL; p = LIST_NEXT(p, links)) {
+			if (p->type != TXNLIST_TXNID) {
+				printf("Unrecognized type: %d\n", p->type);
+				continue;
+			}
+			switch (p->u.t.status) {
+			case TXN_OK:
+				txntype = "OK";
+				break;
+			case TXN_COMMIT:
+				txntype = "commit";
+				break;
+			case TXN_PREPARE:
+				txntype = "prepare";
+				break;
+			case TXN_ABORT:
+				txntype = "abort";
+				break;
+			case TXN_IGNORE:
+				txntype = "ignore";
+				break;
+			case TXN_EXPECTED:
+				txntype = "expected";
+				break;
+			case TXN_UNEXPECTED:
+				txntype = "unexpected";
+				break;
+			default:
+				txntype = "UNKNOWN";
+				break;
+			}
 			printf("TXNID: %lx(%lu): %s\n",
-			    (u_long)p->u.t.txnid, (u_long)p->u.t.generation,
-			    stats[p->u.t.status]);
-			break;
-		default:
-			printf("Unrecognized type: %d\n", p->type);
-			break;
+			    (u_long)p->u.t.txnid,
+			    (u_long)p->u.t.generation, txntype);
 		}
-	}
 }
 #endif
diff --git a/storage/bdb/db/db_dup.c b/storage/bdb/db/db_dup.c
index 2d33d79153fd9cfdc6f1b4a616412a09565884bd..725e81cceffa4d1d3dcbad9ade49917d5cf3ec2f 100644
--- a/storage/bdb/db/db_dup.c
+++ b/storage/bdb/db/db_dup.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_dup.c,v 11.39 2004/02/18 21:34:37 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_dup.c,v 11.32 2002/08/08 03:57:47 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -20,7 +18,7 @@ static const char revid[] = "$Id: db_dup.c,v 11.32 2002/08/08 03:57:47 bostic Ex
 #include "db_int.h"
 #include "dbinc/db_page.h"
 #include "dbinc/db_shash.h"
-#include "dbinc/lock.h"
+#include "dbinc/mp.h"
 #include "dbinc/db_am.h"
 
 /*
@@ -164,118 +162,3 @@ __db_pitem(dbc, pagep, indx, nbytes, hdr, data)
 
 	return (0);
 }
-
-/*
- * __db_relink --
- *	Relink around a deleted page.
- *
- * PUBLIC: int __db_relink __P((DBC *, u_int32_t, PAGE *, PAGE **, int));
- */
-int
-__db_relink(dbc, add_rem, pagep, new_next, needlock)
-	DBC *dbc;
-	u_int32_t add_rem;
-	PAGE *pagep, **new_next;
-	int needlock;
-{
-	DB *dbp;
-	PAGE *np, *pp;
-	DB_LOCK npl, ppl;
-	DB_LSN *nlsnp, *plsnp, ret_lsn;
-	DB_MPOOLFILE *mpf;
-	int ret;
-
-	dbp = dbc->dbp;
-	np = pp = NULL;
-	LOCK_INIT(npl);
-	LOCK_INIT(ppl);
-	nlsnp = plsnp = NULL;
-	mpf = dbp->mpf;
-	ret = 0;
-
-	/*
-	 * Retrieve and lock the one/two pages.  For a remove, we may need
-	 * two pages (the before and after).  For an add, we only need one
-	 * because, the split took care of the prev.
-	 */
-	if (pagep->next_pgno != PGNO_INVALID) {
-		if (needlock && (ret = __db_lget(dbc,
-		    0, pagep->next_pgno, DB_LOCK_WRITE, 0, &npl)) != 0)
-			goto err;
-		if ((ret = mpf->get(mpf, &pagep->next_pgno, 0, &np)) != 0) {
-			__db_pgerr(dbp, pagep->next_pgno, ret);
-			goto err;
-		}
-		nlsnp = &np->lsn;
-	}
-	if (add_rem == DB_REM_PAGE && pagep->prev_pgno != PGNO_INVALID) {
-		if (needlock && (ret = __db_lget(dbc,
-		    0, pagep->prev_pgno, DB_LOCK_WRITE, 0, &ppl)) != 0)
-			goto err;
-		if ((ret = mpf->get(mpf, &pagep->prev_pgno, 0, &pp)) != 0) {
-			__db_pgerr(dbp, pagep->next_pgno, ret);
-			goto err;
-		}
-		plsnp = &pp->lsn;
-	}
-
-	/* Log the change. */
-	if (DBC_LOGGING(dbc)) {
-		if ((ret = __db_relink_log(dbp, dbc->txn, &ret_lsn, 0, add_rem,
-		    pagep->pgno, &pagep->lsn, pagep->prev_pgno, plsnp,
-		    pagep->next_pgno, nlsnp)) != 0)
-			goto err;
-	} else
-		LSN_NOT_LOGGED(ret_lsn);
-	if (np != NULL)
-		np->lsn = ret_lsn;
-	if (pp != NULL)
-		pp->lsn = ret_lsn;
-	if (add_rem == DB_REM_PAGE)
-		pagep->lsn = ret_lsn;
-
-	/*
-	 * Modify and release the two pages.
-	 *
-	 * !!!
-	 * The parameter new_next gets set to the page following the page we
-	 * are removing.  If there is no following page, then new_next gets
-	 * set to NULL.
-	 */
-	if (np != NULL) {
-		if (add_rem == DB_ADD_PAGE)
-			np->prev_pgno = pagep->pgno;
-		else
-			np->prev_pgno = pagep->prev_pgno;
-		if (new_next == NULL)
-			ret = mpf->put(mpf, np, DB_MPOOL_DIRTY);
-		else {
-			*new_next = np;
-			ret = mpf->set(mpf, np, DB_MPOOL_DIRTY);
-		}
-		if (ret != 0)
-			goto err;
-		if (needlock)
-			(void)__TLPUT(dbc, npl);
-	} else if (new_next != NULL)
-		*new_next = NULL;
-
-	if (pp != NULL) {
-		pp->next_pgno = pagep->next_pgno;
-		if ((ret = mpf->put(mpf, pp, DB_MPOOL_DIRTY)) != 0)
-			goto err;
-		if (needlock)
-			(void)__TLPUT(dbc, ppl);
-	}
-	return (0);
-
-err:	if (np != NULL)
-		(void)mpf->put(mpf, np, 0);
-	if (needlock)
-		(void)__TLPUT(dbc, npl);
-	if (pp != NULL)
-		(void)mpf->put(mpf, pp, 0);
-	if (needlock)
-		(void)__TLPUT(dbc, ppl);
-	return (ret);
-}
diff --git a/storage/bdb/db/db_iface.c b/storage/bdb/db/db_iface.c
index b518c3b14b2c444df1abfb5aa8545ef801c58553..7be20ede13294328484abc52523dfdd6c203799a 100644
--- a/storage/bdb/db/db_iface.c
+++ b/storage/bdb/db/db_iface.c
@@ -1,26 +1,44 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_iface.c,v 11.121 2004/10/07 17:33:32 sue Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_iface.c,v 11.77 2002/08/08 03:57:47 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
+
+#include <string.h>
 #endif
 
 #include "db_int.h"
 #include "dbinc/db_page.h"
-#include "dbinc/db_am.h"
-
+#include "dbinc/db_shash.h"
+#include "dbinc/btree.h"
+#include "dbinc/hash.h"			/* For __db_no_hash_am(). */
+#include "dbinc/qam.h"			/* For __db_no_queue_am(). */
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
+#include "dbinc/mp.h"
+
+static int __db_associate_arg __P((DB *, DB *,
+	       int (*)(DB *, const DBT *, const DBT *, DBT *), u_int32_t));
+static int __db_c_get_arg __P((DBC *, DBT *, DBT *, u_int32_t));
+static int __db_c_pget_arg __P((DBC *, DBT *, u_int32_t));
+static int __db_c_put_arg __P((DBC *, DBT *, DBT *, u_int32_t));
 static int __db_curinval __P((const DB_ENV *));
-static int __db_fnl __P((const DB_ENV *, const char *));
+static int __db_cursor_arg __P((DB *, u_int32_t));
+static int __db_del_arg __P((DB *, u_int32_t));
+static int __db_get_arg __P((const DB *, const DBT *, DBT *, u_int32_t));
+static int __db_join_arg __P((DB *, DBC **, u_int32_t));
+static int __db_open_arg __P((DB *,
+	       DB_TXN *, const char *, const char *, DBTYPE, u_int32_t));
+static int __db_pget_arg __P((DB *, DBT *, u_int32_t));
+static int __db_put_arg __P((DB *, DBT *, DBT *, u_int32_t));
 static int __db_rdonly __P((const DB_ENV *, const char *));
 static int __dbt_ferr __P((const DB *, const char *, const DBT *, int));
 
@@ -31,25 +49,340 @@ static int __dbt_ferr __P((const DB *, const char *, const DBT *, int));
  */
 #define	IS_READONLY(dbp)						\
     (F_ISSET(dbp, DB_AM_RDONLY) ||					\
-    (F_ISSET((dbp)->dbenv, DB_ENV_REP_CLIENT) &&			\
+    (IS_REP_CLIENT((dbp)->dbenv) &&					\
     !F_ISSET((dbp), DB_AM_CL_WRITER)))
 
 /*
- * __db_cursorchk --
- *	Common cursor argument checking routine.
+ * These functions implement the Berkeley DB API.  They are organized in a
+ * layered fashion.  The interface functions (XXX_pp) perform all generic
+ * error checks (for example, PANIC'd region, replication state change
+ * in progress, inconsistent transaction usage), call function-specific
+ * check routines (_arg) to check for proper flag usage, etc., do pre-amble
+ * processing (incrementing handle counts, handling auto-commit), call the
+ * function and then do post-amble processing (DB_AUTO_COMMIT, dec handle
+ * counts).
+ *
+ * So, the basic structure is:
+ *	Check for generic errors
+ *	Call function-specific check routine
+ *	Increment handle count
+ *	Create internal transaction if necessary
+ *	Call underlying worker function
+ *	Commit/abort internal transaction if necessary
+ *	Decrement handle count
+ */
+
+/*
+ * __db_associate_pp --
+ *	DB->associate pre/post processing.
  *
- * PUBLIC: int __db_cursorchk __P((const DB *, u_int32_t));
+ * PUBLIC: int __db_associate_pp __P((DB *, DB_TXN *, DB *,
+ * PUBLIC:     int (*)(DB *, const DBT *, const DBT *, DBT *), u_int32_t));
  */
 int
-__db_cursorchk(dbp, flags)
-	const DB *dbp;
+__db_associate_pp(dbp, txn, sdbp, callback, flags)
+	DB *dbp, *sdbp;
+	DB_TXN *txn;
+	int (*callback) __P((DB *, const DBT *, const DBT *, DBT *));
 	u_int32_t flags;
 {
-	/* DB_DIRTY_READ is the only valid bit-flag and requires locking. */
-	if (LF_ISSET(DB_DIRTY_READ)) {
-		if (!LOCKING_ON(dbp->dbenv))
-			return (__db_fnl(dbp->dbenv, "DB->cursor"));
-		LF_CLR(DB_DIRTY_READ);
+	DBC *sdbc;
+	DB_ENV *dbenv;
+	int handle_check, ret, txn_local;
+
+	dbenv = dbp->dbenv;
+
+	PANIC_CHECK(dbenv);
+
+	if ((ret = __db_associate_arg(dbp, sdbp, callback, flags)) != 0)
+		return (ret);
+
+	/*
+	 * Secondary cursors may have the primary's lock file ID, so we need
+	 * to make sure that no older cursors are lying around when we make
+	 * the transition.
+	 */
+	if (TAILQ_FIRST(&sdbp->active_queue) != NULL ||
+	    TAILQ_FIRST(&sdbp->join_queue) != NULL) {
+		__db_err(dbenv,
+    "Databases may not become secondary indices while cursors are open");
+		return (EINVAL);
+	}
+
+	/*
+	 * Create a local transaction as necessary, check for consistent
+	 * transaction usage, and, if we have no transaction but do have
+	 * locking on, acquire a locker id for the handle lock acquisition.
+	 */
+	txn_local = 0;
+	if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
+		if ((ret = __db_txn_auto_init(dbenv, &txn)) != 0)
+			return (ret);
+		txn_local = 1;
+		LF_CLR(DB_AUTO_COMMIT);
+	} else if (txn != NULL && !TXN_ON(dbenv))
+		return (__db_not_txn_env(dbenv));
+
+	/* Check for consistent transaction usage. */
+	if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0)) != 0)
+		goto err;
+
+	/* Check for replication block. */
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, txn != NULL)) != 0)
+		goto err;
+
+	while ((sdbc = TAILQ_FIRST(&sdbp->free_queue)) != NULL)
+		if ((ret = __db_c_destroy(sdbc)) != 0)
+			break;
+
+	if (ret == 0)
+		ret = __db_associate(dbp, txn, sdbp, callback, flags);
+
+	/* Release replication block. */
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
+
+err:	return (txn_local ? __db_txn_auto_resolve(dbenv, txn, 0, ret) : ret);
+}
+
+/*
+ * __db_associate_arg --
+ *	Check DB->associate arguments.
+ */
+static int
+__db_associate_arg(dbp, sdbp, callback, flags)
+	DB *dbp, *sdbp;
+	int (*callback) __P((DB *, const DBT *, const DBT *, DBT *));
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	int ret;
+
+	dbenv = dbp->dbenv;
+
+	if (F_ISSET(sdbp, DB_AM_SECONDARY)) {
+		__db_err(dbenv,
+		    "Secondary index handles may not be re-associated");
+		return (EINVAL);
+	}
+	if (F_ISSET(dbp, DB_AM_SECONDARY)) {
+		__db_err(dbenv,
+		    "Secondary indices may not be used as primary databases");
+		return (EINVAL);
+	}
+	if (F_ISSET(dbp, DB_AM_DUP)) {
+		__db_err(dbenv,
+		    "Primary databases may not be configured with duplicates");
+		return (EINVAL);
+	}
+	if (F_ISSET(dbp, DB_AM_RENUMBER)) {
+		__db_err(dbenv,
+	    "Renumbering recno databases may not be used as primary databases");
+		return (EINVAL);
+	}
+	if (dbp->dbenv != sdbp->dbenv &&
+	    (!F_ISSET(dbp->dbenv, DB_ENV_DBLOCAL) ||
+	     !F_ISSET(sdbp->dbenv, DB_ENV_DBLOCAL))) {
+		__db_err(dbenv,
+	    "The primary and secondary must be opened in the same environment");
+		return (EINVAL);
+	}
+	if ((DB_IS_THREADED(dbp) && !DB_IS_THREADED(sdbp)) ||
+	    (!DB_IS_THREADED(dbp) && DB_IS_THREADED(sdbp))) {
+		__db_err(dbenv,
+	    "The DB_THREAD setting must be the same for primary and secondary");
+		return (EINVAL);
+	}
+	if (callback == NULL &&
+	    (!F_ISSET(dbp, DB_AM_RDONLY) || !F_ISSET(sdbp, DB_AM_RDONLY))) {
+		__db_err(dbenv,
+    "Callback function may be NULL only when database handles are read-only");
+		return (EINVAL);
+	}
+
+	if ((ret = __db_fchk(dbenv,
+	    "DB->associate", flags, DB_CREATE | DB_AUTO_COMMIT)) != 0)
+		return (ret);
+
+	return (0);
+}
+
+/*
+ * __db_close_pp --
+ *	DB->close pre/post processing.
+ *
+ * PUBLIC: int __db_close_pp __P((DB *, u_int32_t));
+ */
+int
+__db_close_pp(dbp, flags)
+	DB *dbp;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	int handle_check, ret, t_ret;
+
+	dbenv = dbp->dbenv;
+	ret = 0;
+
+	PANIC_CHECK(dbenv);
+
+	/*
+	 * !!!
+	 * The actual argument checking is simple, do it inline.
+	 *
+	 * Validate arguments and complain if they're wrong, but as a DB
+	 * handle destructor, we can't fail.
+	 */
+	if (flags != 0 && flags != DB_NOSYNC &&
+	    (t_ret = __db_ferr(dbenv, "DB->close", 0)) != 0 && ret == 0)
+		ret = t_ret;
+
+	/* Check for replication block. */
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check &&
+	    (t_ret = __db_rep_enter(dbp, 0, 0, 0)) != 0) {
+		handle_check = 0;
+		if (ret == 0)
+			ret = t_ret;
+	}
+
+	if ((t_ret = __db_close(dbp, NULL, flags)) != 0 && ret == 0)
+		ret = t_ret;
+
+	/* Release replication block. */
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
+
+	return (ret);
+}
+
+/*
+ * __db_cursor_pp --
+ *	DB->cursor pre/post processing.
+ *
+ * PUBLIC: int __db_cursor_pp __P((DB *, DB_TXN *, DBC **, u_int32_t));
+ */
+int
+__db_cursor_pp(dbp, txn, dbcp, flags)
+	DB *dbp;
+	DB_TXN *txn;
+	DBC **dbcp;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	int handle_check, ret;
+
+	dbenv = dbp->dbenv;
+
+	PANIC_CHECK(dbenv);
+	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->cursor");
+
+	if ((ret = __db_cursor_arg(dbp, flags)) != 0)
+		return (ret);
+
+	/*
+	 * Check for consistent transaction usage.  For now, assume that
+	 * this cursor might be used for read operations only (in which
+	 * case it may not require a txn).  We'll check more stringently
+	 * in c_del and c_put.  (Note that this all means that the
+	 * read-op txn tests have to be a subset of the write-op ones.)
+	 */
+	if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 1)) != 0)
+		return (ret);
+
+	/* Check for replication block. */
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, txn != NULL)) != 0)
+		return (ret);
+
+	ret = __db_cursor(dbp, txn, dbcp, flags);
+
+	/* Release replication block. */
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
+
+	return (ret);
+}
+
+/*
+ * __db_cursor --
+ *	DB->cursor.
+ *
+ * PUBLIC: int __db_cursor __P((DB *, DB_TXN *, DBC **, u_int32_t));
+ */
+int
+__db_cursor(dbp, txn, dbcp, flags)
+	DB *dbp;
+	DB_TXN *txn;
+	DBC **dbcp;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	DBC *dbc;
+	db_lockmode_t mode;
+	u_int32_t op;
+	int ret;
+
+	dbenv = dbp->dbenv;
+
+	if ((ret = __db_cursor_int(dbp,
+	    txn, dbp->type, PGNO_INVALID, 0, DB_LOCK_INVALIDID, &dbc)) != 0)
+		return (ret);
+
+	/*
+	 * If this is CDB, do all the locking in the interface, which is
+	 * right here.
+	 */
+	if (CDB_LOCKING(dbenv)) {
+		op = LF_ISSET(DB_OPFLAGS_MASK);
+		mode = (op == DB_WRITELOCK) ? DB_LOCK_WRITE :
+		    ((op == DB_WRITECURSOR) ? DB_LOCK_IWRITE : DB_LOCK_READ);
+		if ((ret = __lock_get(dbenv, dbc->locker, 0,
+		    &dbc->lock_dbt, mode, &dbc->mylock)) != 0)
+			goto err;
+		if (op == DB_WRITECURSOR)
+			F_SET(dbc, DBC_WRITECURSOR);
+		if (op == DB_WRITELOCK)
+			F_SET(dbc, DBC_WRITER);
+	}
+
+	if (LF_ISSET(DB_DIRTY_READ) ||
+	    (txn != NULL && F_ISSET(txn, TXN_DIRTY_READ)))
+		F_SET(dbc, DBC_DIRTY_READ);
+
+	if (LF_ISSET(DB_DEGREE_2) ||
+	    (txn != NULL && F_ISSET(txn, TXN_DEGREE_2)))
+		F_SET(dbc, DBC_DEGREE_2);
+
+	*dbcp = dbc;
+	return (0);
+
+err:	(void)__db_c_close(dbc);
+	return (ret);
+}
+
+/*
+ * __db_cursor_arg --
+ *	Check DB->cursor arguments.
+ */
+static int
+__db_cursor_arg(dbp, flags)
+	DB *dbp;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbp->dbenv;
+
+	/*
+	 * DB_DIRTY_READ  and DB_DGREE_2 are the only valid bit-flags
+	 * and requires locking.
+	 */
+	if (LF_ISSET(DB_DIRTY_READ | DB_DEGREE_2)) {
+		if (!LOCKING_ON(dbenv))
+			return (__db_fnl(dbenv, "DB->cursor"));
+		LF_CLR(DB_DIRTY_READ | DB_DEGREE_2);
 	}
 
 	/* Check for invalid function flags. */
@@ -58,98 +391,1387 @@ __db_cursorchk(dbp, flags)
 		break;
 	case DB_WRITECURSOR:
 		if (IS_READONLY(dbp))
-			return (__db_rdonly(dbp->dbenv, "DB->cursor"));
-		if (!CDB_LOCKING(dbp->dbenv))
-			return (__db_ferr(dbp->dbenv, "DB->cursor", 0));
+			return (__db_rdonly(dbenv, "DB->cursor"));
+		if (!CDB_LOCKING(dbenv))
+			return (__db_ferr(dbenv, "DB->cursor", 0));
 		break;
 	case DB_WRITELOCK:
 		if (IS_READONLY(dbp))
-			return (__db_rdonly(dbp->dbenv, "DB->cursor"));
+			return (__db_rdonly(dbenv, "DB->cursor"));
 		break;
 	default:
-		return (__db_ferr(dbp->dbenv, "DB->cursor", 0));
+		return (__db_ferr(dbenv, "DB->cursor", 0));
 	}
 
 	return (0);
 }
 
 /*
- * __db_ccountchk --
- *	Common cursor count argument checking routine.
+ * __db_del_pp --
+ *	DB->del pre/post processing.
  *
- * PUBLIC: int __db_ccountchk __P((const DB *, u_int32_t, int));
+ * PUBLIC: int __db_del_pp __P((DB *, DB_TXN *, DBT *, u_int32_t));
  */
 int
-__db_ccountchk(dbp, flags, isvalid)
-	const DB *dbp;
+__db_del_pp(dbp, txn, key, flags)
+	DB *dbp;
+	DB_TXN *txn;
+	DBT *key;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	int handle_check, ret, txn_local;
+
+	dbenv = dbp->dbenv;
+
+	PANIC_CHECK(dbenv);
+	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->del");
+
+	if ((ret = __db_del_arg(dbp, flags)) != 0)
+		return (ret);
+
+	/* Create local transaction as necessary. */
+	if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
+		if ((ret = __db_txn_auto_init(dbenv, &txn)) != 0)
+			return (ret);
+		txn_local = 1;
+		LF_CLR(DB_AUTO_COMMIT);
+	} else
+		txn_local = 0;
+
+	/* Check for consistent transaction usage. */
+	if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0)) != 0)
+		goto err;
+
+	/* Check for replication block. */
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, txn != NULL)) != 0)
+		goto err;
+
+	ret = __db_del(dbp, txn, key, flags);
+
+	/* Release replication block. */
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
+
+err:	return (txn_local ? __db_txn_auto_resolve(dbenv, txn, 0, ret) : ret);
+}
+
+/*
+ * __db_del_arg --
+ *	Check DB->delete arguments.
+ */
+static int
+__db_del_arg(dbp, flags)
+	DB *dbp;
 	u_int32_t flags;
-	int isvalid;
 {
+	DB_ENV *dbenv;
+
+	dbenv = dbp->dbenv;
+
+	/* Check for changes to a read-only tree. */
+	if (IS_READONLY(dbp))
+		return (__db_rdonly(dbenv, "DB->del"));
+
 	/* Check for invalid function flags. */
+	LF_CLR(DB_AUTO_COMMIT);
 	switch (flags) {
 	case 0:
 		break;
 	default:
-		return (__db_ferr(dbp->dbenv, "DBcursor->c_count", 0));
+		return (__db_ferr(dbenv, "DB->del", 0));
 	}
 
+	return (0);
+}
+
+/*
+ * db_fd_pp --
+ *	DB->fd pre/post processing.
+ *
+ * PUBLIC: int __db_fd_pp __P((DB *, int *));
+ */
+int
+__db_fd_pp(dbp, fdp)
+	DB *dbp;
+	int *fdp;
+{
+	DB_ENV *dbenv;
+	DB_FH *fhp;
+	int handle_check, ret;
+
+	dbenv = dbp->dbenv;
+
+	PANIC_CHECK(dbenv);
+	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->fd");
+
+	/* Check for replication block. */
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, 0)) != 0)
+		return (ret);
+
 	/*
-	 * The cursor must be initialized, return EINVAL for an invalid cursor,
-	 * otherwise 0.
+	 * !!!
+	 * There's no argument checking to be done.
+	 *
+	 * !!!
+	 * The actual method call is simple, do it inline.
+	 *
+	 * XXX
+	 * Truly spectacular layering violation.
 	 */
-	return (isvalid ? 0 : __db_curinval(dbp->dbenv));
+	if ((ret = __mp_xxx_fh(dbp->mpf, &fhp)) != 0)
+		goto err;
+
+	if (fhp == NULL) {
+		*fdp = -1;
+		__db_err(dbenv,
+		    "Database does not have a valid file handle");
+		ret = ENOENT;
+	} else
+		*fdp = fhp->fd;
+
+err:	/* Release replication block. */
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
+
+	return (ret);
 }
 
 /*
- * __db_cdelchk --
- *	Common cursor delete argument checking routine.
+ * __db_get_pp --
+ *	DB->get pre/post processing.
  *
- * PUBLIC: int __db_cdelchk __P((const DB *, u_int32_t, int));
+ * PUBLIC: int __db_get_pp __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
  */
 int
-__db_cdelchk(dbp, flags, isvalid)
-	const DB *dbp;
+__db_get_pp(dbp, txn, key, data, flags)
+	DB *dbp;
+	DB_TXN *txn;
+	DBT *key, *data;
 	u_int32_t flags;
-	int isvalid;
 {
-	/* Check for changes to a read-only tree. */
-	if (IS_READONLY(dbp))
-		return (__db_rdonly(dbp->dbenv, "c_del"));
+	DB_ENV *dbenv;
+	u_int32_t mode;
+	int handle_check, ret, txn_local;
 
-	/* Check for invalid function flags. */
-	switch (flags) {
-	case 0:
-		break;
-	case DB_UPDATE_SECONDARY:
-		DB_ASSERT(F_ISSET(dbp, DB_AM_SECONDARY));
-		break;
-	default:
-		return (__db_ferr(dbp->dbenv, "DBcursor->c_del", 0));
+	dbenv = dbp->dbenv;
+
+	PANIC_CHECK(dbenv);
+	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->get");
+
+	if ((ret = __db_get_arg(dbp, key, data, flags)) != 0)
+		return (ret);
+
+	mode = 0;
+	txn_local = 0;
+	if (LF_ISSET(DB_DIRTY_READ))
+		mode = DB_DIRTY_READ;
+	else if ((flags & DB_OPFLAGS_MASK) == DB_CONSUME ||
+	    (flags & DB_OPFLAGS_MASK) == DB_CONSUME_WAIT) {
+		mode = DB_WRITELOCK;
+		if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
+			if ((ret = __db_txn_auto_init(dbenv, &txn)) != 0)
+				return (ret);
+			txn_local = 1;
+			LF_CLR(DB_AUTO_COMMIT);
+		}
 	}
 
-	/*
-	 * The cursor must be initialized, return EINVAL for an invalid cursor,
-	 * otherwise 0.
+	/* Check for consistent transaction usage. */
+	if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID,
+	    mode == DB_WRITELOCK || LF_ISSET(DB_RMW) ? 0 : 1)) != 0)
+		goto err;
+
+	/* Check for replication block. */
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, txn != NULL)) != 0)
+		goto err;
+
+	ret = __db_get(dbp, txn, key, data, flags);
+
+	/* Release replication block. */
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
+
+err:	return (txn_local ? __db_txn_auto_resolve(dbenv, txn, 0, ret) : ret);
+}
+
+/*
+ * __db_get --
+ *	DB->get.
+ *
+ * PUBLIC: int __db_get __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
+ */
+int
+__db_get(dbp, txn, key, data, flags)
+	DB *dbp;
+	DB_TXN *txn;
+	DBT *key, *data;
+	u_int32_t flags;
+{
+	DBC *dbc;
+	u_int32_t mode;
+	int ret, t_ret;
+
+	mode = 0;
+	if (LF_ISSET(DB_DIRTY_READ)) {
+		mode = DB_DIRTY_READ;
+		LF_CLR(DB_DIRTY_READ);
+	} else if (LF_ISSET(DB_DEGREE_2)) {
+		mode = DB_DEGREE_2;
+		LF_CLR(DB_DEGREE_2);
+	} else if ((flags & DB_OPFLAGS_MASK) == DB_CONSUME ||
+	    (flags & DB_OPFLAGS_MASK) == DB_CONSUME_WAIT)
+		mode = DB_WRITELOCK;
+
+	if ((ret = __db_cursor(dbp, txn, &dbc, mode)) != 0)
+		return (ret);
+
+	DEBUG_LREAD(dbc, txn, "DB->get", key, NULL, flags);
+
+	/*
+	 * The DBC_TRANSIENT flag indicates that we're just doing a
+	 * single operation with this cursor, and that in case of
+	 * error we don't need to restore it to its old position--we're
+	 * going to close it right away.  Thus, we can perform the get
+	 * without duplicating the cursor, saving some cycles in this
+	 * common case.
+	 */
+	F_SET(dbc, DBC_TRANSIENT);
+
+	/*
+	 * SET_RET_MEM indicates that if key and/or data have no DBT
+	 * flags set and DB manages the returned-data memory, that memory
+	 * will belong to this handle, not to the underlying cursor.
+	 */
+	SET_RET_MEM(dbc, dbp);
+
+	if (LF_ISSET(~(DB_RMW | DB_MULTIPLE)) == 0)
+		LF_SET(DB_SET);
+
+	ret = __db_c_get(dbc, key, data, flags);
+
+	if (dbc != NULL && (t_ret = __db_c_close(dbc)) != 0 && ret == 0)
+		ret = t_ret;
+
+	return (ret);
+}
+
+/*
+ * __db_get_arg --
+ *	DB->get argument checking, used by both DB->get and DB->pget.
+ */
+static int
+__db_get_arg(dbp, key, data, flags)
+	const DB *dbp;
+	const DBT *key;
+	DBT *data;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	int check_thread, dirty, multi, ret;
+
+	dbenv = dbp->dbenv;
+
+	/*
+	 * Check for read-modify-write validity.  DB_RMW doesn't make sense
+	 * with CDB cursors since if you're going to write the cursor, you
+	 * had to create it with DB_WRITECURSOR.  Regardless, we check for
+	 * LOCKING_ON and not STD_LOCKING, as we don't want to disallow it.
+	 * If this changes, confirm that DB does not itself set the DB_RMW
+	 * flag in a path where CDB may have been configured.
+	 */
+	check_thread = dirty = 0;
+	if (LF_ISSET(DB_DIRTY_READ | DB_RMW | DB_DEGREE_2)) {
+		if (!LOCKING_ON(dbenv))
+			return (__db_fnl(dbenv, "DB->get"));
+		dirty = LF_ISSET(DB_DIRTY_READ | DB_DEGREE_2);
+		if ((ret = __db_fcchk(dbenv,
+		    "DB->get", flags, DB_DIRTY_READ, DB_DEGREE_2)) != 0)
+			return (ret);
+		LF_CLR(DB_DIRTY_READ | DB_RMW | DB_DEGREE_2);
+	}
+
+	multi = 0;
+	if (LF_ISSET(DB_MULTIPLE | DB_MULTIPLE_KEY)) {
+		if (LF_ISSET(DB_MULTIPLE_KEY))
+			goto multi_err;
+		multi = LF_ISSET(DB_MULTIPLE) ? 1 : 0;
+		LF_CLR(DB_MULTIPLE);
+	}
+
+	if (LF_ISSET(DB_AUTO_COMMIT)) {
+		LF_CLR(DB_AUTO_COMMIT);
+		if (flags != DB_CONSUME && flags != DB_CONSUME_WAIT)
+			goto err;
+	}
+
+	/* Check for invalid function flags. */
+	switch (flags) {
+	case 0:
+	case DB_GET_BOTH:
+		break;
+	case DB_SET_RECNO:
+		check_thread = 1;
+		if (!F_ISSET(dbp, DB_AM_RECNUM))
+			goto err;
+		break;
+	case DB_CONSUME:
+	case DB_CONSUME_WAIT:
+		check_thread = 1;
+		if (dirty) {
+			__db_err(dbenv,
+    "%s is not supported with DB_CONSUME or DB_CONSUME_WAIT",
+			     LF_ISSET(DB_DIRTY_READ) ?
+			     "DB_DIRTY_READ" : "DB_DEGREE_2");
+			return (EINVAL);
+		}
+		if (multi)
+multi_err:		return (__db_ferr(dbenv, "DB->get", 1));
+		if (dbp->type == DB_QUEUE)
+			break;
+		/* FALLTHROUGH */
+	default:
+err:		return (__db_ferr(dbenv, "DB->get", 0));
+	}
+
+	/*
+	 * Check for invalid key/data flags.
+	 *
+	 * XXX: Dave Krinsky
+	 * Remember to modify this when we fix the flag-returning problem.
+	 */
+	if ((ret = __dbt_ferr(dbp, "key", key, check_thread)) != 0)
+		return (ret);
+	if ((ret = __dbt_ferr(dbp, "data", data, 1)) != 0)
+		return (ret);
+
+	if (multi) {
+		if (!F_ISSET(data, DB_DBT_USERMEM)) {
+			__db_err(dbenv,
+			    "DB_MULTIPLE requires DB_DBT_USERMEM be set");
+			return (EINVAL);
+		}
+		if (F_ISSET(key, DB_DBT_PARTIAL) ||
+		    F_ISSET(data, DB_DBT_PARTIAL)) {
+			__db_err(dbenv,
+			    "DB_MULTIPLE does not support DB_DBT_PARTIAL");
+			return (EINVAL);
+		}
+		if (data->ulen < 1024 ||
+		    data->ulen < dbp->pgsize || data->ulen % 1024 != 0) {
+			__db_err(dbenv, "%s%s",
+			    "DB_MULTIPLE buffers must be ",
+			    "aligned, at least page size and multiples of 1KB");
+			return (EINVAL);
+		}
+	}
+
+	return (0);
+}
+
+/*
+ * __db_join_pp --
+ *	DB->join pre/post processing.
+ *
+ * PUBLIC: int __db_join_pp __P((DB *, DBC **, DBC **, u_int32_t));
+ */
+int
+__db_join_pp(primary, curslist, dbcp, flags)
+	DB *primary;
+	DBC **curslist, **dbcp;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	int handle_check, ret;
+
+	dbenv = primary->dbenv;
+
+	PANIC_CHECK(dbenv);
+
+	if ((ret = __db_join_arg(primary, curslist, flags)) != 0)
+		return (ret);
+
+	/* Check for replication block. */
+	handle_check = IS_REPLICATED(dbenv, primary);
+	if (handle_check && (ret =
+	    __db_rep_enter(primary, 1, 0, curslist[0]->txn != NULL)) != 0)
+		return (ret);
+
+	ret = __db_join(primary, curslist, dbcp, flags);
+
+	/* Release replication block. */
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
+
+	return (ret);
+}
+
+/*
+ * __db_join_arg --
+ *	Check DB->join arguments.
+ */
+static int
+__db_join_arg(primary, curslist, flags)
+	DB *primary;
+	DBC **curslist;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	DB_TXN *txn;
+	int i;
+
+	dbenv = primary->dbenv;
+
+	switch (flags) {
+	case 0:
+	case DB_JOIN_NOSORT:
+		break;
+	default:
+		return (__db_ferr(dbenv, "DB->join", 0));
+	}
+
+	if (curslist == NULL || curslist[0] == NULL) {
+		__db_err(dbenv,
+	    "At least one secondary cursor must be specified to DB->join");
+		return (EINVAL);
+	}
+
+	txn = curslist[0]->txn;
+	for (i = 1; curslist[i] != NULL; i++)
+		if (curslist[i]->txn != txn) {
+			__db_err(dbenv,
+		    "All secondary cursors must share the same transaction");
+			return (EINVAL);
+		}
+
+	return (0);
+}
+
+/*
+ * __db_key_range_pp --
+ *	DB->key_range pre/post processing.
+ *
+ * PUBLIC: int __db_key_range_pp
+ * PUBLIC:     __P((DB *, DB_TXN *, DBT *, DB_KEY_RANGE *, u_int32_t));
+ */
+int
+__db_key_range_pp(dbp, txn, key, kr, flags)
+	DB *dbp;
+	DB_TXN *txn;
+	DBT *key;
+	DB_KEY_RANGE *kr;
+	u_int32_t flags;
+{
+	DBC *dbc;
+	DB_ENV *dbenv;
+	int handle_check, ret, t_ret;
+
+	dbenv = dbp->dbenv;
+
+	PANIC_CHECK(dbp->dbenv);
+	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->key_range");
+
+	/*
+	 * !!!
+	 * The actual argument checking is simple, do it inline.
+	 */
+	if (flags != 0)
+		return (__db_ferr(dbenv, "DB->key_range", 0));
+
+	/* Check for consistent transaction usage. */
+	if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 1)) != 0)
+		return (ret);
+
+	/* Check for replication block. */
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, txn != NULL)) != 0)
+		return (ret);
+
+	/*
+	 * !!!
+	 * The actual method call is simple, do it inline.
+	 */
+	switch (dbp->type) {
+	case DB_BTREE:
+		/* Acquire a cursor. */
+		if ((ret = __db_cursor(dbp, txn, &dbc, 0)) != 0)
+			break;
+
+		DEBUG_LWRITE(dbc, NULL, "bam_key_range", NULL, NULL, 0);
+
+		ret = __bam_key_range(dbc, key, kr, flags);
+
+		if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
+			ret = t_ret;
+		break;
+	case DB_HASH:
+	case DB_QUEUE:
+	case DB_RECNO:
+		ret = __dbh_am_chk(dbp, DB_OK_BTREE);
+		break;
+	case DB_UNKNOWN:
+	default:
+		ret = __db_unknown_type(dbenv, "DB->key_range", dbp->type);
+		break;
+	}
+
+	/* Release replication block. */
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
+
+	return (ret);
+}
+
+/*
+ * __db_open_pp --
+ *	DB->open pre/post processing.
+ *
+ * PUBLIC: int __db_open_pp __P((DB *, DB_TXN *,
+ * PUBLIC:     const char *, const char *, DBTYPE, u_int32_t, int));
+ */
+int
+__db_open_pp(dbp, txn, fname, dname, type, flags, mode)
+	DB *dbp;
+	DB_TXN *txn;
+	const char *fname, *dname;
+	DBTYPE type;
+	u_int32_t flags;
+	int mode;
+{
+	DB_ENV *dbenv;
+	int handle_check, nosync, remove_me, ret, txn_local;
+
+	dbenv = dbp->dbenv;
+	nosync = 1;
+	remove_me = 0;
+
+	PANIC_CHECK(dbenv);
+
+	if ((ret = __db_open_arg(dbp, txn, fname, dname, type, flags)) != 0)
+		return (ret);
+
+	/*
+	 * Save the file and database names and flags.  We do this here
+	 * because we don't pass all of the flags down into the actual
+	 * DB->open method call, we strip DB_AUTO_COMMIT at this layer.
+	 */
+	if ((fname != NULL &&
+	    (ret = __os_strdup(dbenv, fname, &dbp->fname)) != 0) ||
+	    (dname != NULL &&
+	    (ret = __os_strdup(dbenv, dname, &dbp->dname)) != 0))
+		return (ret);
+	dbp->open_flags = flags;
+
+	/* Save the current DB handle flags for refresh. */
+	dbp->orig_flags = dbp->flags;
+
+	/*
+	 * Create local transaction as necessary, check for consistent
+	 * transaction usage.
+	 */
+	txn_local = 0;
+	if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
+		if ((ret = __db_txn_auto_init(dbenv, &txn)) != 0)
+			return (ret);
+		txn_local = 1;
+		LF_CLR(DB_AUTO_COMMIT);
+	} else
+		if (txn != NULL && !TXN_ON(dbenv))
+			return (__db_not_txn_env(dbenv));
+
+	/* Check for replication block. */
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check &&
+	    (ret = __db_rep_enter(dbp, 1, 0, txn != NULL)) != 0) {
+		handle_check = 0;
+		goto err;
+	}
+
+	if ((ret = __db_open(dbp,
+	    txn, fname, dname, type, flags, mode, PGNO_BASE_MD)) != 0)
+		goto err;
+
+	/*
+	 * You can open the database that describes the subdatabases in the
+	 * rest of the file read-only.  The content of each key's data is
+	 * unspecified and applications should never be adding new records
+	 * or updating existing records.  However, during recovery, we need
+	 * to open these databases R/W so we can redo/undo changes in them.
+	 * Likewise, we need to open master databases read/write during
+	 * rename and remove so we can be sure they're fully sync'ed, so
+	 * we provide an override flag for the purpose.
+	 */
+	if (dname == NULL && !IS_RECOVERING(dbenv) && !LF_ISSET(DB_RDONLY) &&
+	    !LF_ISSET(DB_RDWRMASTER) && F_ISSET(dbp, DB_AM_SUBDB)) {
+		__db_err(dbenv,
+    "files containing multiple databases may only be opened read-only");
+		ret = EINVAL;
+		goto err;
+	}
+
+	/*
+	 * Success: file creations have to be synchronous, otherwise we don't
+	 * care.
+	 */
+	if (F_ISSET(dbp, DB_AM_CREATED | DB_AM_CREATED_MSTR))
+		nosync = 0;
+
+	/* Success: don't discard the file on close. */
+	F_CLR(dbp, DB_AM_DISCARD | DB_AM_CREATED | DB_AM_CREATED_MSTR);
+
+	/*
+	 * If not transactional, remove the databases/subdatabases.  If we're
+	 * transactional, the child transaction abort cleans up.
+	 */
+err:	if (ret != 0 && txn == NULL) {
+		remove_me = F_ISSET(dbp, DB_AM_CREATED);
+		if (F_ISSET(dbp, DB_AM_CREATED_MSTR) ||
+		    (dname == NULL && remove_me))
+			/* Remove file. */
+			(void)__db_remove_int(dbp, txn, fname, NULL, DB_FORCE);
+		else if (remove_me)
+			/* Remove subdatabase. */
+			(void)__db_remove_int(dbp, txn, fname, dname, DB_FORCE);
+	}
+
+	/* Release replication block. */
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
+
+	return (txn_local ?
+	    __db_txn_auto_resolve(dbenv, txn, nosync, ret) : ret);
+}
+
+/*
+ * __db_open_arg --
+ *	Check DB->open arguments.
+ */
+static int
+__db_open_arg(dbp, txn, fname, dname, type, flags)
+	DB *dbp;
+	DB_TXN *txn;
+	const char *fname, *dname;
+	DBTYPE type;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	u_int32_t ok_flags;
+	int ret;
+
+	dbenv = dbp->dbenv;
+
+	/* Validate arguments. */
+#undef	OKFLAGS
+#define	OKFLAGS								\
+    (DB_AUTO_COMMIT | DB_CREATE | DB_DIRTY_READ | DB_EXCL |		\
+     DB_FCNTL_LOCKING | DB_NO_AUTO_COMMIT | DB_NOMMAP | DB_RDONLY |	\
+     DB_RDWRMASTER | DB_THREAD | DB_TRUNCATE | DB_WRITEOPEN)
+	if ((ret = __db_fchk(dbenv, "DB->open", flags, OKFLAGS)) != 0)
+		return (ret);
+	if (LF_ISSET(DB_EXCL) && !LF_ISSET(DB_CREATE))
+		return (__db_ferr(dbenv, "DB->open", 1));
+	if (LF_ISSET(DB_RDONLY) && LF_ISSET(DB_CREATE))
+		return (__db_ferr(dbenv, "DB->open", 1));
+
+#ifdef	HAVE_VXWORKS
+	if (LF_ISSET(DB_TRUNCATE)) {
+		__db_err(dbenv, "DB_TRUNCATE not supported on VxWorks");
+		return (DB_OPNOTSUP);
+	}
+#endif
+	switch (type) {
+	case DB_UNKNOWN:
+		if (LF_ISSET(DB_CREATE|DB_TRUNCATE)) {
+			__db_err(dbenv,
+	    "%s: DB_UNKNOWN type specified with DB_CREATE or DB_TRUNCATE",
+			    fname);
+			return (EINVAL);
+		}
+		ok_flags = 0;
+		break;
+	case DB_BTREE:
+		ok_flags = DB_OK_BTREE;
+		break;
+	case DB_HASH:
+#ifndef HAVE_HASH
+		return (__db_no_hash_am(dbenv));
+#endif
+		ok_flags = DB_OK_HASH;
+		break;
+	case DB_QUEUE:
+#ifndef HAVE_QUEUE
+		return (__db_no_queue_am(dbenv));
+#endif
+		ok_flags = DB_OK_QUEUE;
+		break;
+	case DB_RECNO:
+		ok_flags = DB_OK_RECNO;
+		break;
+	default:
+		__db_err(dbenv, "unknown type: %lu", (u_long)type);
+		return (EINVAL);
+	}
+	if (ok_flags)
+		DB_ILLEGAL_METHOD(dbp, ok_flags);
+
+	/* The environment may have been created, but never opened. */
+	if (!F_ISSET(dbenv, DB_ENV_DBLOCAL | DB_ENV_OPEN_CALLED)) {
+		__db_err(dbenv, "environment not yet opened");
+		return (EINVAL);
+	}
+
+	/*
+	 * Historically, you could pass in an environment that didn't have a
+	 * mpool, and DB would create a private one behind the scenes.  This
+	 * no longer works.
+	 */
+	if (!F_ISSET(dbenv, DB_ENV_DBLOCAL) && !MPOOL_ON(dbenv)) {
+		__db_err(dbenv, "environment did not include a memory pool");
+		return (EINVAL);
+	}
+
+	/*
+	 * You can't specify threads during DB->open if subsystems in the
+	 * environment weren't configured with them.
+	 */
+	if (LF_ISSET(DB_THREAD) &&
+	    !F_ISSET(dbenv, DB_ENV_DBLOCAL | DB_ENV_THREAD)) {
+		__db_err(dbenv, "environment not created using DB_THREAD");
+		return (EINVAL);
+	}
+
+	/* DB_TRUNCATE is neither transaction recoverable nor lockable. */
+	if (LF_ISSET(DB_TRUNCATE) && (LOCKING_ON(dbenv) || txn != NULL)) {
+		__db_err(dbenv,
+		    "DB_TRUNCATE illegal with %s specified",
+		    LOCKING_ON(dbenv) ? "locking" : "transactions");
+		return (EINVAL);
+	}
+
+	/* Subdatabase checks. */
+	if (dname != NULL) {
+		/* Subdatabases must be created in named files. */
+		if (fname == NULL) {
+			__db_err(dbenv,
+		    "multiple databases cannot be created in temporary files");
+			return (EINVAL);
+		}
+
+		/* QAM can't be done as a subdatabase. */
+		if (type == DB_QUEUE) {
+			__db_err(dbenv, "Queue databases must be one-per-file");
+			return (EINVAL);
+		}
+	}
+
+	return (0);
+}
+
+/*
+ * __db_pget_pp --
+ *	DB->pget pre/post processing.
+ *
+ * PUBLIC: int __db_pget_pp
+ * PUBLIC:     __P((DB *, DB_TXN *, DBT *, DBT *, DBT *, u_int32_t));
+ */
+int
+__db_pget_pp(dbp, txn, skey, pkey, data, flags)
+	DB *dbp;
+	DB_TXN *txn;
+	DBT *skey, *pkey, *data;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	int handle_check, ret;
+
+	dbenv = dbp->dbenv;
+
+	PANIC_CHECK(dbenv);
+	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->pget");
+
+	if ((ret = __db_pget_arg(dbp, pkey, flags)) != 0)
+		return (ret);
+
+	if ((ret = __db_get_arg(dbp, skey, data, flags)) != 0)
+		return (ret);
+
+	/* Check for replication block. */
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, txn != NULL)) != 0)
+		return (ret);
+
+	ret = __db_pget(dbp, txn, skey, pkey, data, flags);
+
+	/* Release replication block. */
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
+
+	return (ret);
+}
+
+/*
+ * __db_pget --
+ *	DB->pget.
+ *
+ * PUBLIC: int __db_pget
+ * PUBLIC:     __P((DB *, DB_TXN *, DBT *, DBT *, DBT *, u_int32_t));
+ */
+int
+__db_pget(dbp, txn, skey, pkey, data, flags)
+	DB *dbp;
+	DB_TXN *txn;
+	DBT *skey, *pkey, *data;
+	u_int32_t flags;
+{
+	DBC *dbc;
+	int ret, t_ret;
+
+	if ((ret = __db_cursor(dbp, txn, &dbc, 0)) != 0)
+		return (ret);
+
+	SET_RET_MEM(dbc, dbp);
+
+	DEBUG_LREAD(dbc, txn, "__db_pget", skey, NULL, flags);
+
+	/*
+	 * !!!
+	 * The actual method call is simple, do it inline.
+	 *
+	 * The underlying cursor pget will fill in a default DBT for null
+	 * pkeys, and use the cursor's returned-key memory internally to
+	 * store any intermediate primary keys.  However, we've just set
+	 * the returned-key memory to the DB handle's key memory, which
+	 * is unsafe to use if the DB handle is threaded.  If the pkey
+	 * argument is NULL, use the DBC-owned returned-key memory
+	 * instead;  it'll go away when we close the cursor before we
+	 * return, but in this case that's just fine, as we're not
+	 * returning the primary key.
+	 */
+	if (pkey == NULL)
+		dbc->rkey = &dbc->my_rkey;
+
+	/*
+	 * The cursor is just a perfectly ordinary secondary database cursor.
+	 * Call its c_pget() method to do the dirty work.
+	 */
+	if (flags == 0 || flags == DB_RMW)
+		flags |= DB_SET;
+
+	ret = __db_c_pget(dbc, skey, pkey, data, flags);
+
+	if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
+		ret = t_ret;
+
+	return (ret);
+}
+
+/*
+ * __db_pget_arg --
+ *	Check DB->pget arguments.
+ */
+static int
+__db_pget_arg(dbp, pkey, flags)
+	DB *dbp;
+	DBT *pkey;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	int ret;
+
+	dbenv = dbp->dbenv;
+
+	if (!F_ISSET(dbp, DB_AM_SECONDARY)) {
+		__db_err(dbenv,
+		    "DB->pget may only be used on secondary indices");
+		return (EINVAL);
+	}
+
+	if (LF_ISSET(DB_MULTIPLE | DB_MULTIPLE_KEY)) {
+		__db_err(dbenv,
+	"DB_MULTIPLE and DB_MULTIPLE_KEY may not be used on secondary indices");
+		return (EINVAL);
+	}
+
+	/* DB_CONSUME makes no sense on a secondary index. */
+	LF_CLR(DB_RMW);
+	switch (flags) {
+	case DB_CONSUME:
+	case DB_CONSUME_WAIT:
+		return (__db_ferr(dbenv, "DB->pget", 0));
+	default:
+		/* __db_get_arg will catch the rest. */
+		break;
+	}
+
+	/*
+	 * We allow the pkey field to be NULL, so that we can make the
+	 * two-DBT get calls into wrappers for the three-DBT ones.
+	 */
+	if (pkey != NULL &&
+	    (ret = __dbt_ferr(dbp, "primary key", pkey, 1)) != 0)
+		return (ret);
+
+	/* But the pkey field can't be NULL if we're doing a DB_GET_BOTH. */
+	if (pkey == NULL && flags == DB_GET_BOTH) {
+		__db_err(dbenv,
+		    "DB_GET_BOTH on a secondary index requires a primary key");
+		return (EINVAL);
+	}
+
+	return (0);
+}
+
+/*
+ * __db_put_pp --
+ *	DB->put pre/post processing.
+ *
+ * PUBLIC: int __db_put_pp __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
+ */
+int
+__db_put_pp(dbp, txn, key, data, flags)
+	DB *dbp;
+	DB_TXN *txn;
+	DBT *key, *data;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	int handle_check, ret, txn_local;
+
+	dbenv = dbp->dbenv;
+
+	PANIC_CHECK(dbenv);
+	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->put");
+
+	if ((ret = __db_put_arg(dbp, key, data, flags)) != 0)
+		return (ret);
+
+	/* Create local transaction as necessary. */
+	if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
+		if ((ret = __db_txn_auto_init(dbenv, &txn)) != 0)
+			return (ret);
+		txn_local = 1;
+		LF_CLR(DB_AUTO_COMMIT);
+	} else
+		txn_local = 0;
+
+	/* Check for consistent transaction usage. */
+	if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0)) != 0)
+		goto err;
+
+	/* Check for replication block. */
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, txn != NULL)) != 0)
+		goto err;
+
+	ret = __db_put(dbp, txn, key, data, flags);
+
+	/* Release replication block. */
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
+
+err:	return (txn_local ? __db_txn_auto_resolve(dbenv, txn, 0, ret) : ret);
+}
+
+/*
+ * __db_put_arg --
+ *	Check DB->put arguments.
+ */
+static int
+__db_put_arg(dbp, key, data, flags)
+	DB *dbp;
+	DBT *key, *data;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	int ret, returnkey;
+
+	dbenv = dbp->dbenv;
+	returnkey = 0;
+
+	/* Check for changes to a read-only tree. */
+	if (IS_READONLY(dbp))
+		return (__db_rdonly(dbenv, "put"));
+
+	/* Check for puts on a secondary. */
+	if (F_ISSET(dbp, DB_AM_SECONDARY)) {
+		__db_err(dbenv, "DB->put forbidden on secondary indices");
+		return (EINVAL);
+	}
+
+	/* Check for invalid function flags. */
+	LF_CLR(DB_AUTO_COMMIT);
+	switch (flags) {
+	case 0:
+	case DB_NOOVERWRITE:
+		break;
+	case DB_APPEND:
+		if (dbp->type != DB_RECNO && dbp->type != DB_QUEUE)
+			goto err;
+		returnkey = 1;
+		break;
+	case DB_NODUPDATA:
+		if (F_ISSET(dbp, DB_AM_DUPSORT))
+			break;
+		/* FALLTHROUGH */
+	default:
+err:		return (__db_ferr(dbenv, "DB->put", 0));
+	}
+
+	/* Check for invalid key/data flags. */
+	if ((ret = __dbt_ferr(dbp, "key", key, returnkey)) != 0)
+		return (ret);
+	if ((ret = __dbt_ferr(dbp, "data", data, 0)) != 0)
+		return (ret);
+
+	/* Keys shouldn't have partial flags during a put. */
+	if (F_ISSET(key, DB_DBT_PARTIAL))
+		return (__db_ferr(dbenv, "key DBT", 0));
+
+	/* Check for partial puts in the presence of duplicates. */
+	if (F_ISSET(data, DB_DBT_PARTIAL) &&
+	    (F_ISSET(dbp, DB_AM_DUP) || F_ISSET(key, DB_DBT_DUPOK))) {
+		__db_err(dbenv,
+"a partial put in the presence of duplicates requires a cursor operation");
+		return (EINVAL);
+	}
+
+	return (0);
+}
+
+/*
+ * __db_sync_pp --
+ *	DB->sync pre/post processing.
+ *
+ * PUBLIC: int __db_sync_pp __P((DB *, u_int32_t));
+ */
+int
+__db_sync_pp(dbp, flags)
+	DB *dbp;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	int handle_check, ret;
+
+	dbenv = dbp->dbenv;
+
+	PANIC_CHECK(dbp->dbenv);
+	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->sync");
+
+	/*
+	 * !!!
+	 * The actual argument checking is simple, do it inline.
+	 */
+	if (flags != 0)
+		return (__db_ferr(dbenv, "DB->sync", 0));
+
+	/* Check for replication block. */
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, 0)) != 0)
+		return (ret);
+
+	ret = __db_sync(dbp);
+
+	/* Release replication block. */
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
+
+	return (ret);
+}
+
+/*
+ * __db_c_close_pp --
+ *	DBC->c_close pre/post processing.
+ *
+ * PUBLIC: int __db_c_close_pp __P((DBC *));
+ */
+int
+__db_c_close_pp(dbc)
+	DBC *dbc;
+{
+	DB_ENV *dbenv;
+	DB *dbp;
+	int handle_check, ret;
+
+	dbp = dbc->dbp;
+	dbenv = dbp->dbenv;
+
+	PANIC_CHECK(dbenv);
+
+	/*
+	 * If the cursor is already closed we have a serious problem, and we
+	 * assume that the cursor isn't on the active queue.  Don't do any of
+	 * the remaining cursor close processing.
+	 */
+	if (!F_ISSET(dbc, DBC_ACTIVE)) {
+		if (dbp != NULL)
+			__db_err(dbenv, "Closing already-closed cursor");
+		DB_ASSERT(0);
+		return (EINVAL);
+	}
+
+	/* Check for replication block. */
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check &&
+	    (ret = __db_rep_enter(dbp, 0, 0, dbc->txn != NULL)) != 0)
+		return (ret);
+
+	ret = __db_c_close(dbc);
+
+	/* Release replication block. */
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
+
+	return (ret);
+}
+
+/*
+ * __db_c_count_pp --
+ *	DBC->c_count pre/post processing.
+ *
+ * PUBLIC: int __db_c_count_pp __P((DBC *, db_recno_t *, u_int32_t));
+ */
+int
+__db_c_count_pp(dbc, recnop, flags)
+	DBC *dbc;
+	db_recno_t *recnop;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	DB *dbp;
+	int handle_check, ret;
+
+	dbp = dbc->dbp;
+	dbenv = dbp->dbenv;
+
+	PANIC_CHECK(dbenv);
+
+	/*
+	 * !!!
+	 * The actual argument checking is simple, do it inline.
+	 */
+	if (flags != 0)
+		return (__db_ferr(dbenv, "DBcursor->count", 0));
+
+	/*
+	 * The cursor must be initialized, return EINVAL for an invalid cursor,
+	 * otherwise 0.
+	 */
+	if (!IS_INITIALIZED(dbc))
+		return (__db_curinval(dbenv));
+
+	/* Check for replication block. */
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check &&
+	    (ret = __db_rep_enter(dbp, 1, 0, dbc->txn != NULL)) != 0)
+		return (ret);
+
+	ret = __db_c_count(dbc, recnop);
+
+	/* Release replication block. */
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
+
+	return (ret);
+}
+
+/*
+ * __db_c_del_pp --
+ *	DBC->c_del pre/post processing.
+ *
+ * PUBLIC: int __db_c_del_pp __P((DBC *, u_int32_t));
+ */
+int
+__db_c_del_pp(dbc, flags)
+	DBC *dbc;
+	u_int32_t flags;
+{
+	DB *dbp;
+	DB_ENV *dbenv;
+	int handle_check, ret;
+
+	dbp = dbc->dbp;
+	dbenv = dbp->dbenv;
+
+	PANIC_CHECK(dbenv);
+
+	if ((ret = __db_c_del_arg(dbc, flags)) != 0)
+		return (ret);
+
+	/* Check for consistent transaction usage. */
+	if ((ret = __db_check_txn(dbp, dbc->txn, dbc->locker, 0)) != 0)
+		return (ret);
+
+	/* Check for replication block. */
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check &&
+	    (ret = __db_rep_enter(dbp, 1, 0, dbc->txn != NULL)) != 0)
+		return (ret);
+
+	DEBUG_LWRITE(dbc, dbc->txn, "DBcursor->del", NULL, NULL, flags);
+
+	ret = __db_c_del(dbc, flags);
+
+	/* Release replication block. */
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
+
+	return (ret);
+}
+
+/*
+ * __db_c_del_arg --
+ *	Check DBC->c_del arguments.
+ *
+ * PUBLIC: int __db_c_del_arg __P((DBC *, u_int32_t));
+ */
+int
+__db_c_del_arg(dbc, flags)
+	DBC *dbc;
+	u_int32_t flags;
+{
+	DB *dbp;
+	DB_ENV *dbenv;
+
+	dbp = dbc->dbp;
+	dbenv = dbp->dbenv;
+
+	/* Check for changes to a read-only tree. */
+	if (IS_READONLY(dbp))
+		return (__db_rdonly(dbenv, "DBcursor->del"));
+
+	/* Check for invalid function flags. */
+	switch (flags) {
+	case 0:
+		break;
+	case DB_UPDATE_SECONDARY:
+		DB_ASSERT(F_ISSET(dbp, DB_AM_SECONDARY));
+		break;
+	default:
+		return (__db_ferr(dbenv, "DBcursor->del", 0));
+	}
+
+	/*
+	 * The cursor must be initialized, return EINVAL for an invalid cursor,
+	 * otherwise 0.
+	 */
+	if (!IS_INITIALIZED(dbc))
+		return (__db_curinval(dbenv));
+
+	return (0);
+}
+
+/*
+ * __db_c_dup_pp --
+ *	DBC->c_dup pre/post processing.
+ *
+ * PUBLIC: int __db_c_dup_pp __P((DBC *, DBC **, u_int32_t));
+ */
+int
+__db_c_dup_pp(dbc, dbcp, flags)
+	DBC *dbc, **dbcp;
+	u_int32_t flags;
+{
+	DB *dbp;
+	DB_ENV *dbenv;
+	int handle_check, ret;
+
+	dbp = dbc->dbp;
+	dbenv = dbp->dbenv;
+
+	PANIC_CHECK(dbenv);
+
+	/*
+	 * !!!
+	 * The actual argument checking is simple, do it inline.
 	 */
-	return (isvalid ? 0 : __db_curinval(dbp->dbenv));
+	if (flags != 0 && flags != DB_POSITION)
+		return (__db_ferr(dbenv, "DBcursor->dup", 0));
+
+	/* Check for replication block. */
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check &&
+	    (ret = __db_rep_enter(dbp, 1, 0, dbc->txn != NULL)) != 0)
+		return (ret);
+
+	ret = __db_c_dup(dbc, dbcp, flags);
+
+	/* Release replication block. */
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
+
+	return (ret);
 }
 
 /*
- * __db_cgetchk --
- *	Common cursor get argument checking routine.
+ * __db_c_get_pp --
+ *	DBC->c_get pre/post processing.
  *
- * PUBLIC: int __db_cgetchk __P((const DB *, DBT *, DBT *, u_int32_t, int));
+ * PUBLIC: int __db_c_get_pp __P((DBC *, DBT *, DBT *, u_int32_t));
  */
 int
-__db_cgetchk(dbp, key, data, flags, isvalid)
-	const DB *dbp;
+__db_c_get_pp(dbc, key, data, flags)
+	DBC *dbc;
+	DBT *key, *data;
+	u_int32_t flags;
+{
+	DB *dbp;
+	DB_ENV *dbenv;
+	int handle_check, ret;
+
+	dbp = dbc->dbp;
+	dbenv = dbp->dbenv;
+
+	PANIC_CHECK(dbenv);
+
+	if ((ret = __db_c_get_arg(dbc, key, data, flags)) != 0)
+		return (ret);
+
+	/* Check for replication block. */
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check &&
+	    (ret = __db_rep_enter(dbp, 1, 0, dbc->txn != NULL)) != 0)
+		return (ret);
+
+	DEBUG_LREAD(dbc, dbc->txn, "DBcursor->get",
+	    flags == DB_SET || flags == DB_SET_RANGE ? key : NULL, NULL, flags);
+
+	ret = __db_c_get(dbc, key, data, flags);
+
+	/* Release replication block. */
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
+
+	return (ret);
+}
+
+/*
+ * __db_c_get_arg --
+ *	Common DBC->get argument checking, used by both DBC->get and DBC->pget.
+ */
+static int
+__db_c_get_arg(dbc, key, data, flags)
+	DBC *dbc;
 	DBT *key, *data;
 	u_int32_t flags;
-	int isvalid;
 {
+	DB *dbp;
+	DB_ENV *dbenv;
 	int dirty, multi, ret;
 
+	dbp = dbc->dbp;
+	dbenv = dbp->dbenv;
+
 	/*
+	 * Typically in checking routines that modify the flags, we have
+	 * to save them and restore them, because the checking routine
+	 * calls the work routine.  However, this is a pure-checking
+	 * routine which returns to a function that calls the work routine,
+	 * so it's OK that we do not save and restore the flags, even though
+	 * we modify them.
+	 *
 	 * Check for read-modify-write validity.  DB_RMW doesn't make sense
 	 * with CDB cursors since if you're going to write the cursor, you
 	 * had to create it with DB_WRITECURSOR.  Regardless, we check for
@@ -159,8 +1781,8 @@ __db_cgetchk(dbp, key, data, flags, isvalid)
 	 */
 	dirty = 0;
 	if (LF_ISSET(DB_DIRTY_READ | DB_RMW)) {
-		if (!LOCKING_ON(dbp->dbenv))
-			return (__db_fnl(dbp->dbenv, "DBcursor->c_get"));
+		if (!LOCKING_ON(dbenv))
+			return (__db_fnl(dbenv, "DBcursor->get"));
 		if (LF_ISSET(DB_DIRTY_READ))
 			dirty = 1;
 		LF_CLR(DB_DIRTY_READ | DB_RMW);
@@ -179,7 +1801,7 @@ __db_cgetchk(dbp, key, data, flags, isvalid)
 	case DB_CONSUME:
 	case DB_CONSUME_WAIT:
 		if (dirty) {
-			__db_err(dbp->dbenv,
+			__db_err(dbenv,
     "DB_DIRTY_READ is not supported with DB_CONSUME or DB_CONSUME_WAIT");
 			return (EINVAL);
 		}
@@ -200,7 +1822,7 @@ __db_cgetchk(dbp, key, data, flags, isvalid)
 	case DB_PREV:
 	case DB_PREV_NODUP:
 		if (multi)
-multi_err:		return (__db_ferr(dbp->dbenv, "DBcursor->c_get", 1));
+multi_err:		return (__db_ferr(dbenv, "DBcursor->get", 1));
 		break;
 	case DB_GET_BOTHC:
 		if (dbp->type == DB_QUEUE)
@@ -222,7 +1844,7 @@ multi_err:		return (__db_ferr(dbp->dbenv, "DBcursor->c_get", 1));
 			goto err;
 		break;
 	default:
-err:		return (__db_ferr(dbp->dbenv, "DBcursor->c_get", 0));
+err:		return (__db_ferr(dbenv, "DBcursor->get", 0));
 	}
 
 	/* Check for invalid key/data flags. */
@@ -231,571 +1853,339 @@ err:		return (__db_ferr(dbp->dbenv, "DBcursor->c_get", 0));
 	if ((ret = __dbt_ferr(dbp, "data", data, 0)) != 0)
 		return (ret);
 
-	if (multi && !F_ISSET(data, DB_DBT_USERMEM)) {
-		__db_err(dbp->dbenv,
-		    "DB_MULTIPLE(_KEY) requires that DB_DBT_USERMEM be set");
-		return (EINVAL);
-	}
-	if (multi &&
-	    (F_ISSET(key, DB_DBT_PARTIAL) || F_ISSET(data, DB_DBT_PARTIAL))) {
-		__db_err(dbp->dbenv,
-		    "DB_DBT_PARTIAL forbidden with DB_MULTIPLE(_KEY)");
-		return (EINVAL);
+	if (multi) {
+		if (!F_ISSET(data, DB_DBT_USERMEM)) {
+			__db_err(dbenv,
+	    "DB_MULTIPLE/DB_MULTIPLE_KEY require DB_DBT_USERMEM be set");
+			return (EINVAL);
+		}
+		if (F_ISSET(key, DB_DBT_PARTIAL) ||
+		    F_ISSET(data, DB_DBT_PARTIAL)) {
+			__db_err(dbenv,
+	    "DB_MULTIPLE/DB_MULTIPLE_KEY do not support DB_DBT_PARTIAL");
+			return (EINVAL);
+		}
+		if (data->ulen < 1024 ||
+		    data->ulen < dbp->pgsize || data->ulen % 1024 != 0) {
+			__db_err(dbenv, "%s%s",
+			    "DB_MULTIPLE/DB_MULTIPLE_KEY buffers must be ",
+			    "aligned, at least page size and multiples of 1KB");
+			return (EINVAL);
+		}
 	}
 
 	/*
 	 * The cursor must be initialized for DB_CURRENT, DB_GET_RECNO and
 	 * DB_NEXT_DUP.  Return EINVAL for an invalid cursor, otherwise 0.
 	 */
-	if (isvalid || (flags != DB_CURRENT &&
-	    flags != DB_GET_RECNO && flags != DB_NEXT_DUP))
-		return (0);
+	if (!IS_INITIALIZED(dbc) && (flags == DB_CURRENT ||
+	    flags == DB_GET_RECNO || flags == DB_NEXT_DUP))
+		return (__db_curinval(dbenv));
 
-	return (__db_curinval(dbp->dbenv));
+	/* Check for consistent transaction usage. */
+	if (LF_ISSET(DB_RMW) &&
+	    (ret = __db_check_txn(dbp, dbc->txn, dbc->locker, 0)) != 0)
+		return (ret);
+
+	return (0);
 }
 
 /*
- * __db_cputchk --
- *	Common cursor put argument checking routine.
+ * __db_secondary_close_pp --
+ *	DB->close for secondaries
  *
- * PUBLIC: int __db_cputchk __P((const DB *,
- * PUBLIC:    const DBT *, DBT *, u_int32_t, int));
+ * PUBLIC: int __db_secondary_close_pp __P((DB *, u_int32_t));
  */
 int
-__db_cputchk(dbp, key, data, flags, isvalid)
-	const DB *dbp;
-	const DBT *key;
-	DBT *data;
+__db_secondary_close_pp(dbp, flags)
+	DB *dbp;
 	u_int32_t flags;
-	int isvalid;
 {
-	int key_flags, ret;
-
-	key_flags = 0;
+	DB_ENV *dbenv;
+	int handle_check, ret, t_ret;
 
-	/* Check for changes to a read-only tree. */
-	if (IS_READONLY(dbp))
-		return (__db_rdonly(dbp->dbenv, "c_put"));
+	dbenv = dbp->dbenv;
+	ret = 0;
 
-	/* Check for puts on a secondary. */
-	if (F_ISSET(dbp, DB_AM_SECONDARY)) {
-		if (flags == DB_UPDATE_SECONDARY)
-			flags = DB_KEYLAST;
-		else {
-			__db_err(dbp->dbenv,
-		    "DBcursor->c_put forbidden on secondary indices");
-			return (EINVAL);
-		}
-	}
+	PANIC_CHECK(dbenv);
 
-	/* Check for invalid function flags. */
-	switch (flags) {
-	case DB_AFTER:
-	case DB_BEFORE:
-		switch (dbp->type) {
-		case DB_BTREE:
-		case DB_HASH:		/* Only with unsorted duplicates. */
-			if (!F_ISSET(dbp, DB_AM_DUP))
-				goto err;
-			if (dbp->dup_compare != NULL)
-				goto err;
-			break;
-		case DB_QUEUE:		/* Not permitted. */
-			goto err;
-		case DB_RECNO:		/* Only with mutable record numbers. */
-			if (!F_ISSET(dbp, DB_AM_RENUMBER))
-				goto err;
-			key_flags = 1;
-			break;
-		default:
-			goto err;
-		}
-		break;
-	case DB_CURRENT:
-		/*
-		 * If there is a comparison function, doing a DB_CURRENT
-		 * must not change the part of the data item that is used
-		 * for the comparison.
-		 */
-		break;
-	case DB_NODUPDATA:
-		if (!F_ISSET(dbp, DB_AM_DUPSORT))
-			goto err;
-		/* FALLTHROUGH */
-	case DB_KEYFIRST:
-	case DB_KEYLAST:
-		key_flags = 1;
-		break;
-	default:
-err:		return (__db_ferr(dbp->dbenv, "DBcursor->c_put", 0));
+	/*
+	 * !!!
+	 * The actual argument checking is simple, do it inline.
+	 *
+	 * Validate arguments and complain if they're wrong, but as a DB
+	 * handle destructor, we can't fail.
+	 */
+	if (flags != 0 && flags != DB_NOSYNC &&
+	    (t_ret = __db_ferr(dbenv, "DB->close", 0)) != 0 && ret == 0)
+		ret = t_ret;
+
+	/* Check for replication block. */
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check &&
+	    (t_ret = __db_rep_enter(dbp, 0, 0, 0)) != 0) {
+		handle_check = 0;
+		if (ret == 0)
+			ret = t_ret;
 	}
 
-	/* Check for invalid key/data flags. */
-	if (key_flags && (ret = __dbt_ferr(dbp, "key", key, 0)) != 0)
-		return (ret);
-	if ((ret = __dbt_ferr(dbp, "data", data, 0)) != 0)
-		return (ret);
+	if ((t_ret = __db_secondary_close(dbp, flags)) != 0 && ret == 0)
+		ret = t_ret;
 
-	/*
-	 * The cursor must be initialized for anything other than DB_KEYFIRST
-	 * and DB_KEYLAST, return EINVAL for an invalid cursor, otherwise 0.
-	 */
-	if (isvalid || flags == DB_KEYFIRST ||
-	    flags == DB_KEYLAST || flags == DB_NODUPDATA)
-		return (0);
+	/* Release replication block. */
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
 
-	return (__db_curinval(dbp->dbenv));
+	return (ret);
 }
 
 /*
- * __db_pgetchk --
- *	DB->pget flag check.
+ * __db_c_pget_pp --
+ *	DBC->c_pget pre/post processing.
  *
- * PUBLIC: int __db_pgetchk __P((const DB *, const DBT *, DBT *, DBT *,
- * PUBLIC:	u_int32_t));
+ * PUBLIC: int __db_c_pget_pp __P((DBC *, DBT *, DBT *, DBT *, u_int32_t));
  */
 int
-__db_pgetchk(dbp, skey, pkey, data, flags)
-	const DB *dbp;
-	const DBT *skey;
-	DBT *pkey, *data;
+__db_c_pget_pp(dbc, skey, pkey, data, flags)
+	DBC *dbc;
+	DBT *skey, *pkey, *data;
 	u_int32_t flags;
 {
-	int ret;
-	u_int32_t save_flags;
+	DB *dbp;
+	DB_ENV *dbenv;
+	int handle_check, ret;
 
-	save_flags = flags;
+	dbp = dbc->dbp;
+	dbenv = dbp->dbenv;
 
-	if (!F_ISSET(dbp, DB_AM_SECONDARY)) {
-		__db_err(dbp->dbenv,
-		    "DB->pget may only be used on secondary indices");
-		return (EINVAL);
-	}
+	PANIC_CHECK(dbenv);
 
-	if (LF_ISSET(DB_MULTIPLE | DB_MULTIPLE_KEY)) {
-		__db_err(dbp->dbenv,
-	"DB_MULTIPLE and DB_MULTIPLE_KEY may not be used on secondary indices");
-		return (EINVAL);
-	}
+	if ((ret = __db_c_pget_arg(dbc, pkey, flags)) != 0)
+		return (ret);
 
-	/* DB_CONSUME makes no sense on a secondary index. */
-	LF_CLR(DB_RMW);
-	switch (flags) {
-	case DB_CONSUME:
-	case DB_CONSUME_WAIT:
-		return (__db_ferr(dbp->dbenv, "DB->pget", 0));
-	default:
-		/* __db_getchk will catch the rest. */
-		break;
-	}
+	if ((ret = __db_c_get_arg(dbc, skey, data, flags)) != 0)
+		return (ret);
 
-	/*
-	 * We allow the pkey field to be NULL, so that we can make the
-	 * two-DBT get calls into wrappers for the three-DBT ones.
-	 */
-	if (pkey != NULL &&
-	    (ret = __dbt_ferr(dbp, "primary key", pkey, 1)) != 0)
+	/* Check for replication block. */
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check &&
+	    (ret = __db_rep_enter(dbp, 1, 0, dbc->txn != NULL)) != 0)
 		return (ret);
 
-	/* But the pkey field can't be NULL if we're doing a DB_GET_BOTH. */
-	if (pkey == NULL && flags == DB_GET_BOTH) {
-		__db_err(dbp->dbenv,
-		    "DB_GET_BOTH on a secondary index requires a primary key");
-		return (EINVAL);
-	}
+	ret = __db_c_pget(dbc, skey, pkey, data, flags);
 
-	return (__db_getchk(dbp, skey, data, save_flags));
+	/* Release replication block. */
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
+
+	return (ret);
 }
 
 /*
- * __db_cpgetchk --
- *	Secondary-index cursor get argument checking routine.
- *
- * PUBLIC: int __db_cpgetchk __P((const DB *,
- * PUBLIC:     DBT *, DBT *, DBT *, u_int32_t, int));
+ * __db_c_pget_arg --
+ *	Check DBC->pget arguments.
  */
-int
-__db_cpgetchk(dbp, skey, pkey, data, flags, isvalid)
-	const DB *dbp;
-	DBT *skey, *pkey, *data;
+static int
+__db_c_pget_arg(dbc, pkey, flags)
+	DBC *dbc;
+	DBT *pkey;
 	u_int32_t flags;
-	int isvalid;
 {
+	DB *dbp;
+	DB_ENV *dbenv;
 	int ret;
-	u_int32_t save_flags;
 
-	save_flags = flags;
+	dbp = dbc->dbp;
+	dbenv = dbp->dbenv;
 
 	if (!F_ISSET(dbp, DB_AM_SECONDARY)) {
-		__db_err(dbp->dbenv,
-		    "DBcursor->c_pget may only be used on secondary indices");
+		__db_err(dbenv,
+		    "DBcursor->pget may only be used on secondary indices");
 		return (EINVAL);
 	}
 
 	if (LF_ISSET(DB_MULTIPLE | DB_MULTIPLE_KEY)) {
-		__db_err(dbp->dbenv,
+		__db_err(dbenv,
 	"DB_MULTIPLE and DB_MULTIPLE_KEY may not be used on secondary indices");
 		return (EINVAL);
 	}
 
-	LF_CLR(DB_RMW);
-	switch (flags) {
+	switch (LF_ISSET(~DB_RMW)) {
 	case DB_CONSUME:
 	case DB_CONSUME_WAIT:
-		/* DB_CONSUME makes no sense on a secondary index. */
-		return (__db_ferr(dbp->dbenv, "DBcursor->c_pget", 0));
+		/* These flags make no sense on a secondary index. */
+		return (__db_ferr(dbenv, "DBcursor->pget", 0));
 	case DB_GET_BOTH:
 		/* DB_GET_BOTH is "get both the primary and the secondary". */
 		if (pkey == NULL) {
-			__db_err(dbp->dbenv,
+			__db_err(dbenv,
 		    "DB_GET_BOTH requires both a secondary and a primary key");
-			return (EINVAL);
-		}
-		break;
-	default:
-		/* __db_cgetchk will catch the rest. */
-		break;
-	}
-
-	/*
-	 * We allow the pkey field to be NULL, so that we can make the
-	 * two-DBT get calls into wrappers for the three-DBT ones.
-	 */
-	if (pkey != NULL &&
-	    (ret = __dbt_ferr(dbp, "primary key", pkey, 0)) != 0)
-		return (ret);
-
-	/* But the pkey field can't be NULL if we're doing a DB_GET_BOTH. */
-	if (pkey == NULL && flags == DB_GET_BOTH) {
-		__db_err(dbp->dbenv,
-		    "DB_GET_BOTH on a secondary index requires a primary key");
-		return (EINVAL);
-	}
-
-	return (__db_cgetchk(dbp, skey, data, save_flags, isvalid));
-}
-
-/*
- * __db_delchk --
- *	Common delete argument checking routine.
- *
- * PUBLIC: int __db_delchk __P((const DB *, DBT *, u_int32_t));
- */
-int
-__db_delchk(dbp, key, flags)
-	const DB *dbp;
-	DBT *key;
-	u_int32_t flags;
-{
-	COMPQUIET(key, NULL);
-
-	/* Check for changes to a read-only tree. */
-	if (IS_READONLY(dbp))
-		return (__db_rdonly(dbp->dbenv, "delete"));
-
-	/* Check for invalid function flags. */
-	LF_CLR(DB_AUTO_COMMIT);
-	switch (flags) {
-	case 0:
-		break;
-	default:
-		return (__db_ferr(dbp->dbenv, "DB->del", 0));
-	}
-
-	return (0);
-}
-
-/*
- * __db_getchk --
- *	Common get argument checking routine.
- *
- * PUBLIC: int __db_getchk __P((const DB *, const DBT *, DBT *, u_int32_t));
- */
-int
-__db_getchk(dbp, key, data, flags)
-	const DB *dbp;
-	const DBT *key;
-	DBT *data;
-	u_int32_t flags;
-{
-	int dirty, multi, ret;
-
-	/*
-	 * Check for read-modify-write validity.  DB_RMW doesn't make sense
-	 * with CDB cursors since if you're going to write the cursor, you
-	 * had to create it with DB_WRITECURSOR.  Regardless, we check for
-	 * LOCKING_ON and not STD_LOCKING, as we don't want to disallow it.
-	 * If this changes, confirm that DB does not itself set the DB_RMW
-	 * flag in a path where CDB may have been configured.
-	 */
-	dirty = 0;
-	if (LF_ISSET(DB_DIRTY_READ | DB_RMW)) {
-		if (!LOCKING_ON(dbp->dbenv))
-			return (__db_fnl(dbp->dbenv, "DB->get"));
-		if (LF_ISSET(DB_DIRTY_READ))
-			dirty = 1;
-		LF_CLR(DB_DIRTY_READ | DB_RMW);
-	}
-
-	multi = 0;
-	if (LF_ISSET(DB_MULTIPLE | DB_MULTIPLE_KEY)) {
-		if (LF_ISSET(DB_MULTIPLE_KEY))
-			goto multi_err;
-		multi = LF_ISSET(DB_MULTIPLE) ? 1 : 0;
-		LF_CLR(DB_MULTIPLE);
-	}
-
-	/* Check for invalid function flags. */
-	switch (flags) {
-	case 0:
-	case DB_GET_BOTH:
-		break;
-	case DB_SET_RECNO:
-		if (!F_ISSET(dbp, DB_AM_RECNUM))
-			goto err;
-		break;
-	case DB_CONSUME:
-	case DB_CONSUME_WAIT:
-		if (dirty) {
-			__db_err(dbp->dbenv,
-    "DB_DIRTY_READ is not supported with DB_CONSUME or DB_CONSUME_WAIT");
-			return (EINVAL);
-		}
-		if (multi)
-multi_err:		return (__db_ferr(dbp->dbenv, "DB->get", 1));
-		if (dbp->type == DB_QUEUE)
-			break;
-		/* FALLTHROUGH */
+			return (EINVAL);
+		}
+		break;
 	default:
-err:		return (__db_ferr(dbp->dbenv, "DB->get", 0));
+		/* __db_c_get_arg will catch the rest. */
+		break;
 	}
 
 	/*
-	 * Check for invalid key/data flags.
-	 *
-	 * XXX: Dave Krinsky
-	 * Remember to modify this when we fix the flag-returning problem.
+	 * We allow the pkey field to be NULL, so that we can make the
+	 * two-DBT get calls into wrappers for the three-DBT ones.
 	 */
-	if ((ret = __dbt_ferr(dbp, "key", key, flags == DB_SET_RECNO)) != 0)
-		return (ret);
-	if ((ret = __dbt_ferr(dbp, "data", data, 1)) != 0)
+	if (pkey != NULL &&
+	    (ret = __dbt_ferr(dbp, "primary key", pkey, 0)) != 0)
 		return (ret);
 
-	if (multi && !F_ISSET(data, DB_DBT_USERMEM)) {
-		__db_err(dbp->dbenv,
-		    "DB_MULTIPLE requires that DB_DBT_USERMEM be set");
-		return (EINVAL);
-	}
-	if (multi &&
-	    (F_ISSET(key, DB_DBT_PARTIAL) || F_ISSET(data, DB_DBT_PARTIAL))) {
-		__db_err(dbp->dbenv,
-		    "DB_DBT_PARTIAL forbidden with DB_MULTIPLE(_KEY)");
+	/* But the pkey field can't be NULL if we're doing a DB_GET_BOTH. */
+	if (pkey == NULL && (flags & DB_OPFLAGS_MASK) == DB_GET_BOTH) {
+		__db_err(dbenv,
+		    "DB_GET_BOTH on a secondary index requires a primary key");
 		return (EINVAL);
 	}
-
 	return (0);
 }
 
 /*
- * __db_joinchk --
- *	Common join argument checking routine.
+ * __db_c_put_pp --
+ *	DBC->put pre/post processing.
  *
- * PUBLIC: int __db_joinchk __P((const DB *, DBC * const *, u_int32_t));
+ * PUBLIC: int __db_c_put_pp __P((DBC *, DBT *, DBT *, u_int32_t));
  */
 int
-__db_joinchk(dbp, curslist, flags)
-	const DB *dbp;
-	DBC * const *curslist;
+__db_c_put_pp(dbc, key, data, flags)
+	DBC *dbc;
+	DBT *key, *data;
 	u_int32_t flags;
 {
-	DB_TXN *txn;
-	int i;
-
-	switch (flags) {
-	case 0:
-	case DB_JOIN_NOSORT:
-		break;
-	default:
-		return (__db_ferr(dbp->dbenv, "DB->join", 0));
-	}
+	DB *dbp;
+	DB_ENV *dbenv;
+	int handle_check, ret;
 
-	if (curslist == NULL || curslist[0] == NULL) {
-		__db_err(dbp->dbenv,
-	    "At least one secondary cursor must be specified to DB->join");
-		return (EINVAL);
-	}
+	dbp = dbc->dbp;
+	dbenv = dbp->dbenv;
 
-	txn = curslist[0]->txn;
-	for (i = 1; curslist[i] != NULL; i++)
-		if (curslist[i]->txn != txn) {
-			__db_err(dbp->dbenv,
-		    "All secondary cursors must share the same transaction");
-			return (EINVAL);
-		}
+	PANIC_CHECK(dbenv);
 
-	return (0);
-}
+	if ((ret = __db_c_put_arg(dbc, key, data, flags)) != 0)
+		return (ret);
 
-/*
- * __db_joingetchk --
- *	Common join_get argument checking routine.
- *
- * PUBLIC: int __db_joingetchk __P((const DB *, DBT *, u_int32_t));
- */
-int
-__db_joingetchk(dbp, key, flags)
-	const DB *dbp;
-	DBT *key;
-	u_int32_t flags;
-{
+	/* Check for consistent transaction usage. */
+	if ((ret = __db_check_txn(dbp, dbc->txn, dbc->locker, 0)) != 0)
+		return (ret);
 
-	if (LF_ISSET(DB_DIRTY_READ | DB_RMW)) {
-		if (!LOCKING_ON(dbp->dbenv))
-			return (__db_fnl(dbp->dbenv, "DBcursor->c_get"));
+	/* Check for replication block. */
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check &&
+	    (ret = __db_rep_enter(dbp, 1, 0, dbc->txn != NULL)) != 0)
+		return (ret);
 
-		LF_CLR(DB_DIRTY_READ | DB_RMW);
-	}
+	DEBUG_LWRITE(dbc, dbc->txn, "DBcursor->put",
+	    flags == DB_KEYFIRST || flags == DB_KEYLAST ||
+	    flags == DB_NODUPDATA || flags == DB_UPDATE_SECONDARY ?
+	    key : NULL, data, flags);
 
-	switch (flags) {
-	case 0:
-	case DB_JOIN_ITEM:
-		break;
-	default:
-		return (__db_ferr(dbp->dbenv, "DBcursor->c_get", 0));
-	}
+	ret =__db_c_put(dbc, key, data, flags);
 
-	/*
-	 * A partial get of the key of a join cursor don't make much sense;
-	 * the entire key is necessary to query the primary database
-	 * and find the datum, and so regardless of the size of the key
-	 * it would not be a performance improvement.  Since it would require
-	 * special handling, we simply disallow it.
-	 *
-	 * A partial get of the data, however, potentially makes sense (if
-	 * all possible data are a predictable large structure, for instance)
-	 * and causes us no headaches, so we permit it.
-	 */
-	if (F_ISSET(key, DB_DBT_PARTIAL)) {
-		__db_err(dbp->dbenv,
-		    "DB_DBT_PARTIAL may not be set on key during join_get");
-		return (EINVAL);
-	}
+	/* Release replication block. */
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
 
-	return (0);
+	return (ret);
 }
 
 /*
- * __db_putchk --
- *	Common put argument checking routine.
- *
- * PUBLIC: int __db_putchk
- * PUBLIC:    __P((const DB *, DBT *, const DBT *, u_int32_t, int));
+ * __db_c_put_arg --
+ *	Check DBC->put arguments.
  */
-int
-__db_putchk(dbp, key, data, flags, isdup)
-	const DB *dbp;
-	DBT *key;
-	const DBT *data;
+static int
+__db_c_put_arg(dbc, key, data, flags)
+	DBC *dbc;
+	DBT *key, *data;
 	u_int32_t flags;
-	int isdup;
 {
-	int ret, returnkey;
+	DB *dbp;
+	DB_ENV *dbenv;
+	int key_flags, ret;
 
-	returnkey = 0;
+	dbp = dbc->dbp;
+	dbenv = dbp->dbenv;
+	key_flags = 0;
 
 	/* Check for changes to a read-only tree. */
 	if (IS_READONLY(dbp))
-		return (__db_rdonly(dbp->dbenv, "put"));
+		return (__db_rdonly(dbenv, "c_put"));
 
 	/* Check for puts on a secondary. */
 	if (F_ISSET(dbp, DB_AM_SECONDARY)) {
-		__db_err(dbp->dbenv, "DB->put forbidden on secondary indices");
-		return (EINVAL);
+		if (flags == DB_UPDATE_SECONDARY)
+			flags = DB_KEYLAST;
+		else {
+			__db_err(dbenv,
+		    "DBcursor->put forbidden on secondary indices");
+			return (EINVAL);
+		}
 	}
 
 	/* Check for invalid function flags. */
-	LF_CLR(DB_AUTO_COMMIT);
 	switch (flags) {
-	case 0:
-	case DB_NOOVERWRITE:
-		break;
-	case DB_APPEND:
-		if (dbp->type != DB_RECNO && dbp->type != DB_QUEUE)
+	case DB_AFTER:
+	case DB_BEFORE:
+		switch (dbp->type) {
+		case DB_BTREE:
+		case DB_HASH:		/* Only with unsorted duplicates. */
+			if (!F_ISSET(dbp, DB_AM_DUP))
+				goto err;
+			if (dbp->dup_compare != NULL)
+				goto err;
+			break;
+		case DB_QUEUE:		/* Not permitted. */
 			goto err;
-		returnkey = 1;
+		case DB_RECNO:		/* Only with mutable record numbers. */
+			if (!F_ISSET(dbp, DB_AM_RENUMBER))
+				goto err;
+			key_flags = 1;
+			break;
+		case DB_UNKNOWN:
+		default:
+			goto err;
+		}
+		break;
+	case DB_CURRENT:
+		/*
+		 * If there is a comparison function, doing a DB_CURRENT
+		 * must not change the part of the data item that is used
+		 * for the comparison.
+		 */
 		break;
 	case DB_NODUPDATA:
-		if (F_ISSET(dbp, DB_AM_DUPSORT))
-			break;
+		if (!F_ISSET(dbp, DB_AM_DUPSORT))
+			goto err;
 		/* FALLTHROUGH */
+	case DB_KEYFIRST:
+	case DB_KEYLAST:
+		key_flags = 1;
+		break;
 	default:
-err:		return (__db_ferr(dbp->dbenv, "DB->put", 0));
+err:		return (__db_ferr(dbenv, "DBcursor->put", 0));
 	}
 
 	/* Check for invalid key/data flags. */
-	if ((ret = __dbt_ferr(dbp, "key", key, returnkey)) != 0)
+	if (key_flags && (ret = __dbt_ferr(dbp, "key", key, 0)) != 0)
 		return (ret);
 	if ((ret = __dbt_ferr(dbp, "data", data, 0)) != 0)
 		return (ret);
 
-	/* Check for partial puts in the presence of duplicates. */
-	if (isdup && F_ISSET(data, DB_DBT_PARTIAL)) {
-		__db_err(dbp->dbenv,
-"a partial put in the presence of duplicates requires a cursor operation");
-		return (EINVAL);
-	}
-
-	return (0);
-}
-
-/*
- * __db_statchk --
- *	Common stat argument checking routine.
- *
- * PUBLIC: int __db_statchk __P((const DB *, u_int32_t));
- */
-int
-__db_statchk(dbp, flags)
-	const DB *dbp;
-	u_int32_t flags;
-{
-	/* Check for invalid function flags. */
-	switch (flags) {
-	case 0:
-	case DB_FAST_STAT:
-	case DB_CACHED_COUNTS:		/* Deprecated and undocumented. */
-		break;
-	case DB_RECORDCOUNT:		/* Deprecated and undocumented. */
-		if (dbp->type == DB_RECNO)
-			break;
-		if (dbp->type == DB_BTREE && F_ISSET(dbp, DB_AM_RECNUM))
-			break;
-		goto err;
-	default:
-err:		return (__db_ferr(dbp->dbenv, "DB->stat", 0));
-	}
-
-	return (0);
-}
+	/* Keys shouldn't have partial flags during a put. */
+	if (F_ISSET(key, DB_DBT_PARTIAL))
+		return (__db_ferr(dbenv, "key DBT", 0));
 
-/*
- * __db_syncchk --
- *	Common sync argument checking routine.
- *
- * PUBLIC: int __db_syncchk __P((const DB *, u_int32_t));
- */
-int
-__db_syncchk(dbp, flags)
-	const DB *dbp;
-	u_int32_t flags;
-{
-	/* Check for invalid function flags. */
-	switch (flags) {
-	case 0:
-		break;
-	default:
-		return (__db_ferr(dbp->dbenv, "DB->sync", 0));
-	}
+	/*
+	 * The cursor must be initialized for anything other than DB_KEYFIRST
+	 * and DB_KEYLAST, return EINVAL for an invalid cursor, otherwise 0.
+	 */
+	if (!IS_INITIALIZED(dbc) && flags != DB_KEYFIRST &&
+	    flags != DB_KEYLAST && flags != DB_NODUPDATA)
+		return (__db_curinval(dbenv));
 
 	return (0);
 }
@@ -860,20 +2250,6 @@ __db_rdonly(dbenv, name)
 	return (EACCES);
 }
 
-/*
- * __db_fnl --
- *	Common flag-needs-locking message.
- */
-static int
-__db_fnl(dbenv, name)
-	const DB_ENV *dbenv;
-	const char *name;
-{
-	__db_err(dbenv,
-	    "%s: the DB_DIRTY_READ and DB_RMW flags require locking", name);
-	return (EINVAL);
-}
-
 /*
  * __db_curinval
  *	Report that a cursor is in an invalid state.
@@ -888,96 +2264,58 @@ __db_curinval(dbenv)
 }
 
 /*
- * __db_secondary_corrupt --
- *	Report that a secondary index appears corrupt, as it has a record
- * that does not correspond to a record in the primary.
- *
- * PUBLIC: int __db_secondary_corrupt __P((DB *));
- */
-int
-__db_secondary_corrupt(dbp)
-	DB *dbp;
-{
-
-	__db_err(dbp->dbenv,
-	    "Secondary index corrupt: item in secondary not found in primary");
-	return (DB_SECONDARY_BAD);
-}
-
-/*
- * __db_associatechk --
- *	Argument checking routine for DB->associate().
+ * __db_txn_auto_init --
+ *	Handle DB_AUTO_COMMIT initialization.
  *
- * PUBLIC: int __db_associatechk __P((DB *, DB *,
- * PUBLIC:     int (*)(DB *, const DBT *, const DBT *, DBT *), u_int32_t));
+ * PUBLIC: int __db_txn_auto_init __P((DB_ENV *, DB_TXN **));
  */
 int
-__db_associatechk(dbp, sdbp, callback, flags)
-	DB *dbp, *sdbp;
-	int (*callback) __P((DB *, const DBT *, const DBT *, DBT *));
-	u_int32_t flags;
-{
+__db_txn_auto_init(dbenv, txnidp)
 	DB_ENV *dbenv;
-
-	dbenv = dbp->dbenv;
-
-	if (F_ISSET(sdbp, DB_AM_SECONDARY)) {
-		__db_err(dbenv,
-		    "Secondary index handles may not be re-associated");
-		return (EINVAL);
-	}
-	if (F_ISSET(dbp, DB_AM_SECONDARY)) {
-		__db_err(dbenv,
-		    "Secondary indices may not be used as primary databases");
-		return (EINVAL);
-	}
-	if (F_ISSET(dbp, DB_AM_DUP)) {
-		__db_err(dbenv,
-		    "Primary databases may not be configured with duplicates");
-		return (EINVAL);
-	}
-	if (F_ISSET(dbp, DB_AM_RENUMBER)) {
+	DB_TXN **txnidp;
+{
+	if (*txnidp != NULL) {
 		__db_err(dbenv,
-	    "Renumbering recno databases may not be used as primary databases");
+    "DB_AUTO_COMMIT may not be specified along with a transaction handle");
 		return (EINVAL);
 	}
-	if (callback == NULL &&
-	    (!F_ISSET(dbp, DB_AM_RDONLY) || !F_ISSET(sdbp, DB_AM_RDONLY))) {
+
+	if (!TXN_ON(dbenv)) {
 		__db_err(dbenv,
-    "Callback function may be NULL only when database handles are read-only");
+    "DB_AUTO_COMMIT may not be specified in non-transactional environment");
 		return (EINVAL);
 	}
 
-	return (__db_fchk(dbenv,
-	    "DB->associate", flags, DB_CREATE | DB_AUTO_COMMIT));
+	/*
+	 * We're creating a transaction for the user, and we want it to block
+	 * if replication recovery is running.  Call the user-level API.
+	 */
+	return (dbenv->txn_begin(dbenv, NULL, txnidp, 0));
 }
 
 /*
- * __db_txn_auto --
- *	Handle DB_AUTO_COMMIT initialization.
+ * __db_txn_auto_resolve --
+ *	Handle DB_AUTO_COMMIT resolution.
  *
- * PUBLIC: int __db_txn_auto __P((DB *, DB_TXN **));
+ * PUBLIC: int __db_txn_auto_resolve __P((DB_ENV *, DB_TXN *, int, int));
  */
 int
-__db_txn_auto(dbp, txnidp)
-	DB *dbp;
-	DB_TXN **txnidp;
-{
+__db_txn_auto_resolve(dbenv, txn, nosync, ret)
 	DB_ENV *dbenv;
+	DB_TXN *txn;
+	int nosync, ret;
+{
+	int t_ret;
 
-	dbenv = dbp->dbenv;
-
-	if (*txnidp != NULL) {
-		__db_err(dbenv,
-    "DB_AUTO_COMMIT may not be specified along with a transaction handle");
-		return (EINVAL);
-	}
+	/*
+	 * We're resolving a transaction for the user, and must decrement the
+	 * replication handle count.  Call the user-level API.
+	 */
+	if (ret == 0)
+		return (txn->commit(txn, nosync ? DB_TXN_NOSYNC : 0));
 
-	if (!TXN_ON(dbenv)) {
-		__db_err(dbenv,
-    "DB_AUTO_COMMIT may not be specified in non-transactional environment");
-		return (EINVAL);
-	}
+	if ((t_ret = txn->abort(txn)) != 0)
+		return (__db_panic(dbenv, t_ret));
 
-	return (dbenv->txn_begin(dbenv, NULL, txnidp, 0));
+	return (ret);
 }
diff --git a/storage/bdb/db/db_join.c b/storage/bdb/db/db_join.c
index 6281b1a83839e480557e7537d71380fc7b3c324a..f486f296ebf4e8c02ff26b67f1a4070b695fabf7 100644
--- a/storage/bdb/db/db_join.c
+++ b/storage/bdb/db/db_join.c
@@ -1,16 +1,14 @@
 /*
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1998-2002
+ * Copyright (c) 1998-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_join.c,v 11.75 2004/09/22 03:30:23 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_join.c,v 11.55 2002/08/08 03:57:47 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -23,10 +21,11 @@ static const char revid[] = "$Id: db_join.c,v 11.55 2002/08/08 03:57:47 bostic E
 #include "dbinc/db_join.h"
 #include "dbinc/btree.h"
 
-static int __db_join_close __P((DBC *));
+static int __db_join_close_pp __P((DBC *));
 static int __db_join_cmp __P((const void *, const void *));
 static int __db_join_del __P((DBC *, u_int32_t));
 static int __db_join_get __P((DBC *, DBT *, DBT *, u_int32_t));
+static int __db_join_get_pp __P((DBC *, DBT *, DBT *, u_int32_t));
 static int __db_join_getnext __P((DBC *, DBT *, DBT *, u_int32_t, u_int32_t));
 static int __db_join_primget __P((DB *,
     DB_TXN *, u_int32_t, DBT *, DBT *, u_int32_t));
@@ -67,7 +66,7 @@ static int __db_join_put __P((DBC *, DBT *, DBT *, u_int32_t));
  * cursor method of a DB, join cursors are created through an explicit
  * call to DB->join.
  *
- * The curslist is an array of existing, intialized cursors and primary
+ * The curslist is an array of existing, initialized cursors and primary
  * is the DB of the primary file.  The data item that joins all the
  * cursors in the curslist is used as the key into the primary and that
  * key and data are returned.  When no more items are left in the join
@@ -84,26 +83,18 @@ __db_join(primary, curslist, dbcp, flags)
 	DB_ENV *dbenv;
 	DBC *dbc;
 	JOIN_CURSOR *jc;
-	int ret;
-	u_int32_t i;
 	size_t ncurs, nslots;
+	u_int32_t i;
+	int ret;
 
-	COMPQUIET(nslots, 0);
-
-	PANIC_CHECK(primary->dbenv);
-
-	if ((ret = __db_joinchk(primary, curslist, flags)) != 0)
-		return (ret);
-
+	dbenv = primary->dbenv;
 	dbc = NULL;
 	jc = NULL;
-	dbenv = primary->dbenv;
 
 	if ((ret = __os_calloc(dbenv, 1, sizeof(DBC), &dbc)) != 0)
 		goto err;
 
-	if ((ret = __os_calloc(dbenv,
-	    1, sizeof(JOIN_CURSOR), &jc)) != 0)
+	if ((ret = __os_calloc(dbenv, 1, sizeof(JOIN_CURSOR), &jc)) != 0)
 		goto err;
 
 	if ((ret = __os_malloc(dbenv, 256, &jc->j_key.data)) != 0)
@@ -122,7 +113,7 @@ __db_join(primary, curslist, dbcp, flags)
 	 * the number of cursors involved in the join, because the
 	 * list is NULL-terminated.
 	 */
-	ncurs = jc->j_curslist - curslist;
+	ncurs = (size_t)(jc->j_curslist - curslist);
 	nslots = ncurs + 1;
 
 	/*
@@ -208,18 +199,21 @@ __db_join(primary, curslist, dbcp, flags)
 	 * because this is the last thing that can fail.  Modifier of this
 	 * function beware!
 	 */
-	if ((ret = jc->j_curslist[0]->c_dup(jc->j_curslist[0], jc->j_workcurs,
-	    DB_POSITIONI)) != 0)
+	if ((ret =
+	    __db_c_dup(jc->j_curslist[0], jc->j_workcurs, DB_POSITION)) != 0)
 		goto err;
 
-	dbc->c_close = __db_join_close;
+	dbc->c_close = __db_join_close_pp;
 	dbc->c_del = __db_join_del;
-	dbc->c_get = __db_join_get;
+	dbc->c_get = __db_join_get_pp;
 	dbc->c_put = __db_join_put;
-	dbc->internal = (DBC_INTERNAL *) jc;
+	dbc->internal = (DBC_INTERNAL *)jc;
 	dbc->dbp = primary;
 	jc->j_primary = primary;
 
+	/* Stash the first cursor's transaction here for easy access. */
+	dbc->txn = curslist[0]->txn;
+
 	*dbcp = dbc;
 
 	MUTEX_THREAD_LOCK(dbenv, primary->mutexp);
@@ -233,7 +227,7 @@ err:	if (jc != NULL) {
 			__os_free(dbenv, jc->j_curslist);
 		if (jc->j_workcurs != NULL) {
 			if (jc->j_workcurs[0] != NULL)
-				__os_free(dbenv, jc->j_workcurs[0]);
+				(void)__db_c_close(jc->j_workcurs[0]);
 			__os_free(dbenv, jc->j_workcurs);
 		}
 		if (jc->j_fdupcurs != NULL)
@@ -247,6 +241,36 @@ err:	if (jc != NULL) {
 	return (ret);
 }
 
+/*
+ * __db_join_close_pp --
+ *	DBC->c_close pre/post processing for join cursors.
+ */
+static int
+__db_join_close_pp(dbc)
+	DBC *dbc;
+{
+	DB_ENV *dbenv;
+	DB *dbp;
+	int handle_check, ret;
+
+	dbp = dbc->dbp;
+	dbenv = dbp->dbenv;
+
+	PANIC_CHECK(dbenv);
+
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check &&
+	    (ret = __db_rep_enter(dbp, 0, 0, dbc->txn != NULL)) != 0)
+		return (ret);
+
+	ret = __db_join_close(dbc);
+
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
+
+	return (ret);
+}
+
 static int
 __db_join_put(dbc, key, data, flags)
 	DBC *dbc;
@@ -273,6 +297,77 @@ __db_join_del(dbc, flags)
 	return (EINVAL);
 }
 
+/*
+ * __db_join_get_pp --
+ *	DBjoin->get pre/post processing.
+ */
+static int
+__db_join_get_pp(dbc, key, data, flags)
+	DBC *dbc;
+	DBT *key, *data;
+	u_int32_t flags;
+{
+	DB *dbp;
+	DB_ENV *dbenv;
+	u_int32_t handle_check, save_flags;
+	int ret;
+
+	dbp = dbc->dbp;
+	dbenv = dbp->dbenv;
+
+	/* Save the original flags value. */
+	save_flags = flags;
+
+	PANIC_CHECK(dbenv);
+
+	if (LF_ISSET(DB_DIRTY_READ | DB_DEGREE_2 | DB_RMW)) {
+		if (!LOCKING_ON(dbp->dbenv))
+			return (__db_fnl(dbp->dbenv, "DBcursor->c_get"));
+
+		LF_CLR(DB_DIRTY_READ | DB_DEGREE_2 | DB_RMW);
+	}
+
+	switch (flags) {
+	case 0:
+	case DB_JOIN_ITEM:
+		break;
+	default:
+		return (__db_ferr(dbp->dbenv, "DBcursor->c_get", 0));
+	}
+
+	/*
+	 * A partial get of the key of a join cursor don't make much sense;
+	 * the entire key is necessary to query the primary database
+	 * and find the datum, and so regardless of the size of the key
+	 * it would not be a performance improvement.  Since it would require
+	 * special handling, we simply disallow it.
+	 *
+	 * A partial get of the data, however, potentially makes sense (if
+	 * all possible data are a predictable large structure, for instance)
+	 * and causes us no headaches, so we permit it.
+	 */
+	if (F_ISSET(key, DB_DBT_PARTIAL)) {
+		__db_err(dbp->dbenv,
+		    "DB_DBT_PARTIAL may not be set on key during join_get");
+		return (EINVAL);
+	}
+
+	handle_check = IS_REPLICATED(dbp->dbenv, dbp);
+	if (handle_check &&
+	    (ret = __db_rep_enter(dbp, 1, 0, dbc->txn != NULL)) != 0)
+		return (ret);
+
+	/* Restore the original flags value. */
+	flags = save_flags;
+
+	ret = __db_join_get(dbc, key, data, flags);
+
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
+
+	return (ret);
+}
+
 static int
 __db_join_get(dbc, key_arg, data_arg, flags)
 	DBC *dbc;
@@ -289,18 +384,13 @@ __db_join_get(dbc, key_arg, data_arg, flags)
 	dbp = dbc->dbp;
 	jc = (JOIN_CURSOR *)dbc->internal;
 
-	PANIC_CHECK(dbp->dbenv);
-
 	operation = LF_ISSET(DB_OPFLAGS_MASK);
 
 	/* !!!
 	 * If the set of flags here changes, check that __db_join_primget
 	 * is updated to handle them properly.
 	 */
-	opmods = LF_ISSET(DB_RMW | DB_DIRTY_READ);
-
-	if ((ret = __db_joingetchk(dbp, key_arg, flags)) != 0)
-		return (ret);
+	opmods = LF_ISSET(DB_RMW | DB_DEGREE_2 | DB_DIRTY_READ);
 
 	/*
 	 * Since we are fetching the key as a datum in the secondary indices,
@@ -329,11 +419,10 @@ __db_join_get(dbc, key_arg, data_arg, flags)
 		goto samekey;
 	F_CLR(jc, JOIN_RETRY);
 
-retry:	ret = jc->j_workcurs[0]->c_real_get(jc->j_workcurs[0],
-	    &jc->j_key, key_n,
+retry:	ret = __db_c_get(jc->j_workcurs[0], &jc->j_key, key_n,
 	    opmods | (jc->j_exhausted[0] ? DB_NEXT_DUP : DB_CURRENT));
 
-	if (ret == ENOMEM) {
+	if (ret == DB_BUFFER_SMALL) {
 		jc->j_key.ulen <<= 1;
 		if ((ret = __os_realloc(dbp->dbenv,
 		    jc->j_key.ulen, &jc->j_key.data)) != 0)
@@ -358,7 +447,7 @@ retry:	ret = jc->j_workcurs[0]->c_real_get(jc->j_workcurs[0],
 	 */
 	for (i = 1; i < jc->j_ncurs; i++) {
 		if (jc->j_fdupcurs[i] != NULL &&
-		    (ret = jc->j_fdupcurs[i]->c_close(jc->j_fdupcurs[i])) != 0)
+		    (ret = __db_c_close(jc->j_fdupcurs[i])) != 0)
 			goto err;
 		jc->j_fdupcurs[i] = NULL;
 	}
@@ -382,9 +471,8 @@ retry:	ret = jc->j_workcurs[0]->c_real_get(jc->j_workcurs[0],
 		DB_ASSERT(jc->j_curslist[i] != NULL);
 		if (jc->j_workcurs[i] == NULL)
 			/* If this is NULL, we need to dup curslist into it. */
-			if ((ret = jc->j_curslist[i]->c_dup(
-			    jc->j_curslist[i], jc->j_workcurs + i,
-			    DB_POSITIONI)) != 0)
+			if ((ret = __db_c_dup(jc->j_curslist[i],
+			    &jc->j_workcurs[i], DB_POSITION)) != 0)
 				goto err;
 
 retry2:		cp = jc->j_workcurs[i];
@@ -435,7 +523,7 @@ retry2:		cp = jc->j_workcurs[i];
 					 * and let strange things happen--we
 					 * can't make rope childproof.
 					 */
-					if ((ret = jc->j_workcurs[j]->c_close(
+					if ((ret = __db_c_close(
 					    jc->j_workcurs[j])) != 0)
 						goto err;
 					if (!SORTED_SET(jc, 0) ||
@@ -448,10 +536,10 @@ retry2:		cp = jc->j_workcurs[i];
 						jc->j_workcurs[j] = NULL;
 					else
 						/* Partial reset suffices. */
-						if ((jc->j_fdupcurs[j]->c_dup(
+						if ((__db_c_dup(
 						    jc->j_fdupcurs[j],
 						    &jc->j_workcurs[j],
-						    DB_POSITIONI)) != 0)
+						    DB_POSITION)) != 0)
 							goto err;
 					jc->j_exhausted[j] = 0;
 				}
@@ -467,23 +555,21 @@ retry2:		cp = jc->j_workcurs[i];
 			for (j = i + 1;
 			    jc->j_workcurs[j] != NULL;
 			    j++) {
-				if ((ret = jc->j_workcurs[j]->c_close(
-				    jc->j_workcurs[j])) != 0)
+				if ((ret =
+				    __db_c_close(jc->j_workcurs[j])) != 0)
 					goto err;
 				jc->j_exhausted[j] = 0;
-				if (jc->j_fdupcurs[j] != NULL &&
-				    (ret = jc->j_fdupcurs[j]->c_dup(
-				    jc->j_fdupcurs[j], &jc->j_workcurs[j],
-				    DB_POSITIONI)) != 0)
-					goto err;
-				else
+				if (jc->j_fdupcurs[j] == NULL)
 					jc->j_workcurs[j] = NULL;
+				else if ((ret = __db_c_dup(jc->j_fdupcurs[j],
+				    &jc->j_workcurs[j], DB_POSITION)) != 0)
+					goto err;
 			}
 			goto retry2;
 			/* NOTREACHED */
 		}
 
-		if (ret == ENOMEM) {
+		if (ret == DB_BUFFER_SMALL) {
 			jc->j_key.ulen <<= 1;
 			if ((ret = __os_realloc(dbp->dbenv, jc->j_key.ulen,
 			    &jc->j_key.data)) != 0) {
@@ -521,9 +607,8 @@ mem_err:			__db_err(dbp->dbenv,
 		 * duplicate duplicates;  store this into jc->j_fdupcurs[i].
 		 */
 		if (SORTED_SET(jc, i) && jc->j_fdupcurs[i] == NULL && (ret =
-		    cp->c_dup(cp, &jc->j_fdupcurs[i], DB_POSITIONI)) != 0)
+		    __db_c_dup(cp, &jc->j_fdupcurs[i], DB_POSITION)) != 0)
 			goto err;
-
 	}
 
 err:	if (ret != 0)
@@ -534,7 +619,7 @@ samekey:	/*
 		 * Get the key we tried and failed to return last time;
 		 * it should be the current datum of all the secondary cursors.
 		 */
-		if ((ret = jc->j_workcurs[0]->c_real_get(jc->j_workcurs[0],
+		if ((ret = __db_c_get(jc->j_workcurs[0],
 		    &jc->j_key, key_n, DB_CURRENT | opmods)) != 0)
 			return (ret);
 		F_CLR(jc, JOIN_RETRY);
@@ -615,7 +700,13 @@ samekey:	/*
 	return (ret);
 }
 
-static int
+/*
+ * __db_join_close --
+ *	DBC->c_close for join cursors.
+ *
+ * PUBLIC: int __db_join_close __P((DBC *));
+ */
+int
 __db_join_close(dbc)
 	DBC *dbc;
 {
@@ -653,11 +744,11 @@ __db_join_close(dbc)
 	 * mucking with.
 	 */
 	for (i = 0; i < jc->j_ncurs; i++) {
-		if (jc->j_workcurs[i] != NULL && (t_ret =
-		    jc->j_workcurs[i]->c_close(jc->j_workcurs[i])) != 0)
+		if (jc->j_workcurs[i] != NULL &&
+		    (t_ret = __db_c_close(jc->j_workcurs[i])) != 0)
 			ret = t_ret;
-		if (jc->j_fdupcurs[i] != NULL && (t_ret =
-		    jc->j_fdupcurs[i]->c_close(jc->j_fdupcurs[i])) != 0)
+		if (jc->j_fdupcurs[i] != NULL &&
+		    (t_ret = __db_c_close(jc->j_fdupcurs[i])) != 0)
 			ret = t_ret;
 	}
 
@@ -711,7 +802,7 @@ __db_join_getnext(dbc, key, data, exhausted, opmods)
 		 */
 		memset(&ldata, 0, sizeof(DBT));
 		F_SET(&ldata, DB_DBT_MALLOC);
-		if ((ret = dbc->c_real_get(dbc,
+		if ((ret = __db_c_get(dbc,
 		    key, &ldata, opmods | DB_CURRENT)) != 0)
 			break;
 		cmp = func(dbp, data, &ldata);
@@ -736,7 +827,7 @@ __db_join_getnext(dbc, key, data, exhausted, opmods)
 		__os_ufree(dbp->dbenv, ldata.data);
 		/* FALLTHROUGH */
 	case 1:
-		ret = dbc->c_real_get(dbc, key, data, opmods | DB_GET_BOTHC);
+		ret = __db_c_get(dbc, key, data, opmods | DB_GET_BOTHC);
 		break;
 	default:
 		ret = EINVAL;
@@ -757,17 +848,14 @@ __db_join_cmp(a, b)
 	DBC *dbca, *dbcb;
 	db_recno_t counta, countb;
 
-	/* In case c_count fails, pretend cursors are equal. */
-	counta = countb = 0;
-
 	dbca = *((DBC * const *)a);
 	dbcb = *((DBC * const *)b);
 
-	if (dbca->c_count(dbca, &counta, 0) != 0 ||
-	    dbcb->c_count(dbcb, &countb, 0) != 0)
+	if (__db_c_count(dbca, &counta) != 0 ||
+	    __db_c_count(dbcb, &countb) != 0)
 		return (0);
 
-	return (counta - countb);
+	return ((long)counta - (long)countb);
 }
 
 /*
@@ -784,7 +872,11 @@ __db_join_primget(dbp, txn, lockerid, key, data, flags)
 	u_int32_t flags;
 {
 	DBC *dbc;
-	int dirty, ret, rmw, t_ret;
+	int ret, rmw, t_ret;
+
+	if ((ret = __db_cursor_int(dbp,
+	    txn, dbp->type, PGNO_INVALID, 0, lockerid, &dbc)) != 0)
+		return (ret);
 
 	/*
 	 * The only allowable flags here are the two flags copied into
@@ -793,17 +885,17 @@ __db_join_primget(dbp, txn, lockerid, key, data, flags)
 	 * It's a DB bug if we allow any other flags down in here.
 	 */
 	rmw = LF_ISSET(DB_RMW);
-	dirty = LF_ISSET(DB_DIRTY_READ);
-	LF_CLR(DB_RMW | DB_DIRTY_READ);
-	DB_ASSERT(flags == 0);
-
-	if ((ret = __db_icursor(dbp,
-	    txn, dbp->type, PGNO_INVALID, 0, lockerid, &dbc)) != 0)
-		return (ret);
-
-	if (dirty ||
+	if (LF_ISSET(DB_DIRTY_READ) ||
 	    (txn != NULL && F_ISSET(txn, TXN_DIRTY_READ)))
 		F_SET(dbc, DBC_DIRTY_READ);
+
+	if (LF_ISSET(DB_DEGREE_2) ||
+	    (txn != NULL && F_ISSET(txn, TXN_DEGREE_2)))
+		F_SET(dbc, DBC_DEGREE_2);
+
+	LF_CLR(DB_RMW | DB_DIRTY_READ | DB_DEGREE_2);
+	DB_ASSERT(flags == 0);
+
 	F_SET(dbc, DBC_TRANSIENT);
 
 	/*
@@ -813,10 +905,26 @@ __db_join_primget(dbp, txn, lockerid, key, data, flags)
 	 */
 	SET_RET_MEM(dbc, dbp);
 
-	ret = dbc->c_get(dbc, key, data, DB_SET | rmw);
+	ret = __db_c_get(dbc, key, data, DB_SET | rmw);
 
 	if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
 		ret = t_ret;
 
 	return (ret);
 }
+
+/*
+ * __db_secondary_corrupt --
+ *	Report that a secondary index appears corrupt, as it has a record
+ * that does not correspond to a record in the primary or vice versa.
+ *
+ * PUBLIC: int __db_secondary_corrupt __P((DB *));
+ */
+int
+__db_secondary_corrupt(dbp)
+	DB *dbp;
+{
+	__db_err(dbp->dbenv,
+	    "Secondary index corrupt: not consistent with primary");
+	return (DB_SECONDARY_BAD);
+}
diff --git a/storage/bdb/db/db_meta.c b/storage/bdb/db/db_meta.c
index 015ef5c8fc7ad87a4379b5293417e99d03b273c8..c5e88bb560a6a42c31f10e9bfef0a41002139215 100644
--- a/storage/bdb/db/db_meta.c
+++ b/storage/bdb/db/db_meta.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -38,14 +38,12 @@
  * 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.
+ *
+ * $Id: db_meta.c,v 11.89 2004/10/05 14:28:33 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_meta.c,v 11.61 2002/08/08 03:57:48 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -56,9 +54,10 @@ static const char revid[] = "$Id: db_meta.c,v 11.61 2002/08/08 03:57:48 bostic E
 #include "dbinc/db_page.h"
 #include "dbinc/db_shash.h"
 #include "dbinc/lock.h"
+#include "dbinc/mp.h"
 #include "dbinc/db_am.h"
 
-static void __db_init_meta __P((void *, u_int32_t, db_pgno_t, u_int32_t));
+static void __db_init_meta __P((DB *, void *, db_pgno_t, u_int32_t));
 
 /*
  * __db_init_meta --
@@ -67,9 +66,9 @@ static void __db_init_meta __P((void *, u_int32_t, db_pgno_t, u_int32_t));
  * retain the page number and LSN of the existing page.
  */
 static void
-__db_init_meta(p, pgsize, pgno, pgtype)
+__db_init_meta(dbp, p, pgno, pgtype)
+	DB *dbp;
 	void *p;
-	u_int32_t pgsize;
 	db_pgno_t pgno;
 	u_int32_t pgtype;
 {
@@ -80,7 +79,9 @@ __db_init_meta(p, pgsize, pgno, pgtype)
 	save_lsn = meta->lsn;
 	memset(meta, 0, sizeof(DBMETA));
 	meta->lsn = save_lsn;
-	meta->pagesize = pgsize;
+	meta->pagesize = dbp->pgsize;
+	if (F_ISSET(dbp, DB_AM_CHKSUM))
+		FLD_SET(meta->metaflags, DBMETA_CHKSUM);
 	meta->pgno = pgno;
 	meta->type = (u_int8_t)pgtype;
 }
@@ -103,8 +104,9 @@ __db_new(dbc, type, pagepp)
 	DB_LSN lsn;
 	DB_MPOOLFILE *mpf;
 	PAGE *h;
-	db_pgno_t pgno, newnext;
-	int meta_flags, extend, ret;
+	db_pgno_t last, pgno, newnext;
+	u_int32_t meta_flags;
+	int extend, ret, t_ret;
 
 	meta = NULL;
 	meta_flags = 0;
@@ -117,15 +119,16 @@ __db_new(dbc, type, pagepp)
 	if ((ret = __db_lget(dbc,
 	    LCK_ALWAYS, pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
 		goto err;
-	if ((ret = mpf->get(mpf, &pgno, 0, (PAGE **)&meta)) != 0)
+	if ((ret = __memp_fget(mpf, &pgno, 0, &meta)) != 0)
 		goto err;
+	last = meta->last_pgno;
 	if (meta->free == PGNO_INVALID) {
-		pgno = meta->last_pgno + 1;
+		last = pgno = meta->last_pgno + 1;
 		ZERO_LSN(lsn);
 		extend = 1;
 	} else {
 		pgno = meta->free;
-		if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
+		if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
 			goto err;
 
 		/*
@@ -145,8 +148,8 @@ __db_new(dbc, type, pagepp)
 	 */
 	if (DBC_LOGGING(dbc)) {
 		if ((ret = __db_pg_alloc_log(dbp, dbc->txn, &LSN(meta), 0,
-		    &LSN(meta), PGNO_BASE_MD, &lsn, pgno,
-		    (u_int32_t)type, newnext)) != 0)
+		    &LSN(meta), PGNO_BASE_MD, &lsn,
+		    pgno, (u_int32_t)type, newnext, meta->last_pgno)) != 0)
 			goto err;
 	} else
 		LSN_NOT_LOGGED(LSN(meta));
@@ -155,12 +158,12 @@ __db_new(dbc, type, pagepp)
 	meta->free = newnext;
 
 	if (extend == 1) {
-		meta->last_pgno++;
-		if ((ret = mpf->get(mpf, &pgno, DB_MPOOL_NEW, &h)) != 0)
+		if ((ret = __memp_fget(mpf, &pgno, DB_MPOOL_NEW, &h)) != 0)
 			goto err;
+		DB_ASSERT(last == pgno);
+		meta->last_pgno = pgno;
 		ZERO_LSN(h->lsn);
 		h->pgno = pgno;
-		DB_ASSERT(pgno == meta->last_pgno);
 	}
 	LSN(h) = LSN(meta);
 
@@ -169,14 +172,18 @@ __db_new(dbc, type, pagepp)
 	if (TYPE(h) != P_INVALID)
 		return (__db_panic(dbp->dbenv, EINVAL));
 
-	(void)mpf->put(mpf, (PAGE *)meta, DB_MPOOL_DIRTY);
-	(void)__TLPUT(dbc, metalock);
+	ret = __memp_fput(mpf, (PAGE *)meta, DB_MPOOL_DIRTY);
+	meta = NULL;
+	if ((t_ret = __TLPUT(dbc, metalock)) != 0 && ret == 0)
+		ret = t_ret;
+	if (ret != 0)
+		goto err;
 
 	switch (type) {
 		case P_BTREEMETA:
 		case P_HASHMETA:
 		case P_QAMMETA:
-			__db_init_meta(h, dbp->pgsize, h->pgno, type);
+			__db_init_meta(dbp, h, h->pgno, type);
 			break;
 		default:
 			P_INIT(h, dbp->pgsize,
@@ -201,9 +208,9 @@ __db_new(dbc, type, pagepp)
 	return (0);
 
 err:	if (h != NULL)
-		(void)mpf->put(mpf, h, 0);
+		(void)__memp_fput(mpf, h, 0);
 	if (meta != NULL)
-		(void)mpf->put(mpf, meta, meta_flags);
+		(void)__memp_fput(mpf, meta, meta_flags);
 	(void)__TLPUT(dbc, metalock);
 	return (ret);
 }
@@ -221,7 +228,7 @@ __db_free(dbc, h)
 {
 	DBMETA *meta;
 	DB *dbp;
-	DBT ldbt;
+	DBT ddbt, ldbt;
 	DB_LOCK metalock;
 	DB_MPOOLFILE *mpf;
 	db_pgno_t pgno;
@@ -242,7 +249,7 @@ __db_free(dbc, h)
 	if ((ret = __db_lget(dbc,
 	    LCK_ALWAYS, pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
 		goto err;
-	if ((ret = mpf->get(mpf, &pgno, 0, (PAGE **)&meta)) != 0) {
+	if ((ret = __memp_fget(mpf, &pgno, 0, &meta)) != 0) {
 		(void)__TLPUT(dbc, metalock);
 		goto err;
 	}
@@ -253,10 +260,42 @@ __db_free(dbc, h)
 		memset(&ldbt, 0, sizeof(ldbt));
 		ldbt.data = h;
 		ldbt.size = P_OVERHEAD(dbp);
-		if ((ret = __db_pg_free_log(dbp,
-		    dbc->txn, &LSN(meta), 0, h->pgno,
-		    &LSN(meta), PGNO_BASE_MD, &ldbt, meta->free)) != 0) {
-			(void)mpf->put(mpf, (PAGE *)meta, 0);
+		switch (h->type) {
+		case P_HASH:
+		case P_IBTREE:
+		case P_IRECNO:
+		case P_LBTREE:
+		case P_LRECNO:
+		case P_LDUP:
+			if (h->entries > 0) {
+				ldbt.size += h->entries * sizeof(db_indx_t);
+				ddbt.data = (u_int8_t *)h + h->hf_offset;
+				ddbt.size = dbp->pgsize - h->hf_offset;
+				ret = __db_pg_freedata_log(dbp, dbc->txn,
+				     &LSN(meta), 0, h->pgno, &LSN(meta),
+				     PGNO_BASE_MD, &ldbt,
+				     meta->free, meta->last_pgno, &ddbt);
+				break;
+			}
+			goto log;
+		case P_HASHMETA:
+			ldbt.size = sizeof(HMETA);
+			goto log;
+		case P_BTREEMETA:
+			ldbt.size = sizeof(BTMETA);
+			goto log;
+		case P_OVERFLOW:
+			ldbt.size += OV_LEN(h);
+			goto log;
+		default:
+			DB_ASSERT(h->type != P_QAMDATA);
+
+log:			ret = __db_pg_free_log(dbp,
+			    dbc->txn, &LSN(meta), 0, h->pgno, &LSN(meta),
+			    PGNO_BASE_MD, &ldbt, meta->free, meta->last_pgno);
+		}
+		if (ret != 0) {
+			(void)__memp_fput(mpf, (PAGE *)meta, 0);
 			(void)__TLPUT(dbc, metalock);
 			goto err;
 		}
@@ -264,20 +303,44 @@ __db_free(dbc, h)
 		LSN_NOT_LOGGED(LSN(meta));
 	LSN(h) = LSN(meta);
 
-	P_INIT(h, dbp->pgsize, h->pgno, PGNO_INVALID, meta->free, 0, P_INVALID);
+#ifdef HAVE_FTRUNCATE
+	if (h->pgno == meta->last_pgno) {
+		if ((ret = __memp_fput(mpf, h, DB_MPOOL_DISCARD)) != 0)
+			goto err;
+		/* Give the page back to the OS. */
+		if ((ret = __memp_ftruncate(mpf, meta->last_pgno, 0)) != 0)
+			goto err;
+		meta->last_pgno--;
+		h = NULL;
+	} else
+#endif
 
-	meta->free = h->pgno;
+	{
+		/*
+		 * If we are not truncating the page then we
+		 * reinitialize it and put it hat the head of
+		 * the free list.
+		 */
+		P_INIT(h, dbp->pgsize,
+		    h->pgno, PGNO_INVALID, meta->free, 0, P_INVALID);
+#ifdef DIAGNOSTIC
+		memset((u_int8_t *) h + P_OVERHEAD(dbp),
+		    CLEAR_BYTE, dbp->pgsize - P_OVERHEAD(dbp));
+#endif
+		meta->free = h->pgno;
+	}
 
 	/* Discard the metadata page. */
 	if ((t_ret =
-	    mpf->put(mpf, (PAGE *)meta, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+	    __memp_fput(mpf, (PAGE *)meta, DB_MPOOL_DIRTY)) != 0 && ret == 0)
 		ret = t_ret;
 	if ((t_ret = __TLPUT(dbc, metalock)) != 0 && ret == 0)
 		ret = t_ret;
 
 	/* Discard the caller's page reference. */
 	dirty_flag = DB_MPOOL_DIRTY;
-err:	if ((t_ret = mpf->put(mpf, h, dirty_flag)) != 0 && ret == 0)
+err:	if (h != NULL &&
+	    (t_ret = __memp_fput(mpf, h, dirty_flag)) != 0 && ret == 0)
 		ret = t_ret;
 
 	/*
@@ -298,34 +361,21 @@ int
 __db_lprint(dbc)
 	DBC *dbc;
 {
+	DB_ENV *dbenv;
 	DB *dbp;
 	DB_LOCKREQ req;
 
 	dbp = dbc->dbp;
+	dbenv = dbp->dbenv;
 
-	if (LOCKING_ON(dbp->dbenv)) {
+	if (LOCKING_ON(dbenv)) {
 		req.op = DB_LOCK_DUMP;
-		dbp->dbenv->lock_vec(dbp->dbenv, dbc->locker, 0, &req, 1, NULL);
+		(void)__lock_vec(dbenv, dbc->locker, 0, &req, 1, NULL);
 	}
 	return (0);
 }
 #endif
 
-/*
- * Implement the rules for transactional locking.  We can release the previous
- * lock if we are not in a transaction or COUPLE_ALWAYS is specifed (used in
- * record locking).  If we are doing dirty reads then we can release read locks
- * and down grade write locks.
- */
-#define	DB_PUT_ACTION(dbc, action, lockp)				\
-	    (((action == LCK_COUPLE || action == LCK_COUPLE_ALWAYS) &&	\
-	    LOCK_ISSET(*lockp)) ?					\
-	    (dbc->txn == NULL || action == LCK_COUPLE_ALWAYS ||		\
-	    (F_ISSET(dbc, DBC_DIRTY_READ) &&				\
-	    (lockp)->mode == DB_LOCK_DIRTY)) ? LCK_COUPLE :		\
-	    (F_ISSET((dbc)->dbp, DB_AM_DIRTY) &&			\
-	    (lockp)->mode == DB_LOCK_WRITE) ? LCK_DOWNGRADE : 0 : 0)
-
 /*
  * __db_lget --
  *	The standard lock get call.
@@ -359,7 +409,7 @@ __db_lget(dbc, action, pgno, mode, lkflags, lockp)
 	if (CDB_LOCKING(dbenv) ||
 	    !LOCKING_ON(dbenv) || F_ISSET(dbc, DBC_COMPENSATE) ||
 	    (F_ISSET(dbc, DBC_RECOVER) &&
-	    (action != LCK_ROLLBACK || F_ISSET(dbenv, DB_ENV_REP_CLIENT))) ||
+	    (action != LCK_ROLLBACK || IS_REP_CLIENT(dbenv))) ||
 	    (action != LCK_ALWAYS && F_ISSET(dbc, DBC_OPD))) {
 		LOCK_INIT(*lockp);
 		return (0);
@@ -371,6 +421,8 @@ __db_lget(dbc, action, pgno, mode, lkflags, lockp)
 	else
 		dbc->lock.type = DB_PAGE_LOCK;
 	lkflags &= ~DB_LOCK_RECORD;
+	if (action == LCK_ROLLBACK)
+		lkflags |= DB_LOCK_ABORT;
 
 	/*
 	 * If the transaction enclosing this cursor has DB_LOCK_NOWAIT set,
@@ -382,42 +434,69 @@ __db_lget(dbc, action, pgno, mode, lkflags, lockp)
 	if (F_ISSET(dbc, DBC_DIRTY_READ) && mode == DB_LOCK_READ)
 		mode = DB_LOCK_DIRTY;
 
-	has_timeout = txn != NULL && F_ISSET(txn, TXN_LOCKTIMEOUT);
+	has_timeout = F_ISSET(dbc, DBC_RECOVER) ||
+	    (txn != NULL && F_ISSET(txn, TXN_LOCKTIMEOUT));
+
+	/*
+	 * Transactional locking.
+	 * Hold on to the previous read lock only if we are in full isolation.
+	 * COUPLE_ALWAYS indicates we are holding an interior node
+	 * which need not be isolated.
+	 * Downgrade write locks if we are supporting dirty readers.
+	 */
+	if ((action != LCK_COUPLE && action != LCK_COUPLE_ALWAYS) ||
+	    !LOCK_ISSET(*lockp))
+		action = 0;
+	else if (dbc->txn == NULL || action == LCK_COUPLE_ALWAYS)
+		action = LCK_COUPLE;
+	else if (F_ISSET(dbc, DBC_DEGREE_2) && lockp->mode == DB_LOCK_READ)
+		action = LCK_COUPLE;
+	else if (F_ISSET(dbc, DBC_DIRTY_READ) && lockp->mode == DB_LOCK_DIRTY)
+		action = LCK_COUPLE;
+	else if (F_ISSET(dbc->dbp, DB_AM_DIRTY) && lockp->mode == DB_LOCK_WRITE)
+		action = LCK_DOWNGRADE;
+	else
+		action = 0;
+
+	switch (action) {
+	case LCK_DOWNGRADE:
+		if ((ret = __lock_downgrade(
+		    dbenv, lockp, DB_LOCK_WWRITE, 0)) != 0)
+			return (ret);
+		/* FALLTHROUGH */
+
+	default:
+		if (!has_timeout) {
+			ret = __lock_get(dbenv,
+			    dbc->locker, lkflags, &dbc->lock_dbt, mode, lockp);
+			break;
+		}
 
-	switch (DB_PUT_ACTION(dbc, action, lockp)) {
+		/* FALLTHROUGH */
 	case LCK_COUPLE:
-lck_couple:	couple[0].op = has_timeout? DB_LOCK_GET_TIMEOUT : DB_LOCK_GET;
+		couple[0].op = has_timeout? DB_LOCK_GET_TIMEOUT : DB_LOCK_GET;
 		couple[0].obj = &dbc->lock_dbt;
 		couple[0].mode = mode;
-		if (action == LCK_COUPLE_ALWAYS)
-			action = LCK_COUPLE;
 		UMRW_SET(couple[0].timeout);
 		if (has_timeout)
-			couple[0].timeout = txn->lock_timeout;
+			couple[0].timeout =
+			     F_ISSET(dbc, DBC_RECOVER) ? 0 : txn->lock_timeout;
 		if (action == LCK_COUPLE) {
 			couple[1].op = DB_LOCK_PUT;
 			couple[1].lock = *lockp;
 		}
 
-		ret = dbenv->lock_vec(dbenv, dbc->locker,
+		ret = __lock_vec(dbenv, dbc->locker,
 		    lkflags, couple, action == LCK_COUPLE ? 2 : 1, &reqp);
 		if (ret == 0 || reqp == &couple[1])
 			*lockp = couple[0].lock;
 		break;
-	case LCK_DOWNGRADE:
-		if ((ret = dbenv->lock_downgrade(
-		    dbenv, lockp, DB_LOCK_WWRITE, 0)) != 0)
-			return (ret);
-		/* FALL THROUGH */
-	default:
-		if (has_timeout)
-			goto lck_couple;
-		ret = dbenv->lock_get(dbenv,
-		    dbc->locker, lkflags, &dbc->lock_dbt, mode, lockp);
-		break;
 	}
 
-	return (ret);
+	if (txn != NULL && ret == DB_LOCK_DEADLOCK)
+		F_SET(txn, TXN_DEADLOCK);
+	return ((ret == DB_LOCK_NOTGRANTED &&
+	     !F_ISSET(dbenv, DB_ENV_TIME_NOTGRANTED)) ? DB_LOCK_DEADLOCK : ret);
 }
 
 /*
@@ -432,13 +511,28 @@ __db_lput(dbc, lockp)
 	DB_LOCK *lockp;
 {
 	DB_ENV *dbenv;
-	int ret;
+	int action, ret;
 
-	dbenv = dbc->dbp->dbenv;
+	/*
+	 * Transactional locking.
+	 * Hold on to the read locks only if we are in full isolation.
+	 * Downgrade write locks if we are supporting dirty readers.
+	 */
+	if (F_ISSET(dbc->dbp, DB_AM_DIRTY) && lockp->mode == DB_LOCK_WRITE)
+		action = LCK_DOWNGRADE;
+	else if (dbc->txn == NULL)
+		action = LCK_COUPLE;
+	else if (F_ISSET(dbc, DBC_DEGREE_2) && lockp->mode == DB_LOCK_READ)
+		action = LCK_COUPLE;
+	else if (F_ISSET(dbc, DBC_DIRTY_READ) && lockp->mode == DB_LOCK_DIRTY)
+		action = LCK_COUPLE;
+	else
+		action = 0;
 
-	switch (DB_PUT_ACTION(dbc, LCK_COUPLE, lockp)) {
+	dbenv = dbc->dbp->dbenv;
+	switch (action) {
 	case LCK_COUPLE:
-		ret = dbenv->lock_put(dbenv, lockp);
+		ret = __lock_put(dbenv, lockp, 0);
 		break;
 	case LCK_DOWNGRADE:
 		ret = __lock_downgrade(dbenv, lockp, DB_LOCK_WWRITE, 0);
diff --git a/storage/bdb/db/db_method.c b/storage/bdb/db/db_method.c
index 14712180df0b85f309eadab707f0cadb6cd2737b..4266fbf0e1ea395df565842d71dcbeee8cc79663 100644
--- a/storage/bdb/db/db_method.c
+++ b/storage/bdb/db/db_method.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_method.c,v 11.116 2004/10/11 18:22:05 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_method.c,v 11.78 2002/07/02 19:26:55 sue Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -21,44 +19,55 @@ static const char revid[] = "$Id: db_method.c,v 11.78 2002/07/02 19:26:55 sue Ex
 #include <string.h>
 #endif
 
+#ifdef HAVE_RPC
+#include "db_server.h"
+#endif
+
 #include "db_int.h"
 #include "dbinc/crypto.h"
 #include "dbinc/db_page.h"
 #include "dbinc/db_shash.h"
 #include "dbinc/btree.h"
 #include "dbinc/hash.h"
+#include "dbinc/lock.h"
+#include "dbinc/mp.h"
 #include "dbinc/qam.h"
 #include "dbinc/xa.h"
 #include "dbinc_auto/xa_ext.h"
-#include "dbinc/db_shash.h"
-#include "dbinc/lock.h"
 
 #ifdef HAVE_RPC
-#include "dbinc_auto/db_server.h"
 #include "dbinc_auto/rpc_client_ext.h"
 #endif
 
 static int  __db_get_byteswapped __P((DB *, int *));
+static int  __db_get_dbname __P((DB *, const char **, const char **));
+static DB_ENV *__db_get_env __P((DB *));
+static int  __db_get_transactional __P((DB *));
 static int  __db_get_type __P((DB *, DBTYPE *dbtype));
 static int  __db_init __P((DB *, u_int32_t));
-static int  __db_key_range
-		__P((DB *, DB_TXN *, DBT *, DB_KEY_RANGE *, u_int32_t));
 static int  __db_set_alloc __P((DB *, void *(*)(size_t),
 		void *(*)(void *, size_t), void (*)(void *)));
 static int  __db_set_append_recno __P((DB *, int (*)(DB *, DBT *, db_recno_t)));
+static int  __db_get_cachesize __P((DB *, u_int32_t *, u_int32_t *, int *));
 static int  __db_set_cachesize __P((DB *, u_int32_t, u_int32_t, int));
-static int  __db_set_cache_priority __P((DB *, DB_CACHE_PRIORITY));
 static int  __db_set_dup_compare
 		__P((DB *, int (*)(DB *, const DBT *, const DBT *)));
+static int  __db_get_encrypt_flags __P((DB *, u_int32_t *));
 static int  __db_set_encrypt __P((DB *, const char *, u_int32_t));
 static int  __db_set_feedback __P((DB *, void (*)(DB *, int, int)));
-static int  __db_set_flags __P((DB *, u_int32_t));
-static int  __db_set_pagesize __P((DB *, u_int32_t));
+static void __db_map_flags __P((DB *, u_int32_t *, u_int32_t *));
+static int  __db_get_pagesize __P((DB *, u_int32_t *));
 static int  __db_set_paniccall __P((DB *, void (*)(DB_ENV *, int)));
-static void __db_set_errcall __P((DB *, void (*)(const char *, char *)));
+static void __db_set_errcall
+	      __P((DB *, void (*)(const DB_ENV *, const char *, const char *)));
+static void __db_get_errfile __P((DB *, FILE **));
 static void __db_set_errfile __P((DB *, FILE *));
+static void __db_get_errpfx __P((DB *, const char **));
 static void __db_set_errpfx __P((DB *, const char *));
-static int  __db_stat_fail __P((DB *, void *, u_int32_t));
+static void __db_set_msgcall
+	      __P((DB *, void (*)(const DB_ENV *, const char *)));
+static void __db_get_msgfile __P((DB *, FILE **));
+static void __db_set_msgfile __P((DB *, FILE *));
 static void __dbh_err __P((DB *, int, const char *, ...));
 static void __dbh_errx __P((DB *, const char *, ...));
 
@@ -85,6 +94,8 @@ db_create(dbpp, dbenv, flags)
 	switch (flags) {
 	case 0:
 		break;
+	case DB_REP_CREATE:
+		break;
 	case DB_XA_CREATE:
 		if (dbenv != NULL) {
 			__db_err(dbenv,
@@ -113,25 +124,47 @@ db_create(dbpp, dbenv, flags)
 	else
 #endif
 		ret = __db_init(dbp, flags);
-	if (ret != 0) {
-		__os_free(dbenv, dbp);
-		return (ret);
-	}
+	if (ret != 0)
+		goto err;
 
 	/* If we don't have an environment yet, allocate a local one. */
 	if (dbenv == NULL) {
-		if ((ret = db_env_create(&dbenv, 0)) != 0) {
-			__os_free(dbenv, dbp);
-			return (ret);
-		}
+		if ((ret = db_env_create(&dbenv, 0)) != 0)
+			goto err;
 		F_SET(dbenv, DB_ENV_DBLOCAL);
 	}
+	dbp->dbenv = dbenv;
+	MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
 	++dbenv->db_ref;
+	MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
 
-	dbp->dbenv = dbenv;
+	/*
+	 * Set the replication timestamp; it's 0 if we're not in a replicated
+	 * environment.
+	 */
+	dbp->timestamp =
+	    (F_ISSET(dbenv, DB_ENV_DBLOCAL) || !REP_ON(dbenv)) ? 0 :
+	    ((REGENV *)((REGINFO *)dbenv->reginfo)->primary)->rep_timestamp;
+
+	/* If not RPC, open a backing DB_MPOOLFILE handle in the memory pool. */
+#ifdef HAVE_RPC
+	if (!RPC_ON(dbenv))
+#endif
+		if ((ret = __memp_fcreate(dbenv, &dbp->mpf)) != 0)
+			goto err;
+
+	dbp->type = DB_UNKNOWN;
 
 	*dbpp = dbp;
 	return (0);
+
+err:	if (dbp->mpf != NULL)
+		(void)__memp_fclose(dbp->mpf, 0);
+	if (dbenv != NULL && F_ISSET(dbenv, DB_ENV_DBLOCAL))
+		(void)__dbenv_close(dbenv, 0);
+	__os_free(dbenv, dbp);
+	*dbpp = NULL;
+	return (ret);
 }
 
 /*
@@ -156,42 +189,57 @@ __db_init(dbp, flags)
 	FLD_SET(dbp->am_ok,
 	    DB_OK_BTREE | DB_OK_HASH | DB_OK_QUEUE | DB_OK_RECNO);
 
-	dbp->associate = __db_associate;
-	dbp->close = __db_close;
-	dbp->cursor = __db_cursor;
-	dbp->del = __db_delete;
+	dbp->associate = __db_associate_pp;
+	dbp->close = __db_close_pp;
+	dbp->cursor = __db_cursor_pp;
+	dbp->del = __db_del_pp;
+	dbp->dump = __db_dump_pp;
 	dbp->err = __dbh_err;
 	dbp->errx = __dbh_errx;
-	dbp->fd = __db_fd;
-	dbp->get = __db_get;
+	dbp->fd = __db_fd_pp;
+	dbp->get = __db_get_pp;
 	dbp->get_byteswapped = __db_get_byteswapped;
+	dbp->get_dbname = __db_get_dbname;
+	dbp->get_env = __db_get_env;
+	dbp->get_open_flags = __db_get_open_flags;
+	dbp->get_transactional = __db_get_transactional;
 	dbp->get_type = __db_get_type;
-	dbp->join = __db_join;
-	dbp->key_range = __db_key_range;
-	dbp->open = __db_open;
-	dbp->pget = __db_pget;
-	dbp->put = __db_put;
-	dbp->remove = __db_remove;
-	dbp->rename = __db_rename;
-	dbp->truncate = __db_truncate;
+	dbp->join = __db_join_pp;
+	dbp->key_range = __db_key_range_pp;
+	dbp->open = __db_open_pp;
+	dbp->pget = __db_pget_pp;
+	dbp->put = __db_put_pp;
+	dbp->remove = __db_remove_pp;
+	dbp->rename = __db_rename_pp;
+	dbp->truncate = __db_truncate_pp;
 	dbp->set_alloc = __db_set_alloc;
 	dbp->set_append_recno = __db_set_append_recno;
+	dbp->get_cachesize = __db_get_cachesize;
 	dbp->set_cachesize = __db_set_cachesize;
-	dbp->set_cache_priority = __db_set_cache_priority;
 	dbp->set_dup_compare = __db_set_dup_compare;
+	dbp->get_encrypt_flags = __db_get_encrypt_flags;
 	dbp->set_encrypt = __db_set_encrypt;
 	dbp->set_errcall = __db_set_errcall;
+	dbp->get_errfile = __db_get_errfile;
 	dbp->set_errfile = __db_set_errfile;
+	dbp->get_errpfx = __db_get_errpfx;
 	dbp->set_errpfx = __db_set_errpfx;
 	dbp->set_feedback = __db_set_feedback;
+	dbp->get_flags = __db_get_flags;
 	dbp->set_flags = __db_set_flags;
+	dbp->get_lorder = __db_get_lorder;
 	dbp->set_lorder = __db_set_lorder;
+	dbp->set_msgcall = __db_set_msgcall;
+	dbp->get_msgfile = __db_get_msgfile;
+	dbp->set_msgfile = __db_set_msgfile;
+	dbp->get_pagesize = __db_get_pagesize;
 	dbp->set_pagesize = __db_set_pagesize;
 	dbp->set_paniccall = __db_set_paniccall;
-	dbp->stat = __db_stat_fail;
-	dbp->sync = __db_sync;
-	dbp->upgrade = __db_upgrade;
-	dbp->verify = __db_verify;
+	dbp->stat = __db_stat_pp;
+	dbp->stat_print = __db_stat_print_pp;
+	dbp->sync = __db_sync_pp;
+	dbp->upgrade = __db_upgrade_pp;
+	dbp->verify = __db_verify_pp;
 
 					/* Access method specific. */
 	if ((ret = __bam_db_create(dbp)) != 0)
@@ -208,6 +256,9 @@ __db_init(dbp, flags)
 	if (LF_ISSET(DB_XA_CREATE) && (ret = __db_xa_create(dbp)) != 0)
 		return (ret);
 
+	if (LF_ISSET(DB_REP_CREATE))
+		F_SET(dbp, DB_AM_REPLICATION);
+
 	return (0);
 }
 
@@ -245,7 +296,7 @@ __dbh_am_chk(dbp, flags)
  *	Error message, including the standard error string.
  */
 static void
-#ifdef __STDC__
+#ifdef STDC_HEADERS
 __dbh_err(DB *dbp, int error, const char *fmt, ...)
 #else
 __dbh_err(dbp, error, fmt, va_alist)
@@ -263,7 +314,7 @@ __dbh_err(dbp, error, fmt, va_alist)
  *	Error message.
  */
 static void
-#ifdef __STDC__
+#ifdef STDC_HEADERS
 __dbh_errx(DB *dbp, const char *fmt, ...)
 #else
 __dbh_errx(dbp, fmt, va_alist)
@@ -284,48 +335,65 @@ __db_get_byteswapped(dbp, isswapped)
 	DB *dbp;
 	int *isswapped;
 {
-	DB_ILLEGAL_BEFORE_OPEN(dbp, "get_byteswapped");
+	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->get_byteswapped");
 
 	*isswapped = F_ISSET(dbp, DB_AM_SWAP) ? 1 : 0;
 	return (0);
 }
 
 /*
- * __db_get_type --
- *	Return type of underlying database.
+ * __db_get_dbname --
+ *	Get the name of the database as passed to DB->open.
  */
 static int
-__db_get_type(dbp, dbtype)
+__db_get_dbname(dbp, fnamep, dnamep)
 	DB *dbp;
-	DBTYPE *dbtype;
+	const char **fnamep, **dnamep;
 {
-	DB_ILLEGAL_BEFORE_OPEN(dbp, "get_type");
+	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->get_dbname");
 
-	*dbtype = dbp->type;
+	if (fnamep != NULL)
+		*fnamep = dbp->fname;
+	if (dnamep != NULL)
+		*dnamep = dbp->dname;
 	return (0);
 }
 
 /*
- * __db_key_range --
- *	Return proportion of keys above and below given key.
+ * __db_get_env --
+ *	Get the DB_ENV handle that was passed to db_create.
+ */
+static DB_ENV *
+__db_get_env(dbp)
+	DB *dbp;
+{
+	return (dbp->dbenv);
+}
+
+/*
+ * get_transactional --
+ *	Get whether this database was created in a transaction.
  */
 static int
-__db_key_range(dbp, txn, key, kr, flags)
+__db_get_transactional(dbp)
 	DB *dbp;
-	DB_TXN *txn;
-	DBT *key;
-	DB_KEY_RANGE *kr;
-	u_int32_t flags;
 {
-	COMPQUIET(txn, NULL);
-	COMPQUIET(key, NULL);
-	COMPQUIET(kr, NULL);
-	COMPQUIET(flags, 0);
+	return (F_ISSET(dbp, DB_AM_TXN) ? 1 : 0);
+}
 
-	DB_ILLEGAL_BEFORE_OPEN(dbp, "key_range");
-	DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
+/*
+ * __db_get_type --
+ *	Return type of underlying database.
+ */
+static int
+__db_get_type(dbp, dbtype)
+	DB *dbp;
+	DBTYPE *dbtype;
+{
+	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->get_type");
 
-	return (EINVAL);
+	*dbtype = dbp->type;
+	return (0);
 }
 
 /*
@@ -337,7 +405,7 @@ __db_set_append_recno(dbp, func)
 	DB *dbp;
 	int (*func) __P((DB *, DBT *, db_recno_t));
 {
-	DB_ILLEGAL_AFTER_OPEN(dbp, "set_append_recno");
+	DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_append_recno");
 	DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO);
 
 	dbp->db_append_recno = func;
@@ -346,40 +414,36 @@ __db_set_append_recno(dbp, func)
 }
 
 /*
- * __db_set_cachesize --
- *	Set underlying cache size.
+ * __db_get_cachesize --
+ *	Get underlying cache size.
  */
 static int
-__db_set_cachesize(dbp, cache_gbytes, cache_bytes, ncache)
+__db_get_cachesize(dbp, cache_gbytesp, cache_bytesp, ncachep)
 	DB *dbp;
-	u_int32_t cache_gbytes, cache_bytes;
-	int ncache;
+	u_int32_t *cache_gbytesp, *cache_bytesp;
+	int *ncachep;
 {
-	DB_ILLEGAL_IN_ENV(dbp, "set_cachesize");
-	DB_ILLEGAL_AFTER_OPEN(dbp, "set_cachesize");
+	DB_ILLEGAL_IN_ENV(dbp, "DB->get_cachesize");
 
-	return (dbp->dbenv->set_cachesize(
-	    dbp->dbenv, cache_gbytes, cache_bytes, ncache));
+	return (__memp_get_cachesize(dbp->dbenv,
+	    cache_gbytesp, cache_bytesp, ncachep));
 }
 
 /*
- * __db_set_cache_priority --
- *	Set cache priority for pages from this file.
+ * __db_set_cachesize --
+ *	Set underlying cache size.
  */
 static int
-__db_set_cache_priority(dbp, priority)
+__db_set_cachesize(dbp, cache_gbytes, cache_bytes, ncache)
 	DB *dbp;
-	DB_CACHE_PRIORITY priority;
+	u_int32_t cache_gbytes, cache_bytes;
+	int ncache;
 {
-	/*
-	 * If an underlying DB_MPOOLFILE exists, call it.  Otherwise, save
-	 * the information away until DB->open is called.
-	 */
-	if (dbp->mpf == NULL) {
-		dbp->priority = priority;
-		return (0);
-	}
-	return (dbp->mpf->set_priority(dbp->mpf, priority));
+	DB_ILLEGAL_IN_ENV(dbp, "DB->set_cachesize");
+	DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_cachesize");
+
+	return (__memp_set_cachesize(
+	    dbp->dbenv, cache_gbytes, cache_bytes, ncache));
 }
 
 /*
@@ -393,10 +457,10 @@ __db_set_dup_compare(dbp, func)
 {
 	int ret;
 
-	DB_ILLEGAL_AFTER_OPEN(dbp, "dup_compare");
+	DB_ILLEGAL_AFTER_OPEN(dbp, "DB->dup_compare");
 	DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE | DB_OK_HASH);
 
-	if ((ret = dbp->set_flags(dbp, DB_DUPSORT)) != 0)
+	if ((ret = __db_set_flags(dbp, DB_DUPSORT)) != 0)
 		return (ret);
 
 	dbp->dup_compare = func;
@@ -404,6 +468,19 @@ __db_set_dup_compare(dbp, func)
 	return (0);
 }
 
+/*
+ * __db_get_encrypt_flags --
+ */
+static int
+__db_get_encrypt_flags(dbp, flagsp)
+	DB *dbp;
+	u_int32_t *flagsp;
+{
+	DB_ILLEGAL_IN_ENV(dbp, "DB->get_encrypt_flags");
+
+	return (__dbenv_get_encrypt_flags(dbp->dbenv, flagsp));
+}
+
 /*
  * __db_set_encrypt --
  *	Set database passwd.
@@ -417,10 +494,10 @@ __db_set_encrypt(dbp, passwd, flags)
 	DB_CIPHER *db_cipher;
 	int ret;
 
-	DB_ILLEGAL_IN_ENV(dbp, "set_encrypt");
-	DB_ILLEGAL_AFTER_OPEN(dbp, "set_encrypt");
+	DB_ILLEGAL_IN_ENV(dbp, "DB->set_encrypt");
+	DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_encrypt");
 
-	if ((ret = dbp->dbenv->set_encrypt(dbp->dbenv, passwd, flags)) != 0)
+	if ((ret = __dbenv_set_encrypt(dbp->dbenv, passwd, flags)) != 0)
 		return (ret);
 
 	/*
@@ -432,15 +509,23 @@ __db_set_encrypt(dbp, passwd, flags)
 	    (ret = db_cipher->init(dbp->dbenv, db_cipher)) != 0)
 		return (ret);
 
-	return (dbp->set_flags(dbp, DB_ENCRYPT));
+	return (__db_set_flags(dbp, DB_ENCRYPT));
 }
 
 static void
 __db_set_errcall(dbp, errcall)
 	DB *dbp;
-	void (*errcall) __P((const char *, char *));
+	void (*errcall) __P((const DB_ENV *, const char *, const char *));
 {
-	dbp->dbenv->set_errcall(dbp->dbenv, errcall);
+	__dbenv_set_errcall(dbp->dbenv, errcall);
+}
+
+static void
+__db_get_errfile(dbp, errfilep)
+	DB *dbp;
+	FILE **errfilep;
+{
+	__dbenv_get_errfile(dbp->dbenv, errfilep);
 }
 
 static void
@@ -448,7 +533,15 @@ __db_set_errfile(dbp, errfile)
 	DB *dbp;
 	FILE *errfile;
 {
-	dbp->dbenv->set_errfile(dbp->dbenv, errfile);
+	__dbenv_set_errfile(dbp->dbenv, errfile);
+}
+
+static void
+__db_get_errpfx(dbp, errpfxp)
+	DB *dbp;
+	const char **errpfxp;
+{
+	__dbenv_get_errpfx(dbp->dbenv, errpfxp);
 }
 
 static void
@@ -456,7 +549,7 @@ __db_set_errpfx(dbp, errpfx)
 	DB *dbp;
 	const char *errpfx;
 {
-	dbp->dbenv->set_errpfx(dbp->dbenv, errpfx);
+	__dbenv_set_errpfx(dbp->dbenv, errpfx);
 }
 
 static int
@@ -468,42 +561,143 @@ __db_set_feedback(dbp, feedback)
 	return (0);
 }
 
-static int
+/*
+ * __db_map_flags --
+ *	Maps between public and internal flag values.
+ *      This function doesn't check for validity, so it can't fail.
+ */
+static void
+__db_map_flags(dbp, inflagsp, outflagsp)
+	DB *dbp;
+	u_int32_t *inflagsp, *outflagsp;
+{
+	COMPQUIET(dbp, NULL);
+
+	if (FLD_ISSET(*inflagsp, DB_CHKSUM)) {
+		FLD_SET(*outflagsp, DB_AM_CHKSUM);
+		FLD_CLR(*inflagsp, DB_CHKSUM);
+	}
+	if (FLD_ISSET(*inflagsp, DB_ENCRYPT)) {
+		FLD_SET(*outflagsp, DB_AM_ENCRYPT | DB_AM_CHKSUM);
+		FLD_CLR(*inflagsp, DB_ENCRYPT);
+	}
+	if (FLD_ISSET(*inflagsp, DB_TXN_NOT_DURABLE)) {
+		FLD_SET(*outflagsp, DB_AM_NOT_DURABLE);
+		FLD_CLR(*inflagsp, DB_TXN_NOT_DURABLE);
+	}
+}
+
+/*
+ * __db_get_flags --
+ *	The DB->get_flags method.
+ *
+ * PUBLIC: int __db_get_flags __P((DB *, u_int32_t *));
+ */
+int
+__db_get_flags(dbp, flagsp)
+	DB *dbp;
+	u_int32_t *flagsp;
+{
+	static const u_int32_t db_flags[] = {
+		DB_CHKSUM,
+		DB_DUP,
+		DB_DUPSORT,
+		DB_ENCRYPT,
+		DB_INORDER,
+		DB_RECNUM,
+		DB_RENUMBER,
+		DB_REVSPLITOFF,
+		DB_SNAPSHOT,
+		DB_TXN_NOT_DURABLE,
+		0
+	};
+	u_int32_t f, flags, mapped_flag;
+	int i;
+
+	flags = 0;
+	for (i = 0; (f = db_flags[i]) != 0; i++) {
+		mapped_flag = 0;
+		__db_map_flags(dbp, &f, &mapped_flag);
+		__bam_map_flags(dbp, &f, &mapped_flag);
+		__ram_map_flags(dbp, &f, &mapped_flag);
+#ifdef HAVE_QUEUE
+		__qam_map_flags(dbp, &f, &mapped_flag);
+#endif
+		DB_ASSERT(f == 0);
+		if (F_ISSET(dbp, mapped_flag) == mapped_flag)
+			LF_SET(db_flags[i]);
+	}
+
+	*flagsp = flags;
+	return (0);
+}
+
+/*
+ * __db_set_flags --
+ *	DB->set_flags.
+ *
+ * PUBLIC: int  __db_set_flags __P((DB *, u_int32_t));
+ */
+int
 __db_set_flags(dbp, flags)
 	DB *dbp;
 	u_int32_t flags;
 {
+	DB_ENV *dbenv;
 	int ret;
 
-	/*
-	 * !!!
-	 * The hash access method only takes two flags: DB_DUP and DB_DUPSORT.
-	 * The Btree access method uses them for the same purposes, and so we
-	 * resolve them there.
-	 *
-	 * The queue access method takes no flags.
-	 */
-	if (LF_ISSET(DB_ENCRYPT)) {
-		if (!CRYPTO_ON(dbp->dbenv)) {
-			__db_err(dbp->dbenv,
+	dbenv = dbp->dbenv;
+
+	if (LF_ISSET(DB_ENCRYPT) && !CRYPTO_ON(dbenv)) {
+		__db_err(dbenv,
 		    "Database environment not configured for encryption");
-			return (EINVAL);
-		}
-		F_SET(dbp, DB_AM_ENCRYPT);
-		F_SET(dbp, DB_AM_CHKSUM);
-		LF_CLR(DB_ENCRYPT);
-	}
-	if (LF_ISSET(DB_CHKSUM_SHA1)) {
-		F_SET(dbp, DB_AM_CHKSUM);
-		LF_CLR(DB_CHKSUM_SHA1);
+		return (EINVAL);
 	}
+	if (LF_ISSET(DB_TXN_NOT_DURABLE))
+		ENV_REQUIRES_CONFIG(dbenv,
+		    dbenv->tx_handle, "DB_NOT_DURABLE", DB_INIT_TXN);
+
+	__db_map_flags(dbp, &flags, &dbp->flags);
 
 	if ((ret = __bam_set_flags(dbp, &flags)) != 0)
 		return (ret);
 	if ((ret = __ram_set_flags(dbp, &flags)) != 0)
 		return (ret);
+#ifdef HAVE_QUEUE
+	if ((ret = __qam_set_flags(dbp, &flags)) != 0)
+		return (ret);
+#endif
+
+	return (flags == 0 ? 0 : __db_ferr(dbenv, "DB->set_flags", 0));
+}
+
+/*
+ * __db_get_lorder --
+ *	Get whether lorder is swapped or not.
+ *
+ * PUBLIC: int  __db_get_lorder __P((DB *, int *));
+ */
+int
+__db_get_lorder(dbp, db_lorderp)
+	DB *dbp;
+	int *db_lorderp;
+{
+	int ret;
+
+	/* Flag if the specified byte order requires swapping. */
+	switch (ret = __db_byteorder(dbp->dbenv, 1234)) {
+	case 0:
+		*db_lorderp = F_ISSET(dbp, DB_AM_SWAP) ? 4321 : 1234;
+		break;
+	case DB_SWAPBYTES:
+		*db_lorderp = F_ISSET(dbp, DB_AM_SWAP) ? 1234 : 4321;
+		break;
+	default:
+		return (ret);
+		/* NOTREACHED */
+	}
 
-	return (flags == 0 ? 0 : __db_ferr(dbp->dbenv, "DB->set_flags", 0));
+	return (0);
 }
 
 /*
@@ -519,7 +713,7 @@ __db_set_lorder(dbp, db_lorder)
 {
 	int ret;
 
-	DB_ILLEGAL_AFTER_OPEN(dbp, "set_lorder");
+	DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_lorder");
 
 	/* Flag if the specified byte order requires swapping. */
 	switch (ret = __db_byteorder(dbp->dbenv, db_lorder)) {
@@ -543,19 +737,57 @@ __db_set_alloc(dbp, mal_func, real_func, free_func)
 	void *(*real_func) __P((void *, size_t));
 	void (*free_func) __P((void *));
 {
-	DB_ILLEGAL_IN_ENV(dbp, "set_alloc");
-	DB_ILLEGAL_AFTER_OPEN(dbp, "set_alloc");
+	DB_ILLEGAL_IN_ENV(dbp, "DB->set_alloc");
+	DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_alloc");
+
+	return (__dbenv_set_alloc(dbp->dbenv, mal_func, real_func, free_func));
+}
+
+static void
+__db_set_msgcall(dbp, msgcall)
+	DB *dbp;
+	void (*msgcall) __P((const DB_ENV *, const char *));
+{
+	__dbenv_set_msgcall(dbp->dbenv, msgcall);
+}
 
-	return (dbp->dbenv->set_alloc(dbp->dbenv,
-	    mal_func, real_func, free_func));
+static void
+__db_get_msgfile(dbp, msgfilep)
+	DB *dbp;
+	FILE **msgfilep;
+{
+	__dbenv_get_msgfile(dbp->dbenv, msgfilep);
+}
+
+static void
+__db_set_msgfile(dbp, msgfile)
+	DB *dbp;
+	FILE *msgfile;
+{
+	__dbenv_set_msgfile(dbp->dbenv, msgfile);
 }
 
 static int
+__db_get_pagesize(dbp, db_pagesizep)
+	DB *dbp;
+	u_int32_t *db_pagesizep;
+{
+	*db_pagesizep = dbp->pgsize;
+	return (0);
+}
+
+/*
+ * __db_set_pagesize --
+ *	DB->set_pagesize
+ *
+ * PUBLIC: int  __db_set_pagesize __P((DB *, u_int32_t));
+ */
+int
 __db_set_pagesize(dbp, db_pagesize)
 	DB *dbp;
 	u_int32_t db_pagesize;
 {
-	DB_ILLEGAL_AFTER_OPEN(dbp, "set_pagesize");
+	DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_pagesize");
 
 	if (db_pagesize < DB_MIN_PGSIZE) {
 		__db_err(dbp->dbenv, "page sizes may not be smaller than %lu",
@@ -592,27 +824,7 @@ __db_set_paniccall(dbp, paniccall)
 	DB *dbp;
 	void (*paniccall) __P((DB_ENV *, int));
 {
-	return (dbp->dbenv->set_paniccall(dbp->dbenv, paniccall));
-}
-
-static int
-__db_stat_fail(dbp, sp, flags)
-	DB *dbp;
-	void *sp;
-	u_int32_t flags;
-{
-	COMPQUIET(sp, NULL);
-	COMPQUIET(flags, 0);
-
-	/*
-	 * DB->stat isn't initialized until the actual DB->open call,
-	 * but we don't want to core dump.
-	 */
-	PANIC_CHECK(dbp->dbenv);
-	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->stat");
-
-	/* NOTREACHED */
-	return (EINVAL);
+	return (__dbenv_set_paniccall(dbp->dbenv, paniccall));
 }
 
 #ifdef HAVE_RPC
@@ -642,9 +854,12 @@ __dbcl_init(dbp, dbenv, flags)
 	dbp->fd = __dbcl_db_fd;
 	dbp->get = __dbcl_db_get;
 	dbp->get_byteswapped = __db_get_byteswapped;
+	dbp->get_transactional = __db_get_transactional;
 	dbp->get_type = __db_get_type;
 	dbp->join = __dbcl_db_join;
 	dbp->key_range = __dbcl_db_key_range;
+	dbp->get_dbname = __dbcl_db_get_name;
+	dbp->get_open_flags = __dbcl_db_get_open_flags;
 	dbp->open = __dbcl_db_open_wrap;
 	dbp->pget = __dbcl_db_pget;
 	dbp->put = __dbcl_db_put;
@@ -652,16 +867,22 @@ __dbcl_init(dbp, dbenv, flags)
 	dbp->rename = __dbcl_db_rename;
 	dbp->set_alloc = __dbcl_db_alloc;
 	dbp->set_append_recno = __dbcl_db_set_append_recno;
+	dbp->get_cachesize = __dbcl_db_get_cachesize;
 	dbp->set_cachesize = __dbcl_db_cachesize;
-	dbp->set_cache_priority = __dbcl_db_cache_priority;
 	dbp->set_dup_compare = __dbcl_db_dup_compare;
+	dbp->get_encrypt_flags = __dbcl_db_get_encrypt_flags;
 	dbp->set_encrypt = __dbcl_db_encrypt;
 	dbp->set_errcall = __db_set_errcall;
+	dbp->get_errfile = __db_get_errfile;
 	dbp->set_errfile = __db_set_errfile;
+	dbp->get_errpfx = __db_get_errpfx;
 	dbp->set_errpfx = __db_set_errpfx;
 	dbp->set_feedback = __dbcl_db_feedback;
+	dbp->get_flags = __dbcl_db_get_flags;
 	dbp->set_flags = __dbcl_db_flags;
+	dbp->get_lorder = __dbcl_db_get_lorder;
 	dbp->set_lorder = __dbcl_db_lorder;
+	dbp->get_pagesize = __dbcl_db_get_pagesize;
 	dbp->set_pagesize = __dbcl_db_pagesize;
 	dbp->set_paniccall = __dbcl_db_panic;
 	dbp->stat = __dbcl_db_stat;
@@ -675,15 +896,23 @@ __dbcl_init(dbp, dbenv, flags)
 	 */
 	dbp->set_bt_compare = __dbcl_db_bt_compare;
 	dbp->set_bt_maxkey = __dbcl_db_bt_maxkey;
+	dbp->get_bt_minkey = __dbcl_db_get_bt_minkey;
 	dbp->set_bt_minkey = __dbcl_db_bt_minkey;
 	dbp->set_bt_prefix = __dbcl_db_bt_prefix;
+	dbp->get_h_ffactor = __dbcl_db_get_h_ffactor;
 	dbp->set_h_ffactor = __dbcl_db_h_ffactor;
 	dbp->set_h_hash = __dbcl_db_h_hash;
+	dbp->get_h_nelem = __dbcl_db_get_h_nelem;
 	dbp->set_h_nelem = __dbcl_db_h_nelem;
+	dbp->get_q_extentsize = __dbcl_db_get_extentsize;
 	dbp->set_q_extentsize = __dbcl_db_extentsize;
+	dbp->get_re_delim = __dbcl_db_get_re_delim;
 	dbp->set_re_delim = __dbcl_db_re_delim;
+	dbp->get_re_len = __dbcl_db_get_re_len;
 	dbp->set_re_len = __dbcl_db_re_len;
+	dbp->get_re_pad = __dbcl_db_get_re_pad;
 	dbp->set_re_pad = __dbcl_db_re_pad;
+	dbp->get_re_source = __dbcl_db_get_re_source;
 	dbp->set_re_source = __dbcl_db_re_source;
 
 	return (__dbcl_db_create(dbp, dbenv, flags));
diff --git a/storage/bdb/db/db_open.c b/storage/bdb/db/db_open.c
index 8352525361f8a4986f101df22f3d8dba9e2673f5..35e1150910db386f758bd1730e04a0558a85201c 100644
--- a/storage/bdb/db/db_open.c
+++ b/storage/bdb/db/db_open.c
@@ -1,20 +1,17 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_open.c,v 11.240 2004/09/22 20:53:19 margo Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_open.c,v 11.215 2002/08/15 15:27:52 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
-#include <stddef.h>
 #include <stdlib.h>
 #include <string.h>
 #endif
@@ -30,50 +27,49 @@ static const char revid[] = "$Id: db_open.c,v 11.215 2002/08/15 15:27:52 bostic
 #include "dbinc/hash.h"
 #include "dbinc/lock.h"
 #include "dbinc/log.h"
+#include "dbinc/mp.h"
 #include "dbinc/qam.h"
 #include "dbinc/txn.h"
 
-static int __db_openchk __P((DB *,
-    DB_TXN *, const char *, const char *, DBTYPE, u_int32_t));
-
 /*
  * __db_open --
- *	Main library interface to the DB access methods.
+ *	DB->open method.
+ *
+ * This routine gets called in three different ways:
+ *
+ * 1. It can be called to open a file/database.  In this case, subdb will
+ *    be NULL and meta_pgno will be PGNO_BASE_MD.
+ * 2. It can be called to open a subdatabase during normal operation.  In
+ *    this case, name and subname will both be non-NULL and meta_pgno will
+ *    be PGNO_BASE_MD (also PGNO_INVALID).
+ * 3. It can be called during recovery to open a file/database, in which case
+ *    name will be non-NULL, subname will be NULL, and meta-pgno will be
+ *    PGNO_BASE_MD.
+ * 4. It can be called during recovery to open a subdatabase, in which case
+ *    name will be non-NULL, subname may be NULL and meta-pgno will be
+ *    a valid pgno (i.e., not PGNO_BASE_MD).
  *
  * PUBLIC: int __db_open __P((DB *, DB_TXN *,
- * PUBLIC:     const char *, const char *, DBTYPE, u_int32_t, int));
+ * PUBLIC:     const char *, const char *, DBTYPE, u_int32_t, int, db_pgno_t));
  */
 int
-__db_open(dbp, txn, name, subdb, type, flags, mode)
+__db_open(dbp, txn, fname, dname, type, flags, mode, meta_pgno)
 	DB *dbp;
 	DB_TXN *txn;
-	const char *name, *subdb;
+	const char *fname, *dname;
 	DBTYPE type;
 	u_int32_t flags;
 	int mode;
+	db_pgno_t meta_pgno;
 {
 	DB_ENV *dbenv;
-	int remove_master, remove_me, ret, t_ret, txn_local;
+	int ret;
+	u_int32_t id;
 
 	dbenv = dbp->dbenv;
-	remove_me = remove_master = txn_local = 0;
-
-	PANIC_CHECK(dbenv);
-
-	if ((ret = __db_openchk(dbp, txn, name, subdb, type, flags)) != 0)
-		return (ret);
+	id = TXN_INVALID;
 
-	/*
-	 * Create local transaction as necessary, check for consistent
-	 * transaction usage.
-	 */
-	if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
-		if ((ret = __db_txn_auto(dbp, &txn)) != 0)
-			return (ret);
-		txn_local = 1;
-	} else
-		if (txn != NULL && !TXN_ON(dbenv))
-			return (__db_not_txn_env(dbenv));
+	DB_TEST_RECOVERY(dbp, DB_TEST_PREOPEN, ret, fname);
 
 	/*
 	 * If the environment was configured with threads, the DB handle
@@ -92,123 +88,21 @@ __db_open(dbp, txn, name, subdb, type, flags, mode)
 	if (LF_ISSET(DB_DIRTY_READ))
 		F_SET(dbp, DB_AM_DIRTY);
 
-	/* Fill in the type. */
-	dbp->type = type;
-
-	/*
-	 * If we're opening a subdatabase, we have to open (and potentially
-	 * create) the main database, and then get (and potentially store)
-	 * our base page number in that database.  Then, we can finally open
-	 * the subdatabase.
-	 */
-	if ((ret = __db_dbopen(
-	    dbp, txn, name, subdb, flags, mode, PGNO_BASE_MD)) != 0)
-		goto err;
-
-	/*
-	 * You can open the database that describes the subdatabases in the
-	 * rest of the file read-only.  The content of each key's data is
-	 * unspecified and applications should never be adding new records
-	 * or updating existing records.  However, during recovery, we need
-	 * to open these databases R/W so we can redo/undo changes in them.
-	 * Likewise, we need to open master databases read/write during
-	 * rename and remove so we can be sure they're fully sync'ed, so
-	 * we provide an override flag for the purpose.
-	 */
-	if (subdb == NULL && !IS_RECOVERING(dbenv) && !LF_ISSET(DB_RDONLY) &&
-	    !LF_ISSET(DB_RDWRMASTER) && F_ISSET(dbp, DB_AM_SUBDB)) {
-		__db_err(dbenv,
-    "files containing multiple databases may only be opened read-only");
-		ret = EINVAL;
-		goto err;
-	}
-
-err:	/* If we were successful, don't discard the file on close. */
-	if (ret == 0)
-		/* If we were successful, don't discard the file on close. */
-		F_CLR(dbp, DB_AM_DISCARD | DB_AM_CREATED | DB_AM_CREATED_MSTR);
-	else {
-		/*
-		 * If we are not transactional, we need to remove the
-		 * databases/subdatabases.  If we are transactional, then
-		 * the abort of the child transaction should take care of
-		 * cleaning them up.
-		 */
-		remove_me = txn == NULL && F_ISSET(dbp, DB_AM_CREATED);
-		remove_master = txn == NULL && F_ISSET(dbp, DB_AM_CREATED_MSTR);
-
-		/*
-		 * If we had an error, it may have happened before or after
-		 * we actually logged the open.  If it happened before, then
-		 * abort won't know anything about it and won't close or
-		 * refresh the dbp, so we need to do it explicitly.
-		 */
-		(void)__db_refresh(dbp, txn, DB_NOSYNC);
-	}
-
-	/* Remove anyone we created. */
-	if (remove_master || (subdb == NULL && remove_me))
-		/* Remove file. */
-		(void)dbenv->dbremove(dbenv, txn, name, NULL, 0);
-	else if (remove_me)
-		/* Remove subdatabase. */
-		(void)dbenv->dbremove(dbenv, txn, name, subdb, 0);
-
-	/* Commit for DB_AUTO_COMMIT. */
-	if (txn_local) {
-		if (ret == 0)
-			ret = txn->commit(txn, 0);
-		else
-			if ((t_ret = txn->abort(txn)) != 0)
-				ret = __db_panic(dbenv, t_ret);
-	}
-
-	return (ret);
-}
-
-/*
- * __db_dbopen --
- *	Open a database.  This routine  gets called in three different ways.
- * 1. It can be called to open a file/database.  In this case, subdb will
- *    be NULL and meta_pgno will be PGNO_BASE_MD.
- * 2. It can be called to open a subdatabase during normal operation.  In
- *    this case, name and subname will both be non-NULL and meta_pgno will
- *    be PGNO_BAS_MD (also PGNO_INVALID).
- * 3. It can be called during recovery to open a subdatabase in which case
- *    name will be non-NULL, subname mqy be NULL and meta-pgno will be
- *    a valid pgno (i.e., not PGNO_BASE_MD).
- *
- * PUBLIC: int __db_dbopen __P((DB *, DB_TXN *,
- * PUBLIC:     const char *, const char *, u_int32_t, int, db_pgno_t));
- */
-int
-__db_dbopen(dbp, txn, name, subdb, flags, mode, meta_pgno)
-	DB *dbp;
-	DB_TXN *txn;
-	const char *name, *subdb;
-	u_int32_t flags;
-	int mode;
-	db_pgno_t meta_pgno;
-{
-	DB_ENV *dbenv;
-	int ret;
-	u_int32_t id;
-
-	dbenv = dbp->dbenv;
-	id = TXN_INVALID;
 	if (txn != NULL)
 		F_SET(dbp, DB_AM_TXN);
 
-	DB_TEST_RECOVERY(dbp, DB_TEST_PREOPEN, ret, name);
+	/* Fill in the type. */
+	dbp->type = type;
+
 	/*
-	 * If name is NULL, it's always a create, so make sure that we
+	 * If fname is NULL, it's always a create, so make sure that we
 	 * have a type specified.  It would be nice if this checking
 	 * were done in __db_open where most of the interface checking
 	 * is done, but this interface (__db_dbopen) is used by the
 	 * recovery and limbo system, so we need to safeguard this
 	 * interface as well.
 	 */
-	if (name == NULL) {
+	if (fname == NULL) {
 		F_SET(dbp, DB_AM_INMEM);
 
 		if (dbp->type == DB_UNKNOWN) {
@@ -235,17 +129,17 @@ __db_dbopen(dbp, txn, name, subdb, flags, mode, meta_pgno)
 		 * Store the locker in the file id structure -- we can get it
 		 * from there as necessary, and it saves having two copies.
 		 */
-		if (LOCKING_ON(dbenv) && (ret = dbenv->lock_id(dbenv,
-		    (u_int32_t *)dbp->fileid)) != 0)
+		if (LOCKING_ON(dbenv) &&
+		    (ret = __lock_id(dbenv, (u_int32_t *)dbp->fileid)) != 0)
 			return (ret);
-	} else if (subdb == NULL && meta_pgno == PGNO_BASE_MD) {
+	} else if (dname == NULL && meta_pgno == PGNO_BASE_MD) {
 		/* Open/create the underlying file.  Acquire locks. */
 		if ((ret =
-		    __fop_file_setup(dbp, txn, name, mode, flags, &id)) != 0)
+		    __fop_file_setup(dbp, txn, fname, mode, flags, &id)) != 0)
 			return (ret);
 	} else {
 		if ((ret = __fop_subdb_setup(dbp,
-		    txn, name, subdb, mode, flags)) != 0)
+		    txn, fname, dname, mode, flags)) != 0)
 			return (ret);
 		meta_pgno = dbp->meta_pgno;
 	}
@@ -261,13 +155,13 @@ __db_dbopen(dbp, txn, name, subdb, flags, mode, meta_pgno)
 	 * opened and updated the master using access method interfaces,
 	 * so we don't want to get rid of any pages that are in the mpool.
 	 * If we created the file when we opened the master, we already hit
-	 * this check in a non-subdb context then.
+	 * this check in a non-subdatabase context then.
 	 */
-	if (subdb == NULL && F_ISSET(dbp, DB_AM_CREATED))
+	if (dname == NULL && F_ISSET(dbp, DB_AM_CREATED))
 		LF_SET(DB_TRUNCATE);
 
 	/* Set up the underlying environment. */
-	if ((ret = __db_dbenv_setup(dbp, txn, name, id, flags)) != 0)
+	if ((ret = __db_dbenv_setup(dbp, txn, fname, id, flags)) != 0)
 		return (ret);
 
 	/*
@@ -283,21 +177,21 @@ __db_dbopen(dbp, txn, name, subdb, flags, mode, meta_pgno)
 	 * For unnamed files, we need to actually create the file now
 	 * that the mpool is open.
 	 */
-	if (name == NULL && (ret = __db_new_file(dbp, txn, NULL, NULL)) != 0)
+	if (fname == NULL && (ret = __db_new_file(dbp, txn, NULL, NULL)) != 0)
 		return (ret);
 
 	switch (dbp->type) {
 	case DB_BTREE:
-		ret = __bam_open(dbp, txn, name, meta_pgno, flags);
+		ret = __bam_open(dbp, txn, fname, meta_pgno, flags);
 		break;
 	case DB_HASH:
-		ret = __ham_open(dbp, txn, name, meta_pgno, flags);
+		ret = __ham_open(dbp, txn, fname, meta_pgno, flags);
 		break;
 	case DB_RECNO:
-		ret = __ram_open(dbp, txn, name, meta_pgno, flags);
+		ret = __ram_open(dbp, txn, fname, meta_pgno, flags);
 		break;
 	case DB_QUEUE:
-		ret = __qam_open(dbp, txn, name, meta_pgno, mode, flags);
+		ret = __qam_open(dbp, txn, fname, meta_pgno, mode, flags);
 		break;
 	case DB_UNKNOWN:
 		return (__db_unknown_type(dbenv, "__db_dbopen", dbp->type));
@@ -305,7 +199,7 @@ __db_dbopen(dbp, txn, name, subdb, flags, mode, meta_pgno)
 	if (ret != 0)
 		goto err;
 
-	DB_TEST_RECOVERY(dbp, DB_TEST_POSTOPEN, ret, name);
+	DB_TEST_RECOVERY(dbp, DB_TEST_POSTOPEN, ret, fname);
 
 	/*
 	 * Unnamed files don't need handle locks, so we only have to check
@@ -313,7 +207,7 @@ __db_dbopen(dbp, txn, name, subdb, flags, mode, meta_pgno)
 	 * files.
 	 */
 	if (!F_ISSET(dbp, DB_AM_RECOVER) &&
-	    name != NULL && LOCK_ISSET(dbp->handle_lock)) {
+	    fname != NULL && LOCK_ISSET(dbp->handle_lock)) {
 		if (txn != NULL) {
 			ret = __txn_lockevent(dbenv,
 			    txn, dbp, &dbp->handle_lock, dbp->lid);
@@ -327,6 +221,23 @@ err:
 	return (ret);
 }
 
+/*
+ * __db_get_open_flags --
+ *	Accessor for flags passed into DB->open call
+ *
+ * PUBLIC: int __db_get_open_flags __P((DB *, u_int32_t *));
+ */
+int
+__db_get_open_flags(dbp, flagsp)
+	DB *dbp;
+	u_int32_t *flagsp;
+{
+	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->get_open_flags");
+
+	*flagsp = dbp->open_flags;
+	return (0);
+}
+
 /*
  * __db_new_file --
  *	Create a new database file.
@@ -353,6 +264,7 @@ __db_new_file(dbp, txn, fhp, name)
 	case DB_QUEUE:
 		ret = __qam_new_file(dbp, txn, fhp, name);
 		break;
+	case DB_UNKNOWN:
 	default:
 		__db_err(dbp->dbenv,
 		    "%s: Invalid type %d specified", name, dbp->type);
@@ -391,10 +303,10 @@ __db_init_subdb(mdbp, dbp, name, txn)
 	if (!F_ISSET(dbp, DB_AM_CREATED)) {
 		/* Subdb exists; read meta-data page and initialize. */
 		mpf = mdbp->mpf;
-		if  ((ret = mpf->get(mpf, &dbp->meta_pgno, 0, &meta)) != 0)
+		if  ((ret = __memp_fget(mpf, &dbp->meta_pgno, 0, &meta)) != 0)
 			goto err;
 		ret = __db_meta_setup(mdbp->dbenv, dbp, name, meta, 0, 0);
-		if ((t_ret = mpf->put(mpf, meta, 0)) != 0 && ret == 0)
+		if ((t_ret = __memp_fput(mpf, meta, 0)) != 0 && ret == 0)
 			ret = t_ret;
 		/*
 		 * If __db_meta_setup found that the meta-page hadn't
@@ -417,6 +329,7 @@ __db_init_subdb(mdbp, dbp, name, txn)
 	case DB_QUEUE:
 		ret = EINVAL;
 		break;
+	case DB_UNKNOWN:
 	default:
 		__db_err(dbp->dbenv,
 		    "Invalid subdatabase type %d specified", dbp->type);
@@ -442,7 +355,8 @@ __db_chk_meta(dbenv, dbp, meta, do_metachk)
 	DBMETA *meta;
 	int do_metachk;
 {
-	int is_hmac, ret;
+	int is_hmac, ret, swapped;
+	u_int32_t orig_chk;
 	u_int8_t *chksum;
 
 	ret = 0;
@@ -453,11 +367,34 @@ __db_chk_meta(dbenv, dbp, meta, do_metachk)
 
 		is_hmac = meta->encrypt_alg == 0 ? 0 : 1;
 		chksum = ((BTMETA *)meta)->chksum;
-		if (do_metachk && ((ret = __db_check_chksum(dbenv,
-		    (DB_CIPHER *)dbenv->crypto_handle, chksum, meta,
-		    DBMETASIZE, is_hmac)) != 0))
-			return (ret);
-	}
+
+		/*
+		 * If we need to swap, the checksum function overwrites the
+		 * original checksum with 0, so we need to save a copy of the
+		 * original for swapping later.
+		 */
+		orig_chk = *(u_int32_t *)chksum;
+
+		/*
+		 * We cannot add this to __db_metaswap because that gets done
+		 * later after we've verified the checksum or decrypted.
+		 */
+		if (do_metachk) {
+			swapped = 0;
+chk_retry:		if ((ret = __db_check_chksum(dbenv,
+			    (DB_CIPHER *)dbenv->crypto_handle, chksum, meta,
+			    DBMETASIZE, is_hmac)) != 0) {
+				if (is_hmac || swapped)
+					return (ret);
+
+				M_32_SWAP(orig_chk);
+				swapped = 1;
+				*(u_int32_t *)chksum = orig_chk;
+				goto chk_retry;
+			}
+		}
+	} else if (dbp != NULL)
+		F_CLR(dbp, DB_AM_CHKSUM);
 
 #ifdef HAVE_CRYPTO
 	ret = __crypto_decrypt_meta(dbenv, dbp, (u_int8_t *)meta, do_metachk);
@@ -544,6 +481,10 @@ swap_retry:
 
 	switch (magic) {
 	case DB_BTREEMAGIC:
+		if (dbp->type != DB_UNKNOWN &&
+		    dbp->type != DB_RECNO && dbp->type != DB_BTREE)
+			goto bad_format;
+
 		flags = meta->flags;
 		if (F_ISSET(dbp, DB_AM_SWAP))
 			M_32_SWAP(flags);
@@ -556,12 +497,17 @@ swap_retry:
 			return (ret);
 		break;
 	case DB_HASHMAGIC:
+		if (dbp->type != DB_UNKNOWN && dbp->type != DB_HASH)
+			goto bad_format;
+
 		dbp->type = DB_HASH;
 		if ((oflags & DB_TRUNCATE) == 0 && (ret =
 		    __ham_metachk(dbp, name, (HMETA *)meta)) != 0)
 			return (ret);
 		break;
 	case DB_QAMMAGIC:
+		if (dbp->type != DB_UNKNOWN && dbp->type != DB_QUEUE)
+			goto bad_format;
 		dbp->type = DB_QUEUE;
 		if ((oflags & DB_TRUNCATE) == 0 && (ret =
 		    __qam_metachk(dbp, name, (QMETA *)meta)) != 0)
@@ -569,135 +515,20 @@ swap_retry:
 		break;
 	case DB_RENAMEMAGIC:
 		F_SET(dbp, DB_AM_IN_RENAME);
-		break;
-	}
-	return (0);
 
-bad_format:
-	__db_err(dbenv, "%s: unexpected file type or format", name);
-	return (ret == 0 ? EINVAL : ret);
-}
+		/* Copy the file's ID. */
+		memcpy(dbp->fileid, ((DBMETA *)meta)->uid, DB_FILE_ID_LEN);
 
-/*
- * __db_openchk --
- *	Interface error checking for open calls.
- */
-static int
-__db_openchk(dbp, txn, name, subdb, type, flags)
-	DB *dbp;
-	DB_TXN *txn;
-	const char *name, *subdb;
-	DBTYPE type;
-	u_int32_t flags;
-{
-	DB_ENV *dbenv;
-	int ret;
-	u_int32_t ok_flags;
-
-	dbenv = dbp->dbenv;
-
-	/* Validate arguments. */
-#define	OKFLAGS								\
-    (DB_AUTO_COMMIT | DB_CREATE | DB_DIRTY_READ | DB_EXCL |		\
-     DB_FCNTL_LOCKING | DB_NOMMAP | DB_RDONLY | DB_RDWRMASTER |		\
-     DB_THREAD | DB_TRUNCATE | DB_WRITEOPEN)
-	if ((ret = __db_fchk(dbenv, "DB->open", flags, OKFLAGS)) != 0)
-		return (ret);
-	if (LF_ISSET(DB_EXCL) && !LF_ISSET(DB_CREATE))
-		return (__db_ferr(dbenv, "DB->open", 1));
-	if (LF_ISSET(DB_RDONLY) && LF_ISSET(DB_CREATE))
-		return (__db_ferr(dbenv, "DB->open", 1));
-
-#ifdef	HAVE_VXWORKS
-	if (LF_ISSET(DB_TRUNCATE)) {
-		__db_err(dbenv, "DB_TRUNCATE unsupported in VxWorks");
-		return (__db_eopnotsup(dbenv));
-	}
-#endif
-	switch (type) {
-	case DB_UNKNOWN:
-		if (LF_ISSET(DB_CREATE|DB_TRUNCATE)) {
-			__db_err(dbenv,
-	    "%s: DB_UNKNOWN type specified with DB_CREATE or DB_TRUNCATE",
-			    name);
-			return (EINVAL);
-		}
-		ok_flags = 0;
-		break;
-	case DB_BTREE:
-		ok_flags = DB_OK_BTREE;
-		break;
-	case DB_HASH:
-		ok_flags = DB_OK_HASH;
-		break;
-	case DB_QUEUE:
-		ok_flags = DB_OK_QUEUE;
-		break;
-	case DB_RECNO:
-		ok_flags = DB_OK_RECNO;
 		break;
 	default:
-		__db_err(dbenv, "unknown type: %lu", (u_long)type);
-		return (EINVAL);
-	}
-	if (ok_flags)
-		DB_ILLEGAL_METHOD(dbp, ok_flags);
-
-	/* The environment may have been created, but never opened. */
-	if (!F_ISSET(dbenv, DB_ENV_DBLOCAL | DB_ENV_OPEN_CALLED)) {
-		__db_err(dbenv, "environment not yet opened");
-		return (EINVAL);
-	}
-
-	/*
-	 * Historically, you could pass in an environment that didn't have a
-	 * mpool, and DB would create a private one behind the scenes.  This
-	 * no longer works.
-	 */
-	if (!F_ISSET(dbenv, DB_ENV_DBLOCAL) && !MPOOL_ON(dbenv)) {
-		__db_err(dbenv, "environment did not include a memory pool");
-		return (EINVAL);
-	}
-
-	/*
-	 * You can't specify threads during DB->open if subsystems in the
-	 * environment weren't configured with them.
-	 */
-	if (LF_ISSET(DB_THREAD) &&
-	    !F_ISSET(dbenv, DB_ENV_DBLOCAL | DB_ENV_THREAD)) {
-		__db_err(dbenv, "environment not created using DB_THREAD");
-		return (EINVAL);
-	}
-
-	/* DB_TRUNCATE is not transaction recoverable. */
-	if (LF_ISSET(DB_TRUNCATE) && txn != NULL) {
-		__db_err(dbenv,
-		    "DB_TRUNCATE illegal with transaction specified");
-		return (EINVAL);
-	}
-
-	/* Subdatabase checks. */
-	if (subdb != NULL) {
-		/* Subdatabases must be created in named files. */
-		if (name == NULL) {
-			__db_err(dbenv,
-		    "multiple databases cannot be created in temporary files");
-			return (EINVAL);
-		}
-
-		/* Truncate is a physical file operation */
-		if (LF_ISSET(DB_TRUNCATE)) {
-			__db_err(dbenv,
-			    "DB_TRUNCATE illegal with multiple databases");
-			return (EINVAL);
-		}
-
-		/* QAM can't be done as a subdatabase. */
-		if (type == DB_QUEUE) {
-			__db_err(dbenv, "Queue databases must be one-per-file");
-			return (EINVAL);
-		}
+		goto bad_format;
 	}
-
 	return (0);
+
+bad_format:
+	if (F_ISSET(dbp, DB_AM_RECOVER))
+		ret = ENOENT;
+	else
+		__db_err(dbenv, "%s: unexpected file type or format", name);
+	return (ret == 0 ? EINVAL : ret);
 }
diff --git a/storage/bdb/db/db_overflow.c b/storage/bdb/db/db_overflow.c
index 27dcb41a2ffc8c0c8b113f2a2dfd5ef59f9f5f1e..046e60fab9aebce6023c4cb96756d7bf3a3bdf04 100644
--- a/storage/bdb/db/db_overflow.c
+++ b/storage/bdb/db/db_overflow.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -38,14 +38,12 @@
  * 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.
+ *
+ * $Id: db_overflow.c,v 11.54 2004/03/28 17:17:50 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_overflow.c,v 11.46 2002/08/08 03:57:48 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -54,8 +52,9 @@ static const char revid[] = "$Id: db_overflow.c,v 11.46 2002/08/08 03:57:48 bost
 
 #include "db_int.h"
 #include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
 #include "dbinc/db_am.h"
-#include "dbinc/db_verify.h"
+#include "dbinc/mp.h"
 
 /*
  * Big key/data code.
@@ -116,7 +115,7 @@ __db_goff(dbp, dbt, tlen, pgno, bpp, bpsz)
 	if (F_ISSET(dbt, DB_DBT_USERMEM)) {
 		if (needed > dbt->ulen) {
 			dbt->size = needed;
-			return (ENOMEM);
+			return (DB_BUFFER_SMALL);
 		}
 	} else if (F_ISSET(dbt, DB_DBT_MALLOC)) {
 		if ((ret = __os_umalloc(dbenv, needed, &dbt->data)) != 0)
@@ -124,13 +123,20 @@ __db_goff(dbp, dbt, tlen, pgno, bpp, bpsz)
 	} else if (F_ISSET(dbt, DB_DBT_REALLOC)) {
 		if ((ret = __os_urealloc(dbenv, needed, &dbt->data)) != 0)
 			return (ret);
-	} else if (*bpsz == 0 || *bpsz < needed) {
+	} else if (bpsz != NULL && (*bpsz == 0 || *bpsz < needed)) {
 		if ((ret = __os_realloc(dbenv, needed, bpp)) != 0)
 			return (ret);
 		*bpsz = needed;
 		dbt->data = *bpp;
-	} else
+	} else if (bpp != NULL)
 		dbt->data = *bpp;
+	else {
+		DB_ASSERT(
+		    F_ISSET(dbt,
+		    DB_DBT_USERMEM | DB_DBT_MALLOC | DB_DBT_REALLOC) ||
+		    bpsz != NULL || bpp != NULL);
+		return (DB_BUFFER_SMALL);
+	}
 
 	/*
 	 * Step through the linked list of pages, copying the data on each
@@ -138,7 +144,7 @@ __db_goff(dbp, dbt, tlen, pgno, bpp, bpsz)
 	 */
 	dbt->size = needed;
 	for (curoff = 0, p = dbt->data; pgno != PGNO_INVALID && needed > 0;) {
-		if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
+		if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
 			return (ret);
 
 		/* Check if we need any bytes from this page. */
@@ -157,7 +163,7 @@ __db_goff(dbp, dbt, tlen, pgno, bpp, bpsz)
 		}
 		curoff += OV_LEN(h);
 		pgno = h->next_pgno;
-		(void)mpf->put(mpf, h, 0);
+		(void)__memp_fput(mpf, h, 0);
 	}
 	return (0);
 }
@@ -222,7 +228,7 @@ __db_poff(dbc, dbt, pgnop)
 			    lastp == NULL ? &null_lsn : &LSN(lastp),
 			    &null_lsn)) != 0) {
 				if (lastp != NULL)
-					(void)mpf->put(mpf,
+					(void)__memp_fput(mpf,
 					    lastp, DB_MPOOL_DIRTY);
 				lastp = pagep;
 				break;
@@ -251,12 +257,12 @@ __db_poff(dbc, dbt, pgnop)
 		else {
 			lastp->next_pgno = PGNO(pagep);
 			pagep->prev_pgno = PGNO(lastp);
-			(void)mpf->put(mpf, lastp, DB_MPOOL_DIRTY);
+			(void)__memp_fput(mpf, lastp, DB_MPOOL_DIRTY);
 		}
 		lastp = pagep;
 	}
 	if (lastp != NULL &&
-	    (t_ret = mpf->put(mpf, lastp, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+	    (t_ret = __memp_fput(mpf, lastp, DB_MPOOL_DIRTY)) != 0 && ret == 0)
 		ret = t_ret;
 	return (ret);
 }
@@ -281,22 +287,20 @@ __db_ovref(dbc, pgno, adjust)
 	dbp = dbc->dbp;
 	mpf = dbp->mpf;
 
-	if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0) {
-		__db_pgerr(dbp, pgno, ret);
-		return (ret);
-	}
+	if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
+		return (__db_pgerr(dbp, pgno, ret));
 
 	if (DBC_LOGGING(dbc)) {
 		if ((ret = __db_ovref_log(dbp,
 		    dbc->txn, &LSN(h), 0, h->pgno, adjust, &LSN(h))) != 0) {
-			(void)mpf->put(mpf, h, 0);
+			(void)__memp_fput(mpf, h, 0);
 			return (ret);
 		}
 	} else
 		LSN_NOT_LOGGED(LSN(h));
 	OV_REF(h) += adjust;
 
-	(void)mpf->put(mpf, h, DB_MPOOL_DIRTY);
+	(void)__memp_fput(mpf, h, DB_MPOOL_DIRTY);
 	return (0);
 }
 
@@ -322,10 +326,8 @@ __db_doff(dbc, pgno)
 	mpf = dbp->mpf;
 
 	do {
-		if ((ret = mpf->get(mpf, &pgno, 0, &pagep)) != 0) {
-			__db_pgerr(dbp, pgno, ret);
-			return (ret);
-		}
+		if ((ret = __memp_fget(mpf, &pgno, 0, &pagep)) != 0)
+			return (__db_pgerr(dbp, pgno, ret));
 
 		DB_ASSERT(TYPE(pagep) == P_OVERFLOW);
 		/*
@@ -333,7 +335,7 @@ __db_doff(dbc, pgno)
 		 * decrement the reference count and return.
 		 */
 		if (OV_REF(pagep) > 1) {
-			(void)mpf->put(mpf, pagep, 0);
+			(void)__memp_fput(mpf, pagep, 0);
 			return (__db_ovref(dbc, pgno, -1));
 		}
 
@@ -346,12 +348,13 @@ __db_doff(dbc, pgno)
 			    PGNO(pagep), PREV_PGNO(pagep),
 			    NEXT_PGNO(pagep), &tmp_dbt,
 			    &LSN(pagep), &null_lsn, &null_lsn)) != 0) {
-				(void)mpf->put(mpf, pagep, 0);
+				(void)__memp_fput(mpf, pagep, 0);
 				return (ret);
 			}
 		} else
 			LSN_NOT_LOGGED(LSN(pagep));
 		pgno = pagep->next_pgno;
+		OV_LEN(pagep) = 0;
 		if ((ret = __db_free(dbc, pagep)) != 0)
 			return (ret);
 	} while (pgno != PGNO_INVALID);
@@ -411,7 +414,7 @@ __db_moff(dbp, dbt, pgno, tlen, cmpfunc, cmpp)
 	/* While there are both keys to compare. */
 	for (*cmpp = 0, p1 = dbt->data,
 	    key_left = dbt->size; key_left > 0 && pgno != PGNO_INVALID;) {
-		if ((ret = mpf->get(mpf, &pgno, 0, &pagep)) != 0)
+		if ((ret = __memp_fget(mpf, &pgno, 0, &pagep)) != 0)
 			return (ret);
 
 		cmp_bytes = OV_LEN(pagep) < key_left ? OV_LEN(pagep) : key_left;
@@ -424,7 +427,7 @@ __db_moff(dbp, dbt, pgno, tlen, cmpfunc, cmpp)
 				break;
 			}
 		pgno = NEXT_PGNO(pagep);
-		if ((ret = mpf->put(mpf, pagep, 0)) != 0)
+		if ((ret = __memp_fput(mpf, pagep, 0)) != 0)
 			return (ret);
 		if (*cmpp != 0)
 			return (0);
@@ -438,289 +441,3 @@ __db_moff(dbp, dbt, pgno, tlen, cmpfunc, cmpp)
 
 	return (0);
 }
-
-/*
- * __db_vrfy_overflow --
- *	Verify overflow page.
- *
- * PUBLIC: int __db_vrfy_overflow __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t,
- * PUBLIC:     u_int32_t));
- */
-int
-__db_vrfy_overflow(dbp, vdp, h, pgno, flags)
-	DB *dbp;
-	VRFY_DBINFO *vdp;
-	PAGE *h;
-	db_pgno_t pgno;
-	u_int32_t flags;
-{
-	VRFY_PAGEINFO *pip;
-	int isbad, ret, t_ret;
-
-	isbad = 0;
-	if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
-		return (ret);
-
-	if ((ret = __db_vrfy_datapage(dbp, vdp, h, pgno, flags)) != 0) {
-		if (ret == DB_VERIFY_BAD)
-			isbad = 1;
-		else
-			goto err;
-	}
-
-	pip->refcount = OV_REF(h);
-	if (pip->refcount < 1) {
-		EPRINT((dbp->dbenv,
-		    "Page %lu: overflow page has zero reference count",
-		    (u_long)pgno));
-		isbad = 1;
-	}
-
-	/* Just store for now. */
-	pip->olen = HOFFSET(h);
-
-err:	if ((t_ret = __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0)
-		ret = t_ret;
-	return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
-}
-
-/*
- * __db_vrfy_ovfl_structure --
- *	Walk a list of overflow pages, avoiding cycles and marking
- *	pages seen.
- *
- * PUBLIC: int __db_vrfy_ovfl_structure
- * PUBLIC:     __P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t, u_int32_t));
- */
-int
-__db_vrfy_ovfl_structure(dbp, vdp, pgno, tlen, flags)
-	DB *dbp;
-	VRFY_DBINFO *vdp;
-	db_pgno_t pgno;
-	u_int32_t tlen;
-	u_int32_t flags;
-{
-	DB *pgset;
-	VRFY_PAGEINFO *pip;
-	db_pgno_t next, prev;
-	int isbad, p, ret, t_ret;
-	u_int32_t refcount;
-
-	pgset = vdp->pgset;
-	DB_ASSERT(pgset != NULL);
-	isbad = 0;
-
-	/* This shouldn't happen, but just to be sure. */
-	if (!IS_VALID_PGNO(pgno))
-		return (DB_VERIFY_BAD);
-
-	/*
-	 * Check the first prev_pgno;  it ought to be PGNO_INVALID,
-	 * since there's no prev page.
-	 */
-	if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
-		return (ret);
-
-	/* The refcount is stored on the first overflow page. */
-	refcount = pip->refcount;
-
-	if (pip->type != P_OVERFLOW) {
-		EPRINT((dbp->dbenv,
-		    "Page %lu: overflow page of invalid type %lu",
-		    (u_long)pgno, (u_long)pip->type));
-		ret = DB_VERIFY_BAD;
-		goto err;		/* Unsafe to continue. */
-	}
-
-	prev = pip->prev_pgno;
-	if (prev != PGNO_INVALID) {
-		EPRINT((dbp->dbenv,
-	    "Page %lu: first page in overflow chain has a prev_pgno %lu",
-		    (u_long)pgno, (u_long)prev));
-		isbad = 1;
-	}
-
-	for (;;) {
-		/*
-		 * This is slightly gross.  Btree leaf pages reference
-		 * individual overflow trees multiple times if the overflow page
-		 * is the key to a duplicate set.  The reference count does not
-		 * reflect this multiple referencing.  Thus, if this is called
-		 * during the structure verification of a btree leaf page, we
-		 * check to see whether we've seen it from a leaf page before
-		 * and, if we have, adjust our count of how often we've seen it
-		 * accordingly.
-		 *
-		 * (This will screw up if it's actually referenced--and
-		 * correctly refcounted--from two different leaf pages, but
-		 * that's a very unlikely brokenness that we're not checking for
-		 * anyway.)
-		 */
-
-		if (LF_ISSET(ST_OVFL_LEAF)) {
-			if (F_ISSET(pip, VRFY_OVFL_LEAFSEEN)) {
-				if ((ret =
-				    __db_vrfy_pgset_dec(pgset, pgno)) != 0)
-					goto err;
-			} else
-				F_SET(pip, VRFY_OVFL_LEAFSEEN);
-		}
-
-		if ((ret = __db_vrfy_pgset_get(pgset, pgno, &p)) != 0)
-			goto err;
-
-		/*
-		 * We may have seen this elsewhere, if the overflow entry
-		 * has been promoted to an internal page.
-		 */
-		if ((u_int32_t)p > refcount) {
-			EPRINT((dbp->dbenv,
-			    "Page %lu: encountered twice in overflow traversal",
-			    (u_long)pgno));
-			ret = DB_VERIFY_BAD;
-			goto err;
-		}
-		if ((ret = __db_vrfy_pgset_inc(pgset, pgno)) != 0)
-			goto err;
-
-		/* Keep a running tab on how much of the item we've seen. */
-		tlen -= pip->olen;
-
-		/* Send feedback to the application about our progress. */
-		if (!LF_ISSET(DB_SALVAGE))
-			__db_vrfy_struct_feedback(dbp, vdp);
-
-		next = pip->next_pgno;
-
-		/* Are we there yet? */
-		if (next == PGNO_INVALID)
-			break;
-
-		/*
-		 * We've already checked this when we saved it, but just
-		 * to be sure...
-		 */
-		if (!IS_VALID_PGNO(next)) {
-			DB_ASSERT(0);
-			EPRINT((dbp->dbenv,
-			    "Page %lu: bad next_pgno %lu on overflow page",
-			    (u_long)pgno, (u_long)next));
-			ret = DB_VERIFY_BAD;
-			goto err;
-		}
-
-		if ((ret = __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 ||
-		    (ret = __db_vrfy_getpageinfo(vdp, next, &pip)) != 0)
-			return (ret);
-		if (pip->prev_pgno != pgno) {
-			EPRINT((dbp->dbenv,
-		"Page %lu: bad prev_pgno %lu on overflow page (should be %lu)",
-			    (u_long)next, (u_long)pip->prev_pgno,
-			    (u_long)pgno));
-			isbad = 1;
-			/*
-			 * It's safe to continue because we have separate
-			 * cycle detection.
-			 */
-		}
-
-		pgno = next;
-	}
-
-	if (tlen > 0) {
-		isbad = 1;
-		EPRINT((dbp->dbenv,
-		    "Page %lu: overflow item incomplete", (u_long)pgno));
-	}
-
-err:	if ((t_ret =
-	    __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
-		ret = t_ret;
-	return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
-}
-
-/*
- * __db_safe_goff --
- *	Get an overflow item, very carefully, from an untrusted database,
- *	in the context of the salvager.
- *
- * PUBLIC: int __db_safe_goff __P((DB *, VRFY_DBINFO *, db_pgno_t,
- * PUBLIC:     DBT *, void **, u_int32_t));
- */
-int
-__db_safe_goff(dbp, vdp, pgno, dbt, buf, flags)
-	DB *dbp;
-	VRFY_DBINFO *vdp;
-	db_pgno_t pgno;
-	DBT *dbt;
-	void **buf;
-	u_int32_t flags;
-{
-	DB_MPOOLFILE *mpf;
-	PAGE *h;
-	int ret, t_ret;
-	u_int32_t bytesgot, bytes;
-	u_int8_t *src, *dest;
-
-	mpf = dbp->mpf;
-	h = NULL;
-	ret = t_ret = 0;
-	bytesgot = bytes = 0;
-
-	while ((pgno != PGNO_INVALID) && (IS_VALID_PGNO(pgno))) {
-		/*
-		 * Mark that we're looking at this page;  if we've seen it
-		 * already, quit.
-		 */
-		if ((ret = __db_salvage_markdone(vdp, pgno)) != 0)
-			break;
-
-		if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
-			break;
-
-		/*
-		 * Make sure it's really an overflow page, unless we're
-		 * being aggressive, in which case we pretend it is.
-		 */
-		if (!LF_ISSET(DB_AGGRESSIVE) && TYPE(h) != P_OVERFLOW) {
-			ret = DB_VERIFY_BAD;
-			break;
-		}
-
-		src = (u_int8_t *)h + P_OVERHEAD(dbp);
-		bytes = OV_LEN(h);
-
-		if (bytes + P_OVERHEAD(dbp) > dbp->pgsize)
-			bytes = dbp->pgsize - P_OVERHEAD(dbp);
-
-		if ((ret = __os_realloc(dbp->dbenv,
-		    bytesgot + bytes, buf)) != 0)
-			break;
-
-		dest = (u_int8_t *)*buf + bytesgot;
-		bytesgot += bytes;
-
-		memcpy(dest, src, bytes);
-
-		pgno = NEXT_PGNO(h);
-
-		if ((ret = mpf->put(mpf, h, 0)) != 0)
-			break;
-		h = NULL;
-	}
-
-	/*
-	 * If we're being aggressive, salvage a partial datum if there
-	 * was an error somewhere along the way.
-	 */
-	if (ret == 0 || LF_ISSET(DB_AGGRESSIVE)) {
-		dbt->size = bytesgot;
-		dbt->data = *buf;
-	}
-
-	/* If we broke out on error, don't leave pages pinned. */
-	if (h != NULL && (t_ret = mpf->put(mpf, h, 0)) != 0 && ret == 0)
-		ret = t_ret;
-
-	return (ret);
-}
diff --git a/storage/bdb/db/db_ovfl_vrfy.c b/storage/bdb/db/db_ovfl_vrfy.c
new file mode 100644
index 0000000000000000000000000000000000000000..a3c5fba7c126e633c2b4a4bab5e0f04447e62557
--- /dev/null
+++ b/storage/bdb/db/db_ovfl_vrfy.c
@@ -0,0 +1,374 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2004
+ *	Sleepycat Software.  All rights reserved.
+ */
+/*
+ * Copyright (c) 1990, 1993, 1994, 1995, 1996
+ *	Keith Bostic.  All rights reserved.
+ */
+/*
+ * Copyright (c) 1990, 1993, 1994, 1995
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: db_ovfl_vrfy.c,v 11.56 2004/01/28 03:35:57 bostic Exp $
+ */
+
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/db_am.h"
+#include "dbinc/db_verify.h"
+#include "dbinc/mp.h"
+
+/*
+ * __db_vrfy_overflow --
+ *	Verify overflow page.
+ *
+ * PUBLIC: int __db_vrfy_overflow __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t,
+ * PUBLIC:     u_int32_t));
+ */
+int
+__db_vrfy_overflow(dbp, vdp, h, pgno, flags)
+	DB *dbp;
+	VRFY_DBINFO *vdp;
+	PAGE *h;
+	db_pgno_t pgno;
+	u_int32_t flags;
+{
+	VRFY_PAGEINFO *pip;
+	int isbad, ret, t_ret;
+
+	isbad = 0;
+	if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
+		return (ret);
+
+	if ((ret = __db_vrfy_datapage(dbp, vdp, h, pgno, flags)) != 0) {
+		if (ret == DB_VERIFY_BAD)
+			isbad = 1;
+		else
+			goto err;
+	}
+
+	pip->refcount = OV_REF(h);
+	if (pip->refcount < 1) {
+		EPRINT((dbp->dbenv,
+		    "Page %lu: overflow page has zero reference count",
+		    (u_long)pgno));
+		isbad = 1;
+	}
+
+	/* Just store for now. */
+	pip->olen = HOFFSET(h);
+
+err:	if ((t_ret = __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0)
+		ret = t_ret;
+	return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
+}
+
+/*
+ * __db_vrfy_ovfl_structure --
+ *	Walk a list of overflow pages, avoiding cycles and marking
+ *	pages seen.
+ *
+ * PUBLIC: int __db_vrfy_ovfl_structure
+ * PUBLIC:     __P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t, u_int32_t));
+ */
+int
+__db_vrfy_ovfl_structure(dbp, vdp, pgno, tlen, flags)
+	DB *dbp;
+	VRFY_DBINFO *vdp;
+	db_pgno_t pgno;
+	u_int32_t tlen;
+	u_int32_t flags;
+{
+	DB *pgset;
+	VRFY_PAGEINFO *pip;
+	db_pgno_t next, prev;
+	int isbad, ret, seen_cnt, t_ret;
+	u_int32_t refcount;
+
+	pgset = vdp->pgset;
+	DB_ASSERT(pgset != NULL);
+	isbad = 0;
+
+	/* This shouldn't happen, but just to be sure. */
+	if (!IS_VALID_PGNO(pgno))
+		return (DB_VERIFY_BAD);
+
+	/*
+	 * Check the first prev_pgno;  it ought to be PGNO_INVALID,
+	 * since there's no prev page.
+	 */
+	if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
+		return (ret);
+
+	/* The refcount is stored on the first overflow page. */
+	refcount = pip->refcount;
+
+	if (pip->type != P_OVERFLOW) {
+		EPRINT((dbp->dbenv,
+		    "Page %lu: overflow page of invalid type %lu",
+		    (u_long)pgno, (u_long)pip->type));
+		ret = DB_VERIFY_BAD;
+		goto err;		/* Unsafe to continue. */
+	}
+
+	prev = pip->prev_pgno;
+	if (prev != PGNO_INVALID) {
+		EPRINT((dbp->dbenv,
+	    "Page %lu: first page in overflow chain has a prev_pgno %lu",
+		    (u_long)pgno, (u_long)prev));
+		isbad = 1;
+	}
+
+	for (;;) {
+		/*
+		 * We may have seen this page elsewhere, if the overflow entry
+		 * has been promoted to an internal page;  we just want to
+		 * make sure that each overflow page is seen exactly as many
+		 * times as its refcount dictates.
+		 *
+		 * Note that this code also serves to keep us from looping
+		 * infinitely if there's a cycle in an overflow chain.
+		 */
+		if ((ret = __db_vrfy_pgset_get(pgset, pgno, &seen_cnt)) != 0)
+			goto err;
+		if ((u_int32_t)seen_cnt > refcount) {
+			EPRINT((dbp->dbenv,
+		"Page %lu: encountered too many times in overflow traversal",
+			    (u_long)pgno));
+			ret = DB_VERIFY_BAD;
+			goto err;
+		}
+		if ((ret = __db_vrfy_pgset_inc(pgset, pgno)) != 0)
+			goto err;
+
+		/*
+		 * Each overflow page can be referenced multiple times,
+		 * because it's possible for overflow Btree keys to get
+		 * promoted to internal pages.  We want to make sure that
+		 * each page is referenced from a Btree leaf (or Hash data
+		 * page, which we consider a "leaf" here) exactly once; if
+		 * the parent was a leaf, set a flag to indicate that we've
+		 * seen this page in a leaf context.
+		 *
+		 * If the parent is not a leaf--in which case it's a Btree
+		 * internal page--we don't need to bother doing any further
+		 * verification, as we'll do it when we hit the leaf (or
+		 * complain that we never saw the leaf).  Only the first
+		 * page in an overflow chain should ever have a refcount
+		 * greater than 1, and the combination of the LEAFSEEN check
+		 * and the fact that we bail after the first page for
+		 * non-leaves should ensure this.
+		 *
+		 * Note that each "child" of a page, such as an overflow page,
+		 * is stored and verified in a structure check exactly once,
+		 * so this code does not need to contend with the fact that
+		 * overflow chains used as Btree duplicate keys may be
+		 * referenced multiply from a single Btree leaf page.
+		 */
+		if (LF_ISSET(ST_OVFL_LEAF)) {
+			if (F_ISSET(pip, VRFY_OVFL_LEAFSEEN)) {
+				EPRINT((dbp->dbenv,
+		"Page %lu: overflow page linked twice from leaf or data page",
+				    (u_long)pgno));
+				ret = DB_VERIFY_BAD;
+				goto err;
+			}
+			F_SET(pip, VRFY_OVFL_LEAFSEEN);
+		}
+
+		/*
+		 * We want to verify each overflow chain only once, and
+		 * although no chain should be linked more than once from a
+		 * leaf page, we can't guarantee that it'll be linked that
+		 * once if it's linked from an internal page and the key
+		 * is gone.
+		 *
+		 * seen_cnt is the number of times we'd encountered this page
+		 * before calling this function.
+		 */
+		if (seen_cnt == 0) {
+			/*
+			 * Keep a running tab on how much of the item we've
+			 * seen.
+			 */
+			tlen -= pip->olen;
+
+			/* Send the application feedback about our progress. */
+			if (!LF_ISSET(DB_SALVAGE))
+				__db_vrfy_struct_feedback(dbp, vdp);
+		} else
+			goto done;
+
+		next = pip->next_pgno;
+
+		/* Are we there yet? */
+		if (next == PGNO_INVALID)
+			break;
+
+		/*
+		 * We've already checked this when we saved it, but just
+		 * to be sure...
+		 */
+		if (!IS_VALID_PGNO(next)) {
+			DB_ASSERT(0);
+			EPRINT((dbp->dbenv,
+			    "Page %lu: bad next_pgno %lu on overflow page",
+			    (u_long)pgno, (u_long)next));
+			ret = DB_VERIFY_BAD;
+			goto err;
+		}
+
+		if ((ret = __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 ||
+		    (ret = __db_vrfy_getpageinfo(vdp, next, &pip)) != 0)
+			return (ret);
+		if (pip->prev_pgno != pgno) {
+			EPRINT((dbp->dbenv,
+		"Page %lu: bad prev_pgno %lu on overflow page (should be %lu)",
+			    (u_long)next, (u_long)pip->prev_pgno,
+			    (u_long)pgno));
+			isbad = 1;
+			/*
+			 * It's safe to continue because we have separate
+			 * cycle detection.
+			 */
+		}
+
+		pgno = next;
+	}
+
+	if (tlen > 0) {
+		isbad = 1;
+		EPRINT((dbp->dbenv,
+		    "Page %lu: overflow item incomplete", (u_long)pgno));
+	}
+
+done:
+err:	if ((t_ret =
+	    __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
+		ret = t_ret;
+	return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
+}
+
+/*
+ * __db_safe_goff --
+ *	Get an overflow item, very carefully, from an untrusted database,
+ *	in the context of the salvager.
+ *
+ * PUBLIC: int __db_safe_goff __P((DB *, VRFY_DBINFO *, db_pgno_t,
+ * PUBLIC:     DBT *, void *, u_int32_t));
+ */
+int
+__db_safe_goff(dbp, vdp, pgno, dbt, buf, flags)
+	DB *dbp;
+	VRFY_DBINFO *vdp;
+	db_pgno_t pgno;
+	DBT *dbt;
+	void *buf;
+	u_int32_t flags;
+{
+	DB_MPOOLFILE *mpf;
+	PAGE *h;
+	int ret, t_ret;
+	u_int32_t bytesgot, bytes;
+	u_int8_t *src, *dest;
+
+	mpf = dbp->mpf;
+	h = NULL;
+	ret = t_ret = 0;
+	bytesgot = bytes = 0;
+
+	while ((pgno != PGNO_INVALID) && (IS_VALID_PGNO(pgno))) {
+		/*
+		 * Mark that we're looking at this page;  if we've seen it
+		 * already, quit.
+		 */
+		if ((ret = __db_salvage_markdone(vdp, pgno)) != 0)
+			break;
+
+		if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
+			break;
+
+		/*
+		 * Make sure it's really an overflow page, unless we're
+		 * being aggressive, in which case we pretend it is.
+		 */
+		if (!LF_ISSET(DB_AGGRESSIVE) && TYPE(h) != P_OVERFLOW) {
+			ret = DB_VERIFY_BAD;
+			break;
+		}
+
+		src = (u_int8_t *)h + P_OVERHEAD(dbp);
+		bytes = OV_LEN(h);
+
+		if (bytes + P_OVERHEAD(dbp) > dbp->pgsize)
+			bytes = dbp->pgsize - P_OVERHEAD(dbp);
+
+		if ((ret = __os_realloc(dbp->dbenv,
+		    bytesgot + bytes, buf)) != 0)
+			break;
+
+		dest = *(u_int8_t **)buf + bytesgot;
+		bytesgot += bytes;
+
+		memcpy(dest, src, bytes);
+
+		pgno = NEXT_PGNO(h);
+
+		if ((ret = __memp_fput(mpf, h, 0)) != 0)
+			break;
+		h = NULL;
+	}
+
+	/*
+	 * If we're being aggressive, salvage a partial datum if there
+	 * was an error somewhere along the way.
+	 */
+	if (ret == 0 || LF_ISSET(DB_AGGRESSIVE)) {
+		dbt->size = bytesgot;
+		dbt->data = *(void **)buf;
+	}
+
+	/* If we broke out on error, don't leave pages pinned. */
+	if (h != NULL && (t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
+		ret = t_ret;
+
+	return (ret);
+}
diff --git a/storage/bdb/db/db_pr.c b/storage/bdb/db/db_pr.c
index 235e7187f7c9f203e577f66a938ccd6a3a32baee..e63daf3ee20ab03e62830771d23e2b28a6eef3d6 100644
--- a/storage/bdb/db/db_pr.c
+++ b/storage/bdb/db/db_pr.c
@@ -1,23 +1,20 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_pr.c,v 11.121 2004/10/28 14:48:43 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_pr.c,v 11.84 2002/09/10 02:45:20 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 #endif
 
 #include "db_int.h"
@@ -29,15 +26,6 @@ static const char revid[] = "$Id: db_pr.c,v 11.84 2002/09/10 02:45:20 bostic Exp
 #include "dbinc/qam.h"
 #include "dbinc/db_verify.h"
 
-static int	 __db_bmeta __P((DB *, FILE *, BTMETA *, u_int32_t));
-static int	 __db_hmeta __P((DB *, FILE *, HMETA *, u_int32_t));
-static void	 __db_meta __P((DB *, DBMETA *, FILE *, FN const *, u_int32_t));
-static const char *__db_pagetype_to_string __P((u_int32_t));
-static void	 __db_prdb __P((DB *, FILE *));
-static void	 __db_proff __P((void *, FILE *));
-static int	 __db_prtree __P((DB *, FILE *, u_int32_t));
-static int	 __db_qmeta __P((DB *, FILE *, QMETA *, u_int32_t));
-
 /*
  * __db_loadme --
  *	A nice place to put a breakpoint.
@@ -52,21 +40,34 @@ __db_loadme()
 	__os_id(&id);
 }
 
+#ifdef HAVE_STATISTICS
+static int	 __db_bmeta __P((DB *, BTMETA *, u_int32_t));
+static int	 __db_hmeta __P((DB *, HMETA *, u_int32_t));
+static void	 __db_meta __P((DB *, DBMETA *, FN const *, u_int32_t));
+static const char *__db_pagetype_to_string __P((u_int32_t));
+static void	 __db_prdb __P((DB *, u_int32_t));
+static void	 __db_proff __P((DB_ENV *, DB_MSGBUF *, void *));
+static int	 __db_prtree __P((DB *, u_int32_t));
+static int	 __db_qmeta __P((DB *, QMETA *, u_int32_t));
+
 /*
- * __db_dump --
+ * __db_dumptree --
  *	Dump the tree to a file.
  *
- * PUBLIC: int __db_dump __P((DB *, char *, char *));
+ * PUBLIC: int __db_dumptree __P((DB *, char *, char *));
  */
 int
-__db_dump(dbp, op, name)
+__db_dumptree(dbp, op, name)
 	DB *dbp;
 	char *op, *name;
 {
-	FILE *fp;
+	DB_ENV *dbenv;
+	FILE *fp, *orig_fp;
 	u_int32_t flags;
 	int ret;
 
+	dbenv = dbp->dbenv;
+
 	for (flags = 0; *op != '\0'; ++op)
 		switch (*op) {
 		case 'a':
@@ -81,74 +82,74 @@ __db_dump(dbp, op, name)
 			return (EINVAL);
 		}
 
-	if (name == NULL)
-		fp = stdout;
-	else {
+	if (name != NULL) {
 		if ((fp = fopen(name, "w")) == NULL)
 			return (__os_get_errno());
-	}
 
-	__db_prdb(dbp, fp);
+		orig_fp = dbenv->db_msgfile;
+		dbenv->db_msgfile = fp;
+	} else
+		fp = orig_fp = NULL;
+
+	__db_prdb(dbp, flags);
 
-	fprintf(fp, "%s\n", DB_LINE);
+	__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
 
-	ret = __db_prtree(dbp, fp, flags);
+	ret = __db_prtree(dbp, flags);
 
-	fflush(fp);
-	if (name != NULL)
-		fclose(fp);
+	if (fp != NULL) {
+		(void)fclose(fp);
+		dbenv->db_msgfile = orig_fp;
+	}
 
 	return (ret);
 }
 
+static const FN __db_flags_fn[] = {
+	{ DB_AM_CHKSUM,		"checksumming" },
+	{ DB_AM_CL_WRITER,	"client replica writer" },
+	{ DB_AM_COMPENSATE,	"created by compensating transaction" },
+	{ DB_AM_CREATED,	"database created" },
+	{ DB_AM_CREATED_MSTR,	"encompassing file created" },
+	{ DB_AM_DBM_ERROR,	"dbm/ndbm error" },
+	{ DB_AM_DELIMITER,	"variable length" },
+	{ DB_AM_DIRTY,		"dirty reads" },
+	{ DB_AM_DISCARD,	"discard cached pages" },
+	{ DB_AM_DUP,		"duplicates" },
+	{ DB_AM_DUPSORT,	"sorted duplicates" },
+	{ DB_AM_ENCRYPT,	"encrypted" },
+	{ DB_AM_FIXEDLEN,	"fixed-length records" },
+	{ DB_AM_INMEM,		"in-memory" },
+	{ DB_AM_IN_RENAME,	"file is being renamed" },
+	{ DB_AM_NOT_DURABLE,	"changes not logged" },
+	{ DB_AM_OPEN_CALLED,	"open called" },
+	{ DB_AM_PAD,		"pad value" },
+	{ DB_AM_PGDEF,		"default page size" },
+	{ DB_AM_RDONLY,		"read-only" },
+	{ DB_AM_RECNUM,		"Btree record numbers" },
+	{ DB_AM_RECOVER,	"opened for recovery" },
+	{ DB_AM_RENUMBER,	"renumber" },
+	{ DB_AM_REPLICATION,	"replication file" },
+	{ DB_AM_REVSPLITOFF,	"no reverse splits" },
+	{ DB_AM_SECONDARY,	"secondary" },
+	{ DB_AM_SNAPSHOT,	"load on open" },
+	{ DB_AM_SUBDB,		"subdatabases" },
+	{ DB_AM_SWAP,		"needswap" },
+	{ DB_AM_TXN,		"transactional" },
+	{ DB_AM_VERIFYING,	"verifier" },
+	{ 0,			NULL }
+};
+
 /*
- * __db_inmemdbflags --
- *	Call a callback for printing or other handling of strings associated
- * with whatever in-memory DB structure flags are set.
+ * __db_get_flags_fn --
+ *	Return the __db_flags_fn array.
  *
- * PUBLIC: void __db_inmemdbflags __P((u_int32_t, void *,
- * PUBLIC:     void (*)(u_int32_t, const FN *, void *)));
+ * PUBLIC: const FN * __db_get_flags_fn __P((void));
  */
-void
-__db_inmemdbflags(flags, cookie, callback)
-	u_int32_t flags;
-	void *cookie;
-	void (*callback) __P((u_int32_t, const FN *, void *));
+const FN *
+__db_get_flags_fn()
 {
-	static const FN fn[] = {
-		{ DB_AM_CHKSUM,		"checksumming" },
-		{ DB_AM_CL_WRITER,	"client replica writer" },
-		{ DB_AM_COMPENSATE,	"created by compensating transaction" },
-		{ DB_AM_CREATED,	"database created" },
-		{ DB_AM_CREATED_MSTR,	"encompassing file created" },
-		{ DB_AM_DBM_ERROR,	"dbm/ndbm error" },
-		{ DB_AM_DELIMITER,	"variable length" },
-		{ DB_AM_DIRTY,		"dirty reads" },
-		{ DB_AM_DISCARD,	"discard cached pages" },
-		{ DB_AM_DUP,		"duplicates" },
-		{ DB_AM_DUPSORT,	"sorted duplicates" },
-		{ DB_AM_ENCRYPT,	"encrypted" },
-		{ DB_AM_FIXEDLEN,	"fixed-length records" },
-		{ DB_AM_INMEM,		"in-memory" },
-		{ DB_AM_IN_RENAME,	"file is being renamed" },
-		{ DB_AM_OPEN_CALLED,	"DB->open called" },
-		{ DB_AM_PAD,		"pad value" },
-		{ DB_AM_PGDEF,		"default page size" },
-		{ DB_AM_RDONLY,		"read-only" },
-		{ DB_AM_RECNUM,		"Btree record numbers" },
-		{ DB_AM_RECOVER,	"opened for recovery" },
-		{ DB_AM_RENUMBER,	"renumber" },
-		{ DB_AM_REVSPLITOFF,	"no reverse splits" },
-		{ DB_AM_SECONDARY,	"secondary" },
-		{ DB_AM_SNAPSHOT,	"load on open" },
-		{ DB_AM_SUBDB,		"subdatabases" },
-		{ DB_AM_SWAP,		"needswap" },
-		{ DB_AM_TXN,		"transactional" },
-		{ DB_AM_VERIFYING,	"verifier" },
-		{ 0,			NULL }
-	};
-
-	callback(flags, fn, cookie);
+	return (__db_flags_fn);
 }
 
 /*
@@ -156,57 +157,67 @@ __db_inmemdbflags(flags, cookie, callback)
  *	Print out the DB structure information.
  */
 static void
-__db_prdb(dbp, fp)
+__db_prdb(dbp, flags)
 	DB *dbp;
-	FILE *fp;
+	u_int32_t flags;
 {
+	DB_MSGBUF mb;
+	DB_ENV *dbenv;
 	BTREE *bt;
 	HASH *h;
 	QUEUE *q;
 
-	fprintf(fp,
-	    "In-memory DB structure:\n%s: %#lx",
+	dbenv = dbp->dbenv;
+
+	DB_MSGBUF_INIT(&mb);
+	__db_msg(dbenv, "In-memory DB structure:");
+	__db_msgadd(dbenv, &mb, "%s: %#lx",
 	    __db_dbtype_to_string(dbp->type), (u_long)dbp->flags);
-	__db_inmemdbflags(dbp->flags, fp, __db_prflags);
-	fprintf(fp, "\n");
+	__db_prflags(dbenv, &mb, dbp->flags, __db_flags_fn, " (", ")");
+	DB_MSGBUF_FLUSH(dbenv, &mb);
 
 	switch (dbp->type) {
 	case DB_BTREE:
 	case DB_RECNO:
 		bt = dbp->bt_internal;
-		fprintf(fp, "bt_meta: %lu bt_root: %lu\n",
+		__db_msg(dbenv, "bt_meta: %lu bt_root: %lu",
 		    (u_long)bt->bt_meta, (u_long)bt->bt_root);
-		fprintf(fp, "bt_maxkey: %lu bt_minkey: %lu\n",
+		__db_msg(dbenv, "bt_maxkey: %lu bt_minkey: %lu",
 		    (u_long)bt->bt_maxkey, (u_long)bt->bt_minkey);
-		fprintf(fp, "bt_compare: %#lx bt_prefix: %#lx\n",
-		    P_TO_ULONG(bt->bt_compare), P_TO_ULONG(bt->bt_prefix));
-		fprintf(fp, "bt_lpgno: %lu\n", (u_long)bt->bt_lpgno);
+		if (!LF_ISSET(DB_PR_RECOVERYTEST))
+			__db_msg(dbenv, "bt_compare: %#lx bt_prefix: %#lx",
+			    P_TO_ULONG(bt->bt_compare),
+			    P_TO_ULONG(bt->bt_prefix));
+		__db_msg(dbenv, "bt_lpgno: %lu", (u_long)bt->bt_lpgno);
 		if (dbp->type == DB_RECNO) {
-			fprintf(fp,
-		    "re_pad: %#lx re_delim: %#lx re_len: %lu re_source: %s\n",
+			__db_msg(dbenv,
+		    "re_pad: %#lx re_delim: %#lx re_len: %lu re_source: %s",
 			    (u_long)bt->re_pad, (u_long)bt->re_delim,
 			    (u_long)bt->re_len,
 			    bt->re_source == NULL ? "" : bt->re_source);
-			fprintf(fp, "re_modified: %d re_eof: %d re_last: %lu\n",
+			__db_msg(dbenv,
+			    "re_modified: %d re_eof: %d re_last: %lu",
 			    bt->re_modified, bt->re_eof, (u_long)bt->re_last);
 		}
 		break;
 	case DB_HASH:
 		h = dbp->h_internal;
-		fprintf(fp, "meta_pgno: %lu\n", (u_long)h->meta_pgno);
-		fprintf(fp, "h_ffactor: %lu\n", (u_long)h->h_ffactor);
-		fprintf(fp, "h_nelem: %lu\n", (u_long)h->h_nelem);
-		fprintf(fp, "h_hash: %#lx\n", P_TO_ULONG(h->h_hash));
+		__db_msg(dbenv, "meta_pgno: %lu", (u_long)h->meta_pgno);
+		__db_msg(dbenv, "h_ffactor: %lu", (u_long)h->h_ffactor);
+		__db_msg(dbenv, "h_nelem: %lu", (u_long)h->h_nelem);
+		if (!LF_ISSET(DB_PR_RECOVERYTEST))
+			__db_msg(dbenv, "h_hash: %#lx", P_TO_ULONG(h->h_hash));
 		break;
 	case DB_QUEUE:
 		q = dbp->q_internal;
-		fprintf(fp, "q_meta: %lu\n", (u_long)q->q_meta);
-		fprintf(fp, "q_root: %lu\n", (u_long)q->q_root);
-		fprintf(fp, "re_pad: %#lx re_len: %lu\n",
+		__db_msg(dbenv, "q_meta: %lu", (u_long)q->q_meta);
+		__db_msg(dbenv, "q_root: %lu", (u_long)q->q_root);
+		__db_msg(dbenv, "re_pad: %#lx re_len: %lu",
 		    (u_long)q->re_pad, (u_long)q->re_len);
-		fprintf(fp, "rec_page: %lu\n", (u_long)q->rec_page);
-		fprintf(fp, "page_ext: %lu\n", (u_long)q->page_ext);
+		__db_msg(dbenv, "rec_page: %lu", (u_long)q->rec_page);
+		__db_msg(dbenv, "page_ext: %lu", (u_long)q->page_ext);
 		break;
+	case DB_UNKNOWN:
 	default:
 		break;
 	}
@@ -217,9 +228,8 @@ __db_prdb(dbp, fp)
  *	Print out the entire tree.
  */
 static int
-__db_prtree(dbp, fp, flags)
+__db_prtree(dbp, flags)
 	DB *dbp;
-	FILE *fp;
 	u_int32_t flags;
 {
 	DB_MPOOLFILE *mpf;
@@ -230,18 +240,18 @@ __db_prtree(dbp, fp, flags)
 	mpf = dbp->mpf;
 
 	if (dbp->type == DB_QUEUE)
-		return (__db_prqueue(dbp, fp, flags));
+		return (__db_prqueue(dbp, flags));
 
 	/*
 	 * Find out the page number of the last page in the database, then
 	 * dump each page.
 	 */
-	mpf->last_pgno(mpf, &last);
+	__memp_last_pgno(mpf, &last);
 	for (i = 0; i <= last; ++i) {
-		if ((ret = mpf->get(mpf, &i, 0, &h)) != 0)
+		if ((ret = __memp_fget(mpf, &i, 0, &h)) != 0)
 			return (ret);
-		(void)__db_prpage(dbp, h, fp, flags);
-		if ((ret = mpf->put(mpf, h, 0)) != 0)
+		(void)__db_prpage(dbp, h, flags);
+		if ((ret = __memp_fput(mpf, h, 0)) != 0)
 			return (ret);
 	}
 
@@ -253,13 +263,14 @@ __db_prtree(dbp, fp, flags)
  *	Print out common metadata information.
  */
 static void
-__db_meta(dbp, dbmeta, fp, fn, flags)
+__db_meta(dbp, dbmeta, fn, flags)
 	DB *dbp;
 	DBMETA *dbmeta;
-	FILE *fp;
 	FN const *fn;
 	u_int32_t flags;
 {
+	DB_MSGBUF mb;
+	DB_ENV *dbenv;
 	DB_MPOOLFILE *mpf;
 	PAGE *h;
 	db_pgno_t pgno;
@@ -267,58 +278,62 @@ __db_meta(dbp, dbmeta, fp, fn, flags)
 	int cnt, ret;
 	const char *sep;
 
+	dbenv = dbp->dbenv;
 	mpf = dbp->mpf;
+	DB_MSGBUF_INIT(&mb);
 
-	fprintf(fp, "\tmagic: %#lx\n", (u_long)dbmeta->magic);
-	fprintf(fp, "\tversion: %lu\n", (u_long)dbmeta->version);
-	fprintf(fp, "\tpagesize: %lu\n", (u_long)dbmeta->pagesize);
-	fprintf(fp, "\ttype: %lu\n", (u_long)dbmeta->type);
-	fprintf(fp, "\tkeys: %lu\trecords: %lu\n",
+	__db_msg(dbenv, "\tmagic: %#lx", (u_long)dbmeta->magic);
+	__db_msg(dbenv, "\tversion: %lu", (u_long)dbmeta->version);
+	__db_msg(dbenv, "\tpagesize: %lu", (u_long)dbmeta->pagesize);
+	__db_msg(dbenv, "\ttype: %lu", (u_long)dbmeta->type);
+	__db_msg(dbenv, "\tkeys: %lu\trecords: %lu",
 	    (u_long)dbmeta->key_count, (u_long)dbmeta->record_count);
 
+	/*
+	 * If we're doing recovery testing, don't display the free list,
+	 * it may have changed and that makes the dump diff not work.
+	 */
 	if (!LF_ISSET(DB_PR_RECOVERYTEST)) {
-		/*
-		 * If we're doing recovery testing, don't display the free
-		 * list, it may have changed and that makes the dump diff
-		 * not work.
-		 */
-		fprintf(fp, "\tfree list: %lu", (u_long)dbmeta->free);
+		__db_msgadd(
+		    dbenv, &mb, "\tfree list: %lu", (u_long)dbmeta->free);
 		for (pgno = dbmeta->free,
 		    cnt = 0, sep = ", "; pgno != PGNO_INVALID;) {
-			if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0) {
-				fprintf(fp,
-			    "Unable to retrieve free-list page: %lu: %s\n",
+			if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0) {
+				DB_MSGBUF_FLUSH(dbenv, &mb);
+				__db_msg(dbenv,
+			    "Unable to retrieve free-list page: %lu: %s",
 				    (u_long)pgno, db_strerror(ret));
 				break;
 			}
 			pgno = h->next_pgno;
-			(void)mpf->put(mpf, h, 0);
-			fprintf(fp, "%s%lu", sep, (u_long)pgno);
+			(void)__memp_fput(mpf, h, 0);
+			__db_msgadd(dbenv, &mb, "%s%lu", sep, (u_long)pgno);
 			if (++cnt % 10 == 0) {
-				fprintf(fp, "\n");
+				DB_MSGBUF_FLUSH(dbenv, &mb);
 				cnt = 0;
 				sep = "\t";
 			} else
 				sep = ", ";
 		}
-		fprintf(fp, "\n");
-		fprintf(fp, "\tlast_pgno: %lu\n", (u_long)dbmeta->last_pgno);
+		DB_MSGBUF_FLUSH(dbenv, &mb);
+		__db_msg(dbenv, "\tlast_pgno: %lu", (u_long)dbmeta->last_pgno);
 	}
 
 	if (fn != NULL) {
-		fprintf(fp, "\tflags: %#lx", (u_long)dbmeta->flags);
-		__db_prflags(dbmeta->flags, fn, fp);
-		fprintf(fp, "\n");
+		DB_MSGBUF_FLUSH(dbenv, &mb);
+		__db_msgadd(dbenv, &mb, "\tflags: %#lx", (u_long)dbmeta->flags);
+		__db_prflags(dbenv, &mb, dbmeta->flags, fn, " (", ")");
 	}
 
-	fprintf(fp, "\tuid: ");
+	DB_MSGBUF_FLUSH(dbenv, &mb);
+	__db_msgadd(dbenv, &mb, "\tuid: ");
 	for (p = (u_int8_t *)dbmeta->uid,
 	    cnt = 0; cnt < DB_FILE_ID_LEN; ++cnt) {
-		fprintf(fp, "%x", *p++);
+		__db_msgadd(dbenv, &mb, "%x", *p++);
 		if (cnt < DB_FILE_ID_LEN - 1)
-			fprintf(fp, " ");
+			__db_msgadd(dbenv, &mb, " ");
 	}
-	fprintf(fp, "\n");
+	DB_MSGBUF_FLUSH(dbenv, &mb);
 }
 
 /*
@@ -326,30 +341,33 @@ __db_meta(dbp, dbmeta, fp, fn, flags)
  *	Print out the btree meta-data page.
  */
 static int
-__db_bmeta(dbp, fp, h, flags)
+__db_bmeta(dbp, h, flags)
 	DB *dbp;
-	FILE *fp;
 	BTMETA *h;
 	u_int32_t flags;
 {
-	static const FN mfn[] = {
+	static const FN fn[] = {
 		{ BTM_DUP,	"duplicates" },
 		{ BTM_RECNO,	"recno" },
 		{ BTM_RECNUM,	"btree:recnum" },
 		{ BTM_FIXEDLEN,	"recno:fixed-length" },
 		{ BTM_RENUMBER,	"recno:renumber" },
 		{ BTM_SUBDB,	"multiple-databases" },
+		{ BTM_DUPSORT,	"sorted duplicates" },
 		{ 0,		NULL }
 	};
+	DB_ENV *dbenv;
+
+	dbenv = dbp->dbenv;
 
-	__db_meta(dbp, (DBMETA *)h, fp, mfn, flags);
+	__db_meta(dbp, (DBMETA *)h, fn, flags);
 
-	fprintf(fp, "\tmaxkey: %lu minkey: %lu\n",
+	__db_msg(dbenv, "\tmaxkey: %lu minkey: %lu",
 	    (u_long)h->maxkey, (u_long)h->minkey);
 	if (dbp->type == DB_RECNO)
-		fprintf(fp, "\tre_len: %#lx re_pad: %lu\n",
+		__db_msg(dbenv, "\tre_len: %#lx re_pad: %#lx",
 		    (u_long)h->re_len, (u_long)h->re_pad);
-	fprintf(fp, "\troot: %lu\n", (u_long)h->root);
+	__db_msg(dbenv, "\troot: %lu", (u_long)h->root);
 
 	return (0);
 }
@@ -359,31 +377,36 @@ __db_bmeta(dbp, fp, h, flags)
  *	Print out the hash meta-data page.
  */
 static int
-__db_hmeta(dbp, fp, h, flags)
+__db_hmeta(dbp, h, flags)
 	DB *dbp;
-	FILE *fp;
 	HMETA *h;
 	u_int32_t flags;
 {
-	static const FN mfn[] = {
-		{ DB_HASH_DUP,	 "duplicates" },
-		{ DB_HASH_SUBDB, "multiple-databases" },
-		{ 0,		 NULL }
+	DB_MSGBUF mb;
+	static const FN fn[] = {
+		{ DB_HASH_DUP,		"duplicates" },
+		{ DB_HASH_SUBDB,	"multiple-databases" },
+		{ DB_HASH_DUPSORT,	"sorted duplicates" },
+		{ 0,			NULL }
 	};
+	DB_ENV *dbenv;
 	int i;
 
-	__db_meta(dbp, (DBMETA *)h, fp, mfn, flags);
+	dbenv = dbp->dbenv;
+	DB_MSGBUF_INIT(&mb);
 
-	fprintf(fp, "\tmax_bucket: %lu\n", (u_long)h->max_bucket);
-	fprintf(fp, "\thigh_mask: %#lx\n", (u_long)h->high_mask);
-	fprintf(fp, "\tlow_mask:  %#lx\n", (u_long)h->low_mask);
-	fprintf(fp, "\tffactor: %lu\n", (u_long)h->ffactor);
-	fprintf(fp, "\tnelem: %lu\n", (u_long)h->nelem);
-	fprintf(fp, "\th_charkey: %#lx\n", (u_long)h->h_charkey);
-	fprintf(fp, "\tspare points: ");
+	__db_meta(dbp, (DBMETA *)h, fn, flags);
+
+	__db_msg(dbenv, "\tmax_bucket: %lu", (u_long)h->max_bucket);
+	__db_msg(dbenv, "\thigh_mask: %#lx", (u_long)h->high_mask);
+	__db_msg(dbenv, "\tlow_mask:  %#lx", (u_long)h->low_mask);
+	__db_msg(dbenv, "\tffactor: %lu", (u_long)h->ffactor);
+	__db_msg(dbenv, "\tnelem: %lu", (u_long)h->nelem);
+	__db_msg(dbenv, "\th_charkey: %#lx", (u_long)h->h_charkey);
+	__db_msgadd(dbenv, &mb, "\tspare points: ");
 	for (i = 0; i < NCACHED; i++)
-		fprintf(fp, "%lu ", (u_long)h->spares[i]);
-	fprintf(fp, "\n");
+		__db_msgadd(dbenv, &mb, "%lu ", (u_long)h->spares[i]);
+	DB_MSGBUF_FLUSH(dbenv, &mb);
 
 	return (0);
 }
@@ -393,20 +416,23 @@ __db_hmeta(dbp, fp, h, flags)
  *	Print out the queue meta-data page.
  */
 static int
-__db_qmeta(dbp, fp, h, flags)
+__db_qmeta(dbp, h, flags)
 	DB *dbp;
-	FILE *fp;
 	QMETA *h;
 	u_int32_t flags;
 {
-	__db_meta(dbp, (DBMETA *)h, fp, NULL, flags);
+	DB_ENV *dbenv;
+
+	dbenv = dbp->dbenv;
 
-	fprintf(fp, "\tfirst_recno: %lu\n", (u_long)h->first_recno);
-	fprintf(fp, "\tcur_recno: %lu\n", (u_long)h->cur_recno);
-	fprintf(fp, "\tre_len: %#lx re_pad: %lu\n",
+	__db_meta(dbp, (DBMETA *)h, NULL, flags);
+
+	__db_msg(dbenv, "\tfirst_recno: %lu", (u_long)h->first_recno);
+	__db_msg(dbenv, "\tcur_recno: %lu", (u_long)h->cur_recno);
+	__db_msg(dbenv, "\tre_len: %#lx re_pad: %lu",
 	    (u_long)h->re_len, (u_long)h->re_pad);
-	fprintf(fp, "\trec_page: %lu\n", (u_long)h->rec_page);
-	fprintf(fp, "\tpage_ext: %lu\n", (u_long)h->page_ext);
+	__db_msg(dbenv, "\trec_page: %lu", (u_long)h->rec_page);
+	__db_msg(dbenv, "\tpage_ext: %lu", (u_long)h->page_ext);
 
 	return (0);
 }
@@ -415,13 +441,12 @@ __db_qmeta(dbp, fp, h, flags)
  * __db_prnpage
  *	-- Print out a specific page.
  *
- * PUBLIC: int __db_prnpage __P((DB *, db_pgno_t, FILE *));
+ * PUBLIC: int __db_prnpage __P((DB *, db_pgno_t));
  */
 int
-__db_prnpage(dbp, pgno, fp)
+__db_prnpage(dbp, pgno)
 	DB *dbp;
 	db_pgno_t pgno;
-	FILE *fp;
 {
 	DB_MPOOLFILE *mpf;
 	PAGE *h;
@@ -429,12 +454,12 @@ __db_prnpage(dbp, pgno, fp)
 
 	mpf = dbp->mpf;
 
-	if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
+	if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
 		return (ret);
 
-	ret = __db_prpage(dbp, h, fp, DB_PR_PAGE);
+	ret = __db_prpage(dbp, h, DB_PR_PAGE);
 
-	if ((t_ret = mpf->put(mpf, h, 0)) != 0 && ret == 0)
+	if ((t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
 		ret = t_ret;
 
 	return (ret);
@@ -444,17 +469,18 @@ __db_prnpage(dbp, pgno, fp)
  * __db_prpage
  *	-- Print out a page.
  *
- * PUBLIC: int __db_prpage __P((DB *, PAGE *, FILE *, u_int32_t));
+ * PUBLIC: int __db_prpage __P((DB *, PAGE *, u_int32_t));
  */
 int
-__db_prpage(dbp, h, fp, flags)
+__db_prpage(dbp, h, flags)
 	DB *dbp;
 	PAGE *h;
-	FILE *fp;
 	u_int32_t flags;
 {
 	BINTERNAL *bi;
 	BKEYDATA *bk;
+	DB_ENV *dbenv;
+	DB_MSGBUF mb;
 	HOFFPAGE a_hkd;
 	QAMDATA *qp, *qep;
 	RINTERNAL *ri;
@@ -467,6 +493,9 @@ __db_prpage(dbp, h, fp, flags)
 	const char *s;
 	void *sp;
 
+	dbenv = dbp->dbenv;
+	DB_MSGBUF_INIT(&mb);
+
 	/*
 	 * If we're doing recovery testing and this page is P_INVALID,
 	 * assume it's a page that's on the free list, and don't display it.
@@ -474,9 +503,8 @@ __db_prpage(dbp, h, fp, flags)
 	if (LF_ISSET(DB_PR_RECOVERYTEST) && TYPE(h) == P_INVALID)
 		return (0);
 
-	s = __db_pagetype_to_string(TYPE(h));
-	if (s == NULL) {
-		fprintf(fp, "ILLEGAL PAGE TYPE: page: %lu type: %lu\n",
+	if ((s = __db_pagetype_to_string(TYPE(h))) == NULL) {
+		__db_msg(dbenv, "ILLEGAL PAGE TYPE: page: %lu type: %lu",
 		    (u_long)h->pgno, (u_long)TYPE(h));
 		return (1);
 	}
@@ -490,27 +518,28 @@ __db_prpage(dbp, h, fp, flags)
 	pagesize = (u_int32_t)dbp->mpf->mfp->stat.st_pagesize;
 
 	/* Page number, page type. */
-	fprintf(fp, "page %lu: %s level: %lu",
+	__db_msgadd(dbenv, &mb, "page %lu: %s level: %lu",
 	    (u_long)h->pgno, s, (u_long)h->level);
 
 	/* Record count. */
 	if (TYPE(h) == P_IBTREE ||
 	    TYPE(h) == P_IRECNO || (TYPE(h) == P_LRECNO &&
 	    h->pgno == ((BTREE *)dbp->bt_internal)->bt_root))
-		fprintf(fp, " records: %lu", (u_long)RE_NREC(h));
+		__db_msgadd(dbenv, &mb, " records: %lu", (u_long)RE_NREC(h));
 
 	/* LSN. */
 	if (!LF_ISSET(DB_PR_RECOVERYTEST))
-		fprintf(fp, " (lsn.file: %lu lsn.offset: %lu)\n",
+		__db_msgadd(dbenv, &mb, " (lsn.file: %lu lsn.offset: %lu)",
 		    (u_long)LSN(h).file, (u_long)LSN(h).offset);
+	DB_MSGBUF_FLUSH(dbenv, &mb);
 
 	switch (TYPE(h)) {
 	case P_BTREEMETA:
-		return (__db_bmeta(dbp, fp, (BTMETA *)h, flags));
+		return (__db_bmeta(dbp, (BTMETA *)h, flags));
 	case P_HASHMETA:
-		return (__db_hmeta(dbp, fp, (HMETA *)h, flags));
+		return (__db_hmeta(dbp, (HMETA *)h, flags));
 	case P_QAMMETA:
-		return (__db_qmeta(dbp, fp, (QMETA *)h, flags));
+		return (__db_qmeta(dbp, (QMETA *)h, flags));
 	case P_QAMDATA:				/* Should be meta->start. */
 		if (!LF_ISSET(DB_PR_PAGE))
 			return (0);
@@ -524,33 +553,37 @@ __db_prpage(dbp, h, fp, flags)
 			if (!F_ISSET(qp, QAM_SET))
 				continue;
 
-			fprintf(fp, "%s",
+			__db_msgadd(dbenv, &mb, "%s",
 			    F_ISSET(qp, QAM_VALID) ? "\t" : "       D");
-			fprintf(fp, "[%03lu] %4lu ", (u_long)recno,
+			__db_msgadd(dbenv, &mb, "[%03lu] %4lu ", (u_long)recno,
 			    (u_long)((u_int8_t *)qp - (u_int8_t *)h));
-			__db_pr(qp->data, qlen, fp);
+			__db_pr(dbenv, &mb, qp->data, qlen);
 		}
 		return (0);
+	default:
+		break;
 	}
 
 	/* LSN. */
 	if (LF_ISSET(DB_PR_RECOVERYTEST))
-		fprintf(fp, " (lsn.file: %lu lsn.offset: %lu)\n",
+		__db_msg(dbenv, " (lsn.file: %lu lsn.offset: %lu)",
 		    (u_long)LSN(h).file, (u_long)LSN(h).offset);
 
 	s = "\t";
 	if (TYPE(h) != P_IBTREE && TYPE(h) != P_IRECNO) {
-		fprintf(fp, "%sprev: %4lu next: %4lu",
+		__db_msgadd(dbenv, &mb, "%sprev: %4lu next: %4lu",
 		    s, (u_long)PREV_PGNO(h), (u_long)NEXT_PGNO(h));
 		s = " ";
 	}
 	if (TYPE(h) == P_OVERFLOW) {
-		fprintf(fp, "%sref cnt: %4lu ", s, (u_long)OV_REF(h));
-		__db_pr((u_int8_t *)h + P_OVERHEAD(dbp), OV_LEN(h), fp);
+		__db_msgadd(dbenv, &mb,
+		    "%sref cnt: %4lu ", s, (u_long)OV_REF(h));
+		__db_pr(dbenv, &mb, (u_int8_t *)h + P_OVERHEAD(dbp), OV_LEN(h));
 		return (0);
 	}
-	fprintf(fp, "%sentries: %4lu", s, (u_long)NUM_ENT(h));
-	fprintf(fp, " offset: %4lu\n", (u_long)HOFFSET(h));
+	__db_msgadd(dbenv, &mb, "%sentries: %4lu", s, (u_long)NUM_ENT(h));
+	__db_msgadd(dbenv, &mb, " offset: %4lu", (u_long)HOFFSET(h));
+	DB_MSGBUF_FLUSH(dbenv, &mb);
 
 	if (TYPE(h) == P_INVALID || !LF_ISSET(DB_PR_PAGE))
 		return (0);
@@ -558,11 +591,11 @@ __db_prpage(dbp, h, fp, flags)
 	ret = 0;
 	inp = P_INP(dbp, h);
 	for (i = 0; i < NUM_ENT(h); i++) {
-		if ((db_alignp_t)(P_ENTRY(dbp, h, i) - (u_int8_t *)h) <
-		    (db_alignp_t)(P_OVERHEAD(dbp)) ||
+		if ((uintptr_t)(P_ENTRY(dbp, h, i) - (u_int8_t *)h) <
+		    (uintptr_t)(P_OVERHEAD(dbp)) ||
 		    (size_t)(P_ENTRY(dbp, h, i) - (u_int8_t *)h) >= pagesize) {
-			fprintf(fp,
-			    "ILLEGAL PAGE OFFSET: indx: %lu of %lu\n",
+			__db_msg(dbenv,
+			    "ILLEGAL PAGE OFFSET: indx: %lu of %lu",
 			    (u_long)i, (u_long)inp[i]);
 			ret = EINVAL;
 			continue;
@@ -585,13 +618,11 @@ __db_prpage(dbp, h, fp, flags)
 			deleted = B_DISSET(GET_BKEYDATA(dbp, h, i)->type);
 			break;
 		default:
-			fprintf(fp,
-			    "ILLEGAL PAGE ITEM: %lu\n", (u_long)TYPE(h));
-			ret = EINVAL;
-			continue;
+			goto type_err;
 		}
-		fprintf(fp, "%s", deleted ? "       D" : "\t");
-		fprintf(fp, "[%03lu] %4lu ", (u_long)i, (u_long)inp[i]);
+		__db_msgadd(dbenv, &mb, "%s", deleted ? "       D" : "\t");
+		__db_msgadd(
+		    dbenv, &mb, "[%03lu] %4lu ", (u_long)i, (u_long)inp[i]);
 		switch (TYPE(h)) {
 		case P_HASH:
 			hk = sp;
@@ -599,8 +630,9 @@ __db_prpage(dbp, h, fp, flags)
 			case H_OFFDUP:
 				memcpy(&pgno,
 				    HOFFDUP_PGNO(hk), sizeof(db_pgno_t));
-				fprintf(fp,
-				    "%4lu [offpage dups]\n", (u_long)pgno);
+				__db_msgadd(dbenv, &mb,
+				    "%4lu [offpage dups]", (u_long)pgno);
+				DB_MSGBUF_FLUSH(dbenv, &mb);
 				break;
 			case H_DUPLICATE:
 				/*
@@ -614,44 +646,54 @@ __db_prpage(dbp, h, fp, flags)
 				else
 					len = 1;
 
-				fprintf(fp, "Duplicates:\n");
+				__db_msgadd(dbenv, &mb, "Duplicates:");
+				DB_MSGBUF_FLUSH(dbenv, &mb);
 				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");
-					__db_pr(p, dlen, fp);
+					__db_msgadd(dbenv, &mb, "\t\t");
+					__db_pr(dbenv, &mb, p, dlen);
 					p += sizeof(db_indx_t) + dlen;
 				}
 				break;
 			case H_KEYDATA:
-				__db_pr(HKEYDATA_DATA(hk),
+				__db_pr(dbenv, &mb, HKEYDATA_DATA(hk),
 				    LEN_HKEYDATA(dbp, h, i == 0 ?
-				    pagesize : 0, i), fp);
+				    pagesize : 0, i));
 				break;
 			case H_OFFPAGE:
 				memcpy(&a_hkd, hk, HOFFPAGE_SIZE);
-				fprintf(fp,
-				    "overflow: total len: %4lu page: %4lu\n",
+				__db_msgadd(dbenv, &mb,
+				    "overflow: total len: %4lu page: %4lu",
 				    (u_long)a_hkd.tlen, (u_long)a_hkd.pgno);
+				DB_MSGBUF_FLUSH(dbenv, &mb);
+				break;
+			default:
+				DB_MSGBUF_FLUSH(dbenv, &mb);
+				__db_msg(dbenv, "ILLEGAL HASH PAGE TYPE: %lu",
+				    (u_long)HPAGE_PTYPE(hk));
+				ret = EINVAL;
 				break;
 			}
 			break;
 		case P_IBTREE:
 			bi = sp;
-			fprintf(fp, "count: %4lu pgno: %4lu type: %4lu",
+			__db_msgadd(dbenv, &mb,
+			    "count: %4lu pgno: %4lu type: %4lu",
 			    (u_long)bi->nrecs, (u_long)bi->pgno,
 			    (u_long)bi->type);
 			switch (B_TYPE(bi->type)) {
 			case B_KEYDATA:
-				__db_pr(bi->data, bi->len, fp);
+				__db_pr(dbenv, &mb, bi->data, bi->len);
 				break;
 			case B_DUPLICATE:
 			case B_OVERFLOW:
-				__db_proff(bi->data, fp);
+				__db_proff(dbenv, &mb, bi->data);
 				break;
 			default:
-				fprintf(fp, "ILLEGAL BINTERNAL TYPE: %lu\n",
+				DB_MSGBUF_FLUSH(dbenv, &mb);
+				__db_msg(dbenv, "ILLEGAL BINTERNAL TYPE: %lu",
 				    (u_long)B_TYPE(bi->type));
 				ret = EINVAL;
 				break;
@@ -659,8 +701,9 @@ __db_prpage(dbp, h, fp, flags)
 			break;
 		case P_IRECNO:
 			ri = sp;
-			fprintf(fp, "entries %4lu pgno %4lu\n",
+			__db_msgadd(dbenv, &mb, "entries %4lu pgno %4lu",
 			    (u_long)ri->nrecs, (u_long)ri->pgno);
+			DB_MSGBUF_FLUSH(dbenv, &mb);
 			break;
 		case P_LBTREE:
 		case P_LDUP:
@@ -668,23 +711,29 @@ __db_prpage(dbp, h, fp, flags)
 			bk = sp;
 			switch (B_TYPE(bk->type)) {
 			case B_KEYDATA:
-				__db_pr(bk->data, bk->len, fp);
+				__db_pr(dbenv, &mb, bk->data, bk->len);
 				break;
 			case B_DUPLICATE:
 			case B_OVERFLOW:
-				__db_proff(bk, fp);
+				__db_proff(dbenv, &mb, bk);
 				break;
 			default:
-				fprintf(fp,
-			    "ILLEGAL DUPLICATE/LBTREE/LRECNO TYPE: %lu\n",
+				DB_MSGBUF_FLUSH(dbenv, &mb);
+				__db_msg(dbenv,
+			    "ILLEGAL DUPLICATE/LBTREE/LRECNO TYPE: %lu",
 				    (u_long)B_TYPE(bk->type));
 				ret = EINVAL;
 				break;
 			}
 			break;
+		default:
+type_err:		DB_MSGBUF_FLUSH(dbenv, &mb);
+			__db_msg(dbenv,
+			    "ILLEGAL PAGE TYPE: %lu", (u_long)TYPE(h));
+			ret = EINVAL;
+			continue;
 		}
 	}
-	(void)fflush(fp);
 	return (ret);
 }
 
@@ -692,141 +741,30 @@ __db_prpage(dbp, h, fp, flags)
  * __db_pr --
  *	Print out a data element.
  *
- * PUBLIC: void __db_pr __P((u_int8_t *, u_int32_t, FILE *));
+ * PUBLIC: void __db_pr __P((DB_ENV *, DB_MSGBUF *, u_int8_t *, u_int32_t));
  */
 void
-__db_pr(p, len, fp)
+__db_pr(dbenv, mbp, p, len)
+	DB_ENV *dbenv;
+	DB_MSGBUF *mbp;
 	u_int8_t *p;
 	u_int32_t len;
-	FILE *fp;
 {
-	u_int lastch;
-	int i;
+	u_int32_t i;
 
-	fprintf(fp, "len: %3lu", (u_long)len);
-	lastch = '.';
+	__db_msgadd(dbenv, mbp, "len: %3lu", (u_long)len);
 	if (len != 0) {
-		fprintf(fp, " data: ");
+		__db_msgadd(dbenv, mbp, " data: ");
 		for (i = len <= 20 ? len : 20; i > 0; --i, ++p) {
-			lastch = *p;
 			if (isprint((int)*p) || *p == '\n')
-				fprintf(fp, "%c", *p);
+				__db_msgadd(dbenv, mbp, "%c", *p);
 			else
-				fprintf(fp, "0x%.2x", (u_int)*p);
-		}
-		if (len > 20) {
-			fprintf(fp, "...");
-			lastch = '.';
+				__db_msgadd(dbenv, mbp, "%#.2x", (u_int)*p);
 		}
+		if (len > 20)
+			__db_msgadd(dbenv, mbp, "...");
 	}
-	if (lastch != '\n')
-		fprintf(fp, "\n");
-}
-
-/*
- * __db_prdbt --
- *	Print out a DBT data element.
- *
- * PUBLIC: int __db_prdbt __P((DBT *, int, const char *, void *,
- * PUBLIC:     int (*)(void *, const void *), int, VRFY_DBINFO *));
- */
-int
-__db_prdbt(dbtp, checkprint, prefix, handle, callback, is_recno, vdp)
-	DBT *dbtp;
-	int checkprint;
-	const char *prefix;
-	void *handle;
-	int (*callback) __P((void *, const void *));
-	int is_recno;
-	VRFY_DBINFO *vdp;
-{
-	static const char hex[] = "0123456789abcdef";
-	db_recno_t recno;
-	u_int32_t len;
-	int ret;
-#define	DBTBUFLEN	100
-	char *p, *hp, buf[DBTBUFLEN], hbuf[DBTBUFLEN];
-
-	if (vdp != NULL) {
-		/*
-		 * If vdp is non-NULL, we might be the first key in the
-		 * "fake" subdatabase used for key/data pairs we can't
-		 * associate with a known subdb.
-		 *
-		 * Check and clear the SALVAGE_PRINTHEADER flag;  if
-		 * it was set, print a subdatabase header.
-		 */
-		if (F_ISSET(vdp, SALVAGE_PRINTHEADER))
-			(void)__db_prheader(NULL, "__OTHER__", 0, 0,
-			    handle, callback, vdp, 0);
-		F_CLR(vdp, SALVAGE_PRINTHEADER);
-		F_SET(vdp, SALVAGE_PRINTFOOTER);
-
-		/*
-		 * Even if the printable flag wasn't set by our immediate
-		 * caller, it may be set on a salvage-wide basis.
-		 */
-		if (F_ISSET(vdp, SALVAGE_PRINTABLE))
-			checkprint = 1;
-	}
-
-	/*
-	 * !!!
-	 * This routine is the routine that dumps out items in the format
-	 * used by db_dump(1) and db_load(1).  This means that the format
-	 * cannot change.
-	 */
-	if (prefix != NULL && (ret = callback(handle, prefix)) != 0)
-		return (ret);
-	if (is_recno) {
-		/*
-		 * We're printing a record number, and this has to be done
-		 * in a platform-independent way.  So we use the numeral in
-		 * straight ASCII.
-		 */
-		(void)__ua_memcpy(&recno, dbtp->data, sizeof(recno));
-		snprintf(buf, DBTBUFLEN, "%lu", (u_long)recno);
-
-		/* If we're printing data as hex, print keys as hex too. */
-		if (!checkprint) {
-			for (len = (u_int32_t)strlen(buf), p = buf, hp = hbuf;
-			    len-- > 0; ++p) {
-				*hp++ = hex[(u_int8_t)(*p & 0xf0) >> 4];
-				*hp++ = hex[*p & 0x0f];
-			}
-			*hp = '\0';
-			ret = callback(handle, hbuf);
-		} else
-			ret = callback(handle, buf);
-
-		if (ret != 0)
-			return (ret);
-	} else if (checkprint) {
-		for (len = dbtp->size, p = dbtp->data; len--; ++p)
-			if (isprint((int)*p)) {
-				if (*p == '\\' &&
-				    (ret = callback(handle, "\\")) != 0)
-					return (ret);
-				snprintf(buf, DBTBUFLEN, "%c", *p);
-				if ((ret = callback(handle, buf)) != 0)
-					return (ret);
-			} else {
-				snprintf(buf, DBTBUFLEN, "\\%c%c",
-				    hex[(u_int8_t)(*p & 0xf0) >> 4],
-				    hex[*p & 0x0f]);
-				if ((ret = callback(handle, buf)) != 0)
-					return (ret);
-			}
-	} else
-		for (len = dbtp->size, p = dbtp->data; len--; ++p) {
-			snprintf(buf, DBTBUFLEN, "%c%c",
-			    hex[(u_int8_t)(*p & 0xf0) >> 4],
-			    hex[*p & 0x0f]);
-			if ((ret = callback(handle, buf)) != 0)
-				return (ret);
-		}
-
-	return (callback(handle, "\n"));
+	DB_MSGBUF_FLUSH(dbenv, mbp);
 }
 
 /*
@@ -834,80 +772,109 @@ __db_prdbt(dbtp, checkprint, prefix, handle, callback, is_recno, vdp)
  *	Print out an off-page element.
  */
 static void
-__db_proff(vp, fp)
+__db_proff(dbenv, mbp, vp)
+	DB_ENV *dbenv;
+	DB_MSGBUF *mbp;
 	void *vp;
-	FILE *fp;
 {
 	BOVERFLOW *bo;
 
 	bo = vp;
 	switch (B_TYPE(bo->type)) {
 	case B_OVERFLOW:
-		fprintf(fp, "overflow: total len: %4lu page: %4lu\n",
+		__db_msgadd(dbenv, mbp, "overflow: total len: %4lu page: %4lu",
 		    (u_long)bo->tlen, (u_long)bo->pgno);
 		break;
 	case B_DUPLICATE:
-		fprintf(fp, "duplicate: page: %4lu\n", (u_long)bo->pgno);
+		__db_msgadd(
+		    dbenv, mbp, "duplicate: page: %4lu", (u_long)bo->pgno);
+		break;
+	default:
+		/* NOTREACHED */
 		break;
 	}
+	DB_MSGBUF_FLUSH(dbenv, mbp);
 }
 
 /*
  * __db_prflags --
  *	Print out flags values.
  *
- * PUBLIC: void __db_prflags __P((u_int32_t, const FN *, void *));
+ * PUBLIC: void __db_prflags __P((DB_ENV *, DB_MSGBUF *,
+ * PUBLIC:     u_int32_t, const FN *, const char *, const char *));
  */
 void
-__db_prflags(flags, fn, vfp)
+__db_prflags(dbenv, mbp, flags, fn, prefix, suffix)
+	DB_ENV *dbenv;
+	DB_MSGBUF *mbp;
 	u_int32_t flags;
 	FN const *fn;
-	void *vfp;
+	const char *prefix, *suffix;
 {
-	FILE *fp;
+	DB_MSGBUF mb;
 	const FN *fnp;
-	int found;
+	int found, standalone;
 	const char *sep;
 
 	/*
-	 * We pass the FILE * through a void * so that we can use
-	 * this function as as a callback.
+	 * If it's a standalone message, output the suffix (which will be the
+	 * label), regardless of whether we found anything or not, and flush
+	 * the line.
 	 */
-	fp = (FILE *)vfp;
+	if (mbp == NULL) {
+		standalone = 1;
+		mbp = &mb;
+		DB_MSGBUF_INIT(mbp);
+	} else
+		standalone = 0;
 
-	sep = " (";
+	sep = prefix == NULL ? "" : prefix;
 	for (found = 0, fnp = fn; fnp->mask != 0; ++fnp)
 		if (LF_ISSET(fnp->mask)) {
-			fprintf(fp, "%s%s", sep, fnp->name);
+			__db_msgadd(dbenv, mbp, "%s%s", sep, fnp->name);
 			sep = ", ";
 			found = 1;
 		}
-	if (found)
-		fprintf(fp, ")");
+
+	if ((standalone || found) && suffix != NULL)
+		__db_msgadd(dbenv, mbp, "%s", suffix);
+	if (standalone)
+		DB_MSGBUF_FLUSH(dbenv, mbp);
 }
 
 /*
- * __db_dbtype_to_string --
- *	Return the name of the database type.
- * PUBLIC: const char * __db_dbtype_to_string __P((DBTYPE));
+ * __db_lockmode_to_string --
+ *	Return the name of the lock mode.
+ *
+ * PUBLIC: const char * __db_lockmode_to_string __P((db_lockmode_t));
  */
 const char *
-__db_dbtype_to_string(type)
-	DBTYPE type;
+__db_lockmode_to_string(mode)
+	db_lockmode_t mode;
 {
-	switch (type) {
-	case DB_BTREE:
-		return ("btree");
-	case DB_HASH:
-		return ("hash");
-	case DB_RECNO:
-		return ("recno");
-	case DB_QUEUE:
-		return ("queue");
+	switch (mode) {
+	case DB_LOCK_NG:
+		return ("Not granted");
+	case DB_LOCK_READ:
+		return ("Shared/read");
+	case DB_LOCK_WRITE:
+		return ("Exclusive/write");
+	case DB_LOCK_WAIT:
+		return ("Wait for event");
+	case DB_LOCK_IWRITE:
+		return ("Intent exclusive/write");
+	case DB_LOCK_IREAD:
+		return ("Intent shared/read");
+	case DB_LOCK_IWR:
+		return ("Intent to read/write");
+	case DB_LOCK_DIRTY:
+		return ("Dirty read");
+	case DB_LOCK_WWRITE:
+		return ("Was written");
 	default:
-		return ("UNKNOWN TYPE");
+		break;
 	}
-	/* NOTREACHED */
+	return ("UNKNOWN LOCK MODE");
 }
 
 /*
@@ -965,52 +932,307 @@ __db_pagetype_to_string(type)
 	return (s);
 }
 
+#else /* !HAVE_STATISTICS */
+
+/*
+ * __db_dumptree --
+ *	Dump the tree to a file.
+ *
+ * PUBLIC: int __db_dumptree __P((DB *, char *, char *));
+ */
+int
+__db_dumptree(dbp, op, name)
+	DB *dbp;
+	char *op, *name;
+{
+	COMPQUIET(op, NULL);
+	COMPQUIET(name, NULL);
+
+	return (__db_stat_not_built(dbp->dbenv));
+}
+
+/*
+ * __db_get_flags_fn --
+ *	Return the __db_flags_fn array.
+ *
+ * PUBLIC: const FN * __db_get_flags_fn __P((void));
+ */
+const FN *
+__db_get_flags_fn()
+{
+	static const FN __db_flags_fn[] = {
+		{ 0,	NULL }
+	};
+
+	/*
+	 * !!!
+	 * The Tcl API uses this interface, stub it off.
+	 */
+	return (__db_flags_fn);
+}
+#endif
+
+/*
+ * __db_dump_pp --
+ *	DB->dump pre/post processing.
+ *
+ * PUBLIC: int __db_dump_pp __P((DB *, const char *,
+ * PUBLIC:     int (*)(void *, const void *), void *, int, int));
+ */
+int
+__db_dump_pp(dbp, subname, callback, handle, pflag, keyflag)
+	DB *dbp;
+	const char *subname;
+	int (*callback) __P((void *, const void *));
+	void *handle;
+	int pflag, keyflag;
+{
+	DB_ENV *dbenv;
+	int handle_check, ret;
+
+	dbenv = dbp->dbenv;
+
+	PANIC_CHECK(dbenv);
+	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->dump");
+
+	/* Check for replication block. */
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, 1)) != 0)
+		return (ret);
+
+	ret = __db_dump(dbp, subname, callback, handle, pflag, keyflag);
+
+	/* Release replication block. */
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
+
+	return (0);
+}
+
+/*
+ * __db_dump --
+ *	DB->dump.
+ *
+ * PUBLIC: int __db_dump __P((DB *, const char *,
+ * PUBLIC:     int (*)(void *, const void *), void *, int, int));
+ */
+int
+__db_dump(dbp, subname, callback, handle, pflag, keyflag)
+	DB *dbp;
+	const char *subname;
+	int (*callback) __P((void *, const void *));
+	void *handle;
+	int pflag, keyflag;
+{
+	DB_ENV *dbenv;
+	DBC *dbcp;
+	DBT key, data;
+	DBT keyret, dataret;
+	db_recno_t recno;
+	int is_recno, ret, t_ret;
+	void *pointer;
+
+	dbenv = dbp->dbenv;
+
+	if ((ret = __db_prheader(
+	    dbp, subname, pflag, keyflag, handle, callback, NULL, 0)) != 0)
+		return (ret);
+
+	/*
+	 * Get a cursor and step through the database, printing out each
+	 * key/data pair.
+	 */
+	if ((ret = __db_cursor(dbp, NULL, &dbcp, 0)) != 0)
+		return (ret);
+
+	memset(&key, 0, sizeof(key));
+	memset(&data, 0, sizeof(data));
+	if ((ret = __os_malloc(dbenv, 1024 * 1024, &data.data)) != 0)
+		goto err;
+	data.ulen = 1024 * 1024;
+	data.flags = DB_DBT_USERMEM;
+	is_recno = (dbp->type == DB_RECNO || dbp->type == DB_QUEUE);
+	keyflag = is_recno ? keyflag : 1;
+	if (is_recno) {
+		keyret.data = &recno;
+		keyret.size = sizeof(recno);
+	}
+
+retry: while ((ret =
+	    __db_c_get(dbcp, &key, &data, DB_NEXT | DB_MULTIPLE_KEY)) == 0) {
+		DB_MULTIPLE_INIT(pointer, &data);
+		for (;;) {
+			if (is_recno)
+				DB_MULTIPLE_RECNO_NEXT(pointer, &data,
+				    recno, dataret.data, dataret.size);
+			else
+				DB_MULTIPLE_KEY_NEXT(pointer,
+				    &data, keyret.data,
+				    keyret.size, dataret.data, dataret.size);
+
+			if (dataret.data == NULL)
+				break;
+
+			if ((keyflag &&
+			    (ret = __db_prdbt(&keyret, pflag, " ",
+			    handle, callback, is_recno)) != 0) ||
+			    (ret = __db_prdbt(&dataret, pflag, " ",
+			    handle, callback, 0)) != 0)
+				goto err;
+		}
+	}
+	if (ret == DB_BUFFER_SMALL) {
+		data.size = (u_int32_t)DB_ALIGN(data.size, 1024);
+		if ((ret = __os_realloc(dbenv, data.size, &data.data)) != 0)
+			goto err;
+		data.ulen = data.size;
+		goto retry;
+	}
+
+	(void)__db_prfooter(handle, callback);
+
+err:	if ((t_ret = __db_c_close(dbcp)) != 0 && ret == 0)
+		ret = t_ret;
+	if (data.data != NULL)
+		__os_free(dbenv, data.data);
+
+	return (ret);
+}
+
+/*
+ * __db_prdbt --
+ *	Print out a DBT data element.
+ *
+ * PUBLIC: int __db_prdbt __P((DBT *, int, const char *, void *,
+ * PUBLIC:     int (*)(void *, const void *), int));
+ */
+int
+__db_prdbt(dbtp, checkprint, prefix, handle, callback, is_recno)
+	DBT *dbtp;
+	int checkprint;
+	const char *prefix;
+	void *handle;
+	int (*callback) __P((void *, const void *));
+	int is_recno;
+{
+	static const u_char hex[] = "0123456789abcdef";
+	db_recno_t recno;
+	size_t len;
+	int ret;
+#define	DBTBUFLEN	100
+	u_int8_t *p, *hp;
+	char buf[DBTBUFLEN], hbuf[DBTBUFLEN];
+
+	/*
+	 * !!!
+	 * This routine is the routine that dumps out items in the format
+	 * used by db_dump(1) and db_load(1).  This means that the format
+	 * cannot change.
+	 */
+	if (prefix != NULL && (ret = callback(handle, prefix)) != 0)
+		return (ret);
+	if (is_recno) {
+		/*
+		 * We're printing a record number, and this has to be done
+		 * in a platform-independent way.  So we use the numeral in
+		 * straight ASCII.
+		 */
+		(void)__ua_memcpy(&recno, dbtp->data, sizeof(recno));
+		snprintf(buf, DBTBUFLEN, "%lu", (u_long)recno);
+
+		/* If we're printing data as hex, print keys as hex too. */
+		if (!checkprint) {
+			for (len = strlen(buf), p = (u_int8_t *)buf,
+			    hp = (u_int8_t *)hbuf; len-- > 0; ++p) {
+				*hp++ = hex[(u_int8_t)(*p & 0xf0) >> 4];
+				*hp++ = hex[*p & 0x0f];
+			}
+			*hp = '\0';
+			ret = callback(handle, hbuf);
+		} else
+			ret = callback(handle, buf);
+
+		if (ret != 0)
+			return (ret);
+	} else if (checkprint) {
+		for (len = dbtp->size, p = dbtp->data; len--; ++p)
+			if (isprint((int)*p)) {
+				if (*p == '\\' &&
+				    (ret = callback(handle, "\\")) != 0)
+					return (ret);
+				snprintf(buf, DBTBUFLEN, "%c", *p);
+				if ((ret = callback(handle, buf)) != 0)
+					return (ret);
+			} else {
+				snprintf(buf, DBTBUFLEN, "\\%c%c",
+				    hex[(u_int8_t)(*p & 0xf0) >> 4],
+				    hex[*p & 0x0f]);
+				if ((ret = callback(handle, buf)) != 0)
+					return (ret);
+			}
+	} else
+		for (len = dbtp->size, p = dbtp->data; len--; ++p) {
+			snprintf(buf, DBTBUFLEN, "%c%c",
+			    hex[(u_int8_t)(*p & 0xf0) >> 4],
+			    hex[*p & 0x0f]);
+			if ((ret = callback(handle, buf)) != 0)
+				return (ret);
+		}
+
+	return (callback(handle, "\n"));
+}
+
 /*
  * __db_prheader --
  *	Write out header information in the format expected by db_load.
  *
- * PUBLIC: int	__db_prheader __P((DB *, char *, int, int, void *,
+ * PUBLIC: int	__db_prheader __P((DB *, const char *, int, int, void *,
  * PUBLIC:     int (*)(void *, const void *), VRFY_DBINFO *, db_pgno_t));
  */
 int
 __db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
 	DB *dbp;
-	char *subname;
+	const char *subname;
 	int pflag, keyflag;
 	void *handle;
 	int (*callback) __P((void *, const void *));
 	VRFY_DBINFO *vdp;
 	db_pgno_t meta_pgno;
 {
-	DB_BTREE_STAT *btsp;
-	DB_ENV *dbenv;
-	DB_HASH_STAT *hsp;
-	DB_QUEUE_STAT *qsp;
 	DBT dbt;
+	DB_ENV *dbenv;
+	DBTYPE dbtype;
 	VRFY_PAGEINFO *pip;
+	u_int32_t flags, tmp_u_int32;
+	size_t buflen;
 	char *buf;
-	int buflen, ret, t_ret;
-	u_int32_t dbtype;
+	int using_vdp, ret, t_ret, tmp_int;
 
-	btsp = NULL;
-	hsp = NULL;
-	qsp = NULL;
 	ret = 0;
 	buf = NULL;
 	COMPQUIET(buflen, 0);
 
+	/*
+	 * If dbp is NULL, then pip is guaranteed to be non-NULL; we only ever
+	 * call __db_prheader with a NULL dbp from one case inside __db_prdbt,
+	 * and this is a special subdatabase for "lost" items.  In this case
+	 * we have a vdp (from which we'll get a pip).  In all other cases, we
+	 * will have a non-NULL dbp (and vdp may or may not be NULL depending
+	 * on whether we're salvaging).
+	 */
+	DB_ASSERT(dbp != NULL || vdp != NULL);
+
 	if (dbp == NULL)
 		dbenv = NULL;
 	else
 		dbenv = dbp->dbenv;
 
 	/*
-	 * If we've been passed a verifier statistics object, use
-	 * that;  we're being called in a context where dbp->stat
-	 * is unsafe.
+	 * If we've been passed a verifier statistics object, use that;  we're
+	 * being called in a context where dbp->stat is unsafe.
 	 *
-	 * Also, the verifier may set the pflag on a per-salvage basis.
-	 * If so, respect that.
+	 * Also, the verifier may set the pflag on a per-salvage basis.  If so,
+	 * respect that.
 	 */
 	if (vdp != NULL) {
 		if ((ret = __db_vrfy_getpageinfo(vdp, meta_pgno, &pip)) != 0)
@@ -1018,18 +1240,19 @@ __db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
 
 		if (F_ISSET(vdp, SALVAGE_PRINTABLE))
 			pflag = 1;
-	} else
+		using_vdp = 1;
+	} else {
 		pip = NULL;
+		using_vdp = 0;
+	}
 
 	/*
-	 * If dbp is NULL, we're being called from inside __db_prdbt,
-	 * and this is a special subdatabase for "lost" items.  Make it a btree.
-	 * Otherwise, set dbtype to the appropriate type for the specified
-	 * meta page, or the type of the dbp.
+	 * If dbp is NULL, make it a btree.  Otherwise, set dbtype to whatever
+	 * appropriate type for the specified meta page, or the type of the dbp.
 	 */
 	if (dbp == NULL)
 		dbtype = DB_BTREE;
-	else if (pip != NULL)
+	else if (using_vdp)
 		switch (pip->type) {
 		case P_BTREEMETA:
 			if (F_ISSET(pip, VRFY_IS_RECNO))
@@ -1040,12 +1263,15 @@ __db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
 		case P_HASHMETA:
 			dbtype = DB_HASH;
 			break;
+		case P_QAMMETA:
+			dbtype = DB_QUEUE;
+			break;
 		default:
 			/*
-			 * If the meta page is of a bogus type, it's
-			 * because we have a badly corrupt database.
-			 * (We must be in the verifier for pip to be non-NULL.)
-			 * Pretend we're a Btree and salvage what we can.
+			 * If the meta page is of a bogus type, it's because
+			 * we have a badly corrupt database.  (We must be in
+			 * the verifier for pip to be non-NULL.) Pretend we're
+			 * a Btree and salvage what we can.
 			 */
 			DB_ASSERT(F_ISSET(dbp, DB_AM_VERIFYING));
 			dbtype = DB_BTREE;
@@ -1075,17 +1301,16 @@ __db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
 		if ((ret = callback(handle, buf)) != 0)
 			goto err;
 		memset(&dbt, 0, sizeof(dbt));
-		dbt.data = subname;
+		dbt.data = (char *)subname;
 		dbt.size = (u_int32_t)strlen(subname);
-		if ((ret = __db_prdbt(&dbt,
-		    1, NULL, handle, callback, 0, NULL)) != 0)
+		if ((ret = __db_prdbt(&dbt, 1, NULL, handle, callback, 0)) != 0)
 			goto err;
 	}
 	switch (dbtype) {
 	case DB_BTREE:
 		if ((ret = callback(handle, "type=btree\n")) != 0)
 			goto err;
-		if (pip != NULL) {
+		if (using_vdp) {
 			if (F_ISSET(pip, VRFY_HAS_RECNUMS))
 				if ((ret =
 				    callback(handle, "recnum=1\n")) != 0)
@@ -1105,30 +1330,31 @@ __db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
 			}
 			break;
 		}
-		if ((ret = dbp->stat(dbp, &btsp, 0)) != 0) {
-			dbp->err(dbp, ret, "DB->stat");
+
+		if ((ret = __db_get_flags(dbp, &flags)) != 0) {
+			__db_err(dbenv, "DB->get_flags: %s", db_strerror(ret));
 			goto err;
 		}
 		if (F_ISSET(dbp, DB_AM_RECNUM))
 			if ((ret = callback(handle, "recnum=1\n")) != 0)
 				goto err;
-		if (btsp->bt_maxkey != 0) {
-			snprintf(buf, buflen,
-			    "bt_maxkey=%lu\n", (u_long)btsp->bt_maxkey);
-			if ((ret = callback(handle, buf)) != 0)
-				goto err;
+		if ((ret = __bam_get_bt_minkey(dbp, &tmp_u_int32)) != 0) {
+			__db_err(dbenv,
+			    "DB->get_bt_minkey: %s", db_strerror(ret));
+			goto err;
 		}
-		if (btsp->bt_minkey != 0 && btsp->bt_minkey != DEFMINKEYPAGE) {
+		if (tmp_u_int32 != 0 && tmp_u_int32 != DEFMINKEYPAGE) {
 			snprintf(buf, buflen,
-			    "bt_minkey=%lu\n", (u_long)btsp->bt_minkey);
+			    "bt_minkey=%lu\n", (u_long)tmp_u_int32);
 			if ((ret = callback(handle, buf)) != 0)
 				goto err;
 		}
 		break;
 	case DB_HASH:
+#ifdef HAVE_HASH
 		if ((ret = callback(handle, "type=hash\n")) != 0)
 			goto err;
-		if (pip != NULL) {
+		if (using_vdp) {
 			if (pip->h_ffactor != 0) {
 				snprintf(buf, buflen,
 				    "h_ffactor=%lu\n", (u_long)pip->h_ffactor);
@@ -1143,24 +1369,35 @@ __db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
 			}
 			break;
 		}
-		if ((ret = dbp->stat(dbp, &hsp, 0)) != 0) {
-			dbp->err(dbp, ret, "DB->stat");
+		if ((ret = __ham_get_h_ffactor(dbp, &tmp_u_int32)) != 0) {
+			__db_err(dbenv,
+			    "DB->get_h_ffactor: %s", db_strerror(ret));
 			goto err;
 		}
-		if (hsp->hash_ffactor != 0) {
+		if (tmp_u_int32 != 0) {
 			snprintf(buf, buflen,
-			    "h_ffactor=%lu\n", (u_long)hsp->hash_ffactor);
+			    "h_ffactor=%lu\n", (u_long)tmp_u_int32);
 			if ((ret = callback(handle, buf)) != 0)
 				goto err;
 		}
-		if (hsp->hash_nkeys != 0) {
+		if ((ret = __ham_get_h_nelem(dbp, &tmp_u_int32)) != 0) {
+			__db_err(dbenv,
+			    "DB->get_h_nelem: %s", db_strerror(ret));
+			goto err;
+		}
+		if (tmp_u_int32 != 0) {
 			snprintf(buf, buflen,
-			    "h_nelem=%lu\n", (u_long)hsp->hash_nkeys);
+			    "h_nelem=%lu\n", (u_long)tmp_u_int32);
 			if ((ret = callback(handle, buf)) != 0)
 				goto err;
 		}
 		break;
+#else
+		ret = __db_no_hash_am(dbenv);
+		goto err;
+#endif
 	case DB_QUEUE:
+#ifdef HAVE_QUEUE
 		if ((ret = callback(handle, "type=queue\n")) != 0)
 			goto err;
 		if (vdp != NULL) {
@@ -1170,29 +1407,44 @@ __db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
 				goto err;
 			break;
 		}
-		if ((ret = dbp->stat(dbp, &qsp, 0)) != 0) {
-			dbp->err(dbp, ret, "DB->stat");
+		if ((ret = __ram_get_re_len(dbp, &tmp_u_int32)) != 0) {
+			__db_err(dbenv,
+			    "DB->get_re_len: %s", db_strerror(ret));
 			goto err;
 		}
-		snprintf(buf, buflen, "re_len=%lu\n", (u_long)qsp->qs_re_len);
+		snprintf(buf, buflen, "re_len=%lu\n", (u_long)tmp_u_int32);
 		if ((ret = callback(handle, buf)) != 0)
 			goto err;
-		if (qsp->qs_re_pad != 0 && qsp->qs_re_pad != ' ') {
-			snprintf(buf, buflen, "re_pad=%#x\n", qsp->qs_re_pad);
+		if ((ret = __ram_get_re_pad(dbp, &tmp_int)) != 0) {
+			__db_err(dbenv,
+			    "DB->get_re_pad: %s", db_strerror(ret));
+			goto err;
+		}
+		if (tmp_int != 0 && tmp_int != ' ') {
+			snprintf(buf, buflen, "re_pad=%#x\n", tmp_int);
 			if ((ret = callback(handle, buf)) != 0)
 				goto err;
 		}
-		if (qsp->qs_extentsize != 0) {
+		if ((ret = __qam_get_extentsize(dbp, &tmp_u_int32)) != 0) {
+			__db_err(dbenv,
+			    "DB->get_q_extentsize: %s", db_strerror(ret));
+			goto err;
+		}
+		if (tmp_u_int32 != 0) {
 			snprintf(buf, buflen,
-			    "extentsize=%lu\n", (u_long)qsp->qs_extentsize);
+			    "extentsize=%lu\n", (u_long)tmp_u_int32);
 			if ((ret = callback(handle, buf)) != 0)
 				goto err;
 		}
 		break;
+#else
+		ret = __db_no_queue_am(dbenv);
+		goto err;
+#endif
 	case DB_RECNO:
 		if ((ret = callback(handle, "type=recno\n")) != 0)
 			goto err;
-		if (pip != NULL) {
+		if (using_vdp) {
 			if (F_ISSET(pip, VRFY_IS_RRECNO))
 				if ((ret =
 				    callback(handle, "renumber=1\n")) != 0)
@@ -1205,33 +1457,42 @@ __db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
 			}
 			break;
 		}
-		if ((ret = dbp->stat(dbp, &btsp, 0)) != 0) {
-			dbp->err(dbp, ret, "DB->stat");
-			goto err;
-		}
 		if (F_ISSET(dbp, DB_AM_RENUMBER))
 			if ((ret = callback(handle, "renumber=1\n")) != 0)
 				goto err;
 		if (F_ISSET(dbp, DB_AM_FIXEDLEN)) {
+			if ((ret = __ram_get_re_len(dbp, &tmp_u_int32)) != 0) {
+				__db_err(dbenv,
+				    "DB->get_re_len: %s", db_strerror(ret));
+				goto err;
+			}
 			snprintf(buf, buflen,
-			    "re_len=%lu\n", (u_long)btsp->bt_re_len);
+			    "re_len=%lu\n", (u_long)tmp_u_int32);
 			if ((ret = callback(handle, buf)) != 0)
 				goto err;
-		}
-		if (btsp->bt_re_pad != 0 && btsp->bt_re_pad != ' ') {
-			snprintf(buf, buflen, "re_pad=%#x\n", btsp->bt_re_pad);
-			if ((ret = callback(handle, buf)) != 0)
+
+			if ((ret = __ram_get_re_pad(dbp, &tmp_int)) != 0) {
+				__db_err(dbenv,
+				    "DB->get_re_pad: %s", db_strerror(ret));
 				goto err;
+			}
+			if (tmp_int != 0 && tmp_int != ' ') {
+				snprintf(buf,
+				    buflen, "re_pad=%#x\n", (u_int)tmp_int);
+				if ((ret = callback(handle, buf)) != 0)
+					goto err;
+			}
 		}
 		break;
 	case DB_UNKNOWN:
 		DB_ASSERT(0);			/* Impossible. */
-		__db_err(dbp->dbenv, "Impossible DB type in __db_prheader");
+		__db_err(dbenv,
+		    "Unknown or unsupported DB type in __db_prheader");
 		ret = EINVAL;
 		goto err;
 	}
 
-	if (pip != NULL) {
+	if (using_vdp) {
 		if (F_ISSET(pip, VRFY_HAS_DUPS))
 			if ((ret = callback(handle, "duplicates=1\n")) != 0)
 				goto err;
@@ -1262,15 +1523,9 @@ __db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
 
 	ret = callback(handle, "HEADER=END\n");
 
-err:	if (pip != NULL &&
+err:	if (using_vdp &&
 	    (t_ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0 && ret == 0)
 		ret = t_ret;
-	if (btsp != NULL)
-		__os_ufree(dbenv, btsp);
-	if (hsp != NULL)
-		__os_ufree(dbenv, hsp);
-	if (qsp != NULL)
-		__os_ufree(dbenv, qsp);
 	if (buf != NULL)
 		__os_free(dbenv, buf);
 
@@ -1292,3 +1547,52 @@ __db_prfooter(handle, callback)
 {
 	return (callback(handle, "DATA=END\n"));
 }
+
+/*
+ * __db_pr_callback --
+ *	Callback function for using pr_* functions from C.
+ *
+ * PUBLIC: int  __db_pr_callback __P((void *, const void *));
+ */
+int
+__db_pr_callback(handle, str_arg)
+	void *handle;
+	const void *str_arg;
+{
+	char *str;
+	FILE *f;
+
+	str = (char *)str_arg;
+	f = (FILE *)handle;
+
+	if (fprintf(f, "%s", str) != (int)strlen(str))
+		return (EIO);
+
+	return (0);
+}
+
+/*
+ * __db_dbtype_to_string --
+ *	Return the name of the database type.
+ *
+ * PUBLIC: const char * __db_dbtype_to_string __P((DBTYPE));
+ */
+const char *
+__db_dbtype_to_string(type)
+	DBTYPE type;
+{
+	switch (type) {
+	case DB_BTREE:
+		return ("btree");
+	case DB_HASH:
+		return ("hash");
+	case DB_RECNO:
+		return ("recno");
+	case DB_QUEUE:
+		return ("queue");
+	case DB_UNKNOWN:
+	default:
+		break;
+	}
+	return ("UNKNOWN TYPE");
+}
diff --git a/storage/bdb/db/db_rec.c b/storage/bdb/db/db_rec.c
index 303ab2fe1d40fd16f0d7a2e34874151b83953d3d..bce2b8701a3489699183fc55040696ed6b7b5ad9 100644
--- a/storage/bdb/db/db_rec.c
+++ b/storage/bdb/db/db_rec.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_rec.c,v 11.61 2004/10/21 14:39:58 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_rec.c,v 11.35 2002/08/08 03:57:49 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -19,9 +17,14 @@ static const char revid[] = "$Id: db_rec.c,v 11.35 2002/08/08 03:57:49 bostic Ex
 
 #include "db_int.h"
 #include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
 #include "dbinc/log.h"
+#include "dbinc/mp.h"
 #include "dbinc/hash.h"
 
+static int __db_pg_free_recover_int __P((DB_ENV *,
+    __db_pg_freedata_args *, DB *, DB_LSN *, DB_MPOOLFILE *, db_recops, int));
+
 /*
  * PUBLIC: int __db_addrem_recover
  * PUBLIC:    __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
@@ -50,20 +53,7 @@ __db_addrem_recover(dbenv, dbtp, lsnp, op, info)
 	REC_PRINT(__db_addrem_print);
 	REC_INTRO(__db_addrem_read, 1);
 
-	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
-		if (DB_UNDO(op)) {
-			/*
-			 * We are undoing and the page doesn't exist.  That
-			 * is equivalent to having a pagelsn of 0, so we
-			 * would not have to undo anything.  In this case,
-			 * don't bother creating a page.
-			 */
-			goto done;
-		} else
-			if ((ret = mpf->get(mpf,
-			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
-				goto out;
-	}
+	REC_FGET(mpf, argp->pgno, &pagep, done);
 
 	cmp_n = log_compare(lsnp, &LSN(pagep));
 	cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
@@ -96,7 +86,7 @@ __db_addrem_recover(dbenv, dbtp, lsnp, op, info)
 			LSN(pagep) = argp->pagelsn;
 	}
 
-	if ((ret = mpf->put(mpf, pagep, change)) != 0)
+	if ((ret = __memp_fput(mpf, pagep, change)) != 0)
 		goto out;
 	pagep = NULL;
 
@@ -104,7 +94,7 @@ done:	*lsnp = argp->prev_lsn;
 	ret = 0;
 
 out:	if (pagep != NULL)
-		(void)mpf->put(mpf, pagep, 0);
+		(void)__memp_fput(mpf, pagep, 0);
 	REC_CLOSE;
 }
 
@@ -133,21 +123,7 @@ __db_big_recover(dbenv, dbtp, lsnp, op, info)
 	REC_PRINT(__db_big_print);
 	REC_INTRO(__db_big_read, 1);
 
-	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
-		if (DB_UNDO(op)) {
-			/*
-			 * We are undoing and the page doesn't exist.  That
-			 * is equivalent to having a pagelsn of 0, so we
-			 * would not have to undo anything.  In this case,
-			 * don't bother creating a page.
-			 */
-			ret = 0;
-			goto ppage;
-		} else
-			if ((ret = mpf->get(mpf,
-			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
-				goto out;
-	}
+	REC_FGET(mpf, argp->pgno, &pagep, ppage);
 
 	/*
 	 * There are three pages we need to check.  The one on which we are
@@ -182,7 +158,7 @@ __db_big_recover(dbenv, dbtp, lsnp, op, info)
 	if (change)
 		LSN(pagep) = DB_REDO(op) ? *lsnp : argp->pagelsn;
 
-	if ((ret = mpf->put(mpf, pagep, change)) != 0)
+	if ((ret = __memp_fput(mpf, pagep, change)) != 0)
 		goto out;
 	pagep = NULL;
 
@@ -196,22 +172,7 @@ __db_big_recover(dbenv, dbtp, lsnp, op, info)
 	/* Now check the previous page. */
 ppage:	if (argp->prev_pgno != PGNO_INVALID) {
 		change = 0;
-		if ((ret = mpf->get(mpf, &argp->prev_pgno, 0, &pagep)) != 0) {
-			if (DB_UNDO(op)) {
-				/*
-				 * We are undoing and the page doesn't exist.
-				 * That is equivalent to having a pagelsn of 0,
-				 * so we would not have to undo anything.  In
-				 * this case, don't bother creating a page.
-				 */
-				*lsnp = argp->prev_lsn;
-				ret = 0;
-				goto npage;
-			} else
-				if ((ret = mpf->get(mpf, &argp->prev_pgno,
-				    DB_MPOOL_CREATE, &pagep)) != 0)
-					goto out;
-		}
+		REC_FGET(mpf, argp->prev_pgno, &pagep, npage);
 
 		cmp_n = log_compare(lsnp, &LSN(pagep));
 		cmp_p = log_compare(&LSN(pagep), &argp->prevlsn);
@@ -229,7 +190,7 @@ ppage:	if (argp->prev_pgno != PGNO_INVALID) {
 		}
 		if (change)
 			LSN(pagep) = DB_REDO(op) ? *lsnp : argp->prevlsn;
-		if ((ret = mpf->put(mpf, pagep, change)) != 0)
+		if ((ret = __memp_fput(mpf, pagep, change)) != 0)
 			goto out;
 	}
 	pagep = NULL;
@@ -237,20 +198,7 @@ ppage:	if (argp->prev_pgno != PGNO_INVALID) {
 	/* Now check the next page.  Can only be set on a delete. */
 npage:	if (argp->next_pgno != PGNO_INVALID) {
 		change = 0;
-		if ((ret = mpf->get(mpf, &argp->next_pgno, 0, &pagep)) != 0) {
-			if (DB_UNDO(op)) {
-				/*
-				 * We are undoing and the page doesn't exist.
-				 * That is equivalent to having a pagelsn of 0,
-				 * so we would not have to undo anything.  In
-				 * this case, don't bother creating a page.
-				 */
-				goto done;
-			} else
-				if ((ret = mpf->get(mpf, &argp->next_pgno,
-				    DB_MPOOL_CREATE, &pagep)) != 0)
-					goto out;
-		}
+		REC_FGET(mpf, argp->next_pgno, &pagep, done);
 
 		cmp_n = log_compare(lsnp, &LSN(pagep));
 		cmp_p = log_compare(&LSN(pagep), &argp->nextlsn);
@@ -264,7 +212,7 @@ npage:	if (argp->next_pgno != PGNO_INVALID) {
 		}
 		if (change)
 			LSN(pagep) = DB_REDO(op) ? *lsnp : argp->nextlsn;
-		if ((ret = mpf->put(mpf, pagep, change)) != 0)
+		if ((ret = __memp_fput(mpf, pagep, change)) != 0)
 			goto out;
 	}
 	pagep = NULL;
@@ -273,7 +221,7 @@ done:	*lsnp = argp->prev_lsn;
 	ret = 0;
 
 out:	if (pagep != NULL)
-		(void)mpf->put(mpf, pagep, 0);
+		(void)__memp_fput(mpf, pagep, 0);
 	REC_CLOSE;
 }
 
@@ -304,12 +252,7 @@ __db_ovref_recover(dbenv, dbtp, lsnp, op, info)
 	REC_PRINT(__db_ovref_print);
 	REC_INTRO(__db_ovref_read, 1);
 
-	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
-		if (DB_UNDO(op))
-			goto done;
-		__db_pgerr(file_dbp, argp->pgno, ret);
-		goto out;
-	}
+	REC_FGET(mpf, argp->pgno, &pagep, done);
 
 	modified = 0;
 	cmp = log_compare(&LSN(pagep), &argp->lsn);
@@ -327,144 +270,7 @@ __db_ovref_recover(dbenv, dbtp, lsnp, op, info)
 		pagep->lsn = argp->lsn;
 		modified = 1;
 	}
-	if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
-		goto out;
-	pagep = NULL;
-
-done:	*lsnp = argp->prev_lsn;
-	ret = 0;
-
-out:	if (pagep != NULL)
-		(void)mpf->put(mpf, pagep, 0);
-	REC_CLOSE;
-}
-
-/*
- * __db_relink_recover --
- *	Recovery function for relink.
- *
- * PUBLIC: int __db_relink_recover
- * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
- */
-int
-__db_relink_recover(dbenv, dbtp, lsnp, op, info)
-	DB_ENV *dbenv;
-	DBT *dbtp;
-	DB_LSN *lsnp;
-	db_recops op;
-	void *info;
-{
-	__db_relink_args *argp;
-	DB *file_dbp;
-	DBC *dbc;
-	DB_MPOOLFILE *mpf;
-	PAGE *pagep;
-	int cmp_n, cmp_p, modified, ret;
-
-	pagep = NULL;
-	COMPQUIET(info, NULL);
-	REC_PRINT(__db_relink_print);
-	REC_INTRO(__db_relink_read, 1);
-
-	/*
-	 * There are up to three pages we need to check -- the page, and the
-	 * previous and next pages, if they existed.  For a page add operation,
-	 * the current page is the result of a split and is being recovered
-	 * elsewhere, so all we need do is recover the next page.
-	 */
-	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
-		if (DB_REDO(op)) {
-			__db_pgerr(file_dbp, argp->pgno, ret);
-			goto out;
-		}
-		goto next2;
-	}
-	modified = 0;
-	if (argp->opcode == DB_ADD_PAGE)
-		goto next1;
-
-	cmp_p = log_compare(&LSN(pagep), &argp->lsn);
-	CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn);
-	if (cmp_p == 0 && DB_REDO(op)) {
-		/* Redo the relink. */
-		pagep->lsn = *lsnp;
-		modified = 1;
-	} else if (log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) {
-		/* Undo the relink. */
-		pagep->next_pgno = argp->next;
-		pagep->prev_pgno = argp->prev;
-
-		pagep->lsn = argp->lsn;
-		modified = 1;
-	}
-next1:	if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
-		goto out;
-	pagep = NULL;
-
-next2:	if ((ret = mpf->get(mpf, &argp->next, 0, &pagep)) != 0) {
-		if (DB_REDO(op)) {
-			__db_pgerr(file_dbp, argp->next, ret);
-			goto out;
-		}
-		goto prev;
-	}
-	modified = 0;
-	cmp_n = log_compare(lsnp, &LSN(pagep));
-	cmp_p = log_compare(&LSN(pagep), &argp->lsn_next);
-	CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn_next);
-	if ((argp->opcode == DB_REM_PAGE && cmp_p == 0 && DB_REDO(op)) ||
-	    (argp->opcode == DB_ADD_PAGE && cmp_n == 0 && DB_UNDO(op))) {
-		/* Redo the remove or undo the add. */
-		pagep->prev_pgno = argp->prev;
-
-		modified = 1;
-	} else if ((argp->opcode == DB_REM_PAGE && cmp_n == 0 && DB_UNDO(op)) ||
-	    (argp->opcode == DB_ADD_PAGE && cmp_p == 0 && DB_REDO(op))) {
-		/* Undo the remove or redo the add. */
-		pagep->prev_pgno = argp->pgno;
-
-		modified = 1;
-	}
-	if (modified == 1) {
-		if (DB_UNDO(op))
-			pagep->lsn = argp->lsn_next;
-		else
-			pagep->lsn = *lsnp;
-	}
-	if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
-		goto out;
-	pagep = NULL;
-	if (argp->opcode == DB_ADD_PAGE)
-		goto done;
-
-prev:	if ((ret = mpf->get(mpf, &argp->prev, 0, &pagep)) != 0) {
-		if (DB_REDO(op)) {
-			__db_pgerr(file_dbp, argp->prev, ret);
-			goto out;
-		}
-		goto done;
-	}
-	modified = 0;
-	cmp_p = log_compare(&LSN(pagep), &argp->lsn_prev);
-	CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn_prev);
-	if (cmp_p == 0 && DB_REDO(op)) {
-		/* Redo the relink. */
-		pagep->next_pgno = argp->next;
-
-		modified = 1;
-	} else if (log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) {
-		/* Undo the relink. */
-		pagep->next_pgno = argp->pgno;
-
-		modified = 1;
-	}
-	if (modified == 1) {
-		if (DB_UNDO(op))
-			pagep->lsn = argp->lsn_prev;
-		else
-			pagep->lsn = *lsnp;
-	}
-	if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+	if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
 		goto out;
 	pagep = NULL;
 
@@ -472,7 +278,7 @@ done:	*lsnp = argp->prev_lsn;
 	ret = 0;
 
 out:	if (pagep != NULL)
-		(void)mpf->put(mpf, pagep, 0);
+		(void)__memp_fput(mpf, pagep, 0);
 	REC_CLOSE;
 }
 
@@ -535,8 +341,7 @@ __db_noop_recover(dbenv, dbtp, lsnp, op, info)
 	REC_PRINT(__db_noop_print);
 	REC_INTRO(__db_noop_read, 0);
 
-	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
-		goto out;
+	REC_FGET(mpf, argp->pgno, &pagep, done);
 
 	cmp_n = log_compare(lsnp, &LSN(pagep));
 	cmp_p = log_compare(&LSN(pagep), &argp->prevlsn);
@@ -549,12 +354,12 @@ __db_noop_recover(dbenv, dbtp, lsnp, op, info)
 		LSN(pagep) = argp->prevlsn;
 		change = DB_MPOOL_DIRTY;
 	}
-	ret = mpf->put(mpf, pagep, change);
+	ret = __memp_fput(mpf, pagep, change);
 	pagep = NULL;
 
 done:	*lsnp = argp->prev_lsn;
 out:	if (pagep != NULL)
-		(void)mpf->put(mpf, pagep, 0);
+		(void)__memp_fput(mpf, pagep, 0);
 	REC_CLOSE;
 }
 
@@ -580,35 +385,69 @@ __db_pg_alloc_recover(dbenv, dbtp, lsnp, op, info)
 	DB_MPOOLFILE *mpf;
 	PAGE *pagep;
 	db_pgno_t pgno;
-	int cmp_n, cmp_p, created, level, modified, ret;
+	int cmp_n, cmp_p, created, level, meta_modified, modified, ret;
 
 	meta = NULL;
 	pagep = NULL;
+	created = meta_modified = modified = 0;
 	REC_PRINT(__db_pg_alloc_print);
 	REC_INTRO(__db_pg_alloc_read, 0);
 
 	/*
-	 * Fix up the allocated page.  If we're redoing the operation, we have
-	 * to get the page (creating it if it doesn't exist), and update its
-	 * LSN.  If we're undoing the operation, we have to reset the page's
-	 * LSN and put it on the free list.
-	 *
 	 * Fix up the metadata page.  If we're redoing the operation, we have
 	 * to get the metadata page and update its LSN and its free pointer.
 	 * If we're undoing the operation and the page was ever created, we put
 	 * it on the freelist.
 	 */
 	pgno = PGNO_BASE_MD;
-	if ((ret = mpf->get(mpf, &pgno, 0, &meta)) != 0) {
+	if ((ret = __memp_fget(mpf, &pgno, 0, &meta)) != 0) {
 		/* The metadata page must always exist on redo. */
 		if (DB_REDO(op)) {
-			__db_pgerr(file_dbp, pgno, ret);
+			ret = __db_pgerr(file_dbp, pgno, ret);
 			goto out;
 		} else
 			goto done;
 	}
-	created = modified = 0;
-	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
+	cmp_n = log_compare(lsnp, &LSN(meta));
+	cmp_p = log_compare(&LSN(meta), &argp->meta_lsn);
+	CHECK_LSN(op, cmp_p, &LSN(meta), &argp->meta_lsn);
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		LSN(meta) = *lsnp;
+		meta->free = argp->next;
+		meta_modified = 1;
+		if (argp->pgno > meta->last_pgno)
+			meta->last_pgno = argp->pgno;
+	} else if (cmp_n == 0 && DB_UNDO(op)) {
+		/* Need to undo update described. */
+		LSN(meta) = argp->meta_lsn;
+		/*
+		 * If the page has a zero LSN then its newly created
+		 * and will be truncated or go into limbo rather than
+		 * directly on the free list.
+		 */
+		if (!IS_ZERO_LSN(argp->page_lsn))
+			meta->free = argp->pgno;
+#ifdef HAVE_FTRUNCATE
+		/*
+		 * With truncate we will restore the file to
+		 * its original length.  Without truncate
+		 * the last_pgno never goes backward.
+		 */
+		meta->last_pgno = argp->last_pgno;
+#endif
+		meta_modified = 1;
+	}
+
+	/*
+	 * Fix up the allocated page. If the page does not exist
+	 * and we can truncate it then don't create it.
+	 * Otherwise if we're redoing the operation, we have
+	 * to get the page (creating it if it doesn't exist), and update its
+	 * LSN.  If we're undoing the operation, we have to reset the page's
+	 * LSN and put it on the free list, or into limbo..
+	 */
+	if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
 		/*
 		 * We have to be able to identify if a page was newly
 		 * created so we can recover it properly.  We cannot simply
@@ -617,9 +456,15 @@ __db_pg_alloc_recover(dbenv, dbtp, lsnp, op, info)
 		 * try for the page without CREATE and if that fails, then
 		 * create it.
 		 */
-		if ((ret =
-		    mpf->get(mpf, &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0) {
-			__db_pgerr(file_dbp, argp->pgno, ret);
+#ifdef HAVE_FTRUNCATE
+		if (DB_UNDO(op))
+			goto do_truncate;
+#endif
+		if ((ret = __memp_fget(
+		    mpf, &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0) {
+			if (DB_UNDO(op) && ret == ENOSPC)
+				goto do_truncate;
+			ret = __db_pgerr(file_dbp, argp->pgno, ret);
 			goto out;
 		}
 		created = modified = 1;
@@ -630,27 +475,24 @@ __db_pg_alloc_recover(dbenv, dbtp, lsnp, op, info)
 	cmp_p = log_compare(&LSN(pagep), &argp->page_lsn);
 
 	/*
-	 * If an inital allocation is aborted and then reallocated
-	 * during an archival restore the log record will have
-	 * an LSN for the page but the page will be empty.
+	 * If an initial allocation is aborted and then reallocated during
+	 * an archival restore the log record will have an LSN for the page
+	 * but the page will be empty.
+	 * If we we rolled back this allocation previously during an
+	 * archive restore, the page may have INIT_LSN from the limbo list.
 	 */
-	if (IS_ZERO_LSN(LSN(pagep)))
+	if (IS_ZERO_LSN(LSN(pagep)) ||
+	    (IS_ZERO_LSN(argp->page_lsn) && IS_INIT_LSN(LSN(pagep))))
 		cmp_p = 0;
+
 	CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->page_lsn);
 	/*
-	 * If we we rolled back this allocation previously during an
-	 * archive restore, the page may have the LSN of the meta page
-	 * at the point of the roll back.  This will be no more
-	 * than the LSN of the metadata page at the time of this allocation.
 	 * Another special case we have to handle is if we ended up with a
 	 * page of all 0's which can happen if we abort between allocating a
 	 * page in mpool and initializing it.  In that case, even if we're
 	 * undoing, we need to re-initialize the page.
 	 */
-	if (DB_REDO(op) &&
-	    (cmp_p == 0 ||
-	    (IS_ZERO_LSN(argp->page_lsn) &&
-	    log_compare(&LSN(pagep), &argp->meta_lsn) <= 0))) {
+	if (DB_REDO(op) && cmp_p == 0) {
 		/* Need to redo update described. */
 		switch (argp->ptype) {
 		case P_LBTREE:
@@ -681,174 +523,337 @@ __db_pg_alloc_recover(dbenv, dbtp, lsnp, op, info)
 		modified = 1;
 	}
 
+do_truncate:
 	/*
-	 * If the page was newly created, put it on the limbo list.
+	 * If the page was newly created, give it back, if
+	 * possible.  Otherwise put it into limbo.
 	 */
-	if (IS_ZERO_LSN(LSN(pagep)) &&
+	if ((pagep == NULL || IS_ZERO_LSN(LSN(pagep))) &&
 	    IS_ZERO_LSN(argp->page_lsn) && DB_UNDO(op)) {
+#ifdef HAVE_FTRUNCATE
+		COMPQUIET(info, NULL);
+		/* Discard the page. */
+		if (pagep != NULL) {
+			if ((ret =
+			     __memp_fput(mpf, pagep, DB_MPOOL_DISCARD)) != 0)
+				goto out;
+			pagep = NULL;
+			/* Give the page back to the OS. */
+			if (meta->last_pgno <= argp->pgno &&
+			    (ret = __memp_ftruncate(mpf, argp->pgno, 0)) != 0)
+				goto out;
+		}
+#else
 		/* Put the page in limbo.*/
 		if ((ret = __db_add_limbo(dbenv,
 		    info, argp->fileid, argp->pgno, 1)) != 0)
 			goto out;
+		/* The last_pgno grows if this was a new page. */
+		if (argp->pgno > meta->last_pgno) {
+			meta->last_pgno = argp->pgno;
+			meta_modified = 1;
+		}
+#endif
 	}
 
-	if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+	if (pagep != NULL &&
+	     (ret = __memp_fput(mpf,
+	     pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
 		goto out;
 	pagep = NULL;
 
-	/* Fix up the metadata page. */
-	modified = 0;
-	cmp_n = log_compare(lsnp, &LSN(meta));
-	cmp_p = log_compare(&LSN(meta), &argp->meta_lsn);
-	CHECK_LSN(op, cmp_p, &LSN(meta), &argp->meta_lsn);
-	if (cmp_p == 0 && DB_REDO(op)) {
-		/* Need to redo update described. */
-		LSN(meta) = *lsnp;
-		meta->free = argp->next;
-		modified = 1;
-	} else if (cmp_n == 0 && DB_UNDO(op)) {
-		/* Need to undo update described. */
-		LSN(meta) = argp->meta_lsn;
-
-		/*
-		 * If the page has a zero LSN then its newly created
-		 * and will go into limbo rather than directly on the
-		 * free list.
-		 */
-		if (!IS_ZERO_LSN(argp->page_lsn))
-			meta->free = argp->pgno;
-		modified = 1;
-	}
-	if ((ret = mpf->put(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+	if ((ret = __memp_fput(mpf,
+	    meta, meta_modified ? DB_MPOOL_DIRTY : 0)) != 0)
 		goto out;
 	meta = NULL;
-	/*
-	 * This could be the metapage from a subdb which is read from disk
-	 * to recover its creation.
-	 */
-	if (F_ISSET(file_dbp, DB_AM_SUBDB))
-		switch (argp->type) {
-		case P_BTREEMETA:
-		case P_HASHMETA:
-		case P_QAMMETA:
-			file_dbp->sync(file_dbp, 0);
-			break;
-		}
 
 done:	*lsnp = argp->prev_lsn;
 	ret = 0;
 
 out:	if (pagep != NULL)
-		(void)mpf->put(mpf, pagep, 0);
+		(void)__memp_fput(mpf, pagep, 0);
 	if (meta != NULL)
-		(void)mpf->put(mpf, meta, 0);
+		(void)__memp_fput(mpf, meta, 0);
 	if (ret == ENOENT && op == DB_TXN_BACKWARD_ALLOC)
 		ret = 0;
 	REC_CLOSE;
 }
 
 /*
- * __db_pg_free_recover --
- *	Recovery function for pg_free.
- *
- * PUBLIC: int __db_pg_free_recover
- * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ * __db_pg_free_recover_int --
  */
-int
-__db_pg_free_recover(dbenv, dbtp, lsnp, op, info)
+static int
+__db_pg_free_recover_int(dbenv, argp, file_dbp, lsnp, mpf, op, data)
 	DB_ENV *dbenv;
-	DBT *dbtp;
+	__db_pg_freedata_args *argp;
+	DB *file_dbp;
 	DB_LSN *lsnp;
+	DB_MPOOLFILE *mpf;
 	db_recops op;
-	void *info;
+	int data;
 {
-	__db_pg_free_args *argp;
-	DB *file_dbp;
-	DBC *dbc;
 	DBMETA *meta;
 	DB_LSN copy_lsn;
-	DB_MPOOLFILE *mpf;
 	PAGE *pagep;
 	db_pgno_t pgno;
-	int cmp_n, cmp_p, modified, ret;
+	int cmp_n, cmp_p, meta_modified, modified, ret;
 
-	COMPQUIET(info, NULL);
 	meta = NULL;
 	pagep = NULL;
-	REC_PRINT(__db_pg_free_print);
-	REC_INTRO(__db_pg_free_read, 1);
-
-	/*
-	 * Fix up the freed page.  If we're redoing the operation we get the
-	 * page and explicitly discard its contents, then update its LSN.  If
-	 * we're undoing the operation, we get the page and restore its header.
-	 * Create the page if necessary, we may be freeing an aborted
-	 * create.
-	 */
-	if ((ret = mpf->get(mpf, &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
-		goto out;
-	modified = 0;
-	(void)__ua_memcpy(&copy_lsn, &LSN(argp->header.data), sizeof(DB_LSN));
-	cmp_n = log_compare(lsnp, &LSN(pagep));
-	cmp_p = log_compare(&LSN(pagep), &copy_lsn);
-	CHECK_LSN(op, cmp_p, &LSN(pagep), &copy_lsn);
-	if (DB_REDO(op) &&
-	    (cmp_p == 0 ||
-	    (IS_ZERO_LSN(copy_lsn) &&
-	    log_compare(&LSN(pagep), &argp->meta_lsn) <= 0))) {
-		/* Need to redo update described. */
-		P_INIT(pagep, file_dbp->pgsize,
-		    argp->pgno, PGNO_INVALID, argp->next, 0, P_INVALID);
-		pagep->lsn = *lsnp;
-
-		modified = 1;
-	} else if (cmp_n == 0 && DB_UNDO(op)) {
-		/* Need to undo update described. */
-		memcpy(pagep, argp->header.data, argp->header.size);
-
-		modified = 1;
-	}
-	if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
-		goto out;
-	pagep = NULL;
+	meta_modified = modified = 0;
 
 	/*
-	 * Fix up the metadata page.  If we're redoing or undoing the operation
-	 * we get the page and update its LSN and free pointer.
+	 * Get the metapage first so we can see where we are.
 	 */
 	pgno = PGNO_BASE_MD;
-	if ((ret = mpf->get(mpf, &pgno, 0, &meta)) != 0) {
+	if ((ret = __memp_fget(mpf, &pgno, 0, &meta)) != 0) {
 		/* The metadata page must always exist. */
-		__db_pgerr(file_dbp, pgno, ret);
+		ret = __db_pgerr(file_dbp, pgno, ret);
 		goto out;
 	}
-
-	modified = 0;
 	cmp_n = log_compare(lsnp, &LSN(meta));
 	cmp_p = log_compare(&LSN(meta), &argp->meta_lsn);
 	CHECK_LSN(op, cmp_p, &LSN(meta), &argp->meta_lsn);
+
+	/*
+	 * Fix up the metadata page.  If we're redoing or undoing the operation
+	 * we get the page and update its LSN, last and free pointer.
+	 */
 	if (cmp_p == 0 && DB_REDO(op)) {
+#ifdef HAVE_FTRUNCATE
+		/*
+		 * If we are at the end of the file truncate, otherwise
+		 * put on the free list.
+		*/
+		if (argp->pgno == argp->last_pgno)
+			meta->last_pgno = argp->pgno - 1;
+		else
+			meta->free = argp->pgno;
+#else
 		/* Need to redo the deallocation. */
 		meta->free = argp->pgno;
+		/*
+		 * If this was a compensating transaction and
+		 * we are a replica, then we never executed the
+		 * original allocation which incremented meta->free.
+		 */
+		if (meta->last_pgno < meta->free)
+			meta->last_pgno = meta->free;
+#endif
 		LSN(meta) = *lsnp;
-		modified = 1;
+		meta_modified = 1;
 	} else if (cmp_n == 0 && DB_UNDO(op)) {
 		/* Need to undo the deallocation. */
 		meta->free = argp->next;
 		LSN(meta) = argp->meta_lsn;
+		if (meta->last_pgno < argp->pgno)
+			meta->last_pgno = argp->pgno;
+		meta_modified = 1;
+	}
+
+	/*
+	 * Get the freed page.  If we support truncate then don't
+	 * create the page if we are going to free it.  If we're
+	 * redoing the operation we get the page and explicitly discard
+	 * its contents, then update its LSN.  If we're undoing the
+	 * operation, we get the page and restore its header.
+	 * If we don't support truncate, then we must create the page
+	 * and roll it back.
+	 */
+#ifdef HAVE_FTRUNCATE
+	if (DB_REDO(op) || meta->last_pgno < argp->pgno) {
+		if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
+			if (ret == DB_PAGE_NOTFOUND)
+				goto done;
+			goto out;
+		}
+	} else
+#endif
+	if ((ret =
+	    __memp_fget(mpf, &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+		goto out;
+
+	(void)__ua_memcpy(&copy_lsn, &LSN(argp->header.data), sizeof(DB_LSN));
+	cmp_n = IS_ZERO_LSN(LSN(pagep)) ? 0 : log_compare(lsnp, &LSN(pagep));
+	cmp_p = log_compare(&LSN(pagep), &copy_lsn);
+
+#ifdef HAVE_FTRUNCATE
+	/*
+	 * This page got extended by a later allocation,
+	 * but its allocation was not in the scope of this
+	 * recovery pass.
+	 */
+	if (IS_ZERO_LSN(LSN(pagep)))
+		cmp_p = 0;
+#endif
+
+	CHECK_LSN(op, cmp_p, &LSN(pagep), &copy_lsn);
+	if (DB_REDO(op) &&
+	    (cmp_p == 0 ||
+	    (IS_ZERO_LSN(copy_lsn) &&
+	    log_compare(&LSN(pagep), &argp->meta_lsn) <= 0))) {
+		/* Need to redo the deallocation. */
+#ifdef HAVE_FTRUNCATE
+		if (meta->last_pgno <= argp->pgno) {
+			if ((ret =
+			    __memp_fput(mpf, pagep, DB_MPOOL_DISCARD)) != 0)
+				goto out;
+			pagep = NULL;
+			if ((ret = __memp_ftruncate(mpf, argp->pgno, 0)) != 0)
+				goto out;
+		} else if (argp->last_pgno == argp->pgno) {
+			/* The page was truncated at runtime, zero it out. */
+			P_INIT(pagep, 0, PGNO_INVALID,
+			    PGNO_INVALID, PGNO_INVALID, 0, P_INVALID);
+			ZERO_LSN(pagep->lsn);
+			modified = 1;
+		} else
+#endif
+		{
+			P_INIT(pagep, file_dbp->pgsize,
+			    argp->pgno, PGNO_INVALID, argp->next, 0, P_INVALID);
+			pagep->lsn = *lsnp;
+
+			modified = 1;
+		}
+	} else if (cmp_n == 0 && DB_UNDO(op)) {
+		/* Need to reallocate the page. */
+		memcpy(pagep, argp->header.data, argp->header.size);
+		if (data)
+			memcpy((u_int8_t*)pagep + pagep->hf_offset,
+			     argp->data.data, argp->data.size);
+
 		modified = 1;
 	}
-	if ((ret = mpf->put(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+	if (pagep != NULL &&
+	    (ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+		goto out;
+
+	pagep = NULL;
+#ifdef HAVE_FTRUNCATE
+done:
+#endif
+	if ((ret = __memp_fput(mpf,
+	     meta, meta_modified ? DB_MPOOL_DIRTY : 0)) != 0)
 		goto out;
 	meta = NULL;
 
-done:	*lsnp = argp->prev_lsn;
 	ret = 0;
 
 out:	if (pagep != NULL)
-		(void)mpf->put(mpf, pagep, 0);
+		(void)__memp_fput(mpf, pagep, 0);
 	if (meta != NULL)
-		(void)mpf->put(mpf, meta, 0);
+		(void)__memp_fput(mpf, meta, 0);
+
+	return (ret);
+}
+
+/*
+ * __db_pg_free_recover --
+ *	Recovery function for pg_free.
+ *
+ * PUBLIC: int __db_pg_free_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__db_pg_free_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	__db_pg_free_args *argp;
+	int ret;
+
+	COMPQUIET(info, NULL);
+	REC_PRINT(__db_pg_free_print);
+	REC_INTRO(__db_pg_free_read, 1);
+
+	ret = __db_pg_free_recover_int(dbenv,
+	     (__db_pg_freedata_args *)argp, file_dbp, lsnp, mpf, op, 0);
+
+done:	*lsnp = argp->prev_lsn;
+out:
+	REC_CLOSE;
+}
+
+/*
+ * __db_pg_new_recover --
+ *	A new page from the file was put on the free list.
+ * This record is only generated during a LIMBO_COMPENSATE.
+ *
+ * PUBLIC: int __db_pg_new_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__db_pg_new_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+#ifndef HAVE_FTRUNCATE
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	__db_pg_free_args *argp;
+	int ret;
+
+	REC_PRINT(__db_pg_free_print);
+	REC_INTRO(__db_pg_free_read, 1);
+	COMPQUIET(op, DB_TXN_ABORT);
+
+	if ((ret =
+	    __db_add_limbo(dbenv, info, argp->fileid, argp->pgno, 1)) == 0)
+		*lsnp = argp->prev_lsn;
+
+done:
+out:
+	REC_CLOSE;
+#else
+	COMPQUIET(dbenv, NULL);
+	COMPQUIET(dbtp, NULL);
+	COMPQUIET(lsnp, NULL);
+	COMPQUIET(op, DB_TXN_PRINT);
+	COMPQUIET(info, NULL);
+	return (0);
+#endif
+}
+
+/*
+ * __db_pg_freedata_recover --
+ *	Recovery function for pg_freedata.
+ *
+ * PUBLIC: int __db_pg_freedata_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__db_pg_freedata_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	__db_pg_freedata_args *argp;
+	int ret;
+
+	COMPQUIET(info, NULL);
+	REC_PRINT(__db_pg_freedata_print);
+	REC_INTRO(__db_pg_freedata_read, 1);
+
+	ret = __db_pg_free_recover_int(dbenv, argp, file_dbp, lsnp, mpf, op, 1);
+
+done:	*lsnp = argp->prev_lsn;
+out:
 	REC_CLOSE;
 }
 
@@ -895,3 +900,132 @@ __db_cksum_recover(dbenv, dbtp, lsnp, op, info)
 	__os_free(dbenv, argp);
 	return (ret);
 }
+
+/*
+ * __db_pg_prepare_recover --
+ *	Recovery function for pg_prepare.
+ *
+ * PUBLIC: int __db_pg_prepare_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__db_pg_prepare_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+#ifndef HAVE_FTRUNCATE
+	__db_pg_prepare_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int ret, t_ret;
+
+	REC_PRINT(__db_pg_prepare_print);
+	REC_INTRO(__db_pg_prepare_read, 1);
+
+	mpf = file_dbp->mpf;
+
+	/*
+	 * If this made it into the limbo list at prepare time then
+	 * it was a new free page allocated by an aborted subtransaction.
+	 * Only that subtransaction could have toched the page.
+	 * All other pages in the free list at this point are
+	 * either of the same nature or were put there by this subtransactions
+	 * other subtransactions that followed this one.  If
+	 * they were put there by this subtransaction the log records
+	 * of the following allocations will reflect that.
+	 * Note that only one transaction could have had the
+	 * metapage locked at the point of the crash.
+	 * All this is to say that we can P_INIT this page without
+	 * loosing other pages on the free list because they
+	 * will be linked in by records earlier in the log for
+	 * this transaction which we will roll back.
+	 */
+	if (op == DB_TXN_ABORT) {
+		if ((ret = __memp_fget(
+		    mpf, &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+			goto out;
+		P_INIT(pagep, file_dbp->pgsize,
+		    argp->pgno, PGNO_INVALID, PGNO_INVALID, 0, P_INVALID);
+		ZERO_LSN(pagep->lsn);
+		ret = __db_add_limbo(dbenv, info, argp->fileid, argp->pgno, 1);
+		if ((t_ret =
+		    __memp_fput(mpf, pagep, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+			ret = t_ret;
+	}
+
+done:	if (ret == 0)
+		*lsnp = argp->prev_lsn;
+out:	REC_CLOSE;
+#else
+	COMPQUIET(dbenv, NULL);
+	COMPQUIET(dbtp, NULL);
+	COMPQUIET(lsnp, NULL);
+	COMPQUIET(op, DB_TXN_PRINT);
+	COMPQUIET(info, NULL);
+	return (0);
+#endif
+
+}
+
+/*
+ * __db_pg_init_recover --
+ *	Recovery function to reinit pages for truncate.
+ *
+ * PUBLIC: int __db_pg_init_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__db_pg_init_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__db_pg_init_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_LSN copy_lsn;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	COMPQUIET(info, NULL);
+	REC_PRINT(__db_pg_init_print);
+	REC_INTRO(__db_pg_init_read, 1);
+
+	mpf = file_dbp->mpf;
+	REC_FGET(mpf, argp->pgno, &pagep, done);
+
+	modified = 0;
+	(void)__ua_memcpy(&copy_lsn, &LSN(argp->header.data), sizeof(DB_LSN));
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+	cmp_p = log_compare(&LSN(pagep), &copy_lsn);
+	CHECK_LSN(op, cmp_p, &LSN(pagep), &copy_lsn);
+
+	if (cmp_p == 0 && DB_REDO(op)) {
+		P_INIT(pagep, file_dbp->pgsize, PGNO(pagep), PGNO_INVALID,
+		    PGNO_INVALID, TYPE(pagep) == P_HASH ? 0 : 1, TYPE(pagep));
+		pagep->lsn = *lsnp;
+		modified = 1;
+	} else if (cmp_n == 0 && DB_UNDO(op)) {
+		/* Put the data back on the page. */
+		memcpy(pagep, argp->header.data, argp->header.size);
+		if (argp->data.size > 0)
+			memcpy((u_int8_t*)pagep + pagep->hf_offset,
+			     argp->data.data, argp->data.size);
+
+		modified = 1;
+	}
+	if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+		goto out;
+
+done:	*lsnp = argp->prev_lsn;
+out:
+	REC_CLOSE;
+}
diff --git a/storage/bdb/db/db_reclaim.c b/storage/bdb/db/db_reclaim.c
index 9aa39bcfa9b8b07cca4de9da5a96a462c9d17353..4795b8caa08a77dc68a57c270fed1e733b0fe45d 100644
--- a/storage/bdb/db/db_reclaim.c
+++ b/storage/bdb/db/db_reclaim.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_reclaim.c,v 11.42 2004/06/10 04:46:44 ubell Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_reclaim.c,v 11.28 2002/08/06 06:11:17 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #include <string.h>
@@ -20,7 +18,7 @@ static const char revid[] = "$Id: db_reclaim.c,v 11.28 2002/08/06 06:11:17 bosti
 #include "dbinc/db_page.h"
 #include "dbinc/db_shash.h"
 #include "dbinc/btree.h"
-#include "dbinc/lock.h"
+#include "dbinc/mp.h"
 
 /*
  * __db_traverse_big
@@ -48,12 +46,18 @@ __db_traverse_big(dbp, pgno, callback, cookie)
 
 	do {
 		did_put = 0;
-		if ((ret = mpf->get(mpf, &pgno, 0, &p)) != 0)
+		if ((ret = __memp_fget(mpf, &pgno, 0, &p)) != 0)
 			return (ret);
+		/*
+		 * If we are freeing pages only process the overflow
+		 * chain if the head of the chain has a refcount of 1.
+		 */
 		pgno = NEXT_PGNO(p);
+		if (callback == __db_truncate_callback && OV_REF(p) != 1)
+			pgno = PGNO_INVALID;
 		if ((ret = callback(dbp, p, cookie, &did_put)) == 0 &&
 		    !did_put)
-			ret = mpf->put(mpf, p, 0);
+			ret = __memp_fput(mpf, p, 0);
 	} while (ret == 0 && pgno != PGNO_INVALID);
 
 	return (ret);
@@ -79,8 +83,15 @@ __db_reclaim_callback(dbp, p, cookie, putp)
 {
 	int ret;
 
-	COMPQUIET(dbp, NULL);
+	/*
+	 * We don't want to log the free of the root with the subdb.
+	 * If we abort then the subdb may not be openable to undo
+	 * the free.
+	 */
 
+	if ((dbp->type == DB_BTREE || dbp->type == DB_RECNO) &&
+	    PGNO(p) == ((BTREE *)dbp->bt_internal)->bt_root)
+		return (0);
 	if ((ret = __db_free(cookie, p)) != 0)
 		return (ret);
 	*putp = 1;
@@ -103,12 +114,9 @@ __db_truncate_callback(dbp, p, cookie, putp)
 	void *cookie;
 	int *putp;
 {
-	DBMETA *meta;
-	DBT ldbt;
-	DB_LOCK metalock;
 	DB_MPOOLFILE *mpf;
+	DBT ddbt, ldbt;
 	db_indx_t indx, len, off, tlen, top;
-	db_pgno_t pgno;
 	db_trunc_param *param;
 	u_int8_t *hk, type;
 	int ret;
@@ -147,7 +155,12 @@ __db_truncate_callback(dbp, p, cookie, putp)
 			*putp = 0;
 		break;
 	case P_LRECNO:
-		param->count += top;
+		for (indx = 0; indx < top; indx += O_INDX) {
+			type = GET_BKEYDATA(dbp, p, indx)->type;
+			if (!B_DISSET(type))
+				++param->count;
+		}
+
 		if (((BTREE *)dbp->bt_internal)->bt_root == PGNO(p)) {
 			type = P_LRECNO;
 			goto reinit;
@@ -165,8 +178,8 @@ __db_truncate_callback(dbp, p, cookie, putp)
 		for (indx = 0; indx < top; indx += P_INDX) {
 			switch (*H_PAIRDATA(dbp, p, indx)) {
 			case H_OFFDUP:
-			case H_OFFPAGE:
 				break;
+			case H_OFFPAGE:
 			case H_KEYDATA:
 				++param->count;
 				break;
@@ -174,12 +187,15 @@ __db_truncate_callback(dbp, p, cookie, putp)
 				tlen = LEN_HDATA(dbp, p, 0, indx);
 				hk = H_PAIRDATA(dbp, p, indx);
 				for (off = 0; off < tlen;
-				    off += len + 2 * sizeof (db_indx_t)) {
+				    off += len + 2 * sizeof(db_indx_t)) {
 					++param->count;
 					memcpy(&len,
 					    HKEYDATA_DATA(hk)
 					    + off, sizeof(db_indx_t));
 				}
+				break;
+			default:
+				return (__db_pgfmt(dbp->dbenv, p->pgno));
 			}
 		}
 		/* Don't free the head of the bucket. */
@@ -188,41 +204,16 @@ __db_truncate_callback(dbp, p, cookie, putp)
 
 reinit:			*putp = 0;
 			if (DBC_LOGGING(param->dbc)) {
-				pgno = PGNO_BASE_MD;
-				if ((ret = __db_lget(param->dbc, LCK_ALWAYS,
-				    pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
-					return (ret);
-				if ((ret = mpf->get(mpf,
-				    &pgno, 0, (PAGE **)&meta)) != 0) {
-					goto err;
-				}
 				memset(&ldbt, 0, sizeof(ldbt));
+				memset(&ddbt, 0, sizeof(ddbt));
 				ldbt.data = p;
 				ldbt.size = P_OVERHEAD(dbp);
-				if ((ret = __db_pg_free_log(dbp,
-				    param->dbc->txn, &LSN(meta), 0,
-				    p->pgno, &LSN(meta),
-				    PGNO_BASE_MD, &ldbt, meta->free)) != 0)
-					goto err;
-				LSN(p) = LSN(meta);
-
-				if ((ret =
-				    __db_pg_alloc_log(dbp,
-				    param->dbc->txn, &LSN(meta), 0,
-				    &LSN(meta), PGNO_BASE_MD,
-				    &p->lsn, p->pgno, type, meta->free)) != 0) {
-err:					(void)mpf->put(mpf, (PAGE *)meta, 0);
-					(void)__TLPUT(param->dbc, metalock);
-					return (ret);
-				}
-				LSN(p) = LSN(meta);
-
-				if ((ret = mpf->put(mpf,
-				    (PAGE *)meta, DB_MPOOL_DIRTY)) != 0) {
-					(void)__TLPUT(param->dbc, metalock);
-					return (ret);
-				}
-				if ((ret = __TLPUT(param->dbc, metalock)) != 0)
+				ldbt.size += p->entries * sizeof(db_indx_t);
+				ddbt.data = (u_int8_t *)p + p->hf_offset;
+				ddbt.size = dbp->pgsize - p->hf_offset;
+				if ((ret = __db_pg_init_log(dbp,
+				    param->dbc->txn, &LSN(p), 0,
+				    p->pgno, &ldbt, &ddbt)) != 0)
 					return (ret);
 			} else
 				LSN_NOT_LOGGED(LSN(p));
@@ -239,7 +230,7 @@ err:					(void)mpf->put(mpf, (PAGE *)meta, 0);
 		if ((ret = __db_free(param->dbc, p)) != 0)
 			return (ret);
 	} else {
-		if ((ret = mpf->put(mpf, p, DB_MPOOL_DIRTY)) != 0)
+		if ((ret = __memp_fput(mpf, p, DB_MPOOL_DIRTY)) != 0)
 			return (ret);
 		*putp = 1;
 	}
diff --git a/storage/bdb/db/db_remove.c b/storage/bdb/db/db_remove.c
index ef11c3425558e7ecdcdf3f318f93d15b1af942c2..5497c5e011d45c70a11c21501b93a5a173478019 100644
--- a/storage/bdb/db/db_remove.c
+++ b/storage/bdb/db/db_remove.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
+ * Copyright (c) 2001-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_remove.c,v 11.219 2004/09/16 17:55:17 margo Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_remove.c,v 11.203 2002/08/19 18:34:18 margo Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #endif
@@ -23,27 +21,25 @@ static const char revid[] = "$Id: db_remove.c,v 11.203 2002/08/19 18:34:18 margo
 #include "dbinc/db_shash.h"
 #include "dbinc/lock.h"
 
-static int __db_subdb_remove __P((DB *, DB_TXN *, const char *, const char *));
 static int __db_dbtxn_remove __P((DB *, DB_TXN *, const char *));
+static int __db_subdb_remove __P((DB *, DB_TXN *, const char *, const char *));
 
 /*
- * __dbenv_dbremove
- *	Remove method for DB_ENV.
+ * __dbenv_dbremove_pp
+ *	DB_ENV->dbremove pre/post processing.
  *
- * PUBLIC: int __dbenv_dbremove __P((DB_ENV *,
+ * PUBLIC: int __dbenv_dbremove_pp __P((DB_ENV *,
  * PUBLIC:     DB_TXN *, const char *, const char *, u_int32_t));
  */
 int
-__dbenv_dbremove(dbenv, txn, name, subdb, flags)
+__dbenv_dbremove_pp(dbenv, txn, name, subdb, flags)
 	DB_ENV *dbenv;
 	DB_TXN *txn;
 	const char *name, *subdb;
 	u_int32_t flags;
 {
 	DB *dbp;
-	int ret, t_ret, txn_local;
-
-	txn_local = 0;
+	int handle_check, ret, t_ret, txn_local;
 
 	PANIC_CHECK(dbenv);
 	ENV_ILLEGAL_BEFORE_OPEN(dbenv, "DB_ENV->dbremove");
@@ -52,63 +48,79 @@ __dbenv_dbremove(dbenv, txn, name, subdb, flags)
 	if ((ret = __db_fchk(dbenv, "DB->remove", flags, DB_AUTO_COMMIT)) != 0)
 		return (ret);
 
-	if ((ret = db_create(&dbp, dbenv, 0)) != 0)
-		return (ret);
-
 	/*
 	 * Create local transaction as necessary, check for consistent
 	 * transaction usage.
 	 */
 	if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
-		if ((ret = __db_txn_auto(dbp, &txn)) != 0)
+		if ((ret = __db_txn_auto_init(dbenv, &txn)) != 0)
 			return (ret);
 		txn_local = 1;
-	} else
+	} else {
 		if (txn != NULL && !TXN_ON(dbenv))
 			return (__db_not_txn_env(dbenv));
+		txn_local = 0;
+	}
 
-	ret = __db_remove_i(dbp, txn, name, subdb);
+	if ((ret = db_create(&dbp, dbenv, 0)) != 0)
+		goto err;
+
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check && (ret = __db_rep_enter(dbp, 1, 1, txn != NULL)) != 0)
+		goto err;
+
+	ret = __db_remove_int(dbp, txn, name, subdb, flags);
 
-	/* Commit for DB_AUTO_COMMIT. */
 	if (txn_local) {
-		if (ret == 0)
-			ret = txn->commit(txn, 0);
-		else
-			if ((t_ret = txn->abort(txn)) != 0)
-				ret = __db_panic(dbenv, t_ret);
 		/*
-		 * We created the DBP here and when we committed/aborted,
-		 * we release all the tranasctional locks, which includes
-		 * the handle lock; mark the handle cleared explicitly.
+		 * We created the DBP here and when we commit/abort, we'll
+		 * release all the transactional locks, including the handle
+		 * lock; mark the handle cleared explicitly.
 		 */
 		LOCK_INIT(dbp->handle_lock);
 		dbp->lid = DB_LOCK_INVALIDID;
+	} else if (txn != NULL) {
+		/*
+		 * We created this handle locally so we need to close it
+		 * and clean it up.  Unfortunately, it's holding transactional
+		 * locks that need to persist until the end of transaction.
+		 * If we invalidate the locker id (dbp->lid), then the close
+		 * won't free these locks prematurely.
+		 */
+		 dbp->lid = DB_LOCK_INVALIDID;
 	}
 
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
+
+err:	if (txn_local)
+		ret = __db_txn_auto_resolve(dbenv, txn, 0, ret);
+
 	/*
-	 * We never opened this dbp for real, so don't call the transactional
-	 * version of DB->close, and use NOSYNC to avoid calling into mpool.
+	 * We never opened this dbp for real, so don't include a transaction
+	 * handle, and use NOSYNC to avoid calling into mpool.
 	 */
-	if ((t_ret = dbp->close(dbp, DB_NOSYNC)) != 0 && ret == 0)
+	if ((t_ret = __db_close(dbp, NULL, DB_NOSYNC)) != 0 && ret == 0)
 		ret = t_ret;
 
 	return (ret);
 }
 
 /*
- * __db_remove
- *	Remove method for DB.
+ * __db_remove_pp
+ *	DB->remove pre/post processing.
  *
- * PUBLIC: int __db_remove __P((DB *, const char *, const char *, u_int32_t));
+ * PUBLIC: int __db_remove_pp
+ * PUBLIC:     __P((DB *, const char *, const char *, u_int32_t));
  */
 int
-__db_remove(dbp, name, subdb, flags)
+__db_remove_pp(dbp, name, subdb, flags)
 	DB *dbp;
 	const char *name, *subdb;
 	u_int32_t flags;
 {
 	DB_ENV *dbenv;
-	int ret, t_ret;
+	int handle_check, ret;
 
 	dbenv = dbp->dbenv;
 
@@ -126,57 +138,85 @@ __db_remove(dbp, name, subdb, flags)
 	 */
 	if (F_ISSET(dbp, DB_AM_OPEN_CALLED)) {
 		ret = __db_mi_open(dbenv, "DB->remove", 1);
-		goto err;
+		return (ret);
 	}
 
 	/* Validate arguments. */
 	if ((ret = __db_fchk(dbenv, "DB->remove", flags, 0)) != 0)
-		goto err;
+		return (ret);
 
 	/* Check for consistent transaction usage. */
 	if ((ret = __db_check_txn(dbp, NULL, DB_LOCK_INVALIDID, 0)) != 0)
-		goto err;
+		return (ret);
+
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check && (ret = __db_rep_enter(dbp, 1, 1, 0)) != 0)
+		return (ret);
 
 	/* Remove the file. */
-	ret = __db_remove_i(dbp, NULL, name, subdb);
+	ret = __db_remove(dbp, NULL, name, subdb, flags);
 
-	/*
-	 * We never opened this dbp for real, use NOSYNC to avoid calling into
-	 * mpool.
-	 */
-err:	if ((t_ret = dbp->close(dbp, DB_NOSYNC)) != 0 && ret == 0)
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
+/*
+ * __db_remove
+ *	DB->remove method.
+ *
+ * PUBLIC: int __db_remove
+ * PUBLIC:     __P((DB *, DB_TXN *, const char *, const char *, u_int32_t));
+ */
+int
+__db_remove(dbp, txn, name, subdb, flags)
+	DB *dbp;
+	DB_TXN *txn;
+	const char *name, *subdb;
+	u_int32_t flags;
+{
+	int ret, t_ret;
+
+	ret = __db_remove_int(dbp, txn, name, subdb, flags);
+
+	if ((t_ret = __db_close(dbp, txn, DB_NOSYNC)) != 0 && ret == 0)
 		ret = t_ret;
 
 	return (ret);
 }
 
 /*
- * __db_remove_i
- *	Internal remove method for DB.
+ * __db_remove_int
+ *	Worker function for the DB->remove method.
  *
- * PUBLIC: int __db_remove_i __P((DB *, DB_TXN *, const char *, const char *));
+ * PUBLIC: int __db_remove_int __P((DB *,
+ * PUBLIC:    DB_TXN *, const char *, const char *, u_int32_t));
  */
 int
-__db_remove_i(dbp, txn, name, subdb)
+__db_remove_int(dbp, txn, name, subdb, flags)
 	DB *dbp;
 	DB_TXN *txn;
 	const char *name, *subdb;
+	u_int32_t flags;
 {
 	DB_ENV *dbenv;
-	DB_LSN newlsn;
 	int ret;
-	char *real_name;
+	char *real_name, *tmpname;
 
 	dbenv = dbp->dbenv;
-	real_name = NULL;
+	real_name = tmpname = NULL;
 
 	/* Handle subdatabase removes separately. */
-	if (subdb != NULL)
-		return (__db_subdb_remove(dbp, txn, name, subdb));
+	if (subdb != NULL) {
+		ret = __db_subdb_remove(dbp, txn, name, subdb);
+		goto err;
+	}
 
 	/* Handle transactional file removes separately. */
-	if (txn != NULL)
-		return (__db_dbtxn_remove(dbp, txn, name));
+	if (txn != NULL) {
+		ret = __db_dbtxn_remove(dbp, txn, name);
+		goto err;
+	}
 
 	/*
 	 * The remaining case is a non-transactional file remove.
@@ -185,20 +225,30 @@ __db_remove_i(dbp, txn, name, subdb)
 	 */
 	if ((ret = __db_appname(dbenv,
 	    DB_APP_DATA, name, 0, NULL, &real_name)) != 0)
-		return (ret);
+		goto err;
+
+	/*
+	 * If force is set, remove the temporary file.  Ignore errors because
+	 * the backup file might not exist.
+	 */
+	if (LF_ISSET(DB_FORCE) &&
+	    (ret = __db_backup_name(dbenv, real_name, NULL, &tmpname)) == 0)
+		(void)__os_unlink(dbenv, tmpname);
 
 	if ((ret = __fop_remove_setup(dbp, NULL, real_name, 0)) != 0)
 		goto err;
 
 	if (dbp->db_am_remove != NULL &&
-	    (ret = dbp->db_am_remove(dbp, NULL, name, subdb, &newlsn)) != 0)
+	    (ret = dbp->db_am_remove(dbp, NULL, name, subdb)) != 0)
 		goto err;
 
-	ret = __fop_remove(dbenv, NULL, dbp->fileid, name, DB_APP_DATA);
+	ret = __fop_remove(dbenv, NULL, dbp->fileid, name, DB_APP_DATA,
+	    F_ISSET(dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0);
 
-err:
-	if (real_name != NULL)
+err:	if (real_name != NULL)
 		__os_free(dbenv, real_name);
+	if (tmpname != NULL)
+		__os_free(dbenv, tmpname);
 
 	return (ret);
 }
@@ -222,7 +272,7 @@ __db_subdb_remove(dbp, txn, name, subdb)
 	if ((ret = db_create(&sdbp, dbp->dbenv, 0)) != 0)
 		goto err;
 	if ((ret = __db_open(sdbp,
-	    txn, name, subdb, DB_UNKNOWN, DB_WRITEOPEN, 0)) != 0)
+	    txn, name, subdb, DB_UNKNOWN, DB_WRITEOPEN, 0, PGNO_BASE_MD)) != 0)
 		goto err;
 
 	DB_TEST_RECOVERY(sdbp, DB_TEST_PREDESTROY, ret, name);
@@ -238,6 +288,8 @@ __db_subdb_remove(dbp, txn, name, subdb)
 			if ((ret = __ham_reclaim(sdbp, txn)) != 0)
 				goto err;
 			break;
+		case DB_QUEUE:
+		case DB_UNKNOWN:
 		default:
 			ret = __db_unknown_type(
 			    sdbp->dbenv, "__db_subdb_remove", sdbp->type);
@@ -260,11 +312,11 @@ __db_subdb_remove(dbp, txn, name, subdb)
 DB_TEST_RECOVERY_LABEL
 err:
 	/* Close the main and subdatabases. */
-	if ((t_ret = __db_close_i(sdbp, txn, 0)) != 0 && ret == 0)
+	if ((t_ret = __db_close(sdbp, txn, 0)) != 0 && ret == 0)
 		ret = t_ret;
 
 	if (mdbp != NULL &&
-	    (t_ret = __db_close_i(mdbp, txn, 0)) != 0 && ret == 0)
+	    (t_ret = __db_close(mdbp, txn, DB_NOSYNC)) != 0 && ret == 0)
 		ret = t_ret;
 
 	return (ret);
@@ -277,7 +329,6 @@ __db_dbtxn_remove(dbp, txn, name)
 	const char *name;
 {
 	DB_ENV *dbenv;
-	DB_LSN newlsn;
 	int ret;
 	char *tmpname;
 
@@ -297,15 +348,16 @@ __db_dbtxn_remove(dbp, txn, name)
 
 	DB_TEST_RECOVERY(dbp, DB_TEST_PREDESTROY, ret, name);
 
-	if ((ret = __db_rename_i(dbp, txn, name, NULL, tmpname)) != 0)
+	if ((ret = __db_rename_int(dbp, txn, name, NULL, tmpname)) != 0)
 		goto err;
 
 	/* The internal removes will also translate into delayed removes. */
 	if (dbp->db_am_remove != NULL &&
-	    (ret = dbp->db_am_remove(dbp, txn, tmpname, NULL, &newlsn)) != 0)
+	    (ret = dbp->db_am_remove(dbp, txn, tmpname, NULL)) != 0)
 		goto err;
 
-	ret = __fop_remove(dbenv, txn, dbp->fileid, tmpname, DB_APP_DATA);
+	ret = __fop_remove(dbenv, txn, dbp->fileid, tmpname, DB_APP_DATA,
+	    F_ISSET(dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0);
 
 	DB_TEST_RECOVERY(dbp, DB_TEST_POSTDESTROY, ret, name);
 
diff --git a/storage/bdb/db/db_rename.c b/storage/bdb/db/db_rename.c
index 87f88232cdaa1e24d8790c71d64119f42f6a2efe..12f1f22760a836674d4a89cb1d275266d70d12d3 100644
--- a/storage/bdb/db/db_rename.c
+++ b/storage/bdb/db/db_rename.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
+ * Copyright (c) 2001-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_rename.c,v 11.216 2004/09/16 17:55:17 margo Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_rename.c,v 11.203 2002/08/07 16:16:47 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #include <string.h>
@@ -23,28 +21,28 @@ static const char revid[] = "$Id: db_rename.c,v 11.203 2002/08/07 16:16:47 bosti
 #include "dbinc/fop.h"
 #include "dbinc/lock.h"
 #include "dbinc/log.h"
+#include "dbinc/mp.h"
 
-static int __db_subdb_rename __P(( DB *, DB_TXN *,
-		const char *, const char *, const char *));
+static int __dbenv_dbrename __P((DB_ENV *,
+	       DB_TXN *, const char *, const char *, const char *, int));
+static int __db_subdb_rename __P((DB *,
+	       DB_TXN *, const char *, const char *, const char *));
 
 /*
- * __dbenv_dbrename
- *	Rename method for DB_ENV.
+ * __dbenv_dbrename_pp
+ *	DB_ENV->dbrename pre/post processing.
  *
- * PUBLIC: int __dbenv_dbrename __P((DB_ENV *, DB_TXN *,
+ * PUBLIC: int __dbenv_dbrename_pp __P((DB_ENV *, DB_TXN *,
  * PUBLIC:     const char *, const char *, const char *, u_int32_t));
  */
 int
-__dbenv_dbrename(dbenv, txn, name, subdb, newname, flags)
+__dbenv_dbrename_pp(dbenv, txn, name, subdb, newname, flags)
 	DB_ENV *dbenv;
 	DB_TXN *txn;
 	const char *name, *subdb, *newname;
 	u_int32_t flags;
 {
-	DB *dbp;
-	int ret, t_ret, txn_local;
-
-	txn_local = 0;
+	int ret, txn_local;
 
 	PANIC_CHECK(dbenv);
 	ENV_ILLEGAL_BEFORE_OPEN(dbenv, "DB_ENV->dbrename");
@@ -53,67 +51,97 @@ __dbenv_dbrename(dbenv, txn, name, subdb, newname, flags)
 	if ((ret = __db_fchk(dbenv, "DB->rename", flags, DB_AUTO_COMMIT)) != 0)
 		return (ret);
 
-	if ((ret = db_create(&dbp, dbenv, 0)) != 0)
-		return (ret);
-
 	/*
 	 * Create local transaction as necessary, check for consistent
 	 * transaction usage.
 	 */
 	if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
-		if ((ret = __db_txn_auto(dbp, &txn)) != 0)
+		if ((ret = __db_txn_auto_init(dbenv, &txn)) != 0)
 			return (ret);
 		txn_local = 1;
-	} else
+	} else {
 		if (txn != NULL && !TXN_ON(dbenv))
 			return (__db_not_txn_env(dbenv));
+		txn_local = 0;
+	}
 
-	ret = __db_rename_i(dbp, txn, name, subdb, newname);
+	ret = __dbenv_dbrename(dbenv, txn, name, subdb, newname, txn_local);
 
-	/* Commit for DB_AUTO_COMMIT. */
-	if (txn_local) {
-		if (ret == 0)
-			ret = txn->commit(txn, 0);
-		else
-			if ((t_ret = txn->abort(txn)) != 0)
-				ret = __db_panic(dbenv, t_ret);
+	return (txn_local ? __db_txn_auto_resolve(dbenv, txn, 0, ret) : ret);
+}
+
+/*
+ * __dbenv_dbrename
+ *	DB_ENV->dbrename.
+ */
+static int
+__dbenv_dbrename(dbenv, txn, name, subdb, newname, txn_local)
+	DB_ENV *dbenv;
+	DB_TXN *txn;
+	const char *name, *subdb, *newname;
+	int txn_local;
+{
+	DB *dbp;
+	int handle_check, ret, t_ret;
+
+	if ((ret = db_create(&dbp, dbenv, 0)) != 0)
+		return (ret);
+	if (txn != NULL)
+		F_SET(dbp, DB_AM_TXN);
+
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check && (ret = __db_rep_enter(dbp, 1, 1, txn != NULL)) != 0)
+		goto err;
+
+	ret = __db_rename_int(dbp, txn, name, subdb, newname);
 
+	if (txn_local) {
 		/*
-		 * We created the DBP here and when we committed/aborted,
-		 * we release all the tranasctional locks, which includes
-		 * the handle lock; mark the handle cleared explicitly.
+		 * We created the DBP here and when we commit/abort, we'll
+		 * release all the transactional locks, including the handle
+		 * lock; mark the handle cleared explicitly.
 		 */
 		LOCK_INIT(dbp->handle_lock);
 		dbp->lid = DB_LOCK_INVALIDID;
+	} else if (txn != NULL) {
+		/*
+		 * We created this handle locally so we need to close it
+		 * and clean it up.  Unfortunately, it's holding transactional
+		 * locks that need to persist until the end of transaction.
+		 * If we invalidate the locker id (dbp->lid), then the close
+		 * won't free these locks prematurely.
+		 */
+		 dbp->lid = DB_LOCK_INVALIDID;
 	}
 
-	/*
-	 * We never opened this dbp for real, so don't call the transactional
-	 * version of DB->close, and use NOSYNC to avoid calling into mpool.
-	 */
-	if ((t_ret = dbp->close(dbp, DB_NOSYNC)) != 0 && ret == 0)
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
+
+err:
+	if ((t_ret = __db_close(dbp, txn, DB_NOSYNC)) != 0 && ret == 0)
 		ret = t_ret;
 
 	return (ret);
 }
 
 /*
- * __db_rename
- *	Rename method for DB.
+ * __db_rename_pp
+ *	DB->rename pre/post processing.
  *
- * PUBLIC: int __db_rename __P((DB *,
+ * PUBLIC: int __db_rename_pp __P((DB *,
  * PUBLIC:     const char *, const char *, const char *, u_int32_t));
  */
 int
-__db_rename(dbp, name, subdb, newname, flags)
+__db_rename_pp(dbp, name, subdb, newname, flags)
 	DB *dbp;
 	const char *name, *subdb, *newname;
 	u_int32_t flags;
 {
 	DB_ENV *dbenv;
-	int ret, t_ret;
+	int handle_check, ret;
 
 	dbenv = dbp->dbenv;
+	handle_check = 0;
 
 	PANIC_CHECK(dbenv);
 
@@ -140,28 +168,54 @@ __db_rename(dbp, name, subdb, newname, flags)
 	if ((ret = __db_check_txn(dbp, NULL, DB_LOCK_INVALIDID, 0)) != 0)
 		goto err;
 
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check && (ret = __db_rep_enter(dbp, 1, 1, 0)) != 0) {
+		handle_check = 0;
+		goto err;
+	}
+
 	/* Rename the file. */
-	ret = __db_rename_i(dbp, NULL, name, subdb, newname);
+	ret = __db_rename(dbp, NULL, name, subdb, newname);
 
-	/*
-	 * We never opened this dbp for real, use NOSYNC to avoid calling into
-	 * mpool.
-	 */
-err:	if ((t_ret = dbp->close(dbp, DB_NOSYNC)) != 0 && ret == 0)
+err:	if (handle_check)
+		__env_db_rep_exit(dbenv);
+
+	return (ret);
+}
+
+/*
+ * __db_rename
+ *	DB->rename method.
+ *
+ * PUBLIC: int __db_rename
+ * PUBLIC:     __P((DB *, DB_TXN *, const char *, const char *, const char *));
+ */
+int
+__db_rename(dbp, txn, name, subdb, newname)
+	DB *dbp;
+	DB_TXN *txn;
+	const char *name, *subdb, *newname;
+{
+	int ret, t_ret;
+
+	ret = __db_rename_int(dbp, txn, name, subdb, newname);
+
+	if ((t_ret = __db_close(dbp, txn, DB_NOSYNC)) != 0 && ret == 0)
 		ret = t_ret;
 
 	return (ret);
 }
 
 /*
- * __db_rename_i
- *	Internal rename method for DB.
+ * __db_rename_int
+ *	Worker function for DB->rename method; the close of the dbp is
+ * left in the wrapper routine.
  *
- * PUBLIC: int __db_rename_i __P((DB *,
- * PUBLIC:      DB_TXN *, const char *, const char *, const char *));
+ * PUBLIC: int __db_rename_int
+ * PUBLIC:     __P((DB *, DB_TXN *, const char *, const char *, const char *));
  */
 int
-__db_rename_i(dbp, txn, name, subdb, newname)
+__db_rename_int(dbp, txn, name, subdb, newname)
 	DB *dbp;
 	DB_TXN *txn;
 	const char *name, *subdb, *newname;
@@ -180,9 +234,11 @@ __db_rename_i(dbp, txn, name, subdb, newname)
 		goto err;
 	}
 
-	/* From here on down, this pertains to files. */
-
-	/* Find the real name of the file. */
+	/*
+	 * From here on down, this pertains to files.
+	 *
+	 * Find the real name of the file.
+	 */
 	if ((ret = __db_appname(dbenv,
 	    DB_APP_DATA, name, 0, NULL, &real_name)) != 0)
 		goto err;
@@ -220,8 +276,7 @@ __db_rename_i(dbp, txn, name, subdb, newname)
 	DB_TEST_RECOVERY(dbp, DB_TEST_POSTDESTROY, ret, newname);
 
 DB_TEST_RECOVERY_LABEL
-err:
-	if (real_name != NULL)
+err:	if (real_name != NULL)
 		__os_free(dbenv, real_name);
 
 	return (ret);
@@ -265,14 +320,14 @@ __db_subdb_rename(dbp, txn, name, subdb, newname)
 	    MU_OPEN, NULL, 0)) != 0)
 		goto err;
 
-	if ((ret = mdbp->mpf->get(mdbp->mpf, &dbp->meta_pgno, 0, &meta)) != 0)
+	if ((ret = __memp_fget(mdbp->mpf, &dbp->meta_pgno, 0, &meta)) != 0)
 		goto err;
-	memcpy(&dbp->fileid, ((DBMETA *)meta)->uid, DB_FILE_ID_LEN);
+	memcpy(dbp->fileid, ((DBMETA *)meta)->uid, DB_FILE_ID_LEN);
 	if ((ret = __fop_lock_handle(dbenv,
-	    dbp, mdbp->lid, DB_LOCK_WRITE, NULL, 0)) != 0)
+	    dbp, mdbp->lid, DB_LOCK_WRITE, NULL, NOWAIT_FLAG(txn))) != 0)
 		goto err;
 
-	ret = mdbp->mpf->put(mdbp->mpf, meta, 0);
+	ret = __memp_fput(mdbp->mpf, meta, 0);
 	meta = NULL;
 	if (ret != 0)
 		goto err;
@@ -286,11 +341,11 @@ __db_subdb_rename(dbp, txn, name, subdb, newname)
 DB_TEST_RECOVERY_LABEL
 err:
 	if (meta != NULL &&
-	    (t_ret = mdbp->mpf->put(mdbp->mpf, meta, 0)) != 0 && ret == 0)
+	    (t_ret = __memp_fput(mdbp->mpf, meta, 0)) != 0 && ret == 0)
 		ret = t_ret;
 
 	if (mdbp != NULL &&
-	    (t_ret = __db_close_i(mdbp, txn, 0)) != 0 && ret == 0)
+	    (t_ret = __db_close(mdbp, txn, DB_NOSYNC)) != 0 && ret == 0)
 		ret = t_ret;
 
 	return (ret);
diff --git a/storage/bdb/db/db_ret.c b/storage/bdb/db/db_ret.c
index b1af7b4ffebe58ca14defba2b2b8cc65b3394856..99421eccc188b1e6d24b71ace5a284c9c7a1dfa8 100644
--- a/storage/bdb/db/db_ret.c
+++ b/storage/bdb/db/db_ret.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_ret.c,v 11.26 2004/02/05 02:25:13 mjc Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_ret.c,v 11.21 2002/03/28 19:21:47 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -92,6 +90,8 @@ __db_retcopy(dbenv, dbt, data, len, memp, memsize)
 {
 	int ret;
 
+	ret = 0;
+
 	/* If returning a partial record, reset the length. */
 	if (F_ISSET(dbt, DB_DBT_PARTIAL)) {
 		data = (u_int8_t *)data + dbt->doff;
@@ -103,14 +103,6 @@ __db_retcopy(dbenv, dbt, data, len, memp, memsize)
 			len = 0;
 	}
 
-	/*
-	 * Return the length of the returned record in the DBT size field.
-	 * This satisfies the requirement that if we're using user memory
-	 * and insufficient memory was provided, return the amount necessary
-	 * in the size field.
-	 */
-	dbt->size = len;
-
 	/*
 	 * Allocate memory to be owned by the application: DB_DBT_MALLOC,
 	 * DB_DBT_REALLOC.
@@ -127,28 +119,36 @@ __db_retcopy(dbenv, dbt, data, len, memp, memsize)
 	 * memory pointer is allowed to be NULL.
 	 */
 	if (F_ISSET(dbt, DB_DBT_MALLOC)) {
-		if ((ret = __os_umalloc(dbenv, len, &dbt->data)) != 0)
-			return (ret);
+		ret = __os_umalloc(dbenv, len, &dbt->data);
 	} else if (F_ISSET(dbt, DB_DBT_REALLOC)) {
-		if ((ret = __os_urealloc(dbenv, len, &dbt->data)) != 0)
-			return (ret);
+		if (dbt->data == NULL || dbt->size == 0 || dbt->size < len)
+			ret = __os_urealloc(dbenv, len, &dbt->data);
 	} else if (F_ISSET(dbt, DB_DBT_USERMEM)) {
 		if (len != 0 && (dbt->data == NULL || dbt->ulen < len))
-			return (ENOMEM);
+			ret = DB_BUFFER_SMALL;
 	} else if (memp == NULL || memsize == NULL) {
-		return (EINVAL);
+		ret = EINVAL;
 	} else {
 		if (len != 0 && (*memsize == 0 || *memsize < len)) {
-			if ((ret = __os_realloc(dbenv, len, memp)) != 0) {
+			if ((ret = __os_realloc(dbenv, len, memp)) == 0)
+				*memsize = len;
+			else
 				*memsize = 0;
-				return (ret);
-			}
-			*memsize = len;
 		}
-		dbt->data = *memp;
+		if (ret == 0)
+			dbt->data = *memp;
 	}
 
-	if (len != 0)
+	if (ret == 0 && len != 0)
 		memcpy(dbt->data, data, len);
-	return (0);
+
+	/*
+	 * Return the length of the returned record in the DBT size field.
+	 * This satisfies the requirement that if we're using user memory
+	 * and insufficient memory was provided, return the amount necessary
+	 * in the size field.
+	 */
+	dbt->size = len;
+
+	return (ret);
 }
diff --git a/storage/bdb/db/db_setid.c b/storage/bdb/db/db_setid.c
new file mode 100644
index 0000000000000000000000000000000000000000..fffba1c6dcb388946fbca42ccea8fbd9139ff883
--- /dev/null
+++ b/storage/bdb/db/db_setid.c
@@ -0,0 +1,155 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2000-2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_setid.c,v 1.6 2004/09/24 13:41:08 bostic Exp $
+ */
+
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_swap.h"
+#include "dbinc/db_am.h"
+
+/*
+ * __db_fileid_reset --
+ *	Reset the file IDs for every database in the file.
+ *
+ * PUBLIC: int __db_fileid_reset __P((DB_ENV *, char *, int));
+ */
+int
+__db_fileid_reset(dbenv, name, passwd)
+	DB_ENV *dbenv;
+	char *name;
+	int passwd;
+{
+	DB *dbp;
+	DBC *dbcp;
+	DBT key, data;
+	DB_MPOOLFILE *mpf;
+	db_pgno_t pgno;
+	int t_ret, ret;
+	void *pagep;
+	char *real_name;
+	u_int8_t fileid[DB_FILE_ID_LEN];
+
+	dbp = NULL;
+	dbcp = NULL;
+	real_name = NULL;
+
+	/* Get the real backing file name. */
+	if ((ret = __db_appname(dbenv,
+	    DB_APP_DATA, name, 0, NULL, &real_name)) != 0)
+		return (ret);
+
+	/* Get a new file ID. */
+	if ((ret = __os_fileid(dbenv, real_name, 1, fileid)) != 0) {
+		dbenv->err(dbenv, ret, "unable to get new file ID");
+		goto err;
+	}
+
+	/* Create the DB object. */
+	if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
+		dbenv->err(dbenv, ret, "db_create");
+		goto err;
+	}
+
+	/* If configured with a password, the databases are encrypted. */
+	if (passwd && (ret = dbp->set_flags(dbp, DB_ENCRYPT)) != 0) {
+		dbp->err(dbp, ret, "DB->set_flags: DB_ENCRYPT");
+		goto err;
+	}
+
+	/*
+	 * Open the DB file.
+	 *
+	 * !!!
+	 * Note DB_RDWRMASTER flag, we need to open the master database file
+	 * for writing in this case.
+	 */
+	if ((ret = dbp->open(dbp,
+	    NULL, name, NULL, DB_UNKNOWN, DB_RDWRMASTER, 0)) != 0) {
+		dbp->err(dbp, ret, "DB->open: %s", name);
+		goto err;
+	}
+
+	mpf = dbp->mpf;
+
+	pgno = PGNO_BASE_MD;
+	if ((ret = mpf->get(mpf, &pgno, 0, &pagep)) != 0) {
+		dbp->err(dbp, ret,
+		    "%s: DB_MPOOLFILE->get: %lu", name, (u_long)pgno);
+		goto err;
+	}
+	memcpy(((DBMETA *)pagep)->uid, fileid, DB_FILE_ID_LEN);
+	if ((ret = mpf->put(mpf, pagep, DB_MPOOL_DIRTY)) != 0) {
+		dbp->err(dbp, ret,
+		    "%s: DB_MPOOLFILE->put: %lu", name, (u_long)pgno);
+		goto err;
+	}
+
+	/*
+	 * If the database file doesn't support subdatabases, we only have
+	 * to update a single metadata page.  Otherwise, we have to open a
+	 * cursor and step through the master database, and update all of
+	 * the subdatabases' metadata pages.
+	 */
+	if (!F_ISSET(dbp, DB_AM_SUBDB))
+		goto err;
+
+	memset(&key, 0, sizeof(key));
+	memset(&data, 0, sizeof(data));
+	if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) {
+		dbp->err(dbp, ret, "DB->cursor");
+		goto err;
+	}
+	while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0) {
+		/*
+		 * XXX
+		 * We're handling actual data, not on-page meta-data, so it
+		 * hasn't been converted to/from opposite endian architectures.
+		 * Do it explicitly, now.
+		 */
+		memcpy(&pgno, data.data, sizeof(db_pgno_t));
+		DB_NTOHL(&pgno);
+		if ((ret = mpf->get(mpf, &pgno, 0, &pagep)) != 0) {
+			dbp->err(dbp, ret,
+			    "%s: DB_MPOOLFILE->get: %lu", name, (u_long)pgno);
+			goto err;
+		}
+		memcpy(((DBMETA *)pagep)->uid, fileid, DB_FILE_ID_LEN);
+		if ((ret = mpf->put(mpf, pagep, DB_MPOOL_DIRTY)) != 0) {
+			dbp->err(dbp, ret,
+			    "%s: DB_MPOOLFILE->put: %lu", name, (u_long)pgno);
+			goto err;
+		}
+	}
+	if (ret == DB_NOTFOUND)
+		ret = 0;
+	else
+		dbp->err(dbp, ret, "DBcursor->get");
+
+err:	if (dbcp != NULL && (t_ret = dbcp->c_close(dbcp)) != 0) {
+		dbp->err(dbp, ret, "DBcursor->close");
+		if (ret == 0)
+			ret = t_ret;
+	}
+	if (dbp != NULL && (t_ret = dbp->close(dbp, 0)) != 0) {
+		dbenv->err(dbenv, ret, "DB->close");
+		if (ret == 0)
+			ret = t_ret;
+	}
+	if (real_name != NULL)
+		__os_free(dbenv, real_name);
+
+	return (ret);
+}
diff --git a/storage/bdb/db/db_setlsn.c b/storage/bdb/db/db_setlsn.c
new file mode 100644
index 0000000000000000000000000000000000000000..5865798e508b56a9e02d6b410c6eabffc7d680a4
--- /dev/null
+++ b/storage/bdb/db/db_setlsn.c
@@ -0,0 +1,83 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2000-2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_setlsn.c,v 1.2 2004/04/27 16:10:13 bostic Exp $
+ */
+
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
+
+/*
+ * __db_lsn_reset --
+ *	Reset the LSNs for every page in the file.
+ *
+ * PUBLIC: int __db_lsn_reset __P((DB_ENV *, char *, int));
+ */
+int
+__db_lsn_reset(dbenv, name, passwd)
+	DB_ENV *dbenv;
+	char *name;
+	int passwd;
+{
+	DB *dbp;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	db_pgno_t pgno;
+	int t_ret, ret;
+
+	/* Create the DB object. */
+	if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
+		dbenv->err(dbenv, ret, "db_create");
+		return (1);
+	}
+
+	/* If configured with a password, the databases are encrypted. */
+	if (passwd && (ret = dbp->set_flags(dbp, DB_ENCRYPT)) != 0) {
+		dbp->err(dbp, ret, "DB->set_flags: DB_ENCRYPT");
+		goto err;
+	}
+
+	/*
+	 * Open the DB file.
+	 *
+	 * !!!
+	 * Note DB_RDWRMASTER flag, we need to open the master database file
+	 * for writing in this case.
+	 */
+	if ((ret = dbp->open(dbp,
+	    NULL, name, NULL, DB_UNKNOWN, DB_RDWRMASTER, 0)) != 0) {
+		dbp->err(dbp, ret, "DB->open: %s", name);
+		goto err;
+	}
+
+	/* Reset the LSN on every page of the database file. */
+	mpf = dbp->mpf;
+	for (pgno = 0; (ret = mpf->get(mpf, &pgno, 0, &pagep)) == 0; ++pgno) {
+		LSN_NOT_LOGGED(pagep->lsn);
+		if ((ret = mpf->put(mpf, pagep, DB_MPOOL_DIRTY)) != 0) {
+			dbp->err(dbp, ret, "DB_MPOOLFILE->put: %s", name);
+			goto err;
+		}
+	}
+
+	if (ret == DB_PAGE_NOTFOUND)
+		ret = 0;
+	else
+		dbp->err(dbp, ret, "DB_MPOOLFILE->get: %s", name);
+
+err:	if ((t_ret = dbp->close(dbp, 0)) != 0 && ret == 0)
+		ret = t_ret;
+	return (ret == 0 ? 0 : 1);
+}
diff --git a/storage/bdb/db/db_stati.c b/storage/bdb/db/db_stati.c
new file mode 100644
index 0000000000000000000000000000000000000000..cd73b8ea47710127c564d4c7312836c54f44386e
--- /dev/null
+++ b/storage/bdb/db/db_stati.c
@@ -0,0 +1,500 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_stati.c,v 11.123 2004/07/19 16:40:51 bostic Exp $
+ */
+
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#if TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#endif
+
+#include <string.h>
+#endif
+
+#include "db_int.h"
+
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/btree.h"
+#include "dbinc/hash.h"
+#include "dbinc/qam.h"
+#include "dbinc/log.h"
+#include "dbinc/mp.h"
+
+#ifdef HAVE_STATISTICS
+static int __db_print_all __P((DB *, u_int32_t));
+static int __db_print_citem __P((DBC *));
+static int __db_print_cursor __P((DB *));
+static int __db_print_stats __P((DB *, u_int32_t));
+static int __db_stat_arg __P((DB *, u_int32_t));
+
+/*
+ * __db_stat_pp --
+ *	DB->stat pre/post processing.
+ *
+ * PUBLIC: int __db_stat_pp __P((DB *, DB_TXN *, void *, u_int32_t));
+ */
+int
+__db_stat_pp(dbp, txn, spp, flags)
+	DB *dbp;
+	DB_TXN *txn;
+	void *spp;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	int handle_check, ret;
+
+	dbenv = dbp->dbenv;
+
+	PANIC_CHECK(dbp->dbenv);
+	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->stat");
+
+	if ((ret = __db_stat_arg(dbp, flags)) != 0)
+		return (ret);
+
+	/* Check for replication block. */
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, 0)) != 0)
+		return (ret);
+
+	ret = __db_stat(dbp, txn, spp, flags);
+
+	/* Release replication block. */
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
+
+	return (ret);
+}
+
+/*
+ * __db_stat --
+ *	DB->stat.
+ *
+ * PUBLIC: int __db_stat __P((DB *, DB_TXN *, void *, u_int32_t));
+ */
+int
+__db_stat(dbp, txn, spp, flags)
+	DB *dbp;
+	DB_TXN *txn;
+	void *spp;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	DBC *dbc;
+	int ret, t_ret;
+
+	dbenv = dbp->dbenv;
+
+	/* Acquire a cursor. */
+	if ((ret = __db_cursor(dbp, txn,
+	     &dbc, LF_ISSET(DB_DEGREE_2 | DB_DIRTY_READ))) != 0)
+		return (ret);
+
+	DEBUG_LWRITE(dbc, NULL, "DB->stat", NULL, NULL, flags);
+	LF_CLR(DB_DEGREE_2 | DB_DIRTY_READ);
+
+	switch (dbp->type) {
+	case DB_BTREE:
+	case DB_RECNO:
+		ret = __bam_stat(dbc, spp, flags);
+		break;
+	case DB_HASH:
+		ret = __ham_stat(dbc, spp, flags);
+		break;
+	case DB_QUEUE:
+		ret = __qam_stat(dbc, spp, flags);
+		break;
+	case DB_UNKNOWN:
+	default:
+		ret = (__db_unknown_type(dbenv, "DB->stat", dbp->type));
+		break;
+	}
+
+	if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
+		ret = t_ret;
+
+	return (ret);
+}
+
+/*
+ * __db_stat_arg --
+ *	Check DB->stat arguments.
+ */
+static int
+__db_stat_arg(dbp, flags)
+	DB *dbp;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbp->dbenv;
+
+	/* Check for invalid function flags. */
+	LF_CLR(DB_DEGREE_2 | DB_DIRTY_READ);
+	switch (flags) {
+	case 0:
+	case DB_FAST_STAT:
+	case DB_CACHED_COUNTS:		/* Deprecated and undocumented. */
+		break;
+	case DB_RECORDCOUNT:		/* Deprecated and undocumented. */
+		if (dbp->type == DB_RECNO)
+			break;
+		if (dbp->type == DB_BTREE && F_ISSET(dbp, DB_AM_RECNUM))
+			break;
+		/* FALLTHROUGH */
+	default:
+		return (__db_ferr(dbenv, "DB->stat", 0));
+	}
+
+	return (0);
+}
+
+/*
+ * __db_stat_print_pp --
+ *	DB->stat_print pre/post processing.
+ *
+ * PUBLIC: int __db_stat_print_pp __P((DB *, u_int32_t));
+ */
+int
+__db_stat_print_pp(dbp, flags)
+	DB *dbp;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	int handle_check, ret;
+
+	dbenv = dbp->dbenv;
+
+	PANIC_CHECK(dbenv);
+	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->stat");
+
+	/*
+	 * !!!
+	 * The actual argument checking is simple, do it inline.
+	 */
+	if ((ret = __db_fchk(dbenv, "DB->stat_print",
+	    flags, DB_STAT_ALL | DB_STAT_CLEAR)) != 0)
+		return (ret);
+
+	/* Check for replication block. */
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, 0)) != 0)
+		return (ret);
+
+	ret = __db_stat_print(dbp, flags);
+
+	/* Release replication block. */
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
+
+	return (ret);
+}
+
+/*
+ * __db_stat_print --
+ *	DB->stat_print.
+ *
+ * PUBLIC: int __db_stat_print __P((DB *, u_int32_t));
+ */
+int
+__db_stat_print(dbp, flags)
+	DB *dbp;
+	u_int32_t flags;
+{
+	int ret;
+
+	if (flags == 0 || LF_ISSET(DB_STAT_ALL)) {
+		ret = __db_print_stats(dbp, flags);
+		if (flags == 0 || ret != 0)
+			return (ret);
+	}
+
+	if (LF_ISSET(DB_STAT_ALL) && (ret = __db_print_all(dbp, flags)) != 0)
+		return (ret);
+
+	return (0);
+}
+
+/*
+ * __db_print_stats --
+ *	Display default DB handle statistics.
+ */
+static int
+__db_print_stats(dbp, flags)
+	DB *dbp;
+	u_int32_t flags;
+{
+	DBC *dbc;
+	DB_ENV *dbenv;
+	int ret, t_ret;
+
+	dbenv = dbp->dbenv;
+
+	/* Acquire a cursor. */
+	if ((ret = __db_cursor(dbp, NULL, &dbc, 0)) != 0)
+		return (ret);
+
+	DEBUG_LWRITE(dbc, NULL, "DB->stat_print", NULL, NULL, 0);
+
+	switch (dbp->type) {
+	case DB_BTREE:
+	case DB_RECNO:
+		ret = __bam_stat_print(dbc, flags);
+		break;
+	case DB_HASH:
+		ret = __ham_stat_print(dbc, flags);
+		break;
+	case DB_QUEUE:
+		ret = __qam_stat_print(dbc, flags);
+		break;
+	case DB_UNKNOWN:
+	default:
+		ret = (__db_unknown_type(dbenv, "DB->stat_print", dbp->type));
+		break;
+	}
+
+	if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
+		ret = t_ret;
+
+	return (ret);
+}
+
+/*
+ * __db_print_all --
+ *	Display debugging DB handle statistics.
+ */
+static int
+__db_print_all(dbp, flags)
+	DB *dbp;
+	u_int32_t flags;
+{
+	static const FN fn[] = {
+		{ DB_AM_CHKSUM,		"DB_AM_CHKSUM" },
+		{ DB_AM_CL_WRITER,	"DB_AM_CL_WRITER" },
+		{ DB_AM_COMPENSATE,	"DB_AM_COMPENSATE" },
+		{ DB_AM_CREATED,	"DB_AM_CREATED" },
+		{ DB_AM_CREATED_MSTR,	"DB_AM_CREATED_MSTR" },
+		{ DB_AM_DBM_ERROR,	"DB_AM_DBM_ERROR" },
+		{ DB_AM_DELIMITER,	"DB_AM_DELIMITER" },
+		{ DB_AM_DIRTY,		"DB_AM_DIRTY" },
+		{ DB_AM_DISCARD,	"DB_AM_DISCARD" },
+		{ DB_AM_DUP,		"DB_AM_DUP" },
+		{ DB_AM_DUPSORT,	"DB_AM_DUPSORT" },
+		{ DB_AM_ENCRYPT,	"DB_AM_ENCRYPT" },
+		{ DB_AM_FIXEDLEN,	"DB_AM_FIXEDLEN" },
+		{ DB_AM_INMEM,		"DB_AM_INMEM" },
+		{ DB_AM_IN_RENAME,	"DB_AM_IN_RENAME" },
+		{ DB_AM_NOT_DURABLE,	"DB_AM_NOT_DURABLE" },
+		{ DB_AM_OPEN_CALLED,	"DB_AM_OPEN_CALLED" },
+		{ DB_AM_PAD,		"DB_AM_PAD" },
+		{ DB_AM_PGDEF,		"DB_AM_PGDEF" },
+		{ DB_AM_RDONLY,		"DB_AM_RDONLY" },
+		{ DB_AM_RECNUM,		"DB_AM_RECNUM" },
+		{ DB_AM_RECOVER,	"DB_AM_RECOVER" },
+		{ DB_AM_RENUMBER,	"DB_AM_RENUMBER" },
+		{ DB_AM_REPLICATION,	"DB_AM_REPLICATION" },
+		{ DB_AM_REVSPLITOFF,	"DB_AM_REVSPLITOFF" },
+		{ DB_AM_SECONDARY,	"DB_AM_SECONDARY" },
+		{ DB_AM_SNAPSHOT,	"DB_AM_SNAPSHOT" },
+		{ DB_AM_SUBDB,		"DB_AM_SUBDB" },
+		{ DB_AM_SWAP,		"DB_AM_SWAP" },
+		{ DB_AM_TXN,		"DB_AM_TXN" },
+		{ DB_AM_VERIFYING,	"DB_AM_VERIFYING" },
+		{ 0,			NULL }
+	};
+	DB_ENV *dbenv;
+
+	dbenv = dbp->dbenv;
+
+	__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+	__db_msg(dbenv, "DB handle information:");
+	STAT_ULONG("Page size", dbp->pgsize);
+	STAT_ISSET("Append recno", dbp->db_append_recno);
+	STAT_ISSET("Feedback", dbp->db_feedback);
+	STAT_ISSET("Dup compare", dbp->dup_compare);
+	STAT_ISSET("App private", dbp->app_private);
+	STAT_ISSET("DbEnv", dbp->dbenv);
+	STAT_STRING("Type", __db_dbtype_to_string(dbp->type));
+
+	__db_print_mutex(dbenv, NULL, dbp->mutexp, "Thread mutex", flags);
+
+	STAT_STRING("File", dbp->fname);
+	STAT_STRING("Database", dbp->dname);
+	STAT_HEX("Open flags", dbp->open_flags);
+
+	__db_print_fileid(dbenv, dbp->fileid, "\tFile ID");
+
+	STAT_ULONG("Cursor adjust ID", dbp->adj_fileid);
+	STAT_ULONG("Meta pgno", dbp->meta_pgno);
+	STAT_ULONG("Locker ID", dbp->lid);
+	STAT_ULONG("Handle lock", dbp->cur_lid);
+	STAT_ULONG("Associate lock", dbp->associate_lid);
+	STAT_ULONG("RPC remote ID", dbp->cl_id);
+
+	__db_msg(dbenv,
+	    "%.24s\tReplication handle timestamp",
+	    dbp->timestamp == 0 ? "0" : ctime(&dbp->timestamp));
+
+	STAT_ISSET("Secondary callback", dbp->s_callback);
+	STAT_ISSET("Primary handle", dbp->s_primary);
+
+	STAT_ISSET("api internal", dbp->api_internal);
+	STAT_ISSET("Btree/Recno internal", dbp->bt_internal);
+	STAT_ISSET("Hash internal", dbp->h_internal);
+	STAT_ISSET("Queue internal", dbp->q_internal);
+	STAT_ISSET("XA internal", dbp->xa_internal);
+
+	__db_prflags(dbenv, NULL, dbp->flags, fn, NULL, "\tFlags");
+
+	if (dbp->log_filename == NULL)
+		STAT_ISSET("File naming information", dbp->log_filename);
+	else
+		__dbreg_print_fname(dbenv, dbp->log_filename);
+
+	(void)__db_print_cursor(dbp);
+
+	return (0);
+}
+
+/*
+ * __db_print_cursor --
+ *	Display the cursor active and free queues.
+ */
+static int
+__db_print_cursor(dbp)
+	DB *dbp;
+{
+	DB_ENV *dbenv;
+	DBC *dbc;
+	int ret, t_ret;
+
+	dbenv = dbp->dbenv;
+
+	__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+	__db_msg(dbenv, "DB handle cursors:");
+
+	ret = 0;
+	MUTEX_THREAD_LOCK(dbp->dbenv, dbp->mutexp);
+	__db_msg(dbenv, "Active queue:");
+	for (dbc = TAILQ_FIRST(&dbp->active_queue);
+	    dbc != NULL; dbc = TAILQ_NEXT(dbc, links))
+		if ((t_ret = __db_print_citem(dbc)) != 0 && ret == 0)
+			ret = t_ret;
+	__db_msg(dbenv, "Join queue:");
+	for (dbc = TAILQ_FIRST(&dbp->join_queue);
+	    dbc != NULL; dbc = TAILQ_NEXT(dbc, links))
+		if ((t_ret = __db_print_citem(dbc)) != 0 && ret == 0)
+			ret = t_ret;
+	__db_msg(dbenv, "Free queue:");
+	for (dbc = TAILQ_FIRST(&dbp->free_queue);
+	    dbc != NULL; dbc = TAILQ_NEXT(dbc, links))
+		if ((t_ret = __db_print_citem(dbc)) != 0 && ret == 0)
+			ret = t_ret;
+	MUTEX_THREAD_UNLOCK(dbp->dbenv, dbp->mutexp);
+
+	return (ret);
+}
+
+static
+int __db_print_citem(dbc)
+	DBC *dbc;
+{
+	static const FN fn[] = {
+		{ DBC_ACTIVE,		"DBC_ACTIVE" },
+		{ DBC_COMPENSATE,	"DBC_COMPENSATE" },
+		{ DBC_DEGREE_2,		"DBC_DEGREE_2" },
+		{ DBC_DIRTY_READ,	"DBC_DIRTY_READ" },
+		{ DBC_OPD,		"DBC_OPD" },
+		{ DBC_RECOVER,		"DBC_RECOVER" },
+		{ DBC_RMW,		"DBC_RMW" },
+		{ DBC_TRANSIENT,	"DBC_TRANSIENT" },
+		{ DBC_WRITECURSOR,	"DBC_WRITECURSOR" },
+		{ DBC_WRITER,		"DBC_WRITER" },
+		{ DBC_MULTIPLE,		"DBC_MULTIPLE" },
+		{ DBC_MULTIPLE_KEY,	"DBC_MULTIPLE_KEY" },
+		{ DBC_OWN_LID,		"DBC_OWN_LID" },
+		{ 0,			NULL }
+	};
+	DB *dbp;
+	DBC_INTERNAL *cp;
+	DB_ENV *dbenv;
+
+	dbp = dbc->dbp;
+	dbenv = dbp->dbenv;
+	cp = dbc->internal;
+
+	STAT_HEX("DBC", dbc);
+	STAT_HEX("Associated dbp", dbc->dbp);
+	STAT_HEX("Associated txn", dbc->txn);
+	STAT_HEX("Internal", cp);
+	STAT_HEX("Default locker ID", dbc->lid);
+	STAT_HEX("Locker", dbc->locker);
+	STAT_STRING("Type", __db_dbtype_to_string(dbc->dbtype));
+
+	STAT_HEX("Off-page duplicate cursor", cp->opd);
+	STAT_HEX("Referenced page", cp->page);
+	STAT_ULONG("Root", cp->root);
+	STAT_ULONG("Page number", cp->pgno);
+	STAT_ULONG("Page index", cp->indx);
+	STAT_STRING("Lock mode", __db_lockmode_to_string(cp->lock_mode));
+	__db_prflags(dbenv, NULL, dbc->flags, fn, NULL, "\tFlags");
+
+	switch (dbc->dbtype) {
+	case DB_BTREE:
+	case DB_RECNO:
+		__bam_print_cursor(dbc);
+		break;
+	case DB_HASH:
+		__ham_print_cursor(dbc);
+		break;
+	case DB_UNKNOWN:
+		DB_ASSERT(dbp->type != DB_UNKNOWN);
+		/* FALLTHROUGH */
+	case DB_QUEUE:
+	default:
+		break;
+	}
+	return (0);
+}
+
+#else /* !HAVE_STATISTICS */
+
+int
+__db_stat_pp(dbp, txn, spp, flags)
+	DB *dbp;
+	DB_TXN *txn;
+	void *spp;
+	u_int32_t flags;
+{
+	COMPQUIET(spp, NULL);
+	COMPQUIET(txn, NULL);
+	COMPQUIET(flags, 0);
+
+	return (__db_stat_not_built(dbp->dbenv));
+}
+
+int
+__db_stat_print_pp(dbp, flags)
+	DB *dbp;
+	u_int32_t flags;
+{
+	COMPQUIET(flags, 0);
+
+	return (__db_stat_not_built(dbp->dbenv));
+}
+#endif
diff --git a/storage/bdb/db/db_truncate.c b/storage/bdb/db/db_truncate.c
index 49546ae51b9a633c1edb2104e3344100db4a48f1..801f3712ffbc4530ea4651ae50dd232aaaa473af 100644
--- a/storage/bdb/db/db_truncate.c
+++ b/storage/bdb/db/db_truncate.c
@@ -1,95 +1,202 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
+ * Copyright (c) 2001-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_truncate.c,v 11.201 2004/07/15 15:52:51 sue Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_truncate.c,v 11.185 2002/08/07 16:16:48 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
+
+#include <string.h>
 #endif
 
 #include "db_int.h"
 #include "dbinc/db_page.h"
+#include "dbinc/log.h"
 #include "dbinc/btree.h"
 #include "dbinc/hash.h"
 #include "dbinc/qam.h"
+#include "dbinc/txn.h"
+
+static int __db_cursor_check __P((DB *));
 
 /*
- * __db_truncate
- *	truncate method for DB.
+ * __db_truncate_pp
+ *	DB->truncate pre/post processing.
  *
- * PUBLIC: int __db_truncate __P((DB *, DB_TXN *, u_int32_t *, u_int32_t));
+ * PUBLIC: int __db_truncate_pp __P((DB *, DB_TXN *, u_int32_t *, u_int32_t));
  */
 int
-__db_truncate(dbp, txn, countp, flags)
+__db_truncate_pp(dbp, txn, countp, flags)
 	DB *dbp;
 	DB_TXN *txn;
 	u_int32_t *countp, flags;
 {
 	DB_ENV *dbenv;
-	int ret, t_ret, txn_local;
+	int handle_check, ret, txn_local;
 
 	dbenv = dbp->dbenv;
-	ret = txn_local = 0;
 
 	PANIC_CHECK(dbenv);
 
 	/* Check for invalid flags. */
+	if (F_ISSET(dbp, DB_AM_SECONDARY)) {
+		__db_err(dbenv,
+		    "DBP->truncate forbidden on secondary indices");
+		return (EINVAL);
+	}
 	if ((ret =
 	    __db_fchk(dbenv, "DB->truncate", flags, DB_AUTO_COMMIT)) != 0)
 		return (ret);
 
+	/*
+	 * Make sure there are no active cursors on this db.  Since we drop
+	 * pages we cannot really adjust cursors.
+	 */
+	if (__db_cursor_check(dbp) != 0) {
+		__db_err(dbenv,
+		     "DB->truncate not permitted with active cursors");
+		return (EINVAL);
+	}
+
 	/*
 	 * Create local transaction as necessary, check for consistent
 	 * transaction usage.
 	 */
+	txn_local = 0;
 	if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
-		if ((ret = __db_txn_auto(dbp, &txn)) != 0)
-			return (ret);
+		if ((ret = __db_txn_auto_init(dbenv, &txn)) != 0)
+			goto err;
 		txn_local = 1;
-	} else
-		if (txn != NULL && !TXN_ON(dbenv))
-			return (__db_not_txn_env(dbenv));
+		LF_CLR(DB_AUTO_COMMIT);
+	} else if (txn != NULL && !TXN_ON(dbenv)) {
+		ret = __db_not_txn_env(dbenv);
+		return (ret);
+	}
+
+	handle_check = IS_REPLICATED(dbenv, dbp);
+	if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, txn != NULL)) != 0)
+		goto err;
+
+	ret = __db_truncate(dbp, txn, countp);
+
+	if (handle_check)
+		__env_db_rep_exit(dbenv);
+
+err:	return (txn_local ? __db_txn_auto_resolve(dbenv, txn, 0, ret) : ret);
+}
+
+/*
+ * __db_truncate
+ *	DB->truncate.
+ *
+ * PUBLIC: int __db_truncate __P((DB *, DB_TXN *, u_int32_t *));
+ */
+int
+__db_truncate(dbp, txn, countp)
+	DB *dbp;
+	DB_TXN *txn;
+	u_int32_t *countp;
+{
+	DB *sdbp;
+	DBC *dbc;
+	DB_ENV *dbenv;
+	u_int32_t scount;
+	int ret, t_ret;
+
+	dbenv = dbp->dbenv;
+	dbc = NULL;
+	ret = 0;
+
+	/*
+	 * Run through all secondaries and truncate them first.  The count
+	 * returned is the count of the primary only.  QUEUE uses normal
+	 * processing to truncate so it will update the secondaries normally.
+	 */
+	if (dbp->type != DB_QUEUE && LIST_FIRST(&dbp->s_secondaries) != NULL) {
+		for (sdbp = __db_s_first(dbp);
+		    sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp))
+			if ((ret = __db_truncate(sdbp, txn, &scount)) != 0)
+				break;
+		if (sdbp != NULL)
+			(void)__db_s_done(sdbp);
+		if (ret != 0)
+			return (ret);
+	}
 
 	DB_TEST_RECOVERY(dbp, DB_TEST_PREDESTROY, ret, NULL);
+
+	/* Acquire a cursor. */
+	if ((ret = __db_cursor(dbp, txn, &dbc, 0)) != 0)
+		return (ret);
+
+	DEBUG_LWRITE(dbc, txn, "DB->truncate", NULL, NULL, 0);
+
 	switch (dbp->type) {
-		case DB_BTREE:
-		case DB_RECNO:
-			if ((ret = __bam_truncate(dbp, txn, countp)) != 0)
-				goto err;
-			break;
-		case DB_HASH:
-			if ((ret = __ham_truncate(dbp, txn, countp)) != 0)
-				goto err;
-			break;
-		case DB_QUEUE:
-			if ((ret = __qam_truncate(dbp, txn, countp)) != 0)
-				goto err;
-			break;
-		default:
-			ret = __db_unknown_type(
-			    dbenv, "__db_truncate", dbp->type);
-			goto err;
+	case DB_BTREE:
+	case DB_RECNO:
+		ret = __bam_truncate(dbc, countp);
+		break;
+	case DB_HASH:
+		ret = __ham_truncate(dbc, countp);
+		break;
+	case DB_QUEUE:
+		ret = __qam_truncate(dbc, countp);
+		break;
+	case DB_UNKNOWN:
+	default:
+		ret = __db_unknown_type(dbenv, "DB->truncate", dbp->type);
+		break;
 	}
+
+	/* Discard the cursor. */
+	if (dbc != NULL && (t_ret = __db_c_close(dbc)) != 0 && ret == 0)
+		ret = t_ret;
+
 	DB_TEST_RECOVERY(dbp, DB_TEST_POSTDESTROY, ret, NULL);
 
 DB_TEST_RECOVERY_LABEL
-err:
-	/* Commit for DB_AUTO_COMMIT. */
-	if (txn_local) {
-		if (ret == 0)
-			ret = txn->commit(txn, 0);
-		else
-			if ((t_ret = txn->abort(txn)) != 0)
-				ret = __db_panic(dbenv, t_ret);
-	}
 
 	return (ret);
 }
+
+/*
+ * __db_cursor_check --
+ *	See if there are any active cursors on this db.
+ */
+static int
+__db_cursor_check(dbp)
+	DB *dbp;
+{
+	DB *ldbp;
+	DBC *dbc;
+	DB_ENV *dbenv;
+	int found;
+
+	dbenv = dbp->dbenv;
+
+	MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
+	for (found = 0, ldbp = __dblist_get(dbenv, dbp->adj_fileid);
+	    ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
+	    ldbp = LIST_NEXT(ldbp, dblistlinks)) {
+		MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
+		for (dbc = TAILQ_FIRST(&ldbp->active_queue);
+		    dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
+			if (IS_INITIALIZED(dbc)) {
+				found = 1;
+				break;
+			}
+		}
+		MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
+		if (found == 1)
+			break;
+	}
+	MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
+
+	return (found);
+}
diff --git a/storage/bdb/db/db_upg.c b/storage/bdb/db/db_upg.c
index c0eb72f3713665202d55b77918e2fd4f5999cd31..a41a1c49def04fad895cad8e264e5b8e27beec7c 100644
--- a/storage/bdb/db/db_upg.c
+++ b/storage/bdb/db/db_upg.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_upg.c,v 11.35 2004/03/24 20:37:35 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_upg.c,v 11.29 2002/03/27 18:59:04 krinsky Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -36,11 +34,43 @@ static int (* const func_31_list[P_PAGETYPE_MAX])
 	NULL,			/* P_OVERFLOW */
 	__ham_31_hashmeta,	/* P_HASHMETA */
 	__bam_31_btreemeta,	/* P_BTREEMETA */
+	NULL,			/* P_QAMMETA */
+	NULL,			/* P_QAMDATA */
+	NULL,			/* P_LDUP */
 };
 
 static int __db_page_pass __P((DB *, char *, u_int32_t, int (* const [])
 	       (DB *, char *, u_int32_t, DB_FH *, PAGE *, int *), DB_FH *));
 
+/*
+ * __db_upgrade_pp --
+ *	DB->upgrade pre/post processing.
+ *
+ * PUBLIC: int __db_upgrade_pp __P((DB *, const char *, u_int32_t));
+ */
+int
+__db_upgrade_pp(dbp, fname, flags)
+	DB *dbp;
+	const char *fname;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	int ret;
+
+	dbenv = dbp->dbenv;
+
+	PANIC_CHECK(dbp->dbenv);
+
+	/*
+	 * !!!
+	 * The actual argument checking is simple, do it inline.
+	 */
+	if ((ret = __db_fchk(dbenv, "DB->upgrade", flags, DB_DUPSORT)) != 0)
+		return (ret);
+
+	return (__db_upgrade(dbp, fname, flags));
+}
+
 /*
  * __db_upgrade --
  *	Upgrade an existing database.
@@ -54,17 +84,14 @@ __db_upgrade(dbp, fname, flags)
 	u_int32_t flags;
 {
 	DB_ENV *dbenv;
-	DB_FH fh;
+	DB_FH *fhp;
 	size_t n;
 	int ret, t_ret;
 	u_int8_t mbuf[256];
 	char *real_name;
 
 	dbenv = dbp->dbenv;
-
-	/* Validate arguments. */
-	if ((ret = __db_fchk(dbenv, "DB->upgrade", flags, DB_DUPSORT)) != 0)
-		return (ret);
+	fhp = NULL;
 
 	/* Get the real backing file name. */
 	if ((ret = __db_appname(dbenv,
@@ -72,7 +99,7 @@ __db_upgrade(dbp, fname, flags)
 		return (ret);
 
 	/* Open the file. */
-	if ((ret = __os_open(dbenv, real_name, 0, 0, &fh)) != 0) {
+	if ((ret = __os_open(dbenv, real_name, 0, 0, &fhp)) != 0) {
 		__db_err(dbenv, "%s: %s", real_name, db_strerror(ret));
 		return (ret);
 	}
@@ -85,7 +112,7 @@ __db_upgrade(dbp, fname, flags)
 	 * Read the metadata page.  We read 256 bytes, which is larger than
 	 * any access method's metadata page and smaller than any disk sector.
 	 */
-	if ((ret = __os_read(dbenv, &fh, mbuf, sizeof(mbuf), &n)) != 0)
+	if ((ret = __os_read(dbenv, fhp, mbuf, sizeof(mbuf), &n)) != 0)
 		goto err;
 
 	switch (((DBMETA *)mbuf)->magic) {
@@ -100,9 +127,9 @@ __db_upgrade(dbp, fname, flags)
 			    __bam_30_btreemeta(dbp, real_name, mbuf)) != 0)
 				goto err;
 			if ((ret = __os_seek(dbenv,
-			    &fh, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0)
+			    fhp, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0)
 				goto err;
-			if ((ret = __os_write(dbenv, &fh, mbuf, 256, &n)) != 0)
+			if ((ret = __os_write(dbenv, fhp, mbuf, 256, &n)) != 0)
 				goto err;
 			/* FALLTHROUGH */
 		case 7:
@@ -113,7 +140,7 @@ __db_upgrade(dbp, fname, flags)
 			memcpy(&dbp->pgsize, mbuf + 20, sizeof(u_int32_t));
 
 			if ((ret = __db_page_pass(
-			    dbp, real_name, flags, func_31_list, &fh)) != 0)
+			    dbp, real_name, flags, func_31_list, fhp)) != 0)
 				goto err;
 			/* FALLTHROUGH */
 		case 8:
@@ -138,9 +165,9 @@ __db_upgrade(dbp, fname, flags)
 			    __ham_30_hashmeta(dbp, real_name, mbuf)) != 0)
 				goto err;
 			if ((ret = __os_seek(dbenv,
-			    &fh, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0)
+			    fhp, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0)
 				goto err;
-			if ((ret = __os_write(dbenv, &fh, mbuf, 256, &n)) != 0)
+			if ((ret = __os_write(dbenv, fhp, mbuf, 256, &n)) != 0)
 				goto err;
 
 			/*
@@ -152,14 +179,14 @@ __db_upgrade(dbp, fname, flags)
 			 * the end of the database file.
 			 *
 			 * In DB 3.X, we now create all the hash pages
-			 * belonging to a doubling atomicly;  it's not
+			 * belonging to a doubling atomically; it's not
 			 * safe to just save them for later, because when
 			 * we create an overflow page we'll just create
 			 * a new last page (whatever that may be).  Grow
 			 * the database to the end of the current doubling.
 			 */
 			if ((ret =
-			    __ham_30_sizefix(dbp, &fh, real_name, mbuf)) != 0)
+			    __ham_30_sizefix(dbp, fhp, real_name, mbuf)) != 0)
 				goto err;
 			/* FALLTHROUGH */
 		case 6:
@@ -170,7 +197,7 @@ __db_upgrade(dbp, fname, flags)
 			memcpy(&dbp->pgsize, mbuf + 20, sizeof(u_int32_t));
 
 			if ((ret = __db_page_pass(
-			    dbp, real_name, flags, func_31_list, &fh)) != 0)
+			    dbp, real_name, flags, func_31_list, fhp)) != 0)
 				goto err;
 			/* FALLTHROUGH */
 		case 7:
@@ -198,9 +225,9 @@ __db_upgrade(dbp, fname, flags)
 			if ((ret = __qam_32_qammeta(dbp, real_name, mbuf)) != 0)
 				return (ret);
 			if ((ret = __os_seek(dbenv,
-			    &fh, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0)
+			    fhp, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0)
 				goto err;
-			if ((ret = __os_write(dbenv, &fh, mbuf, 256, &n)) != 0)
+			if ((ret = __os_write(dbenv, fhp, mbuf, 256, &n)) != 0)
 				goto err;
 			/* FALLTHROUGH */
 		case 3:
@@ -232,9 +259,10 @@ __db_upgrade(dbp, fname, flags)
 		goto err;
 	}
 
-	ret = __os_fsync(dbenv, &fh);
+	ret = __os_fsync(dbenv, fhp);
 
-err:	if ((t_ret = __os_closehandle(dbenv, &fh)) != 0 && ret == 0)
+err:	if (fhp != NULL &&
+	    (t_ret = __os_closehandle(dbenv, fhp)) != 0 && ret == 0)
 		ret = t_ret;
 	__os_free(dbenv, real_name);
 
@@ -277,7 +305,8 @@ __db_page_pass(dbp, real_name, flags, fl, fhp)
 	/* Walk the file, calling the underlying conversion functions. */
 	for (i = 0; i < pgno_last; ++i) {
 		if (dbp->db_feedback != NULL)
-			dbp->db_feedback(dbp, DB_UPGRADE, (i * 100)/pgno_last);
+			dbp->db_feedback(
+			    dbp, DB_UPGRADE, (int)((i * 100)/pgno_last));
 		if ((ret = __os_seek(dbenv,
 		    fhp, dbp->pgsize, i, 0, 0, DB_OS_SEEK_SET)) != 0)
 			break;
diff --git a/storage/bdb/db/db_upg_opd.c b/storage/bdb/db/db_upg_opd.c
index f410b797bff58f6b67d56fada9295beb414aa336..fcae089ad0c408c6c5b58d32e43293340e6adaee 100644
--- a/storage/bdb/db/db_upg_opd.c
+++ b/storage/bdb/db/db_upg_opd.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_upg_opd.c,v 11.21 2004/03/19 16:10:26 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_upg_opd.c,v 11.18 2002/08/06 06:11:18 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -102,26 +100,26 @@ __db_31_offdup(dbp, real_name, fhp, sorted, pgnop)
 	}
 
 	/* If we only have a single page, it's easy. */
-	if (cur_cnt > 1) {
-		/*
-		 * pgno_cur is the list of pages we just converted.  We're
-		 * going to walk that list, but we'll need to create a new
-		 * list while we do so.
-		 */
-		if ((ret = __os_malloc(dbp->dbenv,
-		    cur_cnt * sizeof(db_pgno_t), &pgno_next)) != 0)
-			goto err;
-
-		/* Figure out where we can start allocating new pages. */
-		if ((ret = __db_lastpgno(dbp, real_name, fhp, &pgno_last)) != 0)
-			goto err;
-
-		/* Allocate room for an internal page. */
-		if ((ret = __os_malloc(dbp->dbenv,
-		    dbp->pgsize, &ipage)) != 0)
-			goto err;
-		PGNO(ipage) = PGNO_INVALID;
-	}
+	if (cur_cnt <= 1)
+		goto done;
+
+	/*
+	 * pgno_cur is the list of pages we just converted.  We're
+	 * going to walk that list, but we'll need to create a new
+	 * list while we do so.
+	 */
+	if ((ret = __os_malloc(dbp->dbenv,
+	    cur_cnt * sizeof(db_pgno_t), &pgno_next)) != 0)
+		goto err;
+
+	/* Figure out where we can start allocating new pages. */
+	if ((ret = __db_lastpgno(dbp, real_name, fhp, &pgno_last)) != 0)
+		goto err;
+
+	/* Allocate room for an internal page. */
+	if ((ret = __os_malloc(dbp->dbenv, dbp->pgsize, &ipage)) != 0)
+		goto err;
+	PGNO(ipage) = PGNO_INVALID;
 
 	/*
 	 * Repeatedly walk the list of pages, building internal pages, until
@@ -181,7 +179,7 @@ __db_31_offdup(dbp, real_name, fhp, sorted, pgnop)
 		pgno_next = tmp;
 	}
 
-	*pgnop = pgno_cur[0];
+done:	*pgnop = pgno_cur[0];
 
 err:	if (pgno_cur != NULL)
 		__os_free(dbp->dbenv, pgno_cur);
diff --git a/storage/bdb/db/db_vrfy.c b/storage/bdb/db/db_vrfy.c
index 1bbecdbd87a8a462bbda3ec72999fdd99263138a..d0cd22b6a37d0ef7552688390216e0dca6426328 100644
--- a/storage/bdb/db/db_vrfy.c
+++ b/storage/bdb/db/db_vrfy.c
@@ -1,18 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2000-2002
+ * Copyright (c) 2000-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: db_vrfy.c,v 1.107 2002/09/03 17:27:15 bostic Exp $
+ * $Id: db_vrfy.c,v 1.138 2004/10/11 18:47:50 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_vrfy.c,v 1.107 2002/09/03 17:27:15 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -27,161 +23,105 @@ static const char revid[] = "$Id: db_vrfy.c,v 1.107 2002/09/03 17:27:15 bostic E
 #include "dbinc/btree.h"
 #include "dbinc/hash.h"
 #include "dbinc/lock.h"
+#include "dbinc/mp.h"
 #include "dbinc/qam.h"
 #include "dbinc/txn.h"
 
-static int  __db_guesspgsize __P((DB_ENV *, DB_FH *));
-static int  __db_is_valid_magicno __P((u_int32_t, DBTYPE *));
-static int  __db_is_valid_pagetype __P((u_int32_t));
-static int  __db_meta2pgset
+/*
+ * This is the code for DB->verify, the DB database consistency checker.
+ * For now, it checks all subdatabases in a database, and verifies
+ * everything it knows how to (i.e. it's all-or-nothing, and one can't
+ * check only for a subset of possible problems).
+ */
+
+static u_int __db_guesspgsize __P((DB_ENV *, DB_FH *));
+static int   __db_is_valid_magicno __P((u_int32_t, DBTYPE *));
+static int   __db_is_valid_pagetype __P((u_int32_t));
+static int   __db_meta2pgset
 		__P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t, DB *));
-static int __db_salvage __P((DB *, VRFY_DBINFO *, db_pgno_t,
-		PAGE *, void *, int (*)(void *, const void *), u_int32_t));
-static int __db_salvage_subdbpg __P((DB *, VRFY_DBINFO *,
+static int   __db_salvage_subdbpg __P((DB *, VRFY_DBINFO *,
 		PAGE *, void *, int (*)(void *, const void *), u_int32_t));
-static int  __db_salvage_subdbs
-		__P((DB *, VRFY_DBINFO *, void *,
+static int   __db_salvage_subdbs __P((DB *, VRFY_DBINFO *, void *,
 		int(*)(void *, const void *), u_int32_t, int *));
-static int  __db_salvage_unknowns
-		__P((DB *, VRFY_DBINFO *, void *,
+static int   __db_salvage_unknowns __P((DB *, VRFY_DBINFO *, void *,
 		int (*)(void *, const void *), u_int32_t));
-static int  __db_vrfy_common
+static int   __db_verify __P((DB *, const char *, const char *,
+		void *, int (*)(void *, const void *), u_int32_t));
+static int   __db_verify_arg __P((DB *, const char *, void *, u_int32_t));
+static int   __db_vrfy_freelist
+		__P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t));
+static int   __db_vrfy_invalid
 		__P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t, u_int32_t));
-static int  __db_vrfy_freelist __P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t));
-static int  __db_vrfy_invalid
-		__P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t, u_int32_t));
-static int  __db_vrfy_orderchkonly __P((DB *,
+static int   __db_vrfy_orderchkonly __P((DB *,
 		VRFY_DBINFO *, const char *, const char *, u_int32_t));
-static int  __db_vrfy_pagezero __P((DB *, VRFY_DBINFO *, DB_FH *, u_int32_t));
-static int  __db_vrfy_subdbs
+static int   __db_vrfy_pagezero __P((DB *, VRFY_DBINFO *, DB_FH *, u_int32_t));
+static int   __db_vrfy_subdbs
 		__P((DB *, VRFY_DBINFO *, const char *, u_int32_t));
-static int  __db_vrfy_structure
+static int   __db_vrfy_structure
 		__P((DB *, VRFY_DBINFO *, const char *, db_pgno_t, u_int32_t));
-static int  __db_vrfy_walkpages
-		__P((DB *, VRFY_DBINFO *, void *, int (*)(void *, const void *),
-		u_int32_t));
+static int   __db_vrfy_walkpages __P((DB *, VRFY_DBINFO *,
+		void *, int (*)(void *, const void *), u_int32_t));
 
-/*
- * This is the code for DB->verify, the DB database consistency checker.
- * For now, it checks all subdatabases in a database, and verifies
- * everything it knows how to (i.e. it's all-or-nothing, and one can't
- * check only for a subset of possible problems).
- */
+#define	VERIFY_FLAGS							\
+    (DB_AGGRESSIVE |							\
+     DB_NOORDERCHK | DB_ORDERCHKONLY | DB_PRINTABLE | DB_SALVAGE | DB_UNREF)
 
 /*
- * __db_verify --
- *	Walk the entire file page-by-page, either verifying with or without
- *	dumping in db_dump -d format, or DB_SALVAGE-ing whatever key/data
- *	pairs can be found and dumping them in standard (db_load-ready)
- *	dump format.
+ * __db_verify_pp --
+ *	DB->verify public interface.
  *
- *	(Salvaging isn't really a verification operation, but we put it
- *	here anyway because it requires essentially identical top-level
- *	code.)
- *
- *	flags may be 0, DB_NOORDERCHK, DB_ORDERCHKONLY, or DB_SALVAGE
- *	(and optionally DB_AGGRESSIVE).
- *
- *	__db_verify itself is simply a wrapper to __db_verify_internal,
- *	which lets us pass appropriate equivalents to FILE * in from the
- *	non-C APIs.
- *
- * PUBLIC: int __db_verify
+ * PUBLIC: int __db_verify_pp
  * PUBLIC:     __P((DB *, const char *, const char *, FILE *, u_int32_t));
  */
 int
-__db_verify(dbp, file, database, outfile, flags)
+__db_verify_pp(dbp, file, database, outfile, flags)
 	DB *dbp;
 	const char *file, *database;
 	FILE *outfile;
 	u_int32_t flags;
 {
-
+	/*
+	 * __db_verify_pp is a wrapper to __db_verify_internal, which lets
+	 * us pass appropriate equivalents to FILE * in from the non-C APIs.
+	 */
 	return (__db_verify_internal(dbp,
-	    file, database, outfile, __db_verify_callback, flags));
-}
-
-/*
- * __db_verify_callback --
- *	Callback function for using pr_* functions from C.
- *
- * PUBLIC: int  __db_verify_callback __P((void *, const void *));
- */
-int
-__db_verify_callback(handle, str_arg)
-	void *handle;
-	const void *str_arg;
-{
-	char *str;
-	FILE *f;
-
-	str = (char *)str_arg;
-	f = (FILE *)handle;
-
-	if (fprintf(f, "%s", str) != (int)strlen(str))
-		return (EIO);
-
-	return (0);
+	    file, database, outfile, __db_pr_callback, flags));
 }
 
 /*
  * __db_verify_internal --
- *	Inner meat of __db_verify.
  *
  * PUBLIC: int __db_verify_internal __P((DB *, const char *,
  * PUBLIC:     const char *, void *, int (*)(void *, const void *), u_int32_t));
  */
 int
-__db_verify_internal(dbp_orig, name, subdb, handle, callback, flags)
-	DB *dbp_orig;
-	const char *name, *subdb;
+__db_verify_internal(dbp, fname, dname, handle, callback, flags)
+	DB *dbp;
+	const char *fname, *dname;
 	void *handle;
 	int (*callback) __P((void *, const void *));
 	u_int32_t flags;
 {
-	DB *dbp;
 	DB_ENV *dbenv;
-	DB_FH fh, *fhp;
-	VRFY_DBINFO *vdp;
-	int has, ret, isbad;
-	char *real_name;
-
-	dbenv = dbp_orig->dbenv;
-	vdp = NULL;
-	real_name = NULL;
-	ret = isbad = 0;
+	int ret, t_ret;
 
-	memset(&fh, 0, sizeof(fh));
-	fhp = &fh;
+	dbenv = dbp->dbenv;
 
 	PANIC_CHECK(dbenv);
-	DB_ILLEGAL_AFTER_OPEN(dbp_orig, "verify");
-
-#define	OKFLAGS (DB_AGGRESSIVE | DB_NOORDERCHK | DB_ORDERCHKONLY | \
-    DB_PRINTABLE | DB_SALVAGE)
-	if ((ret = __db_fchk(dbenv, "DB->verify", flags, OKFLAGS)) != 0)
-		return (ret);
+	DB_ILLEGAL_AFTER_OPEN(dbp, "DB->verify");
 
+#ifdef HAVE_FTRUNCATE
 	/*
-	 * DB_SALVAGE is mutually exclusive with the other flags except
-	 * DB_AGGRESSIVE and DB_PRINTABLE.
+	 * If we're using ftruncate to abort page-allocation functions, there
+	 * should never be unreferenced pages.  Always check for unreferenced
+	 * pages on those systems.
 	 */
-	if (LF_ISSET(DB_SALVAGE) &&
-	    (flags & ~DB_AGGRESSIVE & ~DB_PRINTABLE) != DB_SALVAGE)
-		return (__db_ferr(dbenv, "__db_verify", 1));
-
-	/* DB_AGGRESSIVE and DB_PRINTABLE are only meaningful when salvaging. */
-	if ((LF_ISSET(DB_AGGRESSIVE) || LF_ISSET(DB_PRINTABLE)) &&
-	    !LF_ISSET(DB_SALVAGE))
-		return (__db_ferr(dbenv, "__db_verify", 1));
-
-	if (LF_ISSET(DB_ORDERCHKONLY) && flags != DB_ORDERCHKONLY)
-		return (__db_ferr(dbenv, "__db_verify", 1));
+	if (!LF_ISSET(DB_SALVAGE))
+		LF_SET(DB_UNREF);
+#endif
 
-	if (LF_ISSET(DB_ORDERCHKONLY) && subdb == NULL) {
-		__db_err(dbenv, "DB_ORDERCHKONLY requires a database name");
-		return (EINVAL);
-	}
+	if ((ret = __db_verify_arg(dbp, dname, handle, flags)) != 0)
+		goto err;
 
 	/*
 	 * Forbid working in an environment that uses transactions or
@@ -190,45 +130,113 @@ __db_verify_internal(dbp_orig, name, subdb, handle, callback, flags)
 	 * locking conventions either.
 	 */
 	if (TXN_ON(dbenv) || LOCKING_ON(dbenv) || LOGGING_ON(dbenv)) {
-		dbp_orig->errx(dbp_orig,
-	    "verify may not be used with transactions, logging, or locking");
-		return (EINVAL);
-		/* NOTREACHED */
+		__db_err(dbenv,
+    "DB->verify may not be used with transactions, logging, or locking");
+		ret = EINVAL;
+		goto err;
 	}
 
-	/* Create a dbp to use internally, which we can close at our leisure. */
-	if ((ret = db_create(&dbp, dbenv, 0)) != 0)
-		goto err;
+	ret = __db_verify(dbp, fname, dname, handle, callback, flags);
 
-	F_SET(dbp, DB_AM_VERIFYING);
+	/* Db.verify is a DB handle destructor. */
+err:	if ((t_ret = __db_close(dbp, NULL, 0)) != 0 && ret == 0)
+		ret = t_ret;
 
-	/* Copy the supplied pagesize, which we use if the file one is bogus. */
-	if (dbp_orig->pgsize >= DB_MIN_PGSIZE &&
-	    dbp_orig->pgsize <= DB_MAX_PGSIZE)
-		dbp->set_pagesize(dbp, dbp_orig->pgsize);
+	return (ret);
+}
 
-	/* Copy the feedback function, if present, and initialize it. */
-	if (!LF_ISSET(DB_SALVAGE) && dbp_orig->db_feedback != NULL) {
-		dbp->set_feedback(dbp, dbp_orig->db_feedback);
-		dbp->db_feedback(dbp, DB_VERIFY, 0);
-	}
+/*
+ * __db_verify_arg --
+ *	Check DB->verify arguments.
+ */
+static int
+__db_verify_arg(dbp, dname, handle, flags)
+	DB *dbp;
+	const char *dname;
+	void *handle;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	int ret;
+
+	dbenv = dbp->dbenv;
+
+	if ((ret = __db_fchk(dbenv, "DB->verify", flags, VERIFY_FLAGS)) != 0)
+		return (ret);
 
 	/*
-	 * Copy the comparison and hashing functions.  Note that
-	 * even if the database is not a hash or btree, the respective
-	 * internal structures will have been initialized.
+	 * DB_SALVAGE is mutually exclusive with the other flags except
+	 * DB_AGGRESSIVE, DB_PRINTABLE.
+	 *
+	 * DB_AGGRESSIVE and DB_PRINTABLE are only meaningful when salvaging.
+	 *
+	 * DB_SALVAGE requires an output stream.
 	 */
-	if (dbp_orig->dup_compare != NULL &&
-	    (ret = dbp->set_dup_compare(dbp, dbp_orig->dup_compare)) != 0)
-		goto err;
-	if (((BTREE *)dbp_orig->bt_internal)->bt_compare != NULL &&
-	    (ret = dbp->set_bt_compare(dbp,
-	    ((BTREE *)dbp_orig->bt_internal)->bt_compare)) != 0)
-		goto err;
-	if (((HASH *)dbp_orig->h_internal)->h_hash != NULL &&
-	    (ret = dbp->set_h_hash(dbp,
-	    ((HASH *)dbp_orig->h_internal)->h_hash)) != 0)
-		goto err;
+	if (LF_ISSET(DB_SALVAGE)) {
+		if (LF_ISSET(~(DB_AGGRESSIVE | DB_PRINTABLE | DB_SALVAGE)))
+			return (__db_ferr(dbenv, "DB->verify", 1));
+		if (handle == NULL) {
+			__db_err(dbenv,
+			    "DB_SALVAGE requires a an output handle");
+			return (EINVAL);
+		}
+	} else
+		if (LF_ISSET(DB_AGGRESSIVE | DB_PRINTABLE))
+			return (__db_ferr(dbenv, "DB->verify", 1));
+
+	/* 
+	 * DB_ORDERCHKONLY is mutually exclusive with DB_SALVAGE and
+	 * DB_NOORDERCHK, and requires a database name.
+	 */
+	if ((ret = __db_fcchk(dbenv, "DB->verify", flags,
+	    DB_ORDERCHKONLY, DB_SALVAGE | DB_NOORDERCHK)) != 0)
+		return (ret);
+	if (LF_ISSET(DB_ORDERCHKONLY) && dname == NULL) {
+		__db_err(dbenv, "DB_ORDERCHKONLY requires a database name");
+		return (EINVAL);
+	}
+	return (0);
+}
+
+/*
+ * __db_verify --
+ *	Walk the entire file page-by-page, either verifying with or without
+ *	dumping in db_dump -d format, or DB_SALVAGE-ing whatever key/data
+ *	pairs can be found and dumping them in standard (db_load-ready)
+ *	dump format.
+ *
+ *	(Salvaging isn't really a verification operation, but we put it
+ *	here anyway because it requires essentially identical top-level
+ *	code.)
+ *
+ *	flags may be 0, DB_NOORDERCHK, DB_ORDERCHKONLY, or DB_SALVAGE
+ *	(and optionally DB_AGGRESSIVE).
+ */
+static int
+__db_verify(dbp, name, subdb, handle, callback, flags)
+	DB *dbp;
+	const char *name, *subdb;
+	void *handle;
+	int (*callback) __P((void *, const void *));
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	DB_FH *fhp;
+	VRFY_DBINFO *vdp;
+	int has, isbad, ret, t_ret;
+	char *real_name;
+
+	dbenv = dbp->dbenv;
+	fhp = NULL;
+	vdp = NULL;
+	real_name = NULL;
+	has = ret = isbad = 0;
+
+	F_SET(dbp, DB_AM_VERIFYING);
+
+	/* Initialize any feedback function. */
+	if (!LF_ISSET(DB_SALVAGE) && dbp->db_feedback != NULL)
+		dbp->db_feedback(dbp, DB_VERIFY, 0);
 
 	/*
 	 * We don't know how large the cache is, and if the database
@@ -266,7 +274,7 @@ __db_verify_internal(dbp_orig, name, subdb, handle, callback, flags)
 	 * safe to open the database normally and then use the page swapping
 	 * code, which makes life easier.
 	 */
-	if ((ret = __os_open(dbenv, real_name, DB_OSO_RDONLY, 0444, fhp)) != 0)
+	if ((ret = __os_open(dbenv, real_name, DB_OSO_RDONLY, 0, &fhp)) != 0)
 		goto err;
 
 	/* Verify the metadata page 0; set pagesize and type. */
@@ -293,11 +301,19 @@ __db_verify_internal(dbp_orig, name, subdb, handle, callback, flags)
 	    name, TXN_INVALID, DB_ODDFILESIZE | DB_RDONLY)) != 0)
 		return (ret);
 
+	/*
+	 * Set our name in the Queue subsystem;  we may need it later
+	 * to deal with extents.
+	 */
+	if (dbp->type == DB_QUEUE &&
+	    (ret = __qam_set_ext_data(dbp, name)) != 0)
+		return (ret);
+
 	/* Mark the dbp as opened, so that we correctly handle its close. */
 	F_SET(dbp, DB_AM_OPEN_CALLED);
 
 	/* Find out the page number of the last page in the database. */
-	dbp->mpf->last_pgno(dbp->mpf, &vdp->last_pgno);
+	__memp_last_pgno(dbp->mpf, &vdp->last_pgno);
 
 	/*
 	 * DB_ORDERCHKONLY is a special case;  our file consists of
@@ -330,7 +346,6 @@ __db_verify_internal(dbp_orig, name, subdb, handle, callback, flags)
 		 * subdbs;  on the walkpages pass, we print out
 		 * whichever data pages we have not seen.
 		 */
-		has = 0;
 		if (!LF_ISSET(DB_AGGRESSIVE) && (__db_salvage_subdbs(dbp,
 		    vdp, handle, callback, flags, &has)) != 0)
 			isbad = 1;
@@ -344,16 +359,13 @@ __db_verify_internal(dbp_orig, name, subdb, handle, callback, flags)
 		 */
 		if (has == 1)
 			F_SET(vdp, SALVAGE_PRINTHEADER);
-		else if ((ret = __db_prheader(dbp,
-		    NULL, 0, 0, handle, callback, vdp, PGNO_BASE_MD)) != 0)
-			goto err;
 	}
 
 	if ((ret =
 	    __db_vrfy_walkpages(dbp, vdp, handle, callback, flags)) != 0) {
 		if (ret == DB_VERIFY_BAD)
 			isbad = 1;
-		else if (ret != 0)
+		else
 			goto err;
 	}
 
@@ -363,7 +375,7 @@ __db_verify_internal(dbp_orig, name, subdb, handle, callback, flags)
 		    __db_vrfy_structure(dbp, vdp, name, 0, flags)) != 0) {
 			if (ret == DB_VERIFY_BAD)
 				isbad = 1;
-			else if (ret != 0)
+			else
 				goto err;
 		}
 
@@ -380,14 +392,7 @@ __db_verify_internal(dbp_orig, name, subdb, handle, callback, flags)
 		__db_salvage_destroy(vdp);
 	}
 
-	if (0) {
-		/* Don't try to strerror() DB_VERIFY_FATAL;  it's private. */
-err:		if (ret == DB_VERIFY_FATAL)
-			ret = DB_VERIFY_BAD;
-		(void)__db_err(dbenv, "%s: %s", name, db_strerror(ret));
-	}
-
-	if (LF_ISSET(DB_SALVAGE) &&
+err:	if (LF_ISSET(DB_SALVAGE) &&
 	    (has == 0 || F_ISSET(vdp, SALVAGE_PRINTFOOTER)))
 		(void)__db_prfooter(handle, callback);
 
@@ -395,18 +400,31 @@ err:		if (ret == DB_VERIFY_FATAL)
 done:	if (!LF_ISSET(DB_SALVAGE) && dbp->db_feedback != NULL)
 		dbp->db_feedback(dbp, DB_VERIFY, 100);
 
-	if (F_ISSET(fhp, DB_FH_VALID))
-		(void)__os_closehandle(dbenv, fhp);
-	if (dbp)
-		(void)dbp->close(dbp, 0);
-	if (vdp)
-		(void)__db_vrfy_dbinfo_destroy(dbenv, vdp);
-	if (real_name)
+	if (fhp != NULL &&
+	    (t_ret = __os_closehandle(dbenv, fhp)) != 0 && ret == 0)
+		ret = t_ret;
+	if (vdp != NULL &&
+	    (t_ret = __db_vrfy_dbinfo_destroy(dbenv, vdp)) != 0 && ret == 0)
+		ret = t_ret;
+	if (real_name != NULL)
 		__os_free(dbenv, real_name);
 
-	if ((ret == 0 && isbad == 1) || ret == DB_VERIFY_FATAL)
+	/*
+	 * DB_VERIFY_FATAL is a private error, translate to a public one.
+	 *
+	 * If we didn't find a page, it's probably a page number was corrupted.
+	 * Return the standard corruption error.
+	 *
+	 * Otherwise, if we found corruption along the way, set the return.
+	 */
+	if (ret == DB_VERIFY_FATAL ||
+	    ret == DB_PAGE_NOTFOUND || (ret == 0 && isbad == 1))
 		ret = DB_VERIFY_BAD;
 
+	/* Make sure there's a public complaint if we found corruption. */
+	if (ret != 0)
+		__db_err(dbenv, "%s: %s", name, db_strerror(ret));
+
 	return (ret);
 }
 
@@ -461,7 +479,7 @@ __db_vrfy_pagezero(dbp, vdp, fhp, flags)
 
 	if ((ret = __db_chk_meta(dbenv, dbp, meta, 1)) != 0) {
 		EPRINT((dbenv,
-		    "Page %lu: metadata page corrupted, (u_long)PGNO_BASE_MD"));
+		    "Page %lu: metadata page corrupted", (u_long)PGNO_BASE_MD));
 		isbad = 1;
 		if (ret != -1) {
 			EPRINT((dbenv,
@@ -615,12 +633,9 @@ __db_vrfy_walkpages(dbp, vdp, handle, callback, flags)
 
 	dbenv = dbp->dbenv;
 	mpf = dbp->mpf;
+	h = NULL;
 	ret = isbad = t_ret = 0;
 
-	if ((ret = __db_fchk(dbenv,
-	    "__db_vrfy_walkpages", flags, OKFLAGS)) != 0)
-		return (ret);
-
 	for (i = 0; i <= vdp->last_pgno; i++) {
 		/*
 		 * If DB_SALVAGE is set, we inspect our database of
@@ -634,13 +649,12 @@ __db_vrfy_walkpages(dbp, vdp, handle, callback, flags)
 		 * If an individual page get fails, keep going if and only
 		 * if we're salvaging.
 		 */
-		if ((t_ret = mpf->get(mpf, &i, 0, &h)) != 0) {
+		if ((t_ret = __memp_fget(mpf, &i, 0, &h)) != 0) {
 			if (ret == 0)
 				ret = t_ret;
 			if (LF_ISSET(DB_SALVAGE))
 				continue;
-			else
-				return (ret);
+			return (ret);
 		}
 
 		if (LF_ISSET(DB_SALVAGE)) {
@@ -688,23 +702,19 @@ __db_vrfy_walkpages(dbp, vdp, handle, callback, flags)
 				    (u_long)i));
 				break;
 			case P_HASH:
-				ret = __ham_vrfy(dbp,
-				    vdp, h, i, flags);
+				ret = __ham_vrfy(dbp, vdp, h, i, flags);
 				break;
 			case P_IBTREE:
 			case P_IRECNO:
 			case P_LBTREE:
 			case P_LDUP:
-				ret = __bam_vrfy(dbp,
-				    vdp, h, i, flags);
+				ret = __bam_vrfy(dbp, vdp, h, i, flags);
 				break;
 			case P_LRECNO:
-				ret = __ram_vrfy_leaf(dbp,
-				    vdp, h, i, flags);
+				ret = __ram_vrfy_leaf(dbp, vdp, h, i, flags);
 				break;
 			case P_OVERFLOW:
-				ret = __db_vrfy_overflow(dbp,
-				    vdp, h, i, flags);
+				ret = __db_vrfy_overflow(dbp, vdp, h, i, flags);
 				break;
 			case P_HASHMETA:
 				ret = __ham_vrfy_meta(dbp,
@@ -746,14 +756,14 @@ __db_vrfy_walkpages(dbp, vdp, handle, callback, flags)
 			 */
 			if (dbp->db_feedback != NULL)
 				dbp->db_feedback(dbp, DB_VERIFY,
-				    (i + 1) * 50 / (vdp->last_pgno + 1));
+				    (int)((i + 1) * 50 / (vdp->last_pgno + 1)));
 		}
 
 		/*
 		 * Just as with the page get, bail if and only if we're
 		 * not salvaging.
 		 */
-		if ((t_ret = mpf->put(mpf, h, 0)) != 0) {
+		if ((t_ret = __memp_fput(mpf, h, 0)) != 0) {
 			if (ret == 0)
 				ret = t_ret;
 			if (!LF_ISSET(DB_SALVAGE))
@@ -761,8 +771,22 @@ __db_vrfy_walkpages(dbp, vdp, handle, callback, flags)
 		}
 	}
 
+	/*
+	 * If we've seen a Queue metadata page, we may need to walk Queue
+	 * extent pages that won't show up between 0 and vdp->last_pgno.
+	 */
+	if (F_ISSET(vdp, VRFY_QMETA_SET) && (t_ret =
+	    __qam_vrfy_walkqueue(dbp, vdp, handle, callback, flags)) != 0) {
+		if (ret == 0)
+			ret = t_ret;
+		if (t_ret == DB_VERIFY_BAD)
+			isbad = 1;
+		else if (!LF_ISSET(DB_SALVAGE))
+			return (ret);
+	}
+
 	if (0) {
-err:		if ((t_ret = mpf->put(mpf, h, 0)) != 0)
+err:		if (h != NULL && (t_ret = __memp_fput(mpf, h, 0)) != 0)
 			return (ret == 0 ? t_ret : ret);
 	}
 
@@ -797,13 +821,6 @@ __db_vrfy_structure(dbp, vdp, dbname, meta_pgno, flags)
 	dbenv = dbp->dbenv;
 	pgset = vdp->pgset;
 
-	if ((ret = __db_fchk(dbenv, "DB->verify", flags, OKFLAGS)) != 0)
-		return (ret);
-	if (LF_ISSET(DB_SALVAGE)) {
-		__db_err(dbenv, "__db_vrfy_structure called with DB_SALVAGE");
-		return (EINVAL);
-	}
-
 	/*
 	 * Providing feedback here is tricky;  in most situations,
 	 * we fetch each page one more time, but we do so in a top-down
@@ -824,7 +841,7 @@ __db_vrfy_structure(dbp, vdp, dbname, meta_pgno, flags)
 	/*
 	 * Call the appropriate function to downwards-traverse the db type.
 	 */
-	switch(dbp->type) {
+	switch (dbp->type) {
 	case DB_BTREE:
 	case DB_RECNO:
 		if ((ret = __bam_vrfy_structure(dbp, vdp, 0, flags)) != 0) {
@@ -844,6 +861,7 @@ __db_vrfy_structure(dbp, vdp, dbname, meta_pgno, flags)
 		hassubs = F_ISSET(pip, VRFY_HAS_SUBDBS) ? 1 : 0;
 		if ((ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0)
 			goto err;
+		pip = NULL;
 
 		if (isbad == 0 && hassubs)
 			if ((ret =
@@ -875,13 +893,12 @@ __db_vrfy_structure(dbp, vdp, dbname, meta_pgno, flags)
 		 * Skip to "err".
 		 */
 		goto err;
-		/* NOTREACHED */
+	case DB_UNKNOWN:
 	default:
 		/* This should only happen if the verifier is somehow broken. */
 		DB_ASSERT(0);
 		ret = EINVAL;
 		goto err;
-		/* NOTREACHED */
 	}
 
 	/* Walk free list. */
@@ -909,7 +926,15 @@ __db_vrfy_structure(dbp, vdp, dbname, meta_pgno, flags)
 			goto err;
 		if ((ret = __db_vrfy_pgset_get(pgset, i, &p)) != 0)
 			goto err;
-		if (p == 0) {
+		if (pip->type == P_OVERFLOW) {
+			if ((u_int32_t)p != pip->refcount) {
+				EPRINT((dbenv,
+		    "Page %lu: overflow refcount %lu, referenced %lu times",
+				    (u_long)i,
+				    (u_long)pip->refcount, (u_long)p));
+				isbad = 1;
+			}
+		} else if (p == 0 && LF_ISSET(DB_UNREF)) {
 			EPRINT((dbenv,
 			    "Page %lu: unreferenced page", (u_long)i));
 			isbad = 1;
@@ -952,6 +977,8 @@ __db_is_valid_pagetype(type)
 	case P_QAMDATA:
 	case P_LDUP:
 		return (1);
+	default:
+		break;
 	}
 	return (0);
 }
@@ -974,6 +1001,8 @@ __db_is_valid_magicno(magic, typep)
 	case DB_QAMMAGIC:
 		*typep = DB_QUEUE;
 		return (1);
+	default:
+		break;
 	}
 	*typep = DB_UNKNOWN;
 	return (0);
@@ -982,8 +1011,11 @@ __db_is_valid_magicno(magic, typep)
 /*
  * __db_vrfy_common --
  *	Verify info common to all page types.
+ *
+ * PUBLIC: int  __db_vrfy_common
+ * PUBLIC:     __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t, u_int32_t));
  */
-static int
+int
 __db_vrfy_common(dbp, vdp, h, pgno, flags)
 	DB *dbp;
 	VRFY_DBINFO *vdp;
@@ -1166,7 +1198,7 @@ __db_vrfy_datapage(dbp, vdp, h, pgno, flags)
 	switch (TYPE(h)) {
 	case P_IBTREE:
 	case P_IRECNO:
-		if (LEVEL(h) < LEAFLEVEL + 1 || LEVEL(h) > MAXBTREELEVEL) {
+		if (LEVEL(h) < LEAFLEVEL + 1) {
 			isbad = 1;
 			EPRINT((dbenv, "Page %lu: bad btree level %lu",
 			    (u_long)pgno, (u_long)LEVEL(h)));
@@ -1418,13 +1450,13 @@ __db_vrfy_subdbs(dbp, vdp, dbname, flags)
 	    __db_master_open(dbp, NULL, dbname, DB_RDONLY, 0, &mdbp)) != 0)
 		return (ret);
 
-	if ((ret = __db_icursor(mdbp,
+	if ((ret = __db_cursor_int(mdbp,
 	    NULL, DB_BTREE, PGNO_INVALID, 0, DB_LOCK_INVALIDID, &dbc)) != 0)
 		goto err;
 
 	memset(&key, 0, sizeof(key));
 	memset(&data, 0, sizeof(data));
-	while ((ret = dbc->c_get(dbc, &key, &data, DB_NEXT)) == 0) {
+	while ((ret = __db_c_get(dbc, &key, &data, DB_NEXT)) == 0) {
 		if (data.size != sizeof(db_pgno_t)) {
 			EPRINT((dbenv,
 			    "Subdatabase entry not page-number size"));
@@ -1475,7 +1507,6 @@ __db_vrfy_subdbs(dbp, vdp, dbname, flags)
 			    (u_long)meta_pgno, (u_long)type));
 			ret = DB_VERIFY_BAD;
 			goto err;
-			/* NOTREACHED */
 		}
 	}
 
@@ -1485,7 +1516,7 @@ __db_vrfy_subdbs(dbp, vdp, dbname, flags)
 err:	if (dbc != NULL && (t_ret = __db_c_close(dbc)) != 0 && ret == 0)
 		ret = t_ret;
 
-	if ((t_ret = mdbp->close(mdbp, 0)) != 0 && ret == 0)
+	if ((t_ret = __db_close(mdbp, NULL, 0)) != 0 && ret == 0)
 		ret = t_ret;
 
 	return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
@@ -1512,7 +1543,7 @@ __db_vrfy_struct_feedback(dbp, vdp)
 		vdp->pgs_remaining--;
 
 	/* Don't allow a feedback call of 100 until we're really done. */
-	progress = 100 - (vdp->pgs_remaining * 50 / (vdp->last_pgno + 1));
+	progress = 100 - (int)(vdp->pgs_remaining * 50 / (vdp->last_pgno + 1));
 	dbp->db_feedback(dbp, DB_VERIFY, progress == 100 ? 99 : progress);
 }
 
@@ -1549,8 +1580,6 @@ __db_vrfy_orderchkonly(dbp, vdp, name, subdb, flags)
 	LF_CLR(DB_NOORDERCHK);
 
 	/* Open the master database and get the meta_pgno for the subdb. */
-	if ((ret = db_create(&mdbp, NULL, 0)) != 0)
-		return (ret);
 	if ((ret = __db_master_open(dbp, NULL, name, DB_RDONLY, 0, &mdbp)) != 0)
 		goto err;
 
@@ -1558,7 +1587,7 @@ __db_vrfy_orderchkonly(dbp, vdp, name, subdb, flags)
 	key.data = (void *)subdb;
 	key.size = (u_int32_t)strlen(subdb);
 	memset(&data, 0, sizeof(data));
-	if ((ret = mdbp->get(mdbp, NULL, &key, &data, 0)) != 0)
+	if ((ret = __db_get(mdbp, NULL, &key, &data, 0)) != 0)
 		goto err;
 
 	if (data.size != sizeof(db_pgno_t)) {
@@ -1575,7 +1604,7 @@ __db_vrfy_orderchkonly(dbp, vdp, name, subdb, flags)
 	 */
 	DB_NTOHL(&meta_pgno);
 
-	if ((ret = mpf->get(mpf, &meta_pgno, 0, &h)) != 0)
+	if ((ret = __memp_fget(mpf, &meta_pgno, 0, &h)) != 0)
 		goto err;
 
 	if ((ret = __db_vrfy_pgset(dbenv, dbp->pgsize, &pgset)) != 0)
@@ -1592,16 +1621,17 @@ __db_vrfy_orderchkonly(dbp, vdp, name, subdb, flags)
 		if ((ret =
 		    __db_meta2pgset(dbp, vdp, meta_pgno, flags, pgset)) != 0)
 			goto err;
-		if ((ret = pgset->cursor(pgset, NULL, &pgsc, 0)) != 0)
+		if ((ret = __db_cursor_int(pgset, NULL, dbp->type,
+		    PGNO_INVALID, 0, DB_LOCK_INVALIDID, &pgsc)) != 0)
 			goto err;
 		while ((ret = __db_vrfy_pgset_next(pgsc, &p)) == 0) {
-			if ((ret = mpf->get(mpf, &p, 0, &currpg)) != 0)
+			if ((ret = __memp_fget(mpf, &p, 0, &currpg)) != 0)
 				goto err;
 			if ((ret = __bam_vrfy_itemorder(dbp,
 			    NULL, currpg, p, NUM_ENT(currpg), 1,
 			    F_ISSET(&btmeta->dbmeta, BTM_DUP), flags)) != 0)
 				goto err;
-			if ((ret = mpf->put(mpf, currpg, 0)) != 0)
+			if ((ret = __memp_fput(mpf, currpg, 0)) != 0)
 				goto err;
 			currpg = NULL;
 		}
@@ -1646,7 +1676,7 @@ __db_vrfy_orderchkonly(dbp, vdp, name, subdb, flags)
 		for (bucket = 0; bucket <= hmeta->max_bucket; bucket++) {
 			pgno = BS_TO_PAGE(bucket, hmeta->spares);
 			while (pgno != PGNO_INVALID) {
-				if ((ret = mpf->get(mpf,
+				if ((ret = __memp_fget(mpf,
 				    &pgno, 0, &currpg)) != 0)
 					goto err;
 				if ((ret = __ham_vrfy_hashing(dbp,
@@ -1654,7 +1684,7 @@ __db_vrfy_orderchkonly(dbp, vdp, name, subdb, flags)
 				    flags, h_internal->h_hash)) != 0)
 					goto err;
 				pgno = NEXT_PGNO(currpg);
-				if ((ret = mpf->put(mpf, currpg, 0)) != 0)
+				if ((ret = __memp_fput(mpf, currpg, 0)) != 0)
 					goto err;
 				currpg = NULL;
 			}
@@ -1667,16 +1697,16 @@ __db_vrfy_orderchkonly(dbp, vdp, name, subdb, flags)
 		break;
 	}
 
-err:	if (pgsc != NULL && (t_ret = pgsc->c_close(pgsc)) != 0 && ret == 0)
+err:	if (pgsc != NULL && (t_ret = __db_c_close(pgsc)) != 0 && ret == 0)
 		ret = t_ret;
 	if (pgset != NULL &&
-	    (t_ret = pgset->close(pgset, 0)) != 0 && ret == 0)
+	    (t_ret = __db_close(pgset, NULL, 0)) != 0 && ret == 0)
 		ret = t_ret;
-	if (h != NULL && (t_ret = mpf->put(mpf, h, 0)) != 0)
+	if (h != NULL && (t_ret = __memp_fput(mpf, h, 0)) != 0)
 		ret = t_ret;
-	if (currpg != NULL && (t_ret = mpf->put(mpf, currpg, 0)) != 0)
+	if (currpg != NULL && (t_ret = __memp_fput(mpf, currpg, 0)) != 0)
 		ret = t_ret;
-	if ((t_ret = mdbp->close(mdbp, 0)) != 0)
+	if ((t_ret = __db_close(mdbp, NULL, 0)) != 0)
 		ret = t_ret;
 	return (ret);
 }
@@ -1685,8 +1715,11 @@ err:	if (pgsc != NULL && (t_ret = pgsc->c_close(pgsc)) != 0 && ret == 0)
  * __db_salvage --
  *	Walk through a page, salvaging all likely or plausible (w/
  *	DB_AGGRESSIVE) key/data pairs.
+ *
+ * PUBLIC: int __db_salvage __P((DB *, VRFY_DBINFO *, db_pgno_t,
+ * PUBLIC:     PAGE *, void *, int (*)(void *, const void *), u_int32_t));
  */
-static int
+int
 __db_salvage(dbp, vdp, pgno, h, handle, callback, flags)
 	DB *dbp;
 	VRFY_DBINFO *vdp;
@@ -1696,6 +1729,7 @@ __db_salvage(dbp, vdp, pgno, h, handle, callback, flags)
 	int (*callback) __P((void *, const void *));
 	u_int32_t flags;
 {
+	int ret;
 	DB_ASSERT(LF_ISSET(DB_SALVAGE));
 
 	/* If we got this page in the subdb pass, we can safely skip it. */
@@ -1703,20 +1737,25 @@ __db_salvage(dbp, vdp, pgno, h, handle, callback, flags)
 		return (0);
 
 	switch (TYPE(h)) {
+	case P_HASHMETA:
+		ret = __ham_vrfy_meta(dbp, vdp, (HMETA *)h, pgno, flags);
+		break;
+	case P_BTREEMETA:
+		ret = __bam_vrfy_meta(dbp, vdp, (BTMETA *)h, pgno, flags);
+		break;
+	case P_QAMMETA:
+		ret = __qam_vrfy_meta(dbp, vdp, (QMETA *)h, pgno, flags);
+		break;
 	case P_HASH:
 		return (__ham_salvage(dbp,
 		    vdp, pgno, h, handle, callback, flags));
-		/* NOTREACHED */
 	case P_LBTREE:
 		return (__bam_salvage(dbp,
 		    vdp, pgno, P_LBTREE, h, handle, callback, NULL, flags));
-		/* NOTREACHED */
 	case P_LDUP:
 		return (__db_salvage_markneeded(vdp, pgno, SALVAGE_LDUP));
-		/* NOTREACHED */
 	case P_OVERFLOW:
 		return (__db_salvage_markneeded(vdp, pgno, SALVAGE_OVERFLOW));
-		/* NOTREACHED */
 	case P_LRECNO:
 		/*
 		 * Recnos are tricky -- they may represent dup pages, or
@@ -1731,16 +1770,21 @@ __db_salvage(dbp, vdp, pgno, h, handle, callback, flags)
 		 * database page, the "unknowns" pass will pick us up.
 		 */
 		return (__db_salvage_markneeded(vdp, pgno, SALVAGE_LRECNO));
-		/* NOTREACHED */
+	case P_QAMDATA:
+		return (__qam_salvage(dbp,
+		    vdp, pgno, h, handle, callback, flags));
 	case P_IBTREE:
 	case P_INVALID:
 	case P_IRECNO:
 	case __P_DUPLICATE:
 	default:
 		/* XXX: Should we be more aggressive here? */
-		break;
+		return (0);
 	}
-	return (0);
+
+	return (ret != 0 ? ret :
+	     __db_prheader(dbp, NULL, 0, 1,
+	     handle, callback, vdp, PGNO_BASE_MD));
 }
 
 /*
@@ -1779,7 +1823,7 @@ __db_salvage_unknowns(dbp, vdp, handle, callback, flags)
 	while ((ret = __db_salvage_getnext(vdp, &pgno, &pgtype)) == 0) {
 		dbt = NULL;
 
-		if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0) {
+		if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0) {
 			err_ret = ret;
 			continue;
 		}
@@ -1803,9 +1847,9 @@ __db_salvage_unknowns(dbp, vdp, handle, callback, flags)
 			 */
 			if ((ret = __db_safe_goff(dbp,
 			    vdp, pgno, &key, &ovflbuf, flags)) != 0 ||
-			    (ret = __db_prdbt(&key,
+			    (ret = __db_vrfy_prdbt(&key,
 			    0, " ", handle, callback, 0, vdp)) != 0 ||
-			    (ret = __db_prdbt(&unkdbt,
+			    (ret = __db_vrfy_prdbt(&unkdbt,
 			    0, " ", handle, callback, 0, vdp)) != 0)
 				err_ret = ret;
 			break;
@@ -1824,7 +1868,7 @@ __db_salvage_unknowns(dbp, vdp, handle, callback, flags)
 			DB_ASSERT(0);
 			break;
 		}
-		if ((ret = mpf->put(mpf, h, 0)) != 0)
+		if ((ret = __memp_fput(mpf, h, 0)) != 0)
 			err_ret = ret;
 	}
 
@@ -1904,6 +1948,17 @@ __db_vrfy_inpitem(dbp, h, pgno, i, is_btree, flags, himarkp, offsetp)
 		*himarkp = offset;
 
 	if (is_btree) {
+		/*
+		 * Check alignment;  if it's unaligned, it's unsafe to
+		 * manipulate this item.
+		 */
+		if (offset != DB_ALIGN(offset, sizeof(u_int32_t))) {
+			EPRINT((dbenv,
+			    "Page %lu: unaligned offset %lu at page index %lu",
+			    (u_long)pgno, (u_long)offset, (u_long)i));
+			return (DB_VERIFY_BAD);
+		}
+
 		/*
 		 * Check that the item length remains on-page.
 		 */
@@ -2053,7 +2108,7 @@ __db_salvage_duptree(dbp, vdp, pgno, key, handle, callback, flags)
 		return (DB_VERIFY_BAD);
 
 	/* We have a plausible page.  Try it. */
-	if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
+	if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
 		return (ret);
 
 	switch (TYPE(h)) {
@@ -2081,10 +2136,9 @@ __db_salvage_duptree(dbp, vdp, pgno, key, handle, callback, flags)
 	default:
 		ret = DB_VERIFY_BAD;
 		goto err;
-		/* NOTREACHED */
 	}
 
-err:	if ((t_ret = mpf->put(mpf, h, 0)) != 0 && ret == 0)
+err:	if ((t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
 		ret = t_ret;
 	return (ret);
 }
@@ -2117,7 +2171,7 @@ __db_salvage_subdbs(dbp, vdp, handle, callback, flags, hassubsp)
 	err_ret = 0;
 
 	meta_pgno = PGNO_BASE_MD;
-	if ((ret = mpf->get(mpf, &meta_pgno, 0, &h)) != 0)
+	if ((ret = __memp_fget(mpf, &meta_pgno, 0, &h)) != 0)
 		return (ret);
 
 	if (TYPE(h) == P_BTREEMETA)
@@ -2142,7 +2196,7 @@ __db_salvage_subdbs(dbp, vdp, handle, callback, flags, hassubsp)
 	/* We think we've got subdbs.  Mark it so. */
 	*hassubsp = 1;
 
-	if ((ret = mpf->put(mpf, h, 0)) != 0)
+	if ((ret = __memp_fput(mpf, h, 0)) != 0)
 		return (ret);
 
 	/*
@@ -2159,10 +2213,10 @@ __db_salvage_subdbs(dbp, vdp, handle, callback, flags, hassubsp)
 	    __db_meta2pgset(dbp, vdp, PGNO_BASE_MD, flags, pgset)) != 0)
 		goto err;
 
-	if ((ret = pgset->cursor(pgset, NULL, &pgsc, 0)) != 0)
+	if ((ret = __db_cursor(pgset, NULL, &pgsc, 0)) != 0)
 		goto err;
 	while ((ret = __db_vrfy_pgset_next(pgsc, &p)) == 0) {
-		if ((ret = mpf->get(mpf, &p, 0, &h)) != 0) {
+		if ((ret = __memp_fget(mpf, &p, 0, &h)) != 0) {
 			err_ret = ret;
 			continue;
 		}
@@ -2175,25 +2229,23 @@ __db_salvage_subdbs(dbp, vdp, handle, callback, flags, hassubsp)
 		else if ((ret = __db_salvage_subdbpg(
 		    dbp, vdp, h, handle, callback, flags)) != 0)
 			err_ret = ret;
-nextpg:		if ((ret = mpf->put(mpf, h, 0)) != 0)
+nextpg:		if ((ret = __memp_fput(mpf, h, 0)) != 0)
 			err_ret = ret;
 	}
 
 	if (ret != DB_NOTFOUND)
 		goto err;
-	if ((ret = pgsc->c_close(pgsc)) != 0)
+	if ((ret = __db_c_close(pgsc)) != 0)
 		goto err;
 
-	ret = pgset->close(pgset, 0);
+	ret = __db_close(pgset, NULL, 0);
 	return ((ret == 0 && err_ret != 0) ? err_ret : ret);
 
-	/* NOTREACHED */
-
 err:	if (pgsc != NULL)
-		(void)pgsc->c_close(pgsc);
+		(void)__db_c_close(pgsc);
 	if (pgset != NULL)
-		(void)pgset->close(pgset, 0);
-	(void)mpf->put(mpf, h, 0);
+		(void)__db_close(pgset, NULL, 0);
+	(void)__memp_fput(mpf, h, 0);
 	return (ret);
 }
 
@@ -2247,8 +2299,8 @@ __db_salvage_subdbpg(dbp, vdp, master, handle, callback, flags)
 			 * name so long it overflows.  Ick.
 			 */
 			bo = (BOVERFLOW *)bkkey;
-			if ((ret = __db_safe_goff(dbp, vdp, bo->pgno, &key,
-			    (void **)&subdbname, flags)) != 0) {
+			if ((ret = __db_safe_goff(dbp, vdp,
+			    bo->pgno, &key, &subdbname, flags)) != 0) {
 				err_ret = DB_VERIFY_BAD;
 				continue;
 			}
@@ -2258,7 +2310,7 @@ __db_salvage_subdbpg(dbp, vdp, master, handle, callback, flags)
 			    key.size + 1, &subdbname)) != 0)
 				goto err;
 			subdbname[key.size] = '\0';
-		} else if (B_TYPE(bkkey->type == B_KEYDATA)) {
+		} else if (B_TYPE(bkkey->type) == B_KEYDATA) {
 			if ((ret = __os_realloc(dbenv,
 			    bkkey->len + 1, &subdbname)) != 0)
 				goto err;
@@ -2271,7 +2323,8 @@ __db_salvage_subdbpg(dbp, vdp, master, handle, callback, flags)
 			err_ret = DB_VERIFY_BAD;
 			continue;
 		}
-		memcpy(&meta_pgno, bkdata->data, sizeof(db_pgno_t));
+		memcpy(&meta_pgno,
+		    (db_pgno_t *)bkdata->data, sizeof(db_pgno_t));
 
 		/*
 		 * Subdatabase meta pgnos are stored in network byte
@@ -2281,7 +2334,7 @@ __db_salvage_subdbpg(dbp, vdp, master, handle, callback, flags)
 
 		/* If we can't get the subdb meta page, just skip the subdb. */
 		if (!IS_VALID_PGNO(meta_pgno) ||
-		    (ret = mpf->get(mpf, &meta_pgno, 0, &subpg)) != 0) {
+		    (ret = __memp_fget(mpf, &meta_pgno, 0, &subpg)) != 0) {
 			err_ret = ret;
 			continue;
 		}
@@ -2297,7 +2350,7 @@ __db_salvage_subdbpg(dbp, vdp, master, handle, callback, flags)
 		if ((ret =
 		    __db_vrfy_common(dbp, vdp, subpg, meta_pgno, flags)) != 0) {
 			err_ret = ret;
-			(void)mpf->put(mpf, subpg, 0);
+			(void)__memp_fput(mpf, subpg, 0);
 			continue;
 		}
 		switch (TYPE(subpg)) {
@@ -2305,7 +2358,7 @@ __db_salvage_subdbpg(dbp, vdp, master, handle, callback, flags)
 			if ((ret = __bam_vrfy_meta(dbp,
 			    vdp, (BTMETA *)subpg, meta_pgno, flags)) != 0) {
 				err_ret = ret;
-				(void)mpf->put(mpf, subpg, 0);
+				(void)__memp_fput(mpf, subpg, 0);
 				continue;
 			}
 			break;
@@ -2313,7 +2366,7 @@ __db_salvage_subdbpg(dbp, vdp, master, handle, callback, flags)
 			if ((ret = __ham_vrfy_meta(dbp,
 			    vdp, (HMETA *)subpg, meta_pgno, flags)) != 0) {
 				err_ret = ret;
-				(void)mpf->put(mpf, subpg, 0);
+				(void)__memp_fput(mpf, subpg, 0);
 				continue;
 			}
 			break;
@@ -2321,10 +2374,9 @@ __db_salvage_subdbpg(dbp, vdp, master, handle, callback, flags)
 			/* This isn't an appropriate page;  skip this subdb. */
 			err_ret = DB_VERIFY_BAD;
 			continue;
-			/* NOTREACHED */
 		}
 
-		if ((ret = mpf->put(mpf, subpg, 0)) != 0) {
+		if ((ret = __memp_fput(mpf, subpg, 0)) != 0) {
 			err_ret = ret;
 			continue;
 		}
@@ -2340,24 +2392,24 @@ __db_salvage_subdbpg(dbp, vdp, master, handle, callback, flags)
 			continue;
 		}
 
-		if ((ret = pgset->cursor(pgset, NULL, &pgsc, 0)) != 0)
+		if ((ret = __db_cursor(pgset, NULL, &pgsc, 0)) != 0)
 			goto err;
 		while ((ret = __db_vrfy_pgset_next(pgsc, &p)) == 0) {
-			if ((ret = mpf->get(mpf, &p, 0, &subpg)) != 0) {
+			if ((ret = __memp_fget(mpf, &p, 0, &subpg)) != 0) {
 				err_ret = ret;
 				continue;
 			}
 			if ((ret = __db_salvage(dbp, vdp, p, subpg,
 			    handle, callback, flags)) != 0)
 				err_ret = ret;
-			if ((ret = mpf->put(mpf, subpg, 0)) != 0)
+			if ((ret = __memp_fput(mpf, subpg, 0)) != 0)
 				err_ret = ret;
 		}
 
 		if (ret != DB_NOTFOUND)
 			goto err;
 
-		if ((ret = pgsc->c_close(pgsc)) != 0)
+		if ((ret = __db_c_close(pgsc)) != 0)
 			goto err;
 		if ((ret = __db_prfooter(handle, callback)) != 0)
 			goto err;
@@ -2365,7 +2417,7 @@ __db_salvage_subdbpg(dbp, vdp, master, handle, callback, flags)
 err:	if (subdbname)
 		__os_free(dbenv, subdbname);
 
-	if ((t_ret = pgset->close(pgset, 0)) != 0)
+	if ((t_ret = __db_close(pgset, NULL, 0)) != 0)
 		ret = t_ret;
 
 	if ((t_ret = __db_salvage_markdone(vdp, PGNO(master))) != 0)
@@ -2394,7 +2446,7 @@ __db_meta2pgset(dbp, vdp, pgno, flags, pgset)
 
 	mpf = dbp->mpf;
 
-	if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
+	if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
 		return (ret);
 
 	switch (TYPE(h)) {
@@ -2409,7 +2461,7 @@ __db_meta2pgset(dbp, vdp, pgno, flags, pgset)
 		break;
 	}
 
-	if ((t_ret = mpf->put(mpf, h, 0)) != 0)
+	if ((t_ret = __memp_fput(mpf, h, 0)) != 0)
 		return (t_ret);
 	return (ret);
 }
@@ -2419,7 +2471,7 @@ __db_meta2pgset(dbp, vdp, pgno, flags, pgset)
  *	Try to guess what the pagesize is if the one on the meta page
  *	and the one in the db are invalid.
  */
-static int
+static u_int
 __db_guesspgsize(dbenv, fhp)
 	DB_ENV *dbenv;
 	DB_FH *fhp;
diff --git a/storage/bdb/db/db_vrfy_stub.c b/storage/bdb/db/db_vrfy_stub.c
new file mode 100644
index 0000000000000000000000000000000000000000..486802d7dd73498c4a02b5e2142a719ad98e6c0c
--- /dev/null
+++ b/storage/bdb/db/db_vrfy_stub.c
@@ -0,0 +1,103 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_vrfy_stub.c,v 11.6 2004/06/14 15:23:32 bostic Exp $
+ */
+
+#include "db_config.h"
+
+#ifndef HAVE_VERIFY
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
+#include "dbinc/db_verify.h"
+
+/*
+ * If the library wasn't compiled with the verification support, various
+ * routines aren't available.  Stub them here, returning an appropriate
+ * error.
+ */
+
+static int __db_novrfy __P((DB_ENV *));
+
+/*
+ * __db_novrfy --
+ *	Error when a Berkeley DB build doesn't include the access method.
+ */
+static int
+__db_novrfy(dbenv)
+	DB_ENV *dbenv;
+{
+	__db_err(dbenv,
+	    "library build did not include support for database verification");
+	return (DB_OPNOTSUP);
+}
+
+int
+__db_verify_pp(dbp, file, database, outfile, flags)
+	DB *dbp;
+	const char *file, *database;
+	FILE *outfile;
+	u_int32_t flags;
+{
+	int ret;
+
+	COMPQUIET(file, NULL);
+	COMPQUIET(database, NULL);
+	COMPQUIET(outfile, NULL);
+	COMPQUIET(flags, 0);
+
+	ret = __db_novrfy(dbp->dbenv);
+
+	/* The verify method is a destructor. */
+	(void)__db_close(dbp, NULL, 0);
+
+	return (ret);
+}
+
+int
+__db_verify_internal(dbp, name, subdb, handle, callback, flags)
+	DB *dbp;
+	const char *name, *subdb;
+	void *handle;
+	int (*callback) __P((void *, const void *));
+	u_int32_t flags;
+{
+	COMPQUIET(dbp, NULL);
+	COMPQUIET(name, NULL);
+	COMPQUIET(subdb, NULL);
+	COMPQUIET(handle, NULL);
+	COMPQUIET(callback, NULL);
+	COMPQUIET(flags, 0);
+	return (0);
+}
+
+int
+__db_vrfy_getpageinfo(vdp, pgno, pipp)
+	VRFY_DBINFO *vdp;
+	db_pgno_t pgno;
+	VRFY_PAGEINFO **pipp;
+{
+	COMPQUIET(pgno, 0);
+	COMPQUIET(pipp, NULL);
+	return (__db_novrfy(vdp->pgdbp->dbenv));
+}
+
+int
+__db_vrfy_putpageinfo(dbenv, vdp, pip)
+	DB_ENV *dbenv;
+	VRFY_DBINFO *vdp;
+	VRFY_PAGEINFO *pip;
+{
+	COMPQUIET(vdp, NULL);
+	COMPQUIET(pip, NULL);
+	return (__db_novrfy(dbenv));
+}
+#endif /* !HAVE_VERIFY */
diff --git a/storage/bdb/db/db_vrfyutil.c b/storage/bdb/db/db_vrfyutil.c
index 44344ceed112e19e228347e48bf4d1bf92271a24..f1034af1f2e38df15e3eb09935072e3e671460be 100644
--- a/storage/bdb/db/db_vrfyutil.c
+++ b/storage/bdb/db/db_vrfyutil.c
@@ -1,18 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2000-2002
+ * Copyright (c) 2000-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: db_vrfyutil.c,v 11.29 2002/08/08 03:57:50 bostic Exp $
+ * $Id: db_vrfyutil.c,v 11.40 2004/10/11 18:47:50 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_vrfyutil.c,v 11.29 2002/08/08 03:57:50 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -24,8 +20,8 @@ static const char revid[] = "$Id: db_vrfyutil.c,v 11.29 2002/08/08 03:57:50 bost
 #include "dbinc/db_verify.h"
 #include "dbinc/db_am.h"
 
+static int __db_vrfy_childinc __P((DBC *, VRFY_CHILDINFO *));
 static int __db_vrfy_pageinfo_create __P((DB_ENV *, VRFY_PAGEINFO **));
-static int __db_vrfy_pgset_iinc __P((DB *, db_pgno_t, int));
 
 /*
  * __db_vrfy_dbinfo_create --
@@ -47,31 +43,30 @@ __db_vrfy_dbinfo_create(dbenv, pgsize, vdpp)
 	vdp = NULL;
 	cdbp = pgdbp = pgset = NULL;
 
-	if ((ret = __os_calloc(NULL,
-	    1, sizeof(VRFY_DBINFO), (void **)&vdp)) != 0)
+	if ((ret = __os_calloc(NULL, 1, sizeof(VRFY_DBINFO), &vdp)) != 0)
 		goto err;
 
 	if ((ret = db_create(&cdbp, dbenv, 0)) != 0)
 		goto err;
 
-	if ((ret = cdbp->set_flags(cdbp, DB_DUP)) != 0)
+	if ((ret = __db_set_flags(cdbp, DB_DUP)) != 0)
 		goto err;
 
-	if ((ret = cdbp->set_pagesize(cdbp, pgsize)) != 0)
+	if ((ret = __db_set_pagesize(cdbp, pgsize)) != 0)
 		goto err;
 
-	if ((ret =
-	    cdbp->open(cdbp, NULL, NULL, NULL, DB_BTREE, DB_CREATE, 0600)) != 0)
+	if ((ret = __db_open(cdbp,
+	    NULL, NULL, NULL, DB_BTREE, DB_CREATE, 0600, PGNO_BASE_MD)) != 0)
 		goto err;
 
 	if ((ret = db_create(&pgdbp, dbenv, 0)) != 0)
 		goto err;
 
-	if ((ret = pgdbp->set_pagesize(pgdbp, pgsize)) != 0)
+	if ((ret = __db_set_pagesize(pgdbp, pgsize)) != 0)
 		goto err;
 
-	if ((ret = pgdbp->open(pgdbp,
-	    NULL, NULL, NULL, DB_BTREE, DB_CREATE, 0600)) != 0)
+	if ((ret = __db_open(pgdbp,
+	    NULL, NULL, NULL, DB_BTREE, DB_CREATE, 0600, PGNO_BASE_MD)) != 0)
 		goto err;
 
 	if ((ret = __db_vrfy_pgset(dbenv, pgsize, &pgset)) != 0)
@@ -87,9 +82,9 @@ __db_vrfy_dbinfo_create(dbenv, pgsize, vdpp)
 	return (0);
 
 err:	if (cdbp != NULL)
-		(void)cdbp->close(cdbp, 0);
+		(void)__db_close(cdbp, NULL, 0);
 	if (pgdbp != NULL)
-		(void)pgdbp->close(pgdbp, 0);
+		(void)__db_close(pgdbp, NULL, 0);
 	if (vdp != NULL)
 		__os_free(dbenv, vdp);
 	return (ret);
@@ -117,17 +112,19 @@ __db_vrfy_dbinfo_destroy(dbenv, vdp)
 		__os_free(NULL, c);
 	}
 
-	if ((t_ret = vdp->pgdbp->close(vdp->pgdbp, 0)) != 0)
+	if ((t_ret = __db_close(vdp->pgdbp, NULL, 0)) != 0)
 		ret = t_ret;
 
-	if ((t_ret = vdp->cdbp->close(vdp->cdbp, 0)) != 0 && ret == 0)
+	if ((t_ret = __db_close(vdp->cdbp, NULL, 0)) != 0 && ret == 0)
 		ret = t_ret;
 
-	if ((t_ret = vdp->pgset->close(vdp->pgset, 0)) != 0 && ret == 0)
+	if ((t_ret = __db_close(vdp->pgset, NULL, 0)) != 0 && ret == 0)
 		ret = t_ret;
 
 	DB_ASSERT(LIST_FIRST(&vdp->activepips) == NULL);
 
+	if (vdp->extents != NULL)
+		__os_free(dbenv, vdp->extents);
 	__os_free(dbenv, vdp);
 	return (ret);
 }
@@ -183,9 +180,9 @@ __db_vrfy_getpageinfo(vdp, pgno, pipp)
 	key.data = &pgno;
 	key.size = sizeof(db_pgno_t);
 
-	if ((ret = pgdbp->get(pgdbp, NULL, &key, &data, 0)) == 0) {
+	if ((ret = __db_get(pgdbp, NULL, &key, &data, 0)) == 0) {
 		/* Found it. */
-		DB_ASSERT(data.size = sizeof(VRFY_PAGEINFO));
+		DB_ASSERT(data.size == sizeof(VRFY_PAGEINFO));
 		pip = data.data;
 		DB_ASSERT(pip->pi_refcount == 0);
 		LIST_INSERT_HEAD(&vdp->activepips, pip, links);
@@ -241,7 +238,7 @@ __db_vrfy_putpageinfo(dbenv, vdp, pip)
 	data.data = pip;
 	data.size = sizeof(VRFY_PAGEINFO);
 
-	if ((ret = pgdbp->put(pgdbp, NULL, &key, &data, 0)) != 0)
+	if ((ret = __db_put(pgdbp, NULL, &key, &data, 0)) != 0)
 		return (ret);
 
 	for (p = LIST_FIRST(&vdp->activepips); p != NULL;
@@ -282,13 +279,13 @@ __db_vrfy_pgset(dbenv, pgsize, dbpp)
 
 	if ((ret = db_create(&dbp, dbenv, 0)) != 0)
 		return (ret);
-	if ((ret = dbp->set_pagesize(dbp, pgsize)) != 0)
+	if ((ret = __db_set_pagesize(dbp, pgsize)) != 0)
 		goto err;
-	if ((ret = dbp->open(dbp,
-	    NULL, NULL, NULL, DB_BTREE, DB_CREATE, 0600)) == 0)
+	if ((ret = __db_open(dbp,
+	    NULL, NULL, NULL, DB_BTREE, DB_CREATE, 0600, PGNO_BASE_MD)) == 0)
 		*dbpp = dbp;
 	else
-err:		(void)dbp->close(dbp, 0);
+err:		(void)__db_close(dbp, NULL, 0);
 
 	return (ret);
 }
@@ -318,9 +315,8 @@ __db_vrfy_pgset_get(dbp, pgno, valp)
 	data.ulen = sizeof(int);
 	F_SET(&data, DB_DBT_USERMEM);
 
-	if ((ret = dbp->get(dbp, NULL, &key, &data, 0)) == 0) {
-		DB_ASSERT(data.size = sizeof(int));
-		memcpy(&val, data.data, sizeof(int));
+	if ((ret = __db_get(dbp, NULL, &key, &data, 0)) == 0) {
+		DB_ASSERT(data.size == sizeof(int));
 	} else if (ret == DB_NOTFOUND)
 		val = 0;
 	else
@@ -341,36 +337,6 @@ __db_vrfy_pgset_inc(dbp, pgno)
 	DB *dbp;
 	db_pgno_t pgno;
 {
-
-	return (__db_vrfy_pgset_iinc(dbp, pgno, 1));
-}
-
-/*
- * __db_vrfy_pgset_dec --
- *	Increment the value associated with a pgno by 1.
- *
- * PUBLIC: int __db_vrfy_pgset_dec __P((DB *, db_pgno_t));
- */
-int
-__db_vrfy_pgset_dec(dbp, pgno)
-	DB *dbp;
-	db_pgno_t pgno;
-{
-
-	return (__db_vrfy_pgset_iinc(dbp, pgno, -1));
-}
-
-/*
- * __db_vrfy_pgset_iinc --
- *	Increment the value associated with a pgno by i.
- *
- */
-static int
-__db_vrfy_pgset_iinc(dbp, pgno, i)
-	DB *dbp;
-	db_pgno_t pgno;
-	int i;
-{
 	DBT key, data;
 	int ret;
 	int val;
@@ -386,16 +352,15 @@ __db_vrfy_pgset_iinc(dbp, pgno, i)
 	data.ulen = sizeof(int);
 	F_SET(&data, DB_DBT_USERMEM);
 
-	if ((ret = dbp->get(dbp, NULL, &key, &data, 0)) == 0) {
+	if ((ret = __db_get(dbp, NULL, &key, &data, 0)) == 0) {
 		DB_ASSERT(data.size == sizeof(int));
-		memcpy(&val, data.data, sizeof(int));
 	} else if (ret != DB_NOTFOUND)
 		return (ret);
 
 	data.size = sizeof(int);
-	val += i;
+	++val;
 
-	return (dbp->put(dbp, NULL, &key, &data, 0));
+	return (__db_put(dbp, NULL, &key, &data, 0));
 }
 
 /*
@@ -422,7 +387,7 @@ __db_vrfy_pgset_next(dbc, pgnop)
 	key.data = &pgno;
 	key.ulen = sizeof(db_pgno_t);
 
-	if ((ret = dbc->c_get(dbc, &key, &data, DB_NEXT)) != 0)
+	if ((ret = __db_c_get(dbc, &key, &data, DB_NEXT)) != 0)
 		return (ret);
 
 	DB_ASSERT(key.size == sizeof(db_pgno_t));
@@ -449,7 +414,7 @@ __db_vrfy_childcursor(vdp, dbcp)
 
 	cdbp = vdp->cdbp;
 
-	if ((ret = cdbp->cursor(cdbp, NULL, &dbc, 0)) == 0)
+	if ((ret = __db_cursor(cdbp, NULL, &dbc, 0)) == 0)
 		*dbcp = dbc;
 
 	return (ret);
@@ -501,10 +466,12 @@ __db_vrfy_childput(vdp, pgno, cip)
 	    ret = __db_vrfy_ccnext(cc, &oldcip))
 		if (oldcip->pgno == cip->pgno) {
 			/*
-			 * Found a matching child.  Return without
-			 * putting it again.
+			 * Found a matching child.  Increment its reference
+			 * count--we've run into it again--but don't put it
+			 * again.
 			 */
-			if ((ret = __db_vrfy_ccclose(cc)) != 0)
+			if ((ret = __db_vrfy_childinc(cc, oldcip)) != 0 ||
+			    (ret = __db_vrfy_ccclose(cc)) != 0)
 				return (ret);
 			return (0);
 		}
@@ -515,10 +482,34 @@ __db_vrfy_childput(vdp, pgno, cip)
 	if ((ret = __db_vrfy_ccclose(cc)) != 0)
 		return (ret);
 
+	cip->refcnt = 1;
 	data.data = cip;
 	data.size = sizeof(VRFY_CHILDINFO);
 
-	return (cdbp->put(cdbp, NULL, &key, &data, 0));
+	return (__db_put(cdbp, NULL, &key, &data, 0));
+}
+
+/*
+ * __db_vrfy_childinc --
+ *	Increment the refcount of the VRFY_CHILDINFO struct that the child
+ * cursor is pointing to.  (The caller has just retrieved this struct, and
+ * passes it in as cip to save us a get.)
+ */
+static int
+__db_vrfy_childinc(dbc, cip)
+	DBC *dbc;
+	VRFY_CHILDINFO *cip;
+{
+	DBT key, data;
+
+	memset(&key, 0, sizeof(DBT));
+	memset(&data, 0, sizeof(DBT));
+
+	cip->refcnt++;
+	data.data = cip;
+	data.size = sizeof(VRFY_CHILDINFO);
+
+	return (__db_c_put(dbc, &key, &data, DB_CURRENT));
 }
 
 /*
@@ -543,7 +534,7 @@ __db_vrfy_ccset(dbc, pgno, cipp)
 	key.data = &pgno;
 	key.size = sizeof(db_pgno_t);
 
-	if ((ret = dbc->c_get(dbc, &key, &data, DB_SET)) != 0)
+	if ((ret = __db_c_get(dbc, &key, &data, DB_SET)) != 0)
 		return (ret);
 
 	DB_ASSERT(data.size == sizeof(VRFY_CHILDINFO));
@@ -571,7 +562,7 @@ __db_vrfy_ccnext(dbc, cipp)
 	memset(&key, 0, sizeof(DBT));
 	memset(&data, 0, sizeof(DBT));
 
-	if ((ret = dbc->c_get(dbc, &key, &data, DB_NEXT_DUP)) != 0)
+	if ((ret = __db_c_get(dbc, &key, &data, DB_NEXT_DUP)) != 0)
 		return (ret);
 
 	DB_ASSERT(data.size == sizeof(VRFY_CHILDINFO));
@@ -596,7 +587,7 @@ __db_vrfy_ccclose(dbc)
 	DBC *dbc;
 {
 
-	return (dbc->c_close(dbc));
+	return (__db_c_close(dbc));
 }
 
 /*
@@ -618,8 +609,7 @@ __db_vrfy_pageinfo_create(dbenv, pgipp)
 	 * used, and so we always allocate with __os_umalloc so we can free
 	 * with __os_ufree.
 	 */
-	if ((ret = __os_umalloc(dbenv,
-	    sizeof(VRFY_PAGEINFO), (void **)&pgip)) != 0)
+	if ((ret = __os_umalloc(dbenv, sizeof(VRFY_PAGEINFO), &pgip)) != 0)
 		return (ret);
 	memset(pgip, 0, sizeof(VRFY_PAGEINFO));
 
@@ -645,17 +635,17 @@ __db_salvage_init(vdp)
 	if ((ret = db_create(&dbp, NULL, 0)) != 0)
 		return (ret);
 
-	if ((ret = dbp->set_pagesize(dbp, 1024)) != 0)
+	if ((ret = __db_set_pagesize(dbp, 1024)) != 0)
 		goto err;
 
-	if ((ret = dbp->open(dbp,
-	    NULL, NULL, NULL, DB_BTREE, DB_CREATE, 0)) != 0)
+	if ((ret = __db_open(dbp,
+	    NULL, NULL, NULL, DB_BTREE, DB_CREATE, 0, PGNO_BASE_MD)) != 0)
 		goto err;
 
 	vdp->salvage_pages = dbp;
 	return (0);
 
-err:	(void)dbp->close(dbp, 0);
+err:	(void)__db_close(dbp, NULL, 0);
 	return (ret);
 }
 
@@ -668,7 +658,7 @@ void
 __db_salvage_destroy(vdp)
 	VRFY_DBINFO *vdp;
 {
-	(void)vdp->salvage_pages->close(vdp->salvage_pages, 0);
+	(void)__db_close(vdp->salvage_pages, NULL, 0);
 }
 
 /*
@@ -697,14 +687,14 @@ __db_salvage_getnext(vdp, pgnop, pgtypep)
 	memset(&key, 0, sizeof(DBT));
 	memset(&data, 0, sizeof(DBT));
 
-	if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0)
+	if ((ret = __db_cursor(dbp, NULL, &dbc, 0)) != 0)
 		return (ret);
 
-	while ((ret = dbc->c_get(dbc, &key, &data, DB_NEXT)) == 0) {
+	while ((ret = __db_c_get(dbc, &key, &data, DB_NEXT)) == 0) {
 		DB_ASSERT(data.size == sizeof(u_int32_t));
 		memcpy(&pgtype, data.data, sizeof(pgtype));
 
-		if ((ret = dbc->c_del(dbc, 0)) != 0)
+		if ((ret = __db_c_del(dbc, 0)) != 0)
 			goto err;
 		if (pgtype != SALVAGE_IGNORE)
 			goto found;
@@ -720,7 +710,7 @@ found:		DB_ASSERT(key.size == sizeof(db_pgno_t));
 		*pgtypep = *(u_int32_t *)data.data;
 	}
 
-err:	(void)dbc->c_close(dbc);
+err:	(void)__db_c_close(dbc);
 	return (ret);
 }
 
@@ -763,7 +753,7 @@ __db_salvage_isdone(vdp, pgno)
 	 * If it's there and is marked anything else, that's fine--we
 	 * want to mark it done.
 	 */
-	ret = dbp->get(dbp, NULL, &key, &data, 0);
+	ret = __db_get(dbp, NULL, &key, &data, 0);
 	if (ret == 0) {
 		/*
 		 * The key's already here.  Check and see if it's already
@@ -830,7 +820,7 @@ __db_salvage_markdone(vdp, pgno)
 	data.size = sizeof(u_int32_t);
 	data.data = &pgtype;
 
-	return (dbp->put(dbp, NULL, &key, &data, 0));
+	return (__db_put(dbp, NULL, &key, &data, 0));
 }
 
 /*
@@ -867,6 +857,49 @@ __db_salvage_markneeded(vdp, pgno, pgtype)
 	 * unless it's already there, in which case it's presumably
 	 * already been marked done.
 	 */
-	ret = dbp->put(dbp, NULL, &key, &data, DB_NOOVERWRITE);
+	ret = __db_put(dbp, NULL, &key, &data, DB_NOOVERWRITE);
 	return (ret == DB_KEYEXIST ? 0 : ret);
 }
+
+/*
+ * __db_vrfy_prdbt --
+ *	Print out a DBT data element from a verification routine.
+ *
+ * PUBLIC: int __db_vrfy_prdbt __P((DBT *, int, const char *, void *,
+ * PUBLIC:     int (*)(void *, const void *), int, VRFY_DBINFO *));
+ */
+int
+__db_vrfy_prdbt(dbtp, checkprint, prefix, handle, callback, is_recno, vdp)
+	DBT *dbtp;
+	int checkprint;
+	const char *prefix;
+	void *handle;
+	int (*callback) __P((void *, const void *));
+	int is_recno;
+	VRFY_DBINFO *vdp;
+{
+	if (vdp != NULL) {
+		/*
+		 * If vdp is non-NULL, we might be the first key in the
+		 * "fake" subdatabase used for key/data pairs we can't
+		 * associate with a known subdb.
+		 *
+		 * Check and clear the SALVAGE_PRINTHEADER flag;  if
+		 * it was set, print a subdatabase header.
+		 */
+		if (F_ISSET(vdp, SALVAGE_PRINTHEADER))
+			(void)__db_prheader(
+			    NULL, "__OTHER__", 0, 0, handle, callback, vdp, 0);
+		F_CLR(vdp, SALVAGE_PRINTHEADER);
+		F_SET(vdp, SALVAGE_PRINTFOOTER);
+
+		/*
+		 * Even if the printable flag wasn't set by our immediate
+		 * caller, it may be set on a salvage-wide basis.
+		 */
+		if (F_ISSET(vdp, SALVAGE_PRINTABLE))
+			checkprint = 1;
+	}
+	return (
+	    __db_prdbt(dbtp, checkprint, prefix, handle, callback, is_recno));
+}
diff --git a/storage/bdb/db185/db185.c b/storage/bdb/db185/db185.c
index 99d37bcf341c15e53139843458082cae7ecf2097..8399eac42f47f714f5becd12b6a861d7a9181996 100644
--- a/storage/bdb/db185/db185.c
+++ b/storage/bdb/db185/db185.c
@@ -1,17 +1,17 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db185.c,v 11.35 2004/03/24 20:37:35 bostic Exp $
  */
 
 #include "db_config.h"
 
 #ifndef lint
 static const char copyright[] =
-    "Copyright (c) 1996-2002\nSleepycat Software Inc.  All rights reserved.\n";
-static const char revid[] =
-    "$Id: db185.c,v 11.28 2002/05/09 01:55:14 bostic Exp $";
+    "Copyright (c) 1996-2004\nSleepycat Software Inc.  All rights reserved.\n";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -19,7 +19,6 @@ static const char revid[] =
 
 #include <fcntl.h>
 #include <string.h>
-#include <unistd.h>
 #endif
 
 #include "db_int.h"
@@ -32,7 +31,6 @@ static int	db185_fd __P((const DB185 *));
 static int	db185_get __P((const DB185 *, const DBT185 *, DBT185 *, u_int));
 static u_int32_t
 		db185_hash __P((DB *, const void *, u_int32_t));
-static void	db185_openstderr __P((DB_FH *));
 static size_t	db185_prefix __P((DB *, const DBT *, const DBT *));
 static int	db185_put __P((const DB185 *, DBT185 *, const DBT185 *, u_int));
 static int	db185_seq __P((const DB185 *, DBT185 *, DBT185 *, u_int));
@@ -59,8 +57,7 @@ __db185_open(file, oflags, mode, type, openinfo)
 	const RECNOINFO *ri;
 	DB *dbp;
 	DB185 *db185p;
-	DB_FH fh;
-	size_t nw;
+	DB_FH *fhp;
 	int ret;
 
 	dbp = NULL;
@@ -161,8 +158,8 @@ __db185_open(file, oflags, mode, type, openinfo)
 		if (file != NULL) {
 			if (oflags & O_CREAT && __os_exists(file, NULL) != 0)
 				if (__os_openhandle(NULL, file,
-				    oflags, mode, &fh) == 0)
-					(void)__os_closehandle(NULL, &fh);
+				    oflags, mode, &fhp) == 0)
+					(void)__os_closehandle(NULL, fhp);
 			(void)dbp->set_re_source(dbp, file);
 
 			if (O_RDONLY)
@@ -176,11 +173,10 @@ __db185_open(file, oflags, mode, type, openinfo)
 			 * !!!
 			 * We can't support the bfname field.
 			 */
-#define	BFMSG	"DB: DB 1.85's recno bfname field is not supported.\n"
+#define	BFMSG \
+	"Berkeley DB: DB 1.85's recno bfname field is not supported.\n"
 			if (ri->bfname != NULL) {
-				db185_openstderr(&fh);
-				(void)__os_write(NULL, &fh,
-				    BFMSG, sizeof(BFMSG) - 1, &nw);
+				dbp->errx(dbp, "%s", BFMSG);
 				goto einval;
 			}
 
@@ -228,7 +224,7 @@ __db185_open(file, oflags, mode, type, openinfo)
 	 * Store a reference so we can indirect from the DB 1.85 structure
 	 * to the underlying DB structure, and vice-versa.  This has to be
 	 * done BEFORE the DB::open method call because the hash callback
-	 * is exercised as part of hash database initialiation.
+	 * is exercised as part of hash database initialization.
 	 */
 	db185p->dbp = dbp;
 	dbp->api_internal = db185p;
@@ -244,9 +240,9 @@ __db185_open(file, oflags, mode, type, openinfo)
 
 	return (db185p);
 
-err:	if (ret < 0)		/* DB 1.85 can't handle DB 2.0's errors. */
-einval:		ret = EINVAL;
-	if (db185p != NULL)
+einval:	ret = EINVAL;
+
+err:	if (db185p != NULL)
 		__os_free(NULL, db185p);
 	if (dbp != NULL)
 		(void)dbp->close(dbp, 0);
@@ -271,8 +267,6 @@ db185_close(db185p)
 	if (ret == 0)
 		return (0);
 
-	if (ret < 0)		/* DB 1.85 can't handle DB 2.0's errors. */
-		ret = EINVAL;
 	__os_set_errno(ret);
 	return (-1);
 }
@@ -307,8 +301,9 @@ db185_del(db185p, key185, flags)
 		return (1);
 	}
 
-	if (ret < 0)		/* DB 1.85 can't handle DB 2.0's errors. */
+	if (0) {
 einval:		ret = EINVAL;
+	}
 	__os_set_errno(ret);
 	return (-1);
 }
@@ -325,8 +320,6 @@ db185_fd(db185p)
 	if ((ret = dbp->fd(dbp, &fd)) == 0)
 		return (fd);
 
-	if (ret < 0)		/* DB 1.85 can't handle DB 2.0's errors. */
-		ret = EINVAL;
 	__os_set_errno(ret);
 	return (-1);
 }
@@ -363,8 +356,9 @@ db185_get(db185p, key185, data185, flags)
 		return (1);
 	}
 
-	if (ret < 0)		/* DB 1.85 can't handle DB 2.0's errors. */
+	if (0) {
 einval:		ret = EINVAL;
+	}
 	__os_set_errno(ret);
 	return (-1);
 }
@@ -440,8 +434,9 @@ db185_put(db185p, key185, data185, flags)
 		return (1);
 	}
 
-	if (ret < 0)		/* DB 1.85 can't handle DB 2.0's errors. */
+	if (0) {
 einval:		ret = EINVAL;
+	}
 	__os_set_errno(ret);
 	return (-1);
 }
@@ -499,8 +494,9 @@ db185_seq(db185p, key185, data185, flags)
 		return (1);
 	}
 
-	if (ret < 0)		/* DB 1.85 can't handle DB 2.0's errors. */
+	if (0) {
 einval:		ret = EINVAL;
+	}
 	__os_set_errno(ret);
 	return (-1);
 }
@@ -511,8 +507,6 @@ db185_sync(db185p, flags)
 	u_int flags;
 {
 	DB *dbp;
-	DB_FH fh;
-	size_t nw;
 	int ret;
 
 	dbp = db185p->dbp;
@@ -525,10 +519,10 @@ db185_sync(db185p, flags)
 		 * !!!
 		 * We can't support the R_RECNOSYNC flag.
 		 */
-#define	RSMSG	"DB: DB 1.85's R_RECNOSYNC sync flag is not supported.\n"
-		db185_openstderr(&fh);
-		(void)__os_write(NULL, &fh, RSMSG, sizeof(RSMSG) - 1, &nw);
-		goto einval;
+#define	RSMSG \
+	"Berkeley DB: DB 1.85's R_RECNOSYNC sync flag is not supported.\n"
+		dbp->errx(dbp, "%s", RSMSG);
+		/* FALLTHROUGH */
 	default:
 		goto einval;
 	}
@@ -536,26 +530,13 @@ db185_sync(db185p, flags)
 	if ((ret = dbp->sync(dbp, 0)) == 0)
 		return (0);
 
-	if (ret < 0)		/* DB 1.85 can't handle DB 2.0's errors. */
+	if (0) {
 einval:		ret = EINVAL;
+	}
 	__os_set_errno(ret);
 	return (-1);
 }
 
-static void
-db185_openstderr(fhp)
-	DB_FH *fhp;
-{
-	/* Dummy up the results of an __os_openhandle() on stderr. */
-	memset(fhp, 0, sizeof(*fhp));
-	F_SET(fhp, DB_FH_VALID);
-
-#ifndef STDERR_FILENO
-#define	STDERR_FILENO	2
-#endif
-	fhp->fd = STDERR_FILENO;
-}
-
 /*
  * db185_compare --
  *	Cutout routine to call the user's Btree comparison function.
diff --git a/storage/bdb/db185/db185_int.in b/storage/bdb/db185/db185_int.in
index a4a3ce19c17ed496985324fc4ce563a2241b6305..f9bfdbba01ccd08a17bfc95bc2c08b54ce51aa33 100644
--- a/storage/bdb/db185/db185_int.in
+++ b/storage/bdb/db185/db185_int.in
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -36,7 +36,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: db185_int.in,v 11.12 2002/01/11 15:51:51 bostic Exp $
+ * $Id: db185_int.in,v 11.14 2004/01/28 03:35:59 bostic Exp $
  */
 
 #ifndef _DB185_INT_H_
diff --git a/storage/bdb/db_archive/db_archive.c b/storage/bdb/db_archive/db_archive.c
index dc8718e4c03e03e31adf8f29df8595c8c6ae3575..d5db42deed2406113e068814d38d3c4f28faa5b5 100644
--- a/storage/bdb/db_archive/db_archive.c
+++ b/storage/bdb/db_archive/db_archive.c
@@ -1,17 +1,17 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_archive.c,v 11.46 2004/06/10 01:00:08 bostic Exp $
  */
 
 #include "db_config.h"
 
 #ifndef lint
 static const char copyright[] =
-    "Copyright (c) 1996-2002\nSleepycat Software Inc.  All rights reserved.\n";
-static const char revid[] =
-    "$Id: db_archive.c,v 11.36 2002/03/28 20:13:34 bostic Exp $";
+    "Copyright (c) 1996-2004\nSleepycat Software Inc.  All rights reserved.\n";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -39,20 +39,25 @@ main(argc, argv)
 	const char *progname = "db_archive";
 	DB_ENV	*dbenv;
 	u_int32_t flags;
-	int ch, e_close, exitval, ret, verbose;
+	int ch, exitval, ret, verbose;
 	char **file, *home, **list, *passwd;
 
 	if ((ret = version_check(progname)) != 0)
 		return (ret);
 
+	dbenv = NULL;
 	flags = 0;
-	e_close = exitval = verbose = 0;
+	exitval = verbose = 0;
 	home = passwd = NULL;
-	while ((ch = getopt(argc, argv, "ah:lP:sVv")) != EOF)
+	file = list = NULL;
+	while ((ch = getopt(argc, argv, "adh:lP:sVv")) != EOF)
 		switch (ch) {
 		case 'a':
 			LF_SET(DB_ARCH_ABS);
 			break;
+		case 'd':
+			LF_SET(DB_ARCH_REMOVE);
+			break;
 		case 'h':
 			home = optarg;
 			break;
@@ -99,14 +104,10 @@ main(argc, argv)
 		    "%s: db_env_create: %s\n", progname, db_strerror(ret));
 		goto shutdown;
 	}
-	e_close = 1;
 
 	dbenv->set_errfile(dbenv, stderr);
 	dbenv->set_errpfx(dbenv, progname);
 
-	if (verbose)
-		(void)dbenv->set_verbose(dbenv, DB_VERB_CHKPOINT, 1);
-
 	if (passwd != NULL && (ret = dbenv->set_encrypt(dbenv,
 	    passwd, DB_ENCRYPT_AES)) != 0) {
 		dbenv->err(dbenv, ret, "set_passwd");
@@ -118,9 +119,10 @@ main(argc, argv)
 	 */
 	if ((ret = dbenv->open(dbenv,
 	    home, DB_JOINENV | DB_USE_ENVIRON, 0)) != 0 &&
+	    (ret == DB_VERSION_MISMATCH ||
 	    (ret = dbenv->open(dbenv, home, DB_CREATE |
-	    DB_INIT_LOG | DB_INIT_TXN | DB_PRIVATE | DB_USE_ENVIRON, 0)) != 0) {
-		dbenv->err(dbenv, ret, "open");
+	    DB_INIT_LOG | DB_PRIVATE | DB_USE_ENVIRON, 0)) != 0)) {
+		dbenv->err(dbenv, ret, "DB_ENV->open");
 		goto shutdown;
 	}
 
@@ -140,12 +142,15 @@ main(argc, argv)
 	if (0) {
 shutdown:	exitval = 1;
 	}
-	if (e_close && (ret = dbenv->close(dbenv, 0)) != 0) {
+	if (dbenv != NULL && (ret = dbenv->close(dbenv, 0)) != 0) {
 		exitval = 1;
 		fprintf(stderr,
 		    "%s: dbenv->close: %s\n", progname, db_strerror(ret));
 	}
 
+	if (passwd != NULL)
+		free(passwd);
+
 	/* Resend any caught signal. */
 	__db_util_sigresend();
 
@@ -156,7 +161,7 @@ int
 usage()
 {
 	(void)fprintf(stderr,
-	    "usage: db_archive [-alsVv] [-h home] [-P password]\n");
+	    "usage: db_archive [-adlsVv] [-h home] [-P password]\n");
 	return (EXIT_FAILURE);
 }
 
@@ -168,12 +173,11 @@ version_check(progname)
 
 	/* Make sure we're loaded with the right version of the DB library. */
 	(void)db_version(&v_major, &v_minor, &v_patch);
-	if (v_major != DB_VERSION_MAJOR ||
-	    v_minor != DB_VERSION_MINOR || v_patch != DB_VERSION_PATCH) {
+	if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) {
 		fprintf(stderr,
-	"%s: version %d.%d.%d doesn't match library version %d.%d.%d\n",
+	"%s: version %d.%d doesn't match library version %d.%d\n",
 		    progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
-		    DB_VERSION_PATCH, v_major, v_minor, v_patch);
+		    v_major, v_minor);
 		return (EXIT_FAILURE);
 	}
 	return (0);
diff --git a/storage/bdb/db_checkpoint/db_checkpoint.c b/storage/bdb/db_checkpoint/db_checkpoint.c
index a59572c5f76a7a4bd44778cf6caa91d02e98075e..538b66ddcd1b124660804b05feb1adef63ffe09d 100644
--- a/storage/bdb/db_checkpoint/db_checkpoint.c
+++ b/storage/bdb/db_checkpoint/db_checkpoint.c
@@ -1,17 +1,17 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_checkpoint.c,v 11.54 2004/03/24 15:13:12 bostic Exp $
  */
 
 #include "db_config.h"
 
 #ifndef lint
 static const char copyright[] =
-    "Copyright (c) 1996-2002\nSleepycat Software Inc.  All rights reserved.\n";
-static const char revid[] =
-    "$Id: db_checkpoint.c,v 11.46 2002/08/08 03:50:31 bostic Exp $";
+    "Copyright (c) 1996-2004\nSleepycat Software Inc.  All rights reserved.\n";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -55,7 +55,7 @@ main(argc, argv)
 	time_t now;
 	long argval;
 	u_int32_t flags, kbytes, minutes, seconds;
-	int ch, e_close, exitval, once, ret, verbose;
+	int ch, exitval, once, ret, verbose;
 	char *home, *logfile, *passwd;
 
 	if ((ret = version_check(progname)) != 0)
@@ -68,8 +68,9 @@ main(argc, argv)
 	 */
 #define	MAX_UINT32_T	2147483647
 
+	dbenv = NULL;
 	kbytes = minutes = 0;
-	e_close = exitval = once = verbose = 0;
+	exitval = once = verbose = 0;
 	flags = 0;
 	home = logfile = passwd = NULL;
 	while ((ch = getopt(argc, argv, "1h:k:L:P:p:Vv")) != EOF)
@@ -144,7 +145,6 @@ main(argc, argv)
 		    "%s: db_env_create: %s\n", progname, db_strerror(ret));
 		goto shutdown;
 	}
-	e_close = 1;
 
 	dbenv->set_errfile(dbenv, stderr);
 	dbenv->set_errpfx(dbenv, progname);
@@ -178,7 +178,7 @@ main(argc, argv)
 	while (!__db_util_interrupted()) {
 		if (verbose) {
 			(void)time(&now);
-			dbenv->errx(dbenv, "checkpoint: %s", ctime(&now));
+			dbenv->errx(dbenv, "checkpoint begin: %s", ctime(&now));
 		}
 
 		if ((ret = dbenv->txn_checkpoint(dbenv,
@@ -187,10 +187,16 @@ main(argc, argv)
 			goto shutdown;
 		}
 
+		if (verbose) {
+			(void)time(&now);
+			dbenv->errx(dbenv,
+			    "checkpoint complete: %s", ctime(&now));
+		}
+
 		if (once)
 			break;
 
-		(void)__os_sleep(dbenv, seconds, 0);
+		__os_sleep(dbenv, seconds, 0);
 	}
 
 	if (0) {
@@ -202,12 +208,15 @@ shutdown:	exitval = 1;
 		remove(logfile);
 
 	/* Clean up the environment. */
-	if (e_close && (ret = dbenv->close(dbenv, 0)) != 0) {
+	if (dbenv != NULL && (ret = dbenv->close(dbenv, 0)) != 0) {
 		exitval = 1;
 		fprintf(stderr,
 		    "%s: dbenv->close: %s\n", progname, db_strerror(ret));
 	}
 
+	if (passwd != NULL)
+		free(passwd);
+
 	/* Resend any caught signal. */
 	__db_util_sigresend();
 
@@ -231,12 +240,11 @@ version_check(progname)
 
 	/* Make sure we're loaded with the right version of the DB library. */
 	(void)db_version(&v_major, &v_minor, &v_patch);
-	if (v_major != DB_VERSION_MAJOR ||
-	    v_minor != DB_VERSION_MINOR || v_patch != DB_VERSION_PATCH) {
+	if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) {
 		fprintf(stderr,
-	"%s: version %d.%d.%d doesn't match library version %d.%d.%d\n",
+	"%s: version %d.%d doesn't match library version %d.%d\n",
 		    progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
-		    DB_VERSION_PATCH, v_major, v_minor, v_patch);
+		    v_major, v_minor);
 		return (EXIT_FAILURE);
 	}
 	return (0);
diff --git a/storage/bdb/db_deadlock/db_deadlock.c b/storage/bdb/db_deadlock/db_deadlock.c
index 523918b9ea41d36a27698d9e33f894b92168ca8e..cc91db25d749b1cc03e3c7d7772336019e17f68a 100644
--- a/storage/bdb/db_deadlock/db_deadlock.c
+++ b/storage/bdb/db_deadlock/db_deadlock.c
@@ -1,17 +1,17 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_deadlock.c,v 11.45 2004/03/24 15:13:12 bostic Exp $
  */
 
 #include "db_config.h"
 
 #ifndef lint
 static const char copyright[] =
-    "Copyright (c) 1996-2002\nSleepycat Software Inc.  All rights reserved.\n";
-static const char revid[] =
-    "$Id: db_deadlock.c,v 11.38 2002/08/08 03:50:32 bostic Exp $";
+    "Copyright (c) 1996-2004\nSleepycat Software Inc.  All rights reserved.\n";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -52,17 +52,18 @@ main(argc, argv)
 	DB_ENV  *dbenv;
 	u_int32_t atype;
 	time_t now;
-	long secs, usecs;
-	int ch, e_close, exitval, ret, verbose;
+	u_long secs, usecs;
+	int ch, exitval, ret, verbose;
 	char *home, *logfile, *str;
 
 	if ((ret = version_check(progname)) != 0)
 		return (ret);
 
+	dbenv = NULL;
 	atype = DB_LOCK_DEFAULT;
 	home = logfile = NULL;
 	secs = usecs = 0;
-	e_close = exitval = verbose = 0;
+	exitval = verbose = 0;
 	while ((ch = getopt(argc, argv, "a:h:L:t:Vvw")) != EOF)
 		switch (ch) {
 		case 'a':
@@ -79,6 +80,9 @@ main(argc, argv)
 			case 'o':
 				atype = DB_LOCK_OLDEST;
 				break;
+			case 'W':
+				atype = DB_LOCK_MAXWRITE;
+				break;
 			case 'w':
 				atype = DB_LOCK_MINWRITE;
 				break;
@@ -101,11 +105,11 @@ main(argc, argv)
 		case 't':
 			if ((str = strchr(optarg, '.')) != NULL) {
 				*str++ = '\0';
-				if (*str != '\0' && __db_getlong(
+				if (*str != '\0' && __db_getulong(
 				    NULL, progname, str, 0, LONG_MAX, &usecs))
 					return (EXIT_FAILURE);
 			}
-			if (*optarg != '\0' && __db_getlong(
+			if (*optarg != '\0' && __db_getulong(
 			    NULL, progname, optarg, 0, LONG_MAX, &secs))
 				return (EXIT_FAILURE);
 			if (secs == 0 && usecs == 0)
@@ -150,7 +154,6 @@ main(argc, argv)
 		    "%s: db_env_create: %s\n", progname, db_strerror(ret));
 		goto shutdown;
 	}
-	e_close = 1;
 
 	dbenv->set_errfile(dbenv, stderr);
 	dbenv->set_errpfx(dbenv, progname);
@@ -161,8 +164,8 @@ main(argc, argv)
 	}
 
 	/* An environment is required. */
-	if ((ret = dbenv->open(dbenv, home,
-	    DB_JOINENV | DB_USE_ENVIRON, 0)) != 0) {
+	if ((ret =
+	    dbenv->open(dbenv, home, DB_INIT_LOCK | DB_USE_ENVIRON, 0)) != 0) {
 		dbenv->err(dbenv, ret, "open");
 		goto shutdown;
 	}
@@ -181,7 +184,7 @@ main(argc, argv)
 		/* Make a pass every "secs" secs and "usecs" usecs. */
 		if (secs == 0 && usecs == 0)
 			break;
-		(void)__os_sleep(dbenv, secs, usecs);
+		__os_sleep(dbenv, secs, usecs);
 	}
 
 	if (0) {
@@ -190,10 +193,10 @@ shutdown:	exitval = 1;
 
 	/* Clean up the logfile. */
 	if (logfile != NULL)
-		remove(logfile);
+		(void)remove(logfile);
 
 	/* Clean up the environment. */
-	if (e_close && (ret = dbenv->close(dbenv, 0)) != 0) {
+	if (dbenv != NULL && (ret = dbenv->close(dbenv, 0)) != 0) {
 		exitval = 1;
 		fprintf(stderr,
 		    "%s: dbenv->close: %s\n", progname, db_strerror(ret));
@@ -210,7 +213,7 @@ usage()
 {
 	(void)fprintf(stderr, "%s\n\t%s\n",
 	    "usage: db_deadlock [-Vv]",
-	    "[-a e | m | n | o | w | y] [-h home] [-L file] [-t sec.usec]");
+	    "[-a e | m | n | o | W | w | y] [-h home] [-L file] [-t sec.usec]");
 	return (EXIT_FAILURE);
 }
 
@@ -222,12 +225,11 @@ version_check(progname)
 
 	/* Make sure we're loaded with the right version of the DB library. */
 	(void)db_version(&v_major, &v_minor, &v_patch);
-	if (v_major != DB_VERSION_MAJOR ||
-	    v_minor != DB_VERSION_MINOR || v_patch != DB_VERSION_PATCH) {
+	if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) {
 		fprintf(stderr,
-	"%s: version %d.%d.%d doesn't match library version %d.%d.%d\n",
+	"%s: version %d.%d doesn't match library version %d.%d\n",
 		    progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
-		    DB_VERSION_PATCH, v_major, v_minor, v_patch);
+		    v_major, v_minor);
 		return (EXIT_FAILURE);
 	}
 	return (0);
diff --git a/storage/bdb/db_dump/db_dump.c b/storage/bdb/db_dump/db_dump.c
index 143884a3fa8475822b6476a4da6f684748e8c7fa..732a4c62fd0d0da5f2b2f418240016fba5ba53e6 100644
--- a/storage/bdb/db_dump/db_dump.c
+++ b/storage/bdb/db_dump/db_dump.c
@@ -1,17 +1,17 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_dump.c,v 11.99 2004/10/11 18:53:13 bostic Exp $
  */
 
 #include "db_config.h"
 
 #ifndef lint
 static const char copyright[] =
-    "Copyright (c) 1996-2002\nSleepycat Software Inc.  All rights reserved.\n";
-static const char revid[] =
-    "$Id: db_dump.c,v 11.80 2002/08/08 03:50:34 bostic Exp $";
+    "Copyright (c) 1996-2004\nSleepycat Software Inc.  All rights reserved.\n";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -28,7 +28,6 @@ static const char revid[] =
 #include "dbinc/db_am.h"
 
 int	 db_init __P((DB_ENV *, char *, int, u_int32_t, int *));
-int	 dump __P((DB *, int, int));
 int	 dump_sub __P((DB_ENV *, DB *, char *, int, int));
 int	 is_sub __P((DB *, int *));
 int	 main __P((int, char *[]));
@@ -47,16 +46,17 @@ main(argc, argv)
 	DB_ENV	*dbenv;
 	DB *dbp;
 	u_int32_t cache;
-	int ch, d_close;
-	int e_close, exitval, keyflag, lflag, nflag, pflag, private;
+	int ch;
+	int exitval, keyflag, lflag, nflag, pflag, private;
 	int ret, Rflag, rflag, resize, subs;
 	char *dopt, *home, *passwd, *subname;
 
 	if ((ret = version_check(progname)) != 0)
 		return (ret);
 
+	dbenv = NULL;
 	dbp = NULL;
-	d_close = e_close = exitval = lflag = nflag = pflag = rflag = Rflag = 0;
+	exitval = lflag = nflag = pflag = rflag = Rflag = 0;
 	keyflag = 0;
 	cache = MEGABYTE;
 	private = 0;
@@ -159,7 +159,6 @@ retry:	if ((ret = db_env_create(&dbenv, 0)) != 0) {
 		    "%s: db_env_create: %s\n", progname, db_strerror(ret));
 		goto err;
 	}
-	e_close = 1;
 
 	dbenv->set_errfile(dbenv, stderr);
 	dbenv->set_errpfx(dbenv, progname);
@@ -188,19 +187,20 @@ retry:	if ((ret = db_env_create(&dbenv, 0)) != 0) {
 		dbenv->err(dbenv, ret, "db_create");
 		goto err;
 	}
-	d_close = 1;
 
 	/*
 	 * If we're salvaging, don't do an open;  it might not be safe.
 	 * Dispatch now into the salvager.
 	 */
 	if (rflag) {
-		if ((ret = dbp->verify(dbp, argv[0], NULL, stdout,
+		/* The verify method is a destructor. */
+		ret = dbp->verify(dbp, argv[0], NULL, stdout,
 		    DB_SALVAGE |
 		    (Rflag ? DB_AGGRESSIVE : 0) |
-		    (pflag ? DB_PRINTABLE : 0))) != 0)
+		    (pflag ? DB_PRINTABLE : 0));
+		dbp = NULL;
+		if (ret != 0)
 			goto err;
-		exitval = 0;
 		goto done;
 	}
 
@@ -210,21 +210,21 @@ retry:	if ((ret = db_env_create(&dbenv, 0)) != 0) {
 		goto err;
 	}
 	if (private != 0) {
-		if ((ret = __db_util_cache(dbenv, dbp, &cache, &resize)) != 0)
+		if ((ret = __db_util_cache(dbp, &cache, &resize)) != 0)
 			goto err;
 		if (resize) {
 			(void)dbp->close(dbp, 0);
-			d_close = 0;
+			dbp = NULL;
 
 			(void)dbenv->close(dbenv, 0);
-			e_close = 0;
+			dbenv = NULL;
 			goto retry;
 		}
 	}
 
 	if (dopt != NULL) {
-		if (__db_dump(dbp, dopt, NULL)) {
-			dbp->err(dbp, ret, "__db_dump: %s", argv[0]);
+		if ((ret = __db_dumptree(dbp, dopt, NULL)) != 0) {
+			dbp->err(dbp, ret, "__db_dumptree: %s", argv[0]);
 			goto err;
 		}
 	} else if (lflag) {
@@ -245,25 +245,27 @@ retry:	if ((ret = db_env_create(&dbenv, 0)) != 0) {
 			if (dump_sub(dbenv, dbp, argv[0], pflag, keyflag))
 				goto err;
 		} else
-			if (__db_prheader(dbp, NULL, pflag, keyflag, stdout,
-			    __db_verify_callback, NULL, 0) ||
-			    dump(dbp, pflag, keyflag))
+			if (dbp->dump(dbp, NULL,
+			    __db_pr_callback, stdout, pflag, keyflag))
 				goto err;
 	}
 
 	if (0) {
 err:		exitval = 1;
 	}
-done:	if (d_close && (ret = dbp->close(dbp, 0)) != 0) {
+done:	if (dbp != NULL && (ret = dbp->close(dbp, 0)) != 0) {
 		exitval = 1;
 		dbenv->err(dbenv, ret, "close");
 	}
-	if (e_close && (ret = dbenv->close(dbenv, 0)) != 0) {
+	if (dbenv != NULL && (ret = dbenv->close(dbenv, 0)) != 0) {
 		exitval = 1;
 		fprintf(stderr,
 		    "%s: dbenv->close: %s\n", progname, db_strerror(ret));
 	}
 
+	if (passwd != NULL)
+		free(passwd);
+
 	/* Resend any caught signal. */
 	__db_util_sigresend();
 
@@ -303,9 +305,11 @@ db_init(dbenv, home, is_salvage, cache, is_privatep)
 	 * before we create our own.
 	 */
 	*is_privatep = 0;
-	if (dbenv->open(dbenv, home,
-	    DB_USE_ENVIRON | (is_salvage ? DB_INIT_MPOOL : DB_JOINENV), 0) == 0)
+	if ((ret = dbenv->open(dbenv, home, DB_USE_ENVIRON |
+	    (is_salvage ? DB_INIT_MPOOL : DB_JOINENV), 0)) == 0)
 		return (0);
+	if (ret == DB_VERSION_MISMATCH)
+		goto err;
 
 	/*
 	 * An environment is required because we may be trying to look at
@@ -324,7 +328,7 @@ db_init(dbenv, home, is_salvage, cache, is_privatep)
 		return (0);
 
 	/* An environment is required. */
-	dbenv->err(dbenv, ret, "open");
+err:	dbenv->err(dbenv, ret, "DB_ENV->open");
 	return (1);
 }
 
@@ -344,7 +348,7 @@ is_sub(dbp, yesno)
 	switch (dbp->type) {
 	case DB_BTREE:
 	case DB_RECNO:
-		if ((ret = dbp->stat(dbp, &btsp, DB_FAST_STAT)) != 0) {
+		if ((ret = dbp->stat(dbp, NULL, &btsp, DB_FAST_STAT)) != 0) {
 			dbp->err(dbp, ret, "DB->stat");
 			return (ret);
 		}
@@ -352,7 +356,7 @@ is_sub(dbp, yesno)
 		free(btsp);
 		break;
 	case DB_HASH:
-		if ((ret = dbp->stat(dbp, &hsp, DB_FAST_STAT)) != 0) {
+		if ((ret = dbp->stat(dbp, NULL, &hsp, DB_FAST_STAT)) != 0) {
 			dbp->err(dbp, ret, "DB->stat");
 			return (ret);
 		}
@@ -361,6 +365,7 @@ is_sub(dbp, yesno)
 		break;
 	case DB_QUEUE:
 		break;
+	case DB_UNKNOWN:
 	default:
 		dbp->errx(dbp, "unknown database type");
 		return (1);
@@ -415,10 +420,8 @@ dump_sub(dbenv, parent_dbp, parent_name, pflag, keyflag)
 		    parent_name, subdb, DB_UNKNOWN, DB_RDONLY, 0)) != 0)
 			dbp->err(dbp, ret,
 			    "DB->open: %s:%s", parent_name, subdb);
-		if (ret == 0 &&
-		    (__db_prheader(dbp, subdb, pflag, keyflag, stdout,
-		    __db_verify_callback, NULL, 0) ||
-		    dump(dbp, pflag, keyflag)))
+		if (ret == 0 && dbp->dump(
+		    dbp, subdb, __db_pr_callback, stdout, pflag, keyflag))
 			ret = 1;
 		(void)dbp->close(dbp, 0);
 		free(subdb);
@@ -426,12 +429,12 @@ dump_sub(dbenv, parent_dbp, parent_name, pflag, keyflag)
 			return (1);
 	}
 	if (ret != DB_NOTFOUND) {
-		dbp->err(dbp, ret, "DBcursor->get");
+		parent_dbp->err(parent_dbp, ret, "DBcursor->get");
 		return (1);
 	}
 
 	if ((ret = dbcp->c_close(dbcp)) != 0) {
-		dbp->err(dbp, ret, "DBcursor->close");
+		parent_dbp->err(parent_dbp, ret, "DBcursor->close");
 		return (1);
 	}
 
@@ -462,8 +465,8 @@ show_subs(dbp)
 	memset(&key, 0, sizeof(key));
 	memset(&data, 0, sizeof(data));
 	while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0) {
-		if ((ret = __db_prdbt(&key, 1, NULL, stdout,
-		    __db_verify_callback, 0, NULL)) != 0) {
+		if ((ret = dbp->dbenv->prdbt(
+		    &key, 1, NULL, stdout, __db_pr_callback, 0)) != 0) {
 			dbp->errx(dbp, NULL);
 			return (1);
 		}
@@ -480,104 +483,6 @@ show_subs(dbp)
 	return (0);
 }
 
-/*
- * dump --
- *	Dump out the records for a DB.
- */
-int
-dump(dbp, pflag, keyflag)
-	DB *dbp;
-	int pflag, keyflag;
-{
-	DBC *dbcp;
-	DBT key, data;
-	DBT keyret, dataret;
-	db_recno_t recno;
-	int is_recno, failed, ret;
-	void *pointer;
-
-	/*
-	 * Get a cursor and step through the database, printing out each
-	 * key/data pair.
-	 */
-	if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) {
-		dbp->err(dbp, ret, "DB->cursor");
-		return (1);
-	}
-
-	failed = 0;
-	memset(&key, 0, sizeof(key));
-	memset(&data, 0, sizeof(data));
-	data.data = malloc(1024 * 1024);
-	if (data.data == NULL) {
-		dbp->err(dbp, ENOMEM, "bulk get buffer");
-		failed = 1;
-		goto err;
-	}
-	data.ulen = 1024 * 1024;
-	data.flags = DB_DBT_USERMEM;
-	is_recno = (dbp->type == DB_RECNO || dbp->type == DB_QUEUE);
-	keyflag = is_recno ? keyflag : 1;
-	if (is_recno) {
-		keyret.data = &recno;
-		keyret.size = sizeof(recno);
-	}
-
-retry:
-	while ((ret =
-	    dbcp->c_get(dbcp, &key, &data, DB_NEXT | DB_MULTIPLE_KEY)) == 0) {
-		DB_MULTIPLE_INIT(pointer, &data);
-		for (;;) {
-			if (is_recno)
-				DB_MULTIPLE_RECNO_NEXT(pointer, &data,
-				    recno, dataret.data, dataret.size);
-			else
-				DB_MULTIPLE_KEY_NEXT(pointer,
-				    &data, keyret.data,
-				    keyret.size, dataret.data, dataret.size);
-
-			if (dataret.data == NULL)
-				break;
-
-			if ((keyflag && (ret = __db_prdbt(&keyret,
-			    pflag, " ", stdout, __db_verify_callback,
-			    is_recno, NULL)) != 0) || (ret =
-			    __db_prdbt(&dataret, pflag, " ", stdout,
-				__db_verify_callback, 0, NULL)) != 0) {
-				dbp->errx(dbp, NULL);
-				failed = 1;
-				goto err;
-			}
-		}
-	}
-	if (ret == ENOMEM) {
-		data.data = realloc(data.data, data.size);
-		if (data.data == NULL) {
-			dbp->err(dbp, ENOMEM, "bulk get buffer");
-			failed = 1;
-			goto err;
-		}
-		data.ulen = data.size;
-		goto retry;
-	}
-
-	if (ret != DB_NOTFOUND) {
-		dbp->err(dbp, ret, "DBcursor->get");
-		failed = 1;
-	}
-
-err:	if (data.data != NULL)
-		free(data.data);
-
-	if ((ret = dbcp->c_close(dbcp)) != 0) {
-		dbp->err(dbp, ret, "DBcursor->close");
-		failed = 1;
-	}
-
-	(void)__db_prfooter(stdout, __db_verify_callback);
-	return (failed);
-}
-
 /*
  * usage --
  *	Display the usage message.
@@ -599,12 +504,11 @@ version_check(progname)
 
 	/* Make sure we're loaded with the right version of the DB library. */
 	(void)db_version(&v_major, &v_minor, &v_patch);
-	if (v_major != DB_VERSION_MAJOR ||
-	    v_minor != DB_VERSION_MINOR || v_patch != DB_VERSION_PATCH) {
+	if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) {
 		fprintf(stderr,
-	"%s: version %d.%d.%d doesn't match library version %d.%d.%d\n",
+	"%s: version %d.%d doesn't match library version %d.%d\n",
 		    progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
-		    DB_VERSION_PATCH, v_major, v_minor, v_patch);
+		    v_major, v_minor);
 		return (EXIT_FAILURE);
 	}
 	return (0);
diff --git a/storage/bdb/db_dump185/db_dump185.c b/storage/bdb/db_dump185/db_dump185.c
index 97164f34a9a73903dbdf1cd6d60105e4f2d034f9..2fb3cc5ab58ebd01a4372853ed3a3f886ec04b91 100644
--- a/storage/bdb/db_dump185/db_dump185.c
+++ b/storage/bdb/db_dump185/db_dump185.c
@@ -1,15 +1,15 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_dump185.c,v 11.19 2004/01/28 03:36:00 bostic Exp $
  */
 
 #ifndef lint
 static char copyright[] =
-    "Copyright (c) 1996-2002\nSleepycat Software Inc.  All rights reserved.\n";
-static char revid[] =
-    "$Id: db_dump185.c,v 11.17 2002/08/08 03:50:35 bostic Exp $";
+    "Copyright (c) 1996-2004\nSleepycat Software Inc.  All rights reserved.\n";
 #endif
 
 #include <sys/types.h>
diff --git a/storage/bdb/db_load/db_load.c b/storage/bdb/db_load/db_load.c
index d27fca04ec02a2f9ef6e9b115b7ca55846309523..db0caf42d58a32c229b1db208352d36b20b4f9e4 100644
--- a/storage/bdb/db_load/db_load.c
+++ b/storage/bdb/db_load/db_load.c
@@ -1,17 +1,17 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_load.c,v 11.100 2004/10/29 17:29:02 bostic Exp $
  */
 
 #include "db_config.h"
 
 #ifndef lint
 static const char copyright[] =
-    "Copyright (c) 1996-2002\nSleepycat Software Inc.  All rights reserved.\n";
-static const char revid[] =
-    "$Id: db_load.c,v 11.71 2002/08/08 03:50:36 bostic Exp $";
+    "Copyright (c) 1996-2004\nSleepycat Software Inc.  All rights reserved.\n";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -50,6 +50,7 @@ int	db_init __P((DB_ENV *, char *, u_int32_t, int *));
 int	dbt_rdump __P((DB_ENV *, DBT *));
 int	dbt_rprint __P((DB_ENV *, DBT *));
 int	dbt_rrecno __P((DB_ENV *, DBT *, int));
+int	dbt_to_recno __P((DB_ENV *, DBT *, db_recno_t *));
 int	digitize __P((DB_ENV *, int, int *));
 int	env_create __P((DB_ENV **, LDG *));
 int	load __P((DB_ENV *, char *, DBTYPE, char **, u_int, LDG *, int *));
@@ -70,12 +71,13 @@ main(argc, argv)
 	int argc;
 	char *argv[];
 {
+	enum { NOTSET, FILEID_RESET, LSN_RESET, STANDARD_LOAD } mode;
 	extern char *optarg;
 	extern int optind;
 	DBTYPE dbtype;
 	DB_ENV	*dbenv;
 	LDG ldg;
-	u_int32_t ldf;
+	u_int ldf;
 	int ch, existed, exitval, ret;
 	char **clist, **clp;
 
@@ -91,22 +93,39 @@ main(argc, argv)
 	if ((ret = version_check(ldg.progname)) != 0)
 		return (ret);
 
+	mode = NOTSET;
 	ldf = 0;
-	exitval = 0;
+	exitval = existed = 0;
 	dbtype = DB_UNKNOWN;
 
 	/* Allocate enough room for configuration arguments. */
-	if ((clp = clist = (char **)calloc(argc + 1, sizeof(char *))) == NULL) {
+	if ((clp = clist =
+	    (char **)calloc((size_t)argc + 1, sizeof(char *))) == NULL) {
 		fprintf(stderr, "%s: %s\n", ldg.progname, strerror(ENOMEM));
 		return (EXIT_FAILURE);
 	}
 
-	while ((ch = getopt(argc, argv, "c:f:h:nP:Tt:V")) != EOF)
+	/*
+	 * There are two modes for db_load: -r and everything else.  The -r
+	 * option zeroes out the database LSN's or resets the file ID, it
+	 * doesn't really "load" a new database.  The functionality is in
+	 * db_load because we don't have a better place to put it, and we
+	 * don't want to create a new utility for just that functionality.
+	 */
+	while ((ch = getopt(argc, argv, "c:f:h:nP:r:Tt:V")) != EOF)
 		switch (ch) {
 		case 'c':
+			if (mode != NOTSET && mode != STANDARD_LOAD)
+				return (usage());
+			mode = STANDARD_LOAD;
+
 			*clp++ = optarg;
 			break;
 		case 'f':
+			if (mode != NOTSET && mode != STANDARD_LOAD)
+				return (usage());
+			mode = STANDARD_LOAD;
+
 			if (freopen(optarg, "r", stdin) == NULL) {
 				fprintf(stderr, "%s: %s: reopen: %s\n",
 				    ldg.progname, optarg, strerror(errno));
@@ -117,6 +136,10 @@ main(argc, argv)
 			ldg.home = optarg;
 			break;
 		case 'n':
+			if (mode != NOTSET && mode != STANDARD_LOAD)
+				return (usage());
+			mode = STANDARD_LOAD;
+
 			ldf |= LDF_NOOVERWRITE;
 			break;
 		case 'P':
@@ -129,10 +152,28 @@ main(argc, argv)
 			}
 			ldf |= LDF_PASSWORD;
 			break;
+		case 'r':
+			if (mode == STANDARD_LOAD)
+				return (usage());
+			if (strcmp(optarg, "lsn") == 0)
+				mode = LSN_RESET;
+			else if (strcmp(optarg, "fileid") == 0)
+				mode = FILEID_RESET;
+			else
+				return (usage());
+			break;
 		case 'T':
+			if (mode != NOTSET && mode != STANDARD_LOAD)
+				return (usage());
+			mode = STANDARD_LOAD;
+
 			ldf |= LDF_NOHEADER;
 			break;
 		case 't':
+			if (mode != NOTSET && mode != STANDARD_LOAD)
+				return (usage());
+			mode = STANDARD_LOAD;
+
 			if (strcmp(optarg, "btree") == 0) {
 				dbtype = DB_BTREE;
 				break;
@@ -173,10 +214,24 @@ main(argc, argv)
 	if (env_create(&dbenv, &ldg) != 0)
 		goto shutdown;
 
-	while (!ldg.endofile)
-		if (load(dbenv, argv[0], dbtype, clist, ldf,
-		    &ldg, &existed) != 0)
-			goto shutdown;
+	/* If we're resetting the LSNs, that's an entirely separate path. */
+	switch (mode) {
+	case FILEID_RESET:
+		exitval = dbenv->fileid_reset(
+		    dbenv, argv[0], ldf & LDF_PASSWORD ? 1 : 0);
+		break;
+	case LSN_RESET:
+		exitval = dbenv->lsn_reset(
+		    dbenv, argv[0], ldf & LDF_PASSWORD ? 1 : 0);
+		break;
+	case NOTSET:
+	case STANDARD_LOAD:
+		while (!ldg.endofile)
+			if (load(dbenv, argv[0], dbtype, clist, ldf,
+			    &ldg, &existed) != 0)
+				goto shutdown;
+		break;
+	}
 
 	if (0) {
 shutdown:	exitval = 1;
@@ -190,6 +245,8 @@ shutdown:	exitval = 1;
 	/* Resend any caught signal. */
 	__db_util_sigresend();
 	free(clist);
+	if (ldg.passwd != NULL)
+		free(ldg.passwd);
 
 	/*
 	 * Return 0 on success, 1 if keys existed already, and 2 on failure.
@@ -223,8 +280,6 @@ load(dbenv, name, argtype, clist, flags, ldg, existedp)
 	int ascii_recno, checkprint, hexkeys, keyflag, keys, resize, ret, rval;
 	char *subdb;
 
-	*existedp = 0;
-
 	put_flags = LF_ISSET(LDF_NOOVERWRITE) ? DB_NOOVERWRITE : 0;
 	G(endodata) = 0;
 
@@ -235,16 +290,17 @@ load(dbenv, name, argtype, clist, flags, ldg, existedp)
 	memset(&rkey, 0, sizeof(DBT));
 
 retry_db:
+	dbtype = DB_UNKNOWN;
+	keys = -1;
+	hexkeys = -1;
+	keyflag = -1;
+
 	/* Create the DB object. */
 	if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
 		dbenv->err(dbenv, ret, "db_create");
 		goto err;
 	}
 
-	dbtype = DB_UNKNOWN;
-	keys = -1;
-	hexkeys = -1;
-	keyflag = -1;
 	/* Read the header -- if there's no header, we expect flat text. */
 	if (LF_ISSET(LDF_NOHEADER)) {
 		checkprint = 1;
@@ -328,6 +384,20 @@ retry_db:
 		goto err;
 	}
 
+#if 0
+	Set application-specific btree comparison or hash functions here.
+	For example:
+
+	if ((ret = dbp->set_bt_compare(dbp, local_comparison_func)) != 0) {
+		dbp->err(dbp, ret, "DB->set_bt_compare");
+		goto err;
+	}
+	if ((ret = dbp->set_h_hash(dbp, local_hash_func)) != 0) {
+		dbp->err(dbp, ret, "DB->set_h_hash");
+		goto err;
+	}
+#endif
+
 	/* Open the DB file. */
 	if ((ret = dbp->open(dbp, NULL, name, subdb, dbtype,
 	    DB_CREATE | (TXN_ON(dbenv) ? DB_AUTO_COMMIT : 0),
@@ -336,13 +406,14 @@ retry_db:
 		goto err;
 	}
 	if (ldg->private != 0) {
-		if ((ret =
-		    __db_util_cache(dbenv, dbp, &ldg->cache, &resize)) != 0)
+		if ((ret = __db_util_cache(dbp, &ldg->cache, &resize)) != 0)
 			goto err;
 		if (resize) {
-			dbp->close(dbp, 0);
+			if ((ret = dbp->close(dbp, 0)) != 0)
+				goto err;
 			dbp = NULL;
-			dbenv->close(dbenv, 0);
+			if ((ret = dbenv->close(dbenv, 0)) != 0)
+				goto err;
 			if ((ret = env_create(&dbenv, ldg)) != 0)
 				goto err;
 			goto retry_db;
@@ -350,8 +421,7 @@ retry_db:
 	}
 
 	/* Initialize the key/data pair. */
-	readp = &key;
-	writep = &key;
+	readp = writep = &key;
 	if (dbtype == DB_RECNO || dbtype == DB_QUEUE) {
 		key.size = sizeof(recno);
 		if (keyflag) {
@@ -360,16 +430,14 @@ retry_db:
 				readp = &rkey;
 				goto key_data;
 			}
-		}
-		else
+		} else
 			key.data = &recno;
 	} else
-key_data:	if ((readp->data =
-		    (void *)malloc(readp->ulen = 1024)) == NULL) {
+key_data:	if ((readp->data = malloc(readp->ulen = 1024)) == NULL) {
 			dbenv->err(dbenv, ENOMEM, NULL);
 			goto err;
 		}
-	if ((data.data = (void *)malloc(data.ulen = 1024)) == NULL) {
+	if ((data.data = malloc(data.ulen = 1024)) == NULL) {
 		dbenv->err(dbenv, ENOMEM, NULL);
 		goto err;
 	}
@@ -380,7 +448,7 @@ key_data:	if ((readp->data =
 
 	/* Get each key/data pair and add them to the database. */
 	for (recno = 1; !__db_util_interrupted(); ++recno) {
-		if (!keyflag)
+		if (!keyflag) {
 			if (checkprint) {
 				if (dbt_rprint(dbenv, &data))
 					goto err;
@@ -388,12 +456,16 @@ key_data:	if ((readp->data =
 				if (dbt_rdump(dbenv, &data))
 					goto err;
 			}
-		else
+		} else {
 			if (checkprint) {
 				if (dbt_rprint(dbenv, readp))
 					goto err;
+				if (ascii_recno &&
+				    dbt_to_recno(dbenv, readp, &datarecno) != 0)
+					goto err;
+
 				if (!G(endodata) && dbt_rprint(dbenv, &data))
-					goto fmt;
+					goto odd_count;
 			} else {
 				if (ascii_recno) {
 					if (dbt_rrecno(dbenv, readp, hexkeys))
@@ -401,24 +473,16 @@ key_data:	if ((readp->data =
 				} else
 					if (dbt_rdump(dbenv, readp))
 						goto err;
+
 				if (!G(endodata) && dbt_rdump(dbenv, &data)) {
-fmt:					dbenv->errx(dbenv,
+odd_count:				dbenv->errx(dbenv,
 					    "odd number of key/data pairs");
 					goto err;
 				}
 			}
+		}
 		if (G(endodata))
 			break;
-		if (readp != writep) {
-			if (sscanf(readp->data, "%ud", &datarecno) != 1)
-				dbenv->errx(dbenv,
-				    "%s: non-integer key at line: %d",
-				    name, !keyflag ? recno : recno * 2 - 1);
-			if (datarecno == 0)
-				dbenv->errx(dbenv, "%s: zero key at line: %d",
-				    name,
-				    !keyflag ? recno : recno * 2 - 1);
-		}
 retry:		if (txn != NULL)
 			if ((ret = dbenv->txn_begin(dbenv, txn, &ctxn, 0)) != 0)
 				goto err;
@@ -438,8 +502,8 @@ retry:		if (txn != NULL)
 			    name,
 			    !keyflag ? recno : recno * 2 - 1);
 
-			(void)__db_prdbt(&key, checkprint, 0, stderr,
-			    __db_verify_callback, 0, NULL);
+			(void)dbenv->prdbt(&key,
+			    checkprint, 0, stderr, __db_pr_callback, 0);
 			break;
 		case DB_LOCK_DEADLOCK:
 			/* If we have a child txn, retry--else it's fatal. */
@@ -490,7 +554,7 @@ err:		rval = 1;
 	/* Free allocated memory. */
 	if (subdb != NULL)
 		free(subdb);
-	if (dbtype != DB_RECNO && dbtype != DB_QUEUE)
+	if (dbtype != DB_RECNO && dbtype != DB_QUEUE && key.data != NULL)
 		free(key.data);
 	if (rkey.data != NULL)
 		free(rkey.data);
@@ -499,6 +563,38 @@ err:		rval = 1;
 	return (rval);
 }
 
+/*
+ * env_create --
+ *	Create the environment and initialize it for error reporting.
+ */
+int
+env_create(dbenvp, ldg)
+	DB_ENV **dbenvp;
+	LDG *ldg;
+{
+	DB_ENV *dbenv;
+	int ret;
+
+	if ((ret = db_env_create(dbenvp, 0)) != 0) {
+		fprintf(stderr,
+		    "%s: db_env_create: %s\n", ldg->progname, db_strerror(ret));
+		return (ret);
+	}
+	dbenv = *dbenvp;
+	dbenv->set_errfile(dbenv, stderr);
+	dbenv->set_errpfx(dbenv, ldg->progname);
+	if (ldg->passwd != NULL && (ret = dbenv->set_encrypt(dbenv,
+	    ldg->passwd, DB_ENCRYPT_AES)) != 0) {
+		dbenv->err(dbenv, ret, "set_passwd");
+		return (ret);
+	}
+	if ((ret = db_init(dbenv, ldg->home, ldg->cache, &ldg->private)) != 0)
+		return (ret);
+	dbenv->app_private = ldg;
+
+	return (0);
+}
+
 /*
  * db_init --
  *	Initialize the environment.
@@ -517,8 +613,10 @@ db_init(dbenv, home, cache, is_private)
 	/* We may be loading into a live environment.  Try and join. */
 	flags = DB_USE_ENVIRON |
 	    DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN;
-	if (dbenv->open(dbenv, home, flags, 0) == 0)
+	if ((ret = dbenv->open(dbenv, home, flags, 0)) == 0)
 		return (0);
+	if (ret == DB_VERSION_MISMATCH)
+		goto err;
 
 	/*
 	 * We're trying to load a database.
@@ -543,7 +641,7 @@ db_init(dbenv, home, cache, is_private)
 		return (0);
 
 	/* An environment is required. */
-	dbenv->err(dbenv, ret, "DB_ENV->open");
+err:	dbenv->err(dbenv, ret, "DB_ENV->open");
 	return (1);
 }
 
@@ -565,12 +663,12 @@ db_init(dbenv, home, cache, is_private)
 		}							\
 		continue;						\
 	}
-#define	NUMBER(name, value, keyword, func)				\
+#define	NUMBER(name, value, keyword, func, t)				\
 	if (strcmp(name, keyword) == 0) {				\
-		if (__db_getlong(dbp,					\
+		if (__db_getlong(dbenv,					\
 		    NULL, value, 1, LONG_MAX, &val) != 0)		\
 			return (1);					\
-		if ((ret = dbp->func(dbp, val)) != 0)			\
+		if ((ret = dbp->func(dbp, (t)val)) != 0)		\
 			goto nameerr;					\
 		continue;						\
 	}
@@ -628,17 +726,17 @@ configure(dbenv, dbp, clp, subdbp, keysp)
 		}
 
 #ifdef notyet
-		NUMBER(name, value, "bt_maxkey", set_bt_maxkey);
+		NUMBER(name, value, "bt_maxkey", set_bt_maxkey, u_int32_t);
 #endif
-		NUMBER(name, value, "bt_minkey", set_bt_minkey);
-		NUMBER(name, value, "db_lorder", set_lorder);
-		NUMBER(name, value, "db_pagesize", set_pagesize);
-		FLAG(name, value, "chksum", DB_CHKSUM_SHA1);
+		NUMBER(name, value, "bt_minkey", set_bt_minkey, u_int32_t);
+		NUMBER(name, value, "db_lorder", set_lorder, int);
+		NUMBER(name, value, "db_pagesize", set_pagesize, u_int32_t);
+		FLAG(name, value, "chksum", DB_CHKSUM);
 		FLAG(name, value, "duplicates", DB_DUP);
 		FLAG(name, value, "dupsort", DB_DUPSORT);
-		NUMBER(name, value, "h_ffactor", set_h_ffactor);
-		NUMBER(name, value, "h_nelem", set_h_nelem);
-		NUMBER(name, value, "re_len", set_re_len);
+		NUMBER(name, value, "h_ffactor", set_h_ffactor, u_int32_t);
+		NUMBER(name, value, "h_nelem", set_h_nelem, u_int32_t);
+		NUMBER(name, value, "re_len", set_re_len, u_int32_t);
 		STRING(name, value, "re_pad", set_re_pad);
 		FLAG(name, value, "recnum", DB_RECNUM);
 		FLAG(name, value, "renumber", DB_RENUMBER);
@@ -666,8 +764,9 @@ rheader(dbenv, dbp, dbtypep, subdbp, checkprintp, keysp)
 	char **subdbp;
 	int *checkprintp, *keysp;
 {
+	size_t buflen, linelen, start;
 	long val;
-	int ch, first, hdr, linelen, buflen, ret, start;
+	int ch, first, hdr, ret;
 	char *buf, *name, *p, *value;
 
 	*dbtypep = DB_UNKNOWN;
@@ -681,7 +780,7 @@ rheader(dbenv, dbp, dbtypep, subdbp, checkprintp, keysp)
 	buflen = 4096;
 	if (G(hdrbuf) == NULL) {
 		hdr = 0;
-		if ((buf = (char *)malloc(buflen)) == NULL) {
+		if ((buf = malloc(buflen)) == NULL) {
 memerr:			dbp->errx(dbp, "could not allocate buffer %d", buflen);
 			return (1);
 		}
@@ -709,19 +808,21 @@ memerr:			dbp->errx(dbp, "could not allocate buffer %d", buflen);
 					break;
 				}
 
-				if (ch == '\n')
-					break;
-
-				buf[linelen++] = ch;
-
-				/* If the buffer is too small, double it. */
+				/*
+				 * If the buffer is too small, double it.
+				 */
 				if (linelen + start == buflen) {
-					G(hdrbuf) = (char *)realloc(G(hdrbuf),
-					    buflen *= 2);
+					G(hdrbuf) =
+					    realloc(G(hdrbuf), buflen *= 2);
 					if (G(hdrbuf) == NULL)
 						goto memerr;
 					buf = &G(hdrbuf)[start];
 				}
+
+				if (ch == '\n')
+					break;
+
+				buf[linelen++] = ch;
 			}
 			if (G(endofile) == 1)
 				break;
@@ -816,18 +917,18 @@ memerr:			dbp->errx(dbp, "could not allocate buffer %d", buflen);
 		}
 
 #ifdef notyet
-		NUMBER(name, value, "bt_maxkey", set_bt_maxkey);
+		NUMBER(name, value, "bt_maxkey", set_bt_maxkey, u_int32_t);
 #endif
-		NUMBER(name, value, "bt_minkey", set_bt_minkey);
-		NUMBER(name, value, "db_lorder", set_lorder);
-		NUMBER(name, value, "db_pagesize", set_pagesize);
-		NUMBER(name, value, "extentsize", set_q_extentsize);
-		FLAG(name, value, "chksum", DB_CHKSUM_SHA1);
+		NUMBER(name, value, "bt_minkey", set_bt_minkey, u_int32_t);
+		NUMBER(name, value, "db_lorder", set_lorder, int);
+		NUMBER(name, value, "db_pagesize", set_pagesize, u_int32_t);
+		NUMBER(name, value, "extentsize", set_q_extentsize, u_int32_t);
+		FLAG(name, value, "chksum", DB_CHKSUM);
 		FLAG(name, value, "duplicates", DB_DUP);
 		FLAG(name, value, "dupsort", DB_DUPSORT);
-		NUMBER(name, value, "h_ffactor", set_h_ffactor);
-		NUMBER(name, value, "h_nelem", set_h_nelem);
-		NUMBER(name, value, "re_len", set_re_len);
+		NUMBER(name, value, "h_ffactor", set_h_ffactor, u_int32_t);
+		NUMBER(name, value, "h_nelem", set_h_nelem, u_int32_t);
+		NUMBER(name, value, "re_len", set_re_len, u_int32_t);
 		STRING(name, value, "re_pad", set_re_pad);
 		FLAG(name, value, "recnum", DB_RECNUM);
 		FLAG(name, value, "renumber", DB_RENUMBER);
@@ -839,19 +940,16 @@ memerr:			dbp->errx(dbp, "could not allocate buffer %d", buflen);
 	}
 	ret = 0;
 	if (0) {
-nameerr:
-		dbp->err(dbp, ret, "%s: %s=%s", G(progname), name, value);
-		ret = 1;
-	}
-	if (0)
+nameerr:	dbp->err(dbp, ret, "%s: %s=%s", G(progname), name, value);
 err:		ret = 1;
+	}
 	if (0) {
-badfmt:
-		dbp->errx(dbp, "line %lu: unexpected format", G(lineno));
+badfmt:		dbp->errx(dbp, "line %lu: unexpected format", G(lineno));
 		ret = 1;
 	}
 	if (name != NULL) {
-		*p = '=';
+		if (p != NULL)
+			*p = '=';
 		free(name);
 	}
 	return (ret);
@@ -882,7 +980,7 @@ convprintable(dbenv, instr, outstrp)
 	 * Just malloc a string big enough for the whole input string;
 	 * the output string will be smaller (or of equal length).
 	 */
-	if ((outstr = (char *)malloc(strlen(instr))) == NULL)
+	if ((outstr = malloc(strlen(instr) + 1)) == NULL)
 		return (ENOMEM);
 
 	*outstrp = outstr;
@@ -974,7 +1072,7 @@ dbt_rprint(dbenv, dbtp)
 		if (len >= dbtp->ulen - 10) {
 			dbtp->ulen *= 2;
 			if ((dbtp->data =
-			    (void *)realloc(dbtp->data, dbtp->ulen)) == NULL) {
+			    realloc(dbtp->data, dbtp->ulen)) == NULL) {
 				dbenv->err(dbenv, ENOMEM, NULL);
 				return (1);
 			}
@@ -1039,7 +1137,7 @@ dbt_rdump(dbenv, dbtp)
 		if (len >= dbtp->ulen - 10) {
 			dbtp->ulen *= 2;
 			if ((dbtp->data =
-			    (void *)realloc(dbtp->data, dbtp->ulen)) == NULL) {
+			    realloc(dbtp->data, dbtp->ulen)) == NULL) {
 				dbenv->err(dbenv, ENOMEM, NULL);
 				return (1);
 			}
@@ -1066,6 +1164,7 @@ dbt_rrecno(dbenv, dbtp, ishex)
 	int ishex;
 {
 	char buf[32], *p, *q;
+	u_long recno;
 
 	++G(lineno);
 
@@ -1104,16 +1203,30 @@ dbt_rrecno(dbenv, dbtp, ishex)
 		*p = '\0';
 	}
 
-	if (__db_getulong(NULL,
-	    G(progname), buf + 1, 0, 0, (u_long *)dbtp->data)) {
+	if (__db_getulong(dbenv, G(progname), buf + 1, 0, 0, &recno)) {
 bad:		badend(dbenv);
 		return (1);
 	}
 
+	*((db_recno_t *)dbtp->data) = recno;
 	dbtp->size = sizeof(db_recno_t);
 	return (0);
 }
 
+int
+dbt_to_recno(dbenv, dbt, recnop)
+	DB_ENV *dbenv;
+	DBT *dbt;
+	db_recno_t *recnop;
+{
+	char buf[32];				/* Large enough for 2^64. */
+
+	memcpy(buf, dbt->data, dbt->size);
+	buf[dbt->size] = '\0';
+
+	return (__db_getulong(dbenv, G(progname), buf, 0, 0, (u_long *)recnop));
+}
+
 /*
  * digitize --
  *	Convert a character to an integer.
@@ -1140,6 +1253,8 @@ digitize(dbenv, c, errorp)
 	case 'd': return (13);
 	case 'e': return (14);
 	case 'f': return (15);
+	default:			/* Not possible. */
+		break;
 	}
 
 	dbenv->errx(dbenv, "unexpected hexadecimal value");
@@ -1181,6 +1296,8 @@ usage()
 	(void)fprintf(stderr, "%s\n\t%s\n",
 	    "usage: db_load [-nTV] [-c name=value] [-f file]",
     "[-h home] [-P password] [-t btree | hash | recno | queue] db_file");
+	(void)fprintf(stderr, "%s\n",
+	    "usage: db_load -r lsn | fileid [-h home] [-P password] db_file");
 	return (EXIT_FAILURE);
 }
 
@@ -1192,41 +1309,12 @@ version_check(progname)
 
 	/* Make sure we're loaded with the right version of the DB library. */
 	(void)db_version(&v_major, &v_minor, &v_patch);
-	if (v_major != DB_VERSION_MAJOR ||
-	    v_minor != DB_VERSION_MINOR || v_patch != DB_VERSION_PATCH) {
+	if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) {
 		fprintf(stderr,
-	"%s: version %d.%d.%d doesn't match library version %d.%d.%d\n",
+	"%s: version %d.%d doesn't match library version %d.%d\n",
 		    progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
-		    DB_VERSION_PATCH, v_major, v_minor, v_patch);
+		    v_major, v_minor);
 		return (EXIT_FAILURE);
 	}
 	return (0);
 }
-
-int
-env_create(dbenvp, ldg)
-	DB_ENV **dbenvp;
-	LDG *ldg;
-{
-	DB_ENV *dbenv;
-	int ret;
-
-	if ((ret = db_env_create(dbenvp, 0)) != 0) {
-		fprintf(stderr,
-		    "%s: db_env_create: %s\n", ldg->progname, db_strerror(ret));
-		return (ret);
-	}
-	dbenv = *dbenvp;
-	dbenv->set_errfile(dbenv, stderr);
-	dbenv->set_errpfx(dbenv, ldg->progname);
-	if (ldg->passwd != NULL && (ret = dbenv->set_encrypt(dbenv,
-	    ldg->passwd, DB_ENCRYPT_AES)) != 0) {
-		dbenv->err(dbenv, ret, "set_passwd");
-		return (ret);
-	}
-	if ((ret = db_init(dbenv, ldg->home, ldg->cache, &ldg->private)) != 0)
-		return (ret);
-	dbenv->app_private = ldg;
-
-	return (0);
-}
diff --git a/storage/bdb/db_printlog/README b/storage/bdb/db_printlog/README
index d59f4c77f555d09a165f2c0049415c8eca0e554e..d625964296c127ce9cb3ed53ac36edc2c9426085 100644
--- a/storage/bdb/db_printlog/README
+++ b/storage/bdb/db_printlog/README
@@ -1,4 +1,4 @@
-# $Id: README,v 10.6 2002/06/20 14:52:54 bostic Exp $
+# $Id: README,v 10.7 2004/09/24 00:43:16 bostic Exp $
 
 Berkeley DB log dump utility.  This utility dumps out a DB log in human
 readable form, a record at a time, to assist in recovery and transaction
@@ -28,7 +28,7 @@ rectype.awk     Print out a range of the log -- command line should
 		rectypes (or partial strings of rectypes) sought.
 
 status.awk	Read through db_printlog output and list the transactions
-		encountered, and whether they commited or aborted.
+		encountered, and whether they committed or aborted.
 
 txn.awk		Print out all the records for a comma-separated list of
 		transaction IDs.
diff --git a/storage/bdb/db_printlog/db_printlog.c b/storage/bdb/db_printlog/db_printlog.c
index af6d00d593a32d107a82a3dbe5b824d2463cb1c4..d06477160a84b45366af023e2143ea8fbc1b6df3 100644
--- a/storage/bdb/db_printlog/db_printlog.c
+++ b/storage/bdb/db_printlog/db_printlog.c
@@ -1,17 +1,17 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_printlog.c,v 11.64 2004/06/17 17:35:17 bostic Exp $
  */
 
 #include "db_config.h"
 
 #ifndef lint
 static const char copyright[] =
-    "Copyright (c) 1996-2002\nSleepycat Software Inc.  All rights reserved.\n";
-static const char revid[] =
-    "$Id: db_printlog.c,v 11.52 2002/08/08 03:50:38 bostic Exp $";
+    "Copyright (c) 1996-2004\nSleepycat Software Inc.  All rights reserved.\n";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -31,14 +31,14 @@ static const char revid[] =
 #include "dbinc/hash.h"
 #include "dbinc/log.h"
 #include "dbinc/qam.h"
-#include "dbinc/rep.h"
 #include "dbinc/txn.h"
 
+int lsn_arg __P((const char *, char *, DB_LSN *));
 int main __P((int, char *[]));
+int open_rep_db __P((DB_ENV *, DB **, DBC **));
+int print_app_record __P((DB_ENV *, DBT *, DB_LSN *, db_recops));
 int usage __P((void));
 int version_check __P((const char *));
-int print_app_record __P((DB_ENV *, DBT *, DB_LSN *, db_recops));
-int open_rep_db __P((DB_ENV *, DB **, DBC **));
 
 int
 main(argc, argv)
@@ -50,13 +50,14 @@ main(argc, argv)
 	const char *progname = "db_printlog";
 	DB *dbp;
 	DBC *dbc;
+	DBT data, keydbt;
 	DB_ENV	*dbenv;
 	DB_LOGC *logc;
-	int (**dtab) __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+	DB_LSN key, start, stop;
 	size_t dtabsize;
-	DBT data, keydbt;
-	DB_LSN key;
-	int ch, e_close, exitval, nflag, rflag, ret, repflag;
+	u_int32_t logcflag;
+	int ch, cmp, exitval, nflag, rflag, ret, repflag;
+	int (**dtab) __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
 	char *home, *passwd;
 
 	if ((ret = version_check(progname)) != 0)
@@ -64,13 +65,25 @@ main(argc, argv)
 
 	dbp = NULL;
 	dbc = NULL;
+	dbenv = NULL;
 	logc = NULL;
-	e_close = exitval = nflag = rflag = repflag = 0;
-	home = passwd = NULL;
+	ZERO_LSN(start);
+	ZERO_LSN(stop);
 	dtabsize = 0;
+	exitval = nflag = rflag = repflag = 0;
 	dtab = NULL;
-	while ((ch = getopt(argc, argv, "h:NP:rRV")) != EOF)
+	home = passwd = NULL;
+
+	while ((ch = getopt(argc, argv, "b:e:h:NP:rRV")) != EOF)
 		switch (ch) {
+		case 'b':
+			if (lsn_arg(progname, optarg, &start))
+				return (usage());
+			break;
+		case 'e':
+			if (lsn_arg(progname, optarg, &stop))
+				return (usage());
+			break;
 		case 'h':
 			home = optarg;
 			break;
@@ -89,7 +102,7 @@ main(argc, argv)
 		case 'r':
 			rflag = 1;
 			break;
-		case 'R':
+		case 'R':		/* Undocumented */
 			repflag = 1;
 			break;
 		case 'V':
@@ -117,7 +130,6 @@ main(argc, argv)
 		    "%s: db_env_create: %s\n", progname, db_strerror(ret));
 		goto shutdown;
 	}
-	e_close = 1;
 
 	dbenv->set_errfile(dbenv, stderr);
 	dbenv->set_errpfx(dbenv, progname);
@@ -158,28 +170,34 @@ main(argc, argv)
 	if (repflag) {
 		if ((ret = dbenv->open(dbenv, home,
 		    DB_INIT_MPOOL | DB_USE_ENVIRON, 0)) != 0 &&
+		    (ret == DB_VERSION_MISMATCH ||
 		    (ret = dbenv->open(dbenv, home,
 		    DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON, 0))
-		    != 0) {
-			dbenv->err(dbenv, ret, "open");
+		    != 0)) {
+			dbenv->err(dbenv, ret, "DB_ENV->open");
 			goto shutdown;
 		}
 	} else if ((ret = dbenv->open(dbenv, home,
 	    DB_JOINENV | DB_USE_ENVIRON, 0)) != 0 &&
+	    (ret == DB_VERSION_MISMATCH ||
 	    (ret = dbenv->open(dbenv, home,
-	    DB_CREATE | DB_INIT_LOG | DB_PRIVATE | DB_USE_ENVIRON, 0)) != 0) {
-		dbenv->err(dbenv, ret, "open");
+	    DB_CREATE | DB_INIT_LOG | DB_PRIVATE | DB_USE_ENVIRON, 0)) != 0)) {
+		dbenv->err(dbenv, ret, "DB_ENV->open");
 		goto shutdown;
 	}
 
 	/* Initialize print callbacks. */
 	if ((ret = __bam_init_print(dbenv, &dtab, &dtabsize)) != 0 ||
-	    (ret = __dbreg_init_print(dbenv, &dtab, &dtabsize)) != 0 ||
 	    (ret = __crdel_init_print(dbenv, &dtab, &dtabsize)) != 0 ||
 	    (ret = __db_init_print(dbenv, &dtab, &dtabsize)) != 0 ||
+	    (ret = __dbreg_init_print(dbenv, &dtab, &dtabsize)) != 0 ||
 	    (ret = __fop_init_print(dbenv, &dtab, &dtabsize)) != 0 ||
-	    (ret = __qam_init_print(dbenv, &dtab, &dtabsize)) != 0 ||
+#ifdef HAVE_HASH
 	    (ret = __ham_init_print(dbenv, &dtab, &dtabsize)) != 0 ||
+#endif
+#ifdef HAVE_QUEUE
+	    (ret = __qam_init_print(dbenv, &dtab, &dtabsize)) != 0 ||
+#endif
 	    (ret = __txn_init_print(dbenv, &dtab, &dtabsize)) != 0) {
 		dbenv->err(dbenv, ret, "callback: initialization");
 		goto shutdown;
@@ -194,17 +212,22 @@ main(argc, argv)
 		goto shutdown;
 	}
 
+	if (IS_ZERO_LSN(start)) {
+		memset(&keydbt, 0, sizeof(keydbt));
+		logcflag = rflag ? DB_PREV : DB_NEXT;
+	} else {
+		key = start;
+		logcflag = DB_SET;
+	}
 	memset(&data, 0, sizeof(data));
-	memset(&keydbt, 0, sizeof(keydbt));
-	while (!__db_util_interrupted()) {
+
+	for (; !__db_util_interrupted(); logcflag = rflag ? DB_PREV : DB_NEXT) {
 		if (repflag) {
-			ret = dbc->c_get(dbc,
-			    &keydbt, &data, rflag ? DB_PREV : DB_NEXT);
+			ret = dbc->c_get(dbc, &keydbt, &data, logcflag);
 			if (ret == 0)
 				key = ((REP_CONTROL *)keydbt.data)->lsn;
 		} else
-			ret = logc->get(logc,
-			    &key, &data, rflag ? DB_PREV : DB_NEXT);
+			ret = logc->get(logc, &key, &data, logcflag);
 		if (ret != 0) {
 			if (ret == DB_NOTFOUND)
 				break;
@@ -213,6 +236,15 @@ main(argc, argv)
 			goto shutdown;
 		}
 
+		/*
+		 * We may have reached the end of the range we're displaying.
+		 */
+		if (!IS_ZERO_LSN(stop)) {
+			cmp = log_compare(&key, &stop);
+			if ((rflag && cmp < 0) || (!rflag && cmp > 0))
+				break;
+		}
+
 		ret = __db_dispatch(dbenv,
 		    dtab, dtabsize, &data, &key, DB_TXN_PRINT, NULL);
 
@@ -247,12 +279,15 @@ shutdown:	exitval = 1;
 	 */
 	if (dtab != NULL)
 		__os_free(dbenv, dtab);
-	if (e_close && (ret = dbenv->close(dbenv, 0)) != 0) {
+	if (dbenv != NULL && (ret = dbenv->close(dbenv, 0)) != 0) {
 		exitval = 1;
 		fprintf(stderr,
 		    "%s: dbenv->close: %s\n", progname, db_strerror(ret));
 	}
 
+	if (passwd != NULL)
+		free(passwd);
+
 	/* Resend any caught signal. */
 	__db_util_sigresend();
 
@@ -262,8 +297,8 @@ shutdown:	exitval = 1;
 int
 usage()
 {
-	fprintf(stderr, "%s\n",
-	    "usage: db_printlog [-NrV] [-h home] [-P password]");
+	fprintf(stderr, "usage: db_printlog %s\n",
+	    "[-NrV] [-b file/offset] [-e file/offset] [-h home] [-P password]");
 	return (EXIT_FAILURE);
 }
 
@@ -275,12 +310,11 @@ version_check(progname)
 
 	/* Make sure we're loaded with the right version of the DB library. */
 	(void)db_version(&v_major, &v_minor, &v_patch);
-	if (v_major != DB_VERSION_MAJOR ||
-	    v_minor != DB_VERSION_MINOR || v_patch != DB_VERSION_PATCH) {
+	if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) {
 		fprintf(stderr,
-	"%s: version %d.%d.%d doesn't match library version %d.%d.%d\n",
+	"%s: version %d.%d doesn't match library version %d.%d\n",
 		    progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
-		    DB_VERSION_PATCH, v_major, v_minor, v_patch);
+		    v_major, v_minor);
 		return (EXIT_FAILURE);
 	}
 	return (0);
@@ -298,7 +332,9 @@ print_app_record(dbenv, dbt, lsnp, op)
 	u_int32_t i, rectype;
 
 	DB_ASSERT(op == DB_TXN_PRINT);
+
 	COMPQUIET(dbenv, NULL);
+	COMPQUIET(op, DB_TXN_PRINT);
 
 	/*
 	 * Fetch the rectype, which always must be at the beginning of the
@@ -358,3 +394,38 @@ err:	if (*dbpp != NULL)
 		(void)(*dbpp)->close(*dbpp, 0);
 	return (ret);
 }
+
+/*
+ * lsn_arg --
+ *	Parse a LSN argument.
+ */
+int
+lsn_arg(progname, optarg, lsnp)
+	const char *progname;
+	char *optarg;
+	DB_LSN *lsnp;
+{
+	char *p;
+	u_long uval;
+
+	/*
+	 * Expected format is: lsn.file/lsn.offset.
+	 *
+	 * Don't use getsubopt(3), some systems don't have it.
+	 */
+	if ((p = strchr(optarg, '/')) == NULL)
+		return (1);
+	*p = '\0';
+
+	if (__db_getulong(NULL, progname, optarg, 0, 0, &uval))
+		return (1);
+	if (uval > UINT32_MAX)
+		return (1);
+	lsnp->file = uval;
+	if (__db_getulong(NULL, progname, p + 1, 0, 0, &uval))
+		return (1);
+	if (uval > UINT32_MAX)
+		return (1);
+	lsnp->offset = uval;
+	return (0);
+}
diff --git a/storage/bdb/db_printlog/dbname.awk b/storage/bdb/db_printlog/dbname.awk
index 4795599457957074fe50cf399b103c8114b60f6c..41ef97a162d5a39e92f651d2d14e90cbb3ee3cf9 100644
--- a/storage/bdb/db_printlog/dbname.awk
+++ b/storage/bdb/db_printlog/dbname.awk
@@ -1,4 +1,4 @@
-# $Id: dbname.awk,v 1.5 2002/05/07 05:45:51 ubell Exp $
+# $Id: dbname.awk,v 1.7 2003/11/21 20:00:03 ubell Exp $
 #
 # Take a comma-separated list of database names and spit out all the
 # log records that affect those databases.
@@ -14,6 +14,7 @@ NR == 1 {
 	filenames[nfiles] = DBNAME 0;
 	files[nfiles] = -1
 	myfile = -1;
+	nreg = 0;
 }
 
 /^\[.*dbreg_register/ {
@@ -29,12 +30,12 @@ NR == 1 {
 }
 /name:/ {
 	if (register >= 2) {
+		myfile = -2;
 		for (i = 0; i <= nfiles; i++) {
 			if ($2 == filenames[i]) {
 				if (register == 2) {
 					printme = 0;
-					myfile = -1;
-					files[i] = -1;
+					myfile = -2;
 				} else {
 					myfile = i;
 				}
@@ -45,17 +46,18 @@ NR == 1 {
 	register = 0;
 }
 /fileid:/{
-	if (myfile != -1) {
-		files[myfile] = $2;
+	if (myfile == -2)
+		files[$2] = 0;
+	else if (myfile != -1) {
+		files[$2] = 1;
+		if ($2 > nreg)
+			nreg = $2;
 		printme = 1;
 		register = 0;
 		myfile = -1;
-	} else
-		for (i = 0; i <= nfiles; i++)
-			if ($2 == files[i]) {
-				printme = 1
-				break;
-			}
+	} else if ($2 <= nreg && files[$2] == 1) {
+		printme = 1
+	}
 }
 
 /^\[/{
diff --git a/storage/bdb/db_printlog/rectype.awk b/storage/bdb/db_printlog/rectype.awk
index 7f7b2f5ee15c563cc08fe950b960ede2030e781f..f30124cac432d52676040a92beca6a0d239a89dd 100644
--- a/storage/bdb/db_printlog/rectype.awk
+++ b/storage/bdb/db_printlog/rectype.awk
@@ -1,7 +1,7 @@
-# $Id: rectype.awk,v 11.3 2000/07/17 22:00:49 ubell Exp $
+# $Id: rectype.awk,v 11.4 2004/04/19 09:36:58 bostic Exp $
 #
-# Print out a range of the log
-# Command line should set RECTYPE to the a comma separated list
+# Print out a range of the log.
+# Command line should set RECTYPE to a comma separated list
 # of the rectypes (or partial strings of rectypes) sought.
 NR == 1 {
 	ntypes = 0
diff --git a/storage/bdb/db_printlog/status.awk b/storage/bdb/db_printlog/status.awk
index 13df0b6194a81b44fd98fd0f032ecc3ef21087fc..a0c381ed9e253bcc6af6172230eb1e6eac206778 100644
--- a/storage/bdb/db_printlog/status.awk
+++ b/storage/bdb/db_printlog/status.awk
@@ -1,10 +1,10 @@
-# $Id: status.awk,v 10.3 2002/04/11 01:35:24 margo Exp $
+# $Id: status.awk,v 10.5 2004/09/24 00:43:17 bostic Exp $
 #
 # Read through db_printlog output and list all the transactions encountered
-# and whether they commited or aborted.
+# and whether they committed or aborted.
 #
 # 1 = started
-# 2 = commited
+# 2 = committed
 # 3 = explicitly aborted
 # 4 = other
 BEGIN {
@@ -18,6 +18,10 @@ BEGIN {
 		cur_txn++;
 	}
 }
+/	child:/ {
+	txnid = substr($2, 3);
+	status[txnid] = 2;
+}
 /txn_regop/ {
 	txnid = $5
 	in_regop = 1
@@ -36,11 +40,11 @@ END {
 	for (i = 0; i < cur_txn; i++) {
 		if (status[txns[i]] == 1)
 			printf("%s\tABORT\n", txns[i]);
-		if (status[txns[i]] == 2)
+		else if (status[txns[i]] == 2)
 			printf("%s\tCOMMIT\n", txns[i]);
-		if (status[txns[i]] == 3)
+		else if (status[txns[i]] == 3)
 			printf("%s\tABORT\n", txns[i]);
-		if (status[txns[i]] == 4)
+		else if (status[txns[i]] == 4)
 			printf("%s\tOTHER\n", txns[i]);
 	}
 }
diff --git a/storage/bdb/db_recover/db_recover.c b/storage/bdb/db_recover/db_recover.c
index b6414267f936b0844e02889916fca75fc17b2926..75961f78c8634a66702504573738df1f988c4782 100644
--- a/storage/bdb/db_recover/db_recover.c
+++ b/storage/bdb/db_recover/db_recover.c
@@ -1,17 +1,17 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_recover.c,v 11.41 2004/01/28 03:36:00 bostic Exp $
  */
 
 #include "db_config.h"
 
 #ifndef lint
 static const char copyright[] =
-    "Copyright (c) 1996-2002\nSleepycat Software Inc.  All rights reserved.\n";
-static const char revid[] =
-    "$Id: db_recover.c,v 11.33 2002/03/28 20:13:42 bostic Exp $";
+    "Copyright (c) 1996-2004\nSleepycat Software Inc.  All rights reserved.\n";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -34,7 +34,6 @@ static const char revid[] =
 #endif
 
 #include "db_int.h"
-#include "dbinc/txn.h"
 
 int main __P((int, char *[]));
 int read_timestamp __P((const char *, char *, time_t *));
@@ -50,8 +49,7 @@ main(argc, argv)
 	extern int optind;
 	const char *progname = "db_recover";
 	DB_ENV	*dbenv;
-	DB_TXNREGION *region;
-	time_t now, timestamp;
+	time_t timestamp;
 	u_int32_t flags;
 	int ch, exitval, fatal_recover, ret, retain_env, verbose;
 	char *home, *passwd;
@@ -117,10 +115,8 @@ main(argc, argv)
 	}
 	dbenv->set_errfile(dbenv, stderr);
 	dbenv->set_errpfx(dbenv, progname);
-	if (verbose) {
+	if (verbose)
 		(void)dbenv->set_verbose(dbenv, DB_VERB_RECOVERY, 1);
-		(void)dbenv->set_verbose(dbenv, DB_VERB_CHKPOINT, 1);
-	}
 	if (timestamp &&
 	    (ret = dbenv->set_tx_timestamp(dbenv, &timestamp)) != 0) {
 		dbenv->err(dbenv, ret, "DB_ENV->set_timestamp");
@@ -155,16 +151,6 @@ main(argc, argv)
 		goto shutdown;
 	}
 
-	if (verbose) {
-		(void)time(&now);
-		region = ((DB_TXNMGR *)dbenv->tx_handle)->reginfo.primary;
-		dbenv->errx(dbenv, "Recovery complete at %.24s", ctime(&now));
-		dbenv->errx(dbenv, "%s %lx %s [%lu][%lu]",
-		    "Maximum transaction id", (u_long)region->last_txnid,
-		    "Recovery checkpoint", (u_long)region->last_ckp.file,
-		    (u_long)region->last_ckp.offset);
-	}
-
 	if (0) {
 shutdown:	exitval = 1;
 	}
@@ -175,6 +161,8 @@ shutdown:	exitval = 1;
 		fprintf(stderr,
 		    "%s: dbenv->close: %s\n", progname, db_strerror(ret));
 	}
+	if (passwd != NULL)
+		free(passwd);
 
 	/* Resend any caught signal. */
 	__db_util_sigresend();
@@ -243,7 +231,7 @@ read_timestamp(progname, arg, timep)
 	}
 
 	yearset = 0;
-	switch(strlen(arg)) {
+	switch (strlen(arg)) {
 	case 12:			/* CCYYMMDDhhmm */
 		t->tm_year = ATOI2(arg);
 		t->tm_year *= 100;
@@ -301,12 +289,11 @@ version_check(progname)
 
 	/* Make sure we're loaded with the right version of the DB library. */
 	(void)db_version(&v_major, &v_minor, &v_patch);
-	if (v_major != DB_VERSION_MAJOR ||
-	    v_minor != DB_VERSION_MINOR || v_patch != DB_VERSION_PATCH) {
+	if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) {
 		fprintf(stderr,
-	"%s: version %d.%d.%d doesn't match library version %d.%d.%d\n",
+	"%s: version %d.%d doesn't match library version %d.%d\n",
 		    progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
-		    DB_VERSION_PATCH, v_major, v_minor, v_patch);
+		    v_major, v_minor);
 		return (EXIT_FAILURE);
 	}
 	return (0);
diff --git a/storage/bdb/db_stat/db_stat.c b/storage/bdb/db_stat/db_stat.c
index a2b01b71e0ae128ae29cb9ec6e3690c1680ab0cd..aa1918655036cf3b9ac6da303736f68bbdbefe7e 100644
--- a/storage/bdb/db_stat/db_stat.c
+++ b/storage/bdb/db_stat/db_stat.c
@@ -1,17 +1,17 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_stat.c,v 11.158 2004/07/15 18:26:48 ubell Exp $
  */
 
 #include "db_config.h"
 
 #ifndef lint
 static const char copyright[] =
-    "Copyright (c) 1996-2002\nSleepycat Software Inc.  All rights reserved.\n";
-static const char revid[] =
-    "$Id: db_stat.c,v 11.125 2002/08/08 15:26:15 bostic Exp $";
+    "Copyright (c) 1996-2004\nSleepycat Software Inc.  All rights reserved.\n";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -36,30 +36,13 @@ static const char revid[] =
 
 #include "db_int.h"
 #include "dbinc/db_page.h"
-
-#define	PCT(f, t, pgsize)						\
-    ((t) == 0 ? 0 :							\
-    (((double)(((t) * (pgsize)) - (f)) / ((t) * (pgsize))) * 100))
+#include "dbinc/txn.h"
 
 typedef enum { T_NOTSET,
     T_DB, T_ENV, T_LOCK, T_LOG, T_MPOOL, T_REP, T_TXN } test_t;
 
-int	 argcheck __P((char *, const char *));
-int	 btree_stats __P((DB_ENV *, DB *, DB_BTREE_STAT *, int));
 int	 db_init __P((DB_ENV *, char *, test_t, u_int32_t, int *));
-void	 dl __P((const char *, u_long));
-void	 dl_bytes __P((const char *, u_long, u_long, u_long));
-int	 env_stats __P((DB_ENV *, u_int32_t));
-int	 hash_stats __P((DB_ENV *, DB *, int));
-int	 lock_stats __P((DB_ENV *, char *, u_int32_t));
-int	 log_stats __P((DB_ENV *, u_int32_t));
 int	 main __P((int, char *[]));
-int	 mpool_stats __P((DB_ENV *, char *, u_int32_t));
-void	 prflags __P((u_int32_t, const FN *));
-int	 queue_stats __P((DB_ENV *, DB *, int));
-int	 rep_stats __P((DB_ENV *, u_int32_t));
-int	 txn_compare __P((const void *, const void *));
-int	 txn_stats __P((DB_ENV *, u_int32_t));
 int	 usage __P((void));
 int	 version_check __P((const char *));
 
@@ -75,44 +58,65 @@ main(argc, argv)
 	DB_BTREE_STAT *sp;
 	DB *alt_dbp, *dbp;
 	test_t ttype;
-	u_int32_t cache;
-	int ch, checked, d_close, e_close, exitval, fast, flags;
+	u_int32_t cache, env_flags, fast, flags;
+	int ch, exitval;
 	int nflag, private, resize, ret;
-	char *db, *home, *internal, *passwd, *subdb;
+	char *db, *home, *p, *passwd, *subdb;
 
 	if ((ret = version_check(progname)) != 0)
 		return (ret);
 
+	dbenv = NULL;
 	dbp = NULL;
 	ttype = T_NOTSET;
 	cache = MEGABYTE;
-	d_close = e_close = exitval = fast = flags = nflag = private = 0;
-	db = home = internal = passwd = subdb = NULL;
+	exitval = fast = flags = nflag = private = 0;
+	db = home = passwd = subdb = NULL;
+	env_flags = 0;
 
-	while ((ch = getopt(argc, argv, "C:cd:efh:lM:mNP:rs:tVZ")) != EOF)
+	while ((ch = getopt(argc, argv, "C:cd:Eefh:L:lM:mNP:R:rs:tVZ")) != EOF)
 		switch (ch) {
-		case 'C':
-			if (ttype != T_NOTSET)
-				goto argcombo;
-			ttype = T_LOCK;
-			if (!argcheck(internal = optarg, "Aclmop"))
-				return (usage());
-			break;
-		case 'c':
-			if (ttype != T_NOTSET)
+		case 'C': case 'c':
+			if (ttype != T_NOTSET && ttype != T_LOCK)
 				goto argcombo;
 			ttype = T_LOCK;
+			if (ch != 'c')
+				for (p = optarg; *p; ++p)
+					switch (*p) {
+					case 'A':
+						LF_SET(DB_STAT_ALL);
+						break;
+					case 'c':
+						LF_SET(DB_STAT_LOCK_CONF);
+						break;
+					case 'l':
+						LF_SET(DB_STAT_LOCK_LOCKERS);
+						break;
+					case 'm': /* Backward compatible. */
+						break;
+					case 'o':
+						LF_SET(DB_STAT_LOCK_OBJECTS);
+						break;
+					case 'p':
+						LF_SET(DB_STAT_LOCK_PARAMS);
+						break;
+					default:
+						return (usage());
+					}
 			break;
 		case 'd':
-			if (ttype != T_DB && ttype != T_NOTSET)
+			if (ttype != T_NOTSET && ttype != T_DB)
 				goto argcombo;
 			ttype = T_DB;
 			db = optarg;
 			break;
-		case 'e':
-			if (ttype != T_NOTSET)
+		case 'E': case 'e':
+			if (ttype != T_NOTSET && ttype != T_ENV)
 				goto argcombo;
 			ttype = T_ENV;
+			LF_SET(DB_STAT_SUBSYSTEM);
+			if (ch == 'E')
+				LF_SET(DB_STAT_ALL);
 			break;
 		case 'f':
 			fast = DB_FAST_STAT;
@@ -120,22 +124,38 @@ main(argc, argv)
 		case 'h':
 			home = optarg;
 			break;
-		case 'l':
-			if (ttype != T_NOTSET)
+		case 'L': case 'l':
+			if (ttype != T_NOTSET && ttype != T_LOG)
 				goto argcombo;
 			ttype = T_LOG;
+			if (ch != 'l')
+				for (p = optarg; *p; ++p)
+					switch (*p) {
+					case 'A':
+						LF_SET(DB_STAT_ALL);
+						break;
+					default:
+						return (usage());
+					}
 			break;
-		case 'M':
-			if (ttype != T_NOTSET)
-				goto argcombo;
-			ttype = T_MPOOL;
-			if (!argcheck(internal = optarg, "Ahm"))
-				return (usage());
-			break;
-		case 'm':
-			if (ttype != T_NOTSET)
+		case 'M': case 'm':
+			if (ttype != T_NOTSET && ttype != T_MPOOL)
 				goto argcombo;
 			ttype = T_MPOOL;
+			if (ch != 'm')
+				for (p = optarg; *p; ++p)
+					switch (*p) {
+					case 'A':
+						LF_SET(DB_STAT_ALL);
+						break;
+					case 'h':
+						LF_SET(DB_STAT_MEMP_HASH);
+						break;
+					case 'm': /* Backward compatible. */
+						break;
+					default:
+						return (usage());
+					}
 			break;
 		case 'N':
 			nflag = 1;
@@ -149,13 +169,22 @@ main(argc, argv)
 				return (EXIT_FAILURE);
 			}
 			break;
-		case 'r':
-			if (ttype != T_NOTSET)
+		case 'R': case 'r':
+			if (ttype != T_NOTSET && ttype != T_REP)
 				goto argcombo;
 			ttype = T_REP;
+			if (ch != 'r')
+				for (p = optarg; *p; ++p)
+					switch (*p) {
+					case 'A':
+						LF_SET(DB_STAT_ALL);
+						break;
+					default:
+						return (usage());
+					}
 			break;
 		case 's':
-			if (ttype != T_DB && ttype != T_NOTSET)
+			if (ttype != T_NOTSET && ttype != T_DB)
 				goto argcombo;
 			ttype = T_DB;
 			subdb = optarg;
@@ -173,7 +202,7 @@ argcombo:			fprintf(stderr,
 			printf("%s\n", db_version(NULL, NULL, NULL));
 			return (EXIT_SUCCESS);
 		case 'Z':
-			flags |= DB_STAT_CLEAR;
+			LF_SET(DB_STAT_CLEAR);
 			break;
 		case '?':
 		default:
@@ -190,7 +219,12 @@ argcombo:			fprintf(stderr,
 	case T_NOTSET:
 		return (usage());
 		/* NOTREACHED */
-	default:
+	case T_ENV:
+	case T_LOCK:
+	case T_LOG:
+	case T_MPOOL:
+	case T_REP:
+	case T_TXN:
 		if (fast != 0)
 			return (usage());
 		break;
@@ -203,12 +237,11 @@ argcombo:			fprintf(stderr,
 	 * Create an environment object and initialize it for error
 	 * reporting.
 	 */
-retry:	if ((ret = db_env_create(&dbenv, 0)) != 0) {
+retry:	if ((ret = db_env_create(&dbenv, env_flags)) != 0) {
 		fprintf(stderr,
 		    "%s: db_env_create: %s\n", progname, db_strerror(ret));
-		goto shutdown;
+		goto err;
 	}
-	e_close = 1;
 
 	dbenv->set_errfile(dbenv, stderr);
 	dbenv->set_errpfx(dbenv, progname);
@@ -216,52 +249,51 @@ retry:	if ((ret = db_env_create(&dbenv, 0)) != 0) {
 	if (nflag) {
 		if ((ret = dbenv->set_flags(dbenv, DB_NOLOCKING, 1)) != 0) {
 			dbenv->err(dbenv, ret, "set_flags: DB_NOLOCKING");
-			goto shutdown;
+			goto err;
 		}
 		if ((ret = dbenv->set_flags(dbenv, DB_NOPANIC, 1)) != 0) {
 			dbenv->err(dbenv, ret, "set_flags: DB_NOPANIC");
-			goto shutdown;
+			goto err;
 		}
 	}
 
 	if (passwd != NULL &&
 	    (ret = dbenv->set_encrypt(dbenv, passwd, DB_ENCRYPT_AES)) != 0) {
 		dbenv->err(dbenv, ret, "set_passwd");
-		goto shutdown;
+		goto err;
 	}
 
 	/* Initialize the environment. */
 	if (db_init(dbenv, home, ttype, cache, &private) != 0)
-		goto shutdown;
+		goto err;
 
 	switch (ttype) {
 	case T_DB:
-		/* Create the DB object and open the file. */
 		if (flags != 0)
 			return (usage());
+
+		/* Create the DB object and open the file. */
 		if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
 			dbenv->err(dbenv, ret, "db_create");
-			goto shutdown;
+			goto err;
 		}
-		d_close = 1;
 
 		if ((ret = dbp->open(dbp,
 		    NULL, db, subdb, DB_UNKNOWN, DB_RDONLY, 0)) != 0) {
-			dbp->err(dbp, ret, "DB->open: %s", db);
-			goto shutdown;
+			dbenv->err(dbenv, ret, "DB->open: %s", db);
+			goto err;
 		}
 
 		/* Check if cache is too small for this DB's pagesize. */
 		if (private) {
-			if ((ret =
-			    __db_util_cache(dbenv, dbp, &cache, &resize)) != 0)
-				goto shutdown;
+			if ((ret = __db_util_cache(dbp, &cache, &resize)) != 0)
+				goto err;
 			if (resize) {
-				(void)dbp->close(dbp, 0);
-				d_close = 0;
+				(void)dbp->close(dbp, DB_NOSYNC);
+				dbp = NULL;
 
 				(void)dbenv->close(dbenv, 0);
-				e_close = 0;
+				dbenv = NULL;
 				goto retry;
 			}
 		}
@@ -271,13 +303,10 @@ retry:	if ((ret = db_env_create(&dbenv, 0)) != 0) {
 		 * If its a master-db then we cannot.  So check to see,
 		 * if its btree then it might be.
 		 */
-		checked = 0;
-		if (subdb == NULL && dbp->type == DB_BTREE) {
-			if ((ret = dbp->stat(dbp, &sp, DB_FAST_STAT)) != 0) {
-				dbp->err(dbp, ret, "DB->stat");
-				goto shutdown;
-			}
-			checked = 1;
+		if (subdb == NULL && dbp->type == DB_BTREE &&
+		    (ret = dbp->stat(dbp, NULL, &sp, DB_FAST_STAT)) != 0) {
+			dbenv->err(dbenv, ret, "DB->stat");
+			goto err;
 		}
 
 		if (subdb != NULL ||
@@ -285,881 +314,78 @@ retry:	if ((ret = db_env_create(&dbenv, 0)) != 0) {
 		    (sp->bt_metaflags & BTM_SUBDB) == 0) {
 			if ((ret = db_create(&alt_dbp, dbenv, 0)) != 0) {
 				dbenv->err(dbenv, ret, "db_create");
-				goto shutdown;
+				goto err;
 			}
 			if ((ret = dbp->open(alt_dbp, NULL,
-			    db, subdb, DB_UNKNOWN, 0, 0)) != 0) {
-				dbenv->err(dbenv,
-				   ret, "DB->open: %s:%s", db, subdb);
-				(void)alt_dbp->close(alt_dbp, 0);
-				goto shutdown;
+			    db, subdb, DB_UNKNOWN, DB_RDONLY, 0)) != 0) {
+				if (subdb == NULL)
+					dbenv->err(dbenv,
+					   ret, "DB->open: %s", db);
+				else
+					dbenv->err(dbenv,
+					   ret, "DB->open: %s:%s", db, subdb);
+				(void)alt_dbp->close(alt_dbp, DB_NOSYNC);
+				goto err;
 			}
 
-			(void)dbp->close(dbp, 0);
+			(void)dbp->close(dbp, DB_NOSYNC);
 			dbp = alt_dbp;
-
-			/* Need to run again to update counts */
-			checked = 0;
 		}
 
-		switch (dbp->type) {
-		case DB_BTREE:
-		case DB_RECNO:
-			if (btree_stats(
-			    dbenv, dbp, checked == 1 ? sp : NULL, fast))
-				goto shutdown;
-			break;
-		case DB_HASH:
-			if (hash_stats(dbenv, dbp, fast))
-				goto shutdown;
-			break;
-		case DB_QUEUE:
-			if (queue_stats(dbenv, dbp, fast))
-				goto shutdown;
-			break;
-		case DB_UNKNOWN:
-			dbenv->errx(dbenv, "Unknown database type.");
-			goto shutdown;
-		}
+		if (dbp->stat_print(dbp, flags))
+			goto err;
 		break;
 	case T_ENV:
-		if (env_stats(dbenv, flags))
-			goto shutdown;
+		if (dbenv->stat_print(dbenv, flags))
+			goto err;
 		break;
 	case T_LOCK:
-		if (lock_stats(dbenv, internal, flags))
-			goto shutdown;
+		if (dbenv->lock_stat_print(dbenv, flags))
+			goto err;
 		break;
 	case T_LOG:
-		if (log_stats(dbenv, flags))
-			goto shutdown;
+		if (dbenv->log_stat_print(dbenv, flags))
+			goto err;
 		break;
 	case T_MPOOL:
-		if (mpool_stats(dbenv, internal, flags))
-			goto shutdown;
+		if (dbenv->memp_stat_print(dbenv, flags))
+			goto err;
 		break;
 	case T_REP:
-		if (rep_stats(dbenv, flags))
-			goto shutdown;
+		if (dbenv->rep_stat_print(dbenv, flags))
+			goto err;
 		break;
 	case T_TXN:
-		if (txn_stats(dbenv, flags))
-			goto shutdown;
+		if (dbenv->txn_stat_print(dbenv, flags))
+			goto err;
 		break;
 	case T_NOTSET:
-		dbenv->errx(dbenv, "Unknown statistics flag.");
-		goto shutdown;
+		dbenv->errx(dbenv, "Unknown statistics flag");
+		goto err;
 	}
 
 	if (0) {
-shutdown:	exitval = 1;
+err:		exitval = 1;
 	}
-	if (d_close && (ret = dbp->close(dbp, 0)) != 0) {
+	if (dbp != NULL && (ret = dbp->close(dbp, DB_NOSYNC)) != 0) {
 		exitval = 1;
 		dbenv->err(dbenv, ret, "close");
 	}
-	if (e_close && (ret = dbenv->close(dbenv, 0)) != 0) {
+	if (dbenv != NULL && (ret = dbenv->close(dbenv, 0)) != 0) {
 		exitval = 1;
 		fprintf(stderr,
 		    "%s: dbenv->close: %s\n", progname, db_strerror(ret));
 	}
 
+	if (passwd != NULL)
+		free(passwd);
+
 	/* Resend any caught signal. */
 	__db_util_sigresend();
 
 	return (exitval == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
 }
 
-/*
- * env_stats --
- *	Display environment statistics.
- */
-int
-env_stats(dbenv, flags)
-	DB_ENV *dbenv;
-	u_int32_t flags;
-{
-	REGENV renv;
-	REGION *rp, regs[1024];
-	int n, ret;
-	const char *lable;
-
-	n = sizeof(regs) / sizeof(regs[0]);
-	if ((ret = __db_e_stat(dbenv, &renv, regs, &n, flags)) != 0)  {
-		dbenv->err(dbenv, ret, "__db_e_stat");
-		return (1);
-	}
-
-	printf("%d.%d.%d\tEnvironment version.\n",
-	    renv.majver, renv.minver, renv.patch);
-	printf("%lx\tMagic number.\n", (u_long)renv.magic);
-	printf("%d\tPanic value.\n", renv.envpanic);
-
-	/* Adjust the reference count for us... */
-	printf("%d\tReferences.\n", renv.refcnt - 1);
-
-	dl("Locks granted without waiting.\n",
-	    (u_long)renv.mutex.mutex_set_nowait);
-	dl("Locks granted after waiting.\n",
-	    (u_long)renv.mutex.mutex_set_wait);
-
-	while (n > 0) {
-		printf("%s\n", DB_LINE);
-		rp = &regs[--n];
-		switch (rp->type) {
-		case REGION_TYPE_ENV:
-			lable = "Environment";
-			break;
-		case REGION_TYPE_LOCK:
-			lable = "Lock";
-			break;
-		case REGION_TYPE_LOG:
-			lable = "Log";
-			break;
-		case REGION_TYPE_MPOOL:
-			lable = "Mpool";
-			break;
-		case REGION_TYPE_MUTEX:
-			lable = "Mutex";
-			break;
-		case REGION_TYPE_TXN:
-			lable = "Txn";
-			break;
-		case INVALID_REGION_TYPE:
-		default:
-			lable = "Invalid";
-			break;
-		}
-		printf("%s Region: %d.\n", lable, rp->id);
-		dl_bytes("Size", (u_long)0, (u_long)0, (u_long)rp->size);
-		printf("%ld\tSegment ID.\n", rp->segid);
-		dl("Locks granted without waiting.\n",
-		    (u_long)rp->mutex.mutex_set_nowait);
-		dl("Locks granted after waiting.\n",
-		    (u_long)rp->mutex.mutex_set_wait);
-	}
-
-	return (0);
-}
-
-/*
- * btree_stats --
- *	Display btree/recno statistics.
- */
-int
-btree_stats(dbenv, dbp, msp, fast)
-	DB_ENV *dbenv;
-	DB *dbp;
-	DB_BTREE_STAT *msp;
-	int fast;
-{
-	static const FN fn[] = {
-		{ BTM_DUP,	"duplicates" },
-		{ BTM_FIXEDLEN,	"fixed-length" },
-		{ BTM_RECNO,	"recno" },
-		{ BTM_RECNUM,	"record-numbers" },
-		{ BTM_RENUMBER,	"renumber" },
-		{ BTM_SUBDB,	"multiple-databases" },
-		{ 0,		NULL }
-	};
-	DB_BTREE_STAT *sp;
-	int ret;
-
-	COMPQUIET(dbenv, NULL);
-
-	if (msp != NULL)
-		sp = msp;
-	else if ((ret = dbp->stat(dbp, &sp, fast)) != 0) {
-		dbp->err(dbp, ret, "DB->stat");
-		return (1);
-	}
-
-	printf("%lx\tBtree magic number.\n", (u_long)sp->bt_magic);
-	printf("%lu\tBtree version number.\n", (u_long)sp->bt_version);
-	prflags(sp->bt_metaflags, fn);
-	if (dbp->type == DB_BTREE) {
-#ifdef NOT_IMPLEMENTED
-		dl("Maximum keys per-page.\n", (u_long)sp->bt_maxkey);
-#endif
-		dl("Minimum keys per-page.\n", (u_long)sp->bt_minkey);
-	}
-	if (dbp->type == DB_RECNO) {
-		dl("Fixed-length record size.\n", (u_long)sp->bt_re_len);
-		if (isprint(sp->bt_re_pad) && !isspace(sp->bt_re_pad))
-			printf("%c\tFixed-length record pad.\n",
-			    (int)sp->bt_re_pad);
-		else
-			printf("0x%x\tFixed-length record pad.\n",
-			    (int)sp->bt_re_pad);
-	}
-	dl("Underlying database page size.\n", (u_long)sp->bt_pagesize);
-	dl("Number of levels in the tree.\n", (u_long)sp->bt_levels);
-	dl(dbp->type == DB_BTREE ?
-	    "Number of unique keys in the tree.\n" :
-	    "Number of records in the tree.\n", (u_long)sp->bt_nkeys);
-	dl("Number of data items in the tree.\n", (u_long)sp->bt_ndata);
-
-	dl("Number of tree internal pages.\n", (u_long)sp->bt_int_pg);
-	dl("Number of bytes free in tree internal pages",
-	    (u_long)sp->bt_int_pgfree);
-	printf(" (%.0f%% ff).\n",
-	    PCT(sp->bt_int_pgfree, sp->bt_int_pg, sp->bt_pagesize));
-
-	dl("Number of tree leaf pages.\n", (u_long)sp->bt_leaf_pg);
-	dl("Number of bytes free in tree leaf pages",
-	    (u_long)sp->bt_leaf_pgfree);
-	printf(" (%.0f%% ff).\n",
-	    PCT(sp->bt_leaf_pgfree, sp->bt_leaf_pg, sp->bt_pagesize));
-
-	dl("Number of tree duplicate pages.\n", (u_long)sp->bt_dup_pg);
-	dl("Number of bytes free in tree duplicate pages",
-	    (u_long)sp->bt_dup_pgfree);
-	printf(" (%.0f%% ff).\n",
-	    PCT(sp->bt_dup_pgfree, sp->bt_dup_pg, sp->bt_pagesize));
-
-	dl("Number of tree overflow pages.\n", (u_long)sp->bt_over_pg);
-	dl("Number of bytes free in tree overflow pages",
-	    (u_long)sp->bt_over_pgfree);
-	printf(" (%.0f%% ff).\n",
-	    PCT(sp->bt_over_pgfree, sp->bt_over_pg, sp->bt_pagesize));
-
-	dl("Number of pages on the free list.\n", (u_long)sp->bt_free);
-
-	free(sp);
-
-	return (0);
-}
-
-/*
- * hash_stats --
- *	Display hash statistics.
- */
-int
-hash_stats(dbenv, dbp, fast)
-	DB_ENV *dbenv;
-	DB *dbp;
-	int fast;
-{
-	static const FN fn[] = {
-		{ DB_HASH_DUP,	"duplicates" },
-		{ DB_HASH_SUBDB,"multiple-databases" },
-		{ 0,		NULL }
-	};
-	DB_HASH_STAT *sp;
-	int ret;
-
-	COMPQUIET(dbenv, NULL);
-
-	if ((ret = dbp->stat(dbp, &sp, fast)) != 0) {
-		dbp->err(dbp, ret, "DB->stat");
-		return (1);
-	}
-
-	printf("%lx\tHash magic number.\n", (u_long)sp->hash_magic);
-	printf("%lu\tHash version number.\n", (u_long)sp->hash_version);
-	prflags(sp->hash_metaflags, fn);
-	dl("Underlying database page size.\n", (u_long)sp->hash_pagesize);
-	dl("Specified fill factor.\n", (u_long)sp->hash_ffactor);
-	dl("Number of keys in the database.\n", (u_long)sp->hash_nkeys);
-	dl("Number of data items in the database.\n", (u_long)sp->hash_ndata);
-
-	dl("Number of hash buckets.\n", (u_long)sp->hash_buckets);
-	dl("Number of bytes free on bucket pages", (u_long)sp->hash_bfree);
-	printf(" (%.0f%% ff).\n",
-	    PCT(sp->hash_bfree, sp->hash_buckets, sp->hash_pagesize));
-
-	dl("Number of overflow pages.\n", (u_long)sp->hash_bigpages);
-	dl("Number of bytes free in overflow pages",
-	    (u_long)sp->hash_big_bfree);
-	printf(" (%.0f%% ff).\n",
-	    PCT(sp->hash_big_bfree, sp->hash_bigpages, sp->hash_pagesize));
-
-	dl("Number of bucket overflow pages.\n", (u_long)sp->hash_overflows);
-	dl("Number of bytes free in bucket overflow pages",
-	    (u_long)sp->hash_ovfl_free);
-	printf(" (%.0f%% ff).\n",
-	    PCT(sp->hash_ovfl_free, sp->hash_overflows, sp->hash_pagesize));
-
-	dl("Number of duplicate pages.\n", (u_long)sp->hash_dup);
-	dl("Number of bytes free in duplicate pages",
-	    (u_long)sp->hash_dup_free);
-	printf(" (%.0f%% ff).\n",
-	    PCT(sp->hash_dup_free, sp->hash_dup, sp->hash_pagesize));
-
-	dl("Number of pages on the free list.\n", (u_long)sp->hash_free);
-
-	free(sp);
-
-	return (0);
-}
-
-/*
- * queue_stats --
- *	Display queue statistics.
- */
-int
-queue_stats(dbenv, dbp, fast)
-	DB_ENV *dbenv;
-	DB *dbp;
-	int fast;
-{
-	DB_QUEUE_STAT *sp;
-	int ret;
-
-	COMPQUIET(dbenv, NULL);
-
-	if ((ret = dbp->stat(dbp, &sp, fast)) != 0) {
-		dbp->err(dbp, ret, "DB->stat");
-		return (1);
-	}
-
-	printf("%lx\tQueue magic number.\n", (u_long)sp->qs_magic);
-	printf("%lu\tQueue version number.\n", (u_long)sp->qs_version);
-	dl("Fixed-length record size.\n", (u_long)sp->qs_re_len);
-	if (isprint(sp->qs_re_pad) && !isspace(sp->qs_re_pad))
-		printf("%c\tFixed-length record pad.\n", (int)sp->qs_re_pad);
-	else
-		printf("0x%x\tFixed-length record pad.\n", (int)sp->qs_re_pad);
-	dl("Underlying database page size.\n", (u_long)sp->qs_pagesize);
-	if (sp->qs_extentsize != 0)
-		dl("Underlying database extent size.\n",
-		    (u_long)sp->qs_extentsize);
-	dl("Number of records in the database.\n", (u_long)sp->qs_nkeys);
-	dl("Number of database pages.\n", (u_long)sp->qs_pages);
-	dl("Number of bytes free in database pages", (u_long)sp->qs_pgfree);
-	printf(" (%.0f%% ff).\n",
-	    PCT(sp->qs_pgfree, sp->qs_pages, sp->qs_pagesize));
-	printf("%lu\tFirst undeleted record.\n", (u_long)sp->qs_first_recno);
-	printf(
-	    "%lu\tNext available record number.\n", (u_long)sp->qs_cur_recno);
-
-	free(sp);
-
-	return (0);
-}
-
-/*
- * lock_stats --
- *	Display lock statistics.
- */
-int
-lock_stats(dbenv, internal, flags)
-	DB_ENV *dbenv;
-	char *internal;
-	u_int32_t flags;
-{
-	DB_LOCK_STAT *sp;
-	int ret;
-
-	if (internal != NULL) {
-		if ((ret =
-		    dbenv->lock_dump_region(dbenv, internal, stdout)) != 0) {
-			dbenv->err(dbenv, ret, NULL);
-			return (1);
-		}
-		return (0);
-	}
-
-	if ((ret = dbenv->lock_stat(dbenv, &sp, flags)) != 0) {
-		dbenv->err(dbenv, ret, NULL);
-		return (1);
-	}
-
-	dl("Last allocated locker ID.\n", (u_long)sp->st_id);
-	dl("Current maximum unused locker ID.\n", (u_long)sp->st_cur_maxid);
-	dl("Number of lock modes.\n", (u_long)sp->st_nmodes);
-	dl("Maximum number of locks possible.\n", (u_long)sp->st_maxlocks);
-	dl("Maximum number of lockers possible.\n", (u_long)sp->st_maxlockers);
-	dl("Maximum number of lock objects possible.\n",
-	    (u_long)sp->st_maxobjects);
-	dl("Number of current locks.\n", (u_long)sp->st_nlocks);
-	dl("Maximum number of locks at any one time.\n",
-	    (u_long)sp->st_maxnlocks);
-	dl("Number of current lockers.\n", (u_long)sp->st_nlockers);
-	dl("Maximum number of lockers at any one time.\n",
-	    (u_long)sp->st_maxnlockers);
-	dl("Number of current lock objects.\n", (u_long)sp->st_nobjects);
-	dl("Maximum number of lock objects at any one time.\n",
-	    (u_long)sp->st_maxnobjects);
-	dl("Total number of locks requested.\n", (u_long)sp->st_nrequests);
-	dl("Total number of locks released.\n", (u_long)sp->st_nreleases);
-	dl(
-  "Total number of lock requests failing because DB_LOCK_NOWAIT was set.\n",
-	    (u_long)sp->st_nnowaits);
-	dl(
-  "Total number of locks not immediately available due to conflicts.\n",
-	    (u_long)sp->st_nconflicts);
-	dl("Number of deadlocks.\n", (u_long)sp->st_ndeadlocks);
-	dl("Lock timeout value.\n", (u_long)sp->st_locktimeout);
-	dl("Number of locks that have timed out.\n",
-	    (u_long)sp->st_nlocktimeouts);
-	dl("Transaction timeout value.\n", (u_long)sp->st_txntimeout);
-	dl("Number of transactions that have timed out.\n",
-	    (u_long)sp->st_ntxntimeouts);
-
-	dl_bytes("The size of the lock region.",
-	    (u_long)0, (u_long)0, (u_long)sp->st_regsize);
-	dl("The number of region locks granted after waiting.\n",
-	    (u_long)sp->st_region_wait);
-	dl("The number of region locks granted without waiting.\n",
-	    (u_long)sp->st_region_nowait);
-
-	free(sp);
-
-	return (0);
-}
-
-/*
- * log_stats --
- *	Display log statistics.
- */
-int
-log_stats(dbenv, flags)
-	DB_ENV *dbenv;
-	u_int32_t flags;
-{
-	DB_LOG_STAT *sp;
-	int ret;
-
-	if ((ret = dbenv->log_stat(dbenv, &sp, flags)) != 0) {
-		dbenv->err(dbenv, ret, NULL);
-		return (1);
-	}
-
-	printf("%lx\tLog magic number.\n", (u_long)sp->st_magic);
-	printf("%lu\tLog version number.\n", (u_long)sp->st_version);
-	dl_bytes("Log record cache size",
-	    (u_long)0, (u_long)0, (u_long)sp->st_lg_bsize);
-	printf("%#o\tLog file mode.\n", sp->st_mode);
-	if (sp->st_lg_size % MEGABYTE == 0)
-		printf("%luMb\tCurrent log file size.\n",
-		    (u_long)sp->st_lg_size / MEGABYTE);
-	else if (sp->st_lg_size % 1024 == 0)
-		printf("%luKb\tCurrent log file size.\n",
-		    (u_long)sp->st_lg_size / 1024);
-	else
-		printf("%lu\tCurrent log file size.\n",
-		    (u_long)sp->st_lg_size);
-	dl_bytes("Log bytes written",
-	    (u_long)0, (u_long)sp->st_w_mbytes, (u_long)sp->st_w_bytes);
-	dl_bytes("Log bytes written since last checkpoint",
-	    (u_long)0, (u_long)sp->st_wc_mbytes, (u_long)sp->st_wc_bytes);
-	dl("Total log file writes.\n", (u_long)sp->st_wcount);
-	dl("Total log file write due to overflow.\n",
-	    (u_long)sp->st_wcount_fill);
-	dl("Total log file flushes.\n", (u_long)sp->st_scount);
-	printf("%lu\tCurrent log file number.\n", (u_long)sp->st_cur_file);
-	printf("%lu\tCurrent log file offset.\n", (u_long)sp->st_cur_offset);
-	printf("%lu\tOn-disk log file number.\n", (u_long)sp->st_disk_file);
-	printf("%lu\tOn-disk log file offset.\n", (u_long)sp->st_disk_offset);
-
-	dl("Max commits in a log flush.\n", (u_long)sp->st_maxcommitperflush);
-	dl("Min commits in a log flush.\n", (u_long)sp->st_mincommitperflush);
-
-	dl_bytes("Log region size",
-	    (u_long)0, (u_long)0, (u_long)sp->st_regsize);
-	dl("The number of region locks granted after waiting.\n",
-	    (u_long)sp->st_region_wait);
-	dl("The number of region locks granted without waiting.\n",
-	    (u_long)sp->st_region_nowait);
-
-	free(sp);
-
-	return (0);
-}
-
-/*
- * mpool_stats --
- *	Display mpool statistics.
- */
-int
-mpool_stats(dbenv, internal, flags)
-	DB_ENV *dbenv;
-	char *internal;
-	u_int32_t flags;
-{
-	DB_MPOOL_FSTAT **fsp;
-	DB_MPOOL_STAT *gsp;
-	int ret;
-
-	if (internal != NULL) {
-		if ((ret =
-		    dbenv->memp_dump_region(dbenv, internal, stdout)) != 0) {
-			dbenv->err(dbenv, ret, NULL);
-			return (1);
-		}
-		return (0);
-	}
-
-	if ((ret = dbenv->memp_stat(dbenv, &gsp, &fsp, flags)) != 0) {
-		dbenv->err(dbenv, ret, NULL);
-		return (1);
-	}
-
-	dl_bytes("Total cache size",
-	    (u_long)gsp->st_gbytes, (u_long)0, (u_long)gsp->st_bytes);
-	dl("Number of caches.\n", (u_long)gsp->st_ncache);
-	dl_bytes("Pool individual cache size",
-	    (u_long)0, (u_long)0, (u_long)gsp->st_regsize);
-	dl("Requested pages mapped into the process' address space.\n",
-	    (u_long)gsp->st_map);
-	dl("Requested pages found in the cache", (u_long)gsp->st_cache_hit);
-	if (gsp->st_cache_hit + gsp->st_cache_miss != 0)
-		printf(" (%.0f%%)", ((double)gsp->st_cache_hit /
-		    (gsp->st_cache_hit + gsp->st_cache_miss)) * 100);
-	printf(".\n");
-	dl("Requested pages not found in the cache.\n",
-	    (u_long)gsp->st_cache_miss);
-	dl("Pages created in the cache.\n", (u_long)gsp->st_page_create);
-	dl("Pages read into the cache.\n", (u_long)gsp->st_page_in);
-	dl("Pages written from the cache to the backing file.\n",
-	    (u_long)gsp->st_page_out);
-	dl("Clean pages forced from the cache.\n",
-	    (u_long)gsp->st_ro_evict);
-	dl("Dirty pages forced from the cache.\n",
-	    (u_long)gsp->st_rw_evict);
-	dl("Dirty pages written by trickle-sync thread.\n",
-	    (u_long)gsp->st_page_trickle);
-	dl("Current total page count.\n",
-	    (u_long)gsp->st_pages);
-	dl("Current clean page count.\n",
-	    (u_long)gsp->st_page_clean);
-	dl("Current dirty page count.\n",
-	    (u_long)gsp->st_page_dirty);
-	dl("Number of hash buckets used for page location.\n",
-	    (u_long)gsp->st_hash_buckets);
-	dl("Total number of times hash chains searched for a page.\n",
-	    (u_long)gsp->st_hash_searches);
-	dl("The longest hash chain searched for a page.\n",
-	    (u_long)gsp->st_hash_longest);
-	dl("Total number of hash buckets examined for page location.\n",
-	    (u_long)gsp->st_hash_examined);
-	dl("The number of hash bucket locks granted without waiting.\n",
-	    (u_long)gsp->st_hash_nowait);
-	dl("The number of hash bucket locks granted after waiting.\n",
-	    (u_long)gsp->st_hash_wait);
-	dl("The maximum number of times any hash bucket lock was waited for.\n",
-	    (u_long)gsp->st_hash_max_wait);
-	dl("The number of region locks granted without waiting.\n",
-	    (u_long)gsp->st_region_nowait);
-	dl("The number of region locks granted after waiting.\n",
-	    (u_long)gsp->st_region_wait);
-	dl("The number of page allocations.\n",
-	    (u_long)gsp->st_alloc);
-	dl("The number of hash buckets examined during allocations\n",
-	    (u_long)gsp->st_alloc_buckets);
-	dl("The max number of hash buckets examined for an allocation\n",
-	    (u_long)gsp->st_alloc_max_buckets);
-	dl("The number of pages examined during allocations\n",
-	    (u_long)gsp->st_alloc_pages);
-	dl("The max number of pages examined for an allocation\n",
-	    (u_long)gsp->st_alloc_max_pages);
-
-	for (; fsp != NULL && *fsp != NULL; ++fsp) {
-		printf("%s\n", DB_LINE);
-		printf("Pool File: %s\n", (*fsp)->file_name);
-		dl("Page size.\n", (u_long)(*fsp)->st_pagesize);
-		dl("Requested pages mapped into the process' address space.\n",
-		    (u_long)(*fsp)->st_map);
-		dl("Requested pages found in the cache",
-		    (u_long)(*fsp)->st_cache_hit);
-		if ((*fsp)->st_cache_hit + (*fsp)->st_cache_miss != 0)
-			printf(" (%.0f%%)", ((double)(*fsp)->st_cache_hit /
-			    ((*fsp)->st_cache_hit + (*fsp)->st_cache_miss)) *
-			    100);
-		printf(".\n");
-		dl("Requested pages not found in the cache.\n",
-		    (u_long)(*fsp)->st_cache_miss);
-		dl("Pages created in the cache.\n",
-		    (u_long)(*fsp)->st_page_create);
-		dl("Pages read into the cache.\n",
-		    (u_long)(*fsp)->st_page_in);
-		dl("Pages written from the cache to the backing file.\n",
-		    (u_long)(*fsp)->st_page_out);
-	}
-
-	free(gsp);
-
-	return (0);
-}
-
-/*
- * rep_stats --
- *	Display replication statistics.
- */
-int
-rep_stats(dbenv, flags)
-	DB_ENV *dbenv;
-	u_int32_t flags;
-{
-	DB_REP_STAT *sp;
-	int is_client, ret;
-	const char *p;
-
-	if ((ret = dbenv->rep_stat(dbenv, &sp, flags)) != 0) {
-		dbenv->err(dbenv, ret, NULL);
-		return (1);
-	}
-
-	is_client = 0;
-	switch (sp->st_status) {
-	case DB_REP_MASTER:
-		printf("Environment configured as a replication master.\n");
-		break;
-	case DB_REP_CLIENT:
-		printf("Environment configured as a replication client.\n");
-		is_client = 1;
-		break;
-	case DB_REP_LOGSONLY:
-		printf("Environment configured as a logs-only replica.\n");
-		is_client = 1;
-		break;
-	default:
-		printf("Environment not configured for replication.\n");
-		break;
-	}
-
-	printf("%lu/%lu\t%s\n",
-	    (u_long)sp->st_next_lsn.file, (u_long)sp->st_next_lsn.offset,
-	    is_client ? "Next LSN expected." : "Next LSN to be used.");
-	p = sp->st_waiting_lsn.file == 0 ?
-	    "Not waiting for any missed log records." :
-	    "LSN of first missed log record being waited for.";
-	printf("%lu/%lu\t%s\n",
-	    (u_long)sp->st_waiting_lsn.file, (u_long)sp->st_waiting_lsn.offset,
-	    p);
-
-	dl("Number of duplicate master conditions detected.\n",
-	    (u_long)sp->st_dupmasters);
-	if (sp->st_env_id != DB_EID_INVALID)
-		dl("Current environment ID.\n", (u_long)sp->st_env_id);
-	else
-		printf("No current environment ID.\n");
-	dl("Current environment priority.\n", (u_long)sp->st_env_priority);
-	dl("Current generation number.\n", (u_long)sp->st_gen);
-	dl("Number of duplicate log records received.\n",
-	    (u_long)sp->st_log_duplicated);
-	dl("Number of log records currently queued.\n",
-	    (u_long)sp->st_log_queued);
-	dl("Maximum number of log records ever queued at once.\n",
-	    (u_long)sp->st_log_queued_max);
-	dl("Total number of log records queued.\n",
-	    (u_long)sp->st_log_queued_total);
-	dl("Number of log records received and appended to the log.\n",
-	    (u_long)sp->st_log_records);
-	dl("Number of log records missed and requested.\n",
-	    (u_long)sp->st_log_requested);
-	if (sp->st_master != DB_EID_INVALID)
-		dl("Current master ID.\n", (u_long)sp->st_master);
-	else
-		printf("No current master ID.\n");
-	dl("Number of times the master has changed.\n",
-	    (u_long)sp->st_master_changes);
-	dl("Number of messages received with a bad generation number.\n",
-	    (u_long)sp->st_msgs_badgen);
-	dl("Number of messages received and processed.\n",
-	    (u_long)sp->st_msgs_processed);
-	dl("Number of messages ignored due to pending recovery.\n",
-	    (u_long)sp->st_msgs_recover);
-	dl("Number of failed message sends.\n",
-	    (u_long)sp->st_msgs_send_failures);
-	dl("Number of messages sent.\n", (u_long)sp->st_msgs_sent);
-	dl("Number of new site messages received.\n", (u_long)sp->st_newsites);
-	dl("Transmission limited.\n", (u_long)sp->st_nthrottles);
-	dl("Number of outdated conditions detected.\n",
-	    (u_long)sp->st_outdated);
-	dl("Number of transactions applied.\n", (u_long)sp->st_txns_applied);
-
-	dl("Number of elections held.\n", (u_long)sp->st_elections);
-	dl("Number of elections won.\n", (u_long)sp->st_elections_won);
-
-	if (sp->st_election_status == 0)
-		printf("No election in progress.\n");
-	else {
-		dl("Current election phase.\n", (u_long)sp->st_election_status);
-		dl("Election winner.\n",
-		    (u_long)sp->st_election_cur_winner);
-		dl("Election generation number.\n",
-		    (u_long)sp->st_election_gen);
-		printf("%lu/%lu\tMaximum LSN of election winner.\n",
-		    (u_long)sp->st_election_lsn.file,
-		    (u_long)sp->st_election_lsn.offset);
-		dl("Number of sites expected to participate in elections.\n",
-		    (u_long)sp->st_election_nsites);
-		dl("Election priority.\n", (u_long)sp->st_election_priority);
-		dl("Election tiebreaker value.\n",
-		    (u_long)sp->st_election_tiebreaker);
-		dl("Votes received this election round.\n",
-		    (u_long)sp->st_election_votes);
-	}
-
-	free(sp);
-
-	return (0);
-}
-
-/*
- * txn_stats --
- *	Display transaction statistics.
- */
-int
-txn_stats(dbenv, flags)
-	DB_ENV *dbenv;
-	u_int32_t flags;
-{
-	DB_TXN_STAT *sp;
-	u_int32_t i;
-	int ret;
-	const char *p;
-
-	if ((ret = dbenv->txn_stat(dbenv, &sp, flags)) != 0) {
-		dbenv->err(dbenv, ret, NULL);
-		return (1);
-	}
-
-	p = sp->st_last_ckp.file == 0 ?
-	    "No checkpoint LSN." : "File/offset for last checkpoint LSN.";
-	printf("%lu/%lu\t%s\n",
-	    (u_long)sp->st_last_ckp.file, (u_long)sp->st_last_ckp.offset, p);
-	if (sp->st_time_ckp == 0)
-		printf("0\tNo checkpoint timestamp.\n");
-	else
-		printf("%.24s\tCheckpoint timestamp.\n",
-		    ctime(&sp->st_time_ckp));
-	printf("%lx\tLast transaction ID allocated.\n",
-	    (u_long)sp->st_last_txnid);
-	dl("Maximum number of active transactions possible.\n",
-	    (u_long)sp->st_maxtxns);
-	dl("Active transactions.\n", (u_long)sp->st_nactive);
-	dl("Maximum active transactions.\n", (u_long)sp->st_maxnactive);
-	dl("Number of transactions begun.\n", (u_long)sp->st_nbegins);
-	dl("Number of transactions aborted.\n", (u_long)sp->st_naborts);
-	dl("Number of transactions committed.\n", (u_long)sp->st_ncommits);
-	dl("Number of transactions restored.\n", (u_long)sp->st_nrestores);
-
-	dl_bytes("Transaction region size",
-	    (u_long)0, (u_long)0, (u_long)sp->st_regsize);
-	dl("The number of region locks granted after waiting.\n",
-	    (u_long)sp->st_region_wait);
-	dl("The number of region locks granted without waiting.\n",
-	    (u_long)sp->st_region_nowait);
-
-	qsort(sp->st_txnarray,
-	    sp->st_nactive, sizeof(sp->st_txnarray[0]), txn_compare);
-	for (i = 0; i < sp->st_nactive; ++i) {
-		printf("\tid: %lx; begin LSN: file/offset %lu/%lu",
-		    (u_long)sp->st_txnarray[i].txnid,
-		    (u_long)sp->st_txnarray[i].lsn.file,
-		    (u_long)sp->st_txnarray[i].lsn.offset);
-		if (sp->st_txnarray[i].parentid == 0)
-			printf("\n");
-		else
-			printf(" parent: %lx\n",
-			    (u_long)sp->st_txnarray[i].parentid);
-	}
-
-	free(sp);
-
-	return (0);
-}
-
-int
-txn_compare(a1, b1)
-	const void *a1, *b1;
-{
-	const DB_TXN_ACTIVE *a, *b;
-
-	a = a1;
-	b = b1;
-
-	if (a->txnid > b->txnid)
-		return (1);
-	if (a->txnid < b->txnid)
-		return (-1);
-	return (0);
-}
-
-/*
- * dl --
- *	Display a big value.
- */
-void
-dl(msg, value)
-	const char *msg;
-	u_long value;
-{
-	/*
-	 * Two formats: if less than 10 million, display as the number, if
-	 * greater than 10 million display as ###M.
-	 */
-	if (value < 10000000)
-		printf("%lu\t%s", value, msg);
-	else
-		printf("%luM\t%s", value / 1000000, msg);
-}
-
-/*
- * dl_bytes --
- *	Display a big number of bytes.
- */
-void
-dl_bytes(msg, gbytes, mbytes, bytes)
-	const char *msg;
-	u_long gbytes, mbytes, bytes;
-{
-	const char *sep;
-
-	/* Normalize the values. */
-	while (bytes >= MEGABYTE) {
-		++mbytes;
-		bytes -= MEGABYTE;
-	}
-	while (mbytes >= GIGABYTE / MEGABYTE) {
-		++gbytes;
-		mbytes -= GIGABYTE / MEGABYTE;
-	}
-
-	sep = "";
-	if (gbytes > 0) {
-		printf("%luGB", gbytes);
-		sep = " ";
-	}
-	if (mbytes > 0) {
-		printf("%s%luMB", sep, mbytes);
-		sep = " ";
-	}
-	if (bytes >= 1024) {
-		printf("%s%luKB", sep, bytes / 1024);
-		bytes %= 1024;
-		sep = " ";
-	}
-	if (bytes > 0)
-		printf("%s%luB", sep, bytes);
-
-	printf("\t%s.\n", msg);
-}
-
-/*
- * prflags --
- *	Print out flag values.
- */
-void
-prflags(flags, fnp)
-	u_int32_t flags;
-	const FN *fnp;
-{
-	const char *sep;
-
-	sep = "\t";
-	printf("Flags:");
-	for (; fnp->mask != 0; ++fnp)
-		if (fnp->mask & flags) {
-			printf("%s%s", sep, fnp->name);
-			sep = ", ";
-		}
-	printf("\n");
-}
-
 /*
  * db_init --
  *	Initialize the environment.
@@ -1189,6 +415,8 @@ db_init(dbenv, home, ttype, cache, is_private)
 	if ((ret =
 	    dbenv->open(dbenv, home, DB_JOINENV | DB_USE_ENVIRON, 0)) == 0)
 		return (0);
+	if (ret == DB_VERSION_MISMATCH)
+		goto err;
 	if (ttype != T_DB && ttype != T_LOG) {
 		dbenv->err(dbenv, ret, "DB_ENV->open%s%s",
 		    home == NULL ? "" : ": ", home == NULL ? "" : home);
@@ -1215,35 +443,24 @@ db_init(dbenv, home, ttype, cache, is_private)
 		oflags |= DB_INIT_MPOOL;
 	if (ttype == T_LOG)
 		oflags |= DB_INIT_LOG;
+	if (ttype == T_REP)
+		oflags |= DB_INIT_REP;
 	if ((ret = dbenv->open(dbenv, home, oflags, 0)) == 0)
 		return (0);
 
 	/* An environment is required. */
-	dbenv->err(dbenv, ret, "open");
-	return (1);
-}
-
-/*
- * argcheck --
- *	Return if argument flags are okay.
- */
-int
-argcheck(arg, ok_args)
-	char *arg;
-	const char *ok_args;
-{
-	for (; *arg != '\0'; ++arg)
-		if (strchr(ok_args, *arg) == NULL)
-			return (0);
+err:	dbenv->err(dbenv, ret, "DB_ENV->open");
 	return (1);
 }
 
 int
 usage()
 {
-	fprintf(stderr, "%s\n\t%s\n",
-	    "usage: db_stat [-celmNrtVZ] [-C Aclmop]",
-	    "[-d file [-f] [-s database]] [-h home] [-M Ahlm] [-P password]");
+	fprintf(stderr, "usage: db_stat %s\n",
+	    "-d file [-fN] [-h home] [-P password] [-s database]");
+	fprintf(stderr, "usage: db_stat %s\n\t%s\n",
+	    "[-cEelmNrtVZ] [-C Aclop]",
+	    "[-h home] [-L A] [-M A] [-P password] [-R A]");
 	return (EXIT_FAILURE);
 }
 
@@ -1255,12 +472,11 @@ version_check(progname)
 
 	/* Make sure we're loaded with the right version of the DB library. */
 	(void)db_version(&v_major, &v_minor, &v_patch);
-	if (v_major != DB_VERSION_MAJOR ||
-	    v_minor != DB_VERSION_MINOR || v_patch != DB_VERSION_PATCH) {
+	if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) {
 		fprintf(stderr,
-	"%s: version %d.%d.%d doesn't match library version %d.%d.%d\n",
+	"%s: version %d.%d doesn't match library version %d.%d\n",
 		    progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
-		    DB_VERSION_PATCH, v_major, v_minor, v_patch);
+		    v_major, v_minor);
 		return (EXIT_FAILURE);
 	}
 	return (0);
diff --git a/storage/bdb/db_stat/dd.sh b/storage/bdb/db_stat/dd.sh
new file mode 100644
index 0000000000000000000000000000000000000000..d8bb7033f9802d77d72ce5b24a1ebb2134791438
--- /dev/null
+++ b/storage/bdb/db_stat/dd.sh
@@ -0,0 +1,79 @@
+#! /bin/sh
+#	$Id: dd.sh,v 1.3 2004/05/04 15:51:45 bostic Exp $
+#
+# Display environment's deadlocks based on "db_stat -Co" output.
+
+t1=__a
+t2=__b
+
+trap 'rm -f $t1 $t2; exit 0' 0 1 2 3 13 15
+
+if [ $# -ne 1 ]; then
+	echo "Usage: dd.sh [db_stat -Co output]"
+	exit 1
+fi
+
+if `egrep '\<WAIT\>.*\<page\>' $1 > /dev/null`; then
+	n=`egrep '\<WAIT\>.*\<page\>' $1 | wc -l | awk '{print $1}'`
+	echo "dd.sh: $1: $n page locks in a WAIT state."
+else
+	echo "dd.sh: $1: No page locks in a WAIT state found."
+	exit 1
+fi
+
+# Print out list of node wait states, and output cycles in the graph.
+egrep '\<WAIT\>.*\<page\>' $1 | awk '{print $1 " " $7}' |
+while read l p; do
+	p=`egrep "\<HELD\>.*\<page\>[	 ][	 ]*$p$" $1 | awk '{print $1}'`
+	echo "$l $p"
+done | tsort > /dev/null 2>$t1
+
+# Display the locks in a single cycle.
+display_one() {
+	if [ -s $1 ]; then
+		echo "Deadlock #$c ============"
+		c=`expr $c + 1`
+		cat $1 | sort -n +6
+		:> $1
+	fi
+}
+
+# Display the locks in all of the cycles.
+#
+# Requires tsort output some text before each list of nodes in the cycle,
+# and the actual node displayed on the line be the second (white-space)
+# separated item on the line.  For example:
+#
+#	tsort: cycle in data
+#	tsort: 8000177f
+#	tsort: 80001792
+#	tsort: 80001774
+#	tsort: cycle in data
+#	tsort: 80001776
+#	tsort: 80001793
+#	tsort: cycle in data
+#	tsort: 8000176a
+#	tsort: 8000178a
+#
+# XXX
+# Currently, db_stat doesn't display the implicit wait relationship between
+# parent and child transactions, where the parent won't release a lock until
+# the child commits/aborts.  This means the deadlock where parent holds a
+# lock, thread A waits on parent, child waits on thread A won't be shown.
+if [ -s $t1 ]; then
+	c=1
+	:>$t2
+	while read a b; do
+		case $b in
+		[0-9]*)
+			egrep $b $1 >> $t2;;
+		*)
+			display_one $t2;;
+		esac
+	done < $t1
+	display_one $t2
+else
+	echo 'No deadlocks found.'
+fi
+
+exit 0
diff --git a/storage/bdb/db_upgrade/db_upgrade.c b/storage/bdb/db_upgrade/db_upgrade.c
index f46b5eabc4e52cb8109be8451bf31ef30dd9c955..0f43be6ba770e229a512f5b9381d6c93d0a76245 100644
--- a/storage/bdb/db_upgrade/db_upgrade.c
+++ b/storage/bdb/db_upgrade/db_upgrade.c
@@ -1,17 +1,17 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_upgrade.c,v 1.37 2004/06/10 01:00:09 bostic Exp $
  */
 
 #include "db_config.h"
 
 #ifndef lint
 static const char copyright[] =
-    "Copyright (c) 1996-2002\nSleepycat Software Inc.  All rights reserved.\n";
-static const char revid[] =
-    "$Id: db_upgrade.c,v 1.31 2002/03/28 20:13:47 bostic Exp $";
+    "Copyright (c) 1996-2004\nSleepycat Software Inc.  All rights reserved.\n";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -40,7 +40,7 @@ main(argc, argv)
 	DB *dbp;
 	DB_ENV *dbenv;
 	u_int32_t flags;
-	int ch, e_close, exitval, nflag, ret, t_ret;
+	int ch, exitval, nflag, ret, t_ret;
 	char *home, *passwd;
 
 	if ((ret = version_check(progname)) != 0)
@@ -48,7 +48,7 @@ main(argc, argv)
 
 	dbenv = NULL;
 	flags = nflag = 0;
-	e_close = exitval = 0;
+	exitval = 0;
 	home = passwd = NULL;
 	while ((ch = getopt(argc, argv, "h:NP:sV")) != EOF)
 		switch (ch) {
@@ -95,7 +95,6 @@ main(argc, argv)
 		    progname, db_strerror(ret));
 		goto shutdown;
 	}
-	e_close = 1;
 
 	dbenv->set_errfile(dbenv, stderr);
 	dbenv->set_errpfx(dbenv, progname);
@@ -123,9 +122,11 @@ main(argc, argv)
 	 */
 	if ((ret = dbenv->open(dbenv,
 	    home, DB_JOINENV | DB_USE_ENVIRON, 0)) != 0 &&
+	    (ret == DB_VERSION_MISMATCH ||
 	    (ret = dbenv->open(dbenv, home,
-	    DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON, 0)) != 0) {
-		dbenv->err(dbenv, ret, "open");
+	    DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON,
+	    0)) != 0)) {
+		dbenv->err(dbenv, ret, "DB_ENV->open");
 		goto shutdown;
 	}
 
@@ -150,12 +151,15 @@ main(argc, argv)
 	if (0) {
 shutdown:	exitval = 1;
 	}
-	if (e_close && (ret = dbenv->close(dbenv, 0)) != 0) {
+	if (dbenv != NULL && (ret = dbenv->close(dbenv, 0)) != 0) {
 		exitval = 1;
 		fprintf(stderr,
 		    "%s: dbenv->close: %s\n", progname, db_strerror(ret));
 	}
 
+	if (passwd != NULL)
+		free(passwd);
+
 	/* Resend any caught signal. */
 	__db_util_sigresend();
 
@@ -178,12 +182,11 @@ version_check(progname)
 
 	/* Make sure we're loaded with the right version of the DB library. */
 	(void)db_version(&v_major, &v_minor, &v_patch);
-	if (v_major != DB_VERSION_MAJOR ||
-	    v_minor != DB_VERSION_MINOR || v_patch != DB_VERSION_PATCH) {
+	if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) {
 		fprintf(stderr,
-	"%s: version %d.%d.%d doesn't match library version %d.%d.%d\n",
+	"%s: version %d.%d doesn't match library version %d.%d\n",
 		    progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
-		    DB_VERSION_PATCH, v_major, v_minor, v_patch);
+		    v_major, v_minor);
 		return (EXIT_FAILURE);
 	}
 	return (0);
diff --git a/storage/bdb/db_verify/db_verify.c b/storage/bdb/db_verify/db_verify.c
index 8d63a20e7bce8042f9b02556e2afec5a4c470258..148ce1f8e43ce2ff20e47ba6dc51d9432d2bab07 100644
--- a/storage/bdb/db_verify/db_verify.c
+++ b/storage/bdb/db_verify/db_verify.c
@@ -1,17 +1,17 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_verify.c,v 1.49 2004/08/01 00:21:58 bostic Exp $
  */
 
 #include "db_config.h"
 
 #ifndef lint
 static const char copyright[] =
-    "Copyright (c) 1996-2002\nSleepycat Software Inc.  All rights reserved.\n";
-static const char revid[] =
-    "$Id: db_verify.c,v 1.38 2002/08/08 03:51:38 bostic Exp $";
+    "Copyright (c) 1996-2004\nSleepycat Software Inc.  All rights reserved.\n";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -39,19 +39,21 @@ main(argc, argv)
 	const char *progname = "db_verify";
 	DB *dbp, *dbp1;
 	DB_ENV *dbenv;
-	u_int32_t cache;
-	int ch, d_close, e_close, exitval, nflag, oflag, private;
-	int quiet, resize, ret, t_ret;
+	u_int32_t flags, cache;
+	int ch, exitval, nflag, private;
+	int quiet, resize, ret;
 	char *home, *passwd;
 
 	if ((ret = version_check(progname)) != 0)
 		return (ret);
 
 	dbenv = NULL;
+	dbp = NULL;
 	cache = MEGABYTE;
-	d_close = e_close = exitval = nflag = oflag = quiet = 0;
+	exitval = nflag = quiet = 0;
+	flags = 0;
 	home = passwd = NULL;
-	while ((ch = getopt(argc, argv, "h:NoP:qV")) != EOF)
+	while ((ch = getopt(argc, argv, "h:NoP:quV")) != EOF)
 		switch (ch) {
 		case 'h':
 			home = optarg;
@@ -69,11 +71,14 @@ main(argc, argv)
 			}
 			break;
 		case 'o':
-			oflag = 1;
+			LF_SET(DB_NOORDERCHK);
 			break;
 		case 'q':
 			quiet = 1;
 			break;
+		case 'u':			/* Undocumented. */
+			LF_SET(DB_UNREF);
+			break;
 		case 'V':
 			printf("%s\n", db_version(NULL, NULL, NULL));
 			return (EXIT_SUCCESS);
@@ -99,7 +104,6 @@ retry:	if ((ret = db_env_create(&dbenv, 0)) != 0) {
 		    "%s: db_env_create: %s\n", progname, db_strerror(ret));
 		goto shutdown;
 	}
-	e_close = 1;
 
 	if (!quiet) {
 		dbenv->set_errfile(dbenv, stderr);
@@ -130,14 +134,18 @@ retry:	if ((ret = db_env_create(&dbenv, 0)) != 0) {
 	private = 0;
 	if ((ret =
 	    dbenv->open(dbenv, home, DB_INIT_MPOOL | DB_USE_ENVIRON, 0)) != 0) {
-		if ((ret = dbenv->set_cachesize(dbenv, 0, cache, 1)) != 0) {
-			dbenv->err(dbenv, ret, "set_cachesize");
-			goto shutdown;
+		if (ret != DB_VERSION_MISMATCH) {
+			if ((ret =
+			    dbenv->set_cachesize(dbenv, 0, cache, 1)) != 0) {
+				dbenv->err(dbenv, ret, "set_cachesize");
+				goto shutdown;
+			}
+			private = 1;
+			ret = dbenv->open(dbenv, home, DB_CREATE |
+			    DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON, 0);
 		}
-		private = 1;
-		if ((ret = dbenv->open(dbenv, home,
-	    DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON, 0)) != 0) {
-			dbenv->err(dbenv, ret, "open");
+		if (ret != 0) {
+			dbenv->err(dbenv, ret, "DB_ENV->open");
 			goto shutdown;
 		}
 	}
@@ -147,11 +155,14 @@ retry:	if ((ret = db_env_create(&dbenv, 0)) != 0) {
 			dbenv->err(dbenv, ret, "%s: db_create", progname);
 			goto shutdown;
 		}
-		d_close = 1;
 
 		/*
 		 * We create a 2nd dbp to this database to get its pagesize
 		 * because the dbp we're using for verify cannot be opened.
+		 *
+		 * If the database is corrupted, we may not be able to open
+		 * it, of course.  In that case, just continue, using the
+		 * cache size we have.
 		 */
 		if (private) {
 			if ((ret = db_create(&dbp1, dbenv, 0)) != 0) {
@@ -160,12 +171,9 @@ retry:	if ((ret = db_env_create(&dbenv, 0)) != 0) {
 				goto shutdown;
 			}
 
-			if ((ret = dbp1->open(dbp1, NULL,
-			    argv[0], NULL, DB_UNKNOWN, DB_RDONLY, 0)) != 0) {
-				dbenv->err(dbenv, ret, "DB->open: %s", argv[0]);
-				(void)dbp1->close(dbp1, 0);
-				goto shutdown;
-			}
+			ret = dbp1->open(dbp1,
+			    NULL, argv[0], NULL, DB_UNKNOWN, DB_RDONLY, 0);
+
 			/*
 			 * If we get here, we can check the cache/page.
 			 * !!!
@@ -174,28 +182,24 @@ retry:	if ((ret = db_env_create(&dbenv, 0)) != 0) {
 			 * will still be working on the same argv when we
 			 * get back into the for-loop.
 			 */
-			ret = __db_util_cache(dbenv, dbp1, &cache, &resize);
-			(void)dbp1->close(dbp1, 0);
-			if (ret != 0)
-				goto shutdown;
-
-			if (resize) {
-				(void)dbp->close(dbp, 0);
-				d_close = 0;
-
-				(void)dbenv->close(dbenv, 0);
-				e_close = 0;
-				goto retry;
+			if (ret == 0) {
+				if (__db_util_cache(
+				    dbp1, &cache, &resize) == 0 && resize) {
+					(void)dbp1->close(dbp1, 0);
+					(void)dbp->close(dbp, 0);
+					dbp = NULL;
+
+					(void)dbenv->close(dbenv, 0);
+					dbenv = NULL;
+					goto retry;
+				}
 			}
+			(void)dbp1->close(dbp1, 0);
 		}
-		if ((ret = dbp->verify(dbp,
-		    argv[0], NULL, NULL, oflag ? DB_NOORDERCHK : 0)) != 0)
-			dbp->err(dbp, ret, "DB->verify: %s", argv[0]);
-		if ((t_ret = dbp->close(dbp, 0)) != 0 && ret == 0) {
-			dbenv->err(dbenv, ret, "DB->close: %s", argv[0]);
-			ret = t_ret;
-		}
-		d_close = 0;
+
+		/* The verify method is a destructor. */
+		ret = dbp->verify(dbp, argv[0], NULL, NULL, flags);
+		dbp = NULL;
 		if (ret != 0)
 			goto shutdown;
 	}
@@ -204,16 +208,19 @@ retry:	if ((ret = db_env_create(&dbenv, 0)) != 0) {
 shutdown:	exitval = 1;
 	}
 
-	if (d_close && (ret = dbp->close(dbp, 0)) != 0) {
+	if (dbp != NULL && (ret = dbp->close(dbp, 0)) != 0) {
 		exitval = 1;
 		dbenv->err(dbenv, ret, "close");
 	}
-	if (e_close && (ret = dbenv->close(dbenv, 0)) != 0) {
+	if (dbenv != NULL && (ret = dbenv->close(dbenv, 0)) != 0) {
 		exitval = 1;
 		fprintf(stderr,
 		    "%s: dbenv->close: %s\n", progname, db_strerror(ret));
 	}
 
+	if (passwd != NULL)
+		free(passwd);
+
 	/* Resend any caught signal. */
 	__db_util_sigresend();
 
@@ -236,12 +243,11 @@ version_check(progname)
 
 	/* Make sure we're loaded with the right version of the DB library. */
 	(void)db_version(&v_major, &v_minor, &v_patch);
-	if (v_major != DB_VERSION_MAJOR ||
-	    v_minor != DB_VERSION_MINOR || v_patch != DB_VERSION_PATCH) {
+	if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) {
 		fprintf(stderr,
-	"%s: version %d.%d.%d doesn't match library version %d.%d.%d\n",
+	"%s: version %d.%d doesn't match library version %d.%d\n",
 		    progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
-		    DB_VERSION_PATCH, v_major, v_minor, v_patch);
+		    v_major, v_minor);
 		return (EXIT_FAILURE);
 	}
 	return (0);
diff --git a/storage/bdb/dbinc/btree.h b/storage/bdb/dbinc/btree.h
index 54da9c5b2080905cb854bd658259bc6e07582ff3..d6bb2c839e170d5b9c5e37caa08c741147c87fa1 100644
--- a/storage/bdb/dbinc/btree.h
+++ b/storage/bdb/dbinc/btree.h
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -39,7 +39,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: btree.h,v 11.45 2002/08/06 06:11:21 bostic Exp $
+ * $Id: btree.h,v 11.50 2004/07/22 21:52:57 bostic Exp $
  */
 #ifndef	_DB_BTREE_H_
 #define	_DB_BTREE_H_
@@ -146,12 +146,12 @@ struct __epg {
 #define	BT_STK_CLR(c) do {						\
 	(c)->csp = (c)->sp;						\
 	(c)->csp->page = NULL;						\
-	LOCK_INIT((c)->csp->lock);				\
+	LOCK_INIT((c)->csp->lock);					\
 } while (0)
 
 #define	BT_STK_ENTER(dbenv, c, pagep, page_indx, l, mode, ret) do {	\
-	if ((ret =							\
-	    (c)->csp == (c)->esp ? __bam_stkgrow(dbenv, c) : 0) == 0) {	\
+	if ((ret = ((c)->csp == (c)->esp ?				\
+	    __bam_stkgrow(dbenv, c) : 0)) == 0) {			\
 		(c)->csp->page = pagep;					\
 		(c)->csp->indx = page_indx;				\
 		(c)->csp->entries = NUM_ENT(pagep);			\
@@ -171,7 +171,7 @@ struct __epg {
 		(c)->csp->page = NULL;					\
 		(c)->csp->indx = page_indx;				\
 		(c)->csp->entries = NUM_ENT(pagep);			\
-		LOCK_INIT((c)->csp->lock);			\
+		LOCK_INIT((c)->csp->lock);				\
 		(c)->csp->lock_mode = DB_LOCK_NG;			\
 	}								\
 } while (0)
@@ -237,7 +237,7 @@ struct __cursor {
  */
 #define	B_MINKEY_TO_OVFLSIZE(dbp, minkey, pgsize)			\
 	((u_int16_t)(((pgsize) - P_OVERHEAD(dbp)) / ((minkey) * P_INDX) -\
-	    (BKEYDATA_PSIZE(0) + ALIGN(1, sizeof(int32_t)))))
+	    (BKEYDATA_PSIZE(0) + DB_ALIGN(1, sizeof(int32_t)))))
 
 /*
  * The maximum space that a single item can ever take up on one page.
@@ -281,6 +281,7 @@ struct __btree {			/* Btree access method. */
 	 * of its information.
 	 */
 	db_pgno_t bt_lpgno;		/* Last insert location. */
+	DB_LSN	  bt_llsn;		/* Last insert LSN. */
 
 	/*
 	 * !!!
diff --git a/storage/bdb/dbinc/crypto.h b/storage/bdb/dbinc/crypto.h
index 92fad098a4ab2471ef54fee04c10a312c800bb8e..8eeebf81b28c637590c0bfdbb70ed4dfdebacad9 100644
--- a/storage/bdb/dbinc/crypto.h
+++ b/storage/bdb/dbinc/crypto.h
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: crypto.h,v 1.9 2002/08/06 06:37:07 bostic Exp $
+ * $Id: crypto.h,v 1.12 2004/01/28 03:36:00 bostic Exp $
  */
 
 #ifndef	_DB_CRYPTO_H_
@@ -33,7 +33,7 @@
  * This structure is per-process, not in shared memory.
  */
 struct __db_cipher {
-	int	(*adj_size) __P((size_t));
+	u_int	(*adj_size) __P((size_t));
 	int	(*close) __P((DB_ENV *, void *));
 	int	(*decrypt) __P((DB_ENV *, void *, void *, u_int8_t *, size_t));
 	int	(*encrypt) __P((DB_ENV *, void *, void *, u_int8_t *, size_t));
diff --git a/storage/bdb/dbinc/cxx_int.h b/storage/bdb/dbinc/cxx_int.h
index 9af3979d9f155942c41a00fd0dc7d15a96b9c2db..d71ca25d034f694bec2d4b958877d0b10053b507 100644
--- a/storage/bdb/dbinc/cxx_int.h
+++ b/storage/bdb/dbinc/cxx_int.h
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: cxx_int.h,v 11.20 2002/01/11 15:52:23 bostic Exp $
+ * $Id: cxx_int.h,v 11.25 2004/09/22 22:20:31 mjc Exp $
  */
 
 #ifndef _CXX_INT_H_
@@ -30,27 +30,23 @@
 									   \
 	class _IMP_CLASS {};                                               \
 									   \
-	inline _WRAPPED_TYPE unwrap(_WRAPPER_CLASS *val)                   \
+	inline _WRAPPED_TYPE *unwrap(_WRAPPER_CLASS *val)                  \
 	{                                                                  \
 		if (!val) return (0);                                      \
-		return ((_WRAPPED_TYPE)((void *)(val->imp())));            \
+		return (val->get_##_WRAPPED_TYPE());                       \
 	}                                                                  \
 									   \
-	inline const _WRAPPED_TYPE unwrapConst(const _WRAPPER_CLASS *val)  \
+	inline const _WRAPPED_TYPE *unwrapConst(const _WRAPPER_CLASS *val) \
 	{                                                                  \
 		if (!val) return (0);                                      \
-		return ((const _WRAPPED_TYPE)((void *)(val->constimp()))); \
-	}                                                                  \
-									   \
-	inline _IMP_CLASS *wrap(_WRAPPED_TYPE val)                         \
-	{                                                                  \
-		return ((_IMP_CLASS*)((void *)val));                       \
+		return (val->get_const_##_WRAPPED_TYPE());                 \
 	}
 
-WRAPPED_CLASS(DbMpoolFile, DbMpoolFileImp, DB_MPOOLFILE*)
-WRAPPED_CLASS(Db, DbImp, DB*)
-WRAPPED_CLASS(DbEnv, DbEnvImp, DB_ENV*)
-WRAPPED_CLASS(DbTxn, DbTxnImp, DB_TXN*)
+WRAPPED_CLASS(Db, DbImp, DB)
+WRAPPED_CLASS(DbEnv, DbEnvImp, DB_ENV)
+WRAPPED_CLASS(DbMpoolFile, DbMpoolFileImp, DB_MPOOLFILE)
+WRAPPED_CLASS(DbSequence, DbSequenceImp, DB_SEQUENCE)
+WRAPPED_CLASS(DbTxn, DbTxnImp, DB_TXN)
 
 // A tristate integer value used by the DB_ERROR macro below.
 // We chose not to make this an enumerated type so it can
@@ -66,11 +62,11 @@ WRAPPED_CLASS(DbTxn, DbTxnImp, DB_TXN*)
 // the tristate values given above.  If UNKNOWN is specified,
 // the behavior is taken from the last initialized DbEnv.
 //
-#define	DB_ERROR(caller, ecode, policy) \
-    DbEnv::runtime_error(caller, ecode, policy)
+#define	DB_ERROR(env, caller, ecode, policy) \
+    DbEnv::runtime_error(env, caller, ecode, policy)
 
-#define	DB_ERROR_DBT(caller, dbt, policy) \
-    DbEnv::runtime_error_dbt(caller, dbt, policy)
+#define	DB_ERROR_DBT(env, caller, dbt, policy) \
+    DbEnv::runtime_error_dbt(env, caller, dbt, policy)
 
 #define	DB_OVERFLOWED_DBT(dbt) \
 	(F_ISSET(dbt, DB_DBT_USERMEM) && dbt->size > dbt->ulen)
diff --git a/storage/bdb/dbinc/db.in b/storage/bdb/dbinc/db.in
index 208de3bd622af8b563f94121297917df19dbde31..e8e17236c7c873fa39314b86c01acb872fae9c15 100644
--- a/storage/bdb/dbinc/db.in
+++ b/storage/bdb/dbinc/db.in
@@ -1,10 +1,10 @@
 /*
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: db.in,v 11.323 2002/09/03 17:27:16 bostic Exp $
+ * $Id: db.in,v 11.463 2004/10/11 18:47:50 bostic Exp $
  *
  * db.h include file layout:
  *	General.
@@ -23,7 +23,9 @@
 
 #ifndef __NO_SYSTEM_INCLUDES
 #include <sys/types.h>
-
+@inttypes_h_decl@
+@stdint_h_decl@
+@stddef_h_decl@
 #include <stdio.h>
 #endif
 
@@ -31,24 +33,9 @@
 extern "C" {
 #endif
 
-/*
- * XXX
- * Handle function prototypes and the keyword "const".  This steps on name
- * space that DB doesn't control, but all of the other solutions are worse.
- *
- * XXX
- * While Microsoft's compiler is ANSI C compliant, it doesn't have _STDC_
- * defined by default, you specify a command line flag or #pragma to turn
- * it on.  Don't do that, however, because some of Microsoft's own header
- * files won't compile.
- */
-#undef	__P
-#if defined(__STDC__) || defined(__cplusplus) || defined(_MSC_VER)
-#define	__P(protos)	protos		/* ANSI C prototypes */
-#else
-#define	const
-#define	__P(protos)	()		/* K&R C preprocessor */
-#endif
+@DB_CONST@
+@DB_PROTO1@
+@DB_PROTO2@
 
 /*
  * Berkeley DB version information.
@@ -78,6 +65,8 @@ extern "C" {
 @u_int16_decl@
 @int32_decl@
 @u_int32_decl@
+@int64_decl@
+@u_int64_decl@
 #endif
 
 @u_char_decl@
@@ -86,6 +75,32 @@ extern "C" {
 @u_long_decl@
 @ssize_t_decl@
 
+/*
+ * uintmax_t --
+ * Largest unsigned type, used to align structures in memory.  We don't store
+ * floating point types in structures, so integral types should be sufficient
+ * (and we don't have to worry about systems that store floats in other than
+ * power-of-2 numbers of bytes).  Additionally this fixes compilers that rewrite
+ * structure assignments and ANSI C memcpy calls to be in-line instructions
+ * that happen to require alignment.  Note: this alignment isn't sufficient for
+ * mutexes, which depend on things like cache line alignment.  Mutex alignment
+ * is handled separately, in mutex.h.
+ *
+ * uintptr_t --
+ * Unsigned type that's the same size as a pointer.  There are places where
+ * DB modifies pointers by discarding the bottom bits to guarantee alignment.
+ * We can't use uintmax_t, it may be larger than the pointer, and compilers
+ * get upset about that.  So far we haven't run on any machine where there's
+ * no unsigned type the same size as a pointer -- here's hoping.
+ */
+@uintmax_t_decl@
+@uintptr_t_decl@
+
+/*
+ * Sequences are only available on machines with 64-bit integral types.
+ */
+@db_seq_decl@
+
 /* Basic types that are exported or quasi-exported. */
 typedef	u_int32_t	db_pgno_t;	/* Page number type. */
 typedef	u_int16_t	db_indx_t;	/* Page offset type. */
@@ -97,11 +112,13 @@ typedef	u_int32_t	db_recno_t;	/* Record number type. */
 typedef u_int32_t	db_timeout_t;	/* Type of a timeout. */
 
 /*
- * Region offsets are currently limited to 32-bits.  I expect that's going
- * to have to be fixed in the not-too-distant future, since we won't want to
- * split 100Gb memory pools into that many different regions.
+ * Region offsets are the difference between a pointer in a region and the
+ * region's base address.  With private environments, both addresses are the
+ * result of calling malloc, and we can't assume anything about what malloc
+ * will return, so region offsets have to be able to hold differences between
+ * arbitrary pointers.
  */
-typedef u_int32_t roff_t;
+typedef	uintptr_t	roff_t;
 
 /*
  * Forward structure declarations, so we can declare pointers and
@@ -128,6 +145,9 @@ struct __db_preplist;	typedef struct __db_preplist DB_PREPLIST;
 struct __db_qam_stat;	typedef struct __db_qam_stat DB_QUEUE_STAT;
 struct __db_rep;	typedef struct __db_rep DB_REP;
 struct __db_rep_stat;	typedef struct __db_rep_stat DB_REP_STAT;
+struct __db_sequence;	typedef struct __db_sequence DB_SEQUENCE;
+struct __db_seq_record; typedef struct __db_seq_record DB_SEQ_RECORD;
+struct __db_seq_stat;	typedef struct __db_seq_stat DB_SEQUENCE_STAT;
 struct __db_txn;	typedef struct __db_txn DB_TXN;
 struct __db_txn_active;	typedef struct __db_txn_active DB_TXN_ACTIVE;
 struct __db_txn_stat;	typedef struct __db_txn_stat DB_TXN_STAT;
@@ -152,8 +172,6 @@ struct __db_dbt {
 	u_int32_t dlen;			/* RO: get/put record length. */
 	u_int32_t doff;			/* RO: get/put record offset. */
 
-	void	*app_private;		/* Application-private handle. */
-
 #define	DB_DBT_APPMALLOC	0x001	/* Callback allocated memory. */
 #define	DB_DBT_ISSET		0x002	/* Lower level calls set value. */
 #define	DB_DBT_MALLOC		0x004	/* Return in malloc'd memory. */
@@ -169,17 +187,18 @@ struct __db_dbt {
  *	Interfaces which use any of these common flags should never have
  *	interface specific flags in this range.
  */
-#define	DB_CREATE	      0x000001	/* Create file as necessary. */
-#define	DB_CXX_NO_EXCEPTIONS  0x000002	/* C++: return error values. */
-#define	DB_FORCE	      0x000004	/* Force (anything). */
-#define	DB_NOMMAP	      0x000008	/* Don't mmap underlying file. */
-#define	DB_RDONLY	      0x000010	/* Read-only (O_RDONLY). */
-#define	DB_RECOVER	      0x000020	/* Run normal recovery. */
-#define	DB_THREAD	      0x000040	/* Applications are threaded. */
-#define	DB_TRUNCATE	      0x000080	/* Discard existing DB (O_TRUNC). */
-#define	DB_TXN_NOSYNC	      0x000100	/* Do not sync log on commit. */
-#define	DB_USE_ENVIRON	      0x000200	/* Use the environment. */
-#define	DB_USE_ENVIRON_ROOT   0x000400	/* Use the environment if root. */
+#define	DB_CREATE	      0x0000001	/* Create file as necessary. */
+#define	DB_CXX_NO_EXCEPTIONS  0x0000002	/* C++: return error values. */
+#define	DB_FORCE	      0x0000004	/* Force (anything). */
+#define	DB_NOMMAP	      0x0000008	/* Don't mmap underlying file. */
+#define	DB_RDONLY	      0x0000010	/* Read-only (O_RDONLY). */
+#define	DB_RECOVER	      0x0000020	/* Run normal recovery. */
+#define	DB_THREAD	      0x0000040	/* Applications are threaded. */
+#define	DB_TRUNCATE	      0x0000080	/* Discard existing DB (O_TRUNC). */
+#define	DB_TXN_NOSYNC	      0x0000100	/* Do not sync log on commit. */
+#define	DB_TXN_NOT_DURABLE    0x0000200	/* Do not log changes. */
+#define	DB_USE_ENVIRON	      0x0000400	/* Use the environment. */
+#define	DB_USE_ENVIRON_ROOT   0x0000800	/* Use the environment if root. */
 
 /*
  * Common flags --
@@ -189,116 +208,147 @@ struct __db_dbt {
  * DB_AUTO_COMMIT:
  *	DB_ENV->set_flags, DB->associate, DB->del, DB->put, DB->open,
  *	DB->remove, DB->rename, DB->truncate
+ * DB_DEGREE_2:
+ *	DB->cursor, DB->get, DB->join, DBcursor->c_get, DB_ENV->txn_begin
  * DB_DIRTY_READ:
  *	DB->cursor, DB->get, DB->join, DB->open, DBcursor->c_get,
  *	DB_ENV->txn_begin
+ * DB_NOAUTO_COMMIT
+ *	DB->associate, DB->del, DB->put, DB->open,
+ *	DB->remove, DB->rename, DB->truncate
  *
- *	   Shared flags up to 0x000400 */
-#define	DB_AUTO_COMMIT	    0x00800000	/* Implied transaction. */
-#define	DB_DIRTY_READ	    0x01000000	/* Dirty Read. */
+ * !!!
+ * The DB_DIRTY_READ and DB_DEGREE_2 bit masks can't be changed without
+ * also changing the masks for the flags that can be OR'd into DB
+ * access method and cursor operation values.
+ */
+#define	DB_AUTO_COMMIT	      0x01000000/* Implied transaction. */
+#define	DB_DEGREE_2	      0x02000000/* Degree 2. */
+#define	DB_DIRTY_READ	      0x04000000/* Dirty Read. */
+#define	DB_NO_AUTO_COMMIT     0x08000000/* Override env-wide AUTOCOMMIT. */
 
 /*
  * Flags private to db_env_create.
  */
-#define	DB_CLIENT	      0x000001	/* Open for a client environment. */
+#define	DB_RPCCLIENT	      0x0000001	/* An RPC client environment. */
 
 /*
  * Flags private to db_create.
  */
-#define	DB_XA_CREATE	      0x000001	/* Open in an XA environment. */
+#define	DB_REP_CREATE	      0x0000001	/* Open of an internal rep database. */
+#define	DB_XA_CREATE	      0x0000002	/* Open in an XA environment. */
 
 /*
  * Flags private to DB_ENV->open.
- *	   Shared flags up to 0x000400 */
-#define	DB_INIT_CDB	      0x000800	/* Concurrent Access Methods. */
-#define	DB_INIT_LOCK	      0x001000	/* Initialize locking. */
-#define	DB_INIT_LOG	      0x002000	/* Initialize logging. */
-#define	DB_INIT_MPOOL	      0x004000	/* Initialize mpool. */
-#define	DB_INIT_TXN	      0x008000	/* Initialize transactions. */
-#define	DB_JOINENV	      0x010000	/* Initialize all subsystems present. */
-#define	DB_LOCKDOWN	      0x020000	/* Lock memory into physical core. */
-#define	DB_PRIVATE	      0x040000	/* DB_ENV is process local. */
-#define	DB_RECOVER_FATAL      0x080000	/* Run catastrophic recovery. */
-#define	DB_SYSTEM_MEM	      0x100000	/* Use system-backed memory. */
+ *	   Shared flags up to 0x0000800 */
+#define	DB_INIT_CDB	      0x0001000	/* Concurrent Access Methods. */
+#define	DB_INIT_LOCK	      0x0002000	/* Initialize locking. */
+#define	DB_INIT_LOG	      0x0004000	/* Initialize logging. */
+#define	DB_INIT_MPOOL	      0x0008000	/* Initialize mpool. */
+#define	DB_INIT_REP	      0x0010000	/* Initialize replication. */
+#define	DB_INIT_TXN	      0x0020000	/* Initialize transactions. */
+#define	DB_JOINENV	      0x0040000	/* Initialize all subsystems present. */
+#define	DB_LOCKDOWN	      0x0080000	/* Lock memory into physical core. */
+#define	DB_PRIVATE	      0x0100000	/* DB_ENV is process local. */
+#define	DB_RECOVER_FATAL      0x0200000	/* Run catastrophic recovery. */
+#define	DB_SYSTEM_MEM	      0x0400000	/* Use system-backed memory. */
 
 /*
  * Flags private to DB->open.
- *	   Shared flags up to 0x000400 */
-#define	DB_EXCL		      0x000800	/* Exclusive open (O_EXCL). */
-#define	DB_FCNTL_LOCKING      0x001000	/* UNDOC: fcntl(2) locking. */
-#define	DB_RDWRMASTER	      0x002000	/* UNDOC: allow subdb master open R/W */
-#define	DB_WRITEOPEN	      0x004000	/* UNDOC: open with write lock. */
+ *	   Shared flags up to 0x0000800 */
+#define	DB_EXCL		      0x0001000	/* Exclusive open (O_EXCL). */
+#define	DB_FCNTL_LOCKING      0x0002000	/* UNDOC: fcntl(2) locking. */
+#define	DB_RDWRMASTER	      0x0004000	/* UNDOC: allow subdb master open R/W */
+#define	DB_WRITEOPEN	      0x0008000	/* UNDOC: open with write lock. */
 
 /*
  * Flags private to DB_ENV->txn_begin.
- *	   Shared flags up to 0x000400 */
-#define	DB_TXN_NOWAIT	      0x000800	/* Do not wait for locks in this TXN. */
-#define	DB_TXN_SYNC	      0x001000	/* Always sync log on commit. */
+ *	   Shared flags up to 0x0000800 */
+#define	DB_TXN_NOWAIT	      0x0001000	/* Do not wait for locks in this TXN. */
+#define	DB_TXN_SYNC	      0x0002000	/* Always sync log on commit. */
 
 /*
  * Flags private to DB_ENV->set_encrypt.
  */
-#define	DB_ENCRYPT_AES	      0x000001	/* AES, assumes SHA1 checksum */
+#define	DB_ENCRYPT_AES	      0x0000001	/* AES, assumes SHA1 checksum */
 
 /*
  * Flags private to DB_ENV->set_flags.
- *	   Shared flags up to 0x000400 */
-#define	DB_CDB_ALLDB	      0x000800	/* Set CDB locking per environment. */
-#define	DB_DIRECT_DB	      0x001000	/* Don't buffer databases in the OS. */
-#define	DB_DIRECT_LOG	      0x002000	/* Don't buffer log files in the OS. */
-#define	DB_NOLOCKING	      0x004000	/* Set locking/mutex behavior. */
-#define	DB_NOPANIC	      0x008000	/* Set panic state per DB_ENV. */
-#define	DB_OVERWRITE	      0x010000	/* Overwrite unlinked region files. */
-#define	DB_PANIC_ENVIRONMENT  0x020000	/* Set panic state per environment. */
-#define	DB_REGION_INIT	      0x040000	/* Page-fault regions on open. */
-#define	DB_TXN_WRITE_NOSYNC   0x080000	/* Write, don't sync, on txn commit. */
-#define	DB_YIELDCPU	      0x100000	/* Yield the CPU (a lot). */
+ *	   Shared flags up to 0x00000800 */
+#define	DB_CDB_ALLDB	      0x00001000/* Set CDB locking per environment. */
+#define	DB_DIRECT_DB	      0x00002000/* Don't buffer databases in the OS. */
+#define	DB_DIRECT_LOG	      0x00004000/* Don't buffer log files in the OS. */
+#define	DB_DSYNC_LOG	      0x00008000/* Set O_DSYNC on the log. */
+#define	DB_LOG_AUTOREMOVE     0x00010000/* Automatically remove log files. */
+#define	DB_LOG_INMEMORY       0x00020000/* Store logs in buffers in memory. */
+#define	DB_NOLOCKING	      0x00040000/* Set locking/mutex behavior. */
+#define	DB_NOPANIC	      0x00080000/* Set panic state per DB_ENV. */
+#define	DB_OVERWRITE	      0x00100000/* Overwrite unlinked region files. */
+#define	DB_PANIC_ENVIRONMENT  0x00200000/* Set panic state per environment. */
+#define	DB_REGION_INIT	      0x00400000/* Page-fault regions on open. */
+#define	DB_TIME_NOTGRANTED    0x00800000/* Return NOTGRANTED on timeout. */
+/*	      Shared flags at 0x01000000 */
+/*	      Shared flags at 0x02000000 */
+/*	      Shared flags at 0x04000000 */
+/*	      Shared flags at 0x08000000 */
+#define	DB_TXN_WRITE_NOSYNC   0x10000000/* Write, don't sync, on txn commit. */
+#define	DB_YIELDCPU	      0x20000000/* Yield the CPU (a lot). */
 
 /*
  * Flags private to DB->set_feedback's callback.
  */
-#define	DB_UPGRADE	      0x000001	/* Upgrading. */
-#define	DB_VERIFY	      0x000002	/* Verifying. */
+#define	DB_UPGRADE	      0x0000001	/* Upgrading. */
+#define	DB_VERIFY	      0x0000002	/* Verifying. */
 
 /*
  * Flags private to DB_MPOOLFILE->open.
- *	   Shared flags up to 0x000400 */
-#define	DB_DIRECT	      0x000800	/* Don't buffer the file in the OS. */
-#define	DB_EXTENT	      0x001000	/* UNDOC: dealing with an extent. */
-#define	DB_ODDFILESIZE	      0x002000	/* Truncate file to N * pgsize. */
+ *	   Shared flags up to 0x0000800 */
+#define	DB_DIRECT	      0x0001000	/* Don't buffer the file in the OS. */
+#define	DB_DURABLE_UNKNOWN    0x0002000 /* internal: durability on open. */
+#define	DB_EXTENT	      0x0004000	/* internal: dealing with an extent. */
+#define	DB_ODDFILESIZE	      0x0008000	/* Truncate file to N * pgsize. */
 
 /*
  * Flags private to DB->set_flags.
  */
-#define	DB_CHKSUM_SHA1	      0x000001	/* Use SHA1 checksumming */
-#define	DB_DUP		      0x000002	/* Btree, Hash: duplicate keys. */
-#define	DB_DUPSORT	      0x000004	/* Btree, Hash: duplicate keys. */
-#define	DB_ENCRYPT	      0x000008	/* Btree, Hash: duplicate keys. */
-#define	DB_RECNUM	      0x000010	/* Btree: record numbers. */
-#define	DB_RENUMBER	      0x000020	/* Recno: renumber on insert/delete. */
-#define	DB_REVSPLITOFF	      0x000040	/* Btree: turn off reverse splits. */
-#define	DB_SNAPSHOT	      0x000080	/* Recno: snapshot the input. */
+#define	DB_CHKSUM	      0x0000001	/* Do checksumming */
+#define	DB_DUP		      0x0000002	/* Btree, Hash: duplicate keys. */
+#define	DB_DUPSORT	      0x0000004	/* Btree, Hash: duplicate keys. */
+#define	DB_ENCRYPT	      0x0000008	/* Btree, Hash: duplicate keys. */
+#define	DB_INORDER	      0x0000010	/* Queue: strict ordering on consume. */
+#define	DB_RECNUM	      0x0000020	/* Btree: record numbers. */
+#define	DB_RENUMBER	      0x0000040	/* Recno: renumber on insert/delete. */
+#define	DB_REVSPLITOFF	      0x0000080	/* Btree: turn off reverse splits. */
+#define	DB_SNAPSHOT	      0x0000100	/* Recno: snapshot the input. */
 
 /*
- * Flags private to the DB->stat methods.
+ * Flags private to the DB_ENV->stat_print, DB->stat and DB->stat_print methods.
  */
-#define	DB_STAT_CLEAR	      0x000001	/* Clear stat after returning values. */
+#define	DB_STAT_ALL	      0x0000001	/* Print: Everything. */
+#define	DB_STAT_CLEAR	      0x0000002	/* Clear stat after returning values. */
+#define	DB_STAT_LOCK_CONF     0x0000004	/* Print: Lock conflict matrix. */
+#define	DB_STAT_LOCK_LOCKERS  0x0000008	/* Print: Lockers. */
+#define	DB_STAT_LOCK_OBJECTS  0x0000010	/* Print: Lock objects. */
+#define	DB_STAT_LOCK_PARAMS   0x0000020	/* Print: Lock parameters. */
+#define	DB_STAT_MEMP_HASH     0x0000040	/* Print: Mpool hash buckets. */
+#define	DB_STAT_SUBSYSTEM     0x0000080	/* Print: Subsystems too. */
 
 /*
  * Flags private to DB->join.
  */
-#define	DB_JOIN_NOSORT	      0x000001	/* Don't try to optimize join. */
+#define	DB_JOIN_NOSORT	      0x0000001	/* Don't try to optimize join. */
 
 /*
  * Flags private to DB->verify.
  */
-#define	DB_AGGRESSIVE	      0x000001	/* Salvage whatever could be data.*/
-#define	DB_NOORDERCHK	      0x000002	/* Skip sort order/hashing check. */
-#define	DB_ORDERCHKONLY	      0x000004	/* Only perform the order check. */
-#define	DB_PR_PAGE	      0x000008	/* Show page contents (-da). */
-#define	DB_PR_RECOVERYTEST    0x000010	/* Recovery test (-dr). */
-#define	DB_PRINTABLE	      0x000020	/* Use printable format for salvage. */
-#define	DB_SALVAGE	      0x000040	/* Salvage what looks like data. */
+#define	DB_AGGRESSIVE	      0x0000001	/* Salvage whatever could be data.*/
+#define	DB_NOORDERCHK	      0x0000002	/* Skip sort order/hashing check. */
+#define	DB_ORDERCHKONLY	      0x0000004	/* Only perform the order check. */
+#define	DB_PR_PAGE	      0x0000008	/* Show page contents (-da). */
+#define	DB_PR_RECOVERYTEST    0x0000010	/* Recovery test (-dr). */
+#define	DB_PRINTABLE	      0x0000020	/* Use printable format for salvage. */
+#define	DB_SALVAGE	      0x0000040	/* Salvage what looks like data. */
+#define	DB_UNREF	      0x0000080	/* Report unreferenced pages. */
 /*
  * !!!
  * These must not go over 0x8000, or they will collide with the flags
@@ -308,7 +358,8 @@ struct __db_dbt {
 /*
  * Flags private to DB->set_rep_transport's send callback.
  */
-#define	DB_REP_PERMANENT	0x0001	/* Important--app. may want to flush. */
+#define	DB_REP_NOBUFFER	      0x0000001	/* Do not buffer this message. */
+#define	DB_REP_PERMANENT      0x0000002	/* Important--app. may want to flush. */
 
 /*******************************************************
  * Locking.
@@ -324,15 +375,16 @@ struct __db_dbt {
 #define	DB_LOCK_NORUN		0
 #define	DB_LOCK_DEFAULT		1	/* Default policy. */
 #define	DB_LOCK_EXPIRE		2	/* Only expire locks, no detection. */
-#define	DB_LOCK_MAXLOCKS	3	/* Abort txn with maximum # of locks. */
-#define	DB_LOCK_MINLOCKS	4	/* Abort txn with minimum # of locks. */
-#define	DB_LOCK_MINWRITE	5	/* Abort txn with minimum writelocks. */
-#define	DB_LOCK_OLDEST		6	/* Abort oldest transaction. */
-#define	DB_LOCK_RANDOM		7	/* Abort random transaction. */
-#define	DB_LOCK_YOUNGEST	8	/* Abort youngest transaction. */
+#define	DB_LOCK_MAXLOCKS	3	/* Select locker with max locks. */
+#define	DB_LOCK_MAXWRITE	4	/* Select locker with max writelocks. */
+#define	DB_LOCK_MINLOCKS	5	/* Select locker with min locks. */
+#define	DB_LOCK_MINWRITE	6	/* Select locker with min writelocks. */
+#define	DB_LOCK_OLDEST		7	/* Select oldest locker. */
+#define	DB_LOCK_RANDOM		8	/* Select random locker. */
+#define	DB_LOCK_YOUNGEST	9	/* Select youngest locker. */
 
 /* Flag values for lock_vec(), lock_get(). */
-#define	DB_LOCK_FREE_LOCKER	0x001	/* Internal: Free locker as well. */
+#define	DB_LOCK_ABORT		0x001	/* Internal: Lock during abort. */
 #define	DB_LOCK_NOWAIT		0x002	/* Don't wait on unavailable lock. */
 #define	DB_LOCK_RECORD		0x004	/* Internal: record lock. */
 #define	DB_LOCK_REMOVE		0x008	/* Internal: flag object removed. */
@@ -382,16 +434,15 @@ typedef enum {
  */
 typedef enum  {
 	DB_LSTAT_ABORTED=1,		/* Lock belongs to an aborted txn. */
-	DB_LSTAT_ERR=2,			/* Lock is bad. */
-	DB_LSTAT_EXPIRED=3,		/* Lock has expired. */
-	DB_LSTAT_FREE=4,		/* Lock is unallocated. */
-	DB_LSTAT_HELD=5,		/* Lock is currently held. */
-	DB_LSTAT_NOTEXIST=6,		/* Object on which lock was waiting
+	DB_LSTAT_EXPIRED=2,		/* Lock has expired. */
+	DB_LSTAT_FREE=3,		/* Lock is unallocated. */
+	DB_LSTAT_HELD=4,		/* Lock is currently held. */
+	DB_LSTAT_NOTEXIST=5,		/* Object on which lock was waiting
 					 * was removed */
-	DB_LSTAT_PENDING=7,		/* Lock was waiting and has been
+	DB_LSTAT_PENDING=6,		/* Lock was waiting and has been
 					 * promoted; waiting for the owner
 					 * to run and upgrade it to held. */
-	DB_LSTAT_WAITING=8		/* Lock is on the wait queue. */
+	DB_LSTAT_WAITING=7		/* Lock is on the wait queue. */
 }db_status_t;
 
 /* Lock statistics structure. */
@@ -401,7 +452,7 @@ struct __db_lock_stat {
 	u_int32_t st_maxlocks;		/* Maximum number of locks in table. */
 	u_int32_t st_maxlockers;	/* Maximum num of lockers in table. */
 	u_int32_t st_maxobjects;	/* Maximum num of objects in table. */
-	u_int32_t st_nmodes;		/* Number of lock modes. */
+	int	  st_nmodes;		/* Number of lock modes. */
 	u_int32_t st_nlocks;		/* Current number of locks. */
 	u_int32_t st_maxnlocks;		/* Maximum number of locks so far. */
 	u_int32_t st_nlockers;		/* Current number of lockers. */
@@ -420,7 +471,7 @@ struct __db_lock_stat {
 	u_int32_t st_ntxntimeouts;	/* Number of transaction timeouts. */
 	u_int32_t st_region_wait;	/* Region lock granted after wait. */
 	u_int32_t st_region_nowait;	/* Region lock granted without wait. */
-	u_int32_t st_regsize;		/* Region size. */
+	roff_t	  st_regsize;		/* Region size. */
 };
 
 /*
@@ -433,7 +484,6 @@ struct __db_ilock {
 #define	DB_HANDLE_LOCK	1
 #define	DB_RECORD_LOCK	2
 #define	DB_PAGE_LOCK	3
-#define	DB_TXN_LOCK	4
 	u_int32_t type;			/* Type of lock. */
 };
 
@@ -443,7 +493,7 @@ struct __db_ilock {
  *	lock_get request (or a lock_vec/DB_LOCK_GET).
  */
 struct __db_lock_u {
-	size_t		off;		/* Offset of the lock in the region */
+	roff_t		off;		/* Offset of the lock in the region */
 	u_int32_t	ndx;		/* Index of the object referenced by
 					 * this lock; used for locking. */
 	u_int32_t	gen;		/* Generation number of this lock. */
@@ -462,14 +512,25 @@ struct __db_lockreq {
 /*******************************************************
  * Logging.
  *******************************************************/
-#define	DB_LOGVERSION	7		/* Current log version. */
-#define	DB_LOGOLDVER	7		/* Oldest log version supported. */
+#define	DB_LOGVERSION	10		/* Current log version. */
+#define	DB_LOGOLDVER	10		/* Oldest log version supported. */
 #define	DB_LOGMAGIC	0x040988
 
-/* Flag values for log_archive(). */
-#define	DB_ARCH_ABS		0x001	/* Absolute pathnames. */
-#define	DB_ARCH_DATA		0x002	/* Data files. */
-#define	DB_ARCH_LOG		0x004	/* Log files. */
+/* Flag values for DB_ENV->log_archive(). */
+#define	DB_ARCH_ABS	0x001		/* Absolute pathnames. */
+#define	DB_ARCH_DATA	0x002		/* Data files. */
+#define	DB_ARCH_LOG	0x004		/* Log files. */
+#define	DB_ARCH_REMOVE	0x008	/* Remove log files. */
+
+/* Flag values for DB_ENV->log_put(). */
+#define	DB_FLUSH		0x001	/* Flush data to disk (public). */
+#define	DB_LOG_CHKPNT		0x002	/* Flush supports a checkpoint */
+#define	DB_LOG_COMMIT		0x004	/* Flush supports a commit */
+#define	DB_LOG_NOCOPY		0x008	/* Don't copy data */
+#define	DB_LOG_NOT_DURABLE	0x010	/* Do not log; keep in memory */
+#define	DB_LOG_PERM		0x020	/* Flag record with REP_PERMANENT */
+#define	DB_LOG_RESEND		0x040	/* Resent log record */
+#define	DB_LOG_WRNOSYNC		0x080	/* Write, don't sync log_put */
 
 /*
  * A DB_LSN has two parts, a fileid which identifies a specific file, and an
@@ -485,6 +546,18 @@ struct __db_lsn {
 	u_int32_t	offset;		/* File offset. */
 };
 
+/*
+ * Application-specified log record types start at DB_user_BEGIN, and must not
+ * equal or exceed DB_debug_FLAG.
+ *
+ * DB_debug_FLAG is the high-bit of the u_int32_t that specifies a log record
+ * type.  If the flag is set, it's a log record that was logged for debugging
+ * purposes only, even if it reflects a database change -- the change was part
+ * of a non-durable transaction.
+ */
+#define	DB_user_BEGIN		10000
+#define	DB_debug_FLAG		0x80000000
+
 /*
  * DB_LOGC --
  *	Log cursor.
@@ -492,7 +565,7 @@ struct __db_lsn {
 struct __db_log_cursor {
 	DB_ENV	 *dbenv;		/* Enclosing dbenv. */
 
-	DB_FH	 *c_fh;			/* File handle. */
+	DB_FH	 *c_fhp;		/* File handle. */
 	DB_LSN	  c_lsn;		/* Cursor: LSN */
 	u_int32_t c_len;		/* Cursor: record length */
 	u_int32_t c_prev;		/* Cursor: previous record's offset */
@@ -521,7 +594,7 @@ struct __db_log_cursor {
 struct __db_log_stat {
 	u_int32_t st_magic;		/* Log file magic number. */
 	u_int32_t st_version;		/* Log file version number. */
-	int st_mode;			/* Log file mode. */
+	int	  st_mode;			/* Log file mode. */
 	u_int32_t st_lg_bsize;		/* Log buffer size. */
 	u_int32_t st_lg_size;		/* Log file size. */
 	u_int32_t st_w_bytes;		/* Bytes to log. */
@@ -537,11 +610,19 @@ struct __db_log_stat {
 	u_int32_t st_cur_offset;	/* Current log file offset. */
 	u_int32_t st_disk_file;		/* Known on disk log file number. */
 	u_int32_t st_disk_offset;	/* Known on disk log file offset. */
-	u_int32_t st_regsize;		/* Region size. */
+	roff_t	  st_regsize;		/* Region size. */
 	u_int32_t st_maxcommitperflush;	/* Max number of commits in a flush. */
 	u_int32_t st_mincommitperflush;	/* Min number of commits in a flush. */
 };
 
+/*
+ * We need to record the first log record of a transaction.
+ * For user defined logging this macro returns the place to
+ * put that information, if it is need in rlsnp, otherwise it
+ * leaves it unchanged.
+ */
+#define	DB_SET_BEGIN_LSNP(txn, rlsnp)	((txn)->set_begin_lsnp(txn, rlsnp))
+
 /*******************************************************
  * Shared buffer cache (mpool).
  *******************************************************/
@@ -554,6 +635,11 @@ struct __db_log_stat {
 #define	DB_MPOOL_CLEAN		0x001	/* Page is not modified. */
 #define	DB_MPOOL_DIRTY		0x002	/* Page is modified. */
 #define	DB_MPOOL_DISCARD	0x004	/* Don't cache the page. */
+#define	DB_MPOOL_FREE		0x008	/* Free page if present. */
+
+/* Flags values for DB_MPOOLFILE->set_flags. */
+#define	DB_MPOOL_NOFILE		0x001	/* Never open a backing file. */
+#define	DB_MPOOL_UNLINK		0x002	/* Unlink the file on last close. */
 
 /* Priority values for DB_MPOOLFILE->set_priority. */
 typedef enum {
@@ -566,21 +652,14 @@ typedef enum {
 
 /* Per-process DB_MPOOLFILE information. */
 struct __db_mpoolfile {
-	/* These fields need to be protected for multi-threaded support. */
-	DB_MUTEX *mutexp;		/* Structure thread lock. */
-
 	DB_FH	  *fhp;			/* Underlying file handle. */
 
-	u_int32_t  ref;			/* Reference count. */
-
 	/*
 	 * !!!
-	 * The pinref and q fields are protected by the region lock, not the
-	 * DB_MPOOLFILE structure mutex.  We don't use the structure mutex
-	 * because then I/O (which holds the structure lock held because of
-	 * the race between the seek and write of the file descriptor) would
-	 * block any other put/get calls using this DB_MPOOLFILE structure.
+	 * The ref, pinref and q fields are protected by the region lock.
 	 */
+	u_int32_t  ref;			/* Reference count. */
+
 	u_int32_t pinref;		/* Pinned block reference count. */
 
 	/*
@@ -594,63 +673,82 @@ struct __db_mpoolfile {
 	} q;				/* Linked list of DB_MPOOLFILE's. */
 
 	/*
-	 * These fields are not thread-protected because they are initialized
-	 * when the file is opened and never modified.
+	 * !!!
+	 * The rest of the fields (with the exception of the MP_FLUSH flag)
+	 * are not thread-protected, even when they may be modified at any
+	 * time by the application.  The reason is the DB_MPOOLFILE handle
+	 * is single-threaded from the viewpoint of the application, and so
+	 * the only fields needing to be thread-protected are those accessed
+	 * by checkpoint or sync threads when using DB_MPOOLFILE structures
+	 * to flush buffers from the cache.
 	 */
-	int	  ftype;		/* File type. */
-	DBT	 *pgcookie;		/* Byte-string passed to pgin/pgout. */
-	u_int8_t *fileid;		/* Unique file ID. */
-	int32_t	  lsn_offset;		/* LSN offset in page. */
-	u_int32_t clear_len;		/* Cleared length on created pages. */
+	DB_ENV	       *dbenv;		/* Overlying DB_ENV. */
+	MPOOLFILE      *mfp;		/* Underlying MPOOLFILE. */
+
+	u_int32_t	clear_len;	/* Cleared length on created pages. */
+	u_int8_t			/* Unique file ID. */
+			fileid[DB_FILE_ID_LEN];
+	int		ftype;		/* File type. */
+	int32_t		lsn_offset;	/* LSN offset in page. */
+	u_int32_t	gbytes, bytes;	/* Maximum file size. */
+	DBT	       *pgcookie;	/* Byte-string passed to pgin/pgout. */
+	DB_CACHE_PRIORITY		/* Cache priority. */
+			priority;
 
-	DB_MPOOL  *dbmp;		/* Overlying DB_MPOOL. */
-	MPOOLFILE *mfp;			/* Underlying MPOOLFILE. */
+	void	       *addr;		/* Address of mmap'd region. */
+	size_t		len;		/* Length of mmap'd region. */
 
-	void	  *addr;		/* Address of mmap'd region. */
-	size_t	   len;			/* Length of mmap'd region. */
+	u_int32_t	config_flags;	/* Flags to DB_MPOOLFILE->set_flags. */
 
 					/* Methods. */
-	int  (*close) __P((DB_MPOOLFILE *, u_int32_t));
-	int  (*get) __P((DB_MPOOLFILE *, db_pgno_t *, u_int32_t, void *));
-	void (*get_fileid) __P((DB_MPOOLFILE *, u_int8_t *));
-	void (*last_pgno) __P((DB_MPOOLFILE *, db_pgno_t *));
-	int  (*open)__P((DB_MPOOLFILE *, const char *, u_int32_t, int, size_t));
-	int  (*put) __P((DB_MPOOLFILE *, void *, u_int32_t));
-	void (*refcnt) __P((DB_MPOOLFILE *, db_pgno_t *));
-	int  (*set) __P((DB_MPOOLFILE *, void *, u_int32_t));
-	int  (*set_clear_len) __P((DB_MPOOLFILE *, u_int32_t));
-	int  (*set_fileid) __P((DB_MPOOLFILE *, u_int8_t *));
-	int  (*set_ftype) __P((DB_MPOOLFILE *, int));
-	int  (*set_lsn_offset) __P((DB_MPOOLFILE *, int32_t));
-	int  (*set_pgcookie) __P((DB_MPOOLFILE *, DBT *));
-	int  (*set_priority) __P((DB_MPOOLFILE *, DB_CACHE_PRIORITY));
-	void (*set_unlink) __P((DB_MPOOLFILE *, int));
-	int  (*sync) __P((DB_MPOOLFILE *));
+	int (*close) __P((DB_MPOOLFILE *, u_int32_t));
+	int (*get) __P((DB_MPOOLFILE *, db_pgno_t *, u_int32_t, void *));
+	int (*open) __P((DB_MPOOLFILE *, const char *, u_int32_t, int, size_t));
+	int (*put) __P((DB_MPOOLFILE *, void *, u_int32_t));
+	int (*set) __P((DB_MPOOLFILE *, void *, u_int32_t));
+	int (*get_clear_len) __P((DB_MPOOLFILE *, u_int32_t *));
+	int (*set_clear_len) __P((DB_MPOOLFILE *, u_int32_t));
+	int (*get_fileid) __P((DB_MPOOLFILE *, u_int8_t *));
+	int (*set_fileid) __P((DB_MPOOLFILE *, u_int8_t *));
+	int (*get_flags) __P((DB_MPOOLFILE *, u_int32_t *));
+	int (*set_flags) __P((DB_MPOOLFILE *, u_int32_t, int));
+	int (*get_ftype) __P((DB_MPOOLFILE *, int *));
+	int (*set_ftype) __P((DB_MPOOLFILE *, int));
+	int (*get_lsn_offset) __P((DB_MPOOLFILE *, int32_t *));
+	int (*set_lsn_offset) __P((DB_MPOOLFILE *, int32_t));
+	int (*get_maxsize) __P((DB_MPOOLFILE *, u_int32_t *, u_int32_t *));
+	int (*set_maxsize) __P((DB_MPOOLFILE *, u_int32_t, u_int32_t));
+	int (*get_pgcookie) __P((DB_MPOOLFILE *, DBT *));
+	int (*set_pgcookie) __P((DB_MPOOLFILE *, DBT *));
+	int (*get_priority) __P((DB_MPOOLFILE *, DB_CACHE_PRIORITY *));
+	int (*set_priority) __P((DB_MPOOLFILE *, DB_CACHE_PRIORITY));
+	int (*sync) __P((DB_MPOOLFILE *));
 
 	/*
-	 * MP_OPEN_CALLED and MP_READONLY do not need to be thread protected
-	 * because they are initialized when the file is opened, and never
-	 * modified.
+	 * MP_FILEID_SET, MP_OPEN_CALLED and MP_READONLY do not need to be
+	 * thread protected because they are initialized before the file is
+	 * linked onto the per-process lists, and never modified.
 	 *
-	 * MP_FLUSH, MP_UPGRADE and MP_UPGRADE_FAIL are thread protected
-	 * becase they are potentially read by multiple threads of control.
+	 * MP_FLUSH is thread protected because it is potentially read/set by
+	 * multiple threads of control.
 	 */
-#define	MP_FLUSH	0x001		/* Was opened to flush a buffer. */
-#define	MP_OPEN_CALLED	0x002		/* File opened. */
-#define	MP_READONLY	0x004		/* File is readonly. */
-#define	MP_UPGRADE	0x008		/* File descriptor is readwrite. */
-#define	MP_UPGRADE_FAIL	0x010		/* Upgrade wasn't possible. */
+#define	MP_FILEID_SET	0x001		/* Application supplied a file ID. */
+#define	MP_FLUSH	0x002		/* Was opened to flush a buffer. */
+#define	MP_OPEN_CALLED	0x004		/* File opened. */
+#define	MP_READONLY	0x008		/* File is readonly. */
 	u_int32_t  flags;
 };
 
-/*
- * Mpool statistics structure.
- */
+/* Mpool statistics structure. */
 struct __db_mpool_stat {
 	u_int32_t st_gbytes;		/* Total cache size: GB. */
 	u_int32_t st_bytes;		/* Total cache size: B. */
 	u_int32_t st_ncache;		/* Number of caches. */
-	u_int32_t st_regsize;		/* Cache size. */
+	roff_t	  st_regsize;		/* Region size. */
+	size_t	  st_mmapsize;		/* Maximum file size for mmap. */
+	int	  st_maxopenfd;		/* Maximum number of open fd's. */
+	int	  st_maxwrite;		/* Maximum buffers to write. */
+	int	  st_maxwrite_sleep;	/* Sleep after writing max buffers. */
 	u_int32_t st_map;		/* Pages from mapped files. */
 	u_int32_t st_cache_hit;		/* Pages found in the cache. */
 	u_int32_t st_cache_miss;	/* Pages not found in the cache. */
@@ -682,7 +780,7 @@ struct __db_mpool_stat {
 /* Mpool file statistics structure. */
 struct __db_mpool_fstat {
 	char *file_name;		/* File name. */
-	size_t st_pagesize;		/* Page size. */
+	u_int32_t st_pagesize;		/* Page size. */
 	u_int32_t st_map;		/* Pages from mapped files. */
 	u_int32_t st_cache_hit;		/* Pages found in the cache. */
 	u_int32_t st_cache_miss;	/* Pages not found in the cache. */
@@ -702,10 +800,9 @@ typedef enum {
 	DB_TXN_BACKWARD_ALLOC=2,	/* Internal. */
 	DB_TXN_BACKWARD_ROLL=3,		/* Public. */
 	DB_TXN_FORWARD_ROLL=4,		/* Public. */
-	DB_TXN_GETPGNOS=5,		/* Internal. */
-	DB_TXN_OPENFILES=6,		/* Internal. */
-	DB_TXN_POPENFILES=7,		/* Internal. */
-	DB_TXN_PRINT=8			/* Public. */
+	DB_TXN_OPENFILES=5,		/* Internal. */
+	DB_TXN_POPENFILES=6,		/* Internal. */
+	DB_TXN_PRINT=7			/* Public. */
 } db_recops;
 
 /*
@@ -723,6 +820,7 @@ struct __db_txn {
 	DB_TXN		*parent;	/* Pointer to transaction's parent. */
 	DB_LSN		last_lsn;	/* Lsn of last log write. */
 	u_int32_t	txnid;		/* Unique transaction id. */
+	u_int32_t	tid;		/* Thread id for use in MT XA. */
 	roff_t		off;		/* Detail structure within region. */
 	db_timeout_t	lock_timeout;	/* Timeout for locks for this txn. */
 	db_timeout_t	expire;		/* Time this txn expires. */
@@ -732,11 +830,16 @@ struct __db_txn {
 	 * !!!
 	 * Explicit representations of structures from queue.h.
 	 * TAILQ_ENTRY(__db_txn) links;
+	 * TAILQ_ENTRY(__db_txn) xalinks;
 	 */
 	struct {
 		struct __db_txn *tqe_next;
 		struct __db_txn **tqe_prev;
 	} links;			/* Links transactions off manager. */
+	struct {
+		struct __db_txn *tqe_next;
+		struct __db_txn **tqe_prev;
+	} xalinks;			/* Links active XA transactions. */
 
 	/*
 	 * !!!
@@ -748,6 +851,16 @@ struct __db_txn {
 		struct __txn_event **tqh_last;
 	} events;
 
+	/*
+	 * !!!
+	 * Explicit representations of structures from queue.h.
+	 * STAILQ_HEAD(__logrec, __txn_logrec) logs;
+	 */
+	struct {
+		struct __txn_logrec *stqh_first;
+		struct __txn_logrec **stqh_last;
+	} logs;				/* Links deferred events. */
+
 	/*
 	 * !!!
 	 * Explicit representations of structures from queue.h.
@@ -768,8 +881,8 @@ struct __db_txn {
 		struct __db_txn **tqe_prev;
 	} klinks;
 
-	/* API-private structure: used by C++ */
-	void	*api_internal;
+	void	*api_internal;		/* C++ API private. */
+	void	*xml_internal;		/* XML API private. */
 
 	u_int32_t	cursors;	/* Number of cursors open for txn */
 
@@ -779,24 +892,44 @@ struct __db_txn {
 	int	  (*discard) __P((DB_TXN *, u_int32_t));
 	u_int32_t (*id) __P((DB_TXN *));
 	int	  (*prepare) __P((DB_TXN *, u_int8_t *));
+	void	  (*set_begin_lsnp) __P((DB_TXN *txn, DB_LSN **));
 	int	  (*set_timeout) __P((DB_TXN *, db_timeout_t, u_int32_t));
 
-#define	TXN_CHILDCOMMIT	0x01		/* Transaction that has committed. */
-#define	TXN_COMPENSATE	0x02		/* Compensating transaction. */
-#define	TXN_DIRTY_READ	0x04		/* Transaction does dirty reads. */
-#define	TXN_LOCKTIMEOUT	0x08		/* Transaction has a lock timeout. */
-#define	TXN_MALLOC	0x10		/* Structure allocated by TXN system. */
-#define	TXN_NOSYNC	0x20		/* Do not sync on prepare and commit. */
-#define	TXN_NOWAIT	0x40		/* Do not wait on locks. */
-#define	TXN_SYNC	0x80		/* Sync on prepare and commit. */
+#define	TXN_CHILDCOMMIT	0x001		/* Transaction that has committed. */
+#define	TXN_COMPENSATE	0x002		/* Compensating transaction. */
+#define	TXN_DEADLOCK	0x004		/* Transaction has deadlocked. */
+#define	TXN_DEGREE_2	0x008		/* Has degree 2 isolation. */
+#define	TXN_DIRTY_READ	0x010		/* Transaction does dirty reads. */
+#define	TXN_LOCKTIMEOUT	0x020		/* Transaction has a lock timeout. */
+#define	TXN_MALLOC	0x040		/* Structure allocated by TXN system. */
+#define	TXN_NOSYNC	0x080		/* Do not sync on prepare and commit. */
+#define	TXN_NOWAIT	0x100		/* Do not wait on locks. */
+#define	TXN_RESTORED	0x200		/* Transaction has been restored. */
+#define	TXN_SYNC	0x400		/* Sync on prepare and commit. */
 	u_int32_t	flags;
 };
 
+/*
+ * Structure used for two phase commit interface.  Berkeley DB support for two
+ * phase commit is compatible with the X/open XA interface.
+ *
+ * The XA #define XIDDATASIZE defines the size of a global transaction ID.  We
+ * have our own version here (for name space reasons) which must have the same
+ * value.
+ */
+#define	DB_XIDDATASIZE	128
+struct __db_preplist {
+	DB_TXN	*txn;
+	u_int8_t gid[DB_XIDDATASIZE];
+};
+
 /* Transaction statistics structure. */
 struct __db_txn_active {
-	u_int32_t	txnid;		/* Transaction ID */
-	u_int32_t	parentid;	/* Transaction ID of parent */
-	DB_LSN		lsn;		/* LSN when transaction began */
+	u_int32_t txnid;		/* Transaction ID */
+	u_int32_t parentid;		/* Transaction ID of parent */
+	DB_LSN	  lsn;			/* LSN when transaction began */
+	u_int32_t xa_status;		/* XA status */
+	u_int8_t  xid[DB_XIDDATASIZE];	/* XA global transaction ID */
 };
 
 struct __db_txn_stat {
@@ -814,19 +947,7 @@ struct __db_txn_stat {
 	DB_TXN_ACTIVE *st_txnarray;	/* array of active transactions */
 	u_int32_t st_region_wait;	/* Region lock granted after wait. */
 	u_int32_t st_region_nowait;	/* Region lock granted without wait. */
-	u_int32_t st_regsize;		/* Region size. */
-};
-
-/*
- * Structure used for two phase commit interface.  Berkeley DB support for two
- * phase commit is compatible with the X/open XA interface.  The xa #define
- * XIDDATASIZE defines the size of a global transaction ID.  We have our own
- * version here which must have the same value.
- */
-#define	DB_XIDDATASIZE	128
-struct __db_preplist {
-	DB_TXN	*txn;
-	u_int8_t gid[DB_XIDDATASIZE];
+	roff_t	  st_regsize;		/* Region size. */
 };
 
 /*******************************************************
@@ -838,8 +959,7 @@ struct __db_preplist {
 
 /* rep_start flags values */
 #define	DB_REP_CLIENT		0x001
-#define	DB_REP_LOGSONLY		0x002
-#define	DB_REP_MASTER		0x004
+#define	DB_REP_MASTER		0x002
 
 /* Replication statistics. */
 struct __db_rep_stat {
@@ -855,12 +975,15 @@ struct __db_rep_stat {
 	u_int32_t st_status;		/* Current replication status. */
 	DB_LSN st_next_lsn;		/* Next LSN to use or expect. */
 	DB_LSN st_waiting_lsn;		/* LSN we're awaiting, if any. */
+	db_pgno_t st_next_pg;		/* Next pg we expect. */
+	db_pgno_t st_waiting_pg;	/* pg we're awaiting, if any. */
 
 	u_int32_t st_dupmasters;	/* # of times a duplicate master
 					   condition was detected.+ */
 	int st_env_id;			/* Current environment ID. */
 	int st_env_priority;		/* Current environment priority. */
 	u_int32_t st_gen;		/* Current generation number. */
+	u_int32_t st_egen;		/* Current election gen number. */
 	u_int32_t st_log_duplicated;	/* Log records received multiply.+ */
 	u_int32_t st_log_queued;	/* Log records currently queued.+ */
 	u_int32_t st_log_queued_max;	/* Max. log records queued at once.+ */
@@ -881,6 +1004,10 @@ struct __db_rep_stat {
 	u_int32_t st_nthrottles;	/* # of times we were throttled. */
 	u_int32_t st_outdated;		/* # of times we detected and returned
 					   an OUTDATED condition.+ */
+	u_int32_t st_pg_duplicated;	/* Pages received multiply.+ */
+	u_int32_t st_pg_records;	/* Pages received and stored.+ */
+	u_int32_t st_pg_requested;	/* Pages missed and requested.+ */
+	u_int32_t st_startup_complete;	/* Site completed client sync-up. */
 	u_int32_t st_txns_applied;	/* # of transactions applied.+ */
 
 	/* Elections generally. */
@@ -892,11 +1019,75 @@ struct __db_rep_stat {
 	u_int32_t st_election_gen;	/* Election generation number. */
 	DB_LSN st_election_lsn;		/* Max. LSN of current winner. */
 	int st_election_nsites;		/* # of "registered voters". */
+	int st_election_nvotes;		/* # of "registered voters" needed. */
 	int st_election_priority;	/* Current election priority. */
 	int st_election_status;		/* Current election status. */
-	int st_election_tiebreaker;	/* Election tiebreaker value. */
+	u_int32_t st_election_tiebreaker;/* Election tiebreaker value. */
 	int st_election_votes;		/* Votes received in this round. */
 };
+/*
+ * The storage record for a sequence.
+ */
+struct __db_seq_record {
+	u_int32_t	seq_version;	/* Version size/number. */
+#define	DB_SEQ_DEC		0x00000001	/* Decrement sequence. */
+#define	DB_SEQ_INC		0x00000002	/* Increment sequence. */
+#define	DB_SEQ_RANGE_SET	0x00000004	/* Range set (internal). */
+#define	DB_SEQ_WRAP		0x00000008	/* Wrap sequence at min/max. */
+	u_int32_t	flags;		/* Flags. */
+	db_seq_t	seq_value;	/* Current value. */
+	db_seq_t	seq_max;	/* Max permitted. */
+	db_seq_t	seq_min;	/* Min permitted. */
+};
+
+/*
+ * Handle for a sequence object.
+ */
+struct __db_sequence {
+	DB		*seq_dbp;	/* DB handle for this sequence. */
+	DB_MUTEX	*seq_mutexp;	/* Mutex if sequence is threaded. */
+	DB_SEQ_RECORD	*seq_rp;	/* Pointer to current data. */
+	DB_SEQ_RECORD	seq_record;	/* Data from DB_SEQUENCE. */
+	int32_t		seq_cache_size; /* Number of values cached. */
+	db_seq_t	seq_last_value;	/* Last value cached. */
+	DBT		seq_key;	/* DBT pointing to sequence key. */
+	DBT		seq_data;	/* DBT pointing to seq_record. */
+
+	/* API-private structure: used by C++ and Java. */
+	void		*api_internal;
+
+	int		(*close) __P((DB_SEQUENCE *, u_int32_t));
+	int		(*get) __P((DB_SEQUENCE *,
+			      DB_TXN *, int32_t, db_seq_t *, u_int32_t));
+	int		(*get_cachesize) __P((DB_SEQUENCE *, int32_t *));
+	int		(*get_db) __P((DB_SEQUENCE *, DB **));
+	int		(*get_flags) __P((DB_SEQUENCE *, u_int32_t *));
+	int		(*get_key) __P((DB_SEQUENCE *, DBT *));
+	int		(*get_range) __P((DB_SEQUENCE *,
+			     db_seq_t *, db_seq_t *));
+	int		(*initial_value) __P((DB_SEQUENCE *, db_seq_t));
+	int		(*open) __P((DB_SEQUENCE *,
+			    DB_TXN *, DBT *, u_int32_t));
+	int		(*remove) __P((DB_SEQUENCE *, DB_TXN *, u_int32_t));
+	int		(*set_cachesize) __P((DB_SEQUENCE *, int32_t));
+	int		(*set_flags) __P((DB_SEQUENCE *, u_int32_t));
+	int		(*set_range) __P((DB_SEQUENCE *, db_seq_t, db_seq_t));
+	int		(*stat) __P((DB_SEQUENCE *,
+			    DB_SEQUENCE_STAT **, u_int32_t));
+	int		(*stat_print) __P((DB_SEQUENCE *, u_int32_t));
+};
+
+struct __db_seq_stat {
+	u_int32_t st_wait;	  /* Sequence lock granted without wait. */
+	u_int32_t st_nowait;	  /* Sequence lock granted after wait. */
+	db_seq_t  st_current;	  /* Current value in db. */
+	db_seq_t  st_value;	  /* Current cached value. */
+	db_seq_t  st_last_value;  /* Last cached value. */
+	db_seq_t  st_min;	  /* Minimum value. */
+	db_seq_t  st_max;	  /* Maximum value. */
+	int32_t   st_cache_size;  /* Cache size. */
+	u_int32_t st_flags;	  /* Flag value. */
+};
 
 /*******************************************************
  * Access methods.
@@ -923,6 +1114,9 @@ typedef enum {
 #define	DB_QAMOLDVER	3		/* Oldest queue version supported. */
 #define	DB_QAMMAGIC	0x042253
 
+#define	DB_SEQUENCE_VERSION 2		/* Current sequence version. */
+#define	DB_SEQUENCE_OLDVER  1		/* Oldest queue version supported. */
+
 /*
  * DB access method and cursor operation values.  Each value is an operation
  * code to which additional bit flags are added.
@@ -931,51 +1125,50 @@ typedef enum {
 #define	DB_APPEND		 2	/* put() */
 #define	DB_BEFORE		 3	/* c_put() */
 #define	DB_CACHED_COUNTS	 4	/* stat() */
-#define	DB_COMMIT		 5	/* log_put() (internal) */
-#define	DB_CONSUME		 6	/* get() */
-#define	DB_CONSUME_WAIT		 7	/* get() */
-#define	DB_CURRENT		 8	/* c_get(), c_put(), DB_LOGC->get() */
-#define	DB_FAST_STAT		 9	/* stat() */
-#define	DB_FIRST		10	/* c_get(), DB_LOGC->get() */
-#define	DB_GET_BOTH		11	/* get(), c_get() */
-#define	DB_GET_BOTHC		12	/* c_get() (internal) */
-#define	DB_GET_BOTH_RANGE	13	/* get(), c_get() */
-#define	DB_GET_RECNO		14	/* c_get() */
-#define	DB_JOIN_ITEM		15	/* c_get(); do not do primary lookup */
-#define	DB_KEYFIRST		16	/* c_put() */
-#define	DB_KEYLAST		17	/* c_put() */
-#define	DB_LAST			18	/* c_get(), DB_LOGC->get() */
-#define	DB_NEXT			19	/* c_get(), DB_LOGC->get() */
-#define	DB_NEXT_DUP		20	/* c_get() */
-#define	DB_NEXT_NODUP		21	/* c_get() */
-#define	DB_NODUPDATA		22	/* put(), c_put() */
-#define	DB_NOOVERWRITE		23	/* put() */
-#define	DB_NOSYNC		24	/* close() */
-#define	DB_POSITION		25	/* c_dup() */
-#define	DB_POSITIONI		26	/* c_dup() (internal) */
-#define	DB_PREV			27	/* c_get(), DB_LOGC->get() */
-#define	DB_PREV_NODUP		28	/* c_get(), DB_LOGC->get() */
-#define	DB_RECORDCOUNT		29	/* stat() */
-#define	DB_SET			30	/* c_get(), DB_LOGC->get() */
-#define	DB_SET_LOCK_TIMEOUT	31	/* set_timout() */
-#define	DB_SET_RANGE		32	/* c_get() */
-#define	DB_SET_RECNO		33	/* get(), c_get() */
-#define	DB_SET_TXN_NOW		34	/* set_timout() (internal) */
-#define	DB_SET_TXN_TIMEOUT	35	/* set_timout() */
-#define	DB_UPDATE_SECONDARY	36	/* c_get(), c_del() (internal) */
-#define	DB_WRITECURSOR		37	/* cursor() */
-#define	DB_WRITELOCK		38	/* cursor() (internal) */
+#define	DB_CONSUME		 5	/* get() */
+#define	DB_CONSUME_WAIT		 6	/* get() */
+#define	DB_CURRENT		 7	/* c_get(), c_put(), DB_LOGC->get() */
+#define	DB_FAST_STAT		 8	/* stat() */
+#define	DB_FIRST		 9	/* c_get(), DB_LOGC->get() */
+#define	DB_GET_BOTH		10	/* get(), c_get() */
+#define	DB_GET_BOTHC		11	/* c_get() (internal) */
+#define	DB_GET_BOTH_RANGE	12	/* get(), c_get() */
+#define	DB_GET_RECNO		13	/* c_get() */
+#define	DB_JOIN_ITEM		14	/* c_get(); do not do primary lookup */
+#define	DB_KEYFIRST		15	/* c_put() */
+#define	DB_KEYLAST		16	/* c_put() */
+#define	DB_LAST			17	/* c_get(), DB_LOGC->get() */
+#define	DB_NEXT			18	/* c_get(), DB_LOGC->get() */
+#define	DB_NEXT_DUP		19	/* c_get() */
+#define	DB_NEXT_NODUP		20	/* c_get() */
+#define	DB_NODUPDATA		21	/* put(), c_put() */
+#define	DB_NOOVERWRITE		22	/* put() */
+#define	DB_NOSYNC		23	/* close() */
+#define	DB_POSITION		24	/* c_dup() */
+#define	DB_PREV			25	/* c_get(), DB_LOGC->get() */
+#define	DB_PREV_NODUP		26	/* c_get(), DB_LOGC->get() */
+#define	DB_RECORDCOUNT		27	/* stat() */
+#define	DB_SET			28	/* c_get(), DB_LOGC->get() */
+#define	DB_SET_LOCK_TIMEOUT	29	/* set_timout() */
+#define	DB_SET_RANGE		30	/* c_get() */
+#define	DB_SET_RECNO		31	/* get(), c_get() */
+#define	DB_SET_TXN_NOW		32	/* set_timout() (internal) */
+#define	DB_SET_TXN_TIMEOUT	33	/* set_timout() */
+#define	DB_UPDATE_SECONDARY	34	/* c_get(), c_del() (internal) */
+#define	DB_WRITECURSOR		35	/* cursor() */
+#define	DB_WRITELOCK		36	/* cursor() (internal) */
 
 /* This has to change when the max opcode hits 255. */
 #define	DB_OPFLAGS_MASK	0x000000ff	/* Mask for operations flags. */
-/*	DB_DIRTY_READ	0x01000000	   Dirty Read. */
-#define	DB_FLUSH	0x02000000	/* Flush data to disk. */
-#define	DB_MULTIPLE	0x04000000	/* Return multiple data values. */
-#define	DB_MULTIPLE_KEY	0x08000000	/* Return multiple data/key pairs. */
-#define	DB_NOCOPY	0x10000000	/* Don't copy data */
-#define	DB_PERMANENT	0x20000000	/* Flag record with REP_PERMANENT. */
-#define	DB_RMW		0x40000000	/* Acquire write flag immediately. */
-#define	DB_WRNOSYNC	0x80000000	/* Private: write, don't sync log_put */
+
+/*
+ * Masks for flags that can be OR'd into DB access method and cursor
+ * operation values.
+ *
+ *	DB_DIRTY_READ	0x04000000	   Dirty Read. */
+#define	DB_MULTIPLE	0x08000000	/* Return multiple data values. */
+#define	DB_MULTIPLE_KEY	0x10000000	/* Return multiple data/key pairs. */
+#define	DB_RMW		0x20000000	/* Acquire write flag immediately. */
 
 /*
  * DB (user visible) error return codes.
@@ -992,39 +1185,47 @@ typedef enum {
  * document that we own the error name space from -30,800 to -30,999.
  */
 /* DB (public) error return codes. */
-#define	DB_DONOTINDEX		(-30999)/* "Null" return from 2ndary callbk. */
-#define	DB_KEYEMPTY		(-30998)/* Key/data deleted or never created. */
-#define	DB_KEYEXIST		(-30997)/* The key/data pair already exists. */
-#define	DB_LOCK_DEADLOCK	(-30996)/* Deadlock. */
-#define	DB_LOCK_NOTGRANTED	(-30995)/* Lock unavailable. */
-#define	DB_NOSERVER		(-30994)/* Server panic return. */
-#define	DB_NOSERVER_HOME	(-30993)/* Bad home sent to server. */
-#define	DB_NOSERVER_ID		(-30992)/* Bad ID sent to server. */
-#define	DB_NOTFOUND		(-30991)/* Key/data pair not found (EOF). */
-#define	DB_OLD_VERSION		(-30990)/* Out-of-date version. */
-#define	DB_PAGE_NOTFOUND	(-30989)/* Requested page not found. */
-#define	DB_REP_DUPMASTER	(-30988)/* There are two masters. */
-#define	DB_REP_HOLDELECTION	(-30987)/* Time to hold an election. */
-#define	DB_REP_NEWMASTER	(-30986)/* We have learned of a new master. */
-#define	DB_REP_NEWSITE		(-30985)/* New site entered system. */
-#define	DB_REP_OUTDATED		(-30984)/* Site is too far behind master. */
-#define	DB_REP_UNAVAIL		(-30983)/* Site cannot currently be reached. */
-#define	DB_RUNRECOVERY		(-30982)/* Panic return. */
-#define	DB_SECONDARY_BAD	(-30981)/* Secondary index corrupt. */
-#define	DB_VERIFY_BAD		(-30980)/* Verify failed; bad format. */
+#define	DB_BUFFER_SMALL		(-30999)/* User memory too small for return. */
+#define	DB_DONOTINDEX		(-30998)/* "Null" return from 2ndary callbk. */
+#define	DB_KEYEMPTY		(-30997)/* Key/data deleted or never created. */
+#define	DB_KEYEXIST		(-30996)/* The key/data pair already exists. */
+#define	DB_LOCK_DEADLOCK	(-30995)/* Deadlock. */
+#define	DB_LOCK_NOTGRANTED	(-30994)/* Lock unavailable. */
+#define	DB_LOG_BUFFER_FULL	(-30993)/* In-memory log buffer full. */
+#define	DB_NOSERVER		(-30992)/* Server panic return. */
+#define	DB_NOSERVER_HOME	(-30991)/* Bad home sent to server. */
+#define	DB_NOSERVER_ID		(-30990)/* Bad ID sent to server. */
+#define	DB_NOTFOUND		(-30989)/* Key/data pair not found (EOF). */
+#define	DB_OLD_VERSION		(-30988)/* Out-of-date version. */
+#define	DB_PAGE_NOTFOUND	(-30987)/* Requested page not found. */
+#define	DB_REP_DUPMASTER	(-30986)/* There are two masters. */
+#define	DB_REP_HANDLE_DEAD	(-30985)/* Rolled back a commit. */
+#define	DB_REP_HOLDELECTION	(-30984)/* Time to hold an election. */
+#define	DB_REP_ISPERM		(-30983)/* Cached not written perm written.*/
+#define	DB_REP_NEWMASTER	(-30982)/* We have learned of a new master. */
+#define	DB_REP_NEWSITE		(-30981)/* New site entered system. */
+#define	DB_REP_NOTPERM		(-30980)/* Permanent log record not written. */
+#define	DB_REP_STARTUPDONE	(-30979)/* Client startup complete. */
+#define	DB_REP_UNAVAIL		(-30978)/* Site cannot currently be reached. */
+#define	DB_RUNRECOVERY		(-30977)/* Panic return. */
+#define	DB_SECONDARY_BAD	(-30976)/* Secondary index corrupt. */
+#define	DB_VERIFY_BAD		(-30975)/* Verify failed; bad format. */
+#define	DB_VERSION_MISMATCH	(-30974)/* Environment version mismatch. */
 
 /* DB (private) error return codes. */
 #define	DB_ALREADY_ABORTED	(-30899)
 #define	DB_DELETED		(-30898)/* Recovery file marked deleted. */
-#define	DB_JAVA_CALLBACK	(-30897)/* Exception during a java callback. */
-#define	DB_LOCK_NOTEXIST	(-30896)/* Object to lock is gone. */
-#define	DB_NEEDSPLIT		(-30895)/* Page needs to be split. */
-#define	DB_SURPRISE_KID		(-30894)/* Child commit where parent
+#define	DB_LOCK_NOTEXIST	(-30897)/* Object to lock is gone. */
+#define	DB_NEEDSPLIT		(-30896)/* Page needs to be split. */
+#define	DB_REP_EGENCHG		(-30895)/* Egen changed while in election. */
+#define	DB_REP_LOGREADY		(-30894)/* Rep log ready for recovery. */
+#define	DB_REP_PAGEDONE		(-30893)/* This page was already done. */
+#define	DB_SURPRISE_KID		(-30892)/* Child commit where parent
 					   didn't know it was a parent. */
-#define	DB_SWAPBYTES		(-30893)/* Database needs byte swapping. */
-#define	DB_TIMEOUT		(-30892)/* Timed out waiting for election. */
-#define	DB_TXN_CKP		(-30891)/* Encountered ckp record in log. */
-#define	DB_VERIFY_FATAL		(-30890)/* DB->verify cannot proceed. */
+#define	DB_SWAPBYTES		(-30891)/* Database needs byte swapping. */
+#define	DB_TIMEOUT		(-30890)/* Timed out waiting for election. */
+#define	DB_TXN_CKP		(-30889)/* Encountered ckp record in log. */
+#define	DB_VERIFY_FATAL		(-30888)/* DB->verify cannot proceed. */
 
 /* Database handle. */
 struct __db {
@@ -1048,10 +1249,12 @@ struct __db {
 	DBTYPE	 type;			/* DB access method type. */
 
 	DB_MPOOLFILE *mpf;		/* Backing buffer pool. */
-	DB_CACHE_PRIORITY priority;	/* Priority in the buffer pool. */
 
 	DB_MUTEX *mutexp;		/* Synchronization for free threading */
 
+	char *fname, *dname;		/* File/database passed to DB->open. */
+	u_int32_t open_flags;		/* Flags passed to DB->open. */
+
 	u_int8_t fileid[DB_FILE_ID_LEN];/* File's unique ID for locking. */
 
 	u_int32_t adj_fileid;		/* File's unique ID for curs. adj. */
@@ -1065,7 +1268,9 @@ struct __db {
 	u_int32_t associate_lid;	/* Locker id for DB->associate call. */
 	DB_LOCK	handle_lock;		/* Lock held on this handle. */
 
-	long	 cl_id;			/* RPC: remote client id. */
+	u_int	 cl_id;			/* RPC: remote client id. */
+
+	time_t	 timestamp;		/* Handle timestamp for replication. */
 
 	/*
 	 * Returned data memory for DB->get() and friends.
@@ -1176,12 +1381,25 @@ struct __db {
 	int  (*close) __P((DB *, u_int32_t));
 	int  (*cursor) __P((DB *, DB_TXN *, DBC **, u_int32_t));
 	int  (*del) __P((DB *, DB_TXN *, DBT *, u_int32_t));
+	int  (*dump) __P((DB *,
+		const char *, int (*)(void *, const void *), void *, int, int));
 	void (*err) __P((DB *, int, const char *, ...));
 	void (*errx) __P((DB *, const char *, ...));
 	int  (*fd) __P((DB *, int *));
 	int  (*get) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
 	int  (*pget) __P((DB *, DB_TXN *, DBT *, DBT *, DBT *, u_int32_t));
 	int  (*get_byteswapped) __P((DB *, int *));
+	int  (*get_cachesize) __P((DB *, u_int32_t *, u_int32_t *, int *));
+	int  (*get_dbname) __P((DB *, const char **, const char **));
+	int  (*get_encrypt_flags) __P((DB *, u_int32_t *));
+	DB_ENV *(*get_env) __P((DB *));
+	void (*get_errfile) __P((DB *, FILE **));
+	void (*get_errpfx) __P((DB *, const char **));
+	int  (*get_flags) __P((DB *, u_int32_t *));
+	int  (*get_lorder) __P((DB *, int *));
+	int  (*get_open_flags) __P((DB *, u_int32_t *));
+	int  (*get_pagesize) __P((DB *, u_int32_t *));
+	int  (*get_transactional) __P((DB *));
 	int  (*get_type) __P((DB *, DBTYPE *));
 	int  (*join) __P((DB *, DBC **, DBC **, u_int32_t));
 	int  (*key_range) __P((DB *,
@@ -1197,24 +1415,29 @@ struct __db {
 	int  (*set_alloc) __P((DB *, void *(*)(size_t),
 		void *(*)(void *, size_t), void (*)(void *)));
 	int  (*set_cachesize) __P((DB *, u_int32_t, u_int32_t, int));
-	int  (*set_cache_priority) __P((DB *, DB_CACHE_PRIORITY));
 	int  (*set_dup_compare) __P((DB *,
 	    int (*)(DB *, const DBT *, const DBT *)));
 	int  (*set_encrypt) __P((DB *, const char *, u_int32_t));
-	void (*set_errcall) __P((DB *, void (*)(const char *, char *)));
+	void (*set_errcall) __P((DB *,
+	    void (*)(const DB_ENV *, const char *, const char *)));
 	void (*set_errfile) __P((DB *, FILE *));
 	void (*set_errpfx) __P((DB *, const char *));
 	int  (*set_feedback) __P((DB *, void (*)(DB *, int, int)));
 	int  (*set_flags) __P((DB *, u_int32_t));
 	int  (*set_lorder) __P((DB *, int));
+	void (*set_msgcall) __P((DB *, void (*)(const DB_ENV *, const char *)));
+	void (*get_msgfile) __P((DB *, FILE **));
+	void (*set_msgfile) __P((DB *, FILE *));
 	int  (*set_pagesize) __P((DB *, u_int32_t));
 	int  (*set_paniccall) __P((DB *, void (*)(DB_ENV *, int)));
-	int  (*stat) __P((DB *, void *, u_int32_t));
+	int  (*stat) __P((DB *, DB_TXN *, void *, u_int32_t));
+	int  (*stat_print) __P((DB *, u_int32_t));
 	int  (*sync) __P((DB *, u_int32_t));
 	int  (*upgrade) __P((DB *, const char *, u_int32_t));
 	int  (*verify) __P((DB *,
 	    const char *, const char *, FILE *, u_int32_t));
 
+	int  (*get_bt_minkey) __P((DB *, u_int32_t *));
 	int  (*set_bt_compare) __P((DB *,
 	    int (*)(DB *, const DBT *, const DBT *)));
 	int  (*set_bt_maxkey) __P((DB *, u_int32_t));
@@ -1222,19 +1445,26 @@ struct __db {
 	int  (*set_bt_prefix) __P((DB *,
 	    size_t (*)(DB *, const DBT *, const DBT *)));
 
+	int  (*get_h_ffactor) __P((DB *, u_int32_t *));
+	int  (*get_h_nelem) __P((DB *, u_int32_t *));
 	int  (*set_h_ffactor) __P((DB *, u_int32_t));
 	int  (*set_h_hash) __P((DB *,
 	    u_int32_t (*)(DB *, const void *, u_int32_t)));
 	int  (*set_h_nelem) __P((DB *, u_int32_t));
 
+	int  (*get_re_delim) __P((DB *, int *));
+	int  (*get_re_len) __P((DB *, u_int32_t *));
+	int  (*get_re_pad) __P((DB *, int *));
+	int  (*get_re_source) __P((DB *, const char **));
 	int  (*set_re_delim) __P((DB *, int));
 	int  (*set_re_len) __P((DB *, u_int32_t));
 	int  (*set_re_pad) __P((DB *, int));
 	int  (*set_re_source) __P((DB *, const char *));
+
+	int  (*get_q_extentsize) __P((DB *, u_int32_t *));
 	int  (*set_q_extentsize) __P((DB *, u_int32_t));
 
-	int  (*db_am_remove) __P((DB *,
-	    DB_TXN *, const char *, const char *, DB_LSN *));
+	int  (*db_am_remove) __P((DB *, DB_TXN *, const char *, const char *));
 	int  (*db_am_rename) __P((DB *, DB_TXN *,
 	    const char *, const char *, const char *));
 
@@ -1265,32 +1495,35 @@ struct __db {
 #define	DB_AM_ENCRYPT		0x00000800 /* Encryption. */
 #define	DB_AM_FIXEDLEN		0x00001000 /* Fixed-length records. */
 #define	DB_AM_INMEM		0x00002000 /* In-memory; no sync on close. */
-#define	DB_AM_IN_RENAME		0x00004000 /* File is being renamed. */
-#define	DB_AM_OPEN_CALLED	0x00008000 /* DB->open called. */
-#define	DB_AM_PAD		0x00010000 /* Fixed-length record pad. */
-#define	DB_AM_PGDEF		0x00020000 /* Page size was defaulted. */
-#define	DB_AM_RDONLY		0x00040000 /* Database is readonly. */
-#define	DB_AM_RECNUM		0x00080000 /* DB_RECNUM. */
-#define	DB_AM_RECOVER		0x00100000 /* DB opened by recovery routine. */
-#define	DB_AM_RENUMBER		0x00200000 /* DB_RENUMBER. */
-#define	DB_AM_REVSPLITOFF	0x00400000 /* DB_REVSPLITOFF. */
-#define	DB_AM_SECONDARY		0x00800000 /* Database is a secondary index. */
-#define	DB_AM_SNAPSHOT		0x01000000 /* DB_SNAPSHOT. */
-#define	DB_AM_SUBDB		0x02000000 /* Subdatabases supported. */
-#define	DB_AM_SWAP		0x04000000 /* Pages need to be byte-swapped. */
-#define	DB_AM_TXN		0x08000000 /* Opened in a transaction. */
-#define	DB_AM_VERIFYING		0x10000000 /* DB handle is in the verifier. */
+#define	DB_AM_INORDER		0x00004000 /* DB_INORDER. */
+#define	DB_AM_IN_RENAME		0x00008000 /* File is being renamed. */
+#define	DB_AM_NOT_DURABLE	0x00010000 /* Do not log changes. */
+#define	DB_AM_OPEN_CALLED	0x00020000 /* DB->open called. */
+#define	DB_AM_PAD		0x00040000 /* Fixed-length record pad. */
+#define	DB_AM_PGDEF		0x00080000 /* Page size was defaulted. */
+#define	DB_AM_RDONLY		0x00100000 /* Database is readonly. */
+#define	DB_AM_RECNUM		0x00200000 /* DB_RECNUM. */
+#define	DB_AM_RECOVER		0x00400000 /* DB opened by recovery routine. */
+#define	DB_AM_RENUMBER		0x00800000 /* DB_RENUMBER. */
+#define	DB_AM_REPLICATION	0x01000000 /* An internal replication file. */
+#define	DB_AM_REVSPLITOFF	0x02000000 /* DB_REVSPLITOFF. */
+#define	DB_AM_SECONDARY		0x04000000 /* Database is a secondary index. */
+#define	DB_AM_SNAPSHOT		0x08000000 /* DB_SNAPSHOT. */
+#define	DB_AM_SUBDB		0x10000000 /* Subdatabases supported. */
+#define	DB_AM_SWAP		0x20000000 /* Pages need to be byte-swapped. */
+#define	DB_AM_TXN		0x40000000 /* Opened in a transaction. */
+#define	DB_AM_VERIFYING		0x80000000 /* DB handle is in the verifier. */
+	u_int32_t orig_flags;		   /* Flags at  open, for refresh. */
 	u_int32_t flags;
 };
 
 /*
- * Macros for bulk get.  Note that wherever we use a DBT *, we explicitly
- * cast it; this allows the same macros to work with C++ Dbt *'s, as Dbt
- * is a subclass of struct DBT in C++.
+ * Macros for bulk get.  These are only intended for the C API.
+ * For C++, use DbMultiple*Iterator.
  */
 #define	DB_MULTIPLE_INIT(pointer, dbt)					\
-	(pointer = (u_int8_t *)((DBT *)(dbt))->data +			\
-	    ((DBT *)(dbt))->ulen - sizeof(u_int32_t))
+	(pointer = (u_int8_t *)(dbt)->data +				\
+	    (dbt)->ulen - sizeof(u_int32_t))
 #define	DB_MULTIPLE_NEXT(pointer, dbt, retdata, retdlen)		\
 	do {								\
 		if (*((u_int32_t *)(pointer)) == (u_int32_t)-1) {	\
@@ -1299,12 +1532,12 @@ struct __db {
 			break;						\
 		}							\
 		retdata = (u_int8_t *)					\
-		    ((DBT *)(dbt))->data + *(u_int32_t *)(pointer);	\
+		    (dbt)->data + *(u_int32_t *)(pointer);		\
 		(pointer) = (u_int32_t *)(pointer) - 1;			\
 		retdlen = *(u_int32_t *)(pointer);			\
 		(pointer) = (u_int32_t *)(pointer) - 1;			\
 		if (retdlen == 0 &&					\
-		    retdata == (u_int8_t *)((DBT *)(dbt))->data)	\
+		    retdata == (u_int8_t *)(dbt)->data)			\
 			retdata = NULL;					\
 	} while (0)
 #define	DB_MULTIPLE_KEY_NEXT(pointer, dbt, retkey, retklen, retdata, retdlen) \
@@ -1316,12 +1549,12 @@ struct __db {
 			break;						\
 		}							\
 		retkey = (u_int8_t *)					\
-		    ((DBT *)(dbt))->data + *(u_int32_t *)(pointer);	\
+		    (dbt)->data + *(u_int32_t *)(pointer);		\
 		(pointer) = (u_int32_t *)(pointer) - 1;			\
 		retklen = *(u_int32_t *)(pointer);			\
 		(pointer) = (u_int32_t *)(pointer) - 1;			\
 		retdata = (u_int8_t *)					\
-		    ((DBT *)(dbt))->data + *(u_int32_t *)(pointer);	\
+		    (dbt)->data + *(u_int32_t *)(pointer);		\
 		(pointer) = (u_int32_t *)(pointer) - 1;			\
 		retdlen = *(u_int32_t *)(pointer);			\
 		(pointer) = (u_int32_t *)(pointer) - 1;			\
@@ -1338,7 +1571,7 @@ struct __db {
 		recno = *(u_int32_t *)(pointer);			\
 		(pointer) = (u_int32_t *)(pointer) - 1;			\
 		retdata = (u_int8_t *)					\
-		    ((DBT *)(dbt))->data + *(u_int32_t *)(pointer);	\
+		    (dbt)->data + *(u_int32_t *)(pointer);		\
 		(pointer) = (u_int32_t *)(pointer) - 1;			\
 		retdlen = *(u_int32_t *)(pointer);			\
 		(pointer) = (u_int32_t *)(pointer) - 1;			\
@@ -1386,9 +1619,9 @@ struct __dbc {
 	u_int32_t locker;		/* Locker for this operation. */
 	DBT	  lock_dbt;		/* DBT referencing lock. */
 	DB_LOCK_ILOCK lock;		/* Object to be locked. */
-	DB_LOCK	  mylock;		/* Lock held on this cursor. */
+	DB_LOCK	  mylock;		/* CDB lock held on this cursor. */
 
-	long	  cl_id;		/* Remote client id. */
+	u_int	  cl_id;		/* Remote client id. */
 
 	DBTYPE	  dbtype;		/* Cursor type. */
 
@@ -1411,18 +1644,15 @@ struct __dbc {
 	int (*c_am_put) __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *));
 	int (*c_am_writelock) __P((DBC *));
 
-	/* Private: for secondary indices. */
-	int (*c_real_get) __P((DBC *, DBT *, DBT *, u_int32_t));
-
 #define	DBC_ACTIVE	 0x0001		/* Cursor in use. */
 #define	DBC_COMPENSATE	 0x0002		/* Cursor compensating, don't lock. */
-#define	DBC_DIRTY_READ	 0x0004		/* Cursor supports dirty reads. */
-#define	DBC_OPD		 0x0008		/* Cursor references off-page dups. */
-#define	DBC_RECOVER	 0x0010		/* Recovery cursor; don't log/lock. */
-#define	DBC_RMW		 0x0020		/* Acquire write flag in read op. */
-#define	DBC_TRANSIENT	 0x0040		/* Cursor is transient. */
-#define	DBC_WRITECURSOR	 0x0080		/* Cursor may be used to write (CDB). */
-#define	DBC_WRITEDUP	 0x0100		/* idup'ed DBC_WRITECURSOR (CDB). */
+#define	DBC_DEGREE_2	 0x0004		/* Cursor has degree 2 isolation. */
+#define	DBC_DIRTY_READ	 0x0008		/* Cursor supports dirty reads. */
+#define	DBC_OPD		 0x0010		/* Cursor references off-page dups. */
+#define	DBC_RECOVER	 0x0020		/* Recovery cursor; don't log/lock. */
+#define	DBC_RMW		 0x0040		/* Acquire write flag in read op. */
+#define	DBC_TRANSIENT	 0x0080		/* Cursor is transient. */
+#define	DBC_WRITECURSOR	 0x0100		/* Cursor may be used to write (CDB). */
 #define	DBC_WRITER	 0x0200		/* Cursor immediately writing (CDB). */
 #define	DBC_MULTIPLE	 0x0400		/* Return Multiple data. */
 #define	DBC_MULTIPLE_KEY 0x0800		/* Return Multiple keys and data. */
@@ -1454,6 +1684,7 @@ struct __db_bt_stat {
 	u_int32_t bt_leaf_pg;		/* Leaf pages. */
 	u_int32_t bt_dup_pg;		/* Duplicate pages. */
 	u_int32_t bt_over_pg;		/* Overflow pages. */
+	u_int32_t bt_empty_pg;		/* Empty pages. */
 	u_int32_t bt_free;		/* Pages on the free list. */
 	u_int32_t bt_int_pgfree;	/* Bytes free in internal pages. */
 	u_int32_t bt_leaf_pgfree;	/* Bytes free in leaf pages. */
@@ -1503,22 +1734,23 @@ struct __db_qam_stat {
  *******************************************************/
 #define	DB_REGION_MAGIC	0x120897	/* Environment magic number. */
 
-typedef enum {
-	DB_NOTICE_LOGFILE_CHANGED
-} db_notices;
-
 /* Database Environment handle. */
 struct __db_env {
 	/*******************************************************
 	 * Public: owned by the application.
 	 *******************************************************/
+					/* Error message callback. */
+	void (*db_errcall) __P((const DB_ENV *, const char *, const char *));
 	FILE		*db_errfile;	/* Error message file stream. */
 	const char	*db_errpfx;	/* Error message prefix. */
-					/* Callbacks. */
-	void (*db_errcall) __P((const char *, char *));
+
+	FILE		*db_msgfile;	/* Statistics message file stream. */
+					/* Statistics message callback. */
+	void (*db_msgcall) __P((const DB_ENV *, const char *));
+
+					/* Other Callbacks. */
 	void (*db_feedback) __P((DB_ENV *, int, int));
 	void (*db_paniccall) __P((DB_ENV *, int));
-	void (*db_noticecall) __P((DB_ENV *, db_notices));
 
 					/* App-specified alloc functions. */
 	void *(*db_malloc) __P((size_t));
@@ -1530,11 +1762,10 @@ struct __db_env {
 	 * entries.  There's no reason that it needs to be limited, if
 	 * there are ever more than 32 entries, convert to a bit array.
 	 */
-#define	DB_VERB_CHKPOINT	0x0001	/* List checkpoints. */
-#define	DB_VERB_DEADLOCK	0x0002	/* Deadlock detection information. */
-#define	DB_VERB_RECOVERY	0x0004	/* Recovery information. */
-#define	DB_VERB_REPLICATION	0x0008	/* Replication information. */
-#define	DB_VERB_WAITSFOR	0x0010	/* Dump waits-for table. */
+#define	DB_VERB_DEADLOCK	0x0001	/* Deadlock detection information. */
+#define	DB_VERB_RECOVERY	0x0002	/* Recovery information. */
+#define	DB_VERB_REPLICATION	0x0004	/* Replication information. */
+#define	DB_VERB_WAITSFOR	0x0008	/* Dump waits-for table. */
 	u_int32_t	 verbose;	/* Verbose output. */
 
 	void		*app_private;	/* Application-private handle. */
@@ -1544,7 +1775,7 @@ struct __db_env {
 
 	/* Locking. */
 	u_int8_t	*lk_conflicts;	/* Two dimensional conflict matrix. */
-	u_int32_t	 lk_modes;	/* Number of lock modes in table. */
+	int		 lk_modes;	/* Number of lock modes in table. */
 	u_int32_t	 lk_max;	/* Maximum number of locks. */
 	u_int32_t	 lk_max_lockers;/* Maximum number of lockers. */
 	u_int32_t	 lk_max_objects;/* Maximum number of locked objects. */
@@ -1559,11 +1790,18 @@ struct __db_env {
 	/* Memory pool. */
 	u_int32_t	 mp_gbytes;	/* Cachesize: GB. */
 	u_int32_t	 mp_bytes;	/* Cachesize: Bytes. */
-	size_t		 mp_size;	/* DEPRECATED: Cachesize: bytes. */
-	int		 mp_ncache;	/* Number of cache regions. */
+	u_int		 mp_ncache;	/* Number of cache regions. */
 	size_t		 mp_mmapsize;	/* Maximum file size for mmap. */
+	int		 mp_maxopenfd;	/* Maximum open file descriptors. */
+	int		 mp_maxwrite;	/* Maximum buffers to write. */
+	int				/* Sleep after writing max buffers. */
+			 mp_maxwrite_sleep;
 
+	/* Replication */
 	int		 rep_eid;	/* environment id. */
+	int		(*rep_send)	/* Send function. */
+			    __P((DB_ENV *, const DBT *, const DBT *,
+			    const DB_LSN *, int, u_int32_t));
 
 	/* Transactions. */
 	u_int32_t	 tx_max;	/* Maximum number of transactions. */
@@ -1573,8 +1811,6 @@ struct __db_env {
 	/*******************************************************
 	 * Private: owned by DB.
 	 *******************************************************/
-	int		 panic_errval;	/* Panic causing errno. */
-
 					/* User files, paths. */
 	char		*db_home;	/* Database home. */
 	char		*db_log_dir;	/* Database log file directory. */
@@ -1585,6 +1821,9 @@ struct __db_env {
 	int		 data_next;	/* Next Database data file slot. */
 
 	int		 db_mode;	/* Default open permissions. */
+	int		 dir_mode;	/* Intermediate directory perms. */
+	u_int32_t	 env_lid;	/* Locker ID in non-threaded handles. */
+	u_int32_t	 open_flags;	/* Flags passed to DB_ENV->open. */
 
 	void		*reginfo;	/* REGINFO structure reference. */
 	DB_FH		*lockfhp;	/* fcntl(2) locking file handle. */
@@ -1595,7 +1834,7 @@ struct __db_env {
 					/* Slots in the dispatch table. */
 
 	void		*cl_handle;	/* RPC: remote client handle. */
-	long		 cl_id;		/* RPC: remote client env id. */
+	u_int		 cl_id;		/* RPC: remote client env id. */
 
 	int		 db_ref;	/* DB reference count. */
 
@@ -1626,13 +1865,17 @@ struct __db_env {
 	 * !!!
 	 * Explicit representations of structures from queue.h.
 	 * TAILQ_ENTRY(__db_env) links;
+	 * TAILQ_HEAD(xa_txn, __db_txn);
 	 */
 	struct {
 		struct __db_env *tqe_next;
 		struct __db_env **tqe_prev;
 	} links;
+	struct __xa_txn {	/* XA Active Transactions. */
+		struct __db_txn *tqh_first;
+		struct __db_txn **tqh_last;
+	} xa_txn;
 	int		 xa_rmid;	/* XA Resource Manager ID. */
-	DB_TXN		*xa_txn;	/* XA Current transaction. */
 
 	/* API-private structure. */
 	void		*api1_internal;	/* C++, Perl API private */
@@ -1648,37 +1891,67 @@ struct __db_env {
 					/* DB_ENV Methods. */
 	int  (*close) __P((DB_ENV *, u_int32_t));
 	int  (*dbremove) __P((DB_ENV *,
-	    DB_TXN *, const char *, const char *, u_int32_t));
+		DB_TXN *, const char *, const char *, u_int32_t));
 	int  (*dbrename) __P((DB_ENV *, DB_TXN *,
-	    const char *, const char *, const char *, u_int32_t));
+		const char *, const char *, const char *, u_int32_t));
 	void (*err) __P((const DB_ENV *, int, const char *, ...));
 	void (*errx) __P((const DB_ENV *, const char *, ...));
 	int  (*open) __P((DB_ENV *, const char *, u_int32_t, int));
 	int  (*remove) __P((DB_ENV *, const char *, u_int32_t));
-	int  (*set_data_dir) __P((DB_ENV *, const char *));
+	int  (*stat_print) __P((DB_ENV *, u_int32_t));
+
+					/* House-keeping. */
+	int  (*fileid_reset) __P((DB_ENV *, char *, int));
+	int  (*is_bigendian) __P((void));
+	int  (*lsn_reset) __P((DB_ENV *, char *, int));
+	int  (*prdbt) __P((DBT *,
+		int, const char *, void *, int (*)(void *, const void *), int));
+
+					/* Setters/getters. */
 	int  (*set_alloc) __P((DB_ENV *, void *(*)(size_t),
 		void *(*)(void *, size_t), void (*)(void *)));
 	int  (*set_app_dispatch) __P((DB_ENV *,
 		int (*)(DB_ENV *, DBT *, DB_LSN *, db_recops)));
+	int  (*get_data_dirs) __P((DB_ENV *, const char ***));
+	int  (*set_data_dir) __P((DB_ENV *, const char *));
+	int  (*get_encrypt_flags) __P((DB_ENV *, u_int32_t *));
 	int  (*set_encrypt) __P((DB_ENV *, const char *, u_int32_t));
-	void (*set_errcall) __P((DB_ENV *, void (*)(const char *, char *)));
+	void (*set_errcall) __P((DB_ENV *,
+	    void (*)(const DB_ENV *, const char *, const char *)));
+	void (*get_errfile) __P((DB_ENV *, FILE **));
 	void (*set_errfile) __P((DB_ENV *, FILE *));
+	void (*get_errpfx) __P((DB_ENV *, const char **));
 	void (*set_errpfx) __P((DB_ENV *, const char *));
 	int  (*set_feedback) __P((DB_ENV *, void (*)(DB_ENV *, int, int)));
+	int  (*get_flags) __P((DB_ENV *, u_int32_t *));
 	int  (*set_flags) __P((DB_ENV *, u_int32_t, int));
-	void (*set_noticecall) __P((DB_ENV *, void (*)(DB_ENV *, db_notices)));
+	int  (*get_home) __P((DB_ENV *, const char **));
+	int  (*set_intermediate_dir) __P((DB_ENV *, int, u_int32_t));
+	int  (*get_open_flags) __P((DB_ENV *, u_int32_t *));
 	int  (*set_paniccall) __P((DB_ENV *, void (*)(DB_ENV *, int)));
 	int  (*set_rpc_server) __P((DB_ENV *,
 		void *, const char *, long, long, u_int32_t));
+	int  (*get_shm_key) __P((DB_ENV *, long *));
 	int  (*set_shm_key) __P((DB_ENV *, long));
+	void (*set_msgcall) __P((DB_ENV *,
+		void (*)(const DB_ENV *, const char *)));
+	void (*get_msgfile) __P((DB_ENV *, FILE **));
+	void (*set_msgfile) __P((DB_ENV *, FILE *));
+	int  (*get_tas_spins) __P((DB_ENV *, u_int32_t *));
 	int  (*set_tas_spins) __P((DB_ENV *, u_int32_t));
+	int  (*get_tmp_dir) __P((DB_ENV *, const char **));
 	int  (*set_tmp_dir) __P((DB_ENV *, const char *));
+	int  (*get_verbose) __P((DB_ENV *, u_int32_t, int *));
 	int  (*set_verbose) __P((DB_ENV *, u_int32_t, int));
 
 	void *lg_handle;		/* Log handle and methods. */
+	int  (*get_lg_bsize) __P((DB_ENV *, u_int32_t *));
 	int  (*set_lg_bsize) __P((DB_ENV *, u_int32_t));
+	int  (*get_lg_dir) __P((DB_ENV *, const char **));
 	int  (*set_lg_dir) __P((DB_ENV *, const char *));
+	int  (*get_lg_max) __P((DB_ENV *, u_int32_t *));
 	int  (*set_lg_max) __P((DB_ENV *, u_int32_t));
+	int  (*get_lg_regionmax) __P((DB_ENV *, u_int32_t *));
 	int  (*set_lg_regionmax) __P((DB_ENV *, u_int32_t));
 	int  (*log_archive) __P((DB_ENV *, char **[], u_int32_t));
 	int  (*log_cursor) __P((DB_ENV *, DB_LOGC **, u_int32_t));
@@ -1686,83 +1959,92 @@ struct __db_env {
 	int  (*log_flush) __P((DB_ENV *, const DB_LSN *));
 	int  (*log_put) __P((DB_ENV *, DB_LSN *, const DBT *, u_int32_t));
 	int  (*log_stat) __P((DB_ENV *, DB_LOG_STAT **, u_int32_t));
+	int  (*log_stat_print) __P((DB_ENV *, u_int32_t));
 
 	void *lk_handle;		/* Lock handle and methods. */
+	int  (*get_lk_conflicts) __P((DB_ENV *, const u_int8_t **, int *));
 	int  (*set_lk_conflicts) __P((DB_ENV *, u_int8_t *, int));
+	int  (*get_lk_detect) __P((DB_ENV *, u_int32_t *));
 	int  (*set_lk_detect) __P((DB_ENV *, u_int32_t));
 	int  (*set_lk_max) __P((DB_ENV *, u_int32_t));
+	int  (*get_lk_max_locks) __P((DB_ENV *, u_int32_t *));
 	int  (*set_lk_max_locks) __P((DB_ENV *, u_int32_t));
+	int  (*get_lk_max_lockers) __P((DB_ENV *, u_int32_t *));
 	int  (*set_lk_max_lockers) __P((DB_ENV *, u_int32_t));
+	int  (*get_lk_max_objects) __P((DB_ENV *, u_int32_t *));
 	int  (*set_lk_max_objects) __P((DB_ENV *, u_int32_t));
 	int  (*lock_detect) __P((DB_ENV *, u_int32_t, u_int32_t, int *));
-	int  (*lock_dump_region) __P((DB_ENV *, char *, FILE *));
 	int  (*lock_get) __P((DB_ENV *,
 		u_int32_t, u_int32_t, const DBT *, db_lockmode_t, DB_LOCK *));
 	int  (*lock_put) __P((DB_ENV *, DB_LOCK *));
 	int  (*lock_id) __P((DB_ENV *, u_int32_t *));
 	int  (*lock_id_free) __P((DB_ENV *, u_int32_t));
-	int  (*lock_id_set) __P((DB_ENV *, u_int32_t, u_int32_t));
 	int  (*lock_stat) __P((DB_ENV *, DB_LOCK_STAT **, u_int32_t));
+	int  (*lock_stat_print) __P((DB_ENV *, u_int32_t));
 	int  (*lock_vec) __P((DB_ENV *,
 		u_int32_t, u_int32_t, DB_LOCKREQ *, int, DB_LOCKREQ **));
-	int  (*lock_downgrade) __P((DB_ENV *,
-		DB_LOCK *, db_lockmode_t, u_int32_t));
 
 	void *mp_handle;		/* Mpool handle and methods. */
-	int  (*set_mp_mmapsize) __P((DB_ENV *, size_t));
+	int  (*get_cachesize) __P((DB_ENV *, u_int32_t *, u_int32_t *, int *));
 	int  (*set_cachesize) __P((DB_ENV *, u_int32_t, u_int32_t, int));
-	int  (*memp_dump_region) __P((DB_ENV *, char *, FILE *));
+	int  (*get_mp_mmapsize) __P((DB_ENV *, size_t *));
+	int  (*set_mp_mmapsize) __P((DB_ENV *, size_t));
+	int  (*get_mp_max_openfd) __P((DB_ENV *, int *));
+	int  (*set_mp_max_openfd) __P((DB_ENV *, int));
+	int  (*get_mp_max_write) __P((DB_ENV *, int *, int *));
+	int  (*set_mp_max_write) __P((DB_ENV *, int, int));
 	int  (*memp_fcreate) __P((DB_ENV *, DB_MPOOLFILE **, u_int32_t));
-	int  (*memp_nameop) __P((DB_ENV *,
-		u_int8_t *, const char *, const char *, const char *));
 	int  (*memp_register) __P((DB_ENV *, int,
 		int (*)(DB_ENV *, db_pgno_t, void *, DBT *),
 		int (*)(DB_ENV *, db_pgno_t, void *, DBT *)));
 	int  (*memp_stat) __P((DB_ENV *,
 		DB_MPOOL_STAT **, DB_MPOOL_FSTAT ***, u_int32_t));
+	int  (*memp_stat_print) __P((DB_ENV *, u_int32_t));
 	int  (*memp_sync) __P((DB_ENV *, DB_LSN *));
 	int  (*memp_trickle) __P((DB_ENV *, int, int *));
 
 	void *rep_handle;		/* Replication handle and methods. */
-	int  (*rep_elect) __P((DB_ENV *, int, int, u_int32_t, int *));
+	int  (*rep_elect) __P((DB_ENV *, int, int, int,
+		u_int32_t, int *, u_int32_t));
 	int  (*rep_flush) __P((DB_ENV *));
-	int  (*rep_process_message) __P((DB_ENV *, DBT *, DBT *, int *));
+	int  (*rep_process_message) __P((DB_ENV *, DBT *, DBT *,
+	    int *, DB_LSN *));
 	int  (*rep_start) __P((DB_ENV *, DBT *, u_int32_t));
 	int  (*rep_stat) __P((DB_ENV *, DB_REP_STAT **, u_int32_t));
-	int  (*set_rep_election) __P((DB_ENV *,
-		u_int32_t, u_int32_t, u_int32_t, u_int32_t));
+	int  (*rep_stat_print) __P((DB_ENV *, u_int32_t));
+	int  (*get_rep_limit) __P((DB_ENV *, u_int32_t *, u_int32_t *));
 	int  (*set_rep_limit) __P((DB_ENV *, u_int32_t, u_int32_t));
 	int  (*set_rep_request) __P((DB_ENV *, u_int32_t, u_int32_t));
-	int  (*set_rep_timeout) __P((DB_ENV *, u_int32_t, u_int32_t));
 	int  (*set_rep_transport) __P((DB_ENV *, int,
-		int (*) (DB_ENV *, const DBT *, const DBT *, int, u_int32_t)));
+		int (*) (DB_ENV *, const DBT *, const DBT *, const DB_LSN *,
+		int, u_int32_t)));
 
 	void *tx_handle;		/* Txn handle and methods. */
+	int  (*get_tx_max) __P((DB_ENV *, u_int32_t *));
 	int  (*set_tx_max) __P((DB_ENV *, u_int32_t));
+	int  (*get_tx_timestamp) __P((DB_ENV *, time_t *));
 	int  (*set_tx_timestamp) __P((DB_ENV *, time_t *));
 	int  (*txn_begin) __P((DB_ENV *, DB_TXN *, DB_TXN **, u_int32_t));
 	int  (*txn_checkpoint) __P((DB_ENV *, u_int32_t, u_int32_t, u_int32_t));
-	int  (*txn_id_set) __P((DB_ENV *, u_int32_t, u_int32_t));
 	int  (*txn_recover) __P((DB_ENV *,
 		DB_PREPLIST *, long, long *, u_int32_t));
 	int  (*txn_stat) __P((DB_ENV *, DB_TXN_STAT **, u_int32_t));
+	int  (*txn_stat_print) __P((DB_ENV *, u_int32_t));
+	int  (*get_timeout) __P((DB_ENV *, db_timeout_t *, u_int32_t));
 	int  (*set_timeout) __P((DB_ENV *, db_timeout_t, u_int32_t));
 
 #define	DB_TEST_ELECTINIT	 1	/* after __rep_elect_init */
-#define	DB_TEST_ELECTSEND	 2	/* after REP_ELECT msgnit */
-#define	DB_TEST_ELECTVOTE1	 3	/* after __rep_send_vote 1 */
-#define	DB_TEST_ELECTVOTE2	 4	/* after __rep_wait */
-#define	DB_TEST_ELECTWAIT1	 5	/* after REP_VOTE2 */
-#define	DB_TEST_ELECTWAIT2	 6	/* after __rep_wait 2 */
-#define	DB_TEST_PREDESTROY	 7	/* before destroy op */
-#define	DB_TEST_PREOPEN		 8	/* before __os_open */
-#define	DB_TEST_POSTDESTROY	 9	/* after destroy op */
-#define	DB_TEST_POSTLOG		 10	/* after logging all pages */
-#define	DB_TEST_POSTLOGMETA	 11	/* after logging meta in btree */
-#define	DB_TEST_POSTOPEN	 12	/* after __os_open */
-#define	DB_TEST_POSTSYNC	 13	/* after syncing the log */
-#define	DB_TEST_SUBDB_LOCKS	 14	/* subdb locking tests */
+#define	DB_TEST_ELECTVOTE1	 2	/* after sending VOTE1 */
+#define	DB_TEST_POSTDESTROY	 3	/* after destroy op */
+#define	DB_TEST_POSTLOG		 4	/* after logging all pages */
+#define	DB_TEST_POSTLOGMETA	 5	/* after logging meta in btree */
+#define	DB_TEST_POSTOPEN	 6	/* after __os_open */
+#define	DB_TEST_POSTSYNC	 7	/* after syncing the log */
+#define	DB_TEST_PREDESTROY	 8	/* before destroy op */
+#define	DB_TEST_PREOPEN		 9	/* before __os_open */
+#define	DB_TEST_SUBDB_LOCKS	 10	/* subdb locking tests */
 	int		 test_abort;	/* Abort value for testing. */
+	int		 test_check;	/* Checkpoint value for testing. */
 	int		 test_copy;	/* Copy value for testing. */
 
 #define	DB_ENV_AUTO_COMMIT	0x0000001 /* DB_AUTO_COMMIT. */
@@ -1772,25 +2054,26 @@ struct __db_env {
 #define	DB_ENV_DBLOCAL		0x0000010 /* DB_ENV allocated for private DB. */
 #define	DB_ENV_DIRECT_DB	0x0000020 /* DB_DIRECT_DB set. */
 #define	DB_ENV_DIRECT_LOG	0x0000040 /* DB_DIRECT_LOG set. */
-#define	DB_ENV_FATAL		0x0000080 /* Doing fatal recovery in env. */
-#define	DB_ENV_LOCKDOWN		0x0000100 /* DB_LOCKDOWN set. */
-#define	DB_ENV_NOLOCKING	0x0000200 /* DB_NOLOCKING set. */
-#define	DB_ENV_NOMMAP		0x0000400 /* DB_NOMMAP set. */
-#define	DB_ENV_NOPANIC		0x0000800 /* Okay if panic set. */
-#define	DB_ENV_OPEN_CALLED	0x0001000 /* DB_ENV->open called. */
-#define	DB_ENV_OVERWRITE	0x0002000 /* DB_OVERWRITE set. */
-#define	DB_ENV_PRIVATE		0x0004000 /* DB_PRIVATE set. */
-#define	DB_ENV_REGION_INIT	0x0008000 /* DB_REGION_INIT set. */
-#define	DB_ENV_REP_CLIENT	0x0010000 /* Replication client. */
-#define	DB_ENV_REP_LOGSONLY	0x0020000 /* Log files only replication site. */
-#define	DB_ENV_REP_MASTER	0x0040000 /* Replication master. */
-#define	DB_ENV_RPCCLIENT	0x0080000 /* DB_CLIENT set. */
+#define	DB_ENV_DSYNC_LOG	0x0000080 /* DB_DSYNC_LOG set. */
+#define	DB_ENV_FATAL		0x0000100 /* Doing fatal recovery in env. */
+#define	DB_ENV_LOCKDOWN		0x0000200 /* DB_LOCKDOWN set. */
+#define	DB_ENV_LOG_AUTOREMOVE   0x0000400 /* DB_LOG_AUTOREMOVE set. */
+#define	DB_ENV_LOG_INMEMORY     0x0000800 /* DB_LOG_INMEMORY set. */
+#define	DB_ENV_NOLOCKING	0x0001000 /* DB_NOLOCKING set. */
+#define	DB_ENV_NOMMAP		0x0002000 /* DB_NOMMAP set. */
+#define	DB_ENV_NOPANIC		0x0004000 /* Okay if panic set. */
+#define	DB_ENV_OPEN_CALLED	0x0008000 /* DB_ENV->open called. */
+#define	DB_ENV_OVERWRITE	0x0010000 /* DB_OVERWRITE set. */
+#define	DB_ENV_PRIVATE		0x0020000 /* DB_PRIVATE set. */
+#define	DB_ENV_REGION_INIT	0x0040000 /* DB_REGION_INIT set. */
+#define	DB_ENV_RPCCLIENT	0x0080000 /* DB_RPCCLIENT set. */
 #define	DB_ENV_RPCCLIENT_GIVEN	0x0100000 /* User-supplied RPC client struct */
 #define	DB_ENV_SYSTEM_MEM	0x0200000 /* DB_SYSTEM_MEM set. */
 #define	DB_ENV_THREAD		0x0400000 /* DB_THREAD set. */
-#define	DB_ENV_TXN_NOSYNC	0x0800000 /* DB_TXN_NOSYNC set. */
-#define	DB_ENV_TXN_WRITE_NOSYNC	0x1000000 /* DB_TXN_WRITE_NOSYNC set. */
-#define	DB_ENV_YIELDCPU		0x2000000 /* DB_YIELDCPU set. */
+#define	DB_ENV_TIME_NOTGRANTED	0x0800000 /* DB_TIME_NOTGRANTED set. */
+#define	DB_ENV_TXN_NOSYNC	0x1000000 /* DB_TXN_NOSYNC set. */
+#define	DB_ENV_TXN_WRITE_NOSYNC	0x2000000 /* DB_TXN_WRITE_NOSYNC set. */
+#define	DB_ENV_YIELDCPU		0x4000000 /* DB_YIELDCPU set. */
 	u_int32_t flags;
 };
 
diff --git a/storage/bdb/dbinc/db_185.in b/storage/bdb/dbinc/db_185.in
index 86e2290c304a99257dcbdfe2457242a1d4087192..338455a601ad40547abeae0e7ee32a5d8a87893a 100644
--- a/storage/bdb/dbinc/db_185.in
+++ b/storage/bdb/dbinc/db_185.in
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -32,7 +32,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: db_185.in,v 11.8 2002/01/11 15:52:24 bostic Exp $
+ * $Id: db_185.in,v 11.11 2004/01/28 03:36:01 bostic Exp $
  */
 
 #ifndef _DB_185_H_
@@ -164,6 +164,6 @@ typedef struct {
 } RECNOINFO;
 
 /* Re-define the user's dbopen calls. */
-#define dbopen __db185_open@DB_VERSION_UNIQUE_NAME@
+#define	dbopen __db185_open@DB_VERSION_UNIQUE_NAME@
 
 #endif /* !_DB_185_H_ */
diff --git a/storage/bdb/dbinc/db_am.h b/storage/bdb/dbinc/db_am.h
index c5aa424255d0f03d4ca7fd5db53f3e9286e46b97..ed1956c66f4eb18bb2ef9fba093c5699b4a69997 100644
--- a/storage/bdb/dbinc/db_am.h
+++ b/storage/bdb/dbinc/db_am.h
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: db_am.h,v 11.61 2002/08/08 03:20:46 bostic Exp $
+ * $Id: db_am.h,v 11.78 2004/09/22 21:14:56 ubell Exp $
  */
 #ifndef _DB_AM_H_
 #define	_DB_AM_H_
@@ -16,27 +16,27 @@
  */
 #define	IS_AUTO_COMMIT(dbenv, txn, flags)				\
 	(LF_ISSET(DB_AUTO_COMMIT) ||					\
-	    ((txn) == NULL && F_ISSET((dbenv), DB_ENV_AUTO_COMMIT)))
+	    ((txn) == NULL && F_ISSET((dbenv), DB_ENV_AUTO_COMMIT) &&	\
+	    !LF_ISSET(DB_NO_AUTO_COMMIT)))
 
 /* DB recovery operation codes. */
 #define	DB_ADD_DUP	1
 #define	DB_REM_DUP	2
 #define	DB_ADD_BIG	3
 #define	DB_REM_BIG	4
-#define	DB_ADD_PAGE	5
-#define	DB_REM_PAGE	6
 
 /*
  * Standard initialization and shutdown macros for all recovery functions.
  */
-#define	REC_INTRO(func, inc_count) {					\
+#define	REC_INTRO(func, inc_count) do {					\
 	argp = NULL;							\
 	dbc = NULL;							\
 	file_dbp = NULL;						\
-	mpf = NULL;							\
+	/* mpf isn't used by all of the recovery functions. */		\
+	COMPQUIET(mpf, NULL);						\
 	if ((ret = func(dbenv, dbtp->data, &argp)) != 0)		\
 		goto out;						\
-	if ((ret = __dbreg_id_to_db(dbenv, argp->txnid,		\
+	if ((ret = __dbreg_id_to_db(dbenv, argp->txnid,			\
 	    &file_dbp, argp->fileid, inc_count)) != 0) {		\
 		if (ret	== DB_DELETED) {				\
 			ret = 0;					\
@@ -44,34 +44,59 @@
 		}							\
 		goto out;						\
 	}								\
-	if ((ret = file_dbp->cursor(file_dbp, NULL, &dbc, 0)) != 0)	\
+	if ((ret = __db_cursor(file_dbp, NULL, &dbc, 0)) != 0)		\
 		goto out;						\
 	F_SET(dbc, DBC_RECOVER);					\
 	mpf = file_dbp->mpf;						\
-}
+} while (0)
 
 #define	REC_CLOSE {							\
 	int __t_ret;							\
 	if (argp != NULL)						\
 		__os_free(dbenv, argp);					\
 	if (dbc != NULL &&						\
-	    (__t_ret = dbc->c_close(dbc)) != 0 && ret == 0)		\
+	    (__t_ret = __db_c_close(dbc)) != 0 && ret == 0)		\
 		ret = __t_ret;						\
-	return (ret);							\
-}
+	}								\
+	return (ret)
 
 /*
  * No-op versions of the same macros.
  */
-#define	REC_NOOP_INTRO(func) {						\
+#define	REC_NOOP_INTRO(func) do {					\
 	argp = NULL;							\
 	if ((ret = func(dbenv, dbtp->data, &argp)) != 0)		\
 		return (ret);						\
-}
+} while (0)
 #define	REC_NOOP_CLOSE							\
 	if (argp != NULL)						\
 		__os_free(dbenv, argp);					\
-	return (ret);							\
+	return (ret)
+
+/*
+ * Macro for reading pages during recovery.  In most cases we
+ * want to avoid an error if the page is not found during rollback
+ * or if we are using truncate to remove pages from the file.
+ */
+#ifndef HAVE_FTRUNCATE
+#define	REC_FGET(mpf, pgno, pagep, cont)				\
+	if ((ret = __memp_fget(mpf, &(pgno), 0, pagep)) != 0) {		\
+		if (ret != DB_PAGE_NOTFOUND || DB_REDO(op)) {		\
+			ret = __db_pgerr(file_dbp, pgno, ret);		\
+			goto out;					\
+		} else							\
+			goto cont;					\
+	}
+#else
+#define	REC_FGET(mpf, pgno, pagep, cont)				\
+	if ((ret = __memp_fget(mpf, &(pgno), 0, pagep)) != 0) {		\
+		if (ret != DB_PAGE_NOTFOUND) {				\
+			ret = __db_pgerr(file_dbp, pgno, ret);		\
+			goto out;					\
+		} else							\
+			goto cont;					\
+	}
+#endif
 
 /*
  * Standard debugging macro for all recovery functions.
@@ -99,8 +124,10 @@
  * we don't tie up the internal pages of the tree longer than necessary.
  */
 #define	__LPUT(dbc, lock)						\
-	(LOCK_ISSET(lock) ?						\
-	(dbc)->dbp->dbenv->lock_put((dbc)->dbp->dbenv, &(lock)) : 0)
+	__ENV_LPUT((dbc)->dbp->dbenv, 					\
+	     lock, F_ISSET((dbc)->dbp, DB_AM_DIRTY) ? DB_LOCK_DOWNGRADE : 0)
+#define	__ENV_LPUT(dbenv, lock, flags)					\
+	(LOCK_ISSET(lock) ? __lock_put(dbenv, &(lock), flags) : 0)
 
 /*
  * __TLPUT -- transactional lock put
@@ -117,7 +144,7 @@
 
 typedef struct {
 	DBC *dbc;
-	int count;
+	u_int32_t count;
 } db_trunc_param;
 
 #include "dbinc/db_dispatch.h"
diff --git a/storage/bdb/dbinc/db_cxx.in b/storage/bdb/dbinc/db_cxx.in
index 6752b36ec425cf6dde58cab2b7197f7bfe99c634..356145765f0d707282d410f2b97377e0932a1c77 100644
--- a/storage/bdb/dbinc/db_cxx.in
+++ b/storage/bdb/dbinc/db_cxx.in
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: db_cxx.in,v 11.113 2002/08/23 13:02:27 mjc Exp $
+ * $Id: db_cxx.in,v 11.147 2004/10/07 21:39:48 bostic Exp $
  */
 
 #ifndef _DB_CXX_H_
@@ -54,15 +54,15 @@
 @cxx_have_stdheaders@
 #ifdef HAVE_CXX_STDHEADERS
 #include <iostream>
-#define	__DB_OSTREAMCLASS	std::ostream
+#include <exception>
+#define	__DB_STD(x)	std::x
 #else
 #include <iostream.h>
-#define	__DB_OSTREAMCLASS	ostream
+#include <exception.h>
+#define	__DB_STD(x)	x
 #endif
 
 #include "db.h"
-#include "cxx_common.h"
-#include "cxx_except.h"
 
 class Db;                                        // forward
 class Dbc;                                       // forward
@@ -75,29 +75,20 @@ class DbMpoolFile;                               // forward
 class DbPreplist;                                // forward
 class Dbt;                                       // forward
 class DbTxn;                                     // forward
+class DbLock;                                    // forward
+class DbSequence;                                // forward
+class Dbt;                                       // forward
 
-// These classes are not defined here and should be invisible
-// to the user, but some compilers require forward references.
-// There is one for each use of the DEFINE_DB_CLASS macro.
-
-class DbImp;
-class DbEnvImp;
-class DbMpoolFileImp;
-class DbTxnImp;
+class DbMultipleIterator;                        // forward
+class DbMultipleKeyDataIterator;                 // forward
+class DbMultipleRecnoDataIterator;               // forward
+class DbMultipleDataIterator;                    // forward
 
-// DEFINE_DB_CLASS defines an imp_ data member and imp() accessor.
-// The underlying type is a pointer to an opaque *Imp class, that
-// gets converted to the correct implementation class by the implementation.
-//
-// Since these defines use "private/public" labels, and leave the access
-// being "private", we always use these by convention before any data
-// members in the private section of a class.  Keeping them in the
-// private section also emphasizes that they are off limits to user code.
-//
-#define	DEFINE_DB_CLASS(name) \
-	public: class name##Imp* imp() { return (imp_); } \
-	public: const class name##Imp* constimp() const { return (imp_); } \
-	private: class name##Imp* imp_
+class DbException;                               // forward
+class DbDeadlockException;                       // forward
+class DbLockNotGrantedException;                 // forward
+class DbMemoryException;                         // forward
+class DbRunRecoveryException;                    // forward
 
 ////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////
@@ -122,6 +113,35 @@ class DbTxnImp;
 
 #endif
 
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+//
+// Mechanisms for declaring classes
+//
+
+//
+// Every class defined in this file has an _exported next to the class name.
+// This is needed for WinTel machines so that the class methods can
+// be exported or imported in a DLL as appropriate.  Users of the DLL
+// use the define DB_USE_DLL.  When the DLL is built, DB_CREATE_DLL
+// must be defined.
+//
+#if defined(_MSC_VER)
+
+#  if defined(DB_CREATE_DLL)
+#    define _exported __declspec(dllexport)      // creator of dll
+#  elif defined(DB_USE_DLL)
+#    define _exported __declspec(dllimport)      // user of dll
+#  else
+#    define _exported                            // static lib creator or user
+#  endif
+
+#else /* _MSC_VER */
+
+#  define _exported
+
+#endif /* _MSC_VER */
+
 // Some interfaces can be customized by allowing users to define
 // callback functions.  For performance and logistical reasons, some
 // callback functions must be declared in extern "C" blocks.  For others,
@@ -148,179 +168,194 @@ extern "C" {
 		(DB_ENV *dbenv, db_pgno_t pgno, void *pgaddr, DBT *pgcookie);
 	typedef int (*pgout_fcn_type)
 		(DB_ENV *dbenv, db_pgno_t pgno, void *pgaddr, DBT *pgcookie);
-};
+}
 
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
 //
-// Lock classes
+// Represents a database table = a set of keys with associated values.
 //
-
-class _exported DbLock
+class _exported Db
 {
 	friend class DbEnv;
 
 public:
-	DbLock();
-	DbLock(const DbLock &);
-	DbLock &operator = (const DbLock &);
-
-protected:
-	// We can add data to this class if needed
-	// since its contained class is not allocated by db.
-	// (see comment at top)
-
-	DbLock(DB_LOCK);
-	DB_LOCK lock_;
-};
-
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-//
-// Log classes
-//
-
-class _exported DbLsn : protected DB_LSN
-{
-	friend class DbEnv;          // friendship needed to cast to base class
-	friend class DbLogc;         // friendship needed to cast to base class
-};
-
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-//
-// Memory pool classes
-//
+	Db(DbEnv*, u_int32_t);      // create a Db object, then call open()
+	virtual ~Db();              // does *not* call close.
 
-class _exported DbMpoolFile
-{
-	friend class DbEnv;
+	// These methods exactly match those in the C interface.
+	//
+	virtual int associate(DbTxn *txn, Db *secondary,
+	    int (*callback)(Db *, const Dbt *, const Dbt *, Dbt *),
+	    u_int32_t flags);
+	virtual int close(u_int32_t flags);
+	virtual int cursor(DbTxn *txnid, Dbc **cursorp, u_int32_t flags);
+	virtual int del(DbTxn *txnid, Dbt *key, u_int32_t flags);
+	virtual void err(int, const char *, ...);
+	virtual void errx(const char *, ...);
+	virtual int fd(int *fdp);
+	virtual int get(DbTxn *txnid, Dbt *key, Dbt *data, u_int32_t flags);
+	virtual void *get_app_private() const;
+	virtual int get_byteswapped(int *);
+	virtual int get_dbname(const char **, const char **);
+	virtual int get_open_flags(u_int32_t *);
+	virtual int get_type(DBTYPE *);
+	virtual int get_transactional();
+	virtual int join(Dbc **curslist, Dbc **dbcp, u_int32_t flags);
+	virtual int key_range(DbTxn *, Dbt *, DB_KEY_RANGE *, u_int32_t);
+	virtual int open(DbTxn *txnid,
+	    const char *, const char *subname, DBTYPE, u_int32_t, int);
+	virtual int pget(DbTxn *txnid, Dbt *key, Dbt *pkey, Dbt *data,
+		 u_int32_t flags);
+	virtual int put(DbTxn *, Dbt *, Dbt *, u_int32_t);
+	virtual int remove(const char *, const char *, u_int32_t);
+	virtual int rename(const char *, const char *, const char *, u_int32_t);
+	virtual int set_alloc(db_malloc_fcn_type, db_realloc_fcn_type,
+		      db_free_fcn_type);
+	virtual void set_app_private(void *);
+	virtual int set_append_recno(int (*)(Db *, Dbt *, db_recno_t));
+	virtual int set_bt_compare(bt_compare_fcn_type); /*deprecated*/
+	virtual int set_bt_compare(int (*)(Db *, const Dbt *, const Dbt *));
+	virtual int set_bt_maxkey(u_int32_t);
+	virtual int get_bt_minkey(u_int32_t *);
+	virtual int set_bt_minkey(u_int32_t);
+	virtual int set_bt_prefix(bt_prefix_fcn_type); /*deprecated*/
+	virtual int set_bt_prefix(size_t (*)(Db *, const Dbt *, const Dbt *));
+	virtual int get_cachesize(u_int32_t *, u_int32_t *, int *);
+	virtual int set_cachesize(u_int32_t, u_int32_t, int);
+	virtual int set_dup_compare(dup_compare_fcn_type); /*deprecated*/
+	virtual int set_dup_compare(int (*)(Db *, const Dbt *, const Dbt *));
+	virtual int get_encrypt_flags(u_int32_t *);
+	virtual int set_encrypt(const char *, u_int32_t);
+	virtual void set_errcall(
+			void (*)(const DbEnv *, const char *, const char *));
+	virtual void get_errfile(FILE **);
+	virtual void set_errfile(FILE *);
+	virtual void get_errpfx(const char **);
+	virtual void set_errpfx(const char *);
+	virtual int set_feedback(void (*)(Db *, int, int));
+	virtual int get_flags(u_int32_t *);
+	virtual int set_flags(u_int32_t);
+	virtual int get_h_ffactor(u_int32_t *);
+	virtual int set_h_ffactor(u_int32_t);
+	virtual int set_h_hash(h_hash_fcn_type); /*deprecated*/
+	virtual int set_h_hash(u_int32_t (*)(Db *, const void *, u_int32_t));
+	virtual int get_h_nelem(u_int32_t *);
+	virtual int set_h_nelem(u_int32_t);
+	virtual int get_lorder(int *);
+	virtual int set_lorder(int);
+	virtual void set_msgcall(void (*)(const DbEnv *, const char *));
+	virtual void get_msgfile(FILE **);
+	virtual void set_msgfile(FILE *);
+	virtual int get_pagesize(u_int32_t *);
+	virtual int set_pagesize(u_int32_t);
+	virtual int set_paniccall(void (*)(DbEnv *, int));
+	virtual int get_re_delim(int *);
+	virtual int set_re_delim(int);
+	virtual int get_re_len(u_int32_t *);
+	virtual int set_re_len(u_int32_t);
+	virtual int get_re_pad(int *);
+	virtual int set_re_pad(int);
+	virtual int get_re_source(const char **);
+	virtual int set_re_source(const char *);
+	virtual int get_q_extentsize(u_int32_t *);
+	virtual int set_q_extentsize(u_int32_t);
+	virtual int stat(DbTxn *, void *sp, u_int32_t flags);
+	virtual int stat_print(u_int32_t flags);
+	virtual int sync(u_int32_t flags);
+	virtual int truncate(DbTxn *, u_int32_t *, u_int32_t);
+	virtual int upgrade(const char *name, u_int32_t flags);
+	virtual int verify(const char *, const char *, __DB_STD(ostream) *,
+		      u_int32_t);
 
-private:
-	// Put this first to allow inlining with some C++ compilers (g++-2.95)
-	DEFINE_DB_CLASS(DbMpoolFile);
+	// These additional methods are not in the C interface, and
+	// are only available for C++.
+	//
+	virtual __DB_STD(ostream) *get_error_stream();
+	virtual void set_error_stream(__DB_STD(ostream) *);
+	virtual __DB_STD(ostream) *get_message_stream();
+	virtual void set_message_stream(__DB_STD(ostream) *);
 
-public:
-	int close(u_int32_t flags);
-	int get(db_pgno_t *pgnoaddr, u_int32_t flags, void *pagep);
-	void last_pgno(db_pgno_t *pgnoaddr);
-	int open(const char *file, u_int32_t flags, int mode, size_t pagesize);
-	int put(void *pgaddr, u_int32_t flags);
-	void refcnt(db_pgno_t *pgnoaddr);
-	int set(void *pgaddr, u_int32_t flags);
-	int set_clear_len(u_int32_t len);
-	int set_fileid(u_int8_t *fileid);
-	int set_ftype(int ftype);
-	int set_lsn_offset(int32_t offset);
-	int set_pgcookie(DBT *dbt);
-	void set_unlink(int);
-	int sync();
+	virtual DbEnv *get_env();
+	virtual DbMpoolFile *get_mpf();
 
-	virtual DB_MPOOLFILE *get_DB_MPOOLFILE()
+	virtual DB *get_DB()
 	{
-		return (DB_MPOOLFILE *)imp();
+		return imp_;
 	}
 
-	virtual const DB_MPOOLFILE *get_const_DB_MPOOLFILE() const
+	virtual const DB *get_const_DB() const
 	{
-		return (const DB_MPOOLFILE *)constimp();
+		return imp_;
 	}
 
-private:
-	// We can add data to this class if needed
-	// since it is implemented via a pointer.
-	// (see comment at top)
-
-	// Note: use DbEnv::memp_fcreate() to get pointers to a DbMpoolFile,
-	// and call DbMpoolFile::close() rather than delete to release them.
-	//
-	DbMpoolFile();
+	static Db* get_Db(DB *db)
+	{
+		return (Db *)db->api_internal;
+	}
 
-	// Shut g++ up.
-protected:
-	virtual ~DbMpoolFile();
+	static const Db* get_const_Db(const DB *db)
+	{
+		return (const Db *)db->api_internal;
+	}
 
 private:
 	// no copying
-	DbMpoolFile(const DbMpoolFile &);
-	void operator = (const DbMpoolFile &);
-};
+	Db(const Db &);
+	Db &operator = (const Db &);
 
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-//
-// This is filled in and returned by the DbEnv::txn_recover() method.
-//
+	void cleanup();
+	int initialize();
+	int error_policy();
+
+	// instance data
+	DB *imp_;
+	DbEnv *env_;
+	DbMpoolFile *mpf_;
+	int construct_error_;
+	u_int32_t flags_;
+	u_int32_t construct_flags_;
 
-class _exported DbPreplist
-{
 public:
-	DbTxn *txn;
-	u_int8_t gid[DB_XIDDATASIZE];
+	// These are public only because they need to be called
+	// via C callback functions.  They should never be used by
+	// external users of this class.
+	//
+	int (*append_recno_callback_)(Db *, Dbt *, db_recno_t);
+	int (*associate_callback_)(Db *, const Dbt *, const Dbt *, Dbt *);
+	int (*bt_compare_callback_)(Db *, const Dbt *, const Dbt *);
+	size_t (*bt_prefix_callback_)(Db *, const Dbt *, const Dbt *);
+	int (*dup_compare_callback_)(Db *, const Dbt *, const Dbt *);
+	void (*feedback_callback_)(Db *, int, int);
+	u_int32_t (*h_hash_callback_)(Db *, const void *, u_int32_t);
 };
 
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
 //
-// Transaction classes
+// Cursor
 //
-
-class _exported DbTxn
+class _exported Dbc : protected DBC
 {
-	friend class DbEnv;
-
-private:
-	// Put this first to allow inlining with some C++ compilers (g++-2.95)
-	DEFINE_DB_CLASS(DbTxn);
+	friend class Db;
 
 public:
-	int abort();
-	int commit(u_int32_t flags);
-	int discard(u_int32_t flags);
-	u_int32_t id();
-	int prepare(u_int8_t *gid);
-	int set_timeout(db_timeout_t timeout, u_int32_t flags);
-
-	virtual DB_TXN *get_DB_TXN()
-	{
-		return (DB_TXN *)imp();
-	}
-
-	virtual const DB_TXN *get_const_DB_TXN() const
-	{
-		return (const DB_TXN *)constimp();
-	}
-
-	static DbTxn* get_DbTxn(DB_TXN *txn)
-	{
-		return (DbTxn *)txn->api_internal;
-	}
-
-	static const DbTxn* get_const_DbTxn(const DB_TXN *txn)
-	{
-		return (const DbTxn *)txn->api_internal;
-	}
-
-	// For internal use only.
-	static DbTxn* wrap_DB_TXN(DB_TXN *txn);
+	int close();
+	int count(db_recno_t *countp, u_int32_t flags);
+	int del(u_int32_t flags);
+	int dup(Dbc** cursorp, u_int32_t flags);
+	int get(Dbt* key, Dbt *data, u_int32_t flags);
+	int pget(Dbt* key, Dbt* pkey, Dbt *data, u_int32_t flags);
+	int put(Dbt* key, Dbt *data, u_int32_t flags);
 
 private:
-	// We can add data to this class if needed
-	// since it is implemented via a pointer.
-	// (see comment at top)
+	// No data is permitted in this class (see comment at top)
 
-	// Note: use DbEnv::txn_begin() to get pointers to a DbTxn,
-	// and call DbTxn::abort() or DbTxn::commit rather than
-	// delete to release them.
+	// Note: use Db::cursor() to get pointers to a Dbc,
+	// and call Dbc::close() rather than delete to release them.
 	//
-	DbTxn();
-	// For internal use only.
-	DbTxn(DB_TXN *txn);
-	virtual ~DbTxn();
+	Dbc();
+	~Dbc();
 
 	// no copying
-	DbTxn(const DbTxn &);
-	void operator = (const DbTxn &);
+	Dbc(const Dbc &);
+	Dbc &operator = (const Dbc &);
 };
 
 //
@@ -338,10 +373,6 @@ class _exported DbEnv
 	friend class DbLock;
 	friend class DbMpoolFile;
 
-private:
-	// Put this first to allow inlining with some C++ compilers (g++-2.95)
-	DEFINE_DB_CLASS(DbEnv);
-
 public:
 	// After using this constructor, you can set any needed
 	// parameters for the environment using the set_* methods.
@@ -362,41 +393,70 @@ public:
 	virtual void err(int, const char *, ...);
 	virtual void errx(const char *, ...);
 	virtual void *get_app_private() const;
+	virtual int get_home(const char **);
+	virtual int get_open_flags(u_int32_t *);
 	virtual int open(const char *, u_int32_t, int);
 	virtual int remove(const char *, u_int32_t);
 	virtual int set_alloc(db_malloc_fcn_type, db_realloc_fcn_type,
-		      db_free_fcn_type);
+			      db_free_fcn_type);
 	virtual void set_app_private(void *);
+	virtual int get_cachesize(u_int32_t *, u_int32_t *, int *);
 	virtual int set_cachesize(u_int32_t, u_int32_t, int);
+	virtual int get_data_dirs(const char ***);
 	virtual int set_data_dir(const char *);
-	virtual int set_encrypt(const char *, int);
-	virtual void set_errcall(void (*)(const char *, char *));
+	virtual int get_encrypt_flags(u_int32_t *);
+	virtual int set_encrypt(const char *, u_int32_t);
+	virtual void set_errcall(
+			void (*)(const DbEnv *, const char *, const char *));
+	virtual void get_errfile(FILE **);
 	virtual void set_errfile(FILE *);
+	virtual void get_errpfx(const char **);
 	virtual void set_errpfx(const char *);
+	virtual int get_flags(u_int32_t *);
 	virtual int set_flags(u_int32_t, int);
 	virtual int set_feedback(void (*)(DbEnv *, int, int));
+	virtual int get_lg_bsize(u_int32_t *);
 	virtual int set_lg_bsize(u_int32_t);
+	virtual int get_lg_dir(const char **);
 	virtual int set_lg_dir(const char *);
+	virtual int get_lg_max(u_int32_t *);
 	virtual int set_lg_max(u_int32_t);
+	virtual int get_lg_regionmax(u_int32_t *);
 	virtual int set_lg_regionmax(u_int32_t);
+	virtual int get_lk_conflicts(const u_int8_t **, int *);
 	virtual int set_lk_conflicts(u_int8_t *, int);
+	virtual int get_lk_detect(u_int32_t *);
 	virtual int set_lk_detect(u_int32_t);
 	virtual int set_lk_max(u_int32_t);
+	virtual int get_lk_max_lockers(u_int32_t *);
 	virtual int set_lk_max_lockers(u_int32_t);
+	virtual int get_lk_max_locks(u_int32_t *);
 	virtual int set_lk_max_locks(u_int32_t);
+	virtual int get_lk_max_objects(u_int32_t *);
 	virtual int set_lk_max_objects(u_int32_t);
+	virtual int get_mp_mmapsize(size_t *);
 	virtual int set_mp_mmapsize(size_t);
+	virtual void set_msgcall(void (*)(const DbEnv *, const char *));
+	virtual void get_msgfile(FILE **);
+	virtual void set_msgfile(FILE *);
 	virtual int set_paniccall(void (*)(DbEnv *, int));
 	virtual int set_rpc_server(void *, char *, long, long, u_int32_t);
+	virtual int get_shm_key(long *);
 	virtual int set_shm_key(long);
-	virtual int set_timeout(db_timeout_t timeout, u_int32_t flags);
+	virtual int get_timeout(db_timeout_t *, u_int32_t);
+	virtual int set_timeout(db_timeout_t, u_int32_t);
+	virtual int get_tmp_dir(const char **);
 	virtual int set_tmp_dir(const char *);
+	virtual int get_tas_spins(u_int32_t *);
 	virtual int set_tas_spins(u_int32_t);
+	virtual int get_tx_max(u_int32_t *);
 	virtual int set_tx_max(u_int32_t);
 	virtual int set_app_dispatch(int (*)(DbEnv *,
 	    Dbt *, DbLsn *, db_recops));
+	virtual int get_tx_timestamp(time_t *);
 	virtual int set_tx_timestamp(time_t *);
-	virtual int set_verbose(u_int32_t which, int onoff);
+	virtual int get_verbose(u_int32_t which, int *);
+	virtual int set_verbose(u_int32_t which, int);
 
 	// Version information.  A static method so it can be obtained anytime.
 	//
@@ -414,15 +474,18 @@ public:
 	// set_error_stream() to force all errors to a C++ stream.
 	// It is unwise to mix these approaches.
 	//
-	virtual void set_error_stream(__DB_OSTREAMCLASS *);
+	virtual __DB_STD(ostream) *get_error_stream();
+	virtual void set_error_stream(__DB_STD(ostream) *);
+	virtual __DB_STD(ostream) *get_message_stream();
+	virtual void set_message_stream(__DB_STD(ostream) *);
 
 	// used internally
-	static void runtime_error(const char *caller, int err,
+	static void runtime_error(DbEnv *env, const char *caller, int err,
 				  int error_policy);
-	static void runtime_error_dbt(const char *caller, Dbt *dbt,
+	static void runtime_error_dbt(DbEnv *env, const char *caller, Dbt *dbt,
 				  int error_policy);
-	static void runtime_error_lock_get(const char *caller, int err,
-				  db_lockop_t op, db_lockmode_t mode,
+	static void runtime_error_lock_get(DbEnv *env, const char *caller,
+				  int err, db_lockop_t op, db_lockmode_t mode,
 				  const Dbt *obj, DbLock lock, int index,
 				  int error_policy);
 
@@ -435,8 +498,9 @@ public:
 	virtual int lock_id_free(u_int32_t id);
 	virtual int lock_put(DbLock *lock);
 	virtual int lock_stat(DB_LOCK_STAT **statp, u_int32_t flags);
-	virtual int lock_vec(u_int32_t locker, u_int32_t flags, DB_LOCKREQ list[],
-		     int nlist, DB_LOCKREQ **elistp);
+	virtual int lock_stat_print(u_int32_t flags);
+	virtual int lock_vec(u_int32_t locker, u_int32_t flags,
+		     DB_LOCKREQ list[], int nlist, DB_LOCKREQ **elistp);
 
 	// Log functions
 	//
@@ -448,6 +512,7 @@ public:
 	virtual int log_put(DbLsn *lsn, const Dbt *data, u_int32_t flags);
 
 	virtual int log_stat(DB_LOG_STAT **spp, u_int32_t flags);
+	virtual int log_stat_print(u_int32_t flags);
 
 	// Mpool functions
 	//
@@ -457,47 +522,52 @@ public:
 			  pgout_fcn_type pgout_fcn);
 	virtual int memp_stat(DB_MPOOL_STAT
 		      **gsp, DB_MPOOL_FSTAT ***fsp, u_int32_t flags);
+	virtual int memp_stat_print(u_int32_t flags);
 	virtual int memp_sync(DbLsn *lsn);
 	virtual int memp_trickle(int pct, int *nwrotep);
 
 	// Transaction functions
 	//
 	virtual int txn_begin(DbTxn *pid, DbTxn **tid, u_int32_t flags);
-	virtual int txn_checkpoint(u_int32_t kbyte, u_int32_t min, u_int32_t flags);
+	virtual int txn_checkpoint(u_int32_t kbyte, u_int32_t min,
+			u_int32_t flags);
 	virtual int txn_recover(DbPreplist *preplist, long count,
 			long *retp, u_int32_t flags);
 	virtual int txn_stat(DB_TXN_STAT **statp, u_int32_t flags);
+	virtual int txn_stat_print(u_int32_t flags);
 
 	// Replication functions
 	//
-	virtual int rep_elect(int, int, u_int32_t, int *);
-	virtual int rep_process_message(Dbt *, Dbt *, int *);
+	virtual int rep_elect(int, int, int, u_int32_t, int *, u_int32_t);
+	virtual int rep_process_message(Dbt *, Dbt *, int *, DbLsn *);
 	virtual int rep_start(Dbt *, u_int32_t);
 	virtual int rep_stat(DB_REP_STAT **statp, u_int32_t flags);
+	virtual int rep_stat_print(u_int32_t flags);
+	virtual int get_rep_limit(u_int32_t *, u_int32_t *);
 	virtual int set_rep_limit(u_int32_t, u_int32_t);
-	virtual int set_rep_transport(u_int32_t,
-	    int (*)(DbEnv *, const Dbt *, const Dbt *, int, u_int32_t));
+	virtual int set_rep_transport(int, int (*)(DbEnv *,
+	    const Dbt *, const Dbt *, const DbLsn *, int, u_int32_t));
 
 	// Conversion functions
 	//
 	virtual DB_ENV *get_DB_ENV()
 	{
-		return (DB_ENV *)imp();
+		return imp_;
 	}
 
 	virtual const DB_ENV *get_const_DB_ENV() const
 	{
-		return (const DB_ENV *)constimp();
+		return imp_;
 	}
 
 	static DbEnv* get_DbEnv(DB_ENV *dbenv)
 	{
-		return (DbEnv *)dbenv->api1_internal;
+		return dbenv ? (DbEnv *)dbenv->api1_internal : 0;
 	}
 
 	static const DbEnv* get_const_DbEnv(const DB_ENV *dbenv)
 	{
-		return (const DbEnv *)dbenv->api1_internal;
+		return dbenv ? (const DbEnv *)dbenv->api1_internal : 0;
 	}
 
 	// For internal use only.
@@ -507,14 +577,19 @@ public:
 	// via C functions.  They should never be called by users
 	// of this class.
 	//
-	static void _stream_error_function(const char *, char *);
 	static int _app_dispatch_intercept(DB_ENV *env, DBT *dbt, DB_LSN *lsn,
-					db_recops op);
+				       db_recops op);
 	static void _paniccall_intercept(DB_ENV *env, int errval);
 	static void _feedback_intercept(DB_ENV *env, int opcode, int pct);
 	static int _rep_send_intercept(DB_ENV *env,
 				       const DBT *cntrl, const DBT *data,
-				       int id, u_int32_t flags);
+				       const DB_LSN *lsn, int id,
+				       u_int32_t flags);
+	static void _stream_error_function(const DB_ENV *env,
+					   const char *prefix,
+					   const char *message);
+	static void _stream_message_function(const DB_ENV *env,
+					     const char *message);
 
 private:
 	void cleanup();
@@ -529,157 +604,272 @@ private:
 	void operator = (const DbEnv &);
 
 	// instance data
+	DB_ENV *imp_;
 	int construct_error_;
 	u_int32_t construct_flags_;
+	__DB_STD(ostream) *error_stream_;
+	__DB_STD(ostream) *message_stream_;
+
 	int (*app_dispatch_callback_)(DbEnv *, Dbt *, DbLsn *, db_recops);
+	void (*error_callback_)(const DbEnv *, const char *, const char *);
 	void (*feedback_callback_)(DbEnv *, int, int);
+	void (*message_callback_)(const DbEnv *, const char *);
 	void (*paniccall_callback_)(DbEnv *, int);
 	int (*pgin_callback_)(DbEnv *dbenv, db_pgno_t pgno,
 			      void *pgaddr, Dbt *pgcookie);
 	int (*pgout_callback_)(DbEnv *dbenv, db_pgno_t pgno,
 			       void *pgaddr, Dbt *pgcookie);
 	int (*rep_send_callback_)(DbEnv *,
-	    const Dbt *, const Dbt *, int, u_int32_t);
-
-	// class data
-	static __DB_OSTREAMCLASS *error_stream_;
+	    const Dbt *, const Dbt *, const DbLsn *, int, u_int32_t);
 };
 
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
 //
-// Table access classes
+// Lock
 //
+class _exported DbLock
+{
+	friend class DbEnv;
+
+public:
+	DbLock();
+	DbLock(const DbLock &);
+	DbLock &operator = (const DbLock &);
+
+protected:
+	// We can add data to this class if needed
+	// since its contained class is not allocated by db.
+	// (see comment at top)
+
+	DbLock(DB_LOCK);
+	DB_LOCK lock_;
+};
 
 //
-// Represents a database table = a set of keys with associated values.
+// Log cursor
 //
-class _exported Db
+class _exported DbLogc : protected DB_LOGC
 {
 	friend class DbEnv;
 
+public:
+	int close(u_int32_t _flags);
+	int get(DbLsn *lsn, Dbt *data, u_int32_t _flags);
+
 private:
-	// Put this first to allow inlining with some C++ compilers (g++-2.95)
-	DEFINE_DB_CLASS(Db);
+	// No data is permitted in this class (see comment at top)
+
+	// Note: use Db::cursor() to get pointers to a Dbc,
+	// and call Dbc::close() rather than delete to release them.
+	//
+	DbLogc();
+	~DbLogc();
+
+	// no copying
+	DbLogc(const Dbc &);
+	DbLogc &operator = (const Dbc &);
+};
+
+//
+// Log sequence number
+//
+class _exported DbLsn : public DB_LSN
+{
+	friend class DbEnv;          // friendship needed to cast to base class
+	friend class DbLogc;         // friendship needed to cast to base class
+};
+
+//
+// Memory pool file
+//
+class _exported DbMpoolFile
+{
+	friend class DbEnv;
+	friend class Db;
 
 public:
-	Db(DbEnv*, u_int32_t);      // create a Db object, then call open()
-	virtual ~Db();              // does *not* call close.
+	int close(u_int32_t flags);
+	int get(db_pgno_t *pgnoaddr, u_int32_t flags, void *pagep);
+	int open(const char *file, u_int32_t flags, int mode, size_t pagesize);
+	int get_transactional(void);
+	int put(void *pgaddr, u_int32_t flags);
+	int set(void *pgaddr, u_int32_t flags);
+	int get_clear_len(u_int32_t *len);
+	int set_clear_len(u_int32_t len);
+	int get_fileid(u_int8_t *fileid);
+	int set_fileid(u_int8_t *fileid);
+	int get_flags(u_int32_t *flagsp);
+	int set_flags(u_int32_t flags, int onoff);
+	int get_ftype(int *ftype);
+	int set_ftype(int ftype);
+	int get_lsn_offset(int32_t *offsetp);
+	int set_lsn_offset(int32_t offset);
+	int get_maxsize(u_int32_t *gbytes, u_int32_t *bytes);
+	int set_maxsize(u_int32_t gbytes, u_int32_t bytes);
+	int get_pgcookie(DBT *dbt);
+	int set_pgcookie(DBT *dbt);
+	int get_priority(DB_CACHE_PRIORITY *priorityp);
+	int set_priority(DB_CACHE_PRIORITY priority);
+	int sync();
 
-	// These methods exactly match those in the C interface.
-	//
-	virtual int associate(DbTxn *txn, Db *secondary,
-	    int (*callback)(Db *, const Dbt *, const Dbt *, Dbt *),
-	    u_int32_t flags);
-	virtual int close(u_int32_t flags);
-        virtual int cursor(DbTxn *txnid, Dbc **cursorp, u_int32_t flags);
-	virtual int del(DbTxn *txnid, Dbt *key, u_int32_t flags);
-	virtual void err(int, const char *, ...);
-	virtual void errx(const char *, ...);
-	virtual int fd(int *fdp);
-	virtual int get(DbTxn *txnid, Dbt *key, Dbt *data, u_int32_t flags);
-	virtual void *get_app_private() const;
-	virtual int get_byteswapped(int *);
-	virtual int get_type(DBTYPE *);
-	virtual int join(Dbc **curslist, Dbc **dbcp, u_int32_t flags);
-	virtual int key_range(DbTxn *, Dbt *, DB_KEY_RANGE *, u_int32_t);
-	virtual int open(DbTxn *txnid,
-	    const char *, const char *subname, DBTYPE, u_int32_t, int);
-	virtual int pget(DbTxn *txnid, Dbt *key, Dbt *pkey, Dbt *data,
-		 u_int32_t flags);
-	virtual int put(DbTxn *, Dbt *, Dbt *, u_int32_t);
-	virtual int remove(const char *, const char *, u_int32_t);
-	virtual int rename(const char *, const char *, const char *, u_int32_t);
-	virtual int set_alloc(db_malloc_fcn_type, db_realloc_fcn_type,
-		      db_free_fcn_type);
-	virtual void set_app_private(void *);
-	virtual int set_append_recno(int (*)(Db *, Dbt *, db_recno_t));
-	virtual int set_bt_compare(bt_compare_fcn_type); /*deprecated*/
-	virtual int set_bt_compare(int (*)(Db *, const Dbt *, const Dbt *));
-	virtual int set_bt_maxkey(u_int32_t);
-	virtual int set_bt_minkey(u_int32_t);
-	virtual int set_bt_prefix(bt_prefix_fcn_type); /*deprecated*/
-	virtual int set_bt_prefix(size_t (*)(Db *, const Dbt *, const Dbt *));
-	virtual int set_cachesize(u_int32_t, u_int32_t, int);
-	virtual int set_cache_priority(DB_CACHE_PRIORITY);
-	virtual int set_dup_compare(dup_compare_fcn_type); /*deprecated*/
-	virtual int set_dup_compare(int (*)(Db *, const Dbt *, const Dbt *));
-	virtual int set_encrypt(const char *, int);
-	virtual void set_errcall(void (*)(const char *, char *));
-	virtual void set_errfile(FILE *);
-	virtual void set_errpfx(const char *);
-	virtual int set_feedback(void (*)(Db *, int, int));
-	virtual int set_flags(u_int32_t);
-	virtual int set_h_ffactor(u_int32_t);
-	virtual int set_h_hash(h_hash_fcn_type); /*deprecated*/
-	virtual int set_h_hash(u_int32_t (*)(Db *, const void *, u_int32_t));
-	virtual int set_h_nelem(u_int32_t);
-	virtual int set_lorder(int);
-	virtual int set_pagesize(u_int32_t);
-	virtual int set_paniccall(void (*)(DbEnv *, int));
-	virtual int set_re_delim(int);
-	virtual int set_re_len(u_int32_t);
-	virtual int set_re_pad(int);
-	virtual int set_re_source(char *);
-	virtual int set_q_extentsize(u_int32_t);
-	virtual int stat(void *sp, u_int32_t flags);
-	virtual int sync(u_int32_t flags);
-	virtual int truncate(DbTxn *, u_int32_t *, u_int32_t);
-	virtual int upgrade(const char *name, u_int32_t flags);
-	virtual int verify(const char *, const char *, __DB_OSTREAMCLASS *, u_int32_t);
+	virtual DB_MPOOLFILE *get_DB_MPOOLFILE()
+	{
+		return imp_;
+	}
 
-	// These additional methods are not in the C interface, and
-	// are only available for C++.
+	virtual const DB_MPOOLFILE *get_const_DB_MPOOLFILE() const
+	{
+		return imp_;
+	}
+
+private:
+	DB_MPOOLFILE *imp_;
+
+	// We can add data to this class if needed
+	// since it is implemented via a pointer.
+	// (see comment at top)
+
+	// Note: use DbEnv::memp_fcreate() to get pointers to a DbMpoolFile,
+	// and call DbMpoolFile::close() rather than delete to release them.
 	//
-	virtual void set_error_stream(__DB_OSTREAMCLASS *);
+	DbMpoolFile();
 
-	virtual DB *get_DB()
+	// Shut g++ up.
+protected:
+	virtual ~DbMpoolFile();
+
+private:
+	// no copying
+	DbMpoolFile(const DbMpoolFile &);
+	void operator = (const DbMpoolFile &);
+};
+
+//
+// This is filled in and returned by the DbEnv::txn_recover() method.
+//
+class _exported DbPreplist
+{
+public:
+	DbTxn *txn;
+	u_int8_t gid[DB_XIDDATASIZE];
+};
+
+//
+// A sequence record in a database
+//
+class _exported DbSequence
+{
+public:
+	DbSequence(Db *db, u_int32_t flags);
+	virtual ~DbSequence();
+
+	int open(DbTxn *txnid, Dbt *key, u_int32_t flags);
+	int initial_value(db_seq_t value);
+	int close(u_int32_t flags);
+	int remove(DbTxn *txnid, u_int32_t flags);
+	int stat(DB_SEQUENCE_STAT **sp, u_int32_t flags);
+	int stat_print(u_int32_t flags);
+	
+	int get(DbTxn *txnid, int32_t delta, db_seq_t *retp, u_int32_t flags);
+	int get_cachesize(int32_t *sizep);
+	int set_cachesize(int32_t size);
+	int get_flags(u_int32_t *flagsp);
+	int set_flags(u_int32_t flags);
+	int get_range(db_seq_t *minp, db_seq_t *maxp);
+	int set_range(db_seq_t min, db_seq_t max);
+
+	Db *get_db();
+	Dbt *get_key();
+
+	virtual DB_SEQUENCE *get_DB_SEQUENCE()
 	{
-		return (DB *)imp();
+		return imp_;
 	}
 
-	virtual const DB *get_const_DB() const
+	virtual const DB_SEQUENCE *get_const_DB_SEQUENCE() const
 	{
-		return (const DB *)constimp();
+		return imp_;
 	}
 
-	static Db* get_Db(DB *db)
+	static DbSequence* get_DbSequence(DB_SEQUENCE *seq)
 	{
-		return (Db *)db->api_internal;
+		return (DbSequence *)seq->api_internal;
 	}
 
-	static const Db* get_const_Db(const DB *db)
+	static const DbSequence* get_const_DbSequence(const DB_SEQUENCE *seq)
 	{
-		return (const Db *)db->api_internal;
+		return (const DbSequence *)seq->api_internal;
 	}
 
+	// For internal use only.
+	static DbSequence* wrap_DB_SEQUENCE(DB_SEQUENCE *seq);
+
 private:
+	DbSequence(DB_SEQUENCE *seq);
 	// no copying
-	Db(const Db &);
-	Db &operator = (const Db &);
+	DbSequence(const DbSequence &);
+	DbSequence &operator = (const DbSequence &);
 
-	void cleanup();
-	int initialize();
-	int error_policy();
+	DB_SEQUENCE *imp_;
+	DBT key_;
+};
 
-	// instance data
-	DbEnv *env_;
-	int construct_error_;
-	u_int32_t flags_;
-	u_int32_t construct_flags_;
+//
+// Transaction
+//
+class _exported DbTxn
+{
+	friend class DbEnv;
 
 public:
-	// These are public only because they need to be called
-	// via C callback functions.  They should never be used by
-	// external users of this class.
+	int abort();
+	int commit(u_int32_t flags);
+	int discard(u_int32_t flags);
+	u_int32_t id();
+	int prepare(u_int8_t *gid);
+	int set_timeout(db_timeout_t timeout, u_int32_t flags);
+
+	virtual DB_TXN *get_DB_TXN()
+	{
+		return imp_;
+	}
+
+	virtual const DB_TXN *get_const_DB_TXN() const
+	{
+		return imp_;
+	}
+
+	static DbTxn* get_DbTxn(DB_TXN *txn)
+	{
+		return (DbTxn *)txn->api_internal;
+	}
+
+	static const DbTxn* get_const_DbTxn(const DB_TXN *txn)
+	{
+		return (const DbTxn *)txn->api_internal;
+	}
+
+	// For internal use only.
+	static DbTxn* wrap_DB_TXN(DB_TXN *txn);
+
+private:
+	DB_TXN *imp_;
+
+	// We can add data to this class if needed
+	// since it is implemented via a pointer.
+	// (see comment at top)
+
+	// Note: use DbEnv::txn_begin() to get pointers to a DbTxn,
+	// and call DbTxn::abort() or DbTxn::commit rather than
+	// delete to release them.
 	//
-	int (*append_recno_callback_)(Db *, Dbt *, db_recno_t);
-	int (*associate_callback_)(Db *, const Dbt *, const Dbt *, Dbt *);
-	int (*bt_compare_callback_)(Db *, const Dbt *, const Dbt *);
-	size_t (*bt_prefix_callback_)(Db *, const Dbt *, const Dbt *);
-	int (*dup_compare_callback_)(Db *, const Dbt *, const Dbt *);
-	void (*feedback_callback_)(Db *, int, int);
-	u_int32_t (*h_hash_callback_)(Db *, const void *, u_int32_t);
+	DbTxn();
+	// For internal use only.
+	DbTxn(DB_TXN *txn);
+	virtual ~DbTxn();
+
+	// no copying
+	DbTxn(const DbTxn &);
+	void operator = (const DbTxn &);
 };
 
 //
@@ -687,13 +877,13 @@ public:
 //
 class _exported Dbt : private DBT
 {
-	friend class Dbc;
 	friend class Db;
+	friend class Dbc;
 	friend class DbEnv;
 	friend class DbLogc;
+	friend class DbSequence;
 
 public:
-
 	// key/data
 	void *get_data() const                 { return data; }
 	void set_data(void *value)             { data = value; }
@@ -744,52 +934,155 @@ private:
 	// not of your subclassed type.
 };
 
-class _exported Dbc : protected DBC
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+//
+// multiple key/data/reco iterator classes
+//
+
+// DbMultipleIterator is a shared private base class for the three types
+// of bulk-return Iterator;  it should never be instantiated directly,
+// but it handles the functionality shared by its subclasses.
+class _exported DbMultipleIterator
 {
-	friend class Db;
+public:
+	DbMultipleIterator(const Dbt &dbt);
+protected:
+	u_int8_t *data_;
+	u_int32_t *p_;
+};
 
+class _exported DbMultipleKeyDataIterator : private DbMultipleIterator
+{
 public:
-	int close();
-	int count(db_recno_t *countp, u_int32_t flags);
-	int del(u_int32_t flags);
-	int dup(Dbc** cursorp, u_int32_t flags);
-	int get(Dbt* key, Dbt *data, u_int32_t flags);
-	int pget(Dbt* key, Dbt* pkey, Dbt *data, u_int32_t flags);
-	int put(Dbt* key, Dbt *data, u_int32_t flags);
+	DbMultipleKeyDataIterator(const Dbt &dbt) : DbMultipleIterator(dbt) {}
+	bool next(Dbt &key, Dbt &data);
+};
+
+class _exported DbMultipleRecnoDataIterator : private DbMultipleIterator
+{
+public:
+	DbMultipleRecnoDataIterator(const Dbt &dbt) : DbMultipleIterator(dbt) {}
+	bool next(db_recno_t &recno, Dbt &data);
+};
+
+class _exported DbMultipleDataIterator : private DbMultipleIterator
+{
+public:
+	DbMultipleDataIterator(const Dbt &dbt) : DbMultipleIterator(dbt) {}
+	bool next(Dbt &data);
+};
+
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+//
+// Exception classes
+//
+
+// Almost any error in the DB library throws a DbException.
+// Every exception should be considered an abnormality
+// (e.g. bug, misuse of DB, file system error).
+//
+class _exported DbException : public __DB_STD(exception)
+{
+public:
+	virtual ~DbException() throw();
+	DbException(int err);
+	DbException(const char *description);
+	DbException(const char *description, int err);
+	DbException(const char *prefix, const char *description, int err);
+	int get_errno() const;
+	virtual const char *what() const throw();
+	DbEnv *get_env() const;
+	void set_env(DbEnv *env);
+
+	DbException(const DbException &);
+	DbException &operator = (const DbException &);
 
 private:
-	// No data is permitted in this class (see comment at top)
+	void describe(const char *prefix, const char *description);
 
-	// Note: use Db::cursor() to get pointers to a Dbc,
-	// and call Dbc::close() rather than delete to release them.
-	//
-	Dbc();
-	~Dbc();
+	char *what_;
+	int err_;                   // errno
+	DbEnv *env_;
+};
 
-	// no copying
-	Dbc(const Dbc &);
-	Dbc &operator = (const Dbc &);
+//
+// A specific sort of exception that occurs when
+// an operation is aborted to resolve a deadlock.
+//
+class _exported DbDeadlockException : public DbException
+{
+public:
+	virtual ~DbDeadlockException() throw();
+	DbDeadlockException(const char *description);
+
+	DbDeadlockException(const DbDeadlockException &);
+	DbDeadlockException &operator = (const DbDeadlockException &);
 };
 
-class _exported DbLogc : protected DB_LOGC
+//
+// A specific sort of exception that occurs when
+// a lock is not granted, e.g. by lock_get or lock_vec.
+// Note that the Dbt is only live as long as the Dbt used
+// in the offending call.
+//
+class _exported DbLockNotGrantedException : public DbException
 {
-	friend class DbEnv;
+public:
+	virtual ~DbLockNotGrantedException() throw();
+	DbLockNotGrantedException(const char *prefix, db_lockop_t op,
+	    db_lockmode_t mode, const Dbt *obj, const DbLock lock, int index);
+	DbLockNotGrantedException(const char *description);
+
+	DbLockNotGrantedException(const DbLockNotGrantedException &);
+	DbLockNotGrantedException &operator =
+	    (const DbLockNotGrantedException &);
+
+	db_lockop_t get_op() const;
+	db_lockmode_t get_mode() const;
+	const Dbt* get_obj() const;
+	DbLock *get_lock() const;
+	int get_index() const;
+
+private:
+	db_lockop_t op_;
+	db_lockmode_t mode_;
+	const Dbt *obj_;
+	DbLock *lock_;
+	int index_;
+};
 
+//
+// A specific sort of exception that occurs when
+// user declared memory is insufficient in a Dbt.
+//
+class _exported DbMemoryException : public DbException
+{
 public:
-	int close(u_int32_t _flags);
-	int get(DbLsn *lsn, Dbt *data, u_int32_t _flags);
+	virtual ~DbMemoryException() throw();
+	DbMemoryException(Dbt *dbt);
+	DbMemoryException(const char *prefix, Dbt *dbt);
 
+	DbMemoryException(const DbMemoryException &);
+	DbMemoryException &operator = (const DbMemoryException &);
+
+	Dbt *get_dbt() const;
 private:
-	// No data is permitted in this class (see comment at top)
+	Dbt *dbt_;
+};
 
-	// Note: use Db::cursor() to get pointers to a Dbc,
-	// and call Dbc::close() rather than delete to release them.
-	//
-	DbLogc();
-	~DbLogc();
+//
+// A specific sort of exception that occurs when
+// recovery is required before continuing DB activity.
+//
+class _exported DbRunRecoveryException : public DbException
+{
+public:
+	virtual ~DbRunRecoveryException() throw();
+	DbRunRecoveryException(const char *description);
 
-	// no copying
-	DbLogc(const Dbc &);
-	DbLogc &operator = (const Dbc &);
+	DbRunRecoveryException(const DbRunRecoveryException &);
+	DbRunRecoveryException &operator = (const DbRunRecoveryException &);
 };
 #endif /* !_DB_CXX_H_ */
diff --git a/storage/bdb/dbinc/db_dispatch.h b/storage/bdb/dbinc/db_dispatch.h
index 283eb1e95deccabe88ac42d0150936999183ef33..bbaff69dbfbd200c5cff90102fdbe24006c6da18 100644
--- a/storage/bdb/dbinc/db_dispatch.h
+++ b/storage/bdb/dbinc/db_dispatch.h
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -32,7 +32,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: db_dispatch.h,v 11.30 2002/06/20 19:34:03 margo Exp $
+ * $Id: db_dispatch.h,v 11.38 2004/07/26 19:54:08 margo Exp $
  */
 
 #ifndef _DB_DISPATCH_H_
@@ -57,14 +57,14 @@ struct __db_txnhead {
 	DB_LSN ckplsn;		/* LSN of last retained checkpoint. */
 	DB_LSN trunc_lsn;	/* Lsn to which we are going to truncate;
 				 * make sure we abort anyone after this. */
-	int32_t generation;	/* Current generation number. */
-	int32_t gen_alloc;	/* Number of generations allocated. */
+	u_int32_t generation;	/* Current generation number. */
+	u_int32_t gen_alloc;	/* Number of generations allocated. */
 	struct {
-		int32_t generation;
+		u_int32_t generation;
 		u_int32_t txn_min;
 		u_int32_t txn_max;
-	} *gen_array;		/* Array of txnids associted with a gen. */
-	int nslots;
+	} *gen_array;		/* Array of txnids associated with a gen. */
+	u_int nslots;
 	LIST_HEAD(__db_headlink, __db_txnlist) head[1];
 };
 
@@ -74,17 +74,17 @@ struct __db_txnlist {
 	union {
 		struct {
 			u_int32_t txnid;
-			int32_t	generation;
-			int32_t status;
+			u_int32_t generation;
+			u_int32_t status;
 		} t;
 		struct {
-			int32_t ntxns;
-			int32_t maxn;
+			u_int32_t ntxns;
+			u_int32_t maxn;
 			DB_LSN *lsn_array;
 		} l;
 		struct {
-			int32_t nentries;
-			int32_t maxentry;
+			u_int32_t nentries;
+			u_int32_t maxentry;
 			int32_t locked;
 			char *fname;
 			int32_t fileid;
@@ -100,6 +100,16 @@ struct __db_txnlist {
  */
 #define	TXNLIST_NEW	0x1
 
-#define	DB_user_BEGIN		10000
+/*
+ * States for limbo list processing.
+ */
+
+typedef enum {
+	LIMBO_NORMAL,		/* Normal processing. */
+	LIMBO_PREPARE,		/* We are preparing a transaction. */
+	LIMBO_RECOVER,		/* We are in recovery. */
+	LIMBO_TIMESTAMP,	/* We are recovering to a timestamp. */
+	LIMBO_COMPENSATE	/* After recover to ts, generate log records. */
+} db_limbo_state;
 
 #endif /* !_DB_DISPATCH_H_ */
diff --git a/storage/bdb/dbinc/db_int.in b/storage/bdb/dbinc/db_int.in
index 2f46293a65d9c18bf24d9b6784e1a2582cb74455..522f2f7280b4bf1dd0f6d88f4991b9c1739a7d05 100644
--- a/storage/bdb/dbinc/db_int.in
+++ b/storage/bdb/dbinc/db_int.in
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: db_int.in,v 11.106 2002/09/10 02:48:08 bostic Exp $
+ * $Id: db_int.in,v 11.155 2004/10/28 16:07:38 ubell Exp $
  */
 
 #ifndef _DB_INTERNAL_H_
@@ -15,7 +15,7 @@
  * here because it's OK if db_int.h includes queue structure declarations.
  *******************************************************/
 #ifndef NO_SYSTEM_INCLUDES
-#if defined(__STDC__) || defined(__cplusplus)
+#if defined(STDC_HEADERS) || defined(__cplusplus)
 #include <stdarg.h>
 #else
 #include <varargs.h>
@@ -35,8 +35,43 @@ extern "C" {
 /*******************************************************
  * General purpose constants and macros.
  *******************************************************/
-#define	UINT16_T_MAX	    0xffff	/* Maximum 16 bit unsigned. */
-#define	UINT32_T_MAX	0xffffffff	/* Maximum 32 bit unsigned. */
+#ifndef	UINT16_MAX
+#define	UINT16_MAX	65535		/* Maximum 16-bit unsigned. */
+#endif
+#ifndef	UINT32_MAX
+#ifdef __STDC__
+#define	UINT32_MAX	4294967295U	/* Maximum 32-bit unsigned. */
+#else
+#define	UINT32_MAX	0xffffffff	/* Maximum 32-bit unsigned. */
+#endif
+#endif
+
+#if defined(HAVE_LONG_LONG) && defined(HAVE_UNSIGNED_LONG_LONG)
+#undef	INT64_MAX
+#undef	INT64_MIN
+#undef	UINT64_MAX
+
+#ifdef	DB_WIN32
+#define	INT64_MAX	_I64_MAX
+#define	INT64_MIN	_I64_MIN
+#define	UINT64_MAX	_UI64_MAX
+
+#define	INT64_FMT	"%l64d"
+#define	UINT64_FMT	"%l64u"
+#else
+/*
+ * Override the system's 64-bit min/max constants.  AIX's 32-bit compiler can
+ * handle 64-bit values, but the system's constants don't include the LL/ULL
+ * suffix, and so can't be compiled using the 32-bit compiler.
+ */
+#define	INT64_MAX	9223372036854775807LL
+#define	INT64_MIN	(-INT64_MAX-1)
+#define	UINT64_MAX	18446744073709551615ULL
+
+#define	INT64_FMT	"%lld"
+#define	UINT64_FMT	"%llu"
+#endif	/* DB_WIN32 */
+#endif	/* HAVE_LONG_LONG && HAVE_UNSIGNED_LONG_LONG */
 
 #define	MEGABYTE	1048576
 #define	GIGABYTE	1073741824
@@ -64,50 +99,38 @@ extern "C" {
  */
 #define	DB_DEF_IOSIZE	(8 * 1024)
 
-/*
- * Aligning items to particular sizes or in pages or memory.
- *
- * db_align_t --
- * Largest integral type, used to align structures in memory.  We don't store
- * floating point types in structures, so integral types should be sufficient
- * (and we don't have to worry about systems that store floats in other than
- * power-of-2 numbers of bytes).  Additionally this fixes compiler that rewrite
- * structure assignments and ANSI C memcpy calls to be in-line instructions
- * that happen to require alignment.  Note: this alignment isn't sufficient for
- * mutexes, which depend on things like cache line alignment.  Mutex alignment
- * is handled separately, in mutex.h.
- *
- * db_alignp_t --
- * Integral type that's the same size as a pointer.  There are places where
- * DB modifies pointers by discarding the bottom bits to guarantee alignment.
- * We can't use db_align_t, it may be larger than the pointer, and compilers
- * get upset about that.  So far we haven't run on any machine where there
- * isn't an integral type the same size as a pointer -- here's hoping.
- */
-@db_align_t_decl@
-@db_alignp_t_decl@
-
 /* Align an integer to a specific boundary. */
-#undef	ALIGN
-#define	ALIGN(v, bound)	(((v) + (bound) - 1) & ~(((db_align_t)bound) - 1))
+#undef	DB_ALIGN
+#define	DB_ALIGN(v, bound)						\
+	(((v) + (bound) - 1) & ~(((uintmax_t)bound) - 1))
+
+/* Increment a pointer to a specific boundary. */
+#undef	ALIGNP_INC
+#define	ALIGNP_INC(p, bound)						\
+	(void *)(((uintptr_t)(p) + (bound) - 1) & ~(((uintptr_t)bound) - 1))
+
+/* Decrement a pointer to a specific boundary. */
+#undef	ALIGNP_DEC
+#define	ALIGNP_DEC(p, bound)						\
+	(void *)((uintptr_t)(p) & ~(((uintptr_t)bound) - 1))
 
 /*
  * Print an address as a u_long (a u_long is the largest type we can print
  * portably).  Most 64-bit systems have made longs 64-bits, so this should
  * work.
  */
-#define	P_TO_ULONG(p)	((u_long)(db_alignp_t)(p))
+#define	P_TO_ULONG(p)	((u_long)(uintptr_t)(p))
 
 /*
  * Convert a pointer to a small integral value.
  *
- * The (u_int16_t)(db_alignp_t) cast avoids warnings: the (db_alignp_t) cast
+ * The (u_int16_t)(uintptr_t) cast avoids warnings: the (uintptr_t) cast
  * converts the value to an integral type, and the (u_int16_t) cast converts
  * it to a small integral type so we don't get complaints when we assign the
- * final result to an integral type smaller than db_alignp_t.
+ * final result to an integral type smaller than uintptr_t.
  */
-#define	P_TO_UINT32(p)	((u_int32_t)(db_alignp_t)(p))
-#define	P_TO_UINT16(p)	((u_int16_t)(db_alignp_t)(p))
+#define	P_TO_UINT32(p)	((u_int32_t)(uintptr_t)(p))
+#define	P_TO_UINT16(p)	((u_int16_t)(uintptr_t)(p))
 
 /*
  * There are several on-page structures that are declared to have a number of
@@ -145,71 +168,117 @@ typedef struct __fn {
 #define	LF_ISSET(f)		((flags) & (f))
 #define	LF_SET(f)		((flags) |= (f))
 
-/* Display separator string. */
-#undef	DB_LINE
-#define	DB_LINE "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="
+/*
+ * Calculate a percentage.  The values can overflow 32-bit integer arithmetic
+ * so we use floating point.
+ *
+ * When calculating a bytes-vs-page size percentage, we're getting the inverse
+ * of the percentage in all cases, that is, we want 100 minus the percentage we
+ * calculate.
+ */
+#define	DB_PCT(v, total)						\
+	((int)((total) == 0 ? 0 : ((double)(v) * 100) / (total)))
+#define	DB_PCT_PG(v, total, pgsize)					\
+	((int)((total) == 0 ? 0 :					\
+	    100 - ((double)(v) * 100) / ((total) * (pgsize))))
 
-/* Unused, or not-used-yet variable.  "Shut that bloody compiler up!" */
-#define	COMPQUIET(n, v)	(n) = (v)
+/*
+ * Structure used for callback message aggregation.
+ *
+ * Display values in XXX_stat_print calls.
+ */
+typedef struct __db_msgbuf {
+	char *buf;			/* Heap allocated buffer. */
+	char *cur;			/* Current end of message. */
+	size_t len;			/* Allocated length of buffer. */
+} DB_MSGBUF;
+#define	DB_MSGBUF_INIT(a) do {						\
+	(a)->buf = (a)->cur = NULL;					\
+	(a)->len = 0;							\
+} while (0)
+#define	DB_MSGBUF_FLUSH(dbenv, a) do {					\
+	if ((a)->buf != NULL) {						\
+		if ((a)->cur != (a)->buf)				\
+			__db_msg(dbenv, "%s", (a)->buf);		\
+		__os_free(dbenv, (a)->buf);				\
+		DB_MSGBUF_INIT(a);					\
+	}								\
+} while (0)
+#define	STAT_FMT(msg, fmt, type, v) do {				\
+	DB_MSGBUF __mb;							\
+	DB_MSGBUF_INIT(&__mb);						\
+	__db_msgadd(dbenv, &__mb, fmt, (type)(v));			\
+	__db_msgadd(dbenv, &__mb, "\t%s", msg);				\
+	DB_MSGBUF_FLUSH(dbenv, &__mb);					\
+} while (0)
+#define	STAT_HEX(msg, v)						\
+	__db_msg(dbenv, "%#lx\t%s", (u_long)(v), msg)
+#define	STAT_ISSET(msg, p)						\
+	__db_msg(dbenv, "%sSet\t%s", (p) == NULL ? "!" : " ", msg)
+#define	STAT_LONG(msg, v)						\
+	__db_msg(dbenv, "%ld\t%s", (long)(v), msg)
+#define	STAT_LSN(msg, lsnp)						\
+	__db_msg(dbenv, "%lu/%lu\t%s",					\
+	    (u_long)(lsnp)->file, (u_long)(lsnp)->offset, msg)
+#define	STAT_STRING(msg, p) do {					\
+	const char *__p = p;	/* p may be a function call. */		\
+	__db_msg(dbenv, "%s\t%s", __p == NULL ? "!Set" : __p, msg);	\
+} while (0)
+#define	STAT_ULONG(msg, v)						\
+	__db_msg(dbenv, "%lu\t%s", (u_long)(v), msg)
 
 /*******************************************************
  * API return values
  *******************************************************/
- /*
-  * Return values that are OK for each different call.  Most calls have
-  * a standard 'return of 0 is only OK value', but some, like db->get
-  * have DB_NOTFOUND as a return value, but it really isn't an error.
-  */
+/*
+ * Return values that are OK for each different call.  Most calls have a
+ * standard 'return of 0 is only OK value', but some, like db->get have
+ * DB_NOTFOUND as a return value, but it really isn't an error.
+ */
 #define	DB_RETOK_STD(ret)	((ret) == 0)
 #define	DB_RETOK_DBCDEL(ret)	((ret) == 0 || (ret) == DB_KEYEMPTY || \
 				    (ret) == DB_NOTFOUND)
-#define	DB_RETOK_DBCGET(ret)	DB_RETOK_DBGET(ret)
-#define	DB_RETOK_DBCPUT(ret)	((ret) == 0 || (ret) == DB_KEYEXIST || \
+#define	DB_RETOK_DBCGET(ret)	((ret) == 0 || (ret) == DB_KEYEMPTY || \
 				    (ret) == DB_NOTFOUND)
-#define	DB_RETOK_DBDEL(ret)	((ret) == 0 || (ret) == DB_NOTFOUND)
-#define	DB_RETOK_DBGET(ret)	((ret) == 0 || (ret) == DB_KEYEMPTY || \
+#define	DB_RETOK_DBCPUT(ret)	((ret) == 0 || (ret) == DB_KEYEXIST || \
 				    (ret) == DB_NOTFOUND)
+#define	DB_RETOK_DBDEL(ret)	DB_RETOK_DBCDEL(ret)
+#define	DB_RETOK_DBGET(ret)	DB_RETOK_DBCGET(ret)
 #define	DB_RETOK_DBPUT(ret)	((ret) == 0 || (ret) == DB_KEYEXIST)
 #define	DB_RETOK_LGGET(ret)	((ret) == 0 || (ret) == DB_NOTFOUND)
 #define	DB_RETOK_MPGET(ret)	((ret) == 0 || (ret) == DB_PAGE_NOTFOUND)
-#define	DB_RETOK_REPPMSG(ret)	((ret) == 0 || (ret) == DB_REP_NEWMASTER || \
-				    (ret) == DB_REP_NEWSITE)
+#define	DB_RETOK_REPPMSG(ret)	((ret) == 0 || \
+				    (ret) == DB_REP_ISPERM || \
+				    (ret) == DB_REP_NEWMASTER || \
+				    (ret) == DB_REP_NEWSITE || \
+				    (ret) == DB_REP_NOTPERM || \
+				    (ret) == DB_REP_STARTUPDONE)
+
+/* Find a reasonable operation-not-supported error. */
+#ifdef	EOPNOTSUPP
+#define	DB_OPNOTSUP	EOPNOTSUPP
+#else
+#ifdef	ENOTSUP
+#define	DB_OPNOTSUP	ENOTSUP
+#else
+#define	DB_OPNOTSUP	EINVAL
+#endif
+#endif
 
 /*******************************************************
  * Files.
  *******************************************************/
- /*
-  * We use 1024 as the maximum path length.  It's too hard to figure out what
-  * the real path length is, as it was traditionally stored in <sys/param.h>,
-  * and that file isn't always available.
-  */
+/*
+ * We use 1024 as the maximum path length.  It's too hard to figure out what
+ * the real path length is, as it was traditionally stored in <sys/param.h>,
+ * and that file isn't always available.
+ */
 #undef	MAXPATHLEN
 #define	MAXPATHLEN	1024
 
 #define	PATH_DOT	"."	/* Current working directory. */
-#define	PATH_SEPARATOR	"/"	/* Path separator character(s). */
-
-/*
- * Flags understood by __os_open.
- */
-#define	DB_OSO_CREATE	0x0001		/* POSIX: O_CREAT */
-#define	DB_OSO_DIRECT	0x0002		/* Don't buffer the file in the OS. */
-#define	DB_OSO_EXCL	0x0004		/* POSIX: O_EXCL */
-#define	DB_OSO_LOG	0x0008		/* Opening a log file. */
-#define	DB_OSO_RDONLY	0x0010		/* POSIX: O_RDONLY */
-#define	DB_OSO_REGION	0x0020		/* Opening a region file. */
-#define	DB_OSO_SEQ	0x0040		/* Expected sequential access. */
-#define	DB_OSO_TEMP	0x0080		/* Remove after last close. */
-#define	DB_OSO_TRUNC	0x0100		/* POSIX: O_TRUNC */
-
-/*
- * Seek options understood by __os_seek.
- */
-typedef enum {
-	DB_OS_SEEK_CUR,			/* POSIX: SEEK_CUR */
-	DB_OS_SEEK_END,			/* POSIX: SEEK_END */
-	DB_OS_SEEK_SET			/* POSIX: SEEK_SET */
-} DB_OS_SEEK;
+				/* Path separator character(s). */
+#define	PATH_SEPARATOR	"@PATH_SEPARATOR@"
 
 /*******************************************************
  * Environment.
@@ -228,6 +297,7 @@ typedef enum {
  * LOCKING_ON	Locking has been configured.
  * LOGGING_ON	Logging has been configured.
  * MPOOL_ON	Memory pool has been configured.
+ * REP_ON	Replication has been configured.
  * RPC_ON	RPC has been configured.
  * TXN_ON	Transactions have been configured.
  */
@@ -236,6 +306,7 @@ typedef enum {
 #define	LOCKING_ON(dbenv)	((dbenv)->lk_handle != NULL)
 #define	LOGGING_ON(dbenv)	((dbenv)->lg_handle != NULL)
 #define	MPOOL_ON(dbenv)		((dbenv)->mp_handle != NULL)
+#define	REP_ON(dbenv)		((dbenv)->rep_handle != NULL)
 #define	RPC_ON(dbenv)		((dbenv)->cl_handle != NULL)
 #define	TXN_ON(dbenv)		((dbenv)->tx_handle != NULL)
 
@@ -267,6 +338,9 @@ typedef enum {
 #define	ENV_REQUIRES_CONFIG(dbenv, handle, i, flags)			\
 	if (handle == NULL)						\
 		return (__db_env_config(dbenv, i, flags));
+#define	ENV_NOT_CONFIGURED(dbenv, handle, i, flags)			\
+	if (F_ISSET((dbenv), DB_ENV_OPEN_CALLED))			\
+		ENV_REQUIRES_CONFIG(dbenv, handle, i, flags)
 
 /*******************************************************
  * Database Access Methods.
@@ -381,7 +455,7 @@ typedef struct __dbpginfo {
 	(LSN).file = 0;							\
 	(LSN).offset = 0;						\
 } while (0)
-#define	IS_ZERO_LSN(LSN)	((LSN).file == 0)
+#define	IS_ZERO_LSN(LSN)	((LSN).file == 0 && (LSN).offset == 0)
 
 #define	IS_INIT_LSN(LSN)	((LSN).file == 1 && (LSN).offset == 0)
 #define	INIT_LSN(LSN)		do {					\
@@ -390,11 +464,11 @@ typedef struct __dbpginfo {
 } while (0)
 
 #define	MAX_LSN(LSN) do {						\
-	(LSN).file = UINT32_T_MAX;					\
-	(LSN).offset = UINT32_T_MAX;					\
+	(LSN).file = UINT32_MAX;					\
+	(LSN).offset = UINT32_MAX;					\
 } while (0)
 #define	IS_MAX_LSN(LSN) \
-	((LSN).file == UINT32_T_MAX && (LSN).offset == UINT32_T_MAX)
+	((LSN).file == UINT32_MAX && (LSN).offset == UINT32_MAX)
 
 /* If logging is turned off, smash the lsn. */
 #define	LSN_NOT_LOGGED(LSN) do {					\
@@ -404,34 +478,12 @@ typedef struct __dbpginfo {
 #define	IS_NOT_LOGGED_LSN(LSN) \
 	((LSN).file == 0 && (LSN).offset == 1)
 
-/*
- * Test if the environment is currently logging changes.  If we're in
- * recovery or we're a replication client, we don't need to log changes
- * because they're already in the log, even though we have a fully functional
- * log system.
- */
-#define	DBENV_LOGGING(dbenv)						\
-	(LOGGING_ON(dbenv) && !F_ISSET((dbenv), DB_ENV_REP_CLIENT) &&	\
-	    (!IS_RECOVERING(dbenv)))
-
-/*
- * Test if we need to log a change.  Note that the DBC_RECOVER flag is set
- * when we're in abort, as well as during recovery;  thus DBC_LOGGING may be
- * false for a particular dbc even when DBENV_LOGGING is true.
- *
- * We explicitly use LOGGING_ON/DB_ENV_REP_CLIENT here because we don't
- * want to have to pull in the log headers, which IS_RECOVERING (and thus
- * DBENV_LOGGING) rely on, and because DBC_RECOVER should be set anytime
- * IS_RECOVERING would be true.
- */
-#define	DBC_LOGGING(dbc)						\
-	(LOGGING_ON((dbc)->dbp->dbenv) && !F_ISSET((dbc), DBC_RECOVER) && \
-	 !F_ISSET((dbc)->dbp->dbenv, DB_ENV_REP_CLIENT))
-
 /*******************************************************
  * Txn.
  *******************************************************/
 #define	DB_NONBLOCK(C)	((C)->txn != NULL && F_ISSET((C)->txn, TXN_NOWAIT))
+#define	NOWAIT_FLAG(txn) \
+	((txn) != NULL && F_ISSET((txn), TXN_NOWAIT) ? DB_LOCK_NOWAIT : 0)
 #define	IS_SUBTRANSACTION(txn)						\
 	((txn) != NULL && (txn)->parent != NULL)
 
@@ -441,6 +493,33 @@ typedef struct __dbpginfo {
 #define	DB_IV_BYTES     16		/* Bytes per IV */
 #define	DB_MAC_KEY	20		/* Bytes per MAC checksum */
 
+/*******************************************************
+ * Secondaries over RPC.
+ *******************************************************/
+#ifdef CONFIG_TEST
+/*
+ * These are flags passed to DB->associate calls by the Tcl API if running
+ * over RPC.  The RPC server will mask out these flags before making the real
+ * DB->associate call.
+ *
+ * These flags must coexist with the valid flags to DB->associate (currently
+ * DB_AUTO_COMMIT and DB_CREATE).  DB_AUTO_COMMIT is in the group of
+ * high-order shared flags (0xff000000), and DB_CREATE is in the low-order
+ * group (0x00000fff), so we pick a range in between.
+ */
+#define	DB_RPC2ND_MASK		0x00f00000 /* Reserved bits. */
+
+#define	DB_RPC2ND_REVERSEDATA	0x00100000 /* callback_n(0) _s_reversedata. */
+#define	DB_RPC2ND_NOOP		0x00200000 /* callback_n(1) _s_noop */
+#define	DB_RPC2ND_CONCATKEYDATA	0x00300000 /* callback_n(2) _s_concatkeydata */
+#define	DB_RPC2ND_CONCATDATAKEY 0x00400000 /* callback_n(3) _s_concatdatakey */
+#define	DB_RPC2ND_REVERSECONCAT	0x00500000 /* callback_n(4) _s_reverseconcat */
+#define	DB_RPC2ND_TRUNCDATA	0x00600000 /* callback_n(5) _s_truncdata */
+#define	DB_RPC2ND_CONSTANT	0x00700000 /* callback_n(6) _s_constant */
+#define	DB_RPC2ND_GETZIP	0x00800000 /* sj_getzip */
+#define	DB_RPC2ND_GETNAME	0x00900000 /* sj_getname */
+#endif
+
 /*******************************************************
  * Forward structure declarations.
  *******************************************************/
@@ -467,7 +546,46 @@ struct __vrfy_pageinfo; typedef struct __vrfy_pageinfo VRFY_PAGEINFO;
 #include "dbinc_auto/mutex_ext.h"	/* XXX: Include after region.h. */
 #include "dbinc_auto/env_ext.h"
 #include "dbinc/os.h"
+#include "dbinc/rep.h"
 #include "dbinc_auto/clib_ext.h"
 #include "dbinc_auto/common_ext.h"
 
+/*******************************************************
+ * Remaining Log.
+ * These need to be defined after the general includes
+ * because they need rep.h from above.
+ *******************************************************/
+/*
+ * Test if the environment is currently logging changes.  If we're in recovery
+ * or we're a replication client, we don't need to log changes because they're
+ * already in the log, even though we have a fully functional log system.
+ */
+#define	DBENV_LOGGING(dbenv)						\
+	(LOGGING_ON(dbenv) && !IS_REP_CLIENT(dbenv) &&			\
+	    (!IS_RECOVERING(dbenv)))
+
+/*
+ * Test if we need to log a change.  By default, we don't log operations without
+ * associated transactions, unless DIAGNOSTIC, DEBUG_ROP or DEBUG_WOP are on.
+ * This is because we want to get log records for read/write operations, and, if
+ * we trying to debug something, more information is always better.
+ *
+ * The DBC_RECOVER flag is set when we're in abort, as well as during recovery;
+ * thus DBC_LOGGING may be false for a particular dbc even when DBENV_LOGGING
+ * is true.
+ *
+ * We explicitly use LOGGING_ON/IS_REP_CLIENT here because we don't want to pull
+ * in the log headers, which IS_RECOVERING (and thus DBENV_LOGGING) rely on, and
+ * because DBC_RECOVER should be set anytime IS_RECOVERING would be true.
+ */
+#if defined(DIAGNOSTIC) || defined(DEBUG_ROP)  || defined(DEBUG_WOP)
+#define	DBC_LOGGING(dbc)						\
+	(LOGGING_ON((dbc)->dbp->dbenv) &&				\
+	    !F_ISSET((dbc), DBC_RECOVER) && !IS_REP_CLIENT((dbc)->dbp->dbenv))
+#else
+#define	DBC_LOGGING(dbc)						\
+	((dbc)->txn != NULL && LOGGING_ON((dbc)->dbp->dbenv) &&		\
+	    !F_ISSET((dbc), DBC_RECOVER) && !IS_REP_CLIENT((dbc)->dbp->dbenv))
+#endif
+
 #endif /* !_DB_INTERNAL_H_ */
diff --git a/storage/bdb/dbinc/db_join.h b/storage/bdb/dbinc/db_join.h
index 487ce3eebbbf84417de66ae15a18b25cea987fa2..3fea2ad2f126e6a3065a1f5145732bbee221a6a1 100644
--- a/storage/bdb/dbinc/db_join.h
+++ b/storage/bdb/dbinc/db_join.h
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1998-2002
+ * Copyright (c) 1998-2004
  *	Sleepycat Software.  All rights reserved.
  *
  *	@(#)db_join.h	11.1 (Sleepycat) 7/25/99
@@ -18,7 +18,7 @@
 typedef struct __join_cursor {
 	u_int8_t *j_exhausted;	/* Array of flags; is cursor i exhausted? */
 	DBC	**j_curslist;	/* Array of cursors in the join: constant. */
-	DBC	**j_fdupcurs;	/* Cursors w/ first intances of current dup. */
+	DBC	**j_fdupcurs;	/* Cursors w/ first instances of current dup. */
 	DBC	**j_workcurs;	/* Scratch cursor copies to muck with. */
 	DB	 *j_primary;	/* Primary dbp. */
 	DBT	  j_key;	/* Used to do lookups. */
diff --git a/storage/bdb/dbinc/db_page.h b/storage/bdb/dbinc/db_page.h
index 97497556fd9ec0e93a1765393bda4ad42e989df7..59a1292ffe39f4e53d5786ec4a116d7bdd04bcf6 100644
--- a/storage/bdb/dbinc/db_page.h
+++ b/storage/bdb/dbinc/db_page.h
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: db_page.h,v 11.52 2002/09/13 21:24:04 bostic Exp $
+ * $Id: db_page.h,v 11.63 2004/09/17 22:00:27 mjc Exp $
  */
 
 #ifndef _DB_PAGE_H_
@@ -243,6 +243,12 @@ typedef struct _db_page {
 	u_int8_t  type;		/*    25: Page type. */
 } PAGE;
 
+/*
+ * With many compilers sizeof(PAGE) == 28, while SIZEOF_PAGE == 26.
+ * We add in other things directly after the page header and need
+ * the SIZEOF_PAGE.  When giving the sizeof(), many compilers will
+ * pad it out to the next 4-byte boundary.
+ */
 #define	SIZEOF_PAGE	26
 /*
  * !!!
@@ -322,7 +328,7 @@ typedef struct _qpage {
 #define	RE_NREC_ADJ(p, adj)						\
 	PREV_PGNO(p) += adj;
 #define	RE_NREC_SET(p, num)						\
-	PREV_PGNO(p) = num;
+	PREV_PGNO(p) = (num);
 
 /*
  * Initialize a page.
@@ -332,13 +338,13 @@ typedef struct _qpage {
  * P_INIT call.
  */
 #define	P_INIT(pg, pg_size, n, pg_prev, pg_next, btl, pg_type) do {	\
-	PGNO(pg) = n;							\
-	PREV_PGNO(pg) = pg_prev;					\
-	NEXT_PGNO(pg) = pg_next;					\
-	NUM_ENT(pg) = 0;						\
-	HOFFSET(pg) = pg_size;						\
-	LEVEL(pg) = btl;						\
-	TYPE(pg) = pg_type;						\
+	PGNO(pg) = (n);							\
+	PREV_PGNO(pg) = (pg_prev);					\
+	NEXT_PGNO(pg) = (pg_next);					\
+	NUM_ENT(pg) = (0);						\
+	HOFFSET(pg) = (db_indx_t)(pg_size);				\
+	LEVEL(pg) = (btl);						\
+	TYPE(pg) = (pg_type);						\
 } while (0)
 
 /* Page header length (offset to first index). */
@@ -432,8 +438,8 @@ typedef struct _hkeydata {
  * not a PAIR index.
  */
 #define	LEN_HITEM(dbp, pg, pgsize, indx)				\
-	(((indx) == 0 ? pgsize :					\
-	(P_INP(dbp, pg)[indx - 1])) - (P_INP(dbp, pg)[indx]))
+	(((indx) == 0 ? (pgsize) :					\
+	(P_INP(dbp, pg)[(indx) - 1])) - (P_INP(dbp, pg)[indx]))
 
 #define	LEN_HKEYDATA(dbp, pg, psize, indx)				\
 	(db_indx_t)(LEN_HITEM(dbp, pg, psize, indx) - HKEYDATA_SIZE(0))
@@ -547,10 +553,13 @@ typedef struct _bkeydata {
 
 /*
  * Page space required to add a new BKEYDATA item to the page, with and
- * without the index value.
+ * without the index value.  The (u_int16_t) cast avoids warnings: DB_ALIGN
+ * casts to uintmax_t, the cast converts it to a small integral type so we
+ * don't get complaints when we assign the final result to an integral type
+ * smaller than uintmax_t.
  */
 #define	BKEYDATA_SIZE(len)						\
-	ALIGN((len) + SSZA(BKEYDATA, data), sizeof(u_int32_t))
+	(u_int16_t)DB_ALIGN((len) + SSZA(BKEYDATA, data), sizeof(u_int32_t))
 #define	BKEYDATA_PSIZE(len)						\
 	(BKEYDATA_SIZE(len) + sizeof(db_indx_t))
 
@@ -572,13 +581,10 @@ typedef struct _boverflow {
 
 /*
  * Page space required to add a new BOVERFLOW item to the page, with and
- * without the index value.  The (u_int16_t) cast avoids warnings: ALIGN
- * casts to db_align_t, the cast converts it to a small integral type so
- * we don't get complaints when we assign the final result to an integral
- * type smaller than db_align_t.
+ * without the index value.
  */
 #define	BOVERFLOW_SIZE							\
-	((u_int16_t)ALIGN(sizeof(BOVERFLOW), sizeof(u_int32_t)))
+	((u_int16_t)DB_ALIGN(sizeof(BOVERFLOW), sizeof(u_int32_t)))
 #define	BOVERFLOW_PSIZE							\
 	(BOVERFLOW_SIZE + sizeof(db_indx_t))
 
@@ -615,7 +621,7 @@ typedef struct _binternal {
  * without the index value.
  */
 #define	BINTERNAL_SIZE(len)						\
-	ALIGN((len) + SSZA(BINTERNAL, data), sizeof(u_int32_t))
+	(u_int16_t)DB_ALIGN((len) + SSZA(BINTERNAL, data), sizeof(u_int32_t))
 #define	BINTERNAL_PSIZE(len)						\
 	(BINTERNAL_SIZE(len) + sizeof(db_indx_t))
 
@@ -640,7 +646,7 @@ typedef struct _rinternal {
  * without the index value.
  */
 #define	RINTERNAL_SIZE							\
-	ALIGN(sizeof(RINTERNAL), sizeof(u_int32_t))
+	(u_int16_t)DB_ALIGN(sizeof(RINTERNAL), sizeof(u_int32_t))
 #define	RINTERNAL_PSIZE							\
 	(RINTERNAL_SIZE + sizeof(db_indx_t))
 
diff --git a/storage/bdb/dbinc/db_server_int.h b/storage/bdb/dbinc/db_server_int.h
index efec539b2f8dcd22c1102bf6dc5c619d551c5cdd..eba36efcb5bf41efeddc43b7f29fa7a33dd1196f 100644
--- a/storage/bdb/dbinc/db_server_int.h
+++ b/storage/bdb/dbinc/db_server_int.h
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2000-2002
+ * Copyright (c) 2000-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: db_server_int.h,v 1.23 2002/02/12 15:01:24 sue Exp $
+ * $Id: db_server_int.h,v 1.25 2004/01/28 03:36:02 bostic Exp $
  */
 
 #ifndef _DB_SERVER_INT_H_
diff --git a/storage/bdb/dbinc/db_shash.h b/storage/bdb/dbinc/db_shash.h
index 2c54d6145c536c76f1a999ed5cd3b6a277153449..51277e5e0b30f1f3155ec3f3152c9f63d56f4659 100644
--- a/storage/bdb/dbinc/db_shash.h
+++ b/storage/bdb/dbinc/db_shash.h
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: db_shash.h,v 11.11 2002/01/11 15:52:26 bostic Exp $
+ * $Id: db_shash.h,v 11.13 2004/01/28 03:36:02 bostic Exp $
  */
 
 #ifndef	_DB_SHASH_H_
diff --git a/storage/bdb/dbinc/db_swap.h b/storage/bdb/dbinc/db_swap.h
index d5aad65385eab7a8b65a3f931e9488130de328a5..25391ce59574f952aa8f6a858127a1867db1b167 100644
--- a/storage/bdb/dbinc/db_swap.h
+++ b/storage/bdb/dbinc/db_swap.h
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -32,18 +32,63 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: db_swap.h,v 11.8 2002/01/11 15:52:26 bostic Exp $
+ * $Id: db_swap.h,v 11.11 2004/01/28 03:36:02 bostic Exp $
  */
 
 #ifndef _DB_SWAP_H_
 #define	_DB_SWAP_H_
 
+/*
+ * Little endian <==> big endian 64-bit swap macros.
+ *	M_64_SWAP	swap a memory location
+ *	P_64_COPY	copy potentially unaligned 4 byte quantities
+ *	P_64_SWAP	swap a referenced memory location
+ */
+#undef	M_64_SWAP
+#define	M_64_SWAP(a) {							\
+	u_int64_t _tmp;							\
+	_tmp = a;							\
+	((u_int8_t *)&a)[0] = ((u_int8_t *)&_tmp)[7];			\
+	((u_int8_t *)&a)[1] = ((u_int8_t *)&_tmp)[6];			\
+	((u_int8_t *)&a)[2] = ((u_int8_t *)&_tmp)[5];			\
+	((u_int8_t *)&a)[3] = ((u_int8_t *)&_tmp)[4];			\
+	((u_int8_t *)&a)[4] = ((u_int8_t *)&_tmp)[3];			\
+	((u_int8_t *)&a)[5] = ((u_int8_t *)&_tmp)[2];			\
+	((u_int8_t *)&a)[6] = ((u_int8_t *)&_tmp)[1];			\
+	((u_int8_t *)&a)[7] = ((u_int8_t *)&_tmp)[0];			\
+}
+#undef	P_64_COPY
+#define	P_64_COPY(a, b) {						\
+	((u_int8_t *)b)[0] = ((u_int8_t *)a)[0];			\
+	((u_int8_t *)b)[1] = ((u_int8_t *)a)[1];			\
+	((u_int8_t *)b)[2] = ((u_int8_t *)a)[2];			\
+	((u_int8_t *)b)[3] = ((u_int8_t *)a)[3];			\
+	((u_int8_t *)b)[4] = ((u_int8_t *)a)[4];			\
+	((u_int8_t *)b)[5] = ((u_int8_t *)a)[5];			\
+	((u_int8_t *)b)[6] = ((u_int8_t *)a)[6];			\
+	((u_int8_t *)b)[7] = ((u_int8_t *)a)[7];			\
+}
+#undef	P_64_SWAP
+#define	P_64_SWAP(a) {							\
+	u_int64_t _tmp;							\
+	P_64_COPY(a, &_tmp);						\
+	((u_int8_t *)a)[0] = ((u_int8_t *)&_tmp)[7];			\
+	((u_int8_t *)a)[1] = ((u_int8_t *)&_tmp)[6];			\
+	((u_int8_t *)a)[2] = ((u_int8_t *)&_tmp)[5];			\
+	((u_int8_t *)a)[3] = ((u_int8_t *)&_tmp)[4];			\
+	((u_int8_t *)a)[4] = ((u_int8_t *)&_tmp)[3];			\
+	((u_int8_t *)a)[5] = ((u_int8_t *)&_tmp)[2];			\
+	((u_int8_t *)a)[6] = ((u_int8_t *)&_tmp)[1];			\
+	((u_int8_t *)a)[7] = ((u_int8_t *)&_tmp)[0];			\
+}
+
 /*
  * Little endian <==> big endian 32-bit swap macros.
  *	M_32_SWAP	swap a memory location
  *	P_32_COPY	copy potentially unaligned 4 byte quantities
  *	P_32_SWAP	swap a referenced memory location
  */
+#undef	M_32_SWAP
 #define	M_32_SWAP(a) {							\
 	u_int32_t _tmp;							\
 	_tmp = a;							\
@@ -52,12 +97,14 @@
 	((u_int8_t *)&a)[2] = ((u_int8_t *)&_tmp)[1];			\
 	((u_int8_t *)&a)[3] = ((u_int8_t *)&_tmp)[0];			\
 }
+#undef	P_32_COPY
 #define	P_32_COPY(a, b) {						\
 	((u_int8_t *)b)[0] = ((u_int8_t *)a)[0];			\
 	((u_int8_t *)b)[1] = ((u_int8_t *)a)[1];			\
 	((u_int8_t *)b)[2] = ((u_int8_t *)a)[2];			\
 	((u_int8_t *)b)[3] = ((u_int8_t *)a)[3];			\
 }
+#undef	P_32_SWAP
 #define	P_32_SWAP(a) {							\
 	u_int32_t _tmp;							\
 	P_32_COPY(a, &_tmp);						\
@@ -73,16 +120,19 @@
  *	P_16_COPY	copy potentially unaligned 2 byte quantities
  *	P_16_SWAP	swap a referenced memory location
  */
+#undef	M_16_SWAP
 #define	M_16_SWAP(a) {							\
 	u_int16_t _tmp;							\
 	_tmp = (u_int16_t)a;						\
 	((u_int8_t *)&a)[0] = ((u_int8_t *)&_tmp)[1];			\
 	((u_int8_t *)&a)[1] = ((u_int8_t *)&_tmp)[0];			\
 }
+#undef	P_16_COPY
 #define	P_16_COPY(a, b) {						\
 	((u_int8_t *)b)[0] = ((u_int8_t *)a)[0];			\
 	((u_int8_t *)b)[1] = ((u_int8_t *)a)[1];			\
 }
+#undef	P_16_SWAP
 #define	P_16_SWAP(a) {							\
 	u_int16_t _tmp;							\
 	P_16_COPY(a, &_tmp);						\
@@ -90,10 +140,12 @@
 	((u_int8_t *)a)[1] = ((u_int8_t *)&_tmp)[0];			\
 }
 
+#undef	SWAP32
 #define	SWAP32(p) {							\
 	P_32_SWAP(p);							\
 	(p) += sizeof(u_int32_t);					\
 }
+#undef	SWAP16
 #define	SWAP16(p) {							\
 	P_16_SWAP(p);							\
 	(p) += sizeof(u_int16_t);					\
@@ -104,10 +156,12 @@
  * pointers to the right size memory locations; the portability magic for
  * finding the real system functions isn't worth the effort.
  */
+#undef	DB_HTONL
 #define	DB_HTONL(p) do {						\
 	if (!__db_isbigendian())					\
 		P_32_SWAP(p);						\
 } while (0)
+#undef	DB_NTOHL
 #define	DB_NTOHL(p) do {						\
 	if (!__db_isbigendian())					\
 		P_32_SWAP(p);						\
diff --git a/storage/bdb/dbinc/db_upgrade.h b/storage/bdb/dbinc/db_upgrade.h
index 3ccba810889396bd820189b6c43d90b6800dbdb8..e7ac0bc96e70563b7a9c065b9d0cd970fe5693e0 100644
--- a/storage/bdb/dbinc/db_upgrade.h
+++ b/storage/bdb/dbinc/db_upgrade.h
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: db_upgrade.h,v 1.10 2002/01/11 15:52:26 bostic Exp $
+ * $Id: db_upgrade.h,v 1.12 2004/01/28 03:36:02 bostic Exp $
  */
 
 #ifndef _DB_UPGRADE_H_
diff --git a/storage/bdb/dbinc/db_verify.h b/storage/bdb/dbinc/db_verify.h
index 949c9a2a6a1469db99889cb1ed47a7c90a57bbf4..528ba8f04cbacf8955c5e029322e43ceaa59c71e 100644
--- a/storage/bdb/dbinc/db_verify.h
+++ b/storage/bdb/dbinc/db_verify.h
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: db_verify.h,v 1.26 2002/08/06 06:37:08 bostic Exp $
+ * $Id: db_verify.h,v 1.34 2004/05/20 14:34:12 bostic Exp $
  */
 
 #ifndef _DB_VERIFY_H_
@@ -19,25 +19,24 @@
  * EPRINT is the macro for error printing.  Takes as an arg the arg set
  * for DB->err.
  */
-#define	EPRINT(x)							\
-	do {								\
-		if (!LF_ISSET(DB_SALVAGE))				\
-			__db_err x;					\
-	} while (0)
+#define	EPRINT(x) do {							\
+	if (!LF_ISSET(DB_SALVAGE))					\
+		__db_err x;						\
+} while (0)
 
 /* For fatal type errors--i.e., verifier bugs. */
 #define	TYPE_ERR_PRINT(dbenv, func, pgno, ptype)			\
-    EPRINT(((dbenv), "Page %lu: %s called on nonsensical page of type %lu", \
-	(u_long)(pgno), (func), (u_long)(ptype)));
+	EPRINT(((dbenv),						\
+	    "Page %lu: %s called on nonsensical page of type %lu",	\
+	    (u_long)(pgno), (func), (u_long)(ptype)));
 
 /* Complain about a totally zeroed page where we don't expect one. */
-#define	ZEROPG_ERR_PRINT(dbenv, pgno, str)				   \
-    do {								   \
-	    EPRINT(((dbenv), "Page %lu: %s is of inappropriate type %lu",  \
-		(u_long)(pgno), str, (u_long)P_INVALID));		   \
-	    EPRINT(((dbenv), "Page %lu: totally zeroed page",		   \
-		(u_long)(pgno)));					   \
-    } while (0)
+#define	ZEROPG_ERR_PRINT(dbenv, pgno, str) do {				\
+	EPRINT(((dbenv), "Page %lu: %s is of inappropriate type %lu",	\
+	    (u_long)(pgno), str, (u_long)P_INVALID));			\
+	EPRINT(((dbenv), "Page %lu: totally zeroed page",		\
+	    (u_long)(pgno)));						\
+} while (0)
 
 /*
  * Note that 0 is, in general, a valid pgno, despite equalling PGNO_INVALID;
@@ -127,10 +126,18 @@ struct __vrfy_dbinfo {
 	/* Queue needs these to verify data pages in the first pass. */
 	u_int32_t	re_len;
 	u_int32_t	rec_page;
+	u_int32_t	page_ext;
+	u_int32_t       first_recno;
+	u_int32_t       last_recno;
+	int		nextents;
+	db_pgno_t	*extents;
 
 #define	SALVAGE_PRINTABLE	0x01	/* Output printable chars literally. */
 #define	SALVAGE_PRINTHEADER	0x02	/* Print the unknown-key header. */
 #define	SALVAGE_PRINTFOOTER	0x04	/* Print the unknown-key footer. */
+#define	VRFY_LEAFCHAIN_BROKEN	0x08	/* Lost one or more Btree leaf pgs. */
+#define	VRFY_QMETA_SET		0x10    /* We've seen a QUEUE meta page and
+					   set things up for it. */
 	u_int32_t	flags;
 }; /* VRFY_DBINFO */
 
@@ -190,6 +197,7 @@ struct __vrfy_pageinfo {
 }; /* VRFY_PAGEINFO */
 
 struct __vrfy_childinfo {
+	/* The following fields are set by the caller of __db_vrfy_childput. */
 	db_pgno_t	pgno;
 
 #define	V_DUPLICATE	1		/* off-page dup metadata */
@@ -199,6 +207,9 @@ struct __vrfy_childinfo {
 	db_recno_t	nrecs;		/* record count on a btree subtree */
 	u_int32_t	tlen;		/* ovfl. item total size */
 
+	/* The following field is maintained by __db_vrfy_childput. */
+	u_int32_t	refcnt;		/* # of times parent points to child. */
+
 	LIST_ENTRY(__vrfy_childinfo) links;
 }; /* VRFY_CHILDINFO */
 
diff --git a/storage/bdb/dbinc/debug.h b/storage/bdb/dbinc/debug.h
index 21f80387cccb19da25e61bd207c75b53f0ac76b6..068c8af2b0d70f85083465e226d02b75df501517 100644
--- a/storage/bdb/dbinc/debug.h
+++ b/storage/bdb/dbinc/debug.h
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1998-2002
+ * Copyright (c) 1998-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: debug.h,v 11.31 2002/08/06 06:37:08 bostic Exp $
+ * $Id: debug.h,v 11.44 2004/09/24 00:43:18 bostic Exp $
  */
 
 #ifndef _DB_DEBUG_H_
@@ -14,6 +14,13 @@
 extern "C" {
 #endif
 
+/*
+ * Turn on additional error checking in gcc 3.X.
+ */
+#if !defined(__GNUC__) || __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
+#define	__attribute__(s)
+#endif
+
 /*
  * When running with #DIAGNOSTIC defined, we smash memory and do memory
  * guarding with a special byte value.
@@ -23,13 +30,25 @@ extern "C" {
 
 /*
  * DB assertions.
+ *
+ * Use __STDC__ rather than STDC_HEADERS, the #e construct is ANSI C specific.
  */
-#if defined(DIAGNOSTIC) && defined(__STDC__)
+#if defined(__STDC__) && defined(DIAGNOSTIC)
 #define	DB_ASSERT(e)	((e) ? (void)0 : __db_assert(#e, __FILE__, __LINE__))
 #else
 #define	DB_ASSERT(e)
 #endif
 
+/*
+ * "Shut that bloody compiler up!"
+ *
+ * Unused, or not-used-yet variable.  We need to write and then read the
+ * variable, some compilers are too bloody clever by half.
+ */
+#define	COMPQUIET(n, v)							\
+	(n) = (v);							\
+	(n) = (n)
+
 /*
  * Purify and other run-time tools complain about uninitialized reads/writes
  * of structure fields whose only purpose is padding, as well as when heap
@@ -42,22 +61,22 @@ extern "C" {
 #endif
 
 /*
- * Error message handling.  Use a macro instead of a function because va_list
+ * Message handling.  Use a macro instead of a function because va_list
  * references to variadic arguments cannot be reset to the beginning of the
  * variadic argument list (and then rescanned), by functions other than the
  * original routine that took the variadic list of arguments.
  */
-#if defined(__STDC__) || defined(__cplusplus)
-#define	DB_REAL_ERR(env, error, error_set, stderr_default, fmt) {	\
+#if defined(STDC_HEADERS) || defined(__cplusplus)
+#define	DB_REAL_ERR(env, error, error_set, default_stream, fmt) {	\
 	va_list ap;							\
 									\
-	/* Call the user's callback function, if specified. */		\
+	/* Call the application's callback function, if specified. */	\
 	va_start(ap, fmt);						\
 	if ((env) != NULL && (env)->db_errcall != NULL)			\
 		__db_errcall(env, error, error_set, fmt, ap);		\
 	va_end(ap);							\
 									\
-	/* Write to the user's file descriptor, if specified. */	\
+	/* Write to the application's file descriptor, if specified. */\
 	va_start(ap, fmt);						\
 	if ((env) != NULL && (env)->db_errfile != NULL)			\
 		__db_errfile(env, error, error_set, fmt, ap);		\
@@ -68,22 +87,22 @@ extern "C" {
 	 * write to the default.					\
 	 */								\
 	va_start(ap, fmt);						\
-	if ((stderr_default) && ((env) == NULL ||			\
+	if ((default_stream) && ((env) == NULL ||			\
 	    ((env)->db_errcall == NULL && (env)->db_errfile == NULL)))	\
 		__db_errfile(env, error, error_set, fmt, ap);		\
 	va_end(ap);							\
 }
 #else
-#define	DB_REAL_ERR(env, error, error_set, stderr_default, fmt) {	\
+#define	DB_REAL_ERR(env, error, error_set, default_stream, fmt) {	\
 	va_list ap;							\
 									\
-	/* Call the user's callback function, if specified. */		\
+	/* Call the application's callback function, if specified. */	\
 	va_start(ap);							\
 	if ((env) != NULL && (env)->db_errcall != NULL)			\
 		__db_errcall(env, error, error_set, fmt, ap);		\
 	va_end(ap);							\
 									\
-	/* Write to the user's file descriptor, if specified. */	\
+	/* Write to the application's file descriptor, if specified. */\
 	va_start(ap);							\
 	if ((env) != NULL && (env)->db_errfile != NULL)			\
 		__db_errfile(env, error, error_set, fmt, ap);		\
@@ -94,12 +113,57 @@ extern "C" {
 	 * write to the default.					\
 	 */								\
 	va_start(ap);							\
-	if ((stderr_default) && ((env) == NULL ||			\
+	if ((default_stream) && ((env) == NULL ||			\
 	    ((env)->db_errcall == NULL && (env)->db_errfile == NULL)))	\
 		__db_errfile(env, error, error_set, fmt, ap);		\
 	va_end(ap);							\
 }
 #endif
+#if defined(STDC_HEADERS) || defined(__cplusplus)
+#define	DB_REAL_MSG(env, fmt) {						\
+	va_list ap;							\
+									\
+	/* Call the application's callback function, if specified. */	\
+	va_start(ap, fmt);						\
+	if ((env) != NULL && (env)->db_msgcall != NULL)			\
+		__db_msgcall(env, fmt, ap);				\
+	va_end(ap);							\
+									\
+	/*								\
+	 * If the application specified a file descriptor, or we wrote	\
+	 * to neither the application's callback routine or to its file	\
+	 * descriptor, write to stdout.					\
+	 */								\
+	va_start(ap, fmt);						\
+	if ((env) == NULL ||						\
+	    (env)->db_msgfile != NULL || (env)->db_msgcall == NULL) {	\
+		__db_msgfile(env, fmt, ap);				\
+	}								\
+	va_end(ap);							\
+}
+#else
+#define	DB_REAL_MSG(env, fmt) {						\
+	va_list ap;							\
+									\
+	/* Call the application's callback function, if specified. */	\
+	va_start(ap);							\
+	if ((env) != NULL && (env)->db_msgcall != NULL)			\
+		__db_msgcall(env, fmt, ap);				\
+	va_end(ap);							\
+									\
+	/*								\
+	 * If the application specified a file descriptor, or we wrote	\
+	 * to neither the application's callback routine or to its file	\
+	 * descriptor, write to stdout.					\
+	 */								\
+	va_start(ap);							\
+	if ((env) == NULL ||						\
+	    (env)->db_msgfile != NULL || (env)->db_msgcall == NULL) {	\
+		__db_msgfile(env, fmt, ap);				\
+	}								\
+	va_end(ap);							\
+}
+#endif
 
 /*
  * Debugging macro to log operations.
@@ -140,14 +204,12 @@ extern "C" {
  * Hook for testing subdb locks.
  */
 #if CONFIG_TEST
-#define	DB_TEST_SUBLOCKS(env, flags)					\
-do {									\
+#define	DB_TEST_SUBLOCKS(env, flags) do {				\
 	if ((env)->test_abort == DB_TEST_SUBDB_LOCKS)			\
 		(flags) |= DB_LOCK_NOWAIT;				\
 } while (0)
 
-#define	DB_ENV_TEST_RECOVERY(env, val, ret, name)			\
-do {									\
+#define	DB_ENV_TEST_RECOVERY(env, val, ret, name) do {			\
 	int __ret;							\
 	PANIC_CHECK((env));						\
 	if ((env)->test_copy == (val)) {				\
@@ -163,15 +225,14 @@ do {									\
 	}								\
 } while (0)
 
-#define	DB_TEST_RECOVERY(dbp, val, ret, name)				\
-do {									\
+#define	DB_TEST_RECOVERY(dbp, val, ret, name) do {			\
 	int __ret;							\
 	PANIC_CHECK((dbp)->dbenv);					\
 	if ((dbp)->dbenv->test_copy == (val)) {				\
 		/* Copy the file. */					\
 		if (F_ISSET((dbp),					\
 		    DB_AM_OPEN_CALLED) && (dbp)->mpf != NULL)		\
-			(void)(dbp)->sync((dbp), 0);			\
+			(void)__db_sync(dbp);				\
 		if ((__ret =						\
 		    __db_testcopy((dbp)->dbenv, (dbp), (name))) != 0)	\
 			(ret) = __db_panic((dbp)->dbenv, __ret);	\
@@ -185,11 +246,16 @@ do {									\
 } while (0)
 
 #define	DB_TEST_RECOVERY_LABEL	db_tr_err:
+
+#define	DB_TEST_CHECKPOINT(env, val)					\
+	if ((val) != 0)							\
+		__os_sleep((env), (u_long)(val), 0)
 #else
 #define	DB_TEST_SUBLOCKS(env, flags)
 #define	DB_ENV_TEST_RECOVERY(env, val, ret, name)
 #define	DB_TEST_RECOVERY(dbp, val, ret, name)
 #define	DB_TEST_RECOVERY_LABEL
+#define	DB_TEST_CHECKPOINT(env, val)
 #endif
 
 #if defined(__cplusplus)
diff --git a/storage/bdb/dbinc/fop.h b/storage/bdb/dbinc/fop.h
index c438ef7ef40c2b1e9035e84b7af7efce9b9551ef..ef87ff6e25abba76553500f4305c44838f040078 100644
--- a/storage/bdb/dbinc/fop.h
+++ b/storage/bdb/dbinc/fop.h
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
+ * Copyright (c) 2001-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: fop.h,v 11.3 2002/03/27 04:34:54 bostic Exp $
+ * $Id: fop.h,v 11.5 2004/01/28 03:36:02 bostic Exp $
  */
 
 #ifndef	_FOP_H_
diff --git a/storage/bdb/dbinc/globals.h b/storage/bdb/dbinc/globals.h
index 3441ade2ea91e1f5c4a0a70af715854e4b6b9ea5..95d96533a7470e39c21fca2b84cbe3fc64190af6 100644
--- a/storage/bdb/dbinc/globals.h
+++ b/storage/bdb/dbinc/globals.h
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: globals.h,v 11.1 2002/07/12 18:56:41 bostic Exp $
+ * $Id: globals.h,v 11.9 2004/09/17 22:00:27 mjc Exp $
  */
 
 /*******************************************************
@@ -17,7 +17,6 @@
 #endif
 
 typedef struct __db_globals {
-	u_int32_t no_write_errors;	/* write error testing disallowed */
 #ifdef HAVE_VXWORKS
 	u_int32_t db_global_init;	/* VxWorks: inited */
 	SEM_ID db_global_lock;		/* VxWorks: global semaphore */
@@ -25,21 +24,26 @@ typedef struct __db_globals {
 					/* XA: list of opened environments. */
 	TAILQ_HEAD(__db_envq, __db_env) db_envq;
 
+	char *db_line;			/* DB display string. */
+
 	int	(*j_close) __P((int));	/* Underlying OS interface jump table.*/
 	void	(*j_dirfree) __P((char **, int));
 	int	(*j_dirlist) __P((const char *, char ***, int *));
 	int	(*j_exists) __P((const char *, int *));
 	void	(*j_free) __P((void *));
 	int	(*j_fsync) __P((int));
+	int	(*j_ftruncate) __P((int, off_t));
 	int	(*j_ioinfo) __P((const char *,
 		    int, u_int32_t *, u_int32_t *, u_int32_t *));
 	void   *(*j_malloc) __P((size_t));
 	int	(*j_map) __P((char *, size_t, int, int, void **));
 	int	(*j_open) __P((const char *, int, ...));
+	ssize_t	(*j_pread) __P((int, void *, size_t, off_t));
+	ssize_t	(*j_pwrite) __P((int, const void *, size_t, off_t));
 	ssize_t	(*j_read) __P((int, void *, size_t));
 	void   *(*j_realloc) __P((void *, size_t));
 	int	(*j_rename) __P((const char *, const char *));
-	int	(*j_seek) __P((int, size_t, db_pgno_t, u_int32_t, int, int));
+	int	(*j_seek) __P((int, off_t, int));
 	int	(*j_sleep) __P((u_long, u_long));
 	int	(*j_unlink) __P((const char *));
 	int	(*j_unmap) __P((void *, size_t));
@@ -49,13 +53,18 @@ typedef struct __db_globals {
 
 #ifdef DB_INITIALIZE_DB_GLOBALS
 DB_GLOBALS __db_global_values = {
-	0,				/* write error testing disallowed */
 #ifdef HAVE_VXWORKS
 	0,				/* VxWorks: initialized */
 	NULL,				/* VxWorks: global semaphore */
 #endif
 					/* XA: list of opened environments. */
 	{NULL, &__db_global_values.db_envq.tqh_first},
+
+	"=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=",
+
+	NULL,
+	NULL,
+	NULL,
 	NULL,
 	NULL,
 	NULL,
diff --git a/storage/bdb/dbinc/hash.h b/storage/bdb/dbinc/hash.h
index 98289735fc4997d3eb6fd1b3751dcc95c41c9861..10059a5e027ee669b4bd07d608f5c93d5cd69a05 100644
--- a/storage/bdb/dbinc/hash.h
+++ b/storage/bdb/dbinc/hash.h
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -39,7 +39,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: hash.h,v 11.26 2002/03/27 04:34:54 bostic Exp $
+ * $Id: hash.h,v 11.28 2004/01/28 03:36:02 bostic Exp $
  */
 
 #ifndef	_DB_HASH_H_
diff --git a/storage/bdb/dbinc/hmac.h b/storage/bdb/dbinc/hmac.h
index 16f61fb58adb0a72be0304112b3a04707e54c43e..439537927ea61f92c6422d6291fc82437483a7d8 100644
--- a/storage/bdb/dbinc/hmac.h
+++ b/storage/bdb/dbinc/hmac.h
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: hmac.h,v 1.3 2002/08/06 06:37:08 bostic Exp $
+ * $Id: hmac.h,v 1.5 2004/01/28 03:36:02 bostic Exp $
  */
 
 #ifndef	_DB_HMAC_H_
diff --git a/storage/bdb/dbinc/lock.h b/storage/bdb/dbinc/lock.h
index 7ddc9ce99884c9aa0929d4d39761a11ae0912231..e59abbff84c79913395a63a5c5177adc3201280b 100644
--- a/storage/bdb/dbinc/lock.h
+++ b/storage/bdb/dbinc/lock.h
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: lock.h,v 11.42 2002/05/18 01:34:13 bostic Exp $
+ * $Id: lock.h,v 11.53 2004/09/22 21:14:56 ubell Exp $
  */
 
 #ifndef	_DB_LOCK_H_
@@ -33,7 +33,8 @@
  * for the NUMWRITES option to deadlock detection.
  */
 #define	IS_WRITELOCK(m) \
-	((m) == DB_LOCK_WRITE || (m) == DB_LOCK_IWRITE || (m) == DB_LOCK_IWR)
+	((m) == DB_LOCK_WRITE || (m) == DB_LOCK_WWRITE || \
+	    (m) == DB_LOCK_IWRITE || (m) == DB_LOCK_IWR)
 
 /*
  * Lock timers.
@@ -45,8 +46,13 @@ typedef struct {
 
 #define	LOCK_TIME_ISVALID(time)		((time)->tv_sec != 0)
 #define	LOCK_SET_TIME_INVALID(time)	((time)->tv_sec = 0)
+#define	LOCK_TIME_ISMAX(time)		((time)->tv_sec == UINT32_MAX)
+#define	LOCK_SET_TIME_MAX(time)		((time)->tv_sec = UINT32_MAX)
 #define	LOCK_TIME_EQUAL(t1, t2)						\
 	((t1)->tv_sec == (t2)->tv_sec && (t1)->tv_usec == (t2)->tv_usec)
+#define	LOCK_TIME_GREATER(t1, t2)					\
+	((t1)->tv_sec > (t2)->tv_sec ||					\
+	((t1)->tv_sec == (t2)->tv_sec && (t1)->tv_usec > (t2)->tv_usec))
 
 /*
  * DB_LOCKREGION --
@@ -55,6 +61,7 @@ typedef struct {
 typedef struct __db_lockregion {
 	u_int32_t	need_dd;	/* flag for deadlock detector */
 	u_int32_t	detect;		/* run dd on every conflict */
+	db_timeval_t	next_timeout;	/* next time to expire a lock */
 					/* free lock header */
 	SH_TAILQ_HEAD(__flock) free_locks;
 					/* free obj header */
@@ -89,7 +96,7 @@ typedef struct __db_lockregion {
  */
 typedef struct __sh_dbt {
 	u_int32_t size;			/* Byte length. */
-	ssize_t   off;			/* Region offset. */
+	roff_t    off;			/* Region offset. */
 } SH_DBT;
 
 #define	SH_DBT_PTR(p)	((void *)(((u_int8_t *)(p)) + (p)->off))
@@ -101,8 +108,8 @@ typedef struct __db_lockobj {
 	SH_DBT	lockobj;		/* Identifies object locked. */
 	SH_TAILQ_ENTRY links;		/* Links for free list or hash list. */
 	SH_TAILQ_ENTRY dd_links;	/* Links for dd list. */
-	SH_TAILQ_HEAD(__wait) waiters;	/* List of waiting locks. */
-	SH_TAILQ_HEAD(__hold) holders;	/* List of held locks. */
+	SH_TAILQ_HEAD(__waitl) waiters;	/* List of waiting locks. */
+	SH_TAILQ_HEAD(__holdl) holders;	/* List of held locks. */
 					/* Declare room in the object to hold
 					 * typical DB lock structures so that
 					 * we do not have to allocate them from
@@ -118,8 +125,8 @@ typedef struct __db_locker {
 	u_int32_t dd_id;		/* Deadlock detector id. */
 	u_int32_t nlocks;		/* Number of locks held. */
 	u_int32_t nwrites;		/* Number of write locks held. */
-	size_t master_locker;		/* Locker of master transaction. */
-	size_t parent_locker;		/* Parent of this child. */
+	roff_t  master_locker;		/* Locker of master transaction. */
+	roff_t  parent_locker;		/* Parent of this child. */
 	SH_LIST_HEAD(_child) child_locker;	/* List of descendant txns;
 						   only used in a "master"
 						   txn. */
@@ -153,9 +160,13 @@ typedef struct __db_locktab {
 	DB_HASHTAB	*locker_tab;	/* Beginning of locker hash table. */
 } DB_LOCKTAB;
 
-/* Test for conflicts. */
+/*
+ * Test for conflicts.
+ *
+ * Cast HELD and WANTED to ints, they are usually db_lockmode_t enums.
+ */
 #define	CONFLICTS(T, R, HELD, WANTED) \
-	(T)->conflicts[(HELD) * (R)->stat.st_nmodes + (WANTED)]
+	(T)->conflicts[((int)HELD) * (R)->stat.st_nmodes + ((int)WANTED)]
 
 #define	OBJ_LINKS_VALID(L) ((L)->links.stqe_prev != -1)
 
@@ -172,7 +183,7 @@ struct __db_lock {
 	SH_LIST_ENTRY	locker_links;	/* List of locks held by a locker. */
 	u_int32_t	refcount;	/* Reference count the lock. */
 	db_lockmode_t	mode;		/* What sort of lock. */
-	ssize_t		obj;		/* Relative offset of object struct. */
+	roff_t		obj;		/* Relative offset of object struct. */
 	db_status_t	status;		/* Status of this lock. */
 };
 
@@ -180,8 +191,6 @@ struct __db_lock {
  * Flag values for __lock_put_internal:
  * DB_LOCK_DOALL:     Unlock all references in this lock (instead of only 1).
  * DB_LOCK_FREE:      Free the lock (used in checklocker).
- * DB_LOCK_IGNOREDEL: Remove from the locker hash table even if already
-		      deleted (used in checklocker).
  * DB_LOCK_NOPROMOTE: Don't bother running promotion when releasing locks
  *		      (used by __lock_put_internal).
  * DB_LOCK_UNLINK:    Remove from the locker links (used in checklocker).
@@ -189,11 +198,12 @@ struct __db_lock {
  * we pass some of those around (i.e., DB_LOCK_REMOVE).
  */
 #define	DB_LOCK_DOALL		0x010000
-#define	DB_LOCK_FREE		0x020000
-#define	DB_LOCK_IGNOREDEL	0x040000
+#define	DB_LOCK_DOWNGRADE	0x020000
+#define	DB_LOCK_FREE		0x040000
 #define	DB_LOCK_NOPROMOTE	0x080000
 #define	DB_LOCK_UNLINK		0x100000
-#define	DB_LOCK_NOWAITERS	0x200000
+#define	DB_LOCK_NOREGION	0x200000
+#define	DB_LOCK_NOWAITERS	0x400000
 
 /*
  * Macros to get/release different types of mutexes.
@@ -205,8 +215,8 @@ struct __db_lock {
 #define	LOCKER_LOCK(lt, reg, locker, ndx)				\
 	ndx = __lock_locker_hash(locker) % (reg)->locker_t_size;
 
-#define	LOCKREGION(dbenv, lt)  R_LOCK((dbenv), &(lt)->reginfo)
-#define	UNLOCKREGION(dbenv, lt)  R_UNLOCK((dbenv), &(lt)->reginfo)
+#define	LOCKREGION(dbenv, lt)  R_LOCK((dbenv), &((DB_LOCKTAB *)lt)->reginfo)
+#define	UNLOCKREGION(dbenv, lt)  R_UNLOCK((dbenv), &((DB_LOCKTAB *)lt)->reginfo)
 
 #include "dbinc_auto/lock_ext.h"
 #endif /* !_DB_LOCK_H_ */
diff --git a/storage/bdb/dbinc/log.h b/storage/bdb/dbinc/log.h
index 434994528ea06c58b14a9771bdda6356d9460f90..9a8690138b784908858d1257ea15298b068e1df9 100644
--- a/storage/bdb/dbinc/log.h
+++ b/storage/bdb/dbinc/log.h
@@ -1,15 +1,60 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: log.h,v 11.60 2002/08/06 06:37:08 bostic Exp $
+ * $Id: log.h,v 11.90 2004/10/15 16:59:39 bostic Exp $
  */
 
 #ifndef _LOG_H_
 #define	_LOG_H_
 
+/*******************************************************
+ * DBREG:
+ *	The DB file register code keeps track of open files.  It's stored
+ *	in the log subsystem's shared region, and so appears in the log.h
+ *	header file, but is logically separate.
+ *******************************************************/
+/*
+ * The per-process table that maps log file-id's to DB structures.
+ */
+typedef	struct __db_entry {
+	DB	*dbp;			/* Open dbp for this file id. */
+	int	deleted;		/* File was not found during open. */
+} DB_ENTRY;
+
+/*
+ * FNAME --
+ *	File name and id.
+ */
+struct __fname {
+	SH_TAILQ_ENTRY q;		/* File name queue. */
+
+	int32_t   id;			/* Logging file id. */
+	DBTYPE	  s_type;		/* Saved DB type. */
+
+	roff_t	  name_off;		/* Name offset. */
+	db_pgno_t meta_pgno;		/* Page number of the meta page. */
+	u_int8_t  ufid[DB_FILE_ID_LEN];	/* Unique file id. */
+
+	u_int32_t create_txnid;		/*
+					 * Txn ID of the DB create, stored so
+					 * we can log it at register time.
+					 */
+	int	  is_durable;		/* Is this file durable or not. */
+};
+
+/* File open/close register log record opcodes. */
+#define	DBREG_CHKPNT	1		/* Checkpoint: file name/id dump. */
+#define	DBREG_CLOSE	2		/* File close. */
+#define	DBREG_OPEN	3		/* File open. */
+#define	DBREG_RCLOSE	4		/* File close after recovery. */
+
+/*******************************************************
+ * LOG:
+ *	The log subsystem information.
+ *******************************************************/
 struct __db_log;	typedef struct __db_log DB_LOG;
 struct __hdr;		typedef struct __hdr HDR;
 struct __log;		typedef struct __log LOG;
@@ -20,17 +65,11 @@ struct __log_persist;	typedef struct __log_persist LOGP;
 #define	LFNAME_V1	"log.%05d"	/* Log file name template, rev 1. */
 
 #define	LG_MAX_DEFAULT		(10 * MEGABYTE)	/* 10 MB. */
+#define	LG_MAX_INMEM		(256 * 1024)	/* 256 KB. */
 #define	LG_BSIZE_DEFAULT	(32 * 1024)	/* 32 KB. */
+#define	LG_BSIZE_INMEM		(1 * MEGABYTE)	/* 1 MB. */
 #define	LG_BASE_REGION_SIZE	(60 * 1024)	/* 60 KB. */
 
-/*
- * The per-process table that maps log file-id's to DB structures.
- */
-typedef	struct __db_entry {
-	DB	*dbp;			/* Open dbp for this file id. */
-	int	deleted;		/* File was not found during open. */
-} DB_ENTRY;
-
 /*
  * DB_LOG
  *	Per-process log structure.
@@ -52,12 +91,10 @@ struct __db_log {
 
 /*
  * These fields are always accessed while the region lock is held, so they do
- * not have to be protected by the thread lock as well, OR, they are only used
- * when threads are not being used, i.e. most cursor operations are disallowed
- * on threaded logs.
+ * not have to be protected by the thread lock as well.
  */
 	u_int32_t lfname;		/* Log file "name". */
-	DB_FH	  lfh;			/* Log file handle. */
+	DB_FH	 *lfhp;			/* Log file handle. */
 
 	u_int8_t *bufp;			/* Region buffer. */
 
@@ -67,8 +104,7 @@ struct __db_log {
 
 #define	DBLOG_RECOVER		0x01	/* We are in recovery. */
 #define	DBLOG_FORCE_OPEN	0x02	/* Force the DB open even if it appears
-					 * to be deleted.
-					 */
+					 * to be deleted. */
 	u_int32_t flags;
 };
 
@@ -124,8 +160,8 @@ struct __log {
 	SH_TAILQ_HEAD(__fq1) fq;	/* List of file names. */
 	int32_t	fid_max;		/* Max fid allocated. */
 	roff_t	free_fid_stack;		/* Stack of free file ids. */
-	int	free_fids;		/* Height of free fid stack. */
-	int	free_fids_alloced;	/* Number of free fid slots alloc'ed. */
+	u_int	free_fids;		/* Height of free fid stack. */
+	u_int	free_fids_alloced;	/* N free fid slots allocated. */
 
 	/*
 	 * The lsn LSN is the file offset that we're about to write and which
@@ -144,7 +180,16 @@ struct __log {
 	u_int32_t w_off;		/* Current write offset in the file. */
 	u_int32_t len;			/* Length of the last record. */
 
+	DB_LSN	  active_lsn;		/* Oldest active LSN in the buffer. */
+	size_t	  a_off;		/* Offset in the buffer of first active
+					   file. */
+
 	/*
+	 * Due to alignment constraints on some architectures (e.g. HP-UX),
+	 * DB_MUTEXes must be the first element of shalloced structures,
+	 * and as a corollary there can be only one per structure.  Thus,
+	 * flush_mutex_off points to a mutex in a separately-allocated chunk.
+	 *
 	 * The s_lsn LSN is the last LSN that we know is on disk, not just
 	 * written, but synced.  This field is protected by the flush mutex
 	 * rather than by the region mutex.
@@ -156,17 +201,32 @@ struct __log {
 	DB_LOG_STAT stat;		/* Log statistics. */
 
 	/*
+	 * !!! - NOTE that the next 7 fields, waiting_lsn, verify_lsn,
+	 * max_wait_lsn, maxperm_lsn, wait_recs, rcvd_recs,
+	 * and ready_lsn are NOT protected
+	 * by the log region lock.  They are protected by db_rep->db_mutexp.
+	 * If you need access to both, you must acquire db_rep->db_mutexp
+	 * before acquiring the log region lock.
+	 *
 	 * The waiting_lsn is used by the replication system.  It is the
 	 * first LSN that we are holding without putting in the log, because
 	 * we received one or more log records out of order.  Associated with
 	 * the waiting_lsn is the number of log records that we still have to
 	 * receive before we decide that we should request it again.
+	 *
+	 * The max_wait_lsn is used to control retransmission in the face
+	 * of dropped messages.  If we are requesting all records from the
+	 * current gap (i.e., chunk of the log that we are missing), then
+	 * the max_wait_lsn contains the first LSN that we are known to have
+	 * in the __db.rep.db.  If we requested only a single record, then
+	 * the max_wait_lsn has the LSN of that record we requested.
 	 */
 	DB_LSN	  waiting_lsn;		/* First log record after a gap. */
 	DB_LSN	  verify_lsn;		/* LSN we are waiting to verify. */
+	DB_LSN	  max_wait_lsn;		/* Maximum LSN requested. */
+	DB_LSN	  max_perm_lsn;		/* Maximum PERMANENT LSN processed. */
 	u_int32_t wait_recs;		/* Records to wait before requesting. */
 	u_int32_t rcvd_recs;		/* Records received while waiting. */
-
 	/*
 	 * The ready_lsn is also used by the replication system.  It is the
 	 * next LSN we expect to receive.  It's normally equal to "lsn",
@@ -185,18 +245,34 @@ struct __log {
 	 */
 	DB_LSN	cached_ckp_lsn;
 
+	u_int32_t regionmax;		/* Configured size of the region. */
+
 	roff_t	  buffer_off;		/* Log buffer offset in the region. */
 	u_int32_t buffer_size;		/* Log buffer size. */
 
 	u_int32_t log_size;		/* Log file's size. */
 	u_int32_t log_nsize;		/* Next log file's size. */
 
-	u_int32_t ncommit;		/* Number of txns waiting to commit. */
+	/*
+	 * DB_LOG_AUTOREMOVE and DB_LOG_INMEMORY: not protected by a mutex,
+	 * all we care about is if they're zero or non-zero.
+	 */
+	int	  db_log_autoremove;
+	int	  db_log_inmemory;
 
+	u_int32_t ncommit;		/* Number of txns waiting to commit. */
 	DB_LSN	  t_lsn;		/* LSN of first commit */
 	SH_TAILQ_HEAD(__commit) commits;/* list of txns waiting to commit. */
 	SH_TAILQ_HEAD(__free) free_commits;/* free list of commit structs. */
 
+	/*
+	 * In-memory logs maintain a list of the start positions of all log
+	 * files currently active in the in-memory buffer.  This is to make the
+	 * lookup from LSN to log buffer offset efficient.
+	 */
+	SH_TAILQ_HEAD(__logfile) logfiles;
+	SH_TAILQ_HEAD(__free_logfile) free_logfiles;
+
 #ifdef HAVE_MUTEX_SYSTEM_RESOURCES
 #define	LG_MAINT_SIZE	(sizeof(roff_t) * DB_MAX_HANDLES)
 
@@ -206,8 +282,7 @@ struct __log {
 
 /*
  * __db_commit structure --
- *	One of these is allocated for each transaction waiting
- * to commit.
+ *	One of these is allocated for each transaction waiting to commit.
  */
 struct __db_commit {
 	DB_MUTEX	mutex;		/* Mutex for txn to wait on. */
@@ -219,41 +294,72 @@ struct __db_commit {
 };
 
 /*
- * FNAME --
- *	File name and id.
+ * Check for the proper progression of Log Sequence Numbers.
+ * If we are rolling forward the LSN on the page must be greater
+ * than or equal to the previous LSN in log record.
+ * We ignore NOT LOGGED LSNs.  The user did an unlogged update.
+ * We should eventually see a log record that matches and continue
+ * forward.
+ * If truncate is supported then a ZERO LSN implies a page that was
+ * allocated prior to the recovery start pont and then truncated
+ * later in the log.  An allocation of a page after this
+ * page will extend the file, leaving a hole.  We want to
+ * ignore this page until it is truncated again.
+ *
  */
-struct __fname {
-	SH_TAILQ_ENTRY q;		/* File name queue. */
 
-	int32_t id;			/* Logging file id. */
-	DBTYPE	  s_type;		/* Saved DB type. */
+#ifdef HAVE_FTRUNCATE
+#define	CHECK_LSN(redo, cmp, lsn, prev)					\
+	if (DB_REDO(redo) && (cmp) < 0 &&				\
+	    !IS_NOT_LOGGED_LSN(*(lsn)) && !IS_ZERO_LSN(*(lsn))) {	\
+		ret = __db_check_lsn(dbenv, lsn, prev);			\
+		goto out;						\
+	}
+#else
+#define	CHECK_LSN(redo, cmp, lsn, prev)					\
+	if (DB_REDO(redo) && (cmp) < 0 && !IS_NOT_LOGGED_LSN(*(lsn))) {	\
+		ret = __db_check_lsn(dbenv, lsn, prev);			\
+		goto out;						\
+	}
+#endif
 
-	roff_t	  name_off;		/* Name offset. */
-	db_pgno_t meta_pgno;		/* Page number of the meta page. */
-	u_int8_t  ufid[DB_FILE_ID_LEN];	/* Unique file id. */
+/*
+ * Helper for in-memory logs -- check whether an offset is in range
+ * in a ring buffer (inclusive of start, exclusive of end).
+ */
+struct __db_filestart {
+	u_int32_t	file;
+	size_t		b_off;
 
-	u_int32_t create_txnid;		/*
-					 * Txn ID of the DB create, stored so
-					 * we can log it at register time.
-					 */
+	SH_TAILQ_ENTRY	links;		/* Either on free or waiting list. */
 };
 
-/* File open/close register log record opcodes. */
-#define	LOG_CHECKPOINT	1		/* Checkpoint: file name/id dump. */
-#define	LOG_CLOSE	2		/* File close. */
-#define	LOG_OPEN	3		/* File open. */
-#define	LOG_RCLOSE	4		/* File close after recovery. */
+#define	RINGBUF_LEN(lp, start, end)					\
+	((start) < (end) ?						\
+	    (end) - (start) : (lp)->buffer_size - ((start) - (end)))
 
-#define	CHECK_LSN(redo, cmp, lsn, prev)					\
-	DB_ASSERT(!DB_REDO(redo) ||					\
-	    (cmp) >= 0 || IS_NOT_LOGGED_LSN(*lsn));			\
-	if (DB_REDO(redo) && (cmp) < 0 && !IS_NOT_LOGGED_LSN(*(lsn))) {	\
-		__db_err(dbenv,						\
-	"Log sequence error: page LSN %lu %lu; previous LSN %lu %lu",	\
-		    (u_long)(lsn)->file, (u_long)(lsn)->offset,		\
-		    (u_long)(prev)->file, (u_long)(prev)->offset);	\
-		goto out;						\
-	}
+/*
+ * Internal macro to set pointer to the begin_lsn for generated
+ * logging routines.  If begin_lsn is already set then do nothing.
+ */
+#undef DB_SET_BEGIN_LSNP
+#define	DB_SET_BEGIN_LSNP(txn, rlsnp) do {				\
+	DB_LSN *__lsnp;							\
+	TXN_DETAIL *__td;						\
+	__td = R_ADDR(&(txn)->mgrp->reginfo, (txn)->off);		\
+	while (__td->parent != INVALID_ROFF)				\
+		__td = R_ADDR(&(txn)->mgrp->reginfo, __td->parent);	\
+	__lsnp = &__td->begin_lsn;					\
+	if (IS_ZERO_LSN(*__lsnp))					\
+		*(rlsnp) = __lsnp;					\
+} while (0)
+
+/*
+ * These are used in __log_backup to determine which LSN in the
+ * checkpoint record to compare and return.
+ */
+#define	CKPLSN_CMP	0
+#define	LASTCKP_CMP	1
 
 /*
  * Status codes indicating the validity of a log file examined by
diff --git a/storage/bdb/dbinc/mp.h b/storage/bdb/dbinc/mp.h
index 5c805b923649a8e2e70a4ae3eedb469f57dd1201..871bd6df9226f6cd4276f8ef37eddef417eb579e 100644
--- a/storage/bdb/dbinc/mp.h
+++ b/storage/bdb/dbinc/mp.h
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: mp.h,v 11.44 2002/08/06 06:11:21 bostic Exp $
+ * $Id: mp.h,v 11.61 2004/09/17 22:00:27 mjc Exp $
  */
 
 #ifndef	_DB_MP_H_
@@ -18,6 +18,17 @@ struct __mpool;		typedef struct __mpool MPOOL;
 				/* We require at least 20KB of cache. */
 #define	DB_CACHESIZE_MIN	(20 * 1024)
 
+/*
+ * DB_MPOOLFILE initialization methods cannot be called after open is called,
+ * other methods cannot be called before open is called
+ */
+#define	MPF_ILLEGAL_AFTER_OPEN(dbmfp, name)				\
+	if (F_ISSET(dbmfp, MP_OPEN_CALLED))				\
+		return (__db_mi_open((dbmfp)->dbenv, name, 1));
+#define	MPF_ILLEGAL_BEFORE_OPEN(dbmfp, name)				\
+	if (!F_ISSET(dbmfp, MP_OPEN_CALLED))				\
+		return (__db_mi_open((dbmfp)->dbenv, name, 0));
+
 typedef enum {
 	DB_SYNC_ALLOC,		/* Flush for allocation. */
 	DB_SYNC_CACHE,		/* Checkpoint or flush entire cache. */
@@ -74,7 +85,7 @@ struct __db_mpreg {
  *	more frequent than a random data page.
  */
 #define	NCACHE(mp, mf_offset, pgno)					\
-	(((pgno) ^ ((mf_offset) >> 3)) % ((MPOOL *)mp)->nreg)
+	(((pgno) ^ ((u_int32_t)(mf_offset) >> 3)) % ((MPOOL *)mp)->nreg)
 
 /*
  * NBUCKET --
@@ -115,6 +126,12 @@ struct __mpool {
 
 	SH_TAILQ_HEAD(__mpfq) mpfq;	/* List of MPOOLFILEs. */
 
+	/* Configuration information: protected by the region lock. */
+	size_t mp_mmapsize;		/* Maximum file size for mmap. */
+	int    mp_maxopenfd;		/* Maximum open file descriptors. */
+	int    mp_maxwrite;		/* Maximum buffers to write. */
+	int    mp_maxwrite_sleep;	/* Sleep after writing max buffers. */
+
 	/*
 	 * The nreg, regids and maint_off fields are not thread protected,
 	 * as they are initialized during mpool creation, and not modified
@@ -124,7 +141,7 @@ struct __mpool {
 	roff_t	  regids;		/* Array of underlying REGION Ids. */
 
 #ifdef HAVE_MUTEX_SYSTEM_RESOURCES
-	roff_t	    maint_off;		/* Maintenance information offset */
+	roff_t	  maint_off;		/* Maintenance information offset */
 #endif
 
 	/*
@@ -137,10 +154,10 @@ struct __mpool {
 	 * The last_checked and lru_count fields are thread protected by
 	 * the region lock.
 	 */
-	int	    htab_buckets;	/* Number of hash table entries. */
-	roff_t	    htab;		/* Hash table offset. */
-	u_int32_t   last_checked;	/* Last bucket checked for free. */
-	u_int32_t   lru_count;		/* Counter for buffer LRU */
+	u_int32_t htab_buckets;	/* Number of hash table entries. */
+	roff_t	  htab;		/* Hash table offset. */
+	u_int32_t last_checked;	/* Last bucket checked for free. */
+	u_int32_t lru_count;		/* Counter for buffer LRU */
 
 	/*
 	 * The stat fields are generally not thread protected, and cannot be
@@ -149,6 +166,13 @@ struct __mpool {
 	 * region lock).
 	 */
 	DB_MPOOL_STAT stat;		/* Per-cache mpool statistics. */
+
+	/*
+	 * We track page puts so that we can decide when allocation is never
+	 * going to succeed.  We don't lock the field, all we care about is
+	 * if it changes.
+	 */
+	u_int32_t  put_counter;		/* Count of page put calls. */
 };
 
 struct __db_mpool_hash {
@@ -158,6 +182,17 @@ struct __db_mpool_hash {
 
 	u_int32_t	hash_page_dirty;/* Count of dirty pages. */
 	u_int32_t	hash_priority;	/* Minimum priority of bucket buffer. */
+
+#ifdef	HPUX_MUTEX_PAD
+	/*
+	 * !!!
+	 * We allocate the mpool hash buckets as an array, which means that
+	 * they are not individually aligned.  This fails on one platform:
+	 * HPUX 10.20, where mutexes require 16 byte alignment.   This is a
+	 * grievous hack for that single platform.
+	 */
+	u_int8_t	pad[HPUX_MUTEX_PAD];
+#endif
 };
 
 /*
@@ -165,7 +200,7 @@ struct __db_mpool_hash {
  * When the LRU counter wraps, we shift everybody down to a base-relative
  * value.
  */
-#define	MPOOL_BASE_DECREMENT	(UINT32_T_MAX - (UINT32_T_MAX / 4))
+#define	MPOOL_BASE_DECREMENT	(UINT32_MAX - (UINT32_MAX / 4))
 
 /*
  * Mpool priorities from low to high.  Defined in terms of fractions of the
@@ -178,21 +213,6 @@ struct __db_mpool_hash {
 #define	MPOOL_PRI_DIRTY		10	/* Dirty gets a 10% boost. */
 #define	MPOOL_PRI_VERY_HIGH	1	/* Add number of buffers in pool. */
 
-/*
- * MPOOLFILE_IGNORE --
- *	Discard an MPOOLFILE and any buffers it references: update the flags
- *	so we never try to write buffers associated with the file, nor can we
- *	find it when looking for files to join.  In addition, clear the ftype
- *	field, there's no reason to post-process pages, they can be discarded
- *	by any thread.
- *
- * Expects the MPOOLFILE mutex to be held.
- */
-#define	MPOOLFILE_IGNORE(mfp) {						\
-	(mfp)->ftype = 0;						\
-	F_SET(mfp, MP_DEADFILE);					\
-}
-
 /*
  * MPOOLFILE --
  *	Shared DB_MPOOLFILE information.
@@ -206,10 +226,18 @@ struct __mpoolfile {
 
 	roff_t	  path_off;		/* File name location. */
 
+	/*
+	 * We normally don't lock the deadfile field when we read it since we
+	 * only care if the field is zero or non-zero.  We do lock on read when
+	 * searching for a matching MPOOLFILE -- see that code for more detail.
+	 */
+	int32_t	  deadfile;		/* Dirty pages can be discarded. */
+
 	/* Protected by mpool cache 0 region lock. */
 	SH_TAILQ_ENTRY q;		/* List of MPOOLFILEs */
 	db_pgno_t last_pgno;		/* Last page in the file. */
 	db_pgno_t orig_last_pgno;	/* Original last page in the file. */
+	db_pgno_t maxpgno;		/* Maximum page number. */
 
 	/*
 	 * None of the following fields are thread protected.
@@ -218,26 +246,48 @@ struct __mpoolfile {
 	 * without holding a lock.  However, it has to be set before adding
 	 * any buffers to the cache that depend on it being set, so there
 	 * would need to be incorrect operation ordering to have a problem.
-	 *
+	 */
+	int32_t	  ftype;		/* File type. */
+
+	/*
 	 * There are potential races with the priority field because it's read
 	 * without holding a lock.  However, a collision is unlikely and if it
 	 * happens is of little consequence.
+	 */
+	int32_t   priority;		/* Priority when unpinning buffer. */
+
+	/*
+	 * There are potential races with the file_written field (many threads
+	 * may be writing blocks at the same time), and with no_backing_file
+	 * and unlink_on_close fields, as they may be set while other threads
+	 * are reading them.  However, we only care if the field value is zero
+	 * or non-zero, so don't lock the memory.
+	 *
+	 * !!!
+	 * Theoretically, a 64-bit architecture could put two of these fields
+	 * in a single memory operation and we could race.  I have never seen
+	 * an architecture where that's a problem, and I believe Java requires
+	 * that to never be the case.
 	 *
+	 * File_written is set whenever a buffer is marked dirty in the cache.
+	 * It can be cleared in some cases, after all dirty buffers have been
+	 * written AND the file has been flushed to disk.
+	 */
+	int32_t	  file_written;		/* File was written. */
+	int32_t	  no_backing_file;	/* Never open a backing file. */
+	int32_t	  unlink_on_close;	/* Unlink file on last close. */
+
+	/*
 	 * We do not protect the statistics in "stat" because of the cost of
 	 * the mutex in the get/put routines.  There is a chance that a count
 	 * will get lost.
-	 *
-	 * The remaining fields are initialized at open and never subsequently
-	 * modified, except for the MP_DEADFILE, which is only set and never
-	 * unset.  (If there was more than one flag that was subsequently set,
-	 * there might be a race, but with a single flag there can't be.)
 	 */
-	int32_t	  ftype;		/* File type. */
-
-	int32_t   priority;		/* Priority when unpinning buffer. */
-
 	DB_MPOOL_FSTAT stat;		/* Per-file mpool statistics. */
 
+	/*
+	 * The remaining fields are initialized at open and never subsequently
+	 * modified.
+	 */
 	int32_t	  lsn_off;		/* Page's LSN offset. */
 	u_int32_t clear_len;		/* Bytes to clear on page create. */
 
@@ -246,15 +296,28 @@ struct __mpoolfile {
 	roff_t	  pgcookie_len;		/* Pgin/pgout cookie length. */
 	roff_t	  pgcookie_off;		/* Pgin/pgout cookie location. */
 
-#define	MP_CAN_MMAP	0x01		/* If the file can be mmap'd. */
-#define	MP_DEADFILE	0x02		/* Dirty pages can simply be trashed. */
-#define	MP_DIRECT	0x04		/* No OS buffering. */
-#define	MP_EXTENT	0x08		/* Extent file. */
-#define	MP_TEMP		0x10		/* Backing file is a temporary. */
-#define	MP_UNLINK	0x20		/* Unlink file on last close. */
+	/*
+	 * The flags are initialized at open and never subsequently modified.
+	 */
+#define	MP_CAN_MMAP		0x001	/* If the file can be mmap'd. */
+#define	MP_DIRECT		0x002	/* No OS buffering. */
+#define	MP_DURABLE_UNKNOWN	0x004	/* We don't care about durability. */
+#define	MP_EXTENT		0x008	/* Extent file. */
+#define	MP_FAKE_DEADFILE	0x010	/* Deadfile field: fake flag. */
+#define	MP_FAKE_FILEWRITTEN	0x020	/* File_written field: fake flag. */
+#define	MP_FAKE_NB		0x040	/* No_backing_file field: fake flag. */
+#define	MP_FAKE_UOC		0x080	/* Unlink_on_close field: fake flag. */
+#define	MP_NOT_DURABLE		0x100	/* File is not durable. */
+#define	MP_TEMP			0x200	/* Backing file is a temporary. */
 	u_int32_t  flags;
 };
 
+/*
+ * Flags to __memp_bh_free.
+ */
+#define	BH_FREE_FREEMEM		0x01
+#define	BH_FREE_UNLOCKED	0x02
+
 /*
  * BH --
  *	Buffer header.
diff --git a/storage/bdb/dbinc/mutex.h b/storage/bdb/dbinc/mutex.h
index 41bb1b4bb5972a60d6c4a57bc49cfec4c34fe5b5..056d34bab5cd515fe37af4982521a58d7656610c 100644
--- a/storage/bdb/dbinc/mutex.h
+++ b/storage/bdb/dbinc/mutex.h
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: mutex.h,v 11.71 2002/09/10 01:36:48 bostic Exp $
+ * $Id: mutex.h,v 11.100 2004/10/05 14:41:12 mjc Exp $
  */
 
 #ifndef _DB_MUTEX_H_
@@ -77,7 +77,10 @@
 #ifdef HAVE_MUTEX_AIX_CHECK_LOCK
 #include <sys/atomic_op.h>
 typedef int tsl_t;
+
+#ifndef	MUTEX_ALIGN
 #define	MUTEX_ALIGN	sizeof(int)
+#endif
 
 #ifdef LOAD_ACTUAL_MUTEX_CODE
 #define	MUTEX_INIT(x)	0
@@ -86,6 +89,25 @@ typedef int tsl_t;
 #endif
 #endif
 
+/*********************************************************************
+ * Apple/Darwin library functions.
+ *********************************************************************/
+#ifdef HAVE_MUTEX_DARWIN_SPIN_LOCK_TRY
+typedef u_int32_t tsl_t;
+
+#ifndef	MUTEX_ALIGN
+#define	MUTEX_ALIGN	sizeof(int)
+#endif
+
+#ifdef LOAD_ACTUAL_MUTEX_CODE
+extern int _spin_lock_try(tsl_t *);
+extern void _spin_unlock(tsl_t *);
+#define	MUTEX_SET(tsl)          _spin_lock_try(tsl)
+#define	MUTEX_UNSET(tsl)        _spin_unlock(tsl)
+#define	MUTEX_INIT(tsl)         (MUTEX_UNSET(tsl), 0)
+#endif
+#endif
+
 /*********************************************************************
  * General C library functions (msemaphore).
  *
@@ -104,14 +126,17 @@ typedef int tsl_t;
 #define	MUTEX_NO_MALLOC_LOCKS
 #define	MUTEX_NO_SHMGET_LOCKS
 
+#ifndef	MUTEX_ALIGN
 #define	MUTEX_ALIGN	16
+#define	HPUX_MUTEX_PAD	 8
+#endif
 #endif
 
 #if defined(HAVE_MUTEX_MSEM_INIT) || defined(HAVE_MUTEX_HPPA_MSEM_INIT)
 #include <sys/mman.h>
 typedef msemaphore tsl_t;
 
-#ifndef MUTEX_ALIGN
+#ifndef	MUTEX_ALIGN
 #define	MUTEX_ALIGN	sizeof(int)
 #endif
 
@@ -128,7 +153,9 @@ typedef msemaphore tsl_t;
 #ifdef HAVE_MUTEX_PLAN9
 typedef Lock tsl_t;
 
+#ifndef	MUTEX_ALIGN
 #define	MUTEX_ALIGN	sizeof(int)
+#endif
 
 #define	MUTEX_INIT(x)	(memset(x, 0, sizeof(Lock)), 0)
 #define	MUTEX_SET(x)	canlock(x)
@@ -159,7 +186,10 @@ typedef spinlock_t tsl_t;
 #ifdef HAVE_MUTEX_SEMA_INIT
 #include <synch.h>
 typedef sema_t tsl_t;
+
+#ifndef	MUTEX_ALIGN
 #define	MUTEX_ALIGN	 sizeof(int)
+#endif
 
 #ifdef LOAD_ACTUAL_MUTEX_CODE
 #define	MUTEX_DESTROY(x) sema_destroy(x)
@@ -175,7 +205,10 @@ typedef sema_t tsl_t;
 #ifdef HAVE_MUTEX_SGI_INIT_LOCK
 #include <abi_mutex.h>
 typedef abilock_t tsl_t;
+
+#ifndef	MUTEX_ALIGN
 #define	MUTEX_ALIGN	sizeof(int)
+#endif
 
 #ifdef LOAD_ACTUAL_MUTEX_CODE
 #define	MUTEX_INIT(x)	(init_lock(x) != 0)
@@ -194,7 +227,10 @@ typedef abilock_t tsl_t;
 #ifdef HAVE_MUTEX_SOLARIS_LOCK_TRY
 #include <sys/machlock.h>
 typedef lock_t tsl_t;
+
+#ifndef	MUTEX_ALIGN
 #define	MUTEX_ALIGN	sizeof(int)
+#endif
 
 #ifdef LOAD_ACTUAL_MUTEX_CODE
 #define	MUTEX_INIT(x)	0
@@ -209,8 +245,11 @@ typedef lock_t tsl_t;
 #ifdef HAVE_MUTEX_VMS
 #include <sys/mman.h>;
 #include <builtins.h>
-typedef unsigned char tsl_t;
+typedef volatile unsigned char tsl_t;
+
+#ifndef	MUTEX_ALIGN
 #define	MUTEX_ALIGN		sizeof(unsigned int)
+#endif
 
 #ifdef LOAD_ACTUAL_MUTEX_CODE
 #ifdef __ALPHA
@@ -234,7 +273,10 @@ typedef unsigned char tsl_t;
 #ifdef HAVE_MUTEX_VXWORKS
 #include "taskLib.h"
 typedef SEM_ID tsl_t;
+
+#ifndef	MUTEX_ALIGN
 #define	MUTEX_ALIGN		sizeof(unsigned int)
+#endif
 
 #ifdef LOAD_ACTUAL_MUTEX_CODE
 #define	MUTEX_SET(tsl)		(semTake((*tsl), WAIT_FOREVER) == OK)
@@ -249,8 +291,7 @@ typedef SEM_ID tsl_t;
  * trying to initialize the global lock at the same time.
  */
 #undef	DB_BEGIN_SINGLE_THREAD
-#define	DB_BEGIN_SINGLE_THREAD						\
-do {									\
+#define	DB_BEGIN_SINGLE_THREAD do {					\
 	if (DB_GLOBAL(db_global_init))					\
 		(void)semTake(DB_GLOBAL(db_global_lock), WAIT_FOREVER);	\
 	else {								\
@@ -283,7 +324,10 @@ do {									\
  *********************************************************************/
 #ifdef HAVE_MUTEX_WIN16
 typedef unsigned int tsl_t;
+
+#ifndef	MUTEX_ALIGN
 #define	MUTEX_ALIGN		sizeof(unsigned int)
+#endif
 
 #ifdef LOAD_ACTUAL_MUTEX_CODE
 #define	MUTEX_INIT(x)		0
@@ -295,19 +339,34 @@ typedef unsigned int tsl_t;
 /*********************************************************************
  * Win32
  *********************************************************************/
-#ifdef HAVE_MUTEX_WIN32
+#if defined(HAVE_MUTEX_WIN32) || defined(HAVE_MUTEX_WIN32_GCC)
 #define	MUTEX_FIELDS							\
 	LONG tas;							\
 	LONG nwaiters;							\
-	union {								\
-		HANDLE event;	/* Windows event HANDLE for wakeups */	\
-		u_int32_t id;	/* ID used for shared mutexes */	\
-	} /* anonymous */;
+	u_int32_t id;	/* ID used for creating events */		\
 
 #if defined(LOAD_ACTUAL_MUTEX_CODE)
 #define	MUTEX_SET(tsl)		(!InterlockedExchange((PLONG)tsl, 1))
 #define	MUTEX_UNSET(tsl)	(*(tsl) = 0)
 #define	MUTEX_INIT(tsl)		MUTEX_UNSET(tsl)
+
+/*
+ * From Intel's performance tuning documentation (and see SR #6975):
+ * ftp://download.intel.com/design/perftool/cbts/appnotes/sse2/w_spinlock.pdf
+ *
+ * "For this reason, it is highly recommended that you insert the PAUSE
+ * instruction into all spin-wait code immediately. Using the PAUSE
+ * instruction does not affect the correctness of programs on existing
+ * platforms, and it improves performance on Pentium 4 processor platforms."
+ */
+#ifdef HAVE_MUTEX_WIN32
+#ifndef _WIN64
+#define	MUTEX_PAUSE		{__asm{_emit 0xf3}; __asm{_emit 0x90}}
+#endif
+#endif
+#ifdef HAVE_MUTEX_WIN32_GCC
+#define	MUTEX_PAUSE		asm volatile ("rep; nop" : : );
+#endif
 #endif
 #endif
 
@@ -318,9 +377,8 @@ typedef unsigned int tsl_t;
 typedef unsigned char tsl_t;
 
 #ifdef LOAD_ACTUAL_MUTEX_CODE
-/*
- * For gcc/68K, 0 is clear, 1 is set.
- */
+#define	MUTEX_SET_TEST	1		/* gcc/68K: 0 is clear, 1 is set. */
+
 #define	MUTEX_SET(tsl) ({						\
 	register tsl_t *__l = (tsl);					\
 	int __r;							\
@@ -342,14 +400,16 @@ typedef unsigned char tsl_t;
  *********************************************************************/
 #ifdef HAVE_MUTEX_ALPHA_GCC_ASSEMBLY
 typedef u_int32_t tsl_t;
+
+#ifndef	MUTEX_ALIGN
 #define	MUTEX_ALIGN	4
+#endif
 
 #ifdef LOAD_ACTUAL_MUTEX_CODE
 /*
  * For gcc/alpha.  Should return 0 if could not acquire the lock, 1 if
  * lock was acquired properly.
  */
-#ifdef __GNUC__
 static inline int
 MUTEX_SET(tsl_t *tsl) {
 	register tsl_t *__l = tsl;
@@ -377,15 +437,27 @@ MUTEX_UNSET(tsl_t *tsl) {
 	asm volatile("	mb\n");
 	return *tsl = 0;
 }
+
+#define	MUTEX_INIT(tsl)		MUTEX_UNSET(tsl)
+#endif
+#endif
+
+/*********************************************************************
+ * Tru64/cc assembly.
+ *********************************************************************/
+#ifdef HAVE_MUTEX_TRU64_CC_ASSEMBLY
+typedef volatile u_int32_t tsl_t;
+
+#ifndef	MUTEX_ALIGN
+#define	MUTEX_ALIGN	4
 #endif
 
-#ifdef __DECC
+#ifdef LOAD_ACTUAL_MUTEX_CODE
 #include <alpha/builtins.h>
 #define	MUTEX_SET(tsl)		(__LOCK_LONG_RETRY((tsl), 1) != 0)
-#define	MUTEX_UNSET(tsl)	(*(tsl) = 0)
-#endif
+#define	MUTEX_UNSET(tsl)	(__UNLOCK_LONG(tsl))
 
-#define	MUTEX_INIT(tsl)		MUTEX_UNSET(tsl)
+#define	MUTEX_INIT(tsl)		(MUTEX_UNSET(tsl), 0)
 #endif
 #endif
 
@@ -396,15 +468,15 @@ MUTEX_UNSET(tsl_t *tsl) {
 typedef unsigned char tsl_t;
 
 #ifdef LOAD_ACTUAL_MUTEX_CODE
-/*
- * For arm/gcc, 0 is clear, 1 is set.
- */
+#define	MUTEX_SET_TEST	1		/* gcc/arm: 0 is clear, 1 is set. */
+
 #define	MUTEX_SET(tsl) ({						\
 	int __r;							\
-	asm volatile("swpb %0, %1, [%2]"				\
-	    : "=r" (__r) 						\
-	    : "0" (1), "r" (tsl)					\
-	    : "memory"							\
+	asm volatile(							\
+		"swpb	%0, %1, [%2]\n\t"				\
+		"eor	%0, %0, #1\n\t"					\
+	    : "=&r" (__r)						\
+	    : "r" (1), "r" (tsl)					\
 	    );								\
 	__r & 1;							\
 })
@@ -419,7 +491,11 @@ typedef unsigned char tsl_t;
  *********************************************************************/
 #ifdef HAVE_MUTEX_HPPA_GCC_ASSEMBLY
 typedef u_int32_t tsl_t;
+
+#ifndef	MUTEX_ALIGN
 #define	MUTEX_ALIGN	16
+#define	HPUX_MUTEX_PAD	 8
+#endif
 
 #ifdef LOAD_ACTUAL_MUTEX_CODE
 /*
@@ -446,9 +522,8 @@ typedef u_int32_t tsl_t;
 typedef unsigned char tsl_t;
 
 #ifdef LOAD_ACTUAL_MUTEX_CODE
-/*
- * For gcc/ia64, 0 is clear, 1 is set.
- */
+#define	MUTEX_SET_TEST	1		/* gcc/ia64: 0 is clear, 1 is set. */
+
 #define	MUTEX_SET(tsl) ({						\
 	register tsl_t *__l = (tsl);					\
 	long __r;							\
@@ -468,8 +543,7 @@ typedef unsigned char tsl_t;
 /*********************************************************************
  * PowerPC/gcc assembly.
  *********************************************************************/
-#if defined(HAVE_MUTEX_PPC_GENERIC_GCC_ASSEMBLY) ||			\
-    (HAVE_MUTEX_PPC_APPLE_GCC_ASSEMBLY)
+#if defined(HAVE_MUTEX_PPC_GCC_ASSEMBLY)
 typedef u_int32_t tsl_t;
 
 #ifdef LOAD_ACTUAL_MUTEX_CODE
@@ -503,54 +577,56 @@ typedef u_int32_t tsl_t;
  *
  * 'set' mutexes have the value 1, like on Intel; the returned value from
  * MUTEX_SET() is 1 if the mutex previously had its low bit clear, 0 otherwise.
- *
- * Mutexes on Mac OS X work the same way as the standard PowerPC version, but
- * the assembler syntax is subtly different -- the standard PowerPC version
- * assembles but doesn't work correctly.  This version makes (unnecessary?)
- * use of a stupid linker trick: __db_mutex_tas_dummy is never called, but the
- * ___db_mutex_set label is used as a function name.
  */
-#ifdef HAVE_MUTEX_PPC_APPLE_GCC_ASSEMBLY
-extern int __db_mutex_set __P((volatile tsl_t *));
-void
-__db_mutex_tas_dummy()
-{
-	__asm__	__volatile__("		\n\
-	.globl 	___db_mutex_set		\n\
-___db_mutex_set:			\n\
-	lwarx	r5,0,r3			\n\
-	cmpwi 	r5,0			\n\
-	bne 	fail			\n\
-	addi 	r5,r5,1			\n\
-	stwcx. 	r5,0,r3			\n\
-	beq 	success			\n\
-fail:					\n\
-	li 	r3,0			\n\
-	blr 				\n\
-success:				\n\
-	li 	r3,1			\n\
-	blr");	
+#define	MUTEX_SET_TEST	1		/* gcc/ppc: 0 is clear, 1 is set. */
+
+static inline int
+MUTEX_SET(int *tsl)  {
+         int __r;
+         int __tmp = (int)tsl;
+    asm volatile (
+"0:                             \n\t"
+"       lwarx   %0,0,%2         \n\t"
+"       cmpwi   %0,0            \n\t"
+"       bne-    1f              \n\t"
+"       stwcx.  %2,0,%2         \n\t"
+"       isync                   \n\t"
+"       beq+    2f              \n\t"
+"       b       0b              \n\t"
+"1:                             \n\t"
+"       li      %1, 0           \n\t"
+"2:                             \n\t"
+         : "=&r" (__r), "=r" (tsl)
+         : "r" (__tmp)
+         : "cr0", "memory");
+         return (int)tsl;
 }
-#define	MUTEX_SET(tsl)  __db_mutex_set(tsl)
-#endif
-#ifdef HAVE_MUTEX_PPC_GENERIC_GCC_ASSEMBLY
-#define	MUTEX_SET(tsl)	({		\
-	int __one = 1;			\
-	int __r;			\
-	tsl_t *__l = (tsl);		\
-	asm volatile ("			\
-0:					\
-	lwarx %0,0,%1;			\
-	cmpwi %0,0;			\
-	bne 1f;				\
-	stwcx. %2,0,%1;			\
-	bne- 0b;			\
-1:"					\
-	: "=&r" (__r)			\
-	: "r" (__l), "r" (__one));	\
-	!(__r & 1);			\
-})
+
+static inline int
+MUTEX_UNSET(tsl_t *tsl) {
+         asm volatile("sync" : : : "memory");
+         return *tsl = 0;
+}
+#define	MUTEX_INIT(tsl)		MUTEX_UNSET(tsl)
+#endif
+#endif
+
+/*********************************************************************
+ * OS/390 C
+ *********************************************************************/
+#ifdef HAVE_MUTEX_S390_CC_ASSEMBLY
+typedef int tsl_t;
+
+#ifndef	MUTEX_ALIGN
+#define	MUTEX_ALIGN	sizeof(int)
 #endif
+
+#ifdef LOAD_ACTUAL_MUTEX_CODE
+/*
+ * cs() is declared in <stdlib.h> but is built in to the compiler.
+ * Must use LANGLVL(EXTENDED) to get its declaration.
+ */
+#define	MUTEX_SET(tsl)		(!cs(&zero, (tsl), 1))
 #define	MUTEX_UNSET(tsl)	(*(tsl) = 0)
 #define	MUTEX_INIT(tsl)		MUTEX_UNSET(tsl)
 #endif
@@ -563,9 +639,8 @@ success:				\n\
 typedef int tsl_t;
 
 #ifdef LOAD_ACTUAL_MUTEX_CODE
-/*
- * For gcc/S390, 0 is clear, 1 is set.
- */
+#define	MUTEX_SET_TEST	1		/* gcc/S390: 0 is clear, 1 is set. */
+
 static inline int
 MUTEX_SET(tsl_t *tsl) {							\
 	register tsl_t *__l = (tsl);					\
@@ -595,9 +670,8 @@ typedef unsigned char tsl_t;
 #ifdef LOAD_ACTUAL_MUTEX_CODE
 /*
  * UnixWare has threads in libthread, but OpenServer doesn't (yet).
- *
- * For cc/x86, 0 is clear, 1 is set.
  */
+#define	MUTEX_SET_TEST	1		/* cc/x86: 0 is clear, 1 is set. */
 
 #if defined(__USLC__)
 asm int
@@ -637,9 +711,9 @@ typedef unsigned char tsl_t;
  * so is functional there as well.  For v7, stbar may generate an illegal
  * instruction and we have no way to tell what we're running on.  Some
  * operating systems notice and skip this instruction in the fault handler.
- *
- * For gcc/sparc, 0 is clear, 1 is set.
  */
+#define	MUTEX_SET_TEST	1		/* gcc/sparc: 0 is clear, 1 is set. */
+
 #define	MUTEX_SET(tsl) ({						\
 	register tsl_t *__l = (tsl);					\
 	register tsl_t __r;						\
@@ -660,7 +734,10 @@ typedef unsigned char tsl_t;
 #ifdef HAVE_MUTEX_UTS_CC_ASSEMBLY
 typedef int tsl_t;
 
+#ifndef	MUTEX_ALIGN
 #define	MUTEX_ALIGN	sizeof(int)
+#endif
+
 #ifdef LOAD_ACTUAL_MUTEX_CODE
 #define	MUTEX_INIT(x)	0
 #define	MUTEX_SET(x)	(!uts_lock(x, 1))
@@ -675,9 +752,8 @@ typedef int tsl_t;
 typedef unsigned char tsl_t;
 
 #ifdef LOAD_ACTUAL_MUTEX_CODE
-/*
- * For gcc/x86, 0 is clear, 1 is set.
- */
+#define	MUTEX_SET_TEST	1		/* gcc/x86: 0 is clear, 1 is set. */
+
 #define	MUTEX_SET(tsl) ({						\
 	register tsl_t *__l = (tsl);					\
 	int __r;							\
@@ -690,6 +766,17 @@ typedef unsigned char tsl_t;
 
 #define	MUTEX_UNSET(tsl)	(*(tsl) = 0)
 #define	MUTEX_INIT(tsl)		MUTEX_UNSET(tsl)
+
+/*
+ * From Intel's performance tuning documentation (and see SR #6975):
+ * ftp://download.intel.com/design/perftool/cbts/appnotes/sse2/w_spinlock.pdf
+ *
+ * "For this reason, it is highly recommended that you insert the PAUSE
+ * instruction into all spin-wait code immediately. Using the PAUSE
+ * instruction does not affect the correctness of programs on existing
+ * platforms, and it improves performance on Pentium 4 processor platforms."
+ */
+#define	MUTEX_PAUSE		asm volatile ("rep; nop" : : );
 #endif
 #endif
 
@@ -717,33 +804,38 @@ typedef unsigned char tsl_t;
 
 /*
  * !!!
- * These defines are separated into the u_int8_t flags stored in the
- * mutex below, and the 32 bit flags passed to __db_mutex_setup.
- * But they must co-exist and not overlap.  Flags to __db_mutex_setup are:
+ * The flag arguments for __db_mutex_setup (and the underlying initialization
+ * function for the mutex type, for example, __db_tas_mutex_init), and flags
+ * stored in the DB_MUTEX structure are combined, and may not overlap.  Flags
+ * to __db_mutex_setup:
  *
- * MUTEX_ALLOC - Use when the mutex to initialize needs to be allocated.
- *    The 'ptr' arg to __db_mutex_setup should be a DB_MUTEX ** whenever
- *    you use this flag.  If this flag is not set, the 'ptr' arg is
- *    a DB_MUTEX *.
- * MUTEX_NO_RECORD - Explicitly do not record the mutex in the region.
- *    Otherwise the mutex will be recorded by default.  If you set
- *    this you need to understand why you don't need it recorded.  The
- *    *only* ones not recorded are those that are part of region structures
- *    that only get destroyed when the regions are destroyed.
- * MUTEX_NO_RLOCK - Explicitly do not lock the given region otherwise
- *    the region will be locked by default.
- * MUTEX_SELF_BLOCK - Set if self blocking mutex.
- * MUTEX_THREAD - Set if mutex is a thread-only mutex.
+ * MUTEX_ALLOC:
+ *	Use when the mutex to initialize needs to be allocated. The 'ptr'
+ *	arg to __db_mutex_setup should be a DB_MUTEX ** whenever you use
+ *	this flag.  If this flag is not set, the 'ptr' arg is a DB_MUTEX *.
+ * MUTEX_NO_RECORD:
+ *	Explicitly do not record the mutex in the region.  Otherwise the
+ *	mutex will be recorded by default.  If you set this you need to
+ *	understand why you don't need it recorded.  The *only* ones not
+ *	recorded are those that are part of region structures that only
+ *	get destroyed when the regions are destroyed.
+ * MUTEX_NO_RLOCK:
+ *	Explicitly do not lock the given region otherwise the region will
+ *	be locked by default.
+ * MUTEX_SELF_BLOCK:
+ *	Set if self blocking mutex.
+ * MUTEX_THREAD:
+ *	Set if mutex is a thread-only mutex.
  */
-#define	MUTEX_IGNORE		0x001	/* Ignore, no lock required. */
-#define	MUTEX_INITED		0x002	/* Mutex is successfully initialized */
-#define	MUTEX_MPOOL		0x004	/* Allocated from mpool. */
-#define	MUTEX_SELF_BLOCK	0x008	/* Must block self. */
-/* Flags only, may be larger than 0xff. */
-#define	MUTEX_ALLOC		0x00000100 /* Allocate and init a mutex */
-#define	MUTEX_NO_RECORD		0x00000200 /* Do not record lock */
-#define	MUTEX_NO_RLOCK		0x00000400 /* Do not acquire region lock */
-#define	MUTEX_THREAD		0x00000800 /* Thread-only mutex. */
+#define	MUTEX_ALLOC		0x0001	/* Allocate and init a mutex */
+#define	MUTEX_IGNORE		0x0002	/* Ignore, no lock required. */
+#define	MUTEX_INITED		0x0004	/* Mutex is successfully initialized */
+#define	MUTEX_LOGICAL_LOCK	0x0008	/* Mutex backs database lock. */
+#define	MUTEX_MPOOL		0x0010	/* Allocated from mpool. */
+#define	MUTEX_NO_RECORD		0x0020	/* Do not record lock */
+#define	MUTEX_NO_RLOCK		0x0040	/* Do not acquire region lock */
+#define	MUTEX_SELF_BLOCK	0x0080	/* Must block self. */
+#define	MUTEX_THREAD		0x0100	/* Thread-only mutex. */
 
 /* Mutex. */
 struct __mutex_t {
@@ -753,7 +845,6 @@ struct __mutex_t {
 #else
 	tsl_t	tas;			/* Test and set. */
 #endif
-	u_int32_t spins;		/* Spins before block. */
 	u_int32_t locked;		/* !0 if locked. */
 #else
 	u_int32_t off;			/* Byte offset to lock. */
@@ -766,10 +857,19 @@ struct __mutex_t {
 #ifdef HAVE_MUTEX_SYSTEM_RESOURCES
 	roff_t	  reg_off;		/* Shared lock info offset. */
 #endif
-
-	u_int8_t  flags;		/* MUTEX_XXX */
+	/*
+	 * Flags should be an unsigned integer even if it's not required by
+	 * the possible flags values, getting a single byte on some machines
+	 * is expensive, and the mutex structure is a MP hot spot.
+	 */
+	u_int32_t flags;		/* MUTEX_XXX */
 };
 
+/* Macro to clear mutex statistics. */
+#define	MUTEX_CLEAR(mp) {						\
+	(mp)->mutex_set_wait = (mp)->mutex_set_nowait = 0;		\
+}
+
 /* Redirect calls to the correct functions. */
 #ifdef HAVE_MUTEX_THREADS
 #if defined(HAVE_MUTEX_PTHREADS) ||					\
@@ -779,7 +879,8 @@ struct __mutex_t {
 #define	__db_mutex_lock(a, b)		__db_pthread_mutex_lock(a, b)
 #define	__db_mutex_unlock(a, b)		__db_pthread_mutex_unlock(a, b)
 #define	__db_mutex_destroy(a)		__db_pthread_mutex_destroy(a)
-#elif defined(HAVE_MUTEX_WIN32)
+#else
+#if defined(HAVE_MUTEX_WIN32) || defined(HAVE_MUTEX_WIN32_GCC)
 #define	__db_mutex_init_int(a, b, c, d)	__db_win32_mutex_init(a, b, d)
 #define	__db_mutex_lock(a, b)		__db_win32_mutex_lock(a, b)
 #define	__db_mutex_unlock(a, b)		__db_win32_mutex_unlock(a, b)
@@ -790,6 +891,7 @@ struct __mutex_t {
 #define	__db_mutex_unlock(a, b)		__db_tas_mutex_unlock(a, b)
 #define	__db_mutex_destroy(a)		__db_tas_mutex_destroy(a)
 #endif
+#endif
 #else
 #define	__db_mutex_init_int(a, b, c, d)	__db_fcntl_mutex_init(a, b, c)
 #define	__db_mutex_lock(a, b)		__db_fcntl_mutex_lock(a, b)
diff --git a/storage/bdb/dbinc/os.h b/storage/bdb/dbinc/os.h
index 01ca0ac470d25dd765600fc6d3e539c720489377..24685a4a76586a300173318dc427ad56752be4a0 100644
--- a/storage/bdb/dbinc/os.h
+++ b/storage/bdb/dbinc/os.h
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: os.h,v 11.14 2002/03/27 04:34:55 bostic Exp $
+ * $Id: os.h,v 11.25 2004/09/22 03:40:20 bostic Exp $
  */
 
 #ifndef _DB_OS_H_
@@ -14,38 +14,79 @@
 extern "C" {
 #endif
 
+/* Number of times to retry system calls that return EINTR or EBUSY. */
+#define	DB_RETRY	100
+
+#define	RETRY_CHK(op, ret) do {						\
+	int __retries = DB_RETRY;					\
+	do {								\
+		(ret) = (op);						\
+	} while ((ret) != 0 && (((ret) = __os_get_errno()) == EAGAIN ||	\
+	    (ret) == EBUSY || (ret) == EINTR) && --__retries > 0);	\
+} while (0)
+
+/*
+ * Flags understood by __os_open.
+ */
+#define	DB_OSO_CREATE	0x0001		/* POSIX: O_CREAT */
+#define	DB_OSO_DIRECT	0x0002		/* Don't buffer the file in the OS. */
+#define	DB_OSO_DSYNC	0x0004		/* POSIX: O_DSYNC. */
+#define	DB_OSO_EXCL	0x0008		/* POSIX: O_EXCL */
+#define	DB_OSO_LOG	0x0010		/* Opening a log file. */
+#define	DB_OSO_RDONLY	0x0020		/* POSIX: O_RDONLY */
+#define	DB_OSO_REGION	0x0040		/* Opening a region file. */
+#define	DB_OSO_SEQ	0x0080		/* Expected sequential access. */
+#define	DB_OSO_TEMP	0x0100		/* Remove after last close. */
+#define	DB_OSO_TRUNC	0x0200		/* POSIX: O_TRUNC */
+
+/*
+ * Seek options understood by __os_seek.
+ */
+typedef enum {
+	DB_OS_SEEK_CUR,			/* POSIX: SEEK_CUR */
+	DB_OS_SEEK_END,			/* POSIX: SEEK_END */
+	DB_OS_SEEK_SET			/* POSIX: SEEK_SET */
+} DB_OS_SEEK;
+
+/*
+ * We group certain seek/write calls into a single function so that we
+ * can use pread(2)/pwrite(2) where they're available.
+ */
+#define	DB_IO_READ	1
+#define	DB_IO_WRITE	2
+
 /* DB filehandle. */
 struct __fh_t {
+	/*
+	 * The file-handle mutex is only used to protect the handle/fd
+	 * across seek and read/write pairs, it does not protect the
+	 * the reference count, or any other fields in the structure.
+	 */
+	DB_MUTEX  *mutexp;		/* Mutex to lock. */
+
+	int	  ref;			/* Reference count. */
+
 #if defined(DB_WIN32)
 	HANDLE	  handle;		/* Windows/32 file handle. */
 #endif
 	int	  fd;			/* POSIX file descriptor. */
-	char	*name;			/* File name. */
 
-	u_int32_t log_size;		/* XXX: Log file size. */
-	u_int32_t pagesize;		/* XXX: Page size. */
+	char	*name;			/* File name (ref DB_FH_UNLINK) */
+
+	/*
+	 * Last seek statistics, used for zero-filling on filesystems
+	 * that don't support it directly.
+	 */
+	db_pgno_t pgno;
+	u_int32_t pgsize;
+	u_int32_t offset;
 
 #define	DB_FH_NOSYNC	0x01		/* Handle doesn't need to be sync'd. */
-#define	DB_FH_UNLINK	0x02		/* Unlink on close */
-#define	DB_FH_VALID	0x04		/* Handle is valid. */
+#define	DB_FH_OPENED	0x02		/* Handle is valid. */
+#define	DB_FH_UNLINK	0x04		/* Unlink on close */
 	u_int8_t flags;
 };
 
-/*
- * We group certain seek/write calls into a single function so that we
- * can use pread(2)/pwrite(2) where they're available.
- */
-#define	DB_IO_READ	1
-#define	DB_IO_WRITE	2
-typedef struct __io_t {
-	DB_FH	  *fhp;			/* I/O file handle. */
-	DB_MUTEX  *mutexp;		/* Mutex to lock. */
-	size_t	   pagesize;		/* Page size. */
-	db_pgno_t  pgno;		/* Page number. */
-	u_int8_t  *buf;			/* Buffer. */
-	size_t	   bytes;		/* Bytes read/written. */
-} DB_IO;
-
 #if defined(__cplusplus)
 }
 #endif
diff --git a/storage/bdb/dbinc/qam.h b/storage/bdb/dbinc/qam.h
index 0306ed07d2ab62e95a13968ba6958db60b80cb04..43910d01d7691d0ac2846d8d5065fef4f54f05d2 100644
--- a/storage/bdb/dbinc/qam.h
+++ b/storage/bdb/dbinc/qam.h
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: qam.h,v 11.38 2002/08/06 06:11:21 bostic Exp $
+ * $Id: qam.h,v 11.49 2004/09/17 22:00:27 mjc Exp $
  */
 
 #ifndef	_DB_QAM_H_
@@ -70,6 +70,7 @@ struct __queue {
 
 /* Format for queue extent names. */
 #define	QUEUE_EXTENT "%s%c__dbq.%s.%d"
+#define	QUEUE_EXTENT_HEAD "__dbq.%s."
 
 typedef struct __qam_filelist {
 	DB_MPOOLFILE *mpf;
@@ -77,7 +78,7 @@ typedef struct __qam_filelist {
 } QUEUE_FILELIST;
 
 /*
- * Caculate the page number of a recno
+ * Calculate the page number of a recno.
  *
  * Number of records per page =
  *	Divide the available space on the page by the record len + header.
@@ -93,8 +94,8 @@ typedef struct __qam_filelist {
  */
 #define	CALC_QAM_RECNO_PER_PAGE(dbp)					\
     (((dbp)->pgsize - QPAGE_SZ(dbp)) /					\
-    ALIGN(((QUEUE *)(dbp)->q_internal)->re_len +			\
-    sizeof(QAMDATA) - SSZA(QAMDATA, data), sizeof(u_int32_t)))
+    (u_int32_t)DB_ALIGN((uintmax_t)SSZA(QAMDATA, data) +		\
+    ((QUEUE *)(dbp)->q_internal)->re_len, sizeof(u_int32_t)))
 
 #define	QAM_RECNO_PER_PAGE(dbp)	(((QUEUE*)(dbp)->q_internal)->rec_page)
 
@@ -102,22 +103,32 @@ typedef struct __qam_filelist {
     (((QUEUE *)(dbp)->q_internal)->q_root				\
     + (((recno) - 1) / QAM_RECNO_PER_PAGE(dbp)))
 
+#define	QAM_PAGE_EXTENT(dbp, pgno)					\
+    (((pgno) - 1) / ((QUEUE *)(dbp)->q_internal)->page_ext)
+
+#define	QAM_RECNO_EXTENT(dbp, recno)					\
+    QAM_PAGE_EXTENT(dbp, QAM_RECNO_PAGE(dbp, recno))
+
 #define	QAM_RECNO_INDEX(dbp, pgno, recno)				\
     (((recno) - 1) - (QAM_RECNO_PER_PAGE(dbp)				\
     * (pgno - ((QUEUE *)(dbp)->q_internal)->q_root)))
 
 #define	QAM_GET_RECORD(dbp, page, index)				\
-    ((QAMDATA *)((u_int8_t *)(page) +					\
-    QPAGE_SZ(dbp) + (ALIGN(sizeof(QAMDATA) - SSZA(QAMDATA, data) +	\
-    ((QUEUE *)(dbp)->q_internal)->re_len, sizeof(u_int32_t)) * index)))
+    ((QAMDATA *)((u_int8_t *)(page) + (QPAGE_SZ(dbp) +			\
+    (DB_ALIGN((uintmax_t)SSZA(QAMDATA, data) +				\
+    ((QUEUE *)(dbp)->q_internal)->re_len, sizeof(u_int32_t)) * index))))
 
 #define	QAM_AFTER_CURRENT(meta, recno)					\
     ((recno) > (meta)->cur_recno &&					\
-    ((meta)->first_recno <= (meta)->cur_recno || (recno) < (meta)->first_recno))
+    ((meta)->first_recno <= (meta)->cur_recno ||			\
+    ((recno) < (meta)->first_recno &&					\
+    (recno) - (meta)->cur_recno < (meta)->first_recno - (recno))))
 
 #define	QAM_BEFORE_FIRST(meta, recno)					\
     ((recno) < (meta)->first_recno &&					\
-    ((meta->first_recno <= (meta)->cur_recno || (recno) > (meta)->cur_recno)))
+    ((meta->first_recno <= (meta)->cur_recno ||				\
+    ((recno) > (meta)->cur_recno &&					\
+    (recno) - (meta)->cur_recno > (meta)->first_recno - (recno)))))
 
 #define	QAM_NOT_VALID(meta, recno)					\
     (recno == RECNO_OOB ||						\
@@ -145,6 +156,15 @@ typedef enum {
 	QAM_PROBE_MPF
 } qam_probe_mode;
 
+/*
+ * Ops for __qam_nameop.
+ */
+typedef enum {
+	QAM_NAME_DISCARD,
+	QAM_NAME_RENAME,
+	QAM_NAME_REMOVE
+} qam_name_op;
+
 #define	__qam_fget(dbp, pgnoaddr, flags, addrp) \
 	__qam_fprobe(dbp, *pgnoaddr, addrp, QAM_PROBE_GET, flags)
 
diff --git a/storage/bdb/dbinc/queue.h b/storage/bdb/dbinc/queue.h
index 8d4a771add624c63e50fe8e26a04b5573caf748c..bf09b12d7abd0db465f0f3585fdae574819e07db 100644
--- a/storage/bdb/dbinc/queue.h
+++ b/storage/bdb/dbinc/queue.h
@@ -1,3 +1,4 @@
+
 /*
  * Copyright (c) 1991, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -10,7 +11,11 @@
  * 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. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -27,52 +32,40 @@
  * SUCH DAMAGE.
  *
  *	@(#)queue.h	8.5 (Berkeley) 8/20/94
+ * $FreeBSD: src/sys/sys/queue.h,v 1.54 2002/08/05 05:18:43 alfred Exp $
  */
 
-/*
- * XXX
- * We #undef the queue macros because there are incompatible versions of this
- * file and these macros on various systems.  What makes the problem worse is
- * they are included and/or defined by system include files which we may have
- * already loaded into Berkeley DB before getting here.  For example, FreeBSD's
- * <rpc/rpc.h> includes its system <sys/queue.h>, and VxWorks UnixLib.h defines
- * several of the LIST_XXX macros.  Make sure we use ours.
- */
-#undef	LIST_HEAD
-#undef	LIST_ENTRY
-#undef	LIST_FIRST
-#undef	LIST_NEXT
-#undef	LIST_INIT
-#undef	LIST_INSERT_AFTER
-#undef	LIST_INSERT_BEFORE
-#undef	LIST_INSERT_HEAD
-#undef	LIST_REMOVE
-#undef	TAILQ_HEAD
-#undef	TAILQ_ENTRY
-#undef	TAILQ_FIRST
-#undef	TAILQ_NEXT
-#undef	TAILQ_INIT
-#undef	TAILQ_INSERT_HEAD
-#undef	TAILQ_INSERT_TAIL
-#undef	TAILQ_INSERT_AFTER
-#undef	TAILQ_INSERT_BEFORE
-#undef	TAILQ_REMOVE
-#undef	CIRCLEQ_HEAD
-#undef	CIRCLEQ_ENTRY
-#undef	CIRCLEQ_FIRST
-#undef	CIRCLEQ_LAST
-#undef	CIRCLEQ_NEXT
-#undef	CIRCLEQ_PREV
-#undef	CIRCLEQ_INIT
-#undef	CIRCLEQ_INSERT_AFTER
-#undef	CIRCLEQ_INSERT_BEFORE
-#undef	CIRCLEQ_INSERT_HEAD
-#undef	CIRCLEQ_INSERT_TAIL
-#undef	CIRCLEQ_REMOVE
+#ifndef	_DB_QUEUE_H_
+#define	_DB_QUEUE_H_
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
 
 /*
- * This file defines three types of data structures: lists, tail queues,
- * and circular queues.
+ * This file defines four types of data structures: singly-linked lists,
+ * singly-linked tail queues, lists and tail queues.
+ *
+ * A singly-linked list is headed by a single forward pointer. The elements
+ * are singly linked for minimum space and pointer manipulation overhead at
+ * the expense of O(n) removal for arbitrary elements. New elements can be
+ * added to the list after an existing element or at the head of the list.
+ * Elements being removed from the head of the list should use the explicit
+ * macro for this purpose for optimum efficiency. A singly-linked list may
+ * only be traversed in the forward direction.  Singly-linked lists are ideal
+ * for applications with large datasets and few or no removals or for
+ * implementing a LIFO queue.
+ *
+ * A singly-linked tail queue is headed by a pair of pointers, one to the
+ * head of the list and the other to the tail of the list. The elements are
+ * singly linked for minimum space and pointer manipulation overhead at the
+ * expense of O(n) removal for arbitrary elements. New elements can be added
+ * to the list after an existing element, at the head of the list, or at the
+ * end of the list. Elements being removed from the head of the tail queue
+ * should use the explicit macro for this purpose for optimum efficiency.
+ * A singly-linked tail queue may only be traversed in the forward direction.
+ * Singly-linked tail queues are ideal for applications with large datasets
+ * and few or no removals or for implementing a FIFO queue.
  *
  * A list is headed by a single forward pointer (or an array of forward
  * pointers for a hash table header). The elements are doubly linked
@@ -86,234 +79,486 @@
  * linked so that an arbitrary element can be removed without a need to
  * traverse the list. New elements can be added to the list before or
  * after an existing element, at the head of the list, or at the end of
- * the list. A tail queue may only be traversed in the forward direction.
- *
- * A circle queue is headed by a pair of pointers, one to the head of the
- * list and the other to the tail of the list. The elements are doubly
- * linked so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before or after
- * an existing element, at the head of the list, or at the end of the list.
- * A circle queue may be traversed in either direction, but has a more
- * complex end of list detection.
+ * the list. A tail queue may be traversed in either direction.
  *
  * For details on the use of these macros, see the queue(3) manual page.
+ *
+ *
+ *			SLIST	LIST	STAILQ	TAILQ
+ * _HEAD		+	+	+	+
+ * _HEAD_INITIALIZER	+	+	+	+
+ * _ENTRY		+	+	+	+
+ * _INIT		+	+	+	+
+ * _EMPTY		+	+	+	+
+ * _FIRST		+	+	+	+
+ * _NEXT		+	+	+	+
+ * _PREV		-	-	-	+
+ * _LAST		-	-	+	+
+ * _FOREACH		+	+	+	+
+ * _FOREACH_REVERSE	-	-	-	+
+ * _INSERT_HEAD		+	+	+	+
+ * _INSERT_BEFORE	-	+	-	+
+ * _INSERT_AFTER	+	+	+	+
+ * _INSERT_TAIL		-	-	+	+
+ * _CONCAT		-	-	+	+
+ * _REMOVE_HEAD		+	-	+	-
+ * _REMOVE		+	+	+	+
+ *
  */
 
-#if defined(__cplusplus)
-extern "C" {
-#endif
+/*
+ * XXX
+ * We #undef all of the macros because there are incompatible versions of this
+ * file and these macros on various systems.  What makes the problem worse is
+ * they are included and/or defined by system include files which we may have
+ * already loaded into Berkeley DB before getting here.  For example, FreeBSD's
+ * <rpc/rpc.h> includes its system <sys/queue.h>, and VxWorks UnixLib.h defines
+ * several of the LIST_XXX macros.  Visual C.NET 7.0 also defines some of these
+ * same macros in Vc7\PlatformSDK\Include\WinNT.h.  Make sure we use ours.
+ */
+#undef LIST_EMPTY
+#undef LIST_ENTRY
+#undef LIST_FIRST
+#undef LIST_FOREACH
+#undef LIST_HEAD
+#undef LIST_HEAD_INITIALIZER
+#undef LIST_INIT
+#undef LIST_INSERT_AFTER
+#undef LIST_INSERT_BEFORE
+#undef LIST_INSERT_HEAD
+#undef LIST_NEXT
+#undef LIST_REMOVE
+#undef QMD_TRACE_ELEM
+#undef QMD_TRACE_HEAD
+#undef QUEUE_MACRO_DEBUG
+#undef SLIST_EMPTY
+#undef SLIST_ENTRY
+#undef SLIST_FIRST
+#undef SLIST_FOREACH
+#undef SLIST_FOREACH_PREVPTR
+#undef SLIST_HEAD
+#undef SLIST_HEAD_INITIALIZER
+#undef SLIST_INIT
+#undef SLIST_INSERT_AFTER
+#undef SLIST_INSERT_HEAD
+#undef SLIST_NEXT
+#undef SLIST_REMOVE
+#undef SLIST_REMOVE_HEAD
+#undef STAILQ_CONCAT
+#undef STAILQ_EMPTY
+#undef STAILQ_ENTRY
+#undef STAILQ_FIRST
+#undef STAILQ_FOREACH
+#undef STAILQ_HEAD
+#undef STAILQ_HEAD_INITIALIZER
+#undef STAILQ_INIT
+#undef STAILQ_INSERT_AFTER
+#undef STAILQ_INSERT_HEAD
+#undef STAILQ_INSERT_TAIL
+#undef STAILQ_LAST
+#undef STAILQ_NEXT
+#undef STAILQ_REMOVE
+#undef STAILQ_REMOVE_HEAD
+#undef STAILQ_REMOVE_HEAD_UNTIL
+#undef TAILQ_CONCAT
+#undef TAILQ_EMPTY
+#undef TAILQ_ENTRY
+#undef TAILQ_FIRST
+#undef TAILQ_FOREACH
+#undef TAILQ_FOREACH_REVERSE
+#undef TAILQ_HEAD
+#undef TAILQ_HEAD_INITIALIZER
+#undef TAILQ_INIT
+#undef TAILQ_INSERT_AFTER
+#undef TAILQ_INSERT_BEFORE
+#undef TAILQ_INSERT_HEAD
+#undef TAILQ_INSERT_TAIL
+#undef TAILQ_LAST
+#undef TAILQ_NEXT
+#undef TAILQ_PREV
+#undef TAILQ_REMOVE
+#undef TRACEBUF
+#undef TRASHIT
+
+#define	QUEUE_MACRO_DEBUG 0
+#if QUEUE_MACRO_DEBUG
+/* Store the last 2 places the queue element or head was altered */
+struct qm_trace {
+	char * lastfile;
+	int lastline;
+	char * prevfile;
+	int prevline;
+};
+
+#define	TRACEBUF	struct qm_trace trace;
+#define	TRASHIT(x)	do {(x) = (void *)-1;} while (0)
+
+#define	QMD_TRACE_HEAD(head) do {					\
+	(head)->trace.prevline = (head)->trace.lastline;		\
+	(head)->trace.prevfile = (head)->trace.lastfile;		\
+	(head)->trace.lastline = __LINE__;				\
+	(head)->trace.lastfile = __FILE__;				\
+} while (0)
+
+#define	QMD_TRACE_ELEM(elem) do {					\
+	(elem)->trace.prevline = (elem)->trace.lastline;		\
+	(elem)->trace.prevfile = (elem)->trace.lastfile;		\
+	(elem)->trace.lastline = __LINE__;				\
+	(elem)->trace.lastfile = __FILE__;				\
+} while (0)
+
+#else
+#define	QMD_TRACE_ELEM(elem)
+#define	QMD_TRACE_HEAD(head)
+#define	TRACEBUF
+#define	TRASHIT(x)
+#endif	/* QUEUE_MACRO_DEBUG */
+
+/*
+ * Singly-linked List declarations.
+ */
+#define	SLIST_HEAD(name, type)						\
+struct name {								\
+	struct type *slh_first;	/* first element */			\
+}
+
+#define	SLIST_HEAD_INITIALIZER(head)					\
+	{ NULL }
+
+#define	SLIST_ENTRY(type)						\
+struct {								\
+	struct type *sle_next;	/* next element */			\
+}
+
+/*
+ * Singly-linked List functions.
+ */
+#define	SLIST_EMPTY(head)	((head)->slh_first == NULL)
+
+#define	SLIST_FIRST(head)	((head)->slh_first)
+
+#define	SLIST_FOREACH(var, head, field)					\
+	for ((var) = SLIST_FIRST((head));				\
+	    (var);							\
+	    (var) = SLIST_NEXT((var), field))
+
+#define	SLIST_FOREACH_PREVPTR(var, varp, head, field)			\
+	for ((varp) = &SLIST_FIRST((head));				\
+	    ((var) = *(varp)) != NULL;					\
+	    (varp) = &SLIST_NEXT((var), field))
+
+#define	SLIST_INIT(head) do {						\
+	SLIST_FIRST((head)) = NULL;					\
+} while (0)
+
+#define	SLIST_INSERT_AFTER(slistelm, elm, field) do {			\
+	SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field);	\
+	SLIST_NEXT((slistelm), field) = (elm);				\
+} while (0)
+
+#define	SLIST_INSERT_HEAD(head, elm, field) do {			\
+	SLIST_NEXT((elm), field) = SLIST_FIRST((head));			\
+	SLIST_FIRST((head)) = (elm);					\
+} while (0)
+
+#define	SLIST_NEXT(elm, field)	((elm)->field.sle_next)
+
+#define	SLIST_REMOVE(head, elm, type, field) do {			\
+	if (SLIST_FIRST((head)) == (elm)) {				\
+		SLIST_REMOVE_HEAD((head), field);			\
+	}								\
+	else {								\
+		struct type *curelm = SLIST_FIRST((head));		\
+		while (SLIST_NEXT(curelm, field) != (elm))		\
+			curelm = SLIST_NEXT(curelm, field);		\
+		SLIST_NEXT(curelm, field) =				\
+		    SLIST_NEXT(SLIST_NEXT(curelm, field), field);	\
+	}								\
+} while (0)
+
+#define	SLIST_REMOVE_HEAD(head, field) do {				\
+	SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field);	\
+} while (0)
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#define	STAILQ_HEAD(name, type)						\
+struct name {								\
+	struct type *stqh_first;/* first element */			\
+	struct type **stqh_last;/* addr of last next element */		\
+}
+
+#define	STAILQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).stqh_first }
+
+#define	STAILQ_ENTRY(type)						\
+struct {								\
+	struct type *stqe_next;	/* next element */			\
+}
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#define	STAILQ_CONCAT(head1, head2) do {				\
+	if (!STAILQ_EMPTY((head2))) {					\
+		*(head1)->stqh_last = (head2)->stqh_first;		\
+		(head1)->stqh_last = (head2)->stqh_last;		\
+		STAILQ_INIT((head2));					\
+	}								\
+} while (0)
+
+#define	STAILQ_EMPTY(head)	((head)->stqh_first == NULL)
+
+#define	STAILQ_FIRST(head)	((head)->stqh_first)
+
+#define	STAILQ_FOREACH(var, head, field)				\
+	for ((var) = STAILQ_FIRST((head));				\
+	   (var);							\
+	   (var) = STAILQ_NEXT((var), field))
+
+#define	STAILQ_INIT(head) do {						\
+	STAILQ_FIRST((head)) = NULL;					\
+	(head)->stqh_last = &STAILQ_FIRST((head));			\
+} while (0)
+
+#define	STAILQ_INSERT_AFTER(head, tqelm, elm, field) do {		\
+	if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
+		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
+	STAILQ_NEXT((tqelm), field) = (elm);				\
+} while (0)
+
+#define	STAILQ_INSERT_HEAD(head, elm, field) do {			\
+	if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL)	\
+		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
+	STAILQ_FIRST((head)) = (elm);					\
+} while (0)
+
+#define	STAILQ_INSERT_TAIL(head, elm, field) do {			\
+	STAILQ_NEXT((elm), field) = NULL;				\
+	*(head)->stqh_last = (elm);					\
+	(head)->stqh_last = &STAILQ_NEXT((elm), field);			\
+} while (0)
+
+#define	STAILQ_LAST(head, type, field)					\
+	(STAILQ_EMPTY((head)) ?						\
+		NULL :							\
+		((struct type *)					\
+		((char *)((head)->stqh_last) - __offsetof(struct type, field))))
+
+#define	STAILQ_NEXT(elm, field)	((elm)->field.stqe_next)
+
+#define	STAILQ_REMOVE(head, elm, type, field) do {			\
+	if (STAILQ_FIRST((head)) == (elm)) {				\
+		STAILQ_REMOVE_HEAD((head), field);			\
+	}								\
+	else {								\
+		struct type *curelm = STAILQ_FIRST((head));		\
+		while (STAILQ_NEXT(curelm, field) != (elm))		\
+			curelm = STAILQ_NEXT(curelm, field);		\
+		if ((STAILQ_NEXT(curelm, field) =			\
+		     STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
+			(head)->stqh_last = &STAILQ_NEXT((curelm), field);\
+	}								\
+} while (0)
+
+#define	STAILQ_REMOVE_HEAD(head, field) do {				\
+	if ((STAILQ_FIRST((head)) =					\
+	     STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL)		\
+		(head)->stqh_last = &STAILQ_FIRST((head));		\
+} while (0)
+
+#define	STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do {			\
+	if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL)	\
+		(head)->stqh_last = &STAILQ_FIRST((head));		\
+} while (0)
 
 /*
- * List definitions.
+ * List declarations.
  */
 #define	LIST_HEAD(name, type)						\
 struct name {								\
 	struct type *lh_first;	/* first element */			\
 }
 
+#define	LIST_HEAD_INITIALIZER(head)					\
+	{ NULL }
+
 #define	LIST_ENTRY(type)						\
 struct {								\
 	struct type *le_next;	/* next element */			\
 	struct type **le_prev;	/* address of previous next element */	\
 }
 
-#define	LIST_FIRST(head)		((head)->lh_first)
-#define	LIST_NEXT(elm, field)		((elm)->field.le_next)
-
 /*
  * List functions.
  */
-#define	LIST_INIT(head) {						\
-	(head)->lh_first = NULL;					\
-}
+
+#define	LIST_EMPTY(head)	((head)->lh_first == NULL)
+
+#define	LIST_FIRST(head)	((head)->lh_first)
+
+#define	LIST_FOREACH(var, head, field)					\
+	for ((var) = LIST_FIRST((head));				\
+	    (var);							\
+	    (var) = LIST_NEXT((var), field))
+
+#define	LIST_INIT(head) do {						\
+	LIST_FIRST((head)) = NULL;					\
+} while (0)
 
 #define	LIST_INSERT_AFTER(listelm, elm, field) do {			\
-	if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)	\
-		(listelm)->field.le_next->field.le_prev =		\
-		    &(elm)->field.le_next;				\
-	(listelm)->field.le_next = (elm);				\
-	(elm)->field.le_prev = &(listelm)->field.le_next;		\
+	if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
+		LIST_NEXT((listelm), field)->field.le_prev =		\
+		    &LIST_NEXT((elm), field);				\
+	LIST_NEXT((listelm), field) = (elm);				\
+	(elm)->field.le_prev = &LIST_NEXT((listelm), field);		\
 } while (0)
 
 #define	LIST_INSERT_BEFORE(listelm, elm, field) do {			\
 	(elm)->field.le_prev = (listelm)->field.le_prev;		\
-	(elm)->field.le_next = (listelm);				\
+	LIST_NEXT((elm), field) = (listelm);				\
 	*(listelm)->field.le_prev = (elm);				\
-	(listelm)->field.le_prev = &(elm)->field.le_next;		\
+	(listelm)->field.le_prev = &LIST_NEXT((elm), field);		\
 } while (0)
 
 #define	LIST_INSERT_HEAD(head, elm, field) do {				\
-	if (((elm)->field.le_next = (head)->lh_first) != NULL)		\
-		(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
-	(head)->lh_first = (elm);					\
-	(elm)->field.le_prev = &(head)->lh_first;			\
+	if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL)	\
+		LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
+	LIST_FIRST((head)) = (elm);					\
+	(elm)->field.le_prev = &LIST_FIRST((head));			\
 } while (0)
 
+#define	LIST_NEXT(elm, field)	((elm)->field.le_next)
+
 #define	LIST_REMOVE(elm, field) do {					\
-	if ((elm)->field.le_next != NULL)				\
-		(elm)->field.le_next->field.le_prev =			\
+	if (LIST_NEXT((elm), field) != NULL)				\
+		LIST_NEXT((elm), field)->field.le_prev =		\
 		    (elm)->field.le_prev;				\
-	*(elm)->field.le_prev = (elm)->field.le_next;			\
+	*(elm)->field.le_prev = LIST_NEXT((elm), field);		\
 } while (0)
 
 /*
- * Tail queue definitions.
+ * Tail queue declarations.
  */
 #define	TAILQ_HEAD(name, type)						\
 struct name {								\
 	struct type *tqh_first;	/* first element */			\
 	struct type **tqh_last;	/* addr of last next element */		\
+	TRACEBUF							\
 }
 
+#define	TAILQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).tqh_first }
+
 #define	TAILQ_ENTRY(type)						\
 struct {								\
 	struct type *tqe_next;	/* next element */			\
 	struct type **tqe_prev;	/* address of previous next element */	\
+	TRACEBUF							\
 }
 
-#define	TAILQ_FIRST(head)		((head)->tqh_first)
-#define	TAILQ_NEXT(elm, field)		((elm)->field.tqe_next)
-
 /*
  * Tail queue functions.
  */
-#define	TAILQ_INIT(head) do {						\
-	(head)->tqh_first = NULL;					\
-	(head)->tqh_last = &(head)->tqh_first;				\
+#define	TAILQ_CONCAT(head1, head2, field) do {				\
+	if (!TAILQ_EMPTY(head2)) {					\
+		*(head1)->tqh_last = (head2)->tqh_first;		\
+		(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last;	\
+		(head1)->tqh_last = (head2)->tqh_last;			\
+		TAILQ_INIT((head2));					\
+		QMD_TRACE_HEAD(head);					\
+		QMD_TRACE_HEAD(head2);					\
+	}								\
 } while (0)
 
-#define	TAILQ_INSERT_HEAD(head, elm, field) do {			\
-	if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)	\
-		(head)->tqh_first->field.tqe_prev =			\
-		    &(elm)->field.tqe_next;				\
-	else								\
-		(head)->tqh_last = &(elm)->field.tqe_next;		\
-	(head)->tqh_first = (elm);					\
-	(elm)->field.tqe_prev = &(head)->tqh_first;			\
-} while (0)
+#define	TAILQ_EMPTY(head)	((head)->tqh_first == NULL)
 
-#define	TAILQ_INSERT_TAIL(head, elm, field) do {			\
-	(elm)->field.tqe_next = NULL;					\
-	(elm)->field.tqe_prev = (head)->tqh_last;			\
-	*(head)->tqh_last = (elm);					\
-	(head)->tqh_last = &(elm)->field.tqe_next;			\
+#define	TAILQ_FIRST(head)	((head)->tqh_first)
+
+#define	TAILQ_FOREACH(var, head, field)					\
+	for ((var) = TAILQ_FIRST((head));				\
+	    (var);							\
+	    (var) = TAILQ_NEXT((var), field))
+
+#define	TAILQ_FOREACH_REVERSE(var, head, headname, field)		\
+	for ((var) = TAILQ_LAST((head), headname);			\
+	    (var);							\
+	    (var) = TAILQ_PREV((var), headname, field))
+
+#define	TAILQ_INIT(head) do {						\
+	TAILQ_FIRST((head)) = NULL;					\
+	(head)->tqh_last = &TAILQ_FIRST((head));			\
+	QMD_TRACE_HEAD(head);						\
 } while (0)
 
 #define	TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
-	if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
-		(elm)->field.tqe_next->field.tqe_prev =		\
-		    &(elm)->field.tqe_next;				\
-	else								\
-		(head)->tqh_last = &(elm)->field.tqe_next;		\
-	(listelm)->field.tqe_next = (elm);				\
-	(elm)->field.tqe_prev = &(listelm)->field.tqe_next;		\
+	if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
+		TAILQ_NEXT((elm), field)->field.tqe_prev =		\
+		    &TAILQ_NEXT((elm), field);				\
+	else {								\
+		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
+		QMD_TRACE_HEAD(head);					\
+	}								\
+	TAILQ_NEXT((listelm), field) = (elm);				\
+	(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field);		\
+	QMD_TRACE_ELEM(&(elm)->field);					\
+	QMD_TRACE_ELEM(&listelm->field);				\
 } while (0)
 
 #define	TAILQ_INSERT_BEFORE(listelm, elm, field) do {			\
 	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\
-	(elm)->field.tqe_next = (listelm);				\
+	TAILQ_NEXT((elm), field) = (listelm);				\
 	*(listelm)->field.tqe_prev = (elm);				\
-	(listelm)->field.tqe_prev = &(elm)->field.tqe_next;		\
+	(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field);		\
+	QMD_TRACE_ELEM(&(elm)->field);					\
+	QMD_TRACE_ELEM(&listelm->field);				\
 } while (0)
 
-#define	TAILQ_REMOVE(head, elm, field) do {				\
-	if (((elm)->field.tqe_next) != NULL)				\
-		(elm)->field.tqe_next->field.tqe_prev =		\
-		    (elm)->field.tqe_prev;				\
+#define	TAILQ_INSERT_HEAD(head, elm, field) do {			\
+	if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)	\
+		TAILQ_FIRST((head))->field.tqe_prev =			\
+		    &TAILQ_NEXT((elm), field);				\
 	else								\
-		(head)->tqh_last = (elm)->field.tqe_prev;		\
-	*(elm)->field.tqe_prev = (elm)->field.tqe_next;			\
-} while (0)
-
-/*
- * This macro is used to fixup the queue after moving the head.
- */
-#define	TAILQ_REINSERT_HEAD(head, elm, field) do {			\
-	DB_ASSERT((head)->tqh_first == (elm));				\
-	(elm)->field.tqe_prev = &(head)->tqh_first;                     \
-} while (0)
-
-/*
- * Circular queue definitions.
- */
-#define	CIRCLEQ_HEAD(name, type)					\
-struct name {								\
-	struct type *cqh_first;		/* first element */		\
-	struct type *cqh_last;		/* last element */		\
-}
-
-#define	CIRCLEQ_ENTRY(type)						\
-struct {								\
-	struct type *cqe_next;		/* next element */		\
-	struct type *cqe_prev;		/* previous element */		\
-}
-
-#define	CIRCLEQ_FIRST(head)		((head)->cqh_first)
-#define	CIRCLEQ_LAST(head)		((head)->cqh_last)
-#define	CIRCLEQ_NEXT(elm, field)	((elm)->field.cqe_next)
-#define	CIRCLEQ_PREV(elm, field)	((elm)->field.cqe_prev)
-
-/*
- * Circular queue functions.
- */
-#define	CIRCLEQ_INIT(head) do {						\
-	(head)->cqh_first = (void *)(head);				\
-	(head)->cqh_last = (void *)(head);				\
+		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
+	TAILQ_FIRST((head)) = (elm);					\
+	(elm)->field.tqe_prev = &TAILQ_FIRST((head));			\
+	QMD_TRACE_HEAD(head);						\
+	QMD_TRACE_ELEM(&(elm)->field);					\
 } while (0)
 
-#define	CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {		\
-	(elm)->field.cqe_next = (listelm)->field.cqe_next;		\
-	(elm)->field.cqe_prev = (listelm);				\
-	if ((listelm)->field.cqe_next == (void *)(head))		\
-		(head)->cqh_last = (elm);				\
-	else								\
-		(listelm)->field.cqe_next->field.cqe_prev = (elm);	\
-	(listelm)->field.cqe_next = (elm);				\
+#define	TAILQ_INSERT_TAIL(head, elm, field) do {			\
+	TAILQ_NEXT((elm), field) = NULL;				\
+	(elm)->field.tqe_prev = (head)->tqh_last;			\
+	*(head)->tqh_last = (elm);					\
+	(head)->tqh_last = &TAILQ_NEXT((elm), field);			\
+	QMD_TRACE_HEAD(head);						\
+	QMD_TRACE_ELEM(&(elm)->field);					\
 } while (0)
 
-#define	CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {		\
-	(elm)->field.cqe_next = (listelm);				\
-	(elm)->field.cqe_prev = (listelm)->field.cqe_prev;		\
-	if ((listelm)->field.cqe_prev == (void *)(head))		\
-		(head)->cqh_first = (elm);				\
-	else								\
-		(listelm)->field.cqe_prev->field.cqe_next = (elm);	\
-	(listelm)->field.cqe_prev = (elm);				\
-} while (0)
+#define	TAILQ_LAST(head, headname)					\
+	(*(((struct headname *)((head)->tqh_last))->tqh_last))
 
-#define	CIRCLEQ_INSERT_HEAD(head, elm, field) do {			\
-	(elm)->field.cqe_next = (head)->cqh_first;			\
-	(elm)->field.cqe_prev = (void *)(head);				\
-	if ((head)->cqh_last == (void *)(head))				\
-		(head)->cqh_last = (elm);				\
-	else								\
-		(head)->cqh_first->field.cqe_prev = (elm);		\
-	(head)->cqh_first = (elm);					\
-} while (0)
+#define	TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
 
-#define	CIRCLEQ_INSERT_TAIL(head, elm, field) do {			\
-	(elm)->field.cqe_next = (void *)(head);				\
-	(elm)->field.cqe_prev = (head)->cqh_last;			\
-	if ((head)->cqh_first == (void *)(head))			\
-		(head)->cqh_first = (elm);				\
-	else								\
-		(head)->cqh_last->field.cqe_next = (elm);		\
-	(head)->cqh_last = (elm);					\
-} while (0)
+#define	TAILQ_PREV(elm, headname, field)				\
+	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
 
-#define	CIRCLEQ_REMOVE(head, elm, field) do {				\
-	if ((elm)->field.cqe_next == (void *)(head))			\
-		(head)->cqh_last = (elm)->field.cqe_prev;		\
-	else								\
-		(elm)->field.cqe_next->field.cqe_prev =			\
-		    (elm)->field.cqe_prev;				\
-	if ((elm)->field.cqe_prev == (void *)(head))			\
-		(head)->cqh_first = (elm)->field.cqe_next;		\
-	else								\
-		(elm)->field.cqe_prev->field.cqe_next =			\
-		    (elm)->field.cqe_next;				\
+#define	TAILQ_REMOVE(head, elm, field) do {				\
+	if ((TAILQ_NEXT((elm), field)) != NULL)				\
+		TAILQ_NEXT((elm), field)->field.tqe_prev =		\
+		    (elm)->field.tqe_prev;				\
+	else {								\
+		(head)->tqh_last = (elm)->field.tqe_prev;		\
+		QMD_TRACE_HEAD(head);					\
+	}								\
+	*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);		\
+	TRASHIT((elm)->field.tqe_next);					\
+	TRASHIT((elm)->field.tqe_prev);					\
+	QMD_TRACE_ELEM(&(elm)->field);					\
 } while (0)
 
 #if defined(__cplusplus)
 }
 #endif
+#endif	/* !_DB_QUEUE_H_ */
diff --git a/storage/bdb/dbinc/region.h b/storage/bdb/dbinc/region.h
index 9ee6c81062f7d60be6ad441464ba31f77bfa2382..98f6ea07b1648e0cbc4cfad646ddfd58f15d4ee5 100644
--- a/storage/bdb/dbinc/region.h
+++ b/storage/bdb/dbinc/region.h
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1998-2002
+ * Copyright (c) 1998-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: region.h,v 11.33 2002/08/06 06:11:22 bostic Exp $
+ * $Id: region.h,v 11.51 2004/10/15 16:59:39 bostic Exp $
  */
 
 #ifndef _DB_REGION_H_
@@ -53,7 +53,7 @@
  * or joining the REGENV file, i.e., __db.001.  We have to be absolutely sure
  * that only one process creates it, and that everyone else joins it without
  * seeing inconsistent data.  Once that region is created, we can use normal
- * shared locking procedures to do mutal exclusion for all other regions.
+ * shared locking procedures to do mutual exclusion for all other regions.
  *
  * One of the REGION structures in the main environment region describes the
  * environment region itself.
@@ -99,11 +99,10 @@
 extern "C" {
 #endif
 
-#define	DB_REGION_FMT	"__db.%03d"	/* Region file name format. */
-#define	DB_REGION_NAME_NUM	5	/* First digit offset in file names. */
-#define	DB_REGION_NAME_LENGTH	8	/* Length of file names. */
-
-#define	DB_REGION_ENV	"__db.001"	/* Primary environment name. */
+#define	DB_REGION_PREFIX	"__db"		/* DB file name prefix. */
+#define	DB_REGION_FMT		"__db.%03d"	/* Region file name format. */
+#define	DB_REGION_ENV		"__db.001"	/* Primary environment name. */
+#define	DB_REGION_NAME_LENGTH	8		/* Length of file names. */
 
 #define	INVALID_REGION_ID	0	/* Out-of-band region ID. */
 #define	REGION_ID_ENV		1	/* Primary environment ID. */
@@ -115,7 +114,7 @@ typedef enum {
 	REGION_TYPE_LOG,
 	REGION_TYPE_MPOOL,
 	REGION_TYPE_MUTEX,
-	REGION_TYPE_TXN } reg_type;
+	REGION_TYPE_TXN } reg_type_t;
 
 #define	INVALID_REGION_SEGID	-1	/* Segment IDs are either shmget(2) or
 					 * Win16 segment identifiers.  They are
@@ -149,13 +148,9 @@ typedef struct __db_reg_env {
 	 * Note, the magic and panic fields are NOT protected by any mutex,
 	 * and for this reason cannot be anything more complicated than a
 	 * zero/non-zero value.
-	 *
-	 * !!!
-	 * The valid region magic number must appear at the same byte offset
-	 * in both the environment and each shared region, as Windows/95 uses
-	 * it to determine if the memory has been zeroed since it was last used.
 	 */
 	u_int32_t  magic;		/* Valid region magic number. */
+	u_int32_t  envid;		/* Unique environment ID. */
 
 	int	   envpanic;		/* Environment is dead. */
 
@@ -172,6 +167,11 @@ typedef struct __db_reg_env {
 	u_int32_t  refcnt;		/* References to the environment. */
 
 	roff_t	   rep_off;		/* Offset of the replication area. */
+#define	DB_REGENV_REPLOCKED	0x0001	/* Env locked for rep backup. */
+	u_int32_t  flags;		/* Shared environment flags. */
+#define	DB_REGENV_TIMEOUT	30	/* Backup timeout. */
+	time_t	   op_timestamp;	/* Timestamp for operations. */
+	time_t	   rep_timestamp;	/* Timestamp for rep db handles. */
 
 	size_t	   pad;			/* Guarantee that following memory is
 					 * size_t aligned.  This is necessary
@@ -189,20 +189,13 @@ typedef struct __db_region {
 	 */
 	DB_MUTEX   mutex;		/* Region mutex. */
 
-	/*
-	 * !!!
-	 * The valid region magic number must appear at the same byte offset
-	 * in both the environment and each shared region, as Windows/95 uses
-	 * it to determine if the memory has been zeroed since it was last used.
-	 */
-	u_int32_t  magic;
-
 	SH_LIST_ENTRY q;		/* Linked list of REGIONs. */
 
-	reg_type   type;		/* Region type. */
+	reg_type_t type;		/* Region type. */
 	u_int32_t  id;			/* Region id. */
 
-	roff_t	   size;		/* Region size in bytes. */
+	roff_t	   size_orig;		/* Region size in bytes (original). */
+	roff_t	   size;		/* Region size in bytes (adjusted). */
 
 	roff_t	   primary;		/* Primary data structure offset. */
 
@@ -213,19 +206,25 @@ typedef struct __db_region {
  * Per-process/per-attachment information about a single region.
  */
 struct __db_reginfo_t {		/* __db_r_attach IN parameters. */
-	reg_type    type;		/* Region type. */
+	DB_ENV	   *dbenv;		/* Enclosing environment. */
+	reg_type_t  type;		/* Region type. */
 	u_int32_t   id;			/* Region id. */
-	int	    mode;		/* File creation mode. */
 
 				/* __db_r_attach OUT parameters. */
 	REGION	   *rp;			/* Shared region. */
 
 	char	   *name;		/* Region file name. */
 
-	void	   *addr;		/* Region allocation address. */
+	void	   *addr_orig;		/* Region address (original). */
+	void	   *addr;		/* Region address (adjusted). */
 	void	   *primary;		/* Primary data structure address. */
 
-	void	   *wnt_handle;		/* Win/NT HANDLE. */
+	size_t	    max_alloc;		/* Maximum bytes allocated. */
+	size_t	    allocated;		/* Bytes allocated. */
+
+#ifdef DB_WIN32
+	HANDLE	wnt_handle;		/* Win/NT HANDLE. */
+#endif
 
 #define	REGION_CREATE		0x01	/* Caller created region. */
 #define	REGION_CREATE_OK	0x02	/* Caller willing to create region. */
@@ -256,15 +255,13 @@ typedef struct __db_regmaint_t {
 /*
  * R_ADDR	Return a per-process address for a shared region offset.
  * R_OFFSET	Return a shared region offset for a per-process address.
- *
- * !!!
- * R_OFFSET should really be returning a ptrdiff_t, but that's not yet
- * portable.  We use u_int32_t, which restricts regions to 4Gb in size.
  */
-#define	R_ADDR(base, offset)						\
-	((void *)((u_int8_t *)((base)->addr) + offset))
-#define	R_OFFSET(base, p)						\
-	((u_int32_t)((u_int8_t *)(p) - (u_int8_t *)(base)->addr))
+#define	R_ADDR(reginfop, offset)					\
+	(F_ISSET((reginfop)->dbenv, DB_ENV_PRIVATE) ? (void *)(offset) :\
+	(void *)((u_int8_t *)((reginfop)->addr) + (offset)))
+#define	R_OFFSET(reginfop, p)						\
+	(F_ISSET((reginfop)->dbenv, DB_ENV_PRIVATE) ? (roff_t)(p) :	\
+	(roff_t)((u_int8_t *)(p) - (u_int8_t *)(reginfop)->addr))
 
 /*
  * R_LOCK	Lock/unlock a region.
@@ -283,7 +280,9 @@ typedef struct __db_regmaint_t {
 		return (__db_panic_msg(dbenv));
 
 #define	PANIC_SET(dbenv, onoff)						\
-	((REGENV *)((REGINFO *)(dbenv)->reginfo)->primary)->envpanic = (onoff);
+	if ((dbenv)->reginfo != NULL)					\
+		((REGENV *)((REGINFO *)					\
+		    (dbenv)->reginfo)->primary)->envpanic = (onoff);
 
 /*
  * All regions are created on 8K boundaries out of sheer paranoia, so we
@@ -293,7 +292,7 @@ typedef struct __db_regmaint_t {
 #define	OS_VMPAGESIZE		(8 * 1024)
 #define	OS_VMROUNDOFF(i) {						\
 	if ((i) <							\
-	    (UINT32_T_MAX - OS_VMPAGESIZE) + 1 || (i) < OS_VMPAGESIZE)	\
+	    (UINT32_MAX - OS_VMPAGESIZE) + 1 || (i) < OS_VMPAGESIZE)	\
 		(i) += OS_VMPAGESIZE - 1;				\
 	(i) -= (i) % OS_VMPAGESIZE;					\
 }
diff --git a/storage/bdb/dbinc/rep.h b/storage/bdb/dbinc/rep.h
index 1e315494c87d5a2cad4e1767c44c7e9e13c9b6c9..ec1f290f45abac7961373634e2feee3ae1027cdb 100644
--- a/storage/bdb/dbinc/rep.h
+++ b/storage/bdb/dbinc/rep.h
@@ -1,20 +1,22 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
+ * Copyright (c) 2001-2004
  *	Sleepycat Software.  All rights reserved.
  */
 
 #ifndef _REP_H_
 #define	_REP_H_
 
+#include "dbinc_auto/rep_auto.h"
+
 #define	REP_ALIVE	1	/* I am alive message. */
 #define	REP_ALIVE_REQ	2	/* Request for alive messages. */
 #define	REP_ALL_REQ	3	/* Request all log records greater than LSN. */
-#define	REP_ELECT	4	/* Indicates that all listeners should */
-				/* begin master election */
-#define	REP_FILE	6	/* Page of a database file. */
-#define	REP_FILE_REQ	7	/* Request for a database file. */
+#define	REP_DUPMASTER	4	/* Duplicate master detected; propagate. */
+#define	REP_FILE	5	/* Page of a database file. NOTUSED */
+#define	REP_FILE_FAIL	6	/* File requested does not exist. */
+#define	REP_FILE_REQ	7	/* Request for a database file. NOTUSED */
 #define	REP_LOG		8	/* Log record. */
 #define	REP_LOG_MORE	9	/* There are more log records to request. */
 #define	REP_LOG_REQ	10	/* Request for a log record. */
@@ -29,23 +31,71 @@
 				 * someone who heard about a NEWSITE.
 				 */
 #define	REP_PAGE	16	/* Database page. */
-#define	REP_PAGE_REQ	17	/* Request for a database page. */
-#define	REP_PLIST	18	/* Database page list. */
-#define	REP_PLIST_REQ	19	/* Request for a page list. */
-#define	REP_VERIFY	20	/* A log record for verification. */
-#define	REP_VERIFY_FAIL	21	/* The client is outdated. */
-#define	REP_VERIFY_REQ	22	/* Request for a log record to verify. */
-#define	REP_VOTE1	23	/* Send out your information for an election. */
-#define	REP_VOTE2	24	/* Send a "you are master" vote. */
+#define	REP_PAGE_FAIL	17	/* Requested page does not exist. */
+#define	REP_PAGE_MORE	18	/* There are more pages to request. */
+#define	REP_PAGE_REQ	19	/* Request for a database page. */
+#define	REP_UPDATE	20	/* Environment hotcopy information. */
+#define	REP_UPDATE_REQ	21	/* Request for hotcopy information. */
+#define	REP_VERIFY	22	/* A log record for verification. */
+#define	REP_VERIFY_FAIL	23	/* The client is outdated. */
+#define	REP_VERIFY_REQ	24	/* Request for a log record to verify. */
+#define	REP_VOTE1	25	/* Send out your information for an election. */
+#define	REP_VOTE2	26	/* Send a "you are master" vote. */
 
-/* Used to consistently designate which messages ought to be received where. */
-#define	MASTER_ONLY(dbenv)	\
-	if (!F_ISSET(dbenv, DB_ENV_REP_MASTER)) return (EINVAL)
+/*
+ * REP_PRINT_MESSAGE
+ *	A function to print a debugging message.
+ *
+ * RPRINT
+ *	A macro for debug printing.  Takes as an arg the arg set for __db_msg.
+ *
+ * !!! This function assumes a local DB_MSGBUF variable called 'mb'.
+ */
+#ifdef DIAGNOSTIC
+#define	REP_PRINT_MESSAGE(dbenv, eid, rp, str)				\
+	__rep_print_message(dbenv, eid, rp, str)
+#define RPRINT(e, r, x) do {						\
+	if (FLD_ISSET((e)->verbose, DB_VERB_REPLICATION)) {		\
+		DB_MSGBUF_INIT(&mb);					\
+		if ((e)->db_errpfx == NULL) {				\
+			if (F_ISSET((r), REP_F_CLIENT))			\
+				__db_msgadd((e), &mb, "CLIENT: ");	\
+			else if (F_ISSET((r), REP_F_MASTER))		\
+				__db_msgadd((e), &mb, "MASTER: ");	\
+			else						\
+				__db_msgadd((e), &mb, "REP_UNDEF: ");	\
+		} else							\
+			__db_msgadd((e), &mb, "%s: ",(e)->db_errpfx);	\
+		__db_msgadd x;						\
+		DB_MSGBUF_FLUSH((e), &mb);				\
+	}								\
+} while (0)	
+#else
+#define	REP_PRINT_MESSAGE(dbenv, eid, rp, str)
+#define RPRINT(e, r, x)
+#endif
 
-#define	CLIENT_ONLY(dbenv)	\
-	if (!F_ISSET(dbenv, DB_ENV_REP_CLIENT)) return (EINVAL)
+/*
+ * Election gen file name
+ *	The file contains an egen number for an election this client
+ * has NOT participated in.  I.e. it is the number of a future
+ * election.  We create it when we create the rep region, if it
+ * doesn't already exist and initialize egen to 1.  If it does
+ * exist, we read it when we create the rep region.  We write it
+ * immediately before sending our VOTE1 in an election.  That way,
+ * if a client has ever sent a vote for any election, the file is
+ * already going to be updated to reflect a future election,
+ * should it crash.
+ */
+#define	REP_EGENNAME	"__db.rep.egen"
 
-#define	ANYSITE(dbenv)
+/*
+ * Database types for __rep_client_dbinit
+ */
+typedef enum {
+	REP_DB,		/* Log record database. */
+	REP_PG		/* Pg database. */
+} repdb_t;
 
 /* Shared replication structure. */
 
@@ -58,12 +108,16 @@ typedef struct __rep {
 	 */
 	DB_MUTEX	mutex;		/* Region lock. */
 	roff_t		db_mutex_off;	/* Client database mutex. */
-	u_int32_t	tally_off;	/* Offset of the tally region. */
+	roff_t		tally_off;	/* Offset of the tally region. */
+	roff_t		v2tally_off;	/* Offset of the vote2 tally region. */
 	int		eid;		/* Environment id. */
 	int		master_id;	/* ID of the master site. */
-	u_int32_t	gen;		/* Replication generation number */
+	u_int32_t	egen;		/* Replication election generation. */
+	u_int32_t	gen;		/* Replication generation number. */
+	u_int32_t	recover_gen;	/* Last generation number in log. */
 	int		asites;		/* Space allocated for sites. */
 	int		nsites;		/* Number of sites in group. */
+	int		nvotes;		/* Number of votes needed. */
 	int		priority;	/* My priority in an election. */
 	u_int32_t	gbytes;		/* Limit on data sent in single... */
 	u_int32_t	bytes;		/* __rep_process_message call. */
@@ -73,6 +127,30 @@ typedef struct __rep {
 					 * request a missing log record. */
 	u_int32_t	max_gap;	/* Maximum number of records before
 					 * requesting a missing log record. */
+	/* Status change information */
+	int		elect_th;	/* A thread is in rep_elect. */
+	u_int32_t	msg_th;		/* Number of callers in rep_proc_msg. */
+	int		start_th;	/* A thread is in rep_start. */
+	u_int32_t	handle_cnt;	/* Count of handles in library. */
+	u_int32_t	op_cnt;		/* Multi-step operation count.*/
+	int		in_recovery;	/* Running recovery now. */
+
+	/* Backup information. */
+	int		nfiles;		/* Number of files we have info on. */
+	int		curfile;	/* Current file we're getting. */
+	__rep_fileinfo_args	*curinfo;	/* Current file info ptr. */
+	void		*finfo;		/* Current file info buffer. */
+	void		*nextinfo;	/* Next file info buffer. */
+	void		*originfo;	/* Original file info buffer. */
+	DB_LSN		first_lsn;	/* Earliest LSN we need. */
+	DB_LSN		last_lsn;	/* Latest LSN we need. */
+	db_pgno_t	ready_pg;	/* Next pg expected. */
+	db_pgno_t	waiting_pg;	/* First pg after gap. */
+	db_pgno_t	max_wait_pg;	/* Maximum pg requested. */
+	u_int32_t	npages;		/* Num of pages rcvd for this file. */
+	DB_MPOOLFILE	*file_mpf;	/* Mpoolfile for in-mem database. */
+	DB		*file_dbp;	/* This file's page info. */
+	DB		*queue_dbp;	/* Dbp for a queue file. */
 
 	/* Vote tallying information. */
 	int		sites;		/* Sites heard from. */
@@ -80,38 +158,102 @@ typedef struct __rep {
 	int		w_priority;	/* Winner priority. */
 	u_int32_t	w_gen;		/* Winner generation. */
 	DB_LSN		w_lsn;		/* Winner LSN. */
-	int		w_tiebreaker;	/* Winner tiebreaking value. */
+	u_int32_t	w_tiebreaker;	/* Winner tiebreaking value. */
 	int		votes;		/* Number of votes for this site. */
 
 	/* Statistics. */
 	DB_REP_STAT	stat;
 
-#define	REP_F_EPHASE1	0x01		/* In phase 1 of election. */
-#define	REP_F_EPHASE2	0x02		/* In phase 2 of election. */
-#define	REP_F_LOGSONLY	0x04		/* Log-site only; cannot be upgraded. */
-#define	REP_F_MASTER	0x08		/* Master replica. */
-#define	REP_F_RECOVER	0x10
-#define	REP_F_UPGRADE	0x20		/* Upgradeable replica. */
-#define	REP_ISCLIENT	(REP_F_UPGRADE | REP_F_LOGSONLY)
+#define	REP_F_CLIENT		0x00001		/* Client replica. */
+#define	REP_F_EPHASE1		0x00002		/* In phase 1 of election. */
+#define	REP_F_EPHASE2		0x00004		/* In phase 2 of election. */
+#define	REP_F_MASTER		0x00008		/* Master replica. */
+#define	REP_F_MASTERELECT	0x00010		/* Master elect */
+#define	REP_F_NOARCHIVE		0x00020		/* Rep blocks log_archive */
+#define	REP_F_READY		0x00040		/* Wait for txn_cnt to be 0. */
+#define	REP_F_RECOVER_LOG	0x00080		/* In recovery - log. */
+#define	REP_F_RECOVER_PAGE	0x00100		/* In recovery - pages. */
+#define	REP_F_RECOVER_UPDATE	0x00200		/* In recovery - files. */
+#define	REP_F_RECOVER_VERIFY	0x00400		/* In recovery - verify. */
+#define	REP_F_TALLY		0x00800		/* Tallied vote before elect. */
 	u_int32_t	flags;
 } REP;
 
+/*
+ * Recovery flag mask to easily check any/all recovery bits.  That is
+ * REP_F_READY and all REP_F_RECOVER*.  This must change if the values
+ * of the flags change.
+ */
+#define	REP_F_RECOVER_MASK					\
+    (REP_F_READY | REP_F_RECOVER_LOG | REP_F_RECOVER_PAGE |	\
+     REP_F_RECOVER_UPDATE | REP_F_RECOVER_VERIFY)
+
 #define	IN_ELECTION(R)		F_ISSET((R), REP_F_EPHASE1 | REP_F_EPHASE2)
-#define	ELECTION_DONE(R)	F_CLR((R), REP_F_EPHASE1 | REP_F_EPHASE2)
+#define	IN_ELECTION_TALLY(R) \
+	F_ISSET((R), REP_F_EPHASE1 | REP_F_EPHASE2 | REP_F_TALLY)
+#define	IS_REP_MASTER(dbenv)						\
+	(REP_ON(dbenv) && ((DB_REP *)(dbenv)->rep_handle)->region &&	\
+	    F_ISSET(((REP *)((DB_REP *)(dbenv)->rep_handle)->region),	\
+	    REP_F_MASTER))
+
+#define	IS_REP_CLIENT(dbenv)						\
+	(REP_ON(dbenv) && ((DB_REP *)(dbenv)->rep_handle)->region &&	\
+	    F_ISSET(((REP *)((DB_REP *)(dbenv)->rep_handle)->region),	\
+	    REP_F_CLIENT))
+
+#define	IS_CLIENT_PGRECOVER(dbenv)					\
+	(IS_REP_CLIENT(dbenv) &&					\
+	    F_ISSET(((REP *)((DB_REP *)(dbenv)->rep_handle)->region),   \
+	    REP_F_RECOVER_PAGE))
+
+/*
+ * Macros to figure out if we need to do replication pre/post-amble
+ * processing.
+ */
+#define	IS_REPLICATED(E, D)						\
+	(!F_ISSET((D), DB_AM_RECOVER | DB_AM_REPLICATION) &&		\
+	REP_ON(E) && ((DB_REP *)((E)->rep_handle))->region != NULL &&	\
+	((DB_REP *)((E)->rep_handle))->region->flags != 0)
+
+#define	IS_ENV_REPLICATED(E) (REP_ON(E) &&		\
+	((DB_REP *)((E)->rep_handle))->region != NULL &&		\
+	((DB_REP *)((E)->rep_handle))->region->flags != 0)
 
 /*
  * Per-process replication structure.
+ *
+ * There are 2 mutexes used in replication.
+ * 1.  rep_mutexp - This protects the fields of the rep region above.
+ * 2.  db_mutexp - This protects the per-process flags, and bookkeeping
+ * database and all of the components that maintain it.  Those
+ * components include the following fields in the log region (see log.h):
+ *	a. ready_lsn
+ *	b. waiting_lsn
+ *	c. verify_lsn
+ *	d. wait_recs
+ *	e. rcvd_recs
+ *	f. max_wait_lsn
+ * These fields in the log region are NOT protected by the log
+ * region lock at all.
+ *
+ * Note that the per-process flags should truly be protected by a
+ * special per-process thread mutex, but it is currently set in so
+ * isolated a manner that it didn't make sense to do so and in most
+ * case we're already holding the db_mutexp anyway.
+ *
+ * The lock ordering protocol is that db_mutexp must be acquired
+ * first and then either rep_mutexp, or the log region mutex may
+ * be acquired if necessary.
  */
 struct __db_rep {
-	DB_MUTEX	*mutexp;
+	DB_MUTEX	*rep_mutexp;	/* Mutex for rep region */
 
 	DB_MUTEX	*db_mutexp;	/* Mutex for bookkeeping database. */
 	DB		*rep_db;	/* Bookkeeping database. */
 
 	REP		*region;	/* In memory structure. */
-	int		(*rep_send)	/* Send function. */
-			    __P((DB_ENV *,
-			    const DBT *, const DBT *, int, u_int32_t));
+#define	DBREP_OPENFILES		0x0001	/* This handle has opened files. */
+	u_int32_t	flags;		/* per-process flags. */
 };
 
 /*
@@ -120,10 +262,10 @@ struct __db_rep {
  * Note that the version information should be at the beginning of the
  * structure, so that we can rearrange the rest of it while letting the
  * version checks continue to work.  DB_REPVERSION should be revved any time
- * the rest of the structure changes.
+ * the rest of the structure changes or when the message numbers change.
  */
 typedef struct __rep_control {
-#define	DB_REPVERSION	1
+#define	DB_REPVERSION	2
 	u_int32_t	rep_version;	/* Replication version number. */
 	u_int32_t	log_version;	/* Log version number. */
 
@@ -135,37 +277,28 @@ typedef struct __rep_control {
 
 /* Election vote information. */
 typedef struct __rep_vote {
-	int	priority;		/* My site's priority. */
-	int	nsites;			/* Number of sites I've been in
+	u_int32_t	egen;		/* Election generation. */
+	int		nsites;		/* Number of sites I've been in
 					 * communication with. */
-	int	tiebreaker;		/* Tie-breaking quasi-random int. */
+	int		nvotes;		/* Number of votes needed to win. */
+	int		priority;	/* My site's priority. */
+	u_int32_t	tiebreaker;	/* Tie-breaking quasi-random value. */
 } REP_VOTE_INFO;
 
+typedef struct __rep_vtally {
+	u_int32_t	egen;		/* Voter's election generation. */
+	int		eid;		/* Voter's ID. */
+} REP_VTALLY;
+
 /*
  * This structure takes care of representing a transaction.
  * It holds all the records, sorted by page number so that
  * we can obtain locks and apply updates in a deadlock free
  * order.
  */
-typedef struct __lsn_page {
-	DB_LSN		lsn;
-	u_int32_t	fid;
-	DB_LOCK_ILOCK	pgdesc;
-#define	LSN_PAGE_NOLOCK		0x0001	/* No lock necessary for log rec. */
-	u_int32_t	flags;
-} LSN_PAGE;
-
-typedef struct __txn_recs {
-	int		npages;
-	int		nalloc;
-	LSN_PAGE	*array;
-	u_int32_t	txnid;
-	u_int32_t	lockid;
-} TXN_RECS;
-
 typedef struct __lsn_collection {
-	int nlsns;
-	int nalloc;
+	u_int nlsns;
+	u_int nalloc;
 	DB_LSN *array;
 } LSN_COLLECTION;
 
diff --git a/storage/bdb/dbinc/shqueue.h b/storage/bdb/dbinc/shqueue.h
index 47fdf12ac9277b1230a6a1fb04368ced346f1661..8d7e4eef922924c0ebf9747b67cabc39a1e775dd 100644
--- a/storage/bdb/dbinc/shqueue.h
+++ b/storage/bdb/dbinc/shqueue.h
@@ -1,18 +1,18 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: shqueue.h,v 11.9 2002/01/11 15:52:30 bostic Exp $
+ * $Id: shqueue.h,v 11.15 2004/03/24 20:37:37 bostic Exp $
  */
 
 #ifndef	_SYS_SHQUEUE_H_
 #define	_SYS_SHQUEUE_H_
 
 /*
- * This file defines three types of data structures: lists, tail queues, and
- * circular queues, similarly to the include file <sys/queue.h>.
+ * This file defines two types of data structures: lists and tail queues
+ * similarly to the include file <sys/queue.h>.
  *
  * The difference is that this set of macros can be used for structures that
  * reside in shared memory that may be mapped at different addresses in each
@@ -20,6 +20,14 @@
  * the normal macros, although the macro calls require an additional type
  * parameter, only used by the HEAD and ENTRY macros of the standard macros.
  *
+ * Since we use relative offsets of type ssize_t rather than pointers, 0
+ * (aka NULL) is a valid offset and cannot be used to indicate the end
+ * of a list.  Therefore, we use -1 to indicate end of list.
+ *
+ * The macros ending in "P" return pointers without checking for end or
+ * beginning of lists, the others check for end of list and evaluate to
+ * either a pointer or NULL.
+ *
  * For details on the use of these macros, see the queue(3) manual page.
  */
 
@@ -28,32 +36,34 @@ extern "C" {
 #endif
 
 /*
- * Shared list definitions.
+ * Shared memory list definitions.
  */
 #define	SH_LIST_HEAD(name)						\
 struct name {								\
 	ssize_t slh_first;	/* first element */			\
 }
 
+#define	SH_LIST_HEAD_INITIALIZER(head)					\
+	{ -1 }
+
 #define	SH_LIST_ENTRY							\
 struct {								\
-	ssize_t sle_next;	/* relative offset next element */	\
+	ssize_t sle_next;	/* relative offset to next element */	\
 	ssize_t sle_prev;	/* relative offset of prev element */	\
 }
 
 /*
- * Shared list functions.  Since we use relative offsets for pointers,
- * 0 is a valid offset.  Therefore, we use -1 to indicate end of list.
- * The macros ending in "P" return pointers without checking for end
- * of list, the others check for end of list and evaluate to either a
- * pointer or NULL.
+ * Shared memory list functions.
  */
 
+#define	SH_LIST_EMPTY(head)						\
+	((head)->slh_first == -1)
+
 #define	SH_LIST_FIRSTP(head, type)					\
 	((struct type *)(((u_int8_t *)(head)) + (head)->slh_first))
 
 #define	SH_LIST_FIRST(head, type)					\
-	((head)->slh_first == -1 ? NULL :				\
+	(SH_LIST_EMPTY(head) ? NULL :					\
 	((struct type *)(((u_int8_t *)(head)) + (head)->slh_first)))
 
 #define	SH_LIST_NEXTP(elm, field, type)					\
@@ -63,22 +73,58 @@ struct {								\
 	((elm)->field.sle_next == -1 ? NULL :				\
 	((struct type *)(((u_int8_t *)(elm)) + (elm)->field.sle_next)))
 
-#define	SH_LIST_PREV(elm, field)					\
+  /*
+   *__SH_LIST_PREV_OFF is private API.  It calculates the address of
+   * the elm->field.sle_next member of a SH_LIST structure.  All offsets
+   * between elements are relative to that point in SH_LIST structures.
+   */
+#define	__SH_LIST_PREV_OFF(elm, field)					\
 	((ssize_t *)(((u_int8_t *)(elm)) + (elm)->field.sle_prev))
 
+#define	SH_LIST_PREV(elm, field, type)					\
+	(struct type *)((ssize_t)elm - (*__SH_LIST_PREV_OFF(elm, field)))
+
+#define	SH_LIST_FOREACH(var, head, field, type)				\
+	for ((var) = SH_LIST_FIRST((head), type);			\
+	    (var);							\
+	    (var) = SH_LIST_NEXT((var), field, type))
+
 #define	SH_PTR_TO_OFF(src, dest)					\
 	((ssize_t)(((u_int8_t *)(dest)) - ((u_int8_t *)(src))))
 
 /*
+ * Given correct A.next: B.prev = SH_LIST_NEXT_TO_PREV(A)
+ * in a list [A, B]
+ * The prev value is always the offset from an element to its preceding
+ * element's next location, not the beginning of the structure.  To get
+ * to the beginning of an element structure in memory given an element
+ * do the following:
+ * A = B - (B.prev + (&B.next - B))
  * Take the element's next pointer and calculate what the corresponding
  * Prev pointer should be -- basically it is the negation plus the offset
  * of the next field in the structure.
  */
 #define	SH_LIST_NEXT_TO_PREV(elm, field)				\
-	(-(elm)->field.sle_next + SH_PTR_TO_OFF(elm, &(elm)->field.sle_next))
+	(((elm)->field.sle_next == -1 ? 0 : -(elm)->field.sle_next) +	\
+	   SH_PTR_TO_OFF(elm, &(elm)->field.sle_next))
 
 #define	SH_LIST_INIT(head) (head)->slh_first = -1
 
+#define	SH_LIST_INSERT_BEFORE(head, listelm, elm, field, type) do {	\
+	if (listelm == SH_LIST_FIRST(head, type)) {			\
+	SH_LIST_INSERT_HEAD(head, elm, field, type);			\
+	} else {							\
+		(elm)->field.sle_next = SH_PTR_TO_OFF(elm, listelm);	\
+		(elm)->field.sle_prev = SH_LIST_NEXT_TO_PREV(		\
+			SH_LIST_PREV((listelm), field, type), field) +	\
+		(elm)->field.sle_next;					\
+		(SH_LIST_PREV(listelm, field, type))->field.sle_next =	\
+			(SH_PTR_TO_OFF((SH_LIST_PREV(listelm, field,	\
+						     type)), elm));	\
+	(listelm)->field.sle_prev = SH_LIST_NEXT_TO_PREV(elm, field);	\
+	}								\
+} while (0)
+
 #define	SH_LIST_INSERT_AFTER(listelm, elm, field, type) do {		\
 	if ((listelm)->field.sle_next != -1) {				\
 		(elm)->field.sle_next = SH_PTR_TO_OFF(elm,		\
@@ -93,7 +139,7 @@ struct {								\
 
 #define	SH_LIST_INSERT_HEAD(head, elm, field, type) do {		\
 	if ((head)->slh_first != -1) {					\
-		(elm)->field.sle_next =				\
+		(elm)->field.sle_next =					\
 		    (head)->slh_first - SH_PTR_TO_OFF(head, elm);	\
 		SH_LIST_FIRSTP(head, type)->field.sle_prev =		\
 			SH_LIST_NEXT_TO_PREV(elm, field);		\
@@ -107,13 +153,19 @@ struct {								\
 	if ((elm)->field.sle_next != -1) {				\
 		SH_LIST_NEXTP(elm, field, type)->field.sle_prev =	\
 			(elm)->field.sle_prev - (elm)->field.sle_next;	\
-		*SH_LIST_PREV(elm, field) += (elm)->field.sle_next;	\
+		*__SH_LIST_PREV_OFF(elm, field) += (elm)->field.sle_next;\
 	} else								\
-		*SH_LIST_PREV(elm, field) = -1;				\
+		*__SH_LIST_PREV_OFF(elm, field) = -1;			\
+} while (0)
+
+#define	SH_LIST_REMOVE_HEAD(head, field, type) do {			\
+	if (!SH_LIST_EMPTY(head)) {					\
+		SH_LIST_REMOVE(SH_LIST_FIRSTP(head, type), field, type);\
+	}								\
 } while (0)
 
 /*
- * Shared tail queue definitions.
+ * Shared memory tail queue definitions.
  */
 #define	SH_TAILQ_HEAD(name)						\
 struct name {								\
@@ -121,6 +173,9 @@ struct name {								\
 	ssize_t stqh_last;	/* relative offset of last's next */	\
 }
 
+#define	SH_TAILQ_HEAD_INITIALIZER(head)					\
+	{ -1, 0 }
+
 #define	SH_TAILQ_ENTRY							\
 struct {								\
 	ssize_t stqe_next;	/* relative offset of next element */	\
@@ -128,28 +183,80 @@ struct {								\
 }
 
 /*
- * Shared tail queue functions.
+ * Shared memory tail queue functions.
  */
+
+#define	SH_TAILQ_EMPTY(head)						\
+	((head)->stqh_first == -1)
+
 #define	SH_TAILQ_FIRSTP(head, type)					\
 	((struct type *)((u_int8_t *)(head) + (head)->stqh_first))
 
 #define	SH_TAILQ_FIRST(head, type)					\
-	((head)->stqh_first == -1 ? NULL : SH_TAILQ_FIRSTP(head, type))
+	(SH_TAILQ_EMPTY(head) ? NULL : SH_TAILQ_FIRSTP(head, type))
 
 #define	SH_TAILQ_NEXTP(elm, field, type)				\
 	((struct type *)((u_int8_t *)(elm) + (elm)->field.stqe_next))
 
 #define	SH_TAILQ_NEXT(elm, field, type)					\
-	((elm)->field.stqe_next == -1 ? NULL : SH_TAILQ_NEXTP(elm, field, type))
-
-#define	SH_TAILQ_PREVP(elm, field)					\
-	((ssize_t *)((u_int8_t *)(elm) + (elm)->field.stqe_prev))
-
-#define	SH_TAILQ_LAST(head)						\
+	((elm)->field.stqe_next == -1 ? NULL :				\
+	((struct type *)((u_int8_t *)(elm) + (elm)->field.stqe_next)))
+
+  /*
+   * __SH_TAILQ_PREV_OFF is private API.  It calculates the address of
+   * the elm->field.stqe_next member of a SH_TAILQ structure.  All
+   * offsets between elements are relative to that point in SH_TAILQ
+   * structures.
+   */
+#define	__SH_TAILQ_PREV_OFF(elm, field)					\
+	((ssize_t *)(((u_int8_t *)(elm)) + (elm)->field.stqe_prev))
+
+#define	SH_TAILQ_PREVP(elm, field, type)				\
+	(struct type *)((ssize_t)elm - (*__SH_TAILQ_PREV_OFF(elm, field)))
+
+#define	SH_TAILQ_PREV(head, elm, field, type)				\
+	(((elm) == SH_TAILQ_FIRST(head, type)) ? NULL :		\
+	  (struct type *)((ssize_t)elm - (*__SH_TAILQ_PREV_OFF(elm, field))))
+
+  /*
+   * __SH_TAILQ_LAST_OFF is private API.  It calculates the address of
+   * the stqe_next member of a SH_TAILQ structure in the last element
+   * of this list.  All offsets between elements are relative to that
+   * point in SH_TAILQ structures.
+   */
+#define	__SH_TAILQ_LAST_OFF(head)					\
 	((ssize_t *)(((u_int8_t *)(head)) + (head)->stqh_last))
 
+#define	SH_TAILQ_LAST(head, field, type)				\
+	(SH_TAILQ_EMPTY(head) ? NULL :				\
+	(struct type *)((ssize_t)(head) +				\
+	 ((ssize_t)((head)->stqh_last) -				\
+	 ((ssize_t)SH_PTR_TO_OFF(SH_TAILQ_FIRST(head, type),		\
+		&(SH_TAILQ_FIRST(head, type)->field.stqe_next))))))
+
+/*
+ * Given correct A.next: B.prev = SH_TAILQ_NEXT_TO_PREV(A)
+ * in a list [A, B]
+ * The prev value is always the offset from an element to its preceding
+ * element's next location, not the beginning of the structure.  To get
+ * to the beginning of an element structure in memory given an element
+ * do the following:
+ * A = B - (B.prev + (&B.next - B))
+ */
 #define	SH_TAILQ_NEXT_TO_PREV(elm, field)				\
-	(-(elm)->field.stqe_next + SH_PTR_TO_OFF(elm, &(elm)->field.stqe_next))
+	(((elm)->field.stqe_next == -1 ? 0 :				\
+		(-(elm)->field.stqe_next) +				\
+		SH_PTR_TO_OFF(elm, &(elm)->field.stqe_next)))
+
+#define	SH_TAILQ_FOREACH(var, head, field, type)			\
+	for ((var) = SH_TAILQ_FIRST((head), type);			\
+	    (var);							\
+	    (var) = SH_TAILQ_NEXT((var), field, type))
+
+#define	SH_TAILQ_FOREACH_REVERSE(var, head, field, type)		\
+	for ((var) = SH_TAILQ_LAST((head), field, type);		\
+	    (var);							\
+	    (var) = SH_TAILQ_PREV((head), (var), field, type))
 
 #define	SH_TAILQ_INIT(head) {						\
 	(head)->stqh_first = -1;					\
@@ -163,9 +270,9 @@ struct {								\
 		SH_TAILQ_FIRSTP(head, type)->field.stqe_prev =		\
 			SH_TAILQ_NEXT_TO_PREV(elm, field);		\
 	} else {							\
-		(elm)->field.stqe_next = -1;				\
 		(head)->stqh_last =					\
 		    SH_PTR_TO_OFF(head, &(elm)->field.stqe_next);	\
+		(elm)->field.stqe_next = -1;				\
 	}								\
 	(head)->stqh_first = SH_PTR_TO_OFF(head, elm);			\
 	(elm)->field.stqe_prev =					\
@@ -180,13 +287,29 @@ struct {								\
 	    SH_PTR_TO_OFF((head), &(head)->stqh_first))			\
 		(head)->stqh_first = SH_PTR_TO_OFF(head, elm);		\
 	else								\
-		*SH_TAILQ_LAST(head) = -(head)->stqh_last +		\
+		*__SH_TAILQ_LAST_OFF(head) = -(head)->stqh_last +	\
 		    SH_PTR_TO_OFF((elm), &(elm)->field.stqe_next) +	\
 		    SH_PTR_TO_OFF(head, elm);				\
 	(head)->stqh_last =						\
 	    SH_PTR_TO_OFF(head, &((elm)->field.stqe_next));		\
 } while (0)
 
+#define	SH_TAILQ_INSERT_BEFORE(head, listelm, elm, field, type) do {	\
+	if (listelm == SH_TAILQ_FIRST(head, type)) {			\
+		SH_TAILQ_INSERT_HEAD(head, elm, field, type);		\
+	} else {							\
+		(elm)->field.stqe_next = SH_PTR_TO_OFF(elm, listelm);	\
+		(elm)->field.stqe_prev = SH_TAILQ_NEXT_TO_PREV(		\
+			SH_TAILQ_PREVP((listelm), field, type), field) + \
+			(elm)->field.stqe_next;				\
+		(SH_TAILQ_PREVP(listelm, field, type))->field.stqe_next =\
+		(SH_PTR_TO_OFF((SH_TAILQ_PREVP(listelm, field, type)),	\
+			elm));						\
+		(listelm)->field.stqe_prev =				\
+			SH_TAILQ_NEXT_TO_PREV(elm, field);		\
+	}								\
+} while (0)
+
 #define	SH_TAILQ_INSERT_AFTER(head, listelm, elm, field, type) do {	\
 	if ((listelm)->field.stqe_next != -1) {				\
 		(elm)->field.stqe_next = (listelm)->field.stqe_next -	\
@@ -208,129 +331,14 @@ struct {								\
 		    (elm)->field.stqe_prev +				\
 		    SH_PTR_TO_OFF(SH_TAILQ_NEXTP(elm,			\
 		    field, type), elm);					\
-		*SH_TAILQ_PREVP(elm, field) += elm->field.stqe_next;	\
+		*__SH_TAILQ_PREV_OFF(elm, field) += elm->field.stqe_next;\
 	} else {							\
 		(head)->stqh_last = (elm)->field.stqe_prev +		\
 			SH_PTR_TO_OFF(head, elm);			\
-		*SH_TAILQ_PREVP(elm, field) = -1;			\
+		*__SH_TAILQ_PREV_OFF(elm, field) = -1;			\
 	}								\
 } while (0)
 
-/*
- * Shared circular queue definitions.
- */
-#define	SH_CIRCLEQ_HEAD(name)						\
-struct name {								\
-	ssize_t scqh_first;		/* first element */		\
-	ssize_t scqh_last;		/* last element */		\
-}
-
-#define	SH_CIRCLEQ_ENTRY						\
-struct {								\
-	ssize_t scqe_next;		/* next element */		\
-	ssize_t scqe_prev;		/* previous element */		\
-}
-
-/*
- * Shared circular queue functions.
- */
-#define	SH_CIRCLEQ_FIRSTP(head, type)					\
-	((struct type *)(((u_int8_t *)(head)) + (head)->scqh_first))
-
-#define	SH_CIRCLEQ_FIRST(head, type)					\
-	((head)->scqh_first == -1 ?					\
-	(void *)head : SH_CIRCLEQ_FIRSTP(head, type))
-
-#define	SH_CIRCLEQ_LASTP(head, type)					\
-	((struct type *)(((u_int8_t *)(head)) + (head)->scqh_last))
-
-#define	SH_CIRCLEQ_LAST(head, type)					\
-	((head)->scqh_last == -1 ? (void *)head : SH_CIRCLEQ_LASTP(head, type))
-
-#define	SH_CIRCLEQ_NEXTP(elm, field, type)				\
-	((struct type *)(((u_int8_t *)(elm)) + (elm)->field.scqe_next))
-
-#define	SH_CIRCLEQ_NEXT(head, elm, field, type)				\
-	((elm)->field.scqe_next == SH_PTR_TO_OFF(elm, head) ?		\
-	    (void *)head : SH_CIRCLEQ_NEXTP(elm, field, type))
-
-#define	SH_CIRCLEQ_PREVP(elm, field, type)				\
-	((struct type *)(((u_int8_t *)(elm)) + (elm)->field.scqe_prev))
-
-#define	SH_CIRCLEQ_PREV(head, elm, field, type)				\
-	((elm)->field.scqe_prev == SH_PTR_TO_OFF(elm, head) ?		\
-	    (void *)head : SH_CIRCLEQ_PREVP(elm, field, type))
-
-#define	SH_CIRCLEQ_INIT(head) {						\
-	(head)->scqh_first = 0;						\
-	(head)->scqh_last = 0;						\
-}
-
-#define	SH_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field, type) do {	\
-	(elm)->field.scqe_prev = SH_PTR_TO_OFF(elm, listelm);		\
-	(elm)->field.scqe_next = (listelm)->field.scqe_next +		\
-	    (elm)->field.scqe_prev;					\
-	if (SH_CIRCLEQ_NEXTP(listelm, field, type) == (void *)head)	\
-		(head)->scqh_last = SH_PTR_TO_OFF(head, elm);		\
-	else								\
-		SH_CIRCLEQ_NEXTP(listelm,				\
-		    field, type)->field.scqe_prev =			\
-		    SH_PTR_TO_OFF(SH_CIRCLEQ_NEXTP(listelm,		\
-		    field, type), elm);					\
-	(listelm)->field.scqe_next = -(elm)->field.scqe_prev;		\
-} while (0)
-
-#define	SH_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field, type) do {	\
-	(elm)->field.scqe_next = SH_PTR_TO_OFF(elm, listelm);		\
-	(elm)->field.scqe_prev = (elm)->field.scqe_next -		\
-		SH_CIRCLEQ_PREVP(listelm, field, type)->field.scqe_next;\
-	if (SH_CIRCLEQ_PREVP(listelm, field, type) == (void *)(head))	\
-		(head)->scqh_first = SH_PTR_TO_OFF(head, elm);		\
-	else								\
-		SH_CIRCLEQ_PREVP(listelm,				\
-		    field, type)->field.scqe_next =			\
-		    SH_PTR_TO_OFF(SH_CIRCLEQ_PREVP(listelm,		\
-		    field, type), elm);					\
-	(listelm)->field.scqe_prev = -(elm)->field.scqe_next;		\
-} while (0)
-
-#define	SH_CIRCLEQ_INSERT_HEAD(head, elm, field, type) do {		\
-	(elm)->field.scqe_prev = SH_PTR_TO_OFF(elm, head);		\
-	(elm)->field.scqe_next = (head)->scqh_first +			\
-		(elm)->field.scqe_prev;					\
-	if ((head)->scqh_last == 0)					\
-		(head)->scqh_last = -(elm)->field.scqe_prev;		\
-	else								\
-		SH_CIRCLEQ_FIRSTP(head, type)->field.scqe_prev =	\
-		    SH_PTR_TO_OFF(SH_CIRCLEQ_FIRSTP(head, type), elm);	\
-	(head)->scqh_first = -(elm)->field.scqe_prev;			\
-} while (0)
-
-#define	SH_CIRCLEQ_INSERT_TAIL(head, elm, field, type) do {		\
-	(elm)->field.scqe_next = SH_PTR_TO_OFF(elm, head);		\
-	(elm)->field.scqe_prev = (head)->scqh_last +			\
-	    (elm)->field.scqe_next;					\
-	if ((head)->scqh_first == 0)					\
-		(head)->scqh_first = -(elm)->field.scqe_next;		\
-	else								\
-		SH_CIRCLEQ_LASTP(head, type)->field.scqe_next =	\
-		    SH_PTR_TO_OFF(SH_CIRCLEQ_LASTP(head, type), elm);	\
-	(head)->scqh_last = -(elm)->field.scqe_next;			\
-} while (0)
-
-#define	SH_CIRCLEQ_REMOVE(head, elm, field, type) do {			\
-	if (SH_CIRCLEQ_NEXTP(elm, field, type) == (void *)(head))	\
-		(head)->scqh_last += (elm)->field.scqe_prev;		\
-	else								\
-		SH_CIRCLEQ_NEXTP(elm, field, type)->field.scqe_prev +=	\
-		    (elm)->field.scqe_prev;				\
-	if (SH_CIRCLEQ_PREVP(elm, field, type) == (void *)(head))	\
-		(head)->scqh_first += (elm)->field.scqe_next;		\
-	else								\
-		SH_CIRCLEQ_PREVP(elm, field, type)->field.scqe_next +=	\
-		    (elm)->field.scqe_next;				\
-} while (0)
-
 #if defined(__cplusplus)
 }
 #endif
diff --git a/storage/bdb/dbinc/tcl_db.h b/storage/bdb/dbinc/tcl_db.h
index 8c04d5452954e6507b0967906af76d3363d05b98..f1adea5ae7cae30e2da4e70b9e9df1692eba054e 100644
--- a/storage/bdb/dbinc/tcl_db.h
+++ b/storage/bdb/dbinc/tcl_db.h
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: tcl_db.h,v 11.30 2002/08/06 06:11:22 bostic Exp $
+ * $Id: tcl_db.h,v 11.40 2004/09/22 03:40:20 bostic Exp $
  */
 
 #ifndef _DB_TCL_DB_H_
@@ -13,7 +13,8 @@
 #define	MSG_SIZE 100		/* Message size */
 
 enum INFOTYPE {
-    I_ENV, I_DB, I_DBC, I_TXN, I_MP, I_PG, I_LOCK, I_LOGC, I_NDBM, I_MUTEX };
+    I_ENV, I_DB, I_DBC, I_TXN, I_MP,
+    I_PG, I_LOCK, I_LOGC, I_NDBM, I_MUTEX, I_SEQ};
 
 #define	MAX_ID		8	/* Maximum number of sub-id's we need */
 #define	DBTCL_PREP	64	/* Size of txn_recover preplist */
@@ -25,7 +26,7 @@ typedef struct _mutex_entry {
 	union {
 		struct {
 			DB_MUTEX	real_m;
-			u_int32_t	real_val;
+			int		real_val;
 		} r;
 		/*
 		 * This is here to make sure that each of the mutex structures
@@ -46,7 +47,6 @@ typedef struct _mutex_data {
 	REGINFO		 reginfo;
 	_MUTEX_ENTRY	*marray;
 	size_t		 size;
-	u_int32_t	 n_mutex;
 } _MUTEX_DATA;
 
 /*
@@ -74,7 +74,7 @@ typedef struct _mutex_data {
  * I believe the number of simultaneous DB widgets in existence at one time
  * is not going to be that large (more than several dozen) such that
  * linearly searching the list is not going to impact performance in a
- * noticable way.  Should performance be impacted due to the size of the
+ * noticeable way.  Should performance be impacted due to the size of the
  * info list, then perhaps it is time to revisit this decision.
  */
 typedef struct dbtcl_info {
@@ -100,7 +100,7 @@ typedef struct dbtcl_info {
 	} und;
 	union data2 {
 		int anydata;
-		size_t pagesz;
+		int pagesz;
 	} und2;
 	DBT i_lockobj;
 	FILE *i_err;
@@ -156,26 +156,39 @@ typedef struct dbtcl_global {
 
 extern DBTCL_GLOBAL __dbtcl_global;
 
-#define	NAME_TO_ENV(name) (DB_ENV *)_NameToPtr((name))
-#define	NAME_TO_DB(name) (DB *)_NameToPtr((name))
-#define	NAME_TO_DBC(name) (DBC *)_NameToPtr((name))
-#define	NAME_TO_TXN(name) (DB_TXN *)_NameToPtr((name))
-#define	NAME_TO_MP(name) (DB_MPOOLFILE *)_NameToPtr((name))
-#define	NAME_TO_LOCK(name) (DB_LOCK *)_NameToPtr((name))
+/*
+ * Tcl_NewStringObj takes an "int" length argument, when the typical use is to
+ * call it with a size_t length (for example, returned by strlen).  Tcl is in
+ * the wrong, but that doesn't help us much -- cast the argument.
+ */
+#define	NewStringObj(a, b)						\
+	Tcl_NewStringObj(a, (int)b)
+
+#define	NAME_TO_DB(name)	(DB *)_NameToPtr((name))
+#define	NAME_TO_DBC(name)	(DBC *)_NameToPtr((name))
+#define	NAME_TO_ENV(name)	(DB_ENV *)_NameToPtr((name))
+#define	NAME_TO_LOCK(name)	(DB_LOCK *)_NameToPtr((name))
+#define	NAME_TO_MP(name)	(DB_MPOOLFILE *)_NameToPtr((name))
+#define	NAME_TO_TXN(name)	(DB_TXN *)_NameToPtr((name))
+#define	NAME_TO_SEQUENCE(name)	(DB_SEQUENCE *)_NameToPtr((name))
 
 /*
- * MAKE_STAT_LIST appends a {name value} pair to a result list
- * that MUST be called 'res' that is a Tcl_Obj * in the local
- * function.  This macro also assumes a label "error" to go to
- * in the even of a Tcl error.  For stat functions this will
- * typically go before the "free" function to free the stat structure
- * returned by DB.
+ * MAKE_STAT_LIST appends a {name value} pair to a result list that MUST be
+ * called 'res' that is a Tcl_Obj * in the local function.  This macro also
+ * assumes a label "error" to go to in the event of a Tcl error.  For stat
+ * functions this will typically go before the "free" function to free the
+ * stat structure returned by DB.
  */
-#define	MAKE_STAT_LIST(s,v)					\
-do {								\
-	result = _SetListElemInt(interp, res, (s), (v));	\
-	if (result != TCL_OK)					\
-		goto error;					\
+#define	MAKE_STAT_LIST(s, v) do {					\
+	result = _SetListElemInt(interp, res, (s), (long)(v));		\
+	if (result != TCL_OK)						\
+		goto error;						\
+} while (0)
+
+#define	MAKE_WSTAT_LIST(s, v) do {					\
+	result = _SetListElemWideInt(interp, res, (s), (int64_t)(v));	\
+	if (result != TCL_OK)						\
+		goto error;						\
 } while (0)
 
 /*
@@ -186,14 +199,13 @@ do {								\
  * typically go before the "free" function to free the stat structure
  * returned by DB.
  */
-#define	MAKE_STAT_LSN(s, lsn)						\
-do {									\
+#define	MAKE_STAT_LSN(s, lsn) do {					\
 	myobjc = 2;							\
 	myobjv[0] = Tcl_NewLongObj((long)(lsn)->file);			\
 	myobjv[1] = Tcl_NewLongObj((long)(lsn)->offset);		\
 	lsnlist = Tcl_NewListObj(myobjc, myobjv);			\
 	myobjc = 2;							\
-	myobjv[0] = Tcl_NewStringObj((s), strlen(s));			\
+	myobjv[0] = Tcl_NewStringObj((s), (int)strlen(s));		\
 	myobjv[1] = lsnlist;						\
 	thislist = Tcl_NewListObj(myobjc, myobjv);			\
 	result = Tcl_ListObjAppendElement(interp, res, thislist);	\
@@ -209,27 +221,25 @@ do {									\
  * typically go before the "free" function to free the stat structure
  * returned by DB.
  */
-#define	MAKE_STAT_STRLIST(s,s1)					\
-do {								\
-	result = _SetListElem(interp, res, (s), strlen(s),	\
-	    (s1), strlen(s1));					\
-	if (result != TCL_OK)					\
-		goto error;					\
+#define	MAKE_STAT_STRLIST(s,s1) do {					\
+	result = _SetListElem(interp, res, (s), strlen(s),		\
+	    (s1), strlen(s1));						\
+	if (result != TCL_OK)						\
+		goto error;						\
 } while (0)
 
 /*
  * FLAG_CHECK checks that the given flag is not set yet.
  * If it is, it sets up an error message.
  */
-#define	FLAG_CHECK(flag)					\
-do {								\
-	if ((flag) != 0) {					\
-		Tcl_SetResult(interp,				\
-		    " Only 1 policy can be specified.\n",	\
-		    TCL_STATIC);				\
-		result = TCL_ERROR;				\
-		break;						\
-	}							\
+#define	FLAG_CHECK(flag) do {						\
+	if ((flag) != 0) {						\
+		Tcl_SetResult(interp,					\
+		    " Only 1 policy can be specified.\n",		\
+		    TCL_STATIC);					\
+		result = TCL_ERROR;					\
+		break;							\
+	}								\
 } while (0)
 
 /*
@@ -237,15 +247,14 @@ do {								\
  * only set to the given allowed value.
  * If it is, it sets up an error message.
  */
-#define	FLAG_CHECK2(flag,val)					\
-do {								\
-	if (((flag) & ~(val)) != 0) {				\
-		Tcl_SetResult(interp,				\
-		    " Only 1 policy can be specified.\n",	\
-		    TCL_STATIC);				\
-		result = TCL_ERROR;				\
-		break;						\
-	}							\
+#define	FLAG_CHECK2(flag, val) do {					\
+	if (((flag) & ~(val)) != 0) {					\
+		Tcl_SetResult(interp,					\
+		    " Only 1 policy can be specified.\n",		\
+		    TCL_STATIC);					\
+		result = TCL_ERROR;					\
+		break;							\
+	}								\
 } while (0)
 
 /*
diff --git a/storage/bdb/dbinc/txn.h b/storage/bdb/dbinc/txn.h
index 31b00a6ba748128531e77306de40ab92809a9c6b..514b740e88ac8d2c08e6cf752a3c21c21eb56f0c 100644
--- a/storage/bdb/dbinc/txn.h
+++ b/storage/bdb/dbinc/txn.h
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: txn.h,v 11.43 2002/08/29 14:22:19 margo Exp $
+ * $Id: txn.h,v 11.54 2004/09/24 00:43:18 bostic Exp $
  */
 
 #ifndef	_TXN_H_
@@ -14,12 +14,14 @@
 
 /* Operation parameters to the delayed commit processing code. */
 typedef enum {
+	TXN_CLOSE,		/* Close a DB handle whose close had failed. */
 	TXN_REMOVE,		/* Remove a file. */
 	TXN_TRADE,		/* Trade lockers. */
 	TXN_TRADED		/* Already traded; downgrade lock. */
 } TXN_EVENT_T;
 
 struct __db_txnregion;	typedef struct __db_txnregion DB_TXNREGION;
+struct __txn_logrec;	typedef struct __txn_logrec DB_TXNLOGREC;
 
 /*
  * !!!
@@ -46,8 +48,8 @@ typedef struct __txn_detail {
 #define	TXN_PREPARED		3
 #define	TXN_COMMITTED		4
 	u_int32_t status;		/* status of the transaction */
-#define	TXN_COLLECTED		0x1
-#define	TXN_RESTORED		0x2
+#define	TXN_DTL_COLLECTED	0x1
+#define	TXN_DTL_RESTORED	0x2
 	u_int32_t flags;		/* collected during txn_recover */
 
 	SH_TAILQ_ENTRY	links;		/* free/active list */
@@ -75,14 +77,14 @@ typedef struct __txn_detail {
  *	The transaction manager encapsulates the transaction system.
  */
 struct __db_txnmgr {
-/*
- * These fields need to be protected for multi-threaded support.
- *
- * !!!
- * As this structure is allocated in per-process memory, the mutex may need
- * to be stored elsewhere on architectures unable to support mutexes in heap
- * memory, e.g., HP/UX 9.
- */
+	/*
+	 * These fields need to be protected for multi-threaded support.
+	 *
+	 * !!!
+	 * As this structure is allocated in per-process memory, the mutex may
+	 * need to be stored elsewhere on architectures unable to support
+	 * mutexes in heap memory, e.g., HP/UX 9.
+	 */
 	DB_MUTEX	*mutexp;	/* Lock list of active transactions
 					 * (including the content of each
 					 * TXN_DETAIL structure on the list).
@@ -104,10 +106,10 @@ struct __db_txnregion {
 	u_int32_t	maxtxns;	/* maximum number of active TXNs */
 	u_int32_t	last_txnid;	/* last transaction id given out */
 	u_int32_t	cur_maxid;	/* current max unused id. */
+
 	DB_LSN		last_ckp;	/* lsn of the last checkpoint */
 	time_t		time_ckp;	/* time of last checkpoint */
-	u_int32_t	logtype;	/* type of logging */
-	u_int32_t	locktype;	/* lock type */
+
 	DB_TXN_STAT	stat;		/* Statistics for txns. */
 
 #define	TXN_IN_RECOVERY	 0x01		/* environment is being recovered */
@@ -121,21 +123,91 @@ struct __db_txnregion {
 #endif
 };
 
+/*
+ * DB_TXNLOGREC --
+ *	An in-memory, linked-list copy of a log record.
+ */
+struct __txn_logrec {
+	STAILQ_ENTRY(__txn_logrec) links;/* Linked list. */
+
+	u_int8_t data[1];		/* Log record. */
+};
+
 /*
  * Log record types.  Note that these are *not* alphabetical.  This is
  * intentional so that we don't change the meaning of values between
- * software upgrades. EXPECTED, UNEXPECTED, IGNORE, NOTFOUND and OK
- * are used in the
- * txnlist functions.
+ * software upgrades.
+ *
+ * EXPECTED, UNEXPECTED, IGNORE, and OK are used in the txnlist functions.
+ * Here is an explanation of how the statuses are used.
+ *
+ * TXN_OK
+ *	BEGIN records for transactions found on the txnlist during
+ *	OPENFILES (BEGIN records are those with a prev_lsn of 0,0)
+ *
+ * TXN_COMMIT
+ *	Transaction committed and should be rolled forward.
+ *
+ * TXN_ABORT
+ *	This transaction's changes must be undone.  Either there was
+ *	never a prepare or commit record for this transaction OR there
+ *	was a commit, but we are recovering to a timestamp or particular
+ *	LSN and that point is before this transaction's commit.
+ *
+ * TXN_PREPARE
+ *	Prepare record, but no commit record is in the log.
+ *
+ * TXN_IGNORE
+ *	Generic meaning is that this transaction should not be
+ *	processed during later recovery passes.  We use it in a
+ *	number of different manners:
+ *
+ *	1. We never saw its BEGIN record.  Therefore, the logs have
+ *	   been reclaimed and we *know* that this transaction doesn't
+ *	   need to be aborted, because in order for it to be
+ *	   reclaimed, there must have been a subsequent checkpoint
+ *	   (and any dirty pages for this transaction made it to
+ *	   disk).
+ *
+ *	2. This is a child transaction that created a database.
+ *	   For some reason, we don't want to recreate that database
+ *	   (i.e., it already exists or some other database created
+ *	   after it exists).
+ *
+ *	3. During recovery open of subdatabases, if the master check fails,
+ *	   we use a TXN_IGNORE on the create of the subdb in the nested
+ *	   transaction.
+ *
+ *	4. During a remove, the file with the name being removed isn't
+ *	   the file for which we are recovering a remove.
+ *
+ * TXN_EXPECTED
+ *	After a successful open during recovery, we update the
+ *	transaction's status to TXN_EXPECTED.  The open was done
+ *	in the parent, but in the open log record, we record the
+ *	child transaction's ID if we also did a create.  When there
+ *	is a valid ID in that field, we use it and mark the child's
+ *	status as TXN_EXPECTED (indicating that we don't need to redo
+ *	a create for this file).
+ *
+ *	When recovering a remove, if we don't find or can't open
+ *	the file, the child (which does the remove) gets marked
+ *	EXPECTED (indicating that we don't need to redo the remove).
+ *
+ * TXN_UNEXPECTED
+ *	During recovery, we attempted an open that should have succeeded
+ *	and we got ENOENT, so like with the EXPECTED case, we indicate
+ *	in the child that we got the UNEXPECTED return so that we do redo
+ *	the creating/deleting operation.
+ *
  */
 #define	TXN_OK		0
 #define	TXN_COMMIT	1
 #define	TXN_PREPARE	2
 #define	TXN_ABORT	3
-#define	TXN_NOTFOUND	4
-#define	TXN_IGNORE	5
-#define	TXN_EXPECTED	6
-#define	TXN_UNEXPECTED	7
+#define	TXN_IGNORE	4
+#define	TXN_EXPECTED	5
+#define	TXN_UNEXPECTED	6
 
 #include "dbinc_auto/txn_auto.h"
 #include "dbinc_auto/txn_ext.h"
diff --git a/storage/bdb/dbinc/xa.h b/storage/bdb/dbinc/xa.h
index 64bdac8c914f69094f12679f089d696f3a7cf85e..71333c2c97bbb98605d8a774572f2978561ef44e 100644
--- a/storage/bdb/dbinc/xa.h
+++ b/storage/bdb/dbinc/xa.h
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1998-2002
+ * Copyright (c) 1998-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: xa.h,v 11.5 2002/01/11 15:52:30 bostic Exp $
+ * $Id: xa.h,v 11.7 2004/01/28 03:36:02 bostic Exp $
  */
 /*
  * Start of xa.h header
diff --git a/storage/bdb/dbm/dbm.c b/storage/bdb/dbm/dbm.c
index 3aa6fff698212063b6fdd44b80565dc13d3365a4..842b8d0a445b6906e856c8d45f8d64941d06f22c 100644
--- a/storage/bdb/dbm/dbm.c
+++ b/storage/bdb/dbm/dbm.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -38,14 +38,12 @@
  * 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.
+ *
+ * $Id: dbm.c,v 11.18 2004/05/10 21:26:47 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: dbm.c,v 11.14 2002/02/22 16:11:10 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -76,14 +74,11 @@ static const char revid[] = "$Id: dbm.c,v 11.14 2002/02/22 16:11:10 bostic Exp $
  * EXTERN: int	 __db_ndbm_store __P((DBM *, datum, datum, int));
  *
  * EXTERN: int	 __db_dbm_close __P((void));
- * EXTERN: int	 __db_dbm_dbrdonly __P((void));
  * EXTERN: int	 __db_dbm_delete __P((datum));
- * EXTERN: int	 __db_dbm_dirf __P((void));
  * EXTERN: datum __db_dbm_fetch __P((datum));
  * EXTERN: datum __db_dbm_firstkey __P((void));
  * EXTERN: int	 __db_dbm_init __P((char *));
  * EXTERN: datum __db_dbm_nextkey __P((datum));
- * EXTERN: int	 __db_dbm_pagf __P((void));
  * EXTERN: int	 __db_dbm_store __P((datum, datum));
  *
  * EXTERN: #endif
@@ -101,7 +96,7 @@ __db_dbm_init(file)
 	char *file;
 {
 	if (__cur_db != NULL)
-		(void)dbm_close(__cur_db);
+		dbm_close(__cur_db);
 	if ((__cur_db =
 	    dbm_open(file, O_CREAT | O_RDWR, __db_omode("rw----"))) != NULL)
 		return (0);
@@ -289,7 +284,7 @@ __db_ndbm_fetch(dbm, key)
 
 	memset(&_key, 0, sizeof(DBT));
 	memset(&_data, 0, sizeof(DBT));
-	_key.size = key.dsize;
+	_key.size = (u_int32_t)key.dsize;
 	_key.data = key.dptr;
 
 	/*
@@ -299,7 +294,7 @@ __db_ndbm_fetch(dbm, key)
 	 */
 	if ((ret = dbc->dbp->get(dbc->dbp, NULL, &_key, &_data, 0)) == 0) {
 		data.dptr = _data.data;
-		data.dsize = _data.size;
+		data.dsize = (int)_data.size;
 	} else {
 		data.dptr = NULL;
 		data.dsize = 0;
@@ -334,7 +329,7 @@ __db_ndbm_firstkey(dbm)
 
 	if ((ret = dbc->c_get(dbc, &_key, &_data, DB_FIRST)) == 0) {
 		key.dptr = _key.data;
-		key.dsize = _key.size;
+		key.dsize = (int)_key.size;
 	} else {
 		key.dptr = NULL;
 		key.dsize = 0;
@@ -369,7 +364,7 @@ __db_ndbm_nextkey(dbm)
 
 	if ((ret = dbc->c_get(dbc, &_key, &_data, DB_NEXT)) == 0) {
 		key.dptr = _key.data;
-		key.dsize = _key.size;
+		key.dsize = (int)_key.size;
 	} else {
 		key.dptr = NULL;
 		key.dsize = 0;
@@ -401,7 +396,7 @@ __db_ndbm_delete(dbm, key)
 
 	memset(&_key, 0, sizeof(DBT));
 	_key.data = key.dptr;
-	_key.size = key.dsize;
+	_key.size = (u_int32_t)key.dsize;
 
 	if ((ret = dbc->dbp->del(dbc->dbp, NULL, &_key, 0)) == 0)
 		return (0);
@@ -435,11 +430,11 @@ __db_ndbm_store(dbm, key, data, flags)
 
 	memset(&_key, 0, sizeof(DBT));
 	_key.data = key.dptr;
-	_key.size = key.dsize;
+	_key.size = (u_int32_t)key.dsize;
 
 	memset(&_data, 0, sizeof(DBT));
 	_data.data = data.dptr;
-	_data.size = data.dsize;
+	_data.size = (u_int32_t)data.dsize;
 
 	if ((ret = dbc->dbp->put(dbc->dbp, NULL,
 	    &_key, &_data, flags == DBM_INSERT ? DB_NOOVERWRITE : 0)) == 0)
diff --git a/storage/bdb/dbreg/dbreg.c b/storage/bdb/dbreg/dbreg.c
index 289fe67ed50d8d3691771aa883ecd5838b569335..930c8bb7ade4fa7b71a4ae310f8d21721f879f07 100644
--- a/storage/bdb/dbreg/dbreg.c
+++ b/storage/bdb/dbreg/dbreg.c
@@ -1,14 +1,13 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: dbreg.c,v 11.90 2004/10/15 16:59:39 bostic Exp $
  */
-#include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: dbreg.c,v 11.68 2002/08/28 19:05:27 margo Exp $";
-#endif /* not lint */
+#include "db_config.h"
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
@@ -17,8 +16,14 @@ static const char revid[] = "$Id: dbreg.c,v 11.68 2002/08/28 19:05:27 margo Exp
 #endif
 
 #include "db_int.h"
+#include "dbinc/db_page.h"
 #include "dbinc/log.h"
 #include "dbinc/txn.h"
+#include "dbinc/db_am.h"
+
+static int __dbreg_push_id __P((DB_ENV *, int32_t));
+static int __dbreg_pop_id __P((DB_ENV *, int32_t *));
+static int __dbreg_pluck_id __P((DB_ENV *, int32_t));
 
 /*
  * The dbreg subsystem, as its name implies, registers database handles so
@@ -96,37 +101,33 @@ __dbreg_setup(dbp, name, create_txnid)
 	DB_ENV *dbenv;
 	DB_LOG *dblp;
 	FNAME *fnp;
+	REGINFO *infop;
 	int ret;
 	size_t len;
 	void *namep;
 
 	dbenv = dbp->dbenv;
 	dblp = dbenv->lg_handle;
+	infop = &dblp->reginfo;
 
 	fnp = NULL;
 	namep = NULL;
 
 	/* Allocate an FNAME and, if necessary, a buffer for the name itself. */
-	R_LOCK(dbenv, &dblp->reginfo);
-	if ((ret =
-	    __db_shalloc(dblp->reginfo.addr, sizeof(FNAME), 0, &fnp)) != 0) {
-		R_UNLOCK(dbenv, &dblp->reginfo);
-		return (ret);
-	}
+	R_LOCK(dbenv, infop);
+	if ((ret = __db_shalloc(infop, sizeof(FNAME), 0, &fnp)) != 0)
+		goto err;
 	memset(fnp, 0, sizeof(FNAME));
 	if (name != NULL) {
 		len = strlen(name) + 1;
-		if ((ret = __db_shalloc(dblp->reginfo.addr,
-		    len, 0, &namep)) != 0) {
-			R_UNLOCK(dbenv, &dblp->reginfo);
-			return (ret);
-		}
-		fnp->name_off = R_OFFSET(&dblp->reginfo, namep);
+		if ((ret = __db_shalloc(infop, len, 0, &namep)) != 0)
+			goto err;
+		fnp->name_off = R_OFFSET(infop, namep);
 		memcpy(namep, name, len);
 	} else
 		fnp->name_off = INVALID_ROFF;
 
-	R_UNLOCK(dbenv, &dblp->reginfo);
+	R_UNLOCK(dbenv, infop);
 
 	/*
 	 * Fill in all the remaining info that we'll need later to register
@@ -141,6 +142,13 @@ __dbreg_setup(dbp, name, create_txnid)
 	dbp->log_filename = fnp;
 
 	return (0);
+
+err:	R_UNLOCK(dbenv, infop);
+	if (ret == ENOMEM)
+		__db_err(dbenv,
+    "Logging region out of memory; you may need to increase its size");
+
+	return (ret);
 }
 
 /*
@@ -155,10 +163,12 @@ __dbreg_teardown(dbp)
 {
 	DB_ENV *dbenv;
 	DB_LOG *dblp;
+	REGINFO *infop;
 	FNAME *fnp;
 
 	dbenv = dbp->dbenv;
 	dblp = dbenv->lg_handle;
+	infop = &dblp->reginfo;
 	fnp = dbp->log_filename;
 
 	/*
@@ -170,12 +180,11 @@ __dbreg_teardown(dbp)
 
 	DB_ASSERT(fnp->id == DB_LOGFILEID_INVALID);
 
-	R_LOCK(dbenv, &dblp->reginfo);
+	R_LOCK(dbenv, infop);
 	if (fnp->name_off != INVALID_ROFF)
-		__db_shalloc_free(dblp->reginfo.addr,
-		    R_ADDR(&dblp->reginfo, fnp->name_off));
-	__db_shalloc_free(dblp->reginfo.addr, fnp);
-	R_UNLOCK(dbenv, &dblp->reginfo);
+		__db_shalloc_free(infop, R_ADDR(infop, fnp->name_off));
+	__db_shalloc_free(infop, fnp);
+	R_UNLOCK(dbenv, infop);
 
 	dbp->log_filename = NULL;
 
@@ -184,7 +193,9 @@ __dbreg_teardown(dbp)
 
 /*
  * __dbreg_new_id --
- *	Assign an unused dbreg id to this database handle.
+ *	Get an unused dbreg id to this database handle.
+ *	Used as a wrapper to acquire the mutex and
+ *	only set the id on success.
  *
  * PUBLIC: int __dbreg_new_id __P((DB *, DB_TXN *));
  */
@@ -193,10 +204,8 @@ __dbreg_new_id(dbp, txn)
 	DB *dbp;
 	DB_TXN *txn;
 {
-	DBT fid_dbt, r_name;
 	DB_ENV *dbenv;
 	DB_LOG *dblp;
-	DB_LSN unused;
 	FNAME *fnp;
 	LOG *lp;
 	int32_t id;
@@ -209,17 +218,49 @@ __dbreg_new_id(dbp, txn)
 
 	/* The fq_mutex protects the FNAME list and id management. */
 	MUTEX_LOCK(dbenv, &lp->fq_mutex);
+	if (fnp->id != DB_LOGFILEID_INVALID) {
+		MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
+		return (0);
+	}
+	if ((ret = __dbreg_get_id(dbp, txn, &id)) == 0)
+		fnp->id = id;
+	MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
+	return (ret);
+}
+
+/*
+ * __dbreg_get_id --
+ *	Assign an unused dbreg id to this database handle.
+ *	Assume the caller holds the fq_mutex locked.  Assume the
+ *	caller will set the fnp->id field with the id we return.
+ *
+ * PUBLIC: int __dbreg_get_id __P((DB *, DB_TXN *, int32_t *));
+ */
+int
+__dbreg_get_id(dbp, txn, idp)
+	DB *dbp;
+	DB_TXN *txn;
+	int32_t *idp;
+{
+	DBT fid_dbt, r_name;
+	DB_ENV *dbenv;
+	DB_LOG *dblp;
+	DB_LSN unused;
+	FNAME *fnp;
+	LOG *lp;
+	int32_t id;
+	int ret;
+
+	dbenv = dbp->dbenv;
+	dblp = dbenv->lg_handle;
+	lp = dblp->reginfo.primary;
+	fnp = dbp->log_filename;
 
 	/*
 	 * It's possible that after deciding we needed to call this function,
 	 * someone else allocated an ID before we grabbed the lock.  Check
 	 * to make sure there was no race and we have something useful to do.
 	 */
-	if (fnp->id != DB_LOGFILEID_INVALID) {
-		MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
-		return (0);
-	}
-
 	/* Get an unused ID from the free list. */
 	if ((ret = __dbreg_pop_id(dbenv, &id)) != 0)
 		goto err;
@@ -228,7 +269,7 @@ __dbreg_new_id(dbp, txn)
 	if (id == DB_LOGFILEID_INVALID)
 		id = lp->fid_max++;
 
-	fnp->id = id;
+	fnp->is_durable = !F_ISSET(dbp, DB_AM_NOT_DURABLE);
 
 	/* Hook the FNAME into the list of open files. */
 	SH_TAILQ_INSERT_HEAD(&lp->fq, fnp, q, __fname);
@@ -247,18 +288,34 @@ __dbreg_new_id(dbp, txn)
 	}
 	fid_dbt.data = dbp->fileid;
 	fid_dbt.size = DB_FILE_ID_LEN;
-	if ((ret = __dbreg_register_log(dbenv, txn, &unused, 0, LOG_OPEN,
-	    r_name.size == 0 ? NULL : &r_name, &fid_dbt, id, fnp->s_type,
-	    fnp->meta_pgno, fnp->create_txnid)) != 0)
+	if ((ret = __dbreg_register_log(dbenv, txn, &unused,
+	    F_ISSET(dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0,
+	    DBREG_OPEN, r_name.size == 0 ? NULL : &r_name, &fid_dbt, id,
+	    fnp->s_type, fnp->meta_pgno, fnp->create_txnid)) != 0)
 		goto err;
+	/*
+	 * Once we log the create_txnid, we need to make sure we never
+	 * log it again (as might happen if this is a replication client
+	 * that later upgrades to a master).
+	 */
+	fnp->create_txnid = TXN_INVALID;
 
 	DB_ASSERT(dbp->type == fnp->s_type);
 	DB_ASSERT(dbp->meta_pgno == fnp->meta_pgno);
 
 	if ((ret = __dbreg_add_dbentry(dbenv, dblp, dbp, id)) != 0)
 		goto err;
-
-err:	MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
+	/*
+	 * If we have a successful call, set the ID.  Otherwise
+	 * we have to revoke it and remove it from all the lists
+	 * it has been added to, and return an invalid id.
+	 */
+err:
+	if (ret != 0 && id != DB_LOGFILEID_INVALID) {
+		(void)__dbreg_revoke_id(dbp, 1, id);
+		id = DB_LOGFILEID_INVALID;
+	}
+	*idp = id;
 	return (ret);
 }
 
@@ -318,7 +375,8 @@ __dbreg_assign_id(dbp, id)
 		} else if (ret != 0)
 			goto err;
 
-		if ((ret = __dbreg_revoke_id(close_dbp, 1)) != 0)
+		if ((ret = __dbreg_revoke_id(close_dbp, 1,
+		    DB_LOGFILEID_INVALID)) != 0)
 			goto err;
 	}
 
@@ -333,16 +391,22 @@ cont:	if ((ret = __dbreg_pluck_id(dbenv, id)) != 0)
 
 	/* Now go ahead and assign the id to our dbp. */
 	fnp->id = id;
+	fnp->is_durable = !F_ISSET(dbp, DB_AM_NOT_DURABLE);
 	SH_TAILQ_INSERT_HEAD(&lp->fq, fnp, q, __fname);
 
+	/*
+	 * If we get an error adding the dbentry, revoke the id.
+	 * We void the return value since we want to retain and
+	 * return the original error in ret anyway.
+	 */
 	if ((ret = __dbreg_add_dbentry(dbenv, dblp, dbp, id)) != 0)
-		goto err;
+		(void)__dbreg_revoke_id(dbp, 1, id);
 
 err:	MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
 
 	/* There's nothing useful that our caller can do if this close fails. */
 	if (close_dbp != NULL)
-		(void)close_dbp->close(close_dbp, DB_NOSYNC);
+		(void)__db_close(close_dbp, NULL, DB_NOSYNC);
 
 	return (ret);
 }
@@ -352,12 +416,13 @@ err:	MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
  *	Take a log id away from a dbp, in preparation for closing it,
  *	but without logging the close.
  *
- * PUBLIC: int __dbreg_revoke_id __P((DB *, int));
+ * PUBLIC: int __dbreg_revoke_id __P((DB *, int, int32_t));
  */
 int
-__dbreg_revoke_id(dbp, have_lock)
+__dbreg_revoke_id(dbp, have_lock, force_id)
 	DB *dbp;
 	int have_lock;
+	int32_t force_id;
 {
 	DB_ENV *dbenv;
 	DB_LOG *dblp;
@@ -372,13 +437,23 @@ __dbreg_revoke_id(dbp, have_lock)
 	fnp = dbp->log_filename;
 
 	/* If we lack an ID, this is a null-op. */
-	if (fnp == NULL || fnp->id == DB_LOGFILEID_INVALID)
+	if (fnp == NULL)
 		return (0);
 
+	/*
+	 * If we have a force_id, we had an error after allocating
+	 * the id, and putting it on the fq list, but before we
+	 * finished setting up fnp.  So, if we have a force_id use it.
+	 */
+	if (force_id != DB_LOGFILEID_INVALID)
+		id = force_id;
+	else if (fnp->id == DB_LOGFILEID_INVALID)
+		return (0);
+	else
+		id = fnp->id;
 	if (!have_lock)
 		MUTEX_LOCK(dbenv, &lp->fq_mutex);
 
-	id = fnp->id;
 	fnp->id = DB_LOGFILEID_INVALID;
 
 	/* Remove the FNAME from the list of open files. */
@@ -400,12 +475,13 @@ __dbreg_revoke_id(dbp, have_lock)
  *	Take a dbreg id away from a dbp that we're closing, and log
  * the unregistry.
  *
- * PUBLIC: int __dbreg_close_id __P((DB *, DB_TXN *));
+ * PUBLIC: int __dbreg_close_id __P((DB *, DB_TXN *, u_int32_t));
  */
 int
-__dbreg_close_id(dbp, txn)
+__dbreg_close_id(dbp, txn, op)
 	DB *dbp;
 	DB_TXN *txn;
+	u_int32_t op;
 {
 	DBT fid_dbt, r_name, *dbtp;
 	DB_ENV *dbenv;
@@ -438,13 +514,133 @@ __dbreg_close_id(dbp, txn)
 	memset(&fid_dbt, 0, sizeof(fid_dbt));
 	fid_dbt.data = fnp->ufid;
 	fid_dbt.size = DB_FILE_ID_LEN;
-	if ((ret = __dbreg_register_log(dbenv, txn,
-	    &r_unused, 0, LOG_CLOSE, dbtp, &fid_dbt, fnp->id,
+	if ((ret = __dbreg_register_log(dbenv, txn, &r_unused,
+	    F_ISSET(dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0,
+	    op, dbtp, &fid_dbt, fnp->id,
 	    fnp->s_type, fnp->meta_pgno, TXN_INVALID)) != 0)
 		goto err;
 
-	ret = __dbreg_revoke_id(dbp, 1);
+	ret = __dbreg_revoke_id(dbp, 1, DB_LOGFILEID_INVALID);
 
 err:	MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
 	return (ret);
 }
+
+/*
+ * __dbreg_push_id and __dbreg_pop_id --
+ *	Dbreg ids from closed files are kept on a stack in shared memory
+ * for recycling.  (We want to reuse them as much as possible because each
+ * process keeps open files in an array by ID.)  Push them to the stack and
+ * pop them from it, managing memory as appropriate.
+ *
+ * The stack is protected by the fq_mutex, and in both functions we assume
+ * that this is already locked.
+ */
+static int
+__dbreg_push_id(dbenv, id)
+	DB_ENV *dbenv;
+	int32_t id;
+{
+	DB_LOG *dblp;
+	LOG *lp;
+	REGINFO *infop;
+	int32_t *stack, *newstack;
+	int ret;
+
+	dblp = dbenv->lg_handle;
+	infop = &dblp->reginfo;
+	lp = infop->primary;
+
+	if (lp->free_fid_stack == INVALID_ROFF) {
+		stack = NULL;
+		DB_ASSERT(lp->free_fids_alloced == 0);
+	} else
+		stack = R_ADDR(infop, lp->free_fid_stack);
+
+	/* Check if we have room on the stack. */
+	if (lp->free_fids_alloced <= lp->free_fids + 1) {
+		R_LOCK(dbenv, infop);
+		if ((ret = __db_shalloc(infop,
+		    (lp->free_fids_alloced + 20) * sizeof(u_int32_t), 0,
+		    &newstack)) != 0) {
+			R_UNLOCK(dbenv, infop);
+			return (ret);
+		}
+
+		if (stack != NULL) {
+			memcpy(newstack, stack,
+			    lp->free_fids_alloced * sizeof(u_int32_t));
+			__db_shalloc_free(infop, stack);
+		}
+		stack = newstack;
+		lp->free_fid_stack = R_OFFSET(infop, stack);
+		lp->free_fids_alloced += 20;
+		R_UNLOCK(dbenv, infop);
+	}
+
+	stack[lp->free_fids++] = id;
+	return (0);
+}
+
+static int
+__dbreg_pop_id(dbenv, id)
+	DB_ENV *dbenv;
+	int32_t *id;
+{
+	DB_LOG *dblp;
+	LOG *lp;
+	int32_t *stack;
+
+	dblp = dbenv->lg_handle;
+	lp = dblp->reginfo.primary;
+
+	/* Do we have anything to pop? */
+	if (lp->free_fid_stack != INVALID_ROFF && lp->free_fids > 0) {
+		stack = R_ADDR(&dblp->reginfo, lp->free_fid_stack);
+		*id = stack[--lp->free_fids];
+	} else
+		*id = DB_LOGFILEID_INVALID;
+
+	return (0);
+}
+
+/*
+ * __dbreg_pluck_id --
+ *	Remove a particular dbreg id from the stack of free ids.  This is
+ * used when we open a file, as in recovery, with a specific ID that might
+ * be on the stack.
+ *
+ * Returns success whether or not the particular id was found, and like
+ * push and pop, assumes that the fq_mutex is locked.
+ */
+static int
+__dbreg_pluck_id(dbenv, id)
+	DB_ENV *dbenv;
+	int32_t id;
+{
+	DB_LOG *dblp;
+	LOG *lp;
+	int32_t *stack;
+	u_int i;
+
+	dblp = dbenv->lg_handle;
+	lp = dblp->reginfo.primary;
+
+	/* Do we have anything to look at? */
+	if (lp->free_fid_stack != INVALID_ROFF) {
+		stack = R_ADDR(&dblp->reginfo, lp->free_fid_stack);
+		for (i = 0; i < lp->free_fids; i++)
+			if (id == stack[i]) {
+				/*
+				 * Found it.  Overwrite it with the top
+				 * id (which may harmlessly be itself),
+				 * and shorten the stack by one.
+				 */
+				stack[i] = stack[lp->free_fids - 1];
+				lp->free_fids--;
+				return (0);
+			}
+	}
+
+	return (0);
+}
diff --git a/storage/bdb/dbreg/dbreg.src b/storage/bdb/dbreg/dbreg.src
index 18429471e8240fa1ef46cd8cd1f0856efdb1cd6f..ff3fc292308ddd6566ee8fc36357fbd77a07d3cd 100644
--- a/storage/bdb/dbreg/dbreg.src
+++ b/storage/bdb/dbreg/dbreg.src
@@ -1,17 +1,15 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: dbreg.src,v 10.22 2002/03/27 04:31:44 bostic Exp $
+ * $Id: dbreg.src,v 10.26 2004/06/17 17:35:17 bostic Exp $
  */
 
 PREFIX	__dbreg
 DBPRIVATE
 
-INCLUDE	#include "db_config.h"
-INCLUDE
 INCLUDE #ifndef NO_SYSTEM_INCLUDES
 INCLUDE #include <sys/types.h>
 INCLUDE
@@ -25,7 +23,6 @@ INCLUDE #include "dbinc/db_page.h"
 INCLUDE #include "dbinc/db_dispatch.h"
 INCLUDE #include "dbinc/db_am.h"
 INCLUDE #include "dbinc/log.h"
-INCLUDE #include "dbinc/rep.h"
 INCLUDE #include "dbinc/txn.h"
 INCLUDE
 
diff --git a/storage/bdb/dbreg/dbreg_rec.c b/storage/bdb/dbreg/dbreg_rec.c
index ba3ba0e06d9f29eef041422bb8e6ebb3563f2965..07b175a1f3ae622e5acf48c3ff758263bb8bab36 100644
--- a/storage/bdb/dbreg/dbreg_rec.c
+++ b/storage/bdb/dbreg/dbreg_rec.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -31,14 +31,12 @@
  * 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.
+ *
+ * $Id: dbreg_rec.c,v 11.133 2004/09/24 00:43:18 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: dbreg_rec.c,v 11.108 2002/08/14 20:04:25 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -47,8 +45,10 @@ static const char revid[] = "$Id: dbreg_rec.c,v 11.108 2002/08/14 20:04:25 bosti
 
 #include "db_int.h"
 #include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
 #include "dbinc/db_am.h"
 #include "dbinc/log.h"
+#include "dbinc/mp.h"
 #include "dbinc/txn.h"
 
 static int __dbreg_open_file __P((DB_ENV *,
@@ -71,6 +71,7 @@ __dbreg_register_recover(dbenv, dbtp, lsnp, op, info)
 	DB *dbp;
 	__dbreg_register_args *argp;
 	int do_close, do_open, do_rem, ret, t_ret;
+	u_int32_t status;
 
 	dblp = dbenv->lg_handle;
 	dbp = NULL;
@@ -83,28 +84,26 @@ __dbreg_register_recover(dbenv, dbtp, lsnp, op, info)
 		goto out;
 
 	switch (argp->opcode) {
-	case LOG_OPEN:
+	case DBREG_OPEN:
 		if ((DB_REDO(op) ||
 		    op == DB_TXN_OPENFILES || op == DB_TXN_POPENFILES))
 			do_open = 1;
 		else
 			do_close = 1;
 		break;
-
-	case LOG_CLOSE:
+	case DBREG_CLOSE:
 		if (DB_UNDO(op))
 			do_open = 1;
 		else
 			do_close = 1;
 		break;
-	case LOG_RCLOSE:
+	case DBREG_RCLOSE:
 		/*
-		 * LOG_RCLOSE was generated by recover because a file
-		 * was left open.  The POPENFILES pass, which is run
-		 * to open files to abort prepared transactions,
-		 * may not include the open for this file so we
-		 * open it here.  Note that a normal CLOSE is
-		 * not legal before the prepared transaction is
+		 * DBREG_RCLOSE was generated by recover because a file was
+		 * left open.  The POPENFILES pass, which is run to open
+		 * files to abort prepared transactions, may not include the
+		 * open for this file so we open it here.  Note that a normal
+		 * CLOSE is not legal before the prepared transaction is
 		 * committed or aborted.
 		 */
 		if (DB_UNDO(op) || op == DB_TXN_POPENFILES)
@@ -112,12 +111,15 @@ __dbreg_register_recover(dbenv, dbtp, lsnp, op, info)
 		else
 			do_close = 1;
 		break;
-
-	case LOG_CHECKPOINT:
+	case DBREG_CHKPNT:
 		if (DB_UNDO(op) ||
 		    op == DB_TXN_OPENFILES || op == DB_TXN_POPENFILES)
 			do_open = 1;
 		break;
+	default:
+		DB_ASSERT(0);
+		ret = EINVAL;
+		break;
 	}
 
 	if (do_open) {
@@ -125,7 +127,7 @@ __dbreg_register_recover(dbenv, dbtp, lsnp, op, info)
 		 * We must open the db even if the meta page is not
 		 * yet written as we may be creating subdatabase.
 		 */
-		if (op == DB_TXN_OPENFILES && argp->opcode != LOG_CHECKPOINT)
+		if (op == DB_TXN_OPENFILES && argp->opcode != DBREG_CHKPNT)
 			F_SET(dblp, DBLOG_FORCE_OPEN);
 
 		/*
@@ -136,6 +138,8 @@ __dbreg_register_recover(dbenv, dbtp, lsnp, op, info)
 		ret = __dbreg_open_file(dbenv,
 		    op == DB_TXN_ABORT || op == DB_TXN_POPENFILES ?
 		    argp->txnid : NULL, argp, info);
+		if (ret == DB_PAGE_NOTFOUND && argp->meta_pgno != PGNO_BASE_MD)
+			ret = ENOENT;
 		if (ret == ENOENT || ret == EINVAL) {
 			/*
 			 * If this is an OPEN while rolling forward, it's
@@ -150,8 +154,17 @@ __dbreg_register_recover(dbenv, dbtp, lsnp, op, info)
 				dblp->dbentry[argp->fileid].deleted = 0;
 				ret =
 				    __dbreg_open_file(dbenv, NULL, argp, info);
+				if (ret == DB_PAGE_NOTFOUND &&
+				     argp->meta_pgno != PGNO_BASE_MD)
+					ret = ENOENT;
 			}
-			ret = 0;
+			/*
+			 * We treat ENOENT as OK since it's possible that
+			 * the file was renamed or deleted.
+			 * All other errors, we return.
+			 */
+			if (ret == ENOENT)
+				ret = 0;
 		}
 		F_CLR(dblp, DBLOG_FORCE_OPEN);
 	}
@@ -174,19 +187,24 @@ __dbreg_register_recover(dbenv, dbtp, lsnp, op, info)
 			 * Typically, closes should match an open which means
 			 * that if this is a close, there should be a valid
 			 * entry in the dbentry table when we get here,
-			 * however there is an exception.  If this is an
+			 * however there are exceptions.  1. If this is an
 			 * OPENFILES pass, then we may have started from
 			 * a log file other than the first, and the
 			 * corresponding open appears in an earlier file.
-			 * We can ignore that case, but all others are errors.
+			 * 2. If we are undoing an open on an abort or
+			 * recovery, it's possible that we failed after
+			 * the log record, but before we actually entered
+			 * a handle here.
+			 * 3. If we aborted an open, then we wrote a non-txnal
+			 * RCLOSE into the log.  During the forward pass, the
+			 * file won't be open, and that's OK.
 			 */
 			dbe = &dblp->dbentry[argp->fileid];
 			if (dbe->dbp == NULL && !dbe->deleted) {
 				/* No valid entry here. */
-				if ((argp->opcode != LOG_CLOSE &&
-				    argp->opcode != LOG_RCLOSE) ||
-				    (op != DB_TXN_OPENFILES &&
-				    op !=DB_TXN_POPENFILES)) {
+				if ((DB_REDO(op) &&
+				    argp->opcode != DBREG_RCLOSE) ||
+				    argp->opcode == DBREG_CHKPNT) {
 					__db_err(dbenv,
 					    "Improper file close at %lu/%lu",
 					    (u_long)lsnp->file,
@@ -199,59 +217,70 @@ __dbreg_register_recover(dbenv, dbtp, lsnp, op, info)
 
 			/* We have either an open entry or a deleted entry. */
 			if ((dbp = dbe->dbp) != NULL) {
-				MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
-				(void)__dbreg_revoke_id(dbp, 0);
-
 				/*
 				 * If we're a replication client, it's
 				 * possible to get here with a dbp that
 				 * the user opened, but which we later
 				 * assigned a fileid to.  Be sure that
 				 * we only close dbps that we opened in
-				 * the recovery code;  they should have
-				 * DB_AM_RECOVER set.
-				 *
-				 * The only exception is if we're aborting
-				 * in a normal environment;  then we might
-				 * get here with a non-AM_RECOVER database.
+				 * the recovery code or that were opened
+				 * inside a currently aborting transaction.
 				 */
-				if (F_ISSET(dbp, DB_AM_RECOVER) ||
-				    op == DB_TXN_ABORT)
-					do_rem = 1;
+				do_rem = F_ISSET(dbp, DB_AM_RECOVER) ||
+				    op == DB_TXN_ABORT;
+				MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+				if (op == DB_TXN_ABORT)
+					(void)__dbreg_close_id(dbp,
+					    NULL, DBREG_RCLOSE);
+				else
+					(void)__dbreg_revoke_id(dbp, 0,
+					    DB_LOGFILEID_INVALID);
 			} else if (dbe->deleted) {
 				MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
 				__dbreg_rem_dbentry(dblp, argp->fileid);
 			}
 		} else
 			MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
-		if (do_rem) {
-			/*
-			 * If we are undoing a create we'd better discard
-			 * any buffers from the memory pool.
-			 */
-			if (dbp != NULL && dbp->mpf != NULL && argp->id != 0) {
-				if ((ret = dbp->mpf->close(dbp->mpf,
-				    DB_MPOOL_DISCARD)) != 0)
+
+		/*
+		 * During recovery, all files are closed.  On an abort, we only
+		 * close the file if we opened it during the abort
+		 * (DB_AM_RECOVER set), otherwise we simply do a __db_refresh.
+		 * For the close case, if remove or rename has closed the file,
+		 * don't request a sync, because a NULL mpf would be a problem.
+		 *
+		 * If we are undoing a create we'd better discard any buffers
+		 * from the memory pool.  We identify creates because the
+		 * argp->id field contains the transaction containing the file
+		 * create; if that id is invalid, we are not creating.
+		 *
+		 * On the backward pass, we need to "undo" opens even if the
+		 * transaction in which they appeared committed, because we have
+		 * already undone the corresponding close.  In that case, the
+		 * id will be valid, but we do not want to discard buffers.
+		 */
+		if (do_rem && dbp != NULL) {
+			if (argp->id != TXN_INVALID) {
+				if ((ret = __db_txnlist_find(dbenv,
+				    info, argp->txnid->txnid, &status))
+				    != DB_NOTFOUND && ret != 0)
 					goto out;
-				dbp->mpf = NULL;
+				if (ret == DB_NOTFOUND || status != TXN_COMMIT)
+					F_SET(dbp, DB_AM_DISCARD);
+				ret = 0;
 			}
 
-			/*
-			 * During recovery, all files are closed.  On an abort,
-			 * we only close the file if we opened it during the
-			 * abort (DB_AM_RECOVER set), otherwise we simply do
-			 * a __db_refresh.  For the close case, if remove or
-			 * rename has closed the file, don't request a sync,
-			 * because the NULL mpf would be a problem.
-			 */
-			if (dbp != NULL) {
-				if (op == DB_TXN_ABORT &&
-				    !F_ISSET(dbp, DB_AM_RECOVER))
-					t_ret =
-					    __db_refresh(dbp, NULL, DB_NOSYNC);
-				else
-					t_ret = dbp->close(dbp, DB_NOSYNC);
-				if (t_ret != 0 && ret == 0)
+			if (op == DB_TXN_ABORT &&
+			    !F_ISSET(dbp, DB_AM_RECOVER)) {
+				if ((t_ret = __db_refresh(dbp,
+				    NULL, DB_NOSYNC, NULL)) != 0 && ret == 0)
+					ret = t_ret;
+			} else {
+				if (op == DB_TXN_APPLY &&
+				    (t_ret = __db_sync(dbp)) != 0 && ret == 0)
+					ret = t_ret;
+				if ((t_ret = __db_close(
+				    dbp, NULL, DB_NOSYNC)) != 0 && ret == 0)
 					ret = t_ret;
 			}
 		}
@@ -277,48 +306,51 @@ __dbreg_open_file(dbenv, txn, argp, info)
 	void *info;
 {
 	DB_ENTRY *dbe;
-	DB_LOG *lp;
+	DB_LOG *dblp;
 	DB *dbp;
-	u_int32_t id;
+	u_int32_t id, status;
+	int ret;
 
-	lp = (DB_LOG *)dbenv->lg_handle;
-	/*
-	 * We never re-open temporary files.  Temp files are only
-	 * useful during aborts in which case the dbp was entered
-	 * when the file was registered.  During recovery, we treat
-	 * temp files as properly deleted files, allowing the open to
-	 * fail and not reporting any errors when recovery fails to
-	 * get a valid dbp from __dbreg_id_to_db.
-	 */
-	if (argp->name.size == 0) {
-		(void)__dbreg_add_dbentry(dbenv, lp, NULL, argp->fileid);
-		return (ENOENT);
-	}
+	dblp = (DB_LOG *)dbenv->lg_handle;
 
 	/*
 	 * When we're opening, we have to check that the name we are opening
 	 * is what we expect.  If it's not, then we close the old file and
 	 * open the new one.
 	 */
-	MUTEX_THREAD_LOCK(dbenv, lp->mutexp);
-	if (argp->fileid < lp->dbentry_cnt)
-		dbe = &lp->dbentry[argp->fileid];
+	MUTEX_THREAD_LOCK(dbenv, dblp->mutexp);
+	if (argp->fileid < dblp->dbentry_cnt)
+		dbe = &dblp->dbentry[argp->fileid];
 	else
 		dbe = NULL;
 
 	if (dbe != NULL) {
 		if (dbe->deleted) {
-			MUTEX_THREAD_UNLOCK(dbenv, lp->mutexp);
+			MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
 			return (ENOENT);
 		}
+
+		/*
+		 * At the end of OPENFILES, we may have a file open.  The
+		 * open was part of a committed transaction, so it doesn't
+		 * get undone.  However, if the fileid was previously used,
+		 * we'll see a close that may need to get undone.  There are
+		 * three ways we can detect this. 1) the meta-pgno in the
+		 * current file does not match that of the open file, 2) the
+		 * file uid of the current file does not match that of the
+		 * previously opened file, 3) the current file is unnamed, in
+		 * which case it should never be opened during recovery.
+		 */
 		if ((dbp = dbe->dbp) != NULL) {
 			if (dbp->meta_pgno != argp->meta_pgno ||
-			    memcmp(dbp->fileid,
-			    argp->uid.data, DB_FILE_ID_LEN) != 0) {
-				MUTEX_THREAD_UNLOCK(dbenv, lp->mutexp);
-				(void)__dbreg_revoke_id(dbp, 0);
+			    argp->name.size == 0 ||
+			    memcmp(dbp->fileid, argp->uid.data,
+			    DB_FILE_ID_LEN) != 0) {
+				MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+				(void)__dbreg_revoke_id(dbp, 0,
+				    DB_LOGFILEID_INVALID);
 				if (F_ISSET(dbp, DB_AM_RECOVER))
-					dbp->close(dbp, DB_NOSYNC);
+					(void)__db_close(dbp, NULL, DB_NOSYNC);
 				goto reopen;
 			}
 
@@ -328,7 +360,7 @@ __dbreg_open_file(dbenv, txn, argp, info)
 			 * here had better be the same dbp.
 			 */
 			DB_ASSERT(dbe->dbp == dbp);
-			MUTEX_THREAD_UNLOCK(dbenv, lp->mutexp);
+			MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
 
 			/*
 			 * This is a successful open.  We need to record that
@@ -336,27 +368,40 @@ __dbreg_open_file(dbenv, txn, argp, info)
 			 * subtransaction that created the file system object.
 			 */
 			if (argp->id != TXN_INVALID &&
-			    __db_txnlist_update(dbenv, info,
-			    argp->id, TXN_EXPECTED, NULL) == TXN_NOTFOUND)
-				(void)__db_txnlist_add(dbenv,
-				    info, argp->id, TXN_EXPECTED, NULL);
+			    (ret = __db_txnlist_update(dbenv, info,
+			    argp->id, TXN_EXPECTED, NULL, &status, 1)) != 0)
+				return (ret);
 			return (0);
 		}
 	}
 
-	MUTEX_THREAD_UNLOCK(dbenv, lp->mutexp);
+	MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+
+reopen:
+	/*
+	 * We never re-open temporary files.  Temp files are only useful during
+	 * aborts in which case the dbp was entered when the file was
+	 * registered. During recovery, we treat temp files as properly deleted
+	 * files, allowing the open to fail and not reporting any errors when
+	 * recovery fails to get a valid dbp from __dbreg_id_to_db.
+	 */
+	if (argp->name.size == 0) {
+		(void)__dbreg_add_dbentry(dbenv, dblp, NULL, argp->fileid);
+		return (ENOENT);
+	}
 
 	/*
 	 * We are about to pass a recovery txn pointer into the main library.
 	 * We need to make sure that any accessed fields are set appropriately.
 	 */
-reopen:	if (txn != NULL) {
+	if (txn != NULL) {
 		id = txn->txnid;
 		memset(txn, 0, sizeof(DB_TXN));
 		txn->txnid = id;
 		txn->mgrp = dbenv->tx_handle;
 	}
 
-	return (__dbreg_do_open(dbenv, txn, lp, argp->uid.data, argp->name.data,
+	return (__dbreg_do_open(dbenv,
+	    txn, dblp, argp->uid.data, argp->name.data,
 	    argp->ftype, argp->fileid, argp->meta_pgno, info, argp->id));
 }
diff --git a/storage/bdb/dbreg/dbreg_stat.c b/storage/bdb/dbreg/dbreg_stat.c
new file mode 100644
index 0000000000000000000000000000000000000000..dd53b77c3d47f44a33eaaf5361131ec7fee15f43
--- /dev/null
+++ b/storage/bdb/dbreg/dbreg_stat.c
@@ -0,0 +1,97 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: dbreg_stat.c,v 11.48 2004/10/15 16:59:41 bostic Exp $
+ */
+
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
+#include "dbinc/log.h"
+#include "dbinc/txn.h"
+
+#ifdef HAVE_STATISTICS
+/*
+ * __dbreg_print_fname --
+ *	Display the contents of an FNAME structure.
+ *
+ * PUBLIC: void __dbreg_print_fname __P((DB_ENV *, FNAME *));
+ */
+void
+__dbreg_print_fname(dbenv, fnp)
+	DB_ENV *dbenv;
+	FNAME *fnp;
+{
+	__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+	__db_msg(dbenv, "DB handle FNAME contents:");
+	STAT_LONG("log ID", fnp->id);
+	STAT_ULONG("Meta pgno", fnp->meta_pgno);
+	__db_print_fileid(dbenv, fnp->ufid, "\tFile ID");
+	STAT_ULONG("create txn", fnp->create_txnid);
+	STAT_LONG("durable", fnp->is_durable);
+}
+
+/*
+ * __dbreg_print_dblist --
+ *	Display the DB_ENV's list of files.
+ *
+ * PUBLIC: void __dbreg_print_dblist __P((DB_ENV *, u_int32_t));
+ */
+void
+__dbreg_print_dblist(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	DB *dbp;
+	DB_LOG *dblp;
+	FNAME *fnp;
+	LOG *lp;
+	int del, first;
+	char *name;
+
+	dblp = dbenv->lg_handle;
+	lp = dblp->reginfo.primary;
+
+	__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+	__db_msg(dbenv, "LOG FNAME list:");
+	__db_print_mutex(dbenv, NULL, &lp->fq_mutex, "File name mutex", flags);
+
+	STAT_LONG("Fid max", lp->fid_max);
+
+	MUTEX_LOCK(dbenv, &lp->fq_mutex);
+	for (first = 1, fnp = SH_TAILQ_FIRST(&lp->fq, __fname);
+	    fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
+		if (first) {
+			first = 0;
+			__db_msg(dbenv,
+			    "ID\tName\tType\tPgno\tTxnid\tDBP-info");
+		}
+		if (fnp->name_off == INVALID_ROFF)
+			name = "";
+		else
+			name = R_ADDR(&dblp->reginfo, fnp->name_off);
+
+		dbp = fnp->id >= dblp->dbentry_cnt ? NULL :
+		    dblp->dbentry[fnp->id].dbp;
+		del = fnp->id >= dblp->dbentry_cnt ? 0 :
+		    dblp->dbentry[fnp->id].deleted;
+		__db_msg(dbenv, "%ld\t%s\t%s\t%lu\t%lx\t%s %d %lx %lx",
+		    (long)fnp->id, name,
+		    __db_dbtype_to_string(fnp->s_type),
+		    (u_long)fnp->meta_pgno, (u_long)fnp->create_txnid,
+		    dbp == NULL ? "No DBP" : "DBP", del, P_TO_ULONG(dbp),
+		    (u_long)(dbp == NULL ? 0 : dbp->flags));
+	}
+	MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
+}
+#endif
diff --git a/storage/bdb/dbreg/dbreg_util.c b/storage/bdb/dbreg/dbreg_util.c
index 0db5c640adb7d6c1877d7e0f59899d60106c27c0..6f1cc9297a55271e73b44c64fe48211fd41eabca 100644
--- a/storage/bdb/dbreg/dbreg_util.c
+++ b/storage/bdb/dbreg/dbreg_util.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: dbreg_util.c,v 11.50 2004/10/15 16:59:41 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: dbreg_util.c,v 11.22 2002/09/10 02:43:10 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #include <string.h>
@@ -51,7 +49,7 @@ __dbreg_add_dbentry(dbenv, dblp, dbp, ndx)
 	 */
 	if (dblp->dbentry_cnt <= ndx) {
 		if ((ret = __os_realloc(dbenv,
-		    (ndx + DB_GROW_SIZE) * sizeof(DB_ENTRY),
+		    (size_t)(ndx + DB_GROW_SIZE) * sizeof(DB_ENTRY),
 		    &dblp->dbentry)) != 0)
 			goto err;
 
@@ -83,19 +81,21 @@ __dbreg_rem_dbentry(dblp, ndx)
 	int32_t ndx;
 {
 	MUTEX_THREAD_LOCK(dblp->dbenv, dblp->mutexp);
-	dblp->dbentry[ndx].dbp = NULL;
-	dblp->dbentry[ndx].deleted = 0;
+	if (dblp->dbentry_cnt > ndx) {
+		dblp->dbentry[ndx].dbp = NULL;
+		dblp->dbentry[ndx].deleted = 0;
+	}
 	MUTEX_THREAD_UNLOCK(dblp->dbenv, dblp->mutexp);
 }
 
 /*
- * __dbreg_open_files --
- *	Put a LOG_CHECKPOINT log record for each open database.
+ * __dbreg_log_files --
+ *	Put a DBREG_CHKPNT/CLOSE log record for each open database.
  *
- * PUBLIC: int __dbreg_open_files __P((DB_ENV *));
+ * PUBLIC: int __dbreg_log_files __P((DB_ENV *));
  */
 int
-__dbreg_open_files(dbenv)
+__dbreg_log_files(dbenv)
 	DB_ENV *dbenv;
 {
 	DB_LOG *dblp;
@@ -114,6 +114,7 @@ __dbreg_open_files(dbenv)
 
 	for (fnp = SH_TAILQ_FIRST(&lp->fq, __fname);
 	    fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
+
 		if (fnp->name_off == INVALID_ROFF)
 			dbtp = NULL;
 		else {
@@ -126,18 +127,17 @@ __dbreg_open_files(dbenv)
 		fid_dbt.data = fnp->ufid;
 		fid_dbt.size = DB_FILE_ID_LEN;
 		/*
-		 * Output LOG_CHECKPOINT records which will be
-		 * processed during the OPENFILES pass of recovery.
-		 * At the end of recovery we want to output the
-		 * files that were open so that a future recovery
-		 * run will have the correct files open during
-		 * a backward pass.  For this we output LOG_RCLOSE
-		 * records so that the files will be closed on
-		 * the forward pass.
+		 * Output DBREG_CHKPNT records which will be processed during
+		 * the OPENFILES pass of recovery.  At the end of recovery we
+		 * want to output the files that were open so a future recovery
+		 * run will have the correct files open during a backward pass.
+		 * For this we output DBREG_RCLOSE records so the files will be
+		 * closed on the forward pass.
 		 */
 		if ((ret = __dbreg_register_log(dbenv,
-		    NULL, &r_unused, 0,
-		    F_ISSET(dblp, DBLOG_RECOVER) ? LOG_RCLOSE : LOG_CHECKPOINT,
+		    NULL, &r_unused,
+		    fnp->is_durable ? 0 : DB_LOG_NOT_DURABLE,
+		    F_ISSET(dblp, DBLOG_RECOVER) ? DBREG_RCLOSE : DBREG_CHKPNT,
 		    dbtp, &fid_dbt, fnp->id, fnp->s_type, fnp->meta_pgno,
 		    TXN_INVALID)) != 0)
 			break;
@@ -150,7 +150,8 @@ __dbreg_open_files(dbenv)
 
 /*
  * __dbreg_close_files --
- *	Close files that were opened by the recovery daemon.  We sync the
+ *	Remove the id's of open files and actually close those
+ *	files that were opened by the recovery daemon.  We sync the
  *	file, unless its mpf pointer has been NULLed by a db_remove or
  *	db_rename.  We may not have flushed the log_register record that
  *	closes the file.
@@ -174,13 +175,19 @@ __dbreg_close_files(dbenv)
 	ret = 0;
 	MUTEX_THREAD_LOCK(dbenv, dblp->mutexp);
 	for (i = 0; i < dblp->dbentry_cnt; i++) {
-		/* We only want to close dbps that recovery opened. */
-		if ((dbp = dblp->dbentry[i].dbp) != NULL &&
-		    F_ISSET(dbp, DB_AM_RECOVER)) {
+		/*
+		 * We only want to close dbps that recovery opened.  Any
+		 * dbps that weren't opened by recovery but show up here
+		 * are about to be unconditionally removed from the table.
+		 * Before doing so, we need to revoke their log fileids
+		 * so that we don't end up leaving around FNAME entries
+		 * for dbps that shouldn't have them.
+		 */
+		if ((dbp = dblp->dbentry[i].dbp) != NULL) {
 			/*
-			 * It's unsafe to call DB->close while holding the
-			 * thread lock, because we'll call __dbreg_rem_dbentry
-			 * and grab it again.
+			 * It's unsafe to call DB->close or revoke_id
+			 * while holding the thread lock, because
+			 * we'll call __dbreg_rem_dbentry and grab it again.
 			 *
 			 * Just drop it.  Since dbreg ids go monotonically
 			 * upward, concurrent opens should be safe, and the
@@ -189,11 +196,17 @@ __dbreg_close_files(dbenv)
 			 * making all outstanding dbps invalid.
 			 */
 			MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
-			if ((t_ret = dbp->close(dbp,
-			    dbp->mpf == NULL ? DB_NOSYNC : 0)) != 0 && ret == 0)
+			if (F_ISSET(dbp, DB_AM_RECOVER))
+				t_ret = __db_close(dbp,
+				     NULL, dbp->mpf == NULL ? DB_NOSYNC : 0);
+			else
+				t_ret = __dbreg_revoke_id(
+				     dbp, 0, DB_LOGFILEID_INVALID);
+			if (ret == 0)
 				ret = t_ret;
 			MUTEX_THREAD_LOCK(dbenv, dblp->mutexp);
 		}
+
 		dblp->dbentry[i].deleted = 0;
 		dblp->dbentry[i].dbp = NULL;
 	}
@@ -201,40 +214,6 @@ __dbreg_close_files(dbenv)
 	return (ret);
 }
 
-/*
- * __dbreg_nofiles --
- *	Check that there are no open files in the process local table.
- *	Returns 0 if there are no files and EINVAL if there are any.
- *
- * PUBLIC: int __dbreg_nofiles __P((DB_ENV *));
- */
-int
-__dbreg_nofiles(dbenv)
-	DB_ENV *dbenv;
-{
-	DB *dbp;
-	DB_LOG *dblp;
-	int ret;
-	int32_t i;
-
-	/* If we haven't initialized logging, we have nothing to do. */
-	if (!LOGGING_ON(dbenv))
-		return (0);
-
-	dblp = dbenv->lg_handle;
-	ret = 0;
-	MUTEX_THREAD_LOCK(dbenv, dblp->mutexp);
-	for (i = 0; i < dblp->dbentry_cnt; i++) {
-		if ((dbp = dblp->dbentry[i].dbp) != NULL &&
-		    !F_ISSET(dbp, DB_AM_RECOVER)) {
-			ret = EINVAL;
-			break;
-		}
-	}
-	MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
-	return (ret);
-}
-
 /*
  * __dbreg_id_to_db --
  *	Return the DB corresponding to the specified dbreg id.
@@ -365,9 +344,9 @@ err:	MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
  * PUBLIC: int __dbreg_id_to_fname __P((DB_LOG *, int32_t, int, FNAME **));
  */
 int
-__dbreg_id_to_fname(dblp, lid, have_lock, fnamep)
+__dbreg_id_to_fname(dblp, id, have_lock, fnamep)
 	DB_LOG *dblp;
-	int32_t lid;
+	int32_t id;
 	int have_lock;
 	FNAME **fnamep;
 {
@@ -385,7 +364,7 @@ __dbreg_id_to_fname(dblp, lid, have_lock, fnamep)
 		MUTEX_LOCK(dbenv, &lp->fq_mutex);
 	for (fnp = SH_TAILQ_FIRST(&lp->fq, __fname);
 	    fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
-		if (fnp->id == lid) {
+		if (fnp->id == id) {
 			*fnamep = fnp;
 			ret = 0;
 			break;
@@ -452,12 +431,12 @@ __dbreg_get_name(dbenv, fid, namep)
 	char **namep;
 {
 	DB_LOG *dblp;
-	FNAME *fname;
+	FNAME *fnp;
 
 	dblp = dbenv->lg_handle;
 
-	if (dblp != NULL && __dbreg_fid_to_fname(dblp, fid, 0, &fname) == 0) {
-		*namep = R_ADDR(&dblp->reginfo, fname->name_off);
+	if (dblp != NULL && __dbreg_fid_to_fname(dblp, fid, 0, &fnp) == 0) {
+		*namep = R_ADDR(&dblp->reginfo, fnp->name_off);
 		return (0);
 	}
 
@@ -486,8 +465,8 @@ __dbreg_do_open(dbenv,
 	u_int32_t id;
 {
 	DB *dbp;
+	u_int32_t cstat, ret_stat;
 	int ret;
-	u_int32_t cstat;
 
 	if ((ret = db_create(&dbp, lp->dbenv, 0)) != 0)
 		return (ret);
@@ -511,9 +490,8 @@ __dbreg_do_open(dbenv,
 		memcpy(dbp->fileid, uid, DB_FILE_ID_LEN);
 		dbp->meta_pgno = meta_pgno;
 	}
-	dbp->type = ftype;
-	if ((ret = __db_dbopen(dbp, txn, name, NULL,
-	    DB_ODDFILESIZE, __db_omode("rw----"), meta_pgno)) == 0) {
+	if ((ret = __db_open(dbp, txn, name, NULL,
+	    ftype, DB_ODDFILESIZE, __db_omode("rw----"), meta_pgno)) == 0) {
 
 		/*
 		 * Verify that we are opening the same file that we were
@@ -536,29 +514,24 @@ __dbreg_do_open(dbenv,
 		 * know how to handle the subtransaction that created
 		 * the file system object.
 		 */
-		if (id != TXN_INVALID) {
-			if ((ret = __db_txnlist_update(dbenv,
-			    info, id, cstat, NULL)) == TXN_NOTFOUND)
-				ret = __db_txnlist_add(dbenv,
-				    info, id, cstat, NULL);
-			else if (ret > 0)
-				ret = 0;
-		}
+		if (id != TXN_INVALID)
+			ret = __db_txnlist_update(dbenv,
+			    info, id, cstat, NULL, &ret_stat, 1);
+
 err:		if (cstat == TXN_IGNORE)
 			goto not_right;
 		return (ret);
-	} else {
+	} else if (ret == ENOENT) {
 		/* Record that the open failed in the txnlist. */
-		if (id != TXN_INVALID && (ret = __db_txnlist_update(dbenv,
-		    info, id, TXN_UNEXPECTED, NULL)) == TXN_NOTFOUND)
-			ret = __db_txnlist_add(dbenv,
-			    info, id, TXN_UNEXPECTED, NULL);
+		if (id != TXN_INVALID)
+			ret = __db_txnlist_update(dbenv, info,
+			    id, TXN_UNEXPECTED, NULL, &ret_stat, 1);
 	}
 not_right:
-	(void)dbp->close(dbp, 0);
+	(void)__db_close(dbp, NULL, DB_NOSYNC);
 	/* Add this file as deleted. */
 	(void)__dbreg_add_dbentry(dbenv, lp, NULL, ndx);
-	return (ENOENT);
+	return (ret);
 }
 
 static int
@@ -573,15 +546,14 @@ __dbreg_check_master(dbenv, uid, name)
 	ret = 0;
 	if ((ret = db_create(&dbp, dbenv, 0)) != 0)
 		return (ret);
-	dbp->type = DB_BTREE;
 	F_SET(dbp, DB_AM_RECOVER);
-	ret = __db_dbopen(dbp,
-	    NULL, name, NULL, 0, __db_omode("rw----"), PGNO_BASE_MD);
+	ret = __db_open(dbp,
+	    NULL, name, NULL, DB_BTREE, 0, __db_omode("rw----"), PGNO_BASE_MD);
 
 	if (ret == 0 && memcmp(uid, dbp->fileid, DB_FILE_ID_LEN) != 0)
 		ret = EINVAL;
 
-	(void)dbp->close(dbp, 0);
+	(void)__db_close(dbp, NULL, 0);
 	return (ret);
 }
 
@@ -604,194 +576,54 @@ __dbreg_lazy_id(dbp)
 	DB *dbp;
 {
 	DB_ENV *dbenv;
+	DB_LOG *dblp;
 	DB_TXN *txn;
+	FNAME *fnp;
+	LOG *lp;
+	int32_t id;
 	int ret;
 
 	dbenv = dbp->dbenv;
 
-	DB_ASSERT(F_ISSET(dbenv, DB_ENV_REP_MASTER));
-
-	if ((ret = dbenv->txn_begin(dbenv, NULL, &txn, 0)) != 0)
-		return (ret);
-
-	if ((ret = __dbreg_new_id(dbp, txn)) != 0) {
-		(void)txn->abort(txn);
-		return (ret);
-	}
-
-	return (txn->commit(txn, DB_TXN_NOSYNC));
-}
-
-/*
- * __dbreg_push_id and __dbreg_pop_id --
- *	Dbreg ids from closed files are kept on a stack in shared memory
- * for recycling.  (We want to reuse them as much as possible because each
- * process keeps open files in an array by ID.)  Push them to the stack and
- * pop them from it, managing memory as appropriate.
- *
- * The stack is protected by the fq_mutex, and in both functions we assume
- * that this is already locked.
- *
- * PUBLIC: int __dbreg_push_id __P((DB_ENV *, int32_t));
- * PUBLIC: int __dbreg_pop_id __P((DB_ENV *, int32_t *));
- */
-int
-__dbreg_push_id(dbenv, id)
-	DB_ENV *dbenv;
-	int32_t id;
-{
-	DB_LOG *dblp;
-	LOG *lp;
-	int32_t *stack, *newstack;
-	int ret;
+	DB_ASSERT(IS_REP_MASTER(dbenv));
 
+	dbenv = dbp->dbenv;
 	dblp = dbenv->lg_handle;
 	lp = dblp->reginfo.primary;
+	fnp = dbp->log_filename;
 
-	if (lp->free_fid_stack != INVALID_ROFF)
-		stack = R_ADDR(&dblp->reginfo, lp->free_fid_stack);
-	else
-		stack = NULL;
-
-	/* Check if we have room on the stack. */
-	if (lp->free_fids_alloced <= lp->free_fids + 1) {
-		R_LOCK(dbenv, &dblp->reginfo);
-		if ((ret = __db_shalloc(dblp->reginfo.addr,
-		    (lp->free_fids_alloced + 20) * sizeof(u_int32_t), 0,
-		    &newstack)) != 0) {
-			R_UNLOCK(dbenv, &dblp->reginfo);
-			return (ret);
-		}
-
-		memcpy(newstack, stack,
-		    lp->free_fids_alloced * sizeof(u_int32_t));
-		lp->free_fid_stack = R_OFFSET(&dblp->reginfo, newstack);
-		lp->free_fids_alloced += 20;
-
-		if (stack != NULL)
-			__db_shalloc_free(dblp->reginfo.addr, stack);
-
-		stack = newstack;
-		R_UNLOCK(dbenv, &dblp->reginfo);
+	/* The fq_mutex protects the FNAME list and id management. */
+	MUTEX_LOCK(dbenv, &lp->fq_mutex);
+	if (fnp->id != DB_LOGFILEID_INVALID) {
+		MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
+		return (0);
 	}
+	id = DB_LOGFILEID_INVALID;
+	if ((ret = __txn_begin(dbenv, NULL, &txn, 0)) != 0)
+		goto err;
 
-	DB_ASSERT(stack != NULL);
-	stack[lp->free_fids++] = id;
-	return (0);
-}
-
-int
-__dbreg_pop_id(dbenv, id)
-	DB_ENV *dbenv;
-	int32_t *id;
-{
-	DB_LOG *dblp;
-	LOG *lp;
-	int32_t *stack;
-
-	dblp = dbenv->lg_handle;
-	lp = dblp->reginfo.primary;
-
-	/* Do we have anything to pop? */
-	if (lp->free_fid_stack != INVALID_ROFF && lp->free_fids > 0) {
-		stack = R_ADDR(&dblp->reginfo, lp->free_fid_stack);
-		*id = stack[--lp->free_fids];
-	} else
-		*id = DB_LOGFILEID_INVALID;
-
-	return (0);
-}
-
-/*
- * __dbreg_pluck_id --
- *	Remove a particular dbreg id from the stack of free ids.  This is
- * used when we open a file, as in recovery, with a specific ID that might
- * be on the stack.
- *
- * Returns success whether or not the particular id was found, and like
- * push and pop, assumes that the fq_mutex is locked.
- *
- * PUBLIC: int __dbreg_pluck_id __P((DB_ENV *, int32_t));
- */
-int
-__dbreg_pluck_id(dbenv, id)
-	DB_ENV *dbenv;
-	int32_t id;
-{
-	DB_LOG *dblp;
-	LOG *lp;
-	int32_t *stack;
-	int i;
-
-	dblp = dbenv->lg_handle;
-	lp = dblp->reginfo.primary;
-
-	/* Do we have anything to look at? */
-	if (lp->free_fid_stack != INVALID_ROFF) {
-		stack = R_ADDR(&dblp->reginfo, lp->free_fid_stack);
-		for (i = 0; i < lp->free_fids; i++)
-			if (id == stack[i]) {
-				/*
-				 * Found it.  Overwrite it with the top
-				 * id (which may harmlessly be itself),
-				 * and shorten the stack by one.
-				 */
-				stack[i] = stack[lp->free_fids - 1];
-				lp->free_fids--;
-				return (0);
-			}
+	if ((ret = __dbreg_get_id(dbp, txn, &id)) != 0) {
+		(void)__txn_abort(txn);
+		goto err;
 	}
 
-	return (0);
-}
-
-#ifdef DEBUG
-/*
- * __dbreg_print_dblist --
- *	Display the list of files.
- *
- * PUBLIC: void __dbreg_print_dblist __P((DB_ENV *));
- */
-void
-__dbreg_print_dblist(dbenv)
-	DB_ENV *dbenv;
-{
-	DB *dbp;
-	DB_LOG *dblp;
-	FNAME *fnp;
-	LOG *lp;
-	int del, first;
-	char *name;
-
-	dblp = dbenv->lg_handle;
-	lp = dblp->reginfo.primary;
-
-	MUTEX_LOCK(dbenv, &lp->fq_mutex);
-
-	for (first = 1, fnp = SH_TAILQ_FIRST(&lp->fq, __fname);
-	    fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
-		if (first) {
-			first = 0;
-			__db_err(dbenv,
-			    "ID\t\t\tName\tType\tPgno\tTxnid\tDBP-info");
-		}
-		if (fnp->name_off == INVALID_ROFF)
-			name = "";
-		else
-			name = R_ADDR(&dblp->reginfo, fnp->name_off);
-
-		dbp = fnp->id >= dblp->dbentry_cnt ? NULL :
-		    dblp->dbentry[fnp->id].dbp;
-		del = fnp->id >= dblp->dbentry_cnt ? 0 :
-		    dblp->dbentry[fnp->id].deleted;
-		__db_err(dbenv, "%ld\t%s\t\t\t%s\t%lu\t%lx\t%s %d %lx %lx",
-		    (long)fnp->id, name,
-		    __db_dbtype_to_string(fnp->s_type),
-		    (u_long)fnp->meta_pgno, (u_long)fnp->create_txnid,
-		    dbp == NULL ? "No DBP" : "DBP", del, P_TO_ULONG(dbp),
-		    dbp == NULL ? 0 : dbp->flags);
-	}
+	if ((ret = __txn_commit(txn, DB_TXN_NOSYNC)) != 0)
+		goto err;
 
+	/*
+	 * All DB related logging routines check the id value *without*
+	 * holding the fq_mutex to know whether we need to call
+	 * dbreg_lazy_id to begin with.  We must set the ID after a
+	 * *successful* commit so that there is no possibility of a second
+	 * modification call finding a valid ID in the dbp before the
+	 * dbreg_register and commit records are in the log.
+	 * If there was an error, then we call __dbreg_revoke_id to
+	 * remove the entry from the lists.
+	 */
+	fnp->id = id;
+err:
+	if (ret != 0 && id != DB_LOGFILEID_INVALID)
+		(void)__dbreg_revoke_id(dbp, 1, id);
 	MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
+	return (ret);
 }
-#endif
diff --git a/storage/bdb/dist/Makefile.in b/storage/bdb/dist/Makefile.in
index a7cc0e11f34bd2d574a266709ab266bb89f49b70..cf484b6bf99fe8b9420f893764777f456f19ff60 100644
--- a/storage/bdb/dist/Makefile.in
+++ b/storage/bdb/dist/Makefile.in
@@ -1,4 +1,4 @@
-# $Id: Makefile.in,v 11.175 2002/08/29 14:22:20 margo Exp $
+# $Id: Makefile.in,v 11.264 2004/11/01 21:55:33 mark Exp $
 
 srcdir=	@srcdir@/..
 builddir=.
@@ -30,7 +30,6 @@ ln=	@db_cv_path_ln@
 mkdir=	@db_cv_path_mkdir@
 ranlib=	@db_cv_path_ranlib@
 rm=	@db_cv_path_rm@
-rpm=	@db_cv_path_rpm@
 strip=	@db_cv_path_strip@
 
 ##################################################
@@ -44,28 +43,30 @@ LIBTOOL=	@LIBTOOL@
 POSTLINK=	@POSTLINK@
 SOLINK=		@MAKEFILE_SOLINK@
 SOFLAGS=	@SOFLAGS@
-SOMAJOR=	@DB_VERSION_MAJOR@
-SOVERSION=	@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@
+LIBMAJOR=	@DB_VERSION_MAJOR@
+LIBVERSION=	@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@
+
+CPPFLAGS=	-I$(builddir) -I$(srcdir) @CPPFLAGS@
 
 ##################################################
 # C API.
 ##################################################
-CPPFLAGS=	-I$(builddir) -I$(srcdir) -I$(srcdir)/dbinc @CPPFLAGS@
 CFLAGS=	 	-c $(CPPFLAGS) @CFLAGS@
 CC=		@MAKEFILE_CC@
-CCLINK=		@MAKEFILE_CCLINK@
+CCLINK=		@MAKEFILE_CCLINK@ @CFLAGS@
 
 LDFLAGS=	@LDFLAGS@
 LIBS=		@LIBS@
+TEST_LIBS=	@TEST_LIBS@
 LIBSO_LIBS=	@LIBSO_LIBS@
 
-libdb=		libdb.a
-libso_base=	libdb
-libso=		$(libso_base)-$(SOVERSION).@SOSUFFIX@
-libso_static=	$(libso_base)-$(SOVERSION).a
-libso_target=	$(libso_base)-$(SOVERSION).la
-libso_default=	$(libso_base).@SOSUFFIX@
-libso_major=	$(libso_base)-$(SOMAJOR).@SOSUFFIX@
+libdb_base=	libdb
+libdb=		$(libdb_base).a
+libdb_version=	$(libdb_base)-$(LIBVERSION).a
+libso=		$(libdb_base)-$(LIBVERSION)@SOSUFFIX@
+libso_target=	$(libdb_base)-$(LIBVERSION).la
+libso_default=	$(libdb_base)@SOSUFFIX@
+libso_major=	$(libdb_base)-$(LIBMAJOR)@SOSUFFIX@
 
 ##################################################
 # C++ API.
@@ -74,17 +75,17 @@ libso_major=	$(libso_base)-$(SOMAJOR).@SOSUFFIX@
 ##################################################
 CXXFLAGS=	-c $(CPPFLAGS) @CXXFLAGS@
 CXX=		@MAKEFILE_CXX@
-CXXLINK=	@MAKEFILE_CXXLINK@
-XSOLINK=	@MAKEFILE_XSOLINK@
+CXXLINK=	@MAKEFILE_CXXLINK@ @CXXFLAGS@
+XSOLINK=	@MAKEFILE_XSOLINK@ @CXXFLAGS@
 LIBXSO_LIBS=	@LIBXSO_LIBS@
 
-libcxx=		libdb_cxx.a
-libxso_base=	libdb_cxx
-libxso=		$(libxso_base)-$(SOVERSION).@SOSUFFIX@
-libxso_static=	$(libxso_base)-$(SOVERSION).a
-libxso_target=	$(libxso_base)-$(SOVERSION).la
-libxso_default=	$(libxso_base).@SOSUFFIX@
-libxso_major=	$(libxso_base)-$(SOMAJOR).@SOSUFFIX@
+libcxx_base=	libdb_cxx
+libcxx=		$(libcxx_base).a
+libcxx_version=	$(libcxx_base)-$(LIBVERSION).a
+libxso=		$(libcxx_base)-$(LIBVERSION)@SOSUFFIX@
+libxso_target=	$(libcxx_base)-$(LIBVERSION).la
+libxso_default=	$(libcxx_base)@SOSUFFIX@
+libxso_major=	$(libcxx_base)-$(LIBMAJOR)@SOSUFFIX@
 
 ##################################################
 # Java API.
@@ -98,25 +99,26 @@ JAR=		@JAR@
 JAVAC=		env CLASSPATH="$(CLASSPATH)" @JAVAC@
 JAVACFLAGS=	@JAVACFLAGS@
 JAVA_CLASSTOP=	./classes
-JAVA_RPCCLASSES=./classes.rpc
-JAVA_SRCDIR=	$(srcdir)/java/src
+JAVA_RPCCLASSTOP=./classes.rpc
+JAVA_EXCLASSTOP=./classes.ex
 JAVA_DBREL=	com/sleepycat/db
 JAVA_EXREL=	com/sleepycat/examples
 JAVA_RPCREL=	com/sleepycat/db/rpcserver
-JAVA_DBDIR=	$(JAVA_SRCDIR)/$(JAVA_DBREL)
-JAVA_EXDIR=	$(JAVA_SRCDIR)/$(JAVA_EXREL)
+JAVA_SRCDIR=	$(srcdir)/java/src
+JAVA_EXDIR=	$(srcdir)/examples_java/src/com/sleepycat/examples
 JAVA_RPCDIR=	$(srcdir)/rpc_server/java
+JAVA_SLEEPYCAT=	$(srcdir)/java/src/com/sleepycat
 
 libj_jarfile=	db.jar
 libj_exjarfile=	dbexamples.jar
 rpc_jarfile=	dbsvc.jar
 libjso_base=	libdb_java
-libjso=		$(libjso_base)-$(SOVERSION).@JMODSUFFIX@
-libjso_static=	$(libjso_base)-$(SOVERSION).a
-libjso_target=	$(libjso_base)-$(SOVERSION).la
-libjso_default=	$(libjso_base).@JMODSUFFIX@
-libjso_major=	$(libjso_base)-$(SOMAJOR).@JMODSUFFIX@
-libjso_g=	$(libjso_base)-$(SOVERSION)_g.@JMODSUFFIX@
+libjso=		$(libjso_base)-$(LIBVERSION)@JMODSUFFIX@
+libjso_static=	$(libjso_base)-$(LIBVERSION).a
+libjso_target=	$(libjso_base)-$(LIBVERSION).la
+libjso_default=	$(libjso_base)@JMODSUFFIX@
+libjso_major=	$(libjso_base)-$(LIBMAJOR)@JMODSUFFIX@
+libjso_g=	$(libjso_base)-$(LIBVERSION)_g@JMODSUFFIX@
 
 ##################################################
 # TCL API.
@@ -126,11 +128,11 @@ libjso_g=	$(libjso_base)-$(SOVERSION)_g.@JMODSUFFIX@
 TCFLAGS=	@TCFLAGS@
 LIBTSO_LIBS=	@LIBTSO_LIBS@
 libtso_base=	libdb_tcl
-libtso=		$(libtso_base)-$(SOVERSION).@MODSUFFIX@
-libtso_static=	$(libtso_base)-$(SOVERSION).a
-libtso_target=	$(libtso_base)-$(SOVERSION).la
-libtso_default=	$(libtso_base).@MODSUFFIX@
-libtso_major=	$(libtso_base)-$(SOMAJOR).@MODSUFFIX@
+libtso=		$(libtso_base)-$(LIBVERSION)@MODSUFFIX@
+libtso_static=	$(libtso_base)-$(LIBVERSION).a
+libtso_target=	$(libtso_base)-$(LIBVERSION).la
+libtso_default=	$(libtso_base)@MODSUFFIX@
+libtso_major=	$(libtso_base)-$(LIBMAJOR)@MODSUFFIX@
 
 ##################################################
 # db_dump185 UTILITY
@@ -152,90 +154,321 @@ DB185LIB=
 ##################################################
 # Object and utility lists.
 ##################################################
-C_OBJS= @ADDITIONAL_OBJS@ @LTLIBOBJS@ @RPC_CLIENT_OBJS@ \
+BTREE_OBJS=\
 	bt_compare@o@ bt_conv@o@ bt_curadj@o@ bt_cursor@o@ bt_delete@o@ \
 	bt_method@o@ bt_open@o@ bt_put@o@ bt_rec@o@ bt_reclaim@o@ \
 	bt_recno@o@ bt_rsearch@o@ bt_search@o@ bt_split@o@ bt_stat@o@ \
-	bt_upgrade@o@ bt_verify@o@ btree_auto@o@ crdel_auto@o@ \
-	crdel_rec@o@ db@o@ db_am@o@ db_auto@o@ db_byteorder@o@ db_cam@o@ \
-	db_conv@o@ db_dispatch@o@ db_dup@o@ db_err@o@ db_getlong@o@ \
-	db_idspace@o@ db_iface@o@ db_join@o@ db_log2@o@ db_meta@o@ \
-	db_method@o@ db_open@o@ db_overflow@o@ db_pr@o@ db_rec@o@ \
-	db_reclaim@o@ db_rename@o@ db_remove@o@ db_ret@o@ db_salloc@o@ \
-	db_shash@o@ db_truncate@o@ db_upg@o@ db_upg_opd@o@ db_vrfy@o@ \
-	db_vrfyutil@o@ dbm@o@ dbreg@o@ dbreg_auto@o@ dbreg_rec@o@ \
-	dbreg_util@o@ env_file@o@ env_method@o@ env_open@o@ env_recover@o@ \
-	env_region@o@ fileops_auto@o@ fop_basic@o@ fop_rec@o@ \
-	fop_util@o@ hash@o@ hash_auto@o@ hash_conv@o@ hash_dup@o@ \
-	hash_func@o@ hash_meta@o@ hash_method@o@ hash_open@o@ \
-	hash_page@o@ hash_rec@o@ hash_reclaim@o@ hash_stat@o@ \
-	hash_upgrade@o@ hash_verify@o@ hmac@o@ hsearch@o@ lock@o@ \
-	lock_deadlock@o@ lock_method@o@ lock_region@o@ lock_stat@o@ \
-	lock_util@o@ log@o@ log_archive@o@ log_compare@o@ log_get@o@ \
-	log_method@o@ log_put@o@ mp_alloc@o@ mp_bh@o@ mp_fget@o@ \
-	mp_fopen@o@ mp_fput@o@ mp_fset@o@ mp_method@o@ mp_region@o@ \
-	mp_register@o@ mp_stat@o@ mp_sync@o@ mp_trickle@o@ mutex@o@ \
-	os_abs@o@ os_alloc@o@ os_clock@o@ os_config@o@ os_dir@o@ \
-	os_errno@o@ os_fid@o@ os_fsync@o@ os_handle@o@ os_id@o@ \
-	os_map@o@ os_method@o@ os_oflags@o@ os_open@o@ os_region@o@ \
-	os_rename@o@ os_root@o@ os_rpath@o@ os_rw@o@ os_seek@o@ \
-	os_sleep@o@ os_spin@o@ os_stat@o@ os_tmpdir@o@ os_unlink@o@ \
+	bt_upgrade@o@ btree_auto@o@
+BTREE_VRFY_OBJS=\
+	db_ovfl_vrfy@o@ db_vrfy@o@ db_vrfyutil@o@ bt_verify@o@
+HASH_OBJS=\
+	hash@o@ hash_auto@o@ hash_conv@o@ hash_dup@o@ hash_meta@o@ \
+	hash_method@o@ hash_open@o@ hash_page@o@ hash_rec@o@ \
+	hash_reclaim@o@ hash_stat@o@ hash_upgrade@o@
+HASH_VRFY_OBJS=\
+	hash_verify@o@
+QUEUE_OBJS=\
 	qam@o@ qam_auto@o@ qam_conv@o@ qam_files@o@ qam_method@o@ \
-	qam_open@o@ qam_rec@o@ qam_stat@o@ qam_upgrade@o@ qam_verify@o@ \
-	rep_method@o@ rep_record@o@ rep_region@o@ rep_util@o@ sha1@o@ \
-	txn@o@ txn_auto@o@ txn_method@o@ txn_rec@o@ txn_recover@o@ \
-	txn_region@o@ txn_stat@o@ txn_util@o@ xa@o@ xa_db@o@ xa_map@o@
+	qam_open@o@ qam_rec@o@ qam_stat@o@ qam_upgrade@o@
+QUEUE_VRFY_OBJS=\
+	qam_verify@o@
+REP_OBJS=\
+	rep_auto@o@ rep_backup@o@ rep_method@o@ rep_record@o@ rep_region@o@ \
+	rep_stat@o@ rep_util@o@
+PRINT_OBJS=\
+	btree_autop@o@ crdel_autop@o@ db_autop@o@ dbreg_autop@o@ \
+	fileops_autop@o@ hash_autop@o@ qam_autop@o@ rep_autop@o@ \
+	txn_autop@o@
+
+C_OBJS= @ADDITIONAL_OBJS@ @REPLACEMENT_OBJS@ @CRYPTO_OBJS@ @RPC_CLIENT_OBJS@ \
+	crdel_auto@o@ crdel_rec@o@ db@o@ db_am@o@ db_auto@o@ \
+	db_byteorder@o@ db_cam@o@ db_conv@o@ db_dispatch@o@ db_dup@o@ \
+	db_err@o@ db_getlong@o@ db_idspace@o@ db_iface@o@ db_join@o@ \
+	db_log2@o@ db_meta@o@ db_method@o@ db_open@o@ db_overflow@o@ \
+	db_pr@o@ db_rec@o@ db_reclaim@o@ db_rename@o@ db_remove@o@ \
+	db_ret@o@ db_salloc@o@ db_setid@o@ db_setlsn@o@ db_shash@o@ \
+	db_stati@o@ db_truncate@o@ db_upg@o@ db_upg_opd@o@ dbm@o@ \
+	dbreg@o@ dbreg_auto@o@ dbreg_rec@o@ dbreg_stat@o@ dbreg_util@o@ \
+	env_file@o@ env_method@o@ env_open@o@ env_recover@o@ \
+	env_region@o@ env_stat@o@ fileops_auto@o@ fop_basic@o@ \
+	fop_rec@o@ fop_util@o@ hash_func@o@ hmac@o@ hsearch@o@ lock@o@ \
+	lock_deadlock@o@ lock_id@o@ lock_list@o@ lock_method@o@ \
+	lock_region@o@ lock_stat@o@ lock_timer@o@ lock_util@o@ log@o@ \
+	log_archive@o@ log_compare@o@ log_get@o@ log_method@o@ \
+	log_put@o@ log_stat@o@ mp_alloc@o@ mp_bh@o@ mp_fget@o@ \
+	mp_fmethod@o@ mp_fopen@o@ mp_fput@o@ mp_fset@o@ mp_method@o@ \
+	mp_region@o@ mp_register@o@ mp_stat@o@ mp_sync@o@ mp_trickle@o@ \
+	mutex@o@ os_abs@o@ os_alloc@o@ os_clock@o@ os_config@o@ \
+	os_dir@o@ os_errno@o@ os_fid@o@ os_fsync@o@ os_handle@o@ \
+	os_id@o@ os_map@o@ os_method@o@ os_oflags@o@ os_open@o@ \
+	os_region@o@ os_rename@o@ os_root@o@ os_rpath@o@ os_rw@o@ \
+	os_seek@o@ os_sleep@o@ os_spin@o@ os_stat@o@ os_tmpdir@o@ \
+	os_truncate@o@ os_unlink@o@ sha1@o@ seq_stat@o@ sequence@o@ \
+	snprintf@o@ txn@o@ txn_auto@o@ txn_method@o@ txn_rec@o@ \
+	txn_recover@o@ txn_region@o@ txn_stat@o@ txn_util@o@ xa@o@ \
+	xa_db@o@ xa_map@o@
 
 CXX_OBJS=\
-	cxx_db@o@ cxx_dbc@o@ cxx_dbt@o@ cxx_env@o@ cxx_except@o@ \
-	cxx_lock@o@ cxx_logc@o@ cxx_mpool@o@ cxx_txn@o@
+	cxx_db@o@ cxx_dbc@o@ cxx_dbt@o@ cxx_env@o@ cxx_except@o@ cxx_lock@o@ \
+	cxx_logc@o@ cxx_mpool@o@ cxx_multi@o@ cxx_seq@o@ cxx_txn@o@
+
+CRYPTO_OBJS=\
+	aes_method@o@ crypto@o@ mt19937db@o@ rijndael-alg-fst@o@ \
+	rijndael-api-fst@o@
 
 JAVA_OBJS=\
-	java_Db@o@ java_DbEnv@o@ java_DbLock@o@ java_DbLogc@o@ \
-	java_DbLsn@o@ java_DbTxn@o@ java_DbUtil@o@ java_Dbc@o@ \
-	java_Dbt@o@ \
-	java_info@o@ java_locked@o@ java_util@o@ java_stat_auto@o@
+	db_java_wrap@o@
 
 JAVA_DBSRCS=\
-	$(JAVA_DBDIR)/Db.java $(JAVA_DBDIR)/DbAppendRecno.java \
-	$(JAVA_DBDIR)/DbAppDispatch.java \
-	$(JAVA_DBDIR)/DbBtreeCompare.java $(JAVA_DBDIR)/DbBtreePrefix.java \
-	$(JAVA_DBDIR)/DbBtreeStat.java $(JAVA_DBDIR)/DbClient.java \
-	$(JAVA_DBDIR)/DbConstants.java $(JAVA_DBDIR)/DbDeadlockException.java \
-	$(JAVA_DBDIR)/DbDupCompare.java $(JAVA_DBDIR)/DbEnv.java \
-	$(JAVA_DBDIR)/DbEnvFeedback.java $(JAVA_DBDIR)/DbErrcall.java \
-	$(JAVA_DBDIR)/DbException.java $(JAVA_DBDIR)/DbFeedback.java \
-	$(JAVA_DBDIR)/DbHash.java $(JAVA_DBDIR)/DbHashStat.java \
-	$(JAVA_DBDIR)/DbKeyRange.java $(JAVA_DBDIR)/DbLock.java \
-	$(JAVA_DBDIR)/DbLockNotGrantedException.java \
-	$(JAVA_DBDIR)/DbLockRequest.java $(JAVA_DBDIR)/DbLockStat.java \
-	$(JAVA_DBDIR)/DbLogc.java $(JAVA_DBDIR)/DbLogStat.java \
-	$(JAVA_DBDIR)/DbLsn.java $(JAVA_DBDIR)/DbMemoryException.java \
-	$(JAVA_DBDIR)/DbMpoolFStat.java $(JAVA_DBDIR)/DbMpoolStat.java \
-	$(JAVA_DBDIR)/DbMultipleDataIterator.java \
-	$(JAVA_DBDIR)/DbMultipleIterator.java \
-	$(JAVA_DBDIR)/DbMultipleKeyDataIterator.java \
-	$(JAVA_DBDIR)/DbMultipleRecnoDataIterator.java \
-	$(JAVA_DBDIR)/DbOutputStreamErrcall.java \
-	$(JAVA_DBDIR)/DbPreplist.java $(JAVA_DBDIR)/DbQueueStat.java \
-	$(JAVA_DBDIR)/DbRepStat.java $(JAVA_DBDIR)/DbRepTransport.java \
-	$(JAVA_DBDIR)/DbRunRecoveryException.java \
-	$(JAVA_DBDIR)/DbSecondaryKeyCreate.java $(JAVA_DBDIR)/DbTxn.java \
-	$(JAVA_DBDIR)/DbTxnStat.java \
-	$(JAVA_DBDIR)/DbUtil.java $(JAVA_DBDIR)/Dbc.java $(JAVA_DBDIR)/Dbt.java
+	$(JAVA_SLEEPYCAT)/bind/ByteArrayBinding.java \
+	$(JAVA_SLEEPYCAT)/bind/EntityBinding.java \
+	$(JAVA_SLEEPYCAT)/bind/EntryBinding.java \
+	$(JAVA_SLEEPYCAT)/bind/RecordNumberBinding.java \
+	$(JAVA_SLEEPYCAT)/bind/serial/ClassCatalog.java \
+	$(JAVA_SLEEPYCAT)/bind/serial/SerialBinding.java \
+	$(JAVA_SLEEPYCAT)/bind/serial/SerialInput.java \
+	$(JAVA_SLEEPYCAT)/bind/serial/SerialOutput.java \
+	$(JAVA_SLEEPYCAT)/bind/serial/SerialSerialBinding.java \
+	$(JAVA_SLEEPYCAT)/bind/serial/SerialSerialKeyCreator.java \
+	$(JAVA_SLEEPYCAT)/bind/serial/StoredClassCatalog.java \
+	$(JAVA_SLEEPYCAT)/bind/serial/TupleSerialBinding.java \
+	$(JAVA_SLEEPYCAT)/bind/serial/TupleSerialKeyCreator.java \
+	$(JAVA_SLEEPYCAT)/bind/serial/TupleSerialMarshalledBinding.java \
+	$(JAVA_SLEEPYCAT)/bind/serial/TupleSerialMarshalledKeyCreator.java \
+	$(JAVA_SLEEPYCAT)/bind/tuple/BooleanBinding.java \
+	$(JAVA_SLEEPYCAT)/bind/tuple/ByteBinding.java \
+	$(JAVA_SLEEPYCAT)/bind/tuple/CharacterBinding.java \
+	$(JAVA_SLEEPYCAT)/bind/tuple/DoubleBinding.java \
+	$(JAVA_SLEEPYCAT)/bind/tuple/FloatBinding.java \
+	$(JAVA_SLEEPYCAT)/bind/tuple/IntegerBinding.java \
+	$(JAVA_SLEEPYCAT)/bind/tuple/LongBinding.java \
+	$(JAVA_SLEEPYCAT)/bind/tuple/MarshalledTupleEntry.java \
+	$(JAVA_SLEEPYCAT)/bind/tuple/MarshalledTupleKeyEntity.java \
+	$(JAVA_SLEEPYCAT)/bind/tuple/ShortBinding.java \
+	$(JAVA_SLEEPYCAT)/bind/tuple/StringBinding.java \
+	$(JAVA_SLEEPYCAT)/bind/tuple/TupleBinding.java \
+	$(JAVA_SLEEPYCAT)/bind/tuple/TupleInput.java \
+	$(JAVA_SLEEPYCAT)/bind/tuple/TupleInputBinding.java \
+	$(JAVA_SLEEPYCAT)/bind/tuple/TupleMarshalledBinding.java \
+	$(JAVA_SLEEPYCAT)/bind/tuple/TupleOutput.java \
+	$(JAVA_SLEEPYCAT)/bind/tuple/TupleTupleBinding.java \
+	$(JAVA_SLEEPYCAT)/bind/tuple/TupleTupleKeyCreator.java \
+	$(JAVA_SLEEPYCAT)/bind/tuple/TupleTupleMarshalledBinding.java \
+	$(JAVA_SLEEPYCAT)/bind/tuple/TupleTupleMarshalledKeyCreator.java \
+	$(JAVA_SLEEPYCAT)/collections/CurrentTransaction.java \
+	$(JAVA_SLEEPYCAT)/collections/DataCursor.java \
+	$(JAVA_SLEEPYCAT)/collections/DataView.java \
+	$(JAVA_SLEEPYCAT)/collections/KeyRange.java \
+	$(JAVA_SLEEPYCAT)/collections/KeyRangeException.java \
+	$(JAVA_SLEEPYCAT)/collections/MapEntryParameter.java \
+	$(JAVA_SLEEPYCAT)/collections/PrimaryKeyAssigner.java \
+	$(JAVA_SLEEPYCAT)/collections/RangeCursor.java \
+	$(JAVA_SLEEPYCAT)/collections/StoredCollection.java \
+	$(JAVA_SLEEPYCAT)/collections/StoredCollections.java \
+	$(JAVA_SLEEPYCAT)/collections/StoredContainer.java \
+	$(JAVA_SLEEPYCAT)/collections/StoredEntrySet.java \
+	$(JAVA_SLEEPYCAT)/collections/StoredIterator.java \
+	$(JAVA_SLEEPYCAT)/collections/StoredKeySet.java \
+	$(JAVA_SLEEPYCAT)/collections/StoredList.java \
+	$(JAVA_SLEEPYCAT)/collections/StoredMap.java \
+	$(JAVA_SLEEPYCAT)/collections/StoredMapEntry.java \
+	$(JAVA_SLEEPYCAT)/collections/StoredSortedEntrySet.java \
+	$(JAVA_SLEEPYCAT)/collections/StoredSortedKeySet.java \
+	$(JAVA_SLEEPYCAT)/collections/StoredSortedMap.java \
+	$(JAVA_SLEEPYCAT)/collections/StoredSortedValueSet.java \
+	$(JAVA_SLEEPYCAT)/collections/StoredValueSet.java \
+	$(JAVA_SLEEPYCAT)/collections/TransactionRunner.java \
+	$(JAVA_SLEEPYCAT)/collections/TransactionWorker.java \
+	$(JAVA_SLEEPYCAT)/collections/TupleSerialFactory.java \
+	$(JAVA_SLEEPYCAT)/compat/DbCompat.java \
+	$(JAVA_SLEEPYCAT)/db/BtreePrefixCalculator.java \
+	$(JAVA_SLEEPYCAT)/db/BtreeStats.java \
+	$(JAVA_SLEEPYCAT)/db/CacheFile.java \
+	$(JAVA_SLEEPYCAT)/db/CacheFilePriority.java \
+	$(JAVA_SLEEPYCAT)/db/CacheFileStats.java \
+	$(JAVA_SLEEPYCAT)/db/CacheStats.java \
+	$(JAVA_SLEEPYCAT)/db/CheckpointConfig.java \
+	$(JAVA_SLEEPYCAT)/db/Cursor.java \
+	$(JAVA_SLEEPYCAT)/db/CursorConfig.java \
+	$(JAVA_SLEEPYCAT)/db/Database.java \
+	$(JAVA_SLEEPYCAT)/db/DatabaseConfig.java \
+	$(JAVA_SLEEPYCAT)/db/DatabaseEntry.java \
+	$(JAVA_SLEEPYCAT)/db/DatabaseException.java \
+	$(JAVA_SLEEPYCAT)/db/DatabaseStats.java \
+	$(JAVA_SLEEPYCAT)/db/DatabaseType.java \
+	$(JAVA_SLEEPYCAT)/db/DeadlockException.java \
+	$(JAVA_SLEEPYCAT)/db/Environment.java \
+	$(JAVA_SLEEPYCAT)/db/EnvironmentConfig.java \
+	$(JAVA_SLEEPYCAT)/db/ErrorHandler.java \
+	$(JAVA_SLEEPYCAT)/db/FeedbackHandler.java \
+	$(JAVA_SLEEPYCAT)/db/HashStats.java \
+	$(JAVA_SLEEPYCAT)/db/Hasher.java \
+	$(JAVA_SLEEPYCAT)/db/JoinConfig.java \
+	$(JAVA_SLEEPYCAT)/db/JoinCursor.java \
+	$(JAVA_SLEEPYCAT)/db/KeyRange.java \
+	$(JAVA_SLEEPYCAT)/db/Lock.java \
+	$(JAVA_SLEEPYCAT)/db/LockDetectMode.java \
+	$(JAVA_SLEEPYCAT)/db/LockMode.java \
+	$(JAVA_SLEEPYCAT)/db/LockNotGrantedException.java \
+	$(JAVA_SLEEPYCAT)/db/LockOperation.java \
+	$(JAVA_SLEEPYCAT)/db/LockRequest.java \
+	$(JAVA_SLEEPYCAT)/db/LockRequestMode.java \
+	$(JAVA_SLEEPYCAT)/db/LockStats.java \
+	$(JAVA_SLEEPYCAT)/db/LogCursor.java \
+	$(JAVA_SLEEPYCAT)/db/LogRecordHandler.java \
+	$(JAVA_SLEEPYCAT)/db/LogSequenceNumber.java \
+	$(JAVA_SLEEPYCAT)/db/LogStats.java \
+	$(JAVA_SLEEPYCAT)/db/MemoryException.java \
+	$(JAVA_SLEEPYCAT)/db/MessageHandler.java \
+	$(JAVA_SLEEPYCAT)/db/MultipleDataEntry.java \
+	$(JAVA_SLEEPYCAT)/db/MultipleEntry.java \
+	$(JAVA_SLEEPYCAT)/db/MultipleKeyDataEntry.java \
+	$(JAVA_SLEEPYCAT)/db/MultipleRecnoDataEntry.java \
+	$(JAVA_SLEEPYCAT)/db/OperationStatus.java \
+	$(JAVA_SLEEPYCAT)/db/PanicHandler.java \
+	$(JAVA_SLEEPYCAT)/db/PreparedTransaction.java \
+	$(JAVA_SLEEPYCAT)/db/QueueStats.java \
+	$(JAVA_SLEEPYCAT)/db/RecordNumberAppender.java \
+	$(JAVA_SLEEPYCAT)/db/RecoveryOperation.java \
+	$(JAVA_SLEEPYCAT)/db/ReplicationHandleDeadException.java \
+	$(JAVA_SLEEPYCAT)/db/ReplicationStats.java \
+	$(JAVA_SLEEPYCAT)/db/ReplicationStatus.java \
+	$(JAVA_SLEEPYCAT)/db/ReplicationTransport.java \
+	$(JAVA_SLEEPYCAT)/db/RunRecoveryException.java \
+	$(JAVA_SLEEPYCAT)/db/SecondaryConfig.java \
+	$(JAVA_SLEEPYCAT)/db/SecondaryCursor.java \
+	$(JAVA_SLEEPYCAT)/db/SecondaryDatabase.java \
+	$(JAVA_SLEEPYCAT)/db/SecondaryKeyCreator.java \
+	$(JAVA_SLEEPYCAT)/db/Sequence.java \
+	$(JAVA_SLEEPYCAT)/db/SequenceConfig.java \
+	$(JAVA_SLEEPYCAT)/db/SequenceStats.java \
+	$(JAVA_SLEEPYCAT)/db/StatsConfig.java \
+	$(JAVA_SLEEPYCAT)/db/Transaction.java \
+	$(JAVA_SLEEPYCAT)/db/TransactionConfig.java \
+	$(JAVA_SLEEPYCAT)/db/TransactionStats.java \
+	$(JAVA_SLEEPYCAT)/db/VerifyConfig.java \
+	$(JAVA_SLEEPYCAT)/db/internal/Db.java \
+	$(JAVA_SLEEPYCAT)/db/internal/DbClient.java \
+	$(JAVA_SLEEPYCAT)/db/internal/DbConstants.java \
+	$(JAVA_SLEEPYCAT)/db/internal/DbEnv.java \
+	$(JAVA_SLEEPYCAT)/db/internal/DbLock.java \
+	$(JAVA_SLEEPYCAT)/db/internal/DbLogc.java \
+	$(JAVA_SLEEPYCAT)/db/internal/DbMpoolFile.java \
+	$(JAVA_SLEEPYCAT)/db/internal/DbSequence.java \
+	$(JAVA_SLEEPYCAT)/db/internal/DbTxn.java \
+	$(JAVA_SLEEPYCAT)/db/internal/DbUtil.java \
+	$(JAVA_SLEEPYCAT)/db/internal/Dbc.java \
+	$(JAVA_SLEEPYCAT)/db/internal/db_java.java \
+	$(JAVA_SLEEPYCAT)/db/internal/db_javaJNI.java \
+	$(JAVA_SLEEPYCAT)/util/ExceptionUnwrapper.java \
+	$(JAVA_SLEEPYCAT)/util/ExceptionWrapper.java \
+	$(JAVA_SLEEPYCAT)/util/FastInputStream.java \
+	$(JAVA_SLEEPYCAT)/util/FastOutputStream.java \
+	$(JAVA_SLEEPYCAT)/util/IOExceptionWrapper.java \
+	$(JAVA_SLEEPYCAT)/util/RuntimeExceptionWrapper.java \
+	$(JAVA_SLEEPYCAT)/util/UtfOps.java
 
 JAVA_EXSRCS=\
-	$(JAVA_EXDIR)/AccessExample.java \
-	$(JAVA_EXDIR)/BtRecExample.java \
-	$(JAVA_EXDIR)/BulkAccessExample.java \
-	$(JAVA_EXDIR)/EnvExample.java \
-	$(JAVA_EXDIR)/LockExample.java \
-	$(JAVA_EXDIR)/TpcbExample.java
+	$(JAVA_EXDIR)/collections/access/AccessExample.java \
+	$(JAVA_EXDIR)/collections/hello/HelloDatabaseWorld.java \
+	$(JAVA_EXDIR)/collections/ship/basic/PartData.java \
+	$(JAVA_EXDIR)/collections/ship/basic/PartKey.java \
+	$(JAVA_EXDIR)/collections/ship/basic/Sample.java \
+	$(JAVA_EXDIR)/collections/ship/basic/SampleDatabase.java \
+	$(JAVA_EXDIR)/collections/ship/basic/SampleViews.java \
+	$(JAVA_EXDIR)/collections/ship/basic/ShipmentData.java \
+	$(JAVA_EXDIR)/collections/ship/basic/ShipmentKey.java \
+	$(JAVA_EXDIR)/collections/ship/basic/SupplierData.java \
+	$(JAVA_EXDIR)/collections/ship/basic/SupplierKey.java \
+	$(JAVA_EXDIR)/collections/ship/basic/Weight.java \
+	$(JAVA_EXDIR)/collections/ship/entity/Part.java \
+	$(JAVA_EXDIR)/collections/ship/entity/PartData.java \
+	$(JAVA_EXDIR)/collections/ship/entity/PartKey.java \
+	$(JAVA_EXDIR)/collections/ship/entity/Sample.java \
+	$(JAVA_EXDIR)/collections/ship/entity/SampleDatabase.java \
+	$(JAVA_EXDIR)/collections/ship/entity/SampleViews.java \
+	$(JAVA_EXDIR)/collections/ship/entity/Shipment.java \
+	$(JAVA_EXDIR)/collections/ship/entity/ShipmentData.java \
+	$(JAVA_EXDIR)/collections/ship/entity/ShipmentKey.java \
+	$(JAVA_EXDIR)/collections/ship/entity/Supplier.java \
+	$(JAVA_EXDIR)/collections/ship/entity/SupplierData.java \
+	$(JAVA_EXDIR)/collections/ship/entity/SupplierKey.java \
+	$(JAVA_EXDIR)/collections/ship/entity/Weight.java \
+	$(JAVA_EXDIR)/collections/ship/factory/Part.java \
+	$(JAVA_EXDIR)/collections/ship/factory/PartKey.java \
+	$(JAVA_EXDIR)/collections/ship/factory/Sample.java \
+	$(JAVA_EXDIR)/collections/ship/factory/SampleDatabase.java \
+	$(JAVA_EXDIR)/collections/ship/factory/SampleViews.java \
+	$(JAVA_EXDIR)/collections/ship/factory/Shipment.java \
+	$(JAVA_EXDIR)/collections/ship/factory/ShipmentKey.java \
+	$(JAVA_EXDIR)/collections/ship/factory/Supplier.java \
+	$(JAVA_EXDIR)/collections/ship/factory/SupplierKey.java \
+	$(JAVA_EXDIR)/collections/ship/factory/Weight.java \
+	$(JAVA_EXDIR)/collections/ship/index/PartData.java \
+	$(JAVA_EXDIR)/collections/ship/index/PartKey.java \
+	$(JAVA_EXDIR)/collections/ship/index/Sample.java \
+	$(JAVA_EXDIR)/collections/ship/index/SampleDatabase.java \
+	$(JAVA_EXDIR)/collections/ship/index/SampleViews.java \
+	$(JAVA_EXDIR)/collections/ship/index/ShipmentData.java \
+	$(JAVA_EXDIR)/collections/ship/index/ShipmentKey.java \
+	$(JAVA_EXDIR)/collections/ship/index/SupplierData.java \
+	$(JAVA_EXDIR)/collections/ship/index/SupplierKey.java \
+	$(JAVA_EXDIR)/collections/ship/index/Weight.java \
+	$(JAVA_EXDIR)/collections/ship/marshal/MarshalledEnt.java \
+	$(JAVA_EXDIR)/collections/ship/marshal/MarshalledKey.java \
+	$(JAVA_EXDIR)/collections/ship/marshal/Part.java \
+	$(JAVA_EXDIR)/collections/ship/marshal/PartKey.java \
+	$(JAVA_EXDIR)/collections/ship/marshal/Sample.java \
+	$(JAVA_EXDIR)/collections/ship/marshal/SampleDatabase.java \
+	$(JAVA_EXDIR)/collections/ship/marshal/SampleViews.java \
+	$(JAVA_EXDIR)/collections/ship/marshal/Shipment.java \
+	$(JAVA_EXDIR)/collections/ship/marshal/ShipmentKey.java \
+	$(JAVA_EXDIR)/collections/ship/marshal/Supplier.java \
+	$(JAVA_EXDIR)/collections/ship/marshal/SupplierKey.java \
+	$(JAVA_EXDIR)/collections/ship/marshal/Weight.java \
+	$(JAVA_EXDIR)/collections/ship/sentity/Part.java \
+	$(JAVA_EXDIR)/collections/ship/sentity/PartKey.java \
+	$(JAVA_EXDIR)/collections/ship/sentity/Sample.java \
+	$(JAVA_EXDIR)/collections/ship/sentity/SampleDatabase.java \
+	$(JAVA_EXDIR)/collections/ship/sentity/SampleViews.java \
+	$(JAVA_EXDIR)/collections/ship/sentity/Shipment.java \
+	$(JAVA_EXDIR)/collections/ship/sentity/ShipmentKey.java \
+	$(JAVA_EXDIR)/collections/ship/sentity/Supplier.java \
+	$(JAVA_EXDIR)/collections/ship/sentity/SupplierKey.java \
+	$(JAVA_EXDIR)/collections/ship/sentity/Weight.java \
+	$(JAVA_EXDIR)/collections/ship/tuple/Part.java \
+	$(JAVA_EXDIR)/collections/ship/tuple/PartData.java \
+	$(JAVA_EXDIR)/collections/ship/tuple/PartKey.java \
+	$(JAVA_EXDIR)/collections/ship/tuple/Sample.java \
+	$(JAVA_EXDIR)/collections/ship/tuple/SampleDatabase.java \
+	$(JAVA_EXDIR)/collections/ship/tuple/SampleViews.java \
+	$(JAVA_EXDIR)/collections/ship/tuple/Shipment.java \
+	$(JAVA_EXDIR)/collections/ship/tuple/ShipmentData.java \
+	$(JAVA_EXDIR)/collections/ship/tuple/ShipmentKey.java \
+	$(JAVA_EXDIR)/collections/ship/tuple/Supplier.java \
+	$(JAVA_EXDIR)/collections/ship/tuple/SupplierData.java \
+	$(JAVA_EXDIR)/collections/ship/tuple/SupplierKey.java \
+	$(JAVA_EXDIR)/collections/ship/tuple/Weight.java \
+	$(JAVA_EXDIR)/db/AccessExample.java \
+	$(JAVA_EXDIR)/db/BtRecExample.java \
+	$(JAVA_EXDIR)/db/BulkAccessExample.java \
+	$(JAVA_EXDIR)/db/EnvExample.java \
+	$(JAVA_EXDIR)/db/GettingStarted/ExampleDatabaseLoad.java \
+	$(JAVA_EXDIR)/db/GettingStarted/ExampleDatabaseRead.java \
+	$(JAVA_EXDIR)/db/GettingStarted/Inventory.java \
+	$(JAVA_EXDIR)/db/GettingStarted/InventoryBinding.java \
+	$(JAVA_EXDIR)/db/GettingStarted/ItemNameKeyCreator.java \
+	$(JAVA_EXDIR)/db/GettingStarted/MyDbs.java \
+	$(JAVA_EXDIR)/db/GettingStarted/Vendor.java \
+	$(JAVA_EXDIR)/db/LockExample.java \
+	$(JAVA_EXDIR)/db/RPCExample.java \
+	$(JAVA_EXDIR)/db/SequenceExample.java \
+	$(JAVA_EXDIR)/db/TpcbExample.java
 
 TCL_OBJS=\
 	tcl_compat@o@ tcl_db@o@ tcl_db_pkg@o@ tcl_dbcursor@o@ tcl_env@o@ \
 	tcl_internal@o@ tcl_lock@o@ tcl_log@o@ tcl_mp@o@ tcl_rep@o@ \
-	tcl_txn@o@ tcl_util@o@
+	tcl_seq@o@ tcl_txn@o@ tcl_util@o@
 
 RPC_CLIENT_OBJS=\
 	client@o@ db_server_clnt@o@ db_server_xdr@o@ gen_client@o@ \
@@ -250,16 +483,19 @@ RPC_CXXSRV_OBJS=\
 	gen_db_server@o@
 
 RPC_JAVASRV_SRCS=\
-	$(JAVA_RPCDIR)/DbDispatcher.java \
-	$(JAVA_RPCDIR)/DbServer.java \
+	$(JAVA_RPCDIR)/AssociateCallbacks.java \
+	$(JAVA_RPCDIR)/Dispatcher.java \
 	$(JAVA_RPCDIR)/FreeList.java \
+	$(JAVA_RPCDIR)/JoinCursorAdapter.java \
 	$(JAVA_RPCDIR)/LocalIterator.java \
 	$(JAVA_RPCDIR)/RpcDb.java \
 	$(JAVA_RPCDIR)/RpcDbEnv.java \
 	$(JAVA_RPCDIR)/RpcDbTxn.java \
 	$(JAVA_RPCDIR)/RpcDbc.java \
+	$(JAVA_RPCDIR)/Server.java \
 	$(JAVA_RPCDIR)/Timer.java \
-	$(JAVA_RPCDIR)/gen/DbServerStub.java \
+	$(JAVA_RPCDIR)/Util.java \
+	$(JAVA_RPCDIR)/gen/ServerStubs.java \
 	$(JAVA_RPCDIR)/gen/__db_associate_msg.java \
 	$(JAVA_RPCDIR)/gen/__db_associate_reply.java \
 	$(JAVA_RPCDIR)/gen/__db_bt_maxkey_msg.java \
@@ -280,7 +516,33 @@ RPC_JAVASRV_SRCS=\
 	$(JAVA_RPCDIR)/gen/__db_extentsize_reply.java \
 	$(JAVA_RPCDIR)/gen/__db_flags_msg.java \
 	$(JAVA_RPCDIR)/gen/__db_flags_reply.java \
+	$(JAVA_RPCDIR)/gen/__db_get_bt_minkey_msg.java \
+	$(JAVA_RPCDIR)/gen/__db_get_bt_minkey_reply.java \
+	$(JAVA_RPCDIR)/gen/__db_get_encrypt_flags_msg.java \
+	$(JAVA_RPCDIR)/gen/__db_get_encrypt_flags_reply.java \
+	$(JAVA_RPCDIR)/gen/__db_get_extentsize_msg.java \
+	$(JAVA_RPCDIR)/gen/__db_get_extentsize_reply.java \
+	$(JAVA_RPCDIR)/gen/__db_get_flags_msg.java \
+	$(JAVA_RPCDIR)/gen/__db_get_flags_reply.java \
+	$(JAVA_RPCDIR)/gen/__db_get_h_ffactor_msg.java \
+	$(JAVA_RPCDIR)/gen/__db_get_h_ffactor_reply.java \
+	$(JAVA_RPCDIR)/gen/__db_get_h_nelem_msg.java \
+	$(JAVA_RPCDIR)/gen/__db_get_h_nelem_reply.java \
+	$(JAVA_RPCDIR)/gen/__db_get_lorder_msg.java \
+	$(JAVA_RPCDIR)/gen/__db_get_lorder_reply.java \
 	$(JAVA_RPCDIR)/gen/__db_get_msg.java \
+	$(JAVA_RPCDIR)/gen/__db_get_name_msg.java \
+	$(JAVA_RPCDIR)/gen/__db_get_name_reply.java \
+	$(JAVA_RPCDIR)/gen/__db_get_open_flags_msg.java \
+	$(JAVA_RPCDIR)/gen/__db_get_open_flags_reply.java \
+	$(JAVA_RPCDIR)/gen/__db_get_pagesize_msg.java \
+	$(JAVA_RPCDIR)/gen/__db_get_pagesize_reply.java \
+	$(JAVA_RPCDIR)/gen/__db_get_re_delim_msg.java \
+	$(JAVA_RPCDIR)/gen/__db_get_re_delim_reply.java \
+	$(JAVA_RPCDIR)/gen/__db_get_re_len_msg.java \
+	$(JAVA_RPCDIR)/gen/__db_get_re_len_reply.java \
+	$(JAVA_RPCDIR)/gen/__db_get_re_pad_msg.java \
+	$(JAVA_RPCDIR)/gen/__db_get_re_pad_reply.java \
 	$(JAVA_RPCDIR)/gen/__db_get_reply.java \
 	$(JAVA_RPCDIR)/gen/__db_h_ffactor_msg.java \
 	$(JAVA_RPCDIR)/gen/__db_h_ffactor_reply.java \
@@ -344,6 +606,16 @@ RPC_JAVASRV_SRCS=\
 	$(JAVA_RPCDIR)/gen/__env_encrypt_reply.java \
 	$(JAVA_RPCDIR)/gen/__env_flags_msg.java \
 	$(JAVA_RPCDIR)/gen/__env_flags_reply.java \
+	$(JAVA_RPCDIR)/gen/__env_get_cachesize_msg.java \
+	$(JAVA_RPCDIR)/gen/__env_get_cachesize_reply.java \
+	$(JAVA_RPCDIR)/gen/__env_get_encrypt_flags_msg.java \
+	$(JAVA_RPCDIR)/gen/__env_get_encrypt_flags_reply.java \
+	$(JAVA_RPCDIR)/gen/__env_get_flags_msg.java \
+	$(JAVA_RPCDIR)/gen/__env_get_flags_reply.java \
+	$(JAVA_RPCDIR)/gen/__env_get_home_msg.java \
+	$(JAVA_RPCDIR)/gen/__env_get_home_reply.java \
+	$(JAVA_RPCDIR)/gen/__env_get_open_flags_msg.java \
+	$(JAVA_RPCDIR)/gen/__env_get_open_flags_reply.java \
 	$(JAVA_RPCDIR)/gen/__env_open_msg.java \
 	$(JAVA_RPCDIR)/gen/__env_open_reply.java \
 	$(JAVA_RPCDIR)/gen/__env_remove_msg.java \
@@ -364,8 +636,8 @@ RPC_JAVASRV_SRCS=\
 
 UTIL_PROGS=\
 	@ADDITIONAL_PROGS@ \
-	db_archive db_checkpoint db_deadlock \
-	db_dump db_load db_printlog db_recover db_stat db_upgrade db_verify
+	db_archive db_checkpoint db_deadlock db_dump db_load db_printlog \
+	db_recover db_stat db_upgrade db_verify
 
 ##################################################
 # List of files installed into the library directory.
@@ -375,13 +647,13 @@ LIB_INSTALL_FILE_LIST=\
 	$(libso) \
 	$(libso_default) \
 	$(libso_major) \
-	$(libso_static) \
+	$(libdb_version) \
 	$(libso_target) \
 	$(libcxx) \
 	$(libxso) \
 	$(libxso_default) \
 	$(libxso_major) \
-	$(libxso_static) \
+	$(libcxx_version) \
 	$(libxso_target) \
 	$(libtso) \
 	$(libtso_default) \
@@ -398,10 +670,9 @@ LIB_INSTALL_FILE_LIST=\
 	$(libj_jarfile)
 
 ##################################################
-# We're building a standard library or a RPM file hierarchy, potentially
-# for Embedix.  Note: "all" must be the first target in the Makefile.
+# Note: "all" must be the first target in the Makefile.
 ##################################################
-all: @BUILD_TARGET@ libdb.a
+all: @BUILD_TARGET@
 
 install-strip install: all @INSTALL_TARGET@
 
@@ -410,29 +681,49 @@ install-strip install: all @INSTALL_TARGET@
 ##################################################
 library_build: @INSTALL_LIBS@ @ADDITIONAL_LANG@ $(UTIL_PROGS)
 
-$(libdb): $(C_OBJS)
+# Static C library named libdb.a.
+$(libdb): $(DEF_LIB)
+
+# Real static C library.
+$(libdb_version): $(C_OBJS)
 	$(ar) cr $@ $(C_OBJS)
 	test ! -f $(ranlib) || $(ranlib) $@
+	$(rm) -f $(libdb)
+	$(ln) -s $(libdb_version) $(libdb)
 
-$(libcxx): $(CXX_OBJS) $(C_OBJS)
+# Shared C library.
+$(libso_target): $(C_OBJS)
+	$(SOLINK) $(SOFLAGS) $(LDFLAGS) -o $@ $(C_OBJS) $(LIBSO_LIBS)
+	$(rm) -f $(libdb)
+	$(ln) -s .libs/$(libdb_version) $(libdb)
+
+# Static C++ library named libdb_cxx.a.
+$(libcxx): $(DEF_LIB_CXX)
+
+# Real static C++ library.
+$(libcxx_version): $(CXX_OBJS) $(C_OBJS)
 	$(ar) cr $@ $(CXX_OBJS) $(C_OBJS)
 	test ! -f $(ranlib) || $(ranlib) $@
+	$(rm) -f $(libcxx)
+	$(ln) -s $(libcxx_version) $(libcxx)
 
-$(libso_target): $(C_OBJS)
-	$(SOLINK) $(SOFLAGS) $(LDFLAGS) -o $@ $(C_OBJS) $(LIBSO_LIBS)
+# Shared C++ library.
+$(libxso_target): $(CXX_OBJS) $(C_OBJS)
+	$(XSOLINK) $(SOFLAGS) $(LDFLAGS) \
+	    -o $@ $(CXX_OBJS) $(C_OBJS) $(LIBXSO_LIBS)
+	$(rm) -f $(libcxx)
+	$(ln) -s .libs/$(libcxx_version) $(libcxx)
 
+# Shared Java library.
 $(libjso_target): $(JAVA_OBJS) $(C_OBJS)
-	$(SOLINK) -jnimodule $(SOFLAGS) $(LDFLAGS) \
+	$(SOLINK) -shrext @JMODSUFFIX@ $(SOFLAGS) $(LDFLAGS) \
 	    -o $@ $(JAVA_OBJS) $(C_OBJS) $(LIBJSO_LIBS)
 
+# Shared Tcl library.
 $(libtso_target): $(TCL_OBJS) $(C_OBJS)
-	$(SOLINK) -module $(SOFLAGS) $(LDFLAGS) \
+	$(SOLINK) @LIBTSO_MODULE@ $(SOFLAGS) $(LDFLAGS) \
 	    -o $@ $(TCL_OBJS) $(C_OBJS) $(LIBTSO_LIBS)
 
-$(libxso_target): $(CXX_OBJS) $(C_OBJS)
-	$(XSOLINK) $(SOFLAGS) $(LDFLAGS) \
-	    -o $@ $(CXX_OBJS) $(C_OBJS) $(LIBXSO_LIBS)
-
 ##################################################
 # Creating individual dependencies and actions for building class
 # files is possible, but it is very messy and error prone.
@@ -443,22 +734,23 @@ $(libj_jarfile): $(JAVA_DBSRCS)
 	@test -d $(JAVA_CLASSTOP) || \
 	   ($(mkdir) -p $(JAVA_CLASSTOP) && $(chmod) $(dmode) $(JAVA_CLASSTOP))
 	$(JAVAC) -d $(JAVA_CLASSTOP) $(JAVACFLAGS) $(JAVA_DBSRCS)
-	cd $(JAVA_CLASSTOP) && $(JAR) cf ../$(libj_jarfile) $(JAVA_DBREL)
+	cd $(JAVA_CLASSTOP) && $(JAR) cf ../$(libj_jarfile) ./com/sleepycat
 
 $(libj_exjarfile): $(libj_jarfile) $(JAVA_EXSRCS)
-	@test -d $(JAVA_CLASSTOP) || \
-	   ($(mkdir) -p $(JAVA_CLASSTOP) && $(chmod) $(dmode) $(JAVA_CLASSTOP))
-	$(JAVAC) -d $(JAVA_CLASSTOP) $(JAVACFLAGS) $(JAVA_EXSRCS)
-	cd $(JAVA_CLASSTOP) && $(JAR) cf ../$(libj_exjarfile) $(JAVA_EXREL)
+	@test -d $(JAVA_EXCLASSTOP) || \
+	   ($(mkdir) -p $(JAVA_EXCLASSTOP) && \
+		$(chmod) $(dmode) $(JAVA_EXCLASSTOP))
+	$(JAVAC) -classpath $(libj_jarfile) -d $(JAVA_EXCLASSTOP) \
+		$(JAVACFLAGS) $(JAVA_EXSRCS)
+	cd $(JAVA_EXCLASSTOP) && $(JAR) cf ../$(libj_exjarfile) .
 
 $(rpc_jarfile): $(libj_jarfile) $(RPC_JAVASRV_SRCS)
-	@test -d $(JAVA_RPCCLASSES) || \
-	   ($(mkdir) -p $(JAVA_RPCCLASSES) && \
-	       $(chmod) $(dmode) $(JAVA_RPCCLASSES))
+	@test -d $(JAVA_RPCCLASSTOP) || \
+	   ($(mkdir) -p $(JAVA_RPCCLASSTOP) && \
+	       $(chmod) $(dmode) $(JAVA_RPCCLASSTOP))
 	env CLASSPATH=$(CLASSPATH):$(JAVA_RPCDIR)/oncrpc.jar \
-	    @JAVAC@ -d $(JAVA_RPCCLASSES) $(JAVACFLAGS) $(RPC_JAVASRV_SRCS)
-	cd $(JAVA_RPCCLASSES) && $(JAR) cf ../$(rpc_jarfile) $(JAVA_RPCREL)
-
+	    @JAVAC@ -d $(JAVA_RPCCLASSTOP) $(JAVACFLAGS) $(RPC_JAVASRV_SRCS)
+	cd $(JAVA_RPCCLASSTOP) && $(JAR) cf ../$(rpc_jarfile) $(JAVA_RPCREL)
 
 ##################################################
 # Utilities
@@ -474,11 +766,11 @@ berkeley_db_cxxsvc: $(RPC_CXXSRV_OBJS) util_log@o@ $(DEF_LIB_CXX)
 	$(POSTLINK) $@
 
 berkeley_db_javasvc: $(rpc_jarfile)
-	echo > $@ "#!/bin/sh"
-	echo >> $@ CLASSPATH="$(CLASSPATH):$(rpc_jarfile):$(JAVA_RPCDIR)/oncrpc.jar"
-	echo >> $@ LD_LIBRARY_PATH=.libs
-	echo >> $@ export CLASSPATH LD_LIBRARY_PATH
-	echo >> $@ exec java com.sleepycat.db.rpcserver.DbServer \$$@
+	echo "#!/bin/sh" > $@
+	echo CLASSPATH="$(CLASSPATH):$(rpc_jarfile):$(JAVA_RPCDIR)/oncrpc.jar" >> $@
+	echo LD_LIBRARY_PATH=.libs >> $@
+	echo export CLASSPATH LD_LIBRARY_PATH >> $@
+	echo exec java com.sleepycat.db.rpcserver.Server \$$@ >> $@
 	chmod +x $@
 
 db_archive: db_archive@o@ util_sig@o@ $(DEF_LIB)
@@ -497,20 +789,22 @@ db_deadlock: db_deadlock@o@ util_log@o@ util_sig@o@ $(DEF_LIB)
 	$(POSTLINK) $@
 
 db_dump: db_dump@o@ util_cache@o@ util_sig@o@ $(DEF_LIB)
-	$(CCLINK) -o $@ $(LDFLAGS) db_dump@o@ util_cache@o@ util_sig@o@ $(DEF_LIB) $(LIBS)
+	$(CCLINK) -o $@ $(LDFLAGS) \
+	    db_dump@o@ util_cache@o@ util_sig@o@ $(DEF_LIB) $(LIBS)
 	$(POSTLINK) $@
 
-db_dump185: db_dump185@o@ @LTLIBOBJS@
-	$(CCLINK) -o $@ $(LDFLAGS) db_dump185@o@ @LTLIBOBJS@ $(DB185LIB)
+db_dump185: db_dump185@o@ @REPLACEMENT_OBJS@
+	$(CCLINK) -o $@ $(LDFLAGS) db_dump185@o@ @REPLACEMENT_OBJS@ $(DB185LIB)
 	$(POSTLINK) $@
 
 db_load: db_load@o@ util_cache@o@ util_sig@o@ $(DEF_LIB)
-	$(CCLINK) -o $@ $(LDFLAGS) db_load@o@ util_cache@o@ util_sig@o@ $(DEF_LIB) $(LIBS)
+	$(CCLINK) -o $@ $(LDFLAGS) \
+	    db_load@o@ util_cache@o@ util_sig@o@ $(DEF_LIB) $(LIBS)
 	$(POSTLINK) $@
 
-db_printlog: db_printlog@o@ util_sig@o@ $(DEF_LIB)
+db_printlog: db_printlog@o@ $(PRINT_OBJS) util_sig@o@ $(DEF_LIB)
 	$(CCLINK) -o $@ $(LDFLAGS) \
-	    db_printlog@o@ util_sig@o@ $(DEF_LIB) $(LIBS)
+	    db_printlog@o@ $(PRINT_OBJS) util_sig@o@ $(DEF_LIB) $(LIBS)
 	$(POSTLINK) $@
 
 db_recover: db_recover@o@ util_sig@o@ $(DEF_LIB)
@@ -519,7 +813,8 @@ db_recover: db_recover@o@ util_sig@o@ $(DEF_LIB)
 	$(POSTLINK) $@
 
 db_stat: db_stat@o@ util_cache@o@ util_sig@o@ $(DEF_LIB)
-	$(CCLINK) -o $@ $(LDFLAGS) db_stat@o@ util_cache@o@ util_sig@o@ $(DEF_LIB) $(LIBS)
+	$(CCLINK) -o $@ $(LDFLAGS) \
+	    db_stat@o@ util_cache@o@ util_sig@o@ $(DEF_LIB) $(LIBS)
 	$(POSTLINK) $@
 
 db_upgrade: db_upgrade@o@ util_sig@o@ $(DEF_LIB)
@@ -541,129 +836,109 @@ library_install: install_include install_lib install_utilities install_docs
 uninstall: uninstall_include uninstall_lib uninstall_utilities uninstall_docs
 
 install_setup:
-	@test -d $(prefix) || \
-	    ($(mkdir) -p $(prefix) && $(chmod) $(dmode) $(prefix))
+	@test -d $(DESTDIR)$(prefix) || \
+	    ($(mkdir) -p $(DESTDIR)$(prefix) && \
+	    $(chmod) $(dmode) $(DESTDIR)$(prefix))
 
 INCDOT=	db.h db_cxx.h @ADDITIONAL_INCS@
-INCINC=	cxx_common.h cxx_except.h
 install_include:
-	@echo "Installing DB include files: $(includedir) ..."
-	@test -d $(includedir) || \
-	    ($(mkdir) -p $(includedir) && $(chmod) $(dmode) $(includedir))
-	@cd $(includedir) && $(rm) -f $(INCDOT) $(INCINC)
-	@$(cp) -p $(INCDOT) $(includedir)
-	@cd $(srcdir)/dbinc/ && $(cp) -p $(INCINC) $(includedir)
-	@cd $(includedir) && $(chmod) $(fmode) $(INCDOT) $(INCINC)
+	@echo "Installing DB include files: $(DESTDIR)$(includedir) ..."
+	@test -d $(DESTDIR)$(includedir) || \
+	    ($(mkdir) -p $(DESTDIR)$(includedir) && \
+	    $(chmod) $(dmode) $(DESTDIR)$(includedir))
+	@cd $(DESTDIR)$(includedir) && $(rm) -f $(INCDOT)
+	@$(cp) -p $(INCDOT) $(DESTDIR)$(includedir)
+	@cd $(DESTDIR)$(includedir) && $(chmod) $(fmode) $(INCDOT)
 
 uninstall_include:
-	@cd $(includedir) && $(rm) -f $(INCDOT) $(INCINC)
+	@cd $(DESTDIR)$(includedir) && $(rm) -f $(INCDOT)
 
 install_lib:
-	@echo "Installing DB library: $(libdir) ..."
-	@test -d $(libdir) || \
-	    ($(mkdir) -p $(libdir) && $(chmod) $(dmode) $(libdir))
-	@cd $(libdir) && $(rm) -f $(LIB_INSTALL_FILE_LIST)
-	@$(INSTALLER) @INSTALL_LIBS@ $(libdir)
-	@(cd $(libdir) && \
+	@echo "Installing DB library: $(DESTDIR)$(libdir) ..."
+	@test -d $(DESTDIR)$(libdir) || \
+	    ($(mkdir) -p $(DESTDIR)$(libdir) && \
+	    $(chmod) $(dmode) $(DESTDIR)$(libdir))
+	@cd $(DESTDIR)$(libdir) && $(rm) -f $(LIB_INSTALL_FILE_LIST)
+	@$(INSTALLER) @INSTALL_LIBS@ $(DESTDIR)$(libdir)
+	@(cd $(DESTDIR)$(libdir) && \
 	    test -f $(libso) && $(ln) -s $(libso) $(libso_default); \
 	    test -f $(libso) && $(ln) -s $(libso) $(libso_major); \
-	    test -f $(libso_static) && $(ln) -s $(libso_static) $(libdb); \
 	    test -f $(libxso) && $(ln) -s $(libxso) $(libxso_default); \
 	    test -f $(libxso) && $(ln) -s $(libxso) $(libxso_major); \
-	    test -f $(libxso_static) && $(ln) -s $(libxso_static) $(libcxx); \
 	    test -f $(libtso) && $(ln) -s $(libtso) $(libtso_default); \
 	    test -f $(libtso) && $(ln) -s $(libtso) $(libtso_major); \
 	    test -f $(libjso) && $(ln) -s $(libjso) $(libjso_default); \
 	    test -f $(libjso) && $(ln) -s $(libjso) $(libjso_major); \
 	    test -f $(libjso) && $(ln) -s $(libjso) $(libjso_g)) || true
 	@(test -f $(libj_jarfile) && \
-	    $(cp) $(libj_jarfile) $(libdir) && \
-	    $(chmod) $(fmode) $(libdir)/$(libj_jarfile)) || true
+	    $(cp) $(libj_jarfile) $(DESTDIR)$(libdir) && \
+	    $(chmod) $(fmode) $(DESTDIR)$(libdir)/$(libj_jarfile)) || true
 
 uninstall_lib:
-	@cd $(libdir) && $(rm) -f $(LIB_INSTALL_FILE_LIST)
+	@cd $(DESTDIR)$(libdir) && $(rm) -f $(LIB_INSTALL_FILE_LIST)
 
 install_utilities:
-	echo "Installing DB utilities: $(bindir) ..."
-	@test -d $(bindir) || \
-	    ($(mkdir) -p $(bindir) && $(chmod) $(dmode) $(bindir))
+	@echo "Installing DB utilities: $(DESTDIR)$(bindir) ..."
+	@test -d $(DESTDIR)$(bindir) || \
+	    ($(mkdir) -p $(DESTDIR)$(bindir) && \
+	    $(chmod) $(dmode) $(DESTDIR)$(bindir))
 	@for i in $(UTIL_PROGS); do \
-		$(rm) -f $(bindir)/$$i $(bindir)/$$i.exe; \
+		$(rm) -f $(DESTDIR)$(bindir)/$$i $(DESTDIR)$(bindir)/$$i.exe; \
 		test -f $$i.exe && i=$$i.exe || true; \
-		$(INSTALLER) $$i $(bindir)/$$i; \
-		test -f $(strip) && $(strip) $(bindir)/$$i || true; \
-		$(chmod) $(emode) $(bindir)/$$i; \
+		$(INSTALLER) $$i $(DESTDIR)$(bindir)/$$i; \
+		test -f $(strip) && $(strip) $(DESTDIR)$(bindir)/$$i || true; \
+		$(chmod) $(emode) $(DESTDIR)$(bindir)/$$i; \
 	done
 
 uninstall_utilities:
-	@(cd $(bindir); for i in $(UTIL_PROGS); do \
+	@(cd $(DESTDIR)$(bindir); for i in $(UTIL_PROGS); do \
 		$(rm) -f $$i $$i.exe; \
 	done)
 
-DOCLIST=\
-	api_c api_cxx api_java api_tcl images index.html ref reftoc.html \
+DOCLIST=api_c api_cxx api_tcl collections gsg images index.html java ref \
 	sleepycat utility
+
 install_docs:
-	@echo "Installing documentation: $(docdir) ..."
-	@test -d $(docdir) || \
-	    ($(mkdir) -p $(docdir) && $(chmod) $(dmode) $(docdir))
-	@cd $(docdir) && $(rm) -rf $(DOCLIST)
-	@cd $(srcdir)/docs && $(cp) -pr $(DOCLIST) $(docdir)/
+	@echo "Installing documentation: $(DESTDIR)$(docdir) ..."
+	@test -d $(DESTDIR)$(docdir) || \
+	    ($(mkdir) -p $(DESTDIR)$(docdir) && \
+	    $(chmod) $(dmode) $(DESTDIR)$(docdir))
+	@cd $(DESTDIR)$(docdir) && $(rm) -rf $(DOCLIST)
+	@cd $(srcdir)/docs && $(cp) -pr $(DOCLIST) $(DESTDIR)$(docdir)/
 
 uninstall_docs:
-	@cd $(docdir) && $(rm) -rf $(DOCLIST)
-
-##################################################
-# RPM, Embedix build and install.
-##################################################
-RPM_ARCHIVE=db-@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@.tar.gz
-rpm_build:
-	@$(rm) -rf BUILD RPMS SOURCES SPECS SRPMS RPM_INSTALL
-	@$(mkdir) -p BUILD && $(chmod) $(dmode) BUILD
-	@$(mkdir) -p RPMS/i386 && $(chmod) $(dmode) RPMS RPMS/i386
-	@$(mkdir) -p SOURCES && $(chmod) $(dmode) SOURCES
-	@$(mkdir) -p SPECS && $(chmod) $(dmode) SPECS
-	@$(mkdir) -p SRPMS && $(chmod) $(dmode) SRPMS
-	$(cp) @db_cv_path_rpm_archive@/$(RPM_ARCHIVE) SOURCES/
-	$(cp) db.spec SPECS/db.spec
-	$(rpm) --rcfile @CONFIGURATION_PATH@/rpmrc -ba SPECS/db.spec
-
-rpm_install:
-
-RPM_SRPMS=db-@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@-1.src.rpm
-embedix_install:
-	$(cp) db.ecd @db_cv_path_embedix_install@/config-data/ecds/db.ecd
-	$(chmod) $(fmode) @db_cv_path_embedix_install@/config-data/ecds/db.ecd
-	$(cp) SRPMS/$(RPM_SRPMS) \
-	    @db_cv_path_embedix_install@/Packages/SRPMS/$(RPM_SRPMS)
-	$(chmod) $(fmode) \
-	    @db_cv_path_embedix_install@/Packages/SRPMS/$(RPM_SRPMS)
+	@cd $(docdir) && $(rm) -rf $(DESTDIR)$(DOCLIST)
 
 ##################################################
 # Remaining standard Makefile targets.
 ##################################################
 CLEAN_LIST=\
-	berkeley_db_svc berkeley_db_cxxsvc berkeley_db_javasvc \
-	db_dump185 db_perf dbs bench_001 \
-	ex_access ex_apprec ex_btrec ex_dbclient ex_env ex_lock ex_mpool \
-	ex_repquote ex_thread ex_tpcb excxx_access excxx_btrec excxx_env \
-	excxx_lock excxx_mpool excxx_tpcb rpmrc
+	bench_001 berkeley_db_cxxsvc berkeley_db_javasvc berkeley_db_svc \
+	db_dump185 db_perf dbs ex_access ex_apprec ex_btrec ex_dbclient \
+	ex_env ex_lock ex_mpool ex_repquote ex_sequence ex_thread \
+	ex_tpcb example_database_load example_database_read excxx_access \
+	excxx_btrec excxx_env excxx_example_database_load \
+	excxx_example_database_read excxx_lock excxx_mpool \
+	excxx_sequence excxx_tpcb
 
 mostly-clean clean:
 	$(rm) -rf $(C_OBJS)
 	$(rm) -rf $(CXX_OBJS) $(JAVA_OBJS) $(TCL_OBJS)
 	$(rm) -rf $(RPC_CLIENT_OBJS) $(RPC_SRV_OBJS) $(RPC_CXXSRV_OBJS)
 	$(rm) -rf $(UTIL_PROGS) *.exe $(CLEAN_LIST)
-	$(rm) -rf $(JAVA_CLASSTOP) $(JAVA_RPCCLASSES) $(rpc_jarfile)
+	$(rm) -rf $(JAVA_CLASSTOP) $(JAVA_EXCLASSTOP)
+	$(rm) -rf $(JAVA_RPCCLASSES) $(rpc_jarfile)
 	$(rm) -rf tags *@o@ *.o *.o.lock *.lo core *.core
-	$(rm) -rf ALL.OUT.* BUILD PARALLEL_TESTDIR.* RPMS RPM_INSTALL
-	$(rm) -rf RUN_LOG RUNQUEUE SOURCES SPECS SRPMS TESTDIR TESTDIR.A
-	$(rm) -rf logtrack_seen.db tm .libs $(LIB_INSTALL_FILE_LIST)
+	$(rm) -rf ALL.OUT.* PARALLEL_TESTDIR.*
+	$(rm) -rf RUN_LOG RUNQUEUE TESTDIR TESTDIR.A
+	$(rm) -rf TEST.LIST logtrack_seen.db tm .libs $(LIB_INSTALL_FILE_LIST)
 
 REALCLEAN_LIST=\
-	Makefile confdefs.h config.cache config.log config.status db.h \
-	db.spec db185_int.h db_185.h db_config.h db_cxx.h db_int.h \
-	db_int_def.h include.tcl
+	Makefile confdefs.h config.cache config.log config.status \
+	configure.lineno db.h db185_int.h db_185.h db_config.h \
+	db_cxx.h db_int.h db_int_def.h include.tcl \
+	db_server.h db_server_clnt.c db_server_svc.c db_server_xdr.c \
+	gen_db_server.c win_db.h
 
 distclean maintainer-clean realclean: clean
 	$(rm) -rf $(REALCLEAN_LIST)
@@ -672,7 +947,7 @@ distclean maintainer-clean realclean: clean
 check depend dvi info obj TAGS:
 	@echo "$@: make target not supported" && true
 
-dist:
+dist rpm rpmbuild:
 	@echo "$@: make target not supported" && false
 
 ##################################################
@@ -706,19 +981,19 @@ DBS_OBJS=\
 	dbs_yield@o@
 dbs: $(DBS_OBJS) $(DEF_LIB)
 	$(CCLINK) -o $@ \
-	    $(LDFLAGS) $(DBS_OBJS) $(DEF_LIB) @LOAD_LIBS@ $(LIBS)
+	    $(LDFLAGS) $(DBS_OBJS) $(DEF_LIB) $(TEST_LIBS) $(LIBS)
 	$(POSTLINK) $@
 
 db_perf@o@: $(srcdir)/test_perf/db_perf.c
 	$(CC) $(CFLAGS) $?
-perf_cache_check@o@: $(srcdir)/test_perf/perf_cache_check.c
-	$(CC) $(CFLAGS) $?
 perf_checkpoint@o@: $(srcdir)/test_perf/perf_checkpoint.c
 	$(CC) $(CFLAGS) $?
 perf_config@o@: $(srcdir)/test_perf/perf_config.c
 	$(CC) $(CFLAGS) $?
 perf_dbs@o@: $(srcdir)/test_perf/perf_dbs.c
 	$(CC) $(CFLAGS) $?
+perf_dead@o@: $(srcdir)/test_perf/perf_dead.c
+	$(CC) $(CFLAGS) $?
 perf_debug@o@: $(srcdir)/test_perf/perf_debug.c
 	$(CC) $(CFLAGS) $?
 perf_file@o@: $(srcdir)/test_perf/perf_file.c
@@ -737,6 +1012,10 @@ perf_rand@o@: $(srcdir)/test_perf/perf_rand.c
 	$(CC) $(CFLAGS) $?
 perf_spawn@o@: $(srcdir)/test_perf/perf_spawn.c
 	$(CC) $(CFLAGS) $?
+perf_stat@o@: $(srcdir)/test_perf/perf_stat.c
+	$(CC) $(CFLAGS) $?
+perf_sync@o@: $(srcdir)/test_perf/perf_sync.c
+	$(CC) $(CFLAGS) $?
 perf_thread@o@: $(srcdir)/test_perf/perf_thread.c
 	$(CC) $(CFLAGS) $?
 perf_trickle@o@: $(srcdir)/test_perf/perf_trickle.c
@@ -748,20 +1027,21 @@ perf_util@o@: $(srcdir)/test_perf/perf_util.c
 perf_vx@o@: $(srcdir)/test_perf/perf_vx.c
 	$(CC) $(CFLAGS) $?
 DBPERF_OBJS=\
-	db_perf@o@ perf_cache_check@o@ perf_checkpoint@o@ perf_config@o@ \
-	perf_dbs@o@ perf_debug@o@ perf_file@o@ perf_key@o@ perf_log@o@ \
-	perf_misc@o@ perf_op@o@ perf_parse@o@ perf_rand@o@ \
-	perf_spawn@o@ perf_thread@o@ perf_trickle@o@ perf_txn@o@ \
-	perf_util@o@ perf_vx@o@
+	db_perf@o@ perf_checkpoint@o@ perf_config@o@ perf_dbs@o@ \
+	perf_dead@o@ perf_debug@o@ perf_file@o@ perf_key@o@ perf_log@o@ \
+	perf_misc@o@ perf_op@o@ perf_parse@o@ perf_rand@o@ perf_spawn@o@ \
+	perf_stat@o@ perf_sync@o@ perf_thread@o@ perf_trickle@o@ \
+	perf_txn@o@ perf_util@o@ perf_vx@o@
+
 db_perf: $(DBPERF_OBJS) $(DEF_LIB)
 	$(CCLINK) -o $@ \
-	    $(LDFLAGS) $(DBPERF_OBJS) $(DEF_LIB) @LOAD_LIBS@ $(LIBS)
+	    $(LDFLAGS) $(DBPERF_OBJS) $(DEF_LIB) $(TEST_LIBS) $(LIBS)
 	$(POSTLINK) $@
 
 tm@o@: $(srcdir)/mutex/tm.c
 	$(CC) $(CFLAGS) $?
 tm: tm@o@ $(DEF_LIB)
-	$(CCLINK) -o $@ $(LDFLAGS) tm@o@ $(DEF_LIB) @LOAD_LIBS@ $(LIBS)
+	$(CCLINK) -o $@ $(LDFLAGS) tm@o@ $(DEF_LIB) $(TEST_LIBS) $(LIBS)
 	$(POSTLINK) $@
 
 ##################################################
@@ -788,7 +1068,7 @@ ex_apprec_rec@o@: $(srcdir)/examples_c/ex_apprec/ex_apprec_rec.c
 EX_APPREC_OBJS=ex_apprec@o@ ex_apprec_auto@o@ ex_apprec_rec@o@
 ex_apprec: $(EX_APPREC_OBJS) $(DEF_LIB)
 	$(CCLINK) -o $@ \
-	    $(LDFLAGS) $(EX_APPREC_OBJS) $(DEF_LIB) @LOAD_LIBS@ $(LIBS)
+	    $(LDFLAGS) $(EX_APPREC_OBJS) $(DEF_LIB) $(TEST_LIBS) $(LIBS)
 
 ex_btrec@o@: $(srcdir)/examples_c/ex_btrec.c
 	$(CC) $(CFLAGS) $?
@@ -834,14 +1114,20 @@ EX_RQ_OBJS=\
 	ex_rq_client@o@ ex_rq_main@o@ ex_rq_master@o@ ex_rq_net@o@ ex_rq_util@o@
 ex_repquote: $(EX_RQ_OBJS) $(DEF_LIB)
 	$(CCLINK) -o $@ \
-	    $(LDFLAGS) $(EX_RQ_OBJS) $(DEF_LIB) @LOAD_LIBS@ $(LIBS)
+	    $(LDFLAGS) $(EX_RQ_OBJS) $(DEF_LIB) $(TEST_LIBS) $(LIBS)
+	$(POSTLINK) $@
+
+ex_sequence@o@: $(srcdir)/examples_c/ex_sequence.c
+	$(CC) $(CFLAGS) $?
+ex_sequence: ex_sequence@o@ $(DEF_LIB)
+	$(CCLINK) -o $@ $(LDFLAGS) ex_sequence@o@ $(DEF_LIB) $(LIBS)
 	$(POSTLINK) $@
 
 ex_thread@o@: $(srcdir)/examples_c/ex_thread.c
 	$(CC) $(CFLAGS) $?
 ex_thread: ex_thread@o@ $(DEF_LIB)
 	$(CCLINK) -o $@ \
-	    $(LDFLAGS) ex_thread@o@ $(DEF_LIB) @LOAD_LIBS@ $(LIBS)
+	    $(LDFLAGS) ex_thread@o@ $(DEF_LIB) $(TEST_LIBS) $(LIBS)
 	$(POSTLINK) $@
 
 ex_tpcb@o@: $(srcdir)/examples_c/ex_tpcb.c
@@ -850,6 +1136,26 @@ ex_tpcb: ex_tpcb@o@ $(DEF_LIB)
 	$(CCLINK) -o $@ $(LDFLAGS) ex_tpcb@o@ $(DEF_LIB) $(LIBS)
 	$(POSTLINK) $@
 
+gettingstarted_common@o@: \
+    $(srcdir)/examples_c/getting_started/gettingstarted_common.c
+	$(CC) -I $(srcdir)/examples_c/getting_started $(CFLAGS) $?
+example_database_load@o@: \
+    $(srcdir)/examples_c/getting_started/example_database_load.c
+	$(CC) $(CFLAGS) $?
+example_database_read@o@: \
+    $(srcdir)/examples_c/getting_started/example_database_read.c
+	$(CC) $(CFLAGS) $?
+example_database_load: example_database_load@o@ gettingstarted_common@o@ \
+    $(DEF_LIB)
+	$(CCLINK) -o $@ $(LDFLAGS) \
+	    example_database_load@o@ gettingstarted_common@o@ $(DEF_LIB) $(LIBS)
+	$(POSTLINK) $@
+example_database_read: example_database_read@o@ gettingstarted_common@o@ \
+    $(DEF_LIB)
+	$(CCLINK) -o $@ $(LDFLAGS) \
+	    example_database_read@o@ gettingstarted_common@o@ $(DEF_LIB) $(LIBS)
+	$(POSTLINK) $@
+
 ##################################################
 # Example programs for C++.
 ##################################################
@@ -883,12 +1189,37 @@ excxx_mpool: MpoolExample@o@ $(DEF_LIB_CXX)
 	$(CXXLINK) -o $@ $(LDFLAGS) MpoolExample@o@ $(DEF_LIB_CXX) $(LIBS)
 	$(POSTLINK) $@
 
+SequenceExample@o@: $(srcdir)/examples_cxx/SequenceExample.cpp
+	$(CXX) $(CXXFLAGS) $?
+excxx_sequence: SequenceExample@o@ $(DEF_LIB_CXX)
+	$(CXXLINK) -o $@ $(LDFLAGS) SequenceExample@o@ $(DEF_LIB_CXX) $(LIBS)
+	$(POSTLINK) $@
+
 TpcbExample@o@: $(srcdir)/examples_cxx/TpcbExample.cpp
 	$(CXX) $(CXXFLAGS) $?
 excxx_tpcb: TpcbExample@o@ $(DEF_LIB_CXX)
 	$(CXXLINK) -o $@ $(LDFLAGS) TpcbExample@o@ $(DEF_LIB_CXX) $(LIBS)
 	$(POSTLINK) $@
 
+excxx_example_database_load@o@: \
+    $(srcdir)/examples_cxx/getting_started/excxx_example_database_load.cpp
+	$(CXX) -I$(srcdir)/examples_cxx/getting_started $(CXXFLAGS) $?
+excxx_example_database_read@o@: \
+    $(srcdir)/examples_cxx/getting_started/excxx_example_database_read.cpp
+	$(CXX) -I$(srcdir)/examples_cxx/getting_started $(CXXFLAGS) $?
+MyDb@o@: $(srcdir)/examples_cxx/getting_started/MyDb.cpp
+	$(CXX) -I$(srcdir)/examples_cxx/getting_started $(CXXFLAGS) $?
+excxx_example_database_load: \
+    excxx_example_database_load@o@ MyDb@o@ $(DEF_LIB_CXX)
+	$(CXXLINK) -o $@ $(LDFLAGS) \
+	    excxx_example_database_load@o@ MyDb@o@ $(DEF_LIB_CXX) $(LIBS)
+	$(POSTLINK) $@
+excxx_example_database_read: \
+    excxx_example_database_read@o@ MyDb@o@ $(DEF_LIB_CXX)
+	$(CXXLINK) -o $@ $(LDFLAGS) \
+	    excxx_example_database_read@o@ MyDb@o@ $(DEF_LIB_CXX) $(LIBS)
+	$(POSTLINK) $@
+
 ##################################################
 # C API build rules.
 ##################################################
@@ -922,8 +1253,6 @@ bt_search@o@: $(srcdir)/btree/bt_search.c
 	 $(CC) $(CFLAGS) $?
 bt_split@o@: $(srcdir)/btree/bt_split.c
 	 $(CC) $(CFLAGS) $?
-bt_stack@o@: $(srcdir)/btree/bt_stack.c
-	 $(CC) $(CFLAGS) $?
 bt_stat@o@: $(srcdir)/btree/bt_stat.c
 	 $(CC) $(CFLAGS) $?
 bt_upgrade@o@: $(srcdir)/btree/bt_upgrade.c
@@ -932,12 +1261,18 @@ bt_verify@o@: $(srcdir)/btree/bt_verify.c
 	 $(CC) $(CFLAGS) $?
 btree_auto@o@: $(srcdir)/btree/btree_auto.c
 	 $(CC) $(CFLAGS) $?
+btree_autop@o@: $(srcdir)/btree/btree_autop.c
+	 $(CC) $(CFLAGS) $?
 crdel_auto@o@: $(srcdir)/db/crdel_auto.c
 	 $(CC) $(CFLAGS) $?
+crdel_autop@o@: $(srcdir)/db/crdel_autop.c
+	 $(CC) $(CFLAGS) $?
 crdel_rec@o@: $(srcdir)/db/crdel_rec.c
 	 $(CC) $(CFLAGS) $?
 crypto@o@: $(srcdir)/crypto/crypto.c
 	 $(CC) $(CFLAGS) $?
+crypto_stub@o@: $(srcdir)/common/crypto_stub.c
+	 $(CC) $(CFLAGS) $?
 db185@o@: $(srcdir)/db185/db185.c
 	 $(CC) $(CFLAGS) $?
 db@o@: $(srcdir)/db/db.c
@@ -946,6 +1281,8 @@ db_am@o@: $(srcdir)/db/db_am.c
 	 $(CC) $(CFLAGS) $?
 db_auto@o@: $(srcdir)/db/db_auto.c
 	 $(CC) $(CFLAGS) $?
+db_autop@o@: $(srcdir)/db/db_autop.c
+	 $(CC) $(CFLAGS) $?
 db_byteorder@o@: $(srcdir)/common/db_byteorder.c
 	 $(CC) $(CFLAGS) $?
 db_cam@o@: $(srcdir)/db/db_cam.c
@@ -976,6 +1313,8 @@ db_open@o@: $(srcdir)/db/db_open.c
 	 $(CC) $(CFLAGS) $?
 db_overflow@o@: $(srcdir)/db/db_overflow.c
 	 $(CC) $(CFLAGS) $?
+db_ovfl_vrfy@o@: $(srcdir)/db/db_ovfl_vrfy.c
+	 $(CC) $(CFLAGS) $?
 db_pr@o@: $(srcdir)/db/db_pr.c
 	 $(CC) $(CFLAGS) $?
 db_rec@o@: $(srcdir)/db/db_rec.c
@@ -988,10 +1327,16 @@ db_remove@o@: $(srcdir)/db/db_remove.c
 	 $(CC) $(CFLAGS) $?
 db_ret@o@: $(srcdir)/db/db_ret.c
 	 $(CC) $(CFLAGS) $?
+db_setid@o@: $(srcdir)/db/db_setid.c
+	 $(CC) $(CFLAGS) $?
+db_setlsn@o@: $(srcdir)/db/db_setlsn.c
+	 $(CC) $(CFLAGS) $?
 db_salloc@o@: $(srcdir)/env/db_salloc.c
 	 $(CC) $(CFLAGS) $?
 db_shash@o@: $(srcdir)/env/db_shash.c
 	 $(CC) $(CFLAGS) $?
+db_stati@o@: $(srcdir)/db/db_stati.c
+	 $(CC) $(CFLAGS) $?
 db_truncate@o@: $(srcdir)/db/db_truncate.c
 	 $(CC) $(CFLAGS) $?
 db_upg@o@: $(srcdir)/db/db_upg.c
@@ -1002,14 +1347,20 @@ db_vrfy@o@: $(srcdir)/db/db_vrfy.c
 	 $(CC) $(CFLAGS) $?
 db_vrfyutil@o@: $(srcdir)/db/db_vrfyutil.c
 	 $(CC) $(CFLAGS) $?
+db_vrfy_stub@o@: $(srcdir)/db/db_vrfy_stub.c
+	$(CC) $(CFLAGS) $?
 dbm@o@: $(srcdir)/dbm/dbm.c
 	 $(CC) $(CFLAGS) $?
 dbreg@o@: $(srcdir)/dbreg/dbreg.c
 	 $(CC) $(CFLAGS) $?
 dbreg_auto@o@: $(srcdir)/dbreg/dbreg_auto.c
 	 $(CC) $(CFLAGS) $?
+dbreg_autop@o@: $(srcdir)/dbreg/dbreg_autop.c
+	 $(CC) $(CFLAGS) $?
 dbreg_rec@o@: $(srcdir)/dbreg/dbreg_rec.c
 	 $(CC) $(CFLAGS) $?
+dbreg_stat@o@: $(srcdir)/dbreg/dbreg_stat.c
+	 $(CC) $(CFLAGS) $?
 dbreg_util@o@: $(srcdir)/dbreg/dbreg_util.c
 	 $(CC) $(CFLAGS) $?
 env_file@o@: $(srcdir)/env/env_file.c
@@ -1022,8 +1373,12 @@ env_recover@o@: $(srcdir)/env/env_recover.c
 	 $(CC) $(CFLAGS) $?
 env_region@o@: $(srcdir)/env/env_region.c
 	 $(CC) $(CFLAGS) $?
+env_stat@o@: $(srcdir)/env/env_stat.c
+	 $(CC) $(CFLAGS) $?
 fileops_auto@o@: $(srcdir)/fileops/fileops_auto.c
 	 $(CC) $(CFLAGS) $?
+fileops_autop@o@: $(srcdir)/fileops/fileops_autop.c
+	 $(CC) $(CFLAGS) $?
 fop_basic@o@: $(srcdir)/fileops/fop_basic.c
 	 $(CC) $(CFLAGS) $?
 fop_rec@o@: $(srcdir)/fileops/fop_rec.c
@@ -1034,6 +1389,8 @@ hash@o@: $(srcdir)/hash/hash.c
 	 $(CC) $(CFLAGS) $?
 hash_auto@o@: $(srcdir)/hash/hash_auto.c
 	 $(CC) $(CFLAGS) $?
+hash_autop@o@: $(srcdir)/hash/hash_autop.c
+	 $(CC) $(CFLAGS) $?
 hash_conv@o@: $(srcdir)/hash/hash_conv.c
 	 $(CC) $(CFLAGS) $?
 hash_dup@o@: $(srcdir)/hash/hash_dup.c
@@ -1054,6 +1411,8 @@ hash_reclaim@o@: $(srcdir)/hash/hash_reclaim.c
 	 $(CC) $(CFLAGS) $?
 hash_stat@o@: $(srcdir)/hash/hash_stat.c
 	 $(CC) $(CFLAGS) $?
+hash_stub@o@: $(srcdir)/hash/hash_stub.c
+	 $(CC) $(CFLAGS) $?
 hash_upgrade@o@: $(srcdir)/hash/hash_upgrade.c
 	 $(CC) $(CFLAGS) $?
 hash_verify@o@: $(srcdir)/hash/hash_verify.c
@@ -1066,12 +1425,18 @@ lock@o@: $(srcdir)/lock/lock.c
 	 $(CC) $(CFLAGS) $?
 lock_deadlock@o@:$(srcdir)/lock/lock_deadlock.c
 	 $(CC) $(CFLAGS) $?
+lock_id@o@:$(srcdir)/lock/lock_id.c
+	 $(CC) $(CFLAGS) $?
+lock_list@o@:$(srcdir)/lock/lock_list.c
+	 $(CC) $(CFLAGS) $?
 lock_method@o@:$(srcdir)/lock/lock_method.c
 	 $(CC) $(CFLAGS) $?
 lock_region@o@:$(srcdir)/lock/lock_region.c
 	 $(CC) $(CFLAGS) $?
 lock_stat@o@:$(srcdir)/lock/lock_stat.c
 	 $(CC) $(CFLAGS) $?
+lock_timer@o@:$(srcdir)/lock/lock_timer.c
+	 $(CC) $(CFLAGS) $?
 lock_util@o@:$(srcdir)/lock/lock_util.c
 	 $(CC) $(CFLAGS) $?
 log@o@: $(srcdir)/log/log.c
@@ -1086,12 +1451,16 @@ log_method@o@: $(srcdir)/log/log_method.c
 	 $(CC) $(CFLAGS) $?
 log_put@o@: $(srcdir)/log/log_put.c
 	 $(CC) $(CFLAGS) $?
+log_stat@o@: $(srcdir)/log/log_stat.c
+	 $(CC) $(CFLAGS) $?
 mp_alloc@o@: $(srcdir)/mp/mp_alloc.c
 	 $(CC) $(CFLAGS) $?
 mp_bh@o@: $(srcdir)/mp/mp_bh.c
 	 $(CC) $(CFLAGS) $?
 mp_fget@o@: $(srcdir)/mp/mp_fget.c
 	 $(CC) $(CFLAGS) $?
+mp_fmethod@o@: $(srcdir)/mp/mp_fmethod.c
+	 $(CC) $(CFLAGS) $?
 mp_fopen@o@: $(srcdir)/mp/mp_fopen.c
 	 $(CC) $(CFLAGS) $?
 mp_fput@o@: $(srcdir)/mp/mp_fput.c
@@ -1118,62 +1487,68 @@ mut_pthread@o@: $(srcdir)/mutex/mut_pthread.c
 	 $(CC) $(CFLAGS) $?
 mut_tas@o@: $(srcdir)/mutex/mut_tas.c
 	 $(CC) $(CFLAGS) $?
+mut_win32@o@: $(srcdir)/mutex/mut_win32.c
+	 $(CC) $(CFLAGS) $?
 mutex@o@: $(srcdir)/mutex/mutex.c
 	 $(CC) $(CFLAGS) $?
-os_abs@o@: $(srcdir)/os/os_abs.c
+os_abs@o@: $(srcdir)/@OSDIR@/os_abs.c
 	 $(CC) $(CFLAGS) $?
 os_alloc@o@: $(srcdir)/os/os_alloc.c
 	 $(CC) $(CFLAGS) $?
-os_clock@o@: $(srcdir)/os/os_clock.c
+os_clock@o@: $(srcdir)/@OSDIR@/os_clock.c
 	 $(CC) $(CFLAGS) $?
-os_config@o@: $(srcdir)/os/os_config.c
+os_config@o@: $(srcdir)/@OSDIR@/os_config.c
 	 $(CC) $(CFLAGS) $?
-os_dir@o@: $(srcdir)/os/os_dir.c
+os_dir@o@: $(srcdir)/@OSDIR@/os_dir.c
 	 $(CC) $(CFLAGS) $?
-os_errno@o@: $(srcdir)/os/os_errno.c
+os_errno@o@: $(srcdir)/@OSDIR@/os_errno.c
 	 $(CC) $(CFLAGS) $?
-os_fid@o@: $(srcdir)/os/os_fid.c
+os_fid@o@: $(srcdir)/@OSDIR@/os_fid.c
 	 $(CC) $(CFLAGS) $?
-os_fsync@o@: $(srcdir)/os/os_fsync.c
+os_fsync@o@: $(srcdir)/@OSDIR@/os_fsync.c
 	 $(CC) $(CFLAGS) $?
 os_id@o@: $(srcdir)/os/os_id.c
 	 $(CC) $(CFLAGS) $?
-os_handle@o@: $(srcdir)/os/os_handle.c
+os_handle@o@: $(srcdir)/@OSDIR@/os_handle.c
 	 $(CC) $(CFLAGS) $?
-os_map@o@: $(srcdir)/os/os_map.c
+os_map@o@: $(srcdir)/@OSDIR@/os_map.c
 	 $(CC) $(CFLAGS) $?
 os_method@o@: $(srcdir)/os/os_method.c
 	 $(CC) $(CFLAGS) $?
 os_oflags@o@: $(srcdir)/os/os_oflags.c
 	 $(CC) $(CFLAGS) $?
-os_open@o@: $(srcdir)/os/os_open.c
+os_open@o@: $(srcdir)/@OSDIR@/os_open.c
 	 $(CC) $(CFLAGS) $?
 os_region@o@: $(srcdir)/os/os_region.c
 	 $(CC) $(CFLAGS) $?
-os_rename@o@: $(srcdir)/os/os_rename.c
+os_rename@o@: $(srcdir)/@OSDIR@/os_rename.c
 	 $(CC) $(CFLAGS) $?
 os_root@o@: $(srcdir)/os/os_root.c
 	 $(CC) $(CFLAGS) $?
 os_rpath@o@: $(srcdir)/os/os_rpath.c
 	 $(CC) $(CFLAGS) $?
-os_rw@o@: $(srcdir)/os/os_rw.c
+os_rw@o@: $(srcdir)/@OSDIR@/os_rw.c
 	 $(CC) $(CFLAGS) $?
-os_seek@o@: $(srcdir)/os/os_seek.c
+os_seek@o@: $(srcdir)/@OSDIR@/os_seek.c
 	 $(CC) $(CFLAGS) $?
-os_sleep@o@: $(srcdir)/os/os_sleep.c
+os_sleep@o@: $(srcdir)/@OSDIR@/os_sleep.c
 	 $(CC) $(CFLAGS) $?
-os_spin@o@: $(srcdir)/os/os_spin.c
+os_spin@o@: $(srcdir)/@OSDIR@/os_spin.c
 	 $(CC) $(CFLAGS) $?
-os_stat@o@: $(srcdir)/os/os_stat.c
+os_stat@o@: $(srcdir)/@OSDIR@/os_stat.c
 	 $(CC) $(CFLAGS) $?
 os_tmpdir@o@: $(srcdir)/os/os_tmpdir.c
 	 $(CC) $(CFLAGS) $?
+os_truncate@o@: $(srcdir)/@OSDIR@/os_truncate.c
+	 $(CC) $(CFLAGS) $?
 os_unlink@o@: $(srcdir)/os/os_unlink.c
 	 $(CC) $(CFLAGS) $?
 qam@o@: $(srcdir)/qam/qam.c
 	 $(CC) $(CFLAGS) $?
 qam_auto@o@: $(srcdir)/qam/qam_auto.c
 	 $(CC) $(CFLAGS) $?
+qam_autop@o@: $(srcdir)/qam/qam_autop.c
+	 $(CC) $(CFLAGS) $?
 qam_conv@o@: $(srcdir)/qam/qam_conv.c
 	 $(CC) $(CFLAGS) $?
 qam_files@o@: $(srcdir)/qam/qam_files.c
@@ -1186,28 +1561,48 @@ qam_rec@o@: $(srcdir)/qam/qam_rec.c
 	 $(CC) $(CFLAGS) $?
 qam_stat@o@: $(srcdir)/qam/qam_stat.c
 	 $(CC) $(CFLAGS) $?
+qam_stub@o@: $(srcdir)/qam/qam_stub.c
+	 $(CC) $(CFLAGS) $?
 qam_upgrade@o@: $(srcdir)/qam/qam_upgrade.c
 	 $(CC) $(CFLAGS) $?
 qam_verify@o@: $(srcdir)/qam/qam_verify.c
 	 $(CC) $(CFLAGS) $?
+rep_auto@o@: $(srcdir)/rep/rep_auto.c
+	 $(CC) $(CFLAGS) $?
+rep_autop@o@: $(srcdir)/rep/rep_autop.c
+	 $(CC) $(CFLAGS) $?
+rep_backup@o@: $(srcdir)/rep/rep_backup.c
+	 $(CC) $(CFLAGS) $?
 rep_method@o@: $(srcdir)/rep/rep_method.c
 	 $(CC) $(CFLAGS) $?
 rep_record@o@: $(srcdir)/rep/rep_record.c
 	 $(CC) $(CFLAGS) $?
 rep_region@o@: $(srcdir)/rep/rep_region.c
 	 $(CC) $(CFLAGS) $?
+rep_stub@o@: $(srcdir)/rep/rep_stub.c
+	 $(CC) $(CFLAGS) $?
+rep_stat@o@: $(srcdir)/rep/rep_stat.c
+	 $(CC) $(CFLAGS) $?
 rep_util@o@: $(srcdir)/rep/rep_util.c
 	 $(CC) $(CFLAGS) $?
 rijndael-alg-fst@o@: $(srcdir)/crypto/rijndael/rijndael-alg-fst.c
 	$(CC) $(CFLAGS) $?
 rijndael-api-fst@o@: $(srcdir)/crypto/rijndael/rijndael-api-fst.c
 	$(CC) $(CFLAGS) $?
+seq_stat@o@: $(srcdir)/sequence/seq_stat.c
+	 $(CC) $(CFLAGS) $?
+sequence@o@: $(srcdir)/sequence/sequence.c
+	 $(CC) $(CFLAGS) $?
 sha1@o@: $(srcdir)/hmac/sha1.c
 	$(CC) $(CFLAGS) $?
+stat_stub@o@: $(srcdir)/common/stat_stub.c
+	 $(CC) $(CFLAGS) $?
 txn@o@: $(srcdir)/txn/txn.c
 	 $(CC) $(CFLAGS) $?
 txn_auto@o@: $(srcdir)/txn/txn_auto.c
 	 $(CC) $(CFLAGS) $?
+txn_autop@o@: $(srcdir)/txn/txn_autop.c
+	 $(CC) $(CFLAGS) $?
 txn_method@o@: $(srcdir)/txn/txn_method.c
 	 $(CC) $(CFLAGS) $?
 txn_rec@o@: $(srcdir)/txn/txn_rec.c
@@ -1254,37 +1649,17 @@ cxx_logc@o@: $(srcdir)/cxx/cxx_logc.cpp
 	$(CXX) $(CXXFLAGS) $?
 cxx_mpool@o@: $(srcdir)/cxx/cxx_mpool.cpp
 	$(CXX) $(CXXFLAGS) $?
+cxx_multi@o@: $(srcdir)/cxx/cxx_multi.cpp
+	$(CXX) $(CXXFLAGS) $?
+cxx_seq@o@: $(srcdir)/cxx/cxx_seq.cpp
+	$(CXX) $(CXXFLAGS) $?
 cxx_txn@o@: $(srcdir)/cxx/cxx_txn.cpp
 	$(CXX) $(CXXFLAGS) $?
 
 ##################################################
 # Java API build rules.
 ##################################################
-java_Db@o@::$(srcdir)/libdb_java/java_Db.c
-	$(CC) $(CFLAGS) $?
-java_DbEnv@o@: $(srcdir)/libdb_java/java_DbEnv.c
-	$(CC) $(CFLAGS) $?
-java_DbLock@o@: $(srcdir)/libdb_java/java_DbLock.c
-	$(CC) $(CFLAGS) $?
-java_DbLogc@o@: $(srcdir)/libdb_java/java_DbLogc.c
-	$(CC) $(CFLAGS) $?
-java_DbLsn@o@: $(srcdir)/libdb_java/java_DbLsn.c
-	$(CC) $(CFLAGS) $?
-java_DbTxn@o@: $(srcdir)/libdb_java/java_DbTxn.c
-	$(CC) $(CFLAGS) $?
-java_DbUtil@o@: $(srcdir)/libdb_java/java_DbUtil.c
-	$(CC) $(CFLAGS) $?
-java_Dbc@o@: $(srcdir)/libdb_java/java_Dbc.c
-	$(CC) $(CFLAGS) $?
-java_Dbt@o@: $(srcdir)/libdb_java/java_Dbt.c
-	$(CC) $(CFLAGS) $?
-java_info@o@: $(srcdir)/libdb_java/java_info.c
-	$(CC) $(CFLAGS) $?
-java_locked@o@: $(srcdir)/libdb_java/java_locked.c
-	$(CC) $(CFLAGS) $?
-java_util@o@: $(srcdir)/libdb_java/java_util.c
-	$(CC) $(CFLAGS) $?
-java_stat_auto@o@: $(srcdir)/libdb_java/java_stat_auto.c
+db_java_wrap@o@: $(srcdir)/libdb_java/db_java_wrap.c
 	$(CC) $(CFLAGS) $?
 
 ##################################################
@@ -1310,6 +1685,8 @@ tcl_mp@o@: $(srcdir)/tcl/tcl_mp.c
 	$(CC) $(CFLAGS) $(TCFLAGS) $?
 tcl_rep@o@: $(srcdir)/tcl/tcl_rep.c
 	$(CC) $(CFLAGS) $(TCFLAGS) $?
+tcl_seq@o@: $(srcdir)/tcl/tcl_seq.c
+	$(CC) $(CFLAGS) $(TCFLAGS) $?
 tcl_txn@o@: $(srcdir)/tcl/tcl_txn.c
 	$(CC) $(CFLAGS) $(TCFLAGS) $?
 tcl_util@o@: $(srcdir)/tcl/tcl_util.c
@@ -1321,7 +1698,7 @@ tcl_util@o@: $(srcdir)/tcl/tcl_util.c
 # RPC client files
 client@o@: $(srcdir)/rpc_client/client.c
 	$(CC) $(CFLAGS) $?
-db_server_clnt@o@: $(srcdir)/rpc_client/db_server_clnt.c
+db_server_clnt@o@: db_server_clnt.c
 	$(CC) $(CFLAGS) $?
 gen_client@o@: $(srcdir)/rpc_client/gen_client.c
 	$(CC) $(CFLAGS) $?
@@ -1331,13 +1708,13 @@ gen_client_ret@o@: $(srcdir)/rpc_client/gen_client_ret.c
 # RPC server files
 db_server_proc@o@: $(srcdir)/rpc_server/c/db_server_proc.c
 	$(CC) $(CFLAGS) $?
-db_server_svc@o@: $(srcdir)/rpc_server/c/db_server_svc.c
+db_server_svc@o@: db_server_svc.c
 	$(CC) $(CFLAGS) $?
 db_server_util@o@: $(srcdir)/rpc_server/c/db_server_util.c
 	$(CC) $(CFLAGS) $?
-db_server_xdr@o@: $(srcdir)/rpc_server/c/db_server_xdr.c
+db_server_xdr@o@: db_server_xdr.c
 	$(CC) $(CFLAGS) $?
-gen_db_server@o@: $(srcdir)/rpc_server/c/gen_db_server.c
+gen_db_server@o@: gen_db_server.c
 	$(CC) $(CFLAGS) $?
 db_server_cxxproc@o@: $(srcdir)/rpc_server/cxx/db_server_cxxproc.cpp
 	$(CXX) $(CXXFLAGS) $?
@@ -1393,5 +1770,7 @@ snprintf@o@: $(srcdir)/clib/snprintf.c
 	$(CC) $(CFLAGS) $?
 strerror@o@: $(srcdir)/clib/strerror.c
 	$(CC) $(CFLAGS) $?
-vsnprintf@o@: $(srcdir)/clib/vsnprintf.c
+strtol@o@: $(srcdir)/clib/strtol.c
+	$(CC) $(CFLAGS) $?
+strtoul@o@: $(srcdir)/clib/strtoul.c
 	$(CC) $(CFLAGS) $?
diff --git a/storage/bdb/dist/RELEASE b/storage/bdb/dist/RELEASE
index 61151b8589c0953e7485b6a84d79a3e8fd0f5b92..35e16a4333b39f9dc289091f061be2408236aa83 100644
--- a/storage/bdb/dist/RELEASE
+++ b/storage/bdb/dist/RELEASE
@@ -1,28 +1,11 @@
-# $Id: RELEASE,v 11.123 2002/09/13 22:16:02 bostic Exp $
+# $Id: RELEASE,v 11.195 2004/11/09 01:30:41 bostic Exp $
 
 DB_VERSION_MAJOR=4
-DB_VERSION_MINOR=1
-DB_VERSION_PATCH=24
+DB_VERSION_MINOR=3
+DB_VERSION_PATCH=28
 DB_VERSION="$DB_VERSION_MAJOR.$DB_VERSION_MINOR.$DB_VERSION_PATCH"
 
 DB_VERSION_UNIQUE_NAME=`printf "_%d%03d" $DB_VERSION_MAJOR $DB_VERSION_MINOR`
 
 DB_RELEASE_DATE=`date "+%B %e, %Y"`
 DB_VERSION_STRING="Sleepycat Software: Berkeley DB $DB_VERSION: ($DB_RELEASE_DATE)"
-
-# this file is included by all s_* scripts, so it's the way to apply
-# hacks :)
-
-# bitkeeper doesn't like somebody to mess with permissions!
-chmod()
-{
-  echo "chmod $1 $2" >/dev/null
-}
-
-# useful trick to find auto-generated files
-#cmp()
-#{
-#  echo "==>> CMP $1 $2" >/dev/tty
-#  /usr/bin/cmp "$1" "$2"
-#}
-
diff --git a/storage/bdb/dist/aclocal/config.ac b/storage/bdb/dist/aclocal/config.ac
index cd288425946fc39e6095d30008297364aee41c61..717a0becc2f24708c82d3330b59354b0501abcd9 100644
--- a/storage/bdb/dist/aclocal/config.ac
+++ b/storage/bdb/dist/aclocal/config.ac
@@ -1,5 +1,12 @@
 # Features we don't test for, but want the #defines to exist for
 # other ports.
+AH_TEMPLATE(DB_WIN32,
+    [We use DB_WIN32 much as one would use _WIN32 -- to specify that
+    we're using an operating system environment that supports Win32
+    calls and semantics.  We don't use _WIN32 because Cygwin/GCC also
+    defines _WIN32, even though Cygwin/GCC closely emulates the Unix
+    environment.])
+
 AH_TEMPLATE(HAVE_VXWORKS, [Define to 1 if building VxWorks.])
 
 AH_TEMPLATE(HAVE_FILESYSTEM_NOTZERO,
@@ -48,4 +55,8 @@ AH_BOTTOM([/*
 #endif
 #ifndef	HAVE_VSNPRINTF
 #define	vsnprintf	__db_Cvsnprintf
+#endif
+
+#ifdef DB_WIN32
+#include "win_db.h"
 #endif])
diff --git a/storage/bdb/dist/aclocal/libtool.ac b/storage/bdb/dist/aclocal/libtool.ac
index e99faf15e4e1d1c68a5aaac35a093850a0f88853..71dae456a52ed373df415cc3721fb79ce8c4a5bd 100644
--- a/storage/bdb/dist/aclocal/libtool.ac
+++ b/storage/bdb/dist/aclocal/libtool.ac
@@ -1,5 +1,5 @@
-# libtool.m4 - Configure libtool for the host system. -*-Shell-script-*-
-## Copyright 1996, 1997, 1998, 1999, 2000, 2001
+# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
+## Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004
 ## Free Software Foundation, Inc.
 ## Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
 ##
@@ -22,10 +22,61 @@
 ## configuration script generated by Autoconf, you may include it under
 ## the same distribution terms that you use for the rest of that program.
 
-# serial 46 AC_PROG_LIBTOOL
+# serial 47 AC_PROG_LIBTOOL
 
+
+# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED)
+# -----------------------------------------------------------
+# If this macro is not defined by Autoconf, define it here.
+m4_ifdef([AC_PROVIDE_IFELSE],
+         [],
+         [m4_define([AC_PROVIDE_IFELSE],
+	         [m4_ifdef([AC_PROVIDE_$1],
+		           [$2], [$3])])])
+
+
+# AC_PROG_LIBTOOL
+# ---------------
 AC_DEFUN([AC_PROG_LIBTOOL],
+[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl
+dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX
+dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX.
+  AC_PROVIDE_IFELSE([AC_PROG_CXX],
+    [AC_LIBTOOL_CXX],
+    [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX
+  ])])
+dnl And a similar setup for Fortran 77 support
+  AC_PROVIDE_IFELSE([AC_PROG_F77],
+    [AC_LIBTOOL_F77],
+    [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77
+])])
+
+dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly.
+dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run
+dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both.
+  AC_PROVIDE_IFELSE([AC_PROG_GCJ],
+    [AC_LIBTOOL_GCJ],
+    [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
+      [AC_LIBTOOL_GCJ],
+      [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],
+	[AC_LIBTOOL_GCJ],
+      [ifdef([AC_PROG_GCJ],
+	     [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])
+       ifdef([A][M_PROG_GCJ],
+	     [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])])
+       ifdef([LT_AC_PROG_GCJ],
+	     [define([LT_AC_PROG_GCJ],
+		defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])])
+])])# AC_PROG_LIBTOOL
+
+
+# _AC_PROG_LIBTOOL
+# ----------------
+AC_DEFUN([_AC_PROG_LIBTOOL],
 [AC_REQUIRE([AC_LIBTOOL_SETUP])dnl
+AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl
+AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl
+AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl
 
 # This can be used to rebuild libtool when needed
 LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh"
@@ -36,10 +87,13 @@ AC_SUBST(LIBTOOL)dnl
 
 # Prevent multiple expansion
 define([AC_PROG_LIBTOOL], [])
-])
+])# _AC_PROG_LIBTOOL
 
+
+# AC_LIBTOOL_SETUP
+# ----------------
 AC_DEFUN([AC_LIBTOOL_SETUP],
-[AC_PREREQ(2.13)dnl
+[AC_PREREQ(2.50)dnl
 AC_REQUIRE([AC_ENABLE_SHARED])dnl
 AC_REQUIRE([AC_ENABLE_STATIC])dnl
 AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl
@@ -49,405 +103,252 @@ AC_REQUIRE([AC_PROG_CC])dnl
 AC_REQUIRE([AC_PROG_LD])dnl
 AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl
 AC_REQUIRE([AC_PROG_NM])dnl
+
 AC_REQUIRE([AC_PROG_LN_S])dnl
 AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl
+# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers!
 AC_REQUIRE([AC_OBJEXT])dnl
 AC_REQUIRE([AC_EXEEXT])dnl
 dnl
 
+AC_LIBTOOL_SYS_MAX_CMD_LEN
+AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+AC_LIBTOOL_OBJDIR
+
+AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
 _LT_AC_PROG_ECHO_BACKSLASH
-# Only perform the check for file, if the check method requires it
-case $deplibs_check_method in
-file_magic*)
-  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
-    AC_PATH_MAGIC
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test "X${COLLECT_NAMES+set}" != Xset; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
   fi
   ;;
 esac
 
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e s/^X//'
+[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g']
+
+# Same as above, but do not quote variable references.
+[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g']
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+# Constants:
+rm="rm -f"
+
+# Global variables:
+default_ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except M$VC,
+# which needs '.lib').
+libext=a
+ltmain="$ac_aux_dir/ltmain.sh"
+ofile="$default_ofile"
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+AC_CHECK_TOOL(AR, ar, false)
 AC_CHECK_TOOL(RANLIB, ranlib, :)
 AC_CHECK_TOOL(STRIP, strip, :)
 
-ifdef([AC_PROVIDE_AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no)
-ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL],
-enable_win32_dll=yes, enable_win32_dll=no)
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
 
-AC_ARG_ENABLE(libtool-lock,
-  [  --disable-libtool-lock  avoid locking (might break parallel builds)])
-test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+# Set sane defaults for various variables
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+test -z "$AS" && AS=as
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+test -z "$LD" && LD=ld
+test -z "$LN_S" && LN_S="ln -s"
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+test -z "$NM" && NM=nm
+test -z "$SED" && SED=sed
+test -z "$OBJDUMP" && OBJDUMP=objdump
+test -z "$RANLIB" && RANLIB=:
+test -z "$STRIP" && STRIP=:
+test -z "$ac_objext" && ac_objext=o
 
-# Some flags need to be propagated to the compiler or linker for good
-# libtool support.
-case $host in
-*-*-irix6*)
-  # Find out which ABI we are using.
-  echo '[#]line __oline__ "configure"' > conftest.$ac_ext
-  if AC_TRY_EVAL(ac_compile); then
-    case `/usr/bin/file conftest.$ac_objext` in
-    *32-bit*)
-      LD="${LD-ld} -32"
-      ;;
-    *N32*)
-      LD="${LD-ld} -n32"
-      ;;
-    *64-bit*)
-      LD="${LD-ld} -64"
-      ;;
-    esac
-  fi
-  rm -rf conftest*
-  ;;
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
 
-*-*-sco3.2v5*)
-  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
-  SAVE_CFLAGS="$CFLAGS"
-  CFLAGS="$CFLAGS -belf"
-  AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
-    [AC_LANG_SAVE
-     AC_LANG_C
-     AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
-     AC_LANG_RESTORE])
-  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
-    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
-    CFLAGS="$SAVE_CFLAGS"
-  fi
-  ;;
+if test -n "$RANLIB"; then
+  case $host_os in
+  openbsd*)
+    old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds"
+    ;;
+  *)
+    old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
 
-ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL],
-[*-*-cygwin* | *-*-mingw* | *-*-pw32*)
-  AC_CHECK_TOOL(DLLTOOL, dlltool, false)
-  AC_CHECK_TOOL(AS, as, false)
-  AC_CHECK_TOOL(OBJDUMP, objdump, false)
+cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'`
 
-  # recent cygwin and mingw systems supply a stub DllMain which the user
-  # can override, but on older systems we have to supply one
-  AC_CACHE_CHECK([if libtool should supply DllMain function], lt_cv_need_dllmain,
-    [AC_TRY_LINK([],
-      [extern int __attribute__((__stdcall__)) DllMain(void*, int, void*);
-      DllMain (0, 0, 0);],
-      [lt_cv_need_dllmain=no],[lt_cv_need_dllmain=yes])])
-
-  case $host/$CC in
-  *-*-cygwin*/gcc*-mno-cygwin*|*-*-mingw*)
-    # old mingw systems require "-dll" to link a DLL, while more recent ones
-    # require "-mdll"
-    SAVE_CFLAGS="$CFLAGS"
-    CFLAGS="$CFLAGS -mdll"
-    AC_CACHE_CHECK([how to link DLLs], lt_cv_cc_dll_switch,
-      [AC_TRY_LINK([], [], [lt_cv_cc_dll_switch=-mdll],[lt_cv_cc_dll_switch=-dll])])
-    CFLAGS="$SAVE_CFLAGS" ;;
-  *-*-cygwin* | *-*-pw32*)
-    # cygwin systems need to pass --dll to the linker, and not link
-    # crt.o which will require a WinMain@16 definition.
-    lt_cv_cc_dll_switch="-Wl,--dll -nostartfiles" ;;
-  esac
+# Only perform the check for file, if the check method requires it
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    AC_PATH_MAGIC
+  fi
   ;;
-  ])
 esac
 
-_LT_AC_LTCONFIG_HACK
-
-])
-
-# AC_LIBTOOL_HEADER_ASSERT
-# ------------------------
-AC_DEFUN([AC_LIBTOOL_HEADER_ASSERT],
-[AC_CACHE_CHECK([whether $CC supports assert without backlinking],
-    [lt_cv_func_assert_works],
-    [case $host in
-    *-*-solaris*)
-      if test "$GCC" = yes && test "$with_gnu_ld" != yes; then
-        case `$CC --version 2>/dev/null` in
-        [[12]].*) lt_cv_func_assert_works=no ;;
-        *)        lt_cv_func_assert_works=yes ;;
-        esac
-      fi
-      ;;
-    esac])
+AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no)
+AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL],
+enable_win32_dll=yes, enable_win32_dll=no)
 
-if test "x$lt_cv_func_assert_works" = xyes; then
-  AC_CHECK_HEADERS(assert.h)
-fi
-])# AC_LIBTOOL_HEADER_ASSERT
+AC_ARG_ENABLE([libtool-lock],
+    [AC_HELP_STRING([--disable-libtool-lock],
+	[avoid locking (might break parallel builds)])])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
 
-# _LT_AC_CHECK_DLFCN
-# --------------------
-AC_DEFUN([_LT_AC_CHECK_DLFCN],
-[AC_CHECK_HEADERS(dlfcn.h)
-])# _LT_AC_CHECK_DLFCN
+AC_ARG_WITH([pic],
+    [AC_HELP_STRING([--with-pic],
+	[try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
+    [pic_mode="$withval"],
+    [pic_mode=default])
+test -z "$pic_mode" && pic_mode=default
 
-# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
-# ---------------------------------
-AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE],
-[AC_REQUIRE([AC_CANONICAL_HOST])
-AC_REQUIRE([AC_PROG_NM])
-AC_REQUIRE([AC_OBJEXT])
-# Check for command to grab the raw symbol name followed by C symbol from nm.
-AC_MSG_CHECKING([command to parse $NM output])
-AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [dnl
+# Use C for the default configuration in the libtool script
+tagname=
+AC_LIBTOOL_LANG_C_CONFIG
+_LT_AC_TAGCONFIG
+])# AC_LIBTOOL_SETUP
 
-# These are sane defaults that work on at least a few old systems.
-# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
 
-# Character class describing NM global symbol codes.
-symcode='[[BCDEGRST]]'
+# _LT_AC_SYS_COMPILER
+# -------------------
+AC_DEFUN([_LT_AC_SYS_COMPILER],
+[AC_REQUIRE([AC_PROG_CC])dnl
 
-# Regexp to match symbols that can be accessed directly from C.
-sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
 
-# Transform the above into a raw symbol and a C symbol.
-symxfrm='\1 \2\3 \3'
+# Allow CC to be a program name with arguments.
+compiler=$CC
+])# _LT_AC_SYS_COMPILER
+
+
+# _LT_AC_SYS_LIBPATH_AIX
+# ----------------------
+# Links a minimal program and checks the executable
+# for the system default hardcoded library path. In most cases,
+# this is /usr/lib:/lib, but when the MPI compilers are used
+# the location of the communication and MPI libs are included too.
+# If we don't find anything, use the default library path according
+# to the aix ld manual.
+AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX],
+[AC_LINK_IFELSE(AC_LANG_PROGRAM,[
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0  *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0  *\(.*\)$/\1/; p; }
+}'`; fi],[])
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+])# _LT_AC_SYS_LIBPATH_AIX
+
+
+# _LT_AC_SHELL_INIT(ARG)
+# ----------------------
+AC_DEFUN([_LT_AC_SHELL_INIT],
+[ifdef([AC_DIVERSION_NOTICE],
+	     [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)],
+	 [AC_DIVERT_PUSH(NOTICE)])
+$1
+AC_DIVERT_POP
+])# _LT_AC_SHELL_INIT
 
-# Transform an extracted symbol line into a proper C declaration
-lt_cv_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'"
 
-# Transform an extracted symbol line into symbol name and symbol address
-lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/  {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/  {\"\2\", (lt_ptr) \&\2},/p'"
+# _LT_AC_PROG_ECHO_BACKSLASH
+# --------------------------
+# Add some code to the start of the generated configure script which
+# will find an echo command which doesn't interpret backslashes.
+AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH],
+[_LT_AC_SHELL_INIT([
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
 
-# Define system-specific variables.
-case $host_os in
-aix*)
-  symcode='[[BCDT]]'
-  ;;
-cygwin* | mingw* | pw32*)
-  symcode='[[ABCDGISTW]]'
-  ;;
-hpux*) # Its linker distinguishes data from code symbols
-  lt_cv_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
-  lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/  {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"\2\", (lt_ptr) \&\2},/p'"
-  ;;
-irix*)
-  symcode='[[BCDEGRST]]'
-  ;;
-solaris* | sysv5*)
-  symcode='[[BDT]]'
-  ;;
-sysv4)
-  symcode='[[DFNSTU]]'
+case X$ECHO in
+X*--fallback-echo)
+  # Remove one level of quotation (which was required for Make).
+  ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','`
   ;;
 esac
 
-# Handle CRLF in mingw tool chain
-opt_cr=
-case $host_os in
-mingw*)
-  opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp
-  ;;
-esac
+echo=${ECHO-echo}
+if test "X[$]1" = X--no-reexec; then
+  # Discard the --no-reexec flag, and continue.
+  shift
+elif test "X[$]1" = X--fallback-echo; then
+  # Avoid inline document here, it may be left over
+  :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then
+  # Yippee, $echo works!
+  :
+else
+  # Restart under the correct shell.
+  exec $SHELL "[$]0" --no-reexec ${1+"[$]@"}
+fi
 
-# If we're using GNU nm, then use its standard symbol codes.
-if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then
-  symcode='[[ABCDGISTW]]'
+if test "X[$]1" = X--fallback-echo; then
+  # used as fallback echo
+  shift
+  cat <<EOF
+[$]*
+EOF
+  exit 0
 fi
 
-# Try without a prefix undercore, then with it.
-for ac_symprfx in "" "_"; do
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
 
-  # Write the raw and C identifiers.
-lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ 	]]\($symcode$symcode*\)[[ 	]][[ 	]]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'"
+if test -z "$ECHO"; then
+if test "X${echo_test_string+set}" != Xset; then
+# find a string as large as possible, as long as the shell can cope with it
+  for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do
+    # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+    if (echo_test_string="`eval $cmd`") 2>/dev/null &&
+       echo_test_string="`eval $cmd`" &&
+       (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
+    then
+      break
+    fi
+  done
+fi
 
-  # Check to see that the pipe works correctly.
-  pipe_works=no
-  rm -f conftest*
-  cat > conftest.$ac_ext <<EOF
-#ifdef __cplusplus
-extern "C" {
-#endif
-char nm_test_var;
-void nm_test_func(){}
-#ifdef __cplusplus
-}
-#endif
-int main(){nm_test_var='a';nm_test_func();return(0);}
-EOF
+if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+   echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+   test "X$echo_testing_string" = "X$echo_test_string"; then
+  :
+else
+  # The Solaris, AIX, and Digital Unix default echo programs unquote
+  # backslashes.  This makes it impossible to quote backslashes using
+  #   echo "$something" | sed 's/\\/\\\\/g'
+  #
+  # So, first we look for a working echo in the user's PATH.
 
-  if AC_TRY_EVAL(ac_compile); then
-    # Now try to grab the symbols.
-    nlist=conftest.nm
-    if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then
-      # Try sorting and uniquifying the output.
-      if sort "$nlist" | uniq > "$nlist"T; then
-	mv -f "$nlist"T "$nlist"
-      else
-	rm -f "$nlist"T
-      fi
-
-      # Make sure that we snagged all the symbols we need.
-      if egrep ' nm_test_var$' "$nlist" >/dev/null; then
-	if egrep ' nm_test_func$' "$nlist" >/dev/null; then
-	  cat <<EOF > conftest.$ac_ext
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-EOF
-	  # Now generate the symbol file.
-	  eval "$lt_cv_global_symbol_to_cdecl"' < "$nlist" >> conftest.$ac_ext'
-
-	  cat <<EOF >> conftest.$ac_ext
-#if defined (__STDC__) && __STDC__
-# define lt_ptr void *
-#else
-# define lt_ptr char *
-# define const
-#endif
-
-/* The mapping between symbol names and symbols. */
-const struct {
-  const char *name;
-  lt_ptr address;
-}
-lt_preloaded_symbols[[]] =
-{
-EOF
-	  sed "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (lt_ptr) \&\2},/" < "$nlist" >> conftest.$ac_ext
-	  cat <<\EOF >> conftest.$ac_ext
-  {0, (lt_ptr) 0}
-};
-
-#ifdef __cplusplus
-}
-#endif
-EOF
-	  # Now try linking the two files.
-	  mv conftest.$ac_objext conftstm.$ac_objext
-	  save_LIBS="$LIBS"
-	  save_CFLAGS="$CFLAGS"
-	  LIBS="conftstm.$ac_objext"
-	  CFLAGS="$CFLAGS$no_builtin_flag"
-	  if AC_TRY_EVAL(ac_link) && test -s conftest; then
-	    pipe_works=yes
-	  fi
-	  LIBS="$save_LIBS"
-	  CFLAGS="$save_CFLAGS"
-	else
-	  echo "cannot find nm_test_func in $nlist" >&AC_FD_CC
-	fi
-      else
-	echo "cannot find nm_test_var in $nlist" >&AC_FD_CC
-      fi
-    else
-      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AC_FD_CC
-    fi
-  else
-    echo "$progname: failed program was:" >&AC_FD_CC
-    cat conftest.$ac_ext >&5
-  fi
-  rm -f conftest* conftst*
-
-  # Do not use the global_symbol_pipe unless it works.
-  if test "$pipe_works" = yes; then
-    break
-  else
-    lt_cv_sys_global_symbol_pipe=
-  fi
-done
-])
-global_symbol_pipe="$lt_cv_sys_global_symbol_pipe"
-if test -z "$lt_cv_sys_global_symbol_pipe"; then
-  global_symbol_to_cdecl=
-  global_symbol_to_c_name_address=
-else
-  global_symbol_to_cdecl="$lt_cv_global_symbol_to_cdecl"
-  global_symbol_to_c_name_address="$lt_cv_global_symbol_to_c_name_address"
-fi
-if test -z "$global_symbol_pipe$global_symbol_to_cdec$global_symbol_to_c_name_address";
-then
-  AC_MSG_RESULT(failed)
-else
-  AC_MSG_RESULT(ok)
-fi
-]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
-
-# _LT_AC_LIBTOOL_SYS_PATH_SEPARATOR
-# ---------------------------------
-AC_DEFUN([_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR],
-[# Find the correct PATH separator.  Usually this is `:', but
-# DJGPP uses `;' like DOS.
-if test "X${PATH_SEPARATOR+set}" != Xset; then
-  UNAME=${UNAME-`uname 2>/dev/null`}
-  case X$UNAME in
-    *-DOS) lt_cv_sys_path_separator=';' ;;
-    *)     lt_cv_sys_path_separator=':' ;;
-  esac
-  PATH_SEPARATOR=$lt_cv_sys_path_separator
-fi
-])# _LT_AC_LIBTOOL_SYS_PATH_SEPARATOR
-
-# _LT_AC_PROG_ECHO_BACKSLASH
-# --------------------------
-# Add some code to the start of the generated configure script which
-# will find an echo command which doesn't interpret backslashes.
-AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH],
-[ifdef([AC_DIVERSION_NOTICE], [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)],
-			      [AC_DIVERT_PUSH(NOTICE)])
-_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR
-
-# Check that we are running under the correct shell.
-SHELL=${CONFIG_SHELL-/bin/sh}
-
-case X$ECHO in
-X*--fallback-echo)
-  # Remove one level of quotation (which was required for Make).
-  ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','`
-  ;;
-esac
-
-echo=${ECHO-echo}
-if test "X[$]1" = X--no-reexec; then
-  # Discard the --no-reexec flag, and continue.
-  shift
-elif test "X[$]1" = X--fallback-echo; then
-  # Avoid inline document here, it may be left over
-  :
-elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
-  # Yippee, $echo works!
-  :
-else
-  # Restart under the correct shell.
-  exec $SHELL "[$]0" --no-reexec ${1+"[$]@"}
-fi
-
-if test "X[$]1" = X--fallback-echo; then
-  # used as fallback echo
-  shift
-  cat <<EOF
-$*
-EOF
-  exit 0
-fi
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
-
-if test -z "$ECHO"; then
-if test "X${echo_test_string+set}" != Xset; then
-# find a string as large as possible, as long as the shell can cope with it
-  for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do
-    # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
-    if (echo_test_string="`eval $cmd`") 2>/dev/null &&
-       echo_test_string="`eval $cmd`" &&
-       (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
-    then
-      break
-    fi
-  done
-fi
-
-if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
-   echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
-   test "X$echo_testing_string" = "X$echo_test_string"; then
-  :
-else
-  # The Solaris, AIX, and Digital Unix default echo programs unquote
-  # backslashes.  This makes it impossible to quote backslashes using
-  #   echo "$something" | sed 's/\\/\\\\/g'
-  #
-  # So, first we look for a working echo in the user's PATH.
-
-  IFS="${IFS= 	}"; save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
   for dir in $PATH /usr/ucb; do
+    IFS="$lt_save_ifs"
     if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
        test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
        echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
@@ -456,7 +357,7 @@ else
       break
     fi
   done
-  IFS="$save_ifs"
+  IFS="$lt_save_ifs"
 
   if test "X$echo" = Xecho; then
     # We didn't find a better echo, so look for alternatives.
@@ -529,41 +430,336 @@ if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then
 fi
 
 AC_SUBST(ECHO)
-AC_DIVERT_POP
-])# _LT_AC_PROG_ECHO_BACKSLASH
+])])# _LT_AC_PROG_ECHO_BACKSLASH
 
-# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
-#                           ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
-# ------------------------------------------------------------------
-AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF],
-[if test "$cross_compiling" = yes; then :
-  [$4]
+
+# _LT_AC_LOCK
+# -----------
+AC_DEFUN([_LT_AC_LOCK],
+[AC_ARG_ENABLE([libtool-lock],
+    [AC_HELP_STRING([--disable-libtool-lock],
+	[avoid locking (might break parallel builds)])])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.$ac_objext` in
+    *ELF-32*)
+      HPUX_IA64_MODE="32"
+      ;;
+    *ELF-64*)
+      HPUX_IA64_MODE="64"
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '[#]line __oline__ "configure"' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+   if test "$lt_cv_prog_gnu_ld" = yes; then
+    case `/usr/bin/file conftest.$ac_objext` in
+    *32-bit*)
+      LD="${LD-ld} -melf32bsmip"
+      ;;
+    *N32*)
+      LD="${LD-ld} -melf32bmipn32"
+      ;;
+    *64-bit*)
+      LD="${LD-ld} -melf64bmip"
+      ;;
+    esac
+   else
+    case `/usr/bin/file conftest.$ac_objext` in
+    *32-bit*)
+      LD="${LD-ld} -32"
+      ;;
+    *N32*)
+      LD="${LD-ld} -n32"
+      ;;
+    *64-bit*)
+      LD="${LD-ld} -64"
+      ;;
+    esac
+   fi
+  fi
+  rm -rf conftest*
+  ;;
+
+x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case "`/usr/bin/file conftest.o`" in
+    *32-bit*)
+      case $host in
+        x86_64-*linux*)
+          LD="${LD-ld} -m elf_i386"
+          ;;
+        ppc64-*linux*|powerpc64-*linux*)
+          LD="${LD-ld} -m elf32ppclinux"
+          ;;
+        s390x-*linux*)
+          LD="${LD-ld} -m elf_s390"
+          ;;
+        sparc64-*linux*)
+          LD="${LD-ld} -m elf32_sparc"
+          ;;
+      esac
+      ;;
+    *64-bit*)
+      case $host in
+        x86_64-*linux*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
+        ppc*-*linux*|powerpc*-*linux*)
+          LD="${LD-ld} -m elf64ppc"
+          ;;
+        s390*-*linux*)
+          LD="${LD-ld} -m elf64_s390"
+          ;;
+        sparc*-*linux*)
+          LD="${LD-ld} -m elf64_sparc"
+          ;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+    [AC_LANG_PUSH(C)
+     AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+     AC_LANG_POP])
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL],
+[*-*-cygwin* | *-*-mingw* | *-*-pw32*)
+  AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+  AC_CHECK_TOOL(AS, as, false)
+  AC_CHECK_TOOL(OBJDUMP, objdump, false)
+  ;;
+  ])
+esac
+
+need_locks="$enable_libtool_lock"
+
+])# _LT_AC_LOCK
+
+
+# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+#		[OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION],
+[AC_REQUIRE([LT_AC_PROG_SED])
+AC_CACHE_CHECK([$1], [$2],
+  [$2=no
+  ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
+   printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$3"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&AS_MESSAGE_LOG_FD
+   echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test ! -s conftest.err; then
+       $2=yes
+     fi
+   fi
+   $rm conftest*
+])
+
+if test x"[$]$2" = xyes; then
+    ifelse([$5], , :, [$5])
 else
-  AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
-  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
-  lt_status=$lt_dlunknown
-  cat > conftest.$ac_ext <<EOF
-[#line __oline__ "configure"
-#include "confdefs.h"
+    ifelse([$6], , :, [$6])
+fi
+])# AC_LIBTOOL_COMPILER_OPTION
+
+
+# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+#                          [ACTION-SUCCESS], [ACTION-FAILURE])
+# ------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([AC_LIBTOOL_LINKER_OPTION],
+[AC_CACHE_CHECK([$1], [$2],
+  [$2=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $3"
+   printf "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&AS_MESSAGE_LOG_FD
+     else
+       $2=yes
+     fi
+   fi
+   $rm conftest*
+   LDFLAGS="$save_LDFLAGS"
+])
 
-#if HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
+if test x"[$]$2" = xyes; then
+    ifelse([$4], , :, [$4])
+else
+    ifelse([$5], , :, [$5])
+fi
+])# AC_LIBTOOL_LINKER_OPTION
 
-#include <stdio.h>
 
-#ifdef RTLD_GLOBAL
-#  define LT_DLGLOBAL		RTLD_GLOBAL
-#else
-#  ifdef DL_GLOBAL
-#    define LT_DLGLOBAL		DL_GLOBAL
-#  else
-#    define LT_DLGLOBAL		0
-#  endif
-#endif
+# AC_LIBTOOL_SYS_MAX_CMD_LEN
+# --------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN],
+[# find the maximum length of command line arguments
+AC_MSG_CHECKING([the maximum length of command line arguments])
+AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
+  i=0
+  teststring="ABCD"
+
+  case $build_os in
+  msdosdjgpp*)
+    # On DJGPP, this test can blow up pretty badly due to problems in libc
+    # (any single argument exceeding 2000 bytes causes a buffer overrun
+    # during glob expansion).  Even if it were fixed, the result of this
+    # check would be larger than it should be.
+    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
+    ;;
 
-/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
-   find out it does not work in some platform. */
+  gnu*)
+    # Under GNU Hurd, this test is not required because there is
+    # no limit to the length of command line arguments.
+    # Libtool will interpret -1 as no limit whatsoever
+    lt_cv_sys_max_cmd_len=-1;
+    ;;
+
+  cygwin* | mingw*)
+    # On Win9x/ME, this test blows up -- it succeeds, but takes
+    # about 5 minutes as the teststring grows exponentially.
+    # Worse, since 9x/ME are not pre-emptively multitasking,
+    # you end up with a "frozen" computer, even though with patience
+    # the test eventually succeeds (with a max line length of 256k).
+    # Instead, let's just punt: use the minimum linelength reported by
+    # all of the supported platforms: 8192 (on NT/2K/XP).
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  amigaos*)
+    # On AmigaOS with pdksh, this test takes hours, literally.
+    # So we just punt and use a minimum line length of 8192.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  netbsd* | freebsd* | openbsd* | darwin* )
+    # This has been around since 386BSD, at least.  Likely further.
+    if test -x /sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+    elif test -x /usr/sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+    else
+      lt_cv_sys_max_cmd_len=65536 # usable default for *BSD
+    fi
+    # And add a safety zone
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+    ;;
+
+ *)
+    # If test is not a shell built-in, we'll probably end up computing a
+    # maximum length that is only half of the actual maximum length, but
+    # we can't tell.
+    SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+    while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \
+	       = "XX$teststring") >/dev/null 2>&1 &&
+	    new_result=`expr "X$teststring" : ".*" 2>&1` &&
+	    lt_cv_sys_max_cmd_len=$new_result &&
+	    test $i != 17 # 1/2 MB should be enough
+    do
+      i=`expr $i + 1`
+      teststring=$teststring$teststring
+    done
+    teststring=
+    # Add a significant safety factor because C++ compilers can tack on massive
+    # amounts of additional arguments before passing them to the linker.
+    # It appears as though 1/2 is a usable value.
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+    ;;
+  esac
+])
+if test -n $lt_cv_sys_max_cmd_len ; then
+  AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
+else
+  AC_MSG_RESULT(none)
+fi
+])# AC_LIBTOOL_SYS_MAX_CMD_LEN
+
+
+# _LT_AC_CHECK_DLFCN
+# --------------------
+AC_DEFUN([_LT_AC_CHECK_DLFCN],
+[AC_CHECK_HEADERS(dlfcn.h)dnl
+])# _LT_AC_CHECK_DLFCN
+
+
+# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+#                           ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+# ------------------------------------------------------------------
+AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF],
+[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
+if test "$cross_compiling" = yes; then :
+  [$4]
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<EOF
+[#line __oline__ "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL		RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL		DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL		0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
 #ifndef LT_DLLAZY_OR_NOW
 #  ifdef RTLD_LAZY
 #    define LT_DLLAZY_OR_NOW		RTLD_LAZY
@@ -620,10 +816,12 @@ fi
 rm -fr conftest*
 ])# _LT_AC_TRY_DLOPEN_SELF
 
+
 # AC_LIBTOOL_DLOPEN_SELF
 # -------------------
 AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF],
-[if test "x$enable_dlopen" != xyes; then
+[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
+if test "x$enable_dlopen" != xyes; then
   enable_dlopen=unknown
   enable_dlopen_self=unknown
   enable_dlopen_self_static=unknown
@@ -638,24 +836,39 @@ else
     lt_cv_dlopen_self=yes
     ;;
 
-  cygwin* | mingw* | pw32*)
+  mingw* | pw32*)
     lt_cv_dlopen="LoadLibrary"
     lt_cv_dlopen_libs=
    ;;
 
+  cygwin*)
+    lt_cv_dlopen="dlopen"
+    lt_cv_dlopen_libs=
+   ;;
+
+  darwin*)
+  # if libdl is installed we need to link against it
+    AC_CHECK_LIB([dl], [dlopen],
+		[lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[
+    lt_cv_dlopen="dyld"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ])
+   ;;
+
   *)
     AC_CHECK_FUNC([shl_load],
-          [lt_cv_dlopen="shl_load"],
+	  [lt_cv_dlopen="shl_load"],
       [AC_CHECK_LIB([dld], [shl_load],
-            [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"],
+	    [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"],
 	[AC_CHECK_FUNC([dlopen],
 	      [lt_cv_dlopen="dlopen"],
 	  [AC_CHECK_LIB([dl], [dlopen],
-	        [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
+		[lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
 	    [AC_CHECK_LIB([svld], [dlopen],
-	          [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
+		  [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
 	      [AC_CHECK_LIB([dld], [dld_link],
-	            [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"])
+		    [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"])
 	      ])
 	    ])
 	  ])
@@ -673,7 +886,6 @@ else
   case $lt_cv_dlopen in
   dlopen)
     save_CPPFLAGS="$CPPFLAGS"
-    AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
     test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
 
     save_LDFLAGS="$LDFLAGS"
@@ -717,736 +929,1809 @@ else
 fi
 ])# AC_LIBTOOL_DLOPEN_SELF
 
-AC_DEFUN([_LT_AC_LTCONFIG_HACK],
-[AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])dnl
-# Sed substitution that helps us do robust quoting.  It backslashifies
-# metacharacters that are still active within double-quoted strings.
-Xsed='sed -e s/^X//'
-sed_quote_subst='s/\([[\\"\\`$\\\\]]\)/\\\1/g'
-
-# Same as above, but do not quote variable references.
-double_quote_subst='s/\([[\\"\\`\\\\]]\)/\\\1/g'
-
-# Sed substitution to delay expansion of an escaped shell variable in a
-# double_quote_subst'ed string.
-delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
 
-# Constants:
-rm="rm -f"
+# AC_LIBTOOL_PROG_CC_C_O([TAGNAME])
+# ---------------------------------
+# Check to see if options -c and -o are simultaneously supported by compiler
+AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O],
+[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
+AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
+  [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
+  [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
+   $rm -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&AS_MESSAGE_LOG_FD
+   echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test ! -s out/conftest.err; then
+       _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+     fi
+   fi
+   chmod u+w .
+   $rm conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+   $rm out/* && rmdir out
+   cd ..
+   rmdir conftest
+   $rm conftest*
+])
+])# AC_LIBTOOL_PROG_CC_C_O
 
-# Global variables:
-default_ofile=libtool
-can_build_shared=yes
 
-# All known linkers require a `.a' archive for static linking (except M$VC,
-# which needs '.lib').
-libext=a
-ltmain="$ac_aux_dir/ltmain.sh"
-ofile="$default_ofile"
-with_gnu_ld="$lt_cv_prog_gnu_ld"
-need_locks="$enable_libtool_lock"
+# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME])
+# -----------------------------------------
+# Check to see if we can do hard links to lock some files if needed
+AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS],
+[AC_REQUIRE([_LT_AC_LOCK])dnl
 
-old_CC="$CC"
-old_CFLAGS="$CFLAGS"
+hard_links="nottested"
+if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  AC_MSG_CHECKING([if we can lock with hard links])
+  hard_links=yes
+  $rm conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  AC_MSG_RESULT([$hard_links])
+  if test "$hard_links" = no; then
+    AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe])
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS
 
-# Set sane defaults for various variables
-test -z "$AR" && AR=ar
-test -z "$AR_FLAGS" && AR_FLAGS=cru
-test -z "$AS" && AS=as
-test -z "$CC" && CC=cc
-test -z "$DLLTOOL" && DLLTOOL=dlltool
-test -z "$LD" && LD=ld
-test -z "$LN_S" && LN_S="ln -s"
-test -z "$MAGIC_CMD" && MAGIC_CMD=file
-test -z "$NM" && NM=nm
-test -z "$OBJDUMP" && OBJDUMP=objdump
-test -z "$RANLIB" && RANLIB=:
-test -z "$STRIP" && STRIP=:
-test -z "$ac_objext" && ac_objext=o
 
-if test x"$host" != x"$build"; then
-  ac_tool_prefix=${host_alias}-
+# AC_LIBTOOL_OBJDIR
+# -----------------
+AC_DEFUN([AC_LIBTOOL_OBJDIR],
+[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
+[rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  lt_cv_objdir=.libs
 else
-  ac_tool_prefix=
+  # MS-DOS does not allow filenames that begin with a dot.
+  lt_cv_objdir=_libs
 fi
+rmdir .libs 2>/dev/null])
+objdir=$lt_cv_objdir
+])# AC_LIBTOOL_OBJDIR
 
-# Transform linux* to *-*-linux-gnu*, to support old configure scripts.
-case $host_os in
-linux-gnu*) ;;
-linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
-esac
 
-case $host_os in
-aix3*)
-  # AIX sometimes has problems with the GCC collect2 program.  For some
-  # reason, if we set the COLLECT_NAMES environment variable, the problems
-  # vanish in a puff of smoke.
-  if test "X${COLLECT_NAMES+set}" != Xset; then
-    COLLECT_NAMES=
-    export COLLECT_NAMES
+# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME])
+# ----------------------------------------------
+# Check hardcoding attributes.
+AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH],
+[AC_MSG_CHECKING([how to hardcode library paths into programs])
+_LT_AC_TAGVAR(hardcode_action, $1)=
+if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \
+   test -n "$_LT_AC_TAGVAR(runpath_var, $1)" || \
+   test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then
+
+  # We can hardcode non-existant directories.
+  if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no &&
+     test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then
+    # Linking always hardcodes the temporary library directory.
+    _LT_AC_TAGVAR(hardcode_action, $1)=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    _LT_AC_TAGVAR(hardcode_action, $1)=immediate
   fi
-  ;;
-esac
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  _LT_AC_TAGVAR(hardcode_action, $1)=unsupported
+fi
+AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)])
 
-# Determine commands to create old-style static archives.
-old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs'
-old_postinstall_cmds='chmod 644 $oldlib'
-old_postuninstall_cmds=
+if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH
 
-if test -n "$RANLIB"; then
+
+# AC_LIBTOOL_SYS_LIB_STRIP
+# ------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP],
+[striplib=
+old_striplib=
+AC_MSG_CHECKING([whether stripping libraries is possible])
+if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+  AC_MSG_RESULT([yes])
+else
+# FIXME - insert some real tests, host_os isn't really good enough
   case $host_os in
-  openbsd*)
-    old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds"
-    ;;
-  *)
-    old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds"
+   darwin*)
+       if test -n "$STRIP" ; then
+         striplib="$STRIP -x"
+         AC_MSG_RESULT([yes])
+       else
+  AC_MSG_RESULT([no])
+fi
+       ;;
+   *)
+  AC_MSG_RESULT([no])
     ;;
   esac
-  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
 fi
+])# AC_LIBTOOL_SYS_LIB_STRIP
 
-# Allow CC to be a program name with arguments.
-set dummy $CC
-compiler="[$]2"
 
-## FIXME: this should be a separate macro
-##
-AC_MSG_CHECKING([for objdir])
-rm -f .libs 2>/dev/null
-mkdir .libs 2>/dev/null
-if test -d .libs; then
-  objdir=.libs
+# AC_LIBTOOL_SYS_DYNAMIC_LINKER
+# -----------------------------
+# PORTME Fill in your ld.so characteristics
+AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER],
+[AC_MSG_CHECKING([dynamic linker characteristics])
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+if test "$GCC" = yes; then
+  sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+  if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
+    # if the path contains ";" then we assume it to be the separator
+    # otherwise default to the standard path separator (i.e. ":") - it is
+    # assumed that no part of a normal pathname contains ";" but that should
+    # okay in the real world where ";" in dirpaths is itself problematic.
+    sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+  else
+    sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
+  fi
 else
-  # MS-DOS does not allow filenames that begin with a dot.
-  objdir=_libs
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
 fi
-rmdir .libs 2>/dev/null
-AC_MSG_RESULT($objdir)
-##
-## END FIXME
-
+need_lib_prefix=unknown
+hardcode_into_libs=no
 
-## FIXME: this should be a separate macro
-##
-AC_ARG_WITH(pic,
-[  --with-pic              try to use only PIC/non-PIC objects [default=use both]],
-pic_mode="$withval", pic_mode=default)
-test -z "$pic_mode" && pic_mode=default
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
 
-# We assume here that the value for lt_cv_prog_cc_pic will not be cached
-# in isolation, and that seeing it set (from the cache) indicates that
-# the associated values are set (in the cache) correctly too.
-AC_MSG_CHECKING([for $compiler option to produce PIC])
-AC_CACHE_VAL(lt_cv_prog_cc_pic,
-[ lt_cv_prog_cc_pic=
-  lt_cv_prog_cc_shlib=
-  lt_cv_prog_cc_wl=
-  lt_cv_prog_cc_static=
-  lt_cv_prog_cc_no_builtin=
-  lt_cv_prog_cc_can_build_shared=$can_build_shared
+case $host_os in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+  shlibpath_var=LIBPATH
 
-  if test "$GCC" = yes; then
-    lt_cv_prog_cc_wl='-Wl,'
-    lt_cv_prog_cc_static='-static'
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}${shared_ext}$major'
+  ;;
 
+aix4* | aix5*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
     case $host_os in
-    aix*)
-      # Below there is a dirty hack to force normal static linking with -ldl
-      # The problem is because libdl dynamically linked with both libc and
-      # libC (AIX C++ library), which obviously doesn't included in libraries
-      # list by gcc. This cause undefined symbols with -static flags.
-      # This hack allows C programs to be linked with "-static -ldl", but
-      # not sure about C++ programs.
-      lt_cv_prog_cc_static="$lt_cv_prog_cc_static ${lt_cv_prog_cc_wl}-lC"
-      ;;
-    amigaos*)
-      # FIXME: we need at least 68020 code to build shared libraries, but
-      # adding the `-m68020' flag to GCC prevents building anything better,
-      # like `-m68040'.
-      lt_cv_prog_cc_pic='-m68020 -resident32 -malways-restore-a4'
-      ;;
-    beos* | irix5* | irix6* | osf3* | osf4* | osf5*)
-      # PIC is the default for these OSes.
-      ;;
-    darwin* | rhapsody*)
-      # PIC is the default on this platform
-      # Common symbols not allowed in MH_DYLIB files
-      lt_cv_prog_cc_pic='-fno-common'
-      ;;
-    cygwin* | mingw* | pw32* | os2*)
-      # This hack is so that the source file can tell whether it is being
-      # built for inclusion in a dll (and should export symbols for example).
-      lt_cv_prog_cc_pic='-DDLL_EXPORT'
-      ;;
-    sysv4*MP*)
-      if test -d /usr/nec; then
-	 lt_cv_prog_cc_pic=-Kconform_pic
+      aix4 | aix4.[[01]] | aix4.[[01]].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+	   echo ' yes '
+	   echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+	:
+      else
+	can_build_shared=no
       fi
       ;;
-    *)
-      lt_cv_prog_cc_pic='-fPIC'
-      ;;
     esac
-  else
-    # PORTME Check for PIC flags for the system compiler.
-    case $host_os in
-    aix3* | aix4* | aix5*)
-      lt_cv_prog_cc_wl='-Wl,'
-      # All AIX code is PIC.
-      if test "$host_cpu" = ia64; then
-	# AIX 5 now supports IA64 processor
-	lt_cv_prog_cc_static='-Bstatic'
-      else
-	lt_cv_prog_cc_static='-bnso -bI:/lib/syscalls.exp'
-      fi
-      ;;
-
-    hpux9* | hpux10* | hpux11*)
-      # Is there a better lt_cv_prog_cc_static that works with the bundled CC?
-      lt_cv_prog_cc_wl='-Wl,'
-      lt_cv_prog_cc_static="${lt_cv_prog_cc_wl}-a ${lt_cv_prog_cc_wl}archive"
-      lt_cv_prog_cc_pic='+Z'
-      ;;
-
-    irix5* | irix6*)
-      lt_cv_prog_cc_wl='-Wl,'
-      lt_cv_prog_cc_static='-non_shared'
-      # PIC (with -KPIC) is the default.
-      ;;
+    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}${shared_ext}$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
 
-    cygwin* | mingw* | pw32* | os2*)
-      # This hack is so that the source file can tell whether it is being
-      # built for inclusion in a dll (and should export symbols for example).
-      lt_cv_prog_cc_pic='-DDLL_EXPORT'
-      ;;
+amigaos*)
+  library_names_spec='$libname.ixlibrary $libname.a'
+  # Create ${libname}_ixlibrary.a entries in /sys/libs.
+  finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+  ;;
 
-    newsos6)
-      lt_cv_prog_cc_pic='-KPIC'
-      lt_cv_prog_cc_static='-Bstatic'
-      ;;
+beos*)
+  library_names_spec='${libname}${shared_ext}'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
 
-    osf3* | osf4* | osf5*)
-      # All OSF/1 code is PIC.
-      lt_cv_prog_cc_wl='-Wl,'
-      lt_cv_prog_cc_static='-non_shared'
-      ;;
+bsdi[[45]]*)
+  version_type=linux
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
 
-    sco3.2v5*)
-      lt_cv_prog_cc_pic='-Kpic'
-      lt_cv_prog_cc_static='-dn'
-      lt_cv_prog_cc_shlib='-belf'
-      ;;
+cygwin* | mingw* | pw32*)
+  version_type=windows
+  shrext_cmds=".dll"
+  need_version=no
+  need_lib_prefix=no
 
-    solaris*)
-      lt_cv_prog_cc_pic='-KPIC'
-      lt_cv_prog_cc_static='-Bstatic'
-      lt_cv_prog_cc_wl='-Wl,'
-      ;;
+  case $GCC,$host_os in
+  yes,cygwin* | yes,mingw* | yes,pw32*)
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $rm \$dlpath'
+    shlibpath_overrides_runpath=yes
 
-    sunos4*)
-      lt_cv_prog_cc_pic='-PIC'
-      lt_cv_prog_cc_static='-Bstatic'
-      lt_cv_prog_cc_wl='-Qoption ld '
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
       ;;
-
-    sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
-      lt_cv_prog_cc_pic='-KPIC'
-      lt_cv_prog_cc_static='-Bstatic'
-      if test "x$host_vendor" = xsni; then
-	lt_cv_prog_cc_wl='-LD'
+    mingw*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+      if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then
+        # It is most probably a Windows format PATH printed by
+        # mingw gcc, but we are running on Cygwin. Gcc prints its search
+        # path with ; separators, and with drive letters. We can handle the
+        # drive letters (cygwin fileutils understands them), so leave them,
+        # especially as we might pass files found there to a mingw objdump,
+        # which wouldn't understand a cygwinified path. Ahh.
+        sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
       else
-	lt_cv_prog_cc_wl='-Wl,'
-      fi
-      ;;
-
-    uts4*)
-      lt_cv_prog_cc_pic='-pic'
-      lt_cv_prog_cc_static='-Bstatic'
-      ;;
-
-    sysv4*MP*)
-      if test -d /usr/nec ;then
-	lt_cv_prog_cc_pic='-Kconform_pic'
-	lt_cv_prog_cc_static='-Bstatic'
+        sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
       fi
       ;;
-
-    *)
-      lt_cv_prog_cc_can_build_shared=no
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
       ;;
     esac
-  fi
-])
-if test -z "$lt_cv_prog_cc_pic"; then
-  AC_MSG_RESULT([none])
-else
-  AC_MSG_RESULT([$lt_cv_prog_cc_pic])
-
-  # Check to make sure the pic_flag actually works.
-  AC_MSG_CHECKING([if $compiler PIC flag $lt_cv_prog_cc_pic works])
-  AC_CACHE_VAL(lt_cv_prog_cc_pic_works, [dnl
-    save_CFLAGS="$CFLAGS"
-    CFLAGS="$CFLAGS $lt_cv_prog_cc_pic -DPIC"
-    AC_TRY_COMPILE([], [], [dnl
-      case $host_os in
-      hpux9* | hpux10* | hpux11*)
-	# On HP-UX, both CC and GCC only warn that PIC is supported... then
-	# they create non-PIC objects.  So, if there were any warnings, we
-	# assume that PIC is not supported.
-	if test -s conftest.err; then
-	  lt_cv_prog_cc_pic_works=no
-	else
-	  lt_cv_prog_cc_pic_works=yes
-	fi
-	;;
-      *)
-	lt_cv_prog_cc_pic_works=yes
-	;;
-      esac
-    ], [dnl
-      lt_cv_prog_cc_pic_works=no
-    ])
-    CFLAGS="$save_CFLAGS"
-  ])
-
-  if test "X$lt_cv_prog_cc_pic_works" = Xno; then
-    lt_cv_prog_cc_pic=
-    lt_cv_prog_cc_can_build_shared=no
-  else
-    lt_cv_prog_cc_pic=" $lt_cv_prog_cc_pic"
-  fi
-
-  AC_MSG_RESULT([$lt_cv_prog_cc_pic_works])
-fi
-##
-## END FIXME
-
-# Check for any special shared library compilation flags.
-if test -n "$lt_cv_prog_cc_shlib"; then
-  AC_MSG_WARN([\`$CC' requires \`$lt_cv_prog_cc_shlib' to build shared libraries])
-  if echo "$old_CC $old_CFLAGS " | egrep -e "[[ 	]]$lt_cv_prog_cc_shlib[[ 	]]" >/dev/null; then :
-  else
-   AC_MSG_WARN([add \`$lt_cv_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure])
-    lt_cv_prog_cc_can_build_shared=no
-  fi
-fi
-
-## FIXME: this should be a separate macro
-##
-AC_MSG_CHECKING([if $compiler static flag $lt_cv_prog_cc_static works])
-AC_CACHE_VAL([lt_cv_prog_cc_static_works], [dnl
-  lt_cv_prog_cc_static_works=no
-  save_LDFLAGS="$LDFLAGS"
-  LDFLAGS="$LDFLAGS $lt_cv_prog_cc_static"
-  AC_TRY_LINK([], [], [lt_cv_prog_cc_static_works=yes])
-  LDFLAGS="$save_LDFLAGS"
-])
-
-# Belt *and* braces to stop my trousers falling down:
-test "X$lt_cv_prog_cc_static_works" = Xno && lt_cv_prog_cc_static=
-AC_MSG_RESULT([$lt_cv_prog_cc_static_works])
-
-pic_flag="$lt_cv_prog_cc_pic"
-special_shlib_compile_flags="$lt_cv_prog_cc_shlib"
-wl="$lt_cv_prog_cc_wl"
-link_static_flag="$lt_cv_prog_cc_static"
-no_builtin_flag="$lt_cv_prog_cc_no_builtin"
-can_build_shared="$lt_cv_prog_cc_can_build_shared"
-##
-## END FIXME
-
-
-## FIXME: this should be a separate macro
-##
-# Check to see if options -o and -c are simultaneously supported by compiler
-AC_MSG_CHECKING([if $compiler supports -c -o file.$ac_objext])
-AC_CACHE_VAL([lt_cv_compiler_c_o], [
-$rm -r conftest 2>/dev/null
-mkdir conftest
-cd conftest
-echo "int some_variable = 0;" > conftest.$ac_ext
-mkdir out
-# According to Tom Tromey, Ian Lance Taylor reported there are C compilers
-# that will create temporary files in the current directory regardless of
-# the output directory.  Thus, making CWD read-only will cause this test
-# to fail, enabling locking or at least warning the user not to do parallel
-# builds.
-chmod -w .
-save_CFLAGS="$CFLAGS"
-CFLAGS="$CFLAGS -o out/conftest2.$ac_objext"
-compiler_c_o=no
-if { (eval echo configure:__oline__: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
-  # The compiler can only warn and ignore the option if not recognized
-  # So say no if there are warnings
-  if test -s out/conftest.err; then
-    lt_cv_compiler_c_o=no
-  else
-    lt_cv_compiler_c_o=yes
-  fi
-else
-  # Append any errors to the config.log.
-  cat out/conftest.err 1>&AC_FD_CC
-  lt_cv_compiler_c_o=no
-fi
-CFLAGS="$save_CFLAGS"
-chmod u+w .
-$rm conftest* out/*
-rmdir out
-cd ..
-rmdir conftest
-$rm -r conftest 2>/dev/null
-])
-compiler_c_o=$lt_cv_compiler_c_o
-AC_MSG_RESULT([$compiler_c_o])
-
-if test x"$compiler_c_o" = x"yes"; then
-  # Check to see if we can write to a .lo
-  AC_MSG_CHECKING([if $compiler supports -c -o file.lo])
-  AC_CACHE_VAL([lt_cv_compiler_o_lo], [
-  lt_cv_compiler_o_lo=no
-  save_CFLAGS="$CFLAGS"
-  CFLAGS="$CFLAGS -c -o conftest.lo"
-  save_objext="$ac_objext"
-  ac_objext=lo
-  AC_TRY_COMPILE([], [int some_variable = 0;], [dnl
-    # The compiler can only warn and ignore the option if not recognized
-    # So say no if there are warnings
-    if test -s conftest.err; then
-      lt_cv_compiler_o_lo=no
-    else
-      lt_cv_compiler_o_lo=yes
-    fi
-  ])
-  ac_objext="$save_objext"
-  CFLAGS="$save_CFLAGS"
-  ])
-  compiler_o_lo=$lt_cv_compiler_o_lo
-  AC_MSG_RESULT([$compiler_o_lo])
-else
-  compiler_o_lo=no
-fi
-##
-## END FIXME
-
-## FIXME: this should be a separate macro
-##
-# Check to see if we can do hard links to lock some files if needed
-hard_links="nottested"
-if test "$compiler_c_o" = no && test "$need_locks" != no; then
-  # do not overwrite the value of need_locks provided by the user
-  AC_MSG_CHECKING([if we can lock with hard links])
-  hard_links=yes
-  $rm conftest*
-  ln conftest.a conftest.b 2>/dev/null && hard_links=no
-  touch conftest.a
-  ln conftest.a conftest.b 2>&5 || hard_links=no
-  ln conftest.a conftest.b 2>/dev/null && hard_links=no
-  AC_MSG_RESULT([$hard_links])
-  if test "$hard_links" = no; then
-    AC_MSG_WARN([\`$CC' does not support \`-c -o', so \`make -j' may be unsafe])
-    need_locks=warn
-  fi
-else
-  need_locks=no
-fi
-##
-## END FIXME
+    ;;
 
-## FIXME: this should be a separate macro
-##
-if test "$GCC" = yes; then
-  # Check to see if options -fno-rtti -fno-exceptions are supported by compiler
-  AC_MSG_CHECKING([if $compiler supports -fno-rtti -fno-exceptions])
-  echo "int some_variable = 0;" > conftest.$ac_ext
-  save_CFLAGS="$CFLAGS"
-  CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.$ac_ext"
-  compiler_rtti_exceptions=no
-  AC_TRY_COMPILE([], [int some_variable = 0;], [dnl
-    # The compiler can only warn and ignore the option if not recognized
-    # So say no if there are warnings
-    if test -s conftest.err; then
-      compiler_rtti_exceptions=no
-    else
-      compiler_rtti_exceptions=yes
-    fi
-  ])
-  CFLAGS="$save_CFLAGS"
-  AC_MSG_RESULT([$compiler_rtti_exceptions])
+  *)
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    ;;
+  esac
+  dynamic_linker='Win32 ld.exe'
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
 
-  if test "$compiler_rtti_exceptions" = "yes"; then
-    no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions'
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+  soname_spec='${libname}${release}${major}$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='$(test .$module = .yes && echo .so || echo .dylib)'
+  # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
+  if test "$GCC" = yes; then
+    sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
   else
-    no_builtin_flag=' -fno-builtin'
+    sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
   fi
-fi
-##
-## END FIXME
-
-## FIXME: this should be a separate macro
-##
-# See if the linker supports building shared libraries.
-AC_MSG_CHECKING([whether the linker ($LD) supports shared libraries])
-
-allow_undefined_flag=
-no_undefined_flag=
-need_lib_prefix=unknown
-need_version=unknown
-# when you set need_version to no, make sure it does not cause -set_version
-# flags to be left without arguments
-archive_cmds=
-archive_expsym_cmds=
-old_archive_from_new_cmds=
-old_archive_from_expsyms_cmds=
-export_dynamic_flag_spec=
-whole_archive_flag_spec=
-thread_safe_flag_spec=
-hardcode_into_libs=no
-hardcode_libdir_flag_spec=
-hardcode_libdir_separator=
-hardcode_direct=no
-hardcode_minus_L=no
-hardcode_shlibpath_var=unsupported
-runpath_var=
-link_all_deplibs=unknown
-always_export_symbols=no
-export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols'
-# include_expsyms should be a list of space-separated symbols to be *always*
-# included in the symbol list
-include_expsyms=
-# exclude_expsyms can be an egrep regular expression of symbols to exclude
-# it will be wrapped by ` (' and `)$', so one must not match beginning or
-# end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
-# as well as any symbol that contains `d'.
-exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
-# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
-# platforms (ab)use it in PIC code, but their linkers get confused if
-# the symbol is explicitly referenced.  Since portable code cannot
-# rely on this symbol name, it's probably fine to never include it in
-# preloaded symbol tables.
-extract_expsyms_cmds=
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
 
-case $host_os in
-cygwin* | mingw* | pw32*)
-  # FIXME: the MSVC++ port hasn't been tested in a loooong time
-  # When not using gcc, we currently assume that we are using
-  # Microsoft Visual C++.
-  if test "$GCC" != yes; then
-    with_gnu_ld=no
-  fi
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
   ;;
-openbsd*)
-  with_gnu_ld=no
+
+freebsd1*)
+  dynamic_linker=no
   ;;
-esac
 
-ld_shlibs=yes
-if test "$with_gnu_ld" = yes; then
-  # If archive_cmds runs LD, not CC, wlarc should be empty
-  wlarc='${wl}'
+kfreebsd*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='GNU ld.so'
+  ;;
 
-  # See if GNU ld supports shared libraries.
+freebsd*)
+  objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
   case $host_os in
-  aix3* | aix4* | aix5*)
-    # On AIX, the GNU linker is very broken
-    # Note:Check GNU linker on AIX 5-IA64 when/if it becomes available.
-    ld_shlibs=no
-    cat <<EOF 1>&2
-
-*** Warning: the GNU linker, at least up to release 2.9.1, is reported
-*** to be unable to reliably create shared libraries on AIX.
-*** Therefore, libtool is disabling shared libraries support.  If you
-*** really care for shared libraries, you may want to modify your PATH
-*** so that a non-GNU linker is found, and then restart.
-
-EOF
+  freebsd2*)
+    shlibpath_overrides_runpath=yes
     ;;
-
-  amigaos*)
-    archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_minus_L=yes
-
-    # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
-    # that the semantics of dynamic libraries on AmigaOS, at least up
-    # to version 4, is to share data among multiple programs linked
-    # with the same dynamic library.  Since this doesn't match the
-    # behavior of shared libraries on other platforms, we can use
-    # them.
-    ld_shlibs=no
+  freebsd3.[01]* | freebsdelf3.[01]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  *) # from 3.2 on
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
     ;;
+  esac
+  ;;
 
-  beos*)
-    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
-      allow_undefined_flag=unsupported
-      # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
-      # support --undefined.  This deserves some investigation.  FIXME
-      archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case "$host_cpu" in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    if test "X$HPUX_IA64_MODE" = X32; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
     else
-      ld_shlibs=no
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
     fi
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+   hppa*64*)
+     shrext_cmds='.sl'
+     hardcode_into_libs=yes
+     dynamic_linker="$host_os dld.sl"
+     shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+     shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+     library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+     soname_spec='${libname}${release}${shared_ext}$major'
+     sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+     sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+     ;;
+   *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
     ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555.
+  postinstall_cmds='chmod 555 $lib'
+  ;;
 
-  cygwin* | mingw* | pw32*)
-    # hardcode_libdir_flag_spec is actually meaningless, as there is
-    # no search path for DLLs.
-    hardcode_libdir_flag_spec='-L$libdir'
-    allow_undefined_flag=unsupported
-    always_export_symbols=yes
-
-    extract_expsyms_cmds='test -f $output_objdir/impgen.c || \
-      sed -e "/^# \/\* impgen\.c starts here \*\//,/^# \/\* impgen.c ends here \*\// { s/^# //;s/^# *$//; p; }" -e d < $''0 > $output_objdir/impgen.c~
-      test -f $output_objdir/impgen.exe || (cd $output_objdir && \
-      if test "x$HOST_CC" != "x" ; then $HOST_CC -o impgen impgen.c ; \
-      else $CC -o impgen impgen.c ; fi)~
-      $output_objdir/impgen $dir/$soroot > $output_objdir/$soname-def'
-
-    old_archive_from_expsyms_cmds='$DLLTOOL --as=$AS --dllname $soname --def $output_objdir/$soname-def --output-lib $output_objdir/$newlib'
-
-    # cygwin and mingw dlls have different entry points and sets of symbols
-    # to exclude.
-    # FIXME: what about values for MSVC?
-    dll_entry=__cygwin_dll_entry@12
-    dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12~
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+	if test "$lt_cv_prog_gnu_ld" = yes; then
+		version_type=linux
+	else
+		version_type=irix
+	fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Append ld.so.conf contents to the search path
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`$SED -e 's/[:,\t]/ /g;s/=[^=]*$//;s/=[^= ]* / /g' /etc/ld.so.conf | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+knetbsd*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='GNU ld.so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+nto-qnx*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+openbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
     case $host_os in
-    mingw*)
-      # mingw values
-      dll_entry=_DllMainCRTStartup@12
-      dll_exclude_symbols=DllMain@12,DllMainCRTStartup@12,DllEntryPoint@12~
+      openbsd2.[[89]] | openbsd2.[[89]].*)
+	shlibpath_overrides_runpath=no
+	;;
+      *)
+	shlibpath_overrides_runpath=yes
+	;;
+      esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  ;;
+
+os2*)
+  libname_spec='$name'
+  shrext_cmds=".dll"
+  need_lib_prefix=no
+  library_names_spec='$libname${shared_ext} $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+sco3.2v5*)
+  version_type=osf
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      export_dynamic_flag_spec='${wl}-Blargedynsym'
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
       ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+    soname_spec='$libname${shared_ext}.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+AC_MSG_RESULT([$dynamic_linker])
+test "$dynamic_linker" = no && can_build_shared=no
+])# AC_LIBTOOL_SYS_DYNAMIC_LINKER
+
+
+# _LT_AC_TAGCONFIG
+# ----------------
+AC_DEFUN([_LT_AC_TAGCONFIG],
+[AC_ARG_WITH([tags],
+    [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@],
+        [include additional configurations @<:@automatic@:>@])],
+    [tagnames="$withval"])
+
+if test -f "$ltmain" && test -n "$tagnames"; then
+  if test ! -f "${ofile}"; then
+    AC_MSG_WARN([output file `$ofile' does not exist])
+  fi
+
+  if test -z "$LTCC"; then
+    eval "`$SHELL ${ofile} --config | grep '^LTCC='`"
+    if test -z "$LTCC"; then
+      AC_MSG_WARN([output file `$ofile' does not look like a libtool script])
+    else
+      AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile'])
+    fi
+  fi
+
+  # Extract list of available tagged configurations in $ofile.
+  # Note that this assumes the entire list is on one line.
+  available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'`
+
+  lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+  for tagname in $tagnames; do
+    IFS="$lt_save_ifs"
+    # Check whether tagname contains only valid characters
+    case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in
+    "") ;;
+    *)  AC_MSG_ERROR([invalid tag name: $tagname])
+	;;
     esac
 
-    # mingw and cygwin differ, and it's simplest to just exclude the union
-    # of the two symbol sets.
-    dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12
+    if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null
+    then
+      AC_MSG_ERROR([tag name \"$tagname\" already exists])
+    fi
+
+    # Update the list of available tags.
+    if test -n "$tagname"; then
+      echo appending configuration tag \"$tagname\" to $ofile
+
+      case $tagname in
+      CXX)
+	if test -n "$CXX" && test "X$CXX" != "Xno"; then
+	  AC_LIBTOOL_LANG_CXX_CONFIG
+	else
+	  tagname=""
+	fi
+	;;
+
+      F77)
+	if test -n "$F77" && test "X$F77" != "Xno"; then
+	  AC_LIBTOOL_LANG_F77_CONFIG
+	else
+	  tagname=""
+	fi
+	;;
+
+      GCJ)
+	if test -n "$GCJ" && test "X$GCJ" != "Xno"; then
+	  AC_LIBTOOL_LANG_GCJ_CONFIG
+	else
+	  tagname=""
+	fi
+	;;
+
+      RC)
+	AC_LIBTOOL_LANG_RC_CONFIG
+	;;
+
+      *)
+	AC_MSG_ERROR([Unsupported tag name: $tagname])
+	;;
+      esac
+
+      # Append the new tag name to the list of available tags.
+      if test -n "$tagname" ; then
+      available_tags="$available_tags $tagname"
+    fi
+    fi
+  done
+  IFS="$lt_save_ifs"
+
+  # Now substitute the updated list of available tags.
+  if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then
+    mv "${ofile}T" "$ofile"
+    chmod +x "$ofile"
+  else
+    rm -f "${ofile}T"
+    AC_MSG_ERROR([unable to update list of available tagged configurations.])
+  fi
+fi
+])# _LT_AC_TAGCONFIG
+
+
+# AC_LIBTOOL_DLOPEN
+# -----------------
+# enable checks for dlopen support
+AC_DEFUN([AC_LIBTOOL_DLOPEN],
+ [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])
+])# AC_LIBTOOL_DLOPEN
+
+
+# AC_LIBTOOL_WIN32_DLL
+# --------------------
+# declare package support for building win32 dll's
+AC_DEFUN([AC_LIBTOOL_WIN32_DLL],
+[AC_BEFORE([$0], [AC_LIBTOOL_SETUP])
+])# AC_LIBTOOL_WIN32_DLL
+
+
+# AC_ENABLE_SHARED([DEFAULT])
+# ---------------------------
+# implement the --enable-shared flag
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+AC_DEFUN([AC_ENABLE_SHARED],
+[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE([shared],
+    [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
+	[build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_shared=yes ;;
+    no) enable_shared=no ;;
+    *)
+      enable_shared=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_shared=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_shared=]AC_ENABLE_SHARED_DEFAULT)
+])# AC_ENABLE_SHARED
+
+
+# AC_DISABLE_SHARED
+# -----------------
+#- set the default shared flag to --disable-shared
+AC_DEFUN([AC_DISABLE_SHARED],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_SHARED(no)
+])# AC_DISABLE_SHARED
+
+
+# AC_ENABLE_STATIC([DEFAULT])
+# ---------------------------
+# implement the --enable-static flag
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+AC_DEFUN([AC_ENABLE_STATIC],
+[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE([static],
+    [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@],
+	[build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_static=yes ;;
+    no) enable_static=no ;;
+    *)
+     enable_static=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_static=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_static=]AC_ENABLE_STATIC_DEFAULT)
+])# AC_ENABLE_STATIC
+
+
+# AC_DISABLE_STATIC
+# -----------------
+# set the default static flag to --disable-static
+AC_DEFUN([AC_DISABLE_STATIC],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_STATIC(no)
+])# AC_DISABLE_STATIC
+
+
+# AC_ENABLE_FAST_INSTALL([DEFAULT])
+# ---------------------------------
+# implement the --enable-fast-install flag
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+AC_DEFUN([AC_ENABLE_FAST_INSTALL],
+[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE([fast-install],
+    [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
+    [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_fast_install=yes ;;
+    no) enable_fast_install=no ;;
+    *)
+      enable_fast_install=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_fast_install=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT)
+])# AC_ENABLE_FAST_INSTALL
+
+
+# AC_DISABLE_FAST_INSTALL
+# -----------------------
+# set the default to --disable-fast-install
+AC_DEFUN([AC_DISABLE_FAST_INSTALL],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_FAST_INSTALL(no)
+])# AC_DISABLE_FAST_INSTALL
+
+
+# AC_LIBTOOL_PICMODE([MODE])
+# --------------------------
+# implement the --with-pic flag
+# MODE is either `yes' or `no'.  If omitted, it defaults to `both'.
+AC_DEFUN([AC_LIBTOOL_PICMODE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+pic_mode=ifelse($#,1,$1,default)
+])# AC_LIBTOOL_PICMODE
+
+
+# AC_PROG_EGREP
+# -------------
+# This is predefined starting with Autoconf 2.54, so this conditional
+# definition can be removed once we require Autoconf 2.54 or later.
+m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP],
+[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep],
+   [if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+    then ac_cv_prog_egrep='grep -E'
+    else ac_cv_prog_egrep='egrep'
+    fi])
+ EGREP=$ac_cv_prog_egrep
+ AC_SUBST([EGREP])
+])])
+
+
+# AC_PATH_TOOL_PREFIX
+# -------------------
+# find a file program which can recognise shared library
+AC_DEFUN([AC_PATH_TOOL_PREFIX],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+[case $MAGIC_CMD in
+[[\\/*] |  ?:[\\/]*])
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+dnl $ac_dummy forces splitting on constant user-supplied paths.
+dnl POSIX.2 word splitting is done only on the output of word expansions,
+dnl not every word.  This closes a longstanding sh security hole.
+  ac_dummy="ifelse([$2], , $PATH, [$2])"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$1; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/$1"
+      if test -n "$file_magic_test_file"; then
+	case $deplibs_check_method in
+	"file_magic "*)
+	  file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
+	  MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+	    $EGREP "$file_magic_regex" > /dev/null; then
+	    :
+	  else
+	    cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+	  fi ;;
+	esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac])
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  AC_MSG_RESULT($MAGIC_CMD)
+else
+  AC_MSG_RESULT(no)
+fi
+])# AC_PATH_TOOL_PREFIX
+
+
+# AC_PATH_MAGIC
+# -------------
+# find a file program which can recognise a shared library
+AC_DEFUN([AC_PATH_MAGIC],
+[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
+  else
+    MAGIC_CMD=:
+  fi
+fi
+])# AC_PATH_MAGIC
+
+
+# AC_PROG_LD
+# ----------
+# find the pathname to the GNU or non-GNU linker
+AC_DEFUN([AC_PROG_LD],
+[AC_ARG_WITH([gnu-ld],
+    [AC_HELP_STRING([--with-gnu-ld],
+	[assume the C compiler uses GNU ld @<:@default=no@:>@])],
+    [test "$withval" = no || with_gnu_ld=yes],
+    [with_gnu_ld=no])
+AC_REQUIRE([LT_AC_PROG_SED])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  AC_MSG_CHECKING([for ld used by $CC])
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [[\\/]]* | ?:[[\\/]]*)
+      re_direlt='/[[^/]][[^/]]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+	ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  AC_MSG_CHECKING([for GNU ld])
+else
+  AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(lt_cv_path_LD,
+[if test -z "$LD"; then
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some GNU ld's only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+      *GNU* | *'with BFD'*)
+	test "$with_gnu_ld" != no && break
+	;;
+      *)
+	test "$with_gnu_ld" != yes && break
+	;;
+      esac
+    fi
+  done
+  IFS="$lt_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  AC_MSG_RESULT($LD)
+else
+  AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_PROG_LD_GNU
+])# AC_PROG_LD
+
+
+# AC_PROG_LD_GNU
+# --------------
+AC_DEFUN([AC_PROG_LD_GNU],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  lt_cv_prog_gnu_ld=yes
+  ;;
+*)
+  lt_cv_prog_gnu_ld=no
+  ;;
+esac])
+with_gnu_ld=$lt_cv_prog_gnu_ld
+])# AC_PROG_LD_GNU
+
+
+# AC_PROG_LD_RELOAD_FLAG
+# ----------------------
+# find reload flag for linker
+#   -- PORTME Some linkers may need a different reload flag.
+AC_DEFUN([AC_PROG_LD_RELOAD_FLAG],
+[AC_CACHE_CHECK([for $LD option to reload object files],
+  lt_cv_ld_reload_flag,
+  [lt_cv_ld_reload_flag='-r'])
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+  darwin*)
+    if test "$GCC" = yes; then
+      reload_cmds='$CC -nostdlib ${wl}-r -o $output$reload_objs'
+    else
+      reload_cmds='$LD$reload_flag -o $output$reload_objs'
+    fi
+    ;;
+esac
+])# AC_PROG_LD_RELOAD_FLAG
+
+
+# AC_DEPLIBS_CHECK_METHOD
+# -----------------------
+# how to check for library dependencies
+#  -- PORTME fill in with the dynamic library characteristics
+AC_DEFUN([AC_DEPLIBS_CHECK_METHOD],
+[AC_CACHE_CHECK([how to recognise dependent libraries],
+lt_cv_deplibs_check_method,
+[lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix4* | aix5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi[[45]]*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin*)
+  # func_win32_libid is a shell function defined in ltmain.sh
+  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+  lt_cv_file_magic_cmd='func_win32_libid'
+  ;;
+
+mingw* | pw32*)
+  # Base MSYS/MinGW do not provide the 'file' command needed by
+  # func_win32_libid shell function, so use a weaker test based on 'objdump'.
+  lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+  lt_cv_file_magic_cmd='$OBJDUMP -f'
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+freebsd* | kfreebsd*-gnu)
+  if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[[3-9]]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20* | hpux11*)
+  lt_cv_file_magic_cmd=/usr/bin/file
+  case "$host_cpu" in
+  ia64*)
+    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
+    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+    ;;
+  hppa*64*)
+    [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]']
+    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+    ;;
+  *)
+    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library'
+    lt_cv_file_magic_test_file=/usr/lib/libc.sl
+    ;;
+  esac
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $LD in
+  *-32|*"-32 ") libmagic=32-bit;;
+  *-n32|*"-n32 ") libmagic=N32;;
+  *-64|*"-64 ") libmagic=64-bit;;
+  *) libmagic=never-match;;
+  esac
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be Linux ELF.
+linux*)
+  case $host_cpu in
+  alpha*|hppa*|i*86|ia64*|m68*|mips*|powerpc*|sparc*|s390*|sh*)
+    lt_cv_deplibs_check_method=pass_all ;;
+  *)
+    # glibc up to 2.1.1 does not perform some relocations on ARM
+    # this will be overridden with pass_all, but let us keep it just in case
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;;
+  esac
+  lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+netbsd*)
+  if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+nto-qnx*)
+  lt_cv_deplibs_check_method=unknown
+  ;;
+
+openbsd*)
+  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sco3.2v5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  siemens)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  esac
+  ;;
+
+sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+esac
+])
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+])# AC_DEPLIBS_CHECK_METHOD
+
 
-    # recent cygwin and mingw systems supply a stub DllMain which the user
-    # can override, but on older systems we have to supply one (in ltdll.c)
-    if test "x$lt_cv_need_dllmain" = "xyes"; then
-      ltdll_obj='$output_objdir/$soname-ltdll.'"$ac_objext "
-      ltdll_cmds='test -f $output_objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $''0 > $output_objdir/$soname-ltdll.c~
-	test -f $output_objdir/$soname-ltdll.$ac_objext || (cd $output_objdir && $CC -c $soname-ltdll.c)~'
-    else
-      ltdll_obj=
-      ltdll_cmds=
+# AC_PROG_NM
+# ----------
+# find the pathname to a BSD-compatible name lister
+AC_DEFUN([AC_PROG_NM],
+[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM,
+[if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM="$NM"
+else
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    tmp_nm="$ac_dir/${ac_tool_prefix}nm"
+    if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+      # Check to see if the nm accepts a BSD-compat flag.
+      # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+      #   nm: unknown option "B" ignored
+      # Tru64's nm complains that /dev/null is an invalid object file
+      case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+      */dev/null* | *'Invalid file or object type'*)
+	lt_cv_path_NM="$tmp_nm -B"
+	break
+        ;;
+      *)
+	case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+	*/dev/null*)
+	  lt_cv_path_NM="$tmp_nm -p"
+	  break
+	  ;;
+	*)
+	  lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+	  continue # so that we can try to find one that supports BSD flags
+	  ;;
+	esac
+      esac
     fi
+  done
+  IFS="$lt_save_ifs"
+  test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
+fi])
+NM="$lt_cv_path_NM"
+])# AC_PROG_NM
 
-    # Extract the symbol export list from an `--export-all' def file,
-    # then regenerate the def file from the symbol export list, so that
-    # the compiled dll only exports the symbol export list.
-    # Be careful not to strip the DATA tag left be newer dlltools.
-    export_symbols_cmds="$ltdll_cmds"'
-      $DLLTOOL --export-all --exclude-symbols '$dll_exclude_symbols' --output-def $output_objdir/$soname-def '$ltdll_obj'$libobjs $convenience~
-      sed -e "1,/EXPORTS/d" -e "s/ @ [[0-9]]*//" -e "s/ *;.*$//" < $output_objdir/$soname-def > $export_symbols'
-
-    # If the export-symbols file already is a .def file (1st line
-    # is EXPORTS), use it as is.
-    # If DATA tags from a recent dlltool are present, honour them!
-    archive_expsym_cmds='if test "x`head -1 $export_symbols`" = xEXPORTS; then
-	cp $export_symbols $output_objdir/$soname-def;
-      else
-	echo EXPORTS > $output_objdir/$soname-def;
-	_lt_hint=1;
-	cat $export_symbols | while read symbol; do
-	 set dummy \$symbol;
-	 case \[$]# in
-	   2) echo "   \[$]2 @ \$_lt_hint ; " >> $output_objdir/$soname-def;;
-	   *) echo "     \[$]2 @ \$_lt_hint \[$]3 ; " >> $output_objdir/$soname-def;;
-	 esac;
-	 _lt_hint=`expr 1 + \$_lt_hint`;
-	done;
-      fi~
-      '"$ltdll_cmds"'
-      $CC -Wl,--base-file,$output_objdir/$soname-base '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~
-      $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp~
-      $CC -Wl,--base-file,$output_objdir/$soname-base $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~
-      $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp --output-lib $output_objdir/$libname.dll.a~
-      $CC $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags'
-    ;;
 
-  netbsd*)
-    if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
-      archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
-      wlarc=
-    else
-      archive_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
-      archive_expsym_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
-    fi
-    ;;
+# AC_CHECK_LIBM
+# -------------
+# check for math library
+AC_DEFUN([AC_CHECK_LIBM],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*)
+  # These system don't have libm, or don't need it
+  ;;
+*-ncr-sysv4.3*)
+  AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
+  AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
+  ;;
+*)
+  AC_CHECK_LIB(m, cos, LIBM="-lm")
+  ;;
+esac
+])# AC_CHECK_LIBM
 
-  solaris* | sysv5*)
-    if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then
-      ld_shlibs=no
-      cat <<EOF 1>&2
 
-*** Warning: The releases 2.8.* of the GNU linker cannot reliably
-*** create shared libraries on Solaris systems.  Therefore, libtool
-*** is disabling shared libraries support.  We urge you to upgrade GNU
-*** binutils to release 2.9.1 or newer.  Another option is to modify
-*** your PATH or compiler configuration so that the native linker is
-*** used, and then restart.
+# AC_LIBLTDL_CONVENIENCE([DIRECTORY])
+# -----------------------------------
+# sets LIBLTDL to the link flags for the libltdl convenience library and
+# LTDLINCL to the include flags for the libltdl header and adds
+# --enable-ltdl-convenience to the configure arguments.  Note that LIBLTDL
+# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called.  If
+# DIRECTORY is not provided, it is assumed to be `libltdl'.  LIBLTDL will
+# be prefixed with '${top_builddir}/' and LTDLINCL will be prefixed with
+# '${top_srcdir}/' (note the single quotes!).  If your package is not
+# flat and you're not using automake, define top_builddir and
+# top_srcdir appropriately in the Makefiles.
+AC_DEFUN([AC_LIBLTDL_CONVENIENCE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+  case $enable_ltdl_convenience in
+  no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
+  "") enable_ltdl_convenience=yes
+      ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
+  esac
+  LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la
+  LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+  # For backwards non-gettext consistent compatibility...
+  INCLTDL="$LTDLINCL"
+])# AC_LIBLTDL_CONVENIENCE
+
+
+# AC_LIBLTDL_INSTALLABLE([DIRECTORY])
+# -----------------------------------
+# sets LIBLTDL to the link flags for the libltdl installable library and
+# LTDLINCL to the include flags for the libltdl header and adds
+# --enable-ltdl-install to the configure arguments.  Note that LIBLTDL
+# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called.  If
+# DIRECTORY is not provided and an installed libltdl is not found, it is
+# assumed to be `libltdl'.  LIBLTDL will be prefixed with '${top_builddir}/'
+# and LTDLINCL will be prefixed with '${top_srcdir}/' (note the single
+# quotes!).  If your package is not flat and you're not using automake,
+# define top_builddir and top_srcdir appropriately in the Makefiles.
+# In the future, this macro may have to be called after AC_PROG_LIBTOOL.
+AC_DEFUN([AC_LIBLTDL_INSTALLABLE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+  AC_CHECK_LIB(ltdl, lt_dlinit,
+  [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no],
+  [if test x"$enable_ltdl_install" = xno; then
+     AC_MSG_WARN([libltdl not installed, but installation disabled])
+   else
+     enable_ltdl_install=yes
+   fi
+  ])
+  if test x"$enable_ltdl_install" = x"yes"; then
+    ac_configure_args="$ac_configure_args --enable-ltdl-install"
+    LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la
+    LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+  else
+    ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
+    LIBLTDL="-lltdl"
+    LTDLINCL=
+  fi
+  # For backwards non-gettext consistent compatibility...
+  INCLTDL="$LTDLINCL"
+])# AC_LIBLTDL_INSTALLABLE
+
+
+# AC_LIBTOOL_CXX
+# --------------
+# enable support for C++ libraries
+AC_DEFUN([AC_LIBTOOL_CXX],
+[AC_REQUIRE([_LT_AC_LANG_CXX])
+])# AC_LIBTOOL_CXX
+
+
+# _LT_AC_LANG_CXX
+# ---------------
+AC_DEFUN([_LT_AC_LANG_CXX],
+[AC_REQUIRE([AC_PROG_CXX])
+AC_REQUIRE([AC_PROG_CXXCPP])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX])
+])# _LT_AC_LANG_CXX
+
+
+# AC_LIBTOOL_F77
+# --------------
+# enable support for Fortran 77 libraries
+AC_DEFUN([AC_LIBTOOL_F77],
+[AC_REQUIRE([_LT_AC_LANG_F77])
+])# AC_LIBTOOL_F77
+
+
+# _LT_AC_LANG_F77
+# ---------------
+AC_DEFUN([_LT_AC_LANG_F77],
+[AC_REQUIRE([AC_PROG_F77])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77])
+])# _LT_AC_LANG_F77
+
+
+# AC_LIBTOOL_GCJ
+# --------------
+# enable support for GCJ libraries
+AC_DEFUN([AC_LIBTOOL_GCJ],
+[AC_REQUIRE([_LT_AC_LANG_GCJ])
+])# AC_LIBTOOL_GCJ
+
+
+# _LT_AC_LANG_GCJ
+# ---------------
+AC_DEFUN([_LT_AC_LANG_GCJ],
+[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[],
+  [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[],
+    [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[],
+      [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])],
+	 [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])],
+	   [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ])
+])# _LT_AC_LANG_GCJ
+
+
+# AC_LIBTOOL_RC
+# --------------
+# enable support for Windows resource files
+AC_DEFUN([AC_LIBTOOL_RC],
+[AC_REQUIRE([LT_AC_PROG_RC])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC])
+])# AC_LIBTOOL_RC
+
+
+# AC_LIBTOOL_LANG_C_CONFIG
+# ------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined.  Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG])
+AC_DEFUN([_LT_AC_LANG_C_CONFIG],
+[lt_save_CC="$CC"
+AC_LANG_PUSH(C)
 
-EOF
-    elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
-      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
-      archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
-    else
-      ld_shlibs=no
-    fi
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}\n'
+
+_LT_AC_SYS_COMPILER
+
+#
+# Check for any special shared library compilation flags.
+#
+_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)=
+if test "$GCC" = no; then
+  case $host_os in
+  sco3.2v5*)
+    _LT_AC_TAGVAR(lt_prog_cc_shlib, $1)='-belf'
     ;;
+  esac
+fi
+if test -n "$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)"; then
+  AC_MSG_WARN([`$CC' requires `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to build shared libraries])
+  if echo "$old_CC $old_CFLAGS " | grep "[[ 	]]$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)[[ 	]]" >/dev/null; then :
+  else
+    AC_MSG_WARN([add `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to the CC or CFLAGS env variable and reconfigure])
+    _LT_AC_TAGVAR(lt_cv_prog_cc_can_build_shared, $1)=no
+  fi
+fi
 
-  sunos4*)
-    archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
-    wlarc=
-    hardcode_direct=yes
-    hardcode_shlibpath_var=no
+
+#
+# Check to make sure the static flag actually works.
+#
+AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $_LT_AC_TAGVAR(lt_prog_compiler_static, $1) works],
+  _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1),
+  $_LT_AC_TAGVAR(lt_prog_compiler_static, $1),
+  [],
+  [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=])
+
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1)
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+AC_LIBTOOL_SYS_LIB_STRIP
+AC_LIBTOOL_DLOPEN_SELF($1)
+
+# Report which librarie types wil actually be built
+AC_MSG_CHECKING([if libtool supports shared libraries])
+AC_MSG_RESULT([$can_build_shared])
+
+AC_MSG_CHECKING([whether to build shared libraries])
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case "$host_os" in
+aix3*)
+  test "$enable_shared" = yes && enable_static=no
+  if test -n "$RANLIB"; then
+    archive_cmds="$archive_cmds~\$RANLIB \$lib"
+    postinstall_cmds='$RANLIB $lib'
+  fi
+  ;;
+
+aix4* | aix5*)
+  if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+    test "$enable_shared" = yes && enable_static=no
+  fi
     ;;
+esac
+AC_MSG_RESULT([$enable_shared])
 
-  *)
-    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
-      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
-      archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+AC_MSG_CHECKING([whether to build static libraries])
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+AC_MSG_RESULT([$enable_static])
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_POP
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_C_CONFIG
+
+
+# AC_LIBTOOL_LANG_CXX_CONFIG
+# --------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined.  Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)])
+AC_DEFUN([_LT_AC_LANG_CXX_CONFIG],
+[AC_LANG_PUSH(C++)
+AC_REQUIRE([AC_PROG_CXX])
+AC_REQUIRE([AC_PROG_CXXCPP])
+
+_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_AC_TAGVAR(allow_undefined_flag, $1)=
+_LT_AC_TAGVAR(always_export_symbols, $1)=no
+_LT_AC_TAGVAR(archive_expsym_cmds, $1)=
+_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_direct, $1)=no
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+_LT_AC_TAGVAR(hardcode_automatic, $1)=no
+_LT_AC_TAGVAR(module_cmds, $1)=
+_LT_AC_TAGVAR(module_expsym_cmds, $1)=
+_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_AC_TAGVAR(no_undefined_flag, $1)=
+_LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Dependencies to place before and after the object being linked:
+_LT_AC_TAGVAR(predep_objects, $1)=
+_LT_AC_TAGVAR(postdep_objects, $1)=
+_LT_AC_TAGVAR(predeps, $1)=
+_LT_AC_TAGVAR(postdeps, $1)=
+_LT_AC_TAGVAR(compiler_lib_search_path, $1)=
+
+# Source file extension for C++ test sources.
+ac_ext=cc
+
+# Object file extension for compiled C++ test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_LD=$LD
+lt_save_GCC=$GCC
+GCC=$GXX
+lt_save_with_gnu_ld=$with_gnu_ld
+lt_save_path_LD=$lt_cv_path_LD
+if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+  lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+else
+  unset lt_cv_prog_gnu_ld
+fi
+if test -n "${lt_cv_path_LDCXX+set}"; then
+  lt_cv_path_LD=$lt_cv_path_LDCXX
+else
+  unset lt_cv_path_LD
+fi
+test -z "${LDCXX+set}" || LD=$LDCXX
+CC=${CXX-"c++"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'`
+
+# We don't want -fno-exception wen compiling C++ code, so set the
+# no_builtin_flag separately
+if test "$GXX" = yes; then
+  _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+else
+  _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+fi
+
+if test "$GXX" = yes; then
+  # Set up default GNU C++ configuration
+
+  AC_PROG_LD
+
+  # Check if GNU C++ uses GNU ld as the underlying linker, since the
+  # archiving commands below assume that GNU ld is being used.
+  if test "$with_gnu_ld" = yes; then
+    _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+    _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+    _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+    #     investigate it a little bit more. (MM)
+    wlarc='${wl}'
+
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if eval "`$CC -print-prog-name=ld` --help 2>&1" | \
+	grep 'no-whole-archive' > /dev/null; then
+      _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
     else
-      ld_shlibs=no
+      _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
     fi
-    ;;
-  esac
+  else
+    with_gnu_ld=no
+    wlarc=
 
-  if test "$ld_shlibs" = yes; then
-    runpath_var=LD_RUN_PATH
-    hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir'
-    export_dynamic_flag_spec='${wl}--export-dynamic'
-    case $host_os in
-    cygwin* | mingw* | pw32*)
-      # dlltool doesn't understand --whole-archive et. al.
-      whole_archive_flag_spec=
-      ;;
-    *)
-      # ancient GNU ld didn't support --whole-archive et. al.
-      if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then
-	whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
-      else
-	whole_archive_flag_spec=
-      fi
-      ;;
-    esac
+    # A generic and very simple default shared library creation
+    # command for GNU C++ for the case where it uses the native
+    # linker, instead of GNU ld.  If possible, this setting should
+    # overridden to take advantage of the native linker features on
+    # the platform it is being used on.
+    _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
   fi
+
+  # Commands to make compiler produce verbose output that lists
+  # what "hidden" libraries, object files and flags are used when
+  # linking a shared library.
+  output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
 else
-  # PORTME fill in a description of your system's linker (not GNU ld)
-  case $host_os in
+  GXX=no
+  with_gnu_ld=no
+  wlarc=
+fi
+
+# PORTME: fill in a description of your system's C++ link characteristics
+AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+_LT_AC_TAGVAR(ld_shlibs, $1)=yes
+case $host_os in
   aix3*)
-    allow_undefined_flag=unsupported
-    always_export_symbols=yes
-    archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
-    # Note: this linker hardcodes the directories in LIBPATH if there
-    # are no directories specified by -L.
-    hardcode_minus_L=yes
-    if test "$GCC" = yes && test -z "$link_static_flag"; then
-      # Neither direct hardcoding nor static linking is supported with a
-      # broken collect2.
-      hardcode_direct=unsupported
-    fi
+    # FIXME: insert proper C++ library support
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
     ;;
-
   aix4* | aix5*)
     if test "$host_cpu" = ia64; then
       # On IA64, the linker does run time linking by default, so we don't
@@ -1462,10 +2747,12 @@ else
       # need to do runtime linking.
       case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*)
 	for ld_flag in $LDFLAGS; do
-	  if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+	  case $ld_flag in
+	  *-brtl*)
 	    aix_use_runtimelinking=yes
 	    break
-	  fi
+	    ;;
+	  esac
 	done
       esac
 
@@ -1479,910 +2766,953 @@ else
     # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
     # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
 
-    hardcode_direct=yes
-    archive_cmds=''
-    hardcode_libdir_separator=':'
+    _LT_AC_TAGVAR(archive_cmds, $1)=''
+    _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+    _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+    _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
 
-    #### Local change for Sleepycat's Berkeley DB [#5779]:
-    # Added $aix_export variable to control use of exports file.
-    # For non-gcc, we don't use exports files, and rather trust
-    # the binder's -qmkshrobj option to export all the mangled
-    # symbols we need for C++ and java.
-
-    aix_export="\${wl}$exp_sym_flag:\$export_symbols"
-
-    if test "$GCC" = yes; then
-      case $host_os in aix4.[[012]]|aix4.[[012]].*)
+    if test "$GXX" = yes; then
+      case $host_os in aix4.[012]|aix4.[012].*)
+      # We only want to do this on AIX 4.2 and lower, the check
+      # below for broken collect2 doesn't work under 4.3+
 	collect2name=`${CC} -print-prog-name=collect2`
 	if test -f "$collect2name" && \
-	  strings "$collect2name" | grep resolve_lib_name >/dev/null
+	   strings "$collect2name" | grep resolve_lib_name >/dev/null
 	then
 	  # We have reworked collect2
-	  hardcode_direct=yes
+	  _LT_AC_TAGVAR(hardcode_direct, $1)=yes
 	else
 	  # We have old collect2
-	  hardcode_direct=unsupported
+	  _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
 	  # It fails to find uninstalled libraries when the uninstalled
 	  # path is not listed in the libpath.  Setting hardcode_minus_L
 	  # to unsupported forces relinking
-	  hardcode_minus_L=yes
-	  hardcode_libdir_flag_spec='-L$libdir'
-	  hardcode_libdir_separator=
+	  _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+	  _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+	  _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
 	fi
       esac
-
       shared_flag='-shared'
     else
       # not using gcc
       if test "$host_cpu" = ia64; then
-	shared_flag='${wl}-G'
+	# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+	# chokes on -Wl,-G. The following line is correct:
+	shared_flag='-G'
       else
 	if test "$aix_use_runtimelinking" = yes; then
 	  shared_flag='${wl}-G'
 	else
-	  shared_flag='${wl}-bM:SRE'
-	fi
-      fi
-
-      # Test for -qmkshrobj and use it if it's available.
-      # It's superior for determining exportable symbols,
-      # especially for C++ or JNI libraries, which have
-      # mangled names.
-      #
-      AC_LANG_CONFTEST(void f(){})
-      if AC_TRY_EVAL(CC -c conftest.c) && AC_TRY_EVAL(CC -o conftest conftest.$ac_objext -qmkshrobj -lC_r); then
-        lt_cv_aix_mkshrobj=yes
-      else
-        lt_cv_aix_mkshrobj=no
-      fi
-
-      if test "$lt_cv_aix_mkshrobj" = yes; then
-        aix_export="-qmkshrobj"
-      fi
-    fi
-
-    # It seems that -bexpall can do strange things, so it is better to
-    # generate a list of symbols to export.
-    always_export_symbols=yes
-    if test "$aix_use_runtimelinking" = yes; then
-      # Warning - without using the other runtime loading flags (-brtl),
-      # -berok will link without error, but may produce a broken library.
-      allow_undefined_flag='-berok'
-      hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:/usr/lib:/lib'
-      archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag $aix_export $shared_flag"
-    else
-      if test "$host_cpu" = ia64; then
-	hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
-	allow_undefined_flag="-z nodefs"
-	archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname ${wl}-h$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag $aix_export"
-      else
-	hardcode_libdir_flag_spec='${wl}-bnolibpath ${wl}-blibpath:$libdir:/usr/lib:/lib'
-	# Warning - without using the other run time loading flags,
-	# -berok will link without error, but may produce a broken library.
-	allow_undefined_flag='${wl}-berok'
-	# This is a bit strange, but is similar to how AIX traditionally builds
-	# it's shared libraries.
-	archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${allow_undefined_flag} '"\${wl}$no_entry_flag $aix_export"' ~$AR -crlo $objdir/$libname$release.a $objdir/$soname'
-      fi
-    fi
-    ;;
-
-  amigaos*)
-    archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_minus_L=yes
-    # see comment about different semantics on the GNU ld section
-    ld_shlibs=no
-    ;;
-
-  cygwin* | mingw* | pw32*)
-    # When not using gcc, we currently assume that we are using
-    # Microsoft Visual C++.
-    # hardcode_libdir_flag_spec is actually meaningless, as there is
-    # no search path for DLLs.
-    hardcode_libdir_flag_spec=' '
-    allow_undefined_flag=unsupported
-    # Tell ltmain to make .lib files, not .a files.
-    libext=lib
-    # FIXME: Setting linknames here is a bad hack.
-    archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames='
-    # The linker will automatically build a .lib file if we build a DLL.
-    old_archive_from_new_cmds='true'
-    # FIXME: Should let the user specify the lib program.
-    old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs'
-    fix_srcfile_path='`cygpath -w "$srcfile"`'
-    ;;
-
-  darwin* | rhapsody*)
-    case "$host_os" in
-    rhapsody* | darwin1.[[012]])
-      allow_undefined_flag='-undefined suppress'
-      ;;
-    *) # Darwin 1.3 on
-      allow_undefined_flag='-flat_namespace -undefined suppress'
-      ;;
-    esac
-    # FIXME: Relying on posixy $() will cause problems for
-    #        cross-compilation, but unfortunately the echo tests do not
-    #        yet detect zsh echo's removal of \ escapes.
-
-    #### Local change for Sleepycat's Berkeley DB [#5664] [#6511]
-    case "$host_os" in
-    darwin[[12345]].*)
-       # removed double quotes in the following line:
-       archive_cmds='$nonopt $(test x$module = xyes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib $libobjs $deplibs$linker_flags -install_name $rpath/$soname $verstring'
-       ;;
-    *) # Darwin6.0 on (Mac OS/X Jaguar)
-       archive_cmds='$nonopt $allow_undefined_flag -o $lib $libobjs $deplibs$linker_flags -dynamiclib -install_name $rpath/$soname $verstring'
-       ;;
-    esac
-    #### End of changes for Sleepycat's Berkeley DB [#5664] [#6511]
-
-    # We need to add '_' to the symbols in $export_symbols first
-    #archive_expsym_cmds="$archive_cmds"' && strip -s $export_symbols'
-    hardcode_direct=yes
-    hardcode_shlibpath_var=no
-    whole_archive_flag_spec='-all_load $convenience'
-    ;;
-
-  freebsd1*)
-    ld_shlibs=no
-    ;;
-
-  # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
-  # support.  Future versions do this automatically, but an explicit c++rt0.o
-  # does not break anything, and helps significantly (at the cost of a little
-  # extra space).
-  freebsd2.2*)
-    archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
-    hardcode_libdir_flag_spec='-R$libdir'
-    hardcode_direct=yes
-    hardcode_shlibpath_var=no
-    ;;
-
-  # Unfortunately, older versions of FreeBSD 2 do not have this feature.
-  freebsd2*)
-    archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
-    hardcode_direct=yes
-    hardcode_minus_L=yes
-    hardcode_shlibpath_var=no
-    ;;
-
-  # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
-  freebsd*)
-    archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
-    hardcode_libdir_flag_spec='-R$libdir'
-    hardcode_direct=yes
-    hardcode_shlibpath_var=no
-    ;;
-
-  hpux9* | hpux10* | hpux11*)
-    case $host_os in
-    hpux9*) archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' ;;
-    *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' ;;
-    esac
-    hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
-    hardcode_libdir_separator=:
-    hardcode_direct=yes
-    hardcode_minus_L=yes # Not in the search PATH, but as the default
-			 # location of the library.
-    export_dynamic_flag_spec='${wl}-E'
-    ;;
-
-  irix5* | irix6*)
-    if test "$GCC" = yes; then
-      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
-    else
-      archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
-    fi
-    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
-    hardcode_libdir_separator=:
-    link_all_deplibs=yes
-    ;;
-
-  netbsd*)
-    if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
-      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
-    else
-      archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
-    fi
-    hardcode_libdir_flag_spec='-R$libdir'
-    hardcode_direct=yes
-    hardcode_shlibpath_var=no
-    ;;
-
-  newsos6)
-    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
-    hardcode_direct=yes
-    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
-    hardcode_libdir_separator=:
-    hardcode_shlibpath_var=no
-    ;;
-
-  openbsd*)
-    hardcode_direct=yes
-    hardcode_shlibpath_var=no
-    if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
-      archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $linker_flags'
-      hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
-      export_dynamic_flag_spec='${wl}-E'
-    else
-      case "$host_os" in
-      openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
-	archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
-	hardcode_libdir_flag_spec='-R$libdir'
-        ;;
-      *)
-        archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $linker_flags'
-        hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
-        ;;
-      esac
-    fi
-    ;;
-
-  os2*)
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_minus_L=yes
-    allow_undefined_flag=unsupported
-    archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
-    old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
-    ;;
-
-  osf3*)
-    if test "$GCC" = yes; then
-      allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
-      archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
-    else
-      allow_undefined_flag=' -expect_unresolved \*'
-      archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+	  shared_flag='${wl}-bM:SRE'
+	fi
+      fi
     fi
-    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
-    hardcode_libdir_separator=:
-    ;;
 
-  osf4* | osf5*)	# as osf3* with the addition of -msym flag
-    if test "$GCC" = yes; then
-      allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
-      archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
-      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
-    else
-      allow_undefined_flag=' -expect_unresolved \*'
-      archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
-      archive_expsym_cmds='for i in `cat $export_symbols`; do printf "-exported_symbol " >> $lib.exp; echo "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
-      $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp'
+    # It seems that -bexpall does not export symbols beginning with
+    # underscore (_), so it is better to generate a list of symbols to export.
+    _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+    if test "$aix_use_runtimelinking" = yes; then
+      # Warning - without using the other runtime loading flags (-brtl),
+      # -berok will link without error, but may produce a broken library.
+      _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok'
+      # Determine the default libpath from the value encoded in an empty executable.
+      _LT_AC_SYS_LIBPATH_AIX
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
 
-      #Both c and cxx compiler support -rpath directly
-      hardcode_libdir_flag_spec='-rpath $libdir'
+      _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+     else
+      if test "$host_cpu" = ia64; then
+	_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+	_LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+	_LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"
+      else
+	# Determine the default libpath from the value encoded in an empty executable.
+	_LT_AC_SYS_LIBPATH_AIX
+	_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+	# Warning - without using the other run time loading flags,
+	# -berok will link without error, but may produce a broken library.
+	_LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+	_LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+	# -bexpall does not export symbols beginning with underscore (_)
+	_LT_AC_TAGVAR(always_export_symbols, $1)=yes
+	# Exported symbols can be pulled into shared objects from archives
+	_LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' '
+	_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+	# This is similar to how AIX traditionally builds it's shared libraries.
+	_LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+      fi
     fi
-    hardcode_libdir_separator=:
-    ;;
-
-  sco3.2v5*)
-    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
-    hardcode_shlibpath_var=no
-    runpath_var=LD_RUN_PATH
-    hardcode_runpath_var=yes
-    export_dynamic_flag_spec='${wl}-Bexport'
     ;;
-
-  solaris*)
-    # gcc --version < 3.0 without binutils cannot create self contained
-    # shared libraries reliably, requiring libgcc.a to resolve some of
-    # the object symbols generated in some cases.  Libraries that use
-    # assert need libgcc.a to resolve __eprintf, for example.  Linking
-    # a copy of libgcc.a into every shared library to guarantee resolving
-    # such symbols causes other problems:  According to Tim Van Holder
-    # <tim.van.holder@pandora.be>, C++ libraries end up with a separate
-    # (to the application) exception stack for one thing.
-    no_undefined_flag=' -z defs'
-    if test "$GCC" = yes; then
-      case `$CC --version 2>/dev/null` in
-      [[12]].*)
-	cat <<EOF 1>&2
-
-*** Warning: Releases of GCC earlier than version 3.0 cannot reliably
-*** create self contained shared libraries on Solaris systems, without
-*** introducing a dependency on libgcc.a.  Therefore, libtool is disabling
-*** -no-undefined support, which will at least allow you to build shared
-*** libraries.  However, you may find that when you link such libraries
-*** into an application without using GCC, you have to manually add
-*** \`gcc --print-libgcc-file-name\` to the link command.  We urge you to
-*** upgrade to a newer version of GCC.  Another option is to rebuild your
-*** current GCC to use the GNU linker from GNU binutils 2.9.1 or newer.
-
-EOF
-        no_undefined_flag=
+  chorus*)
+    case $cc_basename in
+      *)
+	# FIXME: insert proper C++ library support
+	_LT_AC_TAGVAR(ld_shlibs, $1)=no
 	;;
-      esac
-    fi
-    # $CC -shared without GNU ld will not create a library from C++
-    # object files and a static libstdc++, better avoid it by now
-    archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
-    archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
-		$LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
-    hardcode_libdir_flag_spec='-R$libdir'
-    hardcode_shlibpath_var=no
-    case $host_os in
-    solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
-    *) # Supported since Solaris 2.6 (maybe 2.5.1?)
-      whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;;
     esac
-    link_all_deplibs=yes
     ;;
 
-  sunos4*)
-    if test "x$host_vendor" = xsequent; then
-      # Use $CC to link under sequent, because it throws in some extra .o
-      # files that make .init and .fini sections work.
-      archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
-    else
-      archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
-    fi
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_direct=yes
-    hardcode_minus_L=yes
-    hardcode_shlibpath_var=no
-    ;;
 
-  sysv4)
-    if test "x$host_vendor" = xsno; then
-      archive_cmds='$LD -G -Bsymbolic -h $soname -o $lib $libobjs $deplibs $linker_flags'
-      hardcode_direct=yes # is this really true???
+  cygwin* | mingw* | pw32*)
+    # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+    # as there is no search path for DLLs.
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+    _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+    _LT_AC_TAGVAR(always_export_symbols, $1)=no
+    _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+
+    if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+      _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib'
+      # If the export-symbols file already is a .def file (1st line
+      # is EXPORTS), use it as is; otherwise, prepend...
+      _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+	cp $export_symbols $output_objdir/$soname.def;
+      else
+	echo EXPORTS > $output_objdir/$soname.def;
+	cat $export_symbols >> $output_objdir/$soname.def;
+      fi~
+      $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib'
     else
-      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
-      hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
     fi
-    runpath_var='LD_RUN_PATH'
-    hardcode_shlibpath_var=no
-    ;;
+  ;;
+      darwin* | rhapsody*)
+        case "$host_os" in
+        rhapsody* | darwin1.[[012]])
+         _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress'
+         ;;
+       *) # Darwin 1.3 on
+         if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+           _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+         else
+           case ${MACOSX_DEPLOYMENT_TARGET} in
+             10.[[012]])
+               _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+               ;;
+             10.*)
+               _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup'
+               ;;
+           esac
+         fi
+         ;;
+        esac
+      _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_AC_TAGVAR(hardcode_direct, $1)=no
+      _LT_AC_TAGVAR(hardcode_automatic, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+      _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=''
+      _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+    if test "$GXX" = yes ; then
+      lt_int_apple_cc_single_mod=no
+      output_verbose_link_cmd='echo'
+      if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then
+       lt_int_apple_cc_single_mod=yes
+      fi
+      if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+      else
+          _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+        fi
+        _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+        # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+          if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+            _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          else
+            _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          fi
+            _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+      else
+      case "$cc_basename" in
+        xlc*)
+         output_verbose_link_cmd='echo'
+          _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+          _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+          _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          ;;
+       *)
+         _LT_AC_TAGVAR(ld_shlibs, $1)=no
+          ;;
+      esac
+      fi
+        ;;
 
-  sysv4.3*)
-    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
-    hardcode_shlibpath_var=no
-    export_dynamic_flag_spec='-Bexport'
+  dgux*)
+    case $cc_basename in
+      ec++)
+	# FIXME: insert proper C++ library support
+	_LT_AC_TAGVAR(ld_shlibs, $1)=no
+	;;
+      ghcx)
+	# Green Hills C++ Compiler
+	# FIXME: insert proper C++ library support
+	_LT_AC_TAGVAR(ld_shlibs, $1)=no
+	;;
+      *)
+	# FIXME: insert proper C++ library support
+	_LT_AC_TAGVAR(ld_shlibs, $1)=no
+	;;
+    esac
     ;;
-
-  sysv5*)
-    no_undefined_flag=' -z text'
-    # $CC -shared without GNU ld will not create a library from C++
-    # object files and a static libstdc++, better avoid it by now
-    archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
-    archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
-		$LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
-    hardcode_libdir_flag_spec=
-    hardcode_shlibpath_var=no
-    runpath_var='LD_RUN_PATH'
+  freebsd[12]*)
+    # C++ shared libraries reported to be fairly broken before switch to ELF
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
     ;;
-
-  uts4*)
-    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_shlibpath_var=no
+  freebsd-elf*)
+    _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
     ;;
-
-  dgux*)
-    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_shlibpath_var=no
+  freebsd* | kfreebsd*-gnu)
+    # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+    # conventions
+    _LT_AC_TAGVAR(ld_shlibs, $1)=yes
     ;;
-
-  sysv4*MP*)
-    if test -d /usr/nec; then
-      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
-      hardcode_shlibpath_var=no
-      runpath_var=LD_RUN_PATH
-      hardcode_runpath_var=yes
-      ld_shlibs=yes
-    fi
+  gnu*)
     ;;
-
-  sysv4.2uw2*)
-    archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
-    hardcode_direct=yes
-    hardcode_minus_L=no
-    hardcode_shlibpath_var=no
-    hardcode_runpath_var=yes
-    runpath_var=LD_RUN_PATH
+  hpux9*)
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+    _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+    _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+    _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+    _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+				# but as the default
+				# location of the library.
+
+    case $cc_basename in
+    CC)
+      # FIXME: insert proper C++ library support
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      ;;
+    aCC)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      # Commands to make compiler produce verbose output that lists
+      # what "hidden" libraries, object files and flags are used when
+      # linking a shared library.
+      #
+      # There doesn't appear to be a way to prevent this compiler from
+      # explicitly linking system object files so we need to strip them
+      # from the output so that they don't get included in the library
+      # dependencies.
+      output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[-]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+      ;;
+    *)
+      if test "$GXX" = yes; then
+        _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+        # FIXME: insert proper C++ library support
+        _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+    esac
     ;;
-
-  sysv5uw7* | unixware7*)
-    no_undefined_flag='${wl}-z ${wl}text'
-    if test "$GCC" = yes; then
-      archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
-    else
-      archive_cmds='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+  hpux10*|hpux11*)
+    if test $with_gnu_ld = no; then
+      case "$host_cpu" in
+      hppa*64*)
+	_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+	_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
+	_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+        ;;
+      ia64*)
+	_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+        ;;
+      *)
+	_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+	_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+	_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+        ;;
+      esac
     fi
-    runpath_var='LD_RUN_PATH'
-    hardcode_shlibpath_var=no
-    ;;
-
-  *)
-    ld_shlibs=no
-    ;;
-  esac
-fi
-AC_MSG_RESULT([$ld_shlibs])
-test "$ld_shlibs" = no && can_build_shared=no
-##
-## END FIXME
-
-## FIXME: this should be a separate macro
-##
-# Check hardcoding attributes.
-AC_MSG_CHECKING([how to hardcode library paths into programs])
-hardcode_action=
-if test -n "$hardcode_libdir_flag_spec" || \
-   test -n "$runpath_var"; then
-
-  # We can hardcode non-existant directories.
-  if test "$hardcode_direct" != no &&
-     # If the only mechanism to avoid hardcoding is shlibpath_var, we
-     # have to relink, otherwise we might link with an installed library
-     # when we should be linking with a yet-to-be-installed one
-     ## test "$hardcode_shlibpath_var" != no &&
-     test "$hardcode_minus_L" != no; then
-    # Linking always hardcodes the temporary library directory.
-    hardcode_action=relink
-  else
-    # We can link without hardcoding, and we can hardcode nonexisting dirs.
-    hardcode_action=immediate
-  fi
-else
-  # We cannot hardcode anything, or else we can only hardcode existing
-  # directories.
-  hardcode_action=unsupported
-fi
-AC_MSG_RESULT([$hardcode_action])
-##
-## END FIXME
-
-## FIXME: this should be a separate macro
-##
-striplib=
-old_striplib=
-AC_MSG_CHECKING([whether stripping libraries is possible])
-if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
-  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
-  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
-  AC_MSG_RESULT([yes])
-else
-  AC_MSG_RESULT([no])
-fi
-##
-## END FIXME
-
-reload_cmds='$LD$reload_flag -o $output$reload_objs'
-test -z "$deplibs_check_method" && deplibs_check_method=unknown
-
-## FIXME: this should be a separate macro
-##
-# PORTME Fill in your ld.so characteristics
-AC_MSG_CHECKING([dynamic linker characteristics])
-library_names_spec=
-libname_spec='lib$name'
-soname_spec=
-postinstall_cmds=
-postuninstall_cmds=
-finish_cmds=
-finish_eval=
-shlibpath_var=
-shlibpath_overrides_runpath=unknown
-version_type=none
-dynamic_linker="$host_os ld.so"
-sys_lib_dlsearch_path_spec="/lib /usr/lib"
-sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
-
-case $host_os in
-aix3*)
-  version_type=linux
-  library_names_spec='${libname}${release}.so$versuffix $libname.a'
-  shlibpath_var=LIBPATH
-
-  # AIX has no versioning support, so we append a major version to the name.
-  soname_spec='${libname}${release}.so$major'
-  ;;
-
-aix4* | aix5*)
-  version_type=linux
-
-  #### Local change for Sleepycat's Berkeley DB [#5779]:
-  # If we don't set need_version, we'll get x.so.0.0.0,
-  # even if -avoid-version is set.
-  need_version=no
+    case "$host_cpu" in
+    hppa*64*)
+      _LT_AC_TAGVAR(hardcode_direct, $1)=no
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+    ia64*)
+      _LT_AC_TAGVAR(hardcode_direct, $1)=no
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+					      # but as the default
+					      # location of the library.
+      ;;
+    *)
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+					      # but as the default
+					      # location of the library.
+      ;;
+    esac
 
-  if test "$host_cpu" = ia64; then
-    # AIX 5 supports IA64
-    library_names_spec='${libname}${release}.so$major ${libname}${release}.so$versuffix $libname.so'
-    shlibpath_var=LD_LIBRARY_PATH
-  else
-    # With GCC up to 2.95.x, collect2 would create an import file
-    # for dependence libraries.  The import file would start with
-    # the line `#! .'.  This would cause the generated library to
-    # depend on `.', always an invalid library.  This was fixed in
-    # development snapshots of GCC prior to 3.0.
-    case $host_os in
-      aix4 | aix4.[[01]] | aix4.[[01]].*)
-	if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
-	     echo ' yes '
-	     echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
-	  :
+    case $cc_basename in
+      CC)
+	# FIXME: insert proper C++ library support
+	_LT_AC_TAGVAR(ld_shlibs, $1)=no
+	;;
+      aCC)
+	case "$host_cpu" in
+	hppa*64*|ia64*)
+	  _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs'
+	  ;;
+	*)
+	  _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	  ;;
+	esac
+	# Commands to make compiler produce verbose output that lists
+	# what "hidden" libraries, object files and flags are used when
+	# linking a shared library.
+	#
+	# There doesn't appear to be a way to prevent this compiler from
+	# explicitly linking system object files so we need to strip them
+	# from the output so that they don't get included in the library
+	# dependencies.
+	output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+	;;
+      *)
+	if test "$GXX" = yes; then
+	  if test $with_gnu_ld = no; then
+	    case "$host_cpu" in
+	    ia64*|hppa*64*)
+	      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs'
+	      ;;
+	    *)
+	      _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	      ;;
+	    esac
+	  fi
 	else
-	  can_build_shared=no
+	  # FIXME: insert proper C++ library support
+	  _LT_AC_TAGVAR(ld_shlibs, $1)=no
 	fi
 	;;
     esac
-    # AIX (on Power*) has no versioning support, so currently we can
-    # not hardcode correct soname into executable. Probably we can
-    # add versioning support to collect2, so additional links can
-    # be useful in future.
-    if test "$aix_use_runtimelinking" = yes; then
-      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
-      # instead of lib<name>.a to let people know that these are not
-      # typical AIX shared libraries.
-      library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-    else
-      # We preserve .a as extension for shared libraries through AIX4.2
-      # and later when we are not doing run time linking.
-      library_names_spec='${libname}${release}.a $libname.a'
-      soname_spec='${libname}${release}.so$major'
-    fi
-    shlibpath_var=LIBPATH
-  fi
-  ;;
-
-amigaos*)
-  library_names_spec='$libname.ixlibrary $libname.a'
-  # Create ${libname}_ixlibrary.a entries in /sys/libs.
-  finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done'
-  ;;
-
-beos*)
-  library_names_spec='${libname}.so'
-  dynamic_linker="$host_os ld.so"
-  shlibpath_var=LIBRARY_PATH
-  ;;
-
-bsdi4*)
-  version_type=linux
-  need_version=no
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  soname_spec='${libname}${release}.so$major'
-  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
-  shlibpath_var=LD_LIBRARY_PATH
-  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
-  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
-  export_dynamic_flag_spec=-rdynamic
-  # the default ld.so.conf also contains /usr/contrib/lib and
-  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
-  # libtool to hard-code these into programs
-  ;;
-
-cygwin* | mingw* | pw32*)
-  version_type=windows
-  need_version=no
-  need_lib_prefix=no
-  case $GCC,$host_os in
-  yes,cygwin*)
-    library_names_spec='$libname.dll.a'
-    soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll'
-    postinstall_cmds='dlpath=`bash 2>&1 -c '\''. $dir/${file}i;echo \$dlname'\''`~
-      dldir=$destdir/`dirname \$dlpath`~
-      test -d \$dldir || mkdir -p \$dldir~
-      $install_prog .libs/$dlname \$dldir/$dlname'
-    postuninstall_cmds='dldll=`bash 2>&1 -c '\''. $file; echo \$dlname'\''`~
-      dlpath=$dir/\$dldll~
-       $rm \$dlpath'
-    ;;
-  yes,mingw*)
-    library_names_spec='${libname}`echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll'
-    sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | sed -e "s/^libraries://" -e "s/;/ /g"`
-    ;;
-  yes,pw32*)
-    library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll'
     ;;
-  *)
-    library_names_spec='${libname}`echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll $libname.lib'
+  irix5* | irix6*)
+    case $cc_basename in
+      CC)
+	# SGI C++
+	_LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
+
+	# Archives containing C++ object files must be created using
+	# "CC -ar", where "CC" is the IRIX C++ compiler.  This is
+	# necessary to make sure instantiated templates are included
+	# in the archive.
+	_LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
+	;;
+      *)
+	if test "$GXX" = yes; then
+	  if test "$with_gnu_ld" = no; then
+	    _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
+	  else
+	    _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib'
+	  fi
+	fi
+	_LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+	;;
+    esac
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+    _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
     ;;
-  esac
-  dynamic_linker='Win32 ld.exe'
-  # FIXME: first we should search . and the directory the executable is in
-  shlibpath_var=PATH
-  ;;
-
-darwin* | rhapsody*)
-  dynamic_linker="$host_os dyld"
-  version_type=darwin
-  need_lib_prefix=no
-  need_version=no
-  # FIXME: Relying on posixy $() will cause problems for
-  #        cross-compilation, but unfortunately the echo tests do not
-  #        yet detect zsh echo's removal of \ escapes.
-  #### Local change for Sleepycat's Berkeley DB [#6117]:
-  # added support for -jnimodule, encapsulated below in ${darwin_suffix}
-  darwin_suffix='$(test .$jnimodule = .yes && echo jnilib || (test .$module = .yes && echo so || echo dylib))'
-  library_names_spec='${libname}${release}${versuffix}.'"${darwin_suffix}"' ${libname}${release}${major}.'"${darwin_suffix}"' ${libname}.'"${darwin_suffix}"
-  soname_spec='${libname}${release}${major}.'"${darwin_suffix}"
-  shlibpath_overrides_runpath=yes
-  shlibpath_var=DYLD_LIBRARY_PATH
-  ;;
-
-freebsd1*)
-  dynamic_linker=no
-  ;;
-
-freebsd*)
-  objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
-  version_type=freebsd-$objformat
-  case $version_type in
-    freebsd-elf*)
-      library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
-      need_version=no
-      need_lib_prefix=no
-      ;;
-    freebsd-*)
-      library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix'
-      need_version=yes
-      ;;
-  esac
-  shlibpath_var=LD_LIBRARY_PATH
-  case $host_os in
-  freebsd2*)
-    shlibpath_overrides_runpath=yes
+  linux*)
+    case $cc_basename in
+      KCC)
+	# Kuck and Associates, Inc. (KAI) C++ Compiler
+
+	# KCC will only create a shared library if the output file
+	# ends with ".so" (or ".sl" for HP-UX), so rename the library
+	# to its proper name (with version) after linking.
+	_LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+	_LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+	# Commands to make compiler produce verbose output that lists
+	# what "hidden" libraries, object files and flags are used when
+	# linking a shared library.
+	#
+	# There doesn't appear to be a way to prevent this compiler from
+	# explicitly linking system object files so we need to strip them
+	# from the output so that they don't get included in the library
+	# dependencies.
+	output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+
+	_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir'
+	_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+	# Archives containing C++ object files must be created using
+	# "CC -Bstatic", where "CC" is the KAI C++ compiler.
+	_LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+	;;
+      icpc)
+	# Intel C++
+	with_gnu_ld=yes
+	# version 8.0 and above of icpc choke on multiply defined symbols
+	# if we add $predep_objects and $postdep_objects, however 7.1 and
+	# earlier do not add the objects themselves.
+	case `$CC -V 2>&1` in
+	*"Version 7."*)
+  	  _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+  	  _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+	  ;;
+	*)  # Version 8.0 or newer
+  	  _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+  	_LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+	  ;;
+	esac
+	_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+	_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+	_LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+	;;
+      cxx)
+	# Compaq C++
+	_LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	_LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname  -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+	runpath_var=LD_RUN_PATH
+	_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+	_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	# Commands to make compiler produce verbose output that lists
+	# what "hidden" libraries, object files and flags are used when
+	# linking a shared library.
+	#
+	# There doesn't appear to be a way to prevent this compiler from
+	# explicitly linking system object files so we need to strip them
+	# from the output so that they don't get included in the library
+	# dependencies.
+	output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+	;;
+    esac
     ;;
-  *)
-    shlibpath_overrides_runpath=no
-    hardcode_into_libs=yes
+  lynxos*)
+    # FIXME: insert proper C++ library support
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
     ;;
-  esac
-  ;;
-
-gnu*)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so'
-  soname_spec='${libname}${release}.so$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  hardcode_into_libs=yes
-  ;;
-
-hpux9* | hpux10* | hpux11*)
-  # Give a soname corresponding to the major version so that dld.sl refuses to
-  # link against other versions.
-  dynamic_linker="$host_os dld.sl"
-  version_type=sunos
-  need_lib_prefix=no
-  need_version=no
-  shlibpath_var=SHLIB_PATH
-  shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
-  library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl'
-  soname_spec='${libname}${release}.sl$major'
-  # HP-UX runs *really* slowly unless shared libraries are mode 555.
-  postinstall_cmds='chmod 555 $lib'
-  ;;
-
-irix5* | irix6*)
-  version_type=irix
-  need_lib_prefix=no
-  need_version=no
-  soname_spec='${libname}${release}.so$major'
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so $libname.so'
-  case $host_os in
-  irix5*)
-    libsuff= shlibsuff=
+  m88k*)
+    # FIXME: insert proper C++ library support
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
     ;;
-  *)
-    case $LD in # libtool.m4 will add one of these switches to LD
-    *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;;
-    *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;;
-    *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;;
-    *) libsuff= shlibsuff= libmagic=never-match;;
+  mvs*)
+    case $cc_basename in
+      cxx)
+	# FIXME: insert proper C++ library support
+	_LT_AC_TAGVAR(ld_shlibs, $1)=no
+	;;
+      *)
+	# FIXME: insert proper C++ library support
+	_LT_AC_TAGVAR(ld_shlibs, $1)=no
+	;;
     esac
     ;;
-  esac
-  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
-  shlibpath_overrides_runpath=no
-  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
-  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
-  ;;
+  netbsd*)
+    if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable  -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+      wlarc=
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+    fi
+    # Workaround some broken pre-1.5 toolchains
+    output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+    ;;
+  openbsd2*)
+    # C++ shared libraries are fairly broken
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    ;;
+  openbsd*)
+    _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+    if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+      _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
+      _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+      _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+    fi
+    output_verbose_link_cmd='echo'
+    ;;
+  osf3*)
+    case $cc_basename in
+      KCC)
+	# Kuck and Associates, Inc. (KAI) C++ Compiler
 
-# No shared lib support for Linux oldld, aout, or coff.
-linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*)
-  dynamic_linker=no
-  ;;
+	# KCC will only create a shared library if the output file
+	# ends with ".so" (or ".sl" for HP-UX), so rename the library
+	# to its proper name (with version) after linking.
+	_LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
 
-# This must be Linux ELF.
-linux-gnu*)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  soname_spec='${libname}${release}.so$major'
-  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=no
-  # This implies no fast_install, which is unacceptable.
-  # Some rework will be needed to allow for fast_install
-  # before this can be enabled.
-  hardcode_into_libs=yes
+	_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
 
-  # We used to test for /lib/ld.so.1 and disable shared libraries on
-  # powerpc, because MkLinux only supported shared libraries with the
-  # GNU dynamic linker.  Since this was broken with cross compilers,
-  # most powerpc-linux boxes support dynamic linking these days and
-  # people can always --disable-shared, the test was removed, and we
-  # assume the GNU/Linux dynamic linker is in use.
-  dynamic_linker='GNU/Linux ld.so'
-  ;;
+	# Archives containing C++ object files must be created using
+	# "CC -Bstatic", where "CC" is the KAI C++ compiler.
+	_LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
 
-netbsd*)
-  version_type=sunos
-  need_lib_prefix=no
-  need_version=no
-  if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
-    library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
-    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
-    dynamic_linker='NetBSD (a.out) ld.so'
-  else
-    library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so'
-    soname_spec='${libname}${release}.so$major'
-    dynamic_linker='NetBSD ld.elf_so'
-  fi
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=yes
-  hardcode_into_libs=yes
-  ;;
+	;;
+      RCC)
+	# Rational C++ 2.4.1
+	# FIXME: insert proper C++ library support
+	_LT_AC_TAGVAR(ld_shlibs, $1)=no
+	;;
+      cxx)
+	_LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+	_LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
+
+	_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+	_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	# Commands to make compiler produce verbose output that lists
+	# what "hidden" libraries, object files and flags are used when
+	# linking a shared library.
+	#
+	# There doesn't appear to be a way to prevent this compiler from
+	# explicitly linking system object files so we need to strip them
+	# from the output so that they don't get included in the library
+	# dependencies.
+	output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+	;;
+      *)
+	if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+	  _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+	  _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
 
-newsos6)
-  version_type=linux
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=yes
-  ;;
+	  _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+	  _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
 
-nto-qnx)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  soname_spec='${libname}${release}.so$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=yes
-  ;;
+	  # Commands to make compiler produce verbose output that lists
+	  # what "hidden" libraries, object files and flags are used when
+	  # linking a shared library.
+	  output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
 
-openbsd*)
-  version_type=sunos
-  need_lib_prefix=no
-  need_version=no
-  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
-    case "$host_os" in
-    openbsd2.[[89]] | openbsd2.[[89]].*)
-      shlibpath_overrides_runpath=no
-      ;;
-    *)
-      shlibpath_overrides_runpath=yes
-      ;;
+	else
+	  # FIXME: insert proper C++ library support
+	  _LT_AC_TAGVAR(ld_shlibs, $1)=no
+	fi
+	;;
     esac
-  else
-    shlibpath_overrides_runpath=yes
-  fi
-  library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
-  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
-  shlibpath_var=LD_LIBRARY_PATH
-  ;;
+    ;;
+  osf4* | osf5*)
+    case $cc_basename in
+      KCC)
+	# Kuck and Associates, Inc. (KAI) C++ Compiler
+
+	# KCC will only create a shared library if the output file
+	# ends with ".so" (or ".sl" for HP-UX), so rename the library
+	# to its proper name (with version) after linking.
+	_LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+	_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	# Archives containing C++ object files must be created using
+	# the KAI C++ compiler.
+	_LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs'
+	;;
+      RCC)
+	# Rational C++ 2.4.1
+	# FIXME: insert proper C++ library support
+	_LT_AC_TAGVAR(ld_shlibs, $1)=no
+	;;
+      cxx)
+	_LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+	_LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
+	_LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+	  echo "-hidden">> $lib.exp~
+	  $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp  `test -n "$verstring" && echo -set_version	$verstring` -update_registry $objdir/so_locations -o $lib~
+	  $rm $lib.exp'
+
+	_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+	_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	# Commands to make compiler produce verbose output that lists
+	# what "hidden" libraries, object files and flags are used when
+	# linking a shared library.
+	#
+	# There doesn't appear to be a way to prevent this compiler from
+	# explicitly linking system object files so we need to strip them
+	# from the output so that they don't get included in the library
+	# dependencies.
+	output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+	;;
+      *)
+	if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+	  _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+	 _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
 
-os2*)
-  libname_spec='$name'
-  need_lib_prefix=no
-  library_names_spec='$libname.dll $libname.a'
-  dynamic_linker='OS/2 ld.exe'
-  shlibpath_var=LIBPATH
-  ;;
+	  _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+	  _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
 
-osf3* | osf4* | osf5*)
-  version_type=osf
-  need_version=no
-  soname_spec='${libname}${release}.so'
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
-  shlibpath_var=LD_LIBRARY_PATH
-  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
-  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
-  ;;
+	  # Commands to make compiler produce verbose output that lists
+	  # what "hidden" libraries, object files and flags are used when
+	  # linking a shared library.
+	  output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
 
-sco3.2v5*)
-  version_type=osf
-  soname_spec='${libname}${release}.so$major'
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  shlibpath_var=LD_LIBRARY_PATH
-  ;;
+	else
+	  # FIXME: insert proper C++ library support
+	  _LT_AC_TAGVAR(ld_shlibs, $1)=no
+	fi
+	;;
+    esac
+    ;;
+  psos*)
+    # FIXME: insert proper C++ library support
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    ;;
+  sco*)
+    _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+    case $cc_basename in
+      CC)
+	# FIXME: insert proper C++ library support
+	_LT_AC_TAGVAR(ld_shlibs, $1)=no
+	;;
+      *)
+	# FIXME: insert proper C++ library support
+	_LT_AC_TAGVAR(ld_shlibs, $1)=no
+	;;
+    esac
+    ;;
+  sunos4*)
+    case $cc_basename in
+      CC)
+	# Sun C++ 4.x
+	# FIXME: insert proper C++ library support
+	_LT_AC_TAGVAR(ld_shlibs, $1)=no
+	;;
+      lcc)
+	# Lucid
+	# FIXME: insert proper C++ library support
+	_LT_AC_TAGVAR(ld_shlibs, $1)=no
+	;;
+      *)
+	# FIXME: insert proper C++ library support
+	_LT_AC_TAGVAR(ld_shlibs, $1)=no
+	;;
+    esac
+    ;;
+  solaris*)
+    case $cc_basename in
+      CC)
+	# Sun C++ 4.2, 5.x and Centerline C++
+	_LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+	_LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -nolib -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	_LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+	$CC -G${allow_undefined_flag} -nolib ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+	_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+	_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+	case $host_os in
+	  solaris2.[0-5] | solaris2.[0-5].*) ;;
+	  *)
+	    # The C++ compiler is used as linker so we must use $wl
+	    # flag to pass the commands to the underlying system
+	    # linker.
+	    # Supported since Solaris 2.6 (maybe 2.5.1?)
+	    _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+	    ;;
+	esac
+	_LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+	# Commands to make compiler produce verbose output that lists
+	# what "hidden" libraries, object files and flags are used when
+	# linking a shared library.
+	#
+	# There doesn't appear to be a way to prevent this compiler from
+	# explicitly linking system object files so we need to strip them
+	# from the output so that they don't get included in the library
+	# dependencies.
+	output_verbose_link_cmd='templist=`$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep "\-[[LR]]"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+
+	# Archives containing C++ object files must be created using
+	# "CC -xar", where "CC" is the Sun C++ compiler.  This is
+	# necessary to make sure instantiated templates are included
+	# in the archive.
+	_LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+	;;
+      gcx)
+	# Green Hills C++ Compiler
+	_LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
 
-solaris*)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  soname_spec='${libname}${release}.so$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=yes
-  hardcode_into_libs=yes
-  # ldd complains unless libraries are executable
-  postinstall_cmds='chmod +x $lib'
-  ;;
+	# The C++ compiler must be used to create the archive.
+	_LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+	;;
+      *)
+	# GNU C++ compiler with Solaris linker
+	if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+	  _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs'
+	  if $CC --version | grep -v '^2\.7' > /dev/null; then
+	    _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+	    _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+		$CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+	  else
+	    # g++ 2.7 appears to require `-G' NOT `-shared' on this
+	    # platform.
+	    _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+	    _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+		$CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+	  fi
 
-sunos4*)
-  version_type=sunos
-  library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
-  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=yes
-  if test "$with_gnu_ld" = yes; then
-    need_lib_prefix=no
-  fi
-  need_version=yes
-  ;;
+	  _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir'
+	fi
+	;;
+    esac
+    ;;
+  sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*)
+    _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+    ;;
+  tandem*)
+    case $cc_basename in
+      NCC)
+	# NonStop-UX NCC 3.20
+	# FIXME: insert proper C++ library support
+	_LT_AC_TAGVAR(ld_shlibs, $1)=no
+	;;
+      *)
+	# FIXME: insert proper C++ library support
+	_LT_AC_TAGVAR(ld_shlibs, $1)=no
+	;;
+    esac
+    ;;
+  vxworks*)
+    # FIXME: insert proper C++ library support
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    ;;
+  *)
+    # FIXME: insert proper C++ library support
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    ;;
+esac
+AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)])
+test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+_LT_AC_TAGVAR(GCC, $1)="$GXX"
+_LT_AC_TAGVAR(LD, $1)="$LD"
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+AC_LIBTOOL_POSTDEP_PREDEP($1)
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+AC_LIBTOOL_SYS_LIB_STRIP
+AC_LIBTOOL_DLOPEN_SELF($1)
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_POP
+CC=$lt_save_CC
+LDCXX=$LD
+LD=$lt_save_LD
+GCC=$lt_save_GCC
+with_gnu_ldcxx=$with_gnu_ld
+with_gnu_ld=$lt_save_with_gnu_ld
+lt_cv_path_LDCXX=$lt_cv_path_LD
+lt_cv_path_LD=$lt_save_path_LD
+lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+])# AC_LIBTOOL_LANG_CXX_CONFIG
+
+# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME])
+# ------------------------
+# Figure out "hidden" library dependencies from verbose
+# compiler output when linking a shared library.
+# Parse the compiler output and extract the necessary
+# objects, libraries and library flags.
+AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[
+dnl we can't use the lt_simple_compile_test_code here,
+dnl because it contains code intended for an executable,
+dnl not a library.  It's possible we should let each
+dnl tag define a new lt_????_link_test_code variable,
+dnl but it's only used here...
+ifelse([$1],[],[cat > conftest.$ac_ext <<EOF
+int a;
+void foo (void) { a = 0; }
+EOF
+],[$1],[CXX],[cat > conftest.$ac_ext <<EOF
+class Foo
+{
+public:
+  Foo (void) { a = 0; }
+private:
+  int a;
+};
+EOF
+],[$1],[F77],[cat > conftest.$ac_ext <<EOF
+      subroutine foo
+      implicit none
+      integer*4 a
+      a=0
+      return
+      end
+EOF
+],[$1],[GCJ],[cat > conftest.$ac_ext <<EOF
+public class foo {
+  private int a;
+  public void bar (void) {
+    a = 0;
+  }
+};
+EOF
+])
+dnl Parse the compiler output and extract the necessary
+dnl objects, libraries and library flags.
+if AC_TRY_EVAL(ac_compile); then
+  # Parse the compiler output and extract the necessary
+  # objects, libraries and library flags.
+
+  # Sentinel used to keep track of whether or not we are before
+  # the conftest object file.
+  pre_test_object_deps_done=no
+
+  # The `*' in the case matches for architectures that use `case' in
+  # $output_verbose_cmd can trigger glob expansion during the loop
+  # eval without this substitution.
+  output_verbose_link_cmd="`$echo \"X$output_verbose_link_cmd\" | $Xsed -e \"$no_glob_subst\"`"
+
+  for p in `eval $output_verbose_link_cmd`; do
+    case $p in
+
+    -L* | -R* | -l*)
+       # Some compilers place space between "-{L,R}" and the path.
+       # Remove the space.
+       if test $p = "-L" \
+	  || test $p = "-R"; then
+	 prev=$p
+	 continue
+       else
+	 prev=
+       fi
+
+       if test "$pre_test_object_deps_done" = no; then
+	 case $p in
+	 -L* | -R*)
+	   # Internal compiler library paths should come after those
+	   # provided the user.  The postdeps already come after the
+	   # user supplied libs so there is no need to process them.
+	   if test -z "$_LT_AC_TAGVAR(compiler_lib_search_path, $1)"; then
+	     _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}"
+	   else
+	     _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${_LT_AC_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}"
+	   fi
+	   ;;
+	 # The "-l" case would never come before the object being
+	 # linked, so don't bother handling this case.
+	 esac
+       else
+	 if test -z "$_LT_AC_TAGVAR(postdeps, $1)"; then
+	   _LT_AC_TAGVAR(postdeps, $1)="${prev}${p}"
+	 else
+	   _LT_AC_TAGVAR(postdeps, $1)="${_LT_AC_TAGVAR(postdeps, $1)} ${prev}${p}"
+	 fi
+       fi
+       ;;
 
-sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
-  version_type=linux
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  soname_spec='${libname}${release}.so$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  case $host_vendor in
-    sni)
-      shlibpath_overrides_runpath=no
-      ;;
-    motorola)
-      need_lib_prefix=no
-      need_version=no
-      shlibpath_overrides_runpath=no
-      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
-      ;;
-  esac
-  ;;
+    *.$objext)
+       # This assumes that the test object file only shows up
+       # once in the compiler output.
+       if test "$p" = "conftest.$objext"; then
+	 pre_test_object_deps_done=yes
+	 continue
+       fi
+
+       if test "$pre_test_object_deps_done" = no; then
+	 if test -z "$_LT_AC_TAGVAR(predep_objects, $1)"; then
+	   _LT_AC_TAGVAR(predep_objects, $1)="$p"
+	 else
+	   _LT_AC_TAGVAR(predep_objects, $1)="$_LT_AC_TAGVAR(predep_objects, $1) $p"
+	 fi
+       else
+	 if test -z "$_LT_AC_TAGVAR(postdep_objects, $1)"; then
+	   _LT_AC_TAGVAR(postdep_objects, $1)="$p"
+	 else
+	   _LT_AC_TAGVAR(postdep_objects, $1)="$_LT_AC_TAGVAR(postdep_objects, $1) $p"
+	 fi
+       fi
+       ;;
 
-uts4*)
-  version_type=linux
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  soname_spec='${libname}${release}.so$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  ;;
+    *) ;; # Ignore the rest.
 
-dgux*)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  soname_spec='${libname}${release}.so$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  ;;
+    esac
+  done
 
-sysv4*MP*)
-  if test -d /usr/nec ;then
-    version_type=linux
-    library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so'
-    soname_spec='$libname.so.$major'
-    shlibpath_var=LD_LIBRARY_PATH
-  fi
-  ;;
+  # Clean up.
+  rm -f a.out a.exe
+else
+  echo "libtool.m4: error: problem compiling $1 test program"
+fi
 
-*)
-  dynamic_linker=no
-  ;;
+$rm -f confest.$objext
+
+case " $_LT_AC_TAGVAR(postdeps, $1) " in
+*" -lc "*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;;
 esac
-AC_MSG_RESULT([$dynamic_linker])
-test "$dynamic_linker" = no && can_build_shared=no
-##
-## END FIXME
+])# AC_LIBTOOL_POSTDEP_PREDEP
+
+# AC_LIBTOOL_LANG_F77_CONFIG
+# ------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined.  Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG], [_LT_AC_LANG_F77_CONFIG(F77)])
+AC_DEFUN([_LT_AC_LANG_F77_CONFIG],
+[AC_REQUIRE([AC_PROG_F77])
+AC_LANG_PUSH(Fortran 77)
+
+_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_AC_TAGVAR(allow_undefined_flag, $1)=
+_LT_AC_TAGVAR(always_export_symbols, $1)=no
+_LT_AC_TAGVAR(archive_expsym_cmds, $1)=
+_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_direct, $1)=no
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+_LT_AC_TAGVAR(hardcode_automatic, $1)=no
+_LT_AC_TAGVAR(module_cmds, $1)=
+_LT_AC_TAGVAR(module_expsym_cmds, $1)=
+_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_AC_TAGVAR(no_undefined_flag, $1)=
+_LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="      subroutine t\n      return\n      end\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="      program t\n      end\n"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${F77-"f77"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'`
 
-## FIXME: this should be a separate macro
-##
-# Report the final consequences.
 AC_MSG_CHECKING([if libtool supports shared libraries])
 AC_MSG_RESULT([$can_build_shared])
-##
-## END FIXME
 
-## FIXME: this should be a separate macro
-##
 AC_MSG_CHECKING([whether to build shared libraries])
 test "$can_build_shared" = "no" && enable_shared=no
 
@@ -2396,137 +3726,210 @@ aix3*)
     postinstall_cmds='$RANLIB $lib'
   fi
   ;;
-
-aix4*)
-  if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
-    test "$enable_shared" = yes && enable_static=no
-  fi
+aix4* | aix5*)
+  test "$enable_shared" = yes && enable_static=no
   ;;
 esac
 AC_MSG_RESULT([$enable_shared])
-##
-## END FIXME
 
-## FIXME: this should be a separate macro
-##
 AC_MSG_CHECKING([whether to build static libraries])
 # Make sure either enable_shared or enable_static is yes.
 test "$enable_shared" = yes || enable_static=yes
 AC_MSG_RESULT([$enable_static])
-##
-## END FIXME
 
-if test "$hardcode_action" = relink; then
-  # Fast installation is not supported
-  enable_fast_install=no
-elif test "$shlibpath_overrides_runpath" = yes ||
-     test "$enable_shared" = no; then
-  # Fast installation is not necessary
-  enable_fast_install=needless
-fi
+test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
 
-variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
-if test "$GCC" = yes; then
-  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
-fi
+_LT_AC_TAGVAR(GCC, $1)="$G77"
+_LT_AC_TAGVAR(LD, $1)="$LD"
 
-AC_LIBTOOL_DLOPEN_SELF
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+AC_LIBTOOL_SYS_LIB_STRIP
 
-## FIXME: this should be a separate macro
-##
-if test "$enable_shared" = yes && test "$GCC" = yes; then
-  case $archive_cmds in
-  *'~'*)
-    # FIXME: we may have to deal with multi-command sequences.
-    ;;
-  '$CC '*)
-    # Test whether the compiler implicitly links with -lc since on some
-    # systems, -lgcc has to come before -lc. If gcc already passes -lc
-    # to ld, don't add -lc before -lgcc.
-    AC_MSG_CHECKING([whether -lc should be explicitly linked in])
-    AC_CACHE_VAL([lt_cv_archive_cmds_need_lc],
-    [$rm conftest*
-    echo 'static int dummy;' > conftest.$ac_ext
-
-    if AC_TRY_EVAL(ac_compile); then
-      soname=conftest
-      lib=conftest
-      libobjs=conftest.$ac_objext
-      deplibs=
-      wl=$lt_cv_prog_cc_wl
-      compiler_flags=-v
-      linker_flags=-v
-      verstring=
-      output_objdir=.
-      libname=conftest
-      save_allow_undefined_flag=$allow_undefined_flag
-      allow_undefined_flag=
-      if AC_TRY_EVAL(archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1)
-      then
-	lt_cv_archive_cmds_need_lc=no
-      else
-	lt_cv_archive_cmds_need_lc=yes
-      fi
-      allow_undefined_flag=$save_allow_undefined_flag
-    else
-      cat conftest.err 1>&5
-    fi])
-    AC_MSG_RESULT([$lt_cv_archive_cmds_need_lc])
-    ;;
-  esac
-fi
-need_lc=${lt_cv_archive_cmds_need_lc-yes}
-##
-## END FIXME
 
-## FIXME: this should be a separate macro
-##
-# The second clause should only fire when bootstrapping the
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_POP
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_F77_CONFIG
+
+
+# AC_LIBTOOL_LANG_GCJ_CONFIG
+# --------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined.  Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG], [_LT_AC_LANG_GCJ_CONFIG(GCJ)])
+AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG],
+[AC_LANG_SAVE
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }\n'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${GCJ-"gcj"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1)
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+AC_LIBTOOL_SYS_LIB_STRIP
+AC_LIBTOOL_DLOPEN_SELF($1)
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_RESTORE
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_GCJ_CONFIG
+
+
+# AC_LIBTOOL_LANG_RC_CONFIG
+# --------------------------
+# Ensure that the configuration vars for the Windows resource compiler are
+# suitably defined.  Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG], [_LT_AC_LANG_RC_CONFIG(RC)])
+AC_DEFUN([_LT_AC_LANG_RC_CONFIG],
+[AC_LANG_SAVE
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="$lt_simple_compile_test_code"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${RC-"windres"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_RESTORE
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_RC_CONFIG
+
+
+# AC_LIBTOOL_CONFIG([TAGNAME])
+# ----------------------------
+# If TAGNAME is not passed, then create an initial libtool script
+# with a default configuration from the untagged config vars.  Otherwise
+# add code to config.status for appending the configuration named by
+# TAGNAME from the matching tagged config vars.
+AC_DEFUN([AC_LIBTOOL_CONFIG],
+[# The else clause should only fire when bootstrapping the
 # libtool distribution, otherwise you forgot to ship ltmain.sh
 # with your package, and you will get complaints that there are
 # no rules to generate ltmain.sh.
 if test -f "$ltmain"; then
-  :
-else
-  # If there is no Makefile yet, we rely on a make rule to execute
-  # `config.status --recheck' to rerun these tests and create the
-  # libtool script then.
-  test -f Makefile && make "$ltmain"
-fi
-
-if test -f "$ltmain"; then
-  trap "$rm \"${ofile}T\"; exit 1" 1 2 15
-  $rm -f "${ofile}T"
-
-  echo creating $ofile
-
+  # See if we are running on zsh, and set the options which allow our commands through
+  # without removal of \ escapes.
+  if test -n "${ZSH_VERSION+set}" ; then
+    setopt NO_GLOB_SUBST
+  fi
   # Now quote all the things that may contain metacharacters while being
   # careful not to overquote the AC_SUBSTed values.  We take copies of the
   # variables and quote the copies for generation of the libtool script.
-  for var in echo old_CC old_CFLAGS \
-    AR AR_FLAGS CC LD LN_S NM SHELL \
-    reload_flag reload_cmds wl \
-    pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \
-    thread_safe_flag_spec whole_archive_flag_spec libname_spec \
-    library_names_spec soname_spec \
-    RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \
-    old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds \
-    postuninstall_cmds extract_expsyms_cmds old_archive_from_expsyms_cmds \
-    old_striplib striplib file_magic_cmd export_symbols_cmds \
-    deplibs_check_method allow_undefined_flag no_undefined_flag \
-    finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \
-    global_symbol_to_c_name_address \
-    hardcode_libdir_flag_spec hardcode_libdir_separator  \
+  for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM \
+    SED SHELL STRIP \
+    libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+    old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+    deplibs_check_method reload_flag reload_cmds need_locks \
+    lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+    lt_cv_sys_global_symbol_to_c_name_address \
     sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
-    compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do
+    old_postinstall_cmds old_postuninstall_cmds \
+    _LT_AC_TAGVAR(compiler, $1) \
+    _LT_AC_TAGVAR(CC, $1) \
+    _LT_AC_TAGVAR(LD, $1) \
+    _LT_AC_TAGVAR(lt_prog_compiler_wl, $1) \
+    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1) \
+    _LT_AC_TAGVAR(lt_prog_compiler_static, $1) \
+    _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) \
+    _LT_AC_TAGVAR(export_dynamic_flag_spec, $1) \
+    _LT_AC_TAGVAR(thread_safe_flag_spec, $1) \
+    _LT_AC_TAGVAR(whole_archive_flag_spec, $1) \
+    _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) \
+    _LT_AC_TAGVAR(old_archive_cmds, $1) \
+    _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) \
+    _LT_AC_TAGVAR(predep_objects, $1) \
+    _LT_AC_TAGVAR(postdep_objects, $1) \
+    _LT_AC_TAGVAR(predeps, $1) \
+    _LT_AC_TAGVAR(postdeps, $1) \
+    _LT_AC_TAGVAR(compiler_lib_search_path, $1) \
+    _LT_AC_TAGVAR(archive_cmds, $1) \
+    _LT_AC_TAGVAR(archive_expsym_cmds, $1) \
+    _LT_AC_TAGVAR(postinstall_cmds, $1) \
+    _LT_AC_TAGVAR(postuninstall_cmds, $1) \
+    _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) \
+    _LT_AC_TAGVAR(allow_undefined_flag, $1) \
+    _LT_AC_TAGVAR(no_undefined_flag, $1) \
+    _LT_AC_TAGVAR(export_symbols_cmds, $1) \
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) \
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) \
+    _LT_AC_TAGVAR(hardcode_libdir_separator, $1) \
+    _LT_AC_TAGVAR(hardcode_automatic, $1) \
+    _LT_AC_TAGVAR(module_cmds, $1) \
+    _LT_AC_TAGVAR(module_expsym_cmds, $1) \
+    _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) \
+    _LT_AC_TAGVAR(exclude_expsyms, $1) \
+    _LT_AC_TAGVAR(include_expsyms, $1); do
 
     case $var in
-    reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \
-    old_postinstall_cmds | old_postuninstall_cmds | \
-    export_symbols_cmds | archive_cmds | archive_expsym_cmds | \
-    extract_expsyms_cmds | old_archive_from_expsyms_cmds | \
+    _LT_AC_TAGVAR(old_archive_cmds, $1) | \
+    _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) | \
+    _LT_AC_TAGVAR(archive_cmds, $1) | \
+    _LT_AC_TAGVAR(archive_expsym_cmds, $1) | \
+    _LT_AC_TAGVAR(module_cmds, $1) | \
+    _LT_AC_TAGVAR(module_expsym_cmds, $1) | \
+    _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) | \
+    _LT_AC_TAGVAR(export_symbols_cmds, $1) | \
+    extract_expsyms_cmds | reload_cmds | finish_cmds | \
     postinstall_cmds | postuninstall_cmds | \
-    finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+    old_postinstall_cmds | old_postuninstall_cmds | \
+    sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
       # Double-quote double-evaled strings.
       eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
       ;;
@@ -2536,14 +3939,31 @@ if test -f "$ltmain"; then
     esac
   done
 
-  cat <<__EOF__ > "${ofile}T"
-#! $SHELL
+  case $lt_echo in
+  *'\[$]0 --fallback-echo"')
+    lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\[$]0 --fallback-echo"[$]/[$]0 --fallback-echo"/'`
+    ;;
+  esac
+
+ifelse([$1], [],
+  [cfgfile="${ofile}T"
+  trap "$rm \"$cfgfile\"; exit 1" 1 2 15
+  $rm -f "$cfgfile"
+  AC_MSG_NOTICE([creating $ofile])],
+  [cfgfile="$ofile"])
+
+  cat <<__EOF__ >> "$cfgfile"
+ifelse([$1], [],
+[#! $SHELL
 
-# `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
 # Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
 # NOTE: Changes made to this file will be lost: look at ltmain.sh.
 #
-# Copyright (C) 1996-2000 Free Software Foundation, Inc.
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+#
+# This file is part of GNU Libtool:
 # Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
 #
 # This program is free software; you can redistribute it and/or modify
@@ -2565,14 +3985,21 @@ if test -f "$ltmain"; then
 # configuration script generated by Autoconf, you may include it under
 # the same distribution terms that you use for the rest of that program.
 
+# A sed program that does not truncate output.
+SED=$lt_SED
+
 # Sed that helps us avoid accidentally triggering echo(1) options like -n.
-Xsed="sed -e s/^X//"
+Xsed="$SED -e s/^X//"
 
 # The HP-UX ksh and POSIX shell print the target directory to stdout
 # if CDPATH is set.
-if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
 
-# ### BEGIN LIBTOOL CONFIG
+# The names of the tagged configurations supported by this script.
+available_tags=
+
+# ### BEGIN LIBTOOL CONFIG],
+[# ### BEGIN LIBTOOL TAG CONFIG: $tagname])
 
 # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
 
@@ -2586,7 +4013,10 @@ build_libtool_libs=$enable_shared
 build_old_libs=$enable_static
 
 # Whether or not to add -lc for building shared libraries.
-build_libtool_need_lc=$need_lc
+build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)
 
 # Whether or not to optimize for fast installation.
 fast_install=$enable_fast_install
@@ -2602,14 +4032,20 @@ echo=$lt_echo
 AR=$lt_AR
 AR_FLAGS=$lt_AR_FLAGS
 
-# The default C compiler.
-CC=$lt_CC
+# A C compiler.
+LTCC=$lt_LTCC
+
+# A language-specific compiler.
+CC=$lt_[]_LT_AC_TAGVAR(compiler, $1)
 
 # Is the compiler the GNU C compiler?
-with_gcc=$GCC
+with_gcc=$_LT_AC_TAGVAR(GCC, $1)
+
+# An ERE matcher.
+EGREP=$lt_EGREP
 
 # The linker used to build libraries.
-LD=$lt_LD
+LD=$lt_[]_LT_AC_TAGVAR(LD, $1)
 
 # Whether we need hard or soft links.
 LN_S=$lt_LN_S
@@ -2618,7 +4054,7 @@ LN_S=$lt_LN_S
 NM=$lt_NM
 
 # A symbol stripping program
-STRIP=$STRIP
+STRIP=$lt_STRIP
 
 # Used to examine libraries when file_magic_cmd begins "file"
 MAGIC_CMD=$MAGIC_CMD
@@ -2640,7 +4076,7 @@ reload_flag=$lt_reload_flag
 reload_cmds=$lt_reload_cmds
 
 # How to pass a linker flag through the compiler.
-wl=$lt_wl
+wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)
 
 # Object file suffix (normally "o").
 objext="$ac_objext"
@@ -2648,18 +4084,21 @@ objext="$ac_objext"
 # Old archive suffix (normally "a").
 libext="$libext"
 
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
 # Executable file suffix (normally "").
 exeext="$exeext"
 
 # Additional compiler flags for building library objects.
-pic_flag=$lt_pic_flag
+pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)
 pic_mode=$pic_mode
 
-# Does compiler simultaneously support -c and -o options?
-compiler_c_o=$lt_compiler_c_o
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
 
-# Can we write directly to a .lo ?
-compiler_o_lo=$lt_compiler_o_lo
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)
 
 # Must we lock files when doing compilation ?
 need_locks=$lt_need_locks
@@ -2679,946 +4118,1788 @@ dlopen_self=$enable_dlopen_self
 # Whether dlopen of statically linked programs is supported.
 dlopen_self_static=$enable_dlopen_self_static
 
-# Compiler flag to prevent dynamic linking.
-link_static_flag=$lt_link_static_flag
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1)
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1)
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1)
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1)
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1)
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1)
+archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1)
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1)
+module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1)
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1)
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1)
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1)
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1)
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1)
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1)
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1)
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1)
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1)
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1)
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1)
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1)
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1)
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1)
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1)
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1)
+
+# Symbols that must always be exported.
+include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1)
+
+ifelse([$1],[],
+[# ### END LIBTOOL CONFIG],
+[# ### END LIBTOOL TAG CONFIG: $tagname])
+
+__EOF__
+
+ifelse([$1],[], [
+  case $host_os in
+  aix3*)
+    cat <<\EOF >> "$cfgfile"
+
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+EOF
+    ;;
+  esac
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1)
+
+  mv -f "$cfgfile" "$ofile" || \
+    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+  chmod +x "$ofile"
+])
+else
+  # If there is no Makefile yet, we rely on a make rule to execute
+  # `config.status --recheck' to rerun these tests and create the
+  # libtool script then.
+  ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+  if test -f "$ltmain_in"; then
+    test -f Makefile && make "$ltmain"
+  fi
+fi
+])# AC_LIBTOOL_CONFIG
+
+
+# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME])
+# -------------------------------------------
+AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI],
+[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
+
+_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+
+if test "$GCC" = yes; then
+  _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+
+  AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
+    lt_cv_prog_compiler_rtti_exceptions,
+    [-fno-rtti -fno-exceptions], [],
+    [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
+fi
+])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI
+
+
+# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+# ---------------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE],
+[AC_REQUIRE([AC_CANONICAL_HOST])
+AC_REQUIRE([AC_PROG_NM])
+AC_REQUIRE([AC_OBJEXT])
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output from $compiler object])
+AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
+[
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[[BCDEGRST]]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+
+# Transform the above into a raw symbol and a C symbol.
+symxfrm='\1 \2\3 \3'
 
-# Compiler flag to turn off builtin functions.
-no_builtin_flag=$lt_no_builtin_flag
+# Transform an extracted symbol line into a proper C declaration
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'"
 
-# Compiler flag to allow reflexive dlopens.
-export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/  {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/  {\"\2\", (lt_ptr) \&\2},/p'"
 
-# Compiler flag to generate shared objects directly from archives.
-whole_archive_flag_spec=$lt_whole_archive_flag_spec
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[[BCDT]]'
+  ;;
+cygwin* | mingw* | pw32*)
+  symcode='[[ABCDGISTW]]'
+  ;;
+hpux*) # Its linker distinguishes data from code symbols
+  if test "$host_cpu" = ia64; then
+    symcode='[[ABCDEGRST]]'
+  fi
+  lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+  lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/  {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"\2\", (lt_ptr) \&\2},/p'"
+  ;;
+irix* | nonstopux*)
+  symcode='[[BCDEGRST]]'
+  ;;
+osf*)
+  symcode='[[BCDEGQRST]]'
+  ;;
+solaris* | sysv5*)
+  symcode='[[BDRT]]'
+  ;;
+sysv4)
+  symcode='[[DFNSTU]]'
+  ;;
+esac
 
-# Compiler flag to generate thread-safe objects.
-thread_safe_flag_spec=$lt_thread_safe_flag_spec
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+  opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
 
-# Library versioning type.
-version_type=$version_type
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+  symcode='[[ABCDGIRSTW]]' ;;
+esac
 
-# Format of library name prefix.
-libname_spec=$lt_libname_spec
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
 
-# List of archive names.  First name is the real one, the rest are links.
-# The last name is the one that the linker finds with -lNAME.
-library_names_spec=$lt_library_names_spec
+  # Write the raw and C identifiers.
+  lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ 	]]\($symcode$symcode*\)[[ 	]][[ 	]]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'"
 
-# The coded name of the library, if different from the real name.
-soname_spec=$lt_soname_spec
+  # Check to see that the pipe works correctly.
+  pipe_works=no
 
-# Commands used to build and install an old-style archive.
-RANLIB=$lt_RANLIB
-old_archive_cmds=$lt_old_archive_cmds
-old_postinstall_cmds=$lt_old_postinstall_cmds
-old_postuninstall_cmds=$lt_old_postuninstall_cmds
+  rm -f conftest*
+  cat > conftest.$ac_ext <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
 
-# Create an old-style archive from a shared archive.
-old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+  if AC_TRY_EVAL(ac_compile); then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+	mv -f "$nlist"T "$nlist"
+      else
+	rm -f "$nlist"T
+      fi
 
-# Create a temporary old-style archive to link instead of a shared archive.
-old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+      # Make sure that we snagged all the symbols we need.
+      if grep ' nm_test_var$' "$nlist" >/dev/null; then
+	if grep ' nm_test_func$' "$nlist" >/dev/null; then
+	  cat <<EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
 
-# Commands used to build and install a shared archive.
-archive_cmds=$lt_archive_cmds
-archive_expsym_cmds=$lt_archive_expsym_cmds
-postinstall_cmds=$lt_postinstall_cmds
-postuninstall_cmds=$lt_postuninstall_cmds
+EOF
+	  # Now generate the symbol file.
+	  eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext'
 
-# Commands to strip libraries.
-old_striplib=$lt_old_striplib
-striplib=$lt_striplib
+	  cat <<EOF >> conftest.$ac_ext
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
 
-# Method to check whether dependent libraries are shared objects.
-deplibs_check_method=$lt_deplibs_check_method
+/* The mapping between symbol names and symbols. */
+const struct {
+  const char *name;
+  lt_ptr_t address;
+}
+lt_preloaded_symbols[[]] =
+{
+EOF
+	  $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext
+	  cat <<\EOF >> conftest.$ac_ext
+  {0, (lt_ptr_t) 0}
+};
 
-# Command to use when deplibs_check_method == file_magic.
-file_magic_cmd=$lt_file_magic_cmd
+#ifdef __cplusplus
+}
+#endif
+EOF
+	  # Now try linking the two files.
+	  mv conftest.$ac_objext conftstm.$ac_objext
+	  lt_save_LIBS="$LIBS"
+	  lt_save_CFLAGS="$CFLAGS"
+	  LIBS="conftstm.$ac_objext"
+	  CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
+	  if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then
+	    pipe_works=yes
+	  fi
+	  LIBS="$lt_save_LIBS"
+	  CFLAGS="$lt_save_CFLAGS"
+	else
+	  echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
+	fi
+      else
+	echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
+    fi
+  else
+    echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
+    cat conftest.$ac_ext >&5
+  fi
+  rm -f conftest* conftst*
 
-# Flag that allows shared libraries with undefined symbols to be built.
-allow_undefined_flag=$lt_allow_undefined_flag
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$pipe_works" = yes; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+])
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+  AC_MSG_RESULT(failed)
+else
+  AC_MSG_RESULT(ok)
+fi
+]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
 
-# Flag that forces no undefined symbols.
-no_undefined_flag=$lt_no_undefined_flag
 
-# Commands used to finish a libtool library installation in a directory.
-finish_cmds=$lt_finish_cmds
+# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME])
+# ---------------------------------------
+AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC],
+[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)=
+_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=
 
-# Same as above, but a single script fragment to be evaled but not shown.
-finish_eval=$lt_finish_eval
+AC_MSG_CHECKING([for $compiler option to produce PIC])
+ ifelse([$1],[CXX],[
+  # C++ specific cases for pic, static, wl, etc.
+  if test "$GXX" = yes; then
+    _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+    _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
 
-# Take the output of nm and produce a listing of raw symbols and C names.
-global_symbol_pipe=$lt_global_symbol_pipe
+    case $host_os in
+    aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	_LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+    amigaos*)
+      # FIXME: we need at least 68020 code to build shared libraries, but
+      # adding the `-m68020' flag to GCC prevents building anything better,
+      # like `-m68040'.
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+      ;;
+    beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+    mingw* | os2* | pw32*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
+      ;;
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+      ;;
+    *djgpp*)
+      # DJGPP does not support shared libraries at all
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+      ;;
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+      fi
+      ;;
+    hpux*)
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case "$host_cpu" in
+      hppa*64*|ia64*)
+	;;
+      *)
+	_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	;;
+      esac
+      ;;
+    *)
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+    esac
+  else
+    case $host_os in
+      aix4* | aix5*)
+	# All AIX code is PIC.
+	if test "$host_cpu" = ia64; then
+	  # AIX 5 now supports IA64 processor
+	  _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	else
+	  _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+	fi
+	;;
+      chorus*)
+	case $cc_basename in
+	cxch68)
+	  # Green Hills C++ Compiler
+	  # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+	  ;;
+	esac
+	;;
+       darwin*)
+         # PIC is the default on this platform
+         # Common symbols not allowed in MH_DYLIB files
+         case "$cc_basename" in
+           xlc*)
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon'
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           ;;
+         esac
+       ;;
+      dgux*)
+	case $cc_basename in
+	  ec++)
+	    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    ;;
+	  ghcx)
+	    # Green Hills C++ Compiler
+	    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      freebsd* | kfreebsd*-gnu)
+	# FreeBSD uses GNU C++
+	;;
+      hpux9* | hpux10* | hpux11*)
+	case $cc_basename in
+	  CC)
+	    _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive"
+	    if test "$host_cpu" != ia64; then
+	      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+	    fi
+	    ;;
+	  aCC)
+	    _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive"
+	    case "$host_cpu" in
+	    hppa*64*|ia64*)
+	      # +Z the default
+	      ;;
+	    *)
+	      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+	      ;;
+	    esac
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      irix5* | irix6* | nonstopux*)
+	case $cc_basename in
+	  CC)
+	    _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+	    # CC pic flag -KPIC is the default.
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      linux*)
+	case $cc_basename in
+	  KCC)
+	    # KAI C++ Compiler
+	    _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+	    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	    ;;
+	  icpc)
+	    # Intel C++
+	    _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+	    ;;
+	  cxx)
+	    # Compaq C++
+	    # Make sure the PIC flag is empty.  It appears that all Alpha
+	    # Linux and Compaq Tru64 Unix objects are PIC.
+	    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+	    _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      lynxos*)
+	;;
+      m88k*)
+	;;
+      mvs*)
+	case $cc_basename in
+	  cxx)
+	    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      netbsd*)
+	;;
+      osf3* | osf4* | osf5*)
+	case $cc_basename in
+	  KCC)
+	    _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+	    ;;
+	  RCC)
+	    # Rational C++ 2.4.1
+	    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+	    ;;
+	  cxx)
+	    # Digital/Compaq C++
+	    _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    # Make sure the PIC flag is empty.  It appears that all Alpha
+	    # Linux and Compaq Tru64 Unix objects are PIC.
+	    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+	    _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      psos*)
+	;;
+      sco*)
+	case $cc_basename in
+	  CC)
+	    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      solaris*)
+	case $cc_basename in
+	  CC)
+	    # Sun C++ 4.2, 5.x and Centerline C++
+	    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	    _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+	    ;;
+	  gcx)
+	    # Green Hills C++ Compiler
+	    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      sunos4*)
+	case $cc_basename in
+	  CC)
+	    # Sun C++ 4.x
+	    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+	    _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	    ;;
+	  lcc)
+	    # Lucid
+	    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      tandem*)
+	case $cc_basename in
+	  NCC)
+	    # NonStop-UX NCC 3.20
+	    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      unixware*)
+	;;
+      vxworks*)
+	;;
+      *)
+	_LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+	;;
+    esac
+  fi
+],
+[
+  if test "$GCC" = yes; then
+    _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+    _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
 
-# Transform the output of nm in a proper C declaration
-global_symbol_to_cdecl=$lt_global_symbol_to_cdecl
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	_LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
 
-# Transform the output of nm in a C name address pair
-global_symbol_to_c_name_address=$lt_global_symbol_to_c_name_address
+    amigaos*)
+      # FIXME: we need at least 68020 code to build shared libraries, but
+      # adding the `-m68020' flag to GCC prevents building anything better,
+      # like `-m68040'.
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+      ;;
 
-# This is the shared library runtime path variable.
-runpath_var=$runpath_var
+    beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
 
-# This is the shared library path variable.
-shlibpath_var=$shlibpath_var
+    mingw* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
+      ;;
 
-# Is shlibpath searched before the hard-coded library search path?
-shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+      ;;
 
-# How to hardcode a shared library path into an executable.
-hardcode_action=$hardcode_action
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      enable_shared=no
+      ;;
 
-# Whether we should hardcode library paths into libraries.
-hardcode_into_libs=$hardcode_into_libs
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+      fi
+      ;;
 
-# Flag to hardcode \$libdir into a binary during linking.
-# This must work even if \$libdir does not exist.
-hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+    hpux*)
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case "$host_cpu" in
+      hppa*64*|ia64*)
+	# +Z the default
+	;;
+      *)
+	_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	;;
+      esac
+      ;;
 
-# Whether we need a single -rpath flag with a separated argument.
-hardcode_libdir_separator=$lt_hardcode_libdir_separator
+    *)
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	_LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      else
+	_LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+      darwin*)
+        # PIC is the default on this platform
+        # Common symbols not allowed in MH_DYLIB files
+       case "$cc_basename" in
+         xlc*)
+         _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon'
+         _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+         ;;
+       esac
+       ;;
 
-# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
-# resulting binary.
-hardcode_direct=$hardcode_direct
+    mingw* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
+      ;;
 
-# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
-# resulting binary.
-hardcode_minus_L=$hardcode_minus_L
+    hpux9* | hpux10* | hpux11*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case "$host_cpu" in
+      hppa*64*|ia64*)
+	# +Z the default
+	;;
+      *)
+	_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+	;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+      ;;
 
-# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
-# the resulting binary.
-hardcode_shlibpath_var=$hardcode_shlibpath_var
+    irix5* | irix6* | nonstopux*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # PIC (with -KPIC) is the default.
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
 
-# Variables whose values should be saved in libtool wrapper scripts and
-# restored at relink time.
-variables_saved_for_relink="$variables_saved_for_relink"
+    newsos6)
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
 
-# Whether libtool must link a program against all its dependency libraries.
-link_all_deplibs=$link_all_deplibs
+    linux*)
+      case $CC in
+      icc* | ecc*)
+	_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	_LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+        ;;
+      ccc*)
+        _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+        # All Alpha code is PIC.
+        _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+        ;;
+      esac
+      ;;
 
-# Compile-time system search path for libraries
-sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+    osf3* | osf4* | osf5*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # All OSF/1 code is PIC.
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
 
-# Run-time system search path for libraries
-sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+    sco3.2v5*)
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kpic'
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-dn'
+      ;;
 
-# Fix the shell variable \$srcfile for the compiler.
-fix_srcfile_path="$fix_srcfile_path"
+    solaris*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
 
-# Set to yes if exported symbols are required.
-always_export_symbols=$always_export_symbols
+    sunos4*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
 
-# The commands to list exported symbols.
-export_symbols_cmds=$lt_export_symbols_cmds
+    sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
 
-# The commands to extract the exported symbol list from a shared archive.
-extract_expsyms_cmds=$lt_extract_expsyms_cmds
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+	_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
+	_LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
 
-# Symbols that should not be listed in the preloaded symbols.
-exclude_expsyms=$lt_exclude_expsyms
+    uts4*)
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
 
-# Symbols that must always be exported.
-include_expsyms=$lt_include_expsyms
+    *)
+      _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      ;;
+    esac
+  fi
+])
+AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)])
 
-# ### END LIBTOOL CONFIG
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then
+  AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works],
+    _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1),
+    [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [],
+    [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in
+     "" | " "*) ;;
+     *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;;
+     esac],
+    [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+     _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
+fi
+case "$host_os" in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+    ;;
+  *)
+    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])"
+    ;;
+esac
+])
 
-__EOF__
 
+# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME])
+# ------------------------------------
+# See if the linker supports building shared libraries.
+AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS],
+[AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+ifelse([$1],[CXX],[
+  _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
   case $host_os in
-  aix3*)
-    cat <<\EOF >> "${ofile}T"
-
-# AIX sometimes has problems with the GCC collect2 program.  For some
-# reason, if we set the COLLECT_NAMES environment variable, the problems
-# vanish in a puff of smoke.
-if test "X${COLLECT_NAMES+set}" != Xset; then
-  COLLECT_NAMES=
-  export COLLECT_NAMES
-fi
-EOF
+  aix4* | aix5*)
+    # If we're using GNU nm, then we don't want the "-C" option.
+    # -C means demangle to AIX nm, but means don't demangle with GNU nm
+    if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+      _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+    else
+      _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+    fi
     ;;
+  pw32*)
+    _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
+  ;;
+  cygwin* | mingw*)
+    _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols'
+  ;;
+  *)
+    _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  ;;
   esac
+],[
+  runpath_var=
+  _LT_AC_TAGVAR(allow_undefined_flag, $1)=
+  _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+  _LT_AC_TAGVAR(archive_cmds, $1)=
+  _LT_AC_TAGVAR(archive_expsym_cmds, $1)=
+  _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)=
+  _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)=
+  _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+  _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+  _LT_AC_TAGVAR(thread_safe_flag_spec, $1)=
+  _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+  _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+  _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+  _LT_AC_TAGVAR(hardcode_direct, $1)=no
+  _LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+  _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+  _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
+  _LT_AC_TAGVAR(hardcode_automatic, $1)=no
+  _LT_AC_TAGVAR(module_cmds, $1)=
+  _LT_AC_TAGVAR(module_expsym_cmds, $1)=
+  _LT_AC_TAGVAR(always_export_symbols, $1)=no
+  _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  _LT_AC_TAGVAR(include_expsyms, $1)=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ` (' and `)$', so one must not match beginning or
+  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+  # as well as any symbol that contains `d'.
+  _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_"
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  extract_expsyms_cmds=
 
   case $host_os in
-  cygwin* | mingw* | pw32* | os2*)
-    cat <<'EOF' >> "${ofile}T"
-      # This is a source program that is used to create dlls on Windows
-      # Don't remove nor modify the starting and closing comments
-# /* ltdll.c starts here */
-# #define WIN32_LEAN_AND_MEAN
-# #include <windows.h>
-# #undef WIN32_LEAN_AND_MEAN
-# #include <stdio.h>
-#
-# #ifndef __CYGWIN__
-# #  ifdef __CYGWIN32__
-# #    define __CYGWIN__ __CYGWIN32__
-# #  endif
-# #endif
-#
-# #ifdef __cplusplus
-# extern "C" {
-# #endif
-# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved);
-# #ifdef __cplusplus
-# }
-# #endif
-#
-# #ifdef __CYGWIN__
-# #include <cygwin/cygwin_dll.h>
-# DECLARE_CYGWIN_DLL( DllMain );
-# #endif
-# HINSTANCE __hDllInstance_base;
-#
-# BOOL APIENTRY
-# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
-# {
-#   __hDllInstance_base = hInst;
-#   return TRUE;
-# }
-# /* ltdll.c ends here */
-	# This is a source program that is used to create import libraries
-	# on Windows for dlls which lack them. Don't remove nor modify the
-	# starting and closing comments
-# /* impgen.c starts here */
-# /*   Copyright (C) 1999-2000 Free Software Foundation, Inc.
-#
-#  This file is part of GNU libtool.
-#
-#  This program is free software; you can redistribute it and/or modify
-#  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation; either version 2 of the License, or
-#  (at your option) any later version.
-#
-#  This program is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#  GNU General Public License for more details.
-#
-#  You should have received a copy of the GNU General Public License
-#  along with this program; if not, write to the Free Software
-#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#  */
-#
-# #include <stdio.h>		/* for printf() */
-# #include <unistd.h>		/* for open(), lseek(), read() */
-# #include <fcntl.h>		/* for O_RDONLY, O_BINARY */
-# #include <string.h>		/* for strdup() */
-#
-# /* O_BINARY isn't required (or even defined sometimes) under Unix */
-# #ifndef O_BINARY
-# #define O_BINARY 0
-# #endif
-#
-# static unsigned int
-# pe_get16 (fd, offset)
-#      int fd;
-#      int offset;
-# {
-#   unsigned char b[2];
-#   lseek (fd, offset, SEEK_SET);
-#   read (fd, b, 2);
-#   return b[0] + (b[1]<<8);
-# }
-#
-# static unsigned int
-# pe_get32 (fd, offset)
-#     int fd;
-#     int offset;
-# {
-#   unsigned char b[4];
-#   lseek (fd, offset, SEEK_SET);
-#   read (fd, b, 4);
-#   return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
-# }
-#
-# static unsigned int
-# pe_as32 (ptr)
-#      void *ptr;
-# {
-#   unsigned char *b = ptr;
-#   return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
-# }
-#
-# int
-# main (argc, argv)
-#     int argc;
-#     char *argv[];
-# {
-#     int dll;
-#     unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
-#     unsigned long export_rva, export_size, nsections, secptr, expptr;
-#     unsigned long name_rvas, nexp;
-#     unsigned char *expdata, *erva;
-#     char *filename, *dll_name;
-#
-#     filename = argv[1];
-#
-#     dll = open(filename, O_RDONLY|O_BINARY);
-#     if (dll < 1)
-# 	return 1;
-#
-#     dll_name = filename;
-#
-#     for (i=0; filename[i]; i++)
-# 	if (filename[i] == '/' || filename[i] == '\\'  || filename[i] == ':')
-# 	    dll_name = filename + i +1;
-#
-#     pe_header_offset = pe_get32 (dll, 0x3c);
-#     opthdr_ofs = pe_header_offset + 4 + 20;
-#     num_entries = pe_get32 (dll, opthdr_ofs + 92);
-#
-#     if (num_entries < 1) /* no exports */
-# 	return 1;
-#
-#     export_rva = pe_get32 (dll, opthdr_ofs + 96);
-#     export_size = pe_get32 (dll, opthdr_ofs + 100);
-#     nsections = pe_get16 (dll, pe_header_offset + 4 +2);
-#     secptr = (pe_header_offset + 4 + 20 +
-# 	      pe_get16 (dll, pe_header_offset + 4 + 16));
-#
-#     expptr = 0;
-#     for (i = 0; i < nsections; i++)
-#     {
-# 	char sname[8];
-# 	unsigned long secptr1 = secptr + 40 * i;
-# 	unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
-# 	unsigned long vsize = pe_get32 (dll, secptr1 + 16);
-# 	unsigned long fptr = pe_get32 (dll, secptr1 + 20);
-# 	lseek(dll, secptr1, SEEK_SET);
-# 	read(dll, sname, 8);
-# 	if (vaddr <= export_rva && vaddr+vsize > export_rva)
-# 	{
-# 	    expptr = fptr + (export_rva - vaddr);
-# 	    if (export_rva + export_size > vaddr + vsize)
-# 		export_size = vsize - (export_rva - vaddr);
-# 	    break;
-# 	}
-#     }
-#
-#     expdata = (unsigned char*)malloc(export_size);
-#     lseek (dll, expptr, SEEK_SET);
-#     read (dll, expdata, export_size);
-#     erva = expdata - export_rva;
-#
-#     nexp = pe_as32 (expdata+24);
-#     name_rvas = pe_as32 (expdata+32);
-#
-#     printf ("EXPORTS\n");
-#     for (i = 0; i<nexp; i++)
-#     {
-# 	unsigned long name_rva = pe_as32 (erva+name_rvas+i*4);
-# 	printf ("\t%s @ %ld ;\n", erva+name_rva, 1+ i);
-#     }
-#
-#     return 0;
-# }
-# /* impgen.c ends here */
-
-EOF
+  cygwin* | mingw* | pw32*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test "$GCC" != yes; then
+      with_gnu_ld=no
+    fi
+    ;;
+  openbsd*)
+    with_gnu_ld=no
     ;;
   esac
 
-  # We use sed instead of cat because bash on DJGPP gets confused if
-  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
-  # text mode, it properly converts lines to CR/LF.  This bash problem
-  # is reportedly fixed, but why not run on old versions too?
-  sed '$q' "$ltmain" >> "${ofile}T" || (rm -f "${ofile}T"; exit 1)
+  _LT_AC_TAGVAR(ld_shlibs, $1)=yes
+  if test "$with_gnu_ld" = yes; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='${wl}'
 
-  mv -f "${ofile}T" "$ofile" || \
-    (rm -f "$ofile" && cp "${ofile}T" "$ofile" && rm -f "${ofile}T")
-  chmod +x "$ofile"
-fi
-##
-## END FIXME
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix3* | aix4* | aix5*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test "$host_cpu" != ia64; then
+	_LT_AC_TAGVAR(ld_shlibs, $1)=no
+	cat <<EOF 1>&2
 
-])# _LT_AC_LTCONFIG_HACK
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
 
-# AC_LIBTOOL_DLOPEN - enable checks for dlopen support
-AC_DEFUN([AC_LIBTOOL_DLOPEN], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])])
+EOF
+      fi
+      ;;
 
-# AC_LIBTOOL_WIN32_DLL - declare package support for building win32 dll's
-AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_BEFORE([$0], [AC_LIBTOOL_SETUP])])
+    amigaos*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+
+      # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+      # that the semantics of dynamic libraries on AmigaOS, at least up
+      # to version 4, is to share data among multiple programs linked
+      # with the same dynamic library.  Since this doesn't match the
+      # behavior of shared libraries on other platforms, we can't use
+      # them.
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      ;;
 
-# AC_ENABLE_SHARED - implement the --enable-shared flag
-# Usage: AC_ENABLE_SHARED[(DEFAULT)]
-#   Where DEFAULT is either `yes' or `no'.  If omitted, it defaults to
-#   `yes'.
-AC_DEFUN([AC_ENABLE_SHARED],
-[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl
-AC_ARG_ENABLE(shared,
-changequote(<<, >>)dnl
-<<  --enable-shared[=PKGS]  build shared libraries [default=>>AC_ENABLE_SHARED_DEFAULT],
-changequote([, ])dnl
-[p=${PACKAGE-default}
-case $enableval in
-yes) enable_shared=yes ;;
-no) enable_shared=no ;;
-*)
-  enable_shared=no
-  # Look at the argument we got.  We use all the common list separators.
-  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
-  for pkg in $enableval; do
-    if test "X$pkg" = "X$p"; then
-      enable_shared=yes
-    fi
-  done
-  IFS="$ac_save_ifs"
-  ;;
-esac],
-enable_shared=AC_ENABLE_SHARED_DEFAULT)dnl
-])
+    beos*)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+	_LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+	# Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+	# support --undefined.  This deserves some investigation.  FIXME
+	_LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      else
+	_LT_AC_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
 
-# AC_DISABLE_SHARED - set the default shared flag to --disable-shared
-AC_DEFUN([AC_DISABLE_SHARED],
-[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
-AC_ENABLE_SHARED(no)])
+    cygwin* | mingw* | pw32*)
+      # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+      # as there is no search path for DLLs.
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_AC_TAGVAR(always_export_symbols, $1)=no
+      _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols'
+
+      if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+        _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib'
+	# If the export-symbols file already is a .def file (1st line
+	# is EXPORTS), use it as is; otherwise, prepend...
+	_LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+	  cp $export_symbols $output_objdir/$soname.def;
+	else
+	  echo EXPORTS > $output_objdir/$soname.def;
+	  cat $export_symbols >> $output_objdir/$soname.def;
+	fi~
+	$CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000  ${wl}--out-implib,$lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
 
-# AC_ENABLE_STATIC - implement the --enable-static flag
-# Usage: AC_ENABLE_STATIC[(DEFAULT)]
-#   Where DEFAULT is either `yes' or `no'.  If omitted, it defaults to
-#   `yes'.
-AC_DEFUN([AC_ENABLE_STATIC],
-[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl
-AC_ARG_ENABLE(static,
-changequote(<<, >>)dnl
-<<  --enable-static[=PKGS]  build static libraries [default=>>AC_ENABLE_STATIC_DEFAULT],
-changequote([, ])dnl
-[p=${PACKAGE-default}
-case $enableval in
-yes) enable_static=yes ;;
-no) enable_static=no ;;
-*)
-  enable_static=no
-  # Look at the argument we got.  We use all the common list separators.
-  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
-  for pkg in $enableval; do
-    if test "X$pkg" = "X$p"; then
-      enable_static=yes
-    fi
-  done
-  IFS="$ac_save_ifs"
-  ;;
-esac],
-enable_static=AC_ENABLE_STATIC_DEFAULT)dnl
-])
+    netbsd*)
+      if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+	_LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+	wlarc=
+      else
+	_LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	_LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
 
-# AC_DISABLE_STATIC - set the default static flag to --disable-static
-AC_DEFUN([AC_DISABLE_STATIC],
-[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
-AC_ENABLE_STATIC(no)])
+    solaris* | sysv5*)
+      if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+	_LT_AC_TAGVAR(ld_shlibs, $1)=no
+	cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
 
+EOF
+      elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+	_LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	_LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	_LT_AC_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    sunos4*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
 
-# AC_ENABLE_FAST_INSTALL - implement the --enable-fast-install flag
-# Usage: AC_ENABLE_FAST_INSTALL[(DEFAULT)]
-#   Where DEFAULT is either `yes' or `no'.  If omitted, it defaults to
-#   `yes'.
-AC_DEFUN([AC_ENABLE_FAST_INSTALL],
-[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl
-AC_ARG_ENABLE(fast-install,
-changequote(<<, >>)dnl
-<<  --enable-fast-install[=PKGS]  optimize for fast installation [default=>>AC_ENABLE_FAST_INSTALL_DEFAULT],
-changequote([, ])dnl
-[p=${PACKAGE-default}
-case $enableval in
-yes) enable_fast_install=yes ;;
-no) enable_fast_install=no ;;
-*)
-  enable_fast_install=no
-  # Look at the argument we got.  We use all the common list separators.
-  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
-  for pkg in $enableval; do
-    if test "X$pkg" = "X$p"; then
-      enable_fast_install=yes
+  linux*)
+    if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+        tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	_LT_AC_TAGVAR(archive_cmds, $1)="$tmp_archive_cmds"
+      supports_anon_versioning=no
+      case `$LD -v 2>/dev/null` in
+        *\ [01].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
+        *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+        *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+        *\ 2.11.*) ;; # other 2.11 versions
+        *) supports_anon_versioning=yes ;;
+      esac
+      if test $supports_anon_versioning = yes; then
+        _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~
+cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+$echo "local: *; };" >> $output_objdir/$libname.ver~
+        $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+      else
+        _LT_AC_TAGVAR(archive_expsym_cmds, $1)="$tmp_archive_cmds"
+      fi
+    else
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
     fi
-  done
-  IFS="$ac_save_ifs"
-  ;;
-esac],
-enable_fast_install=AC_ENABLE_FAST_INSTALL_DEFAULT)dnl
-])
-
-# AC_DISABLE_FAST_INSTALL - set the default to --disable-fast-install
-AC_DEFUN([AC_DISABLE_FAST_INSTALL],
-[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
-AC_ENABLE_FAST_INSTALL(no)])
+    ;;
 
-# AC_LIBTOOL_PICMODE - implement the --with-pic flag
-# Usage: AC_LIBTOOL_PICMODE[(MODE)]
-#   Where MODE is either `yes' or `no'.  If omitted, it defaults to
-#   `both'.
-AC_DEFUN([AC_LIBTOOL_PICMODE],
-[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
-pic_mode=ifelse($#,1,$1,default)])
+    *)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+	_LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	_LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	_LT_AC_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+    esac
 
+    if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = yes; then
+      runpath_var=LD_RUN_PATH
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+      _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+      # ancient GNU ld didn't support --whole-archive et. al.
+      if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+ 	_LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+      else
+  	_LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+      fi
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+      _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+      if test "$GCC" = yes && test -z "$link_static_flag"; then
+	# Neither direct hardcoding nor static linking is supported with a
+	# broken collect2.
+	_LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
+      fi
+      ;;
 
-# AC_PATH_TOOL_PREFIX - find a file program which can recognise shared library
-AC_DEFUN([AC_PATH_TOOL_PREFIX],
-[AC_MSG_CHECKING([for $1])
-AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
-[case $MAGIC_CMD in
-  /*)
-  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
-  ;;
-  ?:/*)
-  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a dos path.
-  ;;
-  *)
-  ac_save_MAGIC_CMD="$MAGIC_CMD"
-  IFS="${IFS=   }"; ac_save_ifs="$IFS"; IFS=":"
-dnl $ac_dummy forces splitting on constant user-supplied paths.
-dnl POSIX.2 word splitting is done only on the output of word expansions,
-dnl not every word.  This closes a longstanding sh security hole.
-  ac_dummy="ifelse([$2], , $PATH, [$2])"
-  for ac_dir in $ac_dummy; do
-    test -z "$ac_dir" && ac_dir=.
-    if test -f $ac_dir/$1; then
-      lt_cv_path_MAGIC_CMD="$ac_dir/$1"
-      if test -n "$file_magic_test_file"; then
-	case $deplibs_check_method in
-	"file_magic "*)
-	  file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
-	  MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
-	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
-	    egrep "$file_magic_regex" > /dev/null; then
-	    :
-	  else
-	    cat <<EOF 1>&2
+    aix4* | aix5*)
+      if test "$host_cpu" = ia64; then
+	# On IA64, the linker does run time linking by default, so we don't
+	# have to do anything special.
+	aix_use_runtimelinking=no
+	exp_sym_flag='-Bexport'
+	no_entry_flag=""
+      else
+	# If we're using GNU nm, then we don't want the "-C" option.
+	# -C means demangle to AIX nm, but means don't demangle with GNU nm
+	if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+	  _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+	else
+	  _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+	fi
+	aix_use_runtimelinking=no
+
+	# Test if we are trying to use run time linking or normal
+	# AIX style linking. If -brtl is somewhere in LDFLAGS, we
+	# need to do runtime linking.
+	case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*)
+	  for ld_flag in $LDFLAGS; do
+  	  if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+  	    aix_use_runtimelinking=yes
+  	    break
+  	  fi
+	  done
+	esac
 
-*** Warning: the command libtool uses to detect shared libraries,
-*** $file_magic_cmd, produces output that libtool cannot recognize.
-*** The result is that libtool may fail to recognize shared libraries
-*** as such.  This will affect the creation of libtool libraries that
-*** depend on shared libraries, but programs linked with such libtool
-*** libraries will work regardless of this problem.  Nevertheless, you
-*** may want to report the problem to your system manager and/or to
-*** bug-libtool@gnu.org
+	exp_sym_flag='-bexport'
+	no_entry_flag='-bnoentry'
+      fi
 
-EOF
-	  fi ;;
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      _LT_AC_TAGVAR(archive_cmds, $1)=''
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+      _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+      if test "$GCC" = yes; then
+	case $host_os in aix4.[012]|aix4.[012].*)
+	# We only want to do this on AIX 4.2 and lower, the check
+	# below for broken collect2 doesn't work under 4.3+
+	  collect2name=`${CC} -print-prog-name=collect2`
+	  if test -f "$collect2name" && \
+  	   strings "$collect2name" | grep resolve_lib_name >/dev/null
+	  then
+  	  # We have reworked collect2
+  	  _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+	  else
+  	  # We have old collect2
+  	  _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
+  	  # It fails to find uninstalled libraries when the uninstalled
+  	  # path is not listed in the libpath.  Setting hardcode_minus_L
+  	  # to unsupported forces relinking
+  	  _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+  	  _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+  	  _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+	  fi
 	esac
+	shared_flag='-shared'
+      else
+	# not using gcc
+	if test "$host_cpu" = ia64; then
+  	# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+  	# chokes on -Wl,-G. The following line is correct:
+	  shared_flag='-G'
+	else
+  	if test "$aix_use_runtimelinking" = yes; then
+	    shared_flag='${wl}-G'
+	  else
+	    shared_flag='${wl}-bM:SRE'
+  	fi
+	fi
       fi
-      break
-    fi
-  done
-  IFS="$ac_save_ifs"
-  MAGIC_CMD="$ac_save_MAGIC_CMD"
-  ;;
-esac])
-MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
-if test -n "$MAGIC_CMD"; then
-  AC_MSG_RESULT($MAGIC_CMD)
-else
-  AC_MSG_RESULT(no)
-fi
-])
 
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+      if test "$aix_use_runtimelinking" = yes; then
+	# Warning - without using the other runtime loading flags (-brtl),
+	# -berok will link without error, but may produce a broken library.
+	_LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok'
+       # Determine the default libpath from the value encoded in an empty executable.
+       _LT_AC_SYS_LIBPATH_AIX
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+	_LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+       else
+	if test "$host_cpu" = ia64; then
+	  _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+	  _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+	  _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"
+	else
+	 # Determine the default libpath from the value encoded in an empty executable.
+	 _LT_AC_SYS_LIBPATH_AIX
+	 _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+	  # Warning - without using the other run time loading flags,
+	  # -berok will link without error, but may produce a broken library.
+	  _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+	  _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+	  # -bexpall does not export symbols beginning with underscore (_)
+	  _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+	  # Exported symbols can be pulled into shared objects from archives
+	  _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' '
+	  _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+	  # This is similar to how AIX traditionally builds it's shared libraries.
+	  _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+	fi
+      fi
+      ;;
 
-# AC_PATH_MAGIC - find a file program which can recognise a shared library
-AC_DEFUN([AC_PATH_MAGIC],
-[AC_REQUIRE([AC_CHECK_TOOL_PREFIX])dnl
-AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin:$PATH)
-if test -z "$lt_cv_path_MAGIC_CMD"; then
-  if test -n "$ac_tool_prefix"; then
-    AC_PATH_TOOL_PREFIX(file, /usr/bin:$PATH)
-  else
-    MAGIC_CMD=:
-  fi
-fi
-])
+    amigaos*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+      # see comment about different semantics on the GNU ld section
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      ;;
 
+    bsdi[[45]]*)
+      _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
+      ;;
 
-# AC_PROG_LD - find the path to the GNU or non-GNU linker
-AC_DEFUN([AC_PROG_LD],
-[AC_ARG_WITH(gnu-ld,
-[  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]],
-test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
-AC_REQUIRE([AC_PROG_CC])dnl
-AC_REQUIRE([AC_CANONICAL_HOST])dnl
-AC_REQUIRE([AC_CANONICAL_BUILD])dnl
-AC_REQUIRE([_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR])dnl
-ac_prog=ld
-if test "$GCC" = yes; then
-  # Check if gcc -print-prog-name=ld gives a path.
-  AC_MSG_CHECKING([for ld used by GCC])
-  case $host in
-  *-*-mingw*)
-    # gcc leaves a trailing carriage return which upsets mingw
-    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
-  *)
-    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
-  esac
-  case $ac_prog in
-    # Accept absolute paths.
-    [[\\/]]* | [[A-Za-z]]:[[\\/]]*)
-      re_direlt='/[[^/]][[^/]]*/\.\./'
-      # Canonicalize the path of ld
-      ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
-      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
-	ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
-      done
-      test -z "$LD" && LD="$ac_prog"
+    cygwin* | mingw* | pw32*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+      _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+      # Tell ltmain to make .lib files, not .a files.
+      libext=lib
+      # Tell ltmain to make .dll files, not .so files.
+      shrext_cmds=".dll"
+      # FIXME: Setting linknames here is a bad hack.
+      _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+      # The linker will automatically build a .lib file if we build a DLL.
+      _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true'
+      # FIXME: Should let the user specify the lib program.
+      _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs'
+      fix_srcfile_path='`cygpath -w "$srcfile"`'
+      _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
       ;;
-  "")
-    # If it fails, then pretend we aren't using GCC.
-    ac_prog=ld
-    ;;
-  *)
-    # If it is relative, then search for the first ld in PATH.
-    with_gnu_ld=unknown
-    ;;
-  esac
-elif test "$with_gnu_ld" = yes; then
-  AC_MSG_CHECKING([for GNU ld])
-else
-  AC_MSG_CHECKING([for non-GNU ld])
-fi
-AC_CACHE_VAL(lt_cv_path_LD,
-[if test -z "$LD"; then
-  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
-  for ac_dir in $PATH; do
-    test -z "$ac_dir" && ac_dir=.
-    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
-      lt_cv_path_LD="$ac_dir/$ac_prog"
-      # Check to see if the program is GNU ld.  I'd rather use --version,
-      # but apparently some GNU ld's only accept -v.
-      # Break only if it was the GNU/non-GNU ld that we prefer.
-      if "$lt_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
-	test "$with_gnu_ld" != no && break
-      else
-	test "$with_gnu_ld" != yes && break
-      fi
+
+    darwin* | rhapsody*)
+      case "$host_os" in
+        rhapsody* | darwin1.[[012]])
+         _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress'
+         ;;
+       *) # Darwin 1.3 on
+         if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+           _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+         else
+           case ${MACOSX_DEPLOYMENT_TARGET} in
+             10.[[012]])
+               _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+               ;;
+             10.*)
+               _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup'
+               ;;
+           esac
+         fi
+         ;;
+      esac
+      _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_AC_TAGVAR(hardcode_direct, $1)=no
+      _LT_AC_TAGVAR(hardcode_automatic, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+      _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=''
+      _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+    if test "$GCC" = yes ; then
+    	output_verbose_link_cmd='echo'
+        _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+      _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+      # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+      _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+      _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    else
+      case "$cc_basename" in
+        xlc*)
+         output_verbose_link_cmd='echo'
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+         _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+         _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          ;;
+       *)
+         _LT_AC_TAGVAR(ld_shlibs, $1)=no
+          ;;
+      esac
     fi
-  done
-  IFS="$ac_save_ifs"
-else
-  lt_cv_path_LD="$LD" # Let the user override the test with a path.
-fi])
-LD="$lt_cv_path_LD"
-if test -n "$LD"; then
-  AC_MSG_RESULT($LD)
-else
-  AC_MSG_RESULT(no)
-fi
-test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
-AC_PROG_LD_GNU
-])
+      ;;
 
-# AC_PROG_LD_GNU -
-AC_DEFUN([AC_PROG_LD_GNU],
-[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
-[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
-if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
-  lt_cv_prog_gnu_ld=yes
-else
-  lt_cv_prog_gnu_ld=no
-fi])
-with_gnu_ld=$lt_cv_prog_gnu_ld
-])
+    dgux*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
 
-# AC_PROG_LD_RELOAD_FLAG - find reload flag for linker
-#   -- PORTME Some linkers may need a different reload flag.
-AC_DEFUN([AC_PROG_LD_RELOAD_FLAG],
-[AC_CACHE_CHECK([for $LD option to reload object files], lt_cv_ld_reload_flag,
-[lt_cv_ld_reload_flag='-r'])
-reload_flag=$lt_cv_ld_reload_flag
-test -n "$reload_flag" && reload_flag=" $reload_flag"
-])
+    freebsd1*)
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      ;;
 
-# AC_DEPLIBS_CHECK_METHOD - how to check for library dependencies
-#  -- PORTME fill in with the dynamic library characteristics
-AC_DEFUN([AC_DEPLIBS_CHECK_METHOD],
-[AC_CACHE_CHECK([how to recognise dependant libraries],
-lt_cv_deplibs_check_method,
-[lt_cv_file_magic_cmd='$MAGIC_CMD'
-lt_cv_file_magic_test_file=
-lt_cv_deplibs_check_method='unknown'
-# Need to set the preceding variable on all platforms that support
-# interlibrary dependencies.
-# 'none' -- dependencies not supported.
-# `unknown' -- same as none, but documents that we really don't know.
-# 'pass_all' -- all dependencies passed with no checks.
-# 'test_compile' -- check by making test program.
-# 'file_magic [[regex]]' -- check by looking for files in library path
-# which responds to the $file_magic_cmd with a given egrep regex.
-# If you have `file' or equivalent on your system and you're not sure
-# whether `pass_all' will *always* work, you probably want this one.
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
 
-case $host_os in
-aix4* | aix5*)
-  lt_cv_deplibs_check_method=pass_all
-  ;;
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
 
-beos*)
-  lt_cv_deplibs_check_method=pass_all
-  ;;
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | kfreebsd*-gnu)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
 
-bsdi4*)
-  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
-  lt_cv_file_magic_cmd='/usr/bin/file -L'
-  lt_cv_file_magic_test_file=/shlib/libc.so
-  ;;
+    hpux9*)
+      if test "$GCC" = yes; then
+	_LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+	_LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+      ;;
 
-cygwin* | mingw* | pw32*)
-  lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
-  lt_cv_file_magic_cmd='$OBJDUMP -f'
-  ;;
+    hpux10* | hpux11*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+	case "$host_cpu" in
+	hppa*64*|ia64*)
+	  _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	  _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	esac
+      else
+	case "$host_cpu" in
+	hppa*64*|ia64*)
+	  _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  ;;
+	*)
+	  _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+	  ;;
+	esac
+      fi
+      if test "$with_gnu_ld" = no; then
+	case "$host_cpu" in
+	hppa*64*)
+	  _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+	  _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
+	  _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+	  _LT_AC_TAGVAR(hardcode_direct, $1)=no
+	  _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+	  ;;
+	ia64*)
+	  _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+	  _LT_AC_TAGVAR(hardcode_direct, $1)=no
+	  _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+
+	  # hardcode_minus_L: Not really in the search PATH,
+	  # but as the default location of the library.
+	  _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+	  ;;
+	*)
+	  _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+	  _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+	  _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+	  _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+
+	  # hardcode_minus_L: Not really in the search PATH,
+	  # but as the default location of the library.
+	  _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+	  ;;
+	esac
+      fi
+      ;;
 
-darwin* | rhapsody*)
-  lt_cv_deplibs_check_method='file_magic Mach-O dynamically linked shared library'
-  lt_cv_file_magic_cmd='/usr/bin/file -L'
-  case "$host_os" in
-  rhapsody* | darwin1.[[012]])
-    lt_cv_file_magic_test_file=`echo /System/Library/Frameworks/System.framework/Versions/*/System | head -1`
-    ;;
-  *) # Darwin 1.3 on
-    lt_cv_file_magic_test_file='/usr/lib/libSystem.dylib'
-    ;;
-  esac
-  ;;
+    irix5* | irix6* | nonstopux*)
+      if test "$GCC" = yes; then
+	_LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+	_LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+	_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir'
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
 
-freebsd*)
-  if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
-    case $host_cpu in
-    i*86 )
-      # Not sure whether the presence of OpenBSD here was a mistake.
-      # Let's accept both of them until this is cleared up.
-      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[[3-9]]86 (compact )?demand paged shared library'
-      lt_cv_file_magic_cmd=/usr/bin/file
-      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+    netbsd*)
+      if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+	_LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+	_LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    newsos6)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    openbsd*)
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+	_LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+	_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+      else
+       case $host_os in
+	 openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
+	   _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+	   _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+	   ;;
+	 *)
+	   _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	   _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	   ;;
+       esac
+      fi
       ;;
-    esac
-  else
-    lt_cv_deplibs_check_method=pass_all
-  fi
-  ;;
 
-gnu*)
-  lt_cv_deplibs_check_method=pass_all
-  ;;
+    os2*)
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+      _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+      ;;
 
-hpux10.20*|hpux11*)
-  lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library'
-  lt_cv_file_magic_cmd=/usr/bin/file
-  lt_cv_file_magic_test_file=/usr/lib/libc.sl
-  ;;
+    osf3*)
+      if test "$GCC" = yes; then
+	_LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+	_LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+	_LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+	_LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+      ;;
 
-irix5* | irix6*)
-  case $host_os in
-  irix5*)
-    # this will be overridden with pass_all, but let us keep it just in case
-    lt_cv_deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1"
-    ;;
-  *)
-    case $LD in
-    *-32|*"-32 ") libmagic=32-bit;;
-    *-n32|*"-n32 ") libmagic=N32;;
-    *-64|*"-64 ") libmagic=64-bit;;
-    *) libmagic=never-match;;
-    esac
-    # this will be overridden with pass_all, but let us keep it just in case
-    lt_cv_deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[[1234]] dynamic lib MIPS - version 1"
-    ;;
-  esac
-  lt_cv_file_magic_test_file=`echo /lib${libsuff}/libc.so*`
-  lt_cv_deplibs_check_method=pass_all
-  ;;
+    osf4* | osf5*)	# as osf3* with the addition of -msym flag
+      if test "$GCC" = yes; then
+	_LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+	_LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      else
+	_LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+	_LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+	_LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+	$LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp'
 
-# This must be Linux ELF.
-linux-gnu*)
-  case $host_cpu in
-  alpha* | hppa* | i*86 | powerpc* | sparc* | ia64* )
-    lt_cv_deplibs_check_method=pass_all ;;
-  *)
-    # glibc up to 2.1.1 does not perform some relocations on ARM
-    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;;
-  esac
-  lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
-  ;;
+	# Both c and cxx compiler support -rpath directly
+	_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+      ;;
 
-netbsd*)
-  if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
-    lt_cv_deplibs_check_method='match_pattern /lib[[^/\.]]+\.so\.[[0-9]]+\.[[0-9]]+$'
-  else
-    lt_cv_deplibs_check_method='match_pattern /lib[[^/\.]]+\.so$'
-  fi
-  ;;
+    sco3.2v5*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+      runpath_var=LD_RUN_PATH
+      hardcode_runpath_var=yes
+      ;;
 
-newos6*)
-  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
-  lt_cv_file_magic_cmd=/usr/bin/file
-  lt_cv_file_magic_test_file=/usr/lib/libnls.so
-  ;;
+    solaris*)
+      _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text'
+      if test "$GCC" = yes; then
+	_LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+	  $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+      else
+	_LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	_LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+  	$LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      case $host_os in
+      solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+      *) # Supported since Solaris 2.6 (maybe 2.5.1?)
+	_LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;;
+      esac
+      _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
 
-nto-qnx)
-  lt_cv_deplibs_check_method=unknown
-  ;;
+    sunos4*)
+      if test "x$host_vendor" = xsequent; then
+	# Use $CC to link under sequent, because it throws in some extra .o
+	# files that make .init and .fini sections work.
+	_LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	_LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
 
-openbsd*)
-  lt_cv_file_magic_cmd=/usr/bin/file
-  lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
-  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
-    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB shared object'
-  else
-    lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library'
-  fi
-  ;;
+    sysv4)
+      case $host_vendor in
+	sni)
+	  _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true???
+	;;
+	siemens)
+	  ## LD is ld it makes a PLAMLIB
+	  ## CC just makes a GrossModule.
+	  _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+	  _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
+	  _LT_AC_TAGVAR(hardcode_direct, $1)=no
+        ;;
+	motorola)
+	  _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
+	;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
 
-osf3* | osf4* | osf5*)
-  # this will be overridden with pass_all, but let us keep it just in case
-  lt_cv_deplibs_check_method='file_magic COFF format alpha shared library'
-  lt_cv_file_magic_test_file=/shlib/libc.so
-  lt_cv_deplibs_check_method=pass_all
-  ;;
+    sysv4.3*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
+      ;;
 
-sco3.2v5*)
-  lt_cv_deplibs_check_method=pass_all
-  ;;
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	_LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+	runpath_var=LD_RUN_PATH
+	hardcode_runpath_var=yes
+	_LT_AC_TAGVAR(ld_shlibs, $1)=yes
+      fi
+      ;;
 
-solaris*)
-  lt_cv_deplibs_check_method=pass_all
-  lt_cv_file_magic_test_file=/lib/libc.so
-  ;;
+    sysv4.2uw2*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      hardcode_runpath_var=yes
+      runpath_var=LD_RUN_PATH
+      ;;
 
-sysv5uw[[78]]* | sysv4*uw2*)
-  lt_cv_deplibs_check_method=pass_all
-  ;;
+   sysv5OpenUNIX8* | sysv5UnixWare7* |  sysv5uw[[78]]* | unixware7*)
+      _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z ${wl}text'
+      if test "$GCC" = yes; then
+	_LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	_LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      runpath_var='LD_RUN_PATH'
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
 
-sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
-  case $host_vendor in
-  motorola)
-    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
-    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
-    ;;
-  ncr)
-    lt_cv_deplibs_check_method=pass_all
-    ;;
-  sequent)
-    lt_cv_file_magic_cmd='/bin/file'
-    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
-    ;;
-  sni)
-    lt_cv_file_magic_cmd='/bin/file'
-    lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
-    lt_cv_file_magic_test_file=/lib/libc.so
-    ;;
-  esac
-  ;;
-esac
-])
-file_magic_cmd=$lt_cv_file_magic_cmd
-deplibs_check_method=$lt_cv_deplibs_check_method
+    sysv5*)
+      _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text'
+      # $CC -shared without GNU ld will not create a library from C++
+      # object files and a static libstdc++, better avoid it by now
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+  		$LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      runpath_var='LD_RUN_PATH'
+      ;;
+
+    uts4*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *)
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      ;;
+    esac
+  fi
 ])
+AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)])
+test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
 
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
 
-# AC_PROG_NM - find the path to a BSD-compatible name lister
-AC_DEFUN([AC_PROG_NM],
-[AC_REQUIRE([_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR])dnl
-AC_MSG_CHECKING([for BSD-compatible nm])
-AC_CACHE_VAL(lt_cv_path_NM,
-[if test -n "$NM"; then
-  # Let the user override the test.
-  lt_cv_path_NM="$NM"
-else
-  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
-  for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
-    test -z "$ac_dir" && ac_dir=.
-    tmp_nm=$ac_dir/${ac_tool_prefix}nm
-    if test -f $tmp_nm || test -f $tmp_nm$ac_exeext ; then
-      # Check to see if the nm accepts a BSD-compat flag.
-      # Adding the `sed 1q' prevents false positives on HP-UX, which says:
-      #   nm: unknown option "B" ignored
-      # Tru64's nm complains that /dev/null is an invalid object file
-      if ($tmp_nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep '(/dev/null|Invalid file or object type)' >/dev/null; then
-	lt_cv_path_NM="$tmp_nm -B"
-	break
-      elif ($tmp_nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
-	lt_cv_path_NM="$tmp_nm -p"
-	break
+#
+# Do we need to explicitly link libc?
+#
+case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in
+x|xyes)
+  # Assume -lc should be added
+  _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $_LT_AC_TAGVAR(archive_cmds, $1) in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      AC_MSG_CHECKING([whether -lc should be explicitly linked in])
+      $rm conftest*
+      printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+      if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
+        soname=conftest
+        lib=conftest
+        libobjs=conftest.$ac_objext
+        deplibs=
+        wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)
+        compiler_flags=-v
+        linker_flags=-v
+        verstring=
+        output_objdir=.
+        libname=conftest
+        lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1)
+        _LT_AC_TAGVAR(allow_undefined_flag, $1)=
+        if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1)
+        then
+	  _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+        else
+	  _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+        fi
+        _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
       else
-	lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
-	continue # so that we can try to find one that supports BSD flags
+        cat conftest.err 1>&5
       fi
-    fi
-  done
-  IFS="$ac_save_ifs"
-  test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
-fi])
-NM="$lt_cv_path_NM"
-AC_MSG_RESULT([$NM])
-])
-
-# AC_CHECK_LIBM - check for math library
-AC_DEFUN([AC_CHECK_LIBM],
-[AC_REQUIRE([AC_CANONICAL_HOST])dnl
-LIBM=
-case $host in
-*-*-beos* | *-*-cygwin* | *-*-pw32*)
-  # These system don't have libm
-  ;;
-*-ncr-sysv4.3*)
-  AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
-  AC_CHECK_LIB(m, main, LIBM="$LIBM -lm")
-  ;;
-*)
-  AC_CHECK_LIB(m, main, LIBM="-lm")
+      $rm conftest*
+      AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)])
+      ;;
+    esac
+  fi
   ;;
 esac
-])
+])# AC_LIBTOOL_PROG_LD_SHLIBS
 
-# AC_LIBLTDL_CONVENIENCE[(dir)] - sets LIBLTDL to the link flags for
-# the libltdl convenience library and INCLTDL to the include flags for
-# the libltdl header and adds --enable-ltdl-convenience to the
-# configure arguments.  Note that LIBLTDL and INCLTDL are not
-# AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called.  If DIR is not
-# provided, it is assumed to be `libltdl'.  LIBLTDL will be prefixed
-# with '${top_builddir}/' and INCLTDL will be prefixed with
-# '${top_srcdir}/' (note the single quotes!).  If your package is not
-# flat and you're not using automake, define top_builddir and
-# top_srcdir appropriately in the Makefiles.
-AC_DEFUN([AC_LIBLTDL_CONVENIENCE],
-[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
-  case $enable_ltdl_convenience in
-  no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
-  "") enable_ltdl_convenience=yes
-      ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
-  esac
-  LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la
-  INCLTDL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
-])
 
-# AC_LIBLTDL_INSTALLABLE[(dir)] - sets LIBLTDL to the link flags for
-# the libltdl installable library and INCLTDL to the include flags for
-# the libltdl header and adds --enable-ltdl-install to the configure
-# arguments.  Note that LIBLTDL and INCLTDL are not AC_SUBSTed, nor is
-# AC_CONFIG_SUBDIRS called.  If DIR is not provided and an installed
-# libltdl is not found, it is assumed to be `libltdl'.  LIBLTDL will
-# be prefixed with '${top_builddir}/' and INCLTDL will be prefixed
-# with '${top_srcdir}/' (note the single quotes!).  If your package is
-# not flat and you're not using automake, define top_builddir and
-# top_srcdir appropriately in the Makefiles.
-# In the future, this macro may have to be called after AC_PROG_LIBTOOL.
-AC_DEFUN([AC_LIBLTDL_INSTALLABLE],
-[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
-  AC_CHECK_LIB(ltdl, main,
-  [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no],
-  [if test x"$enable_ltdl_install" = xno; then
-     AC_MSG_WARN([libltdl not installed, but installation disabled])
-   else
-     enable_ltdl_install=yes
-   fi
-  ])
-  if test x"$enable_ltdl_install" = x"yes"; then
-    ac_configure_args="$ac_configure_args --enable-ltdl-install"
-    LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la
-    INCLTDL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
-  else
-    ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
-    LIBLTDL="-lltdl"
-    INCLTDL=
-  fi
-])
+# _LT_AC_FILE_LTDLL_C
+# -------------------
+# Be careful that the start marker always follows a newline.
+AC_DEFUN([_LT_AC_FILE_LTDLL_C], [
+# /* ltdll.c starts here */
+# #define WIN32_LEAN_AND_MEAN
+# #include <windows.h>
+# #undef WIN32_LEAN_AND_MEAN
+# #include <stdio.h>
+#
+# #ifndef __CYGWIN__
+# #  ifdef __CYGWIN32__
+# #    define __CYGWIN__ __CYGWIN32__
+# #  endif
+# #endif
+#
+# #ifdef __cplusplus
+# extern "C" {
+# #endif
+# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved);
+# #ifdef __cplusplus
+# }
+# #endif
+#
+# #ifdef __CYGWIN__
+# #include <cygwin/cygwin_dll.h>
+# DECLARE_CYGWIN_DLL( DllMain );
+# #endif
+# HINSTANCE __hDllInstance_base;
+#
+# BOOL APIENTRY
+# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
+# {
+#   __hDllInstance_base = hInst;
+#   return TRUE;
+# }
+# /* ltdll.c ends here */
+])# _LT_AC_FILE_LTDLL_C
+
+
+# _LT_AC_TAGVAR(VARNAME, [TAGNAME])
+# ---------------------------------
+AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])])
+
 
 # old names
 AC_DEFUN([AM_PROG_LIBTOOL],   [AC_PROG_LIBTOOL])
@@ -3631,3 +5912,76 @@ AC_DEFUN([AM_PROG_NM],        [AC_PROG_NM])
 
 # This is just to silence aclocal about the macro not being used
 ifelse([AC_DISABLE_FAST_INSTALL])
+
+AC_DEFUN([LT_AC_PROG_GCJ],
+[AC_CHECK_TOOL(GCJ, gcj, no)
+  test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2"
+  AC_SUBST(GCJFLAGS)
+])
+
+AC_DEFUN([LT_AC_PROG_RC],
+[AC_CHECK_TOOL(RC, windres, no)
+])
+
+############################################################
+# NOTE: This macro has been submitted for inclusion into   #
+#  GNU Autoconf as AC_PROG_SED.  When it is available in   #
+#  a released version of Autoconf we should remove this    #
+#  macro and use it instead.                               #
+############################################################
+# LT_AC_PROG_SED
+# --------------
+# Check for a fully-functional sed program, that truncates
+# as few characters as possible.  Prefer GNU sed if found.
+AC_DEFUN([LT_AC_PROG_SED],
+[AC_MSG_CHECKING([for a sed that does not truncate output])
+AC_CACHE_VAL(lt_cv_path_SED,
+[# Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for lt_ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
+        lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+      fi
+    done
+  done
+done
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+  test ! -f $lt_ac_sed && break
+  cat /dev/null > conftest.in
+  lt_ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+  # Check for GNU sed and select it if it is found.
+  if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+    lt_cv_path_SED=$lt_ac_sed
+    break
+  fi
+  while true; do
+    cat conftest.in conftest.in >conftest.tmp
+    mv conftest.tmp conftest.in
+    cp conftest.in conftest.nl
+    echo >>conftest.nl
+    $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+    cmp -s conftest.out conftest.nl || break
+    # 10000 chars as input seems more than enough
+    test $lt_ac_count -gt 10 && break
+    lt_ac_count=`expr $lt_ac_count + 1`
+    if test $lt_ac_count -gt $lt_ac_max; then
+      lt_ac_max=$lt_ac_count
+      lt_cv_path_SED=$lt_ac_sed
+    fi
+  done
+done
+])
+SED=$lt_cv_path_SED
+AC_MSG_RESULT([$SED])
+])
diff --git a/storage/bdb/dist/aclocal/mutex.ac b/storage/bdb/dist/aclocal/mutex.ac
index f3f5529c74f60124749cb6c819be29a44597a5d9..959ed4ebe56c75ab356c18aa59437973c6a8ad5c 100644
--- a/storage/bdb/dist/aclocal/mutex.ac
+++ b/storage/bdb/dist/aclocal/mutex.ac
@@ -1,28 +1,6 @@
-# $Id: mutex.ac,v 11.38 2002/07/25 20:07:52 sue Exp $
+# $Id: mutex.ac,v 11.46 2004/07/09 16:23:19 bostic Exp $
 
 # POSIX pthreads tests: inter-process safe and intra-process only.
-#
-# We need to run a test here, because the PTHREAD_PROCESS_SHARED flag compiles
-# fine on problematic systems, but won't actually work.  This is a problem for
-# cross-compilation environments.  I think inter-process mutexes are as likely
-# to fail in cross-compilation environments as real ones (especially since the
-# likely cross-compilation environment is Linux, where inter-process mutexes
-# don't currently work -- the latest estimate I've heard is Q1 2002, as part
-# of IBM's NGPT package).  So:
-#
-# If checking for inter-process pthreads mutexes:
-#	If it's local, run a test.
-#	If it's a cross-compilation, fail.
-#
-# If the user specified pthreads mutexes and we're checking for intra-process
-# mutexes only:
-#	If it's local, run a test.
-#	If it's a cross-compilation, run a link-test.
-#
-# So, the thing you can't do here is configure for inter-process POSIX pthread
-# mutexes when cross-compiling.  Since we're using the GNU/Cygnus toolchain for
-# cross-compilation, the target system is likely Linux or *BSD, so we're doing
-# the right thing.
 AC_DEFUN(AM_PTHREADS_SHARED, [
 AC_TRY_RUN([
 #include <pthread.h>
@@ -44,7 +22,27 @@ main() {
 	pthread_cond_destroy(&cond) ||
 	pthread_condattr_destroy(&condattr) ||
 	pthread_mutexattr_destroy(&mutexattr));
-}], [db_cv_mutex="$1"],, [db_cv_mutex="no"])])
+}], [db_cv_mutex="$1"],,
+AC_TRY_LINK([
+#include <pthread.h>],[
+	pthread_cond_t cond;
+	pthread_mutex_t mutex;
+	pthread_condattr_t condattr;
+	pthread_mutexattr_t mutexattr;
+	exit (
+	pthread_condattr_init(&condattr) ||
+	pthread_condattr_setpshared(&condattr, PTHREAD_PROCESS_SHARED) ||
+	pthread_mutexattr_init(&mutexattr) ||
+	pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED) ||
+	pthread_cond_init(&cond, &condattr) ||
+	pthread_mutex_init(&mutex, &mutexattr) ||
+	pthread_mutex_lock(&mutex) ||
+	pthread_mutex_unlock(&mutex) ||
+	pthread_mutex_destroy(&mutex) ||
+	pthread_cond_destroy(&cond) ||
+	pthread_condattr_destroy(&condattr) ||
+	pthread_mutexattr_destroy(&mutexattr));
+], [db_cv_mutex="$1"]))])
 AC_DEFUN(AM_PTHREADS_PRIVATE, [
 AC_TRY_RUN([
 #include <pthread.h>
@@ -91,7 +89,6 @@ AC_DEFUN(AM_DEFINE_MUTEXES, [
 # other ports.
 AH_TEMPLATE(HAVE_MUTEX_VMS, [Define to 1 to use VMS mutexes.])
 AH_TEMPLATE(HAVE_MUTEX_VXWORKS, [Define to 1 to use VxWorks mutexes.])
-AH_TEMPLATE(HAVE_MUTEX_WIN32, [Define to 1 to use Windows mutexes.])
 
 AC_CACHE_CHECK([for mutexes], db_cv_mutex, [
 db_cv_mutex=no
@@ -104,37 +101,32 @@ orig_libs=$LIBS
 # is already using one type of mutex and doesn't want to mix-and-match (for
 # example, on Solaris, which has POSIX, UI and LWP mutexes).  Second, the
 # applications POSIX pthreads mutexes don't support inter-process locking,
-# but the application wants to use them anyway (for example, current Linux
-# and *BSD systems).
-#
-# If we're on Solaris, we insist that -lthread or -lpthread be used.  The
-# problem is the Solaris C library has UI/POSIX interface stubs, but they're
-# broken, configuring them for inter-process mutexes doesn't return an error,
-# but it doesn't work either.   Otherwise, we try first without the library
-# and then with it: there's some information that SCO/UnixWare/OpenUNIX needs
-# this. [#4950]
+# but the application wants to use them anyway (for example, some Linux and
+# *BSD systems).
 #
 # Test for LWP threads before testing for UI/POSIX threads, we prefer them
 # on Solaris.  There's a bug in SunOS 5.7 where applications get pwrite, not
 # pwrite64, if they load the C library before the appropriate threads library,
 # e.g., tclsh using dlopen to load the DB library.  By using LWP threads we
 # avoid answering lots of user questions, not to mention the bugs.
+#
+# Otherwise, test for POSIX threads before UI threads.  There are Linux systems
+# that support a UI compatibility mode, and applications are more likely to be
+# written for POSIX threads than UI threads.
+#
+# Try and link with a threads library if possible.  The problem is the Solaris
+# C library has UI/POSIX interface stubs, but they're broken, configuring them
+# for inter-process mutexes doesn't return an error, but it doesn't work either.
 if test "$db_cv_posixmutexes" = yes; then
-	case "$host_os" in
-	solaris*)
-		db_cv_mutex="posix_library_only";;
-	*)
-		db_cv_mutex="posix_only";;
-	esac
+	db_cv_mutex="posix_only";
 fi
-
 if test "$db_cv_uimutexes" = yes; then
-	case "$host_os" in
-	solaris*)
-		db_cv_mutex="ui_library_only";;
-	*)
-		db_cv_mutex="ui_only";;
-	esac
+	db_cv_mutex="ui_only";
+fi
+
+# User-specified Win32 mutexes (MinGW build)
+if test "$db_cv_mingw" = "yes"; then
+	db_cv_mutex=win32/gcc
 fi
 
 # LWP threads: _lwp_XXX
@@ -151,10 +143,33 @@ AC_TRY_LINK([
 ], [db_cv_mutex="Solaris/lwp"])
 fi
 
-# UI threads: thr_XXX
+# POSIX.1 pthreads: pthread_XXX
 #
-# Try with and without the -lthread library.
+# If the user specified we use POSIX pthreads mutexes, and we fail to find the
+# full interface, try and configure for just intra-process support.
+if test "$db_cv_mutex" = no -o "$db_cv_mutex" = "posix_only"; then
+	LIBS="$LIBS -lpthread"
+	AM_PTHREADS_SHARED("POSIX/pthreads/library")
+	LIBS="$orig_libs"
+fi
+if test "$db_cv_mutex" = no -o "$db_cv_mutex" = "posix_only"; then
+	AM_PTHREADS_SHARED("POSIX/pthreads")
+fi
+if test "$db_cv_mutex" = "posix_only"; then
+	AM_PTHREADS_PRIVATE("POSIX/pthreads/private")
+fi
+if test "$db_cv_mutex" = "posix_only"; then
+	LIBS="$LIBS -lpthread"
+	AM_PTHREADS_PRIVATE("POSIX/pthreads/library/private")
+	LIBS="$orig_libs"
+fi
+if test "$db_cv_mutex" = "posix_only"; then
+	AC_MSG_ERROR([unable to find POSIX 1003.1 mutex interfaces])
+fi
+
+# UI threads: thr_XXX
 if test "$db_cv_mutex" = no -o "$db_cv_mutex" = "ui_only"; then
+LIBS="$LIBS -lthread"
 AC_TRY_LINK([
 #include <thread.h>
 #include <synch.h>],[
@@ -166,11 +181,10 @@ AC_TRY_LINK([
 	cond_init(&cond, type, NULL) ||
 	mutex_lock(&mutex) ||
 	mutex_unlock(&mutex));
-], [db_cv_mutex="UI/threads"])
+], [db_cv_mutex="UI/threads/library"])
+LIBS="$orig_libs"
 fi
-if test "$db_cv_mutex" = no -o \
-    "$db_cv_mutex" = "ui_only" -o "$db_cv_mutex" = "ui_library_only"; then
-LIBS="$LIBS -lthread"
+if test "$db_cv_mutex" = no -o "$db_cv_mutex" = "ui_only"; then
 AC_TRY_LINK([
 #include <thread.h>
 #include <synch.h>],[
@@ -182,42 +196,12 @@ AC_TRY_LINK([
 	cond_init(&cond, type, NULL) ||
 	mutex_lock(&mutex) ||
 	mutex_unlock(&mutex));
-], [db_cv_mutex="UI/threads/library"])
-LIBS="$orig_libs"
+], [db_cv_mutex="UI/threads"])
 fi
-if test "$db_cv_mutex" = "ui_only" -o "$db_cv_mutex" = "ui_library_only"; then
+if test "$db_cv_mutex" = "ui_only"; then
 	AC_MSG_ERROR([unable to find UI mutex interfaces])
 fi
 
-# POSIX.1 pthreads: pthread_XXX
-#
-# Try with and without the -lpthread library.  If the user specified we use
-# POSIX pthreads mutexes, and we fail to find the full interface, try and
-# configure for just intra-process support.
-if test "$db_cv_mutex" = no -o "$db_cv_mutex" = "posix_only"; then
-	AM_PTHREADS_SHARED("POSIX/pthreads")
-fi
-if test "$db_cv_mutex" = no -o \
-    "$db_cv_mutex" = "posix_only" -o "$db_cv_mutex" = "posix_library_only"; then
-	LIBS="$LIBS -lpthread"
-	AM_PTHREADS_SHARED("POSIX/pthreads/library")
-	LIBS="$orig_libs"
-fi
-if test "$db_cv_mutex" = "posix_only"; then
-	AM_PTHREADS_PRIVATE("POSIX/pthreads/private")
-fi
-if test "$db_cv_mutex" = "posix_only" -o \
-    "$db_cv_mutex" = "posix_library_only"; then
-	LIBS="$LIBS -lpthread"
-	AM_PTHREADS_PRIVATE("POSIX/pthreads/library/private")
-	LIBS="$orig_libs"
-fi
-
-if test "$db_cv_mutex" = "posix_only" -o \
-    "$db_cv_mutex" = "posix_library_only"; then
-	AC_MSG_ERROR([unable to find POSIX 1003.1 mutex interfaces])
-fi
-
 # msemaphore: HPPA only
 # Try HPPA before general msem test, it needs special alignment.
 if test "$db_cv_mutex" = no; then
@@ -327,7 +311,27 @@ AC_TRY_LINK([
 ], [db_cv_mutex="AIX/_check_lock"])
 fi
 
-# Alpha/gcc: OSF/1
+# _spin_lock_try/_spin_unlock: Apple/Darwin
+if test "$db_cv_mutex" = no; then
+AC_TRY_LINK(,[
+	int x;
+	_spin_lock_try(&x);
+	_spin_unlock(&x);
+], [db_cv_mutex="Darwin/_spin_lock_try"])
+fi
+
+# Tru64/cc
+if test "$db_cv_mutex" = no; then
+AC_TRY_COMPILE(,[
+#if defined(__alpha) && defined(__DECC)
+	exit(0);
+#else
+	FAIL TO COMPILE/LINK
+#endif
+], [db_cv_mutex="Tru64/cc-assembly"])
+fi
+
+# Alpha/gcc
 if test "$db_cv_mutex" = no; then
 AC_TRY_COMPILE(,[
 #if defined(__alpha) && defined(__GNUC__)
@@ -361,16 +365,6 @@ AC_TRY_COMPILE(,[
 fi
 
 # PPC/gcc:
-# Test for Apple first, it requires slightly different assembly.
-if test "$db_cv_mutex" = no; then
-AC_TRY_COMPILE(,[
-#if (defined(__powerpc__) || defined(__ppc__)) && defined(__GNUC__) && defined(__APPLE__)
-	exit(0);
-#else
-	FAIL TO COMPILE/LINK
-#endif
-], [db_cv_mutex="PPC_APPLE/gcc-assembly"])
-fi
 if test "$db_cv_mutex" = no; then
 AC_TRY_COMPILE(,[
 #if (defined(__powerpc__) || defined(__ppc__)) && defined(__GNUC__)
@@ -378,7 +372,7 @@ AC_TRY_COMPILE(,[
 #else
 	FAIL TO COMPILE/LINK
 #endif
-], [db_cv_mutex="PPC_GENERIC/gcc-assembly"])
+], [db_cv_mutex="PPC/gcc-assembly"])
 fi
 
 # Sparc/gcc: SunOS, Solaris
@@ -406,7 +400,7 @@ fi
 # x86/gcc: FreeBSD, NetBSD, BSD/OS, Linux
 if test "$db_cv_mutex" = no; then
 AC_TRY_COMPILE(,[
-#if (defined(i386) || defined(__i386__)) && defined(__GNUC__)
+#if (defined(i386) || defined(__i386__) || defined(__x86_64__)) && defined(__GNUC__)
 	exit(0);
 #else
 	FAIL TO COMPILE/LINK
@@ -414,6 +408,17 @@ AC_TRY_COMPILE(,[
 ], [db_cv_mutex="x86/gcc-assembly"])
 fi
 
+# S390/cc: IBM OS/390 Unix
+if test "$db_cv_mutex" = no; then
+AC_TRY_COMPILE(,[
+#if defined(__MVS__) && defined(__IBMC__)
+	exit(0);
+#else
+	FAIL TO COMPILE/LINK
+#endif
+], [db_cv_mutex="S390/cc-assembly"])
+fi
+
 # S390/gcc: Linux
 if test "$db_cv_mutex" = no; then
 AC_TRY_COMPILE(,[
@@ -462,6 +467,10 @@ AIX/_check_lock)	ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
 			AC_DEFINE(HAVE_MUTEX_AIX_CHECK_LOCK)
 			AH_TEMPLATE(HAVE_MUTEX_AIX_CHECK_LOCK,
 			    [Define to 1 to use the AIX _check_lock mutexes.]);;
+Darwin/_spin_lock_try)	ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
+			AC_DEFINE(HAVE_MUTEX_DARWIN_SPIN_LOCK_TRY)
+			AH_TEMPLATE(HAVE_MUTEX_DARWIN_SPIN_LOCK_TRY,
+			    [Define to 1 to use the Apple/Darwin _spin_lock_try mutexes.]);;
 ALPHA/gcc-assembly)	ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
 			AC_DEFINE(HAVE_MUTEX_ALPHA_GCC_ASSEMBLY)
 			AH_TEMPLATE(HAVE_MUTEX_ALPHA_GCC_ASSEMBLY,
@@ -494,12 +503,16 @@ POSIX/pthreads/private)	ADDITIONAL_OBJS="mut_pthread${o} $ADDITIONAL_OBJS"
 			AH_TEMPLATE(HAVE_MUTEX_THREAD_ONLY,
 			    [Define to 1 to configure mutexes intra-process only.]);;
 POSIX/pthreads/library)	LIBS="$LIBS -lpthread"
+			LIBJSO_LIBS="$LIBJSO_LIBS -lpthread"
+			LIBTSO_LIBS="$LIBTSO_LIBS -lpthread"
 			ADDITIONAL_OBJS="mut_pthread${o} $ADDITIONAL_OBJS"
 			AC_DEFINE(HAVE_MUTEX_PTHREADS)
 			AH_TEMPLATE(HAVE_MUTEX_PTHREADS,
 			    [Define to 1 to use POSIX 1003.1 pthread_XXX mutexes.]);;
 POSIX/pthreads/library/private)
 			LIBS="$LIBS -lpthread"
+			LIBJSO_LIBS="$LIBJSO_LIBS -lpthread"
+			LIBTSO_LIBS="$LIBTSO_LIBS -lpthread"
 			ADDITIONAL_OBJS="mut_pthread${o} $ADDITIONAL_OBJS"
 			AC_DEFINE(HAVE_MUTEX_PTHREADS)
 			AH_TEMPLATE(HAVE_MUTEX_PTHREADS,
@@ -507,20 +520,20 @@ POSIX/pthreads/library/private)
 			AC_DEFINE(HAVE_MUTEX_THREAD_ONLY)
 			AH_TEMPLATE(HAVE_MUTEX_THREAD_ONLY,
 			    [Define to 1 to configure mutexes intra-process only.]);;
-PPC_GENERIC/gcc-assembly)
+PPC/gcc-assembly)
 			ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
-			AC_DEFINE(HAVE_MUTEX_PPC_GENERIC_GCC_ASSEMBLY)
-			AH_TEMPLATE(HAVE_MUTEX_PPC_GENERIC_GCC_ASSEMBLY,
-			    [Define to 1 to use the GCC compiler and generic PowerPC assembly language.]);;
-PPC_APPLE/gcc-assembly)	ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
-			AC_DEFINE(HAVE_MUTEX_PPC_APPLE_GCC_ASSEMBLY)
-			AH_TEMPLATE(HAVE_MUTEX_PPC_APPLE_GCC_ASSEMBLY,
-			    [Define to 1 to use the GCC compiler and Apple PowerPC assembly language.]);;
+			AC_DEFINE(HAVE_MUTEX_PPC_GCC_ASSEMBLY)
+			AH_TEMPLATE(HAVE_MUTEX_PPC_GCC_ASSEMBLY,
+			    [Define to 1 to use the GCC compiler and PowerPC assembly language mutexes.]);;
 ReliantUNIX/initspin)	LIBS="$LIBS -lmproc"
 			ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
 			AC_DEFINE(HAVE_MUTEX_RELIANTUNIX_INITSPIN)
 			AH_TEMPLATE(HAVE_MUTEX_RELIANTUNIX_INITSPIN,
 			    [Define to 1 to use Reliant UNIX initspin mutexes.]);;
+S390/cc-assembly)	ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
+			AC_DEFINE(HAVE_MUTEX_S390_CC_ASSEMBLY)
+			AH_TEMPLATE(HAVE_MUTEX_S390_CC_ASSEMBLY,
+			    [Define to 1 to use the IBM C compiler and S/390 assembly language mutexes.]);;
 S390/gcc-assembly)	ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
 			AC_DEFINE(HAVE_MUTEX_S390_GCC_ASSEMBLY)
 			AH_TEMPLATE(HAVE_MUTEX_S390_GCC_ASSEMBLY,
@@ -545,6 +558,11 @@ Sparc/gcc-assembly)	ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
 			AC_DEFINE(HAVE_MUTEX_SPARC_GCC_ASSEMBLY)
 			AH_TEMPLATE(HAVE_MUTEX_SPARC_GCC_ASSEMBLY,
 			    [Define to 1 to use the GCC compiler and Sparc assembly language mutexes.]);;
+Tru64/cc-assembly)	ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
+			AC_DEFINE(HAVE_MUTEX_TRU64_CC_ASSEMBLY)
+			AH_TEMPLATE(HAVE_MUTEX_TRU64_CC_ASSEMBLY,
+			    [Define to 1 to use the CC compiler and Tru64 assembly language mutexes.]);;
+
 UI/threads)		ADDITIONAL_OBJS="mut_pthread${o} $ADDITIONAL_OBJS"
 			AC_DEFINE(HAVE_MUTEX_UI_THREADS)
 			AH_TEMPLATE(HAVE_MUTEX_UI_THREADS,
@@ -562,10 +580,16 @@ UNIX/sema_init)		ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
 			AC_DEFINE(HAVE_MUTEX_SEMA_INIT)
 			AH_TEMPLATE(HAVE_MUTEX_SEMA_INIT,
 			    [Define to 1 to use the obsolete POSIX 1003.1 sema_XXX mutexes.]);;
-UTS/cc-assembly)	ADDITIONAL_OBJS="$ADDITIONAL_OBJS uts4.cc${o}"
+UTS/cc-assembly)	ADDITIONAL_OBJS="uts4.cc${o} $ADDITIONAL_OBJS"
 			AC_DEFINE(HAVE_MUTEX_UTS_CC_ASSEMBLY)
 			AH_TEMPLATE(HAVE_MUTEX_UTS_CC_ASSEMBLY,
 			    [Define to 1 to use the UTS compiler and assembly language mutexes.]);;
+win32)			ADDITIONAL_OBJS="mut_win32${o} $ADDITIONAL_OBJS"
+			AC_DEFINE(HAVE_MUTEX_WIN32)
+			AH_TEMPLATE(HAVE_MUTEX_WIN32, [Define to 1 to use the MSVC compiler and Windows mutexes.]);;
+win32/gcc)		ADDITIONAL_OBJS="mut_win32${o} $ADDITIONAL_OBJS"
+			AC_DEFINE(HAVE_MUTEX_WIN32_GCC)
+			AH_TEMPLATE(HAVE_MUTEX_WIN32_GCC, [Define to 1 to use the GCC compiler and Windows mutexes.]);;
 x86/gcc-assembly)	ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS"
 			AC_DEFINE(HAVE_MUTEX_X86_GCC_ASSEMBLY)
 			AH_TEMPLATE(HAVE_MUTEX_X86_GCC_ASSEMBLY,
diff --git a/storage/bdb/dist/aclocal/options.ac b/storage/bdb/dist/aclocal/options.ac
index ba45c34dfe9e22005d0b75ae0d6a4030e42326a8..b770fc44478e9d4521033715d70d87aee18fe791 100644
--- a/storage/bdb/dist/aclocal/options.ac
+++ b/storage/bdb/dist/aclocal/options.ac
@@ -1,4 +1,4 @@
-# $Id: options.ac,v 11.19 2002/06/25 19:31:48 bostic Exp $
+# $Id: options.ac,v 11.37 2004/06/10 16:38:18 bostic Exp $
 
 # Process user-specified options.
 AC_DEFUN(AM_OPTIONS_SET, [
@@ -11,6 +11,66 @@ AC_ARG_ENABLE(bigfile,
 	[AC_MSG_ERROR(
 	    [--enable-bigfile no longer supported, use --enable-largefile])])
 
+AC_MSG_CHECKING(if --disable-cryptography option specified)
+AC_ARG_ENABLE(cryptography,
+	AC_HELP_STRING([--disable-cryptography],
+	    [Do not build database cryptography support.]),, enableval="yes")
+db_cv_build_cryptography="$enableval"
+case "$enableval" in
+ no) AC_MSG_RESULT(yes);;
+yes) AC_MSG_RESULT(no);;
+esac
+
+AC_MSG_CHECKING(if --disable-hash option specified)
+AC_ARG_ENABLE(hash,
+	AC_HELP_STRING([--disable-hash],
+	    [Do not build Hash access method.]),, enableval="yes")
+db_cv_build_hash="$enableval"
+case "$enableval" in
+ no) AC_MSG_RESULT(yes);;
+yes) AC_MSG_RESULT(no);;
+esac
+
+AC_MSG_CHECKING(if --disable-queue option specified)
+AC_ARG_ENABLE(queue,
+	AC_HELP_STRING([--disable-queue],
+	    [Do not build Queue access method.]),, enableval="yes")
+db_cv_build_queue="$enableval"
+case "$enableval" in
+ no) AC_MSG_RESULT(yes);;
+yes) AC_MSG_RESULT(no);;
+esac
+
+AC_MSG_CHECKING(if --disable-replication option specified)
+AC_ARG_ENABLE(replication,
+	AC_HELP_STRING([--disable-replication],
+	    [Do not build database replication support.]),, enableval="yes")
+db_cv_build_replication="$enableval"
+case "$enableval" in
+ no) AC_MSG_RESULT(yes);;
+yes) AC_MSG_RESULT(no);;
+esac
+
+AC_MSG_CHECKING(if --disable-statistics option specified)
+AC_ARG_ENABLE(statistics,
+	AC_HELP_STRING([--disable-statistics],
+	    [Do not build statistics support.]),, enableval="yes")
+db_cv_build_statistics="$enableval"
+case "$enableval" in
+ no) AC_MSG_RESULT(yes);;
+yes) AC_MSG_RESULT(no);;
+esac
+
+AC_MSG_CHECKING(if --disable-verify option specified)
+AC_ARG_ENABLE(verify,
+	AC_HELP_STRING([--disable-verify],
+	    [Do not build database verification support.]),, enableval="yes")
+db_cv_build_verify="$enableval"
+case "$enableval" in
+ no) AC_MSG_RESULT(yes);;
+yes) AC_MSG_RESULT(no);;
+esac
+
 AC_MSG_CHECKING(if --enable-compat185 option specified)
 AC_ARG_ENABLE(compat185,
 	[AC_HELP_STRING([--enable-compat185],
@@ -51,7 +111,20 @@ AC_ARG_ENABLE(diagnostic,
 	[AC_HELP_STRING([--enable-diagnostic],
 			[Build a version with run-time diagnostics.])],
 	[db_cv_diagnostic="$enable_diagnostic"], [db_cv_diagnostic="no"])
-AC_MSG_RESULT($db_cv_diagnostic)
+if test "$db_cv_diagnostic" = "yes"; then
+	AC_MSG_RESULT($db_cv_diagnostic)
+fi
+if test "$db_cv_diagnostic" = "no" -a "$db_cv_debug_rop" = "yes"; then
+	db_cv_diagnostic="yes"
+	AC_MSG_RESULT([by --enable-debug_rop])
+fi
+if test "$db_cv_diagnostic" = "no" -a "$db_cv_debug_wop" = "yes"; then
+	db_cv_diagnostic="yes"
+	AC_MSG_RESULT([by --enable-debug_wop])
+fi
+if test "$db_cv_diagnostic" = "no"; then
+	AC_MSG_RESULT($db_cv_diagnostic)
+fi
 
 AC_MSG_CHECKING(if --enable-dump185 option specified)
 AC_ARG_ENABLE(dump185,
@@ -67,6 +140,20 @@ AC_ARG_ENABLE(java,
 	[db_cv_java="$enable_java"], [db_cv_java="no"])
 AC_MSG_RESULT($db_cv_java)
 
+AC_MSG_CHECKING(if --enable-mingw option specified)
+AC_ARG_ENABLE(mingw,
+	[AC_HELP_STRING([--enable-mingw],
+			[Build Berkeley DB for MinGW.])],
+	[db_cv_mingw="$enable_mingw"], [db_cv_mingw="no"])
+AC_MSG_RESULT($db_cv_mingw)
+
+AC_MSG_CHECKING(if --enable-o_direct option specified)
+AC_ARG_ENABLE(o_direct,
+	[AC_HELP_STRING([--enable-o_direct],
+			[Enable the O_DIRECT flag for direct I/O.])],
+	[db_cv_o_direct="$enable_o_direct"], [db_cv_o_direct="no"])
+AC_MSG_RESULT($db_cv_o_direct)
+
 AC_MSG_CHECKING(if --enable-posixmutexes option specified)
 AC_ARG_ENABLE(posixmutexes,
 	[AC_HELP_STRING([--enable-posixmutexes],
@@ -81,6 +168,21 @@ AC_ARG_ENABLE(rpc,
 	[db_cv_rpc="$enable_rpc"], [db_cv_rpc="no"])
 AC_MSG_RESULT($db_cv_rpc)
 
+AC_MSG_CHECKING(if --enable-smallbuild option specified)
+AC_ARG_ENABLE(smallbuild,
+	[AC_HELP_STRING([--enable-smallbuild],
+			[Build small footprint version of the library.])],
+	[db_cv_smallbuild="$enable_smallbuild"], [db_cv_smallbuild="no"])
+if test "$db_cv_smallbuild" = "yes"; then
+	db_cv_build_cryptography="no"
+	db_cv_build_hash="no"
+	db_cv_build_queue="no"
+	db_cv_build_replication="no"
+	db_cv_build_statistics="no"
+	db_cv_build_verify="no"
+fi
+AC_MSG_RESULT($db_cv_smallbuild)
+
 AC_MSG_CHECKING(if --enable-tcl option specified)
 AC_ARG_ENABLE(tcl,
 	[AC_HELP_STRING([--enable-tcl],
@@ -105,28 +207,10 @@ AC_MSG_RESULT($db_cv_uimutexes)
 AC_MSG_CHECKING(if --enable-umrw option specified)
 AC_ARG_ENABLE(umrw,
 	[AC_HELP_STRING([--enable-umrw],
-			[Mask harmless unitialized memory read/writes.])],
+			[Mask harmless uninitialized memory read/writes.])],
 	[db_cv_umrw="$enable_umrw"], [db_cv_umrw="no"])
 AC_MSG_RESULT($db_cv_umrw)
 
-AC_MSG_CHECKING([if --with-embedix=DIR option specified])
-AC_ARG_WITH(embedix,
-	[AC_HELP_STRING([--with-embedix=DIR],
-			[Embedix install directory location.])],
-	[with_embedix="$withval"], [with_embedix="no"])
-if test "$with_embedix" = "no"; then
-	db_cv_embedix="no"
-	AC_MSG_RESULT($with_embedix)
-else
-	db_cv_embedix="yes"
-	if test "$with_embedix" = "yes"; then
-		db_cv_path_embedix_install="/opt/Embedix"
-	else
-		db_cv_path_embedix_install="$with_embedix"
-	fi
-	AC_MSG_RESULT($db_cv_path_embedix_install)
-fi
-
 AC_MSG_CHECKING(if --with-mutex=MUTEX option specified)
 AC_ARG_WITH(mutex,
 	[AC_HELP_STRING([--with-mutex=MUTEX],
@@ -140,21 +224,20 @@ if test "$with_mutex" != "no"; then
 fi
 AC_MSG_RESULT($with_mutex)
 
-AC_MSG_CHECKING(if --with-rpm=DIR option specified)
-AC_ARG_WITH(rpm,
-	[AC_HELP_STRING([--with-rpm=DIR],
-			[Directory location of RPM archive.])],
-	[with_rpm="$withval"], [with_rpm="no"])
-if test "$with_rpm" = "no"; then
-	db_cv_rpm="no"
-else
-	if test "$with_rpm" = "yes"; then
-		AC_MSG_ERROR([--with-rpm requires a directory argument])
-	fi
-	db_cv_rpm="yes"
-	db_cv_path_rpm_archive="$with_rpm"
+AH_TEMPLATE(MUTEX_ALIGN,
+    [Define to a value if using non-standard mutex alignment.])
+AC_MSG_CHECKING(if --with-mutexalign=ALIGNMENT option specified)
+AC_ARG_WITH(mutexalign,
+	[AC_HELP_STRING([--with-mutexalign=ALIGNMENT],
+			[Selection of non-standard mutex alignment.])],
+	[with_mutexalign="$withval"], [with_mutexalign="no"])
+if test "$with_mutexalign" = "yes"; then
+	AC_MSG_ERROR([--with-mutexalign requires a mutex alignment argument])
+fi
+if test "$with_mutexalign" != "no"; then
+	AC_DEFINE_UNQUOTED(MUTEX_ALIGN, $with_mutexalign)
 fi
-AC_MSG_RESULT($with_rpm)
+AC_MSG_RESULT($with_mutexalign)
 
 AC_MSG_CHECKING([if --with-tcl=DIR option specified])
 AC_ARG_WITH(tcl,
@@ -173,25 +256,37 @@ AC_ARG_WITH(uniquename,
 	[with_uniquename="$withval"], [with_uniquename="no"])
 if test "$with_uniquename" = "no"; then
 	db_cv_uniquename="no"
+	DB_VERSION_UNIQUE_NAME=""
 	AC_MSG_RESULT($with_uniquename)
 else
 	db_cv_uniquename="yes"
-	if test "$with_uniquename" != "yes"; then
+	if test "$with_uniquename" = "yes"; then
+		DB_VERSION_UNIQUE_NAME="__EDIT_DB_VERSION_UNIQUE_NAME__"
+	else
 		DB_VERSION_UNIQUE_NAME="$with_uniquename"
 	fi
 	AC_MSG_RESULT($DB_VERSION_UNIQUE_NAME)
 fi
 
-# Embedix requires RPM.
-if test "$db_cv_embedix" = "yes"; then
-	if test "$db_cv_rpm" = "no"; then
-		AC_MSG_ERROR([--with-embedix requires --with-rpm])
-	fi
-fi
-
 # Test requires Tcl
 if test "$db_cv_test" = "yes"; then
 	if test "$db_cv_tcl" = "no"; then
 		AC_MSG_ERROR([--enable-test requires --enable-tcl])
 	fi
+fi
+
+# Uniquename excludes C++, Java, RPC.
+if test "$db_cv_uniquename" = "yes"; then
+	if test "$db_cv_rpc" = "yes"; then
+		AC_MSG_ERROR(
+		    [--with-uniquename is not compatible with --enable-rpc])
+	fi
+	if test "$db_cv_cxx" = "yes"; then
+		AC_MSG_ERROR(
+		    [--with-uniquename is not compatible with --enable-cxx])
+	fi
+	if test "$db_cv_java" = "yes"; then
+		AC_MSG_ERROR(
+		    [--with-uniquename is not compatible with --enable-java])
+	fi
 fi])
diff --git a/storage/bdb/dist/aclocal/programs.ac b/storage/bdb/dist/aclocal/programs.ac
index 7bfa1fa26468198879a9b55c4da440e061af1357..db6b4f03e84317f9d6bb1ae3c0e4758f203baafd 100644
--- a/storage/bdb/dist/aclocal/programs.ac
+++ b/storage/bdb/dist/aclocal/programs.ac
@@ -1,4 +1,4 @@
-# $Id: programs.ac,v 11.20 2001/09/24 02:09:25 bostic Exp $
+# $Id: programs.ac,v 11.22 2004/06/10 16:38:18 bostic Exp $
 
 # Check for programs used in building/installation.
 AC_DEFUN(AM_PROGRAMS_SET, [
@@ -18,15 +18,6 @@ if test "$db_cv_path_cp" = missing_cp; then
 	AC_MSG_ERROR([No cp utility found.])
 fi
 
-if test "$db_cv_rpm" = "yes"; then
-	AC_CHECK_TOOL(path_ldconfig, ldconfig, missing_ldconfig)
-	AC_PATH_PROG(db_cv_path_ldconfig, $path_ldconfig, missing_ldconfig)
-	if test "$db_cv_path_ldconfig" != missing_ldconfig; then
-		RPM_POST_INSTALL="%post -p $db_cv_path_ldconfig"
-		RPM_POST_UNINSTALL="%postun -p $db_cv_path_ldconfig"
-	fi
-fi
-
 AC_CHECK_TOOL(db_cv_path_ln, ln, missing_ln)
 if test "$db_cv_path_ln" = missing_ln; then
 	AC_MSG_ERROR([No ln utility found.])
@@ -47,10 +38,10 @@ if test "$db_cv_path_rm" = missing_rm; then
 	AC_MSG_ERROR([No rm utility found.])
 fi
 
-if test "$db_cv_rpm" = "yes"; then
-	AC_CHECK_TOOL(db_cv_path_rpm, rpm, missing_rpm)
-	if test "$db_cv_path_rpm" = missing_rpm; then
-		AC_MSG_ERROR([No rpm utility found.])
+if test "$db_cv_rpc" = "yes"; then
+	AC_CHECK_TOOL(db_cv_path_rpcgen, rpcgen, missing_rpcgen)
+	if test "$db_cv_path_rpcgen" = missing_rpcgen; then
+		AC_MSG_ERROR([No rpcgen utility found.])
 	fi
 fi
 
diff --git a/storage/bdb/dist/aclocal/rpc.ac b/storage/bdb/dist/aclocal/rpc.ac
new file mode 100644
index 0000000000000000000000000000000000000000..7d7f4dabe806af864782cc66b09757f00dcef8e8
--- /dev/null
+++ b/storage/bdb/dist/aclocal/rpc.ac
@@ -0,0 +1,83 @@
+# $Id: rpc.ac,v 11.9 2004/09/27 21:33:48 mjc Exp $
+
+# Try and configure RPC support.
+AC_DEFUN(AM_RPC_CONFIGURE, [
+	AC_DEFINE(HAVE_RPC)
+	AH_TEMPLATE(HAVE_RPC, [Define to 1 if building RPC client/server.])
+
+	# We use the target's rpcgen utility because it may be architecture
+	# specific, for example, 32- or 64-bit specific.
+	XDR_FILE=$srcdir/../rpc_server/db_server.x
+
+	# Prefer the -C option to rpcgen which generates ANSI C-conformant
+	# code.
+	RPCGEN="rpcgen -C"
+	AC_MSG_CHECKING(["$RPCGEN" build of db_server.h])
+	$RPCGEN -h $XDR_FILE > db_server.h 2>/dev/null
+	if test $? -ne 0; then
+		AC_MSG_RESULT([no])
+
+		# Try rpcgen without the -C option.
+		RPCGEN="rpcgen"
+		AC_MSG_CHECKING(["$RPCGEN" build of db_server.h])
+		$RPCGEN -h $XDR_FILE > db_server.h 2>/dev/null
+		if test $? -ne 0; then
+			AC_MSG_RESULT([no])
+			AC_MSG_ERROR(
+			    [Unable to build RPC support: $RPCGEN failed.])
+		fi
+	fi
+
+	# Some rpcgen programs generate a set of client stubs called something
+	# like __db_env_create_4003 and functions on the server to handle the
+	# request called something like __db_env_create_4003_svc.  Others
+	# expect client and server stubs to both be called __db_env_create_4003.
+	#
+	# We have to generate code in whichever format rpcgen expects, and the
+	# only reliable way to do that is to check what is in the db_server.h
+	# file we just created.
+	if grep "env_create_[[0-9]]*_svc" db_server.h >/dev/null 2>&1 ; then
+		sed 's/__SVCSUFFIX__/_svc/' \
+		    < $srcdir/../rpc_server/c/gen_db_server.c > gen_db_server.c
+	else
+		sed 's/__SVCSUFFIX__//' \
+		    < $srcdir/../rpc_server/c/gen_db_server.c > gen_db_server.c
+	fi
+
+	AC_MSG_RESULT([yes])
+
+	$RPCGEN -l $XDR_FILE |
+	sed -e 's/^#include.*db_server.h.*/#include "db_server.h"/' \
+	    -e '1,/^#include/s/^#include/#include "db_config.h"\
+&/' > db_server_clnt.c
+
+	$RPCGEN -s tcp $XDR_FILE |
+	sed -e 's/^#include.*db_server.h.*/#include "db_server.h"/' \
+	    -e 's/^main *()/__dbsrv_main()/' \
+	    -e 's/^main *(.*argc.*argv.*)/__dbsrv_main(int argc, char *argv[])/' \
+	    -e '/^db_rpc_serverprog/,/^}/{' \
+	    -e 's/return;//' \
+	    -e 's/^}/__dbsrv_timeout(0);}/' \
+	    -e '}' \
+	    -e '1,/^#include/s/^#include/#include "db_config.h"\
+&/' > db_server_svc.c
+
+	$RPCGEN -c $XDR_FILE |
+	sed -e 's/^#include.*db_server.h.*/#include "db_server.h"/' \
+	    -e '1,/^#include/s/^#include/#include "db_config.h"\
+&/' > db_server_xdr.c
+
+	RPC_SERVER_H=db_server.h
+	RPC_CLIENT_OBJS="\$(RPC_CLIENT_OBJS)"
+	ADDITIONAL_PROGS="berkeley_db_svc $ADDITIONAL_PROGS"
+
+	case "$host_os" in
+	hpux*)
+		AC_CHECK_FUNC(svc_run,,
+		    AC_CHECK_LIB(nsl, svc_run,
+		    LIBS="-lnsl $LIBS"; LIBTSO_LIBS="-lnsl $LIBTSO_LIBS";
+		    LIBJSO_LIBS="-lnsl $LIBJSO_LIBS"));;
+	solaris*)
+		AC_CHECK_FUNC(svc_run,, AC_CHECK_LIB(nsl, svc_run));;
+	esac
+])
diff --git a/storage/bdb/dist/aclocal/sequence.ac b/storage/bdb/dist/aclocal/sequence.ac
new file mode 100644
index 0000000000000000000000000000000000000000..ca320b2320530aff37c42e885a0fdc2dc8dc7aa3
--- /dev/null
+++ b/storage/bdb/dist/aclocal/sequence.ac
@@ -0,0 +1,76 @@
+# $Id: sequence.ac,v 1.3 2004/10/28 18:14:30 bostic Exp $
+
+# Try and configure sequence support.
+AC_DEFUN(AM_SEQUENCE_CONFIGURE, [
+	AC_MSG_CHECKING([for 64-bit integral type support for sequences])
+	db_cv_build_sequence="yes"
+
+	# Have to have found 64-bit types to support sequences.  If we don't
+	# find the native types, we try and create our own.
+	if test "$ac_cv_type_int64_t" = "no" -a -z "$int64_decl"; then
+		db_cv_build_sequence="no"
+	fi
+	if test "$ac_cv_type_uint64_t" = "no" -a -z "$u_int64_decl"; then
+		db_cv_build_sequence="no"
+	fi
+
+	# Have to be able to cast variables to the "unsigned long long" and
+	# "long long" types, that's our cast for the printf "%ll[du]" format.
+	if test "$ac_cv_type_long_long" = "no"; then
+		db_cv_build_sequence="no"
+	fi
+	if test "$ac_cv_type_unsigned_long_long" = "no"; then
+		db_cv_build_sequence="no"
+	fi
+
+	# Test to see if we can declare variables of the appropriate size
+	# and format them.  If we're cross-compiling, all we get is a link
+	# test, which won't test for the appropriate printf format strings.
+	if test "$db_cv_build_sequence" = "yes"; then
+		AC_TRY_RUN([
+		main() {
+			long long l;
+			unsigned long long u;
+			char buf[100];
+
+			buf[0] = 'a';
+			l = 9223372036854775807LL;
+			(void)snprintf(buf, sizeof(buf), "%lld", l);
+			if (strcmp(buf, "9223372036854775807"))
+				return (1);
+			u = 18446744073709551615ULL;
+			(void)snprintf(buf, sizeof(buf), "%llu", u);
+			if (strcmp(buf, "18446744073709551615"))
+				return (1);
+			return (0);
+		}],, [db_cv_build_sequence="no"],
+		AC_TRY_LINK(,[
+			long long l;
+			unsigned long long u;
+			char buf[100];
+
+			buf[0] = 'a';
+			l = 9223372036854775807LL;
+			(void)snprintf(buf, sizeof(buf), "%lld", l);
+			if (strcmp(buf, "9223372036854775807"))
+				return (1);
+			u = 18446744073709551615ULL;
+			(void)snprintf(buf, sizeof(buf), "%llu", u);
+			if (strcmp(buf, "18446744073709551615"))
+				return (1);
+			return (0);
+		],, [db_cv_build_sequence="no"]))
+	fi
+	if test "$db_cv_build_sequence" = "yes"; then
+		AC_DEFINE(HAVE_SEQUENCE)
+		AH_TEMPLATE(HAVE_SEQUENCE,
+		    [Define to 1 if building sequence support.])
+
+		AC_SUBST(db_seq_decl)
+		db_seq_decl="typedef int64_t db_seq_t;";
+	else
+		# It still has to compile, but it won't run.
+		db_seq_decl="typedef int db_seq_t;";
+	fi
+	AC_MSG_RESULT($db_cv_build_sequence)
+])
diff --git a/storage/bdb/dist/aclocal/sosuffix.ac b/storage/bdb/dist/aclocal/sosuffix.ac
index 1197128293b7acd6713b886a854071e71dc4306c..8864280f1ae502344fddbe3b0fc4ff63727de45b 100644
--- a/storage/bdb/dist/aclocal/sosuffix.ac
+++ b/storage/bdb/dist/aclocal/sosuffix.ac
@@ -1,29 +1,32 @@
-# $Id: sosuffix.ac,v 1.1 2002/07/08 13:15:05 dda Exp $
+# $Id: sosuffix.ac,v 1.4 2004/08/14 20:00:45 dda Exp $
 # Determine shared object suffixes.
 #
 # Our method is to use the libtool variable $library_names_spec,
 # set by using AC_PROG_LIBTOOL.  This variable is a snippet of shell
-# defined in terms of $versuffix, $release, $libname, $module and $jnimodule.
+# defined in terms of $versuffix, $release, $libname and $module
 # We want to eval it and grab the suffix used for shared objects.
-# By setting $module and $jnimodule to yes/no, we obtain the suffixes
+# By setting $module to yes/no, we obtain the suffixes
 # used to create dlloadable, or java loadable modules.
 # On many (*nix) systems, these all evaluate to .so, but there
 # are some notable exceptions.
+# Before calling this macro, $LIBTOOL_PROG must be set to
+# the correct method of invoking libtool (e.g. $SHELL ./libtool)
 
 # This macro is used internally to discover the suffix for the current
-# settings of $module and $jnimodule.  The result is stored in $_SOSUFFIX.
+# settings of $module.  The result is stored in $_SOSUFFIX.
 AC_DEFUN(_SOSUFFIX_INTERNAL, [
 	versuffix=""
 	release=""
 	libname=libfoo
-	eval library_names=\"$library_names_spec\"
-	_SOSUFFIX=`echo "$library_names" | sed -e 's/.*\.\([[a-zA-Z0-9_]]*\).*/\1/'`
-	if test "$_SOSUFFIX" = '' ; then
-		_SOSUFFIX=so
-		if test "$enable_shared" = "yes" && test "$_SOSUFFIX_MESSAGE" = ""; then
-			_SOSUFFIX_MESSAGE=yes
-        		AC_MSG_WARN([libtool may not know about this architecture.])
-               		AC_MSG_WARN([assuming .$_SUFFIX suffix for dynamic libraries.])
+	eval _SOSUFFIX=\"$shrext_cmds\"
+	if test "$_SOSUFFIX" = "" ; then
+		_SOSUFFIX=".so"
+		if test `$LIBTOOL_PROG --config | grep build_libtool_libs | grep no` 2>/dev/null; then
+			if test "$_SOSUFFIX_MESSAGE" = ""; then
+				_SOSUFFIX_MESSAGE=yes
+        			AC_MSG_WARN([libtool may not know about this architecture.])
+               			AC_MSG_WARN([assuming $_SUFFIX suffix for dynamic libraries.])
+			fi
         	fi
         fi
 ])
@@ -33,7 +36,6 @@ AC_DEFUN(_SOSUFFIX_INTERNAL, [
 AC_DEFUN(SOSUFFIX_CONFIG, [
 	AC_MSG_CHECKING([SOSUFFIX from libtool])
 	module=no
-	jnimodule=no
         _SOSUFFIX_INTERNAL
         SOSUFFIX=$_SOSUFFIX
 	AC_MSG_RESULT($SOSUFFIX)
@@ -46,7 +48,6 @@ AC_DEFUN(SOSUFFIX_CONFIG, [
 AC_DEFUN(MODSUFFIX_CONFIG, [
 	AC_MSG_CHECKING([MODSUFFIX from libtool])
 	module=yes
-	jnimodule=no
         _SOSUFFIX_INTERNAL
         MODSUFFIX=$_SOSUFFIX
 	AC_MSG_RESULT($MODSUFFIX)
@@ -55,14 +56,20 @@ AC_DEFUN(MODSUFFIX_CONFIG, [
 
 # JMODSUFFIX_CONFIG will set the variable JMODSUFFIX to be the
 # shared library extension used JNI modules opened by Java.
-# To discover this, we set $jnimodule, simulating libtool's -jnimodule option.
-# -jnimodule is currently a Sleepycat local extension to libtool.
+# To discover this, we set $jnimodule, simulating libtool's -shrext option.
+##########################################################################
+# Robert Boehne:  Not much point in this macro any more because apparently
+# Darwin is the only OS that wants or needs the .jnilib extension.
+##########################################################################
 AC_DEFUN(JMODSUFFIX_CONFIG, [
 	AC_MSG_CHECKING([JMODSUFFIX from libtool])
 	module=yes
-	jnimodule=yes
         _SOSUFFIX_INTERNAL
-        JMODSUFFIX=$_SOSUFFIX
+	if test `uname` = "Darwin"; then
+	    JMODSUFFIX=".jnilib"
+	else
+            JMODSUFFIX=$_SOSUFFIX
+	fi
 	AC_MSG_RESULT($JMODSUFFIX)
 	AC_SUBST(JMODSUFFIX)
 ])
diff --git a/storage/bdb/dist/aclocal/tcl.ac b/storage/bdb/dist/aclocal/tcl.ac
index 80ed19c5a972226f6f37fb7fb102412fe67ddf22..d28d360834c2f22d108d16d0dbc50cefec9ba524 100644
--- a/storage/bdb/dist/aclocal/tcl.ac
+++ b/storage/bdb/dist/aclocal/tcl.ac
@@ -1,4 +1,4 @@
-# $Id: tcl.ac,v 11.14 2002/09/07 17:25:58 dda Exp $
+# $Id: tcl.ac,v 11.18 2004/03/11 20:11:17 bostic Exp $
 
 # The SC_* macros in this file are from the unix/tcl.m4 files in the Tcl
 # 8.3.0 distribution, with some minor changes.  For this reason, license
@@ -87,6 +87,12 @@ AC_DEFUN(SC_LOAD_TCLCONFIG, [
 		AC_MSG_RESULT([file not found])
 	fi
 
+	# DB requires at least version 8.4.
+	if test ${TCL_MAJOR_VERSION} -lt 8 \
+	    -o ${TCL_MAJOR_VERSION} -eq 8 -a ${TCL_MINOR_VERSION} -lt 4; then
+		AC_MSG_ERROR([Berkeley DB requires Tcl version 8.4 or better.])
+	fi
+
 	#
 	# The eval is required to do the TCL_DBGX substitution in the
 	# TCL_LIB_FILE variable
@@ -118,8 +124,7 @@ AC_DEFUN(SC_LOAD_TCLCONFIG, [
 
 # Optional Tcl API.
 AC_DEFUN(AM_TCL_LOAD, [
-if test "$db_cv_tcl" = "yes"; then
-	if test "$enable_shared" = "no"; then
+	if test `$LIBTOOL_PROG --config | grep build_libtool_libs | grep no` 2>/dev/null; then
 		AC_MSG_ERROR([Tcl requires shared libraries])
 	fi
 
@@ -133,4 +138,4 @@ if test "$db_cv_tcl" = "yes"; then
 	fi
 
 	INSTALL_LIBS="${INSTALL_LIBS} \$(libtso_target)"
-fi])
+])
diff --git a/storage/bdb/dist/aclocal/types.ac b/storage/bdb/dist/aclocal/types.ac
index db8aaac6884d231796917d357592d3a7275ea60c..b5843385c1a2c681c922c7d67a2f63b8b32863cc 100644
--- a/storage/bdb/dist/aclocal/types.ac
+++ b/storage/bdb/dist/aclocal/types.ac
@@ -1,11 +1,4 @@
-# $Id: types.ac,v 11.10 2001/12/10 14:16:49 bostic Exp $
-
-# db.h includes <sys/types.h> and <stdio.h>, not the other default includes
-# autoconf usually includes.  For that reason, we specify a set of includes
-# for all type checking tests. [#5060]
-AC_DEFUN(DB_INCLUDES, [[
-#include <sys/types.h>
-#include <stdio.h>]])
+# $Id: types.ac,v 11.18 2004/10/25 18:14:14 bostic Exp $
 
 # Check the sizes we know about, and see if any of them match what's needed.
 #
@@ -21,8 +14,12 @@ AC_DEFUN(AM_SEARCH_USIZES, [
 		$1="typedef unsigned short $2;";;
 	"$ac_cv_sizeof_unsigned_long")
 		$1="typedef unsigned long $2;";;
+	"$ac_cv_sizeof_unsigned_long_long")
+		$1="typedef unsigned long long $2;";;
 	*)
-		AC_MSG_ERROR([No unsigned $3-byte integral type]);;
+		if test "$4" != "notfatal"; then
+			AC_MSG_ERROR([No unsigned $3-byte integral type])
+		fi;;
 	esac])
 AC_DEFUN(AM_SEARCH_SSIZES, [
 	case "$3" in
@@ -34,113 +31,133 @@ AC_DEFUN(AM_SEARCH_SSIZES, [
 		$1="typedef short $2;";;
 	"$ac_cv_sizeof_long")
 		$1="typedef long $2;";;
+	"$ac_cv_sizeof_long_long")
+		$1="typedef long long $2;";;
 	*)
-		AC_MSG_ERROR([No signed $3-byte integral type]);;
+		if test "$4" != "notfatal"; then
+			AC_MSG_ERROR([No signed $3-byte integral type])
+		fi;;
 	esac])
 
 # Check for the standard system types.
 AC_DEFUN(AM_TYPES, [
 
-# We need to know the sizes of various objects on this system.
-# We don't use the SIZEOF_XXX values created by autoconf.
-AC_CHECK_SIZEOF(char,, DB_INCLUDES)
-AC_CHECK_SIZEOF(unsigned char,, DB_INCLUDES)
-AC_CHECK_SIZEOF(short,, DB_INCLUDES)
-AC_CHECK_SIZEOF(unsigned short,, DB_INCLUDES)
-AC_CHECK_SIZEOF(int,, DB_INCLUDES)
-AC_CHECK_SIZEOF(unsigned int,, DB_INCLUDES)
-AC_CHECK_SIZEOF(long,, DB_INCLUDES)
-AC_CHECK_SIZEOF(unsigned long,, DB_INCLUDES)
-AC_CHECK_SIZEOF(size_t,, DB_INCLUDES)
-AC_CHECK_SIZEOF(char *,, DB_INCLUDES)
+# db.h includes <sys/types.h> and <stdio.h>, not the other default includes
+# autoconf usually includes.  For that reason, we specify a set of includes
+# for all type checking tests. [#5060]
+#
+# C99 says types should be in <stdint.h>; include <stdint.h> if it exists.
+#
+# Some systems have types in <stddef.h>; include <stddef.h> if it exists.
+#
+# IBM's OS/390 and z/OS releases have types in <inttypes.h> not also found
+# in <sys/types.h>; include <inttypes.h> if it exists.
+db_includes="#include <sys/types.h>"
+AC_SUBST(inttypes_h_decl)
+AC_CHECK_HEADER(inttypes.h, [
+	db_includes="$db_includes
+#include <inttypes.h>"
+	inttypes_h_decl="#include <inttypes.h>"])
+AC_SUBST(stdint_h_decl)
+AC_CHECK_HEADER(stdint.h, [
+	db_includes="$db_includes
+#include <stdint.h>"
+	stdint_h_decl="#include <stdint.h>"])
+AC_SUBST(stddef_h_decl)
+AC_CHECK_HEADER(stddef.h, [
+	db_includes="$db_includes
+#include <stddef.h>"
+	stddef_h_decl="#include <stddef.h>"])
+db_includes="$db_includes
+#include <stdio.h>"
 
 # We require off_t and size_t, and we don't try to substitute our own
 # if we can't find them.
-AC_CHECK_TYPE(off_t,,, DB_INCLUDES)
-if test "$ac_cv_type_off_t" = no; then
-	AC_MSG_ERROR([No off_t type.])
-fi
+AC_CHECK_TYPE(off_t,, AC_MSG_ERROR([No off_t type.]), $db_includes)
+AC_CHECK_TYPE(size_t,, AC_MSG_ERROR([No size_t type.]), $db_includes)
+
+# Check for long long and unsigned long long, we only support sequences
+# if those types are available.
+AC_CHECK_TYPES([long long, unsigned long long],,, $db_includes)
 
-AC_CHECK_TYPE(size_t,,, DB_INCLUDES)
-if test "$ac_cv_type_size_t" = no; then
-	AC_MSG_ERROR([No size_t type.])
-fi
+# We need to know the sizes of various objects on this system.
+AC_CHECK_SIZEOF(char,, $db_includes)
+AC_CHECK_SIZEOF(unsigned char,, $db_includes)
+AC_CHECK_SIZEOF(short,, $db_includes)
+AC_CHECK_SIZEOF(unsigned short,, $db_includes)
+AC_CHECK_SIZEOF(int,, $db_includes)
+AC_CHECK_SIZEOF(unsigned int,, $db_includes)
+AC_CHECK_SIZEOF(long,, $db_includes)
+AC_CHECK_SIZEOF(unsigned long,, $db_includes)
+AC_CHECK_SIZEOF(long long,, $db_includes)
+AC_CHECK_SIZEOF(unsigned long long,, $db_includes)
+AC_CHECK_SIZEOF(size_t,, $db_includes)
+AC_CHECK_SIZEOF(char *,, $db_includes)
 
 # We look for u_char, u_short, u_int, u_long -- if we can't find them,
 # we create our own.
 AC_SUBST(u_char_decl)
-AC_CHECK_TYPE(u_char,,, DB_INCLUDES)
-if test "$ac_cv_type_u_char" = no; then
-	u_char_decl="typedef unsigned char u_char;"
-fi
+AC_CHECK_TYPE(u_char,,
+    [u_char_decl="typedef unsigned char u_char;"], $db_includes)
 
 AC_SUBST(u_short_decl)
-AC_CHECK_TYPE(u_short,,, DB_INCLUDES)
-if test "$ac_cv_type_u_short" = no; then
-	u_short_decl="typedef unsigned short u_short;"
-fi
+AC_CHECK_TYPE(u_short,,
+    [u_short_decl="typedef unsigned short u_short;"], $db_includes)
 
 AC_SUBST(u_int_decl)
-AC_CHECK_TYPE(u_int,,, DB_INCLUDES)
-if test "$ac_cv_type_u_int" = no; then
-	u_int_decl="typedef unsigned int u_int;"
-fi
+AC_CHECK_TYPE(u_int,,
+    [u_int_decl="typedef unsigned int u_int;"], $db_includes)
 
 AC_SUBST(u_long_decl)
-AC_CHECK_TYPE(u_long,,, DB_INCLUDES)
-if test "$ac_cv_type_u_long" = no; then
-	u_long_decl="typedef unsigned long u_long;"
-fi
+AC_CHECK_TYPE(u_long,,
+    [u_long_decl="typedef unsigned long u_long;"], $db_includes)
 
+# We look for fixed-size variants of u_char, u_short, u_int, u_long as well.
 AC_SUBST(u_int8_decl)
-AC_CHECK_TYPE(u_int8_t,,, DB_INCLUDES)
-if test "$ac_cv_type_u_int8_t" = no; then
-	AM_SEARCH_USIZES(u_int8_decl, u_int8_t, 1)
-fi
+AC_CHECK_TYPE(u_int8_t,,
+    [AM_SEARCH_USIZES(u_int8_decl, u_int8_t, 1)], $db_includes)
 
 AC_SUBST(u_int16_decl)
-AC_CHECK_TYPE(u_int16_t,,, DB_INCLUDES)
-if test "$ac_cv_type_u_int16_t" = no; then
-	AM_SEARCH_USIZES(u_int16_decl, u_int16_t, 2)
-fi
+AC_CHECK_TYPE(u_int16_t,,
+    [AM_SEARCH_USIZES(u_int16_decl, u_int16_t, 2)], $db_includes)
 
 AC_SUBST(int16_decl)
-AC_CHECK_TYPE(int16_t,,, DB_INCLUDES)
-if test "$ac_cv_type_int16_t" = no; then
-	AM_SEARCH_SSIZES(int16_decl, int16_t, 2)
-fi
+AC_CHECK_TYPE(int16_t,,
+    [AM_SEARCH_SSIZES(int16_decl, int16_t, 2)], $db_includes)
 
 AC_SUBST(u_int32_decl)
-AC_CHECK_TYPE(u_int32_t,,, DB_INCLUDES)
-if test "$ac_cv_type_u_int32_t" = no; then
-	AM_SEARCH_USIZES(u_int32_decl, u_int32_t, 4)
-fi
+AC_CHECK_TYPE(u_int32_t,,
+    [AM_SEARCH_USIZES(u_int32_decl, u_int32_t, 4)], $db_includes)
 
 AC_SUBST(int32_decl)
-AC_CHECK_TYPE(int32_t,,, DB_INCLUDES)
-if test "$ac_cv_type_int32_t" = no; then
-	AM_SEARCH_SSIZES(int32_decl, int32_t, 4)
-fi
+AC_CHECK_TYPE(int32_t,,
+    [AM_SEARCH_SSIZES(int32_decl, int32_t, 4)], $db_includes)
+
+AC_SUBST(u_int64_decl)
+AC_CHECK_TYPE(u_int64_t,,
+    [AM_SEARCH_USIZES(u_int64_decl, u_int64_t, 8, notfatal)], $db_includes)
+
+AC_SUBST(int64_decl)
+AC_CHECK_TYPE(int64_t,,
+    [AM_SEARCH_SSIZES(int64_decl, int64_t, 8, notfatal)], $db_includes)
 
 # Check for ssize_t -- if none exists, find a signed integral type that's
 # the same size as a size_t.
 AC_SUBST(ssize_t_decl)
-AC_CHECK_TYPE(ssize_t,,, DB_INCLUDES)
-if test "$ac_cv_type_ssize_t" = no; then
-	AM_SEARCH_SSIZES(ssize_t_decl, ssize_t, $ac_cv_sizeof_size_t)
-fi
-
-# Find the largest integral type.
-AC_SUBST(db_align_t_decl)
-AC_CHECK_TYPE(unsigned long long,,, DB_INCLUDES)
-if test "$ac_cv_type_unsigned_long_long" = no; then
-	db_align_t_decl="typedef unsigned long db_align_t;"
-else
-	db_align_t_decl="typedef unsigned long long db_align_t;"
-fi
-
-# Find an integral type which is the same size as a pointer.
-AC_SUBST(db_alignp_t_decl)
-AM_SEARCH_USIZES(db_alignp_t_decl, db_alignp_t, $ac_cv_sizeof_char_p)
-
+AC_CHECK_TYPE(ssize_t,,
+    [AM_SEARCH_SSIZES(ssize_t_decl, ssize_t, $ac_cv_sizeof_size_t)],
+    $db_includes)
+
+# Check for uintmax_t -- if none exists, first the largest unsigned integral
+# type available.
+AC_SUBST(uintmax_t_decl)
+AC_CHECK_TYPE(uintmax_t,, [AC_CHECK_TYPE(unsigned long long,
+    [uintmax_t_decl="typedef unsigned long long uintmax_t;"],
+    [uintmax_t_decl="typedef unsigned long uintmax_t;"], $db_includes)])
+
+# Check for uintptr_t -- if none exists, find an integral type which is
+# the same size as a pointer.
+AC_SUBST(uintptr_t_decl)
+AC_CHECK_TYPE(uintptr_t,,
+    [AM_SEARCH_USIZES(uintptr_t_decl, uintptr_t, $ac_cv_sizeof_char_p)])
 ])
diff --git a/storage/bdb/dist/aclocal_java/ac_jni_include_dirs.ac b/storage/bdb/dist/aclocal_java/ac_jni_include_dirs.ac
index 65cfbbfd13eeee501c245d93e23eede2a76168a2..b70d108d6cf4d53f9c3e951c2e14441d62f3d459 100644
--- a/storage/bdb/dist/aclocal_java/ac_jni_include_dirs.ac
+++ b/storage/bdb/dist/aclocal_java/ac_jni_include_dirs.ac
@@ -28,7 +28,7 @@ dnl Note: This macro can work with the autoconf M4 macros for Java programs.
 dnl This particular macro is not part of the original set of macros.
 dnl
 dnl @author Don Anderson <dda@sleepycat.com>
-dnl @version $Id: ac_jni_include_dirs.ac,v 1.8 2002/09/04 21:27:30 dda Exp $
+dnl @version $Id: ac_jni_include_dirs.ac,v 1.12 2003/10/05 18:10:06 dda Exp $
 dnl
 AC_DEFUN(AC_JNI_INCLUDE_DIR,[
 
@@ -54,18 +54,19 @@ esac
 # If we find jni.h in /usr/include, then it's not a java-only tree, so
 # don't add /usr/include or subdirectories to the list of includes.
 # An extra -I/usr/include can foul things up with newer gcc's.
-if test -f "$_JINC/jni.h"; then
+#
+# If we don't find jni.h, just keep going.  Hopefully javac knows where
+# to find its include files, even if we can't.
+if test -r "$_JINC/jni.h"; then
 	if test "$_JINC" != "/usr/include"; then
 		JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $_JINC"
 	fi
 else
 	_JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'`
-	if test -f "$_JTOPDIR/include/jni.h"; then
+	if test -r "$_JTOPDIR/include/jni.h"; then
 		if test "$_JTOPDIR" != "/usr"; then
 			JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $_JTOPDIR/include"
 		fi
-	else
-		AC_MSG_ERROR([cannot find java include files])
 	fi
 fi
 
@@ -74,6 +75,8 @@ if test "$_JTOPDIR" != "/usr"; then
 	case "$host_os" in
 	aix*)		_JNI_INC_SUBDIRS="aix";;
 	bsdi*)		_JNI_INC_SUBDIRS="bsdos";;
+	freebsd*)	_JNI_INC_SUBDIRS="freebsd";;
+	hp*)		_JNI_INC_SUBDIRS="hp-ux";;
 	linux*)		_JNI_INC_SUBDIRS="linux genunix";;
 	osf*)		_JNI_INC_SUBDIRS="alpha";;
 	solaris*)	_JNI_INC_SUBDIRS="solaris";;
@@ -109,4 +112,3 @@ while ls -ld "$_cur" 2>/dev/null | grep " -> " >/dev/null; do
 done
 _ACJNI_FOLLOWED="$_cur"
 ])# _ACJNI
-
diff --git a/storage/bdb/dist/aclocal_java/ac_prog_java.ac b/storage/bdb/dist/aclocal_java/ac_prog_java.ac
index 8cb244451321823cf9cb24c699b99e255ef5cd16..67a879ffcf675724f66dd15e7145316c216c1316 100644
--- a/storage/bdb/dist/aclocal_java/ac_prog_java.ac
+++ b/storage/bdb/dist/aclocal_java/ac_prog_java.ac
@@ -62,14 +62,16 @@ dnl
 dnl    AC_OUTPUT(Makefile)
 dnl
 dnl @author Stephane Bortzmeyer <bortzmeyer@pasteur.fr>
-dnl @version $Id: ac_prog_java.ac,v 1.1 2001/08/23 16:58:43 dda Exp $
+dnl @version $Id: ac_prog_java.ac,v 1.2 2003/05/10 17:46:09 dda Exp $
+dnl
+dnl Note: Modified by dda@sleepycat.com to prefer java over kaffe. [#8059]
 dnl
 AC_DEFUN([AC_PROG_JAVA],[
 AC_REQUIRE([AC_EXEEXT])dnl
 if test x$JAVAPREFIX = x; then
-        test x$JAVA = x && AC_CHECK_PROGS(JAVA, kaffe$EXEEXT java$EXEEXT)
+        test x$JAVA = x && AC_CHECK_PROGS(JAVA, java$EXEEXT kaffe$EXEEXT)
 else
-        test x$JAVA = x && AC_CHECK_PROGS(JAVA, kaffe$EXEEXT java$EXEEXT, $JAVAPREFIX)
+        test x$JAVA = x && AC_CHECK_PROGS(JAVA, java$EXEEXT kaffe$EXEEXT, $JAVAPREFIX)
 fi
 test x$JAVA = x && AC_MSG_ERROR([no acceptable Java virtual machine found in \$PATH])
 AC_PROG_JAVA_WORKS
diff --git a/storage/bdb/dist/buildrel b/storage/bdb/dist/buildrel
index b796169c719eeb3c39212f819e0701d491079284..2537376a87a5a62e2e2c34b6b7dc09419125fee2 100644
--- a/storage/bdb/dist/buildrel
+++ b/storage/bdb/dist/buildrel
@@ -1,7 +1,6 @@
-#!/bin/sh -
-#	$Id: buildrel,v 1.39 2002/09/06 14:30:31 bostic Exp $
+# $Id: buildrel,v 1.65 2004/11/09 01:26:29 bostic Exp $
 #
-# Build the distribution archives.
+# Build the distribution package.
 #
 # A set of commands intended to be cut and pasted into a csh window.
 
@@ -10,67 +9,82 @@ setenv D `pwd`
 
 # Update the release number.
 cd $D/dist
+cvs -q update RELEASE
 vi RELEASE
-setenv VERSION \
-`sh -c '. RELEASE; echo $DB_VERSION_MAJOR.$DB_VERSION_MINOR.$DB_VERSION_PATCH'`
+setenv VERSION `sh -c '. RELEASE; echo $DB_VERSION'`
 echo "Version: $VERSION"
 
-# Make sure the source tree is up-to-date, generate new support files, and
-# commit anything that's changed.
+# Make sure the source tree is up-to-date
 cd $D && cvs -q update
+
+# Build auto-generated files.
 cd $D/dist && sh s_all
+
+# Commit all of the changes.
 cd $D && cvs -q commit
 
 # Copy a development tree into a release tree.
 setenv R /var/tmp/db-$VERSION
 rm -rf $R && mkdir -p $R
-cd $D && tar cf - \
-`cvs -q status | sed -n -e "/Repository/s;.*/CVSROOT/db/;;" -e "s/,v//p"` | \
-(cd $R && tar xpf -)
+cd $D && cvs -q status | \
+    grep "Repository revision" | \
+    sed -e 's;.*CVSROOT/db/;;' \
+        -e 's;.*CVSROOT/;;' \
+	-e 's;,v$;;' | pax -rw $R/
+
+# Build the documentation, copy it into place.
+cd db_docs && cvs -q update
+cd db_docs && sh build $D clean && sh build $D |& sed '/.html$/d'
+cd je/docs_src && sh build db ../../db
+rm -rf $R/docs && cp -r $D/docs $R/docs
+
+# Remove source directories we don't distribute.
+cd $R && rm -rf docs_src docs/api_java
+cd $R && rm -rf test/TODO test/upgrade test_perf test_purify
+cd $R && rm -rf test_server test_thread test_vxworks test_xa
+cd $R && rm -rf java/src/com/sleepycat/xa
 
 # Fix symbolic links and permissions.
 cd $R/dist && sh s_perm
 cd $R/dist && sh s_symlink
 
-# Build a version.
+# Build a version and smoke test.
 cd $R && rm -rf build_run && mkdir build_run
 cd $R/build_run && ~bostic/bin/dbconf && make >& mklog
-
-# Smoke test.
-cd $R/build_run && ./ex_access
-
-# Build the documentation.
-cd $R/docs_src && sh build clean
-cd $R/docs_src && sh build |& sed '/.html$/d'
+cd $R/build_run && make ex_access && ./ex_access
 
 # Check the install
 cd $R/build_run && make prefix=`pwd`/BDB install
 
-# Clean up the tree.
-cd $R && rm -rf build_run docs_src
-cd $R && rm -rf test/TODO test/upgrade test_perf test_purify
-cd $R && rm -rf test_server test_thread test_vxworks test_xa
+# Build a small-footprint version and smoke test.
+cd $R && rm -rf build_run && mkdir build_run
+cd $R/build_run && ../dist/configure --enable-smallbuild && make >& mklog
+cd $R/build_run && make ex_access && ./ex_access
+
+# Remove the build directory
+cd $R && rm -rf build_run
 
 # ACQUIRE ROOT PRIVILEGES
 cd $R && find . -type d | xargs chmod 775
 cd $R && find . -type f | xargs chmod 444
 cd $R && chmod 664 build_win32/*.dsp
 cd $R/dist && sh s_perm
-chown -R 100.100 $R
+chown -R 100 $R
+chgrp -R 100 $R
 # DISCARD ROOT PRIVILEGES
 
-# Compare this release with the last one.
-set LR=3.1.X
-cd $R/.. && gzcat /a/releases/db-${LR}.tar.gz | tar xf -
-cd $R/../db-${LR} && find . | sort > /tmp/__OLD
-cd $R && find . | sort > /tmp/__NEW
-diff -c /tmp/__OLD /tmp/__NEW
+# Check for file names differing only in case.
+cd $R && find . | sort -f | uniq -ic | sed '/1 /d'
 
 # Create the crypto tar archive release.
 setenv T "$R/../db-$VERSION.tar.gz"
 cd $R/.. && tar cf - db-$VERSION | gzip --best > $T
 chmod 444 $T
 
+# Check the path length.
+gzcat $T | tar tf - |\
+awk '{ if (length() > 99) print "Path length: " length() " bytes: " $0;}'
+
 # Create the non-crypto tree.
 setenv RNC "$R/../db-$VERSION.NC"
 rm -rf $RNC $R/../__TMP && mkdir $R/../__TMP
@@ -83,7 +97,8 @@ cd $RNC && find . -type d | xargs chmod 775
 cd $RNC && find . -type f | xargs chmod 444
 cd $RNC && chmod 664 build_win32/*.dsp
 cd $RNC/dist && sh s_perm
-chown -R 100.100 $RNC
+chown -R 100 $RNC
+chgrp -R 100 $RNC
 # DISCARD ROOT PRIVILEGES
 
 # Create the non-crypto tar archive release.
@@ -91,11 +106,15 @@ setenv T "$R/../db-$VERSION.NC.tar.gz"
 cd $RNC/.. && tar cf - db-$VERSION.NC | gzip --best > $T
 chmod 444 $T
 
-# Remove symbolic links to tags files.  They're large and we don't want
-# to store real symbolic links in the zip archive for portability reasons.
+# Check the path length.
+gzcat $T | tar tf - |\
+awk '{ if (length() > 99) print "Path length: " length() " bytes: " $0;}'
+
+# Remove tags files.  They're large and we don't want to store symbolic links
+# in the zip archive for portability reasons.
 # ACQUIRE ROOT PRIVILEGES
-cd $R && rm -f `find . -type l -name 'tags'`
-cd $RNC && rm -f `find . -type l -name 'tags'`
+cd $R && rm -f `find . -name 'tags'`
+cd $RNC && rm -f `find . -name 'tags'`
 # DISCARD ROOT PRIVILEGES
 
 # Create the crypto zip archive release.
diff --git a/storage/bdb/dist/config.guess b/storage/bdb/dist/config.guess
index fd30ab0314cd95a2544eaaefb5ebf4291c52805c..7d0185e019ed6b83bca92431ff478d7e19b0037e 100755
--- a/storage/bdb/dist/config.guess
+++ b/storage/bdb/dist/config.guess
@@ -1,9 +1,9 @@
 #! /bin/sh
 # Attempt to guess a canonical system name.
 #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002 Free Software Foundation, Inc.
+#   2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
-timestamp='2002-07-23'
+timestamp='2004-09-07'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -53,7 +53,7 @@ version="\
 GNU config.guess ($timestamp)
 
 Originally written by Per Bothner.
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
@@ -98,30 +98,32 @@ trap 'exit 1' 1 2 15
 # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
 # use `HOST_CC' if defined, but it is deprecated.
 
-# This shell variable is my proudest work .. or something. --bje
+# Portable tmp directory creation inspired by the Autoconf team.
 
-set_cc_for_build='tmpdir=${TMPDIR-/tmp}/config-guess-$$ ;
-(old=`umask` && umask 077 && mkdir $tmpdir && umask $old && unset old)
-   || (echo "$me: cannot create $tmpdir" >&2 && exit 1) ;
-dummy=$tmpdir/dummy ;
-files="$dummy.c $dummy.o $dummy.rel $dummy" ;
-trap '"'"'rm -f $files; rmdir $tmpdir; exit 1'"'"' 1 2 15 ;
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
 case $CC_FOR_BUILD,$HOST_CC,$CC in
  ,,)    echo "int x;" > $dummy.c ;
 	for c in cc gcc c89 c99 ; do
-	  if ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ; then
+	  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
 	     CC_FOR_BUILD="$c"; break ;
 	  fi ;
 	done ;
-	rm -f $files ;
 	if test x"$CC_FOR_BUILD" = x ; then
 	  CC_FOR_BUILD=no_compiler_found ;
 	fi
 	;;
  ,,*)   CC_FOR_BUILD=$CC ;;
  ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
-esac ;
-unset files'
+esac ;'
 
 # This is needed to find uname on a Pyramid OSx when run in the BSD universe.
 # (ghazi@noc.rutgers.edu 1994-08-24)
@@ -178,21 +180,38 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 		;;
 	esac
 	# The OS release
-	release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+	# Debian GNU/NetBSD machines have a different userland, and
+	# thus, need a distinct triplet. However, they do not need
+	# kernel version information, so it can be replaced with a
+	# suitable tag, in the style of linux-gnu.
+	case "${UNAME_VERSION}" in
+	    Debian*)
+		release='-gnu'
+		;;
+	    *)
+		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+		;;
+	esac
 	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
 	# contains redundant information, the shorter form:
 	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
 	echo "${machine}-${os}${release}"
 	exit 0 ;;
+    amd64:OpenBSD:*:*)
+	echo x86_64-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
     amiga:OpenBSD:*:*)
 	echo m68k-unknown-openbsd${UNAME_RELEASE}
 	exit 0 ;;
-    arc:OpenBSD:*:*)
-	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+    cats:OpenBSD:*:*)
+	echo arm-unknown-openbsd${UNAME_RELEASE}
 	exit 0 ;;
     hp300:OpenBSD:*:*)
 	echo m68k-unknown-openbsd${UNAME_RELEASE}
 	exit 0 ;;
+    luna88k:OpenBSD:*:*)
+    	echo m88k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
     mac68k:OpenBSD:*:*)
 	echo m68k-unknown-openbsd${UNAME_RELEASE}
 	exit 0 ;;
@@ -208,86 +227,76 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     mvmeppc:OpenBSD:*:*)
 	echo powerpc-unknown-openbsd${UNAME_RELEASE}
 	exit 0 ;;
-    pmax:OpenBSD:*:*)
-	echo mipsel-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
     sgi:OpenBSD:*:*)
-	echo mipseb-unknown-openbsd${UNAME_RELEASE}
+	echo mips64-unknown-openbsd${UNAME_RELEASE}
 	exit 0 ;;
     sun3:OpenBSD:*:*)
 	echo m68k-unknown-openbsd${UNAME_RELEASE}
 	exit 0 ;;
-    wgrisc:OpenBSD:*:*)
-	echo mipsel-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
     *:OpenBSD:*:*)
 	echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
 	exit 0 ;;
+    *:ekkoBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+	exit 0 ;;
+    macppc:MirBSD:*:*)
+	echo powerppc-unknown-mirbsd${UNAME_RELEASE}
+	exit 0 ;;
+    *:MirBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+	exit 0 ;;
     alpha:OSF1:*:*)
-	if test $UNAME_RELEASE = "V4.0"; then
+	case $UNAME_RELEASE in
+	*4.0)
 		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
-	fi
+		;;
+	*5.*)
+	        UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+		;;
+	esac
+	# According to Compaq, /usr/sbin/psrinfo has been available on
+	# OSF/1 and Tru64 systems produced since 1995.  I hope that
+	# covers most systems running today.  This code pipes the CPU
+	# types through head -n 1, so we only detect the type of CPU 0.
+	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+	case "$ALPHA_CPU_TYPE" in
+	    "EV4 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV4.5 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "LCA4 (21066/21068)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV5 (21164)")
+		UNAME_MACHINE="alphaev5" ;;
+	    "EV5.6 (21164A)")
+		UNAME_MACHINE="alphaev56" ;;
+	    "EV5.6 (21164PC)")
+		UNAME_MACHINE="alphapca56" ;;
+	    "EV5.7 (21164PC)")
+		UNAME_MACHINE="alphapca57" ;;
+	    "EV6 (21264)")
+		UNAME_MACHINE="alphaev6" ;;
+	    "EV6.7 (21264A)")
+		UNAME_MACHINE="alphaev67" ;;
+	    "EV6.8CB (21264C)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8AL (21264B)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8CX (21264D)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.9A (21264/EV69A)")
+		UNAME_MACHINE="alphaev69" ;;
+	    "EV7 (21364)")
+		UNAME_MACHINE="alphaev7" ;;
+	    "EV7.9 (21364A)")
+		UNAME_MACHINE="alphaev79" ;;
+	esac
+	# A Pn.n version is a patched version.
 	# A Vn.n version is a released version.
 	# A Tn.n version is a released field test version.
 	# A Xn.n version is an unreleased experimental baselevel.
 	# 1.2 uses "1.2" for uname -r.
-	eval $set_cc_for_build
-	cat <<EOF >$dummy.s
-	.data
-\$Lformat:
-	.byte 37,100,45,37,120,10,0	# "%d-%x\n"
-
-	.text
-	.globl main
-	.align 4
-	.ent main
-main:
-	.frame \$30,16,\$26,0
-	ldgp \$29,0(\$27)
-	.prologue 1
-	.long 0x47e03d80 # implver \$0
-	lda \$2,-1
-	.long 0x47e20c21 # amask \$2,\$1
-	lda \$16,\$Lformat
-	mov \$0,\$17
-	not \$1,\$18
-	jsr \$26,printf
-	ldgp \$29,0(\$26)
-	mov 0,\$16
-	jsr \$26,exit
-	.end main
-EOF
-	$CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
-	if test "$?" = 0 ; then
-		case `$dummy` in
-			0-0)
-				UNAME_MACHINE="alpha"
-				;;
-			1-0)
-				UNAME_MACHINE="alphaev5"
-				;;
-			1-1)
-				UNAME_MACHINE="alphaev56"
-				;;
-			1-101)
-				UNAME_MACHINE="alphapca56"
-				;;
-			2-303)
-				UNAME_MACHINE="alphaev6"
-				;;
-			2-307)
-				UNAME_MACHINE="alphaev67"
-				;;
-			2-1307)
-				UNAME_MACHINE="alphaev68"
-				;;
-			3-1307)
-				UNAME_MACHINE="alphaev7"
-				;;
-		esac
-	fi
-	rm -f $dummy.s $dummy && rmdir $tmpdir
-	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
 	exit 0 ;;
     Alpha\ *:Windows_NT*:*)
 	# How do we know it's Interix rather than the generic POSIX subsystem?
@@ -310,6 +319,9 @@ EOF
     *:OS/390:*:*)
 	echo i370-ibm-openedition
 	exit 0 ;;
+    *:OS400:*:*)
+        echo powerpc-ibm-os400
+	exit 0 ;;
     arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
 	echo arm-acorn-riscix${UNAME_RELEASE}
 	exit 0;;
@@ -327,6 +339,9 @@ EOF
     NILE*:*:*:dcosx)
 	echo pyramid-pyramid-svr4
 	exit 0 ;;
+    DRS?6000:unix:4.0:6*)
+	echo sparc-icl-nx6
+	exit 0 ;;
     DRS?6000:UNIX_SV:4.2*:7*)
 	case `/usr/bin/uname -p` in
 	    sparc) echo sparc-icl-nx7 && exit 0 ;;
@@ -399,6 +414,9 @@ EOF
     *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
         echo m68k-unknown-mint${UNAME_RELEASE}
         exit 0 ;;
+    m68k:machten:*:*)
+	echo m68k-apple-machten${UNAME_RELEASE}
+	exit 0 ;;
     powerpc:machten:*:*)
 	echo powerpc-apple-machten${UNAME_RELEASE}
 	exit 0 ;;
@@ -437,16 +455,18 @@ EOF
 	  exit (-1);
 	}
 EOF
-	$CC_FOR_BUILD $dummy.c -o $dummy \
+	$CC_FOR_BUILD -o $dummy $dummy.c \
 	  && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
-	  && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0
-	rm -f $dummy.c $dummy && rmdir $tmpdir
+	  && exit 0
 	echo mips-mips-riscos${UNAME_RELEASE}
 	exit 0 ;;
     Motorola:PowerMAX_OS:*:*)
 	echo powerpc-motorola-powermax
 	exit 0 ;;
-    Night_Hawk:*:*:PowerMAX_OS)
+    Motorola:*:4.3:PL8-*)
+	echo powerpc-harris-powermax
+	exit 0 ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
 	echo powerpc-harris-powermax
 	exit 0 ;;
     Night_Hawk:Power_UNIX:*:*)
@@ -521,8 +541,7 @@ EOF
 			exit(0);
 			}
 EOF
-		$CC_FOR_BUILD $dummy.c -o $dummy && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0
-		rm -f $dummy.c $dummy && rmdir $tmpdir
+		$CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
 		echo rs6000-ibm-aix3.2.5
 	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
 		echo rs6000-ibm-aix3.2.4
@@ -620,11 +639,21 @@ EOF
                   exit (0);
               }
 EOF
-		    (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null) && HP_ARCH=`$dummy`
-		    if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi
-		    rm -f $dummy.c $dummy && rmdir $tmpdir
+		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+		    test -z "$HP_ARCH" && HP_ARCH=hppa
 		fi ;;
 	esac
+	if [ ${HP_ARCH} = "hppa2.0w" ]
+	then
+	    # avoid double evaluation of $set_cc_for_build
+	    test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
+	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
+	    then
+		HP_ARCH="hppa2.0w"
+	    else
+		HP_ARCH="hppa64"
+	    fi
+	fi
 	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
 	exit 0 ;;
     ia64:HP-UX:*:*)
@@ -658,8 +687,7 @@ EOF
 	  exit (0);
 	}
 EOF
-	$CC_FOR_BUILD $dummy.c -o $dummy && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0
-	rm -f $dummy.c $dummy && rmdir $tmpdir
+	$CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
 	echo unknown-hitachi-hiuxwe2
 	exit 0 ;;
     9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
@@ -717,21 +745,26 @@ EOF
     CRAY*TS:*:*:*)
 	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
 	exit 0 ;;
-    CRAY*T3D:*:*:*)
-	echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
-	exit 0 ;;
     CRAY*T3E:*:*:*)
 	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
 	exit 0 ;;
     CRAY*SV1:*:*:*)
 	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
 	exit 0 ;;
+    *:UNICOS/mp:*:*)
+	echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
     F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
 	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
         FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
         FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
         echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
         exit 0 ;;
+    5000:UNIX_System_V:4.*:*)
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit 0 ;;
     i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
 	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
 	exit 0 ;;
@@ -742,19 +775,7 @@ EOF
 	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
 	exit 0 ;;
     *:FreeBSD:*:*)
-	# Determine whether the default compiler uses glibc.
-	eval $set_cc_for_build
-	sed 's/^	//' << EOF >$dummy.c
-	#include <features.h>
-	#if __GLIBC__ >= 2
-	LIBC=gnu
-	#else
-	LIBC=
-	#endif
-EOF
-	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
-	rm -f $dummy.c && rmdir $tmpdir
-	echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
+	echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
 	exit 0 ;;
     i*:CYGWIN*:*)
 	echo ${UNAME_MACHINE}-pc-cygwin
@@ -765,14 +786,17 @@ EOF
     i*:PW*:*)
 	echo ${UNAME_MACHINE}-pc-pw32
 	exit 0 ;;
-    x86:Interix*:3*)
-	echo i386-pc-interix3
+    x86:Interix*:[34]*)
+	echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
+	exit 0 ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+	echo i${UNAME_MACHINE}-pc-mks
 	exit 0 ;;
     i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
 	# How do we know it's Interix rather than the generic POSIX subsystem?
 	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
 	# UNAME_MACHINE based on the output of uname instead of i386?
-	echo i386-pc-interix
+	echo i586-pc-interix
 	exit 0 ;;
     i*:UWIN*:*)
 	echo ${UNAME_MACHINE}-pc-uwin
@@ -784,17 +808,34 @@ EOF
 	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
 	exit 0 ;;
     *:GNU:*:*)
+	# the GNU system
 	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
 	exit 0 ;;
+    *:GNU/*:*:*)
+	# other systems with GNU libc and userland
+	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+	exit 0 ;;
     i*86:Minix:*:*)
 	echo ${UNAME_MACHINE}-pc-minix
 	exit 0 ;;
     arm*:Linux:*:*)
 	echo ${UNAME_MACHINE}-unknown-linux-gnu
 	exit 0 ;;
+    cris:Linux:*:*)
+	echo cris-axis-linux-gnu
+	exit 0 ;;
+    crisv32:Linux:*:*)
+	echo crisv32-axis-linux-gnu
+	exit 0 ;;
+    frv:Linux:*:*)
+    	echo frv-unknown-linux-gnu
+	exit 0 ;;
     ia64:Linux:*:*)
 	echo ${UNAME_MACHINE}-unknown-linux-gnu
 	exit 0 ;;
+    m32r*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
     m68*:Linux:*:*)
 	echo ${UNAME_MACHINE}-unknown-linux-gnu
 	exit 0 ;;
@@ -815,8 +856,26 @@ EOF
 	#endif
 EOF
 	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
-	rm -f $dummy.c && rmdir $tmpdir
-	test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0
+	test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+	;;
+    mips64:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef mips64
+	#undef mips64el
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=mips64el
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=mips64
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+	test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
 	;;
     ppc:Linux:*:*)
 	echo powerpc-unknown-linux-gnu
@@ -852,6 +911,9 @@ EOF
     s390:Linux:*:* | s390x:Linux:*:*)
 	echo ${UNAME_MACHINE}-ibm-linux
 	exit 0 ;;
+    sh64*:Linux:*:*)
+    	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
     sh*:Linux:*:*)
 	echo ${UNAME_MACHINE}-unknown-linux-gnu
 	exit 0 ;;
@@ -909,9 +971,11 @@ EOF
 	LIBC=gnuaout
 	#endif
 	#endif
+	#ifdef __dietlibc__
+	LIBC=dietlibc
+	#endif
 EOF
 	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
-	rm -f $dummy.c && rmdir $tmpdir
 	test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
 	test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
 	;;
@@ -929,6 +993,26 @@ EOF
         # Use sysv4.2uw... so that sysv4* matches it.
 	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
 	exit 0 ;;
+    i*86:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	echo ${UNAME_MACHINE}-pc-os2-emx
+	exit 0 ;;
+    i*86:XTS-300:*:STOP)
+	echo ${UNAME_MACHINE}-unknown-stop
+	exit 0 ;;
+    i*86:atheos:*:*)
+	echo ${UNAME_MACHINE}-unknown-atheos
+	exit 0 ;;
+	i*86:syllable:*:*)
+	echo ${UNAME_MACHINE}-pc-syllable
+	exit 0 ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+	echo i386-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    i*86:*DOS:*:*)
+	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+	exit 0 ;;
     i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
 	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
 	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
@@ -963,9 +1047,6 @@ EOF
 		echo ${UNAME_MACHINE}-pc-sysv32
 	fi
 	exit 0 ;;
-    i*86:*DOS:*:*)
-	echo ${UNAME_MACHINE}-pc-msdosdjgpp
-	exit 0 ;;
     pc:*:*:*)
 	# Left here for compatibility:
         # uname -m prints for DJGPP always 'pc', but it prints nothing about
@@ -989,9 +1070,15 @@ EOF
 	# "miniframe"
 	echo m68010-convergent-sysv
 	exit 0 ;;
-    M68*:*:R3V[567]*:*)
+    mc68k:UNIX:SYSTEM5:3.51m)
+	echo m68k-convergent-sysv
+	exit 0 ;;
+    M680?0:D-NIX:5.3:*)
+	echo m68k-diab-dnix
+	exit 0 ;;
+    M68*:*:R3V[5678]*:*)
 	test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
-    3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0)
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
 	OS_REL=''
 	test -r /etc/.relid \
 	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
@@ -1008,9 +1095,6 @@ EOF
     mc68030:UNIX_System_V:4.*:*)
 	echo m68k-atari-sysv4
 	exit 0 ;;
-    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
-	echo i386-unknown-lynxos${UNAME_RELEASE}
-	exit 0 ;;
     TSUNAMI:LynxOS:2.*:*)
 	echo sparc-unknown-lynxos${UNAME_RELEASE}
 	exit 0 ;;
@@ -1082,6 +1166,9 @@ EOF
     SX-5:SUPER-UX:*:*)
 	echo sx5-nec-superux${UNAME_RELEASE}
 	exit 0 ;;
+    SX-6:SUPER-UX:*:*)
+	echo sx6-nec-superux${UNAME_RELEASE}
+	exit 0 ;;
     Power*:Rhapsody:*:*)
 	echo powerpc-apple-rhapsody${UNAME_RELEASE}
 	exit 0 ;;
@@ -1089,7 +1176,12 @@ EOF
 	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
 	exit 0 ;;
     *:Darwin:*:*)
-	echo `uname -p`-apple-darwin${UNAME_RELEASE}
+	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+	case $UNAME_PROCESSOR in
+	    *86) UNAME_PROCESSOR=i686 ;;
+	    unknown) UNAME_PROCESSOR=powerpc ;;
+	esac
+	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
 	exit 0 ;;
     *:procnto*:*:* | *:QNX:[0123456789]*:*)
 	UNAME_PROCESSOR=`uname -p`
@@ -1102,7 +1194,7 @@ EOF
     *:QNX:*:4*)
 	echo i386-pc-qnx
 	exit 0 ;;
-    NSR-[GKLNPTVW]:NONSTOP_KERNEL:*:*)
+    NSR-?:NONSTOP_KERNEL:*:*)
 	echo nsr-tandem-nsk${UNAME_RELEASE}
 	exit 0 ;;
     *:NonStop-UX:*:*)
@@ -1125,11 +1217,6 @@ EOF
 	fi
 	echo ${UNAME_MACHINE}-unknown-plan9
 	exit 0 ;;
-    i*86:OS/2:*:*)
-	# If we were able to find `uname', then EMX Unix compatibility
-	# is probably installed.
-	echo ${UNAME_MACHINE}-pc-os2-emx
-	exit 0 ;;
     *:TOPS-10:*:*)
 	echo pdp10-unknown-tops10
 	exit 0 ;;
@@ -1148,12 +1235,19 @@ EOF
     *:ITS:*:*)
 	echo pdp10-unknown-its
 	exit 0 ;;
-    i*86:XTS-300:*:STOP)
-	echo ${UNAME_MACHINE}-unknown-stop
+    SEI:*:*:SEIUX)
+        echo mips-sei-seiux${UNAME_RELEASE}
 	exit 0 ;;
-    i*86:atheos:*:*)
-	echo ${UNAME_MACHINE}-unknown-atheos
+    *:DragonFly:*:*)
+	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
 	exit 0 ;;
+    *:*VMS:*:*)
+    	UNAME_MACHINE=`(uname -p) 2>/dev/null`
+	case "${UNAME_MACHINE}" in
+	    A*) echo alpha-dec-vms && exit 0 ;;
+	    I*) echo ia64-dec-vms && exit 0 ;;
+	    V*) echo vax-dec-vms && exit 0 ;;
+	esac
 esac
 
 #echo '(No uname command or uname output not recognized.)' 1>&2
@@ -1274,8 +1368,7 @@ main ()
 }
 EOF
 
-$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0
-rm -f $dummy.c $dummy && rmdir $tmpdir
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0
 
 # Apollos put the system type in the environment.
 
diff --git a/storage/bdb/dist/config.hin b/storage/bdb/dist/config.hin
new file mode 100644
index 0000000000000000000000000000000000000000..28d6181027a67dd7c2bbce0ed18ec3ee000f7ddb
--- /dev/null
+++ b/storage/bdb/dist/config.hin
@@ -0,0 +1,458 @@
+/* config.hin.  Generated from configure.ac by autoheader.  */
+
+/* Define to 1 if you want to build a version for running the test suite. */
+#undef CONFIG_TEST
+
+/* We use DB_WIN32 much as one would use _WIN32 -- to specify that we're using
+   an operating system environment that supports Win32 calls and semantics. We
+   don't use _WIN32 because Cygwin/GCC also defines _WIN32, even though
+   Cygwin/GCC closely emulates the Unix environment. */
+#undef DB_WIN32
+
+/* Define to 1 if you want a debugging version. */
+#undef DEBUG
+
+/* Define to 1 if you want a version that logs read operations. */
+#undef DEBUG_ROP
+
+/* Define to 1 if you want a version that logs write operations. */
+#undef DEBUG_WOP
+
+/* Define to 1 if you want a version with run-time diagnostic checking. */
+#undef DIAGNOSTIC
+
+/* Define to 1 if you have the `clock_gettime' function. */
+#undef HAVE_CLOCK_GETTIME
+
+/* Define to 1 if Berkeley DB release includes strong cryptography. */
+#undef HAVE_CRYPTO
+
+/* Define to 1 if you have the `directio' function. */
+#undef HAVE_DIRECTIO
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+   */
+#undef HAVE_DIRENT_H
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have EXIT_SUCCESS/EXIT_FAILURE #defines. */
+#undef HAVE_EXIT_SUCCESS
+
+/* Define to 1 if fcntl/F_SETFD denies child access to file descriptors. */
+#undef HAVE_FCNTL_F_SETFD
+
+/* Define to 1 if you have the `fdatasync' function. */
+#undef HAVE_FDATASYNC
+
+/* Define to 1 if allocated filesystem blocks are not zeroed. */
+#undef HAVE_FILESYSTEM_NOTZERO
+
+/* Define to 1 if you have the `ftruncate' function. */
+#undef HAVE_FTRUNCATE
+
+/* Define to 1 if you have the `getcwd' function. */
+#undef HAVE_GETCWD
+
+/* Define to 1 if you have the `getopt' function. */
+#undef HAVE_GETOPT
+
+/* Define to 1 if you have the `getrusage' function. */
+#undef HAVE_GETRUSAGE
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define to 1 if you have the `getuid' function. */
+#undef HAVE_GETUID
+
+/* Define to 1 if building Hash access method. */
+#undef HAVE_HASH
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `nsl' library (-lnsl). */
+#undef HAVE_LIBNSL
+
+/* Define to 1 if the system has the type `long long'. */
+#undef HAVE_LONG_LONG
+
+/* Define to 1 if you have the `memcmp' function. */
+#undef HAVE_MEMCMP
+
+/* Define to 1 if you have the `memcpy' function. */
+#undef HAVE_MEMCPY
+
+/* Define to 1 if you have the `memmove' function. */
+#undef HAVE_MEMMOVE
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `mlock' function. */
+#undef HAVE_MLOCK
+
+/* Define to 1 if you have the `mmap' function. */
+#undef HAVE_MMAP
+
+/* Define to 1 if you have the `munlock' function. */
+#undef HAVE_MUNLOCK
+
+/* Define to 1 if you have the `munmap' function. */
+#undef HAVE_MUNMAP
+
+/* Define to 1 to use the GCC compiler and 68K assembly language mutexes. */
+#undef HAVE_MUTEX_68K_GCC_ASSEMBLY
+
+/* Define to 1 to use the AIX _check_lock mutexes. */
+#undef HAVE_MUTEX_AIX_CHECK_LOCK
+
+/* Define to 1 to use the GCC compiler and Alpha assembly language mutexes. */
+#undef HAVE_MUTEX_ALPHA_GCC_ASSEMBLY
+
+/* Define to 1 to use the GCC compiler and ARM assembly language mutexes. */
+#undef HAVE_MUTEX_ARM_GCC_ASSEMBLY
+
+/* Define to 1 to use the Apple/Darwin _spin_lock_try mutexes. */
+#undef HAVE_MUTEX_DARWIN_SPIN_LOCK_TRY
+
+/* Define to 1 to use the UNIX fcntl system call mutexes. */
+#undef HAVE_MUTEX_FCNTL
+
+/* Define to 1 to use the GCC compiler and PaRisc assembly language mutexes.
+   */
+#undef HAVE_MUTEX_HPPA_GCC_ASSEMBLY
+
+/* Define to 1 to use the msem_XXX mutexes on HP-UX. */
+#undef HAVE_MUTEX_HPPA_MSEM_INIT
+
+/* Define to 1 to use the GCC compiler and IA64 assembly language mutexes. */
+#undef HAVE_MUTEX_IA64_GCC_ASSEMBLY
+
+/* Define to 1 to use the msem_XXX mutexes on systems other than HP-UX. */
+#undef HAVE_MUTEX_MSEM_INIT
+
+/* Define to 1 to use the GCC compiler and PowerPC assembly language mutexes.
+   */
+#undef HAVE_MUTEX_PPC_GCC_ASSEMBLY
+
+/* Define to 1 to use POSIX 1003.1 pthread_XXX mutexes. */
+#undef HAVE_MUTEX_PTHREADS
+
+/* Define to 1 to use Reliant UNIX initspin mutexes. */
+#undef HAVE_MUTEX_RELIANTUNIX_INITSPIN
+
+/* Define to 1 to use the IBM C compiler and S/390 assembly language mutexes.
+   */
+#undef HAVE_MUTEX_S390_CC_ASSEMBLY
+
+/* Define to 1 to use the GCC compiler and S/390 assembly language mutexes. */
+#undef HAVE_MUTEX_S390_GCC_ASSEMBLY
+
+/* Define to 1 to use the SCO compiler and x86 assembly language mutexes. */
+#undef HAVE_MUTEX_SCO_X86_CC_ASSEMBLY
+
+/* Define to 1 to use the obsolete POSIX 1003.1 sema_XXX mutexes. */
+#undef HAVE_MUTEX_SEMA_INIT
+
+/* Define to 1 to use the SGI XXX_lock mutexes. */
+#undef HAVE_MUTEX_SGI_INIT_LOCK
+
+/* Define to 1 to use the Solaris _lock_XXX mutexes. */
+#undef HAVE_MUTEX_SOLARIS_LOCK_TRY
+
+/* Define to 1 to use the Solaris lwp threads mutexes. */
+#undef HAVE_MUTEX_SOLARIS_LWP
+
+/* Define to 1 to use the GCC compiler and Sparc assembly language mutexes. */
+#undef HAVE_MUTEX_SPARC_GCC_ASSEMBLY
+
+/* Define to 1 if mutexes hold system resources. */
+#undef HAVE_MUTEX_SYSTEM_RESOURCES
+
+/* Define to 1 if fast mutexes are available. */
+#undef HAVE_MUTEX_THREADS
+
+/* Define to 1 to configure mutexes intra-process only. */
+#undef HAVE_MUTEX_THREAD_ONLY
+
+/* Define to 1 to use the CC compiler and Tru64 assembly language mutexes. */
+#undef HAVE_MUTEX_TRU64_CC_ASSEMBLY
+
+/* Define to 1 to use the UNIX International mutexes. */
+#undef HAVE_MUTEX_UI_THREADS
+
+/* Define to 1 to use the UTS compiler and assembly language mutexes. */
+#undef HAVE_MUTEX_UTS_CC_ASSEMBLY
+
+/* Define to 1 to use VMS mutexes. */
+#undef HAVE_MUTEX_VMS
+
+/* Define to 1 to use VxWorks mutexes. */
+#undef HAVE_MUTEX_VXWORKS
+
+/* Define to 1 to use the MSVC compiler and Windows mutexes. */
+#undef HAVE_MUTEX_WIN32
+
+/* Define to 1 to use the GCC compiler and Windows mutexes. */
+#undef HAVE_MUTEX_WIN32_GCC
+
+/* Define to 1 to use the GCC compiler and x86 assembly language mutexes. */
+#undef HAVE_MUTEX_X86_GCC_ASSEMBLY
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+#undef HAVE_NDIR_H
+
+/* Define to 1 if you have the O_DIRECT flag. */
+#undef HAVE_O_DIRECT
+
+/* Define to 1 if you have the `pread' function. */
+#undef HAVE_PREAD
+
+/* Define to 1 if you have the `pstat_getdynamic' function. */
+#undef HAVE_PSTAT_GETDYNAMIC
+
+/* Define to 1 if you have the `pwrite' function. */
+#undef HAVE_PWRITE
+
+/* Define to 1 if building on QNX. */
+#undef HAVE_QNX
+
+/* Define to 1 if building Queue access method. */
+#undef HAVE_QUEUE
+
+/* Define to 1 if you have the `raise' function. */
+#undef HAVE_RAISE
+
+/* Define to 1 if you have the `rand' function. */
+#undef HAVE_RAND
+
+/* Define to 1 if building replication support. */
+#undef HAVE_REPLICATION
+
+/* Define to 1 if building RPC client/server. */
+#undef HAVE_RPC
+
+/* Define to 1 if you have the `sched_yield' function. */
+#undef HAVE_SCHED_YIELD
+
+/* Define to 1 if you have the `select' function. */
+#undef HAVE_SELECT
+
+/* Define to 1 if building sequence support. */
+#undef HAVE_SEQUENCE
+
+/* Define to 1 if you have the `shmget' function. */
+#undef HAVE_SHMGET
+
+/* Define to 1 if you have the `snprintf' function. */
+#undef HAVE_SNPRINTF
+
+/* Define to 1 if you have the `srand' function. */
+#undef HAVE_SRAND
+
+/* Define to 1 if building statistics support. */
+#undef HAVE_STATISTICS
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#undef HAVE_STRCASECMP
+
+/* Define to 1 if you have the `strdup' function. */
+#undef HAVE_STRDUP
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strtol' function. */
+#undef HAVE_STRTOL
+
+/* Define to 1 if you have the `strtoul' function. */
+#undef HAVE_STRTOUL
+
+/* Define to 1 if `st_blksize' is member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_BLKSIZE
+
+/* Define to 1 if you have the `sysconf' function. */
+#undef HAVE_SYSCONF
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+   */
+#undef HAVE_SYS_DIR_H
+
+/* Define to 1 if you have the <sys/fcntl.h> header file. */
+#undef HAVE_SYS_FCNTL_H
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+   */
+#undef HAVE_SYS_NDIR_H
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if unlink of file with open file descriptors will fail. */
+#undef HAVE_UNLINK_WITH_OPEN_FAILURE
+
+/* Define to 1 if the system has the type `unsigned long long'. */
+#undef HAVE_UNSIGNED_LONG_LONG
+
+/* Define to 1 if building access method verification support. */
+#undef HAVE_VERIFY
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#undef HAVE_VSNPRINTF
+
+/* Define to 1 if building VxWorks. */
+#undef HAVE_VXWORKS
+
+/* Define to 1 if you have the `yield' function. */
+#undef HAVE_YIELD
+
+/* Define to 1 if you have the `_fstati64' function. */
+#undef HAVE__FSTATI64
+
+/* Define to a value if using non-standard mutex alignment. */
+#undef MUTEX_ALIGN
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* The size of a `char', as computed by sizeof. */
+#undef SIZEOF_CHAR
+
+/* The size of a `char *', as computed by sizeof. */
+#undef SIZEOF_CHAR_P
+
+/* The size of a `int', as computed by sizeof. */
+#undef SIZEOF_INT
+
+/* The size of a `long', as computed by sizeof. */
+#undef SIZEOF_LONG
+
+/* The size of a `long long', as computed by sizeof. */
+#undef SIZEOF_LONG_LONG
+
+/* The size of a `short', as computed by sizeof. */
+#undef SIZEOF_SHORT
+
+/* The size of a `size_t', as computed by sizeof. */
+#undef SIZEOF_SIZE_T
+
+/* The size of a `unsigned char', as computed by sizeof. */
+#undef SIZEOF_UNSIGNED_CHAR
+
+/* The size of a `unsigned int', as computed by sizeof. */
+#undef SIZEOF_UNSIGNED_INT
+
+/* The size of a `unsigned long', as computed by sizeof. */
+#undef SIZEOF_UNSIGNED_LONG
+
+/* The size of a `unsigned long long', as computed by sizeof. */
+#undef SIZEOF_UNSIGNED_LONG_LONG
+
+/* The size of a `unsigned short', as computed by sizeof. */
+#undef SIZEOF_UNSIGNED_SHORT
+
+/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
+#undef STAT_MACROS_BROKEN
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Define to 1 to mask harmless uninitialized memory read/writes. */
+#undef UMRW
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/*
+ * Exit success/failure macros.
+ */
+#ifndef	HAVE_EXIT_SUCCESS
+#define	EXIT_FAILURE	1
+#define	EXIT_SUCCESS	0
+#endif
+
+/*
+ * Don't step on the namespace.  Other libraries may have their own
+ * implementations of these functions, we don't want to use their
+ * implementations or force them to use ours based on the load order.
+ */
+#ifndef	HAVE_GETCWD
+#define	getcwd		__db_Cgetcwd
+#endif
+#ifndef	HAVE_MEMCMP
+#define	memcmp		__db_Cmemcmp
+#endif
+#ifndef	HAVE_MEMCPY
+#define	memcpy		__db_Cmemcpy
+#endif
+#ifndef	HAVE_MEMMOVE
+#define	memmove		__db_Cmemmove
+#endif
+#ifndef	HAVE_RAISE
+#define	raise		__db_Craise
+#endif
+#ifndef	HAVE_SNPRINTF
+#define	snprintf	__db_Csnprintf
+#endif
+#ifndef	HAVE_STRCASECMP
+#define	strcasecmp	__db_Cstrcasecmp
+#define	strncasecmp	__db_Cstrncasecmp
+#endif
+#ifndef	HAVE_STRERROR
+#define	strerror	__db_Cstrerror
+#endif
+#ifndef	HAVE_VSNPRINTF
+#define	vsnprintf	__db_Cvsnprintf
+#endif
+
+#ifdef DB_WIN32
+#include "win_db.h"
+#endif
diff --git a/storage/bdb/dist/config.sub b/storage/bdb/dist/config.sub
index 9ff085efaf7fcd45cacc11aff70bc30fef9099b7..edb6b663ca2b30ff0dd886e09137ebb59b6e4568 100755
--- a/storage/bdb/dist/config.sub
+++ b/storage/bdb/dist/config.sub
@@ -1,9 +1,9 @@
 #! /bin/sh
 # Configuration validation subroutine script.
 #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002 Free Software Foundation, Inc.
+#   2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
-timestamp='2002-07-03'
+timestamp='2004-08-29'
 
 # This file is (in principle) common to ALL GNU software.
 # The presence of a machine in this file suggests that SOME GNU software
@@ -70,7 +70,7 @@ Report bugs and patches to <config-patches@gnu.org>."
 version="\
 GNU config.sub ($timestamp)
 
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
@@ -118,7 +118,8 @@ esac
 # Here we must recognize all the valid KERNEL-OS combinations.
 maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
 case $maybe_os in
-  nto-qnx* | linux-gnu* | freebsd*-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*)
+  nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
+  kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
     os=-$maybe_os
     basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
     ;;
@@ -144,7 +145,7 @@ case $os in
 	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
 	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
 	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-	-apple | -axis)
+	-apple | -axis | -knuth | -cray)
 		os=
 		basic_machine=$1
 		;;
@@ -228,36 +229,42 @@ case $basic_machine in
 	| a29k \
 	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
 	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+	| am33_2.0 \
 	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
 	| c4x | clipper \
 	| d10v | d30v | dlx | dsp16xx \
 	| fr30 | frv \
 	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
 	| i370 | i860 | i960 | ia64 \
-	| ip2k \
-	| m32r | m68000 | m68k | m88k | mcore \
+	| ip2k | iq2000 \
+	| m32r | m32rle | m68000 | m68k | m88k | mcore \
 	| mips | mipsbe | mipseb | mipsel | mipsle \
 	| mips16 \
 	| mips64 | mips64el \
+	| mips64vr | mips64vrel \
 	| mips64orion | mips64orionel \
 	| mips64vr4100 | mips64vr4100el \
 	| mips64vr4300 | mips64vr4300el \
 	| mips64vr5000 | mips64vr5000el \
 	| mipsisa32 | mipsisa32el \
+	| mipsisa32r2 | mipsisa32r2el \
 	| mipsisa64 | mipsisa64el \
+	| mipsisa64r2 | mipsisa64r2el \
 	| mipsisa64sb1 | mipsisa64sb1el \
+	| mipsisa64sr71k | mipsisa64sr71kel \
 	| mipstx39 | mipstx39el \
 	| mn10200 | mn10300 \
+	| msp430 \
 	| ns16k | ns32k \
 	| openrisc | or32 \
 	| pdp10 | pdp11 | pj | pjl \
 	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
 	| pyramid \
-	| sh | sh[1234] | sh3e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+	| sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
 	| sh64 | sh64le \
-	| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
+	| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv8 | sparcv9 | sparcv9b \
 	| strongarm \
-	| tahoe | thumb | tic80 | tron \
+	| tahoe | thumb | tic4x | tic80 | tron \
 	| v850 | v850e \
 	| we32k \
 	| x86 | xscale | xstormy16 | xtensa \
@@ -292,40 +299,48 @@ case $basic_machine in
 	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
 	| avr-* \
 	| bs2000-* \
-	| c[123]* | c30-* | [cjt]90-* | c54x-* \
-	| clipper-* | cydra-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+	| clipper-* | craynv-* | cydra-* \
 	| d10v-* | d30v-* | dlx-* \
 	| elxsi-* \
 	| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
 	| h8300-* | h8500-* \
 	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
 	| i*86-* | i860-* | i960-* | ia64-* \
-	| ip2k-* \
-	| m32r-* \
+	| ip2k-* | iq2000-* \
+	| m32r-* | m32rle-* \
 	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
 	| m88110-* | m88k-* | mcore-* \
 	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
 	| mips16-* \
 	| mips64-* | mips64el-* \
+	| mips64vr-* | mips64vrel-* \
 	| mips64orion-* | mips64orionel-* \
 	| mips64vr4100-* | mips64vr4100el-* \
 	| mips64vr4300-* | mips64vr4300el-* \
 	| mips64vr5000-* | mips64vr5000el-* \
 	| mipsisa32-* | mipsisa32el-* \
+	| mipsisa32r2-* | mipsisa32r2el-* \
 	| mipsisa64-* | mipsisa64el-* \
+	| mipsisa64r2-* | mipsisa64r2el-* \
 	| mipsisa64sb1-* | mipsisa64sb1el-* \
-	| mipstx39 | mipstx39el \
+	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+	| mipstx39-* | mipstx39el-* \
+	| mmix-* \
+	| msp430-* \
 	| none-* | np1-* | ns16k-* | ns32k-* \
 	| orion-* \
 	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
 	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
 	| pyramid-* \
 	| romp-* | rs6000-* \
-	| sh-* | sh[1234]-* | sh3e-* | sh[34]eb-* | shbe-* \
+	| sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
 	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
 	| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
-	| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
-	| tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \
+	| sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+	| tahoe-* | thumb-* \
+	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+	| tron-* \
 	| v850-* | v850e-* | vax-* \
 	| we32k-* \
 	| x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
@@ -349,6 +364,9 @@ case $basic_machine in
 		basic_machine=a29k-amd
 		os=-udi
 		;;
+    	abacus)
+		basic_machine=abacus-unknown
+		;;
 	adobe68k)
 		basic_machine=m68010-adobe
 		os=-scout
@@ -363,6 +381,12 @@ case $basic_machine in
 		basic_machine=a29k-none
 		os=-bsd
 		;;
+	amd64)
+		basic_machine=x86_64-pc
+		;;
+	amd64-*)
+		basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
 	amdahl)
 		basic_machine=580-amdahl
 		os=-sysv
@@ -422,12 +446,27 @@ case $basic_machine in
 		basic_machine=j90-cray
 		os=-unicos
 		;;
+	craynv)
+		basic_machine=craynv-cray
+		os=-unicosmp
+		;;
+	cr16c)
+		basic_machine=cr16c-unknown
+		os=-elf
+		;;
 	crds | unos)
 		basic_machine=m68k-crds
 		;;
+	crisv32 | crisv32-* | etraxfs*)
+		basic_machine=crisv32-axis
+		;;
 	cris | cris-* | etrax*)
 		basic_machine=cris-axis
 		;;
+	crx)
+		basic_machine=crx-unknown
+		os=-elf
+		;;
 	da30 | da30-*)
 		basic_machine=m68k-da30
 		;;
@@ -628,10 +667,6 @@ case $basic_machine in
 	mips3*)
 		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
 		;;
-	mmix*)
-		basic_machine=mmix-knuth
-		os=-mmixware
-		;;
 	monitor)
 		basic_machine=m68k-rom68k
 		os=-coff
@@ -723,6 +758,10 @@ case $basic_machine in
 		basic_machine=or32-unknown
 		os=-coff
 		;;
+	os400)
+		basic_machine=powerpc-ibm
+		os=-os400
+		;;
 	OSE68000 | ose68000)
 		basic_machine=m68000-ericsson
 		os=-ose
@@ -745,49 +784,55 @@ case $basic_machine in
 	pbb)
 		basic_machine=m68k-tti
 		;;
-        pc532 | pc532-*)
+	pc532 | pc532-*)
 		basic_machine=ns32k-pc532
 		;;
 	pentium | p5 | k5 | k6 | nexgen | viac3)
 		basic_machine=i586-pc
 		;;
-	pentiumpro | p6 | 6x86 | athlon)
+	pentiumpro | p6 | 6x86 | athlon | athlon_*)
 		basic_machine=i686-pc
 		;;
-	pentiumii | pentium2)
+	pentiumii | pentium2 | pentiumiii | pentium3)
 		basic_machine=i686-pc
 		;;
+	pentium4)
+		basic_machine=i786-pc
+		;;
 	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
 		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
 		;;
 	pentiumpro-* | p6-* | 6x86-* | athlon-*)
 		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
 		;;
-	pentiumii-* | pentium2-*)
+	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
 		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
 		;;
+	pentium4-*)
+		basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
 	pn)
 		basic_machine=pn-gould
 		;;
 	power)	basic_machine=power-ibm
 		;;
 	ppc)	basic_machine=powerpc-unknown
-	        ;;
+		;;
 	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
 		;;
 	ppcle | powerpclittle | ppc-le | powerpc-little)
 		basic_machine=powerpcle-unknown
-	        ;;
+		;;
 	ppcle-* | powerpclittle-*)
 		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
 		;;
 	ppc64)	basic_machine=powerpc64-unknown
-	        ;;
+		;;
 	ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
 		;;
 	ppc64le | powerpc64little | ppc64-le | powerpc64-little)
 		basic_machine=powerpc64le-unknown
-	        ;;
+		;;
 	ppc64le-* | powerpc64little-*)
 		basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
 		;;
@@ -818,6 +863,16 @@ case $basic_machine in
 		basic_machine=a29k-amd
 		os=-udi
 		;;
+	sb1)
+		basic_machine=mipsisa64sb1-unknown
+		;;
+	sb1el)
+		basic_machine=mipsisa64sb1el-unknown
+		;;
+	sei)
+		basic_machine=mips-sei
+		os=-seiux
+		;;
 	sequent)
 		basic_machine=i386-sequent
 		;;
@@ -825,6 +880,9 @@ case $basic_machine in
 		basic_machine=sh-hitachi
 		os=-hms
 		;;
+	sh64)
+		basic_machine=sh64-unknown
+		;;
 	sparclite-wrs | simso-wrs)
 		basic_machine=sparclite-wrs
 		os=-vxworks
@@ -883,7 +941,7 @@ case $basic_machine in
 	sun386 | sun386i | roadrunner)
 		basic_machine=i386-sun
 		;;
-        sv1)
+	sv1)
 		basic_machine=sv1-cray
 		os=-unicos
 		;;
@@ -891,10 +949,6 @@ case $basic_machine in
 		basic_machine=i386-sequent
 		os=-dynix
 		;;
-	t3d)
-		basic_machine=alpha-cray
-		os=-unicos
-		;;
 	t3e)
 		basic_machine=alphaev5-cray
 		os=-unicos
@@ -907,6 +961,14 @@ case $basic_machine in
 		basic_machine=tic54x-unknown
 		os=-coff
 		;;
+	tic55x | c55x*)
+		basic_machine=tic55x-unknown
+		os=-coff
+		;;
+	tic6x | c6x*)
+		basic_machine=tic6x-unknown
+		os=-coff
+		;;
 	tx39)
 		basic_machine=mipstx39-unknown
 		;;
@@ -920,6 +982,10 @@ case $basic_machine in
 	tower | tower-32)
 		basic_machine=m68k-ncr
 		;;
+	tpf)
+		basic_machine=s390x-ibm
+		os=-tpf
+		;;
 	udi29k)
 		basic_machine=a29k-amd
 		os=-udi
@@ -941,8 +1007,8 @@ case $basic_machine in
 		os=-vms
 		;;
 	vpp*|vx|vx-*)
-               basic_machine=f301-fujitsu
-               ;;
+		basic_machine=f301-fujitsu
+		;;
 	vxworks960)
 		basic_machine=i960-wrs
 		os=-vxworks
@@ -963,11 +1029,7 @@ case $basic_machine in
 		basic_machine=hppa1.1-winbond
 		os=-proelf
 		;;
-	windows32)
-		basic_machine=i386-pc
-		os=-windows32-msvcrt
-		;;
-        xps | xps100)
+	xps | xps100)
 		basic_machine=xps100-honeywell
 		;;
 	ymp)
@@ -997,6 +1059,9 @@ case $basic_machine in
 	romp)
 		basic_machine=romp-ibm
 		;;
+	mmix)
+		basic_machine=mmix-knuth
+		;;
 	rs6000)
 		basic_machine=rs6000-ibm
 		;;
@@ -1013,16 +1078,16 @@ case $basic_machine in
 	we32k)
 		basic_machine=we32k-att
 		;;
-	sh3 | sh4 | sh3eb | sh4eb | sh[1234]le | sh3ele)
+	sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
 		basic_machine=sh-unknown
 		;;
 	sh64)
 		basic_machine=sh64-unknown
 		;;
-	sparc | sparcv9 | sparcv9b)
+	sparc | sparcv8 | sparcv9 | sparcv9b)
 		basic_machine=sparc-sun
 		;;
-        cydra)
+	cydra)
 		basic_machine=cydra-cydrome
 		;;
 	orion)
@@ -1037,10 +1102,6 @@ case $basic_machine in
 	pmac | pmac-mpw)
 		basic_machine=powerpc-apple
 		;;
-	c4x*)
-		basic_machine=c4x-none
-		os=-coff
-		;;
 	*-unknown)
 		# Make sure to match an already-canonicalized machine name.
 		;;
@@ -1096,18 +1157,20 @@ case $os in
 	      | -aos* \
 	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
 	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
-	      | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
-	      | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
+	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
 	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
 	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
 	      | -chorusos* | -chorusrdb* \
 	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
-	      | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
-	      | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
+	      | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
 	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
 	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
 	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
-	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* | -powermax*)
+	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly*)
 	# Remember, each alternative MUST END IN *, to match a version number.
 		;;
 	-qnx*)
@@ -1119,8 +1182,10 @@ case $os in
 			;;
 		esac
 		;;
+	-nto-qnx*)
+		;;
 	-nto*)
-		os=-nto-qnx
+		os=`echo $os | sed -e 's|nto|nto-qnx|'`
 		;;
 	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
 	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
@@ -1129,6 +1194,9 @@ case $os in
 	-mac*)
 		os=`echo $os | sed -e 's|mac|macos|'`
 		;;
+	-linux-dietlibc)
+		os=-linux-dietlibc
+		;;
 	-linux*)
 		os=`echo $os | sed -e 's|linux|linux-gnu|'`
 		;;
@@ -1141,6 +1209,9 @@ case $os in
 	-opened*)
 		os=-openedition
 		;;
+        -os400*)
+		os=-os400
+		;;
 	-wince*)
 		os=-wince
 		;;
@@ -1162,6 +1233,9 @@ case $os in
 	-atheos*)
 		os=-atheos
 		;;
+	-syllable*)
+		os=-syllable
+		;;
 	-386bsd)
 		os=-bsd
 		;;
@@ -1172,7 +1246,7 @@ case $os in
 		os=-rtmk-nova
 		;;
 	-ns2 )
-	        os=-nextstep2
+		os=-nextstep2
 		;;
 	-nsk*)
 		os=-nsk
@@ -1184,6 +1258,9 @@ case $os in
 	-sinix*)
 		os=-sysv4
 		;;
+        -tpf*)
+		os=-tpf
+		;;
 	-triton*)
 		os=-sysv3
 		;;
@@ -1211,8 +1288,14 @@ case $os in
 	-xenix)
 		os=-xenix
 		;;
-        -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
-	        os=-mint
+	-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+		os=-mint
+		;;
+	-aros*)
+		os=-aros
+		;;
+	-kaos*)
+		os=-kaos
 		;;
 	-none)
 		;;
@@ -1245,11 +1328,14 @@ case $basic_machine in
 	arm*-semi)
 		os=-aout
 		;;
+    c4x-* | tic4x-*)
+        os=-coff
+        ;;
 	# This must come before the *-dec entry.
 	pdp10-*)
 		os=-tops20
 		;;
-        pdp11-*)
+	pdp11-*)
 		os=-none
 		;;
 	*-dec | vax-*)
@@ -1291,6 +1377,9 @@ case $basic_machine in
 	*-ibm)
 		os=-aix
 		;;
+    	*-knuth)
+		os=-mmixware
+		;;
 	*-wec)
 		os=-proelf
 		;;
@@ -1342,19 +1431,19 @@ case $basic_machine in
 	*-next)
 		os=-nextstep3
 		;;
-        *-gould)
+	*-gould)
 		os=-sysv
 		;;
-        *-highlevel)
+	*-highlevel)
 		os=-bsd
 		;;
 	*-encore)
 		os=-bsd
 		;;
-        *-sgi)
+	*-sgi)
 		os=-irix
 		;;
-        *-siemens)
+	*-siemens)
 		os=-sysv4
 		;;
 	*-masscomp)
@@ -1423,9 +1512,15 @@ case $basic_machine in
 			-mvs* | -opened*)
 				vendor=ibm
 				;;
+			-os400*)
+				vendor=ibm
+				;;
 			-ptx*)
 				vendor=sequent
 				;;
+			-tpf*)
+				vendor=ibm
+				;;
 			-vxsim* | -vxworks* | -windiss*)
 				vendor=wrs
 				;;
diff --git a/storage/bdb/dist/configure.ac b/storage/bdb/dist/configure.ac
index 0bf53972f54a14fbc517b3733fd3bbc484107534..8106d51d0ca5ff3caf564898abdbf99b0eedeff4 100644
--- a/storage/bdb/dist/configure.ac
+++ b/storage/bdb/dist/configure.ac
@@ -1,25 +1,25 @@
-# $Id: configure.ac,v 11.156 2002/09/04 13:51:17 bostic Exp $
+# $Id: configure.ac,v 11.221 2004/11/16 01:07:57 mjc Exp $
 # Process this file with autoconf to produce a configure script.
 
 PACKAGE=db
 AC_INIT(Berkeley DB,
 	__EDIT_DB_VERSION__, support@sleepycat.com, db-__EDIT_DB_VERSION__)
 AC_CONFIG_SRCDIR([../db/db.c])
-AC_CONFIG_HEADER(db_config.h:config.hin)
+AC_CONFIG_HEADERS([db_config.h:config.hin])
 
 # Configure setup.
 AC_CANONICAL_HOST()
 AC_ARG_PROGRAM()
 
-# We cannot build in the top-level directory.
-AC_MSG_CHECKING(if building in the top-level directory)
-[ test -d db_archive ] && AC_MSG_ERROR([
-Berkeley DB cannot be built in the top-level distribution directory.])
+# Don't build in the top-level or dist directories.
+AC_MSG_CHECKING(if building in the top-level or dist directories)
+if [ test -d db_archive -o -f configure.ac ] ; then
+	AC_MSG_RESULT(yes)
+	AC_MSG_ERROR(
+    [Berkeley DB should not be built in the top-level or dist directories.])
+fi
 AC_MSG_RESULT(no)
 
-# Minimum autoconf version required.
-AC_PREREQ(2.53)
-
 # Substitution variables.
 AC_SUBST(ADDITIONAL_INCS)
 AC_SUBST(ADDITIONAL_LANG)
@@ -30,13 +30,13 @@ AC_SUBST(CFLAGS)
 AC_SUBST(CONFIGURATION_ARGS)
 AC_SUBST(CONFIGURATION_PATH)
 AC_SUBST(CPPFLAGS)
+AC_SUBST(CRYPTO_OBJS)
 AC_SUBST(CXX)
 AC_SUBST(CXXFLAGS)
+AC_SUBST(DB_PROTO1)
+AC_SUBST(DB_PROTO2)
 AC_SUBST(DEFAULT_LIB)
 AC_SUBST(DEFAULT_LIB_CXX)
-AC_SUBST(EMBEDIX_ECD_CXX)
-AC_SUBST(EMBEDIX_ECD_RPC)
-AC_SUBST(EMBEDIX_ROOT)
 AC_SUBST(INSTALLER)
 AC_SUBST(INSTALL_LIBS)
 AC_SUBST(INSTALL_TARGET)
@@ -48,63 +48,66 @@ AC_SUBST(LIBS)
 AC_SUBST(LIBSO_LIBS)
 AC_SUBST(LIBTOOL)
 AC_SUBST(LIBTSO_LIBS)
+AC_SUBST(LIBTSO_MODSUFFIX)
+AC_SUBST(LIBTSO_MODULE)
 AC_SUBST(LIBXSO_LIBS)
-AC_SUBST(LOAD_LIBS)
 AC_SUBST(MAKEFILE_CC)
 AC_SUBST(MAKEFILE_CCLINK)
 AC_SUBST(MAKEFILE_CXX)
 AC_SUBST(MAKEFILE_CXXLINK)
 AC_SUBST(MAKEFILE_SOLINK)
 AC_SUBST(MAKEFILE_XSOLINK)
+AC_SUBST(OSDIR)
+AC_SUBST(PATH_SEPARATOR)
 AC_SUBST(POSTLINK)
+AC_SUBST(REPLACEMENT_OBJS)
 AC_SUBST(RPC_CLIENT_OBJS)
-AC_SUBST(RPM_POST_INSTALL)
-AC_SUBST(RPM_POST_UNINSTALL)
+AC_SUBST(RPC_SERVER_H)
 AC_SUBST(SOFLAGS)
-AC_SUBST(db_cv_path_embedix_install)
-AC_SUBST(db_cv_path_rpm_archive)
+AC_SUBST(TEST_LIBS)
 AC_SUBST(db_int_def)
 AC_SUBST(o)
 
-# RPM needs the current absolute path.
-# RPM needs the list of original arguments, but we don't include the RPM
-# option itself.
-CONFIGURATION_PATH=${PWD-`pwd`}
-CONFIGURATION_ARGS=`echo "$*" |
-    sed -e 's/--with-embedix[[^ ]]*//' -e 's/--with-rpm[[^ ]]*//'`
-
-# Set the version.
-AM_VERSION_SET
-
 # Set the default installation location.
-AC_PREFIX_DEFAULT(/usr/local/BerkeleyDB.@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@)
+AC_PREFIX_DEFAULT(/usr/local/BerkeleyDB.__EDIT_DB_VERSION_MAJOR__.__EDIT_DB_VERSION_MINOR__)
+
+# Configure the version information.
+AC_SUBST(DB_VERSION_MAJOR)
+DB_VERSION_MAJOR="__EDIT_DB_VERSION_MAJOR__"
+AC_SUBST(DB_VERSION_MINOR)
+DB_VERSION_MINOR="__EDIT_DB_VERSION_MINOR__"
+AC_SUBST(DB_VERSION_PATCH)
+DB_VERSION_PATCH="__EDIT_DB_VERSION_PATCH__"
+AC_SUBST(DB_VERSION_STRING)
+DB_VERSION_STRING='"__EDIT_DB_VERSION_STRING__"'
+AC_SUBST(DB_VERSION_UNIQUE_NAME)
 
 # Process all options before using them.
 AM_OPTIONS_SET
 
 # Set some #defines based on configuration options.
-if test "$db_cv_diagnostic" = yes; then
+if test "$db_cv_diagnostic" = "yes"; then
 	AC_DEFINE(DIAGNOSTIC)
 	AH_TEMPLATE(DIAGNOSTIC,
     [Define to 1 if you want a version with run-time diagnostic checking.])
 fi
-if test "$db_cv_debug_rop" = yes; then
+if test "$db_cv_debug_rop" = "yes"; then
 	AC_DEFINE(DEBUG_ROP)
 	AH_TEMPLATE(DEBUG_ROP,
     [Define to 1 if you want a version that logs read operations.])
 fi
-if test "$db_cv_debug_wop" = yes; then
+if test "$db_cv_debug_wop" = "yes"; then
 	AC_DEFINE(DEBUG_WOP)
 	AH_TEMPLATE(DEBUG_WOP,
     [Define to 1 if you want a version that logs write operations.])
 fi
-if test "$db_cv_umrw" = yes; then
+if test "$db_cv_umrw" = "yes"; then
 	AC_DEFINE(UMRW)
 	AH_TEMPLATE(UMRW,
-    [Define to 1 to mask harmless unitialized memory read/writes.])
+    [Define to 1 to mask harmless uninitialized memory read/writes.])
 
 fi
-if test "$db_cv_test" = yes; then
+if test "$db_cv_test" = "yes"; then
 	AC_DEFINE(CONFIG_TEST)
 	AH_TEMPLATE(CONFIG_TEST,
     [Define to 1 if you want to build a version for running the test suite.])
@@ -114,27 +117,12 @@ fi
 AM_PROGRAMS_SET
 AC_PROG_INSTALL
 
-# RPM/Embedix support: change the standard make and install targets
-if test "$db_cv_rpm" = "yes"; then
-	BUILD_TARGET="rpm_build"
-	echo "topdir: $CONFIGURATION_PATH" > rpmrc
-	if test "$db_cv_embedix" = "yes"; then
-		EMBEDIX_ROOT="/usr"
-		INSTALL_TARGET="embedix_install"
-	else
-		INSTALL_TARGET="rpm_install"
-	fi
-else
-	BUILD_TARGET="library_build"
-	INSTALL_TARGET="library_install"
-fi
+BUILD_TARGET="library_build"
+INSTALL_TARGET="library_install"
 
 # This is where we handle stuff that autoconf can't handle: compiler,
 # preprocessor and load flags, libraries that the standard tests don't
-# look for.  The default optimization is -O.  We would like to set the
-# default optimization for systems using gcc to -O2, but we can't.  By
-# the time we know we're using gcc, it's too late to set optimization
-# flags.
+# look for.
 #
 # There are additional libraries we need for some compiler/architecture
 # combinations.
@@ -145,7 +133,6 @@ fi
 # The makefile CC may be different than the CC used in config testing,
 # because the makefile CC may be set to use $(LIBTOOL).
 #
-# XXX
 # Don't override anything if it's already set from the environment.
 optimize_def="-O"
 case "$host_os" in
@@ -154,25 +141,22 @@ aix4.3.*|aix5*)
 	CC=${CC-"xlc_r"}
 	CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE"
 	LDFLAGS="$LDFLAGS -Wl,-brtl";;
-bsdi3*)	optimize_def="-O2"
-	CC=${CC-"shlicc2"}
+bsdi3*)	CC=${CC-"shlicc2"}
 	LIBS="$LIBS -lipc";;
-bsdi*)	optimize_def="-O2";;
+cygwin*)
+	CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE -D_REENTRANT";;
 freebsd*)
-	optimize_def="-O2"
 	CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE"
-	#LDFLAGS="$LDFLAGS -pthread"
-        ;;
+	LDFLAGS="$LDFLAGS -pthread";;
+gnu*|k*bsd*-gnu|linux*)
+	CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE -D_REENTRANT";;
 hpux*)	CPPFLAGS="$CPPFLAGS -D_REENTRANT";;
 irix*)	optimize_def="-O2"
 	CPPFLAGS="$CPPFLAGS -D_SGI_MP_SOURCE";;
-linux*)	optimize_def="-O2"
-	CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE -D_REENTRANT";;
 mpeix*)	CPPFLAGS="$CPPFLAGS -D_POSIX_SOURCE -D_SOCKET_SOURCE"
 	LIBS="$LIBS -lsocket -lsvipc";;
-osf*)	CPPFLAGS="$CPPFLAGS -D_REENTRANT"
-	LDFLAGS="$LDFLAGS -pthread";;
-*qnx)	AC_DEFINE(HAVE_QNX)
+osf*)	CPPFLAGS="$CPPFLAGS -pthread";;
+*qnx*)	AC_DEFINE(HAVE_QNX)
 	AH_TEMPLATE(HAVE_QNX, [Define to 1 if building on QNX.]);;
 solaris*)
 	CPPFLAGS="$CPPFLAGS -D_REENTRANT";;
@@ -189,19 +173,52 @@ CXXFLAGS=${CXXFLAGS-"$CFLAGS"}
 # XXX
 # Some compilers can't mix optimizing and debug flags.  The only way to
 # handle this is to specify CFLAGS in the environment before configuring.
-if test "$db_cv_debug" = yes; then
+if test "$db_cv_debug" = "yes"; then
 	AC_DEFINE(DEBUG)
 	AH_TEMPLATE(DEBUG, [Define to 1 if you want a debugging version.])
 
 	CFLAGS="$CFLAGS -g"
 	CXXFLAGS="$CXXFLAGS -g"
+	db_cv_build_type=debug
+else
+	db_cv_build_type=release
 fi
+AC_SUBST(db_cv_build_type)
 
 # The default compiler is cc (NOT gcc), the default CFLAGS is as specified
 # above, NOT what is set by AC_PROG_CC, as it won't set optimization flags
 # for any compiler other than gcc.
 AC_PROG_CC(cc gcc)
 
+# Set specific per-compiler flags.
+if test "$GCC" = "yes"; then
+	# We want -O2 if we're using gcc.
+	CFLAGS="$CFLAGS "
+	CFLAGS=`echo "$CFLAGS" | sed 's/-O /-O2 /g'`
+else
+	case "$host_os" in
+	hpux11.0*)	;;
+	hpux11*)	CPPFLAGS="$CPPFLAGS -mt";;
+	esac
+fi
+
+# Checks for compiler characteristics.
+DB_PROTO1="#undef __P"
+
+# AC_PROG_CC_STDC only sets ac_cv_prog_cc_stdc if the test fails, so
+# check for "no", not "yes".
+if test "$ac_cv_prog_cc_stdc" = "no"; then
+	DB_PROTO2="#define	__P(protos)	()"
+else
+	DB_PROTO2="#define	__P(protos)	protos"
+fi
+
+AC_C_CONST
+AC_SUBST(DB_CONST)
+if test "$ac_cv_c_const" != "yes"; then
+	DB_CONST="#define const"
+fi
+
 # Because of shared library building, the ${CC} used for config tests
 # may be different than the ${CC} we want to put in the Makefile.
 # The latter is known as ${MAKEFILE_CC} in this script.
@@ -230,6 +247,9 @@ if test "$db_cv_cxx" = "yes"; then
 		esac
 	fi
 	AC_PROG_CXX
+	###### WORKAROUND: SEE SR #7938
+	AC_PROG_CXXCPP
+	###############################
 	AC_CXX_HAVE_STDHEADERS
 	MAKEFILE_CXX="${CXX}"
 	MAKEFILE_CXXLINK="${CXX}"
@@ -260,8 +280,8 @@ CCC=CXX
 # Libtool configuration.
 AC_PROG_LIBTOOL
 
-LIBTOOL="\$(SHELL) ./libtool"
 SOFLAGS="-rpath \$(libdir)"
+LIBTOOL_PROG="${SHELL} ./libtool"
 
 # Set SOSUFFIX and friends
 SOSUFFIX_CONFIG
@@ -277,53 +297,70 @@ MAKEFILE_CXX="\$(LIBTOOL) --mode=compile ${MAKEFILE_CXX}"
 MAKEFILE_XSOLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CXXLINK} -avoid-version"
 MAKEFILE_CXXLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CXXLINK}"
 
+LIBTOOL="\$(SHELL) ./libtool"
+
+case "$host_os" in
+cygwin* | mingw*)
+	MAKEFILE_SOLINK="$MAKEFILE_SOLINK -no-undefined"
+	MAKEFILE_XSOLINK="$MAKEFILE_XSOLINK -no-undefined";;
+esac
+
 # Configure for shared libraries, static libraries, or both.  If both are
 # configured, build the utilities and example programs with shared versions.
 #
 # $o is set to ".o" or ".lo", and is the file suffix used in the Makefile
 # instead of .o
+if test `$LIBTOOL_PROG --config |
+    grep build_libtool_libs | grep no` 2>/dev/null; then
+	enable_shared="no"
+else
+	enable_shared="yes"
+fi
+if test `$LIBTOOL_PROG --config |
+    grep build_old_libs | grep no` 2>/dev/null; then
+	enable_static="no"
+else
+	enable_static="yes"
+fi
+
+case "$host_os" in
+    darwin*)
+        LIBTSO_MODULE=""
+        LIBTSO_MODSUFFIX=".dylib"
+    ;;
+    *)
+        LIBTSO_MODULE="-module"
+        LIBTSO_MODSUFFIX=@MODSUFFIX@
+    ;;
+esac
+
+# C API.
 if test "$enable_shared" = "no"; then
-	DEFAULT_LIB="\$(libdb)"
-	POSTLINK="@true"
+	DEFAULT_LIB="\$(libdb_version)"
+	POSTLINK=": "
 	o=".o"
-fi
-if test "$enable_shared" = "yes"; then
+else
 	DEFAULT_LIB="\$(libso_target)"
 	POSTLINK="\$(LIBTOOL) --mode=execute true"
 	o=".lo"
 fi
 INSTALL_LIBS="$DEFAULT_LIB"
+if test "$enable_static" = "yes"; then
+	INSTALL_LIBS="$INSTALL_LIBS \$(libdb)"
+fi
 
 # Optional C++ API.
 if test "$db_cv_cxx" = "yes"; then
 	if test "$enable_shared" = "no"; then
-		DEFAULT_LIB_CXX="\$(libcxx)"
+		DEFAULT_LIB_CXX="\$(libcxx_version)"
 	fi
 	if test "$enable_shared" = "yes"; then
 		DEFAULT_LIB_CXX="\$(libxso_target)"
 	fi
 	INSTALL_LIBS="$INSTALL_LIBS $DEFAULT_LIB_CXX"
-
-	# Fill in C++ library for Embedix.
-	EMBEDIX_ECD_CXX='<OPTION db-extra>\
-	TYPE=bool\
-	DEFAULT_VALUE=1\
-	PROMPT=Include BerkeleyDB C++ library?\
-	<KEEPLIST>\
-		/usr/include/db_cxx.h\
-		/usr/lib/libdb_cxx-@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.so\
-	</KEEPLIST>\
-	<PROVIDES>\
-		libdb_cxx-@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.so\
-	</PROVIDES>\
-	<REQUIRES>\
-		ld-linux.so.2\
-		libc.so.6\
-	</REQUIRES>\
-	STATIC_SIZE=0\
-	STORAGE_SIZE=523612\
-	STARTUP_TIME=0\
-	</OPTION>'
+	if test "$enable_static" = "yes"; then
+		INSTALL_LIBS="$INSTALL_LIBS \$(libcxx)"
+	fi
 fi
 
 # Optional Java API.
@@ -333,9 +370,28 @@ if test "$db_cv_java" = "yes"; then
 		AC_MSG_ERROR([Java requires shared libraries])
 	fi
 
+        # A classpath that includes . is needed to check for Java
+	CLASSPATH=".:$CLASSPATH"
+	export CLASSPATH
 	AC_PROG_JAVAC
 	AC_PROG_JAR
-        AC_JNI_INCLUDE_DIR
+	AC_PROG_JAVA
+	AC_JNI_INCLUDE_DIR
+
+	AC_MSG_CHECKING(java version)
+        case "$JAVA" in
+	*kaffe* )
+		JAVA_VERSION=`$JAVA -version 2>&1 |
+			sed -e '/Java Version:/!d' -e 's/.*Java Version: \([[^ 	]]*\)[[ 	]]*/\1/'` ;;
+	* )	JAVA_VERSION=`$JAVA -version 2>&1 |
+        	       	sed -e '/ version /!d' -e 's/.*"\(.*\)".*/\1/'` ;;
+	esac
+	AC_MSG_RESULT($JAVA_VERSION)
+	case "$JAVA_VERSION" in
+	1.[[3456789]]* | 1.[[1-9]][[0-9]]* | [[23456789]]* ) ;;
+	* )
+		AC_MSG_ERROR([Java version 1.3 or higher required, got $JAVA_VERSION]) ;;
+	esac
 
 	for JNI_INCLUDE_DIR in $JNI_INCLUDE_DIRS
 	do
@@ -348,88 +404,69 @@ else
 	JAVAC=nojavac
 fi
 
-# Optional RPC client/server.
-if test "$db_cv_rpc" = "yes"; then
-	AC_DEFINE(HAVE_RPC)
-	AH_TEMPLATE(HAVE_RPC, [Define to 1 if building RPC client/server.])
-
-	RPC_CLIENT_OBJS="\$(RPC_CLIENT_OBJS)"
-	ADDITIONAL_PROGS="berkeley_db_svc $ADDITIONAL_PROGS"
-	
-	EMBEDIX_ECD_RPC="/usr/bin/berkeley_db_svc"
-
-	case "$host_os" in
-	hpux*)
-		AC_CHECK_FUNC(svc_run,,
-		    AC_CHECK_LIB(nsl, svc_run,
-		    LIBS="-lnsl $LIBS"; LIBTSO_LIBS="-lnsl $LIBTSO_LIBS"));;
-	solaris*)
-		AC_CHECK_FUNC(svc_run,, AC_CHECK_LIB(nsl, svc_run));;
-	esac
-fi
-
-AM_TCL_LOAD
-
-# Optional crypto support.
-if test -d "$srcdir/../crypto"; then
-	AC_DEFINE(HAVE_CRYPTO)
-	AH_TEMPLATE(HAVE_CRYPTO,
-    [Define to 1 if Berkeley DB release includes strong cryptography.])
-	ADDITIONAL_OBJS="aes_method${o} crypto${o} mt19937db${o} rijndael-alg-fst${o} rijndael-api-fst${o} $ADDITIONAL_OBJS"
-fi
-
-# Optional DB 1.85 compatibility API.
-if test "$db_cv_compat185" = "yes"; then
-	ADDITIONAL_INCS="db_185.h $ADDITIONAL_INCS"
-	ADDITIONAL_OBJS="db185${o} $ADDITIONAL_OBJS"
-fi
+# MinGW support.
+if test "$db_cv_mingw" = "yes"; then
+	OSDIR=os_win32
+	PATH_SEPARATOR="\\\\/:"
 
-# Optional utilities.
-if test "$db_cv_dump185" = "yes"; then
-	ADDITIONAL_PROGS="db_dump185 $ADDITIONAL_PROGS"
+	AC_DEFINE(DB_WIN32)
+	AC_DEFINE(STDC_HEADERS)
+else
+	OSDIR=os
+	PATH_SEPARATOR="/"
 fi
 
-# Checks for compiler characteristics.
-AC_C_CONST
-
 # Checks for include files, structures, C types.
 AC_HEADER_STAT
 AC_HEADER_TIME
 AC_HEADER_DIRENT
-AC_CHECK_HEADERS(sys/select.h sys/time.h)
+AC_CHECK_HEADERS(sys/select.h sys/time.h sys/fcntl.h)
 AC_CHECK_MEMBERS([struct stat.st_blksize])
 AM_TYPES
 
 AC_CACHE_CHECK([for ANSI C exit success/failure values], db_cv_exit_defines, [
 AC_TRY_COMPILE([#include <stdlib.h>], return (EXIT_SUCCESS);,
     [db_cv_exit_defines=yes], [db_cv_exit_defines=no])])
-if test "$db_cv_exit_defines" = yes; then
+if test "$db_cv_exit_defines" = "yes"; then
 	AC_DEFINE(HAVE_EXIT_SUCCESS)
 	AH_TEMPLATE(HAVE_EXIT_SUCCESS,
     [Define to 1 if you have EXIT_SUCCESS/EXIT_FAILURE #defines.])
 fi
 
-# Test for various functions/libraries that the test and example programs use:
-#	sched_yield function
-#	pthreads, socket and math libraries
-AC_CHECK_FUNC(sched_yield,,
-    AC_SEARCH_LIBS(sched_yield, rt, LOAD_LIBS="$LOAD_LIBS -lrt"))
-
-# XXX
+# Test for various functions/libraries -- do tests that change library values
+# first.
+#
+# The Berkeley DB library calls fdatasync, and it's only available in -lrt on
+# Solaris.  See if we can find it either without additional libraries or in
+# -lrt.  If fdatasync is found in -lrt, add -lrt to the Java and Tcl shared
+# library link lines.
+AC_SEARCH_LIBS(fdatasync, rt, [dnl
+    if test "$ac_cv_search_fdatasync" != "none required" ; then
+        LIBJSO_LIBS="$LIBJSO_LIBS -lrt";
+        LIBSO_LIBS="$LIBSO_LIBS -lrt";
+        LIBTSO_LIBS="$LIBTSO_LIBS -lrt";
+    fi])
+
+# The test and example programs use the sched_yield function, taken from -lrt
+# on Solaris.
+AC_SEARCH_LIBS(sched_yield, rt)
+
+# !!!
 # We can't check for pthreads in the same way we did the test for sched_yield
 # because the Solaris C library includes pthread interfaces which are not
-# thread-safe.  For that reason we always add -lpthread if we find a pthread
-# library.  Also we can't depend on any specific call existing (pthread_create,
-# for example), as it may be #defined in an include file -- OSF/1 (Tru64) has
-# this problem.
-AC_HAVE_LIBRARY(pthread, LOAD_LIBS="$LOAD_LIBS -lpthread")
+# inter-process safe.  For that reason we always add -lpthread if we find a
+# pthread library.
+#
+# We can't depend on any specific call existing (pthread_create, for example),
+# as it may be #defined in an include file -- OSF/1 (Tru64) has this problem.
+AC_HAVE_LIBRARY(pthread, TEST_LIBS="$TEST_LIBS -lpthread")
 
-# XXX
-# We could be more exact about whether these libraries are needed, but we don't
-# bother -- if they exist, we load them.
-AC_HAVE_LIBRARY(m, LOAD_LIBS="$LOAD_LIBS -lm")
-AC_HAVE_LIBRARY(socket, LOAD_LIBS="$LOAD_LIBS -lsocket")
-AC_HAVE_LIBRARY(nsl, LOAD_LIBS="$LOAD_LIBS -lnsl")
+# !!!
+# We could be more exact about whether these libraries are needed, but don't
+# bother -- if they exist, we load them, it's only the test programs anyway.
+AC_HAVE_LIBRARY(m, TEST_LIBS="$TEST_LIBS -lm")
+AC_HAVE_LIBRARY(socket, TEST_LIBS="$TEST_LIBS -lsocket")
+AC_HAVE_LIBRARY(nsl, TEST_LIBS="$TEST_LIBS -lnsl")
 
 # Check for mutexes.
 # We do this here because it changes $LIBS.
@@ -442,22 +479,22 @@ AM_DEFINE_MUTEXES
 # buffer is non-NULL -- Solaris can't handle a NULL buffer, and they
 # deleted getwd().
 AC_REPLACE_FUNCS(getcwd getopt memcmp memcpy memmove raise)
-AC_REPLACE_FUNCS(snprintf strcasecmp strdup strerror vsnprintf)
+AC_REPLACE_FUNCS(strcasecmp strdup strerror strtol strtoul)
 
 # Check for system functions we optionally use.
-AC_CHECK_FUNCS(_fstati64 clock_gettime directio gettimeofday getuid)
-AC_CHECK_FUNCS(pstat_getdynamic sched_yield select strtoul sysconf yield)
-
-# Checks for system functions for which we don't have replacements.
-# We require qsort(3).
-AC_CHECK_FUNCS(qsort, , AC_MSG_ERROR([No qsort library function.]))
+AC_CHECK_FUNCS(_fstati64 clock_gettime directio fdatasync ftruncate getrusage)
+AC_CHECK_FUNCS(gettimeofday getuid pstat_getdynamic rand sched_yield)
+AC_CHECK_FUNCS(select snprintf srand sysconf vsnprintf yield)
 
 # Pread/pwrite.
 # HP-UX has pread/pwrite, but it doesn't work with largefile support.
-case "$host_os" in
-hpux*)
-	AC_MSG_WARN([pread/pwrite interfaces ignored on $host_os.]);;
-*)	AC_CHECK_FUNCS(pread pwrite)
+# NCR's version of System V R 4.3 has pread/pwrite symbols, but no support.
+case "$host_os-$host_vendor" in
+hpux*|sysv4.3*-ncr)
+	AC_MSG_WARN(
+	    [pread/pwrite interfaces ignored on $host_os-$host_vendor.]);;
+*)
+	AC_CHECK_FUNCS(pread pwrite);;
 esac
 
 # Check for fcntl(2) to deny child process access to file descriptors.
@@ -467,7 +504,7 @@ AC_TRY_LINK([
 #include <fcntl.h>], [
 	fcntl(1, F_SETFD, 1);
 ], [db_cv_fcntl_f_setfd=yes], [db_cv_fcntl_f_setfd=no])])
-if test "$db_cv_fcntl_f_setfd" = yes; then
+if test "$db_cv_fcntl_f_setfd" = "yes"; then
 	AC_DEFINE(HAVE_FCNTL_F_SETFD)
 	AH_TEMPLATE(HAVE_FCNTL_F_SETFD,
     [Define to 1 if fcntl/F_SETFD denies child access to file descriptors.])
@@ -475,28 +512,25 @@ fi
 
 # A/UX has a broken getopt(3).
 case "$host_os" in
-aux*)	ADDITIONAL_OBJS="getopt${o} $ADDITIONAL_OBJS";;
+aux*)	AC_LIBOBJ([getopt]);;
 esac
 
-# Linux has the O_DIRECT flag, but you can't actually use it.
-AC_CACHE_CHECK([for open/O_DIRECT], db_cv_open_o_direct, [
-echo "test for working open/O_DIRECT" > __o_direct_file
-AC_TRY_RUN([
-#include <sys/types.h>
-#include <fcntl.h>
-main() {
-int c, fd = open("__o_direct_file", O_RDONLY | O_DIRECT, 0);
-exit ((fd == -1) || (read(fd, &c, 1) != 1));
-}], [db_cv_open_o_direct=yes], [db_cv_open_o_direct=no],
-AC_TRY_LINK([
-#include <sys/types.h>   
-#include <fcntl.h>], [
-	open("__o_direct_file", O_RDONLY | O_DIRECT, 0);
-], [db_cv_open_o_direct=yes], [db_cv_open_o_direct=no]))
-rm -f __o_direct_file])
-if test "$db_cv_open_o_direct" = yes; then
-	AC_DEFINE(HAVE_O_DIRECT)
-	AH_TEMPLATE(HAVE_O_DIRECT, [Define to 1 if you have the O_DIRECT flag.])
+# Linux has a broken O_DIRECT flag, but you can't detect it at configure time.
+# Linux and SGI require buffer alignment we may not match, otherwise writes
+# will fail.  Default to not using the O_DIRECT flag.
+if test "$db_cv_o_direct" = "yes"; then
+	AC_CACHE_CHECK([for open/O_DIRECT], db_cv_open_o_direct, [
+	AC_TRY_LINK([
+	#include <sys/types.h>
+	#include <fcntl.h>], [
+		open("a", O_RDONLY | O_DIRECT, 0);
+	], [db_cv_open_o_direct=yes], [db_cv_open_o_direct=no])])
+	if test \
+	    "$db_cv_o_direct" = "yes" -a "$db_cv_open_o_direct" = "yes"; then
+		AC_DEFINE(HAVE_O_DIRECT)
+		AH_TEMPLATE(HAVE_O_DIRECT,
+		    [Define to 1 if you have the O_DIRECT flag.])
+	fi
 fi
 
 # Check for largefile support.
@@ -516,11 +550,11 @@ AC_SYS_LARGEFILE
 mmap_ok=no
 case "$host_os" in
 bsdi3*|bsdi4.0)
-	AC_MSG_WARN([mlock(2) interface ignored on BSD/OS 3.X and 4.0.])
+	AC_MSG_WARN([mlock(2) interface ignored on $host_os-$host_vendor.])
 	mmap_ok=yes
 	AC_CHECK_FUNCS(mmap munmap, , mmap_ok=no);;
 ultrix*)
-	AC_MSG_WARN([mmap(2) interface ignored on Ultrix.]);;
+	AC_MSG_WARN([mmap(2) interface ignored on $host_os-$host_vendor.]);;
 *)
 	mmap_ok=yes
 	AC_CHECK_FUNCS(mlock munlock)
@@ -534,29 +568,125 @@ esac
 shmget_ok=no
 case "$host_os" in
 sunos*)
-	AC_MSG_WARN([shmget(2) interface ignored on SunOS.]);;
+	AC_MSG_WARN([shmget(2) interface ignored on $host_os-$host_vendor.]);;
 *)
 	shmget_ok=yes
 	AC_CHECK_FUNCS(shmget, , shmget_ok=no);;
 esac
 
 # We require either mmap/munmap(2) or shmget(2).
-if test "$mmap_ok" = no -a "$shmget_ok" = no; then
+if test "$mmap_ok" = "no" -a "$shmget_ok" = "no"; then
 	AC_MSG_WARN([Neither mmap/munmap(2) or shmget(2) library functions.])
 fi
 
-# If we're not doing version name substitution, DB_VERSION_UNIQUE_NAME
-# needs to be erased.
-if test "$db_cv_uniquename" = "no"; then
-	DB_VERSION_UNIQUE_NAME=""
+# Optional RPC client/server.
+if test "$db_cv_rpc" = "yes"; then
+	AM_RPC_CONFIGURE
+fi
+
+# Optional Tcl support.
+if test "$db_cv_tcl" = "yes"; then
+	AM_TCL_LOAD
+fi
+
+# Optional sequence code.
+AM_SEQUENCE_CONFIGURE
+
+# Optional DB 1.85 compatibility API.
+if test "$db_cv_compat185" = "yes"; then
+	ADDITIONAL_INCS="db_185.h $ADDITIONAL_INCS"
+
+	ADDITIONAL_OBJS="db185${o} $ADDITIONAL_OBJS"
+fi
+
+# Optional utilities.
+if test "$db_cv_dump185" = "yes"; then
+	ADDITIONAL_PROGS="db_dump185 $ADDITIONAL_PROGS"
+fi
+
+# You can disable pieces of functionality to save space.
+#
+# Btree is always configured: it is the standard method, and Hash off-page
+# duplicates require it.
+ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(BTREE_OBJS)"
+
+# Hash can be disabled.
+if test "$db_cv_build_hash" = "yes"; then
+	AC_DEFINE(HAVE_HASH)
+	AH_TEMPLATE(HAVE_HASH, [Define to 1 if building Hash access method.])
+	ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(HASH_OBJS)"
+	if test "$db_cv_build_verify" = "yes"; then
+		ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(HASH_VRFY_OBJS)"
+	fi
+else
+	ADDITIONAL_OBJS="$ADDITIONAL_OBJS hash_stub${o}"
+fi
+
+# Queue can be disabled.
+if test "$db_cv_build_queue" = "yes"; then
+	AC_DEFINE(HAVE_QUEUE)
+	AH_TEMPLATE(HAVE_QUEUE, [Define to 1 if building Queue access method.])
+	ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(QUEUE_OBJS)"
+	if test "$db_cv_build_verify" = "yes"; then
+		ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(QUEUE_VRFY_OBJS)"
+	fi
+else
+	ADDITIONAL_OBJS="$ADDITIONAL_OBJS qam_stub${o}"
+fi
+
+# Replication can be disabled.
+if test "$db_cv_build_replication" = "yes"; then
+	AC_DEFINE(HAVE_REPLICATION)
+	AH_TEMPLATE(HAVE_REPLICATION,
+	    [Define to 1 if building replication support.])
+	ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(REP_OBJS)"
+else
+	ADDITIONAL_OBJS="$ADDITIONAL_OBJS rep_stub${o}"
+fi
+
+# The statistics code can be disabled.
+if test "$db_cv_build_statistics" = "yes"; then
+	AC_DEFINE(HAVE_STATISTICS)
+	AH_TEMPLATE(HAVE_STATISTICS,
+	    [Define to 1 if building statistics support.])
+fi
+
+# The verification code can be disabled.
+if test "$db_cv_build_verify" = "yes"; then
+	AC_DEFINE(HAVE_VERIFY)
+	AH_TEMPLATE(HAVE_VERIFY,
+	    [Define to 1 if building access method verification support.])
+	ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(BTREE_VRFY_OBJS)"
+else
+	ADDITIONAL_OBJS="$ADDITIONAL_OBJS db_vrfy_stub${o}"
+fi
+
+# The crypto code can be disabled.
+if test -d "$srcdir/../crypto" -a "$db_cv_build_cryptography" = "yes"; then
+	AC_DEFINE(HAVE_CRYPTO)
+	AH_TEMPLATE(HAVE_CRYPTO,
+    [Define to 1 if Berkeley DB release includes strong cryptography.])
+
+	CRYPTO_OBJS="\$(CRYPTO_OBJS)"
+else
+	CRYPTO_OBJS="crypto_stub${o}"
 fi
 
+# We need to add the additional object files into the Makefile with the correct
+# suffix.  We can't use $LTLIBOBJS itself, because that variable has $U encoded
+# in it for automake, and that's not what we want.  See SR #7227 for additional
+# information.
+#
+# XXX: I'm not sure this is correct.
+REPLACEMENT_OBJS=`echo "$LIB@&t@OBJS" |
+		 sed "s,\.[[^.]]* ,$o ,g;s,\.[[^.]]*$,$o,"`
+
 # This is necessary so that .o files in LIBOBJS are also built via
 # the ANSI2KNR-filtering rules.
 LIB@&t@OBJS=`echo "$LIB@&t@OBJS" |
 	     sed 's,\.[[^.]]* ,$U&,g;s,\.[[^.]]*$,$U&,'`
 LTLIBOBJS=`echo "$LIB@&t@OBJS" |
-	   sed "s,\.[[^.]]* ,$o ,g;s,\.[[^.]]*$,$o,"`
+	   sed 's,\.[[^.]]* ,.lo ,g;s,\.[[^.]]*$,.lo,'`
 AC_SUBST(LTLIBOBJS)
 
 # Initial output file list.
@@ -565,15 +695,21 @@ CREATE_LIST="Makefile
     db_int.h:$srcdir/../dbinc/db_int.in
     include.tcl:$srcdir/../test/include.tcl"
 
+# MinGW needs win_db.h.
+if test "$db_cv_mingw" = "yes"; then
+CREATE_LIST="$CREATE_LIST
+    win_db.h:$srcdir/win_db.in"
+fi
+
 # Create the db.h file from a source file, a list of global function
 # prototypes, and, if configured for unique names, a list of #defines
 # to do DB_VERSION_UNIQUE_NAME substitution.
 if test "$db_cv_uniquename" = "yes"; then
 	CREATE_LIST="$CREATE_LIST
-	db.h:$srcdir/../dbinc/db.in:$srcdir/../dbinc_auto/rpc_defs.in:$srcdir/../dbinc_auto/ext_def.in:$srcdir/../dbinc_auto/ext_prot.in"
+	db.h:$srcdir/../dbinc/db.in:$srcdir/../dbinc_auto/ext_def.in:$srcdir/../dbinc_auto/ext_prot.in"
 else
 	CREATE_LIST="$CREATE_LIST
-	db.h:$srcdir/../dbinc/db.in:$srcdir/../dbinc_auto/rpc_defs.in:$srcdir/../dbinc_auto/ext_prot.in"
+	db.h:$srcdir/../dbinc/db.in:$srcdir/../dbinc_auto/ext_prot.in"
 fi
 
 # If configured for unique names, create the db_int_uext.h file (which
@@ -600,13 +736,5 @@ if test "$db_cv_compat185" = "yes"; then
 	fi
 fi
 
-if test "$db_cv_embedix" = "yes"; then
-	CREATE_LIST="$CREATE_LIST db.ecd:../dist/db.ecd.in"
-fi
-
-if test "$db_cv_rpm" = "yes"; then
-	CREATE_LIST="$CREATE_LIST db.spec:../dist/db.spec.in"
-fi
-
 AC_CONFIG_FILES($CREATE_LIST)
 AC_OUTPUT
diff --git a/storage/bdb/dist/gen_inc.awk b/storage/bdb/dist/gen_inc.awk
index 2f5b491cda1f898b830c7762c08cf8f9a3d1ec7d..d48d02bb1d2841fcb9cf92b634b74857c8a3131c 100644
--- a/storage/bdb/dist/gen_inc.awk
+++ b/storage/bdb/dist/gen_inc.awk
@@ -18,17 +18,17 @@
 #	i_pfile		include file that contains internal (PUBLIC) prototypes
 /PUBLIC:/ {
 	sub("^.*PUBLIC:[	 ][	 ]*", "")
-	if ($0 ~ /^#(if|ifdef|ifndef|else|endif)/) {
+	if ($0 ~ "^#if|^#ifdef|^#ifndef|^#else|^#endif") {
 		print $0 >> i_pfile
 		print $0 >> i_dfile
 		next
 	}
 	pline = sprintf("%s %s", pline, $0)
-	if (pline ~ /\)\);/) {
+	if (pline ~ "\\)\\);") {
 		sub("^[	 ]*", "", pline)
 		print pline >> i_pfile
 		if (pline !~ db_version_unique_name) {
-			sub("[	 ][	 ]*__P.*", "", pline)
+			gsub("[	 ][	 ]*__P.*", "", pline)
 			sub("^.*[	 ][*]*", "", pline)
 			printf("#define	%s %s@DB_VERSION_UNIQUE_NAME@\n",
 			    pline, pline) >> i_dfile
@@ -53,17 +53,17 @@
 # functions in libraries built with that configuration option.
 /EXTERN:/ {
 	sub("^.*EXTERN:[	 ][	 ]*", "")
-	if ($0 ~ /^#(if|ifdef|ifndef|else|endif)/) {
+	if ($0 ~ "^#if|^#ifdef|^#ifndef|^#else|^#endif") {
 		print $0 >> e_pfile
 		print $0 >> e_dfile
 		next
 	}
 	eline = sprintf("%s %s", eline, $0)
-	if (eline ~ /\)\);/) {
+	if (eline ~ "\\)\\);") {
 		sub("^[	 ]*", "", eline)
 		print eline >> e_pfile
-		if (eline !~ db_version_unique_name && eline !~ /^int txn_/) {
-			sub("[	 ][	 ]*__P.*", "", eline)
+		if (eline !~ db_version_unique_name && eline !~ "^int txn_") {
+			gsub("[	 ][	 ]*__P.*", "", eline)
 			sub("^.*[	 ][*]*", "", eline)
 			printf("#define	%s %s@DB_VERSION_UNIQUE_NAME@\n",
 			    eline, eline) >> e_dfile
diff --git a/storage/bdb/dist/gen_rec.awk b/storage/bdb/dist/gen_rec.awk
index 75f2e86ca9e36725b9099331e2aac0d4efbb6352..001ec65f0c5e709c2c1a90f26464e5f4714e415c 100644
--- a/storage/bdb/dist/gen_rec.awk
+++ b/storage/bdb/dist/gen_rec.awk
@@ -2,10 +2,10 @@
 #
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: gen_rec.awk,v 11.70 2002/08/08 15:44:47 bostic Exp $
+# $Id: gen_rec.awk,v 11.110 2004/10/20 20:40:58 bostic Exp $
 #
 
 # This awk script generates all the log, print, and read routines for the DB
@@ -34,35 +34,32 @@
 # DB:
 # 	DBPRIVATE	Indicates that a file will be built as part of DB,
 #			rather than compiled independently, and so can use
-#			DB-private interfaces (such as DB_NOCOPY).
+#			DB-private interfaces (such as DB_LOG_NOCOPY).
 #	DB		A DB handle.  Logs the dbreg fileid for that handle,
 #			and makes the *_log interface take a DB * instead of a
 #			DB_ENV *.
 #	PGDBT		Just like DBT, only we know it stores a page or page
 #			header, so we can byte-swap it (once we write the
 #			byte-swapping code, which doesn't exist yet).
-#	WRLOCK
-#	WRLOCKNZ	An ARG that stores a db_pgno_t, which the getpgnos
-#			function should acquire a lock on.  WRLOCK implies
-#			that we should always get the lock;  WRLOCKNZ implies
-#			that we should do so if and only if the pgno is non-zero
-#			(unfortunately, 0 is both PGNO_INVALID and the main
-#			metadata page number).
+#	LOCKS		Just like DBT, but uses a print function for locks.
 
 BEGIN {
 	if (source_file == "" ||
 	    header_file == "" || template_file == "") {
 	    print "Usage: gen_rec.awk requires three variables to be set:"
-	    print "\tsource_file\t-- the C source file being created"
-	    print "\theader_file\t-- the C #include file being created"
+	    print "\theader_file\t-- the recover #include file being created"
+	    print "\tprint_file\t-- the print source file being created"
+	    print "\tsource_file\t-- the recover source file being created"
 	    print "\ttemplate_file\t-- the template file being created"
 	    exit
 	}
 	FS="[\t ][\t ]*"
 	CFILE=source_file
 	HFILE=header_file
+	PFILE=print_file
 	TFILE=template_file
 	dbprivate = 0
+	buf_only = 1;
 }
 /^[ 	]*DBPRIVATE/ {
 	dbprivate = 1
@@ -71,9 +68,17 @@ BEGIN {
 	prefix = $2
 	num_funcs = 0;
 
-	# Start .c file.
-	printf("/* Do not edit: automatically built by gen_rec.awk. */\n") \
+	# Start .c files.
+	printf("/* Do not edit: automatically built by gen_rec.awk. */\n\n") \
 	    > CFILE
+	printf("#include \"db_config.h\"\n\n") >> CFILE
+	printf("/* Do not edit: automatically built by gen_rec.awk. */\n\n") \
+	    > PFILE
+	printf("#include \"db_config.h\"\n\n") >> PFILE
+	if (prefix == "__ham")
+		printf("#ifdef HAVE_HASH\n") >> PFILE
+	if (prefix == "__qam")
+		printf("#ifdef HAVE_QUEUE\n") >> PFILE
 
 	# Start .h file, make the entire file conditional.
 	printf("/* Do not edit: automatically built by gen_rec.awk. */\n\n") \
@@ -94,12 +99,14 @@ BEGIN {
 	printf("#include \"dbinc/log.h\"\n\n") >> TFILE
 }
 /^[ 	]*INCLUDE/ {
-	if ($3 == "")
-		printf("%s\n", $2) >> CFILE
-	else
-		printf("%s %s\n", $2, $3) >> CFILE
+	for (i = 2; i < NF; i++)
+		printf("%s ", $i) >> CFILE
+	printf("%s\n", $i) >> CFILE
+	for (i = 2; i < NF; i++)
+		printf("%s ", $i) >> PFILE
+	printf("%s\n", $i) >> PFILE
 }
-/^[ 	]*(BEGIN|IGNORED)/ {
+/^[ 	]*(BEGIN|IGNORED|BEGIN_BUF)/ {
 	if (in_begin) {
 		print "Invalid format: missing END statement"
 		exit
@@ -108,21 +115,22 @@ BEGIN {
 	is_dbt = 0;
 	has_dbp = 0;
 	is_uint = 0;
-	need_log_function = ($1 == "BEGIN");
+	need_log_function = ($1 == "BEGIN") || ($1 == "BEGIN_BUF");
+	not_buf = ($1 == "BEGIN") || ($1 == "IGNORED");
+	if (not_buf)
+		buf_only = 0;
 	nvars = 0;
 
-	# number of locks that the getpgnos functions will return
-	nlocks = 0;
-
 	thisfunc = $2;
 	funcname = sprintf("%s_%s", prefix, $2);
 
-	rectype = $3;
+	if (not_buf)
+		rectype = $3;
 
 	funcs[num_funcs] = funcname;
 	++num_funcs;
 }
-/^[ 	]*(DB|ARG|DBT|PGDBT|POINTER|WRLOCK|WRLOCKNZ)/ {
+/^[ 	]*(DB|ARG|DBT|LOCKS|PGDBT|POINTER|TIME)/ {
 	vars[nvars] = $2;
 	types[nvars] = $3;
 	atypes[nvars] = $1;
@@ -135,7 +143,7 @@ BEGIN {
 		has_dbp = 1;
 	}
 
-	if ($1 == "DB" || $1 == "ARG" || $1 == "WRLOCK" || $1 == "WRLOCKNZ") {
+	if ($1 == "DB" || $1 == "ARG" || $1 == "TIME") {
 		sizes[nvars] = sprintf("sizeof(u_int32_t)");
 		is_uint = 1;
 	} else if ($1 == "POINTER")
@@ -148,17 +156,6 @@ BEGIN {
 	}
 	nvars++;
 }
-/^[	]*(WRLOCK|WRLOCKNZ)/ {
-	nlocks++;
-
-	if ($1 == "WRLOCK") {
-		lock_if_zero[nlocks] = 1;
-	} else {
-		lock_if_zero[nlocks] = 0;
-	}
-
-	lock_pgnos[nlocks] = $2;
-}
 /^[ 	]*END/ {
 	if (!in_begin) {
 		print "Invalid format: missing BEGIN statement"
@@ -166,14 +163,18 @@ BEGIN {
 	}
 
 	# Declare the record type.
-	printf("#define\tDB_%s\t%d\n", funcname, rectype) >> HFILE
+	if (not_buf) {
+		printf("#define\tDB_%s\t%d\n", funcname, rectype) >> HFILE
+	}
 
 	# Structure declaration.
 	printf("typedef struct _%s_args {\n", funcname) >> HFILE
 
 	# Here are the required fields for every structure
-	printf("\tu_int32_t type;\n\tDB_TXN *txnid;\n") >> HFILE
-	printf("\tDB_LSN prev_lsn;\n") >>HFILE
+	if (not_buf) {
+		printf("\tu_int32_t type;\n\tDB_TXN *txnid;\n") >> HFILE
+		printf("\tDB_LSN prev_lsn;\n") >>HFILE
+	}
 
 	# Here are the specified fields.
 	for (i = 0; i < nvars; i++) {
@@ -186,25 +187,22 @@ BEGIN {
 	}
 	printf("} %s_args;\n\n", funcname) >> HFILE
 
-	# Output the log, print, read, and getpgnos functions.
+	# Output the log, print and read functions.
 	if (need_log_function) {
 		log_function();
-
-		# The getpgnos function calls DB-private (__rep_*) functions,
-		# so we only generate it for our own logging functions,
-		# not application-specific ones.
-		if (dbprivate) {
-			getpgnos_function();
-		}
 	}
-	print_function();
+	if (not_buf) {
+		print_function();
+	}
 	read_function();
 
 	# Recovery template
-	cmd = sprintf(\
+	if (not_buf) {
+		cmd = sprintf(\
     "sed -e s/PREF/%s/ -e s/FUNC/%s/ < template/rec_ctemp >> %s",
-	    prefix, thisfunc, TFILE)
-	system(cmd);
+		    prefix, thisfunc, TFILE)
+		system(cmd);
+	}
 
 	# Done writing stuff, reset and continue.
 	in_begin = 0;
@@ -214,79 +212,63 @@ END {
 	# End the conditional for the HFILE
 	printf("#endif\n") >> HFILE;
 
+	if (buf_only == 1)
+		exit
+
 	# Print initialization routine; function prototype
 	p[1] = sprintf("int %s_init_print %s%s", prefix,
 	    "__P((DB_ENV *, int (***)(DB_ENV *, DBT *, DB_LSN *, ",
 	    "db_recops, void *), size_t *));");
 	p[2] = "";
-	proto_format(p);
+	proto_format(p, PFILE);
 
 	# Create the routine to call __db_add_recovery(print_fn, id)
 	printf("int\n%s_init_print(dbenv, dtabp, dtabsizep)\n", \
-	    prefix) >> CFILE;
-	printf("\tDB_ENV *dbenv;\n") >> CFILE;;
-	printf("\tint (***dtabp)__P((DB_ENV *, DBT *, DB_LSN *,") >> CFILE;
-	printf(" db_recops, void *));\n") >> CFILE;
-	printf("\tsize_t *dtabsizep;\n{\n") >> CFILE;
+	    prefix) >> PFILE;
+	printf("\tDB_ENV *dbenv;\n") >> PFILE;;
+	printf("\tint (***dtabp)__P((DB_ENV *, DBT *, DB_LSN *,") >> PFILE;
+	printf(" db_recops, void *));\n") >> PFILE;
+	printf("\tsize_t *dtabsizep;\n{\n") >> PFILE;
 	# If application-specific, the user will need a prototype for
 	# __db_add_recovery, since they won't have DB's.
 	if (!dbprivate) {
-		printf("\tint __db_add_recovery __P((DB_ENV *,\n") >> CFILE;
+		printf("\tint __db_add_recovery __P((DB_ENV *,\n") >> PFILE;
 		printf(\
-"\t    int (***)(DB_ENV *, DBT *, DB_LSN *, db_recops, void *),\n") >> CFILE;
-		printf("\t    size_t *,\n") >> CFILE;
+"\t    int (***)(DB_ENV *, DBT *, DB_LSN *, db_recops, void *),\n") >> PFILE;
+		printf("\t    size_t *,\n") >> PFILE;
 		printf(\
 "\t    int (*)(DB_ENV *, DBT *, DB_LSN *, db_recops, void *), u_int32_t));\n") \
-		    >> CFILE;
+		    >> PFILE;
 	}
 
-	printf("\tint ret;\n\n") >> CFILE;
+	printf("\tint ret;\n\n") >> PFILE;
 	for (i = 0; i < num_funcs; i++) {
-		printf("\tif ((ret = __db_add_recovery(dbenv, ") >> CFILE;
-		printf("dtabp, dtabsizep,\n") >> CFILE;
+		printf("\tif ((ret = __db_add_recovery(dbenv, ") >> PFILE;
+		printf("dtabp, dtabsizep,\n") >> PFILE;
 		printf("\t    %s_print, DB_%s)) != 0)\n", \
-		    funcs[i], funcs[i]) >> CFILE;
-		printf("\t\treturn (ret);\n") >> CFILE;
+		    funcs[i], funcs[i]) >> PFILE;
+		printf("\t\treturn (ret);\n") >> PFILE;
 	}
-	printf("\treturn (0);\n}\n\n") >> CFILE;
-
-	# We only want to generate *_init_{getpgnos,recover} functions
-	# if this is a DB-private, rather than application-specific,
-	# set of recovery functions.  Application-specific recovery functions
-	# should be dispatched using the DB_ENV->set_app_dispatch callback
-	# rather than a DB dispatch table ("dtab").
+	printf("\treturn (0);\n}\n") >> PFILE;
+	if (prefix == "__ham")
+		printf("#endif /* HAVE_HASH */\n") >> PFILE
+	if (prefix == "__qam")
+		printf("#endif /* HAVE_QUEUE */\n") >> PFILE
+
+	# We only want to generate *_init_recover functions if this is a
+	# DB-private, rather than application-specific, set of recovery
+	# functions.  Application-specific recovery functions should be
+	# dispatched using the DB_ENV->set_app_dispatch callback rather
+	# than a DB dispatch table ("dtab").
 	if (!dbprivate)
 		exit
 
-	# Page number initialization routine; function prototype
-	p[1] = sprintf("int %s_init_getpgnos %s%s", prefix,
-	    "__P((DB_ENV *, int (***)(DB_ENV *, DBT *, DB_LSN *, ",
-	    "db_recops, void *), size_t *));");
-	p[2] = "";
-	proto_format(p);
-
-	# Create the routine to call db_add_recovery(pgno_fn, id)
-	printf("int\n%s_init_getpgnos(dbenv, dtabp, dtabsizep)\n", \
-	    prefix) >> CFILE;
-	printf("\tDB_ENV *dbenv;\n") >> CFILE;
-	printf("\tint (***dtabp)__P((DB_ENV *, DBT *, DB_LSN *,") >> CFILE;
-	printf(" db_recops, void *));\n") >> CFILE;
-	printf("\tsize_t *dtabsizep;\n{\n\tint ret;\n\n") >> CFILE;
-	for (i = 0; i < num_funcs; i++) {
-		printf("\tif ((ret = __db_add_recovery(dbenv, ") >> CFILE;
-		printf("dtabp, dtabsizep,\n") >> CFILE;
-		printf("\t    %s_getpgnos, DB_%s)) != 0)\n", \
-		    funcs[i], funcs[i]) >> CFILE;
-		printf("\t\treturn (ret);\n") >> CFILE;
-	}
-	printf("\treturn (0);\n}\n\n") >> CFILE;
-
 	# Recover initialization routine
 	p[1] = sprintf("int %s_init_recover %s%s", prefix,
 	    "__P((DB_ENV *, int (***)(DB_ENV *, DBT *, DB_LSN *, ",
 	    "db_recops, void *), size_t *));");
 	p[2] = "";
-	proto_format(p);
+	proto_format(p, CFILE);
 
 	# Create the routine to call db_add_recovery(func, id)
 	printf("int\n%s_init_recover(dbenv, dtabp, dtabsizep)\n", \
@@ -305,37 +287,48 @@ END {
 	printf("\treturn (0);\n}\n") >> CFILE;
 }
 
-function log_function() {
+function log_function()
+{
 	# Write the log function; function prototype
 	pi = 1;
-	p[pi++] = sprintf("int %s_log", funcname);
-	p[pi++] = " ";
-	if (has_dbp == 1) {
-		p[pi++] = "__P((DB *, DB_TXN *, DB_LSN *, u_int32_t";
+	if (not_buf) {
+		p[pi++] = sprintf("int %s_log", funcname);
+		p[pi++] = " ";
+		if (has_dbp == 1) {
+			p[pi++] = "__P((DB *";
+		} else {
+			p[pi++] = "__P((DB_ENV *";
+		}
+		p[pi++] = ", DB_TXN *, DB_LSN *, u_int32_t";
 	} else {
-		p[pi++] = "__P((DB_ENV *, DB_TXN *, DB_LSN *, u_int32_t";
+		p[pi++] = sprintf("int %s_buf", funcname);
+		p[pi++] = " ";
+		p[pi++] = "__P((u_int8_t *, size_t, size_t *";
 	}
 	for (i = 0; i < nvars; i++) {
 		if (modes[i] == "DB")
 			continue;
 		p[pi++] = ", ";
 		p[pi++] = sprintf("%s%s%s",
-		    (modes[i] == "DBT" || modes[i] == "PGDBT") ? "const " : "",
-		    types[i],
-		    (modes[i] == "DBT" || modes[i] == "PGDBT") ? " *" : "");
+		    (modes[i] == "DBT" || modes[i] == "LOCKS" ||
+		    modes[i] == "PGDBT") ? "const " : "", types[i],
+		    (modes[i] == "DBT" || modes[i] == "LOCKS" ||
+		    modes[i] == "PGDBT") ? " *" : "");
 	}
 	p[pi++] = "";
 	p[pi++] = "));";
 	p[pi++] = "";
-	proto_format(p);
+	proto_format(p, CFILE);
 
 	# Function declaration
-	if (has_dbp == 1) {
+	if (not_buf && has_dbp == 1) {
 		printf("int\n%s_log(dbp, txnid, ret_lsnp, flags", \
 		    funcname) >> CFILE;
-	} else {
+	} else if (not_buf) {
 		printf("int\n%s_log(dbenv, txnid, ret_lsnp, flags", \
 		    funcname) >> CFILE;
+	} else {
+		printf("int\n%s_buf(buf, max, lenp", funcname) >> CFILE;
 	}
 	for (i = 0; i < nvars; i++) {
 		if (modes[i] == "DB") {
@@ -353,16 +346,22 @@ function log_function() {
 	printf(")\n") >> CFILE;
 
 	# Now print the parameters
-	if (has_dbp == 1) {
-		printf("\tDB *dbp;\n") >> CFILE;
+	if (not_buf) {
+		if (has_dbp == 1) {
+			printf("\tDB *dbp;\n") >> CFILE;
+		} else {
+			printf("\tDB_ENV *dbenv;\n") >> CFILE;
+		}
+		printf("\tDB_TXN *txnid;\n\tDB_LSN *ret_lsnp;\n") >> CFILE;
+		printf("\tu_int32_t flags;\n") >> CFILE;
 	} else {
-		printf("\tDB_ENV *dbenv;\n") >> CFILE;
+		printf("\tu_int8_t *buf;\n") >> CFILE;
+		printf("\tsize_t max, *lenp;\n") >> CFILE;
 	}
-	printf("\tDB_TXN *txnid;\n\tDB_LSN *ret_lsnp;\n") >> CFILE;
-	printf("\tu_int32_t flags;\n") >> CFILE;
 	for (i = 0; i < nvars; i++) {
 		# We just skip for modes == DB.
-		if (modes[i] == "DBT" || modes[i] == "PGDBT")
+		if (modes[i] == "DBT" ||
+		     modes[i] == "LOCKS" || modes[i] == "PGDBT")
 			printf("\tconst %s *%s;\n", types[i], vars[i]) >> CFILE;
 		else if (modes[i] != "DB")
 			printf("\t%s %s;\n", types[i], vars[i]) >> CFILE;
@@ -370,110 +369,213 @@ function log_function() {
 
 	# Function body and local decls
 	printf("{\n") >> CFILE;
-	printf("\tDBT logrec;\n") >> CFILE;
-	if (has_dbp == 1)
-		printf("\tDB_ENV *dbenv;\n") >> CFILE;
-	printf("\tDB_LSN *lsnp, null_lsn;\n") >> CFILE;
-	if (is_dbt == 1)
-		printf("\tu_int32_t zero;\n") >> CFILE;
-	if (is_uint == 1)
-		printf("\tu_int32_t uinttmp;\n") >> CFILE;
-	printf("\tu_int32_t npad, rectype, txn_num;\n") >> CFILE;
-	printf("\tint ret;\n") >> CFILE;
-	printf("\tu_int8_t *bp;\n\n") >> CFILE;
+	if (not_buf) {
+		printf("\tDBT logrec;\n") >> CFILE;
+		if (has_dbp == 1)
+			printf("\tDB_ENV *dbenv;\n") >> CFILE;
+		if (dbprivate)
+			printf("\tDB_TXNLOGREC *lr;\n") >> CFILE;
+		printf("\tDB_LSN *lsnp, null_lsn, *rlsnp;\n") >> CFILE;
+		printf("\tu_int32_t ") >> CFILE;
+		if (is_dbt == 1)
+			printf("zero, ") >> CFILE;
+		if (is_uint == 1)
+			printf("uinttmp, ") >> CFILE;
+		printf("rectype, txn_num;\n") >> CFILE;
+		printf("\tu_int npad;\n") >> CFILE;
+	} else {
+		if (is_dbt == 1)
+			printf("\tu_int32_t zero;\n") >> CFILE;
+		if (is_uint == 1)
+			printf("\tu_int32_t uinttmp;\n") >> CFILE;
+		printf("\tu_int8_t *endbuf;\n") >> CFILE;
+	}
+	printf("\tu_int8_t *bp;\n") >> CFILE;
+	printf("\tint ") >> CFILE;
+	if (dbprivate && not_buf) {
+		printf("is_durable, ") >> CFILE;
+	}
+	printf("ret;\n\n") >> CFILE;
 
 	# Initialization
-	if (has_dbp == 1)
-		printf("\tdbenv = dbp->dbenv;\n") >> CFILE;
-	printf("\trectype = DB_%s;\n", funcname) >> CFILE;
-	printf("\tnpad = 0;\n\n") >> CFILE;
-
-	printf("\tif (txnid == NULL) {\n") >> CFILE;
-	printf("\t\ttxn_num = 0;\n") >> CFILE;
-	printf("\t\tnull_lsn.file = 0;\n") >> CFILE;
-	printf("\t\tnull_lsn.offset = 0;\n") >> CFILE;
-	printf("\t\tlsnp = &null_lsn;\n") >> CFILE;
-	printf("\t} else {\n") >> CFILE;
-	if (funcname != "__db_debug" && dbprivate) {
-		printf(\
-		    "\t\tif (TAILQ_FIRST(&txnid->kids) != NULL &&\n") >> CFILE;
-		printf("\t\t    (ret = __txn_activekids(") >> CFILE;
-		printf("dbenv, rectype, txnid)) != 0)\n") >> CFILE;
-		printf("\t\t\treturn (ret);\n") >> CFILE;
-	}
-	printf("\t\ttxn_num = txnid->txnid;\n") >> CFILE;
-	printf("\t\tlsnp = &txnid->last_lsn;\n") >> CFILE;
-	printf("\t}\n\n") >> CFILE;
-
-	# Malloc
-	printf("\tlogrec.size = sizeof(rectype) + ") >> CFILE;
-	printf("sizeof(txn_num) + sizeof(DB_LSN)") >> CFILE;
-	for (i = 0; i < nvars; i++)
-		printf("\n\t    + %s", sizes[i]) >> CFILE;
-	printf(";\n") >> CFILE
-	if (dbprivate) {
-		printf("\tif (CRYPTO_ON(dbenv)) {\n") >> CFILE;
-		printf("\t\tnpad =\n") >> CFILE
-		printf(\
-"\t\t    ((DB_CIPHER *)dbenv->crypto_handle)->adj_size(logrec.size);\n")\
+	if (not_buf) {
+		if (has_dbp == 1)
+			printf("\tdbenv = dbp->dbenv;\n") >> CFILE;
+		if (dbprivate)
+			printf("\tCOMPQUIET(lr, NULL);\n\n") >> CFILE;
+		printf("\trectype = DB_%s;\n", funcname) >> CFILE;
+		printf("\tnpad = 0;\n") >> CFILE;
+		printf("\trlsnp = ret_lsnp;\n\n") >> CFILE;
+	}
+	printf("\tret = 0;\n\n") >> CFILE;
+
+	if (not_buf) {
+		if (dbprivate) {
+			printf("\tif (LF_ISSET(DB_LOG_NOT_DURABLE)") \
+			    >> CFILE;
+			if (has_dbp == 1) {
+				printf(" ||\n\t    ") >> CFILE;
+				printf("F_ISSET(dbp, DB_AM_NOT_DURABLE)) {\n") \
+				    >> CFILE;
+			} else {
+				printf(") {\n") >> CFILE;
+				printf("\t\tif (txnid == NULL)\n") >> CFILE;
+				printf("\t\t\treturn (0);\n") >> CFILE;
+			}
+			printf("\t\tis_durable = 0;\n") >> CFILE;
+			printf("\t} else\n") >> CFILE;
+			printf("\t\tis_durable = 1;\n\n") >> CFILE;
+		}
+		printf("\tif (txnid == NULL) {\n") >> CFILE;
+		printf("\t\ttxn_num = 0;\n") >> CFILE;
+		printf("\t\tlsnp = &null_lsn;\n") >> CFILE;
+		printf("\t\tnull_lsn.file = null_lsn.offset = 0;\n") >> CFILE;
+		printf("\t} else {\n") >> CFILE;
+		if (dbprivate && funcname != "__db_debug") {
+			printf(\
+    "\t\tif (TAILQ_FIRST(&txnid->kids) != NULL &&\n") >> CFILE;
+			printf("\t\t    (ret = __txn_activekids(") >> CFILE;
+			printf("dbenv, rectype, txnid)) != 0)\n") >> CFILE;
+			printf("\t\t\treturn (ret);\n") >> CFILE;
+		}
+		printf("\t\t/*\n\t\t * We need to assign begin_lsn while ") \
 		    >> CFILE;
-		printf("\t\tlogrec.size += npad;\n\t}\n\n") >> CFILE
-	}
-	write_malloc("logrec.data", "logrec.size", CFILE)
-	printf("\tif (npad > 0)\n") >> CFILE;
-	printf("\t\tmemset((u_int8_t *)logrec.data + logrec.size ") >> CFILE;
-	printf("- npad, 0, npad);\n\n") >> CFILE;
-
-	# Copy args into buffer
-	printf("\tbp = logrec.data;\n\n") >> CFILE;
-	printf("\tmemcpy(bp, &rectype, sizeof(rectype));\n") >> CFILE;
-	printf("\tbp += sizeof(rectype);\n\n") >> CFILE;
-	printf("\tmemcpy(bp, &txn_num, sizeof(txn_num));\n") >> CFILE;
-	printf("\tbp += sizeof(txn_num);\n\n") >> CFILE;
-	printf("\tmemcpy(bp, lsnp, sizeof(DB_LSN));\n") >> CFILE;
-	printf("\tbp += sizeof(DB_LSN);\n\n") >> CFILE;
+		printf("holding region mutex.\n") >> CFILE;
+		printf("\t\t * That assignment is done inside the ") >> CFILE;
+		printf("DbEnv->log_put call,\n\t\t * ") >> CFILE;
+		printf("so pass in the appropriate memory location to be ") \
+		    >> CFILE;
+		printf("filled\n\t\t * in by the log_put code.\n\t\t*/\n") \
+		    >> CFILE;
+		printf("\t\tDB_SET_BEGIN_LSNP(txnid, &rlsnp);\n") >> CFILE;
+		printf("\t\ttxn_num = txnid->txnid;\n") >> CFILE;
+		printf("\t\tlsnp = &txnid->last_lsn;\n") >> CFILE;
+		printf("\t}\n\n") >> CFILE;
+
+		# If we're logging a DB handle, make sure we have a log
+		# file ID for it.
+		db_handle_id_function(modes, nvars);
+
+		# Malloc
+		printf("\tlogrec.size = ") >> CFILE;
+		printf("sizeof(rectype) + ") >> CFILE;
+		printf("sizeof(txn_num) + sizeof(DB_LSN)") >> CFILE;
+		for (i = 0; i < nvars; i++)
+			printf("\n\t    + %s", sizes[i]) >> CFILE;
+		printf(";\n") >> CFILE
+		if (dbprivate) {
+			printf("\tif (CRYPTO_ON(dbenv)) {\n") >> CFILE;
+			printf("\t\tnpad =\n") >> CFILE;
+			printf("\t\t    ((DB_CIPHER *)dbenv->crypto_handle)") \
+			    >> CFILE;
+			printf("->adj_size(logrec.size);\n") >> CFILE;
+			printf("\t\tlogrec.size += npad;\n\t}\n\n") >> CFILE
 
-	for (i = 0; i < nvars; i ++) {
-		if (modes[i] == "ARG" || modes[i] == "WRLOCK" || \
-		    modes[i] == "WRLOCKNZ") {
+			printf("\tif (is_durable || txnid == NULL) {\n") \
+			    >> CFILE;
+			printf("\t\tif ((ret =\n\t\t    __os_malloc(dbenv, ") \
+			    >> CFILE;
+			printf("logrec.size, &logrec.data)) != 0)\n") >> CFILE;
+			printf("\t\t\treturn (ret);\n") >> CFILE;
+			printf("\t} else {\n") >> CFILE;
+			write_malloc("\t\t",
+			    "lr", "logrec.size + sizeof(DB_TXNLOGREC)", CFILE)
+			printf("#ifdef DIAGNOSTIC\n") >> CFILE;
+			printf("\t\tif ((ret =\n\t\t    __os_malloc(dbenv, ") \
+			    >> CFILE;
+			printf("logrec.size, &logrec.data)) != 0) {\n") \
+			    >> CFILE;
+			printf("\t\t\t__os_free(dbenv, lr);\n") >> CFILE;
+			printf("\t\t\treturn (ret);\n") >> CFILE;
+			printf("\t\t}\n") >> CFILE;
+			printf("#else\n") >> CFILE;
+			printf("\t\tlogrec.data = lr->data;\n") >> CFILE;
+			printf("#endif\n") >> CFILE;
+			printf("\t}\n") >> CFILE;
+		} else {
+			write_malloc("\t", "logrec.data", "logrec.size", CFILE)
+			printf("\tbp = logrec.data;\n\n") >> CFILE;
+		}
+		printf("\tif (npad > 0)\n") >> CFILE;
+		printf("\t\tmemset((u_int8_t *)logrec.data + logrec.size ") \
+		    >> CFILE;
+		printf("- npad, 0, npad);\n\n") >> CFILE;
+		printf("\tbp = logrec.data;\n\n") >> CFILE;
+
+		# Copy args into buffer
+		printf("\tmemcpy(bp, &rectype, sizeof(rectype));\n") >> CFILE;
+		printf("\tbp += sizeof(rectype);\n\n") >> CFILE;
+		printf("\tmemcpy(bp, &txn_num, sizeof(txn_num));\n") >> CFILE;
+		printf("\tbp += sizeof(txn_num);\n\n") >> CFILE;
+		printf("\tmemcpy(bp, lsnp, sizeof(DB_LSN));\n") >> CFILE;
+		printf("\tbp += sizeof(DB_LSN);\n\n") >> CFILE;
+	} else {
+		# If we're logging a DB handle, make sure we have a log
+		# file ID for it.
+		db_handle_id_function(modes, nvars);
+
+		printf("\tbp = buf;\n") >> CFILE;
+		printf("\tendbuf = bp + max;\n\n") >> CFILE
+	}
+
+	for (i = 0; i < nvars; i++) {
+		if (modes[i] == "ARG" || modes[i] == "TIME") {
 			printf("\tuinttmp = (u_int32_t)%s;\n", \
 			    vars[i]) >> CFILE;
+			if (!not_buf) {
+				printf(\
+				    "\tif (bp + sizeof(uinttmp) > endbuf)\n") \
+				    >> CFILE;
+				printf("\t\treturn (ENOMEM);\n") >> CFILE;
+			}
 			printf("\tmemcpy(bp, &uinttmp, sizeof(uinttmp));\n") \
 			    >> CFILE;
 			printf("\tbp += sizeof(uinttmp);\n\n") >> CFILE;
-		} else if (modes[i] == "DBT" || modes[i] == "PGDBT") {
+		} else if (modes[i] == "DBT" ||  \
+		     modes[i] == "LOCKS" || modes[i] == "PGDBT") {
 			printf("\tif (%s == NULL) {\n", vars[i]) >> CFILE;
 			printf("\t\tzero = 0;\n") >> CFILE;
+			if (!not_buf) {
+				printf(\
+			    "\t\tif (bp + sizeof(u_int32_t) > endbuf)\n") \
+				    >> CFILE;
+				printf("\t\t\treturn (ENOMEM);\n") >> CFILE;
+			}
 			printf("\t\tmemcpy(bp, &zero, sizeof(u_int32_t));\n") \
 				>> CFILE;
 			printf("\t\tbp += sizeof(u_int32_t);\n") >> CFILE;
 			printf("\t} else {\n") >> CFILE;
+			if (!not_buf) {
+				printf(\
+			    "\t\tif (bp + sizeof(%s->size) > endbuf)\n", \
+				    vars[i]) >> CFILE;
+				printf("\t\t\treturn (ENOMEM);\n") >> CFILE;
+			}
 			printf("\t\tmemcpy(bp, &%s->size, ", vars[i]) >> CFILE;
 			printf("sizeof(%s->size));\n", vars[i]) >> CFILE;
 			printf("\t\tbp += sizeof(%s->size);\n", vars[i]) \
 			    >> CFILE;
+			if (!not_buf) {
+				printf("\t\tif (bp + %s->size > endbuf)\n", \
+				    vars[i]) >> CFILE;
+				printf("\t\t\treturn (ENOMEM);\n") >> CFILE;
+			}
 			printf("\t\tmemcpy(bp, %s->data, %s->size);\n", \
 			    vars[i], vars[i]) >> CFILE;
 			printf("\t\tbp += %s->size;\n\t}\n\n", \
 			    vars[i]) >> CFILE;
 		} else if (modes[i] == "DB") {
-			# We need to log a DB handle.  To do this, we
-			# actually just log its fileid;  from that, we'll
-			# be able to acquire an open handle at recovery time.
-			printf("\tDB_ASSERT(dbp->log_filename != NULL);\n") \
-			    >> CFILE;
-			printf("\tif (dbp->log_filename->id == ") >> CFILE;
-			printf("DB_LOGFILEID_INVALID &&\n\t    ") >> CFILE
-			printf("(ret = __dbreg_lazy_id(dbp)) != 0)\n") \
-			    >> CFILE;
-			printf("\t\treturn (ret);\n\n") >> CFILE;
-
 			printf("\tuinttmp = ") >> CFILE;
 			printf("(u_int32_t)dbp->log_filename->id;\n") >> CFILE;
 			printf("\tmemcpy(bp, &uinttmp, sizeof(uinttmp));\n") \
 			    >> CFILE;
 			printf("\tbp += sizeof(uinttmp);\n\n") >> CFILE;
 		} else { # POINTER
+			if (!not_buf) {
+				printf("\tif (bp + %s > endbuf)\n", \
+				    sizes[i]) >> CFILE;
+				printf("\t\treturn (ENOMEM);\n") >> CFILE;
+			}
 			printf("\tif (%s != NULL)\n", vars[i]) >> CFILE;
 			printf("\t\tmemcpy(bp, %s, %s);\n", vars[i], \
 			    sizes[i]) >> CFILE;
@@ -486,140 +588,267 @@ function log_function() {
 	# Error checking.  User code won't have DB_ASSERT available, but
 	# this is a pretty unlikely assertion anyway, so we just leave it out
 	# rather than requiring assert.h.
-	if (dbprivate) {
-		printf("\tDB_ASSERT((u_int32_t)") >> CFILE;
-		printf("(bp - (u_int8_t *)logrec.data) <= logrec.size);\n") \
-		    >> CFILE;
-	}
+	if (not_buf) {
+		if (dbprivate) {
+			printf("\tDB_ASSERT((u_int32_t)") >> CFILE;
+			printf("(bp - (u_int8_t *)logrec.data) ") >> CFILE;
+			printf("<= logrec.size);\n\n") >> CFILE;
+			# Save the log record off in the txn's linked list,
+			# or do log call.
+			# We didn't call the crypto alignment function when
+			# we created this log record (because we don't have
+			# the right header files to find the function), so
+			# we have to copy the log record to make sure the
+			# alignment is correct.
+			printf("\tif (is_durable || txnid == NULL) {\n") \
+			    >> CFILE;
+			# Output the log record and update the return LSN.
+			printf("\t\tif ((ret = __log_put(dbenv, rlsnp,") \
+			    >> CFILE;
+			printf("(DBT *)&logrec,\n") >> CFILE;
+			printf("\t\t    flags | DB_LOG_NOCOPY)) == 0") >> CFILE;
+			printf(" && txnid != NULL) {\n") >> CFILE;
+			printf("\t\t\ttxnid->last_lsn = *rlsnp;\n") >> CFILE;
+
+			printf("\t\t\tif (rlsnp != ret_lsnp)\n") >> CFILE;
+			printf("\t\t\t\t *ret_lsnp = *rlsnp;\n") >> CFILE;
+			printf("\t\t}\n\t} else {\n") >> CFILE;
+			printf("#ifdef DIAGNOSTIC\n") >> CFILE;
+
+			# Add the debug bit if we are logging a ND record.
+			printf("\t\t/*\n") >> CFILE;
+			printf("\t\t * Set the debug bit if we are") >> CFILE;
+			printf(" going to log non-durable\n") >> CFILE;
+			printf("\t\t * transactions so they will be ignored") \
+			    >> CFILE;
+			printf(" by recovery.\n") >> CFILE;
+			printf("\t\t */\n") >> CFILE;
+			printf("\t\tmemcpy(lr->data, logrec.data, ") >> CFILE
+			printf("logrec.size);\n") >> CFILE;
+			printf("\t\trectype |= DB_debug_FLAG;\n") >> CFILE;
+			printf("\t\tmemcpy(") >> CFILE
+			printf("logrec.data, &rectype, sizeof(rectype));\n\n") \
+			    >> CFILE;
+			# Output the log record.
+			printf("\t\tret = __log_put(dbenv,\n") >> CFILE;
+			printf("\t\t    rlsnp, (DBT *)&logrec, ") >> CFILE;
+			printf("flags | DB_LOG_NOCOPY);\n") >> CFILE;
+			printf("#else\n") >> CFILE;
+			printf("\t\tret = 0;\n") >> CFILE;
+			printf("#endif\n") >> CFILE;
+			# Add a ND record to the txn list.
+			printf("\t\tSTAILQ_INSERT_HEAD(&txnid") >> CFILE;
+			printf("->logs, lr, links);\n") >> CFILE;
+			# Update the return LSN.
+			printf("\t\tLSN_NOT_LOGGED(*ret_lsnp);\n") >> CFILE;
+			printf("\t}\n\n") >> CFILE;
+		} else {
+			printf("\tif ((ret = dbenv->log_put(dbenv, rlsnp,") >> CFILE;
+			printf(" (DBT *)&logrec,\n") >> CFILE;
+			printf("\t    flags | DB_LOG_NOCOPY)) == 0") >> CFILE;
+			printf(" && txnid != NULL) {\n") >> CFILE;
+
+                	# Update the transactions last_lsn.
+			printf("\t\ttxnid->last_lsn = *rlsnp;\n") >> CFILE;
+			printf("\t\tif (rlsnp != ret_lsnp)\n") >> CFILE;
+			printf("\t\t\t *ret_lsnp = *rlsnp;\n") >> CFILE;
+			printf("\t}\n") >> CFILE;
 
-	# Issue log call
-	# We didn't call the crypto alignment function when we created this
-	# log record (because we don't have the right header files to find
-	# the function), so we have to copy the log record to make sure the
-	# alignment is correct.
-	printf(\
-	    "\tret = dbenv->log_put(dbenv,\n\t   ret_lsnp, (DBT *)&logrec, ") \
-	    >> CFILE;
-	if (dbprivate) {
-		printf("flags | DB_NOCOPY);\n") >> CFILE;
+		}
+		# If out of disk space log writes may fail.  If we are debugging
+		# that print out which records did not make it to disk.
+		printf("#ifdef LOG_DIAGNOSTIC\n") >> CFILE
+		printf("\tif (ret != 0)\n") >> CFILE;
+		printf("\t\t(void)%s_print(dbenv,\n", funcname) >> CFILE;
+		printf("\t\t    (DBT *)&logrec, ret_lsnp, NULL, NULL);\n") \
+		    >> CFILE
+		printf("#endif\n\n") >> CFILE
+		# Free and return
+		if (dbprivate) {
+			printf("#ifdef DIAGNOSTIC\n") >> CFILE
+			write_free("\t", "logrec.data", CFILE)
+			printf("#else\n") >> CFILE
+			printf("\tif (is_durable || txnid == NULL)\n") >> CFILE;
+			write_free("\t\t", "logrec.data", CFILE)
+			printf("#endif\n") >> CFILE
+		} else {
+			write_free("\t", "logrec.data", CFILE)
+		}
 	} else {
-		printf("flags);\n") >> CFILE;
+		printf("\t*lenp = (u_int32_t)(bp - buf);\n\n") >> CFILE
 	}
 
-	# Update the transactions last_lsn
-	printf("\tif (txnid != NULL && ret == 0)\n") >> CFILE;
-	printf("\t\ttxnid->last_lsn = *ret_lsnp;\n") >> CFILE;
-
-	# If out of disk space log writes may fail.  If we are debugging
-	# that print out which records did not make it to disk.
-	printf("#ifdef LOG_DIAGNOSTIC\n") >> CFILE
-	printf("\tif (ret != 0)\n") >> CFILE;
-	printf("\t\t(void)%s_print(dbenv,\n", funcname) >> CFILE;
-	printf("\t\t    (DBT *)&logrec, ret_lsnp, NULL, NULL);\n") >> CFILE
-	printf("#endif\n") >> CFILE
-
-	# Free and return
-	write_free("logrec.data", CFILE)
 	printf("\treturn (ret);\n}\n\n") >> CFILE;
 }
 
-function print_function() {
+# If we're logging a DB handle, make sure we have a log
+# file ID for it.
+function db_handle_id_function(modes, n)
+{
+	for (i = 0; i < n; i++)
+		if (modes[i] == "DB") {
+			# We actually log the DB handle's fileid; from
+			# that ID we're able to acquire an open handle
+			# at recovery time.
+			printf(\
+		    "\tDB_ASSERT(dbp->log_filename != NULL);\n") \
+			    >> CFILE;
+			printf("\tif (dbp->log_filename->id == ") \
+			    >> CFILE;
+			printf("DB_LOGFILEID_INVALID &&\n\t    ") \
+			    >> CFILE
+			printf("(ret = __dbreg_lazy_id(dbp)) != 0)\n") \
+			    >> CFILE
+			printf("\t\treturn (ret);\n\n") >> CFILE;
+			break;
+		}
+}
+
+function print_function()
+{
 	# Write the print function; function prototype
 	p[1] = sprintf("int %s_print", funcname);
 	p[2] = " ";
 	p[3] = "__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));";
 	p[4] = "";
-	proto_format(p);
+	proto_format(p, PFILE);
 
 	# Function declaration
-	printf("int\n%s_print(dbenv, ", funcname) >> CFILE;
-	printf("dbtp, lsnp, notused2, notused3)\n") >> CFILE;
-	printf("\tDB_ENV *dbenv;\n") >> CFILE;
-	printf("\tDBT *dbtp;\n") >> CFILE;
-	printf("\tDB_LSN *lsnp;\n") >> CFILE;
-	printf("\tdb_recops notused2;\n\tvoid *notused3;\n{\n") >> CFILE;
+	printf("int\n%s_print(dbenv, ", funcname) >> PFILE;
+	printf("dbtp, lsnp, notused2, notused3)\n") >> PFILE;
+	printf("\tDB_ENV *dbenv;\n") >> PFILE;
+	printf("\tDBT *dbtp;\n") >> PFILE;
+	printf("\tDB_LSN *lsnp;\n") >> PFILE;
+	printf("\tdb_recops notused2;\n\tvoid *notused3;\n{\n") >> PFILE;
 
 	# Locals
-	printf("\t%s_args *argp;\n", funcname) >> CFILE;
+	printf("\t%s_args *argp;\n", funcname) >> PFILE;
+	for (i = 0; i < nvars; i ++)
+		if (modes[i] == "TIME") {
+			printf("\tstruct tm *lt;\n") >> PFILE
+			printf("\ttime_t timeval;\n") >> PFILE
+			break;
+		}
 	for (i = 0; i < nvars; i ++)
 		if (modes[i] == "DBT" || modes[i] == "PGDBT") {
-			printf("\tu_int32_t i;\n") >> CFILE
-			printf("\tint ch;\n") >> CFILE
+			printf("\tu_int32_t i;\n") >> PFILE
+			printf("\tint ch;\n") >> PFILE
 			break;
 		}
-
-	printf("\tint ret;\n\n") >> CFILE;
+	printf("\tint ret;\n\n") >> PFILE;
 
 	# Get rid of complaints about unused parameters.
-	printf("\tnotused2 = DB_TXN_ABORT;\n\tnotused3 = NULL;\n\n") >> CFILE;
+	printf("\tnotused2 = DB_TXN_ABORT;\n\tnotused3 = NULL;\n\n") >> PFILE;
 
 	# Call read routine to initialize structure
 	printf("\tif ((ret = %s_read(dbenv, dbtp->data, &argp)) != 0)\n", \
-	    funcname) >> CFILE;
-	printf("\t\treturn (ret);\n") >> CFILE;
+	    funcname) >> PFILE;
+	printf("\t\treturn (ret);\n") >> PFILE;
 
 	# Print values in every record
-	printf("\t(void)printf(\n\t    \"[%%lu][%%lu]%s: ", funcname) >> CFILE;
-	printf("rec: %%lu txnid %%lx ") >> CFILE;
-	printf("prevlsn [%%lu][%%lu]\\n\",\n") >> CFILE;
-	printf("\t    (u_long)lsnp->file,\n") >> CFILE;
-	printf("\t    (u_long)lsnp->offset,\n") >> CFILE;
-	printf("\t    (u_long)argp->type,\n") >> CFILE;
-	printf("\t    (u_long)argp->txnid->txnid,\n") >> CFILE;
-	printf("\t    (u_long)argp->prev_lsn.file,\n") >> CFILE;
-	printf("\t    (u_long)argp->prev_lsn.offset);\n") >> CFILE;
+	printf("\t(void)printf(\n\t    \"[%%lu][%%lu]%s%%s: ",\
+	     funcname) >> PFILE;
+	printf("rec: %%lu txnid %%lx ") >> PFILE;
+	printf("prevlsn [%%lu][%%lu]\\n\",\n") >> PFILE;
+	printf("\t    (u_long)lsnp->file,\n") >> PFILE;
+	printf("\t    (u_long)lsnp->offset,\n") >> PFILE;
+	printf("\t    (argp->type & DB_debug_FLAG) ? \"_debug\" : \"\",\n") \
+	     >> PFILE;
+	printf("\t    (u_long)argp->type,\n") >> PFILE;
+	printf("\t    (u_long)argp->txnid->txnid,\n") >> PFILE;
+	printf("\t    (u_long)argp->prev_lsn.file,\n") >> PFILE;
+	printf("\t    (u_long)argp->prev_lsn.offset);\n") >> PFILE;
 
 	# Now print fields of argp
 	for (i = 0; i < nvars; i ++) {
-		printf("\t(void)printf(\"\\t%s: ", vars[i]) >> CFILE;
+		if (modes[i] == "TIME") {
+			printf("\ttimeval = (time_t)argp->%s;\n",
+			    vars[i]) >> PFILE;
+			printf("\tlt = localtime(&timeval);\n") >> PFILE;
+			printf("\t(void)printf(\n\t    \"\\t%s: ",
+			    vars[i]) >> PFILE;
+		} else
+			printf("\t(void)printf(\"\\t%s: ", vars[i]) >> PFILE;
 
 		if (modes[i] == "DBT" || modes[i] == "PGDBT") {
-			printf("\");\n") >> CFILE;
-			printf("\tfor (i = 0; i < ") >> CFILE;
-			printf("argp->%s.size; i++) {\n", vars[i]) >> CFILE;
+			printf("\");\n") >> PFILE;
+			printf("\tfor (i = 0; i < ") >> PFILE;
+			printf("argp->%s.size; i++) {\n", vars[i]) >> PFILE;
 			printf("\t\tch = ((u_int8_t *)argp->%s.data)[i];\n", \
-			    vars[i]) >> CFILE;
-			printf("\t\tprintf(isprint(ch) || ch == 0x0a") >> CFILE;
-			printf(" ? \"%%c\" : \"%%#x \", ch);\n") >> CFILE;
-			printf("\t}\n\t(void)printf(\"\\n\");\n") >> CFILE;
+			    vars[i]) >> PFILE;
+			printf("\t\tprintf(isprint(ch) || ch == 0x0a") >> PFILE;
+			printf(" ? \"%%c\" : \"%%#x \", ch);\n") >> PFILE;
+			printf("\t}\n\t(void)printf(\"\\n\");\n") >> PFILE;
 		} else if (types[i] == "DB_LSN *") {
 			printf("[%%%s][%%%s]\\n\",\n", \
-			    formats[i], formats[i]) >> CFILE;
+			    formats[i], formats[i]) >> PFILE;
 			printf("\t    (u_long)argp->%s.file,", \
-			    vars[i]) >> CFILE;
+			    vars[i]) >> PFILE;
 			printf(" (u_long)argp->%s.offset);\n", \
-			    vars[i]) >> CFILE;
+			    vars[i]) >> PFILE;
+		} else if (modes[i] == "TIME") {
+			# Time values are displayed in two ways: the standard
+			# string returned by ctime, and in the input format
+			# expected by db_recover -t.
+			printf(\
+	    "%%%s (%%.24s, 20%%02lu%%02lu%%02lu%%02lu%%02lu.%%02lu)\\n\",\n", \
+			    formats[i]) >> PFILE;
+			printf("\t    (long)argp->%s, ", vars[i]) >> PFILE;
+			printf("ctime(&timeval),", vars[i]) >> PFILE;
+			printf("\n\t    (u_long)lt->tm_year - 100, ") >> PFILE;
+			printf("(u_long)lt->tm_mon+1,") >> PFILE;
+			printf("\n\t    (u_long)lt->tm_mday, ") >> PFILE;
+			printf("(u_long)lt->tm_hour,") >> PFILE;
+			printf("\n\t    (u_long)lt->tm_min, ") >> PFILE;
+			printf("(u_long)lt->tm_sec);\n") >> PFILE;
+		} else if (modes[i] == "LOCKS") {
+			printf("\\n\");\n") >> PFILE;
+			printf("\t__lock_list_print(dbenv, &argp->locks);\n") \
+				>> PFILE;
 		} else {
 			if (formats[i] == "lx")
-				printf("0x") >> CFILE;
-			printf("%%%s\\n\", ", formats[i]) >> CFILE;
+				printf("0x") >> PFILE;
+			printf("%%%s\\n\", ", formats[i]) >> PFILE;
 			if (formats[i] == "lx" || formats[i] == "lu")
-				printf("(u_long)") >> CFILE;
+				printf("(u_long)") >> PFILE;
 			if (formats[i] == "ld")
-				printf("(long)") >> CFILE;
-			printf("argp->%s);\n", vars[i]) >> CFILE;
+				printf("(long)") >> PFILE;
+			printf("argp->%s);\n", vars[i]) >> PFILE;
 		}
 	}
-	printf("\t(void)printf(\"\\n\");\n") >> CFILE;
-	write_free("argp", CFILE);
-	printf("\treturn (0);\n") >> CFILE;
-	printf("}\n\n") >> CFILE;
+	printf("\t(void)printf(\"\\n\");\n") >> PFILE;
+	write_free("\t", "argp", PFILE);
+	printf("\treturn (0);\n") >> PFILE;
+	printf("}\n\n") >> PFILE;
 }
 
-function read_function() {
+function read_function()
+{
 	# Write the read function; function prototype
-	p[1] = sprintf("int %s_read __P((DB_ENV *, void *,", funcname);
+	if (not_buf)
+		p[1] = sprintf("int %s_read __P((DB_ENV *, void *,", funcname);
+	else
+		p[1] = sprintf("int %s_read __P((DB_ENV *, void *, void **,", \
+		    funcname);
 	p[2] = " ";
 	p[3] = sprintf("%s_args **));", funcname);
 	p[4] = "";
-	proto_format(p);
+	proto_format(p, CFILE);
 
 	# Function declaration
-	printf("int\n%s_read(dbenv, recbuf, argpp)\n", funcname) >> CFILE;
+	if (not_buf)
+		printf("int\n%s_read(dbenv, recbuf, argpp)\n", funcname) \
+		    >> CFILE;
+	else
+		printf(\
+		    "int\n%s_read(dbenv, recbuf, nextp, argpp)\n", funcname) \
+		    >> CFILE;
 
 	# Now print the parameters
 	printf("\tDB_ENV *dbenv;\n") >> CFILE;
 	printf("\tvoid *recbuf;\n") >> CFILE;
+	if (!not_buf)
+		printf("\tvoid **nextp;\n") >> CFILE;
 	printf("\t%s_args **argpp;\n", funcname) >> CFILE;
 
 	# Function body and local decls
@@ -637,26 +866,37 @@ function read_function() {
 		printf("\n\tdbenv = NULL;\n") >> CFILE;
 	}
 
-	malloc_size = sprintf("sizeof(%s_args) + sizeof(DB_TXN)", funcname)
-	write_malloc("argp", malloc_size, CFILE)
+	if (not_buf) {
+		malloc_size = sprintf("sizeof(%s_args) + sizeof(DB_TXN)", \
+		    funcname)
+	} else {
+		malloc_size = sprintf("sizeof(%s_args)", funcname)
+	}
+	write_malloc("\t", "argp", malloc_size, CFILE)
 
 	# Set up the pointers to the txnid.
-	printf("\targp->txnid = (DB_TXN *)&argp[1];\n\n") >> CFILE;
+	printf("\tbp = recbuf;\n") >> CFILE;
 
-	# First get the record type, prev_lsn, and txnid fields.
+	if (not_buf) {
+		printf("\targp->txnid = (DB_TXN *)&argp[1];\n\n") >> CFILE;
 
-	printf("\tbp = recbuf;\n") >> CFILE;
-	printf("\tmemcpy(&argp->type, bp, sizeof(argp->type));\n") >> CFILE;
-	printf("\tbp += sizeof(argp->type);\n\n") >> CFILE;
-	printf("\tmemcpy(&argp->txnid->txnid,  bp, ") >> CFILE;
-	printf("sizeof(argp->txnid->txnid));\n") >> CFILE;
-	printf("\tbp += sizeof(argp->txnid->txnid);\n\n") >> CFILE;
-	printf("\tmemcpy(&argp->prev_lsn, bp, sizeof(DB_LSN));\n") >> CFILE;
-	printf("\tbp += sizeof(DB_LSN);\n\n") >> CFILE;
+		# First get the record type, prev_lsn, and txnid fields.
+
+		printf("\tmemcpy(&argp->type, bp, sizeof(argp->type));\n") \
+		    >> CFILE;
+		printf("\tbp += sizeof(argp->type);\n\n") >> CFILE;
+		printf("\tmemcpy(&argp->txnid->txnid,  bp, ") >> CFILE;
+		printf("sizeof(argp->txnid->txnid));\n") >> CFILE;
+		printf("\tbp += sizeof(argp->txnid->txnid);\n\n") >> CFILE;
+		printf("\tmemcpy(&argp->prev_lsn, bp, sizeof(DB_LSN));\n") \
+		    >> CFILE;
+		printf("\tbp += sizeof(DB_LSN);\n\n") >> CFILE;
+	}
 
 	# Now get rest of data.
 	for (i = 0; i < nvars; i ++) {
-		if (modes[i] == "DBT" || modes[i] == "PGDBT") {
+		if (modes[i] == "DBT" || \
+		    modes[i] == "LOCKS" || modes[i] == "PGDBT") {
 			printf("\tmemset(&argp->%s, 0, sizeof(argp->%s));\n", \
 			    vars[i], vars[i]) >> CFILE;
 			printf("\tmemcpy(&argp->%s.size, ", vars[i]) >> CFILE;
@@ -664,8 +904,8 @@ function read_function() {
 			printf("\tbp += sizeof(u_int32_t);\n") >> CFILE;
 			printf("\targp->%s.data = bp;\n", vars[i]) >> CFILE;
 			printf("\tbp += argp->%s.size;\n", vars[i]) >> CFILE;
-		} else if (modes[i] == "ARG" || modes[i] == "WRLOCK" || \
-		    modes[i] == "WRLOCKNZ" || modes[i] == "DB") {
+		} else if (modes[i] == "ARG" || modes[i] == "TIME" ||
+		    modes[i] == "DB") {
 			printf("\tmemcpy(&uinttmp, bp, sizeof(uinttmp));\n") \
 			    >> CFILE;
 			printf("\targp->%s = (%s)uinttmp;\n", vars[i], \
@@ -680,118 +920,17 @@ function read_function() {
 	}
 
 	# Free and return
+	if (!not_buf)
+		printf("\t*nextp = bp;\n") >> CFILE;
 	printf("\t*argpp = argp;\n") >> CFILE;
 	printf("\treturn (0);\n}\n\n") >> CFILE;
 }
 
-function getpgnos_function() {
-	# Write the getpgnos function;  function prototype
-	p[1] = sprintf("int %s_getpgnos", funcname);
-	p[2] = " ";
-	p[3] = "__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));";
-	p[4] = "";
-	proto_format(p);
-
-	# Function declaration
-	printf("int\n%s_getpgnos(dbenv, ", funcname) >> CFILE;
-	printf("rec, lsnp, notused1, summary)\n") >> CFILE;
-	printf("\tDB_ENV *dbenv;\n") >> CFILE;
-	printf("\tDBT *rec;\n") >> CFILE;
-	printf("\tDB_LSN *lsnp;\n") >> CFILE;
-	printf("\tdb_recops notused1;\n") >> CFILE;
-	printf("\tvoid *summary;\n{\n") >> CFILE;
-
-	# If there are no locks, return this fact.
-	if (nlocks == 0) {
-		printf("\tTXN_RECS *t;\n") >> CFILE;
-		printf("\tint ret;\n") >> CFILE;
-		printf("\tCOMPQUIET(rec, NULL);\n") >> CFILE;
-		printf("\tCOMPQUIET(notused1, DB_TXN_ABORT);\n") >> CFILE;
-
-		printf("\n\tt = (TXN_RECS *)summary;\n") >> CFILE;
-		printf("\n\tif ((ret = __rep_check_alloc(dbenv, ") >> CFILE;
-		printf("t, 1)) != 0)\n") >> CFILE;
-		printf("\t\treturn (ret);\n") >> CFILE;
-
-		printf("\n\tt->array[t->npages].flags = LSN_PAGE_NOLOCK;\n") \
-			>> CFILE;
-		printf("\tt->array[t->npages].lsn = *lsnp;\n") >> CFILE;
-		printf("\tt->array[t->npages].fid = DB_LOGFILEID_INVALID;\n") \
-			>> CFILE;
-		printf("\tmemset(&t->array[t->npages].pgdesc, 0,\n") >> CFILE;
-		printf("\t    sizeof(t->array[t->npages].pgdesc));\n") >> CFILE;
-		printf("\n\tt->npages++;\n") >> CFILE;
-
-		printf("\n") >> CFILE;
-		printf("\treturn (0);\n") >> CFILE;
-		printf("}\n\n") >> CFILE;
-		return;
-	}
-
-	# Locals
-	printf("\tDB *dbp;\n") >> CFILE;
-	printf("\tTXN_RECS *t;\n") >> CFILE;
-	printf("\t%s_args *argp;\n", funcname) >> CFILE;
-	printf("\tu_int32_t ret;\n\n") >> CFILE;
-
-	# Shut up compiler.
-	printf("\tCOMPQUIET(notused1, DB_TXN_ABORT);\n\n") >> CFILE;
-
-	printf("\targp = NULL;\n") >> CFILE;
-	printf("\tt = (TXN_RECS *)summary;\n\n") >> CFILE;
-
-	printf("\tif ((ret = %s_read(dbenv, rec->data, &argp)) != 0)\n", \
-		funcname) >> CFILE;
-	printf("\t\treturn (ret);\n") >> CFILE;
-
-	# Get file ID.
-	printf("\n\tif ((ret = __dbreg_id_to_db(dbenv,\n\t    ") >> CFILE;
-	printf("argp->txnid, &dbp, argp->fileid, 0)) != 0)\n") >> CFILE;
-	printf("\t\tgoto err;\n") >> CFILE;
-
-	printf("\n\tif ((ret = __rep_check_alloc(dbenv, t, %d)) != 0)\n", \
-		nlocks) >> CFILE;
-	printf("\t\tgoto err;\n\n") >> CFILE;
-
-	for (i = 1; i <= nlocks; i++) {
-		if (lock_if_zero[i]) {
-			indent = "\t";
-		} else {
-			indent = "\t\t";
-			printf("\tif (argp->%s != PGNO_INVALID) {\n", \
-				lock_pgnos[i]) >> CFILE;
-		}
-		printf("%st->array[t->npages].flags = 0;\n", indent) >> CFILE;
-		printf("%st->array[t->npages].fid = argp->fileid;\n", indent) \
-		    >> CFILE;
-		printf("%st->array[t->npages].lsn = *lsnp;\n", indent) >> CFILE;
-		printf("%st->array[t->npages].pgdesc.pgno = argp->%s;\n", \
-			indent, lock_pgnos[i]) >> CFILE;
-		printf("%st->array[t->npages].pgdesc.type = DB_PAGE_LOCK;\n", \
-			indent) >> CFILE;
-		printf("%smemcpy(t->array[t->npages].pgdesc.fileid, ", indent) \
-			>> CFILE;
-		printf("dbp->fileid,\n%s    DB_FILE_ID_LEN);\n", \
-			indent, indent) >> CFILE;
-		printf("%st->npages++;\n", indent) >> CFILE;
-		if (!lock_if_zero[i]) {
-			printf("\t}\n") >> CFILE;
-		}
-	}
-
-	printf("\nerr:\tif (argp != NULL)\n") >> CFILE;
-	write_free("argp", CFILE);
-
-	printf("\treturn (ret);\n") >> CFILE;
-
-	printf("}\n\n") >> CFILE;
-}
-
 # proto_format --
 #	Pretty-print a function prototype.
-function proto_format(p)
+function proto_format(p, fp)
 {
-	printf("/*\n") >> CFILE;
+	printf("/*\n") >> fp;
 
 	s = "";
 	for (i = 1; i in p; ++i)
@@ -799,46 +938,44 @@ function proto_format(p)
 
 	t = " * PUBLIC: "
 	if (length(s) + length(t) < 80)
-		printf("%s%s", t, s) >> CFILE;
+		printf("%s%s", t, s) >> fp;
 	else {
 		split(s, p, "__P");
 		len = length(t) + length(p[1]);
-		printf("%s%s", t, p[1]) >> CFILE
+		printf("%s%s", t, p[1]) >> fp
 
 		n = split(p[2], comma, ",");
 		comma[1] = "__P" comma[1];
 		for (i = 1; i <= n; i++) {
 			if (len + length(comma[i]) > 70) {
-				printf("\n * PUBLIC:    ") >> CFILE;
+				printf("\n * PUBLIC:    ") >> fp;
 				len = 0;
 			}
-			printf("%s%s", comma[i], i == n ? "" : ",") >> CFILE;
+			printf("%s%s", comma[i], i == n ? "" : ",") >> fp;
 			len += length(comma[i]) + 2;
 		}
 	}
-	printf("\n */\n") >> CFILE;
+	printf("\n */\n") >> fp;
 	delete p;
 }
 
-function write_malloc(ptr, size, file)
+function write_malloc(tab, ptr, size, file)
 {
 	if (dbprivate) {
-		printf("\tif ((ret = ") >> file;
-		printf(\
-		    "__os_malloc(dbenv,\n\t    " size ", &" ptr ")) != 0)\n") \
-		    >> file
-		printf("\t\treturn (ret);\n\n") >> file;
+		print(tab "if ((ret = __os_malloc(dbenv,") >> file
+		print(tab "    " size ", &" ptr ")) != 0)") >> file
+		print(tab "\treturn (ret);") >> file;
 	} else {
-		printf("\tif ((" ptr " = malloc(" size ")) == NULL)\n") >> file
-		printf("\t\treturn (ENOMEM);\n\n") >> file
+		print(tab "if ((" ptr " = malloc(" size ")) == NULL)") >> file
+		print(tab "\treturn (ENOMEM);") >> file
 	}
 }
 
-function write_free(ptr, file)
+function write_free(tab, ptr, file)
 {
 	if (dbprivate) {
-		printf("\t__os_free(dbenv, " ptr ");\n") >> file
+		print(tab "__os_free(dbenv, " ptr ");") >> file
 	} else {
-		printf("\tfree(" ptr ");\n") >> file
+		print(tab "free(" ptr ");") >> file
 	}
 }
diff --git a/storage/bdb/dist/gen_rpc.awk b/storage/bdb/dist/gen_rpc.awk
index 03975d7321b93feaad0535ae0b18434d7d3f5a68..7eee77b3df2df4c58161393f73b70c804acb0478 100644
--- a/storage/bdb/dist/gen_rpc.awk
+++ b/storage/bdb/dist/gen_rpc.awk
@@ -1,5 +1,5 @@
 #
-# $Id: gen_rpc.awk,v 11.50 2002/07/02 19:26:57 sue Exp $
+# $Id: gen_rpc.awk,v 11.58 2004/08/19 20:28:37 mjc Exp $
 # Awk script for generating client/server RPC code.
 #
 # This awk script generates most of the RPC routines for DB client/server
@@ -14,7 +14,6 @@
 #	xidsize		-- size of GIDs
 #	client_file	-- the C source file being created for client code
 #	ctmpl_file	-- the C template file being created for client code
-#	sed_file	-- the sed file created to alter server proc code
 #	server_file	-- the C source file being created for server code
 #	stmpl_file	-- the C template file being created for server code
 #	xdr_file	-- the XDR message file created
@@ -23,15 +22,13 @@
 BEGIN {
 	if (major == "" || minor == "" || xidsize == "" ||
 	    client_file == "" || ctmpl_file == "" ||
-	    sed_file == "" || server_file == "" ||
-	    stmpl_file == "" || xdr_file == "") {
+	    server_file == "" || stmpl_file == "" || xdr_file == "") {
 		print "Usage: gen_rpc.awk requires these variables be set:"
 		print "\tmajor\t-- Major version number"
 		print "\tminor\t-- Minor version number"
 		print "\txidsize\t-- GID size"
 		print "\tclient_file\t-- the client C source file being created"
 		print "\tctmpl_file\t-- the client template file being created"
-		print "\tsed_file\t-- the sed command file being created"
 		print "\tserver_file\t-- the server C source file being created"
 		print "\tstmpl_file\t-- the server template file being created"
 		print "\txdr_file\t-- the XDR message file being created"
@@ -51,32 +48,24 @@ BEGIN {
 	printf("/* Do not edit: automatically built by gen_rpc.awk. */\n") \
 	    > SFILE
 
-	# Server procedure template and a sed file to massage an existing
-	# template source file to change args.
-	# SEDFILE should be same name as PFILE but .c
-	#
+	# Server procedure template.
 	PFILE = stmpl_file
-	SEDFILE = sed_file
-	printf("") > SEDFILE
-	printf("/* Do not edit: automatically built by gen_rpc.awk. */\n") \
-	    > PFILE
-
 	XFILE = xdr_file
 	printf("/* Do not edit: automatically built by gen_rpc.awk. */\n") \
 	    > XFILE
 	nendlist = 1;
 }
 END {
-	printf("#endif /* HAVE_RPC */\n") >> CFILE
-	printf("#endif /* HAVE_RPC */\n") >> TFILE
-	printf("program DB_RPC_SERVERPROG {\n") >> XFILE
-	printf("\tversion DB_RPC_SERVERVERS {\n") >> XFILE
+	if (error == 0) {
+		printf("program DB_RPC_SERVERPROG {\n") >> XFILE
+		printf("\tversion DB_RPC_SERVERVERS {\n") >> XFILE
 
-	for (i = 1; i < nendlist; ++i)
-		printf("\t\t%s;\n", endlist[i]) >> XFILE
+		for (i = 1; i < nendlist; ++i)
+			printf("\t\t%s;\n", endlist[i]) >> XFILE
 
-	printf("\t} = %d%03d;\n", major, minor) >> XFILE
-	printf("} = 351457;\n") >> XFILE
+		printf("\t} = %d%03d;\n", major, minor) >> XFILE
+		printf("} = 351457;\n") >> XFILE
+	}
 }
 
 /^[	 ]*BEGIN/ {
@@ -169,9 +158,34 @@ END {
 		retlist_type[rvars] = $5;
 	} else
 		retlist_type[rvars] = 0;
+	ret_isarg[rvars] = 0;
 
 	++rvars;
 }
+/^[	 ]*ARET/ {
+	ret_type[rvars] = $2;
+	rpc_type[nvars] = "IGNORE";
+	retc_type[rvars] = $3;
+	c_type[nvars] = sprintf("%s *", $3);
+	pr_type[nvars] = c_type[nvars];
+	retargs[rvars] = $4;
+	args[nvars] = sprintf("%sp", $4);
+	if (ret_type[rvars] == "LIST" || ret_type[rvars] == "DBT") {
+		xdr_free = 1;
+	}
+	func_arg[nvars] = 0;
+	if (ret_type[nvars] == "LIST") {
+		retlist_type[rvars] =  $5;
+		list_type[nvars] = $5;
+	} else {
+		retlist_type[rvars] = 0;
+		list_type[nvars] = 0;
+	}
+	ret_isarg[rvars] = 1;
+
+	++nvars;
+	++rvars;
+}
 /^[	 ]*END/ {
 	#
 	# =====================================================
@@ -180,33 +194,29 @@ END {
 	if (first == 0) {
 		printf("#include \"db_config.h\"\n") >> CFILE
 		printf("\n") >> CFILE
-		printf("#ifdef HAVE_RPC\n") >> CFILE
 		printf("#ifndef NO_SYSTEM_INCLUDES\n") >> CFILE
-		printf("#include <sys/types.h>\n\n") >> CFILE
+		printf("#include <sys/types.h>\n") >> CFILE
+		printf("\n") >> CFILE
 		printf("#include <rpc/rpc.h>\n") >> CFILE
-		printf("#include <rpc/xdr.h>\n") >> CFILE
 		printf("\n") >> CFILE
 		printf("#include <string.h>\n") >> CFILE
 		printf("#endif\n") >> CFILE
 		printf("\n") >> CFILE
+		printf("#include \"db_server.h\"\n") >> CFILE
+		printf("\n") >> CFILE
 		printf("#include \"db_int.h\"\n") >> CFILE
 		printf("#include \"dbinc/txn.h\"\n") >> CFILE
-		printf("\n") >> CFILE
-		printf("#include \"dbinc_auto/db_server.h\"\n") >> CFILE
 		printf("#include \"dbinc_auto/rpc_client_ext.h\"\n") >> CFILE
 		printf("\n") >> CFILE
 
 		printf("#include \"db_config.h\"\n") >> TFILE
 		printf("\n") >> TFILE
-		printf("#ifdef HAVE_RPC\n") >> TFILE
 		printf("#ifndef NO_SYSTEM_INCLUDES\n") >> TFILE
 		printf("#include <sys/types.h>\n") >> TFILE
-		printf("#include <rpc/rpc.h>\n") >> TFILE
 		printf("\n") >> TFILE
 		printf("#include <string.h>\n") >> TFILE
 		printf("#endif\n") >> TFILE
 		printf("#include \"db_int.h\"\n") >> TFILE
-		printf("#include \"dbinc_auto/db_server.h\"\n") >> TFILE
 		printf("#include \"dbinc/txn.h\"\n") >> TFILE
 		printf("\n") >> TFILE
 
@@ -216,13 +226,13 @@ END {
 		printf("#include <sys/types.h>\n") >> SFILE
 		printf("\n") >> SFILE
 		printf("#include <rpc/rpc.h>\n") >> SFILE
-		printf("#include <rpc/xdr.h>\n") >> SFILE
 		printf("\n") >> SFILE
 		printf("#include <string.h>\n") >> SFILE
 		printf("#endif\n") >> SFILE
 		printf("\n") >> SFILE
+		printf("#include \"db_server.h\"\n") >> SFILE
+		printf("\n") >> SFILE
 		printf("#include \"db_int.h\"\n") >> SFILE
-		printf("#include \"dbinc_auto/db_server.h\"\n") >> SFILE
 		printf("#include \"dbinc/db_server_int.h\"\n") >> SFILE
 		printf("#include \"dbinc_auto/rpc_server_ext.h\"\n") >> SFILE
 		printf("\n") >> SFILE
@@ -237,10 +247,10 @@ END {
 		printf("#include <string.h>\n") >> PFILE
 		printf("#endif\n") >> PFILE
 		printf("\n") >> PFILE
+		printf("#include \"db_server.h\"\n") >> PFILE
+		printf("\n") >> PFILE
 		printf("#include \"db_int.h\"\n") >> PFILE
-		printf("#include \"dbinc_auto/db_server.h\"\n") >> PFILE
 		printf("#include \"dbinc/db_server_int.h\"\n") >> PFILE
-		printf("#include \"dbinc_auto/rpc_server_ext.h\"\n") >> PFILE
 		printf("\n") >> PFILE
 
 		first = 1;
@@ -275,9 +285,9 @@ END {
 			printf("__dbcl_rpc_illegal(dbenv, name)\n") >> CFILE
 			printf("\tDB_ENV *dbenv;\n\tchar *name;\n") >> CFILE
 			printf("{\n\t__db_err(dbenv,") >> CFILE
-			printf(" \"%%s method meaningless in an RPC") >> CFILE
-			printf(" environment\", name);\n") >> CFILE
-			printf("\treturn (__db_eopnotsup(dbenv));\n") >> CFILE
+			printf(" \"%%s method unsupported in RPC") >> CFILE
+			printf(" environments\", name);\n") >> CFILE
+			printf("\treturn (DB_OPNOTSUP);\n") >> CFILE
 			printf("}\n\n") >> CFILE
 
 			first_nofunc = 1
@@ -285,6 +295,7 @@ END {
 		#
 		# Spit out PUBLIC prototypes.
 		#
+		delete p;
 		pi = 1;
 		p[pi++] = sprintf("int __dbcl_%s __P((", name);
 		p[pi++] = "";
@@ -293,9 +304,8 @@ END {
 			p[pi++] = ", ";
 		}
 		p[pi - 1] = "";
-		p[pi++] = "));";
-		p[pi] = "";
-		proto_format(p, 0, CFILE);
+		p[pi] = "));";
+		proto_format(p, CFILE);
 
 		#
 		# Spit out function name/args.
@@ -336,7 +346,7 @@ END {
 				printf("\tdbenv = %s->mgrp->dbenv;\n", \
 				    args[txn_idx]) >> CFILE
 			else if (mp_handle)
-				printf("\tdbenv = %s->dbmp->dbenv;\n", \
+				printf("\tdbenv = %s->dbenv;\n", \
 				    args[mp_idx]) >> CFILE
 			else
 				printf("\tdbenv = NULL;\n") >> CFILE
@@ -413,6 +423,7 @@ END {
 	# Generate the reply message
 	#
 	printf("struct __%s_reply {\n", name) >> XFILE
+	printf("\t/* num return vars: %d */\n", rvars) >> XFILE
 	printf("\tint status;\n") >> XFILE
 	for (i = 0; i < rvars; ++i) {
 		if (ret_type[i] == "ID") {
@@ -450,13 +461,9 @@ END {
 	#
 	# First spit out PUBLIC prototypes for server functions.
 	#
-	p[1] = sprintf("__%s_reply *__db_%s_%d%03d __P((__%s_msg *, struct svc_req *));",
-	    name, name, major, minor, name);
-	p[2] = "";
-	proto_format(p, 0, SFILE);
-
 	printf("__%s_reply *\n", name) >> SFILE
-	printf("__db_%s_%d%03d(msg, req)\n", name, major, minor) >> SFILE
+	printf("__db_%s_%d%03d__SVCSUFFIX__(msg, req)\n", \
+	    name, major, minor) >> SFILE
 	printf("\t__%s_msg *msg;\n", name) >> SFILE;
 	printf("\tstruct svc_req *req;\n", name) >> SFILE;
 	printf("{\n") >> SFILE
@@ -503,7 +510,7 @@ END {
 			    sep, args[i], args[i]) >> SFILE
 		}
 		if (rpc_type[i] == "GID") {
-			printf("%smsg->%s", sep, args[i]) >> SFILE
+			printf("%s(u_int8_t *)msg->%s", sep, args[i]) >> SFILE
 		}
 		if (rpc_type[i] == "INT") {
 			printf("%smsg->%s", sep, args[i]) >> SFILE
@@ -542,16 +549,9 @@ END {
 	# =====================================================
 	# Generate Procedure Template Server code
 	#
-	# Produce SED file commands if needed at the same time
-	#
 	# Spit out comment, prototype, function name and arg list.
-	#
-	printf("/^\\/\\* BEGIN __%s_proc/,/^\\/\\* END __%s_proc/c\\\n", \
-	    name, name) >> SEDFILE
-
 	printf("/* BEGIN __%s_proc */\n", name) >> PFILE
-	printf("/* BEGIN __%s_proc */\\\n", name) >> SEDFILE
-
+	delete p;
 	pi = 1;
 	p[pi++] = sprintf("void __%s_proc __P((", name);
 	p[pi++] = "";
@@ -574,6 +574,10 @@ END {
 			p[pi++] = "u_int32_t";
 			p[pi++] = ", ";
 		}
+		if (rpc_type[i] == "INTRET") {
+			p[pi++] = "u_int32_t *";
+			p[pi++] = ", ";
+		}
 		if (rpc_type[i] == "LIST" && list_type[i] == "GID") {
 			p[pi++] = "u_int8_t *";
 			p[pi++] = ", ";
@@ -616,12 +620,9 @@ END {
 		p[pi++] = "));";
 	}
 	p[pi++] = "";
-	proto_format(p, 1, SEDFILE);
 
 	printf("void\n") >> PFILE
-	printf("void\\\n") >> SEDFILE
 	printf("__%s_proc(", name) >> PFILE
-	printf("__%s_proc(", name) >> SEDFILE
 	sep = "";
 	argcount = 0;
 	for (i = 0; i < nvars; ++i) {
@@ -634,23 +635,21 @@ END {
 			continue;
 		if (rpc_type[i] == "ID") {
 			printf("%s%scl_id", sep, args[i]) >> PFILE
-			printf("%s%scl_id", sep, args[i]) >> SEDFILE
 		}
 		if (rpc_type[i] == "STRING") {
 			printf("%s%s", sep, args[i]) >> PFILE
-			printf("%s%s", sep, args[i]) >> SEDFILE
 		}
 		if (rpc_type[i] == "GID") {
 			printf("%s%s", sep, args[i]) >> PFILE
-			printf("%s%s", sep, args[i]) >> SEDFILE
 		}
 		if (rpc_type[i] == "INT") {
 			printf("%s%s", sep, args[i]) >> PFILE
-			printf("%s%s", sep, args[i]) >> SEDFILE
+		}
+		if (rpc_type[i] == "INTRET") {
+			printf("%s%s", sep, args[i]) >> PFILE
 		}
 		if (rpc_type[i] == "LIST") {
 			printf("%s%s", sep, args[i]) >> PFILE
-			printf("%s%s", sep, args[i]) >> SEDFILE
 			argcount++;
 			split_lines();
 			if (argcount == 0) {
@@ -659,11 +658,9 @@ END {
 				sep = ", ";
 			}
 			printf("%s%slen", sep, args[i]) >> PFILE
-			printf("%s%slen", sep, args[i]) >> SEDFILE
 		}
 		if (rpc_type[i] == "DBT") {
 			printf("%s%sdlen", sep, args[i]) >> PFILE
-			printf("%s%sdlen", sep, args[i]) >> SEDFILE
 			sep = ", ";
 			argcount++;
 			split_lines();
@@ -673,7 +670,6 @@ END {
 				sep = ", ";
 			}
 			printf("%s%sdoff", sep, args[i]) >> PFILE
-			printf("%s%sdoff", sep, args[i]) >> SEDFILE
 			argcount++;
 			split_lines();
 			if (argcount == 0) {
@@ -682,7 +678,6 @@ END {
 				sep = ", ";
 			}
 			printf("%s%sulen", sep, args[i]) >> PFILE
-			printf("%s%sulen", sep, args[i]) >> SEDFILE
 			argcount++;
 			split_lines();
 			if (argcount == 0) {
@@ -691,7 +686,6 @@ END {
 				sep = ", ";
 			}
 			printf("%s%sflags", sep, args[i]) >> PFILE
-			printf("%s%sflags", sep, args[i]) >> SEDFILE
 			argcount++;
 			split_lines();
 			if (argcount == 0) {
@@ -700,7 +694,6 @@ END {
 				sep = ", ";
 			}
 			printf("%s%sdata", sep, args[i]) >> PFILE
-			printf("%s%sdata", sep, args[i]) >> SEDFILE
 			argcount++;
 			split_lines();
 			if (argcount == 0) {
@@ -709,18 +702,14 @@ END {
 				sep = ", ";
 			}
 			printf("%s%ssize", sep, args[i]) >> PFILE
-			printf("%s%ssize", sep, args[i]) >> SEDFILE
 		}
 		sep = ", ";
 	}
 	printf("%sreplyp",sep) >> PFILE
-	printf("%sreplyp",sep) >> SEDFILE
 	if (xdr_free) {
 		printf("%sfreep)\n",sep) >> PFILE
-		printf("%sfreep)\\\n",sep) >> SEDFILE
 	} else {
 		printf(")\n") >> PFILE
-		printf(")\\\n") >> SEDFILE
 	}
 	#
 	# Spit out arg types/names;
@@ -728,65 +717,44 @@ END {
 	for (i = 0; i < nvars; ++i) {
 		if (rpc_type[i] == "ID") {
 			printf("\tlong %scl_id;\n", args[i]) >> PFILE
-			printf("\\\tlong %scl_id;\\\n", args[i]) >> SEDFILE
 		}
 		if (rpc_type[i] == "STRING") {
 			printf("\tchar *%s;\n", args[i]) >> PFILE
-			printf("\\\tchar *%s;\\\n", args[i]) >> SEDFILE
 		}
 		if (rpc_type[i] == "GID") {
 			printf("\tu_int8_t *%s;\n", args[i]) >> PFILE
-			printf("\\\tu_int8_t *%s;\\\n", args[i]) >> SEDFILE
 		}
 		if (rpc_type[i] == "INT") {
 			printf("\tu_int32_t %s;\n", args[i]) >> PFILE
-			printf("\\\tu_int32_t %s;\\\n", args[i]) >> SEDFILE
 		}
 		if (rpc_type[i] == "LIST" && list_type[i] == "GID") {
 			printf("\tu_int8_t * %s;\n", args[i]) >> PFILE
-			printf("\\\tu_int8_t * %s;\\\n", args[i]) >> SEDFILE
 		}
 		if (rpc_type[i] == "LIST" && list_type[i] == "INT") {
 			printf("\tu_int32_t * %s;\n", args[i]) >> PFILE
-			printf("\\\tu_int32_t * %s;\\\n", \
-			    args[i]) >> SEDFILE
 			printf("\tu_int32_t %ssize;\n", args[i]) >> PFILE
-			printf("\\\tu_int32_t %ssize;\\\n", args[i]) >> SEDFILE
 		}
 		if (rpc_type[i] == "LIST" && list_type[i] == "ID") {
 			printf("\tu_int32_t * %s;\n", args[i]) >> PFILE
-			printf("\\\tu_int32_t * %s;\\\n", args[i]) \
-			    >> SEDFILE
 		}
 		if (rpc_type[i] == "LIST") {
 			printf("\tu_int32_t %slen;\n", args[i]) >> PFILE
-			printf("\\\tu_int32_t %slen;\\\n", args[i]) \
-			    >> SEDFILE
 		}
 		if (rpc_type[i] == "DBT") {
 			printf("\tu_int32_t %sdlen;\n", args[i]) >> PFILE
-			printf("\\\tu_int32_t %sdlen;\\\n", args[i]) >> SEDFILE
 			printf("\tu_int32_t %sdoff;\n", args[i]) >> PFILE
-			printf("\\\tu_int32_t %sdoff;\\\n", args[i]) >> SEDFILE
 			printf("\tu_int32_t %sulen;\n", args[i]) >> PFILE
-			printf("\\\tu_int32_t %sulen;\\\n", args[i]) >> SEDFILE
 			printf("\tu_int32_t %sflags;\n", args[i]) >> PFILE
-			printf("\\\tu_int32_t %sflags;\\\n", args[i]) >> SEDFILE
 			printf("\tvoid *%sdata;\n", args[i]) >> PFILE
-			printf("\\\tvoid *%sdata;\\\n", args[i]) >> SEDFILE
 			printf("\tu_int32_t %ssize;\n", args[i]) >> PFILE
-			printf("\\\tu_int32_t %ssize;\\\n", args[i]) >> SEDFILE
 		}
 	}
 	printf("\t__%s_reply *replyp;\n",name) >> PFILE
-	printf("\\\t__%s_reply *replyp;\\\n",name) >> SEDFILE
 	if (xdr_free) {
 		printf("\tint * freep;\n") >> PFILE
-		printf("\\\tint * freep;\\\n") >> SEDFILE
 	}
 
 	printf("/* END __%s_proc */\n", name) >> PFILE
-	printf("/* END __%s_proc */\n", name) >> SEDFILE
 
 	#
 	# Function body
@@ -819,6 +787,7 @@ END {
 	#
 	# Spit out PUBLIC prototypes.
 	#
+	delete p;
 	pi = 1;
 	p[pi++] = sprintf("int __dbcl_%s __P((", name);
 	p[pi++] = "";
@@ -827,9 +796,8 @@ END {
 		p[pi++] = ", ";
 	}
 	p[pi - 1] = "";
-	p[pi++] = "));";
-	p[pi] = "";
-	proto_format(p, 0, CFILE);
+	p[pi] = "));";
+	proto_format(p, CFILE);
 
 	#
 	# Spit out function name/args.
@@ -1034,6 +1002,18 @@ END {
 
 	if (ret_code == 0) {
 		printf("\tret = replyp->status;\n") >> CFILE
+
+		#
+		# Set any arguments that are returned
+		#
+		for (i = 0; i < rvars; ++i) {
+			if (ret_isarg[i]) {
+				printf("\tif (%sp != NULL)\n", \
+				    retargs[i]) >> CFILE;
+				printf("\t\t*%sp = replyp->%s;\n", \
+				    retargs[i], retargs[i]) >> CFILE;
+			}
+		}
 	} else {
 		printf("\tret = __dbcl_%s_ret(", name) >> CFILE
 		sep = "";
@@ -1060,6 +1040,7 @@ END {
 		#
 		# If we are doing a list, write prototypes
 		#
+		delete p;
 		pi = 1;
 		p[pi++] = sprintf("int __dbcl_%s_ret __P((", name);
 		p[pi++] = "";
@@ -1067,9 +1048,8 @@ END {
 			p[pi++] = pr_type[i];
 			p[pi++] = ", ";
 		}
-		p[pi++] = sprintf("__%s_reply *));", name);
-		p[pi++] = "";
-		proto_format(p, 0, TFILE);
+		p[pi] = sprintf("__%s_reply *));", name);
+		proto_format(p, TFILE);
 
 		printf("int\n") >> TFILE
 		printf("__dbcl_%s_ret(", name) >> TFILE
@@ -1160,32 +1140,22 @@ function split_lines() {
 		sub("[ 	]$", "", sep)
 
 		printf("%s\n\t\t", sep) >> PFILE
-		printf("%s\\\n\\\t\\\t", sep) >> SEDFILE
 	}
 }
 
 # proto_format --
 #	Pretty-print a function prototype.
-function proto_format(p, sedfile, OUTPUT)
+function proto_format(p, OUTPUT)
 {
-	if (sedfile)
-		printf("/*\\\n") >> OUTPUT;
-	else
-		printf("/*\n") >> OUTPUT;
+	printf("/*\n") >> OUTPUT;
 
 	s = "";
 	for (i = 1; i in p; ++i)
 		s = s p[i];
 
-	if (sedfile)
-		t = "\\ * PUBLIC: "
-	else
-		t = " * PUBLIC: "
+	t = " * PUBLIC: "
 	if (length(s) + length(t) < 80)
-		if (sedfile)
-			printf("%s%s", t, s) >> OUTPUT;
-		else
-			printf("%s%s", t, s) >> OUTPUT;
+		printf("%s%s", t, s) >> OUTPUT;
 	else {
 		split(s, p, "__P");
 		len = length(t) + length(p[1]);
@@ -1195,20 +1165,12 @@ function proto_format(p, sedfile, OUTPUT)
 		comma[1] = "__P" comma[1];
 		for (i = 1; i <= n; i++) {
 			if (len + length(comma[i]) > 75) {
-				if (sedfile)
-					printf(\
-					    "\\\n\\ * PUBLIC:     ") >> OUTPUT;
-				else
-					printf("\n * PUBLIC:     ") >> OUTPUT;
+				printf("\n * PUBLIC:     ") >> OUTPUT;
 				len = 0;
 			}
 			printf("%s%s", comma[i], i == n ? "" : ",") >> OUTPUT;
 			len += length(comma[i]);
 		}
 	}
-	if (sedfile)
-		printf("\\\n\\ */\\\n") >> OUTPUT;
-	else
-		printf("\n */\n") >> OUTPUT;
-	delete p;
+	printf("\n */\n") >> OUTPUT;
 }
diff --git a/storage/bdb/dist/ltmain.sh b/storage/bdb/dist/ltmain.sh
index f07d424527d8b15f9e8879d8a0d847e894c5b9f2..c96a96ddd38b3761094c66a3573c3afec1e30b04 100644
--- a/storage/bdb/dist/ltmain.sh
+++ b/storage/bdb/dist/ltmain.sh
@@ -1,7 +1,7 @@
 # ltmain.sh - Provide generalized library-building support services.
 # NOTE: Changing this file will not affect anything until you rerun configure.
 #
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004
 # Free Software Foundation, Inc.
 # Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
 #
@@ -24,6 +24,34 @@
 # configuration script generated by Autoconf, you may include it under
 # the same distribution terms that you use for the rest of that program.
 
+basename="s,^.*/,,g"
+
+# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
+# is ksh but when the shell is invoked as "sh" and the current value of
+# the _XPG environment variable is not equal to 1 (one), the special
+# positional parameter $0, within a function call, is the name of the
+# function.
+progpath="$0"
+
+# The name of this program:
+progname=`echo "$progpath" | $SED $basename`
+modename="$progname"
+
+# Global variables:
+EXIT_SUCCESS=0
+EXIT_FAILURE=1
+
+PROGRAM=ltmain.sh
+PACKAGE=libtool
+VERSION=1.5.8
+TIMESTAMP=" (1.1220.2.117 2004/08/04 14:12:05)"
+
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes.
+if test -n "${ZSH_VERSION+set}" ; then
+  setopt NO_GLOB_SUBST
+fi
+
 # Check that we have a working $echo.
 if test "X$1" = X--no-reexec; then
   # Discard the --no-reexec flag, and continue.
@@ -36,7 +64,7 @@ elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
   :
 else
   # Restart under the correct shell, and then maybe $echo will work.
-  exec $SHELL "$0" --no-reexec ${1+"$@"}
+  exec $SHELL "$progpath" --no-reexec ${1+"$@"}
 fi
 
 if test "X$1" = X--fallback-echo; then
@@ -45,19 +73,9 @@ if test "X$1" = X--fallback-echo; then
   cat <<EOF
 $*
 EOF
-  exit 0
+  exit $EXIT_SUCCESS
 fi
 
-# The name of this program.
-progname=`$echo "$0" | sed 's%^.*/%%'`
-modename="$progname"
-
-# Constants.
-PROGRAM=ltmain.sh
-PACKAGE=libtool
-VERSION=1.4.2
-TIMESTAMP=" (1.922.2.53 2001/09/11 03:18:52)"
-
 default_mode=
 help="Try \`$progname --help' for more information."
 magic="%%%MAGIC variable%%%"
@@ -67,10 +85,19 @@ rm="rm -f"
 
 # Sed substitution that helps us do robust quoting.  It backslashifies
 # metacharacters that are still active within double-quoted strings.
-Xsed='sed -e 1s/^X//'
+Xsed="${SED}"' -e 1s/^X//'
 sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
-SP2NL='tr \040 \012'
-NL2SP='tr \015\012 \040\040'
+# test EBCDIC or ASCII
+case `echo A|tr A '\301'` in
+ A) # EBCDIC based system
+  SP2NL="tr '\100' '\n'"
+  NL2SP="tr '\r\n' '\100\100'"
+  ;;
+ *) # Assume ASCII based system
+  SP2NL="tr '\040' '\012'"
+  NL2SP="tr '\015\012' '\040\040'"
+  ;;
+esac
 
 # NLS nuisances.
 # Only set LANG and LC_ALL to C if already set.
@@ -85,12 +112,13 @@ if test "${LANG+set}" = set; then
 fi
 
 # Make sure IFS has a sensible default
-: ${IFS=" 	"}
+: ${IFS=" 	
+"}
 
 if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
-  echo "$modename: not configured to build any kind of library" 1>&2
-  echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
-  exit 1
+  $echo "$modename: not configured to build any kind of library" 1>&2
+  $echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
+  exit $EXIT_FAILURE
 fi
 
 # Global variables.
@@ -105,8 +133,237 @@ execute_dlfiles=
 lo2o="s/\\.lo\$/.${objext}/"
 o2lo="s/\\.${objext}\$/.lo/"
 
+#####################################
+# Shell function definitions:
+# This seems to be the best place for them
+
+# func_win32_libid arg
+# return the library type of file 'arg'
+#
+# Need a lot of goo to handle *both* DLLs and import libs
+# Has to be a shell function in order to 'eat' the argument
+# that is supplied when $file_magic_command is called.
+func_win32_libid () {
+  win32_libid_type="unknown"
+  win32_fileres=`file -L $1 2>/dev/null`
+  case $win32_fileres in
+  *ar\ archive\ import\ library*) # definitely import
+    win32_libid_type="x86 archive import"
+    ;;
+  *ar\ archive*) # could be an import, or static
+    if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \
+      $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then
+      win32_nmres=`eval $NM -f posix -A $1 | \
+	sed -n -e '1,100{/ I /{x;/import/!{s/^/import/;h;p;};x;};}'`
+      if test "X$win32_nmres" = "Ximport" ; then
+        win32_libid_type="x86 archive import"
+      else
+        win32_libid_type="x86 archive static"
+      fi
+    fi
+    ;;
+  *DLL*)
+    win32_libid_type="x86 DLL"
+    ;;
+  *executable*) # but shell scripts are "executable" too...
+    case $win32_fileres in
+    *MS\ Windows\ PE\ Intel*)
+      win32_libid_type="x86 DLL"
+      ;;
+    esac
+    ;;
+  esac
+  $echo $win32_libid_type
+}
+
+
+# func_infer_tag arg
+# Infer tagged configuration to use if any are available and
+# if one wasn't chosen via the "--tag" command line option.
+# Only attempt this if the compiler in the base compile
+# command doesn't match the default compiler.
+# arg is usually of the form 'gcc ...'
+func_infer_tag () {
+    if test -n "$available_tags" && test -z "$tagname"; then
+      CC_quoted=
+      for arg in $CC; do
+	case $arg in
+	  *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	  arg="\"$arg\""
+	  ;;
+	esac
+	CC_quoted="$CC_quoted $arg"
+      done
+      case $@ in
+      # Blanks in the command may have been stripped by the calling shell,
+      # but not from the CC environment variable when configure was run.
+      " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) ;;
+      # Blanks at the start of $base_compile will cause this to fail
+      # if we don't check for them as well.
+      *)
+	for z in $available_tags; do
+	  if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
+	    # Evaluate the configuration.
+	    eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
+	    CC_quoted=
+	    for arg in $CC; do
+	    # Double-quote args containing other shell metacharacters.
+	    case $arg in
+	      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	      arg="\"$arg\""
+	      ;;
+	    esac
+	    CC_quoted="$CC_quoted $arg"
+	  done
+	    case "$@ " in
+	      " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*)
+	      # The compiler in the base compile command matches
+	      # the one in the tagged configuration.
+	      # Assume this is the tagged configuration we want.
+	      tagname=$z
+	      break
+	      ;;
+	    esac
+	  fi
+	done
+	# If $tagname still isn't set, then no tagged configuration
+	# was found and let the user know that the "--tag" command
+	# line option must be used.
+	if test -z "$tagname"; then
+	  $echo "$modename: unable to infer tagged configuration"
+	  $echo "$modename: specify a tag with \`--tag'" 1>&2
+	  exit $EXIT_FAILURE
+#        else
+#          $echo "$modename: using $tagname tagged configuration"
+	fi
+	;;
+      esac
+    fi
+}
+
+
+# func_extract_archives gentop oldlib ...
+func_extract_archives () {
+    my_gentop="$1"; shift
+    my_oldlibs=${1+"$@"}
+    my_oldobjs=""
+    my_xlib=""
+    my_xabs=""
+    my_xdir=""
+    my_status=""
+
+    $show "${rm}r $my_gentop"
+    $run ${rm}r "$my_gentop"
+    $show "$mkdir $my_gentop"
+    $run $mkdir "$my_gentop"
+    my_status=$?
+    if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then
+      exit $my_status
+    fi
+
+    for my_xlib in $my_oldlibs; do
+      # Extract the objects.
+      case $my_xlib in
+	[\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
+	*) my_xabs=`pwd`"/$my_xlib" ;;
+      esac
+      my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'`
+      my_xdir="$my_gentop/$my_xlib"
+
+      $show "${rm}r $my_xdir"
+      $run ${rm}r "$my_xdir"
+      $show "$mkdir $my_xdir"
+      $run $mkdir "$my_xdir"
+      status=$?
+      if test "$status" -ne 0 && test ! -d "$my_xdir"; then
+	exit $status
+      fi
+      case $host in
+      *-darwin*)
+	$show "Extracting $my_xabs"
+	# Do not bother doing anything if just a dry run
+	if test -z "$run"; then
+	  darwin_orig_dir=`pwd`
+	  cd $my_xdir || exit $?
+	  darwin_archive=$my_xabs
+	  darwin_curdir=`pwd`
+	  darwin_base_archive=`basename $darwin_archive`
+	  darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null`
+	  if test -n "$darwin_arches"; then 
+	    darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'`
+	    darwin_arch=
+	    $show "$darwin_base_archive has multiple architectures $darwin_arches"
+	    for darwin_arch in  $darwin_arches ; do
+	      mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+	      lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
+	      # Remove the table of contents from the thin files.
+	      $AR -d "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" __.SYMDEF 2>/dev/null || true
+	      $AR -d "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" __.SYMDEF\ SORTED 2>/dev/null || true
+	      cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+	      $AR -xo "${darwin_base_archive}"
+	      rm "${darwin_base_archive}"
+	      cd "$darwin_curdir"
+	    done # $darwin_arches
+      ## Okay now we have a bunch of thin objects, gotta fatten them up :)
+	    darwin_filelist=`find unfat-$$ -type f | xargs basename | sort -u | $NL2SP`
+	    darwin_file=
+	    darwin_files=
+	    for darwin_file in $darwin_filelist; do
+	      darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP`
+	      lipo -create -output "$darwin_file" $darwin_files
+	    done # $darwin_filelist
+	    rm -rf unfat-$$
+	    cd "$darwin_orig_dir"
+	  else
+	    cd $darwin_orig_dir
+	    (cd $my_xdir && $AR x $my_xabs) || exit $?
+	  fi # $darwin_arches
+	fi # $run
+      ;;
+      *)
+	# We will extract separately just the conflicting names and we will
+	# no longer touch any unique names. It is faster to leave these
+	# extract automatically by $AR in one run.
+	$show "(cd $my_xdir && $AR x $my_xabs)"
+	$run eval "(cd \$my_xdir && $AR x \$my_xabs)" || exit $?
+	if ($AR t "$my_xabs" | sort | sort -uc >/dev/null 2>&1); then
+	  :
+	else
+	  $echo "$modename: warning: object name conflicts; renaming object files" 1>&2
+	  $echo "$modename: warning: to ensure that they will not overwrite" 1>&2
+	  $AR t "$my_xabs" | sort | uniq -cd | while read -r count name
+	  do
+	    i=1
+	    while test "$i" -le "$count"
+	    do
+	      # Put our $i before any first dot (extension)
+	      # Never overwrite any file
+	      name_to="$name"
+	      while test "X$name_to" = "X$name" || test -f "$my_xdir/$name_to"
+	      do
+		name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"`
+	      done
+	      $show "(cd $my_xdir && $AR xN $i $my_xabs '$name' && $mv '$name' '$name_to')"
+	      $run eval "(cd \$my_xdir && $AR xN $i \$my_xabs '$name' && $mv '$name' '$name_to')" || exit $?
+	      i=`expr $i + 1`
+	    done
+	  done
+	fi
+	;;
+      esac
+      my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
+    done
+
+    func_extract_archives_result="$my_oldobjs"
+}
+# End of Shell function definitions
+#####################################
+
+# Darwin sucks
+eval std_shrext=\"$shrext_cmds\"
+
 # Parse our command line options once, thoroughly.
-while test $# -gt 0
+while test "$#" -gt 0
 do
   arg="$1"
   shift
@@ -122,6 +379,34 @@ do
     execute_dlfiles)
       execute_dlfiles="$execute_dlfiles $arg"
       ;;
+    tag)
+      tagname="$arg"
+      preserve_args="${preserve_args}=$arg"
+
+      # Check whether tagname contains only valid characters
+      case $tagname in
+      *[!-_A-Za-z0-9,/]*)
+	$echo "$progname: invalid tag name: $tagname" 1>&2
+	exit $EXIT_FAILURE
+	;;
+      esac
+
+      case $tagname in
+      CC)
+	# Don't test for the "default" C tag, as we know, it's there, but
+	# not specially marked.
+	;;
+      *)
+	if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$progpath" > /dev/null; then
+	  taglist="$taglist $tagname"
+	  # Evaluate the configuration.
+	  eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $progpath`"
+	else
+	  $echo "$progname: ignoring unknown tag $tagname" 1>&2
+	fi
+	;;
+      esac
+      ;;
     *)
       eval "$prev=\$arg"
       ;;
@@ -139,18 +424,27 @@ do
     ;;
 
   --version)
-    echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
-    exit 0
+    $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
+    $echo
+    $echo "Copyright (C) 2003  Free Software Foundation, Inc."
+    $echo "This is free software; see the source for copying conditions.  There is NO"
+    $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+    exit $EXIT_SUCCESS
     ;;
 
   --config)
-    sed -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $0
-    exit 0
+    ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $progpath
+    # Now print the configurations for the tags.
+    for tagname in $taglist; do
+      ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath"
+    done
+    exit $EXIT_SUCCESS
     ;;
 
   --debug)
-    echo "$progname: enabling shell trace mode"
+    $echo "$progname: enabling shell trace mode"
     set -x
+    preserve_args="$preserve_args $arg"
     ;;
 
   --dry-run | -n)
@@ -158,18 +452,18 @@ do
     ;;
 
   --features)
-    echo "host: $host"
+    $echo "host: $host"
     if test "$build_libtool_libs" = yes; then
-      echo "enable shared libraries"
+      $echo "enable shared libraries"
     else
-      echo "disable shared libraries"
+      $echo "disable shared libraries"
     fi
     if test "$build_old_libs" = yes; then
-      echo "enable static libraries"
+      $echo "enable static libraries"
     else
-      echo "disable static libraries"
+      $echo "disable static libraries"
     fi
-    exit 0
+    exit $EXIT_SUCCESS
     ;;
 
   --finish) mode="finish" ;;
@@ -177,8 +471,19 @@ do
   --mode) prevopt="--mode" prev=mode ;;
   --mode=*) mode="$optarg" ;;
 
+  --preserve-dup-deps) duplicate_deps="yes" ;;
+
   --quiet | --silent)
     show=:
+    preserve_args="$preserve_args $arg"
+    ;;
+
+  --tag) prevopt="--tag" prev=tag ;;
+  --tag=*)
+    set tag "$optarg" ${1+"$@"}
+    shift
+    prev=tag
+    preserve_args="$preserve_args --tag"
     ;;
 
   -dlopen)
@@ -189,7 +494,7 @@ do
   -*)
     $echo "$modename: unrecognized option \`$arg'" 1>&2
     $echo "$help" 1>&2
-    exit 1
+    exit $EXIT_FAILURE
     ;;
 
   *)
@@ -202,7 +507,7 @@ done
 if test -n "$prevopt"; then
   $echo "$modename: option \`$prevopt' requires an argument" 1>&2
   $echo "$help" 1>&2
-  exit 1
+  exit $EXIT_FAILURE
 fi
 
 # If this variable is set in any of the actions, the command in it
@@ -214,8 +519,10 @@ if test -z "$show_help"; then
 
   # Infer the operation mode.
   if test -z "$mode"; then
+    $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2
+    $echo "*** Future versions of Libtool will require -mode=MODE be specified." 1>&2
     case $nonopt in
-    *cc | *++ | gcc* | *-gcc*)
+    *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*)
       mode=link
       for arg
       do
@@ -256,7 +563,7 @@ if test -z "$show_help"; then
   if test -n "$execute_dlfiles" && test "$mode" != execute; then
     $echo "$modename: unrecognized option \`-dlopen'" 1>&2
     $echo "$help" 1>&2
-    exit 1
+    exit $EXIT_FAILURE
   fi
 
   # Change the help message to a mode-specific one.
@@ -270,158 +577,124 @@ if test -z "$show_help"; then
     modename="$modename: compile"
     # Get the compilation command and the source file.
     base_compile=
-    prev=
-    lastarg=
-    srcfile="$nonopt"
+    srcfile="$nonopt"  #  always keep a non-empty value in "srcfile"
+    suppress_opt=yes
     suppress_output=
+    arg_mode=normal
+    libobj=
+    later=
 
-    user_target=no
     for arg
     do
-      case $prev in
-      "") ;;
-      xcompiler)
-	# Aesthetically quote the previous argument.
-	prev=
-	lastarg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
-
-	case $arg in
-	# Double-quote args containing other shell metacharacters.
-	# Many Bourne shells cannot handle close brackets correctly
-	# in scan sets, so we specify it separately.
-	*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
-	  arg="\"$arg\""
-	  ;;
-	esac
+      case "$arg_mode" in
+      arg  )
+	# do not "continue".  Instead, add this to base_compile
+	lastarg="$arg"
+	arg_mode=normal
+	;;
 
-	# Add the previous argument to base_compile.
-	if test -z "$base_compile"; then
-	  base_compile="$lastarg"
-	else
-	  base_compile="$base_compile $lastarg"
-	fi
+      target )
+	libobj="$arg"
+	arg_mode=normal
 	continue
 	;;
-      esac
 
-      # Accept any command-line options.
-      case $arg in
-      -o)
-	if test "$user_target" != "no"; then
-	  $echo "$modename: you cannot specify \`-o' more than once" 1>&2
-	  exit 1
-	fi
-	user_target=next
-	;;
+      normal )
+	# Accept any command-line options.
+	case $arg in
+	-o)
+	  if test -n "$libobj" ; then
+	    $echo "$modename: you cannot specify \`-o' more than once" 1>&2
+	    exit $EXIT_FAILURE
+	  fi
+	  arg_mode=target
+	  continue
+	  ;;
 
-      -static)
-	build_old_libs=yes
-	continue
-	;;
+	-static | -prefer-pic | -prefer-non-pic)
+	  later="$later $arg"
+	  continue
+	  ;;
 
-      -prefer-pic)
-	pic_mode=yes
-	continue
-	;;
+	-no-suppress)
+	  suppress_opt=no
+	  continue
+	  ;;
 
-      -prefer-non-pic)
-	pic_mode=no
-	continue
-	;;
+	-Xcompiler)
+	  arg_mode=arg  #  the next one goes into the "base_compile" arg list
+	  continue      #  The current "srcfile" will either be retained or
+	  ;;            #  replaced later.  I would guess that would be a bug.
 
-      -Xcompiler)
-	prev=xcompiler
-	continue
-	;;
+	-Wc,*)
+	  args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"`
+	  lastarg=
+	  save_ifs="$IFS"; IFS=','
+ 	  for arg in $args; do
+	    IFS="$save_ifs"
 
-      -Wc,*)
-	args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"`
-	lastarg=
-	save_ifs="$IFS"; IFS=','
-	for arg in $args; do
+	    # Double-quote args containing other shell metacharacters.
+	    # Many Bourne shells cannot handle close brackets correctly
+	    # in scan sets, so we specify it separately.
+	    case $arg in
+	      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	      arg="\"$arg\""
+	      ;;
+	    esac
+	    lastarg="$lastarg $arg"
+	  done
 	  IFS="$save_ifs"
+	  lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"`
 
-	  # Double-quote args containing other shell metacharacters.
-	  # Many Bourne shells cannot handle close brackets correctly
-	  # in scan sets, so we specify it separately.
-	  case $arg in
-	    *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
-	    arg="\"$arg\""
-	    ;;
-	  esac
-	  lastarg="$lastarg $arg"
-	done
-	IFS="$save_ifs"
-	lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"`
-
-	# Add the arguments to base_compile.
-	if test -z "$base_compile"; then
-	  base_compile="$lastarg"
-	else
+	  # Add the arguments to base_compile.
 	  base_compile="$base_compile $lastarg"
-	fi
-	continue
-	;;
-      esac
+	  continue
+	  ;;
 
-      case $user_target in
-      next)
-	# The next one is the -o target name
-	user_target=yes
-	continue
-	;;
-      yes)
-	# We got the output file
-	user_target=set
-	libobj="$arg"
-	continue
+	* )
+	  # Accept the current argument as the source file.
+	  # The previous "srcfile" becomes the current argument.
+	  #
+	  lastarg="$srcfile"
+	  srcfile="$arg"
+	  ;;
+	esac  #  case $arg
 	;;
-      esac
-
-      # Accept the current argument as the source file.
-      lastarg="$srcfile"
-      srcfile="$arg"
+      esac    #  case $arg_mode
 
       # Aesthetically quote the previous argument.
-
-      # Backslashify any backslashes, double quotes, and dollar signs.
-      # These are the only characters that are still specially
-      # interpreted inside of double-quoted scrings.
       lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"`
 
+      case $lastarg in
       # Double-quote args containing other shell metacharacters.
       # Many Bourne shells cannot handle close brackets correctly
       # in scan sets, so we specify it separately.
-      case $lastarg in
       *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
 	lastarg="\"$lastarg\""
 	;;
       esac
 
-      # Add the previous argument to base_compile.
-      if test -z "$base_compile"; then
-	base_compile="$lastarg"
-      else
-	base_compile="$base_compile $lastarg"
-      fi
-    done
+      base_compile="$base_compile $lastarg"
+    done # for arg
 
-    case $user_target in
-    set)
+    case $arg_mode in
+    arg)
+      $echo "$modename: you must specify an argument for -Xcompile"
+      exit $EXIT_FAILURE
       ;;
-    no)
-      # Get the name of the library object.
-      libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'`
+    target)
+      $echo "$modename: you must specify a target with \`-o'" 1>&2
+      exit $EXIT_FAILURE
       ;;
     *)
-      $echo "$modename: you must specify a target with \`-o'" 1>&2
-      exit 1
+      # Get the name of the library object.
+      [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'`
       ;;
     esac
 
     # Recognize several different file suffixes.
     # If the user specifies -o file.o, it is replaced with file.lo
-    xform='[cCFSfmso]'
+    xform='[cCFSifmso]'
     case $libobj in
     *.ada) xform=ada ;;
     *.adb) xform=adb ;;
@@ -429,10 +702,13 @@ if test -z "$show_help"; then
     *.asm) xform=asm ;;
     *.c++) xform=c++ ;;
     *.cc) xform=cc ;;
+    *.ii) xform=ii ;;
+    *.class) xform=class ;;
     *.cpp) xform=cpp ;;
     *.cxx) xform=cxx ;;
     *.f90) xform=f90 ;;
     *.for) xform=for ;;
+    *.java) xform=java ;;
     esac
 
     libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
@@ -441,25 +717,55 @@ if test -z "$show_help"; then
     *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;;
     *)
       $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2
-      exit 1
+      exit $EXIT_FAILURE
       ;;
     esac
 
+    func_infer_tag $base_compile
+
+    for arg in $later; do
+      case $arg in
+      -static)
+	build_old_libs=yes
+	continue
+	;;
+
+      -prefer-pic)
+	pic_mode=yes
+	continue
+	;;
+
+      -prefer-non-pic)
+	pic_mode=no
+	continue
+	;;
+      esac
+    done
+
+    objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+    xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
+    if test "X$xdir" = "X$obj"; then
+      xdir=
+    else
+      xdir=$xdir/
+    fi
+    lobj=${xdir}$objdir/$objname
+
     if test -z "$base_compile"; then
       $echo "$modename: you must specify a compilation command" 1>&2
       $echo "$help" 1>&2
-      exit 1
+      exit $EXIT_FAILURE
     fi
 
     # Delete any leftover library objects.
     if test "$build_old_libs" = yes; then
-      removelist="$obj $libobj"
+      removelist="$obj $lobj $libobj ${libobj}T"
     else
-      removelist="$libobj"
+      removelist="$lobj $libobj ${libobj}T"
     fi
 
     $run $rm $removelist
-    trap "$run $rm $removelist; exit 1" 1 2 15
+    trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15
 
     # On Cygwin there's no "real" PIC flag so we must build both object types
     case $host_os in
@@ -467,7 +773,7 @@ if test -z "$show_help"; then
       pic_mode=default
       ;;
     esac
-    if test $pic_mode = no && test "$deplibs_check_method" != pass_all; then
+    if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then
       # non-PIC code in shared libraries is not supported
       pic_mode=default
     fi
@@ -478,8 +784,9 @@ if test -z "$show_help"; then
       output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext}
       lockfile="$output_obj.lock"
       removelist="$removelist $output_obj $lockfile"
-      trap "$run $rm $removelist; exit 1" 1 2 15
+      trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15
     else
+      output_obj=
       need_locks=no
       lockfile=
     fi
@@ -487,13 +794,13 @@ if test -z "$show_help"; then
     # Lock this critical section if it is needed
     # We use this script file to make the link, it avoids creating a new file
     if test "$need_locks" = yes; then
-      until $run ln "$0" "$lockfile" 2>/dev/null; do
+      until $run ln "$progpath" "$lockfile" 2>/dev/null; do
 	$show "Waiting for $lockfile to be removed"
 	sleep 2
       done
     elif test "$need_locks" = warn; then
       if test -f "$lockfile"; then
-	echo "\
+	$echo "\
 *** ERROR, $lockfile exists and contains:
 `cat $lockfile 2>/dev/null`
 
@@ -505,68 +812,67 @@ avoid parallel builds (make -j) in this platform, or get a better
 compiler."
 
 	$run $rm $removelist
-	exit 1
+	exit $EXIT_FAILURE
       fi
-      echo $srcfile > "$lockfile"
+      $echo $srcfile > "$lockfile"
     fi
 
     if test -n "$fix_srcfile_path"; then
       eval srcfile=\"$fix_srcfile_path\"
     fi
 
+    $run $rm "$libobj" "${libobj}T"
+
+    # Create a libtool object file (analogous to a ".la" file),
+    # but don't create it if we're doing a dry run.
+    test -z "$run" && cat > ${libobj}T <<EOF
+# $libobj - a libtool object file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+EOF
+
     # Only build a PIC object if we are building libtool libraries.
     if test "$build_libtool_libs" = yes; then
       # Without this assignment, base_compile gets emptied.
       fbsd_hideous_sh_bug=$base_compile
 
       if test "$pic_mode" != no; then
-	# All platforms use -DPIC, to notify preprocessed assembler code.
-	command="$base_compile $srcfile $pic_flag -DPIC"
+	command="$base_compile $srcfile $pic_flag"
       else
 	# Don't build PIC code
 	command="$base_compile $srcfile"
       fi
-      if test "$build_old_libs" = yes; then
-	lo_libobj="$libobj"
-	dir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'`
-	if test "X$dir" = "X$libobj"; then
-	  dir="$objdir"
-	else
-	  dir="$dir/$objdir"
-	fi
-	libobj="$dir/"`$echo "X$libobj" | $Xsed -e 's%^.*/%%'`
 
-	if test -d "$dir"; then
-	  $show "$rm $libobj"
-	  $run $rm $libobj
-	else
-	  $show "$mkdir $dir"
-	  $run $mkdir $dir
-	  status=$?
-	  if test $status -ne 0 && test ! -d $dir; then
-	    exit $status
-	  fi
+      if test ! -d "${xdir}$objdir"; then
+	$show "$mkdir ${xdir}$objdir"
+	$run $mkdir ${xdir}$objdir
+	status=$?
+	if test "$status" -ne 0 && test ! -d "${xdir}$objdir"; then
+	  exit $status
 	fi
       fi
-      if test "$compiler_o_lo" = yes; then
-	output_obj="$libobj"
-	command="$command -o $output_obj"
-      elif test "$compiler_c_o" = yes; then
-	output_obj="$obj"
-	command="$command -o $output_obj"
+
+      if test -z "$output_obj"; then
+	# Place PIC objects in $objdir
+	command="$command -o $lobj"
       fi
 
-      $run $rm "$output_obj"
+      $run $rm "$lobj" "$output_obj"
+
       $show "$command"
       if $run eval "$command"; then :
       else
 	test -n "$output_obj" && $run $rm $removelist
-	exit 1
+	exit $EXIT_FAILURE
       fi
 
       if test "$need_locks" = warn &&
-	 test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then
-	echo "\
+	 test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+	$echo "\
 *** ERROR, $lockfile contains:
 `cat $lockfile 2>/dev/null`
 
@@ -581,13 +887,13 @@ avoid parallel builds (make -j) in this platform, or get a better
 compiler."
 
 	$run $rm $removelist
-	exit 1
+	exit $EXIT_FAILURE
       fi
 
       # Just move the object if needed, then go on to compile the next one
-      if test x"$output_obj" != x"$libobj"; then
-	$show "$mv $output_obj $libobj"
-	if $run $mv $output_obj $libobj; then :
+      if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
+	$show "$mv $output_obj $lobj"
+	if $run $mv $output_obj $lobj; then :
 	else
 	  error=$?
 	  $run $rm $removelist
@@ -595,48 +901,23 @@ compiler."
 	fi
       fi
 
-      # If we have no pic_flag, then copy the object into place and finish.
-      if (test -z "$pic_flag" || test "$pic_mode" != default) &&
-	 test "$build_old_libs" = yes; then
-	# Rename the .lo from within objdir to obj
-	if test -f $obj; then
-	  $show $rm $obj
-	  $run $rm $obj
-	fi
+      # Append the name of the PIC object to the libtool object file.
+      test -z "$run" && cat >> ${libobj}T <<EOF
+pic_object='$objdir/$objname'
 
-	$show "$mv $libobj $obj"
-	if $run $mv $libobj $obj; then :
-	else
-	  error=$?
-	  $run $rm $removelist
-	  exit $error
-	fi
+EOF
 
-	xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
-	if test "X$xdir" = "X$obj"; then
-	  xdir="."
-	else
-	  xdir="$xdir"
-	fi
-	baseobj=`$echo "X$obj" | $Xsed -e "s%.*/%%"`
-	libobj=`$echo "X$baseobj" | $Xsed -e "$o2lo"`
-	# Now arrange that obj and lo_libobj become the same file
-	$show "(cd $xdir && $LN_S $baseobj $libobj)"
-	if $run eval '(cd $xdir && $LN_S $baseobj $libobj)'; then
-	  # Unlock the critical section if it was locked
-	  if test "$need_locks" != no; then
-	    $run $rm "$lockfile"
-	  fi
-	  exit 0
-	else
-	  error=$?
-	  $run $rm $removelist
-	  exit $error
-	fi
+      # Allow error messages only from the first compilation.
+      if test "$suppress_opt" = yes; then
+        suppress_output=' >/dev/null 2>&1'
       fi
+    else
+      # No PIC object so indicate it doesn't exist in the libtool
+      # object file.
+      test -z "$run" && cat >> ${libobj}T <<EOF
+pic_object=none
 
-      # Allow error messages only from the first compilation.
-      suppress_output=' >/dev/null 2>&1'
+EOF
     fi
 
     # Only build a position-dependent object if we build old libraries.
@@ -645,27 +926,25 @@ compiler."
 	# Don't build PIC code
 	command="$base_compile $srcfile"
       else
-	# All platforms use -DPIC, to notify preprocessed assembler code.
-	command="$base_compile $srcfile $pic_flag -DPIC"
+	command="$base_compile $srcfile $pic_flag"
       fi
       if test "$compiler_c_o" = yes; then
 	command="$command -o $obj"
-	output_obj="$obj"
       fi
 
       # Suppress compiler output if we already did a PIC compilation.
       command="$command$suppress_output"
-      $run $rm "$output_obj"
+      $run $rm "$obj" "$output_obj"
       $show "$command"
       if $run eval "$command"; then :
       else
 	$run $rm $removelist
-	exit 1
+	exit $EXIT_FAILURE
       fi
 
       if test "$need_locks" = warn &&
-	 test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then
-	echo "\
+	 test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+	$echo "\
 *** ERROR, $lockfile contains:
 `cat $lockfile 2>/dev/null`
 
@@ -680,11 +959,11 @@ avoid parallel builds (make -j) in this platform, or get a better
 compiler."
 
 	$run $rm $removelist
-	exit 1
+	exit $EXIT_FAILURE
       fi
 
       # Just move the object if needed
-      if test x"$output_obj" != x"$obj"; then
+      if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
 	$show "$mv $output_obj $obj"
 	if $run $mv $output_obj $obj; then :
 	else
@@ -694,29 +973,31 @@ compiler."
 	fi
       fi
 
-      # Create an invalid libtool object if no PIC, so that we do not
-      # accidentally link it into a program.
-      if test "$build_libtool_libs" != yes; then
-	$show "echo timestamp > $libobj"
-	$run eval "echo timestamp > \$libobj" || exit $?
-      else
-	# Move the .lo from within objdir
-	$show "$mv $libobj $lo_libobj"
-	if $run $mv $libobj $lo_libobj; then :
-	else
-	  error=$?
-	  $run $rm $removelist
-	  exit $error
-	fi
-      fi
+      # Append the name of the non-PIC object the libtool object file.
+      # Only append if the libtool object file exists.
+      test -z "$run" && cat >> ${libobj}T <<EOF
+# Name of the non-PIC object.
+non_pic_object='$objname'
+
+EOF
+    else
+      # Append the name of the non-PIC object the libtool object file.
+      # Only append if the libtool object file exists.
+      test -z "$run" && cat >> ${libobj}T <<EOF
+# Name of the non-PIC object.
+non_pic_object=none
+
+EOF
     fi
 
+    $run $mv "${libobj}T" "${libobj}"
+
     # Unlock the critical section if it was locked
     if test "$need_locks" != no; then
       $run $rm "$lockfile"
     fi
 
-    exit 0
+    exit $EXIT_SUCCESS
     ;;
 
   # libtool link mode
@@ -727,7 +1008,7 @@ compiler."
       # It is impossible to link a dll without this setting, and
       # we shouldn't force the makefile maintainer to figure out
       # which system we are compiling for in order to pass an extra
-      # flag for every libtool invokation.
+      # flag for every libtool invocation.
       # allow_undefined=no
 
       # FIXME: Unfortunately, there are problems with the above when trying
@@ -742,6 +1023,7 @@ compiler."
       ;;
     esac
     libtool_args="$nonopt"
+    base_compile="$nonopt $@"
     compile_command="$nonopt"
     finalize_command="$nonopt"
 
@@ -757,6 +1039,7 @@ compiler."
     linker_flags=
     dllsearchpath=
     lib_search_path=`pwd`
+    inst_prefix_dir=
 
     avoid_version=no
     dlfiles=
@@ -771,6 +1054,8 @@ compiler."
     module=no
     no_install=no
     objs=
+    non_pic_objects=
+    precious_files_regex=
     prefer_static_libs=no
     preload=no
     prev=
@@ -782,6 +1067,9 @@ compiler."
     temp_rpath=
     thread_safe=no
     vinfo=
+    vinfo_number=no
+
+    func_infer_tag $base_compile
 
     # We need to know -static, to get the right output filenames.
     for arg
@@ -812,7 +1100,7 @@ compiler."
     test -n "$old_archive_from_new_cmds" && build_old_libs=yes
 
     # Go through the arguments, transforming them on the way.
-    while test $# -gt 0; do
+    while test "$#" -gt 0; do
       arg="$1"
       shift
       case $arg in
@@ -877,7 +1165,7 @@ compiler."
 	  export_symbols="$arg"
 	  if test ! -f "$arg"; then
 	    $echo "$modename: symbol file \`$arg' does not exist"
-	    exit 1
+	    exit $EXIT_FAILURE
 	  fi
 	  prev=
 	  continue
@@ -887,18 +1175,135 @@ compiler."
 	  prev=
 	  continue
 	  ;;
+	inst_prefix)
+	  inst_prefix_dir="$arg"
+	  prev=
+	  continue
+	  ;;
+	precious_regex)
+	  precious_files_regex="$arg"
+	  prev=
+	  continue
+	  ;;
 	release)
 	  release="-$arg"
 	  prev=
 	  continue
 	  ;;
+	objectlist)
+	  if test -f "$arg"; then
+	    save_arg=$arg
+	    moreargs=
+	    for fil in `cat $save_arg`
+	    do
+#	      moreargs="$moreargs $fil"
+	      arg=$fil
+	      # A libtool-controlled object.
+
+	      # Check to see that this really is a libtool object.
+	      if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+		pic_object=
+		non_pic_object=
+
+		# Read the .lo file
+		# If there is no directory component, then add one.
+		case $arg in
+		*/* | *\\*) . $arg ;;
+		*) . ./$arg ;;
+		esac
+
+		if test -z "$pic_object" || \
+		   test -z "$non_pic_object" ||
+		   test "$pic_object" = none && \
+		   test "$non_pic_object" = none; then
+		  $echo "$modename: cannot find name of object for \`$arg'" 1>&2
+		  exit $EXIT_FAILURE
+		fi
+
+		# Extract subdirectory from the argument.
+		xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+		if test "X$xdir" = "X$arg"; then
+		  xdir=
+		else
+		  xdir="$xdir/"
+		fi
+
+		if test "$pic_object" != none; then
+		  # Prepend the subdirectory the object is found in.
+		  pic_object="$xdir$pic_object"
+
+		  if test "$prev" = dlfiles; then
+		    if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+		      dlfiles="$dlfiles $pic_object"
+		      prev=
+		      continue
+		    else
+		      # If libtool objects are unsupported, then we need to preload.
+		      prev=dlprefiles
+		    fi
+		  fi
+
+		  # CHECK ME:  I think I busted this.  -Ossama
+		  if test "$prev" = dlprefiles; then
+		    # Preload the old-style object.
+		    dlprefiles="$dlprefiles $pic_object"
+		    prev=
+		  fi
+
+		  # A PIC object.
+		  libobjs="$libobjs $pic_object"
+		  arg="$pic_object"
+		fi
+
+		# Non-PIC object.
+		if test "$non_pic_object" != none; then
+		  # Prepend the subdirectory the object is found in.
+		  non_pic_object="$xdir$non_pic_object"
+
+		  # A standard non-PIC object
+		  non_pic_objects="$non_pic_objects $non_pic_object"
+		  if test -z "$pic_object" || test "$pic_object" = none ; then
+		    arg="$non_pic_object"
+		  fi
+		fi
+	      else
+		# Only an error if not doing a dry-run.
+		if test -z "$run"; then
+		  $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
+		  exit $EXIT_FAILURE
+		else
+		  # Dry-run case.
+
+		  # Extract subdirectory from the argument.
+		  xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+		  if test "X$xdir" = "X$arg"; then
+		    xdir=
+		  else
+		    xdir="$xdir/"
+		  fi
+
+		  pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
+		  non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
+		  libobjs="$libobjs $pic_object"
+		  non_pic_objects="$non_pic_objects $non_pic_object"
+		fi
+	      fi
+	    done
+	  else
+	    $echo "$modename: link input file \`$save_arg' does not exist"
+	    exit $EXIT_FAILURE
+	  fi
+	  arg=$save_arg
+	  prev=
+	  continue
+	  ;;
 	rpath | xrpath)
 	  # We need an absolute path.
 	  case $arg in
 	  [\\/]* | [A-Za-z]:[\\/]*) ;;
 	  *)
 	    $echo "$modename: only absolute run-paths are allowed" 1>&2
-	    exit 1
+	    exit $EXIT_FAILURE
 	    ;;
 	  esac
 	  if test "$prev" = rpath; then
@@ -930,13 +1335,26 @@ compiler."
 	  finalize_command="$finalize_command $wl$qarg"
 	  continue
 	  ;;
+	xcclinker)
+	  linker_flags="$linker_flags $qarg"
+	  compiler_flags="$compiler_flags $qarg"
+	  prev=
+	  compile_command="$compile_command $qarg"
+	  finalize_command="$finalize_command $qarg"
+	  continue
+	  ;;
+	shrext)
+  	  shrext_cmds="$arg"
+	  prev=
+	  continue
+	  ;;
 	*)
 	  eval "$prev=\"\$arg\""
 	  prev=
 	  continue
 	  ;;
 	esac
-      fi # test -n $prev
+      fi # test -n "$prev"
 
       prevarg="$arg"
 
@@ -978,7 +1396,7 @@ compiler."
       -export-symbols | -export-symbols-regex)
 	if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
 	  $echo "$modename: more than one -exported-symbols argument is not allowed"
-	  exit 1
+	  exit $EXIT_FAILURE
 	fi
 	if test "X$arg" = "X-export-symbols"; then
 	  prev=expsyms
@@ -988,11 +1406,16 @@ compiler."
 	continue
 	;;
 
+      -inst-prefix-dir)
+	prev=inst_prefix
+	continue
+	;;
+
       # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
       # so, if we see these flags be careful not to treat them like -L
       -L[A-Z][A-Z]*:*)
 	case $with_gcc/$host in
-	no/*-*-irix*)
+	no/*-*-irix* | /*-*-irix*)
 	  compile_command="$compile_command $arg"
 	  finalize_command="$finalize_command $arg"
 	  ;;
@@ -1009,7 +1432,7 @@ compiler."
 	  absdir=`cd "$dir" && pwd`
 	  if test -z "$absdir"; then
 	    $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2
-	    exit 1
+	    exit $EXIT_FAILURE
 	  fi
 	  dir="$absdir"
 	  ;;
@@ -1043,32 +1466,84 @@ compiler."
 	    # These systems don't actually have a C library (as such)
 	    test "X$arg" = "X-lc" && continue
 	    ;;
-	  *-*-openbsd*)
+	  *-*-openbsd* | *-*-freebsd*)
 	    # Do not include libc due to us having libc/libc_r.
 	    test "X$arg" = "X-lc" && continue
 	    ;;
+	  *-*-rhapsody* | *-*-darwin1.[012])
+	    # Rhapsody C and math libraries are in the System framework
+	    deplibs="$deplibs -framework System"
+	    continue
 	  esac
-	 elif test "X$arg" = "X-lc_r"; then
-	  case $host in
-	  *-*-openbsd*)
-	    # Do not include libc_r directly, use -pthread flag.
-	    continue
-	    ;;
-	  esac
+	elif test "X$arg" = "X-lc_r"; then
+	 case $host in
+	 *-*-openbsd* | *-*-freebsd*)
+	   # Do not include libc_r directly, use -pthread flag.
+	   continue
+	   ;;
+	 esac
 	fi
 	deplibs="$deplibs $arg"
 	continue
 	;;
 
+     -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe)
+	deplibs="$deplibs $arg"
+	continue
+	;;
+
       -module)
 	module=yes
 	continue
 	;;
 
-      #### Local change for Sleepycat's Berkeley DB [#6117]:
-      -jnimodule)
-	module=yes
-	jnimodule=yes
+      # gcc -m* arguments should be passed to the linker via $compiler_flags
+      # in order to pass architecture information to the linker
+      # (e.g. 32 vs 64-bit).  This may also be accomplished via -Wl,-mfoo
+      # but this is not reliable with gcc because gcc may use -mfoo to
+      # select a different linker, different libraries, etc, while
+      # -Wl,-mfoo simply passes -mfoo to the linker.
+      -m*)
+	# Unknown arguments in both finalize_command and compile_command need
+	# to be aesthetically quoted because they are evaled later.
+	arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+	case $arg in
+	*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	  arg="\"$arg\""
+	  ;;
+	esac
+        compile_command="$compile_command $arg"
+        finalize_command="$finalize_command $arg"
+        if test "$with_gcc" = "yes" ; then
+          compiler_flags="$compiler_flags $arg"
+        fi
+        continue
+        ;;
+
+      ################################################################
+      #### Local edit for Sleepycat SR #8705
+      #### This case was given to us by Albert Chin, and we expect
+      #### this to be included in future versions of libtool,
+      #### though we must verify that before upgrading.
+      ################################################################
+      # Flags for IRIX and Solaris compiler
+      -64|-mips[0-9]|-xarch=*)
+	# Unknown arguments in both finalize_command and compile_command need
+	# to be aesthetically quoted because they are evaled later.
+	arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+	case $arg in
+	*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	  arg="\"$arg\""
+	  ;;
+	esac
+	compile_command="$compile_command $arg"
+	finalize_command="$finalize_command $arg"
+	compiler_flags="$compiler_flags $arg"
+	continue
+	;;
+
+      -shrext)
+	prev=shrext
 	continue
 	;;
 
@@ -1096,8 +1571,18 @@ compiler."
 	continue
 	;;
 
+      -objectlist)
+	prev=objectlist
+	continue
+	;;
+
       -o) prev=output ;;
 
+      -precious-files-regex)
+	prev=precious_regex
+	continue
+	;;
+
       -release)
 	prev=release
 	continue
@@ -1120,7 +1605,7 @@ compiler."
 	[\\/]* | [A-Za-z]:[\\/]*) ;;
 	*)
 	  $echo "$modename: only absolute run-paths are allowed" 1>&2
-	  exit 1
+	  exit $EXIT_FAILURE
 	  ;;
 	esac
 	case "$xrpath " in
@@ -1148,6 +1633,11 @@ compiler."
 	prev=vinfo
 	continue
 	;;
+      -version-number)
+	prev=vinfo
+	vinfo_number=yes
+	continue
+	;;
 
       -Wc,*)
 	args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'`
@@ -1196,6 +1686,11 @@ compiler."
 	continue
 	;;
 
+      -XCClinker)
+	prev=xcclinker
+	continue
+	;;
+
       # Some other compiler flag.
       -* | +*)
 	# Unknown arguments in both finalize_command and compile_command need
@@ -1208,29 +1703,101 @@ compiler."
 	esac
 	;;
 
-      *.lo | *.$objext)
-	# A library or standard object.
-	if test "$prev" = dlfiles; then
-	  # This file was specified with -dlopen.
-	  if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
-	    dlfiles="$dlfiles $arg"
-	    prev=
-	    continue
-	  else
-	    # If libtool objects are unsupported, then we need to preload.
-	    prev=dlprefiles
-	  fi
-	fi
+      *.$objext)
+	# A standard object.
+	objs="$objs $arg"
+	;;
 
-	if test "$prev" = dlprefiles; then
-	  # Preload the old-style object.
-	  dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e "$lo2o"`
-	  prev=
-	else
+      *.lo)
+	# A libtool-controlled object.
+
+	# Check to see that this really is a libtool object.
+	if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+	  pic_object=
+	  non_pic_object=
+
+	  # Read the .lo file
+	  # If there is no directory component, then add one.
 	  case $arg in
-	  *.lo) libobjs="$libobjs $arg" ;;
-	  *) objs="$objs $arg" ;;
+	  */* | *\\*) . $arg ;;
+	  *) . ./$arg ;;
 	  esac
+
+	  if test -z "$pic_object" || \
+	     test -z "$non_pic_object" ||
+	     test "$pic_object" = none && \
+	     test "$non_pic_object" = none; then
+	    $echo "$modename: cannot find name of object for \`$arg'" 1>&2
+	    exit $EXIT_FAILURE
+	  fi
+
+	  # Extract subdirectory from the argument.
+	  xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+	  if test "X$xdir" = "X$arg"; then
+	    xdir=
+ 	  else
+	    xdir="$xdir/"
+	  fi
+
+	  if test "$pic_object" != none; then
+	    # Prepend the subdirectory the object is found in.
+	    pic_object="$xdir$pic_object"
+
+	    if test "$prev" = dlfiles; then
+	      if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+		dlfiles="$dlfiles $pic_object"
+		prev=
+		continue
+	      else
+		# If libtool objects are unsupported, then we need to preload.
+		prev=dlprefiles
+	      fi
+	    fi
+
+	    # CHECK ME:  I think I busted this.  -Ossama
+	    if test "$prev" = dlprefiles; then
+	      # Preload the old-style object.
+	      dlprefiles="$dlprefiles $pic_object"
+	      prev=
+	    fi
+
+	    # A PIC object.
+	    libobjs="$libobjs $pic_object"
+	    arg="$pic_object"
+	  fi
+
+	  # Non-PIC object.
+	  if test "$non_pic_object" != none; then
+	    # Prepend the subdirectory the object is found in.
+	    non_pic_object="$xdir$non_pic_object"
+
+	    # A standard non-PIC object
+	    non_pic_objects="$non_pic_objects $non_pic_object"
+	    if test -z "$pic_object" || test "$pic_object" = none ; then
+	      arg="$non_pic_object"
+	    fi
+	  fi
+	else
+	  # Only an error if not doing a dry-run.
+	  if test -z "$run"; then
+	    $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
+	    exit $EXIT_FAILURE
+	  else
+	    # Dry-run case.
+
+	    # Extract subdirectory from the argument.
+	    xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+	    if test "X$xdir" = "X$arg"; then
+	      xdir=
+	    else
+	      xdir="$xdir/"
+	    fi
+
+	    pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
+	    non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
+	    libobjs="$libobjs $pic_object"
+	    non_pic_objects="$non_pic_objects $non_pic_object"
+	  fi
 	fi
 	;;
 
@@ -1281,7 +1848,7 @@ compiler."
     if test -n "$prev"; then
       $echo "$modename: the \`$prevarg' option requires an argument" 1>&2
       $echo "$help" 1>&2
-      exit 1
+      exit $EXIT_FAILURE
     fi
 
     if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
@@ -1290,6 +1857,7 @@ compiler."
       finalize_command="$finalize_command $arg"
     fi
 
+    oldlibs=
     # calculate the name of the file, without its directory
     outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'`
     libobjs_save="$libobjs"
@@ -1310,11 +1878,11 @@ compiler."
       output_objdir="$output_objdir/$objdir"
     fi
     # Create the object directory.
-    if test ! -d $output_objdir; then
+    if test ! -d "$output_objdir"; then
       $show "$mkdir $output_objdir"
       $run $mkdir $output_objdir
       status=$?
-      if test $status -ne 0 && test ! -d $output_objdir; then
+      if test "$status" -ne 0 && test ! -d "$output_objdir"; then
 	exit $status
       fi
     fi
@@ -1324,7 +1892,7 @@ compiler."
     "")
       $echo "$modename: you must specify an output file" 1>&2
       $echo "$help" 1>&2
-      exit 1
+      exit $EXIT_FAILURE
       ;;
     *.$libext) linkmode=oldlib ;;
     *.lo | *.$objext) linkmode=obj ;;
@@ -1332,16 +1900,47 @@ compiler."
     *) linkmode=prog ;; # Anything else should be a program.
     esac
 
+    case $host in
+    *cygwin* | *mingw* | *pw32*)
+      # don't eliminate duplications in $postdeps and $predeps
+      duplicate_compiler_generated_deps=yes
+      ;;
+    *)
+      duplicate_compiler_generated_deps=$duplicate_deps
+      ;;
+    esac
     specialdeplibs=
+
     libs=
     # Find all interdependent deplibs by searching for libraries
     # that are linked more than once (e.g. -la -lb -la)
     for deplib in $deplibs; do
-      case "$libs " in
-      *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
-      esac
+      if test "X$duplicate_deps" = "Xyes" ; then
+	case "$libs " in
+	*" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	esac
+      fi
       libs="$libs $deplib"
     done
+
+    if test "$linkmode" = lib; then
+      libs="$predeps $libs $compiler_lib_search_path $postdeps"
+
+      # Compute libraries that are listed more than once in $predeps
+      # $postdeps and mark them as special (i.e., whose duplicates are
+      # not to be eliminated).
+      pre_post_deps=
+      if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then
+	for pre_post_dep in $predeps $postdeps; do
+	  case "$pre_post_deps " in
+	  *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;;
+	  esac
+	  pre_post_deps="$pre_post_deps $pre_post_dep"
+	done
+      fi
+      pre_post_deps=
+    fi
+
     deplibs=
     newdependency_libs=
     newlib_search_path=
@@ -1356,7 +1955,7 @@ compiler."
 	  *.la) ;;
 	  *)
 	    $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2
-	    exit 1
+	    exit $EXIT_FAILURE
 	    ;;
 	  esac
 	done
@@ -1373,39 +1972,59 @@ compiler."
 	;;
     esac
     for pass in $passes; do
-      if test $linkmode = prog; then
-	# Determine which files to process
+      if test "$linkmode,$pass" = "lib,link" ||
+	 test "$linkmode,$pass" = "prog,scan"; then
+	libs="$deplibs"
+	deplibs=
+      fi
+      if test "$linkmode" = prog; then
 	case $pass in
-	dlopen)
-	  libs="$dlfiles"
-	  save_deplibs="$deplibs" # Collect dlpreopened libraries
-	  deplibs=
-	  ;;
+	dlopen) libs="$dlfiles" ;;
 	dlpreopen) libs="$dlprefiles" ;;
 	link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
 	esac
       fi
+      if test "$pass" = dlopen; then
+	# Collect dlpreopened libraries
+	save_deplibs="$deplibs"
+	deplibs=
+      fi
       for deplib in $libs; do
 	lib=
 	found=no
 	case $deplib in
+	-mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe)
+	  if test "$linkmode,$pass" = "prog,link"; then
+	    compile_deplibs="$deplib $compile_deplibs"
+	    finalize_deplibs="$deplib $finalize_deplibs"
+	  else
+	    deplibs="$deplib $deplibs"
+	  fi
+	  continue
+	  ;;
 	-l*)
-	  if test $linkmode = oldlib && test $linkmode = obj; then
-	    $echo "$modename: warning: \`-l' is ignored for archives/objects: $deplib" 1>&2
+	  if test "$linkmode" != lib && test "$linkmode" != prog; then
+	    $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2
 	    continue
 	  fi
-	  if test $pass = conv; then
+	  if test "$pass" = conv; then
 	    deplibs="$deplib $deplibs"
 	    continue
 	  fi
 	  name=`$echo "X$deplib" | $Xsed -e 's/^-l//'`
 	  for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do
-	    # Search the libtool library
-	    lib="$searchdir/lib${name}.la"
-	    if test -f "$lib"; then
-	      found=yes
-	      break
-	    fi
+	    for search_ext in .la $std_shrext .so .a; do
+	      # Search the libtool library
+	      lib="$searchdir/lib${name}${search_ext}"
+	      if test -f "$lib"; then
+		if test "$search_ext" = ".la"; then
+		  found=yes
+		else
+		  found=no
+		fi
+		break 2
+	      fi
+	    done
 	  done
 	  if test "$found" != yes; then
 	    # deplib doesn't seem to be a libtool library
@@ -1414,40 +2033,76 @@ compiler."
 	      finalize_deplibs="$deplib $finalize_deplibs"
 	    else
 	      deplibs="$deplib $deplibs"
-	      test $linkmode = lib && newdependency_libs="$deplib $newdependency_libs"
+	      test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
 	    fi
 	    continue
+	  else # deplib is a libtool library
+	    # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
+	    # We need to do some special things here, and not later.
+	    if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+	      case " $predeps $postdeps " in
+	      *" $deplib "*)
+		if (${SED} -e '2q' $lib |
+                    grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+		  library_names=
+		  old_library=
+		  case $lib in
+		  */* | *\\*) . $lib ;;
+		  *) . ./$lib ;;
+		  esac
+		  for l in $old_library $library_names; do
+		    ll="$l"
+		  done
+		  if test "X$ll" = "X$old_library" ; then # only static version available
+		    found=no
+		    ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
+		    test "X$ladir" = "X$lib" && ladir="."
+		    lib=$ladir/$old_library
+		    if test "$linkmode,$pass" = "prog,link"; then
+		      compile_deplibs="$deplib $compile_deplibs"
+		      finalize_deplibs="$deplib $finalize_deplibs"
+		    else
+		      deplibs="$deplib $deplibs"
+		      test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+		    fi
+		    continue
+		  fi
+		fi
+	        ;;
+	      *) ;;
+	      esac
+	    fi
 	  fi
 	  ;; # -l
 	-L*)
 	  case $linkmode in
 	  lib)
 	    deplibs="$deplib $deplibs"
-	    test $pass = conv && continue
+	    test "$pass" = conv && continue
 	    newdependency_libs="$deplib $newdependency_libs"
 	    newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
 	    ;;
 	  prog)
-	    if test $pass = conv; then
+	    if test "$pass" = conv; then
 	      deplibs="$deplib $deplibs"
 	      continue
 	    fi
-	    if test $pass = scan; then
+	    if test "$pass" = scan; then
 	      deplibs="$deplib $deplibs"
-	      newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
 	    else
 	      compile_deplibs="$deplib $compile_deplibs"
 	      finalize_deplibs="$deplib $finalize_deplibs"
 	    fi
+	    newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
 	    ;;
 	  *)
-	    $echo "$modename: warning: \`-L' is ignored for archives/objects: $deplib" 1>&2
+	    $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2
 	    ;;
 	  esac # linkmode
 	  continue
 	  ;; # -L
 	-R*)
-	  if test $pass = link; then
+	  if test "$pass" = link; then
 	    dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
 	    # Make sure the xrpath contains only unique directories.
 	    case "$xrpath " in
@@ -1460,28 +2115,45 @@ compiler."
 	  ;;
 	*.la) lib="$deplib" ;;
 	*.$libext)
-	  if test $pass = conv; then
+	  if test "$pass" = conv; then
 	    deplibs="$deplib $deplibs"
 	    continue
 	  fi
 	  case $linkmode in
 	  lib)
-	    if test "$deplibs_check_method" != pass_all; then
-	      echo
-	      echo "*** Warning: This library needs some functionality provided by $deplib."
-	      echo "*** I have the capability to make that library automatically link in when"
-	      echo "*** you link to this library.  But I can only do this if you have a"
-	      echo "*** shared version of the library, which you do not appear to have."
+	    valid_a_lib=no
+	    case $deplibs_check_method in
+	      match_pattern*)
+		set dummy $deplibs_check_method
+	        match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+		if eval $echo \"$deplib\" 2>/dev/null \
+		    | $SED 10q \
+		    | $EGREP "$match_pattern_regex" > /dev/null; then
+		  valid_a_lib=yes
+		fi
+		;;
+	      pass_all)
+		valid_a_lib=yes
+		;;
+            esac
+	    if test "$valid_a_lib" != yes; then
+	      $echo
+	      $echo "*** Warning: Trying to link with static lib archive $deplib."
+	      $echo "*** I have the capability to make that library automatically link in when"
+	      $echo "*** you link to this library.  But I can only do this if you have a"
+	      $echo "*** shared version of the library, which you do not appear to have"
+	      $echo "*** because the file extensions .$libext of this argument makes me believe"
+	      $echo "*** that it is just a static archive that I should not used here."
 	    else
-	      echo
-	      echo "*** Warning: Linking the shared library $output against the"
-	      echo "*** static library $deplib is not portable!"
+	      $echo
+	      $echo "*** Warning: Linking the shared library $output against the"
+	      $echo "*** static library $deplib is not portable!"
 	      deplibs="$deplib $deplibs"
 	    fi
 	    continue
 	    ;;
 	  prog)
-	    if test $pass != link; then
+	    if test "$pass" != link; then
 	      deplibs="$deplib $deplibs"
 	    else
 	      compile_deplibs="$deplib $compile_deplibs"
@@ -1492,14 +2164,18 @@ compiler."
 	  esac # linkmode
 	  ;; # *.$libext
 	*.lo | *.$objext)
-	  if test $pass = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
-	    # If there is no dlopen support or we're linking statically,
-	    # we need to preload.
-	    newdlprefiles="$newdlprefiles $deplib"
-	    compile_deplibs="$deplib $compile_deplibs"
-	    finalize_deplibs="$deplib $finalize_deplibs"
-	  else
-	    newdlfiles="$newdlfiles $deplib"
+	  if test "$pass" = conv; then
+	    deplibs="$deplib $deplibs"
+	  elif test "$linkmode" = prog; then
+	    if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+	      # If there is no dlopen support or we're linking statically,
+	      # we need to preload.
+	      newdlprefiles="$newdlprefiles $deplib"
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    else
+	      newdlfiles="$newdlfiles $deplib"
+	    fi
 	  fi
 	  continue
 	  ;;
@@ -1508,17 +2184,17 @@ compiler."
 	  continue
 	  ;;
 	esac # case $deplib
-	if test $found = yes || test -f "$lib"; then :
+	if test "$found" = yes || test -f "$lib"; then :
 	else
 	  $echo "$modename: cannot find the library \`$lib'" 1>&2
-	  exit 1
+	  exit $EXIT_FAILURE
 	fi
 
 	# Check to see that this really is a libtool archive.
-	if (sed -e '2q' $lib | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+	if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
 	else
 	  $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
-	  exit 1
+	  exit $EXIT_FAILURE
 	fi
 
 	ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
@@ -1531,8 +2207,9 @@ compiler."
 	library_names=
 	old_library=
 	# If the library was installed with an old release of libtool,
-	# it will not redefine variable installed.
+	# it will not redefine variables installed, or shouldnotlink
 	installed=yes
+	shouldnotlink=no
 
 	# Read the .la file
 	case $lib in
@@ -1542,19 +2219,18 @@ compiler."
 
 	if test "$linkmode,$pass" = "lib,link" ||
 	   test "$linkmode,$pass" = "prog,scan" ||
-	   { test $linkmode = oldlib && test $linkmode = obj; }; then
-	   # Add dl[pre]opened files of deplib
+	   { test "$linkmode" != prog && test "$linkmode" != lib; }; then
 	  test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
 	  test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
 	fi
 
-	if test $pass = conv; then
+	if test "$pass" = conv; then
 	  # Only check for convenience libraries
 	  deplibs="$lib $deplibs"
 	  if test -z "$libdir"; then
 	    if test -z "$old_library"; then
 	      $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
-	      exit 1
+	      exit $EXIT_FAILURE
 	    fi
 	    # It is a libtool convenience library, so add in its objects.
 	    convenience="$convenience $ladir/$objdir/$old_library"
@@ -1562,18 +2238,21 @@ compiler."
 	    tmp_libs=
 	    for deplib in $dependency_libs; do
 	      deplibs="$deplib $deplibs"
-	      case "$tmp_libs " in
-	      *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
-	      esac
+              if test "X$duplicate_deps" = "Xyes" ; then
+	        case "$tmp_libs " in
+	        *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	        esac
+              fi
 	      tmp_libs="$tmp_libs $deplib"
 	    done
-	  elif test $linkmode != prog && test $linkmode != lib; then
+	  elif test "$linkmode" != prog && test "$linkmode" != lib; then
 	    $echo "$modename: \`$lib' is not a convenience library" 1>&2
-	    exit 1
+	    exit $EXIT_FAILURE
 	  fi
 	  continue
 	fi # $pass = conv
 
+
 	# Get the name of the library we link against.
 	linklib=
 	for l in $old_library $library_names; do
@@ -1581,19 +2260,23 @@ compiler."
 	done
 	if test -z "$linklib"; then
 	  $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
-	  exit 1
+	  exit $EXIT_FAILURE
 	fi
 
 	# This library was specified with -dlopen.
-	if test $pass = dlopen; then
+	if test "$pass" = dlopen; then
 	  if test -z "$libdir"; then
 	    $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2
-	    exit 1
+	    exit $EXIT_FAILURE
 	  fi
-	  if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+	  if test -z "$dlname" ||
+	     test "$dlopen_support" != yes ||
+	     test "$build_libtool_libs" = no; then
 	    # If there is no dlname, no dlopen support or we're linking
-	    # statically, we need to preload.
-	    dlprefiles="$dlprefiles $lib"
+	    # statically, we need to preload.  We also need to preload any
+	    # dependent libraries so libltdl's deplib preloader doesn't
+	    # bomb out in the load deplibs phase.
+	    dlprefiles="$dlprefiles $lib $dependency_libs"
 	  else
 	    newdlfiles="$newdlfiles $lib"
 	  fi
@@ -1626,18 +2309,25 @@ compiler."
 	    absdir="$libdir"
 	  fi
 	else
-	  dir="$ladir/$objdir"
-	  absdir="$abs_ladir/$objdir"
-	  # Remove this search path later
-	  notinst_path="$notinst_path $abs_ladir"
+	  if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+	    dir="$ladir"
+	    absdir="$abs_ladir"
+	    # Remove this search path later
+	    notinst_path="$notinst_path $abs_ladir"
+	  else
+	    dir="$ladir/$objdir"
+	    absdir="$abs_ladir/$objdir"
+	    # Remove this search path later
+	    notinst_path="$notinst_path $abs_ladir"
+	  fi
 	fi # $installed = yes
 	name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
 
 	# This library was specified with -dlpreopen.
-	if test $pass = dlpreopen; then
+	if test "$pass" = dlpreopen; then
 	  if test -z "$libdir"; then
 	    $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2
-	    exit 1
+	    exit $EXIT_FAILURE
 	  fi
 	  # Prefer using a static library (so that no silly _DYNAMIC symbols
 	  # are required to link).
@@ -1653,18 +2343,19 @@ compiler."
 
 	if test -z "$libdir"; then
 	  # Link the convenience library
-	  if test $linkmode = lib; then
+	  if test "$linkmode" = lib; then
 	    deplibs="$dir/$old_library $deplibs"
 	  elif test "$linkmode,$pass" = "prog,link"; then
 	    compile_deplibs="$dir/$old_library $compile_deplibs"
 	    finalize_deplibs="$dir/$old_library $finalize_deplibs"
 	  else
-	    deplibs="$lib $deplibs"
+	    deplibs="$lib $deplibs" # used for prog,scan pass
 	  fi
 	  continue
 	fi
 
-	if test $linkmode = prog && test $pass != link; then
+
+	if test "$linkmode" = prog && test "$pass" != link; then
 	  newlib_search_path="$newlib_search_path $ladir"
 	  deplibs="$lib $deplibs"
 
@@ -1680,28 +2371,36 @@ compiler."
 	    -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test
 	    esac
 	    # Need to link against all dependency_libs?
-	    if test $linkalldeplibs = yes; then
+	    if test "$linkalldeplibs" = yes; then
 	      deplibs="$deplib $deplibs"
 	    else
 	      # Need to hardcode shared library paths
 	      # or/and link against static libraries
 	      newdependency_libs="$deplib $newdependency_libs"
 	    fi
-	    case "$tmp_libs " in
-	    *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
-	    esac
+	    if test "X$duplicate_deps" = "Xyes" ; then
+	      case "$tmp_libs " in
+	      *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	      esac
+	    fi
 	    tmp_libs="$tmp_libs $deplib"
 	  done # for deplib
 	  continue
 	fi # $linkmode = prog...
 
-	link_static=no # Whether the deplib will be linked statically
-	if test -n "$library_names" &&
-	   { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
-	  # Link against this shared library
+	if test "$linkmode,$pass" = "prog,link"; then
+	  if test -n "$library_names" &&
+	     { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
+	    # We need to hardcode the library path
+	    if test -n "$shlibpath_var"; then
+	      # Make sure the rpath contains only unique directories.
+	      case "$temp_rpath " in
+	      *" $dir "*) ;;
+	      *" $absdir "*) ;;
+	      *) temp_rpath="$temp_rpath $dir" ;;
+	      esac
+	    fi
 
-	  if test "$linkmode,$pass" = "prog,link" ||
-	   { test $linkmode = lib && test $hardcode_into_libs = yes; }; then
 	    # Hardcode the library path.
 	    # Skip directories that are in the system default run-time
 	    # search path.
@@ -1723,17 +2422,6 @@ compiler."
 	      esac
 	      ;;
 	    esac
-	    if test $linkmode = prog; then
-	      # We need to hardcode the library path
-	      if test -n "$shlibpath_var"; then
-		# Make sure the rpath contains only unique directories.
-		case "$temp_rpath " in
-		*" $dir "*) ;;
-		*" $absdir "*) ;;
-		*) temp_rpath="$temp_rpath $dir" ;;
-		esac
-	      fi
-	    fi
 	  fi # $linkmode,$pass = prog,link...
 
 	  if test "$alldeplibs" = yes &&
@@ -1743,11 +2431,52 @@ compiler."
 	    # We only need to search for static libraries
 	    continue
 	  fi
+	fi
 
+	link_static=no # Whether the deplib will be linked statically
+	if test -n "$library_names" &&
+	   { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
 	  if test "$installed" = no; then
 	    notinst_deplibs="$notinst_deplibs $lib"
 	    need_relink=yes
 	  fi
+	  # This is a shared library
+
+	  # Warn about portability, can't link against -module's on
+	  # some systems (darwin)
+	  if test "$shouldnotlink" = yes && test "$pass" = link ; then
+	    $echo
+	    if test "$linkmode" = prog; then
+	      $echo "*** Warning: Linking the executable $output against the loadable module"
+	    else
+	      $echo "*** Warning: Linking the shared library $output against the loadable module"
+	    fi
+	    $echo "*** $linklib is not portable!"
+	  fi
+	  if test "$linkmode" = lib &&
+	     test "$hardcode_into_libs" = yes; then
+	    # Hardcode the library path.
+	    # Skip directories that are in the system default run-time
+	    # search path.
+	    case " $sys_lib_dlsearch_path " in
+	    *" $absdir "*) ;;
+	    *)
+	      case "$compile_rpath " in
+	      *" $absdir "*) ;;
+	      *) compile_rpath="$compile_rpath $absdir"
+	      esac
+	      ;;
+	    esac
+	    case " $sys_lib_dlsearch_path " in
+	    *" $libdir "*) ;;
+	    *)
+	      case "$finalize_rpath " in
+	      *" $libdir "*) ;;
+	      *) finalize_rpath="$finalize_rpath $libdir"
+	      esac
+	      ;;
+	    esac
+	  fi
 
 	  if test -n "$old_archive_from_expsyms_cmds"; then
 	    # figure out the soname
@@ -1761,7 +2490,7 @@ compiler."
 	    elif test -n "$soname_spec"; then
 	      # bleh windows
 	      case $host in
-	      *cygwin*)
+	      *cygwin* | mingw*)
 		major=`expr $current - $age`
 		versuffix="-$major"
 		;;
@@ -1773,17 +2502,18 @@ compiler."
 
 	    # Make a new name for the extract_expsyms_cmds to use
 	    soroot="$soname"
-	    soname=`echo $soroot | sed -e 's/^.*\///'`
-	    newlib="libimp-`echo $soname | sed 's/^lib//;s/\.dll$//'`.a"
+	    soname=`$echo $soroot | ${SED} -e 's/^.*\///'`
+	    newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a"
 
 	    # If the library has no export list, then create one now
 	    if test -f "$output_objdir/$soname-def"; then :
 	    else
 	      $show "extracting exported symbol list from \`$soname'"
 	      save_ifs="$IFS"; IFS='~'
-	      eval cmds=\"$extract_expsyms_cmds\"
+	      cmds=$extract_expsyms_cmds
 	      for cmd in $cmds; do
 		IFS="$save_ifs"
+		eval cmd=\"$cmd\"
 		$show "$cmd"
 		$run eval "$cmd" || exit $?
 	      done
@@ -1794,9 +2524,10 @@ compiler."
 	    if test -f "$output_objdir/$newlib"; then :; else
 	      $show "generating import library for \`$soname'"
 	      save_ifs="$IFS"; IFS='~'
-	      eval cmds=\"$old_archive_from_expsyms_cmds\"
+	      cmds=$old_archive_from_expsyms_cmds
 	      for cmd in $cmds; do
 		IFS="$save_ifs"
+		eval cmd=\"$cmd\"
 		$show "$cmd"
 		$run eval "$cmd" || exit $?
 	      done
@@ -1805,9 +2536,9 @@ compiler."
 	    # make sure the library variables are pointing to the new library
 	    dir=$output_objdir
 	    linklib=$newlib
-	  fi # test -n $old_archive_from_expsyms_cmds
+	  fi # test -n "$old_archive_from_expsyms_cmds"
 
-	  if test $linkmode = prog || test "$mode" != relink; then
+	  if test "$linkmode" = prog || test "$mode" != relink; then
 	    add_shlibpath=
 	    add_dir=
 	    add=
@@ -1816,6 +2547,22 @@ compiler."
 	    immediate | unsupported)
 	      if test "$hardcode_direct" = no; then
 		add="$dir/$linklib"
+		case $host in
+		  *-*-sco3.2v5* ) add_dir="-L$dir" ;;
+		  *-*-darwin* )
+		    # if the lib is a module then we can not link against
+		    # it, someone is ignoring the new warnings I added
+		    if /usr/bin/file -L $add 2> /dev/null | $EGREP "bundle" >/dev/null ; then
+		      $echo "** Warning, lib $linklib is a module, not a shared library"
+		      if test -z "$old_library" ; then
+		        $echo
+		        $echo "** And there doesn't seem to be a static archive available"
+		        $echo "** The link will probably fail, sorry"
+		      else
+		        add="$dir/$old_library"
+		      fi
+		    fi
+		esac
 	      elif test "$hardcode_minus_L" = no; then
 		case $host in
 		*-*-sunos*) add_shlibpath="$dir" ;;
@@ -1834,6 +2581,14 @@ compiler."
 		add="$dir/$linklib"
 	      elif test "$hardcode_minus_L" = yes; then
 		add_dir="-L$dir"
+		# Try looking first in the location we're being installed to.
+		if test -n "$inst_prefix_dir"; then
+		  case "$libdir" in
+		    [\\/]*)
+		      add_dir="$add_dir -L$inst_prefix_dir$libdir"
+		      ;;
+		  esac
+		fi
 		add="-l$name"
 	      elif test "$hardcode_shlibpath_var" = yes; then
 		add_shlibpath="$dir"
@@ -1847,7 +2602,7 @@ compiler."
 
 	    if test "$lib_linked" != yes; then
 	      $echo "$modename: configuration error: unsupported hardcode properties"
-	      exit 1
+	      exit $EXIT_FAILURE
 	    fi
 
 	    if test -n "$add_shlibpath"; then
@@ -1856,7 +2611,7 @@ compiler."
 	      *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
 	      esac
 	    fi
-	    if test $linkmode = prog; then
+	    if test "$linkmode" = prog; then
 	      test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
 	      test -n "$add" && compile_deplibs="$add $compile_deplibs"
 	    else
@@ -1873,7 +2628,7 @@ compiler."
 	    fi
 	  fi
 
-	  if test $linkmode = prog || test "$mode" = relink; then
+	  if test "$linkmode" = prog || test "$mode" = relink; then
 	    add_shlibpath=
 	    add_dir=
 	    add=
@@ -1889,13 +2644,28 @@ compiler."
 	      *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
 	      esac
 	      add="-l$name"
+	    elif test "$hardcode_automatic" = yes; then
+	      if test -n "$inst_prefix_dir" &&
+		 test -f "$inst_prefix_dir$libdir/$linklib" ; then
+	        add="$inst_prefix_dir$libdir/$linklib"
+	      else
+	        add="$libdir/$linklib"
+	      fi
 	    else
 	      # We cannot seem to hardcode it, guess we'll fake it.
 	      add_dir="-L$libdir"
+	      # Try looking first in the location we're being installed to.
+	      if test -n "$inst_prefix_dir"; then
+		case "$libdir" in
+		  [\\/]*)
+		    add_dir="$add_dir -L$inst_prefix_dir$libdir"
+		    ;;
+		esac
+	      fi
 	      add="-l$name"
 	    fi
 
-	    if test $linkmode = prog; then
+	    if test "$linkmode" = prog; then
 	      test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
 	      test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
 	    else
@@ -1903,16 +2673,7 @@ compiler."
 	      test -n "$add" && deplibs="$add $deplibs"
 	    fi
 	  fi
-	elif test $linkmode = prog; then
-	  if test "$alldeplibs" = yes &&
-	     { test "$deplibs_check_method" = pass_all ||
-	       { test "$build_libtool_libs" = yes &&
-		 test -n "$library_names"; }; }; then
-	    # We only need to search for static libraries
-	    continue
-	  fi
-
-	  # Try to link the static library
+	elif test "$linkmode" = prog; then
 	  # Here we assume that one of hardcode_direct or hardcode_minus_L
 	  # is not unsupported.  This is valid on all known static and
 	  # shared platforms.
@@ -1932,20 +2693,21 @@ compiler."
 
 	    # Just print a warning and add the library to dependency_libs so
 	    # that the program can be linked against the static library.
-	    echo
-	    echo "*** Warning: This library needs some functionality provided by $lib."
-	    echo "*** I have the capability to make that library automatically link in when"
-	    echo "*** you link to this library.  But I can only do this if you have a"
-	    echo "*** shared version of the library, which you do not appear to have."
+	    $echo
+	    $echo "*** Warning: This system can not link to static lib archive $lib."
+	    $echo "*** I have the capability to make that library automatically link in when"
+	    $echo "*** you link to this library.  But I can only do this if you have a"
+	    $echo "*** shared version of the library, which you do not appear to have."
 	    if test "$module" = yes; then
-	      echo "*** Therefore, libtool will create a static module, that should work "
-	      echo "*** as long as the dlopening application is linked with the -dlopen flag."
+	      $echo "*** But as you try to build a module library, libtool will still create "
+	      $echo "*** a static module, that should work as long as the dlopening application"
+	      $echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
 	      if test -z "$global_symbol_pipe"; then
-		echo
-		echo "*** However, this would only work if libtool was able to extract symbol"
-		echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
-		echo "*** not find such a program.  So, this module is probably useless."
-		echo "*** \`nm' from GNU binutils and a full rebuild may help."
+		$echo
+		$echo "*** However, this would only work if libtool was able to extract symbol"
+		$echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+		$echo "*** not find such a program.  So, this module is probably useless."
+		$echo "*** \`nm' from GNU binutils and a full rebuild may help."
 	      fi
 	      if test "$build_old_libs" = no; then
 		build_libtool_libs=module
@@ -1962,10 +2724,11 @@ compiler."
 	  fi
 	fi # link shared/static library?
 
-	if test $linkmode = lib; then
+	if test "$linkmode" = lib; then
 	  if test -n "$dependency_libs" &&
-	     { test $hardcode_into_libs != yes || test $build_old_libs = yes ||
-	       test $link_static = yes; }; then
+	     { test "$hardcode_into_libs" != yes ||
+	       test "$build_old_libs" = yes ||
+	       test "$link_static" = yes; }; then
 	    # Extract -R from dependency_libs
 	    temp_deplibs=
 	    for libdir in $dependency_libs; do
@@ -1988,13 +2751,15 @@ compiler."
 	  tmp_libs=
 	  for deplib in $dependency_libs; do
 	    newdependency_libs="$deplib $newdependency_libs"
-	    case "$tmp_libs " in
-	    *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
-	    esac
+	    if test "X$duplicate_deps" = "Xyes" ; then
+	      case "$tmp_libs " in
+	      *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	      esac
+	    fi
 	    tmp_libs="$tmp_libs $deplib"
 	  done
 
-	  if test $link_all_deplibs != no; then
+	  if test "$link_all_deplibs" != no; then
 	    # Add the search paths of all dependency libraries
 	    for deplib in $dependency_libs; do
 	      case $deplib in
@@ -2014,22 +2779,67 @@ compiler."
 		  ;;
 		esac
 		if grep "^installed=no" $deplib > /dev/null; then
-		  path="-L$absdir/$objdir"
+		  path="$absdir/$objdir"
 		else
-		  eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+		  eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
 		  if test -z "$libdir"; then
 		    $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
-		    exit 1
+		    exit $EXIT_FAILURE
 		  fi
 		  if test "$absdir" != "$libdir"; then
 		    $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2
 		  fi
-		  path="-L$absdir"
+		  path="$absdir"
 		fi
+		depdepl=
+		case $host in
+		*-*-darwin*)
+		  # we do not want to link against static libs,
+		  # but need to link against shared
+		  eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
+		  if test -n "$deplibrary_names" ; then
+		    for tmp in $deplibrary_names ; do
+		      depdepl=$tmp
+		    done
+		    if test -f "$path/$depdepl" ; then
+		      depdepl="$path/$depdepl"
+		    fi
+		    # do not add paths which are already there
+		    case " $newlib_search_path " in
+		    *" $path "*) ;;
+		    *) newlib_search_path="$newlib_search_path $path";;
+		    esac
+		  fi
+		  path=""
+		  ;;
+		*)
+		  path="-L$path"
+		  ;;
+		esac
+		;;
+	      -l*)
+		case $host in
+		*-*-darwin*)
+		  # Again, we only want to link against shared libraries
+		  eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"`
+		  for tmp in $newlib_search_path ; do
+		    if test -f "$tmp/lib$tmp_libs.dylib" ; then
+		      eval depdepl="$tmp/lib$tmp_libs.dylib"
+		      break
+		    fi
+		  done
+		  path=""
+		  ;;
+		*) continue ;;
+		esac
 		;;
 	      *) continue ;;
 	      esac
 	      case " $deplibs " in
+	      *" $depdepl "*) ;;
+	      *) deplibs="$depdepl $deplibs" ;;
+	      esac
+	      case " $deplibs " in
 	      *" $path "*) ;;
 	      *) deplibs="$deplibs $path" ;;
 	      esac
@@ -2037,15 +2847,15 @@ compiler."
 	  fi # link_all_deplibs != no
 	fi # linkmode = lib
       done # for deplib in $libs
-      if test $pass = dlpreopen; then
+      dependency_libs="$newdependency_libs"
+      if test "$pass" = dlpreopen; then
 	# Link the dlpreopened libraries before other libraries
 	for deplib in $save_deplibs; do
 	  deplibs="$deplib $deplibs"
 	done
       fi
-      if test $pass != dlopen; then
-	test $pass != scan && dependency_libs="$newdependency_libs"
-	if test $pass != conv; then
+      if test "$pass" != dlopen; then
+	if test "$pass" != conv; then
 	  # Make sure lib_search_path contains only unique directories.
 	  lib_search_path=
 	  for dir in $newlib_search_path; do
@@ -2067,9 +2877,30 @@ compiler."
 	  eval tmp_libs=\"\$$var\"
 	  new_libs=
 	  for deplib in $tmp_libs; do
+	    # FIXME: Pedantically, this is the right thing to do, so
+	    #        that some nasty dependency loop isn't accidentally
+	    #        broken:
+	    #new_libs="$deplib $new_libs"
+	    # Pragmatically, this seems to cause very few problems in
+	    # practice:
 	    case $deplib in
 	    -L*) new_libs="$deplib $new_libs" ;;
+	    -R*) ;;
 	    *)
+	      # And here is the reason: when a library appears more
+	      # than once as an explicit dependence of a library, or
+	      # is implicitly linked in more than once by the
+	      # compiler, it is considered special, and multiple
+	      # occurrences thereof are not removed.  Compare this
+	      # with having the same library being listed as a
+	      # dependency of multiple other libraries: in this case,
+	      # we know (pedantically, we assume) the library does not
+	      # need to be listed more than once, so we keep only the
+	      # last copy.  This is not always right, but it is rare
+	      # enough that we require users that really mean to play
+	      # such unportable linking tricks to link the library
+	      # using -Wl,-lname, so that libtool does not consider it
+	      # for duplicate removal.
 	      case " $specialdeplibs " in
 	      *" $deplib "*) new_libs="$deplib $new_libs" ;;
 	      *)
@@ -2097,19 +2928,32 @@ compiler."
 	  eval $var=\"$tmp_libs\"
 	done # for var
       fi
-      if test "$pass" = "conv" &&
-       { test "$linkmode" = "lib" || test "$linkmode" = "prog"; }; then
-	libs="$deplibs" # reset libs
-	deplibs=
-      fi
+      # Last step: remove runtime libs from dependency_libs
+      # (they stay in deplibs)
+      tmp_libs=
+      for i in $dependency_libs ; do
+	case " $predeps $postdeps $compiler_lib_search_path " in
+	*" $i "*)
+	  i=""
+	  ;;
+	esac
+	if test -n "$i" ; then
+	  tmp_libs="$tmp_libs $i"
+	fi
+      done
+      dependency_libs=$tmp_libs
     done # for pass
-    if test $linkmode = prog; then
+    if test "$linkmode" = prog; then
       dlfiles="$newdlfiles"
       dlprefiles="$newdlprefiles"
     fi
 
     case $linkmode in
     oldlib)
+      if test -n "$deplibs"; then
+	$echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2
+      fi
+
       if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
 	$echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2
       fi
@@ -2123,7 +2967,7 @@ compiler."
       fi
 
       if test -n "$vinfo"; then
-	$echo "$modename: warning: \`-version-info' is ignored for archives" 1>&2
+	$echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2
       fi
 
       if test -n "$release"; then
@@ -2145,17 +2989,19 @@ compiler."
       case $outputname in
       lib*)
 	name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+	eval shared_ext=\"$shrext_cmds\"
 	eval libname=\"$libname_spec\"
 	;;
       *)
 	if test "$module" = no; then
 	  $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2
 	  $echo "$help" 1>&2
-	  exit 1
+	  exit $EXIT_FAILURE
 	fi
 	if test "$need_lib_prefix" != no; then
 	  # Add the "lib" prefix for modules if required
 	  name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+	  eval shared_ext=\"$shrext_cmds\"
 	  eval libname=\"$libname_spec\"
 	else
 	  libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
@@ -2166,11 +3012,11 @@ compiler."
       if test -n "$objs"; then
 	if test "$deplibs_check_method" != pass_all; then
 	  $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1
-	  exit 1
+	  exit $EXIT_FAILURE
 	else
-	  echo
-	  echo "*** Warning: Linking the shared library $output against the non-libtool"
-	  echo "*** objects $objs is not portable!"
+	  $echo
+	  $echo "*** Warning: Linking the shared library $output against the non-libtool"
+	  $echo "*** objects $objs is not portable!"
 	  libobjs="$libobjs $objs"
 	fi
       fi
@@ -2180,7 +3026,7 @@ compiler."
       fi
 
       set dummy $rpath
-      if test $# -gt 2; then
+      if test "$#" -gt 2; then
 	$echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
       fi
       install_libdir="$2"
@@ -2189,14 +3035,16 @@ compiler."
       if test -z "$rpath"; then
 	if test "$build_libtool_libs" = yes; then
 	  # Building a libtool convenience library.
-	  libext=al
+	  # Some compilers have problems with a `.al' extension so
+	  # convenience libraries should have the same extension an
+	  # archive normally would.
 	  oldlibs="$output_objdir/$libname.$libext $oldlibs"
 	  build_libtool_libs=convenience
 	  build_old_libs=yes
 	fi
 
 	if test -n "$vinfo"; then
-	  $echo "$modename: warning: \`-version-info' is ignored for convenience libraries" 1>&2
+	  $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2
 	fi
 
 	if test -n "$release"; then
@@ -2212,12 +3060,49 @@ compiler."
 	if test -n "$8"; then
 	  $echo "$modename: too many parameters to \`-version-info'" 1>&2
 	  $echo "$help" 1>&2
-	  exit 1
+	  exit $EXIT_FAILURE
 	fi
 
-	current="$2"
-	revision="$3"
-	age="$4"
+	# convert absolute version numbers to libtool ages
+	# this retains compatibility with .la files and attempts
+	# to make the code below a bit more comprehensible
+
+	case $vinfo_number in
+	yes)
+	  number_major="$2"
+	  number_minor="$3"
+	  number_revision="$4"
+	  #
+	  # There are really only two kinds -- those that
+	  # use the current revision as the major version
+	  # and those that subtract age and use age as
+	  # a minor version.  But, then there is irix
+	  # which has an extra 1 added just for fun
+	  #
+	  case $version_type in
+	  darwin|linux|osf|windows)
+	    current=`expr $number_major + $number_minor`
+	    age="$number_minor"
+	    revision="$number_revision"
+	    ;;
+	  freebsd-aout|freebsd-elf|sunos)
+	    current="$number_major"
+	    revision="$number_minor"
+	    age="0"
+	    ;;
+	  irix|nonstopux)
+	    current=`expr $number_major + $number_minor - 1`
+	    age="$number_minor"
+	    revision="$number_minor"
+	    ;;
+	  esac
+	  ;;
+	no)
+	  current="$2"
+	  revision="$3"
+	  age="$4"
+	  ;;
+	esac
 
 	# Check that each of the things are valid numbers.
 	case $current in
@@ -2225,7 +3110,7 @@ compiler."
 	*)
 	  $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2
 	  $echo "$modename: \`$vinfo' is not valid version information" 1>&2
-	  exit 1
+	  exit $EXIT_FAILURE
 	  ;;
 	esac
 
@@ -2234,7 +3119,7 @@ compiler."
 	*)
 	  $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2
 	  $echo "$modename: \`$vinfo' is not valid version information" 1>&2
-	  exit 1
+	  exit $EXIT_FAILURE
 	  ;;
 	esac
 
@@ -2243,14 +3128,14 @@ compiler."
 	*)
 	  $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2
 	  $echo "$modename: \`$vinfo' is not valid version information" 1>&2
-	  exit 1
+	  exit $EXIT_FAILURE
 	  ;;
 	esac
 
-	if test $age -gt $current; then
+	if test "$age" -gt "$current"; then
 	  $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
 	  $echo "$modename: \`$vinfo' is not valid version information" 1>&2
-	  exit 1
+	  exit $EXIT_FAILURE
 	fi
 
 	# Calculate the version variables.
@@ -2267,7 +3152,7 @@ compiler."
 	  versuffix="$major.$age.$revision"
 	  # Darwin ld doesn't like 0 for these options...
 	  minor_current=`expr $current + 1`
-	  verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+	  verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
 	  ;;
 
 	freebsd-aout)
@@ -2280,16 +3165,21 @@ compiler."
 	  versuffix=".$current";
 	  ;;
 
-	irix)
+	irix | nonstopux)
 	  major=`expr $current - $age + 1`
-	  verstring="sgi$major.$revision"
+
+	  case $version_type in
+	    nonstopux) verstring_prefix=nonstopux ;;
+	    *)         verstring_prefix=sgi ;;
+	  esac
+	  verstring="$verstring_prefix$major.$revision"
 
 	  # Add in all the interfaces that we are compatible with.
 	  loop=$revision
-	  while test $loop != 0; do
+	  while test "$loop" -ne 0; do
 	    iface=`expr $revision - $loop`
 	    loop=`expr $loop - 1`
-	    verstring="sgi$major.$iface:$verstring"
+	    verstring="$verstring_prefix$major.$iface:$verstring"
 	  done
 
 	  # Before this point, $major must not contain `.'.
@@ -2303,13 +3193,13 @@ compiler."
 	  ;;
 
 	osf)
-	  major=`expr $current - $age`
+	  major=.`expr $current - $age`
 	  versuffix=".$current.$age.$revision"
 	  verstring="$current.$age.$revision"
 
 	  # Add in all the interfaces that we are compatible with.
 	  loop=$age
-	  while test $loop != 0; do
+	  while test "$loop" -ne 0; do
 	    iface=`expr $current - $loop`
 	    loop=`expr $loop - 1`
 	    verstring="$verstring:${iface}.0"
@@ -2333,20 +3223,19 @@ compiler."
 
 	*)
 	  $echo "$modename: unknown library version type \`$version_type'" 1>&2
-	  echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
-	  exit 1
+	  $echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
+	  exit $EXIT_FAILURE
 	  ;;
 	esac
 
 	# Clear the version info if we defaulted, and they specified a release.
 	if test -z "$vinfo" && test -n "$release"; then
 	  major=
-	  verstring="0.0"
 	  case $version_type in
 	  darwin)
 	    # we can't check for "0.0" in archive_cmds due to quoting
 	    # problems, so we reset it completely
-	    verstring=""
+	    verstring=
 	    ;;
 	  *)
 	    verstring="0.0"
@@ -2380,9 +3269,30 @@ compiler."
       fi
 
       if test "$mode" != relink; then
-	# Remove our outputs.
-	$show "${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*"
-	$run ${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*
+	# Remove our outputs, but don't remove object files since they
+	# may have been created when compiling PIC objects.
+	removelist=
+	tempremovelist=`$echo "$output_objdir/*"`
+	for p in $tempremovelist; do
+	  case $p in
+	    *.$objext)
+	       ;;
+	    $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
+	       if test "X$precious_files_regex" != "X"; then
+	         if echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
+	         then
+		   continue
+		 fi
+	       fi
+	       removelist="$removelist $p"
+	       ;;
+	    *) ;;
+	  esac
+	done
+	if test -n "$removelist"; then
+	  $show "${rm}r $removelist"
+	  $run ${rm}r $removelist
+	fi
       fi
 
       # Now set the variables for building old libraries.
@@ -2395,9 +3305,9 @@ compiler."
 
       # Eliminate all temporary directories.
       for path in $notinst_path; do
-	lib_search_path=`echo "$lib_search_path " | sed -e 's% $path % %g'`
-	deplibs=`echo "$deplibs " | sed -e 's% -L$path % %g'`
-	dependency_libs=`echo "$dependency_libs " | sed -e 's% -L$path % %g'`
+	lib_search_path=`$echo "$lib_search_path " | ${SED} -e 's% $path % %g'`
+	deplibs=`$echo "$deplibs " | ${SED} -e 's% -L$path % %g'`
+	dependency_libs=`$echo "$dependency_libs " | ${SED} -e 's% -L$path % %g'`
       done
 
       if test -n "$xrpath"; then
@@ -2410,7 +3320,7 @@ compiler."
 	  *) finalize_rpath="$finalize_rpath $libdir" ;;
 	  esac
 	done
-	if test $hardcode_into_libs != yes || test $build_old_libs = yes; then
+	if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
 	  dependency_libs="$temp_xrpath $dependency_libs"
 	fi
       fi
@@ -2448,19 +3358,13 @@ compiler."
 	  *-*-netbsd*)
 	    # Don't link with libc until the a.out ld.so is fixed.
 	    ;;
-	  *-*-openbsd*)
+	  *-*-openbsd* | *-*-freebsd*)
 	    # Do not include libc due to us having libc/libc_r.
+	    test "X$arg" = "X-lc" && continue
 	    ;;
-	  #### Local change for Sleepycat's Berkeley DB [#2380]:
-	  # FreeBSD, like OpenBSD, uses libc/libc_r and should not
-	  # link against libc/c_r explicitly;  the -pthread linker flag
-	  # implicitly controls use of -lc and -lc_r.
-	  *-*-freebsd*)
-	    # Do not include libc due to us having libc/libc_r.
-	    ;; 
-	  *)
+ 	  *)
 	    # Add libc to deplibs on all other systems if necessary.
-	    if test $build_libtool_need_lc = "yes"; then
+	    if test "$build_libtool_need_lc" = "yes"; then
 	      deplibs="$deplibs -lc"
 	    fi
 	    ;;
@@ -2487,7 +3391,7 @@ compiler."
 	  # This might be a little naive.  We might want to check
 	  # whether the library exists or not.  But this is on
 	  # osf3 & osf4 and I'm not really sure... Just
-	  # implementing what was already the behaviour.
+	  # implementing what was already the behavior.
 	  newdeplibs=$deplibs
 	  ;;
 	test_compile)
@@ -2500,64 +3404,88 @@ compiler."
 	  int main() { return 0; }
 EOF
 	  $rm conftest
-	  $CC -o conftest conftest.c $deplibs
-	  if test $? -eq 0 ; then
+	  $LTCC -o conftest conftest.c $deplibs
+	  if test "$?" -eq 0 ; then
 	    ldd_output=`ldd conftest`
 	    for i in $deplibs; do
 	      name="`expr $i : '-l\(.*\)'`"
 	      # If $name is empty we are operating on a -L argument.
-	      if test -n "$name" && test "$name" != "0"; then
-		libname=`eval \\$echo \"$libname_spec\"`
-		deplib_matches=`eval \\$echo \"$library_names_spec\"`
-		set dummy $deplib_matches
-		deplib_match=$2
-		if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
-		  newdeplibs="$newdeplibs $i"
-		else
-		  droppeddeps=yes
-		  echo
-		  echo "*** Warning: This library needs some functionality provided by $i."
-		  echo "*** I have the capability to make that library automatically link in when"
-		  echo "*** you link to this library.  But I can only do this if you have a"
-		  echo "*** shared version of the library, which you do not appear to have."
+              if test "$name" != "" && test "$name" -ne "0"; then
+		if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		  case " $predeps $postdeps " in
+		  *" $i "*)
+		    newdeplibs="$newdeplibs $i"
+		    i=""
+		    ;;
+		  esac
+	        fi
+		if test -n "$i" ; then
+		  libname=`eval \\$echo \"$libname_spec\"`
+		  deplib_matches=`eval \\$echo \"$library_names_spec\"`
+		  set dummy $deplib_matches
+		  deplib_match=$2
+		  if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+		    newdeplibs="$newdeplibs $i"
+		  else
+		    droppeddeps=yes
+		    $echo
+		    $echo "*** Warning: dynamic linker does not accept needed library $i."
+		    $echo "*** I have the capability to make that library automatically link in when"
+		    $echo "*** you link to this library.  But I can only do this if you have a"
+		    $echo "*** shared version of the library, which I believe you do not have"
+		    $echo "*** because a test_compile did reveal that the linker did not use it for"
+		    $echo "*** its dynamic dependency list that programs get resolved with at runtime."
+		  fi
 		fi
 	      else
 		newdeplibs="$newdeplibs $i"
 	      fi
 	    done
 	  else
-	    # Error occured in the first compile.  Let's try to salvage the situation:
-	    # Compile a seperate program for each library.
+	    # Error occurred in the first compile.  Let's try to salvage
+	    # the situation: Compile a separate program for each library.
 	    for i in $deplibs; do
 	      name="`expr $i : '-l\(.*\)'`"
-	     # If $name is empty we are operating on a -L argument.
-	      if test -n "$name" && test "$name" != "0"; then
+	      # If $name is empty we are operating on a -L argument.
+              if test "$name" != "" && test "$name" != "0"; then
 		$rm conftest
-		$CC -o conftest conftest.c $i
+		$LTCC -o conftest conftest.c $i
 		# Did it work?
-		if test $? -eq 0 ; then
+		if test "$?" -eq 0 ; then
 		  ldd_output=`ldd conftest`
-		  libname=`eval \\$echo \"$libname_spec\"`
-		  deplib_matches=`eval \\$echo \"$library_names_spec\"`
-		  set dummy $deplib_matches
-		  deplib_match=$2
-		  if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
-		    newdeplibs="$newdeplibs $i"
-		  else
-		    droppeddeps=yes
-		    echo
-		    echo "*** Warning: This library needs some functionality provided by $i."
-		    echo "*** I have the capability to make that library automatically link in when"
-		    echo "*** you link to this library.  But I can only do this if you have a"
-		    echo "*** shared version of the library, which you do not appear to have."
+		  if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		    case " $predeps $postdeps " in
+		    *" $i "*)
+		      newdeplibs="$newdeplibs $i"
+		      i=""
+		      ;;
+		    esac
+		  fi
+		  if test -n "$i" ; then
+		    libname=`eval \\$echo \"$libname_spec\"`
+		    deplib_matches=`eval \\$echo \"$library_names_spec\"`
+		    set dummy $deplib_matches
+		    deplib_match=$2
+		    if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+		      newdeplibs="$newdeplibs $i"
+		    else
+		      droppeddeps=yes
+		      $echo
+		      $echo "*** Warning: dynamic linker does not accept needed library $i."
+		      $echo "*** I have the capability to make that library automatically link in when"
+		      $echo "*** you link to this library.  But I can only do this if you have a"
+		      $echo "*** shared version of the library, which you do not appear to have"
+		      $echo "*** because a test_compile did reveal that the linker did not use this one"
+		      $echo "*** as a dynamic dependency that programs can get resolved with at runtime."
+		    fi
 		  fi
 		else
 		  droppeddeps=yes
-		  echo
-		  echo "*** Warning!  Library $i is needed by this library but I was not able to"
-		  echo "***  make it link in!  You will probably need to install it or some"
-		  echo "*** library that it depends on before this library will be fully"
-		  echo "*** functional.  Installing it before continuing would be even better."
+		  $echo
+		  $echo "*** Warning!  Library $i is needed by this library but I was not able to"
+		  $echo "***  make it link in!  You will probably need to install it or some"
+		  $echo "*** library that it depends on before this library will be fully"
+		  $echo "*** functional.  Installing it before continuing would be even better."
 		fi
 	      else
 		newdeplibs="$newdeplibs $i"
@@ -2571,11 +3499,20 @@ EOF
 	  for a_deplib in $deplibs; do
 	    name="`expr $a_deplib : '-l\(.*\)'`"
 	    # If $name is empty we are operating on a -L argument.
-	    if test -n "$name" && test "$name" != "0"; then
-	      libname=`eval \\$echo \"$libname_spec\"`
-	      for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
-		    potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
-		    for potent_lib in $potential_libs; do
+            if test "$name" != "" && test  "$name" != "0"; then
+	      if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		case " $predeps $postdeps " in
+		*" $a_deplib "*)
+		  newdeplibs="$newdeplibs $a_deplib"
+		  a_deplib=""
+		  ;;
+		esac
+	      fi
+	      if test -n "$a_deplib" ; then
+		libname=`eval \\$echo \"$libname_spec\"`
+		for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+		  potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+		  for potent_lib in $potential_libs; do
 		      # Follow soft links.
 		      if ls -lLd "$potent_lib" 2>/dev/null \
 			 | grep " -> " >/dev/null; then
@@ -2588,28 +3525,36 @@ EOF
 		      # but so what?
 		      potlib="$potent_lib"
 		      while test -h "$potlib" 2>/dev/null; do
-			potliblink=`ls -ld $potlib | sed 's/.* -> //'`
+			potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
 			case $potliblink in
 			[\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
 			*) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
 			esac
 		      done
 		      if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \
-			 | sed 10q \
-			 | egrep "$file_magic_regex" > /dev/null; then
+			 | ${SED} 10q \
+			 | $EGREP "$file_magic_regex" > /dev/null; then
 			newdeplibs="$newdeplibs $a_deplib"
 			a_deplib=""
 			break 2
 		      fi
-		    done
-	      done
+		  done
+		done
+	      fi
 	      if test -n "$a_deplib" ; then
 		droppeddeps=yes
-		echo
-		echo "*** Warning: This library needs some functionality provided by $a_deplib."
-		echo "*** I have the capability to make that library automatically link in when"
-		echo "*** you link to this library.  But I can only do this if you have a"
-		echo "*** shared version of the library, which you do not appear to have."
+		$echo
+		$echo "*** Warning: linker path does not have real file for library $a_deplib."
+		$echo "*** I have the capability to make that library automatically link in when"
+		$echo "*** you link to this library.  But I can only do this if you have a"
+		$echo "*** shared version of the library, which you do not appear to have"
+		$echo "*** because I did check the linker path looking for a file starting"
+		if test -z "$potlib" ; then
+		  $echo "*** with $libname but no candidates were found. (...for file magic test)"
+		else
+		  $echo "*** with $libname and none of the candidates passed a file format test"
+		  $echo "*** using a file magic. Last file checked: $potlib"
+		fi
 	      fi
 	    else
 	      # Add a -L argument.
@@ -2624,26 +3569,44 @@ EOF
 	    name="`expr $a_deplib : '-l\(.*\)'`"
 	    # If $name is empty we are operating on a -L argument.
 	    if test -n "$name" && test "$name" != "0"; then
-	      libname=`eval \\$echo \"$libname_spec\"`
-	      for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
-		potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
-		for potent_lib in $potential_libs; do
-		  if eval echo \"$potent_lib\" 2>/dev/null \
-		      | sed 10q \
-		      | egrep "$match_pattern_regex" > /dev/null; then
-		    newdeplibs="$newdeplibs $a_deplib"
-		    a_deplib=""
-		    break 2
-		  fi
+	      if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		case " $predeps $postdeps " in
+		*" $a_deplib "*)
+		  newdeplibs="$newdeplibs $a_deplib"
+		  a_deplib=""
+		  ;;
+		esac
+	      fi
+	      if test -n "$a_deplib" ; then
+		libname=`eval \\$echo \"$libname_spec\"`
+		for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+		  potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+		  for potent_lib in $potential_libs; do
+		    potlib="$potent_lib" # see symlink-check above in file_magic test
+		    if eval $echo \"$potent_lib\" 2>/dev/null \
+		        | ${SED} 10q \
+		        | $EGREP "$match_pattern_regex" > /dev/null; then
+		      newdeplibs="$newdeplibs $a_deplib"
+		      a_deplib=""
+		      break 2
+		    fi
+		  done
 		done
-	      done
+	      fi
 	      if test -n "$a_deplib" ; then
 		droppeddeps=yes
-		echo
-		echo "*** Warning: This library needs some functionality provided by $a_deplib."
-		echo "*** I have the capability to make that library automatically link in when"
-		echo "*** you link to this library.  But I can only do this if you have a"
-		echo "*** shared version of the library, which you do not appear to have."
+		$echo
+		$echo "*** Warning: linker path does not have real file for library $a_deplib."
+		$echo "*** I have the capability to make that library automatically link in when"
+		$echo "*** you link to this library.  But I can only do this if you have a"
+		$echo "*** shared version of the library, which you do not appear to have"
+		$echo "*** because I did check the linker path looking for a file starting"
+		if test -z "$potlib" ; then
+		  $echo "*** with $libname but no candidates were found. (...for regex pattern test)"
+		else
+		  $echo "*** with $libname and none of the candidates passed a file format test"
+		  $echo "*** using a regex pattern. Last file checked: $potlib"
+		fi
 	      fi
 	    else
 	      # Add a -L argument.
@@ -2653,16 +3616,23 @@ EOF
 	  ;;
 	none | unknown | *)
 	  newdeplibs=""
-	  if $echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
-	       -e 's/ -[LR][^ ]*//g' -e 's/[ 	]//g' |
-	     grep . >/dev/null; then
-	    echo
+	  tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
+	    -e 's/ -[LR][^ ]*//g'`
+	  if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+	    for i in $predeps $postdeps ; do
+	      # can't use Xsed below, because $i might contain '/'
+	      tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"`
+	    done
+	  fi
+	  if $echo "X $tmp_deplibs" | $Xsed -e 's/[ 	]//g' \
+	    | grep . >/dev/null; then
+	    $echo
 	    if test "X$deplibs_check_method" = "Xnone"; then
-	      echo "*** Warning: inter-library dependencies are not supported in this platform."
+	      $echo "*** Warning: inter-library dependencies are not supported in this platform."
 	    else
-	      echo "*** Warning: inter-library dependencies are not known to be supported."
+	      $echo "*** Warning: inter-library dependencies are not known to be supported."
 	    fi
-	    echo "*** All declared inter-library dependencies are being dropped."
+	    $echo "*** All declared inter-library dependencies are being dropped."
 	    droppeddeps=yes
 	  fi
 	  ;;
@@ -2682,17 +3652,17 @@ EOF
 
 	if test "$droppeddeps" = yes; then
 	  if test "$module" = yes; then
-	    echo
-	    echo "*** Warning: libtool could not satisfy all declared inter-library"
-	    echo "*** dependencies of module $libname.  Therefore, libtool will create"
-	    echo "*** a static module, that should work as long as the dlopening"
-	    echo "*** application is linked with the -dlopen flag."
+	    $echo
+	    $echo "*** Warning: libtool could not satisfy all declared inter-library"
+	    $echo "*** dependencies of module $libname.  Therefore, libtool will create"
+	    $echo "*** a static module, that should work as long as the dlopening"
+	    $echo "*** application is linked with the -dlopen flag."
 	    if test -z "$global_symbol_pipe"; then
-	      echo
-	      echo "*** However, this would only work if libtool was able to extract symbol"
-	      echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
-	      echo "*** not find such a program.  So, this module is probably useless."
-	      echo "*** \`nm' from GNU binutils and a full rebuild may help."
+	      $echo
+	      $echo "*** However, this would only work if libtool was able to extract symbol"
+	      $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+	      $echo "*** not find such a program.  So, this module is probably useless."
+	      $echo "*** \`nm' from GNU binutils and a full rebuild may help."
 	    fi
 	    if test "$build_old_libs" = no; then
 	      oldlibs="$output_objdir/$libname.$libext"
@@ -2702,16 +3672,16 @@ EOF
 	      build_libtool_libs=no
 	    fi
 	  else
-	    echo "*** The inter-library dependencies that have been dropped here will be"
-	    echo "*** automatically added whenever a program is linked with this library"
-	    echo "*** or is declared to -dlopen it."
-
-	    if test $allow_undefined = no; then
-	      echo
-	      echo "*** Since this library must not contain undefined symbols,"
-	      echo "*** because either the platform does not support them or"
-	      echo "*** it was explicitly requested with -no-undefined,"
-	      echo "*** libtool will only create a static version of it."
+	    $echo "*** The inter-library dependencies that have been dropped here will be"
+	    $echo "*** automatically added whenever a program is linked with this library"
+	    $echo "*** or is declared to -dlopen it."
+
+	    if test "$allow_undefined" = no; then
+	      $echo
+	      $echo "*** Since this library must not contain undefined symbols,"
+	      $echo "*** because either the platform does not support them or"
+	      $echo "*** it was explicitly requested with -no-undefined,"
+	      $echo "*** libtool will only create a static version of it."
 	      if test "$build_old_libs" = no; then
 		oldlibs="$output_objdir/$libname.$libext"
 		build_libtool_libs=module
@@ -2733,7 +3703,7 @@ EOF
 
       # Test again, we may have decided not to build it any more
       if test "$build_libtool_libs" = yes; then
-	if test $hardcode_into_libs = yes; then
+	if test "$hardcode_into_libs" = yes; then
 	  # Hardcode the library paths
 	  hardcode_libdirs=
 	  dep_rpath=
@@ -2769,7 +3739,11 @@ EOF
 	  if test -n "$hardcode_libdir_separator" &&
 	     test -n "$hardcode_libdirs"; then
 	    libdir="$hardcode_libdirs"
-	    eval dep_rpath=\"$hardcode_libdir_flag_spec\"
+	    if test -n "$hardcode_libdir_flag_spec_ld"; then
+	      eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\"
+	    else
+	      eval dep_rpath=\"$hardcode_libdir_flag_spec\"
+	    fi
 	  fi
 	  if test -n "$runpath_var" && test -n "$perm_rpath"; then
 	    # We should set the runpath_var.
@@ -2789,6 +3763,7 @@ EOF
 	fi
 
 	# Get the real and link names of the library.
+	eval shared_ext=\"$shrext_cmds\"
 	eval library_names=\"$library_names_spec\"
 	set dummy $library_names
 	realname="$2"
@@ -2799,7 +3774,9 @@ EOF
 	else
 	  soname="$realname"
 	fi
-	test -z "$dlname" && dlname=$soname
+	if test -z "$dlname"; then
+	  dlname=$soname
+	fi
 
 	lib="$output_objdir/$realname"
 	for link
@@ -2807,23 +3784,6 @@ EOF
 	  linknames="$linknames $link"
 	done
 
-	# Ensure that we have .o objects for linkers which dislike .lo
-	# (e.g. aix) in case we are running --disable-static
-	for obj in $libobjs; do
-	  xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
-	  if test "X$xdir" = "X$obj"; then
-	    xdir="."
-	  else
-	    xdir="$xdir"
-	  fi
-	  baseobj=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
-	  oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"`
-	  if test ! -f $xdir/$oldobj; then
-	    $show "(cd $xdir && ${LN_S} $baseobj $oldobj)"
-	    $run eval '(cd $xdir && ${LN_S} $baseobj $oldobj)' || exit $?
-	  fi
-	done
-
 	# Use standard objects if they are pic
 	test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
 
@@ -2833,17 +3793,26 @@ EOF
 	    $show "generating symbol list for \`$libname.la'"
 	    export_symbols="$output_objdir/$libname.exp"
 	    $run $rm $export_symbols
-	    eval cmds=\"$export_symbols_cmds\"
+	    cmds=$export_symbols_cmds
 	    save_ifs="$IFS"; IFS='~'
 	    for cmd in $cmds; do
 	      IFS="$save_ifs"
-	      $show "$cmd"
-	      $run eval "$cmd" || exit $?
+	      eval cmd=\"$cmd\"
+	      if len=`expr "X$cmd" : ".*"` &&
+	       test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+	        $show "$cmd"
+	        $run eval "$cmd" || exit $?
+	        skipped_export=false
+	      else
+	        # The command line is too long to execute in one step.
+	        $show "using reloadable object file for export list..."
+	        skipped_export=:
+	      fi
 	    done
 	    IFS="$save_ifs"
 	    if test -n "$export_symbols_regex"; then
-	      $show "egrep -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
-	      $run eval 'egrep -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+	      $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
+	      $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
 	      $show "$mv \"${export_symbols}T\" \"$export_symbols\""
 	      $run eval '$mv "${export_symbols}T" "$export_symbols"'
 	    fi
@@ -2854,46 +3823,30 @@ EOF
 	  $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"'
 	fi
 
+	tmp_deplibs=
+	for test_deplib in $deplibs; do
+		case " $convenience " in
+		*" $test_deplib "*) ;;
+		*)
+			tmp_deplibs="$tmp_deplibs $test_deplib"
+			;;
+		esac
+	done
+	deplibs="$tmp_deplibs"
+
 	if test -n "$convenience"; then
 	  if test -n "$whole_archive_flag_spec"; then
+	    save_libobjs=$libobjs
 	    eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
 	  else
 	    gentop="$output_objdir/${outputname}x"
-	    $show "${rm}r $gentop"
-	    $run ${rm}r "$gentop"
-	    $show "mkdir $gentop"
-	    $run mkdir "$gentop"
-	    status=$?
-	    if test $status -ne 0 && test ! -d "$gentop"; then
-	      exit $status
-	    fi
 	    generated="$generated $gentop"
 
-	    for xlib in $convenience; do
-	      # Extract the objects.
-	      case $xlib in
-	      [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
-	      *) xabs=`pwd`"/$xlib" ;;
-	      esac
-	      xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
-	      xdir="$gentop/$xlib"
-
-	      $show "${rm}r $xdir"
-	      $run ${rm}r "$xdir"
-	      $show "mkdir $xdir"
-	      $run mkdir "$xdir"
-	      status=$?
-	      if test $status -ne 0 && test ! -d "$xdir"; then
-		exit $status
-	      fi
-	      $show "(cd $xdir && $AR x $xabs)"
-	      $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
-
-	      libobjs="$libobjs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP`
-	    done
+	    func_extract_archives $gentop $convenience
+	    libobjs="$libobjs $func_extract_archives_result"
 	  fi
 	fi
-
+	
 	if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
 	  eval flag=\"$thread_safe_flag_spec\"
 	  linker_flags="$linker_flags $flag"
@@ -2905,14 +3858,147 @@ EOF
 	fi
 
 	# Do each of the archive commands.
+	if test "$module" = yes && test -n "$module_cmds" ; then
+	  if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+	    eval test_cmds=\"$module_expsym_cmds\"
+	    cmds=$module_expsym_cmds
+	  else
+	    eval test_cmds=\"$module_cmds\"
+	    cmds=$module_cmds
+	  fi
+	else
 	if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
-	  eval cmds=\"$archive_expsym_cmds\"
+	  eval test_cmds=\"$archive_expsym_cmds\"
+	  cmds=$archive_expsym_cmds
+	else
+	  eval test_cmds=\"$archive_cmds\"
+	  cmds=$archive_cmds
+	  fi
+	fi
+
+	if test "X$skipped_export" != "X:" && len=`expr "X$test_cmds" : ".*"` &&
+	   test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+	  :
 	else
-	  eval cmds=\"$archive_cmds\"
+	  # The command line is too long to link in one step, link piecewise.
+	  $echo "creating reloadable object files..."
+
+	  # Save the value of $output and $libobjs because we want to
+	  # use them later.  If we have whole_archive_flag_spec, we
+	  # want to use save_libobjs as it was before
+	  # whole_archive_flag_spec was expanded, because we can't
+	  # assume the linker understands whole_archive_flag_spec.
+	  # This may have to be revisited, in case too many
+	  # convenience libraries get linked in and end up exceeding
+	  # the spec.
+	  if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
+	    save_libobjs=$libobjs
+	  fi
+	  save_output=$output
+
+	  # Clear the reloadable object creation command queue and
+	  # initialize k to one.
+	  test_cmds=
+	  concat_cmds=
+	  objlist=
+	  delfiles=
+	  last_robj=
+	  k=1
+	  output=$output_objdir/$save_output-${k}.$objext
+	  # Loop over the list of objects to be linked.
+	  for obj in $save_libobjs
+	  do
+	    eval test_cmds=\"$reload_cmds $objlist $last_robj\"
+	    if test "X$objlist" = X ||
+	       { len=`expr "X$test_cmds" : ".*"` &&
+		 test "$len" -le "$max_cmd_len"; }; then
+	      objlist="$objlist $obj"
+	    else
+	      # The command $test_cmds is almost too long, add a
+	      # command to the queue.
+	      if test "$k" -eq 1 ; then
+		# The first file doesn't have a previous command to add.
+		eval concat_cmds=\"$reload_cmds $objlist $last_robj\"
+	      else
+		# All subsequent reloadable object files will link in
+		# the last one created.
+		eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\"
+	      fi
+	      last_robj=$output_objdir/$save_output-${k}.$objext
+	      k=`expr $k + 1`
+	      output=$output_objdir/$save_output-${k}.$objext
+	      objlist=$obj
+	      len=1
+	    fi
+	  done
+	  # Handle the remaining objects by creating one last
+	  # reloadable object file.  All subsequent reloadable object
+	  # files will link in the last one created.
+	  test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+	  eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\"
+
+	  if ${skipped_export-false}; then
+	    $show "generating symbol list for \`$libname.la'"
+	    export_symbols="$output_objdir/$libname.exp"
+	    $run $rm $export_symbols
+	    libobjs=$output
+	    # Append the command to create the export file.
+	    eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\"
+          fi
+
+	  # Set up a command to remove the reloadale object files
+	  # after they are used.
+	  i=0
+	  while test "$i" -lt "$k"
+	  do
+	    i=`expr $i + 1`
+	    delfiles="$delfiles $output_objdir/$save_output-${i}.$objext"
+	  done
+
+	  $echo "creating a temporary reloadable object file: $output"
+
+	  # Loop through the commands generated above and execute them.
+	  save_ifs="$IFS"; IFS='~'
+	  for cmd in $concat_cmds; do
+	    IFS="$save_ifs"
+	    $show "$cmd"
+	    $run eval "$cmd" || exit $?
+	  done
+	  IFS="$save_ifs"
+
+	  libobjs=$output
+	  # Restore the value of output.
+	  output=$save_output
+
+	  if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
+	    eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+	  fi
+	  # Expand the library linking commands again to reset the
+	  # value of $libobjs for piecewise linking.
+
+	  # Do each of the archive commands.
+	  if test "$module" = yes && test -n "$module_cmds" ; then
+	    if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+	      cmds=$module_expsym_cmds
+	    else
+	      cmds=$module_cmds
+	    fi
+	  else
+	  if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+	    cmds=$archive_expsym_cmds
+	  else
+	    cmds=$archive_cmds
+	    fi
+	  fi
+
+	  # Append the command to remove the reloadable object files
+	  # to the just-reset $cmds.
+	  eval cmds=\"\$cmds~\$rm $delfiles\"
 	fi
 	save_ifs="$IFS"; IFS='~'
 	for cmd in $cmds; do
 	  IFS="$save_ifs"
+	  eval cmd=\"$cmd\"
 	  $show "$cmd"
 	  $run eval "$cmd" || exit $?
 	done
@@ -2921,7 +4007,7 @@ EOF
 	# Restore the uninstalled library and exit
 	if test "$mode" = relink; then
 	  $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $?
-	  exit 0
+	  exit $EXIT_SUCCESS
 	fi
 
 	# Create links to the real library.
@@ -2969,7 +4055,7 @@ EOF
       *.lo)
 	if test -n "$objs$old_deplibs"; then
 	  $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2
-	  exit 1
+	  exit $EXIT_FAILURE
 	fi
 	libobj="$output"
 	obj=`$echo "X$output" | $Xsed -e "$lo2o"`
@@ -2998,38 +4084,10 @@ EOF
 	  eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\"
 	else
 	  gentop="$output_objdir/${obj}x"
-	  $show "${rm}r $gentop"
-	  $run ${rm}r "$gentop"
-	  $show "mkdir $gentop"
-	  $run mkdir "$gentop"
-	  status=$?
-	  if test $status -ne 0 && test ! -d "$gentop"; then
-	    exit $status
-	  fi
 	  generated="$generated $gentop"
 
-	  for xlib in $convenience; do
-	    # Extract the objects.
-	    case $xlib in
-	    [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
-	    *) xabs=`pwd`"/$xlib" ;;
-	    esac
-	    xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
-	    xdir="$gentop/$xlib"
-
-	    $show "${rm}r $xdir"
-	    $run ${rm}r "$xdir"
-	    $show "mkdir $xdir"
-	    $run mkdir "$xdir"
-	    status=$?
-	    if test $status -ne 0 && test ! -d "$xdir"; then
-	      exit $status
-	    fi
-	    $show "(cd $xdir && $AR x $xabs)"
-	    $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
-
-	    reload_conv_objs="$reload_objs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP`
-	  done
+	  func_extract_archives $gentop $convenience
+	  reload_conv_objs="$reload_objs $func_extract_archives_result"
 	fi
       fi
 
@@ -3037,10 +4095,11 @@ EOF
       reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
 
       output="$obj"
-      eval cmds=\"$reload_cmds\"
+      cmds=$reload_cmds
       save_ifs="$IFS"; IFS='~'
       for cmd in $cmds; do
 	IFS="$save_ifs"
+	eval cmd=\"$cmd\"
 	$show "$cmd"
 	$run eval "$cmd" || exit $?
       done
@@ -3053,7 +4112,7 @@ EOF
 	  $run ${rm}r $gentop
 	fi
 
-	exit 0
+	exit $EXIT_SUCCESS
       fi
 
       if test "$build_libtool_libs" != yes; then
@@ -3064,37 +4123,24 @@ EOF
 
 	# Create an invalid libtool object if no PIC, so that we don't
 	# accidentally link it into a program.
-	$show "echo timestamp > $libobj"
-	$run eval "echo timestamp > $libobj" || exit $?
-	exit 0
+	# $show "echo timestamp > $libobj"
+	# $run eval "echo timestamp > $libobj" || exit $?
+	exit $EXIT_SUCCESS
       fi
 
       if test -n "$pic_flag" || test "$pic_mode" != default; then
 	# Only do commands if we really have different PIC objects.
 	reload_objs="$libobjs $reload_conv_objs"
 	output="$libobj"
-	eval cmds=\"$reload_cmds\"
+	cmds=$reload_cmds
 	save_ifs="$IFS"; IFS='~'
 	for cmd in $cmds; do
 	  IFS="$save_ifs"
+	  eval cmd=\"$cmd\"
 	  $show "$cmd"
 	  $run eval "$cmd" || exit $?
 	done
 	IFS="$save_ifs"
-      else
-	# Just create a symlink.
-	$show $rm $libobj
-	$run $rm $libobj
-	xdir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'`
-	if test "X$xdir" = "X$libobj"; then
-	  xdir="."
-	else
-	  xdir="$xdir"
-	fi
-	baseobj=`$echo "X$libobj" | $Xsed -e 's%^.*/%%'`
-	oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"`
-	$show "(cd $xdir && $LN_S $oldobj $baseobj)"
-	$run eval '(cd $xdir && $LN_S $oldobj $baseobj)' || exit $?
       fi
 
       if test -n "$gentop"; then
@@ -3102,12 +4148,12 @@ EOF
 	$run ${rm}r $gentop
       fi
 
-      exit 0
+      exit $EXIT_SUCCESS
       ;;
 
     prog)
       case $host in
-	*cygwin*) output=`echo $output | sed -e 's,.exe$,,;s,$,.exe,'` ;;
+	*cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;;
       esac
       if test -n "$vinfo"; then
 	$echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
@@ -3132,6 +4178,16 @@ EOF
 	;;
       esac
 
+      case $host in
+      *darwin*)
+        # Don't allow lazy linking, it breaks C++ global constructors
+        if test "$tagname" = CXX ; then
+        compile_command="$compile_command ${wl}-bind_at_load"
+        finalize_command="$finalize_command ${wl}-bind_at_load"
+        fi
+        ;;
+      esac
+
       compile_command="$compile_command $compile_deplibs"
       finalize_command="$finalize_command $finalize_deplibs"
 
@@ -3282,12 +4338,12 @@ extern \"C\" {
 	    done
 
 	    if test -n "$exclude_expsyms"; then
-	      $run eval 'egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+	      $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
 	      $run eval '$mv "$nlist"T "$nlist"'
 	    fi
 
 	    if test -n "$export_symbols_regex"; then
-	      $run eval 'egrep -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+	      $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
 	      $run eval '$mv "$nlist"T "$nlist"'
 	    fi
 
@@ -3295,9 +4351,9 @@ extern \"C\" {
 	    if test -z "$export_symbols"; then
 	      export_symbols="$output_objdir/$output.exp"
 	      $run $rm $export_symbols
-	      $run eval "sed -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+	      $run eval "${SED} -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
 	    else
-	      $run eval "sed -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"'
+	      $run eval "${SED} -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"'
 	      $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T'
 	      $run eval 'mv "$nlist"T "$nlist"'
 	    fi
@@ -3305,8 +4361,8 @@ extern \"C\" {
 
 	  for arg in $dlprefiles; do
 	    $show "extracting global C symbols from \`$arg'"
-	    name=`echo "$arg" | sed -e 's%^.*/%%'`
-	    $run eval 'echo ": $name " >> "$nlist"'
+	    name=`$echo "$arg" | ${SED} -e 's%^.*/%%'`
+	    $run eval '$echo ": $name " >> "$nlist"'
 	    $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
 	  done
 
@@ -3315,12 +4371,18 @@ extern \"C\" {
 	    test -f "$nlist" || : > "$nlist"
 
 	    if test -n "$exclude_expsyms"; then
-	      egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+	      $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
 	      $mv "$nlist"T "$nlist"
 	    fi
 
 	    # Try sorting and uniquifying the output.
-	    if grep -v "^: " < "$nlist" | sort +2 | uniq > "$nlist"S; then
+	    if grep -v "^: " < "$nlist" |
+		if sort -k 3 </dev/null >/dev/null 2>&1; then
+		  sort -k 3
+		else
+		  sort +2
+		fi |
+		uniq > "$nlist"S; then
 	      :
 	    else
 	      grep -v "^: " < "$nlist" > "$nlist"S
@@ -3329,7 +4391,7 @@ extern \"C\" {
 	    if test -f "$nlist"S; then
 	      eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"'
 	    else
-	      echo '/* NONE */' >> "$output_objdir/$dlsyms"
+	      $echo '/* NONE */' >> "$output_objdir/$dlsyms"
 	    fi
 
 	    $echo >> "$output_objdir/$dlsyms" "\
@@ -3381,18 +4443,18 @@ static const void *lt_preloaded_setup() {
 	  *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
 	    case "$compile_command " in
 	    *" -static "*) ;;
-	    *) pic_flag_for_symtable=" $pic_flag -DPIC -DFREEBSD_WORKAROUND";;
+	    *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";;
 	    esac;;
 	  *-*-hpux*)
 	    case "$compile_command " in
 	    *" -static "*) ;;
-	    *) pic_flag_for_symtable=" $pic_flag -DPIC";;
+	    *) pic_flag_for_symtable=" $pic_flag";;
 	    esac
 	  esac
 
 	  # Now compile the dynamic symbol file.
-	  $show "(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
-	  $run eval '(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
+	  $show "(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
+	  $run eval '(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
 
 	  # Clean up the generated files.
 	  $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
@@ -3404,7 +4466,7 @@ static const void *lt_preloaded_setup() {
 	  ;;
 	*)
 	  $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
-	  exit 1
+	  exit $EXIT_FAILURE
 	  ;;
 	esac
       else
@@ -3417,7 +4479,7 @@ static const void *lt_preloaded_setup() {
 	finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
       fi
 
-      if test $need_relink = no || test "$build_libtool_libs" != yes; then
+      if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
 	# Replace the output file specification.
 	compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
 	link_command="$compile_command$compile_rpath"
@@ -3492,7 +4554,7 @@ static const void *lt_preloaded_setup() {
 	# Link the executable and exit
 	$show "$link_command"
 	$run eval "$link_command" || exit $?
-	exit 0
+	exit $EXIT_SUCCESS
       fi
 
       if test "$hardcode_action" = relink; then
@@ -3542,15 +4604,15 @@ static const void *lt_preloaded_setup() {
 	    relink_command="$var=\"$var_value\"; export $var; $relink_command"
 	  fi
 	done
-	relink_command="cd `pwd`; $relink_command"
+	relink_command="(cd `pwd`; $relink_command)"
 	relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
       fi
 
       # Quote $echo for shipping.
-      if test "X$echo" = "X$SHELL $0 --fallback-echo"; then
-	case $0 in
-	[\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";;
-	*) qecho="$SHELL `pwd`/$0 --fallback-echo";;
+      if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then
+	case $progpath in
+	[\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";;
+	*) qecho="$SHELL `pwd`/$progpath --fallback-echo";;
 	esac
 	qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"`
       else
@@ -3562,15 +4624,230 @@ static const void *lt_preloaded_setup() {
 	# win32 will think the script is a binary if it has
 	# a .exe suffix, so we strip it off here.
 	case $output in
-	  *.exe) output=`echo $output|sed 's,.exe$,,'` ;;
+	  *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;;
 	esac
 	# test for cygwin because mv fails w/o .exe extensions
 	case $host in
-	  *cygwin*) exeext=.exe ;;
+	  *cygwin*)
+	    exeext=.exe
+	    outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;;
 	  *) exeext= ;;
 	esac
+	case $host in
+	  *cygwin* | *mingw* )
+	    cwrappersource=`$echo ${objdir}/lt-${output}.c`
+	    cwrapper=`$echo ${output}.exe`
+	    $rm $cwrappersource $cwrapper
+	    trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
+
+	    cat > $cwrappersource <<EOF
+
+/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
+   Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+
+   The $output program cannot be directly executed until all the libtool
+   libraries that it depends on are installed.
+
+   This wrapper executable should never be moved out of the build directory.
+   If it is, it will not operate correctly.
+
+   Currently, it simply execs the wrapper *script* "/bin/sh $output",
+   but could eventually absorb all of the scripts functionality and
+   exec $objdir/$outputname directly.
+*/
+EOF
+	    cat >> $cwrappersource<<"EOF"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+
+#if defined(PATH_MAX)
+# define LT_PATHMAX PATH_MAX
+#elif defined(MAXPATHLEN)
+# define LT_PATHMAX MAXPATHLEN
+#else
+# define LT_PATHMAX 1024
+#endif
+
+#ifndef DIR_SEPARATOR
+#define DIR_SEPARATOR '/'
+#endif
+
+#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
+  defined (__OS2__)
+#define HAVE_DOS_BASED_FILE_SYSTEM
+#ifndef DIR_SEPARATOR_2
+#define DIR_SEPARATOR_2 '\\'
+#endif
+#endif
+
+#ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+#else /* DIR_SEPARATOR_2 */
+# define IS_DIR_SEPARATOR(ch) \
+        (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+#endif /* DIR_SEPARATOR_2 */
+
+#define XMALLOC(type, num)      ((type *) xmalloc ((num) * sizeof(type)))
+#define XFREE(stale) do { \
+  if (stale) { free ((void *) stale); stale = 0; } \
+} while (0)
+
+const char *program_name = NULL;
+
+void * xmalloc (size_t num);
+char * xstrdup (const char *string);
+char * basename (const char *name);
+char * fnqualify(const char *path);
+char * strendzap(char *str, const char *pat);
+void lt_fatal (const char *message, ...);
+
+int
+main (int argc, char *argv[])
+{
+  char **newargz;
+  int i;
+
+  program_name = (char *) xstrdup ((char *) basename (argv[0]));
+  newargz = XMALLOC(char *, argc+2);
+EOF
+
+	    cat >> $cwrappersource <<EOF
+  newargz[0] = "$SHELL";
+EOF
+
+	    cat >> $cwrappersource <<"EOF"
+  newargz[1] = fnqualify(argv[0]);
+  /* we know the script has the same name, without the .exe */
+  /* so make sure newargz[1] doesn't end in .exe */
+  strendzap(newargz[1],".exe");
+  for (i = 1; i < argc; i++)
+    newargz[i+1] = xstrdup(argv[i]);
+  newargz[argc+1] = NULL;
+EOF
+
+	    cat >> $cwrappersource <<EOF
+  execv("$SHELL",newargz);
+EOF
+
+	    cat >> $cwrappersource <<"EOF"
+}
+
+void *
+xmalloc (size_t num)
+{
+  void * p = (void *) malloc (num);
+  if (!p)
+    lt_fatal ("Memory exhausted");
+
+  return p;
+}
+
+char *
+xstrdup (const char *string)
+{
+  return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL
+;
+}
+
+char *
+basename (const char *name)
+{
+  const char *base;
+
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  /* Skip over the disk name in MSDOS pathnames. */
+  if (isalpha (name[0]) && name[1] == ':')
+    name += 2;
+#endif
+
+  for (base = name; *name; name++)
+    if (IS_DIR_SEPARATOR (*name))
+      base = name + 1;
+  return (char *) base;
+}
+
+char *
+fnqualify(const char *path)
+{
+  size_t size;
+  char *p;
+  char tmp[LT_PATHMAX + 1];
+
+  assert(path != NULL);
+
+  /* Is it qualified already? */
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  if (isalpha (path[0]) && path[1] == ':')
+    return xstrdup (path);
+#endif
+  if (IS_DIR_SEPARATOR (path[0]))
+    return xstrdup (path);
+
+  /* prepend the current directory */
+  /* doesn't handle '~' */
+  if (getcwd (tmp, LT_PATHMAX) == NULL)
+    lt_fatal ("getcwd failed");
+  size = strlen(tmp) + 1 + strlen(path) + 1; /* +2 for '/' and '\0' */
+  p = XMALLOC(char, size);
+  sprintf(p, "%s%c%s", tmp, DIR_SEPARATOR, path);
+  return p;
+}
+
+char *
+strendzap(char *str, const char *pat)
+{
+  size_t len, patlen;
+
+  assert(str != NULL);
+  assert(pat != NULL);
+
+  len = strlen(str);
+  patlen = strlen(pat);
+
+  if (patlen <= len)
+  {
+    str += len - patlen;
+    if (strcmp(str, pat) == 0)
+      *str = '\0';
+  }
+  return str;
+}
+
+static void
+lt_error_core (int exit_status, const char * mode,
+          const char * message, va_list ap)
+{
+  fprintf (stderr, "%s: %s: ", program_name, mode);
+  vfprintf (stderr, message, ap);
+  fprintf (stderr, ".\n");
+
+  if (exit_status >= 0)
+    exit (exit_status);
+}
+
+void
+lt_fatal (const char *message, ...)
+{
+  va_list ap;
+  va_start (ap, message);
+  lt_error_core (EXIT_FAILURE, "FATAL", message, ap);
+  va_end (ap);
+}
+EOF
+	  # we should really use a build-platform specific compiler
+	  # here, but OTOH, the wrappers (shell script and this C one)
+	  # are only useful if you want to execute the "real" binary.
+	  # Since the "real" binary is built for $host, then this
+	  # wrapper might as well be built for $host, too.
+	  $run $LTCC -s -o $cwrapper $cwrappersource
+	  ;;
+	esac
 	$rm $output
-	trap "$rm $output; exit 1" 1 2 15
+	trap "$rm $output; exit $EXIT_FAILURE" 1 2 15
 
 	$echo > $output "\
 #! $SHELL
@@ -3586,12 +4863,12 @@ static const void *lt_preloaded_setup() {
 
 # Sed substitution that helps us do robust quoting.  It backslashifies
 # metacharacters that are still active within double-quoted strings.
-Xsed='sed -e 1s/^X//'
+Xsed='${SED} -e 1s/^X//'
 sed_quote_subst='$sed_quote_subst'
 
 # The HP-UX ksh and POSIX shell print the target directory to stdout
 # if CDPATH is set.
-if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
 
 relink_command=\"$relink_command\"
 
@@ -3624,7 +4901,7 @@ else
   test \"x\$thisdir\" = \"x\$file\" && thisdir=.
 
   # Follow symbolic links until we get to the real thisdir.
-  file=\`ls -ld \"\$file\" | sed -n 's/.*-> //p'\`
+  file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\`
   while test -n \"\$file\"; do
     destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
 
@@ -3637,7 +4914,7 @@ else
     fi
 
     file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
-    file=\`ls -ld \"\$thisdir/\$file\" | sed -n 's/.*-> //p'\`
+    file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\`
   done
 
   # Try to get the absolute directory name.
@@ -3646,12 +4923,12 @@ else
 "
 
 	if test "$fast_install" = yes; then
-	  echo >> $output "\
+	  $echo >> $output "\
   program=lt-'$outputname'$exeext
   progdir=\"\$thisdir/$objdir\"
 
   if test ! -f \"\$progdir/\$program\" || \\
-     { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | sed 1q\`; \\
+     { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
        test \"X\$file\" != \"X\$progdir/\$program\"; }; then
 
     file=\"\$\$-\$program\"
@@ -3662,7 +4939,7 @@ else
       $rm \"\$progdir/\$file\"
     fi"
 
-	  echo >> $output "\
+	  $echo >> $output "\
 
     # relink executable if necessary
     if test -n \"\$relink_command\"; then
@@ -3670,7 +4947,7 @@ else
       else
 	$echo \"\$relink_command_output\" >&2
 	$rm \"\$progdir/\$file\"
-	exit 1
+	exit $EXIT_FAILURE
       fi
     fi
 
@@ -3680,13 +4957,13 @@ else
     $rm \"\$progdir/\$file\"
   fi"
 	else
-	  echo >> $output "\
+	  $echo >> $output "\
   program='$outputname'
   progdir=\"\$thisdir/$objdir\"
 "
 	fi
 
-	echo >> $output "\
+	$echo >> $output "\
 
   if test -f \"\$progdir/\$program\"; then"
 
@@ -3717,14 +4994,6 @@ else
       # Run the actual program with our arguments.
 "
 	case $host in
-	# win32 systems need to use the prog path for dll
-	# lookup to work
-	*-*-cygwin* | *-*-pw32*)
-	  $echo >> $output "\
-      exec \$progdir/\$program \${1+\"\$@\"}
-"
-	  ;;
-
 	# Backslashes separate directories on plain windows
 	*-*-mingw | *-*-os2*)
 	  $echo >> $output "\
@@ -3734,30 +5003,26 @@ else
 
 	*)
 	  $echo >> $output "\
-      # Export the path to the program.
-      PATH=\"\$progdir:\$PATH\"
-      export PATH
-
-      exec \$program \${1+\"\$@\"}
+      exec \$progdir/\$program \${1+\"\$@\"}
 "
 	  ;;
 	esac
 	$echo >> $output "\
       \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\"
-      exit 1
+      exit $EXIT_FAILURE
     fi
   else
     # The program doesn't exist.
     \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2
     \$echo \"This script is just a wrapper for \$program.\" 1>&2
-    echo \"See the $PACKAGE documentation for more information.\" 1>&2
-    exit 1
+    $echo \"See the $PACKAGE documentation for more information.\" 1>&2
+    exit $EXIT_FAILURE
   fi
 fi\
 "
 	chmod +x $output
       fi
-      exit 0
+      exit $EXIT_SUCCESS
       ;;
     esac
 
@@ -3773,74 +5038,86 @@ fi\
 	  oldobjs="$libobjs_save"
 	  build_libtool_libs=no
 	else
-	  oldobjs="$objs$old_deplibs "`$echo "X$libobjs_save" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`
+	  oldobjs="$old_deplibs $non_pic_objects"
 	fi
 	addlibs="$old_convenience"
       fi
 
       if test -n "$addlibs"; then
 	gentop="$output_objdir/${outputname}x"
-	$show "${rm}r $gentop"
-	$run ${rm}r "$gentop"
-	$show "mkdir $gentop"
-	$run mkdir "$gentop"
-	status=$?
-	if test $status -ne 0 && test ! -d "$gentop"; then
-	  exit $status
-	fi
 	generated="$generated $gentop"
 
-	# Add in members from convenience archives.
-	for xlib in $addlibs; do
-	  # Extract the objects.
-	  case $xlib in
-	  [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
-	  *) xabs=`pwd`"/$xlib" ;;
-	  esac
-	  xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
-	  xdir="$gentop/$xlib"
-
-	  $show "${rm}r $xdir"
-	  $run ${rm}r "$xdir"
-	  $show "mkdir $xdir"
-	  $run mkdir "$xdir"
-	  status=$?
-	  if test $status -ne 0 && test ! -d "$xdir"; then
-	    exit $status
-	  fi
-	  $show "(cd $xdir && $AR x $xabs)"
-	  $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
-
-	  oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP`
-	done
+	func_extract_archives $gentop $addlibs
+	oldobjs="$oldobjs $func_extract_archives_result"
       fi
 
       # Do each command in the archive commands.
       if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
-	eval cmds=\"$old_archive_from_new_cmds\"
+       cmds=$old_archive_from_new_cmds
       else
-	# Ensure that we have .o objects in place in case we decided
-	# not to build a shared library, and have fallen back to building
-	# static libs even though --disable-static was passed!
-	for oldobj in $oldobjs; do
-	  if test ! -f $oldobj; then
-	    xdir=`$echo "X$oldobj" | $Xsed -e 's%/[^/]*$%%'`
-	    if test "X$xdir" = "X$oldobj"; then
-	      xdir="."
+	eval cmds=\"$old_archive_cmds\"
+
+	if len=`expr "X$cmds" : ".*"` &&
+	     test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+	  cmds=$old_archive_cmds
+	else
+	  # the command line is too long to link in one step, link in parts
+	  $echo "using piecewise archive linking..."
+	  save_RANLIB=$RANLIB
+	  RANLIB=:
+	  objlist=
+	  concat_cmds=
+	  save_oldobjs=$oldobjs
+	  # GNU ar 2.10+ was changed to match POSIX; thus no paths are
+	  # encoded into archives.  This makes 'ar r' malfunction in
+	  # this piecewise linking case whenever conflicting object
+	  # names appear in distinct ar calls; check, warn and compensate.
+	    if (for obj in $save_oldobjs
+	    do
+	      $echo "X$obj" | $Xsed -e 's%^.*/%%'
+	    done | sort | sort -uc >/dev/null 2>&1); then
+	    :
+	  else
+	    $echo "$modename: warning: object name conflicts; overriding AR_FLAGS to 'cq'" 1>&2
+	    $echo "$modename: warning: to ensure that POSIX-compatible ar will work" 1>&2
+	    AR_FLAGS=cq
+	  fi
+	  # Is there a better way of finding the last object in the list?
+	  for obj in $save_oldobjs
+	  do
+	    last_oldobj=$obj
+	  done
+	  for obj in $save_oldobjs
+	  do
+	    oldobjs="$objlist $obj"
+	    objlist="$objlist $obj"
+	    eval test_cmds=\"$old_archive_cmds\"
+	    if len=`expr "X$test_cmds" : ".*"` &&
+	       test "$len" -le "$max_cmd_len"; then
+	      :
 	    else
-	      xdir="$xdir"
+	      # the above command should be used before it gets too long
+	      oldobjs=$objlist
+	      if test "$obj" = "$last_oldobj" ; then
+	        RANLIB=$save_RANLIB
+	      fi
+	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+	      eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\"
+	      objlist=
 	    fi
-	    baseobj=`$echo "X$oldobj" | $Xsed -e 's%^.*/%%'`
-	    obj=`$echo "X$baseobj" | $Xsed -e "$o2lo"`
-	    $show "(cd $xdir && ${LN_S} $obj $baseobj)"
-	    $run eval '(cd $xdir && ${LN_S} $obj $baseobj)' || exit $?
+	  done
+	  RANLIB=$save_RANLIB
+	  oldobjs=$objlist
+	  if test "X$oldobjs" = "X" ; then
+	    eval cmds=\"\$concat_cmds\"
+	  else
+	    eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
 	  fi
-	done
-
-	eval cmds=\"$old_archive_cmds\"
+	fi
       fi
       save_ifs="$IFS"; IFS='~'
       for cmd in $cmds; do
+        eval cmd=\"$cmd\"
 	IFS="$save_ifs"
 	$show "$cmd"
 	$run eval "$cmd" || exit $?
@@ -3872,8 +5149,12 @@ fi\
 	fi
       done
       # Quote the link command for shipping.
-      relink_command="cd `pwd`; $SHELL $0 --mode=relink $libtool_args"
+      relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
       relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+      if test "$hardcode_automatic" = yes ; then
+	relink_command=
+      fi
+
 
       # Only create the output if not a dry run.
       if test -z "$run"; then
@@ -3889,10 +5170,10 @@ fi\
 	      case $deplib in
 	      *.la)
 		name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'`
-		eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+		eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
 		if test -z "$libdir"; then
 		  $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
-		  exit 1
+		  exit $EXIT_FAILURE
 		fi
 		newdependency_libs="$newdependency_libs $libdir/$name"
 		;;
@@ -3903,10 +5184,10 @@ fi\
 	    newdlfiles=
 	    for lib in $dlfiles; do
 	      name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
-	      eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+	      eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
 	      if test -z "$libdir"; then
 		$echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
-		exit 1
+		exit $EXIT_FAILURE
 	      fi
 	      newdlfiles="$newdlfiles $libdir/$name"
 	    done
@@ -3914,20 +5195,39 @@ fi\
 	    newdlprefiles=
 	    for lib in $dlprefiles; do
 	      name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
-	      eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+	      eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
 	      if test -z "$libdir"; then
 		$echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
-		exit 1
+		exit $EXIT_FAILURE
 	      fi
 	      newdlprefiles="$newdlprefiles $libdir/$name"
 	    done
 	    dlprefiles="$newdlprefiles"
+	  else
+	    newdlfiles=
+	    for lib in $dlfiles; do
+	      case $lib in
+		[\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+		*) abs=`pwd`"/$lib" ;;
+	      esac
+	      newdlfiles="$newdlfiles $abs"
+	    done
+	    dlfiles="$newdlfiles"
+	    newdlprefiles=
+	    for lib in $dlprefiles; do
+	      case $lib in
+		[\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+		*) abs=`pwd`"/$lib" ;;
+	      esac
+	      newdlprefiles="$newdlprefiles $abs"
+	    done
+	    dlprefiles="$newdlprefiles"
 	  fi
 	  $rm $output
 	  # place dlname in correct position for cygwin
 	  tdlname=$dlname
 	  case $host,$output,$installed,$module,$dlname in
-	    *cygwin*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
+	    *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
 	  esac
 	  $echo > $output "\
 # $outputname - a libtool library file
@@ -3956,13 +5256,16 @@ revision=$revision
 # Is this an already installed library?
 installed=$installed
 
+# Should we warn about portability when linking against -modules?
+shouldnotlink=$module
+
 # Files to dlopen/dlpreopen
 dlopen='$dlfiles'
 dlpreopen='$dlprefiles'
 
 # Directory that this library needs to be installed in:
 libdir='$install_libdir'"
-	  if test "$installed" = no && test $need_relink = yes; then
+	  if test "$installed" = no && test "$need_relink" = yes; then
 	    $echo >> $output "\
 relink_command=\"$relink_command\""
 	  fi
@@ -3975,7 +5278,7 @@ relink_command=\"$relink_command\""
       $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $?
       ;;
     esac
-    exit 0
+    exit $EXIT_SUCCESS
     ;;
 
   # libtool install mode
@@ -4064,13 +5367,13 @@ relink_command=\"$relink_command\""
     if test -z "$install_prog"; then
       $echo "$modename: you must specify an install program" 1>&2
       $echo "$help" 1>&2
-      exit 1
+      exit $EXIT_FAILURE
     fi
 
     if test -n "$prev"; then
       $echo "$modename: the \`$prev' option requires an argument" 1>&2
       $echo "$help" 1>&2
-      exit 1
+      exit $EXIT_FAILURE
     fi
 
     if test -z "$files"; then
@@ -4080,7 +5383,7 @@ relink_command=\"$relink_command\""
 	$echo "$modename: you must specify a destination" 1>&2
       fi
       $echo "$help" 1>&2
-      exit 1
+      exit $EXIT_FAILURE
     fi
 
     # Strip any trailing slash from the destination.
@@ -4098,10 +5401,10 @@ relink_command=\"$relink_command\""
 
       # Not a directory, so check to see that there is only one file specified.
       set dummy $files
-      if test $# -gt 2; then
+      if test "$#" -gt 2; then
 	$echo "$modename: \`$dest' is not a directory" 1>&2
 	$echo "$help" 1>&2
-	exit 1
+	exit $EXIT_FAILURE
       fi
     fi
     case $destdir in
@@ -4113,7 +5416,7 @@ relink_command=\"$relink_command\""
 	*)
 	  $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2
 	  $echo "$help" 1>&2
-	  exit 1
+	  exit $EXIT_FAILURE
 	  ;;
 	esac
       done
@@ -4138,11 +5441,11 @@ relink_command=\"$relink_command\""
 
       *.la)
 	# Check to see that this really is a libtool archive.
-	if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+	if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
 	else
 	  $echo "$modename: \`$file' is not a valid libtool archive" 1>&2
 	  $echo "$help" 1>&2
-	  exit 1
+	  exit $EXIT_FAILURE
 	fi
 
 	library_names=
@@ -4173,12 +5476,33 @@ relink_command=\"$relink_command\""
 	dir="$dir$objdir"
 
 	if test -n "$relink_command"; then
+	  # Determine the prefix the user has applied to our future dir.
+	  inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"`
+
+	  # Don't allow the user to place us outside of our expected
+	  # location b/c this prevents finding dependent libraries that
+	  # are installed to the same prefix.
+	  # At present, this check doesn't affect windows .dll's that
+	  # are installed into $libdir/../bin (currently, that works fine)
+	  # but it's something to keep an eye on.
+	  if test "$inst_prefix_dir" = "$destdir"; then
+	    $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2
+	    exit $EXIT_FAILURE
+	  fi
+
+	  if test -n "$inst_prefix_dir"; then
+	    # Stick the inst_prefix_dir data into the link command.
+	    relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
+	  else
+	    relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
+	  fi
+
 	  $echo "$modename: warning: relinking \`$file'" 1>&2
 	  $show "$relink_command"
 	  if $run eval "$relink_command"; then :
 	  else
 	    $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
-	    continue
+	    exit $EXIT_FAILURE
 	  fi
 	fi
 
@@ -4200,7 +5524,7 @@ relink_command=\"$relink_command\""
 	    $run eval "$striplib $destdir/$realname" || exit $?
 	  fi
 
-	  if test $# -gt 0; then
+	  if test "$#" -gt 0; then
 	    # Delete the old symlinks, and create new ones.
 	    for linkname
 	    do
@@ -4213,10 +5537,11 @@ relink_command=\"$relink_command\""
 
 	  # Do each command in the postinstall commands.
 	  lib="$destdir/$realname"
-	  eval cmds=\"$postinstall_cmds\"
+	  cmds=$postinstall_cmds
 	  save_ifs="$IFS"; IFS='~'
 	  for cmd in $cmds; do
 	    IFS="$save_ifs"
+	    eval cmd=\"$cmd\"
 	    $show "$cmd"
 	    $run eval "$cmd" || exit $?
 	  done
@@ -4256,7 +5581,7 @@ relink_command=\"$relink_command\""
 	*)
 	  $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2
 	  $echo "$help" 1>&2
-	  exit 1
+	  exit $EXIT_FAILURE
 	  ;;
 	esac
 
@@ -4274,7 +5599,7 @@ relink_command=\"$relink_command\""
 	  $show "$install_prog $staticobj $staticdest"
 	  $run eval "$install_prog \$staticobj \$staticdest" || exit $?
 	fi
-	exit 0
+	exit $EXIT_SUCCESS
 	;;
 
       *)
@@ -4286,21 +5611,49 @@ relink_command=\"$relink_command\""
 	  destfile="$destdir/$destfile"
 	fi
 
+	# If the file is missing, and there is a .exe on the end, strip it
+	# because it is most likely a libtool script we actually want to
+	# install
+	stripped_ext=""
+	case $file in
+	  *.exe)
+	    if test ! -f "$file"; then
+	      file=`$echo $file|${SED} 's,.exe$,,'`
+	      stripped_ext=".exe"
+	    fi
+	    ;;
+	esac
+
 	# Do a test to see if this is really a libtool program.
-	if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+	case $host in
+	*cygwin*|*mingw*)
+	    wrapper=`$echo $file | ${SED} -e 's,.exe$,,'`
+	    ;;
+	*)
+	    wrapper=$file
+	    ;;
+	esac
+	if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then
 	  notinst_deplibs=
 	  relink_command=
 
+	  # To insure that "foo" is sourced, and not "foo.exe",
+	  # finese the cygwin/MSYS system by explicitly sourcing "foo."
+	  # which disallows the automatic-append-.exe behavior.
+	  case $build in
+	  *cygwin* | *mingw*) wrapperdot=${wrapper}. ;;
+	  *) wrapperdot=${wrapper} ;;
+	  esac
 	  # If there is no directory component, then add one.
 	  case $file in
-	  */* | *\\*) . $file ;;
-	  *) . ./$file ;;
+	  */* | *\\*) . ${wrapperdot} ;;
+	  *) . ./${wrapperdot} ;;
 	  esac
 
 	  # Check the variables that should have been set.
 	  if test -z "$notinst_deplibs"; then
-	    $echo "$modename: invalid libtool wrapper script \`$file'" 1>&2
-	    exit 1
+	    $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2
+	    exit $EXIT_FAILURE
 	  fi
 
 	  finalize=yes
@@ -4322,10 +5675,17 @@ relink_command=\"$relink_command\""
 	  done
 
 	  relink_command=
+	  # To insure that "foo" is sourced, and not "foo.exe",
+	  # finese the cygwin/MSYS system by explicitly sourcing "foo."
+	  # which disallows the automatic-append-.exe behavior.
+	  case $build in
+	  *cygwin* | *mingw*) wrapperdot=${wrapper}. ;;
+	  *) wrapperdot=${wrapper} ;;
+	  esac
 	  # If there is no directory component, then add one.
 	  case $file in
-	  */* | *\\*) . $file ;;
-	  *) . ./$file ;;
+	  */* | *\\*) . ${wrapperdot} ;;
+	  *) . ./${wrapperdot} ;;
 	  esac
 
 	  outputname=
@@ -4334,12 +5694,16 @@ relink_command=\"$relink_command\""
 	      tmpdir="/tmp"
 	      test -n "$TMPDIR" && tmpdir="$TMPDIR"
 	      tmpdir="$tmpdir/libtool-$$"
-	      if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then :
+	      save_umask=`umask`
+	      umask 0077
+	      if $mkdir "$tmpdir"; then
+	        umask $save_umask
 	      else
+	        umask $save_umask
 		$echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2
 		continue
 	      fi
-	      file=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+	      file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'`
 	      outputname="$tmpdir/$file"
 	      # Replace the output file specification.
 	      relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
@@ -4357,14 +5721,14 @@ relink_command=\"$relink_command\""
 	    fi
 	  else
 	    # Install the binary that we compiled earlier.
-	    file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
+	    file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
 	  fi
 	fi
 
 	# remove .exe since cygwin /usr/bin/install will append another
 	# one anyways
 	case $install_prog,$host in
-	/usr/bin/install*,*cygwin*)
+	*/usr/bin/install*,*cygwin*)
 	  case $file:$destfile in
 	  *.exe:*.exe)
 	    # this is ok
@@ -4373,7 +5737,7 @@ relink_command=\"$relink_command\""
 	    destfile=$destfile.exe
 	    ;;
 	  *:*.exe)
-	    destfile=`echo $destfile | sed -e 's,.exe$,,'`
+	    destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'`
 	    ;;
 	  esac
 	  ;;
@@ -4394,16 +5758,17 @@ relink_command=\"$relink_command\""
       $show "$install_prog $file $oldlib"
       $run eval "$install_prog \$file \$oldlib" || exit $?
 
-      if test -n "$stripme" && test -n "$striplib"; then
+      if test -n "$stripme" && test -n "$old_striplib"; then
 	$show "$old_striplib $oldlib"
 	$run eval "$old_striplib $oldlib" || exit $?
       fi
 
       # Do each command in the postinstall commands.
-      eval cmds=\"$old_postinstall_cmds\"
+      cmds=$old_postinstall_cmds
       save_ifs="$IFS"; IFS='~'
       for cmd in $cmds; do
 	IFS="$save_ifs"
+	eval cmd=\"$cmd\"
 	$show "$cmd"
 	$run eval "$cmd" || exit $?
       done
@@ -4417,9 +5782,9 @@ relink_command=\"$relink_command\""
     if test -n "$current_libdirs"; then
       # Maybe just do a dry run.
       test -n "$run" && current_libdirs=" -n$current_libdirs"
-      exec_cmd='$SHELL $0 --finish$current_libdirs'
+      exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs'
     else
-      exit 0
+      exit $EXIT_SUCCESS
     fi
     ;;
 
@@ -4438,10 +5803,11 @@ relink_command=\"$relink_command\""
       for libdir in $libdirs; do
 	if test -n "$finish_cmds"; then
 	  # Do each command in the finish commands.
-	  eval cmds=\"$finish_cmds\"
+	  cmds=$finish_cmds
 	  save_ifs="$IFS"; IFS='~'
 	  for cmd in $cmds; do
 	    IFS="$save_ifs"
+	    eval cmd=\"$cmd\"
 	    $show "$cmd"
 	    $run eval "$cmd" || admincmds="$admincmds
        $cmd"
@@ -4458,43 +5824,43 @@ relink_command=\"$relink_command\""
     fi
 
     # Exit here if they wanted silent mode.
-    test "$show" = ":" && exit 0
+    test "$show" = : && exit $EXIT_SUCCESS
 
-    echo "----------------------------------------------------------------------"
-    echo "Libraries have been installed in:"
+    $echo "----------------------------------------------------------------------"
+    $echo "Libraries have been installed in:"
     for libdir in $libdirs; do
-      echo "   $libdir"
+      $echo "   $libdir"
     done
-    echo
-    echo "If you ever happen to want to link against installed libraries"
-    echo "in a given directory, LIBDIR, you must either use libtool, and"
-    echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
-    echo "flag during linking and do at least one of the following:"
+    $echo
+    $echo "If you ever happen to want to link against installed libraries"
+    $echo "in a given directory, LIBDIR, you must either use libtool, and"
+    $echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
+    $echo "flag during linking and do at least one of the following:"
     if test -n "$shlibpath_var"; then
-      echo "   - add LIBDIR to the \`$shlibpath_var' environment variable"
-      echo "     during execution"
+      $echo "   - add LIBDIR to the \`$shlibpath_var' environment variable"
+      $echo "     during execution"
     fi
     if test -n "$runpath_var"; then
-      echo "   - add LIBDIR to the \`$runpath_var' environment variable"
-      echo "     during linking"
+      $echo "   - add LIBDIR to the \`$runpath_var' environment variable"
+      $echo "     during linking"
     fi
     if test -n "$hardcode_libdir_flag_spec"; then
       libdir=LIBDIR
       eval flag=\"$hardcode_libdir_flag_spec\"
 
-      echo "   - use the \`$flag' linker flag"
+      $echo "   - use the \`$flag' linker flag"
     fi
     if test -n "$admincmds"; then
-      echo "   - have your system administrator run these commands:$admincmds"
+      $echo "   - have your system administrator run these commands:$admincmds"
     fi
     if test -f /etc/ld.so.conf; then
-      echo "   - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+      $echo "   - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
     fi
-    echo
-    echo "See any operating system documentation about shared libraries for"
-    echo "more information, such as the ld(1) and ld.so(8) manual pages."
-    echo "----------------------------------------------------------------------"
-    exit 0
+    $echo
+    $echo "See any operating system documentation about shared libraries for"
+    $echo "more information, such as the ld(1) and ld.so(8) manual pages."
+    $echo "----------------------------------------------------------------------"
+    exit $EXIT_SUCCESS
     ;;
 
   # libtool execute mode
@@ -4506,7 +5872,7 @@ relink_command=\"$relink_command\""
     if test -z "$cmd"; then
       $echo "$modename: you must specify a COMMAND" 1>&2
       $echo "$help"
-      exit 1
+      exit $EXIT_FAILURE
     fi
 
     # Handle -dlopen flags immediately.
@@ -4514,18 +5880,18 @@ relink_command=\"$relink_command\""
       if test ! -f "$file"; then
 	$echo "$modename: \`$file' is not a file" 1>&2
 	$echo "$help" 1>&2
-	exit 1
+	exit $EXIT_FAILURE
       fi
 
       dir=
       case $file in
       *.la)
 	# Check to see that this really is a libtool archive.
-	if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+	if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
 	else
 	  $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
 	  $echo "$help" 1>&2
-	  exit 1
+	  exit $EXIT_FAILURE
 	fi
 
 	# Read the libtool library.
@@ -4552,7 +5918,7 @@ relink_command=\"$relink_command\""
 	  dir="$dir/$objdir"
 	else
 	  $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
-	  exit 1
+	  exit $EXIT_FAILURE
 	fi
 	;;
 
@@ -4592,7 +5958,7 @@ relink_command=\"$relink_command\""
       -*) ;;
       *)
 	# Do a test to see if this is really a libtool program.
-	if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+	if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
 	  # If there is no directory component, then add one.
 	  case $file in
 	  */* | *\\*) . $file ;;
@@ -4615,7 +5981,7 @@ relink_command=\"$relink_command\""
 	eval "export $shlibpath_var"
       fi
 
-      # Restore saved enviroment variables
+      # Restore saved environment variables
       if test "${save_LC_ALL+set}" = set; then
 	LC_ALL="$save_LC_ALL"; export LC_ALL
       fi
@@ -4624,7 +5990,7 @@ relink_command=\"$relink_command\""
       fi
 
       # Now prepare to actually exec the command.
-      exec_cmd='"$cmd"$args'
+      exec_cmd="\$cmd$args"
     else
       # Display what would be done.
       if test -n "$shlibpath_var"; then
@@ -4632,7 +5998,7 @@ relink_command=\"$relink_command\""
 	$echo "export $shlibpath_var"
       fi
       $echo "$cmd$args"
-      exit 0
+      exit $EXIT_SUCCESS
     fi
     ;;
 
@@ -4660,24 +6026,25 @@ relink_command=\"$relink_command\""
     if test -z "$rm"; then
       $echo "$modename: you must specify an RM program" 1>&2
       $echo "$help" 1>&2
-      exit 1
+      exit $EXIT_FAILURE
     fi
 
     rmdirs=
 
+    origobjdir="$objdir"
     for file in $files; do
       dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
       if test "X$dir" = "X$file"; then
 	dir=.
-	objdir="$objdir"
+	objdir="$origobjdir"
       else
-	objdir="$dir/$objdir"
+	objdir="$dir/$origobjdir"
       fi
       name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
-      test $mode = uninstall && objdir="$dir"
+      test "$mode" = uninstall && objdir="$dir"
 
       # Remember objdir for removal later, being careful to avoid duplicates
-      if test $mode = clean; then
+      if test "$mode" = clean; then
 	case " $rmdirs " in
 	  *" $objdir "*) ;;
 	  *) rmdirs="$rmdirs $objdir" ;;
@@ -4701,7 +6068,7 @@ relink_command=\"$relink_command\""
       case $name in
       *.la)
 	# Possibly a libtool archive, so verify it.
-	if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+	if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
 	  . $dir/$name
 
 	  # Delete the libtool libraries and symlinks.
@@ -4709,18 +6076,19 @@ relink_command=\"$relink_command\""
 	    rmfiles="$rmfiles $objdir/$n"
 	  done
 	  test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
-	  test $mode = clean && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
+	  test "$mode" = clean && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
 
-	  if test $mode = uninstall; then
+	  if test "$mode" = uninstall; then
 	    if test -n "$library_names"; then
 	      # Do each command in the postuninstall commands.
-	      eval cmds=\"$postuninstall_cmds\"
+	      cmds=$postuninstall_cmds
 	      save_ifs="$IFS"; IFS='~'
 	      for cmd in $cmds; do
 		IFS="$save_ifs"
+		eval cmd=\"$cmd\"
 		$show "$cmd"
 		$run eval "$cmd"
-		if test $? != 0 && test "$rmforce" != yes; then
+		if test "$?" -ne 0 && test "$rmforce" != yes; then
 		  exit_status=1
 		fi
 	      done
@@ -4729,13 +6097,14 @@ relink_command=\"$relink_command\""
 
 	    if test -n "$old_library"; then
 	      # Do each command in the old_postuninstall commands.
-	      eval cmds=\"$old_postuninstall_cmds\"
+	      cmds=$old_postuninstall_cmds
 	      save_ifs="$IFS"; IFS='~'
 	      for cmd in $cmds; do
 		IFS="$save_ifs"
+		eval cmd=\"$cmd\"
 		$show "$cmd"
 		$run eval "$cmd"
-		if test $? != 0 && test "$rmforce" != yes; then
+		if test "$?" -ne 0 && test "$rmforce" != yes; then
 		  exit_status=1
 		fi
 	      done
@@ -4747,22 +6116,52 @@ relink_command=\"$relink_command\""
 	;;
 
       *.lo)
-	if test "$build_old_libs" = yes; then
-	  oldobj=`$echo "X$name" | $Xsed -e "$lo2o"`
-	  rmfiles="$rmfiles $dir/$oldobj"
+	# Possibly a libtool object, so verify it.
+	if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+
+	  # Read the .lo file
+	  . $dir/$name
+
+	  # Add PIC object to the list of files to remove.
+	  if test -n "$pic_object" \
+	     && test "$pic_object" != none; then
+	    rmfiles="$rmfiles $dir/$pic_object"
+	  fi
+
+	  # Add non-PIC object to the list of files to remove.
+	  if test -n "$non_pic_object" \
+	     && test "$non_pic_object" != none; then
+	    rmfiles="$rmfiles $dir/$non_pic_object"
+	  fi
 	fi
 	;;
 
       *)
-	# Do a test to see if this is a libtool program.
-	if test $mode = clean &&
-	   (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
-	  relink_command=
-	  . $dir/$file
+	if test "$mode" = clean ; then
+	  noexename=$name
+	  case $file in
+	  *.exe)
+	    file=`$echo $file|${SED} 's,.exe$,,'`
+	    noexename=`$echo $name|${SED} 's,.exe$,,'`
+	    # $file with .exe has already been added to rmfiles,
+	    # add $file without .exe
+	    rmfiles="$rmfiles $file"
+	    ;;
+	  esac
+	  # Do a test to see if this is a libtool program.
+	  if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+	    relink_command=
+	    . $dir/$noexename
 
-	  rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
-	  if test "$fast_install" = yes && test -n "$relink_command"; then
-	    rmfiles="$rmfiles $objdir/lt-$name"
+	    # note $name still contains .exe if it was in $file originally
+	    # as does the version of $file that was added into $rmfiles
+	    rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
+	    if test "$fast_install" = yes && test -n "$relink_command"; then
+	      rmfiles="$rmfiles $objdir/lt-$name"
+	    fi
+	    if test "X$noexename" != "X$name" ; then
+	      rmfiles="$rmfiles $objdir/lt-${noexename}.c"
+	    fi
 	  fi
 	fi
 	;;
@@ -4770,6 +6169,7 @@ relink_command=\"$relink_command\""
       $show "$rm $rmfiles"
       $run $rm $rmfiles || exit_status=1
     done
+    objdir="$origobjdir"
 
     # Try to remove the ${objdir}s in the directories where we deleted files
     for dir in $rmdirs; do
@@ -4785,20 +6185,20 @@ relink_command=\"$relink_command\""
   "")
     $echo "$modename: you must specify a MODE" 1>&2
     $echo "$generic_help" 1>&2
-    exit 1
+    exit $EXIT_FAILURE
     ;;
   esac
 
   if test -z "$exec_cmd"; then
     $echo "$modename: invalid operation mode \`$mode'" 1>&2
     $echo "$generic_help" 1>&2
-    exit 1
+    exit $EXIT_FAILURE
   fi
 fi # test -z "$show_help"
 
 if test -n "$exec_cmd"; then
   eval exec $exec_cmd
-  exit 1
+  exit $EXIT_FAILURE
 fi
 
 # We need to display help for each of the modes.
@@ -4817,6 +6217,7 @@ Provide generalized library-building support services.
     --mode=MODE       use operation mode MODE [default=inferred from MODE-ARGS]
     --quiet           same as \`--silent'
     --silent          don't print informational messages
+    --tag=TAG         use configuration variables from tag TAG
     --version         print version information
 
 MODE must be one of the following:
@@ -4830,8 +6231,10 @@ MODE must be one of the following:
       uninstall       remove libraries from an installed directory
 
 MODE-ARGS vary depending on the MODE.  Try \`$modename --help --mode=MODE' for
-a more detailed description of MODE."
-  exit 0
+a more detailed description of MODE.
+
+Report bugs to <bug-libtool@gnu.org>."
+  exit $EXIT_SUCCESS
   ;;
 
 clean)
@@ -4937,12 +6340,14 @@ The following components of LINK-COMMAND are treated specially:
 		    try to export only the symbols matching REGEX
   -LLIBDIR          search LIBDIR for required installed libraries
   -lNAME            OUTPUT-FILE requires the installed library libNAME
-  -jnimodule        build a library that can dlopened via Java JNI
   -module           build a library that can dlopened
   -no-fast-install  disable the fast-install mode
   -no-install       link a not-installable executable
   -no-undefined     declare that a library does not refer to external symbols
   -o OUTPUT-FILE    create OUTPUT-FILE from the specified objects
+  -objectlist FILE  Use a list of object files found in FILE to specify objects
+  -precious-files-regex REGEX
+                    don't remove output files matching REGEX
   -release RELEASE  specify package release information
   -rpath LIBDIR     the created library will eventually be installed in LIBDIR
   -R[ ]LIBDIR       add LIBDIR to the runtime path of programs and libraries
@@ -4984,14 +6389,34 @@ Otherwise, only FILE itself is deleted using RM."
 *)
   $echo "$modename: invalid operation mode \`$mode'" 1>&2
   $echo "$help" 1>&2
-  exit 1
+  exit $EXIT_FAILURE
   ;;
 esac
 
-echo
+$echo
 $echo "Try \`$modename --help' for more information about other modes."
 
-exit 0
+exit $EXIT_SUCCESS
+
+# The TAGs below are defined such that we never get into a situation
+# in which we disable both kinds of libraries.  Given conflicting
+# choices, we go for a static library, that is the most portable,
+# since we can't tell whether shared libraries were disabled because
+# the user asked for that or because the platform doesn't support
+# them.  This is particularly important on AIX, because we don't
+# support having both static and shared libraries enabled at the same
+# time on that platform, so we default to a shared-only configuration.
+# If a disable-shared tag is given, we'll fallback to a static-only
+# configuration.  But we'll never go from static-only to shared-only.
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
+build_libtool_libs=no
+build_old_libs=yes
+# ### END LIBTOOL TAG CONFIG: disable-shared
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-static
+build_old_libs=`case $build_libtool_libs in yes) $echo no;; *) $echo yes;; esac`
+# ### END LIBTOOL TAG CONFIG: disable-static
 
 # Local Variables:
 # mode:shell-script
diff --git a/storage/bdb/dist/pubdef.in b/storage/bdb/dist/pubdef.in
index f42363022cd0f0e955694ce710ca6b761abe1bf4..7f6ad2ebd694d81f8f32294798482190a5ff9c8d 100644
--- a/storage/bdb/dist/pubdef.in
+++ b/storage/bdb/dist/pubdef.in
@@ -1,8 +1,8 @@
 # Name
 # D == documentation
 # I == include file
-# C == Java case value (declared and initialized)
-# J == Java constant (declared only)
+# J == Java constant
+# N == wrapped by the Java native layer
 DB_AFTER		D I J
 DB_AGGRESSIVE		D I J
 DB_ALREADY_ABORTED	* I *
@@ -20,7 +20,9 @@ DB_AM_DUPSORT		* I *
 DB_AM_ENCRYPT		* I *
 DB_AM_FIXEDLEN		* I *
 DB_AM_INMEM		* I *
+DB_AM_INORDER		* I *
 DB_AM_IN_RENAME		* I *
+DB_AM_NOT_DURABLE	* I *
 DB_AM_OPEN_CALLED	* I *
 DB_AM_PAD		* I *
 DB_AM_PGDEF		* I *
@@ -28,6 +30,7 @@ DB_AM_RDONLY		* I *
 DB_AM_RECNUM		* I *
 DB_AM_RECOVER		* I *
 DB_AM_RENUMBER		* I *
+DB_AM_REPLICATION	* I *
 DB_AM_REVSPLITOFF	* I *
 DB_AM_SECONDARY		* I *
 DB_AM_SNAPSHOT		* I *
@@ -39,39 +42,42 @@ DB_APPEND		D I J
 DB_ARCH_ABS		D I J
 DB_ARCH_DATA		D I J
 DB_ARCH_LOG		D I J
+DB_ARCH_REMOVE		D I J
 DB_AUTO_COMMIT		D I J
 DB_BEFORE		D I J
-DB_BTREE		D I C
+DB_BTREE		D I J
 DB_BTREEMAGIC		* I *
 DB_BTREEOLDVER		* I *
 DB_BTREEVERSION		* I *
-DB_CACHED_COUNTS	* I J
+DB_BUFFER_SMALL		D I N
+DB_CACHED_COUNTS	* I *
 DB_CDB_ALLDB		D I J
-DB_CHKSUM_SHA1		D I J
-DB_CLIENT		D I J
-DB_COMMIT		* I *
+DB_CHKSUM		D I J
 DB_CONFIG		D * *
 DB_CONSUME		D I J
 DB_CONSUME_WAIT		D I J
 DB_CREATE		D I J
 DB_CURRENT		D I J
-DB_CXX_NO_EXCEPTIONS	D I J
+DB_CXX_NO_EXCEPTIONS	D I *
 DB_DBM_HSEARCH		* I *
-DB_DBT_APPMALLOC	D I *
+DB_DBT_APPMALLOC	D I N
 DB_DBT_DUPOK		* I *
 DB_DBT_ISSET		* I *
 DB_DBT_MALLOC		D I J
 DB_DBT_PARTIAL		D I J
-DB_DBT_REALLOC		D I J
+DB_DBT_REALLOC		D I N
 DB_DBT_USERMEM		D I J
+DB_DEGREE_2		D I J
 DB_DELETED		* I *
-DB_DIRECT		D I J
+DB_DIRECT		D I *
 DB_DIRECT_DB		D I J
 DB_DIRECT_LOG		D I J
 DB_DIRTY_READ		D I J
-DB_DONOTINDEX		D I C
+DB_DONOTINDEX		D I J
+DB_DSYNC_LOG		D I J
 DB_DUP			D I J
 DB_DUPSORT		D I J
+DB_DURABLE_UNKNOWN	* I *
 DB_EID_BROADCAST	D I J
 DB_EID_INVALID		D I J
 DB_ENCRYPT		D I J
@@ -83,8 +89,11 @@ DB_ENV_CREATE		* I *
 DB_ENV_DBLOCAL		* I *
 DB_ENV_DIRECT_DB	* I *
 DB_ENV_DIRECT_LOG	* I *
+DB_ENV_DSYNC_LOG	* I *
 DB_ENV_FATAL		* I *
 DB_ENV_LOCKDOWN		* I *
+DB_ENV_LOG_AUTOREMOVE	* I *
+DB_ENV_LOG_INMEMORY	* I *
 DB_ENV_NOLOCKING	* I *
 DB_ENV_NOMMAP		* I *
 DB_ENV_NOPANIC		* I *
@@ -92,13 +101,11 @@ DB_ENV_OPEN_CALLED	* I *
 DB_ENV_OVERWRITE	* I *
 DB_ENV_PRIVATE		* I *
 DB_ENV_REGION_INIT	* I *
-DB_ENV_REP_CLIENT	* I *
-DB_ENV_REP_LOGSONLY	* I *
-DB_ENV_REP_MASTER	* I *
 DB_ENV_RPCCLIENT	* I *
 DB_ENV_RPCCLIENT_GIVEN	* I *
 DB_ENV_SYSTEM_MEM	* I *
 DB_ENV_THREAD		* I *
+DB_ENV_TIME_NOTGRANTED	* I *
 DB_ENV_TXN_NOSYNC	* I *
 DB_ENV_TXN_WRITE_NOSYNC	* I *
 DB_ENV_YIELDCPU		* I *
@@ -115,7 +122,7 @@ DB_GET_BOTHC		* I *
 DB_GET_BOTH_RANGE	D I J
 DB_GET_RECNO		D I J
 DB_HANDLE_LOCK		* I *
-DB_HASH			D I C
+DB_HASH			D I J
 DB_HASHMAGIC		* I *
 DB_HASHOLDVER		* I *
 DB_HASHVERSION		* I *
@@ -124,24 +131,25 @@ DB_INIT_CDB		D I J
 DB_INIT_LOCK		D I J
 DB_INIT_LOG		D I J
 DB_INIT_MPOOL		D I J
+DB_INIT_REP		D I J
 DB_INIT_TXN		D I J
-DB_JAVA_CALLBACK	* I *
+DB_INORDER		D I J
 DB_JOINENV		D I J
 DB_JOIN_ITEM		D I J
 DB_JOIN_NOSORT		D I J
-DB_KEYEMPTY		D I C
-DB_KEYEXIST		D I C
+DB_KEYEMPTY		D I J
+DB_KEYEXIST		D I J
 DB_KEYFIRST		D I J
 DB_KEYLAST		D I J
 DB_LAST			D I J
 DB_LOCKDOWN		D I J
 DB_LOCKVERSION		* I *
-DB_LOCK_DEADLOCK	D I C
+DB_LOCK_ABORT		* I *
+DB_LOCK_DEADLOCK	D I J
 DB_LOCK_DEFAULT		D I J
 DB_LOCK_DIRTY		* I *
 DB_LOCK_DUMP		* I *
 DB_LOCK_EXPIRE		D I J
-DB_LOCK_FREE_LOCKER	* I *
 DB_LOCK_GET		D I J
 DB_LOCK_GET_TIMEOUT	D I J
 DB_LOCK_INHERIT		* I *
@@ -149,12 +157,13 @@ DB_LOCK_IREAD		D I J
 DB_LOCK_IWR		D I J
 DB_LOCK_IWRITE		D I J
 DB_LOCK_MAXLOCKS	D I J
+DB_LOCK_MAXWRITE	D I J
 DB_LOCK_MINLOCKS	D I J
 DB_LOCK_MINWRITE	D I J
 DB_LOCK_NG		* I *
 DB_LOCK_NORUN		* I *
 DB_LOCK_NOTEXIST	* I *
-DB_LOCK_NOTGRANTED	D I C
+DB_LOCK_NOTGRANTED	D I J
 DB_LOCK_NOWAIT		D I J
 DB_LOCK_OLDEST		D I J
 DB_LOCK_PUT		D I J
@@ -180,11 +189,20 @@ DB_LOGFILEID_INVALID	* I *
 DB_LOGMAGIC		* I *
 DB_LOGOLDVER		* I *
 DB_LOGVERSION		* I *
+DB_LOG_AUTOREMOVE	D I J
+DB_LOG_BUFFER_FULL	D I *
+DB_LOG_CHKPNT		* I *
+DB_LOG_COMMIT		* I *
 DB_LOG_DISK		* I *
+DB_LOG_INMEMORY		D I J
 DB_LOG_LOCKED		* I *
+DB_LOG_NOCOPY		* I *
+DB_LOG_NOT_DURABLE	* I *
+DB_LOG_PERM		* I *
+DB_LOG_RESEND		* I *
 DB_LOG_SILENT_ERR	* I *
+DB_LOG_WRNOSYNC		* I *
 DB_LSTAT_ABORTED	* I *
-DB_LSTAT_ERR		* I *
 DB_LSTAT_EXPIRED	* I *
 DB_LSTAT_FREE		* I *
 DB_LSTAT_HELD		* I *
@@ -197,8 +215,11 @@ DB_MPOOL_CLEAN		D I *
 DB_MPOOL_CREATE		D I *
 DB_MPOOL_DIRTY		D I *
 DB_MPOOL_DISCARD	D I *
+DB_MPOOL_FREE		* I *
 DB_MPOOL_LAST		D I *
 DB_MPOOL_NEW		D I *
+DB_MPOOL_NOFILE		D I J
+DB_MPOOL_UNLINK		D I J
 DB_MULTIPLE		D I J
 DB_MULTIPLE_INIT	D I *
 DB_MULTIPLE_KEY		D I J
@@ -209,33 +230,31 @@ DB_NEEDSPLIT		* I *
 DB_NEXT			D I J
 DB_NEXT_DUP		D I J
 DB_NEXT_NODUP		D I J
-DB_NOCOPY		* I *
 DB_NODUPDATA		D I J
 DB_NOLOCKING		D I J
 DB_NOMMAP		D I J
 DB_NOORDERCHK		D I J
 DB_NOOVERWRITE		D I J
 DB_NOPANIC		D I J
-DB_NOSERVER		D I C
-DB_NOSERVER_HOME	D I C
-DB_NOSERVER_ID		D I C
+DB_NOSERVER		D I *
+DB_NOSERVER_HOME	D I J
+DB_NOSERVER_ID		D I J
 DB_NOSYNC		D I J
-DB_NOTFOUND		D I C
-DB_ODDFILESIZE		D I J
+DB_NOTFOUND		D I J
+DB_NO_AUTO_COMMIT	* I *
+DB_ODDFILESIZE		D I *
 DB_OK_BTREE		* I *
 DB_OK_HASH		* I *
 DB_OK_QUEUE		* I *
 DB_OK_RECNO		* I *
-DB_OLD_VERSION		D I C
+DB_OLD_VERSION		D I *
 DB_OPFLAGS_MASK		* I *
 DB_ORDERCHKONLY		D I J
 DB_OVERWRITE		D I J
 DB_PAGE_LOCK		* I *
-DB_PAGE_NOTFOUND	D I C
+DB_PAGE_NOTFOUND	D I *
 DB_PANIC_ENVIRONMENT	D I J
-DB_PERMANENT		* I *
 DB_POSITION		D I J
-DB_POSITIONI		* I *
 DB_PREV			D I J
 DB_PREV_NODUP		D I J
 DB_PRINTABLE		D I J
@@ -250,12 +269,12 @@ DB_PR_RECOVERYTEST	* I *
 DB_QAMMAGIC		* I *
 DB_QAMOLDVER		* I *
 DB_QAMVERSION		* I *
-DB_QUEUE		D I C
+DB_QUEUE		D I J
 DB_RDONLY		D I J
 DB_RDWRMASTER		* I *
-DB_RECNO		D I C
+DB_RECNO		D I J
 DB_RECNUM		D I J
-DB_RECORDCOUNT		* I J
+DB_RECORDCOUNT		* I *
 DB_RECORD_LOCK		* I *
 DB_RECOVER		D I J
 DB_RECOVER_FATAL	D I J
@@ -265,37 +284,54 @@ DB_REGION_MAGIC		* I *
 DB_RENAMEMAGIC		* I *
 DB_RENUMBER		D I J
 DB_REP_CLIENT		D I J
-DB_REP_DUPMASTER	D I C
-DB_REP_HOLDELECTION	D I C
-DB_REP_LOGSONLY		D I J
+DB_REP_CREATE		* I *
+DB_REP_DUPMASTER	D I J
+DB_REP_EGENCHG		* I *
+DB_REP_HANDLE_DEAD	D I N
+DB_REP_HOLDELECTION	D I J
+DB_REP_ISPERM		D I J
+DB_REP_LOGREADY		* I *
 DB_REP_MASTER		D I J
-DB_REP_NEWMASTER	D I C
-DB_REP_NEWSITE		D I C
-DB_REP_OUTDATED		D I C
+DB_REP_NEWMASTER	D I J
+DB_REP_NEWSITE		D I J
+DB_REP_NOBUFFER		D I J
+DB_REP_NOTPERM		D I J
+DB_REP_PAGEDONE		* I *
 DB_REP_PERMANENT	D I J
-DB_REP_UNAVAIL		D I J
+DB_REP_STARTUPDONE	D I J
+DB_REP_UNAVAIL		D I *
 DB_REVSPLITOFF		D I J
 DB_RMW			D I J
-DB_RUNRECOVERY		D I C
+DB_RPCCLIENT		D I J
+DB_RUNRECOVERY		D I N
 DB_SALVAGE		D I J
-DB_SECONDARY_BAD	D I C
+DB_SECONDARY_BAD	D I *
+DB_SEQUENCE_VERSION	* I *
+DB_SEQ_DEC		D I J
+DB_SEQ_INC		D I J
+DB_SEQ_RANGE_SET	* I *
+DB_SEQ_WRAP		D I J
 DB_SET			D I J
+DB_SET_BEGIN_LSNP	* I *
 DB_SET_LOCK_TIMEOUT	D I J
 DB_SET_RANGE		D I J
 DB_SET_RECNO		D I J
 DB_SET_TXN_NOW		* I *
 DB_SET_TXN_TIMEOUT	D I J
 DB_SNAPSHOT		D I J
+DB_STAT_ALL		D I *
 DB_STAT_CLEAR		D I J
+DB_STAT_LOCK_CONF	D I *
+DB_STAT_LOCK_LOCKERS	D I *
+DB_STAT_LOCK_OBJECTS	D I *
+DB_STAT_LOCK_PARAMS	D I *
+DB_STAT_MEMP_HASH	D I *
+DB_STAT_SUBSYSTEM	D I *
 DB_SURPRISE_KID		* I *
 DB_SWAPBYTES		* I *
 DB_SYSTEM_MEM		D I J
 DB_TEST_ELECTINIT	* I *
-DB_TEST_ELECTSEND	* I *
 DB_TEST_ELECTVOTE1	* I *
-DB_TEST_ELECTVOTE2	* I *
-DB_TEST_ELECTWAIT1	* I *
-DB_TEST_ELECTWAIT2	* I *
 DB_TEST_POSTDESTROY	* I *
 DB_TEST_POSTLOG		* I *
 DB_TEST_POSTLOGMETA	* I *
@@ -306,45 +342,45 @@ DB_TEST_PREOPEN		* I *
 DB_TEST_SUBDB_LOCKS	* I *
 DB_THREAD		D I J
 DB_TIMEOUT		* I *
+DB_TIME_NOTGRANTED	D I J
 DB_TRUNCATE		D I J
 DB_TXNVERSION		* I *
-DB_TXN_ABORT		D I C
-DB_TXN_APPLY		D I C
+DB_TXN_ABORT		D I J
+DB_TXN_APPLY		D I J
 DB_TXN_BACKWARD_ALLOC	* I *
-DB_TXN_BACKWARD_ROLL	D I C
+DB_TXN_BACKWARD_ROLL	D I J
 DB_TXN_CKP		* I *
-DB_TXN_FORWARD_ROLL	D I C
-DB_TXN_GETPGNOS		* I *
-DB_TXN_LOCK		* I *
+DB_TXN_FORWARD_ROLL	D I J
 DB_TXN_NOSYNC		D I J
+DB_TXN_NOT_DURABLE	D I J
 DB_TXN_NOWAIT		D I J
 DB_TXN_OPENFILES	* I *
 DB_TXN_POPENFILES	* I *
-DB_TXN_PRINT		D I C
+DB_TXN_PRINT		D I J
 DB_TXN_SYNC		D I J
 DB_TXN_WRITE_NOSYNC	D I J
 DB_UNDO			* I *
-DB_UNKNOWN		D I C
+DB_UNKNOWN		D I J
+DB_UNREF		* I *
 DB_UPDATE_SECONDARY	* I *
 DB_UPGRADE		D I J
 DB_USE_ENVIRON		D I J
 DB_USE_ENVIRON_ROOT	D I J
-DB_VERB_CHKPOINT	D I J
 DB_VERB_DEADLOCK	D I J
 DB_VERB_RECOVERY	D I J
 DB_VERB_REPLICATION	D I J
 DB_VERB_WAITSFOR	D I J
 DB_VERIFY		D I J
-DB_VERIFY_BAD		D I C
+DB_VERIFY_BAD		D I N
 DB_VERIFY_FATAL		* I *
 DB_VERSION_MAJOR	* I J
 DB_VERSION_MINOR	* I J
+DB_VERSION_MISMATCH	D I *
 DB_VERSION_PATCH	* I J
-DB_VERSION_STRING	* I *
+DB_VERSION_STRING	* I N
 DB_WRITECURSOR		D I J
 DB_WRITELOCK		* I *
 DB_WRITEOPEN		* I *
-DB_WRNOSYNC		* I *
 DB_XA_CREATE		D I J
 DB_XIDDATASIZE		D I J
 DB_YIELDCPU		D I J
diff --git a/storage/bdb/dist/s_all b/storage/bdb/dist/s_all
index 132017def3c9fd4a1ccebb40376bf16033c04e34..02686b742bf66e91b46b7f48a8e8376b8e55b451 100644
--- a/storage/bdb/dist/s_all
+++ b/storage/bdb/dist/s_all
@@ -1,11 +1,9 @@
 #!/bin/sh -
-#	$Id: s_all,v 1.10 2001/08/04 14:01:44 bostic Exp $
+#	$Id: s_all,v 1.11 2002/10/30 15:26:36 bostic Exp $
 
-sh s_dir
-
-#sh s_perm		# permissions.
+sh s_perm		# permissions.
 sh s_symlink		# symbolic links.
-sh s_readme		# db/README file.
+sh s_readme		# distribution README file.
 
 #
 # The following order is important, s_include must run last.
@@ -17,7 +15,7 @@ sh s_include		# standard include files.
 
 sh s_win32		# Win32 include files.
 sh s_win32_dsp		# Win32 build environment.
-#sh s_vxworks		# VxWorks include files.
-#sh s_java		# Java support.
+sh s_vxworks		# VxWorks include files.
+sh s_java		# Java support.
 sh s_test		# Test suite support.
 sh s_tags		# Tags files.
diff --git a/storage/bdb/dist/s_config b/storage/bdb/dist/s_config
index 3e033da81aba594d8d602058d3e883ba21848465..604a1d08916bc471c1abe1b93293518afb6ef5ec 100755
--- a/storage/bdb/dist/s_config
+++ b/storage/bdb/dist/s_config
@@ -1,41 +1,31 @@
 #!/bin/sh -
-#	$Id: s_config,v 1.9 2002/05/20 19:18:13 bostic Exp $
+#	$Id: s_config,v 1.13 2003/07/02 15:27:44 bostic Exp $
 #
 # Build the autoconfiguration files.
 
 trap 'rm -f aclocal.m4 ; exit 0' 0 1 2 3 13 15
 
-msgac="# DO NOT EDIT: automatically built by dist/s_config."
-
 . ./RELEASE
 
-echo "Building aclocal.m4"
-(echo "$msgac" &&
- echo "AC_DEFUN(AM_VERSION_SET, [" &&
- echo "AC_SUBST(DB_VERSION_MAJOR)" &&
- echo "DB_VERSION_MAJOR=$DB_VERSION_MAJOR" &&
- echo "AC_SUBST(DB_VERSION_MINOR)" &&
- echo "DB_VERSION_MINOR=$DB_VERSION_MINOR" &&
- echo "AC_SUBST(DB_VERSION_PATCH)" &&
- echo "DB_VERSION_PATCH=$DB_VERSION_PATCH" &&
- echo "AC_SUBST(DB_VERSION_UNIQUE_NAME)" &&
- echo "DB_VERSION_UNIQUE_NAME=$DB_VERSION_UNIQUE_NAME" &&
- echo "AC_SUBST(DB_VERSION_STRING)" &&
- echo "DB_VERSION_STRING=\"\\\"$DB_VERSION_STRING\\\"\"" &&
- echo "])" &&
- cat aclocal/*.ac aclocal_java/*.ac) > aclocal.m4
-
-echo "Running autoheader to build config.hin"
+echo "autoconf: building aclocal.m4..."
+cat aclocal/*.ac aclocal_java/*.ac > aclocal.m4
+
+echo "autoconf: running autoheader to build config.hin..."
 rm -f config.hin
 autoheader
 chmod 444 config.hin
 
-echo "Running autoconf to build configure"
+echo "autoconf: running autoconf to build configure"
 rm -f configure
 autoconf
 
 # Edit version information we couldn't pre-compute.
-(echo "1,\$s/__EDIT_DB_VERSION__/$DB_VERSION/g" &&
+(echo "1,\$s/__EDIT_DB_VERSION_MAJOR__/$DB_VERSION_MAJOR/g" &&
+ echo "1,\$s/__EDIT_DB_VERSION_MINOR__/$DB_VERSION_MINOR/g" &&
+ echo "1,\$s/__EDIT_DB_VERSION_PATCH__/$DB_VERSION_PATCH/g" &&
+ echo "1,\$s/__EDIT_DB_VERSION_STRING__/$DB_VERSION_STRING/g" &&
+ echo "1,\$s/__EDIT_DB_VERSION_UNIQUE_NAME__/$DB_VERSION_UNIQUE_NAME/g" &&
+ echo "1,\$s/__EDIT_DB_VERSION__/$DB_VERSION/g" &&
  echo "w" &&
  echo "q") | ed configure
 
diff --git a/storage/bdb/dist/s_crypto b/storage/bdb/dist/s_crypto
index f7947cb3e1045d6d8bc02f5206ef52085ae348e5..05a93043a8bbdeb913db1e04128891c1159729e2 100644
--- a/storage/bdb/dist/s_crypto
+++ b/storage/bdb/dist/s_crypto
@@ -1,10 +1,8 @@
 #!/bin/sh -
-#	$Id: s_crypto,v 11.5 2002/09/13 13:14:14 bostic Exp $
+#	$Id: s_crypto,v 11.8 2003/11/24 22:41:26 bostic Exp $
 
 # Remove crypto from the DB source tree.
 
-. ./RELEASE
-
 d=..
 
 t=/tmp/__db_a
@@ -19,8 +17,8 @@ fi
 # Remove the crypto.
 rm -rf $d/crypto
 
-# Update the docs.
-f=$d/docs/ref/env/encrypt.html
+# Update the release splash page.
+f=$d/docs/index.html
 chmod 664 $f
 (echo '/DOES/' &&
  echo 's/DOES/DOES NOT/' &&
@@ -40,6 +38,8 @@ chmod 664 $f
 f=srcfiles.in
 chmod 664 $f
 (echo 'g/^crypto\//d' &&
+ echo '/crypto_stub\.c/' &&
+ echo 's/small/dynamic small static vx/' &&
  echo 'w' &&
  echo 'q') | ed $f
 
diff --git a/storage/bdb/dist/s_include b/storage/bdb/dist/s_include
index 878b4a38af1e3b21f4a827b963973d0989b24107..ab058d86dba2c053b0f25efbb0aa5134f8c6b5a3 100755
--- a/storage/bdb/dist/s_include
+++ b/storage/bdb/dist/s_include
@@ -1,5 +1,5 @@
 #!/bin/sh -
-#	$Id: s_include,v 1.19 2002/03/27 04:31:50 bostic Exp $
+#	$Id: s_include,v 1.22 2004/04/19 18:27:17 mjc Exp $
 #
 # Build the automatically generated function prototype files.
 
@@ -71,14 +71,19 @@ head defonly _DB_INT_DEF_IN_ > $i_dfile
 
 # Process the standard directories, creating per-directory prototype
 # files and adding to the external prototype and #define files.
-for i in db btree clib common dbreg env fileops hash hmac \
-    lock log mp mutex os qam rep rpc_client rpc_server tcl txn xa; do
+for i in db btree clib common crypto dbreg env fileops hash hmac \
+    lock log mp mutex os qam rep rpc_client rpc_server sequence tcl txn xa; do
 	head "_${i}_ext_h_" > $i_pfile
 
-	f="../$i/*.c"
-	[ $i = os ] && f="$f ../os_win32/*.c"
-	[ $i = rpc_server ] && f="../$i/c/*.c"
-	[ $i = crypto ] && f="../$i/*.c ../$i/*/*.c"
+	if [ $i = os ] ; then
+		f=`ls ../$i/*.c ../os_win32/*.c`
+	elif [ $i = rpc_server ] ; then
+		f=`ls ../$i/c/*.c`
+	elif [ $i = crypto ] ; then
+		f=`ls ../$i/*.c ../$i/*/*.c`
+	else
+		f=`ls ../$i/*.c`
+	fi
 	awk -f gen_inc.awk \
 	    -v db_version_unique_name=$DB_VERSION_UNIQUE_NAME \
 	    -v e_dfile=$e_dfile \
@@ -96,7 +101,7 @@ done
 # Process directories which only add to the external prototype and #define
 # files.
 for i in dbm hsearch; do
-	f="../$i/*.c"
+	f=`ls ../$i/*.c`
 	awk -f gen_inc.awk \
 	    -v db_version_unique_name=$DB_VERSION_UNIQUE_NAME \
 	    -v e_dfile=$e_dfile \
@@ -105,16 +110,6 @@ for i in dbm hsearch; do
 	    -v i_pfile="" $f
 done
 
-# RPC uses rpcgen to generate a header file; post-process it to add more
-# interfaces to the internal #define file.
-sed -e '/extern bool_t xdr___/{' \
-    -e 's/.* //' \
-    -e 's/();//' \
-    -e 's/.*/#define & &@DB_VERSION_UNIQUE_NAME@/' \
-    -e 'p' \
-    -e '}' \
-    -e d < ../dbinc_auto/db_server.h >> $i_dfile
-
 # There are a few globals in DB -- add them to the external/internal
 # #define files.
 (echo "#define __db_global_values __db_global_values@DB_VERSION_UNIQUE_NAME@";
@@ -141,7 +136,7 @@ cmp $i_dfile $f > /dev/null 2>&1 ||
 head space defonly _DB_EXT_185_DEF_IN_ > $e_dfile
 head space _DB_EXT_185_PROT_IN_ > $e_pfile
 
-f="../db185/*.c"
+f=`ls ../db185/*.c`
 awk -f gen_inc.awk \
     -v db_version_unique_name=$DB_VERSION_UNIQUE_NAME \
     -v e_dfile=$e_dfile \
diff --git a/storage/bdb/dist/s_java b/storage/bdb/dist/s_java
index f7c96e823a144b47ffdf11bcfde966cb3fca5f49..ae715ccd687c9fe4b6ac04e02acb3b2a6a532bc8 100755
--- a/storage/bdb/dist/s_java
+++ b/storage/bdb/dist/s_java
@@ -1,273 +1,8 @@
 #!/bin/sh -
-#	$Id: s_java,v 1.13 2002/09/09 20:47:30 bostic Exp $
+#	$Id: s_java,v 11.8 2004/04/06 20:43:35 mjc Exp $
 #
 # Build the Java files.
 
-msgjava="/* DO NOT EDIT: automatically built by dist/s_java. */"
-
-. ./RELEASE
-
-t=/tmp/__java
-c=/tmp/__javajnic
-h=/tmp/__javajnih
-trap 'rm -f $t $c $h; exit 0' 0 1 2 3 13 15
-
-# Build DbConstants.java.
-(echo "$msgjava" &&
- echo &&
- echo 'package com.sleepycat.db;' &&
- echo &&
- echo 'class DbConstants' &&
- echo '{' &&
- for i in `egrep '^DB_.*J$' pubdef.in | awk '{print $1}'`; do \
-	egrep -w "^#define[	 ]$i|^[	 ][	 ]*$i" ../dbinc/db.in; \
- done |
- sed -e "s/@DB_VERSION_MAJOR@/$DB_VERSION_MAJOR/" \
-     -e "s/@DB_VERSION_MINOR@/$DB_VERSION_MINOR/" \
-     -e "s/@DB_VERSION_PATCH@/$DB_VERSION_PATCH/" \
-     -e 's/^#define[	 ][	 ]*//' \
-     -e 's/[()=,]/ /g' \
-     -e 's/\/\*/ /' | \
- awk '{ print "    static final int " $1 " = " $2 ";" }' &&
- echo '}' &&
- echo &&
- echo '// end of DbConstants.java') > $t
-
-f=../java/src/com/sleepycat/db/DbConstants.java
-cmp $t $f > /dev/null 2>&1 ||
-    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
-
-# Build Db.java.
-f=../java/src/com/sleepycat/db/Db.java.in
-sed '/BEGIN-JAVA-SPECIAL-CONSTANTS/q' < $f > $t
-(echo "    $msgjava" &&
- for i in `egrep '^DB_.*C$' pubdef.in | awk '{print $1}'`; do \
-	egrep -w "^#define[	 ]$i|^[	 ][	 ]*$i" ../dbinc/db.in; \
- done |
- sed -e 's/^#define[	 ][	 ]*//' \
-     -e 's/[()=,]/ /g' |
- awk '{ print "    public static final int " $1 " = " $2 ";" }') >> $t
-(for i in `egrep '^DB_.*J$' pubdef.in | awk '{print $1}'`; do \
-	egrep -w "^#define[	 ]$i|^[	 ][	 ]*$i" ../dbinc/db.in; \
- done |
- sed -e 's/^#define[	 ][	 ]*//' \
-     -e 's/[()=,]/ /g' |
- awk '{ print "    public static final int " $1 ";" }') >> $t
-sed -n \
-    '/END-JAVA-SPECIAL-CONSTANTS/,/BEGIN-JAVA-CONSTANT-INITIALIZATION/p' \
-    < $f >> $t
-(echo "        $msgjava" &&
- for i in `egrep '^DB_.*J$' pubdef.in | awk '{print $1}'`; do \
-	egrep -w "^#define[	 ]$i|^[	 ][	 ]*$i" ../dbinc/db.in; \
- done |
- sed -e 's/^#define[	 ][	 ]*//' \
-     -e 's/[()=,]/ /g' \
-     -e 's/\/\*/ /' | \
- awk '{ print "        " $1 " = DbConstants." $1 ";" }') >> $t
-sed -n '/END-JAVA-CONSTANT-INITIALIZATION/,$p' < $f >> $t
-
-f=../java/src/com/sleepycat/db/Db.java
-cmp $t $f > /dev/null 2>&1 ||
-    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
-
-# Script to convert DB C structure declarations into Java declarations.
-jclass()
-{
-	cat ../dbinc/db.in |
-	sed -n \
-	-e "/struct $1 {/,/^}/{" \
-	-e "/$1/d" \
-	-e '/;/!d' \
-	-e '/^}/d' \
-	-e '/char[	 ]*\*/{' \
-	-e "s/^[	 ]*[^\*]*\*[	 ]*\([^;]*\).*/$2    public String \1;/p"\
-	-e 'd' \
-	-e '}' \
-	-e '/time_t/{' \
-	-e "s/^[	 ]*[^	 ]*[	 ]*\([^;]*\).*/$2    public long \1;/p" \
-	-e 'd' \
-	-e '}' \
-	-e '/DB_LSN[	 ]*/{' \
-	-e "s/^[	 ]*[^	 ]*[	 ]*\([^;]*\).*/$2    public DbLsn \1;/p"\
-	-e 'd' \
-	-e '}' \
-	-e '/DB_TXN_ACTIVE[	 ]*\*/{' \
-	-e "s/^[	 ]*[^\*]*\*[	 ]*\([^;]*\).*/$2    public Active \1[];/p"\
-	-e 'd' \
-	-e '}' \
-	-e "s/^[	 ]*[^	 ]*[	 ]*\([^;]*\).*/$2    public int \1;/p" \
-	-e '}'
-}
-
-# Script to convert DB C structure declarations into Java declarations.
-jclass_jni()
-{
-	c=$3
-	h=$4
-	echo "extern int $2(JNIEnv *jnienv, jclass cl, jobject jobj, struct $1 *statp);" >> $h
-	echo "int $2(JNIEnv *jnienv, jclass cl," >> $c
-	echo "    jobject jobj, struct $1 *statp) {" >> $c
-	cat ../dbinc/db.in |
-	sed -n \
-	-e "/struct $1 {/,/^}/{" \
-	-e "/$1/d" \
-	-e '/;/!d' \
-	-e '/^}/d' \
-	-e '/char[	 ]*\*/{' \
-            -e "s/^[	 ]*[^\*]*\*[	 ]*\([^;]*\).*/	JAVADB_STAT_STRING(jnienv, cl, jobj, statp, \1);/p"\
-	-e 'd' \
-	-e '}' \
-	-e '/time_t/{' \
-	-e "s/^[	 ]*[^	 ]*[	 ]*\([^;]*\).*/	JAVADB_STAT_LONG(jnienv, cl, jobj, statp, \1);/p" \
-	-e 'd' \
-	-e '}' \
-	-e '/DB_LSN[	 ]*/{' \
-	-e "s/^[	 ]*[^	 ]*[	 ]*\([^;]*\).*/	JAVADB_STAT_LSN(jnienv, cl, jobj, statp, \1);/p"\
-	-e 'd' \
-	-e '}' \
-	-e '/DB_TXN_ACTIVE[	 ]*\*/{' \
-	-e "s/^[	 ]*[^\*]*\*[	 ]*\([^;]*\).*/	JAVADB_STAT_ACTIVE(jnienv, cl, jobj, statp, \1);/p"\
-	-e 'd' \
-	-e '}' \
-	-e "s/^[	 ]*[^	 ]*[	 ]*\([^;]*\).*/	JAVADB_STAT_INT(jnienv, cl, jobj, statp, \1);/p" \
-	-e '}' >> $c
-        echo '	return (0);' >> $c
-	echo '}' >> $c
-}
-
-echo "$msgjava" >> $c
-echo "$msgjava" >> $h
-echo '#include "java_util.h"' >> $c
-
-# Build DbBtreeStat.java
-(echo "$msgjava" &&
- echo &&
- echo 'package com.sleepycat.db;' &&
- echo &&
- echo "public class DbBtreeStat"
- echo '{'
- jclass __db_bt_stat &&
- echo '}' &&
- echo '// end of DbBtreeStat.java') > $t
-jclass_jni __db_bt_stat __jv_fill_bt_stat $c $h
-f=../java/src/com/sleepycat/db/DbBtreeStat.java
-cmp $t $f > /dev/null 2>&1 ||
-    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
-
-# Build DbHashStat.java
-(echo "$msgjava" &&
- echo &&
- echo 'package com.sleepycat.db;' &&
- echo &&
- echo "public class DbHashStat"
- echo '{'
- jclass __db_h_stat &&
- echo '}' &&
- echo '// end of DbHashStat.java') > $t
-jclass_jni __db_h_stat __jv_fill_h_stat $c $h
-f=../java/src/com/sleepycat/db/DbHashStat.java
-cmp $t $f > /dev/null 2>&1 ||
-    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
-
-# Build DbLockStat.java
-(echo "$msgjava" &&
- echo &&
- echo 'package com.sleepycat.db;' &&
- echo &&
- echo "public class DbLockStat"
- echo '{'
- jclass __db_lock_stat &&
- echo '}' &&
- echo '// end of DbLockStat.java') > $t
-jclass_jni __db_lock_stat __jv_fill_lock_stat $c $h
-f=../java/src/com/sleepycat/db/DbLockStat.java
-cmp $t $f > /dev/null 2>&1 ||
-    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
-
-# Build DbLogStat.java
-(echo "$msgjava" &&
- echo &&
- echo 'package com.sleepycat.db;' &&
- echo &&
- echo "public class DbLogStat"
- echo '{'
- jclass __db_log_stat &&
- echo '}' &&
- echo '// end of DbLogStat.java') > $t
-jclass_jni __db_log_stat __jv_fill_log_stat $c $h
-f=../java/src/com/sleepycat/db/DbLogStat.java
-cmp $t $f > /dev/null 2>&1 ||
-    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
-
-# Build DbMpoolFStat.java
-(echo "$msgjava" &&
- echo &&
- echo 'package com.sleepycat.db;' &&
- echo &&
- echo "public class DbMpoolFStat"
- echo '{'
- jclass __db_mpool_fstat &&
- echo '}' &&
- echo '// end of DbMpoolFStat.java') > $t
-jclass_jni __db_mpool_stat __jv_fill_mpool_stat $c $h
-f=../java/src/com/sleepycat/db/DbMpoolFStat.java
-cmp $t $f > /dev/null 2>&1 ||
-    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
-
-# Build DbQueueStat.java
-(echo "$msgjava" &&
- echo &&
- echo 'package com.sleepycat.db;' &&
- echo &&
- echo "public class DbQueueStat"
- echo '{'
- jclass __db_qam_stat &&
- echo '}' &&
- echo '// end of DbQueueStat.java') > $t
-jclass_jni __db_qam_stat __jv_fill_qam_stat $c $h
-f=../java/src/com/sleepycat/db/DbQueueStat.java
-cmp $t $f > /dev/null 2>&1 ||
-    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
-
-# Build DbRepStat.java
-(echo "$msgjava" &&
- echo &&
- echo 'package com.sleepycat.db;' &&
- echo &&
- echo "public class DbRepStat"
- echo '{'
- jclass __db_rep_stat &&
- echo '}' &&
- echo '// end of DbRepStat.java') > $t
-jclass_jni __db_rep_stat __jv_fill_rep_stat $c $h
-f=../java/src/com/sleepycat/db/DbRepStat.java
-cmp $t $f > /dev/null 2>&1 ||
-    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
-
-# Build DbTxnStat.java
-(echo "$msgjava" &&
- echo &&
- echo 'package com.sleepycat.db;' &&
- echo &&
- echo "public class DbTxnStat"
- echo '{'
- echo "    public static class Active {"
- jclass __db_txn_active "    " &&
- echo '    };' &&
- jclass __db_txn_stat &&
- echo '}' &&
- echo '// end of DbTxnStat.java') > $t
-jclass_jni __db_txn_stat __jv_fill_txn_stat $c $h
-f=../java/src/com/sleepycat/db/DbTxnStat.java
-cmp $t $f > /dev/null 2>&1 ||
-    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
-
-mv $c $t
-f=../libdb_java/java_stat_auto.c
-cmp $t $f > /dev/null 2>&1 ||
-    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
-
-mv $h $t
-f=../libdb_java/java_stat_auto.h
-cmp $t $f > /dev/null 2>&1 ||
-    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+sh s_java_stat		# Create Java stat methods
+sh s_java_swig		# Create core Java API with SWIG
+sh s_java_const		# Create Java constants
diff --git a/storage/bdb/dist/s_java_const b/storage/bdb/dist/s_java_const
new file mode 100755
index 0000000000000000000000000000000000000000..644b32324d6a40d26cdd8cb752ebcdeec56c228a
--- /dev/null
+++ b/storage/bdb/dist/s_java_const
@@ -0,0 +1,35 @@
+#!/bin/sh -
+#	$Id: s_java_const,v 1.27 2004/07/30 14:51:37 mjc Exp $
+#
+# Build the Java files.
+
+msgjava="/* DO NOT EDIT: automatically built by dist/s_java_const. */"
+
+. RELEASE
+
+t=/tmp/__java
+trap 'rm -f $t; exit 0' 0 1 2 3 13 15
+
+(echo "$msgjava" &&
+ echo &&
+ echo 'package com.sleepycat.db.internal;' &&
+ echo &&
+ echo 'public interface DbConstants' &&
+ echo '{' &&
+ for i in `egrep '^DB_.*J$' pubdef.in | awk '{print $1}'`; do \
+     egrep -w "^#define[	 ]$i|^[	 ][	 ]*$i" ../dbinc/db.in; \
+ done |
+ sed -e "s/@DB_VERSION_MAJOR@/$DB_VERSION_MAJOR/" \
+     -e "s/@DB_VERSION_MINOR@/$DB_VERSION_MINOR/" \
+     -e "s/@DB_VERSION_PATCH@/$DB_VERSION_PATCH/" \
+     -e 's/^#define[	 ][	 ]*//' \
+     -e 's/[()=,]/ /g' \
+     -e 's/\/\*/ /' | \
+ awk '{ print "    int " $1 " = " $2 ";" }' &&
+ echo '}' &&
+ echo &&
+ echo '// end of DbConstants.java') > $t
+
+f=../java/src/com/sleepycat/db/internal/DbConstants.java
+cmp $t $f > /dev/null 2>&1 ||
+    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
diff --git a/storage/bdb/dist/s_java_stat b/storage/bdb/dist/s_java_stat
new file mode 100755
index 0000000000000000000000000000000000000000..4eb2ab1470ace002a823b6eab5c2b80e0cba0919
--- /dev/null
+++ b/storage/bdb/dist/s_java_stat
@@ -0,0 +1,327 @@
+#!/bin/sh -
+#	$Id: s_java_stat,v 1.33 2004/09/28 19:30:36 mjc Exp $
+#
+# Build the Java files.
+
+msgjava="/*-
+ * DO NOT EDIT: automatically built by dist/s_java_stat.
+ *
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2002-2004
+ *	Sleepycat Software.  All rights reserved.
+ */"
+
+
+s=/tmp/__java.sed
+t=/tmp/__java
+c=/tmp/__javajnic
+u1=/tmp/__javautil1
+u2=/tmp/__javautil2
+trap 'rm -f $t $c $u1 $u2; exit 0' 0 1 2 3 13 15
+
+# Script to convert DB C structure declarations into Java declarations.
+jclass()
+{
+	cat > $s <<EOF
+/struct __db_$1 {/,/^}/{
+	/__db_$1/d
+	/;/!d
+	/^}/d
+	/char[	 ]*\*/{
+		s/^[	 ]*[^\*]*\*[	 ]*\([^;]*\).*/\\
+$2    private String \1;\\
+$2    public String get_\1() {\\
+$2        return \1;\\
+$2    }/p
+		d
+	}
+	/time_t/{
+		s/^[	 ]*[^	 ]*[	 ]*\([^;]*\).*/\\
+$2    private long \1;\\
+$2    public long get_\1() {\\
+$2        return \1;\\
+$2    }/p
+		d
+	}
+	/db_seq_t/{
+		s/^[	 ]*[^	 ]*[	 ]*\([^;]*\).*/\\
+$2    private long \1;\\
+$2    public long get_\1() {\\
+$2        return \1;\\
+$2    }/p
+		d
+	}
+	/DB_LSN[	 ]*/{
+		s/^[	 ]*[^	 ]*[	 ]*\([^;]*\).*/\\
+$2    private LogSequenceNumber \1;\\
+$2    public LogSequenceNumber get_\1() {\\
+$2        return \1;\\
+$2    }/p
+		d
+	}
+	/DB_TXN_ACTIVE[	 ]*\*/{
+		s/^[	 ]*[^\*]*\*[	 ]*\([^;]*\).*/\\
+$2    private Active[] \1;\\
+$2    public Active[] get_\1() {\\
+$2        return \1;\\
+$2    }/p
+		d
+	}
+	/u_int8_t[	 ]*xid\[/{
+		s/^[	 ]*[^	 ]*[	 ]*\([^[;]*\).*/\\
+$2    private byte[] \1;\\
+$2    public byte[] get_\1() {\\
+$2        return \1;\\
+$2    }/p
+		d
+	}
+	s/^[	 ]*[^	 ]*[	 ]*\([^;]*\).*/\\
+$2    private int \1;\\
+$2    public int get_\1() {\\
+$2        return \1;\\
+$2    }/p
+}
+EOF
+	sed -n -f $s < ../dbinc/db.in |
+	perl -w -p -e 's/get_(st|bt|hash|qs)_/get_/;' \
+	           -e 'if (m/get.*\(/) {' \
+	           -e     's/_n([b-df-hj-np-tv-z])/_num_$1/;' \
+	           -e     's/_(min|max)([a-z])/_$1_$2/;' \
+	           -e     's/pg(.)/_pages_$1/;' \
+	           -e     's/(count|flag|free|id\(|page|size|timeout)/_$1/g;' \
+	           -e     's/__*/_/g;' \
+	           -e     's/_(.)/\U$1/g' \
+	           -e '};' \
+	           -e '1'
+}
+
+# Script to convert DB C structure declarations into a JNI method to fill the
+# corresponding Java class
+jclass_jni()
+{
+	fill=__dbj_fill_$1
+	j_class=$2
+	jni_fieldid_decls $1 $2
+	jni_fieldids $1 $2
+	cat > $s <<EOF
+/struct __db_$1 {/,/^}/{
+	/__db_$1/d
+	/;/!d
+	/^}/d
+	/char[	 ]*\*/{
+		s/^[	 ]*[^\*]*\*[	 ]*\([^;]*\).*/	JAVADB_STAT_STRING(jnienv, jobj, $1_\1_fid, statp, \1);/p
+		d
+	}
+	/time_t/{
+		s/^[	 ]*[^	 ]*[	 ]*\([^;]*\).*/	JAVADB_STAT_LONG(jnienv, jobj, $1_\1_fid, statp, \1);/p
+		d
+	}
+	/db_seq_t/{
+		s/^[	 ]*[^	 ]*[	 ]*\([^;]*\).*/	JAVADB_STAT_LONG(jnienv, jobj, $1_\1_fid, statp, \1);/p
+		d
+	}
+	/DB_LSN[	 ]*/{
+		s/^[	 ]*[^	 ]*[	 ]*\([^;]*\).*/	JAVADB_STAT_LSN(jnienv, jobj, $1_\1_fid, statp, \1);/p
+		d
+	}
+	/DB_TXN_ACTIVE[	 ]*\*/{
+		s/^[	 ]*[^\*]*\*[	 ]*\([^;]*\).*/	JAVADB_STAT_ACTIVE(jnienv, jobj, $1_\1_fid, statp, \1);/p
+		d
+	}
+	/u_int8_t[	 ]*xid\[/{
+		s/^[	 ]*[^	 ]*[	 ]*\([^[;]*\).*/	JAVADB_STAT_XID(jnienv, jobj, $1_\1_fid, statp, \1);/p
+		d
+	}
+	s/^[	 ]*[^	 ]*[	 ]*\([^;]*\).*/	JAVADB_STAT_INT(jnienv, jobj, $1_\1_fid, statp, \1);/p
+}
+EOF
+	echo "static int $fill(JNIEnv *jnienv, " >> $c
+	echo "    jobject jobj, struct __db_$1 *statp) {" >> $c
+	sed -n -f $s < ../dbinc/db.in >> $c
+        echo '	return (0);' >> $c
+	echo '}' >> $c
+}
+
+jni_fieldid_decls()
+{
+	cat > $s <<EOF
+/struct __db_$1 {/,/^}/{
+	/__db_$1/d
+	/;/!d
+	/^}/d
+	/char[	 ]*\*/{
+		s/^[	 ]*[^\*]*\*[	 ]*\([^;]*\).*/static jfieldID $1_\1_fid;/p
+		d
+	}
+	/time_t/{
+		s/^[	 ]*[^	 ]*[	 ]*\([^;]*\).*/static jfieldID $1_\1_fid;/p
+		d
+	}
+	/db_seq_t/{
+		s/^[	 ]*[^	 ]*[	 ]*\([^;]*\).*/static jfieldID $1_\1_fid;/p
+		d
+	}
+	/DB_LSN[	 ]*/{
+		s/^[	 ]*[^	 ]*[	 ]*\([^;]*\).*/static jfieldID $1_\1_fid;/p
+		d
+	}
+	/DB_TXN_ACTIVE[	 ]*\*/{
+		s/^[	 ]*[^\*]*\*[	 ]*\([^;]*\).*/static jfieldID $1_\1_fid;/p
+		d
+	}
+	/u_int8_t[	 ]*xid\[/{
+		s/^[	 ]*[^	 ]*[	 ]*\([^[;]*\).*/static jfieldID $1_\1_fid;/p
+		d
+	}
+	s/^[	 ]*[^	 ]*[	 ]*\([^;]*\).*/static jfieldID $1_\1_fid;/p
+}
+EOF
+	sed -n -f $s < ../dbinc/db.in >> $u1
+}
+
+jni_fieldids()
+{
+	cat > $s <<EOF
+/struct __db_$1 {/,/^}/{
+	/__db_$1/d
+	/;/!d
+	/^}/d
+	/char[	 ]*\*/{
+		s/^[	 ]*[^\*]*\*[	 ]*\([^;]*\).*/	{ \&$1_\1_fid, \&$1_class, \"\1\", \"Ljava\/lang\/String;\" },/p
+		d
+	}
+	/time_t/{
+		s/^[	 ]*[^	 ]*[	 ]*\([^;]*\).*/	{ \&$1_\1_fid, \&$1_class, \"\1\", \"J\" },/p
+		d
+	}
+	/db_seq_t/{
+		s/^[	 ]*[^	 ]*[	 ]*\([^;]*\).*/	{ \&$1_\1_fid, \&$1_class, \"\1\", \"J\" },/p
+		d
+	}
+	/DB_LSN[	 ]*/{
+		s/^[	 ]*[^	 ]*[	 ]*\([^;]*\).*/	{ \&$1_\1_fid, \&$1_class, \"\1\", \"L\" DB_PKG \"LogSequenceNumber;\" },/p
+		d
+	}
+	/DB_TXN_ACTIVE[	 ]*\*/{
+		s/^[	 ]*[^\*]*\*[	 ]*\([^;]*\).*/	{ \&$1_\1_fid, \&$1_class, \"\1\", \"[L\" DB_PKG \"TransactionStats\$Active;\" },/p
+		d
+	}
+	/u_int8_t[	 ]*xid\[/{
+		s/^[	 ]*[^	 ]*[	 ]*\([^[;]*\).*/	{ \&$1_\1_fid, \&$1_class, \"\1\", \"[B\" },/p
+		d
+	}
+	s/^[	 ]*[^	 ]*[	 ]*\([^;]*\).*/	{ \&$1_\1_fid, \&$1_class, \"\1\", \"I\" },/p
+}
+EOF
+	sed -n -f $s < ../dbinc/db.in >> $u2
+}
+
+# Script to convert DB C structure declarations into a toString method body
+jclass_toString()
+{
+	cat > $s <<EOF
+/struct __db_$1 {/,/^}/{
+	/__db_$1/d
+	/;/!d
+	/^}/d
+	/char[	 ]*\*/{
+		s/^[	 ]*[^\*]*\*[	 ]*\([^;]*\).*/$3            + "\\\\n$3  \1=" + \1/p
+		d
+	}
+	/DB_TXN_ACTIVE[	 ]*\*/{
+		s/^[	 ]*[^\*]*\*[	 ]*\([^;]*\).*/$3            + \"\\\\n$3  \1=\" + DbUtil.objectArrayToString(\1, \"\1\")/p
+		d
+	}
+	/u_int8_t[	 ]*xid\[/{
+		s/^[	 ]*[^	 ]*[	 ]*\([^[;]*\).*/$3            + \"\\\\n$3  \1=\" + DbUtil.byteArrayToString(\1)/p
+		d
+	}
+	s/^[	 ]*[^	 ]*[	 ]*\([^;]*\).*/$3            + \"\\\\n$3  \1=\" + \1/p
+}
+EOF
+	echo
+	echo "$3    public String toString() {"
+	echo "$3        return \"$2:\""
+	sed -n -f $s < ../dbinc/db.in
+	echo "$3            ;"
+	echo "$3    }"
+}
+
+stat_class()
+{
+	c_struct=__db_$1
+	j_class=$2
+	extends=$3
+
+	(echo "$msgjava"
+	 echo
+	 echo 'package com.sleepycat.db;'
+	 echo
+	 echo "public class $j_class$extends {"
+	 echo "    // no public constructor"
+	 echo "    protected $j_class() {}"
+	 jclass $1
+	 jclass_toString $1 $2
+	 echo '}') > $t
+	jclass_jni $1 $2
+	f=../java/src/com/sleepycat/db/$j_class.java
+	cmp $t $f > /dev/null 2>&1 ||
+	    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+}
+
+echo "$msgjava" > $c
+> $u1
+> $u2
+
+stat_class bt_stat BtreeStats " extends DatabaseStats"
+stat_class h_stat HashStats " extends DatabaseStats"
+stat_class lock_stat LockStats
+stat_class log_stat LogStats
+stat_class mpool_fstat CacheFileStats
+stat_class mpool_stat CacheStats
+stat_class qam_stat QueueStats " extends DatabaseStats"
+stat_class rep_stat ReplicationStats
+stat_class seq_stat SequenceStats
+
+# Build TransactionStats.java - special because of embedded Active class
+(echo "$msgjava"
+ echo
+ echo 'package com.sleepycat.db;'
+ echo
+ echo 'import com.sleepycat.db.internal.DbUtil;'
+ echo
+ echo "public class TransactionStats"
+ echo '{'
+ echo "    // no public constructor"
+ echo "    protected TransactionStats() {}"
+ echo
+ echo -n "    public static class Active {"
+ echo    "        // no public constructor"
+ echo    "        protected Active() {}"
+ jclass txn_active "    "
+ jclass_toString txn_active Active "    "
+ echo '    };'
+ jclass txn_stat
+ jclass_toString txn_stat TransactionStats
+ echo '}'
+ echo '// end of TransactionStats.java') > $t
+jclass_jni txn_stat __dbj_fill_txn_stat
+jclass_jni txn_active __dbj_fill_txn_active
+f=../java/src/com/sleepycat/db/TransactionStats.java
+cmp $t $f > /dev/null 2>&1 ||
+    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+
+mv $c $t
+f=../libdb_java/java_stat_auto.c
+cmp $t $f > /dev/null 2>&1 ||
+    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+
+f=../libdb_java/java_util.i
+sed '/BEGIN-STAT-FIELD-DECLS/q' < $f > $t
+cat $u1 >> $t
+sed -n '/END-STAT-FIELD-DECLS/,/BEGIN-STAT-FIELDS/p' < $f >> $t
+cat $u2 >> $t
+sed -n '/END-STAT-FIELDS/,$p' < $f >> $t
+cmp $t $f > /dev/null 2>&1 ||
+    (echo "Building $f" && rm -f $f && cp $t $f && chmod 644 $f)
diff --git a/storage/bdb/dist/s_java_swig b/storage/bdb/dist/s_java_swig
new file mode 100755
index 0000000000000000000000000000000000000000..c1e67e3160852d60c01614da8f64c7d9eac2bff5
--- /dev/null
+++ b/storage/bdb/dist/s_java_swig
@@ -0,0 +1,55 @@
+#!/bin/sh -
+#       $Id: s_java_swig,v 11.11 2004/09/23 17:31:53 mjc Exp $
+#
+# Run SWIG to generate the Java APIs
+
+SWIG=swig
+SWIG_DIR=../libdb_java
+SWIG_FILE=$SWIG_DIR/db.i
+PACKAGE="com.sleepycat.db.internal"
+
+die() {
+	echo "$@" >&2
+	exit 1
+}
+
+[ -f $SWIG_FILE ] || die "Must be run from the dist directory"
+
+for api in java ; do
+	echo "Building $api API"
+
+	swig_args=""
+	case $api in
+	java)
+		swig_args="-nodefault -package $PACKAGE $args"
+		;;
+	esac
+
+	$SWIG -Wall -$api $swig_args -I$SWIG_DIR \
+	    -o ../libdb_$api/db_${api}_wrap.c $SWIG_FILE || exit $?
+done
+
+# Skip Java sources if run with "-n"
+if [ "x$1" = "x-n" ] ; then
+	rm -f $SWIG_DIR/*.java
+	exit 0
+fi
+
+# Fixups for Java
+JAVA_SRCTOP=../java/src
+JAVA_PKGDIR=com/sleepycat/db/internal
+JAVA_SRCDIR=$JAVA_SRCTOP/$JAVA_PKGDIR
+
+# SWIG 1.3.18 puts the Java files in the same directory as the native code.
+cd $SWIG_DIR
+[ -f Db.java ] || exit 1
+
+for f in *.java ; do
+	case $f in
+		SWIGTYPE*)
+			die "Interface contains unresolved types: $f"
+	esac
+	rm -f $JAVA_SRCDIR/$f
+	perl -p $SWIG_DIR/java-post.pl < $f > $JAVA_SRCDIR/$f || exit $?
+	rm -f $f
+done
diff --git a/storage/bdb/dist/s_je2db b/storage/bdb/dist/s_je2db
new file mode 100644
index 0000000000000000000000000000000000000000..aaaa42cf12de5e8ecc8a4eb99af2583327a23cea
--- /dev/null
+++ b/storage/bdb/dist/s_je2db
@@ -0,0 +1,88 @@
+#!/bin/sh -
+
+# The examples must be hand-edited after they are copied:
+# - add setInitializeCache(true), setInitializeLocking(true), setType(BTREE)
+# - add null databaseName param to openDatabase() and openSecondaryDatabase()
+# - remove foreign key configuration and imports
+
+COPY_EXAMPLES=0
+
+JEDIR=$1
+if [ $# -eq 1 ] ; then
+    DBDIR=..
+else
+    DBDIR=$2
+fi
+
+if [ ! -d "$DBDIR/dbinc" -o ! -f "$JEDIR/build.xml" ] ; then
+	echo >&2 "Usage $0 /path/to/je [ /path/to/db ]"
+	exit 1
+fi
+
+JEDIR=$(cd "$JEDIR" ; /bin/pwd)
+DBDIR=$(cd "$DBDIR" ; /bin/pwd)
+
+JESRC="$JEDIR/src"
+JETEST="$JEDIR/test"
+JEEXAMPLES="$JEDIR/examples"
+DBSRC="$DBDIR/java/src"
+DBTEST="$DBDIR/test/scr024/src"
+DBEXAMPLES="$DBDIR/examples_java/src"
+DIRMATCH="com/sleepycat\(/examples\)*/\(\(bind\)\|\(collections\)\|\(util\)\)"
+
+cd "$JESRC"
+for d in `find . -type d | grep -v CVS | grep $DIRMATCH` ; do
+	#echo "$DBSRC/$d"
+	mkdir -p "$DBSRC/$d"
+done
+cd "$JETEST"
+for d in `find . -type d | grep -v CVS | grep $DIRMATCH` ; do
+	#echo "$DBTEST/$d"
+	mkdir -p "$DBTEST/$d"
+done
+if [ $COPY_EXAMPLES -eq 1 ] ; then
+    cd "$JEEXAMPLES"
+    for d in `find . -type d | grep -v CVS | grep $DIRMATCH` ; do
+            #echo "$DBEXAMPLES/$d"
+            mkdir -p "$DBEXAMPLES/$d"
+    done
+fi
+
+E1='s/com\.sleepycat\.je/com.sleepycat.db/g'
+E2='/import com\.sleepycat\.db\.ForeignKeyNullifier/d'
+E3='/implements/s/, ForeignKeyNullifier//'
+E4='/<!-- begin JE only -->/,/<!-- end JE only -->/d'
+EXCLUDETESTS="\(\(ForeignKeyTest\)\|\(TupleSerialFactoryTest\)\)"
+
+cd "$JESRC"
+for f in `find . -name '*.java' | grep $DIRMATCH` ; do
+	#echo $DBSRC/$f
+	sed -e "$E1" -e "$E2" -e "$E3" -e "$E4" < $f > $DBSRC/$f.sed.out
+        diff -q -I "\$\Id:" $DBSRC/$f $DBSRC/$f.sed.out || \
+            mv -f $DBSRC/$f.sed.out $DBSRC/$f
+        rm -f $DBSRC/$f.sed.out
+done
+
+cd "$JETEST"
+for f in `find . -name '*.java' | grep $DIRMATCH | grep -v $EXCLUDETESTS` ; do
+	#echo $DBTEST/$f
+	sed -e "$E1" < $f > $DBTEST/$f.sed.out
+        diff -q -I "\$\Id:" $DBTEST/$f $DBTEST/$f.sed.out || \
+            mv -f $DBTEST/$f.sed.out $DBTEST/$f
+        rm -f $DBTEST/$f.sed.out
+done
+cp -f "com/sleepycat/collections/test/serial/TestSerial.java.original" \
+      "$DBTEST/com/sleepycat/collections/test/serial"
+
+if [ $COPY_EXAMPLES -eq 1 ] ; then
+    cd "$JEEXAMPLES"
+    for f in `find . -name '*.java' | grep $DIRMATCH` ; do
+            #echo $DBEXAMPLES/$f
+            sed -e "$E1" < $f > $DBEXAMPLES/$f.sed.out
+            diff -q -I "\$\Id:" $DBEXAMPLES/$f $DBEXAMPLES/$f.sed.out || \
+                mv -f $DBEXAMPLES/$f.sed.out $DBEXAMPLES/$f
+            rm -f $DBEXAMPLES/$f.sed.out
+    done
+fi
+
+exit 0
diff --git a/storage/bdb/dist/s_perm b/storage/bdb/dist/s_perm
index c35278b8c8388ede9ed5f1eaebec9ac64c64c0a1..8c3a0f74645758d345f3bd9944b756b71121d5da 100755
--- a/storage/bdb/dist/s_perm
+++ b/storage/bdb/dist/s_perm
@@ -1,14 +1,12 @@
 #!/bin/sh -
-#	$Id: s_perm,v 1.23 2002/09/09 15:03:06 bostic Exp $
+#	$Id: s_perm,v 1.31 2004/10/05 18:56:58 bostic Exp $
 
 d=..
 echo 'Updating Berkeley DB source tree permissions...'
 
-. ./RELEASE
-
 run()
 {
-	echo "	$1 ($2)"
+	#echo "	$1 ($2)"
 	if [ -f "$d/$1" ]; then
 		chmod "$2" "$d/$1"
 	else
@@ -24,9 +22,12 @@ run dist/configure 555
 run dist/install-sh 555
 run dist/s_all 555
 run dist/s_config 555
+run dist/s_crypto 555
 run dist/s_include 555
 run dist/s_java 555
-run dist/s_javah 555
+run dist/s_java_const 555
+run dist/s_java_stat 555
+run dist/s_java_swig 555
 run dist/s_perm 555
 run dist/s_readme 555
 run dist/s_recover 555
@@ -38,12 +39,13 @@ run dist/s_vxworks 555
 run dist/s_win32 555
 run dist/s_win32_dsp 555
 run dist/vx_buildcd 555
+run mod_db4/configure 555
 
 run perl/BerkeleyDB/dbinfo 555
 run perl/BerkeleyDB/mkpod 555
 
 for i in `cd $d && find build_vxworks \
     -name '*.wsp' -o -name '*.cdf' -o -name '*.wpj'`; do
-	echo "	$i (775)"
+	#echo "	$i (775)"
 	chmod 775 $d/$i
 done
diff --git a/storage/bdb/dist/s_readme b/storage/bdb/dist/s_readme
index 1da9f9681c0ad24b08963320f8209d9262287328..f2ed0704451a7835c55f2245c97fdfa19b603b30 100755
--- a/storage/bdb/dist/s_readme
+++ b/storage/bdb/dist/s_readme
@@ -1,14 +1,16 @@
 #!/bin/sh -
-#	$Id: s_readme,v 1.6 2002/02/14 02:50:26 bostic Exp $
+#	$Id: s_readme,v 1.7 2003/07/02 15:27:44 bostic Exp $
 #
 # Build the README.
 
+echo 'Updating Berkeley DB README file...'
+
 d=..
 
 t=/tmp/__t
 trap 'rm -f $t; exit 0' 0 1 2 3 13 15
 
-. ./RELEASE
+. RELEASE
 
 cat << END_OF_README>$t
 $DB_VERSION_STRING
diff --git a/storage/bdb/dist/s_recover b/storage/bdb/dist/s_recover
index fc2e160c0834b03e16de2812eeff548164dfa278..b30a085545d9a6c530dc245e3e2e53c62b79da9c 100755
--- a/storage/bdb/dist/s_recover
+++ b/storage/bdb/dist/s_recover
@@ -1,32 +1,29 @@
 #!/bin/sh -
-#	$Id: s_recover,v 1.14 2002/03/27 04:31:51 bostic Exp $
+#	$Id: s_recover,v 1.17 2004/06/17 17:35:19 bostic Exp $
 #
 # Build the automatically generated logging/recovery files.
 
-. ./RELEASE
-
-tmp=/tmp/__db_a
+header=/tmp/__db_a
 loglist=/tmp/__db_b
-source=/tmp/__db_c
-header=/tmp/__db_d
+print=/tmp/__db_c
+source=/tmp/__db_d
 template=/tmp/__db_e
+tmp=/tmp/__db_f
 
-trap 'rm -f $tmp $loglist $source $header $template; exit 1' 1 2 3 13 15
-trap 'rm -f $tmp $loglist $source $header $template; exit 0' 0
+trap 'rm -f /tmp/__db_[abcdef]; exit 1' 1 2 3 13 15
+trap 'rm -f /tmp/__db_[abcdef]; exit 0' 0
 
-DIR="db dbreg btree hash qam txn"
+DIR="db dbreg btree fileops hash qam rep txn"
 
 # Check to make sure we haven't duplicated a log record entry, and build
 # the list of log record types that the test suite uses.
 for i in $DIR; do
-	p=none
 	for f in ../$i/*.src; do
 		# Grab the PREFIX;  there should only be one per file, and
 		# so it's okay to just take the first.
 		grep '^PREFIX' $f | sed q
 		egrep '^BEGIN[	 ]|^IGNORED[	 ]|^DEPRECATED[	 ]' $f |
 		    awk '{print $1 "\t" $2 "\t" $3}'
-
 	done
 done > $loglist
 grep -v '^PREFIX' $loglist |
@@ -42,12 +39,13 @@ cmp $loglist $f > /dev/null 2>&1 ||
     (echo "Building $f" && rm -f $f && cp $loglist $f && chmod 444 $f)
 
 # Build DB's recovery routines.
-for i in db dbreg btree fileops hash qam txn; do
+for i in $DIR; do
 	for f in ../$i/*.src; do
 		subsystem=`basename $f .src`
 		awk -f gen_rec.awk \
-		    -v source_file=$source \
 		    -v header_file=$header \
+		    -v print_file=$print\
+		    -v source_file=$source \
 		    -v template_file=$template < $f
 
 		f=../dbinc_auto/${subsystem}_auto.h
@@ -58,6 +56,10 @@ for i in db dbreg btree fileops hash qam txn; do
 		cmp $source $f > /dev/null 2>&1 ||
 		    (echo "Building $f" &&
 		    rm -f $f && cp $source $f && chmod 444 $f)
+		f=../$i/${subsystem}_autop.c
+		cmp $print $f > /dev/null 2>&1 ||
+		    (echo "Building $f" &&
+		    rm -f $f && cp $print $f && chmod 444 $f)
 		f=template/rec_${subsystem}
 		cmp $template $f > /dev/null 2>&1 ||
 		    (echo "Building $f" &&
@@ -66,4 +68,4 @@ for i in db dbreg btree fileops hash qam txn; do
 done
 
 # Build the example application's recovery routines.
-#(cd ../examples_c/ex_apprec && sh auto_rebuild)
+(cd ../examples_c/ex_apprec && sh auto_rebuild)
diff --git a/storage/bdb/dist/s_rpc b/storage/bdb/dist/s_rpc
index cdafa669d85b2e29abb5446c5395e02b20be1a9d..8dada0e3baf8b26356ba4752b928f6974b43dcc9 100644
--- a/storage/bdb/dist/s_rpc
+++ b/storage/bdb/dist/s_rpc
@@ -1,9 +1,9 @@
 #!/bin/sh -
-#	$Id: s_rpc,v 11.18 2002/08/15 15:22:09 bostic Exp $
+#	$Id: s_rpc,v 11.20 2004/03/11 20:11:17 bostic Exp $
 #
 # Build the automatically generated RPC files
 
-echo "Building RPC client/server files"
+echo "Building RPC client/server files..."
 
 . ./RELEASE
 
@@ -13,122 +13,26 @@ trap 'rm -f $t ; exit 1' 1 2 3 13 15
 
 client_file=../rpc_client/gen_client.c
 ctmpl_file=./template/gen_client_ret
-dbinc_file=../dbinc/db.in
-defs_file=../dbinc_auto/rpc_defs.in
-header_file=../dbinc_auto/db_server.h
-proc_file=../rpc_server/c/db_server_proc.c
-rpcclnt_file=../rpc_client/db_server_clnt.c
-rpcsvc_file=../rpc_server/c/db_server_svc.c
-rpcxdr_file=../rpc_server/c/db_server_xdr.c
-sed_file=../rpc_server/c/db_server_proc.sed
 server_file=../rpc_server/c/gen_db_server.c
 stmpl_file=./template/db_server_proc
 xdr_file=../rpc_server/db_server.x
 
-rm -f   $client_file \
-	$ctmpl_file \
-	$header_file \
-	$rpcclnt_file \
-	$rpcsvc_file \
-	$proc_file \
-	$rpcxdr_file \
-	$sed_file \
-	$server_file \
-	$stmpl_file \
-	$xdr_file
+rm -f $client_file $ctmpl_file $server_file $stmpl_file $xdr_file
 
 #
 # Generate client/server/XDR code
 #
 xidsize=\
-`awk '/^#define/ { if ($2 == "DB_XIDDATASIZE") { print $3 }}' $dbinc_file`
+`awk '/^#define/ { if ($2 == "DB_XIDDATASIZE") { print $3 }}' ../dbinc/db.in`
 
 awk -f gen_rpc.awk \
-    -v major=$DB_VERSION_MAJOR \
-    -v minor=$DB_VERSION_MINOR \
-    -v xidsize=$xidsize \
     -v client_file=$client_file \
     -v ctmpl_file=$ctmpl_file \
-    -v sed_file=$sed_file \
+    -v major=$DB_VERSION_MAJOR \
+    -v minor=$DB_VERSION_MINOR \
     -v server_file=$server_file \
     -v stmpl_file=$stmpl_file \
-    -v xdr_file=$xdr_file < ../rpc_server/rpc.src
-chmod 444 $client_file $server_file
+    -v xdr_file=$xdr_file \
+    -v xidsize=$xidsize < ../rpc_server/rpc.src
 
-#
-# Now run rpcgen to generate all our sources from the XDR file
-#
-rpcgen -h $xdr_file > $header_file
-rpcgen -l $xdr_file > $rpcclnt_file
-rpcgen -s tcp $xdr_file > $rpcsvc_file
-rpcgen -c $xdr_file > $rpcxdr_file
-
-#
-# Run various server files through sed.
-#
-cat <<ENDOFSEDTEXT>$t
-s/^#include[	 ]"db_server.h"/#include "db_config.h"\\
-\\
-\\#ifndef NO_SYSTEM_INCLUDES\\
-\\#include <rpc\\/rpc.h>\\
-\\#include <rpc\\/pmap_clnt.h>/
-/^#include <netinet.in.h>/a\\
-\\#endif\\
-\\
-\\#include "db_int.h"\\
-\\#include "dbinc_auto/db_server.h"\\
-\\#include "dbinc/db_server_int.h"\\
-\\#include "dbinc_auto/rpc_server_ext.h"
-/^	return;/i\\
-\\	__dbsrv_timeout(0);
-s/svc_sendreply(transp, xdr_void,/svc_sendreply(transp, (xdrproc_t)xdr_void,/
-s/svc_getargs(transp, xdr_argument, &argument)/svc_getargs(transp, (xdrproc_t)xdr_argument, (char *)\&argument)/
-s/svc_sendreply(transp, xdr_result, result)/svc_sendreply(transp, (xdrproc_t)xdr_result, result)/
-s/svc_freeargs(transp, xdr_argument, &argument)/svc_freeargs(transp, (xdrproc_t)xdr_argument, (char *)\&argument)/
-s/^main/void __dbsrv_main/
-ENDOFSEDTEXT
-sed -f $t $rpcsvc_file > ${rpcsvc_file}.new
-mv ${rpcsvc_file}.new $rpcsvc_file
-
-sed -f $sed_file ${proc_file}.in > ${proc_file}
-
-# Run rpcgen files through sed to add HAVE_RPC ifdef and appropriate
-# includes.
-cat <<ENDOFSEDTEXT>$t
-1i\\
-\\#include "db_config.h"\\
-\\
-\\#ifdef HAVE_RPC
-/^#include "db_server.h"/c\\
-\\#ifndef NO_SYSTEM_INCLUDES\\
-\\#include <rpc/rpc.h>\\
-\\
-\\#include <strings.h>\\
-\\#endif\\
-\\
-\\#include "db_int.h"\\
-\\#include "dbinc_auto/db_server.h"
-\$a\\
-\\#endif /* HAVE_RPC */
-ENDOFSEDTEXT
-
-sed -f $t $rpcxdr_file > ${rpcxdr_file}.new
-mv ${rpcxdr_file}.new $rpcxdr_file
-sed -f $t $rpcclnt_file > ${rpcclnt_file}.new
-mv ${rpcclnt_file}.new $rpcclnt_file
-
-# Copy the DB_RPC SERVER #defines into a separate file so
-# they can be part of db.h.
-msgc="/* DO NOT EDIT: automatically built by dist/s_rpc. */"
-(echo  "" && echo "$msgc" &&
-    sed -n -e "/DB_RPC_SERVER/p" $header_file) > $defs_file
-
-# Fix up the header file:
-#	Remove the DB_RPC_SERVER #defines.
-#	Remove the <rpc/rpc.h> include, it needs to be included earlier
-#	than that.
-sed -e "/DB_RPC_SERVER/d"\
-    -e "/^#include.*<rpc\/rpc.h>/d" $header_file > ${header_file}.new
-mv ${header_file}.new $header_file
-
-chmod 444 $header_file $rpcclnt_file $rpcsvc_file $rpcxdr_file
+chmod 444 $client_file $server_file
diff --git a/storage/bdb/dist/s_symlink b/storage/bdb/dist/s_symlink
index 8da49ca0c7520b33cbfb16f07f6cfbe8de1d4678..533eb6b4435ff64caa3b0faadef254f704a182e9 100755
--- a/storage/bdb/dist/s_symlink
+++ b/storage/bdb/dist/s_symlink
@@ -1,12 +1,11 @@
 #!/bin/sh -
-#	$Id: s_symlink,v 1.28 2002/08/18 21:15:45 bostic Exp $
+#	$Id: s_symlink,v 1.32 2004/04/01 15:10:53 bostic Exp $
 
 echo 'Creating Berkeley DB source tree symbolic links...'
-. ./RELEASE
 
 build()
 {
-	echo "	$1 -> $2"
+	#echo "	$1 -> $2"
 	(cd ../`dirname $1` && rm -f `basename $1` && ln -s $2 `basename $1`)
 }
 
@@ -14,7 +13,7 @@ build btree/tags ../dist/tags
 build build_unix/tags ../dist/tags
 build clib/tags ../dist/tags
 build common/tags ../dist/tags
-#build crypto/tags ../dist/tags
+build crypto/tags ../dist/tags
 build cxx/tags ../dist/tags
 build db/tags ../dist/tags
 build db185/tags ../dist/tags
@@ -34,9 +33,8 @@ build dbinc_auto/tags ../dist/tags
 build dbm/tags ../dist/tags
 build dbreg/tags ../dist/tags
 build env/tags ../dist/tags
-#build examples_c/tags ../dist/tags
-#build examples_cxx/tags ../dist/tags
-#build examples_java java/src/com/sleepycat/examples
+build examples_c/tags ../dist/tags
+build examples_cxx/tags ../dist/tags
 build fileops/tags ../dist/tags
 build hash/tags ../dist/tags
 build hmac/tags ../dist/tags
@@ -53,7 +51,7 @@ build qam/tags ../dist/tags
 build rep/tags ../dist/tags
 build rpc_client/tags ../dist/tags
 build rpc_server/tags ../dist/tags
+build sequence/tags ../dist/tags
 build tcl/tags ../dist/tags
-build test_server/tags ../dist/tags
 build txn/tags ../dist/tags
 build xa/tags ../dist/tags
diff --git a/storage/bdb/dist/s_tags b/storage/bdb/dist/s_tags
index 18b6025aa862f6b7e162767b9566c1fe756d26cc..d1c21e5b2329f89aeaca608fa5640dc72632695b 100755
--- a/storage/bdb/dist/s_tags
+++ b/storage/bdb/dist/s_tags
@@ -1,16 +1,14 @@
 #!/bin/sh -
-#	$Id: s_tags,v 1.16 2002/03/28 20:13:07 krinsky Exp $
+#	$Id: s_tags,v 1.18 2004/04/01 15:11:14 bostic Exp $
 #
 # Build tags files.
 
-. ./RELEASE
-
-files="../dbinc/*.h \
+files=`echo ../dbinc/*.h \
 	../dbinc/*.in \
 	../btree/*.[ch] \
 	../clib/*.[ch] \
 	../common/*.[ch] \
-#	../crypto/*.[ch] \
+	../crypto/*.[ch] \
 	../crypto/mersenne/*.[ch] \
 	../crypto/rijndael/*.[ch] \
 	../db/*.[ch] \
@@ -31,11 +29,12 @@ files="../dbinc/*.h \
 	../rep/*.[ch] \
 	../rpc_client/*.[ch] \
 	../rpc_server/c/*.[ch] \
+	../sequence/*.[ch] \
 	../tcl/*.[ch] \
 	../txn/*.[ch] \
 	../xa/*.[ch] \
 	../cxx/*.cpp \
-	../libdb_java/*.[ch]"
+	../libdb_java/*.[ch] | sed 's/[^ ]*stub.c//g'`
 
 f=tags
 echo "Building $f"
@@ -56,7 +55,7 @@ fi
 ctags $flags $files 2>/dev/null
 chmod 444 $f
 
-#f=../test_perf/tags
-#echo "Building $f"
-#(cd ../test_perf && ctags $flags *.[ch] 2>/dev/null)
-#chmod 444 $f
+f=../test_perf/tags
+echo "Building $f"
+(cd ../test_perf && ctags $flags *.[ch] 2>/dev/null)
+chmod 444 $f
diff --git a/storage/bdb/dist/s_test b/storage/bdb/dist/s_test
index 16f3b9712d04cb3c65adc41b457c5bdc009abf3f..df0648d56ba2d15e1a170d59e921755f33f5b5ae 100755
--- a/storage/bdb/dist/s_test
+++ b/storage/bdb/dist/s_test
@@ -1,5 +1,5 @@
 #!/bin/sh -
-#	$Id: s_test,v 1.24 2002/08/09 02:24:58 bostic Exp $
+#	$Id: s_test,v 1.29 2004/05/13 18:51:43 mjc Exp $
 #
 # Build the Tcl test files.
 
@@ -9,12 +9,12 @@ msg2="# Automatically built by dist/s_test; may require local editing."
 t=/tmp/__t
 trap 'rm -f $t; exit 0' 0 1 2 3 13 15
 
-. ./RELEASE
+. RELEASE
 
 (echo "$msg1"					&& \
  echo ""					&& \
  echo "set tclsh_path @TCL_TCLSH@"		&& \
- echo "set tcllib .libs/libdb_tcl-@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@MODSUFFIX@" && \
+ echo "set tcllib .libs/libdb_tcl-@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@@LIBTSO_MODSUFFIX@" && \
  echo ""					&& \
  echo "set rpc_server localhost"	 	&& \
  echo "set rpc_path ."			 	&& \
@@ -22,6 +22,7 @@ trap 'rm -f $t; exit 0' 0 1 2 3 13 15
  echo ""					&& \
  echo "set src_root @srcdir@/.."		&& \
  echo "set test_path @srcdir@/../test"		&& \
+ echo "set je_root @srcdir@/../../je"		&& \
  echo ""					&& \
  echo "global testdir"				&& \
  echo "set testdir ./TESTDIR"			&& \
@@ -46,6 +47,7 @@ cmp $t $f > /dev/null 2>&1 ||
  echo ""					&& \
  echo "set src_root .."				&& \
  echo "set test_path ../test"			&& \
+ echo "set je_root ../../je"			&& \
  echo ""					&& \
  echo "global testdir"				&& \
  echo "set testdir ./TESTDIR"			&& \
diff --git a/storage/bdb/dist/s_vxworks b/storage/bdb/dist/s_vxworks
index 05c2599d02c51e89d470e5b68be60920ddac1b5d..fbff44ab0197587c68d665919db20ea6ac11483a 100644
--- a/storage/bdb/dist/s_vxworks
+++ b/storage/bdb/dist/s_vxworks
@@ -1,21 +1,22 @@
 #!/bin/sh -
-#	$Id: s_vxworks,v 1.37 2002/08/19 21:27:06 bostic Exp $
+#	$Id: s_vxworks,v 1.52 2004/10/15 18:28:21 bostic Exp $
 #
 # Build the VxWorks files.
 
 msgc="/* DO NOT EDIT: automatically built by dist/s_vxworks. */"
 
-. ./RELEASE
+. RELEASE
 
 s=/tmp/__db_a
 t=/tmp/__db_b
-vxfilelist=/tmp/__db_c
+u=/tmp/__db_c
+vxfilelist=/tmp/__db_d
+vxsmallfiles=/tmp/__db_e
 
-trap 'rm -f $s $t $vxfilelist ; exit 0' 0
-trap 'rm -f $s $t $vxfilelist ; exit 1' 1 2 3 13 15
+trap 'rm -f $s $t $u $vxfilelist $vxsmallfiles ; exit 0' 0
+trap 'rm -f $s $t $u $vxfilelist $vxsmallfiles ; exit 1' 1 2 3 13 15
 
 # Build the VxWorks automatically generated files.
-f=../build_vxworks/db.h
 cat <<ENDOFSEDTEXT > $s
 /extern "C" {/{
 n
@@ -27,37 +28,54 @@ i\\
 #define	__vxworks\\
 #endif
 }
+/@inttypes_h_decl@/d
+/@stdint_h_decl@/d
+/@stddef_h_decl@/d
 s/@u_int8_decl@/typedef unsigned char u_int8_t;/
-s/@u_int16_decl@/typedef unsigned short u_int16_t;/
-s/@u_int32_decl@/typedef unsigned int u_int32_t;/
 /@int16_decl@/d
+s/@u_int16_decl@/typedef unsigned short u_int16_t;/
 /@int32_decl@/d
+s/@u_int32_decl@/typedef unsigned int u_int32_t;/
+s/@int64_decl@//
+s/@u_int64_decl@//
 /@u_char_decl@/d
 /@u_short_decl@/d
 /@u_int_decl@/d
 /@u_long_decl@/d
 /@ssize_t_decl@/d
+s/@uintmax_t_decl@/typedef unsigned long uintmax_t;/
+s/@uintptr_t_decl@/typedef unsigned long uintptr_t;/
+s/@db_seq_decl@/typedef int db_seq_t;/
 s/@DB_VERSION_MAJOR@/$DB_VERSION_MAJOR/
 s/@DB_VERSION_MINOR@/$DB_VERSION_MINOR/
 s/@DB_VERSION_PATCH@/$DB_VERSION_PATCH/
 s/@DB_VERSION_STRING@/"$DB_VERSION_STRING"/
 s/@DB_VERSION_UNIQUE_NAME@//
+s/@DB_CONST@//
+s/@DB_PROTO1@/#undef __P/
+s/@DB_PROTO2@/#define	__P(protos)	protos/
 ENDOFSEDTEXT
 (echo "$msgc" &&
     sed -f $s ../dbinc/db.in &&
-    cat ../dbinc_auto/rpc_defs.in &&
     cat ../dbinc_auto/ext_prot.in) > $t
+`egrep '@.*@' $t` && {
+	echo 'Unexpanded autoconf variables found in VxWorks db.h.'
+	exit 1
+}
+f=../build_vxworks/db.h
 cmp $t $f > /dev/null 2>&1 ||
     (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
 
-f=../build_vxworks/db_int.h
 cat <<ENDOFSEDTEXT > $s
-s/\(PATH_SEPARATOR[^"]*"\)\/"/\1\/\\\\\\\\\\"/
-s/@db_align_t_decl@/typedef unsigned long db_align_t;/
-s/@db_alignp_t_decl@/typedef unsigned long db_alignp_t;/
+s/@PATH_SEPARATOR@/\/\\\\\\\\/
 s/@db_int_def@//
 ENDOFSEDTEXT
 (echo "$msgc" && sed -f $s ../dbinc/db_int.in) > $t
+`egrep '@.*@' $t` && {
+	echo 'Unexpanded autoconf variables found in VxWorks db_int.h.'
+	exit 1
+}
+f=../build_vxworks/db_int.h
 cmp $t $f > /dev/null 2>&1 ||
     (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
 
@@ -66,6 +84,19 @@ f=../build_vxworks/db_config.h
 cmp $t $f > /dev/null 2>&1 ||
     (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
 
+f=../build_vxworks/db_config_small.h
+(echo "$msgc" &&
+    sed -e "s/__EDIT_DB_VERSION__/$DB_VERSION/" \
+	-e "s;^#define.*HAVE_CRYPTO.*1;/* #undef HAVE_CRYPTO */;" \
+	-e "s;^#define.*HAVE_HASH.*1;/* #undef HAVE_HASH */;" \
+	-e "s;^#define.*HAVE_QUEUE.*1;/* #undef HAVE_QUEUE */;" \
+	-e "s;^#define.*HAVE_REPLICATION.*1;/* #undef HAVE_REPLICATION */;" \
+	-e "s;^#define.*HAVE_STATISTICS.*1;/* #undef HAVE_STATISTICS */;" \
+	-e "s;^#define.*HAVE_VERIFY.*1;/* #undef HAVE_VERIFY */;" \
+    vx_config.in) > $t
+cmp $t $f > /dev/null 2>&1 ||
+    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+
 # Build a sed script that will change a "standard" DB utility into
 # VxWorks-compatible code.
 transform()
@@ -164,7 +195,11 @@ for i in $PROGRAM_LIST; do
 	fi
 
 	sed "s/__DB_APPLICATION_NAME__/$target/g" < vx_2.0/wpj.in > $t
-	f=../build_vxworks/$target/$target.wpj
+	f=../build_vxworks/$target/${target}20.wpj
+	cmp $t $f > /dev/null 2>&1 ||
+	    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+	sed "s/__DB_APPLICATION_NAME__/$target/g" < vx_2.2/wpj.in > $t
+	f=../build_vxworks/$target/${target}22.wpj
 	cmp $t $f > /dev/null 2>&1 ||
 	    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
 done
@@ -174,151 +209,86 @@ sed -e '/^$/d' -e '/^[	 #]/d' srcfiles.in |
     egrep -w vx |
     sed 's/[	 ].*//' > $vxfilelist
 
+# Build the list of files VxWorks knows about.
+sed -e '/^$/d' -e '/^[	 #]/d' srcfiles.in |
+    egrep -w vxsmall |
+    sed 's/[	 ].*//' > $vxsmallfiles
+
 # Build VxWorks Tornado 2.0 project files for the library itself.
-(cat vx_2.0/BerkeleyDB.wpj
-for i in `cat $vxfilelist`; do
-	o="<BEGIN> FILE_\$(PRJ_DIR)/../$i"
-	echo "${o}_dependDone"
-	echo "TRUE"
-	echo "<END>"
-	echo
-	echo "${o}_dependencies"
-	echo "\$(PRJ_DIR)/db_config.h \\"
-	echo "	\$(PRJ_DIR)/db_int.h \\"
-	echo "	\$(PRJ_DIR)/db.h"
-	echo "<END>"
-	echo
-	echo "${o}_objects"
-	echo "`basename $i .c`.o"
+for v in 0 2 ; do
+	#
+	# Build regular project files
+	#
+	(cat vx_2.${v}/BerkeleyDB.wpj
+	for i in `cat $vxfilelist`; do
+		o="<BEGIN> FILE_\$(PRJ_DIR)/../$i"
+		echo "${o}_dependDone"
+		echo "TRUE"
+		echo "<END>"
+		echo
+		echo "${o}_dependencies"
+		echo "\$(PRJ_DIR)/db_config.h \\"
+		echo "	\$(PRJ_DIR)/db_int.h \\"
+		echo "	\$(PRJ_DIR)/db.h"
+		echo "<END>"
+		echo
+		echo "${o}_objects"
+		echo "`basename $i .c`.o"
+		echo "<END>"
+		echo
+		echo "${o}_tool"
+		echo "C/C++ compiler"
+		echo "<END>"
+		echo
+	done
+	echo "<BEGIN> PROJECT_FILES"
+	sed -e '$!s/$/ \\/' \
+	    -e 's/^/$(PRJ_DIR)\/..\//' \
+	    -e '1!s/^/	/' < $vxfilelist
 	echo "<END>"
 	echo
-	echo "${o}_tool"
-	echo "C/C++ compiler"
+	echo "<BEGIN> userComments"
+	echo "BerkeleyDB"
+	echo "<END>") > $t
+	#
+	# Build small lib project files
+	#
+	(cat vx_2.${v}/BerkeleyDBsmall.wpj
+	for i in `cat $vxsmallfiles`; do
+		o="<BEGIN> FILE_\$(PRJ_DIR)/../$i"
+		echo "${o}_dependDone"
+		echo "TRUE"
+		echo "<END>"
+		echo
+		echo "${o}_dependencies"
+		echo "\$(PRJ_DIR)/db_config.h \\"
+		echo "	\$(PRJ_DIR)/db_int.h \\"
+		echo "	\$(PRJ_DIR)/db.h"
+		echo "<END>"
+		echo
+		echo "${o}_objects"
+		echo "`basename $i .c`.o"
+		echo "<END>"
+		echo
+		echo "${o}_tool"
+		echo "C/C++ compiler"
+		echo "<END>"
+		echo
+	done
+	echo "<BEGIN> PROJECT_FILES"
+	sed -e '$!s/$/ \\/' \
+	    -e 's/^/$(PRJ_DIR)\/..\//' \
+	    -e '1!s/^/	/' < $vxsmallfiles
 	echo "<END>"
 	echo
-done
-echo "<BEGIN> PROJECT_FILES"
-sed -e '$!s/$/ \\/' \
-    -e 's/^/$(PRJ_DIR)\/..\//' \
-    -e '1!s/^/	/' < $vxfilelist
-echo "<END>"
-echo
-echo "<BEGIN> userComments"
-echo "BerkeleyDB"
-echo "<END>") > $t
-f=../build_vxworks/BerkeleyDB.wpj
-cmp $t $f > /dev/null 2>&1 ||
-    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
-
-# Build VxWorks Tornado 3.1 project files for the utilities.
-for i in $PROGRAM_LIST; do
-	if [ $i = "ex_access" ]; then
-		target=dbdemo
-		dir=../examples_c
-	else
-		target=$i
-		dir=../$i
-	fi
-
-	cp vx_3.1/Makefile.custom $t
-	f=../build_vxworks/$target/$target/Makefile.custom
+	echo "<BEGIN> userComments"
+	echo "BerkeleyDB"
+	echo "<END>") > $u
+	f=../build_vxworks/BerkeleyDB2${v}.wpj
 	cmp $t $f > /dev/null 2>&1 ||
 	    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
-
-	for j in component.cdf component.wpj; do
-		#
-		# Some parts of the component files needs to have the
-		# name in all capitals.  Sigh.
-		#
-		z=`echo $target | tr "a-z" "A-Z"`
-		sed -e "s/__DB_APPLICATION_NAME__/$target/g" \
-		    -e "s/__DB_CAPAPPL_NAME__/$z/g" < vx_3.1/$j > $t
-		f=../build_vxworks/$target/$target/$j
-		cmp $t $f > /dev/null 2>&1 ||
-		    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
-	done
-done
-
-# Build VxWorks Tornado 3.1 project files for the library itself.
-cp vx_3.1/Makefile.custom $t
-f=../build_vxworks/BerkeleyDB/Makefile.custom
-cmp $t $f > /dev/null 2>&1 ||
-    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
-
-(cat vx_3.1/cdf.1
-echo -n "	MODULES"
-for i in `cat $vxfilelist`; do
-	echo "			`basename $i .c`.o"
-done | sort | sed -e '$!s/$/ \\/'
-cat vx_3.1/cdf.2
-for i in `cat $vxfilelist`; do
-	b="`basename $i .c`.o"
-	echo "Module $b {"
-	echo
-	echo "	NAME		$b"
-	echo "	SRC_PATH_NAME	\$(PRJ_DIR)/../../$i"
-	echo "}"
-	echo
+	f=../build_vxworks/BerkeleyDB2${v}small.wpj
+	cmp $u $f > /dev/null 2>&1 ||
+	    (echo "Building $f" && rm -f $f && cp $u $f && chmod 444 $f)
 done
-cat vx_3.1/cdf.3)> $t
-f=../build_vxworks/BerkeleyDB/component.cdf
-cmp $t $f > /dev/null 2>&1 ||
-    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
 
-(cat vx_3.1/wpj.1
-for i in `cat $vxfilelist`; do
-	o="<BEGIN> BUILD_PENTIUM2gnu.debug_FILE_\$(PRJ_DIR)/../../$i"
-	echo "${o}_infoTags"
-	echo "toolMacro objects"
-	echo "<END>"
-	echo
-	echo "${o}_objects"
-	echo "`basename $i .c`.o"
-	echo "<END>"
-	echo
-	echo "${o}_toolMacro"
-	echo "CC"
-	echo "<END>"
-	echo
-done
-cat vx_3.1/wpj.2
-for i in `cat $vxfilelist`; do
-	o="<BEGIN> BUILD_PENTIUM2gnu.release_FILE_\$(PRJ_DIR)/../../$i"
-	echo "${o}_infoTags"
-	echo "toolMacro objects"
-	echo "<END>"
-	echo
-	echo "${o}_objects"
-	echo "`basename $i .c`.o"
-	echo "<END>"
-	echo
-	echo "${o}_toolMacro"
-	echo "CC"
-	echo "<END>"
-	echo
-done
-cat vx_3.1/wpj.3
-for i in `cat $vxfilelist`; do
-	o="<BEGIN> BUILD_PENTIUMgnu.debug_FILE_\$(PRJ_DIR)/../../$i"
-	echo "${o}_infoTags"
-	echo "toolMacro objects"
-	echo "<END>"
-	echo
-	echo "${o}_objects"
-	echo "`basename $i .c`.o"
-	echo "<END>"
-	echo
-	echo "${o}_toolMacro"
-	echo "CC"
-	echo "<END>"
-	echo
-done
-cat vx_3.1/wpj.4
-sort $vxfilelist |
-sed -e 's/^/$(PRJ_DIR)\/..\/..\//' \
-    -e '1!s/^/	/' \
-    -e '$!s/$/ \\/'
-cat vx_3.1/wpj.5) > $t
-f=../build_vxworks/BerkeleyDB/component.wpj
-cmp $t $f > /dev/null 2>&1 ||
-    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
diff --git a/storage/bdb/dist/s_win32 b/storage/bdb/dist/s_win32
index 207978b82bb74c28ed486b40b1b4b0d02113a9b1..acdb9224918d1d80dffb6d2b0d6551bdca1ac4e1 100755
--- a/storage/bdb/dist/s_win32
+++ b/storage/bdb/dist/s_win32
@@ -1,12 +1,12 @@
 #!/bin/sh -
-#	$Id: s_win32,v 1.25 2002/05/20 19:18:14 bostic Exp $
+#	$Id: s_win32,v 1.37 2004/10/15 18:28:21 bostic Exp $
 #
 # Build Windows/32 include files.
 
 msgc="/* DO NOT EDIT: automatically built by dist/s_win32. */"
 msgw="; DO NOT EDIT: automatically built by dist/s_win32."
 
-. ./RELEASE
+. RELEASE
 
 s=/tmp/__db_a$$
 t=/tmp/__db_b$$
@@ -15,16 +15,21 @@ rm -f $s $t
 trap 'rm -f $s $t ; exit 1' 1 2 3 13 15
 
 # Build the Win32 automatically generated files.
-f=../build_win32/db.h
 cat <<ENDOFSEDTEXT > $s
+/@inttypes_h_decl@/d
+/@stdint_h_decl@/d
+s/@stddef_h_decl@/#include <stddef.h>/
 s/@u_int8_decl@/typedef unsigned char u_int8_t;/
 s/@int16_decl@/typedef short int16_t;/
 s/@u_int16_decl@/typedef unsigned short u_int16_t;/
 s/@int32_decl@/typedef int int32_t;/
 s/@u_int32_decl@/typedef unsigned int u_int32_t;/
+s/@int64_decl@/typedef __int64 int64_t;/
+s/@u_int64_decl@/typedef unsigned __int64 u_int64_t;/
+s/@db_seq_decl@/typedef int64_t db_seq_t;/
 /@u_char_decl@/{
 	i\\
-#if !defined(_WINSOCKAPI_)
+#ifndef _WINSOCKAPI_
 	s/@u_char_decl@/typedef unsigned char u_char;/
 }
 s/@u_short_decl@/typedef unsigned short u_short;/
@@ -36,10 +41,20 @@ s/@u_int_decl@/typedef unsigned int u_int;/
 }
 /@ssize_t_decl@/{
 	i\\
-#if defined(_WIN64)\\
-typedef __int64 ssize_t;\\
+#ifdef _WIN64\\
+typedef int64_t ssize_t;\\
+#else\\
+typedef int32_t ssize_t;\\
+#endif
+	d
+}
+s/@uintmax_t_decl@/typedef u_int64_t uintmax_t;/
+/@uintptr_t_decl@/{
+	i\\
+#ifdef _WIN64\\
+typedef u_int64_t uintptr_t;\\
 #else\\
-typedef int ssize_t;\\
+typedef u_int32_t uintptr_t;\\
 #endif
 	d
 }
@@ -48,35 +63,60 @@ s/@DB_VERSION_MINOR@/$DB_VERSION_MINOR/
 s/@DB_VERSION_PATCH@/$DB_VERSION_PATCH/
 s/@DB_VERSION_STRING@/"$DB_VERSION_STRING"/
 s/@DB_VERSION_UNIQUE_NAME@//
+s/@DB_CONST@//
+s/@DB_PROTO1@/#undef __P/
+s/@DB_PROTO2@/#define	__P(protos)	protos/
 ENDOFSEDTEXT
 (echo "$msgc" &&
     sed -f $s ../dbinc/db.in &&
-    cat ../dbinc_auto/rpc_defs.in &&
     cat ../dbinc_auto/ext_prot.in) > $t
+`egrep '@.*@' $t` && {
+	echo 'Unexpanded autoconf variables found in Windows db.h.'
+	exit 1
+}
+f=../build_win32/db.h
+cmp $t $f > /dev/null 2>&1 ||
+    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+f=../build_win64/db.h
 cmp $t $f > /dev/null 2>&1 ||
     (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
 
-f=../build_win32/db_cxx.h
 cat <<ENDOFSEDTEXT > $s
 s/@cxx_have_stdheaders@/#define	HAVE_CXX_STDHEADERS 1/
 ENDOFSEDTEXT
 (echo "$msgc" && sed -f $s ../dbinc/db_cxx.in) > $t
+`egrep '@.*@' $t` && {
+	echo 'Unexpanded autoconf variables found in Windows db_cxx.h.'
+	exit 1
+}
+f=../build_win32/db_cxx.h
+cmp $t $f > /dev/null 2>&1 ||
+    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+f=../build_win64/db_cxx.h
 cmp $t $f > /dev/null 2>&1 ||
     (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
 
-f=../build_win32/db_int.h
 cat <<ENDOFSEDTEXT > $s
-s/\(PATH_SEPARATOR[^"]*"\)\/"/\1\\\\\\\\\\/:\"/
-s/@db_align_t_decl@/typedef unsigned long db_align_t;/
-s/@db_alignp_t_decl@/typedef unsigned long db_alignp_t;/
+s/@PATH_SEPARATOR@/\\\\\\\\\/:/
 s/@db_int_def@//
 ENDOFSEDTEXT
 (echo "$msgc" && sed -f $s ../dbinc/db_int.in) > $t
+`egrep '@.*@' $t` && {
+	echo 'Unexpanded autoconf variables found in Windows db_int.h.'
+	exit 1
+}
+f=../build_win32/db_int.h
+cmp $t $f > /dev/null 2>&1 ||
+    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+f=../build_win64/db_int.h
 cmp $t $f > /dev/null 2>&1 ||
     (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
 
 f=../build_win32/db_config.h
 (echo "$msgc" && sed "s/__EDIT_DB_VERSION__/$DB_VERSION/" win_config.in) > $t
+cmp $t $f > /dev/null 2>&1 ||
+    (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
+f=../build_win64/db_config.h
 cmp $t $f > /dev/null 2>&1 ||
     (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
 
@@ -92,9 +132,6 @@ cmp $t $f > /dev/null 2>&1 ||
 
 f=../build_win32/libdb.def
 (echo $msgw &&
- echo &&
- echo \
- "DESCRIPTION	'Berkeley DB $DB_VERSION_MAJOR.$DB_VERSION_MINOR Library'" &&
  echo &&
  echo EXPORTS;
 a=1
@@ -105,4 +142,12 @@ done) > $t
 cmp $t $f > /dev/null 2>&1 ||
     (echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
 
+f=../build_win32/win_db.h
+i=win_db.in
+cmp $i $f > /dev/null 2>&1 ||
+    (echo "Building $f" && rm -f $f && cp $i $f && chmod 444 $f)
+f=../build_win64/win_db.h
+cmp $i $f > /dev/null 2>&1 ||
+    (echo "Building $f" && rm -f $f && cp $i $f && chmod 444 $f)
+
 rm -f $s $t
diff --git a/storage/bdb/dist/s_win32_dsp b/storage/bdb/dist/s_win32_dsp
index af5551ec248c46e1d9031a7b5492c3cdf1f6d85e..10e0ccc4b0532670ba0a6f36c5381b65342aca79 100644
--- a/storage/bdb/dist/s_win32_dsp
+++ b/storage/bdb/dist/s_win32_dsp
@@ -1,11 +1,10 @@
 #!/bin/sh -
-#	$Id: s_win32_dsp,v 1.8 2002/03/26 23:37:55 bostic Exp $
+#	$Id: s_win32_dsp,v 1.12 2004/08/20 15:01:06 mjc Exp $
 #
 # Build Windows/32 .dsp files.
 
-. ./RELEASE
+. RELEASE
 
-BUILDDIR=../build_win32
 SRCFILES=srcfiles.in
 
 create_dsp()
@@ -27,7 +26,7 @@ create_dsp()
         # forward slash, but we need that when feeding that to the
         # later sed command.
         set - `echo $srcpath | sed -e 's;\(.*\)/;../\\1 ;' \
-            -e 's;../build_win32;.;' \
+            -e "s;$BUILDDIR;.;" \
             -e 's;/;\\\\\\\\;g'`
 	srcdir="$1"
 	srcfile="$2"
@@ -35,9 +34,7 @@ create_dsp()
             -e "s/@srcfile@/$srcfile/g" \
             < $srctemplate >> $dspoutput.insert
     done
-    # We need exactly one space after the 'r' modifier
-    # See 5.9 in http://www.student.northpark.edu/pemente/sed/sedfaq.txt
-    sed -e "/@SOURCE_FILES@/r $dspoutput.insert" \
+    sed -e "/@SOURCE_FILES@/r$dspoutput.insert" \
         -e "/@SOURCE_FILES@/d" \
         -e "s/@project_name@/$projname/g" \
         -e "s/@DB_VERSION_MAJOR@/$DB_VERSION_MAJOR/g" \
@@ -70,40 +67,52 @@ sed -e "s/#.*$//" \
 MODULES="`sed -e 's/^[^ ]* //' < $TMPA \
     | tr ' ' '\012' | sort | uniq`"
 
-for module in $MODULES
+for BUILDDIR in ../build_win32 ../build_win64
 do
-    case "$module" in
-    dynamic )
-        create_dsp db_dll " $module " $TMPA \
-		$BUILDDIR/dynamic_dsp.src $BUILDDIR/srcfile_dsp.src
-        ;;
-    java )
-        create_dsp db_java " $module " $TMPA \
-		$BUILDDIR/java_dsp.src $BUILDDIR/srcfile_dsp.src
-        ;;
-    tcl )
-        create_dsp db_tcl " $module " $TMPA \
-		$BUILDDIR/tcl_dsp.src $BUILDDIR/srcfile_dsp.src
-        ;;
-    testutil )
-        create_dsp db_test " $module " $TMPA \
-		$BUILDDIR/db_test.src $BUILDDIR/srcfile_dsp.src
-        ;;
-    static )
-        create_dsp db_static " $module " $TMPA \
-		$BUILDDIR/static_dsp.src $BUILDDIR/srcfile_dsp.src
-        ;;
-    app=* )
-	appname=`echo $module | sed -e 's/^app=//'`
-        create_dsp $appname " $module " $TMPA \
-		$BUILDDIR/app_dsp.src $BUILDDIR/srcfile_dsp.src
-        ;;
-    vx )
-	;;
-    * )
-        echo "s_win32_dsp: module name $module in $SRCFILES is unknown type"
-        ;;
-    esac
+    for module in $MODULES
+    do
+        case "$module" in
+        dynamic )
+            create_dsp db_dll " $module " $TMPA \
+                    $BUILDDIR/dynamic_dsp.src $BUILDDIR/srcfile_dsp.src
+            ;;
+        small )
+            create_dsp db_small " $module " $TMPA \
+                    $BUILDDIR/small_dsp.src $BUILDDIR/srcfile_dsp.src
+            ;;
+        static )
+            create_dsp db_static " $module " $TMPA \
+                    $BUILDDIR/static_dsp.src $BUILDDIR/srcfile_dsp.src
+            ;;
+        java )
+            create_dsp db_java " $module " $TMPA \
+                    $BUILDDIR/java_dsp.src $BUILDDIR/srcfile_dsp.src
+            ;;
+        tcl )
+            create_dsp db_tcl " $module " $TMPA \
+                    $BUILDDIR/tcl_dsp.src $BUILDDIR/srcfile_dsp.src
+            ;;
+        testutil )
+            create_dsp db_test " $module " $TMPA \
+                    $BUILDDIR/db_test.src $BUILDDIR/srcfile_dsp.src
+            ;;
+        app=* )
+            appname=`echo $module | sed -e 's/^app=//'`
+            if [ -f $BUILDDIR/$appname.src ] ; then
+                    srcname=$BUILDDIR/$appname.src
+            else
+                    srcname=$BUILDDIR/app_dsp.src
+            fi
+            create_dsp $appname " $module " $TMPA \
+                    $srcname $BUILDDIR/srcfile_dsp.src
+            ;;
+        vx|vxsmall )
+            ;;
+        * )
+            echo "s_win32_dsp: module name $module in $SRCFILES is unknown type"
+            ;;
+        esac
+    done
 done
 
 rm -f $TMPA
diff --git a/storage/bdb/dist/s_winmsi b/storage/bdb/dist/s_winmsi
new file mode 100644
index 0000000000000000000000000000000000000000..d7dc42770cf643bb755aaa7d705167d2e72ad22b
--- /dev/null
+++ b/storage/bdb/dist/s_winmsi
@@ -0,0 +1,126 @@
+#!/bin/bash -
+#	$Id: s_winmsi,v 1.6 2005/04/15 18:48:57 philipr Exp $
+#
+# Note: The s_winmsi script in Berkeley DB core closely parallels the
+# s_winmsi script in Berkeley DB/XML.  If you change one,
+# consider whether your changes apply to the other.
+# As of this writing, the two s_winmsi scripts 'diff' very closely, and
+# identical portions have been factored into functions in s_winmsi.fcn.
+#
+#   Usage: s_winmsi [ options ]
+#
+# See the Usage() function in s_winmsi.fcn for a full list of options.
+# By default, this script expects a db-X.Y.Z.NC.zip file
+# to be in this directory, and uses it to build all binaries
+# needed for an Windows install, and finally builds the an
+# output db-X.Y.Z.NC.msi file that can be installed on
+# Windows XP and 2000.
+#
+# The major other inputs to this script are these files:
+#
+#   features.in        list of choosable features (like Java,PHP,...)
+#   files.in           what files are in each feature and where they belong
+#   links.in           a list of URLs that end up as part of the Start Menu
+#   environment.in     a list of environment vars that must be set
+#
+# This script does a number of operations, using the directory
+# './winmsi/stage' as a staging area:
+#
+#   extracts the contents of the input ZIP file and uses those
+#   files (minus docs/...) to build a Sources directory for
+#   the Sources features.
+#
+#   builds Berkeley DB using Visual Studio tools using a .BAT
+#   script derived from winbuild.in .
+#
+#   builds Perl and other APIs .
+#
+#   uses {features,files,links,environment}.in to build some include
+#   files in WiX XML format.  These files are named
+#   *.wixinc (e.g. directory.wixinc)
+#
+#   run m4 on dbcorewix.in to create dbcore.wxs .  dbcorewix.in
+#   uses m4 macros to allow reasonable refactoring of repeated
+#   UI code.  Also, m4 is used to include the files created in
+#   the previous step.
+#
+#   Use the WiX compiler/linker on the .wxs files to create the .msi file.
+#
+################################################################
+
+# Define all needed shell functions
+. ./winmsi/s_winmsi.fcn
+
+ERRORLOG="$0".log
+SetupErrorLog
+
+# Do this before parsing options, we need the version number
+. ./RELEASE
+dbver=db-$DB_VERSION.NC
+
+# Set variables used by functions to customize this installer
+PRODUCT_NAME="Berkeley DB"
+PRODUCT_VERSION="$DB_VERSION"
+PRODUCT_STAGE=`pwd`/winmsi/stage
+PRODUCT_LICENSEDIR="${PRODUCT_STAGE}/$dbver"
+PRODUCT_SUB_BLDDIR="${PRODUCT_STAGE}/$dbver"
+PRODUCT_BLDDIR="${PRODUCT_STAGE}/$dbver"
+PRODUCT_SRCDIR="${PRODUCT_STAGE}/$dbver"
+PRODUCT_DBBUILDDIR="${PRODUCT_STAGE}/$dbver/build_unix"
+PRODUCT_SHARED_WINMSIDIR=`pwd`/winmsi
+PRODUCT_IMAGEDIR=$PRODUCT_SHARED_WINMSIDIR/images
+PRODUCT_ZIP_FILEFMT="db-X.Y.Z.NC.zip"
+PRODUCT_MSI_FILEFMT="db-X.Y.Z.NC.msi"
+
+# Gather command line options, and use reasonable defaults
+SetupOptions \
+        -input "$dbver.zip" \
+        -output "$dbver.msi" \
+        "$@"
+
+if [ "$OPT_USEBUILD" != '' ]; then
+    PRODUCT_BLDDIR="${OPT_USEBUILD}"
+    PRODUCT_SUB_BLDDIR="${OPT_USEBUILD}"
+fi
+
+Progress "s_winmsi starting, errors to $ERRORLOG"
+
+# Fail fast for certain missing files
+
+RequireCygwin
+RequireJava
+RequireTcl
+RequireWix
+RequirePerl
+
+CreateStage
+cd ${PRODUCT_STAGE}
+
+
+CreateSources ${PRODUCT_STAGE}/Sources
+
+# The docs are put into a separate feature set
+mv ${PRODUCT_STAGE}/Sources/docs ${PRODUCT_STAGE}/
+
+# Build everything unless we were told to use a preexisting build
+if [ "$OPT_USEBUILD" = '' ]; then
+    CreateWindowsBuild
+    CreateWindowsSystem
+    CreateInclude \
+        ${PRODUCT_SUB_BLDDIR}/installed_include \
+        ${PRODUCT_SUB_BLDDIR}/dbinc/* \
+        ${PRODUCT_SUB_BLDDIR}/dbinc_auto/* \
+        ${PRODUCT_SUB_BLDDIR}/build_win32/*.h
+    CreateDbPerl
+fi
+
+if ! "$OPT_SKIPGEN" ; then
+  CreateLicenseRtf ../../../LICENSE license.rtf
+  CreateWixIncludeFiles
+fi
+
+CreateMsi ../dbcorewix.in dbcore.wxs "$OPT_OUTFILE"
+
+Progress "s_winmsi finished, $OPT_OUTFILE created."
+exit 0
+
diff --git a/storage/bdb/dist/srcfiles.in b/storage/bdb/dist/srcfiles.in
index 54aeea0c1bceecf3d1abeb156aade37d7809f999..b00be5a10f06b2e4a28d6de444aa5f95cc1e3950 100644
--- a/storage/bdb/dist/srcfiles.in
+++ b/storage/bdb/dist/srcfiles.in
@@ -1,4 +1,4 @@
-#	$Id: srcfiles.in,v 1.59 2002/08/29 14:22:21 margo Exp $
+#	$Id: srcfiles.in,v 1.87 2004/10/30 21:07:01 bostic Exp $
 #
 # This is an input file for the s_win32_dsp and s_vxworks scripts.  It lists
 # the source files in the Berkeley DB tree and notes which are used to build
@@ -13,30 +13,33 @@
 #
 #   app=NAME		Linked into application NAME.exe (db_NAME.dsp)
 #   dynamic		File is in the Windows DLL (db_dll.dsp)
-#   java		File is in the Windows Java DLL (db_java.dsp)
+#   small		File is in the small Windows library (db_small.dsp)
 #   static		File is in the Windows static library (db_static.dsp)
+#   java		File is in the Windows Java DLL (db_java.dsp)
 #   tcl			File is in the Windows tcl DLL (db_tcl.dsp)
 #   testutil		File is used for Windows testing (db_test.dsp)
 #   vx			File is in the VxWorks library.
+#   vxsmall		File is in the small VxWorks library.
 
-btree/bt_compare.c				dynamic static vx
-btree/bt_conv.c					dynamic static vx
-btree/bt_curadj.c				dynamic static vx
-btree/bt_cursor.c				dynamic static vx
-btree/bt_delete.c				dynamic static vx
-btree/bt_method.c				dynamic static vx
-btree/bt_open.c					dynamic static vx
-btree/bt_put.c					dynamic static vx
-btree/bt_rec.c					dynamic static vx
-btree/bt_reclaim.c				dynamic static vx
-btree/bt_recno.c				dynamic static vx
-btree/bt_rsearch.c				dynamic static vx
-btree/bt_search.c				dynamic static vx
-btree/bt_split.c				dynamic static vx
-btree/bt_stat.c					dynamic static vx
-btree/bt_upgrade.c				dynamic static vx
+btree/bt_compare.c				dynamic small static vx vxsmall
+btree/bt_conv.c					dynamic small static vx vxsmall
+btree/bt_curadj.c				dynamic small static vx vxsmall
+btree/bt_cursor.c				dynamic small static vx vxsmall
+btree/bt_delete.c				dynamic small static vx vxsmall
+btree/bt_method.c				dynamic small static vx vxsmall
+btree/bt_open.c					dynamic small static vx vxsmall
+btree/bt_put.c					dynamic small static vx vxsmall
+btree/bt_rec.c					dynamic small static vx vxsmall
+btree/bt_reclaim.c				dynamic small static vx vxsmall
+btree/bt_recno.c				dynamic small static vx vxsmall
+btree/bt_rsearch.c				dynamic small static vx vxsmall
+btree/bt_search.c				dynamic small static vx vxsmall
+btree/bt_split.c				dynamic small static vx vxsmall
+btree/bt_stat.c					dynamic small static vx vxsmall
+btree/bt_upgrade.c				dynamic small static vx vxsmall
 btree/bt_verify.c				dynamic static vx
-btree/btree_auto.c				dynamic static vx
+btree/btree_auto.c				dynamic small static vx vxsmall
+btree/btree_autop.c				app=db_printlog
 build_vxworks/db_archive/db_archive.c
 build_vxworks/db_checkpoint/db_checkpoint.c
 build_vxworks/db_deadlock/db_deadlock.c
@@ -49,63 +52,78 @@ build_vxworks/db_upgrade/db_upgrade.c
 build_vxworks/db_verify/db_verify.c
 build_vxworks/dbdemo/dbdemo.c
 build_win32/dbkill.cpp				testutil
-build_win32/dllmain.c				dynamic
 build_win32/libdb.def				dynamic
 build_win32/libdb.rc				dynamic
 build_win32/libdb_tcl.def			tcl
 clib/getcwd.c
-clib/getopt.c					vx
+clib/getopt.c					vx vxsmall
 clib/memcmp.c
 clib/memmove.c
 clib/raise.c
-clib/snprintf.c					vx
-clib/strcasecmp.c				dynamic static vx
-clib/strdup.c					vx
+clib/snprintf.c					vx vxsmall
+clib/strcasecmp.c				dynamic small static vx vxsmall
+clib/strdup.c					vx vxsmall
 clib/strerror.c
-clib/vsnprintf.c				vx
-common/db_byteorder.c				dynamic static vx
-common/db_err.c					dynamic static vx
-common/db_getlong.c				dynamic static vx
-common/db_idspace.c				dynamic static vx
-common/db_log2.c				dynamic static vx
-common/util_arg.c				vx
-common/util_cache.c				dynamic static vx
-common/util_log.c				dynamic static vx
-common/util_sig.c				dynamic static vx
-cxx/cxx_db.cpp					dynamic static
-cxx/cxx_dbc.cpp					dynamic static
-cxx/cxx_dbt.cpp					dynamic static
-cxx/cxx_env.cpp					dynamic static
-cxx/cxx_except.cpp				dynamic static
-cxx/cxx_lock.cpp				dynamic static
-cxx/cxx_logc.cpp				dynamic static
-cxx/cxx_mpool.cpp				dynamic static
-cxx/cxx_txn.cpp					dynamic static
-db/crdel_auto.c					dynamic static vx
-db/crdel_rec.c					dynamic static vx
-db/db.c						dynamic static vx
-db/db_am.c					dynamic static vx
-db/db_auto.c					dynamic static vx
-db/db_cam.c					dynamic static vx
-db/db_conv.c					dynamic static vx
-db/db_dispatch.c				dynamic static vx
-db/db_dup.c					dynamic static vx
-db/db_iface.c					dynamic static vx
-db/db_join.c					dynamic static vx
-db/db_meta.c					dynamic static vx
-db/db_method.c					dynamic static vx
-db/db_open.c					dynamic static vx
-db/db_overflow.c				dynamic static vx
-db/db_pr.c					dynamic static vx
-db/db_rec.c					dynamic static vx
-db/db_reclaim.c					dynamic static vx
-db/db_remove.c					dynamic static vx
-db/db_rename.c					dynamic static vx
-db/db_ret.c					dynamic static vx
-db/db_truncate.c				dynamic static vx
-db/db_upg.c					dynamic static vx
-db/db_upg_opd.c					dynamic static vx
+clib/strtol.c
+clib/strtoul.c
+common/crypto_stub.c				small vxsmall
+common/db_byteorder.c				dynamic small static vx vxsmall
+common/db_err.c					dynamic small static vx vxsmall
+common/db_getlong.c				dynamic small static vx vxsmall
+common/db_idspace.c				dynamic small static vx vxsmall
+common/db_log2.c				dynamic small static vx vxsmall
+common/util_arg.c				vx vxsmall
+common/util_cache.c				dynamic small static vx vxsmall
+common/util_log.c				dynamic small static vx vxsmall
+common/util_sig.c				dynamic small static vx vxsmall
+crypto/aes_method.c				dynamic static vx
+crypto/crypto.c					dynamic static vx
+crypto/mersenne/mt19937db.c			dynamic static vx
+crypto/rijndael/rijndael-alg-fst.c		dynamic static vx
+crypto/rijndael/rijndael-api-fst.c		dynamic static vx
+cxx/cxx_db.cpp					dynamic small static
+cxx/cxx_dbc.cpp					dynamic small static
+cxx/cxx_dbt.cpp					dynamic small static
+cxx/cxx_env.cpp					dynamic small static
+cxx/cxx_except.cpp				dynamic small static
+cxx/cxx_lock.cpp				dynamic small static
+cxx/cxx_logc.cpp				dynamic small static
+cxx/cxx_mpool.cpp				dynamic small static
+cxx/cxx_multi.cpp				dynamic small static
+cxx/cxx_seq.cpp					dynamic small static
+cxx/cxx_txn.cpp					dynamic small static
+db/crdel_auto.c					dynamic small static vx vxsmall
+db/crdel_autop.c				app=db_printlog
+db/crdel_rec.c					dynamic small static vx vxsmall
+db/db.c						dynamic small static vx vxsmall
+db/db_am.c					dynamic small static vx vxsmall
+db/db_auto.c					dynamic small static vx vxsmall
+db/db_autop.c					app=db_printlog
+db/db_cam.c					dynamic small static vx vxsmall
+db/db_conv.c					dynamic small static vx vxsmall
+db/db_dispatch.c				dynamic small static vx vxsmall
+db/db_dup.c					dynamic small static vx vxsmall
+db/db_iface.c					dynamic small static vx vxsmall
+db/db_join.c					dynamic small static vx vxsmall
+db/db_meta.c					dynamic small static vx vxsmall
+db/db_method.c					dynamic small static vx vxsmall
+db/db_open.c					dynamic small static vx vxsmall
+db/db_overflow.c				dynamic small static vx vxsmall
+db/db_ovfl_vrfy.c				dynamic static vx
+db/db_pr.c					dynamic small static vx vxsmall
+db/db_rec.c					dynamic small static vx vxsmall
+db/db_reclaim.c					dynamic small static vx vxsmall
+db/db_remove.c					dynamic small static vx vxsmall
+db/db_rename.c					dynamic small static vx vxsmall
+db/db_ret.c					dynamic small static vx vxsmall
+db/db_setid.c					dynamic small static vx vxsmall
+db/db_setlsn.c					dynamic small static vx vxsmall
+db/db_stati.c					dynamic small static vx vxsmall
+db/db_truncate.c				dynamic small static vx vxsmall
+db/db_upg.c					dynamic small static vx vxsmall
+db/db_upg_opd.c					dynamic small static vx vxsmall
 db/db_vrfy.c					dynamic static vx
+db/db_vrfy_stub.c				small vxsmall
 db/db_vrfyutil.c				dynamic static vx
 db185/db185.c
 db_archive/db_archive.c				app=db_archive
@@ -116,53 +134,71 @@ db_dump185/db_dump185.c
 db_load/db_load.c				app=db_load
 db_printlog/db_printlog.c			app=db_printlog
 db_recover/db_recover.c				app=db_recover
+db_server_clnt.c
+db_server_svc.c
+db_server_xdr.c
 db_stat/db_stat.c				app=db_stat
 db_upgrade/db_upgrade.c				app=db_upgrade
 db_verify/db_verify.c				app=db_verify
 dbm/dbm.c					dynamic static
-dbreg/dbreg.c					dynamic static vx
-dbreg/dbreg_auto.c				dynamic static vx
-dbreg/dbreg_rec.c				dynamic static vx
-dbreg/dbreg_util.c				dynamic static vx
-env/db_salloc.c					dynamic static vx
-env/db_shash.c					dynamic static vx
-env/env_file.c					dynamic static vx
-env/env_method.c				dynamic static vx
-env/env_open.c					dynamic static vx
-env/env_recover.c				dynamic static vx
-env/env_region.c				dynamic static vx
+dbreg/dbreg.c					dynamic small static vx vxsmall
+dbreg/dbreg_auto.c				dynamic small static vx vxsmall
+dbreg/dbreg_autop.c				app=db_printlog
+dbreg/dbreg_rec.c				dynamic small static vx vxsmall
+dbreg/dbreg_stat.c				dynamic small static vx vxsmall
+dbreg/dbreg_util.c				dynamic small static vx vxsmall
+env/db_salloc.c					dynamic small static vx vxsmall
+env/db_shash.c					dynamic small static vx vxsmall
+env/env_file.c					dynamic small static vx vxsmall
+env/env_method.c				dynamic small static vx vxsmall
+env/env_open.c					dynamic small static vx vxsmall
+env/env_recover.c				dynamic small static vx vxsmall
+env/env_region.c				dynamic small static vx vxsmall
+env/env_stat.c					dynamic small static vx vxsmall
 examples_c/bench_001.c
 examples_c/ex_access.c				app=ex_access
 examples_c/ex_apprec/ex_apprec.c
 examples_c/ex_apprec/ex_apprec_auto.c
+examples_c/ex_apprec/ex_apprec_autop.c
 examples_c/ex_apprec/ex_apprec_rec.c
 examples_c/ex_btrec.c				app=ex_btrec
 examples_c/ex_dbclient.c
 examples_c/ex_env.c				app=ex_env
 examples_c/ex_lock.c				app=ex_lock
 examples_c/ex_mpool.c				app=ex_mpool
-examples_c/ex_repquote/ex_rq_client.c
-examples_c/ex_repquote/ex_rq_main.c
-examples_c/ex_repquote/ex_rq_master.c
-examples_c/ex_repquote/ex_rq_net.c
-examples_c/ex_repquote/ex_rq_util.c
+examples_c/ex_repquote/ex_rq_client.c		app=ex_repquote
+examples_c/ex_repquote/ex_rq_main.c		app=ex_repquote
+examples_c/ex_repquote/ex_rq_master.c		app=ex_repquote
+examples_c/ex_repquote/ex_rq_net.c		app=ex_repquote
+examples_c/ex_repquote/ex_rq_util.c		app=ex_repquote
+examples_c/ex_sequence.c
 examples_c/ex_thread.c
 examples_c/ex_tpcb.c				app=ex_tpcb
+examples_c/getting_started/example_database_load.c
+examples_c/getting_started/example_database_read.c
+examples_c/getting_started/gettingstarted_common.c
 examples_cxx/AccessExample.cpp			app=excxx_access
 examples_cxx/BtRecExample.cpp			app=excxx_btrec
 examples_cxx/EnvExample.cpp			app=excxx_env
 examples_cxx/LockExample.cpp			app=excxx_lock
 examples_cxx/MpoolExample.cpp			app=excxx_mpool
+examples_cxx/SequenceExample.cpp
 examples_cxx/TpcbExample.cpp			app=excxx_tpcb
-fileops/fileops_auto.c				dynamic static vx
-fileops/fop_basic.c				dynamic static vx
-fileops/fop_rec.c				dynamic static vx
-fileops/fop_util.c				dynamic static vx
+examples_cxx/getting_started/MyDb.cpp
+examples_cxx/getting_started/excxx_example_database_load.cpp
+examples_cxx/getting_started/excxx_example_database_read.cpp
+fileops/fileops_auto.c				dynamic small static vx vxsmall
+fileops/fileops_autop.c				app=db_printlog
+fileops/fop_basic.c				dynamic small static vx vxsmall
+fileops/fop_rec.c				dynamic small static vx vxsmall
+fileops/fop_util.c				dynamic small static vx vxsmall
+gen_db_server.c
 hash/hash.c					dynamic static vx
 hash/hash_auto.c				dynamic static vx
+hash/hash_autop.c				app=db_printlog
 hash/hash_conv.c				dynamic static vx
 hash/hash_dup.c					dynamic static vx
-hash/hash_func.c				dynamic static vx
+hash/hash_func.c				dynamic small static vx vxsmall
 hash/hash_meta.c				dynamic static vx
 hash/hash_method.c				dynamic static vx
 hash/hash_open.c				dynamic static vx
@@ -170,124 +206,125 @@ hash/hash_page.c				dynamic static vx
 hash/hash_rec.c					dynamic static vx
 hash/hash_reclaim.c				dynamic static vx
 hash/hash_stat.c				dynamic static vx
+hash/hash_stub.c				small vxsmall
 hash/hash_upgrade.c				dynamic static vx
 hash/hash_verify.c				dynamic static vx
-hmac/hmac.c					dynamic static vx
-hmac/sha1.c					dynamic static vx
+hmac/hmac.c					dynamic small static vx vxsmall
+hmac/sha1.c					dynamic small static vx vxsmall
 hsearch/hsearch.c				dynamic static vx
-libdb_java/java_Db.c				java
-libdb_java/java_DbEnv.c				java
-libdb_java/java_DbLock.c			java
-libdb_java/java_DbLogc.c			java
-libdb_java/java_DbLsn.c				java
-libdb_java/java_DbTxn.c				java
-libdb_java/java_DbUtil.c			java
-libdb_java/java_Dbc.c				java
-libdb_java/java_Dbt.c				java
-libdb_java/java_info.c				java
-libdb_java/java_locked.c			java
-libdb_java/java_stat_auto.c			java
-libdb_java/java_util.c				java
-lock/lock.c					dynamic static vx
-lock/lock_deadlock.c				dynamic static vx
-lock/lock_method.c				dynamic static vx
-lock/lock_region.c				dynamic static vx
-lock/lock_stat.c				dynamic static vx
-lock/lock_util.c				dynamic static vx
-log/log.c					dynamic static vx
-log/log_archive.c				dynamic static vx
-log/log_compare.c				dynamic static vx
-log/log_get.c					dynamic static vx
-log/log_method.c				dynamic static vx
-log/log_put.c					dynamic static vx
-mp/mp_alloc.c					dynamic static vx
-mp/mp_bh.c					dynamic static vx
-mp/mp_fget.c					dynamic static vx
-mp/mp_fopen.c					dynamic static vx
-mp/mp_fput.c					dynamic static vx
-mp/mp_fset.c					dynamic static vx
-mp/mp_method.c					dynamic static vx
-mp/mp_region.c					dynamic static vx
-mp/mp_register.c				dynamic static vx
-mp/mp_stat.c					dynamic static vx
-mp/mp_sync.c					dynamic static vx
-mp/mp_trickle.c					dynamic static vx
+libdb_java/db_java_wrap.c			java
+lock/lock.c					dynamic small static vx vxsmall
+lock/lock_deadlock.c				dynamic small static vx vxsmall
+lock/lock_id.c					dynamic small static vx vxsmall
+lock/lock_list.c				dynamic small static vx vxsmall
+lock/lock_method.c				dynamic small static vx vxsmall
+lock/lock_region.c				dynamic small static vx vxsmall
+lock/lock_stat.c				dynamic small static vx vxsmall
+lock/lock_timer.c				dynamic small static vx vxsmall
+lock/lock_util.c				dynamic small static vx vxsmall
+log/log.c					dynamic small static vx vxsmall
+log/log_archive.c				dynamic small static vx vxsmall
+log/log_compare.c				dynamic small static vx vxsmall
+log/log_get.c					dynamic small static vx vxsmall
+log/log_method.c				dynamic small static vx vxsmall
+log/log_put.c					dynamic small static vx vxsmall
+log/log_stat.c					dynamic small static vx vxsmall
+mp/mp_alloc.c					dynamic small static vx vxsmall
+mp/mp_bh.c					dynamic small static vx vxsmall
+mp/mp_fget.c					dynamic small static vx vxsmall
+mp/mp_fmethod.c					dynamic small static vx vxsmall
+mp/mp_fopen.c					dynamic small static vx vxsmall
+mp/mp_fput.c					dynamic small static vx vxsmall
+mp/mp_fset.c					dynamic small static vx vxsmall
+mp/mp_method.c					dynamic small static vx vxsmall
+mp/mp_region.c					dynamic small static vx vxsmall
+mp/mp_register.c				dynamic small static vx vxsmall
+mp/mp_stat.c					dynamic small static vx vxsmall
+mp/mp_sync.c					dynamic small static vx vxsmall
+mp/mp_trickle.c					dynamic small static vx vxsmall
 mutex/mut_fcntl.c
 mutex/mut_pthread.c
-mutex/mut_tas.c					vx
-mutex/mut_win32.c				dynamic static
-mutex/mutex.c					dynamic static vx
+mutex/mut_tas.c					vx vxsmall
+mutex/mut_win32.c				dynamic small static
+mutex/mutex.c					dynamic small static vx vxsmall
 mutex/tm.c
 os/os_abs.c
-os/os_alloc.c					dynamic static vx
-os/os_clock.c					vx
+os/os_alloc.c					dynamic small static vx vxsmall
+os/os_clock.c					vx vxsmall
 os/os_config.c
-os/os_dir.c					vx
-os/os_errno.c					vx
-os/os_fid.c					vx
-os/os_fsync.c					vx
-os/os_handle.c					vx
-os/os_id.c					dynamic static vx
+os/os_dir.c					vx vxsmall
+os/os_errno.c					vx vxsmall
+os/os_fid.c					vx vxsmall
+os/os_fsync.c					vx vxsmall
+os/os_handle.c					vx vxsmall
+os/os_id.c					dynamic small static vx vxsmall
 os/os_map.c
-os/os_method.c					dynamic static vx
-os/os_oflags.c					dynamic static vx
-os/os_open.c					vx
-os/os_region.c					dynamic static vx
-os/os_rename.c					vx
-os/os_root.c					dynamic static vx
-os/os_rpath.c					dynamic static vx
-os/os_rw.c					vx
-os/os_seek.c					vx
-os/os_sleep.c					vx
-os/os_spin.c					vx
-os/os_stat.c					vx
-os/os_tmpdir.c					dynamic static vx
-os/os_unlink.c					dynamic static vx
-os_vxworks/os_vx_abs.c				vx
-os_vxworks/os_vx_config.c			vx
-os_vxworks/os_vx_map.c				vx
-os_win32/os_abs.c				dynamic static
-os_win32/os_clock.c				dynamic static
-os_win32/os_config.c				dynamic static
-os_win32/os_dir.c				dynamic static
-os_win32/os_errno.c				dynamic static
-os_win32/os_fid.c				dynamic static
-os_win32/os_fsync.c				dynamic static
-os_win32/os_handle.c				dynamic static
-os_win32/os_map.c				dynamic static
-os_win32/os_open.c				dynamic static
-os_win32/os_rename.c				dynamic static
-os_win32/os_rw.c				dynamic static
-os_win32/os_seek.c				dynamic static
-os_win32/os_sleep.c				dynamic static
-os_win32/os_spin.c				dynamic static
-os_win32/os_stat.c				dynamic static
-os_win32/os_type.c				dynamic static
+os/os_method.c					dynamic small static vx vxsmall
+os/os_oflags.c					dynamic small static vx vxsmall
+os/os_open.c					vx vxsmall
+os/os_region.c					dynamic small static vx vxsmall
+os/os_rename.c					vx vxsmall
+os/os_root.c					dynamic small static vx vxsmall
+os/os_rpath.c					dynamic small static vx vxsmall
+os/os_rw.c					vx vxsmall
+os/os_seek.c					vx vxsmall
+os/os_sleep.c					vx vxsmall
+os/os_spin.c					vx vxsmall
+os/os_stat.c					vx vxsmall
+os/os_tmpdir.c					dynamic small static vx vxsmall
+os/os_truncate.c				vx vxsmall
+os/os_unlink.c					vx vxsmall
+os_vxworks/os_vx_abs.c				vx vxsmall
+os_vxworks/os_vx_config.c			vx vxsmall
+os_vxworks/os_vx_map.c				vx vxsmall
+os_win32/os_abs.c				dynamic small static
+os_win32/os_clock.c				dynamic small static
+os_win32/os_config.c				dynamic small static
+os_win32/os_dir.c				dynamic small static
+os_win32/os_errno.c				dynamic small static
+os_win32/os_fid.c				dynamic small static
+os_win32/os_fsync.c				dynamic small static
+os_win32/os_handle.c				dynamic small static
+os_win32/os_map.c				dynamic small static
+os_win32/os_open.c				dynamic small static
+os_win32/os_rename.c				dynamic small static
+os_win32/os_rw.c				dynamic small static
+os_win32/os_seek.c				dynamic small static
+os_win32/os_sleep.c				dynamic small static
+os_win32/os_spin.c				dynamic small static
+os_win32/os_stat.c				dynamic small static
+os_win32/os_truncate.c				dynamic small static
+os_win32/os_unlink.c				dynamic small static
 qam/qam.c					dynamic static vx
 qam/qam_auto.c					dynamic static vx
+qam/qam_autop.c					app=db_printlog
 qam/qam_conv.c					dynamic static vx
 qam/qam_files.c					dynamic static vx
 qam/qam_method.c				dynamic static vx
 qam/qam_open.c					dynamic static vx
 qam/qam_rec.c					dynamic static vx
 qam/qam_stat.c					dynamic static vx
+qam/qam_stub.c					small vxsmall
 qam/qam_upgrade.c				dynamic static vx
 qam/qam_verify.c				dynamic static vx
+rep/rep_auto.c					dynamic static vx
+rep/rep_autop.c					app=db_printlog
+rep/rep_backup.c				dynamic static vx
 rep/rep_method.c				dynamic static vx
 rep/rep_record.c				dynamic static vx
 rep/rep_region.c				dynamic static vx
+rep/rep_stat.c					dynamic static vx
+rep/rep_stub.c					small vxsmall
 rep/rep_util.c					dynamic static vx
-rpc_client/client.c				vx
-rpc_client/db_server_clnt.c			vx
-rpc_client/gen_client.c				vx
-rpc_client/gen_client_ret.c			vx
+rpc_client/client.c
+rpc_client/gen_client.c
+rpc_client/gen_client_ret.c
 rpc_server/c/db_server_proc.c
-rpc_server/c/db_server_svc.c
 rpc_server/c/db_server_util.c
-rpc_server/c/db_server_xdr.c			vx
-rpc_server/c/gen_db_server.c
 rpc_server/cxx/db_server_cxxproc.cpp
 rpc_server/cxx/db_server_cxxutil.cpp
+sequence/seq_stat.c				dynamic small static
+sequence/sequence.c				dynamic small static
 tcl/tcl_compat.c				tcl
 tcl/tcl_db.c					tcl
 tcl/tcl_db_pkg.c				tcl
@@ -298,13 +335,14 @@ tcl/tcl_lock.c					tcl
 tcl/tcl_log.c					tcl
 tcl/tcl_mp.c					tcl
 tcl/tcl_rep.c					tcl
+tcl/tcl_seq.c					tcl
 tcl/tcl_txn.c					tcl
 tcl/tcl_util.c					tcl
 test_perf/db_perf.c				app=db_perf
-test_perf/perf_cache_check.c			app=db_perf
 test_perf/perf_checkpoint.c			app=db_perf
 test_perf/perf_config.c				app=db_perf
 test_perf/perf_dbs.c				app=db_perf
+test_perf/perf_dead.c				app=db_perf
 test_perf/perf_debug.c				app=db_perf
 test_perf/perf_file.c				app=db_perf
 test_perf/perf_key.c				app=db_perf
@@ -314,19 +352,22 @@ test_perf/perf_op.c				app=db_perf
 test_perf/perf_parse.c				app=db_perf
 test_perf/perf_rand.c				app=db_perf
 test_perf/perf_spawn.c				app=db_perf
+test_perf/perf_stat.c				app=db_perf
+test_perf/perf_sync.c				app=db_perf
 test_perf/perf_thread.c				app=db_perf
 test_perf/perf_trickle.c			app=db_perf
 test_perf/perf_txn.c				app=db_perf
 test_perf/perf_util.c				app=db_perf
 test_perf/perf_vx.c
-txn/txn.c					dynamic static vx
-txn/txn_auto.c					dynamic static vx
-txn/txn_method.c				dynamic static vx
-txn/txn_rec.c					dynamic static vx
-txn/txn_recover.c				dynamic static vx
-txn/txn_region.c				dynamic static vx
-txn/txn_stat.c					dynamic static vx
-txn/txn_util.c					dynamic static vx
-xa/xa.c						dynamic static vx
-xa/xa_db.c					dynamic static vx
-xa/xa_map.c					dynamic static vx
+txn/txn.c					dynamic small static vx vxsmall
+txn/txn_auto.c					dynamic small static vx vxsmall
+txn/txn_autop.c					app=db_printlog
+txn/txn_method.c				dynamic small static vx vxsmall
+txn/txn_rec.c					dynamic small static vx vxsmall
+txn/txn_recover.c				dynamic small static vx vxsmall
+txn/txn_region.c				dynamic small static vx vxsmall
+txn/txn_stat.c					dynamic small static vx vxsmall
+txn/txn_util.c					dynamic small static vx vxsmall
+xa/xa.c						dynamic small static vx vxsmall
+xa/xa_db.c					dynamic small static vx vxsmall
+xa/xa_map.c					dynamic small static vx vxsmall
diff --git a/storage/bdb/dist/template/db_server_proc b/storage/bdb/dist/template/db_server_proc
new file mode 100644
index 0000000000000000000000000000000000000000..224c83684fb4df9511cc87151e1253d7eb151760
--- /dev/null
+++ b/storage/bdb/dist/template/db_server_proc
@@ -0,0 +1,1794 @@
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <rpc/rpc.h>
+
+#include <string.h>
+#endif
+
+#include "db_server.h"
+
+#include "db_int.h"
+#include "dbinc/db_server_int.h"
+
+/* BEGIN __env_get_cachesize_proc */
+void
+__env_get_cachesize_proc(dbenvcl_id,
+		replyp)
+	long dbenvcl_id;
+	__env_get_cachesize_reply *replyp;
+/* END __env_get_cachesize_proc */
+{
+	int ret;
+	DB_ENV * dbenv;
+	ct_entry *dbenv_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __env_cachesize_proc */
+void
+__env_cachesize_proc(dbenvcl_id, gbytes, bytes,
+		ncache, replyp)
+	long dbenvcl_id;
+	u_int32_t gbytes;
+	u_int32_t bytes;
+	u_int32_t ncache;
+	__env_cachesize_reply *replyp;
+/* END __env_cachesize_proc */
+{
+	int ret;
+	DB_ENV * dbenv;
+	ct_entry *dbenv_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __env_close_proc */
+void
+__env_close_proc(dbenvcl_id, flags, replyp)
+	long dbenvcl_id;
+	u_int32_t flags;
+	__env_close_reply *replyp;
+/* END __env_close_proc */
+{
+	int ret;
+	DB_ENV * dbenv;
+	ct_entry *dbenv_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __env_create_proc */
+void
+__env_create_proc(timeout, replyp)
+	u_int32_t timeout;
+	__env_create_reply *replyp;
+/* END __env_create_proc */
+{
+	int ret;
+
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __env_dbremove_proc */
+void
+__env_dbremove_proc(dbenvcl_id, txnpcl_id, name,
+		subdb, flags, replyp)
+	long dbenvcl_id;
+	long txnpcl_id;
+	char *name;
+	char *subdb;
+	u_int32_t flags;
+	__env_dbremove_reply *replyp;
+/* END __env_dbremove_proc */
+{
+	int ret;
+	DB_ENV * dbenv;
+	ct_entry *dbenv_ctp;
+	DB_TXN * txnp;
+	ct_entry *txnp_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+	ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+	txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __env_dbrename_proc */
+void
+__env_dbrename_proc(dbenvcl_id, txnpcl_id, name,
+		subdb, newname, flags, replyp)
+	long dbenvcl_id;
+	long txnpcl_id;
+	char *name;
+	char *subdb;
+	char *newname;
+	u_int32_t flags;
+	__env_dbrename_reply *replyp;
+/* END __env_dbrename_proc */
+{
+	int ret;
+	DB_ENV * dbenv;
+	ct_entry *dbenv_ctp;
+	DB_TXN * txnp;
+	ct_entry *txnp_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+	ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+	txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __env_get_encrypt_flags_proc */
+void
+__env_get_encrypt_flags_proc(dbenvcl_id, replyp)
+	long dbenvcl_id;
+	__env_get_encrypt_flags_reply *replyp;
+/* END __env_get_encrypt_flags_proc */
+{
+	int ret;
+	DB_ENV * dbenv;
+	ct_entry *dbenv_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __env_encrypt_proc */
+void
+__env_encrypt_proc(dbenvcl_id, passwd, flags, replyp)
+	long dbenvcl_id;
+	char *passwd;
+	u_int32_t flags;
+	__env_encrypt_reply *replyp;
+/* END __env_encrypt_proc */
+{
+	int ret;
+	DB_ENV * dbenv;
+	ct_entry *dbenv_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __env_get_flags_proc */
+void
+__env_get_flags_proc(dbenvcl_id, replyp)
+	long dbenvcl_id;
+	__env_get_flags_reply *replyp;
+/* END __env_get_flags_proc */
+{
+	int ret;
+	DB_ENV * dbenv;
+	ct_entry *dbenv_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __env_flags_proc */
+void
+__env_flags_proc(dbenvcl_id, flags, onoff, replyp)
+	long dbenvcl_id;
+	u_int32_t flags;
+	u_int32_t onoff;
+	__env_flags_reply *replyp;
+/* END __env_flags_proc */
+{
+	int ret;
+	DB_ENV * dbenv;
+	ct_entry *dbenv_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __env_get_home_proc */
+void
+__env_get_home_proc(dbenvcl_id, replyp)
+	long dbenvcl_id;
+	__env_get_home_reply *replyp;
+/* END __env_get_home_proc */
+{
+	int ret;
+	DB_ENV * dbenv;
+	ct_entry *dbenv_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __env_get_open_flags_proc */
+void
+__env_get_open_flags_proc(dbenvcl_id, replyp)
+	long dbenvcl_id;
+	__env_get_open_flags_reply *replyp;
+/* END __env_get_open_flags_proc */
+{
+	int ret;
+	DB_ENV * dbenv;
+	ct_entry *dbenv_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __env_open_proc */
+void
+__env_open_proc(dbenvcl_id, home, flags,
+		mode, replyp)
+	long dbenvcl_id;
+	char *home;
+	u_int32_t flags;
+	u_int32_t mode;
+	__env_open_reply *replyp;
+/* END __env_open_proc */
+{
+	int ret;
+	DB_ENV * dbenv;
+	ct_entry *dbenv_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __env_remove_proc */
+void
+__env_remove_proc(dbenvcl_id, home, flags, replyp)
+	long dbenvcl_id;
+	char *home;
+	u_int32_t flags;
+	__env_remove_reply *replyp;
+/* END __env_remove_proc */
+{
+	int ret;
+	DB_ENV * dbenv;
+	ct_entry *dbenv_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __txn_abort_proc */
+void
+__txn_abort_proc(txnpcl_id, replyp)
+	long txnpcl_id;
+	__txn_abort_reply *replyp;
+/* END __txn_abort_proc */
+{
+	int ret;
+	DB_TXN * txnp;
+	ct_entry *txnp_ctp;
+
+	ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+	txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __txn_begin_proc */
+void
+__txn_begin_proc(dbenvcl_id, parentcl_id,
+		flags, replyp)
+	long dbenvcl_id;
+	long parentcl_id;
+	u_int32_t flags;
+	__txn_begin_reply *replyp;
+/* END __txn_begin_proc */
+{
+	int ret;
+	DB_ENV * dbenv;
+	ct_entry *dbenv_ctp;
+	DB_TXN * parent;
+	ct_entry *parent_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+	ACTIVATE_CTP(parent_ctp, parentcl_id, CT_TXN);
+	parent = (DB_TXN *)parent_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __txn_commit_proc */
+void
+__txn_commit_proc(txnpcl_id, flags, replyp)
+	long txnpcl_id;
+	u_int32_t flags;
+	__txn_commit_reply *replyp;
+/* END __txn_commit_proc */
+{
+	int ret;
+	DB_TXN * txnp;
+	ct_entry *txnp_ctp;
+
+	ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+	txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __txn_discard_proc */
+void
+__txn_discard_proc(txnpcl_id, flags, replyp)
+	long txnpcl_id;
+	u_int32_t flags;
+	__txn_discard_reply *replyp;
+/* END __txn_discard_proc */
+{
+	int ret;
+	DB_TXN * txnp;
+	ct_entry *txnp_ctp;
+
+	ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+	txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __txn_prepare_proc */
+void
+__txn_prepare_proc(txnpcl_id, gid, replyp)
+	long txnpcl_id;
+	u_int8_t *gid;
+	__txn_prepare_reply *replyp;
+/* END __txn_prepare_proc */
+{
+	int ret;
+	DB_TXN * txnp;
+	ct_entry *txnp_ctp;
+
+	ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+	txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __txn_recover_proc */
+void
+__txn_recover_proc(dbenvcl_id, count,
+		flags, replyp, freep)
+	long dbenvcl_id;
+	u_int32_t count;
+	u_int32_t flags;
+	__txn_recover_reply *replyp;
+	int * freep;
+/* END __txn_recover_proc */
+{
+	int ret;
+	DB_ENV * dbenv;
+	ct_entry *dbenv_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_associate_proc */
+void
+__db_associate_proc(dbpcl_id, txnpcl_id, sdbpcl_id,
+		flags, replyp)
+	long dbpcl_id;
+	long txnpcl_id;
+	long sdbpcl_id;
+	u_int32_t flags;
+	__db_associate_reply *replyp;
+/* END __db_associate_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+	DB_TXN * txnp;
+	ct_entry *txnp_ctp;
+	DB * sdbp;
+	ct_entry *sdbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+	ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+	txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+	ACTIVATE_CTP(sdbp_ctp, sdbpcl_id, CT_DB);
+	sdbp = (DB *)sdbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_bt_maxkey_proc */
+void
+__db_bt_maxkey_proc(dbpcl_id, maxkey, replyp)
+	long dbpcl_id;
+	u_int32_t maxkey;
+	__db_bt_maxkey_reply *replyp;
+/* END __db_bt_maxkey_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_get_bt_minkey_proc */
+void
+__db_get_bt_minkey_proc(dbpcl_id, replyp)
+	long dbpcl_id;
+	__db_get_bt_minkey_reply *replyp;
+/* END __db_get_bt_minkey_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_bt_minkey_proc */
+void
+__db_bt_minkey_proc(dbpcl_id, minkey, replyp)
+	long dbpcl_id;
+	u_int32_t minkey;
+	__db_bt_minkey_reply *replyp;
+/* END __db_bt_minkey_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_close_proc */
+void
+__db_close_proc(dbpcl_id, flags, replyp)
+	long dbpcl_id;
+	u_int32_t flags;
+	__db_close_reply *replyp;
+/* END __db_close_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_create_proc */
+void
+__db_create_proc(dbenvcl_id, flags, replyp)
+	long dbenvcl_id;
+	u_int32_t flags;
+	__db_create_reply *replyp;
+/* END __db_create_proc */
+{
+	int ret;
+	DB_ENV * dbenv;
+	ct_entry *dbenv_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_del_proc */
+void
+__db_del_proc(dbpcl_id, txnpcl_id, keydlen,
+		keydoff, keyulen, keyflags, keydata,
+		keysize, flags, replyp)
+	long dbpcl_id;
+	long txnpcl_id;
+	u_int32_t keydlen;
+	u_int32_t keydoff;
+	u_int32_t keyulen;
+	u_int32_t keyflags;
+	void *keydata;
+	u_int32_t keysize;
+	u_int32_t flags;
+	__db_del_reply *replyp;
+/* END __db_del_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+	DB_TXN * txnp;
+	ct_entry *txnp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+	ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+	txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_get_encrypt_flags_proc */
+void
+__db_get_encrypt_flags_proc(dbpcl_id, replyp)
+	long dbpcl_id;
+	__db_get_encrypt_flags_reply *replyp;
+/* END __db_get_encrypt_flags_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_encrypt_proc */
+void
+__db_encrypt_proc(dbpcl_id, passwd, flags, replyp)
+	long dbpcl_id;
+	char *passwd;
+	u_int32_t flags;
+	__db_encrypt_reply *replyp;
+/* END __db_encrypt_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_get_extentsize_proc */
+void
+__db_get_extentsize_proc(dbpcl_id, replyp)
+	long dbpcl_id;
+	__db_get_extentsize_reply *replyp;
+/* END __db_get_extentsize_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_extentsize_proc */
+void
+__db_extentsize_proc(dbpcl_id, extentsize, replyp)
+	long dbpcl_id;
+	u_int32_t extentsize;
+	__db_extentsize_reply *replyp;
+/* END __db_extentsize_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_get_flags_proc */
+void
+__db_get_flags_proc(dbpcl_id, replyp)
+	long dbpcl_id;
+	__db_get_flags_reply *replyp;
+/* END __db_get_flags_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_flags_proc */
+void
+__db_flags_proc(dbpcl_id, flags, replyp)
+	long dbpcl_id;
+	u_int32_t flags;
+	__db_flags_reply *replyp;
+/* END __db_flags_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_get_proc */
+void
+__db_get_proc(dbpcl_id, txnpcl_id, keydlen,
+		keydoff, keyulen, keyflags, keydata,
+		keysize, datadlen, datadoff, dataulen,
+		dataflags, datadata, datasize, flags, replyp, freep)
+	long dbpcl_id;
+	long txnpcl_id;
+	u_int32_t keydlen;
+	u_int32_t keydoff;
+	u_int32_t keyulen;
+	u_int32_t keyflags;
+	void *keydata;
+	u_int32_t keysize;
+	u_int32_t datadlen;
+	u_int32_t datadoff;
+	u_int32_t dataulen;
+	u_int32_t dataflags;
+	void *datadata;
+	u_int32_t datasize;
+	u_int32_t flags;
+	__db_get_reply *replyp;
+	int * freep;
+/* END __db_get_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+	DB_TXN * txnp;
+	ct_entry *txnp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+	ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+	txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_get_name_proc */
+void
+__db_get_name_proc(dbpcl_id, replyp)
+	long dbpcl_id;
+	__db_get_name_reply *replyp;
+/* END __db_get_name_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_get_open_flags_proc */
+void
+__db_get_open_flags_proc(dbpcl_id, replyp)
+	long dbpcl_id;
+	__db_get_open_flags_reply *replyp;
+/* END __db_get_open_flags_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_get_h_ffactor_proc */
+void
+__db_get_h_ffactor_proc(dbpcl_id, replyp)
+	long dbpcl_id;
+	__db_get_h_ffactor_reply *replyp;
+/* END __db_get_h_ffactor_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_h_ffactor_proc */
+void
+__db_h_ffactor_proc(dbpcl_id, ffactor, replyp)
+	long dbpcl_id;
+	u_int32_t ffactor;
+	__db_h_ffactor_reply *replyp;
+/* END __db_h_ffactor_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_get_h_nelem_proc */
+void
+__db_get_h_nelem_proc(dbpcl_id, replyp)
+	long dbpcl_id;
+	__db_get_h_nelem_reply *replyp;
+/* END __db_get_h_nelem_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_h_nelem_proc */
+void
+__db_h_nelem_proc(dbpcl_id, nelem, replyp)
+	long dbpcl_id;
+	u_int32_t nelem;
+	__db_h_nelem_reply *replyp;
+/* END __db_h_nelem_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_key_range_proc */
+void
+__db_key_range_proc(dbpcl_id, txnpcl_id, keydlen,
+		keydoff, keyulen, keyflags, keydata,
+		keysize, flags, replyp)
+	long dbpcl_id;
+	long txnpcl_id;
+	u_int32_t keydlen;
+	u_int32_t keydoff;
+	u_int32_t keyulen;
+	u_int32_t keyflags;
+	void *keydata;
+	u_int32_t keysize;
+	u_int32_t flags;
+	__db_key_range_reply *replyp;
+/* END __db_key_range_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+	DB_TXN * txnp;
+	ct_entry *txnp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+	ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+	txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_get_lorder_proc */
+void
+__db_get_lorder_proc(dbpcl_id, replyp)
+	long dbpcl_id;
+	__db_get_lorder_reply *replyp;
+/* END __db_get_lorder_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_lorder_proc */
+void
+__db_lorder_proc(dbpcl_id, lorder, replyp)
+	long dbpcl_id;
+	u_int32_t lorder;
+	__db_lorder_reply *replyp;
+/* END __db_lorder_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_open_proc */
+void
+__db_open_proc(dbpcl_id, txnpcl_id, name,
+		subdb, type, flags, mode, replyp)
+	long dbpcl_id;
+	long txnpcl_id;
+	char *name;
+	char *subdb;
+	u_int32_t type;
+	u_int32_t flags;
+	u_int32_t mode;
+	__db_open_reply *replyp;
+/* END __db_open_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+	DB_TXN * txnp;
+	ct_entry *txnp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+	ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+	txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_get_pagesize_proc */
+void
+__db_get_pagesize_proc(dbpcl_id, replyp)
+	long dbpcl_id;
+	__db_get_pagesize_reply *replyp;
+/* END __db_get_pagesize_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_pagesize_proc */
+void
+__db_pagesize_proc(dbpcl_id, pagesize, replyp)
+	long dbpcl_id;
+	u_int32_t pagesize;
+	__db_pagesize_reply *replyp;
+/* END __db_pagesize_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_pget_proc */
+void
+__db_pget_proc(dbpcl_id, txnpcl_id, skeydlen,
+		skeydoff, skeyulen, skeyflags, skeydata,
+		skeysize, pkeydlen, pkeydoff, pkeyulen,
+		pkeyflags, pkeydata, pkeysize, datadlen,
+		datadoff, dataulen, dataflags, datadata,
+		datasize, flags, replyp, freep)
+	long dbpcl_id;
+	long txnpcl_id;
+	u_int32_t skeydlen;
+	u_int32_t skeydoff;
+	u_int32_t skeyulen;
+	u_int32_t skeyflags;
+	void *skeydata;
+	u_int32_t skeysize;
+	u_int32_t pkeydlen;
+	u_int32_t pkeydoff;
+	u_int32_t pkeyulen;
+	u_int32_t pkeyflags;
+	void *pkeydata;
+	u_int32_t pkeysize;
+	u_int32_t datadlen;
+	u_int32_t datadoff;
+	u_int32_t dataulen;
+	u_int32_t dataflags;
+	void *datadata;
+	u_int32_t datasize;
+	u_int32_t flags;
+	__db_pget_reply *replyp;
+	int * freep;
+/* END __db_pget_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+	DB_TXN * txnp;
+	ct_entry *txnp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+	ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+	txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_put_proc */
+void
+__db_put_proc(dbpcl_id, txnpcl_id, keydlen,
+		keydoff, keyulen, keyflags, keydata,
+		keysize, datadlen, datadoff, dataulen,
+		dataflags, datadata, datasize, flags, replyp, freep)
+	long dbpcl_id;
+	long txnpcl_id;
+	u_int32_t keydlen;
+	u_int32_t keydoff;
+	u_int32_t keyulen;
+	u_int32_t keyflags;
+	void *keydata;
+	u_int32_t keysize;
+	u_int32_t datadlen;
+	u_int32_t datadoff;
+	u_int32_t dataulen;
+	u_int32_t dataflags;
+	void *datadata;
+	u_int32_t datasize;
+	u_int32_t flags;
+	__db_put_reply *replyp;
+	int * freep;
+/* END __db_put_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+	DB_TXN * txnp;
+	ct_entry *txnp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+	ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+	txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_get_re_delim_proc */
+void
+__db_get_re_delim_proc(dbpcl_id, replyp)
+	long dbpcl_id;
+	__db_get_re_delim_reply *replyp;
+/* END __db_get_re_delim_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_re_delim_proc */
+void
+__db_re_delim_proc(dbpcl_id, delim, replyp)
+	long dbpcl_id;
+	u_int32_t delim;
+	__db_re_delim_reply *replyp;
+/* END __db_re_delim_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_get_re_len_proc */
+void
+__db_get_re_len_proc(dbpcl_id, replyp)
+	long dbpcl_id;
+	__db_get_re_len_reply *replyp;
+/* END __db_get_re_len_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_re_len_proc */
+void
+__db_re_len_proc(dbpcl_id, len, replyp)
+	long dbpcl_id;
+	u_int32_t len;
+	__db_re_len_reply *replyp;
+/* END __db_re_len_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_re_pad_proc */
+void
+__db_re_pad_proc(dbpcl_id, pad, replyp)
+	long dbpcl_id;
+	u_int32_t pad;
+	__db_re_pad_reply *replyp;
+/* END __db_re_pad_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_get_re_pad_proc */
+void
+__db_get_re_pad_proc(dbpcl_id, replyp)
+	long dbpcl_id;
+	__db_get_re_pad_reply *replyp;
+/* END __db_get_re_pad_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_remove_proc */
+void
+__db_remove_proc(dbpcl_id, name, subdb,
+		flags, replyp)
+	long dbpcl_id;
+	char *name;
+	char *subdb;
+	u_int32_t flags;
+	__db_remove_reply *replyp;
+/* END __db_remove_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_rename_proc */
+void
+__db_rename_proc(dbpcl_id, name, subdb,
+		newname, flags, replyp)
+	long dbpcl_id;
+	char *name;
+	char *subdb;
+	char *newname;
+	u_int32_t flags;
+	__db_rename_reply *replyp;
+/* END __db_rename_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_stat_proc */
+void
+__db_stat_proc(dbpcl_id, txnpcl_id,
+		flags, replyp, freep)
+	long dbpcl_id;
+	long txnpcl_id;
+	u_int32_t flags;
+	__db_stat_reply *replyp;
+	int * freep;
+/* END __db_stat_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+	DB_TXN * txnp;
+	ct_entry *txnp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+	ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+	txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_sync_proc */
+void
+__db_sync_proc(dbpcl_id, flags, replyp)
+	long dbpcl_id;
+	u_int32_t flags;
+	__db_sync_reply *replyp;
+/* END __db_sync_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_truncate_proc */
+void
+__db_truncate_proc(dbpcl_id, txnpcl_id,
+		flags, replyp)
+	long dbpcl_id;
+	long txnpcl_id;
+	u_int32_t flags;
+	__db_truncate_reply *replyp;
+/* END __db_truncate_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+	DB_TXN * txnp;
+	ct_entry *txnp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+	ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+	txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_cursor_proc */
+void
+__db_cursor_proc(dbpcl_id, txnpcl_id,
+		flags, replyp)
+	long dbpcl_id;
+	long txnpcl_id;
+	u_int32_t flags;
+	__db_cursor_reply *replyp;
+/* END __db_cursor_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+	DB_TXN * txnp;
+	ct_entry *txnp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+	ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+	txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __db_join_proc */
+void
+__db_join_proc(dbpcl_id, curs, curslen,
+		flags, replyp)
+	long dbpcl_id;
+	u_int32_t * curs;
+	u_int32_t curslen;
+	u_int32_t flags;
+	__db_join_reply *replyp;
+/* END __db_join_proc */
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __dbc_close_proc */
+void
+__dbc_close_proc(dbccl_id, replyp)
+	long dbccl_id;
+	__dbc_close_reply *replyp;
+/* END __dbc_close_proc */
+{
+	int ret;
+	DBC * dbc;
+	ct_entry *dbc_ctp;
+
+	ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+	dbc = (DBC *)dbc_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __dbc_count_proc */
+void
+__dbc_count_proc(dbccl_id, flags, replyp)
+	long dbccl_id;
+	u_int32_t flags;
+	__dbc_count_reply *replyp;
+/* END __dbc_count_proc */
+{
+	int ret;
+	DBC * dbc;
+	ct_entry *dbc_ctp;
+
+	ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+	dbc = (DBC *)dbc_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __dbc_del_proc */
+void
+__dbc_del_proc(dbccl_id, flags, replyp)
+	long dbccl_id;
+	u_int32_t flags;
+	__dbc_del_reply *replyp;
+/* END __dbc_del_proc */
+{
+	int ret;
+	DBC * dbc;
+	ct_entry *dbc_ctp;
+
+	ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+	dbc = (DBC *)dbc_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __dbc_dup_proc */
+void
+__dbc_dup_proc(dbccl_id, flags, replyp)
+	long dbccl_id;
+	u_int32_t flags;
+	__dbc_dup_reply *replyp;
+/* END __dbc_dup_proc */
+{
+	int ret;
+	DBC * dbc;
+	ct_entry *dbc_ctp;
+
+	ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+	dbc = (DBC *)dbc_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __dbc_get_proc */
+void
+__dbc_get_proc(dbccl_id, keydlen, keydoff,
+		keyulen, keyflags, keydata, keysize,
+		datadlen, datadoff, dataulen, dataflags,
+		datadata, datasize, flags, replyp, freep)
+	long dbccl_id;
+	u_int32_t keydlen;
+	u_int32_t keydoff;
+	u_int32_t keyulen;
+	u_int32_t keyflags;
+	void *keydata;
+	u_int32_t keysize;
+	u_int32_t datadlen;
+	u_int32_t datadoff;
+	u_int32_t dataulen;
+	u_int32_t dataflags;
+	void *datadata;
+	u_int32_t datasize;
+	u_int32_t flags;
+	__dbc_get_reply *replyp;
+	int * freep;
+/* END __dbc_get_proc */
+{
+	int ret;
+	DBC * dbc;
+	ct_entry *dbc_ctp;
+
+	ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+	dbc = (DBC *)dbc_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __dbc_pget_proc */
+void
+__dbc_pget_proc(dbccl_id, skeydlen, skeydoff,
+		skeyulen, skeyflags, skeydata, skeysize,
+		pkeydlen, pkeydoff, pkeyulen, pkeyflags,
+		pkeydata, pkeysize, datadlen, datadoff,
+		dataulen, dataflags, datadata, datasize,
+		flags, replyp, freep)
+	long dbccl_id;
+	u_int32_t skeydlen;
+	u_int32_t skeydoff;
+	u_int32_t skeyulen;
+	u_int32_t skeyflags;
+	void *skeydata;
+	u_int32_t skeysize;
+	u_int32_t pkeydlen;
+	u_int32_t pkeydoff;
+	u_int32_t pkeyulen;
+	u_int32_t pkeyflags;
+	void *pkeydata;
+	u_int32_t pkeysize;
+	u_int32_t datadlen;
+	u_int32_t datadoff;
+	u_int32_t dataulen;
+	u_int32_t dataflags;
+	void *datadata;
+	u_int32_t datasize;
+	u_int32_t flags;
+	__dbc_pget_reply *replyp;
+	int * freep;
+/* END __dbc_pget_proc */
+{
+	int ret;
+	DBC * dbc;
+	ct_entry *dbc_ctp;
+
+	ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+	dbc = (DBC *)dbc_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
+/* BEGIN __dbc_put_proc */
+void
+__dbc_put_proc(dbccl_id, keydlen, keydoff,
+		keyulen, keyflags, keydata, keysize,
+		datadlen, datadoff, dataulen, dataflags,
+		datadata, datasize, flags, replyp, freep)
+	long dbccl_id;
+	u_int32_t keydlen;
+	u_int32_t keydoff;
+	u_int32_t keyulen;
+	u_int32_t keyflags;
+	void *keydata;
+	u_int32_t keysize;
+	u_int32_t datadlen;
+	u_int32_t datadoff;
+	u_int32_t dataulen;
+	u_int32_t dataflags;
+	void *datadata;
+	u_int32_t datasize;
+	u_int32_t flags;
+	__dbc_put_reply *replyp;
+	int * freep;
+/* END __dbc_put_proc */
+{
+	int ret;
+	DBC * dbc;
+	ct_entry *dbc_ctp;
+
+	ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+	dbc = (DBC *)dbc_ctp->ct_anyp;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	replyp->status = ret;
+	return;
+}
+
diff --git a/storage/bdb/dist/template/gen_client_ret b/storage/bdb/dist/template/gen_client_ret
new file mode 100644
index 0000000000000000000000000000000000000000..3d897e60995e69d5eaca8e832945ced45094a94a
--- /dev/null
+++ b/storage/bdb/dist/template/gen_client_ret
@@ -0,0 +1,723 @@
+/* Do not edit: automatically built by gen_rpc.awk. */
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#endif
+#include "db_int.h"
+#include "dbinc/txn.h"
+
+/*
+ * PUBLIC: int __dbcl_env_create_ret __P((DB_ENV *, long,
+ * PUBLIC:      __env_create_reply *));
+ */
+int
+__dbcl_env_create_ret(dbenv, timeout, replyp)
+	DB_ENV * dbenv;
+	long timeout;
+	__env_create_reply *replyp;
+{
+	int ret;
+	long env;
+
+	if (replyp->status != 0)
+		return (replyp->status);
+	env = replyp->envcl_id;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_env_open_ret __P((DB_ENV *, const char *, u_int32_t, int,
+ * PUBLIC:      __env_open_reply *));
+ */
+int
+__dbcl_env_open_ret(dbenv, home, flags, mode, replyp)
+	DB_ENV * dbenv;
+	const char * home;
+	u_int32_t flags;
+	int mode;
+	__env_open_reply *replyp;
+{
+	int ret;
+	long env;
+
+	if (replyp->status != 0)
+		return (replyp->status);
+	env = replyp->envcl_id;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_env_remove_ret __P((DB_ENV *, const char *, u_int32_t,
+ * PUBLIC:      __env_remove_reply *));
+ */
+int
+__dbcl_env_remove_ret(dbenv, home, flags, replyp)
+	DB_ENV * dbenv;
+	const char * home;
+	u_int32_t flags;
+	__env_remove_reply *replyp;
+{
+	int ret;
+
+	if (replyp->status != 0)
+		return (replyp->status);
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_txn_abort_ret __P((DB_TXN *, __txn_abort_reply *));
+ */
+int
+__dbcl_txn_abort_ret(txnp, replyp)
+	DB_TXN * txnp;
+	__txn_abort_reply *replyp;
+{
+	int ret;
+
+	if (replyp->status != 0)
+		return (replyp->status);
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_txn_begin_ret __P((DB_ENV *, DB_TXN *, DB_TXN **,
+ * PUBLIC:      u_int32_t, __txn_begin_reply *));
+ */
+int
+__dbcl_txn_begin_ret(dbenv, parent, txnpp, flags, replyp)
+	DB_ENV * dbenv;
+	DB_TXN * parent;
+	DB_TXN ** txnpp;
+	u_int32_t flags;
+	__txn_begin_reply *replyp;
+{
+	int ret;
+	long txnid;
+
+	if (replyp->status != 0)
+		return (replyp->status);
+	txnid = replyp->txnidcl_id;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_txn_commit_ret __P((DB_TXN *, u_int32_t,
+ * PUBLIC:      __txn_commit_reply *));
+ */
+int
+__dbcl_txn_commit_ret(txnp, flags, replyp)
+	DB_TXN * txnp;
+	u_int32_t flags;
+	__txn_commit_reply *replyp;
+{
+	int ret;
+
+	if (replyp->status != 0)
+		return (replyp->status);
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_txn_discard_ret __P((DB_TXN *, u_int32_t,
+ * PUBLIC:      __txn_discard_reply *));
+ */
+int
+__dbcl_txn_discard_ret(txnp, flags, replyp)
+	DB_TXN * txnp;
+	u_int32_t flags;
+	__txn_discard_reply *replyp;
+{
+	int ret;
+
+	if (replyp->status != 0)
+		return (replyp->status);
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_txn_recover_ret __P((DB_ENV *, DB_PREPLIST *, long,
+ * PUBLIC:      long *, u_int32_t, __txn_recover_reply *));
+ */
+int
+__dbcl_txn_recover_ret(dbenv, preplist, count, retp, flags, replyp)
+	DB_ENV * dbenv;
+	DB_PREPLIST * preplist;
+	long count;
+	long * retp;
+	u_int32_t flags;
+	__txn_recover_reply *replyp;
+{
+	int ret;
+	u_int32_t *__db_txn;
+	u_int8_t *__db_gid;
+	long retcount;
+
+	if (replyp->status != 0)
+		return (replyp->status);
+
+	/*
+	 * XXX Handle list
+	 */
+
+
+	/*
+	 * XXX Handle list
+	 */
+
+	retcount = replyp->retcount;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_close_ret __P((DB *, u_int32_t, __db_close_reply *));
+ */
+int
+__dbcl_db_close_ret(dbp, flags, replyp)
+	DB * dbp;
+	u_int32_t flags;
+	__db_close_reply *replyp;
+{
+	int ret;
+
+	if (replyp->status != 0)
+		return (replyp->status);
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_create_ret __P((DB *, DB_ENV *, u_int32_t,
+ * PUBLIC:      __db_create_reply *));
+ */
+int
+__dbcl_db_create_ret(dbp, dbenv, flags, replyp)
+	DB * dbp;
+	DB_ENV * dbenv;
+	u_int32_t flags;
+	__db_create_reply *replyp;
+{
+	int ret;
+	long db;
+
+	if (replyp->status != 0)
+		return (replyp->status);
+	db = replyp->dbcl_id;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_get_ret __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t,
+ * PUBLIC:      __db_get_reply *));
+ */
+int
+__dbcl_db_get_ret(dbp, txnp, key, data, flags, replyp)
+	DB * dbp;
+	DB_TXN * txnp;
+	DBT * key;
+	DBT * data;
+	u_int32_t flags;
+	__db_get_reply *replyp;
+{
+	int ret;
+	/* DBT key; */
+	/* DBT data; */
+
+	if (replyp->status != 0)
+		return (replyp->status);
+	/* Handle replyp->keydata; */
+	/* Handle replyp->datadata; */
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_key_range_ret __P((DB *, DB_TXN *, DBT *,
+ * PUBLIC:      DB_KEY_RANGE *, u_int32_t, __db_key_range_reply *));
+ */
+int
+__dbcl_db_key_range_ret(dbp, txnp, key, range, flags, replyp)
+	DB * dbp;
+	DB_TXN * txnp;
+	DBT * key;
+	DB_KEY_RANGE * range;
+	u_int32_t flags;
+	__db_key_range_reply *replyp;
+{
+	int ret;
+	double less;
+	double equal;
+	double greater;
+
+	if (replyp->status != 0)
+		return (replyp->status);
+	less = replyp->less;
+	equal = replyp->equal;
+	greater = replyp->greater;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_open_ret __P((DB *, DB_TXN *, const char *,
+ * PUBLIC:      const char *, DBTYPE, u_int32_t, int, __db_open_reply *));
+ */
+int
+__dbcl_db_open_ret(dbp, txnp, name, subdb, type, flags, mode, replyp)
+	DB * dbp;
+	DB_TXN * txnp;
+	const char * name;
+	const char * subdb;
+	DBTYPE type;
+	u_int32_t flags;
+	int mode;
+	__db_open_reply *replyp;
+{
+	int ret;
+	long db;
+	DBTYPE type;
+	int lorder;
+
+	if (replyp->status != 0)
+		return (replyp->status);
+	db = replyp->dbcl_id;
+	type = replyp->type;
+	lorder = replyp->lorder;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_pget_ret __P((DB *, DB_TXN *, DBT *, DBT *, DBT *,
+ * PUBLIC:      u_int32_t, __db_pget_reply *));
+ */
+int
+__dbcl_db_pget_ret(dbp, txnp, skey, pkey, data, flags, replyp)
+	DB * dbp;
+	DB_TXN * txnp;
+	DBT * skey;
+	DBT * pkey;
+	DBT * data;
+	u_int32_t flags;
+	__db_pget_reply *replyp;
+{
+	int ret;
+	/* DBT skey; */
+	/* DBT pkey; */
+	/* DBT data; */
+
+	if (replyp->status != 0)
+		return (replyp->status);
+	/* Handle replyp->skeydata; */
+	/* Handle replyp->pkeydata; */
+	/* Handle replyp->datadata; */
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_put_ret __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t,
+ * PUBLIC:      __db_put_reply *));
+ */
+int
+__dbcl_db_put_ret(dbp, txnp, key, data, flags, replyp)
+	DB * dbp;
+	DB_TXN * txnp;
+	DBT * key;
+	DBT * data;
+	u_int32_t flags;
+	__db_put_reply *replyp;
+{
+	int ret;
+	/* DBT key; */
+
+	if (replyp->status != 0)
+		return (replyp->status);
+	/* Handle replyp->keydata; */
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_remove_ret __P((DB *, const char *, const char *,
+ * PUBLIC:      u_int32_t, __db_remove_reply *));
+ */
+int
+__dbcl_db_remove_ret(dbp, name, subdb, flags, replyp)
+	DB * dbp;
+	const char * name;
+	const char * subdb;
+	u_int32_t flags;
+	__db_remove_reply *replyp;
+{
+	int ret;
+
+	if (replyp->status != 0)
+		return (replyp->status);
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_rename_ret __P((DB *, const char *, const char *,
+ * PUBLIC:      const char *, u_int32_t, __db_rename_reply *));
+ */
+int
+__dbcl_db_rename_ret(dbp, name, subdb, newname, flags, replyp)
+	DB * dbp;
+	const char * name;
+	const char * subdb;
+	const char * newname;
+	u_int32_t flags;
+	__db_rename_reply *replyp;
+{
+	int ret;
+
+	if (replyp->status != 0)
+		return (replyp->status);
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_stat_ret __P((DB *, DB_TXN *, void *, u_int32_t,
+ * PUBLIC:      __db_stat_reply *));
+ */
+int
+__dbcl_db_stat_ret(dbp, txnp, sp, flags, replyp)
+	DB * dbp;
+	DB_TXN * txnp;
+	void * sp;
+	u_int32_t flags;
+	__db_stat_reply *replyp;
+{
+	int ret;
+	u_int32_t *__db_stats;
+
+	if (replyp->status != 0)
+		return (replyp->status);
+
+	/*
+	 * XXX Handle list
+	 */
+
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_truncate_ret __P((DB *, DB_TXN *, u_int32_t  *,
+ * PUBLIC:      u_int32_t, __db_truncate_reply *));
+ */
+int
+__dbcl_db_truncate_ret(dbp, txnp, countp, flags, replyp)
+	DB * dbp;
+	DB_TXN * txnp;
+	u_int32_t  * countp;
+	u_int32_t flags;
+	__db_truncate_reply *replyp;
+{
+	int ret;
+	u_int32_t count;
+
+	if (replyp->status != 0)
+		return (replyp->status);
+	count = replyp->count;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_cursor_ret __P((DB *, DB_TXN *, DBC **, u_int32_t,
+ * PUBLIC:      __db_cursor_reply *));
+ */
+int
+__dbcl_db_cursor_ret(dbp, txnp, dbcpp, flags, replyp)
+	DB * dbp;
+	DB_TXN * txnp;
+	DBC ** dbcpp;
+	u_int32_t flags;
+	__db_cursor_reply *replyp;
+{
+	int ret;
+	long dbcid;
+
+	if (replyp->status != 0)
+		return (replyp->status);
+	dbcid = replyp->dbcidcl_id;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_join_ret __P((DB *, DBC **, DBC **, u_int32_t,
+ * PUBLIC:      __db_join_reply *));
+ */
+int
+__dbcl_db_join_ret(dbp, curs, dbcp, flags, replyp)
+	DB * dbp;
+	DBC ** curs;
+	DBC ** dbcp;
+	u_int32_t flags;
+	__db_join_reply *replyp;
+{
+	int ret;
+	long dbcid;
+
+	if (replyp->status != 0)
+		return (replyp->status);
+	dbcid = replyp->dbcidcl_id;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_dbc_close_ret __P((DBC *, __dbc_close_reply *));
+ */
+int
+__dbcl_dbc_close_ret(dbc, replyp)
+	DBC * dbc;
+	__dbc_close_reply *replyp;
+{
+	int ret;
+
+	if (replyp->status != 0)
+		return (replyp->status);
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_dbc_count_ret __P((DBC *, db_recno_t *, u_int32_t,
+ * PUBLIC:      __dbc_count_reply *));
+ */
+int
+__dbcl_dbc_count_ret(dbc, countp, flags, replyp)
+	DBC * dbc;
+	db_recno_t * countp;
+	u_int32_t flags;
+	__dbc_count_reply *replyp;
+{
+	int ret;
+	db_recno_t dupcount;
+
+	if (replyp->status != 0)
+		return (replyp->status);
+	dupcount = replyp->dupcount;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_dbc_dup_ret __P((DBC *, DBC **, u_int32_t,
+ * PUBLIC:      __dbc_dup_reply *));
+ */
+int
+__dbcl_dbc_dup_ret(dbc, dbcp, flags, replyp)
+	DBC * dbc;
+	DBC ** dbcp;
+	u_int32_t flags;
+	__dbc_dup_reply *replyp;
+{
+	int ret;
+	long dbcid;
+
+	if (replyp->status != 0)
+		return (replyp->status);
+	dbcid = replyp->dbcidcl_id;
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_dbc_get_ret __P((DBC *, DBT *, DBT *, u_int32_t,
+ * PUBLIC:      __dbc_get_reply *));
+ */
+int
+__dbcl_dbc_get_ret(dbc, key, data, flags, replyp)
+	DBC * dbc;
+	DBT * key;
+	DBT * data;
+	u_int32_t flags;
+	__dbc_get_reply *replyp;
+{
+	int ret;
+	/* DBT key; */
+	/* DBT data; */
+
+	if (replyp->status != 0)
+		return (replyp->status);
+	/* Handle replyp->keydata; */
+	/* Handle replyp->datadata; */
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_dbc_pget_ret __P((DBC *, DBT *, DBT *, DBT *, u_int32_t,
+ * PUBLIC:      __dbc_pget_reply *));
+ */
+int
+__dbcl_dbc_pget_ret(dbc, skey, pkey, data, flags, replyp)
+	DBC * dbc;
+	DBT * skey;
+	DBT * pkey;
+	DBT * data;
+	u_int32_t flags;
+	__dbc_pget_reply *replyp;
+{
+	int ret;
+	/* DBT skey; */
+	/* DBT pkey; */
+	/* DBT data; */
+
+	if (replyp->status != 0)
+		return (replyp->status);
+	/* Handle replyp->skeydata; */
+	/* Handle replyp->pkeydata; */
+	/* Handle replyp->datadata; */
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	return (replyp->status);
+}
+
+/*
+ * PUBLIC: int __dbcl_dbc_put_ret __P((DBC *, DBT *, DBT *, u_int32_t,
+ * PUBLIC:      __dbc_put_reply *));
+ */
+int
+__dbcl_dbc_put_ret(dbc, key, data, flags, replyp)
+	DBC * dbc;
+	DBT * key;
+	DBT * data;
+	u_int32_t flags;
+	__dbc_put_reply *replyp;
+{
+	int ret;
+	/* DBT key; */
+
+	if (replyp->status != 0)
+		return (replyp->status);
+	/* Handle replyp->keydata; */
+
+	/*
+	 * XXX Code goes here
+	 */
+
+	return (replyp->status);
+}
+
diff --git a/storage/bdb/dist/template/rec_btree b/storage/bdb/dist/template/rec_btree
new file mode 100644
index 0000000000000000000000000000000000000000..0b2c96182c40aa8d05abf608637a948d421a73ee
--- /dev/null
+++ b/storage/bdb/dist/template/rec_btree
@@ -0,0 +1,633 @@
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/__bam.h"
+#include "dbinc/log.h"
+
+/*
+ * __bam_split_recover --
+ *	Recovery function for split.
+ *
+ * PUBLIC: int __bam_split_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__bam_split_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__bam_split_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__bam_split_print);
+	REC_INTRO(__bam_split_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __bam_rsplit_recover --
+ *	Recovery function for rsplit.
+ *
+ * PUBLIC: int __bam_rsplit_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__bam_rsplit_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__bam_rsplit_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__bam_rsplit_print);
+	REC_INTRO(__bam_rsplit_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __bam_adj_recover --
+ *	Recovery function for adj.
+ *
+ * PUBLIC: int __bam_adj_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__bam_adj_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__bam_adj_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__bam_adj_print);
+	REC_INTRO(__bam_adj_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __bam_cadjust_recover --
+ *	Recovery function for cadjust.
+ *
+ * PUBLIC: int __bam_cadjust_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__bam_cadjust_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__bam_cadjust_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__bam_cadjust_print);
+	REC_INTRO(__bam_cadjust_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __bam_cdel_recover --
+ *	Recovery function for cdel.
+ *
+ * PUBLIC: int __bam_cdel_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__bam_cdel_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__bam_cdel_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__bam_cdel_print);
+	REC_INTRO(__bam_cdel_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __bam_repl_recover --
+ *	Recovery function for repl.
+ *
+ * PUBLIC: int __bam_repl_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__bam_repl_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__bam_repl_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__bam_repl_print);
+	REC_INTRO(__bam_repl_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __bam_root_recover --
+ *	Recovery function for root.
+ *
+ * PUBLIC: int __bam_root_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__bam_root_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__bam_root_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__bam_root_print);
+	REC_INTRO(__bam_root_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __bam_curadj_recover --
+ *	Recovery function for curadj.
+ *
+ * PUBLIC: int __bam_curadj_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__bam_curadj_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__bam_curadj_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__bam_curadj_print);
+	REC_INTRO(__bam_curadj_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __bam_rcuradj_recover --
+ *	Recovery function for rcuradj.
+ *
+ * PUBLIC: int __bam_rcuradj_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__bam_rcuradj_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__bam_rcuradj_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__bam_rcuradj_print);
+	REC_INTRO(__bam_rcuradj_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __bam_relink_recover --
+ *	Recovery function for relink.
+ *
+ * PUBLIC: int __bam_relink_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__bam_relink_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__bam_relink_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__bam_relink_print);
+	REC_INTRO(__bam_relink_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
diff --git a/storage/bdb/dist/template/rec_crdel b/storage/bdb/dist/template/rec_crdel
new file mode 100644
index 0000000000000000000000000000000000000000..430806e16287030d7b1e7c51f3bef6522ad7ca62
--- /dev/null
+++ b/storage/bdb/dist/template/rec_crdel
@@ -0,0 +1,75 @@
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/__crdel.h"
+#include "dbinc/log.h"
+
+/*
+ * __crdel_metasub_recover --
+ *	Recovery function for metasub.
+ *
+ * PUBLIC: int __crdel_metasub_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__crdel_metasub_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__crdel_metasub_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__crdel_metasub_print);
+	REC_INTRO(__crdel_metasub_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
diff --git a/storage/bdb/dist/template/rec_db b/storage/bdb/dist/template/rec_db
new file mode 100644
index 0000000000000000000000000000000000000000..5c4c8f08d94882b11c3c2729886ed15234e1f1a8
--- /dev/null
+++ b/storage/bdb/dist/template/rec_db
@@ -0,0 +1,757 @@
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/__db.h"
+#include "dbinc/log.h"
+
+/*
+ * __db_addrem_recover --
+ *	Recovery function for addrem.
+ *
+ * PUBLIC: int __db_addrem_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__db_addrem_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__db_addrem_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__db_addrem_print);
+	REC_INTRO(__db_addrem_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __db_big_recover --
+ *	Recovery function for big.
+ *
+ * PUBLIC: int __db_big_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__db_big_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__db_big_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__db_big_print);
+	REC_INTRO(__db_big_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __db_ovref_recover --
+ *	Recovery function for ovref.
+ *
+ * PUBLIC: int __db_ovref_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__db_ovref_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__db_ovref_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__db_ovref_print);
+	REC_INTRO(__db_ovref_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __db_debug_recover --
+ *	Recovery function for debug.
+ *
+ * PUBLIC: int __db_debug_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__db_debug_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__db_debug_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__db_debug_print);
+	REC_INTRO(__db_debug_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __db_noop_recover --
+ *	Recovery function for noop.
+ *
+ * PUBLIC: int __db_noop_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__db_noop_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__db_noop_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__db_noop_print);
+	REC_INTRO(__db_noop_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __db_pg_alloc_recover --
+ *	Recovery function for pg_alloc.
+ *
+ * PUBLIC: int __db_pg_alloc_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__db_pg_alloc_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__db_pg_alloc_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__db_pg_alloc_print);
+	REC_INTRO(__db_pg_alloc_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __db_pg_free_recover --
+ *	Recovery function for pg_free.
+ *
+ * PUBLIC: int __db_pg_free_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__db_pg_free_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__db_pg_free_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__db_pg_free_print);
+	REC_INTRO(__db_pg_free_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __db_cksum_recover --
+ *	Recovery function for cksum.
+ *
+ * PUBLIC: int __db_cksum_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__db_cksum_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__db_cksum_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__db_cksum_print);
+	REC_INTRO(__db_cksum_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __db_pg_freedata_recover --
+ *	Recovery function for pg_freedata.
+ *
+ * PUBLIC: int __db_pg_freedata_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__db_pg_freedata_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__db_pg_freedata_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__db_pg_freedata_print);
+	REC_INTRO(__db_pg_freedata_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __db_pg_prepare_recover --
+ *	Recovery function for pg_prepare.
+ *
+ * PUBLIC: int __db_pg_prepare_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__db_pg_prepare_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__db_pg_prepare_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__db_pg_prepare_print);
+	REC_INTRO(__db_pg_prepare_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __db_pg_new_recover --
+ *	Recovery function for pg_new.
+ *
+ * PUBLIC: int __db_pg_new_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__db_pg_new_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__db_pg_new_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__db_pg_new_print);
+	REC_INTRO(__db_pg_new_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __db_pg_init_recover --
+ *	Recovery function for pg_init.
+ *
+ * PUBLIC: int __db_pg_init_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__db_pg_init_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__db_pg_init_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__db_pg_init_print);
+	REC_INTRO(__db_pg_init_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
diff --git a/storage/bdb/dist/template/rec_dbreg b/storage/bdb/dist/template/rec_dbreg
new file mode 100644
index 0000000000000000000000000000000000000000..bbdf19d5ffcd4996e8877e2c79f5b6fee7224e14
--- /dev/null
+++ b/storage/bdb/dist/template/rec_dbreg
@@ -0,0 +1,75 @@
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/__dbreg.h"
+#include "dbinc/log.h"
+
+/*
+ * __dbreg_register_recover --
+ *	Recovery function for register.
+ *
+ * PUBLIC: int __dbreg_register_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__dbreg_register_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__dbreg_register_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__dbreg_register_print);
+	REC_INTRO(__dbreg_register_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
diff --git a/storage/bdb/dist/template/rec_fileops b/storage/bdb/dist/template/rec_fileops
new file mode 100644
index 0000000000000000000000000000000000000000..c1487835ea9c9377e4bca3865c4038caed1ae193
--- /dev/null
+++ b/storage/bdb/dist/template/rec_fileops
@@ -0,0 +1,323 @@
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/__fop.h"
+#include "dbinc/log.h"
+
+/*
+ * __fop_create_recover --
+ *	Recovery function for create.
+ *
+ * PUBLIC: int __fop_create_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__fop_create_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__fop_create_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__fop_create_print);
+	REC_INTRO(__fop_create_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __fop_remove_recover --
+ *	Recovery function for remove.
+ *
+ * PUBLIC: int __fop_remove_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__fop_remove_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__fop_remove_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__fop_remove_print);
+	REC_INTRO(__fop_remove_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __fop_write_recover --
+ *	Recovery function for write.
+ *
+ * PUBLIC: int __fop_write_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__fop_write_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__fop_write_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__fop_write_print);
+	REC_INTRO(__fop_write_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __fop_rename_recover --
+ *	Recovery function for rename.
+ *
+ * PUBLIC: int __fop_rename_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__fop_rename_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__fop_rename_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__fop_rename_print);
+	REC_INTRO(__fop_rename_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __fop_file_remove_recover --
+ *	Recovery function for file_remove.
+ *
+ * PUBLIC: int __fop_file_remove_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__fop_file_remove_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__fop_file_remove_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__fop_file_remove_print);
+	REC_INTRO(__fop_file_remove_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
diff --git a/storage/bdb/dist/template/rec_hash b/storage/bdb/dist/template/rec_hash
new file mode 100644
index 0000000000000000000000000000000000000000..b5160d50a5634ad182ead63270db5c97a866f67d
--- /dev/null
+++ b/storage/bdb/dist/template/rec_hash
@@ -0,0 +1,571 @@
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/__ham.h"
+#include "dbinc/log.h"
+
+/*
+ * __ham_insdel_recover --
+ *	Recovery function for insdel.
+ *
+ * PUBLIC: int __ham_insdel_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__ham_insdel_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__ham_insdel_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__ham_insdel_print);
+	REC_INTRO(__ham_insdel_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __ham_newpage_recover --
+ *	Recovery function for newpage.
+ *
+ * PUBLIC: int __ham_newpage_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__ham_newpage_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__ham_newpage_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__ham_newpage_print);
+	REC_INTRO(__ham_newpage_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __ham_splitdata_recover --
+ *	Recovery function for splitdata.
+ *
+ * PUBLIC: int __ham_splitdata_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__ham_splitdata_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__ham_splitdata_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__ham_splitdata_print);
+	REC_INTRO(__ham_splitdata_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __ham_replace_recover --
+ *	Recovery function for replace.
+ *
+ * PUBLIC: int __ham_replace_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__ham_replace_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__ham_replace_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__ham_replace_print);
+	REC_INTRO(__ham_replace_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __ham_copypage_recover --
+ *	Recovery function for copypage.
+ *
+ * PUBLIC: int __ham_copypage_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__ham_copypage_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__ham_copypage_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__ham_copypage_print);
+	REC_INTRO(__ham_copypage_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __ham_metagroup_recover --
+ *	Recovery function for metagroup.
+ *
+ * PUBLIC: int __ham_metagroup_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__ham_metagroup_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__ham_metagroup_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__ham_metagroup_print);
+	REC_INTRO(__ham_metagroup_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __ham_groupalloc_recover --
+ *	Recovery function for groupalloc.
+ *
+ * PUBLIC: int __ham_groupalloc_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__ham_groupalloc_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__ham_groupalloc_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__ham_groupalloc_print);
+	REC_INTRO(__ham_groupalloc_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __ham_curadj_recover --
+ *	Recovery function for curadj.
+ *
+ * PUBLIC: int __ham_curadj_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__ham_curadj_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__ham_curadj_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__ham_curadj_print);
+	REC_INTRO(__ham_curadj_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __ham_chgpg_recover --
+ *	Recovery function for chgpg.
+ *
+ * PUBLIC: int __ham_chgpg_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__ham_chgpg_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__ham_chgpg_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__ham_chgpg_print);
+	REC_INTRO(__ham_chgpg_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
diff --git a/storage/bdb/dist/template/rec_qam b/storage/bdb/dist/template/rec_qam
new file mode 100644
index 0000000000000000000000000000000000000000..ffe0d63e4454681ecd7e37cc8244cbd082a09738
--- /dev/null
+++ b/storage/bdb/dist/template/rec_qam
@@ -0,0 +1,323 @@
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/__qam.h"
+#include "dbinc/log.h"
+
+/*
+ * __qam_incfirst_recover --
+ *	Recovery function for incfirst.
+ *
+ * PUBLIC: int __qam_incfirst_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__qam_incfirst_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__qam_incfirst_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__qam_incfirst_print);
+	REC_INTRO(__qam_incfirst_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __qam_mvptr_recover --
+ *	Recovery function for mvptr.
+ *
+ * PUBLIC: int __qam_mvptr_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__qam_mvptr_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__qam_mvptr_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__qam_mvptr_print);
+	REC_INTRO(__qam_mvptr_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __qam_del_recover --
+ *	Recovery function for del.
+ *
+ * PUBLIC: int __qam_del_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__qam_del_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__qam_del_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__qam_del_print);
+	REC_INTRO(__qam_del_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __qam_add_recover --
+ *	Recovery function for add.
+ *
+ * PUBLIC: int __qam_add_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__qam_add_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__qam_add_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__qam_add_print);
+	REC_INTRO(__qam_add_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __qam_delext_recover --
+ *	Recovery function for delext.
+ *
+ * PUBLIC: int __qam_delext_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__qam_delext_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__qam_delext_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__qam_delext_print);
+	REC_INTRO(__qam_delext_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
diff --git a/storage/bdb/dist/template/rec_rep b/storage/bdb/dist/template/rec_rep
new file mode 100644
index 0000000000000000000000000000000000000000..872812cd06941bd7c375e156237f52ab14688521
--- /dev/null
+++ b/storage/bdb/dist/template/rec_rep
@@ -0,0 +1,13 @@
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/__rep.h"
+#include "dbinc/log.h"
+
diff --git a/storage/bdb/dist/template/rec_txn b/storage/bdb/dist/template/rec_txn
new file mode 100644
index 0000000000000000000000000000000000000000..e3ee4c89648e405a5c68e2cdbd11d87b89a8d96a
--- /dev/null
+++ b/storage/bdb/dist/template/rec_txn
@@ -0,0 +1,323 @@
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/__txn.h"
+#include "dbinc/log.h"
+
+/*
+ * __txn_regop_recover --
+ *	Recovery function for regop.
+ *
+ * PUBLIC: int __txn_regop_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__txn_regop_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__txn_regop_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__txn_regop_print);
+	REC_INTRO(__txn_regop_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __txn_ckp_recover --
+ *	Recovery function for ckp.
+ *
+ * PUBLIC: int __txn_ckp_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__txn_ckp_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__txn_ckp_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__txn_ckp_print);
+	REC_INTRO(__txn_ckp_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __txn_child_recover --
+ *	Recovery function for child.
+ *
+ * PUBLIC: int __txn_child_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__txn_child_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__txn_child_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__txn_child_print);
+	REC_INTRO(__txn_child_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __txn_xa_regop_recover --
+ *	Recovery function for xa_regop.
+ *
+ * PUBLIC: int __txn_xa_regop_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__txn_xa_regop_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__txn_xa_regop_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__txn_xa_regop_print);
+	REC_INTRO(__txn_xa_regop_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
+/*
+ * __txn_recycle_recover --
+ *	Recovery function for recycle.
+ *
+ * PUBLIC: int __txn_recycle_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__txn_recycle_recover(dbenv, dbtp, lsnp, op, info)
+	DB_ENV *dbenv;
+	DBT *dbtp;
+	DB_LSN *lsnp;
+	db_recops op;
+	void *info;
+{
+	__txn_recycle_args *argp;
+	DB *file_dbp;
+	DBC *dbc;
+	DB_MPOOLFILE *mpf;
+	PAGE *pagep;
+	int cmp_n, cmp_p, modified, ret;
+
+	REC_PRINT(__txn_recycle_print);
+	REC_INTRO(__txn_recycle_read, 1);
+
+	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
+		if (DB_REDO(op)) {
+			if ((ret = mpf->get(mpf,
+			    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+				goto out;
+		} else {
+			*lsnp = argp->prev_lsn;
+			ret = 0;
+			goto out;
+		}
+
+	modified = 0;
+	cmp_n = log_compare(lsnp, &LSN(pagep));
+
+	/*
+	 * Use this when there is something like "pagelsn" in the argp
+	 * structure.  Sometimes, you might need to compare meta-data
+	 * lsn's instead.
+	 *
+	 * cmp_p = log_compare(&LSN(pagep), argp->pagelsn);
+	 */
+	if (cmp_p == 0 && DB_REDO(op)) {
+		/* Need to redo update described. */
+		modified = 1;
+	} else if (cmp_n == 0 && !DB_REDO(op)) {
+		/* Need to undo update described. */
+		modified = 1;
+	}
+	if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))
+		goto out;
+
+	*lsnp = argp->prev_lsn;
+	ret = 0;
+
+out:	REC_CLOSE;
+}
+
diff --git a/storage/bdb/dist/vx_2.0/BerkeleyDB.wpj b/storage/bdb/dist/vx_2.0/BerkeleyDB.wpj
index 78684d900672b7652f267c50bddeb4ab5d30d665..692d1b40bb69640cd68e036ae3d4030ead7fe2b9 100644
--- a/storage/bdb/dist/vx_2.0/BerkeleyDB.wpj
+++ b/storage/bdb/dist/vx_2.0/BerkeleyDB.wpj
@@ -1,7 +1,7 @@
 Document file - DO NOT EDIT
 
 <BEGIN> BUILD_PENTIUM_debug_BUILDRULE
-BerkeleyDB.out
+BerkeleyDB20.out
 <END>
 
 <BEGIN> BUILD_PENTIUM_debug_MACRO_AR
@@ -9,7 +9,7 @@ ar386
 <END>
 
 <BEGIN> BUILD_PENTIUM_debug_MACRO_ARCHIVE
-$(PRJ_DIR)/PENTIUMgnu/BerkeleyDB_sim.a
+$(PRJ_DIR)/PENTIUMgnu/BerkeleyDB20_sim.a
 <END>
 
 <BEGIN> BUILD_PENTIUM_debug_MACRO_AS
@@ -109,7 +109,7 @@ size386
 <END>
 
 <BEGIN> BUILD_PENTIUM_release_BUILDRULE
-BerkeleyDB.out
+BerkeleyDB20.out
 <END>
 
 <BEGIN> BUILD_PENTIUM_release_MACRO_AR
@@ -117,7 +117,7 @@ ar386
 <END>
 
 <BEGIN> BUILD_PENTIUM_release_MACRO_ARCHIVE
-$(PRJ_DIR)/PENTIUMgnu/BerkeleyDB_sim.a
+$(PRJ_DIR)/PENTIUMgnu/BerkeleyDB20_sim.a
 <END>
 
 <BEGIN> BUILD_PENTIUM_release_MACRO_AS
@@ -143,7 +143,7 @@ cc386
 	-DCPU=PENTIUM \
 	-O2 \
 	-I$(PRJ_DIR) \
-	-I$(PRJ_DIR)/.. 
+	-I$(PRJ_DIR)/..
 <END>
 
 <BEGIN> BUILD_PENTIUM_release_MACRO_CFLAGS_AS
@@ -217,11 +217,11 @@ size386
 ::tc_PENTIUMgnu
 <END>
 
-<BEGIN> BUILD_RULE_BerkeleyDB.out
+<BEGIN> BUILD_RULE_BerkeleyDB20.out
 
 <END>
 
-<BEGIN> BUILD_RULE_BerkeleyDB_sim.out
+<BEGIN> BUILD_RULE_BerkeleyDB20_sim.out
 
 <END>
 
diff --git a/storage/bdb/dist/vx_2.0/BerkeleyDBsmall.wpj b/storage/bdb/dist/vx_2.0/BerkeleyDBsmall.wpj
new file mode 100644
index 0000000000000000000000000000000000000000..3c9fd350fa1882e148f0ab5831bea35689cc1813
--- /dev/null
+++ b/storage/bdb/dist/vx_2.0/BerkeleyDBsmall.wpj
@@ -0,0 +1,251 @@
+Document file - DO NOT EDIT
+
+<BEGIN> BUILD_PENTIUM_debug_BUILDRULE
+BerkeleyDB20small.out
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_AR
+ar386
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_ARCHIVE
+$(PRJ_DIR)/PENTIUMgnu/BerkeleyDB20small_sim.a
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_AS
+cc386
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_CC
+cc386
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_CFLAGS
+-g \
+	-mpentium \
+	-ansi \
+	-nostdinc \
+	-DRW_MULTI_THREAD \
+	-D_REENTRANT \
+	-fvolatile \
+	-nostdlib \
+	-fno-builtin \
+	-fno-defer-pop \
+	-I. \
+	-I$(WIND_BASE)/target/h \
+	-DCPU=PENTIUM \
+	-O0 \
+	-I$(PRJ_DIR) \
+	-I$(PRJ_DIR)/.. \
+	-DDIAGNOSTIC \
+	-DDEBUG
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_CFLAGS_AS
+-g \
+	-mpentium \
+	-ansi \
+	-nostdinc \
+	-fvolatile \
+	-nostdlib \
+	-fno-builtin \
+	-fno-defer-pop \
+	-P \
+	-x \
+	assembler-with-cpp \
+	-I. \
+	-I$(WIND_BASE)/target/h \
+	-DCPU=PENTIUM
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_CPP
+cc386 -E -P -xc
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_LD
+ld386
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_LDFLAGS
+-X -N
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_LD_PARTIAL_FLAGS
+-X -r
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_NM
+nm386 -g
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_OPTION_DEFINE_MACRO
+-D
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_OPTION_INCLUDE_DIR
+-I
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_POST_BUILD_RULE
+
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_PRJ_LIBS
+
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_SIZE
+size386
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_RO_DEPEND_PATH
+{$(WIND_BASE)/target/h/} \
+	{$(WIND_BASE)/target/src/} \
+	{$(WIND_BASE)/target/config/}
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_TC
+::tc_PENTIUMgnu
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_BUILDRULE
+BerkeleyDB20small.out
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_AR
+ar386
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_ARCHIVE
+$(PRJ_DIR)/PENTIUMgnu/BerkeleyDB20small_sim.a
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_AS
+cc386
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_CC
+cc386
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_CFLAGS
+-mpentium \
+	-ansi \
+	-nostdinc \
+	-DRW_MULTI_THREAD \
+	-D_REENTRANT \
+	-fvolatile \
+	-nostdlib \
+	-fno-builtin \
+	-fno-defer-pop \
+	-I. \
+	-I$(WIND_BASE)/target/h \
+	-DCPU=PENTIUM \
+	-O2 \
+	-I$(PRJ_DIR) \
+	-I$(PRJ_DIR)/..
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_CFLAGS_AS
+-g \
+	-mpentium \
+	-ansi \
+	-nostdinc \
+	-fvolatile \
+	-nostdlib \
+	-fno-builtin \
+	-fno-defer-pop \
+	-P \
+	-x \
+	assembler-with-cpp \
+	-I. \
+	-I$(WIND_BASE)/target/h \
+	-DCPU=PENTIUM
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_CPP
+cc386 -E -P -xc
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_LD
+ld386
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_LDDEPS
+
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_LDFLAGS
+-X -N
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_LD_PARTIAL_FLAGS
+-X -r
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_NM
+nm386 -g
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_OPTION_DEFINE_MACRO
+-D
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_OPTION_INCLUDE_DIR
+-I
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_POST_BUILD_RULE
+
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_PRJ_LIBS
+
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_SIZE
+size386
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_RO_DEPEND_PATH
+{$(WIND_BASE)/target/h/} \
+	{$(WIND_BASE)/target/src/} \
+	{$(WIND_BASE)/target/config/}
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_TC
+::tc_PENTIUMgnu
+<END>
+
+<BEGIN> BUILD_RULE_BerkeleyDB20small.out
+
+<END>
+
+<BEGIN> BUILD_RULE_BerkeleyDB20small_sim.out
+
+<END>
+
+<BEGIN> BUILD_RULE_archive
+
+<END>
+
+<BEGIN> BUILD_RULE_objects
+
+<END>
+
+<BEGIN> BUILD__CURRENT
+PENTIUM_debug
+<END>
+
+<BEGIN> BUILD__LIST
+PENTIUM_release PENTIUM_debug
+<END>
+
+<BEGIN> CORE_INFO_TYPE
+::prj_vxApp
+<END>
+
+<BEGIN> CORE_INFO_VERSION
+2.0
+<END>
+
diff --git a/storage/bdb/dist/vx_2.0/wpj.in b/storage/bdb/dist/vx_2.0/wpj.in
index 2b942bb562cad65a64ed14d02aa3639d6cbb688b..a38cf7251a689466258782f817959886cc003793 100644
--- a/storage/bdb/dist/vx_2.0/wpj.in
+++ b/storage/bdb/dist/vx_2.0/wpj.in
@@ -1,7 +1,7 @@
 Document file - DO NOT EDIT
 
 <BEGIN> BUILD_PENTIUMgnu_BUILDRULE
-__DB_APPLICATION_NAME__.out
+__DB_APPLICATION_NAME__20.out
 <END>
 
 <BEGIN> BUILD_PENTIUMgnu_MACRO_AR
@@ -9,7 +9,7 @@ ar386
 <END>
 
 <BEGIN> BUILD_PENTIUMgnu_MACRO_ARCHIVE
-$(PRJ_DIR)/PENTIUMgnu/__DB_APPLICATION_NAME__.a
+$(PRJ_DIR)/PENTIUMgnu/__DB_APPLICATION_NAME__20.a
 <END>
 
 <BEGIN> BUILD_PENTIUMgnu_MACRO_AS
@@ -111,7 +111,7 @@ size386
 
 <END>
 
-<BEGIN> BUILD_RULE___DB_APPLICATION_NAME__.out
+<BEGIN> BUILD_RULE___DB_APPLICATION_NAME__20.out
 
 <END>
 
diff --git a/storage/bdb/dist/vx_2.2/BerkeleyDB.wpj b/storage/bdb/dist/vx_2.2/BerkeleyDB.wpj
new file mode 100644
index 0000000000000000000000000000000000000000..e27a231f76fbf33b41434632bafde5973596f666
--- /dev/null
+++ b/storage/bdb/dist/vx_2.2/BerkeleyDB.wpj
@@ -0,0 +1,310 @@
+Document file - DO NOT EDIT
+
+<BEGIN> BUILD_PENTIUM_debug_BUILDRULE
+BerkeleyDB22.out
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_AR
+arpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_ARCHIVE
+$(PRJ_DIR)/PENTIUM_debug/BerkeleyDB22.a
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_AS
+ccpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_CC
+ccpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_CC_ARCH_SPEC
+-mcpu=pentiumpro -march=pentiumpro
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_CFLAGS
+-g \
+	-mcpu=pentiumpro \
+	-march=pentiumpro \
+	-ansi \
+	-nostdlib \
+	-fno-builtin \
+	-fno-defer-pop \
+	-I. \
+	-I$(WIND_BASE)/target/h \
+	-DCPU=PENTIUM2 \
+	-DTOOL_FAMILY=gnu \
+	-DTOOL=gnu \
+	-O0 \
+	-I$(PRJ_DIR) \
+	-I$(PRJ_DIR)/.. \
+	-DDIAGNOSTIC \
+	-DDEBUG
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_CFLAGS_AS
+-g \
+	-mcpu=pentiumpro \
+	-march=pentiumpro \
+	-ansi \
+	-nostdlib \
+	-fno-builtin \
+	-fno-defer-pop \
+	-P \
+	-xassembler-with-cpp \
+	-I. \
+	-I$(WIND_BASE)/target/h \
+	-DCPU=PENTIUM2 \
+	-DTOOL_FAMILY=gnu \
+	-DTOOL=gnu
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_CPP
+ccpentium -E -P
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_HEX_FLAGS
+
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_LD
+ldpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_LDFLAGS
+-X -N
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_LD_PARTIAL
+ccpentium -r -nostdlib -Wl,-X
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_LD_PARTIAL_FLAGS
+-X -r
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_NM
+nmpentium -g
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_OPTION_DEFINE_MACRO
+-D
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_OPTION_DEPEND
+-M -w
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_OPTION_GENERATE_DEPENDENCY_FILE
+-MD
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_OPTION_INCLUDE_DIR
+-I
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_OPTION_LANG_C
+-xc
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_OPTION_UNDEFINE_MACRO
+-U
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_POST_BUILD_RULE
+
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_PRJ_LIBS
+
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_SIZE
+sizepentium
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_TOOL_FAMILY
+gnu
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_RO_DEPEND_PATH
+{$(WIND_BASE)/target/h/} \
+	{$(WIND_BASE)/target/src/} \
+	{$(WIND_BASE)/target/config/}
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_TC
+::tc_PENTIUM2gnu
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_BUILDRULE
+BerkeleyDB22.out
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_AR
+arpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_ARCHIVE
+$(PRJ_DIR)/PENTIUM_release/BerkeleyDB22.a
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_AS
+ccpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_CC
+ccpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_CC_ARCH_SPEC
+-mcpu=pentiumpro -march=pentiumpro
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_CFLAGS
+-g \
+	-mcpu=pentiumpro \
+	-march=pentiumpro \
+	-ansi \
+	-nostdlib \
+	-fno-builtin \
+	-fno-defer-pop \
+	-I. \
+	-I$(WIND_BASE)/target/h \
+	-DCPU=PENTIUM2 \
+	-DTOOL_FAMILY=gnu \
+	-DTOOL=gnu \
+	-O2 \
+	-I$(PRJ_DIR) \
+	-I$(PRJ_DIR)/..
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_CFLAGS_AS
+-g \
+	-mcpu=pentiumpro \
+	-march=pentiumpro \
+	-ansi \
+	-nostdlib \
+	-fno-builtin \
+	-fno-defer-pop \
+	-P \
+	-xassembler-with-cpp \
+	-I. \
+	-I$(WIND_BASE)/target/h \
+	-DCPU=PENTIUM2 \
+	-DTOOL_FAMILY=gnu \
+	-DTOOL=gnu
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_CPP
+ccpentium -E -P
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_HEX_FLAGS
+
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_LD
+ldpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_LDFLAGS
+-X -N
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_LD_PARTIAL
+ccpentium -r -nostdlib -Wl,-X
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_LD_PARTIAL_FLAGS
+-X -r
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_NM
+nmpentium -g
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_OPTION_DEFINE_MACRO
+-D
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_OPTION_DEPEND
+-M -w
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_OPTION_GENERATE_DEPENDENCY_FILE
+-MD
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_OPTION_INCLUDE_DIR
+-I
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_OPTION_LANG_C
+-xc
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_OPTION_UNDEFINE_MACRO
+-U
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_POST_BUILD_RULE
+
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_PRJ_LIBS
+
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_SIZE
+sizepentium
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_TOOL_FAMILY
+gnu
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_RO_DEPEND_PATH
+{$(WIND_BASE)/target/h/} \
+	{$(WIND_BASE)/target/src/} \
+	{$(WIND_BASE)/target/config/}
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_TC
+::tc_PENTIUM2gnu
+<END>
+
+<BEGIN> BUILD_RULE_BerkeleyDB22.out
+
+<END>
+
+<BEGIN> BUILD_RULE_BerkeleyDB22.pl
+
+<END>
+
+<BEGIN> BUILD_RULE_archive
+
+<END>
+
+<BEGIN> BUILD_RULE_objects
+
+<END>
+
+<BEGIN> BUILD__CURRENT
+PENTIUM_debug
+<END>
+
+<BEGIN> BUILD__LIST
+PENTIUM_release PENTIUM_debug
+<END>
+
+<BEGIN> CORE_INFO_TYPE
+::prj_vxApp
+<END>
+
+<BEGIN> CORE_INFO_VERSION
+2.2
+<END>
+
diff --git a/storage/bdb/dist/vx_2.2/BerkeleyDBsmall.wpj b/storage/bdb/dist/vx_2.2/BerkeleyDBsmall.wpj
new file mode 100644
index 0000000000000000000000000000000000000000..bfbdadc46a56820ca53be82f4445e2554f175394
--- /dev/null
+++ b/storage/bdb/dist/vx_2.2/BerkeleyDBsmall.wpj
@@ -0,0 +1,310 @@
+Document file - DO NOT EDIT
+
+<BEGIN> BUILD_PENTIUM_debug_BUILDRULE
+BerkeleyDB22small.out
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_AR
+arpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_ARCHIVE
+$(PRJ_DIR)/PENTIUM_debug/BerkeleyDB22small.a
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_AS
+ccpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_CC
+ccpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_CC_ARCH_SPEC
+-mcpu=pentiumpro -march=pentiumpro
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_CFLAGS
+-g \
+	-mcpu=pentiumpro \
+	-march=pentiumpro \
+	-ansi \
+	-nostdlib \
+	-fno-builtin \
+	-fno-defer-pop \
+	-I. \
+	-I$(WIND_BASE)/target/h \
+	-DCPU=PENTIUM2 \
+	-DTOOL_FAMILY=gnu \
+	-DTOOL=gnu \
+	-O0 \
+	-I$(PRJ_DIR) \
+	-I$(PRJ_DIR)/.. \
+	-DDIAGNOSTIC \
+	-DDEBUG
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_CFLAGS_AS
+-g \
+	-mcpu=pentiumpro \
+	-march=pentiumpro \
+	-ansi \
+	-nostdlib \
+	-fno-builtin \
+	-fno-defer-pop \
+	-P \
+	-xassembler-with-cpp \
+	-I. \
+	-I$(WIND_BASE)/target/h \
+	-DCPU=PENTIUM2 \
+	-DTOOL_FAMILY=gnu \
+	-DTOOL=gnu
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_CPP
+ccpentium -E -P
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_HEX_FLAGS
+
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_LD
+ldpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_LDFLAGS
+-X -N
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_LD_PARTIAL
+ccpentium -r -nostdlib -Wl,-X
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_LD_PARTIAL_FLAGS
+-X -r
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_NM
+nmpentium -g
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_OPTION_DEFINE_MACRO
+-D
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_OPTION_DEPEND
+-M -w
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_OPTION_GENERATE_DEPENDENCY_FILE
+-MD
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_OPTION_INCLUDE_DIR
+-I
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_OPTION_LANG_C
+-xc
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_OPTION_UNDEFINE_MACRO
+-U
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_POST_BUILD_RULE
+
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_PRJ_LIBS
+
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_SIZE
+sizepentium
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_MACRO_TOOL_FAMILY
+gnu
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_RO_DEPEND_PATH
+{$(WIND_BASE)/target/h/} \
+	{$(WIND_BASE)/target/src/} \
+	{$(WIND_BASE)/target/config/}
+<END>
+
+<BEGIN> BUILD_PENTIUM_debug_TC
+::tc_PENTIUM2gnu
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_BUILDRULE
+BerkeleyDB22small.out
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_AR
+arpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_ARCHIVE
+$(PRJ_DIR)/PENTIUM_release/BerkeleyDB22small.a
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_AS
+ccpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_CC
+ccpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_CC_ARCH_SPEC
+-mcpu=pentiumpro -march=pentiumpro
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_CFLAGS
+-g \
+	-mcpu=pentiumpro \
+	-march=pentiumpro \
+	-ansi \
+	-nostdlib \
+	-fno-builtin \
+	-fno-defer-pop \
+	-I. \
+	-I$(WIND_BASE)/target/h \
+	-DCPU=PENTIUM2 \
+	-DTOOL_FAMILY=gnu \
+	-DTOOL=gnu \
+	-O2 \
+	-I$(PRJ_DIR) \
+	-I$(PRJ_DIR)/..
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_CFLAGS_AS
+-g \
+	-mcpu=pentiumpro \
+	-march=pentiumpro \
+	-ansi \
+	-nostdlib \
+	-fno-builtin \
+	-fno-defer-pop \
+	-P \
+	-xassembler-with-cpp \
+	-I. \
+	-I$(WIND_BASE)/target/h \
+	-DCPU=PENTIUM2 \
+	-DTOOL_FAMILY=gnu \
+	-DTOOL=gnu
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_CPP
+ccpentium -E -P
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_HEX_FLAGS
+
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_LD
+ldpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_LDFLAGS
+-X -N
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_LD_PARTIAL
+ccpentium -r -nostdlib -Wl,-X
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_LD_PARTIAL_FLAGS
+-X -r
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_NM
+nmpentium -g
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_OPTION_DEFINE_MACRO
+-D
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_OPTION_DEPEND
+-M -w
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_OPTION_GENERATE_DEPENDENCY_FILE
+-MD
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_OPTION_INCLUDE_DIR
+-I
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_OPTION_LANG_C
+-xc
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_OPTION_UNDEFINE_MACRO
+-U
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_POST_BUILD_RULE
+
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_PRJ_LIBS
+
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_SIZE
+sizepentium
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_MACRO_TOOL_FAMILY
+gnu
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_RO_DEPEND_PATH
+{$(WIND_BASE)/target/h/} \
+	{$(WIND_BASE)/target/src/} \
+	{$(WIND_BASE)/target/config/}
+<END>
+
+<BEGIN> BUILD_PENTIUM_release_TC
+::tc_PENTIUM2gnu
+<END>
+
+<BEGIN> BUILD_RULE_BerkeleyDB22small.out
+
+<END>
+
+<BEGIN> BUILD_RULE_BerkeleyDB22small.pl
+
+<END>
+
+<BEGIN> BUILD_RULE_archive
+
+<END>
+
+<BEGIN> BUILD_RULE_objects
+
+<END>
+
+<BEGIN> BUILD__CURRENT
+PENTIUM_debug
+<END>
+
+<BEGIN> BUILD__LIST
+PENTIUM_release PENTIUM_debug
+<END>
+
+<BEGIN> CORE_INFO_TYPE
+::prj_vxApp
+<END>
+
+<BEGIN> CORE_INFO_VERSION
+2.2
+<END>
+
diff --git a/storage/bdb/dist/vx_2.2/wpj.in b/storage/bdb/dist/vx_2.2/wpj.in
new file mode 100644
index 0000000000000000000000000000000000000000..d883ef2b19345006b3988079551b937c09ca7691
--- /dev/null
+++ b/storage/bdb/dist/vx_2.2/wpj.in
@@ -0,0 +1,194 @@
+Document file - DO NOT EDIT
+
+<BEGIN> BUILD_PENTIUM2gnu_BUILDRULE
+__DB_APPLICATION_NAME__22.out
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu_MACRO_AR
+arpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu_MACRO_ARCHIVE
+$(PRJ_DIR)/PENTIUM2gnu/__DB_APPLICATION_NAME__22.a
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu_MACRO_AS
+ccpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu_MACRO_CC
+ccpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu_MACRO_CC_ARCH_SPEC
+-mcpu=pentiumpro -march=pentiumpro
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu_MACRO_CFLAGS
+-g \
+	-mcpu=pentiumpro \
+	-march=pentiumpro \
+	-ansi \
+	-nostdlib \
+	-DRW_MULTI_THREAD \
+	-D_REENTRANT \
+	-fvolatile \
+	-fno-builtin \
+	-fno-defer-pop \
+	-I$(PRJ_DIR)/.. \
+	-I$(PRJ_DIR)/../.. \
+	-I$(WIND_BASE)/target/h \
+	-DCPU=PENTIUM2 \
+	-DTOOL_FAMILY=gnu \
+	-DTOOL=gnu
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu_MACRO_CFLAGS_AS
+-g \
+	-mcpu=pentiumpro \
+	-march=pentiumpro \
+	-ansi \
+	-nostdlib \
+	-fno-builtin \
+	-fno-defer-pop \
+	-P \
+	-xassembler-with-cpp \
+	-I$(WIND_BASE)/target/h \
+	-DCPU=PENTIUM2 \
+	-DTOOL_FAMILY=gnu \
+	-DTOOL=gnu
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu_MACRO_CPP
+ccpentium -E -P
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu_MACRO_HEX_FLAGS
+
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu_MACRO_LD
+ldpentium
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu_MACRO_LDFLAGS
+-X -N
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu_MACRO_LD_PARTIAL
+ccpentium -r -nostdlib -Wl,-X
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu_MACRO_LD_PARTIAL_FLAGS
+-X -r
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu_MACRO_NM
+nmpentium -g
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu_MACRO_OPTION_DEFINE_MACRO
+-D
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu_MACRO_OPTION_DEPEND
+-M -w
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu_MACRO_OPTION_GENERATE_DEPENDENCY_FILE
+-MD
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu_MACRO_OPTION_INCLUDE_DIR
+-I
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu_MACRO_OPTION_LANG_C
+-xc
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu_MACRO_OPTION_UNDEFINE_MACRO
+-U
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu_MACRO_POST_BUILD_RULE
+
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu_MACRO_PRJ_LIBS
+
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu_MACRO_SIZE
+sizepentium
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu_MACRO_TOOL_FAMILY
+gnu
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu_RO_DEPEND_PATH
+{$(WIND_BASE)/target/h/} \
+	{$(WIND_BASE)/target/src/} \
+	{$(WIND_BASE)/target/config/}
+<END>
+
+<BEGIN> BUILD_PENTIUM2gnu_TC
+::tc_PENTIUM2gnu
+<END>
+
+<BEGIN> BUILD_RULE_archive
+
+<END>
+
+<BEGIN> BUILD_RULE___DB_APPLICATION_NAME__22.out
+
+<END>
+
+<BEGIN> BUILD_RULE___DB_APPLICATION_NAME__22.pl
+
+<END>
+
+<BEGIN> BUILD_RULE_objects
+
+<END>
+
+<BEGIN> BUILD__CURRENT
+PENTIUM2gnu
+<END>
+
+<BEGIN> BUILD__LIST
+PENTIUM2gnu
+<END>
+
+<BEGIN> CORE_INFO_TYPE
+::prj_vxApp
+<END>
+
+<BEGIN> CORE_INFO_VERSION
+2.2
+<END>
+
+<BEGIN> FILE___DB_APPLICATION_NAME__.c_dependDone
+FALSE
+<END>
+
+<BEGIN> FILE___DB_APPLICATION_NAME__.c_dependencies
+
+<END>
+
+<BEGIN> FILE___DB_APPLICATION_NAME__.c_objects
+__DB_APPLICATION_NAME__.o
+<END>
+
+<BEGIN> FILE___DB_APPLICATION_NAME__.c_tool
+C/C++ compiler
+<END>
+
+<BEGIN> PROJECT_FILES
+$(PRJ_DIR)/__DB_APPLICATION_NAME__.c
+<END>
+
+<BEGIN> userComments
+__DB_APPLICATION_NAME__
+<END>
diff --git a/storage/bdb/dist/vx_config.in b/storage/bdb/dist/vx_config.in
index 43fc8eb71f347665830e1a4995d283cd65392fa1..29e679e548fac027fb0190be07b574cc63db13fc 100644
--- a/storage/bdb/dist/vx_config.in
+++ b/storage/bdb/dist/vx_config.in
@@ -5,6 +5,12 @@
 /* Define to 1 if you want to build a version for running the test suite. */
 /* #undef CONFIG_TEST */
 
+/* We use DB_WIN32 much as one would use _WIN32 -- to specify that we're using
+   an operating system environment that supports Win32 calls and semantics. We
+   don't use _WIN32 because Cygwin/GCC also defines _WIN32, even though
+   Cygwin/GCC closely emulates the Unix environment. */
+/* #undef DB_WIN32 */
+
 /* !!!
  * The DEBUG option may be added using the Tornado project build.
  * DO NOT modify it here.
@@ -29,7 +35,7 @@
 #define HAVE_CLOCK_GETTIME 1
 
 /* Define to 1 if Berkeley DB release includes strong cryptography. */
-/* #undef HAVE_CRYPTO */
+#define HAVE_CRYPTO 1
 
 /* Define to 1 if you have the `directio' function. */
 /* #undef HAVE_DIRECTIO */
@@ -47,27 +53,42 @@
 /* Define to 1 if fcntl/F_SETFD denies child access to file descriptors. */
 /* #undef HAVE_FCNTL_F_SETFD */
 
+/* Define to 1 if you have the `fdatasync' function. */
+/* #undef HAVE_FDATASYNC */
+
 /* Define to 1 if allocated filesystem blocks are not zeroed. */
 #define HAVE_FILESYSTEM_NOTZERO 1
 
+/* Define to 1 if you have the `ftruncate' function. */
+/* #undef HAVE_FTRUNCATE */
+
 /* Define to 1 if you have the `getcwd' function. */
 #define HAVE_GETCWD 1
 
 /* Define to 1 if you have the `getopt' function. */
 /* #undef HAVE_GETOPT */
 
+/* Define to 1 if you have the `getrusage' function. */
+/* #undef HAVE_GETRUSAGE */
+
 /* Define to 1 if you have the `gettimeofday' function. */
 /* #undef HAVE_GETTIMEOFDAY */
 
 /* Define to 1 if you have the `getuid' function. */
 /* #undef HAVE_GETUID */
 
+/* Define to 1 if building Hash access method. */
+#define HAVE_HASH 1
+
 /* Define to 1 if you have the <inttypes.h> header file. */
 /* #undef HAVE_INTTYPES_H */
 
 /* Define to 1 if you have the `nsl' library (-lnsl). */
 /* #undef HAVE_LIBNSL */
 
+/* Define to 1 if the system has the type `long long'. */
+/* #undef HAVE_LONG_LONG */
+
 /* Define to 1 if you have the `memcmp' function. */
 #define HAVE_MEMCMP 1
 
@@ -104,6 +125,9 @@
 /* Define to 1 to use the GCC compiler and ARM assembly language mutexes. */
 /* #undef HAVE_MUTEX_ARM_GCC_ASSEMBLY */
 
+/* Define to 1 to use the Apple/Darwin _spin_lock_try mutexes. */
+/* #undef HAVE_MUTEX_DARWIN_SPIN_LOCK_TRY */
+
 /* Define to 1 to use the UNIX fcntl system call mutexes. */
 /* #undef HAVE_MUTEX_FCNTL */
 
@@ -120,12 +144,9 @@
 /* Define to 1 to use the msem_XXX mutexes on systems other than HP-UX. */
 /* #undef HAVE_MUTEX_MSEM_INIT */
 
-/* Define to 1 to use the GCC compiler and Apple PowerPC assembly language. */
-/* #undef HAVE_MUTEX_PPC_APPLE_GCC_ASSEMBLY */
-
-/* Define to 1 to use the GCC compiler and generic PowerPC assembly language.
+/* Define to 1 to use the GCC compiler and PowerPC assembly language mutexes.
    */
-/* #undef HAVE_MUTEX_PPC_GENERIC_GCC_ASSEMBLY */
+/* #undef HAVE_MUTEX_PPC_GCC_ASSEMBLY */
 
 /* Define to 1 to use POSIX 1003.1 pthread_XXX mutexes. */
 /* #undef HAVE_MUTEX_PTHREADS */
@@ -133,6 +154,10 @@
 /* Define to 1 to use Reliant UNIX initspin mutexes. */
 /* #undef HAVE_MUTEX_RELIANTUNIX_INITSPIN */
 
+/* Define to 1 to use the IBM C compiler and S/390 assembly language mutexes.
+   */
+/* #undef HAVE_MUTEX_S390_CC_ASSEMBLY */
+
 /* Define to 1 to use the GCC compiler and S/390 assembly language mutexes. */
 /* #undef HAVE_MUTEX_S390_GCC_ASSEMBLY */
 
@@ -163,6 +188,9 @@
 /* Define to 1 to configure mutexes intra-process only. */
 /* #undef HAVE_MUTEX_THREAD_ONLY */
 
+/* Define to 1 to use the CC compiler and Tru64 assembly language mutexes. */
+/* #undef HAVE_MUTEX_TRU64_CC_ASSEMBLY */
+
 /* Define to 1 to use the UNIX International mutexes. */
 /* #undef HAVE_MUTEX_UI_THREADS */
 
@@ -175,9 +203,12 @@
 /* Define to 1 to use VxWorks mutexes. */
 #define HAVE_MUTEX_VXWORKS 1
 
-/* Define to 1 to use Windows mutexes. */
+/* Define to 1 to use the MSVC compiler and Windows mutexes. */
 /* #undef HAVE_MUTEX_WIN32 */
 
+/* Define to 1 to use the GCC compiler and Windows mutexes. */
+/* #undef HAVE_MUTEX_WIN32_GCC */
+
 /* Define to 1 to use the GCC compiler and x86 assembly language mutexes. */
 /* #undef HAVE_MUTEX_X86_GCC_ASSEMBLY */
 
@@ -199,12 +230,18 @@
 /* Define to 1 if building on QNX. */
 /* #undef HAVE_QNX */
 
-/* Define to 1 if you have the `qsort' function. */
-#define HAVE_QSORT 1
+/* Define to 1 if building Queue access method. */
+#define HAVE_QUEUE 1
 
 /* Define to 1 if you have the `raise' function. */
 #define HAVE_RAISE 1
 
+/* Define to 1 if you have the `rand' function. */
+#define HAVE_RAND 1
+
+/* Define to 1 if building replication support. */
+#define HAVE_REPLICATION 1
+
 /* Define to 1 if building RPC client/server. */
 /* #undef HAVE_RPC */
 
@@ -214,12 +251,21 @@
 /* Define to 1 if you have the `select' function. */
 #define HAVE_SELECT 1
 
+/* Define to 1 if building sequence support. */
+/* #undef HAVE_SEQUENCE */
+
 /* Define to 1 if you have the `shmget' function. */
 /* #undef HAVE_SHMGET */
 
 /* Define to 1 if you have the `snprintf' function. */
 /* #undef HAVE_SNPRINTF */
 
+/* Define to 1 if you have the `srand' function. */
+#define HAVE_SRAND 1
+
+/* Define to 1 if building statistics support. */
+#define HAVE_STATISTICS 1
+
 /* Define to 1 if you have the <stdint.h> header file. */
 /* #undef HAVE_STDINT_H */
 
@@ -241,6 +287,9 @@
 /* Define to 1 if you have the <string.h> header file. */
 #define HAVE_STRING_H 1
 
+/* Define to 1 if you have the `strtol' function. */
+#define HAVE_STRTOL 1
+
 /* Define to 1 if you have the `strtoul' function. */
 #define HAVE_STRTOUL 1
 
@@ -254,6 +303,9 @@
    */
 /* #undef HAVE_SYS_DIR_H */
 
+/* Define to 1 if you have the <sys/fcntl.h> header file. */
+/* #undef HAVE_SYS_FCNTL_H */
+
 /* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
    */
 /* #undef HAVE_SYS_NDIR_H */
@@ -276,6 +328,12 @@
 /* Define to 1 if unlink of file with open file descriptors will fail. */
 #define HAVE_UNLINK_WITH_OPEN_FAILURE 1
 
+/* Define to 1 if the system has the type `unsigned long long'. */
+/* #undef HAVE_UNSIGNED_LONG_LONG */
+
+/* Define to 1 if building access method verification support. */
+#define HAVE_VERIFY 1
+
 /* Define to 1 if you have the `vsnprintf' function. */
 /* #undef HAVE_VSNPRINTF */
 
@@ -288,6 +346,9 @@
 /* Define to 1 if you have the `_fstati64' function. */
 /* #undef HAVE__FSTATI64 */
 
+/* Define to a value if using non-standard mutex alignment. */
+/* #undef MUTEX_ALIGN */
+
 /* Define to the address where bug reports for this package should be sent. */
 #define PACKAGE_BUGREPORT "support@sleepycat.com"
 
@@ -312,7 +373,7 @@
 /* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
 /* #undef TIME_WITH_SYS_TIME */
 
-/* Define to 1 to mask harmless unitialized memory read/writes. */
+/* Define to 1 to mask harmless uninitialized memory read/writes. */
 /* #undef UMRW */
 
 /* Number of bits in a file offset, on hosts where this is settable. */
diff --git a/storage/bdb/dist/vx_setup/CONFIG.in b/storage/bdb/dist/vx_setup/CONFIG.in
index 6ccceee7034be179d4062bacd37bcffbfc477d10..1fccd1d2ed66ac82d8c0f23491430819161b88d0 100644
--- a/storage/bdb/dist/vx_setup/CONFIG.in
+++ b/storage/bdb/dist/vx_setup/CONFIG.in
@@ -1,4 +1,4 @@
-# 
+#
 # Install configuration file.
 #
 # Note: This file may be modified during the pool manufacturing process to
diff --git a/storage/bdb/dist/vx_setup/LICENSE.TXT b/storage/bdb/dist/vx_setup/LICENSE.TXT
index 7814c679cd73afad2e5c7fd371780e67ad7e679c..f31971375f392f63fbd2fd3fdd99dd43aea40881 100644
--- a/storage/bdb/dist/vx_setup/LICENSE.TXT
+++ b/storage/bdb/dist/vx_setup/LICENSE.TXT
@@ -1,3 +1,3 @@
-Copyright (c) 1996-2002
+Copyright (c) 1996-2004
 	Sleepycat Software.  All rights reserved.
 See the file LICENSE for redistribution information.
diff --git a/storage/bdb/dist/vx_setup/vx_allfile.in b/storage/bdb/dist/vx_setup/vx_allfile.in
index 61a1b8ee8053fdf5d1330b8e997760dfc8857d92..8d87fa97b599d9564a9765d64d61299e857c2f0f 100644
--- a/storage/bdb/dist/vx_setup/vx_allfile.in
+++ b/storage/bdb/dist/vx_setup/vx_allfile.in
@@ -1,5 +1,7 @@
-windlink/sleepycat/BerkeleyDB.@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@/build_vxworks/BerkeleyDB.wpj
-windlink/sleepycat/BerkeleyDB.@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@/build_vxworks/BerkeleyDB.wsp
+windlink/sleepycat/BerkeleyDB.@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@/build_vxworks/BerkeleyDB20.wpj
+windlink/sleepycat/BerkeleyDB.@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@/build_vxworks/BerkeleyDB20.wsp
+windlink/sleepycat/BerkeleyDB.@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@/build_vxworks/BerkeleyDB20.wpj
+windlink/sleepycat/BerkeleyDB.@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@/build_vxworks/BerkeleyDB22.wsp
 windlink/sleepycat/BerkeleyDB.@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@/build_vxworks/db.h
 windlink/sleepycat/BerkeleyDB.@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@/build_vxworks/db_config.h
 windlink/sleepycat/BerkeleyDB.@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@/build_vxworks/db_int.h
diff --git a/storage/bdb/dist/vx_setup/vx_demofile.in b/storage/bdb/dist/vx_setup/vx_demofile.in
index 42a698ea36705a12a3e4695266daf46dd2691032..772f4cb4bc0edcb21179b4847a651b58fd9b81c4 100644
--- a/storage/bdb/dist/vx_setup/vx_demofile.in
+++ b/storage/bdb/dist/vx_setup/vx_demofile.in
@@ -1,3 +1,4 @@
-windlink/sleepycat/BerkeleyDB.@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@/build_vxworks/dbdemo/dbdemo.wpj
+windlink/sleepycat/BerkeleyDB.@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@/build_vxworks/dbdemo/dbdemo20.wpj
+windlink/sleepycat/BerkeleyDB.@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@/build_vxworks/dbdemo/dbdemo22.wpj
 windlink/sleepycat/BerkeleyDB.@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@/build_vxworks/dbdemo/README
 windlink/sleepycat/BerkeleyDB.@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.@DB_VERSION_PATCH@/build_vxworks/dbdemo/dbdemo.c
diff --git a/storage/bdb/dist/win_config.in b/storage/bdb/dist/win_config.in
index 09acab28806d6d975a191162cfc353e5b18db0c8..3406c8774f4611b9d49ca27b11f7038cf06202c0 100644
--- a/storage/bdb/dist/win_config.in
+++ b/storage/bdb/dist/win_config.in
@@ -1,6 +1,12 @@
 /* Define to 1 if you want to build a version for running the test suite. */
 /* #undef CONFIG_TEST */
 
+/* We use DB_WIN32 much as one would use _WIN32 -- to specify that we're using
+   an operating system environment that supports Win32 calls and semantics. We
+   don't use _WIN32 because Cygwin/GCC also defines _WIN32, even though
+   Cygwin/GCC closely emulates the Unix environment. */
+#define DB_WIN32 1
+
 /* Define to 1 if you want a debugging version. */
 /* #undef DEBUG */
 #if defined(_DEBUG)
@@ -22,7 +28,9 @@
 /* #undef HAVE_CLOCK_GETTIME */
 
 /* Define to 1 if Berkeley DB release includes strong cryptography. */
-/* #undef HAVE_CRYPTO */
+#ifndef HAVE_SMALLBUILD
+#define HAVE_CRYPTO 1
+#endif
 
 /* Define to 1 if you have the `directio' function. */
 /* #undef HAVE_DIRECTIO */
@@ -40,27 +48,44 @@
 /* Define to 1 if fcntl/F_SETFD denies child access to file descriptors. */
 /* #undef HAVE_FCNTL_F_SETFD */
 
+/* Define to 1 if you have the `fdatasync' function. */
+/* #undef HAVE_FDATASYNC */
+
 /* Define to 1 if allocated filesystem blocks are not zeroed. */
 #define HAVE_FILESYSTEM_NOTZERO 1
 
+/* Define to 1 if you have the `ftruncate' function. */
+#define HAVE_FTRUNCATE 1
+
 /* Define to 1 if you have the `getcwd' function. */
 #define HAVE_GETCWD 1
 
 /* Define to 1 if you have the `getopt' function. */
 /* #undef HAVE_GETOPT */
 
+/* Define to 1 if you have the `getrusage' function. */
+/* #undef HAVE_GETRUSAGE */
+
 /* Define to 1 if you have the `gettimeofday' function. */
 /* #undef HAVE_GETTIMEOFDAY */
 
 /* Define to 1 if you have the `getuid' function. */
 /* #undef HAVE_GETUID */
 
+/* Define to 1 if building Hash access method. */
+#ifndef HAVE_SMALLBUILD
+#define HAVE_HASH 1
+#endif
+
 /* Define to 1 if you have the <inttypes.h> header file. */
 /* #undef HAVE_INTTYPES_H */
 
 /* Define to 1 if you have the `nsl' library (-lnsl). */
 /* #undef HAVE_LIBNSL */
 
+/* Define to 1 if the system has the type `long long'. */
+#define HAVE_LONG_LONG 1
+
 /* Define to 1 if you have the `memcmp' function. */
 #define HAVE_MEMCMP 1
 
@@ -97,6 +122,9 @@
 /* Define to 1 to use the GCC compiler and ARM assembly language mutexes. */
 /* #undef HAVE_MUTEX_ARM_GCC_ASSEMBLY */
 
+/* Define to 1 to use the Apple/Darwin _spin_lock_try mutexes. */
+/* #undef HAVE_MUTEX_DARWIN_SPIN_LOCK_TRY */
+
 /* Define to 1 to use the UNIX fcntl system call mutexes. */
 /* #undef HAVE_MUTEX_FCNTL */
 
@@ -113,12 +141,9 @@
 /* Define to 1 to use the msem_XXX mutexes on systems other than HP-UX. */
 /* #undef HAVE_MUTEX_MSEM_INIT */
 
-/* Define to 1 to use the GCC compiler and Apple PowerPC assembly language. */
-/* #undef HAVE_MUTEX_PPC_APPLE_GCC_ASSEMBLY */
-
-/* Define to 1 to use the GCC compiler and generic PowerPC assembly language.
+/* Define to 1 to use the GCC compiler and PowerPC assembly language mutexes.
    */
-/* #undef HAVE_MUTEX_PPC_GENERIC_GCC_ASSEMBLY */
+/* #undef HAVE_MUTEX_PPC_GCC_ASSEMBLY */
 
 /* Define to 1 to use POSIX 1003.1 pthread_XXX mutexes. */
 /* #undef HAVE_MUTEX_PTHREADS */
@@ -126,6 +151,10 @@
 /* Define to 1 to use Reliant UNIX initspin mutexes. */
 /* #undef HAVE_MUTEX_RELIANTUNIX_INITSPIN */
 
+/* Define to 1 to use the IBM C compiler and S/390 assembly language mutexes.
+   */
+/* #undef HAVE_MUTEX_S390_CC_ASSEMBLY */
+
 /* Define to 1 to use the GCC compiler and S/390 assembly language mutexes. */
 /* #undef HAVE_MUTEX_S390_GCC_ASSEMBLY */
 
@@ -156,6 +185,9 @@
 /* Define to 1 to configure mutexes intra-process only. */
 /* #undef HAVE_MUTEX_THREAD_ONLY */
 
+/* Define to 1 to use the CC compiler and Tru64 assembly language mutexes. */
+/* #undef HAVE_MUTEX_TRU64_CC_ASSEMBLY */
+
 /* Define to 1 to use the UNIX International mutexes. */
 /* #undef HAVE_MUTEX_UI_THREADS */
 
@@ -168,9 +200,12 @@
 /* Define to 1 to use VxWorks mutexes. */
 /* #undef HAVE_MUTEX_VXWORKS */
 
-/* Define to 1 to use Windows mutexes. */
+/* Define to 1 to use the MSVC compiler and Windows mutexes. */
 #define HAVE_MUTEX_WIN32 1
 
+/* Define to 1 to use the GCC compiler and Windows mutexes. */
+/* #undef HAVE_MUTEX_WIN32_GCC */
+
 /* Define to 1 to use the GCC compiler and x86 assembly language mutexes. */
 /* #undef HAVE_MUTEX_X86_GCC_ASSEMBLY */
 
@@ -192,12 +227,22 @@
 /* Define to 1 if building on QNX. */
 /* #undef HAVE_QNX */
 
-/* Define to 1 if you have the `qsort' function. */
-#define HAVE_QSORT 1
+/* Define to 1 if building Queue access method. */
+#ifndef HAVE_SMALLBUILD
+#define HAVE_QUEUE 1
+#endif
 
 /* Define to 1 if you have the `raise' function. */
 #define HAVE_RAISE 1
 
+/* Define to 1 if you have the `rand' function. */
+#define HAVE_RAND 1
+
+/* Define to 1 if building replication support. */
+#ifndef HAVE_SMALLBUILD
+#define HAVE_REPLICATION 1
+#endif
+
 /* Define to 1 if building RPC client/server. */
 /* #undef HAVE_RPC */
 
@@ -207,12 +252,21 @@
 /* Define to 1 if you have the `select' function. */
 /* #undef HAVE_SELECT */
 
+/* Define to 1 if building sequence support. */
+#define HAVE_SEQUENCE 1
+
 /* Define to 1 if you have the `shmget' function. */
 /* #undef HAVE_SHMGET */
 
 /* Define to 1 if you have the `snprintf' function. */
 #define HAVE_SNPRINTF 1
 
+/* Define to 1 if you have the `srand' function. */
+#define HAVE_SRAND 1
+
+/* Define to 1 if building statistics support. */
+#define HAVE_STATISTICS 1
+
 /* Define to 1 if you have the <stdint.h> header file. */
 /* #undef HAVE_STDINT_H */
 
@@ -234,6 +288,9 @@
 /* Define to 1 if you have the <string.h> header file. */
 #define HAVE_STRING_H 1
 
+/* Define to 1 if you have the `strtol' function. */
+#define HAVE_STRTOL 1
+
 /* Define to 1 if you have the `strtoul' function. */
 #define HAVE_STRTOUL 1
 
@@ -247,6 +304,9 @@
    */
 /* #undef HAVE_SYS_DIR_H */
 
+/* Define to 1 if you have the <sys/fcntl.h> header file. */
+#define HAVE_SYS_FCNTL_H 1
+
 /* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
    */
 /* #undef HAVE_SYS_NDIR_H */
@@ -269,6 +329,14 @@
 /* Define to 1 if unlink of file with open file descriptors will fail. */
 /* #undef HAVE_UNLINK_WITH_OPEN_FAILURE */
 
+/* Define to 1 if the system has the type `unsigned long long'. */
+#define HAVE_UNSIGNED_LONG_LONG 1
+
+/* Define to 1 if building access method verification support. */
+#ifndef HAVE_SMALLBUILD
+#define HAVE_VERIFY 1
+#endif
+
 /* Define to 1 if you have the `vsnprintf' function. */
 #define HAVE_VSNPRINTF 1
 
@@ -281,6 +349,9 @@
 /* Define to 1 if you have the `_fstati64' function. */
 #define HAVE__FSTATI64 1
 
+/* Define to a value if using non-standard mutex alignment. */
+/* #undef MUTEX_ALIGN */
+
 /* Define to the address where bug reports for this package should be sent. */
 #define PACKAGE_BUGREPORT "support@sleepycat.com"
 
@@ -305,7 +376,7 @@
 /* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
 /* #undef TIME_WITH_SYS_TIME */
 
-/* Define to 1 to mask harmless unitialized memory read/writes. */
+/* Define to 1 to mask harmless uninitialized memory read/writes. */
 /* #undef UMRW */
 
 /* Number of bits in a file offset, on hosts where this is settable. */
@@ -359,81 +430,13 @@
 #define	vsnprintf	__db_Cvsnprintf
 #endif
 
-/*
- * XXX
- * The following is not part of the automatic configuration setup, but
- * provides the information necessary to build Berkeley DB on Windows.
- */
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <direct.h>
-#include <fcntl.h>
-#include <io.h>
-#include <limits.h>
-#include <memory.h>
-#include <process.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include <errno.h>
-
-/*
- * To build Tcl interface libraries, the include path must be configured to
- * use the directory containing <tcl.h>, usually the include directory in
- * the Tcl distribution.
- */
-#ifdef DB_TCL_SUPPORT
-#include <tcl.h>
-#endif
-
-#define	WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
-/*
- * All of the necessary includes have been included, ignore the #includes
- * in the Berkeley DB source files.
- */
-#define	NO_SYSTEM_INCLUDES
-
-/*
- * Win32 has getcwd, snprintf and vsnprintf, but under different names.
- */
-#define	getcwd(buf, size)	_getcwd(buf, size)
-#define	snprintf		_snprintf
-#define	vsnprintf		_vsnprintf
-
-/*
- * Win32 does not define getopt and friends in any header file, so we must.
- */
-#if defined(__cplusplus)
-extern "C" {
-#endif
-extern int optind;
-extern char *optarg;
-extern int getopt(int, char * const *, const char *);
-#if defined(__cplusplus)
-}
-#endif
-
-/*
- * We use DB_WIN32 much as one would use _WIN32, to determine that we're
- * using an operating system environment that supports Win32 calls
- * and semantics.  We don't use _WIN32 because cygwin/gcc also defines
- * that, even though it closely emulates the Unix environment.
- */
-#define DB_WIN32 1
+#include "win_db.h"
 
 /*
- * This is a grievous hack -- once we've included windows.h, we have no choice
- * but to use ANSI-style varargs (because it pulls in stdarg.h for us).  DB's
- * code decides which type of varargs to use based on the state of __STDC__.
- * Sensible.  Unfortunately, Microsoft's compiler _doesn't_ define __STDC__
- * unless you invoke it with arguments turning OFF all vendor extensions.  Even
- * more unfortunately, if we do that, it fails to parse windows.h!!!!!  So, we
- * define __STDC__ here, after windows.h comes in.  Note: the compiler knows
- * we've defined it, and starts enforcing strict ANSI compilance from this point
- * on.
+ * Microsoft's compiler _doesn't_ define __STDC__ unless you invoke it with
+ * arguments turning OFF all vendor extensions.  Even more unfortunately, if
+ * we do that, it fails to parse windows.h!!!!!  So, we define __STDC__ here,
+ * after windows.h comes in.  Note: the compiler knows we've defined it, and
+ * starts enforcing strict ANSI compliance from this point on.
  */
 #define __STDC__ 1
diff --git a/storage/bdb/dist/win_db.in b/storage/bdb/dist/win_db.in
new file mode 100644
index 0000000000000000000000000000000000000000..609d8460afaac9c831457fcf08d8f62a4b1db64c
--- /dev/null
+++ b/storage/bdb/dist/win_db.in
@@ -0,0 +1,100 @@
+/*-
+ * $Id: win_db.in,v 11.4 2004/10/07 13:59:24 carol Exp $
+ *
+ * The following provides the information necessary to build Berkeley
+ * DB on native Windows, and other Windows environments such as MinGW.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <direct.h>
+#include <fcntl.h>
+#include <io.h>
+#include <limits.h>
+#include <memory.h>
+#include <process.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <tchar.h>
+#include <time.h>
+#include <errno.h>
+
+/*
+ * To build Tcl interface libraries, the include path must be configured to
+ * use the directory containing <tcl.h>, usually the include directory in
+ * the Tcl distribution.
+ */
+#ifdef DB_TCL_SUPPORT
+#include <tcl.h>
+#endif
+
+#define	WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+/*
+ * All of the necessary includes have been included, ignore the #includes
+ * in the Berkeley DB source files.
+ */
+#define	NO_SYSTEM_INCLUDES
+
+/*
+ * Win32 has getcwd, snprintf and vsnprintf, but under different names.
+ */
+#define	getcwd(buf, size)	_getcwd(buf, size)
+#define	snprintf		_snprintf
+#define	vsnprintf		_vsnprintf
+
+/*
+ * Windows defines off_t to long (i.e., 32 bits).
+ */
+#define	off_t	__db_off_t
+typedef __int64 off_t;
+
+/*
+ * Win32 does not define getopt and friends in any header file, so we must.
+ */
+#if defined(__cplusplus)
+extern "C" {
+#endif
+extern int optind;
+extern char *optarg;
+extern int getopt(int, char * const *, const char *);
+#if defined(__cplusplus)
+}
+#endif
+
+#ifdef _UNICODE
+#define TO_TSTRING(dbenv, s, ts, ret) do {				\
+		int __len = strlen(s) + 1;				\
+		ts = NULL;						\
+		if ((ret = __os_malloc((dbenv),				\
+		    __len * sizeof (_TCHAR), &(ts))) == 0 &&		\
+		    MultiByteToWideChar(CP_UTF8, 0,			\
+		    (s), -1, (ts), __len) == 0)				\
+			ret = __os_get_errno();				\
+	} while (0)
+
+#define FROM_TSTRING(dbenv, ts, s, ret) {				\
+		int __len = WideCharToMultiByte(CP_UTF8, 0, ts, -1,	\
+		    NULL, 0, NULL, NULL);				\
+		s = NULL;						\
+		if ((ret = __os_malloc((dbenv), __len, &(s))) == 0 &&	\
+		    WideCharToMultiByte(CP_UTF8, 0,			\
+		    (ts), -1, (s), __len, NULL, NULL) == 0)		\
+			ret = __os_get_errno();				\
+	} while (0)
+
+#define FREE_STRING(dbenv, s) do {					\
+		if ((s) != NULL) {					\
+			__os_free((dbenv), (s));			\
+			(s) = NULL;					\
+		}							\
+	} while (0)
+
+#else
+#define TO_TSTRING(dbenv, s, ts, ret) (ret) = 0, (ts) = (_TCHAR *)(s)
+#define FROM_TSTRING(dbenv, ts, s, ret) (ret) = 0, (s) = (char *)(ts)
+#define FREE_STRING(dbenv, ts)
+#endif
diff --git a/storage/bdb/dist/win_exports.in b/storage/bdb/dist/win_exports.in
index 52df529d028cf4d7ff4cae8c147bfc29263323a0..9087875ccf6de58d268884eaa037c09eb4e82e72 100644
--- a/storage/bdb/dist/win_exports.in
+++ b/storage/bdb/dist/win_exports.in
@@ -1,15 +1,13 @@
-# $Id: win_exports.in,v 1.25 2002/08/29 14:22:21 margo Exp $
+# $Id: win_exports.in,v 1.41 2004/10/12 17:44:10 bostic Exp $
 
 # Standard interfaces.
 	db_create
 	db_env_create
+	db_sequence_create
 	db_strerror
 	db_version
 	db_xa_switch
 	log_compare
-	txn_abort
-	txn_begin
-	txn_commit
 
 # Library configuration interfaces.
 	db_env_set_func_close
@@ -18,10 +16,13 @@
 	db_env_set_func_exists
 	db_env_set_func_free
 	db_env_set_func_fsync
+	db_env_set_func_ftruncate
 	db_env_set_func_ioinfo
 	db_env_set_func_malloc
 	db_env_set_func_map
 	db_env_set_func_open
+	db_env_set_func_pread
+	db_env_set_func_pwrite
 	db_env_set_func_read
 	db_env_set_func_realloc
 	db_env_set_func_rename
@@ -43,6 +44,8 @@
 	__db_dbm_init
 	__db_dbm_nextkey
 	__db_dbm_store
+	__db_get_flags_fn
+	__db_get_seq_flags_fn
 	__db_hcreate
 	__db_hdestroy
 	__db_hsearch
@@ -70,8 +73,7 @@
 	__ham_func4
 	__ham_func5
 	__ham_test
-	__lock_dump_region
-	__memp_dump_region
+	__lock_id_set
 	__os_calloc
 	__os_closehandle
 	__os_free
@@ -84,44 +86,78 @@
 	__os_strdup
 	__os_umalloc
 	__os_write
+	__txn_id_set
 
 #These are needed for linking tools or java.
-	__bam_init_print
+	__bam_adj_read
+	__bam_cadjust_read
+	__bam_cdel_read
+	__bam_curadj_read
 	__bam_pgin
 	__bam_pgout
-	__crdel_init_print
+	__bam_rcuradj_read
+	__bam_relink_read
+	__bam_repl_read
+	__bam_root_read
+	__bam_rsplit_read
+	__bam_split_read
+	__crdel_metasub_read
+	__db_addrem_read
+	__db_big_read
+	__db_cksum_read
+	__db_debug_read
 	__db_dispatch
-	__db_dump
-	__db_e_stat
+	__db_dumptree
 	__db_err
+	__db_fileid_reset
 	__db_getlong
 	__db_getulong
 	__db_global_values
-	__db_init_print
-	__db_inmemdbflags
 	__db_isbigendian
+	__db_lsn_reset
+	__db_noop_read
 	__db_omode
 	__db_overwrite
+	__db_ovref_read
+	__db_pg_alloc_read
+	__db_pg_free_read
+	__db_pg_freedata_read
+	__db_pg_init_read
+	__db_pg_new_read
+	__db_pg_prepare_read
 	__db_pgin
 	__db_pgout
-	__db_prdbt
-	__db_prfooter
-	__db_prheader
+	__db_pr_callback
 	__db_rpath
+	__db_stat_pp
+	__db_stat_print_pp
 	__db_util_cache
 	__db_util_interrupted
 	__db_util_logset
 	__db_util_siginit
 	__db_util_sigresend
-	__db_verify_callback
 	__db_verify_internal
-	__dbreg_init_print
-	__fop_init_print
+	__dbreg_register_read
+	__fop_create_read
+	__fop_file_remove_read
+	__fop_remove_read
+	__fop_rename_read
+	__fop_write_read
+	__ham_chgpg_read
+	__ham_copypage_read
+	__ham_curadj_read
 	__ham_get_meta
-	__ham_init_print
+	__ham_groupalloc_read
+	__ham_insdel_read
+	__ham_metagroup_read
+	__ham_newpage_read
 	__ham_pgin
 	__ham_pgout
 	__ham_release_meta
+	__ham_replace_read
+	__ham_splitdata_read
+	__lock_list_print
+	__log_stat_pp
 	__os_clock
 	__os_get_errno
 	__os_id
@@ -129,6 +165,15 @@
 	__os_sleep
 	__os_ufree
 	__os_yield
-	__qam_init_print
+	__qam_add_read
+	__qam_del_read
+	__qam_delext_read
+	__qam_incfirst_read
+	__qam_mvptr_read
 	__qam_pgin_out
-	__txn_init_print
+	__rep_stat_print
+	__txn_child_read
+	__txn_ckp_read
+	__txn_recycle_read
+	__txn_regop_read
+	__txn_xa_regop_read
diff --git a/storage/bdb/dist/winmsi/dbcorewix.in b/storage/bdb/dist/winmsi/dbcorewix.in
new file mode 100644
index 0000000000000000000000000000000000000000..03635177de0720373632290fab6ce059cce31748
--- /dev/null
+++ b/storage/bdb/dist/winmsi/dbcorewix.in
@@ -0,0 +1,196 @@
+<!-- $Id: dbcorewix.in,v 1.8 2005/04/18 18:40:27 philipr Exp $
+ -
+ - Dbcorewix.in is the DB core WiX input file, and is used by
+ - s_winmsi to create dbcore.wxs (an input to WiX).
+ - Most everything here is pure 'WiX' syntax within XML,
+ - the exceptions are:
+ -    1) everything is pushed through the m4 preprocessor first.
+ -       this makes certain boilerplate actions in the UI tolerable.
+ -       We put all needed defines at the top of this file.
+ -    2) a very few identifiers beginning with WIX_DB_*
+ -       are predefined as m4 macros on the command line.
+ -       These are items that only the caller (s_winmsi) can know.
+ -
+ - M4 makes many things easier, but there are peculiarities.
+ - In particular, if you are using a macro with args, like
+ - TOPSTRIPE, note that *any* occurance of the characters "( ) ,"
+ - are interpreted by m4, even if they occur in an Xml comment or string.
+ - Remember this when editing this file!
+ -
+ - Beyond that, there is a lot to understand about WiX
+ - and how this file operates, to get started, look at
+ - various WiX tutorials, like:
+ -    http://www.ondotnet.com/pub/a/dotnet/2004/04/19/wix.html
+ -    http://blogs.msdn.com/robmen/archive/2004/04/05/107709.aspx
+ - Also view the lecture covered here:
+ -    http://blogs.msdn.com/robmen/archive/2004/09/23/233684.aspx
+ -
+ - Finally, understand that WiX is an XML layering above the concepts
+ - defined by the world of the MSI installer.  To really know how to do WiX,
+ - (and especially the UI), you need to understand the MSI installer.
+ - A key point is that MSI (and hence WiX) is not really procedural.
+ - MSI defines a number of tables (like Feature or CustomAction) in
+ - an internal database.  WiX merely specifies how to fill these tables,
+ - and the msiexec program merely cranks through the various tables,
+ - processing each row.  It is true that you can do procedural things
+ - via CustomActions, but to get them in order, you must specify columns
+ - in the table with things like After="SomeOtherRowId".
+ -
+ - See "About the User Interface" and subordinate documents:
+ -    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/about_the_user_interface.asp
+-->
+
+m4_include(WIX_DB_SHARED_WINMSIDIR/dbwix.m4)   <!-- Define common macros -->
+
+<Wix xmlns="http://schemas.microsoft.com/wix/2003/01/wi">
+
+  <!-- The ???? stuff asks WiX to create a unique GUID for us -->
+  <Product Id='????????-????-????-????-????????????'
+   Name='Berkeley DB WIX_DB_VERSION' Version='WIX_DB_VERSION.0'
+   Manufacturer='Sleepycat Software, Inc.' Language='1033'>
+
+    <!-- Store files as a compressed 'cabinet' embedded in the .MSI file. -->
+    <Package Id='????????-????-????-????-????????????'
+     Keywords="Embedded Database Datastore"
+     Description='Berkeley DB WIX_DB_VERSION'
+     Comments='includes sources and binaries' InstallerVersion='200'
+     Compressed='yes' Platforms="Intel"
+     Languages="1033" SummaryCodepage="1252" />
+
+    <Media Id='1' Cabinet='dbcore.cab' EmbedCab='yes' />
+
+    COMMON_PROPERTIES()
+
+    <!-- Declare properties for environment -->
+    WIX_DB_ENV_FEATURE_PROPS()
+
+    <Condition Message=
+       "To install [ProductName], you must be running Windows 2000 or Windows XP.">
+       <![CDATA[VersionNT>=500]]></Condition>
+
+    <Condition Message=
+      "You must have administrative access to install this product.">
+      NOT Priviledged
+    </Condition>
+
+    <Directory Id="TARGETDIR" Name="SourceDir">
+      <Directory Id="DesktopFolder" Name="." SourceName="." />
+      <Directory Id="FavoritesFolder" Name="." SourceName="." />
+
+      <Directory Id="ProgramFilesFolder" Name="." SourceName=".">
+        <Directory Id="SleepycatSoftwareFolder" Name="Sleepy~1"
+                   LongName="Sleepycat Software">
+          <Directory Id="INSTALLDIR" Name="WIX_DB_8CHAR_VERSION"
+                   LongName="Berkeley DB WIX_DB_VERSION">
+            <Directory Id="INSTALLUTIL" Name="instutil"
+                   LongName="installutil">
+            </Directory>
+
+
+            <!-- Note: these guids must be changed when an installer
+              -  for a new release is made available.
+              -
+              -  TODO: to play by the rules of components (see
+              -  http://blogs.msdn.com/robmen/archive/2003/10/18/56497.aspx,
+              -  "Component Rules 101" by Rob Mensching),
+              -  we should devise a strategy for ALL guids (remember
+              -  many are created by s_winmsi).  This should work:
+              -
+              -  Each guid is composed of three parts, like so:
+              -     PPPPPPPP-VVVV-VVVV-HHHH-HHHHHHHHHHHH
+              -  The P part is unique to the product, e.g.
+              -  the bdb core installer might always use 9A3FE019.
+              -  The V part is the version of the product, e.g.
+              -  4.2.37 might be translated as 0402-0025   # 25 is 37 in hex
+              -  The H part is a hash value created from the directory
+              -  that houses the component.  Like if the component for
+              -  the directory "bin/Debug" hashed to 1234567890abcdef,
+              -  then the H part is 1234-567890abcdef.
+              - 
+              -  This scheme guarantees that rebuilds of the installer
+              -  over the same release tree get the same GUIDs.
+              -  But for a different release tree (which *should* get
+              -  installed in a different directory, since install
+              -  directories are named by release number), we will get
+              -  completely different GUIDs.
+              -->
+            <Component Id="RequiredFiles"
+                   Guid="13E1DF48-903B-11D9-8BDE-F66BAD1E3F3A"
+                   KeyPath="yes" SharedDllRefCount="yes"
+                   Location="either" DiskId="1">
+
+              <File Id="LICENSE.txt" Name="LICENSE.txt"
+                    src="WIX_DB_SRCDIR\LICENSE" />
+              <File Id="README.txt" Name="README.txt"
+                    src="WIX_DB_SRCDIR\README" />
+	      <Registry Id="RootDir.RegistryVal" Root="HKLM"
+                   Key="SOFTWARE\Sleepycat Software\Berkeley DB\WIX_DB_VERSION"
+                   Name="RootDirectory" Value="[INSTALLDIR]" Type="string"
+                   Action="write" />
+              <CreateFolder />
+            </Component>
+
+            COMMON_COMPONENTS()
+
+            <!-- <Directory>, <Component> generated from files.in -->
+	    WIX_DB_DIRECTORY_STRUCTURE()
+
+          </Directory>
+        </Directory>
+      </Directory>
+      <Directory Id="ProgramMenuFolder" Name="." SourceName=".">
+        <Directory Id="BerkeleyDbMenu" Name="WIX_DB_8CHAR_VERSION"
+         LongName="Berkeley DB WIX_DB_VERSION" />
+      </Directory>
+    </Directory>
+
+    <!-- <File>, <Shortcut> generated from links.in -->
+    WIX_DB_LINKS()
+
+    COMMON_FEATURES(`Berkeley DB')
+
+    <!-- ================================================================ -->
+    <UI>
+
+      <Property Id="DefaultUIFont"><![CDATA[Tahoma8]]></Property>
+      <TextStyle Id="Tahoma8" FaceName="Tahoma" Size="8" />
+
+      DIALOG_WELCOME(MainWelcomeDlg, , ShowLicenseDlg)
+      DIALOG_LICENSE(ShowLicenseDlg, MainWelcomeDlg, TargetFolderDlg,
+                     `Berkeley DB')
+      DIALOG_TARGET(TargetFolderDlg, ShowLicenseDlg, FeatureSelectionDlg)
+      DIALOG_FEATURE(FeatureSelectionDlg, TargetFolderDlg, EnvVarDlg,
+                     `Debug libraries are needed for working C/C++ examples.')
+      DIALOG_ENVIRONMENT(EnvVarDlg, FeatureSelectionDlg, ReadyToInstallDlg)
+      DIALOG_READY(ReadyToInstallDlg, EnvVarDlg, )
+
+      DIALOG_PROGRESS(ShowProgressDlg, , )
+      DIALOG_SUCCESS(InstallSuccessDlg, , , `Berkeley DB',
+                     `in the product blog http://www.sleepycat.com/blogs/db or in the news group news://comp.databases.berkeley-db')
+
+      <!-- Here are extra admin dialogs -->
+      DIALOG_ADMIN_CANCEL(CancelInstallerDlg)
+      DIALOG_ADMIN_NOSPACE(OutOfSpaceDlg, FeatureSelectionDlg)
+      DIALOG_ADMIN_INTERRUPTED(InstallErrorDlg, Return)
+      DIALOG_ADMIN_INTERRUPTED(InstallCancelledDlg, Exit)
+
+
+      <!-- This sequence tells MSI what to do when (at the highest level) -->
+      <InstallUISequence>
+        <Show Dialog="InstallErrorDlg" OnExit="error" />
+        <Show Dialog="InstallCancelledDlg" OnExit="cancel" />
+        <Show Dialog="InstallSuccessDlg" OnExit="success" />
+        <Show Dialog="MainWelcomeDlg" After="CostFinalize" />
+        <Show Dialog="ShowProgressDlg" After="MainWelcomeDlg" />
+      </InstallUISequence>
+
+      COMMON_UI_TEXT()
+      <Property Id="MaxInstallSize">49 MB</Property>
+
+
+    </UI>
+
+    COMMON_EXECUTE_SEQUENCE()
+
+  </Product>
+</Wix>
diff --git a/storage/bdb/dist/winmsi/dbvarsbat.in b/storage/bdb/dist/winmsi/dbvarsbat.in
new file mode 100644
index 0000000000000000000000000000000000000000..b49375285f89d9be89089302d3237cfa78841695
--- /dev/null
+++ b/storage/bdb/dist/winmsi/dbvarsbat.in
@@ -0,0 +1,25 @@
+@echo off
+
+:: $Id: dbvarsbat.in,v 1.2 2005/04/15 18:59:59 philipr Exp $
+:: This file sets the environment variables needed to run Berkeley DB.
+
+set DBROOTDIR=
+for /F "tokens=3 delims=	" %%A in ('REG QUERY "HKLM\SOFTWARE\Sleepycat Software\Berkeley DB\WIX_DB_VERSION" /v RootDirectory') do set DBROOTDIR=%%A
+if ERRORLEVEL 2 goto MISSING
+if not defined DBROOTDIR goto MISSING
+
+echo Setting environment variables for Berkeley DB, installed in %DBROOTDIR%
+
+set PATH=%DBROOTDIR%\bin;%DBROOTDIR%\bin\debug;%PATH%
+set CLASSPATH=%CLASSPATH%;%DBROOTDIR%\jar\debug\db.jar;%DBROOTDIR%\jar\debug\dbexamples.jar;%CLASSPATH%;%DBROOTDIR%\jar\db.jar;%DBROOTDIR%\jar\dbexamples.jar
+goto END
+
+:MISSING
+echo
+echo NOTE:
+echo   The Berkeley DB version could not be determined.
+echo   If you are running on Windows 2000, make sure the
+echo   REG.EXE program is installed from the Tools disk"
+echo
+
+:END
diff --git a/storage/bdb/dist/winmsi/dbwix.m4 b/storage/bdb/dist/winmsi/dbwix.m4
new file mode 100644
index 0000000000000000000000000000000000000000..42fa44e62a8ba5243be9429e1302e1e17d459bc8
--- /dev/null
+++ b/storage/bdb/dist/winmsi/dbwix.m4
@@ -0,0 +1,833 @@
+<!-- $Id: dbwix.m4,v 1.7 2005/04/18 18:41:07 philipr Exp $
+ - This file is included by WiX input files to define m4 macros.
+ - m4 is tricky.  It has NO notion of XML comments, so
+ - take care using these names in comments after they are defined,
+ - since they will be expanded (probably what you don't want).
+ -
+ - Note that this file is shared by multiple installers.
+ - If you want to change a definition to customize an individual project,
+ - consider redefining the macro in a local file.
+ -->
+
+<!-- Some basic UI characteristics -->
+m4_define(`DIALOG_WIDTH', `390')
+m4_define(`DIALOG_HEIGHT', `320')
+m4_define(`BOTTOMSTRIPE_Y', `m4_eval(DIALOG_HEIGHT-32)')
+m4_define(`NAVBUTTON_Y', `m4_eval(DIALOG_HEIGHT-23)')
+m4_define(`NAVBUTTON_DIM', `X="`$1'" Y="NAVBUTTON_Y" Width="66" Height="17"')
+
+<!-- _YPOS is a running total of the current Y position -->
+m4_define(`_YPOS', `0')
+m4_define(`SETY', `m4_define(`_YPOS', `$1')')
+m4_define(`INCY', `SETY(m4_eval(_YPOS+(`$1')))')
+
+<!-- PARTIALHEIGHT(yheight [, gap=10 ]) -->
+m4_define(`PARTIALHEIGHT', `Y="_YPOS" Height="`$1'" INCY(`$1') INCY(_GETGAP(`$2'))')
+m4_define(`_GETGAP', `m4_ifelse(`',`$1', 10, `$1')')
+m4_define(`FULLHEIGHT', `Y="_YPOS" Height="m4_eval(BOTTOMSTRIPE_Y - _YPOS - 10)"')
+
+<!-- BOTTOM_Y:  bottom of the usable area before nav buttons -->
+m4_define(`BOTTOM_Y', `m4_eval(BOTTOMSTRIPE_Y - 10)')
+
+m4_define(`DIALOGPROP', `Width="DIALOG_WIDTH" Height="DIALOG_HEIGHT"
+        Title="[ProductName] - Installer" NoMinimize="yes"')
+
+m4_define(`TOPSTRIPE', `
+        SETY(`$1')
+        INCY(10)
+<!-- stripe bitmap removed for now until we get better quality bitmaps.
+        <Control Id="TopStripe" Type="Bitmap"
+                 X="0" Y="0" Width="DIALOG_WIDTH" Height="`$1'" Text="Stripe" />
+-->
+        <Control Id="TopStripeBorder" Type="Line"
+                 X="0" Y="`$1'" Width="DIALOG_WIDTH" Height="0" />
+        <Control Id="TopTitle" Type="Text"
+                 X="8" Y="6" Width="292" Height="25" Transparent="yes">
+          <Text>{&amp;MSSansBold8}`$2'</Text>
+        </Control>
+        <Control Id="TopText" Type="Text"
+                 X="16" Y="23" Width="m4_eval(DIALOG_WIDTH-34)"
+                 Height="m4_eval(`$1' - 19)" Transparent="yes">
+          <Text>`$3'</Text>
+        </Control>')
+
+m4_define(`TEXTCONTROL', `
+        <Control Id="`$1'" Type="Text"
+            X="20" Y="_YPOS" Width="m4_eval(DIALOG_WIDTH-42)" Height="`$2'">
+          <Text>`$3'</Text>
+        </Control>
+        INCY(`$2')')
+
+<!-- TEXTCONTROL2 (name,height,text). No newline -->
+m4_define(`TEXTCONTROL2', `
+        <Control Id="`$1'" Type="Text"
+            X="20" Y="_YPOS" Width="m4_eval(DIALOG_WIDTH-42)" Height="`$2'" Transparent="yes">
+          <Text>`$3'</Text>
+        </Control>')
+
+m4_define(`BOTTOMSTRIPE', `
+        <Control Id="BottomStripeBorder" Type="Line"
+                 X="0" Y="BOTTOMSTRIPE_Y" Width="DIALOG_WIDTH" Height="0" />')
+
+m4_define(`NEWDIALOGEVENT', `
+          <Publish Event="NewDialog" Value="`$1'">
+                   <![CDATA[1]]>
+          </Publish>')
+
+m4_define(`SPAWNDIALOGEVENT', `
+          <Publish Event="SpawnDialog" Value="`$1'">
+                   <![CDATA[1]]>
+          </Publish>')
+
+<!-- use an arrow only if the text is Back, like this: "< Back" -->
+m4_define(`BACKBUTTON_GENERIC', `
+        <Control Id="`$1'" Type="PushButton"
+                 NAVBUTTON_DIM(170)
+                 Text="m4_ifelse(Back,`$1',&lt; )&amp;`$1'" `$2'>
+           `$3'
+        </Control>')
+
+<!-- use an arrow only if the text is Next, like this: "Next >" -->
+m4_define(`NEXTBUTTON_GENERIC', `
+        <Control Id="`$1'" Type="PushButton"
+                 NAVBUTTON_DIM(236)
+                 Default="yes" Text="&amp;`$1'm4_ifelse(Next,`$1', &gt;)" `$2'>
+           `$3'
+        </Control>')
+
+m4_define(`CANCELBUTTON_GENERIC', `
+        <Control Id="`$1'" Type="PushButton"
+                 NAVBUTTON_DIM(308)
+                 Text="`$1'" `$2'>
+          `$3'
+        </Control>')
+
+m4_define(`NEXTBUTTON_NOTDEFAULT', `
+        <Control Id="`$1'" Type="PushButton"
+                 NAVBUTTON_DIM(236)
+                 Default="no" Text="&amp;`$1'm4_ifelse(Next,`$1', &gt;)" `$2'>
+           `$3'
+        </Control>')
+
+<!-- typical usages -->
+m4_define(`BACKBUTTON_DISABLED', `BACKBUTTON_GENERIC(Back, Disabled="yes")')
+m4_define(`BACKBUTTON', `BACKBUTTON_GENERIC(Back, , NEWDIALOGEVENT(`$1'))')
+m4_define(`NEXTBUTTON_DISABLED', `NEXTBUTTON_GENERIC(Next, Disabled="yes")')
+m4_define(`NEXTBUTTON', `NEXTBUTTON_GENERIC(Next, , NEWDIALOGEVENT(`$1'))')
+m4_define(`CANCELBUTTON', `CANCELBUTTON_GENERIC(Cancel, Cancel="yes",
+                          SPAWNDIALOGEVENT(CancelInstallerDlg))')
+
+<!-- a little (imperfect) magic to create some unique GUIDs. -->
+m4_define(`_GUIDSUFFIX', `10000000')
+m4_define(`_SETGUID', `m4_define(`_GUIDSUFFIX', `$1')')
+m4_define(`_GUIDINC', `_SETGUID(m4_eval(_GUIDSUFFIX+1))')
+m4_define(`GUID_CREATE_UNIQUE', `_GUIDINC()WIX_DB_GUID_PREFIX()`'_GUIDSUFFIX()')
+
+<!-- These three defines are data values, used by GUID_CREATE_PERSISTENT -->
+m4_define(`_WIXDB_PRODUCT', WIX_DB_PRODUCT_NAME)
+m4_define(`_WIXDB_VERSION', WIX_DB_VERSION)
+m4_define(`_WIXDB_CURDIR', `unknown')
+m4_define(`_WIXDB_CURFILE', `unknown')
+m4_define(`_WIXDB_SUBDIR', `')
+
+<!-- These defines set the data values above -->
+m4_define(`WIX_DB_SET_PRODUCT', `m4_define(`_WIXDB_PRODUCT', `$1')')
+m4_define(`WIX_DB_SET_VERSION', `m4_define(`_WIXDB_VERSION', `$1')')
+m4_define(`WIX_DB_SET_CURDIR', `m4_define(`_WIXDB_CURDIR', `$1')')
+m4_define(`WIX_DB_SET_CURFILE', `m4_define(`_WIXDB_CURFILE', `$1')')
+m4_define(`WIX_DB_SET_SUBDIR', `m4_define(`_WIXDB_SUBDIR', `$1')')
+
+m4_define(`_LASTCHAR', `m4_substr(`$1',m4_eval(m4_len(`$1')-1))')
+m4_define(`_LOPCHAR', `m4_substr(`$1',0,m4_eval(m4_len(`$1')-1))')
+m4_define(`_CHOPNAME', `m4_ifelse(_LASTCHAR(`$1'),/,`$1',`_CHOPNAME(_LOPCHAR(`$1'))')')
+m4_define(`WIX_DB_BEGIN_SUBDIR', `WIX_DB_SET_SUBDIR(_WIXDB_SUBDIR/`$1')')
+m4_define(`WIX_DB_END_SUBDIR', `WIX_DB_SET_SUBDIR(_LOPCHAR(_CHOPNAME(_WIXDB_SUBDIR)))')
+m4_define(`WIX_DB_CLEAR_SUBDIR', `WIX_DB_SET_SUBDIR()')
+
+<!-- Create a GUID from the current product, directory, file -->
+m4_define(`WIX_DB_PERSISTENT_GUID', `m4_esyscmd(echo "_WIXDB_PRODUCT @@ _WIXDB_VERSION @@ _WIXDB_CURDIR @@ _WIXDB_SUBDIR @@ _WIXDB_CURFILE" | openssl md5 | sed -e "s/^\(........\)\(....\)\(....\)\(....\)\(....\)\(............\)/\1-\2-\3-\4-\5/")')
+
+m4_define(`DB_LICENSE_INTRO', `The following license applies to this copy of software you are about to install.  Please read it carefully before proceeding.  Select below the nature of the license by which you will use this product.  For more information about Sleepycat Software&apos;s licensing please refer to http://www.sleepycat.com/download/incensinginfo.shtml or contact us at info@sleepycat.com.')
+
+m4_define(`DB_ENVIRONMENT_INTRO', `[ProductName] will need to modify certain environment variables to work properly.  If you elect not to set these variables you may find that some utilities`,' scripts and other parts of [ProductName] won&apos;t work properly.  Please indicate that you skipped this step if you request support help from us.')
+
+m4_define(`COMMON_PROPERTIES', `
+    <Property Id="ApplicationUsers"><![CDATA[AnyUser]]></Property>
+    <Property Id="LicenseType"><![CDATA[Open]]></Property>
+
+    <!-- The ARP* properties affect the Add/Remove Programs dialog -->
+    <Property Id="ARPURLINFOABOUT"><![CDATA[http://www.sleepycat.com]]></Property>
+    <Property Id="ARPCONTACT"><![CDATA[support@sleepycat.com]]></Property>
+    <Property Id="ARPNOMODIFY"><![CDATA[1]]></Property>
+    <Property Id="ARPNOREPAIR"><![CDATA[1]]></Property>
+    <!-- TODO: this icon does not work here -->
+    <Property Id="ARPPRODUCTION"><![CDATA[IconWeb]]></Property>
+
+    <Property Id="INSTALLLEVEL"><![CDATA[200]]></Property>
+    <Property Id="FullOrCustom"><![CDATA[Full]]></Property>
+
+    <Property Id="DiscussionCheck" Hidden="yes"><![CDATA[yes]]></Property>
+    <Property Id="AnnouncementsCheck" Hidden="yes"><![CDATA[yes]]></Property>
+    <Property Id="NewsletterCheck" Hidden="yes"><![CDATA[yes]]></Property>
+    <Property Id="EmailAddress" Hidden="yes"></Property>
+    <Property Id="SalesContactCheck" Hidden="yes"><![CDATA[yes]]></Property>
+    <Property Id="EnvironmentSetCheck" Hidden="yes"><![CDATA[1]]></Property>
+    <Property Id="EnvironmentGenCheck" Hidden="yes"><![CDATA[1]]></Property>
+<!-- (PBR) We use DebugCheck to track the state of the debug checkbox -->
+    <Property Id="DebugCheck" Hidden="yes"><![CDATA[yes]]></Property>
+
+    <!-- Part of the build process creates a program instenv.exe
+      -  that is installed into InstUtil and used only by the installer.
+      -  When a user wants to generate a file with environment vars,
+      -  we launch instreg and that program creates it.
+      -
+      -  The final location of the instenv.exe program is not known
+      -  when we create this property, we set the real value of the
+      -  property later.
+      -->
+
+    <Property Id="InstEnvironmentProgram"><![CDATA[0]]></Property>
+<!-- TODO: should not have to hardwire PATH and CLASSPATH here -->
+    <CustomAction Id="InstEnvironment" Property="InstEnvironmentProgram" 
+         ExeCommand="[INSTALLDIR]\dbvars.bat PATH=[PATHEscValue] CLASSPATH=[CLASSPATHEscValue]" Return="asyncNoWait"/>
+
+    <!-- Some properties to aid in debugging.
+      -  Sometimes creating a msg dialog is the easiest way to see the
+      -  value of a property.  To make this work when you hit the next
+      -  button, add this to your NEXTBUTTON__GENERIC call:
+
+          <Publish Event="DoAction" Value="InstDebug"><![CDATA[1]]></Publish>
+
+      -->
+    <Property Id="DebugUserId">dda</Property>
+    <Property Id="DebugShowProgram">msg.exe</Property>
+
+    <!-- tweek me as needed -->
+    <CustomAction Id="InstDebug" Property="DebugShowProgram" 
+         ExeCommand="[DebugUserId] InstEnvironmentProgram=[InstEnvironmentProgram]= EnvironmentGenCheck=[EnvironmentGenCheck]= AlwaysInstall=[!AlwaysInstall]=" Return="asyncNoWait" />
+
+    <Property Id="NULL" Hidden="yes"></Property>
+    <Property Id="FeatureList" Hidden="yes"></Property>
+    <Property Id="DoInstallDebug" Hidden="yes">yes</Property>
+    <Property Id="DoInstallEnvironment" Hidden="yes">yes</Property>
+
+    <Binary Id="SleepycatLogo" src="WIX_DB_IMAGEDIR\sleepycat.jpg" />
+    <Binary Id="Stripe" src="WIX_DB_IMAGEDIR\topstripe.ibd" />
+
+    <!-- TODO: does not work yet -->
+    <Binary Id="IconWeb" src="WIX_DB_IMAGEDIR\caticon.ibd" />
+
+    <!-- These are 16x16 Windows ico files -->
+    <Binary Id="IconCreateDir" src="WIX_DB_IMAGEDIR\foldernew.ibd" />
+    <Binary Id="IconUp" src="WIX_DB_IMAGEDIR\folderup.ibd" />
+
+')
+
+m4_define(`COMMON_COMPONENTS', `
+        <Component Id="RequiredCommonFiles"
+               Guid="545CFE00-93D7-11D9-EAD3-F63F68BDEB1A"
+                   KeyPath="yes" SharedDllRefCount="yes"
+                   Location="either" DiskId="1">
+	      <Registry Id="Ext.Registry" Root="HKCR"
+                   Key=".bdbsc"
+                   Value="Sleepycat.InformationalShortcut"
+                   Type="string" Action="write" />
+	      <Registry Id="Name.Registry" Root="HKCR"
+                   Key="Sleepycat.InformationalShortcut"
+                   Value="Sleepycat Software Informational Shortcut"
+                   Type="string" Action="write" />
+	      <Registry Id="Tip.Registry" Root="HKCR"
+                   Key="Sleepycat.InformationalShortcut" Name="InfoTip"
+                   Value="Sleepycat Software Informational Shortcut"
+                   Type="string" Action="write" />
+	      <Registry Id="NoShow.Registry" Root="HKCR"
+                   Key="Sleepycat.InformationalShortcut" Name="NeverShowExt"
+                   Type="string" Action="write" />
+	      <Registry Id="Icon.Registry" Root="HKCR"
+                   Key="Sleepycat.InformationalShortcut\DefaultIcon"
+                   Value="[INSTALLDIR]\installutil\webicon.ico"
+                   Type="string" Action="write" />
+	      <Registry Id="Command.Registry" Root="HKCR"
+                   Key="Sleepycat.InformationalShortcut\shell\open\command"
+                   Value="rundll32.exe shdocvw.dll,OpenURL %1"
+                   Type="string" Action="write" />
+	      <Registry Id="Explore.Registry" Root="HKCU"
+                   Key="Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.bdbsc\OpenWithProgIds\Sleepycat.InformationalShortcut"
+                   Action="write" />
+	      <Registry Id="HklmExt.Registry" Root="HKLM"
+                   Key="Software\Classes\.bdbsc"
+                   Value="Sleepycat.InformationalShortcut"
+                   Type="string" Action="write" />
+	      <Registry Id="HklmCommand.Registry" Root="HKLM"
+                   Key="Software\Classes\Sleepycat.InformationalShortcut\shell\open\command"
+                   Value="rundll32.exe shdocvw.dll,OpenURL %1"
+                   Type="string" Action="write" />
+            </Component>
+')
+
+m4_define(`COMMON_UI_TEXT', `
+      <!-- These are needed to show various canned text -->
+      <UIText Id="AbsentPath" />
+      <UIText Id="NewFolder">Fldr|New Folder</UIText>
+      <UIText Id="bytes">bytes</UIText>
+      <UIText Id="GB">GB</UIText>
+      <UIText Id="KB">KB</UIText>
+      <UIText Id="MB">MB</UIText>
+      <UIText Id="MenuAbsent">This feature will not be installed.</UIText>
+      <UIText Id="MenuAllLocal">This feature, and all subfeatures, will be installed.</UIText>
+      <UIText Id="MenuLocal">This feature will be installed.</UIText>
+      <UIText Id="SelAbsentAbsent">This feature will remain uninstalled.</UIText>
+      <UIText Id="SelAbsentLocal">This feature will be installed.</UIText>
+      <UIText Id="SelChildCostNeg">This feature frees up [1] on your hard drive.</UIText>
+      <UIText Id="SelChildCostPos">This feature requires [1] on your hard drive.</UIText>
+      <UIText Id="SelCostPending">Compiling cost for this feature...</UIText>
+      <UIText Id="SelLocalAbsent">This feature will be completely removed.</UIText>
+      <UIText Id="SelLocalLocal">This feature will remain installed.</UIText>
+      <UIText Id="SelParentCostNegNeg">This feature frees up [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures free up [4] on your hard drive.</UIText>
+      <UIText Id="SelParentCostNegPos">This feature frees up [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures require [4] on your hard drive.</UIText>
+      <UIText Id="SelParentCostPosNeg">This feature requires [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures free up [4] on your hard drive.</UIText>
+      <UIText Id="SelParentCostPosPos">This feature requires [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures require [4] on your hard drive.</UIText>
+      <UIText Id="TimeRemaining">Time remaining: {[1] min }[2] sec</UIText>
+      <UIText Id="VolumeCostAvailable">Available</UIText>
+      <UIText Id="VolumeCostDifference">Differences</UIText>
+      <UIText Id="VolumeCostRequired">Required</UIText>
+      <UIText Id="VolumeCostSize">Disk Size</UIText>
+      <UIText Id="VolumeCostVolume">Volume</UIText>
+')
+
+m4_define(`COMMON_FEATURES', `
+    <!-- Here we list all the features to be installed.
+      -  There is one canned feature, the rest of the
+      -  features come from features.in, by way of a file
+      -  that gets included.
+      -->
+    <Feature Id="AlwaysInstall" Title="Always Install"
+             Description="`$1'" Display="hidden" Level="1"
+             AllowAdvertise="no"
+             ConfigurableDirectory="INSTALLDIR" Absent="disallow">
+      <ComponentRef Id="RequiredFiles" />
+      <ComponentRef Id="RequiredCommonFiles" />
+    </Feature>
+
+    <!-- <Feature>, <ComponentRef> generated from {features,files}.in -->
+    WIX_DB_FEATURE_STRUCTURE()
+')
+
+m4_define(`COMMON_EXECUTE_SEQUENCE', `
+    <!-- TODO: fix comment
+      -  We modify the execute sequence to insert some custom actions:
+      -  we want the instenv program to run during install (after files
+      -  are installed), and during uninstall (before files are removed).
+      -  We set a condition on the custom actions to make this happen.
+      -  The "!ident" notation indicates the current action for a feature 
+      -  with that identifier.  We use the AlwaysInstall feature because
+      -  it is always present in our feature list.  A value of 3 means
+      -  it is being installed locally, 1 means it is being uninstalled.
+      - TODO: removed for now
+      <Custom Action="InstEnvironment" After="PublishProduct">
+        <![CDATA[Not Installed]]></Custom>
+      -->
+    <InstallExecuteSequence>
+    </InstallExecuteSequence>
+')
+
+<!--
+  -  Here are macros for each dialog that is shared by the installers.
+  -  The idea for any customization is that each installer
+  -  could potentially override a particular dialog.
+  -  However, if it is feasible to share code, any of these
+  -  dialogs could be parameterized further.
+  -
+  -  In general, these macros have 3 parameters.
+  -  The first is the id name of the dialog.
+  -  The second is the id of the previous dialog (for the Back button).
+  -  The third is the id of the next dialog (for the Next button).
+  -->
+m4_define(`DIALOG_WELCOME', `
+      <Dialog Id="`$1'" DIALOGPROP>
+        BOTTOMSTRIPE()
+        BACKBUTTON_DISABLED()
+        CANCELBUTTON()
+        NEXTBUTTON(`$3')
+
+        TOPSTRIPE(54, `Welcome',
+`The Installer will install [ProductName] on your computer.
+To continue, click Next.')
+
+        <Control Id="Logo" Type="Bitmap" Text="SleepycatLogo" 
+                 X="0" Width="DIALOG_WIDTH" PARTIALHEIGHT(168) />
+      </Dialog>
+')
+
+<!-- Takes a 4th parameter, a short product name, like "Berkeley DB" -->
+m4_define(`DIALOG_LICENSE', `
+      <RadioGroup Property="LicenseType">
+        <RadioButton Value="Open"
+           X="0" Y="0" Width="310" Height="15"
+           Text="I qualify for the &amp;open source license shown above" />
+        <RadioButton Value="Commercial"
+           X="0" Y="15" Width="310" Height="15"
+           Text="I will need a co&amp;mmercial license when I ship my product" />
+      </RadioGroup>
+
+      <Dialog Id="`$1'" DIALOGPROP>
+
+        TOPSTRIPE(84, `Open Source License', DB_LICENSE_INTRO(`$4'))
+        BOTTOMSTRIPE()
+        BACKBUTTON(`$2')
+        CANCELBUTTON()
+	NEXTBUTTON(`$3')
+
+        <Control Id="LicenseText" Type="ScrollableText" X="8" Width="368"
+                  PARTIALHEIGHT(130) Sunken="yes">
+          <Text>WIX_DB_LICENSE_RTF()</Text>
+        </Control>
+
+        <Control Id="LicenseRadio" Type="RadioButtonGroup" X="8" Width="340"
+                 PARTIALHEIGHT(35) Property="LicenseType" />
+
+      </Dialog>
+')
+
+m4_define(`DIALOG_TARGET', `
+
+      <RadioGroup Property="ApplicationUsers">
+        <RadioButton Value="AnyUser" X="0" Y="0" Width="270" Height="15"
+            Text="&amp;Anyone who uses this computer (all users)" />
+        <RadioButton Value="CurUser" X="0" Y="15" Width="270" Height="15"
+            Text="Only for the current user" />
+      </RadioGroup>
+
+      <Dialog Id="`$1'" DIALOGPROP>
+
+        TOPSTRIPE(44, `Installation Folder',
+                  `Click Next to install to the default folder.')
+        BOTTOMSTRIPE()
+        BACKBUTTON(`$2')
+        CANCELBUTTON()
+
+        NEXTBUTTON_GENERIC(Next,,
+	   NEWDIALOGEVENT(`$3')
+          <Publish Event="SetInstallLevel" Value="300">
+            <![CDATA[0]]></Publish>
+          <Publish Property="ALLUSERS" Value="1">
+            <![CDATA[ApplicationUsers = "AnyUser"]]></Publish>
+          <Publish Property="ALLUSERS" Value="{}">
+            <![CDATA[ApplicationUsers = "CurUser"]]></Publish>
+          <Publish Property="SelectedSetupType" Value="Custom">
+            <![CDATA[1]]></Publish>
+
+	)
+
+        TEXTCONTROL(InstallToText, 16, `Install [ProductName] to:')
+
+        <Control Id="ChangeFolder" Type="PushButton" X="318" Y="_YPOS"
+                 Width="66" Height="17" Text="&amp;Change...">
+          <Publish Event="SpawnDialog" Value="ChangeFolderDlg">
+            <![CDATA[1]]></Publish>
+          <Publish Property="NewInstallDir" Value="INSTALLDIR">
+            <![CDATA[1]]></Publish>
+        </Control>
+
+        <Control Id="InstallToValue" Type="Text" X="40" Width="250"
+           PARTIALHEIGHT(20, 20)
+           Property="NewInstallDir" Text="[INSTALLDIR]" />
+
+        TEXTCONTROL(InstallForText, 14, `Install [ProductName] for:')
+
+        <Control Id="InstallForRadio" Type="RadioButtonGroup" PARTIALHEIGHT(50)
+             X="40" Width="310" Property="ApplicationUsers" />
+      </Dialog>
+
+      <Dialog Id="ChangeFolderDlg" DIALOGPROP>
+        TOPSTRIPE(44, `Change the Installation Folder',
+                  `Browse to the folder you want to install to.')
+        BOTTOMSTRIPE()
+        NEXTBUTTON_GENERIC(OK,,
+          <Publish Event="SetTargetPath"
+            Value="[NewInstallDir]"><![CDATA[1]]></Publish>
+          <Publish Event="EndDialog" Value="Return"><![CDATA[1]]></Publish>
+        )
+        CANCELBUTTON_GENERIC(Cancel, Cancel="yes",
+          <Publish Event="Reset" Value="0"><![CDATA[1]]></Publish>
+          <Publish Event="EndDialog" Value="Return"><![CDATA[1]]></Publish>
+        )
+
+        TEXTCONTROL(LookText, 15, `&amp;Install into:')
+
+        <Control Id="DirCombo" Type="DirectoryCombo"
+           X="20" Width="270" Y="_YPOS" Height="80"
+           Property="NewInstallDir" Indirect="yes" Removable="yes"
+           Fixed="yes" Remote="yes" CDROM="yes" RAMDisk="yes" Floppy="yes" />
+
+        <Control Id="FolderUp" Type="PushButton"
+           X="320" Width="19" Y="_YPOS" Height="19"
+           ToolTip="Up One Level" Icon="yes" FixedSize="yes"
+           IconSize="16" Text="IconUp">
+          <Publish Event="DirectoryListUp" Value="0"><![CDATA[1]]></Publish>
+        </Control>
+
+        <Control Id="FolderCreate" Type="PushButton"
+           X="345" Width="19" Y="_YPOS" Height="19"
+           ToolTip="Create New Folder" Icon="yes" FixedSize="yes"
+           IconSize="16" Text="IconCreateDir">
+          <Publish Event="DirectoryListNew" Value="0"><![CDATA[1]]></Publish>
+        </Control>
+
+        INCY(25)
+        <Control Id="DirList" Type="DirectoryList"
+           X="20" Width="342" PARTIALHEIGHT(100, 5)
+           Property="NewInstallDir" Sunken="yes"
+           Indirect="yes" TabSkip="no" />
+
+        <Control Id="FolderText" Type="Text"
+           X="20" Width="99" PARTIALHEIGHT(14, 1)
+           TabSkip="no" Text="&amp;Folder name:" />
+
+        <Control Id="PathEditControl" Type="PathEdit"
+           X="20" Width="342" PARTIALHEIGHT(17)
+           Property="NewInstallDir" Sunken="yes" Indirect="yes" />
+
+      </Dialog>
+
+')
+
+<!-- Takes a 4th parameter, any extra text (restrictions) for debug libs -->
+m4_define(`DIALOG_FEATURE', `
+      <Dialog Id="`$1'" DIALOGPROP TrackDiskSpace="yes">
+
+        TOPSTRIPE(36, `Feature Selection',
+                  `Select the features of [ProductName] you want. Maximum install size is [MaxInstallSize].')
+        BOTTOMSTRIPE()
+        CANCELBUTTON
+        BACKBUTTON(`$2')
+
+        NEXTBUTTON_GENERIC(Next,,
+          <Publish Event="NewDialog" Value="`$3'">
+            <![CDATA[OutOfNoRbDiskSpace <> 1]]></Publish>
+          <Publish Event="NewDialog" Value="OutOfSpaceDlg">
+            <![CDATA[OutOfNoRbDiskSpace = 1]]></Publish>
+          <Publish Property="FullOrCustom" Value="Custom">
+            <![CDATA[1]]></Publish>
+
+           <!--
+            -  This updates the FeatureList property and the
+            -  properties like PATHValue that track the value
+            -  to be displayed for environment variables.
+           -->
+            WIX_DB_ENV_FEATURE_SET()
+        )
+
+
+        <!-- TODO: When the debug checkbox is clicked,
+          -  we would like to update the disk space usage numbers
+          -  as shown in the SelectionTreeControl.  Tried this:
+              <Publish Event="DoAction" Value="CostFinalize">
+                 <![CDATA[1]]></Publish>
+          -  but it made all the numbers zero.  Probably need
+          -  to perform a whole sequence, (like CostInitialize,...)
+          -->
+
+
+        TEXTCONTROL(ClickText, 15,
+`Click on an icon in the list below to change how a feature is installed.')
+        INCY(5)
+
+        <Control Id="SelectionTreeControl" Type="SelectionTree"
+                 X="8" Width="220" FULLHEIGHT
+                 Property="NewInstallDir" Sunken="yes" TabSkip="no" />
+
+        <Control Id="GroupBoxControl" Type="GroupBox"
+                 X="235" Width="131" FULLHEIGHT
+                 Text="Feature Description" />
+        INCY(15)
+
+        <Control Id="ItemDescription" Type="Text"
+                 X="241" Width="120" PARTIALHEIGHT(50) >
+          <Text></Text>
+          <Subscribe Event="SelectionDescription" Attribute="Text" />
+        </Control>
+
+        <Control Id="Size" Type="Text"
+                 X="241" Width="120" PARTIALHEIGHT(50)
+                 Text="Feature size">
+          <Subscribe Event="SelectionSize" Attribute="Text" />
+        </Control>
+
+      </Dialog>
+')
+
+<!--
+ - Note: for Win/9X, Win/ME
+ - Here we must do costfinalize whenever leaving
+ - this dialog (via Back or Next) because changing whether we have
+ - environment enabled or not changes the list of features
+ - (which is finalized by costfinalize).
+ - Calling costfinalize more than once is apparently not
+ - supported on older (9X,ME) systems.
+ -->
+m4_define(`DIALOG_ENVIRONMENT', `
+      <Dialog Id="`$1'" DIALOGPROP>
+        TOPSTRIPE(84, `Setting Environment Variables', DB_ENVIRONMENT_INTRO)
+        BOTTOMSTRIPE()
+        CANCELBUTTON
+        BACKBUTTON_GENERIC(Back, ,
+           NEWDIALOGEVENT(`$2')
+<!--PBR (4/4/2005) I removed this because it resets the feature choices
+           <Publish Event="DoAction" Value="CostFinalize">
+             <![CDATA[1]]></Publish>
+-->
+        )
+        NEXTBUTTON_GENERIC(Next, , 
+           NEWDIALOGEVENT(`$3')
+<!--PBR (4/4/2005) I removed this because it resets the feature choices
+           <Publish Event="DoAction" Value="CostFinalize">
+             <![CDATA[1]]></Publish>
+-->
+          <Publish Property="DoInstallEnvironment" Value="yes">
+                 <![CDATA[EnvironmentSetCheck = "1"]]></Publish>
+          <Publish Property="DoInstallEnvironment" Value="no">
+                 <![CDATA[EnvironmentSetCheck <> "1"]]></Publish>
+        )
+
+        <Control Id="SetEnvBox" Type="CheckBox" PARTIALHEIGHT(15, 5)
+             Text="Set the values in the environment variables"
+             X="26" Width="250" Property="EnvironmentSetCheck" CheckBoxValue="1"/>
+        <Control Id="GenEnvBox" Type="CheckBox" PARTIALHEIGHT(15, 8)
+             Text="Generate a dbvars.bat file with the given values"
+             X="26" Width="250" Property="EnvironmentGenCheck" CheckBoxValue="1"/>
+        INCY(5)
+
+        TEXTCONTROL(ReviewText, 12,
+`Here are the new environment values:')
+
+        <Control Id="LargeBox" Type="Text"
+                  X="19" Width="340" FULLHEIGHT
+                  Disabled="yes" Sunken="yes" Transparent="yes" TabSkip="no" />
+
+        INCY(5)
+
+        <!-- Show the properties for environment -->
+        WIX_DB_ENV_FEATURE_SHOW()
+
+      </Dialog>
+')
+
+m4_define(`DIALOG_READY', `
+      <Dialog Id="`$1'" DIALOGPROP TrackDiskSpace="yes">
+        NEXTBUTTON_GENERIC(Install,,
+          <Publish Event="NewDialog" Value="OutOfSpaceDlg">
+            <![CDATA[OutOfNoRbDiskSpace = 1]]></Publish>
+          <Publish Event="EndDialog" Value="Return">
+            <![CDATA[OutOfNoRbDiskSpace <> 1]]></Publish>
+
+<!-- Note: we set the name of the instenv now because we do not know
+           the installed pathname at the beginning of the execution -->
+
+          <Publish Property="InstEnvironmentProgram"
+                 Value="[INSTALLDIR]\installutil\bin\instenv.exe">
+                 <![CDATA[1]]></Publish>
+        )
+
+        TOPSTRIPE(44, `Ready', `The installer is ready to begin.')
+        BOTTOMSTRIPE()
+        CANCELBUTTON()
+        BACKBUTTON(`$2')
+
+        TEXTCONTROL(ReviewText, 24,
+`If you want to review or change any of your installation settings, click Back to the Feature Selection.  Click Cancel to exit the installer.')
+
+        <Control Id="LargeBox" Type="Text"
+                  X="19" Width="340" FULLHEIGHT
+                  Disabled="yes" Sunken="yes" Transparent="yes" TabSkip="no" />
+
+        INCY(5)
+
+        <Control Id="DestinationText" Type="Text"
+                  X="23" Width="316" PARTIALHEIGHT(11, 4)
+                  TabSkip="no" Text="Destination Folder:" />
+
+        <Control Id="DestinationValue" Type="Text"
+                  X="37" Width="316" PARTIALHEIGHT(13, 8)
+                  TabSkip="no" Text="[INSTALLDIR]" />
+
+        <Control Id="FeatureListText" Type="Text"
+                  X="23" Width="316" PARTIALHEIGHT(13, 4)
+                  TabSkip="no" Text="Features to be installed:" />
+
+        <Control Id="FeatureListValue" Type="Text"
+                  X="37" Width="316" PARTIALHEIGHT(30, 8)
+                  TabSkip="no" Text="Shortcuts[FeatureList]" />
+
+        <Control Id="EnvironmentText" Type="Text"
+                  X="23" Width="316" PARTIALHEIGHT(15, 0)
+                  TabSkip="no" Text="Environment Variables:" />
+
+        <Control Id="EnvironmentValue" Type="Text"
+                  X="37" Width="316" PARTIALHEIGHT(20, 0)
+                  TabSkip="no" Text="[DoInstallEnvironment]" />
+
+      </Dialog>
+
+')
+
+m4_define(`DIALOG_PROGRESS', `
+      <Dialog Id="`$1'" DIALOGPROP Modeless="yes">
+        BOTTOMSTRIPE()
+        BACKBUTTON_DISABLED()
+        CANCELBUTTON()
+        NEXTBUTTON_DISABLED()
+
+        TOPSTRIPE(44, `Installer Progress', `Installing [ProductName].')
+
+        <Control Id="ActionText" Type="Text"
+                  X="59" Y="100" Width="275" Height="12">
+          <Subscribe Event="ActionText" Attribute="Text" />
+        </Control>
+
+        <Control Id="ActionProgress95" Type="ProgressBar"
+                  X="59" Y="113" Width="275" Height="12"
+                  ProgressBlocks="yes" Text="Progress done">
+          <Subscribe Event="InstallFiles" Attribute="Progress" />
+          <Subscribe Event="MoveFiles" Attribute="Progress" />
+          <Subscribe Event="RemoveFiles" Attribute="Progress" />
+          <Subscribe Event="RemoveRegistryValues" Attribute="Progress" />
+          <Subscribe Event="WriteIniValues" Attribute="Progress" />
+          <Subscribe Event="WriteRegistryValues" Attribute="Progress" />
+          <Subscribe Event="UnmoveFiles" Attribute="Progress" />
+          <Subscribe Event="AdminInstallFinalize" Attribute="Progress" />
+          <Subscribe Event="SetProgress" Attribute="Progress" />
+        </Control>
+      </Dialog>
+')
+
+<!--
+  -  Takes two extra parameters (in addition to the usual dialog parms)
+  -  4th: a short product name, like "Berkeley DB"
+  -  5th: a description of where to find online info, like "on www.xyz.com"
+  -->
+m4_define(`DIALOG_SUCCESS', `
+      <Dialog Id="`$1'" DIALOGPROP>
+        BOTTOMSTRIPE()
+        NEXTBUTTON_GENERIC(Finish, Cancel="yes",
+          <Publish Event="DoAction" Value="CleanUp">
+            <![CDATA[ISSCRIPTRUNNING="1"]]></Publish>
+          <Publish Event="EndDialog" Value="Exit">
+            <![CDATA[1]]></Publish>
+        )
+        CANCELBUTTON_GENERIC(Cancel, Disabled="yes", )
+        BACKBUTTON_DISABLED()
+
+        TOPSTRIPE(44, `Installed', `[ProductName] is now installed.')
+
+        TEXTCONTROL(InstallSuccessText, 80,
+`Please contact support@sleepycat.com for any technical issues or info@sleepycat.com for sales and licensing questions.
+
+Information about this product can also be found $5.
+
+Thank you for installing [ProductName].')
+
+        <Control Id="Image" Type="Bitmap" Text="SleepycatLogo"
+                  X="0" Width="DIALOG_WIDTH" FULLHEIGHT TabSkip="no" />
+
+      </Dialog>
+')
+
+
+m4_define(`DIALOG_ADMIN_INTERRUPTED', `
+      <Dialog Id="`$1'" DIALOGPROP>
+        TOPSTRIPE(44, `Interrupted',
+`The installer was interrupted before [ProductName] could be completely installed.')
+
+        BOTTOMSTRIPE()
+        NEXTBUTTON_GENERIC(Finish, Cancel="yes",
+          <Publish Event="DoAction" Value="CleanUp">
+            <![CDATA[ISSCRIPTRUNNING="1"]]></Publish>
+          <Publish Event="EndDialog" Value="Exit">
+            <![CDATA[1]]></Publish>
+          <Condition Action="default">
+            <![CDATA[NOT UpdateStarted]]></Condition>
+        )
+        CANCELBUTTON_GENERIC(Cancel, Disabled="yes",
+          <Publish Property="Suspend" Value="1"><![CDATA[1]]></Publish>
+          <Publish Event="EndDialog" Value="`$2'"><![CDATA[1]]></Publish>
+          <Condition Action="disable"><![CDATA[NOT UpdateStarted]]></Condition>
+          <Condition Action="enable"><![CDATA[UpdateStarted]]></Condition>
+        )
+        BACKBUTTON_GENERIC(Back, Disabled="yes",
+          <Publish Property="Suspend" Value="{}"><![CDATA[1]]></Publish>
+          <Publish Event="EndDialog" Value="`$2'"><![CDATA[1]]></Publish>
+          <Condition Action="disable"><![CDATA[NOT UpdateStarted]]></Condition>
+          <Condition Action="enable"><![CDATA[UpdateStarted]]></Condition>
+          <Condition Action="default"><![CDATA[UpdateStarted]]></Condition>
+        )
+
+        <Control Id="NotModifiedText" Type="Text"
+                  X="20" Y="_YPOS" Width="228" Height="50" Transparent="yes">
+          <Text>Your system has not been modified.  To complete the installation later, please run the installer again.</Text>
+          <Condition Action="hide"><![CDATA[UpdateStarted]]></Condition>
+          <Condition Action="show"><![CDATA[NOT UpdateStarted]]></Condition>
+        </Control>
+
+        <Control Id="YesModifiedText" Type="Text"
+                  X="20" Y="_YPOS" Width="228" Height="50" Transparent="yes">
+          <Text>The product may be partially installed.  Any installed elements will be removed when you exit.</Text>
+          <Condition Action="hide"><![CDATA[NOT UpdateStarted]]></Condition>
+          <Condition Action="show"><![CDATA[UpdateStarted]]></Condition>
+        </Control>
+        INCY(30)
+
+        TEXTCONTROL(FinishText, 25, `Click Finish to exit the install.')
+
+        <Control Id="Image" Type="Bitmap"
+                  X="0" Width="DIALOG_WIDTH" PARTIALHEIGHT(168) Text="SleepycatLogo" />
+      </Dialog>
+')
+
+m4_define(`DIALOG_ADMIN_CANCEL', `
+
+      <Dialog Id="`$1'" Width="280" Height="90"
+              Title="[ProductName] - Installer" NoMinimize="yes">
+
+        SETY(20)
+        TEXTCONTROL(CancelText, 24,
+`Are you sure you want to cancel [ProductName] installation?')
+
+        <Control Id="YesButton" Type="PushButton"
+                  X="60" Y="60" Width="66" Height="17" Text="&amp;Yes">
+          <Publish Event="DoAction" Value="CleanUp">
+                 <![CDATA[ISSCRIPTRUNNING="1"]]></Publish>
+          <Publish Event="EndDialog" Value="Exit"><![CDATA[1]]></Publish>
+        </Control>
+
+        <Control Id="NoButton" Type="PushButton"
+                  X="130" Y="60" Width="66" Height="17"
+                  Default="yes" Cancel="yes" Text="&amp;No">
+          <Publish Event="EndDialog" Value="Return">
+                 <![CDATA[1]]></Publish>
+        </Control>
+
+      </Dialog>
+')
+
+m4_define(`DIALOG_ADMIN_NOSPACE', `
+      <Dialog Id="`$1'" DIALOGPROP>
+        TOPSTRIPE(44, `Out of Disk Space',
+`The disk does not have enough space for the selected features.')
+        BOTTOMSTRIPE()
+
+        CANCELBUTTON_GENERIC(OK, Default="yes" Cancel="yes",
+          <Publish Event="NewDialog" Value="`$2'">
+             <![CDATA[ACTION <> "ADMIN"]]></Publish>
+        )
+
+        TEXTCONTROL(NoSpaceText, 43,
+`The highlighted volumes (if any) do not have enough disk space for the currently selected features.  You can either remove files from the highlighted volumes, or choose to install fewer features, or choose a different destination drive.')
+
+        <Control Id="VolumeCostListControl" Type="VolumeCostList"
+                  X="23" Width="310" FULLHEIGHT
+                  Sunken="yes" Fixed="yes" Remote="yes">
+          <Text>{120}{70}{70}{70}{70}</Text>
+        </Control>
+      </Dialog>
+')
diff --git a/storage/bdb/dist/winmsi/environment.in b/storage/bdb/dist/winmsi/environment.in
new file mode 100644
index 0000000000000000000000000000000000000000..4f394f73a570dc5d6bc8e930ede05167d8a0343c
--- /dev/null
+++ b/storage/bdb/dist/winmsi/environment.in
@@ -0,0 +1,23 @@
+# $Id: environment.in,v 1.5 2005/04/15 19:00:19 philipr Exp $
+# Lists environment variables needed to install particular
+# features in Windows.  Feature names must be
+# listed in features.in .  The meaning of each line is:
+# if a given FEATURE is selected, add to the environment VARIABLE
+# the given VALUE (relative to the root of the tree).
+# Options may be +first or +last to put it at the beginning or end
+# of the variable.  The items are processed in the order given here,
+# so an entry with +first will no longer be first if another line
+# with +first follows it.
+
+# Note: columns below must be separated by tabs.
+
+# feature	variable		value			options
+
+DCoreAPI	PATH			/bin\\debug		+first
+CoreAPI		PATH			/bin			+first
+
+# The debug versions go last, they are preferred if they are installed.
+JavaEx		CLASSPATH		/jar\\dbexamples.jar	+last
+JavaAPI		CLASSPATH		/jar\\db.jar		+last
+DJavaEx		CLASSPATH		/jar\\debug\\dbexamples.jar	+last
+DJavaAPI	CLASSPATH		/jar\\debug\\db.jar	+last
diff --git a/storage/bdb/dist/winmsi/features.in b/storage/bdb/dist/winmsi/features.in
new file mode 100644
index 0000000000000000000000000000000000000000..ead896050cf0f76c0609868ef6971e13df8592a1
--- /dev/null
+++ b/storage/bdb/dist/winmsi/features.in
@@ -0,0 +1,33 @@
+# $Id: features.in,v 1.5 2005/04/15 19:03:35 philipr Exp $
+# Lists features that can be installed on Windows,
+# and their dependencies.
+
+# Note: columns below must be separated by tabs.
+#
+# Feature: the feature identifier.  If it is dependent on another feature,
+#          that is specified via Dependent/Featurename
+# Short name: the name as it shows in the installer's tree display
+# Description: the description that shows when the item is selected
+#
+# Options are one or more of:
+# +default:   the feature is installed by default
+# +required:  the feature cannot be deselected (implies default)
+# +invisible: the feature is not shown to the user (implies required)
+#
+
+# feature	short name	description	options
+
+CoreAPI		"Core Features"	"C/C++ API and required binaries"	+required
+CoreAPI/DCoreAPI	"Debug Core Features"	""	
+CoreTools	"Tools and Utilities"	"Compiled tools for DB maintenance"	+default
+CoreEx		"C/C++ Examples"	"C and C++ compiled examples (requires debug libraries to function)"	+default
+
+JavaAPI		"Java"		"Java API JAR and JNI native libraries"
+JavaAPI/JavaEx	"Java Examples"	"Java examples JAR"
+JavaAPI/DJavaAPI	"Debug Java"	""	
+JavaAPI/DJavaAPI/DJavaEx	"Debug Java Examples"	""	
+PerlAPI		"Perl"		"Perl API .pm and .pod files"
+TclAPI		"Tcl"		"Tcl API binaries"
+TclAPI/DTclAPI		"Debug Tcl"	""	
+Docs		"Documentation"	"Documentation for all products"
+Sources		"Source files"	"Source files for all products"	+default
diff --git a/storage/bdb/dist/winmsi/files.in b/storage/bdb/dist/winmsi/files.in
new file mode 100644
index 0000000000000000000000000000000000000000..b3d5f4ba8bd86a2aba8ccdbb8c2a7f1e6abd6899
--- /dev/null
+++ b/storage/bdb/dist/winmsi/files.in
@@ -0,0 +1,87 @@
+# $Id: files.in,v 1.7 2005/04/15 19:00:36 philipr Exp $
+# Lists files needed to install particular
+# features in Windows.  Feature names must be
+# listed in features.in .
+
+# Note: columns below must be separated by tabs.
+
+# feature	source file				targdir	shortname
+
+CoreAPI		build_win32/Release/libdb43.dll		/bin/
+DCoreAPI	build_win32/Debug/libdb43d.dll		/bin/debug/
+DCoreAPI	build_win32/Debug/db_dll.pdb		/bin/debug/
+CoreAPI		build_win32/Release/libdb43.lib		/lib/
+DCoreAPI	build_win32/Debug/libdb43d.lib		/lib/
+CoreAPI		build_win32/Release/msvcr71.dll		/bin/
+DCoreAPI	build_win32/Debug/msvcr71d.dll		/bin/debug/
+CoreAPI		build_win32/Release/msvcp71.dll		/bin/
+DCoreAPI	build_win32/Debug/msvcp71d.dll		/bin/debug/
+
+# After the build process, we create an installed_include directory
+# housing all the needed include files, for user convenience
+CoreAPI		installed_include/			/include/
+
+CoreAPI		${PRODUCT_SHARED_WINMSIDIR}/images/webicon.ico	/installutil/
+CoreAPI		${PRODUCT_STAGE}/dbvars.bat		/
+
+# We don't include the .lib files for Java, nobody needs to
+# link C/C++ against the java library
+JavaAPI		build_win32/Release/libdb_java43.dll	/bin/	dbj43.dll
+DJavaAPI 	build_win32/Debug/libdb_java43d.dll	/bin/debug/	dbj43d.dll
+DJavaAPI 	build_win32/Debug/db_java.pdb		/bin/debug/
+JavaAPI		build_win32/Release/db.jar		/jar/
+DJavaAPI	build_win32/Debug/db.jar		/jar/debug/
+
+JavaEx		build_win32/Release/dbexamples.jar	/jar/	dbexam~1.jar
+DJavaEx		build_win32/Debug/dbexamples.jar	/jar/debug/	dbexam~1.jar
+
+# We don't include the .lib files for Tcl, nobody needs to
+# link C/C++ against the Tcl library
+DTclAPI		build_win32/Debug/libdb_tcl43d.dll	/bin/debug/	dbt43d.dll
+DTclAPI		build_win32/Debug/db_tcl.pdb		/bin/debug/
+TclAPI		build_win32/Release/libdb_tcl43.dll	/bin/	dbt43.dll
+
+PerlAPI		perl/BerkeleyDB/blib/			/lib/perl/
+
+CoreTools	build_win32/Release/db_archive.exe	/bin/	db_arc~1.exe
+CoreTools	build_win32/Release/db_checkpoint.exe	/bin/	db_che~1.exe
+CoreTools	build_win32/Release/db_deadlock.exe	/bin/	db_dea~1.exe
+CoreTools	build_win32/Release/db_dump.exe		/bin/	db_dump.exe
+CoreTools	build_win32/Release/db_load.exe		/bin/	db_load.exe
+CoreTools	build_win32/Release/db_printlog.exe	/bin/	db_pri~1.exe
+CoreTools	build_win32/Release/db_recover.exe	/bin/	db_rec~1.exe
+CoreTools	build_win32/Release/db_stat.exe		/bin/	db_sta~1.exe
+CoreTools	build_win32/Release/db_upgrade.exe	/bin/	db_upg~1.exe
+CoreTools	build_win32/Release/db_verify.exe	/bin/	db_ver~1.exe
+
+CoreEx		build_win32/Debug/ex_access.exe		/bin/debug/	ex_acc~1.exe
+CoreEx		build_win32/Debug/ex_access.pdb		/bin/debug/	ex_acc~1.pdb
+CoreEx		build_win32/Debug/ex_btrec.exe		/bin/debug/	ex_btr~1.exe
+CoreEx		build_win32/Debug/ex_btrec.pdb		/bin/debug/	ex_btr~1.pdb
+CoreEx		build_win32/Debug/ex_env.exe		/bin/debug/	ex_env.exe
+CoreEx		build_win32/Debug/ex_env.pdb		/bin/debug/	ex_env.pdb
+CoreEx		build_win32/Debug/ex_lock.exe		/bin/debug/	ex_loc~1.exe
+CoreEx		build_win32/Debug/ex_lock.pdb		/bin/debug/	ex_loc~1.pdb
+CoreEx		build_win32/Debug/ex_mpool.pdb		/bin/debug/	ex_mpo~1.pdb
+CoreEx		build_win32/Debug/ex_mpool.exe		/bin/debug/	ex_mpo~1.exe
+CoreEx		build_win32/Debug/ex_repquote.exe	/bin/debug/	ex_rep~1.exe
+CoreEx		build_win32/Debug/ex_repquote.pdb	/bin/debug/	ex_rep~1.pdb
+CoreEx		build_win32/Debug/ex_tpcb.exe		/bin/debug/	ex_tpcb.exe
+CoreEx		build_win32/Debug/ex_tpcb.pdb		/bin/debug/	ex_tpcb.pdb
+
+CoreEx		build_win32/Debug/excxx_access.exe	/bin/debug/	excxx_ac.exe
+CoreEx		build_win32/Debug/excxx_access.pdb	/bin/debug/	excxx_ac.pdb
+CoreEx		build_win32/Debug/excxx_btrec.exe	/bin/debug/	excxx_bt.exe
+CoreEx		build_win32/Debug/excxx_btrec.pdb	/bin/debug/	excxx_bt.pdb
+CoreEx		build_win32/Debug/excxx_env.exe		/bin/debug/	excxx_en.exe
+CoreEx		build_win32/Debug/excxx_env.pdb		/bin/debug/	excxx_en.pdb
+CoreEx		build_win32/Debug/excxx_lock.exe	/bin/debug/	excxx_lk.exe
+CoreEx		build_win32/Debug/excxx_lock.pdb	/bin/debug/	excxx_lk.pdb
+CoreEx		build_win32/Debug/excxx_mpool.exe	/bin/debug/	excxx_mp.exe
+CoreEx		build_win32/Debug/excxx_mpool.pdb	/bin/debug/	excxx_mp.pdb
+CoreEx		build_win32/Debug/excxx_tpcb.exe	/bin/debug/	excxx_tp.exe
+CoreEx		build_win32/Debug/excxx_tpcb.pdb	/bin/debug/	excxx_tp.pdb
+
+Docs		${PRODUCT_STAGE}/docs/			/docs/
+
+Sources		${PRODUCT_STAGE}/Sources/		/db-${PRODUCT_VERSION}/
diff --git a/storage/bdb/dist/winmsi/images/caticon.ibd b/storage/bdb/dist/winmsi/images/caticon.ibd
new file mode 100644
index 0000000000000000000000000000000000000000..e8b17bff46f38d269d0a44b077919adcc7540250
Binary files /dev/null and b/storage/bdb/dist/winmsi/images/caticon.ibd differ
diff --git a/storage/bdb/dist/winmsi/images/foldernew.ibd b/storage/bdb/dist/winmsi/images/foldernew.ibd
new file mode 100644
index 0000000000000000000000000000000000000000..10824136851221d72abcbda82079e40357f227c8
Binary files /dev/null and b/storage/bdb/dist/winmsi/images/foldernew.ibd differ
diff --git a/storage/bdb/dist/winmsi/images/folderup.ibd b/storage/bdb/dist/winmsi/images/folderup.ibd
new file mode 100644
index 0000000000000000000000000000000000000000..f1d3696972675f18527dd21bb339ade7ede476e8
Binary files /dev/null and b/storage/bdb/dist/winmsi/images/folderup.ibd differ
diff --git a/storage/bdb/dist/winmsi/images/sleepycat.jpg b/storage/bdb/dist/winmsi/images/sleepycat.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..213167760c4f11d373fdcd3f0bf35417334112d7
Binary files /dev/null and b/storage/bdb/dist/winmsi/images/sleepycat.jpg differ
diff --git a/storage/bdb/dist/winmsi/images/topstripe.ibd b/storage/bdb/dist/winmsi/images/topstripe.ibd
new file mode 100644
index 0000000000000000000000000000000000000000..be72f9067023a42561048b062a7bf11c9ce4cd5b
Binary files /dev/null and b/storage/bdb/dist/winmsi/images/topstripe.ibd differ
diff --git a/storage/bdb/dist/winmsi/images/webicon.ico b/storage/bdb/dist/winmsi/images/webicon.ico
new file mode 100644
index 0000000000000000000000000000000000000000..e8b17bff46f38d269d0a44b077919adcc7540250
Binary files /dev/null and b/storage/bdb/dist/winmsi/images/webicon.ico differ
diff --git a/storage/bdb/dist/winmsi/links.in b/storage/bdb/dist/winmsi/links.in
new file mode 100644
index 0000000000000000000000000000000000000000..121102f24194e9cb039b7e939f2069b301933954
--- /dev/null
+++ b/storage/bdb/dist/winmsi/links.in
@@ -0,0 +1,18 @@
+# $Id: links.in,v 1.3 2005/04/15 19:01:13 philipr Exp $
+# Lists links to Web sites to be installed on Windows.
+# If the URL starts with file: it is assumed to be a local file,
+# relative to the installation directory.
+
+# Note: columns below must be separated by tabs.
+
+# shortname	name			URL
+
+sleepycp	"Command Prompt"	"cmd:dbvars.bat"
+sleepywb	"Sleepycat Website"	"http://www.sleepycat.com"
+sleepych	"Change Log for Berkeley DB WIX_DB_VERSION"	"http://www.sleepycat.com/update/WIX_DB_VERSION/if.WIX_DB_VERSION.html"
+sleepynw	"Berkeley DB Newsgroup"	"http://groups-beta.google.com/group/comp.databases.berkeley-db"
+sleepybl	"Blog for Berkeley DB"	"http://www.sleepycat.com/blogs/db/"
+sleepysu	"Support for Berkeley DB"	"http://www.sleepycat.com/supports/index.shtml"
+sleepyon	"Online Documentation"	"http://www.sleepycat.com/supports/documentation.shtml/"
+sleepyst	"Company Store"		"http://www.companystuffonline.com/sleepycat/"
+sleepyld	"On disk Documentation"	"file:docs/index.html"
diff --git a/storage/bdb/dist/winmsi/s_winmsi.fcn b/storage/bdb/dist/winmsi/s_winmsi.fcn
new file mode 100644
index 0000000000000000000000000000000000000000..e053e25ea5963f5010a7713eb6d264537b86f3cc
--- /dev/null
+++ b/storage/bdb/dist/winmsi/s_winmsi.fcn
@@ -0,0 +1,1426 @@
+#	$Id: s_winmsi.fcn,v 1.8 2005/04/16 15:56:44 philipr Exp $
+#
+# The common functions used by the s_winmsi scripts (both
+# for core DB and DB/XML).
+#
+# This script uses several bash extensions that are convenient
+# since we "know" it will always run under Cygwin: shell functions,
+# 'return', declaration of 'local' variables, $(command) syntax,
+# ${#X} (counting chars), ${X#regexp} (searching) $((expr)) (arithmetic)
+#
+# These functions use 'global' variables:
+#   ERRORLOG             - a filename
+#   PRODUCT_NAME         - e.g. "Berkeley DB"
+#   PRODUCT_VERSION      - e.g. "4.1.25", derived from dist/RELEASE
+#   PRODUCT_STAGE        - the staging directory for temp files and builds
+#   PRODUCT_LICENSEDIR   - the tree containing LICENSE and README
+#   PRODUCT_SUB_BLDDIR  - top of the subproduct build e.g. "dbxml-2.0.1/dbxml"
+#   PRODUCT_BLDDIR       - top of the build tree e.g. "dbxml-2.0.1"
+#   PRODUCT_SRCDIR       - the dir we unzip to e.g. "dbxml-2.0.1"
+#   PRODUCT_DBBUILDDIR   - where build_unix dir is for Berkeley DB (for Perl)
+#   PRODUCT_SHARED_WINMSIDIR   - where the master winmsi directory is
+#   PRODUCT_IMAGEDIR     - where the images are (usually winmsi/images)
+#   PRODUCT_ZIP_FILEFMT  - what zip file looks like e.g. "db-X.Y.Z.NC.zip"
+#   PRODUCT_MSI_FILEFMT  - what msi file looks like e.g. "db-X.Y.Z.NC.msi"
+#
+# Some of these may seem redundant, but there are options to take
+# an already built tree from a different place than where we'll unzip
+# to and take our sources from, for example.  This allows a lot of flexibility
+# for development and debugging (especially when these trees can be huge).
+
+# This is the magic tag that creates a new unique GUID in Wix.
+# GUIDs are needed on every <Component ... > entry to ensure
+# that the component can be uninstalled.
+GENGUID='Guid="GUID_CREATE_UNIQUE()"'
+PERSISTGUID='Guid="WIX_DB_PERSISTENT_GUID()"'
+
+# MakeRtf()
+# Standard input is plain text, standard output is RTF.
+#
+MakeRtf() {
+    temp1=/tmp/sbm$$a
+    cat > $temp1
+
+
+# Courier is a good font, but the lines with all caps
+# overflows our current dialog size:
+#     {\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Courier New;}}
+#     \viewkind4\uc1\pard\lang1033\f0\fs16 
+#
+# Using Small fonts works:
+#      {\rtf1\ansi\deff0{\fonttbl{\f0\fswiss\fprq2\fcharset0 Small Fonts;}}
+#      {\colortbl ;\red0\green0\blue0;}
+#      \viewkind4\uc1\pard\cf1\lang1033\f0\fs14 
+
+# Arial is the best compromise:
+    sed -e 's/^ *//' << 'EndOfRTFHeader'
+      {\rtf1\ansi\deff0{\fonttbl{\f0\fswiss\fprq2\fcharset0 Arial;}}
+      {\colortbl ;\red0\green0\blue0;}
+      \viewkind4\uc1\pard\cf1\lang1033\f0\fs16 
+EndOfRTFHeader
+
+# Embedded '<' and '>' can cause problems for Wix
+    sed -e 's:$:\\par:' -e 's:<: \\lquote :' -e 's:>: \\rquote :' < $temp1
+    echo -n '}'
+    rm -f $temp1
+}
+
+# NextId()
+# Get the next available unique id, a simple integer counter.
+# We use a file, rather than a shell variable to track the
+# number, because this is called from subshells at various
+# points, and they cannot affect the variables in the parent shell.
+#
+ComponentID=component.id
+NextId()
+{
+    local id=`cat $ComponentID 2>/dev/null`
+    if [ "$id" = '' ]; then
+       id=0
+    fi
+    id=$(($id + 1))
+    echo "$id" > $ComponentID
+    echo "$id"
+}
+
+# CleanFileName(FILENAME)
+# Removes any strange characters in file names,
+# returning the new name on standard output.
+CleanFileName()
+{
+    echo "$1" | sed -e 's/[-%@!]//g'
+}
+
+# GetShortName(FILENAME)
+# Get a Windows short name for the file,
+# to fit into the 8.3 name space.
+# This is not a great algorithm, but it works.
+# The fact is, the names must be unique, but on
+# Win2000 and WinXP, we'll never see them.
+
+ShortID=short.id
+GetShortName()
+{
+    local name=`echo "$1" | tr '[a-z]' '[A-Z]'`
+
+    # See if the name fits into 8.3. If so,
+    # return it right away.
+    #
+    case "$name" in
+    ?????????*.* )  ;;
+    *.????* )   ;;
+    *.*.* )    ;;
+    *[-%@!]* )    ;;
+    *.* ) echo "$name"
+          return
+          ;;
+    * )
+         if [ "${#1}" -le 8 ]; then
+             echo "$name"
+             return
+         fi
+         ;;
+    esac
+
+    # From NAMEISLONG.EXTLONG, build a name
+    # like NAME~ZZZ.EXT, where ZZZ is a unique (hex)
+    # number we build.  This is 
+
+    local id=`cat $ShortID 2>/dev/null`
+    if [ "$id" = '' ]; then
+       id=0
+    fi
+    id=$(($id + 1))
+    echo "$id" > $ShortID
+    if [ "$id" -ge 4096 ]; then
+        echo "BADBADBAD.TXT"  # return something that will give an error
+        Error "ShortId overflow"
+        exit 1
+    fi
+
+    # Convert the id to hex (I ran out of space using decimal)
+    # This is too slow: id=`echo 16 o $id p | dc`
+    id=`printf "%x" $id`
+
+    # Collect and clean up the part of the name before, and after, the dot
+    local before=`CleanFileName "$name" | sed -e 's/^\([^.]*\)[.].*$/\1/'`
+    local after=`CleanFileName "$name" | sed -e 's/^[^.]*[.]\(.*\)$/\1/'`
+
+    # Make sure the before part fits in 5 chars (not 8, since
+    # we need a few for the unique number).
+    if [ "${#before}" -gt 5 ]; then
+        before=`echo "$before" | sed -e 's/^\(.....\).*/\1/'`
+    fi
+    if [ "${#after}" -gt 3 ]; then
+        after=`echo "$after" | sed -e 's/^\(...\).*/\1/'`
+    fi
+    echo "${before}~${id}.${after}"
+}
+
+# Progress([OPTION,]STRING...)
+# Show a major processing step via echo to stdout and to the error log.
+# An OPTION is "-minor", indicating no big banner.
+#
+Progress()
+{
+    if [ "$1" = -minor ]; then
+       shift
+    else
+       echo "" >> $ERRORLOG
+       echo "============================" >> $ERRORLOG
+    fi
+    echo "$@" >> $ERRORLOG
+    echo "$@" >&15
+}
+
+# Error(STRING...)
+# Show an error in a standard way.
+#
+Error()
+{
+    echo "" >> $ERRORLOG
+    echo "****************** FAIL ******************" >> $ERRORLOG
+    echo "ERROR: $@" >> $ERRORLOG
+    echo "ERROR: $@" >&15
+    echo "See $ERRORLOG for details" >&15
+    return 1
+}
+
+# RequireFileInPath(NAME, PATHVAL, FILE)
+# Look for FILE in the path that has value PATHVAL.
+# The path's name is NAME if it needs to be shown.
+#
+RequireFileInPath()
+{
+    local type="$1"
+    local origpath="$2"
+    local file="$3"
+    local upath="$origpath"
+    if [ "$1" != PATH ]; then
+       upath=`cygpath -up "$origpath"`
+    fi
+
+    SAVEIFS="$IFS"
+    IFS=":"
+    found=no
+    for dir in $upath; do
+        if [ -f "$dir/$file" ]; then
+            IFS="$SAVEIFS"
+            return
+        fi
+    done
+    IFS="$SAVEIFS"
+    Error "File $file not found in $type path: $origpath"
+    exit 1
+}
+
+# Rand4X()
+# Return 4 random hex digits on output
+#
+Rand4X() {
+    # The sed command pads the front with 0's as needed
+    (echo 'obase=16'; echo $RANDOM ) | bc |
+        sed -e 's/^/0000/' -e 's/^.*\(....\)$/\1/'
+    
+}
+
+# RunM4()
+# Run M4, making appropriate substitutions.
+# This function uses GLOBAL variables: PRODUCT_VERSION (e.g. "4.1.25")
+# and PRODUCT_LICENSEDIR, which is where certain text files are found
+#
+RunM4() {
+
+    # Given a version number, like 2.3.45, we want to
+    # create a 8 character name for the directory like db2_3_45.
+    # This name is under a "Sleepycat Software" directory,
+    # so it only needs to be unique within the universe of BDB versions.
+    # TODO: instead of using a version number like $DB_VERSION,
+    # maybe use $DB_VERSION_UNIQUE_NAME which looks like "_2003"
+
+    local DB_8CHAR_VERSION=`echo $PRODUCT_VERSION | sed -e 's/[.]/_/g'`
+    if [ ${#DB_8CHAR_VERSION} -le 6 ]; then
+       DB_8CHAR_VERSION="db$DB_8CHAR_VERSION"
+    elif [ ${#DB_8CHAR_VERSION} -le 7 ]; then
+       DB_8CHAR_VERSION="d$DB_8CHAR_VERSION"
+    else
+       Error "Version number too large for simple version number algorithm"
+       exit 1
+    fi
+
+    # Remove leading ./ from PRODUCT_LICENSEDIR if present.
+    local licensedir=`cygpath -w "$PRODUCT_LICENSEDIR"`
+
+    # Create a GUID prefix of the form: ????????-????-????-????-????
+    # This leaves 8 digits of GUID to be manipulated by m4.
+    local GUID_PREFIX="`Rand4X``Rand4X`-`Rand4X`-`Rand4X`-`Rand4X`-`Rand4X`"
+
+    # -P requires that all m4 macros, like define, eval, etc.
+    # are prefixed, like m4_define, m4_eval, etc.  This avoids
+    # various name conflicts with input files.
+    # TODO: rename DB_SRCDIR as DB_LICENSEDIR
+    m4 -P \
+       -DWIX_DB_VERSION="$PRODUCT_VERSION" \
+       -DWIX_DB_8CHAR_VERSION="$DB_8CHAR_VERSION" \
+       -DWIX_DB_GUID_PREFIX="$GUID_PREFIX" \
+       -DWIX_DB_PRODUCT_NAME="$PRODUCT_NAME" \
+       -DWIX_DB_SRCDIR="$licensedir" \
+       -DWIX_DB_TOP="`cygpath -w $PRODUCT_BLDDIR`" \
+       -DWIX_DB_SHARED_WINMSIDIR="$PRODUCT_SHARED_WINMSIDIR" \
+       -DWIX_DB_IMAGEDIR="`cygpath -w $PRODUCT_IMAGEDIR`" \
+       -DWIX_DB_FEATURE_STRUCTURE="m4_include(features.wixinc)" \
+       -DWIX_DB_DIRECTORY_STRUCTURE="m4_include(directory.wixinc)" \
+       -DWIX_DB_LINKS="m4_include(links.wixinc)" \
+       -DWIX_DB_LICENSE_RTF="m4_include(license.rtf)" \
+       -DWIX_DB_ENV_FEATURE_PROPS="m4_include(envprops.wixinc)" \
+       -DWIX_DB_ENV_FEATURE_SET="m4_include(envset.wixinc)" \
+       -DWIX_DB_ENV_FEATURE_SHOW="m4_include(envshow.wixinc)"
+}
+
+# RunTallow(DIR, OPTIONS)
+# Run Tallow, a tool from the WiX distribution
+RunTallow() {
+    local dir="$1"
+    shift
+
+    Id1=`NextId`
+    Id2=`NextId`
+    Id3=`NextId`
+
+    # Tallow is a tool that walks a tree, producing
+    # a WiX directory heirarchy naming the files.
+    # The IDs it produces are not unique (between tallow
+    # runs), so we must make them so here.  Thus "directory78"
+    # becomes "MyFeatureName.123.78" where 123 is an id from NextId.
+    # Secondly, instead of using the tallow output as a separately
+    # compiled fragment, we want to include it directly, so
+    # we need to strip out some extraneous XML entries at the top
+    # and bottom of its output.
+    #
+    # Another thing we do is when we see <Directory></Directory>
+    # pairs, we call m4 macros WIX_DB_{BEGIN,END}_SUBDIR because
+    # we need to track the current directory to generate 'persistent'
+    # GUIDs.  See the discussion about GUIDs in dbwix.m4 .
+    #
+    # !!! For stripping out the extraneous XML, we rely heavily
+    # !!! on the output format, so this is likely to be fragile
+    # !!! between versions of tallow.  Fortunately, it should fail hard.
+    #
+    echo "=============" >> tallow.log
+    echo tallow -nologo -d `cygpath -w "$dir"` "$@" >> tallow.log
+    echo "  <!-- TALLOW output begins here -->"
+         tallow -nologo -d `cygpath -w "$dir"` "$@" > tallow.out || exit 1
+    cat tallow.out >> tallow.log
+    echo "-------------" >> tallow.log
+
+    sed -e '1,/<DirectoryRef/d' -e '/<\/DirectoryRef/,$d' \
+        -e "s/Id=\"directory/Id=\"$feature.$Id1./" \
+        -e "s/Id=\"component/Id=\"$feature.$Id2./" \
+        -e "s/Id=\"file/Id=\"$feature.$Id3./" \
+        -e '/^      <Directory/d' \
+        -e '/^      <\/Directory/d' \
+        -e '/<Directory/s/Name=\"\([^"]*\)"/Name="\1" WIX_DB_BEGIN_SUBDIR(\1) /' \
+        -e '/<\/Directory>/s/$/ WIX_DB_END_SUBDIR()/' \
+        -e "/<Component/s/>/ $PERSISTGUID>/" \
+        < tallow.out > tallow.postsed || exit 1
+
+    echo 'WIX_DB_SET_CURFILE()'
+    echo 'WIX_DB_CLEAR_SUBDIR()'
+    cat tallow.postsed
+    echo 'WIX_DB_CLEAR_SUBDIR()'
+
+    cat tallow.postsed >> tallow.log
+    echo "  <!-- TALLOW output ends here -->"
+}
+
+# ProcessFeatures(INFILES, INFEATURES, INENV, OUTDIRECTORIES, OUTFEATURES,
+#                 OUTSET)
+# Use the files.in and features.in files as
+# input to create two output files, one containing a WiX XML
+# fragment showing directories and needed files,
+# and another containing a WiX XML fragment showing
+# the features in a dependency tree.
+#
+# This creates the heart of the installer flexibility.
+#
+ProcessFeatures() {
+   InFiles="infiles.tmp";  CleanInputFile "$1" "$InFiles" 3 4
+   InFeatures="infeatures.tmp"; CleanInputFile "$2" "$InFeatures" 3 4
+   InEnv="inenv.tmp"; CleanInputFile "$3" "$InEnv" 3 4
+   OutDirs="$4"
+   OutFeatures="$5"
+   OutSet="$6"
+
+   rm -f $OutDirs; touch $OutDirs
+   rm -f $OutFeatures; touch $OutFeatures
+
+   # Initialize the feature list.
+   # This will be expanded (per feature) in ProcessOneFeature
+   #
+   XmlLevel=4
+   Xecho "<Publish Property=\"FeatureList\" Value=\"[NULL]\">" >> $OutSet
+   Xecho "  <![CDATA[1]]></Publish>" >> $OutSet
+
+   Dirs=`cut -f 3 < $InFiles | sort | uniq`
+   Prevdir="/"
+   ProcessDirTransition "$Prevdir" "/" >> $OutDirs
+
+   for Dir in $Dirs; do
+      ProcessDirTransition "$Prevdir" "$Dir" >> $OutDirs
+      ProcessOneDirectory "$Dir" < $InFiles >> $OutDirs || exit 1
+      Prevdir="$Dir"
+   done
+   ProcessDirTransition "$Prevdir" "/" >> $OutDirs
+
+   cat $InEnv | (
+      read line
+      while [ "$line" != '' ]; do
+         local FeatureName=`echo "$line" | cut -f 1`
+         local EnvVariable=`echo "$line" | cut -f 2`
+         local EnvValue=`echo "$line" | cut -f 3`
+         local EnvOption=`echo "$line" | cut -f 4`
+         ProcessOneEnv "$FeatureName" "$EnvVariable" "$EnvValue" "$EnvOption" "$OutDirs" "$OutSet"
+         read line
+      done
+      return 0
+   ) || Error "Error processing environment" || exit 1
+
+   cat $InFeatures | (
+      read line
+      while [ "$line" != '' ]; do
+         local FeaturePath=`echo "$line" | cut -f 1`
+         local ShortName=`echo "$line" | cut -f 2 | StripDoubleQuotes`
+         local Description=`echo "$line" | cut -f 3 | StripDoubleQuotes`
+         local FeatureOptions=`echo "$line" | cut -f 4 | StripDoubleQuotes`
+         ProcessOneFeature "$FeaturePath" "$ShortName" "$Description" "$FeatureOptions" "$OutDirs" "$OutFeatures" "$OutSet"
+         read line
+      done
+      return 0
+   ) || Error "Error processing features" || exit 1
+
+# (PBR)
+# This test code didn't work. My hope was that I could force INSTALLLEVEL
+# to 4 and this would then enable the debug features.
+#   Xecho "<Publish Property=\"INSTALLLEVEL\" Value=\"4\" />" >> $OutSet
+#   Xecho "<Publish Event=\"SetInstallLevel\" Value=\"4\" />" >> $OutSet
+
+}
+
+# ProcessLinks(INLINKS, OUTFEATURES)
+# Process the INLINKS file, and produce XML on stdout.
+# Each line of the input file requires the creation
+# of a '.URL' file in the installation, and a Shortcut
+# in the Windows menu to point to that.
+# Also add the components generated to a feature, put in OUTFEATURES.
+#
+# TODO: We ought to have a Features column in the links.in file,
+# otherwise, the local doc link is always installed.
+#
+ProcessLinks() {
+   # Set a var to a carriage return without actually putting one in this file
+   local CR=`echo A | tr A '\015'`
+   local InLinks="infiles.tmp";  CleanInputFile "$1" "$InLinks" 3 4
+   local here_win=`cygpath -w $(pwd)`
+   # TODO: maybe get a real modification time, but not sure why we need it.
+   local MODTIMEHEX="0000000007DCC301DE"
+   XmlLevel=6
+   local OutFeatures="$2"
+
+   Xecho + "<Feature Id=\"LinksFeature\" Title=\"Links\"" >> $OutFeatures
+   Xecho "   Description=\"Links\" Display=\"hidden\"" >> $OutFeatures
+   Xecho "   Level=\"1\" AllowAdvertise=\"no\"" >> $OutFeatures
+   Xecho "   ConfigurableDirectory=\"INSTALLUTIL\"" >> $$OUTFeatures
+   Xecho "   Absent=\"disallow\">" >> $OutFeatures
+
+   Xecho "<DirectoryRef Id=\"INSTALLUTIL\">"
+   Xecho " <Directory Id=\"INSTALLURL\" Name=\"url\">"
+   Xecho "WIX_DB_SET_CURDIR(/installutil/url)"
+   cat $InLinks | (
+      read line
+      while [ "$line" != '' ]; do
+         local Shortname=`echo "$line" | cut -f 1 | StripDoubleQuotes`
+         local Name=`echo "$line" | cut -f 2 | StripDoubleQuotes`
+         local Url=`echo "$line" | cut -f 3 | StripDoubleQuotes`
+         read line
+
+         # We register the name .bdbsc extension to get the proper icon
+         local UrlName="$Shortname.bdbsc"
+         local UrlShortName="$Shortname.d1b"
+         local TargetFile="[INSTALLDIR]\\installutil\\url\\$UrlName"
+         local CreateUrlFile=true
+         local CommandShortcut=false
+	 local Program=""
+	 case "$Url" in
+         file:* ) CreateUrlFile=false
+                  TargetFile=`echo $Url | sed -e 's/file://'`
+                  TargetFile="[INSTALLDIR]"`cygpath -w $TargetFile`;;
+         cmd:* )  CreateUrlFile=false
+		  UrlName="$Shortname.bat"
+                  UrlShortName="$Shortname.bat"
+	          TargetFile="[INSTALLDIR]\\installutil\\url\\$UrlName"
+                  Program=`echo $Url | sed -e 's/cmd://'`
+                  CommandShortcut=true;;
+         esac
+
+         Xecho "WIX_DB_SET_CURFILE($Shortname)"
+         Xecho + "<Component Id=\"Links.$Shortname\""
+         Xecho "   $PERSISTGUID"
+         Xecho "   SharedDllRefCount=\"yes\" Location=\"either\">"
+
+         if $CreateUrlFile; then
+            echo "[Default]$CR"                 > $UrlName
+            echo "BASEURL=$Url$CR" | RunM4     >> $UrlName   || exit 1
+            echo "[InternetShortcut]$CR"       >> $UrlName
+            echo "URL=$Url$CR"     | RunM4     >> $UrlName   || exit 1
+            echo "Modified=$MODTIMEHEX$CR"     >> $UrlName
+            # TODO: we could have an Entry for IconFile=sleepyweb.ico IconIndex=1?
+            echo ''
+            Xecho "<File Id=\"File.$Shortname\" "
+            Xecho "   LongName=\"$UrlName\" Name=\"$UrlShortName\""
+            Xecho "   Compressed=\"yes\" DiskId=\"1\""
+            Xecho "   src=\"$here_win\\$UrlName\" />"
+         fi
+
+         if $CommandShortcut; then
+	   echo "@echo off"                               > $UrlName
+           echo "set DBROOTDIR="                         >> $UrlName
+           echo "for /F \"tokens=3 delims=	\" %%A in ('REG QUERY \"HKLM\\SOFTWARE\\Sleepycat Software\\$PRODUCT_NAME\\$PRODUCT_VERSION\" /v RootDirectory') do set DBROOTDIR=%%A"                                   >> $UrlName
+           echo "if ERRORLEVEL 2 goto MISSING"           >> $UrlName
+           echo "if not defined DBROOTDIR goto MISSING"  >> $UrlName
+           echo "set FN=\"%DBROOTDIR%$Program\""         >> $UrlName
+           echo "if not exist %FN% goto NOTFOUND"        >> $UrlName
+           echo "cmd /k \"%DBROOTDIR%$Program\"$CR"      >> $UrlName
+           echo "goto END"                               >> $UrlName
+           echo ":NOTFOUND"                              >> $UrlName
+           echo "echo"                                   >> $UrlName
+           echo "echo  Error: The program does not appear to be installed." >> $UrlName
+           echo "echo"                                   >> $UrlName
+           echo "cmd /k"                                 >> $UrlName
+           echo "goto END"                               >> $UrlName
+           echo ":MISSING"                               >> $UrlName
+           echo "echo"                                   >> $UrlName
+           echo "echo NOTE:"                             >> $UrlName
+           echo "echo   The $PRODUCT_NAME version could not be determined." >> $UrlName
+           echo "echo   If you are running on Windows 2000, make sure the" >> $UrlName
+           echo "echo   REG.EXE program is installed from the Tools disk" >> $UrlName
+           echo "echo"                                   >> $UrlName
+           echo "cmd /k"                                 >> $UrlName
+           echo ":END"                                   >> $UrlName
+
+           Xecho "<File Id=\"File.$Shortname\" "
+           Xecho "   LongName=\"$UrlName\" Name=\"$UrlShortName\""
+           Xecho "   Compressed=\"yes\" DiskId=\"1\""
+           Xecho "   src=\"$here_win\\$UrlName\" />"
+
+           Xecho "<Shortcut Id=\"Short.$Shortname\" Directory=\"BerkeleyDbMenu\""
+           Xecho "   Name=\"$Shortname\" LongName=\"$Name\""
+	   Xecho "   WorkingDirectory=\"[INSTALLDIR]\""
+           Xecho "   Target='$TargetFile'"
+           Xecho "   Show=\"normal\" />"
+         else
+           Xecho "<Shortcut Id=\"Short.$Shortname\" Directory=\"BerkeleyDbMenu\""
+           Xecho "   Name=\"$Shortname\" LongName=\"$Name\""
+           Xecho "   Target='$TargetFile'"
+           Xecho "   Show=\"normal\" />"
+         fi
+     
+
+         Xecho - "</Component>"
+
+         Xecho "<ComponentRef Id=\"Links.$Shortname\" />" >> $OutFeatures
+      done
+      return 0
+   ) || Error "Error processing links" || exit 1
+
+   Xecho "</Directory>"
+   Xecho "</DirectoryRef>"
+   Xecho - "</Feature>"  >> $OutFeatures
+}
+
+# ProcessOneDirectory(DIRECTORYNAME)
+# Called by ProcessFeatures.
+# Argument is the directory name to process
+# Standard input is cleaned up files.in (dirname is 3rd column)
+# Standard output will be WiX XML Component/File entries
+#
+ProcessOneDirectory()
+{
+  Dir="$1"
+  grep "	${Dir}	" | (
+    read line
+    while [ "$line" != '' ]; do
+      local feature=`echo "$line" | cut -f 1`
+      local srcfile=`echo "$line" | cut -f 2`
+      local targetdir=`echo "$line" | cut -f 3`
+      local shortname=`echo "$line" | cut -f 4`
+
+      ProcessOneDirectoryFile "$feature" "$srcfile" "$targetdir" "$shortname" || exit 1
+      read line
+    done
+    return 0
+  ) || Error "Error processing directory $Dir" || exit 1
+}
+
+# ProcessOneDirectoryFile(DIRECTORYNAME)
+# Called by ProcessOneDirectory to process a single file in a directory.
+# Standard output will be a single WiX XML Component/File entries
+#
+ProcessOneDirectoryFile()
+{
+   local feature="$1"
+   local srcfile="$2"
+   local targetdir="$3"
+   local shortname="$4"
+   local base=`basename $srcfile`
+
+   #echo "processing file $srcfile in $feature to directory $targetdir..." >&2
+
+   # Prepend the WIX_DB_TOP unless the source file is absolute
+
+   local root=
+   local checkfile=
+   local wsrcfile=
+
+   case "$srcfile" in
+   /* )  root=""
+         wsrcfile=`cygpath -w $srcfile`
+         checkfile="$srcfile"
+         ;;
+   * )   root="$PRODUCT_BLDDIR/"
+         wsrcfile="WIX_DB_TOP()\\`cygpath -w $srcfile`"
+         checkfile="$PRODUCT_BLDDIR/$srcfile"
+         ;;
+   esac
+
+   # If srcfile ends in / then we'll use tallow to walk the directory
+   case "$srcfile" in
+    */ ) if [ ! -d "$root$srcfile" ]; then
+            Error "$root$srcfile: not a directory"
+            exit 1
+         fi
+         Progress -minor "  expanding $root$srcfile..."
+         RunTallow "$root$srcfile"
+         return 0
+    ;;
+    *'*'* )
+         local dirname=`dirname "$root$srcfile"`
+         RunTallow "$dirname" -df "$base"
+         return 0
+    ;;
+   esac
+
+   if [ "$shortname" = '' ]; then
+     shortname=`GetShortName "$base"`
+   fi
+   ID=`NextId`
+
+   if [ ! -r "$checkfile" ]; then
+     Error "$srcfile: file in feature $feature does not exist"
+     Error "  curdir=`pwd`, pathname=$checkfile"
+     exit 1
+   fi
+
+   Xecho "WIX_DB_SET_CURFILE(${base})"
+   Xecho + "<Component Id=\"$feature.$ID\" Location=\"either\" $PERSISTGUID>"
+   Xecho "<File Id=\"${feature}.${ID}\" Name=\"${shortname}\" LongName=\"${base}\" Compressed=\"yes\" KeyPath=\"yes\" DiskId=\"1\" src=\"${wsrcfile}\" />"
+   Xecho - "</Component>"
+   return 0
+}
+
+# ProcessOneFeature(FEATUREPATH, SHORTNAME, DESCRIPTION, OPTS, INDIRECTORYFILE,
+#                   OUTFEATURE, OUTSET)
+# Called by ProcessFeatures to process a line in the features.in file.
+# The first three arguments are the values of the first three columns:
+# the feature dependency path (e.g. "Java/JavaExamples"), the short
+# name, and a descriptive name.  The last argument is the directory
+# file that lists the components.  We use the last name of the feature
+# path (e.g. JavaExamples) to locate all components (really directories)
+# named accordingly, so they can be listed as needed parts of the Feature.
+# Standard output will be WiX XML Feature entries.
+#
+ProcessOneFeature() {
+      local featurename="$1"
+      local shortname="$2"
+      local opts="$4"
+      local dirfile="$5"
+      local outfeature="$6"
+      local outset="$7"
+
+      XmlLevel=4
+      local featcount=0
+      local featurestring=""
+      while [ $(SlashCount $featurename) != 0 ]; do
+         Parent=`echo $featurename | sed -e 's:/.*::'`
+         featurename=`echo $featurename | sed -e 's:^[^/]*/::'`
+         featcount=$(($featcount + 1))
+         Xecho "<FeatureRef Id=\"$Parent\">" >> $outfeature
+      done
+
+
+      # TODO: how to get +default to work?
+      #    have tried messing with level="0" (doesn't show it)
+      #    InstallDefault=\"source\" (doesn't make a difference)
+      #
+      local leveldebug="Level=\"4\""
+      local levelparam="Level=\"1\""
+      local leveldisable="Level=\"0\""
+      local defparam="InstallDefault=\"source\""
+      local displayparam="Display=\"expand\""
+      local params="AllowAdvertise=\"no\""
+      local regfeature=""
+
+      local descparam=""
+      if [ "$3" != '' ]; then
+         descparam="Description=\"$3\""
+      fi
+
+      local opt
+      local reqtext=""
+      local isdebugFeature=false
+      for opt in $opts; do
+        case "$opt" in
+        +default )         ;;
+        +required )        params="$params Absent=\"disallow\""
+                           reqtext=" (required)";;
+        +invisible )       displayparam="Display=\"hidden\""
+                           params="$params Absent=\"disallow\"";;
+        +debug )           isdebugFeature=true;;
+
+        * )                Error "features.in: Bad option $opt"
+                           exit 1;;
+        esac
+      done
+
+
+# (PBR)
+# I tried to get debugging features to work but I could not. The last thing I
+# tried was to set either ADDSOURCE or INSTALLLEVEL. Neither of these solutions
+# will cause the feature conditions to rerun. The only thing I've found to do
+# that is to rerun CostFinalize. The problem with this is it will re-enable all
+# the options again. I'm keeping the basic framework for +debug support
+      if "$isdebugFeature"; then
+        regfeature="${featurename:1}"
+        echo "regfeature = $regfeature"
+
+        Xecho + "<Feature Id=\"$featurename\" Title=\"$shortname$reqtext\" $descparam $params $displayparam $leveldebug $defparam>" >> $outfeature
+      else
+        Xecho + "<Feature Id=\"$featurename\" Title=\"$shortname$reqtext\" $descparam $params $displayparam $levelparam $defparam>" >> $outfeature
+      fi
+
+
+      grep 'Component.*Id="'$featurename'[.0-9]*"' "$dirfile" | sed -e 's/\(Id="[^"]*"\).*/\1 \/>/' -e 's/Component /ComponentRef /' >> $outfeature
+
+      # Create a separate subfeature for any environment variables
+      # associated with the main feature.
+      # The <Condition> stuff is the magic that enables/disables
+      # setting the environment variables depending on the check box property.
+
+      Xecho + "<Feature Id=\"env.$featurename\" Title=\"env vars\" $params Display=\"hidden\" $levelparam $defparam>" >> $outfeature
+
+      Xecho "<Condition $leveldisable><![CDATA[EnvironmentSetCheck<>1]]></Condition>" >> $outfeature
+      Xecho "<Condition $levelparam><![CDATA[EnvironmentSetCheck=1]]></Condition>" >> $outfeature
+      grep 'Component.*Id="env\.'$featurename'[.0-9]*"' "$dirfile" | sed -e 's/\(Id="[^"]*"\).*/\1 \/>/' -e 's/Component /ComponentRef /' >> $outfeature
+
+      Xecho - "</Feature>" >> $outfeature
+      Xecho - "</Feature>" >> $outfeature
+
+      while [ "$featcount" -gt 0 ]; do
+         Xecho - "</FeatureRef>"  >> $outfeature
+         featcount=$(($featcount - 1))
+      done
+
+      # Append the name to the feature list if it is to be installed.
+      # This publish fragment gets 'executed' when leaving the
+      # dialog to select features.  Note that we have to quote
+      # the comma for m4 (`,') since this appears in a macro usage.
+      #
+
+# (PBR)
+# This code sets ADDSOURCE to show which debug options to include. This does not work
+      # If this is a debug feature, only turn on the value if the parent is on
+      if "$isdebugFeature"; then
+ 	  regfeature="${featurename:1}"
+
+#          Xecho "<Publish Property=\"ADDSOURCE\" Value=\"[ADDSOURCE]\`,'\">" >> $outset
+#          Xecho "  <![CDATA[&${regfeature} = 3 AND DebugCheck=\"yes\" AND ADDSOURCE <> NULL]]></Publish>" >> $outset
+
+#          Xecho "<Publish Property=\"ADDSOURCE\" Value=\"[ADDSOURCE]${featurename}\">" >> $outset
+#          Xecho "  <![CDATA[&${regfeature} = 3 AND DebugCheck=\"yes\"]]></Publish>" >> $outset
+
+          Xecho "<Publish Property=\"FeatureList\" Value=\"[FeatureList]\`,' ${shortname}\">" >> $outset
+          Xecho "  <![CDATA[&${regfeature} = 3 AND DebugCheck=\"yes\"]]></Publish>" >> $outset
+
+      else
+        Xecho "<Publish Property=\"FeatureList\" Value=\"[FeatureList]\`,' ${shortname}\">" >> $outset
+        Xecho "  <![CDATA[&${featurename} = 3]]></Publish>" >> $outset
+      fi
+}
+
+# ProcessOneEnv(FEATURE, ENVNAME, ENVVALUE, OPTS, OUTDIRS, OUTSET)
+# Called by ProcessFeatures to process a line in the environment.in file.
+# The four arguments are the values of the four columns.
+# The output will be into two files:
+#   OUTDIRS: WiX XML Component entries, that contain environment values.
+#            This controls the actual setting of the variables.
+#   OUTSET:   WiX XML to set the installer variables if an env variable
+#             is set or a feature selected.
+#
+ProcessOneEnv() {
+      local feature="$1"
+      local envname="$2"
+      local envvalue="$3"
+      local opts="$4"
+      local outdirs="$5"
+      local outset="$6"
+
+      # Make the path uniform.
+      # echo "c:\Program Files\...\/Lib/Hello" | sed -e 's:\\/:\\:' -e 's:/:\\:g`
+      # This produces c:\Program Files\...\Lib\Hello
+      case "$envvalue" in
+      /* ) envvalue=`echo "$envvalue" | sed -e 's:^/::'`
+      esac
+
+      local path="[INSTALLDIR]$envvalue"
+
+      local opt
+      part="last"
+      for opt in $opts; do
+        case "$opt" in
+        +first )         part="first";;
+        +last )          part="last";;
+        * )                Error "environment.in: Bad option $opt"
+                           exit 1;;
+        esac
+      done
+
+      # Generate the OUTDIRS fragment
+      # This looks like:
+      #
+      # <Component Id="env.CoreAPI.43" Guid="4B75755F-1129-292C-3434-238410000247">
+      #   <Environment Id="env.44" Name="+-LIB" Action="set"
+      #     Permanent="no" Part="first" Value="[INSTALLDIR]Lib" />
+      # </Component>
+      #
+      # Having a unique guid makes uninstall work.
+      # Note: We really want these installed as System rather than
+      # User vars (using the System="yes" tag), but only if user
+      # installs for *all* users.  There is no convenient way to
+      # do that, so we leave them as default (User variables).
+
+
+      XmlLevel=4
+      local Id=`NextId`
+      Xecho "WIX_DB_SET_CURFILE(${envname})" >> $outdirs
+      Xecho + "<Component Id=\"env.$feature.$Id\" $PERSISTGUID>"    >> $outdirs
+      Id=`NextId`
+
+      Xecho "<Environment Id=\"env.$Id\" Name=\"+-$envname\" Action=\"set\""  >> $outdirs
+      Xecho "  Permanent=\"no\" Part=\"$part\" Value=\"$path\" />"  >> $outdirs
+
+      Xecho "</Component>"   >> $outdirs
+
+      # Generate the OUTSET fragment
+      # This looks like:
+      #
+      #    <Publish Property="CLASSPATHValue" Value="[INSTALLDIR]Lib/db.jar;[CLASSPATHValue]">
+      #      <![CDATA[&JavaAPI = 3]]></Publish>
+      #    <Publish Property="CLASSPATHEscValue" Value="[INSTALLDIR]Lib/db.jar;[CLASSPATHEscValue]">
+      #      <![CDATA[&JavaAPI = 3]]></Publish>
+      #
+      # This is equivalent to pseudocode:
+      #      if (InstallFeature(JavaAPI)) {
+      #           Prepend CLASSPATHValue with "Lib/db.jar;"
+      #           Prepend CLASSPATHEscValue with "Lib/db.jar;"
+      #      }
+      #
+      XmlLevel=4
+      Xecho "<Publish Property=\"${envname}Value\" Value=\"[INSTALLDIR]${envvalue};[${envname}Value]\">" >> $outset
+      Xecho "   <![CDATA[&${feature} = 3]]></Publish>" >> $outset
+
+      Xecho "<Publish Property=\"${envname}EscValue\" Value=\"[INSTALLDIR]${envvalue};[${envname}EscValue]\">" >> $outset
+      Xecho "   <![CDATA[&${feature} = 3]]></Publish>" >> $outset
+
+      
+}
+
+# CreateProperty(ID, VALUE)
+# Generate a <Property...> tag on the stdout
+CreateProperty() {
+   Xecho "<Property Id=\"$1\" Hidden=\"yes\"><![CDATA[$2]]></Property>"
+}
+
+# ProcessTagProperties(OUTPROPS)
+# Generate some identification tags as properties.
+# This will let us look at an installer and figure out
+# when it was built, etc.
+ProcessTagProperties() {
+   local outprops="$1"
+   local insdate=`date`
+   XmlLevel=4
+
+   CreateProperty _DB_MSI_INSTALLER_DATE "$insdate"   >> $outprops
+   CreateProperty _DB_MSI_PRODUCT_NAME "$PRODUCT_NAME" >> $outprops
+   CreateProperty _DB_MSI_PRODUCT_VERSION "$PRODUCT_VERSION" >> $outprops
+   CreateProperty ARPCOMMENTS "Installer for $PRODUCT_NAME $PRODUCT_VERSION built on $insdate" >> $outprops
+}
+    
+# ProcessEnv(INENVFILE, INBATFILE, OUTPROPS, OUTSET, OUTSHOW)
+# We generate some Property magic to show the user what is set.
+#
+ProcessEnv() {
+   InEnv="inenv.tmp"; CleanInputFile "$1" "$InEnv" 3 4
+   inbat="$2"
+   outprops="$3"
+   outset="$4"
+   outshow="$5"
+
+   # Get a list of the environment variables
+   local envvar
+   local envvars=`cut -f 2 < $InEnv | sort | uniq`
+
+   # For each environment var, create lines that declare
+   # a pair of properties in the envprops.wixinc file like:
+   #
+   #  <Property Id="CLASSPATHValue" Hidden="yes"></Property>
+   #  <Property Id="CLASSPATHEscValue" Hidden="yes"></Property>
+   #
+   # And create lines in the envset.wixinc file like:
+   #
+   #   <Publish Property="CLASSPATHValue" Value="%CLASSPATH%">
+   #        <![CDATA[1]]></Publish>
+   #   <Publish Property="CLASSPATHEscValue" Value="\\%CLASSPATH\\%">
+   #        <![CDATA[1]]></Publish>
+   #
+   # More will be added to that file later.
+   # Then, create lines in the envshow.wixinc file like:
+   #
+   #  <Control Id="CLASSPATHText" Type="Text"
+   #               X="23" Width="316" PARTIALHEIGHT(10, 2)
+   #               TabSkip="no" Text="CLASSPATH:" />
+   #
+   #  <Control Id="CLASSPATHValueText" Type="Text"
+   #               X="37" Width="316" PARTIALHEIGHT(20, 7)
+   #               TabSkip="no" Text="[CLASSPATHValue]" />
+
+   for envvar in $envvars; do
+      XmlLevel=4
+      CreateProperty "${envvar}Value" "" >> $outprops
+      CreateProperty "${envvar}EscValue" "" >> $outprops
+
+      XmlLevel=4
+      Xecho "<Publish Property=\"${envvar}Value\" Value=\"%${envvar}%\">" >> $outset
+      Xecho "      <![CDATA[1]]></Publish>" >> $outset
+      Xecho "<Publish Property=\"${envvar}EscValue\" Value=\"\\%${envvar}\\%\">" >> $outset
+      Xecho "      <![CDATA[1]]></Publish>" >> $outset
+
+      XmlLevel=4
+      Xecho "<Control Id=\"${envvar}Text\" Type=\"Text\""  >> $outshow
+      Xecho "         X=\"23\" Width=\"316\" PARTIALHEIGHT(10, 2)" >> $outshow
+      Xecho "         TabSkip=\"no\" Text=\"${envvar}:\" />"  >> $outshow
+
+      Xecho "<Control Id=\"${envvar}ValueText\" Type=\"Text\"" >> $outshow
+      Xecho "         X=\"37\" Width=\"316\" PARTIALHEIGHT(20, 7)" >> $outshow
+      Xecho "         TabSkip=\"no\" Text=\"[${envvar}Value]\" />" >> $outshow
+
+   done
+
+   # Create the dbvars.bat file from the .bat template file
+   # TODO: the bat template file currently knows the variables
+   #       and their values, it should get them from the environment.in
+
+   RunM4 <"$inbat" >"$PRODUCT_STAGE/dbvars.bat" || Error "m4 failed" || exit 1
+}
+
+
+# CleanInputFile(INFILENAME, OUTFILENAME, MINELEMENTS, MAXELEMENTS)
+# A filter to preprocess and validate input files.
+# We end up without comment lines, a single tab between elements,
+# and a trailing tab.
+# Also some selected shell variables are expanded for convenience.
+# We verify that each line has the number of elements that fall within
+# the given min and max.
+#
+CleanInputFile() {
+   sed \
+        -e 's/#.*//' \
+        -e 's/ *	/	/g' \
+        -e 's/	 */	/g' \
+        -e '/^[ 	]*$/d' \
+        -e 's/$/	/' \
+        -e 's/		*/	/g'  \
+        -e 's:\${PRODUCT_VERSION}:'"${PRODUCT_VERSION}":g \
+        -e 's:\${PRODUCT_STAGE}:'"${PRODUCT_STAGE}":g \
+	-e 's:\${PRODUCT_SHARED_WINMSIDIR}:'"${PRODUCT_SHARED_WINMSIDIR}":g \
+          < "$1" > "$2"
+
+   # count tabs on each line
+   sed -e 's/[^	]//g' -e 's/[	]/x/g' < "$2" | (
+        read line
+        linecount=1
+        while [ "$line" != '' ]; do
+            chars=`echo "$line" | wc -c`
+            chars=$(($chars - 1))  # Remove newline
+            if [ "$chars" -lt "$3" -o "$chars" -gt "$4" ]; then
+               Error "$1: Input file error on or after line $linecount"
+            fi
+            read line
+            linecount=$(($linecount + 1))
+        done
+   )
+}
+
+# StripDoubleQuotes()
+# In some input files, we allow double quotes around
+# multi-word strings for readability.  We strip them
+# here from standard input and write to standard output.
+# We only expect them at the beginning and end.
+#
+StripDoubleQuotes() {
+   sed -e 's/^"//' -e 's/"$//'
+}
+
+# IndentXml(PLUSMINUS_ARG)
+# A global variable $XmlLevel is kept for the indent level.
+# Every call creates blank output that matches the indent level.
+# In addition, with a '-' argument, the indent level
+# decrements by one before printing.
+# With a '+', the indent level increments after printing.
+# This is generally just used by Xecho
+#
+XmlLevel=0
+IndentXml() {
+   if [ "$1" = '-' -a $XmlLevel != 0 ]; then
+     XmlLevel=$(($XmlLevel - 1))
+   fi
+   local idx=0
+   while [ "$idx" != "$XmlLevel" ]; do
+     echo -n '  '
+     idx=$(($idx + 1))
+   done
+   if [ "$1" = '+' ]; then
+     XmlLevel=$(($XmlLevel + 1))
+   fi
+}
+
+# Xecho [ - | + ] ...
+# echoes arguments (like) echo, except that the output
+# is indented for XML first.  If +, the indentation changes
+# after printing, if -, the indentation changes before printing.
+#
+Xecho()
+{
+   local xarg=
+   if [ "$1" = '-' -o "$1" = '+' ]; then
+      xarg="$1"
+      shift
+   fi
+   IndentXml $xarg
+   echo "$@"
+}
+
+# SlashCount(PATH)
+# Returns the number of slashes in its argument
+# Note, we are relying on some advanced
+# features of bash shell substitution
+#
+SlashCount()
+{
+   local allslash=`echo "$1" | sed -e 's:[^/]*::g'`
+   echo "${#allslash}"
+}
+
+# ProcessDirTransition(PREVDIR, NEXTDIR)
+# Used by ProcessFeatures to create the parts
+# of an WiX <Directory> heirarchy (on stdout) needed to
+# transition from directory PREVDIR to NEXTDIR.
+# This may include any needed </Directory> entries as well.
+# For example, ProcessDirTransition /Bin/Stuff /Bin/Foo/Bar
+# produces:
+#    </Directory>      ...to go up one from 'Stuff'
+#    <Directory Foo>
+#      <Directory Bar>
+#
+ProcessDirTransition() {
+   local p="$1"
+   local n="$2"
+   if [ "$p" = '' ]; then p=/; fi
+   if [ "$n" = '' ]; then n=/; fi
+   local nextdir="$2"
+
+   # The number of slashes in $p is the current directory level.
+   XmlLevel=$(($(SlashCount $p) + 4))
+
+   while [ "$p" != / ]; do
+      if [ "${n#${p}}" != "$n" ]; then
+         break
+      fi
+
+      # go up one level, and keep $p terminated with a /
+      p=`dirname $p`
+      case "$p" in
+      */ )   ;;
+      * )    p=$p/;;
+      esac
+      Xecho - "</Directory>"
+   done
+   n=${n#${p}}
+   while [ "$n" != '' ]; do
+      local dirname=`echo $n | sed -e 's:/.*::'`
+      local cleanname=`CleanFileName "$dirname"`
+      local shortname=`GetShortName "$cleanname"`
+      local dirid=`NextId`
+
+      local larg=""
+      if [ "${shortname}" != "${dirname}" ]; then
+          larg="LongName=\"${dirname}\""
+      fi
+      Xecho + "<Directory Id=\"${cleanname}Dir.$dirid\" Name=\"${shortname}\" $larg>"
+
+      n=`echo $n | sed -e 's:^[^/]*/::'`
+   done
+
+   Xecho "WIX_DB_SET_CURDIR($nextdir)"      # Tell the m4 macro what the current dir is
+}
+
+# SetupErrorLog()
+# Given the global variable ERRORLOG for the name of the
+# error output file, do any setup required to make that happen.
+#
+SetupErrorLog() {
+
+    # Before we start to use ERRORLOG, we get a full pathname,
+    # since the caller may change directories at times.
+    case "$ERRORLOG" in
+    /* ) ;;
+    *)   ERRORLOG=`pwd`"/$ERRORLOG" ;;
+    esac
+
+    rm -f $ERRORLOG
+
+    # File descriptor tricks.
+    # Duplicate current stderr to 15, as we'll occasionally
+    # need to report progress to it.  Then, redirect all
+    # stderr from now on to the ERRORLOG.
+    # 
+    exec 15>&2
+    exec 2>>$ERRORLOG
+}
+
+# RequireCygwin
+# Cygwin does not install certain needed components by default.
+# Check to make sure that everything needed by the script
+# and functions is here.
+#
+RequireCygwin() {
+    Progress -minor "checking for Cygwin..."
+    RequireFileInPath PATH "$PATH" m4
+    RequireFileInPath PATH "$PATH" gcc
+    RequireFileInPath PATH "$PATH" make
+    RequireFileInPath PATH "$PATH" unzip
+    RequireFileInPath PATH "$PATH" bc
+    RequireFileInPath PATH "$PATH" openssl    # needed for MD5 hashing
+}
+
+# RequireJava()
+# A java SDK (with include files) must be installed
+#
+RequireJava() {
+    Progress -minor "checking for Java..."
+    RequireFileInPath INCLUDE "$INCLUDE" jni.h
+    RequireFileInPath INCLUDE "$INCLUDE" jni_md.h
+    RequireFileInPath PATH "$PATH" jar.exe
+    RequireFileInPath PATH "$PATH" javac.exe
+}
+
+# RequireTcl()
+# A Tcl SDK (with compatible .lib files) must be installed
+#
+RequireTcl() {
+    Progress -minor "checking for Tcl..."
+    RequireFileInPath INCLUDE "$INCLUDE" tcl.h
+    RequireFileInPath LIB "$LIB" tcl84g.lib
+    RequireFileInPath LIB "$LIB" tcl84.lib
+}
+
+# RequireWix()
+# WiX must be installed
+#
+RequireWix() {
+    Progress -minor "checking for WiX..."
+    RequireFileInPath PATH "$PATH" candle.exe
+    RequireFileInPath PATH "$PATH" light.exe
+    RequireFileInPath PATH "$PATH" tallow.exe
+}
+
+# RequirePerl()
+# Perl must be installed
+#
+RequirePerl() {
+    Progress -minor "checking for Perl..."
+    RequireFileInPath PATH "$PATH" perl.exe
+}
+
+# RequirePython()
+# Python (and include files) must be installed
+#
+RequirePython() {
+    Progress -minor "checking for Python..."
+    RequireFileInPath INCLUDE "$INCLUDE" Python.h
+    RequireFileInPath PATH "$PATH" python.exe
+}
+
+# CreateDbPerl()
+# Build Perl interface (for Berkeley DB only).
+#
+CreateDbPerl() {
+
+    # First build Berkeley DB using cygwin, as that version is
+    # needed for the Perl build
+    local here=`pwd`
+    Progress "building using Cygwin tools (needed for perl)"
+    cd "${PRODUCT_DBBUILDDIR}"
+    insdir="${PRODUCT_STAGE}/install_unix"
+    ../dist/configure --prefix="$insdir" >>$ERRORLOG  || exit 1
+    make install   >>$ERRORLOG  || exit 1
+
+    Progress "building perl"
+    cd ../perl/BerkeleyDB
+    BERKELEYDB_INCLUDE="$insdir/installed_include" BERKELEYDB_LIB="$insdir/lib" \
+         perl Makefile.PL >>$ERRORLOG   || exit 1
+    make >>$ERRORLOG
+    cd $here
+}
+
+# CreateWindowsSystem()
+# Copy Window system files
+#
+CreateWindowsSystem() {
+    local here=`pwd`
+    Progress "Copy Window system files..."
+    cd "${PRODUCT_SUB_BLDDIR}"
+    cp -f $SYSTEMROOT/system32/msvcr71.dll  build_win32/Release/ || exit 1
+    cp -f $SYSTEMROOT/system32/msvcp71.dll  build_win32/Release/ || exit 1
+    cp -f $SYSTEMROOT/system32/msvcr71d.dll build_win32/Debug/ || exit 1
+    cp -f $SYSTEMROOT/system32/msvcp71d.dll build_win32/Debug/ || exit 1
+    cd $here
+}
+
+# CreateInclude(DIR, FILES)
+# Create an include directory populated with the files given
+#
+CreateInclude() {
+
+    local incdir="$1"
+    shift
+
+    Progress "creating the "$incdir" directory..."
+    rm -rf "$incdir"
+    mkdir "$incdir"  || exit 1
+    cp -r "$@" "$incdir"
+}
+
+# CreateWindowsBuild()
+# Do the windows build as defined by the winbuild.bat file
+#
+CreateWindowsBuild() {
+    local here=`pwd`
+    Progress "building using Windows tools..."
+    cd "${PRODUCT_SUB_BLDDIR}"  || exit 1
+
+    # Before starting, copy any installer tools here.
+    # This makes building these tools straightforward
+    # and the results are left in the build directory.
+    #
+    cp -r ${PRODUCT_SHARED_WINMSIDIR}/instenv .
+
+    # We create a wbuild.bat file, which is essentially
+    # identical, except it has the carriage returns added.
+    # This allows us to use our favorite editors on winbuild.bat .
+    #
+    sed -e 's/$//' < ${PRODUCT_STAGE}/../winbuild.bat | tr '\001' '\015'  > wbuild.bat
+    # TODO: Needed?
+    rm -f build_win32/Berkeley_DB.sln
+    rm -f winbld.out winbld.err
+    touch winbld.out winbld.err
+    echo "Build output and errors are collected in" >> $ERRORLOG
+    echo "  winbld.{out,err} until the build has completed." >> $ERRORLOG
+    cmd.exe /x /c call wbuild.bat
+    status=$?
+    cat winbld.out >> $ERRORLOG
+    if [ -s winbld.err -o "$status" != 0 ]; then
+       cat winbld.err >> $ERRORLOG
+       Error "Errors during windows build"
+       exit 1
+    fi
+    cd $here
+}
+
+# CreateSources(SOURCESDIR,DOCDIR...)
+# Create the sources directory, ignoring things in the docdirs
+#
+CreateSources() {
+    local sources="$1"
+
+    Progress "creating the Sources directory in $sources..."
+    rm -rf "$sources"
+    cp -r ${PRODUCT_SRCDIR} "$sources"  || exit 1
+}
+
+# Usage()
+# Show the usage for this script.
+#
+Usage()
+{
+    echo "Usage:  s_winmsi [ options ]" >&2
+    echo "Options: " >&2
+    echo "   -input file       use file rather than ${PRODUCT_ZIP_FILEFMT}" >&2
+    echo "                     where X.Y.Z is defined by ../RELEASE" >&2
+    echo "   -output file      use file rather than ${PRODUCT_MSI_FILEFMT}" >&2
+    echo "                     where X.Y.Z is defined by ../RELEASE" >&2
+    echo "   -usebuild DIR     use DIR for exes, DLLs, etc. " >&2
+    echo "                     rather than building from scratch" >&2
+    echo "   -preserve         preserve the winmsi/msi_staging directory" >&2
+    echo "   -skipgen          skip generating m4 include files" >&2
+}
+
+# SetupOptions()
+# Parse command line options and set global variables as indicated below.
+#
+SetupOptions() {
+    OPT_USEBUILD=
+    OPT_PRESERVE=false
+    OPT_INFILE=
+    OPT_OUTFILE=
+    OPT_SKIPGEN=false
+    while [ "$#" -gt 0 ]; do
+        arg="$1"; shift
+        case "$arg" in
+        -usebuild )  OPT_USEBUILD="$1"; shift ;;
+        -skipgen )   OPT_SKIPGEN=true ;;
+        -preserve )  OPT_PRESERVE=true;;
+        -input )     OPT_INFILE="$1"; shift ;;
+        -output )    OPT_OUTFILE="$1"; shift ;;
+        * )
+            echo "ERROR: Unknown argument '$arg' to s_winmsi" >&2
+            Usage
+            exit 1
+            ;;
+        esac
+    done
+    if [ "$OPT_INFILE" = '' -o ! -f "$OPT_INFILE" ]; then
+        echo "$OPT_INFILE: not found"
+        exit 1
+    fi
+}
+
+# CreateStage()
+# Create the staging area
+#
+CreateStage() {
+    Progress "creating staging area..."
+    if [ "$PRODUCT_STAGE" = '' ]; then
+        Error "PRODUCT_STAGE not set"
+        exit 1
+    fi
+    if ! $OPT_PRESERVE; then
+        trap 'rm -rf ${PRODUCT_STAGE} ; exit 0' 0 1 2 3 13 15
+    fi
+    rm -rf ${PRODUCT_STAGE}   || exit 1
+    mkdir ${PRODUCT_STAGE}    || exit 1
+
+    cd ${PRODUCT_STAGE}
+    
+    Progress "extracting $OPT_INFILE..."
+    unzip -q ../../$OPT_INFILE  || exit 1
+    
+    if [ ! -d $PRODUCT_LICENSEDIR ]; then
+        Error "$OPT_INFILE: no top level $PRODUCT_LICENSEDIR directory"
+        exit 1
+    fi
+}
+
+# CreateLicenseRtf(LICENSEIN, LICENSERTF)
+# From a text LICENSE file, create the equivalent in .rtf format.
+#
+CreateLicenseRtf() {
+    local licensein="$1"
+    local licensertf="$2"
+
+    if [ ! -f "$licensein" ]; then
+        Error "License file $licensein: does not exist"
+        exit 1
+    fi
+    Progress "creating ${licensertf}..."
+    
+    # Build a list of references to components ids (i.e. directories)
+    # that are listed in the .wxs file.  This is needed to refer to
+    # all of the source (sadly it appears there is no better way!)
+    #
+    if ! grep '^=-=-=-=' $licensein > /dev/null; then
+        Error "LICENSE has changed format, this script must be adapted"
+        exit 1
+    fi
+    
+    sed -e '1,/^=-=-=-=-=/d' < $licensein | MakeRtf > $licensertf
+}
+
+    
+# CreateMsi(INFILE,WXSFILE,MSIFILE)
+# Do the final creation of the output .MSI file.
+# It is assumed that all *.wixinc files are now in place.
+# INFILE is an absolute name of the m4 input WiX file.
+# WXSFILE is a short (basename) of the postprocessed WiX file,
+#       after macro expansion, it will be left in staging directory.
+# MSIFILE is a short (basename) of the output .MSI name
+#
+CreateMsi() {
+    local infile="$1"
+    local wxs="$2"
+    local msifile="$3"
+    local o=`echo "$wxs" | sed -e 's/[.]wxs$//' -e 's/$/.wixobj/'`
+
+    rm -f $o $wxs 
+
+    # Preprocess the ${PROD}wix.in file, adding the things we need
+    #
+    Progress "Running m4 to create $wxs..."
+    RunM4 < "$infile" > "$PRODUCT_STAGE/$wxs"  || Error "m4 failed" || exit 1
+
+    local here=`pwd`
+    cd "$PRODUCT_STAGE"
+    rm -f "$o" "$msifile"
+    Progress "compiling $wxs..."
+    candle -w0 $wxs  >> $ERRORLOG || Error "candle (compiler) failed" || exit 1
+
+    Progress "linking .msi file..."
+    light -o "$msifile" $o  >> $ERRORLOG  || Error "light (linker) failed" || exit 1
+    (rm -f "../../$msifile" && mv "$msifile" ../..)  >> $ERRORLOG  || exit 1
+    cd $here
+}
+
+# CreateWixIncludeFiles()
+# Do all processing of input files to produce
+# the include files that we need to process the Wix input file.
+#
+CreateWixIncludeFiles() {
+    local here=`pwd`
+    cd "$PRODUCT_STAGE"
+    # Touch all the wix include files in case any end up empty.
+    touch directory.wixinc features.wixinc envprops.wixinc \
+          envset.wixinc envshow.wixinc links.wixinc
+
+    Progress "tagging the installer..."
+    ProcessTagProperties envprops.wixinc
+    
+    Progress "processing environment..."
+    ProcessEnv ../environment.in ../dbvarsbat.in envprops.wixinc envset.wixinc envshow.wixinc
+    
+    Progress "processing features and files..."
+    ProcessFeatures ../files.in ../features.in ../environment.in \
+                   directory.wixinc features.wixinc \
+                   envset.wixinc
+    
+    Progress "processing links..."
+    ProcessLinks ../links.in features.wixinc > links.wixinc
+    cd $here
+}
diff --git a/storage/bdb/dist/winmsi/winbuild.bat b/storage/bdb/dist/winmsi/winbuild.bat
new file mode 100644
index 0000000000000000000000000000000000000000..b8c9a34add2225c05b8b89d7b307a2181fa6b296
--- /dev/null
+++ b/storage/bdb/dist/winmsi/winbuild.bat
@@ -0,0 +1,119 @@
+@echo off
+::	$Id: winbuild.bat,v 1.4 2005/04/15 19:01:52 philipr Exp $
+::	Helper script to build Berkeley DB libraries and executables
+::	using MSDEV
+::
+
+cd build_win32
+
+:: One of these calls should find the desired batch file
+
+call :TryBat "c:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\vsvars32.bat" && goto BATFOUND1
+
+call :TryBat "c:\Program Files\Microsoft Visual Studio .NET\Common7\Tools\vsvars32.bat" && goto BATFOUND2
+
+call :TryBat "c:\Program Files\Microsoft Visual Studio.NET\Common7\Tools\vsvars32.bat" && goto BATFOUND3
+
+goto BATNOTFOUND
+
+:BATFOUND1
+echo Using Visual Studio .NET 2003
+goto BATFOUND
+
+:BATFOUND2
+echo Using Visual Studio .NET
+echo *********** CHECK: Make sure the binaries are built with the same system libraries that are shipped.
+goto BATFOUND
+
+:BATFOUND3
+echo Using Visual Studio.NET
+echo *********** CHECK: Make sure the binaries are built with the same system libraries that are shipped.
+goto BATFOUND
+
+:BATFOUND
+:CONVERSION
+start /wait devenv /useenv Berkeley_DB.dsw
+
+:: For some reason, the command doesn't wait, at least on XP.
+:: So we ask for input to continue.
+
+
+echo.
+echo ============================================================
+echo.
+echo    Converting the Berkeley DB Workspace to a .NET Solution.
+echo    This will run the IDE to interactively convert.
+echo.
+echo    When prompted during the conversion, say: Yes-to-All.
+echo    When finished with the conversion, do a Save-All and Exit.
+echo    Then hit ENTER to continue this script.
+echo.
+echo ============================================================
+set result=y
+set /P result="Continue? [y] "
+if %result% == n goto NSTOP
+
+if exist Berkeley_DB.sln goto ENDCONVERSION
+echo ************* Berkeley_DB.sln was not created ***********
+echo Trying the conversion again...
+goto CONVERSION
+:ENDCONVERSION
+
+::intenv is used to set environment variables but this isn't used anymore
+::devenv /useenv /build Release /project instenv ..\instenv\instenv.sln >> ..\winbld.out 2>&1
+::if not %errorlevel% == 0 goto ERROR
+
+echo Building Berkeley DB
+devenv /useenv /build Debug /project build_all Berkeley_DB.sln >> ..\winbld.out 2>&1
+if not %errorlevel% == 0 goto ERROR
+devenv /useenv /build Release /project build_all Berkeley_DB.sln >> ..\winbld.out 2>&1
+if not %errorlevel% == 0 goto ERROR
+devenv /useenv /build "Debug Static" /project build_all Berkeley_DB.sln >> ..\winbld.out 2>&1
+if not %errorlevel% == 0 goto ERROR
+devenv /useenv /build "Release Static" /project build_all Berkeley_DB.sln >> ..\winbld.out 2>&1
+if not %errorlevel% == 0 goto ERROR
+devenv /useenv /build Debug /project ex_repquote Berkeley_DB.sln >> ..\winbld.out 2>&1
+if not %errorlevel% == 0 goto ERROR
+devenv /useenv /build Debug /project db_java Berkeley_DB.sln >> ..\winbld.out 2>&1
+if not %errorlevel% == 0 goto ERROR
+devenv /useenv /build Release /project db_java Berkeley_DB.sln >> ..\winbld.out 2>&1
+if not %errorlevel% == 0 goto ERROR
+devenv /useenv /build Debug /project db_tcl Berkeley_DB.sln >> ..\winbld.out 2>&1
+if not %errorlevel% == 0 goto ERROR
+devenv /useenv /build Release /project db_tcl Berkeley_DB.sln >> ..\winbld.out 2>&1
+if not %errorlevel% == 0 goto ERROR
+
+
+goto END
+
+
+:ERROR
+echo *********** ERROR: during win_build.bat *************
+echo *********** ERROR: during win_build.bat *************  >> ..\winbld.err
+exit 1
+goto END
+
+:NSTOP
+echo *********** ERROR: win_build.bat stop requested *************
+echo *********** ERROR: win_built.bat stop requested *************  >> ..\winbld.err
+exit 2
+goto END
+
+:BATNOTFOUND
+echo *********** ERROR: VC Config batch file not found *************
+echo *********** ERROR: VC Config batch file not found *************  >> ..\winbld.err
+exit 3
+goto END
+
+:: TryBat(BATPATH)
+:: If the BATPATH exists, use it and return 0,
+:: otherwise, return 1.
+
+:TryBat
+:: Filename = %1
+if not exist %1 exit /b 1
+call %1
+exit /b 0
+goto :EOF
+
+:END
diff --git a/storage/bdb/env/db_salloc.c b/storage/bdb/env/db_salloc.c
index 1ef768d41147d20736d5768166fa5a73d5c5cc67..f2b1ed386eb4639e10c6cd7730cefae6e2920bfd 100644
--- a/storage/bdb/env/db_salloc.c
+++ b/storage/bdb/env/db_salloc.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_salloc.c,v 11.28 2004/09/17 22:00:27 mjc Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_salloc.c,v 11.16 2002/08/24 20:27:25 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -36,21 +34,27 @@ struct __data {
 	SH_LIST_ENTRY links;
 };
 
+#define	ILLEGAL_SIZE	1			/* An illegal size. */
+
 /*
  * __db_shalloc_init --
  *	Initialize the area as one large chunk.
  *
- * PUBLIC: void __db_shalloc_init __P((void *, size_t));
+ * PUBLIC: void __db_shalloc_init __P((REGINFO *, size_t));
  */
 void
-__db_shalloc_init(area, size)
-	void *area;
+__db_shalloc_init(infop, size)
+	REGINFO *infop;
 	size_t size;
 {
 	struct __data *elp;
 	struct __head *hp;
 
-	hp = area;
+	/* No initialization needed for heap memory regions. */
+	if (F_ISSET(infop->dbenv, DB_ENV_PRIVATE))
+		return;
+
+	hp = infop->addr;
 	SH_LIST_INIT(hp);
 
 	elp = (struct __data *)(hp + 1);
@@ -62,9 +66,9 @@ __db_shalloc_init(area, size)
  * __db_shalloc_size --
  *	Return the space needed for an allocation, including alignment.
  *
- * PUBLIC: int __db_shalloc_size __P((size_t, size_t));
+ * PUBLIC: size_t __db_shalloc_size __P((size_t, size_t));
  */
-int
+size_t
 __db_shalloc_size(len, align)
 	size_t len, align;
 {
@@ -77,27 +81,67 @@ __db_shalloc_size(len, align)
 	++len;
 #endif
 
-	/* Never align to less than a db_align_t boundary. */
-	if (align <= sizeof(db_align_t))
-		align = sizeof(db_align_t);
+	/* Never align to less than a uintmax_t boundary. */
+	if (align <= sizeof(uintmax_t))
+		align = sizeof(uintmax_t);
 
-	return ((int)(ALIGN(len, align) + sizeof (struct __data)));
+	return ((size_t)DB_ALIGN(len, align) + sizeof(struct __data));
 }
 
 /*
  * __db_shalloc --
- *	Allocate some space from the shared region.
+ *	Allocate space from the shared region.
  *
- * PUBLIC: int __db_shalloc __P((void *, size_t, size_t, void *));
+ * PUBLIC: int __db_shalloc __P((REGINFO *, size_t, size_t, void *));
  */
 int
-__db_shalloc(p, len, align, retp)
-	void *p, *retp;
+__db_shalloc(infop, len, align, retp)
+	REGINFO *infop;
 	size_t len, align;
+	void *retp;
 {
+	DB_ENV *dbenv;
 	struct __data *elp;
 	size_t *sp;
-	void *rp;
+	int ret;
+	void *p, *rp;
+
+	dbenv = infop->dbenv;
+
+	/* Never align to less than a uintmax_t boundary. */
+	if (align <= sizeof(uintmax_t))
+		align = sizeof(uintmax_t);
+
+	/* In a private region, we call malloc for additional space. */
+	if (F_ISSET(dbenv, DB_ENV_PRIVATE)) {
+		/* Check to see if we're over our limit. */
+		if (infop->allocated >= infop->max_alloc)
+			return (ENOMEM);
+
+		/* Add enough room for a size. */
+		len += sizeof(size_t);
+
+		/* Add enough room to guarantee alignment is possible. */
+		len += align - 1;
+
+		/* Allocate the space. */
+		if ((ret = __os_malloc(dbenv, len, &p)) != 0)
+			return (ret);
+		infop->allocated += len;
+
+		/* Store the size. */
+		sp = p;
+		*sp++ = len;
+
+		/* Find the aligned location. */
+		*(void **)retp = rp = ALIGNP_INC(sp, align);
+
+		/* Fill in any gaps with illegal sizes. */
+		for (; (void *)sp < rp; ++sp)
+			*sp = ILLEGAL_SIZE;
+
+		return (0);
+	}
 
 	/* Never allocate less than the size of a struct __data. */
 	if (len < sizeof(struct __data))
@@ -108,9 +152,7 @@ __db_shalloc(p, len, align, retp)
 	++len;
 #endif
 
-	/* Never align to less than a db_align_t boundary. */
-	if (align <= sizeof(db_align_t))
-		align = sizeof(db_align_t);
+	p = infop->addr;
 
 	/* Walk the list, looking for a slot. */
 	for (elp = SH_LIST_FIRST((struct __head *)p, __data);
@@ -125,7 +167,8 @@ __db_shalloc(p, len, align, retp)
 		 */
 		rp = (u_int8_t *)elp + sizeof(size_t) + elp->len;
 		rp = (u_int8_t *)rp - len;
-		rp = (u_int8_t *)((db_alignp_t)rp & ~(align - 1));
+		rp = (u_int8_t *)((uintptr_t)rp & ~(align - 1));
+		rp = ALIGNP_DEC(rp, align);
 
 		/*
 		 * Rp may now point before elp->links, in which case the chunk
@@ -168,7 +211,6 @@ __db_shalloc(p, len, align, retp)
 		 * size_t length fields back to the "real" length field to a
 		 * flag value, so that we can find the real length during free.
 		 */
-#define	ILLEGAL_SIZE	1
 		SH_LIST_REMOVE(elp, links, __data);
 		for (sp = rp; (u_int8_t *)--sp >= (u_int8_t *)&elp->links;)
 			*sp = ILLEGAL_SIZE;
@@ -180,19 +222,23 @@ __db_shalloc(p, len, align, retp)
 
 /*
  * __db_shalloc_free --
- *	Free a shared memory allocation.
+ *	Free space into the shared region.
  *
- * PUBLIC: void __db_shalloc_free __P((void *, void *));
+ * PUBLIC: void __db_shalloc_free __P((REGINFO *, void *));
  */
 void
-__db_shalloc_free(regionp, ptr)
-	void *regionp, *ptr;
+__db_shalloc_free(infop, ptr)
+	REGINFO *infop;
+	void *ptr;
 {
+	DB_ENV *dbenv;
 	struct __data *elp, *lastp, *newp;
 	struct __head *hp;
 	size_t free_size, *sp;
 	int merged;
 
+	dbenv = infop->dbenv;
+
 	/*
 	 * Step back over flagged length fields to find the beginning of
 	 * the object and its real size.
@@ -204,6 +250,15 @@ __db_shalloc_free(regionp, ptr)
 	newp = (struct __data *)((u_int8_t *)ptr - sizeof(size_t));
 	free_size = newp->len;
 
+	/* In a private region, we call free. */
+	if (F_ISSET(dbenv, DB_ENV_PRIVATE)) {
+		DB_ASSERT(infop->allocated >= free_size);
+		infop->allocated -= free_size;
+
+		__os_free(dbenv, newp);
+		return;
+	}
+
 #ifdef DIAGNOSTIC
 	/*
 	 * The "real size" includes the guard byte;  it's just the last
@@ -225,7 +280,6 @@ __db_shalloc_free(regionp, ptr)
 	/* Trash the returned memory (including guard byte). */
 	memset(ptr, CLEAR_BYTE, free_size);
 #endif
-
 	/*
 	 * Walk the list, looking for where this entry goes.
 	 *
@@ -235,7 +289,7 @@ __db_shalloc_free(regionp, ptr)
 	 * XXX
 	 * Probably worth profiling this to see how expensive it is.
 	 */
-	hp = (struct __head *)regionp;
+	hp = (struct __head *)(infop->addr);
 	for (elp = SH_LIST_FIRST(hp, __data), lastp = NULL;
 	    elp != NULL && (void *)elp < (void *)ptr;
 	    lastp = elp, elp = SH_LIST_NEXT(elp, links, __data))
@@ -284,7 +338,7 @@ __db_shalloc_free(regionp, ptr)
 }
 
 /*
- * __db_shsizeof --
+ * __db_shalloc_sizeof --
  *	Return the size of a shalloc'd piece of memory.
  *
  * !!!
@@ -292,10 +346,10 @@ __db_shalloc_free(regionp, ptr)
  * the size of the memory being used, but also the extra alignment bytes
  * in front and, #ifdef DIAGNOSTIC, the guard byte at the end.
  *
- * PUBLIC: size_t __db_shsizeof __P((void *));
+ * PUBLIC: size_t __db_shalloc_sizeof __P((void *));
  */
 size_t
-__db_shsizeof(ptr)
+__db_shalloc_sizeof(ptr)
 	void *ptr;
 {
 	struct __data *elp;
@@ -311,28 +365,3 @@ __db_shsizeof(ptr)
 	elp = (struct __data *)((u_int8_t *)sp - sizeof(size_t));
 	return (elp->len);
 }
-
-/*
- * __db_shalloc_dump --
- *
- * PUBLIC: void __db_shalloc_dump __P((void *, FILE *));
- */
-void
-__db_shalloc_dump(addr, fp)
-	void *addr;
-	FILE *fp;
-{
-	struct __data *elp;
-
-	/* Make it easy to call from the debugger. */
-	if (fp == NULL)
-		fp = stderr;
-
-	fprintf(fp, "%s\nMemory free list\n", DB_LINE);
-
-	for (elp = SH_LIST_FIRST((struct __head *)addr, __data);
-	    elp != NULL;
-	    elp = SH_LIST_NEXT(elp, links, __data))
-		fprintf(fp, "%#lx: %lu\t", P_TO_ULONG(elp), (u_long)elp->len);
-	fprintf(fp, "\n");
-}
diff --git a/storage/bdb/env/db_shash.c b/storage/bdb/env/db_shash.c
index 743a126307d20d40a8543fd60ae12933b2ce021e..ac3b31622128f6c81d1c089dd35281ce773dc970 100644
--- a/storage/bdb/env/db_shash.c
+++ b/storage/bdb/env/db_shash.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_shash.c,v 11.9 2004/03/20 16:18:51 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_shash.c,v 11.6 2002/03/01 17:22:16 ubell Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #endif
@@ -75,13 +73,13 @@ static const struct {
  * __db_tablesize --
  *	Choose a size for the hash table.
  *
- * PUBLIC: int __db_tablesize __P((u_int32_t));
+ * PUBLIC: u_int32_t __db_tablesize __P((u_int32_t));
  */
-int
+u_int32_t
 __db_tablesize(n_buckets)
 	u_int32_t n_buckets;
 {
-	int i;
+	u_int i;
 
 	/*
 	 * We try to be clever about how big we make the hash tables.  Use a
@@ -93,15 +91,10 @@ __db_tablesize(n_buckets)
 	if (n_buckets < 32)
 		n_buckets = 32;
 
-	for (i = 0;; ++i) {
-		if (list[i].power == 0) {
-			--i;
-			break;
-		}
+	for (i = 0; i < sizeof(list)/sizeof(list[0]); ++i)
 		if (list[i].power >= n_buckets)
-			break;
-	}
-	return (list[i].prime);
+			return (list[i].prime);
+	return (list[--i].prime);
 }
 
 /*
diff --git a/storage/bdb/env/env_file.c b/storage/bdb/env/env_file.c
index f221fd8d7014ddfa1bbf0cd673ce60b57a9a8668..53f93cc534ea2534046cb6c00f0df677a7528ab7 100644
--- a/storage/bdb/env/env_file.c
+++ b/storage/bdb/env/env_file.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2002
+ * Copyright (c) 2002-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: env_file.c,v 1.11 2004/03/24 20:51:38 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: env_file.c,v 1.5 2002/03/08 17:47:18 sue Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -20,7 +18,7 @@ static const char revid[] = "$Id: env_file.c,v 1.5 2002/03/08 17:47:18 sue Exp $
 #include "db_int.h"
 
 static int __db_overwrite_pass __P((DB_ENV *,
-	       const char *, DB_FH *, u_int32_t, u_int32_t, u_int32_t));
+	       const char *, DB_FH *, u_int32_t, u_int32_t, int));
 
 /*
  * __db_fileinit --
@@ -98,12 +96,11 @@ __db_overwrite(dbenv, path)
 	DB_ENV *dbenv;
 	const char *path;
 {
-	DB_FH fh, *fhp;
+	DB_FH *fhp;
 	u_int32_t mbytes, bytes;
 	int ret;
 
-	fhp = &fh;
-	if ((ret = __os_open(dbenv, path, DB_OSO_REGION, 0, fhp)) == 0 &&
+	if ((ret = __os_open(dbenv, path, DB_OSO_REGION, 0, &fhp)) == 0 &&
 	    (ret = __os_ioinfo(dbenv, path, fhp, &mbytes, &bytes, NULL)) == 0) {
 		/*
 		 * !!!
@@ -112,19 +109,19 @@ __db_overwrite(dbenv, path)
 		 * or logging filesystems will require operating system support.
 		 */
 		if ((ret = __db_overwrite_pass(
-		    dbenv, path, fhp, mbytes, bytes, 0xff)) != 0)
+		    dbenv, path, fhp, mbytes, bytes, 255)) != 0)
 			goto err;
 		if ((ret = __db_overwrite_pass(
-		    dbenv, path, fhp, mbytes, bytes, 0x00)) != 0)
+		    dbenv, path, fhp, mbytes, bytes, 0)) != 0)
 			goto err;
 		if ((ret = __db_overwrite_pass(
-		    dbenv, path, fhp, mbytes, bytes, 0xff)) != 0)
+		    dbenv, path, fhp, mbytes, bytes, 255)) != 0)
 			goto err;
 	} else
 		__db_err(dbenv, "%s: %s", path, db_strerror(ret));
 
-err:	if (F_ISSET(fhp, DB_FH_VALID))
-		__os_closehandle(dbenv, fhp);
+err:	if (fhp != NULL)
+		(void)__os_closehandle(dbenv, fhp);
 	return (ret);
 }
 
@@ -137,7 +134,8 @@ __db_overwrite_pass(dbenv, path, fhp, mbytes, bytes, pattern)
 	DB_ENV *dbenv;
 	const char *path;
 	DB_FH *fhp;
-	u_int32_t mbytes, bytes, pattern;
+	int pattern;
+	u_int32_t mbytes, bytes;
 {
 	size_t len, nw;
 	int i, ret;
diff --git a/storage/bdb/env/env_method.c b/storage/bdb/env/env_method.c
index b51237ec44a9b8447b1757456612096717b8aef2..4f865061b825ba40359d5c2c9ef84d58df11578b 100644
--- a/storage/bdb/env/env_method.c
+++ b/storage/bdb/env/env_method.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: env_method.c,v 11.136 2004/10/11 18:47:50 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: env_method.c,v 11.87 2002/08/29 14:22:21 margo Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -21,6 +19,10 @@ static const char revid[] = "$Id: env_method.c,v 11.87 2002/08/29 14:22:21 margo
 #include <string.h>
 #endif
 
+#ifdef HAVE_RPC
+#include "db_server.h"
+#endif
+
 /*
  * This is the file that initializes the global array.  Do it this way because
  * people keep changing one without changing the other.  Having declaration and
@@ -37,36 +39,28 @@ static const char revid[] = "$Id: env_method.c,v 11.87 2002/08/29 14:22:21 margo
 #include "dbinc/lock.h"
 #include "dbinc/log.h"
 #include "dbinc/mp.h"
-#include "dbinc/rep.h"
 #include "dbinc/txn.h"
 
 #ifdef HAVE_RPC
-#include "dbinc_auto/db_server.h"
 #include "dbinc_auto/rpc_client_ext.h"
 #endif
 
 static void __dbenv_err __P((const DB_ENV *, int, const char *, ...));
 static void __dbenv_errx __P((const DB_ENV *, const char *, ...));
+static int  __dbenv_get_data_dirs __P((DB_ENV *, const char ***));
+static int  __dbenv_get_flags __P((DB_ENV *, u_int32_t *));
+static int  __dbenv_get_home __P((DB_ENV *, const char **));
+static int  __dbenv_get_shm_key __P((DB_ENV *, long *));
+static int  __dbenv_get_tas_spins __P((DB_ENV *, u_int32_t *));
+static int  __dbenv_get_tmp_dir __P((DB_ENV *, const char **));
+static int  __dbenv_get_verbose __P((DB_ENV *, u_int32_t, int *));
 static int  __dbenv_init __P((DB_ENV *));
-static int  __dbenv_set_alloc __P((DB_ENV *, void *(*)(size_t),
-    void *(*)(void *, size_t), void (*)(void *)));
-static int  __dbenv_set_app_dispatch __P((DB_ENV *,
-    int (*)(DB_ENV *, DBT *, DB_LSN *, db_recops)));
-static int  __dbenv_set_data_dir __P((DB_ENV *, const char *));
-static int  __dbenv_set_encrypt __P((DB_ENV *, const char *, u_int32_t));
-static void __dbenv_set_errcall __P((DB_ENV *, void (*)(const char *, char *)));
-static void __dbenv_set_errfile __P((DB_ENV *, FILE *));
-static void __dbenv_set_errpfx __P((DB_ENV *, const char *));
+static void __dbenv_map_flags __P((DB_ENV *, u_int32_t *, u_int32_t *));
+static int  __dbenv_set_app_dispatch
+		__P((DB_ENV *, int (*)(DB_ENV *, DBT *, DB_LSN *, db_recops)));
 static int  __dbenv_set_feedback __P((DB_ENV *, void (*)(DB_ENV *, int, int)));
-static int  __dbenv_set_flags __P((DB_ENV *, u_int32_t, int));
-static void __dbenv_set_noticecall __P((DB_ENV *, void (*)(DB_ENV *, db_notices)));
-static int  __dbenv_set_paniccall __P((DB_ENV *, void (*)(DB_ENV *, int)));
 static int  __dbenv_set_rpc_server_noclnt
-    __P((DB_ENV *, void *, const char *, long, long, u_int32_t));
-static int  __dbenv_set_shm_key __P((DB_ENV *, long));
-static int  __dbenv_set_tas_spins __P((DB_ENV *, u_int32_t));
-static int  __dbenv_set_tmp_dir __P((DB_ENV *, const char *));
-static int  __dbenv_set_verbose __P((DB_ENV *, u_int32_t, int));
+		__P((DB_ENV *, void *, const char *, long, long, u_int32_t));
 
 /*
  * db_env_create --
@@ -92,19 +86,16 @@ db_env_create(dbenvpp, flags)
 	 * We can't call the flags-checking routines, we don't have an
 	 * environment yet.
 	 */
-	if (flags != 0 && flags != DB_CLIENT)
+	if (flags != 0 && !LF_ISSET(DB_RPCCLIENT))
 		return (EINVAL);
-
 	if ((ret = __os_calloc(NULL, 1, sizeof(*dbenv), &dbenv)) != 0)
 		return (ret);
 
 #ifdef HAVE_RPC
-	if (LF_ISSET(DB_CLIENT))
+	if (LF_ISSET(DB_RPCCLIENT))
 		F_SET(dbenv, DB_ENV_RPCCLIENT);
 #endif
-	ret = __dbenv_init(dbenv);
-
-	if (ret != 0) {
+	if ((ret = __dbenv_init(dbenv)) != 0) {
 		__os_free(NULL, dbenv);
 		return (ret);
 	}
@@ -132,49 +123,86 @@ __dbenv_init(dbenv)
 	dbenv->err = __dbenv_err;
 	dbenv->errx = __dbenv_errx;
 	dbenv->set_errcall = __dbenv_set_errcall;
+	dbenv->get_errfile = __dbenv_get_errfile;
 	dbenv->set_errfile = __dbenv_set_errfile;
+	dbenv->get_errpfx = __dbenv_get_errpfx;
 	dbenv->set_errpfx = __dbenv_set_errpfx;
+	dbenv->set_msgcall = __dbenv_set_msgcall;
+	dbenv->get_msgfile = __dbenv_get_msgfile;
+	dbenv->set_msgfile = __dbenv_set_msgfile;
 
 #ifdef	HAVE_RPC
 	if (F_ISSET(dbenv, DB_ENV_RPCCLIENT)) {
-		dbenv->close = __dbcl_env_close;
+		dbenv->close = __dbcl_env_close_wrap;
 		dbenv->dbremove = __dbcl_env_dbremove;
 		dbenv->dbrename = __dbcl_env_dbrename;
+		dbenv->get_home = __dbcl_env_get_home;
+		dbenv->get_open_flags = __dbcl_env_get_open_flags;
 		dbenv->open = __dbcl_env_open_wrap;
 		dbenv->remove = __dbcl_env_remove;
+		dbenv->stat_print = NULL;
+
+		dbenv->fileid_reset = NULL;
+		dbenv->is_bigendian = NULL;
+		dbenv->lsn_reset = NULL;
+		dbenv->prdbt = NULL;
+
 		dbenv->set_alloc = __dbcl_env_alloc;
 		dbenv->set_app_dispatch = __dbcl_set_app_dispatch;
+		dbenv->get_data_dirs = __dbcl_get_data_dirs;
 		dbenv->set_data_dir = __dbcl_set_data_dir;
+		dbenv->get_encrypt_flags = __dbcl_env_get_encrypt_flags;
 		dbenv->set_encrypt = __dbcl_env_encrypt;
 		dbenv->set_feedback = __dbcl_env_set_feedback;
+		dbenv->get_flags = __dbcl_env_get_flags;
 		dbenv->set_flags = __dbcl_env_flags;
-		dbenv->set_noticecall = __dbcl_env_noticecall;
 		dbenv->set_paniccall = __dbcl_env_paniccall;
 		dbenv->set_rpc_server = __dbcl_envrpcserver;
+		dbenv->get_shm_key = __dbcl_get_shm_key;
 		dbenv->set_shm_key = __dbcl_set_shm_key;
+		dbenv->get_tas_spins = __dbcl_get_tas_spins;
 		dbenv->set_tas_spins = __dbcl_set_tas_spins;
+		dbenv->get_timeout = __dbcl_get_timeout;
 		dbenv->set_timeout = __dbcl_set_timeout;
+		dbenv->get_tmp_dir = __dbcl_get_tmp_dir;
 		dbenv->set_tmp_dir = __dbcl_set_tmp_dir;
+		dbenv->get_verbose = __dbcl_get_verbose;
 		dbenv->set_verbose = __dbcl_set_verbose;
 	} else {
 #endif
-		dbenv->close = __dbenv_close;
-		dbenv->dbremove = __dbenv_dbremove;
-		dbenv->dbrename = __dbenv_dbrename;
+		dbenv->close = __dbenv_close_pp;
+		dbenv->dbremove = __dbenv_dbremove_pp;
+		dbenv->dbrename = __dbenv_dbrename_pp;
 		dbenv->open = __dbenv_open;
 		dbenv->remove = __dbenv_remove;
+		dbenv->stat_print = __dbenv_stat_print_pp;
+
+		dbenv->fileid_reset = __db_fileid_reset;
+		dbenv->is_bigendian = __db_isbigendian;
+		dbenv->lsn_reset = __db_lsn_reset;
+		dbenv->prdbt = __db_prdbt;
+
+		dbenv->get_home = __dbenv_get_home;
+		dbenv->get_open_flags = __dbenv_get_open_flags;
 		dbenv->set_alloc = __dbenv_set_alloc;
 		dbenv->set_app_dispatch = __dbenv_set_app_dispatch;
+		dbenv->get_data_dirs = __dbenv_get_data_dirs;
 		dbenv->set_data_dir = __dbenv_set_data_dir;
+		dbenv->get_encrypt_flags = __dbenv_get_encrypt_flags;
 		dbenv->set_encrypt = __dbenv_set_encrypt;
 		dbenv->set_feedback = __dbenv_set_feedback;
+		dbenv->get_flags = __dbenv_get_flags;
 		dbenv->set_flags = __dbenv_set_flags;
-		dbenv->set_noticecall = __dbenv_set_noticecall;
+		dbenv->set_intermediate_dir = __dbenv_set_intermediate_dir;
 		dbenv->set_paniccall = __dbenv_set_paniccall;
 		dbenv->set_rpc_server = __dbenv_set_rpc_server_noclnt;
+		dbenv->get_shm_key = __dbenv_get_shm_key;
 		dbenv->set_shm_key = __dbenv_set_shm_key;
+		dbenv->get_tas_spins = __dbenv_get_tas_spins;
 		dbenv->set_tas_spins = __dbenv_set_tas_spins;
+		dbenv->get_tmp_dir = __dbenv_get_tmp_dir;
 		dbenv->set_tmp_dir = __dbenv_set_tmp_dir;
+		dbenv->get_verbose = __dbenv_get_verbose;
 		dbenv->set_verbose = __dbenv_set_verbose;
 #ifdef	HAVE_RPC
 	}
@@ -182,6 +210,8 @@ __dbenv_init(dbenv)
 	dbenv->shm_key = INVALID_REGION_SEGID;
 	dbenv->db_ref = 0;
 
+	__os_spin(dbenv);
+
 	__log_dbenv_create(dbenv);		/* Subsystem specific. */
 	__lock_dbenv_create(dbenv);
 	__memp_dbenv_create(dbenv);
@@ -196,7 +226,7 @@ __dbenv_init(dbenv)
  *	Error message, including the standard error string.
  */
 static void
-#ifdef __STDC__
+#ifdef STDC_HEADERS
 __dbenv_err(const DB_ENV *dbenv, int error, const char *fmt, ...)
 #else
 __dbenv_err(dbenv, error, fmt, va_alist)
@@ -214,7 +244,7 @@ __dbenv_err(dbenv, error, fmt, va_alist)
  *	Error message.
  */
 static void
-#ifdef __STDC__
+#ifdef STDC_HEADERS
 __dbenv_errx(const DB_ENV *dbenv, const char *fmt, ...)
 #else
 __dbenv_errx(dbenv, fmt, va_alist)
@@ -227,13 +257,30 @@ __dbenv_errx(dbenv, fmt, va_alist)
 }
 
 static int
+__dbenv_get_home(dbenv, homep)
+	DB_ENV *dbenv;
+	const char **homep;
+{
+	ENV_ILLEGAL_BEFORE_OPEN(dbenv, "DB_ENV->get_home");
+	*homep = dbenv->db_home;
+	return (0);
+}
+
+/*
+ * __dbenv_set_alloc --
+ *	{DB_ENV,DB}->set_alloc.
+ *
+ * PUBLIC: int  __dbenv_set_alloc __P((DB_ENV *, void *(*)(size_t),
+ * PUBLIC:          void *(*)(void *, size_t), void (*)(void *)));
+ */
+int
 __dbenv_set_alloc(dbenv, mal_func, real_func, free_func)
 	DB_ENV *dbenv;
 	void *(*mal_func) __P((size_t));
 	void *(*real_func) __P((void *, size_t));
 	void (*free_func) __P((void *));
 {
-	ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_alloc");
+	ENV_ILLEGAL_AFTER_OPEN(dbenv, "DB_ENV->set_alloc");
 
 	dbenv->db_malloc = mal_func;
 	dbenv->db_realloc = real_func;
@@ -250,13 +297,47 @@ __dbenv_set_app_dispatch(dbenv, app_dispatch)
 	DB_ENV *dbenv;
 	int (*app_dispatch) __P((DB_ENV *, DBT *, DB_LSN *, db_recops));
 {
-	ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_app_dispatch");
+	ENV_ILLEGAL_AFTER_OPEN(dbenv, "DB_ENV->set_app_dispatch");
 
 	dbenv->app_dispatch = app_dispatch;
 	return (0);
 }
 
-static int
+/*
+ * __dbenv_get_encrypt_flags --
+ *	{DB_ENV,DB}->get_encrypt_flags.
+ *
+ * PUBLIC: int __dbenv_get_encrypt_flags __P((DB_ENV *, u_int32_t *));
+ */
+int
+__dbenv_get_encrypt_flags(dbenv, flagsp)
+	DB_ENV *dbenv;
+	u_int32_t *flagsp;
+{
+#ifdef HAVE_CRYPTO
+	DB_CIPHER *db_cipher;
+
+	db_cipher = dbenv->crypto_handle;
+	if (db_cipher != NULL && db_cipher->alg == CIPHER_AES)
+		*flagsp = DB_ENCRYPT_AES;
+	else
+		*flagsp = 0;
+	return (0);
+#else
+	COMPQUIET(flagsp, 0);
+	__db_err(dbenv,
+	    "library build did not include support for cryptography");
+	return (DB_OPNOTSUP);
+#endif
+}
+
+/*
+ * __dbenv_set_encrypt --
+ *	DB_ENV->set_encrypt.
+ *
+ * PUBLIC: int __dbenv_set_encrypt __P((DB_ENV *, const char *, u_int32_t));
+ */
+int
 __dbenv_set_encrypt(dbenv, passwd, flags)
 	DB_ENV *dbenv;
 	const char *passwd;
@@ -266,7 +347,7 @@ __dbenv_set_encrypt(dbenv, passwd, flags)
 	DB_CIPHER *db_cipher;
 	int ret;
 
-	ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_encrypt");
+	ENV_ILLEGAL_AFTER_OPEN(dbenv, "DB_ENV->set_encrypt");
 #define	OK_CRYPTO_FLAGS	(DB_ENCRYPT_AES)
 
 	if (flags != 0 && LF_ISSET(~OK_CRYPTO_FLAGS))
@@ -310,6 +391,8 @@ __dbenv_set_encrypt(dbenv, passwd, flags)
 		    != 0)
 			goto err1;
 		break;
+	default:				/* Impossible. */
+		break;
 	}
 	return (0);
 
@@ -320,146 +403,324 @@ err1:
 err:
 	return (ret);
 #else
-	COMPQUIET(dbenv, NULL);
 	COMPQUIET(passwd, NULL);
 	COMPQUIET(flags, 0);
 
-	return (__db_eopnotsup(dbenv));
+	__db_err(dbenv,
+	    "library build did not include support for cryptography");
+	return (DB_OPNOTSUP);
 #endif
 }
 
-static int
-__dbenv_set_flags(dbenv, flags, onoff)
+static void
+__dbenv_map_flags(dbenv, inflagsp, outflagsp)
 	DB_ENV *dbenv;
-	u_int32_t flags;
-	int onoff;
+	u_int32_t *inflagsp, *outflagsp;
 {
-#define	OK_FLAGS							\
-	(DB_AUTO_COMMIT | DB_CDB_ALLDB | DB_DIRECT_DB | DB_DIRECT_LOG |	\
-	    DB_NOLOCKING | DB_NOMMAP | DB_NOPANIC | DB_OVERWRITE |	\
-	    DB_PANIC_ENVIRONMENT | DB_REGION_INIT | DB_TXN_NOSYNC |	\
-	    DB_TXN_WRITE_NOSYNC | DB_YIELDCPU)
-
-	if (LF_ISSET(~OK_FLAGS))
-		return (__db_ferr(dbenv, "DB_ENV->set_flags", 0));
-	if (onoff && LF_ISSET(DB_TXN_WRITE_NOSYNC) && LF_ISSET(DB_TXN_NOSYNC))
-		return (__db_ferr(dbenv, "DB_ENV->set_flags", 1));
+	COMPQUIET(dbenv, NULL);
 
-	if (LF_ISSET(DB_AUTO_COMMIT)) {
-		if (onoff)
-			F_SET(dbenv, DB_ENV_AUTO_COMMIT);
-		else
-			F_CLR(dbenv, DB_ENV_AUTO_COMMIT);
+	if (FLD_ISSET(*inflagsp, DB_AUTO_COMMIT)) {
+		FLD_SET(*outflagsp, DB_ENV_AUTO_COMMIT);
+		FLD_CLR(*inflagsp, DB_AUTO_COMMIT);
 	}
-	if (LF_ISSET(DB_CDB_ALLDB)) {
-		ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_flags: DB_CDB_ALLDB");
-		if (onoff)
-			F_SET(dbenv, DB_ENV_CDB_ALLDB);
-		else
-			F_CLR(dbenv, DB_ENV_CDB_ALLDB);
+	if (FLD_ISSET(*inflagsp, DB_CDB_ALLDB)) {
+		FLD_SET(*outflagsp, DB_ENV_CDB_ALLDB);
+		FLD_CLR(*inflagsp, DB_CDB_ALLDB);
 	}
-	if (LF_ISSET(DB_DIRECT_DB)) {
-		if (onoff)
-			F_SET(dbenv, DB_ENV_DIRECT_DB);
-		else
-			F_CLR(dbenv, DB_ENV_DIRECT_DB);
+	if (FLD_ISSET(*inflagsp, DB_DIRECT_DB)) {
+		FLD_SET(*outflagsp, DB_ENV_DIRECT_DB);
+		FLD_CLR(*inflagsp, DB_DIRECT_DB);
 	}
-	if (LF_ISSET(DB_DIRECT_LOG)) {
-		if (onoff)
-			F_SET(dbenv, DB_ENV_DIRECT_LOG);
-		else
-			F_CLR(dbenv, DB_ENV_DIRECT_LOG);
+	if (FLD_ISSET(*inflagsp, DB_DIRECT_LOG)) {
+		FLD_SET(*outflagsp, DB_ENV_DIRECT_LOG);
+		FLD_CLR(*inflagsp, DB_DIRECT_LOG);
 	}
-	if (LF_ISSET(DB_NOLOCKING)) {
-		if (onoff)
-			F_SET(dbenv, DB_ENV_NOLOCKING);
-		else
-			F_CLR(dbenv, DB_ENV_NOLOCKING);
+	if (FLD_ISSET(*inflagsp, DB_DSYNC_LOG)) {
+		FLD_SET(*outflagsp, DB_ENV_DSYNC_LOG);
+		FLD_CLR(*inflagsp, DB_DSYNC_LOG);
 	}
-	if (LF_ISSET(DB_NOMMAP)) {
-		if (onoff)
-			F_SET(dbenv, DB_ENV_NOMMAP);
-		else
-			F_CLR(dbenv, DB_ENV_NOMMAP);
+	if (FLD_ISSET(*inflagsp, DB_LOG_AUTOREMOVE)) {
+		FLD_SET(*outflagsp, DB_ENV_LOG_AUTOREMOVE);
+		FLD_CLR(*inflagsp, DB_LOG_AUTOREMOVE);
 	}
-	if (LF_ISSET(DB_NOPANIC)) {
-		if (onoff)
-			F_SET(dbenv, DB_ENV_NOPANIC);
-		else
-			F_CLR(dbenv, DB_ENV_NOPANIC);
+	if (FLD_ISSET(*inflagsp, DB_LOG_INMEMORY)) {
+		FLD_SET(*outflagsp, DB_ENV_LOG_INMEMORY);
+		FLD_CLR(*inflagsp, DB_LOG_INMEMORY);
 	}
-	if (LF_ISSET(DB_OVERWRITE)) {
-		if (onoff)
-			F_SET(dbenv, DB_ENV_OVERWRITE);
-		else
-			F_CLR(dbenv, DB_ENV_OVERWRITE);
+	if (FLD_ISSET(*inflagsp, DB_NOLOCKING)) {
+		FLD_SET(*outflagsp, DB_ENV_NOLOCKING);
+		FLD_CLR(*inflagsp, DB_NOLOCKING);
 	}
-	if (LF_ISSET(DB_PANIC_ENVIRONMENT)) {
-		ENV_ILLEGAL_BEFORE_OPEN(dbenv,
-		    "set_flags: DB_PANIC_ENVIRONMENT");
-		PANIC_SET(dbenv, onoff);
+	if (FLD_ISSET(*inflagsp, DB_NOMMAP)) {
+		FLD_SET(*outflagsp, DB_ENV_NOMMAP);
+		FLD_CLR(*inflagsp, DB_NOMMAP);
 	}
-	if (LF_ISSET(DB_REGION_INIT)) {
-		ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_flags: DB_REGION_INIT");
-		if (onoff)
-			F_SET(dbenv, DB_ENV_REGION_INIT);
-		else
-			F_CLR(dbenv, DB_ENV_REGION_INIT);
+	if (FLD_ISSET(*inflagsp, DB_NOPANIC)) {
+		FLD_SET(*outflagsp, DB_ENV_NOPANIC);
+		FLD_CLR(*inflagsp, DB_NOPANIC);
 	}
-	if (LF_ISSET(DB_TXN_NOSYNC)) {
-		if (onoff)
-			F_SET(dbenv, DB_ENV_TXN_NOSYNC);
-		else
-			F_CLR(dbenv, DB_ENV_TXN_NOSYNC);
+	if (FLD_ISSET(*inflagsp, DB_OVERWRITE)) {
+		FLD_SET(*outflagsp, DB_ENV_OVERWRITE);
+		FLD_CLR(*inflagsp, DB_OVERWRITE);
 	}
-	if (LF_ISSET(DB_TXN_WRITE_NOSYNC)) {
-		if (onoff)
-			F_SET(dbenv, DB_ENV_TXN_WRITE_NOSYNC);
-		else
-			F_CLR(dbenv, DB_ENV_TXN_WRITE_NOSYNC);
+	if (FLD_ISSET(*inflagsp, DB_REGION_INIT)) {
+		FLD_SET(*outflagsp, DB_ENV_REGION_INIT);
+		FLD_CLR(*inflagsp, DB_REGION_INIT);
 	}
-	if (LF_ISSET(DB_YIELDCPU)) {
-		if (onoff)
-			F_SET(dbenv, DB_ENV_YIELDCPU);
-		else
-			F_CLR(dbenv, DB_ENV_YIELDCPU);
+	if (FLD_ISSET(*inflagsp, DB_TIME_NOTGRANTED)) {
+		FLD_SET(*outflagsp, DB_ENV_TIME_NOTGRANTED);
+		FLD_CLR(*inflagsp, DB_TIME_NOTGRANTED);
+	}
+	if (FLD_ISSET(*inflagsp, DB_TXN_NOSYNC)) {
+		FLD_SET(*outflagsp, DB_ENV_TXN_NOSYNC);
+		FLD_CLR(*inflagsp, DB_TXN_NOSYNC);
+	}
+	if (FLD_ISSET(*inflagsp, DB_TXN_WRITE_NOSYNC)) {
+		FLD_SET(*outflagsp, DB_ENV_TXN_WRITE_NOSYNC);
+		FLD_CLR(*inflagsp, DB_TXN_WRITE_NOSYNC);
+	}
+	if (FLD_ISSET(*inflagsp, DB_YIELDCPU)) {
+		FLD_SET(*outflagsp, DB_ENV_YIELDCPU);
+		FLD_CLR(*inflagsp, DB_YIELDCPU);
+	}
+}
+
+static int
+__dbenv_get_flags(dbenv, flagsp)
+	DB_ENV *dbenv;
+	u_int32_t *flagsp;
+{
+	static const u_int32_t env_flags[] = {
+		DB_AUTO_COMMIT,
+		DB_CDB_ALLDB,
+		DB_DIRECT_DB,
+		DB_DIRECT_LOG,
+		DB_DSYNC_LOG,
+		DB_LOG_AUTOREMOVE,
+		DB_LOG_INMEMORY,
+		DB_NOLOCKING,
+		DB_NOMMAP,
+		DB_NOPANIC,
+		DB_OVERWRITE,
+		DB_REGION_INIT,
+		DB_TIME_NOTGRANTED,
+		DB_TXN_NOSYNC,
+		DB_TXN_WRITE_NOSYNC,
+		DB_YIELDCPU,
+		0
+	};
+	u_int32_t f, flags, mapped_flag;
+	int i;
+
+	flags = 0;
+	for (i = 0; (f = env_flags[i]) != 0; i++) {
+		mapped_flag = 0;
+		__dbenv_map_flags(dbenv, &f, &mapped_flag);
+		DB_ASSERT(f == 0);
+		if (F_ISSET(dbenv, mapped_flag) == mapped_flag)
+			LF_SET(env_flags[i]);
+	}
+
+	/* Some flags are persisted in the regions. */
+	if (dbenv->reginfo != NULL &&
+	    ((REGENV *)((REGINFO *)dbenv->reginfo)->primary)->envpanic != 0) {
+		LF_SET(DB_PANIC_ENVIRONMENT);
 	}
+	__log_get_flags(dbenv, &flags);
+
+	*flagsp = flags;
+	return (0);
+}
+
+/*
+ * __dbenv_set_flags --
+ *	DB_ENV->set_flags.
+ *
+ * PUBLIC: int  __dbenv_set_flags __P((DB_ENV *, u_int32_t, int));
+ */
+int
+__dbenv_set_flags(dbenv, flags, on)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+	int on;
+{
+	u_int32_t mapped_flags;
+	int ret;
+
+#define	OK_FLAGS							\
+	(DB_AUTO_COMMIT | DB_CDB_ALLDB | DB_DIRECT_DB | DB_DIRECT_LOG |	\
+	    DB_DSYNC_LOG | DB_LOG_AUTOREMOVE | DB_LOG_INMEMORY | \
+	    DB_NOLOCKING | DB_NOMMAP | DB_NOPANIC | DB_OVERWRITE | \
+	    DB_PANIC_ENVIRONMENT | DB_REGION_INIT | DB_TIME_NOTGRANTED | \
+	    DB_TXN_NOSYNC | DB_TXN_WRITE_NOSYNC | DB_YIELDCPU)
+
+	if (LF_ISSET(~OK_FLAGS))
+		return (__db_ferr(dbenv, "DB_ENV->set_flags", 0));
+	if (on) {
+		if ((ret = __db_fcchk(dbenv, "DB_ENV->set_flags",
+		    flags, DB_LOG_INMEMORY, DB_TXN_NOSYNC)) != 0)
+			return (ret);
+		if ((ret = __db_fcchk(dbenv, "DB_ENV->set_flags",
+		    flags, DB_LOG_INMEMORY, DB_TXN_WRITE_NOSYNC)) != 0)
+			return (ret);
+		if ((ret = __db_fcchk(dbenv, "DB_ENV->set_flags",
+		    flags, DB_TXN_NOSYNC, DB_TXN_WRITE_NOSYNC)) != 0)
+			return (ret);
+		if (LF_ISSET(DB_DIRECT_DB |
+		    DB_DIRECT_LOG) && __os_have_direct() == 0) {
+			__db_err(dbenv,
+	"DB_ENV->set_flags: direct I/O either not configured or not supported");
+			return (EINVAL);
+		}
+	}
+
+	if (LF_ISSET(DB_CDB_ALLDB))
+		ENV_ILLEGAL_AFTER_OPEN(dbenv,
+		    "DB_ENV->set_flags: DB_CDB_ALLDB");
+	if (LF_ISSET(DB_PANIC_ENVIRONMENT)) {
+		ENV_ILLEGAL_BEFORE_OPEN(dbenv,
+		    "DB_ENV->set_flags: DB_PANIC_ENVIRONMENT");
+		PANIC_SET(dbenv, on);
+	}
+	if (LF_ISSET(DB_REGION_INIT))
+		ENV_ILLEGAL_AFTER_OPEN(dbenv,
+		    "DB_ENV->set_flags: DB_REGION_INIT");
+
+	/*
+	 * DB_LOG_INMEMORY, DB_TXN_NOSYNC and DB_TXN_WRITE_NOSYNC are
+	 * mutually incompatible.  If we're setting one of them, clear all
+	 * current settings.
+	 */
+	if (LF_ISSET(
+	    DB_LOG_INMEMORY | DB_TXN_NOSYNC | DB_TXN_WRITE_NOSYNC))
+		F_CLR(dbenv,
+		    DB_ENV_LOG_INMEMORY |
+		    DB_ENV_TXN_NOSYNC | DB_ENV_TXN_WRITE_NOSYNC);
+
+	/* Some flags are persisted in the regions. */
+	__log_set_flags(dbenv, flags, on);
+
+	mapped_flags = 0;
+	__dbenv_map_flags(dbenv, &flags, &mapped_flags);
+	if (on)
+		F_SET(dbenv, mapped_flags);
+	else
+		F_CLR(dbenv, mapped_flags);
+
 	return (0);
 }
 
 static int
+__dbenv_get_data_dirs(dbenv, dirpp)
+	DB_ENV *dbenv;
+	const char ***dirpp;
+{
+	*dirpp = (const char **)dbenv->db_data_dir;
+	return (0);
+}
+
+/*
+ * __dbenv_set_data_dir --
+ *	DB_ENV->set_data_dir.
+ *
+ * PUBLIC: int  __dbenv_set_data_dir __P((DB_ENV *, const char *));
+ */
+int
 __dbenv_set_data_dir(dbenv, dir)
 	DB_ENV *dbenv;
 	const char *dir;
 {
 	int ret;
 
+	/*
+	 * The array is NULL-terminated so it can be returned by get_data_dirs
+	 * without a length.
+	 */
+
 #define	DATA_INIT_CNT	20			/* Start with 20 data slots. */
 	if (dbenv->db_data_dir == NULL) {
 		if ((ret = __os_calloc(dbenv, DATA_INIT_CNT,
 		    sizeof(char **), &dbenv->db_data_dir)) != 0)
 			return (ret);
 		dbenv->data_cnt = DATA_INIT_CNT;
-	} else if (dbenv->data_next == dbenv->data_cnt - 1) {
+	} else if (dbenv->data_next == dbenv->data_cnt - 2) {
 		dbenv->data_cnt *= 2;
 		if ((ret = __os_realloc(dbenv,
-		    dbenv->data_cnt * sizeof(char **),
+		    (u_int)dbenv->data_cnt * sizeof(char **),
 		    &dbenv->db_data_dir)) != 0)
 			return (ret);
 	}
-	return (__os_strdup(dbenv,
-	    dir, &dbenv->db_data_dir[dbenv->data_next++]));
+
+	ret = __os_strdup(dbenv,
+	    dir, &dbenv->db_data_dir[dbenv->data_next++]);
+	dbenv->db_data_dir[dbenv->data_next] = NULL;
+	return (ret);
 }
 
-static void
+/*
+ * __dbenv_set_intermediate_dir --
+ *	DB_ENV->set_intermediate_dir.
+ *
+ * !!!
+ * Undocumented routine allowing applications to configure Berkeley DB to
+ * create intermediate directories.
+ *
+ * PUBLIC: int  __dbenv_set_intermediate_dir __P((DB_ENV *, int, u_int32_t));
+ */
+int
+__dbenv_set_intermediate_dir(dbenv, mode, flags)
+	DB_ENV *dbenv;
+	int mode;
+	u_int32_t flags;
+{
+	if (flags != 0)
+		return (__db_ferr(dbenv, "DB_ENV->set_intermediate_dir", 0));
+	if (mode == 0) {
+		__db_err(dbenv,
+		    "DB_ENV->set_intermediate_dir: mode may not be set to 0");
+		return (EINVAL);
+	}
+
+	dbenv->dir_mode = mode;
+	return (0);
+}
+
+/*
+ * __dbenv_set_errcall --
+ *	{DB_ENV,DB}->set_errcall.
+ *
+ * PUBLIC: void __dbenv_set_errcall __P((DB_ENV *,
+ * PUBLIC:		void (*)(const DB_ENV *, const char *, const char *)));
+ */
+void
 __dbenv_set_errcall(dbenv, errcall)
 	DB_ENV *dbenv;
-	void (*errcall) __P((const char *, char *));
+	void (*errcall) __P((const DB_ENV *, const char *, const char *));
 {
 	dbenv->db_errcall = errcall;
 }
 
-static void
+/*
+ * __dbenv_get_errfile --
+ *	{DB_ENV,DB}->get_errfile.
+ *
+ * PUBLIC: void __dbenv_get_errfile __P((DB_ENV *, FILE **));
+ */
+void
+__dbenv_get_errfile(dbenv, errfilep)
+	DB_ENV *dbenv;
+	FILE **errfilep;
+{
+	*errfilep = dbenv->db_errfile;
+}
+
+/*
+ * __dbenv_set_errfile --
+ *	{DB_ENV,DB}->set_errfile.
+ *
+ * PUBLIC: void __dbenv_set_errfile __P((DB_ENV *, FILE *));
+ */
+void
 __dbenv_set_errfile(dbenv, errfile)
 	DB_ENV *dbenv;
 	FILE *errfile;
@@ -467,7 +728,27 @@ __dbenv_set_errfile(dbenv, errfile)
 	dbenv->db_errfile = errfile;
 }
 
-static void
+/*
+ * __dbenv_get_errpfx --
+ *	{DB_ENV,DB}->get_errpfx.
+ *
+ * PUBLIC: void __dbenv_get_errpfx __P((DB_ENV *, const char **));
+ */
+void
+__dbenv_get_errpfx(dbenv, errpfxp)
+	DB_ENV *dbenv;
+	const char **errpfxp;
+{
+	*errpfxp = dbenv->db_errpfx;
+}
+
+/*
+ * __dbenv_set_errpfx --
+ *	{DB_ENV,DB}->set_errpfx.
+ *
+ * PUBLIC: void __dbenv_set_errpfx __P((DB_ENV *, const char *));
+ */
+void
 __dbenv_set_errpfx(dbenv, errpfx)
 	DB_ENV *dbenv;
 	const char *errpfx;
@@ -484,15 +765,56 @@ __dbenv_set_feedback(dbenv, feedback)
 	return (0);
 }
 
-static void
-__dbenv_set_noticecall(dbenv, noticecall)
+/*
+ * __dbenv_set_msgcall --
+ *	{DB_ENV,DB}->set_msgcall.
+ *
+ * PUBLIC: void __dbenv_set_msgcall
+ * PUBLIC:     __P((DB_ENV *, void (*)(const DB_ENV *, const char *)));
+ */
+void
+__dbenv_set_msgcall(dbenv, msgcall)
 	DB_ENV *dbenv;
-	void (*noticecall) __P((DB_ENV *, db_notices));
+	void (*msgcall) __P((const DB_ENV *, const char *));
 {
-	dbenv->db_noticecall = noticecall;
+	dbenv->db_msgcall = msgcall;
 }
-			
-static int
+
+/*
+ * __dbenv_get_msgfile --
+ *	{DB_ENV,DB}->get_msgfile.
+ *
+ * PUBLIC: void __dbenv_get_msgfile __P((DB_ENV *, FILE **));
+ */
+void
+__dbenv_get_msgfile(dbenv, msgfilep)
+	DB_ENV *dbenv;
+	FILE **msgfilep;
+{
+	*msgfilep = dbenv->db_msgfile;
+}
+
+/*
+ * __dbenv_set_msgfile --
+ *	{DB_ENV,DB}->set_msgfile.
+ *
+ * PUBLIC: void __dbenv_set_msgfile __P((DB_ENV *, FILE *));
+ */
+void
+__dbenv_set_msgfile(dbenv, msgfile)
+	DB_ENV *dbenv;
+	FILE *msgfile;
+{
+	dbenv->db_msgfile = msgfile;
+}
+
+/*
+ * __dbenv_set_paniccall --
+ *	{DB_ENV,DB}->set_paniccall.
+ *
+ * PUBLIC: int  __dbenv_set_paniccall __P((DB_ENV *, void (*)(DB_ENV *, int)));
+ */
+int
 __dbenv_set_paniccall(dbenv, paniccall)
 	DB_ENV *dbenv;
 	void (*paniccall) __P((DB_ENV *, int));
@@ -502,17 +824,47 @@ __dbenv_set_paniccall(dbenv, paniccall)
 }
 
 static int
+__dbenv_get_shm_key(dbenv, shm_keyp)
+	DB_ENV *dbenv;
+	long *shm_keyp;			/* !!!: really a key_t *. */
+{
+	*shm_keyp = dbenv->shm_key;
+	return (0);
+}
+
+/*
+ * __dbenv_set_shm_key --
+ *	DB_ENV->set_shm_key.
+ *
+ * PUBLIC: int  __dbenv_set_shm_key __P((DB_ENV *, long));
+ */
+int
 __dbenv_set_shm_key(dbenv, shm_key)
 	DB_ENV *dbenv;
 	long shm_key;			/* !!!: really a key_t. */
 {
-	ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_shm_key");
+	ENV_ILLEGAL_AFTER_OPEN(dbenv, "DB_ENV->set_shm_key");
 
 	dbenv->shm_key = shm_key;
 	return (0);
 }
 
 static int
+__dbenv_get_tas_spins(dbenv, tas_spinsp)
+	DB_ENV *dbenv;
+	u_int32_t *tas_spinsp;
+{
+	*tas_spinsp = dbenv->tas_spins;
+	return (0);
+}
+
+/*
+ * __dbenv_set_tas_spins --
+ *	DB_ENV->set_tas_spins.
+ *
+ * PUBLIC: int  __dbenv_set_tas_spins __P((DB_ENV *, u_int32_t));
+ */
+int
 __dbenv_set_tas_spins(dbenv, tas_spins)
 	DB_ENV *dbenv;
 	u_int32_t tas_spins;
@@ -522,6 +874,21 @@ __dbenv_set_tas_spins(dbenv, tas_spins)
 }
 
 static int
+__dbenv_get_tmp_dir(dbenv, dirp)
+	DB_ENV *dbenv;
+	const char **dirp;
+{
+	*dirp = dbenv->db_tmp_dir;
+	return (0);
+}
+
+/*
+ * __dbenv_set_tmp_dir --
+ *	DB_ENV->set_tmp_dir.
+ *
+ * PUBLIC: int  __dbenv_set_tmp_dir __P((DB_ENV *, const char *));
+ */
+int
 __dbenv_set_tmp_dir(dbenv, dir)
 	DB_ENV *dbenv;
 	const char *dir;
@@ -532,18 +899,42 @@ __dbenv_set_tmp_dir(dbenv, dir)
 }
 
 static int
-__dbenv_set_verbose(dbenv, which, onoff)
+__dbenv_get_verbose(dbenv, which, onoffp)
 	DB_ENV *dbenv;
 	u_int32_t which;
-	int onoff;
+	int *onoffp;
 {
 	switch (which) {
-	case DB_VERB_CHKPOINT:
 	case DB_VERB_DEADLOCK:
 	case DB_VERB_RECOVERY:
 	case DB_VERB_REPLICATION:
 	case DB_VERB_WAITSFOR:
-		if (onoff)
+		*onoffp = FLD_ISSET(dbenv->verbose, which) ? 1 : 0;
+		break;
+	default:
+		return (EINVAL);
+	}
+	return (0);
+}
+
+/*
+ * __dbenv_set_verbose --
+ *	DB_ENV->set_verbose.
+ *
+ * PUBLIC: int  __dbenv_set_verbose __P((DB_ENV *, u_int32_t, int));
+ */
+int
+__dbenv_set_verbose(dbenv, which, on)
+	DB_ENV *dbenv;
+	u_int32_t which;
+	int on;
+{
+	switch (which) {
+	case DB_VERB_DEADLOCK:
+	case DB_VERB_RECOVERY:
+	case DB_VERB_REPLICATION:
+	case DB_VERB_WAITSFOR:
+		if (on)
 			FLD_SET(dbenv->verbose, which);
 		else
 			FLD_CLR(dbenv->verbose, which);
@@ -565,7 +956,8 @@ __db_mi_env(dbenv, name)
 	DB_ENV *dbenv;
 	const char *name;
 {
-	__db_err(dbenv, "%s: method not permitted in shared environment", name);
+	__db_err(dbenv, "%s: method not permitted when environment specified",
+	    name);
 	return (EINVAL);
 }
 
@@ -581,7 +973,7 @@ __db_mi_open(dbenv, name, after)
 	const char *name;
 	int after;
 {
-	__db_err(dbenv, "%s: method not permitted %s open",
+	__db_err(dbenv, "%s: method not permitted %s handle's open method",
 	    name, after ? "after" : "before");
 	return (EINVAL);
 }
@@ -610,6 +1002,9 @@ __db_env_config(dbenv, i, flags)
 	case DB_INIT_MPOOL:
 		sub = "memory pool";
 		break;
+	case DB_INIT_REP:
+		sub = "replication";
+		break;
 	case DB_INIT_TXN:
 		sub = "transaction";
 		break;
@@ -639,5 +1034,5 @@ __dbenv_set_rpc_server_noclnt(dbenv, cl, host, tsec, ssec, flags)
 
 	__db_err(dbenv,
 	    "set_rpc_server method not permitted in non-RPC environment");
-	return (__db_eopnotsup(dbenv));
+	return (DB_OPNOTSUP);
 }
diff --git a/storage/bdb/env/env_open.c b/storage/bdb/env/env_open.c
index ae8399f61cd29981e50784a9bf7ecfcad232939e..0fbce72d009ae0a5da57c4e8d9237f77fca9a8cf 100644
--- a/storage/bdb/env/env_open.c
+++ b/storage/bdb/env/env_open.c
@@ -1,23 +1,21 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: env_open.c,v 11.177 2004/07/17 18:55:08 ubell Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: env_open.c,v 11.111 2002/09/03 01:20:51 mjc Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <ctype.h>
+#include <limits.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 #endif
 
 #include "db_int.h"
@@ -26,19 +24,18 @@ static const char revid[] = "$Id: env_open.c,v 11.111 2002/09/03 01:20:51 mjc Ex
 #include "dbinc/db_shash.h"
 #include "dbinc/btree.h"
 #include "dbinc/hash.h"
+#include "dbinc/fop.h"
 #include "dbinc/lock.h"
 #include "dbinc/log.h"
 #include "dbinc/mp.h"
 #include "dbinc/qam.h"
-#include "dbinc/rep.h"
 #include "dbinc/txn.h"
-#include "dbinc/fop.h"
 
 static int __db_parse __P((DB_ENV *, char *));
-static int __db_tmp_open __P((DB_ENV *, u_int32_t, char *, DB_FH *));
+static int __db_tmp_open __P((DB_ENV *, u_int32_t, char *, DB_FH **));
 static int __dbenv_config __P((DB_ENV *, const char *, u_int32_t));
-static int __dbenv_iremove __P((DB_ENV *, const char *, u_int32_t));
-static int __dbenv_refresh __P((DB_ENV *, u_int32_t));
+static int __dbenv_refresh __P((DB_ENV *, u_int32_t, int));
+static int __dbenv_remove_int __P((DB_ENV *, const char *, u_int32_t));
 
 /*
  * db_version --
@@ -61,7 +58,7 @@ db_version(majverp, minverp, patchp)
 
 /*
  * __dbenv_open --
- *	Initialize an environment.
+ *	DB_ENV->open.
  *
  * PUBLIC: int __dbenv_open __P((DB_ENV *, const char *, u_int32_t, int));
  */
@@ -73,22 +70,23 @@ __dbenv_open(dbenv, db_home, flags, mode)
 	int mode;
 {
 	DB_MPOOL *dbmp;
-	int ret;
 	u_int32_t init_flags, orig_flags;
+	int rep_check, ret;
 
 	orig_flags = dbenv->flags;
+	rep_check = 0;
 
 #undef	OKFLAGS
 #define	OKFLAGS								\
-	DB_CREATE | DB_INIT_CDB | DB_INIT_LOCK | DB_INIT_LOG |		\
-	DB_INIT_MPOOL | DB_INIT_TXN | DB_JOINENV | DB_LOCKDOWN |	\
-	DB_PRIVATE | DB_RECOVER | DB_RECOVER_FATAL | DB_SYSTEM_MEM |	\
-	DB_THREAD | DB_USE_ENVIRON | DB_USE_ENVIRON_ROOT
+	(DB_CREATE | DB_INIT_CDB | DB_INIT_LOCK | DB_INIT_LOG |		\
+	DB_INIT_MPOOL | DB_INIT_REP | DB_INIT_TXN | DB_JOINENV |	\
+	DB_LOCKDOWN | DB_PRIVATE | DB_RECOVER | DB_RECOVER_FATAL |	\
+	DB_SYSTEM_MEM |	DB_THREAD | DB_USE_ENVIRON | DB_USE_ENVIRON_ROOT)
 #undef	OKFLAGS_CDB
 #define	OKFLAGS_CDB							\
-	DB_CREATE | DB_INIT_CDB | DB_INIT_MPOOL | DB_LOCKDOWN |		\
+	(DB_CREATE | DB_INIT_CDB | DB_INIT_MPOOL | DB_LOCKDOWN |	\
 	DB_PRIVATE | DB_SYSTEM_MEM | DB_THREAD |			\
-	DB_USE_ENVIRON | DB_USE_ENVIRON_ROOT
+	DB_USE_ENVIRON | DB_USE_ENVIRON_ROOT)
 
 	/*
 	 * Flags saved in the init_flags field of the environment, representing
@@ -99,7 +97,8 @@ __dbenv_open(dbenv, db_home, flags, mode)
 #define	DB_INITENV_LOCK		0x0004	/* DB_INIT_LOCK */
 #define	DB_INITENV_LOG		0x0008	/* DB_INIT_LOG */
 #define	DB_INITENV_MPOOL	0x0010	/* DB_INIT_MPOOL */
-#define	DB_INITENV_TXN		0x0020	/* DB_INIT_TXN */
+#define	DB_INITENV_REP		0x0020	/* DB_INIT_REP */
+#define	DB_INITENV_TXN		0x0040	/* DB_INIT_TXN */
 
 	if ((ret = __db_fchk(dbenv, "DB_ENV->open", flags, OKFLAGS)) != 0)
 		return (ret);
@@ -114,8 +113,21 @@ __dbenv_open(dbenv, db_home, flags, mode)
 		return (ret);
 	if ((ret = __db_fcchk(dbenv, "DB_ENV->open", flags, DB_JOINENV,
 	    DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL |
-	    DB_INIT_TXN | DB_PRIVATE)) != 0)
+	    DB_INIT_REP | DB_INIT_TXN |
+	    DB_PRIVATE | DB_RECOVER | DB_RECOVER_FATAL)) != 0)
 		return (ret);
+	if (LF_ISSET(DB_INIT_REP) && !LF_ISSET(DB_INIT_TXN)) {
+		__db_err(dbenv, "Replication requires transaction support");
+		return (EINVAL);
+	}
+	if (LF_ISSET(DB_INIT_REP) && !LF_ISSET(DB_INIT_LOCK)) {
+		__db_err(dbenv, "Replication requires locking support");
+		return (EINVAL);
+	}
+	if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL) && !LF_ISSET(DB_INIT_TXN)) {
+		__db_err(dbenv, "Recovery requires transaction support");
+		return (EINVAL);
+	}
 
 	/*
 	 * Currently we support one kind of mutex that is intra-process only,
@@ -125,7 +137,7 @@ __dbenv_open(dbenv, db_home, flags, mode)
 #ifdef HAVE_MUTEX_THREAD_ONLY
 	if (!LF_ISSET(DB_PRIVATE)) {
 		__db_err(dbenv,
-    "Berkeley DB library configured to support only DB_PRIVATE environments");
+    "Berkeley DB library configured to support only private environments");
 		return (EINVAL);
 	}
 #endif
@@ -149,8 +161,8 @@ __dbenv_open(dbenv, db_home, flags, mode)
 	 * reason, from whatever session.
 	 */
 	if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL))
-		if ((ret = __dbenv_iremove(dbenv, db_home, DB_FORCE)) != 0 ||
-		    (ret = __dbenv_refresh(dbenv, orig_flags)) != 0)
+		if ((ret = __dbenv_remove_int(dbenv, db_home, DB_FORCE)) != 0 ||
+		    (ret = __dbenv_refresh(dbenv, orig_flags, 0)) != 0)
 			return (ret);
 
 	/* Initialize the DB_ENV structure. */
@@ -175,41 +187,74 @@ __dbenv_open(dbenv, db_home, flags, mode)
 	dbenv->db_mode = mode == 0 ? __db_omode("rwrw--") : mode;
 
 	/*
-	 * Create/join the environment.  We pass in the flags that
-	 * will be of interest to an environment joining later;  if
-	 * we're not the ones to do the create, we
-	 * pull out whatever has been stored, if we don't do a create.
+	 * Create/join the environment.  We pass in the flags that will be of
+	 * interest to an environment joining later; if we're not the ones to
+	 * do the create, we pull out whatever has been stored.
 	 */
 	init_flags = 0;
-	init_flags |= (LF_ISSET(DB_INIT_CDB) ? DB_INITENV_CDB : 0);
-	init_flags |= (LF_ISSET(DB_INIT_LOCK) ? DB_INITENV_LOCK : 0);
-	init_flags |= (LF_ISSET(DB_INIT_LOG) ? DB_INITENV_LOG : 0);
-	init_flags |= (LF_ISSET(DB_INIT_MPOOL) ? DB_INITENV_MPOOL : 0);
-	init_flags |= (LF_ISSET(DB_INIT_TXN) ? DB_INITENV_TXN : 0);
-	init_flags |=
-	    (F_ISSET(dbenv, DB_ENV_CDB_ALLDB) ? DB_INITENV_CDB_ALLDB : 0);
-
+	if (LF_ISSET(DB_INIT_CDB))
+		FLD_SET(init_flags, DB_INITENV_CDB);
+	if (LF_ISSET(DB_INIT_LOCK))
+		FLD_SET(init_flags, DB_INITENV_LOCK);
+	if (LF_ISSET(DB_INIT_LOG))
+		FLD_SET(init_flags, DB_INITENV_LOG);
+	if (LF_ISSET(DB_INIT_MPOOL))
+		FLD_SET(init_flags, DB_INITENV_MPOOL);
+	if (LF_ISSET(DB_INIT_REP))
+		FLD_SET(init_flags, DB_INITENV_REP);
+	if (LF_ISSET(DB_INIT_TXN))
+		FLD_SET(init_flags, DB_INITENV_TXN);
+	if (F_ISSET(dbenv, DB_ENV_CDB_ALLDB))
+		FLD_SET(init_flags, DB_INITENV_CDB_ALLDB);
 	if ((ret = __db_e_attach(dbenv, &init_flags)) != 0)
 		goto err;
 
 	/*
-	 * __db_e_attach will return the saved init_flags field, which
-	 * contains the DB_INIT_* flags used when we were created.
+	 * __db_e_attach will return the saved init_flags field, which contains
+	 * the DB_INIT_* flags used when the environment was created.
+	 *
+	 * Check if existing environment flags conflict with our flags.
 	 */
+	if (LF_ISSET(DB_INIT_CDB) && FLD_ISSET(init_flags, DB_INITENV_TXN)) {
+		__db_err(dbenv,
+		    "Concurrent Data Store incompatible with environment");
+		ret = EINVAL;
+		goto err;
+	}
+	if (LF_ISSET(DB_INIT_TXN) && FLD_ISSET(init_flags, DB_INITENV_CDB)) {
+		__db_err(dbenv,
+		    "Transactional Data Store incompatible with environment");
+		ret = EINVAL;
+		goto err;
+	}
+
+	/* If we're joining the environment, find out what we're joining. */
 	if (LF_ISSET(DB_JOINENV)) {
 		LF_CLR(DB_JOINENV);
-
-		LF_SET((init_flags & DB_INITENV_CDB) ? DB_INIT_CDB : 0);
-		LF_SET((init_flags & DB_INITENV_LOCK) ? DB_INIT_LOCK : 0);
-		LF_SET((init_flags & DB_INITENV_LOG) ? DB_INIT_LOG : 0);
-		LF_SET((init_flags & DB_INITENV_MPOOL) ? DB_INIT_MPOOL : 0);
-		LF_SET((init_flags & DB_INITENV_TXN) ? DB_INIT_TXN : 0);
-
-		if (LF_ISSET(DB_INITENV_CDB_ALLDB) &&
-		    (ret = dbenv->set_flags(dbenv, DB_CDB_ALLDB, 1)) != 0)
+		if (FLD_ISSET(init_flags, DB_INITENV_CDB))
+			LF_SET(DB_INIT_CDB);
+		if (FLD_ISSET(init_flags, DB_INITENV_LOCK))
+			LF_SET(DB_INIT_LOCK);
+		if (FLD_ISSET(init_flags, DB_INITENV_LOG))
+			LF_SET(DB_INIT_LOG);
+		if (FLD_ISSET(init_flags, DB_INITENV_MPOOL))
+			LF_SET(DB_INIT_MPOOL);
+		if (FLD_ISSET(init_flags, DB_INITENV_REP))
+			LF_SET(DB_INIT_REP);
+		if (FLD_ISSET(init_flags, DB_INITENV_TXN))
+			LF_SET(DB_INIT_TXN);
+		if (FLD_ISSET(init_flags, DB_INITENV_CDB_ALLDB) &&
+		    (ret = __dbenv_set_flags(dbenv, DB_CDB_ALLDB, 1)) != 0)
 			goto err;
 	}
 
+	/*
+	 * Save the flags passed to create the DB_ENV->open, that is, we've
+	 * now replaced flags like DB_JOINENV with the flags responsible for
+	 * the underlying set of subsystems.
+	 */
+	dbenv->open_flags = flags;
+
 	/* Initialize for CDB product. */
 	if (LF_ISSET(DB_INIT_CDB)) {
 		LF_SET(DB_INIT_LOCK);
@@ -217,18 +262,21 @@ __dbenv_open(dbenv, db_home, flags, mode)
 	}
 
 	/*
-	 * Initialize the subsystems.  Transactions imply logging but do not
-	 * imply locking.  While almost all applications want both locking
-	 * and logging, it would not be unreasonable for a single threaded
-	 * process to want transactions for atomicity guarantees, but not
-	 * necessarily need concurrency.
+	 * Initialize the subsystems.
+	 *
+	 * Initialize the replication area first, so that we can lock out this
+	 * call if we're currently running recovery for replication.
 	 */
+	if (LF_ISSET(DB_INIT_REP) && (ret = __rep_open(dbenv)) != 0)
+		goto err;
+
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
 
 	if (LF_ISSET(DB_INIT_MPOOL))
 		if ((ret = __memp_open(dbenv)) != 0)
 			goto err;
-
-#ifdef HAVE_CRYPTO
 	/*
 	 * Initialize the ciphering area prior to any running of recovery so
 	 * that we can initialize the keys, etc. before recovery.
@@ -237,16 +285,23 @@ __dbenv_open(dbenv, db_home, flags, mode)
 	 * This must be after the mpool init, but before the log initialization
 	 * because log_open may attempt to run log_recover during its open.
 	 */
-	if ((ret = __crypto_region_init(dbenv)) != 0)
+	if (LF_ISSET(DB_INIT_MPOOL | DB_INIT_LOG | DB_INIT_TXN) &&
+	    (ret = __crypto_region_init(dbenv)) != 0)
 		goto err;
-#endif
 
+	/*
+	 * Transactions imply logging but do not imply locking.  While almost
+	 * all applications want both locking and logging, it would not be
+	 * unreasonable for a single threaded process to want transactions for
+	 * atomicity guarantees, but not necessarily need concurrency.
+	 */
 	if (LF_ISSET(DB_INIT_LOG | DB_INIT_TXN))
 		if ((ret = __log_open(dbenv)) != 0)
 			goto err;
 	if (LF_ISSET(DB_INIT_LOCK))
 		if ((ret = __lock_open(dbenv)) != 0)
 			goto err;
+
 	if (LF_ISSET(DB_INIT_TXN)) {
 		if ((ret = __txn_open(dbenv)) != 0)
 			goto err;
@@ -279,18 +334,8 @@ __dbenv_open(dbenv, db_home, flags, mode)
 		if ((ret = __txn_init_recover(dbenv, &dbenv->recover_dtab,
 		    &dbenv->recover_dtab_size)) != 0)
 			goto err;
-
-		/* Perform recovery for any previous run. */
-		if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL) &&
-		    (ret = __db_apprec(dbenv, NULL,
-		    LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL))) != 0)
-			goto err;
 	}
 
-	/* Initialize the replication area just in case. */
-	if ((ret = __rep_region_init(dbenv)) != 0)
-		goto err;
-
 	/*
 	 * Initialize the DB list, and its mutex as necessary.  If the env
 	 * handle isn't free-threaded we don't need a mutex because there
@@ -307,18 +352,30 @@ __dbenv_open(dbenv, db_home, flags, mode)
 	 * already be initialized.
 	 */
 	LIST_INIT(&dbenv->dblist);
-	if (F_ISSET(dbenv, DB_ENV_THREAD) && LF_ISSET(DB_INIT_MPOOL)) {
+	if (LF_ISSET(DB_INIT_MPOOL)) {
 		dbmp = dbenv->mp_handle;
-		if ((ret = __db_mutex_setup(
-		    dbenv, dbmp->reginfo, &dbenv->dblist_mutexp,
-		    MUTEX_ALLOC | MUTEX_THREAD)) != 0)
-			goto err;
-		if ((ret = __db_mutex_setup(
-		    dbenv, dbmp->reginfo, &dbenv->mt_mutexp,
-		    MUTEX_ALLOC | MUTEX_THREAD)) != 0)
-			goto err;
+		if (F_ISSET(dbenv, DB_ENV_THREAD)) {
+			if ((ret = __db_mutex_setup(
+			    dbenv, dbmp->reginfo, &dbenv->dblist_mutexp,
+			    MUTEX_ALLOC | MUTEX_THREAD)) != 0)
+				goto err;
+			if ((ret = __db_mutex_setup(
+			    dbenv, dbmp->reginfo, &dbenv->mt_mutexp,
+			    MUTEX_ALLOC | MUTEX_THREAD)) != 0)
+				goto err;
+		}
+		/* Register DB's pgin/pgout functions.  */
+		if ((ret = __memp_register(
+		    dbenv, DB_FTYPE_SET, __db_pgin, __db_pgout)) != 0)
+			return (ret);
 	}
 
+	/* Perform recovery for any previous run. */
+	if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL) &&
+	    (ret = __db_apprec(dbenv, NULL, NULL, 1,
+	    LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL))) != 0)
+		goto err;
+
 	/*
 	 * If we've created the regions, are running with transactions, and did
 	 * not just run recovery, we need to log the fact that the transaction
@@ -330,29 +387,41 @@ __dbenv_open(dbenv, db_home, flags, mode)
 	 * don't need to do anything here in the recover case.
 	 */
 	if (TXN_ON(dbenv) &&
+	    !F_ISSET(dbenv, DB_ENV_LOG_INMEMORY) &&
 	    F_ISSET((REGINFO *)dbenv->reginfo, REGION_CREATE) &&
 	    !LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL) &&
 	    (ret = __txn_reset(dbenv)) != 0)
 		goto err;
 
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+
 	return (0);
 
-err:	/* If we fail after creating the regions, remove them. */
+err:	/*
+	 * If we fail after creating the regions, remove them.
+	 *
+	 * !!!
+	 * No need to call __env_db_rep_exit, that work is done by the calls to
+	 * __dbenv_refresh.
+	 */
 	if (dbenv->reginfo != NULL &&
 	    F_ISSET((REGINFO *)dbenv->reginfo, REGION_CREATE)) {
 		ret = __db_panic(dbenv, ret);
 
-		(void)__dbenv_refresh(dbenv, orig_flags);
-		(void)__dbenv_iremove(dbenv, db_home, DB_FORCE);
-	}
-	(void)__dbenv_refresh(dbenv, orig_flags);
+		/* Refresh the DB_ENV so we can use it to call remove. */
+		(void)__dbenv_refresh(dbenv, orig_flags, rep_check);
+		(void)__dbenv_remove_int(dbenv, db_home, DB_FORCE);
+		(void)__dbenv_refresh(dbenv, orig_flags, 0);
+	} else
+		(void)__dbenv_refresh(dbenv, orig_flags, rep_check);
 
 	return (ret);
 }
 
 /*
  * __dbenv_remove --
- *	Discard an environment.
+ *	DB_ENV->remove.
  *
  * PUBLIC: int __dbenv_remove __P((DB_ENV *, const char *, u_int32_t));
  */
@@ -364,36 +433,36 @@ __dbenv_remove(dbenv, db_home, flags)
 {
 	int ret, t_ret;
 
-	ret = __dbenv_iremove(dbenv, db_home, flags);
+#undef	OKFLAGS
+#define	OKFLAGS								\
+	(DB_FORCE | DB_USE_ENVIRON | DB_USE_ENVIRON_ROOT)
 
-	if ((t_ret = dbenv->close(dbenv, 0)) != 0 && ret == 0)
+	/* Validate arguments. */
+	if ((ret = __db_fchk(dbenv, "DB_ENV->remove", flags, OKFLAGS)) != 0)
+		return (ret);
+
+	ENV_ILLEGAL_AFTER_OPEN(dbenv, "DB_ENV->remove");
+
+	ret = __dbenv_remove_int(dbenv, db_home, flags);
+
+	if ((t_ret = __dbenv_close(dbenv, 0)) != 0 && ret == 0)
 		ret = t_ret;
 
 	return (ret);
 }
 
 /*
- * __dbenv_iremove --
+ * __dbenv_remove_int --
  *	Discard an environment, internal version.
  */
 static int
-__dbenv_iremove(dbenv, db_home, flags)
+__dbenv_remove_int(dbenv, db_home, flags)
 	DB_ENV *dbenv;
 	const char *db_home;
 	u_int32_t flags;
 {
 	int ret;
 
-#undef	OKFLAGS
-#define	OKFLAGS								\
-	DB_FORCE | DB_USE_ENVIRON | DB_USE_ENVIRON_ROOT
-
-	/* Validate arguments. */
-	if ((ret = __db_fchk(dbenv, "DB_ENV->remove", flags, OKFLAGS)) != 0)
-		return (ret);
-
-	ENV_ILLEGAL_AFTER_OPEN(dbenv, "DB_ENV->remove");
-
 	/* Initialize the DB_ENV structure. */
 	if ((ret = __dbenv_config(dbenv, db_home, flags)) != 0)
 		return (ret);
@@ -404,7 +473,7 @@ __dbenv_iremove(dbenv, db_home, flags)
 
 /*
  * __dbenv_config --
- *	Initialize the DB_ENV structure.
+ *	Minor initialization of the DB_ENV structure, read the DB_CONFIG file.
  */
 static int
 __dbenv_config(dbenv, db_home, flags)
@@ -424,12 +493,16 @@ __dbenv_config(dbenv, db_home, flags)
 		return (ret);
 
 	/* Parse the config file. */
+	p = NULL;
 	if ((ret =
 	    __db_appname(dbenv, DB_APP_NONE, "DB_CONFIG", 0, NULL, &p)) != 0)
 		return (ret);
-
-	fp = fopen(p, "r");
-	__os_free(dbenv, p);
+	if (p == NULL)
+		fp = NULL;
+	else {
+		fp = fopen(p, "r");
+		__os_free(dbenv, p);
+	}
 
 	if (fp != NULL) {
 		while (fgets(buf, sizeof(buf), fp) != NULL) {
@@ -459,15 +532,6 @@ __dbenv_config(dbenv, db_home, flags)
 	if (dbenv->db_tmp_dir == NULL && (ret = __os_tmpdir(dbenv, flags)) != 0)
 		return (ret);
 
-	/*
-	 * The locking file descriptor is rarely on.  Set the fd to -1, not
-	 * because it's ever tested, but to make sure we catch mistakes.
-	 */
-	if ((ret = __os_calloc(
-	    dbenv, 1, sizeof(*dbenv->lockfhp), &dbenv->lockfhp)) != 0)
-		return (ret);
-	dbenv->lockfhp->fd = -1;
-
 	/* Flag that the DB_ENV structure has been initialized. */
 	F_SET(dbenv, DB_ENV_OPEN_CALLED);
 
@@ -475,56 +539,87 @@ __dbenv_config(dbenv, db_home, flags)
 }
 
 /*
- * __dbenv_close --
- *	DB_ENV destructor.
+ * __dbenv_close_pp --
+ *	DB_ENV->close pre/post processor.
  *
- * PUBLIC: int __dbenv_close __P((DB_ENV *, u_int32_t));
+ * PUBLIC: int __dbenv_close_pp __P((DB_ENV *, u_int32_t));
  */
 int
-__dbenv_close(dbenv, flags)
+__dbenv_close_pp(dbenv, flags)
 	DB_ENV *dbenv;
 	u_int32_t flags;
 {
-	char **p;
-	int ret, t_ret;
+	int rep_check, ret, t_ret;
 
-	COMPQUIET(flags, 0);
+	ret = 0;
 
 	PANIC_CHECK(dbenv);
+
+	/*
+	 * Validate arguments, but as a DB_ENV handle destructor, we can't
+	 * fail.
+	 */
+	if (flags != 0 &&
+	    (t_ret = __db_ferr(dbenv, "DB_ENV->close", 0)) != 0 && ret == 0)
+		ret = t_ret;
+
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+
+	if ((t_ret = __dbenv_close(dbenv, rep_check)) != 0 && ret == 0)
+		ret = t_ret;
+
+	return (ret);
+}
+
+/*
+ * __dbenv_close --
+ *	DB_ENV->close.
+ *
+ * PUBLIC: int __dbenv_close __P((DB_ENV *, int));
+ */
+int
+__dbenv_close(dbenv, rep_check)
+	DB_ENV *dbenv;
+	int rep_check;
+{
+	int ret, t_ret;
+	char **p;
+
 	ret = 0;
 
 	/*
-	 * Before checking the reference count, we have to see if we
-	 * were in the middle of restoring transactions and need to
-	 * close the open files.
+	 * Before checking the reference count, we have to see if we were in
+	 * the middle of restoring transactions and need to close the open
+	 * files.
 	 */
 	if (TXN_ON(dbenv) && (t_ret = __txn_preclose(dbenv)) != 0 && ret == 0)
 		ret = t_ret;
 
-	if (dbenv->rep_handle != NULL &&
+	if (REP_ON(dbenv) &&
 	    (t_ret = __rep_preclose(dbenv, 1)) != 0 && ret == 0)
-			ret = t_ret;
-
-	if (dbenv->db_ref != 0) {
-		__db_err(dbenv,
-		    "Database handles open during environment close");
-		if (ret == 0)
-			ret = EINVAL;
-	}
+		ret = t_ret;
 
 	/*
 	 * Detach from the regions and undo the allocations done by
 	 * DB_ENV->open.
 	 */
-	if ((t_ret = __dbenv_refresh(dbenv, 0)) != 0 && ret == 0)
+	if ((t_ret = __dbenv_refresh(dbenv, 0, rep_check)) != 0 && ret == 0)
+		ret = t_ret;
+
+	/* Do per-subsystem close. */
+	if ((t_ret = __lock_dbenv_close(dbenv)) != 0 && ret == 0)
 		ret = t_ret;
 
-	/* Do per-subsystem destruction. */
-	__lock_dbenv_close(dbenv); /* void */
 	if ((t_ret = __rep_dbenv_close(dbenv)) != 0 && ret == 0)
 		ret = t_ret;
 
 #ifdef HAVE_CRYPTO
+	/*
+	 * Crypto comes last, because higher level close functions need
+	 * cryptography.
+	 */
 	if ((t_ret = __crypto_dbenv_close(dbenv)) != 0 && ret == 0)
 		ret = t_ret;
 #endif
@@ -555,23 +650,26 @@ __dbenv_close(dbenv, flags)
  * pre-open configuration functions must be preserved.)
  */
 static int
-__dbenv_refresh(dbenv, orig_flags)
+__dbenv_refresh(dbenv, orig_flags, rep_check)
 	DB_ENV *dbenv;
 	u_int32_t orig_flags;
+	int rep_check;
 {
+	DB *ldbp;
 	DB_MPOOL *dbmp;
 	int ret, t_ret;
 
+	dbmp = dbenv->mp_handle;
 	ret = 0;
 
 	/*
-	 * Close subsystems, in the reverse order they were opened (txn
+	 * Refresh subsystems, in the reverse order they were opened (txn
 	 * must be first, it may want to discard locks and flush the log).
 	 *
 	 * !!!
 	 * Note that these functions, like all of __dbenv_refresh, only undo
 	 * the effects of __dbenv_open.  Functions that undo work done by
-	 * db_env_create or by a configurator function should go in
+	 * db_env_create or by a configuration function should go in
 	 * __dbenv_close.
 	 */
 	if (TXN_ON(dbenv) &&
@@ -586,9 +684,17 @@ __dbenv_refresh(dbenv, orig_flags)
 	 * Locking should come after logging, because closing log results
 	 * in files closing which may require locks being released.
 	 */
-	if (LOCKING_ON(dbenv) &&
-	    (t_ret = __lock_dbenv_refresh(dbenv)) != 0 && ret == 0)
-		ret = t_ret;
+	if (LOCKING_ON(dbenv)) {
+		if (!F_ISSET(dbenv, DB_ENV_THREAD) &&
+		    dbenv->env_lid != DB_LOCK_INVALIDID &&
+		    (t_ret = __lock_id_free(dbenv, dbenv->env_lid)) != 0 &&
+		    ret == 0)
+			ret = t_ret;
+		dbenv->env_lid = DB_LOCK_INVALIDID;
+
+		if ((t_ret = __lock_dbenv_refresh(dbenv)) != 0 && ret == 0)
+			ret = t_ret;
+	}
 
 	/*
 	 * Discard DB list and its mutex.
@@ -601,15 +707,21 @@ __dbenv_refresh(dbenv, orig_flags)
 	 * we close databases and try to acquire the mutex when we close
 	 * log file handles.  Ick.
 	 */
+	if (dbenv->db_ref != 0) {
+		__db_err(dbenv, "Database handles remain at environment close");
+		for (ldbp = LIST_FIRST(&dbenv->dblist);
+		    ldbp != NULL; ldbp = LIST_NEXT(ldbp, dblistlinks))
+			__db_err(dbenv, "Open database handle: %s%s%s",
+			    ldbp->fname, ldbp->dname == NULL ? "" : "/",
+			    ldbp->dname == NULL ? "" : ldbp->dname);
+		if (ret == 0)
+			ret = EINVAL;
+	}
 	LIST_INIT(&dbenv->dblist);
-	if (dbenv->dblist_mutexp != NULL) {
-		dbmp = dbenv->mp_handle;
+	if (dbenv->dblist_mutexp != NULL)
 		__db_mutex_free(dbenv, dbmp->reginfo, dbenv->dblist_mutexp);
-	}
-	if (dbenv->mt_mutexp != NULL) {
-		dbmp = dbenv->mp_handle;
+	if (dbenv->mt_mutexp != NULL)
 		__db_mutex_free(dbenv, dbmp->reginfo, dbenv->mt_mutexp);
-	}
 	if (dbenv->mt != NULL) {
 		__os_free(dbenv, dbenv->mt);
 		dbenv->mt = NULL;
@@ -622,13 +734,33 @@ __dbenv_refresh(dbenv, orig_flags)
 		 * faster and cleaner to flush instead.
 		 */
 		if (F_ISSET(dbenv, DB_ENV_PRIVATE) &&
-		    (t_ret = dbenv->memp_sync(dbenv, NULL)) != 0 && ret == 0)
+		    (t_ret = __memp_sync(dbenv, NULL)) != 0 && ret == 0)
 			ret = t_ret;
 		if ((t_ret = __memp_dbenv_refresh(dbenv)) != 0 && ret == 0)
 			ret = t_ret;
 	}
 
-	/* Detach from the region. */
+	/*
+	 * If we're included in a shared replication handle count, this
+	 * is our last chance to decrement that count.
+	 *
+	 * !!!
+	 * We can't afford to do anything dangerous after we decrement the
+	 * handle count, of course, as replication may be proceeding with
+	 * client recovery.  However, since we're discarding the regions
+	 * as soon as we drop the handle count, there's little opportunity
+	 * to do harm.
+	 */
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+
+	/*
+	 * Detach from the region.
+	 *
+	 * Must come after we call __env_db_rep_exit above.
+	 */
+	__rep_dbenv_refresh(dbenv);
+
 	if (dbenv->reginfo != NULL) {
 		if ((t_ret = __db_e_detach(dbenv, 0)) != 0 && ret == 0)
 			ret = t_ret;
@@ -645,13 +777,9 @@ __dbenv_refresh(dbenv, orig_flags)
 		dbenv->db_home = NULL;
 	}
 
+	dbenv->open_flags = 0;
 	dbenv->db_mode = 0;
 
-	if (dbenv->lockfhp != NULL) {
-		__os_free(dbenv, dbenv->lockfhp);
-		dbenv->lockfhp = NULL;
-	}
-
 	if (dbenv->recover_dtab != NULL) {
 		__os_free(dbenv, dbenv->recover_dtab);
 		dbenv->recover_dtab = NULL;
@@ -664,7 +792,11 @@ __dbenv_refresh(dbenv, orig_flags)
 }
 
 #define	DB_ADDSTR(add) {						\
-	if ((add) != NULL) {						\
+	/*								\
+	 * The string might be NULL or zero-length, and the p[-1]	\
+	 * might indirect to before the beginning of our buffer.	\
+	 */								\
+	if ((add) != NULL && (add)[0] != '\0') {			\
 		/* If leading slash, start over. */			\
 		if (__os_abspath(add)) {				\
 			p = str;					\
@@ -680,6 +812,23 @@ __dbenv_refresh(dbenv, orig_flags)
 	}								\
 }
 
+/*
+ * __dbenv_get_open_flags
+ *	Retrieve the flags passed to DB_ENV->open.
+ *
+ * PUBLIC: int __dbenv_get_open_flags __P((DB_ENV *, u_int32_t *));
+ */
+int
+__dbenv_get_open_flags(dbenv, flagsp)
+	DB_ENV *dbenv;
+	u_int32_t *flagsp;
+{
+	ENV_ILLEGAL_BEFORE_OPEN(dbenv, "DB_ENV->get_open_flags");
+
+	*flagsp = dbenv->open_flags;
+	return (0);
+}
+
 /*
  * __db_appname --
  *	Given an optional DB environment, directory and file name and type
@@ -687,15 +836,15 @@ __dbenv_refresh(dbenv, orig_flags)
  *	it in allocated space.
  *
  * PUBLIC: int __db_appname __P((DB_ENV *, APPNAME,
- * PUBLIC:    const char *, u_int32_t, DB_FH *, char **));
+ * PUBLIC:    const char *, u_int32_t, DB_FH **, char **));
  */
 int
-__db_appname(dbenv, appname, file, tmp_oflags, fhp, namep)
+__db_appname(dbenv, appname, file, tmp_oflags, fhpp, namep)
 	DB_ENV *dbenv;
 	APPNAME appname;
 	const char *file;
 	u_int32_t tmp_oflags;
-	DB_FH *fhp;
+	DB_FH **fhpp;
 	char **namep;
 {
 	size_t len, str_len;
@@ -711,8 +860,8 @@ __db_appname(dbenv, appname, file, tmp_oflags, fhp, namep)
 	 * We don't return a name when creating temporary files, just a file
 	 * handle.  Default to an error now.
 	 */
-	if (fhp != NULL)
-		F_CLR(fhp, DB_FH_VALID);
+	if (fhpp != NULL)
+		*fhpp = NULL;
 	if (namep != NULL)
 		*namep = NULL;
 
@@ -768,7 +917,7 @@ retry:	/*
 	 * temporary space that we're going to need to create a temporary file
 	 * name.
 	 */
-#define	DB_TRAIL	"BDBXXXXXX"
+#define	DB_TRAIL	"BDBXXXXX"
 	str_len = len + sizeof(DB_TRAIL) + 10;
 	if ((ret = __os_malloc(dbenv, str_len, &str)) != 0)
 		return (ret);
@@ -792,7 +941,7 @@ retry:	/*
 
 	/* Create the file if so requested. */
 	if (tmp_create &&
-	    (ret = __db_tmp_open(dbenv, tmp_oflags, str, fhp)) != 0) {
+	    (ret = __db_tmp_open(dbenv, tmp_oflags, str, fhpp)) != 0) {
 		__os_free(dbenv, str);
 		return (ret);
 	}
@@ -857,10 +1006,12 @@ __db_parse(dbenv, s)
 
 	/*
 	 * !!!
-	 * The value of 40 is hard-coded into format arguments to sscanf
+	 * The constant 40 is hard-coded into format arguments to sscanf
 	 * below, it can't be changed here without changing it there, too.
+	 * The additional bytes are for a trailing nul byte and because we
+	 * are reading user input -- I don't want to risk any off-by-ones.
 	 */
-	char arg[40];
+	char arg[40 + 5];
 
 	/*
 	 * Name/value pairs are parsed as two white-space separated strings.
@@ -894,71 +1045,88 @@ illegal:	__db_err(dbenv, "mis-formatted name-value pair: %s", s);
 	if (!strcasecmp(name, "set_cachesize")) {
 		if (sscanf(value, "%lu %lu %lu %c", &v1, &v2, &v3, &v4) != 3)
 			goto badarg;
-		__DB_OVFL(v1, UINT32_T_MAX);
-		__DB_OVFL(v2, UINT32_T_MAX);
+		__DB_OVFL(v1, UINT32_MAX);
+		__DB_OVFL(v2, UINT32_MAX);
 		__DB_OVFL(v3, 10000);
-		return (dbenv->set_cachesize(
+		return (__memp_set_cachesize(
 		    dbenv, (u_int32_t)v1, (u_int32_t)v2, (int)v3));
 	}
 
 	if (!strcasecmp(name, "set_data_dir") ||
 	    !strcasecmp(name, "db_data_dir"))		/* Compatibility. */
-		return (dbenv->set_data_dir(dbenv, value));
+		return (__dbenv_set_data_dir(dbenv, value));
+
+	if (!strcasecmp(name, "set_intermediate_dir")) {/* Undocumented. */
+		if (sscanf(value, "%lu %c", &v1, &v4) != 1)
+			goto badarg;
+#ifdef INT_MAX
+		__DB_OVFL(v1, INT_MAX);
+#endif
+		return (__dbenv_set_intermediate_dir(dbenv, (int)v1, 0));
+	}
 
 	if (!strcasecmp(name, "set_flags")) {
 		if (sscanf(value, "%40s %c", arg, &v4) != 1)
 			goto badarg;
 
+		if (!strcasecmp(value, "db_auto_commit"))
+			return (__dbenv_set_flags(dbenv, DB_AUTO_COMMIT, 1));
 		if (!strcasecmp(value, "db_cdb_alldb"))
-			return (dbenv->set_flags(dbenv, DB_CDB_ALLDB, 1));
+			return (__dbenv_set_flags(dbenv, DB_CDB_ALLDB, 1));
 		if (!strcasecmp(value, "db_direct_db"))
-			return (dbenv->set_flags(dbenv, DB_DIRECT_DB, 1));
+			return (__dbenv_set_flags(dbenv, DB_DIRECT_DB, 1));
 		if (!strcasecmp(value, "db_direct_log"))
-			return (dbenv->set_flags(dbenv, DB_DIRECT_LOG, 1));
+			return (__dbenv_set_flags(dbenv, DB_DIRECT_LOG, 1));
+		if (!strcasecmp(value, "db_dsync_log"))
+			return (__dbenv_set_flags(dbenv, DB_DSYNC_LOG, 1));
+		if (!strcasecmp(value, "db_log_autoremove"))
+			return (__dbenv_set_flags(dbenv, DB_LOG_AUTOREMOVE, 1));
+		if (!strcasecmp(value, "db_log_inmemory"))
+			return (__dbenv_set_flags(dbenv, DB_LOG_INMEMORY, 1));
 		if (!strcasecmp(value, "db_nolocking"))
-			return (dbenv->set_flags(dbenv, DB_NOLOCKING, 1));
+			return (__dbenv_set_flags(dbenv, DB_NOLOCKING, 1));
 		if (!strcasecmp(value, "db_nommap"))
-			return (dbenv->set_flags(dbenv, DB_NOMMAP, 1));
-		if (!strcasecmp(value, "db_overwrite"))
-			return (dbenv->set_flags(dbenv, DB_OVERWRITE, 1));
+			return (__dbenv_set_flags(dbenv, DB_NOMMAP, 1));
 		if (!strcasecmp(value, "db_nopanic"))
-			return (dbenv->set_flags(dbenv, DB_NOPANIC, 1));
+			return (__dbenv_set_flags(dbenv, DB_NOPANIC, 1));
+		if (!strcasecmp(value, "db_overwrite"))
+			return (__dbenv_set_flags(dbenv, DB_OVERWRITE, 1));
 		if (!strcasecmp(value, "db_region_init"))
-			return (dbenv->set_flags(dbenv, DB_REGION_INIT, 1));
+			return (__dbenv_set_flags(dbenv, DB_REGION_INIT, 1));
 		if (!strcasecmp(value, "db_txn_nosync"))
-			return (dbenv->set_flags(dbenv, DB_TXN_NOSYNC, 1));
+			return (__dbenv_set_flags(dbenv, DB_TXN_NOSYNC, 1));
 		if (!strcasecmp(value, "db_txn_write_nosync"))
 			return (
-			    dbenv->set_flags(dbenv, DB_TXN_WRITE_NOSYNC, 1));
+			    __dbenv_set_flags(dbenv, DB_TXN_WRITE_NOSYNC, 1));
 		if (!strcasecmp(value, "db_yieldcpu"))
-			return (dbenv->set_flags(dbenv, DB_YIELDCPU, 1));
+			return (__dbenv_set_flags(dbenv, DB_YIELDCPU, 1));
 		goto badarg;
 	}
 
 	if (!strcasecmp(name, "set_lg_bsize")) {
 		if (sscanf(value, "%lu %c", &v1, &v4) != 1)
 			goto badarg;
-		__DB_OVFL(v1, UINT32_T_MAX);
-		return (dbenv->set_lg_bsize(dbenv, (u_int32_t)v1));
+		__DB_OVFL(v1, UINT32_MAX);
+		return (__log_set_lg_bsize(dbenv, (u_int32_t)v1));
 	}
 
 	if (!strcasecmp(name, "set_lg_max")) {
 		if (sscanf(value, "%lu %c", &v1, &v4) != 1)
 			goto badarg;
-		__DB_OVFL(v1, UINT32_T_MAX);
-		return (dbenv->set_lg_max(dbenv, (u_int32_t)v1));
+		__DB_OVFL(v1, UINT32_MAX);
+		return (__log_set_lg_max(dbenv, (u_int32_t)v1));
 	}
 
 	if (!strcasecmp(name, "set_lg_regionmax")) {
 		if (sscanf(value, "%lu %c", &v1, &v4) != 1)
 			goto badarg;
-		__DB_OVFL(v1, UINT32_T_MAX);
-		return (dbenv->set_lg_regionmax(dbenv, (u_int32_t)v1));
+		__DB_OVFL(v1, UINT32_MAX);
+		return (__log_set_lg_regionmax(dbenv, (u_int32_t)v1));
 	}
 
 	if (!strcasecmp(name, "set_lg_dir") ||
 	    !strcasecmp(name, "db_log_dir"))		/* Compatibility. */
-		return (dbenv->set_lg_dir(dbenv, value));
+		return (__log_set_lg_dir(dbenv, value));
 
 	if (!strcasecmp(name, "set_lk_detect")) {
 		if (sscanf(value, "%40s %c", arg, &v4) != 1)
@@ -969,6 +1137,8 @@ illegal:	__db_err(dbenv, "mis-formatted name-value pair: %s", s);
 			flags = DB_LOCK_EXPIRE;
 		else if (!strcasecmp(value, "db_lock_maxlocks"))
 			flags = DB_LOCK_MAXLOCKS;
+		else if (!strcasecmp(value, "db_lock_maxwrite"))
+			flags = DB_LOCK_MAXWRITE;
 		else if (!strcasecmp(value, "db_lock_minlocks"))
 			flags = DB_LOCK_MINLOCKS;
 		else if (!strcasecmp(value, "db_lock_minwrite"))
@@ -981,88 +1151,103 @@ illegal:	__db_err(dbenv, "mis-formatted name-value pair: %s", s);
 			flags = DB_LOCK_YOUNGEST;
 		else
 			goto badarg;
-		return (dbenv->set_lk_detect(dbenv, flags));
+		return (__lock_set_lk_detect(dbenv, flags));
 	}
 
 	if (!strcasecmp(name, "set_lk_max")) {
 		if (sscanf(value, "%lu %c", &v1, &v4) != 1)
 			goto badarg;
-		__DB_OVFL(v1, UINT32_T_MAX);
-		return (dbenv->set_lk_max(dbenv, (u_int32_t)v1));
+		__DB_OVFL(v1, UINT32_MAX);
+		return (__lock_set_lk_max(dbenv, (u_int32_t)v1));
 	}
 
 	if (!strcasecmp(name, "set_lk_max_locks")) {
 		if (sscanf(value, "%lu %c", &v1, &v4) != 1)
 			goto badarg;
-		__DB_OVFL(v1, UINT32_T_MAX);
-		return (dbenv->set_lk_max_locks(dbenv, (u_int32_t)v1));
+		__DB_OVFL(v1, UINT32_MAX);
+		return (__lock_set_lk_max_locks(dbenv, (u_int32_t)v1));
 	}
 
 	if (!strcasecmp(name, "set_lk_max_lockers")) {
 		if (sscanf(value, "%lu %c", &v1, &v4) != 1)
 			goto badarg;
-		__DB_OVFL(v1, UINT32_T_MAX);
-		return (dbenv->set_lk_max_lockers(dbenv, (u_int32_t)v1));
+		__DB_OVFL(v1, UINT32_MAX);
+		return (__lock_set_lk_max_lockers(dbenv, (u_int32_t)v1));
 	}
 
 	if (!strcasecmp(name, "set_lk_max_objects")) {
 		if (sscanf(value, "%lu %c", &v1, &v4) != 1)
 			goto badarg;
-		__DB_OVFL(v1, UINT32_T_MAX);
-		return (dbenv->set_lk_max_objects(dbenv, (u_int32_t)v1));
+		__DB_OVFL(v1, UINT32_MAX);
+		return (__lock_set_lk_max_objects(dbenv, (u_int32_t)v1));
 	}
 
 	if (!strcasecmp(name, "set_lock_timeout")) {
 		if (sscanf(value, "%lu %c", &v1, &v4) != 1)
 			goto badarg;
-		__DB_OVFL(v1, UINT32_T_MAX);
-		return (dbenv->set_timeout(
+		__DB_OVFL(v1, UINT32_MAX);
+		return (__lock_set_env_timeout(
 		    dbenv, (u_int32_t)v1, DB_SET_LOCK_TIMEOUT));
 	}
 
+	if (!strcasecmp(name, "set_mp_max_openfd")) {
+		if (sscanf(value, "%lu %c", &v1, &v4) != 1)
+			goto badarg;
+		__DB_OVFL(v1, INT_MAX);
+		return (__memp_set_mp_max_openfd(dbenv, (int)v1));
+	}
+
+	if (!strcasecmp(name, "set_mp_max_write")) {
+		if (sscanf(value, "%lu %lu %c", &v1, &v2, &v4) != 2)
+			goto badarg;
+		__DB_OVFL(v1, INT_MAX);
+		__DB_OVFL(v2, INT_MAX);
+		return (__memp_set_mp_max_write(dbenv, (int)v1, (int)v2));
+	}
+
 	if (!strcasecmp(name, "set_mp_mmapsize")) {
 		if (sscanf(value, "%lu %c", &v1, &v4) != 1)
 			goto badarg;
-		__DB_OVFL(v1, UINT32_T_MAX);
-		return (dbenv->set_mp_mmapsize(dbenv, (u_int32_t)v1));
+		__DB_OVFL(v1, UINT32_MAX);
+		return (__memp_set_mp_mmapsize(dbenv, (u_int32_t)v1));
 	}
 
 	if (!strcasecmp(name, "set_region_init")) {
 		if (sscanf(value, "%lu %c", &v1, &v4) != 1 || v1 != 1)
 			goto badarg;
-		return (dbenv->set_flags(
+		return (__dbenv_set_flags(
 		    dbenv, DB_REGION_INIT, v1 == 0 ? 0 : 1));
 	}
 
 	if (!strcasecmp(name, "set_shm_key")) {
 		if (sscanf(value, "%lu %c", &v1, &v4) != 1)
 			goto badarg;
-		return (dbenv->set_shm_key(dbenv, (long)v1));
+		return (__dbenv_set_shm_key(dbenv, (long)v1));
 	}
 
 	if (!strcasecmp(name, "set_tas_spins")) {
 		if (sscanf(value, "%lu %c", &v1, &v4) != 1)
 			goto badarg;
-		__DB_OVFL(v1, UINT32_T_MAX);
-		return (dbenv->set_tas_spins(dbenv, (u_int32_t)v1));
+		__DB_OVFL(v1, UINT32_MAX);
+		return (__dbenv_set_tas_spins(dbenv, (u_int32_t)v1));
 	}
 
 	if (!strcasecmp(name, "set_tmp_dir") ||
 	    !strcasecmp(name, "db_tmp_dir"))		/* Compatibility.*/
-		return (dbenv->set_tmp_dir(dbenv, value));
+		return (__dbenv_set_tmp_dir(dbenv, value));
 
 	if (!strcasecmp(name, "set_tx_max")) {
 		if (sscanf(value, "%lu %c", &v1, &v4) != 1)
 			goto badarg;
-		__DB_OVFL(v1, UINT32_T_MAX);
-		return (dbenv->set_tx_max(dbenv, (u_int32_t)v1));
+		__DB_OVFL(v1, UINT32_MAX);
+		return (__txn_set_tx_max(dbenv, (u_int32_t)v1));
 	}
 
 	if (!strcasecmp(name, "set_txn_timeout")) {
 		if (sscanf(value, "%lu %c", &v1, &v4) != 1)
 			goto badarg;
-		__DB_OVFL(v1, UINT32_T_MAX);
-		return (dbenv->set_timeout(
+		__DB_OVFL(v1, UINT32_MAX);
+		return (__lock_set_env_timeout(
 		    dbenv, (u_int32_t)v1, DB_SET_TXN_TIMEOUT));
 	}
 
@@ -1070,17 +1255,17 @@ illegal:	__db_err(dbenv, "mis-formatted name-value pair: %s", s);
 		if (sscanf(value, "%40s %c", arg, &v4) != 1)
 			goto badarg;
 
-		if (!strcasecmp(value, "db_verb_chkpoint"))
-			flags = DB_VERB_CHKPOINT;
 		else if (!strcasecmp(value, "db_verb_deadlock"))
 			flags = DB_VERB_DEADLOCK;
 		else if (!strcasecmp(value, "db_verb_recovery"))
 			flags = DB_VERB_RECOVERY;
+		else if (!strcasecmp(value, "db_verb_replication"))
+			flags = DB_VERB_REPLICATION;
 		else if (!strcasecmp(value, "db_verb_waitsfor"))
 			flags = DB_VERB_WAITSFOR;
 		else
 			goto badarg;
-		return (dbenv->set_verbose(dbenv, flags, 1));
+		return (__dbenv_set_verbose(dbenv, flags, 1));
 	}
 
 	__db_err(dbenv, "unrecognized name-value pair: %s", s);
@@ -1099,16 +1284,15 @@ toobig:	__db_err(dbenv,
  *	Create a temporary file.
  */
 static int
-__db_tmp_open(dbenv, tmp_oflags, path, fhp)
+__db_tmp_open(dbenv, tmp_oflags, path, fhpp)
 	DB_ENV *dbenv;
 	u_int32_t tmp_oflags;
 	char *path;
-	DB_FH *fhp;
+	DB_FH **fhpp;
 {
 	u_int32_t id;
-	int mode, isdir, ret;
-	const char *p;
-	char *trv;
+	int filenum, i, isdir, ret;
+	char *firstx, *trv;
 
 	/*
 	 * Check the target directory; if you have six X's and it doesn't
@@ -1124,36 +1308,19 @@ __db_tmp_open(dbenv, tmp_oflags, path, fhp)
 	}
 
 	/* Build the path. */
-	for (trv = path; *trv != '\0'; ++trv)
-		;
-	*trv = PATH_SEPARATOR[0];
-	for (p = DB_TRAIL; (*++trv = *p) != '\0'; ++p)
-		;
+	(void)strncat(path, PATH_SEPARATOR, 1);
+	(void)strcat(path, DB_TRAIL);
 
-	/* Replace the X's with the process ID. */
-	for (__os_id(&id); *--trv == 'X'; id /= 10)
-		switch (id % 10) {
-		case 0: *trv = '0'; break;
-		case 1: *trv = '1'; break;
-		case 2: *trv = '2'; break;
-		case 3: *trv = '3'; break;
-		case 4: *trv = '4'; break;
-		case 5: *trv = '5'; break;
-		case 6: *trv = '6'; break;
-		case 7: *trv = '7'; break;
-		case 8: *trv = '8'; break;
-		case 9: *trv = '9'; break;
-		}
-	++trv;
-
-	/* Set up open flags and mode. */
-	mode = __db_omode("rw----");
+	/* Replace the X's with the process ID (in decimal). */
+	for (trv = path + strlen(path), __os_id(&id); *--trv == 'X'; id /= 10)
+		*trv = '0' + (id % 10);
+	firstx = trv + 1;
 
 	/* Loop, trying to open a file. */
-	for (;;) {
+	for (filenum = 1;; filenum++) {
 		if ((ret = __os_open(dbenv, path,
 		    tmp_oflags | DB_OSO_CREATE | DB_OSO_EXCL | DB_OSO_TEMP,
-		    mode, fhp)) == 0)
+		    __db_omode("rw----"), fhpp)) == 0)
 			return (0);
 
 		/*
@@ -1170,22 +1337,26 @@ __db_tmp_open(dbenv, tmp_oflags, path, fhp)
 		}
 
 		/*
-		 * Tricky little algorithm for backward compatibility.
-		 * Assumes sequential ordering of lower-case characters.
+		 * Generate temporary file names in a backwards-compatible way.
+		 * If id == 12345, the result is:
+		 *   <path>/DB12345 (tried above, the first time through).
+		 *   <path>/DBa2345 ...  <path>/DBz2345
+		 *   <path>/DBaa345 ...  <path>/DBaz345
+		 *   <path>/DBba345, and so on.
+		 *
+		 * XXX
+		 * This algorithm is O(n**2) -- that is, creating 100 temporary
+		 * files requires 5,000 opens, creating 1000 files requires
+		 * 500,000.  If applications open a lot of temporary files, we
+		 * could improve performance by switching to timestamp-based
+		 * file names.
 		 */
-		for (;;) {
-			if (*trv == '\0')
+		for (i = filenum, trv = firstx; i > 0; i = (i - 1) / 26)
+			if (*trv++ == '\0')
 				return (EINVAL);
-			if (*trv == 'z')
-				*trv++ = 'a';
-			else {
-				if (isdigit((int)*trv))
-					*trv = 'a';
-				else
-					++*trv;
-				break;
-			}
-		}
+
+		for (i = filenum; i > 0; i = (i - 1) / 26)
+			*--trv = 'a' + ((i - 1) % 26);
 	}
 	/* NOTREACHED */
 }
diff --git a/storage/bdb/env/env_recover.c b/storage/bdb/env/env_recover.c
index fbe3b345b0d62c2706c10968fc01940f73d82d89..1c018171f4eafd141e741354b3c66b09b52ae4b5 100644
--- a/storage/bdb/env/env_recover.c
+++ b/storage/bdb/env/env_recover.c
@@ -1,17 +1,17 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: env_recover.c,v 11.126 2004/09/22 03:43:52 bostic Exp $
  */
 
 #include "db_config.h"
 
 #ifndef lint
 static const char copyright[] =
-    "Copyright (c) 1996-2002\nSleepycat Software Inc.  All rights reserved.\n";
-static const char revid[] =
-    "$Id: env_recover.c,v 11.97 2002/08/22 17:43:22 margo Exp $";
+    "Copyright (c) 1996-2004\nSleepycat Software Inc.  All rights reserved.\n";
 #endif
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -34,13 +34,12 @@ static const char revid[] =
 #include "db_int.h"
 #include "dbinc/db_page.h"
 #include "dbinc/db_shash.h"
-#include "dbinc/lock.h"
 #include "dbinc/log.h"
-#include "dbinc/rep.h"
 #include "dbinc/txn.h"
+#include "dbinc/mp.h"
 #include "dbinc/db_am.h"
 
-static int    __log_backup __P((DB_ENV *, DB_LOGC *, DB_LSN *, DB_LSN *));
+static int    __db_log_corrupt __P((DB_ENV *, DB_LSN *));
 static int    __log_earliest __P((DB_ENV *, DB_LOGC *, int32_t *, DB_LSN *));
 static double __lsn_diff __P((DB_LSN *, DB_LSN *, DB_LSN *, u_int32_t, int));
 
@@ -51,26 +50,28 @@ static double __lsn_diff __P((DB_LSN *, DB_LSN *, DB_LSN *, u_int32_t, int));
  * LSN of max_lsn, so we need to roll back sufficiently far for that
  * to work.  See __log_backup for details.
  *
- * PUBLIC: int __db_apprec __P((DB_ENV *, DB_LSN *, u_int32_t));
+ * PUBLIC: int __db_apprec __P((DB_ENV *, DB_LSN *, DB_LSN *, int, u_int32_t));
  */
 int
-__db_apprec(dbenv, max_lsn, flags)
+__db_apprec(dbenv, max_lsn, trunclsn, update, flags)
 	DB_ENV *dbenv;
-	DB_LSN *max_lsn;
+	DB_LSN *max_lsn, *trunclsn;
+	int update;
 	u_int32_t flags;
 {
 	DBT data;
 	DB_LOGC *logc;
-	DB_LSN ckp_lsn, first_lsn, last_lsn, lowlsn, lsn, stop_lsn;
+	DB_LSN ckp_lsn, first_lsn, last_lsn, lowlsn, lsn, stop_lsn, tlsn;
 	DB_TXNREGION *region;
+	REGENV *renv;
+	REGINFO *infop;
 	__txn_ckp_args *ckp_args;
 	time_t now, tlow;
-	int32_t log_size, low;
 	double nfiles;
-	int have_rec, is_thread, progress, ret, t_ret;
+	u_int32_t hi_txn, log_size, txnid;
+	int32_t low;
+	int have_rec, progress, ret, t_ret;
 	int (**dtab) __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-	size_t dtabsize;
-	u_int32_t hi_txn, lockid, txnid;
 	char *p, *pass, t1[60], t2[60];
 	void *txninfo;
 
@@ -80,7 +81,6 @@ __db_apprec(dbenv, max_lsn, flags)
 	ckp_args = NULL;
 	dtab = NULL;
 	hi_txn = TXN_MAXIMUM;
-	lockid = DB_LOCK_INVALIDID;
 	txninfo = NULL;
 	pass = "initial";
 
@@ -93,11 +93,13 @@ __db_apprec(dbenv, max_lsn, flags)
 	   ((LOG *)(((DB_LOG *)dbenv->lg_handle)->reginfo.primary))->log_size;
 
 	/*
-	 * Save the state of the thread flag -- we don't need it on at the
-	 * moment because we're single-threaded until recovery is complete.
+	 * If we need to, update the env handle timestamp.
 	 */
-	is_thread = F_ISSET(dbenv, DB_ENV_THREAD) ? 1 : 0;
-	F_CLR(dbenv, DB_ENV_THREAD);
+	if (update) {
+		infop = dbenv->reginfo;
+		renv = infop->primary;
+		(void)time(&renv->rep_timestamp);
+	}
 
 	/* Set in-recovery flags. */
 	F_SET((DB_LOG *)dbenv->lg_handle, DBLOG_RECOVER);
@@ -105,7 +107,7 @@ __db_apprec(dbenv, max_lsn, flags)
 	F_SET(region, TXN_IN_RECOVERY);
 
 	/* Allocate a cursor for the log. */
-	if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+	if ((ret = __log_cursor(dbenv, &logc)) != 0)
 		goto err;
 
 	/*
@@ -114,7 +116,8 @@ __db_apprec(dbenv, max_lsn, flags)
 	 */
 	ZERO_LSN(lowlsn);
 	if (max_lsn != NULL) {
-		if ((ret = __log_backup(dbenv, logc, max_lsn, &lowlsn)) != 0)
+		if ((ret = __log_backup(dbenv, logc, max_lsn, &lowlsn,
+		    CKPLSN_CMP)) != 0)
 			goto err;
 	} else if (dbenv->tx_timestamp != 0) {
 		if ((ret = __log_earliest(dbenv, logc, &low, &lowlsn)) != 0)
@@ -175,12 +178,12 @@ __db_apprec(dbenv, max_lsn, flags)
 	 *		we have to roll back to the checkpoint whose ckp_lsn
 	 *		is earlier than the max_lsn.  __log_backup will figure
 	 *		that out for us.
-	 *	In case 2, "uncompleted TXNs" include all those who commited
+	 *	In case 2, "uncompleted TXNs" include all those who committed
 	 *	after the user's specified timestamp.
 	 *
 	 * Pass #3:
 	 *	Read forward through the log from the LSN found in pass #2,
-	 *	redoing any committed TXNs (which commited after any user-
+	 *	redoing any committed TXNs (which committed after any user-
 	 *	specified rollback point).  During this pass, checkpoint
 	 *	file information is ignored, and file openings and closings
 	 *	are redone.
@@ -209,7 +212,7 @@ __db_apprec(dbenv, max_lsn, flags)
 	ZERO_LSN(last_lsn);
 #endif
 	memset(&data, 0, sizeof(data));
-	if ((ret = logc->get(logc, &last_lsn, &data, DB_LAST)) != 0) {
+	if ((ret = __log_c_get(logc, &last_lsn, &data, DB_LAST)) != 0) {
 		if (ret == DB_NOTFOUND)
 			ret = 0;
 		else
@@ -224,7 +227,7 @@ __db_apprec(dbenv, max_lsn, flags)
 
 		if (txnid != 0)
 			break;
-	} while ((ret = logc->get(logc, &lsn, &data, DB_PREV)) == 0);
+	} while ((ret = __log_c_get(logc, &lsn, &data, DB_PREV)) == 0);
 
 	/*
 	 * There are no transactions, so there is nothing to do unless
@@ -232,12 +235,9 @@ __db_apprec(dbenv, max_lsn, flags)
 	 * we'll still need to do a vtruncate based on information we haven't
 	 * yet collected.
 	 */
-	if (ret == DB_NOTFOUND) {
+	if (ret == DB_NOTFOUND)
 		ret = 0;
-		if (max_lsn == NULL)
-			goto done;
-	}
-	if (ret != 0)
+	else if (ret != 0)
 		goto err;
 
 	hi_txn = txnid;
@@ -257,7 +257,7 @@ __db_apprec(dbenv, max_lsn, flags)
 	 * Get the first LSN in the log; it's an initial default
 	 * even if this is not a catastrophic recovery.
 	 */
-	if ((ret = logc->get(logc, &ckp_lsn, &data, DB_FIRST)) != 0) {
+	if ((ret = __log_c_get(logc, &ckp_lsn, &data, DB_FIRST)) != 0) {
 		if (ret == DB_NOTFOUND)
 			ret = 0;
 		else
@@ -269,7 +269,7 @@ __db_apprec(dbenv, max_lsn, flags)
 
 	if (!LF_ISSET(DB_RECOVER_FATAL)) {
 		if ((ret = __txn_getckp(dbenv, &ckp_lsn)) == 0 &&
-		    (ret = logc->get(logc, &ckp_lsn, &data, DB_SET)) == 0) {
+		    (ret = __log_c_get(logc, &ckp_lsn, &data, DB_SET)) == 0) {
 			/* We have a recent checkpoint.  This is LSN (1). */
 			if ((ret = __txn_ckp_read(dbenv,
 			    data.data, &ckp_args)) != 0) {
@@ -280,6 +280,7 @@ __db_apprec(dbenv, max_lsn, flags)
 				goto err;
 			}
 			first_lsn = ckp_args->ckp_lsn;
+			__os_free(dbenv, ckp_args);
 			have_rec = 0;
 		}
 
@@ -310,7 +311,7 @@ __db_apprec(dbenv, max_lsn, flags)
 
 	/* Get the record at first_lsn if we don't have it already. */
 	if (!have_rec &&
-	    (ret = logc->get(logc, &first_lsn, &data, DB_SET)) != 0) {
+	    (ret = __log_c_get(logc, &first_lsn, &data, DB_SET)) != 0) {
 		__db_err(dbenv, "Checkpoint LSN record [%ld][%ld] not found",
 		    (u_long)first_lsn.file, (u_long)first_lsn.offset);
 		goto err;
@@ -322,7 +323,7 @@ __db_apprec(dbenv, max_lsn, flags)
 			    (last_lsn.offset - first_lsn.offset) / log_size;
 		else
 			nfiles = (double)(last_lsn.file - first_lsn.file) +
-			    (double)(log_size - first_lsn.offset +
+			    (double)((log_size - first_lsn.offset) +
 			    last_lsn.offset) / log_size;
 		/* We are going to divide by nfiles; make sure it isn't 0. */
 		if (nfiles == 0)
@@ -331,27 +332,29 @@ __db_apprec(dbenv, max_lsn, flags)
 
 	/* Find a low txnid. */
 	ret = 0;
-	do {
+	if (hi_txn != 0) do {
 		/* txnid is after rectype, which is a u_int32. */
 		memcpy(&txnid,
 		    (u_int8_t *)data.data + sizeof(u_int32_t), sizeof(txnid));
 
 		if (txnid != 0)
 			break;
-	} while ((ret = logc->get(logc, &lsn, &data, DB_NEXT)) == 0);
+	} while ((ret = __log_c_get(logc, &lsn, &data, DB_NEXT)) == 0);
 
 	/*
 	 * There are no transactions and we're not recovering to an LSN (see
 	 * above), so there is nothing to do.
 	 */
 	if (ret == DB_NOTFOUND) {
-		ret = 0;
-		if (max_lsn == NULL)
-			goto done;
+		if (log_compare(&lsn, &last_lsn) != 0)
+			ret = __db_log_corrupt(dbenv, &lsn);
+		else
+			ret = 0;
 	}
 
 	/* Reset to the first lsn. */
-	if (ret != 0 || (ret = logc->get(logc, &first_lsn, &data, DB_SET)) != 0)
+	if (ret != 0 ||
+	    (ret = __log_c_get(logc, &first_lsn, &data, DB_SET)) != 0)
 		goto err;
 
 	/* Initialize the transaction list. */
@@ -367,6 +370,10 @@ __db_apprec(dbenv, max_lsn, flags)
 	    txninfo, &data, &first_lsn, &last_lsn, nfiles, 1)) != 0)
 		goto err;
 
+	/* If there were no transactions, then we can bail out early. */
+	if (hi_txn == 0 && max_lsn == NULL)
+		goto done;
+
 	/*
 	 * Pass #2.
 	 *
@@ -375,35 +382,21 @@ __db_apprec(dbenv, max_lsn, flags)
 	 */
 
 	if (FLD_ISSET(dbenv->verbose, DB_VERB_RECOVERY))
-		__db_err(dbenv, "Recovery starting from [%lu][%lu]",
+		__db_msg(dbenv, "Recovery starting from [%lu][%lu]",
 		    (u_long)first_lsn.file, (u_long)first_lsn.offset);
 
-	/*
-	 * If we are doing client recovery, then we need to allocate
-	 * the page-info lock table.
-	 */
-	if (max_lsn != NULL) {
-		if ((ret = __rep_lockpgno_init(dbenv, &dtab, &dtabsize)) != 0)
-			goto err;
-		if ((ret = dbenv->lock_id(dbenv, &lockid)) != 0)
-			goto err;
-	}
-
 	pass = "backward";
-	for (ret = logc->get(logc, &lsn, &data, DB_LAST);
+	for (ret = __log_c_get(logc, &lsn, &data, DB_LAST);
 	    ret == 0 && log_compare(&lsn, &first_lsn) >= 0;
-	    ret = logc->get(logc, &lsn, &data, DB_PREV)) {
+	    ret = __log_c_get(logc, &lsn, &data, DB_PREV)) {
 		if (dbenv->db_feedback != NULL) {
 			progress = 34 + (int)(33 * (__lsn_diff(&first_lsn,
 			    &last_lsn, &lsn, log_size, 0) / nfiles));
 			dbenv->db_feedback(dbenv, DB_RECOVER, progress);
 		}
-		if (max_lsn != NULL && (ret = __rep_lockpages(dbenv,
-		    dtab, dtabsize, &lsn, NULL, NULL, lockid)) != 0)
-			continue;
-
+		tlsn = lsn;
 		ret = __db_dispatch(dbenv, dbenv->recover_dtab,
-		    dbenv->recover_dtab_size, &data, &lsn,
+		    dbenv->recover_dtab_size, &data, &tlsn,
 		    DB_TXN_BACKWARD_ROLL, txninfo);
 		if (ret != 0) {
 			if (ret != DB_TXN_CKP)
@@ -412,7 +405,13 @@ __db_apprec(dbenv, max_lsn, flags)
 				ret = 0;
 		}
 	}
-	if (ret != 0 && ret != DB_NOTFOUND)
+	if (ret == DB_NOTFOUND) {
+		if (log_compare(&lsn, &first_lsn) > 0)
+			ret = __db_log_corrupt(dbenv, &lsn);
+		else
+			ret = 0;
+	}
+	if (ret != 0)
 		goto err;
 
 	/*
@@ -430,23 +429,16 @@ __db_apprec(dbenv, max_lsn, flags)
 	if (max_lsn != NULL || dbenv->tx_timestamp != 0)
 		stop_lsn = ((DB_TXNHEAD *)txninfo)->maxlsn;
 
-	for (ret = logc->get(logc, &lsn, &data, DB_NEXT);
-	    ret == 0; ret = logc->get(logc, &lsn, &data, DB_NEXT)) {
-		/*
-		 * If we are recovering to a timestamp or an LSN,
-		 * we need to make sure that we don't try to roll
-		 * forward beyond the soon-to-be end of log.
-		 */
-		if (log_compare(&lsn, &stop_lsn) > 0)
-			break;
-
+	for (ret = __log_c_get(logc, &lsn, &data, DB_NEXT);
+	    ret == 0; ret = __log_c_get(logc, &lsn, &data, DB_NEXT)) {
 		if (dbenv->db_feedback != NULL) {
 			progress = 67 + (int)(33 * (__lsn_diff(&first_lsn,
 			    &last_lsn, &lsn, log_size, 1) / nfiles));
 			dbenv->db_feedback(dbenv, DB_RECOVER, progress);
 		}
+		tlsn = lsn;
 		ret = __db_dispatch(dbenv, dbenv->recover_dtab,
-		    dbenv->recover_dtab_size, &data, &lsn,
+		    dbenv->recover_dtab_size, &data, &tlsn,
 		    DB_TXN_FORWARD_ROLL, txninfo);
 		if (ret != 0) {
 			if (ret != DB_TXN_CKP)
@@ -454,43 +446,83 @@ __db_apprec(dbenv, max_lsn, flags)
 			else
 				ret = 0;
 		}
+		/*
+		 * If we are recovering to a timestamp or an LSN,
+		 * we need to make sure that we don't try to roll
+		 * forward beyond the soon-to-be end of log.
+		 */
+		if (log_compare(&lsn, &stop_lsn) >= 0)
+			break;
 
 	}
-	if (ret != 0 && ret != DB_NOTFOUND)
+	if (ret == DB_NOTFOUND)
+		ret = __db_log_corrupt(dbenv, &lsn);
+	if (ret != 0)
 		goto err;
 
+#ifndef HAVE_FTRUNCATE
 	/*
 	 * Process any pages that were on the limbo list and move them to
 	 * the free list.  Do this before checkpointing the database.
 	 */
-	 if ((ret = __db_do_the_limbo(dbenv, NULL, NULL, txninfo)) != 0)
+	if ((ret = __db_do_the_limbo(dbenv, NULL, NULL, txninfo,
+	      dbenv->tx_timestamp != 0 ? LIMBO_TIMESTAMP : LIMBO_RECOVER)) != 0)
 		goto err;
+#endif
 
 	if (max_lsn == NULL)
 		region->last_txnid = ((DB_TXNHEAD *)txninfo)->maxid;
 
-	/* Take a checkpoint here to force any dirty data pages to disk. */
 	if (dbenv->tx_timestamp != 0) {
+		/* We are going to truncate, so we'd best close the cursor. */
+		if (logc != NULL && (ret = __log_c_close(logc)) != 0)
+			goto err;
+		logc = NULL;
+		/* Flush everything to disk, we are losing the log. */
+		if ((ret = __memp_sync(dbenv, NULL)) != 0)
+			goto err;
 		region->last_ckp = ((DB_TXNHEAD *)txninfo)->ckplsn;
-		__log_vtruncate(dbenv, &((DB_TXNHEAD *)txninfo)->maxlsn,
-		    &((DB_TXNHEAD *)txninfo)->ckplsn);
+		if ((ret = __log_vtruncate(dbenv,
+		    &((DB_TXNHEAD *)txninfo)->maxlsn,
+		    &((DB_TXNHEAD *)txninfo)->ckplsn, trunclsn)) != 0)
+			goto err;
+
+#ifndef HAVE_FTRUNCATE
+		/*
+		 * Generate logging compensation records.
+		 * If we crash during/after vtruncate we may have
+		 * pages missing from the free list since they
+		 * if we roll things further back from here.
+		 * These pages are only known in memory at this pont.
+		 */
+		 if ((ret = __db_do_the_limbo(dbenv,
+		       NULL, NULL, txninfo, LIMBO_COMPENSATE)) != 0)
+			goto err;
+#endif
 	}
 
-	if ((ret = dbenv->txn_checkpoint(dbenv, 0, 0, DB_FORCE)) != 0)
+	/* Take a checkpoint here to force any dirty data pages to disk. */
+	if ((ret = __txn_checkpoint(dbenv, 0, 0, DB_FORCE)) != 0)
 		goto err;
 
 	/* Close all the db files that are open. */
 	if ((ret = __dbreg_close_files(dbenv)) != 0)
 		goto err;
 
+done:
 	if (max_lsn != NULL) {
-		region->last_ckp = ((DB_TXNHEAD *)txninfo)->ckplsn;
+		if (!IS_ZERO_LSN(((DB_TXNHEAD *)txninfo)->ckplsn))
+			region->last_ckp = ((DB_TXNHEAD *)txninfo)->ckplsn;
+		else if ((ret =
+		    __txn_findlastckp(dbenv, &region->last_ckp, max_lsn)) != 0)
+			goto err;
 
 		/* We are going to truncate, so we'd best close the cursor. */
-		if (logc != NULL && (ret = logc->close(logc, 0)) != 0)
+		if (logc != NULL && (ret = __log_c_close(logc)) != 0)
+			goto err;
+		if ((ret = __log_vtruncate(dbenv,
+		    max_lsn, &((DB_TXNHEAD *)txninfo)->ckplsn, trunclsn)) != 0)
 			goto err;
-		__log_vtruncate(dbenv,
-		    max_lsn, &((DB_TXNHEAD *)txninfo)->ckplsn);
 
 		/*
 		 * Now we need to open files that should be open in order for
@@ -498,9 +530,10 @@ __db_apprec(dbenv, max_lsn, flags)
 		 * truncated the log, we need to recompute from where the
 		 * openfiles pass should begin.
 		 */
-		if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+		if ((ret = __log_cursor(dbenv, &logc)) != 0)
 			goto err;
-		if ((ret = logc->get(logc, &first_lsn, &data, DB_FIRST)) != 0) {
+		if ((ret =
+		    __log_c_get(logc, &first_lsn, &data, DB_FIRST)) != 0) {
 			if (ret == DB_NOTFOUND)
 				ret = 0;
 			else
@@ -508,7 +541,7 @@ __db_apprec(dbenv, max_lsn, flags)
 			goto err;
 		}
 		if ((ret = __txn_getckp(dbenv, &first_lsn)) == 0 &&
-		    (ret = logc->get(logc, &first_lsn, &data, DB_SET)) == 0) {
+		    (ret = __log_c_get(logc, &first_lsn, &data, DB_SET)) == 0) {
 			/* We have a recent checkpoint.  This is LSN (1). */
 			if ((ret = __txn_ckp_read(dbenv,
 			    data.data, &ckp_args)) != 0) {
@@ -519,8 +552,9 @@ __db_apprec(dbenv, max_lsn, flags)
 				goto err;
 			}
 			first_lsn = ckp_args->ckp_lsn;
+			__os_free(dbenv, ckp_args);
 		}
-		if ((ret = logc->get(logc, &first_lsn, &data, DB_SET)) != 0)
+		if ((ret = __log_c_get(logc, &first_lsn, &data, DB_SET)) != 0)
 			goto err;
 		if ((ret = __env_openfiles(dbenv, logc,
 		    txninfo, &data, &first_lsn, NULL, nfiles, 1)) != 0)
@@ -535,10 +569,11 @@ __db_apprec(dbenv, max_lsn, flags)
 
 	if (FLD_ISSET(dbenv->verbose, DB_VERB_RECOVERY)) {
 		(void)time(&now);
-		__db_err(dbenv, "Recovery complete at %.24s", ctime(&now));
-		__db_err(dbenv, "%s %lx %s [%lu][%lu]",
+		__db_msg(dbenv, "Recovery complete at %.24s", ctime(&now));
+		__db_msg(dbenv, "%s %lx %s [%lu][%lu]",
 		    "Maximum transaction ID",
-		    ((DB_TXNHEAD *)txninfo)->maxid,
+		    (u_long)(txninfo == NULL ?
+			TXN_MINIMUM : ((DB_TXNHEAD *)txninfo)->maxid),
 		    "Recovery checkpoint",
 		    (u_long)region->last_ckp.file,
 		    (u_long)region->last_ckp.offset);
@@ -550,17 +585,7 @@ msgerr:		__db_err(dbenv,
 		    (u_long)lsn.file, (u_long)lsn.offset, pass);
 	}
 
-done:
-err:	if (lockid != DB_LOCK_INVALIDID) {
-		if ((t_ret = __rep_unlockpages(dbenv, lockid)) != 0 && ret == 0)
-			ret = t_ret;
-
-		if ((t_ret =
-		    dbenv->lock_id_free(dbenv, lockid)) != 0 && ret == 0)
-			ret = t_ret;
-	}
-
-	if (logc != NULL && (t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+err:	if (logc != NULL && (t_ret = __log_c_close(logc)) != 0 && ret == 0)
 		ret = t_ret;
 
 	if (txninfo != NULL)
@@ -569,14 +594,8 @@ err:	if (lockid != DB_LOCK_INVALIDID) {
 	if (dtab != NULL)
 		__os_free(dbenv, dtab);
 
-	if (ckp_args != NULL)
-		__os_free(dbenv, ckp_args);
-
 	dbenv->tx_timestamp = 0;
 
-	/* Restore the state of the thread flag, clear in-recovery flags. */
-	if (is_thread)
-		F_SET(dbenv, DB_ENV_THREAD);
 	F_CLR((DB_LOG *)dbenv->lg_handle, DBLOG_RECOVER);
 	F_CLR(region, TXN_IN_RECOVERY);
 
@@ -632,48 +651,84 @@ __lsn_diff(low, high, current, max, is_forward)
  *
  * This is used to find the earliest log record to process when a client
  * is trying to sync up with a master whose max LSN is less than this
- * client's max lsn; we want to roll back everything after that
+ * client's max lsn; we want to roll back everything after that.
+ * Also used in the verify phase to walk back via checkpoints.
  *
  * Find the latest checkpoint whose ckp_lsn is less than the max lsn.
+ * PUBLIC: int    __log_backup __P((DB_ENV *, DB_LOGC *, DB_LSN *,
+ * PUBLIC:    DB_LSN *, u_int32_t));
  */
-static int
-__log_backup(dbenv, logc, max_lsn, start_lsn)
+int
+__log_backup(dbenv, logc, max_lsn, start_lsn, cmp)
 	DB_ENV *dbenv;
 	DB_LOGC *logc;
 	DB_LSN *max_lsn, *start_lsn;
+	u_int32_t cmp;
 {
-	DB_LSN lsn;
+	DB_LSN cmp_lsn, lsn;
 	DBT data;
 	__txn_ckp_args *ckp_args;
-	int ret;
+	int lcmp, ret;
 
 	memset(&data, 0, sizeof(data));
 	ckp_args = NULL;
 
-	/*
-	 * Follow checkpoints through the log until we find one with
-	 * a ckp_lsn less than max_lsn.
-	 */
+	if (cmp != CKPLSN_CMP && cmp != LASTCKP_CMP)
+		return (EINVAL);
+
 	if ((ret = __txn_getckp(dbenv, &lsn)) != 0)
 		goto err;
-	while ((ret = logc->get(logc, &lsn, &data, DB_SET)) == 0) {
+	/*
+	 * Cmp tells us whether to check the ckp_lsn or the last_ckp
+	 * fields in the checkpoint record.
+	 */
+	while ((ret = __log_c_get(logc, &lsn, &data, DB_SET)) == 0) {
 		if ((ret = __txn_ckp_read(dbenv, data.data, &ckp_args)) != 0)
 			return (ret);
-		if (log_compare(&ckp_args->ckp_lsn, max_lsn) <= 0) {
-			*start_lsn = ckp_args->ckp_lsn;
+		if (cmp == CKPLSN_CMP) {
+			/*
+			 * Follow checkpoints through the log until
+			 * we find one with a ckp_lsn less than
+			 * or equal max_lsn.
+			 */
+			cmp_lsn = ckp_args->ckp_lsn;
+			lcmp = (log_compare(&cmp_lsn, max_lsn) <= 0);
+		} else {
+			/*
+			 * When we're walking back through the checkpoints
+			 * we want the LSN of this checkpoint strictly less
+			 * than the max_lsn (also a ckp LSN).
+			 */
+			cmp_lsn = lsn;
+			lcmp = (log_compare(&cmp_lsn, max_lsn) < 0);
+		}
+		if (lcmp) {
+			*start_lsn = cmp_lsn;
 			break;
 		}
 
-		lsn = ckp_args->prev_lsn;
-		if (IS_ZERO_LSN(lsn))
+		lsn = ckp_args->last_ckp;
+		/*
+		 * If there are no more checkpoints behind us, we're
+		 * done.  Break with DB_NOTFOUND.
+		 */
+		if (IS_ZERO_LSN(lsn)) {
+			ret = DB_NOTFOUND;
 			break;
+		}
 		__os_free(dbenv, ckp_args);
 	}
 
 	if (ckp_args != NULL)
 		__os_free(dbenv, ckp_args);
-err:	if (IS_ZERO_LSN(*start_lsn) && (ret == 0 || ret == DB_NOTFOUND))
-		ret = logc->get(logc, start_lsn, &data, DB_FIRST);
+	/*
+	 * For CKPLSN_CMP if we walked back through all the checkpoints,
+	 * set the cursor on the first log record.  For LASTCKP_CMP
+	 * we want to return 0,0 in start_lsn.
+	 */
+err:	if (IS_ZERO_LSN(*start_lsn) && cmp == CKPLSN_CMP &&
+	    (ret == 0 || ret == DB_NOTFOUND))
+		ret = __log_c_get(logc, start_lsn, &data, DB_FIRST);
 	return (ret);
 }
 
@@ -703,8 +758,8 @@ __log_earliest(dbenv, logc, lowtime, lowlsn)
 	 * record whose ckp_lsn is greater than first_lsn.
 	 */
 
-	for (ret = logc->get(logc, &first_lsn, &data, DB_FIRST);
-	    ret == 0; ret = logc->get(logc, &lsn, &data, DB_NEXT)) {
+	for (ret = __log_c_get(logc, &first_lsn, &data, DB_FIRST);
+	    ret == 0; ret = __log_c_get(logc, &lsn, &data, DB_NEXT)) {
 		memcpy(&rectype, data.data, sizeof(rectype));
 		if (rectype != DB___txn_ckp)
 			continue;
@@ -749,7 +804,7 @@ __env_openfiles(dbenv, logc, txninfo,
 	int in_recovery;
 	double nfiles;
 {
-	DB_LSN lsn;
+	DB_LSN lsn, tlsn;
 	u_int32_t log_size;
 	int progress, ret;
 
@@ -769,8 +824,9 @@ __env_openfiles(dbenv, logc, txninfo,
 			   last_lsn, &lsn, log_size, 1) / nfiles));
 			dbenv->db_feedback(dbenv, DB_RECOVER, progress);
 		}
+		tlsn = lsn;
 		ret = __db_dispatch(dbenv,
-		    dbenv->recover_dtab, dbenv->recover_dtab_size, data, &lsn,
+		    dbenv->recover_dtab, dbenv->recover_dtab_size, data, &tlsn,
 		    in_recovery ? DB_TXN_OPENFILES : DB_TXN_POPENFILES,
 		    txninfo);
 		if (ret != 0 && ret != DB_TXN_CKP) {
@@ -779,12 +835,27 @@ __env_openfiles(dbenv, logc, txninfo,
 			    (u_long)lsn.file, (u_long)lsn.offset);
 			break;
 		}
-		if ((ret = logc->get(logc, &lsn, data, DB_NEXT)) != 0) {
-			if (ret == DB_NOTFOUND)
-				ret = 0;
+		if ((ret = __log_c_get(logc, &lsn, data, DB_NEXT)) != 0) {
+			if (ret == DB_NOTFOUND) {
+				if (last_lsn != NULL &&
+				   log_compare(&lsn, last_lsn) != 0)
+					ret = __db_log_corrupt(dbenv, &lsn);
+				else
+					ret = 0;
+			}
 			break;
 		}
 	}
 
 	return (ret);
 }
+
+static int
+__db_log_corrupt(dbenv, lsnp)
+	DB_ENV *dbenv;
+	DB_LSN *lsnp;
+{
+	__db_err(dbenv, "Log file corrupt at LSN: [%lu][%lu]",
+	     (u_long)lsnp->file, (u_long)lsnp->offset);
+	return (EINVAL);
+}
diff --git a/storage/bdb/env/env_region.c b/storage/bdb/env/env_region.c
index a919cf328b467b083098a6fb2b196f2367a116ce..17d2e65d37c1dca91f0a2f331aa4571d729fee3f 100644
--- a/storage/bdb/env/env_region.c
+++ b/storage/bdb/env/env_region.c
@@ -1,33 +1,29 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: env_region.c,v 11.103 2004/10/15 16:59:41 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: env_region.c,v 11.64 2002/07/17 15:09:19 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
-#include <ctype.h>
 #include <string.h>
-#include <unistd.h>
 #endif
 
 #include "db_int.h"
 #include "dbinc/db_shash.h"
+#include "dbinc/crypto.h"
 #include "dbinc/lock.h"
 #include "dbinc/log.h"
 #include "dbinc/mp.h"
-#include "dbinc/rep.h"
 #include "dbinc/txn.h"
 
-static int  __db_des_destroy __P((DB_ENV *, REGION *));
+static int  __db_des_destroy __P((DB_ENV *, REGION *, int));
 static int  __db_des_get __P((DB_ENV *, REGINFO *, REGINFO *, REGION **));
 static int  __db_e_remfile __P((DB_ENV *));
 static int  __db_faultmem __P((DB_ENV *, void *, size_t, int));
@@ -51,7 +47,8 @@ __db_e_attach(dbenv, init_flagsp)
 	size_t size;
 	size_t nrw;
 	u_int32_t mbytes, bytes;
-	int retry_cnt, ret, segid;
+	u_int retry_cnt;
+	int ret, segid;
 	char buf[sizeof(DB_REGION_FMT) + 20];
 
 #if !defined(HAVE_MUTEX_THREADS)
@@ -75,7 +72,7 @@ __db_e_attach(dbenv, init_flagsp)
 	 */
 	if (F_ISSET(dbenv, DB_ENV_THREAD)) {
 		__db_err(dbenv,
-"architecture lacks fast mutexes: applications cannot be threaded");
+	    "architecture lacks fast mutexes: applications cannot be threaded");
 		return (EINVAL);
 	}
 #endif
@@ -89,9 +86,9 @@ loop:	renv = NULL;
 	/* Set up the DB_ENV's REG_INFO structure. */
 	if ((ret = __os_calloc(dbenv, 1, sizeof(REGINFO), &infop)) != 0)
 		return (ret);
+	infop->dbenv = dbenv;
 	infop->type = REGION_TYPE_ENV;
 	infop->id = REGION_ID_ENV;
-	infop->mode = dbenv->db_mode;
 	infop->flags = REGION_JOIN_OK;
 	if (F_ISSET(dbenv, DB_ENV_CREATE))
 		F_SET(infop, REGION_CREATE_OK);
@@ -130,8 +127,8 @@ loop:	renv = NULL;
 	 */
 	if (F_ISSET(dbenv, DB_ENV_CREATE)) {
 		if ((ret = __os_open(dbenv, infop->name,
-		    DB_OSO_CREATE | DB_OSO_DIRECT | DB_OSO_EXCL | DB_OSO_REGION,
-		    dbenv->db_mode, dbenv->lockfhp)) == 0)
+		    DB_OSO_CREATE | DB_OSO_EXCL | DB_OSO_REGION,
+		    dbenv->db_mode, &dbenv->lockfhp)) == 0)
 			goto creation;
 		if (ret != EEXIST) {
 			__db_err(dbenv,
@@ -144,10 +141,13 @@ loop:	renv = NULL;
 	 * If we couldn't create the file, try and open it.  (If that fails,
 	 * we're done.)
 	 */
-	if ((ret = __os_open(dbenv, infop->name, DB_OSO_REGION | DB_OSO_DIRECT,
-	    dbenv->db_mode, dbenv->lockfhp)) != 0)
+	if ((ret = __os_open(
+	    dbenv, infop->name, DB_OSO_REGION, 0, &dbenv->lockfhp)) != 0)
 		goto err;
 
+	/* The region exists, it's not okay to recreate it. */
+	F_CLR(infop, REGION_CREATE_OK);
+
 	/*
 	 * !!!
 	 * The region may be in system memory not backed by the filesystem
@@ -231,7 +231,8 @@ loop:	renv = NULL;
 	 * the better.
 	 */
 #ifdef HAVE_MUTEX_THREADS
-	 __os_closehandle(dbenv, dbenv->lockfhp);
+	 (void)__os_closehandle(dbenv, dbenv->lockfhp);
+	 dbenv->lockfhp = NULL;
 #endif
 
 	/* Call the region join routine to acquire the region. */
@@ -248,8 +249,19 @@ loop:	renv = NULL;
 	 * this means that all of our offsets (R_ADDR/R_OFFSET) get shifted
 	 * as well, but that should be fine.
 	 */
-	infop->primary = R_ADDR(infop, 0);
+	infop->primary = infop->addr;
 	infop->addr = (u_int8_t *)infop->addr + sizeof(REGENV);
+	renv = infop->primary;
+
+	/* Make sure the region matches our build. */
+	if (renv->majver != DB_VERSION_MAJOR ||
+	    renv->minver != DB_VERSION_MINOR) {
+		__db_err(dbenv,
+	"Program version %d.%d doesn't match environment version",
+		    DB_VERSION_MAJOR, DB_VERSION_MINOR);
+		ret = DB_VERSION_MISMATCH;
+		goto err;
+	}
 
 	/*
 	 * Check if the environment has had a catastrophic failure.
@@ -265,7 +277,6 @@ loop:	renv = NULL;
 	 * I'd rather play permissions games using the underlying file, but I
 	 * can't because Windows/NT filesystems won't open files mode 0.
 	 */
-	renv = infop->primary;
 	if (renv->envpanic && !F_ISSET(dbenv, DB_ENV_NOPANIC)) {
 		ret = __db_panic_msg(dbenv);
 		goto err;
@@ -273,20 +284,6 @@ loop:	renv = NULL;
 	if (renv->magic != DB_REGION_MAGIC)
 		goto retry;
 
-	/* Make sure the region matches our build. */
-	if (renv->majver != DB_VERSION_MAJOR ||
-	    renv->minver != DB_VERSION_MINOR ||
-	    renv->patch != DB_VERSION_PATCH) {
-		__db_err(dbenv,
-	"Program version %d.%d.%d doesn't match environment version %d.%d.%d",
-		    DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH,
-		    renv->majver, renv->minver, renv->patch);
-#ifndef DIAGNOSTIC
-		ret = EINVAL;
-		goto err;
-#endif
-	}
-
 	/* Lock the environment. */
 	MUTEX_LOCK(dbenv, &renv->mutex);
 
@@ -326,11 +323,13 @@ err_unlock:	MUTEX_UNLOCK(dbenv, &renv->mutex);
 	++renv->refcnt;
 
 	/*
-	 * If our caller wants them, return the flags this environment was
-	 * initialized with.
+	 * Add configuration flags from our caller; return the total set of
+	 * configuration flags for later DB_JOINENV calls.
 	 */
-	if (init_flagsp != NULL)
+	if (init_flagsp != NULL) {
+		renv->init_flags |= *init_flagsp;
 		*init_flagsp = renv->init_flags;
+	}
 
 	/* Discard our lock. */
 	MUTEX_UNLOCK(dbenv, &renv->mutex);
@@ -350,15 +349,15 @@ creation:
 	F_SET(infop, REGION_CREATE);
 
 	/*
-	 * Allocate room for 50 REGION structures plus overhead (we're going
+	 * Allocate room for 100 REGION structures plus overhead (we're going
 	 * to use this space for last-ditch allocation requests), although we
 	 * should never need anything close to that.
 	 *
 	 * Encryption passwds are stored in the env region.  Add that in too.
 	 */
 	memset(&tregion, 0, sizeof(tregion));
-	tregion.size = (roff_t)(50 * sizeof(REGION) +
-	    dbenv->passwd_len + 2048);
+	tregion.size = (roff_t)(100 * sizeof(REGION) +
+	    dbenv->passwd_len + 4096);
 	tregion.segid = INVALID_REGION_SEGID;
 	if ((ret = __os_r_attach(dbenv, infop, &tregion)) != 0)
 		goto err;
@@ -387,9 +386,9 @@ creation:
 	 * region detach, and that all of our offsets (R_ADDR/R_OFFSET) will be
 	 * shifted as well, but that should be fine.
 	 */
-	infop->primary = R_ADDR(infop, 0);
+	infop->primary = infop->addr;
 	infop->addr = (u_int8_t *)infop->addr + sizeof(REGENV);
-	__db_shalloc_init(infop->addr, tregion.size - sizeof(REGENV));
+	__db_shalloc_init(infop, tregion.size - sizeof(REGENV));
 
 	/*
 	 * Initialize the rest of the REGENV structure, except for the magic
@@ -397,7 +396,8 @@ creation:
 	 */
 	renv = infop->primary;
 	renv->envpanic = 0;
-	db_version(&renv->majver, &renv->minver, &renv->patch);
+	__os_unique_id(dbenv, &renv->envid);
+	(void)db_version(&renv->majver, &renv->minver, &renv->patch);
 	SH_LIST_INIT(&renv->regionq);
 	renv->refcnt = 1;
 	renv->cipher_off = INVALID_ROFF;
@@ -481,8 +481,10 @@ find_err:	__db_err(dbenv,
 	 * the better.
 	 */
 #if defined(HAVE_MUTEX_THREADS)
-	if (F_ISSET(dbenv->lockfhp, DB_FH_VALID))
-		 __os_closehandle(dbenv, dbenv->lockfhp);
+	if (dbenv->lockfhp != NULL) {
+		 (void)__os_closehandle(dbenv, dbenv->lockfhp);
+		 dbenv->lockfhp = NULL;
+	}
 #endif
 
 	/* Validate the file. */
@@ -497,8 +499,10 @@ find_err:	__db_err(dbenv,
 
 err:
 retry:	/* Close any open file handle. */
-	if (F_ISSET(dbenv->lockfhp, DB_FH_VALID))
+	if (dbenv->lockfhp != NULL) {
 		(void)__os_closehandle(dbenv, dbenv->lockfhp);
+		dbenv->lockfhp = NULL;
+	}
 
 	/*
 	 * If we joined or created the region, detach from it.  If we created
@@ -555,6 +559,7 @@ __db_e_detach(dbenv, destroy)
 
 	if (F_ISSET(dbenv, DB_ENV_PRIVATE))
 		destroy = 1;
+
 	/* Lock the environment. */
 	MUTEX_LOCK(dbenv, &renv->mutex);
 
@@ -562,7 +567,7 @@ __db_e_detach(dbenv, destroy)
 	if (renv->refcnt == 0) {
 		__db_err(dbenv,
 		    "region %lu (environment): reference count went negative",
-		    infop->rp->id);
+		    (u_long)infop->rp->id);
 	} else
 		--renv->refcnt;
 
@@ -570,39 +575,55 @@ __db_e_detach(dbenv, destroy)
 	MUTEX_UNLOCK(dbenv, &renv->mutex);
 
 	/* Close the locking file handle. */
-	if (F_ISSET(dbenv->lockfhp, DB_FH_VALID))
+	if (dbenv->lockfhp != NULL) {
 		(void)__os_closehandle(dbenv, dbenv->lockfhp);
-
-	/* Reset the addr value that we "corrected" above. */
-	infop->addr = infop->primary;
+		dbenv->lockfhp = NULL;
+	}
 
 	/*
-	 * If we are destroying the environment, we need to
-	 * destroy any system resources backing the mutex, as well
-	 * as any system resources that the replication system may have
-	 * acquired and put in the main region.
-	 *
-	 * Do these now before we free the memory in __os_r_detach.
+	 * If we are destroying the environment, destroy any system resources
+	 * the crypto and replication systems may have acquired and put in the
+	 * main region.
 	 */
 	if (destroy) {
-		__rep_region_destroy(dbenv);
-		__db_mutex_destroy(&renv->mutex);
-		__db_mutex_destroy(&infop->rp->mutex);
+#ifdef HAVE_CRYPTO
+		(void)__crypto_region_destroy(dbenv);
+#endif
+		(void)__rep_region_destroy(dbenv);
 	}
 
 	/*
 	 * Release the region, and kill our reference.
 	 *
+	 * If we are destroying the environment, destroy any system resources
+	 * backing the mutex.
+	 */
+	if (destroy) {
+		(void)__db_mutex_destroy(&renv->mutex);
+		(void)__db_mutex_destroy(&infop->rp->mutex);
+
+		/*
+		 * Only free the REGION structure itself if it was separately
+		 * allocated from the heap.
+		 */
+		if (F_ISSET(dbenv, DB_ENV_PRIVATE))
+			__db_shalloc_free(infop, infop->rp);
+	}
+
+	/* Reset the addr value that we "corrected" above. */
+	infop->addr = infop->primary;
+
+	(void)__os_r_detach(dbenv, infop, destroy);
+	if (infop->name != NULL)
+		__os_free(dbenv, infop->name);
+
+	/*
 	 * We set the DB_ENV->reginfo field to NULL here and discard its memory.
 	 * DB_ENV->remove calls __dbenv_remove to do the region remove, and
 	 * __dbenv_remove attached and then detaches from the region.  We don't
 	 * want to return to DB_ENV->remove with a non-NULL DB_ENV->reginfo
 	 * field because it will attempt to detach again as part of its cleanup.
 	 */
-	(void)__os_r_detach(dbenv, infop, destroy);
-
-	if (infop->name != NULL)
-		__os_free(dbenv, infop->name);
 	__os_free(dbenv, dbenv->reginfo);
 	dbenv->reginfo = NULL;
 
@@ -705,31 +726,22 @@ __db_e_remove(dbenv, flags)
 		 * callers be prepared to create the region in order to join it.
 		 */
 		memset(&reginfo, 0, sizeof(reginfo));
-restart:	for (rp = SH_LIST_FIRST(&renv->regionq, __db_region);
+		for (rp = SH_LIST_FIRST(&renv->regionq, __db_region);
 		    rp != NULL; rp = SH_LIST_NEXT(rp, q, __db_region)) {
 			if (rp->type == REGION_TYPE_ENV)
 				continue;
 
+			/*
+			 * If we get here and can't attach and/or detach to the
+			 * region, it's a mess.  Ignore errors, there's nothing
+			 * we can do about them.
+			 */
 			reginfo.id = rp->id;
 			reginfo.flags = REGION_CREATE_OK;
-			if ((ret = __db_r_attach(dbenv, &reginfo, 0)) != 0) {
-				__db_err(dbenv,
-				    "region %s attach: %s", db_strerror(ret));
-				continue;
-			}
-			R_UNLOCK(dbenv, &reginfo);
-			if ((ret = __db_r_detach(dbenv, &reginfo, 1)) != 0) {
-				__db_err(dbenv,
-				    "region detach: %s", db_strerror(ret));
-				continue;
+			if (__db_r_attach(dbenv, &reginfo, 0) == 0) {
+				R_UNLOCK(dbenv, &reginfo);
+				(void)__db_r_detach(dbenv, &reginfo, 1);
 			}
-			/*
-			 * If we have an error, we continue so we eventually
-			 * reach the end of the list.  If we succeed, restart
-			 * the list because it was relinked when we destroyed
-			 * the entry.
-			 */
-			goto restart;
 		}
 
 		/* Destroy the environment's region. */
@@ -761,17 +773,9 @@ static int
 __db_e_remfile(dbenv)
 	DB_ENV *dbenv;
 {
-	static char *old_region_names[] = {
-		"__db_lock.share",
-		"__db_log.share",
-		"__db_mpool.share",
-		"__db_txn.share",
-		NULL
-	};
 	int cnt, fcnt, lastrm, ret;
-	u_int8_t saved_byte;
 	const char *dir;
-	char *p, **names, *path, buf[sizeof(DB_REGION_FMT) + 20];
+	char saved_char, *p, **names, *path, buf[sizeof(DB_REGION_FMT) + 20];
 
 	/* Get the full path of a file in the environment. */
 	(void)snprintf(buf, sizeof(buf), "%s", DB_REGION_ENV);
@@ -781,11 +785,11 @@ __db_e_remfile(dbenv)
 	/* Get the parent directory for the environment. */
 	if ((p = __db_rpath(path)) == NULL) {
 		p = path;
-		saved_byte = *p;
+		saved_char = *p;
 
 		dir = PATH_DOT;
 	} else {
-		saved_byte = *p;
+		saved_char = *p;
 		*p = '\0';
 
 		dir = path;
@@ -796,33 +800,52 @@ __db_e_remfile(dbenv)
 		__db_err(dbenv, "%s: %s", dir, db_strerror(ret));
 
 	/* Restore the path, and free it. */
-	*p = saved_byte;
+	*p = saved_char;
 	__os_free(dbenv, path);
 
 	if (ret != 0)
 		return (ret);
 
 	/*
-	 * Search for valid region names, and remove them.  We remove the
-	 * environment region last, because it's the key to this whole mess.
+	 * Remove files from the region directory.
 	 */
 	for (lastrm = -1, cnt = fcnt; --cnt >= 0;) {
-		if (strlen(names[cnt]) != DB_REGION_NAME_LENGTH ||
-		    memcmp(names[cnt], DB_REGION_FMT, DB_REGION_NAME_NUM) != 0)
+		/* Skip anything outside our name space. */
+		if (strncmp(names[cnt],
+		    DB_REGION_PREFIX, sizeof(DB_REGION_PREFIX) - 1))
+			continue;
+
+		/* Skip queue extent files. */
+		if (strncmp(names[cnt], "__dbq.", 6) == 0)
 			continue;
+
+		/* Skip replication files. */
+		if (strncmp(names[cnt], "__db.rep.", 9) == 0)
+			continue;
+
+		/*
+		 * Remove the primary environment region last, because it's
+		 * the key to this whole mess.
+		 */
 		if (strcmp(names[cnt], DB_REGION_ENV) == 0) {
 			lastrm = cnt;
 			continue;
 		}
-		for (p = names[cnt] + DB_REGION_NAME_NUM;
-		    *p != '\0' && isdigit((int)*p); ++p)
-			;
-		if (*p != '\0')
-			continue;
 
+		/* Remove the file. */
 		if (__db_appname(dbenv,
 		    DB_APP_NONE, names[cnt], 0, NULL, &path) == 0) {
-			if (F_ISSET(dbenv, DB_ENV_OVERWRITE))
+			/*
+			 * Overwrite region files.  Temporary files would have
+			 * been maintained in encrypted format, so there's no
+			 * reason to overwrite them.  This is not an exact
+			 * check on the file being a region file, but it's
+			 * not likely to be wrong, and the worst thing that can
+			 * happen is we overwrite a file that didn't need to be
+			 * overwritten.
+			 */
+			if (F_ISSET(dbenv, DB_ENV_OVERWRITE) &&
+			    strlen(names[cnt]) == DB_REGION_NAME_LENGTH)
 				(void)__db_overwrite(dbenv, path);
 			(void)__os_unlink(dbenv, path);
 			__os_free(dbenv, path);
@@ -839,73 +862,6 @@ __db_e_remfile(dbenv)
 		}
 	__os_dirfree(dbenv, names, fcnt);
 
-	/*
-	 * !!!
-	 * Backward compatibility -- remove region files from releases
-	 * before 2.8.XX.
-	 */
-	for (names = (char **)old_region_names; *names != NULL; ++names)
-		if (__db_appname(dbenv,
-		    DB_APP_NONE, *names, 0, NULL, &path) == 0) {
-			(void)__os_unlink(dbenv, path);
-			__os_free(dbenv, path);
-		}
-
-	return (0);
-}
-
-/*
- * __db_e_stat
- *	Statistics for the environment.
- *
- * PUBLIC: int __db_e_stat __P((DB_ENV *,
- * PUBLIC:       REGENV *, REGION *, int *, u_int32_t));
- */
-int
-__db_e_stat(dbenv, arg_renv, arg_regions, arg_regions_cnt, flags)
-	DB_ENV *dbenv;
-	REGENV *arg_renv;
-	REGION *arg_regions;
-	int *arg_regions_cnt;
-	u_int32_t flags;
-{
-	REGENV *renv;
-	REGINFO *infop;
-	REGION *rp;
-	int n, ret;
-
-	infop = dbenv->reginfo;
-	renv = infop->primary;
-	rp = infop->rp;
-	if ((ret = __db_fchk(dbenv,
-	    "DB_ENV->stat", flags, DB_STAT_CLEAR)) != 0)
-		return (ret);
-
-	/* Lock the environment. */
-	MUTEX_LOCK(dbenv, &rp->mutex);
-
-	*arg_renv = *renv;
-	if (LF_ISSET(DB_STAT_CLEAR)) {
-		renv->mutex.mutex_set_nowait = 0;
-		renv->mutex.mutex_set_wait = 0;
-	}
-
-	for (n = 0, rp = SH_LIST_FIRST(&renv->regionq, __db_region);
-	    n < *arg_regions_cnt && rp != NULL;
-	    ++n, rp = SH_LIST_NEXT(rp, q, __db_region)) {
-		arg_regions[n] = *rp;
-		if (LF_ISSET(DB_STAT_CLEAR)) {
-			rp->mutex.mutex_set_nowait = 0;
-			rp->mutex.mutex_set_wait = 0;
-		}
-	}
-
-	/* Release the lock. */
-	rp = infop->rp;
-	MUTEX_UNLOCK(dbenv, &rp->mutex);
-
-	*arg_regions_cnt = n == 0 ? n : n - 1;
-
 	return (0);
 }
 
@@ -940,6 +896,7 @@ __db_r_attach(dbenv, infop, size)
 		MUTEX_UNLOCK(dbenv, &renv->mutex);
 		return (ret);
 	}
+	infop->dbenv = dbenv;
 	infop->rp = rp;
 	infop->type = rp->type;
 	infop->id = rp->id;
@@ -972,11 +929,8 @@ __db_r_attach(dbenv, infop, size)
 	 *
 	 * If we created the region, initialize it for allocation.
 	 */
-	if (F_ISSET(infop, REGION_CREATE)) {
-		((REGION *)(infop->addr))->magic = DB_REGION_MAGIC;
-
-		(void)__db_shalloc_init(infop->addr, rp->size);
-	}
+	if (F_ISSET(infop, REGION_CREATE))
+		__db_shalloc_init(infop, rp->size);
 
 	/*
 	 * If the underlying REGION isn't the environment, acquire a lock
@@ -989,8 +943,8 @@ __db_r_attach(dbenv, infop, size)
 
 	return (0);
 
-	/* Discard the underlying region. */
-err:	if (infop->addr != NULL)
+err:	/* Discard the underlying region. */
+	if (infop->addr != NULL)
 		(void)__os_r_detach(dbenv,
 		    infop, F_ISSET(infop, REGION_CREATE));
 	infop->rp = NULL;
@@ -998,7 +952,7 @@ err:	if (infop->addr != NULL)
 
 	/* Discard the REGION structure if we created it. */
 	if (F_ISSET(infop, REGION_CREATE)) {
-		(void)__db_des_destroy(dbenv, rp);
+		(void)__db_des_destroy(dbenv, rp, 1);
 		F_CLR(infop, REGION_CREATE);
 	}
 
@@ -1036,8 +990,8 @@ __db_r_detach(dbenv, infop, destroy)
 	MUTEX_LOCK(dbenv, &rp->mutex);
 
 	/*
-	 * We need to call destroy on per-subsystem info before
-	 * we free the memory associated with the region.
+	 * We need to call destroy on per-subsystem info before we free the
+	 * memory associated with the region.
 	 */
 	if (destroy)
 		__db_region_destroy(dbenv, infop);
@@ -1048,9 +1002,16 @@ __db_r_detach(dbenv, infop, destroy)
 	/* Release the REGION lock. */
 	MUTEX_UNLOCK(dbenv, &rp->mutex);
 
-	/* If we destroyed the region, discard the REGION structure. */
+	/*
+	 * If we destroyed the region, discard the REGION structure.  The only
+	 * time this routine is called with the destroy flag set is when the
+	 * environment is being removed, and it's likely that the only reason
+	 * the environment is being removed is because we crashed.  Don't do
+	 * any unnecessary shared memory manipulation.
+	 */
 	if (destroy &&
-	    ((t_ret = __db_des_destroy(dbenv, rp)) != 0) && ret == 0)
+	    ((t_ret = __db_des_destroy(
+		dbenv, rp, F_ISSET(dbenv, DB_ENV_PRIVATE))) != 0) && ret == 0)
 		ret = t_ret;
 
 	/* Release the environment lock. */
@@ -1130,15 +1091,19 @@ __db_des_get(dbenv, env_infop, infop, rpp)
 	 * next available ID.
 	 */
 	if (rp == NULL) {
-		if ((ret = __db_shalloc(env_infop->addr,
-		    sizeof(REGION), MUTEX_ALIGN, &rp)) != 0)
+		if ((ret = __db_shalloc(env_infop,
+		    sizeof(REGION), MUTEX_ALIGN, &rp)) != 0) {
+			__db_err(dbenv,
+			    "unable to create new master region entry: %s",
+			    db_strerror(ret));
 			return (ret);
+		}
 
 		/* Initialize the region. */
 		memset(rp, 0, sizeof(*rp));
 		if ((ret = __db_mutex_setup(dbenv, env_infop, &rp->mutex,
 		    MUTEX_NO_RECORD | MUTEX_NO_RLOCK)) != 0) {
-			__db_shalloc_free(env_infop->addr, rp);
+			__db_shalloc_free(env_infop, rp);
 			return (ret);
 		}
 		rp->segid = INVALID_REGION_SEGID;
@@ -1163,9 +1128,10 @@ __db_des_get(dbenv, env_infop, infop, rpp)
  *	Destroy a reference to a REGION.
  */
 static int
-__db_des_destroy(dbenv, rp)
+__db_des_destroy(dbenv, rp, shmem_safe)
 	DB_ENV *dbenv;
 	REGION *rp;
+	int shmem_safe;
 {
 	REGINFO *infop;
 
@@ -1175,9 +1141,25 @@ __db_des_destroy(dbenv, rp)
 	 */
 	infop = dbenv->reginfo;
 
-	SH_LIST_REMOVE(rp, q, __db_region);
-	__db_mutex_destroy(&rp->mutex);
-	__db_shalloc_free(infop->addr, rp);
+	/*
+	 * If we're calling during recovery, it may not be safe to access the
+	 * shared memory, as the shared memory may have been corrupted during
+	 * the crash.  If the shared memory is safe, remove the REGION entry
+	 * from its linked list, destroy the mutex, and free the allocated
+	 * memory.  On systems that require system mutex support, we don't
+	 * have a choice -- safe or not, we have to destroy the mutex or we'll
+	 * leak memory.
+	 */
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
+	(void)__db_mutex_destroy(&rp->mutex);
+#else
+	if (shmem_safe)
+		(void)__db_mutex_destroy(&rp->mutex);
+#endif
+	if (shmem_safe) {
+		SH_LIST_REMOVE(rp, q, __db_region);
+		__db_shalloc_free(infop, rp);
+	}
 
 	return (0);
 }
@@ -1196,6 +1178,10 @@ __db_faultmem(dbenv, addr, size, created)
 	int ret;
 	u_int8_t *p, *t;
 
+	/* Ignore heap regions. */
+	if (F_ISSET(dbenv, DB_ENV_PRIVATE))
+		return (0);
+
 	/*
 	 * It's sometimes significantly faster to page-fault in all of the
 	 * region's pages before we run the application, as we see nasty
@@ -1241,7 +1227,7 @@ __db_region_destroy(dbenv, infop)
 		__log_region_destroy(dbenv, infop);
 		break;
 	case REGION_TYPE_MPOOL:
-		__mpool_region_destroy(dbenv, infop);
+		__memp_region_destroy(dbenv, infop);
 		break;
 	case REGION_TYPE_TXN:
 		__txn_region_destroy(dbenv, infop);
@@ -1249,6 +1235,7 @@ __db_region_destroy(dbenv, infop)
 	case REGION_TYPE_ENV:
 	case REGION_TYPE_MUTEX:
 		break;
+	case INVALID_REGION_TYPE:
 	default:
 		DB_ASSERT(0);
 		break;
diff --git a/storage/bdb/env/env_stat.c b/storage/bdb/env/env_stat.c
new file mode 100644
index 0000000000000000000000000000000000000000..c9ab7a112b313657231f96f11a90ee9e7095951d
--- /dev/null
+++ b/storage/bdb/env/env_stat.c
@@ -0,0 +1,666 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: env_stat.c,v 1.21 2004/10/29 17:37:23 bostic Exp $
+ */
+
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/db_am.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
+#include "dbinc/mp.h"
+#include "dbinc/txn.h"
+
+#ifdef HAVE_STATISTICS
+static int  __dbenv_print_all __P((DB_ENV *, u_int32_t));
+static int  __dbenv_print_stats __P((DB_ENV *, u_int32_t));
+static int  __dbenv_stat_print __P((DB_ENV *, u_int32_t));
+static const char *__reg_type __P((reg_type_t));
+
+/*
+ * __dbenv_stat_print_pp --
+ *	DB_ENV->stat_print pre/post processor.
+ *
+ * PUBLIC: int __dbenv_stat_print_pp __P((DB_ENV *, u_int32_t));
+ */
+int
+__dbenv_stat_print_pp(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	int rep_check, ret;
+
+	PANIC_CHECK(dbenv);
+	ENV_ILLEGAL_BEFORE_OPEN(dbenv, "DB_ENV->stat_print");
+
+	if ((ret = __db_fchk(dbenv, "DB_ENV->stat_print",
+	    flags, DB_STAT_ALL | DB_STAT_CLEAR | DB_STAT_SUBSYSTEM)) != 0)
+		return (ret);
+
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __dbenv_stat_print(dbenv, flags);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
+/*
+ * __dbenv_stat_print --
+ *	DB_ENV->stat_print method.
+ */
+static int
+__dbenv_stat_print(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	DB *dbp;
+	int ret;
+
+	if ((ret = __dbenv_print_stats(dbenv, flags)) != 0)
+		return (ret);
+
+	if (LF_ISSET(DB_STAT_ALL) &&
+	    (ret = __dbenv_print_all(dbenv, flags)) != 0)
+		return (ret);
+
+	if (!LF_ISSET(DB_STAT_SUBSYSTEM))
+		return (0);
+
+	/* The subsystems don't know anything about DB_STAT_SUBSYSTEM. */
+	LF_CLR(DB_STAT_SUBSYSTEM);
+
+	if (LOGGING_ON(dbenv)) {
+		__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+		if ((ret = __log_stat_print(dbenv, flags)) != 0)
+			return (ret);
+	}
+
+	if (LOCKING_ON(dbenv)) {
+		__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+		if ((ret = __lock_stat_print(dbenv, flags)) != 0)
+			return (ret);
+	}
+
+	if (MPOOL_ON(dbenv)) {
+		__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+		if ((ret = __memp_stat_print(dbenv, flags)) != 0)
+			return (ret);
+	}
+
+	if (REP_ON(dbenv)) {
+		__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+		if ((ret = __rep_stat_print(dbenv, flags)) != 0)
+			return (ret);
+	}
+
+	if (TXN_ON(dbenv)) {
+		__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+		if ((ret = __txn_stat_print(dbenv, flags)) != 0)
+			return (ret);
+	}
+
+	MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
+	for (dbp = LIST_FIRST(&dbenv->dblist);
+	    dbp != NULL; dbp = LIST_NEXT(dbp, dblistlinks)) {
+		__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+		__db_msg(dbenv, "%s%s%s\tDatabase name",
+		    dbp->fname, dbp->dname == NULL ? "" : "/",
+		    dbp->dname == NULL ? "" : dbp->dname);
+		if ((ret = __db_stat_print(dbp, flags)) != 0)
+			break;
+	}
+	MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
+
+	return (ret);
+}
+
+/*
+ * __dbenv_print_stats --
+ *	Display the default environment statistics.
+ *
+ */
+static int
+__dbenv_print_stats(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	REGENV *renv;
+	REGINFO *infop;
+
+	infop = dbenv->reginfo;
+	renv = infop->primary;
+
+	if (LF_ISSET(DB_STAT_ALL)) {
+		__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+		__db_msg(dbenv, "Default database environment information:");
+	}
+	__db_msg(dbenv, "%d.%d.%d\tEnvironment version",
+	    renv->majver, renv->minver, renv->patch);
+	STAT_HEX("Magic number", renv->magic);
+	STAT_LONG("Panic value", renv->envpanic);
+	STAT_LONG("References", renv->refcnt);
+
+	__db_print_mutex(dbenv, NULL, &renv->mutex,
+	    "The number of region locks that required waiting", flags);
+
+	return (0);
+}
+
+/*
+ * __dbenv_print_all --
+ *	Display the debugging environment statistics.
+ */
+static int
+__dbenv_print_all(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	static const FN fn[] = {
+		{ DB_ENV_AUTO_COMMIT,		"DB_ENV_AUTO_COMMIT" },
+		{ DB_ENV_CDB,			"DB_ENV_CDB" },
+		{ DB_ENV_CDB_ALLDB,		"DB_ENV_CDB_ALLDB" },
+		{ DB_ENV_CREATE,		"DB_ENV_CREATE" },
+		{ DB_ENV_DBLOCAL,		"DB_ENV_DBLOCAL" },
+		{ DB_ENV_DIRECT_DB,		"DB_ENV_DIRECT_DB" },
+		{ DB_ENV_DIRECT_LOG,		"DB_ENV_DIRECT_LOG" },
+		{ DB_ENV_DSYNC_LOG,		"DB_ENV_DSYNC_LOG" },
+		{ DB_ENV_FATAL,			"DB_ENV_FATAL" },
+		{ DB_ENV_LOCKDOWN,		"DB_ENV_LOCKDOWN" },
+		{ DB_ENV_LOG_AUTOREMOVE,	"DB_ENV_LOG_AUTOREMOVE" },
+		{ DB_ENV_LOG_INMEMORY,		"DB_ENV_LOG_INMEMORY" },
+		{ DB_ENV_NOLOCKING,		"DB_ENV_NOLOCKING" },
+		{ DB_ENV_NOMMAP,		"DB_ENV_NOMMAP" },
+		{ DB_ENV_NOPANIC,		"DB_ENV_NOPANIC" },
+		{ DB_ENV_OPEN_CALLED,		"DB_ENV_OPEN_CALLED" },
+		{ DB_ENV_OVERWRITE,		"DB_ENV_OVERWRITE" },
+		{ DB_ENV_PRIVATE,		"DB_ENV_PRIVATE" },
+		{ DB_ENV_REGION_INIT,		"DB_ENV_REGION_INIT" },
+		{ DB_ENV_RPCCLIENT,		"DB_ENV_RPCCLIENT" },
+		{ DB_ENV_RPCCLIENT_GIVEN,	"DB_ENV_RPCCLIENT_GIVEN" },
+		{ DB_ENV_SYSTEM_MEM,		"DB_ENV_SYSTEM_MEM" },
+		{ DB_ENV_THREAD,		"DB_ENV_THREAD" },
+		{ DB_ENV_TIME_NOTGRANTED,	"DB_ENV_TIME_NOTGRANTED" },
+		{ DB_ENV_TXN_NOSYNC,		"DB_ENV_TXN_NOSYNC" },
+		{ DB_ENV_TXN_WRITE_NOSYNC,	"DB_ENV_TXN_WRITE_NOSYNC" },
+		{ DB_ENV_YIELDCPU,		"DB_ENV_YIELDCPU" },
+		{ 0,				NULL }
+	};
+	static const FN ofn[] = {
+		{ DB_CREATE,			"DB_CREATE" },
+		{ DB_CXX_NO_EXCEPTIONS,	"DB_CXX_NO_EXCEPTIONS" },
+		{ DB_FORCE,			"DB_FORCE" },
+		{ DB_INIT_CDB,			"DB_INIT_CDB" },
+		{ DB_INIT_LOCK,		"DB_INIT_LOCK" },
+		{ DB_INIT_LOG,			"DB_INIT_LOG" },
+		{ DB_INIT_MPOOL,		"DB_INIT_MPOOL" },
+		{ DB_INIT_REP,			"DB_INIT_REP" },
+		{ DB_INIT_TXN,			"DB_INIT_TXN" },
+		{ DB_JOINENV,			"DB_JOINENV" },
+		{ DB_LOCKDOWN,			"DB_LOCKDOWN" },
+		{ DB_NOMMAP,			"DB_NOMMAP" },
+		{ DB_PRIVATE,			"DB_PRIVATE" },
+		{ DB_RDONLY,			"DB_RDONLY" },
+		{ DB_RECOVER,			"DB_RECOVER" },
+		{ DB_RECOVER_FATAL,		"DB_RECOVER_FATAL" },
+		{ DB_SYSTEM_MEM,		"DB_SYSTEM_MEM" },
+		{ DB_THREAD,			"DB_THREAD" },
+		{ DB_TRUNCATE,			"DB_TRUNCATE" },
+		{ DB_TXN_NOSYNC,		"DB_TXN_NOSYNC" },
+		{ DB_USE_ENVIRON,		"DB_USE_ENVIRON" },
+		{ DB_USE_ENVIRON_ROOT,		"DB_USE_ENVIRON_ROOT" },
+		{ 0,				NULL }
+	};
+	static const FN vfn[] = {
+		{ DB_VERB_DEADLOCK,		"DB_VERB_DEADLOCK" },
+		{ DB_VERB_RECOVERY,		"DB_VERB_RECOVERY" },
+		{ DB_VERB_REPLICATION,		"DB_VERB_REPLICATION" },
+		{ DB_VERB_WAITSFOR,		"DB_VERB_WAITSFOR" },
+		{ 0,				NULL }
+	};
+	DB_MSGBUF mb;
+	REGENV *renv;
+	REGINFO *infop;
+	REGION *rp, regs[1024];
+	size_t n;
+	char **p;
+
+	infop = dbenv->reginfo;
+	renv = infop->primary;
+	DB_MSGBUF_INIT(&mb);
+
+	/*
+	 * Lock the database environment while we get copies of the region
+	 * information.
+	 */
+	MUTEX_LOCK(dbenv, &infop->rp->mutex);
+
+	for (n = 0, rp = SH_LIST_FIRST(&renv->regionq, __db_region);
+	    n < sizeof(regs) / sizeof(regs[0]) && rp != NULL;
+	    ++n, rp = SH_LIST_NEXT(rp, q, __db_region)) {
+		regs[n] = *rp;
+		if (LF_ISSET(DB_STAT_CLEAR))
+			MUTEX_CLEAR(&rp->mutex);
+	}
+	if (n > 0)
+		--n;
+	MUTEX_UNLOCK(dbenv, &infop->rp->mutex);
+
+	if (LF_ISSET(DB_STAT_ALL)) {
+		__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+		__db_msg(dbenv, "Per region database environment information:");
+	}
+	while (n > 0) {
+		rp = &regs[--n];
+		__db_msg(dbenv, "%s Region:", __reg_type(rp->type));
+		STAT_LONG("Region ID", rp->id);
+		STAT_LONG("Segment ID", rp->segid);
+		__db_dlbytes(dbenv,
+		    "Size", (u_long)0, (u_long)0, (u_long)rp->size);
+		__db_print_mutex(dbenv, NULL, &rp->mutex,
+		    "The number of region locks that required waiting", flags);
+	}
+
+	__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+	__db_msg(dbenv, "DB_ENV handle information:");
+	STAT_ISSET("Errfile", dbenv->db_errfile);
+	STAT_STRING("Errpfx", dbenv->db_errpfx);
+	STAT_ISSET("Errcall", dbenv->db_errcall);
+	STAT_ISSET("Feedback", dbenv->db_feedback);
+	STAT_ISSET("Panic", dbenv->db_paniccall);
+	STAT_ISSET("Malloc", dbenv->db_malloc);
+	STAT_ISSET("Realloc", dbenv->db_realloc);
+	STAT_ISSET("Free", dbenv->db_free);
+	__db_prflags(dbenv, NULL, dbenv->verbose, vfn, NULL, "\tVerbose flags");
+
+	STAT_ISSET("App private", dbenv->app_private);
+	STAT_ISSET("App dispatch", dbenv->app_dispatch);
+	STAT_STRING("Home", dbenv->db_home);
+	STAT_STRING("Log dir", dbenv->db_log_dir);
+	STAT_STRING("Tmp dir", dbenv->db_tmp_dir);
+	if (dbenv->db_data_dir == NULL)
+		STAT_ISSET("Data dir", dbenv->db_data_dir);
+	else {
+		for (p = dbenv->db_data_dir; *p != NULL; ++p)
+			__db_msgadd(dbenv, &mb, "%s\tData dir", *p);
+		DB_MSGBUF_FLUSH(dbenv, &mb);
+	}
+	STAT_FMT("Mode", "%#o", int, dbenv->db_mode);
+	__db_prflags(dbenv, NULL, dbenv->open_flags, ofn, NULL, "\tOpen flags");
+	STAT_ISSET("Lockfhp", dbenv->lockfhp);
+	STAT_ISSET("Rec tab", dbenv->recover_dtab);
+	STAT_ULONG("Rec tab slots", dbenv->recover_dtab_size);
+	STAT_ISSET("RPC client", dbenv->cl_handle);
+	STAT_LONG("RPC client ID", dbenv->cl_id);
+	STAT_LONG("DB ref count", dbenv->db_ref);
+	STAT_LONG("Shared mem key", dbenv->shm_key);
+	STAT_ULONG("test-and-set spin configuration", dbenv->tas_spins);
+	__db_print_mutex(
+	    dbenv, NULL, dbenv->dblist_mutexp, "DB handle mutex", flags);
+
+	STAT_ISSET("api1 internal", dbenv->api1_internal);
+	STAT_ISSET("api2 internal", dbenv->api2_internal);
+	STAT_ISSET("password", dbenv->passwd);
+	STAT_ISSET("crypto handle", dbenv->crypto_handle);
+	__db_print_mutex(dbenv, NULL, dbenv->mt_mutexp, "MT mutex", flags);
+
+	__db_prflags(dbenv, NULL, dbenv->flags, fn, NULL, "\tFlags");
+
+	return (0);
+}
+
+/*
+ * __db_print_fh --
+ *	Print out a file handle.
+ *
+ * PUBLIC: void __db_print_fh __P((DB_ENV *, DB_FH *, u_int32_t));
+ */
+void
+__db_print_fh(dbenv, fh, flags)
+	DB_ENV *dbenv;
+	DB_FH *fh;
+	u_int32_t flags;
+{
+	static const FN fn[] = {
+		{ DB_FH_NOSYNC,	"DB_FH_NOSYNC" },
+		{ DB_FH_OPENED,	"DB_FH_OPENED" },
+		{ DB_FH_UNLINK,	"DB_FH_UNLINK" },
+		{ 0,		NULL }
+	};
+
+	__db_print_mutex(dbenv, NULL, fh->mutexp, "file-handle.mutex", flags);
+
+	STAT_LONG("file-handle.reference count", fh->ref);
+	STAT_LONG("file-handle.file descriptor", fh->fd);
+	STAT_STRING("file-handle.file name", fh->name);
+
+	STAT_ULONG("file-handle.page number", fh->pgno);
+	STAT_ULONG("file-handle.page size", fh->pgsize);
+	STAT_ULONG("file-handle.page offset", fh->offset);
+
+	__db_prflags(dbenv, NULL, fh->flags, fn, NULL, "\tfile-handle.flags");
+}
+
+/*
+ * __db_print_fileid --
+ *	Print out a file ID.
+ *
+ * PUBLIC: void __db_print_fileid __P((DB_ENV *, u_int8_t *, const char *));
+ */
+void
+__db_print_fileid(dbenv, id, suffix)
+	DB_ENV *dbenv;
+	u_int8_t *id;
+	const char *suffix;
+{
+	DB_MSGBUF mb;
+	int i;
+
+	DB_MSGBUF_INIT(&mb);
+	for (i = 0; i < DB_FILE_ID_LEN; ++i, ++id) {
+		__db_msgadd(dbenv, &mb, "%x", (u_int)*id);
+		if (i < DB_FILE_ID_LEN - 1)
+			__db_msgadd(dbenv, &mb, " ");
+	}
+	if (suffix != NULL)
+		__db_msgadd(dbenv, &mb, "%s", suffix);
+	DB_MSGBUF_FLUSH(dbenv, &mb);
+}
+
+/*
+ * __db_print_mutex --
+ *	Print out mutex statistics.
+ *
+ * PUBLIC: void __db_print_mutex
+ * PUBLIC:    __P((DB_ENV *, DB_MSGBUF *, DB_MUTEX *, const char *, u_int32_t));
+ */
+void
+__db_print_mutex(dbenv, mbp, mutex, suffix, flags)
+	DB_ENV *dbenv;
+	DB_MSGBUF *mbp;
+	DB_MUTEX *mutex;
+	const char *suffix;
+	u_int32_t flags;
+{
+	DB_MSGBUF mb;
+	u_long value;
+	int standalone;
+
+	/* If we don't have a mutex, point that out and return. */
+	if (mutex == NULL) {
+		STAT_ISSET(suffix, mutex);
+		return;
+	}
+
+	if (mbp == NULL) {
+		DB_MSGBUF_INIT(&mb);
+		mbp = &mb;
+		standalone = 1;
+	} else
+		standalone = 0;
+
+	/*
+	 * !!!
+	 * We may not hold the mutex lock -- that's OK, we're only reading
+	 * the statistics.
+	 */
+	if ((value = mutex->mutex_set_wait) < 10000000)
+		__db_msgadd(dbenv, mbp, "%lu", value);
+	else
+		__db_msgadd(dbenv, mbp, "%luM", value / 1000000);
+
+	/*
+	 * If standalone, append the mutex percent and the locker information
+	 * after the suffix line.  Otherwise, append it after the counter.
+	 *
+	 * The setting of "suffix" tracks "standalone" -- if standalone, expect
+	 * a suffix and prefix it with a <tab>, otherwise, it's optional.  This
+	 * isn't a design, it's just the semantics we happen to need right now.
+	 */
+	if (standalone) {
+		if (suffix == NULL)			/* Defense. */
+			suffix = "";
+
+		__db_msgadd(dbenv, &mb, "\t%s (%d%%", suffix,
+		    DB_PCT(mutex->mutex_set_wait,
+		    mutex->mutex_set_wait + mutex->mutex_set_nowait));
+#ifdef DIAGNOSTIC
+#ifdef HAVE_MUTEX_THREADS
+		if (mutex->locked != 0)
+			__db_msgadd(dbenv, &mb, "/%lu", (u_long)mutex->locked);
+#else
+		if (mutex->pid != 0)
+			__db_msgadd(dbenv, &mb, "/%lu", (u_long)mutex->pid);
+#endif
+#endif
+		__db_msgadd(dbenv, &mb, ")");
+
+		DB_MSGBUF_FLUSH(dbenv, mbp);
+	} else {
+		__db_msgadd(dbenv, mbp, "/%d%%", DB_PCT(mutex->mutex_set_wait,
+		    mutex->mutex_set_wait + mutex->mutex_set_nowait));
+#ifdef DIAGNOSTIC
+#ifdef HAVE_MUTEX_THREADS
+		if (mutex->locked != 0)
+			__db_msgadd(dbenv, &mb, "/%lu", (u_long)mutex->locked);
+#else
+		if (mutex->pid != 0)
+			__db_msgadd(dbenv, &mb, "/%lu", (u_long)mutex->pid);
+#endif
+#endif
+		if (suffix != NULL)
+			__db_msgadd(dbenv, mbp, "%s", suffix);
+	}
+
+	if (LF_ISSET(DB_STAT_CLEAR))
+		MUTEX_CLEAR(mutex);
+}
+
+/*
+ * __db_dl --
+ *	Display a big value.
+ *
+ * PUBLIC: void __db_dl __P((DB_ENV *, const char *, u_long));
+ */
+void
+__db_dl(dbenv, msg, value)
+	DB_ENV *dbenv;
+	const char *msg;
+	u_long value;
+{
+	/*
+	 * Two formats: if less than 10 million, display as the number, if
+	 * greater than 10 million display as ###M.
+	 */
+	if (value < 10000000)
+		__db_msg(dbenv, "%lu\t%s", value, msg);
+	else
+		__db_msg(dbenv, "%luM\t%s (%lu)", value / 1000000, msg, value);
+}
+
+/*
+ * __db_dl_pct --
+ *	Display a big value, and related percentage.
+ *
+ * PUBLIC: void __db_dl_pct
+ * PUBLIC:          __P((DB_ENV *, const char *, u_long, int, const char *));
+ */
+void
+__db_dl_pct(dbenv, msg, value, pct, tag)
+	DB_ENV *dbenv;
+	const char *msg, *tag;
+	u_long value;
+	int pct;
+{
+	DB_MSGBUF mb;
+
+	DB_MSGBUF_INIT(&mb);
+
+	/*
+	 * Two formats: if less than 10 million, display as the number, if
+	 * greater than 10 million display as ###M.
+	 */
+	if (value < 10000000)
+		__db_msgadd(dbenv, &mb, "%lu\t%s", value, msg);
+	else
+		__db_msgadd(dbenv, &mb, "%luM\t%s", value / 1000000, msg);
+	if (tag == NULL)
+		__db_msgadd(dbenv, &mb, " (%d%%)", pct);
+	else
+		__db_msgadd(dbenv, &mb, " (%d%% %s)", pct, tag);
+
+	DB_MSGBUF_FLUSH(dbenv, &mb);
+}
+
+/*
+ * __db_dlbytes --
+ *	Display a big number of bytes.
+ *
+ * PUBLIC: void __db_dlbytes
+ * PUBLIC:     __P((DB_ENV *, const char *, u_long, u_long, u_long));
+ */
+void
+__db_dlbytes(dbenv, msg, gbytes, mbytes, bytes)
+	DB_ENV *dbenv;
+	const char *msg;
+	u_long gbytes, mbytes, bytes;
+{
+	DB_MSGBUF mb;
+	const char *sep;
+
+	DB_MSGBUF_INIT(&mb);
+
+	/* Normalize the values. */
+	while (bytes >= MEGABYTE) {
+		++mbytes;
+		bytes -= MEGABYTE;
+	}
+	while (mbytes >= GIGABYTE / MEGABYTE) {
+		++gbytes;
+		mbytes -= GIGABYTE / MEGABYTE;
+	}
+
+	if (gbytes == 0 && mbytes == 0 && bytes == 0)
+		__db_msgadd(dbenv, &mb, "0");
+	else {
+		sep = "";
+		if (gbytes > 0) {
+			__db_msgadd(dbenv, &mb, "%luGB", gbytes);
+			sep = " ";
+		}
+		if (mbytes > 0) {
+			__db_msgadd(dbenv, &mb, "%s%luMB", sep, mbytes);
+			sep = " ";
+		}
+		if (bytes >= 1024) {
+			__db_msgadd(dbenv, &mb, "%s%luKB", sep, bytes / 1024);
+			bytes %= 1024;
+			sep = " ";
+		}
+		if (bytes > 0)
+			__db_msgadd(dbenv, &mb, "%s%luB", sep, bytes);
+	}
+
+	__db_msgadd(dbenv, &mb, "\t%s", msg);
+
+	DB_MSGBUF_FLUSH(dbenv, &mb);
+}
+
+/*
+ * __db_print_reginfo --
+ *	Print out underlying shared region information.
+ *
+ * PUBLIC: void __db_print_reginfo __P((DB_ENV *, REGINFO *, const char *));
+ */
+void
+__db_print_reginfo(dbenv, infop, s)
+	DB_ENV *dbenv;
+	REGINFO *infop;
+	const char *s;
+{
+	static const FN fn[] = {
+		{ REGION_CREATE,	"REGION_CREATE" },
+		{ REGION_CREATE_OK,	"REGION_CREATE_OK" },
+		{ REGION_JOIN_OK,	"REGION_JOIN_OK" },
+		{ 0,			NULL }
+	};
+
+	__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+	__db_msg(dbenv, "%s REGINFO information:",  s);
+	STAT_STRING("Region type", __reg_type(infop->type));
+	STAT_ULONG("Region ID", infop->id);
+	STAT_STRING("Region name", infop->name);
+	STAT_HEX("Original region address", infop->addr_orig);
+	STAT_HEX("Region address", infop->addr);
+	STAT_HEX("Region primary address", infop->primary);
+	STAT_ULONG("Region maximum allocation", infop->max_alloc);
+	STAT_ULONG("Region allocated", infop->max_alloc);
+
+	__db_prflags(dbenv, NULL, infop->flags, fn, NULL, "\tRegion flags");
+}
+
+/*
+ * __reg_type --
+ *	Return the region type string.
+ */
+static const char *
+__reg_type(t)
+	reg_type_t t;
+{
+	switch (t) {
+	case REGION_TYPE_ENV:
+		return ("Environment");
+	case REGION_TYPE_LOCK:
+		return ("Lock");
+	case REGION_TYPE_LOG:
+		return ("Log");
+	case REGION_TYPE_MPOOL:
+		return ("Mpool");
+	case REGION_TYPE_MUTEX:
+		return ("Mutex");
+	case REGION_TYPE_TXN:
+		return ("Transaction");
+	case INVALID_REGION_TYPE:
+		return ("Invalid");
+	}
+	return ("Unknown");
+}
+
+#else /* !HAVE_STATISTICS */
+
+/*
+ * __db_stat_not_built --
+ *	Common error routine when library not built with statistics.
+ *
+ * PUBLIC: int __db_stat_not_built __P((DB_ENV *));
+ */
+int
+__db_stat_not_built(dbenv)
+	DB_ENV *dbenv;
+{
+	__db_err(dbenv, "Library build did not include statistics support");
+	return (DB_OPNOTSUP);
+}
+
+int
+__dbenv_stat_print_pp(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	COMPQUIET(flags, 0);
+
+	return (__db_stat_not_built(dbenv));
+}
+#endif
diff --git a/storage/bdb/fileops/fileops.src b/storage/bdb/fileops/fileops.src
index 1fd39dc3c45f87e2f3c7da9a558d845280a1c343..a77b5d5c477836494f81d7ab1ea3e2ad88c177a1 100644
--- a/storage/bdb/fileops/fileops.src
+++ b/storage/bdb/fileops/fileops.src
@@ -1,17 +1,15 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
+ * Copyright (c) 2001-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: fileops.src,v 1.8 2002/04/06 18:25:55 bostic Exp $
+ * $Id: fileops.src,v 1.13 2004/06/17 17:35:20 bostic Exp $
  */
 
 PREFIX	__fop
 DBPRIVATE
 
-INCLUDE	#include "db_config.h"
-INCLUDE
 INCLUDE #ifndef NO_SYSTEM_INCLUDES
 INCLUDE #include <sys/types.h>
 INCLUDE
@@ -25,7 +23,6 @@ INCLUDE #include "dbinc/db_page.h"
 INCLUDE #include "dbinc/db_dispatch.h"
 INCLUDE #include "dbinc/db_am.h"
 INCLUDE #include "dbinc/log.h"
-INCLUDE #include "dbinc/rep.h"
 INCLUDE #include "dbinc/txn.h"
 INCLUDE #include "dbinc/fop.h"
 INCLUDE
@@ -60,7 +57,9 @@ END
  *
  * name: file containing the page.
  * appname: indicates if the name needs to go through __db_appname
- * offset: offset in the file.
+ * pgsize: page size.
+ * pageno: page number in the file.
+ * offset: offset on the page.
  * page: the actual meta-data page.
  * flag: non-0 indicates that this is a tempfile, so we needn't undo
  *	these modifications (we'll toss the file).
@@ -68,6 +67,8 @@ END
 BEGIN write	145
 DBT	name		DBT		s
 ARG	appname		u_int32_t	lu
+ARG	pgsize		u_int32_t	lu
+ARG	pageno		db_pgno_t	lu
 ARG	offset		u_int32_t	lu
 PGDBT	page		DBT		s
 ARG	flag		u_int32_t	lu
diff --git a/storage/bdb/fileops/fop_basic.c b/storage/bdb/fileops/fop_basic.c
index 08160ab2e1a0ca6eee666470e66d7b9e3cc703a7..36a958e950ad9434745270cbd5a2528d479dba35 100644
--- a/storage/bdb/fileops/fop_basic.c
+++ b/storage/bdb/fileops/fop_basic.c
@@ -1,25 +1,25 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
+ * Copyright (c) 2001-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: fop_basic.c,v 1.32 2004/11/15 20:04:50 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: fop_basic.c,v 1.23 2002/08/11 02:11:23 margo Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <string.h>
 #include <sys/types.h>
 #endif
 
 #include "db_int.h"
-#include "dbinc/log.h"
 #include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
 #include "dbinc/fop.h"
+#include "dbinc/log.h"
+#include "dbinc/mp.h"
 #include "dbinc/txn.h"
 #include "dbinc/db_am.h"
 
@@ -36,59 +36,53 @@ static const char revid[] = "$Id: fop_basic.c,v 1.23 2002/08/11 02:11:23 margo E
  * else you wish to store in a file system object.
  *
  * PUBLIC: int __fop_create __P((DB_ENV *,
- * PUBLIC:     DB_TXN *, DB_FH *, const char *, APPNAME, int));
+ * PUBLIC:     DB_TXN *, DB_FH **, const char *, APPNAME, int, u_int32_t));
  */
 int
-__fop_create(dbenv, txn, fhp, name, appname, mode)
+__fop_create(dbenv, txn, fhpp, name, appname, mode, flags)
 	DB_ENV *dbenv;
 	DB_TXN *txn;
-	DB_FH *fhp;
+	DB_FH **fhpp;
 	const char *name;
 	APPNAME appname;
 	int mode;
+	u_int32_t flags;
 {
-	DB_FH fh;
+	DB_FH *fhp;
 	DB_LSN lsn;
 	DBT data;
+	int ret;
 	char *real_name;
-	int do_close, ret;
 
-	ret = 0;
 	real_name = NULL;
 
-	if (fhp != NULL)
-		do_close = 0;
-	else {
-		fhp = &fh;
-		memset(fhp, 0, sizeof(fh));
-		do_close = 1;
-	}
+	if ((ret =
+	    __db_appname(dbenv, appname, name, 0, NULL, &real_name)) != 0)
+		return (ret);
 
 	if (mode == 0)
 		mode = __db_omode("rw----");
 
-	if ((ret =
-	    __db_appname(dbenv, appname, name, 0, NULL, &real_name)) != 0)
-		goto err;
-
 	if (DBENV_LOGGING(dbenv)) {
 		memset(&data, 0, sizeof(data));
 		data.data = (void *)name;
 		data.size = (u_int32_t)strlen(name) + 1;
-		if ((ret = __fop_create_log(dbenv,
-		    txn, &lsn, DB_FLUSH, &data, (u_int32_t)appname, mode)) != 0)
+		if ((ret = __fop_create_log(dbenv, txn, &lsn,
+		    flags | DB_FLUSH, &data, (u_int32_t)appname, mode)) != 0)
 			goto err;
 	}
 
 	DB_ENV_TEST_RECOVERY(dbenv, DB_TEST_POSTLOG, ret, name);
 
-	ret =
-	    __os_open(dbenv, real_name, DB_OSO_CREATE | DB_OSO_EXCL, mode, fhp);
+	if (fhpp == NULL)
+		fhpp = &fhp;
+	ret = __os_open(
+	    dbenv, real_name, DB_OSO_CREATE | DB_OSO_EXCL, mode, fhpp);
 
 err:
 DB_TEST_RECOVERY_LABEL
-	if (do_close && F_ISSET(fhp, DB_FH_VALID))
-		__os_closehandle(dbenv, fhp);
+	if (fhpp == &fhp && fhp != NULL)
+		(void)__os_closehandle(dbenv, fhp);
 	if (real_name != NULL)
 		__os_free(dbenv, real_name);
 	return (ret);
@@ -99,15 +93,16 @@ DB_TEST_RECOVERY_LABEL
  *	Remove a file system object.
  *
  * PUBLIC: int __fop_remove __P((DB_ENV *,
- * PUBLIC:     DB_TXN *, u_int8_t *, const char *, APPNAME));
+ * PUBLIC:     DB_TXN *, u_int8_t *, const char *, APPNAME, u_int32_t));
  */
 int
-__fop_remove(dbenv, txn, fileid, name, appname)
+__fop_remove(dbenv, txn, fileid, name, appname, flags)
 	DB_ENV *dbenv;
 	DB_TXN *txn;
 	u_int8_t *fileid;
 	const char *name;
 	APPNAME appname;
+	u_int32_t flags;
 {
 	DB_LSN lsn;
 	DBT fdbt, ndbt;
@@ -121,7 +116,7 @@ __fop_remove(dbenv, txn, fileid, name, appname)
 		goto err;
 
 	if (txn == NULL) {
-		if (fileid != NULL && (ret = dbenv->memp_nameop(
+		if (fileid != NULL && (ret = __memp_nameop(
 		    dbenv, fileid, NULL, real_name, NULL)) != 0)
 			goto err;
 	} else {
@@ -133,7 +128,7 @@ __fop_remove(dbenv, txn, fileid, name, appname)
 			ndbt.data = (void *)name;
 			ndbt.size = (u_int32_t)strlen(name) + 1;
 			if ((ret = __fop_remove_log(dbenv,
-			    txn, &lsn, 0, &ndbt, &fdbt, appname)) != 0)
+			    txn, &lsn, flags, &ndbt, &fdbt, appname)) != 0)
 				goto err;
 		}
 		ret = __txn_remevent(dbenv, txn, real_name, fileid);
@@ -157,34 +152,38 @@ err:	if (real_name != NULL)
  * handling, then we'll have to zero out regions on abort (and possibly
  * log the before image of the data in the log record).
  *
- * PUBLIC: int __fop_write __P((DB_ENV *, DB_TXN *, const char *, APPNAME,
- * PUBLIC:     DB_FH *, u_int32_t, u_int8_t *, u_int32_t, u_int32_t));
+ * PUBLIC: int __fop_write __P((DB_ENV *,
+ * PUBLIC:     DB_TXN *, const char *, APPNAME, DB_FH *, u_int32_t, db_pgno_t,
+ * PUBLIC:     u_int32_t, u_int8_t *, u_int32_t, u_int32_t, u_int32_t));
  */
 int
-__fop_write(dbenv, txn, name, appname, fhp, off, buf, size, istmp)
+__fop_write(dbenv,
+    txn, name, appname, fhp, pgsize, pageno, off, buf, size, istmp, flags)
 	DB_ENV *dbenv;
 	DB_TXN *txn;
 	const char *name;
 	APPNAME appname;
 	DB_FH *fhp;
+	u_int32_t pgsize;
+	db_pgno_t pageno;
 	u_int32_t off;
 	u_int8_t *buf;
-	u_int32_t size, istmp;
+	u_int32_t size, istmp, flags;
 {
-	DB_FH fh;
 	DB_LSN lsn;
 	DBT data, namedbt;
-	char *real_name;
-	int ret, t_ret, we_opened;
 	size_t nbytes;
+	int local_open, ret, t_ret;
+	char *real_name;
+
+	DB_ASSERT(istmp != 0);
 
-	ret = 0;
-	we_opened = 0;
+	ret = local_open = 0;
 	real_name = NULL;
 
 	if ((ret =
 	    __db_appname(dbenv, appname, name, 0, NULL, &real_name)) != 0)
-		goto err;
+		return (ret);
 
 	if (DBENV_LOGGING(dbenv)) {
 		memset(&data, 0, sizeof(data));
@@ -193,30 +192,29 @@ __fop_write(dbenv, txn, name, appname, fhp, off, buf, size, istmp)
 		memset(&namedbt, 0, sizeof(namedbt));
 		namedbt.data = (void *)name;
 		namedbt.size = (u_int32_t)strlen(name) + 1;
-		if ((ret = __fop_write_log(dbenv,
-		    txn, &lsn, 0, &namedbt, appname, off, &data, istmp)) != 0)
+		if ((ret = __fop_write_log(dbenv, txn, &lsn, flags,
+		    &namedbt, appname, pgsize, pageno, off, &data, istmp)) != 0)
 			goto err;
 	}
 
 	if (fhp == NULL) {
 		/* File isn't open; we need to reopen it. */
-		if ((ret = __os_open(dbenv, real_name, 0, 0, &fh)) != 0)
+		if ((ret = __os_open(dbenv, real_name, 0, 0, &fhp)) != 0)
 			goto err;
-		fhp = &fh;
-		we_opened = 1;
-	} else
-		we_opened = 0;
+		local_open = 1;
+	}
 
 	/* Seek to offset. */
-	if ((ret = __os_seek(dbenv, fhp, 0, 0, off, 0, DB_OS_SEEK_SET)) != 0)
+	if ((ret = __os_seek(dbenv,
+	    fhp, pgsize, pageno, off, 0, DB_OS_SEEK_SET)) != 0)
 		goto err;
 
 	/* Now do the write. */
 	if ((ret = __os_write(dbenv, fhp, buf, size, &nbytes)) != 0)
 		goto err;
 
-err:	if (we_opened)
-		if ((t_ret = __os_closehandle(dbenv, fhp)) != 0 && ret == 0)
+err:	if (local_open &&
+	    (t_ret = __os_closehandle(dbenv, fhp)) != 0 && ret == 0)
 			ret = t_ret;
 
 	if (real_name != NULL)
@@ -228,23 +226,25 @@ err:	if (we_opened)
  * __fop_rename --
  *	Change a file's name.
  *
- * PUBLIC: int __fop_rename __P((DB_ENV *,
- * PUBLIC:      DB_TXN *, const char *, const char *, u_int8_t *, APPNAME));
+ * PUBLIC: int __fop_rename __P((DB_ENV *, DB_TXN *,
+ * PUBLIC:      const char *, const char *, u_int8_t *, APPNAME, u_int32_t));
  */
 int
-__fop_rename(dbenv, txn, oldname, newname, fid, appname)
+__fop_rename(dbenv, txn, oldname, newname, fid, appname, flags)
 	DB_ENV *dbenv;
 	DB_TXN *txn;
 	const char *oldname;
 	const char *newname;
 	u_int8_t *fid;
 	APPNAME appname;
+	u_int32_t flags;
 {
 	DB_LSN lsn;
 	DBT fiddbt, new, old;
 	int ret;
 	char *n, *o;
 
+	o = n = NULL;
 	if ((ret = __db_appname(dbenv, appname, oldname, 0, NULL, &o)) != 0)
 		goto err;
 	if ((ret = __db_appname(dbenv, appname, newname, 0, NULL, &n)) != 0)
@@ -260,16 +260,16 @@ __fop_rename(dbenv, txn, oldname, newname, fid, appname)
 		new.size = (u_int32_t)strlen(newname) + 1;
 		fiddbt.data = fid;
 		fiddbt.size = DB_FILE_ID_LEN;
-		if ((ret = __fop_rename_log(dbenv, txn, &lsn,
-		    DB_FLUSH, &old, &new, &fiddbt, (u_int32_t)appname)) != 0)
+		if ((ret = __fop_rename_log(dbenv, txn, &lsn, flags | DB_FLUSH,
+		    &old, &new, &fiddbt, (u_int32_t)appname)) != 0)
 			goto err;
 	}
 
-	ret = dbenv->memp_nameop(dbenv, fid, newname, o, n);
+	ret = __memp_nameop(dbenv, fid, newname, o, n);
 
-err:	if (o != oldname)
+err:	if (o != NULL)
 		__os_free(dbenv, o);
-	if (n != newname)
+	if (n != NULL)
 		__os_free(dbenv, n);
 	return (ret);
 }
diff --git a/storage/bdb/fileops/fop_rec.c b/storage/bdb/fileops/fop_rec.c
index 67720e01d137bfeaff729feda5b8340342d1ac6e..a9326d53289f9e8ce1b5d1111369816cd2877208 100644
--- a/storage/bdb/fileops/fop_rec.c
+++ b/storage/bdb/fileops/fop_rec.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
+ * Copyright (c) 2001-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: fop_rec.c,v 1.31 2004/09/22 03:45:25 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: fop_rec.c,v 1.18 2002/08/14 20:27:01 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -19,8 +17,10 @@ static const char revid[] = "$Id: fop_rec.c,v 1.18 2002/08/14 20:27:01 bostic Ex
 
 #include "db_int.h"
 #include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
 #include "dbinc/fop.h"
 #include "dbinc/db_am.h"
+#include "dbinc/mp.h"
 #include "dbinc/txn.h"
 
 /*
@@ -38,7 +38,7 @@ __fop_create_recover(dbenv, dbtp, lsnp, op, info)
 	db_recops op;
 	void *info;
 {
-	DB_FH fh;
+	DB_FH *fhp;
 	__fop_create_args *argp;
 	char *real_name;
 	int ret;
@@ -54,10 +54,13 @@ __fop_create_recover(dbenv, dbtp, lsnp, op, info)
 
 	if (DB_UNDO(op))
 		(void)__os_unlink(dbenv, real_name);
-	else if (DB_REDO(op))
+	else if (DB_REDO(op)) {
 		if ((ret = __os_open(dbenv, real_name,
-		    DB_OSO_CREATE | DB_OSO_EXCL, argp->mode, &fh)) == 0)
-			__os_closehandle(dbenv, &fh);
+		    DB_OSO_CREATE | DB_OSO_EXCL, argp->mode, &fhp)) == 0)
+			(void)__os_closehandle(dbenv, fhp);
+		else
+			goto out;
+	}
 
 	*lsnp = argp->prev_lsn;
 
@@ -95,9 +98,10 @@ __fop_remove_recover(dbenv, dbtp, lsnp, op, info)
 	    (const char *)argp->name.data, 0, NULL, &real_name)) != 0)
 		goto out;
 
-	if (DB_REDO(op) && (ret = dbenv->memp_nameop(dbenv,
-	    (u_int8_t *)argp->fid.data, NULL, real_name, NULL)) != 0)
-		goto out;
+	/* Its ok if the file is not there. */
+	if (DB_REDO(op))
+		(void)__memp_nameop(dbenv,
+		    (u_int8_t *)argp->fid.data, NULL, real_name, NULL);
 
 	*lsnp = argp->prev_lsn;
 out:	if (real_name != NULL)
@@ -127,14 +131,17 @@ __fop_write_recover(dbenv, dbtp, lsnp, op, info)
 	REC_PRINT(__fop_write_print);
 	REC_NOOP_INTRO(__fop_write_read);
 
+	ret = 0;
 	if (DB_UNDO(op))
 		DB_ASSERT(argp->flag != 0);
 	else if (DB_REDO(op))
 		ret = __fop_write(dbenv,
-		    argp->txnid, argp->name.data, argp->appname, NULL,
-		    argp->offset, argp->page.data, argp->page.size, argp->flag);
+		    argp->txnid, argp->name.data, argp->appname,
+		    NULL, argp->pgsize, argp->pageno, argp->offset,
+		    argp->page.data, argp->page.size, argp->flag, 0);
 
-	*lsnp = argp->prev_lsn;
+	if (ret == 0)
+		*lsnp = argp->prev_lsn;
 	REC_NOOP_CLOSE;
 }
 
@@ -154,6 +161,7 @@ __fop_rename_recover(dbenv, dbtp, lsnp, op, info)
 	void *info;
 {
 	__fop_rename_args *argp;
+	DB_FH *fhp;
 	DBMETA *meta;
 	char *real_new, *real_old, *src;
 	int ret;
@@ -162,6 +170,7 @@ __fop_rename_recover(dbenv, dbtp, lsnp, op, info)
 	real_new = NULL;
 	real_old = NULL;
 	ret = 0;
+	fhp = NULL;
 	meta = (DBMETA *)&mbuf[0];
 
 	COMPQUIET(info, NULL);
@@ -189,20 +198,24 @@ __fop_rename_recover(dbenv, dbtp, lsnp, op, info)
 		 * way, shape or form, incorrect, so that we should not restore
 		 * it.
 		 */
-		if (__fop_read_meta(
-		    dbenv, src, mbuf, DBMETASIZE, NULL, 1, 0) != 0)
+		if (__os_open(dbenv, src, 0, 0, &fhp) != 0)
+			goto done;
+		if (__fop_read_meta(dbenv,
+		    src, mbuf, DBMETASIZE, fhp, 1, NULL) != 0)
 			goto done;
 		if (__db_chk_meta(dbenv, NULL, meta, 1) != 0)
 			goto done;
 		if (memcmp(argp->fileid.data, meta->uid, DB_FILE_ID_LEN) != 0)
 			goto done;
+		(void)__os_closehandle(dbenv, fhp);
+		fhp = NULL;
 	}
 
 	if (DB_UNDO(op))
-		(void)dbenv->memp_nameop(dbenv, fileid,
+		(void)__memp_nameop(dbenv, fileid,
 		    (const char *)argp->oldname.data, real_new, real_old);
 	if (DB_REDO(op))
-		(void)dbenv->memp_nameop(dbenv, fileid,
+		(void)__memp_nameop(dbenv, fileid,
 		    (const char *)argp->newname.data, real_old, real_new);
 
 done:	*lsnp = argp->prev_lsn;
@@ -210,6 +223,8 @@ out:	if (real_new != NULL)
 		__os_free(dbenv, real_new);
 	if (real_old != NULL)
 		__os_free(dbenv, real_old);
+	if (fhp != NULL)
+		(void)__os_closehandle(dbenv, fhp);
 
 	REC_NOOP_CLOSE;
 }
@@ -235,13 +250,16 @@ __fop_file_remove_recover(dbenv, dbtp, lsnp, op, info)
 {
 	__fop_file_remove_args *argp;
 	DBMETA *meta;
+	DB_FH *fhp;
 	char *real_name;
 	int is_real, is_tmp, ret;
+	size_t len;
 	u_int8_t mbuf[DBMETASIZE];
-	u_int32_t cstat;
+	u_int32_t cstat, ret_stat;
 
-	real_name = NULL;
+	fhp = NULL;
 	is_real = is_tmp = 0;
+	real_name = NULL;
 	meta = (DBMETA *)&mbuf[0];
 	REC_PRINT(__fop_file_remove_print);
 	REC_NOOP_INTRO(__fop_file_remove_read);
@@ -259,8 +277,18 @@ __fop_file_remove_recover(dbenv, dbtp, lsnp, op, info)
 		goto out;
 
 	/* Verify that we are manipulating the correct file.  */
-	if ((ret = __fop_read_meta(dbenv,
-	    real_name, mbuf, DBMETASIZE, NULL, 1, 0)) != 0) {
+	len = 0;
+	if (__os_open(dbenv, real_name, 0, 0, &fhp) != 0 ||
+	    (ret = __fop_read_meta(dbenv, real_name,
+	    mbuf, DBMETASIZE, fhp, 1, &len)) != 0) {
+		/*
+		 * If len is non-zero, then the file exists and has something
+		 * in it, but that something isn't a full meta-data page, so
+		 * this is very bad.  Bail out!
+		 */
+		if (len != 0)
+			goto out;
+
 		/* File does not exist. */
 		cstat = TXN_EXPECTED;
 	} else {
@@ -281,20 +309,23 @@ __fop_file_remove_recover(dbenv, dbtp, lsnp, op, info)
 			/* File exists and is the one that we were removing. */
 			cstat = TXN_COMMIT;
 	}
+	if (fhp != NULL) {
+		(void)__os_closehandle(dbenv, fhp);
+		fhp = NULL;
+	}
 
 	if (DB_UNDO(op)) {
 		/* On the backward pass, we leave a note for the child txn. */
 		if ((ret = __db_txnlist_update(dbenv,
-		    info, argp->child, cstat, NULL)) == DB_NOTFOUND)
-			ret = __db_txnlist_add(dbenv,
-			    info, argp->child, cstat, NULL);
+		    info, argp->child, cstat, NULL, &ret_stat, 1)) != 0)
+			goto out;
 	} else if (DB_REDO(op)) {
 		/*
 		 * On the forward pass, check if someone recreated the
 		 * file while we weren't looking.
 		 */
 		if (cstat == TXN_COMMIT)
-			(void)dbenv->memp_nameop(dbenv,
+			(void)__memp_nameop(dbenv,
 			    is_real ? argp->real_fid.data : argp->tmp_fid.data,
 			    NULL, real_name, NULL);
 	}
@@ -304,5 +335,7 @@ done:	*lsnp = argp->prev_lsn;
 
 out:	if (real_name != NULL)
 		__os_free(dbenv, real_name);
+	if (fhp != NULL)
+		(void)__os_closehandle(dbenv, fhp);
 	REC_NOOP_CLOSE;
 }
diff --git a/storage/bdb/fileops/fop_util.c b/storage/bdb/fileops/fop_util.c
index ea6d86ab08d0c85d04357ef52c89c41a29a794ce..564dc4a36b1721e54a1de3ec592272817ec79704 100644
--- a/storage/bdb/fileops/fop_util.c
+++ b/storage/bdb/fileops/fop_util.c
@@ -1,20 +1,17 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
+ * Copyright (c) 2001-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: fop_util.c,v 1.104 2004/09/24 00:43:18 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: fop_util.c,v 1.52 2002/09/10 02:41:42 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
-#include <stddef.h>
 #include <stdlib.h>
 #include <string.h>
 #endif
@@ -25,6 +22,7 @@ static const char revid[] = "$Id: fop_util.c,v 1.52 2002/09/10 02:41:42 bostic E
 #include "dbinc/db_am.h"
 #include "dbinc/fop.h"
 #include "dbinc/lock.h"
+#include "dbinc/mp.h"
 #include "dbinc/log.h"
 #include "dbinc/txn.h"
 
@@ -34,56 +32,67 @@ static int __fop_set_pgsize __P((DB *, DB_FH *, const char *));
  * Acquire the environment meta-data lock.  The parameters are the
  * environment (ENV), the locker id to use in acquiring the lock (ID)
  * and a pointer to a DB_LOCK.
+ *
+ * !!!
+ * Turn off locking for Critical Path.  The application must do its own
+ * synchronization of open/create.  Two threads creating and opening a
+ * file at the same time may have unpredictable results.
  */
+#ifdef CRITICALPATH_10266
+#define	GET_ENVLOCK(ENV, ID, L) (0)
+#else
 #define	GET_ENVLOCK(ENV, ID, L) do {					\
 	DBT __dbt;							\
 	u_int32_t __lockval;						\
 									\
 	if (LOCKING_ON((ENV))) {					\
-		__lockval = 0;						\
+		__lockval = 1;						\
 		__dbt.data = &__lockval;				\
 		__dbt.size = sizeof(__lockval);				\
-		if ((ret = (ENV)->lock_get((ENV), (ID),			\
+		if ((ret = __lock_get((ENV), (ID),			\
 		    0, &__dbt, DB_LOCK_WRITE, (L))) != 0)		\
 			goto err;					\
 	}								\
 } while (0)
-
-#define	REL_ENVLOCK(ENV, L)						\
-	(!LOCK_ISSET(*(L)) ? 0 : (ENV)->lock_put((ENV), (L)))
+#endif
 
 /*
- * If our caller is doing fcntl(2) locking, then we can't close it
- * because that would discard the caller's lock.  Otherwise, close
- * the handle.
+ * If we open a file handle and our caller is doing fcntl(2) locking,
+ * we can't close the handle because that would discard the caller's
+ * lock. Save it until we close or refresh the DB handle.
  */
 #define	CLOSE_HANDLE(D, F) {						\
-	if (F_ISSET((F), DB_FH_VALID)) {				\
+	if ((F) != NULL) {						\
 		if (LF_ISSET(DB_FCNTL_LOCKING))				\
 			(D)->saved_open_fhp = (F);			\
-		else if ((ret = __os_closehandle((D)->dbenv,(F))) != 0)	\
+		else if ((t_ret =					\
+		    __os_closehandle((D)->dbenv, (F))) != 0) {		\
+			if (ret == 0)					\
+				ret = t_ret;				\
 			goto err;					\
+		}							\
+		(F) = NULL;						\
 	}								\
 }
 
 /*
  * __fop_lock_handle --
  *
- * Get the handle lock for a database.  If the envlock is specified,
- * do this as a lock_vec call that releases the enviroment lock before
- * acquiring the handle lock.
+ * Get the handle lock for a database.  If the envlock is specified, do this
+ * as a lock_vec call that releases the environment lock before acquiring the
+ * handle lock.
  *
  * PUBLIC: int __fop_lock_handle __P((DB_ENV *,
  * PUBLIC:     DB *, u_int32_t, db_lockmode_t, DB_LOCK *, u_int32_t));
  *
  */
 int
-__fop_lock_handle(dbenv, dbp, locker, mode, elock, flags)
+__fop_lock_handle(dbenv, dbp, locker, mode, elockp, flags)
 	DB_ENV *dbenv;
 	DB *dbp;
 	u_int32_t locker;
 	db_lockmode_t mode;
-	DB_LOCK *elock;
+	DB_LOCK *elockp;
 	u_int32_t flags;
 {
 	DBT fileobj;
@@ -91,20 +100,18 @@ __fop_lock_handle(dbenv, dbp, locker, mode, elock, flags)
 	DB_LOCK_ILOCK lock_desc;
 	int ret;
 
-	if (!LOCKING_ON(dbenv) || F_ISSET(dbp, DB_AM_COMPENSATE))
+	if (!LOCKING_ON(dbenv) ||
+	    F_ISSET(dbp, DB_AM_COMPENSATE | DB_AM_RECOVER))
 		return (0);
 
 	/*
 	 * If we are in recovery, the only locking we should be
 	 * doing is on the global environment.
 	 */
-	if (IS_RECOVERING(dbenv)) {
-		if (elock != NULL)
-			REL_ENVLOCK(dbenv, elock);
-		return (0);
-	}
+	if (IS_RECOVERING(dbenv))
+		return (elockp == NULL ? 0 : __ENV_LPUT(dbenv, *elockp, 0));
 
-	memcpy(&lock_desc.fileid, &dbp->fileid, DB_FILE_ID_LEN);
+	memcpy(lock_desc.fileid, dbp->fileid, DB_FILE_ID_LEN);
 	lock_desc.pgno = dbp->meta_pgno;
 	lock_desc.type = DB_HANDLE_LOCK;
 
@@ -112,12 +119,12 @@ __fop_lock_handle(dbenv, dbp, locker, mode, elock, flags)
 	fileobj.data = &lock_desc;
 	fileobj.size = sizeof(lock_desc);
 	DB_TEST_SUBLOCKS(dbenv, flags);
-	if (elock == NULL)
-		ret = dbenv->lock_get(dbenv, locker,
+	if (elockp == NULL)
+		ret = __lock_get(dbenv, locker,
 		    flags, &fileobj, mode, &dbp->handle_lock);
 	else {
 		reqs[0].op = DB_LOCK_PUT;
-		reqs[0].lock = *elock;
+		reqs[0].lock = *elockp;
 		reqs[1].op = DB_LOCK_GET;
 		reqs[1].mode = mode;
 		reqs[1].obj = &fileobj;
@@ -125,9 +132,9 @@ __fop_lock_handle(dbenv, dbp, locker, mode, elock, flags)
 		if ((ret = __lock_vec(dbenv,
 		    locker, flags, reqs, 2, &ereq)) == 0) {
 			dbp->handle_lock = reqs[1].lock;
-			LOCK_INIT(*elock);
+			LOCK_INIT(*elockp);
 		} else if (ereq != reqs)
-			LOCK_INIT(*elock);
+			LOCK_INIT(*elockp);
 	}
 
 	dbp->cur_lid = locker;
@@ -153,6 +160,30 @@ __fop_lock_handle(dbenv, dbp, locker, mode, elock, flags)
  * buffer cache or obtaining a lock (we use this unique fileid to lock
  * as well as to identify like files in the cache).
  *
+ * There are a couple of idiosyncrasies that this code must support, in
+ * particular, DB_TRUNCATE and DB_FCNTL_LOCKING.  First, we disallow
+ * DB_TRUNCATE in the presence of transactions, since opening a file with
+ * O_TRUNC will result in data being lost in an unrecoverable fashion.
+ * We also disallow DB_TRUNCATE if locking is enabled, because even in
+ * the presence of locking, we cannot avoid race conditions, so allowing
+ * DB_TRUNCATE with locking would be misleading.  See SR [#7345] for more
+ * details.
+ *
+ * However, if you are running with neither locking nor transactions, then
+ * you can specify DB_TRUNCATE, and if you do so, we will truncate the file
+ * regardless of its contents.
+ *
+ * FCNTL locking introduces another set of complications.  First, the only
+ * reason we support the DB_FCNTL_LOCKING flag is for historic compatibility
+ * with programs like Sendmail and Postfix.  In these cases, the caller may
+ * already have a lock on the file; we need to make sure that any file handles
+ * we open remain open, because if we were to close them, the lock held by the
+ * caller would go away.  Furthermore, Sendmail and/or Postfix need the ability
+ * to create databases in empty files.  So, when you're doing FCNTL locking,
+ * it's reasonable that you are trying to create a database into a 0-length
+ * file and we allow it, while under normal conditions, we do not create
+ * databases if the files already exist and are not Berkeley DB files.
+ *
  * PUBLIC: int __fop_file_setup __P((DB *,
  * PUBLIC:     DB_TXN *, const char *, int, u_int32_t, u_int32_t *));
  */
@@ -165,13 +196,13 @@ __fop_file_setup(dbp, txn, name, mode, flags, retidp)
 	u_int32_t flags, *retidp;
 {
 	DB_ENV *dbenv;
-	DB_FH fh, *fhp;
-	DB_LOCK elock, tmp_lock;
+	DB_FH *fhp;
+	DB_LOCK elock;
 	DB_TXN *stxn;
-	db_lockmode_t lmode;
-	u_int32_t locker, oflags;
+	size_t len;
+	u_int32_t dflags, locker, oflags;
 	u_int8_t mbuf[DBMETASIZE];
-	int created_fhp, created_locker, ret, tmp_created, truncating;
+	int created_locker, ret, retries, t_ret, tmp_created, truncating;
 	char *real_name, *real_tmpname, *tmpname;
 
 	DB_ASSERT(name != NULL);
@@ -179,25 +210,12 @@ __fop_file_setup(dbp, txn, name, mode, flags, retidp)
 	*retidp = TXN_INVALID;
 
 	dbenv = dbp->dbenv;
+	fhp = NULL;
 	LOCK_INIT(elock);
-	LOCK_INIT(tmp_lock);
 	stxn = NULL;
-	created_fhp = created_locker = 0;
+	created_locker = tmp_created = truncating = 0;
 	real_name = real_tmpname = tmpname = NULL;
-	tmp_created = truncating = 0;
-
-	/*
-	 * If we open a file handle and our caller is doing fcntl(2) locking,
-	 * we can't close it because that would discard the caller's lock.
-	 * Save it until we close the DB handle.
-	 */
-	if (LF_ISSET(DB_FCNTL_LOCKING)) {
-		if ((ret = __os_malloc(dbenv, sizeof(*fhp), &fhp)) != 0)
-			return (ret);
-		created_fhp = 1;
-	} else
-		fhp = &fh;
-	memset(fhp, 0, sizeof(*fhp));
+	dflags = F_ISSET(dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0;
 
 	/*
 	 * Get a lockerid for this handle.  There are paths through queue
@@ -205,11 +223,14 @@ __fop_file_setup(dbp, txn, name, mode, flags, retidp)
 	 * sure we don't clobber it and conflict.
 	 */
 	if (LOCKING_ON(dbenv) &&
-	    !F_ISSET(dbp, DB_AM_COMPENSATE) && dbp->lid == DB_LOCK_INVALIDID) {
+	    !F_ISSET(dbp, DB_AM_COMPENSATE) &&
+	    !F_ISSET(dbp, DB_AM_RECOVER) &&
+	    dbp->lid == DB_LOCK_INVALIDID) {
 		if ((ret = __lock_id(dbenv, &dbp->lid)) != 0)
 			goto err;
 		created_locker = 1;
 	}
+	LOCK_INIT(dbp->handle_lock);
 
 	locker = txn == NULL ? dbp->lid : txn->txnid;
 
@@ -225,80 +246,136 @@ __fop_file_setup(dbp, txn, name, mode, flags, retidp)
 	oflags = 0;
 	if (LF_ISSET(DB_RDONLY))
 		oflags |= DB_OSO_RDONLY;
-
-retry:	if (!F_ISSET(dbp, DB_AM_COMPENSATE))
+	if (LF_ISSET(DB_TRUNCATE))
+		oflags |= DB_OSO_TRUNC;
+	retries = 0;
+retry:
+	/*
+	 * If we cannot create the file, only retry a few times.  We
+	 * think we might be in a race with another create, but it could
+	 * be that the backup filename exists (that is, is left over from
+	 * a previous crash).
+	 */
+	if (++retries > DB_RETRY) {
+		__db_err(dbenv, "__fop_file_setup:  Retry limit (%d) exceeded",
+		    DB_RETRY);
+		goto err;
+	}
+	if (!F_ISSET(dbp, DB_AM_COMPENSATE) && !F_ISSET(dbp, DB_AM_RECOVER))
 		GET_ENVLOCK(dbenv, locker, &elock);
 	if ((ret = __os_exists(real_name, NULL)) == 0) {
-		if (LF_ISSET(DB_EXCL)) {
-			ret = EEXIST;
+		/*
+		 * If the file exists, there are 5 possible cases:
+		 * 1. DB_EXCL was specified so this is an error, unless
+		 *	this is a file left around after a rename and we
+		 *	are in the same transaction.  This gets decomposed
+		 *	into several subcases, because we check for various
+		 *	errors before we know we're in rename.
+		 * 2. We are truncating, and it doesn't matter what kind
+		 *	of file it is, we should open/create it.
+		 * 3. It is 0-length, we are not doing transactions (i.e.,
+		 *      we are sendmail), we should open/create into it.
+		 * 4. Is it a Berkeley DB file and we should simply open it.
+		 * 5. It is not a BDB file and we should return an error.
+		 */
+
+		/* We have to open the file. */
+reopen:		if ((ret = __os_open(dbenv, real_name, oflags, 0, &fhp)) != 0)
 			goto err;
+
+		/* Case 2: DB_TRUNCATE: we must do the creation in place. */
+		if (LF_ISSET(DB_TRUNCATE)) {
+			if (LF_ISSET(DB_EXCL)) {
+				/* Case 1a: DB_EXCL and DB_TRUNCATE. */
+				ret = EEXIST;
+				goto err;
+			}
+			tmpname = (char *)name;
+			goto creat2;
+		}
+
+		/* Cases 1,3-5: we need to read the meta-data page. */
+		ret = __fop_read_meta(dbenv, real_name, mbuf, sizeof(mbuf), fhp,
+		    LF_ISSET(DB_FCNTL_LOCKING) && txn == NULL ? 1 : 0, &len);
+
+		/* Case 3: 0-length, no txns. */
+		if (ret != 0 && len == 0 && txn == NULL) {
+			if (LF_ISSET(DB_EXCL)) {
+				/* Case 1b: DB_EXCL and 0-lenth file exists. */
+				ret = EEXIST;
+				goto err;
+			}
+			tmpname = (char *)name;
+			goto creat2;
 		}
-reopen:		if ((ret = __fop_read_meta(dbenv, real_name,
-		    mbuf, sizeof(mbuf), fhp, 0, oflags)) != 0)
+
+		/* Case 5: Invalid file. */
+		if (ret != 0)
 			goto err;
 
+		/* Case 4: This is a valid file. */
 		if ((ret = __db_meta_setup(dbenv,
 		    dbp, real_name, (DBMETA *)mbuf, flags, 1)) != 0)
 			goto err;
 
 		/* Now, get our handle lock. */
-		lmode = LF_ISSET(DB_TRUNCATE) ? DB_LOCK_WRITE : DB_LOCK_READ;
 		if ((ret = __fop_lock_handle(dbenv,
-		    dbp, locker, lmode, NULL, DB_LOCK_NOWAIT)) == 0) {
-			if ((ret = REL_ENVLOCK(dbenv, &elock)) != 0)
+		    dbp, locker, DB_LOCK_READ, NULL, DB_LOCK_NOWAIT)) == 0) {
+			if ((ret = __ENV_LPUT(dbenv, elock, 0)) != 0)
 				goto err;
-		} else {
-			/* Someone else has file locked; need to wait. */
+		} else if (ret != DB_LOCK_NOTGRANTED ||
+		    (txn != NULL && F_ISSET(txn, TXN_NOWAIT)))
+			goto err;
+		else {
+			/*
+			 * We were unable to acquire the handle lock without
+			 * blocking.  The fact that we are blocking might mean
+			 * that someone else is trying to delete the file.
+			 * Since some platforms cannot delete files while they
+			 * are open (Windows), we are going to have to close
+			 * the file.  This would be a problem if we were doing
+			 * FCNTL locking, because our closing the handle would
+			 * release the FCNTL locks.  Fortunately, if we are
+			 * doing FCNTL locking, then we should never fail to
+			 * acquire our handle lock, so we should never get here.
+			 * We assert it here to make sure we aren't destroying
+			 * any application level FCNTL semantics.
+			 */
+			DB_ASSERT(!LF_ISSET(DB_FCNTL_LOCKING));
 			if ((ret = __os_closehandle(dbenv, fhp)) != 0)
 				goto err;
+			fhp = NULL;
 			ret = __fop_lock_handle(dbenv,
-			    dbp, locker, lmode, &elock, 0);
+			    dbp, locker, DB_LOCK_READ, &elock, 0);
 			if (ret == DB_LOCK_NOTEXIST)
 				goto retry;
 			if (ret != 0)
 				goto err;
 			/*
-			 * XXX I need to convince myself that I don't need
-			 * to re-read the metadata page here.
-			 * XXX If you do need to re-read it you'd better
-			 * decrypt it too...
+			 * XXX
+			 * I need to convince myself that I don't need to
+			 * re-read the metadata page here.  If you do need
+			 * to re-read it you'd better decrypt it too...
 			 */
-			if ((ret = __os_open(dbenv, real_name, 0, 0, fhp)) != 0)
+			if ((ret =
+			    __os_open(dbenv, real_name, 0, 0, &fhp)) != 0)
 				goto err;
 		}
 
-		/*
-		 * Check for a truncate which needs to leap over to the
-		 * create case.
-		 */
-		if (LF_ISSET(DB_TRUNCATE)) {
-			/*
-			 * Sadly, we need to close and reopen the handle
-			 * in order to do the actual truncate.  We couldn't
-			 * do the truncate on the initial open because we
-			 * needed to read the old file-id in order to lock.
-			 */
-			if ((ret = __os_closehandle(dbenv, fhp)) != 0)
-				goto err;
-			if ((ret = __os_open(dbenv,
-			    real_name, DB_OSO_TRUNC, 0, fhp)) != 0)
-				goto err;
-			/*
-			 * This is not-transactional, so we'll do the
-			 * open/create in-place.
-			 */
-			tmp_lock = dbp->handle_lock;
-			truncating = 1;
-			tmpname = (char *)name;
-			goto creat2;
-		}
+		/* If we got here, then we now have the handle lock. */
 
 		/*
-		 * Check for a file in the midst of a rename
+		 * Check for a file in the midst of a rename.  If we find that
+		 * the file is in the midst of a rename, it must be the case
+		 * that it is in our current transaction (else we would still
+		 * be blocking), so we can continue along and create a new file
+		 * with the same name.  In that case, we have to close the file
+		 * handle because we reuse it below.
 		 */
 		if (F_ISSET(dbp, DB_AM_IN_RENAME)) {
 			if (LF_ISSET(DB_CREATE)) {
-				F_CLR(dbp, DB_AM_IN_RENAME);
+				if ((ret = __os_closehandle(dbenv, fhp)) != 0)
+					goto err;
 				goto create;
 			} else {
 				ret = ENOENT;
@@ -306,7 +383,20 @@ reopen:		if ((ret = __fop_read_meta(dbenv, real_name,
 			}
 		}
 
-		CLOSE_HANDLE(dbp, fhp);
+		/*
+		 * Now, case 1: check for DB_EXCL, because the file that exists
+		 * is not in the middle of a rename, so we have an error.  This
+		 * is a weird case, but we need to make sure that we don't
+		 * continue to hold the handle lock, since technically, we
+		 * should not have been allowed to open it.
+		 */
+		if (LF_ISSET(DB_EXCL)) {
+			ret = __ENV_LPUT(dbenv, dbp->handle_lock, 0);
+			LOCK_INIT(dbp->handle_lock);
+			if (ret == 0)
+				ret = EEXIST;
+			goto err;
+		}
 		goto done;
 	}
 
@@ -316,22 +406,40 @@ reopen:		if ((ret = __fop_read_meta(dbenv, real_name,
 	ret = 0;
 
 	/*
-	 * Need to create file; we need to set up the file,
-	 * the fileid and the locks.  Then we need to call
-	 * the appropriate routines to create meta-data pages.
+	 * We need to create file, which means that we need to set up the file,
+	 * the fileid and the locks.  Then we need to call the appropriate
+	 * routines to create meta-data pages.
 	 */
-	if ((ret = REL_ENVLOCK(dbenv, &elock)) != 0)
+	if ((ret = __ENV_LPUT(dbenv, elock, 0)) != 0)
 		goto err;
 
-create:	if ((ret = __db_backup_name(dbenv, name, txn, &tmpname)) != 0)
+create:	if (txn != NULL && IS_REP_CLIENT(dbenv)) {
+		__db_err(dbenv,
+		    "Transactional create on replication client disallowed");
+		ret = EINVAL;
+		goto err;
+	}
+	if ((ret = __db_backup_name(dbenv, name, txn, &tmpname)) != 0)
 		goto err;
 	if (TXN_ON(dbenv) && txn != NULL &&
-	    (ret = dbenv->txn_begin(dbenv, txn, &stxn, 0)) != 0)
+	    (ret = __txn_begin(dbenv, txn, &stxn, 0)) != 0)
 		goto err;
 	if ((ret = __fop_create(dbenv,
-	    stxn, fhp, tmpname, DB_APP_DATA, mode)) != 0)
+	    stxn, &fhp, tmpname, DB_APP_DATA, mode, dflags)) != 0) {
+		/*
+		 * If we don't have transactions there is a race on
+		 * creating the temp file.
+		 */
+		if (!TXN_ON(dbenv) && ret == EEXIST) {
+			__os_free(dbenv, tmpname);
+			tmpname = NULL;
+			__os_yield(dbenv, 1);
+			goto retry;
+		}
 		goto err;
+	}
 	tmp_created = 1;
+
 creat2:	if ((ret = __db_appname(dbenv,
 	    DB_APP_DATA, tmpname, 0, NULL, &real_tmpname)) != 0)
 		goto err;
@@ -347,27 +455,37 @@ creat2:	if ((ret = __db_appname(dbenv,
 
 	if ((ret = __db_new_file(dbp, stxn, fhp, tmpname)) != 0)
 		goto err;
+
+	/*
+	 * We need to close the handle here on platforms where remove and
+	 * rename fail if a handle is open (including Windows).
+	 */
 	CLOSE_HANDLE(dbp, fhp);
 
-	/* Now move the file into place. */
-	if (!F_ISSET(dbp, DB_AM_COMPENSATE))
+	/*
+	 * Now move the file into place unless we are creating in place (because
+	 * we created a database in a file that started out 0-length).
+	 */
+	if (!F_ISSET(dbp, DB_AM_COMPENSATE) && !F_ISSET(dbp, DB_AM_RECOVER))
 		GET_ENVLOCK(dbenv, locker, &elock);
-	if (!truncating && __os_exists(real_name, NULL) == 0) {
+
+	if (F_ISSET(dbp, DB_AM_IN_RENAME)) {
+		F_CLR(dbp, DB_AM_IN_RENAME);
+		__txn_remrem(dbenv, txn, real_name);
+	} else if (name == tmpname) {
+		/* We created it in place. */
+	} else if (__os_exists(real_name, NULL) == 0) {
 		/*
 		 * Someone managed to create the file; remove our temp
 		 * and try to open the file that now exists.
 		 */
 		(void)__fop_remove(dbenv,
-		    NULL, dbp->fileid, tmpname, DB_APP_DATA);
-		if (LOCKING_ON(dbenv))
-			dbenv->lock_put(dbenv, &dbp->handle_lock);
+		    NULL, dbp->fileid, tmpname, DB_APP_DATA, dflags);
+		(void)__ENV_LPUT(dbenv, dbp->handle_lock, 0);
 		LOCK_INIT(dbp->handle_lock);
 
-		/* If we have a saved handle; close it. */
-		if (LF_ISSET(DB_FCNTL_LOCKING))
-			(void)__os_closehandle(dbenv, fhp);
 		if (stxn != NULL) {
-			ret = stxn->abort(stxn);
+			ret = __txn_abort(stxn);
 			stxn = NULL;
 		}
 		if (ret != 0)
@@ -375,21 +493,16 @@ creat2:	if ((ret = __db_appname(dbenv,
 		goto reopen;
 	}
 
-	/* We've successfully created, move the file into place. */
 	if ((ret = __fop_lock_handle(dbenv,
-	    dbp, locker, DB_LOCK_WRITE, &elock, 0)) != 0)
-		goto err;
-	if (!truncating && (ret = __fop_rename(dbenv,
-	    stxn, tmpname, name, dbp->fileid, DB_APP_DATA)) != 0)
+	    dbp, locker, DB_LOCK_WRITE, &elock, NOWAIT_FLAG(txn))) != 0)
 		goto err;
-
-	/* If this was a truncate; release lock on the old file. */
-	if (LOCK_ISSET(tmp_lock) && (ret = __lock_put(dbenv, &tmp_lock)) != 0)
+	if (tmpname != name && (ret = __fop_rename(dbenv,
+	    stxn, tmpname, name, dbp->fileid, DB_APP_DATA, dflags)) != 0)
 		goto err;
 
 	if (stxn != NULL) {
 		*retidp = stxn->txnid;
-		ret = stxn->commit(stxn, 0);
+		ret = __txn_commit(stxn, 0);
 		stxn = NULL;
 	} else
 		*retidp = TXN_INVALID;
@@ -402,33 +515,33 @@ creat2:	if ((ret = __db_appname(dbenv,
 	if (0) {
 errmsg:		__db_err(dbenv, "%s: %s", name, db_strerror(ret));
 
-err:		if (stxn != NULL)
-			(void)stxn->abort(stxn);
+err:		CLOSE_HANDLE(dbp, fhp);
+		if (stxn != NULL)
+			(void)__txn_abort(stxn);
 		if (tmp_created && txn == NULL)
 			(void)__fop_remove(dbenv,
-			    NULL, NULL, tmpname, DB_APP_DATA);
-		if (F_ISSET(fhp, DB_FH_VALID))
-			(void)__os_closehandle(dbenv, fhp);
-		if (LOCK_ISSET(tmp_lock))
-			__lock_put(dbenv, &tmp_lock);
-		if (LOCK_ISSET(dbp->handle_lock) && txn == NULL)
-			__lock_put(dbenv, &dbp->handle_lock);
-		if (LOCK_ISSET(elock))
-			(void)REL_ENVLOCK(dbenv, &elock);
+			    NULL, NULL, tmpname, DB_APP_DATA, dflags);
+		if (txn == NULL)
+			(void)__ENV_LPUT(dbenv, dbp->handle_lock, 0);
+		(void)__ENV_LPUT(dbenv, elock, 0);
 		if (created_locker) {
 			(void)__lock_id_free(dbenv, dbp->lid);
 			dbp->lid = DB_LOCK_INVALIDID;
 		}
-		if (created_fhp)
-			__os_free(dbenv, fhp);
 	}
 
-done:	if (!truncating && tmpname != NULL)
+done:	/*
+	 * There are cases where real_name and tmpname take on the
+	 * exact same string, so we need to make sure that we do not
+	 * free twice.
+	 */
+	if (!truncating && tmpname != NULL && tmpname != name)
 		__os_free(dbenv, tmpname);
 	if (real_name != NULL)
 		__os_free(dbenv, real_name);
 	if (real_tmpname != NULL)
 		__os_free(dbenv, real_tmpname);
+	CLOSE_HANDLE(dbp, fhp);
 
 	return (ret);
 }
@@ -504,13 +617,21 @@ __fop_subdb_setup(dbp, txn, mname, name, mode, flags)
 {
 	DB *mdbp;
 	DB_ENV *dbenv;
-	int do_remove, ret;
+	db_lockmode_t lkmode;
+	int ret, t_ret;
 
 	mdbp = NULL;
 	dbenv = dbp->dbenv;
 
 	if ((ret = __db_master_open(dbp, txn, mname, flags, mode, &mdbp)) != 0)
 		return (ret);
+	/*
+	 * If we created this file, then we need to set the DISCARD flag so
+	 * that if we fail in the middle of this routine, we discard from the
+	 * mpool any pages that we just created.
+	 */
+	if (F_ISSET(mdbp, DB_AM_CREATED))
+		F_SET(mdbp, DB_AM_DISCARD);
 
 	/*
 	 * We are going to close this instance of the master, so we can
@@ -521,7 +642,7 @@ __fop_subdb_setup(dbp, txn, mname, name, mode, flags)
 		mdbp->saved_open_fhp = NULL;
 	}
 
-	/* Now copy the pagesize. */
+	/* Copy the pagesize and set the sub-database flag. */
 	dbp->pgsize = mdbp->pgsize;
 	F_SET(dbp, DB_AM_SUBDB);
 
@@ -548,14 +669,36 @@ __fop_subdb_setup(dbp, txn, mname, name, mode, flags)
 	 */
 
 	memcpy(dbp->fileid, mdbp->fileid, DB_FILE_ID_LEN);
+	lkmode = F_ISSET(dbp, DB_AM_CREATED) || LF_ISSET(DB_WRITEOPEN) ?
+	    DB_LOCK_WRITE : DB_LOCK_READ;
 	if ((ret = __fop_lock_handle(dbenv, dbp,
-	    txn == NULL ? dbp->lid : txn->txnid,
-	    F_ISSET(dbp, DB_AM_CREATED) || LF_ISSET(DB_WRITEOPEN) ?
-	    DB_LOCK_WRITE : DB_LOCK_READ, NULL, 0)) != 0)
+	    txn == NULL ? dbp->lid : txn->txnid, lkmode, NULL,
+	    NOWAIT_FLAG(txn))) != 0)
 		goto err;
 
-	if ((ret = __db_init_subdb(mdbp, dbp, name, txn)) != 0)
+	if ((ret = __db_init_subdb(mdbp, dbp, name, txn)) != 0) {
+		/*
+		 * If there was no transaction and we created this database,
+		 * then we need to undo the update of the master database.
+		 */
+		if (F_ISSET(dbp, DB_AM_CREATED) && txn != NULL)
+			(void)__db_master_update(mdbp, dbp, txn,
+			    name, dbp->type, MU_REMOVE, NULL, 0);
+		F_CLR(dbp, DB_AM_CREATED);
 		goto err;
+	}
+
+	/*
+	 * XXX
+	 * This should have been done at the top of this routine.  The problem
+	 * is that __db_init_subdb() uses "standard" routines to process the
+	 * meta-data page and set information in the DB handle based on it.
+	 * Those routines have to deal with swapped pages and will normally set
+	 * the DB_AM_SWAP flag.  However, we use the master's metadata page and
+	 * that has already been swapped, so they get the is-swapped test wrong.
+	 */
+	F_CLR(dbp, DB_AM_SWAP);
+	F_SET(dbp, F_ISSET(mdbp, DB_AM_SWAP));
 
 	/*
 	 * In the file create case, these happen in separate places so we have
@@ -574,9 +717,16 @@ __fop_subdb_setup(dbp, txn, mname, name, mode, flags)
 		F_CLR(mdbp, DB_AM_DISCARD);
 	}
 
+	if (0) {
+err:
+DB_TEST_RECOVERY_LABEL
+		if (txn == NULL)
+			(void)__ENV_LPUT(dbenv, dbp->handle_lock, 0);
+	}
+
 	/*
 	 * The master's handle lock is under the control of the
-	 * subdb (it acquired the master's locker.  We want to
+	 * subdb (it acquired the master's locker).  We want to
 	 * keep the master's handle lock so that no one can remove
 	 * the file while the subdb is open.  If we register the
 	 * trade event and then invalidate the copy of the lock
@@ -584,36 +734,29 @@ __fop_subdb_setup(dbp, txn, mname, name, mode, flags)
 	 * before we register this event, we'd better remove any
 	 * events that we've already registered for the master.
 	 */
-
 	if (!F_ISSET(dbp, DB_AM_RECOVER) && txn != NULL) {
 		/* Unregister old master events. */
 		 __txn_remlock(dbenv,
 		    txn, &mdbp->handle_lock, DB_LOCK_INVALIDID);
 
 		/* Now register the new event. */
-		if ((ret = __txn_lockevent(dbenv,
-		    txn, dbp, &mdbp->handle_lock, dbp->lid)) != 0)
-			goto err;
+		if ((t_ret = __txn_lockevent(dbenv, txn, dbp,
+		    &mdbp->handle_lock, dbp->lid == DB_LOCK_INVALIDID ?
+		    mdbp->lid : dbp->lid)) != 0 && ret == 0)
+			ret = t_ret;
 	}
 	LOCK_INIT(mdbp->handle_lock);
-	return (__db_close_i(mdbp, txn, 0));
 
-err:
-DB_TEST_RECOVERY_LABEL
-	if (LOCK_ISSET(dbp->handle_lock) && txn == NULL)
-		__lock_put(dbenv, &dbp->handle_lock);
-
-	/* If we created the master file then we need to remove it.  */
-	if (mdbp != NULL) {
-		do_remove = F_ISSET(mdbp, DB_AM_CREATED) ? 1 : 0;
-		if (do_remove)
-			F_SET(mdbp, DB_AM_DISCARD);
-		(void)__db_close_i(mdbp, txn, 0);
-		if (do_remove) {
-			(void)db_create(&mdbp, dbp->dbenv, 0);
-			(void)__db_remove_i(mdbp, txn, mname, NULL);
-		}
-	}
+	/*
+	 * If the master was created, we need to sync so that the metadata
+	 * page is correct on disk for recovery, since it isn't read through
+	 * mpool.  If we're opening a subdb in an existing file, we can skip
+	 * the sync.
+	 */
+	if ((t_ret =__db_close(mdbp, txn,
+	    F_ISSET(dbp, DB_AM_CREATED_MSTR) ? 0 : DB_NOSYNC)) != 0 &&
+	    ret == 0)
+		ret = t_ret;
 	return (ret);
 }
 
@@ -632,7 +775,9 @@ __fop_remove_setup(dbp, txn, name, flags)
 	u_int32_t flags;
 {
 	DB_ENV *dbenv;
+	DB_FH *fhp;
 	DB_LOCK elock;
+	u_int32_t refcnt;
 	u_int8_t mbuf[DBMETASIZE];
 	int ret;
 
@@ -640,9 +785,10 @@ __fop_remove_setup(dbp, txn, name, flags)
 	dbenv = dbp->dbenv;
 	PANIC_CHECK(dbenv);
 	LOCK_INIT(elock);
+	fhp = NULL;
 
 	/* Create locker if necessary. */
-	if (LOCKING_ON(dbenv)) {
+retry:	if (LOCKING_ON(dbenv)) {
 		if (txn != NULL)
 			dbp->lid = txn->txnid;
 		else if (dbp->lid == DB_LOCK_INVALIDID) {
@@ -651,58 +797,134 @@ __fop_remove_setup(dbp, txn, name, flags)
 		}
 	}
 
+	/*
+	 * We are about to open a file handle and then possibly close it.
+	 * We cannot close handles if we are doing FCNTL locking.  However,
+	 * there is no way to pass the FCNTL flag into this routine via the
+	 * user API.  The only way we can get in here and be doing FCNTL
+	 * locking is if we are trying to clean up an open that was called
+	 * with FCNTL locking.  In that case, the save_fhp should already be
+	 * set.  So, we use that field to tell us if we need to make sure
+	 * that we shouldn't close the handle.
+	 */
+	fhp = dbp->saved_open_fhp;
+	DB_ASSERT(LF_ISSET(DB_FCNTL_LOCKING) || fhp == NULL);
+
 	/*
 	 * Lock environment to protect file open.  That will enable us to
 	 * read the meta-data page and get the fileid so that we can lock
 	 * the handle.
 	 */
 	GET_ENVLOCK(dbenv, dbp->lid, &elock);
+	if (fhp == NULL &&
+	    (ret = __os_open(dbenv, name, DB_OSO_RDONLY, 0, &fhp)) != 0)
+		goto err;
 	if ((ret = __fop_read_meta(dbenv,
-	    name, mbuf, sizeof(mbuf), NULL, 0, 0)) != 0)
+	    name, mbuf, sizeof(mbuf), fhp, 0, NULL)) != 0)
 		goto err;
 
 	if ((ret =
 	    __db_meta_setup(dbenv, dbp, name, (DBMETA *)mbuf, flags, 1)) != 0)
 		goto err;
 
-	/* Now, release the environment and get the handle lock. */
+	/*
+	 * Now, get the handle lock.  We first try with NOWAIT, because if
+	 * we have to wait, we're going to have to close the file and reopen
+	 * it, so that if there is someone else removing it, our open doesn't
+	 * prevent that.
+	 */
 	if ((ret = __fop_lock_handle(dbenv,
-	    dbp, dbp->lid, DB_LOCK_WRITE, &elock, 0)) != 0)
+	    dbp, dbp->lid, DB_LOCK_WRITE, NULL, DB_LOCK_NOWAIT)) != 0) {
+		/*
+		 * Close the file, block on the lock, clean up the dbp, and
+		 * then start all over again.
+		 */
+		if (!LF_ISSET(DB_FCNTL_LOCKING)) {
+			(void)__os_closehandle(dbenv, fhp);
+			fhp = NULL;
+		}
+		if (ret == DB_LOCK_NOTEXIST) {
+			if ((ret = __ENV_LPUT(dbenv, elock, 0)) != 0)
+				goto err;
+		} else if (ret != DB_LOCK_NOTGRANTED ||
+		    (txn != NULL && F_ISSET(txn, TXN_NOWAIT)))
+			goto err;
+		else if ((ret = __fop_lock_handle(dbenv,
+		    dbp, dbp->lid, DB_LOCK_WRITE, &elock, 0)) != 0 &&
+		    ret != DB_LOCK_NOTEXIST)
+			goto err;
+
+		if (txn != NULL)
+			dbp->lid = DB_LOCK_INVALIDID;
+		(void)__db_refresh(dbp, txn, DB_NOSYNC, NULL);
+		goto retry;
+	} else if ((ret = __ENV_LPUT(dbenv, elock, 0)) != 0)
 		goto err;
 
-	return (0);
+	/* Check if the file is already open. */
+	if ((ret = __memp_get_refcnt(dbenv, dbp->fileid, &refcnt)) != 0)
+		goto err;
+	/*
+	 * Now, error check.  If the file is already open (refcnt != 0), then
+	 * we must have it open (since we got the lock) and we need to panic,
+	 * because this is a self deadlock and the application has a bug.
+	 * If the file isn't open, but it's in the midst of a rename then
+	 * this file doesn't really exist.
+	 */
+	if (refcnt != 0) {
+		__db_err(dbenv,
+"Attempting to remove file open in current transaction causing self-deadlock");
+		ret = __db_panic(dbenv, DB_LOCK_DEADLOCK);
+	} else if (F_ISSET(dbp, DB_AM_IN_RENAME))
+		ret = ENOENT;
 
-err:	(void)REL_ENVLOCK(dbenv, &elock);
+	if (0) {
+err:		(void)__ENV_LPUT(dbenv, elock, 0);
+	}
+	if (fhp != NULL && !LF_ISSET(DB_FCNTL_LOCKING))
+		(void)__os_closehandle(dbenv, fhp);
+	/*
+	 * If we are going to proceed with the removal, then we need to make
+	 * sure that we don't leave any pages around in the mpool.
+	 */
+	if (ret == 0)
+		F_SET(dbp, DB_AM_DISCARD);
 	return (ret);
 }
 
 /*
  * __fop_read_meta --
- *	Read the meta-data page from a file and return it in buf.  The
- * open file handle is returned in fhp.
+ *	Read the meta-data page from a file and return it in buf.
  *
- * PUBLIC: int __fop_read_meta __P((DB_ENV *,
- * PUBLIC:     const char *, u_int8_t *, size_t, DB_FH *, int, u_int32_t));
+ * PUBLIC: int __fop_read_meta __P((DB_ENV *, const char *,
+ * PUBLIC:     u_int8_t *, size_t, DB_FH *, int, size_t *));
  */
 int
-__fop_read_meta(dbenv, name, buf, size, fhp, errok, flags)
+__fop_read_meta(dbenv, name, buf, size, fhp, errok, nbytesp)
 	DB_ENV *dbenv;
 	const char *name;
 	u_int8_t *buf;
 	size_t size;
 	DB_FH *fhp;
 	int errok;
-	u_int32_t flags;
+	size_t *nbytesp;
 {
-	DB_FH fh, *lfhp;
 	size_t nr;
 	int ret;
 
-	lfhp = fhp == NULL ? &fh : fhp;
-	memset(lfhp, 0, sizeof(*fhp));
-	if ((ret = __os_open(dbenv, name, flags, 0, lfhp)) != 0)
-		goto err;
-	if ((ret = __os_read(dbenv, lfhp, buf, size, &nr)) != 0) {
+	/*
+	 * Our caller wants to know the number of bytes read, even if we
+	 * return an error.
+	 */
+	if (nbytesp != NULL)
+		*nbytesp = 0;
+
+	nr = 0;
+	ret = __os_read(dbenv, fhp, buf, size, &nr);
+	if (nbytesp != NULL)
+		*nbytesp = nr;
+
+	if (ret != 0) {
 		if (!errok)
 			__db_err(dbenv, "%s: %s", name, db_strerror(ret));
 		goto err;
@@ -713,17 +935,9 @@ __fop_read_meta(dbenv, name, buf, size, fhp, errok, flags)
 			__db_err(dbenv,
 			    "%s: unexpected file type or format", name);
 		ret = EINVAL;
-		goto err;
 	}
 
-err:	/*
-	 * On error, we always close the handle.  If there is no error,
-	 * then we only return the handle if the user didn't pass us
-	 * a handle into which to return it.  If fhp is valid, then
-	 * lfhp is the same as fhp.
-	 */
-	if (F_ISSET(lfhp, DB_FH_VALID) && (ret != 0 || fhp == NULL))
-		__os_closehandle(dbenv, lfhp);
+err:
 	return (ret);
 }
 
@@ -743,8 +957,9 @@ __fop_dummy(dbp, txn, old, new, flags)
 	const char *old, *new;
 	u_int32_t flags;
 {
-	DB *tmpdbp;
+	DB *tmpdbp, *t2dbp;
 	DB_ENV *dbenv;
+	DB_FH *fhp;
 	DB_LOCK elock;
 	DB_LSN lsn;
 	DBT fiddbt, namedbt, tmpdbt;
@@ -752,8 +967,9 @@ __fop_dummy(dbp, txn, old, new, flags)
 	char *back;
 	char *realback, *realnew, *realold;
 	int ret, t_ret;
+	size_t len;
 	u_int8_t mbuf[DBMETASIZE];
-	u_int32_t locker, stxnid;
+	u_int32_t dflags, locker, stxnid;
 
 	dbenv = dbp->dbenv;
 	LOCK_INIT(elock);
@@ -762,14 +978,15 @@ __fop_dummy(dbp, txn, old, new, flags)
 	realold = NULL;
 	back = NULL;
 	stxn = NULL;
-	tmpdbp = NULL;
+	tmpdbp = t2dbp = NULL;
+	fhp = NULL;
+	dflags = F_ISSET(dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0;
 
 	DB_ASSERT(txn != NULL);
 	locker = txn->txnid;
 
 	/* Begin sub transaction to encapsulate the rename. */
-	if (TXN_ON(dbenv) &&
-	    (ret = dbenv->txn_begin(dbenv, txn, &stxn, 0)) != 0)
+	if (TXN_ON(dbenv) && (ret = __txn_begin(dbenv, txn, &stxn, 0)) != 0)
 		goto err;
 
 	/* We need to create a dummy file as a place holder. */
@@ -778,7 +995,8 @@ __fop_dummy(dbp, txn, old, new, flags)
 	if ((ret = __db_appname(dbenv,
 	    DB_APP_DATA, back, flags, NULL, &realback)) != 0)
 		goto err;
-	if ((ret = __fop_create(dbenv, stxn, NULL, back, DB_APP_DATA, 0)) != 0)
+	if ((ret = __fop_create(dbenv,
+	    stxn, NULL, back, DB_APP_DATA, 0, dflags)) != 0)
 		goto err;
 
 	memset(mbuf, 0, sizeof(mbuf));
@@ -786,14 +1004,14 @@ __fop_dummy(dbp, txn, old, new, flags)
 	    __os_fileid(dbenv, realback, 1, ((DBMETA *)mbuf)->uid)) != 0)
 		goto err;
 	((DBMETA *)mbuf)->magic = DB_RENAMEMAGIC;
-	if ((ret = __fop_write(dbenv,
-	    stxn, back, DB_APP_DATA, NULL, 0, mbuf, DBMETASIZE, 1)) != 0)
+	if ((ret = __fop_write(dbenv, stxn, back,
+	    DB_APP_DATA, NULL, 0, 0, 0, mbuf, DBMETASIZE, 1, dflags)) != 0)
 		goto err;
 
 	/* Create a dummy dbp handle. */
 	if ((ret = db_create(&tmpdbp, dbenv, 0)) != 0)
 		goto err;
-	memcpy(&tmpdbp->fileid, ((DBMETA *)mbuf)->uid, DB_FILE_ID_LEN);
+	memcpy(tmpdbp->fileid, ((DBMETA *)mbuf)->uid, DB_FILE_ID_LEN);
 
 	/* Now, lock the name space while we initialize this file. */
 	if ((ret = __db_appname(dbenv,
@@ -801,8 +1019,44 @@ __fop_dummy(dbp, txn, old, new, flags)
 		goto err;
 	GET_ENVLOCK(dbenv, locker, &elock);
 	if (__os_exists(realnew, NULL) == 0) {
-		ret = EEXIST;
-		goto err;
+		/*
+		 * It is possible that the only reason this file exists is
+		 * because we've done a previous rename of it and we have
+		 * left a placeholder here.  We need to check for that case
+		 * and allow this rename to succeed if that's the case.
+		 */
+		if ((ret = db_create(&t2dbp, dbenv, 0)) != 0)
+			goto err;
+		if ((ret = __os_open(dbenv, realnew, 0, 0, &fhp)) != 0)
+			goto err;
+		if ((ret = __fop_read_meta(dbenv,
+		    realnew, mbuf, sizeof(mbuf), fhp, 0, &len)) != 0 ||
+		    (ret = __db_meta_setup(dbenv,
+		    t2dbp, realnew, (DBMETA *)mbuf, 0, 1)) != 0) {
+			ret = EEXIST;
+			goto err;
+		}
+
+		/*
+		 * Now, try to acquire the handle lock.  If it's from our txn,
+		 * then we'll get the lock.  If it's not, then someone else has
+		 * it locked,  and we need to report this as an error.  If we
+		 * know we can get the lock, we can immediately release it,
+		 * which we need to do since this is a temporary handle.
+		 */
+		if ((ret = __fop_lock_handle(dbenv,
+		    t2dbp, locker, DB_LOCK_WRITE, NULL, DB_LOCK_NOWAIT)) != 0)
+			ret = EEXIST;
+		else {
+			(void)__lock_put(dbenv, &t2dbp->handle_lock, 0);
+			if (!F_ISSET(t2dbp, DB_AM_IN_RENAME))
+				ret = EEXIST;
+		}
+		if ((t_ret = __os_closehandle(dbenv, fhp)) != 0 && ret == 0)
+			ret = t_ret;
+		fhp = NULL;
+		if (ret != 0)
+			goto err;
 	}
 
 	/*
@@ -810,13 +1064,13 @@ __fop_dummy(dbp, txn, old, new, flags)
 	 * swap for the handle lock.
 	 */
 	if ((ret = __fop_rename(dbenv,
-	    stxn, old, new, dbp->fileid, DB_APP_DATA)) != 0)
+	    stxn, old, new, dbp->fileid, DB_APP_DATA, dflags)) != 0)
 		goto err;
 	if ((ret = __fop_rename(dbenv,
-	    stxn, back, old, tmpdbp->fileid, DB_APP_DATA)) != 0)
+	    stxn, back, old, tmpdbp->fileid, DB_APP_DATA, dflags)) != 0)
 		goto err;
 	if ((ret = __fop_lock_handle(dbenv,
-	    tmpdbp, locker, DB_LOCK_WRITE, &elock, 0)) != 0)
+	    tmpdbp, locker, DB_LOCK_WRITE, &elock, NOWAIT_FLAG(txn))) != 0)
 		goto err;
 
 	/*
@@ -829,7 +1083,7 @@ __fop_dummy(dbp, txn, old, new, flags)
 	if (stxn != NULL) {
 		/* Commit the child. */
 		stxnid = stxn->txnid;
-		ret = stxn->commit(stxn, 0);
+		ret = __txn_commit(stxn, 0);
 		stxn = NULL;
 
 		/* Now log the child information in the parent. */
@@ -855,12 +1109,17 @@ __fop_dummy(dbp, txn, old, new, flags)
 	if ((ret = __txn_remevent(dbenv, txn, realold, NULL)) != 0)
 		goto err;
 
-err:	(void)REL_ENVLOCK(dbenv, &elock);
+err:	(void)__ENV_LPUT(dbenv, elock, 0);
 	if (stxn != NULL)
-		(void)stxn->abort(stxn);
+		(void)__txn_abort(stxn);
 	if (tmpdbp != NULL &&
-	    (t_ret = __db_close_i(tmpdbp, NULL, 0)) != 0 && ret == 0)
+	    (t_ret = __db_close(tmpdbp, NULL, 0)) != 0 && ret == 0)
+		ret = t_ret;
+	if (t2dbp != NULL &&
+	    (t_ret = __db_close(t2dbp, NULL, 0)) != 0 && ret == 0)
 		ret = t_ret;
+	if (fhp != NULL)
+		(void)__os_closehandle(dbenv, fhp);
 	if (realold != NULL)
 		__os_free(dbenv, realold);
 	if (realnew != NULL)
@@ -889,7 +1148,7 @@ __fop_dbrename(dbp, old, new)
 	DB_ENV *dbenv;
 	DB_LOCK elock;
 	char *real_new, *real_old;
-	int ret, tret;
+	int ret, t_ret;
 
 	dbenv = dbp->dbenv;
 	real_new = NULL;
@@ -916,10 +1175,10 @@ __fop_dbrename(dbp, old, new)
 	    DB_APP_DATA, old, 0, NULL, &real_old)) != 0)
 		goto err;
 
-	ret = dbenv->memp_nameop(dbenv, dbp->fileid, new, real_old, real_new);
+	ret = __memp_nameop(dbenv, dbp->fileid, new, real_old, real_new);
 
-err:	if ((tret = REL_ENVLOCK(dbenv, &elock)) != 0 && ret == 0)
-		ret = tret;
+err:	if ((t_ret = __ENV_LPUT(dbenv, elock, 0)) != 0 && ret == 0)
+		ret = t_ret;
 	if (real_old != NULL)
 		__os_free(dbenv, real_old);
 	if (real_new != NULL)
diff --git a/storage/bdb/hash/hash.c b/storage/bdb/hash/hash.c
index 2f972a3238d99f125276a03a8ed704ad146fc871..71c2f5e06902816642625f018466786622b89841 100644
--- a/storage/bdb/hash/hash.c
+++ b/storage/bdb/hash/hash.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -38,18 +38,15 @@
  * 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.
+ *
+ * $Id: hash.c,v 11.200 2004/10/14 18:11:36 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: hash.c,v 11.166 2002/08/06 06:11:25 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
-#include <stdlib.h>
 #include <string.h>
 #endif
 
@@ -59,6 +56,7 @@ static const char revid[] = "$Id: hash.c,v 11.166 2002/08/06 06:11:25 bostic Exp
 #include "dbinc/btree.h"
 #include "dbinc/hash.h"
 #include "dbinc/lock.h"
+#include "dbinc/mp.h"
 
 static int  __ham_bulk __P((DBC *, DBT *, u_int32_t));
 static int  __ham_c_close __P((DBC *, db_pgno_t, int *));
@@ -113,7 +111,8 @@ __ham_quick_delete(dbc)
 	DB_ASSERT(IS_INITIALIZED(dbc));
 	DB_ASSERT(((HASH_CURSOR *)dbc->internal)->opd == NULL);
 
-	ret = __ham_del_pair(dbc, 1);
+	if ((ret = __ham_c_writelock(dbc)) == 0)
+		ret = __ham_del_pair(dbc, 1);
 
 	if ((t_ret = __ham_release_meta(dbc)) != 0 && ret == 0)
 		ret = t_ret;
@@ -148,12 +147,12 @@ __ham_c_init(dbc)
 
 	dbc->internal = (DBC_INTERNAL *) new_curs;
 	dbc->c_close = __db_c_close;
-	dbc->c_count = __db_c_count;
-	dbc->c_del = __db_c_del;
-	dbc->c_dup = __db_c_dup;
-	dbc->c_get = dbc->c_real_get = __db_c_get;
-	dbc->c_pget = __db_c_pget;
-	dbc->c_put = __db_c_put;
+	dbc->c_count = __db_c_count_pp;
+	dbc->c_del = __db_c_del_pp;
+	dbc->c_dup = __db_c_dup_pp;
+	dbc->c_get = __db_c_get_pp;
+	dbc->c_pget = __db_c_pget_pp;
+	dbc->c_put = __db_c_put_pp;
 	dbc->c_am_bulk = __ham_bulk;
 	dbc->c_am_close = __ham_c_close;
 	dbc->c_am_del = __ham_c_del;
@@ -162,9 +161,7 @@ __ham_c_init(dbc)
 	dbc->c_am_put = __ham_c_put;
 	dbc->c_am_writelock = __ham_c_writelock;
 
-	__ham_item_init(dbc);
-
-	return (0);
+	return (__ham_item_init(dbc));
 }
 
 /*
@@ -180,6 +177,7 @@ __ham_c_close(dbc, root_pgno, rmroot)
 	DB_MPOOLFILE *mpf;
 	HASH_CURSOR *hcp;
 	HKEYDATA *dp;
+	db_lockmode_t lock_mode;
 	int doroot, gotmeta, ret, t_ret;
 	u_int32_t dirty;
 
@@ -194,11 +192,19 @@ __ham_c_close(dbc, root_pgno, rmroot)
 		if ((ret = __ham_get_meta(dbc)) != 0)
 			goto done;
 		gotmeta = 1;
-		if ((ret = __ham_get_cpage(dbc, DB_LOCK_READ)) != 0)
+		lock_mode = DB_LOCK_READ;
+
+		/* To support dirty reads we must reget the write lock. */
+		if (F_ISSET(dbc->dbp, DB_AM_DIRTY) &&
+		     F_ISSET((BTREE_CURSOR *)
+		     dbc->internal->opd->internal, C_DELETED))
+			lock_mode = DB_LOCK_WRITE;
+
+		if ((ret = __ham_get_cpage(dbc, lock_mode)) != 0)
 			goto out;
 		dp = (HKEYDATA *)H_PAIRDATA(dbc->dbp, hcp->page, hcp->indx);
 
-		/* If its not a dup we aborted before we changed it. */
+		/* If it's not a dup we aborted before we changed it. */
 		if (HPAGE_PTYPE(dp) == H_OFFDUP)
 			memcpy(&root_pgno,
 			    HOFFPAGE_PGNO(dp), sizeof(db_pgno_t));
@@ -216,13 +222,13 @@ __ham_c_close(dbc, root_pgno, rmroot)
 	}
 
 out:	if (hcp->page != NULL && (t_ret =
-	    mpf->put(mpf, hcp->page, dirty)) != 0 && ret == 0)
+	    __memp_fput(mpf, hcp->page, dirty)) != 0 && ret == 0)
 		ret = t_ret;
 	if (gotmeta != 0 && (t_ret = __ham_release_meta(dbc)) != 0 && ret == 0)
 		ret = t_ret;
 
-done:
-	__ham_item_init(dbc);
+done:	if ((t_ret = __ham_item_init(dbc)) != 0 && ret == 0)
+		ret = t_ret;
 	return (ret);
 }
 
@@ -271,6 +277,10 @@ __ham_c_count(dbc, recnop)
 
 	if ((ret = __ham_get_cpage(dbc, DB_LOCK_READ)) != 0)
 		return (ret);
+	if (hcp->indx >= NUM_ENT(hcp->page)) {
+		*recnop = 0;
+		goto err;
+	}
 
 	switch (HPAGE_PTYPE(H_PAIRDATA(dbp, hcp->page, hcp->indx))) {
 	case H_KEYDATA:
@@ -295,7 +305,7 @@ __ham_c_count(dbc, recnop)
 
 	*recnop = recno;
 
-err:	if ((t_ret = mpf->put(mpf, hcp->page, 0)) != 0 && ret == 0)
+err:	if ((t_ret = __memp_fput(mpf, hcp->page, 0)) != 0 && ret == 0)
 		ret = t_ret;
 	hcp->page = NULL;
 	return (ret);
@@ -353,8 +363,8 @@ __ham_c_del(dbc)
 		ret = __ham_del_pair(dbc, 1);
 
 out:	if (hcp->page != NULL) {
-		if ((t_ret = mpf->put(mpf,
-		    hcp->page, ret == 0 ? DB_MPOOL_DIRTY : 0)) && ret == 0)
+		if ((t_ret = __memp_fput(mpf,
+		    hcp->page, ret == 0 ? DB_MPOOL_DIRTY : 0)) != 0 && ret == 0)
 			ret = t_ret;
 		hcp->page = NULL;
 	}
@@ -375,6 +385,7 @@ __ham_c_dup(orig_dbc, new_dbc)
 	DBC *orig_dbc, *new_dbc;
 {
 	HASH_CURSOR *orig, *new;
+	int ret;
 
 	orig = (HASH_CURSOR *)orig_dbc->internal;
 	new = (HASH_CURSOR *)new_dbc->internal;
@@ -394,16 +405,17 @@ __ham_c_dup(orig_dbc, new_dbc)
 	 * If the old cursor held a lock and we're not in transactions, get one
 	 * for the new one.   The reason that we don't need a new lock if we're
 	 * in a transaction is because we already hold a lock and will continue
-	 * to do so until commit, so there is no point in reaquiring it. We
+	 * to do so until commit, so there is no point in re-acquiring it. We
 	 * don't know if the old lock was a read or write lock, but it doesn't
 	 * matter. We'll get a read lock.  We know that this locker already
 	 * holds a lock of the correct type, so if we need a write lock and
 	 * request it, we know that we'll get it.
 	 */
-	if (!LOCK_ISSET(orig->lock) || orig_dbc->txn != NULL)
-		return (0);
+	if (orig_dbc->txn == NULL && LOCK_ISSET(orig->lock))
+		if ((ret = __ham_lock_bucket(new_dbc, DB_LOCK_READ)) != 0)
+			return (ret);
 
-	return (__ham_lock_bucket(new_dbc, DB_LOCK_READ));
+	return (0);
 }
 
 static int
@@ -488,6 +500,9 @@ __ham_c_get(dbc, key, data, flags, pgnop)
 
 		ret = __ham_item(dbc, lock_type, pgnop);
 		break;
+	default:
+		ret = __db_unknown_flag(dbp->dbenv, "__ham_c_get", flags);
+		break;
 	}
 
 	/*
@@ -515,7 +530,7 @@ __ham_c_get(dbc, key, data, flags, pgnop)
 			case DB_LAST:
 			case DB_PREV:
 			case DB_PREV_NODUP:
-				ret = mpf->put(mpf, hcp->page, 0);
+				ret = __memp_fput(mpf, hcp->page, 0);
 				hcp->page = NULL;
 				if (hcp->bucket == 0) {
 					ret = DB_NOTFOUND;
@@ -533,7 +548,7 @@ __ham_c_get(dbc, key, data, flags, pgnop)
 			case DB_FIRST:
 			case DB_NEXT:
 			case DB_NEXT_NODUP:
-				ret = mpf->put(mpf, hcp->page, 0);
+				ret = __memp_fput(mpf, hcp->page, 0);
 				hcp->page = NULL;
 				hcp->indx = NDX_INVALID;
 				hcp->bucket++;
@@ -600,11 +615,11 @@ __ham_bulk(dbc, data, flags)
 	db_indx_t dup_len, dup_off, dup_tlen, indx, *inp;
 	db_lockmode_t lock_mode;
 	db_pgno_t pgno;
-	int32_t  *endp, key_off, *offp, *saveoff;
-	u_int32_t key_size, size, space;
+	int32_t *endp, *offp, *saveoff;
+	u_int32_t key_off, key_size, pagesize, size, space;
 	u_int8_t *dbuf, *dp, *hk, *np, *tmp;
 	int is_dup, is_key;
-	int need_pg, next_key, no_dup, pagesize, ret, t_ret;
+	int need_pg, next_key, no_dup, ret, t_ret;
 
 	ret = 0;
 	key_off = 0;
@@ -653,7 +668,7 @@ next_pg:
 				    dbc, key_size, pgno, np)) != 0)
 					return (ret);
 				space -= key_size;
-				key_off = (int32_t)(np - dbuf);
+				key_off = (u_int32_t)(np - dbuf);
 				np += key_size;
 			} else {
 				if (need_pg) {
@@ -662,11 +677,11 @@ next_pg:
 					if (space < size) {
 get_key_space:
 						if (offp == endp) {
-							data->size =
-							    ALIGN(size +
-							    pagesize,
-							    sizeof(u_int32_t));
-							return (ENOMEM);
+							data->size = (u_int32_t)
+							    DB_ALIGN(size +
+							    pagesize, 1024);
+							return
+							    (DB_BUFFER_SMALL);
 						}
 						goto back_up;
 					}
@@ -677,8 +692,9 @@ get_key_space:
 					np += size;
 				}
 				key_size = LEN_HKEY(dbp, pg, pagesize, indx);
-				key_off = (int32_t)(inp[indx] - HOFFSET(pg)
-				    + dp - dbuf + SSZA(HKEYDATA, data));
+				key_off = ((inp[indx] - HOFFSET(pg)) +
+				    (u_int32_t)(dp - dbuf)) +
+				    SSZA(HKEYDATA, data);
 			}
 		}
 
@@ -716,15 +732,24 @@ back_up:
 							memcpy(&dup_len,
 							    HKEYDATA_DATA(tmp),
 							    sizeof(db_indx_t));
+						} else  {
+							is_dup = 0;
+							dup_len = 0;
+							dup_off = 0;
+							dup_tlen = 0;
+							F_CLR(cp, H_ISDUP);
 						}
 						goto get_space;
 					}
 					/* indx == 0 */
+					cp->dup_len = dup_len;
+					cp->dup_off = dup_off;
+					cp->dup_tlen = dup_tlen;
 					if ((ret = __ham_item_prev(dbc,
 					    lock_mode, &pgno)) != 0) {
 						if (ret != DB_NOTFOUND)
 							return (ret);
-						if ((ret = mpf->put(mpf,
+						if ((ret = __memp_fput(mpf,
 						    cp->page, 0)) != 0)
 							return (ret);
 						cp->page = NULL;
@@ -755,10 +780,10 @@ get_space:
 					 */
 					if (offp >= endp ||
 					    F_ISSET(dbc, DBC_TRANSIENT)) {
-						data->size = ALIGN(size +
-						    data->ulen - space,
-						    sizeof(u_int32_t));
-						return (ENOMEM);
+						data->size = (u_int32_t)
+						    DB_ALIGN(size +
+						    data->ulen - space, 1024);
+						return (DB_BUFFER_SMALL);
 					}
 					/*
 					 * Don't continue;  we're all out
@@ -806,9 +831,13 @@ get_space:
 				memcpy(&dup_len,
 				    HKEYDATA_DATA(hk), sizeof(db_indx_t));
 				dup_tlen = LEN_HDATA(dbp, pg, pagesize, indx);
-			} else
+			} else {
 				/* Case 3 */
-				is_dup = dup_len = dup_off = dup_tlen = 0;
+				is_dup = 0;
+				dup_len = 0;
+				dup_off = 0;
+				dup_tlen = 0;
+			}
 
 			do {
 				space -= (is_key ? 4 : 2) * sizeof(*offp);
@@ -823,17 +852,18 @@ get_space:
 				if (space > data->ulen) {
 					if (!is_dup || dup_off == 0)
 						goto back_up;
-					dup_off -= (db_indx_t)DUP_SIZE(offp[1]);
+					dup_off -= (db_indx_t)
+					    DUP_SIZE((u_int32_t)offp[1]);
 					goto get_space;
 				}
 				if (is_key) {
-					*offp-- = key_off;
-					*offp-- = key_size;
+					*offp-- = (int32_t)key_off;
+					*offp-- = (int32_t)key_size;
 				}
 				if (is_dup) {
 					*offp-- = (int32_t)(
-					    inp[indx + 1] - HOFFSET(pg) +
-					    dp - dbuf + SSZA(HKEYDATA, data) +
+					    ((inp[indx + 1] - HOFFSET(pg)) +
+					    dp - dbuf) + SSZA(HKEYDATA, data) +
 					    dup_off + sizeof(db_indx_t));
 					memcpy(&dup_len,
 					    HKEYDATA_DATA(hk) + dup_off,
@@ -842,8 +872,8 @@ get_space:
 					*offp-- = dup_len;
 				} else {
 					*offp-- = (int32_t)(
-					    inp[indx + 1] - HOFFSET(pg) +
-					    dp - dbuf + SSZA(HKEYDATA, data));
+					    ((inp[indx + 1] - HOFFSET(pg)) +
+					    dp - dbuf) + SSZA(HKEYDATA, data));
 					*offp-- = LEN_HDATA(dbp, pg,
 					    pagesize, indx);
 				}
@@ -860,15 +890,16 @@ get_space:
 				space -= 2 * sizeof(*offp);
 				if (space > data->ulen)
 					goto back_up;
-				*offp-- = key_off;
-				*offp-- = key_size;
+				*offp-- = (int32_t)key_off;
+				*offp-- = (int32_t)key_size;
 			}
 			saveoff = offp;
 			if ((ret = __bam_bulk_duplicates(dbc,
 			    pgno, dbuf, is_key ? offp + 2 : NULL,
 			    &offp, &np, &space, no_dup)) != 0) {
-				if (ret == ENOMEM) {
+				if (ret == DB_BUFFER_SMALL) {
 					size = space;
+					space = 0;
 					if (is_key && saveoff == offp) {
 						offp += 2;
 						goto back_up;
@@ -893,16 +924,19 @@ get_space:
 				return (ret);
 
 			if (is_key) {
-				*offp-- = key_off;
-				*offp-- = key_size;
+				*offp-- = (int32_t)key_off;
+				*offp-- = (int32_t)key_size;
 			}
 
 			*offp-- = (int32_t)(np - dbuf);
-			*offp-- = size;
+			*offp-- = (int32_t)size;
 
 			np += size;
 			space -= size;
 			break;
+		default:
+			/* Do nothing. */
+			break;
 		}
 	} while (next_key && (indx += 2) < NUM_ENT(pg));
 
@@ -917,7 +951,7 @@ get_space:
 			goto next_pg;
 		if (ret != DB_NOTFOUND)
 			return (ret);
-		if ((ret = mpf->put(dbc->dbp->mpf, cp->page, 0)) != 0)
+		if ((ret = __memp_fput(dbc->dbp->mpf, cp->page, 0)) != 0)
 			return (ret);
 		cp->page = NULL;
 		if ((ret = __ham_get_meta(dbc)) != 0)
@@ -956,7 +990,7 @@ get_space:
 		if (ret != DB_NOTFOUND)
 			return (ret);
 	}
-	*offp = (u_int32_t) -1;
+	*offp = -1;
 	return (0);
 }
 
@@ -1006,7 +1040,7 @@ __ham_c_put(dbc, key, data, flags, pgnop)
 			ret = 0;
 			if (hcp->seek_found_page != PGNO_INVALID &&
 			    hcp->seek_found_page != hcp->pgno) {
-				if ((ret = mpf->put(mpf, hcp->page, 0)) != 0)
+				if ((ret = __memp_fput(mpf, hcp->page, 0)) != 0)
 					goto err2;
 				hcp->page = NULL;
 				hcp->pgno = hcp->seek_found_page;
@@ -1043,6 +1077,9 @@ __ham_c_put(dbc, key, data, flags, pgnop)
 	case DB_CURRENT:
 		ret = __ham_item(dbc, DB_LOCK_WRITE, pgnop);
 		break;
+	default:
+		ret = __db_unknown_flag(dbp->dbenv, "__ham_c_put", flags);
+		break;
 	}
 
 	if (*pgnop == PGNO_INVALID && ret == 0) {
@@ -1055,15 +1092,19 @@ __ham_c_put(dbc, key, data, flags, pgnop)
 			ret = __ham_add_dup(dbc, data, flags, pgnop);
 	}
 
-done:	if (ret == 0 && F_ISSET(hcp, H_EXPAND)) {
+done:	if (hcp->page != NULL) {
+		if ((t_ret = __memp_fput(mpf,
+		    hcp->page, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+			ret = t_ret;
+		if (t_ret == 0)
+			hcp->page = NULL;
+	}
+
+	if (ret == 0 && F_ISSET(hcp, H_EXPAND)) {
 		ret = __ham_expand_table(dbc);
 		F_CLR(hcp, H_EXPAND);
 	}
 
-	if (hcp->page != NULL &&
-	    (t_ret = mpf->set(mpf, hcp->page, DB_MPOOL_DIRTY)) != 0 && ret == 0)
-		ret = t_ret;
-
 err2:	if ((t_ret = __ham_release_meta(dbc)) != 0 && ret == 0)
 		ret = t_ret;
 
@@ -1087,8 +1128,8 @@ __ham_expand_table(dbc)
 	HASH_CURSOR *hcp;
 	PAGE *h;
 	db_pgno_t pgno, mpgno;
-	u_int32_t newalloc, new_bucket, old_bucket;
-	int dirty_meta, got_meta, logn, new_double, ret;
+	u_int32_t dirty_meta, logn, newalloc, new_bucket, old_bucket;
+	int got_meta, new_double, ret, t_ret;
 
 	dbp = dbc->dbp;
 	mpf = dbp->mpf;
@@ -1100,9 +1141,8 @@ __ham_expand_table(dbc)
 	mmeta = (DBMETA *) hcp->hdr;
 	mpgno = mmeta->pgno;
 	h = NULL;
-	dirty_meta = 0;
+	dirty_meta = newalloc = 0;
 	got_meta = 0;
-	newalloc = 0;
 
 	/*
 	 * If the split point is about to increase, make sure that we
@@ -1132,7 +1172,7 @@ __ham_expand_table(dbc)
 		/* Page exists; get it so we can get its LSN */
 		pgno = BUCKET_TO_PAGE(hcp, new_bucket);
 		if ((ret =
-		    mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &h)) != 0)
+		    __memp_fget(mpf, &pgno, DB_MPOOL_CREATE, &h)) != 0)
 			goto err;
 		lsn = h->lsn;
 	} else {
@@ -1142,8 +1182,7 @@ __ham_expand_table(dbc)
 			if ((ret = __db_lget(dbc,
 			   0, mpgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
 				goto err;
-			if ((ret =
-			    mpf->get(mpf, &mpgno, 0, (PAGE **)&mmeta)) != 0)
+			if ((ret = __memp_fget(mpf, &mpgno, 0, &mmeta)) != 0)
 				goto err;
 			got_meta = 1;
 		}
@@ -1164,7 +1203,7 @@ __ham_expand_table(dbc)
 		if ((ret = __ham_metagroup_log(dbp, dbc->txn,
 		    &lsn, 0, hcp->hdr->max_bucket, mpgno, &mmeta->lsn,
 		    hcp->hdr->dbmeta.pgno, &hcp->hdr->dbmeta.lsn,
-		    pgno, &lsn, newalloc)) != 0)
+		    pgno, &lsn, newalloc, mmeta->last_pgno)) != 0)
 			goto err;
 	} else
 		LSN_NOT_LOGGED(lsn);
@@ -1184,20 +1223,21 @@ __ham_expand_table(dbc)
 
 		hcp->hdr->spares[logn + 1] = pgno - new_bucket;
 		pgno += hcp->hdr->max_bucket;
+
+		if ((ret = __memp_fget(mpf, &pgno, DB_MPOOL_CREATE, &h)) != 0)
+			goto err;
+
 		mmeta->last_pgno = pgno;
 		mmeta->lsn = lsn;
 		dirty_meta = DB_MPOOL_DIRTY;
 
-		if ((ret = mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &h)) != 0)
-			goto err;
-
 		P_INIT(h, dbp->pgsize,
 		    pgno, PGNO_INVALID, PGNO_INVALID, 0, P_HASH);
 	}
 
 	/* Write out whatever page we ended up modifying. */
 	h->lsn = lsn;
-	if ((ret = mpf->put(mpf, h, DB_MPOOL_DIRTY)) != 0)
+	if ((ret = __memp_fput(mpf, h, DB_MPOOL_DIRTY)) != 0)
 		goto err;
 	h = NULL;
 
@@ -1214,30 +1254,31 @@ __ham_expand_table(dbc)
 	ret = __ham_split_page(dbc, old_bucket, new_bucket);
 
 err:	if (got_meta)
-		(void)mpf->put(mpf, mmeta, dirty_meta);
-
-	if (LOCK_ISSET(metalock))
-		(void)__TLPUT(dbc, metalock);
-
+		if ((t_ret =
+		    __memp_fput(mpf, mmeta, dirty_meta)) != 0 && ret == 0)
+			ret = t_ret;
+	if ((t_ret = __TLPUT(dbc, metalock)) != 0 && ret == 0)
+			ret = t_ret;
 	if (h != NULL)
-		(void)mpf->put(mpf, h, 0);
+		if ((t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
+			ret = t_ret;
 
 	return (ret);
 }
 
 /*
- * PUBLIC: u_int32_t __ham_call_hash __P((DBC *, u_int8_t *, int32_t));
+ * PUBLIC: u_int32_t __ham_call_hash __P((DBC *, u_int8_t *, u_int32_t));
  */
 u_int32_t
 __ham_call_hash(dbc, k, len)
 	DBC *dbc;
 	u_int8_t *k;
-	int32_t len;
+	u_int32_t len;
 {
 	DB *dbp;
-	u_int32_t n, bucket;
 	HASH_CURSOR *hcp;
 	HASH *hashp;
+	u_int32_t n, bucket;
 
 	dbp = dbc->dbp;
 	hcp = (HASH_CURSOR *)dbc->internal;
@@ -1495,7 +1536,7 @@ __ham_overwrite(dbc, nval, flags)
 			 */
 			if (nval->doff > nondup_size)
 				newsize +=
-				    (nval->doff - nondup_size + nval->size);
+				    ((nval->doff - nondup_size) + nval->size);
 			else if (nval->doff + nval->dlen > nondup_size)
 				newsize += nval->size -
 				    (nondup_size - nval->doff);
@@ -1507,7 +1548,8 @@ __ham_overwrite(dbc, nval, flags)
 			 * the onpage duplicate size in which case we need
 			 * to convert to off-page duplicates.
 			 */
-			if (ISBIG(hcp, hcp->dup_tlen - nondup_size + newsize)) {
+			if (ISBIG(hcp,
+			    (hcp->dup_tlen - nondup_size) + newsize)) {
 				if ((ret = __ham_dup_convert(dbc)) != 0)
 					return (ret);
 				return (hcp->opd->c_am_put(hcp->opd,
@@ -1544,7 +1586,7 @@ __ham_overwrite(dbc, nval, flags)
 
 			/* End of original record (if there is any) */
 			if (nval->doff + nval->dlen < tmp_val.size) {
-				len = tmp_val.size - nval->doff - nval->dlen;
+				len = (tmp_val.size - nval->doff) - nval->dlen;
 				memcpy(p, (u_int8_t *)tmp_val.data +
 				    nval->doff + nval->dlen, len);
 				p += len;
@@ -1563,7 +1605,7 @@ __ham_overwrite(dbc, nval, flags)
 				tmp_val2.size = newsize;
 				if (dbp->dup_compare(
 				    dbp, &tmp_val, &tmp_val2) != 0) {
-					(void)__os_free(dbenv, newrec);
+					__os_free(dbenv, newrec);
 					return (__db_duperr(dbp, flags));
 				}
 			}
@@ -1574,7 +1616,7 @@ __ham_overwrite(dbc, nval, flags)
 			tmp_val2.dlen = DUP_SIZE(hcp->dup_len);
 
 			ret = __ham_replpair(dbc, &tmp_val2, 0);
-			(void)__os_free(dbenv, newrec);
+			__os_free(dbenv, newrec);
 
 			/* Update cursor */
 			if (ret != 0)
@@ -1584,12 +1626,12 @@ __ham_overwrite(dbc, nval, flags)
 				hcp->dup_tlen += (newsize - nondup_size);
 			else
 				hcp->dup_tlen -= (nondup_size - newsize);
-			hcp->dup_len = DUP_SIZE(newsize);
+			hcp->dup_len = newsize;
 			return (0);
 		} else {
 			/* Check whether we need to convert to off page. */
 			if (ISBIG(hcp,
-			    hcp->dup_tlen - hcp->dup_len + nval->size)) {
+			    (hcp->dup_tlen - hcp->dup_len) + nval->size)) {
 				if ((ret = __ham_dup_convert(dbc)) != 0)
 					return (ret);
 				return (hcp->opd->c_am_put(hcp->opd,
@@ -1603,8 +1645,12 @@ __ham_overwrite(dbc, nval, flags)
 				    hcp->indx)) + hcp->dup_off +
 				    sizeof(db_indx_t);
 				tmp_val2.size = hcp->dup_len;
-				if (dbp->dup_compare(dbp, nval, &tmp_val2) != 0)
+				if (dbp->dup_compare(
+				    dbp, nval, &tmp_val2) != 0) {
+					__db_err(dbenv,
+			"Existing data sorts differently from put data");
 					return (EINVAL);
+				}
 			}
 			/* Overwriting a complete duplicate. */
 			if ((ret =
@@ -1620,7 +1666,7 @@ __ham_overwrite(dbc, nval, flags)
 				hcp->dup_tlen += (nval->size - hcp->dup_len);
 			else
 				hcp->dup_tlen -= (hcp->dup_len - nval->size);
-			hcp->dup_len = (db_indx_t)DUP_SIZE(nval->size);
+			hcp->dup_len = (db_indx_t)nval->size;
 		}
 		myval = &tmp_val;
 	} else if (!F_ISSET(nval, DB_DBT_PARTIAL)) {
@@ -1723,6 +1769,8 @@ found_key:			F_SET(hcp, H_OK);
 			 * duplicated, only data items are.
 			 */
 			return (__db_pgfmt(dbp->dbenv, PGNO(hcp->page)));
+		default:
+			return (__db_pgfmt(dbp->dbenv, PGNO(hcp->page)));
 		}
 	}
 
@@ -1977,7 +2025,8 @@ __ham_get_clist(dbp, pgno, indx, listp)
 	DB *ldbp;
 	DBC *cp;
 	DB_ENV *dbenv;
-	int nalloc, nused, ret;
+	u_int nalloc, nused;
+	int ret;
 
 	/*
 	 * Assume that finding anything is the exception, so optimize for
@@ -2036,7 +2085,6 @@ static int
 __ham_c_writelock(dbc)
 	DBC *dbc;
 {
-	DB_ENV *dbenv;
 	DB_LOCK tmp_lock;
 	HASH_CURSOR *hcp;
 	int ret;
@@ -2049,14 +2097,12 @@ __ham_c_writelock(dbc)
 		return (0);
 
 	hcp = (HASH_CURSOR *)dbc->internal;
-	if ((!LOCK_ISSET(hcp->lock) || hcp->lock_mode == DB_LOCK_READ)) {
+	ret = 0;
+	if ((!LOCK_ISSET(hcp->lock) || hcp->lock_mode != DB_LOCK_WRITE)) {
 		tmp_lock = hcp->lock;
-		if ((ret = __ham_lock_bucket(dbc, DB_LOCK_WRITE)) != 0)
-			return (ret);
-		dbenv = dbc->dbp->dbenv;
-		if (LOCK_ISSET(tmp_lock) &&
-		    (ret = dbenv->lock_put(dbenv, &tmp_lock)) != 0)
-			return (ret);
+		if ((ret = __ham_lock_bucket(dbc, DB_LOCK_WRITE)) == 0 &&
+		    tmp_lock.mode != DB_LOCK_WWRITE)
+			ret = __LPUT(dbc, tmp_lock);
 	}
-	return (0);
+	return (ret);
 }
diff --git a/storage/bdb/hash/hash.src b/storage/bdb/hash/hash.src
index b4b633c56e6234021c93a1b099708b409cde39d1..4acff5e5928e82f9af5a6750b6feb165bebc8f64 100644
--- a/storage/bdb/hash/hash.src
+++ b/storage/bdb/hash/hash.src
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: hash.src,v 10.38 2002/04/17 19:03:10 krinsky Exp $
+ * $Id: hash.src,v 10.44 2004/06/17 17:35:21 bostic Exp $
  */
 /*
  * Copyright (c) 1995, 1996
@@ -45,8 +45,6 @@
 PREFIX	__ham
 DBPRIVATE
 
-INCLUDE	#include "db_config.h"
-INCLUDE
 INCLUDE #ifndef NO_SYSTEM_INCLUDES
 INCLUDE #include <sys/types.h>
 INCLUDE
@@ -60,7 +58,6 @@ INCLUDE #include "dbinc/db_page.h"
 INCLUDE #include "dbinc/db_dispatch.h"
 INCLUDE #include "dbinc/db_am.h"
 INCLUDE #include "dbinc/hash.h"
-INCLUDE #include "dbinc/rep.h"
 INCLUDE #include "dbinc/log.h"
 INCLUDE #include "dbinc/txn.h"
 INCLUDE
@@ -80,7 +77,7 @@ INCLUDE
 BEGIN insdel		21
 ARG	opcode		u_int32_t	lu
 DB	fileid		int32_t		ld
-WRLOCK	pgno		db_pgno_t	lu
+ARG	pgno		db_pgno_t	lu
 ARG	ndx		u_int32_t	lu
 POINTER	pagelsn		DB_LSN *	lu
 DBT	key		DBT		s
@@ -100,11 +97,11 @@ END
 BEGIN newpage		22
 ARG	opcode		u_int32_t	lu
 DB	fileid		int32_t		ld
-WRLOCKNZ prev_pgno	db_pgno_t	lu
+ARG	prev_pgno	db_pgno_t	lu
 POINTER	prevlsn		DB_LSN *	lu
-WRLOCKNZ new_pgno	db_pgno_t	lu
+ARG	new_pgno	db_pgno_t	lu
 POINTER	pagelsn		DB_LSN *	lu
-WRLOCKNZ next_pgno	db_pgno_t	lu
+ARG	next_pgno	db_pgno_t	lu
 POINTER	nextlsn		DB_LSN *	lu
 END
 
@@ -117,7 +114,7 @@ END
 BEGIN splitdata		24
 DB	fileid		int32_t		ld
 ARG	opcode		u_int32_t	lu
-WRLOCK	pgno		db_pgno_t	lu
+ARG	pgno		db_pgno_t	lu
 PGDBT	pageimage	DBT		s
 POINTER	pagelsn		DB_LSN *	lu
 END
@@ -136,7 +133,7 @@ END
  */
 BEGIN replace		25
 DB	fileid		int32_t		ld
-WRLOCK	pgno		db_pgno_t	lu
+ARG	pgno		db_pgno_t	lu
 ARG	ndx		u_int32_t	lu
 POINTER	pagelsn		DB_LSN *	lu
 ARG	off		int32_t		ld
@@ -157,11 +154,11 @@ END
  */
 BEGIN copypage		28
 DB	fileid		int32_t		ld
-WRLOCK	pgno		db_pgno_t	lu
+ARG	pgno		db_pgno_t	lu
 POINTER	pagelsn		DB_LSN *	lu
-WRLOCK	next_pgno	db_pgno_t	lu
+ARG	next_pgno	db_pgno_t	lu
 POINTER	nextlsn		DB_LSN *	lu
-WRLOCKNZ nnext_pgno	db_pgno_t	lu
+ARG	nnext_pgno	db_pgno_t	lu
 POINTER	nnextlsn	DB_LSN *	lu
 PGDBT	page		DBT		s
 END
@@ -185,17 +182,19 @@ END
  * newalloc:	1 indicates that this record did the actual allocation;
  *		0 indicates that the pages were already allocated from a
  *		previous (failed) allocation.
+ * last_pgno:	the last page in the file before this op.
  */
 BEGIN metagroup		29
 DB	fileid		int32_t		ld
 ARG	bucket		u_int32_t	lu
-WRLOCK  mmpgno		db_pgno_t	lu
+ARG	 mmpgno		db_pgno_t	lu
 POINTER	mmetalsn	DB_LSN *	lu
-WRLOCKNZ mpgno		db_pgno_t	lu
+ARG	mpgno		db_pgno_t	lu
 POINTER	metalsn		DB_LSN *	lu
-WRLOCK	pgno		db_pgno_t	lu
+ARG	pgno		db_pgno_t	lu
 POINTER	pagelsn		DB_LSN *	lu
 ARG	newalloc	u_int32_t	lu
+ARG	last_pgno	db_pgno_t	lu
 END
 
 /*
@@ -209,13 +208,15 @@ END
  * metalsn: meta-data lsn
  * start_pgno: starting page number
  * num: number of allocated pages
+ * last_pgno:	the last page in the file before this op.
  */
 BEGIN groupalloc	32
 DB	fileid		int32_t		ld
 POINTER	meta_lsn	DB_LSN *	lu
-WRLOCK	start_pgno	db_pgno_t	lu
+ARG	start_pgno	db_pgno_t	lu
 ARG	num		u_int32_t	lu
 ARG	free		db_pgno_t	lu
+ARG	last_pgno	db_pgno_t	lu
 END
 
 /*
diff --git a/storage/bdb/hash/hash_conv.c b/storage/bdb/hash/hash_conv.c
index a93e56a2ee489a827f30b369aa5f6da876002297..a90799c7b25da3608b6d4b85c82eb26d1e09c7b1 100644
--- a/storage/bdb/hash/hash_conv.c
+++ b/storage/bdb/hash/hash_conv.c
@@ -1,14 +1,13 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: hash_conv.c,v 11.16 2004/03/24 20:37:38 bostic Exp $
  */
-#include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: hash_conv.c,v 11.13 2002/08/06 05:34:35 bostic Exp $";
-#endif /* not lint */
+#include "db_config.h"
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
@@ -110,7 +109,7 @@ __ham_mswap(pg)
 	SWAP32(p);		/* h_charkey */
 	for (i = 0; i < NCACHED; ++i)
 		SWAP32(p);	/* spares */
-	p += 59 * sizeof(u_int32_t); /* unusued */
+	p += 59 * sizeof(u_int32_t); /* unused */
 	SWAP32(p);		/* crypto_magic */
 	return (0);
 }
diff --git a/storage/bdb/hash/hash_dup.c b/storage/bdb/hash/hash_dup.c
index ec70e519d54038f6fe2ab564a186e6a0a357197d..93fc2b51f62cbbf863b0931db45673c767eba09d 100644
--- a/storage/bdb/hash/hash_dup.c
+++ b/storage/bdb/hash/hash_dup.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -34,12 +34,11 @@
  * 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.
+ *
+ * $Id: hash_dup.c,v 11.85 2004/06/03 16:32:21 margo Exp $
  */
-#include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: hash_dup.c,v 11.76 2002/08/06 05:34:40 bostic Exp $";
-#endif /* not lint */
+#include "db_config.h"
 
 /*
  * PACKAGE:  hashing
@@ -56,8 +55,10 @@ static const char revid[] = "$Id: hash_dup.c,v 11.76 2002/08/06 05:34:40 bostic
 
 #include "db_int.h"
 #include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
 #include "dbinc/hash.h"
 #include "dbinc/btree.h"
+#include "dbinc/mp.h"
 
 static int __ham_c_chgpg __P((DBC *,
     db_pgno_t, u_int32_t, db_pgno_t, u_int32_t));
@@ -198,11 +199,15 @@ __ham_add_dup(dbc, nval, flags, pgnop)
 		case DB_AFTER:
 			tmp_val.doff = hcp->dup_off + DUP_SIZE(hcp->dup_len);
 			break;
+		default:
+			DB_ASSERT(0);
+			return (EINVAL);
 		}
+
 		/* Add the duplicate. */
 		ret = __ham_replpair(dbc, &tmp_val, 0);
 		if (ret == 0)
-			ret = mpf->set(mpf, hcp->page, DB_MPOOL_DIRTY);
+			ret = __memp_fset(mpf, hcp->page, DB_MPOOL_DIRTY);
 		if (ret != 0)
 			return (ret);
 
@@ -213,12 +218,16 @@ __ham_add_dup(dbc, nval, flags, pgnop)
 			hcp->dup_len = nval->size;
 			hcp->dup_tlen += (db_indx_t)DUP_SIZE(nval->size);
 			break;
+		case DB_BEFORE:
 		case DB_KEYFIRST:
 		case DB_KEYLAST:
-		case DB_BEFORE:
+		case DB_NODUPDATA:
 			hcp->dup_tlen += (db_indx_t)DUP_SIZE(nval->size);
 			hcp->dup_len = nval->size;
 			break;
+		default:
+			DB_ASSERT(0);
+			return (EINVAL);
 		}
 		ret = __ham_c_update(dbc, tmp_val.size, 1, 1);
 		return (ret);
@@ -302,7 +311,7 @@ __ham_dup_convert(dbc)
 
 		ret = __db_pitem(dbc, dp, 0, dbt.size, &dbt, NULL);
 finish:		if (ret == 0) {
-			if ((ret = mpf->set(mpf, dp, DB_MPOOL_DIRTY)) != 0)
+			if ((ret = __memp_fset(mpf, dp, DB_MPOOL_DIRTY)) != 0)
 				break;
 
 			/* Update any other cursors. */
@@ -358,7 +367,7 @@ finish:		if (ret == 0) {
 		}
 		break;
 	default:
-		ret = __db_pgfmt(dbp->dbenv, (u_long)hcp->pgno);
+		ret = __db_pgfmt(dbp->dbenv, hcp->pgno);
 		break;
 	}
 
@@ -371,10 +380,10 @@ finish:		if (ret == 0) {
 		    (u_int32_t)H_DATAINDEX(hcp->indx), PGNO(dp));
 
 err:	if (ret == 0)
-		ret = mpf->set(mpf, hcp->page, DB_MPOOL_DIRTY);
+		ret = __memp_fset(mpf, hcp->page, DB_MPOOL_DIRTY);
 
-	if ((t_ret =
-	    mpf->put(mpf, dp, ret == 0 ? DB_MPOOL_DIRTY : 0)) != 0 && ret == 0)
+	if ((t_ret = __memp_fput(
+	    mpf, dp, ret == 0 ? DB_MPOOL_DIRTY : 0)) != 0 && ret == 0)
 		ret = t_ret;
 
 	if (ret == 0)
@@ -472,8 +481,9 @@ __ham_check_move(dbc, add_len)
 	if (HPAGE_PTYPE(hk) == H_OFFDUP || HPAGE_PTYPE(hk) == H_OFFPAGE)
 		return (0);
 
-	old_len = LEN_HITEM(dbp, hcp->page, dbp->pgsize, H_DATAINDEX(hcp->indx));
-	new_datalen = old_len - HKEYDATA_SIZE(0) + add_len;
+	old_len =
+	    LEN_HITEM(dbp, hcp->page, dbp->pgsize, H_DATAINDEX(hcp->indx));
+	new_datalen = (old_len - HKEYDATA_SIZE(0)) + add_len;
 	if (HPAGE_PTYPE(hk) != H_DUPLICATE)
 		new_datalen += DUP_SIZE(0);
 
@@ -501,16 +511,17 @@ __ham_check_move(dbc, add_len)
 
 	new_datalen = ISBIG(hcp, new_datalen) ?
 	    HOFFDUP_SIZE : HKEYDATA_SIZE(new_datalen);
-	new_datalen += LEN_HITEM(dbp, hcp->page, dbp->pgsize, H_KEYINDEX(hcp->indx));
+	new_datalen +=
+	    LEN_HITEM(dbp, hcp->page, dbp->pgsize, H_KEYINDEX(hcp->indx));
 
 	next_pagep = NULL;
 	for (next_pgno = NEXT_PGNO(hcp->page); next_pgno != PGNO_INVALID;
 	    next_pgno = NEXT_PGNO(next_pagep)) {
 		if (next_pagep != NULL &&
-		    (ret = mpf->put(mpf, next_pagep, 0)) != 0)
+		    (ret = __memp_fput(mpf, next_pagep, 0)) != 0)
 			return (ret);
 
-		if ((ret = mpf->get(mpf,
+		if ((ret = __memp_fget(mpf,
 		    &next_pgno, DB_MPOOL_CREATE, &next_pagep)) != 0)
 			return (ret);
 
@@ -526,7 +537,7 @@ __ham_check_move(dbc, add_len)
 	/* Add new page at the end of the chain. */
 	if (P_FREESPACE(dbp, next_pagep) < new_datalen && (ret =
 	    __ham_add_ovflpage(dbc, next_pagep, 1, &next_pagep)) != 0) {
-		(void)mpf->put(mpf, next_pagep, 0);
+		(void)__memp_fput(mpf, next_pagep, 0);
 		return (ret);
 	}
 
@@ -552,11 +563,11 @@ __ham_check_move(dbc, add_len)
 			d.data = H_PAIRDATA(dbp, hcp->page, hcp->indx);
 			d.size = HOFFPAGE_SIZE;
 		} else {
-			if (HPAGE_PTYPE(H_PAIRDATA(dbp, hcp->page, hcp->indx))
-			    == H_DUPLICATE)
+			if (HPAGE_PTYPE(H_PAIRDATA(dbp,
+			    hcp->page, hcp->indx)) == H_DUPLICATE)
 				rectype |= PAIR_DUPMASK;
-			d.data =
-			    HKEYDATA_DATA(H_PAIRDATA(dbp, hcp->page, hcp->indx));
+			d.data = HKEYDATA_DATA(
+			    H_PAIRDATA(dbp, hcp->page, hcp->indx));
 			d.size = LEN_HDATA(dbp, hcp->page,
 			    dbp->pgsize, hcp->indx);
 		}
@@ -565,7 +576,7 @@ __ham_check_move(dbc, add_len)
 		    dbc->txn, &new_lsn, 0, rectype, PGNO(next_pagep),
 		    (u_int32_t)NUM_ENT(next_pagep), &LSN(next_pagep),
 		    &k, &d)) != 0) {
-			(void)mpf->put(mpf, next_pagep, 0);
+			(void)__memp_fput(mpf, next_pagep, 0);
 			return (ret);
 		}
 	} else
@@ -588,7 +599,7 @@ __ham_check_move(dbc, add_len)
 	 * Note that __ham_del_pair should dirty the page we're moving
 	 * the items from, so we need only dirty the new page ourselves.
 	 */
-	if ((ret = mpf->set(mpf, next_pagep, DB_MPOOL_DIRTY)) != 0)
+	if ((ret = __memp_fset(mpf, next_pagep, DB_MPOOL_DIRTY)) != 0)
 		goto out;
 
 	/* Update all cursors that used to point to this item. */
@@ -613,7 +624,7 @@ __ham_check_move(dbc, add_len)
 		hcp->hdr->nelem++;
 
 out:
-	(void)mpf->put(mpf, hcp->page, DB_MPOOL_DIRTY);
+	(void)__memp_fput(mpf, hcp->page, DB_MPOOL_DIRTY);
 	hcp->page = next_pagep;
 	hcp->pgno = PGNO(hcp->page);
 	hcp->indx = NUM_ENT(hcp->page) - 2;
@@ -645,7 +656,7 @@ __ham_move_offpage(dbc, pagep, ndx, pgno)
 	DBT old_dbt;
 	HOFFDUP od;
 	db_indx_t i, *inp;
-	int32_t shrink;
+	int32_t difflen;
 	u_int8_t *src;
 	int ret;
 
@@ -669,18 +680,24 @@ __ham_move_offpage(dbc, pagep, ndx, pgno)
 	} else
 		LSN_NOT_LOGGED(LSN(pagep));
 
-	shrink = LEN_HITEM(dbp, pagep, dbp->pgsize, ndx) - HOFFDUP_SIZE;
-	inp = P_INP(dbp, pagep);
-
-	if (shrink != 0) {
+	/*
+	 * difflen is the difference in the lengths, and so may be negative.
+	 * We know that the difference between two unsigned lengths from a
+	 * database page will fit into an int32_t.
+	 */
+	difflen =
+	    (int32_t)LEN_HITEM(dbp, pagep, dbp->pgsize, ndx) -
+	    (int32_t)HOFFDUP_SIZE;
+	if (difflen != 0) {
 		/* Copy data. */
+		inp = P_INP(dbp, pagep);
 		src = (u_int8_t *)(pagep) + HOFFSET(pagep);
-		memmove(src + shrink, src, inp[ndx] - HOFFSET(pagep));
-		HOFFSET(pagep) += shrink;
+		memmove(src + difflen, src, inp[ndx] - HOFFSET(pagep));
+		HOFFSET(pagep) += difflen;
 
 		/* Update index table. */
 		for (i = ndx; i < NUM_ENT(pagep); i++)
-			inp[i] += shrink;
+			inp[i] += difflen;
 	}
 
 	/* Now copy the offdup entry onto the page. */
@@ -717,6 +734,7 @@ __ham_dsearch(dbc, dbt, offp, cmpp, flags)
 	i = F_ISSET(hcp, H_CONTINUE) ? hcp->dup_off: 0;
 	data = HKEYDATA_DATA(H_PAIRDATA(dbp, hcp->page, hcp->indx)) + i;
 	hcp->dup_tlen = LEN_HDATA(dbp, hcp->page, dbp->pgsize, hcp->indx);
+	len = hcp->dup_len;
 	while (i < hcp->dup_tlen) {
 		memcpy(&len, data, sizeof(db_indx_t));
 		data += sizeof(db_indx_t);
@@ -748,30 +766,6 @@ __ham_dsearch(dbc, dbt, offp, cmpp, flags)
 	F_SET(hcp, H_ISDUP);
 }
 
-#ifdef DEBUG
-/*
- * __ham_cprint --
- *	Display the current cursor list.
- *
- * PUBLIC: void __ham_cprint __P((DBC *));
- */
-void
-__ham_cprint(dbc)
-	DBC *dbc;
-{
-	HASH_CURSOR *cp;
-
-	cp = (HASH_CURSOR *)dbc->internal;
-
-	fprintf(stderr, "%#0lx->%#0lx: page: %lu index: %lu",
-	    P_TO_ULONG(dbc), P_TO_ULONG(cp), (u_long)cp->pgno,
-	    (u_long)cp->indx);
-	if (F_ISSET(cp, H_DELETED))
-		fprintf(stderr, " (deleted)");
-	fprintf(stderr, "\n");
-}
-#endif /* DEBUG */
-
 /*
  * __ham_dcursor --
  *
diff --git a/storage/bdb/hash/hash_func.c b/storage/bdb/hash/hash_func.c
index c6cc2ad4460e850e3802c2533c1bca738862ff7a..b117fcee3231d8b5383c867af791d4fa15a51782 100644
--- a/storage/bdb/hash/hash_func.c
+++ b/storage/bdb/hash/hash_func.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -38,19 +38,19 @@
  * 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.
+ *
+ * $Id: hash_func.c,v 11.15 2004/01/28 03:36:11 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: hash_func.c,v 11.12 2002/03/28 19:49:42 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #endif
 
 #include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/hash.h"
 
 /*
  * __ham_func2 --
diff --git a/storage/bdb/hash/hash_meta.c b/storage/bdb/hash/hash_meta.c
index 9f224454869babb01fe044baa55a4b633bf54454..6d700fcc1ea2fc915470083a76a943544a86830a 100644
--- a/storage/bdb/hash/hash_meta.c
+++ b/storage/bdb/hash/hash_meta.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: hash_meta.c,v 11.31 2004/09/22 03:46:22 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: hash_meta.c,v 11.19 2002/06/03 14:22:15 ubell Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #endif
@@ -20,6 +18,7 @@ static const char revid[] = "$Id: hash_meta.c,v 11.19 2002/06/03 14:22:15 ubell
 #include "dbinc/db_shash.h"
 #include "dbinc/hash.h"
 #include "dbinc/lock.h"
+#include "dbinc/mp.h"
 
 /*
  * Acquire the meta-data page.
@@ -31,31 +30,23 @@ __ham_get_meta(dbc)
 	DBC *dbc;
 {
 	DB *dbp;
-	DB_ENV *dbenv;
 	DB_MPOOLFILE *mpf;
 	HASH *hashp;
 	HASH_CURSOR *hcp;
 	int ret;
 
 	dbp = dbc->dbp;
-	dbenv = dbp->dbenv;
 	mpf = dbp->mpf;
 	hashp = dbp->h_internal;
 	hcp = (HASH_CURSOR *)dbc->internal;
 
-	if (dbenv != NULL &&
-	    STD_LOCKING(dbc) && !F_ISSET(dbc, DBC_RECOVER | DBC_COMPENSATE)) {
-		dbc->lock.pgno = hashp->meta_pgno;
-		if ((ret = dbenv->lock_get(dbenv, dbc->locker,
-		    DB_NONBLOCK(dbc) ? DB_LOCK_NOWAIT : 0,
-		    &dbc->lock_dbt, DB_LOCK_READ, &hcp->hlock)) != 0)
-			return (ret);
-	}
+	if ((ret = __db_lget(dbc, 0,
+	     hashp->meta_pgno, DB_LOCK_READ, 0, &hcp->hlock)) != 0)
+		return (ret);
 
-	if ((ret = mpf->get(mpf,
-	    &hashp->meta_pgno, DB_MPOOL_CREATE, &(hcp->hdr))) != 0 &&
-	    LOCK_ISSET(hcp->hlock))
-		(void)dbenv->lock_put(dbenv, &hcp->hlock);
+	if ((ret = __memp_fget(mpf,
+	    &hashp->meta_pgno, DB_MPOOL_CREATE, &(hcp->hdr))) != 0)
+		(void)__LPUT(dbc, hcp->hlock);
 
 	return (ret);
 }
@@ -76,15 +67,12 @@ __ham_release_meta(dbc)
 	hcp = (HASH_CURSOR *)dbc->internal;
 
 	if (hcp->hdr)
-		(void)mpf->put(mpf, hcp->hdr,
+		(void)__memp_fput(mpf, hcp->hdr,
 		    F_ISSET(hcp, H_DIRTY) ? DB_MPOOL_DIRTY : 0);
 	hcp->hdr = NULL;
-	if (!F_ISSET(dbc, DBC_RECOVER | DBC_COMPENSATE) &&
-	    dbc->txn == NULL && LOCK_ISSET(hcp->hlock))
-		(void)dbc->dbp->dbenv->lock_put(dbc->dbp->dbenv, &hcp->hlock);
 	F_CLR(hcp, H_DIRTY);
 
-	return (0);
+	return (__TLPUT(dbc, hcp->hlock));
 }
 
 /*
@@ -97,8 +85,6 @@ __ham_dirty_meta(dbc)
 	DBC *dbc;
 {
 	DB *dbp;
-	DB_ENV *dbenv;
-	DB_LOCK _tmp;
 	HASH *hashp;
 	HASH_CURSOR *hcp;
 	int ret;
@@ -108,16 +94,9 @@ __ham_dirty_meta(dbc)
 	hcp = (HASH_CURSOR *)dbc->internal;
 
 	ret = 0;
-	if (STD_LOCKING(dbc) && !F_ISSET(dbc, DBC_RECOVER | DBC_COMPENSATE)) {
-		dbenv = dbp->dbenv;
-		dbc->lock.pgno = hashp->meta_pgno;
-		if ((ret = dbenv->lock_get(dbenv, dbc->locker,
-		    DB_NONBLOCK(dbc) ? DB_LOCK_NOWAIT : 0,
-		    &dbc->lock_dbt, DB_LOCK_WRITE, &_tmp)) == 0) {
-			ret = dbenv->lock_put(dbenv, &hcp->hlock);
-			hcp->hlock = _tmp;
-		}
-	}
+
+	ret = __db_lget(dbc, LCK_COUPLE,
+	     hashp->meta_pgno, DB_LOCK_WRITE, 0, &hcp->hlock);
 
 	if (ret == 0)
 		F_SET(hcp, H_DIRTY);
diff --git a/storage/bdb/hash/hash_method.c b/storage/bdb/hash/hash_method.c
index 9a6bf59536a432c3c6da5e068be32b548c9a33e3..6b59787a672c550a9575c02937dee3d3fe18bfae 100644
--- a/storage/bdb/hash/hash_method.c
+++ b/storage/bdb/hash/hash_method.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: hash_method.c,v 11.17 2004/01/28 03:36:11 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: hash_method.c,v 11.12 2002/03/27 04:32:12 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #endif
@@ -47,8 +45,10 @@ __ham_db_create(dbp)
 	hashp->h_ffactor = 0;
 	hashp->h_hash = NULL;
 
+	dbp->get_h_ffactor = __ham_get_h_ffactor;
 	dbp->set_h_ffactor = __ham_set_h_ffactor;
 	dbp->set_h_hash = __ham_set_h_hash;
+	dbp->get_h_nelem = __ham_get_h_nelem;
 	dbp->set_h_nelem = __ham_set_h_nelem;
 
 	return (0);
@@ -68,6 +68,23 @@ __ham_db_close(dbp)
 	return (0);
 }
 
+/*
+ * __ham_get_h_ffactor --
+ *
+ * PUBLIC: int __ham_get_h_ffactor __P((DB *, u_int32_t *));
+ */
+int
+__ham_get_h_ffactor(dbp, h_ffactorp)
+	DB *dbp;
+	u_int32_t *h_ffactorp;
+{
+	HASH *hashp;
+
+	hashp = dbp->h_internal;
+	*h_ffactorp = hashp->h_ffactor;
+	return (0);
+}
+
 /*
  * __ham_set_h_ffactor --
  *	Set the fill factor.
@@ -79,7 +96,7 @@ __ham_set_h_ffactor(dbp, h_ffactor)
 {
 	HASH *hashp;
 
-	DB_ILLEGAL_AFTER_OPEN(dbp, "set_h_ffactor");
+	DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_h_ffactor");
 	DB_ILLEGAL_METHOD(dbp, DB_OK_HASH);
 
 	hashp = dbp->h_internal;
@@ -98,7 +115,7 @@ __ham_set_h_hash(dbp, func)
 {
 	HASH *hashp;
 
-	DB_ILLEGAL_AFTER_OPEN(dbp, "set_h_hash");
+	DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_h_hash");
 	DB_ILLEGAL_METHOD(dbp, DB_OK_HASH);
 
 	hashp = dbp->h_internal;
@@ -106,6 +123,25 @@ __ham_set_h_hash(dbp, func)
 	return (0);
 }
 
+/*
+ * __db_get_h_nelem --
+ *
+ * PUBLIC: int __ham_get_h_nelem __P((DB *, u_int32_t *));
+ */
+int
+__ham_get_h_nelem(dbp, h_nelemp)
+	DB *dbp;
+	u_int32_t *h_nelemp;
+{
+	HASH *hashp;
+
+	DB_ILLEGAL_METHOD(dbp, DB_OK_HASH);
+
+	hashp = dbp->h_internal;
+	*h_nelemp = hashp->h_nelem;
+	return (0);
+}
+
 /*
  * __ham_set_h_nelem --
  *	Set the table size.
@@ -117,7 +153,7 @@ __ham_set_h_nelem(dbp, h_nelem)
 {
 	HASH *hashp;
 
-	DB_ILLEGAL_AFTER_OPEN(dbp, "set_h_nelem");
+	DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_h_nelem");
 	DB_ILLEGAL_METHOD(dbp, DB_OK_HASH);
 
 	hashp = dbp->h_internal;
diff --git a/storage/bdb/hash/hash_open.c b/storage/bdb/hash/hash_open.c
index f976f5b681609e4bc82603cf8c4db1e31f674320..67b12e5eba56ef736d8a1bbd13e3212a2ea5a811 100644
--- a/storage/bdb/hash/hash_open.c
+++ b/storage/bdb/hash/hash_open.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -38,18 +38,15 @@
  * 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.
+ *
+ * $Id: hash_open.c,v 11.191 2004/06/22 18:43:38 margo Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: hash_open.c,v 11.175 2002/09/04 19:06:44 margo Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
-#include <stdlib.h>
 #include <string.h>
 #endif
 
@@ -60,6 +57,7 @@ static const char revid[] = "$Id: hash_open.c,v 11.175 2002/09/04 19:06:44 margo
 #include "dbinc/log.h"
 #include "dbinc/db_shash.h"
 #include "dbinc/lock.h"
+#include "dbinc/mp.h"
 #include "dbinc/db_swap.h"
 #include "dbinc/btree.h"
 #include "dbinc/fop.h"
@@ -82,18 +80,12 @@ __ham_open(dbp, txn, name, base_pgno, flags)
 {
 	DB_ENV *dbenv;
 	DBC *dbc;
-	DB_MPOOLFILE *mpf;
 	HASH_CURSOR *hcp;
 	HASH *hashp;
 	int ret, t_ret;
 
-	COMPQUIET(name, NULL);
 	dbenv = dbp->dbenv;
 	dbc = NULL;
-	mpf = dbp->mpf;
-
-	/* Initialize the remaining fields/methods of the DB. */
-	dbp->stat = __ham_stat;
 
 	/*
 	 * Get a cursor.  If DB_CREATE is specified, we may be creating
@@ -101,7 +93,7 @@ __ham_open(dbp, txn, name, base_pgno, flags)
 	 * In STD_LOCKING mode, we'll synchronize using the meta page
 	 * lock instead.
 	 */
-	if ((ret = dbp->cursor(dbp,
+	if ((ret = __db_cursor(dbp,
 	    txn, &dbc, LF_ISSET(DB_CREATE) && CDB_LOCKING(dbenv) ?
 	    DB_WRITECURSOR : 0)) != 0)
 		return (ret);
@@ -133,20 +125,16 @@ __ham_open(dbp, txn, name, base_pgno, flags)
 		if (F_ISSET(&hcp->hdr->dbmeta, DB_HASH_SUBDB))
 			F_SET(dbp, DB_AM_SUBDB);
 
-		/* We must initialize last_pgno, it could be stale. */
-		if (!F_ISSET(dbp, DB_AM_RDONLY) &&
-		    dbp->meta_pgno == PGNO_BASE_MD) {
-			if ((ret = __ham_dirty_meta(dbc)) != 0)
-				goto err2;
-			mpf->last_pgno(mpf, &hcp->hdr->dbmeta.last_pgno);
-		}
-	} else if (!IS_RECOVERING(dbenv) && !F_ISSET(dbp, DB_AM_RECOVER))
-		DB_ASSERT(0);
+	} else if (!IS_RECOVERING(dbenv) && !F_ISSET(dbp, DB_AM_RECOVER)) {
+		__db_err(dbp->dbenv,
+		    "%s: Invalid hash meta page %d", name, base_pgno);
+		ret = EINVAL;
+	}
 
 err2:	/* Release the meta data page */
 	if ((t_ret = __ham_release_meta(dbc)) != 0 && ret == 0)
 		ret = t_ret;
-err1:	if ((t_ret  = dbc->c_close(dbc)) != 0 && ret == 0)
+err1:	if ((t_ret  = __db_c_close(dbc)) != 0 && ret == 0)
 		ret = t_ret;
 
 	return (ret);
@@ -269,8 +257,7 @@ __ham_init_meta(dbp, meta, pgno, lsnp)
 {
 	HASH *hashp;
 	db_pgno_t nbuckets;
-	int i;
-	int32_t l2;
+	u_int i, l2;
 
 	hashp = dbp->h_internal;
 	if (hashp->h_hash == NULL)
@@ -341,8 +328,8 @@ __ham_init_meta(dbp, meta, pgno, lsnp)
  * This code appears more complex than it is because of the two cases (named
  * and unnamed).  The way to read the code is that for each page being created,
  * there are three parts: 1) a "get page" chunk (which either uses malloc'd
- * memory or calls mpf->get), 2) the initialization, and 3) the "put page"
- * chunk which either does a fop write or an mpf->put.
+ * memory or calls __memp_fget), 2) the initialization, and 3) the "put page"
+ * chunk which either does a fop write or an __memp_fput.
  *
  * PUBLIC: int __ham_new_file __P((DB *, DB_TXN *, DB_FH *, const char *));
  */
@@ -368,74 +355,81 @@ __ham_new_file(dbp, txn, fhp, name)
 	mpf = dbp->mpf;
 	meta = NULL;
 	page = NULL;
-	memset(&pdbt, 0, sizeof(pdbt));
+	buf = NULL;
 
-	/* Build meta-data page. */
 	if (name == NULL) {
+		/* Build meta-data page. */
 		lpgno = PGNO_BASE_MD;
-		ret = mpf->get(mpf, &lpgno, DB_MPOOL_CREATE, &meta);
+		if ((ret =
+		   __memp_fget(mpf, &lpgno, DB_MPOOL_CREATE, &meta)) != 0)
+			return (ret);
+		LSN_NOT_LOGGED(lsn);
+		lpgno = __ham_init_meta(dbp, meta, PGNO_BASE_MD, &lsn);
+		meta->dbmeta.last_pgno = lpgno;
+		ret = __memp_fput(mpf, meta, DB_MPOOL_DIRTY);
+		meta = NULL;
+		if (ret != 0)
+			goto err;
+
+		/* Allocate the final hash bucket. */
+		if ((ret =
+		    __memp_fget(mpf, &lpgno, DB_MPOOL_CREATE, &page)) != 0)
+			goto err;
+		P_INIT(page,
+		    dbp->pgsize, lpgno, PGNO_INVALID, PGNO_INVALID, 0, P_HASH);
+		LSN_NOT_LOGGED(page->lsn);
+		ret = __memp_fput(mpf, page, DB_MPOOL_DIRTY);
+		page = NULL;
+		if (ret != 0)
+			goto err;
 	} else {
+		memset(&pdbt, 0, sizeof(pdbt));
+
+		/* Build meta-data page. */
 		pginfo.db_pagesize = dbp->pgsize;
 		pginfo.type = dbp->type;
 		pginfo.flags =
 		    F_ISSET(dbp, (DB_AM_CHKSUM | DB_AM_ENCRYPT | DB_AM_SWAP));
 		pdbt.data = &pginfo;
 		pdbt.size = sizeof(pginfo);
-		ret = __os_calloc(dbp->dbenv, 1, dbp->pgsize, &buf);
+		if ((ret = __os_calloc(dbp->dbenv, 1, dbp->pgsize, &buf)) != 0)
+			return (ret);
 		meta = (HMETA *)buf;
-	}
-	if (ret != 0)
-		return (ret);
-
-	LSN_NOT_LOGGED(lsn);
-	lpgno = __ham_init_meta(dbp, meta, PGNO_BASE_MD, &lsn);
-	meta->dbmeta.last_pgno = lpgno;
-
-	if (name == NULL)
-		ret = mpf->put(mpf, meta, DB_MPOOL_DIRTY);
-	else {
+		LSN_NOT_LOGGED(lsn);
+		lpgno = __ham_init_meta(dbp, meta, PGNO_BASE_MD, &lsn);
+		meta->dbmeta.last_pgno = lpgno;
 		if ((ret = __db_pgout(dbenv, PGNO_BASE_MD, meta, &pdbt)) != 0)
 			goto err;
-		ret = __fop_write(dbenv, txn, name,
-		    DB_APP_DATA, fhp, 0, buf, dbp->pgsize, 1);
-	}
-	if (ret != 0)
-		goto err;
-	meta = NULL;
-
-	/* Now allocate the final hash bucket. */
-	if (name == NULL) {
-		if ((ret = mpf->get(mpf, &lpgno, DB_MPOOL_CREATE, &page)) != 0)
+		if ((ret = __fop_write(dbenv, txn, name, DB_APP_DATA, fhp,
+		    dbp->pgsize, 0, 0, buf, dbp->pgsize, 1, F_ISSET(
+		    dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0)) != 0)
 			goto err;
-	} else {
+		meta = NULL;
+
+		/* Allocate the final hash bucket. */
 #ifdef DIAGNOSTIC
 		memset(buf, 0, dbp->pgsize);
 #endif
 		page = (PAGE *)buf;
-	}
-
-	P_INIT(page, dbp->pgsize, lpgno, PGNO_INVALID, PGNO_INVALID, 0, P_HASH);
-	LSN_NOT_LOGGED(page->lsn);
-
-	if (name == NULL)
-		ret = mpf->put(mpf, page, DB_MPOOL_DIRTY);
-	else {
+		P_INIT(page,
+		    dbp->pgsize, lpgno, PGNO_INVALID, PGNO_INVALID, 0, P_HASH);
+		LSN_NOT_LOGGED(page->lsn);
 		if ((ret = __db_pgout(dbenv, lpgno, buf, &pdbt)) != 0)
 			goto err;
-		ret = __fop_write(dbenv, txn, name,
-		    DB_APP_DATA, fhp, lpgno * dbp->pgsize, buf, dbp->pgsize, 1);
+		if ((ret = __fop_write(dbenv, txn, name, DB_APP_DATA, fhp,
+		    dbp->pgsize, lpgno, 0, buf, dbp->pgsize, 1, F_ISSET(
+		    dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0)) != 0)
+			goto err;
+		page = NULL;
 	}
-	if (ret != 0)
-		goto err;
-	page = NULL;
 
-err:	if (name != NULL)
+err:	if (buf != NULL)
 		__os_free(dbenv, buf);
 	else {
 		if (meta != NULL)
-			(void)mpf->put(mpf, meta, 0);
+			(void)__memp_fput(mpf, meta, 0);
 		if (page != NULL)
-			(void)mpf->put(mpf, page, 0);
+			(void)__memp_fput(mpf, page, 0);
 	}
 	return (ret);
 }
@@ -470,7 +464,7 @@ __ham_new_subdb(mdbp, dbp, txn)
 	LOCK_INIT(metalock);
 	LOCK_INIT(mmlock);
 
-	if ((ret = mdbp->cursor(mdbp, txn,
+	if ((ret = __db_cursor(mdbp, txn,
 	    &dbc, CDB_LOCKING(dbenv) ?  DB_WRITECURSOR : 0)) != 0)
 		return (ret);
 
@@ -478,7 +472,8 @@ __ham_new_subdb(mdbp, dbp, txn)
 	if ((ret = __db_lget(dbc,
 	    0, dbp->meta_pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
 		goto err;
-	if ((ret = mpf->get(mpf, &dbp->meta_pgno, DB_MPOOL_CREATE, &meta)) != 0)
+	if ((ret =
+	    __memp_fget(mpf, &dbp->meta_pgno, DB_MPOOL_CREATE, &meta)) != 0)
 		goto err;
 
 	/* Initialize the new meta-data page. */
@@ -494,7 +489,7 @@ __ham_new_subdb(mdbp, dbp, txn)
 	mpgno = PGNO_BASE_MD;
 	if ((ret = __db_lget(dbc, 0, mpgno, DB_LOCK_WRITE, 0, &mmlock)) != 0)
 		goto err;
-	if ((ret = mpf->get(mpf, &mpgno, 0, &mmeta)) != 0)
+	if ((ret = __memp_fget(mpf, &mpgno, 0, &mmeta)) != 0)
 		goto err;
 
 	/*
@@ -513,46 +508,45 @@ __ham_new_subdb(mdbp, dbp, txn)
 	/* Reflect the group allocation. */
 	if (DBENV_LOGGING(dbenv))
 		if ((ret = __ham_groupalloc_log(mdbp, txn,
-		    &LSN(mmeta), 0, &LSN(mmeta),
-		    meta->spares[0], meta->max_bucket + 1, mmeta->free)) != 0)
+		    &LSN(mmeta), 0, &LSN(mmeta), meta->spares[0],
+		    meta->max_bucket + 1, mmeta->free, mmeta->last_pgno)) != 0)
 			goto err;
 
 	/* Release the new meta-data page. */
-	if ((ret = mpf->put(mpf, meta, DB_MPOOL_DIRTY)) != 0)
+	if ((ret = __memp_fput(mpf, meta, DB_MPOOL_DIRTY)) != 0)
 		goto err;
 	meta = NULL;
 
-	mmeta->last_pgno +=lpgno;
-	lpgno = mmeta->last_pgno;
+	lpgno += mmeta->last_pgno;
 
 	/* Now allocate the final hash bucket. */
-	if ((ret = mpf->get(mpf, &lpgno, DB_MPOOL_CREATE, &h)) != 0)
+	if ((ret = __memp_fget(mpf, &lpgno, DB_MPOOL_CREATE, &h)) != 0)
 		goto err;
+
+	mmeta->last_pgno = lpgno;
 	P_INIT(h, dbp->pgsize, lpgno, PGNO_INVALID, PGNO_INVALID, 0, P_HASH);
 	LSN(h) = LSN(mmeta);
-	if ((ret = mpf->put(mpf, h, DB_MPOOL_DIRTY)) != 0)
+	if ((ret = __memp_fput(mpf, h, DB_MPOOL_DIRTY)) != 0)
 		goto err;
 
 	/* Now put the master-metadata page back. */
-	if ((ret = mpf->put(mpf, mmeta, DB_MPOOL_DIRTY)) != 0)
+	if ((ret = __memp_fput(mpf, mmeta, DB_MPOOL_DIRTY)) != 0)
 		goto err;
 	mmeta = NULL;
 
 err:
 	if (mmeta != NULL)
-		if ((t_ret = mpf->put(mpf, mmeta, 0)) != 0 && ret == 0)
-			ret = t_ret;
-	if (LOCK_ISSET(mmlock))
-		if ((t_ret = __LPUT(dbc, mmlock)) != 0 && ret == 0)
+		if ((t_ret = __memp_fput(mpf, mmeta, 0)) != 0 && ret == 0)
 			ret = t_ret;
+	if ((t_ret = __LPUT(dbc, mmlock)) != 0 && ret == 0)
+		ret = t_ret;
 	if (meta != NULL)
-		if ((t_ret = mpf->put(mpf, meta, 0)) != 0 && ret == 0)
-			ret = t_ret;
-	if (LOCK_ISSET(metalock))
-		if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0)
+		if ((t_ret = __memp_fput(mpf, meta, 0)) != 0 && ret == 0)
 			ret = t_ret;
+	if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0)
+		ret = t_ret;
 	if (dbc != NULL)
-		if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
+		if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
 			ret = t_ret;
 	return (ret);
 }
diff --git a/storage/bdb/hash/hash_page.c b/storage/bdb/hash/hash_page.c
index 6788129773ff17b9dc353e0f63c58818e0503406..636767f4ec5b6dd7536288ba71ba18cfff9d0b3d 100644
--- a/storage/bdb/hash/hash_page.c
+++ b/storage/bdb/hash/hash_page.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -38,14 +38,12 @@
  * 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.
+ *
+ * $Id: hash_page.c,v 11.102 2004/09/22 21:14:56 ubell Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: hash_page.c,v 11.87 2002/08/15 02:46:20 bostic Exp $";
-#endif /* not lint */
-
 /*
  * PACKAGE:  hashing
  *
@@ -64,6 +62,7 @@ static const char revid[] = "$Id: hash_page.c,v 11.87 2002/08/15 02:46:20 bostic
 #include "dbinc/db_shash.h"
 #include "dbinc/hash.h"
 #include "dbinc/lock.h"
+#include "dbinc/mp.h"
 
 static int __ham_c_delpg
     __P((DBC *, db_pgno_t, db_pgno_t, u_int32_t, db_ham_mode, u_int32_t *));
@@ -149,7 +148,7 @@ __ham_item_reset(dbc)
 	DB *dbp;
 	DB_MPOOLFILE *mpf;
 	HASH_CURSOR *hcp;
-	int ret;
+	int ret, t_ret;
 
 	dbp = dbc->dbp;
 	mpf = dbp->mpf;
@@ -157,31 +156,35 @@ __ham_item_reset(dbc)
 
 	ret = 0;
 	if (hcp->page != NULL)
-		ret = mpf->put(mpf, hcp->page, 0);
+		ret = __memp_fput(mpf, hcp->page, 0);
+
+	if ((t_ret = __ham_item_init(dbc)) != 0 && ret == 0)
+		ret = t_ret;
 
-	__ham_item_init(dbc);
 	return (ret);
 }
 
 /*
- * PUBLIC: void __ham_item_init __P((DBC *));
+ * PUBLIC: int __ham_item_init __P((DBC *));
  */
-void
+int
 __ham_item_init(dbc)
 	DBC *dbc;
 {
 	HASH_CURSOR *hcp;
+	int ret;
 
 	hcp = (HASH_CURSOR *)dbc->internal;
+
 	/*
-	 * If this cursor still holds any locks, we must
-	 * release them if we are not running with transactions.
+	 * If this cursor still holds any locks, we must release them if
+	 * we are not running with transactions.
 	 */
-	(void)__TLPUT(dbc, hcp->lock);
+	ret = __TLPUT(dbc, hcp->lock);
 
 	/*
-	 * The following fields must *not* be initialized here
-	 * because they may have meaning across inits.
+	 * The following fields must *not* be initialized here because they
+	 * may have meaning across inits.
 	 *	hlock, hdr, split_buf, stats
 	 */
 	hcp->bucket = BUCKET_INVALID;
@@ -198,6 +201,8 @@ __ham_item_init(dbc)
 	hcp->pgno = PGNO_INVALID;
 	hcp->indx = NDX_INVALID;
 	hcp->page = NULL;
+
+	return (ret);
 }
 
 /*
@@ -549,8 +554,8 @@ __ham_del_pair(dbc, reclaim_page)
 	db_ham_mode op;
 	db_indx_t ndx;
 	db_pgno_t chg_pgno, pgno, tmp_pgno;
-	int ret, t_ret;
 	u_int32_t order;
+	int ret, t_ret;
 
 	dbp = dbc->dbp;
 	mpf = dbp->mpf;
@@ -558,8 +563,8 @@ __ham_del_pair(dbc, reclaim_page)
 	n_pagep = p_pagep = nn_pagep = NULL;
 	ndx = hcp->indx;
 
-	if (hcp->page == NULL &&
-	    (ret = mpf->get(mpf, &hcp->pgno, DB_MPOOL_CREATE, &hcp->page)) != 0)
+	if (hcp->page == NULL && (ret = __memp_fget(
+	    mpf, &hcp->pgno, DB_MPOOL_CREATE, &hcp->page)) != 0)
 		return (ret);
 	p = hcp->page;
 
@@ -570,12 +575,12 @@ __ham_del_pair(dbc, reclaim_page)
 	 * to remove the big item and then update the page to remove the
 	 * entry referring to the big item.
 	 */
-	ret = 0;
 	if (HPAGE_PTYPE(H_PAIRKEY(dbp, p, ndx)) == H_OFFPAGE) {
 		memcpy(&pgno, HOFFPAGE_PGNO(P_ENTRY(dbp, p, H_KEYINDEX(ndx))),
 		    sizeof(db_pgno_t));
 		ret = __db_doff(dbc, pgno);
-	}
+	} else
+		ret = 0;
 
 	if (ret == 0)
 		switch (HPAGE_PTYPE(H_PAIRDATA(dbp, p, ndx))) {
@@ -594,6 +599,9 @@ __ham_del_pair(dbc, reclaim_page)
 			 */
 			F_CLR(hcp, H_ISDUP);
 			break;
+		default:
+			/* No-op */
+			break;
 		}
 
 	if (ret)
@@ -604,7 +612,8 @@ __ham_del_pair(dbc, reclaim_page)
 		key_dbt.data = P_ENTRY(dbp, p, H_KEYINDEX(ndx));
 		key_dbt.size = LEN_HITEM(dbp, p, dbp->pgsize, H_KEYINDEX(ndx));
 		data_dbt.data = P_ENTRY(dbp, p, H_DATAINDEX(ndx));
-		data_dbt.size = LEN_HITEM(dbp, p, dbp->pgsize, H_DATAINDEX(ndx));
+		data_dbt.size =
+		    LEN_HITEM(dbp, p, dbp->pgsize, H_DATAINDEX(ndx));
 
 		if ((ret = __ham_insdel_log(dbp,
 		    dbc->txn, &new_lsn, 0, DELPAIR, PGNO(p), (u_int32_t)ndx,
@@ -657,18 +666,18 @@ __ham_del_pair(dbc, reclaim_page)
 	if (!reclaim_page ||
 	    NUM_ENT(p) != 0 ||
 	    (PREV_PGNO(p) == PGNO_INVALID && NEXT_PGNO(p) == PGNO_INVALID))
-		return (mpf->set(mpf, p, DB_MPOOL_DIRTY));
+		return (__memp_fset(mpf, p, DB_MPOOL_DIRTY));
 
 	if (PREV_PGNO(p) == PGNO_INVALID) {
 		/*
 		 * First page in chain is empty and we know that there
 		 * are more pages in the chain.
 		 */
-		if ((ret = mpf->get(mpf, &NEXT_PGNO(p), 0, &n_pagep)) != 0)
+		if ((ret = __memp_fget(mpf, &NEXT_PGNO(p), 0, &n_pagep)) != 0)
 			return (ret);
 
 		if (NEXT_PGNO(n_pagep) != PGNO_INVALID && (ret =
-		    mpf->get(mpf, &NEXT_PGNO(n_pagep), 0, &nn_pagep)) != 0)
+		    __memp_fget(mpf, &NEXT_PGNO(n_pagep), 0, &nn_pagep)) != 0)
 			goto err;
 
 		if (DBC_LOGGING(dbc)) {
@@ -693,7 +702,7 @@ __ham_del_pair(dbc, reclaim_page)
 		if (nn_pagep != NULL) {
 			PREV_PGNO(nn_pagep) = PGNO(p);
 			if ((ret =
-			    mpf->put(mpf, nn_pagep, DB_MPOOL_DIRTY)) != 0) {
+			    __memp_fput(mpf, nn_pagep, DB_MPOOL_DIRTY)) != 0) {
 				nn_pagep = NULL;
 				goto err;
 			}
@@ -721,19 +730,19 @@ __ham_del_pair(dbc, reclaim_page)
 		hcp->pgno = PGNO(p);
 		hcp->order += order;
 
-		if ((ret = mpf->set(mpf, p, DB_MPOOL_DIRTY)) != 0)
+		if ((ret = __memp_fset(mpf, p, DB_MPOOL_DIRTY)) != 0)
 			goto err;
 		if ((ret = __db_free(dbc, n_pagep)) != 0) {
 			n_pagep = NULL;
 			goto err;
 		}
 	} else {
-		if ((ret = mpf->get(mpf, &PREV_PGNO(p), 0, &p_pagep)) != 0)
+		if ((ret = __memp_fget(mpf, &PREV_PGNO(p), 0, &p_pagep)) != 0)
 			goto err;
 
 		if (NEXT_PGNO(p) != PGNO_INVALID) {
 			if ((ret =
-			    mpf->get(mpf, &NEXT_PGNO(p), 0, &n_pagep)) != 0)
+			    __memp_fget(mpf, &NEXT_PGNO(p), 0, &n_pagep)) != 0)
 				goto err;
 			n_lsn = &LSN(n_pagep);
 		} else {
@@ -790,10 +799,10 @@ __ham_del_pair(dbc, reclaim_page)
 		chg_pgno = PGNO(p);
 		ret = __db_free(dbc, p);
 		if ((t_ret =
-		    mpf->put(mpf, p_pagep, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+		    __memp_fput(mpf, p_pagep, DB_MPOOL_DIRTY)) != 0 && ret == 0)
 			ret = t_ret;
 		if (n_pagep != NULL && (t_ret =
-		    mpf->put(mpf, n_pagep, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+		    __memp_fput(mpf, n_pagep, DB_MPOOL_DIRTY)) != 0 && ret == 0)
 			ret = t_ret;
 		if (ret != 0)
 			return (ret);
@@ -806,11 +815,11 @@ __ham_del_pair(dbc, reclaim_page)
 
 err:	/* Clean up any pages. */
 	if (n_pagep != NULL)
-		(void)mpf->put(mpf, n_pagep, 0);
+		(void)__memp_fput(mpf, n_pagep, 0);
 	if (nn_pagep != NULL)
-		(void)mpf->put(mpf, nn_pagep, 0);
+		(void)__memp_fput(mpf, nn_pagep, 0);
 	if (p_pagep != NULL)
-		(void)mpf->put(mpf, p_pagep, 0);
+		(void)__memp_fput(mpf, p_pagep, 0);
 	return (ret);
 }
 
@@ -832,9 +841,9 @@ __ham_replpair(dbc, dbt, make_dup)
 	DB_ENV *dbenv;
 	DB_LSN	new_lsn;
 	HASH_CURSOR *hcp;
-	int32_t change;			/* XXX: Possible overflow. */
+	u_int32_t change;
 	u_int32_t dup_flag, len, memsize;
-	int beyond_eor, is_big, ret, type;
+	int beyond_eor, is_big, is_plus, ret, type;
 	u_int8_t *beg, *dest, *end, *hk, *src;
 	void *memp;
 
@@ -862,7 +871,13 @@ __ham_replpair(dbc, dbt, make_dup)
 	 * formula doesn't work, because we are essentially adding
 	 * new bytes.
 	 */
-	change = dbt->size - dbt->dlen;
+	if (dbt->size > dbt->dlen) {
+		change = dbt->size - dbt->dlen;
+		is_plus = 1;
+	} else {
+		change = dbt->dlen - dbt->size;
+		is_plus = 0;
+	}
 
 	hk = H_PAIRDATA(dbp, hcp->page, hcp->indx);
 	is_big = HPAGE_PTYPE(hk) == H_OFFPAGE;
@@ -874,10 +889,25 @@ __ham_replpair(dbc, dbt, make_dup)
 		    dbp->pgsize, H_DATAINDEX(hcp->indx));
 
 	beyond_eor = dbt->doff + dbt->dlen > len;
-	if (beyond_eor)
-		change += dbt->doff + dbt->dlen - len;
+	if (beyond_eor) {
+		/*
+		 * The change is beyond the end of file.  If change
+		 * is a positive number, we can simply add the extension
+		 * to it.  However, if change is negative, then we need
+		 * to figure out if the extension is larger than the
+		 * negative change.
+		 */
+		if (is_plus)
+			change += dbt->doff + dbt->dlen - len;
+		else if (dbt->doff + dbt->dlen - len > change) {
+			/* Extension bigger than change */
+			is_plus = 1;
+			change = (dbt->doff + dbt->dlen - len) - change;
+		} else /* Extension is smaller than change. */
+			change -= (dbt->doff + dbt->dlen - len);
+	}
 
-	if (change > (int32_t)P_FREESPACE(dbp, hcp->page) ||
+	if ((is_plus && change > P_FREESPACE(dbp, hcp->page)) ||
 	    beyond_eor || is_big) {
 		/*
 		 * Case 3 -- two subcases.
@@ -893,7 +923,7 @@ __ham_replpair(dbc, dbt, make_dup)
 		memset(&tmp, 0, sizeof(tmp));
 		if ((ret =
 		    __db_ret(dbp, hcp->page, H_KEYINDEX(hcp->indx),
-		    &tmp, &dbc->rkey->data, &dbc->rkey->ulen)) != 0)
+		    &tmp, &dbc->my_rkey.data, &dbc->my_rkey.ulen)) != 0)
 			return (ret);
 
 		/* Preserve duplicate info. */
@@ -921,7 +951,7 @@ __ham_replpair(dbc, dbt, make_dup)
 			}
 
 			/* Now shift old data around to make room for new. */
-			if (change > 0) {
+			if (is_plus) {
 				if ((ret = __os_realloc(dbenv,
 				    tdata.size + change, &tdata.data)) != 0)
 					return (ret);
@@ -934,13 +964,19 @@ __ham_replpair(dbc, dbt, make_dup)
 
 			src = (u_int8_t *)tdata.data + dbt->doff + dbt->dlen;
 			if (src < end && tdata.size > dbt->doff + dbt->dlen) {
-				len = tdata.size - dbt->doff - dbt->dlen;
-				dest = src + change;
+				len = tdata.size - (dbt->doff + dbt->dlen);
+				if (is_plus)
+					dest = src + change;
+				else
+					dest = src - change;
 				memmove(dest, src, len);
 			}
 			memcpy((u_int8_t *)tdata.data + dbt->doff,
 			    dbt->data, dbt->size);
-			tdata.size += change;
+			if (is_plus)
+				tdata.size += change;
+			else
+				tdata.size -= change;
 
 			/* Now add the pair. */
 			ret = __ham_add_el(dbc, &tmp, &tdata, type);
@@ -968,7 +1004,7 @@ err:		return (ret);
 		if ((ret = __ham_replace_log(dbp,
 		    dbc->txn, &new_lsn, 0, PGNO(hcp->page),
 		    (u_int32_t)H_DATAINDEX(hcp->indx), &LSN(hcp->page),
-		    (u_int32_t)dbt->doff, &old_dbt, dbt, make_dup)) != 0)
+		    (int32_t)dbt->doff, &old_dbt, dbt, make_dup)) != 0)
 			return (ret);
 
 	} else
@@ -977,7 +1013,7 @@ err:		return (ret);
 	LSN(hcp->page) = new_lsn;	/* Structure assignment. */
 
 	__ham_onpage_replace(dbp, hcp->page, (u_int32_t)H_DATAINDEX(hcp->indx),
-	    (int32_t)dbt->doff, change, dbt);
+	    (int32_t)dbt->doff, change, is_plus, dbt);
 
 	return (0);
 }
@@ -995,15 +1031,16 @@ err:		return (ret);
  * dbt: the new data that gets written at beg.
  *
  * PUBLIC: void __ham_onpage_replace __P((DB *, PAGE *, u_int32_t,
- * PUBLIC:     int32_t, int32_t,  DBT *));
+ * PUBLIC:     int32_t, u_int32_t,  int, DBT *));
  */
 void
-__ham_onpage_replace(dbp, pagep, ndx, off, change, dbt)
+__ham_onpage_replace(dbp, pagep, ndx, off, change, is_plus, dbt)
 	DB *dbp;
 	PAGE *pagep;
 	u_int32_t ndx;
 	int32_t off;
-	int32_t change;
+	u_int32_t change;
+	int is_plus;
 	DBT *dbt;
 {
 	db_indx_t i, *inp;
@@ -1028,15 +1065,25 @@ __ham_onpage_replace(dbp, pagep, ndx, off, change, dbt)
 			len = (int32_t)(
 			    (HKEYDATA_DATA(P_ENTRY(dbp, pagep, ndx)) + off) -
 			    src);
-		dest = src - change;
-		memmove(dest, src, len);
+		if (is_plus)
+			dest = src - change;
+		else
+			dest = src + change;
+		memmove(dest, src, (size_t)len);
 		if (zero_me)
 			memset(dest + len, 0, change);
 
 		/* Now update the indices. */
-		for (i = ndx; i < NUM_ENT(pagep); i++)
-			inp[i] -= change;
-		HOFFSET(pagep) -= change;
+		for (i = ndx; i < NUM_ENT(pagep); i++) {
+			if (is_plus)
+				inp[i] -= change;
+			else
+				inp[i] += change;
+		}
+		if (is_plus)
+			HOFFSET(pagep) -= change;
+		else
+			HOFFSET(pagep) += change;
 	}
 	if (off >= 0)
 		memcpy(HKEYDATA_DATA(P_ENTRY(dbp, pagep, ndx)) + off,
@@ -1069,24 +1116,25 @@ __ham_split_page(dbc, obucket, nbucket)
 	void *big_buf;
 
 	dbp = dbc->dbp;
+	carray = NULL;
 	dbenv = dbp->dbenv;
 	mpf = dbp->mpf;
 	hcp = (HASH_CURSOR *)dbc->internal;
 	temp_pagep = old_pagep = new_pagep = NULL;
-	carray = NULL;
+	npgno = PGNO_INVALID;
 	LOCK_INIT(block);
 
 	bucket_pgno = BUCKET_TO_PAGE(hcp, obucket);
 	if ((ret = __db_lget(dbc,
 	    0, bucket_pgno, DB_LOCK_WRITE, 0, &block)) != 0)
 		goto err;
-	if ((ret = mpf->get(mpf,
+	if ((ret = __memp_fget(mpf,
 	    &bucket_pgno, DB_MPOOL_CREATE, &old_pagep)) != 0)
 		goto err;
 
 	/* Properly initialize the new bucket page. */
 	npgno = BUCKET_TO_PAGE(hcp, nbucket);
-	if ((ret = mpf->get(mpf, &npgno, DB_MPOOL_CREATE, &new_pagep)) != 0)
+	if ((ret = __memp_fget(mpf, &npgno, DB_MPOOL_CREATE, &new_pagep)) != 0)
 		goto err;
 	P_INIT(new_pagep,
 	    dbp->pgsize, npgno, PGNO_INVALID, PGNO_INVALID, 0, P_HASH);
@@ -1191,7 +1239,7 @@ __ham_split_page(dbc, obucket, nbucket)
 
 		if (next_pgno == PGNO_INVALID)
 			temp_pagep = NULL;
-		else if ((ret = mpf->get(
+		else if ((ret = __memp_fget(
 		    mpf, &next_pgno, DB_MPOOL_CREATE, &temp_pagep)) != 0)
 			goto err;
 
@@ -1250,21 +1298,24 @@ __ham_split_page(dbc, obucket, nbucket)
 		LSN_NOT_LOGGED(LSN(new_pagep));
 	}
 
-	ret = mpf->put(mpf, old_pagep, DB_MPOOL_DIRTY);
+	ret = __memp_fput(mpf, old_pagep, DB_MPOOL_DIRTY);
 	if ((t_ret =
-	    mpf->put(mpf, new_pagep, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+	    __memp_fput(mpf, new_pagep, DB_MPOOL_DIRTY)) != 0 && ret == 0)
 		ret = t_ret;
 
 	if (0) {
 err:		if (old_pagep != NULL)
-			(void)mpf->put(mpf, old_pagep, DB_MPOOL_DIRTY);
-		if (new_pagep != NULL)
-			(void)mpf->put(mpf, new_pagep, DB_MPOOL_DIRTY);
+			(void)__memp_fput(mpf, old_pagep, DB_MPOOL_DIRTY);
+		if (new_pagep != NULL) {
+			P_INIT(new_pagep, dbp->pgsize,
+			     npgno, PGNO_INVALID, PGNO_INVALID, 0, P_HASH);
+			(void)__memp_fput(mpf, new_pagep, DB_MPOOL_DIRTY);
+		}
 		if (temp_pagep != NULL && PGNO(temp_pagep) != bucket_pgno)
-			(void)mpf->put(mpf, temp_pagep, DB_MPOOL_DIRTY);
+			(void)__memp_fput(mpf, temp_pagep, DB_MPOOL_DIRTY);
 	}
-	if (LOCK_ISSET(block))
-		__TLPUT(dbc, block);
+	if ((t_ret = __TLPUT(dbc, block)) != 0 && ret == 0)
+		ret = t_ret;
 	if (carray != NULL)		/* We never knew its size. */
 		__os_free(dbenv, carray);
 	return (ret);
@@ -1305,7 +1356,7 @@ __ham_add_el(dbc, key, val, type)
 	pgno = hcp->seek_found_page != PGNO_INVALID ?
 	    hcp->seek_found_page : hcp->pgno;
 	if (hcp->page == NULL &&
-	    (ret = mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &hcp->page)) != 0)
+	    (ret = __memp_fget(mpf, &pgno, DB_MPOOL_CREATE, &hcp->page)) != 0)
 		return (ret);
 
 	key_size = HKEYDATA_PSIZE(key->size);
@@ -1470,8 +1521,8 @@ __ham_copy_item(dbp, src_page, src_ndx, dest_page)
 /*
  *
  * Returns:
- *	pointer on success
- *	NULL on error
+ *	0 on success -- pp points to new page.
+ *	errno on error -- pp not valid.
  *
  * PUBLIC: int __ham_add_ovflpage __P((DBC *, PAGE *, int, PAGE **));
  */
@@ -1496,9 +1547,11 @@ __ham_add_ovflpage(dbc, pagep, release, pp)
 
 	if (DBC_LOGGING(dbc)) {
 		if ((ret = __ham_newpage_log(dbp, dbc->txn, &new_lsn, 0,
-		    PUTOVFL, PGNO(pagep), &LSN(pagep),
-		    PGNO(new_pagep), &LSN(new_pagep), PGNO_INVALID, NULL)) != 0)
+		    PUTOVFL, PGNO(pagep), &LSN(pagep), PGNO(new_pagep),
+		    &LSN(new_pagep), PGNO_INVALID, NULL)) != 0) {
+			(void)__memp_fput(mpf, pagep, DB_MPOOL_DIRTY);
 			return (ret);
+		}
 	} else
 		LSN_NOT_LOGGED(new_lsn);
 
@@ -1509,7 +1562,7 @@ __ham_add_ovflpage(dbc, pagep, release, pp)
 	PREV_PGNO(new_pagep) = PGNO(pagep);
 
 	if (release)
-		ret = mpf->put(mpf, pagep, DB_MPOOL_DIRTY);
+		ret = __memp_fput(mpf, pagep, DB_MPOOL_DIRTY);
 
 	*pp = new_pagep;
 	return (ret);
@@ -1547,13 +1600,19 @@ __ham_get_cpage(dbc, mode)
 	 */
 	LOCK_INIT(tmp_lock);
 	if (STD_LOCKING(dbc)) {
-		if (hcp->lbucket != hcp->bucket &&	/* Case 4 */
-		    (ret = __TLPUT(dbc, hcp->lock)) != 0)
-			return (ret);
+		if (hcp->lbucket != hcp->bucket) {	/* Case 4 */
+			if ((ret = __TLPUT(dbc, hcp->lock)) != 0)
+				return (ret);
+			LOCK_INIT(hcp->lock);
+		}
 
+		/*
+		 * See if we have the right lock.  If we are doing
+		 * dirty reads we assume the write lock has been downgraded.
+		 */
 		if ((LOCK_ISSET(hcp->lock) &&
-		    (hcp->lock_mode == DB_LOCK_READ &&
-		    mode == DB_LOCK_WRITE))) {
+		    ((hcp->lock_mode == DB_LOCK_READ ||
+		    F_ISSET(dbp, DB_AM_DIRTY)) && mode == DB_LOCK_WRITE))) {
 			/* Case 3. */
 			tmp_lock = hcp->lock;
 			LOCK_INIT(hcp->lock);
@@ -1568,10 +1627,9 @@ __ham_get_cpage(dbc, mode)
 		if (ret == 0) {
 			hcp->lock_mode = mode;
 			hcp->lbucket = hcp->bucket;
-			if (LOCK_ISSET(tmp_lock))
-				/* Case 3: release the original lock. */
-				ret =
-				    dbp->dbenv->lock_put(dbp->dbenv, &tmp_lock);
+			/* Case 3: release the original lock. */
+			if ((ret = __ENV_LPUT(dbp->dbenv, tmp_lock, 0)) != 0)
+				return (ret);
 		} else if (LOCK_ISSET(tmp_lock))
 			hcp->lock = tmp_lock;
 	}
@@ -1579,7 +1637,7 @@ __ham_get_cpage(dbc, mode)
 	if (ret == 0 && hcp->page == NULL) {
 		if (hcp->pgno == PGNO_INVALID)
 			hcp->pgno = BUCKET_TO_PAGE(hcp, hcp->bucket);
-		if ((ret = mpf->get(mpf,
+		if ((ret = __memp_fget(mpf,
 		    &hcp->pgno, DB_MPOOL_CREATE, &hcp->page)) != 0)
 			return (ret);
 	}
@@ -1610,12 +1668,12 @@ __ham_next_cpage(dbc, pgno, dirty)
 	mpf = dbp->mpf;
 	hcp = (HASH_CURSOR *)dbc->internal;
 
-	if (hcp->page != NULL &&
-	    (ret = mpf->put(mpf, hcp->page, dirty ? DB_MPOOL_DIRTY : 0)) != 0)
+	if (hcp->page != NULL && (ret =
+	    __memp_fput(mpf, hcp->page, dirty ? DB_MPOOL_DIRTY : 0)) != 0)
 		return (ret);
 	hcp->page = NULL;
 
-	if ((ret = mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &p)) != 0)
+	if ((ret = __memp_fget(mpf, &pgno, DB_MPOOL_CREATE, &p)) != 0)
 		return (ret);
 
 	hcp->page = p;
diff --git a/storage/bdb/hash/hash_rec.c b/storage/bdb/hash/hash_rec.c
index 24d3473c508bcfc98ebba5c1244f4dce2f1dbf04..2934f19192bab595dbdbb8be27ed02a751b652c1 100644
--- a/storage/bdb/hash/hash_rec.c
+++ b/storage/bdb/hash/hash_rec.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -38,14 +38,12 @@
  * 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.
+ *
+ * $Id: hash_rec.c,v 11.83 2004/10/25 16:52:13 ubell Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: hash_rec.c,v 11.69 2002/09/03 14:12:49 margo Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -54,9 +52,11 @@ static const char revid[] = "$Id: hash_rec.c,v 11.69 2002/09/03 14:12:49 margo E
 
 #include "db_int.h"
 #include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
 #include "dbinc/btree.h"
 #include "dbinc/hash.h"
 #include "dbinc/log.h"
+#include "dbinc/mp.h"
 
 static int __ham_alloc_pages __P((DB *, __ham_groupalloc_args *, DB_LSN *));
 
@@ -88,18 +88,30 @@ __ham_insdel_recover(dbenv, dbtp, lsnp, op, info)
 	REC_PRINT(__ham_insdel_print);
 	REC_INTRO(__ham_insdel_read, 1);
 
-	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
+	if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
 		if (DB_UNDO(op)) {
-			/*
-			 * We are undoing and the page doesn't exist.  That
-			 * is equivalent to having a pagelsn of 0, so we
-			 * would not have to undo anything.  In this case,
-			 * don't bother creating a page.
-			 */
+			if (ret == DB_PAGE_NOTFOUND)
+				goto done;
+			else {
+				ret = __db_pgerr(file_dbp, argp->pgno, ret);
+				goto out;
+			}
+		}
+#ifdef HAVE_FTRUNCATE
+		/* If the page is not here then it was later truncated. */
+		if (!IS_ZERO_LSN(argp->pagelsn))
 			goto done;
-		} else if ((ret = mpf->get(mpf,
-		    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+#endif
+		/*
+		 * This page was created by a group allocation and
+		 * the file may not have been extend yet.
+		 * Create the page if necessary.
+		 */
+		if ((ret = __memp_fget(mpf,
+		     &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0) {
+			ret = __db_pgerr(file_dbp, argp->pgno, ret);
 			goto out;
+		}
 	}
 
 	cmp_n = log_compare(lsnp, &LSN(pagep));
@@ -115,8 +127,8 @@ __ham_insdel_recover(dbenv, dbtp, lsnp, op, info)
 	 * We do this by calling __putitem with the type H_OFFPAGE instead
 	 * of H_KEYDATA.
 	 */
-	opcode = OPCODE_OF(argp->opcode);
 
+	opcode = OPCODE_OF(argp->opcode);
 	flags = 0;
 	if ((opcode == DELPAIR && cmp_n == 0 && DB_UNDO(op)) ||
 	    (opcode == PUTPAIR && cmp_p == 0 && DB_REDO(op))) {
@@ -140,7 +152,7 @@ __ham_insdel_recover(dbenv, dbtp, lsnp, op, info)
 				type = H_KEYDATA;
 			__ham_putitem(file_dbp, pagep, &argp->data, type);
 		} else
-			(void)__ham_reputpair(file_dbp, pagep,
+			__ham_reputpair(file_dbp, pagep,
 			    argp->ndx, &argp->key, &argp->data);
 
 		LSN(pagep) = DB_REDO(op) ? *lsnp : argp->pagelsn;
@@ -154,7 +166,7 @@ __ham_insdel_recover(dbenv, dbtp, lsnp, op, info)
 		flags = DB_MPOOL_DIRTY;
 	}
 
-	if ((ret = mpf->put(mpf, pagep, flags)) != 0)
+	if ((ret = __memp_fput(mpf, pagep, flags)) != 0)
 		goto out;
 	pagep = NULL;
 
@@ -163,7 +175,7 @@ done:	*lsnp = argp->prev_lsn;
 	ret = 0;
 
 out:	if (pagep != NULL)
-		(void)mpf->put(mpf, pagep, 0);
+		(void)__memp_fput(mpf, pagep, 0);
 	REC_CLOSE;
 }
 
@@ -197,20 +209,7 @@ __ham_newpage_recover(dbenv, dbtp, lsnp, op, info)
 	REC_PRINT(__ham_newpage_print);
 	REC_INTRO(__ham_newpage_read, 1);
 
-	if ((ret = mpf->get(mpf, &argp->new_pgno, 0, &pagep)) != 0) {
-		if (DB_UNDO(op)) {
-			/*
-			 * We are undoing and the page doesn't exist.  That
-			 * is equivalent to having a pagelsn of 0, so we
-			 * would not have to undo anything.  In this case,
-			 * don't bother creating a page.
-			 */
-			ret = 0;
-			goto ppage;
-		} else if ((ret = mpf->get(mpf,
-		    &argp->new_pgno, DB_MPOOL_CREATE, &pagep)) != 0)
-			goto out;
-	}
+	REC_FGET(mpf, argp->new_pgno, &pagep, ppage);
 
 	/*
 	 * There are potentially three pages we need to check: the one
@@ -241,26 +240,13 @@ __ham_newpage_recover(dbenv, dbtp, lsnp, op, info)
 	if (flags)
 		LSN(pagep) = DB_REDO(op) ? *lsnp : argp->pagelsn;
 
-	if ((ret = mpf->put(mpf, pagep, flags)) != 0)
+	if ((ret = __memp_fput(mpf, pagep, flags)) != 0)
 		goto out;
 	pagep = NULL;
 
 	/* Now do the prev page. */
 ppage:	if (argp->prev_pgno != PGNO_INVALID) {
-		if ((ret = mpf->get(mpf, &argp->prev_pgno, 0, &pagep)) != 0) {
-			if (DB_UNDO(op)) {
-				/*
-				 * We are undoing and the page doesn't exist.
-				 * That is equivalent to having a pagelsn of 0,
-				 * so we would not have to undo anything.  In
-				 * this case, don't bother creating a page.
-				 */
-				ret = 0;
-				goto npage;
-			} else if ((ret = mpf->get(mpf,
-			    &argp->prev_pgno, DB_MPOOL_CREATE, &pagep)) != 0)
-				goto out;
-		}
+		REC_FGET(mpf, argp->prev_pgno, &pagep, npage);
 
 		cmp_n = log_compare(lsnp, &LSN(pagep));
 		cmp_p = log_compare(&LSN(pagep), &argp->prevlsn);
@@ -283,26 +269,14 @@ ppage:	if (argp->prev_pgno != PGNO_INVALID) {
 		if (flags)
 			LSN(pagep) = DB_REDO(op) ? *lsnp : argp->prevlsn;
 
-		if ((ret = mpf->put(mpf, pagep, flags)) != 0)
+		if ((ret = __memp_fput(mpf, pagep, flags)) != 0)
 			goto out;
 		pagep = NULL;
 	}
 
 	/* Now time to do the next page */
 npage:	if (argp->next_pgno != PGNO_INVALID) {
-		if ((ret = mpf->get(mpf, &argp->next_pgno, 0, &pagep)) != 0) {
-			if (DB_UNDO(op)) {
-				/*
-				 * We are undoing and the page doesn't exist.
-				 * That is equivalent to having a pagelsn of 0,
-				 * so we would not have to undo anything.  In
-				 * this case, don't bother creating a page.
-				 */
-				goto done;
-			} else if ((ret = mpf->get(mpf,
-			    &argp->next_pgno, DB_MPOOL_CREATE, &pagep)) != 0)
-				goto out;
-		}
+		REC_FGET(mpf, argp->next_pgno, &pagep, done);
 
 		cmp_n = log_compare(lsnp, &LSN(pagep));
 		cmp_p = log_compare(&LSN(pagep), &argp->nextlsn);
@@ -325,7 +299,7 @@ npage:	if (argp->next_pgno != PGNO_INVALID) {
 		if (flags)
 			LSN(pagep) = DB_REDO(op) ? *lsnp : argp->nextlsn;
 
-		if ((ret = mpf->put(mpf, pagep, flags)) != 0)
+		if ((ret = __memp_fput(mpf, pagep, flags)) != 0)
 			goto out;
 		pagep = NULL;
 	}
@@ -333,7 +307,7 @@ done:	*lsnp = argp->prev_lsn;
 	ret = 0;
 
 out:	if (pagep != NULL)
-		(void)mpf->put(mpf, pagep, 0);
+		(void)__memp_fput(mpf, pagep, 0);
 	REC_CLOSE;
 }
 
@@ -361,8 +335,8 @@ __ham_replace_recover(dbenv, dbtp, lsnp, op, info)
 	DBT dbt;
 	PAGE *pagep;
 	u_int32_t flags;
-	int32_t grow;
-	int cmp_n, cmp_p, ret;
+	u_int32_t change;
+	int cmp_n, cmp_p, is_plus, ret;
 	u_int8_t *hk;
 
 	pagep = NULL;
@@ -371,19 +345,7 @@ __ham_replace_recover(dbenv, dbtp, lsnp, op, info)
 	REC_PRINT(__ham_replace_print);
 	REC_INTRO(__ham_replace_read, 1);
 
-	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
-		if (DB_UNDO(op)) {
-			/*
-			 * We are undoing and the page doesn't exist.  That
-			 * is equivalent to having a pagelsn of 0, so we
-			 * would not have to undo anything.  In this case,
-			 * don't bother creating a page.
-			 */
-			goto done;
-		} else if ((ret = mpf->get(mpf,
-		    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
-			goto out;
-	}
+	REC_FGET(mpf, argp->pgno, &pagep, done);
 
 	cmp_n = log_compare(lsnp, &LSN(pagep));
 	cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
@@ -391,27 +353,45 @@ __ham_replace_recover(dbenv, dbtp, lsnp, op, info)
 
 	memset(&dbt, 0, sizeof(dbt));
 	flags = 0;
-	grow = 1;
 
+	/*
+	 * Before we know the direction of the transformation we will
+	 * determine the size differential; then once we know if we are
+	 * redoing or undoing, we'll adjust the sign (is_plus) appropriately.
+	 */
+	if (argp->newitem.size > argp->olditem.size) {
+		change = argp->newitem.size - argp->olditem.size;
+		is_plus = 1;
+	} else {
+		change = argp->olditem.size - argp->newitem.size;
+		is_plus = 0;
+	}
 	if (cmp_p == 0 && DB_REDO(op)) {
 		/* Reapply the change as specified. */
 		dbt.data = argp->newitem.data;
 		dbt.size = argp->newitem.size;
-		grow = argp->newitem.size - argp->olditem.size;
 		LSN(pagep) = *lsnp;
+		/*
+		 * The is_plus flag is set properly to reflect
+		 * newitem.size - olditem.size.
+		 */
 		flags = DB_MPOOL_DIRTY;
 	} else if (cmp_n == 0 && DB_UNDO(op)) {
 		/* Undo the already applied change. */
 		dbt.data = argp->olditem.data;
 		dbt.size = argp->olditem.size;
-		grow = argp->olditem.size - argp->newitem.size;
+		/*
+		 * Invert is_plus to reflect sign of
+		 * olditem.size - newitem.size.
+		 */
+		is_plus = !is_plus;
 		LSN(pagep) = argp->pagelsn;
 		flags = DB_MPOOL_DIRTY;
 	}
 
 	if (flags) {
 		__ham_onpage_replace(file_dbp, pagep,
-		    argp->ndx, argp->off, grow, &dbt);
+		    argp->ndx, argp->off, change, is_plus, &dbt);
 		if (argp->makedup) {
 			hk = P_ENTRY(file_dbp, pagep, argp->ndx);
 			if (DB_REDO(op))
@@ -421,7 +401,7 @@ __ham_replace_recover(dbenv, dbtp, lsnp, op, info)
 		}
 	}
 
-	if ((ret = mpf->put(mpf, pagep, flags)) != 0)
+	if ((ret = __memp_fput(mpf, pagep, flags)) != 0)
 		goto out;
 	pagep = NULL;
 
@@ -429,7 +409,7 @@ done:	*lsnp = argp->prev_lsn;
 	ret = 0;
 
 out:	if (pagep != NULL)
-		(void)mpf->put(mpf, pagep, 0);
+		(void)__memp_fput(mpf, pagep, 0);
 	REC_CLOSE;
 }
 
@@ -461,18 +441,30 @@ __ham_splitdata_recover(dbenv, dbtp, lsnp, op, info)
 	REC_PRINT(__ham_splitdata_print);
 	REC_INTRO(__ham_splitdata_read, 1);
 
-	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
+	if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
 		if (DB_UNDO(op)) {
-			/*
-			 * We are undoing and the page doesn't exist.  That
-			 * is equivalent to having a pagelsn of 0, so we
-			 * would not have to undo anything.  In this case,
-			 * don't bother creating a page.
-			 */
+			if (ret == DB_PAGE_NOTFOUND)
+				goto done;
+			else {
+				ret = __db_pgerr(file_dbp, argp->pgno, ret);
+				goto out;
+			}
+		}
+#ifdef HAVE_FTRUNCATE
+		/* If the page is not here then it was later truncated. */
+		if (!IS_ZERO_LSN(argp->pagelsn))
 			goto done;
-		} else if ((ret = mpf->get(mpf,
-		    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+#endif
+		/*
+		 * This page was created by a group allocation and
+		 * the file may not have been extend yet.
+		 * Create the page if necessary.
+		 */
+		if ((ret = __memp_fget(mpf,
+		     &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0) {
+			ret = __db_pgerr(file_dbp, argp->pgno, ret);
 			goto out;
+		}
 	}
 
 	cmp_n = log_compare(lsnp, &LSN(pagep));
@@ -508,7 +500,7 @@ __ham_splitdata_recover(dbenv, dbtp, lsnp, op, info)
 		LSN(pagep) = argp->pagelsn;
 		flags = DB_MPOOL_DIRTY;
 	}
-	if ((ret = mpf->put(mpf, pagep, flags)) != 0)
+	if ((ret = __memp_fput(mpf, pagep, flags)) != 0)
 		goto out;
 	pagep = NULL;
 
@@ -516,7 +508,7 @@ done:	*lsnp = argp->prev_lsn;
 	ret = 0;
 
 out:	if (pagep != NULL)
-		(void)mpf->put(mpf, pagep, 0);
+		(void)__memp_fput(mpf, pagep, 0);
 	REC_CLOSE;
 }
 
@@ -552,20 +544,7 @@ __ham_copypage_recover(dbenv, dbtp, lsnp, op, info)
 	flags = 0;
 
 	/* This is the bucket page. */
-	if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
-		if (DB_UNDO(op)) {
-			/*
-			 * We are undoing and the page doesn't exist.  That
-			 * is equivalent to having a pagelsn of 0, so we
-			 * would not have to undo anything.  In this case,
-			 * don't bother creating a page.
-			 */
-			ret = 0;
-			goto donext;
-		} else if ((ret = mpf->get(mpf,
-		    &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
-			goto out;
-	}
+	REC_FGET(mpf, argp->pgno, &pagep, donext);
 
 	cmp_n = log_compare(lsnp, &LSN(pagep));
 	cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
@@ -585,25 +564,12 @@ __ham_copypage_recover(dbenv, dbtp, lsnp, op, info)
 		LSN(pagep) = argp->pagelsn;
 		flags = DB_MPOOL_DIRTY;
 	}
-	if ((ret = mpf->put(mpf, pagep, flags)) != 0)
+	if ((ret = __memp_fput(mpf, pagep, flags)) != 0)
 		goto out;
 	pagep = NULL;
 
 donext:	/* Now fix up the "next" page. */
-	if ((ret = mpf->get(mpf, &argp->next_pgno, 0, &pagep)) != 0) {
-		if (DB_UNDO(op)) {
-			/*
-			 * We are undoing and the page doesn't exist.  That
-			 * is equivalent to having a pagelsn of 0, so we
-			 * would not have to undo anything.  In this case,
-			 * don't bother creating a page.
-			 */
-			ret = 0;
-			goto do_nn;
-		} else if ((ret = mpf->get(mpf,
-		    &argp->next_pgno, DB_MPOOL_CREATE, &pagep)) != 0)
-			goto out;
-	}
+	REC_FGET(mpf, argp->next_pgno, &pagep, do_nn);
 
 	/* For REDO just update the LSN. For UNDO copy page back. */
 	cmp_n = log_compare(lsnp, &LSN(pagep));
@@ -618,7 +584,7 @@ donext:	/* Now fix up the "next" page. */
 		memcpy(pagep, argp->page.data, argp->page.size);
 		flags = DB_MPOOL_DIRTY;
 	}
-	if ((ret = mpf->put(mpf, pagep, flags)) != 0)
+	if ((ret = __memp_fput(mpf, pagep, flags)) != 0)
 		goto out;
 	pagep = NULL;
 
@@ -626,19 +592,7 @@ donext:	/* Now fix up the "next" page. */
 do_nn:	if (argp->nnext_pgno == PGNO_INVALID)
 		goto done;
 
-	if ((ret = mpf->get(mpf, &argp->nnext_pgno, 0, &pagep)) != 0) {
-		if (DB_UNDO(op)) {
-			/*
-			 * We are undoing and the page doesn't exist.  That
-			 * is equivalent to having a pagelsn of 0, so we
-			 * would not have to undo anything.  In this case,
-			 * don't bother creating a page.
-			 */
-			goto done;
-		} else if ((ret = mpf->get(mpf,
-		    &argp->nnext_pgno, DB_MPOOL_CREATE, &pagep)) != 0)
-			goto out;
-	}
+	REC_FGET(mpf, argp->nnext_pgno, &pagep, done);
 
 	cmp_n = log_compare(lsnp, &LSN(pagep));
 	cmp_p = log_compare(&LSN(pagep), &argp->nnextlsn);
@@ -656,7 +610,7 @@ do_nn:	if (argp->nnext_pgno == PGNO_INVALID)
 		LSN(pagep) = argp->nnextlsn;
 		flags = DB_MPOOL_DIRTY;
 	}
-	if ((ret = mpf->put(mpf, pagep, flags)) != 0)
+	if ((ret = __memp_fput(mpf, pagep, flags)) != 0)
 		goto out;
 	pagep = NULL;
 
@@ -664,7 +618,7 @@ done:	*lsnp = argp->prev_lsn;
 	ret = 0;
 
 out:	if (pagep != NULL)
-		(void)mpf->put(mpf, pagep, 0);
+		(void)__memp_fput(mpf, pagep, 0);
 	REC_CLOSE;
 }
 
@@ -702,7 +656,7 @@ __ham_metagroup_recover(dbenv, dbtp, lsnp, op, info)
 
 	/*
 	 * This logs the virtual create of pages pgno to pgno + bucket
-	 * Since the mpool page-allocation is not really able to be
+	 * If HAVE_FTRUNCATE is not supported the mpool page-allocation is not
 	 * transaction protected, we can never undo it.  Even in an abort,
 	 * we have to allocate these pages to the hash table if they
 	 * were actually created.  In particular, during disaster
@@ -721,28 +675,64 @@ __ham_metagroup_recover(dbenv, dbtp, lsnp, op, info)
 	if (argp->newalloc)
 		pgno += argp->bucket;
 
-	if ((ret = mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &pagep)) != 0)
-		goto out;
+	flags = 0;
+	pagep = NULL;
+#ifndef HAVE_FTRUNCATE
+	flags = DB_MPOOL_CREATE;
+#endif
+	ret = __memp_fget(mpf, &pgno, flags, &pagep);
+
+#ifdef HAVE_FTRUNCATE
+	/* If we are undoing, then we don't want to create the page. */
+	if (ret != 0 && DB_REDO(op))
+		ret = __memp_fget(mpf, &pgno, DB_MPOOL_CREATE, &pagep);
+	else if (ret == DB_PAGE_NOTFOUND) {
+		groupgrow = 0;
+		goto do_meta;
+	}
+#endif
+	if (ret != 0) {
+		if (ret != ENOSPC)
+			goto out;
+		pgno = 0;
+		groupgrow = 0;
+		goto do_meta;
+	}
 
 	cmp_n = log_compare(lsnp, &LSN(pagep));
 	cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
 	CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->pagelsn);
 
 	flags = 0;
-	if ((cmp_p == 0 && DB_REDO(op)) || (cmp_n == 0 && DB_UNDO(op))) {
-		/*
-		 * We need to make sure that we redo the allocation of the
-		 * pages.
-		 */
-		if (DB_REDO(op))
-			pagep->lsn = *lsnp;
-		else
-			pagep->lsn = argp->pagelsn;
+	if (cmp_p == 0 && DB_REDO(op)) {
+		pagep->lsn = *lsnp;
 		flags = DB_MPOOL_DIRTY;
 	}
-	if ((ret = mpf->put(mpf, pagep, flags)) != 0)
+	else if (cmp_n == 0 && DB_UNDO(op)) {
+#ifdef HAVE_FTRUNCATE
+		/* If this record allocated the pages give them back. */
+		if (argp->newalloc) {
+			if (pagep != NULL && (ret =
+			     __memp_fput(mpf, pagep, DB_MPOOL_DISCARD)) != 0)
+				goto out;
+			pagep = NULL;
+			if ((ret = __memp_ftruncate(mpf, argp->pgno, 0)) != 0)
+				goto out;
+		} else
+#endif
+		{
+			/*
+			 * Otherwise just roll the page back to its
+			 * previous state.
+			 */
+			pagep->lsn = argp->pagelsn;
+			flags = DB_MPOOL_DIRTY;
+		}
+	}
+	if (pagep != NULL && (ret = __memp_fput(mpf, pagep, flags)) != 0)
 		goto out;
 
+do_meta:
 	/* Now we have to update the meta-data page. */
 	hcp = (HASH_CURSOR *)dbc->internal;
 	if ((ret = __ham_get_meta(dbc)) != 0)
@@ -776,16 +766,26 @@ __ham_metagroup_recover(dbenv, dbtp, lsnp, op, info)
 	 * Now we need to fix up the spares array.  Each entry in the
 	 * spares array indicates the beginning page number for the
 	 * indicated doubling.  We need to fill this in whenever the
-	 * spares array is invalid, since we never reclaim pages from
-	 * the spares array and we have to allocate the pages to the
+	 * spares array is invalid, if we never reclaim pages then
+	 * we have to allocate the pages to the
 	 * spares array in both the redo and undo cases.
 	 */
-	if (argp->newalloc &&
+	if (groupgrow &&
+#ifdef HAVE_FTRUNCATE
+	    !DB_UNDO(op) &&
+#endif
 	    hcp->hdr->spares[__db_log2(argp->bucket + 1) + 1] == PGNO_INVALID) {
 		hcp->hdr->spares[__db_log2(argp->bucket + 1) + 1] =
-		    argp->pgno - argp->bucket - 1;
+		    (argp->pgno - argp->bucket) - 1;
+		did_recover = 1;
+	}
+#ifdef HAVE_FTRUNCATE
+	if (cmp_n == 0 && groupgrow && DB_UNDO(op)) {
+		hcp->hdr->spares[
+		    __db_log2(argp->bucket + 1) + 1] = PGNO_INVALID;
 		did_recover = 1;
 	}
+#endif
 
 	/*
 	 * Finally, we need to potentially fix up the last_pgno field
@@ -793,30 +793,29 @@ __ham_metagroup_recover(dbenv, dbtp, lsnp, op, info)
 	 * same as the hash header page).
 	 */
 	if (argp->mmpgno != argp->mpgno) {
-		if ((ret =
-		    mpf->get(mpf, &argp->mmpgno, 0, (PAGE **)&mmeta)) != 0)
+		if ((ret = __memp_fget(mpf, &argp->mmpgno, 0, &mmeta)) != 0)
 			goto out;
 		mmeta_flags = 0;
 		cmp_n = log_compare(lsnp, &mmeta->lsn);
 		cmp_p = log_compare(&mmeta->lsn, &argp->mmetalsn);
-		if (cmp_p == 0 && DB_REDO(op)) {
+		if (cmp_p == 0 && DB_REDO(op))
 			mmeta->lsn = *lsnp;
-			mmeta_flags = DB_MPOOL_DIRTY;
-		} else if (cmp_n == 0 && DB_UNDO(op)) {
+		else if (cmp_n == 0 && DB_UNDO(op))
 			mmeta->lsn = argp->mmetalsn;
-			mmeta_flags = DB_MPOOL_DIRTY;
-		}
 	} else
 		mmeta = (DBMETA *)hcp->hdr;
 
-	if (argp->newalloc) {
-		if (mmeta->last_pgno < pgno)
-			mmeta->last_pgno = pgno;
-		mmeta_flags = DB_MPOOL_DIRTY;
-	}
+#ifdef HAVE_FTRUNCATE
+	if (cmp_n == 0 && DB_UNDO(op))
+		mmeta->last_pgno = argp->last_pgno;
+	else if (DB_REDO(op))
+#endif
+	if (mmeta->last_pgno < pgno)
+		mmeta->last_pgno = pgno;
+	mmeta_flags = DB_MPOOL_DIRTY;
 
 	if (argp->mmpgno != argp->mpgno &&
-	    (ret = mpf->put(mpf, mmeta, mmeta_flags)) != 0)
+	    (ret = __memp_fput(mpf, mmeta, mmeta_flags)) != 0)
 		goto out;
 	mmeta = NULL;
 
@@ -827,7 +826,7 @@ done:	*lsnp = argp->prev_lsn;
 	ret = 0;
 
 out:	if (mmeta != NULL)
-		(void)mpf->put(mpf, mmeta, 0);
+		(void)__memp_fput(mpf, mmeta, 0);
 	if (dbc != NULL)
 		(void)__ham_release_meta(dbc);
 	if (ret == ENOENT && op == DB_TXN_BACKWARD_ALLOC)
@@ -866,15 +865,12 @@ __ham_groupalloc_recover(dbenv, dbtp, lsnp, op, info)
 	REC_INTRO(__ham_groupalloc_read, 0);
 
 	pgno = PGNO_BASE_MD;
-	if ((ret = mpf->get(mpf, &pgno, 0, &mmeta)) != 0) {
+	if ((ret = __memp_fget(mpf, &pgno, 0, &mmeta)) != 0) {
 		if (DB_REDO(op)) {
-			/* Page should have existed. */
-			__db_pgerr(file_dbp, pgno, ret);
+			ret = __db_pgerr(file_dbp, pgno, ret);
 			goto out;
-		} else {
-			ret = 0;
+		} else
 			goto done;
-		}
 	}
 
 	cmp_n = log_compare(lsnp, &LSN(mmeta));
@@ -890,6 +886,7 @@ __ham_groupalloc_recover(dbenv, dbtp, lsnp, op, info)
 	 * that the pages were never allocated, so we'd better check for
 	 * that and handle it here.
 	 */
+	pgno = argp->start_pgno + argp->num - 1;
 	if (DB_REDO(op)) {
 		if ((ret = __ham_alloc_pages(file_dbp, argp, lsnp)) != 0)
 			goto out;
@@ -899,35 +896,84 @@ __ham_groupalloc_recover(dbenv, dbtp, lsnp, op, info)
 		}
 	} else if (DB_UNDO(op)) {
 		/*
-		 * Reset the last page back to its preallocation state.
+		 * Fetch the last page and determine if it is in
+		 * the post allocation state.
+		 */
+		pagep = NULL;
+		if ((ret = __memp_fget(mpf, &pgno, 0, &pagep)) == 0) {
+			if (log_compare(&pagep->lsn, lsnp) != 0) {
+				if ((ret = __memp_fput(mpf,
+				     pagep, DB_MPOOL_DISCARD)) != 0)
+					goto out;
+				pagep = NULL;
+			}
+		} else if (ret != DB_PAGE_NOTFOUND)
+			goto out;
+#ifdef HAVE_FTRUNCATE
+		COMPQUIET(info, NULL);
+		/*
+		 * If the last page was allocated then truncate back
+		 * to the first page.
 		 */
-		pgno = argp->start_pgno + argp->num - 1;
-		if ((ret = mpf->get(mpf, &pgno, 0, &pagep)) == 0) {
+		if (pagep != NULL) {
+			if ((ret =
+			    __memp_fput(mpf, pagep, DB_MPOOL_DISCARD)) != 0)
+				goto out;
+			if ((ret =
+			     __memp_ftruncate(mpf, argp->start_pgno, 0)) != 0)
+				goto out;
+		}
 
+		/*
+		 * If we are rolling back the metapage, then make
+		 * sure it reflects the the correct last_pgno.
+		 */
+		if (cmp_n == 0) {
+			mmeta->last_pgno = argp->last_pgno;
+			modified = 1;
+		}
+		pgno = 0;
+#else
+		/*
+		 * Reset the last page back to its preallocation state.
+		 */
+		if (pagep != NULL) {
 			if (log_compare(&pagep->lsn, lsnp) == 0)
 				ZERO_LSN(pagep->lsn);
 
-			if ((ret = mpf->put(mpf, pagep, DB_MPOOL_DIRTY)) != 0)
+			if ((ret =
+			    __memp_fput(mpf, pagep, DB_MPOOL_DIRTY)) != 0)
 				goto out;
-		} else if (ret != DB_PAGE_NOTFOUND)
-			goto out;
+		}
 		/*
-		 * Always put the pages into the limbo list and free them later.
+		 * Put the pages into the limbo list and free them later.
 		 */
 		if ((ret = __db_add_limbo(dbenv,
 		    info, argp->fileid, argp->start_pgno, argp->num)) != 0)
 			goto out;
+#endif
 		if (cmp_n == 0) {
 			LSN(mmeta) = argp->meta_lsn;
 			modified = 1;
 		}
 	}
 
+	/*
+	 * In both REDO and UNDO, we have grown the file and need to make
+	 * sure that last_pgno is correct.  If we HAVE_FTRUNCATE pgno
+	 * will only be valid on REDO.
+	 */
+	if (pgno > mmeta->last_pgno) {
+		mmeta->last_pgno = pgno;
+		modified = 1;
+	}
+
 done:	if (ret == 0)
 		*lsnp = argp->prev_lsn;
+	ret = 0;
 
 out:	if (mmeta != NULL)
-		(void)mpf->put(mpf, mmeta, modified ? DB_MPOOL_DIRTY : 0);
+		(void)__memp_fput(mpf, mmeta, modified ? DB_MPOOL_DIRTY : 0);
 
 	if (ret == ENOENT && op == DB_TXN_BACKWARD_ALLOC)
 		ret = 0;
@@ -961,26 +1007,24 @@ __ham_alloc_pages(dbp, argp, lsnp)
 	pgno = argp->start_pgno + argp->num - 1;
 
 	/* If the page exists, and it has been initialized, then we're done. */
-	if ((ret = mpf->get(mpf, &pgno, 0, &pagep)) == 0) {
+	if ((ret = __memp_fget(mpf, &pgno, 0, &pagep)) == 0) {
 		if (NUM_ENT(pagep) == 0 && IS_ZERO_LSN(pagep->lsn))
 			goto reinit_page;
-		if ((ret = mpf->put(mpf, pagep, 0)) != 0)
+		if ((ret = __memp_fput(mpf, pagep, 0)) != 0)
 			return (ret);
 		return (0);
 	}
 
 	/* Had to create the page. */
-	if ((ret = mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &pagep)) != 0) {
-		__db_pgerr(dbp, pgno, ret);
-		return (ret);
-	}
+	if ((ret = __memp_fget(mpf, &pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+		return (__db_pgerr(dbp, pgno, ret));
 
 reinit_page:
 	/* Initialize the newly allocated page. */
 	P_INIT(pagep, dbp->pgsize, pgno, PGNO_INVALID, PGNO_INVALID, 0, P_HASH);
 	pagep->lsn = *lsnp;
 
-	if ((ret = mpf->put(mpf, pagep, DB_MPOOL_DIRTY)) != 0)
+	if ((ret = __memp_fput(mpf, pagep, DB_MPOOL_DIRTY)) != 0)
 		return (ret);
 
 	return (0);
@@ -1016,9 +1060,9 @@ __ham_curadj_recover(dbenv, dbtp, lsnp, op, info)
 		goto done;
 
 	/*
-	 * Undo the adjustment by reinitializing the the cursor
-	 * to look like the one that was used to do the adustment,
-	 * then we invert the add so that undo the adjustment.
+	 * Undo the adjustment by reinitializing the the cursor to look like
+	 * the one that was used to do the adjustment, then we invert the
+	 * add so that undo the adjustment.
 	 */
 	hcp = (HASH_CURSOR *)dbc->internal;
 	hcp->pgno = argp->pgno;
@@ -1140,7 +1184,7 @@ __ham_chgpg_recover(dbenv, dbtp, lsnp, op, info)
 				 * under us.
 				 */
 				MUTEX_THREAD_UNLOCK(dbenv, file_dbp->mutexp);
-				if ((ret = lcp->opd->c_close(lcp->opd)) != 0)
+				if ((ret = __db_c_close(lcp->opd)) != 0)
 					goto out;
 				MUTEX_THREAD_LOCK(dbenv, file_dbp->mutexp);
 				lcp->opd = NULL;
diff --git a/storage/bdb/hash/hash_reclaim.c b/storage/bdb/hash/hash_reclaim.c
index ac90ffff08abfb70c42944036cbf512d91e635d2..f0adba7c67c92c45cfd91f5dedede96375910665 100644
--- a/storage/bdb/hash/hash_reclaim.c
+++ b/storage/bdb/hash/hash_reclaim.c
@@ -1,20 +1,16 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: hash_reclaim.c,v 11.17 2004/06/22 18:43:38 margo Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: hash_reclaim.c,v 11.12 2002/03/28 19:49:43 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
-
-#include <string.h>
 #endif
 
 #include "db_int.h"
@@ -43,7 +39,7 @@ __ham_reclaim(dbp, txn)
 	int ret;
 
 	/* Open up a cursor that we'll use for traversing. */
-	if ((ret = dbp->cursor(dbp, txn, &dbc, 0)) != 0)
+	if ((ret = __db_cursor(dbp, txn, &dbc, 0)) != 0)
 		return (ret);
 	hcp = (HASH_CURSOR *)dbc->internal;
 
@@ -53,7 +49,7 @@ __ham_reclaim(dbp, txn)
 	if ((ret = __ham_traverse(dbc,
 	    DB_LOCK_WRITE, __db_reclaim_callback, dbc, 1)) != 0)
 		goto err;
-	if ((ret = dbc->c_close(dbc)) != 0)
+	if ((ret = __db_c_close(dbc)) != 0)
 		goto err;
 	if ((ret = __ham_release_meta(dbc)) != 0)
 		goto err;
@@ -61,7 +57,7 @@ __ham_reclaim(dbp, txn)
 
 err:	if (hcp->hdr != NULL)
 		(void)__ham_release_meta(dbc);
-	(void)dbc->c_close(dbc);
+	(void)__db_c_close(dbc);
 	return (ret);
 }
 
@@ -70,42 +66,28 @@ err:	if (hcp->hdr != NULL)
  *	Reclaim the pages from a subdatabase and return them to the
  * parent free list.
  *
- * PUBLIC: int __ham_truncate __P((DB *, DB_TXN *txn, u_int32_t *));
+ * PUBLIC: int __ham_truncate __P((DBC *, u_int32_t *));
  */
 int
-__ham_truncate(dbp, txn, countp)
-	DB *dbp;
-	DB_TXN *txn;
+__ham_truncate(dbc, countp)
+	DBC *dbc;
 	u_int32_t *countp;
 {
-	DBC *dbc;
-	HASH_CURSOR *hcp;
 	db_trunc_param trunc;
-	int ret;
-
-	/* Open up a cursor that we'll use for traversing. */
-	if ((ret = dbp->cursor(dbp, txn, &dbc, 0)) != 0)
-		return (ret);
-	hcp = (HASH_CURSOR *)dbc->internal;
+	int ret, t_ret;
 
 	if ((ret = __ham_get_meta(dbc)) != 0)
-		goto err;
+		return (ret);
 
 	trunc.count = 0;
 	trunc.dbc = dbc;
 
-	if ((ret = __ham_traverse(dbc,
-	    DB_LOCK_WRITE, __db_truncate_callback, &trunc, 1)) != 0)
-		goto err;
-	if ((ret = __ham_release_meta(dbc)) != 0)
-		goto err;
-	if ((ret = dbc->c_close(dbc)) != 0)
-		goto err;
-	*countp = trunc.count;
-	return (0);
+	ret = __ham_traverse(dbc,
+	    DB_LOCK_WRITE, __db_truncate_callback, &trunc, 1);
 
-err:	if (hcp->hdr != NULL)
-		(void)__ham_release_meta(dbc);
-	(void)dbc->c_close(dbc);
+	if ((t_ret = __ham_release_meta(dbc)) != 0 && ret == 0)
+		ret = t_ret;
+
+	*countp = trunc.count;
 	return (ret);
 }
diff --git a/storage/bdb/hash/hash_stat.c b/storage/bdb/hash/hash_stat.c
index f9ee1d099cb506cd5da1aaa09d7fdbf863c18f10..a50e383af0d9022d41021f9cb09d99bfc40f02aa 100644
--- a/storage/bdb/hash/hash_stat.c
+++ b/storage/bdb/hash/hash_stat.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: hash_stat.c,v 11.66 2004/09/22 03:46:22 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: hash_stat.c,v 11.48 2002/08/06 06:11:28 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -19,24 +17,27 @@ static const char revid[] = "$Id: hash_stat.c,v 11.48 2002/08/06 06:11:28 bostic
 
 #include "db_int.h"
 #include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
 #include "dbinc/btree.h"
 #include "dbinc/hash.h"
+#include "dbinc/mp.h"
 
+#ifdef HAVE_STATISTICS
 static int __ham_stat_callback __P((DB *, PAGE *, void *, int *));
 
 /*
  * __ham_stat --
  *	Gather/print the hash statistics
  *
- * PUBLIC: int __ham_stat __P((DB *, void *, u_int32_t));
+ * PUBLIC: int __ham_stat __P((DBC *, void *, u_int32_t));
  */
 int
-__ham_stat(dbp, spp, flags)
-	DB *dbp;
+__ham_stat(dbc, spp, flags)
+	DBC *dbc;
 	void *spp;
 	u_int32_t flags;
 {
-	DBC *dbc;
+	DB *dbp;
 	DB_ENV *dbenv;
 	DB_HASH_STAT *sp;
 	DB_MPOOLFILE *mpf;
@@ -45,20 +46,12 @@ __ham_stat(dbp, spp, flags)
 	db_pgno_t pgno;
 	int ret;
 
+	dbp = dbc->dbp;
 	dbenv = dbp->dbenv;
 
-	PANIC_CHECK(dbenv);
-	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->stat");
-
 	mpf = dbp->mpf;
 	sp = NULL;
 
-	/* Check for invalid flags. */
-	if ((ret = __db_statchk(dbp, flags)) != 0)
-		return (ret);
-
-	if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0)
-		return (ret);
 	hcp = (HASH_CURSOR *)dbc->internal;
 
 	if ((ret = __ham_get_meta(dbc)) != 0)
@@ -86,11 +79,11 @@ __ham_stat(dbp, spp, flags)
 	    pgno != PGNO_INVALID;) {
 		++sp->hash_free;
 
-		if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
+		if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
 			goto err;
 
 		pgno = h->next_pgno;
-		(void)mpf->put(mpf, h, 0);
+		(void)__memp_fput(mpf, h, 0);
 	}
 
 	/* Now traverse the rest of the table. */
@@ -107,10 +100,7 @@ __ham_stat(dbp, spp, flags)
 		hcp->hdr->dbmeta.record_count = sp->hash_ndata;
 	}
 
-done:
-	if ((ret = __ham_release_meta(dbc)) != 0)
-		goto err;
-	if ((ret = dbc->c_close(dbc)) != 0)
+done:	if ((ret = __ham_release_meta(dbc)) != 0)
 		goto err;
 
 	*(DB_HASH_STAT **)spp = sp;
@@ -118,12 +108,247 @@ done:
 
 err:	if (sp != NULL)
 		__os_ufree(dbenv, sp);
+
 	if (hcp->hdr != NULL)
 		(void)__ham_release_meta(dbc);
-	(void)dbc->c_close(dbc);
+
 	return (ret);
+}
+
+/*
+ * __ham_stat_print --
+ *	Display hash statistics.
+ *
+ * PUBLIC: int __ham_stat_print __P((DBC *, u_int32_t));
+ */
+int
+__ham_stat_print(dbc, flags)
+	DBC *dbc;
+	u_int32_t flags;
+{
+	static const FN fn[] = {
+		{ DB_HASH_DUP,		"duplicates" },
+		{ DB_HASH_SUBDB,	"multiple-databases" },
+		{ DB_HASH_DUPSORT,	"sorted duplicates" },
+		{ 0,			NULL }
+	};
+	DB *dbp;
+	DB_ENV *dbenv;
+	DB_HASH_STAT *sp;
+	int lorder, ret;
+	const char *s;
+
+	dbp = dbc->dbp;
+	dbenv = dbp->dbenv;
+
+	if ((ret = __ham_stat(dbc, &sp, 0)) != 0)
+		return (ret);
+
+	if (LF_ISSET(DB_STAT_ALL)) {
+		__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+		__db_msg(dbenv, "Default Hash database information:");
+	}
+	__db_msg(dbenv, "%lx\tHash magic number", (u_long)sp->hash_magic);
+	__db_msg(dbenv,
+	    "%lu\tHash version number", (u_long)sp->hash_version);
+	(void)__db_get_lorder(dbp, &lorder);
+	switch (lorder) {
+	case 1234:
+		s = "Little-endian";
+		break;
+	case 4321:
+		s = "Big-endian";
+		break;
+	default:
+		s = "Unrecognized byte order";
+		break;
+	}
+	__db_msg(dbenv, "%s\tByte order", s);
+	__db_prflags(dbenv, NULL, sp->hash_metaflags, fn, NULL, "\tFlags");
+	__db_dl(dbenv,
+	    "Underlying database page size", (u_long)sp->hash_pagesize);
+	__db_dl(dbenv, "Specified fill factor", (u_long)sp->hash_ffactor);
+	__db_dl(dbenv,
+	    "Number of keys in the database", (u_long)sp->hash_nkeys);
+	__db_dl(dbenv,
+	    "Number of data items in the database", (u_long)sp->hash_ndata);
+
+	__db_dl(dbenv, "Number of hash buckets", (u_long)sp->hash_buckets);
+	__db_dl_pct(dbenv, "Number of bytes free on bucket pages",
+	    (u_long)sp->hash_bfree, DB_PCT_PG(
+	    sp->hash_bfree, sp->hash_buckets, sp->hash_pagesize), "ff");
+
+	__db_dl(dbenv,
+	    "Number of overflow pages", (u_long)sp->hash_bigpages);
+	__db_dl_pct(dbenv, "Number of bytes free in overflow pages",
+	    (u_long)sp->hash_big_bfree, DB_PCT_PG(
+	    sp->hash_big_bfree, sp->hash_bigpages, sp->hash_pagesize), "ff");
+
+	__db_dl(dbenv,
+	    "Number of bucket overflow pages", (u_long)sp->hash_overflows);
+	__db_dl_pct(dbenv,
+	    "Number of bytes free in bucket overflow pages",
+	    (u_long)sp->hash_ovfl_free, DB_PCT_PG(
+	    sp->hash_ovfl_free, sp->hash_overflows, sp->hash_pagesize), "ff");
+
+	__db_dl(dbenv, "Number of duplicate pages", (u_long)sp->hash_dup);
+	__db_dl_pct(dbenv, "Number of bytes free in duplicate pages",
+	    (u_long)sp->hash_dup_free, DB_PCT_PG(
+	    sp->hash_dup_free, sp->hash_dup, sp->hash_pagesize), "ff");
+
+	__db_dl(dbenv,
+	    "Number of pages on the free list", (u_long)sp->hash_free);
+
+	__os_ufree(dbenv, sp);
+
+	return (0);
+}
+
+static int
+__ham_stat_callback(dbp, pagep, cookie, putp)
+	DB *dbp;
+	PAGE *pagep;
+	void *cookie;
+	int *putp;
+{
+	DB_HASH_STAT *sp;
+	DB_BTREE_STAT bstat;
+	db_indx_t indx, len, off, tlen, top;
+	u_int8_t *hk;
+	int ret;
+
+	*putp = 0;
+	sp = cookie;
+
+	switch (pagep->type) {
+	case P_INVALID:
+		/*
+		 * Hash pages may be wholly zeroed;  this is not a bug.
+		 * Obviously such pages have no data, so we can just proceed.
+		 */
+		break;
+	case P_HASH:
+		/*
+		 * We count the buckets and the overflow pages
+		 * separately and tally their bytes separately
+		 * as well.  We need to figure out if this page
+		 * is a bucket.
+		 */
+		if (PREV_PGNO(pagep) == PGNO_INVALID)
+			sp->hash_bfree += P_FREESPACE(dbp, pagep);
+		else {
+			sp->hash_overflows++;
+			sp->hash_ovfl_free += P_FREESPACE(dbp, pagep);
+		}
+		top = NUM_ENT(pagep);
+		/* Correct for on-page duplicates and deleted items. */
+		for (indx = 0; indx < top; indx += P_INDX) {
+			switch (*H_PAIRDATA(dbp, pagep, indx)) {
+			case H_OFFDUP:
+				break;
+			case H_OFFPAGE:
+			case H_KEYDATA:
+				sp->hash_ndata++;
+				break;
+			case H_DUPLICATE:
+				tlen = LEN_HDATA(dbp, pagep, 0, indx);
+				hk = H_PAIRDATA(dbp, pagep, indx);
+				for (off = 0; off < tlen;
+				    off += len + 2 * sizeof(db_indx_t)) {
+					sp->hash_ndata++;
+					memcpy(&len,
+					    HKEYDATA_DATA(hk)
+					    + off, sizeof(db_indx_t));
+				}
+				break;
+			default:
+				return (__db_pgfmt(dbp->dbenv, PGNO(pagep)));
+			}
+		}
+		sp->hash_nkeys += H_NUMPAIRS(pagep);
+		break;
+	case P_IBTREE:
+	case P_IRECNO:
+	case P_LBTREE:
+	case P_LRECNO:
+	case P_LDUP:
+		/*
+		 * These are all btree pages; get a correct
+		 * cookie and call them.  Then add appropriate
+		 * fields into our stat structure.
+		 */
+		memset(&bstat, 0, sizeof(bstat));
+		if ((ret = __bam_stat_callback(dbp, pagep, &bstat, putp)) != 0)
+			return (ret);
+		sp->hash_dup++;
+		sp->hash_dup_free += bstat.bt_leaf_pgfree +
+		    bstat.bt_dup_pgfree + bstat.bt_int_pgfree;
+		sp->hash_ndata += bstat.bt_ndata;
+		break;
+	case P_OVERFLOW:
+		sp->hash_bigpages++;
+		sp->hash_big_bfree += P_OVFLSPACE(dbp, dbp->pgsize, pagep);
+		break;
+	default:
+		return (__db_pgfmt(dbp->dbenv, PGNO(pagep)));
+	}
+
+	return (0);
+}
+
+/*
+ * __ham_print_cursor --
+ *	Display the current cursor.
+ *
+ * PUBLIC: void __ham_print_cursor __P((DBC *));
+ */
+void
+__ham_print_cursor(dbc)
+	DBC *dbc;
+{
+	static const FN fn[] = {
+		{ H_CONTINUE,	"H_CONTINUE" },
+		{ H_DELETED,	"H_DELETED" },
+		{ H_DIRTY,	"H_DIRTY" },
+		{ H_DUPONLY,	"H_DUPONLY" },
+		{ H_EXPAND,	"H_EXPAND" },
+		{ H_ISDUP,	"H_ISDUP" },
+		{ H_NEXT_NODUP,	"H_NEXT_NODUP" },
+		{ H_NOMORE,	"H_NOMORE" },
+		{ H_OK,		"H_OK" },
+		{ 0,		NULL }
+	};
+	DB_ENV *dbenv;
+	HASH_CURSOR *cp;
+
+	dbenv = dbc->dbp->dbenv;
+	cp = (HASH_CURSOR *)dbc->internal;
+
+	STAT_ULONG("Bucket traversing", cp->bucket);
+	STAT_ULONG("Bucket locked", cp->lbucket);
+	STAT_ULONG("Duplicate set offset", cp->dup_off);
+	STAT_ULONG("Current duplicate length", cp->dup_len);
+	STAT_ULONG("Total duplicate set length", cp->dup_tlen);
+	STAT_ULONG("Bytes needed for add", cp->seek_size);
+	STAT_ULONG("Page on which we can insert", cp->seek_found_page);
+	STAT_ULONG("Order", cp->order);
+	__db_prflags(dbenv, NULL, cp->flags, fn, NULL, "\tInternal Flags");
+}
+
+#else /* !HAVE_STATISTICS */
 
+int
+__ham_stat(dbc, spp, flags)
+	DBC *dbc;
+	void *spp;
+	u_int32_t flags;
+{
+	COMPQUIET(spp, NULL);
+	COMPQUIET(flags, 0);
+
+	return (__db_stat_not_built(dbc->dbp->dbenv));
 }
+#endif
 
 /*
  * __ham_traverse
@@ -198,7 +423,7 @@ __ham_traverse(dbc, mode, callback, cookie, look_past_max)
 			/*
 			 * If we are cleaning up pages past the max_bucket,
 			 * then they may be on the free list and have their
-			 * next pointers set, but the should be ignored.  In
+			 * next pointers set, but they should be ignored.  In
 			 * fact, we really ought to just skip anybody who is
 			 * not a valid page.
 			 */
@@ -226,7 +451,7 @@ __ham_traverse(dbc, mode, callback, cookie, look_past_max)
 					    callback, cookie))
 					    != 0)
 						goto err;
-					if ((ret = opd->c_close(opd)) != 0)
+					if ((ret = __db_c_close(opd)) != 0)
 						return (ret);
 					opd = NULL;
 					break;
@@ -245,7 +470,13 @@ __ham_traverse(dbc, mode, callback, cookie, look_past_max)
 						goto err;
 					break;
 				case H_KEYDATA:
+				case H_DUPLICATE:
 					break;
+				default:
+					DB_ASSERT(0);
+					ret = EINVAL;
+					goto err;
+
 				}
 			}
 
@@ -262,111 +493,15 @@ __ham_traverse(dbc, mode, callback, cookie, look_past_max)
 		if (ret != 0)
 			goto err;
 
-		if (STD_LOCKING(dbc))
-			(void)dbp->dbenv->lock_put(dbp->dbenv, &hcp->lock);
-
 		if (hcp->page != NULL) {
-			if ((ret = mpf->put(mpf, hcp->page, 0)) != 0)
+			if ((ret = __memp_fput(mpf, hcp->page, 0)) != 0)
 				return (ret);
 			hcp->page = NULL;
 		}
 
 	}
 err:	if (opd != NULL &&
-	    (t_ret = opd->c_close(opd)) != 0 && ret == 0)
+	    (t_ret = __db_c_close(opd)) != 0 && ret == 0)
 		ret = t_ret;
 	return (ret);
 }
-
-static int
-__ham_stat_callback(dbp, pagep, cookie, putp)
-	DB *dbp;
-	PAGE *pagep;
-	void *cookie;
-	int *putp;
-{
-	DB_HASH_STAT *sp;
-	DB_BTREE_STAT bstat;
-	db_indx_t indx, len, off, tlen, top;
-	u_int8_t *hk;
-	int ret;
-
-	*putp = 0;
-	sp = cookie;
-
-	switch (pagep->type) {
-	case P_INVALID:
-		/*
-		 * Hash pages may be wholly zeroed;  this is not a bug.
-		 * Obviously such pages have no data, so we can just proceed.
-		 */
-		break;
-	case P_HASH:
-		/*
-		 * We count the buckets and the overflow pages
-		 * separately and tally their bytes separately
-		 * as well.  We need to figure out if this page
-		 * is a bucket.
-		 */
-		if (PREV_PGNO(pagep) == PGNO_INVALID)
-			sp->hash_bfree += P_FREESPACE(dbp, pagep);
-		else {
-			sp->hash_overflows++;
-			sp->hash_ovfl_free += P_FREESPACE(dbp, pagep);
-		}
-		top = NUM_ENT(pagep);
-		/* Correct for on-page duplicates and deleted items. */
-		for (indx = 0; indx < top; indx += P_INDX) {
-			switch (*H_PAIRDATA(dbp, pagep, indx)) {
-			case H_OFFDUP:
-			case H_OFFPAGE:
-				break;
-			case H_KEYDATA:
-				sp->hash_ndata++;
-				break;
-			case H_DUPLICATE:
-				tlen = LEN_HDATA(dbp, pagep, 0, indx);
-				hk = H_PAIRDATA(dbp, pagep, indx);
-				for (off = 0; off < tlen;
-				    off += len + 2 * sizeof (db_indx_t)) {
-					sp->hash_ndata++;
-					memcpy(&len,
-					    HKEYDATA_DATA(hk)
-					    + off, sizeof(db_indx_t));
-				}
-			}
-		}
-		sp->hash_nkeys += H_NUMPAIRS(pagep);
-		break;
-	case P_IBTREE:
-	case P_IRECNO:
-	case P_LBTREE:
-	case P_LRECNO:
-	case P_LDUP:
-		/*
-		 * These are all btree pages; get a correct
-		 * cookie and call them.  Then add appropriate
-		 * fields into our stat structure.
-		 */
-		memset(&bstat, 0, sizeof(bstat));
-		bstat.bt_dup_pgfree = 0;
-		bstat.bt_int_pgfree = 0;
-		bstat.bt_leaf_pgfree = 0;
-		bstat.bt_ndata = 0;
-		if ((ret = __bam_stat_callback(dbp, pagep, &bstat, putp)) != 0)
-			return (ret);
-		sp->hash_dup++;
-		sp->hash_dup_free += bstat.bt_leaf_pgfree +
-		    bstat.bt_dup_pgfree + bstat.bt_int_pgfree;
-		sp->hash_ndata += bstat.bt_ndata;
-		break;
-	case P_OVERFLOW:
-		sp->hash_bigpages++;
-		sp->hash_big_bfree += P_OVFLSPACE(dbp, dbp->pgsize, pagep);
-		break;
-	default:
-		return (__db_pgfmt(dbp->dbenv, pagep->pgno));
-	}
-
-	return (0);
-}
diff --git a/storage/bdb/hash/hash_stub.c b/storage/bdb/hash/hash_stub.c
new file mode 100644
index 0000000000000000000000000000000000000000..7bbe925c7d25cb7223f7cac66fff5535ad39a98d
--- /dev/null
+++ b/storage/bdb/hash/hash_stub.c
@@ -0,0 +1,391 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: hash_stub.c,v 1.10 2004/09/29 15:35:14 bostic Exp $
+ */
+
+#include "db_config.h"
+
+#ifndef HAVE_HASH
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/hash.h"
+
+/*
+ * If the library wasn't compiled with the Hash access method, various
+ * routines aren't available.  Stub them here, returning an appropriate
+ * error.
+ */
+
+/*
+ * __db_nohasham --
+ *	Error when a Berkeley DB build doesn't include the access method.
+ *
+ * PUBLIC: int __db_no_hash_am __P((DB_ENV *));
+ */
+int
+__db_no_hash_am(dbenv)
+	DB_ENV *dbenv;
+{
+	__db_err(dbenv,
+	    "library build did not include support for the Hash access method");
+	return (DB_OPNOTSUP);
+}
+
+int
+__ham_30_hashmeta(dbp, real_name, obuf)
+	DB *dbp;
+	char *real_name;
+	u_int8_t *obuf;
+{
+	COMPQUIET(real_name, NULL);
+	COMPQUIET(obuf, NULL);
+	return (__db_no_hash_am(dbp->dbenv));
+}
+
+int
+__ham_30_sizefix(dbp, fhp, realname, metabuf)
+	DB *dbp;
+	DB_FH *fhp;
+	char *realname;
+	u_int8_t *metabuf;
+{
+	COMPQUIET(fhp, NULL);
+	COMPQUIET(realname, NULL);
+	COMPQUIET(metabuf, NULL);
+	return (__db_no_hash_am(dbp->dbenv));
+}
+
+int
+__ham_31_hash(dbp, real_name, flags, fhp, h, dirtyp)
+	DB *dbp;
+	char *real_name;
+	u_int32_t flags;
+	DB_FH *fhp;
+	PAGE *h;
+	int *dirtyp;
+{
+	COMPQUIET(real_name, NULL);
+	COMPQUIET(flags, 0);
+	COMPQUIET(fhp, NULL);
+	COMPQUIET(h, NULL);
+	COMPQUIET(dirtyp, NULL);
+	return (__db_no_hash_am(dbp->dbenv));
+}
+
+int
+__ham_31_hashmeta(dbp, real_name, flags, fhp, h, dirtyp)
+	DB *dbp;
+	char *real_name;
+	u_int32_t flags;
+	DB_FH *fhp;
+	PAGE *h;
+	int *dirtyp;
+{
+	COMPQUIET(real_name, NULL);
+	COMPQUIET(flags, 0);
+	COMPQUIET(fhp, NULL);
+	COMPQUIET(h, NULL);
+	COMPQUIET(dirtyp, NULL);
+	return (__db_no_hash_am(dbp->dbenv));
+}
+
+int
+__ham_c_count(dbc, recnop)
+	DBC *dbc;
+	db_recno_t *recnop;
+{
+	COMPQUIET(recnop, NULL);
+	return (__db_no_hash_am(dbc->dbp->dbenv));
+}
+
+int
+__ham_c_dup(orig_dbc, new_dbc)
+	DBC *orig_dbc, *new_dbc;
+{
+	COMPQUIET(new_dbc, NULL);
+	return (__db_no_hash_am(orig_dbc->dbp->dbenv));
+}
+
+int
+__ham_c_init(dbc)
+	DBC *dbc;
+{
+	return (__db_no_hash_am(dbc->dbp->dbenv));
+}
+
+int
+__ham_db_close(dbp)
+	DB *dbp;
+{
+	COMPQUIET(dbp, NULL);
+	return (0);
+}
+
+int
+__ham_db_create(dbp)
+	DB *dbp;
+{
+	COMPQUIET(dbp, NULL);
+	return (0);
+}
+
+int
+__ham_init_print(dbenv, dtabp, dtabsizep)
+	DB_ENV *dbenv;
+	int (***dtabp)__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+	size_t *dtabsizep;
+{
+	COMPQUIET(dbenv, NULL);
+	COMPQUIET(dtabp, NULL);
+	COMPQUIET(dtabsizep, NULL);
+	return (0);
+}
+
+int
+__ham_init_recover(dbenv, dtabp, dtabsizep)
+	DB_ENV *dbenv;
+	int (***dtabp)__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+	size_t *dtabsizep;
+{
+	COMPQUIET(dbenv, NULL);
+	COMPQUIET(dtabp, NULL);
+	COMPQUIET(dtabsizep, NULL);
+	return (0);
+}
+
+int
+__ham_meta2pgset(dbp, vdp, hmeta, flags, pgset)
+	DB *dbp;
+	VRFY_DBINFO *vdp;
+	HMETA *hmeta;
+	u_int32_t flags;
+	DB *pgset;
+{
+	COMPQUIET(vdp, NULL);
+	COMPQUIET(hmeta, NULL);
+	COMPQUIET(flags, 0);
+	COMPQUIET(pgset, NULL);
+	return (__db_no_hash_am(dbp->dbenv));
+}
+
+int
+__ham_metachk(dbp, name, hashm)
+	DB *dbp;
+	const char *name;
+	HMETA *hashm;
+{
+	COMPQUIET(name, NULL);
+	COMPQUIET(hashm, NULL);
+	return (__db_no_hash_am(dbp->dbenv));
+}
+
+int
+__ham_new_file(dbp, txn, fhp, name)
+	DB *dbp;
+	DB_TXN *txn;
+	DB_FH *fhp;
+	const char *name;
+{
+	COMPQUIET(txn, NULL);
+	COMPQUIET(fhp, NULL);
+	COMPQUIET(name, NULL);
+	return (__db_no_hash_am(dbp->dbenv));
+}
+
+int
+__ham_new_subdb(mdbp, dbp, txn)
+	DB *mdbp, *dbp;
+	DB_TXN *txn;
+{
+	COMPQUIET(dbp, NULL);
+	COMPQUIET(txn, NULL);
+	return (__db_no_hash_am(mdbp->dbenv));
+}
+
+int
+__ham_open(dbp, txn, name, base_pgno, flags)
+	DB *dbp;
+	DB_TXN *txn;
+	const char *name;
+	db_pgno_t base_pgno;
+	u_int32_t flags;
+{
+	COMPQUIET(txn, NULL);
+	COMPQUIET(name, NULL);
+	COMPQUIET(base_pgno, 0);
+	COMPQUIET(flags, 0);
+	return (__db_no_hash_am(dbp->dbenv));
+}
+
+int
+__ham_pgin(dbenv, dummydbp, pg, pp, cookie)
+	DB_ENV *dbenv;
+	DB *dummydbp;
+	db_pgno_t pg;
+	void *pp;
+	DBT *cookie;
+{
+	COMPQUIET(dummydbp, NULL);
+	COMPQUIET(pg, 0);
+	COMPQUIET(pp, NULL);
+	COMPQUIET(cookie, NULL);
+	return (__db_no_hash_am(dbenv));
+}
+
+int
+__ham_pgout(dbenv, dummydbp, pg, pp, cookie)
+	DB_ENV *dbenv;
+	DB *dummydbp;
+	db_pgno_t pg;
+	void *pp;
+	DBT *cookie;
+{
+	COMPQUIET(dummydbp, NULL);
+	COMPQUIET(pg, 0);
+	COMPQUIET(pp, NULL);
+	COMPQUIET(cookie, NULL);
+	return (__db_no_hash_am(dbenv));
+}
+
+void
+__ham_print_cursor(dbc)
+	DBC *dbc;
+{
+	(void)__db_no_hash_am(dbc->dbp->dbenv);
+}
+
+int
+__ham_quick_delete(dbc)
+	DBC *dbc;
+{
+	return (__db_no_hash_am(dbc->dbp->dbenv));
+}
+
+int
+__ham_reclaim(dbp, txn)
+	DB *dbp;
+	DB_TXN *txn;
+{
+	COMPQUIET(txn, NULL);
+	return (__db_no_hash_am(dbp->dbenv));
+}
+
+int
+__ham_salvage(dbp, vdp, pgno, h, handle, callback, flags)
+	DB *dbp;
+	VRFY_DBINFO *vdp;
+	db_pgno_t pgno;
+	PAGE *h;
+	void *handle;
+	int (*callback) __P((void *, const void *));
+	u_int32_t flags;
+{
+	COMPQUIET(vdp, NULL);
+	COMPQUIET(pgno, 0);
+	COMPQUIET(h, NULL);
+	COMPQUIET(handle, NULL);
+	COMPQUIET(callback, NULL);
+	COMPQUIET(flags, 0);
+	return (__db_no_hash_am(dbp->dbenv));
+}
+
+int
+__ham_stat(dbc, spp, flags)
+	DBC *dbc;
+	void *spp;
+	u_int32_t flags;
+{
+	COMPQUIET(spp, NULL);
+	COMPQUIET(flags, 0);
+	return (__db_no_hash_am(dbc->dbp->dbenv));
+}
+
+int
+__ham_stat_print(dbc, flags)
+	DBC *dbc;
+	u_int32_t flags;
+{
+	COMPQUIET(flags, 0);
+	return (__db_no_hash_am(dbc->dbp->dbenv));
+}
+
+int
+__ham_truncate(dbc, countp)
+	DBC *dbc;
+	u_int32_t *countp;
+{
+	COMPQUIET(dbc, NULL);
+	COMPQUIET(countp, NULL);
+	return (__db_no_hash_am(dbc->dbp->dbenv));
+}
+
+int
+__ham_vrfy(dbp, vdp, h, pgno, flags)
+	DB *dbp;
+	VRFY_DBINFO *vdp;
+	PAGE *h;
+	db_pgno_t pgno;
+	u_int32_t flags;
+{
+	COMPQUIET(vdp, NULL);
+	COMPQUIET(h, NULL);
+	COMPQUIET(pgno, 0);
+	COMPQUIET(flags, 0);
+	return (__db_no_hash_am(dbp->dbenv));
+}
+
+int
+__ham_vrfy_hashing(dbp, nentries, m, thisbucket, pgno, flags, hfunc)
+	DB *dbp;
+	u_int32_t nentries;
+	HMETA *m;
+	u_int32_t thisbucket;
+	db_pgno_t pgno;
+	u_int32_t flags;
+	u_int32_t (*hfunc) __P((DB *, const void *, u_int32_t));
+{
+	COMPQUIET(nentries, 0);
+	COMPQUIET(m, NULL);
+	COMPQUIET(thisbucket, 0);
+	COMPQUIET(pgno, 0);
+	COMPQUIET(flags, 0);
+	COMPQUIET(hfunc, NULL);
+	return (__db_no_hash_am(dbp->dbenv));
+}
+
+int
+__ham_vrfy_meta(dbp, vdp, m, pgno, flags)
+	DB *dbp;
+	VRFY_DBINFO *vdp;
+	HMETA *m;
+	db_pgno_t pgno;
+	u_int32_t flags;
+{
+	COMPQUIET(vdp, NULL);
+	COMPQUIET(m, NULL);
+	COMPQUIET(pgno, 0);
+	COMPQUIET(flags, 0);
+	return (__db_no_hash_am(dbp->dbenv));
+}
+
+int
+__ham_vrfy_structure(dbp, vdp, meta_pgno, flags)
+	DB *dbp;
+	VRFY_DBINFO *vdp;
+	db_pgno_t meta_pgno;
+	u_int32_t flags;
+{
+	COMPQUIET(vdp, NULL);
+	COMPQUIET(meta_pgno, 0);
+	COMPQUIET(flags, 0);
+	return (__db_no_hash_am(dbp->dbenv));
+}
+#endif /* !HAVE_HASH */
diff --git a/storage/bdb/hash/hash_upgrade.c b/storage/bdb/hash/hash_upgrade.c
index 2dd21d7b644c0c1dbc83da1345ea86e2d60b6721..b626138efd53828564bb338991b06faade02d752 100644
--- a/storage/bdb/hash/hash_upgrade.c
+++ b/storage/bdb/hash/hash_upgrade.c
@@ -1,19 +1,17 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: hash_upgrade.c,v 11.35 2004/04/06 12:38:08 bostic Exp $
  */
-#include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: hash_upgrade.c,v 11.32 2002/08/06 05:34:58 bostic Exp $";
-#endif /* not lint */
+#include "db_config.h"
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
-#include <limits.h>
 #include <string.h>
 #endif
 
@@ -38,8 +36,8 @@ __ham_30_hashmeta(dbp, real_name, obuf)
 	HASHHDR *oldmeta;
 	HMETA30 newmeta;
 	u_int32_t *o_spares, *n_spares;
-	u_int32_t fillf, maxb, nelem;
-	int i, max_entry, ret;
+	u_int32_t fillf, i, maxb, max_entry, nelem;
+	int ret;
 
 	dbenv = dbp->dbenv;
 	memset(&newmeta, 0, sizeof(newmeta));
diff --git a/storage/bdb/hash/hash_verify.c b/storage/bdb/hash/hash_verify.c
index e6f5a2b0d65548a2017d992c28ffcd614808d0e5..b9caab27601170fb188bb6cdeea2914db8ef5ae6 100644
--- a/storage/bdb/hash/hash_verify.c
+++ b/storage/bdb/hash/hash_verify.c
@@ -1,18 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: hash_verify.c,v 1.53 2002/08/06 05:35:02 bostic Exp $
+ * $Id: hash_verify.c,v 1.63 2004/10/14 18:11:36 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: hash_verify.c,v 1.53 2002/08/06 05:35:02 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -21,9 +17,11 @@ static const char revid[] = "$Id: hash_verify.c,v 1.53 2002/08/06 05:35:02 bosti
 
 #include "db_int.h"
 #include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
 #include "dbinc/db_verify.h"
 #include "dbinc/btree.h"
 #include "dbinc/hash.h"
+#include "dbinc/mp.h"
 
 static int __ham_dups_unsorted __P((DB *, u_int8_t *, u_int32_t));
 static int __ham_vrfy_bucket __P((DB *, VRFY_DBINFO *, HMETA *, u_int32_t,
@@ -83,12 +81,12 @@ __ham_vrfy_meta(dbp, vdp, m, pgno, flags)
 	if (!LF_ISSET(DB_NOORDERCHK))
 		if (m->h_charkey != hfunc(dbp, CHARKEY, sizeof(CHARKEY))) {
 			EPRINT((dbp->dbenv,
-"Page %lu: database has different custom hash function; reverify with DB_NOORDERCHK set",
+"Page %lu: database has custom hash function; reverify with DB_NOORDERCHK set",
 			    (u_long)pgno));
 			/*
-			 * Return immediately;  this is probably a sign
-			 * of user error rather than database corruption, so
-			 * we want to avoid extraneous errors.
+			 * Return immediately;  this is probably a sign of user
+			 * error rather than database corruption, so we want to
+			 * avoid extraneous errors.
 			 */
 			isbad = 1;
 			goto err;
@@ -173,6 +171,9 @@ __ham_vrfy_meta(dbp, vdp, m, pgno, flags)
 err:	if ((t_ret =
 	    __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
 		ret = t_ret;
+	if (LF_ISSET(DB_SALVAGE) &&
+	   (t_ret = __db_salvage_markdone(vdp, pgno)) != 0 && ret == 0)
+		ret = t_ret;
 	return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
 }
 
@@ -200,11 +201,6 @@ __ham_vrfy(dbp, vdp, h, pgno, flags)
 	if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
 		return (ret);
 
-	/* Sanity check our flags and page type. */
-	if ((ret = __db_fchk(dbp->dbenv, "__ham_vrfy",
-	    flags, DB_AGGRESSIVE | DB_NOORDERCHK | DB_SALVAGE)) != 0)
-		goto err;
-
 	if (TYPE(h) != P_HASH) {
 		TYPE_ERR_PRINT(dbp->dbenv, "__ham_vrfy", pgno, TYPE(h));
 		DB_ASSERT(0);
@@ -376,7 +372,7 @@ __ham_vrfy_item(dbp, vdp, pgno, h, i, flags)
 		break;
 	default:
 		EPRINT((dbp->dbenv,
-		    "Page %lu: item %i has bad type",
+		    "Page %lu: item %lu has bad type",
 		    (u_long)pip->pgno, (u_long)i));
 		ret = DB_VERIFY_BAD;
 		break;
@@ -428,7 +424,7 @@ __ham_vrfy_structure(dbp, vdp, meta_pgno, flags)
 		return (ret);
 
 	/* Get the meta page;  we'll need it frequently. */
-	if ((ret = mpf->get(mpf, &meta_pgno, 0, &m)) != 0)
+	if ((ret = __memp_fget(mpf, &meta_pgno, 0, &m)) != 0)
 		return (ret);
 
 	/* Loop through bucket by bucket. */
@@ -505,9 +501,9 @@ __ham_vrfy_structure(dbp, vdp, meta_pgno, flags)
 		goto err;
 	}
 
-err:	if ((t_ret = mpf->put(mpf, m, 0)) != 0)
+err:	if ((t_ret = __memp_fput(mpf, m, 0)) != 0)
 		return (t_ret);
-	if (h != NULL && (t_ret = mpf->put(mpf, h, 0)) != 0)
+	if (h != NULL && (t_ret = __memp_fput(mpf, h, 0)) != 0)
 		return (t_ret);
 	return ((isbad == 1 && ret == 0) ? DB_VERIFY_BAD: ret);
 }
@@ -631,7 +627,8 @@ __ham_vrfy_bucket(dbp, vdp, m, bucket, flags)
 		    ret = __db_vrfy_ccnext(cc, &child))
 			if (child->type == V_OVERFLOW) {
 				if ((ret = __db_vrfy_ovfl_structure(dbp, vdp,
-				    child->pgno, child->tlen, flags)) != 0) {
+				    child->pgno, child->tlen,
+				    flags | ST_OVFL_LEAF)) != 0) {
 					if (ret == DB_VERIFY_BAD)
 						isbad = 1;
 					else
@@ -741,7 +738,7 @@ __ham_vrfy_hashing(dbp, nentries, m, thisbucket, pgno, flags, hfunc)
 	memset(&dbt, 0, sizeof(DBT));
 	F_SET(&dbt, DB_DBT_REALLOC);
 
-	if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
+	if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
 		return (ret);
 
 	for (i = 0; i < nentries; i += 2) {
@@ -771,7 +768,7 @@ __ham_vrfy_hashing(dbp, nentries, m, thisbucket, pgno, flags, hfunc)
 
 err:	if (dbt.data != NULL)
 		__os_ufree(dbp->dbenv, dbt.data);
-	if ((t_ret = mpf->put(mpf, h, 0)) != 0)
+	if ((t_ret = __memp_fput(mpf, h, 0)) != 0)
 		return (t_ret);
 
 	return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
@@ -858,7 +855,7 @@ __ham_salvage(dbp, vdp, pgno, h, handle, callback, flags)
 keydata:			memcpy(buf, HKEYDATA_DATA(hk), len);
 				dbt.size = len;
 				dbt.data = buf;
-				if ((ret = __db_prdbt(&dbt,
+				if ((ret = __db_vrfy_prdbt(&dbt,
 				    0, " ", handle, callback, 0, vdp)) != 0)
 					err_ret = ret;
 				break;
@@ -872,11 +869,11 @@ keydata:			memcpy(buf, HKEYDATA_DATA(hk), len);
 				if ((ret = __db_safe_goff(dbp, vdp,
 				    dpgno, &dbt, &buf, flags)) != 0) {
 					err_ret = ret;
-					(void)__db_prdbt(&unkdbt, 0, " ",
+					(void)__db_vrfy_prdbt(&unkdbt, 0, " ",
 					    handle, callback, 0, vdp);
 					break;
 				}
-				if ((ret = __db_prdbt(&dbt,
+				if ((ret = __db_vrfy_prdbt(&dbt,
 				    0, " ", handle, callback, 0, vdp)) != 0)
 					err_ret = ret;
 				break;
@@ -889,7 +886,8 @@ keydata:			memcpy(buf, HKEYDATA_DATA(hk), len);
 				    HOFFPAGE_PGNO(hk), sizeof(dpgno));
 				/* UNKNOWN iff pgno is bad or we're a key. */
 				if (!IS_VALID_PGNO(dpgno) || (i % 2 == 0)) {
-					if ((ret = __db_prdbt(&unkdbt, 0, " ",
+					if ((ret =
+					    __db_vrfy_prdbt(&unkdbt, 0, " ",
 					    handle, callback, 0, vdp)) != 0)
 						err_ret = ret;
 				} else if ((ret = __db_salvage_duptree(dbp,
@@ -932,7 +930,7 @@ keydata:			memcpy(buf, HKEYDATA_DATA(hk), len);
 					memcpy(buf, hk + tlen, dlen);
 					dbt.size = dlen;
 					dbt.data = buf;
-					if ((ret = __db_prdbt(&dbt, 0, " ",
+					if ((ret = __db_vrfy_prdbt(&dbt, 0, " ",
 					    handle, callback, 0, vdp)) != 0)
 						err_ret = ret;
 					tlen += sizeof(db_indx_t);
@@ -994,7 +992,7 @@ int __ham_meta2pgset(dbp, vdp, hmeta, flags, pgset)
 		 * Safely walk the list of pages in this bucket.
 		 */
 		for (;;) {
-			if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
+			if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
 				return (ret);
 			if (TYPE(h) == P_HASH) {
 
@@ -1003,12 +1001,12 @@ int __ham_meta2pgset(dbp, vdp, hmeta, flags, pgset)
 				 * pgset.
 				 */
 				if (++totpgs > vdp->last_pgno) {
-					(void)mpf->put(mpf, h, 0);
+					(void)__memp_fput(mpf, h, 0);
 					return (DB_VERIFY_BAD);
 				}
 				if ((ret =
 				    __db_vrfy_pgset_inc(pgset, pgno)) != 0) {
-					(void)mpf->put(mpf, h, 0);
+					(void)__memp_fput(mpf, h, 0);
 					return (ret);
 				}
 
@@ -1016,7 +1014,7 @@ int __ham_meta2pgset(dbp, vdp, hmeta, flags, pgset)
 			} else
 				pgno = PGNO_INVALID;
 
-			if ((ret = mpf->put(mpf, h, 0)) != 0)
+			if ((ret = __memp_fput(mpf, h, 0)) != 0)
 				return (ret);
 
 			/* If the new pgno is wonky, go onto the next bucket. */
diff --git a/storage/bdb/hmac/hmac.c b/storage/bdb/hmac/hmac.c
index d39a154ec6355ba646e63ee1e237d758923dfe88..bb2da5eb472e71d3919d7bed72ed9f357c2f9d21 100644
--- a/storage/bdb/hmac/hmac.c
+++ b/storage/bdb/hmac/hmac.c
@@ -1,19 +1,17 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
+ * Copyright (c) 2001-2004
  *	Sleepycat Software.  All rights reserved.
  *
  * Some parts of this code originally written by Adam Stubblefield,
- * astubble@rice.edu.
+ * -- astubble@rice.edu.
+ *
+ * $Id: hmac.c,v 1.27 2004/01/28 03:36:11 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: hmac.c,v 1.25 2002/09/10 02:40:40 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <string.h>
 #endif
diff --git a/storage/bdb/hmac/sha1.c b/storage/bdb/hmac/sha1.c
index 2f2c806a21f5918124b1db1090737c308b236b18..8824796f0994de5f11d5fd151dc19b0c2c50abe1 100644
--- a/storage/bdb/hmac/sha1.c
+++ b/storage/bdb/hmac/sha1.c
@@ -1,8 +1,9 @@
+/*
+ * $Id: sha1.c,v 1.14 2004/01/28 03:36:11 bostic Exp $
+ */
+
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: sha1.c,v 1.13 2002/04/09 13:40:36 sue Exp $";
-#endif /* not lint */
 /*
 SHA-1 in C
 By Steve Reid <sreid@sea-to-sky.net>
diff --git a/storage/bdb/hsearch/hsearch.c b/storage/bdb/hsearch/hsearch.c
index 9760aeeb9e8c3e919cbda5458f45d752d39ee2e4..5bcbe93d3865fae03d099a8beeb7ed5ec3df6cc9 100644
--- a/storage/bdb/hsearch/hsearch.c
+++ b/storage/bdb/hsearch/hsearch.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -38,14 +38,12 @@
  * 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.
+ *
+ * $Id: hsearch.c,v 11.14 2004/01/28 03:36:11 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: hsearch.c,v 11.12 2002/02/22 01:55:57 mjc Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
diff --git a/storage/bdb/lock/lock.c b/storage/bdb/lock/lock.c
index 8eda155b822fa0021498ced71b16f23e48fe27c0..2b4f63e0da9492d36cb1ed7de0f1efd2bcafd124 100644
--- a/storage/bdb/lock/lock.c
+++ b/storage/bdb/lock/lock.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: lock.c,v 11.167 2004/10/15 16:59:41 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: lock.c,v 11.108 2002/08/06 06:11:34 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -21,17 +19,12 @@ static const char revid[] = "$Id: lock.c,v 11.108 2002/08/06 06:11:34 bostic Exp
 #include "dbinc/db_shash.h"
 #include "dbinc/lock.h"
 #include "dbinc/log.h"
-#include "dbinc/txn.h"
 
-static int  __lock_checklocker __P((DB_LOCKTAB *,
+static int  __lock_freelock __P((DB_LOCKTAB *,
 		struct __db_lock *, u_int32_t, u_int32_t));
-static void __lock_expires __P((DB_ENV *, db_timeval_t *, db_timeout_t));
-static void __lock_freelocker
-		__P((DB_LOCKTAB *, DB_LOCKREGION *, DB_LOCKER *, u_int32_t));
-static int  __lock_get_internal __P((DB_LOCKTAB *, u_int32_t, u_int32_t,
-		const DBT *, db_lockmode_t, db_timeout_t, DB_LOCK *));
 static int  __lock_getobj
 		__P((DB_LOCKTAB *, const DBT *, u_int32_t, int, DB_LOCKOBJ **));
+static int  __lock_inherit_locks __P ((DB_LOCKTAB *, u_int32_t, u_int32_t));
 static int  __lock_is_parent __P((DB_LOCKTAB *, u_int32_t, DB_LOCKER *));
 static int  __lock_put_internal __P((DB_LOCKTAB *,
 		struct __db_lock *, u_int32_t,  u_int32_t));
@@ -40,124 +33,47 @@ static void __lock_remove_waiter __P((DB_LOCKTAB *,
 		DB_LOCKOBJ *, struct __db_lock *, db_status_t));
 static int __lock_trade __P((DB_ENV *, DB_LOCK *, u_int32_t));
 
-static const char __db_lock_err[] = "Lock table is out of available %s";
 static const char __db_lock_invalid[] = "%s: Lock is no longer valid";
 static const char __db_locker_invalid[] = "Locker is not valid";
 
 /*
- * __lock_id --
- *	Generate a unique locker id.
- *
- * PUBLIC: int __lock_id __P((DB_ENV *, u_int32_t *));
- */
-int
-__lock_id(dbenv, idp)
-	DB_ENV *dbenv;
-	u_int32_t *idp;
-{
-	DB_LOCKER *lk;
-	DB_LOCKTAB *lt;
-	DB_LOCKREGION *region;
-	u_int32_t *ids, locker_ndx;
-	int nids, ret;
-
-	PANIC_CHECK(dbenv);
-	ENV_REQUIRES_CONFIG(dbenv,
-	    dbenv->lk_handle, "DB_ENV->lock_id", DB_INIT_LOCK);
-
-	lt = dbenv->lk_handle;
-	region = lt->reginfo.primary;
-	ret = 0;
-
-	/*
-	 * Allocate a new lock id.  If we wrap around then we
-	 * find the minimum currently in use and make sure we
-	 * can stay below that.  This code is similar to code
-	 * in __txn_begin_int for recovering txn ids.
-	 */
-	LOCKREGION(dbenv, lt);
-	/*
-	 * Our current valid range can span the maximum valid value, so check
-	 * for it and wrap manually.
-	 */
-	if (region->stat.st_id == DB_LOCK_MAXID &&
-	    region->stat.st_cur_maxid != DB_LOCK_MAXID)
-		region->stat.st_id = DB_LOCK_INVALIDID;
-	if (region->stat.st_id == region->stat.st_cur_maxid) {
-		if ((ret = __os_malloc(dbenv,
-		    sizeof(u_int32_t) * region->stat.st_nlockers, &ids)) != 0)
-			goto err;
-		nids = 0;
-		for (lk = SH_TAILQ_FIRST(&region->lockers, __db_locker);
-		    lk != NULL;
-		    lk = SH_TAILQ_NEXT(lk, ulinks, __db_locker))
-			ids[nids++] = lk->id;
-		region->stat.st_id = DB_LOCK_INVALIDID;
-		region->stat.st_cur_maxid = DB_LOCK_MAXID;
-		if (nids != 0)
-			__db_idspace(ids, nids,
-			    &region->stat.st_id, &region->stat.st_cur_maxid);
-		__os_free(dbenv, ids);
-	}
-	*idp = ++region->stat.st_id;
-
-	/* Allocate a locker for this id. */
-	LOCKER_LOCK(lt, region, *idp, locker_ndx);
-	ret = __lock_getlocker(lt, *idp, locker_ndx, 1, &lk);
-
-err:	UNLOCKREGION(dbenv, lt);
-
-	return (ret);
-}
-
-/*
- * __lock_id_free --
- *	Free a locker id.
+ * __lock_vec_pp --
+ *	DB_ENV->lock_vec pre/post processing.
  *
- * PUBLIC: int __lock_id_free __P((DB_ENV *, u_int32_t));
+ * PUBLIC: int __lock_vec_pp __P((DB_ENV *,
+ * PUBLIC:     u_int32_t, u_int32_t, DB_LOCKREQ *, int, DB_LOCKREQ **));
  */
 int
-__lock_id_free(dbenv, id)
+__lock_vec_pp(dbenv, locker, flags, list, nlist, elistp)
 	DB_ENV *dbenv;
-	u_int32_t id;
+	u_int32_t locker, flags;
+	int nlist;
+	DB_LOCKREQ *list, **elistp;
 {
-	DB_LOCKER *sh_locker;
-	DB_LOCKTAB *lt;
-	DB_LOCKREGION *region;
-	u_int32_t locker_ndx;
-	int ret;
+	int rep_check, ret;
 
 	PANIC_CHECK(dbenv);
 	ENV_REQUIRES_CONFIG(dbenv,
-	    dbenv->lk_handle, "DB_ENV->lock_id_free", DB_INIT_LOCK);
-
-	lt = dbenv->lk_handle;
-	region = lt->reginfo.primary;
-
-	LOCKREGION(dbenv, lt);
-	LOCKER_LOCK(lt, region, id, locker_ndx);
-	if ((ret =
-	    __lock_getlocker(lt, id, locker_ndx, 0, &sh_locker)) != 0)
-		goto err;
-	if (sh_locker == NULL) {
-		ret = EINVAL;
-		goto err;
-	}
-
-	if (sh_locker->nlocks != 0) {
-		__db_err(dbenv, "Locker still has locks");
-		ret = EINVAL;
-		goto err;
-	}
+	    dbenv->lk_handle, "DB_ENV->lock_vec", DB_INIT_LOCK);
 
-	__lock_freelocker(lt, region, sh_locker, locker_ndx);
+	/* Validate arguments. */
+	if ((ret = __db_fchk(dbenv,
+	     "DB_ENV->lock_vec", flags, DB_LOCK_NOWAIT)) != 0)
+		return (ret);
 
-err:	UNLOCKREGION(dbenv, lt);
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __lock_vec(dbenv, locker, flags, list, nlist, elistp);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
 	return (ret);
 }
 
 /*
  * __lock_vec --
+ *	DB_ENV->lock_vec.
+ *
  *	Vector lock routine.  This function takes a set of operations
  *	and performs them all at once.  In addition, lock_vec provides
  *	functionality for lock inheritance, releasing all locks for a
@@ -176,26 +92,18 @@ __lock_vec(dbenv, locker, flags, list, nlist, elistp)
 {
 	struct __db_lock *lp, *next_lock;
 	DB_LOCK lock;
-	DB_LOCKER *sh_locker, *sh_parent;
-	DB_LOCKOBJ *obj, *sh_obj;
+	DB_LOCKER *sh_locker;
+	DB_LOCKOBJ *sh_obj;
 	DB_LOCKREGION *region;
 	DB_LOCKTAB *lt;
+	DBT *objlist, *np;
 	u_int32_t lndx, ndx;
 	int did_abort, i, ret, run_dd, upgrade, writes;
 
-	PANIC_CHECK(dbenv);
-	ENV_REQUIRES_CONFIG(dbenv,
-	    dbenv->lk_handle, "DB_ENV->lock_vec", DB_INIT_LOCK);
-
 	/* Check if locks have been globally turned off. */
 	if (F_ISSET(dbenv, DB_ENV_NOLOCKING))
 		return (0);
 
-	/* Validate arguments. */
-	if ((ret = __db_fchk(dbenv, "DB_ENV->lock_vec",
-	    flags, DB_LOCK_FREE_LOCKER | DB_LOCK_NOWAIT)) != 0)
-		return (ret);
-
 	lt = dbenv->lk_handle;
 	region = lt->reginfo.primary;
 
@@ -205,77 +113,18 @@ __lock_vec(dbenv, locker, flags, list, nlist, elistp)
 		switch (list[i].op) {
 		case DB_LOCK_GET_TIMEOUT:
 			LF_SET(DB_LOCK_SET_TIMEOUT);
+			/* FALLTHROUGH */
 		case DB_LOCK_GET:
+			if (IS_RECOVERING(dbenv)) {
+				LOCK_INIT(list[i].lock);
+				break;
+			}
 			ret = __lock_get_internal(dbenv->lk_handle,
 			    locker, flags, list[i].obj,
 			    list[i].mode, list[i].timeout, &list[i].lock);
 			break;
 		case DB_LOCK_INHERIT:
-			/*
-			 * Get the committing locker and mark it as deleted.
-			 * This allows us to traverse the locker links without
-			 * worrying that someone else is deleting locks out
-			 * from under us.  However, if the locker doesn't
-			 * exist, that just means that the child holds no
-			 * locks, so inheritance is easy!
-			 */
-			LOCKER_LOCK(lt, region, locker, ndx);
-			if ((ret = __lock_getlocker(lt,
-			    locker, ndx, 0, &sh_locker)) != 0 ||
-			    sh_locker == NULL ||
-			    F_ISSET(sh_locker, DB_LOCKER_DELETED)) {
-				if (ret == 0 && sh_locker != NULL)
-					ret = EINVAL;
-				__db_err(dbenv, __db_locker_invalid);
-				break;
-			}
-
-			/* Make sure we are a child transaction. */
-			if (sh_locker->parent_locker == INVALID_ROFF) {
-				__db_err(dbenv, "Not a child transaction");
-				ret = EINVAL;
-				break;
-			}
-			sh_parent = (DB_LOCKER *)
-			    R_ADDR(&lt->reginfo, sh_locker->parent_locker);
-			F_SET(sh_locker, DB_LOCKER_DELETED);
-
-			/*
-			 * Now, lock the parent locker; move locks from
-			 * the committing list to the parent's list.
-			 */
-			LOCKER_LOCK(lt, region, locker, ndx);
-			if (F_ISSET(sh_parent, DB_LOCKER_DELETED)) {
-				if (ret == 0) {
-					__db_err(dbenv,
-					    "Parent locker is not valid");
-					ret = EINVAL;
-				}
-				break;
-			}
-
-			for (lp = SH_LIST_FIRST(&sh_locker->heldby, __db_lock);
-			    lp != NULL;
-			    lp = SH_LIST_FIRST(&sh_locker->heldby, __db_lock)) {
-				SH_LIST_REMOVE(lp, locker_links, __db_lock);
-				SH_LIST_INSERT_HEAD(&sh_parent->heldby, lp,
-				    locker_links, __db_lock);
-				lp->holder = sh_parent->id;
-
-				/* Get the object associated with this lock. */
-				obj = (DB_LOCKOBJ *)((u_int8_t *)lp + lp->obj);
-
-				(void)__lock_promote(lt, obj,
-				    LF_ISSET(DB_LOCK_NOWAITERS));
-			}
-
-			/* Transfer child counts to parent. */
-			sh_parent->nlocks += sh_locker->nlocks;
-			sh_parent->nwrites += sh_locker->nwrites;
-
-			/* Now free the original locker. */
-			ret = __lock_checklocker(lt,
-			    NULL, locker, DB_LOCK_IGNOREDEL);
+			ret = __lock_inherit_locks(lt, locker, flags);
 			break;
 		case DB_LOCK_PUT:
 			ret = __lock_put_nolock(dbenv,
@@ -313,15 +162,35 @@ __lock_vec(dbenv, locker, flags, list, nlist, elistp)
 					upgrade = 1;
 				writes = 0;
 			}
+			objlist = list[i].obj;
+			if (objlist != NULL) {
+				/*
+				 * We know these should be ilocks,
+				 * but they could be something else,
+				 * so allocate room for the size too.
+				 */
+				objlist->size =
+				     sh_locker->nwrites * sizeof(DBT);
+				if ((ret = __os_malloc(dbenv,
+				     objlist->size, &objlist->data)) != 0)
+					goto up_done;
+				memset(objlist->data, 0, objlist->size);
+				np = (DBT *) objlist->data;
+			} else
+				np = NULL;
 
 			F_SET(sh_locker, DB_LOCKER_DELETED);
 
 			/* Now traverse the locks, releasing each one. */
 			for (lp = SH_LIST_FIRST(&sh_locker->heldby, __db_lock);
-			    lp != NULL;) {
+			    lp != NULL; lp = next_lock) {
 				sh_obj = (DB_LOCKOBJ *)
 				    ((u_int8_t *)lp + lp->obj);
-				if (writes == 1 || lp->mode == DB_LOCK_READ) {
+				next_lock = SH_LIST_NEXT(lp,
+				    locker_links, __db_lock);
+				if (writes == 1 ||
+				    lp->mode == DB_LOCK_READ ||
+				    lp->mode == DB_LOCK_DIRTY) {
 					SH_LIST_REMOVE(lp,
 					    locker_links, __db_lock);
 					sh_obj = (DB_LOCKOBJ *)
@@ -339,12 +208,24 @@ __lock_vec(dbenv, locker, flags, list, nlist, elistp)
 					    lndx, DB_LOCK_FREE | DB_LOCK_DOALL);
 					if (ret != 0)
 						break;
-					lp = SH_LIST_FIRST(
-					    &sh_locker->heldby, __db_lock);
-				} else
-					lp = SH_LIST_NEXT(lp,
-					    locker_links, __db_lock);
+					continue;
+				}
+				if (objlist != NULL) {
+					DB_ASSERT((char *)np <
+					     (char *)objlist->data +
+					     objlist->size);
+					np->data = SH_DBT_PTR(&sh_obj->lockobj);
+					np->size = sh_obj->lockobj.size;
+					np++;
+				}
 			}
+			if (ret != 0)
+				goto up_done;
+
+			if (objlist != NULL)
+				if ((ret = __lock_fix_list(dbenv,
+				     objlist, sh_locker->nwrites)) != 0)
+					goto up_done;
 			switch (list[i].op) {
 			case DB_LOCK_UPGRADE_WRITE:
 				if (upgrade != 1)
@@ -354,25 +235,21 @@ __lock_vec(dbenv, locker, flags, list, nlist, elistp)
 				    lp != NULL;
 				    lp = SH_LIST_NEXT(lp,
 					    locker_links, __db_lock)) {
-					if (ret != 0)
-						break;
+					if (lp->mode != DB_LOCK_WWRITE)
+						continue;
 					lock.off = R_OFFSET(&lt->reginfo, lp);
 					lock.gen = lp->gen;
 					F_SET(sh_locker, DB_LOCKER_INABORT);
-					ret = __lock_get_internal(lt,
-					    locker, DB_LOCK_UPGRADE,
-					    NULL, DB_LOCK_WRITE, 0, &lock);
+					if ((ret = __lock_get_internal(lt,
+					    locker, flags | DB_LOCK_UPGRADE,
+					    NULL, DB_LOCK_WRITE, 0, &lock)) !=0)
+						break;
 				}
 			up_done:
-				/* FALL THROUGH */
+				/* FALLTHROUGH */
 			case DB_LOCK_PUT_READ:
-				F_CLR(sh_locker, DB_LOCKER_DELETED);
-				break;
-
 			case DB_LOCK_PUT_ALL:
-				if (ret == 0)
-					ret = __lock_checklocker(lt,
-					    NULL, locker, DB_LOCK_IGNOREDEL);
+				F_CLR(sh_locker, DB_LOCKER_DELETED);
 				break;
 			default:
 				break;
@@ -417,9 +294,8 @@ __lock_vec(dbenv, locker, flags, list, nlist, elistp)
 			break;
 
 		case DB_LOCK_TIMEOUT:
-			ret = __lock_set_timeout(dbenv,
+			ret = __lock_set_timeout_internal(dbenv,
 			    locker, 0, DB_SET_TXN_NOW);
-			region->need_dd = 1;
 			break;
 
 		case DB_LOCK_TRADE:
@@ -439,7 +315,7 @@ __lock_vec(dbenv, locker, flags, list, nlist, elistp)
 			 */
 			ret = __lock_trade(dbenv, &list[i].lock, locker);
 			break;
-#ifdef DEBUG
+#if defined(DEBUG) && defined(HAVE_STATISTICS)
 		case DB_LOCK_DUMP:
 			/* Find the locker. */
 			LOCKER_LOCK(lt, region, locker, ndx);
@@ -452,7 +328,7 @@ __lock_vec(dbenv, locker, flags, list, nlist, elistp)
 			for (lp = SH_LIST_FIRST(&sh_locker->heldby, __db_lock);
 			    lp != NULL;
 			    lp = SH_LIST_NEXT(lp, locker_links, __db_lock)) {
-				__lock_printlock(lt, lp, 1);
+				__lock_printlock(lt, NULL, lp, 1);
 			}
 			break;
 #endif
@@ -463,12 +339,13 @@ __lock_vec(dbenv, locker, flags, list, nlist, elistp)
 			break;
 		}
 
-	if (ret == 0 && region->need_dd && region->detect != DB_LOCK_NORUN)
+	if (ret == 0 && region->detect != DB_LOCK_NORUN &&
+	     (region->need_dd || LOCK_TIME_ISVALID(&region->next_timeout)))
 		run_dd = 1;
 	UNLOCKREGION(dbenv, (DB_LOCKTAB *)dbenv->lk_handle);
 
 	if (run_dd)
-		(void)dbenv->lock_detect(dbenv, 0, region->detect, &did_abort);
+		(void)__lock_detect(dbenv, region->detect, &did_abort);
 
 	if (ret != 0 && elistp != NULL)
 		*elistp = &list[i - 1];
@@ -477,13 +354,43 @@ __lock_vec(dbenv, locker, flags, list, nlist, elistp)
 }
 
 /*
- * Lock acquisition routines.  There are two library interfaces:
+ * __lock_get_pp --
+ *	DB_ENV->lock_get pre/post processing.
  *
+ * PUBLIC: int __lock_get_pp __P((DB_ENV *,
+ * PUBLIC:     u_int32_t, u_int32_t, const DBT *, db_lockmode_t, DB_LOCK *));
+ */
+int
+__lock_get_pp(dbenv, locker, flags, obj, lock_mode, lock)
+	DB_ENV *dbenv;
+	u_int32_t locker, flags;
+	const DBT *obj;
+	db_lockmode_t lock_mode;
+	DB_LOCK *lock;
+{
+	int rep_check, ret;
+
+	PANIC_CHECK(dbenv);
+	ENV_REQUIRES_CONFIG(dbenv,
+	    dbenv->lk_handle, "DB_ENV->lock_get", DB_INIT_LOCK);
+
+	/* Validate arguments. */
+	if ((ret = __db_fchk(dbenv, "DB_ENV->lock_get", flags,
+	    DB_LOCK_NOWAIT | DB_LOCK_UPGRADE | DB_LOCK_SWITCH)) != 0)
+		return (ret);
+
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __lock_get(dbenv, locker, flags, obj, lock_mode, lock);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
+/*
  * __lock_get --
- *	original lock get interface that takes a locker id.
- *
- * All the work for lock_get (and for the GET option of lock_vec) is done
- * inside of lock_get_internal.
+ *	DB_ENV->lock_get.
  *
  * PUBLIC: int __lock_get __P((DB_ENV *,
  * PUBLIC:     u_int32_t, u_int32_t, const DBT *, db_lockmode_t, DB_LOCK *));
@@ -498,20 +405,11 @@ __lock_get(dbenv, locker, flags, obj, lock_mode, lock)
 {
 	int ret;
 
-	PANIC_CHECK(dbenv);
-	ENV_REQUIRES_CONFIG(dbenv,
-	    dbenv->lk_handle, "DB_ENV->lock_get", DB_INIT_LOCK);
-
 	if (IS_RECOVERING(dbenv)) {
 		LOCK_INIT(*lock);
 		return (0);
 	}
 
-	/* Validate arguments. */
-	if ((ret = __db_fchk(dbenv, "DB_ENV->lock_get", flags,
-	    DB_LOCK_NOWAIT | DB_LOCK_UPGRADE | DB_LOCK_SWITCH)) != 0)
-		return (ret);
-
 	LOCKREGION(dbenv, (DB_LOCKTAB *)dbenv->lk_handle);
 	ret = __lock_get_internal(dbenv->lk_handle,
 	    locker, flags, obj, lock_mode, 0, lock);
@@ -519,7 +417,15 @@ __lock_get(dbenv, locker, flags, obj, lock_mode, lock)
 	return (ret);
 }
 
-static int
+/*
+ * __lock_get_internal --
+ *	All the work for lock_get (and for the GET option of lock_vec) is done
+ *	inside of lock_get_internal.
+ *
+ * PUBLIC: int  __lock_get_internal __P((DB_LOCKTAB *, u_int32_t, u_int32_t,
+ * PUBLIC:     const DBT *, db_lockmode_t, db_timeout_t, DB_LOCK *));
+ */
+int
 __lock_get_internal(lt, locker, flags, obj, lock_mode, timeout, lock)
 	DB_LOCKTAB *lt;
 	u_int32_t locker, flags;
@@ -533,46 +439,50 @@ __lock_get_internal(lt, locker, flags, obj, lock_mode, timeout, lock)
 	DB_LOCKER *sh_locker;
 	DB_LOCKOBJ *sh_obj;
 	DB_LOCKREGION *region;
-	u_int32_t locker_ndx, obj_ndx;
-	int did_abort, ihold, on_locker_list, no_dd, ret;
+	u_int32_t holder, locker_ndx, obj_ndx;
+	int did_abort, ihold, grant_dirty, no_dd, ret, t_ret;
+
+	/*
+	 * We decide what action to take based on what locks are already held
+	 * and what locks are in the wait queue.
+	 */
+	enum {
+		GRANT,		/* Grant the lock. */
+		UPGRADE,	/* Upgrade the lock. */
+		HEAD,		/* Wait at head of wait queue. */
+		SECOND,		/* Wait as the second waiter. */
+		TAIL		/* Wait at tail of the wait queue. */
+	} action;
 
 	dbenv = lt->dbenv;
 	region = lt->reginfo.primary;
-	on_locker_list = no_dd = ret = 0;
 
 	/* Check if locks have been globally turned off. */
 	if (F_ISSET(dbenv, DB_ENV_NOLOCKING))
 		return (0);
 
+	no_dd = ret = 0;
+	newl = NULL;
+
 	/*
-	 * If we are not going to reuse this lock, initialize the offset to
-	 * invalid so that if we fail it will not look like a valid lock.
+	 * If we are not going to reuse this lock, invalidate it
+	 * so that if we fail it will not look like a valid lock.
 	 */
 	if (!LF_ISSET(DB_LOCK_UPGRADE | DB_LOCK_SWITCH))
 		LOCK_INIT(*lock);
 
 	/* Check that the lock mode is valid.  */
-	if ((u_int32_t)lock_mode >= region->stat.st_nmodes) {
+	if (lock_mode >= (db_lockmode_t)region->stat.st_nmodes) {
 		__db_err(dbenv, "DB_ENV->lock_get: invalid lock mode %lu",
 		    (u_long)lock_mode);
 		return (EINVAL);
 	}
-
-	/* Allocate a new lock.  Optimize for the common case of a grant. */
 	region->stat.st_nrequests++;
-	if ((newl = SH_TAILQ_FIRST(&region->free_locks, __db_lock)) != NULL)
-		SH_TAILQ_REMOVE(&region->free_locks, newl, links, __db_lock);
-	if (newl == NULL) {
-		__db_err(dbenv, __db_lock_err, "locks");
-		return (ENOMEM);
-	}
-	if (++region->stat.st_nlocks > region->stat.st_maxnlocks)
-		region->stat.st_maxnlocks = region->stat.st_nlocks;
 
 	if (obj == NULL) {
 		DB_ASSERT(LOCK_ISSET(*lock));
-		lp = (struct __db_lock *)R_ADDR(&lt->reginfo, lock->off);
-		sh_obj = (DB_LOCKOBJ *) ((u_int8_t *)lp + lp->obj);
+		lp = R_ADDR(&lt->reginfo, lock->off);
+		sh_obj = (DB_LOCKOBJ *)((u_int8_t *)lp + lp->obj);
 	} else {
 		/* Allocate a shared memory new object. */
 		OBJECT_LOCK(lt, region, obj, lock->ndx);
@@ -585,8 +495,9 @@ __lock_get_internal(lt, locker, flags, obj, lock_mode, timeout, lock)
 	if ((ret = __lock_getlocker(lt, locker,
 	    locker_ndx, locker > DB_LOCK_MAXID ? 1 : 0, &sh_locker)) != 0) {
 		/*
-		 * XXX We cannot tell if we created the object or not,
-		 * so we don't kow if we should free it or not.
+		 * XXX
+		 * We cannot tell if we created the object or not, so we don't
+		 * kow if we should free it or not.
 		 */
 		goto err;
 	}
@@ -598,35 +509,45 @@ __lock_get_internal(lt, locker, flags, obj, lock_mode, timeout, lock)
 	}
 
 	/*
-	 * 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.  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 be granted).  The
-	 * downside of this is that a waiting reader can prevent an upgrade
-	 * from reader to writer, which is not uncommon.
+	 * Figure out if we can grant this lock or if it should wait.
+	 * By default, we can grant the new lock if it does not conflict with
+	 * anyone on the holders 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 be granted).  The downside of this is that
+	 * a waiting reader can prevent an upgrade from reader to writer,
+	 * which is not uncommon.
 	 *
-	 * There is one exception to the no-conflict rule.  If a lock is held
-	 * by the requesting locker AND the new lock does not conflict with
-	 * any other holders, then we grant the lock.  The most common place
-	 * this happens is when the holder has a WRITE lock and a READ lock
-	 * request comes in for the same locker.  If we do not grant the read
-	 * lock, then we guarantee deadlock.
+	 * There are two exceptions to the no-conflict rule.  First, if
+	 * a lock is held by the requesting locker AND the new lock does
+	 * not conflict with any other holders, then we grant the lock.
+	 * The most common place this happens is when the holder has a
+	 * WRITE lock and a READ lock request comes in for the same locker.
+	 * If we do not grant the read lock, then we guarantee deadlock.
+	 * Second, dirty readers are granted if at all possible while
+	 * avoiding starvation, see below.
 	 *
 	 * In case of conflict, we put the new lock on the end of the waiters
-	 * list, unless we are upgrading in which case the locker goes on the
-	 * front of the list.
+	 * list, unless we are upgrading or this is a dirty reader in which
+	 * case the locker goes at or near the front of the list.
 	 */
 	ihold = 0;
-	lp = NULL;
-	if (LF_ISSET(DB_LOCK_SWITCH))
-		goto put_lock;
-
+	grant_dirty = 0;
+	holder = 0;
 	wwrite = NULL;
-	for (lp = SH_TAILQ_FIRST(&sh_obj->holders, __db_lock);
-	    lp != NULL;
-	    lp = SH_TAILQ_NEXT(lp, links, __db_lock)) {
+
+	/*
+	 * SWITCH is a special case, used by the queue access method
+	 * when we want to get an entry which is past the end of the queue.
+	 * We have a DB_READ_LOCK and need to switch it to DB_LOCK_WAIT and
+	 * join the waiters queue.  This must be done as a single operation
+	 * so that another locker cannot get in and fail to wake us up.
+	 */
+	if (LF_ISSET(DB_LOCK_SWITCH))
+		lp = NULL;
+	else
+		lp = SH_TAILQ_FIRST(&sh_obj->holders, __db_lock);
+	for (; lp != NULL; lp = SH_TAILQ_NEXT(lp, links, __db_lock)) {
 		if (locker == lp->holder) {
 			if (lp->mode == lock_mode &&
 			    lp->status == DB_LSTAT_HELD) {
@@ -635,16 +556,15 @@ __lock_get_internal(lt, locker, flags, obj, lock_mode, timeout, lock)
 
 				/*
 				 * Lock is held, so we can increment the
-				 * reference count and return this lock.
-				 * We do not count reference increments
-				 * towards the locks held by the locker.
+				 * reference count and return this lock
+				 * to the caller.  We do not count reference
+				 * increments towards the locks held by
+				 * the locker.
 				 */
 				lp->refcount++;
 				lock->off = R_OFFSET(&lt->reginfo, lp);
 				lock->gen = lp->gen;
 				lock->mode = lp->mode;
-
-				ret = 0;
 				goto done;
 			} else {
 				ihold = 1;
@@ -656,106 +576,188 @@ __lock_get_internal(lt, locker, flags, obj, lock_mode, timeout, lock)
 			ihold = 1;
 		else if (CONFLICTS(lt, region, lp->mode, lock_mode))
 			break;
+		else if (lp->mode == DB_LOCK_READ ||
+		     lp->mode == DB_LOCK_WWRITE) {
+			grant_dirty = 1;
+			holder = lp->holder;
+		}
 	}
 
+	/* If we want a write lock and we have a was write, upgrade. */
+	if (wwrite != NULL)
+		LF_SET(DB_LOCK_UPGRADE);
+
 	/*
-	 * If we are looking to upgrade a WWRITE to a WRITE lock
-	 * and there were no conflicting locks then we can just
-	 * upgrade this lock to the one we want.
+	 * If there are conflicting holders we will have to wait.  An upgrade
+	 * or dirty reader goes to the head of the queue, everyone else to the
+	 * back.
 	 */
-	if (wwrite != NULL && lp == NULL) {
-		lp = wwrite;
-		lp->mode = lock_mode;
-		lp->refcount++;
-		lock->off = R_OFFSET(&lt->reginfo, lp);
-		lock->gen = lp->gen;
-		lock->mode = lp->mode;
-
-		ret = 0;
-		goto done;
+	if (lp != NULL) {
+		if (LF_ISSET(DB_LOCK_UPGRADE) || lock_mode == DB_LOCK_DIRTY)
+			action = HEAD;
+		else
+			action = TAIL;
+	} else {
+		if (LF_ISSET(DB_LOCK_SWITCH))
+			action = TAIL;
+		else if (LF_ISSET(DB_LOCK_UPGRADE))
+			action = UPGRADE;
+		else  if (ihold)
+			action = GRANT;
+		else {
+			/*
+			 * Look for conflicting waiters.
+			 */
+			for (lp = SH_TAILQ_FIRST(&sh_obj->waiters, __db_lock);
+			    lp != NULL;
+			    lp = SH_TAILQ_NEXT(lp, links, __db_lock)) {
+				if (CONFLICTS(lt, region, lp->mode,
+				     lock_mode) && locker != lp->holder)
+					break;
+			}
+			/*
+			 * If there are no conflicting holders or waiters,
+			 * then we grant. Normally when we wait, we
+			 * wait at the end (TAIL).  However, the goal of
+			 * DIRTY_READ locks to allow forward progress in the
+			 * face of updating transactions, so we try to allow
+			 * all DIRTY_READ requests to proceed as rapidly
+			 * as possible, so long as we can prevent starvation.
+			 *
+			 * When determining how to queue a DIRTY_READ
+			 * request:
+			 *
+			 *	1. If there is a waiting upgrading writer,
+			 *	   then we enqueue the dirty reader BEHIND it
+			 *	   (second in the queue).
+			 *	2. Else, if the current holders are either
+			 *	   READ or WWRITE, we grant
+			 *	3. Else queue SECOND i.e., behind the first
+			 *	   waiter.
+			 *
+			 * The end result is that dirty_readers get to run
+			 * so long as other lockers are blocked.  Once
+			 * there is a locker which is only waiting on
+			 * dirty readers then they queue up behind that
+			 * locker so that it gets to run.  In general
+			 * this locker will be a WRITE which will shortly
+			 * get downgraded to a WWRITE, permitting the
+			 * DIRTY locks to be granted.
+			 */
+			if (lp == NULL)
+				action = GRANT;
+			else if (lock_mode == DB_LOCK_DIRTY && grant_dirty) {
+				/*
+				 * An upgrade will be at the head of the
+				 * queue.
+				 */
+				lp = SH_TAILQ_FIRST(
+				     &sh_obj->waiters, __db_lock);
+				if (lp->mode == DB_LOCK_WRITE &&
+				     lp->holder == holder)
+					action = SECOND;
+				else
+					action = GRANT;
+			} else if (lock_mode == DB_LOCK_DIRTY)
+				action = SECOND;
+			else
+				action = TAIL;
+		}
 	}
 
-	/*
-	 * Make the new lock point to the new object, initialize fields.
-	 *
-	 * This lock is not linked in anywhere, so we can muck with it
-	 * without holding any mutexes.
-	 */
-put_lock:
-	newl->holder = locker;
-	newl->refcount = 1;
-	newl->mode = lock_mode;
-	newl->obj = SH_PTR_TO_OFF(newl, sh_obj);
-	newl->status = DB_LSTAT_HELD;
+	switch (action) {
+	case HEAD:
+	case TAIL:
+	case SECOND:
+	case GRANT:
+		/* Allocate a new lock. */
+		if ((newl =
+		    SH_TAILQ_FIRST(&region->free_locks, __db_lock)) == NULL)
+			return (__lock_nomem(dbenv, "locks"));
+		SH_TAILQ_REMOVE(&region->free_locks, newl, links, __db_lock);
 
-	/*
-	 * If we are upgrading, then there are two scenarios.  Either
-	 * we had no conflicts, so we can do the upgrade.  Or, there
-	 * is a conflict and we should wait at the HEAD of the waiters
-	 * list.
-	 */
-	if (LF_ISSET(DB_LOCK_UPGRADE)) {
-		if (lp == NULL)
-			goto upgrade;
+		/* Update new lock statistics. */
+		if (++region->stat.st_nlocks > region->stat.st_maxnlocks)
+			region->stat.st_maxnlocks = region->stat.st_nlocks;
 
+		newl->holder = locker;
+		newl->refcount = 1;
+		newl->mode = lock_mode;
+		newl->obj = (roff_t)SH_PTR_TO_OFF(newl, sh_obj);
 		/*
-		 * There was a conflict, wait.  If this is the first waiter,
-		 * add the object to the deadlock detector's list.
+		 * Now, insert the lock onto its locker's list.
+		 * If the locker does not currently hold any locks,
+		 * there's no reason to run a deadlock
+		 * detector, save that information.
 		 */
-		if (SH_TAILQ_FIRST(&sh_obj->waiters, __db_lock) == NULL)
-			SH_TAILQ_INSERT_HEAD(&region->dd_objs,
-			    sh_obj, dd_links, __db_lockobj);
-
-		SH_TAILQ_INSERT_HEAD(&sh_obj->waiters, newl, links, __db_lock);
-		goto llist;
+		no_dd = sh_locker->master_locker == INVALID_ROFF &&
+		    SH_LIST_FIRST(
+		    &sh_locker->child_locker, __db_locker) == NULL &&
+		    SH_LIST_FIRST(&sh_locker->heldby, __db_lock) == NULL;
+
+		SH_LIST_INSERT_HEAD(
+		    &sh_locker->heldby, newl, locker_links, __db_lock);
+		break;
+
+	case UPGRADE:
+upgrade:	if (wwrite != NULL) {
+			lp = wwrite;
+			lp->refcount++;
+			lock->off = R_OFFSET(&lt->reginfo, lp);
+			lock->gen = lp->gen;
+			lock->mode = lock_mode;
+		}
+		else
+			lp = R_ADDR(&lt->reginfo, lock->off);
+		if (IS_WRITELOCK(lock_mode) && !IS_WRITELOCK(lp->mode))
+			sh_locker->nwrites++;
+		lp->mode = lock_mode;
+		goto done;
 	}
 
-	if (lp == NULL && !ihold)
-		for (lp = SH_TAILQ_FIRST(&sh_obj->waiters, __db_lock);
-		    lp != NULL;
-		    lp = SH_TAILQ_NEXT(lp, links, __db_lock)) {
-			if (CONFLICTS(lt, region, lp->mode, lock_mode) &&
-			    locker != lp->holder)
-				break;
-		}
-	if (!LF_ISSET(DB_LOCK_SWITCH) && lp == NULL)
+	switch (action) {
+	case UPGRADE:
+		DB_ASSERT(0);
+		break;
+	case GRANT:
+		newl->status = DB_LSTAT_HELD;
 		SH_TAILQ_INSERT_TAIL(&sh_obj->holders, newl, links);
-	else if (!LF_ISSET(DB_LOCK_NOWAIT)) {
-		/*
-		 * If this is the first waiter, add the object to the
-		 * deadlock detector's list.
-		 */
-		if (SH_TAILQ_FIRST(&sh_obj->waiters, __db_lock) == NULL)
+		break;
+	case HEAD:
+	case TAIL:
+	case SECOND:
+		if (LF_ISSET(DB_LOCK_NOWAIT)) {
+			ret = DB_LOCK_NOTGRANTED;
+			region->stat.st_nnowaits++;
+			goto err;
+		}
+		if ((lp = SH_TAILQ_FIRST(&sh_obj->waiters, __db_lock)) == NULL)
 			SH_TAILQ_INSERT_HEAD(&region->dd_objs,
-			    sh_obj, dd_links, __db_lockobj);
-		SH_TAILQ_INSERT_TAIL(&sh_obj->waiters, newl, links);
-	} else {
-		ret = DB_LOCK_NOTGRANTED;
-		if (SH_LIST_FIRST(&sh_locker->heldby, __db_lock) == NULL &&
-		    LF_ISSET(DB_LOCK_FREE_LOCKER))
-			__lock_freelocker(lt, region, sh_locker, locker_ndx);
-		region->stat.st_nnowaits++;
-		goto err;
-	}
-
-llist:
-	/*
-	 * Now, insert the lock onto its locker's list.  If the locker does
-	 * not currently hold any locks, there's no reason to run a deadlock
-	 * detector, save that information.
-	 */
-	on_locker_list = 1;
-	no_dd = sh_locker->master_locker == INVALID_ROFF &&
-	    SH_LIST_FIRST(&sh_locker->child_locker, __db_locker) == NULL &&
-	    SH_LIST_FIRST(&sh_locker->heldby, __db_lock) == NULL;
-
-	SH_LIST_INSERT_HEAD(&sh_locker->heldby, newl, locker_links, __db_lock);
+				    sh_obj, dd_links, __db_lockobj);
+		switch (action) {
+		case HEAD:
+			SH_TAILQ_INSERT_HEAD(
+			     &sh_obj->waiters, newl, links, __db_lock);
+			break;
+		case SECOND:
+			SH_TAILQ_INSERT_AFTER(
+			     &sh_obj->waiters, lp, newl, links, __db_lock);
+			break;
+		case TAIL:
+			SH_TAILQ_INSERT_TAIL(&sh_obj->waiters, newl, links);
+			break;
+		default:
+			DB_ASSERT(0);
+		}
 
-	if (LF_ISSET(DB_LOCK_SWITCH) || lp != NULL) {
+		/* If we are switching drop the lock we had. */
 		if (LF_ISSET(DB_LOCK_SWITCH) &&
 		    (ret = __lock_put_nolock(dbenv,
-		    lock, &ihold, DB_LOCK_NOWAITERS)) != 0)
+		    lock, &ihold, DB_LOCK_NOWAITERS)) != 0) {
+			__lock_remove_waiter(lt, sh_obj, newl, DB_LSTAT_FREE);
 			goto err;
+		}
+
 		/*
 		 * This is really a blocker for the thread.  It should be
 		 * initialized locked, so that when we try to acquire it, we
@@ -773,25 +775,10 @@ llist:
 		 */
 		if (__lock_expired(dbenv,
 		    &sh_locker->lk_expire, &sh_locker->tx_expire)) {
-			newl->status = DB_LSTAT_ABORTED;
-			region->stat.st_ndeadlocks++;
-			region->stat.st_ntxntimeouts++;
-
-			/*
-			 * Remove the lock from the wait queue and if
-			 * this was the only lock on the wait queue remove
-			 * this object from the deadlock detector object
-			 * list.
-			 */
-			SH_LIST_REMOVE(newl, locker_links, __db_lock);
-			SH_TAILQ_REMOVE(
-			    &sh_obj->waiters, newl, links, __db_lock);
-			if (SH_TAILQ_FIRST(&sh_obj->waiters, __db_lock) == NULL)
-				SH_TAILQ_REMOVE(&region->dd_objs,
-				    sh_obj, dd_links, __db_lockobj);
+			newl->status = DB_LSTAT_EXPIRED;
+			sh_locker->lk_expire = sh_locker->tx_expire;
 
-			/* Clear the timeout, we are done. */
-			LOCK_SET_TIME_INVALID(&sh_locker->tx_expire);
+			/* We are done. */
 			goto expired;
 		}
 
@@ -816,6 +803,11 @@ llist:
 			(timeout == 0 || __lock_expired(dbenv,
 			    &sh_locker->lk_expire, &sh_locker->tx_expire)))
 				sh_locker->lk_expire = sh_locker->tx_expire;
+		if (LOCK_TIME_ISVALID(&sh_locker->lk_expire) &&
+		    (!LOCK_TIME_ISVALID(&region->next_timeout) ||
+		    LOCK_TIME_GREATER(
+		    &region->next_timeout, &sh_locker->lk_expire)))
+			region->next_timeout = sh_locker->lk_expire;
 		UNLOCKREGION(dbenv, (DB_LOCKTAB *)dbenv->lk_handle);
 
 		/*
@@ -823,62 +815,61 @@ llist:
 		 * detector should be run.
 		 */
 		if (region->detect != DB_LOCK_NORUN && !no_dd)
-			(void)dbenv->lock_detect(
-			    dbenv, 0, region->detect, &did_abort);
+			(void)__lock_detect(dbenv, region->detect, &did_abort);
 
 		MUTEX_LOCK(dbenv, &newl->mutex);
 		LOCKREGION(dbenv, (DB_LOCKTAB *)dbenv->lk_handle);
 
-expired:	/* Turn off lock timeout. */
-		LOCK_SET_TIME_INVALID(&sh_locker->lk_expire);
+		/* Turn off lock timeout. */
+		if (newl->status != DB_LSTAT_EXPIRED)
+			LOCK_SET_TIME_INVALID(&sh_locker->lk_expire);
 
-		if (newl->status != DB_LSTAT_PENDING) {
-			(void)__lock_checklocker(lt, newl, newl->holder, 0);
-			switch (newl->status) {
-				case DB_LSTAT_ABORTED:
-					on_locker_list = 0;
-					ret = DB_LOCK_DEADLOCK;
-					break;
-				case DB_LSTAT_NOTEXIST:
-					ret = DB_LOCK_NOTEXIST;
-					break;
-				case DB_LSTAT_EXPIRED:
-					SHOBJECT_LOCK(lt,
-					    region, sh_obj, obj_ndx);
-					if ((ret = __lock_put_internal(
-					    lt, newl, obj_ndx, 0) != 0))
-						goto err;
-					if (LOCK_TIME_EQUAL(
-					    &sh_locker->lk_expire,
-					    &sh_locker->tx_expire)) {
-						region->stat.st_ndeadlocks++;
-						region->stat.st_ntxntimeouts++;
-						return (DB_LOCK_DEADLOCK);
-					} else {
-						region->stat.st_nlocktimeouts++;
-						return (DB_LOCK_NOTGRANTED);
-					}
-				default:
-					ret = EINVAL;
-					break;
-			}
+		switch (newl->status) {
+		case DB_LSTAT_ABORTED:
+			ret = DB_LOCK_DEADLOCK;
 			goto err;
-		} else if (LF_ISSET(DB_LOCK_UPGRADE)) {
-			/*
-			 * The lock that was just granted got put on the
-			 * holders list.  Since we're upgrading some other
-			 * lock, we've got to remove it here.
-			 */
-			SH_TAILQ_REMOVE(
-			    &sh_obj->holders, newl, links, __db_lock);
-			/*
-			 * Ensure that the object is not believed to be on
-			 * the object's lists, if we're traversing by locker.
-			 */
-			newl->links.stqe_prev = -1;
-			goto upgrade;
-		} else
-			newl->status = DB_LSTAT_HELD;
+		case DB_LSTAT_NOTEXIST:
+			ret = DB_LOCK_NOTEXIST;
+			goto err;
+		case DB_LSTAT_EXPIRED:
+expired:		SHOBJECT_LOCK(lt, region, sh_obj, obj_ndx);
+			if ((ret = __lock_put_internal(lt, newl,
+			    obj_ndx, DB_LOCK_UNLINK | DB_LOCK_FREE)) != 0)
+				break;
+			if (LOCK_TIME_EQUAL(
+			    &sh_locker->lk_expire, &sh_locker->tx_expire))
+				region->stat.st_ntxntimeouts++;
+			else
+				region->stat.st_nlocktimeouts++;
+			return (DB_LOCK_NOTGRANTED);
+		case DB_LSTAT_PENDING:
+			if (LF_ISSET(DB_LOCK_UPGRADE)) {
+				/*
+				 * The lock just granted got put on the holders
+				 * list.  Since we're upgrading some other lock,
+				 * we've got to remove it here.
+				 */
+				SH_TAILQ_REMOVE(
+				    &sh_obj->holders, newl, links, __db_lock);
+				/*
+				 * Ensure the object is not believed to be on
+				 * the object's lists, if we're traversing by
+				 * locker.
+				 */
+				newl->links.stqe_prev = -1;
+				goto upgrade;
+			} else
+				newl->status = DB_LSTAT_HELD;
+			break;
+		case DB_LSTAT_FREE:
+		case DB_LSTAT_HELD:
+		case DB_LSTAT_WAITING:
+		default:
+			__db_err(dbenv,
+			    "Unexpected lock status: %d", (int)newl->status);
+			ret = __db_panic(dbenv, EINVAL);
+			goto err;
+		}
 	}
 
 	lock->off = R_OFFSET(&lt->reginfo, newl);
@@ -890,55 +881,64 @@ expired:	/* Turn off lock timeout. */
 
 	return (0);
 
-upgrade:/*
-	 * This was an upgrade, so return the new lock to the free list and
-	 * upgrade the mode of the original lock.
-	 */
-	lp = (struct __db_lock *)R_ADDR(&lt->reginfo, lock->off);
-	if (IS_WRITELOCK(lock_mode) && !IS_WRITELOCK(lp->mode))
-		sh_locker->nwrites++;
-	lp->mode = lock_mode;
-
+done:
 	ret = 0;
-	/* FALLTHROUGH */
-
-done:
-err:	newl->status = DB_LSTAT_FREE;
-	region->stat.st_nlocks--;
-	if (on_locker_list) {
-		SH_LIST_REMOVE(newl, locker_links, __db_lock);
-	}
-	SH_TAILQ_INSERT_HEAD(&region->free_locks, newl, links, __db_lock);
+err:
+	if (newl != NULL &&
+	     (t_ret = __lock_freelock(lt, newl, locker,
+	     DB_LOCK_FREE | DB_LOCK_UNLINK)) != 0 && ret == 0)
+		ret = t_ret;
 	return (ret);
 }
 
 /*
- * Lock release routines.
- *
- * The user callable one is lock_put and the three we use internally are
- * __lock_put_nolock, __lock_put_internal and __lock_downgrade.
+ * __lock_put_pp --
+ *	DB_ENV->lock_put pre/post processing.
  *
- * PUBLIC: int  __lock_put __P((DB_ENV *, DB_LOCK *));
+ * PUBLIC: int  __lock_put_pp __P((DB_ENV *, DB_LOCK *));
  */
 int
-__lock_put(dbenv, lock)
+__lock_put_pp(dbenv, lock)
 	DB_ENV *dbenv;
 	DB_LOCK *lock;
 {
-	DB_LOCKTAB *lt;
-	int ret, run_dd;
+	int rep_check, ret;
 
 	PANIC_CHECK(dbenv);
 	ENV_REQUIRES_CONFIG(dbenv,
 	    dbenv->lk_handle, "DB_LOCK->lock_put", DB_INIT_LOCK);
 
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __lock_put(dbenv, lock, 0);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
+/*
+ * __lock_put --
+ *
+ * PUBLIC: int  __lock_put __P((DB_ENV *, DB_LOCK *, u_int32_t));
+ *  Internal lock_put interface.
+ */
+int
+__lock_put(dbenv, lock, flags)
+	DB_ENV *dbenv;
+	DB_LOCK *lock;
+	u_int32_t flags;
+{
+	DB_LOCKTAB *lt;
+	int ret, run_dd;
+
 	if (IS_RECOVERING(dbenv))
 		return (0);
 
 	lt = dbenv->lk_handle;
 
 	LOCKREGION(dbenv, lt);
-	ret = __lock_put_nolock(dbenv, lock, &run_dd, 0);
+	ret = __lock_put_nolock(dbenv, lock, &run_dd, flags);
 	UNLOCKREGION(dbenv, lt);
 
 	/*
@@ -948,7 +948,7 @@ __lock_put(dbenv, lock)
 	 * actually abort anything.
 	 */
 	if (ret == 0 && run_dd)
-		(void)dbenv->lock_detect(dbenv, 0,
+		(void)__lock_detect(dbenv,
 		    ((DB_LOCKREGION *)lt->reginfo.primary)->detect, NULL);
 	return (ret);
 }
@@ -972,18 +972,27 @@ __lock_put_nolock(dbenv, lock, runp, flags)
 	lt = dbenv->lk_handle;
 	region = lt->reginfo.primary;
 
-	lockp = (struct __db_lock *)R_ADDR(&lt->reginfo, lock->off);
-	LOCK_INIT(*lock);
+	lockp = R_ADDR(&lt->reginfo, lock->off);
 	if (lock->gen != lockp->gen) {
 		__db_err(dbenv, __db_lock_invalid, "DB_LOCK->lock_put");
+		LOCK_INIT(*lock);
 		return (EINVAL);
 	}
 
-	ret = __lock_put_internal(lt,
-	    lockp, lock->ndx, flags | DB_LOCK_UNLINK | DB_LOCK_FREE);
+	if (LF_ISSET(DB_LOCK_DOWNGRADE) &&
+	     lock->mode == DB_LOCK_WRITE && lockp->refcount > 1) {
+		ret = __lock_downgrade(dbenv,
+		    lock, DB_LOCK_WWRITE, DB_LOCK_NOREGION);
+		if (ret == 0)
+			lockp->refcount--;
+	} else
+		ret = __lock_put_internal(lt,
+		    lockp, lock->ndx, flags | DB_LOCK_UNLINK | DB_LOCK_FREE);
+	LOCK_INIT(*lock);
 
 	*runp = 0;
-	if (ret == 0 && region->need_dd && region->detect != DB_LOCK_NORUN)
+	if (ret == 0 && region->detect != DB_LOCK_NORUN &&
+	     (region->need_dd || LOCK_TIME_ISVALID(&region->next_timeout)))
 		*runp = 1;
 
 	return (ret);
@@ -991,10 +1000,12 @@ __lock_put_nolock(dbenv, lock, runp, flags)
 
 /*
  * __lock_downgrade --
- *	Used to downgrade locks.  Currently this is used in two places,
- * 1) by the concurrent access product to downgrade write locks
- * back to iwrite locks and 2) to downgrade write-handle locks to read-handle
- * locks at the end of an open/create.
+ *
+ * Used to downgrade locks.  Currently this is used in three places: 1) by the
+ * Concurrent Data Store product to downgrade write locks back to iwrite locks
+ * and 2) to downgrade write-handle locks to read-handle locks at the end of
+ * an open/create. 3) To downgrade write locks to was_write to support dirty
+ * reads.
  *
  * PUBLIC: int __lock_downgrade __P((DB_ENV *,
  * PUBLIC:     DB_LOCK *, db_lockmode_t, u_int32_t));
@@ -1014,8 +1025,6 @@ __lock_downgrade(dbenv, lock, new_mode, flags)
 	u_int32_t indx;
 	int ret;
 
-	COMPQUIET(flags, 0);
-
 	PANIC_CHECK(dbenv);
 	ret = 0;
 
@@ -1026,9 +1035,10 @@ __lock_downgrade(dbenv, lock, new_mode, flags)
 	lt = dbenv->lk_handle;
 	region = lt->reginfo.primary;
 
-	LOCKREGION(dbenv, lt);
+	if (!LF_ISSET(DB_LOCK_NOREGION))
+		LOCKREGION(dbenv, lt);
 
-	lockp = (struct __db_lock *)R_ADDR(&lt->reginfo, lock->off);
+	lockp = R_ADDR(&lt->reginfo, lock->off);
 	if (lock->gen != lockp->gen) {
 		__db_err(dbenv, __db_lock_invalid, "lock_downgrade");
 		ret = EINVAL;
@@ -1051,12 +1061,14 @@ __lock_downgrade(dbenv, lock, new_mode, flags)
 		F_SET(sh_locker, DB_LOCKER_DIRTY);
 
 	lockp->mode = new_mode;
+	lock->mode = new_mode;
 
 	/* Get the object associated with this lock. */
 	obj = (DB_LOCKOBJ *)((u_int8_t *)lockp + lockp->obj);
 	(void)__lock_promote(lt, obj, LF_ISSET(DB_LOCK_NOWAITERS));
 
-out:	UNLOCKREGION(dbenv, lt);
+out:	if (!LF_ISSET(DB_LOCK_NOREGION))
+		UNLOCKREGION(dbenv, lt);
 
 	return (ret);
 }
@@ -1081,10 +1093,7 @@ __lock_put_internal(lt, lockp, obj_ndx, flags)
 		 * already been done; all we need to do is return it to the
 		 * free list.
 		 */
-		lockp->status = DB_LSTAT_FREE;
-		SH_TAILQ_INSERT_HEAD(
-		    &region->free_locks, lockp, links, __db_lock);
-		region->stat.st_nlocks--;
+		(void)__lock_freelock(lt, lockp, 0, DB_LOCK_FREE);
 		return (0);
 	}
 
@@ -1118,16 +1127,13 @@ __lock_put_internal(lt, lockp, obj_ndx, flags)
 		state_changed = __lock_promote(lt,
 		    sh_obj, LF_ISSET(DB_LOCK_REMOVE | DB_LOCK_NOWAITERS));
 
-	if (LF_ISSET(DB_LOCK_UNLINK))
-		ret = __lock_checklocker(lt, lockp, lockp->holder, flags);
-
 	/* Check if object should be reclaimed. */
 	if (SH_TAILQ_FIRST(&sh_obj->holders, __db_lock) == NULL &&
 	    SH_TAILQ_FIRST(&sh_obj->waiters, __db_lock) == NULL) {
 		HASHREMOVE_EL(lt->obj_tab,
 		    obj_ndx, __db_lockobj, links, sh_obj);
 		if (sh_obj->lockobj.size > sizeof(sh_obj->objdata))
-			__db_shalloc_free(lt->reginfo.addr,
+			__db_shalloc_free(&lt->reginfo,
 			    SH_DBT_PTR(&sh_obj->lockobj));
 		SH_TAILQ_INSERT_HEAD(
 		    &region->free_objs, sh_obj, links, __db_lockobj);
@@ -1136,12 +1142,8 @@ __lock_put_internal(lt, lockp, obj_ndx, flags)
 	}
 
 	/* Free lock. */
-	if (!LF_ISSET(DB_LOCK_UNLINK) && LF_ISSET(DB_LOCK_FREE)) {
-		lockp->status = DB_LSTAT_FREE;
-		SH_TAILQ_INSERT_HEAD(
-		    &region->free_locks, lockp, links, __db_lock);
-		region->stat.st_nlocks--;
-	}
+	if (LF_ISSET(DB_LOCK_UNLINK | DB_LOCK_FREE))
+		ret = __lock_freelock(lt, lockp, lockp->holder, flags);
 
 	/*
 	 * If we did not promote anyone; we need to run the deadlock
@@ -1154,18 +1156,12 @@ __lock_put_internal(lt, lockp, obj_ndx, flags)
 }
 
 /*
- * Utility functions; listed alphabetically.
- */
-
-/*
- * __lock_checklocker --
- *	If a locker has no more locks, then we can free the object.
- * Return a boolean indicating whether we freed the object or not.
+ * __lock_freelock --
+ *	Free a lock.  Unlink it from its locker if necessary.
  *
- * Must be called without the locker's lock set.
  */
 static int
-__lock_checklocker(lt, lockp, locker, flags)
+__lock_freelock(lt, lockp, locker, flags)
 	DB_LOCKTAB *lt;
 	struct __db_lock *lockp;
 	u_int32_t locker, flags;
@@ -1180,24 +1176,16 @@ __lock_checklocker(lt, lockp, locker, flags)
 	region = lt->reginfo.primary;
 	ret = 0;
 
-	LOCKER_LOCK(lt, region, locker, indx);
-
-	/* If the locker's list is NULL, free up the locker. */
-	if ((ret = __lock_getlocker(lt,
-	    locker, indx, 0, &sh_locker)) != 0 || sh_locker == NULL) {
-		if (ret == 0)
-			ret = EINVAL;
-		__db_err(dbenv, __db_locker_invalid);
-		goto freelock;
-	}
-
-	if (F_ISSET(sh_locker, DB_LOCKER_DELETED)) {
-		LF_CLR(DB_LOCK_FREE);
-		if (!LF_ISSET(DB_LOCK_IGNOREDEL))
-			goto freelock;
-	}
-
 	if (LF_ISSET(DB_LOCK_UNLINK)) {
+		LOCKER_LOCK(lt, region, locker, indx);
+		if ((ret = __lock_getlocker(lt,
+		    locker, indx, 0, &sh_locker)) != 0 || sh_locker == NULL) {
+			if (ret == 0)
+				ret = EINVAL;
+			__db_err(dbenv, __db_locker_invalid);
+			return (ret);
+		}
+
 		SH_LIST_REMOVE(lockp, locker_links, __db_lock);
 		if (lockp->status == DB_LSTAT_HELD) {
 			sh_locker->nlocks--;
@@ -1206,11 +1194,6 @@ __lock_checklocker(lt, lockp, locker, flags)
 		}
 	}
 
-	if (SH_LIST_FIRST(&sh_locker->heldby, __db_lock) == NULL &&
-	    LF_ISSET(DB_LOCK_FREE_LOCKER))
-		__lock_freelocker( lt, region, sh_locker, indx);
-
-freelock:
 	if (LF_ISSET(DB_LOCK_FREE)) {
 		lockp->status = DB_LSTAT_FREE;
 		SH_TAILQ_INSERT_HEAD(
@@ -1221,322 +1204,6 @@ freelock:
 	return (ret);
 }
 
-/*
- * __lock_addfamilylocker
- *	Put a locker entry in for a child transaction.
- *
- * PUBLIC: int __lock_addfamilylocker __P((DB_ENV *, u_int32_t, u_int32_t));
- */
-int
-__lock_addfamilylocker(dbenv, pid, id)
-	DB_ENV *dbenv;
-	u_int32_t pid, id;
-{
-	DB_LOCKER *lockerp, *mlockerp;
-	DB_LOCKREGION *region;
-	DB_LOCKTAB *lt;
-	u_int32_t ndx;
-	int ret;
-
-	lt = dbenv->lk_handle;
-	region = lt->reginfo.primary;
-	LOCKREGION(dbenv, lt);
-
-	/* get/create the  parent locker info */
-	LOCKER_LOCK(lt, region, pid, ndx);
-	if ((ret = __lock_getlocker(dbenv->lk_handle,
-	    pid, ndx, 1, &mlockerp)) != 0)
-		goto err;
-
-	/*
-	 * We assume that only one thread can manipulate
-	 * a single transaction family.
-	 * Therefore the master locker cannot go away while
-	 * we manipulate it, nor can another child in the
-	 * family be created at the same time.
-	 */
-	LOCKER_LOCK(lt, region, id, ndx);
-	if ((ret = __lock_getlocker(dbenv->lk_handle,
-	    id, ndx, 1, &lockerp)) != 0)
-		goto err;
-
-	/* Point to our parent. */
-	lockerp->parent_locker = R_OFFSET(&lt->reginfo, mlockerp);
-
-	/* See if this locker is the family master. */
-	if (mlockerp->master_locker == INVALID_ROFF)
-		lockerp->master_locker = R_OFFSET(&lt->reginfo, mlockerp);
-	else {
-		lockerp->master_locker = mlockerp->master_locker;
-		mlockerp = R_ADDR(&lt->reginfo, mlockerp->master_locker);
-	}
-
-	/*
-	 * Link the child at the head of the master's list.
-	 * The guess is when looking for deadlock that
-	 * the most recent child is the one thats blocked.
-	 */
-	SH_LIST_INSERT_HEAD(
-	    &mlockerp->child_locker, lockerp, child_link, __db_locker);
-
-err:
-	UNLOCKREGION(dbenv, lt);
-
-	return (ret);
-}
-
-/*
- * __lock_freefamilylocker
- *	Remove a locker from the hash table and its family.
- *
- * This must be called without the locker bucket locked.
- *
- * PUBLIC: int __lock_freefamilylocker  __P((DB_LOCKTAB *, u_int32_t));
- */
-int
-__lock_freefamilylocker(lt, locker)
-	DB_LOCKTAB *lt;
-	u_int32_t locker;
-{
-	DB_ENV *dbenv;
-	DB_LOCKER *sh_locker;
-	DB_LOCKREGION *region;
-	u_int32_t indx;
-	int ret;
-
-	dbenv = lt->dbenv;
-	region = lt->reginfo.primary;
-
-	LOCKREGION(dbenv, lt);
-	LOCKER_LOCK(lt, region, locker, indx);
-
-	if ((ret = __lock_getlocker(lt,
-	    locker, indx, 0, &sh_locker)) != 0 || sh_locker == NULL)
-		goto freelock;
-
-	if (SH_LIST_FIRST(&sh_locker->heldby, __db_lock) != NULL) {
-		ret = EINVAL;
-		__db_err(dbenv, "Freeing locker with locks");
-		goto freelock;
-	}
-
-	/* If this is part of a family, we must fix up its links. */
-	if (sh_locker->master_locker != INVALID_ROFF)
-		SH_LIST_REMOVE(sh_locker, child_link, __db_locker);
-
-	__lock_freelocker(lt, region, sh_locker, indx);
-
-freelock:
-	UNLOCKREGION(dbenv, lt);
-	return (ret);
-}
-
-/*
- * __lock_freelocker
- *	common code for deleting a locker.
- *
- * This must be called with the locker bucket locked.
- */
-static void
-__lock_freelocker(lt, region, sh_locker, indx)
-	DB_LOCKTAB *lt;
-	DB_LOCKREGION *region;
-	DB_LOCKER *sh_locker;
-	u_int32_t indx;
-
-{
-	HASHREMOVE_EL(
-	    lt->locker_tab, indx, __db_locker, links, sh_locker);
-	SH_TAILQ_INSERT_HEAD(
-	    &region->free_lockers, sh_locker, links, __db_locker);
-	SH_TAILQ_REMOVE(&region->lockers, sh_locker, ulinks, __db_locker);
-	region->stat.st_nlockers--;
-}
-
-/*
- * __lock_set_timeout
- *		-- set timeout values in shared memory.
- * This is called from the transaction system.
- * We either set the time that this tranaction expires or the
- * amount of time that a lock for this transaction is permitted
- * to wait.
- *
- * PUBLIC: int __lock_set_timeout __P(( DB_ENV *,
- * PUBLIC:      u_int32_t, db_timeout_t, u_int32_t));
- */
-int
-__lock_set_timeout(dbenv, locker, timeout, op)
-	DB_ENV *dbenv;
-	u_int32_t locker;
-	db_timeout_t timeout;
-	u_int32_t op;
-{
-	DB_LOCKER *sh_locker;
-	DB_LOCKREGION *region;
-	DB_LOCKTAB *lt;
-	u_int32_t locker_ndx;
-	int ret;
-
-	lt = dbenv->lk_handle;
-	region = lt->reginfo.primary;
-	LOCKREGION(dbenv, lt);
-
-	LOCKER_LOCK(lt, region, locker, locker_ndx);
-	ret = __lock_getlocker(lt, locker, locker_ndx, 1, &sh_locker);
-	UNLOCKREGION(dbenv, lt);
-	if (ret != 0)
-		return (ret);
-
-	if (op == DB_SET_TXN_TIMEOUT) {
-		if (timeout == 0)
-			LOCK_SET_TIME_INVALID(&sh_locker->tx_expire);
-		else
-			__lock_expires(dbenv, &sh_locker->tx_expire, timeout);
-	} else if (op == DB_SET_LOCK_TIMEOUT) {
-		sh_locker->lk_timeout = timeout;
-		F_SET(sh_locker, DB_LOCKER_TIMEOUT);
-	} else if (op == DB_SET_TXN_NOW) {
-		LOCK_SET_TIME_INVALID(&sh_locker->tx_expire);
-		__lock_expires(dbenv, &sh_locker->tx_expire, 0);
-		sh_locker->lk_expire = sh_locker->tx_expire;
-	} else
-		return (EINVAL);
-
-	return (0);
-}
-
-/*
- * __lock_inherit_timeout
- *		-- inherit timeout values from parent locker.
- * This is called from the transaction system.  This will
- * return EINVAL if the parent does not exist or did not
- * have a current txn timeout set.
- *
- * PUBLIC: int __lock_inherit_timeout __P(( DB_ENV *, u_int32_t, u_int32_t));
- */
-int
-__lock_inherit_timeout(dbenv, parent, locker)
-	DB_ENV *dbenv;
-	u_int32_t parent, locker;
-{
-	DB_LOCKER *parent_locker, *sh_locker;
-	DB_LOCKREGION *region;
-	DB_LOCKTAB *lt;
-	u_int32_t locker_ndx;
-	int ret;
-
-	lt = dbenv->lk_handle;
-	region = lt->reginfo.primary;
-	ret = 0;
-	LOCKREGION(dbenv, lt);
-
-	/* If the parent does not exist, we are done. */
-	LOCKER_LOCK(lt, region, parent, locker_ndx);
-	if ((ret = __lock_getlocker(lt,
-	    parent, locker_ndx, 0, &parent_locker)) != 0)
-		goto err;
-
-	/*
-	 * If the parent is not there yet, thats ok.  If it
-	 * does not have any timouts set, then avoid creating
-	 * the child locker at this point.
-	 */
-	if (parent_locker == NULL ||
-	    (LOCK_TIME_ISVALID(&parent_locker->tx_expire) &&
-	    !F_ISSET(parent_locker, DB_LOCKER_TIMEOUT))) {
-		ret = EINVAL;
-		goto done;
-	}
-
-	LOCKER_LOCK(lt, region, locker, locker_ndx);
-	if ((ret = __lock_getlocker(lt,
-	    locker, locker_ndx, 1, &sh_locker)) != 0)
-		goto err;
-
-	sh_locker->tx_expire = parent_locker->tx_expire;
-
-	if (F_ISSET(parent_locker, DB_LOCKER_TIMEOUT)) {
-		sh_locker->lk_timeout = parent_locker->lk_timeout;
-		F_SET(sh_locker, DB_LOCKER_TIMEOUT);
-		if (!LOCK_TIME_ISVALID(&parent_locker->tx_expire))
-			ret = EINVAL;
-	}
-
-done:
-err:
-	UNLOCKREGION(dbenv, lt);
-	return (ret);
-}
-
-/*
- * __lock_getlocker --
- *	Get a locker in the locker hash table.  The create parameter
- * indicates if the locker should be created if it doesn't exist in
- * the table.
- *
- * This must be called with the locker bucket locked.
- *
- * PUBLIC: int __lock_getlocker __P((DB_LOCKTAB *,
- * PUBLIC:     u_int32_t, u_int32_t, int, DB_LOCKER **));
- */
-int
-__lock_getlocker(lt, locker, indx, create, retp)
-	DB_LOCKTAB *lt;
-	u_int32_t locker, indx;
-	int create;
-	DB_LOCKER **retp;
-{
-	DB_ENV *dbenv;
-	DB_LOCKER *sh_locker;
-	DB_LOCKREGION *region;
-
-	dbenv = lt->dbenv;
-	region = lt->reginfo.primary;
-
-	HASHLOOKUP(lt->locker_tab,
-	    indx, __db_locker, links, locker, sh_locker, __lock_locker_cmp);
-
-	/*
-	 * If we found the locker, then we can just return it.  If
-	 * we didn't find the locker, then we need to create it.
-	 */
-	if (sh_locker == NULL && create) {
-		/* Create new locker and then insert it into hash table. */
-		if ((sh_locker = SH_TAILQ_FIRST(
-		    &region->free_lockers, __db_locker)) == NULL) {
-			__db_err(dbenv, __db_lock_err, "locker entries");
-			return (ENOMEM);
-		}
-		SH_TAILQ_REMOVE(
-		    &region->free_lockers, sh_locker, links, __db_locker);
-		if (++region->stat.st_nlockers > region->stat.st_maxnlockers)
-			region->stat.st_maxnlockers = region->stat.st_nlockers;
-
-		sh_locker->id = locker;
-		sh_locker->dd_id = 0;
-		sh_locker->master_locker = INVALID_ROFF;
-		sh_locker->parent_locker = INVALID_ROFF;
-		SH_LIST_INIT(&sh_locker->child_locker);
-		sh_locker->flags = 0;
-		SH_LIST_INIT(&sh_locker->heldby);
-		sh_locker->nlocks = 0;
-		sh_locker->nwrites = 0;
-		sh_locker->lk_timeout = 0;
-		LOCK_SET_TIME_INVALID(&sh_locker->tx_expire);
-		if (locker < TXN_MINIMUM && region->tx_timeout != 0)
-			__lock_expires(dbenv,
-			    &sh_locker->tx_expire, region->tx_timeout);
-		LOCK_SET_TIME_INVALID(&sh_locker->lk_expire);
-
-		HASHINSERT(lt->locker_tab, indx, __db_locker, links, sh_locker);
-		SH_TAILQ_INSERT_HEAD(&region->lockers,
-		    sh_locker, ulinks, __db_locker);
-	}
-
-	*retp = sh_locker;
-	return (0);
-}
-
 /*
  * __lock_getobj --
  *	Get an object in the object hash table.  The create parameter
@@ -1574,8 +1241,7 @@ __lock_getobj(lt, obj, ndx, create, retp)
 		/* Create new object and then insert it into hash table. */
 		if ((sh_obj =
 		    SH_TAILQ_FIRST(&region->free_objs, __db_lockobj)) == NULL) {
-			__db_err(lt->dbenv, __db_lock_err, "object entries");
-			ret = ENOMEM;
+			ret = __lock_nomem(lt->dbenv, "object entries");
 			goto err;
 		}
 
@@ -1585,8 +1251,8 @@ __lock_getobj(lt, obj, ndx, create, retp)
 		 */
 		if (obj->size <= sizeof(sh_obj->objdata))
 			p = sh_obj->objdata;
-		else if ((ret = __db_shalloc(
-		    lt->reginfo.addr, obj->size, 0, &p)) != 0) {
+		else if ((ret =
+		    __db_shalloc(&lt->reginfo, obj->size, 0, &p)) != 0) {
 			__db_err(dbenv, "No space for lock object storage");
 			goto err;
 		}
@@ -1601,7 +1267,8 @@ __lock_getobj(lt, obj, ndx, create, retp)
 		SH_TAILQ_INIT(&sh_obj->waiters);
 		SH_TAILQ_INIT(&sh_obj->holders);
 		sh_obj->lockobj.size = obj->size;
-		sh_obj->lockobj.off = SH_PTR_TO_OFF(&sh_obj->lockobj, p);
+		sh_obj->lockobj.off =
+		    (roff_t)SH_PTR_TO_OFF(&sh_obj->lockobj, p);
 
 		HASHINSERT(lt->obj_tab, ndx, __db_lockobj, links, sh_obj);
 	}
@@ -1615,7 +1282,7 @@ err:	return (ret);
 /*
  * __lock_is_parent --
  *	Given a locker and a transaction, return 1 if the locker is
- * an ancestor of the designcated transaction.  This is used to determine
+ * an ancestor of the designated transaction.  This is used to determine
  * if we should grant locks that appear to conflict, but don't because
  * the lock is already held by an ancestor.
  */
@@ -1629,8 +1296,7 @@ __lock_is_parent(lt, locker, sh_locker)
 
 	parent = sh_locker;
 	while (parent->parent_locker != INVALID_ROFF) {
-		parent = (DB_LOCKER *)
-		    R_ADDR(&lt->reginfo, parent->parent_locker);
+		parent = R_ADDR(&lt->reginfo, parent->parent_locker);
 		if (parent->id == locker)
 			return (1);
 	}
@@ -1638,6 +1304,162 @@ __lock_is_parent(lt, locker, sh_locker)
 	return (0);
 }
 
+/*
+ * __lock_locker_is_parent --
+ *	Determine if "locker" is an ancestor of "child".
+ * *retp == 1 if so, 0 otherwise.
+ *
+ * PUBLIC: int __lock_locker_is_parent
+ * PUBLIC:     __P((DB_ENV *, u_int32_t, u_int32_t, int *));
+ */
+int
+__lock_locker_is_parent(dbenv, locker, child, retp)
+	DB_ENV *dbenv;
+	u_int32_t locker, child;
+	int *retp;
+{
+	DB_LOCKER *sh_locker;
+	DB_LOCKREGION *region;
+	DB_LOCKTAB *lt;
+	u_int32_t locker_ndx;
+	int ret;
+
+	lt = dbenv->lk_handle;
+	region = lt->reginfo.primary;
+
+	LOCKER_LOCK(lt, region, child, locker_ndx);
+	if ((ret =
+	    __lock_getlocker(lt, child, locker_ndx, 0, &sh_locker)) != 0) {
+		__db_err(dbenv, __db_locker_invalid);
+		return (ret);
+	}
+
+	/*
+	 * The locker may not exist for this transaction, if not then it has
+	 * no parents.
+	 */
+	if (sh_locker == NULL)
+		*retp = 0;
+	else
+		*retp = __lock_is_parent(lt, locker, sh_locker);
+	return (0);
+}
+
+/*
+ * __lock_inherit_locks --
+ *	Called on child commit to merge child's locks with parent's.
+ */
+static int
+__lock_inherit_locks(lt, locker, flags)
+	DB_LOCKTAB *lt;
+	u_int32_t locker;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	DB_LOCKER *sh_locker, *sh_parent;
+	DB_LOCKOBJ *obj;
+	DB_LOCKREGION *region;
+	int ret;
+	struct __db_lock *hlp, *lp;
+	u_int32_t ndx;
+
+	region = lt->reginfo.primary;
+	dbenv = lt->dbenv;
+
+	/*
+	 * Get the committing locker and mark it as deleted.
+	 * This allows us to traverse the locker links without
+	 * worrying that someone else is deleting locks out
+	 * from under us.  However, if the locker doesn't
+	 * exist, that just means that the child holds no
+	 * locks, so inheritance is easy!
+	 */
+	LOCKER_LOCK(lt, region, locker, ndx);
+	if ((ret = __lock_getlocker(lt,
+	    locker, ndx, 0, &sh_locker)) != 0 ||
+	    sh_locker == NULL ||
+	    F_ISSET(sh_locker, DB_LOCKER_DELETED)) {
+		if (ret == 0 && sh_locker != NULL)
+			ret = EINVAL;
+		__db_err(dbenv, __db_locker_invalid);
+		goto err;
+	}
+
+	/* Make sure we are a child transaction. */
+	if (sh_locker->parent_locker == INVALID_ROFF) {
+		__db_err(dbenv, "Not a child transaction");
+		ret = EINVAL;
+		goto err;
+	}
+	sh_parent = R_ADDR(&lt->reginfo, sh_locker->parent_locker);
+	F_SET(sh_locker, DB_LOCKER_DELETED);
+
+	/*
+	 * Now, lock the parent locker; move locks from
+	 * the committing list to the parent's list.
+	 */
+	LOCKER_LOCK(lt, region, locker, ndx);
+	if (F_ISSET(sh_parent, DB_LOCKER_DELETED)) {
+		if (ret == 0) {
+			__db_err(dbenv,
+			    "Parent locker is not valid");
+			ret = EINVAL;
+		}
+		goto err;
+	}
+
+	/*
+	 * In order to make it possible for a parent to have
+	 * many, many children who lock the same objects, and
+	 * not require an inordinate number of locks, we try
+	 * to merge the child's locks with its parent's.
+	 */
+	for (lp = SH_LIST_FIRST(&sh_locker->heldby, __db_lock);
+	    lp != NULL;
+	    lp = SH_LIST_FIRST(&sh_locker->heldby, __db_lock)) {
+		SH_LIST_REMOVE(lp, locker_links, __db_lock);
+
+		/* See if the parent already has a lock. */
+		obj = (DB_LOCKOBJ *)((u_int8_t *)lp + lp->obj);
+		for (hlp = SH_TAILQ_FIRST(&obj->holders, __db_lock);
+		    hlp != NULL;
+		    hlp = SH_TAILQ_NEXT(hlp, links, __db_lock))
+			if (hlp->holder == sh_parent->id &&
+			    lp->mode == hlp->mode)
+				break;
+
+		if (hlp != NULL) {
+			/* Parent already holds lock. */
+			hlp->refcount += lp->refcount;
+
+			/* Remove lock from object list and free it. */
+			DB_ASSERT(lp->status == DB_LSTAT_HELD);
+			SH_TAILQ_REMOVE(&obj->holders, lp, links, __db_lock);
+			(void)__lock_freelock(lt, lp, locker, DB_LOCK_FREE);
+		} else {
+			/* Just move lock to parent chains. */
+			SH_LIST_INSERT_HEAD(&sh_parent->heldby,
+			    lp, locker_links, __db_lock);
+			lp->holder = sh_parent->id;
+		}
+
+		/*
+		 * We may need to promote regardless of whether we simply
+		 * moved the lock to the parent or changed the parent's
+		 * reference count, because there might be a sibling waiting,
+		 * who will now be allowed to make forward progress.
+		 */
+		(void)__lock_promote(lt, obj,
+		    LF_ISSET(DB_LOCK_NOWAITERS));
+	}
+
+	/* Transfer child counts to parent. */
+	sh_parent->nlocks += sh_locker->nlocks;
+	sh_parent->nwrites += sh_locker->nwrites;
+
+err:	return (ret);
+}
+
 /*
  * __lock_promote --
  *
@@ -1765,60 +1587,11 @@ __lock_remove_waiter(lt, sh_obj, lockp, status)
 
 	/*
 	 * Wake whoever is waiting on this lock.
-	 *
-	 * The MUTEX_UNLOCK macro normally resolves to a single argument,
-	 * keep the compiler quiet.
 	 */
 	if (do_wakeup)
 		MUTEX_UNLOCK(lt->dbenv, &lockp->mutex);
 }
 
-/*
- * __lock_expires -- set the expire time given the time to live.
- * We assume that if timevalp is set then it contains "now".
- * This avoids repeated system calls to get the time.
- */
-static void
-__lock_expires(dbenv, timevalp, timeout)
-	DB_ENV *dbenv;
-	db_timeval_t *timevalp;
-	db_timeout_t timeout;
-{
-	if (!LOCK_TIME_ISVALID(timevalp))
-		__os_clock(dbenv, &timevalp->tv_sec, &timevalp->tv_usec);
-	if (timeout > 1000000) {
-		timevalp->tv_sec += timeout / 1000000;
-		timevalp->tv_usec += timeout % 1000000;
-	} else
-		timevalp->tv_usec += timeout;
-
-	if (timevalp->tv_usec > 1000000) {
-		timevalp->tv_sec++;
-		timevalp->tv_usec -= 1000000;
-	}
-}
-
-/*
- * __lock_expired -- determine if a lock has expired.
- *
- * PUBLIC: int __lock_expired __P((DB_ENV *, db_timeval_t *, db_timeval_t *));
- */
-int
-__lock_expired(dbenv, now, timevalp)
-	DB_ENV *dbenv;
-	db_timeval_t *now, *timevalp;
-{
-	if (!LOCK_TIME_ISVALID(timevalp))
-		return (0);
-
-	if (!LOCK_TIME_ISVALID(now))
-		__os_clock(dbenv, &now->tv_sec, &now->tv_usec);
-
-	return (now->tv_sec > timevalp->tv_sec ||
-	    (now->tv_sec == timevalp->tv_sec &&
-	    now->tv_usec >= timevalp->tv_usec));
-}
-
 /*
  * __lock_trade --
  *
@@ -1841,8 +1614,7 @@ __lock_trade(dbenv, lock, new_locker)
 
 	lt = dbenv->lk_handle;
 	region = lt->reginfo.primary;
-
-	lp = (struct __db_lock *)R_ADDR(&lt->reginfo, lock->off);
+	lp = R_ADDR(&lt->reginfo, lock->off);
 
 	/* If the lock is already released, simply return. */
 	if (lp->gen != lock->gen)
@@ -1860,7 +1632,7 @@ __lock_trade(dbenv, lock, new_locker)
 	}
 
 	/* Remove the lock from its current locker. */
-	if ((ret = __lock_checklocker(lt, lp, lp->holder, DB_LOCK_UNLINK)) != 0)
+	if ((ret = __lock_freelock(lt, lp, lp->holder, DB_LOCK_UNLINK)) != 0)
 		return (ret);
 
 	/* Add lock to its new locker. */
diff --git a/storage/bdb/lock/lock_deadlock.c b/storage/bdb/lock/lock_deadlock.c
index d1461b89a4f82db68386f87f1d4d11aafba23a59..8caf821007ee7c5b7c798e2836ba9ec202923cda 100644
--- a/storage/bdb/lock/lock_deadlock.c
+++ b/storage/bdb/lock/lock_deadlock.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: lock_deadlock.c,v 11.86 2004/10/15 16:59:42 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: lock_deadlock.c,v 11.54 2002/08/06 05:05:21 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -20,10 +18,10 @@ static const char revid[] = "$Id: lock_deadlock.c,v 11.54 2002/08/06 05:05:21 bo
 #include "db_int.h"
 #include "dbinc/db_shash.h"
 #include "dbinc/lock.h"
+#include "dbinc/log.h"
 #include "dbinc/txn.h"
-#include "dbinc/rep.h"
 
-#define	ISSET_MAP(M, N)	((M)[(N) / 32] & (1 << (N) % 32))
+#define	ISSET_MAP(M, N)	((M)[(N) / 32] & (1 << ((N) % 32)))
 
 #define	CLEAR_MAP(M, N) {						\
 	u_int32_t __i;							\
@@ -44,19 +42,21 @@ static const char revid[] = "$Id: lock_deadlock.c,v 11.54 2002/08/06 05:05:21 bo
 typedef struct {
 	int		valid;
 	int		self_wait;
+	int		in_abort;
 	u_int32_t	count;
 	u_int32_t	id;
-	u_int32_t	last_lock;
+	roff_t		last_lock;
+	roff_t		last_obj;
 	u_int32_t	last_locker_id;
 	db_pgno_t	pgno;
 } locker_info;
 
-static int  __dd_abort __P((DB_ENV *, locker_info *));
-static int  __dd_build __P((DB_ENV *,
+static int __dd_abort __P((DB_ENV *, locker_info *));
+static int __dd_build __P((DB_ENV *,
 	    u_int32_t, u_int32_t **, u_int32_t *, u_int32_t *, locker_info **));
-static int  __dd_find __P((DB_ENV *,
+static int __dd_find __P((DB_ENV *,
 	    u_int32_t *, locker_info *, u_int32_t, u_int32_t, u_int32_t ***));
-static int  __dd_isolder __P((u_int32_t, u_int32_t, u_int32_t, u_int32_t));
+static int __dd_isolder __P((u_int32_t, u_int32_t, u_int32_t, u_int32_t));
 static int __dd_verify __P((locker_info *, u_int32_t *, u_int32_t *,
 	    u_int32_t *, u_int32_t, u_int32_t, u_int32_t));
 
@@ -66,24 +66,18 @@ static void __dd_debug
 #endif
 
 /*
- * lock_detect --
+ * __lock_detect_pp --
+ *	DB_ENV->lock_detect pre/post processing.
  *
- * PUBLIC: int __lock_detect __P((DB_ENV *, u_int32_t, u_int32_t, int *));
+ * PUBLIC: int __lock_detect_pp __P((DB_ENV *, u_int32_t, u_int32_t, int *));
  */
 int
-__lock_detect(dbenv, flags, atype, abortp)
+__lock_detect_pp(dbenv, flags, atype, abortp)
 	DB_ENV *dbenv;
 	u_int32_t flags, atype;
 	int *abortp;
 {
-	DB_LOCKREGION *region;
-	DB_LOCKTAB *lt;
-	DB_TXNMGR *tmgr;
-	locker_info *idmap;
-	u_int32_t *bitmap, *copymap, **deadp, **free_me, *tmpmap;
-	u_int32_t i, keeper, killid, limit, nalloc, nlockers;
-	u_int32_t lock_max, txn_max;
-	int ret;
+	int ret, rep_check;
 
 	PANIC_CHECK(dbenv);
 	ENV_REQUIRES_CONFIG(dbenv,
@@ -96,6 +90,7 @@ __lock_detect(dbenv, flags, atype, abortp)
 	case DB_LOCK_DEFAULT:
 	case DB_LOCK_EXPIRE:
 	case DB_LOCK_MAXLOCKS:
+	case DB_LOCK_MAXWRITE:
 	case DB_LOCK_MINLOCKS:
 	case DB_LOCK_MINWRITE:
 	case DB_LOCK_OLDEST:
@@ -108,6 +103,37 @@ __lock_detect(dbenv, flags, atype, abortp)
 		return (EINVAL);
 	}
 
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __lock_detect(dbenv, atype, abortp);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
+/*
+ * __lock_detect --
+ *	DB_ENV->lock_detect.
+ *
+ * PUBLIC: int __lock_detect __P((DB_ENV *, u_int32_t, int *));
+ */
+int
+__lock_detect(dbenv, atype, abortp)
+	DB_ENV *dbenv;
+	u_int32_t atype;
+	int *abortp;
+{
+	DB_LOCKREGION *region;
+	DB_LOCKTAB *lt;
+	DB_TXNMGR *tmgr;
+	db_timeval_t now;
+	locker_info *idmap;
+	u_int32_t *bitmap, *copymap, **deadp, **free_me, *tmpmap;
+	u_int32_t i, cid, keeper, killid, limit, nalloc, nlockers;
+	u_int32_t lock_max, txn_max;
+	int ret;
+
 	/*
 	 * If this environment is a replication client, then we must use the
 	 * MINWRITE detection discipline.
@@ -127,10 +153,15 @@ __lock_detect(dbenv, flags, atype, abortp)
 	/* Make a pass only if auto-detect would run. */
 	region = lt->reginfo.primary;
 
-	if (region->need_dd == 0) {
+	LOCK_SET_TIME_INVALID(&now);
+	if (region->need_dd == 0 &&
+	     (!LOCK_TIME_ISVALID(&region->next_timeout) ||
+	     !__lock_expired(dbenv, &now, &region->next_timeout))) {
 		UNLOCKREGION(dbenv, lt);
 		return (0);
 	}
+	if (region->need_dd == 0)
+		atype = DB_LOCK_EXPIRE;
 
 	/* Reset need_dd, so we know we've run the detector. */
 	region->need_dd = 0;
@@ -184,98 +215,123 @@ __lock_detect(dbenv, flags, atype, abortp)
 	for (; *deadp != NULL; deadp++) {
 		if (abortp != NULL)
 			++*abortp;
-		killid = (u_int32_t)((*deadp - bitmap) / nalloc);
+		killid = (u_int32_t)(*deadp - bitmap) / nalloc;
 		limit = killid;
-		keeper = BAD_KILLID;
 
-		if (atype == DB_LOCK_DEFAULT || atype == DB_LOCK_RANDOM)
-			goto dokill;
 		/*
-		 * It's conceivable that under XA, the locker could
-		 * have gone away.
+		 * There are cases in which our general algorithm will
+		 * fail.  Returning 1 from verify indicates that the
+		 * particular locker is not only involved in a deadlock,
+		 * but that killing him will allow others to make forward
+		 * progress.  Unfortunately, there are cases where we need
+		 * to abort someone, but killing them will not necessarily
+		 * ensure forward progress (imagine N readers all trying to
+		 * acquire a write lock).
+		 * killid is only set to lockers that pass the db_verify test.
+		 * keeper will hold the best candidate even if it does
+		 * not pass db_verify.  Once we fill in killid then we do
+		 * not need a keeper, but we keep updating it anyway.
 		 */
-		if (killid == BAD_KILLID)
-			break;
+
+		keeper = idmap[killid].in_abort == 0 ? killid : BAD_KILLID;
+		if (keeper == BAD_KILLID ||
+		    __dd_verify(idmap, *deadp,
+		    tmpmap, copymap, nlockers, nalloc, keeper) == 0)
+			killid = BAD_KILLID;
+
+		if (killid != BAD_KILLID &&
+		    (atype == DB_LOCK_DEFAULT || atype == DB_LOCK_RANDOM))
+			goto dokill;
 
 		/*
-		 * Start with the id that we know is deadlocked
-		 * and then examine all other set bits and see
-		 * if any are a better candidate for abortion
-		 * and that they are genuinely part of the
-		 * deadlock.  The definition of "best":
-		 * OLDEST: smallest id
-		 * YOUNGEST: largest id
-		 * MAXLOCKS: maximum count
-		 * MINLOCKS: minimum count
-		 * MINWRITE: minimum count
+		 * Start with the id that we know is deadlocked, then examine
+		 * all other set bits and see if any are a better candidate
+		 * for abortion and they are genuinely part of the deadlock.
+		 * The definition of "best":
+		 *	MAXLOCKS: maximum count
+		 *	MAXWRITE: maximum write count
+		 *	MINLOCKS: minimum count
+		 *	MINWRITE: minimum write count
+		 *	OLDEST: smallest id
+		 *	YOUNGEST: largest id
 		 */
-
-		for (i = (killid + 1) % nlockers;
+		for (i = (limit + 1) % nlockers;
 		    i != limit;
 		    i = (i + 1) % nlockers) {
-			if (!ISSET_MAP(*deadp, i))
+			if (!ISSET_MAP(*deadp, i) || idmap[i].in_abort)
 				continue;
+
+			/*
+			 * Determine if we have a verified candidate
+			 * in killid, if not then compare with the
+			 * non-verified candidate in keeper.
+			 */
+			if (killid == BAD_KILLID) {
+				if (keeper == BAD_KILLID)
+					goto use_next;
+				else
+					cid = keeper;
+			} else
+				cid = killid;
+
 			switch (atype) {
 			case DB_LOCK_OLDEST:
-				if (__dd_isolder(idmap[killid].id,
+				if (__dd_isolder(idmap[cid].id,
 				    idmap[i].id, lock_max, txn_max))
 					continue;
-				keeper = i;
 				break;
 			case DB_LOCK_YOUNGEST:
 				if (__dd_isolder(idmap[i].id,
-				    idmap[killid].id, lock_max, txn_max))
+				    idmap[cid].id, lock_max, txn_max))
 					continue;
-				keeper = i;
 				break;
 			case DB_LOCK_MAXLOCKS:
-				if (idmap[i].count < idmap[killid].count)
+				if (idmap[i].count < idmap[cid].count)
+					continue;
+				break;
+			case DB_LOCK_MAXWRITE:
+				if (idmap[i].count < idmap[cid].count)
 					continue;
-				keeper = i;
 				break;
 			case DB_LOCK_MINLOCKS:
 			case DB_LOCK_MINWRITE:
-				if (idmap[i].count > idmap[killid].count)
+				if (idmap[i].count > idmap[cid].count)
 					continue;
-				keeper = i;
 				break;
+			case DB_LOCK_DEFAULT:
+			case DB_LOCK_RANDOM:
+				goto dokill;
+
 			default:
 				killid = BAD_KILLID;
 				ret = EINVAL;
 				goto dokill;
 			}
+
+use_next:		keeper = i;
 			if (__dd_verify(idmap, *deadp,
 			    tmpmap, copymap, nlockers, nalloc, i))
 				killid = i;
 		}
 
-dokill:		if (killid == BAD_KILLID)
-			continue;
-
-		/*
-		 * There are cases in which our general algorithm will
-		 * fail.  Returning 1 from verify indicates that the
-		 * particular locker is not only involved in a deadlock,
-		 * but that killing him will allow others to make forward
-		 * progress.  Unfortunately, there are cases where we need
-		 * to abort someone, but killing them will not necessarily
-		 * ensure forward progress (imagine N readers all trying to
-		 * acquire a write lock).  In such a scenario, we'll have
-		 * gotten all the way through the loop, we will have found
-		 * someone to keep (keeper will be valid), but killid will
-		 * still be the initial deadlocker.  In this case, if the
-		 * initial killid satisfies __dd_verify, kill it, else abort
-		 * keeper and indicate that we need to run deadlock detection
-		 * again.
-		 */
-
-		if (keeper != BAD_KILLID && killid == limit &&
-		    __dd_verify(idmap, *deadp,
-		    tmpmap, copymap, nlockers, nalloc, killid) == 0) {
-			LOCKREGION(dbenv, lt);
-			region->need_dd = 1;
-			UNLOCKREGION(dbenv, lt);
-			killid = keeper;
+dokill:		if (killid == BAD_KILLID) {
+			if (keeper == BAD_KILLID)
+				/*
+				 * It's conceivable that under XA, the
+				 * locker could have gone away.
+				 */
+				continue;
+			else {
+				/*
+				 * Removing a single locker will not
+				 * break the deadlock, signal to run
+				 * detection again.
+				 */
+				LOCKREGION(dbenv, lt);
+				region->need_dd = 1;
+				UNLOCKREGION(dbenv, lt);
+				killid = keeper;
+			}
 		}
 
 		/* Kill the locker with lockid idmap[killid]. */
@@ -292,7 +348,7 @@ dokill:		if (killid == BAD_KILLID)
 				    "warning: unable to abort locker %lx",
 				    (u_long)idmap[killid].id);
 		} else if (FLD_ISSET(dbenv->verbose, DB_VERB_DEADLOCK))
-			__db_err(dbenv,
+			__db_msg(dbenv,
 			    "Aborting locker %lx", (u_long)idmap[killid].id);
 	}
 	__os_free(dbenv, tmpmap);
@@ -325,15 +381,15 @@ __dd_build(dbenv, atype, bmp, nlockers, allocp, idmap)
 	DB_LOCKREGION *region;
 	DB_LOCKTAB *lt;
 	locker_info *id_array;
-	db_timeval_t now;
+	db_timeval_t now, min_timeout;
 	u_int32_t *bitmap, count, dd, *entryp, id, ndx, nentries, *tmpmap;
 	u_int8_t *pptr;
-	int expire_only, is_first, need_timeout, ret;
+	int expire_only, is_first, ret;
 
 	lt = dbenv->lk_handle;
 	region = lt->reginfo.primary;
 	LOCK_SET_TIME_INVALID(&now);
-	need_timeout = 0;
+	LOCK_SET_TIME_MAX(&min_timeout);
 	expire_only = atype == DB_LOCK_EXPIRE;
 
 	/*
@@ -364,10 +420,10 @@ retry:	count = region->stat.st_nlockers;
 	}
 
 	if (FLD_ISSET(dbenv->verbose, DB_VERB_DEADLOCK))
-		__db_err(dbenv, "%lu lockers", (u_long)count);
+		__db_msg(dbenv, "%lu lockers", (u_long)count);
 
 	count += 20;
-	nentries = ALIGN(count, 32) / 32;
+	nentries = (u_int32_t)DB_ALIGN(count, 32) / 32;
 
 	/*
 	 * Allocate enough space for a count by count bitmap matrix.
@@ -409,16 +465,21 @@ retry:	count = region->stat.st_nlockers;
 	for (id = 0, lip = SH_TAILQ_FIRST(&region->lockers, __db_locker);
 	    lip != NULL;
 	    lip = SH_TAILQ_NEXT(lip, ulinks, __db_locker)) {
-		if (F_ISSET(lip, DB_LOCKER_INABORT))
-			continue;
 		if (lip->master_locker == INVALID_ROFF) {
 			lip->dd_id = id++;
 			id_array[lip->dd_id].id = lip->id;
-			if (atype == DB_LOCK_MINLOCKS ||
-			    atype == DB_LOCK_MAXLOCKS)
+			switch (atype) {
+			case DB_LOCK_MINLOCKS:
+			case DB_LOCK_MAXLOCKS:
 				id_array[lip->dd_id].count = lip->nlocks;
-			if (atype == DB_LOCK_MINWRITE)
+				break;
+			case DB_LOCK_MINWRITE:
+			case DB_LOCK_MAXWRITE:
 				id_array[lip->dd_id].count = lip->nwrites;
+				break;
+			}
+			if (F_ISSET(lip, DB_LOCKER_INABORT))
+				id_array[lip->dd_id].in_abort = 1;
 		} else
 			lip->dd_id = DD_INVALID_ID;
 
@@ -449,18 +510,23 @@ obj_loop:
 			if ((ret = __lock_getlocker(lt,
 			    lp->holder, ndx, 0, &lockerp)) != 0)
 				continue;
-			if (F_ISSET(lockerp, DB_LOCKER_INABORT))
-				continue;
 
 			if (lockerp->dd_id == DD_INVALID_ID) {
 				dd = ((DB_LOCKER *)R_ADDR(&lt->reginfo,
 				    lockerp->master_locker))->dd_id;
 				lockerp->dd_id = dd;
-				if (atype == DB_LOCK_MINLOCKS ||
-				    atype == DB_LOCK_MAXLOCKS)
+				switch (atype) {
+				case DB_LOCK_MINLOCKS:
+				case DB_LOCK_MAXLOCKS:
 					id_array[dd].count += lockerp->nlocks;
-				if (atype == DB_LOCK_MINWRITE)
+					break;
+				case DB_LOCK_MINWRITE:
+				case DB_LOCK_MAXWRITE:
 					id_array[dd].count += lockerp->nwrites;
+					break;
+				}
+				if (F_ISSET(lockerp, DB_LOCKER_INABORT))
+					id_array[dd].in_abort = 1;
 
 			} else
 				dd = lockerp->dd_id;
@@ -495,8 +561,10 @@ look_waiters:
 					MUTEX_UNLOCK(dbenv, &lp->mutex);
 					continue;
 				}
-				need_timeout =
-				    LOCK_TIME_ISVALID(&lockerp->lk_expire);
+				if (LOCK_TIME_GREATER(
+				    &min_timeout, &lockerp->lk_expire))
+					min_timeout = lockerp->lk_expire;
+
 			}
 
 			if (expire_only)
@@ -506,11 +574,16 @@ look_waiters:
 				dd = ((DB_LOCKER *)R_ADDR(&lt->reginfo,
 				    lockerp->master_locker))->dd_id;
 				lockerp->dd_id = dd;
-				if (atype == DB_LOCK_MINLOCKS ||
-				    atype == DB_LOCK_MAXLOCKS)
+				switch (atype) {
+				case DB_LOCK_MINLOCKS:
+				case DB_LOCK_MAXLOCKS:
 					id_array[dd].count += lockerp->nlocks;
-				if (atype == DB_LOCK_MINWRITE)
+					break;
+				case DB_LOCK_MINWRITE:
+				case DB_LOCK_MAXWRITE:
 					id_array[dd].count += lockerp->nwrites;
+					break;
+				}
 			} else
 				dd = lockerp->dd_id;
 			id_array[dd].valid = 1;
@@ -539,10 +612,14 @@ look_waiters:
 		}
 	}
 
-	if (expire_only) {
-		region->need_dd = need_timeout;
-		return (0);
+	if (LOCK_TIME_ISVALID(&region->next_timeout)) {
+		if (LOCK_TIME_ISMAX(&min_timeout))
+			LOCK_SET_TIME_INVALID(&region->next_timeout);
+		else
+			region->next_timeout = min_timeout;
 	}
+	if (expire_only)
+		return (0);
 
 	/* Now for each locker; record its last lock. */
 	for (id = 0; id < count; id++) {
@@ -577,7 +654,8 @@ look_waiters:
 		lp = SH_LIST_FIRST(&lockerp->heldby, __db_lock);
 		if (lp != NULL) {
 			id_array[id].last_locker_id = lockerp->id;
-	get_lock:	id_array[id].last_lock = R_OFFSET(&lt->reginfo, lp);
+get_lock:		id_array[id].last_lock = R_OFFSET(&lt->reginfo, lp);
+			id_array[id].last_obj = lp->obj;
 			lo = (DB_LOCKOBJ *)((u_int8_t *)lp + lp->obj);
 			pptr = SH_DBT_PTR(&lo->lockobj);
 			if (lo->lockobj.size >= sizeof(db_pgno_t))
@@ -589,10 +667,9 @@ look_waiters:
 	}
 
 	/*
-	 * Pass complete, reset the deadlock detector bit,
-	 * unless we have pending timeouts.
+	 * Pass complete, reset the deadlock detector bit.
 	 */
-	region->need_dd = need_timeout;
+	region->need_dd = 0;
 
 	/*
 	 * Now we can release everything except the bitmap matrix that we
@@ -613,9 +690,9 @@ __dd_find(dbenv, bmp, idmap, nlockers, nalloc, deadp)
 	locker_info *idmap;
 	u_int32_t ***deadp;
 {
-	u_int32_t i, j, k, *mymap, *tmpmap;
-	u_int32_t **retp;
-	int ndead, ndeadalloc, ret;
+	u_int32_t i, j, k, *mymap, *tmpmap, **retp;
+	u_int ndead, ndeadalloc;
+	int ret;
 
 #undef	INITIAL_DEAD_ALLOC
 #define	INITIAL_DEAD_ALLOC	8
@@ -690,28 +767,36 @@ __dd_abort(dbenv, info)
 
 	LOCKREGION(dbenv, lt);
 
-	/* Find the locker's last lock. */
+	/*
+	 * Get the locker.  If its gone or was aborted while
+	 * we were detecting return that.
+	 */
 	LOCKER_LOCK(lt, region, info->last_locker_id, ndx);
 	if ((ret = __lock_getlocker(lt,
-	    info->last_locker_id, ndx, 0, &lockerp)) != 0 || lockerp == NULL) {
+	    info->last_locker_id, ndx, 0, &lockerp)) != 0 ||
+	    lockerp == NULL || F_ISSET(lockerp, DB_LOCKER_INABORT)) {
 		if (ret == 0)
 			ret = DB_ALREADY_ABORTED;
 		goto out;
 	}
 
-	/* It's possible that this locker was already aborted. */
+	/*
+	 * Find the locker's last lock.
+	 * It is possible for this lock to have been freed,
+	 * either though a timeout or another detector run.
+	 */
 	if ((lockp = SH_LIST_FIRST(&lockerp->heldby, __db_lock)) == NULL) {
 		ret = DB_ALREADY_ABORTED;
 		goto out;
 	}
 	if (R_OFFSET(&lt->reginfo, lockp) != info->last_lock ||
-	    lockp->status != DB_LSTAT_WAITING) {
+	    lockp->holder != lockerp->id ||
+	    lockp->obj != info->last_obj || lockp->status != DB_LSTAT_WAITING) {
 		ret = DB_ALREADY_ABORTED;
 		goto out;
 	}
 
 	sh_obj = (DB_LOCKOBJ *)((u_int8_t *)lockp + lockp->obj);
-	SH_LIST_REMOVE(lockp, locker_links, __db_lock);
 
 	/* Abort lock, take it off list, and wake up this lock. */
 	SHOBJECT_LOCK(lt, region, sh_obj, ndx);
@@ -746,32 +831,25 @@ __dd_debug(dbenv, idmap, bitmap, nlockers, nalloc)
 	locker_info *idmap;
 	u_int32_t *bitmap, nlockers, nalloc;
 {
+	DB_MSGBUF mb;
 	u_int32_t i, j, *mymap;
-	char *msgbuf;
 
-	__db_err(dbenv, "Waitsfor array\nWaiter:\tWaiting on:");
-
-	/* Allocate space to print 10 bytes per item waited on. */
-#undef	MSGBUF_LEN
-#define	MSGBUF_LEN ((nlockers + 1) * 10 + 64)
-	if (__os_malloc(dbenv, MSGBUF_LEN, &msgbuf) != 0)
-		return;
+	DB_MSGBUF_INIT(&mb);
 
+	__db_msg(dbenv, "Waitsfor array\nWaiter:\tWaiting on:");
 	for (mymap = bitmap, i = 0; i < nlockers; i++, mymap += nalloc) {
 		if (!idmap[i].valid)
 			continue;
-		sprintf(msgbuf,					/* Waiter. */
+
+		__db_msgadd(dbenv, &mb,				/* Waiter. */
 		    "%lx/%lu:\t", (u_long)idmap[i].id, (u_long)idmap[i].pgno);
 		for (j = 0; j < nlockers; j++)
 			if (ISSET_MAP(mymap, j))
-				sprintf(msgbuf, "%s %lx", msgbuf,
-				    (u_long)idmap[j].id);
-		(void)sprintf(msgbuf,
-		    "%s %lu", msgbuf, (u_long)idmap[i].last_lock);
-		__db_err(dbenv, msgbuf);
+				__db_msgadd(dbenv,
+				    &mb, " %lx", (u_long)idmap[j].id);
+		__db_msgadd(dbenv, &mb, " %lu", (u_long)idmap[i].last_lock);
+		DB_MSGBUF_FLUSH(dbenv, &mb);
 	}
-
-	__os_free(dbenv, msgbuf);
 }
 #endif
 
@@ -779,12 +857,12 @@ __dd_debug(dbenv, idmap, bitmap, nlockers, nalloc)
  * Given a bitmap that contains a deadlock, verify that the bit
  * specified in the which parameter indicates a transaction that
  * is actually deadlocked.  Return 1 if really deadlocked, 0 otherwise.
- * deadmap is the array that identified the deadlock.
- * tmpmap is a copy of the initial bitmaps from the dd_build phase
- * origmap is a temporary bit map into which we can OR things
- * nlockers is the number of actual lockers under consideration
- * nalloc is the number of words allocated for the bitmap
- * which is the locker in question
+ * deadmap  --  the array that identified the deadlock.
+ * tmpmap   --  a copy of the initial bitmaps from the dd_build phase.
+ * origmap  --  a temporary bit map into which we can OR things.
+ * nlockers --  the number of actual lockers under consideration.
+ * nalloc   --  the number of words allocated for the bitmap.
+ * which    --  the locker in question.
  */
 static int
 __dd_verify(idmap, deadmap, tmpmap, origmap, nlockers, nalloc, which)
diff --git a/storage/bdb/lock/lock_id.c b/storage/bdb/lock/lock_id.c
new file mode 100644
index 0000000000000000000000000000000000000000..02f85765de624dc2c1dbf4d2c756df239ca10fbe
--- /dev/null
+++ b/storage/bdb/lock/lock_id.c
@@ -0,0 +1,407 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: lock_id.c,v 11.146 2004/10/15 16:59:42 bostic Exp $
+ */
+
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#include <stdlib.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
+
+/*
+ * __lock_id_pp --
+ *	DB_ENV->lock_id pre/post processing.
+ *
+ * PUBLIC: int __lock_id_pp __P((DB_ENV *, u_int32_t *));
+ */
+int
+__lock_id_pp(dbenv, idp)
+	DB_ENV *dbenv;
+	u_int32_t *idp;
+{
+	int rep_check, ret;
+
+	PANIC_CHECK(dbenv);
+	ENV_REQUIRES_CONFIG(dbenv,
+	    dbenv->lk_handle, "DB_ENV->lock_id", DB_INIT_LOCK);
+
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __lock_id(dbenv, idp);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
+/*
+ * __lock_id --
+ *	DB_ENV->lock_id.
+ *
+ * PUBLIC: int  __lock_id __P((DB_ENV *, u_int32_t *));
+ */
+int
+__lock_id(dbenv, idp)
+	DB_ENV *dbenv;
+	u_int32_t *idp;
+{
+	DB_LOCKER *lk;
+	DB_LOCKTAB *lt;
+	DB_LOCKREGION *region;
+	u_int32_t *ids, locker_ndx;
+	int nids, ret;
+
+	lt = dbenv->lk_handle;
+	region = lt->reginfo.primary;
+	ret = 0;
+
+	/*
+	 * Allocate a new lock id.  If we wrap around then we
+	 * find the minimum currently in use and make sure we
+	 * can stay below that.  This code is similar to code
+	 * in __txn_begin_int for recovering txn ids.
+	 */
+	LOCKREGION(dbenv, lt);
+	/*
+	 * Our current valid range can span the maximum valid value, so check
+	 * for it and wrap manually.
+	 */
+	if (region->stat.st_id == DB_LOCK_MAXID &&
+	    region->stat.st_cur_maxid != DB_LOCK_MAXID)
+		region->stat.st_id = DB_LOCK_INVALIDID;
+	if (region->stat.st_id == region->stat.st_cur_maxid) {
+		if ((ret = __os_malloc(dbenv,
+		    sizeof(u_int32_t) * region->stat.st_nlockers, &ids)) != 0)
+			goto err;
+		nids = 0;
+		for (lk = SH_TAILQ_FIRST(&region->lockers, __db_locker);
+		    lk != NULL;
+		    lk = SH_TAILQ_NEXT(lk, ulinks, __db_locker))
+			ids[nids++] = lk->id;
+		region->stat.st_id = DB_LOCK_INVALIDID;
+		region->stat.st_cur_maxid = DB_LOCK_MAXID;
+		if (nids != 0)
+			__db_idspace(ids, nids,
+			    &region->stat.st_id, &region->stat.st_cur_maxid);
+		__os_free(dbenv, ids);
+	}
+	*idp = ++region->stat.st_id;
+
+	/* Allocate a locker for this id. */
+	LOCKER_LOCK(lt, region, *idp, locker_ndx);
+	ret = __lock_getlocker(lt, *idp, locker_ndx, 1, &lk);
+
+err:	UNLOCKREGION(dbenv, lt);
+
+	return (ret);
+}
+
+/*
+ * __lock_id_free_pp --
+ *	DB_ENV->lock_id_free pre/post processing.
+ *
+ * PUBLIC: int __lock_id_free_pp __P((DB_ENV *, u_int32_t));
+ */
+int
+__lock_id_free_pp(dbenv, id)
+	DB_ENV *dbenv;
+	u_int32_t id;
+{
+	int rep_check, ret;
+
+	PANIC_CHECK(dbenv);
+	ENV_REQUIRES_CONFIG(dbenv,
+	    dbenv->lk_handle, "DB_ENV->lock_id_free", DB_INIT_LOCK);
+
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __lock_id_free(dbenv, id);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
+/*
+ * __lock_id_free --
+ *	Free a locker id.
+ *
+ * PUBLIC: int  __lock_id_free __P((DB_ENV *, u_int32_t));
+ */
+int
+__lock_id_free(dbenv, id)
+	DB_ENV *dbenv;
+	u_int32_t id;
+{
+	DB_LOCKER *sh_locker;
+	DB_LOCKTAB *lt;
+	DB_LOCKREGION *region;
+	u_int32_t locker_ndx;
+	int ret;
+
+	PANIC_CHECK(dbenv);
+	ENV_REQUIRES_CONFIG(dbenv,
+	    dbenv->lk_handle, "DB_ENV->lock_id_free", DB_INIT_LOCK);
+
+	lt = dbenv->lk_handle;
+	region = lt->reginfo.primary;
+
+	LOCKREGION(dbenv, lt);
+	LOCKER_LOCK(lt, region, id, locker_ndx);
+	if ((ret = __lock_getlocker(lt, id, locker_ndx, 0, &sh_locker)) != 0)
+		goto err;
+
+	if (sh_locker == NULL) {
+		__db_err(dbenv, "Unknown locker ID: %lx", (u_long)id);
+		ret = EINVAL;
+		goto err;
+	}
+
+	if (sh_locker->nlocks != 0) {
+		__db_err(dbenv, "Locker still has locks");
+		ret = EINVAL;
+		goto err;
+	}
+
+	__lock_freelocker(lt, region, sh_locker, locker_ndx);
+
+err:	UNLOCKREGION(dbenv, lt);
+	return (ret);
+}
+
+/*
+ * __lock_id_set --
+ *	Set the current locker ID and current maximum unused ID (for
+ *	testing purposes only).
+ *
+ * PUBLIC: int __lock_id_set __P((DB_ENV *, u_int32_t, u_int32_t));
+ */
+int
+__lock_id_set(dbenv, cur_id, max_id)
+	DB_ENV *dbenv;
+	u_int32_t cur_id, max_id;
+{
+	DB_LOCKTAB *lt;
+	DB_LOCKREGION *region;
+
+	ENV_REQUIRES_CONFIG(dbenv,
+	    dbenv->lk_handle, "lock_id_set", DB_INIT_LOCK);
+
+	lt = dbenv->lk_handle;
+	region = lt->reginfo.primary;
+	region->stat.st_id = cur_id;
+	region->stat.st_cur_maxid = max_id;
+
+	return (0);
+}
+
+/*
+ * __lock_getlocker --
+ *	Get a locker in the locker hash table.  The create parameter
+ * indicates if the locker should be created if it doesn't exist in
+ * the table.
+ *
+ * This must be called with the locker bucket locked.
+ *
+ * PUBLIC: int __lock_getlocker __P((DB_LOCKTAB *,
+ * PUBLIC:     u_int32_t, u_int32_t, int, DB_LOCKER **));
+ */
+int
+__lock_getlocker(lt, locker, indx, create, retp)
+	DB_LOCKTAB *lt;
+	u_int32_t locker, indx;
+	int create;
+	DB_LOCKER **retp;
+{
+	DB_ENV *dbenv;
+	DB_LOCKER *sh_locker;
+	DB_LOCKREGION *region;
+
+	dbenv = lt->dbenv;
+	region = lt->reginfo.primary;
+
+	HASHLOOKUP(lt->locker_tab,
+	    indx, __db_locker, links, locker, sh_locker, __lock_locker_cmp);
+
+	/*
+	 * If we found the locker, then we can just return it.  If
+	 * we didn't find the locker, then we need to create it.
+	 */
+	if (sh_locker == NULL && create) {
+		/* Create new locker and then insert it into hash table. */
+		if ((sh_locker = SH_TAILQ_FIRST(
+		    &region->free_lockers, __db_locker)) == NULL)
+			return (__lock_nomem(dbenv, "locker entries"));
+		SH_TAILQ_REMOVE(
+		    &region->free_lockers, sh_locker, links, __db_locker);
+		if (++region->stat.st_nlockers > region->stat.st_maxnlockers)
+			region->stat.st_maxnlockers = region->stat.st_nlockers;
+
+		sh_locker->id = locker;
+		sh_locker->dd_id = 0;
+		sh_locker->master_locker = INVALID_ROFF;
+		sh_locker->parent_locker = INVALID_ROFF;
+		SH_LIST_INIT(&sh_locker->child_locker);
+		sh_locker->flags = 0;
+		SH_LIST_INIT(&sh_locker->heldby);
+		sh_locker->nlocks = 0;
+		sh_locker->nwrites = 0;
+		sh_locker->lk_timeout = 0;
+		LOCK_SET_TIME_INVALID(&sh_locker->tx_expire);
+		LOCK_SET_TIME_INVALID(&sh_locker->lk_expire);
+
+		HASHINSERT(lt->locker_tab, indx, __db_locker, links, sh_locker);
+		SH_TAILQ_INSERT_HEAD(&region->lockers,
+		    sh_locker, ulinks, __db_locker);
+	}
+
+	*retp = sh_locker;
+	return (0);
+}
+
+/*
+ * __lock_addfamilylocker
+ *	Put a locker entry in for a child transaction.
+ *
+ * PUBLIC: int __lock_addfamilylocker __P((DB_ENV *, u_int32_t, u_int32_t));
+ */
+int
+__lock_addfamilylocker(dbenv, pid, id)
+	DB_ENV *dbenv;
+	u_int32_t pid, id;
+{
+	DB_LOCKER *lockerp, *mlockerp;
+	DB_LOCKREGION *region;
+	DB_LOCKTAB *lt;
+	u_int32_t ndx;
+	int ret;
+
+	lt = dbenv->lk_handle;
+	region = lt->reginfo.primary;
+	LOCKREGION(dbenv, lt);
+
+	/* get/create the  parent locker info */
+	LOCKER_LOCK(lt, region, pid, ndx);
+	if ((ret = __lock_getlocker(dbenv->lk_handle,
+	    pid, ndx, 1, &mlockerp)) != 0)
+		goto err;
+
+	/*
+	 * We assume that only one thread can manipulate
+	 * a single transaction family.
+	 * Therefore the master locker cannot go away while
+	 * we manipulate it, nor can another child in the
+	 * family be created at the same time.
+	 */
+	LOCKER_LOCK(lt, region, id, ndx);
+	if ((ret = __lock_getlocker(dbenv->lk_handle,
+	    id, ndx, 1, &lockerp)) != 0)
+		goto err;
+
+	/* Point to our parent. */
+	lockerp->parent_locker = R_OFFSET(&lt->reginfo, mlockerp);
+
+	/* See if this locker is the family master. */
+	if (mlockerp->master_locker == INVALID_ROFF)
+		lockerp->master_locker = R_OFFSET(&lt->reginfo, mlockerp);
+	else {
+		lockerp->master_locker = mlockerp->master_locker;
+		mlockerp = R_ADDR(&lt->reginfo, mlockerp->master_locker);
+	}
+
+	/*
+	 * Link the child at the head of the master's list.
+	 * The guess is when looking for deadlock that
+	 * the most recent child is the one thats blocked.
+	 */
+	SH_LIST_INSERT_HEAD(
+	    &mlockerp->child_locker, lockerp, child_link, __db_locker);
+
+err:
+	UNLOCKREGION(dbenv, lt);
+
+	return (ret);
+}
+
+/*
+ * __lock_freefamilylocker
+ *	Remove a locker from the hash table and its family.
+ *
+ * This must be called without the locker bucket locked.
+ *
+ * PUBLIC: int __lock_freefamilylocker  __P((DB_LOCKTAB *, u_int32_t));
+ */
+int
+__lock_freefamilylocker(lt, locker)
+	DB_LOCKTAB *lt;
+	u_int32_t locker;
+{
+	DB_ENV *dbenv;
+	DB_LOCKER *sh_locker;
+	DB_LOCKREGION *region;
+	u_int32_t indx;
+	int ret;
+
+	dbenv = lt->dbenv;
+	region = lt->reginfo.primary;
+
+	LOCKREGION(dbenv, lt);
+	LOCKER_LOCK(lt, region, locker, indx);
+
+	if ((ret = __lock_getlocker(lt,
+	    locker, indx, 0, &sh_locker)) != 0 || sh_locker == NULL)
+		goto err;
+
+	if (SH_LIST_FIRST(&sh_locker->heldby, __db_lock) != NULL) {
+		ret = EINVAL;
+		__db_err(dbenv, "Freeing locker with locks");
+		goto err;
+	}
+
+	/* If this is part of a family, we must fix up its links. */
+	if (sh_locker->master_locker != INVALID_ROFF)
+		SH_LIST_REMOVE(sh_locker, child_link, __db_locker);
+
+	__lock_freelocker(lt, region, sh_locker, indx);
+
+err:
+	UNLOCKREGION(dbenv, lt);
+	return (ret);
+}
+
+/*
+ * __lock_freelocker
+ *      Common code for deleting a locker; must be called with the
+ *	locker bucket locked.
+ *
+ * PUBLIC: void __lock_freelocker
+ * PUBLIC:    __P((DB_LOCKTAB *, DB_LOCKREGION *, DB_LOCKER *, u_int32_t));
+ */
+void
+__lock_freelocker(lt, region, sh_locker, indx)
+	DB_LOCKTAB *lt;
+	DB_LOCKREGION *region;
+	DB_LOCKER *sh_locker;
+	u_int32_t indx;
+
+{
+	HASHREMOVE_EL(
+	    lt->locker_tab, indx, __db_locker, links, sh_locker);
+	SH_TAILQ_INSERT_HEAD(
+	    &region->free_lockers, sh_locker, links, __db_locker);
+	SH_TAILQ_REMOVE(&region->lockers, sh_locker, ulinks, __db_locker);
+	region->stat.st_nlockers--;
+}
diff --git a/storage/bdb/lock/lock_list.c b/storage/bdb/lock/lock_list.c
new file mode 100644
index 0000000000000000000000000000000000000000..5851dc7fadfe8f459be79bc9502061cd0f1f041a
--- /dev/null
+++ b/storage/bdb/lock/lock_list.c
@@ -0,0 +1,351 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: lock_list.c,v 11.146 2004/09/22 03:48:29 bostic Exp $
+ */
+
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#include <stdlib.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
+
+static int __lock_sort_cmp __P((const void *, const void *));
+
+/*
+ * Lock list routines.
+ *	The list is composed of a 32-bit count of locks followed by
+ * each lock.  A lock is represented by a 16-bit page-count, a lock
+ * object and a page list.  A lock object consists of a 16-bit size
+ * and the object itself.   In a pseudo BNF notation, you get:
+ *
+ * LIST = COUNT32 LOCK*
+ * LOCK = COUNT16 LOCKOBJ PAGELIST
+ * LOCKOBJ = COUNT16 OBJ
+ * PAGELIST = COUNT32*
+ *
+ * (Recall that X* means "0 or more X's")
+ *
+ * In most cases, the OBJ is a struct __db_ilock and the page list is
+ * a series of (32-bit) page numbers that should get written into the
+ * pgno field of the __db_ilock.  So, the actual number of pages locked
+ * is the number of items in the PAGELIST plus 1. If this is an application-
+ * specific lock, then we cannot interpret obj and the pagelist must
+ * be empty.
+ *
+ * Consider a lock list for: File A, pages 1&2, File B pages 3-5, Applock
+ * This would be represented as:
+ *	5 1 [fid=A;page=1] 2 2 [fid=B;page=3] 4 5 0 APPLOCK
+ *        ------------------ -------------------- ---------
+ *         LOCK for file A    LOCK for file B     application-specific lock
+ */
+
+#define	MAX_PGNOS	0xffff
+
+/*
+ * These macros are bigger than one might expect because some compilers say a
+ * cast does not return an lvalue, so constructs like *(u_int32_t*)dp = count;
+ * generate warnings.
+ */
+#define	RET_SIZE(size, count)  ((size) +				\
+     sizeof(u_int32_t) + (count) * 2 * sizeof(u_int16_t))
+
+#define	PUT_COUNT(dp, count)	do {	u_int32_t *ip = (u_int32_t *)dp;\
+					*ip = count;			\
+					dp = (u_int8_t *)dp +		\
+					     sizeof(u_int32_t);		\
+				} while (0)
+#define	PUT_PCOUNT(dp, count)	do {	u_int16_t *ip = (u_int16_t *)dp;\
+					*ip = count;			\
+					dp = (u_int8_t *)dp +		\
+					    sizeof(u_int16_t);		\
+				} while (0)
+#define	PUT_SIZE(dp, size)	do {	u_int16_t *ip = (u_int16_t *)dp;\
+					*ip = size;			\
+					dp = (u_int8_t *)dp +		\
+					    sizeof(u_int16_t);		\
+				} while (0)
+#define	PUT_PGNO(dp, pgno)	do {	db_pgno_t *ip = (db_pgno_t *)dp;\
+					*ip = pgno;			\
+					dp = (u_int8_t *)dp +		\
+					    sizeof(db_pgno_t);		\
+				} while (0)
+#define	COPY_OBJ(dp, obj)	do {					\
+					memcpy(dp,			\
+					    (obj)->data, (obj)->size);  \
+					dp = (u_int8_t *)dp +		\
+					     DB_ALIGN((obj)->size,	\
+					     sizeof(u_int32_t));	\
+				} while (0)
+#define	GET_COUNT(dp, count)	do {					\
+					(count) = *(u_int32_t *)dp;	\
+					dp = (u_int8_t *)dp +		\
+					     sizeof(u_int32_t);	\
+				} while (0)
+#define	GET_PCOUNT(dp, count)	do {					\
+					(count) = *(u_int16_t *)dp;	\
+					dp = (u_int8_t *)dp +		\
+					     sizeof(u_int16_t);	\
+				} while (0)
+#define	GET_SIZE(dp, size)	do {					\
+					(size) = *(u_int16_t *)dp;	\
+					dp = (u_int8_t *)dp +		\
+					     sizeof(u_int16_t);	\
+				} while (0)
+#define	GET_PGNO(dp, pgno)	do {					\
+					(pgno) = *(db_pgno_t *)dp;	\
+					dp = (u_int8_t *)dp +		\
+					     sizeof(db_pgno_t);	\
+				} while (0)
+
+/*
+ * __lock_fix_list --
+ *
+ * PUBLIC: int __lock_fix_list __P((DB_ENV *, DBT *, u_int32_t));
+ */
+int
+__lock_fix_list(dbenv, list_dbt, nlocks)
+	DB_ENV *dbenv;
+	DBT *list_dbt;
+	u_int32_t nlocks;
+{
+	DBT *obj;
+	DB_LOCK_ILOCK *lock, *plock;
+	u_int32_t i, j, nfid, npgno, size;
+	u_int8_t *data, *dp;
+	int ret;
+
+	if ((size = list_dbt->size) == 0)
+		return (0);
+
+	obj = (DBT *)list_dbt->data;
+
+	/*
+	 * If necessary sort the list of locks so that locks on the same fileid
+	 * are together.  We do not sort 1 or 2 locks because by definition if
+	 * there are locks on the same fileid they will be together.  The sort
+	 * will also move any locks that do not look like page locks to the end
+	 * of the list so we can stop looking for locks we can combine when we
+	 * hit one.
+	 */
+	switch (nlocks) {
+	case 1:
+		size = RET_SIZE(obj->size, 1);
+		if ((ret = __os_malloc(dbenv, size, &data)) != 0)
+			return (ret);
+
+		dp = data;
+		PUT_COUNT(dp, 1);
+		PUT_PCOUNT(dp, 0);
+		PUT_SIZE(dp, obj->size);
+		COPY_OBJ(dp, obj);
+		break;
+	default:
+		/* Sort so that all locks with same fileid are together. */
+		qsort(list_dbt->data, nlocks, sizeof(DBT), __lock_sort_cmp);
+		/* FALLTHROUGH */
+	case 2:
+		nfid = npgno = 0;
+		i = 0;
+		if (obj->size != sizeof(DB_LOCK_ILOCK))
+			goto not_ilock;
+
+		nfid = 1;
+		plock = (DB_LOCK_ILOCK *)obj->data;
+
+		/* We use ulen to keep track of the number of pages. */
+		j = 0;
+		obj[0].ulen = 0;
+		for (i = 1; i < nlocks; i++) {
+			if (obj[i].size != sizeof(DB_LOCK_ILOCK))
+				break;
+			lock = (DB_LOCK_ILOCK *)obj[i].data;
+			if (obj[j].ulen < MAX_PGNOS &&
+			     lock->type == plock->type &&
+			     memcmp(lock->fileid,
+			     plock->fileid, DB_FILE_ID_LEN) == 0) {
+				obj[j].ulen++;
+				npgno++;
+			} else {
+				nfid++;
+				plock = lock;
+				j = i;
+				obj[j].ulen = 0;
+			}
+		}
+
+not_ilock:	size = nfid * sizeof(DB_LOCK_ILOCK);
+		size += npgno * sizeof(db_pgno_t);
+		/* Add the number of nonstandard locks and get their size. */
+		nfid += nlocks - i;
+		for (; i < nlocks; i++) {
+			size += obj[i].size;
+			obj[i].ulen = 0;
+		}
+
+		size = RET_SIZE(size, nfid);
+		if ((ret = __os_malloc(dbenv, size, &data)) != 0)
+			return (ret);
+
+		dp = data;
+		PUT_COUNT(dp, nfid);
+
+		for (i = 0; i < nlocks; i = j) {
+			PUT_PCOUNT(dp, obj[i].ulen);
+			PUT_SIZE(dp, obj[i].size);
+			COPY_OBJ(dp, &obj[i]);
+			lock = (DB_LOCK_ILOCK *)obj[i].data;
+			for (j = i + 1; j <= i + obj[i].ulen; j++) {
+				lock = (DB_LOCK_ILOCK *)obj[j].data;
+				PUT_PGNO(dp, lock->pgno);
+			}
+		}
+	}
+
+	__os_free(dbenv, list_dbt->data);
+
+	list_dbt->data = data;
+	list_dbt->size = size;
+
+	return (0);
+}
+
+/*
+ * PUBLIC: int __lock_get_list __P((DB_ENV *, u_int32_t, u_int32_t,
+ * PUBLIC:	      db_lockmode_t, DBT *));
+ */
+int
+__lock_get_list(dbenv, locker, flags, lock_mode, list)
+	DB_ENV *dbenv;
+	u_int32_t locker, flags;
+	db_lockmode_t lock_mode;
+	DBT *list;
+{
+	DBT obj_dbt;
+	DB_LOCK ret_lock;
+	DB_LOCK_ILOCK *lock;
+	DB_LOCKTAB *lt;
+	db_pgno_t save_pgno;
+	u_int16_t npgno, size;
+	u_int32_t i, nlocks;
+	int ret;
+	void *dp;
+
+	if (list->size == 0)
+		return (0);
+	ret = 0;
+	lt = dbenv->lk_handle;
+	dp = list->data;
+
+	GET_COUNT(dp, nlocks);
+	LOCKREGION(dbenv, dbenv->lk_handle);
+
+	for (i = 0; i < nlocks; i++) {
+		GET_PCOUNT(dp, npgno);
+		GET_SIZE(dp, size);
+		lock = (DB_LOCK_ILOCK *) dp;
+		save_pgno = lock->pgno;
+		obj_dbt.data = dp;
+		obj_dbt.size = size;
+		dp = ((u_int8_t *)dp) + DB_ALIGN(size, sizeof(u_int32_t));
+		do {
+			if ((ret = __lock_get_internal(lt, locker,
+			     flags, &obj_dbt, lock_mode, 0, &ret_lock)) != 0) {
+			     lock->pgno = save_pgno;
+			     goto err;
+			}
+			if (npgno != 0)
+				GET_PGNO(dp, lock->pgno);
+		} while (npgno-- != 0);
+		lock->pgno = save_pgno;
+	}
+
+err:
+	UNLOCKREGION(dbenv, dbenv->lk_handle);
+	return (ret);
+}
+
+#define	UINT32_CMP(A, B)	((A) == (B) ? 0 : ((A) > (B) ? 1 : -1))
+static int
+__lock_sort_cmp(a, b)
+	const void *a, *b;
+{
+	const DBT *d1, *d2;
+	DB_LOCK_ILOCK *l1, *l2;
+
+	d1 = a;
+	d2 = b;
+
+	/* Force all non-standard locks to sort at end. */
+	if (d1->size != sizeof(DB_LOCK_ILOCK)) {
+		if (d2->size != sizeof(DB_LOCK_ILOCK))
+			return (UINT32_CMP(d1->size, d2->size));
+		else
+			return (1);
+	} else if (d2->size != sizeof(DB_LOCK_ILOCK))
+		return (-1);
+
+	l1 = d1->data;
+	l2 = d2->data;
+	if (l1->type != l2->type)
+		return (UINT32_CMP(l1->type, l2->type));
+	return (memcmp(l1->fileid, l2->fileid, DB_FILE_ID_LEN));
+}
+
+/*
+ * PUBLIC: void __lock_list_print __P((DB_ENV *, DBT *));
+ */
+void
+__lock_list_print(dbenv, list)
+	DB_ENV *dbenv;
+	DBT *list;
+{
+	DB_LOCK_ILOCK *lock;
+	db_pgno_t pgno;
+	u_int16_t npgno, size;
+	u_int32_t i, nlocks;
+	u_int8_t *fidp;
+	char *namep;
+	void *dp;
+
+	if (list->size == 0)
+		return;
+	dp = list->data;
+
+	GET_COUNT(dp, nlocks);
+
+	for (i = 0; i < nlocks; i++) {
+		GET_PCOUNT(dp, npgno);
+		GET_SIZE(dp, size);
+		lock = (DB_LOCK_ILOCK *) dp;
+		fidp = lock->fileid;
+		if (__dbreg_get_name(dbenv, fidp, &namep) != 0)
+			namep = NULL;
+		printf("\t");
+		if (namep == NULL)
+			printf("(%lx %lx %lx %lx %lx)",
+			(u_long)fidp[0], (u_long)fidp[1], (u_long)fidp[2],
+			(u_long)fidp[3], (u_long)fidp[4]);
+		else
+			printf("%-25s", namep);
+		dp = ((u_int8_t *)dp) + DB_ALIGN(size, sizeof(u_int32_t));
+		pgno = lock->pgno;
+		do {
+			printf(" %d", pgno);
+			if (npgno != 0)
+				GET_PGNO(dp, pgno);
+		} while (npgno-- != 0);
+		printf("\n");
+	}
+}
diff --git a/storage/bdb/lock/lock_method.c b/storage/bdb/lock/lock_method.c
index 72703e253bc69621b09ace8e43f726b67c6b5d1f..d571794931dd54507dde6dc1f9131dc6afdcf213 100644
--- a/storage/bdb/lock/lock_method.c
+++ b/storage/bdb/lock/lock_method.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: lock_method.c,v 11.44 2004/06/01 21:50:05 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: lock_method.c,v 11.30 2002/03/27 04:32:20 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -21,22 +19,25 @@ static const char revid[] = "$Id: lock_method.c,v 11.30 2002/03/27 04:32:20 bost
 #include <string.h>
 #endif
 
+#ifdef HAVE_RPC
+#include "db_server.h"
+#endif
+
 #include "db_int.h"
 #include "dbinc/db_shash.h"
 #include "dbinc/lock.h"
 
 #ifdef HAVE_RPC
-#include "dbinc_auto/db_server.h"
 #include "dbinc_auto/rpc_client_ext.h"
 #endif
 
+static int __lock_get_lk_conflicts __P((DB_ENV *, const u_int8_t **, int *));
 static int __lock_set_lk_conflicts __P((DB_ENV *, u_int8_t *, int));
-static int __lock_set_lk_detect __P((DB_ENV *, u_int32_t));
-static int __lock_set_lk_max __P((DB_ENV *, u_int32_t));
-static int __lock_set_lk_max_lockers __P((DB_ENV *, u_int32_t));
-static int __lock_set_lk_max_locks __P((DB_ENV *, u_int32_t));
-static int __lock_set_lk_max_objects __P((DB_ENV *, u_int32_t));
-static int __lock_set_env_timeout __P((DB_ENV *, db_timeout_t, u_int32_t));
+static int __lock_get_lk_detect __P((DB_ENV *, u_int32_t *));
+static int __lock_get_lk_max_lockers __P((DB_ENV *, u_int32_t *));
+static int __lock_get_lk_max_locks __P((DB_ENV *, u_int32_t *));
+static int __lock_get_lk_max_objects __P((DB_ENV *, u_int32_t *));
+static int __lock_get_env_timeout __P((DB_ENV *, db_timeout_t *, u_int32_t));
 
 /*
  * __lock_dbenv_create --
@@ -61,42 +62,51 @@ __lock_dbenv_create(dbenv)
 
 #ifdef	HAVE_RPC
 	if (F_ISSET(dbenv, DB_ENV_RPCCLIENT)) {
+		dbenv->get_lk_conflicts = __dbcl_get_lk_conflicts;
 		dbenv->set_lk_conflicts = __dbcl_set_lk_conflict;
+		dbenv->get_lk_detect = __dbcl_get_lk_detect;
 		dbenv->set_lk_detect = __dbcl_set_lk_detect;
 		dbenv->set_lk_max = __dbcl_set_lk_max;
+		dbenv->get_lk_max_lockers = __dbcl_get_lk_max_lockers;
 		dbenv->set_lk_max_lockers = __dbcl_set_lk_max_lockers;
+		dbenv->get_lk_max_locks = __dbcl_get_lk_max_locks;
 		dbenv->set_lk_max_locks = __dbcl_set_lk_max_locks;
+		dbenv->get_lk_max_objects = __dbcl_get_lk_max_objects;
 		dbenv->set_lk_max_objects = __dbcl_set_lk_max_objects;
+
 		dbenv->lock_detect = __dbcl_lock_detect;
-		dbenv->lock_dump_region = NULL;
 		dbenv->lock_get = __dbcl_lock_get;
 		dbenv->lock_id = __dbcl_lock_id;
 		dbenv->lock_id_free = __dbcl_lock_id_free;
 		dbenv->lock_put = __dbcl_lock_put;
 		dbenv->lock_stat = __dbcl_lock_stat;
+		dbenv->lock_stat_print = NULL;
 		dbenv->lock_vec = __dbcl_lock_vec;
 	} else
 #endif
 	{
+		dbenv->get_lk_conflicts = __lock_get_lk_conflicts;
 		dbenv->set_lk_conflicts = __lock_set_lk_conflicts;
+		dbenv->get_lk_detect = __lock_get_lk_detect;
 		dbenv->set_lk_detect = __lock_set_lk_detect;
 		dbenv->set_lk_max = __lock_set_lk_max;
+		dbenv->get_lk_max_lockers = __lock_get_lk_max_lockers;
 		dbenv->set_lk_max_lockers = __lock_set_lk_max_lockers;
+		dbenv->get_lk_max_locks = __lock_get_lk_max_locks;
 		dbenv->set_lk_max_locks = __lock_set_lk_max_locks;
+		dbenv->get_lk_max_objects = __lock_get_lk_max_objects;
 		dbenv->set_lk_max_objects = __lock_set_lk_max_objects;
+		dbenv->get_timeout = __lock_get_env_timeout;
 		dbenv->set_timeout = __lock_set_env_timeout;
-		dbenv->lock_detect = __lock_detect;
-		dbenv->lock_dump_region = __lock_dump_region;
-		dbenv->lock_get = __lock_get;
-		dbenv->lock_id = __lock_id;
-		dbenv->lock_id_free = __lock_id_free;
-#ifdef CONFIG_TEST
-		dbenv->lock_id_set = __lock_id_set;
-#endif
-		dbenv->lock_put = __lock_put;
-		dbenv->lock_stat = __lock_stat;
-		dbenv->lock_vec = __lock_vec;
-		dbenv->lock_downgrade = __lock_downgrade;
+
+		dbenv->lock_detect = __lock_detect_pp;
+		dbenv->lock_get = __lock_get_pp;
+		dbenv->lock_id = __lock_id_pp;
+		dbenv->lock_id_free = __lock_id_free_pp;
+		dbenv->lock_put = __lock_put_pp;
+		dbenv->lock_stat = __lock_stat_pp;
+		dbenv->lock_stat_print = __lock_stat_print_pp;
+		dbenv->lock_vec = __lock_vec_pp;
 	}
 }
 
@@ -104,9 +114,9 @@ __lock_dbenv_create(dbenv)
  * __lock_dbenv_close --
  *	Lock specific destruction of the DB_ENV structure.
  *
- * PUBLIC: void __lock_dbenv_close __P((DB_ENV *));
+ * PUBLIC: int __lock_dbenv_close __P((DB_ENV *));
  */
-void
+int
 __lock_dbenv_close(dbenv)
 	DB_ENV *dbenv;
 {
@@ -114,6 +124,38 @@ __lock_dbenv_close(dbenv)
 		__os_free(dbenv, dbenv->lk_conflicts);
 		dbenv->lk_conflicts = NULL;
 	}
+
+	return (0);
+}
+
+/*
+ * __lock_get_lk_conflicts
+ *	Get the conflicts matrix.
+ */
+static int
+__lock_get_lk_conflicts(dbenv, lk_conflictsp, lk_modesp)
+	DB_ENV *dbenv;
+	const u_int8_t **lk_conflictsp;
+	int *lk_modesp;
+{
+	ENV_NOT_CONFIGURED(dbenv,
+	    dbenv->lk_handle, "DB_ENV->get_lk_conflicts", DB_INIT_LOCK);
+
+	if (LOCKING_ON(dbenv)) {
+		/* Cannot be set after open, no lock required to read. */
+		if (lk_conflictsp != NULL)
+			*lk_conflictsp =
+			    ((DB_LOCKTAB *)dbenv->lk_handle)->conflicts;
+		if (lk_modesp != NULL)
+			*lk_modesp = ((DB_LOCKREGION *)((DB_LOCKTAB *)
+			    dbenv->lk_handle)->reginfo.primary)->stat.st_nmodes;
+	} else {
+		if (lk_conflictsp != NULL)
+			*lk_conflictsp = dbenv->lk_conflicts;
+		if (lk_modesp != NULL)
+			*lk_modesp = dbenv->lk_modes;
+	}
+	return (0);
 }
 
 /*
@@ -128,36 +170,66 @@ __lock_set_lk_conflicts(dbenv, lk_conflicts, lk_modes)
 {
 	int ret;
 
-	ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_lk_conflicts");
+	ENV_ILLEGAL_AFTER_OPEN(dbenv, "DB_ENV->set_lk_conflicts");
 
 	if (dbenv->lk_conflicts != NULL) {
 		__os_free(dbenv, dbenv->lk_conflicts);
 		dbenv->lk_conflicts = NULL;
 	}
 	if ((ret = __os_malloc(dbenv,
-	    lk_modes * lk_modes, &dbenv->lk_conflicts)) != 0)
+	    (size_t)(lk_modes * lk_modes), &dbenv->lk_conflicts)) != 0)
 		return (ret);
-	memcpy(dbenv->lk_conflicts, lk_conflicts, lk_modes * lk_modes);
+	memcpy(
+	    dbenv->lk_conflicts, lk_conflicts, (size_t)(lk_modes * lk_modes));
 	dbenv->lk_modes = lk_modes;
 
 	return (0);
 }
 
+static int
+__lock_get_lk_detect(dbenv, lk_detectp)
+	DB_ENV *dbenv;
+	u_int32_t *lk_detectp;
+{
+	DB_LOCKTAB *lt;
+
+	ENV_NOT_CONFIGURED(dbenv,
+	    dbenv->lk_handle, "DB_ENV->get_lk_detect", DB_INIT_LOCK);
+
+	if (LOCKING_ON(dbenv)) {
+		lt = dbenv->lk_handle;
+		LOCKREGION(dbenv, lt);
+		*lk_detectp = ((DB_LOCKREGION *)
+		    ((DB_LOCKTAB *)dbenv->lk_handle)->reginfo.primary)->detect;
+		UNLOCKREGION(dbenv, lt);
+	} else
+		*lk_detectp = dbenv->lk_detect;
+	return (0);
+}
+
 /*
  * __lock_set_lk_detect
- *	Set the automatic deadlock detection.
+ *	DB_ENV->set_lk_detect.
+ *
+ * PUBLIC: int __lock_set_lk_detect __P((DB_ENV *, u_int32_t));
  */
-static int
+int
 __lock_set_lk_detect(dbenv, lk_detect)
 	DB_ENV *dbenv;
 	u_int32_t lk_detect;
 {
-	ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_lk_detect");
+	DB_LOCKTAB *lt;
+	DB_LOCKREGION *region;
+	int ret;
+
+	ENV_NOT_CONFIGURED(dbenv,
+	    dbenv->lk_handle, "DB_ENV->set_lk_detect", DB_INIT_LOCK);
 
 	switch (lk_detect) {
 	case DB_LOCK_DEFAULT:
 	case DB_LOCK_EXPIRE:
 	case DB_LOCK_MAXLOCKS:
+	case DB_LOCK_MAXWRITE:
 	case DB_LOCK_MINLOCKS:
 	case DB_LOCK_MINWRITE:
 	case DB_LOCK_OLDEST:
@@ -169,20 +241,49 @@ __lock_set_lk_detect(dbenv, lk_detect)
 	    "DB_ENV->set_lk_detect: unknown deadlock detection mode specified");
 		return (EINVAL);
 	}
-	dbenv->lk_detect = lk_detect;
-	return (0);
+
+	ret = 0;
+	if (LOCKING_ON(dbenv)) {
+		lt = dbenv->lk_handle;
+		region = lt->reginfo.primary;
+		LOCKREGION(dbenv, lt);
+		/*
+		 * Check for incompatible automatic deadlock detection requests.
+		 * There are scenarios where changing the detector configuration
+		 * is reasonable, but we disallow them guessing it is likely to
+		 * be an application error.
+		 *
+		 * We allow applications to turn on the lock detector, and we
+		 * ignore attempts to set it to the default or current value.
+		 */
+		if (region->detect != DB_LOCK_NORUN &&
+		    lk_detect != DB_LOCK_DEFAULT &&
+		    region->detect != lk_detect) {
+			__db_err(dbenv,
+	    "DB_ENV->set_lk_detect: incompatible deadlock detector mode");
+			ret = EINVAL;
+		} else
+			if (region->detect == DB_LOCK_NORUN)
+				region->detect = lk_detect;
+		UNLOCKREGION(dbenv, lt);
+	} else
+		dbenv->lk_detect = lk_detect;
+
+	return (ret);
 }
 
 /*
  * __lock_set_lk_max
- *	Set the lock table size.
+ *	DB_ENV->set_lk_max.
+ *
+ * PUBLIC: int __lock_set_lk_max __P((DB_ENV *, u_int32_t));
  */
-static int
+int
 __lock_set_lk_max(dbenv, lk_max)
 	DB_ENV *dbenv;
 	u_int32_t lk_max;
 {
-	ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_lk_max");
+	ENV_ILLEGAL_AFTER_OPEN(dbenv, "DB_ENV->set_lk_max");
 
 	dbenv->lk_max = lk_max;
 	dbenv->lk_max_objects = lk_max;
@@ -190,86 +291,208 @@ __lock_set_lk_max(dbenv, lk_max)
 	return (0);
 }
 
+static int
+__lock_get_lk_max_locks(dbenv, lk_maxp)
+	DB_ENV *dbenv;
+	u_int32_t *lk_maxp;
+{
+	ENV_NOT_CONFIGURED(dbenv,
+	    dbenv->lk_handle, "DB_ENV->get_lk_maxlocks", DB_INIT_LOCK);
+
+	if (LOCKING_ON(dbenv)) {
+		/* Cannot be set after open, no lock required to read. */
+		*lk_maxp = ((DB_LOCKREGION *)((DB_LOCKTAB *)
+		    dbenv->lk_handle)->reginfo.primary)->stat.st_maxlocks;
+	} else
+		*lk_maxp = dbenv->lk_max;
+	return (0);
+}
+
 /*
  * __lock_set_lk_max_locks
- *	Set the lock table size.
+ *	DB_ENV->set_lk_max_locks.
+ *
+ * PUBLIC: int __lock_set_lk_max_locks __P((DB_ENV *, u_int32_t));
  */
-static int
+int
 __lock_set_lk_max_locks(dbenv, lk_max)
 	DB_ENV *dbenv;
 	u_int32_t lk_max;
 {
-	ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_lk_max_locks");
+	ENV_ILLEGAL_AFTER_OPEN(dbenv, "DB_ENV->set_lk_max_locks");
 
 	dbenv->lk_max = lk_max;
 	return (0);
 }
 
+static int
+__lock_get_lk_max_lockers(dbenv, lk_maxp)
+	DB_ENV *dbenv;
+	u_int32_t *lk_maxp;
+{
+	ENV_NOT_CONFIGURED(dbenv,
+	    dbenv->lk_handle, "DB_ENV->get_lk_max_lockers", DB_INIT_LOCK);
+
+	if (LOCKING_ON(dbenv)) {
+		/* Cannot be set after open, no lock required to read. */
+		*lk_maxp = ((DB_LOCKREGION *)((DB_LOCKTAB *)
+		    dbenv->lk_handle)->reginfo.primary)->stat.st_maxlockers;
+	} else
+		*lk_maxp = dbenv->lk_max_lockers;
+	return (0);
+}
+
 /*
  * __lock_set_lk_max_lockers
- *	Set the lock table size.
+ *	DB_ENV->set_lk_max_lockers.
+ *
+ * PUBLIC: int __lock_set_lk_max_lockers __P((DB_ENV *, u_int32_t));
  */
-static int
+int
 __lock_set_lk_max_lockers(dbenv, lk_max)
 	DB_ENV *dbenv;
 	u_int32_t lk_max;
 {
-	ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_lk_max_lockers");
+	ENV_ILLEGAL_AFTER_OPEN(dbenv, "DB_ENV->set_lk_max_lockers");
 
 	dbenv->lk_max_lockers = lk_max;
 	return (0);
 }
 
+static int
+__lock_get_lk_max_objects(dbenv, lk_maxp)
+	DB_ENV *dbenv;
+	u_int32_t *lk_maxp;
+{
+	ENV_NOT_CONFIGURED(dbenv,
+	    dbenv->lk_handle, "DB_ENV->get_lk_max_objects", DB_INIT_LOCK);
+
+	if (LOCKING_ON(dbenv)) {
+		/* Cannot be set after open, no lock required to read. */
+		*lk_maxp = ((DB_LOCKREGION *)((DB_LOCKTAB *)
+		    dbenv->lk_handle)->reginfo.primary)->stat.st_maxobjects;
+	} else
+		*lk_maxp = dbenv->lk_max_objects;
+	return (0);
+}
+
 /*
  * __lock_set_lk_max_objects
- *	Set the lock table size.
+ *	DB_ENV->set_lk_max_objects.
+ *
+ * PUBLIC: int __lock_set_lk_max_objects __P((DB_ENV *, u_int32_t));
  */
-static int
+int
 __lock_set_lk_max_objects(dbenv, lk_max)
 	DB_ENV *dbenv;
 	u_int32_t lk_max;
 {
-	ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_lk_max_objects");
+	ENV_ILLEGAL_AFTER_OPEN(dbenv, "DB_ENV->set_lk_max_objects");
 
 	dbenv->lk_max_objects = lk_max;
 	return (0);
 }
 
+static int
+__lock_get_env_timeout(dbenv, timeoutp, flag)
+	DB_ENV *dbenv;
+	db_timeout_t *timeoutp;
+	u_int32_t flag;
+{
+	DB_LOCKTAB *lt;
+	DB_LOCKREGION *region;
+	int ret;
+
+	ENV_NOT_CONFIGURED(dbenv,
+	    dbenv->lk_handle, "DB_ENV->get_env_timeout", DB_INIT_LOCK);
+
+	ret = 0;
+	if (LOCKING_ON(dbenv)) {
+		lt = dbenv->lk_handle;
+		region = lt->reginfo.primary;
+		LOCKREGION(dbenv, lt);
+		switch (flag) {
+		case DB_SET_LOCK_TIMEOUT:
+			*timeoutp = region->lk_timeout;
+			break;
+		case DB_SET_TXN_TIMEOUT:
+			*timeoutp = region->tx_timeout;
+			break;
+		default:
+			ret = 1;
+			break;
+		}
+		UNLOCKREGION(dbenv, lt);
+	} else
+		switch (flag) {
+		case DB_SET_LOCK_TIMEOUT:
+			*timeoutp = dbenv->lk_timeout;
+			break;
+		case DB_SET_TXN_TIMEOUT:
+			*timeoutp = dbenv->tx_timeout;
+			break;
+		default:
+			ret = 1;
+			break;
+		}
+
+	if (ret)
+		ret = __db_ferr(dbenv, "DB_ENV->get_timeout", 0);
+
+	return (ret);
+}
+
 /*
  * __lock_set_env_timeout
- *	Set the lock environment timeout.
+ *	DB_ENV->set_lock_timeout.
+ *
+ * PUBLIC: int __lock_set_env_timeout __P((DB_ENV *, db_timeout_t, u_int32_t));
  */
-static int
+int
 __lock_set_env_timeout(dbenv, timeout, flags)
 	DB_ENV *dbenv;
 	db_timeout_t timeout;
 	u_int32_t flags;
 {
+	DB_LOCKTAB *lt;
 	DB_LOCKREGION *region;
+	int ret;
 
-	region = NULL;
-	if (F_ISSET(dbenv, DB_ENV_OPEN_CALLED)) {
-		if (!LOCKING_ON(dbenv))
-			return (__db_env_config(
-			    dbenv, "set_timeout", DB_INIT_LOCK));
-		region = ((DB_LOCKTAB *)dbenv->lk_handle)->reginfo.primary;
-	}
+	ENV_NOT_CONFIGURED(dbenv,
+	    dbenv->lk_handle, "DB_ENV->set_env_timeout", DB_INIT_LOCK);
 
-	switch (flags) {
-	case DB_SET_LOCK_TIMEOUT:
-		dbenv->lk_timeout = timeout;
-		if (region != NULL)
+	ret = 0;
+	if (LOCKING_ON(dbenv)) {
+		lt = dbenv->lk_handle;
+		region = lt->reginfo.primary;
+		LOCKREGION(dbenv, lt);
+		switch (flags) {
+		case DB_SET_LOCK_TIMEOUT:
 			region->lk_timeout = timeout;
-		break;
-	case DB_SET_TXN_TIMEOUT:
-		dbenv->tx_timeout = timeout;
-		if (region != NULL)
+			break;
+		case DB_SET_TXN_TIMEOUT:
 			region->tx_timeout = timeout;
-		break;
-	default:
-		return (__db_ferr(dbenv, "DB_ENV->set_timeout", 0));
-		/* NOTREACHED */
-	}
+			break;
+		default:
+			ret = 1;
+			break;
+		}
+		UNLOCKREGION(dbenv, lt);
+	} else
+		switch (flags) {
+		case DB_SET_LOCK_TIMEOUT:
+			dbenv->lk_timeout = timeout;
+			break;
+		case DB_SET_TXN_TIMEOUT:
+			dbenv->tx_timeout = timeout;
+			break;
+		default:
+			ret = 1;
+			break;
+		}
 
-	return (0);
+	if (ret)
+		ret = __db_ferr(dbenv, "DB_ENV->set_timeout", 0);
+
+	return (ret);
 }
diff --git a/storage/bdb/lock/lock_region.c b/storage/bdb/lock/lock_region.c
index 6df6937e873cdeac6b935bcda9f7eb3068f854ba..b03dc74f15ea935da7dcf72ecd317031d18b4cb6 100644
--- a/storage/bdb/lock/lock_region.c
+++ b/storage/bdb/lock/lock_region.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: lock_region.c,v 11.82 2004/10/15 16:59:42 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: lock_region.c,v 11.69 2002/08/06 05:05:22 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -21,7 +19,7 @@ static const char revid[] = "$Id: lock_region.c,v 11.69 2002/08/06 05:05:22 bost
 #include "dbinc/db_shash.h"
 #include "dbinc/lock.h"
 
-static int  __lock_init __P((DB_ENV *, DB_LOCKTAB *));
+static int  __lock_region_init __P((DB_ENV *, DB_LOCKTAB *));
 static size_t
 	    __lock_region_size __P((DB_ENV *));
 
@@ -83,9 +81,9 @@ __lock_open(dbenv)
 	lt->dbenv = dbenv;
 
 	/* Join/create the lock region. */
+	lt->reginfo.dbenv = dbenv;
 	lt->reginfo.type = REGION_TYPE_LOCK;
 	lt->reginfo.id = INVALID_REGION_ID;
-	lt->reginfo.mode = dbenv->db_mode;
 	lt->reginfo.flags = REGION_JOIN_OK;
 	if (F_ISSET(dbenv, DB_ENV_CREATE))
 		F_SET(&lt->reginfo, REGION_CREATE_OK);
@@ -95,15 +93,23 @@ __lock_open(dbenv)
 
 	/* If we created the region, initialize it. */
 	if (F_ISSET(&lt->reginfo, REGION_CREATE))
-		if ((ret = __lock_init(dbenv, lt)) != 0)
+		if ((ret = __lock_region_init(dbenv, lt)) != 0)
 			goto err;
 
 	/* Set the local addresses. */
 	region = lt->reginfo.primary =
 	    R_ADDR(&lt->reginfo, lt->reginfo.rp->primary);
 
-	/* Check for incompatible automatic deadlock detection requests. */
 	if (dbenv->lk_detect != DB_LOCK_NORUN) {
+		/*
+		 * Check for incompatible automatic deadlock detection requests.
+		 * There are scenarios where changing the detector configuration
+		 * is reasonable, but we disallow them guessing it is likely to
+		 * be an application error.
+		 *
+		 * We allow applications to turn on the lock detector, and we
+		 * ignore attempts to set it to the default or current value.
+		 */
 		if (region->detect != DB_LOCK_NORUN &&
 		    dbenv->lk_detect != DB_LOCK_DEFAULT &&
 		    region->detect != dbenv->lk_detect) {
@@ -112,12 +118,6 @@ __lock_open(dbenv)
 			ret = EINVAL;
 			goto err;
 		}
-
-		/*
-		 * Upgrade if our caller wants automatic detection, and it
-		 * was not currently being done, whether or not we created
-		 * the region.
-		 */
 		if (region->detect == DB_LOCK_NORUN)
 			region->detect = dbenv->lk_detect;
 	}
@@ -126,15 +126,15 @@ __lock_open(dbenv)
 	 * A process joining the region may have reset the lock and transaction
 	 * timeouts.
 	 */
-	 if (dbenv->lk_timeout != 0)
+	if (dbenv->lk_timeout != 0)
 		region->lk_timeout = dbenv->lk_timeout;
-	 if (dbenv->tx_timeout != 0)
+	if (dbenv->tx_timeout != 0)
 		region->tx_timeout = dbenv->tx_timeout;
 
 	/* Set remaining pointers into region. */
-	lt->conflicts = (u_int8_t *)R_ADDR(&lt->reginfo, region->conf_off);
-	lt->obj_tab = (DB_HASHTAB *)R_ADDR(&lt->reginfo, region->obj_off);
-	lt->locker_tab = (DB_HASHTAB *)R_ADDR(&lt->reginfo, region->locker_off);
+	lt->conflicts = R_ADDR(&lt->reginfo, region->conf_off);
+	lt->obj_tab = R_ADDR(&lt->reginfo, region->obj_off);
+	lt->locker_tab = R_ADDR(&lt->reginfo, region->locker_off);
 
 	R_UNLOCK(dbenv, &lt->reginfo);
 
@@ -152,11 +152,11 @@ err:	if (lt->reginfo.addr != NULL) {
 }
 
 /*
- * __lock_init --
+ * __lock_region_init --
  *	Initialize the lock region.
  */
 static int
-__lock_init(dbenv, lt)
+__lock_region_init(dbenv, lt)
 	DB_ENV *dbenv;
 	DB_LOCKTAB *lt;
 {
@@ -168,11 +168,11 @@ __lock_init(dbenv, lt)
 #ifdef HAVE_MUTEX_SYSTEM_RESOURCES
 	size_t maint_size;
 #endif
-	u_int32_t i, lk_modes;
+	u_int32_t i;
 	u_int8_t *addr;
-	int ret;
+	int lk_modes, ret;
 
-	if ((ret = __db_shalloc(lt->reginfo.addr,
+	if ((ret = __db_shalloc(&lt->reginfo,
 	    sizeof(DB_LOCKREGION), 0, &lt->reginfo.primary)) != 0)
 		goto mem_err;
 	lt->reginfo.rp->primary = R_OFFSET(&lt->reginfo, lt->reginfo.primary);
@@ -194,6 +194,7 @@ __lock_init(dbenv, lt)
 	}
 
 	region->need_dd = 0;
+	LOCK_SET_TIME_INVALID(&region->next_timeout);
 	region->detect = DB_LOCK_NORUN;
 	region->lk_timeout = dbenv->lk_timeout;
 	region->tx_timeout = dbenv->tx_timeout;
@@ -208,21 +209,21 @@ __lock_init(dbenv, lt)
 	region->stat.st_nmodes = lk_modes;
 
 	/* Allocate room for the conflict matrix and initialize it. */
-	if ((ret =
-	    __db_shalloc(lt->reginfo.addr, lk_modes * lk_modes, 0, &addr)) != 0)
+	if ((ret = __db_shalloc(
+	    &lt->reginfo, (size_t)(lk_modes * lk_modes), 0, &addr)) != 0)
 		goto mem_err;
-	memcpy(addr, lk_conflicts, lk_modes * lk_modes);
+	memcpy(addr, lk_conflicts, (size_t)(lk_modes * lk_modes));
 	region->conf_off = R_OFFSET(&lt->reginfo, addr);
 
 	/* Allocate room for the object hash table and initialize it. */
-	if ((ret = __db_shalloc(lt->reginfo.addr,
+	if ((ret = __db_shalloc(&lt->reginfo,
 	    region->object_t_size * sizeof(DB_HASHTAB), 0, &addr)) != 0)
 		goto mem_err;
 	__db_hashinit(addr, region->object_t_size);
 	region->obj_off = R_OFFSET(&lt->reginfo, addr);
 
 	/* Allocate room for the locker hash table and initialize it. */
-	if ((ret = __db_shalloc(lt->reginfo.addr,
+	if ((ret = __db_shalloc(&lt->reginfo,
 	    region->locker_t_size * sizeof(DB_HASHTAB), 0, &addr)) != 0)
 		goto mem_err;
 	__db_hashinit(addr, region->locker_t_size);
@@ -231,7 +232,7 @@ __lock_init(dbenv, lt)
 #ifdef	HAVE_MUTEX_SYSTEM_RESOURCES
 	maint_size = __lock_region_maint(dbenv);
 	/* Allocate room for the locker maintenance info and initialize it. */
-	if ((ret = __db_shalloc(lt->reginfo.addr,
+	if ((ret = __db_shalloc(&lt->reginfo,
 	    sizeof(REGMAINT) + maint_size, 0, &addr)) != 0)
 		goto mem_err;
 	__db_maintinit(&lt->reginfo, addr, maint_size);
@@ -245,13 +246,14 @@ __lock_init(dbenv, lt)
 	 */
 	SH_TAILQ_INIT(&region->free_locks);
 	for (i = 0; i < region->stat.st_maxlocks; ++i) {
-		if ((ret = __db_shalloc(lt->reginfo.addr,
+		if ((ret = __db_shalloc(&lt->reginfo,
 		    sizeof(struct __db_lock), MUTEX_ALIGN, &lp)) != 0)
 			goto mem_err;
 		lp->status = DB_LSTAT_FREE;
 		lp->gen = 0;
 		if ((ret = __db_mutex_setup(dbenv, &lt->reginfo, &lp->mutex,
-		    MUTEX_NO_RLOCK | MUTEX_SELF_BLOCK)) != 0)
+		    MUTEX_LOGICAL_LOCK | MUTEX_NO_RLOCK | MUTEX_SELF_BLOCK))
+		    != 0)
 			return (ret);
 		MUTEX_LOCK(dbenv, &lp->mutex);
 		SH_TAILQ_INSERT_HEAD(&region->free_locks, lp, links, __db_lock);
@@ -261,7 +263,7 @@ __lock_init(dbenv, lt)
 	SH_TAILQ_INIT(&region->dd_objs);
 	SH_TAILQ_INIT(&region->free_objs);
 	for (i = 0; i < region->stat.st_maxobjects; ++i) {
-		if ((ret = __db_shalloc(lt->reginfo.addr,
+		if ((ret = __db_shalloc(&lt->reginfo,
 		    sizeof(DB_LOCKOBJ), 0, &op)) != 0)
 			goto mem_err;
 		SH_TAILQ_INSERT_HEAD(
@@ -272,7 +274,7 @@ __lock_init(dbenv, lt)
 	SH_TAILQ_INIT(&region->lockers);
 	SH_TAILQ_INIT(&region->free_lockers);
 	for (i = 0; i < region->stat.st_maxlockers; ++i) {
-		if ((ret = __db_shalloc(lt->reginfo.addr,
+		if ((ret = __db_shalloc(&lt->reginfo,
 		    sizeof(DB_LOCKER), 0, &lidp)) != 0) {
 mem_err:		__db_err(dbenv,
 			    "Unable to allocate memory for the lock table");
@@ -287,8 +289,7 @@ mem_err:		__db_err(dbenv,
 
 /*
  * __lock_dbenv_refresh --
- *	Clean up after the lock system on a close or failed open.  Called
- * only from __dbenv_refresh.  (Formerly called __lock_close.)
+ *	Clean up after the lock system on a close or failed open.
  *
  * PUBLIC: int __lock_dbenv_refresh __P((DB_ENV *));
  */
@@ -296,17 +297,65 @@ int
 __lock_dbenv_refresh(dbenv)
 	DB_ENV *dbenv;
 {
+	struct __db_lock *lp;
+	DB_LOCKER *locker;
+	DB_LOCKOBJ *lockobj;
+	DB_LOCKREGION *lr;
 	DB_LOCKTAB *lt;
+	REGINFO *reginfo;
 	int ret;
 
 	lt = dbenv->lk_handle;
+	reginfo = &lt->reginfo;
+	lr = reginfo->primary;
+
+	/*
+	 * If a private region, return the memory to the heap.  Not needed for
+	 * filesystem-backed or system shared memory regions, that memory isn't
+	 * owned by any particular process.
+	 */
+	if (F_ISSET(dbenv, DB_ENV_PRIVATE)) {
+		/* Discard the conflict matrix. */
+		__db_shalloc_free(reginfo, R_ADDR(&lt->reginfo, lr->conf_off));
+
+		/* Discard the object hash table. */
+		__db_shalloc_free(reginfo, R_ADDR(&lt->reginfo, lr->obj_off));
+
+		/* Discard the locker hash table. */
+		__db_shalloc_free(
+		    reginfo, R_ADDR(&lt->reginfo, lr->locker_off));
+
+		/* Discard locks. */
+		while ((lp =
+		    SH_TAILQ_FIRST(&lr->free_locks, __db_lock)) != NULL) {
+			SH_TAILQ_REMOVE(&lr->free_locks, lp, links, __db_lock);
+			__db_shalloc_free(reginfo, lp);
+		}
+
+		/* Discard objects. */
+		while ((lockobj =
+		    SH_TAILQ_FIRST(&lr->free_objs, __db_lockobj)) != NULL) {
+			SH_TAILQ_REMOVE(
+			    &lr->free_objs, lockobj, links, __db_lockobj);
+			__db_shalloc_free(reginfo, lockobj);
+		}
+
+		/* Discard lockers. */
+		while ((locker =
+		    SH_TAILQ_FIRST(&lr->free_lockers, __db_locker)) != NULL) {
+			SH_TAILQ_REMOVE(
+			    &lr->free_lockers, locker, links, __db_locker);
+			__db_shalloc_free(reginfo, locker);
+		}
+	}
 
 	/* Detach from the region. */
-	ret = __db_r_detach(dbenv, &lt->reginfo, 0);
+	ret = __db_r_detach(dbenv, reginfo, 0);
 
+	/* Discard DB_LOCKTAB. */
 	__os_free(dbenv, lt);
-
 	dbenv->lk_handle = NULL;
+
 	return (ret);
 }
 
@@ -322,25 +371,26 @@ __lock_region_size(dbenv)
 
 	/*
 	 * Figure out how much space we're going to need.  This list should
-	 * map one-to-one with the __db_shalloc calls in __lock_init.
+	 * map one-to-one with the __db_shalloc calls in __lock_region_init.
 	 */
 	retval = 0;
-	retval += __db_shalloc_size(sizeof(DB_LOCKREGION), 1);
-	retval += __db_shalloc_size(dbenv->lk_modes * dbenv->lk_modes, 1);
-	retval += __db_shalloc_size(
-	    __db_tablesize(dbenv->lk_max_lockers) * (sizeof(DB_HASHTAB)), 1);
+	retval += __db_shalloc_size(sizeof(DB_LOCKREGION), 0);
 	retval += __db_shalloc_size(
-	    __db_tablesize(dbenv->lk_max_objects) * (sizeof(DB_HASHTAB)), 1);
+	    (size_t)(dbenv->lk_modes * dbenv->lk_modes), 0);
+	retval += __db_shalloc_size(__db_tablesize
+	    (dbenv->lk_max_lockers) * (sizeof(DB_HASHTAB)), 0);
+	retval += __db_shalloc_size(__db_tablesize
+	    (dbenv->lk_max_objects) * (sizeof(DB_HASHTAB)), 0);
 #ifdef HAVE_MUTEX_SYSTEM_RESOURCES
 	retval +=
-	    __db_shalloc_size(sizeof(REGMAINT) + __lock_region_maint(dbenv), 1);
+	    __db_shalloc_size(sizeof(REGMAINT) + __lock_region_maint(dbenv), 0);
 #endif
-	retval += __db_shalloc_size(
-	    sizeof(struct __db_lock), MUTEX_ALIGN) * dbenv->lk_max;
-	retval += __db_shalloc_size(
-	    sizeof(DB_LOCKOBJ), 1) * dbenv->lk_max_objects;
-	retval += __db_shalloc_size(
-	    sizeof(DB_LOCKER), 1) * dbenv->lk_max_lockers;
+	retval += __db_shalloc_size
+	    (sizeof(struct __db_lock), MUTEX_ALIGN) * dbenv->lk_max;
+	retval +=
+	    __db_shalloc_size(sizeof(DB_LOCKOBJ), 1) * dbenv->lk_max_objects;
+	retval +=
+	    __db_shalloc_size(sizeof(DB_LOCKER), 1) * dbenv->lk_max_lockers;
 
 	/*
 	 * Include 16 bytes of string space per lock.  DB doesn't use it
@@ -381,37 +431,23 @@ __lock_region_destroy(dbenv, infop)
 	DB_ENV *dbenv;
 	REGINFO *infop;
 {
-	__db_shlocks_destroy(infop, (REGMAINT *)R_ADDR(infop,
-	    ((DB_LOCKREGION *)R_ADDR(infop, infop->rp->primary))->maint_off));
-
-	COMPQUIET(dbenv, NULL);
-	COMPQUIET(infop, NULL);
-}
-
-#ifdef CONFIG_TEST
-/*
- * __lock_id_set --
- *	Set the current locker ID and current maximum unused ID (for
- *	testing purposes only).
- *
- * PUBLIC: int __lock_id_set __P((DB_ENV *, u_int32_t, u_int32_t));
- */
-int
-__lock_id_set(dbenv, cur_id, max_id)
-	DB_ENV *dbenv;
-	u_int32_t cur_id, max_id;
-{
-	DB_LOCKTAB *lt;
-	DB_LOCKREGION *region;
+	/*
+	 * This routine is called in two cases: when discarding the mutexes
+	 * from a previous Berkeley DB run, during recovery, and two, when
+	 * discarding the mutexes as we shut down the database environment.
+	 * In the latter case, we also need to discard shared memory segments,
+	 * this is the last time we use them, and the last region-specific
+	 * call we make.
+	 */
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
+	DB_LOCKREGION *lt;
 
-	ENV_REQUIRES_CONFIG(dbenv,
-	    dbenv->lk_handle, "lock_id_set", DB_INIT_LOCK);
+	lt = R_ADDR(infop, infop->rp->primary);
 
-	lt = dbenv->lk_handle;
-	region = lt->reginfo.primary;
-	region->stat.st_id = cur_id;
-	region->stat.st_cur_maxid = max_id;
-
-	return (0);
-}
+	__db_shlocks_destroy(infop, R_ADDR(infop, lt->maint_off));
+	if (infop->primary != NULL && F_ISSET(dbenv, DB_ENV_PRIVATE))
+		__db_shalloc_free(infop, R_ADDR(infop, lt->maint_off));
 #endif
+	if (infop->primary != NULL && F_ISSET(dbenv, DB_ENV_PRIVATE))
+		__db_shalloc_free(infop, infop->primary);
+}
diff --git a/storage/bdb/lock/lock_stat.c b/storage/bdb/lock/lock_stat.c
index 0bef3e18021bd8475c66e863c46ff8a6107cb1f2..7cf56bb90ce6079730e3f04e1141487c8d8a8a34 100644
--- a/storage/bdb/lock/lock_stat.c
+++ b/storage/bdb/lock/lock_stat.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: lock_stat.c,v 11.64 2004/10/15 16:59:42 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: lock_stat.c,v 11.32 2002/08/14 20:08:51 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #include <string.h>
@@ -35,36 +33,62 @@ static const char revid[] = "$Id: lock_stat.c,v 11.32 2002/08/14 20:08:51 bostic
 #include "dbinc/log.h"
 #include "dbinc/db_am.h"
 
-static void __lock_dump_locker __P((DB_LOCKTAB *, DB_LOCKER *, FILE *));
-static void __lock_dump_object __P((DB_LOCKTAB *, DB_LOCKOBJ *, FILE *));
-static void __lock_printheader __P((void));
+#ifdef HAVE_STATISTICS
+static void __lock_dump_locker
+		__P((DB_ENV *, DB_MSGBUF *, DB_LOCKTAB *, DB_LOCKER *));
+static void __lock_dump_object __P((DB_LOCKTAB *, DB_MSGBUF *, DB_LOCKOBJ *));
+static int  __lock_print_all __P((DB_ENV *, u_int32_t));
+static int  __lock_print_stats __P((DB_ENV *, u_int32_t));
+static void __lock_print_header __P((DB_ENV *));
+static int  __lock_stat __P((DB_ENV *, DB_LOCK_STAT **, u_int32_t));
 
 /*
- * __lock_stat --
- *	Return LOCK statistics.
+ * __lock_stat_pp --
+ *	DB_ENV->lock_stat pre/post processing.
  *
- * PUBLIC: int __lock_stat __P((DB_ENV *, DB_LOCK_STAT **, u_int32_t));
+ * PUBLIC: int __lock_stat_pp __P((DB_ENV *, DB_LOCK_STAT **, u_int32_t));
  */
 int
-__lock_stat(dbenv, statp, flags)
+__lock_stat_pp(dbenv, statp, flags)
 	DB_ENV *dbenv;
 	DB_LOCK_STAT **statp;
 	u_int32_t flags;
 {
-	DB_LOCKREGION *region;
-	DB_LOCKTAB *lt;
-	DB_LOCK_STAT *stats, tmp;
-	int ret;
+	int rep_check, ret;
 
 	PANIC_CHECK(dbenv);
 	ENV_REQUIRES_CONFIG(dbenv,
 	    dbenv->lk_handle, "DB_ENV->lock_stat", DB_INIT_LOCK);
 
-	*statp = NULL;
 	if ((ret = __db_fchk(dbenv,
 	    "DB_ENV->lock_stat", flags, DB_STAT_CLEAR)) != 0)
 		return (ret);
 
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __lock_stat(dbenv, statp, flags);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
+/*
+ * __lock_stat --
+ *	DB_ENV->lock_stat.
+ */
+static int
+__lock_stat(dbenv, statp, flags)
+	DB_ENV *dbenv;
+	DB_LOCK_STAT **statp;
+	u_int32_t flags;
+{
+	DB_LOCKREGION *region;
+	DB_LOCKTAB *lt;
+	DB_LOCK_STAT *stats, tmp;
+	int ret;
+
+	*statp = NULL;
 	lt = dbenv->lk_handle;
 
 	if ((ret = __os_umalloc(dbenv, sizeof(*stats), &stats)) != 0)
@@ -84,8 +108,7 @@ __lock_stat(dbenv, statp, flags)
 	if (LF_ISSET(DB_STAT_CLEAR)) {
 		tmp = region->stat;
 		memset(&region->stat, 0, sizeof(region->stat));
-		lt->reginfo.rp->mutex.mutex_set_wait = 0;
-		lt->reginfo.rp->mutex.mutex_set_nowait = 0;
+		MUTEX_CLEAR(&lt->reginfo.rp->mutex);
 
 		region->stat.st_id = tmp.st_id;
 		region->stat.st_cur_maxid = tmp.st_cur_maxid;
@@ -107,163 +130,266 @@ __lock_stat(dbenv, statp, flags)
 	return (0);
 }
 
-#define	LOCK_DUMP_CONF		0x001		/* Conflict matrix. */
-#define	LOCK_DUMP_LOCKERS	0x002		/* Display lockers. */
-#define	LOCK_DUMP_MEM		0x004		/* Display region memory. */
-#define	LOCK_DUMP_OBJECTS	0x008		/* Display objects. */
-#define	LOCK_DUMP_PARAMS	0x010		/* Display params. */
-#define	LOCK_DUMP_ALL				/* All */		\
-	(LOCK_DUMP_CONF | LOCK_DUMP_LOCKERS | LOCK_DUMP_MEM |		\
-	LOCK_DUMP_OBJECTS | LOCK_DUMP_PARAMS)
+/*
+ * __lock_stat_print_pp --
+ *	DB_ENV->lock_stat_print pre/post processing.
+ *
+ * PUBLIC: int __lock_stat_print_pp __P((DB_ENV *, u_int32_t));
+ */
+int
+__lock_stat_print_pp(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	int rep_check, ret;
+
+	PANIC_CHECK(dbenv);
+	ENV_REQUIRES_CONFIG(dbenv,
+	    dbenv->lk_handle, "DB_ENV->lock_stat_print", DB_INIT_LOCK);
+
+#define	DB_STAT_LOCK_FLAGS						\
+	(DB_STAT_ALL | DB_STAT_CLEAR | DB_STAT_LOCK_CONF |		\
+	 DB_STAT_LOCK_LOCKERS |	DB_STAT_LOCK_OBJECTS | DB_STAT_LOCK_PARAMS)
+	if ((ret = __db_fchk(dbenv, "DB_ENV->lock_stat_print",
+	    flags, DB_STAT_CLEAR | DB_STAT_LOCK_FLAGS)) != 0)
+		return (ret);
+
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __lock_stat_print(dbenv, flags);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
 
 /*
- * __lock_dump_region --
+ * __lock_stat_print --
+ *	DB_ENV->lock_stat_print method.
  *
- * PUBLIC: int __lock_dump_region __P((DB_ENV *, char *, FILE *));
+ * PUBLIC: int  __lock_stat_print __P((DB_ENV *, u_int32_t));
  */
 int
-__lock_dump_region(dbenv, area, fp)
+__lock_stat_print(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	u_int32_t orig_flags;
+	int ret;
+
+	orig_flags = flags;
+	LF_CLR(DB_STAT_CLEAR);
+	if (flags == 0 || LF_ISSET(DB_STAT_ALL)) {
+		ret = __lock_print_stats(dbenv, orig_flags);
+		if (flags == 0 || ret != 0)
+			return (ret);
+	}
+
+	if (LF_ISSET(DB_STAT_ALL | DB_STAT_LOCK_CONF | DB_STAT_LOCK_LOCKERS |
+	    DB_STAT_LOCK_OBJECTS | DB_STAT_LOCK_PARAMS) &&
+	    (ret = __lock_print_all(dbenv, orig_flags)) != 0)
+		return (ret);
+
+	return (0);
+}
+
+/*
+ * __lock_print_stats --
+ *	Display default lock region statistics.
+ */
+static int
+__lock_print_stats(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	DB_LOCK_STAT *sp;
+	int ret;
+
+	if ((ret = __lock_stat(dbenv, &sp, flags)) != 0)
+		return (ret);
+
+	if (LF_ISSET(DB_STAT_ALL))
+		__db_msg(dbenv, "Default locking region information:");
+	__db_dl(dbenv, "Last allocated locker ID", (u_long)sp->st_id);
+	__db_msg(dbenv, "%#lx\tCurrent maximum unused locker ID",
+	    (u_long)sp->st_cur_maxid);
+	__db_dl(dbenv, "Number of lock modes", (u_long)sp->st_nmodes);
+	__db_dl(dbenv,
+	    "Maximum number of locks possible", (u_long)sp->st_maxlocks);
+	__db_dl(dbenv,
+	    "Maximum number of lockers possible", (u_long)sp->st_maxlockers);
+	__db_dl(dbenv, "Maximum number of lock objects possible",
+	    (u_long)sp->st_maxobjects);
+	__db_dl(dbenv, "Number of current locks", (u_long)sp->st_nlocks);
+	__db_dl(dbenv, "Maximum number of locks at any one time",
+	    (u_long)sp->st_maxnlocks);
+	__db_dl(dbenv, "Number of current lockers", (u_long)sp->st_nlockers);
+	__db_dl(dbenv, "Maximum number of lockers at any one time",
+	    (u_long)sp->st_maxnlockers);
+	__db_dl(dbenv,
+	    "Number of current lock objects", (u_long)sp->st_nobjects);
+	__db_dl(dbenv, "Maximum number of lock objects at any one time",
+	    (u_long)sp->st_maxnobjects);
+	__db_dl(dbenv,
+	    "Total number of locks requested", (u_long)sp->st_nrequests);
+	__db_dl(dbenv,
+	    "Total number of locks released", (u_long)sp->st_nreleases);
+	__db_dl(dbenv,
+  "Total number of lock requests failing because DB_LOCK_NOWAIT was set",
+	    (u_long)sp->st_nnowaits);
+	__db_dl(dbenv,
+  "Total number of locks not immediately available due to conflicts",
+	    (u_long)sp->st_nconflicts);
+	__db_dl(dbenv, "Number of deadlocks", (u_long)sp->st_ndeadlocks);
+	__db_dl(dbenv, "Lock timeout value", (u_long)sp->st_locktimeout);
+	__db_dl(dbenv, "Number of locks that have timed out",
+	    (u_long)sp->st_nlocktimeouts);
+	__db_dl(dbenv,
+	    "Transaction timeout value", (u_long)sp->st_txntimeout);
+	__db_dl(dbenv, "Number of transactions that have timed out",
+	    (u_long)sp->st_ntxntimeouts);
+
+	__db_dlbytes(dbenv, "The size of the lock region",
+	    (u_long)0, (u_long)0, (u_long)sp->st_regsize);
+	__db_dl_pct(dbenv,
+	    "The number of region locks that required waiting",
+	    (u_long)sp->st_region_wait, DB_PCT(sp->st_region_wait,
+	    sp->st_region_wait + sp->st_region_nowait), NULL);
+
+	__os_ufree(dbenv, sp);
+
+	return (0);
+}
+
+/*
+ * __lock_print_all --
+ *	Display debugging lock region statistics.
+ */
+static int
+__lock_print_all(dbenv, flags)
 	DB_ENV *dbenv;
-	char *area;
-	FILE *fp;
+	u_int32_t flags;
 {
 	DB_LOCKER *lip;
 	DB_LOCKOBJ *op;
 	DB_LOCKREGION *lrp;
 	DB_LOCKTAB *lt;
-	u_int32_t flags, i, j;
-
-	PANIC_CHECK(dbenv);
-	ENV_REQUIRES_CONFIG(dbenv,
-	    dbenv->lk_handle, "lock_dump_region", DB_INIT_LOCK);
-
-	/* Make it easy to call from the debugger. */
-	if (fp == NULL)
-		fp = stderr;
-
-	for (flags = 0; *area != '\0'; ++area)
-		switch (*area) {
-		case 'A':
-			LF_SET(LOCK_DUMP_ALL);
-			break;
-		case 'c':
-			LF_SET(LOCK_DUMP_CONF);
-			break;
-		case 'l':
-			LF_SET(LOCK_DUMP_LOCKERS);
-			break;
-		case 'm':
-			LF_SET(LOCK_DUMP_MEM);
-			break;
-		case 'o':
-			LF_SET(LOCK_DUMP_OBJECTS);
-			break;
-		case 'p':
-			LF_SET(LOCK_DUMP_PARAMS);
-			break;
-		}
+	DB_MSGBUF mb;
+	int i, j;
+	u_int32_t k;
+	char buf[64];
 
 	lt = dbenv->lk_handle;
 	lrp = lt->reginfo.primary;
+	DB_MSGBUF_INIT(&mb);
+
 	LOCKREGION(dbenv, lt);
 
-	if (LF_ISSET(LOCK_DUMP_PARAMS)) {
-		fprintf(fp, "%s\nLock region parameters\n", DB_LINE);
-		fprintf(fp,
-	    "%s: %lu, %s: %lu, %s: %lu,\n%s: %lu, %s: %lu, %s: %lu, %s: %lu\n",
-		    "locker table size", (u_long)lrp->locker_t_size,
-		    "object table size", (u_long)lrp->object_t_size,
-		    "obj_off", (u_long)lrp->obj_off,
-		    "osynch_off", (u_long)lrp->osynch_off,
-		    "locker_off", (u_long)lrp->locker_off,
-		    "lsynch_off", (u_long)lrp->lsynch_off,
-		    "need_dd", (u_long)lrp->need_dd);
+	__db_print_reginfo(dbenv, &lt->reginfo, "Lock");
+
+	if (LF_ISSET(DB_STAT_ALL | DB_STAT_LOCK_PARAMS)) {
+		__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+		__db_msg(dbenv, "Lock region parameters:");
+		STAT_ULONG("locker table size", lrp->locker_t_size);
+		STAT_ULONG("object table size", lrp->object_t_size);
+		STAT_ULONG("obj_off", lrp->obj_off);
+		STAT_ULONG("osynch_off", lrp->osynch_off);
+		STAT_ULONG("locker_off", lrp->locker_off);
+		STAT_ULONG("lsynch_off", lrp->lsynch_off);
+		STAT_ULONG("need_dd", lrp->need_dd);
+		if (LOCK_TIME_ISVALID(&lrp->next_timeout) &&
+		    strftime(buf, sizeof(buf), "%m-%d-%H:%M:%S",
+		    localtime((time_t*)&lrp->next_timeout.tv_sec)) != 0)
+			__db_msg(dbenv, "next_timeout: %s.%lu",
+			     buf, (u_long)lrp->next_timeout.tv_usec);
 	}
 
-	if (LF_ISSET(LOCK_DUMP_CONF)) {
-		fprintf(fp, "\n%s\nConflict matrix\n", DB_LINE);
+	if (LF_ISSET(DB_STAT_ALL | DB_STAT_LOCK_CONF)) {
+		__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+		__db_msg(dbenv, "Lock conflict matrix:");
 		for (i = 0; i < lrp->stat.st_nmodes; i++) {
 			for (j = 0; j < lrp->stat.st_nmodes; j++)
-				fprintf(fp, "%lu\t", (u_long)
+				__db_msgadd(dbenv, &mb, "%lu\t", (u_long)
 				    lt->conflicts[i * lrp->stat.st_nmodes + j]);
-			fprintf(fp, "\n");
+			DB_MSGBUF_FLUSH(dbenv, &mb);
 		}
 	}
 
-	if (LF_ISSET(LOCK_DUMP_LOCKERS)) {
-		fprintf(fp, "%s\nLocks grouped by lockers\n", DB_LINE);
-		__lock_printheader();
-		for (i = 0; i < lrp->locker_t_size; i++)
+	if (LF_ISSET(DB_STAT_ALL | DB_STAT_LOCK_LOCKERS)) {
+		__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+		__db_msg(dbenv, "Locks grouped by lockers:");
+		__lock_print_header(dbenv);
+		for (k = 0; k < lrp->locker_t_size; k++)
 			for (lip =
-			    SH_TAILQ_FIRST(&lt->locker_tab[i], __db_locker);
+			    SH_TAILQ_FIRST(&lt->locker_tab[k], __db_locker);
 			    lip != NULL;
 			    lip = SH_TAILQ_NEXT(lip, links, __db_locker)) {
-				__lock_dump_locker(lt, lip, fp);
+				__lock_dump_locker(dbenv, &mb, lt, lip);
 			}
 	}
 
-	if (LF_ISSET(LOCK_DUMP_OBJECTS)) {
-		fprintf(fp, "%s\nLocks grouped by object\n", DB_LINE);
-		__lock_printheader();
-		for (i = 0; i < lrp->object_t_size; i++) {
-			for (op = SH_TAILQ_FIRST(&lt->obj_tab[i], __db_lockobj);
+	if (LF_ISSET(DB_STAT_ALL | DB_STAT_LOCK_OBJECTS)) {
+		__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+		__db_msg(dbenv, "Locks grouped by object:");
+		__lock_print_header(dbenv);
+		for (k = 0; k < lrp->object_t_size; k++) {
+			for (op = SH_TAILQ_FIRST(&lt->obj_tab[k], __db_lockobj);
 			    op != NULL;
-			    op = SH_TAILQ_NEXT(op, links, __db_lockobj))
-				__lock_dump_object(lt, op, fp);
+			    op = SH_TAILQ_NEXT(op, links, __db_lockobj)) {
+				__lock_dump_object(lt, &mb, op);
+				__db_msg(dbenv, "%s", "");
+			}
 		}
 	}
-
-	if (LF_ISSET(LOCK_DUMP_MEM))
-		__db_shalloc_dump(lt->reginfo.addr, fp);
-
 	UNLOCKREGION(dbenv, lt);
 
 	return (0);
 }
 
 static void
-__lock_dump_locker(lt, lip, fp)
+__lock_dump_locker(dbenv, mbp, lt, lip)
+	DB_ENV *dbenv;
+	DB_MSGBUF *mbp;
 	DB_LOCKTAB *lt;
 	DB_LOCKER *lip;
-	FILE *fp;
 {
 	struct __db_lock *lp;
 	time_t s;
 	char buf[64];
 
-	fprintf(fp, "%8lx dd=%2ld locks held %-4d write locks %-4d",
+	__db_msgadd(dbenv,
+	    mbp, "%8lx dd=%2ld locks held %-4d write locks %-4d",
 	    (u_long)lip->id, (long)lip->dd_id, lip->nlocks, lip->nwrites);
-	fprintf(fp, " %s ", F_ISSET(lip, DB_LOCKER_DELETED) ? "(D)" : "   ");
+	__db_msgadd(
+	    dbenv, mbp, "%s", F_ISSET(lip, DB_LOCKER_DELETED) ? "(D)" : "   ");
 	if (LOCK_TIME_ISVALID(&lip->tx_expire)) {
-		s = lip->tx_expire.tv_sec;
-		strftime(buf, sizeof(buf), "%m-%d-%H:%M:%S", localtime(&s));
-		fprintf(fp,
-		    " expires %s.%lu", buf, (u_long)lip->tx_expire.tv_usec);
+		s = (time_t)lip->tx_expire.tv_sec;
+		if (strftime(buf,
+		    sizeof(buf), "%m-%d-%H:%M:%S", localtime(&s)) != 0)
+			__db_msgadd(dbenv, mbp, "expires %s.%lu",
+			    buf, (u_long)lip->tx_expire.tv_usec);
 	}
 	if (F_ISSET(lip, DB_LOCKER_TIMEOUT))
-		fprintf(fp, " lk timeout %u", lip->lk_timeout);
+		__db_msgadd(dbenv, mbp, " lk timeout %u", lip->lk_timeout);
 	if (LOCK_TIME_ISVALID(&lip->lk_expire)) {
-		s = lip->lk_expire.tv_sec;
-		strftime(buf, sizeof(buf), "%m-%d-%H:%M:%S", localtime(&s));
-		fprintf(fp,
-		    " lk expires %s.%lu", buf, (u_long)lip->lk_expire.tv_usec);
-	}
-	fprintf(fp, "\n");
-
-	lp = SH_LIST_FIRST(&lip->heldby, __db_lock);
-	if (lp != NULL) {
-		for (; lp != NULL;
-		    lp = SH_LIST_NEXT(lp, locker_links, __db_lock))
-			__lock_printlock(lt, lp, 1);
-		fprintf(fp, "\n");
+		s = (time_t)lip->lk_expire.tv_sec;
+		if (strftime(buf,
+		    sizeof(buf), "%m-%d-%H:%M:%S", localtime(&s)) != 0)
+			__db_msgadd(dbenv, mbp, " lk expires %s.%lu",
+			    buf, (u_long)lip->lk_expire.tv_usec);
 	}
+	DB_MSGBUF_FLUSH(dbenv, mbp);
+
+	for (lp = SH_LIST_FIRST(&lip->heldby, __db_lock);
+	    lp != NULL; lp = SH_LIST_NEXT(lp, locker_links, __db_lock))
+		__lock_printlock(lt, mbp, lp, 1);
 }
 
 static void
-__lock_dump_object(lt, op, fp)
+__lock_dump_object(lt, mbp, op)
 	DB_LOCKTAB *lt;
+	DB_MSGBUF *mbp;
 	DB_LOCKOBJ *op;
-	FILE *fp;
 {
 	struct __db_lock *lp;
 
@@ -271,45 +397,55 @@ __lock_dump_object(lt, op, fp)
 	    SH_TAILQ_FIRST(&op->holders, __db_lock);
 	    lp != NULL;
 	    lp = SH_TAILQ_NEXT(lp, links, __db_lock))
-		__lock_printlock(lt, lp, 1);
+		__lock_printlock(lt, mbp, lp, 1);
 	for (lp =
 	    SH_TAILQ_FIRST(&op->waiters, __db_lock);
 	    lp != NULL;
 	    lp = SH_TAILQ_NEXT(lp, links, __db_lock))
-		__lock_printlock(lt, lp, 1);
-
-	fprintf(fp, "\n");
+		__lock_printlock(lt, mbp, lp, 1);
 }
 
 /*
- * __lock_printheader --
+ * __lock_print_header --
  */
 static void
-__lock_printheader()
+__lock_print_header(dbenv)
+	DB_ENV *dbenv;
 {
-	printf("%-8s  %-6s  %-6s  %-10s  %s\n",
+	__db_msg(dbenv, "%-8s %-10s%-4s %-7s %s",
 	    "Locker", "Mode",
-	    "Count", "Status", "----------- Object ----------");
+	    "Count", "Status", "----------------- Object ---------------");
 }
 
 /*
  * __lock_printlock --
  *
- * PUBLIC: void __lock_printlock __P((DB_LOCKTAB *, struct __db_lock *, int));
+ * PUBLIC: void __lock_printlock
+ * PUBLIC:     __P((DB_LOCKTAB *, DB_MSGBUF *mbp, struct __db_lock *, int));
  */
 void
-__lock_printlock(lt, lp, ispgno)
+__lock_printlock(lt, mbp, lp, ispgno)
 	DB_LOCKTAB *lt;
+	DB_MSGBUF *mbp;
 	struct __db_lock *lp;
 	int ispgno;
 {
+	DB_ENV *dbenv;
 	DB_LOCKOBJ *lockobj;
+	DB_MSGBUF mb;
 	db_pgno_t pgno;
 	u_int32_t *fidp, type;
 	u_int8_t *ptr;
 	char *namep;
 	const char *mode, *status;
 
+	dbenv = lt->dbenv;
+
+	if (mbp == NULL) {
+		DB_MSGBUF_INIT(&mb);
+		mbp = &mb;
+	}
+
 	switch (lp->mode) {
 	case DB_LOCK_DIRTY:
 		mode = "DIRTY_READ";
@@ -346,8 +482,8 @@ __lock_printlock(lt, lp, ispgno)
 	case DB_LSTAT_ABORTED:
 		status = "ABORT";
 		break;
-	case DB_LSTAT_ERR:
-		status = "ERROR";
+	case DB_LSTAT_EXPIRED:
+		status = "EXPIRED";
 		break;
 	case DB_LSTAT_FREE:
 		status = "FREE";
@@ -355,20 +491,20 @@ __lock_printlock(lt, lp, ispgno)
 	case DB_LSTAT_HELD:
 		status = "HELD";
 		break;
-	case DB_LSTAT_WAITING:
-		status = "WAIT";
+	case DB_LSTAT_NOTEXIST:
+		status = "NOTEXIST";
 		break;
 	case DB_LSTAT_PENDING:
 		status = "PENDING";
 		break;
-	case DB_LSTAT_EXPIRED:
-		status = "EXPIRED";
+	case DB_LSTAT_WAITING:
+		status = "WAIT";
 		break;
 	default:
 		status = "UNKNOWN";
 		break;
 	}
-	printf("%8lx  %-6s  %6lu  %-10s  ",
+	__db_msgadd(dbenv, mbp, "%8lx %-10s %4lu %-7s ",
 	    (u_long)lp->holder, mode, (u_long)lp->refcount, status);
 
 	lockobj = (DB_LOCKOBJ *)((u_int8_t *)lp + lp->obj);
@@ -381,18 +517,44 @@ __lock_printlock(lt, lp, ispgno)
 		if (__dbreg_get_name(lt->dbenv, (u_int8_t *)fidp, &namep) != 0)
 			namep = NULL;
 		if (namep == NULL)
-			printf("(%lx %lx %lx %lx %lx)",
-			(u_long)fidp[0], (u_long)fidp[1], (u_long)fidp[2],
-			(u_long)fidp[3], (u_long)fidp[4]);
+			__db_msgadd(dbenv, mbp, "(%lx %lx %lx %lx %lx) ",
+			    (u_long)fidp[0], (u_long)fidp[1], (u_long)fidp[2],
+			    (u_long)fidp[3], (u_long)fidp[4]);
 		else
-			printf("%-20s", namep);
-		printf("%-7s  %lu\n",
+			__db_msgadd(dbenv, mbp, "%-25s ", namep);
+		__db_msgadd(dbenv, mbp, "%-7s %7lu",
 			type == DB_PAGE_LOCK ? "page" :
 			type == DB_RECORD_LOCK ? "record" : "handle",
 			(u_long)pgno);
 	} else {
-		printf("0x%lx ", (u_long)R_OFFSET(&lt->reginfo, lockobj));
-		__db_pr(ptr, lockobj->lockobj.size, stdout);
-		printf("\n");
+		__db_msgadd(dbenv, mbp, "0x%lx ",
+		    (u_long)R_OFFSET(&lt->reginfo, lockobj));
+		__db_pr(dbenv, mbp, ptr, lockobj->lockobj.size);
 	}
+	DB_MSGBUF_FLUSH(dbenv, mbp);
 }
+
+#else /* !HAVE_STATISTICS */
+
+int
+__lock_stat_pp(dbenv, statp, flags)
+	DB_ENV *dbenv;
+	DB_LOCK_STAT **statp;
+	u_int32_t flags;
+{
+	COMPQUIET(statp, NULL);
+	COMPQUIET(flags, 0);
+
+	return (__db_stat_not_built(dbenv));
+}
+
+int
+__lock_stat_print_pp(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	COMPQUIET(flags, 0);
+
+	return (__db_stat_not_built(dbenv));
+}
+#endif
diff --git a/storage/bdb/lock/lock_timer.c b/storage/bdb/lock/lock_timer.c
new file mode 100644
index 0000000000000000000000000000000000000000..55efb6c6c028a190a99ea5f87061fcdb63f31c22
--- /dev/null
+++ b/storage/bdb/lock/lock_timer.c
@@ -0,0 +1,216 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: lock_timer.c,v 11.141 2004/03/24 20:51:39 bostic Exp $
+ */
+
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#include <stdlib.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/lock.h"
+
+/*
+ * __lock_set_timeout
+ *		-- set timeout values in shared memory.
+ *
+ * This is called from the transaction system.  We either set the time that
+ * this transaction expires or the amount of time a lock for this transaction
+ * is permitted to wait.
+ *
+ * PUBLIC: int __lock_set_timeout __P(( DB_ENV *,
+ * PUBLIC:      u_int32_t, db_timeout_t, u_int32_t));
+ */
+int
+__lock_set_timeout(dbenv, locker, timeout, op)
+	DB_ENV *dbenv;
+	u_int32_t locker;
+	db_timeout_t timeout;
+	u_int32_t op;
+{
+	DB_LOCKTAB *lt;
+	int ret;
+
+	lt = dbenv->lk_handle;
+
+	LOCKREGION(dbenv, lt);
+	ret = __lock_set_timeout_internal(dbenv, locker, timeout, op);
+	UNLOCKREGION(dbenv, lt);
+	return (ret);
+}
+
+/*
+ * __lock_set_timeout_internal
+ *		-- set timeout values in shared memory.
+ *
+ * This is the internal version called from the lock system.  We either set
+ * the time that this transaction expires or the amount of time that a lock
+ * for this transaction is permitted to wait.
+ *
+ * PUBLIC: int __lock_set_timeout_internal
+ * PUBLIC:     __P((DB_ENV *, u_int32_t, db_timeout_t, u_int32_t));
+ */
+int
+__lock_set_timeout_internal(dbenv, locker, timeout, op)
+	DB_ENV *dbenv;
+	u_int32_t locker;
+	db_timeout_t timeout;
+	u_int32_t op;
+{
+	DB_LOCKER *sh_locker;
+	DB_LOCKREGION *region;
+	DB_LOCKTAB *lt;
+	u_int32_t locker_ndx;
+	int ret;
+
+	lt = dbenv->lk_handle;
+	region = lt->reginfo.primary;
+
+	LOCKER_LOCK(lt, region, locker, locker_ndx);
+	ret = __lock_getlocker(lt, locker, locker_ndx, 1, &sh_locker);
+
+	if (ret != 0)
+		return (ret);
+
+	if (op == DB_SET_TXN_TIMEOUT) {
+		if (timeout == 0)
+			LOCK_SET_TIME_INVALID(&sh_locker->tx_expire);
+		else
+			__lock_expires(dbenv, &sh_locker->tx_expire, timeout);
+	} else if (op == DB_SET_LOCK_TIMEOUT) {
+		sh_locker->lk_timeout = timeout;
+		F_SET(sh_locker, DB_LOCKER_TIMEOUT);
+	} else if (op == DB_SET_TXN_NOW) {
+		LOCK_SET_TIME_INVALID(&sh_locker->tx_expire);
+		__lock_expires(dbenv, &sh_locker->tx_expire, 0);
+		sh_locker->lk_expire = sh_locker->tx_expire;
+		if (!LOCK_TIME_ISVALID(&region->next_timeout) ||
+		    LOCK_TIME_GREATER(
+		    &region->next_timeout, &sh_locker->lk_expire))
+			region->next_timeout = sh_locker->lk_expire;
+	} else
+		return (EINVAL);
+
+	return (0);
+}
+
+/*
+ * __lock_inherit_timeout
+ *		-- inherit timeout values from parent locker.
+ * This is called from the transaction system.  This will
+ * return EINVAL if the parent does not exist or did not
+ * have a current txn timeout set.
+ *
+ * PUBLIC: int __lock_inherit_timeout __P(( DB_ENV *, u_int32_t, u_int32_t));
+ */
+int
+__lock_inherit_timeout(dbenv, parent, locker)
+	DB_ENV *dbenv;
+	u_int32_t parent, locker;
+{
+	DB_LOCKER *parent_locker, *sh_locker;
+	DB_LOCKREGION *region;
+	DB_LOCKTAB *lt;
+	u_int32_t locker_ndx;
+	int ret;
+
+	lt = dbenv->lk_handle;
+	region = lt->reginfo.primary;
+	ret = 0;
+	LOCKREGION(dbenv, lt);
+
+	/* If the parent does not exist, we are done. */
+	LOCKER_LOCK(lt, region, parent, locker_ndx);
+	if ((ret = __lock_getlocker(lt,
+	    parent, locker_ndx, 0, &parent_locker)) != 0)
+		goto err;
+
+	/*
+	 * If the parent is not there yet, thats ok.  If it
+	 * does not have any timouts set, then avoid creating
+	 * the child locker at this point.
+	 */
+	if (parent_locker == NULL ||
+	    (LOCK_TIME_ISVALID(&parent_locker->tx_expire) &&
+	    !F_ISSET(parent_locker, DB_LOCKER_TIMEOUT))) {
+		ret = EINVAL;
+		goto done;
+	}
+
+	LOCKER_LOCK(lt, region, locker, locker_ndx);
+	if ((ret = __lock_getlocker(lt,
+	    locker, locker_ndx, 1, &sh_locker)) != 0)
+		goto err;
+
+	sh_locker->tx_expire = parent_locker->tx_expire;
+
+	if (F_ISSET(parent_locker, DB_LOCKER_TIMEOUT)) {
+		sh_locker->lk_timeout = parent_locker->lk_timeout;
+		F_SET(sh_locker, DB_LOCKER_TIMEOUT);
+		if (!LOCK_TIME_ISVALID(&parent_locker->tx_expire))
+			ret = EINVAL;
+	}
+
+done:
+err:
+	UNLOCKREGION(dbenv, lt);
+	return (ret);
+}
+
+/*
+ * __lock_expires --
+ *	Set the expire time given the time to live.  If timevalp is set then
+ *	it contains "now".  This avoids repeated system calls to get the time.
+ *
+ * PUBLIC: void __lock_expires __P((DB_ENV *, db_timeval_t *, db_timeout_t));
+ */
+void
+__lock_expires(dbenv, timevalp, timeout)
+	DB_ENV *dbenv;
+	db_timeval_t *timevalp;
+	db_timeout_t timeout;
+{
+	if (!LOCK_TIME_ISVALID(timevalp))
+		__os_clock(dbenv, &timevalp->tv_sec, &timevalp->tv_usec);
+	if (timeout > 1000000) {
+		timevalp->tv_sec += timeout / 1000000;
+		timevalp->tv_usec += timeout % 1000000;
+	} else
+		timevalp->tv_usec += timeout;
+
+	if (timevalp->tv_usec > 1000000) {
+		timevalp->tv_sec++;
+		timevalp->tv_usec -= 1000000;
+	}
+}
+
+/*
+ * __lock_expired -- determine if a lock has expired.
+ *
+ * PUBLIC: int __lock_expired __P((DB_ENV *, db_timeval_t *, db_timeval_t *));
+ */
+int
+__lock_expired(dbenv, now, timevalp)
+	DB_ENV *dbenv;
+	db_timeval_t *now, *timevalp;
+{
+	if (!LOCK_TIME_ISVALID(timevalp))
+		return (0);
+
+	if (!LOCK_TIME_ISVALID(now))
+		__os_clock(dbenv, &now->tv_sec, &now->tv_usec);
+
+	return (now->tv_sec > timevalp->tv_sec ||
+	    (now->tv_sec == timevalp->tv_sec &&
+	    now->tv_usec >= timevalp->tv_usec));
+}
diff --git a/storage/bdb/lock/lock_util.c b/storage/bdb/lock/lock_util.c
index 260f021b1ee00ea469e6dbae9fecca57890f9282..0c38d72ac69013a5ae1aa27c133ff222b9e2791b 100644
--- a/storage/bdb/lock/lock_util.c
+++ b/storage/bdb/lock/lock_util.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: lock_util.c,v 11.12 2004/09/22 03:48:29 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: lock_util.c,v 11.8 2002/03/27 04:32:20 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -136,3 +134,18 @@ __lock_locker_hash(locker)
 {
 	return (locker);
 }
+
+/*
+ * __lock_nomem --
+ *	Report a lack of some resource.
+ *
+ * PUBLIC: int __lock_nomem __P((DB_ENV *, const char *));
+ */
+int
+__lock_nomem(dbenv, res)
+	DB_ENV *dbenv;
+	const char *res;
+{
+	__db_err(dbenv, "Lock table is out of available %s", res);
+	return (ENOMEM);
+}
diff --git a/storage/bdb/log/log.c b/storage/bdb/log/log.c
index f57caeccb95ca8c36abd1d500ec72d8a326b58b9..14e888abd29fbb19c7f49e86f0a06a63bf3c41a7 100644
--- a/storage/bdb/log/log.c
+++ b/storage/bdb/log/log.c
@@ -1,14 +1,13 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: log.c,v 11.161 2004/10/15 16:59:42 bostic Exp $
  */
-#include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: log.c,v 11.111 2002/08/16 00:27:44 ubell Exp $";
-#endif /* not lint */
+#include "db_config.h"
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
@@ -16,7 +15,6 @@ static const char revid[] = "$Id: log.c,v 11.111 2002/08/16 00:27:44 ubell Exp $
 #include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 #endif
 
 #include "db_int.h"
@@ -25,10 +23,10 @@ static const char revid[] = "$Id: log.c,v 11.111 2002/08/16 00:27:44 ubell Exp $
 #include "dbinc/log.h"
 #include "dbinc/txn.h"
 
-static int __log_init __P((DB_ENV *, DB_LOG *));
-static int __log_recover __P((DB_LOG *));
-static size_t __log_region_size __P((DB_ENV *));
-static int __log_zero __P((DB_ENV *, DB_LSN *, DB_LSN *));
+static int	__log_init __P((DB_ENV *, DB_LOG *));
+static int	__log_recover __P((DB_LOG *));
+static size_t	__log_region_size __P((DB_ENV *));
+static int	__log_zero __P((DB_ENV *, DB_LSN *, DB_LSN *));
 
 /*
  * __log_open --
@@ -49,10 +47,15 @@ __log_open(dbenv)
 		return (ret);
 	dblp->dbenv = dbenv;
 
+	/* Set the default buffer size, if not otherwise configured. */
+	if (dbenv->lg_bsize == 0)
+		dbenv->lg_bsize = F_ISSET(dbenv, DB_ENV_LOG_INMEMORY) ?
+		    LG_BSIZE_INMEM : LG_BSIZE_DEFAULT;
+
 	/* Join/create the log region. */
+	dblp->reginfo.dbenv = dbenv;
 	dblp->reginfo.type = REGION_TYPE_LOG;
 	dblp->reginfo.id = INVALID_REGION_ID;
-	dblp->reginfo.mode = dbenv->db_mode;
 	dblp->reginfo.flags = REGION_JOIN_OK;
 	if (F_ISSET(dbenv, DB_ENV_CREATE))
 		F_SET(&dblp->reginfo, REGION_CREATE_OK);
@@ -93,33 +96,63 @@ __log_open(dbenv)
 	dbenv->lg_handle = dblp;
 
 	if (F_ISSET(&dblp->reginfo, REGION_CREATE)) {
-		if ((ret = __log_recover(dblp)) != 0) {
-			dbenv->lg_handle = NULL;
-			goto err;
-		}
-
 		/*
 		 * We first take the log file size from the environment, if
-		 * specified.  If that wasn't set, recovery may have set it
-		 * from the persistent information in a log file header.  If
-		 * that didn't set it either, we default.
+		 * specified.  If that wasn't set, default it.  Regardless,
+		 * recovery may set it from the persistent information in a
+		 * log file header.
 		 */
 		if (lp->log_size == 0)
-			lp->log_size = lp->log_nsize = LG_MAX_DEFAULT;
+			lp->log_size = F_ISSET(dbenv, DB_ENV_LOG_INMEMORY) ?
+			    LG_MAX_INMEM : LG_MAX_DEFAULT;
+
+		if ((ret = __log_recover(dblp)) != 0)
+			goto err;
+
+		/*
+		 * If the next log file size hasn't been set yet, default it
+		 * to the current log file size.
+		 */
+		if (lp->log_nsize == 0)
+			lp->log_nsize = lp->log_size;
+
+		/*
+		 * If we haven't written any log files, write the first one
+		 * so that checkpoint gets a valid ckp_lsn value.
+		 */
+		if (IS_INIT_LSN(lp->lsn) &&
+		    (ret = __log_newfile(dblp, NULL, 0)) != 0)
+			goto err;
+
+		/* Initialize replication's next-expected LSN value. */
+		lp->ready_lsn = lp->lsn;
 	} else {
 		/*
 		 * A process joining the region may have reset the log file
 		 * size, too.  If so, it only affects the next log file we
-		 * create.
+		 * create.  We need to check that the size is reasonable given
+		 * the buffer size in the region.
 		 */
-		 if (dbenv->lg_size != 0)
+		 if (dbenv->lg_size != 0) {
+			if ((ret =
+			    __log_check_sizes(dbenv, dbenv->lg_size, 0)) != 0)
+				goto err;
+
 			lp->log_nsize = dbenv->lg_size;
+		 }
+
+		/* Migrate persistent flags from the region into the DB_ENV. */
+		if (lp->db_log_autoremove)
+			F_SET(dbenv, DB_ENV_LOG_AUTOREMOVE);
+		if (lp->db_log_inmemory)
+			F_SET(dbenv, DB_ENV_LOG_INMEMORY);
 	}
 
 	R_UNLOCK(dbenv, &dblp->reginfo);
 	return (0);
 
-err:	if (dblp->reginfo.addr != NULL) {
+err:	dbenv->lg_handle = NULL;
+	if (dblp->reginfo.addr != NULL) {
 		if (F_ISSET(&dblp->reginfo, REGION_CREATE))
 			ret = __db_panic(dbenv, ret);
 		R_UNLOCK(dbenv, &dblp->reginfo);
@@ -144,55 +177,63 @@ __log_init(dbenv, dblp)
 	DB_LOG *dblp;
 {
 	DB_MUTEX *flush_mutexp;
-	LOG *region;
+	LOG *lp;
 	int ret;
 	void *p;
 #ifdef  HAVE_MUTEX_SYSTEM_RESOURCES
 	u_int8_t *addr;
 #endif
 
-	if ((ret = __db_shalloc(dblp->reginfo.addr,
-	    sizeof(*region), 0, &dblp->reginfo.primary)) != 0)
+	/*
+	 * This is the first point where we can validate the buffer size,
+	 * because we know all three settings have been configured (file size,
+	 * buffer size and the in-memory flag).
+	 */
+	if ((ret =
+	   __log_check_sizes(dbenv, dbenv->lg_size, dbenv->lg_bsize)) != 0)
+		return (ret);
+
+	if ((ret = __db_shalloc(&dblp->reginfo,
+	    sizeof(*lp), MUTEX_ALIGN, &dblp->reginfo.primary)) != 0)
 		goto mem_err;
 	dblp->reginfo.rp->primary =
 	    R_OFFSET(&dblp->reginfo, dblp->reginfo.primary);
-	region = dblp->reginfo.primary;
-	memset(region, 0, sizeof(*region));
+	lp = dblp->reginfo.primary;
+	memset(lp, 0, sizeof(*lp));
 
-	region->fid_max = 0;
-	SH_TAILQ_INIT(&region->fq);
-	region->free_fid_stack = INVALID_ROFF;
-	region->free_fids = region->free_fids_alloced = 0;
+	lp->fid_max = 0;
+	SH_TAILQ_INIT(&lp->fq);
+	lp->free_fid_stack = INVALID_ROFF;
+	lp->free_fids = lp->free_fids_alloced = 0;
 
 	/* Initialize LOG LSNs. */
-	INIT_LSN(region->lsn);
-	INIT_LSN(region->ready_lsn);
-	INIT_LSN(region->t_lsn);
+	INIT_LSN(lp->lsn);
+	INIT_LSN(lp->t_lsn);
 
 	/*
 	 * It's possible to be waiting for an LSN of [1][0], if a replication
 	 * client gets the first log record out of order.  An LSN of [0][0]
 	 * signifies that we're not waiting.
 	 */
-	ZERO_LSN(region->waiting_lsn);
+	ZERO_LSN(lp->waiting_lsn);
 
 	/*
 	 * Log makes note of the fact that it ran into a checkpoint on
 	 * startup if it did so, as a recovery optimization.  A zero
 	 * LSN signifies that it hasn't found one [yet].
 	 */
-	ZERO_LSN(region->cached_ckp_lsn);
+	ZERO_LSN(lp->cached_ckp_lsn);
 
 #ifdef  HAVE_MUTEX_SYSTEM_RESOURCES
 	/* Allocate room for the log maintenance info and initialize it. */
-	if ((ret = __db_shalloc(dblp->reginfo.addr,
+	if ((ret = __db_shalloc(&dblp->reginfo,
 	    sizeof(REGMAINT) + LG_MAINT_SIZE, 0, &addr)) != 0)
 		goto mem_err;
 	__db_maintinit(&dblp->reginfo, addr, LG_MAINT_SIZE);
-	region->maint_off = R_OFFSET(&dblp->reginfo, addr);
+	lp->maint_off = R_OFFSET(&dblp->reginfo, addr);
 #endif
 
-	if ((ret = __db_mutex_setup(dbenv, &dblp->reginfo, &region->fq_mutex,
+	if ((ret = __db_mutex_setup(dbenv, &dblp->reginfo, &lp->fq_mutex,
 	    MUTEX_NO_RLOCK)) != 0)
 		return (ret);
 
@@ -201,37 +242,47 @@ __log_init(dbenv, dblp)
 	 * to be aligned to MUTEX_ALIGN, and the only way to guarantee that is
 	 * to make sure they're at the beginning of a shalloc'ed chunk.
 	 */
-	if ((ret = __db_shalloc(dblp->reginfo.addr,
+	if ((ret = __db_shalloc(&dblp->reginfo,
 	    sizeof(DB_MUTEX), MUTEX_ALIGN, &flush_mutexp)) != 0)
 		goto mem_err;
 	if ((ret = __db_mutex_setup(dbenv, &dblp->reginfo, flush_mutexp,
 	    MUTEX_NO_RLOCK)) != 0)
 		return (ret);
-	region->flush_mutex_off = R_OFFSET(&dblp->reginfo, flush_mutexp);
+	lp->flush_mutex_off = R_OFFSET(&dblp->reginfo, flush_mutexp);
 
 	/* Initialize the buffer. */
-	if ((ret =
-	    __db_shalloc(dblp->reginfo.addr, dbenv->lg_bsize, 0, &p)) != 0) {
+	if ((ret = __db_shalloc(&dblp->reginfo, dbenv->lg_bsize, 0, &p)) != 0) {
 mem_err:	__db_err(dbenv, "Unable to allocate memory for the log buffer");
 		return (ret);
 	}
-	region->buffer_size = dbenv->lg_bsize;
-	region->buffer_off = R_OFFSET(&dblp->reginfo, p);
-	region->log_size = region->log_nsize = dbenv->lg_size;
+	lp->regionmax = dbenv->lg_regionmax;
+	lp->buffer_off = R_OFFSET(&dblp->reginfo, p);
+	lp->buffer_size = dbenv->lg_bsize;
+	lp->log_size = lp->log_nsize = dbenv->lg_size;
 
 	/* Initialize the commit Queue. */
-	SH_TAILQ_INIT(&region->free_commits);
-	SH_TAILQ_INIT(&region->commits);
-	region->ncommit = 0;
+	SH_TAILQ_INIT(&lp->free_commits);
+	SH_TAILQ_INIT(&lp->commits);
+	lp->ncommit = 0;
+
+	/* Initialize the logfiles list for in-memory logs. */
+	SH_TAILQ_INIT(&lp->logfiles);
+	SH_TAILQ_INIT(&lp->free_logfiles);
 
 	/*
 	 * Fill in the log's persistent header.  Don't fill in the log file
 	 * sizes, as they may change at any time and so have to be filled in
 	 * as each log file is created.
 	 */
-	region->persist.magic = DB_LOGMAGIC;
-	region->persist.version = DB_LOGVERSION;
-	region->persist.mode = (u_int32_t)dbenv->db_mode;
+	lp->persist.magic = DB_LOGMAGIC;
+	lp->persist.version = DB_LOGVERSION;
+	lp->persist.mode = (u_int32_t)dbenv->db_mode;
+
+	/* Migrate persistent flags from the DB_ENV into the region. */
+	if (F_ISSET(dbenv, DB_ENV_LOG_AUTOREMOVE))
+		lp->db_log_autoremove = 1;
+	if (F_ISSET(dbenv, DB_ENV_LOG_INMEMORY))
+		lp->db_log_inmemory = 1;
 
 	return (0);
 }
@@ -294,11 +345,11 @@ __log_recover(dblp)
 	 * Allocate a cursor and set it to the first record.  This shouldn't
 	 * fail, leave error messages on.
 	 */
-	if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+	if ((ret = __log_cursor(dbenv, &logc)) != 0)
 		return (ret);
 	F_SET(logc, DB_LOG_LOCKED);
 	memset(&dbt, 0, sizeof(dbt));
-	if ((ret = logc->get(logc, &lsn, &dbt, DB_SET)) != 0)
+	if ((ret = __log_c_get(logc, &lsn, &dbt, DB_SET)) != 0)
 		goto err;
 
 	/*
@@ -306,7 +357,7 @@ __log_recover(dblp)
 	 * turn off error messages.
 	 */
 	F_SET(logc, DB_LOG_SILENT_ERR);
-	while (logc->get(logc, &lsn, &dbt, DB_NEXT) == 0) {
+	while (__log_c_get(logc, &lsn, &dbt, DB_NEXT) == 0) {
 		if (dbt.size < sizeof(u_int32_t))
 			continue;
 		memcpy(&rectype, dbt.data, sizeof(u_int32_t));
@@ -332,17 +383,18 @@ __log_recover(dblp)
 
 	/* Set up the current buffer information, too. */
 	lp->len = logc->c_len;
+	lp->a_off = 0;
 	lp->b_off = 0;
 	lp->w_off = lp->lsn.offset;
 
 skipsearch:
 	if (FLD_ISSET(dbenv->verbose, DB_VERB_RECOVERY))
-		__db_err(dbenv,
+		__db_msg(dbenv,
 		    "Finding last valid log LSN: file: %lu offset %lu",
 		    (u_long)lp->lsn.file, (u_long)lp->lsn.offset);
 
 err:	if (logc != NULL)
-		(void)logc->close(logc, 0);
+		(void)__log_c_close(logc);
 
 	return (ret);
 }
@@ -363,18 +415,33 @@ __log_find(dblp, find_first, valp, statusp)
 	logfile_validity *statusp;
 {
 	DB_ENV *dbenv;
+	LOG *lp;
 	logfile_validity logval_status, status;
+	struct __db_filestart *filestart;
 	u_int32_t clv, logval;
 	int cnt, fcnt, ret;
 	const char *dir;
 	char *c, **names, *p, *q, savech;
 
 	dbenv = dblp->dbenv;
+	lp = dblp->reginfo.primary;
 	logval_status = status = DB_LV_NONEXISTENT;
 
 	/* Return a value of 0 as the log file number on failure. */
 	*valp = 0;
 
+	if (lp->db_log_inmemory) {
+		filestart = find_first ?
+		    SH_TAILQ_FIRST(&lp->logfiles, __db_filestart) :
+		    SH_TAILQ_LAST(&lp->logfiles, links, __db_filestart);
+		if (filestart != NULL) {
+			*valp = filestart->file;
+			logval_status = DB_LV_NORMAL;
+		}
+		*statusp = logval_status;
+		return (0);
+	}
+
 	/* Find the directory name. */
 	if ((ret = __log_name(dblp, 1, &p, NULL, 0)) != 0)
 		return (ret);
@@ -424,7 +491,7 @@ __log_find(dblp, find_first, valp, statusp)
 		 * Use atol, not atoi; if an "int" is 16-bits, the largest
 		 * log file name won't fit.
 		 */
-		clv = atol(names[cnt] + (sizeof(LFPREFIX) - 1));
+		clv = (u_int32_t)atol(names[cnt] + (sizeof(LFPREFIX) - 1));
 
 		/*
 		 * If searching for the first log file, we want to return the
@@ -435,7 +502,7 @@ __log_find(dblp, find_first, valp, statusp)
 		 * If we're searching for the last log file, we want to return
 		 * the newest log file, period.
 		 *
-		 * Readable log files should never preceede unreadable log
+		 * Readable log files should never precede unreadable log
 		 * files, that would mean the admin seriously screwed up.
 		 */
 		if (find_first) {
@@ -446,7 +513,7 @@ __log_find(dblp, find_first, valp, statusp)
 			if (logval != 0 && clv < logval)
 				continue;
 
-		if ((ret = __log_valid(dblp, clv, 1, &status)) != 0) {
+		if ((ret = __log_valid(dblp, clv, 1, NULL, 0, &status)) != 0) {
 			__db_err(dbenv, "Invalid log file: %s: %s",
 			    names[cnt], db_strerror(ret));
 			goto err;
@@ -510,40 +577,49 @@ err:	__os_dirfree(dbenv, names, fcnt);
  *	log file if it is not unexpectedly flawed (that is, if it's perfectly
  *	normal, if it's zero-length, or if it's an old version).
  *
- * PUBLIC: int __log_valid __P((DB_LOG *, u_int32_t, int, logfile_validity *));
+ * PUBLIC: int __log_valid __P((DB_LOG *, u_int32_t, int,
+ * PUBLIC:     DB_FH **, u_int32_t, logfile_validity *));
  */
 int
-__log_valid(dblp, number, set_persist, statusp)
+__log_valid(dblp, number, set_persist, fhpp, flags, statusp)
 	DB_LOG *dblp;
 	u_int32_t number;
 	int set_persist;
+	DB_FH **fhpp;
+	u_int32_t flags;
 	logfile_validity *statusp;
 {
 	DB_CIPHER *db_cipher;
 	DB_ENV *dbenv;
-	DB_FH fh;
+	DB_FH *fhp;
 	HDR *hdr;
-	LOG *region;
+	LOG *lp;
 	LOGP *persist;
 	logfile_validity status;
-	size_t hdrsize, nw, recsize;
-	int is_hmac, need_free, ret;
+	size_t hdrsize, nr, recsize;
+	int is_hmac, ret;
 	u_int8_t *tmp;
 	char *fname;
 
 	dbenv = dblp->dbenv;
 	db_cipher = dbenv->crypto_handle;
+	fhp = NULL;
 	persist = NULL;
 	status = DB_LV_NORMAL;
+	tmp = NULL;
+
+	/* Return the file handle to our caller, on request */
+	if (fhpp != NULL)
+		*fhpp = NULL;
 
+	if (flags == 0)
+		flags = DB_OSO_RDONLY | DB_OSO_SEQ;
 	/* Try to open the log file. */
-	if ((ret = __log_name(dblp,
-	    number, &fname, &fh, DB_OSO_RDONLY | DB_OSO_SEQ)) != 0) {
+	if ((ret = __log_name(dblp, number, &fname, &fhp, flags)) != 0) {
 		__os_free(dbenv, fname);
 		return (ret);
 	}
 
-	need_free = 0;
 	hdrsize = HDR_NORMAL_SZ;
 	is_hmac = 0;
 	recsize = sizeof(LOGP);
@@ -554,13 +630,18 @@ __log_valid(dblp, number, set_persist, statusp)
 		is_hmac = 1;
 	}
 	if ((ret = __os_calloc(dbenv, 1, recsize + hdrsize, &tmp)) != 0)
-		return (ret);
-	need_free = 1;
+		goto err;
+
 	hdr = (HDR *)tmp;
 	persist = (LOGP *)(tmp + hdrsize);
-	/* Try to read the header. */
-	if ((ret = __os_read(dbenv, &fh, tmp, recsize + hdrsize, &nw)) != 0 ||
-	    nw != recsize + hdrsize) {
+	/*
+	 * Try to read the header.  This can fail if the log is truncated, or
+	 * if we find a preallocated log file where the header has not yet been
+	 * written, so we need to check whether the header is zero-filled.
+	 */
+	if ((ret = __os_read(dbenv, fhp, tmp, recsize + hdrsize, &nr)) != 0 ||
+	    nr != recsize + hdrsize ||
+	    (hdr->len == 0 && persist->magic == 0 && persist->log_size == 0)) {
 		if (ret == 0)
 			status = DB_LV_INCOMPLETE;
 		else
@@ -570,11 +651,8 @@ __log_valid(dblp, number, set_persist, statusp)
 			 */
 			__db_err(dbenv, "Ignoring log file: %s: %s",
 			    fname, db_strerror(ret));
-
-		(void)__os_closehandle(dbenv, &fh);
 		goto err;
 	}
-	(void)__os_closehandle(dbenv, &fh);
 
 	/*
 	 * Now we have to validate the persistent record.  We have
@@ -630,32 +708,35 @@ __log_valid(dblp, number, set_persist, statusp)
 	}
 
 	/*
-	 * Set our status code to indicate whether the log file
-	 * belongs to an unreadable or readable old version;  leave it
-	 * alone if and only if the log file version is the current one.
+	 * Set our status code to indicate whether the log file belongs to an
+	 * unreadable or readable old version; leave it alone if and only if
+	 * the log file version is the current one.
 	 */
 	if (persist->version > DB_LOGVERSION) {
 		/* This is a fatal error--the log file is newer than DB. */
 		__db_err(dbenv,
-		    "Ignoring log file: %s: unsupported log version %lu",
+		    "Unacceptable log file %s: unsupported log version %lu",
 		    fname, (u_long)persist->version);
 		ret = EINVAL;
 		goto err;
 	} else if (persist->version < DB_LOGOLDVER) {
 		status = DB_LV_OLD_UNREADABLE;
+		/* This is a non-fatal error, but give some feedback. */
+		__db_err(dbenv,
+		    "Skipping log file %s: historic log version %lu",
+		    fname, (u_long)persist->version);
 		/*
-		 * We don't want to set persistent info based on an
-		 * unreadable region, so jump to "err".
+		 * We don't want to set persistent info based on an unreadable
+		 * region, so jump to "err".
 		 */
 		goto err;
 	} else if (persist->version < DB_LOGVERSION)
 		status = DB_LV_OLD_READABLE;
 
 	/*
-	 * Only if we have a current log do we verify the checksum.
-	 * We could not check the checksum before checking the magic
-	 * and version because old log hdrs have the length and checksum
-	 * in a different location.
+	 * Only if we have a current log do we verify the checksum.  We could
+	 * not check the checksum before checking the magic and version because
+	 * old log headers put the length and checksum in a different location.
 	 */
 	if (!CRYPTO_ON(dbenv) && ((ret = __db_check_chksum(dbenv,
 	    db_cipher, &hdr->chksum[0], (u_int8_t *)persist,
@@ -668,8 +749,7 @@ __log_valid(dblp, number, set_persist, statusp)
 	 * If the log is readable so far and we're doing system initialization,
 	 * set the region's persistent information based on the headers.
 	 *
-	 * Always set the current log file size.  Only set the next log file's
-	 * size if the application hasn't set it already.
+	 * Override the current log file size.
 	 *
 	 * XXX
 	 * Always use the persistent header's mode, regardless of what was set
@@ -678,24 +758,29 @@ __log_valid(dblp, number, set_persist, statusp)
 	 * be a problem, though.
 	 */
 	if (set_persist) {
-		region = dblp->reginfo.primary;
-		region->log_size = persist->log_size;
-		if (region->log_nsize == 0)
-			region->log_nsize = persist->log_size;
-		region->persist.mode = persist->mode;
+		lp = dblp->reginfo.primary;
+		lp->log_size = persist->log_size;
+		lp->persist.mode = persist->mode;
 	}
 
-err:	__os_free(dbenv, fname);
-	if (need_free)
+err:	if (fname != NULL)
+		__os_free(dbenv, fname);
+	if (ret == 0 && fhpp != NULL)
+		*fhpp = fhp;
+	else
+		/* Must close on error or if we only used it locally. */
+		(void)__os_closehandle(dbenv, fhp);
+	if (tmp != NULL)
 		__os_free(dbenv, tmp);
+
 	*statusp = status;
+
 	return (ret);
 }
 
 /*
  * __log_dbenv_refresh --
- *	Clean up after the log system on a close or failed open.  Called only
- * from __dbenv_refresh.  (Formerly called __log_close.)
+ *	Clean up after the log system on a close or failed open.
  *
  * PUBLIC: int __log_dbenv_refresh __P((DB_ENV *));
  */
@@ -704,27 +789,52 @@ __log_dbenv_refresh(dbenv)
 	DB_ENV *dbenv;
 {
 	DB_LOG *dblp;
+	LOG *lp;
+	REGINFO *reginfo;
 	int ret, t_ret;
 
 	dblp = dbenv->lg_handle;
+	reginfo = &dblp->reginfo;
+	lp = reginfo->primary;
 
 	/* We may have opened files as part of XA; if so, close them. */
 	F_SET(dblp, DBLOG_RECOVER);
 	ret = __dbreg_close_files(dbenv);
 
+	/*
+	 * If a private region, return the memory to the heap.  Not needed for
+	 * filesystem-backed or system shared memory regions, that memory isn't
+	 * owned by any particular process.
+	 */
+	if (F_ISSET(dbenv, DB_ENV_PRIVATE)) {
+		/* Discard the flush mutex. */
+		__db_shalloc_free(reginfo,
+		    R_ADDR(reginfo, lp->flush_mutex_off));
+
+		/* Discard the buffer. */
+		__db_shalloc_free(reginfo, R_ADDR(reginfo, lp->buffer_off));
+
+		/* Discard stack of free file IDs. */
+		if (lp->free_fid_stack != INVALID_ROFF)
+			__db_shalloc_free(reginfo,
+			    R_ADDR(reginfo, lp->free_fid_stack));
+	}
+
 	/* Discard the per-thread lock. */
 	if (dblp->mutexp != NULL)
-		__db_mutex_free(dbenv, &dblp->reginfo, dblp->mutexp);
+		__db_mutex_free(dbenv, reginfo, dblp->mutexp);
 
 	/* Detach from the region. */
-	if ((t_ret =
-	    __db_r_detach(dbenv, &dblp->reginfo, 0)) != 0 && ret == 0)
+	if ((t_ret = __db_r_detach(dbenv, reginfo, 0)) != 0 && ret == 0)
 		ret = t_ret;
 
 	/* Close open files, release allocated memory. */
-	if (F_ISSET(&dblp->lfh, DB_FH_VALID) &&
-	    (t_ret = __os_closehandle(dbenv, &dblp->lfh)) != 0 && ret == 0)
-		ret = t_ret;
+	if (dblp->lfhp != NULL) {
+		if ((t_ret =
+		    __os_closehandle(dbenv, dblp->lfhp)) != 0 && ret == 0)
+			ret = t_ret;
+		dblp->lfhp = NULL;
+	}
 	if (dblp->dbentry != NULL)
 		__os_free(dbenv, dblp->dbentry);
 
@@ -734,69 +844,6 @@ __log_dbenv_refresh(dbenv)
 	return (ret);
 }
 
-/*
- * __log_stat --
- *	Return log statistics.
- *
- * PUBLIC: int __log_stat __P((DB_ENV *, DB_LOG_STAT **, u_int32_t));
- */
-int
-__log_stat(dbenv, statp, flags)
-	DB_ENV *dbenv;
-	DB_LOG_STAT **statp;
-	u_int32_t flags;
-{
-	DB_LOG *dblp;
-	DB_LOG_STAT *stats;
-	LOG *region;
-	int ret;
-
-	PANIC_CHECK(dbenv);
-	ENV_REQUIRES_CONFIG(dbenv,
-	    dbenv->lg_handle, "DB_ENV->log_stat", DB_INIT_LOG);
-
-	*statp = NULL;
-	if ((ret = __db_fchk(dbenv,
-	    "DB_ENV->log_stat", flags, DB_STAT_CLEAR)) != 0)
-		return (ret);
-
-	dblp = dbenv->lg_handle;
-	region = dblp->reginfo.primary;
-
-	if ((ret = __os_umalloc(dbenv, sizeof(DB_LOG_STAT), &stats)) != 0)
-		return (ret);
-
-	/* Copy out the global statistics. */
-	R_LOCK(dbenv, &dblp->reginfo);
-	*stats = region->stat;
-	if (LF_ISSET(DB_STAT_CLEAR))
-		memset(&region->stat, 0, sizeof(region->stat));
-
-	stats->st_magic = region->persist.magic;
-	stats->st_version = region->persist.version;
-	stats->st_mode = region->persist.mode;
-	stats->st_lg_bsize = region->buffer_size;
-	stats->st_lg_size = region->log_nsize;
-
-	stats->st_region_wait = dblp->reginfo.rp->mutex.mutex_set_wait;
-	stats->st_region_nowait = dblp->reginfo.rp->mutex.mutex_set_nowait;
-	if (LF_ISSET(DB_STAT_CLEAR)) {
-		dblp->reginfo.rp->mutex.mutex_set_wait = 0;
-		dblp->reginfo.rp->mutex.mutex_set_nowait = 0;
-	}
-	stats->st_regsize = dblp->reginfo.rp->size;
-
-	stats->st_cur_file = region->lsn.file;
-	stats->st_cur_offset = region->lsn.offset;
-	stats->st_disk_file = region->s_lsn.file;
-	stats->st_disk_offset = region->s_lsn.offset;
-
-	R_UNLOCK(dbenv, &dblp->reginfo);
-
-	*statp = stats;
-	return (0);
-}
-
 /*
  * __log_get_cached_ckp_lsn --
  *	Retrieve any last checkpoint LSN that we may have found on startup.
@@ -852,11 +899,26 @@ __log_region_destroy(dbenv, infop)
 	DB_ENV *dbenv;
 	REGINFO *infop;
 {
-	__db_shlocks_destroy(infop, (REGMAINT *)R_ADDR(infop,
-	    ((LOG *)R_ADDR(infop, infop->rp->primary))->maint_off));
+	/*
+	 * This routine is called in two cases: when discarding the mutexes
+	 * from a previous Berkeley DB run, during recovery, and two, when
+	 * discarding the mutexes as we shut down the database environment.
+	 * In the latter case, we also need to discard shared memory segments,
+	 * this is the last time we use them, and the last region-specific
+	 * call we make.
+	 */
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
+	LOG *lp;
+
+	lp = R_ADDR(infop, infop->rp->primary);
 
-	COMPQUIET(dbenv, NULL);
-	COMPQUIET(infop, NULL);
+	/* Destroy mutexes. */
+	__db_shlocks_destroy(infop, R_ADDR(infop, lp->maint_off));
+	if (infop->primary != NULL && F_ISSET(dbenv, DB_ENV_PRIVATE))
+		__db_shalloc_free(infop, R_ADDR(infop, lp->maint_off));
+#endif
+	if (infop->primary != NULL && F_ISSET(dbenv, DB_ENV_PRIVATE))
+		__db_shalloc_free(infop, infop->primary);
 }
 
 /*
@@ -867,30 +929,29 @@ __log_region_destroy(dbenv, infop)
  * record to be written). This is used in replication to discard records
  * in the log file that do not agree with the master.
  *
- * PUBLIC: int __log_vtruncate __P((DB_ENV *, DB_LSN *, DB_LSN *));
+ * PUBLIC: int __log_vtruncate __P((DB_ENV *, DB_LSN *, DB_LSN *, DB_LSN *));
  */
 int
-__log_vtruncate(dbenv, lsn, ckplsn)
+__log_vtruncate(dbenv, lsn, ckplsn, trunclsn)
 	DB_ENV *dbenv;
-	DB_LSN *lsn, *ckplsn;
+	DB_LSN *lsn, *ckplsn, *trunclsn;
 {
 	DBT log_dbt;
-	DB_FH fh;
 	DB_LOG *dblp;
 	DB_LOGC *logc;
 	DB_LSN end_lsn;
+	DB_MUTEX *flush_mutexp;
 	LOG *lp;
 	u_int32_t bytes, c_len;
-	int fn, ret, t_ret;
-	char *fname;
+	int ret, t_ret;
 
 	/* Need to find out the length of this soon-to-be-last record. */
-	if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+	if ((ret = __log_cursor(dbenv, &logc)) != 0)
 		return (ret);
 	memset(&log_dbt, 0, sizeof(log_dbt));
-	ret = logc->get(logc, lsn, &log_dbt, DB_SET);
+	ret = __log_c_get(logc, lsn, &log_dbt, DB_SET);
 	c_len = logc->c_len;
-	if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+	if ((t_ret = __log_c_close(logc)) != 0 && ret == 0)
 		ret = t_ret;
 	if (ret != 0)
 		return (ret);
@@ -900,11 +961,23 @@ __log_vtruncate(dbenv, lsn, ckplsn)
 	lp = (LOG *)dblp->reginfo.primary;
 
 	R_LOCK(dbenv, &dblp->reginfo);
+
+	/*
+	 * Flush the log so we can simply initialize the in-memory buffer
+	 * after the truncate.
+	 */
+	if ((ret = __log_flush_int(dblp, NULL, 0)) != 0)
+		goto err;
+
 	end_lsn = lp->lsn;
 	lp->lsn = *lsn;
 	lp->len = c_len;
 	lp->lsn.offset += lp->len;
 
+	if (lp->db_log_inmemory &&
+	    (ret = __log_inmem_lsnoff(dblp, &lp->lsn, &lp->b_off)) != 0)
+		goto err;
+
 	/*
 	 * I am going to assume that the number of bytes written since
 	 * the last checkpoint doesn't exceed a 32-bit number.
@@ -915,7 +988,7 @@ __log_vtruncate(dbenv, lsn, ckplsn)
 		bytes = lp->log_size - ckplsn->offset;
 		if (lp->lsn.file > ckplsn->file + 1)
 			bytes += lp->log_size *
-			    (lp->lsn.file - ckplsn->file - 1);
+			    ((lp->lsn.file - ckplsn->file) - 1);
 		bytes += lp->lsn.offset;
 	} else
 		bytes = lp->lsn.offset - ckplsn->offset;
@@ -927,39 +1000,18 @@ __log_vtruncate(dbenv, lsn, ckplsn)
 	 * If the saved lsn is greater than our new end of log, reset it
 	 * to our current end of log.
 	 */
+	flush_mutexp = R_ADDR(&dblp->reginfo, lp->flush_mutex_off);
+	MUTEX_LOCK(dbenv, flush_mutexp);
 	if (log_compare(&lp->s_lsn, lsn) > 0)
 		lp->s_lsn = lp->lsn;
+	MUTEX_UNLOCK(dbenv, flush_mutexp);
 
-	/*
-	 * If the new end of log is in the middle of the buffer,
-	 * don't change the w_off or f_lsn.  If the new end is
-	 * before the w_off then reset w_off and f_lsn to the new
-	 * end of log.
-	 */
-	if (lp->w_off >= lp->lsn.offset) {
-		lp->f_lsn = lp->lsn;
-		lp->w_off = lp->lsn.offset;
-		lp->b_off = 0;
-	} else
-		lp->b_off = lp->lsn.offset - lp->w_off;
+	/* Initialize the in-region buffer to a pristine state. */
+	ZERO_LSN(lp->f_lsn);
+	lp->w_off = lp->lsn.offset;
 
-	ZERO_LSN(lp->waiting_lsn);
-	lp->ready_lsn = lp->lsn;
-	lp->wait_recs = 0;
-	lp->rcvd_recs = 0;
-
-	/* Now throw away any extra log files that we have around. */
-	for (fn = lp->lsn.file + 1;; fn++) {
-		if (__log_name(dblp, fn, &fname, &fh, DB_OSO_RDONLY) != 0) {
-			__os_free(dbenv, fname);
-			break;
-		}
-		(void)__os_closehandle(dbenv, &fh);
-		ret = __os_unlink(dbenv, fname);
-		__os_free(dbenv, fname);
-		if (ret != 0)
-			goto err;
-	}
+	if (trunclsn != NULL)
+		*trunclsn = lp->lsn;
 
 	/* Truncate the log to the new point. */
 	if ((ret = __log_zero(dbenv, &lp->lsn, &end_lsn)) != 0)
@@ -977,8 +1029,7 @@ err:	R_UNLOCK(dbenv, &dblp->reginfo);
  * lower-numbered than the current logs, the we return *outdatedp non
  * zero, else we return it 0.
  *
- * PUBLIC: int __log_is_outdated __P((DB_ENV *dbenv,
- * PUBLIC:     u_int32_t fnum, int *outdatedp));
+ * PUBLIC: int __log_is_outdated __P((DB_ENV *, u_int32_t, int *));
  */
 int
 __log_is_outdated(dbenv, fnum, outdatedp)
@@ -991,10 +1042,20 @@ __log_is_outdated(dbenv, fnum, outdatedp)
 	char *name;
 	int ret;
 	u_int32_t cfile;
+	struct __db_filestart *filestart;
 
 	dblp = dbenv->lg_handle;
-	*outdatedp = 0;
 
+	if (F_ISSET(dbenv, DB_ENV_LOG_INMEMORY)) {
+		R_LOCK(dbenv, &dblp->reginfo);
+		lp = (LOG *)dblp->reginfo.primary;
+		filestart = SH_TAILQ_FIRST(&lp->logfiles, __db_filestart);
+		*outdatedp = (fnum < filestart->file);
+		R_UNLOCK(dbenv, &dblp->reginfo);
+		return (0);
+	}
+
+	*outdatedp = 0;
 	if ((ret = __log_name(dblp, fnum, &name, NULL, 0)) != 0)
 		return (ret);
 
@@ -1027,58 +1088,310 @@ __log_zero(dbenv, from_lsn, to_lsn)
 	DB_ENV *dbenv;
 	DB_LSN *from_lsn, *to_lsn;
 {
-	char *lname;
+	DB_FH *fhp;
 	DB_LOG *dblp;
 	LOG *lp;
-	int ret;
+	struct __db_filestart *filestart, *nextstart;
 	size_t nbytes, len, nw;
+	u_int32_t fn, mbytes, bytes;
 	u_int8_t buf[4096];
-	u_int32_t mbytes, bytes;
+	int ret;
+	char *fname;
 
 	dblp = dbenv->lg_handle;
+	DB_ASSERT(log_compare(from_lsn, to_lsn) <= 0);
+	if (log_compare(from_lsn, to_lsn) > 0) {
+		__db_err(dbenv,
+		    "Warning: truncating to point beyond end of log");
+		return (0);
+	}
+
 	lp = (LOG *)dblp->reginfo.primary;
-	lname = NULL;
+	if (lp->db_log_inmemory) {
+		/*
+		 * Remove the first file if it is invalidated by this write.
+		 * Log records can't be bigger than a file, so we only need to
+		 * check the first file.
+		 */
+		for (filestart = SH_TAILQ_FIRST(&lp->logfiles, __db_filestart);
+		    filestart != NULL && from_lsn->file < filestart->file;
+		    filestart = nextstart) {
+			nextstart = SH_TAILQ_NEXT(filestart,
+			    links, __db_filestart);
+			SH_TAILQ_REMOVE(&lp->logfiles, filestart,
+			    links, __db_filestart);
+			SH_TAILQ_INSERT_HEAD(&lp->free_logfiles, filestart,
+			    links, __db_filestart);
+		}
+
+		return (0);
+	}
 
-	if (dblp->lfname != lp->lsn.file) {
-		if (F_ISSET(&dblp->lfh, DB_FH_VALID))
-			(void)__os_closehandle(dbenv, &dblp->lfh);
-		dblp->lfname = lp->lsn.file;
+	/* Close any open file handles so unlinks don't fail. */
+	if (dblp->lfhp != NULL) {
+		(void)__os_closehandle(dbenv, dblp->lfhp);
+		dblp->lfhp = NULL;
 	}
 
-	if (from_lsn->file != to_lsn->file) {
-		/* We removed some log files; have to 0 to end of file. */
-		if (!F_ISSET(&dblp->lfh, DB_FH_VALID) && (ret =
-		    __log_name(dblp, dblp->lfname, &lname, &dblp->lfh, 0)) != 0)
+	/* Throw away any extra log files that we have around. */
+	for (fn = from_lsn->file + 1;; fn++) {
+		if (__log_name(dblp, fn, &fname, &fhp, DB_OSO_RDONLY) != 0) {
+			__os_free(dbenv, fname);
+			break;
+		}
+		(void)__os_closehandle(dbenv, fhp);
+		ret = __os_unlink(dbenv, fname);
+		__os_free(dbenv, fname);
+		if (ret != 0)
 			return (ret);
-		if ((ret = __os_ioinfo(dbenv,
-		    NULL, &dblp->lfh, &mbytes, &bytes, NULL)) != 0)
-			goto err;
-		len = mbytes * MEGABYTE + bytes - from_lsn->offset;
-	} else if (to_lsn->offset <= from_lsn->offset)
-		return (0);
-	else
-		len = to_lsn->offset = from_lsn->offset;
+	}
+
+	/* We removed some log files; have to 0 to end of file. */
+	if ((ret =
+	    __log_name(dblp, from_lsn->file, &fname, &dblp->lfhp, 0)) != 0)
+		return (ret);
+	__os_free(dbenv, fname);
+	if ((ret = __os_ioinfo(dbenv,
+	    NULL, dblp->lfhp, &mbytes, &bytes, NULL)) != 0)
+		goto err;
+	DB_ASSERT((mbytes * MEGABYTE + bytes) >= from_lsn->offset);
+	len = (mbytes * MEGABYTE + bytes) - from_lsn->offset;
 
 	memset(buf, 0, sizeof(buf));
 
 	/* Initialize the write position. */
-	if (!F_ISSET(&dblp->lfh, DB_FH_VALID) &&
-	    (ret = __log_name(dblp, dblp->lfname, &lname, &dblp->lfh, 0)) != 0)
-		goto err;
-
 	if ((ret = __os_seek(dbenv,
-	    &dblp->lfh, 0, 0, from_lsn->offset, 0, DB_OS_SEEK_SET)) != 0)
-		return (ret);
+	    dblp->lfhp, 0, 0, from_lsn->offset, 0, DB_OS_SEEK_SET)) != 0)
+		goto err;
 
 	while (len > 0) {
 		nbytes = len > sizeof(buf) ? sizeof(buf) : len;
 		if ((ret =
-		    __os_write(dbenv, &dblp->lfh, buf, nbytes, &nw)) != 0)
-			return (ret);
+		    __os_write(dbenv, dblp->lfhp, buf, nbytes, &nw)) != 0)
+			goto err;
 		len -= nbytes;
 	}
-err:	if (lname != NULL)
-		__os_free(dbenv, lname);
+
+err:	(void)__os_closehandle(dbenv, dblp->lfhp);
+	dblp->lfhp = NULL;
+
+	return (ret);
+}
+
+/*
+ * __log_inmem_lsnoff --
+ *	Find the offset in the buffer of a given LSN.
+ *
+ * PUBLIC: int __log_inmem_lsnoff __P((DB_LOG *, DB_LSN *, size_t *));
+ */
+int
+__log_inmem_lsnoff(dblp, lsn, offsetp)
+	DB_LOG *dblp;
+	DB_LSN *lsn;
+	size_t *offsetp;
+{
+	LOG *lp;
+	struct __db_filestart *filestart;
+
+	lp = (LOG *)dblp->reginfo.primary;
+
+	SH_TAILQ_FOREACH(filestart, &lp->logfiles, links, __db_filestart)
+		if (filestart->file == lsn->file) {
+			*offsetp =
+			    (filestart->b_off + lsn->offset) % lp->buffer_size;
+			return (0);
+		}
+
+	return (DB_NOTFOUND);
+}
+
+/*
+ * __log_inmem_newfile --
+ *	Records the offset of the beginning of a new file in the in-memory
+ *	buffer.
+ *
+ * PUBLIC: int __log_inmem_newfile __P((DB_LOG *, u_int32_t));
+ */
+int
+__log_inmem_newfile(dblp, file)
+	DB_LOG *dblp;
+	u_int32_t file;
+{
+	HDR hdr;
+	LOG *lp;
+	struct __db_filestart *filestart;
+	int ret;
+#ifdef DIAGNOSTIC
+	struct __db_filestart *first, *last;
+#endif
+
+	lp = (LOG *)dblp->reginfo.primary;
+
+	/*
+	 * We write an empty header at the end of every in-memory log file.
+	 * This is used during cursor traversal to indicate when to switch the
+	 * LSN to the next file.
+	 */
+	if (file > 1) {
+		memset(&hdr, 0, sizeof(HDR));
+		__log_inmem_copyin(dblp, lp->b_off, &hdr, sizeof(HDR));
+		lp->b_off = (lp->b_off + sizeof(HDR)) % lp->buffer_size;
+	}
+
+	filestart = SH_TAILQ_FIRST(&lp->free_logfiles, __db_filestart);
+	if (filestart == NULL) {
+		if ((ret = __db_shalloc(&dblp->reginfo,
+		    sizeof(struct __db_filestart), 0, &filestart)) != 0)
+			return (ret);
+		memset(filestart, 0, sizeof(*filestart));
+	} else
+		SH_TAILQ_REMOVE(&lp->free_logfiles, filestart,
+		    links, __db_filestart);
+
+	filestart->file = file;
+	filestart->b_off = lp->b_off;
+
+#ifdef DIAGNOSTIC
+	first = SH_TAILQ_FIRST(&lp->logfiles, __db_filestart);
+	last = SH_TAILQ_LAST(&(lp)->logfiles, links, __db_filestart);
+
+	/* Check that we don't wrap. */
+	DB_ASSERT(!first || first == last ||
+	    RINGBUF_LEN(lp, first->b_off, lp->b_off) ==
+	    RINGBUF_LEN(lp, first->b_off, last->b_off) +
+	    RINGBUF_LEN(lp, last->b_off, lp->b_off));
+#endif
+
+	SH_TAILQ_INSERT_TAIL(&lp->logfiles, filestart, links);
+	return (0);
+}
+
+/*
+ * __log_inmem_chkspace --
+ *	Ensure that the requested amount of space is available in the buffer,
+ *	and invalidate the region.
+ *      Note: assumes that the region lock is held on entry.
+ *
+ * PUBLIC: int __log_inmem_chkspace __P((DB_LOG *, size_t));
+ */
+int
+__log_inmem_chkspace(dblp, len)
+	DB_LOG *dblp;
+	size_t len;
+{
+	LOG *lp;
+	DB_LSN active_lsn, old_active_lsn;
+	struct __db_filestart *filestart;
+
+	lp = dblp->reginfo.primary;
+
+	DB_ASSERT(lp->db_log_inmemory);
+
+	/*
+	 * Allow room for an extra header so that we don't need to check for
+	 * space when switching files.
+	 */
+	len += sizeof(HDR);
+
+	/*
+	 * If transactions are enabled and we're about to fill available space,
+	 * update the active LSN and recheck.  If transactions aren't enabled,
+	 * don't even bother checking: in that case we can always overwrite old
+	 * log records, because we're never going to abort.
+	 */
+	while (TXN_ON(dblp->dbenv) &&
+	    RINGBUF_LEN(lp, lp->b_off, lp->a_off) <= len) {
+		old_active_lsn = lp->active_lsn;
+		active_lsn = lp->lsn;
+
+		/*
+		 * Drop the log region lock so we don't hold it while
+		 * taking the transaction region lock.
+		 */
+		R_UNLOCK(dblp->dbenv, &dblp->reginfo);
+		__txn_getactive(dblp->dbenv, &active_lsn);
+		R_LOCK(dblp->dbenv, &dblp->reginfo);
+		active_lsn.offset = 0;
+
+		/* If we didn't make any progress, give up. */
+		if (log_compare(&active_lsn, &old_active_lsn) == 0) {
+			__db_err(dblp->dbenv,
+      "In-memory log buffer is full (an active transaction spans the buffer)");
+			return (DB_LOG_BUFFER_FULL);
+		}
+
+		/* Make sure we're moving the region LSN forwards. */
+		if (log_compare(&active_lsn, &lp->active_lsn) > 0) {
+			lp->active_lsn = active_lsn;
+			(void)__log_inmem_lsnoff(dblp, &active_lsn,
+			    &lp->a_off);
+		}
+	}
+
+	/*
+	 * Remove the first file if it is invalidated by this write.
+	 * Log records can't be bigger than a file, so we only need to
+	 * check the first file.
+	 */
+	filestart = SH_TAILQ_FIRST(&lp->logfiles, __db_filestart);
+	if (filestart != NULL &&
+	    RINGBUF_LEN(lp, lp->b_off, filestart->b_off) <= len) {
+		SH_TAILQ_REMOVE(&lp->logfiles, filestart,
+		    links, __db_filestart);
+		SH_TAILQ_INSERT_HEAD(&lp->free_logfiles, filestart,
+		    links, __db_filestart);
+		lp->f_lsn.file = filestart->file + 1;
+	}
 
 	return (0);
 }
+
+/*
+ * __log_inmem_copyout --
+ *	Copies the given number of bytes from the buffer -- no checking.
+ *      Note: assumes that the region lock is held on entry.
+ *
+ * PUBLIC: void __log_inmem_copyout __P((DB_LOG *, size_t, void *, size_t));
+ */
+void
+__log_inmem_copyout(dblp, offset, buf, size)
+	DB_LOG *dblp;
+	size_t offset;
+	void *buf;
+	size_t size;
+{
+	LOG *lp;
+	size_t nbytes;
+
+	lp = (LOG *)dblp->reginfo.primary;
+	nbytes = (offset + size < lp->buffer_size) ?
+	    size : lp->buffer_size - offset;
+	memcpy(buf, dblp->bufp + offset, nbytes);
+	if (nbytes < size)
+		memcpy((u_int8_t *)buf + nbytes, dblp->bufp, size - nbytes);
+}
+
+/*
+ * __log_inmem_copyin --
+ *	Copies the given number of bytes into the buffer -- no checking.
+ *      Note: assumes that the region lock is held on entry.
+ *
+ * PUBLIC: void __log_inmem_copyin __P((DB_LOG *, size_t, void *, size_t));
+ */
+void
+__log_inmem_copyin(dblp, offset, buf, size)
+	DB_LOG *dblp;
+	size_t offset;
+	void *buf;
+	size_t size;
+{
+	LOG *lp;
+	size_t nbytes;
+
+	lp = (LOG *)dblp->reginfo.primary;
+	nbytes = (offset + size < lp->buffer_size) ?
+	    size : lp->buffer_size - offset;
+	memcpy(dblp->bufp + offset, buf, nbytes);
+	if (nbytes < size)
+		memcpy(dblp->bufp, (u_int8_t *)buf + nbytes, size - nbytes);
+}
diff --git a/storage/bdb/log/log_archive.c b/storage/bdb/log/log_archive.c
index 19e1af5a93e49b7d22ffc3a75173e19ea4d1a163..8b9e58163d2f2c26b334b445bd8561eb84f8dc13 100644
--- a/storage/bdb/log/log_archive.c
+++ b/storage/bdb/log/log_archive.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: log_archive.c,v 11.62 2004/07/16 21:38:59 mjc Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: log_archive.c,v 11.39 2002/08/06 05:00:31 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -28,38 +26,28 @@ static const char revid[] = "$Id: log_archive.c,v 11.39 2002/08/06 05:00:31 bost
 static int __absname __P((DB_ENV *, char *, char *, char **));
 static int __build_data __P((DB_ENV *, char *, char ***));
 static int __cmpfunc __P((const void *, const void *));
+static int __log_archive __P((DB_ENV *, char **[], u_int32_t));
 static int __usermem __P((DB_ENV *, char ***));
 
 /*
- * __log_archive --
- *	Supporting function for db_archive(1).
+ * __log_archive_pp --
+ *	DB_ENV->log_archive pre/post processing.
  *
- * PUBLIC: int __log_archive __P((DB_ENV *, char **[], u_int32_t));
+ * PUBLIC: int __log_archive_pp __P((DB_ENV *, char **[], u_int32_t));
  */
 int
-__log_archive(dbenv, listp, flags)
+__log_archive_pp(dbenv, listp, flags)
 	DB_ENV *dbenv;
 	char ***listp;
 	u_int32_t flags;
 {
-	DBT rec;
-	DB_LOG *dblp;
-	DB_LOGC *logc;
-	DB_LSN stable_lsn;
-	__txn_ckp_args *ckp_args;
-	char **array, **arrayp, *name, *p, *pref, buf[MAXPATHLEN];
-	int array_size, db_arch_abs, n, ret;
-	u_int32_t fnum;
+	int rep_check, ret;
 
 	PANIC_CHECK(dbenv);
 	ENV_REQUIRES_CONFIG(dbenv,
 	    dbenv->lg_handle, "DB_ENV->log_archive", DB_INIT_LOG);
 
-	name = NULL;
-	dblp = dbenv->lg_handle;
-	COMPQUIET(fnum, 0);
-
-#define	OKFLAGS	(DB_ARCH_ABS | DB_ARCH_DATA | DB_ARCH_LOG)
+#define	OKFLAGS	(DB_ARCH_ABS | DB_ARCH_DATA | DB_ARCH_LOG | DB_ARCH_REMOVE)
 	if (flags != 0) {
 		if ((ret = __db_fchk(
 		    dbenv, "DB_ENV->log_archive", flags, OKFLAGS)) != 0)
@@ -67,17 +55,66 @@ __log_archive(dbenv, listp, flags)
 		if ((ret = __db_fcchk(dbenv, "DB_ENV->log_archive",
 		    flags, DB_ARCH_DATA, DB_ARCH_LOG)) != 0)
 			return (ret);
+		if ((ret = __db_fcchk(dbenv, "DB_ENV->log_archive",
+		    flags, DB_ARCH_REMOVE,
+		    DB_ARCH_ABS | DB_ARCH_DATA | DB_ARCH_LOG)) != 0)
+			return (ret);
 	}
 
-	if (LF_ISSET(DB_ARCH_ABS)) {
-		db_arch_abs = 1;
-		LF_CLR(DB_ARCH_ABS);
-	} else
-		db_arch_abs = 0;
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __log_archive(dbenv, listp, flags);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
+/*
+ * __log_archive --
+ *	DB_ENV->log_archive.  Internal.
+ */
+static int
+__log_archive(dbenv, listp, flags)
+	DB_ENV *dbenv;
+	char ***listp;
+	u_int32_t flags;
+{
+	DBT rec;
+	DB_LOG *dblp;
+	LOG *lp;
+	DB_LOGC *logc;
+	DB_LSN stable_lsn;
+	__txn_ckp_args *ckp_args;
+	u_int array_size, n;
+	u_int32_t fnum;
+	int ret, t_ret;
+	char **array, **arrayp, *name, *p, *pref, buf[MAXPATHLEN];
 
-	if (flags == 0 || flags == DB_ARCH_DATA)
-		ENV_REQUIRES_CONFIG(dbenv,
-		    dbenv->tx_handle, "DB_ENV->log_archive", DB_INIT_TXN);
+	dblp = dbenv->lg_handle;
+	lp = (LOG *)dblp->reginfo.primary;
+	array = NULL;
+	name = NULL;
+	ret = 0;
+	COMPQUIET(fnum, 0);
+
+	if (flags != DB_ARCH_REMOVE)
+		*listp = NULL;
+
+	/* There are no log files if logs are in memory. */
+	if (lp->db_log_inmemory) {
+		LF_CLR(~DB_ARCH_DATA);
+		if (flags == 0)
+			return (0);
+	}
+
+	/*
+	 * If the user wants the list of log files to remove and we're
+	 * at a bad time in replication initialization, just return.
+	 */
+	if (!LF_ISSET(DB_ARCH_DATA) &&
+	    !LF_ISSET(DB_ARCH_LOG) && __rep_noarchive(dbenv))
+		return (0);
 
 	/*
 	 * Get the absolute pathname of the current directory.  It would
@@ -88,46 +125,60 @@ __log_archive(dbenv, listp, flags)
 	 * Can't trust getcwd(3) to set a valid errno.  If it doesn't, just
 	 * guess that we ran out of memory.
 	 */
-	if (db_arch_abs) {
+	if (LF_ISSET(DB_ARCH_ABS)) {
 		__os_set_errno(0);
 		if ((pref = getcwd(buf, sizeof(buf))) == NULL) {
 			if (__os_get_errno() == 0)
 				__os_set_errno(ENOMEM);
-			return (__os_get_errno());
+			ret = __os_get_errno();
+			goto err;
 		}
 	} else
 		pref = NULL;
 
+	LF_CLR(DB_ARCH_ABS);
 	switch (flags) {
 	case DB_ARCH_DATA:
-		return (__build_data(dbenv, pref, listp));
+		ret = __build_data(dbenv, pref, listp);
+		goto err;
 	case DB_ARCH_LOG:
 		memset(&rec, 0, sizeof(rec));
-		if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
-			return (ret);
+		if ((ret = __log_cursor(dbenv, &logc)) != 0)
+			goto err;
 #ifdef UMRW
 		ZERO_LSN(stable_lsn);
 #endif
-		ret = logc->get(logc, &stable_lsn, &rec, DB_LAST);
-		(void)logc->close(logc, 0);
+		ret = __log_c_get(logc, &stable_lsn, &rec, DB_LAST);
+		if ((t_ret = __log_c_close(logc)) != 0 && ret == 0)
+			ret = t_ret;
 		if (ret != 0)
-			return (ret);
+			goto err;
 		fnum = stable_lsn.file;
 		break;
+	case DB_ARCH_REMOVE:
+		__log_autoremove(dbenv);
+		goto err;
 	case 0:
 		memset(&rec, 0, sizeof(rec));
-		if (__txn_getckp(dbenv, &stable_lsn) != 0) {
+		if (!TXN_ON(dbenv)) {
+			__log_get_cached_ckp_lsn(dbenv, &stable_lsn);
+			if (IS_ZERO_LSN(stable_lsn) && (ret =
+			     __txn_findlastckp(dbenv, &stable_lsn, NULL)) != 0)
+				goto err;
+			if (IS_ZERO_LSN(stable_lsn))
+				goto err;
+		}
+		else if (__txn_getckp(dbenv, &stable_lsn) != 0) {
 			/*
 			 * A failure return means that there's no checkpoint
 			 * in the log (so we are not going to be deleting
 			 * any log files).
 			 */
-			*listp = NULL;
-			return (0);
+			goto err;
 		}
-		if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
-			return (ret);
-		if ((ret = logc->get(logc, &stable_lsn, &rec, DB_SET)) != 0 ||
+		if ((ret = __log_cursor(dbenv, &logc)) != 0)
+			goto err;
+		if ((ret = __log_c_get(logc, &stable_lsn, &rec, DB_SET)) != 0 ||
 		    (ret = __txn_ckp_read(dbenv, rec.data, &ckp_args)) != 0) {
 			/*
 			 * A return of DB_NOTFOUND may only mean that the
@@ -135,21 +186,24 @@ __log_archive(dbenv, listp, flags)
 			 * log files that we still have.  This is not
 			 * an error;  it just means our work is done.
 			 */
-			if (ret == DB_NOTFOUND) {
-				*listp = NULL;
+			if (ret == DB_NOTFOUND)
 				ret = 0;
-			}
-			(void)logc->close(logc, 0);
-			return (ret);
+			if ((t_ret = __log_c_close(logc)) != 0 && ret == 0)
+				ret = t_ret;
+			goto err;
 		}
-		if ((ret = logc->close(logc, 0)) != 0)
-			return (ret);
+		if ((ret = __log_c_close(logc)) != 0)
+			goto err;
 		stable_lsn = ckp_args->ckp_lsn;
 		__os_free(dbenv, ckp_args);
 
 		/* Remove any log files before the last stable LSN. */
 		fnum = stable_lsn.file - 1;
 		break;
+	default:
+		DB_ASSERT(0);
+		ret = EINVAL;
+		goto err;
 	}
 
 #define	LIST_INCREMENT	64
@@ -157,7 +211,7 @@ __log_archive(dbenv, listp, flags)
 	array_size = 64;
 	if ((ret = __os_malloc(dbenv,
 	    sizeof(char *) * array_size, &array)) != 0)
-		return (ret);
+		goto err;
 	array[0] = NULL;
 
 	/* Build an array of the file names. */
@@ -179,9 +233,9 @@ __log_archive(dbenv, listp, flags)
 				goto err;
 		}
 
-		if (db_arch_abs) {
-			if ((ret = __absname(dbenv,
-			    pref, name, &array[n])) != 0)
+		if (pref != NULL) {
+			if ((ret =
+			    __absname(dbenv, pref, name, &array[n])) != 0)
 				goto err;
 			__os_free(dbenv, name);
 		} else if ((p = __db_rpath(name)) != NULL) {
@@ -196,11 +250,8 @@ __log_archive(dbenv, listp, flags)
 	}
 
 	/* If there's nothing to return, we're done. */
-	if (n == 0) {
-		*listp = NULL;
-		ret = 0;
+	if (n == 0)
 		goto err;
-	}
 
 	/* Sort the list. */
 	qsort(array, (size_t)n, sizeof(char *), __cmpfunc);
@@ -209,19 +260,45 @@ __log_archive(dbenv, listp, flags)
 	if ((ret = __usermem(dbenv, &array)) != 0)
 		goto err;
 
-	*listp = array;
-	return (0);
+	if (listp != NULL)
+		*listp = array;
 
-err:	if (array != NULL) {
-		for (arrayp = array; *arrayp != NULL; ++arrayp)
-			__os_free(dbenv, *arrayp);
-		__os_free(dbenv, array);
+	if (0) {
+err:		if (array != NULL) {
+			for (arrayp = array; *arrayp != NULL; ++arrayp)
+				__os_free(dbenv, *arrayp);
+			__os_free(dbenv, array);
+		}
+		if (name != NULL)
+			__os_free(dbenv, name);
 	}
-	if (name != NULL)
-		__os_free(dbenv, name);
+
 	return (ret);
 }
 
+/*
+ * __log_autoremove --
+ *	Delete any non-essential log files.
+ *
+ * PUBLIC: void __log_autoremove __P((DB_ENV *));
+ */
+void
+__log_autoremove(dbenv)
+	DB_ENV *dbenv;
+{
+	char **begin, **list;
+
+	if (__log_archive(dbenv, &list, DB_ARCH_ABS) != 0)
+		return;
+
+	if (list != NULL) {
+		for (begin = list; *list != NULL; ++list)
+			(void)__os_unlink(dbenv, *list);
+		__os_ufree(dbenv, begin);
+	}
+	return;
+}
+
 /*
  * __build_data --
  *	Build a list of datafiles for return.
@@ -235,8 +312,9 @@ __build_data(dbenv, pref, listp)
 	DB_LOGC *logc;
 	DB_LSN lsn;
 	__dbreg_register_args *argp;
+	u_int array_size, last, n, nxt;
 	u_int32_t rectype;
-	int array_size, last, n, nxt, ret, t_ret;
+	int ret, t_ret;
 	char **array, **arrayp, **list, **lp, *p, *real_name;
 
 	/* Get some initial space. */
@@ -247,13 +325,13 @@ __build_data(dbenv, pref, listp)
 	array[0] = NULL;
 
 	memset(&rec, 0, sizeof(rec));
-	if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+	if ((ret = __log_cursor(dbenv, &logc)) != 0)
 		return (ret);
-	for (n = 0; (ret = logc->get(logc, &lsn, &rec, DB_PREV)) == 0;) {
+	for (n = 0; (ret = __log_c_get(logc, &lsn, &rec, DB_PREV)) == 0;) {
 		if (rec.size < sizeof(rectype)) {
 			ret = EINVAL;
 			__db_err(dbenv, "DB_ENV->log_archive: bad log record");
-			goto free_continue;
+			break;
 		}
 
 		memcpy(&rectype, rec.data, sizeof(rectype));
@@ -264,7 +342,7 @@ __build_data(dbenv, pref, listp)
 			ret = EINVAL;
 			__db_err(dbenv,
 			    "DB_ENV->log_archive: unable to read log record");
-			goto free_continue;
+			break;
 		}
 
 		if (n >= array_size - 2) {
@@ -306,7 +384,7 @@ free_continue:	__os_free(dbenv, argp);
 	}
 	if (ret == DB_NOTFOUND)
 		ret = 0;
-	if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+	if ((t_ret = __log_c_close(logc)) != 0 && ret == 0)
 		ret = t_ret;
 	if (ret != 0)
 		goto err1;
diff --git a/storage/bdb/log/log_compare.c b/storage/bdb/log/log_compare.c
index 115f9c21b7633f566846a79cd0f1944b193d935f..97d0367ea8e3ecd50771ed0efed15101a06c3c08 100644
--- a/storage/bdb/log/log_compare.c
+++ b/storage/bdb/log/log_compare.c
@@ -1,14 +1,13 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: log_compare.c,v 11.8 2004/01/28 03:36:17 bostic Exp $
  */
-#include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: log_compare.c,v 11.6 2002/01/11 15:52:50 bostic Exp $";
-#endif /* not lint */
+#include "db_config.h"
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
diff --git a/storage/bdb/log/log_get.c b/storage/bdb/log/log_get.c
index c8b028da0fb4bc8e2e46905e89f7e8942f73e3d5..2e8f09a6d90bdec488cd1fcf4f27402416de04f6 100644
--- a/storage/bdb/log/log_get.c
+++ b/storage/bdb/log/log_get.c
@@ -1,20 +1,18 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: log_get.c,v 11.110 2004/09/17 22:00:31 mjc Exp $
  */
-#include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: log_get.c,v 11.81 2002/08/14 20:09:27 bostic Exp $";
-#endif /* not lint */
+#include "db_config.h"
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <string.h>
-#include <unistd.h>
 #endif
 
 #include "db_int.h"
@@ -26,82 +24,100 @@ static const char revid[] = "$Id: log_get.c,v 11.81 2002/08/14 20:09:27 bostic E
 
 typedef enum { L_ALREADY, L_ACQUIRED, L_NONE } RLOCK;
 
-static int __log_c_close __P((DB_LOGC *, u_int32_t));
-static int __log_c_get __P((DB_LOGC *, DB_LSN *, DBT *, u_int32_t));
+static int __log_c_close_pp __P((DB_LOGC *, u_int32_t));
+static int __log_c_get_pp __P((DB_LOGC *, DB_LSN *, DBT *, u_int32_t));
 static int __log_c_get_int __P((DB_LOGC *, DB_LSN *, DBT *, u_int32_t));
-static int __log_c_hdrchk __P((DB_LOGC *, HDR *, int *));
+static int __log_c_hdrchk __P((DB_LOGC *, DB_LSN *, HDR *, int *));
 static int __log_c_incursor __P((DB_LOGC *, DB_LSN *, HDR *, u_int8_t **));
 static int __log_c_inregion __P((DB_LOGC *,
 	       DB_LSN *, RLOCK *, DB_LSN *, HDR *, u_int8_t **));
 static int __log_c_io __P((DB_LOGC *,
 	       u_int32_t, u_int32_t, void *, size_t *, int *));
 static int __log_c_ondisk __P((DB_LOGC *,
-	       DB_LSN *, DB_LSN *, int, HDR *, u_int8_t **, int *));
+	       DB_LSN *, DB_LSN *, u_int32_t, HDR *, u_int8_t **, int *));
 static int __log_c_set_maxrec __P((DB_LOGC *, char *));
-static int __log_c_shortread __P((DB_LOGC *, int));
+static int __log_c_shortread __P((DB_LOGC *, DB_LSN *, int));
 
 /*
- * __log_cursor --
- *	Create a log cursor.
+ * __log_cursor_pp --
+ *	DB_ENV->log_cursor
  *
- * PUBLIC: int __log_cursor __P((DB_ENV *, DB_LOGC **, u_int32_t));
+ * PUBLIC: int __log_cursor_pp __P((DB_ENV *, DB_LOGC **, u_int32_t));
  */
 int
-__log_cursor(dbenv, logcp, flags)
+__log_cursor_pp(dbenv, logcp, flags)
 	DB_ENV *dbenv;
 	DB_LOGC **logcp;
 	u_int32_t flags;
 {
-	DB_LOGC *logc;
-	int ret;
+	int rep_check, ret;
 
 	PANIC_CHECK(dbenv);
 	ENV_REQUIRES_CONFIG(dbenv,
 	    dbenv->lg_handle, "DB_ENV->log_cursor", DB_INIT_LOG);
 
-	*logcp = NULL;
-
 	/* Validate arguments. */
 	if ((ret = __db_fchk(dbenv, "DB_ENV->log_cursor", flags, 0)) != 0)
 		return (ret);
 
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __log_cursor(dbenv, logcp);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
+/*
+ * __log_cursor --
+ *	Create a log cursor.
+ *
+ * PUBLIC: int __log_cursor __P((DB_ENV *, DB_LOGC **));
+ */
+int
+__log_cursor(dbenv, logcp)
+	DB_ENV *dbenv;
+	DB_LOGC **logcp;
+{
+	DB_LOGC *logc;
+	int ret;
+
+	*logcp = NULL;
+
 	/* Allocate memory for the cursor. */
 	if ((ret = __os_calloc(dbenv, 1, sizeof(DB_LOGC), &logc)) != 0)
-		goto err;
-	if ((ret = __os_calloc(dbenv, 1, sizeof(DB_FH), &logc->c_fh)) != 0)
-		goto err;
+		return (ret);
 
 	logc->bp_size = DB_LOGC_BUF_SIZE;
-	if ((ret = __os_malloc(dbenv, logc->bp_size, &logc->bp)) != 0)
-		goto err;
+	/*
+	 * Set this to something positive.
+	 */
+	logc->bp_maxrec = MEGABYTE;
+	if ((ret = __os_malloc(dbenv, logc->bp_size, &logc->bp)) != 0) {
+		__os_free(dbenv, logc);
+		return (ret);
+	}
 
 	logc->dbenv = dbenv;
-	logc->close = __log_c_close;
-	logc->get = __log_c_get;
+	logc->close = __log_c_close_pp;
+	logc->get = __log_c_get_pp;
 
 	*logcp = logc;
 	return (0);
-
-err:	if (logc != NULL) {
-		if (logc->c_fh != NULL)
-			__os_free(dbenv, logc->c_fh);
-		__os_free(dbenv, logc);
-	}
-
-	return (ret);
 }
 
 /*
- * __log_c_close --
- *	Close a log cursor.
+ * __log_c_close_pp --
+ *	DB_LOGC->close pre/post processing.
  */
 static int
-__log_c_close(logc, flags)
+__log_c_close_pp(logc, flags)
 	DB_LOGC *logc;
 	u_int32_t flags;
 {
 	DB_ENV *dbenv;
-	int ret;
+	int rep_check, ret;
 
 	dbenv = logc->dbenv;
 
@@ -109,33 +125,56 @@ __log_c_close(logc, flags)
 	if ((ret = __db_fchk(dbenv, "DB_LOGC->close", flags, 0)) != 0)
 		return (ret);
 
-	if (F_ISSET(logc->c_fh, DB_FH_VALID))
-		(void)__os_closehandle(dbenv, logc->c_fh);
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __log_c_close(logc);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
+/*
+ * __log_c_close --
+ *	DB_LOGC->close.
+ *
+ * PUBLIC: int __log_c_close __P((DB_LOGC *));
+ */
+int
+__log_c_close(logc)
+	DB_LOGC *logc;
+{
+	DB_ENV *dbenv;
+
+	dbenv = logc->dbenv;
+
+	if (logc->c_fhp != NULL) {
+		(void)__os_closehandle(dbenv, logc->c_fhp);
+		logc->c_fhp = NULL;
+	}
 
 	if (logc->c_dbt.data != NULL)
 		__os_free(dbenv, logc->c_dbt.data);
 
 	__os_free(dbenv, logc->bp);
-	__os_free(dbenv, logc->c_fh);
 	__os_free(dbenv, logc);
 
 	return (0);
 }
 
 /*
- * __log_c_get --
- *	Get a log record.
+ * __log_c_get_pp --
+ *	DB_LOGC->get pre/post processing.
  */
 static int
-__log_c_get(logc, alsn, dbt, flags)
+__log_c_get_pp(logc, alsn, dbt, flags)
 	DB_LOGC *logc;
 	DB_LSN *alsn;
 	DBT *dbt;
 	u_int32_t flags;
 {
 	DB_ENV *dbenv;
-	DB_LSN saved_lsn;
-	int ret;
+	int rep_check, ret;
 
 	dbenv = logc->dbenv;
 
@@ -151,7 +190,8 @@ __log_c_get(logc, alsn, dbt, flags)
 		break;
 	case DB_SET:
 		if (IS_ZERO_LSN(*alsn)) {
-			__db_err(dbenv, "DB_LOGC->get: invalid LSN");
+			__db_err(dbenv, "DB_LOGC->get: invalid LSN: %lu/%lu",
+			    (u_long)alsn->file, (u_long)alsn->offset);
 			return (EINVAL);
 		}
 		break;
@@ -159,6 +199,34 @@ __log_c_get(logc, alsn, dbt, flags)
 		return (__db_ferr(dbenv, "DB_LOGC->get", 1));
 	}
 
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __log_c_get(logc, alsn, dbt, flags);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
+/*
+ * __log_c_get --
+ *	DB_LOGC->get.
+ *
+ * PUBLIC: int __log_c_get __P((DB_LOGC *, DB_LSN *, DBT *, u_int32_t));
+ */
+int
+__log_c_get(logc, alsn, dbt, flags)
+	DB_LOGC *logc;
+	DB_LSN *alsn;
+	DBT *dbt;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	DB_LSN saved_lsn;
+	int ret;
+
+	dbenv = logc->dbenv;
+
 	/*
 	 * On error, we take care not to overwrite the caller's LSN.  This
 	 * is because callers looking for the end of the log loop using the
@@ -193,6 +261,10 @@ __log_c_get(logc, alsn, dbt, flags)
 		case DB_LAST:
 			flags = DB_PREV;
 			break;
+		case DB_NEXT:
+		case DB_PREV:
+		default:
+			break;
 		}
 		if (F_ISSET(dbt, DB_DBT_MALLOC)) {
 			__os_free(dbenv, dbt->data);
@@ -297,15 +369,15 @@ __log_c_get_int(logc, alsn, dbt, flags)
 		if (!IS_ZERO_LSN(nlsn)) {
 			/* If at start-of-file, move to the previous file. */
 			if (nlsn.offset == 0) {
-				if (nlsn.file == 1 ||
-				    __log_valid(dblp,
-					nlsn.file - 1, 0, &status) != 0) {
+				if (nlsn.file == 1) {
 					ret = DB_NOTFOUND;
 					goto err;
 				}
-
-				if (status != DB_LV_NORMAL &&
-				    status != DB_LV_OLD_READABLE) {
+				if ((!lp->db_log_inmemory &&
+				    (__log_valid(dblp, nlsn.file - 1, 0, NULL,
+				    0, &status) != 0 ||
+				    (status != DB_LV_NORMAL &&
+				    status != DB_LV_OLD_READABLE)))) {
 					ret = DB_NOTFOUND;
 					goto err;
 				}
@@ -327,6 +399,10 @@ __log_c_get_int(logc, alsn, dbt, flags)
 	case DB_SET:				/* Set log record. */
 		nlsn = *alsn;
 		break;
+	default:
+		DB_ASSERT(0);
+		ret = EINVAL;
+		goto err;
 	}
 
 	if (0) {				/* Move to the next file. */
@@ -357,12 +433,13 @@ next_file:	++nlsn.file;
 	 * coming from the disk -- it means the record can't be in the region's
 	 * buffer.  Else, check the region's buffer.
 	 *
-	 * If the record isn't in the region's buffer, we're going to have to
-	 * read the record from disk.  We want to make a point of not reading
-	 * past the end of the logical log (after recovery, there may be data
-	 * after the end of the logical log, not to mention the log file may
-	 * have been pre-allocated).  So, zero out last_lsn, and initialize it
-	 * inside __log_c_inregion -- if it's still zero when we check it in
+	 * If the record isn't in the region's buffer, then either logs are
+	 * in-memory, and we're done, or  we're going to have to read the
+	 * record from disk.  We want to make a point of not reading past the
+	 * end of the logical log (after recovery, there may be data after the
+	 * end of the logical log, not to mention the log file may have been
+	 * pre-allocated).  So, zero out last_lsn, and initialize it inside
+	 * __log_c_inregion -- if it's still zero when we check it in
 	 * __log_c_ondisk, that's OK, it just means the logical end of the log
 	 * isn't an issue for this request.
 	 */
@@ -376,6 +453,8 @@ next_file:	++nlsn.file;
 			goto err;
 		if (rp != NULL)
 			goto cksum;
+		if (lp->db_log_inmemory)
+			goto nohdr;
 	}
 
 	/*
@@ -393,7 +472,7 @@ next_file:	++nlsn.file;
 	if ((ret = __log_c_ondisk(
 	    logc, &nlsn, &last_lsn, flags, &hdr, &rp, &eof)) != 0)
 		goto err;
-	if (eof == 1) {
+	if (eof) {
 		/*
 		 * Only DB_NEXT automatically moves to the next file, and
 		 * it only happens once.
@@ -429,7 +508,8 @@ cksum:	/*
 				ret = EIO;
 		} else if (ret == -1) {
 			__db_err(dbenv,
-		    "DB_LOGC->get: log record checksum mismatch");
+		    "DB_LOGC->get: log record LSN %lu/%lu: checksum mismatch",
+			    (u_long)nlsn.file, (u_long)nlsn.offset);
 			__db_err(dbenv,
 		    "DB_LOGC->get: catastrophic recovery may be required");
 			ret = __db_panic(dbenv, DB_RUNRECOVERY);
@@ -443,12 +523,11 @@ cksum:	/*
 	 * going to have to retry.
 	 */
 	if (hdr.len == 0) {
-		switch (flags) {
+nohdr:		switch (flags) {
 		case DB_FIRST:
 		case DB_NEXT:
 			/* Zero'd records always indicate the end of a file. */
 			goto next_file;
-
 		case DB_LAST:
 		case DB_PREV:
 			/*
@@ -459,9 +538,11 @@ cksum:	/*
 			 * the first record in that new file should have its
 			 * prev field set correctly.
 			 */
-			 __db_err(dbenv,
+			__db_err(dbenv,
 		"Encountered zero length records while traversing backwards");
-			 DB_ASSERT(0);
+			DB_ASSERT(0);
+			ret = __db_panic(dbenv, DB_RUNRECOVERY);
+			goto err;
 		case DB_SET:
 		default:
 			/* Return the 0-length record. */
@@ -515,6 +596,7 @@ __log_c_incursor(logc, lsn, hdr, pp)
 	u_int8_t **pp;
 {
 	u_int8_t *p;
+	int eof;
 
 	*pp = NULL;
 
@@ -547,9 +629,9 @@ __log_c_incursor(logc, lsn, hdr, pp)
 	 */
 	p = logc->bp + (lsn->offset - logc->bp_lsn.offset);
 	memcpy(hdr, p, hdr->size);
-	if (__log_c_hdrchk(logc, hdr, NULL))
+	if (__log_c_hdrchk(logc, lsn, hdr, &eof))
 		return (DB_NOTFOUND);
-	if (logc->bp_lsn.offset + logc->bp_rlen <= lsn->offset + hdr->len)
+	if (eof || logc->bp_lsn.offset + logc->bp_rlen < lsn->offset + hdr->len)
 		return (0);
 
 	*pp = p;				/* Success. */
@@ -572,9 +654,9 @@ __log_c_inregion(logc, lsn, rlockp, last_lsn, hdr, pp)
 	DB_ENV *dbenv;
 	DB_LOG *dblp;
 	LOG *lp;
-	size_t len, nr;
-	u_int32_t b_disk, b_region;
-	int ret;
+	size_t b_region, len, nr;
+	u_int32_t b_disk;
+	int eof, ret;
 	u_int8_t *p;
 
 	dbenv = logc->dbenv;
@@ -582,6 +664,7 @@ __log_c_inregion(logc, lsn, rlockp, last_lsn, hdr, pp)
 	lp = ((DB_LOG *)logc->dbenv->lg_handle)->reginfo.primary;
 
 	ret = 0;
+	b_region = 0;
 	*pp = NULL;
 
 	/* If we haven't yet acquired the log region lock, do so. */
@@ -601,7 +684,7 @@ __log_c_inregion(logc, lsn, rlockp, last_lsn, hdr, pp)
 	 * come later than this point if the log buffer isn't empty.
 	 */
 	*last_lsn = lp->lsn;
-	if (last_lsn->offset > lp->w_off)
+	if (!lp->db_log_inmemory && last_lsn->offset > lp->w_off)
 		last_lsn->offset = lp->w_off;
 
 	/*
@@ -628,44 +711,62 @@ __log_c_inregion(logc, lsn, rlockp, last_lsn, hdr, pp)
 	 */
 	if (IS_ZERO_LSN(lp->lsn))
 		return (0);
-	if (lsn->file > lp->lsn.file ||
-	    (lsn->file == lp->lsn.file && lsn->offset >= lp->lsn.offset))
+	if (log_compare(lsn, &lp->lsn) >= 0)
 		return (DB_NOTFOUND);
-	if (lp->b_off == 0)
-		return (0);
-	if (lsn->file < lp->f_lsn.file || lsn->offset < lp->f_lsn.offset)
+	else if (lp->db_log_inmemory) {
+		if ((ret = __log_inmem_lsnoff(dblp, lsn, &b_region)) != 0)
+			return (ret);
+	} else if (lp->b_off == 0 || log_compare(lsn, &lp->f_lsn) < 0)
 		return (0);
 
 	/*
 	 * The current contents of the cursor's buffer will be useless for a
-	 * future call -- trash it rather than try and make it look correct.
+	 * future call, we're about to overwrite it -- trash it rather than
+	 * try and make it look correct.
 	 */
-	ZERO_LSN(logc->bp_lsn);
+	logc->bp_rlen = 0;
 
 	/*
 	 * If the requested LSN is greater than the region buffer's first
-	 * byte, we know the entire record is in the buffer.
+	 * byte, we know the entire record is in the buffer on a good LSN.
 	 *
-	 * If the header check fails for any reason, it must be because the
-	 * LSN is bogus.  Fail hard.
+	 * If we're given a bad LSN, the "entire" record might not be in
+	 * our buffer in order to fail at the chksum.  __log_c_hdrchk made
+	 * sure our dest buffer fits, via bp_maxrec, but we also need to
+	 * make sure we don't run off the end of this buffer, the src.
+	 *
+	 * There is one case where the header check can fail: on a scan through
+	 * in-memory logs, when we reach the end of a file we can read an empty
+	 * heady.  In that case, it's safe to return zero, here: it will be
+	 * caught in our caller.  Otherwise, the LSN is bogus.  Fail hard.
 	 */
-	if (lsn->offset > lp->f_lsn.offset) {
-		p = dblp->bufp + (lsn->offset - lp->w_off);
-		memcpy(hdr, p, hdr->size);
-		if (__log_c_hdrchk(logc, hdr, NULL))
+	if (lp->db_log_inmemory || log_compare(lsn, &lp->f_lsn) > 0) {
+		if (!lp->db_log_inmemory)
+			b_region = lsn->offset - lp->w_off;
+		__log_inmem_copyout(dblp, b_region, hdr, hdr->size);
+		if (__log_c_hdrchk(logc, lsn, hdr, &eof) != 0)
+			return (DB_NOTFOUND);
+		if (eof)
+			return (0);
+		if (lp->db_log_inmemory) {
+			if (RINGBUF_LEN(lp, b_region, lp->b_off) < hdr->len)
+				return (DB_NOTFOUND);
+		} else if (lsn->offset + hdr->len > lp->w_off + lp->buffer_size)
 			return (DB_NOTFOUND);
 		if (logc->bp_size <= hdr->len) {
-			len = ALIGN(hdr->len * 2, 128);
+			len = (size_t)DB_ALIGN(hdr->len * 2, 128);
 			if ((ret =
 			    __os_realloc(logc->dbenv, len, &logc->bp)) != 0)
 				 return (ret);
 			logc->bp_size = (u_int32_t)len;
 		}
-		memcpy(logc->bp, p, hdr->len);
+		__log_inmem_copyout(dblp, b_region, logc->bp, hdr->len);
 		*pp = logc->bp;
 		return (0);
 	}
 
+	DB_ASSERT(!lp->db_log_inmemory);
+
 	/*
 	 * There's a partial record, that is, the requested record starts
 	 * in a log file and finishes in the region buffer.  We have to
@@ -702,7 +803,7 @@ __log_c_inregion(logc, lsn, rlockp, last_lsn, hdr, pp)
 	 * of waiting.
 	 */
 	if (logc->bp_size <= b_region + b_disk) {
-		len = ALIGN((b_region + b_disk) * 2, 128);
+		len = (size_t)DB_ALIGN((b_region + b_disk) * 2, 128);
 		if ((ret = __os_realloc(logc->dbenv, len, &logc->bp)) != 0)
 			return (ret);
 		logc->bp_size = (u_int32_t)len;
@@ -729,7 +830,7 @@ __log_c_inregion(logc, lsn, rlockp, last_lsn, hdr, pp)
 		    logc, lsn->file, lsn->offset, p, &nr, NULL)) != 0)
 			return (ret);
 		if (nr < b_disk)
-			return (__log_c_shortread(logc, 0));
+			return (__log_c_shortread(logc, lsn, 0));
 	}
 
 	/* Copy the header information into the caller's structure. */
@@ -747,7 +848,8 @@ static int
 __log_c_ondisk(logc, lsn, last_lsn, flags, hdr, pp, eofp)
 	DB_LOGC *logc;
 	DB_LSN *lsn, *last_lsn;
-	int flags, *eofp;
+	u_int32_t flags;
+	int *eofp;
 	HDR *hdr;
 	u_int8_t **pp;
 {
@@ -766,27 +868,29 @@ __log_c_ondisk(logc, lsn, last_lsn, flags, hdr, pp, eofp)
 	if (*eofp)
 		return (0);
 
-	/* If we read 0 bytes, assume we've hit EOF. */
-	if (nr == 0) {
+	/*
+	 * If the read was successful, but we can't read a full header, assume
+	 * we've hit EOF.  We can't check that the header has been partially
+	 * zeroed out, but it's unlikely that this is caused by a write failure
+	 * since the header is written as a single write call and it's less
+	 * than sector.
+	 */
+	if (nr < hdr->size) {
 		*eofp = 1;
 		return (0);
 	}
 
 	/* Check the HDR. */
-	if ((ret = __log_c_hdrchk(logc, hdr, eofp)) != 0)
+	if ((ret = __log_c_hdrchk(logc, lsn, hdr, eofp)) != 0)
 		return (ret);
 	if (*eofp)
 		return (0);
 
-	/* Otherwise, we should have gotten the bytes we wanted. */
-	if (nr < hdr->size)
-		return (__log_c_shortread(logc, 0));
-
 	/*
 	 * Regardless of how we return, the previous contents of the cursor's
 	 * buffer are useless -- trash it.
 	 */
-	ZERO_LSN(logc->bp_lsn);
+	logc->bp_rlen = 0;
 
 	/*
 	 * Otherwise, we now (finally!) know how big the record is.  (Maybe
@@ -794,7 +898,7 @@ __log_c_ondisk(logc, lsn, last_lsn, flags, hdr, pp, eofp)
 	 * Make sure we have enough space.
 	 */
 	if (logc->bp_size <= hdr->len) {
-		len = ALIGN(hdr->len * 2, 128);
+		len = (size_t)DB_ALIGN(hdr->len * 2, 128);
 		if ((ret = __os_realloc(dbenv, len, &logc->bp)) != 0)
 			return (ret);
 		logc->bp_size = (u_int32_t)len;
@@ -831,11 +935,15 @@ __log_c_ondisk(logc, lsn, last_lsn, flags, hdr, pp, eofp)
 	 * record we're reading.
 	 */
 	if (nr < (lsn->offset + hdr->len) - offset)
-		return (__log_c_shortread(logc, 1));
+		return (__log_c_shortread(logc, lsn, 1));
 
-	/* Set up the return information. */
+	/*
+	 * Set up the return information.
+	 *
+	 * !!!
+	 * No need to set the bp_lsn.file field, __log_c_io set it for us.
+	 */
 	logc->bp_rlen = (u_int32_t)nr;
-	logc->bp_lsn.file = lsn->file;
 	logc->bp_lsn.offset = offset;
 
 	*pp = logc->bp + (lsn->offset - offset);
@@ -855,16 +963,6 @@ __log_c_ondisk(logc, lsn, last_lsn, flags, hdr, pp, eofp)
  * and one made it to disk before a different one that logically precedes
  * it in the log file.
  *
- * XXX
- * I think there's a potential pre-allocation recovery flaw here -- if we
- * fail to write a buffer at the end of a log file (by scheduling its
- * write asynchronously, and it never making it to disk), then succeed in
- * writing a log file block to a subsequent log file, I don't think we will
- * detect that the buffer of 0's should have marked the end of the log files
- * during recovery.  I think we may need to always write some garbage after
- * each block write if we pre-allocate log files.  (At the moment, we do not
- * pre-allocate, so this isn't currently an issue.)
- *
  * Check for impossibly large records.  The malloc should fail later, but we
  * have customers that run mallocs that treat all allocation failures as fatal
  * errors.
@@ -874,8 +972,9 @@ __log_c_ondisk(logc, lsn, last_lsn, flags, hdr, pp, eofp)
  * the middle of a log record, there's no way to tell.
  */
 static int
-__log_c_hdrchk(logc, hdr, eofp)
+__log_c_hdrchk(logc, lsn, hdr, eofp)
 	DB_LOGC *logc;
+	DB_LSN *lsn;
 	HDR *hdr;
 	int *eofp;
 {
@@ -884,9 +983,24 @@ __log_c_hdrchk(logc, hdr, eofp)
 
 	dbenv = logc->dbenv;
 
-	/* Sanity check the log record's size. */
+	/*
+	 * Check EOF before we do any other processing.
+	 */
+	if (eofp != NULL) {
+		if (hdr->prev == 0 && hdr->chksum[0] == 0 && hdr->len == 0) {
+			*eofp = 1;
+			return (0);
+		}
+		*eofp = 0;
+	}
+
+	/*
+	 * Sanity check the log record's size.
+	 * We must check it after "virtual" EOF above.
+	 */
 	if (hdr->len <= hdr->size)
 		goto err;
+
 	/*
 	 * If the cursor's max-record value isn't yet set, it means we aren't
 	 * reading these records from a log file and no check is necessary.
@@ -904,18 +1018,12 @@ __log_c_hdrchk(logc, hdr, eofp)
 		if (logc->bp_maxrec != 0 && hdr->len > logc->bp_maxrec)
 			goto err;
 	}
-
-	if (eofp != NULL) {
-		if (hdr->prev == 0 && hdr->chksum[0] == 0 && hdr->len == 0) {
-			*eofp = 1;
-			return (0);
-		}
-		*eofp = 0;
-	}
 	return (0);
 
 err:	if (!F_ISSET(logc, DB_LOG_SILENT_ERR))
-		__db_err(dbenv, "DB_LOGC->get: invalid log record header");
+		__db_err(dbenv,
+		    "DB_LOGC->get: LSN %lu/%lu: invalid log record header",
+		    (u_long)lsn->file, (u_long)lsn->offset);
 	return (EIO);
 }
 
@@ -943,12 +1051,17 @@ __log_c_io(logc, fnum, offset, p, nrp, eofp)
 	 * If we've switched files, discard the current file handle and acquire
 	 * a new one.
 	 */
-	if (F_ISSET(logc->c_fh, DB_FH_VALID) && logc->bp_lsn.file != fnum)
-		if ((ret = __os_closehandle(dbenv, logc->c_fh)) != 0)
+	if (logc->c_fhp != NULL && logc->bp_lsn.file != fnum) {
+		ret = __os_closehandle(dbenv, logc->c_fhp);
+		logc->c_fhp = NULL;
+		logc->bp_lsn.file = 0;
+
+		if (ret != 0)
 			return (ret);
-	if (!F_ISSET(logc->c_fh, DB_FH_VALID)) {
+	}
+	if (logc->c_fhp == NULL) {
 		if ((ret = __log_name(dblp, fnum,
-		    &np, logc->c_fh, DB_OSO_RDONLY | DB_OSO_SEQ)) != 0) {
+		    &np, &logc->c_fhp, DB_OSO_RDONLY | DB_OSO_SEQ)) != 0) {
 			/*
 			 * If we're allowed to return EOF, assume that's the
 			 * problem, set the EOF status flag and return 0.
@@ -970,22 +1083,26 @@ __log_c_io(logc, fnum, offset, p, nrp, eofp)
 			return (ret);
 		}
 		__os_free(dbenv, np);
+
+		logc->bp_lsn.file = fnum;
 	}
 
 	/* Seek to the record's offset. */
 	if ((ret = __os_seek(dbenv,
-	    logc->c_fh, 0, 0, offset, 0, DB_OS_SEEK_SET)) != 0) {
+	    logc->c_fhp, 0, 0, offset, 0, DB_OS_SEEK_SET)) != 0) {
 		if (!F_ISSET(logc, DB_LOG_SILENT_ERR))
 			__db_err(dbenv,
-			    "DB_LOGC->get: seek: %s", db_strerror(ret));
+			    "DB_LOGC->get: LSN: %lu/%lu: seek: %s",
+			    (u_long)fnum, (u_long)offset, db_strerror(ret));
 		return (ret);
 	}
 
 	/* Read the data. */
-	if ((ret = __os_read(dbenv, logc->c_fh, p, *nrp, nrp)) != 0) {
+	if ((ret = __os_read(dbenv, logc->c_fhp, p, *nrp, nrp)) != 0) {
 		if (!F_ISSET(logc, DB_LOG_SILENT_ERR))
 			__db_err(dbenv,
-			    "DB_LOGC->get: read: %s", db_strerror(ret));
+			    "DB_LOGC->get: LSN: %lu/%lu: read: %s",
+			    (u_long)fnum, (u_long)offset, db_strerror(ret));
 		return (ret);
 	}
 
@@ -997,12 +1114,14 @@ __log_c_io(logc, fnum, offset, p, nrp, eofp)
  *	Read was short -- return a consistent error message and error.
  */
 static int
-__log_c_shortread(logc, silent)
+__log_c_shortread(logc, lsn, check_silent)
 	DB_LOGC *logc;
-	int silent;
+	DB_LSN *lsn;
+	int check_silent;
 {
-	if (!silent || !F_ISSET(logc, DB_LOG_SILENT_ERR))
-		__db_err(logc->dbenv, "DB_LOGC->get: short read");
+	if (!check_silent || !F_ISSET(logc, DB_LOG_SILENT_ERR))
+		__db_err(logc->dbenv, "DB_LOGC->get: LSN: %lu/%lu: short read",
+		    (u_long)lsn->file, (u_long)lsn->offset);
 	return (EIO);
 }
 
@@ -1033,11 +1152,13 @@ __log_c_set_maxrec(logc, np)
 	 * of the file but that's hard -- we may have to decrypt it, checksum
 	 * it and so on.  Stat the file instead.
 	 */
-	if ((ret =
-	    __os_ioinfo(dbenv, np, logc->c_fh, &mbytes, &bytes, NULL)) != 0)
-		return (ret);
-
-	logc->bp_maxrec = mbytes * MEGABYTE + bytes;
+	if (logc->c_fhp != NULL) {
+		if ((ret = __os_ioinfo(dbenv, np, logc->c_fhp,
+		    &mbytes, &bytes, NULL)) != 0)
+			return (ret);
+		if (logc->bp_maxrec < (mbytes * MEGABYTE + bytes))
+			logc->bp_maxrec = mbytes * MEGABYTE + bytes;
+	}
 
 	/*
 	 * If reading from the log file currently being written, we could get
@@ -1052,7 +1173,8 @@ __log_c_set_maxrec(logc, np)
 	 * changed, we don't need a lock on it.
 	 */
 	lp = dblp->reginfo.primary;
-	logc->bp_maxrec += lp->buffer_size;
+	if (logc->bp_maxrec < lp->buffer_size)
+		logc->bp_maxrec = lp->buffer_size;
 
 	return (0);
 }
diff --git a/storage/bdb/log/log_method.c b/storage/bdb/log/log_method.c
index 42adaf11c6ce247fd16f52075c63a789afe3e5af..1565a53a07792835fef20349ec0520ffda429c23 100644
--- a/storage/bdb/log/log_method.c
+++ b/storage/bdb/log/log_method.c
@@ -1,14 +1,13 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: log_method.c,v 11.50 2004/09/22 16:26:15 bostic Exp $
  */
-#include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: log_method.c,v 11.32 2002/05/30 22:16:47 bostic Exp $";
-#endif /* not lint */
+#include "db_config.h"
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
@@ -19,21 +18,23 @@ static const char revid[] = "$Id: log_method.c,v 11.32 2002/05/30 22:16:47 bosti
 
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
+#endif
+
+#ifdef HAVE_RPC
+#include "db_server.h"
 #endif
 
 #include "db_int.h"
 #include "dbinc/log.h"
 
 #ifdef HAVE_RPC
-#include "dbinc_auto/db_server.h"
 #include "dbinc_auto/rpc_client_ext.h"
 #endif
 
-static int __log_set_lg_bsize __P((DB_ENV *, u_int32_t));
-static int __log_set_lg_dir __P((DB_ENV *, const char *));
-static int __log_set_lg_max __P((DB_ENV *, u_int32_t));
-static int __log_set_lg_regionmax __P((DB_ENV *, u_int32_t));
+static int __log_get_lg_bsize __P((DB_ENV *, u_int32_t *));
+static int __log_get_lg_dir __P((DB_ENV *, const char **));
+static int __log_get_lg_max __P((DB_ENV *, u_int32_t *));
+static int __log_get_lg_regionmax __P((DB_ENV *, u_int32_t *));
 
 /*
  * __log_dbenv_create --
@@ -52,7 +53,7 @@ __log_dbenv_create(dbenv)
 	 * the panic state or acquire a mutex in the DB_ENV create path.
 	 */
 
-	dbenv->lg_bsize = LG_BSIZE_DEFAULT;
+	dbenv->lg_bsize = 0;
 	dbenv->lg_regionmax = LG_BASE_REGION_SIZE;
 
 #ifdef	HAVE_RPC
@@ -61,106 +62,160 @@ __log_dbenv_create(dbenv)
 	 * point to client functions.
 	 */
 	if (F_ISSET(dbenv, DB_ENV_RPCCLIENT)) {
+		dbenv->get_lg_bsize = __dbcl_get_lg_bsize;
 		dbenv->set_lg_bsize = __dbcl_set_lg_bsize;
+		dbenv->get_lg_dir = __dbcl_get_lg_dir;
 		dbenv->set_lg_dir = __dbcl_set_lg_dir;
+		dbenv->get_lg_max = __dbcl_get_lg_max;
 		dbenv->set_lg_max = __dbcl_set_lg_max;
+		dbenv->get_lg_regionmax = __dbcl_get_lg_regionmax;
 		dbenv->set_lg_regionmax = __dbcl_set_lg_regionmax;
+
 		dbenv->log_archive = __dbcl_log_archive;
 		dbenv->log_cursor = __dbcl_log_cursor;
 		dbenv->log_file = __dbcl_log_file;
 		dbenv->log_flush = __dbcl_log_flush;
 		dbenv->log_put = __dbcl_log_put;
 		dbenv->log_stat = __dbcl_log_stat;
+		dbenv->log_stat_print = NULL;
 	} else
 #endif
 	{
+		dbenv->get_lg_bsize = __log_get_lg_bsize;
 		dbenv->set_lg_bsize = __log_set_lg_bsize;
+		dbenv->get_lg_dir = __log_get_lg_dir;
 		dbenv->set_lg_dir = __log_set_lg_dir;
+		dbenv->get_lg_max = __log_get_lg_max;
 		dbenv->set_lg_max = __log_set_lg_max;
+		dbenv->get_lg_regionmax = __log_get_lg_regionmax;
 		dbenv->set_lg_regionmax = __log_set_lg_regionmax;
-		dbenv->log_archive = __log_archive;
-		dbenv->log_cursor = __log_cursor;
-		dbenv->log_file = __log_file;
-		dbenv->log_flush = __log_flush;
-		dbenv->log_put = __log_put;
-		dbenv->log_stat = __log_stat;
+
+		dbenv->log_archive = __log_archive_pp;
+		dbenv->log_cursor = __log_cursor_pp;
+		dbenv->log_file = __log_file_pp;
+		dbenv->log_flush = __log_flush_pp;
+		dbenv->log_put = __log_put_pp;
+		dbenv->log_stat = __log_stat_pp;
+		dbenv->log_stat_print = __log_stat_print_pp;
 	}
 }
 
+static int
+__log_get_lg_bsize(dbenv, lg_bsizep)
+	DB_ENV *dbenv;
+	u_int32_t *lg_bsizep;
+{
+	ENV_NOT_CONFIGURED(dbenv,
+	    dbenv->lg_handle, "DB_ENV->get_lg_bsize", DB_INIT_LOG);
+
+	if (LOGGING_ON(dbenv)) {
+		/* Cannot be set after open, no lock required to read. */
+		*lg_bsizep = ((LOG *)
+		    ((DB_LOG *)dbenv->lg_handle)->reginfo.primary)->buffer_size;
+	} else
+		*lg_bsizep = dbenv->lg_bsize;
+	return (0);
+}
+
 /*
  * __log_set_lg_bsize --
- *	Set the log buffer size.
+ *	DB_ENV->set_lg_bsize.
+ *
+ * PUBLIC: int __log_set_lg_bsize __P((DB_ENV *, u_int32_t));
  */
-static int
+int
 __log_set_lg_bsize(dbenv, lg_bsize)
 	DB_ENV *dbenv;
 	u_int32_t lg_bsize;
 {
-	u_int32_t lg_max;
+	ENV_ILLEGAL_AFTER_OPEN(dbenv, "DB_ENV->set_lg_bsize");
 
-	ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_lg_bsize");
+	dbenv->lg_bsize = lg_bsize;
+	return (0);
+}
 
-	if (lg_bsize == 0)
-		lg_bsize = LG_BSIZE_DEFAULT;
+static int
+__log_get_lg_max(dbenv, lg_maxp)
+	DB_ENV *dbenv;
+	u_int32_t *lg_maxp;
+{
+	DB_LOG *dblp;
 
-					/* Let's not be silly. */
-	lg_max = dbenv->lg_size == 0 ? LG_MAX_DEFAULT : dbenv->lg_size;
-	if (lg_bsize > lg_max / 4) {
-		__db_err(dbenv, "log buffer size must be <= log file size / 4");
-		return (EINVAL);
-	}
+	ENV_NOT_CONFIGURED(dbenv,
+	    dbenv->lg_handle, "DB_ENV->get_lg_max", DB_INIT_LOG);
+
+	if (LOGGING_ON(dbenv)) {
+		dblp = dbenv->lg_handle;
+		R_LOCK(dbenv, &dblp->reginfo);
+		*lg_maxp = ((LOG *)dblp->reginfo.primary)->log_nsize;
+		R_UNLOCK(dbenv, &dblp->reginfo);
+	} else
+		*lg_maxp = dbenv->lg_size;
 
-	dbenv->lg_bsize = lg_bsize;
 	return (0);
 }
 
 /*
  * __log_set_lg_max --
- *	Set the maximum log file size.
+ *	DB_ENV->set_lg_max.
+ *
+ * PUBLIC: int __log_set_lg_max __P((DB_ENV *, u_int32_t));
  */
-static int
+int
 __log_set_lg_max(dbenv, lg_max)
 	DB_ENV *dbenv;
 	u_int32_t lg_max;
 {
-	LOG *region;
+	DB_LOG *dblp;
+	LOG *lp;
+	int ret;
 
-	if (lg_max == 0)
-		lg_max = LG_MAX_DEFAULT;
+	ENV_NOT_CONFIGURED(dbenv,
+	    dbenv->lg_handle, "DB_ENV->set_lg_max", DB_INIT_LOG);
 
-	if (F_ISSET(dbenv, DB_ENV_OPEN_CALLED)) {
-		if (!LOGGING_ON(dbenv))
-			return (__db_env_config(
-			    dbenv, "set_lg_max", DB_INIT_LOG));
-		region = ((DB_LOG *)dbenv->lg_handle)->reginfo.primary;
-
-					/* Let's not be silly. */
-		if (lg_max < region->buffer_size * 4)
-			goto err;
-		region->log_nsize = lg_max;
-	} else {
-					/* Let's not be silly. */
-		if (lg_max < dbenv->lg_bsize * 4)
-			goto err;
+	if (LOGGING_ON(dbenv)) {
+		if ((ret = __log_check_sizes(dbenv, lg_max, 0)) != 0)
+			return (ret);
+		dblp = dbenv->lg_handle;
+		lp = dblp->reginfo.primary;
+		R_LOCK(dbenv, &dblp->reginfo);
+		lp->log_nsize = lg_max;
+		R_UNLOCK(dbenv, &dblp->reginfo);
+	} else
 		dbenv->lg_size = lg_max;
-	}
 
 	return (0);
+}
 
-err:	__db_err(dbenv, "log file size must be >= log buffer size * 4");
-	return (EINVAL);
+static int
+__log_get_lg_regionmax(dbenv, lg_regionmaxp)
+	DB_ENV *dbenv;
+	u_int32_t *lg_regionmaxp;
+{
+	ENV_NOT_CONFIGURED(dbenv,
+	    dbenv->lg_handle, "DB_ENV->get_lg_regionmax", DB_INIT_LOG);
+
+	if (LOGGING_ON(dbenv)) {
+		/* Cannot be set after open, no lock required to read. */
+		*lg_regionmaxp = ((LOG *)
+		    ((DB_LOG *)dbenv->lg_handle)->reginfo.primary)->regionmax;
+	} else
+		*lg_regionmaxp = dbenv->lg_regionmax;
+	return (0);
 }
 
 /*
  * __log_set_lg_regionmax --
- *	Set the region size.
+ *	DB_ENV->set_lg_regionmax.
+ *
+ * PUBLIC: int __log_set_lg_regionmax __P((DB_ENV *, u_int32_t));
  */
-static int
+int
 __log_set_lg_regionmax(dbenv, lg_regionmax)
 	DB_ENV *dbenv;
 	u_int32_t lg_regionmax;
 {
-	ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_lg_regionmax");
+	ENV_ILLEGAL_AFTER_OPEN(dbenv, "DB_ENV->set_lg_regionmax");
 
 					/* Let's not be silly. */
 	if (lg_regionmax != 0 && lg_regionmax < LG_BASE_REGION_SIZE) {
@@ -173,11 +228,22 @@ __log_set_lg_regionmax(dbenv, lg_regionmax)
 	return (0);
 }
 
+static int
+__log_get_lg_dir(dbenv, dirp)
+	DB_ENV *dbenv;
+	const char **dirp;
+{
+	*dirp = dbenv->db_log_dir;
+	return (0);
+}
+
 /*
  * __log_set_lg_dir --
- *	Set the log file directory.
+ *	DB_ENV->set_lg_dir.
+ *
+ * PUBLIC: int __log_set_lg_dir __P((DB_ENV *, const char *));
  */
-static int
+int
 __log_set_lg_dir(dbenv, dir)
 	DB_ENV *dbenv;
 	const char *dir;
@@ -186,3 +252,99 @@ __log_set_lg_dir(dbenv, dir)
 		__os_free(dbenv, dbenv->db_log_dir);
 	return (__os_strdup(dbenv, dir, &dbenv->db_log_dir));
 }
+
+/*
+ * __log_get_flags --
+ *	DB_ENV->get_flags.
+ *
+ * PUBLIC: void __log_get_flags __P((DB_ENV *, u_int32_t *));
+ */
+void
+__log_get_flags(dbenv, flagsp)
+	DB_ENV *dbenv;
+	u_int32_t *flagsp;
+{
+	DB_LOG *dblp;
+	LOG *lp;
+	u_int32_t flags;
+
+	if ((dblp = dbenv->lg_handle) == NULL)
+		return;
+
+	lp = dblp->reginfo.primary;
+
+	flags = *flagsp;
+	if (lp->db_log_autoremove)
+		LF_SET(DB_LOG_AUTOREMOVE);
+	else
+		LF_CLR(DB_LOG_AUTOREMOVE);
+	if (lp->db_log_inmemory)
+		LF_SET(DB_LOG_INMEMORY);
+	else
+		LF_CLR(DB_LOG_INMEMORY);
+	*flagsp = flags;
+}
+
+/*
+ * __log_set_flags --
+ *	DB_ENV->set_flags.
+ *
+ * PUBLIC: void __log_set_flags __P((DB_ENV *, u_int32_t, int));
+ */
+void
+__log_set_flags(dbenv, flags, on)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+	int on;
+{
+	DB_LOG *dblp;
+	LOG *lp;
+
+	if ((dblp = dbenv->lg_handle) == NULL)
+		return;
+
+	lp = dblp->reginfo.primary;
+
+	if (LF_ISSET(DB_LOG_AUTOREMOVE))
+		lp->db_log_autoremove = on ? 1 : 0;
+	if (LF_ISSET(DB_LOG_INMEMORY))
+		lp->db_log_inmemory = on ? 1 : 0;
+}
+
+/*
+ * __log_check_sizes --
+ *	Makes sure that the log file size and log buffer size are compatible.
+ *
+ * PUBLIC: int __log_check_sizes __P((DB_ENV *, u_int32_t, u_int32_t));
+ */
+int
+__log_check_sizes(dbenv, lg_max, lg_bsize)
+	DB_ENV *dbenv;
+	u_int32_t lg_max;
+	u_int32_t lg_bsize;
+{
+	LOG *lp;
+	int inmem;
+
+	if (LOGGING_ON(dbenv)) {
+		lp = ((DB_LOG *)dbenv->lg_handle)->reginfo.primary;
+		inmem = lp->db_log_inmemory;
+		lg_bsize = lp->buffer_size;
+	} else
+		inmem = (F_ISSET(dbenv, DB_ENV_LOG_INMEMORY) != 0);
+
+	if (inmem) {
+		if (lg_bsize == 0)
+			lg_bsize = LG_BSIZE_INMEM;
+		if (lg_max == 0)
+			lg_max = LG_MAX_INMEM;
+
+		if (lg_bsize <= lg_max) {
+			__db_err(dbenv,
+		  "in-memory log buffer must be larger than the log file size");
+			return (EINVAL);
+		}
+	}
+
+	return (0);
+}
diff --git a/storage/bdb/log/log_put.c b/storage/bdb/log/log_put.c
index 64276fa8315f2815e094b7044ab52e9a56e2c4fa..86deffe86410eb32abf8bda1d79f6c972377847d 100644
--- a/storage/bdb/log/log_put.c
+++ b/storage/bdb/log/log_put.c
@@ -1,14 +1,13 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: log_put.c,v 11.168 2004/10/15 16:59:42 bostic Exp $
  */
-#include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: log_put.c,v 11.112 2002/09/10 02:39:26 bostic Exp $";
-#endif /* not lint */
+#include "db_config.h"
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
@@ -26,21 +25,19 @@ static const char revid[] = "$Id: log_put.c,v 11.112 2002/09/10 02:39:26 bostic
 
 #include <stdio.h>
 #include <string.h>
-#include <unistd.h>
 #endif
 
 #include "db_int.h"
 #include "dbinc/crypto.h"
 #include "dbinc/hmac.h"
 #include "dbinc/log.h"
-#include "dbinc/rep.h"
 #include "dbinc/txn.h"
 
 static int __log_encrypt_record __P((DB_ENV *, DBT *, HDR *, u_int32_t));
+static int __log_file __P((DB_ENV *, const DB_LSN *, char *, size_t));
 static int __log_fill __P((DB_LOG *, DB_LSN *, void *, u_int32_t));
 static int __log_flush_commit __P((DB_ENV *, const DB_LSN *, u_int32_t));
-static int __log_flush_int __P((DB_LOG *, const DB_LSN *, int));
-static int __log_newfh __P((DB_LOG *));
+static int __log_newfh __P((DB_LOG *, int));
 static int __log_put_next __P((DB_ENV *,
     DB_LSN *, const DBT *, HDR *, DB_LSN *));
 static int __log_putr __P((DB_LOG *,
@@ -48,75 +45,91 @@ static int __log_putr __P((DB_LOG *,
 static int __log_write __P((DB_LOG *, void *, u_int32_t));
 
 /*
- * __log_put --
- *	Write a log record.  This is the public interface, DB_ENV->log_put.
+ * __log_put_pp --
+ *	DB_ENV->log_put pre/post processing.
  *
- * PUBLIC: int __log_put __P((DB_ENV *, DB_LSN *, const DBT *, u_int32_t));
+ * PUBLIC: int __log_put_pp __P((DB_ENV *, DB_LSN *, const DBT *, u_int32_t));
  */
 int
-__log_put(dbenv, lsnp, udbt, flags)
+__log_put_pp(dbenv, lsnp, udbt, flags)
 	DB_ENV *dbenv;
 	DB_LSN *lsnp;
 	const DBT *udbt;
 	u_int32_t flags;
 {
-	DB_CIPHER *db_cipher;
-	DBT *dbt, t;
-	DB_LOG *dblp;
-	DB_LSN lsn, old_lsn;
-	HDR hdr;
-	LOG *lp;
-	u_int32_t do_flush, op, writeonly;
-	int lock_held, need_free, ret;
-	u_int8_t *key;
+	int rep_check, ret;
 
 	PANIC_CHECK(dbenv);
 	ENV_REQUIRES_CONFIG(dbenv,
 	    dbenv->lg_handle, "DB_ENV->log_put", DB_INIT_LOG);
 
-	/* Validate arguments. */
-	op = DB_OPFLAGS_MASK & flags;
-	if (op != 0 && op != DB_COMMIT)
-		return (__db_ferr(dbenv, "DB_ENV->log_put", 0));
-
-	/* Check for allowed bit-flags. */
-	if (LF_ISSET(~(DB_OPFLAGS_MASK |
-	    DB_FLUSH | DB_NOCOPY | DB_PERMANENT | DB_WRNOSYNC)))
-		return (__db_ferr(dbenv, "DB_ENV->log_put", 0));
+	/* Validate arguments: check for allowed flags. */
+	if ((ret = __db_fchk(dbenv, "DB_ENV->log_put", flags,
+	    DB_LOG_CHKPNT | DB_LOG_COMMIT |
+	    DB_FLUSH | DB_LOG_NOCOPY | DB_LOG_PERM | DB_LOG_WRNOSYNC)) != 0)
+		return (ret);
 
-	/* DB_WRNOSYNC and DB_FLUSH are mutually exclusive. */
-	if (LF_ISSET(DB_WRNOSYNC) && LF_ISSET(DB_FLUSH))
+	/* DB_LOG_WRNOSYNC and DB_FLUSH are mutually exclusive. */
+	if (LF_ISSET(DB_LOG_WRNOSYNC) && LF_ISSET(DB_FLUSH))
 		return (__db_ferr(dbenv, "DB_ENV->log_put", 1));
 
 	/* Replication clients should never write log records. */
-	if (F_ISSET(dbenv, DB_ENV_REP_CLIENT) ||
-	    F_ISSET(dbenv, DB_ENV_REP_LOGSONLY)) {
+	if (IS_REP_CLIENT(dbenv)) {
 		__db_err(dbenv,
 		    "DB_ENV->log_put is illegal on replication clients");
 		return (EINVAL);
 	}
 
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __log_put(dbenv, lsnp, udbt, flags);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
+/*
+ * __log_put --
+ *	DB_ENV->log_put.
+ *
+ * PUBLIC: int __log_put __P((DB_ENV *, DB_LSN *, const DBT *, u_int32_t));
+ */
+int
+__log_put(dbenv, lsnp, udbt, flags)
+	DB_ENV *dbenv;
+	DB_LSN *lsnp;
+	const DBT *udbt;
+	u_int32_t flags;
+{
+	DB_CIPHER *db_cipher;
+	DBT *dbt, t;
+	DB_LOG *dblp;
+	DB_LSN lsn, old_lsn;
+	HDR hdr;
+	LOG *lp;
+	int lock_held, need_free, ret;
+	u_int8_t *key;
+
 	dblp = dbenv->lg_handle;
 	lp = dblp->reginfo.primary;
 	db_cipher = dbenv->crypto_handle;
 	dbt = &t;
 	t = *udbt;
 	lock_held = need_free = 0;
-	do_flush = LF_ISSET(DB_FLUSH);
-	writeonly = LF_ISSET(DB_WRNOSYNC);
+	ZERO_LSN(old_lsn);
 
 	/*
-	 * If we are coming from the logging code, we use an internal
-	 * flag, DB_NOCOPY, because we know we can overwrite/encrypt
-	 * the log record in place.  Otherwise, if a user called log_put
-	 * then we must copy it to new memory so that we know we can
-	 * write it.
+	 * If we are coming from the logging code, we use an internal flag,
+	 * DB_LOG_NOCOPY, because we know we can overwrite/encrypt the log
+	 * record in place.  Otherwise, if a user called log_put then we
+	 * must copy it to new memory so that we know we can write it.
 	 *
-	 * We also must copy it to new memory if we are a replication
-	 * master so that we retain an unencrypted copy of the log
-	 * record to send to clients.
+	 * We also must copy it to new memory if we are a replication master
+	 * so that we retain an unencrypted copy of the log record to send
+	 * to clients.
 	 */
-	if (!LF_ISSET(DB_NOCOPY) || F_ISSET(dbenv, DB_ENV_REP_MASTER)) {
+	if (!LF_ISSET(DB_LOG_NOCOPY) || IS_REP_MASTER(dbenv)) {
 		if (CRYPTO_ON(dbenv))
 			t.size += db_cipher->adj_size(udbt->size);
 		if ((ret = __os_calloc(dbenv, 1, t.size, &t.data)) != 0)
@@ -138,28 +151,45 @@ __log_put(dbenv, lsnp, udbt, flags)
 	R_LOCK(dbenv, &dblp->reginfo);
 	lock_held = 1;
 
-	ZERO_LSN(old_lsn);
 	if ((ret = __log_put_next(dbenv, &lsn, dbt, &hdr, &old_lsn)) != 0)
+		goto panic_check;
+
+	/*
+	 * If we are not a rep application, but are sharing a master rep env,
+	 * we should not be writing log records.
+	 */
+	if (IS_REP_MASTER(dbenv) && dbenv->rep_send == NULL) {
+		__db_err(dbenv, "%s %s",
+		    "Non-replication DB_ENV handle attempting",
+		    "to modify a replicated environment");
+		ret = EINVAL;
 		goto err;
+	}
+
+	/*
+	 * Assign the return LSN before dropping the region lock.  Necessary
+	 * in case the lsn is a begin_lsn from a TXN_DETAIL structure passed
+	 * in by the logging routines.
+	 */
+	*lsnp = lsn;
 
-	if (F_ISSET(dbenv, DB_ENV_REP_MASTER)) {
+	if (IS_REP_MASTER(dbenv)) {
 		/*
-		 * Replication masters need to drop the lock to send
-		 * messages, but we want to drop and reacquire it a minimal
-		 * number of times.
+		 * Replication masters need to drop the lock to send messages,
+		 * but want to drop and reacquire it a minimal number of times.
 		 */
 		R_UNLOCK(dbenv, &dblp->reginfo);
 		lock_held = 0;
 
 		/*
-		 * If we changed files and we're in a replicated
-		 * environment, we need to inform our clients now that
-		 * we've dropped the region lock.
+		 * If we changed files and we're in a replicated environment,
+		 * we need to inform our clients now that we've dropped the
+		 * region lock.
 		 *
-		 * Note that a failed NEWFILE send is a dropped message
-		 * that our client can handle, so we can ignore it.  It's
-		 * possible that the record we already put is a commit, so
-		 * we don't just want to return failure.
+		 * Note that a failed NEWFILE send is a dropped message that
+		 * our client can handle, so we can ignore it.  It's possible
+		 * that the record we already put is a commit, so we don't just
+		 * want to return failure.
 		 */
 		if (!IS_ZERO_LSN(old_lsn))
 			(void)__rep_send_message(dbenv,
@@ -181,8 +211,8 @@ __log_put(dbenv, lsnp, udbt, flags)
 		 */
 		if ((__rep_send_message(dbenv,
 		    DB_EID_BROADCAST, REP_LOG, &lsn, udbt, flags) != 0) &&
-		    LF_ISSET(DB_PERMANENT))
-			do_flush |= DB_FLUSH;
+		    LF_ISSET(DB_LOG_PERM))
+			LF_SET(DB_FLUSH);
 	}
 
 	/*
@@ -193,21 +223,32 @@ __log_put(dbenv, lsnp, udbt, flags)
 	 * If a flush is not needed, see if WRITE_NOSYNC was set and we
 	 * need to write out the log buffer.
 	 */
-	if (do_flush || writeonly) {
+	if (LF_ISSET(DB_FLUSH | DB_LOG_WRNOSYNC)) {
 		if (!lock_held) {
 			R_LOCK(dbenv, &dblp->reginfo);
 			lock_held = 1;
 		}
-		if (do_flush)
-			ret = __log_flush_commit(dbenv, &lsn, flags);
-		else if (lp->b_off != 0)
-			/*
-			 * writeonly: if there's anything in the current
-			 * log buffer, we need to write it out.
-			 */
-			if ((ret = __log_write(dblp,
-			    dblp->bufp, (u_int32_t)lp->b_off)) == 0)
-				lp->b_off = 0;
+		if ((ret = __log_flush_commit(dbenv, &lsn, flags)) != 0)
+			goto panic_check;
+	}
+
+	/*
+	 * If flushed a checkpoint record, reset the "bytes since the last
+	 * checkpoint" counters.
+	 */
+	if (LF_ISSET(DB_LOG_CHKPNT))
+		lp->stat.st_wc_bytes = lp->stat.st_wc_mbytes = 0;
+
+	if (0) {
+panic_check:	/*
+		 * Writing log records cannot fail if we're a replication
+		 * master.  The reason is that once we send the record to
+		 * replication clients, the transaction can no longer
+		 * abort, otherwise the master would be out of sync with
+		 * the rest of the replication group.  Panic the system.
+		 */
+		if (ret != 0 && IS_REP_MASTER(dbenv))
+			ret = __db_panic(dbenv, ret);
 	}
 
 err:	if (lock_held)
@@ -215,8 +256,12 @@ err:	if (lock_held)
 	if (need_free)
 		__os_free(dbenv, dbt->data);
 
-	if (ret == 0)
-		*lsnp = lsn;
+	/*
+	 * If auto-remove is set and we switched files, remove unnecessary
+	 * log files.
+	 */
+	if (ret == 0 && !IS_ZERO_LSN(old_lsn) && lp->db_log_autoremove)
+		__log_autoremove(dbenv);
 
 	return (ret);
 }
@@ -243,7 +288,7 @@ __log_txn_lsn(dbenv, lsnp, mbytesp, bytesp)
 
 	/*
 	 * We are trying to get the LSN of the last entry in the log.  We use
-	 * this in two places: 1) DB_ENV->txn_checkpiont uses it as a first
+	 * this in two places: 1) DB_ENV->txn_checkpoint uses it as a first
 	 * value when trying to compute an LSN such that all transactions begun
 	 * before it are complete.   2) DB_ENV->txn_begin uses it as the
 	 * begin_lsn.
@@ -268,8 +313,6 @@ __log_txn_lsn(dbenv, lsnp, mbytesp, bytesp)
 	if (mbytesp != NULL) {
 		*mbytesp = lp->stat.st_wc_mbytes;
 		*bytesp = (u_int32_t)(lp->stat.st_wc_bytes + lp->b_off);
-
-		lp->stat.st_wc_mbytes = lp->stat.st_wc_bytes = 0;
 	}
 
 	R_UNLOCK(dbenv, &dblp->reginfo);
@@ -316,11 +359,13 @@ __log_put_next(dbenv, lsn, dbt, hdr, old_lsnp)
 	    lp->lsn.offset + hdr->size + dbt->size > lp->log_size) {
 		if (hdr->size + sizeof(LOGP) + dbt->size > lp->log_size) {
 			__db_err(dbenv,
-		    "DB_ENV->log_put: record larger than maximum file size");
+	    "DB_ENV->log_put: record larger than maximum file size (%lu > %lu)",
+			    (u_long)hdr->size + sizeof(LOGP) + dbt->size,
+			    (u_long)lp->log_size);
 			return (EINVAL);
 		}
 
-		if ((ret = __log_newfile(dblp, NULL)) != 0)
+		if ((ret = __log_newfile(dblp, NULL, 0)) != 0)
 			return (ret);
 
 		/*
@@ -331,9 +376,6 @@ __log_put_next(dbenv, lsn, dbt, hdr, old_lsnp)
 		 * anyway.
 		 */
 		newfile = 1;
-		
-		if (dbenv->db_noticecall != NULL)
-			dbenv->db_noticecall(dbenv, DB_NOTICE_LOGFILE_CHANGED);
 	}
 
 	/*
@@ -352,7 +394,7 @@ __log_put_next(dbenv, lsn, dbt, hdr, old_lsnp)
 
 /*
  * __log_flush_commit --
- *	Flush a record for which the DB_FLUSH flag to log_put has been set.
+ *	Flush a record.
  */
 static int
 __log_flush_commit(dbenv, lsnp, flags)
@@ -364,15 +406,26 @@ __log_flush_commit(dbenv, lsnp, flags)
 	DB_LSN flush_lsn;
 	LOG *lp;
 	int ret;
-	u_int32_t op;
 
 	dblp = dbenv->lg_handle;
 	lp = dblp->reginfo.primary;
 	flush_lsn = *lsnp;
-	op = DB_OPFLAGS_MASK & flags;
 
-	if ((ret = __log_flush_int(dblp, &flush_lsn, 1)) == 0)
-		return (0);
+	ret = 0;
+
+	/*
+	 * DB_FLUSH:
+	 *	Flush a record for which the DB_FLUSH flag to log_put was set.
+	 *
+	 * DB_LOG_WRNOSYNC:
+	 *	If there's anything in the current log buffer, write it out.
+	 */
+	if (LF_ISSET(DB_FLUSH))
+		ret = __log_flush_int(dblp, &flush_lsn, 1);
+	else if (!lp->db_log_inmemory && lp->b_off != 0)
+		if ((ret = __log_write(dblp,
+		    dblp->bufp, (u_int32_t)lp->b_off)) == 0)
+			lp->b_off = 0;
 
 	/*
 	 * If a flush supporting a transaction commit fails, we must abort the
@@ -380,7 +433,7 @@ __log_flush_commit(dbenv, lsnp, flags)
 	 * if the commit we care about made it to disk successfully, we just
 	 * ignore the failure, because there's no way to undo the commit.)
 	 */
-	if (op != DB_COMMIT)
+	if (ret == 0 || !LF_ISSET(DB_LOG_COMMIT))
 		return (ret);
 
 	if (flush_lsn.file != lp->lsn.file || flush_lsn.offset < lp->w_off)
@@ -390,7 +443,7 @@ __log_flush_commit(dbenv, lsnp, flags)
 	 * Else, make sure that the commit record does not get out after we
 	 * abort the transaction.  Do this by overwriting the commit record
 	 * in the buffer.  (Note that other commits in this buffer will wait
-	 * wait until a sucessful write happens, we do not wake them.)  We
+	 * wait until a successful write happens, we do not wake them.)  We
 	 * point at the right part of the buffer and write an abort record
 	 * over the commit.  We must then try and flush the buffer again,
 	 * since the interesting part of the buffer may have actually made
@@ -408,12 +461,13 @@ __log_flush_commit(dbenv, lsnp, flags)
  *	Initialize and switch to a new log file.  (Note that this is
  * called both when no log yet exists and when we fill a log file.)
  *
- * PUBLIC: int __log_newfile __P((DB_LOG *, DB_LSN *));
+ * PUBLIC: int __log_newfile __P((DB_LOG *, DB_LSN *, u_int32_t));
  */
 int
-__log_newfile(dblp, lsnp)
+__log_newfile(dblp, lsnp, logfile)
 	DB_LOG *dblp;
 	DB_LSN *lsnp;
+	u_int32_t logfile;
 {
 	DB_CIPHER *db_cipher;
 	DB_ENV *dbenv;
@@ -429,6 +483,8 @@ __log_newfile(dblp, lsnp)
 	dbenv = dblp->dbenv;
 	lp = dblp->reginfo.primary;
 
+	DB_ASSERT(logfile == 0 || logfile > lp->lsn.file);
+
 	/* If we're not at the beginning of a file already, start a new one. */
 	if (lp->lsn.offset != 0) {
 		/*
@@ -441,13 +497,12 @@ __log_newfile(dblp, lsnp)
 		 * require all threads to wait here so that the lsn.file
 		 * can be moved ahead after the flush completes.  This
 		 * probably can be changed if we had an lsn for the
-		 * previous file and one for the curent, but it does not
+		 * previous file and one for the current, but it does not
 		 * seem like this would get much more throughput, if any.
 		 */
 		if ((ret = __log_flush_int(dblp, NULL, 0)) != 0)
 			return (ret);
 
-		DB_ASSERT(lp->b_off == 0);
 		/*
 		 * Save the last known offset from the previous file, we'll
 		 * need it to initialize the persistent header information.
@@ -463,13 +518,28 @@ __log_newfile(dblp, lsnp)
 	} else
 		lastoff = 0;
 
+	/*
+	 * Replication may require we reset the log file name space entirely.
+	 * In that case we also force a file switch so that replication can
+	 * clean up old files.
+	 */
+	if (logfile != 0) {
+		lp->lsn.file = logfile;
+		lp->lsn.offset = 0;
+		if ((ret = __log_newfh(dblp, 1)) != 0)
+			return (ret);
+	}
+
+	DB_ASSERT(lp->db_log_inmemory || lp->b_off == 0);
+	if (lp->db_log_inmemory &&
+	    (ret = __log_inmem_newfile(dblp, lp->lsn.file)) != 0)
+		return (ret);
+
 	/*
 	 * Insert persistent information as the first record in every file.
 	 * Note that the previous length is wrong for the very first record
 	 * of the log, but that's okay, we check for it during retrieval.
 	 */
-	DB_ASSERT(lp->b_off == 0);
-
 	memset(&t, 0, sizeof(t));
 	memset(&hdr, 0, sizeof(HDR));
 
@@ -500,8 +570,7 @@ __log_newfile(dblp, lsnp)
 	if (lsnp != NULL)
 		*lsnp = lp->lsn;
 
-err:
-	if (need_free)
+err:	if (need_free)
 		__os_free(dbenv, tmp);
 	return (ret);
 }
@@ -570,6 +639,10 @@ __log_putr(dblp, lsn, dbt, prev, h)
 		    (CRYPTO_ON(dbenv)) ? db_cipher->mac_key : NULL,
 		    hdr->chksum);
 
+	if (lp->db_log_inmemory && (ret = __log_inmem_chkspace(dblp,
+	    (u_int32_t)hdr->size + dbt->size)) != 0)
+		goto err;
+
 	if ((ret = __log_fill(dblp, lsn, hdr, (u_int32_t)hdr->size)) != 0)
 		goto err;
 
@@ -586,10 +659,10 @@ err:
 	 * and be ignored.
 	 */
 	if (w_off + lp->buffer_size < lp->w_off) {
-		if ((t_ret =
-		    __os_seek(dbenv,
-		    &dblp->lfh, 0, 0, w_off, 0, DB_OS_SEEK_SET)) != 0 ||
-		    (t_ret = __os_read(dbenv, &dblp->lfh, dblp->bufp,
+		DB_ASSERT(!lp->db_log_inmemory);
+		if ((t_ret = __os_seek(dbenv,
+		    dblp->lfhp, 0, 0, w_off, 0, DB_OS_SEEK_SET)) != 0 ||
+		    (t_ret = __os_read(dbenv, dblp->lfhp, dblp->bufp,
 		    b_off, &nr)) != 0)
 			return (__db_panic(dbenv, t_ret));
 		if (nr != b_off) {
@@ -606,9 +679,36 @@ err:
 	return (ret);
 }
 
+/*
+ * __log_flush_pp --
+ *	DB_ENV->log_flush pre/post processing.
+ *
+ * PUBLIC: int __log_flush_pp __P((DB_ENV *, const DB_LSN *));
+ */
+int
+__log_flush_pp(dbenv, lsn)
+	DB_ENV *dbenv;
+	const DB_LSN *lsn;
+{
+	int rep_check, ret;
+
+	PANIC_CHECK(dbenv);
+	ENV_REQUIRES_CONFIG(dbenv,
+	    dbenv->lg_handle, "DB_ENV->log_flush", DB_INIT_LOG);
+
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __log_flush(dbenv, lsn);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+
+	return (ret);
+}
+
 /*
  * __log_flush --
- *	Write all records less than or equal to the specified LSN.
+ *	DB_ENV->log_flush
  *
  * PUBLIC: int __log_flush __P((DB_ENV *, const DB_LSN *));
  */
@@ -620,10 +720,6 @@ __log_flush(dbenv, lsn)
 	DB_LOG *dblp;
 	int ret;
 
-	PANIC_CHECK(dbenv);
-	ENV_REQUIRES_CONFIG(dbenv,
-	    dbenv->lg_handle, "DB_ENV->log_flush", DB_INIT_LOG);
-
 	dblp = dbenv->lg_handle;
 	R_LOCK(dbenv, &dblp->reginfo);
 	ret = __log_flush_int(dblp, lsn, 1);
@@ -635,27 +731,35 @@ __log_flush(dbenv, lsn)
  * __log_flush_int --
  *	Write all records less than or equal to the specified LSN; internal
  *	version.
+ *
+ * PUBLIC: int __log_flush_int __P((DB_LOG *, const DB_LSN *, int));
  */
-static int
+int
 __log_flush_int(dblp, lsnp, release)
 	DB_LOG *dblp;
 	const DB_LSN *lsnp;
 	int release;
 {
+	struct __db_commit *commit;
 	DB_ENV *dbenv;
 	DB_LSN flush_lsn, f_lsn;
 	DB_MUTEX *flush_mutexp;
 	LOG *lp;
-	int current, do_flush, first, ret;
 	size_t b_off;
-	struct __db_commit *commit;
 	u_int32_t ncommit, w_off;
+	int do_flush, first, ret;
 
-	ret = 0;
-	ncommit = 0;
 	dbenv = dblp->dbenv;
 	lp = dblp->reginfo.primary;
 	flush_mutexp = R_ADDR(&dblp->reginfo, lp->flush_mutex_off);
+	ncommit = 0;
+	ret = 0;
+
+	if (lp->db_log_inmemory) {
+		lp->s_lsn = lp->lsn;
+		++lp->stat.st_scount;
+		return (0);
+	}
 
 	/*
 	 * If no LSN specified, flush the entire log by setting the flush LSN
@@ -669,16 +773,21 @@ __log_flush_int(dblp, lsnp, release)
 	    (lsnp->file == lp->lsn.file &&
 	    lsnp->offset > lp->lsn.offset - lp->len)) {
 		__db_err(dbenv,
-		    "DB_ENV->log_flush: LSN past current end-of-log");
-		return (EINVAL);
+    "DB_ENV->log_flush: LSN of %lu/%lu past current end-of-log of %lu/%lu",
+		    (u_long)lsnp->file, (u_long)lsnp->offset,
+		    (u_long)lp->lsn.file, (u_long)lp->lsn.offset);
+		__db_err(dbenv, "%s %s %s",
+		    "Database environment corrupt; the wrong log files may",
+		    "have been removed or incompatible database files imported",
+		    "from another environment");
+		return (__db_panic(dbenv, DB_RUNRECOVERY));
 	} else {
 		/*
 		 * See if we need to wait.  s_lsn is not locked so some
 		 * care is needed.  The sync point can only move forward.
+		 * The lsnp->file cannot be greater than the s_lsn.file.
 		 * If the file we want is in the past we are done.
 		 * If the file numbers are the same check the offset.
-		 * If this fails check the file numbers again since the
-		 * offset might have changed while we were looking.
 		 * This all assumes we can read an integer in one
 		 * state or the other, not in transition.
 		 */
@@ -689,9 +798,6 @@ __log_flush_int(dblp, lsnp, release)
 		    lp->s_lsn.offset > lsnp->offset)
 			return (0);
 
-		if (lp->s_lsn.file > lsnp->file)
-			return (0);
-
 		flush_lsn = *lsnp;
 	}
 
@@ -702,8 +808,7 @@ __log_flush_int(dblp, lsnp, release)
 	if (release && lp->in_flush != 0) {
 		if ((commit = SH_TAILQ_FIRST(
 		    &lp->free_commits, __db_commit)) == NULL) {
-			if ((ret =
-			    __db_shalloc(dblp->reginfo.addr,
+			if ((ret = __db_shalloc(&dblp->reginfo,
 			    sizeof(struct __db_commit),
 			    MUTEX_ALIGN, &commit)) != 0)
 				goto flush;
@@ -711,7 +816,7 @@ __log_flush_int(dblp, lsnp, release)
 			if ((ret = __db_mutex_setup(dbenv, &dblp->reginfo,
 			    &commit->mutex, MUTEX_SELF_BLOCK |
 			    MUTEX_NO_RLOCK)) != 0) {
-				__db_shalloc_free(dblp->reginfo.addr, commit);
+				__db_shalloc_free(&dblp->reginfo, commit);
 				return (ret);
 			}
 			MUTEX_LOCK(dbenv, &commit->mutex);
@@ -776,8 +881,11 @@ flush:	MUTEX_LOCK(dbenv, flush_mutexp);
 	 * We may need to write the current buffer.  We have to write the
 	 * current buffer if the flush LSN is greater than or equal to the
 	 * buffer's starting LSN.
+	 *
+	 * Otherwise, it's still possible that this thread may never have
+	 * written to this log file.  Acquire a file descriptor if we don't
+	 * already have one.
 	 */
-	current = 0;
 	if (lp->b_off != 0 && log_compare(&flush_lsn, &lp->f_lsn) >= 0) {
 		if ((ret = __log_write(dblp,
 		    dblp->bufp, (u_int32_t)lp->b_off)) != 0) {
@@ -786,18 +894,8 @@ flush:	MUTEX_LOCK(dbenv, flush_mutexp);
 		}
 
 		lp->b_off = 0;
-		current = 1;
-	}
-
-	/*
-	 * It's possible that this thread may never have written to this log
-	 * file.  Acquire a file descriptor if we don't already have one.
-	 * One last check -- if we're not writing anything from the current
-	 * buffer, don't bother.  We have nothing to write and nothing to
-	 * sync.
-	 */
-	if (!F_ISSET(&dblp->lfh, DB_FH_VALID) || dblp->lfname != lp->lsn.file)
-		if (!current || (ret = __log_newfh(dblp)) != 0) {
+	} else if (dblp->lfhp == NULL || dblp->lfname != lp->lsn.file)
+		if ((ret = __log_newfh(dblp, 0)) != 0) {
 			MUTEX_UNLOCK(dbenv, flush_mutexp);
 			goto done;
 		}
@@ -815,7 +913,7 @@ flush:	MUTEX_LOCK(dbenv, flush_mutexp);
 		R_UNLOCK(dbenv, &dblp->reginfo);
 
 	/* Sync all writes to disk. */
-	if ((ret = __os_fsync(dbenv, &dblp->lfh)) != 0) {
+	if ((ret = __os_fsync(dbenv, dblp->lfhp)) != 0) {
 		MUTEX_UNLOCK(dbenv, flush_mutexp);
 		if (release)
 			R_LOCK(dbenv, &dblp->reginfo);
@@ -901,6 +999,12 @@ __log_fill(dblp, lsn, addr, len)
 	lp = dblp->reginfo.primary;
 	bsize = lp->buffer_size;
 
+	if (lp->db_log_inmemory) {
+		__log_inmem_copyin(dblp, lp->b_off, addr, len);
+		lp->b_off = (lp->b_off + len) % lp->buffer_size;
+		return (0);
+	}
+
 	while (len > 0) {			/* Copy out the data. */
 		/*
 		 * If we're beginning a new buffer, note the user LSN to which
@@ -962,22 +1066,38 @@ __log_write(dblp, addr, len)
 	dbenv = dblp->dbenv;
 	lp = dblp->reginfo.primary;
 
+	DB_ASSERT(!lp->db_log_inmemory);
+
 	/*
-	 * If we haven't opened the log file yet or the current one
-	 * has changed, acquire a new log file.
+	 * If we haven't opened the log file yet or the current one has
+	 * changed, acquire a new log file.  We are creating the file if we're
+	 * about to write to the start of it, in other words, if the write
+	 * offset is zero.
 	 */
-	if (!F_ISSET(&dblp->lfh, DB_FH_VALID) || dblp->lfname != lp->lsn.file)
-		if ((ret = __log_newfh(dblp)) != 0)
+	if (dblp->lfhp == NULL || dblp->lfname != lp->lsn.file)
+		if ((ret = __log_newfh(dblp, lp->w_off == 0)) != 0)
 			return (ret);
 
+	/*
+	 * If we're writing the first block in a log file on a filesystem that
+	 * guarantees unwritten blocks are zero-filled, we set the size of the
+	 * file in advance.  This increases sync performance on some systems,
+	 * because they don't need to update metadata on every sync.
+	 */
+#ifdef HAVE_FILESYSTEM_NOTZERO
+	if (lp->w_off == 0 && !__os_fs_notzero())
+#else
+	if (lp->w_off == 0)
+#endif
+		ret = __db_fileinit(dbenv, dblp->lfhp, lp->log_size, 0);
+
 	/*
 	 * Seek to the offset in the file (someone may have written it
 	 * since we last did).
 	 */
-	if ((ret =
-	    __os_seek(dbenv,
-	    &dblp->lfh, 0, 0, lp->w_off, 0, DB_OS_SEEK_SET)) != 0 ||
-	    (ret = __os_write(dbenv, &dblp->lfh, addr, len, &nw)) != 0)
+	if ((ret = __os_seek(dbenv,
+	    dblp->lfhp, 0, 0, lp->w_off, 0, DB_OS_SEEK_SET)) != 0 ||
+	    (ret = __os_write(dbenv, dblp->lfhp, addr, len, &nw)) != 0)
 		return (ret);
 
 	/* Reset the buffer offset and update the seek offset. */
@@ -998,26 +1118,54 @@ __log_write(dblp, addr, len)
 }
 
 /*
- * __log_file --
- *	Map a DB_LSN to a file name.
+ * __log_file_pp --
+ *	DB_ENV->log_file pre/post processing.
  *
- * PUBLIC: int __log_file __P((DB_ENV *, const DB_LSN *, char *, size_t));
+ * PUBLIC: int __log_file_pp __P((DB_ENV *, const DB_LSN *, char *, size_t));
  */
 int
-__log_file(dbenv, lsn, namep, len)
+__log_file_pp(dbenv, lsn, namep, len)
 	DB_ENV *dbenv;
 	const DB_LSN *lsn;
 	char *namep;
 	size_t len;
 {
-	DB_LOG *dblp;
-	int ret;
-	char *name;
+	int rep_check, ret;
 
 	PANIC_CHECK(dbenv);
 	ENV_REQUIRES_CONFIG(dbenv,
 	    dbenv->lg_handle, "DB_ENV->log_file", DB_INIT_LOG);
 
+	if (F_ISSET(dbenv, DB_ENV_LOG_INMEMORY)) {
+		__db_err(dbenv,
+		    "DB_ENV->log_file is illegal with in-memory logs.");
+		return (EINVAL);
+	}
+
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __log_file(dbenv, lsn, namep, len);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
+/*
+ * __log_file --
+ *	DB_ENV->log_file.
+ */
+static int
+__log_file(dbenv, lsn, namep, len)
+	DB_ENV *dbenv;
+	const DB_LSN *lsn;
+	char *namep;
+	size_t len;
+{
+	DB_LOG *dblp;
+	int ret;
+	char *name;
+
 	dblp = dbenv->lg_handle;
 	R_LOCK(dbenv, &dblp->reginfo);
 	ret = __log_name(dblp, lsn->file, &name, NULL, 0);
@@ -1042,45 +1190,39 @@ __log_file(dbenv, lsn, namep, len)
  *	Acquire a file handle for the current log file.
  */
 static int
-__log_newfh(dblp)
+__log_newfh(dblp, create)
 	DB_LOG *dblp;
+	int create;
 {
 	DB_ENV *dbenv;
 	LOG *lp;
+	u_int32_t flags;
 	int ret;
-	char *name;
+	logfile_validity status;
 
 	dbenv = dblp->dbenv;
 	lp = dblp->reginfo.primary;
 
 	/* Close any previous file descriptor. */
-	if (F_ISSET(&dblp->lfh, DB_FH_VALID))
-		(void)__os_closehandle(dbenv, &dblp->lfh);
+	if (dblp->lfhp != NULL) {
+		(void)__os_closehandle(dbenv, dblp->lfhp);
+		dblp->lfhp = NULL;
+	}
 
-	/*
-	 * Get the path of the new file and open it.
-	 *
-	 * Adding DB_OSO_LOG to the flags may add additional platform-specific
-	 * optimizations.  On WinNT, the logfile is preallocated, which may
-	 * have a time penalty at startup, but have better overall throughput.
-	 * We are not certain that this works reliably, so enable at your own
-	 * risk.
-	 *
-	 * XXX:
-	 * Initialize the log file size.  This is a hack to push the log's
-	 * maximum size down into the Windows __os_open routine, because it
-	 * wants to pre-allocate it.
-	 */
+	flags = DB_OSO_LOG | DB_OSO_SEQ |
+	    (create ? DB_OSO_CREATE : 0) |
+	    (F_ISSET(dbenv, DB_ENV_DIRECT_LOG) ? DB_OSO_DIRECT : 0) |
+	    (F_ISSET(dbenv, DB_ENV_DSYNC_LOG) ? DB_OSO_DSYNC : 0);
+
+	/* Get the path of the new file and open it. */
 	dblp->lfname = lp->lsn.file;
-	dblp->lfh.log_size = lp->log_size;
-	if ((ret = __log_name(dblp, dblp->lfname,
-	    &name, &dblp->lfh,
-	    DB_OSO_CREATE |/* DB_OSO_LOG |*/ DB_OSO_SEQ |
-	    (F_ISSET(dbenv, DB_ENV_DIRECT_LOG) ? DB_OSO_DIRECT : 0))) != 0)
+	if ((ret = __log_valid(dblp, dblp->lfname, 0, &dblp->lfhp,
+	    flags, &status)) != 0)
 		__db_err(dbenv,
-		    "DB_ENV->log_put: %s: %s", name, db_strerror(ret));
+		    "DB_ENV->log_put: %d: %s", lp->lsn.file, db_strerror(ret));
+	else if (status != DB_LV_NORMAL && status != DB_LV_INCOMPLETE)
+		ret = DB_NOTFOUND;
 
-	__os_free(dbenv, name);
 	return (ret);
 }
 
@@ -1089,14 +1231,14 @@ __log_newfh(dblp)
  *	Return the log name for a particular file, and optionally open it.
  *
  * PUBLIC: int __log_name __P((DB_LOG *,
- * PUBLIC:     u_int32_t, char **, DB_FH *, u_int32_t));
+ * PUBLIC:     u_int32_t, char **, DB_FH **, u_int32_t));
  */
 int
-__log_name(dblp, filenumber, namep, fhp, flags)
+__log_name(dblp, filenumber, namep, fhpp, flags)
 	DB_LOG *dblp;
 	u_int32_t filenumber, flags;
 	char **namep;
-	DB_FH *fhp;
+	DB_FH **fhpp;
 {
 	DB_ENV *dbenv;
 	LOG *lp;
@@ -1107,6 +1249,8 @@ __log_name(dblp, filenumber, namep, fhp, flags)
 	dbenv = dblp->dbenv;
 	lp = dblp->reginfo.primary;
 
+	DB_ASSERT(!lp->db_log_inmemory);
+
 	/*
 	 * !!!
 	 * The semantics of this routine are bizarre.
@@ -1127,11 +1271,12 @@ __log_name(dblp, filenumber, namep, fhp, flags)
 	 */
 	(void)snprintf(new, sizeof(new), LFNAME, filenumber);
 	if ((ret = __db_appname(dbenv,
-	    DB_APP_LOG, new, 0, NULL, namep)) != 0 || fhp == NULL)
+	    DB_APP_LOG, new, 0, NULL, namep)) != 0 || fhpp == NULL)
 		return (ret);
 
 	/* Open the new-style file -- if we succeed, we're done. */
-	if ((ret = __os_open(dbenv, *namep, flags, lp->persist.mode, fhp)) == 0)
+	if ((ret = __os_open_extend(dbenv, *namep, 0, flags,
+	    (int)lp->persist.mode, fhpp)) == 0)
 		return (0);
 
 	/*
@@ -1154,8 +1299,8 @@ __log_name(dblp, filenumber, namep, fhp, flags)
 	 * space allocated for the new-style name and return the old-style
 	 * name to the caller.
 	 */
-	if ((ret = __os_open(dbenv,
-	    oname, flags, lp->persist.mode, fhp)) == 0) {
+	if ((ret =
+	    __os_open(dbenv, oname, flags, (int)lp->persist.mode, fhpp)) == 0) {
 		__os_free(dbenv, *namep);
 		*namep = oname;
 		return (0);
@@ -1181,7 +1326,8 @@ err:	__os_free(dbenv, oname);
  * flushed, when log switches files, etc.  This is just a thin PUBLIC wrapper
  * for __log_putr with a slightly prettier interface.
  *
- * Note that the log region mutex should be held when this is called.
+ * Note that the db_rep->db_mutexp should be held when this is called.
+ * Note that we acquire the log region lock while holding db_mutexp.
  *
  * PUBLIC: int __log_rep_put __P((DB_ENV *, DB_LSN *, const DBT *));
  */
@@ -1201,6 +1347,7 @@ __log_rep_put(dbenv, lsnp, rec)
 	dblp = dbenv->lg_handle;
 	lp = dblp->reginfo.primary;
 
+	R_LOCK(dbenv, &dblp->reginfo);
 	memset(&hdr, 0, sizeof(HDR));
 	t = *rec;
 	dbt = &t;
@@ -1221,6 +1368,11 @@ __log_rep_put(dbenv, lsnp, rec)
 	DB_ASSERT(log_compare(lsnp, &lp->lsn) == 0);
 	ret = __log_putr(dblp, lsnp, dbt, lp->lsn.offset - lp->len, &hdr);
 err:
+	/*
+	 * !!! Assume caller holds db_rep->db_mutex to modify ready_lsn.
+	 */
+	lp->ready_lsn = lp->lsn;
+	R_UNLOCK(dbenv, &dblp->reginfo);
 	if (need_free)
 		__os_free(dbenv, t.data);
 	return (ret);
diff --git a/storage/bdb/log/log_stat.c b/storage/bdb/log/log_stat.c
new file mode 100644
index 0000000000000000000000000000000000000000..ce8c8af33c86dd55a0ba7eb83decc7c939038506
--- /dev/null
+++ b/storage/bdb/log/log_stat.c
@@ -0,0 +1,337 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: log_stat.c,v 11.149 2004/10/15 16:59:42 bostic Exp $
+ */
+
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
+#include "dbinc/log.h"
+
+#ifdef HAVE_STATISTICS
+static int __log_print_all __P((DB_ENV *, u_int32_t));
+static int __log_print_stats __P((DB_ENV *, u_int32_t));
+static int __log_stat __P((DB_ENV *, DB_LOG_STAT **, u_int32_t));
+
+/*
+ * __log_stat_pp --
+ *	DB_ENV->log_stat pre/post processing.
+ *
+ * PUBLIC: int __log_stat_pp __P((DB_ENV *, DB_LOG_STAT **, u_int32_t));
+ */
+int
+__log_stat_pp(dbenv, statp, flags)
+	DB_ENV *dbenv;
+	DB_LOG_STAT **statp;
+	u_int32_t flags;
+{
+	int rep_check, ret;
+
+	PANIC_CHECK(dbenv);
+	ENV_REQUIRES_CONFIG(dbenv,
+	    dbenv->lg_handle, "DB_ENV->log_stat", DB_INIT_LOG);
+
+	if ((ret = __db_fchk(dbenv,
+	    "DB_ENV->log_stat", flags, DB_STAT_CLEAR)) != 0)
+		return (ret);
+
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __log_stat(dbenv, statp, flags);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
+/*
+ * __log_stat --
+ *	DB_ENV->log_stat.
+ */
+static int
+__log_stat(dbenv, statp, flags)
+	DB_ENV *dbenv;
+	DB_LOG_STAT **statp;
+	u_int32_t flags;
+{
+	DB_LOG *dblp;
+	DB_LOG_STAT *stats;
+	LOG *lp;
+	int ret;
+
+	*statp = NULL;
+
+	dblp = dbenv->lg_handle;
+	lp = dblp->reginfo.primary;
+
+	if ((ret = __os_umalloc(dbenv, sizeof(DB_LOG_STAT), &stats)) != 0)
+		return (ret);
+
+	/* Copy out the global statistics. */
+	R_LOCK(dbenv, &dblp->reginfo);
+	*stats = lp->stat;
+	if (LF_ISSET(DB_STAT_CLEAR))
+		memset(&lp->stat, 0, sizeof(lp->stat));
+
+	stats->st_magic = lp->persist.magic;
+	stats->st_version = lp->persist.version;
+	stats->st_mode = (int)lp->persist.mode;
+	stats->st_lg_bsize = lp->buffer_size;
+	stats->st_lg_size = lp->log_nsize;
+
+	stats->st_region_wait = dblp->reginfo.rp->mutex.mutex_set_wait;
+	stats->st_region_nowait = dblp->reginfo.rp->mutex.mutex_set_nowait;
+	if (LF_ISSET(DB_STAT_CLEAR))
+		MUTEX_CLEAR(&dblp->reginfo.rp->mutex);
+	stats->st_regsize = dblp->reginfo.rp->size;
+
+	stats->st_cur_file = lp->lsn.file;
+	stats->st_cur_offset = lp->lsn.offset;
+	stats->st_disk_file = lp->s_lsn.file;
+	stats->st_disk_offset = lp->s_lsn.offset;
+
+	R_UNLOCK(dbenv, &dblp->reginfo);
+
+	*statp = stats;
+	return (0);
+}
+
+/*
+ * __log_stat_print_pp --
+ *	DB_ENV->log_stat_print pre/post processing.
+ *
+ * PUBLIC: int __log_stat_print_pp __P((DB_ENV *, u_int32_t));
+ */
+int
+__log_stat_print_pp(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	int rep_check, ret;
+
+	PANIC_CHECK(dbenv);
+	ENV_REQUIRES_CONFIG(dbenv,
+	    dbenv->lg_handle, "DB_ENV->log_stat_print", DB_INIT_LOG);
+
+	if ((ret = __db_fchk(dbenv, "DB_ENV->log_stat_print",
+	    flags, DB_STAT_ALL | DB_STAT_CLEAR)) != 0)
+		return (ret);
+
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __log_stat_print(dbenv, flags);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
+/*
+ * __log_stat_print --
+ *	DB_ENV->log_stat_print method.
+ *
+ * PUBLIC: int __log_stat_print __P((DB_ENV *, u_int32_t));
+ */
+int
+__log_stat_print(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	u_int32_t orig_flags;
+	int ret;
+
+	orig_flags = flags;
+	LF_CLR(DB_STAT_CLEAR);
+	if (flags == 0 || LF_ISSET(DB_STAT_ALL)) {
+		ret = __log_print_stats(dbenv, orig_flags);
+		if (flags == 0 || ret != 0)
+			return (ret);
+	}
+
+	if (LF_ISSET(DB_STAT_ALL) &&
+	    (ret = __log_print_all(dbenv, orig_flags)) != 0)
+		return (ret);
+
+	return (0);
+}
+
+/*
+ * __log_print_stats --
+ *	Display default log region statistics.
+ */
+static int
+__log_print_stats(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	DB_LOG_STAT *sp;
+	int ret;
+
+	if ((ret = __log_stat(dbenv, &sp, flags)) != 0)
+		return (ret);
+
+	if (LF_ISSET(DB_STAT_ALL))
+		__db_msg(dbenv, "Default logging region information:");
+	STAT_HEX("Log magic number", sp->st_magic);
+	STAT_ULONG("Log version number", sp->st_version);
+	__db_dlbytes(dbenv, "Log record cache size",
+	    (u_long)0, (u_long)0, (u_long)sp->st_lg_bsize);
+	__db_msg(dbenv, "%#o\tLog file mode", sp->st_mode);
+	if (sp->st_lg_size % MEGABYTE == 0)
+		__db_msg(dbenv, "%luMb\tCurrent log file size",
+		    (u_long)sp->st_lg_size / MEGABYTE);
+	else if (sp->st_lg_size % 1024 == 0)
+		__db_msg(dbenv, "%luKb\tCurrent log file size",
+		    (u_long)sp->st_lg_size / 1024);
+	else
+		__db_msg(dbenv, "%lu\tCurrent log file size",
+		    (u_long)sp->st_lg_size);
+	__db_dlbytes(dbenv, "Log bytes written",
+	    (u_long)0, (u_long)sp->st_w_mbytes, (u_long)sp->st_w_bytes);
+	__db_dlbytes(dbenv, "Log bytes written since last checkpoint",
+	    (u_long)0, (u_long)sp->st_wc_mbytes, (u_long)sp->st_wc_bytes);
+	__db_dl(dbenv, "Total log file writes", (u_long)sp->st_wcount);
+	__db_dl(dbenv, "Total log file write due to overflow",
+	    (u_long)sp->st_wcount_fill);
+	__db_dl(dbenv, "Total log file flushes", (u_long)sp->st_scount);
+	STAT_ULONG("Current log file number", sp->st_cur_file);
+	STAT_ULONG("Current log file offset", sp->st_cur_offset);
+	STAT_ULONG("On-disk log file number", sp->st_disk_file);
+	STAT_ULONG("On-disk log file offset", sp->st_disk_offset);
+
+	__db_dl(dbenv,
+	    "Maximum commits in a log flush", (u_long)sp->st_maxcommitperflush);
+	__db_dl(dbenv,
+	    "Minimum commits in a log flush", (u_long)sp->st_mincommitperflush);
+
+	__db_dlbytes(dbenv, "Log region size",
+	    (u_long)0, (u_long)0, (u_long)sp->st_regsize);
+	__db_dl_pct(dbenv,
+	    "The number of region locks that required waiting",
+	    (u_long)sp->st_region_wait, DB_PCT(sp->st_region_wait,
+	    sp->st_region_wait + sp->st_region_nowait), NULL);
+
+	__os_ufree(dbenv, sp);
+
+	return (0);
+}
+
+/*
+ * __log_print_all --
+ *	Display debugging log region statistics.
+ */
+static int
+__log_print_all(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	static const FN fn[] = {
+		{ DBLOG_RECOVER,	"DBLOG_RECOVER" },
+		{ DBLOG_FORCE_OPEN,	"DBLOG_FORCE_OPEN" },
+		{ 0,			NULL }
+	};
+	DB_LOG *dblp;
+	DB_MUTEX *flush_mutexp;
+	LOG *lp;
+
+	dblp = dbenv->lg_handle;
+	lp = (LOG *)dblp->reginfo.primary;
+
+	R_LOCK(dbenv, &dblp->reginfo);
+
+	__db_print_reginfo(dbenv, &dblp->reginfo, "Log");
+
+	__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+	__db_msg(dbenv, "DB_LOG handle information:");
+
+	__db_print_mutex(
+	    dbenv, NULL, dblp->mutexp, "DB_LOG handle mutex", flags);
+	STAT_ULONG("Log file name", dblp->lfname);
+	if (dblp->lfhp == NULL)
+		STAT_ISSET("Log file handle", dblp->lfhp);
+	else
+		__db_print_fh(dbenv, dblp->lfhp, flags);
+	__db_prflags(dbenv, NULL, dblp->flags, fn, NULL, "\tFlags");
+
+	__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+	__db_msg(dbenv, "LOG handle information:");
+
+	__db_print_mutex(
+	    dbenv, NULL, &lp->fq_mutex, "file name list mutex", flags);
+
+	STAT_HEX("persist.magic", lp->persist.magic);
+	STAT_ULONG("persist.version", lp->persist.version);
+	__db_dlbytes(dbenv,
+	    "persist.log_size", (u_long)0, (u_long)0, lp->persist.log_size);
+	STAT_FMT("persist.mode", "%#lo", u_long, lp->persist.mode);
+	STAT_LSN("current file offset LSN", &lp->lsn);
+	STAT_LSN("first buffer byte LSN", &lp->lsn);
+	STAT_ULONG("current buffer offset", lp->b_off);
+	STAT_ULONG("current file write offset", lp->w_off);
+	STAT_ULONG("length of last record", lp->len);
+	STAT_LONG("log flush in progress", lp->in_flush);
+
+	flush_mutexp = R_ADDR(&dblp->reginfo, lp->flush_mutex_off);
+	__db_print_mutex(dbenv, NULL, flush_mutexp, "Log flush mutex", flags);
+
+	STAT_LSN("last sync LSN", &lp->s_lsn);
+
+	/*
+	 * Don't display the replication fields here, they're displayed as part
+	 * of the replication statistics.
+	 */
+
+	STAT_LSN("cached checkpoint LSN", &lp->cached_ckp_lsn);
+
+	__db_dlbytes(dbenv,
+	    "log buffer size", (u_long)0, (u_long)0, lp->buffer_size);
+	__db_dlbytes(dbenv,
+	    "log file size", (u_long)0, (u_long)0, lp->log_size);
+	__db_dlbytes(dbenv,
+	    "next log file size", (u_long)0, (u_long)0, lp->log_nsize);
+
+	STAT_ULONG("transactions waiting to commit", lp->ncommit);
+	STAT_LSN("LSN of first commit", &lp->t_lsn);
+
+	__dbreg_print_dblist(dbenv, flags);
+	R_UNLOCK(dbenv, &dblp->reginfo);
+
+	return (0);
+}
+
+#else /* !HAVE_STATISTICS */
+
+int
+__log_stat_pp(dbenv, statp, flags)
+	DB_ENV *dbenv;
+	DB_LOG_STAT **statp;
+	u_int32_t flags;
+{
+	COMPQUIET(statp, NULL);
+	COMPQUIET(flags, 0);
+
+	return (__db_stat_not_built(dbenv));
+}
+
+int
+__log_stat_print_pp(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	COMPQUIET(flags, 0);
+
+	return (__db_stat_not_built(dbenv));
+}
+#endif
diff --git a/storage/bdb/mp/mp_alloc.c b/storage/bdb/mp/mp_alloc.c
index 96dd612d7ba063444730484637e554d4d5a182d0..79aa84f9929681250afa164744cc12aeca7b81f4 100644
--- a/storage/bdb/mp/mp_alloc.c
+++ b/storage/bdb/mp/mp_alloc.c
@@ -1,14 +1,13 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: mp_alloc.c,v 11.47 2004/10/15 16:59:42 bostic Exp $
  */
-#include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: mp_alloc.c,v 11.31 2002/08/14 17:21:37 ubell Exp $";
-#endif /* not lint */
+#include "db_config.h"
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
@@ -19,13 +18,7 @@ static const char revid[] = "$Id: mp_alloc.c,v 11.31 2002/08/14 17:21:37 ubell E
 #include "dbinc/db_shash.h"
 #include "dbinc/mp.h"
 
-typedef struct {
-	DB_MPOOL_HASH *bucket;
-	u_int32_t priority;
-} HS;
-
 static void __memp_bad_buffer __P((DB_MPOOL_HASH *));
-static void __memp_reset_lru __P((DB_ENV *, REGINFO *, MPOOL *));
 
 /*
  * __memp_alloc --
@@ -35,9 +28,9 @@ static void __memp_reset_lru __P((DB_ENV *, REGINFO *, MPOOL *));
  * PUBLIC:     REGINFO *, MPOOLFILE *, size_t, roff_t *, void *));
  */
 int
-__memp_alloc(dbmp, memreg, mfp, len, offsetp, retp)
+__memp_alloc(dbmp, infop, mfp, len, offsetp, retp)
 	DB_MPOOL *dbmp;
-	REGINFO *memreg;
+	REGINFO *infop;
 	MPOOLFILE *mfp;
 	size_t len;
 	roff_t *offsetp;
@@ -50,26 +43,22 @@ __memp_alloc(dbmp, memreg, mfp, len, offsetp, retp)
 	MPOOL *c_mp;
 	MPOOLFILE *bh_mfp;
 	size_t freed_space;
-	u_int32_t buckets, buffers, high_priority, max_na, priority;
-	int aggressive, ret;
+	u_int32_t buckets, buffers, high_priority, priority, put_counter;
+	u_int32_t total_buckets;
+	int aggressive, giveup, ret;
 	void *p;
 
 	dbenv = dbmp->dbenv;
-	c_mp = memreg->primary;
-	dbht = R_ADDR(memreg, c_mp->htab);
+	c_mp = infop->primary;
+	dbht = R_ADDR(infop, c_mp->htab);
 	hp_end = &dbht[c_mp->htab_buckets];
 
-	buckets = buffers = 0;
-	aggressive = 0;
+	buckets = buffers = put_counter = total_buckets = 0;
+	aggressive = giveup = 0;
+	hp_tmp = NULL;
 
 	c_mp->stat.st_alloc++;
 
-	/*
-	 * Get aggressive if we've tried to flush the number of pages as are
-	 * in the system without finding space.
-	 */
-	max_na = 5 * c_mp->htab_buckets;
-
 	/*
 	 * If we're allocating a buffer, and the one we're discarding is the
 	 * same size, we don't want to waste the time to re-integrate it into
@@ -80,20 +69,11 @@ __memp_alloc(dbmp, memreg, mfp, len, offsetp, retp)
 	if (mfp != NULL)
 		len = (sizeof(BH) - sizeof(u_int8_t)) + mfp->stat.st_pagesize;
 
-	R_LOCK(dbenv, memreg);
-
-	/*
-	 * On every buffer allocation we update the buffer generation number
-	 * and check for wraparound.
-	 */
-	if (++c_mp->lru_count == UINT32_T_MAX)
-		__memp_reset_lru(dbenv, memreg, c_mp);
-
+	R_LOCK(dbenv, infop);
 	/*
 	 * Anything newer than 1/10th of the buffer pool is ignored during
 	 * allocation (unless allocation starts failing).
 	 */
-	DB_ASSERT(c_mp->lru_count > c_mp->stat.st_pages / 10);
 	high_priority = c_mp->lru_count - c_mp->stat.st_pages / 10;
 
 	/*
@@ -105,13 +85,13 @@ __memp_alloc(dbmp, memreg, mfp, len, offsetp, retp)
 	 * we need in the hopes it will coalesce into a contiguous chunk of the
 	 * right size.  In the latter case we branch back here and try again.
 	 */
-alloc:	if ((ret = __db_shalloc(memreg->addr, len, MUTEX_ALIGN, &p)) == 0) {
+alloc:	if ((ret = __db_shalloc(infop, len, MUTEX_ALIGN, &p)) == 0) {
 		if (mfp != NULL)
 			c_mp->stat.st_pages++;
-		R_UNLOCK(dbenv, memreg);
+		R_UNLOCK(dbenv, infop);
 
 found:		if (offsetp != NULL)
-			*offsetp = R_OFFSET(memreg, p);
+			*offsetp = R_OFFSET(infop, p);
 		*(void **)retp = p;
 
 		/*
@@ -120,10 +100,11 @@ found:		if (offsetp != NULL)
 		 * We're not holding the region locked here, these statistics
 		 * can't be trusted.
 		 */
-		if (buckets != 0) {
-			if (buckets > c_mp->stat.st_alloc_max_buckets)
-				c_mp->stat.st_alloc_max_buckets = buckets;
-			c_mp->stat.st_alloc_buckets += buckets;
+		total_buckets += buckets;
+		if (total_buckets != 0) {
+			if (total_buckets > c_mp->stat.st_alloc_max_buckets)
+				c_mp->stat.st_alloc_max_buckets = total_buckets;
+			c_mp->stat.st_alloc_buckets += total_buckets;
 		}
 		if (buffers != 0) {
 			if (buffers > c_mp->stat.st_alloc_max_pages)
@@ -131,6 +112,12 @@ found:		if (offsetp != NULL)
 			c_mp->stat.st_alloc_pages += buffers;
 		}
 		return (0);
+	} else if (giveup || c_mp->stat.st_pages == 0) {
+		R_UNLOCK(dbenv, infop);
+
+		__db_err(dbenv,
+		    "unable to allocate space from the buffer cache");
+		return (ret);
 	}
 
 	/*
@@ -138,26 +125,24 @@ found:		if (offsetp != NULL)
 	 * we need.  Reset our free-space counter.
 	 */
 	freed_space = 0;
+	total_buckets += buckets;
+	buckets = 0;
 
 	/*
 	 * Walk the hash buckets and find the next two with potentially useful
 	 * buffers.  Free the buffer with the lowest priority from the buckets'
 	 * chains.
 	 */
-	for (hp_tmp = NULL;;) {
+	for (;;) {
+		/* All pages have been freed, make one last try */
+		if (c_mp->stat.st_pages == 0)
+			goto alloc;
+
 		/* Check for wrap around. */
 		hp = &dbht[c_mp->last_checked++];
 		if (hp >= hp_end) {
 			c_mp->last_checked = 0;
-
-			/*
-			 * If we've gone through all of the hash buckets, try
-			 * an allocation.  If the cache is small, the old page
-			 * size is small, and the new page size is large, we
-			 * might have freed enough memory (but not 3 times the
-			 * memory).
-			 */
-			goto alloc;
+			hp = &dbht[c_mp->last_checked++];
 		}
 
 		/*
@@ -172,41 +157,61 @@ found:		if (offsetp != NULL)
 		/*
 		 * The failure mode is when there are too many buffers we can't
 		 * write or there's not enough memory in the system.  We don't
-		 * have a metric for deciding if allocation has no possible way
-		 * to succeed, so we don't ever fail, we assume memory will be
-		 * available if we wait long enough.
+		 * have a way to know that allocation has no way to succeed.
+		 * We fail if there were no pages returned to the cache after
+		 * we've been trying for a relatively long time.
 		 *
-		 * Get aggressive if we've tried to flush 5 times the number of
-		 * hash buckets as are in the system -- it's possible we have
-		 * been repeatedly trying to flush the same buffers, although
-		 * it's unlikely.  Aggressive means:
+		 * Get aggressive if we've tried to flush the number of hash
+		 * buckets as are in the system and have not found any more
+		 * space.  Aggressive means:
 		 *
 		 * a: set a flag to attempt to flush high priority buffers as
 		 *    well as other buffers.
 		 * b: sync the mpool to force out queue extent pages.  While we
 		 *    might not have enough space for what we want and flushing
 		 *    is expensive, why not?
-		 * c: sleep for a second -- hopefully someone else will run and
-		 *    free up some memory.  Try to allocate memory too, in case
-		 *    the other thread returns its memory to the region.
-		 * d: look at a buffer in every hash bucket rather than choose
+		 * c: look at a buffer in every hash bucket rather than choose
 		 *    the more preferable of two.
+		 * d: start to think about giving up.
+		 *
+		 * If we get here twice, sleep for a second, hopefully someone
+		 * else will run and free up some memory.
+		 *
+		 * Always try to allocate memory too, in case some other thread
+		 * returns its memory to the region.
 		 *
 		 * !!!
 		 * This test ignores pathological cases like no buffers in the
 		 * system -- that shouldn't be possible.
 		 */
-		if ((++buckets % max_na) == 0) {
-			aggressive = 1;
-
-			R_UNLOCK(dbenv, memreg);
-
-			(void)__memp_sync_int(
-			    dbenv, NULL, 0, DB_SYNC_ALLOC, NULL);
-
-			(void)__os_sleep(dbenv, 1, 0);
+		if ((++buckets % c_mp->htab_buckets) == 0) {
+			if (freed_space > 0)
+				goto alloc;
+			R_UNLOCK(dbenv, infop);
+
+			switch (++aggressive) {
+			case 1:
+				break;
+			case 2:
+				put_counter = c_mp->put_counter;
+				/* FALLTHROUGH */
+			case 3:
+			case 4:
+			case 5:
+			case 6:
+				(void)__memp_sync_int(
+				    dbenv, NULL, 0, DB_SYNC_ALLOC, NULL);
+
+				__os_sleep(dbenv, 1, 0);
+				break;
+			default:
+				aggressive = 1;
+				if (put_counter == c_mp->put_counter)
+					giveup = 1;
+				break;
+			}
 
-			R_LOCK(dbenv, memreg);
+			R_LOCK(dbenv, infop);
 			goto alloc;
 		}
 
@@ -234,7 +239,7 @@ found:		if (offsetp != NULL)
 		priority = hp->hash_priority;
 
 		/* Unlock the region and lock the hash bucket. */
-		R_UNLOCK(dbenv, memreg);
+		R_UNLOCK(dbenv, infop);
 		mutexp = &hp->hash_mutex;
 		MUTEX_LOCK(dbenv, mutexp);
 
@@ -277,7 +282,8 @@ found:		if (offsetp != NULL)
 		 * thread may have acquired this buffer and incremented the ref
 		 * count after we wrote it, in which case we can't have it.
 		 *
-		 * If there's a write error, avoid selecting this buffer again
+		 * If there's a write error and we're having problems finding
+		 * something to allocate, avoid selecting this buffer again
 		 * by making it the bucket's least-desirable buffer.
 		 */
 		if (ret != 0 || bhp->ref != 0) {
@@ -299,8 +305,10 @@ found:		if (offsetp != NULL)
 			goto found;
 		}
 
-		freed_space += __db_shsizeof(bhp);
-		__memp_bhfree(dbmp, hp, bhp, 1);
+		freed_space += __db_shalloc_sizeof(bhp);
+		__memp_bhfree(dbmp, hp, bhp, BH_FREE_FREEMEM);
+		if (aggressive > 1)
+			aggressive = 1;
 
 		/*
 		 * Unlock this hash bucket and re-acquire the region lock. If
@@ -310,7 +318,7 @@ found:		if (offsetp != NULL)
 		if (0) {
 next_hb:		MUTEX_UNLOCK(dbenv, mutexp);
 		}
-		R_LOCK(dbenv, memreg);
+		R_LOCK(dbenv, infop);
 
 		/*
 		 * Retry the allocation as soon as we've freed up sufficient
@@ -332,7 +340,7 @@ static void
 __memp_bad_buffer(hp)
 	DB_MPOOL_HASH *hp;
 {
-	BH *bhp, *t_bhp;
+	BH *bhp;
 	u_int32_t priority;
 
 	/* Remove the first buffer from the bucket. */
@@ -342,14 +350,10 @@ __memp_bad_buffer(hp)
 	/*
 	 * Find the highest priority buffer in the bucket.  Buffers are
 	 * sorted by priority, so it's the last one in the bucket.
-	 *
-	 * XXX
-	 * Should use SH_TAILQ_LAST, but I think that macro is broken.
 	 */
 	priority = bhp->priority;
-	for (t_bhp = SH_TAILQ_FIRST(&hp->hash_bucket, __bh);
-	    t_bhp != NULL; t_bhp = SH_TAILQ_NEXT(t_bhp, hq, __bh))
-		priority = t_bhp->priority;
+	if (!SH_TAILQ_EMPTY(&hp->hash_bucket))
+	  priority = SH_TAILQ_LAST(&hp->hash_bucket, hq, __bh)->priority;
 
 	/*
 	 * Set our buffer's priority to be just as bad, and append it to
@@ -362,54 +366,6 @@ __memp_bad_buffer(hp)
 	hp->hash_priority = SH_TAILQ_FIRST(&hp->hash_bucket, __bh)->priority;
 }
 
-/*
- * __memp_reset_lru --
- *	Reset the cache LRU counter.
- */
-static void
-__memp_reset_lru(dbenv, memreg, c_mp)
-	DB_ENV *dbenv;
-	REGINFO *memreg;
-	MPOOL *c_mp;
-{
-	BH *bhp;
-	DB_MPOOL_HASH *hp;
-	int bucket;
-
-	/*
-	 * Update the counter so all future allocations will start at the
-	 * bottom.
-	 */
-	c_mp->lru_count -= MPOOL_BASE_DECREMENT;
-
-	/* Release the region lock. */
-	R_UNLOCK(dbenv, memreg);
-
-	/* Adjust the priority of every buffer in the system. */
-	for (hp = R_ADDR(memreg, c_mp->htab),
-	    bucket = 0; bucket < c_mp->htab_buckets; ++hp, ++bucket) {
-		/*
-		 * Skip empty buckets.
-		 *
-		 * We can check for empty buckets before locking as we
-		 * only care if the pointer is zero or non-zero.
-		 */
-		if (SH_TAILQ_FIRST(&hp->hash_bucket, __bh) == NULL)
-			continue;
-
-		MUTEX_LOCK(dbenv, &hp->hash_mutex);
-		for (bhp = SH_TAILQ_FIRST(&hp->hash_bucket, __bh);
-		    bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, hq, __bh))
-			if (bhp->priority != UINT32_T_MAX &&
-			    bhp->priority > MPOOL_BASE_DECREMENT)
-				bhp->priority -= MPOOL_BASE_DECREMENT;
-		MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
-	}
-
-	/* Reacquire the region lock. */
-	R_LOCK(dbenv, memreg);
-}
-
 #ifdef DIAGNOSTIC
 /*
  * __memp_check_order --
diff --git a/storage/bdb/mp/mp_bh.c b/storage/bdb/mp/mp_bh.c
index 85d15218abf86b707db57677790661b00fc43c73..b28698146624de22d21158b62eefe55da976cf69 100644
--- a/storage/bdb/mp/mp_bh.c
+++ b/storage/bdb/mp/mp_bh.c
@@ -1,20 +1,18 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: mp_bh.c,v 11.99 2004/10/15 16:59:42 bostic Exp $
  */
-#include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: mp_bh.c,v 11.71 2002/09/04 19:06:45 margo Exp $";
-#endif /* not lint */
+#include "db_config.h"
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <string.h>
-#include <unistd.h>
 #endif
 
 #include "db_int.h"
@@ -24,8 +22,7 @@ static const char revid[] = "$Id: mp_bh.c,v 11.71 2002/09/04 19:06:45 margo Exp
 #include "dbinc/db_page.h"
 
 static int __memp_pgwrite
-	   __P((DB_MPOOL *, DB_MPOOLFILE *, DB_MPOOL_HASH *, BH *));
-static int __memp_upgrade __P((DB_MPOOL *, DB_MPOOLFILE *, MPOOLFILE *));
+	       __P((DB_ENV *, DB_MPOOLFILE *, DB_MPOOL_HASH *, BH *));
 
 /*
  * __memp_bhwrite --
@@ -45,54 +42,63 @@ __memp_bhwrite(dbmp, hp, mfp, bhp, open_extents)
 	DB_ENV *dbenv;
 	DB_MPOOLFILE *dbmfp;
 	DB_MPREG *mpreg;
-	int local_open, incremented, ret;
+	int ret;
 
 	dbenv = dbmp->dbenv;
-	local_open = incremented = 0;
 
 	/*
-	 * If the file has been removed or is a closed temporary file, jump
-	 * right ahead and pretend that we've found the file we want -- the
-	 * page-write function knows how to handle the fact that we don't have
-	 * (or need!) any real file descriptor information.
+	 * If the file has been removed or is a closed temporary file, we're
+	 * done -- the page-write function knows how to handle the fact that
+	 * we don't have (or need!) any real file descriptor information.
 	 */
-	if (F_ISSET(mfp, MP_DEADFILE)) {
-		dbmfp = NULL;
-		goto found;
-	}
+	if (mfp->deadfile)
+		return (__memp_pgwrite(dbenv, NULL, hp, bhp));
 
 	/*
 	 * Walk the process' DB_MPOOLFILE list and find a file descriptor for
 	 * the file.  We also check that the descriptor is open for writing.
-	 * If we find a descriptor on the file that's not open for writing, we
-	 * try and upgrade it to make it writeable.  If that fails, we're done.
 	 */
 	MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);
 	for (dbmfp = TAILQ_FIRST(&dbmp->dbmfq);
 	    dbmfp != NULL; dbmfp = TAILQ_NEXT(dbmfp, q))
-		if (dbmfp->mfp == mfp) {
-			if (F_ISSET(dbmfp, MP_READONLY) &&
-			    !F_ISSET(dbmfp, MP_UPGRADE) &&
-			    (F_ISSET(dbmfp, MP_UPGRADE_FAIL) ||
-			    __memp_upgrade(dbmp, dbmfp, mfp))) {
-				MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
-				return (EPERM);
-			}
-
-			/*
-			 * Increment the reference count -- see the comment in
-			 * __memp_fclose_int().
-			 */
+		if (dbmfp->mfp == mfp && !F_ISSET(dbmfp, MP_READONLY)) {
 			++dbmfp->ref;
-			incremented = 1;
 			break;
 		}
 	MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
 
-	if (dbmfp != NULL)
-		goto found;
+	if (dbmfp != NULL) {
+		/*
+		 * Temporary files may not have been created.  We only handle
+		 * temporary files in this path, because only the process that
+		 * created a temporary file will ever flush buffers to it.
+		 */
+		if (dbmfp->fhp == NULL) {
+			/* We may not be allowed to create backing files. */
+			if (mfp->no_backing_file)
+				return (EPERM);
+
+			MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);
+			if (dbmfp->fhp == NULL)
+				ret = __db_appname(dbenv, DB_APP_TMP, NULL,
+				    F_ISSET(dbenv, DB_ENV_DIRECT_DB) ?
+				    DB_OSO_DIRECT : 0, &dbmfp->fhp, NULL);
+			else
+				ret = 0;
+			MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
+			if (ret != 0) {
+				__db_err(dbenv,
+				    "unable to create temporary backing file");
+				return (ret);
+			}
+		}
+
+		goto pgwrite;
+	}
 
 	/*
+	 * There's no file handle for this file in our process.
+	 *
 	 * !!!
 	 * It's the caller's choice if we're going to open extent files.
 	 */
@@ -117,7 +123,7 @@ __memp_bhwrite(dbmp, hp, mfp, bhp, open_extents)
 	 *
 	 * Note we should never get here when the temporary file in question
 	 * has already been closed in another process, in which case it should
-	 * be marked MP_DEADFILE.
+	 * be marked dead.
 	 */
 	if (F_ISSET(mfp, MP_TEMP))
 		return (EPERM);
@@ -140,30 +146,42 @@ __memp_bhwrite(dbmp, hp, mfp, bhp, open_extents)
 	}
 
 	/*
-	 * Try and open the file, attaching to the underlying shared area.
-	 * Ignore any error, assume it's a permissions problem.
+	 * Try and open the file, specifying the known underlying shared area.
 	 *
-	 * XXX
+	 * !!!
 	 * There's no negative cache, so we may repeatedly try and open files
 	 * that we have previously tried (and failed) to open.
 	 */
-	if ((ret = dbenv->memp_fcreate(dbenv, &dbmfp, 0)) != 0)
-		return (ret);
-	if ((ret = __memp_fopen_int(dbmfp, mfp,
-	    R_ADDR(dbmp->reginfo, mfp->path_off),
-	    0, 0, mfp->stat.st_pagesize)) != 0) {
-		(void)dbmfp->close(dbmfp, 0);
+	if ((ret = __memp_fcreate(dbenv, &dbmfp)) != 0)
 		return (ret);
+	if ((ret = __memp_fopen(dbmfp,
+	    mfp, NULL, DB_DURABLE_UNKNOWN, 0, mfp->stat.st_pagesize)) != 0) {
+		(void)__memp_fclose(dbmfp, 0);
+
+		/*
+		 * Ignore any error if the file is marked dead, assume the file
+		 * was removed from under us.
+		 */
+		if (!mfp->deadfile)
+			return (ret);
+
+		dbmfp = NULL;
 	}
-	local_open = 1;
 
-found:	ret = __memp_pgwrite(dbmp, dbmfp, hp, bhp);
+pgwrite:
+	ret = __memp_pgwrite(dbenv, dbmfp, hp, bhp);
+	if (dbmfp == NULL)
+		return (ret);
 
+	/*
+	 * Discard our reference, and, if we're the last reference, make sure
+	 * the file eventually gets closed.
+	 */
 	MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);
-	if (incremented)
-		--dbmfp->ref;
-	else if (local_open)
+	if (dbmfp->ref == 1)
 		F_SET(dbmfp, MP_FLUSH);
+	else
+		--dbmfp->ref;
 	MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
 
 	return (ret);
@@ -182,15 +200,13 @@ __memp_pgread(dbmfp, mutexp, bhp, can_create)
 	BH *bhp;
 	int can_create;
 {
-	DB_IO db_io;
 	DB_ENV *dbenv;
-	DB_MPOOL *dbmp;
 	MPOOLFILE *mfp;
-	size_t len, nr, pagesize;
+	size_t len, nr;
+	u_int32_t pagesize;
 	int ret;
 
-	dbmp = dbmfp->dbmp;
-	dbenv = dbmp->dbenv;
+	dbenv = dbmfp->dbenv;
 	mfp = dbmfp->mfp;
 	pagesize = mfp->stat.st_pagesize;
 
@@ -207,22 +223,16 @@ __memp_pgread(dbmfp, mutexp, bhp, can_create)
 	 * them now, we create them when the pages have to be flushed.
 	 */
 	nr = 0;
-	if (F_ISSET(dbmfp->fhp, DB_FH_VALID)) {
-		db_io.fhp = dbmfp->fhp;
-		db_io.mutexp = dbmfp->mutexp;
-		db_io.pagesize = db_io.bytes = pagesize;
-		db_io.pgno = bhp->pgno;
-		db_io.buf = bhp->buf;
-
-		/*
-		 * The page may not exist; if it doesn't, nr may well be 0,
-		 * but we expect the underlying OS calls not to return an
-		 * error code in this case.
-		 */
-		if ((ret = __os_io(dbenv, &db_io, DB_IO_READ, &nr)) != 0)
+	if (dbmfp->fhp != NULL)
+		if ((ret = __os_io(dbenv, DB_IO_READ,
+		    dbmfp->fhp, bhp->pgno, pagesize, bhp->buf, &nr)) != 0)
 			goto err;
-	}
 
+	/*
+	 * The page may not exist; if it doesn't, nr may well be 0, but we
+	 * expect the underlying OS calls not to return an error code in
+	 * this case.
+	 */
 	if (nr < pagesize) {
 		/*
 		 * Don't output error messages for short reads.  In particular,
@@ -275,20 +285,17 @@ err:	MUTEX_UNLOCK(dbenv, &bhp->mutex);
  *	Write a page to a file.
  */
 static int
-__memp_pgwrite(dbmp, dbmfp, hp, bhp)
-	DB_MPOOL *dbmp;
+__memp_pgwrite(dbenv, dbmfp, hp, bhp)
+	DB_ENV *dbenv;
 	DB_MPOOLFILE *dbmfp;
 	DB_MPOOL_HASH *hp;
 	BH *bhp;
 {
-	DB_ENV *dbenv;
-	DB_IO db_io;
 	DB_LSN lsn;
 	MPOOLFILE *mfp;
 	size_t nw;
 	int callpgin, ret;
 
-	dbenv = dbmp->dbenv;
 	mfp = dbmfp == NULL ? NULL : dbmfp->mfp;
 	callpgin = ret = 0;
 
@@ -318,16 +325,17 @@ __memp_pgwrite(dbmp, dbmfp, hp, bhp)
 	 * Once we pass this point, we know that dbmfp and mfp aren't NULL,
 	 * and that we have a valid file reference.
 	 */
-	if (mfp == NULL || F_ISSET(mfp, MP_DEADFILE))
+	if (mfp == NULL || mfp->deadfile)
 		goto file_dead;
 
 	/*
 	 * If the page is in a file for which we have LSN information, we have
 	 * to ensure the appropriate log records are on disk.
 	 */
-	if (LOGGING_ON(dbenv) && mfp->lsn_off != -1) {
+	if (LOGGING_ON(dbenv) && mfp->lsn_off != -1 &&
+	    !IS_CLIENT_PGRECOVER(dbenv)) {
 		memcpy(&lsn, bhp->buf + mfp->lsn_off, sizeof(DB_LSN));
-		if ((ret = dbenv->log_flush(dbenv, &lsn)) != 0)
+		if ((ret = __log_flush(dbenv, &lsn)) != 0)
 			goto err;
 	}
 
@@ -336,7 +344,7 @@ __memp_pgwrite(dbmp, dbmfp, hp, bhp)
 	 * Verify write-ahead logging semantics.
 	 *
 	 * !!!
-	 * One special case.  There is a single field on the meta-data page,
+	 * Two special cases.  There is a single field on the meta-data page,
 	 * the last-page-number-in-the-file field, for which we do not log
 	 * changes.  If the page was originally created in a database that
 	 * didn't have logging turned on, we can see a page marked dirty but
@@ -345,8 +353,13 @@ __memp_pgwrite(dbmp, dbmfp, hp, bhp)
 	 * previous log record and valid LSN is when the page was created
 	 * without logging turned on, and so we check for that special-case
 	 * LSN value.
+	 *
+	 * Second, when a client is reading database pages from a master
+	 * during an internal backup, we may get pages modified after
+	 * the current end-of-log.
 	 */
-	if (LOGGING_ON(dbenv) && !IS_NOT_LOGGED_LSN(LSN(bhp->buf))) {
+	if (LOGGING_ON(dbenv) && !IS_NOT_LOGGED_LSN(LSN(bhp->buf)) &&
+	    !IS_CLIENT_PGRECOVER(dbenv)) {
 		/*
 		 * There is a potential race here.  If we are in the midst of
 		 * switching log files, it's possible we could test against the
@@ -354,15 +367,17 @@ __memp_pgwrite(dbmp, dbmfp, hp, bhp)
 		 * fail the first test, acquire the log mutex and check again.
 		 */
 		DB_LOG *dblp;
+		DB_MUTEX *mtx;
 		LOG *lp;
 
 		dblp = dbenv->lg_handle;
 		lp = dblp->reginfo.primary;
-		if (!IS_NOT_LOGGED_LSN(LSN(bhp->buf)) &&
+		if (!lp->db_log_inmemory &&
 		    log_compare(&lp->s_lsn, &LSN(bhp->buf)) <= 0) {
-			R_LOCK(dbenv, &dblp->reginfo);
+			mtx = R_ADDR(&dblp->reginfo, lp->flush_mutex_off);
+			MUTEX_LOCK(dbenv, mtx);
 			DB_ASSERT(log_compare(&lp->s_lsn, &LSN(bhp->buf)) > 0);
-			R_UNLOCK(dbenv, &dblp->reginfo);
+			MUTEX_UNLOCK(dbenv, mtx);
 		}
 	}
 #endif
@@ -372,34 +387,15 @@ __memp_pgwrite(dbmp, dbmfp, hp, bhp)
 	 * that the contents of the buffer will need to be passed through pgin
 	 * before they are reused.
 	 */
-	if (mfp->ftype != 0) {
+	if (mfp->ftype != 0 && !F_ISSET(bhp, BH_CALLPGIN)) {
 		callpgin = 1;
 		if ((ret = __memp_pg(dbmfp, bhp, 0)) != 0)
 			goto err;
 	}
 
-	/* Temporary files may not yet have been created. */
-	if (!F_ISSET(dbmfp->fhp, DB_FH_VALID)) {
-		MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);
-		ret = F_ISSET(dbmfp->fhp, DB_FH_VALID) ? 0 :
-		    __db_appname(dbenv, DB_APP_TMP, NULL,
-		    F_ISSET(dbenv, DB_ENV_DIRECT_DB) ? DB_OSO_DIRECT : 0,
-		    dbmfp->fhp, NULL);
-		MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
-		if (ret != 0) {
-			__db_err(dbenv,
-			    "unable to create temporary backing file");
-			goto err;
-		}
-	}
-
 	/* Write the page. */
-	db_io.fhp = dbmfp->fhp;
-	db_io.mutexp = dbmfp->mutexp;
-	db_io.pagesize = db_io.bytes = mfp->stat.st_pagesize;
-	db_io.pgno = bhp->pgno;
-	db_io.buf = bhp->buf;
-	if ((ret = __os_io(dbenv, &db_io, DB_IO_WRITE, &nw)) != 0) {
+	if ((ret = __os_io(dbenv, DB_IO_WRITE, dbmfp->fhp,
+	    bhp->pgno, mfp->stat.st_pagesize, bhp->buf, &nw)) != 0) {
 		__db_err(dbenv, "%s: write failed for page %lu",
 		    __memp_fn(dbmfp), (u_long)bhp->pgno);
 		goto err;
@@ -462,8 +458,8 @@ __memp_pg(dbmfp, bhp, is_pgin)
 	MPOOLFILE *mfp;
 	int ftype, ret;
 
-	dbmp = dbmfp->dbmp;
-	dbenv = dbmp->dbenv;
+	dbenv = dbmfp->dbenv;
+	dbmp = dbenv->mp_handle;
 	mfp = dbmfp->mfp;
 
 	MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);
@@ -476,7 +472,7 @@ __memp_pg(dbmfp, bhp, is_pgin)
 		if (mfp->pgcookie_len == 0)
 			dbtp = NULL;
 		else {
-			dbt.size = mfp->pgcookie_len;
+			dbt.size = (u_int32_t)mfp->pgcookie_len;
 			dbt.data = R_ADDR(dbmp->reginfo, mfp->pgcookie_off);
 			dbtp = &dbt;
 		}
@@ -510,14 +506,15 @@ err:	MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
  * __memp_bhfree --
  *	Free a bucket header and its referenced data.
  *
- * PUBLIC: void __memp_bhfree __P((DB_MPOOL *, DB_MPOOL_HASH *, BH *, int));
+ * PUBLIC: void __memp_bhfree
+ * PUBLIC:     __P((DB_MPOOL *, DB_MPOOL_HASH *, BH *, u_int32_t));
  */
 void
-__memp_bhfree(dbmp, hp, bhp, free_mem)
+__memp_bhfree(dbmp, hp, bhp, flags)
 	DB_MPOOL *dbmp;
 	DB_MPOOL_HASH *hp;
 	BH *bhp;
-	int free_mem;
+	u_int32_t flags;
 {
 	DB_ENV *dbenv;
 	MPOOL *c_mp, *mp;
@@ -545,7 +542,8 @@ __memp_bhfree(dbmp, hp, bhp, free_mem)
 	 * Discard the hash bucket's mutex, it's no longer needed, and
 	 * we don't want to be holding it when acquiring other locks.
 	 */
-	MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
+	if (!LF_ISSET(BH_FREE_UNLOCKED))
+		MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
 
 	/*
 	 * Find the underlying MPOOLFILE and decrement its reference count.
@@ -554,7 +552,7 @@ __memp_bhfree(dbmp, hp, bhp, free_mem)
 	mfp = R_ADDR(dbmp->reginfo, bhp->mf_offset);
 	MUTEX_LOCK(dbenv, &mfp->mutex);
 	if (--mfp->block_cnt == 0 && mfp->mpf_cnt == 0)
-		__memp_mf_discard(dbmp, mfp);
+		(void)__memp_mf_discard(dbmp, mfp);
 	else
 		MUTEX_UNLOCK(dbenv, &mfp->mutex);
 
@@ -565,82 +563,16 @@ __memp_bhfree(dbmp, hp, bhp, free_mem)
 	 * be held.
 	 */
 	__db_shlocks_clear(&bhp->mutex, &dbmp->reginfo[n_cache],
-	    (REGMAINT *)R_ADDR(&dbmp->reginfo[n_cache], mp->maint_off));
+	    R_ADDR(&dbmp->reginfo[n_cache], mp->maint_off));
 
 	/*
 	 * If we're not reusing the buffer immediately, free the buffer header
 	 * and data for real.
 	 */
-	if (free_mem) {
-		__db_shalloc_free(dbmp->reginfo[n_cache].addr, bhp);
+	if (LF_ISSET(BH_FREE_FREEMEM)) {
+		__db_shalloc_free(&dbmp->reginfo[n_cache], bhp);
 		c_mp = dbmp->reginfo[n_cache].primary;
 		c_mp->stat.st_pages--;
 	}
 	R_UNLOCK(dbenv, &dbmp->reginfo[n_cache]);
 }
-
-/*
- * __memp_upgrade --
- *	Upgrade a file descriptor from read-only to read-write.
- */
-static int
-__memp_upgrade(dbmp, dbmfp, mfp)
-	DB_MPOOL *dbmp;
-	DB_MPOOLFILE *dbmfp;
-	MPOOLFILE *mfp;
-{
-	DB_ENV *dbenv;
-	DB_FH *fhp, *tfhp;
-	int ret;
-	char *rpath;
-
-	dbenv = dbmp->dbenv;
-	fhp = NULL;
-	rpath = NULL;
-
-	/*
-	 * Calculate the real name for this file and try to open it read/write.
-	 * We know we have a valid pathname for the file because it's the only
-	 * way we could have gotten a file descriptor of any kind.
-	 */
-	if ((ret = __os_calloc(dbenv, 1, sizeof(DB_FH), &fhp)) != 0)
-		goto err;
-
-	if ((ret = __db_appname(dbenv, DB_APP_DATA,
-	    R_ADDR(dbmp->reginfo, mfp->path_off), 0, NULL, &rpath)) != 0)
-		goto err;
-
-	if (__os_open(dbenv, rpath,
-	    F_ISSET(mfp, MP_DIRECT) ? DB_OSO_DIRECT : 0, 0, fhp) != 0) {
-		F_SET(dbmfp, MP_UPGRADE_FAIL);
-		goto err;
-	}
-
-	/*
-	 * Swap the descriptors and set the upgrade flag.
-	 *
-	 * XXX
-	 * There is a race here.  If another process schedules a read using the
-	 * existing file descriptor and is swapped out before making the system
-	 * call, this code could theoretically close the file descriptor out
-	 * from under it.  While it's very unlikely, this code should still be
-	 * rewritten.
-	 */
-	tfhp = dbmfp->fhp;
-	dbmfp->fhp = fhp;
-	fhp = tfhp;
-
-	(void)__os_closehandle(dbenv, fhp);
-	F_SET(dbmfp, MP_UPGRADE);
-
-	ret = 0;
-	if (0) {
-err:		ret = 1;
-	}
-	if (fhp != NULL)
-		__os_free(dbenv, fhp);
-	if (rpath != NULL)
-		__os_free(dbenv, rpath);
-
-	return (ret);
-}
diff --git a/storage/bdb/mp/mp_fget.c b/storage/bdb/mp/mp_fget.c
index be0785a2184afec0476ab66940a6c418df38e629..a955fc1e63807951c1e69272c19f4907bb180557 100644
--- a/storage/bdb/mp/mp_fget.c
+++ b/storage/bdb/mp/mp_fget.c
@@ -1,14 +1,13 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: mp_fget.c,v 11.96 2004/10/15 16:59:42 bostic Exp $
  */
-#include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: mp_fget.c,v 11.68 2002/08/06 04:58:09 bostic Exp $";
-#endif /* not lint */
+#include "db_config.h"
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
@@ -18,51 +17,30 @@ static const char revid[] = "$Id: mp_fget.c,v 11.68 2002/08/06 04:58:09 bostic E
 
 #include "db_int.h"
 #include "dbinc/db_shash.h"
+#include "dbinc/log.h"
 #include "dbinc/mp.h"
 
-#ifdef HAVE_FILESYSTEM_NOTZERO
-static int __memp_fs_notzero
-    __P((DB_ENV *, DB_MPOOLFILE *, MPOOLFILE *, db_pgno_t *));
-#endif
-
 /*
- * __memp_fget --
- *	Get a page from the file.
+ * __memp_fget_pp --
+ *	DB_MPOOLFILE->get pre/post processing.
  *
- * PUBLIC: int __memp_fget
+ * PUBLIC: int __memp_fget_pp
  * PUBLIC:     __P((DB_MPOOLFILE *, db_pgno_t *, u_int32_t, void *));
  */
 int
-__memp_fget(dbmfp, pgnoaddr, flags, addrp)
+__memp_fget_pp(dbmfp, pgnoaddr, flags, addrp)
 	DB_MPOOLFILE *dbmfp;
 	db_pgno_t *pgnoaddr;
 	u_int32_t flags;
 	void *addrp;
 {
-	enum { FIRST_FOUND, FIRST_MISS, SECOND_FOUND, SECOND_MISS } state;
-	BH *alloc_bhp, *bhp;
 	DB_ENV *dbenv;
-	DB_MPOOL *dbmp;
-	DB_MPOOL_HASH *hp;
-	MPOOL *c_mp, *mp;
-	MPOOLFILE *mfp;
-	roff_t mf_offset;
-	u_int32_t n_cache, st_hsearch;
-	int b_incr, extending, first, ret;
-
-	*(void **)addrp = NULL;
+	int rep_check, ret;
 
-	dbmp = dbmfp->dbmp;
-	dbenv = dbmp->dbenv;
+	dbenv = dbmfp->dbenv;
 
 	PANIC_CHECK(dbenv);
-
-	mp = dbmp->reginfo[0].primary;
-	mfp = dbmfp->mfp;
-	mf_offset = R_OFFSET(dbmp->reginfo, mfp);
-	alloc_bhp = bhp = NULL;
-	hp = NULL;
-	b_incr = extending = ret = 0;
+	MPF_ILLEGAL_BEFORE_OPEN(dbmfp, "DB_MPOOLFILE->get");
 
 	/*
 	 * Validate arguments.
@@ -84,31 +62,89 @@ __memp_fget(dbmfp, pgnoaddr, flags, addrp)
 
 		switch (flags) {
 		case DB_MPOOL_CREATE:
-			break;
 		case DB_MPOOL_LAST:
-			/* Get the last page number in the file. */
-			if (flags == DB_MPOOL_LAST) {
-				R_LOCK(dbenv, dbmp->reginfo);
-				*pgnoaddr = mfp->last_pgno;
-				R_UNLOCK(dbenv, dbmp->reginfo);
-			}
-			break;
 		case DB_MPOOL_NEW:
-			/*
-			 * If always creating a page, skip the first search
-			 * of the hash bucket.
-			 */
-			if (flags == DB_MPOOL_NEW)
-				goto alloc;
 			break;
 		default:
 			return (__db_ferr(dbenv, "memp_fget", 1));
 		}
 	}
 
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__op_rep_enter(dbenv);
+	ret = __memp_fget(dbmfp, pgnoaddr, flags, addrp);
+	/*
+	 * We only decrement the count in op_rep_exit if the operation fails.
+	 * Otherwise the count will be decremented when the page is no longer
+	 * pinned in memp_fput.
+	 */
+	if (ret != 0 && rep_check)
+		__op_rep_exit(dbenv);
+	return (ret);
+}
+
+/*
+ * __memp_fget --
+ *	Get a page from the file.
+ *
+ * PUBLIC: int __memp_fget
+ * PUBLIC:     __P((DB_MPOOLFILE *, db_pgno_t *, u_int32_t, void *));
+ */
+int
+__memp_fget(dbmfp, pgnoaddr, flags, addrp)
+	DB_MPOOLFILE *dbmfp;
+	db_pgno_t *pgnoaddr;
+	u_int32_t flags;
+	void *addrp;
+{
+	enum { FIRST_FOUND, FIRST_MISS, SECOND_FOUND, SECOND_MISS } state;
+	BH *alloc_bhp, *bhp;
+	DB_ENV *dbenv;
+	DB_MPOOL *dbmp;
+	DB_MPOOL_HASH *hp;
+	MPOOL *c_mp, *mp;
+	MPOOLFILE *mfp;
+	roff_t mf_offset;
+	u_int32_t n_cache, st_hsearch;
+	int b_incr, extending, first, ret;
+
+	*(void **)addrp = NULL;
+
+	dbenv = dbmfp->dbenv;
+	dbmp = dbenv->mp_handle;
+
+	c_mp = NULL;
+	mp = dbmp->reginfo[0].primary;
+	mfp = dbmfp->mfp;
+	mf_offset = R_OFFSET(dbmp->reginfo, mfp);
+	alloc_bhp = bhp = NULL;
+	hp = NULL;
+	b_incr = extending = ret = 0;
+
+	switch (flags) {
+	case DB_MPOOL_LAST:
+		/* Get the last page number in the file. */
+		R_LOCK(dbenv, dbmp->reginfo);
+		*pgnoaddr = mfp->last_pgno;
+		R_UNLOCK(dbenv, dbmp->reginfo);
+		break;
+	case DB_MPOOL_NEW:
+		/*
+		 * If always creating a page, skip the first search
+		 * of the hash bucket.
+		 */
+		goto alloc;
+	case DB_MPOOL_CREATE:
+	default:
+		break;
+	}
+
 	/*
 	 * If mmap'ing the file and the page is not past the end of the file,
-	 * just return a pointer.
+	 * just return a pointer.  We can't use R_ADDR here: this is an offset
+	 * into an mmap'd file, not a shared region, and doesn't change for
+	 * private environments.
 	 *
 	 * The page may be past the end of the file, so check the page number
 	 * argument against the original length of the file.  If we previously
@@ -128,8 +164,8 @@ __memp_fget(dbmfp, pgnoaddr, flags, addrp)
 	 */
 	if (dbmfp->addr != NULL &&
 	    F_ISSET(mfp, MP_CAN_MMAP) && *pgnoaddr <= mfp->orig_last_pgno) {
-		*(void **)addrp =
-		    R_ADDR(dbmfp, *pgnoaddr * mfp->stat.st_pagesize);
+		*(void **)addrp = (u_int8_t *)dbmfp->addr +
+		    (*pgnoaddr * mfp->stat.st_pagesize);
 		++mfp->stat.st_map;
 		return (0);
 	}
@@ -160,12 +196,13 @@ retry:	st_hsearch = 0;
 		 * need to ensure it doesn't move and its contents remain
 		 * unchanged.
 		 */
-		if (bhp->ref == UINT16_T_MAX) {
+		if (bhp->ref == UINT16_MAX) {
+			MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
+
 			__db_err(dbenv,
 			    "%s: page %lu: reference count overflow",
 			    __memp_fn(dbmfp), (u_long)bhp->pgno);
-			ret = EINVAL;
-			MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
+			ret = __db_panic(dbenv, EINVAL);
 			goto err;
 		}
 		++bhp->ref;
@@ -250,6 +287,23 @@ retry:	st_hsearch = 0;
 	    (alloc_bhp == NULL ? FIRST_FOUND : SECOND_FOUND);
 	switch (state) {
 	case FIRST_FOUND:
+		/*
+		 * If we are to free the buffer, then this had better
+		 * be the only reference. If so, just free the buffer.
+		 * If not, complain and get out.
+		 */
+		if (flags == DB_MPOOL_FREE) {
+			if (bhp->ref == 1) {
+				__memp_bhfree(dbmp, hp, bhp, BH_FREE_FREEMEM);
+				return (0);
+			}
+			__db_err(dbenv,
+			    "File %s: freeing pinned buffer for page %lu",
+				__memp_fns(dbmp, mfp), (u_long)*pgnoaddr);
+			ret = __db_panic(dbenv, EINVAL);
+			goto err;
+		}
+
 		/* We found the buffer in our first check -- we're done. */
 		break;
 	case FIRST_MISS:
@@ -260,6 +314,12 @@ retry:	st_hsearch = 0;
 		 */
 		MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
 
+		/*
+		 * The buffer is not in the pool, so we don't need to free it.
+		 */
+		if (flags == DB_MPOOL_FREE)
+			return (0);
+
 alloc:		/*
 		 * If DB_MPOOL_NEW is set, we have to allocate a page number.
 		 * If neither DB_MPOOL_CREATE or DB_MPOOL_CREATE is set, then
@@ -272,10 +332,21 @@ alloc:		/*
 		switch (flags) {
 		case DB_MPOOL_NEW:
 			extending = 1;
-			*pgnoaddr = mfp->last_pgno + 1;
+			if (mfp->maxpgno != 0 &&
+			    mfp->last_pgno >= mfp->maxpgno) {
+				__db_err(dbenv, "%s: file limited to %lu pages",
+				    __memp_fn(dbmfp), (u_long)mfp->maxpgno);
+				ret = ENOSPC;
+			} else
+				*pgnoaddr = mfp->last_pgno + 1;
 			break;
 		case DB_MPOOL_CREATE:
-			extending = *pgnoaddr > mfp->last_pgno;
+			if (mfp->maxpgno != 0 && *pgnoaddr > mfp->maxpgno) {
+				__db_err(dbenv, "%s: file limited to %lu pages",
+				    __memp_fn(dbmfp), (u_long)mfp->maxpgno);
+				ret = ENOSPC;
+			} else
+				extending = *pgnoaddr > mfp->last_pgno;
 			break;
 		default:
 			ret = *pgnoaddr > mfp->last_pgno ? DB_PAGE_NOTFOUND : 0;
@@ -292,16 +363,17 @@ alloc:		/*
 		 */
 		mf_offset = R_OFFSET(dbmp->reginfo, mfp);
 		n_cache = NCACHE(mp, mf_offset, *pgnoaddr);
+		c_mp = dbmp->reginfo[n_cache].primary;
 
 		/* Allocate a new buffer header and data space. */
 		if ((ret = __memp_alloc(dbmp,
 		    &dbmp->reginfo[n_cache], mfp, 0, NULL, &alloc_bhp)) != 0)
 			goto err;
 #ifdef DIAGNOSTIC
-		if ((db_alignp_t)alloc_bhp->buf & (sizeof(size_t) - 1)) {
+		if ((uintptr_t)alloc_bhp->buf & (sizeof(size_t) - 1)) {
 			__db_err(dbenv,
-			    "Error: buffer data is NOT size_t aligned");
-			ret = EINVAL;
+		    "DB_MPOOLFILE->get: buffer data is NOT size_t aligned");
+			ret = __db_panic(dbenv, EINVAL);
 			goto err;
 		}
 #endif
@@ -340,14 +412,18 @@ alloc:		/*
 		if (flags == DB_MPOOL_NEW && *pgnoaddr != mfp->last_pgno + 1) {
 			*pgnoaddr = mfp->last_pgno + 1;
 			if (n_cache != NCACHE(mp, mf_offset, *pgnoaddr)) {
-				__db_shalloc_free(
-				    dbmp->reginfo[n_cache].addr, alloc_bhp);
 				/*
 				 * flags == DB_MPOOL_NEW, so extending is set
 				 * and we're holding the region locked.
 				 */
 				R_UNLOCK(dbenv, dbmp->reginfo);
 
+				R_LOCK(dbenv, &dbmp->reginfo[n_cache]);
+				__db_shalloc_free(
+				    &dbmp->reginfo[n_cache], alloc_bhp);
+				c_mp->stat.st_pages--;
+				R_UNLOCK(dbenv, &dbmp->reginfo[n_cache]);
+
 				alloc_bhp = NULL;
 				goto alloc;
 			}
@@ -359,16 +435,7 @@ alloc:		/*
 		 * the file, as necessary, if we extended the file.
 		 */
 		if (extending) {
-#ifdef HAVE_FILESYSTEM_NOTZERO
-			if (*pgnoaddr > mfp->last_pgno &&
-			    __os_fs_notzero() &&
-			    F_ISSET(dbmfp->fhp, DB_FH_VALID))
-				ret = __memp_fs_notzero(
-				    dbenv, dbmfp, mfp, pgnoaddr);
-			else
-				ret = 0;
-#endif
-			if (ret == 0 && *pgnoaddr > mfp->last_pgno)
+			if (*pgnoaddr > mfp->last_pgno)
 				mfp->last_pgno = *pgnoaddr;
 
 			R_UNLOCK(dbenv, dbmp->reginfo);
@@ -390,10 +457,10 @@ alloc:		/*
 		 */
 		MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
 		R_LOCK(dbenv, &dbmp->reginfo[n_cache]);
-		__db_shalloc_free(dbmp->reginfo[n_cache].addr, alloc_bhp);
+		__db_shalloc_free(&dbmp->reginfo[n_cache], alloc_bhp);
+		c_mp->stat.st_pages--;
 		alloc_bhp = NULL;
 		R_UNLOCK(dbenv, &dbmp->reginfo[n_cache]);
-		MUTEX_LOCK(dbenv, &hp->hash_mutex);
 
 		/*
 		 * We can't use the page we found in the pool if DB_MPOOL_NEW
@@ -408,6 +475,9 @@ alloc:		/*
 			b_incr = 0;
 			goto alloc;
 		}
+
+		/* We can use the page -- get the bucket lock. */
+		MUTEX_LOCK(dbenv, &hp->hash_mutex);
 		break;
 	case SECOND_MISS:
 		/*
@@ -427,9 +497,10 @@ alloc:		/*
 		 */
 		b_incr = 1;
 
+		/*lint --e{668} (flexelint: bhp cannot be NULL). */
 		memset(bhp, 0, sizeof(BH));
 		bhp->ref = 1;
-		bhp->priority = UINT32_T_MAX;
+		bhp->priority = UINT32_MAX;
 		bhp->pgno = *pgnoaddr;
 		bhp->mf_offset = mf_offset;
 		SH_TAILQ_INSERT_TAIL(&hp->hash_bucket, bhp, hq);
@@ -505,7 +576,7 @@ alloc:		/*
 	 * the buffer, so there is no need to do it again.)
 	 */
 	if (state != SECOND_MISS && bhp->ref == 1) {
-		bhp->priority = UINT32_T_MAX;
+		bhp->priority = UINT32_MAX;
 		SH_TAILQ_REMOVE(&hp->hash_bucket, bhp, hq, __bh);
 		SH_TAILQ_INSERT_TAIL(&hp->hash_bucket, bhp, hq);
 		hp->hash_priority =
@@ -567,7 +638,7 @@ err:	/*
 	 */
 	if (b_incr) {
 		if (bhp->ref == 1)
-			(void)__memp_bhfree(dbmp, hp, bhp, 1);
+			__memp_bhfree(dbmp, hp, bhp, BH_FREE_FREEMEM);
 		else {
 			--bhp->ref;
 			MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
@@ -575,80 +646,12 @@ err:	/*
 	}
 
 	/* If alloc_bhp is set, free the memory. */
-	if (alloc_bhp != NULL)
-		__db_shalloc_free(dbmp->reginfo[n_cache].addr, alloc_bhp);
-
-	return (ret);
-}
-
-#ifdef HAVE_FILESYSTEM_NOTZERO
-/*
- * __memp_fs_notzero --
- *	Initialize the underlying allocated pages in the file.
- */
-static int
-__memp_fs_notzero(dbenv, dbmfp, mfp, pgnoaddr)
-	DB_ENV *dbenv;
-	DB_MPOOLFILE *dbmfp;
-	MPOOLFILE *mfp;
-	db_pgno_t *pgnoaddr;
-{
-	DB_IO db_io;
-	u_int32_t i, npages;
-	size_t nw;
-	int ret;
-	u_int8_t *page;
-	char *fail;
-
-	/*
-	 * Pages allocated by writing pages past end-of-file are not zeroed,
-	 * on some systems.  Recovery could theoretically be fooled by a page
-	 * showing up that contained garbage.  In order to avoid this, we
-	 * have to write the pages out to disk, and flush them.  The reason
-	 * for the flush is because if we don't sync, the allocation of another
-	 * page subsequent to this one might reach the disk first, and if we
-	 * crashed at the right moment, leave us with this page as the one
-	 * allocated by writing a page past it in the file.
-	 *
-	 * Hash is the only access method that allocates groups of pages.  We
-	 * know that it will use the existence of the last page in a group to
-	 * signify that the entire group is OK; so, write all the pages but
-	 * the last one in the group, flush them to disk, and then write the
-	 * last one to disk and flush it.
-	 */
-	if ((ret = __os_calloc(dbenv, 1, mfp->stat.st_pagesize, &page)) != 0)
-		return (ret);
-
-	db_io.fhp = dbmfp->fhp;
-	db_io.mutexp = dbmfp->mutexp;
-	db_io.pagesize = db_io.bytes = mfp->stat.st_pagesize;
-	db_io.buf = page;
-
-	npages = *pgnoaddr - mfp->last_pgno;
-	for (i = 1; i < npages; ++i) {
-		db_io.pgno = mfp->last_pgno + i;
-		if ((ret = __os_io(dbenv, &db_io, DB_IO_WRITE, &nw)) != 0) {
-			fail = "write";
-			goto err;
-		}
-	}
-	if (i != 1 && (ret = __os_fsync(dbenv, dbmfp->fhp)) != 0) {
-		fail = "sync";
-		goto err;
-	}
-
-	db_io.pgno = mfp->last_pgno + npages;
-	if ((ret = __os_io(dbenv, &db_io, DB_IO_WRITE, &nw)) != 0) {
-		fail = "write";
-		goto err;
-	}
-	if ((ret = __os_fsync(dbenv, dbmfp->fhp)) != 0) {
-		fail = "sync";
-err:		__db_err(dbenv, "%s: %s failed for page %lu",
-		    __memp_fn(dbmfp), fail, (u_long)db_io.pgno);
+	if (alloc_bhp != NULL) {
+		R_LOCK(dbenv, &dbmp->reginfo[n_cache]);
+		__db_shalloc_free(&dbmp->reginfo[n_cache], alloc_bhp);
+		c_mp->stat.st_pages--;
+		R_UNLOCK(dbenv, &dbmp->reginfo[n_cache]);
 	}
 
-	__os_free(dbenv, page);
 	return (ret);
 }
-#endif
diff --git a/storage/bdb/mp/mp_fmethod.c b/storage/bdb/mp/mp_fmethod.c
new file mode 100644
index 0000000000000000000000000000000000000000..e27800c0d7bc16ebbd5c1dd36051d61b9412639f
--- /dev/null
+++ b/storage/bdb/mp/mp_fmethod.c
@@ -0,0 +1,599 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: mp_fmethod.c,v 11.142 2004/10/15 16:59:42 bostic Exp $
+ */
+
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#ifdef HAVE_RPC
+#include <rpc/rpc.h>
+#endif
+
+#include <string.h>
+#endif
+
+#ifdef HAVE_RPC
+#include "db_server.h"
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/log.h"
+#include "dbinc/mp.h"
+
+#ifdef HAVE_RPC
+#include "dbinc_auto/rpc_client_ext.h"
+#endif
+
+static int __memp_get_clear_len __P((DB_MPOOLFILE *, u_int32_t *));
+static int __memp_get_lsn_offset __P((DB_MPOOLFILE *, int32_t *));
+static int __memp_get_maxsize __P((DB_MPOOLFILE *, u_int32_t *, u_int32_t *));
+static int __memp_set_maxsize __P((DB_MPOOLFILE *, u_int32_t, u_int32_t));
+static int __memp_get_pgcookie __P((DB_MPOOLFILE *, DBT *));
+static int __memp_get_priority __P((DB_MPOOLFILE *, DB_CACHE_PRIORITY *));
+static int __memp_set_priority __P((DB_MPOOLFILE *, DB_CACHE_PRIORITY));
+
+/*
+ * __memp_fcreate_pp --
+ *	DB_ENV->memp_fcreate pre/post processing.
+ *
+ * PUBLIC: int __memp_fcreate_pp __P((DB_ENV *, DB_MPOOLFILE **, u_int32_t));
+ */
+int
+__memp_fcreate_pp(dbenv, retp, flags)
+	DB_ENV *dbenv;
+	DB_MPOOLFILE **retp;
+	u_int32_t flags;
+{
+	int rep_check, ret;
+
+	PANIC_CHECK(dbenv);
+
+	/* Validate arguments. */
+	if ((ret = __db_fchk(dbenv, "DB_ENV->memp_fcreate", flags, 0)) != 0)
+		return (ret);
+
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __memp_fcreate(dbenv, retp);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
+/*
+ * __memp_fcreate --
+ *	DB_ENV->memp_fcreate.
+ *
+ * PUBLIC: int __memp_fcreate __P((DB_ENV *, DB_MPOOLFILE **));
+ */
+int
+__memp_fcreate(dbenv, retp)
+	DB_ENV *dbenv;
+	DB_MPOOLFILE **retp;
+{
+	DB_MPOOLFILE *dbmfp;
+	int ret;
+
+	/* Allocate and initialize the per-process structure. */
+	if ((ret = __os_calloc(dbenv, 1, sizeof(DB_MPOOLFILE), &dbmfp)) != 0)
+		return (ret);
+
+	dbmfp->ref = 1;
+	dbmfp->lsn_offset = -1;
+	dbmfp->dbenv = dbenv;
+	dbmfp->mfp = INVALID_ROFF;
+
+#ifdef HAVE_RPC
+	if (F_ISSET(dbenv, DB_ENV_RPCCLIENT)) {
+		dbmfp->get_clear_len = __dbcl_memp_get_clear_len;
+		dbmfp->set_clear_len = __dbcl_memp_set_clear_len;
+		dbmfp->get_fileid = __dbcl_memp_get_fileid;
+		dbmfp->set_fileid = __dbcl_memp_set_fileid;
+		dbmfp->get_flags = __dbcl_memp_get_flags;
+		dbmfp->set_flags = __dbcl_memp_set_flags;
+		dbmfp->get_ftype = __dbcl_memp_get_ftype;
+		dbmfp->set_ftype = __dbcl_memp_set_ftype;
+		dbmfp->get_lsn_offset = __dbcl_memp_get_lsn_offset;
+		dbmfp->set_lsn_offset = __dbcl_memp_set_lsn_offset;
+		dbmfp->get_maxsize = __dbcl_memp_get_maxsize;
+		dbmfp->set_maxsize = __dbcl_memp_set_maxsize;
+		dbmfp->get_pgcookie = __dbcl_memp_get_pgcookie;
+		dbmfp->set_pgcookie = __dbcl_memp_set_pgcookie;
+		dbmfp->get_priority = __dbcl_memp_get_priority;
+		dbmfp->set_priority = __dbcl_memp_set_priority;
+
+		dbmfp->get = __dbcl_memp_fget;
+		dbmfp->open = __dbcl_memp_fopen;
+		dbmfp->put = __dbcl_memp_fput;
+		dbmfp->set = __dbcl_memp_fset;
+		dbmfp->sync = __dbcl_memp_fsync;
+	} else
+#endif
+	{
+		dbmfp->get_clear_len = __memp_get_clear_len;
+		dbmfp->set_clear_len = __memp_set_clear_len;
+		dbmfp->get_fileid = __memp_get_fileid;
+		dbmfp->set_fileid = __memp_set_fileid;
+		dbmfp->get_flags = __memp_get_flags;
+		dbmfp->set_flags = __memp_set_flags;
+		dbmfp->get_ftype = __memp_get_ftype;
+		dbmfp->set_ftype = __memp_set_ftype;
+		dbmfp->get_lsn_offset = __memp_get_lsn_offset;
+		dbmfp->set_lsn_offset = __memp_set_lsn_offset;
+		dbmfp->get_maxsize = __memp_get_maxsize;
+		dbmfp->set_maxsize = __memp_set_maxsize;
+		dbmfp->get_pgcookie = __memp_get_pgcookie;
+		dbmfp->set_pgcookie = __memp_set_pgcookie;
+		dbmfp->get_priority = __memp_get_priority;
+		dbmfp->set_priority = __memp_set_priority;
+
+		dbmfp->get = __memp_fget_pp;
+		dbmfp->open = __memp_fopen_pp;
+		dbmfp->put = __memp_fput_pp;
+		dbmfp->set = __memp_fset_pp;
+		dbmfp->sync = __memp_fsync_pp;
+	}
+	dbmfp->close = __memp_fclose_pp;
+
+	*retp = dbmfp;
+	return (0);
+}
+
+/*
+ * __memp_get_clear_len --
+ *	Get the clear length.
+ */
+static int
+__memp_get_clear_len(dbmfp, clear_lenp)
+	DB_MPOOLFILE *dbmfp;
+	u_int32_t *clear_lenp;
+{
+	*clear_lenp = dbmfp->clear_len;
+	return (0);
+}
+
+/*
+ * __memp_set_clear_len --
+ *	DB_MPOOLFILE->set_clear_len.
+ *
+ * PUBLIC: int __memp_set_clear_len __P((DB_MPOOLFILE *, u_int32_t));
+ */
+int
+__memp_set_clear_len(dbmfp, clear_len)
+	DB_MPOOLFILE *dbmfp;
+	u_int32_t clear_len;
+{
+	MPF_ILLEGAL_AFTER_OPEN(dbmfp, "DB_MPOOLFILE->set_clear_len");
+
+	dbmfp->clear_len = clear_len;
+	return (0);
+}
+
+/*
+ * __memp_get_fileid --
+ *	DB_MPOOLFILE->get_fileid.
+ *
+ * PUBLIC: int __memp_get_fileid __P((DB_MPOOLFILE *, u_int8_t *));
+ */
+int
+__memp_get_fileid(dbmfp, fileid)
+	DB_MPOOLFILE *dbmfp;
+	u_int8_t *fileid;
+{
+	if (!F_ISSET(dbmfp, MP_FILEID_SET)) {
+		__db_err(dbmfp->dbenv, "get_fileid: file ID not set");
+		return (EINVAL);
+	}
+
+	memcpy(fileid, dbmfp->fileid, DB_FILE_ID_LEN);
+	return (0);
+}
+
+/*
+ * __memp_set_fileid --
+ *	DB_MPOOLFILE->set_fileid.
+ *
+ * PUBLIC: int __memp_set_fileid __P((DB_MPOOLFILE *, u_int8_t *));
+ */
+int
+__memp_set_fileid(dbmfp, fileid)
+	DB_MPOOLFILE *dbmfp;
+	u_int8_t *fileid;
+{
+	MPF_ILLEGAL_AFTER_OPEN(dbmfp, "DB_MPOOLFILE->set_fileid");
+
+	memcpy(dbmfp->fileid, fileid, DB_FILE_ID_LEN);
+	F_SET(dbmfp, MP_FILEID_SET);
+
+	return (0);
+}
+
+/*
+ * __memp_get_flags --
+ *	Get the DB_MPOOLFILE flags;
+ *
+ * PUBLIC: int __memp_get_flags __P((DB_MPOOLFILE *, u_int32_t *));
+ */
+int
+__memp_get_flags(dbmfp, flagsp)
+	DB_MPOOLFILE *dbmfp;
+	u_int32_t *flagsp;
+{
+	MPOOLFILE *mfp;
+
+	mfp = dbmfp->mfp;
+
+	*flagsp = 0;
+
+	if (mfp == NULL)
+		*flagsp = FLD_ISSET(dbmfp->config_flags,
+		     DB_MPOOL_NOFILE | DB_MPOOL_UNLINK);
+	else {
+		if (mfp->no_backing_file)
+			FLD_SET(*flagsp, DB_MPOOL_NOFILE);
+		if (mfp->unlink_on_close)
+			FLD_SET(*flagsp, DB_MPOOL_UNLINK);
+	}
+	return (0);
+}
+
+/*
+ * __memp_set_flags --
+ *	Set the DB_MPOOLFILE flags;
+ *
+ * PUBLIC: int __memp_set_flags __P((DB_MPOOLFILE *, u_int32_t, int));
+ */
+int
+__memp_set_flags(dbmfp, flags, onoff)
+	DB_MPOOLFILE *dbmfp;
+	u_int32_t flags;
+	int onoff;
+{
+	DB_ENV *dbenv;
+	MPOOLFILE *mfp;
+	int ret;
+
+	dbenv = dbmfp->dbenv;
+	mfp = dbmfp->mfp;
+
+	switch (flags) {
+	case DB_MPOOL_NOFILE:
+		if (mfp == NULL)
+			if (onoff)
+				FLD_SET(dbmfp->config_flags, DB_MPOOL_NOFILE);
+			else
+				FLD_CLR(dbmfp->config_flags, DB_MPOOL_NOFILE);
+		else
+			mfp->no_backing_file = onoff;
+		break;
+	case DB_MPOOL_UNLINK:
+		if (mfp == NULL)
+			if (onoff)
+				FLD_SET(dbmfp->config_flags, DB_MPOOL_UNLINK);
+			else
+				FLD_CLR(dbmfp->config_flags, DB_MPOOL_UNLINK);
+		else
+			mfp->unlink_on_close = onoff;
+		break;
+	default:
+		if ((ret = __db_fchk(dbenv, "DB_MPOOLFILE->set_flags",
+		    flags, DB_MPOOL_NOFILE | DB_MPOOL_UNLINK)) != 0)
+			return (ret);
+		break;
+	}
+	return (0);
+}
+
+/*
+ * __memp_get_ftype --
+ *	Get the file type (as registered).
+ *
+ * PUBLIC: int __memp_get_ftype __P((DB_MPOOLFILE *, int *));
+ */
+int
+__memp_get_ftype(dbmfp, ftypep)
+	DB_MPOOLFILE *dbmfp;
+	int *ftypep;
+{
+	*ftypep = dbmfp->ftype;
+	return (0);
+}
+
+/*
+ * __memp_set_ftype --
+ *	DB_MPOOLFILE->set_ftype.
+ *
+ * PUBLIC: int __memp_set_ftype __P((DB_MPOOLFILE *, int));
+ */
+int
+__memp_set_ftype(dbmfp, ftype)
+	DB_MPOOLFILE *dbmfp;
+	int ftype;
+{
+	MPF_ILLEGAL_AFTER_OPEN(dbmfp, "DB_MPOOLFILE->set_ftype");
+
+	dbmfp->ftype = ftype;
+	return (0);
+}
+
+/*
+ * __memp_get_lsn_offset --
+ *	Get the page's LSN offset.
+ */
+static int
+__memp_get_lsn_offset(dbmfp, lsn_offsetp)
+	DB_MPOOLFILE *dbmfp;
+	int32_t *lsn_offsetp;
+{
+	*lsn_offsetp = dbmfp->lsn_offset;
+	return (0);
+}
+
+/*
+ * __memp_set_lsn_offset --
+ *	Set the page's LSN offset.
+ *
+ * PUBLIC: int __memp_set_lsn_offset __P((DB_MPOOLFILE *, int32_t));
+ */
+int
+__memp_set_lsn_offset(dbmfp, lsn_offset)
+	DB_MPOOLFILE *dbmfp;
+	int32_t lsn_offset;
+{
+	MPF_ILLEGAL_AFTER_OPEN(dbmfp, "DB_MPOOLFILE->set_lsn_offset");
+
+	dbmfp->lsn_offset = lsn_offset;
+	return (0);
+}
+
+/*
+ * __memp_get_maxsize --
+ *	Get the file's maximum size.
+ */
+static int
+__memp_get_maxsize(dbmfp, gbytesp, bytesp)
+	DB_MPOOLFILE *dbmfp;
+	u_int32_t *gbytesp, *bytesp;
+{
+	DB_ENV *dbenv;
+	DB_MPOOL *dbmp;
+	MPOOLFILE *mfp;
+
+	if ((mfp = dbmfp->mfp) == NULL) {
+		*gbytesp = dbmfp->gbytes;
+		*bytesp = dbmfp->bytes;
+	} else {
+		dbenv = dbmfp->dbenv;
+		dbmp = dbenv->mp_handle;
+
+		R_LOCK(dbenv, dbmp->reginfo);
+		*gbytesp = (u_int32_t)
+		    (mfp->maxpgno / (GIGABYTE / mfp->stat.st_pagesize));
+		*bytesp = (u_int32_t)
+		    ((mfp->maxpgno % (GIGABYTE / mfp->stat.st_pagesize)) *
+		    mfp->stat.st_pagesize);
+		R_UNLOCK(dbenv, dbmp->reginfo);
+	}
+
+	return (0);
+}
+
+/*
+ * __memp_set_maxsize --
+ *	Set the file's maximum size.
+ */
+static int
+__memp_set_maxsize(dbmfp, gbytes, bytes)
+	DB_MPOOLFILE *dbmfp;
+	u_int32_t gbytes, bytes;
+{
+	DB_ENV *dbenv;
+	DB_MPOOL *dbmp;
+	MPOOLFILE *mfp;
+
+	if ((mfp = dbmfp->mfp) == NULL) {
+		dbmfp->gbytes = gbytes;
+		dbmfp->bytes = bytes;
+	} else {
+		dbenv = dbmfp->dbenv;
+		dbmp = dbenv->mp_handle;
+
+		R_LOCK(dbenv, dbmp->reginfo);
+		mfp->maxpgno = (db_pgno_t)
+		    (gbytes * (GIGABYTE / mfp->stat.st_pagesize));
+		mfp->maxpgno += (db_pgno_t)
+		    ((bytes + mfp->stat.st_pagesize - 1) /
+		    mfp->stat.st_pagesize);
+		R_UNLOCK(dbenv, dbmp->reginfo);
+	}
+
+	return (0);
+}
+
+/*
+ * __memp_get_pgcookie --
+ *	Get the pgin/pgout cookie.
+ */
+static int
+__memp_get_pgcookie(dbmfp, pgcookie)
+	DB_MPOOLFILE *dbmfp;
+	DBT *pgcookie;
+{
+	if (dbmfp->pgcookie == NULL) {
+		pgcookie->size = 0;
+		pgcookie->data = "";
+	} else
+		memcpy(pgcookie, dbmfp->pgcookie, sizeof(DBT));
+	return (0);
+}
+
+/*
+ * __memp_set_pgcookie --
+ *	Set the pgin/pgout cookie.
+ *
+ * PUBLIC: int __memp_set_pgcookie __P((DB_MPOOLFILE *, DBT *));
+ */
+int
+__memp_set_pgcookie(dbmfp, pgcookie)
+	DB_MPOOLFILE *dbmfp;
+	DBT *pgcookie;
+{
+	DB_ENV *dbenv;
+	DBT *cookie;
+	int ret;
+
+	MPF_ILLEGAL_AFTER_OPEN(dbmfp, "DB_MPOOLFILE->set_pgcookie");
+	dbenv = dbmfp->dbenv;
+
+	if ((ret = __os_calloc(dbenv, 1, sizeof(*cookie), &cookie)) != 0)
+		return (ret);
+	if ((ret = __os_malloc(dbenv, pgcookie->size, &cookie->data)) != 0) {
+		__os_free(dbenv, cookie);
+		return (ret);
+	}
+
+	memcpy(cookie->data, pgcookie->data, pgcookie->size);
+	cookie->size = pgcookie->size;
+
+	dbmfp->pgcookie = cookie;
+	return (0);
+}
+
+/*
+ * __memp_get_priority --
+ *	Set the cache priority for pages from this file.
+ */
+static int
+__memp_get_priority(dbmfp, priorityp)
+	DB_MPOOLFILE *dbmfp;
+	DB_CACHE_PRIORITY *priorityp;
+{
+	switch (dbmfp->priority) {
+	case MPOOL_PRI_VERY_LOW:
+		*priorityp = DB_PRIORITY_VERY_LOW;
+		break;
+	case MPOOL_PRI_LOW:
+		*priorityp = DB_PRIORITY_LOW;
+		break;
+	case MPOOL_PRI_DEFAULT:
+		*priorityp = DB_PRIORITY_DEFAULT;
+		break;
+	case MPOOL_PRI_HIGH:
+		*priorityp = DB_PRIORITY_HIGH;
+		break;
+	case MPOOL_PRI_VERY_HIGH:
+		*priorityp = DB_PRIORITY_VERY_HIGH;
+		break;
+	default:
+		__db_err(dbmfp->dbenv,
+		    "DB_MPOOLFILE->get_priority: unknown priority value: %d",
+		    dbmfp->priority);
+		return (EINVAL);
+	}
+
+	return (0);
+}
+
+/*
+ * __memp_set_priority --
+ *	Set the cache priority for pages from this file.
+ */
+static int
+__memp_set_priority(dbmfp, priority)
+	DB_MPOOLFILE *dbmfp;
+	DB_CACHE_PRIORITY priority;
+{
+	switch (priority) {
+	case DB_PRIORITY_VERY_LOW:
+		dbmfp->priority = MPOOL_PRI_VERY_LOW;
+		break;
+	case DB_PRIORITY_LOW:
+		dbmfp->priority = MPOOL_PRI_LOW;
+		break;
+	case DB_PRIORITY_DEFAULT:
+		dbmfp->priority = MPOOL_PRI_DEFAULT;
+		break;
+	case DB_PRIORITY_HIGH:
+		dbmfp->priority = MPOOL_PRI_HIGH;
+		break;
+	case DB_PRIORITY_VERY_HIGH:
+		dbmfp->priority = MPOOL_PRI_VERY_HIGH;
+		break;
+	default:
+		__db_err(dbmfp->dbenv,
+		    "DB_MPOOLFILE->set_priority: unknown priority value: %d",
+		    priority);
+		return (EINVAL);
+	}
+
+	/* Update the underlying file if we've already opened it. */
+	if (dbmfp->mfp != NULL)
+		dbmfp->mfp->priority = priority;
+
+	return (0);
+}
+
+/*
+ * __memp_last_pgno --
+ *	Return the page number of the last page in the file.
+ *
+ * !!!
+ * Undocumented interface: DB private.
+ *
+ * PUBLIC: void __memp_last_pgno __P((DB_MPOOLFILE *, db_pgno_t *));
+ */
+void
+__memp_last_pgno(dbmfp, pgnoaddr)
+	DB_MPOOLFILE *dbmfp;
+	db_pgno_t *pgnoaddr;
+{
+	DB_ENV *dbenv;
+	DB_MPOOL *dbmp;
+
+	dbenv = dbmfp->dbenv;
+	dbmp = dbenv->mp_handle;
+
+	R_LOCK(dbenv, dbmp->reginfo);
+	*pgnoaddr = dbmfp->mfp->last_pgno;
+	R_UNLOCK(dbenv, dbmp->reginfo);
+}
+
+/*
+ * __memp_fn --
+ *	On errors we print whatever is available as the file name.
+ *
+ * PUBLIC: char * __memp_fn __P((DB_MPOOLFILE *));
+ */
+char *
+__memp_fn(dbmfp)
+	DB_MPOOLFILE *dbmfp;
+{
+	return (__memp_fns(dbmfp->dbenv->mp_handle, dbmfp->mfp));
+}
+
+/*
+ * __memp_fns --
+ *	On errors we print whatever is available as the file name.
+ *
+ * PUBLIC: char * __memp_fns __P((DB_MPOOL *, MPOOLFILE *));
+ *
+ */
+char *
+__memp_fns(dbmp, mfp)
+	DB_MPOOL *dbmp;
+	MPOOLFILE *mfp;
+{
+	if (mfp->path_off == 0)
+		return ((char *)"temporary");
+
+	return ((char *)R_ADDR(dbmp->reginfo, mfp->path_off));
+}
diff --git a/storage/bdb/mp/mp_fopen.c b/storage/bdb/mp/mp_fopen.c
index 8fdefb0f5e9cf743e008df8c3ce1f90caf6ca201..7e302f898046ad751fe2623c5c430023c14e402a 100644
--- a/storage/bdb/mp/mp_fopen.c
+++ b/storage/bdb/mp/mp_fopen.c
@@ -1,14 +1,13 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: mp_fopen.c,v 11.143 2004/10/15 16:59:43 bostic Exp $
  */
-#include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: mp_fopen.c,v 11.90 2002/08/26 15:22:01 bostic Exp $";
-#endif /* not lint */
+#include "db_config.h"
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
@@ -18,218 +17,18 @@ static const char revid[] = "$Id: mp_fopen.c,v 11.90 2002/08/26 15:22:01 bostic
 
 #include "db_int.h"
 #include "dbinc/db_shash.h"
+#include "dbinc/log.h"
 #include "dbinc/mp.h"
 
-static int  __memp_fclose __P((DB_MPOOLFILE *, u_int32_t));
-static int  __memp_fopen __P((DB_MPOOLFILE *,
-		const char *, u_int32_t, int, size_t));
-static void __memp_get_fileid __P((DB_MPOOLFILE *, u_int8_t *));
-static void __memp_last_pgno __P((DB_MPOOLFILE *, db_pgno_t *));
-static void __memp_refcnt __P((DB_MPOOLFILE *, db_pgno_t *));
-static int  __memp_set_clear_len __P((DB_MPOOLFILE *, u_int32_t));
-static int  __memp_set_fileid __P((DB_MPOOLFILE *, u_int8_t *));
-static int  __memp_set_ftype __P((DB_MPOOLFILE *, int));
-static int  __memp_set_lsn_offset __P((DB_MPOOLFILE *, int32_t));
-static int  __memp_set_pgcookie __P((DB_MPOOLFILE *, DBT *));
-static int  __memp_set_priority __P((DB_MPOOLFILE *, DB_CACHE_PRIORITY));
-static void __memp_set_unlink __P((DB_MPOOLFILE *, int));
-
-/* Initialization methods cannot be called after open is called. */
-#define	MPF_ILLEGAL_AFTER_OPEN(dbmfp, name)				\
-	if (F_ISSET(dbmfp, MP_OPEN_CALLED))				\
-		return (__db_mi_open((dbmfp)->dbmp->dbenv, name, 1));
-
 /*
- * __memp_fcreate --
- *	Create a DB_MPOOLFILE handle.
+ * __memp_fopen_pp --
+ *	DB_MPOOLFILE->open pre/post processing.
  *
- * PUBLIC: int __memp_fcreate __P((DB_ENV *, DB_MPOOLFILE **, u_int32_t));
+ * PUBLIC: int __memp_fopen_pp
+ * PUBLIC:     __P((DB_MPOOLFILE *, const char *, u_int32_t, int, size_t));
  */
 int
-__memp_fcreate(dbenv, retp, flags)
-	DB_ENV *dbenv;
-	DB_MPOOLFILE **retp;
-	u_int32_t flags;
-{
-	DB_MPOOL *dbmp;
-	DB_MPOOLFILE *dbmfp;
-	int ret;
-
-	PANIC_CHECK(dbenv);
-	ENV_REQUIRES_CONFIG(dbenv,
-	    dbenv->mp_handle, "memp_fcreate", DB_INIT_MPOOL);
-
-	dbmp = dbenv->mp_handle;
-
-	/* Validate arguments. */
-	if ((ret = __db_fchk(dbenv, "memp_fcreate", flags, 0)) != 0)
-		return (ret);
-
-	/* Allocate and initialize the per-process structure. */
-	if ((ret = __os_calloc(dbenv, 1, sizeof(DB_MPOOLFILE), &dbmfp)) != 0)
-		return (ret);
-	if ((ret = __os_calloc(dbenv, 1, sizeof(DB_FH), &dbmfp->fhp)) != 0)
-		goto err;
-
-	/* Allocate and initialize a mutex if necessary. */
-	if (F_ISSET(dbenv, DB_ENV_THREAD) &&
-	    (ret = __db_mutex_setup(dbenv, dbmp->reginfo, &dbmfp->mutexp,
-	    MUTEX_ALLOC | MUTEX_THREAD)) != 0)
-		goto err;
-
-	dbmfp->ref = 1;
-	dbmfp->lsn_offset = -1;
-	dbmfp->dbmp = dbmp;
-	dbmfp->mfp = INVALID_ROFF;
-
-	dbmfp->close = __memp_fclose;
-	dbmfp->get = __memp_fget;
-	dbmfp->get_fileid = __memp_get_fileid;
-	dbmfp->last_pgno = __memp_last_pgno;
-	dbmfp->open = __memp_fopen;
-	dbmfp->put = __memp_fput;
-	dbmfp->refcnt = __memp_refcnt;
-	dbmfp->set = __memp_fset;
-	dbmfp->set_clear_len = __memp_set_clear_len;
-	dbmfp->set_fileid = __memp_set_fileid;
-	dbmfp->set_ftype = __memp_set_ftype;
-	dbmfp->set_lsn_offset = __memp_set_lsn_offset;
-	dbmfp->set_pgcookie = __memp_set_pgcookie;
-	dbmfp->set_priority = __memp_set_priority;
-	dbmfp->set_unlink = __memp_set_unlink;
-	dbmfp->sync = __memp_fsync;
-
-	*retp = dbmfp;
-	return (0);
-
-err:	if (dbmfp != NULL) {
-		if (dbmfp->fhp != NULL)
-			(void)__os_free(dbenv, dbmfp->fhp);
-		(void)__os_free(dbenv, dbmfp);
-	}
-	return (ret);
-}
-
-/*
- * __memp_set_clear_len --
- *	Set the clear length.
- */
-static int
-__memp_set_clear_len(dbmfp, clear_len)
-	DB_MPOOLFILE *dbmfp;
-	u_int32_t clear_len;
-{
-	MPF_ILLEGAL_AFTER_OPEN(dbmfp, "set_clear_len");
-
-	dbmfp->clear_len = clear_len;
-	return (0);
-}
-
-/*
- * __memp_set_fileid --
- *	Set the file ID.
- */
-static int
-__memp_set_fileid(dbmfp, fileid)
-	DB_MPOOLFILE *dbmfp;
-	u_int8_t *fileid;
-{
-	MPF_ILLEGAL_AFTER_OPEN(dbmfp, "set_fileid");
-
-	/*
-	 * XXX
-	 * This is dangerous -- we're saving the caller's pointer instead
-	 * of allocating memory and copying the contents.
-	 */
-	dbmfp->fileid = fileid;
-	return (0);
-}
-
-/*
- * __memp_set_ftype --
- *	Set the file type (as registered).
- */
-static int
-__memp_set_ftype(dbmfp, ftype)
-	DB_MPOOLFILE *dbmfp;
-	int ftype;
-{
-	MPF_ILLEGAL_AFTER_OPEN(dbmfp, "set_ftype");
-
-	dbmfp->ftype = ftype;
-	return (0);
-}
-
-/*
- * __memp_set_lsn_offset --
- *	Set the page's LSN offset.
- */
-static int
-__memp_set_lsn_offset(dbmfp, lsn_offset)
-	DB_MPOOLFILE *dbmfp;
-	int32_t lsn_offset;
-{
-	MPF_ILLEGAL_AFTER_OPEN(dbmfp, "set_lsn_offset");
-
-	dbmfp->lsn_offset = lsn_offset;
-	return (0);
-}
-
-/*
- * __memp_set_pgcookie --
- *	Set the pgin/pgout cookie.
- */
-static int
-__memp_set_pgcookie(dbmfp, pgcookie)
-	DB_MPOOLFILE *dbmfp;
-	DBT *pgcookie;
-{
-	MPF_ILLEGAL_AFTER_OPEN(dbmfp, "set_pgcookie");
-
-	dbmfp->pgcookie = pgcookie;
-	return (0);
-}
-
-/*
- * __memp_set_priority --
- *	Set the cache priority for pages from this file.
- */
-static int
-__memp_set_priority(dbmfp, priority)
-	DB_MPOOLFILE *dbmfp;
-	DB_CACHE_PRIORITY priority;
-{
-	switch (priority) {
-	case DB_PRIORITY_VERY_LOW:
-		dbmfp->mfp->priority = MPOOL_PRI_VERY_LOW;
-		break;
-	case DB_PRIORITY_LOW:
-		dbmfp->mfp->priority = MPOOL_PRI_LOW;
-		break;
-	case DB_PRIORITY_DEFAULT:
-		dbmfp->mfp->priority = MPOOL_PRI_DEFAULT;
-		break;
-	case DB_PRIORITY_HIGH:
-		dbmfp->mfp->priority = MPOOL_PRI_HIGH;
-		break;
-	case DB_PRIORITY_VERY_HIGH:
-		dbmfp->mfp->priority = MPOOL_PRI_VERY_HIGH;
-		break;
-	default:
-		__db_err(dbmfp->dbmp->dbenv,
-		    "Unknown priority value: %d", priority);
-		return (EINVAL);
-	}
-
-	return (0);
-}
-
-/*
- * __memp_fopen --
- *	Open a backing file for the memory pool.
- */
-static int
-__memp_fopen(dbmfp, path, flags, mode, pagesize)
+__memp_fopen_pp(dbmfp, path, flags, mode, pagesize)
 	DB_MPOOLFILE *dbmfp;
 	const char *path;
 	u_int32_t flags;
@@ -237,16 +36,14 @@ __memp_fopen(dbmfp, path, flags, mode, pagesize)
 	size_t pagesize;
 {
 	DB_ENV *dbenv;
-	DB_MPOOL *dbmp;
-	int ret;
+	int rep_check, ret;
 
-	dbmp = dbmfp->dbmp;
-	dbenv = dbmp->dbenv;
+	dbenv = dbmfp->dbenv;
 
 	PANIC_CHECK(dbenv);
 
 	/* Validate arguments. */
-	if ((ret = __db_fchk(dbenv, "memp_fopen", flags,
+	if ((ret = __db_fchk(dbenv, "DB_MPOOLFILE->open", flags,
 	    DB_CREATE | DB_DIRECT | DB_EXTENT |
 	    DB_NOMMAP | DB_ODDFILESIZE | DB_RDONLY | DB_TRUNCATE)) != 0)
 		return (ret);
@@ -257,75 +54,110 @@ __memp_fopen(dbmfp, path, flags, mode, pagesize)
 	 */
 	if (pagesize == 0 || !POWER_OF_TWO(pagesize)) {
 		__db_err(dbenv,
-		    "memp_fopen: page sizes must be a power-of-2");
+		    "DB_MPOOLFILE->open: page sizes must be a power-of-2");
 		return (EINVAL);
 	}
 	if (dbmfp->clear_len > pagesize) {
 		__db_err(dbenv,
-		    "memp_fopen: clear length larger than page size");
+		    "DB_MPOOLFILE->open: clear length larger than page size");
 		return (EINVAL);
 	}
 
 	/* Read-only checks, and local flag. */
 	if (LF_ISSET(DB_RDONLY) && path == NULL) {
 		__db_err(dbenv,
-		    "memp_fopen: temporary files can't be readonly");
+		    "DB_MPOOLFILE->open: temporary files can't be readonly");
 		return (EINVAL);
 	}
 
-	return (__memp_fopen_int(dbmfp, NULL, path, flags, mode, pagesize));
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __memp_fopen(dbmfp, NULL, path, flags, mode, pagesize);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
 }
 
 /*
- * __memp_fopen_int --
- *	Open a backing file for the memory pool; internal version.
+ * __memp_fopen --
+ *	DB_MPOOLFILE->open.
  *
- * PUBLIC: int __memp_fopen_int __P((DB_MPOOLFILE *,
+ * PUBLIC: int __memp_fopen __P((DB_MPOOLFILE *,
  * PUBLIC:     MPOOLFILE *, const char *, u_int32_t, int, size_t));
  */
 int
-__memp_fopen_int(dbmfp, mfp, path, flags, mode, pagesize)
+__memp_fopen(dbmfp, mfp, path, flags, mode, pgsize)
 	DB_MPOOLFILE *dbmfp;
 	MPOOLFILE *mfp;
 	const char *path;
 	u_int32_t flags;
 	int mode;
-	size_t pagesize;
+	size_t pgsize;
 {
 	DB_ENV *dbenv;
 	DB_MPOOL *dbmp;
+	DB_MPOOLFILE *tmp_dbmfp;
 	MPOOL *mp;
 	db_pgno_t last_pgno;
 	size_t maxmap;
-	u_int32_t mbytes, bytes, oflags;
-	int mfp_alloc, ret;
-	u_int8_t idbuf[DB_FILE_ID_LEN];
+	u_int32_t mbytes, bytes, oflags, pagesize;
+	int refinc, ret;
 	char *rpath;
 	void *p;
 
-	dbmp = dbmfp->dbmp;
-	dbenv = dbmp->dbenv;
+	dbenv = dbmfp->dbenv;
+	dbmp = dbenv->mp_handle;
 	mp = dbmp->reginfo[0].primary;
-	mfp_alloc = ret = 0;
+	refinc = ret = 0;
 	rpath = NULL;
 
 	/*
-	 * Set the page size so os_open can decide whether to turn buffering
-	 * off if the DB_DIRECT_DB flag is set.
+	 * We're keeping the page size as a size_t in the public API, but
+	 * it's a u_int32_t everywhere internally.
 	 */
-	dbmfp->fhp->pagesize = (u_int32_t)pagesize;
+	pagesize = (u_int32_t)pgsize;
 
 	/*
-	 * If it's a temporary file, delay the open until we actually need
-	 * to write the file, and we know we can't join any existing files.
+	 * We're called internally with a specified mfp, in which case the
+	 * path is NULL, but we'll get the path from the underlying region
+	 * information.  Otherwise, if the path is NULL, it's a temporary
+	 * file -- we know we can't join any existing files, and we'll delay
+	 * the open until we actually need to write the file.
 	 */
-	if (path == NULL)
+	DB_ASSERT(mfp == NULL || path == NULL);
+
+	if (mfp == NULL && path == NULL)
 		goto alloc;
 
 	/*
-	 * Get the real name for this file and open it.  If it's a Queue extent
-	 * file, it may not exist, and that's OK.
+	 * Our caller may be able to tell us which underlying MPOOLFILE we
+	 * need a handle for.
 	 */
+	if (mfp != NULL) {
+		/*
+		 * Deadfile can only be set if mpf_cnt goes to zero (or if we
+		 * failed creating the file DB_AM_DISCARD).  Increment the ref
+		 * count so the file cannot become dead and be unlinked.
+		 */
+		MUTEX_LOCK(dbenv, &mfp->mutex);
+		if (!mfp->deadfile) {
+			++mfp->mpf_cnt;
+			refinc = 1;
+		}
+		MUTEX_UNLOCK(dbenv, &mfp->mutex);
+
+		/*
+		 * Test one last time to see if the file is dead -- it may have
+		 * been removed.  This happens when a checkpoint trying to open
+		 * the file to flush a buffer races with the Db::remove method.
+		 * The error will be ignored, so don't output an error message.
+		 */
+		if (mfp->deadfile)
+			return (EINVAL);
+	}
+
+	/* Convert MP open flags to DB OS-layer open flags. */
 	oflags = 0;
 	if (LF_ISSET(DB_CREATE))
 		oflags |= DB_OSO_CREATE;
@@ -335,15 +167,44 @@ __memp_fopen_int(dbmfp, mfp, path, flags, mode, pagesize)
 		F_SET(dbmfp, MP_READONLY);
 		oflags |= DB_OSO_RDONLY;
 	}
+
+	/*
+	 * Get the real name for this file and open it.
+	 *
+	 * Supply a page size so os_open can decide whether to turn buffering
+	 * off if the DB_DIRECT_DB flag is set.
+	 *
+	 * Acquire the region lock if we're using a path from an underlying
+	 * MPOOLFILE -- there's a race in accessing the path name stored in
+	 * the region, __memp_nameop may be simultaneously renaming the file.
+	 */
+	if (mfp != NULL) {
+		R_LOCK(dbenv, dbmp->reginfo);
+		path = R_ADDR(dbmp->reginfo, mfp->path_off);
+	}
 	if ((ret =
-	    __db_appname(dbenv, DB_APP_DATA, path, 0, NULL, &rpath)) != 0)
-		goto err;
-	if ((ret = __os_open(dbenv, rpath, oflags, mode, dbmfp->fhp)) != 0) {
+	    __db_appname(dbenv, DB_APP_DATA, path, 0, NULL, &rpath)) == 0)
+		ret = __os_open_extend(dbenv,
+		    rpath, (u_int32_t)pagesize, oflags, mode, &dbmfp->fhp);
+	if (mfp != NULL)
+		R_UNLOCK(dbenv, dbmp->reginfo);
+	if (ret != 0) {
+		/* If it's a Queue extent file, it may not exist, that's OK. */
 		if (!LF_ISSET(DB_EXTENT))
 			__db_err(dbenv, "%s: %s", rpath, db_strerror(ret));
 		goto err;
 	}
 
+	/*
+	 * Cache file handles are shared, and have mutexes to protect the
+	 * underlying file handle across seek and read/write calls.
+	 */
+	dbmfp->fhp->ref = 1;
+	if (F_ISSET(dbenv, DB_ENV_THREAD) &&
+	    (ret = __db_mutex_setup(dbenv, dbmp->reginfo,
+	    &dbmfp->fhp->mutexp, MUTEX_ALLOC | MUTEX_THREAD)) != 0)
+		goto err;
+
 	/*
 	 * Figure out the file's size.
 	 *
@@ -366,25 +227,12 @@ __memp_fopen_int(dbmfp, mfp, path, flags, mode, pagesize)
 	 * don't use timestamps, otherwise there'd be no chance of any
 	 * other process joining the party.
 	 */
-	if (dbmfp->fileid == NULL) {
-		if ((ret = __os_fileid(dbenv, rpath, 0, idbuf)) != 0)
-			goto err;
-		dbmfp->fileid = idbuf;
-	}
+	if (!F_ISSET(dbmfp, MP_FILEID_SET) &&
+	    (ret = __os_fileid(dbenv, rpath, 0, dbmfp->fileid)) != 0)
+		goto err;
 
-	/*
-	 * If our caller knows what mfp we're using, increment the ref count,
-	 * no need to search.
-	 *
-	 * We don't need to acquire a lock other than the mfp itself, because
-	 * we know there's another reference and it's not going away.
-	 */
-	if (mfp != NULL) {
-		MUTEX_LOCK(dbenv, &mfp->mutex);
-		++mfp->mpf_cnt;
-		MUTEX_UNLOCK(dbenv, &mfp->mutex);
-		goto check_map;
-	}
+	if (mfp != NULL)
+		goto have_mfp;
 
 	/*
 	 * If not creating a temporary file, walk the list of MPOOLFILE's,
@@ -411,7 +259,7 @@ __memp_fopen_int(dbmfp, mfp, path, flags, mode, pagesize)
 	for (mfp = SH_TAILQ_FIRST(&mp->mpfq, __mpoolfile);
 	    mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) {
 		/* Skip dead files and temporary files. */
-		if (F_ISSET(mfp, MP_DEADFILE | MP_TEMP))
+		if (mfp->deadfile || F_ISSET(mfp, MP_TEMP))
 			continue;
 
 		/* Skip non-matching files. */
@@ -429,7 +277,7 @@ __memp_fopen_int(dbmfp, mfp, path, flags, mode, pagesize)
 		 */
 		if (LF_ISSET(DB_TRUNCATE)) {
 			MUTEX_LOCK(dbenv, &mfp->mutex);
-			MPOOLFILE_IGNORE(mfp);
+			mfp->deadfile = 1;
 			MUTEX_UNLOCK(dbenv, &mfp->mutex);
 			continue;
 		}
@@ -443,9 +291,9 @@ __memp_fopen_int(dbmfp, mfp, path, flags, mode, pagesize)
 		 * created a hash subdatabase in a database that was previously
 		 * all btree.
 		 *
-		 * XXX
+		 * !!!
 		 * We do not check to see if the pgcookie information changed,
-		 * or update it if it is, this might be a bug.
+		 * or update it if it is.
 		 */
 		if (dbmfp->clear_len != mfp->clear_len ||
 		    pagesize != mfp->stat.st_pagesize ||
@@ -458,31 +306,64 @@ __memp_fopen_int(dbmfp, mfp, path, flags, mode, pagesize)
 			goto err;
 		}
 
-		if (dbmfp->ftype != 0)
-			mfp->ftype = dbmfp->ftype;
-
+		/*
+		 * Check to see if this file has died while we waited.
+		 *
+		 * We normally don't lock the deadfile field when we read it as
+		 * we only care if the field is zero or non-zero.  We do lock
+		 * on read when searching for a matching MPOOLFILE so that two
+		 * threads of control don't race between setting the deadfile
+		 * bit and incrementing the reference count, that is, a thread
+		 * of control decrementing the reference count and then setting
+		 * deadfile because the reference count is 0 blocks us finding
+		 * the file without knowing it's about to be marked dead.
+		 */
 		MUTEX_LOCK(dbenv, &mfp->mutex);
+		if (mfp->deadfile) {
+			MUTEX_UNLOCK(dbenv, &mfp->mutex);
+			continue;
+		}
 		++mfp->mpf_cnt;
+		refinc = 1;
 		MUTEX_UNLOCK(dbenv, &mfp->mutex);
+
+		if (dbmfp->ftype != 0)
+			mfp->ftype = dbmfp->ftype;
+
 		break;
 	}
 	R_UNLOCK(dbenv, dbmp->reginfo);
 
 	if (mfp != NULL)
-		goto check_map;
+		goto have_mfp;
 
 alloc:	/* Allocate and initialize a new MPOOLFILE. */
 	if ((ret = __memp_alloc(
 	    dbmp, dbmp->reginfo, NULL, sizeof(MPOOLFILE), NULL, &mfp)) != 0)
 		goto err;
-	mfp_alloc = 1;
 	memset(mfp, 0, sizeof(MPOOLFILE));
 	mfp->mpf_cnt = 1;
 	mfp->ftype = dbmfp->ftype;
 	mfp->stat.st_pagesize = pagesize;
 	mfp->lsn_off = dbmfp->lsn_offset;
 	mfp->clear_len = dbmfp->clear_len;
-
+	mfp->priority = dbmfp->priority;
+	if (dbmfp->gbytes != 0 || dbmfp->bytes != 0) {
+		mfp->maxpgno = (db_pgno_t)
+		    (dbmfp->gbytes * (GIGABYTE / mfp->stat.st_pagesize));
+		mfp->maxpgno += (db_pgno_t)
+		    ((dbmfp->bytes + mfp->stat.st_pagesize - 1) /
+		    mfp->stat.st_pagesize);
+	}
+	if (FLD_ISSET(dbmfp->config_flags, DB_MPOOL_NOFILE))
+		mfp->no_backing_file = 1;
+	if (FLD_ISSET(dbmfp->config_flags, DB_MPOOL_UNLINK))
+		mfp->unlink_on_close = 1;
+
+	if (LF_ISSET(DB_TXN_NOT_DURABLE))
+		F_SET(mfp, MP_NOT_DURABLE);
+	if (LF_ISSET(DB_DURABLE_UNKNOWN | DB_RDONLY))
+		F_SET(mfp, MP_DURABLE_UNKNOWN);
 	if (LF_ISSET(DB_DIRECT))
 		F_SET(mfp, MP_DIRECT);
 	if (LF_ISSET(DB_EXTENT))
@@ -563,9 +444,33 @@ alloc:	/* Allocate and initialize a new MPOOLFILE. */
 	if (ret != 0)
 		goto err;
 
-check_map:
+have_mfp:
+	/*
+	 * We need to verify that all handles open a file either durable or not
+	 * durable.  This needs to be cross process and cross sub-databases, so
+	 * mpool is the place to do it.
+	 */
+	if (!LF_ISSET(DB_DURABLE_UNKNOWN | DB_RDONLY)) {
+		if (F_ISSET(mfp, MP_DURABLE_UNKNOWN)) {
+			if (LF_ISSET(MP_NOT_DURABLE))
+				F_SET(mfp, MP_NOT_DURABLE);
+			F_CLR(mfp, MP_DURABLE_UNKNOWN);
+		} else if (!LF_ISSET(DB_TXN_NOT_DURABLE) !=
+		    !F_ISSET(mfp, MP_NOT_DURABLE)) {
+			__db_err(dbenv,
+	     "Cannot open DURABLE and NOT DURABLE handles in the same file");
+			ret = EINVAL;
+			goto err;
+		}
+	}
+	/*
+	 * All paths to here have initialized the mfp variable to reference
+	 * the selected (or allocated) MPOOLFILE.
+	 */
+	dbmfp->mfp = mfp;
+
 	/*
-	 * If a file:
+	 * Check to see if we can mmap the file.  If a file:
 	 *	+ isn't temporary
 	 *	+ is read-only
 	 *	+ doesn't require any pgin/pgout support
@@ -589,17 +494,22 @@ check_map:
 	if (F_ISSET(mfp, MP_CAN_MMAP)) {
 		if (path == NULL)
 			F_CLR(mfp, MP_CAN_MMAP);
-		if (!F_ISSET(dbmfp, MP_READONLY))
+		else if (!F_ISSET(dbmfp, MP_READONLY))
 			F_CLR(mfp, MP_CAN_MMAP);
-		if (dbmfp->ftype != 0)
+		else if (dbmfp->ftype != 0)
 			F_CLR(mfp, MP_CAN_MMAP);
-		if (LF_ISSET(DB_NOMMAP) || F_ISSET(dbenv, DB_ENV_NOMMAP))
-			F_CLR(mfp, MP_CAN_MMAP);
-		maxmap = dbenv->mp_mmapsize == 0 ?
-		    DB_MAXMMAPSIZE : dbenv->mp_mmapsize;
-		if (mbytes > maxmap / MEGABYTE ||
-		    (mbytes == maxmap / MEGABYTE && bytes >= maxmap % MEGABYTE))
+		else if (LF_ISSET(DB_NOMMAP) || F_ISSET(dbenv, DB_ENV_NOMMAP))
 			F_CLR(mfp, MP_CAN_MMAP);
+		else {
+			R_LOCK(dbenv, dbmp->reginfo);
+			maxmap = mp->mp_mmapsize == 0 ?
+			    DB_MAXMMAPSIZE : mp->mp_mmapsize;
+			R_UNLOCK(dbenv, dbmp->reginfo);
+			if (mbytes > maxmap / MEGABYTE ||
+			    (mbytes == maxmap / MEGABYTE &&
+			    bytes >= maxmap % MEGABYTE))
+				F_CLR(mfp, MP_CAN_MMAP);
+		}
 
 		dbmfp->addr = NULL;
 		if (F_ISSET(mfp, MP_CAN_MMAP)) {
@@ -612,29 +522,45 @@ check_map:
 		}
 	}
 
-	dbmfp->mfp = mfp;
-
 	F_SET(dbmfp, MP_OPEN_CALLED);
 
-	/* Add the file to the process' list of DB_MPOOLFILEs. */
+	/*
+	 * Share the underlying file descriptor if that's possible.
+	 *
+	 * Add the file to the process' list of DB_MPOOLFILEs.
+	 */
 	MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);
+
+	for (tmp_dbmfp = TAILQ_FIRST(&dbmp->dbmfq);
+	    tmp_dbmfp != NULL; tmp_dbmfp = TAILQ_NEXT(tmp_dbmfp, q))
+		if (dbmfp->mfp == tmp_dbmfp->mfp &&
+		    (F_ISSET(dbmfp, MP_READONLY) ||
+		    !F_ISSET(tmp_dbmfp, MP_READONLY))) {
+			if (dbmfp->fhp->mutexp != NULL)
+				__db_mutex_free(
+				    dbenv, dbmp->reginfo, dbmfp->fhp->mutexp);
+			(void)__os_closehandle(dbenv, dbmfp->fhp);
+
+			++tmp_dbmfp->fhp->ref;
+			dbmfp->fhp = tmp_dbmfp->fhp;
+			break;
+		}
+
 	TAILQ_INSERT_TAIL(&dbmp->dbmfq, dbmfp, q);
+
 	MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
 
 	if (0) {
-err:		if (F_ISSET(dbmfp->fhp, DB_FH_VALID))
-			(void)__os_closehandle(dbenv, dbmfp->fhp);
-
-		if (mfp_alloc) {
-			R_LOCK(dbenv, dbmp->reginfo);
-			if (mfp->path_off != 0)
-				__db_shalloc_free(dbmp->reginfo[0].addr,
-				    R_ADDR(dbmp->reginfo, mfp->path_off));
-			if (mfp->fileid_off != 0)
-				__db_shalloc_free(dbmp->reginfo[0].addr,
-				    R_ADDR(dbmp->reginfo, mfp->fileid_off));
-			__db_shalloc_free(dbmp->reginfo[0].addr, mfp);
-			R_UNLOCK(dbenv, dbmp->reginfo);
+err:		if (refinc) {
+			/*
+			 * If mpf_cnt goes to zero here and unlink_on_close is
+			 * set, then we missed the last close, but there was an
+			 * error trying to open the file, so we probably cannot
+			 * unlink it anyway.
+			 */
+			MUTEX_LOCK(dbenv, &mfp->mutex);
+			--mfp->mpf_cnt;
+			MUTEX_UNLOCK(dbenv, &mfp->mutex);
 		}
 
 	}
@@ -644,134 +570,47 @@ err:		if (F_ISSET(dbmfp->fhp, DB_FH_VALID))
 }
 
 /*
- * __memp_get_fileid --
- *	Return the file ID.
- *
- * XXX
- * Undocumented interface: DB private.
- */
-static void
-__memp_get_fileid(dbmfp, fidp)
-	DB_MPOOLFILE *dbmfp;
-	u_int8_t *fidp;
-{
-	/*
-	 * No lock needed -- we're using the handle, it had better not
-	 * be going away.
-	 *
-	 * !!!
-	 * Get the fileID out of the region, not out of the DB_MPOOLFILE
-	 * structure because the DB_MPOOLFILE reference is possibly short
-	 * lived, and isn't to be trusted.
-	 */
-	memcpy(fidp, R_ADDR(
-	    dbmfp->dbmp->reginfo, dbmfp->mfp->fileid_off), DB_FILE_ID_LEN);
-}
-
-/*
- * __memp_last_pgno --
- *	Return the page number of the last page in the file.
- *
- * XXX
- * Undocumented interface: DB private.
- */
-static void
-__memp_last_pgno(dbmfp, pgnoaddr)
-	DB_MPOOLFILE *dbmfp;
-	db_pgno_t *pgnoaddr;
-{
-	DB_ENV *dbenv;
-	DB_MPOOL *dbmp;
-
-	dbmp = dbmfp->dbmp;
-	dbenv = dbmp->dbenv;
-
-	R_LOCK(dbenv, dbmp->reginfo);
-	*pgnoaddr = dbmfp->mfp->last_pgno;
-	R_UNLOCK(dbenv, dbmp->reginfo);
-}
-
-/*
- * __memp_refcnt --
- *	Return the current reference count.
- *
- * XXX
- * Undocumented interface: DB private.
- */
-static void
-__memp_refcnt(dbmfp, cntp)
-	DB_MPOOLFILE *dbmfp;
-	db_pgno_t *cntp;
-{
-	DB_ENV *dbenv;
-
-	dbenv = dbmfp->dbmp->dbenv;
-
-	MUTEX_LOCK(dbenv, &dbmfp->mfp->mutex);
-	*cntp = dbmfp->mfp->mpf_cnt;
-	MUTEX_UNLOCK(dbenv, &dbmfp->mfp->mutex);
-}
-
-/*
- * __memp_set_unlink --
- *	Set unlink on last close flag.
+ * memp_fclose_pp --
+ *	DB_MPOOLFILE->close pre/post processing.
  *
- * XXX
- * Undocumented interface: DB private.
- */
-static void
-__memp_set_unlink(dbmpf, set)
-	DB_MPOOLFILE *dbmpf;
-	int set;
-{
-	DB_ENV *dbenv;
-
-	dbenv = dbmpf->dbmp->dbenv;
-
-	MUTEX_LOCK(dbenv, &dbmpf->mfp->mutex);
-	if (set)
-		F_SET(dbmpf->mfp, MP_UNLINK);
-	else
-		F_CLR(dbmpf->mfp, MP_UNLINK);
-	MUTEX_UNLOCK(dbenv, &dbmpf->mfp->mutex);
-}
-
-/*
- * memp_fclose --
- *	Close a backing file for the memory pool.
+ * PUBLIC: int __memp_fclose_pp __P((DB_MPOOLFILE *, u_int32_t));
  */
-static int
-__memp_fclose(dbmfp, flags)
+int
+__memp_fclose_pp(dbmfp, flags)
 	DB_MPOOLFILE *dbmfp;
 	u_int32_t flags;
 {
 	DB_ENV *dbenv;
-	int ret, t_ret;
+	int rep_check, ret, t_ret;
 
-	dbenv = dbmfp->dbmp->dbenv;
-
-	PANIC_CHECK(dbenv);
+	dbenv = dbmfp->dbenv;
 
 	/*
-	 * XXX
+	 * Validate arguments, but as a handle destructor, we can't fail.
+	 *
+	 * !!!
 	 * DB_MPOOL_DISCARD: Undocumented flag: DB private.
 	 */
 	ret = __db_fchk(dbenv, "DB_MPOOLFILE->close", flags, DB_MPOOL_DISCARD);
 
-	if ((t_ret = __memp_fclose_int(dbmfp, flags)) != 0 && ret == 0)
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	if ((t_ret = __memp_fclose(dbmfp, flags)) != 0 && ret == 0)
 		ret = t_ret;
-
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
 	return (ret);
 }
 
 /*
- * __memp_fclose_int --
- *	Internal version of __memp_fclose.
+ * __memp_fclose --
+ *	DB_MPOOLFILE->close.
  *
- * PUBLIC: int __memp_fclose_int __P((DB_MPOOLFILE *, u_int32_t));
+ * PUBLIC: int __memp_fclose __P((DB_MPOOLFILE *, u_int32_t));
  */
 int
-__memp_fclose_int(dbmfp, flags)
+__memp_fclose(dbmfp, flags)
 	DB_MPOOLFILE *dbmfp;
 	u_int32_t flags;
 {
@@ -779,53 +618,40 @@ __memp_fclose_int(dbmfp, flags)
 	DB_MPOOL *dbmp;
 	MPOOLFILE *mfp;
 	char *rpath;
+	u_int32_t ref;
 	int deleted, ret, t_ret;
 
-	dbmp = dbmfp->dbmp;
-	dbenv = dbmp->dbenv;
+	dbenv = dbmfp->dbenv;
+	dbmp = dbenv->mp_handle;
 	ret = 0;
 
 	/*
-	 * We have to reference count DB_MPOOLFILE structures as other threads
-	 * in the process may be using them.  Here's the problem:
-	 *
-	 * Thread A opens a database.
-	 * Thread B uses thread A's DB_MPOOLFILE to write a buffer
-	 *    in order to free up memory in the mpool cache.
-	 * Thread A closes the database while thread B is using the
-	 *    DB_MPOOLFILE structure.
-	 *
-	 * By opening all databases before creating any threads, and closing
-	 * the databases after all the threads have exited, applications get
-	 * better performance and avoid the problem path entirely.
+	 * Remove the DB_MPOOLFILE from the process' list.
 	 *
-	 * Regardless, holding the DB_MPOOLFILE to flush a dirty buffer is a
-	 * short-term lock, even in worst case, since we better be the only
-	 * thread of control using the DB_MPOOLFILE structure to read pages
-	 * *into* the cache.  Wait until we're the only reference holder and
-	 * remove the DB_MPOOLFILE structure from the list, so nobody else can
-	 * find it.  We do this, rather than have the last reference holder
-	 * (whoever that might be) discard the DB_MPOOLFILE structure, because
-	 * we'd rather write error messages to the application in the close
-	 * routine, not in the checkpoint/sync routine.
+	 * It's possible the underlying mpool cache may never have been created.
+	 * In that case, all we have is a structure, discard it.
 	 *
-	 * !!!
 	 * It's possible the DB_MPOOLFILE was never added to the DB_MPOOLFILE
-	 * file list, check the DB_OPEN_CALLED flag to be sure.
+	 * file list, check the MP_OPEN_CALLED flag to be sure.
 	 */
-	for (deleted = 0;;) {
-		MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);
-		if (dbmfp->ref == 1) {
-			if (F_ISSET(dbmfp, MP_OPEN_CALLED))
-				TAILQ_REMOVE(&dbmp->dbmfq, dbmfp, q);
-			deleted = 1;
-		}
-		MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
+	if (dbmp == NULL)
+		goto done;
 
-		if (deleted)
-			break;
-		__os_sleep(dbenv, 1, 0);
-	}
+	MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);
+
+	DB_ASSERT(dbmfp->ref >= 1);
+	if ((ref = --dbmfp->ref) == 0 && F_ISSET(dbmfp, MP_OPEN_CALLED))
+		TAILQ_REMOVE(&dbmp->dbmfq, dbmfp, q);
+
+	/*
+	 * Decrement the file descriptor's ref count -- if we're the last ref,
+	 * we'll discard the file descriptor.
+	 */
+	if (ref == 0 && dbmfp->fhp != NULL && --dbmfp->fhp->ref > 0)
+		dbmfp->fhp = NULL;
+	MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
+	if (ref != 0)
+		return (0);
 
 	/* Complain if pinned blocks never returned. */
 	if (dbmfp->pinref != 0) {
@@ -839,25 +665,35 @@ __memp_fclose_int(dbmfp, flags)
 	    (ret = __os_unmapfile(dbenv, dbmfp->addr, dbmfp->len)) != 0)
 		__db_err(dbenv, "%s: %s", __memp_fn(dbmfp), db_strerror(ret));
 
-	/* Close the file; temporary files may not yet have been created. */
-	if (F_ISSET(dbmfp->fhp, DB_FH_VALID) &&
-	    (t_ret = __os_closehandle(dbenv, dbmfp->fhp)) != 0) {
-		__db_err(dbenv, "%s: %s", __memp_fn(dbmfp), db_strerror(t_ret));
-		if (ret == 0)
-			ret = t_ret;
+	/*
+	 * Close the file and discard the descriptor structure; temporary
+	 * files may not yet have been created.
+	 */
+	if (dbmfp->fhp != NULL) {
+		if (dbmfp->fhp->mutexp != NULL) {
+			__db_mutex_free(
+			    dbenv, dbmp->reginfo, dbmfp->fhp->mutexp);
+			dbmfp->fhp->mutexp = NULL;
+		}
+		if ((t_ret = __os_closehandle(dbenv, dbmfp->fhp)) != 0) {
+			__db_err(dbenv, "%s: %s",
+			    __memp_fn(dbmfp), db_strerror(t_ret));
+			if (ret == 0)
+				ret = t_ret;
+		}
+		dbmfp->fhp = NULL;
 	}
 
-	/* Discard the thread mutex. */
-	if (dbmfp->mutexp != NULL)
-		__db_mutex_free(dbenv, dbmp->reginfo, dbmfp->mutexp);
-
 	/*
-	 * Discard our reference on the the underlying MPOOLFILE, and close
-	 * it if it's no longer useful to anyone.  It possible the open of
-	 * the file never happened or wasn't successful, in which case, mpf
-	 * will be NULL;
+	 * Discard our reference on the underlying MPOOLFILE, and close it
+	 * if it's no longer useful to anyone.  It possible the open of the
+	 * file never happened or wasn't successful, in which case, mpf will
+	 * be NULL and MP_OPEN_CALLED will not be set.
 	 */
-	if ((mfp = dbmfp->mfp) == NULL)
+	mfp = dbmfp->mfp;
+	DB_ASSERT((F_ISSET(dbmfp, MP_OPEN_CALLED) && mfp != NULL) ||
+	    (!F_ISSET(dbmfp, MP_OPEN_CALLED) && mfp == NULL));
+	if (!F_ISSET(dbmfp, MP_OPEN_CALLED))
 		goto done;
 
 	/*
@@ -871,16 +707,16 @@ __memp_fclose_int(dbmfp, flags)
 	MUTEX_LOCK(dbenv, &mfp->mutex);
 	if (--mfp->mpf_cnt == 0 || LF_ISSET(DB_MPOOL_DISCARD)) {
 		if (LF_ISSET(DB_MPOOL_DISCARD) ||
-		    F_ISSET(mfp, MP_TEMP | MP_UNLINK))
-			MPOOLFILE_IGNORE(mfp);
-		if (F_ISSET(mfp, MP_UNLINK)) {
+		    F_ISSET(mfp, MP_TEMP) || mfp->unlink_on_close)
+			mfp->deadfile = 1;
+		if (mfp->unlink_on_close) {
 			if ((t_ret = __db_appname(dbmp->dbenv,
 			    DB_APP_DATA, R_ADDR(dbmp->reginfo,
 			    mfp->path_off), 0, NULL, &rpath)) != 0 && ret == 0)
 				ret = t_ret;
 			if (t_ret == 0) {
 				if ((t_ret = __os_unlink(
-				    dbmp->dbenv, rpath) != 0) && ret == 0)
+				    dbmp->dbenv, rpath)) != 0 && ret == 0)
 					ret = t_ret;
 				__os_free(dbenv, rpath);
 			}
@@ -895,8 +731,11 @@ __memp_fclose_int(dbmfp, flags)
 	if (deleted == 0)
 		MUTEX_UNLOCK(dbenv, &mfp->mutex);
 
-	/* Discard the DB_MPOOLFILE structure. */
-done:	__os_free(dbenv, dbmfp->fhp);
+done:	/* Discard the DB_MPOOLFILE structure. */
+	if (dbmfp->pgcookie != NULL) {
+		__os_free(dbenv, dbmfp->pgcookie->data);
+		__os_free(dbenv, dbmfp->pgcookie);
+	}
 	__os_free(dbenv, dbmfp);
 
 	return (ret);
@@ -914,15 +753,12 @@ __memp_mf_discard(dbmp, mfp)
 	MPOOLFILE *mfp;
 {
 	DB_ENV *dbenv;
-	DB_FH fh;
 	DB_MPOOL_STAT *sp;
 	MPOOL *mp;
-	char *rpath;
-	int ret;
+	int need_sync, ret;
 
 	dbenv = dbmp->dbenv;
 	mp = dbmp->reginfo[0].primary;
-	ret = 0;
 
 	/*
 	 * Expects caller to be holding the MPOOLFILE mutex.
@@ -931,31 +767,27 @@ __memp_mf_discard(dbmp, mfp)
 	 * The scenario is that dirty buffers from this file need to be
 	 * flushed to satisfy a future checkpoint, but when the checkpoint
 	 * calls mpool sync, the sync code won't know anything about them.
+	 * Ignore files not written, discarded, or only temporary.
 	 */
-	if (!F_ISSET(mfp, MP_DEADFILE) &&
-	    (ret = __db_appname(dbenv, DB_APP_DATA,
-	    R_ADDR(dbmp->reginfo, mfp->path_off), 0, NULL, &rpath)) == 0) {
-		if ((ret = __os_open(dbenv, rpath, 0, 0, &fh)) == 0) {
-			ret = __os_fsync(dbenv, &fh);
-			(void)__os_closehandle(dbenv, &fh);
-		}
-		__os_free(dbenv, rpath);
-	}
+	need_sync =
+	   mfp->file_written && !mfp->deadfile && !F_ISSET(mfp, MP_TEMP);
 
 	/*
-	 * We have to release the MPOOLFILE lock before acquiring the region
-	 * lock so that we don't deadlock.  Make sure nobody ever looks at
-	 * this structure again.
+	 * We have to release the MPOOLFILE mutex before acquiring the region
+	 * mutex so we don't deadlock.  Make sure nobody ever looks at this
+	 * structure again.
 	 */
-	MPOOLFILE_IGNORE(mfp);
+	mfp->deadfile = 1;
 
 	/* Discard the mutex we're holding. */
 	MUTEX_UNLOCK(dbenv, &mfp->mutex);
 
-	/* Delete from the list of MPOOLFILEs. */
+	/* Lock the region and delete from the list of MPOOLFILEs. */
 	R_LOCK(dbenv, dbmp->reginfo);
 	SH_TAILQ_REMOVE(&mp->mpfq, mfp, q, __mpoolfile);
 
+	ret = need_sync ? __memp_mf_sync(dbmp, mfp) : 0;
+
 	/* Copy the statistics into the region. */
 	sp = &mp->stat;
 	sp->st_cache_hit += mfp->stat.st_cache_hit;
@@ -967,52 +799,21 @@ __memp_mf_discard(dbmp, mfp)
 
 	/* Clear the mutex this MPOOLFILE recorded. */
 	__db_shlocks_clear(&mfp->mutex, dbmp->reginfo,
-	    (REGMAINT *)R_ADDR(dbmp->reginfo, mp->maint_off));
+	    R_ADDR(dbmp->reginfo, mp->maint_off));
 
 	/* Free the space. */
 	if (mfp->path_off != 0)
-		__db_shalloc_free(dbmp->reginfo[0].addr,
+		__db_shalloc_free(&dbmp->reginfo[0],
 		    R_ADDR(dbmp->reginfo, mfp->path_off));
 	if (mfp->fileid_off != 0)
-		__db_shalloc_free(dbmp->reginfo[0].addr,
+		__db_shalloc_free(&dbmp->reginfo[0],
 		    R_ADDR(dbmp->reginfo, mfp->fileid_off));
 	if (mfp->pgcookie_off != 0)
-		__db_shalloc_free(dbmp->reginfo[0].addr,
+		__db_shalloc_free(&dbmp->reginfo[0],
 		    R_ADDR(dbmp->reginfo, mfp->pgcookie_off));
-	__db_shalloc_free(dbmp->reginfo[0].addr, mfp);
+	__db_shalloc_free(&dbmp->reginfo[0], mfp);
 
 	R_UNLOCK(dbenv, dbmp->reginfo);
 
 	return (ret);
 }
-
-/*
- * __memp_fn --
- *	On errors we print whatever is available as the file name.
- *
- * PUBLIC: char * __memp_fn __P((DB_MPOOLFILE *));
- */
-char *
-__memp_fn(dbmfp)
-	DB_MPOOLFILE *dbmfp;
-{
-	return (__memp_fns(dbmfp->dbmp, dbmfp->mfp));
-}
-
-/*
- * __memp_fns --
- *	On errors we print whatever is available as the file name.
- *
- * PUBLIC: char * __memp_fns __P((DB_MPOOL *, MPOOLFILE *));
- *
- */
-char *
-__memp_fns(dbmp, mfp)
-	DB_MPOOL *dbmp;
-	MPOOLFILE *mfp;
-{
-	if (mfp->path_off == 0)
-		return ((char *)"temporary");
-
-	return ((char *)R_ADDR(dbmp->reginfo, mfp->path_off));
-}
diff --git a/storage/bdb/mp/mp_fput.c b/storage/bdb/mp/mp_fput.c
index 271e44a4ef87e65cae100bd6ee216e1d3f0ade93..a21eb6733f4c04f925c659711f2ac62a8e2b2eda 100644
--- a/storage/bdb/mp/mp_fput.c
+++ b/storage/bdb/mp/mp_fput.c
@@ -1,14 +1,13 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: mp_fput.c,v 11.59 2004/10/15 16:59:43 bostic Exp $
  */
-#include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: mp_fput.c,v 11.36 2002/08/09 19:04:11 bostic Exp $";
-#endif /* not lint */
+#include "db_config.h"
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
@@ -17,11 +16,38 @@ static const char revid[] = "$Id: mp_fput.c,v 11.36 2002/08/09 19:04:11 bostic E
 
 #include "db_int.h"
 #include "dbinc/db_shash.h"
+#include "dbinc/log.h"
 #include "dbinc/mp.h"
 
+static void __memp_reset_lru __P((DB_ENV *, REGINFO *));
+
+/*
+ * __memp_fput_pp --
+ *	DB_MPOOLFILE->put pre/post processing.
+ *
+ * PUBLIC: int __memp_fput_pp __P((DB_MPOOLFILE *, void *, u_int32_t));
+ */
+int
+__memp_fput_pp(dbmfp, pgaddr, flags)
+	DB_MPOOLFILE *dbmfp;
+	void *pgaddr;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	int ret;
+
+	dbenv = dbmfp->dbenv;
+	PANIC_CHECK(dbenv);
+
+	ret = __memp_fput(dbmfp, pgaddr, flags);
+	if (IS_ENV_REPLICATED(dbenv))
+		__op_rep_exit(dbenv);
+	return (ret);
+}
+
 /*
  * __memp_fput --
- *	Mpool file put function.
+ *	DB_MPOOLFILE->put.
  *
  * PUBLIC: int __memp_fput __P((DB_MPOOLFILE *, void *, u_int32_t));
  */
@@ -31,19 +57,19 @@ __memp_fput(dbmfp, pgaddr, flags)
 	void *pgaddr;
 	u_int32_t flags;
 {
-	BH *argbhp, *bhp, *prev;
+	BH *fbhp, *bhp, *prev;
 	DB_ENV *dbenv;
 	DB_MPOOL *dbmp;
 	DB_MPOOL_HASH *hp;
 	MPOOL *c_mp;
+	MPOOLFILE *mfp;
 	u_int32_t n_cache;
 	int adjust, ret;
 
-	dbmp = dbmfp->dbmp;
-	dbenv = dbmp->dbenv;
-
-	PANIC_CHECK(dbenv);
+	dbenv = dbmfp->dbenv;
+	MPF_ILLEGAL_BEFORE_OPEN(dbmfp, "DB_MPOOLFILE->put");
 
+	dbmp = dbenv->mp_handle;
 	/* Validate arguments. */
 	if (flags) {
 		if ((ret = __db_fchk(dbenv, "memp_fput", flags,
@@ -72,15 +98,16 @@ __memp_fput(dbmfp, pgaddr, flags)
 		return (0);
 
 #ifdef DIAGNOSTIC
+	{
 	/*
 	 * Decrement the per-file pinned buffer count (mapped pages aren't
 	 * counted).
 	 */
 	R_LOCK(dbenv, dbmp->reginfo);
 	if (dbmfp->pinref == 0) {
-		ret = EINVAL;
 		__db_err(dbenv,
 		    "%s: more pages returned than retrieved", __memp_fn(dbmfp));
+		ret = __db_panic(dbenv, EINVAL);
 	} else {
 		ret = 0;
 		--dbmfp->pinref;
@@ -88,6 +115,7 @@ __memp_fput(dbmfp, pgaddr, flags)
 	R_UNLOCK(dbenv, dbmp->reginfo);
 	if (ret != 0)
 		return (ret);
+	}
 #endif
 
 	/* Convert a page address to a buffer header and hash bucket. */
@@ -118,12 +146,24 @@ __memp_fput(dbmfp, pgaddr, flags)
 	 * application returns a page twice.
 	 */
 	if (bhp->ref == 0) {
+		MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
 		__db_err(dbenv, "%s: page %lu: unpinned page returned",
 		    __memp_fn(dbmfp), (u_long)bhp->pgno);
-		MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
-		return (EINVAL);
+		return (__db_panic(dbenv, EINVAL));
 	}
 
+	/* Note the activity so allocation won't decide to quit. */
+	++c_mp->put_counter;
+
+	/*
+	 * Mark the file dirty.  Check for a dirty bit on the buffer as well
+	 * as the dirty flag because the buffer might have been marked dirty
+	 * in the DB_MPOOLFILE->set method.
+	 */
+	mfp = dbmfp->mfp;
+	if (LF_ISSET(DB_MPOOL_DIRTY) || F_ISSET(bhp, BH_DIRTY))
+		mfp->file_written = 1;
+
 	/*
 	 * If more than one reference to the page or a reference other than a
 	 * thread waiting to flush the buffer to disk, we're done.  Ignore the
@@ -135,8 +175,7 @@ __memp_fput(dbmfp, pgaddr, flags)
 	}
 
 	/* Update priority values. */
-	if (F_ISSET(bhp, BH_DISCARD) ||
-	    dbmfp->mfp->priority == MPOOL_PRI_VERY_LOW)
+	if (F_ISSET(bhp, BH_DISCARD) || mfp->priority == MPOOL_PRI_VERY_LOW)
 		bhp->priority = 0;
 	else {
 		/*
@@ -147,14 +186,14 @@ __memp_fput(dbmfp, pgaddr, flags)
 		bhp->priority = c_mp->lru_count;
 
 		adjust = 0;
-		if (dbmfp->mfp->priority != 0)
+		if (mfp->priority != 0)
 			adjust =
-			    (int)c_mp->stat.st_pages / dbmfp->mfp->priority;
+			    (int)c_mp->stat.st_pages / mfp->priority;
 		if (F_ISSET(bhp, BH_DIRTY))
 			adjust += c_mp->stat.st_pages / MPOOL_PRI_DIRTY;
 
 		if (adjust > 0) {
-			if (UINT32_T_MAX - bhp->priority <= (u_int32_t)adjust)
+			if (UINT32_MAX - bhp->priority >= (u_int32_t)adjust)
 				bhp->priority += adjust;
 		} else if (adjust < 0)
 			if (bhp->priority > (u_int32_t)-adjust)
@@ -165,19 +204,25 @@ __memp_fput(dbmfp, pgaddr, flags)
 	 * Buffers on hash buckets are sorted by priority -- move the buffer
 	 * to the correct position in the list.
 	 */
-	argbhp = bhp;
-	SH_TAILQ_REMOVE(&hp->hash_bucket, argbhp, hq, __bh);
+	if ((fbhp =
+	     SH_TAILQ_FIRST(&hp->hash_bucket, __bh)) ==
+	     SH_TAILQ_LAST(&hp->hash_bucket, hq, __bh))
+		goto done;
+
+	if (fbhp == bhp)
+		fbhp = SH_TAILQ_NEXT(fbhp, hq, __bh);
+	SH_TAILQ_REMOVE(&hp->hash_bucket, bhp, hq, __bh);
 
-	prev = NULL;
-	for (bhp = SH_TAILQ_FIRST(&hp->hash_bucket, __bh);
-	    bhp != NULL; prev = bhp, bhp = SH_TAILQ_NEXT(bhp, hq, __bh))
-		if (bhp->priority > argbhp->priority)
+	for (prev = NULL; fbhp != NULL;
+	    prev = fbhp, fbhp = SH_TAILQ_NEXT(fbhp, hq, __bh))
+		if (fbhp->priority > bhp->priority)
 			break;
 	if (prev == NULL)
-		SH_TAILQ_INSERT_HEAD(&hp->hash_bucket, argbhp, hq, __bh);
+		SH_TAILQ_INSERT_HEAD(&hp->hash_bucket, bhp, hq, __bh);
 	else
-		SH_TAILQ_INSERT_AFTER(&hp->hash_bucket, prev, argbhp, hq, __bh);
+		SH_TAILQ_INSERT_AFTER(&hp->hash_bucket, prev, bhp, hq, __bh);
 
+done:
 	/* Reset the hash bucket's priority. */
 	hp->hash_priority = SH_TAILQ_FIRST(&hp->hash_bucket, __bh)->priority;
 
@@ -193,10 +238,61 @@ __memp_fput(dbmfp, pgaddr, flags)
 	 * code has finished, so we're safe as long as we don't let the value
 	 * go to 0 before we finish with the buffer.
 	 */
-	if (F_ISSET(argbhp, BH_LOCKED) && argbhp->ref_sync != 0)
-		--argbhp->ref_sync;
+	if (F_ISSET(bhp, BH_LOCKED) && bhp->ref_sync != 0)
+		--bhp->ref_sync;
 
 	MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
 
+	/*
+	 * On every buffer put we update the buffer generation number and check
+	 * for wraparound.
+	 */
+	if (++c_mp->lru_count == UINT32_MAX)
+		__memp_reset_lru(dbenv, dbmp->reginfo);
+
 	return (0);
 }
+
+/*
+ * __memp_reset_lru --
+ *	Reset the cache LRU counter.
+ */
+static void
+__memp_reset_lru(dbenv, infop)
+	DB_ENV *dbenv;
+	REGINFO *infop;
+{
+	BH *bhp;
+	DB_MPOOL_HASH *hp;
+	MPOOL *c_mp;
+	u_int32_t bucket;
+
+	c_mp = infop->primary;
+
+	/*
+	 * Update the counter so all future allocations will start at the
+	 * bottom.
+	 */
+	c_mp->lru_count -= MPOOL_BASE_DECREMENT;
+
+	/* Adjust the priority of every buffer in the system. */
+	for (hp = R_ADDR(infop, c_mp->htab),
+	    bucket = 0; bucket < c_mp->htab_buckets; ++hp, ++bucket) {
+		/*
+		 * Skip empty buckets.
+		 *
+		 * We can check for empty buckets before locking as we
+		 * only care if the pointer is zero or non-zero.
+		 */
+		if (SH_TAILQ_FIRST(&hp->hash_bucket, __bh) == NULL)
+			continue;
+
+		MUTEX_LOCK(dbenv, &hp->hash_mutex);
+		for (bhp = SH_TAILQ_FIRST(&hp->hash_bucket, __bh);
+		    bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, hq, __bh))
+			if (bhp->priority != UINT32_MAX &&
+			    bhp->priority > MPOOL_BASE_DECREMENT)
+				bhp->priority -= MPOOL_BASE_DECREMENT;
+		MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
+	}
+}
diff --git a/storage/bdb/mp/mp_fset.c b/storage/bdb/mp/mp_fset.c
index 65cd6286ac944fafbe9fd6f1b7e4b99175be8c12..0d29c41dfe96298f54aaff2de7a8d94b7824caef 100644
--- a/storage/bdb/mp/mp_fset.c
+++ b/storage/bdb/mp/mp_fset.c
@@ -1,14 +1,13 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: mp_fset.c,v 11.34 2004/10/15 16:59:43 bostic Exp $
  */
-#include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: mp_fset.c,v 11.25 2002/05/03 15:21:17 bostic Exp $";
-#endif /* not lint */
+#include "db_config.h"
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
@@ -17,32 +16,28 @@ static const char revid[] = "$Id: mp_fset.c,v 11.25 2002/05/03 15:21:17 bostic E
 
 #include "db_int.h"
 #include "dbinc/db_shash.h"
+#include "dbinc/log.h"
 #include "dbinc/mp.h"
 
 /*
- * __memp_fset --
- *	Mpool page set-flag routine.
+ * __memp_fset_pp --
+ *	DB_MPOOLFILE->set pre/post processing.
  *
- * PUBLIC: int __memp_fset __P((DB_MPOOLFILE *, void *, u_int32_t));
+ * PUBLIC: int __memp_fset_pp __P((DB_MPOOLFILE *, void *, u_int32_t));
  */
 int
-__memp_fset(dbmfp, pgaddr, flags)
+__memp_fset_pp(dbmfp, pgaddr, flags)
 	DB_MPOOLFILE *dbmfp;
 	void *pgaddr;
 	u_int32_t flags;
 {
-	BH *bhp;
 	DB_ENV *dbenv;
-	DB_MPOOL *dbmp;
-	DB_MPOOL_HASH *hp;
-	MPOOL *c_mp;
-	u_int32_t n_cache;
-	int ret;
+	int rep_check, ret;
 
-	dbmp = dbmfp->dbmp;
-	dbenv = dbmp->dbenv;
+	dbenv = dbmfp->dbenv;
 
 	PANIC_CHECK(dbenv);
+	MPF_ILLEGAL_BEFORE_OPEN(dbmfp, "DB_MPOOLFILE->set");
 
 	/* Validate arguments. */
 	if (flags == 0)
@@ -61,6 +56,37 @@ __memp_fset(dbmfp, pgaddr, flags)
 		return (EACCES);
 	}
 
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __memp_fset(dbmfp, pgaddr, flags);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
+/*
+ * __memp_fset --
+ *	DB_MPOOLFILE->set.
+ *
+ * PUBLIC: int __memp_fset __P((DB_MPOOLFILE *, void *, u_int32_t));
+ */
+int
+__memp_fset(dbmfp, pgaddr, flags)
+	DB_MPOOLFILE *dbmfp;
+	void *pgaddr;
+	u_int32_t flags;
+{
+	BH *bhp;
+	DB_ENV *dbenv;
+	DB_MPOOL *dbmp;
+	DB_MPOOL_HASH *hp;
+	MPOOL *c_mp;
+	u_int32_t n_cache;
+
+	dbenv = dbmfp->dbenv;
+	dbmp = dbenv->mp_handle;
+
 	/* Convert the page address to a buffer header and hash bucket. */
 	bhp = (BH *)((u_int8_t *)pgaddr - SSZA(BH, buf));
 	n_cache = NCACHE(dbmp->reginfo[0].primary, bhp->mf_offset, bhp->pgno);
diff --git a/storage/bdb/mp/mp_method.c b/storage/bdb/mp/mp_method.c
index 38f0a645f16124d48051a94895bd8410d489846b..b149bfc13da88f6c852772fb4af065e5ccfd1d89 100644
--- a/storage/bdb/mp/mp_method.c
+++ b/storage/bdb/mp/mp_method.c
@@ -1,14 +1,13 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: mp_method.c,v 11.58 2004/10/15 16:59:43 bostic Exp $
  */
-#include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: mp_method.c,v 11.29 2002/03/27 04:32:27 bostic Exp $";
-#endif /* not lint */
+#include "db_config.h"
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
@@ -16,6 +15,12 @@ static const char revid[] = "$Id: mp_method.c,v 11.29 2002/03/27 04:32:27 bostic
 #ifdef HAVE_RPC
 #include <rpc/rpc.h>
 #endif
+
+#include <string.h>
+#endif
+
+#ifdef HAVE_RPC
+#include "db_server.h"
 #endif
 
 #include "db_int.h"
@@ -23,12 +28,12 @@ static const char revid[] = "$Id: mp_method.c,v 11.29 2002/03/27 04:32:27 bostic
 #include "dbinc/mp.h"
 
 #ifdef HAVE_RPC
-#include "dbinc_auto/db_server.h"
 #include "dbinc_auto/rpc_client_ext.h"
 #endif
 
-static int __memp_set_cachesize __P((DB_ENV *, u_int32_t, u_int32_t, int));
-static int __memp_set_mp_mmapsize __P((DB_ENV *, size_t));
+static int __memp_get_mp_max_openfd __P((DB_ENV *, int *));
+static int __memp_get_mp_max_write __P((DB_ENV *, int *, int *));
+static int __memp_get_mp_mmapsize __P((DB_ENV *, size_t *));
 
 /*
  * __memp_dbenv_create --
@@ -59,45 +64,95 @@ __memp_dbenv_create(dbenv)
 
 #ifdef HAVE_RPC
 	if (F_ISSET(dbenv, DB_ENV_RPCCLIENT)) {
+		dbenv->get_cachesize = __dbcl_env_get_cachesize;
 		dbenv->set_cachesize = __dbcl_env_cachesize;
+		dbenv->get_mp_max_openfd = __dbcl_get_mp_max_openfd;
+		dbenv->set_mp_max_openfd = __dbcl_set_mp_max_openfd;
+		dbenv->get_mp_max_write = __dbcl_get_mp_max_write;
+		dbenv->set_mp_max_write = __dbcl_set_mp_max_write;
+		dbenv->get_mp_mmapsize = __dbcl_get_mp_mmapsize;
 		dbenv->set_mp_mmapsize = __dbcl_set_mp_mmapsize;
-		dbenv->memp_dump_region = NULL;
-		dbenv->memp_fcreate = __dbcl_memp_fcreate;
-		dbenv->memp_nameop = NULL;
 		dbenv->memp_register = __dbcl_memp_register;
 		dbenv->memp_stat = __dbcl_memp_stat;
+		dbenv->memp_stat_print = NULL;
 		dbenv->memp_sync = __dbcl_memp_sync;
 		dbenv->memp_trickle = __dbcl_memp_trickle;
 	} else
 #endif
 	{
+		dbenv->get_cachesize = __memp_get_cachesize;
 		dbenv->set_cachesize = __memp_set_cachesize;
+		dbenv->get_mp_max_openfd = __memp_get_mp_max_openfd;
+		dbenv->set_mp_max_openfd = __memp_set_mp_max_openfd;
+		dbenv->get_mp_max_write = __memp_get_mp_max_write;
+		dbenv->set_mp_max_write = __memp_set_mp_max_write;
+		dbenv->get_mp_mmapsize = __memp_get_mp_mmapsize;
 		dbenv->set_mp_mmapsize = __memp_set_mp_mmapsize;
-		dbenv->memp_dump_region = __memp_dump_region;
-		dbenv->memp_fcreate = __memp_fcreate;
-		dbenv->memp_nameop = __memp_nameop;
-		dbenv->memp_register = __memp_register;
-		dbenv->memp_stat = __memp_stat;
-		dbenv->memp_sync = __memp_sync;
-		dbenv->memp_trickle = __memp_trickle;
+		dbenv->memp_register = __memp_register_pp;
+		dbenv->memp_stat = __memp_stat_pp;
+		dbenv->memp_stat_print = __memp_stat_print_pp;
+		dbenv->memp_sync = __memp_sync_pp;
+		dbenv->memp_trickle = __memp_trickle_pp;
+	}
+	dbenv->memp_fcreate = __memp_fcreate_pp;
+}
+
+/*
+ * __memp_get_cachesize --
+ *	{DB_ENV,DB}->get_cachesize.
+ *
+ * PUBLIC: int __memp_get_cachesize
+ * PUBLIC:         __P((DB_ENV *, u_int32_t *, u_int32_t *, int *));
+ */
+int
+__memp_get_cachesize(dbenv, gbytesp, bytesp, ncachep)
+	DB_ENV *dbenv;
+	u_int32_t *gbytesp, *bytesp;
+	int *ncachep;
+{
+	MPOOL *mp;
+
+	ENV_NOT_CONFIGURED(dbenv,
+	    dbenv->mp_handle, "DB_ENV->get_cachesize", DB_INIT_MPOOL);
+
+	if (MPOOL_ON(dbenv)) {
+		/* Cannot be set after open, no lock required to read. */
+		mp = ((DB_MPOOL *)dbenv->mp_handle)->reginfo[0].primary;
+		if (gbytesp != NULL)
+			*gbytesp = mp->stat.st_gbytes;
+		if (bytesp != NULL)
+			*bytesp = mp->stat.st_bytes;
+		if (ncachep != NULL)
+			*ncachep = (int)mp->nreg;
+	} else {
+		if (gbytesp != NULL)
+			*gbytesp = dbenv->mp_gbytes;
+		if (bytesp != NULL)
+			*bytesp = dbenv->mp_bytes;
+		if (ncachep != NULL)
+			*ncachep = (int)dbenv->mp_ncache;
 	}
+	return (0);
 }
 
 /*
  * __memp_set_cachesize --
- *	Initialize the cache size.
+ *	{DB_ENV,DB}->set_cachesize.
+ *
+ * PUBLIC: int __memp_set_cachesize __P((DB_ENV *, u_int32_t, u_int32_t, int));
  */
-static int
-__memp_set_cachesize(dbenv, gbytes, bytes, ncache)
+int
+__memp_set_cachesize(dbenv, gbytes, bytes, arg_ncache)
 	DB_ENV *dbenv;
 	u_int32_t gbytes, bytes;
-	int ncache;
+	int arg_ncache;
 {
-	ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_cachesize");
+	u_int ncache;
 
-	/* Normalize the values. */
-	if (ncache == 0)
-		ncache = 1;
+	ENV_ILLEGAL_AFTER_OPEN(dbenv, "DB_ENV->set_cachesize");
+
+	/* Normalize the cache count. */
+	ncache = arg_ncache <= 0 ? 1 : (u_int)arg_ncache;
 
 	/*
 	 * You can only store 4GB-1 in an unsigned 32-bit value, so correct for
@@ -142,15 +197,374 @@ __memp_set_cachesize(dbenv, gbytes, bytes, ncache)
 	return (0);
 }
 
+static int
+__memp_get_mp_max_openfd(dbenv, maxopenfdp)
+	DB_ENV *dbenv;
+	int *maxopenfdp;
+{
+	DB_MPOOL *dbmp;
+	MPOOL *mp;
+
+	ENV_NOT_CONFIGURED(dbenv,
+	    dbenv->mp_handle, "DB_ENV->get_mp_max_openfd", DB_INIT_MPOOL);
+
+	if (MPOOL_ON(dbenv)) {
+		dbmp = dbenv->mp_handle;
+		mp = dbmp->reginfo[0].primary;
+		R_LOCK(dbenv, dbmp->reginfo);
+		*maxopenfdp = mp->mp_maxopenfd;
+		R_UNLOCK(dbenv, dbmp->reginfo);
+	} else
+		*maxopenfdp = dbenv->mp_maxopenfd;
+	return (0);
+}
+
 /*
- * __memp_set_mp_mmapsize --
- *	Set the maximum mapped file size.
+ * __memp_set_mp_max_openfd --
+ *	Set the maximum number of open fd's when flushing the cache.
+ * PUBLIC: int __memp_set_mp_max_openfd __P((DB_ENV *, int));
+ */
+int
+__memp_set_mp_max_openfd(dbenv, maxopenfd)
+	DB_ENV *dbenv;
+	int maxopenfd;
+{
+	DB_MPOOL *dbmp;
+	MPOOL *mp;
+
+	ENV_NOT_CONFIGURED(dbenv,
+	    dbenv->mp_handle, "DB_ENV->set_mp_max_openfd", DB_INIT_MPOOL);
+
+	if (MPOOL_ON(dbenv)) {
+		dbmp = dbenv->mp_handle;
+		mp = dbmp->reginfo[0].primary;
+		R_LOCK(dbenv, dbmp->reginfo);
+		mp->mp_maxopenfd = maxopenfd;
+		R_UNLOCK(dbenv, dbmp->reginfo);
+	} else
+		dbenv->mp_maxopenfd = maxopenfd;
+	return (0);
+}
+
+static int
+__memp_get_mp_max_write(dbenv, maxwritep, maxwrite_sleepp)
+	DB_ENV *dbenv;
+	int *maxwritep, *maxwrite_sleepp;
+{
+	DB_MPOOL *dbmp;
+	MPOOL *mp;
+
+	ENV_NOT_CONFIGURED(dbenv,
+	    dbenv->mp_handle, "DB_ENV->get_mp_max_openfd", DB_INIT_MPOOL);
+
+	if (MPOOL_ON(dbenv)) {
+		dbmp = dbenv->mp_handle;
+		mp = dbmp->reginfo[0].primary;
+		R_LOCK(dbenv, dbmp->reginfo);
+		*maxwritep = mp->mp_maxwrite;
+		*maxwrite_sleepp = mp->mp_maxwrite_sleep;
+		R_UNLOCK(dbenv, dbmp->reginfo);
+	} else {
+		*maxwritep = dbenv->mp_maxwrite;
+		*maxwrite_sleepp = dbenv->mp_maxwrite_sleep;
+	}
+	return (0);
+}
+
+/*
+ * __memp_set_mp_max_write --
+ *	Set the maximum continuous I/O count.
+ *
+ * PUBLIC: int __memp_set_mp_max_write __P((DB_ENV *, int, int));
  */
+int
+__memp_set_mp_max_write(dbenv, maxwrite, maxwrite_sleep)
+	DB_ENV *dbenv;
+	int maxwrite, maxwrite_sleep;
+{
+	DB_MPOOL *dbmp;
+	MPOOL *mp;
+
+	ENV_NOT_CONFIGURED(dbenv,
+	    dbenv->mp_handle, "DB_ENV->get_mp_max_openfd", DB_INIT_MPOOL);
+
+	if (MPOOL_ON(dbenv)) {
+		dbmp = dbenv->mp_handle;
+		mp = dbmp->reginfo[0].primary;
+		R_LOCK(dbenv, dbmp->reginfo);
+		mp->mp_maxwrite = maxwrite;
+		mp->mp_maxwrite_sleep = maxwrite_sleep;
+		R_UNLOCK(dbenv, dbmp->reginfo);
+	} else {
+		dbenv->mp_maxwrite = maxwrite;
+		dbenv->mp_maxwrite_sleep = maxwrite_sleep;
+	}
+	return (0);
+}
+
 static int
-__memp_set_mp_mmapsize(dbenv, mp_mmapsize )
+__memp_get_mp_mmapsize(dbenv, mp_mmapsizep)
+	DB_ENV *dbenv;
+	size_t *mp_mmapsizep;
+{
+	DB_MPOOL *dbmp;
+	MPOOL *mp;
+
+	ENV_NOT_CONFIGURED(dbenv,
+	    dbenv->mp_handle, "DB_ENV->get_mp_max_mmapsize", DB_INIT_MPOOL);
+
+	if (MPOOL_ON(dbenv)) {
+		dbmp = dbenv->mp_handle;
+		mp = dbmp->reginfo[0].primary;
+		R_LOCK(dbenv, dbmp->reginfo);
+		*mp_mmapsizep = mp->mp_mmapsize;
+		R_UNLOCK(dbenv, dbmp->reginfo);
+	} else
+		*mp_mmapsizep = dbenv->mp_mmapsize;
+	return (0);
+}
+
+/*
+ * __memp_set_mp_mmapsize --
+ *	DB_ENV->set_mp_mmapsize.
+ *
+ * PUBLIC: int __memp_set_mp_mmapsize __P((DB_ENV *, size_t));
+ */
+int
+__memp_set_mp_mmapsize(dbenv, mp_mmapsize)
 	DB_ENV *dbenv;
 	size_t mp_mmapsize;
 {
-	dbenv->mp_mmapsize = mp_mmapsize;
+	DB_MPOOL *dbmp;
+	MPOOL *mp;
+
+	ENV_NOT_CONFIGURED(dbenv,
+	    dbenv->mp_handle, "DB_ENV->get_mp_max_mmapsize", DB_INIT_MPOOL);
+
+	if (MPOOL_ON(dbenv)) {
+		dbmp = dbenv->mp_handle;
+		mp = dbmp->reginfo[0].primary;
+		R_LOCK(dbenv, dbmp->reginfo);
+		mp->mp_mmapsize = mp_mmapsize;
+		R_UNLOCK(dbenv, dbmp->reginfo);
+	} else
+		dbenv->mp_mmapsize = mp_mmapsize;
+	return (0);
+}
+
+/*
+ * __memp_nameop
+ *	Remove or rename a file in the pool.
+ *
+ * PUBLIC: int __memp_nameop __P((DB_ENV *,
+ * PUBLIC:     u_int8_t *, const char *, const char *, const char *));
+ *
+ * XXX
+ * Undocumented interface: DB private.
+ */
+int
+__memp_nameop(dbenv, fileid, newname, fullold, fullnew)
+	DB_ENV *dbenv;
+	u_int8_t *fileid;
+	const char *newname, *fullold, *fullnew;
+{
+	DB_MPOOL *dbmp;
+	MPOOL *mp;
+	MPOOLFILE *mfp;
+	roff_t newname_off;
+	int locked, ret;
+	void *p;
+
+	/* We get passed either a two names, or two NULLs. */
+	DB_ASSERT(
+	    (newname == NULL && fullnew == NULL) ||
+	    (newname != NULL && fullnew != NULL));
+
+	locked = 0;
+	dbmp = NULL;
+
+	if (!MPOOL_ON(dbenv))
+		goto fsop;
+
+	dbmp = dbenv->mp_handle;
+	mp = dbmp->reginfo[0].primary;
+
+	/*
+	 * Remove or rename a file that the mpool might know about.  We assume
+	 * that the fop layer has the file locked for exclusive access, so we
+	 * don't worry about locking except for the mpool mutexes.  Checkpoint
+	 * can happen at any time, independent of file locking, so we have to
+	 * do the actual unlink or rename system call to avoid any race.
+	 *
+	 * If this is a rename, allocate first, because we can't recursively
+	 * grab the region lock.
+	 */
+	if (newname == NULL) {
+		p = NULL;
+		COMPQUIET(newname_off, INVALID_ROFF);
+	} else {
+		if ((ret = __memp_alloc(dbmp, dbmp->reginfo,
+		    NULL, strlen(newname) + 1, &newname_off, &p)) != 0)
+			return (ret);
+		memcpy(p, newname, strlen(newname) + 1);
+	}
+
+	locked = 1;
+	R_LOCK(dbenv, dbmp->reginfo);
+
+	/*
+	 * Find the file -- if mpool doesn't know about this file, that's not
+	 * an error -- we may not have it open.
+	 */
+	for (mfp = SH_TAILQ_FIRST(&mp->mpfq, __mpoolfile);
+	    mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) {
+		/* Ignore non-active files. */
+		if (mfp->deadfile || F_ISSET(mfp, MP_TEMP))
+			continue;
+
+		/* Ignore non-matching files. */
+		if (memcmp(fileid, R_ADDR(
+		    dbmp->reginfo, mfp->fileid_off), DB_FILE_ID_LEN) != 0)
+			continue;
+
+		/* If newname is NULL, we're removing the file. */
+		if (newname == NULL) {
+			MUTEX_LOCK(dbenv, &mfp->mutex);
+			mfp->deadfile = 1;
+			MUTEX_UNLOCK(dbenv, &mfp->mutex);
+		} else {
+			/*
+			 * Else, it's a rename.  We've allocated memory
+			 * for the new name.  Swap it with the old one.
+			 */
+			p = R_ADDR(dbmp->reginfo, mfp->path_off);
+			mfp->path_off = newname_off;
+		}
+		break;
+	}
+
+	/* Delete the memory we no longer need. */
+	if (p != NULL)
+		__db_shalloc_free(&dbmp->reginfo[0], p);
+
+fsop:	if (newname == NULL) {
+		/*
+		 * !!!
+		 * Replication may ask us to unlink a file that's been
+		 * renamed.  Don't complain if it doesn't exist.
+		 */
+		if ((ret = __os_unlink(dbenv, fullold)) == ENOENT)
+			ret = 0;
+	} else {
+		/* Defensive only, fullname should never be NULL. */
+		DB_ASSERT(fullnew != NULL);
+		if (fullnew == NULL)
+			return (EINVAL);
+
+		ret = __os_rename(dbenv, fullold, fullnew, 1);
+	}
+
+	if (locked)
+		R_UNLOCK(dbenv, dbmp->reginfo);
+
+	return (ret);
+}
+
+/*
+ * __memp_get_refcnt
+ *	Return a reference count, given a fileid.
+ *
+ * PUBLIC: int __memp_get_refcnt __P((DB_ENV *, u_int8_t *, u_int32_t *));
+ */
+int
+__memp_get_refcnt(dbenv, fileid, refp)
+	DB_ENV *dbenv;
+	u_int8_t *fileid;
+	u_int32_t *refp;
+{
+	DB_MPOOL *dbmp;
+	MPOOL *mp;
+	MPOOLFILE *mfp;
+
+	*refp = 0;
+
+	if (!MPOOL_ON(dbenv))
+		return (0);
+
+	dbmp = dbenv->mp_handle;
+	mp = dbmp->reginfo[0].primary;
+
+	R_LOCK(dbenv, dbmp->reginfo);
+	/*
+	 * Find the file -- if mpool doesn't know about this file, the
+	 * reference count is 0.
+	 */
+	for (mfp = SH_TAILQ_FIRST(&mp->mpfq, __mpoolfile);
+	    mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) {
+
+		/* Ignore non-active files. */
+		if (mfp->deadfile || F_ISSET(mfp, MP_TEMP))
+			continue;
+
+		/* Ignore non-matching files. */
+		if (memcmp(fileid, R_ADDR(
+		    dbmp->reginfo, mfp->fileid_off), DB_FILE_ID_LEN) != 0)
+			continue;
+
+		*refp = mfp->mpf_cnt;
+		break;
+	}
+	R_UNLOCK(dbenv, dbmp->reginfo);
+
 	return (0);
 }
+
+/*
+ * __memp_ftruncate __
+ *	Truncate the file.
+ *
+ * PUBLIC: int __memp_ftruncate __P((DB_MPOOLFILE *, db_pgno_t, u_int32_t));
+ */
+int
+__memp_ftruncate(dbmfp, pgno, flags)
+	DB_MPOOLFILE *dbmfp;
+	db_pgno_t pgno;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	DB_MPOOL *dbmp;
+	void *pagep;
+	db_pgno_t last_pgno, pg;
+	int ret;
+
+	COMPQUIET(flags, 0);
+	dbenv = dbmfp->dbenv;
+	dbmp = dbenv->mp_handle;
+
+	R_LOCK(dbenv, dbmp->reginfo);
+	last_pgno = dbmfp->mfp->last_pgno;
+	R_UNLOCK(dbenv, dbmp->reginfo);
+
+	if (pgno > last_pgno) {
+		__db_err(dbenv, "Truncate beyond the end of file");
+		return (EINVAL);
+	}
+
+	pg = pgno;
+	do {
+		if ((ret =
+		    __memp_fget(dbmfp, &pg, DB_MPOOL_FREE, &pagep)) != 0)
+			return (ret);
+	} while (pg++ < last_pgno);
+
+	if (!F_ISSET(dbmfp->mfp, MP_TEMP) &&
+	    (ret = __os_truncate(dbenv,
+	    dbmfp->fhp, pgno, dbmfp->mfp->stat.st_pagesize)) != 0)
+		return (ret);
+
+	R_LOCK(dbenv, dbmp->reginfo);
+	dbmfp->mfp->last_pgno = pgno - 1;
+	R_UNLOCK(dbenv, dbmp->reginfo);
+
+	return (ret);
+}
diff --git a/storage/bdb/mp/mp_region.c b/storage/bdb/mp/mp_region.c
index 06eca2f8646967e015ed5c1628a5804c0ba139f5..3c7ee6a4b621f235813962787978f9143a591e2b 100644
--- a/storage/bdb/mp/mp_region.c
+++ b/storage/bdb/mp/mp_region.c
@@ -1,14 +1,13 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: mp_region.c,v 11.68 2004/10/15 16:59:43 bostic Exp $
  */
-#include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: mp_region.c,v 11.49 2002/05/07 18:42:20 bostic Exp $";
-#endif /* not lint */
+#include "db_config.h"
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
@@ -20,9 +19,10 @@ static const char revid[] = "$Id: mp_region.c,v 11.49 2002/05/07 18:42:20 bostic
 #include "dbinc/db_shash.h"
 #include "dbinc/mp.h"
 
-static int __mpool_init __P((DB_ENV *, DB_MPOOL *, int, int));
+static int	__memp_init __P((DB_ENV *, DB_MPOOL *, u_int, u_int32_t));
+static void	__memp_init_config __P((DB_ENV *, MPOOL *));
 #ifdef HAVE_MUTEX_SYSTEM_RESOURCES
-static size_t __mpool_region_maint __P((REGINFO *));
+static size_t	__memp_region_maint __P((REGINFO *));
 #endif
 
 /*
@@ -38,9 +38,10 @@ __memp_open(dbenv)
 	DB_MPOOL *dbmp;
 	MPOOL *mp;
 	REGINFO reginfo;
-	roff_t reg_size, *regids;
-	u_int32_t i;
-	int htab_buckets, ret;
+	roff_t reg_size;
+	u_int i;
+	u_int32_t htab_buckets, *regids;
+	int ret;
 
 	/* Figure out how big each cache region is. */
 	reg_size = (dbenv->mp_gbytes / dbenv->mp_ncache) * GIGABYTE;
@@ -55,7 +56,7 @@ __memp_open(dbenv)
 	 * files.  Use a pagesize of 1K for the calculation -- we walk these
 	 * chains a lot, they must be kept short.
 	 */
-	htab_buckets = __db_tablesize((reg_size / (1 * 1024)) / 10);
+	htab_buckets = __db_tablesize((u_int32_t)(reg_size / (1 * 1024)) / 10);
 
 	/* Create and initialize the DB_MPOOL structure. */
 	if ((ret = __os_calloc(dbenv, 1, sizeof(*dbmp), &dbmp)) != 0)
@@ -66,9 +67,9 @@ __memp_open(dbenv)
 
 	/* Join/create the first mpool region. */
 	memset(&reginfo, 0, sizeof(REGINFO));
+	reginfo.dbenv = dbenv;
 	reginfo.type = REGION_TYPE_MPOOL;
 	reginfo.id = INVALID_REGION_ID;
-	reginfo.mode = dbenv->db_mode;
 	reginfo.flags = REGION_JOIN_OK;
 	if (F_ISSET(dbenv, DB_ENV_CREATE))
 		F_SET(&reginfo, REGION_CREATE_OK);
@@ -95,7 +96,7 @@ __memp_open(dbenv)
 		dbmp->reginfo[0] = reginfo;
 
 		/* Initialize the first region. */
-		if ((ret = __mpool_init(dbenv, dbmp, 0, htab_buckets)) != 0)
+		if ((ret = __memp_init(dbenv, dbmp, 0, htab_buckets)) != 0)
 			goto err;
 
 		/*
@@ -105,21 +106,23 @@ __memp_open(dbenv)
 		mp = R_ADDR(dbmp->reginfo, dbmp->reginfo[0].rp->primary);
 		regids = R_ADDR(dbmp->reginfo, mp->regids);
 		for (i = 1; i < dbmp->nreg; ++i) {
+			dbmp->reginfo[i].dbenv = dbenv;
 			dbmp->reginfo[i].type = REGION_TYPE_MPOOL;
 			dbmp->reginfo[i].id = INVALID_REGION_ID;
-			dbmp->reginfo[i].mode = dbenv->db_mode;
 			dbmp->reginfo[i].flags = REGION_CREATE_OK;
 			if ((ret = __db_r_attach(
 			    dbenv, &dbmp->reginfo[i], reg_size)) != 0)
 				goto err;
 			if ((ret =
-			    __mpool_init(dbenv, dbmp, i, htab_buckets)) != 0)
+			    __memp_init(dbenv, dbmp, i, htab_buckets)) != 0)
 				goto err;
 			R_UNLOCK(dbenv, &dbmp->reginfo[i]);
 
 			regids[i] = dbmp->reginfo[i].id;
 		}
 
+		__memp_init_config(dbenv, mp);
+
 		R_UNLOCK(dbenv, dbmp->reginfo);
 	} else {
 		/*
@@ -137,6 +140,8 @@ __memp_open(dbenv)
 			dbmp->reginfo[i].id = INVALID_REGION_ID;
 		dbmp->reginfo[0] = reginfo;
 
+		__memp_init_config(dbenv, mp);
+
 		/*
 		 * We have to unlock the primary mpool region before we attempt
 		 * to join the additional mpool regions.  If we don't, we can
@@ -153,9 +158,9 @@ __memp_open(dbenv)
 		/* Join remaining regions. */
 		regids = R_ADDR(dbmp->reginfo, mp->regids);
 		for (i = 1; i < dbmp->nreg; ++i) {
+			dbmp->reginfo[i].dbenv = dbenv;
 			dbmp->reginfo[i].type = REGION_TYPE_MPOOL;
 			dbmp->reginfo[i].id = regids[i];
-			dbmp->reginfo[i].mode = 0;
 			dbmp->reginfo[i].flags = REGION_JOIN_OK;
 			if ((ret = __db_r_attach(
 			    dbenv, &dbmp->reginfo[i], 0)) != 0)
@@ -197,14 +202,15 @@ err:	if (dbmp->reginfo != NULL && dbmp->reginfo[0].addr != NULL) {
 }
 
 /*
- * __mpool_init --
+ * __memp_init --
  *	Initialize a MPOOL structure in shared memory.
  */
 static int
-__mpool_init(dbenv, dbmp, reginfo_off, htab_buckets)
+__memp_init(dbenv, dbmp, reginfo_off, htab_buckets)
 	DB_ENV *dbenv;
 	DB_MPOOL *dbmp;
-	int reginfo_off, htab_buckets;
+	u_int reginfo_off;
+	u_int32_t htab_buckets;
 {
 	DB_MPOOL_HASH *htab;
 	MPOOL *mp;
@@ -212,13 +218,12 @@ __mpool_init(dbenv, dbmp, reginfo_off, htab_buckets)
 #ifdef HAVE_MUTEX_SYSTEM_RESOURCES
 	size_t maint_size;
 #endif
-	int i, ret;
+	u_int32_t i;
+	int ret;
 	void *p;
 
-	mp = NULL;
-
 	reginfo = &dbmp->reginfo[reginfo_off];
-	if ((ret = __db_shalloc(reginfo->addr,
+	if ((ret = __db_shalloc(reginfo,
 	    sizeof(MPOOL), MUTEX_ALIGN, &reginfo->primary)) != 0)
 		goto mem_err;
 	reginfo->rp->primary = R_OFFSET(reginfo, reginfo->primary);
@@ -226,9 +231,9 @@ __mpool_init(dbenv, dbmp, reginfo_off, htab_buckets)
 	memset(mp, 0, sizeof(*mp));
 
 #ifdef	HAVE_MUTEX_SYSTEM_RESOURCES
-	maint_size = __mpool_region_maint(reginfo);
+	maint_size = __memp_region_maint(reginfo);
 	/* Allocate room for the maintenance info and initialize it. */
-	if ((ret = __db_shalloc(reginfo->addr,
+	if ((ret = __db_shalloc(reginfo,
 	    sizeof(REGMAINT) + maint_size, 0, &p)) != 0)
 		goto mem_err;
 	__db_maintinit(reginfo, p, maint_size);
@@ -241,21 +246,20 @@ __mpool_init(dbenv, dbmp, reginfo_off, htab_buckets)
 		ZERO_LSN(mp->lsn);
 
 		mp->nreg = dbmp->nreg;
-		if ((ret = __db_shalloc(dbmp->reginfo[0].addr,
-		    dbmp->nreg * sizeof(int), 0, &p)) != 0)
+		if ((ret = __db_shalloc(&dbmp->reginfo[0],
+		    dbmp->nreg * sizeof(u_int32_t), 0, &p)) != 0)
 			goto mem_err;
 		mp->regids = R_OFFSET(dbmp->reginfo, p);
 	}
 
 	/* Allocate hash table space and initialize it. */
-	if ((ret = __db_shalloc(reginfo->addr,
-	    htab_buckets * sizeof(DB_MPOOL_HASH), 0, &htab)) != 0)
+	if ((ret = __db_shalloc(reginfo,
+	    htab_buckets * sizeof(DB_MPOOL_HASH), MUTEX_ALIGN, &htab)) != 0)
 		goto mem_err;
 	mp->htab = R_OFFSET(reginfo, htab);
 	for (i = 0; i < htab_buckets; i++) {
 		if ((ret = __db_mutex_setup(dbenv,
-		    reginfo, &htab[i].hash_mutex,
-		    MUTEX_NO_RLOCK)) != 0)
+		    reginfo, &htab[i].hash_mutex, MUTEX_NO_RLOCK)) != 0)
 			return (ret);
 		SH_TAILQ_INIT(&htab[i].hash_bucket);
 		htab[i].hash_page_dirty = htab[i].hash_priority = 0;
@@ -274,6 +278,26 @@ mem_err:__db_err(dbenv, "Unable to allocate memory for mpool region");
 	return (ret);
 }
 
+/*
+ * __memp_init_config --
+ *	Initialize shared configuration information.
+ */
+static void
+__memp_init_config(dbenv, mp)
+	DB_ENV *dbenv;
+	MPOOL *mp;
+{
+	/* A process joining the region may reset the mpool configuration. */
+	if (dbenv->mp_mmapsize != 0)
+		mp->mp_mmapsize = dbenv->mp_mmapsize;
+	if (dbenv->mp_maxopenfd != 0)
+		mp->mp_maxopenfd = dbenv->mp_maxopenfd;
+	if (dbenv->mp_maxwrite != 0)
+		mp->mp_maxwrite = dbenv->mp_maxwrite;
+	if (dbenv->mp_maxwrite_sleep != 0)
+		mp->mp_maxwrite_sleep = dbenv->mp_maxwrite_sleep;
+}
+
 /*
  * __memp_dbenv_refresh --
  *	Clean up after the mpool system on a close or failed open.
@@ -284,36 +308,75 @@ int
 __memp_dbenv_refresh(dbenv)
 	DB_ENV *dbenv;
 {
+	BH *bhp;
 	DB_MPOOL *dbmp;
 	DB_MPOOLFILE *dbmfp;
+	DB_MPOOL_HASH *hp;
 	DB_MPREG *mpreg;
-	u_int32_t i;
+	MPOOL *mp;
+	REGINFO *reginfo;
+	u_int32_t bucket, i;
 	int ret, t_ret;
 
 	ret = 0;
 	dbmp = dbenv->mp_handle;
 
+	/*
+	 * If a private region, return the memory to the heap.  Not needed for
+	 * filesystem-backed or system shared memory regions, that memory isn't
+	 * owned by any particular process.
+	 *
+	 * Discard buffers.
+	 */
+	if (F_ISSET(dbenv, DB_ENV_PRIVATE))
+		for (i = 0; i < dbmp->nreg; ++i) {
+			reginfo = &dbmp->reginfo[i];
+			mp = reginfo->primary;
+			for (hp = R_ADDR(reginfo, mp->htab), bucket = 0;
+			    bucket < mp->htab_buckets; ++hp, ++bucket)
+				while ((bhp = SH_TAILQ_FIRST(
+				    &hp->hash_bucket, __bh)) != NULL)
+					__memp_bhfree(dbmp, hp, bhp,
+					    BH_FREE_FREEMEM | BH_FREE_UNLOCKED);
+		}
+
+	/* Discard DB_MPOOLFILEs. */
+	while ((dbmfp = TAILQ_FIRST(&dbmp->dbmfq)) != NULL)
+		if ((t_ret = __memp_fclose(dbmfp, 0)) != 0 && ret == 0)
+			ret = t_ret;
+
 	/* Discard DB_MPREGs. */
 	while ((mpreg = LIST_FIRST(&dbmp->dbregq)) != NULL) {
 		LIST_REMOVE(mpreg, q);
 		__os_free(dbenv, mpreg);
 	}
 
-	/* Discard DB_MPOOLFILEs. */
-	while ((dbmfp = TAILQ_FIRST(&dbmp->dbmfq)) != NULL)
-		if ((t_ret = __memp_fclose_int(dbmfp, 0)) != 0 && ret == 0)
-			ret = t_ret;
-
-	/* Discard the thread mutex. */
+	/* Discard the DB_MPOOL thread mutex. */
 	if (dbmp->mutexp != NULL)
 		__db_mutex_free(dbenv, dbmp->reginfo, dbmp->mutexp);
 
-	/* Detach from the region(s). */
-	for (i = 0; i < dbmp->nreg; ++i)
-		if ((t_ret = __db_r_detach(
-		    dbenv, &dbmp->reginfo[i], 0)) != 0 && ret == 0)
+	if (F_ISSET(dbenv, DB_ENV_PRIVATE)) {
+		/* Discard REGION IDs. */
+		reginfo = &dbmp->reginfo[0];
+		mp = dbmp->reginfo[0].primary;
+		__db_shalloc_free(reginfo, R_ADDR(reginfo, mp->regids));
+
+		/* Discard Hash tables. */
+		for (i = 0; i < dbmp->nreg; ++i) {
+			reginfo = &dbmp->reginfo[i];
+			mp = reginfo->primary;
+			__db_shalloc_free(reginfo, R_ADDR(reginfo, mp->htab));
+		}
+	}
+
+	/* Detach from the region. */
+	for (i = 0; i < dbmp->nreg; ++i) {
+		reginfo = &dbmp->reginfo[i];
+		if ((t_ret = __db_r_detach(dbenv, reginfo, 0)) != 0 && ret == 0)
 			ret = t_ret;
+	}
 
+	/* Discard DB_MPOOL. */
 	__os_free(dbenv, dbmp->reginfo);
 	__os_free(dbenv, dbmp);
 
@@ -323,12 +386,12 @@ __memp_dbenv_refresh(dbenv)
 
 #ifdef HAVE_MUTEX_SYSTEM_RESOURCES
 /*
- * __mpool_region_maint --
+ * __memp_region_maint --
  *	Return the amount of space needed for region maintenance info.
  *
  */
 static size_t
-__mpool_region_maint(infop)
+__memp_region_maint(infop)
 	REGINFO *infop;
 {
 	size_t s;
@@ -348,119 +411,34 @@ __mpool_region_maint(infop)
 #endif
 
 /*
- * __mpool_region_destroy
+ * __memp_region_destroy
  *	Destroy any region maintenance info.
  *
- * PUBLIC: void __mpool_region_destroy __P((DB_ENV *, REGINFO *));
+ * PUBLIC: void __memp_region_destroy __P((DB_ENV *, REGINFO *));
  */
 void
-__mpool_region_destroy(dbenv, infop)
+__memp_region_destroy(dbenv, infop)
 	DB_ENV *dbenv;
 	REGINFO *infop;
 {
-	__db_shlocks_destroy(infop, (REGMAINT *)R_ADDR(infop,
-	    ((MPOOL *)R_ADDR(infop, infop->rp->primary))->maint_off));
-
-	COMPQUIET(dbenv, NULL);
-	COMPQUIET(infop, NULL);
-}
-
-/*
- * __memp_nameop
- *	Remove or rename a file in the pool.
- *
- * PUBLIC: int  __memp_nameop __P((DB_ENV *,
- * PUBLIC:     u_int8_t *, const char *, const char *, const char *));
- *
- * XXX
- * Undocumented interface: DB private.
- */
-int
-__memp_nameop(dbenv, fileid, newname, fullold, fullnew)
-	DB_ENV *dbenv;
-	u_int8_t *fileid;
-	const char *newname, *fullold, *fullnew;
-{
-	DB_MPOOL *dbmp;
-	MPOOL *mp;
-	MPOOLFILE *mfp;
-	roff_t newname_off;
-	int locked, ret;
-	void *p;
-
-	locked = 0;
-	dbmp = NULL;
-
-	if (!MPOOL_ON(dbenv))
-		goto fsop;
-
-	dbmp = dbenv->mp_handle;
-	mp = dbmp->reginfo[0].primary;
-
 	/*
-	 * Remove or rename a file that the mpool might know about.  We assume
-	 * that the fop layer has the file locked for exclusive access, so we
-	 * don't worry about locking except for the mpool mutexes.  Checkpoint
-	 * can happen at any time, independent of file locking, so we have to
-	 * do the actual unlink or rename system call to avoid any race.
-	 *
-	 * If this is a rename, allocate first, because we can't recursively
-	 * grab the region lock.
+	 * This routine is called in two cases: when discarding the mutexes
+	 * from a previous Berkeley DB run, during recovery, and two, when
+	 * discarding the mutexes as we shut down the database environment.
+	 * In the latter case, we also need to discard shared memory segments,
+	 * this is the last time we use them, and the last region-specific
+	 * call we make.
 	 */
-	if (newname == NULL)
-		p = NULL;
-	else {
-		if ((ret = __memp_alloc(dbmp, dbmp->reginfo,
-		    NULL, strlen(newname) + 1, &newname_off, &p)) != 0)
-			return (ret);
-		memcpy(p, newname, strlen(newname) + 1);
-	}
-
-	locked = 1;
-	R_LOCK(dbenv, dbmp->reginfo);
-
-	/*
-	 * Find the file -- if mpool doesn't know about this file, that's not
-	 * an error-- we may not have it open.
-	 */
-	for (mfp = SH_TAILQ_FIRST(&mp->mpfq, __mpoolfile);
-	    mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) {
-		/* Ignore non-active files. */
-		if (F_ISSET(mfp, MP_DEADFILE | MP_TEMP))
-			continue;
-
-		/* Ignore non-matching files. */
-		if (memcmp(fileid, R_ADDR(
-		    dbmp->reginfo, mfp->fileid_off), DB_FILE_ID_LEN) != 0)
-			continue;
-
-		/* If newname is NULL, we're removing the file. */
-		if (newname == NULL) {
-			MUTEX_LOCK(dbenv, &mfp->mutex);
-			MPOOLFILE_IGNORE(mfp);
-			MUTEX_UNLOCK(dbenv, &mfp->mutex);
-		} else {
-			/*
-			 * Else, it's a rename.  We've allocated memory
-			 * for the new name.  Swap it with the old one.
-			 */
-			p = R_ADDR(dbmp->reginfo, mfp->path_off);
-			mfp->path_off = newname_off;
-		}
-		break;
-	}
-
-	/* Delete the memory we no longer need. */
-	if (p != NULL)
-		__db_shalloc_free(dbmp->reginfo[0].addr, p);
-
-fsop:	if (newname == NULL)
-		(void)__os_unlink(dbenv, fullold);
-	else
-		(void)__os_rename(dbenv, fullold, fullnew, 1);
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
+	MPOOL *mp;
 
-	if (locked)
-		R_UNLOCK(dbenv, dbmp->reginfo);
+	mp = R_ADDR(infop, infop->rp->primary);
 
-	return (0);
+	/* Destroy mutexes. */
+	__db_shlocks_destroy(infop, R_ADDR(infop, mp->maint_off));
+	if (infop->primary != NULL && F_ISSET(dbenv, DB_ENV_PRIVATE))
+		__db_shalloc_free(infop, R_ADDR(infop, mp->maint_off));
+#endif
+	if (infop->primary != NULL && F_ISSET(dbenv, DB_ENV_PRIVATE))
+		__db_shalloc_free(infop, infop->primary);
 }
diff --git a/storage/bdb/mp/mp_register.c b/storage/bdb/mp/mp_register.c
index 46eefad986fce858256f67f884f7385a111b1c5f..0294fd5f0cbd652717fc879df47b273e5d2fc019 100644
--- a/storage/bdb/mp/mp_register.c
+++ b/storage/bdb/mp/mp_register.c
@@ -1,14 +1,13 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: mp_register.c,v 11.26 2004/07/15 15:52:54 sue Exp $
  */
-#include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: mp_register.c,v 11.21 2002/03/27 04:32:27 bostic Exp $";
-#endif /* not lint */
+#include "db_config.h"
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
@@ -16,11 +15,42 @@ static const char revid[] = "$Id: mp_register.c,v 11.21 2002/03/27 04:32:27 bost
 
 #include "db_int.h"
 #include "dbinc/db_shash.h"
+#include "dbinc/log.h"
 #include "dbinc/mp.h"
 
+/*
+ * memp_register_pp --
+ *	DB_ENV->memp_register pre/post processing.
+ *
+ * PUBLIC: int __memp_register_pp __P((DB_ENV *, int,
+ * PUBLIC:     int (*)(DB_ENV *, db_pgno_t, void *, DBT *),
+ * PUBLIC:     int (*)(DB_ENV *, db_pgno_t, void *, DBT *)));
+ */
+int
+__memp_register_pp(dbenv, ftype, pgin, pgout)
+	DB_ENV *dbenv;
+	int ftype;
+	int (*pgin) __P((DB_ENV *, db_pgno_t, void *, DBT *));
+	int (*pgout) __P((DB_ENV *, db_pgno_t, void *, DBT *));
+{
+	int rep_check, ret;
+
+	PANIC_CHECK(dbenv);
+	ENV_REQUIRES_CONFIG(dbenv,
+	    dbenv->mp_handle, "DB_ENV->memp_register", DB_INIT_MPOOL);
+
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __memp_register(dbenv, ftype, pgin, pgout);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
 /*
  * memp_register --
- *	Register a file type's pgin, pgout routines.
+ *	DB_ENV->memp_register.
  *
  * PUBLIC: int __memp_register __P((DB_ENV *, int,
  * PUBLIC:     int (*)(DB_ENV *, db_pgno_t, void *, DBT *),
@@ -37,10 +67,6 @@ __memp_register(dbenv, ftype, pgin, pgout)
 	DB_MPREG *mpreg;
 	int ret;
 
-	PANIC_CHECK(dbenv);
-	ENV_REQUIRES_CONFIG(dbenv,
-	    dbenv->mp_handle, "DB_ENV->memp_register", DB_INIT_MPOOL);
-
 	dbmp = dbenv->mp_handle;
 
 	/*
diff --git a/storage/bdb/mp/mp_stat.c b/storage/bdb/mp/mp_stat.c
index 12e72b91d7080c9d36a01f3ef696601cf4a6bb92..3896b06da677197225751cc66ab56c2d7e2c246e 100644
--- a/storage/bdb/mp/mp_stat.c
+++ b/storage/bdb/mp/mp_stat.c
@@ -1,42 +1,78 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: mp_stat.c,v 11.82 2004/10/15 16:59:43 bostic Exp $
  */
-#include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: mp_stat.c,v 11.51 2002/08/06 06:13:47 bostic Exp $";
-#endif /* not lint */
+#include "db_config.h"
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <stdio.h>
 #include <string.h>
-#include <unistd.h>
 #endif
 
 #include "db_int.h"
 #include "dbinc/db_page.h"
 #include "dbinc/db_shash.h"
 #include "dbinc/db_am.h"
+#include "dbinc/log.h"
 #include "dbinc/mp.h"
 
-static void __memp_dumpcache __P((DB_ENV *,
-		DB_MPOOL *, REGINFO *, size_t *, FILE *, u_int32_t));
-static void __memp_pbh __P((DB_MPOOL *, BH *, size_t *, FILE *));
-static void __memp_stat_wait __P((REGINFO *, MPOOL *, DB_MPOOL_STAT *, int));
+#ifdef HAVE_STATISTICS
+static void __memp_print_bh
+		__P((DB_ENV *, DB_MPOOL *, BH *, roff_t *, u_int32_t));
+static int  __memp_print_all __P((DB_ENV *, u_int32_t));
+static int  __memp_print_stats __P((DB_ENV *, u_int32_t));
+static void __memp_print_hash __P((DB_ENV *,
+		DB_MPOOL *, REGINFO *, roff_t *, u_int32_t));
+static int  __memp_stat __P((DB_ENV *,
+		DB_MPOOL_STAT **, DB_MPOOL_FSTAT ***, u_int32_t));
+static void __memp_stat_wait __P((
+		REGINFO *, MPOOL *, DB_MPOOL_STAT *, u_int32_t));
 
 /*
- * __memp_stat --
- *	Display MPOOL statistics.
+ * __memp_stat_pp --
+ *	DB_ENV->memp_stat pre/post processing.
  *
- * PUBLIC: int __memp_stat
+ * PUBLIC: int __memp_stat_pp
  * PUBLIC:     __P((DB_ENV *, DB_MPOOL_STAT **, DB_MPOOL_FSTAT ***, u_int32_t));
  */
 int
+__memp_stat_pp(dbenv, gspp, fspp, flags)
+	DB_ENV *dbenv;
+	DB_MPOOL_STAT **gspp;
+	DB_MPOOL_FSTAT ***fspp;
+	u_int32_t flags;
+{
+	int rep_check, ret;
+
+	PANIC_CHECK(dbenv);
+	ENV_REQUIRES_CONFIG(dbenv,
+	    dbenv->mp_handle, "DB_ENV->memp_stat", DB_INIT_MPOOL);
+
+	if ((ret = __db_fchk(dbenv,
+	    "DB_ENV->memp_stat", flags, DB_STAT_CLEAR)) != 0)
+		return (ret);
+
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __memp_stat(dbenv, gspp, fspp, flags);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
+/*
+ * __memp_stat --
+ *	DB_ENV->memp_stat
+ */
+static int
 __memp_stat(dbenv, gspp, fspp, flags)
 	DB_ENV *dbenv;
 	DB_MPOOL_STAT **gspp;
@@ -48,19 +84,11 @@ __memp_stat(dbenv, gspp, fspp, flags)
 	DB_MPOOL_STAT *sp;
 	MPOOL *c_mp, *mp;
 	MPOOLFILE *mfp;
-	size_t len, nlen, pagesize;
-	u_int32_t pages, i;
+	size_t len, nlen;
+	u_int32_t pages, pagesize, i;
 	int ret;
 	char *name, *tname;
 
-	PANIC_CHECK(dbenv);
-	ENV_REQUIRES_CONFIG(dbenv,
-	    dbenv->mp_handle, "memp_stat", DB_INIT_MPOOL);
-
-	if ((ret = __db_fchk(dbenv,
-	    "DB_ENV->memp_stat", flags, DB_STAT_CLEAR)) != 0)
-		return (ret);
-
 	dbmp = dbenv->mp_handle;
 	mp = dbmp->reginfo[0].primary;
 
@@ -75,7 +103,8 @@ __memp_stat(dbenv, gspp, fspp, flags)
 
 		/*
 		 * Initialization and information that is not maintained on
-		 * a per-cache basis.
+		 * a per-cache basis.  Note that configuration information
+		 * may be modified at any time, and so we have to lock.
 		 */
 		c_mp = dbmp->reginfo[0].primary;
 		sp->st_gbytes = c_mp->stat.st_gbytes;
@@ -83,6 +112,13 @@ __memp_stat(dbenv, gspp, fspp, flags)
 		sp->st_ncache = dbmp->nreg;
 		sp->st_regsize = dbmp->reginfo[0].rp->size;
 
+		R_LOCK(dbenv, dbmp->reginfo);
+		sp->st_mmapsize = mp->mp_mmapsize;
+		sp->st_maxopenfd = mp->mp_maxopenfd;
+		sp->st_maxwrite = mp->mp_maxwrite;
+		sp->st_maxwrite_sleep = mp->mp_maxwrite_sleep;
+		R_UNLOCK(dbenv, dbmp->reginfo);
+
 		/* Walk the cache list and accumulate the global information. */
 		for (i = 0; i < mp->nreg; ++i) {
 			c_mp = dbmp->reginfo[i].primary;
@@ -130,12 +166,14 @@ __memp_stat(dbenv, gspp, fspp, flags)
 				    c_mp->stat.st_alloc_max_pages;
 
 			if (LF_ISSET(DB_STAT_CLEAR)) {
-				dbmp->reginfo[i].rp->mutex.mutex_set_wait = 0;
-				dbmp->reginfo[i].rp->mutex.mutex_set_nowait = 0;
+				MUTEX_CLEAR(&dbmp->reginfo[i].rp->mutex);
+
+				R_LOCK(dbenv, dbmp->reginfo);
 				pages = c_mp->stat.st_pages;
 				memset(&c_mp->stat, 0, sizeof(c_mp->stat));
 				c_mp->stat.st_hash_buckets = c_mp->htab_buckets;
 				c_mp->stat.st_pages = pages;
+				R_UNLOCK(dbenv, dbmp->reginfo);
 			}
 		}
 
@@ -230,179 +268,370 @@ __memp_stat(dbenv, gspp, fspp, flags)
 	return (0);
 }
 
-#define	FMAP_ENTRIES	200			/* Files we map. */
+/*
+ * __memp_stat_print_pp --
+ *	DB_ENV->memp_stat_print pre/post processing.
+ *
+ * PUBLIC: int __memp_stat_print_pp __P((DB_ENV *, u_int32_t));
+ */
+int
+__memp_stat_print_pp(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	int rep_check, ret;
 
-#define	MPOOL_DUMP_HASH	0x01			/* Debug hash chains. */
-#define	MPOOL_DUMP_MEM	0x04			/* Debug region memory. */
-#define	MPOOL_DUMP_ALL	0x07			/* Debug all. */
+	PANIC_CHECK(dbenv);
+	ENV_REQUIRES_CONFIG(dbenv,
+	    dbenv->mp_handle, "DB_ENV->memp_stat_print", DB_INIT_MPOOL);
+
+#define	DB_STAT_MEMP_FLAGS						\
+	(DB_STAT_ALL | DB_STAT_CLEAR | DB_STAT_MEMP_HASH)
+	if ((ret = __db_fchk(dbenv,
+	    "DB_ENV->memp_stat_print", flags, DB_STAT_MEMP_FLAGS)) != 0)
+		return (ret);
+
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __memp_stat_print(dbenv, flags);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
+#define	FMAP_ENTRIES	200			/* Files we map. */
 
 /*
- * __memp_dump_region --
- *	Display MPOOL structures.
+ * __memp_stat_print --
+ *	DB_ENV->memp_stat_print method.
  *
- * PUBLIC: int __memp_dump_region __P((DB_ENV *, char *, FILE *));
+ * PUBLIC: int  __memp_stat_print __P((DB_ENV *, u_int32_t));
  */
 int
-__memp_dump_region(dbenv, area, fp)
+__memp_stat_print(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	u_int32_t orig_flags;
+	int ret;
+
+	orig_flags = flags;
+	LF_CLR(DB_STAT_CLEAR);
+	if (flags == 0 || LF_ISSET(DB_STAT_ALL)) {
+		ret = __memp_print_stats(dbenv, orig_flags);
+		if (flags == 0 || ret != 0)
+			return (ret);
+	}
+
+	if (LF_ISSET(DB_STAT_ALL | DB_STAT_MEMP_HASH) &&
+	    (ret = __memp_print_all(dbenv, orig_flags)) != 0)
+		return (ret);
+
+	return (0);
+}
+
+/*
+ * __memp_print_stats --
+ *	Display default mpool region statistics.
+ */
+static int
+__memp_print_stats(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	DB_MPOOL_FSTAT **fsp, **tfsp;
+	DB_MPOOL_STAT *gsp;
+	int ret;
+
+	if ((ret = __memp_stat(dbenv, &gsp, &fsp, flags)) != 0)
+		return (ret);
+
+	if (LF_ISSET(DB_STAT_ALL))
+		__db_msg(dbenv, "Default cache region information:");
+	__db_dlbytes(dbenv, "Total cache size",
+	    (u_long)gsp->st_gbytes, (u_long)0, (u_long)gsp->st_bytes);
+	__db_dl(dbenv, "Number of caches", (u_long)gsp->st_ncache);
+	__db_dlbytes(dbenv, "Pool individual cache size",
+	    (u_long)0, (u_long)0, (u_long)gsp->st_regsize);
+	__db_dlbytes(dbenv, "Maximum memory-mapped file size",
+	    (u_long)0, (u_long)0, (u_long)gsp->st_mmapsize);
+	STAT_LONG("Maximum open file descriptors", gsp->st_maxopenfd);
+	STAT_LONG("Maximum sequential buffer writes", gsp->st_maxwrite);
+	STAT_LONG("Sleep after writing maximum sequential buffers",
+	    gsp->st_maxwrite_sleep);
+	__db_dl(dbenv,
+	    "Requested pages mapped into the process' address space",
+	    (u_long)gsp->st_map);
+	__db_dl_pct(dbenv, "Requested pages found in the cache",
+	    (u_long)gsp->st_cache_hit, DB_PCT(
+	    gsp->st_cache_hit, gsp->st_cache_hit + gsp->st_cache_miss), NULL);
+	__db_dl(dbenv, "Requested pages not found in the cache",
+	    (u_long)gsp->st_cache_miss);
+	__db_dl(dbenv,
+	    "Pages created in the cache", (u_long)gsp->st_page_create);
+	__db_dl(dbenv, "Pages read into the cache", (u_long)gsp->st_page_in);
+	__db_dl(dbenv, "Pages written from the cache to the backing file",
+	    (u_long)gsp->st_page_out);
+	__db_dl(dbenv, "Clean pages forced from the cache",
+	    (u_long)gsp->st_ro_evict);
+	__db_dl(dbenv, "Dirty pages forced from the cache",
+	    (u_long)gsp->st_rw_evict);
+	__db_dl(dbenv, "Dirty pages written by trickle-sync thread",
+	    (u_long)gsp->st_page_trickle);
+	__db_dl(dbenv, "Current total page count",
+	    (u_long)gsp->st_pages);
+	__db_dl(dbenv, "Current clean page count",
+	    (u_long)gsp->st_page_clean);
+	__db_dl(dbenv, "Current dirty page count",
+	    (u_long)gsp->st_page_dirty);
+	__db_dl(dbenv, "Number of hash buckets used for page location",
+	    (u_long)gsp->st_hash_buckets);
+	__db_dl(dbenv,
+	    "Total number of times hash chains searched for a page",
+	    (u_long)gsp->st_hash_searches);
+	__db_dl(dbenv, "The longest hash chain searched for a page",
+	    (u_long)gsp->st_hash_longest);
+	__db_dl(dbenv,
+	    "Total number of hash buckets examined for page location",
+	    (u_long)gsp->st_hash_examined);
+	__db_dl_pct(dbenv,
+	    "The number of hash bucket locks that required waiting",
+	    (u_long)gsp->st_hash_wait, DB_PCT(
+	    gsp->st_hash_wait, gsp->st_hash_wait + gsp->st_hash_nowait), NULL);
+	__db_dl(dbenv,
+    "The maximum number of times any hash bucket lock was waited for",
+	    (u_long)gsp->st_hash_max_wait);
+	__db_dl_pct(dbenv,
+	    "The number of region locks that required waiting",
+	    (u_long)gsp->st_region_wait, DB_PCT(gsp->st_region_wait,
+	    gsp->st_region_wait + gsp->st_region_nowait), NULL);
+	__db_dl(dbenv, "The number of page allocations", (u_long)gsp->st_alloc);
+	__db_dl(dbenv,
+	    "The number of hash buckets examined during allocations",
+	    (u_long)gsp->st_alloc_buckets);
+	__db_dl(dbenv,
+	    "The maximum number of hash buckets examined for an allocation",
+	    (u_long)gsp->st_alloc_max_buckets);
+	__db_dl(dbenv, "The number of pages examined during allocations",
+	    (u_long)gsp->st_alloc_pages);
+	__db_dl(dbenv, "The max number of pages examined for an allocation",
+	    (u_long)gsp->st_alloc_max_pages);
+
+	for (tfsp = fsp; fsp != NULL && *tfsp != NULL; ++tfsp) {
+		if (LF_ISSET(DB_STAT_ALL))
+			__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+		__db_msg(dbenv, "Pool File: %s", (*tfsp)->file_name);
+		__db_dl(dbenv, "Page size", (u_long)(*tfsp)->st_pagesize);
+		__db_dl(dbenv,
+		    "Requested pages mapped into the process' address space",
+		    (u_long)(*tfsp)->st_map);
+		__db_dl_pct(dbenv, "Requested pages found in the cache",
+		    (u_long)(*tfsp)->st_cache_hit, DB_PCT((*tfsp)->st_cache_hit,
+		    (*tfsp)->st_cache_hit + (*tfsp)->st_cache_miss), NULL);
+		__db_dl(dbenv, "Requested pages not found in the cache",
+		    (u_long)(*tfsp)->st_cache_miss);
+		__db_dl(dbenv, "Pages created in the cache",
+		    (u_long)(*tfsp)->st_page_create);
+		__db_dl(dbenv, "Pages read into the cache",
+		    (u_long)(*tfsp)->st_page_in);
+		__db_dl(dbenv,
+		    "Pages written from the cache to the backing file",
+		    (u_long)(*tfsp)->st_page_out);
+	}
+
+	__os_ufree(dbenv, fsp);
+	__os_ufree(dbenv, gsp);
+	return (0);
+}
+
+/*
+ * __memp_print_all --
+ *	Display debugging mpool region statistics.
+ */
+static int
+__memp_print_all(dbenv, flags)
 	DB_ENV *dbenv;
-	char *area;
-	FILE *fp;
+	u_int32_t flags;
 {
 	static const FN fn[] = {
-		{ MP_CAN_MMAP,	"mmapped" },
-		{ MP_DEADFILE,	"dead" },
-		{ MP_DIRECT,	"no buffer" },
-		{ MP_EXTENT,	"extent" },
-		{ MP_TEMP,	"temporary" },
-		{ MP_UNLINK,	"unlink" },
-		{ 0,		NULL }
+		{ MP_CAN_MMAP,		"MP_CAN_MMAP" },
+		{ MP_DIRECT,		"MP_DIRECT" },
+		{ MP_EXTENT,		"MP_EXTENT" },
+		{ MP_FAKE_DEADFILE,	"deadfile" },
+		{ MP_FAKE_FILEWRITTEN,	"file written" },
+		{ MP_FAKE_NB,		"no backing file" },
+		{ MP_FAKE_UOC,		"unlink on close" },
+		{ MP_NOT_DURABLE,	"not durable" },
+		{ MP_TEMP,		"MP_TEMP" },
+		{ 0,			NULL }
+	};
+	static const FN cfn[] = {
+		{ DB_MPOOL_NOFILE,	"DB_MPOOL_NOFILE" },
+		{ DB_MPOOL_UNLINK,	"DB_MPOOL_UNLINK" },
+		{ 0,			NULL }
 	};
 	DB_MPOOL *dbmp;
 	DB_MPOOLFILE *dbmfp;
 	MPOOL *mp;
 	MPOOLFILE *mfp;
-	size_t fmap[FMAP_ENTRIES + 1];
-	u_int32_t i, flags;
+	roff_t fmap[FMAP_ENTRIES + 1];
+	u_int32_t i, mfp_flags;
 	int cnt;
-	u_int8_t *p;
-
-	PANIC_CHECK(dbenv);
-	ENV_REQUIRES_CONFIG(dbenv,
-	    dbenv->mp_handle, "memp_dump_region", DB_INIT_MPOOL);
 
 	dbmp = dbenv->mp_handle;
-
-	/* Make it easy to call from the debugger. */
-	if (fp == NULL)
-		fp = stderr;
-
-	for (flags = 0; *area != '\0'; ++area)
-		switch (*area) {
-		case 'A':
-			LF_SET(MPOOL_DUMP_ALL);
-			break;
-		case 'h':
-			LF_SET(MPOOL_DUMP_HASH);
-			break;
-		case 'm':
-			LF_SET(MPOOL_DUMP_MEM);
-			break;
-		}
-
 	mp = dbmp->reginfo[0].primary;
 
-	/* Display MPOOL structures. */
-	(void)fprintf(fp, "%s\nPool (region addr 0x%lx)\n",
-	    DB_LINE, P_TO_ULONG(dbmp->reginfo[0].addr));
-
-	/* Display the MPOOLFILE structures. */
 	R_LOCK(dbenv, dbmp->reginfo);
+
+	__db_print_reginfo(dbenv, dbmp->reginfo, "Mpool");
+
+	__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+	__db_msg(dbenv, "MPOOL structure:");
+	STAT_LSN("Maximum checkpoint LSN", &mp->lsn);
+	STAT_ULONG("Hash table entries", mp->htab_buckets);
+	STAT_ULONG("Hash table last-checked", mp->last_checked);
+	STAT_ULONG("Hash table LRU count", mp->lru_count);
+	STAT_ULONG("Put counter", mp->put_counter);
+
+	__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+	__db_msg(dbenv, "DB_MPOOL handle information:");
+	__db_print_mutex(
+	    dbenv, NULL, dbmp->mutexp, "DB_MPOOL handle mutex", flags);
+	STAT_ULONG("Underlying cache regions", dbmp->nreg);
+
+	__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+	__db_msg(dbenv, "DB_MPOOLFILE structures:");
+	for (cnt = 0, dbmfp = TAILQ_FIRST(&dbmp->dbmfq);
+	    dbmfp != NULL; dbmfp = TAILQ_NEXT(dbmfp, q), ++cnt) {
+		__db_msg(dbenv, "File #%d: %s: per-process, %s",
+		    cnt + 1, __memp_fn(dbmfp),
+		    F_ISSET(dbmfp, MP_READONLY) ? "readonly" : "read/write");
+		STAT_ULONG("Reference count", dbmfp->ref);
+		STAT_ULONG("Pinned block reference count", dbmfp->ref);
+		STAT_ULONG("Clear length", dbmfp->clear_len);
+		__db_print_fileid(dbenv, dbmfp->fileid, "\tID");
+		STAT_ULONG("File type", dbmfp->ftype);
+		STAT_ULONG("LSN offset", dbmfp->lsn_offset);
+		STAT_ULONG("Max gbytes", dbmfp->gbytes);
+		STAT_ULONG("Max bytes", dbmfp->bytes);
+		STAT_ULONG("Cache priority", dbmfp->priority);
+		STAT_HEX("mmap address", dbmfp->addr);
+		STAT_ULONG("mmap length", dbmfp->len);
+		__db_prflags(dbenv, NULL, dbmfp->flags, cfn, NULL, "\tFlags");
+		__db_print_fh(dbenv, dbmfp->fhp, flags);
+	}
+
+	__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+	__db_msg(dbenv, "MPOOLFILE structures:");
 	for (cnt = 0, mfp = SH_TAILQ_FIRST(&mp->mpfq, __mpoolfile);
 	    mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile), ++cnt) {
-		(void)fprintf(fp, "File #%d: %s: pagesize %lu\n", cnt + 1,
-		    __memp_fns(dbmp, mfp), (u_long)mfp->stat.st_pagesize);
-		(void)fprintf(fp, "\t type %ld; ref %lu; blocks %lu; last %lu;",
-		    (long)mfp->ftype, (u_long)mfp->mpf_cnt,
-		    (u_long)mfp->block_cnt, (u_long)mfp->last_pgno);
-		__db_prflags(mfp->flags, fn, fp);
-
-		(void)fprintf(fp, "\n\t UID: ");
-		p = R_ADDR(dbmp->reginfo, mfp->fileid_off);
-		for (i = 0; i < DB_FILE_ID_LEN; ++i, ++p) {
-			(void)fprintf(fp, "%x", (u_int)*p);
-			if (i < DB_FILE_ID_LEN - 1)
-				(void)fprintf(fp, " ");
-		}
-		(void)fprintf(fp, "\n");
+		__db_msg(dbenv, "File #%d: %s", cnt + 1, __memp_fns(dbmp, mfp));
+		__db_print_mutex(dbenv, NULL, &mfp->mutex, "Mutex", flags);
+
+		MUTEX_LOCK(dbenv, &mfp->mutex);
+		STAT_ULONG("Reference count", mfp->mpf_cnt);
+		STAT_ULONG("Block count", mfp->block_cnt);
+		STAT_ULONG("Last page number", mfp->last_pgno);
+		STAT_ULONG("Original last page number", mfp->orig_last_pgno);
+		STAT_ULONG("Maximum page number", mfp->maxpgno);
+		STAT_LONG("Type", mfp->ftype);
+		STAT_LONG("Priority", mfp->priority);
+		STAT_LONG("Page's LSN offset", mfp->lsn_off);
+		STAT_LONG("Page's clear length", mfp->clear_len);
+
+		__db_print_fileid(dbenv,
+		    R_ADDR(dbmp->reginfo, mfp->fileid_off), "\tID");
+
+		mfp_flags = 0;
+		if (mfp->deadfile)
+			FLD_SET(mfp_flags, MP_FAKE_DEADFILE);
+		if (mfp->file_written)
+			FLD_SET(mfp_flags, MP_FAKE_FILEWRITTEN);
+		if (mfp->no_backing_file)
+			FLD_SET(mfp_flags, MP_FAKE_NB);
+		if (mfp->unlink_on_close)
+			FLD_SET(mfp_flags, MP_FAKE_UOC);
+		__db_prflags(dbenv, NULL, mfp_flags, fn, NULL, "\tFlags");
+
 		if (cnt < FMAP_ENTRIES)
 			fmap[cnt] = R_OFFSET(dbmp->reginfo, mfp);
+		MUTEX_UNLOCK(dbenv, &mfp->mutex);
 	}
 	R_UNLOCK(dbenv, dbmp->reginfo);
 
-	MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);
-	for (dbmfp = TAILQ_FIRST(&dbmp->dbmfq);
-	    dbmfp != NULL; dbmfp = TAILQ_NEXT(dbmfp, q), ++cnt) {
-		(void)fprintf(fp, "File #%d: %s: per-process, %s\n",
-		    cnt + 1, __memp_fn(dbmfp),
-		    F_ISSET(dbmfp, MP_READONLY) ? "readonly" : "read/write");
-		    if (cnt < FMAP_ENTRIES)
-			fmap[cnt] = R_OFFSET(dbmp->reginfo, mfp);
-	}
-	MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
 	if (cnt < FMAP_ENTRIES)
 		fmap[cnt] = INVALID_ROFF;
 	else
 		fmap[FMAP_ENTRIES] = INVALID_ROFF;
 
-	/* Dump the memory pools. */
+	/* Dump the individual caches. */
 	for (i = 0; i < mp->nreg; ++i) {
-		(void)fprintf(fp, "%s\nCache #%d:\n", DB_LINE, i + 1);
-		__memp_dumpcache(
-		    dbenv, dbmp, &dbmp->reginfo[i], fmap, fp, flags);
+		__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+		__db_msg(dbenv, "Cache #%d:", i + 1);
+		__memp_print_hash(dbenv, dbmp, &dbmp->reginfo[i], fmap, flags);
 	}
 
-	/* Flush in case we're debugging. */
-	(void)fflush(fp);
-
 	return (0);
 }
 
 /*
- * __memp_dumpcache --
- *	Display statistics for a cache.
+ * __memp_print_hash --
+ *	Display hash bucket statistics for a cache.
  */
 static void
-__memp_dumpcache(dbenv, dbmp, reginfo, fmap, fp, flags)
+__memp_print_hash(dbenv, dbmp, reginfo, fmap, flags)
 	DB_ENV *dbenv;
 	DB_MPOOL *dbmp;
 	REGINFO *reginfo;
-	size_t *fmap;
-	FILE *fp;
+	roff_t *fmap;
 	u_int32_t flags;
 {
 	BH *bhp;
 	DB_MPOOL_HASH *hp;
+	DB_MSGBUF mb;
 	MPOOL *c_mp;
-	int bucket;
+	u_int32_t bucket;
 
 	c_mp = reginfo->primary;
+	DB_MSGBUF_INIT(&mb);
 
 	/* Display the hash table list of BH's. */
-	if (LF_ISSET(MPOOL_DUMP_HASH)) {
-		(void)fprintf(fp,
-		    "%s\nBH hash table (%lu hash slots)\nbucket (priority):\n",
-		    DB_LINE, (u_long)c_mp->htab_buckets);
-		(void)fprintf(fp,
-		    "\tpageno, file, ref, address [LSN] priority\n");
-
-		for (hp = R_ADDR(reginfo, c_mp->htab),
-		    bucket = 0; bucket < c_mp->htab_buckets; ++hp, ++bucket) {
-			MUTEX_LOCK(dbenv, &hp->hash_mutex);
-			if ((bhp =
-			    SH_TAILQ_FIRST(&hp->hash_bucket, __bh)) != NULL)
-				(void)fprintf(fp, "%lu (%u):\n",
-				    (u_long)bucket, hp->hash_priority);
-			for (; bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, hq, __bh))
-				__memp_pbh(dbmp, bhp, fmap, fp);
-			MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
+	__db_msg(dbenv,
+	    "BH hash table (%lu hash slots)", (u_long)c_mp->htab_buckets);
+	__db_msg(dbenv, "bucket #: priority, mutex");
+	__db_msg(dbenv,
+	    "\tpageno, file, ref, LSN, mutex, address, priority, flags");
+
+	for (hp = R_ADDR(reginfo, c_mp->htab),
+	    bucket = 0; bucket < c_mp->htab_buckets; ++hp, ++bucket) {
+		MUTEX_LOCK(dbenv, &hp->hash_mutex);
+		if ((bhp =
+		    SH_TAILQ_FIRST(&hp->hash_bucket, __bh)) != NULL) {
+			__db_msgadd(dbenv, &mb, "bucket %lu: %lu, ",
+			    (u_long)bucket, (u_long)hp->hash_priority);
+			__db_print_mutex(
+			    dbenv, &mb, &hp->hash_mutex, ":", flags);
+			DB_MSGBUF_FLUSH(dbenv, &mb);
 		}
-	}
+		for (; bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, hq, __bh))
+			__memp_print_bh(dbenv, dbmp, bhp, fmap, flags);
 
-	/* Dump the memory pool. */
-	if (LF_ISSET(MPOOL_DUMP_MEM))
-		__db_shalloc_dump(reginfo->addr, fp);
+		MUTEX_UNLOCK(dbenv, &hp->hash_mutex);
+	}
 }
 
 /*
- * __memp_pbh --
+ * __memp_print_bh --
  *	Display a BH structure.
  */
 static void
-__memp_pbh(dbmp, bhp, fmap, fp)
+__memp_print_bh(dbenv, dbmp, bhp, fmap, flags)
+	DB_ENV *dbenv;
 	DB_MPOOL *dbmp;
 	BH *bhp;
-	size_t *fmap;
-	FILE *fp;
+	roff_t *fmap;
+	u_int32_t flags;
 {
 	static const FN fn[] = {
 		{ BH_CALLPGIN,		"callpgin" },
@@ -413,50 +642,29 @@ __memp_pbh(dbmp, bhp, fmap, fp)
 		{ BH_TRASH,		"trash" },
 		{ 0,			NULL }
 	};
+	DB_MSGBUF mb;
 	int i;
 
+	DB_MSGBUF_INIT(&mb);
+
 	for (i = 0; i < FMAP_ENTRIES; ++i)
 		if (fmap[i] == INVALID_ROFF || fmap[i] == bhp->mf_offset)
 			break;
 
 	if (fmap[i] == INVALID_ROFF)
-		(void)fprintf(fp, "\t%5lu, %lu, %2lu, %8lu [%lu,%lu] %lu",
-		    (u_long)bhp->pgno, (u_long)bhp->mf_offset,
-		    (u_long)bhp->ref, (u_long)R_OFFSET(dbmp->reginfo, bhp),
-		    (u_long)LSN(bhp->buf).file, (u_long)LSN(bhp->buf).offset,
-		    (u_long)bhp->priority);
+		__db_msgadd(dbenv, &mb, "\t%5lu, %lu, ",
+		    (u_long)bhp->pgno, (u_long)bhp->mf_offset);
 	else
-		(void)fprintf(fp, "\t%5lu,   #%d,  %2lu, %8lu [%lu,%lu] %lu",
-		    (u_long)bhp->pgno, i + 1,
-		    (u_long)bhp->ref, (u_long)R_OFFSET(dbmp->reginfo, bhp),
-		    (u_long)LSN(bhp->buf).file, (u_long)LSN(bhp->buf).offset,
-		    (u_long)bhp->priority);
-
-	__db_prflags(bhp->flags, fn, fp);
-
-	(void)fprintf(fp, "\n");
-}
-
-/*
- * __memp_stat_hash --
- *	Total hash bucket stats (other than mutex wait) into the region.
- *
- * PUBLIC: void __memp_stat_hash __P((REGINFO *, MPOOL *, u_int32_t *));
- */
-void
-__memp_stat_hash(reginfo, mp, dirtyp)
-	REGINFO *reginfo;
-	MPOOL *mp;
-	u_int32_t *dirtyp;
-{
-	DB_MPOOL_HASH *hp;
-	u_int32_t dirty;
-	int i;
-
-	hp = R_ADDR(reginfo, mp->htab);
-	for (i = 0, dirty = 0; i < mp->htab_buckets; i++, hp++)
-		dirty += hp->hash_page_dirty;
-	*dirtyp = dirty;
+		__db_msgadd(
+		    dbenv, &mb, "\t%5lu, #%d, ", (u_long)bhp->pgno, i + 1);
+
+	__db_msgadd(dbenv, &mb, "%2lu, %lu/%lu, ", (u_long)bhp->ref,
+	    (u_long)LSN(bhp->buf).file, (u_long)LSN(bhp->buf).offset);
+	__db_print_mutex(dbenv, &mb, &bhp->mutex, ", ", flags);
+	__db_msgadd(dbenv, &mb, "%#08lx, %lu",
+	    (u_long)R_OFFSET(dbmp->reginfo, bhp), (u_long)bhp->priority);
+	__db_prflags(dbenv, &mb, bhp->flags, fn, " (", ")");
+	DB_MSGBUF_FLUSH(dbenv, &mb);
 }
 
 /*
@@ -468,11 +676,11 @@ __memp_stat_wait(reginfo, mp, mstat, flags)
 	REGINFO *reginfo;
 	MPOOL *mp;
 	DB_MPOOL_STAT *mstat;
-	int flags;
+	u_int32_t flags;
 {
 	DB_MPOOL_HASH *hp;
 	DB_MUTEX *mutexp;
-	int i;
+	u_int32_t i;
 
 	mstat->st_hash_max_wait = 0;
 	hp = R_ADDR(reginfo, mp->htab);
@@ -483,9 +691,55 @@ __memp_stat_wait(reginfo, mp, mstat, flags)
 		if (mutexp->mutex_set_wait > mstat->st_hash_max_wait)
 			mstat->st_hash_max_wait = mutexp->mutex_set_wait;
 
-		if (LF_ISSET(DB_STAT_CLEAR)) {
-			mutexp->mutex_set_wait = 0;
-			mutexp->mutex_set_nowait = 0;
-		}
+		if (LF_ISSET(DB_STAT_CLEAR))
+			MUTEX_CLEAR(mutexp);
 	}
 }
+
+#else /* !HAVE_STATISTICS */
+
+int
+__memp_stat_pp(dbenv, gspp, fspp, flags)
+	DB_ENV *dbenv;
+	DB_MPOOL_STAT **gspp;
+	DB_MPOOL_FSTAT ***fspp;
+	u_int32_t flags;
+{
+	COMPQUIET(gspp, NULL);
+	COMPQUIET(fspp, NULL);
+	COMPQUIET(flags, 0);
+
+	return (__db_stat_not_built(dbenv));
+}
+
+int
+__memp_stat_print_pp(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	COMPQUIET(flags, 0);
+
+	return (__db_stat_not_built(dbenv));
+}
+#endif
+
+/*
+ * __memp_stat_hash --
+ *	Total hash bucket stats (other than mutex wait) into the region.
+ *
+ * PUBLIC: void __memp_stat_hash __P((REGINFO *, MPOOL *, u_int32_t *));
+ */
+void
+__memp_stat_hash(reginfo, mp, dirtyp)
+	REGINFO *reginfo;
+	MPOOL *mp;
+	u_int32_t *dirtyp;
+{
+	DB_MPOOL_HASH *hp;
+	u_int32_t dirty, i;
+
+	hp = R_ADDR(reginfo, mp->htab);
+	for (i = 0, dirty = 0; i < mp->htab_buckets; i++, hp++)
+		dirty += hp->hash_page_dirty;
+	*dirtyp = dirty;
+}
diff --git a/storage/bdb/mp/mp_sync.c b/storage/bdb/mp/mp_sync.c
index 03b42208b395507e06898b9d892a11f81251d64d..6aadab2c1319f49573f947574be48a231da46610 100644
--- a/storage/bdb/mp/mp_sync.c
+++ b/storage/bdb/mp/mp_sync.c
@@ -1,14 +1,13 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: mp_sync.c,v 11.98 2004/10/15 16:59:43 bostic Exp $
  */
-#include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: mp_sync.c,v 11.64 2002/08/25 16:00:27 bostic Exp $";
-#endif /* not lint */
+#include "db_config.h"
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
@@ -18,6 +17,7 @@ static const char revid[] = "$Id: mp_sync.c,v 11.64 2002/08/25 16:00:27 bostic E
 
 #include "db_int.h"
 #include "dbinc/db_shash.h"
+#include "dbinc/log.h"
 #include "dbinc/mp.h"
 
 typedef struct {
@@ -28,23 +28,21 @@ typedef struct {
 } BH_TRACK;
 
 static int __bhcmp __P((const void *, const void *));
-static int __memp_close_flush_files __P((DB_ENV *, DB_MPOOL *));
+static int __memp_close_flush_files __P((DB_ENV *, DB_MPOOL *, int));
 static int __memp_sync_files __P((DB_ENV *, DB_MPOOL *));
 
 /*
- * __memp_sync --
- *	Mpool sync function.
+ * __memp_sync_pp --
+ *	DB_ENV->memp_sync pre/post processing.
  *
- * PUBLIC: int __memp_sync __P((DB_ENV *, DB_LSN *));
+ * PUBLIC: int __memp_sync_pp __P((DB_ENV *, DB_LSN *));
  */
 int
-__memp_sync(dbenv, lsnp)
+__memp_sync_pp(dbenv, lsnp)
 	DB_ENV *dbenv;
 	DB_LSN *lsnp;
 {
-	DB_MPOOL *dbmp;
-	MPOOL *mp;
-	int ret;
+	int rep_check, ret;
 
 	PANIC_CHECK(dbenv);
 	ENV_REQUIRES_CONFIG(dbenv,
@@ -58,6 +56,30 @@ __memp_sync(dbenv, lsnp)
 		ENV_REQUIRES_CONFIG(dbenv,
 		    dbenv->lg_handle, "memp_sync", DB_INIT_LOG);
 
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __memp_sync(dbenv, lsnp);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
+/*
+ * __memp_sync --
+ *	DB_ENV->memp_sync.
+ *
+ * PUBLIC: int __memp_sync __P((DB_ENV *, DB_LSN *));
+ */
+int
+__memp_sync(dbenv, lsnp)
+	DB_ENV *dbenv;
+	DB_LSN *lsnp;
+{
+	DB_MPOOL *dbmp;
+	MPOOL *mp;
+	int ret;
+
 	dbmp = dbenv->mp_handle;
 	mp = dbmp->reginfo[0].primary;
 
@@ -87,35 +109,62 @@ __memp_sync(dbenv, lsnp)
 }
 
 /*
- * __memp_fsync --
- *	Mpool file sync function.
+ * __memp_fsync_pp --
+ *	DB_MPOOLFILE->sync pre/post processing.
  *
- * PUBLIC: int __memp_fsync __P((DB_MPOOLFILE *));
+ * PUBLIC: int __memp_fsync_pp __P((DB_MPOOLFILE *));
  */
 int
-__memp_fsync(dbmfp)
+__memp_fsync_pp(dbmfp)
 	DB_MPOOLFILE *dbmfp;
 {
 	DB_ENV *dbenv;
-	DB_MPOOL *dbmp;
+	int rep_check, ret;
 
-	dbmp = dbmfp->dbmp;
-	dbenv = dbmp->dbenv;
+	dbenv = dbmfp->dbenv;
 
 	PANIC_CHECK(dbenv);
+	MPF_ILLEGAL_BEFORE_OPEN(dbmfp, "DB_MPOOLFILE->sync");
+
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __memp_fsync(dbmfp);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
+/*
+ * __memp_fsync --
+ *	DB_MPOOLFILE->sync.
+ *
+ * PUBLIC: int __memp_fsync __P((DB_MPOOLFILE *));
+ */
+int
+__memp_fsync(dbmfp)
+	DB_MPOOLFILE *dbmfp;
+{
+	MPOOLFILE *mfp;
+
+	mfp = dbmfp->mfp;
 
 	/*
 	 * If this handle doesn't have a file descriptor that's open for
-	 * writing, or if the file is a temporary, there's no reason to
-	 * proceed further.
+	 * writing, or if the file is a temporary, or if the file hasn't
+	 * been written since it was flushed, there's no reason to proceed
+	 * further.
 	 */
 	if (F_ISSET(dbmfp, MP_READONLY))
 		return (0);
 
-	if (F_ISSET(dbmfp->mfp, MP_TEMP))
+	if (F_ISSET(mfp, MP_TEMP))
 		return (0);
 
-	return (__memp_sync_int(dbenv, dbmfp, 0, DB_SYNC_FILE, NULL));
+	if (mfp->file_written == 0)
+		return (0);
+
+	return (__memp_sync_int(dbmfp->dbenv, dbmfp, 0, DB_SYNC_FILE, NULL));
 }
 
 /*
@@ -129,7 +178,6 @@ __mp_xxx_fh(dbmfp, fhp)
 	DB_MPOOLFILE *dbmfp;
 	DB_FH **fhp;
 {
-	DB_ENV *dbenv;
 	/*
 	 * This is a truly spectacular layering violation, intended ONLY to
 	 * support compatibility for the DB 1.85 DB->fd call.
@@ -144,26 +192,24 @@ __mp_xxx_fh(dbmfp, fhp)
 	 * because we want to write to the backing file regardless so that
 	 * we get a file descriptor to return.
 	 */
-	*fhp = dbmfp->fhp;
-	if (F_ISSET(dbmfp->fhp, DB_FH_VALID))
+	if ((*fhp = dbmfp->fhp) != NULL)
 		return (0);
-	dbenv = dbmfp->dbmp->dbenv;
 
-	return (__memp_sync_int(dbenv, dbmfp, 0, DB_SYNC_FILE, NULL));
+	return (__memp_sync_int(dbmfp->dbenv, dbmfp, 0, DB_SYNC_FILE, NULL));
 }
 
 /*
  * __memp_sync_int --
  *	Mpool sync internal function.
  *
- * PUBLIC: int __memp_sync_int
- * PUBLIC:     __P((DB_ENV *, DB_MPOOLFILE *, int, db_sync_op, int *));
+ * PUBLIC: int __memp_sync_int __P((DB_ENV *,
+ * PUBLIC:     DB_MPOOLFILE *, u_int32_t, db_sync_op, u_int32_t *));
  */
 int
-__memp_sync_int(dbenv, dbmfp, ar_max, op, wrotep)
+__memp_sync_int(dbenv, dbmfp, trickle_max, op, wrotep)
 	DB_ENV *dbenv;
 	DB_MPOOLFILE *dbmfp;
-	int ar_max, *wrotep;
+	u_int32_t trickle_max, *wrotep;
 	db_sync_op op;
 {
 	BH *bhp;
@@ -173,20 +219,25 @@ __memp_sync_int(dbenv, dbmfp, ar_max, op, wrotep)
 	DB_MUTEX *mutexp;
 	MPOOL *c_mp, *mp;
 	MPOOLFILE *mfp;
-	u_int32_t n_cache;
-	int ar_cnt, hb_lock, i, pass, remaining, ret, t_ret, wait_cnt, wrote;
+	roff_t last_mf_offset;
+	u_int32_t ar_cnt, ar_max, i, n_cache, remaining, wrote;
+	int filecnt, hb_lock, maxopenfd, maxwrite, maxwrite_sleep;
+	int pass, ret, t_ret, wait_cnt, write_cnt;
 
 	dbmp = dbenv->mp_handle;
 	mp = dbmp->reginfo[0].primary;
-	pass = wrote = 0;
+	last_mf_offset = INVALID_ROFF;
+	filecnt = pass = wrote = 0;
 
-	/*
-	 * If the caller does not specify how many pages assume one
-	 * per bucket.
-	 */
-	if (ar_max == 0)
-		ar_max = mp->nreg * mp->htab_buckets;
+	/* Get shared configuration information. */
+	R_LOCK(dbenv, dbmp->reginfo);
+	maxopenfd = mp->mp_maxopenfd;
+	maxwrite = mp->mp_maxwrite;
+	maxwrite_sleep = mp->mp_maxwrite_sleep;
+	R_UNLOCK(dbenv, dbmp->reginfo);
 
+	/* Assume one dirty page per bucket. */
+	ar_max = mp->nreg * mp->htab_buckets;
 	if ((ret =
 	    __os_malloc(dbenv, ar_max * sizeof(BH_TRACK), &bharray)) != 0)
 		return (ret);
@@ -265,6 +316,12 @@ __memp_sync_int(dbenv, dbmfp, ar_max, op, wrotep)
 				bharray[ar_cnt].track_off = bhp->mf_offset;
 				ar_cnt++;
 
+				/*
+				 * If we run out of space, double and continue.
+				 * Don't stop at trickle_max, we want to sort
+				 * as large a sample set as possible in order
+				 * to minimize disk seeks.
+				 */
 				if (ar_cnt >= ar_max) {
 					if ((ret = __os_realloc(dbenv,
 					    (ar_max * 2) * sizeof(BH_TRACK),
@@ -294,12 +351,10 @@ __memp_sync_int(dbenv, dbmfp, ar_max, op, wrotep)
 
 	/*
 	 * If we're trickling buffers, only write enough to reach the correct
-	 * percentage for this region.  We may not write enough if the dirty
-	 * buffers have an unbalanced distribution among the regions, but that
-	 * seems unlikely.
+	 * percentage.
 	 */
-	 if (op == DB_SYNC_TRICKLE && ar_cnt > ar_max / (int)mp->nreg)
-		ar_cnt = ar_max / (int)mp->nreg;
+	if (op == DB_SYNC_TRICKLE && ar_cnt > trickle_max)
+		ar_cnt = trickle_max;
 
 	/*
 	 * Flush the log.  We have to ensure the log records reflecting the
@@ -309,7 +364,7 @@ __memp_sync_int(dbenv, dbmfp, ar_max, op, wrotep)
 	 * flushed the log), but in general this will at least avoid any I/O
 	 * on the log's part.
 	 */
-	if (LOGGING_ON(dbenv) && (ret = dbenv->log_flush(dbenv, NULL)) != 0)
+	if (LOGGING_ON(dbenv) && (ret = __log_flush(dbenv, NULL)) != 0)
 		goto err;
 
 	/*
@@ -317,7 +372,7 @@ __memp_sync_int(dbenv, dbmfp, ar_max, op, wrotep)
 	 * out its hash bucket pointer so we don't process a slot more than
 	 * once.
 	 */
-	for (remaining = ar_cnt, i = pass = 0; remaining > 0; ++i) {
+	for (i = pass = write_cnt = 0, remaining = ar_cnt; remaining > 0; ++i) {
 		if (i >= ar_cnt) {
 			i = 0;
 			++pass;
@@ -402,6 +457,20 @@ __memp_sync_int(dbenv, dbmfp, ar_max, op, wrotep)
 		MUTEX_LOCK(dbenv, mutexp);
 		hb_lock = 1;
 
+		/*
+		 * If we've switched files, check to see if we're configured
+		 * to close file descriptors.
+		 */
+		if (maxopenfd != 0 && bhp->mf_offset != last_mf_offset) {
+			if (++filecnt >= maxopenfd) {
+				filecnt = 0;
+				if ((ret = __memp_close_flush_files(
+				    dbenv, dbmp, 1)) != 0)
+					break;
+			}
+			last_mf_offset = bhp->mf_offset;
+		}
+
 		/*
 		 * If the ref_sync count has gone to 0, we're going to be done
 		 * with this buffer no matter what happens.
@@ -414,10 +483,6 @@ __memp_sync_int(dbenv, dbmfp, ar_max, op, wrotep)
 		/*
 		 * If the ref_sync count has gone to 0 and the buffer is still
 		 * dirty, we write it.  We only try to write the buffer once.
-		 * Any process checkpointing or trickle-flushing the pool
-		 * must be able to write any underlying file -- if the write
-		 * fails, error out.  It would be very strange if file sync
-		 * failed to write, but we don't care if it happens.
 		 */
 		if (bhp->ref_sync == 0 && F_ISSET(bhp, BH_DIRTY)) {
 			hb_lock = 0;
@@ -426,11 +491,18 @@ __memp_sync_int(dbenv, dbmfp, ar_max, op, wrotep)
 			mfp = R_ADDR(dbmp->reginfo, bhp->mf_offset);
 			if ((ret = __memp_bhwrite(dbmp, hp, mfp, bhp, 1)) == 0)
 				++wrote;
-			else if (op == DB_SYNC_CACHE || op == DB_SYNC_TRICKLE)
+			else
 				__db_err(dbenv, "%s: unable to flush page: %lu",
 				    __memp_fns(dbmp, mfp), (u_long)bhp->pgno);
-			else
-				ret = 0;
+
+			/*
+			 * Avoid saturating the disk, sleep once we've done
+			 * some number of writes.
+			 */
+			if (maxwrite != 0 && ++write_cnt >= maxwrite) {
+				write_cnt = 0;
+				__os_sleep(dbenv, 0, (u_long)maxwrite_sleep);
+			}
 		}
 
 		/*
@@ -471,11 +543,7 @@ __memp_sync_int(dbenv, dbmfp, ar_max, op, wrotep)
 			break;
 	}
 
-done:	/* If we've opened files to flush pages, close them. */
-	if ((t_ret = __memp_close_flush_files(dbenv, dbmp)) != 0 && ret == 0)
-		ret = t_ret;
-
-	/*
+done:	/*
 	 * If doing a checkpoint or flushing a file for the application, we
 	 * have to force the pages to disk.  We don't do this as we go along
 	 * because we want to give the OS as much time as possible to lazily
@@ -489,6 +557,10 @@ done:	/* If we've opened files to flush pages, close them. */
 			ret = __os_fsync(dbenv, dbmfp->fhp);
 	}
 
+	/* If we've opened files to flush pages, close them. */
+	if ((t_ret = __memp_close_flush_files(dbenv, dbmp, 0)) != 0 && ret == 0)
+		ret = t_ret;
+
 err:	__os_free(dbenv, bharray);
 	if (wrotep != NULL)
 		*wrotep = wrote;
@@ -508,54 +580,104 @@ int __memp_sync_files(dbenv, dbmp)
 	DB_MPOOLFILE *dbmfp;
 	MPOOL *mp;
 	MPOOLFILE *mfp;
-	int ret, t_ret;
+	int final_ret, ret;
 
-	ret = 0;
+	final_ret = 0;
 	mp = dbmp->reginfo[0].primary;
 
 	R_LOCK(dbenv, dbmp->reginfo);
 	for (mfp = SH_TAILQ_FIRST(&mp->mpfq, __mpoolfile);
 	    mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) {
-		if (mfp->stat.st_page_out == 0 ||
-		    F_ISSET(mfp, MP_DEADFILE | MP_TEMP))
+		if (!mfp->file_written ||
+		    mfp->deadfile || F_ISSET(mfp, MP_TEMP))
 			continue;
 
-		/* Look for an already open handle. */
+		/*
+		 * Look for an already open, writeable handle (fsync doesn't
+		 * work on read-only Windows handles).
+		 */
 		ret = 0;
 		MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);
 		for (dbmfp = TAILQ_FIRST(&dbmp->dbmfq);
-		    dbmfp != NULL; dbmfp = TAILQ_NEXT(dbmfp, q))
-			if (dbmfp->mfp == mfp) {
-				ret = __os_fsync(dbenv, dbmfp->fhp);
-				break;
-			}
+		    dbmfp != NULL; dbmfp = TAILQ_NEXT(dbmfp, q)) {
+			if (dbmfp->mfp != mfp || F_ISSET(dbmfp, MP_READONLY))
+				continue;
+			ret = __os_fsync(dbenv, dbmfp->fhp);
+			break;
+		}
 		MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
-		if (ret != 0)
-			goto err;
 
 		/* If we don't find one, open one. */
-		if (dbmfp == NULL) {
-			if ((ret = dbenv->memp_fcreate(dbenv, &dbmfp, 0)) != 0)
-				goto err;
-			ret = __memp_fopen_int(
-			    dbmfp, mfp, R_ADDR(dbmp->reginfo, mfp->path_off),
-			    0, 0, mfp->stat.st_pagesize);
-			if (ret == 0)
-				ret = __os_fsync(dbenv, dbmfp->fhp);
-			if ((t_ret =
-			    __memp_fclose_int(dbmfp, 0)) != 0 && ret == 0)
-				ret = t_ret;
-			if (ret != 0)
-				goto err;
+		if (dbmfp == NULL)
+			ret = __memp_mf_sync(dbmp, mfp);
+		if (ret != 0) {
+			__db_err(dbenv, "%s: unable to flush: %s",
+			    (char *)R_ADDR(dbmp->reginfo, mfp->path_off),
+			    db_strerror(ret));
+			if (final_ret == 0)
+				final_ret = ret;
+			continue;
 		}
-	}
 
-	if (0) {
-err:		__db_err(dbenv, "%s: cannot sync: %s",
-		    R_ADDR(dbmp->reginfo, mfp->path_off), db_strerror(ret));
+		/*
+		 * If we wrote the file and there are no open handles (or there
+		 * is a single open handle, and it's the one we opened to write
+		 * buffers during checkpoint), clear the file_written flag.  We
+		 * do this so that applications opening thousands of files don't
+		 * loop here opening and flushing those files during checkpoint.
+		 *
+		 * The danger here is if a buffer were to be written as part of
+		 * a checkpoint, and then not be flushed to disk.  This cannot
+		 * happen because we only clear file_written when there are no
+		 * other users of the MPOOLFILE in the system, and, as we hold
+		 * the region lock, no possibility of another thread of control
+		 * racing with us to open a MPOOLFILE.
+		 */
+		if (mfp->mpf_cnt == 0 || (mfp->mpf_cnt == 1 &&
+		    dbmfp != NULL && F_ISSET(dbmfp, MP_FLUSH)))
+			mfp->file_written = 0;
 	}
 	R_UNLOCK(dbenv, dbmp->reginfo);
 
+	return (final_ret);
+}
+
+/*
+ * __memp_mf_sync --
+ *	 Flush an MPOOLFILE.
+ *
+ *	Should only be used when the file is not already open in this process.
+ *
+ * PUBLIC: int __memp_mf_sync __P((DB_MPOOL *, MPOOLFILE *));
+ */
+int
+__memp_mf_sync(dbmp, mfp)
+	DB_MPOOL *dbmp;
+	MPOOLFILE *mfp;
+{
+	DB_ENV *dbenv;
+	DB_FH *fhp;
+	int ret, t_ret;
+	char *rpath;
+
+	dbenv = dbmp->dbenv;
+
+	/*
+	 * Expects caller to be holding the region lock: we're using the path
+	 * name and __memp_nameop might try and rename the file.
+	 */
+	if ((ret = __db_appname(dbenv, DB_APP_DATA,
+	    R_ADDR(dbmp->reginfo, mfp->path_off), 0, NULL,
+	    &rpath)) == 0) {
+		if ((ret = __os_open(dbenv, rpath, 0, 0, &fhp)) == 0) {
+			ret = __os_fsync(dbenv, fhp);
+			if ((t_ret =
+			    __os_closehandle(dbenv, fhp)) != 0 && ret == 0)
+				ret = t_ret;
+		}
+		__os_free(dbenv, rpath);
+	}
+
 	return (ret);
 }
 
@@ -564,11 +686,13 @@ err:		__db_err(dbenv, "%s: cannot sync: %s",
  *	Close files opened only to flush buffers.
  */
 static int
-__memp_close_flush_files(dbenv, dbmp)
+__memp_close_flush_files(dbenv, dbmp, dosync)
 	DB_ENV *dbenv;
 	DB_MPOOL *dbmp;
+	int dosync;
 {
 	DB_MPOOLFILE *dbmfp;
+	MPOOLFILE *mfp;
 	int ret;
 
 	/*
@@ -576,7 +700,7 @@ __memp_close_flush_files(dbenv, dbmp)
 	 * flush buffers.  There are two cases: first, extent files have to
 	 * be closed so they may be removed when empty.  Second, regular
 	 * files have to be closed so we don't run out of descriptors (for
-	 * example, and application partitioning its data into databases
+	 * example, an application partitioning its data into databases
 	 * based on timestamps, so there's a continually increasing set of
 	 * files).
 	 *
@@ -590,7 +714,23 @@ retry:	MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);
 		if (F_ISSET(dbmfp, MP_FLUSH)) {
 			F_CLR(dbmfp, MP_FLUSH);
 			MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);
-			if ((ret = __memp_fclose_int(dbmfp, 0)) != 0)
+			if (dosync) {
+				if ((ret = __os_fsync(dbenv, dbmfp->fhp)) != 0)
+					return (ret);
+				/*
+				 * If the file is clean and we have the only
+				 * open handle on the file, clear the dirty
+				 * flag so we don't re-open and sync it again.
+				 */
+				mfp = dbmfp->mfp;
+				if (mfp->mpf_cnt == 1) {
+					R_LOCK(dbenv, dbmp->reginfo);
+					if (mfp->mpf_cnt == 1)
+						mfp->file_written = 0;
+					R_UNLOCK(dbenv, dbmp->reginfo);
+				}
+			}
+			if ((ret = __memp_fclose(dbmfp, 0)) != 0)
 				return (ret);
 			goto retry;
 		}
diff --git a/storage/bdb/mp/mp_trickle.c b/storage/bdb/mp/mp_trickle.c
index 71077ab60cc34e5a41adf34fd87022dd55eb6fae..fc346890494696167a2d3168e3625bec999f5e11 100644
--- a/storage/bdb/mp/mp_trickle.c
+++ b/storage/bdb/mp/mp_trickle.c
@@ -1,14 +1,13 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: mp_trickle.c,v 11.35 2004/10/15 16:59:43 bostic Exp $
  */
-#include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: mp_trickle.c,v 11.24 2002/08/06 06:13:53 bostic Exp $";
-#endif /* not lint */
+#include "db_config.h"
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
@@ -18,28 +17,51 @@ static const char revid[] = "$Id: mp_trickle.c,v 11.24 2002/08/06 06:13:53 bosti
 
 #include "db_int.h"
 #include "dbinc/db_shash.h"
+#include "dbinc/log.h"
 #include "dbinc/mp.h"
 
+static int __memp_trickle __P((DB_ENV *, int, int *));
+
 /*
- * __memp_trickle --
- *	Keep a specified percentage of the buffers clean.
+ * __memp_trickle_pp --
+ *	DB_ENV->memp_trickle pre/post processing.
  *
- * PUBLIC: int __memp_trickle __P((DB_ENV *, int, int *));
+ * PUBLIC: int __memp_trickle_pp __P((DB_ENV *, int, int *));
  */
 int
-__memp_trickle(dbenv, pct, nwrotep)
+__memp_trickle_pp(dbenv, pct, nwrotep)
 	DB_ENV *dbenv;
 	int pct, *nwrotep;
 {
-	DB_MPOOL *dbmp;
-	MPOOL *c_mp, *mp;
-	u_int32_t clean, dirty, i, total, dtmp;
-	int ret, wrote;
+	int rep_check, ret;
 
 	PANIC_CHECK(dbenv);
 	ENV_REQUIRES_CONFIG(dbenv,
 	    dbenv->mp_handle, "memp_trickle", DB_INIT_MPOOL);
 
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __memp_trickle(dbenv, pct, nwrotep);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
+/*
+ * __memp_trickle --
+ *	DB_ENV->memp_trickle.
+ */
+static int
+__memp_trickle(dbenv, pct, nwrotep)
+	DB_ENV *dbenv;
+	int pct, *nwrotep;
+{
+	DB_MPOOL *dbmp;
+	MPOOL *c_mp, *mp;
+	u_int32_t dirty, i, total, dtmp, wrote;
+	int n, ret;
+
 	dbmp = dbenv->mp_handle;
 	mp = dbmp->reginfo[0].primary;
 
@@ -68,16 +90,19 @@ __memp_trickle(dbenv, pct, nwrotep)
 		dirty += dtmp;
 	}
 
-	clean = total - dirty;
-	if (clean == total || (clean * 100) / total >= (u_long)pct)
+	/*
+	 * !!!
+	 * Be careful in modifying this calculation, total may be 0.
+	 */
+	n = ((total * (u_int)pct) / 100) - (total - dirty);
+	if (dirty == 0 || n <= 0)
 		return (0);
 
-	if (nwrotep == NULL)
-		nwrotep = &wrote;
-	ret = __memp_sync_int(dbenv, NULL,
-	    ((total * pct) / 100) - clean, DB_SYNC_TRICKLE, nwrotep);
-
-	mp->stat.st_page_trickle += *nwrotep;
+	ret = __memp_sync_int(
+	    dbenv, NULL, (u_int32_t)n, DB_SYNC_TRICKLE, &wrote);
+	mp->stat.st_page_trickle += wrote;
+	if (nwrotep != NULL)
+		*nwrotep = (int)wrote;
 
 	return (ret);
 }
diff --git a/storage/bdb/mutex/mut_fcntl.c b/storage/bdb/mutex/mut_fcntl.c
index 2fdf9eff7efa66eed1d287ec7ac50c5847452871..03521bd77b9a3cd87752e3f62f0afed708810ecc 100644
--- a/storage/bdb/mutex/mut_fcntl.c
+++ b/storage/bdb/mutex/mut_fcntl.c
@@ -1,23 +1,21 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: mut_fcntl.c,v 11.26 2004/01/28 03:36:18 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: mut_fcntl.c,v 11.21 2002/05/31 19:37:45 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
+#include <unistd.h>				/* SEEK_SET on SunOS. */
 #endif
 
 #include "db_int.h"
@@ -37,7 +35,7 @@ __db_fcntl_mutex_init(dbenv, mutexp, offset)
 	u_int32_t save;
 
 	/*
-	 * The only setting/checking of the MUTEX_MPOOL flags is in the mutex
+	 * The only setting/checking of the MUTEX_MPOOL flag is in the mutex
 	 * mutex allocation code (__db_mutex_alloc/free).  Preserve only that
 	 * flag.  This is safe because even if this flag was never explicitly
 	 * set, but happened to be set in memory, it will never be checked or
diff --git a/storage/bdb/mutex/mut_pthread.c b/storage/bdb/mutex/mut_pthread.c
index 4a55ce0ca0306587945cadf881dc6d7577012085..6507eba733045648adbd4f2290b1c51dd7c36942 100644
--- a/storage/bdb/mutex/mut_pthread.c
+++ b/storage/bdb/mutex/mut_pthread.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: mut_pthread.c,v 11.62 2004/09/22 16:27:05 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: mut_pthread.c,v 11.53 2002/08/13 19:56:47 sue Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -31,26 +29,29 @@ static const char revid[] = "$Id: mut_pthread.c,v 11.53 2002/08/13 19:56:47 sue
 #endif
 
 #ifdef HAVE_MUTEX_SOLARIS_LWP
+#define	pthread_cond_destroy(x)		0
 #define	pthread_cond_signal		_lwp_cond_signal
 #define	pthread_cond_wait		_lwp_cond_wait
+#define	pthread_mutex_destroy(x)	0
 #define	pthread_mutex_lock		_lwp_mutex_lock
 #define	pthread_mutex_trylock		_lwp_mutex_trylock
 #define	pthread_mutex_unlock		_lwp_mutex_unlock
 /*
+ * !!!
  * _lwp_self returns the LWP process ID which isn't a unique per-thread
  * identifier.  Use pthread_self instead, it appears to work even if we
  * are not a pthreads application.
  */
-#define	pthread_mutex_destroy(x)	0
 #endif
 #ifdef HAVE_MUTEX_UI_THREADS
+#define	pthread_cond_destroy(x)		cond_destroy
 #define	pthread_cond_signal		cond_signal
 #define	pthread_cond_wait		cond_wait
+#define	pthread_mutex_destroy		mutex_destroy
 #define	pthread_mutex_lock		mutex_lock
 #define	pthread_mutex_trylock		mutex_trylock
 #define	pthread_mutex_unlock		mutex_unlock
 #define	pthread_self			thr_self
-#define	pthread_mutex_destroy		mutex_destroy
 #endif
 
 #define	PTHREAD_UNLOCK_ATTEMPTS	5
@@ -73,7 +74,7 @@ __db_pthread_mutex_init(dbenv, mutexp, flags)
 	ret = 0;
 
 	/*
-	 * The only setting/checking of the MUTEX_MPOOL flags is in the mutex
+	 * The only setting/checking of the MUTEX_MPOOL flag is in the mutex
 	 * mutex allocation code (__db_mutex_alloc/free).  Preserve only that
 	 * flag.  This is safe because even if this flag was never explicitly
 	 * set, but happened to be set in memory, it will never be checked or
@@ -184,7 +185,6 @@ __db_pthread_mutex_init(dbenv, mutexp, flags)
 	}}
 #endif
 
-	mutexp->spins = __os_spin(dbenv);
 #ifdef HAVE_MUTEX_SYSTEM_RESOURCES
 	mutexp->reg_off = INVALID_ROFF;
 #endif
@@ -215,7 +215,7 @@ __db_pthread_mutex_lock(dbenv, mutexp)
 		return (0);
 
 	/* Attempt to acquire the resource for N spins. */
-	for (nspins = mutexp->spins; nspins > 0; --nspins)
+	for (nspins = dbenv->tas_spins; nspins > 0; --nspins)
 		if (pthread_mutex_trylock(&mutexp->mutex) == 0)
 			break;
 
@@ -271,11 +271,11 @@ __db_pthread_mutex_lock(dbenv, mutexp)
 		if (ret != 0)
 			goto err;
 	} else {
-		if (nspins == mutexp->spins)
+		if (nspins == dbenv->tas_spins)
 			++mutexp->mutex_set_nowait;
 		else if (nspins > 0) {
 			++mutexp->mutex_set_spin;
-			mutexp->mutex_set_spins += mutexp->spins - nspins;
+			mutexp->mutex_set_spins += dbenv->tas_spins - nspins;
 		} else
 			++mutexp->mutex_set_wait;
 #ifdef DIAGNOSTIC
@@ -350,12 +350,19 @@ int
 __db_pthread_mutex_destroy(mutexp)
 	DB_MUTEX *mutexp;
 {
-	int ret;
+	int ret, t_ret;
 
 	if (F_ISSET(mutexp, MUTEX_IGNORE))
 		return (0);
 
-	if ((ret = pthread_mutex_destroy(&mutexp->mutex)) != 0)
-		__db_err(NULL, "unable to destroy mutex: %s", strerror(ret));
+	ret = 0;
+	if (F_ISSET(mutexp, MUTEX_SELF_BLOCK) &&
+	    (ret = pthread_cond_destroy(&mutexp->cond)) != 0)
+		__db_err(NULL, "unable to destroy cond: %s", strerror(ret));
+	if ((t_ret = pthread_mutex_destroy(&mutexp->mutex)) != 0) {
+		__db_err(NULL, "unable to destroy mutex: %s", strerror(t_ret));
+		if (ret == 0)
+			ret = t_ret;
+	}
 	return (ret);
 }
diff --git a/storage/bdb/mutex/mut_tas.c b/storage/bdb/mutex/mut_tas.c
index c24e09473cae0805df249863552a65c267cc5526..08d7ed876c6fc582f4110369ee546da900b2ed64 100644
--- a/storage/bdb/mutex/mut_tas.c
+++ b/storage/bdb/mutex/mut_tas.c
@@ -1,22 +1,19 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: mut_tas.c,v 11.44 2004/09/15 19:14:49 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: mut_tas.c,v 11.32 2002/05/07 18:42:21 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 #endif
 
 /*
@@ -40,10 +37,14 @@ __db_tas_mutex_init(dbenv, mutexp, flags)
 	u_int32_t save;
 
 	/* Check alignment. */
-	DB_ASSERT(((db_alignp_t)mutexp & (MUTEX_ALIGN - 1)) == 0);
+	if ((uintptr_t)mutexp & (MUTEX_ALIGN - 1)) {
+		__db_err(dbenv,
+		    "__db_tas_mutex_init: mutex not appropriately aligned");
+		return (EINVAL);
+	}
 
 	/*
-	 * The only setting/checking of the MUTEX_MPOOL flags is in the mutex
+	 * The only setting/checking of the MUTEX_MPOOL flag is in the mutex
 	 * mutex allocation code (__db_mutex_alloc/free).  Preserve only that
 	 * flag.  This is safe because even if this flag was never explicitly
 	 * set, but happened to be set in memory, it will never be checked or
@@ -68,11 +69,13 @@ __db_tas_mutex_init(dbenv, mutexp, flags)
 		}
 	}
 
+	if (LF_ISSET(MUTEX_LOGICAL_LOCK))
+		F_SET(mutexp, MUTEX_LOGICAL_LOCK);
+
 	/* Initialize the lock. */
 	if (MUTEX_INIT(&mutexp->tas))
 		return (__os_get_errno());
 
-	mutexp->spins = __os_spin(dbenv);
 #ifdef HAVE_MUTEX_SYSTEM_RESOURCES
 	mutexp->reg_off = INVALID_ROFF;
 #endif
@@ -92,21 +95,48 @@ __db_tas_mutex_lock(dbenv, mutexp)
 	DB_ENV *dbenv;
 	DB_MUTEX *mutexp;
 {
-	u_long ms;
-	int nspins;
+	u_int32_t nspins;
+	u_long ms, max_ms;
 
 	if (F_ISSET(dbenv, DB_ENV_NOLOCKING) || F_ISSET(mutexp, MUTEX_IGNORE))
 		return (0);
 
+	/*
+	 * Wait 1ms initially, up to 10ms for mutexes backing logical database
+	 * locks, and up to 25 ms for mutual exclusion data structure mutexes.
+	 * SR: #7675
+	 */
 	ms = 1;
+	max_ms = F_ISSET(mutexp, MUTEX_LOGICAL_LOCK) ? 10 : 25;
 
 loop:	/* Attempt to acquire the resource for N spins. */
-	for (nspins = mutexp->spins; nspins > 0; --nspins) {
+	for (nspins = dbenv->tas_spins; nspins > 0; --nspins) {
 #ifdef HAVE_MUTEX_HPPA_MSEM_INIT
 relock:
 #endif
-		if (!MUTEX_SET(&mutexp->tas))
+#ifdef HAVE_MUTEX_S390_CC_ASSEMBLY
+		tsl_t zero = 0;
+#endif
+		if (
+#ifdef MUTEX_SET_TEST
+		/*
+		 * If using test-and-set mutexes, and we know the "set" value,
+		 * we can avoid interlocked instructions since they're unlikely
+		 * to succeed.
+		 */
+		mutexp->tas ||
+#endif
+		!MUTEX_SET(&mutexp->tas)) {
+			/*
+			 * Some systems (notably those with newer Intel CPUs)
+			 * need a small pause here. [#6975]
+			 */
+#ifdef MUTEX_PAUSE
+			MUTEX_PAUSE
+#endif
 			continue;
+		}
+
 #ifdef HAVE_MUTEX_HPPA_MSEM_INIT
 		/*
 		 * HP semaphores are unlocked automatically when a holding
@@ -144,10 +174,12 @@ relock:
 		return (0);
 	}
 
-	/* Yield the processor; wait 1ms initially, up to 1 second. */
+	/*
+	 * Yield the processor.
+	 */
 	__os_yield(NULL, ms * USEC_PER_MS);
-	if ((ms <<= 1) > MS_PER_SEC)
-		ms = MS_PER_SEC;
+	if ((ms <<= 1) > max_ms)
+		ms = max_ms;
 
 	goto loop;
 }
diff --git a/storage/bdb/mutex/mut_win32.c b/storage/bdb/mutex/mut_win32.c
index 49eb20a6ecfbad95dda75627f673c0bf711baefa..b510003211e429ad2d9cbe84f8dcf9eb68ba4f70 100644
--- a/storage/bdb/mutex/mut_win32.c
+++ b/storage/bdb/mutex/mut_win32.c
@@ -1,21 +1,18 @@
 /*
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2002
+ * Copyright (c) 2002-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: mut_win32.c,v 1.18 2004/07/06 21:06:39 mjc Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: mut_win32.c,v 1.8 2002/09/10 02:37:25 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <string.h>
-#include <unistd.h>
 #endif
 
 /*
@@ -27,26 +24,20 @@ static const char revid[] = "$Id: mut_win32.c,v 1.8 2002/09/10 02:37:25 bostic E
 /* We don't want to run this code even in "ordinary" diagnostic mode. */
 #undef MUTEX_DIAG
 
+static _TCHAR hex_digits[] = _T("0123456789abcdef");
+
 #define	GET_HANDLE(mutexp, event) do {					\
-	char idbuf[13];							\
+	_TCHAR idbuf[] = _T("db.m00000000");				\
+	_TCHAR *p = idbuf + 12;						\
+	u_int32_t id;							\
 									\
-	if (F_ISSET(mutexp, MUTEX_THREAD)) {				\
-		event = mutexp->event;					\
-		return (0);						\
-	}								\
-									\
-	snprintf(idbuf, sizeof idbuf, "db.m%08x", mutexp->id);		\
+	for (id = (mutexp)->id; id != 0; id >>= 4)			\
+		*--p = hex_digits[id & 0xf];				\
 	event = CreateEvent(NULL, FALSE, FALSE, idbuf);			\
 	if (event == NULL)						\
-		return (__os_win32_errno());				\
+		return (__os_get_errno());				\
 } while (0)
 
-#define	RELEASE_HANDLE(mutexp, event)					\
-	if (!F_ISSET(mutexp, MUTEX_THREAD) && event != NULL) {		\
-		CloseHandle(event);					\
-		event = NULL;						\
-	}
-
 /*
  * __db_win32_mutex_init --
  *	Initialize a DB_MUTEX.
@@ -62,7 +53,7 @@ __db_win32_mutex_init(dbenv, mutexp, flags)
 	u_int32_t save;
 
 	/*
-	 * The only setting/checking of the MUTEX_MPOOL flags is in the mutex
+	 * The only setting/checking of the MUTEX_MPOOL flag is in the mutex
 	 * mutex allocation code (__db_mutex_alloc/free).  Preserve only that
 	 * flag.  This is safe because even if this flag was never explicitly
 	 * set, but happened to be set in memory, it will never be checked or
@@ -74,27 +65,18 @@ __db_win32_mutex_init(dbenv, mutexp, flags)
 
 	/*
 	 * If this is a thread lock or the process has told us that there are
-	 * no other processes in the environment, use thread-only locks, they
-	 * are faster in some cases.
-	 *
-	 * This is where we decide to ignore locks we don't need to set -- if
-	 * the application isn't threaded, there aren't any threads to block.
+	 * no other processes in the environment, and the application isn't
+	 * threaded, there aren't any threads to block.
 	 */
 	if (LF_ISSET(MUTEX_THREAD) || F_ISSET(dbenv, DB_ENV_PRIVATE)) {
 		if (!F_ISSET(dbenv, DB_ENV_THREAD)) {
 			F_SET(mutexp, MUTEX_IGNORE);
 			return (0);
 		}
-		F_SET(mutexp, MUTEX_THREAD);
-		mutexp->event = CreateEvent(NULL, FALSE, FALSE, NULL);
-		if (mutexp->event == NULL)
-			return (__os_win32_errno());
-	} else
-		mutexp->id = ((getpid() & 0xffff) << 16) ^ P_TO_UINT32(mutexp);
-
-	mutexp->spins = __os_spin(dbenv);
-	F_SET(mutexp, MUTEX_INITED);
+	}
 
+	mutexp->id = ((getpid() & 0xffff) << 16) ^ P_TO_UINT32(mutexp);
+	F_SET(mutexp, MUTEX_INITED);
 	return (0);
 }
 
@@ -110,7 +92,8 @@ __db_win32_mutex_lock(dbenv, mutexp)
 	DB_MUTEX *mutexp;
 {
 	HANDLE event;
-	int ret, ms, nspins;
+	u_int32_t nspins;
+	int ret, ms;
 #ifdef MUTEX_DIAG
 	LARGE_INTEGER now;
 #endif
@@ -123,9 +106,17 @@ __db_win32_mutex_lock(dbenv, mutexp)
 	ret = 0;
 
 loop:	/* Attempt to acquire the resource for N spins. */
-	for (nspins = mutexp->spins; nspins > 0; --nspins) {
-		if (!MUTEX_SET(&mutexp->tas))
+	for (nspins = dbenv->tas_spins; nspins > 0; --nspins) {
+		if (!MUTEX_SET(&mutexp->tas)) {
+			/*
+			 * Some systems (notably those with newer Intel CPUs)
+			 * need a small pause here. [#6975]
+			 */
+#ifdef MUTEX_PAUSE
+			MUTEX_PAUSE
+#endif
 			continue;
+		}
 
 #ifdef DIAGNOSTIC
 		if (mutexp->locked)
@@ -139,7 +130,7 @@ loop:	/* Attempt to acquire the resource for N spins. */
 			++mutexp->mutex_set_nowait;
 		else {
 			++mutexp->mutex_set_wait;
-			RELEASE_HANDLE(mutexp, event);
+			CloseHandle(event);
 			InterlockedDecrement(&mutexp->nwaiters);
 #ifdef MUTEX_DIAG
 			if (ret != WAIT_OBJECT_0) {
@@ -170,7 +161,7 @@ loop:	/* Attempt to acquire the resource for N spins. */
 		GET_HANDLE(mutexp, event);
 	}
 	if ((ret = WaitForSingleObject(event, ms)) == WAIT_FAILED)
-		return (__os_win32_errno());
+		return (__os_get_errno());
 	if ((ms <<= 1) > MS_PER_SEC)
 		ms = MS_PER_SEC;
 
@@ -207,7 +198,7 @@ __db_win32_mutex_unlock(dbenv, mutexp)
 	MUTEX_UNSET(&mutexp->tas);
 
 	ret = 0;
-	
+
 	if (mutexp->nwaiters > 0) {
 		GET_HANDLE(mutexp, event);
 
@@ -217,9 +208,9 @@ __db_win32_mutex_unlock(dbenv, mutexp)
 		    now.QuadPart, mutexp, mutexp->id);
 #endif
 		if (!PulseEvent(event))
-			ret = __os_win32_errno();
+			ret = __os_get_errno();
 
-		RELEASE_HANDLE(mutexp, event);
+		CloseHandle(event);
 	}
 
 #ifdef DIAGNOSTIC
@@ -233,7 +224,7 @@ __db_win32_mutex_unlock(dbenv, mutexp)
 
 /*
  * __db_win32_mutex_destroy --
- *	Destroy a DB_MUTEX.
+ *	Destroy a DB_MUTEX - noop with this implementation.
  *
  * PUBLIC: int __db_win32_mutex_destroy __P((DB_MUTEX *));
  */
@@ -241,17 +232,5 @@ int
 __db_win32_mutex_destroy(mutexp)
 	DB_MUTEX *mutexp;
 {
-	int ret;
-
-	if (F_ISSET(mutexp, MUTEX_IGNORE) || !F_ISSET(mutexp, MUTEX_THREAD))
-		return (0);
-
-	ret = 0;
-	if (mutexp->event != NULL) {
-		if (!CloseHandle(mutexp->event))
-			ret = __os_win32_errno();
-		mutexp->event = NULL;
-	}
-
-	return (ret);
+	return (0);
 }
diff --git a/storage/bdb/mutex/mutex.c b/storage/bdb/mutex/mutex.c
index 5418764a889a450db5620893659f0e8e9c859c2c..9d925d11365b126fb3302a3f91c9fb9c207acd9c 100644
--- a/storage/bdb/mutex/mutex.c
+++ b/storage/bdb/mutex/mutex.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: mutex.c,v 11.43 2004/10/15 16:59:44 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: mutex.c,v 11.37 2002/05/31 19:37:46 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -75,7 +73,7 @@ __db_mutex_setup(dbenv, infop, ptr, flags)
 	/*
 	 * Set up to initialize the mutex.
 	 */
-	iflags = LF_ISSET(MUTEX_THREAD | MUTEX_SELF_BLOCK);
+	iflags = LF_ISSET(MUTEX_LOGICAL_LOCK | MUTEX_THREAD | MUTEX_SELF_BLOCK);
 	switch (infop->type) {
 	case REGION_TYPE_LOCK:
 		offset = P_TO_UINT32(mutex) + DB_FCNTL_OFF_LOCK;
@@ -132,7 +130,7 @@ __db_mutex_alloc_int(dbenv, infop, storep)
 	 * we can free buffers until memory is available.
 	 */
 #if	defined(MUTEX_NO_MALLOC_LOCKS) || defined(HAVE_MUTEX_SYSTEM_RESOURCES)
-	ret = __db_shalloc(infop->addr, sizeof(DB_MUTEX), MUTEX_ALIGN, storep);
+	ret = __db_shalloc(infop, sizeof(DB_MUTEX), MUTEX_ALIGN, storep);
 
 	if (ret == ENOMEM && MPOOL_ON(dbenv)) {
 		DB_MPOOL *dbmp;
@@ -176,10 +174,10 @@ __db_mutex_free(dbenv, infop, mutexp)
 
 		dbmp = dbenv->mp_handle;
 		R_LOCK(dbenv, dbmp->reginfo);
-		__db_shalloc_free(dbmp->reginfo[0].addr, mutexp);
+		__db_shalloc_free(&dbmp->reginfo[0], mutexp);
 		R_UNLOCK(dbenv, dbmp->reginfo);
 	} else
-		__db_shalloc_free(infop->addr, mutexp);
+		__db_shalloc_free(infop, mutexp);
 	R_UNLOCK(dbenv, infop);
 #else
 	COMPQUIET(dbenv, NULL);
@@ -290,8 +288,7 @@ __db_shreg_locks_destroy(infop, rp)
 	for (i = 0; i < rp->reglocks; i++)
 		if (rp->regmutexes[i] != 0) {
 			rp->stat.st_destroys++;
-			__db_mutex_destroy((DB_MUTEX *)R_ADDR(infop,
-			    rp->regmutexes[i]));
+			__db_mutex_destroy(R_ADDR(infop, rp->regmutexes[i]));
 		}
 }
 
@@ -372,8 +369,8 @@ __db_mutex_maint(dbenv, infop)
 
 	switch (infop->type) {
 	case REGION_TYPE_LOCK:
-		moff = ((DB_LOCKREGION *)R_ADDR(infop,
-		    infop->rp->primary))->maint_off;
+		moff = ((DB_LOCKREGION *)
+		    R_ADDR(infop, infop->rp->primary))->maint_off;
 		break;
 	case REGION_TYPE_LOG:
 		moff = ((LOG *)R_ADDR(infop, infop->rp->primary))->maint_off;
@@ -382,8 +379,8 @@ __db_mutex_maint(dbenv, infop)
 		moff = ((MPOOL *)R_ADDR(infop, infop->rp->primary))->maint_off;
 		break;
 	case REGION_TYPE_TXN:
-		moff = ((DB_TXNREGION *)R_ADDR(infop,
-		    infop->rp->primary))->maint_off;
+		moff = ((DB_TXNREGION *)
+		    R_ADDR(infop, infop->rp->primary))->maint_off;
 		break;
 	default:
 		__db_err(dbenv,
diff --git a/storage/bdb/mutex/tm.c b/storage/bdb/mutex/tm.c
index 4af1b1907a85d7aab4e090822277a860112672e6..ebfb2f3290fdd4a8ba35c3bfd0428fcc2398cd9c 100644
--- a/storage/bdb/mutex/tm.c
+++ b/storage/bdb/mutex/tm.c
@@ -15,52 +15,70 @@
 #include <string.h>
 #include <unistd.h>
 
-#if defined(HAVE_MUTEX_PTHREADS) || defined(BUILD_PTHREADS_ANYWAY)
+#if defined(MUTEX_THREAD_TEST)
 #include <pthread.h>
 #endif
 
 #include "db_int.h"
 
-void  exec_proc();
-void  tm_file_init();
-void  map_file();
-void  run_proc();
-void *run_thread();
-void *run_thread_wake();
-void  tm_mutex_destroy();
-void  tm_mutex_init();
-void  tm_mutex_stats();
-void  unmap_file();
+#ifndef	HAVE_QNX
+#define	shm_open	open
+#define	shm_unlink	remove
+#endif
 
-#define	MUTEX_WAKEME	0x80			/* Wake-me flag. */
+void  exec_proc(u_long, char *, char *);
+void  map_file(u_int8_t **, u_int8_t **, u_int8_t **, int *);
+void  tm_file_init(void);
+void  run_locker(u_long);
+void *run_lthread(void *);
+void  run_wakeup(u_long);
+void *run_wthread(void *);
+void  tm_mutex_destroy(void);
+void  tm_mutex_init(void);
+void  tm_mutex_stats(void);
+void  unmap_file(u_int8_t *, int);
+int   usage(void);
+
+#define	MT_FILE		"mutex.file"
+#define	MT_FILE_QUIT	"mutex.file.quit"
 
 DB_ENV	 dbenv;					/* Fake out DB. */
 size_t	 len;					/* Backing file size. */
 int	 align;					/* Mutex alignment in file. */
-int	 quit;					/* End-of-test flag. */
-char	*file = "mutex.file";			/* Backing file. */
 
 int	 maxlocks = 20;				/* -l: Backing locks. */
 int	 nlocks = 10000;			/* -n: Locks per processes. */
 int	 nprocs = 20;				/* -p: Processes. */
-int	 child;					/* -s: Slave. */
 int	 nthreads = 1;				/* -t: Threads. */
 int	 verbose;				/* -v: Verbosity. */
 
+typedef struct {
+	DB_MUTEX mutex;				/* Mutex. */
+	u_long	 id;				/* Holder's ID. */
+#define	MUTEX_WAKEME	0x01			/* Request to awake. */
+	u_int	 flags;
+} TM;
+
 int
 main(argc, argv)
 	int argc;
 	char *argv[];
 {
+	enum {LOCKER, WAKEUP, PARENT} rtype;
 	extern int optind;
 	extern char *optarg;
 	pid_t pid;
-	int ch, eval, i, status;
-	char *tmpath;
+	u_long id;
+	int ch, fd, eval, i, status;
+	char *p, *tmpath;
+
+	__os_spin(&dbenv);		/* Fake out DB. */
 
+	rtype = PARENT;
+	id = 0;
 	tmpath = argv[0];
-	while ((ch = getopt(argc, argv, "l:n:p:st:v")) != EOF)
-		switch(ch) {
+	while ((ch = getopt(argc, argv, "l:n:p:T:t:v")) != EOF)
+		switch (ch) {
 		case 'l':
 			maxlocks = atoi(optarg);
 			break;
@@ -70,78 +88,125 @@ main(argc, argv)
 		case 'p':
 			nprocs = atoi(optarg);
 			break;
-		case 's':
-			child = 1;
-			break;
 		case 't':
-			nthreads = atoi(optarg);
-#if !defined(HAVE_MUTEX_PTHREADS) && !defined(BUILD_PTHREADS_ANYWAY)
+			if ((nthreads = atoi(optarg)) == 0)
+				nthreads = 1;
+#if !defined(MUTEX_THREAD_TEST)
 			if (nthreads != 1) {
 				(void)fprintf(stderr,
-	"tm: pthreads not available or not compiled for this platform.\n");
+    "tm: thread support not available or not compiled for this platform.\n");
 				return (EXIT_FAILURE);
 			}
 #endif
 			break;
+		case 'T':
+			if (!memcmp(optarg, "locker", sizeof("locker") - 1))
+				rtype = LOCKER;
+			else if (
+			    !memcmp(optarg, "wakeup", sizeof("wakeup") - 1))
+				rtype = WAKEUP;
+			else
+				return (usage());
+			if ((p = strchr(optarg, '=')) == NULL)
+				return (usage());
+			id = atoi(p + 1);
+			break;
 		case 'v':
 			verbose = 1;
 			break;
 		case '?':
 		default:
-			(void)fprintf(stderr,
-    "usage: tm [-v] [-l maxlocks] [-n locks] [-p procs] [-t threads]\n");
-			return (EXIT_FAILURE);
+			return (usage());
 		}
 	argc -= optind;
 	argv += optind;
 
 	/*
 	 * The file layout:
-	 *	DB_MUTEX[1]		per-thread mutex array lock
-	 *	DB_MUTEX[nthreads]	per-thread mutex array
-	 *	DB_MUTEX[maxlocks]	per-lock mutex array
-	 *	u_long[maxlocks][2]	per-lock ID array
+	 *	TM[1]			per-thread mutex array lock
+	 *	TM[nthreads]		per-thread mutex array
+	 *	TM[maxlocks]		per-lock mutex array
 	 */
-	align = ALIGN(sizeof(DB_MUTEX) * 2, MUTEX_ALIGN);
-	len =
-	    align * (1 + nthreads +  maxlocks) + sizeof(u_long) * maxlocks * 2;
-	printf(
-    "mutex alignment %d, structure alignment %d, backing file %lu bytes\n",
-	    MUTEX_ALIGN, align, (u_long)len);
-
-	if (child) {
-		run_proc();
+	align = DB_ALIGN(sizeof(TM), MUTEX_ALIGN);
+	len = align * (1 + nthreads * nprocs + maxlocks);
+
+	switch (rtype) {
+	case PARENT:
+		break;
+	case LOCKER:
+		run_locker(id);
+		return (EXIT_SUCCESS);
+	case WAKEUP:
+		run_wakeup(id);
 		return (EXIT_SUCCESS);
 	}
 
-	tm_file_init();
-	tm_mutex_init();
-
 	printf(
-	    "%d proc, %d threads/proc, %d lock requests from %d locks:\n",
+    "tm: %d processes, %d threads/process, %d lock requests from %d locks\n",
 	    nprocs, nthreads, nlocks, maxlocks);
-	for (i = 0; i < nprocs; ++i)
+	printf(
+    "tm: mutex alignment %lu, structure alignment %d, backing file %lu bytes\n",
+	    (u_long)MUTEX_ALIGN, align, (u_long)len);
+
+	tm_file_init();			/* Initialize backing file. */
+	tm_mutex_init();		/* Initialize file's mutexes. */
+
+	for (i = 0; i < nprocs; ++i) {
 		switch (fork()) {
 		case -1:
 			perror("fork");
 			return (EXIT_FAILURE);
 		case 0:
-			exec_proc(tmpath);
+			exec_proc(id, tmpath, "locker");
 			break;
 		default:
 			break;
 		}
+		id += nthreads;
+	}
 
-	eval = EXIT_SUCCESS;
-	while ((pid = wait(&status)) != (pid_t)-1) {
-		fprintf(stderr,
+	(void)remove(MT_FILE_QUIT);
+
+	switch (fork()) {
+	case -1:
+		perror("fork");
+		return (EXIT_FAILURE);
+	case 0:
+		exec_proc(id, tmpath, "wakeup");
+		break;
+	default:
+		break;
+	}
+	++id;
+
+	/* Wait for locking threads. */
+	for (i = 0, eval = EXIT_SUCCESS; i < nprocs; ++i)
+		if ((pid = wait(&status)) != (pid_t)-1) {
+			fprintf(stderr,
 		    "%lu: exited %d\n", (u_long)pid, WEXITSTATUS(status));
+			if (WEXITSTATUS(status) != 0)
+				eval = EXIT_FAILURE;
+		}
+
+	/* Signal wakeup thread to exit. */
+	if ((fd = open(MT_FILE_QUIT, O_WRONLY | O_CREAT, 0664)) == -1) {
+		fprintf(stderr, "tm: %s\n", strerror(errno));
+		status = EXIT_FAILURE;
+	}
+	(void)close(fd);
+
+	/* Wait for wakeup thread. */
+	if ((pid = wait(&status)) != (pid_t)-1) {
+		fprintf(stderr,
+	    "%lu: exited %d\n", (u_long)pid, WEXITSTATUS(status));
 		if (WEXITSTATUS(status) != 0)
 			eval = EXIT_FAILURE;
 	}
 
-	tm_mutex_stats();
-	tm_mutex_destroy();
+	(void)remove(MT_FILE_QUIT);
+
+	tm_mutex_stats();			/* Display run statistics. */
+	tm_mutex_destroy();			/* Destroy region. */
 
 	printf("tm: exit status: %s\n",
 	    eval == EXIT_SUCCESS ? "success" : "failed!");
@@ -149,20 +214,24 @@ main(argc, argv)
 }
 
 void
-exec_proc(tmpath)
-	char *tmpath;
+exec_proc(id, tmpath, typearg)
+	u_long id;
+	char *tmpath, *typearg;
 {
-	char *argv[10], **ap, b_l[10], b_n[10], b_t[10];
+	char *argv[10], **ap, b_l[10], b_n[10], b_p[10], b_t[10], b_T[10];
 
 	ap = &argv[0];
 	*ap++ = "tm";
 	sprintf(b_l, "-l%d", maxlocks);
 	*ap++ = b_l;
 	sprintf(b_n, "-n%d", nlocks);
+	*ap++ = b_p;
+	sprintf(b_p, "-p%d", nprocs);
 	*ap++ = b_n;
-	*ap++ = "-s";
 	sprintf(b_t, "-t%d", nthreads);
 	*ap++ = b_t;
+	sprintf(b_T, "-T%s=%lu", typearg, id);
+	*ap++ = b_T;
 	if (verbose)
 		*ap++ = "-v";
 
@@ -174,21 +243,21 @@ exec_proc(tmpath)
 }
 
 void
-run_proc()
+run_locker(id)
+	u_long id;
 {
-#if defined(HAVE_MUTEX_PTHREADS) || defined(BUILD_PTHREADS_ANYWAY)
-	pthread_t *kidsp, wakep;
-	int i, status;
+#if defined(MUTEX_THREAD_TEST)
+	pthread_t *kidsp;
+	int i;
 	void *retp;
 #endif
-	__os_sleep(&dbenv, 3, 0);		/* Let everyone catch up. */
+	int status;
 
-	srand((u_int)time(NULL) / getpid());	/* Initialize random numbers. */
+	__os_sleep(&dbenv, 3, 0);		/* Let everyone catch up. */
 
-	if (nthreads == 1)			/* Simple case. */
-		exit((int)run_thread((void *)0));
+	srand((u_int)time(NULL) % getpid());	/* Initialize random numbers. */
 
-#if defined(HAVE_MUTEX_PTHREADS) || defined(BUILD_PTHREADS_ANYWAY)
+#if defined(MUTEX_THREAD_TEST)
 	/*
 	 * Spawn off threads.  We have nthreads all locking and going to
 	 * sleep, and one other thread cycling through and waking them up.
@@ -200,89 +269,79 @@ run_proc()
 	}
 	for (i = 0; i < nthreads; i++)
 		if ((errno = pthread_create(
-		    &kidsp[i], NULL, run_thread, (void *)i)) != 0) {
-			fprintf(stderr, "tm: failed spawning thread %d: %s\n",
-			    i, strerror(errno));
+		    &kidsp[i], NULL, run_lthread, (void *)(id + i))) != 0) {
+			fprintf(stderr, "tm: failed spawning thread: %s\n",
+			    strerror(errno));
 			exit(EXIT_FAILURE);
 		}
 
-	if ((errno = pthread_create(
-	    &wakep, NULL, run_thread_wake, (void *)0)) != 0) {
-		fprintf(stderr, "tm: failed spawning wakeup thread: %s\n",
-		    strerror(errno));
-		exit(EXIT_FAILURE);
-	}
-
 	/* Wait for the threads to exit. */
-	status = 0;
+	status = EXIT_SUCCESS;
 	for (i = 0; i < nthreads; i++) {
 		pthread_join(kidsp[i], &retp);
 		if (retp != NULL) {
-			fprintf(stderr,
-			    "tm: thread %d exited with error\n", i);
+			fprintf(stderr, "tm: thread exited with error\n");
 			status = EXIT_FAILURE;
 		}
 	}
 	free(kidsp);
-
-	/* Signal wakeup thread to stop. */
-	quit = 1;
-	pthread_join(wakep, &retp);
-	if (retp != NULL) {
-		fprintf(stderr, "tm: wakeup thread exited with error\n");
-		status = EXIT_FAILURE;
-	}
-
-	exit(status);
+#else
+	status = (int)run_lthread((void *)id);
 #endif
+	exit(status);
 }
 
 void *
-run_thread(arg)
+run_lthread(arg)
 	void *arg;
 {
-	DB_MUTEX *gm_addr, *lm_addr, *tm_addr, *mp;
-	u_long gid1, gid2, *id_addr;
-	int fd, i, lock, id, nl, remap;
+	TM *gp, *mp, *tp;
+	u_long id, tid;
+	int fd, i, lock, nl, remap;
+	u_int8_t *gm_addr, *lm_addr, *tm_addr;
 
-	/* Set local and global per-thread ID. */
 	id = (int)arg;
-	gid1 = (u_long)getpid();
-#if defined(HAVE_MUTEX_PTHREADS) || defined(BUILD_PTHREADS_ANYWAY)
-	gid2 = (u_long)pthread_self();
+#if defined(MUTEX_THREAD_TEST)
+	tid = (u_long)pthread_self();
 #else
-	gid2 = 0;
+	tid = 0;
 #endif
-	printf("\tPID: %lu; TID: %lx; ID: %d\n", gid1, gid2, id);
+	printf("Locker: ID %03lu (PID: %lu; TID: %lx)\n",
+	    id, (u_long)getpid(), tid);
 
 	nl = nlocks;
-	for (gm_addr = NULL, remap = 0;;) {
+	for (gm_addr = NULL, gp = tp = NULL, remap = 0;;) {
 		/* Map in the file as necessary. */
 		if (gm_addr == NULL) {
-			map_file(&gm_addr, &tm_addr, &lm_addr, &id_addr, &fd);
+			map_file(&gm_addr, &tm_addr, &lm_addr, &fd);
+			gp = (TM *)gm_addr;
+			tp = (TM *)(tm_addr + id * align);
+			if (verbose)
+				printf(
+				    "%03lu: map threads @ %#lx; locks @ %#lx\n",
+				    id, (u_long)tm_addr, (u_long)lm_addr);
 			remap = (rand() % 100) + 35;
 		}
 
 		/* Select and acquire a data lock. */
 		lock = rand() % maxlocks;
-		mp = (DB_MUTEX *)((u_int8_t *)lm_addr + lock * align);
+		mp = (TM *)(lm_addr + lock * align);
 		if (verbose)
-			printf("%lu/%lx: %03d\n", gid1, gid2, lock);
+			printf("%03lu: lock %d @ %#lx\n",
+			    id, lock, (u_long)&mp->mutex);
 
-		if (__db_mutex_lock(&dbenv, mp)) {
-			fprintf(stderr,
-			    "%lu/%lx: never got lock\n", gid1, gid2);
+		if (__db_mutex_lock(&dbenv, &mp->mutex)) {
+			fprintf(stderr, "%03lu: never got lock %d: %s\n",
+			    id, lock, strerror(errno));
 			return ((void *)EXIT_FAILURE);
 		}
-		if (id_addr[lock * 2] != 0) {
+		if (mp->id != 0) {
 			fprintf(stderr,
-			    "RACE! (%lu/%lx granted lock %d held by %lu/%lx)\n",
-			    gid1, gid2,
-			    lock, id_addr[lock * 2], id_addr[lock * 2 + 1]);
+			    "RACE! (%03lu granted lock %d held by %03lu)\n",
+			    id, lock, mp->id);
 			return ((void *)EXIT_FAILURE);
 		}
-		id_addr[lock * 2] = gid1;
-		id_addr[lock * 2 + 1] = gid2;
+		mp->id = id;
 
 		/*
 		 * Pretend to do some work, periodically checking to see if
@@ -290,17 +349,14 @@ run_thread(arg)
 		 */
 		for (i = 0; i < 3; ++i) {
 			__os_sleep(&dbenv, 0, rand() % 3);
-			if (id_addr[lock * 2] != gid1 ||
-			    id_addr[lock * 2 + 1] != gid2) {
+			if (mp->id != id) {
 				fprintf(stderr,
-			    "RACE! (%lu/%lx stole lock %d from %lu/%lx)\n",
-				    id_addr[lock * 2],
-				    id_addr[lock * 2 + 1], lock, gid1, gid2);
+				    "RACE! (%03lu stole lock %d from %03lu)\n",
+				    mp->id, lock, id);
 				return ((void *)EXIT_FAILURE);
 			}
 		}
 
-#if defined(HAVE_MUTEX_PTHREADS) || defined(BUILD_PTHREADS_ANYWAY)
 		/*
 		 * Test self-blocking and unlocking by other threads/processes:
 		 *
@@ -311,105 +367,186 @@ run_thread(arg)
 		 *
 		 * The wakeup thread will wake us up.
 		 */
-		if (__db_mutex_lock(&dbenv, gm_addr)) {
-			fprintf(stderr, "%lu/%lx: global lock\n", gid1, gid2);
+		if (__db_mutex_lock(&dbenv, &gp->mutex)) {
+			fprintf(stderr,
+			    "%03lu: global lock: %s\n", id, strerror(errno));
 			return ((void *)EXIT_FAILURE);
 		}
-		mp = (DB_MUTEX *)((u_int8_t *)tm_addr + id * align);
-		F_SET(mp, MUTEX_WAKEME);
-		if (__db_mutex_unlock(&dbenv, gm_addr)) {
+		if (tp->id != 0 && tp->id != id) {
 			fprintf(stderr,
-			    "%lu/%lx: per-thread wakeup failed\n", gid1, gid2);
+		    "%03lu: per-thread mutex isn't mine, owned by %03lu\n",
+			    id, tp->id);
 			return ((void *)EXIT_FAILURE);
 		}
-		if (__db_mutex_lock(&dbenv, mp)) {
+		tp->id = id;
+		if (verbose)
+			printf("%03lu: self-blocking\n", id);
+		if (F_ISSET(tp, MUTEX_WAKEME)) {
 			fprintf(stderr,
-			    "%lu/%lx: per-thread lock\n", gid1, gid2);
+			    "%03lu: wakeup flag incorrectly set\n", id);
+			return ((void *)EXIT_FAILURE);
+		}
+		F_SET(tp, MUTEX_WAKEME);
+		if (__db_mutex_unlock(&dbenv, &gp->mutex)) {
+			fprintf(stderr,
+			    "%03lu: global unlock: %s\n", id, strerror(errno));
+			return ((void *)EXIT_FAILURE);
+		}
+		if (__db_mutex_lock(&dbenv, &tp->mutex)) {
+			fprintf(stderr, "%03lu: per-thread lock: %s\n",
+			    id, strerror(errno));
 			return ((void *)EXIT_FAILURE);
 		}
 		/* Time passes... */
-		if (F_ISSET(mp, MUTEX_WAKEME)) {
-			fprintf(stderr, "%lu/%lx: %03d wakeup flag still set\n",
-			    gid1, gid2, id);
+		if (F_ISSET(tp, MUTEX_WAKEME)) {
+			fprintf(stderr, "%03lu: wakeup flag not cleared\n", id);
 			return ((void *)EXIT_FAILURE);
 		}
-#endif
+
+		if (verbose)
+			printf("%03lu: release %d @ %#lx\n",
+			    id, lock, (u_long)&mp->mutex);
 
 		/* Release the data lock. */
-		id_addr[lock * 2] = id_addr[lock * 2 + 1] = 0;
-		mp = (DB_MUTEX *)((u_int8_t *)lm_addr + lock * align);
-		if (__db_mutex_unlock(&dbenv, mp)) {
-			fprintf(stderr, "%lu/%lx: wakeup failed\n", gid1, gid2);
+		mp->id = 0;
+		if (__db_mutex_unlock(&dbenv, &mp->mutex)) {
+			fprintf(stderr,
+			    "%03lu: lock release: %s\n", id, strerror(errno));
 			return ((void *)EXIT_FAILURE);
 		}
 
 		if (--nl % 100 == 0)
-			fprintf(stderr, "%lu/%lx: %d\n", gid1, gid2, nl);
+			fprintf(stderr, "%03lu: %d\n", id, nl);
 
 		if (nl == 0 || --remap == 0) {
-			unmap_file((void *)gm_addr, fd);
+			if (verbose)
+				printf("%03lu: re-mapping\n", id);
+			unmap_file(gm_addr, fd);
 			gm_addr = NULL;
 
 			if (nl == 0)
 				break;
 
-			__os_sleep(&dbenv, rand() % 3, 0);
+			__os_sleep(&dbenv, 0, rand() % 500);
 		}
 	}
 
 	return (NULL);
 }
 
-#if defined(HAVE_MUTEX_PTHREADS) || defined(BUILD_PTHREADS_ANYWAY)
+void
+run_wakeup(id)
+	u_long id;
+{
+#if defined(MUTEX_THREAD_TEST)
+	pthread_t wakep;
+	int status;
+	void *retp;
+#endif
+	__os_sleep(&dbenv, 3, 0);		/* Let everyone catch up. */
+
+	srand((u_int)time(NULL) % getpid());	/* Initialize random numbers. */
+
+#if defined(MUTEX_THREAD_TEST)
+	/*
+	 * Spawn off wakeup thread.
+	 */
+	if ((errno = pthread_create(
+	    &wakep, NULL, run_wthread, (void *)id)) != 0) {
+		fprintf(stderr, "tm: failed spawning wakeup thread: %s\n",
+		    strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+
+	/*
+	 * run_locker will create a file when the wakeup thread is no
+	 * longer needed.
+	 */
+	status = 0;
+	pthread_join(wakep, &retp);
+	if (retp != NULL) {
+		fprintf(stderr, "tm: wakeup thread exited with error\n");
+		status = EXIT_FAILURE;
+	}
+
+	exit(status);
+#else
+	exit((int)run_wthread((void *)id));
+#endif
+}
+
 /*
- * run_thread_wake --
+ * run_wthread --
  *	Thread to wake up other threads that are sleeping.
  */
 void *
-run_thread_wake(arg)
+run_wthread(arg)
 	void *arg;
 {
-	DB_MUTEX *gm_addr, *tm_addr, *mp;
-	int fd, id;
+	struct stat sb;
+	TM *gp, *tp;
+	u_long id, tid;
+	int fd, check_id;
+	u_int8_t *gm_addr, *tm_addr;
+
+	id = (int)arg;
+#if defined(MUTEX_THREAD_TEST)
+	tid = (u_long)pthread_self();
+#else
+	tid = 0;
+#endif
+	printf("Wakeup: ID %03lu (PID: %lu; TID: %lx)\n",
+	    id, (u_long)getpid(), tid);
 
 	arg = NULL;
-	map_file(&gm_addr, &tm_addr, NULL, NULL, &fd);
+	map_file(&gm_addr, &tm_addr, NULL, &fd);
+	if (verbose)
+		printf("%03lu: map threads @ %#lx\n", id, (u_long)tm_addr);
+	gp = (TM *)gm_addr;
 
 	/* Loop, waking up sleepers and periodically sleeping ourselves. */
-	while (!quit) {
-		id = 0;
+	for (check_id = 0;; ++check_id) {
+		/* Check to see if the locking threads have finished. */
+		if (stat(MT_FILE_QUIT, &sb) == 0)
+			break;
+
+		/* Check for ID wraparound. */
+		if (check_id == nthreads * nprocs)
+			check_id = 0;
+
+		/* Check for a thread that needs a wakeup. */
+		tp = (TM *)(tm_addr + check_id * align);
+		if (!F_ISSET(tp, MUTEX_WAKEME))
+			continue;
+
+		if (verbose)
+			printf("%03lu: wakeup thread %03lu @ %#lx\n",
+			    id, tp->id, (u_long)&tp->mutex);
 
 		/* Acquire the global lock. */
-retry:		if (__db_mutex_lock(&dbenv, gm_addr)) {
-			fprintf(stderr, "wt: global lock failed\n");
+		if (__db_mutex_lock(&dbenv, &gp->mutex)) {
+			fprintf(stderr,
+			    "wakeup: global lock: %s\n", strerror(errno));
 			return ((void *)EXIT_FAILURE);
 		}
 
-next:		mp = (DB_MUTEX *)((u_int8_t *)tm_addr + id * align);
-		if (F_ISSET(mp, MUTEX_WAKEME)) {
-			F_CLR(mp, MUTEX_WAKEME);
-			if (__db_mutex_unlock(&dbenv, mp)) {
-				fprintf(stderr, "wt: wakeup failed\n");
-				return ((void *)EXIT_FAILURE);
-			}
+		F_CLR(tp, MUTEX_WAKEME);
+		if (__db_mutex_unlock(&dbenv, &tp->mutex)) {
+			fprintf(stderr,
+			    "wakeup: unlock: %s\n", strerror(errno));
+			return ((void *)EXIT_FAILURE);
 		}
 
-		if (++id < nthreads && id % 3 != 0)
-			goto next;
-
-		if (__db_mutex_unlock(&dbenv, gm_addr)) {
-			fprintf(stderr, "wt: global unlock failed\n");
+		if (__db_mutex_unlock(&dbenv, &gp->mutex)) {
+			fprintf(stderr,
+			    "wakeup: global unlock: %s\n", strerror(errno));
 			return ((void *)EXIT_FAILURE);
 		}
 
-		__os_sleep(&dbenv, 0, 500);
-
-		if (id < nthreads)
-			goto retry;
+		__os_sleep(&dbenv, 0, rand() % 3);
 	}
 	return (NULL);
 }
-#endif
 
 /*
  * tm_file_init --
@@ -420,24 +557,24 @@ tm_file_init()
 {
 	int fd;
 
-
 	/* Initialize the backing file. */
-	printf("Create the backing file...\n");
-#ifdef	HAVE_QNX
-	(void)shm_unlink(file);
-	if ((fd = shm_open(file, O_CREAT | O_RDWR | O_TRUNC,
-#else
-	(void)remove(file);
-	if ((fd = open(file, O_CREAT | O_RDWR | O_TRUNC,
-#endif
+	if (verbose)
+		printf("Create the backing file.\n");
 
+	(void)shm_unlink(MT_FILE);
+
+	if ((fd = shm_open(
+	    MT_FILE, O_CREAT | O_RDWR | O_TRUNC,
 	    S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) == -1) {
-		(void)fprintf(stderr, "%s: open: %s\n", file, strerror(errno));
+		(void)fprintf(stderr,
+		    "%s: open: %s\n", MT_FILE, strerror(errno));
 		exit(EXIT_FAILURE);
 	}
-	if (lseek(fd, (off_t)len, SEEK_SET) != len || write(fd, &fd, 1) != 1) {
+
+	if (lseek(fd,
+	    (off_t)len, SEEK_SET) != (off_t)len || write(fd, &fd, 1) != 1) {
 		(void)fprintf(stderr,
-		    "%s: seek/write: %s\n", file, strerror(errno));
+		    "%s: seek/write: %s\n", MT_FILE, strerror(errno));
 		exit(EXIT_FAILURE);
 	}
 	(void)close(fd);
@@ -450,44 +587,60 @@ tm_file_init()
 void
 tm_mutex_init()
 {
-	DB_MUTEX *gm_addr, *lm_addr, *mp, *tm_addr;
+	TM *mp;
 	int fd, i;
+	u_int8_t *gm_addr, *lm_addr, *tm_addr;
 
-	map_file(&gm_addr, &tm_addr, &lm_addr, NULL, &fd);
+	map_file(&gm_addr, &tm_addr, &lm_addr, &fd);
+	if (verbose)
+		printf("init: map threads @ %#lx; locks @ %#lx\n",
+		    (u_long)tm_addr, (u_long)lm_addr);
 
-	printf("Initialize the global mutex...\n");
-	if (__db_mutex_init_int(&dbenv, gm_addr, 0, 0)) {
+	if (verbose)
+		printf("Initialize the global mutex:\n");
+	mp = (TM *)gm_addr;
+	if (__db_mutex_init_int(&dbenv, &mp->mutex, 0, 0)) {
 		fprintf(stderr,
 		    "__db_mutex_init (global): %s\n", strerror(errno));
 		exit(EXIT_FAILURE);
 	}
+	if (verbose)
+		printf("\t@ %#lx\n", (u_long)&mp->mutex);
 
-	printf("Initialize the per-thread mutexes...\n");
-	for (i = 1, mp = tm_addr;
-	    i <= nthreads; ++i, mp = (DB_MUTEX *)((u_int8_t *)mp + align)) {
-		if (__db_mutex_init_int(&dbenv, mp, 0, MUTEX_SELF_BLOCK)) {
+	if (verbose)
+		printf(
+		    "Initialize %d per-thread mutexes:\n", nthreads * nprocs);
+	for (i = 0; i < nthreads * nprocs; ++i) {
+		mp = (TM *)(tm_addr + i * align);
+		if (__db_mutex_init_int(
+		    &dbenv, &mp->mutex, 0, MUTEX_SELF_BLOCK)) {
 			fprintf(stderr, "__db_mutex_init (per-thread %d): %s\n",
 			    i, strerror(errno));
 			exit(EXIT_FAILURE);
 		}
-		if (__db_mutex_lock(&dbenv, mp)) {
-			fprintf(stderr,
-			    "__db_mutex_init (per-thread %d) lock: %s\n",
+		if (__db_mutex_lock(&dbenv, &mp->mutex)) {
+			fprintf(stderr, "__db_mutex_lock (per-thread %d): %s\n",
 			    i, strerror(errno));
 			exit(EXIT_FAILURE);
 		}
+		if (verbose)
+			printf("\t@ %#lx\n", (u_long)&mp->mutex);
 	}
 
-	printf("Initialize the per-lock mutexes...\n");
-	for (i = 1, mp = lm_addr;
-	    i <= maxlocks; ++i, mp = (DB_MUTEX *)((u_int8_t *)mp + align))
-		if (__db_mutex_init_int(&dbenv, mp, 0, 0)) {
+	if (verbose)
+		printf("Initialize %d per-lock mutexes:\n", maxlocks);
+	for (i = 0; i < maxlocks; ++i) {
+		mp = (TM *)(lm_addr + i * align);
+		if (__db_mutex_init_int(&dbenv, &mp->mutex, 0, 0)) {
 			fprintf(stderr, "__db_mutex_init (per-lock: %d): %s\n",
 			    i, strerror(errno));
 			exit(EXIT_FAILURE);
 		}
+		if (verbose)
+			printf("\t@ %#lx\n", (u_long)&mp->mutex);
+	}
 
-	unmap_file((void *)gm_addr, fd);
+	unmap_file(gm_addr, fd);
 }
 
 /*
@@ -497,22 +650,26 @@ tm_mutex_init()
 void
 tm_mutex_destroy()
 {
-	DB_MUTEX *gm_addr, *lm_addr, *mp, *tm_addr;
+	TM *gp, *mp;
 	int fd, i;
+	u_int8_t *gm_addr, *lm_addr, *tm_addr;
 
-	map_file(&gm_addr, &tm_addr, &lm_addr, NULL, &fd);
+	map_file(&gm_addr, &tm_addr, &lm_addr, &fd);
 
-	printf("Destroy the global mutex...\n");
-	if (__db_mutex_destroy(gm_addr)) {
+	if (verbose)
+		printf("Destroy the global mutex.\n");
+	gp = (TM *)gm_addr;
+	if (__db_mutex_destroy(&gp->mutex)) {
 		fprintf(stderr,
 		    "__db_mutex_destroy (global): %s\n", strerror(errno));
 		exit(EXIT_FAILURE);
 	}
 
-	printf("Destroy the per-thread mutexes...\n");
-	for (i = 1, mp = tm_addr;
-	    i <= nthreads; ++i, mp = (DB_MUTEX *)((u_int8_t *)mp + align)) {
-		if (__db_mutex_destroy(mp)) {
+	if (verbose)
+		printf("Destroy the per-thread mutexes.\n");
+	for (i = 0; i < nthreads * nprocs; ++i) {
+		mp = (TM *)(tm_addr + i * align);
+		if (__db_mutex_destroy(&mp->mutex)) {
 			fprintf(stderr,
 			    "__db_mutex_destroy (per-thread %d): %s\n",
 			    i, strerror(errno));
@@ -520,20 +677,21 @@ tm_mutex_destroy()
 		}
 	}
 
-	printf("Destroy the per-lock mutexes...\n");
-	for (i = 1, mp = lm_addr;
-	    i <= maxlocks; ++i, mp = (DB_MUTEX *)((u_int8_t *)mp + align))
-		if (__db_mutex_destroy(mp)) {
+	if (verbose)
+		printf("Destroy the per-lock mutexes.\n");
+	for (i = 0; i < maxlocks; ++i) {
+		mp = (TM *)(tm_addr + i * align);
+		if (__db_mutex_destroy(&mp->mutex)) {
 			fprintf(stderr,
 			    "__db_mutex_destroy (per-lock: %d): %s\n",
 			    i, strerror(errno));
 			exit(EXIT_FAILURE);
 		}
+	}
 
-	unmap_file((void *)gm_addr, fd);
-#ifdef HAVE_QNX
-	(void)shm_unlink(file);
-#endif
+	unmap_file(gm_addr, fd);
+
+	(void)shm_unlink(MT_FILE);
 }
 
 /*
@@ -543,18 +701,21 @@ tm_mutex_destroy()
 void
 tm_mutex_stats()
 {
-	DB_MUTEX *gm_addr, *lm_addr, *mp;
+	TM *mp;
 	int fd, i;
+	u_int8_t *gm_addr, *lm_addr;
 
-	map_file(&gm_addr, NULL, &lm_addr, NULL, &fd);
+	map_file(&gm_addr, NULL, &lm_addr, &fd);
 
-	printf("Per-lock mutex statistics...\n");
-	for (i = 1, mp = lm_addr;
-	    i <= maxlocks; ++i, mp = (DB_MUTEX *)((u_int8_t *)mp + align))
+	printf("Per-lock mutex statistics.\n");
+	for (i = 0; i < maxlocks; ++i) {
+		mp = (TM *)(lm_addr + i * align);
 		printf("mutex %2d: wait: %lu; no wait %lu\n", i,
-		    (u_long)mp->mutex_set_wait, (u_long)mp->mutex_set_nowait);
+		    (u_long)mp->mutex.mutex_set_wait,
+		    (u_long)mp->mutex.mutex_set_nowait);
+	}
 
-	unmap_file((void *)gm_addr, fd);
+	unmap_file(gm_addr, fd);
 }
 
 /*
@@ -562,12 +723,11 @@ tm_mutex_stats()
  *	Map in the backing file.
  */
 void
-map_file(gm_addrp, tm_addrp, lm_addrp, id_addrp, fdp)
-	DB_MUTEX **gm_addrp, **tm_addrp, **lm_addrp;
-	u_long **id_addrp;
+map_file(gm_addrp, tm_addrp, lm_addrp, fdp)
+	u_int8_t **gm_addrp, **tm_addrp, **lm_addrp;
 	int *fdp;
 {
-	void *maddr;
+	void *addr;
 	int fd;
 
 #ifndef MAP_FAILED
@@ -576,33 +736,27 @@ map_file(gm_addrp, tm_addrp, lm_addrp, id_addrp, fdp)
 #ifndef MAP_FILE
 #define	MAP_FILE	0
 #endif
-#ifdef	HAVE_QNX
-	if ((fd = shm_open(file, O_RDWR, 0)) == -1) {
-#else
-	if ((fd = open(file, O_RDWR, 0)) == -1) {
-#endif
-		fprintf(stderr, "%s: open %s\n", file, strerror(errno));
+	if ((fd = shm_open(MT_FILE, O_RDWR, 0)) == -1) {
+		fprintf(stderr, "%s: open %s\n", MT_FILE, strerror(errno));
 		exit(EXIT_FAILURE);
 	}
 
-	maddr = mmap(NULL, len,
+	addr = mmap(NULL, len,
 	    PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd, (off_t)0);
-	if (maddr == MAP_FAILED) {
-		fprintf(stderr, "%s: mmap: %s\n", file, strerror(errno));
+	if (addr == MAP_FAILED) {
+		fprintf(stderr, "%s: mmap: %s\n", MT_FILE, strerror(errno));
 		exit(EXIT_FAILURE);
 	}
 
 	if (gm_addrp != NULL)
-		*gm_addrp = (DB_MUTEX *)maddr;
-	maddr = (u_int8_t *)maddr + align;
+		*gm_addrp = (u_int8_t *)addr;
+	addr = (u_int8_t *)addr + align;
 	if (tm_addrp != NULL)
-		*tm_addrp = (DB_MUTEX *)maddr;
-	maddr = (u_int8_t *)maddr + align * nthreads;
+		*tm_addrp = (u_int8_t *)addr;
+	addr = (u_int8_t *)addr + align * (nthreads * nprocs);
 	if (lm_addrp != NULL)
-		*lm_addrp = (DB_MUTEX *)maddr;
-	maddr = (u_int8_t *)maddr + align * maxlocks;
-	if (id_addrp != NULL)
-		*id_addrp = (u_long *)maddr;
+		*lm_addrp = (u_int8_t *)addr;
+
 	if (fdp != NULL)
 		*fdp = fd;
 }
@@ -612,11 +766,11 @@ map_file(gm_addrp, tm_addrp, lm_addrp, id_addrp, fdp)
  *	Discard backing file map.
  */
 void
-unmap_file(maddr, fd)
-	void *maddr;
+unmap_file(addr, fd)
+	u_int8_t *addr;
 	int fd;
 {
-	if (munmap(maddr, len) != 0) {
+	if (munmap(addr, len) != 0) {
 		fprintf(stderr, "munmap: %s\n", strerror(errno));
 		exit(EXIT_FAILURE);
 	}
@@ -625,3 +779,16 @@ unmap_file(maddr, fd)
 		exit(EXIT_FAILURE);
 	}
 }
+
+/*
+ * usage --
+ *
+ */
+int
+usage()
+{
+	(void)fprintf(stderr, "%s\n\t%s\n",
+	    "usage: tm [-v] [-l maxlocks]",
+	    "[-n locks] [-p procs] [-T locker=ID|wakeup=ID] [-t threads]");
+	return (EXIT_FAILURE);
+}
diff --git a/storage/bdb/mutex/uts4_cc.s b/storage/bdb/mutex/uts4_cc.s
index 9ebc45aad5473000ff9a169cb96210efd49c68f9..9b314c4afcadb86f33d69f42d319f4c619e21b06 100644
--- a/storage/bdb/mutex/uts4_cc.s
+++ b/storage/bdb/mutex/uts4_cc.s
@@ -1,9 +1,9 @@
  / See the file LICENSE for redistribution information.
  /
- / Copyright (c) 1997-2002
+ / Copyright (c) 1997-2004
  /	Sleepycat Software.  All rights reserved.
  /
- / $Id: uts4_cc.s,v 11.2 2002/04/25 13:42:14 bostic Exp $
+ / $Id: uts4_cc.s,v 11.4 2004/01/28 03:36:18 bostic Exp $
  /
  / int uts_lock ( int *p, int i );
  /             Update the lock word pointed to by p with the
diff --git a/storage/bdb/os/os_abs.c b/storage/bdb/os/os_abs.c
index cd7d0a5d2beac4d5e3a2bfbbf57337029dc6a08e..3d9f921ae97c97457ad87d4923a5465605070ffa 100644
--- a/storage/bdb/os/os_abs.c
+++ b/storage/bdb/os/os_abs.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_abs.c,v 11.7 2004/01/28 03:36:18 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_abs.c,v 11.5 2002/01/11 15:52:58 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #endif
diff --git a/storage/bdb/os/os_alloc.c b/storage/bdb/os/os_alloc.c
index 5b38cc7d6f19d270e336e0f5f58ceabde4f48e80..7dd9f94f52ed6d1cd5399508adf997f98f4c9998 100644
--- a/storage/bdb/os/os_alloc.c
+++ b/storage/bdb/os/os_alloc.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_alloc.c,v 11.41 2004/07/06 21:06:36 mjc Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_alloc.c,v 11.32 2002/08/06 04:57:07 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -23,7 +21,7 @@ static const char revid[] = "$Id: os_alloc.c,v 11.32 2002/08/06 04:57:07 bostic
 #ifdef DIAGNOSTIC
 static void __os_guard __P((DB_ENV *));
 
-union __db_alloc {
+union __db_allocinfo {
 	size_t size;
 	double align;
 };
@@ -41,13 +39,6 @@ union __db_alloc {
  * !!!
  * Correct for systems that don't set errno when malloc and friends fail.
  *
- * !!!
- * There is no circumstance in which we can call __os_umalloc, __os_urealloc
- * or __os_ufree without an environment handle, as we need one to determine
- * whether or not to use an application-specified malloc function.  If we
- * don't have an environment handle, we should be calling __os_XXX instead.
- * Make DIAGNOSTIC blow up if we get this wrong.
- *
  *	Out of memory.
  *	We wish to hold the whole sky,
  *	But we never will.
@@ -69,9 +60,6 @@ __os_umalloc(dbenv, size, storep)
 {
 	int ret;
 
-	/* Require an environment handle. */
-	DB_ASSERT(dbenv != NULL);
-
 	/* Never allocate 0 bytes -- some C libraries don't like it. */
 	if (size == 0)
 		++size;
@@ -85,7 +73,7 @@ __os_umalloc(dbenv, size, storep)
 			/*
 			 *  Correct error return, see __os_malloc.
 			 */
-			if ((ret = __os_get_errno()) == 0) {
+			if ((ret = __os_get_errno_ret_zero()) == 0) {
 				ret = ENOMEM;
 				__os_set_errno(ENOMEM);
 			}
@@ -121,9 +109,6 @@ __os_urealloc(dbenv, size, storep)
 
 	ptr = *(void **)storep;
 
-	/* Require an environment handle. */
-	DB_ASSERT(dbenv != NULL);
-
 	/* Never allocate 0 bytes -- some C libraries don't like it. */
 	if (size == 0)
 		++size;
@@ -140,7 +125,7 @@ __os_urealloc(dbenv, size, storep)
 			/*
 			 * Correct errno, see __os_realloc.
 			 */
-			if ((ret = __os_get_errno()) == 0) {
+			if ((ret = __os_get_errno_ret_zero()) == 0) {
 				ret = ENOMEM;
 				__os_set_errno(ENOMEM);
 			}
@@ -164,24 +149,19 @@ __os_urealloc(dbenv, size, storep)
  * __os_ufree --
  *	free(3) counterpart to __os_umalloc.
  *
- * PUBLIC: int __os_ufree __P((DB_ENV *, void *));
+ * PUBLIC: void __os_ufree __P((DB_ENV *, void *));
  */
-int
+void
 __os_ufree(dbenv, ptr)
 	DB_ENV *dbenv;
 	void *ptr;
 {
-	/* Require an environment handle. */
-	DB_ASSERT(dbenv != NULL);
-
 	if (dbenv != NULL && dbenv->db_free != NULL)
 		dbenv->db_free(ptr);
 	else if (DB_GLOBAL(j_free) != NULL)
 		DB_GLOBAL(j_free)(ptr);
 	else
 		free(ptr);
-
-	return (0);
 }
 
 /*
@@ -260,7 +240,7 @@ __os_malloc(dbenv, size, storep)
 
 #ifdef DIAGNOSTIC
 	/* Add room for size and a guard byte. */
-	size += sizeof(union __db_alloc) + 1;
+	size += sizeof(union __db_allocinfo) + 1;
 #endif
 
 	if (DB_GLOBAL(j_malloc) != NULL)
@@ -274,7 +254,7 @@ __os_malloc(dbenv, size, storep)
 		 * but it turns out that setting errno is quite expensive on
 		 * Windows/NT in an MT environment.
 		 */
-		if ((ret = __os_get_errno()) == 0) {
+		if ((ret = __os_get_errno_ret_zero()) == 0) {
 			ret = ENOMEM;
 			__os_set_errno(ENOMEM);
 		}
@@ -284,6 +264,9 @@ __os_malloc(dbenv, size, storep)
 	}
 
 #ifdef DIAGNOSTIC
+	/* Overwrite memory. */
+	memset(p, CLEAR_BYTE, size);
+
 	/*
 	 * Guard bytes: if #DIAGNOSTIC is defined, we allocate an additional
 	 * byte after the memory and set it to a special value that we check
@@ -291,8 +274,8 @@ __os_malloc(dbenv, size, storep)
 	 */
 	((u_int8_t *)p)[size - 1] = CLEAR_BYTE;
 
-	((union __db_alloc *)p)->size = size;
-	p = &((union __db_alloc *)p)[1];
+	((union __db_allocinfo *)p)->size = size;
+	p = &((union __db_allocinfo *)p)[1];
 #endif
 	*(void **)storep = p;
 
@@ -326,10 +309,10 @@ __os_realloc(dbenv, size, storep)
 
 #ifdef DIAGNOSTIC
 	/* Add room for size and a guard byte. */
-	size += sizeof(union __db_alloc) + 1;
+	size += sizeof(union __db_allocinfo) + 1;
 
-	/* Back up to the real begining */
-	ptr = &((union __db_alloc *)ptr)[-1];
+	/* Back up to the real beginning */
+	ptr = &((union __db_allocinfo *)ptr)[-1];
 #endif
 
 	/*
@@ -347,7 +330,7 @@ __os_realloc(dbenv, size, storep)
 		 * but it turns out that setting errno is quite expensive on
 		 * Windows/NT in an MT environment.
 		 */
-		if ((ret = __os_get_errno()) == 0) {
+		if ((ret = __os_get_errno_ret_zero()) == 0) {
 			ret = ENOMEM;
 			__os_set_errno(ENOMEM);
 		}
@@ -358,8 +341,8 @@ __os_realloc(dbenv, size, storep)
 #ifdef DIAGNOSTIC
 	((u_int8_t *)p)[size - 1] = CLEAR_BYTE;	/* Initialize guard byte. */
 
-	((union __db_alloc *)p)->size = size;
-	p = &((union __db_alloc *)p)[1];
+	((union __db_allocinfo *)p)->size = size;
+	p = &((union __db_allocinfo *)p)[1];
 #endif
 
 	*(void **)storep = p;
@@ -379,7 +362,7 @@ __os_free(dbenv, ptr)
 	void *ptr;
 {
 #ifdef DIAGNOSTIC
-	int size;
+	size_t size;
 	/*
 	 * Check that the guard byte (one past the end of the memory) is
 	 * still CLEAR_BYTE.
@@ -387,12 +370,12 @@ __os_free(dbenv, ptr)
 	if (ptr == NULL)
 		return;
 
-	ptr = &((union __db_alloc *)ptr)[-1];
-	size = ((union __db_alloc *)ptr)->size;
+	ptr = &((union __db_allocinfo *)ptr)[-1];
+	size = ((union __db_allocinfo *)ptr)->size;
 	if (((u_int8_t *)ptr)[size - 1] != CLEAR_BYTE)
 		 __os_guard(dbenv);
 
-	/* Clear memory. */
+	/* Overwrite memory. */
 	if (size != 0)
 		memset(ptr, CLEAR_BYTE, size);
 #endif
diff --git a/storage/bdb/os/os_clock.c b/storage/bdb/os/os_clock.c
index 8da02cf6f9c5c8f737d85ca8ba480d9724e31c82..2a8c44d1c245073f11e380f6198d6381354e379d 100644
--- a/storage/bdb/os/os_clock.c
+++ b/storage/bdb/os/os_clock.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
+ * Copyright (c) 2001-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_clock.c,v 1.15 2004/07/06 17:33:14 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_clock.c,v 1.9 2002/03/29 20:46:44 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -34,38 +32,37 @@ static const char revid[] = "$Id: os_clock.c,v 1.9 2002/03/29 20:46:44 bostic Ex
  * __os_clock --
  *	Return the current time-of-day clock in seconds and microseconds.
  *
- * PUBLIC: int __os_clock __P((DB_ENV *, u_int32_t *, u_int32_t *));
+ * PUBLIC: void __os_clock __P((DB_ENV *, u_int32_t *, u_int32_t *));
  */
-int
+void
 __os_clock(dbenv, secsp, usecsp)
 	DB_ENV *dbenv;
 	u_int32_t *secsp, *usecsp;	/* Seconds and microseconds. */
 {
+	const char *sc;
+	int ret;
+
 #if defined(HAVE_GETTIMEOFDAY)
 	struct timeval tp;
-	int ret;
 
-retry:	if (gettimeofday(&tp, NULL) != 0) {
-		if ((ret = __os_get_errno()) == EINTR)
-			goto retry;
-		__db_err(dbenv, "gettimeofday: %s", strerror(ret));
-		return (ret);
+	RETRY_CHK((gettimeofday(&tp, NULL)), ret);
+	if (ret != 0) {
+		sc = "gettimeofday";
+		goto err;
 	}
 
 	if (secsp != NULL)
-		*secsp = tp.tv_sec;
+		*secsp = (u_int32_t)tp.tv_sec;
 	if (usecsp != NULL)
-		*usecsp = tp.tv_usec;
+		*usecsp = (u_int32_t)tp.tv_usec;
 #endif
 #if !defined(HAVE_GETTIMEOFDAY) && defined(HAVE_CLOCK_GETTIME)
 	struct timespec tp;
-	int ret;
 
-retry:	if (clock_gettime(CLOCK_REALTIME, &tp) != 0) {
-		if ((ret = __os_get_errno()) == EINTR)
-			goto retry;
-		__db_err(dbenv, "clock_gettime: %s", strerror(ret));
-		return (ret);
+	RETRY_CHK((clock_gettime(CLOCK_REALTIME, &tp)), ret);
+	if (ret != 0) {
+		sc = "clock_gettime";
+		goto err;
 	}
 
 	if (secsp != NULL)
@@ -75,12 +72,11 @@ retry:	if (clock_gettime(CLOCK_REALTIME, &tp) != 0) {
 #endif
 #if !defined(HAVE_GETTIMEOFDAY) && !defined(HAVE_CLOCK_GETTIME)
 	time_t now;
-	int ret;
 
-	if (time(&now) == (time_t)-1) {
-		ret = __os_get_errno();
-		__db_err(dbenv, "time: %s", strerror(ret));
-		return (ret);
+	RETRY_CHK((time(&now) == (time_t)-1 ? 1 : 0), ret);
+	if (ret != 0) {
+		sc = "time";
+		goto err;
 	}
 
 	if (secsp != NULL)
@@ -88,5 +84,8 @@ retry:	if (clock_gettime(CLOCK_REALTIME, &tp) != 0) {
 	if (usecsp != NULL)
 		*usecsp = 0;
 #endif
-	return (0);
+	return;
+
+err:	__db_err(dbenv, "%s: %s", sc, strerror(ret));
+	(void)__db_panic(dbenv, ret);
 }
diff --git a/storage/bdb/os/os_config.c b/storage/bdb/os/os_config.c
index b64952a83024421aa848d80d6d87c793a2bfa8f9..dcde0dca9db0bb9c21072853c94e0fc6276a8420 100644
--- a/storage/bdb/os/os_config.c
+++ b/storage/bdb/os/os_config.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1998-2002
+ * Copyright (c) 1998-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_config.c,v 11.15 2004/01/28 03:36:18 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_config.c,v 11.13 2002/01/31 19:54:12 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #endif
diff --git a/storage/bdb/os/os_dir.c b/storage/bdb/os/os_dir.c
index 3f59a23d9630caba60302a64c8fe6d77f7c01ea4..3e381ae7f2be40a0325aa57c4ee3e8cf4ebad923 100644
--- a/storage/bdb/os/os_dir.c
+++ b/storage/bdb/os/os_dir.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_dir.c,v 11.17 2004/04/26 18:48:19 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_dir.c,v 11.14 2002/07/12 18:56:50 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -67,7 +65,7 @@ __os_dirlist(dbenv, dir, namesp, cntp)
 		if (cnt >= arraysz) {
 			arraysz += 100;
 			if ((ret = __os_realloc(dbenv,
-			    arraysz * sizeof(names[0]), &names)) != 0)
+			    (u_int)arraysz * sizeof(names[0]), &names)) != 0)
 				goto nomem;
 		}
 		if ((ret = __os_strdup(dbenv, dp->d_name, &names[cnt])) != 0)
diff --git a/storage/bdb/os/os_errno.c b/storage/bdb/os/os_errno.c
index 4b40f88d1773c5a5528042fd7899bc1612f0c364..52bce4ce67b056e33c849e017507d2bcabd8422f 100644
--- a/storage/bdb/os/os_errno.c
+++ b/storage/bdb/os/os_errno.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_errno.c,v 11.11 2004/01/28 03:36:18 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_errno.c,v 11.8 2002/01/11 15:52:59 bostic Exp $";
-#endif /* not lint */
-
 #include "db_int.h"
 
 /*
@@ -60,5 +58,14 @@ void
 __os_set_errno(evalue)
 	int evalue;
 {
-	errno = evalue;
+	/*
+	 * This routine is called by the compatibility interfaces (DB 1.85,
+	 * dbm and hsearch).  Force values > 0, that is, not one of DB 2.X
+	 * and later's public error returns.  If something bad has happened,
+	 * default to EFAULT -- a nasty return.  Otherwise, default to EINVAL.
+	 * As the compatibility APIs aren't included on Windows, the Windows
+	 * version of this routine doesn't need this behavior.
+	 */
+	errno =
+	    evalue >= 0 ? evalue : (evalue == DB_RUNRECOVERY ? EFAULT : EINVAL);
 }
diff --git a/storage/bdb/os/os_fid.c b/storage/bdb/os/os_fid.c
index 125e6f0712ca47bffcd6f7493deb3fe78a4e5578..29f19cd812275a2870839c0508e6b72e4061472b 100644
--- a/storage/bdb/os/os_fid.c
+++ b/storage/bdb/os/os_fid.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_fid.c,v 11.21 2004/07/06 13:55:48 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_fid.c,v 11.14 2002/08/26 14:37:38 margo Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -28,14 +26,10 @@ static const char revid[] = "$Id: os_fid.c,v 11.14 2002/08/26 14:37:38 margo Exp
 
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 #endif
 
 #include "db_int.h"
 
-#define	SERIAL_INIT	0
-static u_int32_t fid_serial = SERIAL_INIT;
-
 /*
  * __os_fileid --
  *	Return a unique identifier for a file.  The structure
@@ -64,37 +58,16 @@ __os_fileid(dbenv, fname, unique_okay, fidp)
 	memset(fidp, 0, DB_FILE_ID_LEN);
 
 	/* On POSIX/UNIX, use a dev/inode pair. */
-retry:
 #ifdef HAVE_VXWORKS
-	if (stat((char *)fname, &sb) != 0) {
+	RETRY_CHK((stat((char *)fname, &sb)), ret);
 #else
-	if (stat(fname, &sb) != 0) {
+	RETRY_CHK((stat(fname, &sb)), ret);
 #endif
-		if ((ret = __os_get_errno()) == EINTR)
-			goto retry;
+	if (ret != 0) {
 		__db_err(dbenv, "%s: %s", fname, strerror(ret));
 		return (ret);
 	}
 
-	/*
-	 * Initialize/increment the serial number we use to help avoid
-	 * fileid collisions.  Note that we don't bother with locking;
-	 * it's unpleasant to do from down in here, and if we race on
-	 * this no real harm will be done, since the finished fileid
-	 * has so many other components.
-	 *
-	 * We increment by 100000 on each call as a simple way of
-	 * randomizing;  simply incrementing seems potentially less useful
-	 * if pids are also simply incremented, since this is process-local
-	 * and we may be one of a set of processes starting up.  100000
-	 * pushes us out of pid space on most platforms, and has few
-	 * interesting properties in base 2.
-	 */
-	if (fid_serial == SERIAL_INIT)
-		__os_id(&fid_serial);
-	else
-		fid_serial += 100000;
-
 	/*
 	 * !!!
 	 * Nothing is ever big enough -- on Sparc V9, st_ino, st_dev and the
@@ -130,17 +103,35 @@ retry:
 		*fidp++ = *p++;
 
 	if (unique_okay) {
-		/*
-		 * We want the number of seconds, not the high-order 0 bits,
-		 * so convert the returned time_t to a (potentially) smaller
-		 * fixed-size type.
-		 */
-		tmp = (u_int32_t)time(NULL);
+		static u_int32_t fid_serial = 0;
+
+		/* Add in 32-bits of (hopefully) unique number. */
+		__os_unique_id(dbenv, &tmp);
 		for (p = (u_int8_t *)&tmp, i = sizeof(u_int32_t); i > 0; --i)
 			*fidp++ = *p++;
 
-		for (p = (u_int8_t *)&fid_serial, i = sizeof(u_int32_t);
-		    i > 0; --i)
+		/*
+		 * Initialize/increment the serial number we use to help
+		 * avoid fileid collisions.  Note we don't bother with
+		 * locking; it's unpleasant to do from down in here, and
+		 * if we race on this no real harm will be done, since the
+		 * finished fileid has so many other components.
+		 *
+		 * We increment by 100000 on each call as a simple way of
+		 * randomizing; simply incrementing seems potentially less
+		 * useful if pids are also simply incremented, since this
+		 * is process-local and we may be one of a set of processes
+		 * starting up.  100000 pushes us out of pid space on most
+		 * 32-bit platforms, and has few interesting properties in
+		 * base 2.
+		 */
+		if (fid_serial == 0)
+			__os_id(&fid_serial);
+		else
+			fid_serial += 100000;
+
+		for (p =
+		    (u_int8_t *)&fid_serial, i = sizeof(u_int32_t); i > 0; --i)
 			*fidp++ = *p++;
 	}
 
diff --git a/storage/bdb/os/os_fsync.c b/storage/bdb/os/os_fsync.c
index 46ab4885a16366e99bf1be6d242b594be0d715ce..576acf00b5f245bb5e6bb7cff2bb60c278aafa24 100644
--- a/storage/bdb/os/os_fsync.c
+++ b/storage/bdb/os/os_fsync.c
@@ -1,22 +1,20 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_fsync.c,v 11.22 2004/07/06 20:54:09 mjc Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_fsync.c,v 11.14 2002/07/12 18:56:50 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <fcntl.h>			/* XXX: Required by __hp3000s900 */
-#include <unistd.h>
 #include <string.h>
+#include <unistd.h>
 #endif
 
 #include "db_int.h"
@@ -24,7 +22,7 @@ static const char revid[] = "$Id: os_fsync.c,v 11.14 2002/07/12 18:56:50 bostic
 #ifdef	HAVE_VXWORKS
 #include "ioLib.h"
 
-#define	fsync(fd)	__vx_fsync(fd);
+#define	fsync(fd)	__vx_fsync(fd)
 
 int
 __vx_fsync(fd)
@@ -44,7 +42,7 @@ __vx_fsync(fd)
 #endif
 
 #ifdef __hp3000s900
-#define	fsync(fd)	__mpe_fsync(fd);
+#define	fsync(fd)	__mpe_fsync(fd)
 
 int
 __mpe_fsync(fd)
@@ -78,10 +76,17 @@ __os_fsync(dbenv, fhp)
 	if (F_ISSET(fhp, DB_FH_NOSYNC))
 		return (0);
 
-	do {
-		ret = DB_GLOBAL(j_fsync) != NULL ?
-		    DB_GLOBAL(j_fsync)(fhp->fd) : fsync(fhp->fd);
-	} while (ret != 0 && (ret = __os_get_errno()) == EINTR);
+	/* Check for illegal usage. */
+	DB_ASSERT(F_ISSET(fhp, DB_FH_OPENED) && fhp->fd != -1);
+
+	if (DB_GLOBAL(j_fsync) != NULL)
+		ret = DB_GLOBAL(j_fsync)(fhp->fd);
+	else
+#ifdef HAVE_FDATASYNC
+		RETRY_CHK((fdatasync(fhp->fd)), ret);
+#else
+		RETRY_CHK((fsync(fhp->fd)), ret);
+#endif
 
 	if (ret != 0)
 		__db_err(dbenv, "fsync %s", strerror(ret));
diff --git a/storage/bdb/os/os_handle.c b/storage/bdb/os/os_handle.c
index 5f617085e5d3a7802b4ce143bd4e58b297e904c7..62a7bc1a151c23a350e39dbc8997f72623a88ee8 100644
--- a/storage/bdb/os/os_handle.c
+++ b/storage/bdb/os/os_handle.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1998-2002
+ * Copyright (c) 1998-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_handle.c,v 11.40 2004/08/19 17:59:22 sue Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_handle.c,v 11.28 2002/07/12 18:56:50 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -25,30 +23,38 @@ static const char revid[] = "$Id: os_handle.c,v 11.28 2002/07/12 18:56:50 bostic
  * __os_openhandle --
  *	Open a file, using POSIX 1003.1 open flags.
  *
- * PUBLIC: int __os_openhandle __P((DB_ENV *, const char *, int, int, DB_FH *));
+ * PUBLIC: int __os_openhandle
+ * PUBLIC:     __P((DB_ENV *, const char *, int, int, DB_FH **));
  */
 int
-__os_openhandle(dbenv, name, flags, mode, fhp)
+__os_openhandle(dbenv, name, flags, mode, fhpp)
 	DB_ENV *dbenv;
 	const char *name;
 	int flags, mode;
-	DB_FH *fhp;
+	DB_FH **fhpp;
 {
-	int ret, nrepeat;
+	DB_FH *fhp;
+	u_int nrepeat, retries;
+	int ret;
 #ifdef HAVE_VXWORKS
 	int newflags;
 #endif
 
-	memset(fhp, 0, sizeof(*fhp));
+	if ((ret = __os_calloc(dbenv, 1, sizeof(DB_FH), fhpp)) != 0)
+		return (ret);
+	fhp = *fhpp;
 
 	/* If the application specified an interface, use it. */
 	if (DB_GLOBAL(j_open) != NULL) {
-		if ((fhp->fd = DB_GLOBAL(j_open)(name, flags, mode)) == -1)
-			return (__os_get_errno());
-		F_SET(fhp, DB_FH_VALID);
+		if ((fhp->fd = DB_GLOBAL(j_open)(name, flags, mode)) == -1) {
+			ret = __os_get_errno();
+			goto err;
+		}
+		F_SET(fhp, DB_FH_OPENED);
 		return (0);
 	}
 
+	retries = 0;
 	for (nrepeat = 1; nrepeat < 4; ++nrepeat) {
 		ret = 0;
 #ifdef	HAVE_VXWORKS
@@ -65,17 +71,23 @@ __os_openhandle(dbenv, name, flags, mode, fhp)
 		if (LF_ISSET(O_CREAT)) {
 			DB_BEGIN_SINGLE_THREAD;
 			newflags = flags & ~(O_CREAT | O_EXCL);
-			if ((fhp->fd =
-			    open(name, newflags, mode)) != -1) {
+			if ((fhp->fd = open(name, newflags, mode)) != -1) {
+				/*
+				 * We need to mark the file opened at this
+				 * point so that if we get any error below
+				 * we will properly close the fd we just
+				 * opened on the error path.
+				 */
+				F_SET(fhp, DB_FH_OPENED);
 				if (LF_ISSET(O_EXCL)) {
 					/*
-					 * If we get here, we want O_EXCL
-					 * create, and it exists.  Close and
+					 * If we get here, want O_EXCL create,
+					 * and the file exists.  Close and
 					 * return EEXISTS.
 					 */
-					(void)close(fhp->fd);
 					DB_END_SINGLE_THREAD;
-					return (EEXIST);
+					ret = EEXIST;
+					goto err;
 				}
 				/*
 				 * XXX
@@ -90,7 +102,6 @@ __os_openhandle(dbenv, name, flags, mode, fhp)
 				fhp->fd = creat(name, newflags);
 			DB_END_SINGLE_THREAD;
 		} else
-
 		/* FALLTHROUGH */
 #endif
 #ifdef __VMS
@@ -107,41 +118,51 @@ __os_openhandle(dbenv, name, flags, mode, fhp)
 #else
 		fhp->fd = open(name, flags, mode);
 #endif
+		if (fhp->fd != -1) {
+			F_SET(fhp, DB_FH_OPENED);
+
+#if defined(HAVE_FCNTL_F_SETFD)
+			/* Deny file descriptor access to any child process. */
+			if (fcntl(fhp->fd, F_SETFD, 1) == -1) {
+				ret = __os_get_errno();
+				__db_err(dbenv,
+				    "fcntl(F_SETFD): %s", strerror(ret));
+				goto err;
+			}
+#endif
+			break;
+		}
 
-		if (fhp->fd == -1) {
+		switch (ret = __os_get_errno()) {
+		case EMFILE:
+		case ENFILE:
+		case ENOSPC:
 			/*
 			 * If it's a "temporary" error, we retry up to 3 times,
 			 * waiting up to 12 seconds.  While it's not a problem
 			 * if we can't open a database, an inability to open a
 			 * log file is cause for serious dismay.
 			 */
-			ret = __os_get_errno();
-			if (ret == ENFILE || ret == EMFILE || ret == ENOSPC) {
-				(void)__os_sleep(dbenv, nrepeat * 2, 0);
-				continue;
-			}
-
+			__os_sleep(dbenv, nrepeat * 2, 0);
+			break;
+		case EAGAIN:
+		case EBUSY:
+		case EINTR:
 			/*
-			 * If it was an EINTR it's reasonable to retry
-			 * immediately, and arbitrarily often.
+			 * If an EAGAIN, EBUSY or EINTR, retry immediately for
+			 * DB_RETRY times.
 			 */
-			if (ret == EINTR) {
+			if (++retries < DB_RETRY)
 				--nrepeat;
-				continue;
-			}
-		} else {
-#if defined(HAVE_FCNTL_F_SETFD)
-			/* Deny file descriptor access to any child process. */
-			if (fcntl(fhp->fd, F_SETFD, FD_CLOEXEC) == -1) {
-				ret = __os_get_errno();
-				__db_err(dbenv, "fcntl(F_SETFD): %s",
-				    strerror(ret));
-				(void)__os_closehandle(dbenv, fhp);
-			} else
-#endif
-				F_SET(fhp, DB_FH_VALID);
+			break;
+		default:
+			break;
 		}
-		break;
+	}
+
+err:	if (ret != 0) {
+		(void)__os_closehandle(dbenv, fhp);
+		*fhpp = NULL;
 	}
 
 	return (ret);
@@ -160,26 +181,29 @@ __os_closehandle(dbenv, fhp)
 {
 	int ret;
 
-	/* Don't close file descriptors that were never opened. */
-	DB_ASSERT(F_ISSET(fhp, DB_FH_VALID) && fhp->fd != -1);
-
-	do {
-		ret = DB_GLOBAL(j_close) != NULL ?
-		    DB_GLOBAL(j_close)(fhp->fd) : close(fhp->fd);
-	} while (ret != 0 && (ret = __os_get_errno()) == EINTR);
-
-	/* Unlink the file if we haven't already done so. */
-	if (F_ISSET(fhp, DB_FH_UNLINK)) {
-		(void)__os_unlink(dbenv, fhp->name);
-		(void)__os_free(dbenv, fhp->name);
-	}
+	ret = 0;
 
 	/*
-	 * Smash the POSIX file descriptor -- it's never tested, but we want
-	 * to catch any mistakes.
+	 * If we have a valid handle, close it and unlink any temporary
+	 * file.
 	 */
-	fhp->fd = -1;
-	F_CLR(fhp, DB_FH_VALID);
+	if (F_ISSET(fhp, DB_FH_OPENED)) {
+		if (DB_GLOBAL(j_close) != NULL)
+			ret = DB_GLOBAL(j_close)(fhp->fd);
+		else
+			RETRY_CHK((close(fhp->fd)), ret);
+
+		if (ret != 0)
+			__db_err(dbenv, "close: %s", strerror(ret));
+
+		/* Unlink the file if we haven't already done so. */
+		if (F_ISSET(fhp, DB_FH_UNLINK)) {
+			(void)__os_unlink(dbenv, fhp->name);
+			__os_free(dbenv, fhp->name);
+		}
+	}
+
+	__os_free(dbenv, fhp);
 
 	return (ret);
 }
diff --git a/storage/bdb/os/os_id.c b/storage/bdb/os/os_id.c
index c242bb12e23bdb1aaf181ac1bef666469259788b..79df12f9b0fe25c44dd8085d7ed4f9fdac77ec83 100644
--- a/storage/bdb/os/os_id.c
+++ b/storage/bdb/os/os_id.c
@@ -1,19 +1,18 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
+ * Copyright (c) 2001-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_id.c,v 1.9 2004/09/22 16:27:54 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_id.c,v 1.2 2002/01/11 15:52:59 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
+#include <stdlib.h>
 #include <unistd.h>
 #endif
 
@@ -42,6 +41,49 @@ __os_id(idp)
 #ifdef	HAVE_VXWORKS
 	*idp = taskIdSelf();
 #else
-	*idp = getpid();
+	*idp = (u_int32_t)getpid();
+#endif
+}
+
+/*
+ * __os_unique_id --
+ *	Return a unique 32-bit value.
+ *
+ * PUBLIC: void __os_unique_id __P((DB_ENV *, u_int32_t *));
+ */
+void
+__os_unique_id(dbenv, idp)
+	DB_ENV *dbenv;
+	u_int32_t *idp;
+{
+	static int first = 1;
+	u_int32_t id, pid, sec, usec;
+
+	*idp = 0;
+
+	/*
+	 * Our randomized value is comprised of our process ID, the current
+	 * time of day and a couple of a stack addresses, all XOR'd together.
+	 */
+	__os_id(&pid);
+	__os_clock(dbenv, &sec, &usec);
+
+	id = pid ^ sec ^ usec ^ P_TO_UINT32(&pid);
+
+	/*
+	 * We could try and find a reasonable random-number generator, but
+	 * that's not all that easy to do.  Seed and use srand()/rand(), if
+	 * we can find them.
+	 */
+#if HAVE_SRAND
+	if (first == 1)
+		srand((u_int)id);
 #endif
+	first = 0;
+
+#if HAVE_RAND
+	id ^= (u_int)rand();
+#endif
+
+	*idp = id;
 }
diff --git a/storage/bdb/os/os_map.c b/storage/bdb/os/os_map.c
index 6d385b6a84dfd6595fd73f72ca70e1217fb6b66b..adcdaef3c96fc6a41a0ccb913afdc77bbdeb3b2e 100644
--- a/storage/bdb/os/os_map.c
+++ b/storage/bdb/os/os_map.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_map.c,v 11.57 2004/07/06 13:55:48 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_map.c,v 11.44 2002/07/12 18:56:51 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #ifdef HAVE_MMAP
@@ -65,7 +63,7 @@ __os_r_sysattach(dbenv, infop, rp)
 #if defined(HAVE_SHMGET)
 		{
 		key_t segid;
-		int id, ret;
+		int id, mode, ret;
 
 		/*
 		 * We could potentially create based on REGION_CREATE_OK, but
@@ -106,8 +104,13 @@ __os_r_sysattach(dbenv, infop, rp)
 					return (EAGAIN);
 				}
 			}
-			if ((id =
-			    shmget(segid, rp->size, IPC_CREAT | 0600)) == -1) {
+
+			/*
+			 * Map the DbEnv::open method file mode permissions to
+			 * shmget call permissions.
+			 */
+			mode = IPC_CREAT | __db_shm_mode(dbenv);
+			if ((id = shmget(segid, rp->size, mode)) == -1) {
 				ret = __os_get_errno();
 				__db_err(dbenv,
 	"shmget: key: %ld: unable to create shared system memory region: %s",
@@ -136,9 +139,11 @@ __os_r_sysattach(dbenv, infop, rp)
 
 #ifdef HAVE_MMAP
 	{
-	DB_FH fh;
+	DB_FH *fhp;
 	int ret;
 
+	fhp = NULL;
+
 	/*
 	 * Try to open/create the shared region file.  We DO NOT need to ensure
 	 * that multiple threads/processes attempting to simultaneously create
@@ -146,9 +151,9 @@ __os_r_sysattach(dbenv, infop, rp)
 	 * of that.
 	 */
 	if ((ret = __os_open(dbenv, infop->name,
-	    DB_OSO_REGION | DB_OSO_DIRECT |
+	    DB_OSO_REGION |
 	    (F_ISSET(infop, REGION_CREATE_OK) ? DB_OSO_CREATE : 0),
-	    infop->mode, &fh)) != 0)
+	    dbenv->db_mode, &fhp)) != 0)
 		__db_err(dbenv, "%s: %s", infop->name, db_strerror(ret));
 
 	/*
@@ -160,15 +165,15 @@ __os_r_sysattach(dbenv, infop, rp)
 	 */
 	if (ret == 0 && F_ISSET(infop, REGION_CREATE))
 		ret = __db_fileinit(dbenv,
-		    &fh, rp->size, F_ISSET(dbenv, DB_ENV_REGION_INIT) ? 1 : 0);
+		    fhp, rp->size, F_ISSET(dbenv, DB_ENV_REGION_INIT) ? 1 : 0);
 
 	/* Map the file in. */
 	if (ret == 0)
 		ret = __os_map(dbenv,
-		    infop->name, &fh, rp->size, 1, 0, &infop->addr);
+		    infop->name, fhp, rp->size, 1, 0, &infop->addr);
 
-	if (F_ISSET(&fh, DB_FH_VALID))
-		(void)__os_closehandle(dbenv, &fh);
+	if (fhp != NULL)
+		(void)__os_closehandle(dbenv, fhp);
 
 	return (ret);
 	}
@@ -177,7 +182,7 @@ __os_r_sysattach(dbenv, infop, rp)
 	COMPQUIET(rp, NULL);
 	__db_err(dbenv,
 	    "architecture lacks mmap(2), shared environments not possible");
-	return (__db_eopnotsup(dbenv));
+	return (DB_OPNOTSUP);
 #endif
 }
 
@@ -218,7 +223,7 @@ __os_r_sysdetach(dbenv, infop, destroy)
 		if (destroy && shmctl(segid, IPC_RMID,
 		    NULL) != 0 && (ret = __os_get_errno()) != EINVAL) {
 			__db_err(dbenv,
-	    "shmctl: id %ld: unable to delete system shared memory region: %s",
+	    "shmctl: id %d: unable to delete system shared memory region: %s",
 			    segid, strerror(ret));
 			return (ret);
 		}
@@ -293,6 +298,8 @@ __os_unmapfile(dbenv, addr, len)
 	void *addr;
 	size_t len;
 {
+	int ret;
+
 	/* If the user replaced the map call, call through their interface. */
 	if (DB_GLOBAL(j_unmap) != NULL)
 		return (DB_GLOBAL(j_unmap)(addr, len));
@@ -300,19 +307,12 @@ __os_unmapfile(dbenv, addr, len)
 #ifdef HAVE_MMAP
 #ifdef HAVE_MUNLOCK
 	if (F_ISSET(dbenv, DB_ENV_LOCKDOWN))
-		while (munlock(addr, len) != 0 && __os_get_errno() == EINTR)
-			;
+		RETRY_CHK((munlock(addr, len)), ret);
 #else
 	COMPQUIET(dbenv, NULL);
 #endif
-	{
-		int ret;
-
-		while ((ret = munmap(addr, len)) != 0 &&
-		    __os_get_errno() == EINTR)
-			;
-		return (ret ? __os_get_errno() : 0);
-	}
+	RETRY_CHK((munmap(addr, len)), ret);
+	return (ret);
 #else
 	COMPQUIET(dbenv, NULL);
 
@@ -342,6 +342,9 @@ __os_map(dbenv, path, fhp, len, is_region, is_rdonly, addrp)
 		return (DB_GLOBAL(j_map)
 		    (path, len, is_region, is_rdonly, addrp));
 
+	/* Check for illegal usage. */
+	DB_ASSERT(F_ISSET(fhp, DB_FH_OPENED) && fhp->fd != -1);
+
 	/*
 	 * If it's read-only, it's private, and if it's not, it's shared.
 	 * Don't bother with an additional parameter.
@@ -371,6 +374,19 @@ __os_map(dbenv, path, fhp, len, is_region, is_rdonly, addrp)
 	COMPQUIET(is_region, 0);
 #endif
 
+	/*
+	 * FreeBSD:
+	 * Causes data dirtied via this VM map to be flushed to physical media
+	 * only when necessary (usually by the pager) rather then gratuitously.
+	 * Typically this prevents the update daemons from flushing pages
+	 * dirtied through such maps and thus allows efficient sharing of
+	 * memory across unassociated processes using a file-backed shared
+	 * memory map.
+	 */
+#ifdef MAP_NOSYNC
+	flags |= MAP_NOSYNC;
+#endif
+
 	prot = PROT_READ | (is_rdonly ? 0 : PROT_WRITE);
 
 	/*
@@ -438,6 +454,6 @@ __db_nosystemmem(dbenv)
 {
 	__db_err(dbenv,
 	    "architecture doesn't support environments in system memory");
-	return (__db_eopnotsup(dbenv));
+	return (DB_OPNOTSUP);
 }
 #endif
diff --git a/storage/bdb/os/os_method.c b/storage/bdb/os/os_method.c
index 04367654efaef5146ad96f3bc5c7899ebaf33360..a5bb17a797bb3432e2a6b5c37b078705cd2e4e45 100644
--- a/storage/bdb/os/os_method.c
+++ b/storage/bdb/os/os_method.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_method.c,v 11.21 2004/09/17 22:00:31 mjc Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_method.c,v 11.15 2002/07/12 18:56:51 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #endif
@@ -84,6 +82,17 @@ db_env_set_func_fsync(func_fsync)
 	return (0);
 }
 
+/*
+ * EXTERN: int db_env_set_func_ftruncate __P((int (*)(int, off_t)));
+ */
+int
+db_env_set_func_ftruncate(func_ftruncate)
+	int (*func_ftruncate) __P((int, off_t));
+{
+	DB_GLOBAL(j_ftruncate) = func_ftruncate;
+	return (0);
+}
+
 /*
  * EXTERN: int db_env_set_func_ioinfo __P((int (*)(const char *,
  * EXTERN:     int, u_int32_t *, u_int32_t *, u_int32_t *)));
@@ -120,6 +129,30 @@ db_env_set_func_map(func_map)
 	return (0);
 }
 
+/*
+ * EXTERN: int db_env_set_func_pread
+ * EXTERN:    __P((ssize_t (*)(int, void *, size_t, off_t)));
+ */
+int
+db_env_set_func_pread(func_pread)
+	ssize_t (*func_pread) __P((int, void *, size_t, off_t));
+{
+	DB_GLOBAL(j_pread) = func_pread;
+	return (0);
+}
+
+/*
+ * EXTERN: int db_env_set_func_pwrite
+ * EXTERN:    __P((ssize_t (*)(int, const void *, size_t, off_t)));
+ */
+int
+db_env_set_func_pwrite(func_pwrite)
+	ssize_t (*func_pwrite) __P((int, const void *, size_t, off_t));
+{
+	DB_GLOBAL(j_pwrite) = func_pwrite;
+	return (0);
+}
+
 /*
  * EXTERN: int db_env_set_func_open __P((int (*)(const char *, int, ...)));
  */
@@ -167,11 +200,11 @@ db_env_set_func_rename(func_rename)
 
 /*
  * EXTERN: int db_env_set_func_seek
- * EXTERN:     __P((int (*)(int, size_t, db_pgno_t, u_int32_t, int, int)));
+ * EXTERN:     __P((int (*)(int, off_t, int)));
  */
 int
 db_env_set_func_seek(func_seek)
-	int (*func_seek) __P((int, size_t, db_pgno_t, u_int32_t, int, int));
+	int (*func_seek) __P((int, off_t, int));
 {
 	DB_GLOBAL(j_seek) = func_seek;
 	return (0);
diff --git a/storage/bdb/os/os_oflags.c b/storage/bdb/os/os_oflags.c
index f75178de75ed01408f1c6bdc186b9fb683cdac9c..2ffb6db2d9f8b58ec391346824a0fe8fac978287 100644
--- a/storage/bdb/os/os_oflags.c
+++ b/storage/bdb/os/os_oflags.c
@@ -1,20 +1,23 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_oflags.c,v 11.14 2004/07/09 18:39:10 mjc Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_oflags.c,v 11.9 2002/01/11 15:53:00 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #include <sys/stat.h>
 
+#ifdef HAVE_SHMGET
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#endif
+
 #include <fcntl.h>
 #endif
 
@@ -60,18 +63,6 @@ __db_oflags(oflags)
 	return (dbflags);
 }
 
-/*
- * __db_omode --
- *	Convert a permission string to the correct open(2) flags.
- *
- * PUBLIC: int __db_omode __P((const char *));
- */
-int
-__db_omode(perm)
-	const char *perm;
-{
-	int mode;
-
 #ifdef DB_WIN32
 #ifndef	S_IRUSR
 #define	S_IRUSR	S_IREAD		/* R for owner */
@@ -94,13 +85,35 @@ __db_omode(perm)
 #else
 #ifndef	S_IRUSR
 #define	S_IRUSR	0000400		/* R for owner */
+#endif
+#ifndef	S_IWUSR
 #define	S_IWUSR	0000200		/* W for owner */
+#endif
+#ifndef	S_IRGRP
 #define	S_IRGRP	0000040		/* R for group */
+#endif
+#ifndef	S_IWGRP
 #define	S_IWGRP	0000020		/* W for group */
+#endif
+#ifndef	S_IROTH
 #define	S_IROTH	0000004		/* R for other */
+#endif
+#ifndef	S_IWOTH
 #define	S_IWOTH	0000002		/* W for other */
 #endif
 #endif /* DB_WIN32 */
+
+/*
+ * __db_omode --
+ *	Convert a permission string to the correct open(2) flags.
+ *
+ * PUBLIC: int __db_omode __P((const char *));
+ */
+int
+__db_omode(perm)
+	const char *perm;
+{
+	int mode;
 	mode = 0;
 	if (perm[0] == 'r')
 		mode |= S_IRUSR;
@@ -116,3 +129,46 @@ __db_omode(perm)
 		mode |= S_IWOTH;
 	return (mode);
 }
+
+#ifdef HAVE_SHMGET
+
+#ifndef SHM_R
+#define	SHM_R	0400
+#endif
+#ifndef SHM_W
+#define	SHM_W	0200
+#endif
+
+/*
+ * __db_shm_mode --
+ *	Map the DbEnv::open method file mode permissions to shmget call
+ *	permissions.
+ *
+ * PUBLIC: int __db_shm_mode __P((DB_ENV *));
+ */
+int
+__db_shm_mode(dbenv)
+	DB_ENV *dbenv;
+{
+	int mode;
+
+	/* Default to r/w owner, r/w group. */
+	if (dbenv->db_mode == 0)
+		return (SHM_R | SHM_W | SHM_R >> 3 | SHM_W >> 3);
+
+	mode = 0;
+	if (dbenv->db_mode & S_IRUSR)
+		mode |= SHM_R;
+	if (dbenv->db_mode & S_IWUSR)
+		mode |= SHM_W;
+	if (dbenv->db_mode & S_IRGRP)
+		mode |= SHM_R >> 3;
+	if (dbenv->db_mode & S_IWGRP)
+		mode |= SHM_W >> 3;
+	if (dbenv->db_mode & S_IROTH)
+		mode |= SHM_R >> 6;
+	if (dbenv->db_mode & S_IWOTH)
+		mode |= SHM_W >> 6;
+	return (mode);
+}
+#endif
diff --git a/storage/bdb/os/os_open.c b/storage/bdb/os/os_open.c
index 0a4dbadc6e872fa326087df4b597ca7bc63787c1..44c02e6d49763983b2442670db8546e9a94c60b8 100644
--- a/storage/bdb/os/os_open.c
+++ b/storage/bdb/os/os_open.c
@@ -1,55 +1,104 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_open.c,v 11.60 2004/09/24 00:43:19 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_open.c,v 11.37 2002/06/21 20:35:16 sandstro Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef HAVE_SYS_FCNTL_H
+#include <sys/fcntl.h>
+#endif
 
 #include <fcntl.h>
 #include <string.h>
+#include <unistd.h>
 #endif
 
 #include "db_int.h"
 
+static int __os_intermediate_dir __P((DB_ENV *, const char *));
+static int __os_mkdir __P((DB_ENV *, const char *));
 #ifdef HAVE_QNX
-static int __os_region_open __P((DB_ENV *, const char *, int, int, DB_FH *));
+static int __os_region_open __P((DB_ENV *, const char *, int, int, DB_FH **));
 #endif
 
+/*
+ * __os_have_direct --
+ *	Check to see if we support direct I/O.
+ *
+ * PUBLIC: int __os_have_direct __P((void));
+ */
+int
+__os_have_direct()
+{
+	int ret;
+
+	ret = 0;
+
+#ifdef HAVE_O_DIRECT
+	ret = 1;
+#endif
+#if defined(HAVE_DIRECTIO) && defined(DIRECTIO_ON)
+	ret = 1;
+#endif
+	return (ret);
+}
+
 /*
  * __os_open --
  *	Open a file.
  *
- * PUBLIC: int __os_open __P((DB_ENV *, const char *, u_int32_t, int, DB_FH *));
+ * PUBLIC: int __os_open
+ * PUBLIC:     __P((DB_ENV *, const char *, u_int32_t, int, DB_FH **));
  */
 int
-__os_open(dbenv, name, flags, mode, fhp)
+__os_open(dbenv, name, flags, mode, fhpp)
 	DB_ENV *dbenv;
 	const char *name;
 	u_int32_t flags;
 	int mode;
-	DB_FH *fhp;
+	DB_FH **fhpp;
+{
+	return (__os_open_extend(dbenv, name, 0, flags, mode, fhpp));
+}
+
+/*
+ * __os_open_extend --
+ *	Open a file descriptor (including page size and log size information).
+ *
+ * PUBLIC: int __os_open_extend __P((DB_ENV *,
+ * PUBLIC:     const char *, u_int32_t, u_int32_t, int, DB_FH **));
+ */
+int
+__os_open_extend(dbenv, name, page_size, flags, mode, fhpp)
+	DB_ENV *dbenv;
+	const char *name;
+	u_int32_t page_size, flags;
+	int mode;
+	DB_FH **fhpp;
 {
+	DB_FH *fhp;
 	int oflags, ret;
 
+	COMPQUIET(page_size, 0);
+
+	*fhpp = NULL;
 	oflags = 0;
 
-#ifdef DIAGNOSTIC
 #define	OKFLAGS								\
-	(DB_OSO_CREATE | DB_OSO_DIRECT | DB_OSO_EXCL | DB_OSO_LOG |	\
-	 DB_OSO_RDONLY | DB_OSO_REGION | DB_OSO_SEQ | DB_OSO_TEMP |	\
-	 DB_OSO_TRUNC)
+	(DB_OSO_CREATE | DB_OSO_DIRECT | DB_OSO_DSYNC | DB_OSO_EXCL |	\
+	 DB_OSO_LOG | DB_OSO_RDONLY | DB_OSO_REGION | DB_OSO_SEQ |	\
+	 DB_OSO_TEMP | DB_OSO_TRUNC)
 	if ((ret = __db_fchk(dbenv, "__os_open", flags, OKFLAGS)) != 0)
 		return (ret);
-#endif
 
 #if defined(O_BINARY)
 	/*
@@ -72,16 +121,12 @@ __os_open(dbenv, name, flags, mode, fhp)
 	if (LF_ISSET(DB_OSO_EXCL))
 		oflags |= O_EXCL;
 
-#if defined(O_DSYNC) && defined(XXX_NEVER_SET)
-	/*
-	 * !!!
-	 * We should get better performance if we push the log files to disk
-	 * immediately instead of waiting for the sync.  However, Solaris
-	 * (and likely any other system based on the 4BSD filesystem releases),
-	 * doesn't implement O_DSYNC correctly, only flushing data blocks and
-	 * not inode or indirect blocks.
-	 */
-	if (LF_ISSET(DB_OSO_LOG))
+#ifdef HAVE_O_DIRECT
+	if (LF_ISSET(DB_OSO_DIRECT))
+		oflags |= O_DIRECT;
+#endif
+#ifdef O_DSYNC
+	if (LF_ISSET(DB_OSO_LOG) && LF_ISSET(DB_OSO_DSYNC))
 		oflags |= O_DSYNC;
 #endif
 
@@ -93,20 +138,34 @@ __os_open(dbenv, name, flags, mode, fhp)
 	if (LF_ISSET(DB_OSO_TRUNC))
 		oflags |= O_TRUNC;
 
-#ifdef HAVE_O_DIRECT
-	if (LF_ISSET(DB_OSO_DIRECT))
-		oflags |= O_DIRECT;
-#endif
+	/*
+	 * Undocumented feature: allow applications to create intermediate
+	 * directories whenever a file is opened.
+	 */
+	if (dbenv != NULL &&
+	    dbenv->dir_mode != 0 && LF_ISSET(DB_OSO_CREATE) &&
+	    (ret = __os_intermediate_dir(dbenv, name)) != 0)
+		return (ret);
 
 #ifdef HAVE_QNX
 	if (LF_ISSET(DB_OSO_REGION))
-		return (__os_region_open(dbenv, name, oflags, mode, fhp));
+		return (__os_qnx_region_open(dbenv, name, oflags, mode, fhpp));
 #endif
 	/* Open the file. */
-	if ((ret = __os_openhandle(dbenv, name, oflags, mode, fhp)) != 0)
+	if ((ret = __os_openhandle(dbenv, name, oflags, mode, &fhp)) != 0)
 		return (ret);
 
-#ifdef HAVE_DIRECTIO
+#ifdef O_DSYNC
+	if (LF_ISSET(DB_OSO_LOG) && LF_ISSET(DB_OSO_DSYNC))
+		F_SET(fhp, DB_FH_NOSYNC);
+#endif
+
+#if defined(HAVE_DIRECTIO) && defined(DIRECTIO_ON)
+	/*
+	 * The Solaris C library includes directio, but you have to set special
+	 * compile flags to #define DIRECTIO_ON.  Require both in order to call
+	 * directio.
+	 */
 	if (LF_ISSET(DB_OSO_DIRECT))
 		(void)directio(fhp->fd, DIRECTIO_ON);
 #endif
@@ -134,49 +193,62 @@ __os_open(dbenv, name, flags, mode, fhp)
 #endif
 	}
 
+	*fhpp = fhp;
 	return (0);
 }
 
 #ifdef HAVE_QNX
 /*
- * __os_region_open --
+ * __os_qnx_region_open --
  *	Open a shared memory region file using POSIX shm_open.
  */
 static int
-__os_region_open(dbenv, name, oflags, mode, fhp)
+__os_qnx_region_open(dbenv, name, oflags, mode, fhpp)
 	DB_ENV *dbenv;
 	const char *name;
 	int oflags;
 	int mode;
-	DB_FH *fhp;
+	DB_FH **fhpp;
 {
+	DB_FH *fhp;
 	int ret;
 	char *newname;
 
+	if ((ret = __os_calloc(dbenv, 1, sizeof(DB_FH), fhpp)) != 0)
+		return (ret);
+	fhp = *fhpp;
+
 	if ((ret = __os_shmname(dbenv, name, &newname)) != 0)
 		goto err;
-	memset(fhp, 0, sizeof(*fhp));
+
+	/*
+	 * Once we have created the object, we don't need the name
+	 * anymore.  Other callers of this will convert themselves.
+	 */
 	fhp->fd = shm_open(newname, oflags, mode);
-	if (fhp->fd == -1)
+	__os_free(dbenv, newname);
+
+	if (fhp->fd == -1) {
 		ret = __os_get_errno();
-	else {
+		goto err;
+	}
+
+	F_SET(fhp, DB_FH_OPENED);
+
 #ifdef HAVE_FCNTL_F_SETFD
-		/* Deny file descriptor acces to any child process. */
-		if (fcntl(fhp->fd, F_SETFD, 1) == -1) {
-			ret = __os_get_errno();
-			__db_err(dbenv, "fcntl(F_SETFD): %s", strerror(ret));
-			__os_closehandle(dbenv, fhp);
-		} else
+	/* Deny file descriptor access to any child process. */
+	if (fcntl(fhp->fd, F_SETFD, 1) == -1) {
+		ret = __os_get_errno();
+		__db_err(dbenv, "fcntl(F_SETFD): %s", strerror(ret));
+		goto err;
+	}
 #endif
-		F_SET(fhp, DB_FH_VALID);
+
+err:	if (ret != 0) {
+		(void)__os_closehandle(dbenv, fhp);
+		*fhpp = NULL;
 	}
-	/*
-	 * Once we have created the object, we don't need the name
-	 * anymore.  Other callers of this will convert themselves.
-	 */
-err:
-	if (newname != NULL)
-		__os_free(dbenv, newname);
+
 	return (ret);
 }
 
@@ -255,3 +327,86 @@ __os_shmname(dbenv, name, newnamep)
 	return (0);
 }
 #endif
+
+/*
+ * __os_intermediate_dir --
+ *	Create intermediate directories.
+ */
+static int
+__os_intermediate_dir(dbenv, name)
+	DB_ENV *dbenv;
+	const char *name;
+{
+	size_t len;
+	int ret;
+	char savech, *p, *t, buf[128];
+
+	ret = 0;
+
+	/*
+	 * Get a copy so we can modify the string.
+	 *
+	 * Allocate memory if temporary space is too small.
+	 */
+	if ((len = strlen(name)) > sizeof(buf) - 1) {
+		if ((ret = __os_umalloc(dbenv, len, &t)) != 0)
+			return (ret);
+	} else
+		t = buf;
+	(void)strcpy(t, name);
+
+	/*
+	 * Cycle through the path, creating intermediate directories.
+	 *
+	 * Skip the first byte if it's a path separator, it's the start of an
+	 * absolute pathname.
+	 */
+	if (PATH_SEPARATOR[1] == '\0') {
+		for (p = t + 1; p[0] != '\0'; ++p)
+			if (p[0] == PATH_SEPARATOR[0]) {
+				savech = *p;
+				*p = '\0';
+				if (__os_exists(t, NULL) &&
+				    (ret = __os_mkdir(dbenv, t)) != 0)
+					break;
+				*p = savech;
+			}
+	} else
+		for (p = t + 1; p[0] != '\0'; ++p)
+			if (strchr(PATH_SEPARATOR, p[0]) != NULL) {
+				savech = *p;
+				*p = '\0';
+				if (__os_exists(t, NULL) &&
+				    (ret = __os_mkdir(dbenv, t)) != 0)
+					break;
+				*p = savech;
+			}
+	if (t != buf)
+		__os_free(dbenv, t);
+	return (ret);
+}
+
+/*
+ * __os_mkdir --
+ *	Create a directory.
+ */
+static int
+__os_mkdir(dbenv, name)
+	DB_ENV *dbenv;
+	const char *name;
+{
+	int ret;
+
+	/* Make the directory, with paranoid permissions. */
+#ifdef HAVE_VXWORKS
+	RETRY_CHK((mkdir((char *)name)), ret);
+#else
+	RETRY_CHK((mkdir(name, 0600)), ret);
+	if (ret != 0)
+		return (ret);
+
+	/* Set the absolute permissions. */
+	RETRY_CHK((chmod(name, dbenv->dir_mode)), ret);
+#endif
+	return (ret);
+}
diff --git a/storage/bdb/os/os_region.c b/storage/bdb/os/os_region.c
index 6529f708b2cdcf5f946d3d1f9ae3c65312244093..024c0320d350e39e4b1574d5cc57322ee9d96a4e 100644
--- a/storage/bdb/os/os_region.c
+++ b/storage/bdb/os/os_region.c
@@ -1,19 +1,18 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_region.c,v 11.21 2004/06/10 17:20:57 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_region.c,v 11.15 2002/07/12 18:56:51 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
+#include <string.h>
 #endif
 
 #include "db_int.h"
@@ -31,6 +30,7 @@ __os_r_attach(dbenv, infop, rp)
 	REGION *rp;
 {
 	int ret;
+
 	/* Round off the requested size for the underlying VM. */
 	OS_VMROUNDOFF(rp->size);
 
@@ -68,21 +68,43 @@ __os_r_attach(dbenv, infop, rp)
 			return (EINVAL);
 		}
 #endif
-		if ((ret =
-		    __os_malloc(dbenv, rp->size, &infop->addr)) != 0)
+		/*
+		 * Pad out the allocation, we're going to align it to mutex
+		 * alignment.
+		 */
+		if ((ret = __os_malloc(dbenv,
+		    sizeof(REGENV) + (MUTEX_ALIGN - 1), &infop->addr)) != 0)
+			return (ret);
+
+		infop->max_alloc = rp->size;
+	} else {
+		/*
+		 * If the user replaced the map call, call through their
+		 * interface.
+		 */
+		if (DB_GLOBAL(j_map) != NULL && (ret = DB_GLOBAL(j_map)
+		    (infop->name, rp->size, 1, 0, &infop->addr)) != 0)
+			return (ret);
+
+		/* Get some space from the underlying system. */
+		if ((ret = __os_r_sysattach(dbenv, infop, rp)) != 0)
 			return (ret);
-#if defined(UMRW) && !defined(DIAGNOSTIC)
-		memset(infop->addr, CLEAR_BYTE, rp->size);
-#endif
-		return (0);
 	}
 
-	/* If the user replaced the map call, call through their interface. */
-	if (DB_GLOBAL(j_map) != NULL)
-		return (DB_GLOBAL(j_map)(infop->name,
-		    rp->size, 1, 0, &infop->addr));
+	/*
+	 * We may require alignment the underlying system or heap allocation
+	 * library doesn't supply.  Align the address if necessary, saving
+	 * the original values for restoration when the region is discarded.
+	 */
+	infop->addr_orig = infop->addr;
+	infop->addr = ALIGNP_INC(infop->addr_orig, MUTEX_ALIGN);
+
+	rp->size_orig = rp->size;
+	if (infop->addr != infop->addr_orig)
+		rp->size -=
+		    (u_int8_t *)infop->addr - (u_int8_t *)infop->addr_orig;
 
-	return (__os_r_sysattach(dbenv, infop, rp));
+	return (0);
 }
 
 /*
@@ -101,6 +123,12 @@ __os_r_detach(dbenv, infop, destroy)
 
 	rp = infop->rp;
 
+	/* Restore any address/size altered for alignment reasons. */
+	if (infop->addr != infop->addr_orig) {
+		infop->addr = infop->addr_orig;
+		rp->size = rp->size_orig;
+	}
+
 	/* If a region is private, free the memory. */
 	if (F_ISSET(dbenv, DB_ENV_PRIVATE)) {
 		__os_free(dbenv, infop->addr);
diff --git a/storage/bdb/os/os_rename.c b/storage/bdb/os/os_rename.c
index 2569a9c31860d977d2cf27d367ba2333cd24cdfd..a55160bcc5c7dffaf3935ae4fb6f7da7faedd881 100644
--- a/storage/bdb/os/os_rename.c
+++ b/storage/bdb/os/os_rename.c
@@ -1,47 +1,45 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_rename.c,v 11.17 2004/07/06 13:55:48 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_rename.c,v 11.12 2002/07/12 18:56:52 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <string.h>
-#include <unistd.h>
 #endif
 
 #include "db_int.h"
 
 /*
  * __os_rename --
- *	Rename a file.  If flags is non-zero, then errors are OK and we
- * should not output an error message.
+ *	Rename a file.
  *
  * PUBLIC: int __os_rename __P((DB_ENV *,
  * PUBLIC:    const char *, const char *, u_int32_t));
  */
 int
-__os_rename(dbenv, old, new, flags)
+__os_rename(dbenv, old, new, silent)
 	DB_ENV *dbenv;
 	const char *old, *new;
-	u_int32_t flags;
+	u_int32_t silent;
 {
 	int ret;
 
-	do {
-		ret = DB_GLOBAL(j_rename) != NULL ?
-		    DB_GLOBAL(j_rename)(old, new) : rename(old, new);
-	} while (ret != 0 && (ret = __os_get_errno()) == EINTR);
+	RETRY_CHK((DB_GLOBAL(j_rename) != NULL ?
+	    DB_GLOBAL(j_rename)(old, new) : rename(old, new)), ret);
 
-	if (ret != 0 && flags == 0)
+	/*
+	 * If "silent" is not set, then errors are OK and we should not output
+	 * an error message.
+	 */
+	if (!silent && ret != 0)
 		__db_err(dbenv, "rename %s %s: %s", old, new, strerror(ret));
 	return (ret);
 }
diff --git a/storage/bdb/os/os_root.c b/storage/bdb/os/os_root.c
index cd5bfc352e92c9c4ffdc1122fb90c96d9dc3e962..bf4702ed2a521b860cf89c09d7585b86f74a17f2 100644
--- a/storage/bdb/os/os_root.c
+++ b/storage/bdb/os/os_root.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_root.c,v 11.8 2004/01/28 03:36:18 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_root.c,v 11.6 2002/01/11 15:53:01 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
diff --git a/storage/bdb/os/os_rpath.c b/storage/bdb/os/os_rpath.c
index b9ccba01bd54f9c01b3430a565730d2d8b8285e2..28a0a48261ec03be038e897c778a999dbe642055 100644
--- a/storage/bdb/os/os_rpath.c
+++ b/storage/bdb/os/os_rpath.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_rpath.c,v 11.9 2004/01/28 03:36:18 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_rpath.c,v 11.7 2002/01/11 15:53:01 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <string.h>
 #endif
diff --git a/storage/bdb/os/os_rw.c b/storage/bdb/os/os_rw.c
index 9a79342c7b8b38e41bb584cdce00d28972d414f8..5519f35e4f731cefba30384a6e410f988b4b8109 100644
--- a/storage/bdb/os/os_rw.c
+++ b/storage/bdb/os/os_rw.c
@@ -1,18 +1,17 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_rw.c,v 11.39 2004/09/17 22:00:31 mjc Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_rw.c,v 11.24 2002/07/12 18:56:52 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
+#include <sys/stat.h>
 
 #include <string.h>
 #include <unistd.h>
@@ -20,57 +19,83 @@ static const char revid[] = "$Id: os_rw.c,v 11.24 2002/07/12 18:56:52 bostic Exp
 
 #include "db_int.h"
 
+#ifdef HAVE_FILESYSTEM_NOTZERO
+static int __os_zerofill __P((DB_ENV *, DB_FH *));
+#endif
+static int __os_physwrite __P((DB_ENV *, DB_FH *, void *, size_t, size_t *));
+
 /*
  * __os_io --
  *	Do an I/O.
  *
- * PUBLIC: int __os_io __P((DB_ENV *, DB_IO *, int, size_t *));
+ * PUBLIC: int __os_io __P((DB_ENV *,
+ * PUBLIC:     int, DB_FH *, db_pgno_t, u_int32_t, u_int8_t *, size_t *));
  */
 int
-__os_io(dbenv, db_iop, op, niop)
+__os_io(dbenv, op, fhp, pgno, pagesize, buf, niop)
 	DB_ENV *dbenv;
-	DB_IO *db_iop;
 	int op;
+	DB_FH *fhp;
+	db_pgno_t pgno;
+	u_int32_t pagesize;
+	u_int8_t *buf;
 	size_t *niop;
 {
+#if defined(HAVE_PREAD) && defined(HAVE_PWRITE)
+	ssize_t nio;
+#endif
 	int ret;
 
+	/* Check for illegal usage. */
+	DB_ASSERT(F_ISSET(fhp, DB_FH_OPENED) && fhp->fd != -1);
+
 #if defined(HAVE_PREAD) && defined(HAVE_PWRITE)
 	switch (op) {
 	case DB_IO_READ:
 		if (DB_GLOBAL(j_read) != NULL)
 			goto slow;
-		*niop = pread(db_iop->fhp->fd, db_iop->buf,
-		    db_iop->bytes, (off_t)db_iop->pgno * db_iop->pagesize);
+		nio = DB_GLOBAL(j_pread) != NULL ? DB_GLOBAL(j_pread)
+			(fhp->fd, buf, pagesize, (off_t)pgno * pagesize) :
+			pread(fhp->fd, buf, pagesize, (off_t)pgno * pagesize);
 		break;
 	case DB_IO_WRITE:
 		if (DB_GLOBAL(j_write) != NULL)
 			goto slow;
-		*niop = pwrite(db_iop->fhp->fd, db_iop->buf,
-		    db_iop->bytes, (off_t)db_iop->pgno * db_iop->pagesize);
+#ifdef HAVE_FILESYSTEM_NOTZERO
+		if (__os_fs_notzero())
+			goto slow;
+#endif
+		nio = DB_GLOBAL(j_pwrite) != NULL ? DB_GLOBAL(j_pwrite)
+			(fhp->fd, buf, pagesize, (off_t)pgno * pagesize) :
+			pwrite(fhp->fd, buf, pagesize, (off_t)pgno * pagesize);
 		break;
+	default:
+		return (EINVAL);
 	}
-	if (*niop == (size_t)db_iop->bytes)
+	if (nio == (ssize_t)pagesize) {
+		*niop = pagesize;
 		return (0);
+	}
 slow:
 #endif
-	MUTEX_THREAD_LOCK(dbenv, db_iop->mutexp);
+	MUTEX_THREAD_LOCK(dbenv, fhp->mutexp);
 
-	if ((ret = __os_seek(dbenv, db_iop->fhp,
-	    db_iop->pagesize, db_iop->pgno, 0, 0, DB_OS_SEEK_SET)) != 0)
+	if ((ret = __os_seek(dbenv, fhp,
+	    pagesize, pgno, 0, 0, DB_OS_SEEK_SET)) != 0)
 		goto err;
 	switch (op) {
 	case DB_IO_READ:
-		ret = __os_read(dbenv,
-		    db_iop->fhp, db_iop->buf, db_iop->bytes, niop);
+		ret = __os_read(dbenv, fhp, buf, pagesize, niop);
 		break;
 	case DB_IO_WRITE:
-		ret = __os_write(dbenv,
-		    db_iop->fhp, db_iop->buf, db_iop->bytes, niop);
+		ret = __os_write(dbenv, fhp, buf, pagesize, niop);
+		break;
+	default:
+		ret = EINVAL;
 		break;
 	}
 
-err:	MUTEX_THREAD_UNLOCK(dbenv, db_iop->mutexp);
+err:	MUTEX_THREAD_UNLOCK(dbenv, fhp->mutexp);
 
 	return (ret);
 
@@ -95,22 +120,33 @@ __os_read(dbenv, fhp, addr, len, nrp)
 	int ret;
 	u_int8_t *taddr;
 
-	for (taddr = addr,
-	    offset = 0; offset < len; taddr += nr, offset += nr) {
-retry:		if ((nr = DB_GLOBAL(j_read) != NULL ?
-		    DB_GLOBAL(j_read)(fhp->fd, taddr, len - offset) :
-		    read(fhp->fd, taddr, len - offset)) < 0) {
-			if ((ret = __os_get_errno()) == EINTR)
-				goto retry;
-			__db_err(dbenv, "read: 0x%x, %lu: %s", taddr,
-			    (u_long)len-offset, strerror(ret));
-			return (ret);
+	ret = 0;
+
+	/* Check for illegal usage. */
+	DB_ASSERT(F_ISSET(fhp, DB_FH_OPENED) && fhp->fd != -1);
+
+	if (DB_GLOBAL(j_read) != NULL) {
+		*nrp = len;
+		if (DB_GLOBAL(j_read)(fhp->fd, addr, len) != (ssize_t)len) {
+			ret = __os_get_errno();
+			__db_err(dbenv, "read: %#lx, %lu: %s",
+			    P_TO_ULONG(addr), (u_long)len, strerror(ret));
 		}
-		if (nr == 0)
+		return (ret);
+	}
+
+	for (taddr = addr, offset = 0;
+	    offset < len; taddr += nr, offset += (u_int32_t)nr) {
+		RETRY_CHK(((nr = read(
+		    fhp->fd, taddr, len - offset)) < 0 ? 1 : 0), ret);
+		if (nr == 0 || ret != 0)
 			break;
 	}
-	*nrp = taddr - (u_int8_t *)addr;
-	return (0);
+	*nrp = (size_t)(taddr - (u_int8_t *)addr);
+	if (ret != 0)
+		__db_err(dbenv, "read: %#lx, %lu: %s",
+		    P_TO_ULONG(taddr), (u_long)len - offset, strerror(ret));
+	return (ret);
 }
 
 /*
@@ -126,23 +162,158 @@ __os_write(dbenv, fhp, addr, len, nwp)
 	void *addr;
 	size_t len;
 	size_t *nwp;
+{
+	/* Check for illegal usage. */
+	DB_ASSERT(F_ISSET(fhp, DB_FH_OPENED) && fhp->fd != -1);
+
+#ifdef HAVE_FILESYSTEM_NOTZERO
+	/* Zero-fill as necessary. */
+	if (__os_fs_notzero()) {
+		int ret;
+		if ((ret = __os_zerofill(dbenv, fhp)) != 0)
+			return (ret);
+	}
+#endif
+	return (__os_physwrite(dbenv, fhp, addr, len, nwp));
+}
+
+/*
+ * __os_physwrite --
+ *	Physical write to a file handle.
+ */
+static int
+__os_physwrite(dbenv, fhp, addr, len, nwp)
+	DB_ENV *dbenv;
+	DB_FH *fhp;
+	void *addr;
+	size_t len;
+	size_t *nwp;
 {
 	size_t offset;
 	ssize_t nw;
 	int ret;
 	u_int8_t *taddr;
 
-	for (taddr = addr,
-	    offset = 0; offset < len; taddr += nw, offset += nw)
-retry:		if ((nw = DB_GLOBAL(j_write) != NULL ?
-		    DB_GLOBAL(j_write)(fhp->fd, taddr, len - offset) :
-		    write(fhp->fd, taddr, len - offset)) < 0) {
-			if ((ret = __os_get_errno()) == EINTR)
-				goto retry;
-			__db_err(dbenv, "write: 0x%x, %lu: %s", taddr,
-			    (u_long)len-offset, strerror(ret));
-			return (ret);
+	ret = 0;
+
+#if defined(HAVE_FILESYSTEM_NOTZERO) && defined(DIAGNOSTIC)
+	if (__os_fs_notzero()) {
+		struct stat sb;
+		off_t cur_off;
+
+		DB_ASSERT(fstat(fhp->fd, &sb) != -1 &&
+		    (cur_off = lseek(fhp->fd, (off_t)0, SEEK_CUR)) != -1 &&
+		    cur_off <= sb.st_size);
+	}
+#endif
+
+	if (DB_GLOBAL(j_write) != NULL) {
+		*nwp = len;
+		if (DB_GLOBAL(j_write)(fhp->fd, addr, len) != (ssize_t)len) {
+			ret = __os_get_errno();
+			__db_err(dbenv, "write: %#lx, %lu: %s",
+			    P_TO_ULONG(addr), (u_long)len, strerror(ret));
 		}
+		return (ret);
+	}
+
+	for (taddr = addr, offset = 0;
+	    offset < len; taddr += nw, offset += (u_int32_t)nw) {
+		RETRY_CHK(((nw = write(
+		    fhp->fd, taddr, len - offset)) < 0 ? 1 : 0), ret);
+		if (ret != 0)
+			break;
+	}
 	*nwp = len;
-	return (0);
+	if (ret != 0)
+		__db_err(dbenv, "write: %#lx, %lu: %s",
+		    P_TO_ULONG(taddr), (u_long)len - offset, strerror(ret));
+	return (ret);
 }
+
+#ifdef HAVE_FILESYSTEM_NOTZERO
+/*
+ * __os_zerofill --
+ *	Zero out bytes in the file.
+ *
+ *	Pages allocated by writing pages past end-of-file are not zeroed,
+ *	on some systems.  Recovery could theoretically be fooled by a page
+ *	showing up that contained garbage.  In order to avoid this, we
+ *	have to write the pages out to disk, and flush them.  The reason
+ *	for the flush is because if we don't sync, the allocation of another
+ *	page subsequent to this one might reach the disk first, and if we
+ *	crashed at the right moment, leave us with this page as the one
+ *	allocated by writing a page past it in the file.
+ */
+static int
+__os_zerofill(dbenv, fhp)
+	DB_ENV *dbenv;
+	DB_FH *fhp;
+{
+	off_t stat_offset, write_offset;
+	size_t blen, nw;
+	u_int32_t bytes, mbytes;
+	int group_sync, need_free, ret;
+	u_int8_t buf[8 * 1024], *bp;
+
+	/* Calculate the byte offset of the next write. */
+	write_offset = (off_t)fhp->pgno * fhp->pgsize + fhp->offset;
+
+	/* Stat the file. */
+	if ((ret = __os_ioinfo(dbenv, NULL, fhp, &mbytes, &bytes, NULL)) != 0)
+		return (ret);
+	stat_offset = (off_t)mbytes * MEGABYTE + bytes;
+
+	/* Check if the file is large enough. */
+	if (stat_offset >= write_offset)
+		return (0);
+
+	/* Get a large buffer if we're writing lots of data. */
+#undef	ZF_LARGE_WRITE
+#define	ZF_LARGE_WRITE	(64 * 1024)
+	if (write_offset - stat_offset > ZF_LARGE_WRITE) {
+		if ((ret = __os_calloc(dbenv, 1, ZF_LARGE_WRITE, &bp)) != 0)
+			    return (ret);
+		blen = ZF_LARGE_WRITE;
+		need_free = 1;
+	} else {
+		bp = buf;
+		blen = sizeof(buf);
+		need_free = 0;
+		memset(buf, 0, sizeof(buf));
+	}
+
+	/* Seek to the current end of the file. */
+	if ((ret = __os_seek(
+	    dbenv, fhp, MEGABYTE, mbytes, bytes, 0, DB_OS_SEEK_SET)) != 0)
+		goto err;
+
+	/*
+	 * Hash is the only access method that allocates groups of pages.  Hash
+	 * uses the existence of the last page in a group to signify the entire
+	 * group is OK; so, write all the pages but the last one in the group,
+	 * flush them to disk, then write the last one to disk and flush it.
+	 */
+	for (group_sync = 0; stat_offset < write_offset; group_sync = 1) {
+		if (write_offset - stat_offset <= blen) {
+			blen = (size_t)(write_offset - stat_offset);
+			if (group_sync && (ret = __os_fsync(dbenv, fhp)) != 0)
+				goto err;
+		}
+		if ((ret = __os_physwrite(dbenv, fhp, bp, blen, &nw)) != 0)
+			goto err;
+		stat_offset += blen;
+	}
+	if ((ret = __os_fsync(dbenv, fhp)) != 0)
+		goto err;
+
+	/* Seek back to where we started. */
+	mbytes = (u_int32_t)(write_offset / MEGABYTE);
+	bytes = (u_int32_t)(write_offset % MEGABYTE);
+	ret = __os_seek(dbenv, fhp, MEGABYTE, mbytes, bytes, 0, DB_OS_SEEK_SET);
+
+err:	if (need_free)
+		__os_free(dbenv, bp);
+	return (ret);
+}
+#endif
diff --git a/storage/bdb/os/os_seek.c b/storage/bdb/os/os_seek.c
index 5b2aa45d5dd361cf30d8ab5051dfbb6a959a07c3..482bb6c6c7a60ceb11527e66fb89f926ef10059d 100644
--- a/storage/bdb/os/os_seek.c
+++ b/storage/bdb/os/os_seek.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_seek.c,v 11.26 2004/09/17 22:00:31 mjc Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_seek.c,v 11.18 2002/07/12 18:56:52 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -26,13 +24,13 @@ static const char revid[] = "$Id: os_seek.c,v 11.18 2002/07/12 18:56:52 bostic E
  *	Seek to a page/byte offset in the file.
  *
  * PUBLIC: int __os_seek __P((DB_ENV *,
- * PUBLIC:      DB_FH *, size_t, db_pgno_t, u_int32_t, int, DB_OS_SEEK));
+ * PUBLIC:      DB_FH *, u_int32_t, db_pgno_t, u_int32_t, int, DB_OS_SEEK));
  */
 int
 __os_seek(dbenv, fhp, pgsize, pageno, relative, isrewind, db_whence)
 	DB_ENV *dbenv;
 	DB_FH *fhp;
-	size_t pgsize;
+	u_int32_t pgsize;
 	db_pgno_t pageno;
 	u_int32_t relative;
 	int isrewind;
@@ -41,6 +39,9 @@ __os_seek(dbenv, fhp, pgsize, pageno, relative, isrewind, db_whence)
 	off_t offset;
 	int ret, whence;
 
+	/* Check for illegal usage. */
+	DB_ASSERT(F_ISSET(fhp, DB_FH_OPENED) && fhp->fd != -1);
+
 	switch (db_whence) {
 	case DB_OS_SEEK_CUR:
 		whence = SEEK_CUR;
@@ -55,20 +56,20 @@ __os_seek(dbenv, fhp, pgsize, pageno, relative, isrewind, db_whence)
 		return (EINVAL);
 	}
 
+	offset = (off_t)pgsize * pageno + relative;
+	if (isrewind)
+		offset = -offset;
+
 	if (DB_GLOBAL(j_seek) != NULL)
-		ret = DB_GLOBAL(j_seek)(fhp->fd,
-		    pgsize, pageno, relative, isrewind, whence);
-	else {
-		offset = (off_t)pgsize * pageno + relative;
-		if (isrewind)
-			offset = -offset;
-		do {
-			ret = lseek(fhp->fd, offset, whence) == -1 ?
-			    __os_get_errno() : 0;
-		} while (ret == EINTR);
-	}
+		ret = DB_GLOBAL(j_seek)(fhp->fd, offset, whence);
+	else
+		RETRY_CHK((lseek(fhp->fd, offset, whence) == -1 ? 1 : 0), ret);
 
-	if (ret != 0)
+	if (ret == 0) {
+		fhp->pgsize = pgsize;
+		fhp->pgno = pageno;
+		fhp->offset = relative;
+	} else
 		__db_err(dbenv, "seek: %lu %d %d: %s",
 		    (u_long)pgsize * pageno + relative,
 		    isrewind, db_whence, strerror(ret));
diff --git a/storage/bdb/os/os_sleep.c b/storage/bdb/os/os_sleep.c
index 42d496dbae74a024b219dd809e1514f9312802bc..da3e97280dc61de4b358a46148856fa887f1ce91 100644
--- a/storage/bdb/os/os_sleep.c
+++ b/storage/bdb/os/os_sleep.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_sleep.c,v 11.23 2004/03/27 19:09:13 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_sleep.c,v 11.15 2002/07/12 18:56:52 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -45,9 +43,9 @@ static const char revid[] = "$Id: os_sleep.c,v 11.15 2002/07/12 18:56:52 bostic
  * __os_sleep --
  *	Yield the processor for a period of time.
  *
- * PUBLIC: int __os_sleep __P((DB_ENV *, u_long, u_long));
+ * PUBLIC: void __os_sleep __P((DB_ENV *, u_long, u_long));
  */
-int
+void
 __os_sleep(dbenv, secs, usecs)
 	DB_ENV *dbenv;
 	u_long secs, usecs;		/* Seconds and microseconds. */
@@ -59,22 +57,31 @@ __os_sleep(dbenv, secs, usecs)
 	for (; usecs >= 1000000; usecs -= 1000000)
 		++secs;
 
-	if (DB_GLOBAL(j_sleep) != NULL)
-		return (DB_GLOBAL(j_sleep)(secs, usecs));
+	if (DB_GLOBAL(j_sleep) != NULL) {
+		(void)DB_GLOBAL(j_sleep)(secs, usecs);
+		return;
+	}
 
 	/*
 	 * It's important that we yield the processor here so that other
 	 * processes or threads are permitted to run.
+	 *
+	 * Sheer raving paranoia -- don't select for 0 time.
 	 */
-	t.tv_sec = secs;
-	t.tv_usec = usecs;
-	do {
-		ret = select(0, NULL, NULL, NULL, &t) == -1 ?
-		    __os_get_errno() : 0;
-	} while (ret == EINTR);
-
-	if (ret != 0)
-		__db_err(dbenv, "select: %s", strerror(ret));
+	t.tv_sec = (long)secs;
+	if (secs == 0 && usecs == 0)
+		t.tv_usec = 1;
+	else
+		t.tv_usec = (long)usecs;
 
-	return (ret);
+	/*
+	 * We don't catch interrupts and restart the system call here, unlike
+	 * other Berkeley DB system calls.  This may be a user attempting to
+	 * interrupt a sleeping DB utility (for example, db_checkpoint), and
+	 * we want the utility to see the signal and quit.  This assumes it's
+	 * always OK for DB to sleep for less time than originally scheduled.
+	 */
+	if (select(0, NULL, NULL, NULL, &t) == -1)
+		 if ((ret = __os_get_errno()) != EINTR)
+			__db_err(dbenv, "select: %s", strerror(ret));
 }
diff --git a/storage/bdb/os/os_spin.c b/storage/bdb/os/os_spin.c
index fb36977cb44a47907733d54cce2dd99713119a36..23d4d71aec14c4a20a0044ad2e26b2cbceb6a55a 100644
--- a/storage/bdb/os/os_spin.c
+++ b/storage/bdb/os/os_spin.c
@@ -1,23 +1,21 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_spin.c,v 11.20 2004/06/23 14:10:56 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_spin.c,v 11.13 2002/08/07 02:02:07 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #if defined(HAVE_PSTAT_GETDYNAMIC)
 #include <sys/pstat.h>
 #endif
 
-#include <limits.h>
+#include <limits.h>			/* Needed for sysconf on Solaris. */
 #include <unistd.h>
 #endif
 
@@ -58,11 +56,11 @@ __os_sysconf()
 
 /*
  * __os_spin --
- *	Return the number of default spins before blocking.
+ *	Set the number of default spins before blocking.
  *
- * PUBLIC: int __os_spin __P((DB_ENV *));
+ * PUBLIC: void __os_spin __P((DB_ENV *));
  */
-int
+void
 __os_spin(dbenv)
 	DB_ENV *dbenv;
 {
@@ -70,13 +68,12 @@ __os_spin(dbenv)
 	 * If the application specified a value or we've already figured it
 	 * out, return it.
 	 *
-	 * XXX
-	 * We don't want to repeatedly call the underlying function because
-	 * it can be expensive (e.g., requiring multiple filesystem accesses
-	 * under Debian Linux).
+	 * Don't repeatedly call the underlying function because it can be
+	 * expensive (for example, taking multiple filesystem accesses under
+	 * Debian Linux).
 	 */
 	if (dbenv->tas_spins != 0)
-		return (dbenv->tas_spins);
+		return;
 
 	dbenv->tas_spins = 1;
 #if defined(HAVE_PSTAT_GETDYNAMIC)
@@ -92,8 +89,6 @@ __os_spin(dbenv)
 	 */
 	if (dbenv->tas_spins != 1)
 		dbenv->tas_spins *= 50;
-
-	return (dbenv->tas_spins);
 }
 
 /*
@@ -109,5 +104,8 @@ __os_yield(dbenv, usecs)
 {
 	if (DB_GLOBAL(j_yield) != NULL && DB_GLOBAL(j_yield)() == 0)
 		return;
-	(void)__os_sleep(dbenv, 0, usecs);
+#ifdef HAVE_VXWORKS
+	taskDelay(1);
+#endif
+	__os_sleep(dbenv, 0, usecs);
 }
diff --git a/storage/bdb/os/os_stat.c b/storage/bdb/os/os_stat.c
index c3510e36f5daacd883b0dd29f3f2bfdd7dd91cba..92cea98c0ced55f4006d717bb397eaeef95beb95 100644
--- a/storage/bdb/os/os_stat.c
+++ b/storage/bdb/os/os_stat.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_stat.c,v 11.27 2004/07/06 13:55:48 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_stat.c,v 11.20 2002/07/12 18:56:53 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -31,23 +29,17 @@ __os_exists(path, isdirp)
 	const char *path;
 	int *isdirp;
 {
-	int ret;
 	struct stat sb;
+	int ret;
 
 	if (DB_GLOBAL(j_exists) != NULL)
 		return (DB_GLOBAL(j_exists)(path, isdirp));
 
-	do {
-		ret =
 #ifdef HAVE_VXWORKS
-		    stat((char *)path, &sb);
+	RETRY_CHK((stat((char *)path, &sb)), ret);
 #else
-		    stat(path, &sb);
+	RETRY_CHK((stat(path, &sb)), ret);
 #endif
-		if (ret != 0)
-			ret = __os_get_errno();
-	} while (ret == EINTR);
-
 	if (ret != 0)
 		return (ret);
 
@@ -80,17 +72,18 @@ __os_ioinfo(dbenv, path, fhp, mbytesp, bytesp, iosizep)
 	DB_FH *fhp;
 	u_int32_t *mbytesp, *bytesp, *iosizep;
 {
-	int ret;
 	struct stat sb;
+	int ret;
 
 	if (DB_GLOBAL(j_ioinfo) != NULL)
 		return (DB_GLOBAL(j_ioinfo)(path,
 		    fhp->fd, mbytesp, bytesp, iosizep));
 
-retry:
-	if (fstat(fhp->fd, &sb) == -1) {
-		if ((ret = __os_get_errno()) == EINTR)
-			goto retry;
+	/* Check for illegal usage. */
+	DB_ASSERT(F_ISSET(fhp, DB_FH_OPENED) && fhp->fd != -1);
+
+	RETRY_CHK((fstat(fhp->fd, &sb)), ret);
+	if (ret != 0) {
 		__db_err(dbenv, "fstat: %s", strerror(ret));
 		return (ret);
 	}
diff --git a/storage/bdb/os/os_tmpdir.c b/storage/bdb/os/os_tmpdir.c
index 94645af5e71e5508650e6261400e0fc8a2b62298..c1abf3cff8467bd3736bbc68a4e0535654a336de 100644
--- a/storage/bdb/os/os_tmpdir.c
+++ b/storage/bdb/os/os_tmpdir.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1998-2002
+ * Copyright (c) 1998-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_tmpdir.c,v 11.24 2004/10/05 14:55:33 mjc Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_tmpdir.c,v 11.19 2002/01/11 15:53:02 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -98,17 +96,25 @@ __os_tmpdir(dbenv, flags)
 #endif
 #ifdef DB_WIN32
 	/* Get the path to the temporary directory. */
-	{int len;
-	char *eos, temp[MAXPATHLEN + 1];
+	{
+		int ret;
+		_TCHAR tpath[MAXPATHLEN + 1];
+		char *path, *eos;
 
-		if ((len = GetTempPath(sizeof(temp) - 1, temp)) > 2) {
-			eos = &temp[len];
-			*eos-- = '\0';
+		if (GetTempPath(MAXPATHLEN, tpath) > 2) {
+			FROM_TSTRING(dbenv, tpath, path, ret);
+			if (ret != 0)
+				return (ret);
+			eos = path + strlen(path) - 1;
 			if (*eos == '\\' || *eos == '/')
 				*eos = '\0';
-			if (__os_exists(temp, &isdir) == 0 && isdir != 0)
-				return (__os_strdup(dbenv,
-				    temp, &dbenv->db_tmp_dir));
+			if (__os_exists(path, &isdir) == 0 && isdir) {
+				ret = __os_strdup(dbenv,
+				    path, &dbenv->db_tmp_dir);
+				FREE_STRING(dbenv, path);
+				return (ret);
+			}
+			FREE_STRING(dbenv, path);
 		}
 	}
 #endif
diff --git a/storage/bdb/os/os_truncate.c b/storage/bdb/os/os_truncate.c
new file mode 100644
index 0000000000000000000000000000000000000000..0367fde73666a60100d966a5a76339bc2f79ddeb
--- /dev/null
+++ b/storage/bdb/os/os_truncate.c
@@ -0,0 +1,58 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_truncate.c,v 11.7 2004/09/17 22:00:31 mjc Exp $
+ */
+
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#include <unistd.h>
+#endif
+
+#include "db_int.h"
+
+/*
+ * __os_truncate --
+ *	Truncate the file.
+ *
+ * PUBLIC: int __os_truncate __P((DB_ENV *, DB_FH *, db_pgno_t, u_int32_t));
+ */
+int
+__os_truncate(dbenv, fhp, pgno, pgsize)
+	DB_ENV *dbenv;
+	DB_FH *fhp;
+	db_pgno_t pgno;
+	u_int32_t pgsize;
+{
+	off_t offset;
+	int ret;
+
+	/*
+	 * Truncate a file so that "pgno" is discarded from the end of the
+	 * file.
+	 */
+	offset = (off_t)pgsize * pgno;
+
+	if (DB_GLOBAL(j_ftruncate) != NULL)
+		ret = DB_GLOBAL(j_ftruncate)(fhp->fd, offset);
+	else {
+#ifdef HAVE_FTRUNCATE
+		RETRY_CHK((ftruncate(fhp->fd, offset)), ret);
+#else
+		ret = DB_OPNOTSUP;
+#endif
+	}
+
+	if (ret != 0)
+		__db_err(dbenv,
+		    "ftruncate: %lu: %s", (u_long)offset, strerror(ret));
+
+	return (ret);
+}
diff --git a/storage/bdb/os/os_unlink.c b/storage/bdb/os/os_unlink.c
index 28b03afd1aa5a8ac179d30d5440e55d66701510f..228e06d3918eed2bd0c183cd2bb721a7ae1d010a 100644
--- a/storage/bdb/os/os_unlink.c
+++ b/storage/bdb/os/os_unlink.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_unlink.c,v 11.28 2004/07/06 13:55:48 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_unlink.c,v 11.24 2002/07/12 18:56:53 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -69,41 +67,31 @@ __os_unlink(dbenv, path)
 {
 	int ret;
 
-retry:	ret = DB_GLOBAL(j_unlink) != NULL ?
-	    DB_GLOBAL(j_unlink)(path) :
+	if (DB_GLOBAL(j_unlink) != NULL)
+		ret = DB_GLOBAL(j_unlink)(path);
+	else
 #ifdef HAVE_VXWORKS
-	    unlink((char *)path);
+	    RETRY_CHK((unlink((char *)path)), ret);
 #else
-	    unlink(path);
-#endif
-	if (ret == -1) {
-		if ((ret = __os_get_errno()) == EINTR)
-			goto retry;
-		/*
-		 * XXX
-		 * We really shouldn't be looking at this value ourselves,
-		 * but ENOENT usually signals that a file is missing, and
-		 * we attempt to unlink things (such as v. 2.x environment
-		 * regions, in DB_ENV->remove) that we're expecting not to
-		 * be there.  Reporting errors in these cases is annoying.
-		 */
-#ifdef HAVE_VXWORKS
-		/*
-		 * XXX
-		 * The results of unlink are file system driver specific
-		 * on VxWorks.  In the case of removing a file that did
-		 * not exist, some, at least, return an error, but with
-		 * an errno of 0, not ENOENT.
-		 *
-		 * Code below falls through to original if-statement only
-		 * we didn't get a "successful" error.
-		 */
-		if (ret != 0)
-		/* FALLTHROUGH */
+	    RETRY_CHK((unlink(path)), ret);
 #endif
-		if (ret != ENOENT)
-			__db_err(dbenv, "unlink: %s: %s", path, strerror(ret));
-	}
+	/*
+	 * !!!
+	 * The results of unlink are file system driver specific on VxWorks.
+	 * In the case of removing a file that did not exist, some, at least,
+	 * return an error, but with an errno of 0, not ENOENT.  We do not
+	 * have to test for the explicitly, the RETRY_CHK macro resets "ret"
+	 * to be the errno, and so we'll just slide right on through.
+	 *
+	 * XXX
+	 * We shouldn't be testing for an errno of ENOENT here, but ENOENT
+	 * signals that a file is missing, and we attempt to unlink things
+	 * (such as v. 2.x environment regions, in DB_ENV->remove) that we
+	 * are expecting not to be there.  Reporting errors in these cases
+	 * is annoying.
+	 */
+	if (ret != 0 && ret != ENOENT)
+		__db_err(dbenv, "unlink: %s: %s", path, strerror(ret));
 
 	return (ret);
 }
diff --git a/storage/bdb/os_vxworks/os_vx_abs.c b/storage/bdb/os_vxworks/os_vx_abs.c
index 93e9be7269bc17f710bfe0c7121b360e1fc4af0d..34a1fe37a7b9982cbae66d5276ae21cdc4137a9d 100644
--- a/storage/bdb/os_vxworks/os_vx_abs.c
+++ b/storage/bdb/os_vxworks/os_vx_abs.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_vx_abs.c,v 1.9 2004/01/28 03:36:19 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_vx_abs.c,v 1.7 2002/01/11 15:53:02 bostic Exp $";
-#endif /* not lint */
-
 #include "db_int.h"
 #include "iosLib.h"
 
diff --git a/storage/bdb/os_vxworks/os_vx_config.c b/storage/bdb/os_vxworks/os_vx_config.c
index 810983b38ffabeca6f465794e347985b1bcd95c8..b90a4365df19a212590829bb1a1f7944b02366a1 100644
--- a/storage/bdb/os_vxworks/os_vx_config.c
+++ b/storage/bdb/os_vxworks/os_vx_config.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_vx_config.c,v 1.6 2004/01/28 03:36:19 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_vx_config.c,v 1.4 2002/01/11 15:53:03 bostic Exp $";
-#endif /* not lint */
-
 #include "db_int.h"
 
 /*
diff --git a/storage/bdb/os_vxworks/os_vx_map.c b/storage/bdb/os_vxworks/os_vx_map.c
index 8ad4f0765ce33f270d024ba3157fc0cc3c42ba0a..416f4cc8c2d51c333c8d3c4e8b47d53998de22ad 100644
--- a/storage/bdb/os_vxworks/os_vx_map.c
+++ b/storage/bdb/os_vxworks/os_vx_map.c
@@ -1,19 +1,17 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1998-2002
+ * Copyright (c) 1998-2004
  *	Sleepycat Software.  All rights reserved.
  *
  * This code is derived from software contributed to Sleepycat Software by
  * Frederick G.M. Roeber of Netscape Communications Corp.
+ *
+ * $Id: os_vx_map.c,v 1.23 2004/01/28 03:36:19 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_vx_map.c,v 1.21 2002/03/06 19:36:58 margo Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #include <string.h>
diff --git a/storage/bdb/os_win32/os_abs.c b/storage/bdb/os_win32/os_abs.c
index c8bead83ec3aea875583fc2b11c282f2dda2f2b8..ab05b0a7e84c6a425cb71256e360d4dbebefabe3 100644
--- a/storage/bdb/os_win32/os_abs.c
+++ b/storage/bdb/os_win32/os_abs.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_abs.c,v 11.7 2004/01/28 03:36:19 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_abs.c,v 11.5 2002/01/11 15:53:05 bostic Exp $";
-#endif /* not lint */
-
 #include "db_int.h"
 
 /*
diff --git a/storage/bdb/os_win32/os_clock.c b/storage/bdb/os_win32/os_clock.c
index 1bf154f9da97ab20490c6808d3fa0619920bd881..c77076691f7b80ac1e6281b7cf25a507438da698 100644
--- a/storage/bdb/os_win32/os_clock.c
+++ b/storage/bdb/os_win32/os_clock.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
+ * Copyright (c) 2001-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_clock.c,v 1.11 2004/06/28 13:57:18 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_clock.c,v 1.7 2002/07/12 18:56:53 bostic Exp $";
-#endif /* not lint */
-
 #include <sys/types.h>
 #include <sys/timeb.h>
 #include <string.h>
@@ -21,7 +19,7 @@ static const char revid[] = "$Id: os_clock.c,v 1.7 2002/07/12 18:56:53 bostic Ex
  * __os_clock --
  *	Return the current time-of-day clock in seconds and microseconds.
  */
-int
+void
 __os_clock(dbenv, secsp, usecsp)
 	DB_ENV *dbenv;
 	u_int32_t *secsp, *usecsp;	/* Seconds and microseconds. */
@@ -33,5 +31,4 @@ __os_clock(dbenv, secsp, usecsp)
 		*secsp = (u_int32_t)now.time;
 	if (usecsp != NULL)
 		*usecsp = now.millitm * 1000;
-	return (0);
 }
diff --git a/storage/bdb/os_win32/os_config.c b/storage/bdb/os_win32/os_config.c
index a2c220daf1aacda55d2592eb4ff6e7c2b0662a44..41daebd37e0e4037076d8b7750221ea92ffe6433 100644
--- a/storage/bdb/os_win32/os_config.c
+++ b/storage/bdb/os_win32/os_config.c
@@ -1,18 +1,40 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_config.c,v 11.18 2004/02/09 20:54:27 mjc Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_config.c,v 11.13 2002/01/11 15:53:06 bostic Exp $";
-#endif /* not lint */
-
 #include "db_int.h"
 
+/*
+ * __os_is_winnt --
+ *	Return 1 if Windows/NT, otherwise 0.
+ *
+ * PUBLIC: int __os_is_winnt __P((void));
+ */
+int
+__os_is_winnt()
+{
+	static int __os_type = -1;
+
+	/*
+	 * The value of __os_type is computed only once, and cached to
+	 * avoid the overhead of repeated calls to GetVersion().
+	 */
+	if (__os_type == -1) {
+		if ((GetVersion() & 0x80000000) == 0)
+			__os_type = 1;
+		else
+			__os_type = 0;
+	}
+	return (__os_type);
+}
+
 /*
  * __os_fs_notzero --
  *	Return 1 if allocated filesystem blocks are not zeroed.
@@ -20,10 +42,47 @@ static const char revid[] = "$Id: os_config.c,v 11.13 2002/01/11 15:53:06 bostic
 int
 __os_fs_notzero()
 {
+	static int __os_notzero = -1;
+	OSVERSIONINFO osvi;
+
 	/*
 	 * Windows/NT zero-fills pages that were never explicitly written to
-	 * the file.  Windows 95/98 gives you random garbage, and that breaks
+	 * the file.  Note however that this is *NOT* documented.  In fact, the
+	 * Win32 documentation makes it clear that there are no guarantees that
+	 * uninitialized bytes will be zeroed:
+	 *
+	 *   If the file is extended, the contents of the file between the old
+	 *   EOF position and the new position are not defined.
+	 *
+	 * Experiments confirm that NT/2K/XP all zero fill for both NTFS and
+	 * FAT32.  Cygwin also relies on this behavior.  This is the relevant
+	 * comment from Cygwin:
+	 *
+	 *    Oops, this is the bug case - Win95 uses whatever is on the disk
+	 *    instead of some known (safe) value, so we must seek back and fill
+	 *    in the gap with zeros. - DJ
+	 *    Note: this bug doesn't happen on NT4, even though the
+	 *    documentation for WriteFile() says that it *may* happen on any OS.
+	 *
+	 * We're making a bet, here, but we made it a long time ago and haven't
+	 * yet seen any evidence that it was wrong.
+	 *
+	 * Windows 95/98 and On-Time give random garbage, and that breaks
 	 * Berkeley DB.
+	 *
+	 * The value of __os_notzero is computed only once, and cached to
+	 * avoid the overhead of repeated calls to GetVersion().
 	 */
-	return (__os_is_winnt() ? 0 : 1);
+	if (__os_notzero == -1) {
+		if (__os_is_winnt()) {
+			osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+			GetVersionEx(&osvi);
+			if (_tcscmp(osvi.szCSDVersion, _T("RTTarget-32")) == 0)
+				__os_notzero = 1;	/* On-Time */
+			else
+				__os_notzero = 0;	/* Windows/NT */
+		} else
+			__os_notzero = 1;		/* Not Windows/NT */
+	}
+	return (__os_notzero);
 }
diff --git a/storage/bdb/os_win32/os_dir.c b/storage/bdb/os_win32/os_dir.c
index 3f47c4960b0dae89771ff5a4509a9e0e0678c3bb..e0abbb6ee16e049a01eac22f7a52ef857a128277 100644
--- a/storage/bdb/os_win32/os_dir.c
+++ b/storage/bdb/os_win32/os_dir.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_dir.c,v 11.20 2004/10/13 19:12:17 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_dir.c,v 11.12 2002/07/12 18:56:54 bostic Exp $";
-#endif /* not lint */
-
 #include "db_int.h"
 
 /*
@@ -24,44 +22,62 @@ __os_dirlist(dbenv, dir, namesp, cntp)
 	char ***namesp;
 	int *cntp;
 {
-	struct _finddata_t fdata;
-#ifdef _WIN64
-	intptr_t dirhandle;
-#else
-	long dirhandle;
-#endif
-	int arraysz, cnt, finished, ret;
-	char **names, filespec[MAXPATHLEN];
+	HANDLE dirhandle;
+	WIN32_FIND_DATA fdata;
+	int arraysz, cnt, ret;
+	char **names, *onename;
+	_TCHAR tfilespec[MAXPATHLEN + 1];
 
 	if (DB_GLOBAL(j_dirlist) != NULL)
 		return (DB_GLOBAL(j_dirlist)(dir, namesp, cntp));
 
-	(void)snprintf(filespec, sizeof(filespec), "%s/*", dir);
-	if ((dirhandle = _findfirst(filespec, &fdata)) == -1)
+	(void)_sntprintf(tfilespec, MAXPATHLEN,
+	    _T("%hs%hc*"), dir, PATH_SEPARATOR[0]);
+	if ((dirhandle = FindFirstFile(tfilespec, &fdata))
+	    == INVALID_HANDLE_VALUE)
 		return (__os_get_errno());
 
 	names = NULL;
-	finished = 0;
-	for (arraysz = cnt = 0; finished != 1; ++cnt) {
+	arraysz = cnt = ret = 0;
+	for (;;) {
 		if (cnt >= arraysz) {
 			arraysz += 100;
 			if ((ret = __os_realloc(dbenv,
 			    arraysz * sizeof(names[0]), &names)) != 0)
-				goto nomem;
+				goto err;
+		}
+		/*
+		 * FROM_TSTRING doesn't necessarily allocate new memory, so we
+		 * must do that explicitly.  Unfortunately, when compiled with
+		 * UNICODE, we'll copy twice.
+		 */
+		FROM_TSTRING(dbenv, fdata.cFileName, onename, ret);
+		if (ret != 0)
+			goto err;
+		ret = __os_strdup(dbenv, onename, &names[cnt]);
+		FREE_STRING(dbenv, onename);
+		if (ret != 0)
+			goto err;
+		cnt++;
+		if (!FindNextFile(dirhandle, &fdata)) {
+			if (GetLastError() == ERROR_NO_MORE_FILES)
+				break;
+			else {
+				ret = __os_get_errno();
+				goto err;
+			}
 		}
-		if ((ret = __os_strdup(dbenv, fdata.name, &names[cnt])) != 0)
-			goto nomem;
-		if (_findnext(dirhandle, &fdata) != 0)
-			finished = 1;
 	}
-	_findclose(dirhandle);
 
-	*namesp = names;
-	*cntp = cnt;
-	return (0);
+err:	if (!FindClose(dirhandle) && ret == 0)
+		ret = __os_get_errno();
 
-nomem:	if (names != NULL)
+	if (ret == 0) {
+		*namesp = names;
+		*cntp = cnt;
+	} else if (names != NULL)
 		__os_dirfree(dbenv, names, cnt);
+
 	return (ret);
 }
 
diff --git a/storage/bdb/os_win32/os_errno.c b/storage/bdb/os_win32/os_errno.c
index d6fac82e6f3923a5d5a3baaf26ebe9ca8d850285..1af2824cc78eee9688bd7bb03fae1d686bbdc428 100644
--- a/storage/bdb/os_win32/os_errno.c
+++ b/storage/bdb/os_win32/os_errno.c
@@ -1,65 +1,46 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_errno.c,v 11.14 2004/07/06 21:06:38 mjc Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_errno.c,v 11.10 2002/07/12 04:05:00 mjc Exp $";
-#endif /* not lint */
-
 #include "db_int.h"
 
 /*
- * __os_get_errno --
- *	Return the value of errno.
+ * __os_get_errno_ret_zero --
+ *	Return the value of errno, even if it's zero.
  */
 int
-__os_get_errno()
+__os_get_errno_ret_zero()
 {
 	/* This routine must be able to return the same value repeatedly. */
 	return (errno);
 }
 
 /*
- * __os_set_errno --
- *	Set the value of errno.
- */
-void
-__os_set_errno(evalue)
-	int evalue;
-{
-	errno = evalue;
-}
-
-/*
- * __os_win32_errno --
+ * __os_get_errno --
  *	Return the last Windows error as an errno.
  *	We give generic error returns:
  *
  *	EFAULT means Win* call failed,
  *	  and GetLastError provided no extra info.
  *
- *	EIO means error on Win* call.
+ *	EIO means error on Win* call,
  *	  and we were unable to provide a meaningful errno for this Windows
  *	  error.  More information is only available by setting a breakpoint
  *	  here.
- *
- * PUBLIC: #if defined(DB_WIN32)
- * PUBLIC: int __os_win32_errno __P((void));
- * PUBLIC: #endif
  */
 int
-__os_win32_errno(void)
+__os_get_errno()
 {
 	DWORD last_error;
 	int ret;
 
-	/* Ignore errno - we used to check it here. */
-
 	last_error = GetLastError();
 
 	/*
@@ -92,6 +73,7 @@ __os_win32_errno(void)
 
 	case ERROR_DISK_FULL:
 		ret = ENOSPC;
+		break;
 
 	case ERROR_ARENA_TRASHED:
 	case ERROR_BAD_COMMAND:
@@ -143,3 +125,14 @@ __os_win32_errno(void)
 
 	return (ret);
 }
+
+/*
+ * __os_set_errno --
+ *	Set the value of errno.
+ */
+void
+__os_set_errno(evalue)
+	int evalue;
+{
+	errno = evalue;
+}
diff --git a/storage/bdb/os_win32/os_fid.c b/storage/bdb/os_win32/os_fid.c
index 1190ad26e8109e1e595c85d361682aeeb0cd5918..69df865d4492ec3aef6358ea595f340c761bf49c 100644
--- a/storage/bdb/os_win32/os_fid.c
+++ b/storage/bdb/os_win32/os_fid.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_fid.c,v 11.19 2004/07/06 21:06:38 mjc Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_fid.c,v 11.15 2002/08/26 14:37:39 margo Exp $";
-#endif /* not lint */
-
 #include "db_int.h"
 
 #define	SERIAL_INIT	0
@@ -39,7 +37,7 @@ __os_fileid(dbenv, fname, unique_okay, fidp)
 	 * but perhaps not on other platforms, and perhaps not over a network.
 	 * Can't think of a better solution right now.
 	 */
-	DB_FH fh;
+	DB_FH *fhp;
 	BY_HANDLE_FILE_INFORMATION fi;
 	BOOL retval = FALSE;
 
@@ -71,13 +69,13 @@ __os_fileid(dbenv, fname, unique_okay, fidp)
 	 * First we open the file, because we're not given a handle to it.
 	 * If we can't open it, we're in trouble.
 	 */
-	if ((ret = __os_open(dbenv, fname, DB_OSO_RDONLY, _S_IREAD, &fh)) != 0)
+	if ((ret = __os_open(dbenv, fname, DB_OSO_RDONLY, _S_IREAD, &fhp)) != 0)
 		return (ret);
 
 	/* File open, get its info */
-	if ((retval = GetFileInformationByHandle(fh.handle, &fi)) == FALSE)
-		ret = __os_win32_errno();
-	__os_closehandle(dbenv, &fh);
+	if ((retval = GetFileInformationByHandle(fhp->handle, &fi)) == FALSE)
+		ret = __os_get_errno();
+	(void)__os_closehandle(dbenv, fhp);
 
 	if (retval == FALSE)
 		return (ret);
diff --git a/storage/bdb/os_win32/os_fsync.c b/storage/bdb/os_win32/os_fsync.c
index 6fd3e1dcdf4326745466c4b65ecdda4a6f1b2dfc..cc188a2fed596d31436c363af30ddd5502019edf 100644
--- a/storage/bdb/os_win32/os_fsync.c
+++ b/storage/bdb/os_win32/os_fsync.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_fsync.c,v 11.21 2004/07/06 21:06:38 mjc Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_fsync.c,v 11.15 2002/07/12 18:56:54 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -24,15 +22,12 @@ static const char revid[] = "$Id: os_fsync.c,v 11.15 2002/07/12 18:56:54 bostic
 /*
  * __os_fsync --
  *	Flush a file descriptor.
- *
- * PUBLIC: int __os_fsync __P((DB_ENV *, DB_FH *));
  */
 int
 __os_fsync(dbenv, fhp)
 	DB_ENV *dbenv;
 	DB_FH *fhp;
 {
-	BOOL success;
 	int ret;
 
 	/*
@@ -42,16 +37,10 @@ __os_fsync(dbenv, fhp)
 	if (F_ISSET(fhp, DB_FH_NOSYNC))
 		return (0);
 
-	ret = 0;
-	do {
-		if (DB_GLOBAL(j_fsync) != NULL)
-			success = (DB_GLOBAL(j_fsync)(fhp->fd) == 0);
-		else {
-			success = FlushFileBuffers(fhp->handle);
-			if (!success)
-				__os_set_errno(__os_win32_errno());
-		}
-	} while (!success && (ret = __os_get_errno()) == EINTR);
+	if (DB_GLOBAL(j_fsync) != NULL)
+		ret = DB_GLOBAL(j_fsync)(fhp->fd);
+	else
+		RETRY_CHK((!FlushFileBuffers(fhp->handle)), ret);
 
 	if (ret != 0)
 		__db_err(dbenv, "fsync %s", strerror(ret));
diff --git a/storage/bdb/os_win32/os_handle.c b/storage/bdb/os_win32/os_handle.c
index 7db9c3da977a4459bb0506cb62c7fbb039f3f123..4953afd31000fde4af0a1d6928472b404f1032c2 100644
--- a/storage/bdb/os_win32/os_handle.c
+++ b/storage/bdb/os_win32/os_handle.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1998-2002
+ * Copyright (c) 1998-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_handle.c,v 11.39 2004/07/06 21:06:38 mjc Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_handle.c,v 11.30 2002/07/12 18:56:54 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -24,58 +22,69 @@ static const char revid[] = "$Id: os_handle.c,v 11.30 2002/07/12 18:56:54 bostic
 /*
  * __os_openhandle --
  *	Open a file, using POSIX 1003.1 open flags.
- *
- * PUBLIC: int __os_openhandle __P((DB_ENV *, const char *, int, int, DB_FH *));
  */
 int
-__os_openhandle(dbenv, name, flags, mode, fhp)
+__os_openhandle(dbenv, name, flags, mode, fhpp)
 	DB_ENV *dbenv;
 	const char *name;
 	int flags, mode;
-	DB_FH *fhp;
+	DB_FH **fhpp;
 {
-	int ret, nrepeat;
+	DB_FH *fhp;
+	int ret, nrepeat, retries;
 
-	memset(fhp, 0, sizeof(*fhp));
-	fhp->handle = INVALID_HANDLE_VALUE;
+	if ((ret = __os_calloc(dbenv, 1, sizeof(DB_FH), fhpp)) != 0)
+		return (ret);
+	fhp = *fhpp;
 
 	/* If the application specified an interface, use it. */
 	if (DB_GLOBAL(j_open) != NULL) {
-		if ((fhp->fd = DB_GLOBAL(j_open)(name, flags, mode)) == -1)
-			return (__os_get_errno());
-		F_SET(fhp, DB_FH_VALID);
+		if ((fhp->fd = DB_GLOBAL(j_open)(name, flags, mode)) == -1) {
+			ret = __os_get_errno();
+			goto err;
+		}
+		F_SET(fhp, DB_FH_OPENED);
 		return (0);
 	}
 
+	retries = 0;
 	for (nrepeat = 1; nrepeat < 4; ++nrepeat) {
 		ret = 0;
 		fhp->fd = open(name, flags, mode);
 
-		if (fhp->fd == -1) {
+		if (fhp->fd != -1) {
+			F_SET(fhp, DB_FH_OPENED);
+			break;
+		}
+
+		switch (ret = __os_get_errno()) {
+		case EMFILE:
+		case ENFILE:
+		case ENOSPC:
 			/*
 			 * If it's a "temporary" error, we retry up to 3 times,
 			 * waiting up to 12 seconds.  While it's not a problem
 			 * if we can't open a database, an inability to open a
 			 * log file is cause for serious dismay.
 			 */
-			ret = __os_get_errno();
-			if (ret == ENFILE || ret == EMFILE || ret == ENOSPC) {
-				(void)__os_sleep(dbenv, nrepeat * 2, 0);
-				continue;
-			}
-
+			__os_sleep(dbenv, nrepeat * 2, 0);
+			break;
+		case EAGAIN:
+		case EBUSY:
+		case EINTR:
 			/*
-			 * If it was an EINTR it's reasonable to retry
-			 * immediately, and arbitrarily often.
+			 * If an EAGAIN, EBUSY or EINTR, retry immediately for
+			 * DB_RETRY times.
 			 */
-			if (ret == EINTR) {
+			if (++retries < DB_RETRY)
 				--nrepeat;
-				continue;
-			}
-		} else {
-			F_SET(fhp, DB_FH_VALID);
+			break;
 		}
-		break;
+	}
+
+err:	if (ret != 0) {
+		(void)__os_closehandle(dbenv, fhp);
+		*fhpp = NULL;
 	}
 
 	return (ret);
@@ -84,43 +93,39 @@ __os_openhandle(dbenv, name, flags, mode, fhp)
 /*
  * __os_closehandle --
  *	Close a file.
- *
- * PUBLIC: int __os_closehandle __P((DB_ENV *, DB_FH *));
  */
 int
 __os_closehandle(dbenv, fhp)
 	DB_ENV *dbenv;
 	DB_FH *fhp;
 {
-	BOOL success;
 	int ret;
 
-	COMPQUIET(dbenv, NULL);
-	/* Don't close file descriptors that were never opened. */
-	DB_ASSERT(F_ISSET(fhp, DB_FH_VALID) &&
-	    ((fhp->fd != -1) || (fhp->handle != INVALID_HANDLE_VALUE)));
-
 	ret = 0;
 
-	do {
+	/*
+	 * If we have a valid handle, close it and unlink any temporary
+	 * file.
+	 */
+	if (F_ISSET(fhp, DB_FH_OPENED)) {
 		if (DB_GLOBAL(j_close) != NULL)
-			success = (DB_GLOBAL(j_close)(fhp->fd) == 0);
-		else if (fhp->handle != INVALID_HANDLE_VALUE) {
-			success = CloseHandle(fhp->handle);
-			if (!success)
-				__os_set_errno(__os_win32_errno());
-		}
+			ret = DB_GLOBAL(j_close)(fhp->fd);
+		else if (fhp->handle != INVALID_HANDLE_VALUE)
+			RETRY_CHK((!CloseHandle(fhp->handle)), ret);
 		else
-			success = (close(fhp->fd) == 0);
-	} while (!success && (ret = __os_get_errno()) == EINTR);
+			RETRY_CHK((close(fhp->fd)), ret);
 
-	/*
-	 * Smash the POSIX file descriptor -- it's never tested, but we want
-	 * to catch any mistakes.
-	 */
-	fhp->fd = -1;
-	fhp->handle = INVALID_HANDLE_VALUE;
-	F_CLR(fhp, DB_FH_VALID);
+		if (ret != 0)
+			__db_err(dbenv, "CloseHandle: %s", strerror(ret));
+
+		/* Unlink the file if we haven't already done so. */
+		if (F_ISSET(fhp, DB_FH_UNLINK)) {
+			(void)__os_unlink(dbenv, fhp->name);
+			__os_free(dbenv, fhp->name);
+		}
+	}
+
+	__os_free(dbenv, fhp);
 
 	return (ret);
 }
diff --git a/storage/bdb/os_win32/os_map.c b/storage/bdb/os_win32/os_map.c
index 1f16c9fead401d45174ce253c5dfb8b8aa8f5acc..140ac49802347f49b169bc0a0909b77c1603df81 100644
--- a/storage/bdb/os_win32/os_map.c
+++ b/storage/bdb/os_win32/os_map.c
@@ -1,21 +1,19 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_map.c,v 11.51 2004/10/05 14:55:34 mjc Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_map.c,v 11.38 2002/09/10 02:35:48 bostic Exp $";
-#endif /* not lint */
-
 #include "db_int.h"
 
 static int __os_map
   __P((DB_ENV *, char *, REGINFO *, DB_FH *, size_t, int, int, int, void **));
-static int __os_unique_name __P((char *, HANDLE, char *, size_t));
+static int __os_unique_name __P((_TCHAR *, HANDLE, _TCHAR *, size_t));
 
 /*
  * __os_r_sysattach --
@@ -27,7 +25,7 @@ __os_r_sysattach(dbenv, infop, rp)
 	REGINFO *infop;
 	REGION *rp;
 {
-	DB_FH fh;
+	DB_FH *fhp;
 	int is_system, ret;
 
 	/*
@@ -36,9 +34,8 @@ __os_r_sysattach(dbenv, infop, rp)
 	 * properly ordered, our caller has already taken care of that.
 	 */
 	if ((ret = __os_open(dbenv, infop->name,
-	    DB_OSO_DIRECT |
 	    F_ISSET(infop, REGION_CREATE_OK) ? DB_OSO_CREATE: 0,
-	    infop->mode, &fh)) != 0) {
+	    dbenv->db_mode, &fhp)) != 0) {
 		__db_err(dbenv, "%s: %s", infop->name, db_strerror(ret));
 		return (ret);
 	}
@@ -58,12 +55,12 @@ __os_r_sysattach(dbenv, infop, rp)
 	 * calling code writes out the REGENV_REF structure to the primary
 	 * environment file.
 	 */
-	ret = __os_map(dbenv, infop->name, infop, &fh, rp->size,
+	ret = __os_map(dbenv, infop->name, infop, fhp, rp->size,
 	   1, is_system, 0, &infop->addr);
 	if (ret == 0 && is_system == 1)
 		rp->segid = 1;
 
-	(void)__os_closehandle(dbenv, &fh);
+	(void)__os_closehandle(dbenv, fhp);
 
 	return (ret);
 }
@@ -81,11 +78,11 @@ __os_r_sysdetach(dbenv, infop, destroy)
 	int ret, t_ret;
 
 	if (infop->wnt_handle != NULL) {
-		(void)CloseHandle(*((HANDLE*)(infop->wnt_handle)));
-		__os_free(dbenv, infop->wnt_handle);
+		(void)CloseHandle(infop->wnt_handle);
+		infop->wnt_handle = NULL;
 	}
 
-	ret = !UnmapViewOfFile(infop->addr) ? __os_win32_errno() : 0;
+	ret = !UnmapViewOfFile(infop->addr) ? __os_get_errno() : 0;
 	if (ret != 0)
 		__db_err(dbenv, "UnmapViewOfFile: %s", strerror(ret));
 
@@ -133,7 +130,7 @@ __os_unmapfile(dbenv, addr, len)
 	if (DB_GLOBAL(j_unmap) != NULL)
 		return (DB_GLOBAL(j_unmap)(addr, len));
 
-	return (!UnmapViewOfFile(addr) ? __os_win32_errno() : 0);
+	return (!UnmapViewOfFile(addr) ? __os_get_errno() : 0);
 }
 
 /*
@@ -145,12 +142,12 @@ __os_unmapfile(dbenv, addr, len)
  *	names), and repeatable (same files, map to same names).  It's not
  *	so easy to do by name.  Should handle not only:
  *
- *		foo.bar  ==  ./foo.bar  ==  c:/whatever_path/foo.bar
+ *		foo.bar == ./foo.bar == c:/whatever_path/foo.bar
  *
  *	but also understand that:
  *
- *		foo.bar  ==  Foo.Bar	(FAT file system)
- *		foo.bar  !=  Foo.Bar	(NTFS)
+ *		foo.bar == Foo.Bar	(FAT file system)
+ *		foo.bar != Foo.Bar	(NTFS)
  *
  *	The best solution is to use the file index, found in the file
  *	information structure (similar to UNIX inode #).
@@ -165,24 +162,24 @@ __os_unmapfile(dbenv, addr, len)
  */
 static int
 __os_unique_name(orig_path, hfile, result_path, result_path_len)
-	char *orig_path, *result_path;
+	_TCHAR *orig_path, *result_path;
 	HANDLE hfile;
 	size_t result_path_len;
 {
 	BY_HANDLE_FILE_INFORMATION fileinfo;
-	char *basename, *p;
+	_TCHAR *basename, *p;
 
 	/*
 	 * In Windows, pathname components are delimited by '/' or '\', and
 	 * if neither is present, we need to strip off leading drive letter
 	 * (e.g. c:foo.txt).
 	 */
-	basename = strrchr(orig_path, '/');
-	p = strrchr(orig_path, '\\');
+	basename = _tcsrchr(orig_path, '/');
+	p = _tcsrchr(orig_path, '\\');
 	if (basename == NULL || (p != NULL && p > basename))
 		basename = p;
 	if (basename == NULL)
-		basename = strrchr(orig_path, ':');
+		basename = _tcsrchr(orig_path, ':');
 
 	if (basename == NULL)
 		basename = orig_path;
@@ -190,10 +187,10 @@ __os_unique_name(orig_path, hfile, result_path, result_path_len)
 		basename++;
 
 	if (!GetFileInformationByHandle(hfile, &fileinfo))
-		return (__os_win32_errno());
+		return (__os_get_errno());
 
-	(void)snprintf(result_path, result_path_len,
-	    "__db_shmem.%8.8lx.%8.8lx.%8.8lx.%8.8lx.%8.8lx.%s",
+	(void)_sntprintf(result_path, result_path_len,
+	    _T("__db_shmem.%8.8lx.%8.8lx.%8.8lx.%8.8lx.%8.8lx.%s"),
 	    fileinfo.dwVolumeSerialNumber,
 	    fileinfo.nFileIndexHigh,
 	    fileinfo.nFileIndexLow,
@@ -219,9 +216,8 @@ __os_map(dbenv, path, infop, fhp, len, is_region, is_system, is_rdonly, addr)
 	void **addr;
 {
 	HANDLE hMemory;
-	REGENV *renv;
 	int ret, use_pagefile;
-	char shmem_name[MAXPATHLEN];
+	_TCHAR *tpath, shmem_name[MAXPATHLEN];
 	void *pMemory;
 
 	ret = 0;
@@ -234,61 +230,66 @@ __os_map(dbenv, path, infop, fhp, len, is_region, is_system, is_rdonly, addr)
 	 * If creating a region in system space, get a matching name in the
 	 * paging file namespace.
 	 */
-	if (use_pagefile && (ret = __os_unique_name(
-	    path, fhp->handle, shmem_name, sizeof(shmem_name))) != 0)
-		return (ret);
+	if (use_pagefile) {
+		TO_TSTRING(dbenv, path, tpath, ret);
+		if (ret != 0)
+			return (ret);
+		ret = __os_unique_name(tpath, fhp->handle,
+		    shmem_name, sizeof(shmem_name));
+		FREE_STRING(dbenv, tpath);
+		if (ret != 0)
+			return (ret);
+	}
 
 	/*
 	 * XXX
 	 * DB: We have not implemented copy-on-write here.
 	 *
-	 * XXX
-	 * DB: This code will fail if the library is ever compiled on a 64-bit
-	 * machine.
+	 * If this is an region in system memory, we try to open it using the
+	 * OpenFileMapping() first, and only call CreateFileMapping() if we're
+	 * really creating the section.  There are two reasons:
 	 *
-	 * XXX
-	 * If this is an region in system memory, let's try opening using the
-	 * OpenFileMapping() first.  Why, oh why are we doing this?
+	 * 1) We only create the mapping if we have newly created the region.
+	 *    This avoids a long-running problem caused by Windows reference
+	 *    counting, where regions that are closed by all processes are
+	 *    deleted.  It turns out that just checking for a zeroed region
+	 *    is not good enough. See [#4882] and [#7127] for the details.
 	 *
-	 * Well, we might be asking the OS for a handle to a pre-existing
-	 * memory section, or we might be the first to get here and want the
-	 * section created. CreateFileMapping() sounds like it will do both
-	 * jobs. But, not so. It seems to mess up making the commit charge to
-	 * the process. It thinks, incorrectly, that when we want to join a
-	 * previously existing section, that it should make a commit charge
-	 * for the whole section.  In fact, there is no new committed memory
-	 * whatever.  The call can fail if there is insufficient memory free
-	 * to handle the erroneous commit charge.  So, we find that the bogus
-	 * commit is not made if we call OpenFileMapping().  So we do that
-	 * first, and only call CreateFileMapping() if we're really creating
-	 * the section.
+	 * 2) CreateFileMapping seems to mess up making the commit charge to
+	 *    the process. It thinks, incorrectly, that when we want to join a
+	 *    previously existing section, that it should make a commit charge
+	 *    for the whole section.  In fact, there is no new committed memory
+	 *    whatever.  The call can fail if there is insufficient memory free
+	 *    to handle the erroneous commit charge.  So, we find that the
+	 *    bogus commit is not made if we call OpenFileMapping.
 	 */
 	hMemory = NULL;
-	if (use_pagefile)
+	if (use_pagefile) {
 		hMemory = OpenFileMapping(
 		    is_rdonly ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS,
-		    0,
-		    shmem_name);
+		    0, shmem_name);
 
-	if (hMemory == NULL)
-		hMemory = CreateFileMapping(
-		    use_pagefile ? (HANDLE)-1 : fhp->handle,
-		    0,
+		if (hMemory == NULL && F_ISSET(infop, REGION_CREATE_OK))
+			hMemory = CreateFileMapping((HANDLE)-1, 0,
+			    is_rdonly ? PAGE_READONLY : PAGE_READWRITE,
+			    0, (DWORD)len, shmem_name);
+	} else
+		hMemory = CreateFileMapping(fhp->handle, 0,
 		    is_rdonly ? PAGE_READONLY : PAGE_READWRITE,
-		    0, (DWORD)len,
-		    use_pagefile ? shmem_name : NULL);
+		    0, (DWORD)len, NULL);
+
 	if (hMemory == NULL) {
-		ret = __os_win32_errno();
+		ret = __os_get_errno();
 		__db_err(dbenv, "OpenFileMapping: %s", strerror(ret));
-		return (ret);
+		return (__db_panic(dbenv, ret));
 	}
 
 	pMemory = MapViewOfFile(hMemory,
 	    (is_rdonly ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS), 0, 0, len);
 	if (pMemory == NULL) {
-		ret = __os_win32_errno();
+		ret = __os_get_errno();
 		__db_err(dbenv, "MapViewOfFile: %s", strerror(ret));
-		return (ret);
+		return (__db_panic(dbenv, ret));
 	}
 
 	/*
@@ -302,37 +303,13 @@ __os_map(dbenv, path, infop, fhp, len, is_region, is_system, is_rdonly, addr)
 	 * different identity. The two processes then have distinct isolated
 	 * mapped sections, not at all what was wanted. Not closing the handle
 	 * here fixes this problem.  We carry the handle around in the region
-	 * structure so we can close it when unmap is called.  Ignore malloc
-	 * errors, it just means we leak the memory.
+	 * structure so we can close it when unmap is called.
 	 */
-	if (use_pagefile && infop != NULL) {
-		if (__os_malloc(dbenv,
-		    sizeof(HANDLE), &infop->wnt_handle) == 0)
-			memcpy(infop->wnt_handle, &hMemory, sizeof(HANDLE));
-	} else
+	if (use_pagefile && infop != NULL)
+		infop->wnt_handle = hMemory;
+	else
 		CloseHandle(hMemory);
 
-	if (is_region) {
-		/*
-		 * XXX
-		 * Windows/95 zeroes anonymous memory regions at last close.
-		 * This means that the backing file can exist and reference
-		 * the region, but the region itself is no longer initialized.
-		 * If the caller is capable of creating the region, update
-		 * the REGINFO structure so that they do so.
-		 */
-		renv = (REGENV *)pMemory;
-		if (renv->magic == 0) {
-			if (F_ISSET(infop, REGION_CREATE_OK))
-				F_SET(infop, REGION_CREATE);
-			else {
-				(void)UnmapViewOfFile(pMemory);
-				pMemory = NULL;
-				ret = EAGAIN;
-			}
-		}
-	}
-
 	*addr = pMemory;
 	return (ret);
 }
diff --git a/storage/bdb/os_win32/os_open.c b/storage/bdb/os_win32/os_open.c
index c8bae54d585362edc1e302e6bcb836dc0829855b..1aa65cfa077901592361614e360e1749aedc2363 100644
--- a/storage/bdb/os_win32/os_open.c
+++ b/storage/bdb/os_win32/os_open.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_open.c,v 11.37 2004/10/05 14:55:35 mjc Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_open.c,v 11.21 2002/07/12 18:56:55 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -22,32 +20,59 @@ static const char revid[] = "$Id: os_open.c,v 11.21 2002/07/12 18:56:55 bostic E
 
 #include "db_int.h"
 
+/*
+ * __os_have_direct --
+ *	Check to see if we support direct I/O.
+ *
+ * PUBLIC: int __os_have_direct __P((void));
+ */
+int
+__os_have_direct()
+{
+	return (1);
+}
+
 /*
  * __os_open --
  *	Open a file descriptor.
  */
-int
-__os_open(dbenv, name, flags, mode, fhp)
+__os_open(dbenv, name, flags, mode, fhpp)
 	DB_ENV *dbenv;
 	const char *name;
 	u_int32_t flags;
 	int mode;
-	DB_FH *fhp;
+	DB_FH **fhpp;
+{
+	return (__os_open_extend(dbenv, name, 0, flags, mode, fhpp));
+}
+
+/*
+ * __os_open_extend --
+ *	Open a file descriptor (including page size and log size information).
+ */
+int
+__os_open_extend(dbenv, name, page_size, flags, mode, fhpp)
+	DB_ENV *dbenv;
+	const char *name;
+	u_int32_t page_size, flags;
+	int mode;
+	DB_FH **fhpp;
 {
-	DWORD bytesWritten;
-	u_int32_t log_size, pagesize, sectorsize;
-	int access, attr, oflags, share, createflag;
-	int ret, nrepeat;
-	char *drive, dbuf[4]; /* <letter><colon><slosh><nul> */
+	DB_FH *fhp;
+	DWORD cluster_size, sector_size, free_clusters, total_clusters;
+	int access, attr, createflag, nrepeat, oflags, ret, share;
+	_TCHAR *drive, *tname;
+	_TCHAR dbuf[4]; /* <letter><colon><slash><nul> */
+
+	fhp = NULL;
+	tname = NULL;
 
-#ifdef DIAGNOSTIC
 #define	OKFLAGS								\
-	(DB_OSO_CREATE | DB_OSO_DIRECT | DB_OSO_EXCL | DB_OSO_LOG |	\
-	 DB_OSO_RDONLY | DB_OSO_REGION | DB_OSO_SEQ | DB_OSO_TEMP |	\
-	 DB_OSO_TRUNC)
+	(DB_OSO_CREATE | DB_OSO_DIRECT | DB_OSO_DSYNC | DB_OSO_EXCL |	\
+	 DB_OSO_LOG | DB_OSO_RDONLY | DB_OSO_REGION | DB_OSO_SEQ |	\
+	 DB_OSO_TEMP | DB_OSO_TRUNC)
 	if ((ret = __db_fchk(dbenv, "__os_open", flags, OKFLAGS)) != 0)
 		return (ret);
-#endif
 
 	/*
 	 * The "public" interface to the __os_open routine passes around POSIX
@@ -59,6 +84,10 @@ __os_open(dbenv, name, flags, mode, fhp)
 
 		if (LF_ISSET(DB_OSO_CREATE))
 			oflags |= O_CREAT;
+#ifdef O_DSYNC
+		if (LF_ISSET(DB_OSO_LOG) && LF_ISSET(DB_OSO_DSYNC))
+			oflags |= O_DSYNC;
+#endif
 
 		if (LF_ISSET(DB_OSO_EXCL))
 			oflags |= O_EXCL;
@@ -79,18 +108,15 @@ __os_open(dbenv, name, flags, mode, fhp)
 		if (LF_ISSET(DB_OSO_TRUNC))
 			oflags |= O_TRUNC;
 
-		return (__os_openhandle(dbenv, name, oflags, mode, fhp));
+		return (__os_openhandle(dbenv, name, oflags, mode, fhpp));
 	}
 
-	ret = 0;
-
-	if (LF_ISSET(DB_OSO_LOG))
-		log_size = fhp->log_size;			/* XXX: Gag. */
+	TO_TSTRING(dbenv, name, tname, ret);
+	if (ret != 0)
+		goto err;
 
-	pagesize = fhp->pagesize;
-
-	memset(fhp, 0, sizeof(*fhp));
-	fhp->fd = -1;
+	if ((ret = __os_calloc(dbenv, 1, sizeof(DB_FH), &fhp)) != 0)
+		goto err;
 
 	/*
 	 * Otherwise, use the Windows/32 CreateFile interface so that we can
@@ -130,7 +156,7 @@ __os_open(dbenv, name, flags, mode, fhp)
 	else
 		createflag = OPEN_EXISTING;	/* open only if existing */
 
-	if (LF_ISSET(DB_OSO_LOG)) {
+	if (LF_ISSET(DB_OSO_LOG) && LF_ISSET(DB_OSO_DSYNC)) {
 		F_SET(fhp, DB_FH_NOSYNC);
 		attr |= FILE_FLAG_WRITE_THROUGH;
 	}
@@ -149,21 +175,26 @@ __os_open(dbenv, name, flags, mode, fhp)
 	 * we call GetDiskFreeSpace, which expects a drive name like "d:\\"
 	 * or NULL for the current disk (i.e., a relative path)
 	 */
-	if (LF_ISSET(DB_OSO_DIRECT) && pagesize != 0 && name[0] != '\0') {
+	if (LF_ISSET(DB_OSO_DIRECT) && page_size != 0 && name[0] != '\0') {
 		if (name[1] == ':') {
 			drive = dbuf;
-			snprintf(dbuf, sizeof(dbuf), "%c:\\", name[0]);
+			_sntprintf(dbuf, sizeof(dbuf), _T("%c:\\"), tname[0]);
 		} else
 			drive = NULL;
 
-		if (GetDiskFreeSpace(drive, NULL, &sectorsize, NULL, NULL) &&
-		    pagesize % sectorsize == 0)
+		/*
+		 * We ignore all results except sectorsize, but some versions
+		 * of Windows require that the parameters are non-NULL.
+		 */
+		if (GetDiskFreeSpace(drive, &cluster_size,
+		    &sector_size, &free_clusters, &total_clusters) &&
+		    page_size % sector_size == 0)
 			attr |= FILE_FLAG_NO_BUFFERING;
 	}
 
 	for (nrepeat = 1;; ++nrepeat) {
 		fhp->handle =
-		    CreateFile(name, access, share, NULL, createflag, attr, 0);
+		    CreateFile(tname, access, share, NULL, createflag, attr, 0);
 		if (fhp->handle == INVALID_HANDLE_VALUE) {
 			/*
 			 * If it's a "temporary" error, we retry up to 3 times,
@@ -171,47 +202,27 @@ __os_open(dbenv, name, flags, mode, fhp)
 			 * if we can't open a database, an inability to open a
 			 * log file is cause for serious dismay.
 			 */
-			ret = __os_win32_errno();
+			ret = __os_get_errno();
 			if ((ret != ENFILE && ret != EMFILE && ret != ENOSPC) ||
 			    nrepeat > 3)
 				goto err;
 
-			(void)__os_sleep(dbenv, nrepeat * 2, 0);
+			__os_sleep(dbenv, nrepeat * 2, 0);
 		} else
 			break;
 	}
 
-	/*
-	 * Special handling needed for log files.  To get Windows to not update
-	 * the MFT metadata on each write, extend the file to its maximum size.
-	 * Windows will allocate all the data blocks and store them in the MFT
-	 * (inode) area.  In addition, flush the MFT area to disk.
-	 * This strategy only works for Win/NT; Win/9X does not
-	 * guarantee that the logs will be zero filled.
-	 */
-	if (LF_ISSET(DB_OSO_LOG) && log_size != 0 && __os_is_winnt()) {
-		if (SetFilePointer(fhp->handle,
-		    log_size - 1, NULL, FILE_BEGIN) == (DWORD)-1)
-			goto err;
-		if (WriteFile(fhp->handle, "\x00", 1, &bytesWritten, NULL) == 0)
-			goto err;
-		if (bytesWritten != 1)
-			goto err;
-		if (SetEndOfFile(fhp->handle) == 0)
-			goto err;
-		if (SetFilePointer(
-		    fhp->handle, 0, NULL, FILE_BEGIN) == (DWORD)-1)
-			goto err;
-		if (FlushFileBuffers(fhp->handle) == 0)
-			goto err;
-	}
+	FREE_STRING(dbenv, tname);
 
-	F_SET(fhp, DB_FH_VALID);
+	F_SET(fhp, DB_FH_OPENED);
+	*fhpp = fhp;
 	return (0);
 
 err:	if (ret == 0)
-		ret = __os_win32_errno();
-	if (fhp->handle != INVALID_HANDLE_VALUE)
-		(void)CloseHandle(fhp->handle);
+		ret = __os_get_errno();
+
+	FREE_STRING(dbenv, tname);
+	if (fhp != NULL)
+		(void)__os_closehandle(dbenv, fhp);
 	return (ret);
 }
diff --git a/storage/bdb/os_win32/os_rename.c b/storage/bdb/os_win32/os_rename.c
index 67c3846649b5358c9d887c2e9eb08b136358f27a..102633231888d215c76c5801013bf5873500bd39 100644
--- a/storage/bdb/os_win32/os_rename.c
+++ b/storage/bdb/os_win32/os_rename.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_rename.c,v 1.19 2004/10/05 14:55:36 mjc Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_rename.c,v 1.12 2002/07/12 18:56:55 bostic Exp $";
-#endif /* not lint */
-
 #include "db_int.h"
 
 /*
@@ -24,7 +22,7 @@ __os_rename(dbenv, oldname, newname, flags)
 	u_int32_t flags;
 {
 	int ret;
-	char oldbuf[MAX_PATH], newbuf[MAX_PATH];
+	_TCHAR *toldname, *tnewname;
 
 	ret = 0;
 	if (DB_GLOBAL(j_rename) != NULL) {
@@ -33,42 +31,39 @@ __os_rename(dbenv, oldname, newname, flags)
 		goto done;
 	}
 
-	if (!MoveFile(oldname, newname))
-		ret = __os_win32_errno();
+	TO_TSTRING(dbenv, oldname, toldname, ret);
+	if (ret != 0)
+		goto done;
+	TO_TSTRING(dbenv, newname, tnewname, ret);
+	if (ret != 0)
+		goto err;
+
+	if (!MoveFile(toldname, tnewname))
+		ret = __os_get_errno();
 
 	if (ret == EEXIST) {
 		ret = 0;
 		if (__os_is_winnt()) {
 			if (!MoveFileEx(
-			    oldname, newname, MOVEFILE_REPLACE_EXISTING))
-				ret = __os_win32_errno();
+			    toldname, tnewname, MOVEFILE_REPLACE_EXISTING))
+				ret = __os_get_errno();
 		} else {
 			/*
 			 * There is no MoveFileEx for Win9x/Me, so we have to
-			 * do the best we can.
+			 * do the best we can.  Note that the MoveFile call
+			 * above would have succeeded if oldname and newname
+			 * refer to the same file, so we don't need to check
+			 * that here.
 			 */
-			LPTSTR FilePath;
-			if (!GetFullPathName(oldname, sizeof(oldbuf), oldbuf,
-					     &FilePath) ||
-			    !GetFullPathName(newname, sizeof(newbuf), newbuf,
-					     &FilePath)) {
-				ret = __os_win32_errno();
-				goto done;
-			}
-
-			/*
-			 * If the old and new names differ only in case, we're
-			 * done.
-			 */
-			if (strcasecmp(oldbuf, newbuf) == 0)
-				goto done;
-
-			(void)DeleteFile(newname);
-			if (!MoveFile(oldname, newname))
-				ret = __os_win32_errno();
+			(void)DeleteFile(tnewname);
+			if (!MoveFile(toldname, tnewname))
+				ret = __os_get_errno();
 		}
 	}
 
+	FREE_STRING(dbenv, tnewname);
+err:	FREE_STRING(dbenv, toldname);
+
 done:	if (ret != 0 && flags == 0)
 		__db_err(dbenv,
 		    "Rename %s %s: %s", oldname, newname, strerror(ret));
diff --git a/storage/bdb/os_win32/os_rw.c b/storage/bdb/os_win32/os_rw.c
index 63d1f715c5315225f3f732c1b98e728b277d4581..c3c103a9ed8a49533d358eebfaa18f9d1edaa341 100644
--- a/storage/bdb/os_win32/os_rw.c
+++ b/storage/bdb/os_win32/os_rw.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_rw.c,v 11.38 2004/09/17 22:00:32 mjc Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_rw.c,v 11.28 2002/08/06 04:56:19 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -20,23 +18,29 @@ static const char revid[] = "$Id: os_rw.c,v 11.28 2002/08/06 04:56:19 bostic Exp
 
 #include "db_int.h"
 
+#ifdef HAVE_FILESYSTEM_NOTZERO
+static int __os_zerofill __P((DB_ENV *, DB_FH *));
+#endif
+static int __os_physwrite __P((DB_ENV *, DB_FH *, void *, size_t, size_t *));
+
 /*
  * __os_io --
  *	Do an I/O.
- *
- * PUBLIC: int __os_io __P((DB_ENV *, DB_IO *, int, size_t *));
  */
 int
-__os_io(dbenv, db_iop, op, niop)
+__os_io(dbenv, op, fhp, pgno, pagesize, buf, niop)
 	DB_ENV *dbenv;
-	DB_IO *db_iop;
 	int op;
+	DB_FH *fhp;
+	db_pgno_t pgno;
+	u_int32_t pagesize;
+	u_int8_t *buf;
 	size_t *niop;
 {
 	int ret;
 
 	if (__os_is_winnt()) {
-		ULONG64 off = (ULONG64)db_iop->pagesize * db_iop->pgno;
+		ULONG64 off = (ULONG64)pagesize * pgno;
 		OVERLAPPED over;
 		DWORD nbytes;
 		over.Offset = (DWORD)(off & 0xffffffff);
@@ -47,42 +51,44 @@ __os_io(dbenv, db_iop, op, niop)
 		case DB_IO_READ:
 			if (DB_GLOBAL(j_read) != NULL)
 				goto slow;
-			if (!ReadFile(db_iop->fhp->handle,
-			    db_iop->buf, (DWORD)db_iop->bytes, &nbytes, &over))
+			if (!ReadFile(fhp->handle,
+			    buf, (DWORD)pagesize, &nbytes, &over))
 				goto slow;
 			break;
 		case DB_IO_WRITE:
 			if (DB_GLOBAL(j_write) != NULL)
 				goto slow;
-			if (!WriteFile(db_iop->fhp->handle,
-			    db_iop->buf, (DWORD)db_iop->bytes, &nbytes, &over))
+#ifdef HAVE_FILESYSTEM_NOTZERO
+			if (__os_fs_notzero())
+				goto slow;
+#endif
+			if (!WriteFile(fhp->handle,
+			    buf, (DWORD)pagesize, &nbytes, &over))
 				goto slow;
 			break;
 		}
-		if (nbytes == db_iop->bytes) {
+		if (nbytes == pagesize) {
 			*niop = (size_t)nbytes;
 			return (0);
 		}
 	}
 
-slow:	MUTEX_THREAD_LOCK(dbenv, db_iop->mutexp);
+slow:	MUTEX_THREAD_LOCK(dbenv, fhp->mutexp);
 
-	if ((ret = __os_seek(dbenv, db_iop->fhp,
-	    db_iop->pagesize, db_iop->pgno, 0, 0, DB_OS_SEEK_SET)) != 0)
+	if ((ret = __os_seek(dbenv, fhp,
+	    pagesize, pgno, 0, 0, DB_OS_SEEK_SET)) != 0)
 		goto err;
 
 	switch (op) {
 	case DB_IO_READ:
-		ret = __os_read(dbenv,
-		    db_iop->fhp, db_iop->buf, db_iop->bytes, niop);
+		ret = __os_read(dbenv, fhp, buf, pagesize, niop);
 		break;
 	case DB_IO_WRITE:
-		ret = __os_write(dbenv,
-		    db_iop->fhp, db_iop->buf, db_iop->bytes, niop);
+		ret = __os_write(dbenv, fhp, buf, pagesize, niop);
 		break;
 	}
 
-err:	MUTEX_THREAD_UNLOCK(dbenv, db_iop->mutexp);
+err:	MUTEX_THREAD_UNLOCK(dbenv, fhp->mutexp);
 
 	return (ret);
 }
@@ -90,8 +96,6 @@ err:	MUTEX_THREAD_UNLOCK(dbenv, db_iop->mutexp);
 /*
  * __os_read --
  *	Read from a file handle.
- *
- * PUBLIC: int __os_read __P((DB_ENV *, DB_FH *, void *, size_t, size_t *));
  */
 int
 __os_read(dbenv, fhp, addr, len, nrp)
@@ -101,45 +105,42 @@ __os_read(dbenv, fhp, addr, len, nrp)
 	size_t len;
 	size_t *nrp;
 {
-	size_t offset;
-	DWORD nr;
+	size_t offset, nr;
+	DWORD count;
 	int ret;
-	BOOL success;
 	u_int8_t *taddr;
 
-	for (taddr = addr,
-	    offset = 0; offset < len; taddr += nr, offset += nr) {
-retry:		if (DB_GLOBAL(j_read) != NULL) {
-			nr = (DWORD)DB_GLOBAL(j_read)(fhp->fd,
-			    taddr, len - offset);
-			success = (nr >= 0);
-		} else {
-			success = ReadFile(fhp->handle,
-			    taddr, (DWORD)(len - offset), &nr, NULL);
-			if (!success)
-				__os_set_errno(__os_win32_errno());
-		}
+	ret = 0;
 
-		if (!success) {
-			if ((ret = __os_get_errno()) == EINTR)
-				goto retry;
-			__db_err(dbenv, "read: 0x%lx, %lu: %s",
-			    P_TO_ULONG(taddr),
-			    (u_long)len - offset, strerror(ret));
-			return (ret);
+	if (DB_GLOBAL(j_read) != NULL) {
+		*nrp = len;
+		if (DB_GLOBAL(j_read)(fhp->fd, addr, len) != (ssize_t)len) {
+			ret = __os_get_errno();
+			__db_err(dbenv, "read: %#lx, %lu: %s",
+			    P_TO_ULONG(addr), (u_long)len, strerror(ret));
 		}
-		if (nr == 0)
+		return (ret);
+	}
+
+	ret = 0;
+	for (taddr = addr,
+	    offset = 0; offset < len; taddr += nr, offset += nr) {
+		RETRY_CHK((!ReadFile(fhp->handle,
+		    taddr, (DWORD)(len - offset), &count, NULL)), ret);
+		if (count == 0 || ret != 0)
 			break;
+		nr = (size_t)count;
 	}
 	*nrp = taddr - (u_int8_t *)addr;
-	return (0);
+	if (ret != 0)
+		__db_err(dbenv, "read: 0x%lx, %lu: %s",
+		    P_TO_ULONG(taddr), (u_long)len - offset, strerror(ret));
+	return (ret);
 }
 
 /*
  * __os_write --
  *	Write to a file handle.
- *
- * PUBLIC: int __os_write __P((DB_ENV *, DB_FH *, void *, size_t, size_t *));
  */
 int
 __os_write(dbenv, fhp, addr, len, nwp)
@@ -149,34 +150,142 @@ __os_write(dbenv, fhp, addr, len, nwp)
 	size_t len;
 	size_t *nwp;
 {
-	size_t offset;
-	DWORD nw;
 	int ret;
-	BOOL success;
+
+#ifdef HAVE_FILESYSTEM_NOTZERO
+	/* Zero-fill as necessary. */
+	if (__os_fs_notzero() && (ret = __os_zerofill(dbenv, fhp)) != 0)
+		return (ret);
+#endif
+	return (__os_physwrite(dbenv, fhp, addr, len, nwp));
+}
+
+/*
+ * __os_physwrite --
+ *	Physical write to a file handle.
+ */
+static int
+__os_physwrite(dbenv, fhp, addr, len, nwp)
+	DB_ENV *dbenv;
+	DB_FH *fhp;
+	void *addr;
+	size_t len;
+	size_t *nwp;
+{
+	size_t offset, nw;
+	DWORD count;
+	int ret;
 	u_int8_t *taddr;
 
+	if (DB_GLOBAL(j_write) != NULL) {
+		*nwp = len;
+		if (DB_GLOBAL(j_write)(fhp->fd, addr, len) != (ssize_t)len) {
+			ret = __os_get_errno();
+			__db_err(dbenv, "write: %#lx, %lu: %s",
+			    P_TO_ULONG(addr), (u_long)len, strerror(ret));
+		}
+		return (ret);
+	}
+
+	ret = 0;
 	for (taddr = addr,
 	    offset = 0; offset < len; taddr += nw, offset += nw) {
-retry:		if (DB_GLOBAL(j_write) != NULL) {
-			nw = (DWORD)DB_GLOBAL(j_write)(fhp->fd,
-			    taddr, len - offset);
-			success = (nw >= 0);
-		} else {
-			success = WriteFile(fhp->handle,
-			    taddr, (DWORD)(len - offset), &nw, NULL);
-			if (!success)
-				__os_set_errno(__os_win32_errno());
-		}
+		RETRY_CHK((!WriteFile(fhp->handle,
+		    taddr, (DWORD)(len - offset), &count, NULL)), ret);
+		if (ret != 0)
+			break;
+		nw = (size_t)count;
+	}
+	*nwp = len;
+	if (ret != 0)
+		__db_err(dbenv, "write: %#lx, %lu: %s",
+		    P_TO_ULONG(taddr), (u_long)len - offset, strerror(ret));
+	return (ret);
+}
 
-		if (!success) {
-			if ((ret = __os_get_errno()) == EINTR)
-				goto retry;
-			__db_err(dbenv, "write: 0x%x, %lu: %s", taddr,
-			    (u_long)len-offset, strerror(ret));
-			return (ret);
+#ifdef HAVE_FILESYSTEM_NOTZERO
+/*
+ * __os_zerofill --
+ *	Zero out bytes in the file.
+ *
+ *	Pages allocated by writing pages past end-of-file are not zeroed,
+ *	on some systems.  Recovery could theoretically be fooled by a page
+ *	showing up that contained garbage.  In order to avoid this, we
+ *	have to write the pages out to disk, and flush them.  The reason
+ *	for the flush is because if we don't sync, the allocation of another
+ *	page subsequent to this one might reach the disk first, and if we
+ *	crashed at the right moment, leave us with this page as the one
+ *	allocated by writing a page past it in the file.
+ */
+static int
+__os_zerofill(dbenv, fhp)
+	DB_ENV *dbenv;
+	DB_FH *fhp;
+{
+	unsigned __int64 stat_offset, write_offset;
+	size_t blen, nw;
+	u_int32_t bytes, mbytes;
+	int group_sync, need_free, ret;
+	u_int8_t buf[8 * 1024], *bp;
+
+	/* Calculate the byte offset of the next write. */
+	write_offset = (unsigned __int64)fhp->pgno * fhp->pgsize + fhp->offset;
+
+	/* Stat the file. */
+	if ((ret = __os_ioinfo(dbenv, NULL, fhp, &mbytes, &bytes, NULL)) != 0)
+		return (ret);
+	stat_offset = (unsigned __int64)mbytes * MEGABYTE + bytes;
+
+	/* Check if the file is large enough. */
+	if (stat_offset >= write_offset)
+		return (0);
+
+	/* Get a large buffer if we're writing lots of data. */
+#undef	ZF_LARGE_WRITE
+#define	ZF_LARGE_WRITE	(64 * 1024)
+	if (write_offset - stat_offset > ZF_LARGE_WRITE) {
+		if ((ret = __os_calloc(dbenv, 1, ZF_LARGE_WRITE, &bp)) != 0)
+			    return (ret);
+		blen = ZF_LARGE_WRITE;
+		need_free = 1;
+	} else {
+		bp = buf;
+		blen = sizeof(buf);
+		need_free = 0;
+		memset(buf, 0, sizeof(buf));
+	}
+
+	/* Seek to the current end of the file. */
+	if ((ret = __os_seek(
+	    dbenv, fhp, MEGABYTE, mbytes, bytes, 0, DB_OS_SEEK_SET)) != 0)
+		goto err;
+
+	/*
+	 * Hash is the only access method that allocates groups of pages.  Hash
+	 * uses the existence of the last page in a group to signify the entire
+	 * group is OK; so, write all the pages but the last one in the group,
+	 * flush them to disk, then write the last one to disk and flush it.
+	 */
+	for (group_sync = 0; stat_offset < write_offset; group_sync = 1) {
+		if (write_offset - stat_offset <= blen) {
+			blen = (size_t)(write_offset - stat_offset);
+			if (group_sync && (ret = __os_fsync(dbenv, fhp)) != 0)
+				goto err;
 		}
+		if ((ret = __os_physwrite(dbenv, fhp, bp, blen, &nw)) != 0)
+			goto err;
+		stat_offset += blen;
 	}
+	if ((ret = __os_fsync(dbenv, fhp)) != 0)
+		goto err;
 
-	*nwp = len;
-	return (0);
+	/* Seek back to where we started. */
+	mbytes = (u_int32_t)(write_offset / MEGABYTE);
+	bytes = (u_int32_t)(write_offset % MEGABYTE);
+	ret = __os_seek(dbenv, fhp, MEGABYTE, mbytes, bytes, 0, DB_OS_SEEK_SET);
+
+err:	if (need_free)
+		__os_free(dbenv, bp);
+	return (ret);
 }
+#endif
diff --git a/storage/bdb/os_win32/os_seek.c b/storage/bdb/os_win32/os_seek.c
index 40140f515341bdba66093ef3e0aa5281de6879b2..e356c3884d1bbbce169b326893c71eeaffebfce0 100644
--- a/storage/bdb/os_win32/os_seek.c
+++ b/storage/bdb/os_win32/os_seek.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_seek.c,v 11.22 2004/09/17 22:00:32 mjc Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_seek.c,v 11.17 2002/08/06 04:56:20 bostic Exp $";
-#endif /* not lint */
-
 #include "db_int.h"
 
 /*
@@ -21,7 +19,7 @@ int
 __os_seek(dbenv, fhp, pgsize, pageno, relative, isrewind, db_whence)
 	DB_ENV *dbenv;
 	DB_FH *fhp;
-	size_t pgsize;
+	u_int32_t pgsize;
 	db_pgno_t pageno;
 	u_int32_t relative;
 	int isrewind;
@@ -34,10 +32,15 @@ __os_seek(dbenv, fhp, pgsize, pageno, relative, isrewind, db_whence)
 			unsigned long low;
 			long high;
 		};
-	} offset;
+	} offbytes;
+	off_t offset;
 	int ret, whence;
 	DWORD from;
 
+	offset = (off_t)pgsize * pageno + relative;
+	if (isrewind)
+		offset = -offset;
+
 	if (DB_GLOBAL(j_seek) != NULL) {
 		switch (db_whence) {
 		case DB_OS_SEEK_CUR:
@@ -53,8 +56,7 @@ __os_seek(dbenv, fhp, pgsize, pageno, relative, isrewind, db_whence)
 			return (EINVAL);
 		}
 
-		ret = DB_GLOBAL(j_seek)(fhp->fd, pgsize, pageno,
-		    relative, isrewind, whence);
+		ret = DB_GLOBAL(j_seek)(fhp->fd, offset, whence);
 	} else {
 		switch (db_whence) {
 		case DB_OS_SEEK_CUR:
@@ -70,19 +72,21 @@ __os_seek(dbenv, fhp, pgsize, pageno, relative, isrewind, db_whence)
 			return (EINVAL);
 		}
 
-		offset.bigint = (__int64)pgsize * pageno + relative;
-		if (isrewind)
-			offset.bigint = -offset.bigint;
-
+		offbytes.bigint = offset;
 		ret = (SetFilePointer(fhp->handle,
-		    offset.low, &offset.high, from) == (DWORD) - 1) ?
-		    __os_win32_errno() : 0;
+		    offbytes.low, &offbytes.high, from) == (DWORD) - 1) ?
+		    __os_get_errno() : 0;
 	}
 
-	if (ret != 0)
+	if (ret == 0) {
+		fhp->pgsize = pgsize;
+		fhp->pgno = pageno;
+		fhp->offset = relative;
+	} else {
 		__db_err(dbenv, "seek: %lu %d %d: %s",
 		    (u_long)pgsize * pageno + relative,
 		    isrewind, db_whence, strerror(ret));
+	}
 
 	return (ret);
 }
diff --git a/storage/bdb/os_win32/os_sleep.c b/storage/bdb/os_win32/os_sleep.c
index 12b4a7dbc2d107742b538cd619c39d4d2035292c..ae06e49803cd04a236229b6aa1eb1082126b83d7 100644
--- a/storage/bdb/os_win32/os_sleep.c
+++ b/storage/bdb/os_win32/os_sleep.c
@@ -1,23 +1,21 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_sleep.c,v 11.11 2004/03/24 15:13:16 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_sleep.c,v 11.8 2002/07/12 18:56:56 bostic Exp $";
-#endif /* not lint */
-
 #include "db_int.h"
 
 /*
  * __os_sleep --
  *	Yield the processor for a period of time.
  */
-int
+void
 __os_sleep(dbenv, secs, usecs)
 	DB_ENV *dbenv;
 	u_long secs, usecs;		/* Seconds and microseconds. */
@@ -28,13 +26,14 @@ __os_sleep(dbenv, secs, usecs)
 	for (; usecs >= 1000000; ++secs, usecs -= 1000000)
 		;
 
-	if (DB_GLOBAL(j_sleep) != NULL)
-		return (DB_GLOBAL(j_sleep)(secs, usecs));
+	if (DB_GLOBAL(j_sleep) != NULL) {
+		DB_GLOBAL(j_sleep)(secs, usecs);
+		return;
+	}
 
 	/*
 	 * It's important that we yield the processor here so that other
 	 * processes or threads are permitted to run.
 	 */
 	Sleep(secs * 1000 + usecs / 1000);
-	return (0);
 }
diff --git a/storage/bdb/os_win32/os_spin.c b/storage/bdb/os_win32/os_spin.c
index eb50b3b53ff8df5d80332c84ab10855d7180c8b4..a5cb5853980ba12e47662fba5017ae82e8b6bdba 100644
--- a/storage/bdb/os_win32/os_spin.c
+++ b/storage/bdb/os_win32/os_spin.c
@@ -1,23 +1,21 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_spin.c,v 11.16 2004/03/24 15:13:16 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_spin.c,v 11.11 2002/07/12 18:56:56 bostic Exp $";
-#endif /* not lint */
-
 #include "db_int.h"
 
 /*
  * __os_spin --
  *	Return the number of default spins before blocking.
  */
-int
+void
 __os_spin(dbenv)
 	DB_ENV *dbenv;
 {
@@ -28,7 +26,7 @@ __os_spin(dbenv)
 	 * out, return it.
 	 */
 	if (dbenv->tas_spins != 0)
-		return (dbenv->tas_spins);
+		return;
 
 	/* Get the number of processors */
 	GetSystemInfo(&SystemInfo);
@@ -41,7 +39,6 @@ __os_spin(dbenv)
 		 dbenv->tas_spins = 50 * SystemInfo.dwNumberOfProcessors;
 	else
 		 dbenv->tas_spins = 1;
-	return (dbenv->tas_spins);
 }
 
 /*
diff --git a/storage/bdb/os_win32/os_stat.c b/storage/bdb/os_win32/os_stat.c
index c1cba698beada7c52d9ebfabafcb4a454e59ddb6..b11da487a7a11647e68819eecdc65c2fc31bb6fa 100644
--- a/storage/bdb/os_win32/os_stat.c
+++ b/storage/bdb/os_win32/os_stat.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_stat.c,v 11.32 2004/10/07 14:00:11 carol Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: os_stat.c,v 11.22 2002/07/12 18:56:56 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -23,8 +21,6 @@ static const char revid[] = "$Id: os_stat.c,v 11.22 2002/07/12 18:56:56 bostic E
 /*
  * __os_exists --
  *	Return if the file exists.
- *
- * PUBLIC: int __os_exists __P((const char *, int *));
  */
 int
 __os_exists(path, isdirp)
@@ -33,33 +29,29 @@ __os_exists(path, isdirp)
 {
 	int ret;
 	DWORD attrs;
+	_TCHAR *tpath;
 
 	if (DB_GLOBAL(j_exists) != NULL)
 		return (DB_GLOBAL(j_exists)(path, isdirp));
 
-	ret = 0;
-	do {
-		attrs = GetFileAttributes(path);
-		if (attrs == (DWORD)-1)
-			ret = __os_win32_errno();
-	} while (ret == EINTR);
-
+	TO_TSTRING(NULL, path, tpath, ret);
 	if (ret != 0)
 		return (ret);
 
-	if (isdirp != NULL)
+	RETRY_CHK(
+	    ((attrs = GetFileAttributes(tpath)) == (DWORD)-1 ? 1 : 0), ret);
+
+	if (ret == 0 && isdirp != NULL)
 		*isdirp = (attrs & FILE_ATTRIBUTE_DIRECTORY);
 
-	return (0);
+	FREE_STRING(NULL, tpath);
+	return (ret);
 }
 
 /*
  * __os_ioinfo --
  *	Return file size and I/O size; abstracted to make it easier
  *	to replace.
- *
- * PUBLIC: int __os_ioinfo __P((DB_ENV *, const char *,
- * PUBLIC:    DB_FH *, u_int32_t *, u_int32_t *, u_int32_t *));
  */
 int
 __os_ioinfo(dbenv, path, fhp, mbytesp, bytesp, iosizep)
@@ -76,9 +68,8 @@ __os_ioinfo(dbenv, path, fhp, mbytesp, bytesp, iosizep)
 		return (DB_GLOBAL(j_ioinfo)(path,
 		    fhp->fd, mbytesp, bytesp, iosizep));
 
-retry:	if (!GetFileInformationByHandle(fhp->handle, &bhfi)) {
-		if ((ret = __os_win32_errno()) == EINTR)
-			goto retry;
+	RETRY_CHK((!GetFileInformationByHandle(fhp->handle, &bhfi)), ret);
+	if (ret != 0) {
 		__db_err(dbenv,
 		    "GetFileInformationByHandle: %s", strerror(ret));
 		return (ret);
@@ -93,7 +84,12 @@ retry:	if (!GetFileInformationByHandle(fhp->handle, &bhfi)) {
 	if (bytesp != NULL)
 		*bytesp = (u_int32_t)(filesize % MEGABYTE);
 
-	/* The filesystem blocksize is not easily available. */
+	/*
+	 * The filesystem blocksize is not easily available.  In particular,
+	 * the values returned by GetDiskFreeSpace() are not very helpful
+	 * (NTFS volumes often report 512B clusters, which are too small to
+	 * be a useful default).
+	 */
 	if (iosizep != NULL)
 		*iosizep = DB_DEF_IOSIZE;
 	return (0);
diff --git a/storage/bdb/os_win32/os_truncate.c b/storage/bdb/os_win32/os_truncate.c
new file mode 100644
index 0000000000000000000000000000000000000000..51820ab1d8ed40ccd37f5079d5fdc709693aa958
--- /dev/null
+++ b/storage/bdb/os_win32/os_truncate.c
@@ -0,0 +1,99 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_truncate.c,v 1.9 2004/10/05 14:45:30 mjc Exp $
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+/*
+ * __os_truncate --
+ *	Truncate the file.
+ */
+int
+__os_truncate(dbenv, fhp, pgno, pgsize)
+	DB_ENV *dbenv;
+	DB_FH *fhp;
+	db_pgno_t pgno;
+	u_int32_t pgsize;
+{
+	/* Yes, this really is how Microsoft have designed their API */
+	union {
+		__int64 bigint;
+		struct {
+			unsigned long low;
+			long high;
+		};
+	} oldpos;
+	off_t offset;
+	int ret, retries, t_ret;
+
+	offset = (off_t)pgsize * pgno;
+
+	if (DB_GLOBAL(j_ftruncate) != NULL) {
+		ret = DB_GLOBAL(j_ftruncate)(fhp->fd, offset);
+		goto done;
+	}
+
+#ifdef HAVE_FILESYSTEM_NOTZERO
+	/*
+	 * If the filesystem doesn't zero fill, it isn't safe to extend the
+	 * file, or we end up with junk blocks.  Just return in that case.
+	 */
+	if (__os_fs_notzero()) {
+		off_t stat_offset;
+		u_int32_t mbytes, bytes;
+
+		/* Stat the file. */
+		if ((ret =
+		    __os_ioinfo(dbenv, NULL, fhp, &mbytes, &bytes, NULL)) != 0)
+			return (ret);
+		stat_offset = (off_t)mbytes * MEGABYTE + bytes;
+
+		if (offset > stat_offset)
+			return (0);
+	}
+#endif
+
+	retries = 0;
+	do {
+		/*
+		 * Windows doesn't provide truncate directly.  Instead,
+		 * it has SetEndOfFile, which truncates to the current
+		 * position.  So we have to save the current position,
+		 * seek to where we want to truncate to, then seek back
+		 * to where we were.  To avoid races, all of that needs
+		 * to be done while holding the file handle mutex.
+		 */
+		MUTEX_THREAD_LOCK(dbenv, fhp->mutexp);
+		oldpos.bigint = 0;
+		if ((oldpos.low = SetFilePointer(fhp->handle,
+		    0, &oldpos.high, FILE_CURRENT)) == -1 &&
+		    GetLastError() != NO_ERROR) {
+			ret = __os_get_errno();
+			goto end;
+		}
+		if ((ret = __os_seek(dbenv, fhp, pgsize, pgno,
+		    0, 0, DB_OS_SEEK_SET)) != 0)
+			goto end;
+		if (!SetEndOfFile(fhp->handle))
+			ret = __os_get_errno();
+		if ((t_ret = __os_seek(dbenv, fhp, pgsize,
+		    (db_pgno_t)(oldpos.bigint / pgsize),
+		    0, 0, DB_OS_SEEK_SET)) != 0 && ret == 0)
+			ret = t_ret;
+end:		MUTEX_THREAD_UNLOCK(dbenv, fhp->mutexp);
+	} while ((ret == EAGAIN || ret == EBUSY || ret == EINTR) &&
+	    ++retries < DB_RETRY);
+
+done:	if (ret != 0)
+		__db_err(dbenv,
+		    "ftruncate: %lu: %s", pgno * pgsize, strerror(ret));
+
+	return (ret);
+}
diff --git a/storage/bdb/os_win32/os_unlink.c b/storage/bdb/os_win32/os_unlink.c
new file mode 100644
index 0000000000000000000000000000000000000000..d1b50539ef9f2126b6141748ab4cb4a307f74498
--- /dev/null
+++ b/storage/bdb/os_win32/os_unlink.c
@@ -0,0 +1,73 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: os_unlink.c,v 11.5 2004/10/05 14:55:36 mjc Exp $
+ */
+
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#include <unistd.h>
+#endif
+
+#include "db_int.h"
+
+/*
+ * __os_region_unlink --
+ *	Remove a shared memory object file.
+ */
+int
+__os_region_unlink(dbenv, path)
+	DB_ENV *dbenv;
+	const char *path;
+{
+	if (F_ISSET(dbenv, DB_ENV_OVERWRITE))
+		(void)__db_overwrite(dbenv, path);
+
+	return (__os_unlink(dbenv, path));
+}
+
+/*
+ * __os_unlink --
+ *	Remove a file.
+ *
+ * PUBLIC: int __os_unlink __P((DB_ENV *, const char *));
+ */
+int
+__os_unlink(dbenv, path)
+	DB_ENV *dbenv;
+	const char *path;
+{
+	_TCHAR *tpath;
+	int ret;
+
+	if (DB_GLOBAL(j_unlink) != NULL) {
+		ret = DB_GLOBAL(j_unlink)(path);
+		goto done;
+	}
+
+	TO_TSTRING(dbenv, path, tpath, ret);
+	if (ret != 0)
+		return (ret);
+	RETRY_CHK((!DeleteFile(tpath)), ret);
+	FREE_STRING(dbenv, tpath);
+
+	/*
+	 * XXX
+	 * We shouldn't be testing for an errno of ENOENT here, but ENOENT
+	 * signals that a file is missing, and we attempt to unlink things
+	 * (such as v. 2.x environment regions, in DB_ENV->remove) that we
+	 * are expecting not to be there.  Reporting errors in these cases
+	 * is annoying.
+	 */
+done:	if (ret != 0 && ret != ENOENT)
+		__db_err(dbenv, "unlink: %s: %s", path, strerror(ret));
+
+	return (ret);
+}
diff --git a/storage/bdb/perl/BerkeleyDB/BerkeleyDB.pm b/storage/bdb/perl/BerkeleyDB/BerkeleyDB.pm
index c56390ba71fa9bcb6295f3571d92998b98e24814..5791faea5f5d1a8b73682c40a6544e47a23c6786 100644
--- a/storage/bdb/perl/BerkeleyDB/BerkeleyDB.pm
+++ b/storage/bdb/perl/BerkeleyDB/BerkeleyDB.pm
@@ -2,7 +2,7 @@
 package BerkeleyDB;
 
 
-#     Copyright (c) 1997-2002 Paul Marquess. All rights reserved.
+#     Copyright (c) 1997-2004 Paul Marquess. All rights reserved.
 #     This program is free software; you can redistribute it and/or
 #     modify it under the same terms as Perl itself.
 #
@@ -17,7 +17,7 @@ use Carp;
 use vars qw($VERSION @ISA @EXPORT $AUTOLOAD
 		$use_XSLoader);
 
-$VERSION = '0.20';
+$VERSION = '0.26';
 
 require Exporter;
 #require DynaLoader;
@@ -50,16 +50,18 @@ BEGIN {
 	DB_ARCH_ABS
 	DB_ARCH_DATA
 	DB_ARCH_LOG
+	DB_ARCH_REMOVE
 	DB_AUTO_COMMIT
 	DB_BEFORE
-	DB_BROADCAST_EID
 	DB_BTREE
 	DB_BTREEMAGIC
 	DB_BTREEOLDVER
 	DB_BTREEVERSION
+	DB_BUFFER_SMALL
 	DB_CACHED_COUNTS
 	DB_CDB_ALLDB
 	DB_CHECKPOINT
+	DB_CHKSUM
 	DB_CHKSUM_SHA1
 	DB_CLIENT
 	DB_CL_WRITER
@@ -70,6 +72,7 @@ BEGIN {
 	DB_CURLSN
 	DB_CURRENT
 	DB_CXX_NO_EXCEPTIONS
+	DB_DEGREE_2
 	DB_DELETED
 	DB_DELIMITER
 	DB_DIRECT
@@ -77,9 +80,11 @@ BEGIN {
 	DB_DIRECT_LOG
 	DB_DIRTY_READ
 	DB_DONOTINDEX
+	DB_DSYNC_LOG
 	DB_DUP
 	DB_DUPCURSOR
 	DB_DUPSORT
+	DB_DURABLE_UNKNOWN
 	DB_EID_BROADCAST
 	DB_EID_INVALID
 	DB_ENCRYPT
@@ -92,10 +97,13 @@ BEGIN {
 	DB_ENV_DBLOCAL
 	DB_ENV_DIRECT_DB
 	DB_ENV_DIRECT_LOG
+	DB_ENV_DSYNC_LOG
 	DB_ENV_FATAL
 	DB_ENV_LOCKDOWN
 	DB_ENV_LOCKING
 	DB_ENV_LOGGING
+	DB_ENV_LOG_AUTOREMOVE
+	DB_ENV_LOG_INMEMORY
 	DB_ENV_NOLOCKING
 	DB_ENV_NOMMAP
 	DB_ENV_NOPANIC
@@ -112,8 +120,10 @@ BEGIN {
 	DB_ENV_STANDALONE
 	DB_ENV_SYSTEM_MEM
 	DB_ENV_THREAD
+	DB_ENV_TIME_NOTGRANTED
 	DB_ENV_TXN
 	DB_ENV_TXN_NOSYNC
+	DB_ENV_TXN_NOT_DURABLE
 	DB_ENV_TXN_WRITE_NOSYNC
 	DB_ENV_USER_ALLOC
 	DB_ENV_YIELDCPU
@@ -121,6 +131,7 @@ BEGIN {
 	DB_EXTENT
 	DB_FAST_STAT
 	DB_FCNTL_LOCKING
+	DB_FILEOPEN
 	DB_FILE_ID_LEN
 	DB_FIRST
 	DB_FIXEDLEN
@@ -141,8 +152,9 @@ BEGIN {
 	DB_INIT_LOCK
 	DB_INIT_LOG
 	DB_INIT_MPOOL
+	DB_INIT_REP
 	DB_INIT_TXN
-	DB_INVALID_EID
+	DB_INORDER
 	DB_JAVA_CALLBACK
 	DB_JOINENV
 	DB_JOIN_ITEM
@@ -155,6 +167,7 @@ BEGIN {
 	DB_LOCKDOWN
 	DB_LOCKMAGIC
 	DB_LOCKVERSION
+	DB_LOCK_ABORT
 	DB_LOCK_CONFLICT
 	DB_LOCK_DEADLOCK
 	DB_LOCK_DEFAULT
@@ -165,6 +178,7 @@ BEGIN {
 	DB_LOCK_GET_TIMEOUT
 	DB_LOCK_INHERIT
 	DB_LOCK_MAXLOCKS
+	DB_LOCK_MAXWRITE
 	DB_LOCK_MINLOCKS
 	DB_LOCK_MINWRITE
 	DB_LOCK_NORUN
@@ -194,9 +208,19 @@ BEGIN {
 	DB_LOGMAGIC
 	DB_LOGOLDVER
 	DB_LOGVERSION
+	DB_LOG_AUTOREMOVE
+	DB_LOG_BUFFER_FULL
+	DB_LOG_CHKPNT
+	DB_LOG_COMMIT
 	DB_LOG_DISK
+	DB_LOG_INMEMORY
 	DB_LOG_LOCKED
+	DB_LOG_NOCOPY
+	DB_LOG_NOT_DURABLE
+	DB_LOG_PERM
+	DB_LOG_RESEND
 	DB_LOG_SILENT_ERR
+	DB_LOG_WRNOSYNC
 	DB_MAX_PAGES
 	DB_MAX_RECORDS
 	DB_MPOOL_CLEAN
@@ -204,10 +228,13 @@ BEGIN {
 	DB_MPOOL_DIRTY
 	DB_MPOOL_DISCARD
 	DB_MPOOL_EXTENT
+	DB_MPOOL_FREE
 	DB_MPOOL_LAST
 	DB_MPOOL_NEW
 	DB_MPOOL_NEW_GROUP
+	DB_MPOOL_NOFILE
 	DB_MPOOL_PRIVATE
+	DB_MPOOL_UNLINK
 	DB_MULTIPLE
 	DB_MULTIPLE_KEY
 	DB_MUTEXDEBUG
@@ -229,6 +256,7 @@ BEGIN {
 	DB_NOSERVER_ID
 	DB_NOSYNC
 	DB_NOTFOUND
+	DB_NO_AUTO_COMMIT
 	DB_ODDFILESIZE
 	DB_OK_BTREE
 	DB_OK_HASH
@@ -279,23 +307,38 @@ BEGIN {
 	DB_RENAMEMAGIC
 	DB_RENUMBER
 	DB_REP_CLIENT
+	DB_REP_CREATE
 	DB_REP_DUPMASTER
+	DB_REP_EGENCHG
+	DB_REP_HANDLE_DEAD
 	DB_REP_HOLDELECTION
+	DB_REP_ISPERM
+	DB_REP_LOGREADY
 	DB_REP_LOGSONLY
 	DB_REP_MASTER
 	DB_REP_NEWMASTER
 	DB_REP_NEWSITE
+	DB_REP_NOBUFFER
+	DB_REP_NOTPERM
 	DB_REP_OUTDATED
+	DB_REP_PAGEDONE
 	DB_REP_PERMANENT
+	DB_REP_STARTUPDONE
 	DB_REP_UNAVAIL
 	DB_REVSPLITOFF
 	DB_RMW
+	DB_RPCCLIENT
 	DB_RPC_SERVERPROG
 	DB_RPC_SERVERVERS
 	DB_RUNRECOVERY
 	DB_SALVAGE
 	DB_SECONDARY_BAD
+	DB_SEQUENCE_VERSION
 	DB_SEQUENTIAL
+	DB_SEQ_DEC
+	DB_SEQ_INC
+	DB_SEQ_RANGE_SET
+	DB_SEQ_WRAP
 	DB_SET
 	DB_SET_LOCK_TIMEOUT
 	DB_SET_RANGE
@@ -303,7 +346,14 @@ BEGIN {
 	DB_SET_TXN_NOW
 	DB_SET_TXN_TIMEOUT
 	DB_SNAPSHOT
+	DB_STAT_ALL
 	DB_STAT_CLEAR
+	DB_STAT_LOCK_CONF
+	DB_STAT_LOCK_LOCKERS
+	DB_STAT_LOCK_OBJECTS
+	DB_STAT_LOCK_PARAMS
+	DB_STAT_MEMP_HASH
+	DB_STAT_SUBSYSTEM
 	DB_SURPRISE_KID
 	DB_SWAPBYTES
 	DB_SYSTEM_MEM
@@ -315,23 +365,18 @@ BEGIN {
 	DB_TEST_ELECTWAIT1
 	DB_TEST_ELECTWAIT2
 	DB_TEST_POSTDESTROY
-	DB_TEST_POSTEXTDELETE
-	DB_TEST_POSTEXTOPEN
-	DB_TEST_POSTEXTUNLINK
 	DB_TEST_POSTLOG
 	DB_TEST_POSTLOGMETA
 	DB_TEST_POSTOPEN
 	DB_TEST_POSTRENAME
 	DB_TEST_POSTSYNC
 	DB_TEST_PREDESTROY
-	DB_TEST_PREEXTDELETE
-	DB_TEST_PREEXTOPEN
-	DB_TEST_PREEXTUNLINK
 	DB_TEST_PREOPEN
 	DB_TEST_PRERENAME
 	DB_TEST_SUBDB_LOCKS
 	DB_THREAD
 	DB_TIMEOUT
+	DB_TIME_NOTGRANTED
 	DB_TRUNCATE
 	DB_TXNMAGIC
 	DB_TXNVERSION
@@ -341,7 +386,6 @@ BEGIN {
 	DB_TXN_BACKWARD_ROLL
 	DB_TXN_CKP
 	DB_TXN_FORWARD_ROLL
-	DB_TXN_GETPGNOS
 	DB_TXN_LOCK
 	DB_TXN_LOCK_2PL
 	DB_TXN_LOCK_MASK
@@ -352,6 +396,7 @@ BEGIN {
 	DB_TXN_LOG_UNDO
 	DB_TXN_LOG_UNDOREDO
 	DB_TXN_NOSYNC
+	DB_TXN_NOT_DURABLE
 	DB_TXN_NOWAIT
 	DB_TXN_OPENFILES
 	DB_TXN_POPENFILES
@@ -361,7 +406,7 @@ BEGIN {
 	DB_TXN_UNDO
 	DB_TXN_WRITE_NOSYNC
 	DB_UNKNOWN
-	DB_UNRESOLVED_CHILD
+	DB_UNREF
 	DB_UPDATE_SECONDARY
 	DB_UPGRADE
 	DB_USE_ENVIRON
@@ -376,6 +421,7 @@ BEGIN {
 	DB_VERIFY_FATAL
 	DB_VERSION_MAJOR
 	DB_VERSION_MINOR
+	DB_VERSION_MISMATCH
 	DB_VERSION_PATCH
 	DB_VERSION_STRING
 	DB_VRFY_FLAGMASK
@@ -386,6 +432,8 @@ BEGIN {
 	DB_XA_CREATE
 	DB_XIDDATASIZE
 	DB_YIELDCPU
+	DB_debug_FLAG
+	DB_user_BEGIN
 	);
 
 sub AUTOLOAD {
@@ -426,9 +474,12 @@ sub ParseParameters($@)
 
         %options = %{ $rest[0] } ;
     }
-    elsif (@rest >= 2) {
+    elsif (@rest >= 2 && @rest % 2 == 0) {
         %options = @rest ;
     }
+    elsif (@rest > 0) {
+	    croak "$sub: malformed option list";
+    }
 
     while (($key, $value) = each %options)
     {
@@ -448,13 +499,37 @@ sub ParseParameters($@)
     return \%got ;
 }
 
+sub parseEncrypt
+{
+    my $got = shift ;
+
+
+    if (defined $got->{Encrypt}) {
+    	croak("Encrypt parameter must be a hash reference")
+            if !ref $got->{Encrypt} || ref $got->{Encrypt} ne 'HASH' ;
+
+	my %config = %{ $got->{Encrypt} } ;
+
+        my $p = BerkeleyDB::ParseParameters({
+					Password	=> undef,
+					Flags		=> undef,
+				}, %config);
+
+        croak("Must specify Password and Flags with Encrypt parameter")
+	    if ! (defined $p->{Password} && defined $p->{Flags});
+
+        $got->{"Enc_Passwd"} = $p->{Password};
+        $got->{"Enc_Flags"} = $p->{Flags};
+    }
+}
+
 use UNIVERSAL qw( isa ) ;
 
 sub env_remove
 {
     # Usage:
     #
-    #	$env = new BerkeleyDB::Env
+    #	$env = BerkeleyDB::env_remove
     #			[ -Home		=> $path, ]
     #			[ -Config	=> { name => value, name => value }
     #			[ -Flags	=> DB_INIT_LOCK| ]
@@ -552,6 +627,7 @@ package BerkeleyDB::Env ;
 
 use UNIVERSAL qw( isa ) ;
 use Carp ;
+use IO::File;
 use vars qw( %valid_config_keys ) ;
 
 sub isaFilehandle
@@ -580,6 +656,8 @@ sub new
     #			[ -Cachesize	=> number ]
     #			[ -LockDetect	=>  ]
     #			[ -Verbose	=> boolean ]
+    #			[ -Encrypt	=> { Password => string, Flags => value}
+    #
     #			;
 
     my $pkg = shift ;
@@ -595,19 +673,19 @@ sub new
 					LockDetect     	=> 0,
 					Verbose		=> 0,
 					Config		=> undef,
+					Encrypt		=> undef,
+					SharedMemKey	=> undef,
 					}, @_) ;
 
+    my $errfile  = $got->{ErrFile} ;				
     if (defined $got->{ErrFile}) {
-    	croak("ErrFile parameter must be a file name")
-            if ref $got->{ErrFile} ;
-	#if (!isaFilehandle($got->{ErrFile})) {
-	#    my $handle = new IO::File ">$got->{ErrFile}"
-#		or croak "Cannot open file $got->{ErrFile}: $!\n" ;
-#	    $got->{ErrFile} = $handle ;
-#	}
+	if (!isaFilehandle($got->{ErrFile})) {
+	    my $handle = new IO::File ">$got->{ErrFile}"
+		or croak "Cannot open file $got->{ErrFile}: $!\n" ;
+	    $errfile = $got->{ErrFile} = $handle ;
+	}
     }
 
-    
     my %config ;
     if (defined $got->{Config}) {
     	croak("Config parameter must be a hash reference")
@@ -617,7 +695,7 @@ sub new
         @BerkeleyDB::a = () ;
 	my $k = "" ; my $v = "" ;
 	while (($k, $v) = each %config) {
-	    if ($BerkeleyDB::db_version >= 3.1 && ! $valid_config_keys{$k} ) {
+	    if ($BerkeleyDB::db_version >= 3.1 && ! $valid_config_keys{$k} ){
 	        $BerkeleyDB::Error = "illegal name-value pair: $k $v\n" ; 
                 croak $BerkeleyDB::Error ;
 	    }
@@ -628,7 +706,9 @@ sub new
 	    if @BerkeleyDB::a ;
     }
 
-    my ($addr) = _db_appinit($pkg, $got) ;
+    BerkeleyDB::parseEncrypt($got);
+
+    my ($addr) = _db_appinit($pkg, $got, $errfile) ;
     my $obj ;
     $obj = bless [$addr] , $pkg if $addr ;
     if ($obj && $BerkeleyDB::db_version >= 3.1 && keys %config) {
@@ -699,6 +779,7 @@ sub new
 			Env		=> undef,
 			#Tie 		=> undef,
 			Txn		=> undef,
+			Encrypt		=> undef,
 
 			# Hash specific
 			Ffactor		=> 0,
@@ -722,6 +803,8 @@ sub new
     croak("-Tie needs a reference to a hash")
 	if defined $got->{Tie} and $got->{Tie} !~ /HASH/ ;
 
+    BerkeleyDB::parseEncrypt($got);
+
     my ($addr) = _db_open_hash($self, $got);
     my $obj ;
     if ($addr) {
@@ -761,6 +844,7 @@ sub new
 			Env		=> undef,
 			#Tie 		=> undef,
 			Txn		=> undef,
+			Encrypt		=> undef,
 
 			# Btree specific
 			Minkey		=> 0,
@@ -778,6 +862,8 @@ sub new
     croak("-Tie needs a reference to a hash")
 	if defined $got->{Tie} and $got->{Tie} !~ /HASH/ ;
 
+    BerkeleyDB::parseEncrypt($got);
+
     my ($addr) = _db_open_btree($self, $got);
     my $obj ;
     if ($addr) {
@@ -817,6 +903,7 @@ sub new
 			Env		=> undef,
 			#Tie 		=> undef,
 			Txn		=> undef,
+			Encrypt		=> undef,
 
 			# Recno specific
 			Delim		=> undef,
@@ -839,6 +926,8 @@ sub new
 	if $got->{ArrayBase} != 1 and $got->{ArrayBase} != 0 ;
 
 
+    BerkeleyDB::parseEncrypt($got);
+
     $got->{Fname} = $got->{Filename} if defined $got->{Filename} ;
 
     my ($addr) = _db_open_recno($self, $got);
@@ -880,6 +969,7 @@ sub new
 			Env		=> undef,
 			#Tie 		=> undef,
 			Txn		=> undef,
+			Encrypt		=> undef,
 
 			# Queue specific
 			Len		=> undef,
@@ -900,6 +990,8 @@ sub new
     croak("ArrayBase can only be 0 or 1, parsed $got->{ArrayBase}")
 	if $got->{ArrayBase} != 1 and $got->{ArrayBase} != 0 ;
 
+    BerkeleyDB::parseEncrypt($got);
+
     $got->{Fname} = $got->{Filename} if defined $got->{Filename} ;
 
     my ($addr) = _db_open_queue($self, $got);
@@ -997,6 +1089,7 @@ sub new
 			Env		=> undef,
 			#Tie 		=> undef,
 			Txn		=> undef,
+			Encrypt		=> undef,
 
 		      }, @_) ;
 
@@ -1009,6 +1102,8 @@ sub new
     croak("-Tie needs a reference to a hash")
 	if defined $got->{Tie} and $got->{Tie} !~ /HASH/ ;
 
+    BerkeleyDB::parseEncrypt($got);
+
     my ($addr, $type) = _db_open_unknown($got);
     my $obj ;
     if ($addr) {
@@ -1104,11 +1199,9 @@ sub CLEAR
 {
     my $self = shift ;
     my ($key, $value) = (0, 0) ;
-    my $cursor = $self->db_cursor() ;
+    my $cursor = $self->_db_write_cursor() ;
     while ($cursor->c_get($key, $value, BerkeleyDB::DB_PREV()) == 0) 
 	{ $cursor->c_del() }
-    #1 while $cursor->c_del() == 0 ;
-    # cursor will self-destruct
 }
 
 #sub DESTROY
@@ -1193,7 +1286,7 @@ sub SHIFT
 {
     my $self = shift;
     my ($key, $value) = (0, 0) ;
-    my $cursor = $self->db_cursor() ;
+    my $cursor = $self->_db_write_cursor() ;
     return undef if $cursor->c_get($key, $value, BerkeleyDB::DB_FIRST()) != 0 ;
     return undef if $cursor->c_del() != 0 ;
 
@@ -1207,7 +1300,7 @@ sub UNSHIFT
     if (@_)
     {
         my ($key, $value) = (0, 0) ;
-        my $cursor = $self->db_cursor() ;
+        my $cursor = $self->_db_write_cursor() ;
         my $status = $cursor->c_get($key, $value, BerkeleyDB::DB_FIRST()) ;
         if ($status == 0)
         {
@@ -1234,7 +1327,7 @@ sub PUSH
     if (@_)
     {
         my ($key, $value) = (-1, 0) ;
-        my $cursor = $self->db_cursor() ;
+        my $cursor = $self->_db_write_cursor() ;
         my $status = $cursor->c_get($key, $value, BerkeleyDB::DB_LAST()) ;
         if ($status == 0 || $status == BerkeleyDB::DB_NOTFOUND())
 	{
@@ -1259,7 +1352,7 @@ sub POP
 {
     my $self = shift;
     my ($key, $value) = (0, 0) ;
-    my $cursor = $self->db_cursor() ;
+    my $cursor = $self->_db_write_cursor() ;
     return undef if $cursor->c_get($key, $value, BerkeleyDB::DB_LAST()) != 0 ;
     return undef if $cursor->c_del() != 0 ;
 
@@ -1384,11 +1477,22 @@ sub db_cursor
     return $obj ;
 }
 
+sub _db_write_cursor
+{
+    my $db = shift ;
+    my ($addr) = $db->__db_write_cursor(@_) ;
+    my $obj ;
+    $obj = bless [$addr, $db] , "BerkeleyDB::Cursor" if $addr ;
+    return $obj ;
+}
+
 sub db_join
 {
-    croak 'Usage: $db->BerkeleyDB::Common::db_join([cursors], flags=0)'
+    croak 'Usage: $db->BerkeleyDB::db_join([cursors], flags=0)'
 	if @_ < 2 || @_ > 3 ;
     my $db = shift ;
+    croak 'db_join: first parameter is not an array reference'
+	if ! ref $_[0] || ref $_[0] ne 'ARRAY';
     my ($addr) = $db->_db_join(@_) ;
     my $obj ;
     $obj = bless [$addr, $db, $_[0]] , "BerkeleyDB::Cursor" if $addr ;
@@ -1486,6 +1590,58 @@ sub DESTROY
     $self->_DESTROY() ;
 }
 
+package BerkeleyDB::CDS::Lock;
+
+use vars qw(%Object %Count);
+use Carp;
+
+sub BerkeleyDB::Common::cds_lock
+{
+    my $db = shift ;
+
+    # fatal error if database not opened in CDS mode
+    croak("CDS not enabled for this database\n") 
+        if ! $db->cds_enabled();
+
+    if ( ! defined $Object{"$db"})
+    {
+        $Object{"$db"} = $db->_db_write_cursor()
+         || return undef ;
+    }
+
+    ++ $Count{"$db"} ;
+
+    return bless [$db, 1], "BerkeleyDB::CDS::Lock" ;
+}
+
+sub cds_unlock
+{
+    my $self = shift ;
+    my $db = $self->[0] ;
+
+    if ($self->[1]) 
+    {
+        $self->[1] = 0 ;
+        -- $Count{"$db"} if $Count{"$db"} > 0 ;
+
+        if ($Count{"$db"} == 0)
+        {
+            $Object{"$db"}->c_close() ;
+            undef $Object{"$db"};
+        }
+
+        return 1 ;
+    }
+
+    return undef ;
+}
+
+sub DESTROY
+{
+    my $self = shift ;
+    $self->cds_unlock() ;	
+}
+
 package BerkeleyDB::Term ;
 
 END
@@ -1504,3 +1660,4 @@ package BerkeleyDB ;
 __END__
 
 
+
diff --git a/storage/bdb/perl/BerkeleyDB/BerkeleyDB.pod b/storage/bdb/perl/BerkeleyDB/BerkeleyDB.pod
index 60f30e2abfba9f6ecc3a64948f280d89279af801..ba2cc0c5833d0b6acfa2b8d8be7a3988fe2cf276 100644
--- a/storage/bdb/perl/BerkeleyDB/BerkeleyDB.pod
+++ b/storage/bdb/perl/BerkeleyDB/BerkeleyDB.pod
@@ -14,10 +14,10 @@ BerkeleyDB - Perl extension for Berkeley DB version 2, 3 or 4
   $db  = tie %hash, 'BerkeleyDB::Btree', [OPTIONS] ;
   $db  = new BerkeleyDB::Btree [OPTIONS] ;
 
-  $db  = tie %hash, 'BerkeleyDB::Recno', [OPTIONS] ;
+  $db  = tie @array, 'BerkeleyDB::Recno', [OPTIONS] ;
   $db  = new BerkeleyDB::Recno [OPTIONS] ;
 
-  $db  = tie %hash, 'BerkeleyDB::Queue', [OPTIONS] ;
+  $db  = tie @array, 'BerkeleyDB::Queue', [OPTIONS] ;
   $db  = new BerkeleyDB::Queue [OPTIONS] ;
 
   $db  = new BerkeleyDB::Unknown [OPTIONS] ;
@@ -37,7 +37,6 @@ BerkeleyDB - Perl extension for Berkeley DB version 2, 3 or 4
   $status = $db->db_del() ;
   $status = $db->db_sync() ;
   $status = $db->db_close() ;
-  $status = $db->db_close() ;
   $status = $db->db_pget()
   $hash_ref = $db->db_stat() ;
   $status = $db->db_key_range();
@@ -46,6 +45,11 @@ BerkeleyDB - Perl extension for Berkeley DB version 2, 3 or 4
   $boolean = $db->byteswapped() ;
   $status = $db->truncate($count) ;
 
+  $bool = $env->cds_enabled();
+  $bool = $db->cds_enabled();
+  $lock = $db->cds_lock();
+  $lock->cds_unlock();
+  
   ($flag, $old_offset, $old_length) = $db->partial_set($offset, $length) ;
   ($flag, $old_offset, $old_length) = $db->partial_clear() ;
 
@@ -84,6 +88,7 @@ BerkeleyDB - Perl extension for Berkeley DB version 2, 3 or 4
   $status = $env->set_data_dir() ;
   $status = $env->set_tmp_dir() ;
   $status = $env->set_verbose() ;
+  $db_env_ptr = $env->DB_ENV() ;
 
   $BerkeleyDB::Error
   $BerkeleyDB::db_version
@@ -123,17 +128,22 @@ particularly relevant.
 The interface to Berkeley DB is implemented with a number of Perl
 classes.
 
-=head1 ENV CLASS
+=head1 The BerkeleyDB::Env Class
 
 The B<BerkeleyDB::Env> class provides an interface to the Berkeley DB
 function B<db_appinit> in Berkeley DB 2.x or B<db_env_create> and
 B<DBENV-E<gt>open> in Berkeley DB 3.x/4.x. Its purpose is to initialise a
 number of sub-systems that can then be used in a consistent way in all
-the databases you make use of the environment.
+the databases you make use of in the environment.
 
 If you don't intend using transactions, locking or logging, then you
 shouldn't need to make use of B<BerkeleyDB::Env>.
 
+Note that an environment consists of a number of files that Berkeley DB
+manages behind the scenes for you. When you first use an environment, it
+needs to be explicitly created. This is done by including C<DB_CREATE>
+with the C<Flags> parameter, described below.
+
 =head2 Synopsis
 
     $env = new BerkeleyDB::Env
@@ -146,12 +156,15 @@ shouldn't need to make use of B<BerkeleyDB::Env>.
              [ -Flags        => number, ]
              [ -SetFlags     => bitmask, ]
              [ -LockDetect   => number, ]
+             [ -SharedMemKey => number, ]
              [ -Verbose      => boolean, ]
-
-=over 5
+             [ -Encrypt      => { Password => "string",
+	                          Flags    => number }, ]
 
 All the parameters to the BerkeleyDB::Env constructor are optional.
 
+=over 5
+
 =item -Home
 
 If present, this parameter should point to an existing directory. Any
@@ -183,11 +196,34 @@ part of an absolute path.
 If present, this parameter should be the hostname of a server that is running
 the Berkeley DB RPC server. All databases will be accessed via the RPC server.
 
+=item -Encrypt
+
+If present, this parameter will enable encryption of  all data before
+it is written to the database. This parameters must be given a hash
+reference. The format is shown below.
+
+    -Encrypt => { -Password => "abc", Flags => DB_ENCRYPT_AES }
+
+Valid values for the Flags are 0 or C<DB_ENCRYPT_AES>.
+
+This option requires Berkeley DB 4.1 or better.
+
 =item -Cachesize
 
 If present, this parameter sets the size of the environments shared memory
 buffer pool.
 
+=item -SharedMemKey
+
+If present, this parameter sets the base segment ID for the shared memory
+region used by Berkeley DB. 
+
+This option requires Berkeley DB 3.1 or better.
+
+Use C<$env-E<gt>get_shm_key($id)> to find out the base segment ID used
+once the environment is open.
+
+
 =item -Config
 
 This is a variation on the C<-Home> parameter, but it allows finer
@@ -207,8 +243,15 @@ The code below shows an example of how it can be used.
 
 =item -ErrFile
 
-Expects a filenme. Any errors generated internally by Berkeley DB will
-be logged to this file.
+Expects a filename or filenhandle. Any errors generated internally by
+Berkeley DB will be logged to this file. A useful debug setting is to
+open environments with either
+
+    -ErrFile => *STDOUT
+
+or 
+
+    -ErrFile => *STDERR
 
 =item -ErrPrefix
 
@@ -335,11 +378,25 @@ TODO
 
 Returns the status of the last BerkeleyDB::Env method.
 
-=item $env->setmutexlocks()
 
-Only available in Berkeley Db 3.0 or greater. Calls 
-B<db_env_set_mutexlocks> when used with Berkeley DB 3.1.x. When used with
-Berkeley DB 3.0 or 3.2 and better it calls B<DBENV-E<gt>set_mutexlocks>.
+=item $env->DB_ENV()
+
+Returns a pointer to the underlying DB_ENV data structure that Berkeley
+DB uses.
+
+=item $env->get_shm_key($id)
+
+Writes the base segment ID for the shared memory region used by the
+Berkeley DB environment into C<$id>. Returns 0 on success.
+
+This option requires Berkeley DB 4.2 or better.
+
+Use the C<-SharedMemKey> option when opening the environemt to set the
+base segment ID.
+
+=item $env->status()
+
+Returns the status of the last BerkeleyDB::Env method.
 
 =back
 
@@ -352,7 +409,7 @@ TODO.
   $status = BerkeleyDB::db_remove [OPTIONS]
   $status = BerkeleyDB::db_rename [OPTIONS]
   $status = BerkeleyDB::db_verify [OPTIONS]
-  
+
 =head1 THE DATABASE CLASSES
 
 B<BerkeleyDB> supports the following database formats:
@@ -421,6 +478,8 @@ Two forms of constructor are supported:
                 [ -Pagesize      => number,]
                 [ -Env           => $env,]
                 [ -Txn           => $txn,]
+                [ -Encrypt       => { Password => "string",
+	                              Flags    => number }, ],
                 # BerkeleyDB::Hash specific
                 [ -Ffactor       => number,]
                 [ -Nelem         => number,]
@@ -440,6 +499,8 @@ and this
                 [ -Pagesize      => number,]
                 [ -Env           => $env,]
                 [ -Txn           => $txn,]
+                [ -Encrypt       => { Password => "string",
+	                              Flags    => number }, ],
                 # BerkeleyDB::Hash specific
                 [ -Ffactor       => number,]
                 [ -Nelem         => number,]
@@ -464,7 +525,7 @@ B<BerkeleyDB::Hash> supports these options:
 =item -Property
 
 Used to specify extra flags when opening a database. The following
-flags may be specified by logically OR'ing together one or more of the
+flags may be specified by bitwise OR'ing together one or more of the
 following values:
 
 B<DB_DUP>
@@ -731,6 +792,8 @@ Two forms of constructor are supported:
                 [ -Pagesize      => number,]
                 [ -Env           => $env,]
                 [ -Txn           => $txn,]
+                [ -Encrypt       => { Password => "string",
+	                              Flags    => number }, ],
                 # BerkeleyDB::Btree specific
                 [ -Minkey        => number,]
                 [ -Compare       => code reference,]
@@ -750,6 +813,8 @@ and this
                 [ -Pagesize      => number,]
                 [ -Env           => $env,]
                 [ -Txn           => $txn,]
+                [ -Encrypt       => { Password => "string",
+	                              Flags    => number }, ],
                 # BerkeleyDB::Btree specific
                 [ -Minkey        => number,]
                 [ -Compare       => code reference,]
@@ -766,7 +831,7 @@ B<BerkeleyDB::Btree> supports these options:
 =item -Property
 
 Used to specify extra flags when opening a database. The following
-flags may be specified by logically OR'ing together one or more of the
+flags may be specified by bitwise OR'ing together one or more of the
 following values:
 
 B<DB_DUP>
@@ -978,6 +1043,8 @@ Two forms of constructor are supported:
                 [ -Pagesize      => number,]
                 [ -Env           => $env,]
                 [ -Txn           => $txn,]
+                [ -Encrypt       => { Password => "string",
+	                              Flags    => number }, ],
                 # BerkeleyDB::Recno specific
                 [ -Delim           => byte,]
                 [ -Len             => number,]
@@ -997,6 +1064,8 @@ and this
                 [ -Pagesize      => number,]
                 [ -Env           => $env,]
                 [ -Txn           => $txn,]
+                [ -Encrypt       => { Password => "string",
+	                              Flags    => number }, ],
                 # BerkeleyDB::Recno specific
                 [ -Delim           => byte,]
                 [ -Len             => number,]
@@ -1072,6 +1141,8 @@ Two forms of constructor are supported:
                 [ -Pagesize      => number,]
                 [ -Env           => $env,]
                 [ -Txn           => $txn,]
+                [ -Encrypt       => { Password => "string",
+	                              Flags    => number }, ],
                 # BerkeleyDB::Queue specific
                 [ -Len             => number,]
                 [ -Pad             => byte,]
@@ -1090,6 +1161,8 @@ and this
                 [ -Pagesize      => number,]
                 [ -Env           => $env,]
                 [ -Txn           => $txn,]
+                [ -Encrypt       => { Password => "string",
+	                              Flags    => number }, ],
                 # BerkeleyDB::Queue specific
                 [ -Len             => number,]
                 [ -Pad             => byte,]
@@ -1116,6 +1189,8 @@ The constructor looks like this:
                 [ -Pagesize      => number,]
                 [ -Env           => $env,]
                 [ -Txn           => $txn,]
+                [ -Encrypt       => { Password => "string",
+	                              Flags    => number }, ],
 
 
 =head2 An example 
@@ -1180,6 +1255,18 @@ When working under a Berkeley DB environment, this parameter
 
 Defaults to no environment.
 
+=item -Encrypt
+
+If present, this parameter will enable encryption of  all data before
+it is written to the database. This parameters must be given a hash
+reference. The format is shown below.
+
+    -Encrypt => { -Password => "abc", Flags => DB_ENCRYPT_AES }
+
+Valid values for the Flags are 0 or C<DB_ENCRYPT_AES>.
+
+This option requires Berkeley DB 4.1 or better.
+
 =item -Txn
 
 TODO.
@@ -1215,7 +1302,7 @@ TODO.
 
 =back
 
-In addition, the following value may be set by logically OR'ing it into
+In addition, the following value may be set by bitwise OR'ing it into
 the B<$flags> parameter:
 
 =over 5
@@ -1300,7 +1387,32 @@ database and B<DB_RECNO> for a B<BerkeleyDB::Recno> database. This method
 is typically used when a database has been opened with
 B<BerkeleyDB::Unknown>.
 
-=item $ref = $db->db_stat()
+=head2   $bool = $env->cds_enabled();
+
+Returns true if the Berkeley DB environment C<$env> has been opened on
+CDS mode.
+
+=head2   $bool = $db->cds_enabled();
+
+Returns true if the database C<$db> has been opened on CDS mode.
+
+=head2 $lock = $db->cds_lock();
+
+Creates a CDS write lock object C<$lock>.
+
+It is a fatal error to attempt to create a cds_lock if the Berkeley DB
+environment has not been opened in CDS mode.
+
+=head2 $lock->cds_unlock();
+
+Removes a CDS lock. The destruction of the CDS lock object automatically
+calls this method.
+
+Note that if multiple CDS lock objects are created, the underlying write
+lock will not be released until all CDS lock objects are either explictly
+unlocked with this method, or the CDS lock objects have been destroyed.
+
+=head2 $ref = $db->db_stat()
 
 Returns a reference to an associative array containing information about
 the database. The keys of the associative array correspond directly to the
@@ -1430,7 +1542,7 @@ TODO.
 
 =back
 
-In addition, the following value may be set by logically OR'ing it into
+In addition, the following value may be set by bitwise OR'ing it into
 the B<$flags> parameter:
 
 =over 5
@@ -1507,7 +1619,7 @@ deleted, B<c_del> will return B<DB_KEYEMPTY>.
 
 The B<$flags> parameter is not used at present.
 
-=head2 $status = $cursor->c_del($cnt [, $flags])
+=head2 $status = $cursor->c_count($cnt [, $flags])
 
 Stores the number of duplicates at the current cursor position in B<$cnt>.
 
@@ -1518,6 +1630,14 @@ Berkeley DB 3.1 or better.
 
 Returns the status of the last cursor method as a dual type.
 
+=head2  $status = $cursor->c_pget() ;
+
+TODO
+
+=head2  $status = $cursor->c_close()
+
+Closes the cursor B<$cursor>.
+
 =head2 Cursor Examples
 
 TODO
@@ -1536,6 +1656,12 @@ TODO
 
 TODO.
 
+=head1 CDS Mode
+
+The Berkeley Db Concurrent Data Store is a lightweight locking mechanism
+that is useful in scenarios where transactions are overkill. See the
+accompanying document .. for details of using this module in CDS mode.
+
 =head1 DBM Filters
 
 A DBM Filter is a piece of code that is be used when you I<always>
@@ -1731,10 +1857,10 @@ I get asked.
 
 Before Berkeley DB 2.x was written there was only one Perl module that
 interfaced to Berkeley DB. That module is called B<DB_File>. Although
-B<DB_File> can be build with Berkeley DB 1.x, 2.x, 3.x or 4.x, it only provides
-an interface to the functionality available in Berkeley DB 1.x. That
-means that it doesn't support transactions, locking or any of the other
-new features available in DB 2.x or better.
+B<DB_File> can be build with Berkeley DB 1.x, 2.x, 3.x or 4.x, it only
+provides an interface to the functionality available in Berkeley DB
+1.x. That means that it doesn't support transactions, locking or any of
+the other new features available in DB 2.x or better.
 
 =head2 How do I store Perl data structures with BerkeleyDB?
 
@@ -1754,7 +1880,7 @@ The official web site for Berkeley DB is F<http://www.sleepycat.com>.
 
 =head1 COPYRIGHT
 
-Copyright (c) 1997-2002 Paul Marquess. All rights reserved. This program
+Copyright (c) 1997-2004 Paul Marquess. All rights reserved. This program
 is free software; you can redistribute it and/or modify it under the
 same terms as Perl itself.
 
@@ -1781,7 +1907,7 @@ See L<"AUTHOR"> for details.
 
 =head1 AUTHOR
 
-Paul Marquess E<lt>Paul.Marquess@btinternet.comE<gt>.
+Paul Marquess E<lt>pmqs@cpan.orgE<gt>.
 
 Questions about Berkeley DB may be addressed to E<lt>db@sleepycat.comE<gt>.
 
diff --git a/storage/bdb/perl/BerkeleyDB/BerkeleyDB.pod.P b/storage/bdb/perl/BerkeleyDB/BerkeleyDB.pod.P
index 4a848f5388d9ab8b3f8c05b840f70454a829e875..6540a943a7a86e3aed4dcf7a502de62290c3bb59 100644
--- a/storage/bdb/perl/BerkeleyDB/BerkeleyDB.pod.P
+++ b/storage/bdb/perl/BerkeleyDB/BerkeleyDB.pod.P
@@ -14,10 +14,10 @@ BerkeleyDB - Perl extension for Berkeley DB version 2, 3 or 4
   $db  = tie %hash, 'BerkeleyDB::Btree', [OPTIONS] ;
   $db  = new BerkeleyDB::Btree [OPTIONS] ;
 
-  $db  = tie %hash, 'BerkeleyDB::Recno', [OPTIONS] ;
+  $db  = tie @array, 'BerkeleyDB::Recno', [OPTIONS] ;
   $db  = new BerkeleyDB::Recno [OPTIONS] ;
 
-  $db  = tie %hash, 'BerkeleyDB::Queue', [OPTIONS] ;
+  $db  = tie @array, 'BerkeleyDB::Queue', [OPTIONS] ;
   $db  = new BerkeleyDB::Queue [OPTIONS] ;
 
   $db  = new BerkeleyDB::Unknown [OPTIONS] ;
@@ -37,7 +37,6 @@ BerkeleyDB - Perl extension for Berkeley DB version 2, 3 or 4
   $status = $db->db_del() ;
   $status = $db->db_sync() ;
   $status = $db->db_close() ;
-  $status = $db->db_close() ;
   $status = $db->db_pget()
   $hash_ref = $db->db_stat() ;
   $status = $db->db_key_range();
@@ -46,6 +45,11 @@ BerkeleyDB - Perl extension for Berkeley DB version 2, 3 or 4
   $boolean = $db->byteswapped() ;
   $status = $db->truncate($count) ;
 
+  $bool = $env->cds_enabled();
+  $bool = $db->cds_enabled();
+  $lock = $db->cds_lock();
+  $lock->cds_unlock();
+  
   ($flag, $old_offset, $old_length) = $db->partial_set($offset, $length) ;
   ($flag, $old_offset, $old_length) = $db->partial_clear() ;
 
@@ -84,6 +88,7 @@ BerkeleyDB - Perl extension for Berkeley DB version 2, 3 or 4
   $status = $env->set_data_dir() ;
   $status = $env->set_tmp_dir() ;
   $status = $env->set_verbose() ;
+  $db_env_ptr = $env->DB_ENV() ;
 
   $BerkeleyDB::Error
   $BerkeleyDB::db_version
@@ -123,17 +128,22 @@ particularly relevant.
 The interface to Berkeley DB is implemented with a number of Perl
 classes.
 
-=head1 ENV CLASS
+=head1 The BerkeleyDB::Env Class
 
 The B<BerkeleyDB::Env> class provides an interface to the Berkeley DB
 function B<db_appinit> in Berkeley DB 2.x or B<db_env_create> and
 B<DBENV-E<gt>open> in Berkeley DB 3.x/4.x. Its purpose is to initialise a
 number of sub-systems that can then be used in a consistent way in all
-the databases you make use of the environment.
+the databases you make use of in the environment.
 
 If you don't intend using transactions, locking or logging, then you
 shouldn't need to make use of B<BerkeleyDB::Env>.
 
+Note that an environment consists of a number of files that Berkeley DB
+manages behind the scenes for you. When you first use an environment, it
+needs to be explicitly created. This is done by including C<DB_CREATE>
+with the C<Flags> parameter, described below.
+
 =head2 Synopsis
 
     $env = new BerkeleyDB::Env
@@ -146,12 +156,15 @@ shouldn't need to make use of B<BerkeleyDB::Env>.
              [ -Flags        => number, ]
              [ -SetFlags     => bitmask, ]
              [ -LockDetect   => number, ]
+             [ -SharedMemKey => number, ]
              [ -Verbose      => boolean, ]
-
-=over 5
+             [ -Encrypt      => { Password => "string",
+	                          Flags    => number }, ]
 
 All the parameters to the BerkeleyDB::Env constructor are optional.
 
+=over 5
+
 =item -Home
 
 If present, this parameter should point to an existing directory. Any
@@ -183,11 +196,34 @@ part of an absolute path.
 If present, this parameter should be the hostname of a server that is running
 the Berkeley DB RPC server. All databases will be accessed via the RPC server.
 
+=item -Encrypt
+
+If present, this parameter will enable encryption of  all data before
+it is written to the database. This parameters must be given a hash
+reference. The format is shown below.
+
+    -Encrypt => { -Password => "abc", Flags => DB_ENCRYPT_AES }
+
+Valid values for the Flags are 0 or C<DB_ENCRYPT_AES>.
+
+This option requires Berkeley DB 4.1 or better.
+
 =item -Cachesize
 
 If present, this parameter sets the size of the environments shared memory
 buffer pool.
 
+=item -SharedMemKey
+
+If present, this parameter sets the base segment ID for the shared memory
+region used by Berkeley DB. 
+
+This option requires Berkeley DB 3.1 or better.
+
+Use C<$env-E<gt>get_shm_key($id)> to find out the base segment ID used
+once the environment is open.
+
+
 =item -Config
 
 This is a variation on the C<-Home> parameter, but it allows finer
@@ -207,8 +243,15 @@ The code below shows an example of how it can be used.
 
 =item -ErrFile
 
-Expects a filenme. Any errors generated internally by Berkeley DB will
-be logged to this file.
+Expects a filename or filenhandle. Any errors generated internally by
+Berkeley DB will be logged to this file. A useful debug setting is to
+open environments with either
+
+    -ErrFile => *STDOUT
+
+or 
+
+    -ErrFile => *STDERR
 
 =item -ErrPrefix
 
@@ -335,11 +378,25 @@ TODO
 
 Returns the status of the last BerkeleyDB::Env method.
 
-=item $env->setmutexlocks()
 
-Only available in Berkeley Db 3.0 or greater. Calls 
-B<db_env_set_mutexlocks> when used with Berkeley DB 3.1.x. When used with
-Berkeley DB 3.0 or 3.2 and better it calls B<DBENV-E<gt>set_mutexlocks>.
+=item $env->DB_ENV()
+
+Returns a pointer to the underlying DB_ENV data structure that Berkeley
+DB uses.
+
+=item $env->get_shm_key($id)
+
+Writes the base segment ID for the shared memory region used by the
+Berkeley DB environment into C<$id>. Returns 0 on success.
+
+This option requires Berkeley DB 4.2 or better.
+
+Use the C<-SharedMemKey> option when opening the environemt to set the
+base segment ID.
+
+=item $env->status()
+
+Returns the status of the last BerkeleyDB::Env method.
 
 =back
 
@@ -352,7 +409,7 @@ TODO.
   $status = BerkeleyDB::db_remove [OPTIONS]
   $status = BerkeleyDB::db_rename [OPTIONS]
   $status = BerkeleyDB::db_verify [OPTIONS]
-  
+
 =head1 THE DATABASE CLASSES
 
 B<BerkeleyDB> supports the following database formats:
@@ -421,6 +478,8 @@ Two forms of constructor are supported:
                 [ -Pagesize      => number,]
                 [ -Env           => $env,]
                 [ -Txn           => $txn,]
+                [ -Encrypt       => { Password => "string",
+	                              Flags    => number }, ],
                 # BerkeleyDB::Hash specific
                 [ -Ffactor       => number,]
                 [ -Nelem         => number,]
@@ -440,6 +499,8 @@ and this
                 [ -Pagesize      => number,]
                 [ -Env           => $env,]
                 [ -Txn           => $txn,]
+                [ -Encrypt       => { Password => "string",
+	                              Flags    => number }, ],
                 # BerkeleyDB::Hash specific
                 [ -Ffactor       => number,]
                 [ -Nelem         => number,]
@@ -464,7 +525,7 @@ B<BerkeleyDB::Hash> supports these options:
 =item -Property
 
 Used to specify extra flags when opening a database. The following
-flags may be specified by logically OR'ing together one or more of the
+flags may be specified by bitwise OR'ing together one or more of the
 following values:
 
 B<DB_DUP>
@@ -623,6 +684,8 @@ Two forms of constructor are supported:
                 [ -Pagesize      => number,]
                 [ -Env           => $env,]
                 [ -Txn           => $txn,]
+                [ -Encrypt       => { Password => "string",
+	                              Flags    => number }, ],
                 # BerkeleyDB::Btree specific
                 [ -Minkey        => number,]
                 [ -Compare       => code reference,]
@@ -642,6 +705,8 @@ and this
                 [ -Pagesize      => number,]
                 [ -Env           => $env,]
                 [ -Txn           => $txn,]
+                [ -Encrypt       => { Password => "string",
+	                              Flags    => number }, ],
                 # BerkeleyDB::Btree specific
                 [ -Minkey        => number,]
                 [ -Compare       => code reference,]
@@ -658,7 +723,7 @@ B<BerkeleyDB::Btree> supports these options:
 =item -Property
 
 Used to specify extra flags when opening a database. The following
-flags may be specified by logically OR'ing together one or more of the
+flags may be specified by bitwise OR'ing together one or more of the
 following values:
 
 B<DB_DUP>
@@ -817,6 +882,8 @@ Two forms of constructor are supported:
                 [ -Pagesize      => number,]
                 [ -Env           => $env,]
                 [ -Txn           => $txn,]
+                [ -Encrypt       => { Password => "string",
+	                              Flags    => number }, ],
                 # BerkeleyDB::Recno specific
                 [ -Delim           => byte,]
                 [ -Len             => number,]
@@ -836,6 +903,8 @@ and this
                 [ -Pagesize      => number,]
                 [ -Env           => $env,]
                 [ -Txn           => $txn,]
+                [ -Encrypt       => { Password => "string",
+	                              Flags    => number }, ],
                 # BerkeleyDB::Recno specific
                 [ -Delim           => byte,]
                 [ -Len             => number,]
@@ -878,6 +947,8 @@ Two forms of constructor are supported:
                 [ -Pagesize      => number,]
                 [ -Env           => $env,]
                 [ -Txn           => $txn,]
+                [ -Encrypt       => { Password => "string",
+	                              Flags    => number }, ],
                 # BerkeleyDB::Queue specific
                 [ -Len             => number,]
                 [ -Pad             => byte,]
@@ -896,6 +967,8 @@ and this
                 [ -Pagesize      => number,]
                 [ -Env           => $env,]
                 [ -Txn           => $txn,]
+                [ -Encrypt       => { Password => "string",
+	                              Flags    => number }, ],
                 # BerkeleyDB::Queue specific
                 [ -Len             => number,]
                 [ -Pad             => byte,]
@@ -922,6 +995,8 @@ The constructor looks like this:
                 [ -Pagesize      => number,]
                 [ -Env           => $env,]
                 [ -Txn           => $txn,]
+                [ -Encrypt       => { Password => "string",
+	                              Flags    => number }, ],
 
 
 =head2 An example 
@@ -986,6 +1061,18 @@ When working under a Berkeley DB environment, this parameter
 
 Defaults to no environment.
 
+=item -Encrypt
+
+If present, this parameter will enable encryption of  all data before
+it is written to the database. This parameters must be given a hash
+reference. The format is shown below.
+
+    -Encrypt => { -Password => "abc", Flags => DB_ENCRYPT_AES }
+
+Valid values for the Flags are 0 or C<DB_ENCRYPT_AES>.
+
+This option requires Berkeley DB 4.1 or better.
+
 =item -Txn
 
 TODO.
@@ -1021,7 +1108,7 @@ TODO.
 
 =back
 
-In addition, the following value may be set by logically OR'ing it into
+In addition, the following value may be set by bitwise OR'ing it into
 the B<$flags> parameter:
 
 =over 5
@@ -1106,7 +1193,32 @@ database and B<DB_RECNO> for a B<BerkeleyDB::Recno> database. This method
 is typically used when a database has been opened with
 B<BerkeleyDB::Unknown>.
 
-=item $ref = $db->db_stat()
+=head2   $bool = $env->cds_enabled();
+
+Returns true if the Berkeley DB environment C<$env> has been opened on
+CDS mode.
+
+=head2   $bool = $db->cds_enabled();
+
+Returns true if the database C<$db> has been opened on CDS mode.
+
+=head2 $lock = $db->cds_lock();
+
+Creates a CDS write lock object C<$lock>.
+
+It is a fatal error to attempt to create a cds_lock if the Berkeley DB
+environment has not been opened in CDS mode.
+
+=head2 $lock->cds_unlock();
+
+Removes a CDS lock. The destruction of the CDS lock object automatically
+calls this method.
+
+Note that if multiple CDS lock objects are created, the underlying write
+lock will not be released until all CDS lock objects are either explictly
+unlocked with this method, or the CDS lock objects have been destroyed.
+
+=head2 $ref = $db->db_stat()
 
 Returns a reference to an associative array containing information about
 the database. The keys of the associative array correspond directly to the
@@ -1236,7 +1348,7 @@ TODO.
 
 =back
 
-In addition, the following value may be set by logically OR'ing it into
+In addition, the following value may be set by bitwise OR'ing it into
 the B<$flags> parameter:
 
 =over 5
@@ -1313,7 +1425,7 @@ deleted, B<c_del> will return B<DB_KEYEMPTY>.
 
 The B<$flags> parameter is not used at present.
 
-=head2 $status = $cursor->c_del($cnt [, $flags])
+=head2 $status = $cursor->c_count($cnt [, $flags])
 
 Stores the number of duplicates at the current cursor position in B<$cnt>.
 
@@ -1324,6 +1436,14 @@ Berkeley DB 3.1 or better.
 
 Returns the status of the last cursor method as a dual type.
 
+=head2  $status = $cursor->c_pget() ;
+
+TODO
+
+=head2  $status = $cursor->c_close()
+
+Closes the cursor B<$cursor>.
+
 =head2 Cursor Examples
 
 TODO
@@ -1342,6 +1462,12 @@ TODO
 
 TODO.
 
+=head1 CDS Mode
+
+The Berkeley Db Concurrent Data Store is a lightweight locking mechanism
+that is useful in scenarios where transactions are overkill. See the
+accompanying document .. for details of using this module in CDS mode.
+
 =head1 DBM Filters
 
 A DBM Filter is a piece of code that is be used when you I<always>
@@ -1498,10 +1624,10 @@ I get asked.
 
 Before Berkeley DB 2.x was written there was only one Perl module that
 interfaced to Berkeley DB. That module is called B<DB_File>. Although
-B<DB_File> can be build with Berkeley DB 1.x, 2.x, 3.x or 4.x, it only provides
-an interface to the functionality available in Berkeley DB 1.x. That
-means that it doesn't support transactions, locking or any of the other
-new features available in DB 2.x or better.
+B<DB_File> can be build with Berkeley DB 1.x, 2.x, 3.x or 4.x, it only
+provides an interface to the functionality available in Berkeley DB
+1.x. That means that it doesn't support transactions, locking or any of
+the other new features available in DB 2.x or better.
 
 =head2 How do I store Perl data structures with BerkeleyDB?
 
@@ -1521,7 +1647,7 @@ The official web site for Berkeley DB is F<http://www.sleepycat.com>.
 
 =head1 COPYRIGHT
 
-Copyright (c) 1997-2002 Paul Marquess. All rights reserved. This program
+Copyright (c) 1997-2004 Paul Marquess. All rights reserved. This program
 is free software; you can redistribute it and/or modify it under the
 same terms as Perl itself.
 
@@ -1548,7 +1674,7 @@ See L<"AUTHOR"> for details.
 
 =head1 AUTHOR
 
-Paul Marquess E<lt>Paul.Marquess@btinternet.comE<gt>.
+Paul Marquess E<lt>pmqs@cpan.orgE<gt>.
 
 Questions about Berkeley DB may be addressed to E<lt>db@sleepycat.comE<gt>.
 
diff --git a/storage/bdb/perl/BerkeleyDB/BerkeleyDB.xs b/storage/bdb/perl/BerkeleyDB/BerkeleyDB.xs
index 531b38a655fe63db73a7b01531fd08f389704b70..bd78509f5f2285861cce564e07859141afab63d7 100644
--- a/storage/bdb/perl/BerkeleyDB/BerkeleyDB.xs
+++ b/storage/bdb/perl/BerkeleyDB/BerkeleyDB.xs
@@ -1,12 +1,12 @@
 /*
 
- BerkeleyDB.xs -- Perl 5 interface to Berkeley DB version 2 & 3
+ BerkeleyDB.xs -- Perl 5 interface to Berkeley DB version 2, 3 &4
 
- written by Paul Marquess <Paul.Marquess@btinternet.com>
+ written by Paul Marquess <pmqs@cpan.org>
 
  All comments/suggestions/problems are welcome
 
-     Copyright (c) 1997-2002 Paul Marquess. All rights reserved.
+     Copyright (c) 1997-2004 Paul Marquess. All rights reserved.
      This program is free software; you can redistribute it and/or
      modify it under the same terms as Perl itself.
 
@@ -45,6 +45,12 @@ extern "C" {
 #  ifdef fclose
 #    undef fclose
 #  endif
+#  ifdef rename
+#    undef rename
+#  endif
+#  ifdef open
+#    undef open
+#  endif
 #endif
 
 /* Being the Berkeley DB we prefer the <sys/cdefs.h> (which will be
@@ -54,9 +60,9 @@ extern "C" {
 #undef __attribute__
 
 #ifdef USE_PERLIO
-#    define GetFILEptr(sv) PerlIO_findFILE(IoOFP(sv_2io(sv)))
+#    define GetFILEptr(sv) PerlIO_findFILE(IoIFP(sv_2io(sv)))
 #else
-#    define GetFILEptr(sv) IoOFP(sv_2io(sv))
+#    define GetFILEptr(sv) IoIFP(sv_2io(sv))
 #endif
 
 #include <db.h>
@@ -111,6 +117,14 @@ extern "C" {
 #  define AT_LEAST_DB_4_1
 #endif
 
+#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 2)
+#  define AT_LEAST_DB_4_2
+#endif
+
+#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3)
+#  define AT_LEAST_DB_4_3
+#endif
+
 #ifdef __cplusplus
 }
 #endif
@@ -128,10 +142,24 @@ extern "C" {
 #  define DB_QUEUE		4
 #endif /* DB_VERSION_MAJOR == 2 */
 
+#if DB_VERSION_MAJOR == 2 
+#  define BackRef	internal
+#else
+#  if DB_VERSION_MAJOR == 3 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0)
+#    define BackRef	cj_internal
+#  else
+#    define BackRef	api_internal
+#  endif
+#endif
+
 #ifdef AT_LEAST_DB_3_2
 #    define DB_callback	DB * db,
+#    define getCurrentDB ((BerkeleyDB)db->BackRef) 
+#    define saveCurrentDB(db) 
 #else
 #    define DB_callback
+#    define getCurrentDB CurrentDB
+#    define saveCurrentDB(db) CurrentDB = db
 #endif
 
 #if DB_VERSION_MAJOR > 2
@@ -175,12 +203,14 @@ typedef struct {
 	int		Status ;
 	/* char		ErrBuff[1000] ; */
 	SV *		ErrPrefix ;
-	FILE *		ErrHandle ;
+	SV *		ErrHandle ;
 	DB_ENV *	Env ;
 	int		open_dbs ;
 	int		TxnMgrStatus ;
 	int		active ;
 	bool		txn_enabled ;
+	bool		opened ;
+	bool		cds_enabled;
 	} BerkeleyDB_ENV_type ;
 
 
@@ -211,6 +241,7 @@ typedef struct {
 	u_int32_t	dlen ;
 	u_int32_t	doff ;
 	int		active ;
+	bool		cds_enabled;
 #ifdef ALLOW_RECNO_OFFSET
 	int		array_base ;
 #endif
@@ -246,6 +277,7 @@ typedef struct {
 	u_int32_t	dlen ;
 	u_int32_t	doff ;
 	int		active ;
+	bool		cds_enabled;
 #ifdef ALLOW_RECNO_OFFSET
 	int		array_base ;
 #endif
@@ -337,15 +369,6 @@ hash_delete(char * hash, char * key);
 #  define flagSet(bitmask)	((flags & DB_OPFLAGS_MASK) == (bitmask))
 #endif
 
-#if DB_VERSION_MAJOR == 2 
-#  define BackRef	internal
-#else
-#  if DB_VERSION_MAJOR == 3 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0)
-#    define BackRef	cj_internal
-#  else
-#    define BackRef	api_internal
-#  endif
-#endif
 
 #define ERR_BUFF "BerkeleyDB::Error"
 
@@ -460,6 +483,10 @@ hash_delete(char * hash, char * key);
 #define ckActive_Database(a) 	ckActive(a, "Database")
 #define ckActive_Cursor(a) 	ckActive(a, "Cursor")
 
+#define dieIfEnvOpened(e, m) if (e->opened) softCrash("Cannot call method BerkeleyDB::Env::%s after environment has been opened", m);	
+
+#define isSTDOUT_ERR(f) ((f) == stdout || (f) == stderr)
+
 /* Internal Global Data */
 static db_recno_t Value ;
 static db_recno_t zero = 0 ;
@@ -495,7 +522,7 @@ my_strdup(const char *s)
         return NULL ;
 
     {
-        MEM_SIZE l = strlen(s);
+        MEM_SIZE l = strlen(s) + 1;
         char *s1 = (char *)safemalloc(l);
 
         Copy(s, s1, (MEM_SIZE)l, char);
@@ -669,6 +696,8 @@ destroyDB(BerkeleyDB db)
 {
     dTHR;
     if (! PL_dirty && db->active) {
+	if (db->parent_env && db->parent_env->open_dbs)
+	    -- db->parent_env->open_dbs ;
       	-- db->open_cursors ;
 	((db->dbp)->close)(db->dbp, 0) ;
     }
@@ -869,7 +898,7 @@ btree_compare(DB_callback const DBT * key1, const DBT * key2 )
     PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
     PUTBACK ;
 
-    count = perl_call_sv(CurrentDB->compare, G_SCALAR);
+    count = perl_call_sv(getCurrentDB->compare, G_SCALAR);
 
     SPAGAIN ;
 
@@ -896,10 +925,12 @@ dup_compare(DB_callback const DBT * key1, const DBT * key2 )
     BerkeleyDB	keepDB = CurrentDB ;
 
     Trace(("In dup_compare \n")) ;
-    if (!CurrentDB)
+    if (!getCurrentDB)
 	softCrash("Internal Error - No CurrentDB in dup_compare") ;
-    if (CurrentDB->dup_compare == NULL)
-        softCrash("in dup_compare: no callback specified for database '%s'", CurrentDB->filename) ;
+    if (getCurrentDB->dup_compare == NULL)
+
+
+        softCrash("in dup_compare: no callback specified for database '%s'", getCurrentDB->filename) ;
 
     data1 = (char*) key1->data ;
     data2 = (char*) key2->data ;
@@ -924,7 +955,7 @@ dup_compare(DB_callback const DBT * key1, const DBT * key2 )
     PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
     PUTBACK ;
 
-    count = perl_call_sv(CurrentDB->dup_compare, G_SCALAR);
+    count = perl_call_sv(getCurrentDB->dup_compare, G_SCALAR);
 
     SPAGAIN ;
 
@@ -973,7 +1004,7 @@ btree_prefix(DB_callback const DBT * key1, const DBT * key2 )
     PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
     PUTBACK ;
 
-    count = perl_call_sv(CurrentDB->prefix, G_SCALAR);
+    count = perl_call_sv(getCurrentDB->prefix, G_SCALAR);
 
     SPAGAIN ;
 
@@ -1011,7 +1042,7 @@ hash_cb(DB_callback const void * data, u_int32_t size)
     XPUSHs(sv_2mortal(newSVpvn((char*)data,size)));
     PUTBACK ;
 
-    count = perl_call_sv(CurrentDB->hash, G_SCALAR);
+    count = perl_call_sv(getCurrentDB->hash, G_SCALAR);
 
     SPAGAIN ;
 
@@ -1034,13 +1065,16 @@ static int
 associate_cb(DB_callback const DBT * pkey, const DBT * pdata, DBT * skey)
 {
     dSP ;
-    char * pk_dat, * pd_dat, *sk_dat ;
+    char * pk_dat, * pd_dat ;
+    /* char *sk_dat ; */
     int retval ;
     int count ;
     SV * skey_SV ;
+    STRLEN skey_len;
+    char * skey_ptr ;
 
     Trace(("In associate_cb \n")) ;
-    if (((BerkeleyDB)db->BackRef)->associated == NULL){
+    if (getCurrentDB->associated == NULL){
         Trace(("No Callback registered\n")) ;
         return EINVAL ;
     }
@@ -1073,7 +1107,7 @@ associate_cb(DB_callback const DBT * pkey, const DBT * pdata, DBT * skey)
     PUTBACK ;
 
     Trace(("calling associated cb\n"));
-    count = perl_call_sv(((BerkeleyDB)db->BackRef)->associated, G_SCALAR);
+    count = perl_call_sv(getCurrentDB->associated, G_SCALAR);
     Trace(("called associated cb\n"));
 
     SPAGAIN ;
@@ -1087,10 +1121,13 @@ associate_cb(DB_callback const DBT * pkey, const DBT * pdata, DBT * skey)
     
     /* retrieve the secondary key */
     DBT_clear(*skey);
+    skey_ptr = SvPV(skey_SV, skey_len);
     skey->flags = DB_DBT_APPMALLOC;
-    skey->size = SvCUR(skey_SV);
-    skey->data = (char*)safemalloc(skey->size);
-    memcpy(skey->data, SvPVX(skey_SV), skey->size);
+    /* skey->size = SvCUR(skey_SV); */
+    /* skey->data = (char*)safemalloc(skey->size); */
+    skey->size = skey_len;
+    skey->data = (char*)safemalloc(skey_len);
+    memcpy(skey->data, skey_ptr, skey_len);
     Trace(("key is %d -- %.*s\n", skey->size, skey->size, skey->data));
 
     FREETMPS ;
@@ -1102,7 +1139,11 @@ associate_cb(DB_callback const DBT * pkey, const DBT * pdata, DBT * skey)
 #endif /* AT_LEAST_DB_3_3 */
 
 static void
+#ifdef AT_LEAST_DB_4_3
+db_errcall_cb(const DB_ENV* dbenv, const char * db_errpfx, const char * buffer)
+#else
 db_errcall_cb(const char * db_errpfx, char * buffer)
+#endif
 {
 #if 0
 
@@ -1173,7 +1214,9 @@ my_db_open(
 		DBTYPE		type,
 		int		flags,
 		int		mode,
-		DB_INFO * 	info
+		DB_INFO * 	info,
+		char *		password,
+		int		enc_flags
 	)
 {
     DB_ENV *	env    = NULL ;
@@ -1186,6 +1229,7 @@ my_db_open(
 		dbenv, ref_dbenv, file, subname, type, flags, mode)) ;
 
     CurrentDB = db ;
+    
     if (dbenv)
 	env = dbenv->Env ;
 
@@ -1200,12 +1244,21 @@ my_db_open(
         softCrash("Subname needs Berkeley DB 3 or better") ;
 #endif
 
+#ifndef AT_LEAST_DB_4_1
+	    if (password)
+	        softCrash("-Encrypt needs Berkeley DB 4.x or better") ;
+#endif /* ! AT_LEAST_DB_4_1 */
+
 #if DB_VERSION_MAJOR > 2
     Status = db_create(&dbp, env, 0) ;
     Trace(("db_create returned %s\n", my_db_strerror(Status))) ;
     if (Status)
         return RETVAL ;
 
+#ifdef AT_LEAST_DB_3_2
+	dbp->BackRef = db;
+#endif
+
 #ifdef AT_LEAST_DB_3_3
     if (! env) {
 	dbp->set_alloc(dbp, safemalloc, MyRealloc, safefree) ;
@@ -1213,6 +1266,19 @@ my_db_open(
     }
 #endif
 
+#ifdef AT_LEAST_DB_4_1
+    /* set encryption */
+    if (password)
+    {
+        Status = dbp->set_encrypt(dbp, password, enc_flags);
+        Trace(("DB->set_encrypt passwd = %s, flags %d returned %s\n", 
+			      		password, enc_flags,
+  					my_db_strerror(Status))) ;
+         if (Status)
+              return RETVAL ;
+    }
+#endif	  
+
     if (info->re_source) {
         Status = dbp->set_re_source(dbp, info->re_source) ;
 	Trace(("set_re_source [%s] returned %s\n",
@@ -1336,8 +1402,8 @@ my_db_open(
     if (info->q_extentsize) {
 #ifdef AT_LEAST_DB_3_2
         Status = dbp->set_q_extentsize(dbp, info->q_extentsize) ;
-	Trace(("set_flags [%d] returned %s\n",
-		info->flags, my_db_strerror(Status)));
+	Trace(("set_q_extentsize [%d] returned %s\n",
+		info->q_extentsize, my_db_strerror(Status)));
         if (Status)
             return RETVAL ;
 #else
@@ -1345,6 +1411,7 @@ my_db_open(
 #endif
     }
 
+
 #ifdef AT_LEAST_DB_4_1
     if ((Status = (dbp->open)(dbp, txnid, file, subname, type, flags, mode)) == 0) {
 #else
@@ -1355,9 +1422,6 @@ my_db_open(
 #endif /* DB_VERSION_MAJOR == 2 */
 
 	Trace(("db_opened ok\n"));
-#ifdef AT_LEAST_DB_3_3
-	dbp->BackRef = db;
-#endif
 	RETVAL = db ;
 	RETVAL->dbp  = dbp ;
 	RETVAL->txn  = txnid ;
@@ -1378,6 +1442,7 @@ my_db_open(
 	hash_store_iv("BerkeleyDB::Term::Db", (char *)RETVAL, 1) ;
 	Trace(("  storing %p %p in BerkeleyDB::Term::Db\n", RETVAL, dbp)) ;
 	if (dbenv) {
+	    RETVAL->cds_enabled = dbenv->cds_enabled ;
 	    RETVAL->parent_env = dbenv ;
 	    dbenv->Status = Status ;
 	    ++ dbenv->open_dbs ;
@@ -1527,7 +1592,7 @@ _db_rename(ref)
 		dbenv = env->Env ;
             RETVAL = db_create(&dbp, dbenv, 0) ;
 	    if (RETVAL == 0) {
-	        RETVAL = dbp->rename(dbp, db, subdb, newname, flags) ;
+	        RETVAL = (dbp->rename)(dbp, db, subdb, newname, flags) ;
 	    }
 #endif
 	}
@@ -1536,23 +1601,96 @@ _db_rename(ref)
 
 MODULE = BerkeleyDB::Env		PACKAGE = BerkeleyDB::Env PREFIX = env_
 
+BerkeleyDB::Env::Raw
+create(flags=0)
+	u_int32_t flags
+	CODE:
+	{
+#ifndef AT_LEAST_DB_4_1
+	    softCrash("$env->create needs Berkeley DB 4.1 or better") ;
+#else
+	    DB_ENV *	env ;
+	    int    status;
+	    RETVAL = NULL;
+	    Trace(("in BerkeleyDB::Env::create flags=%d\n",  flags)) ;
+	    status = db_env_create(&env, flags) ;
+	    Trace(("db_env_create returned %s\n", my_db_strerror(status))) ;
+	    if (status == 0) {
+	        ZMALLOC(RETVAL, BerkeleyDB_ENV_type) ;
+		RETVAL->Env = env ;
+	        RETVAL->active = TRUE ;
+	        RETVAL->opened = FALSE;
+	        env->set_alloc(env, safemalloc, MyRealloc, safefree) ;
+	        env->set_errcall(env, db_errcall_cb) ;
+	    }
+#endif	    
+	}
+	OUTPUT:
+	    RETVAL
+
+int
+open(env, db_home=NULL, flags=0, mode=0777)
+	BerkeleyDB::Env env
+	char * db_home
+	u_int32_t flags
+	int mode
+    CODE:
+#ifndef AT_LEAST_DB_4_1
+	    softCrash("$env->create needs Berkeley DB 4.1 or better") ;
+#else
+        RETVAL = env->Env->open(env->Env, db_home, flags, mode);
+	env->opened = TRUE;
+#endif
+    OUTPUT:
+        RETVAL
+
+bool
+cds_enabled(env)
+	BerkeleyDB::Env env
+	CODE:
+	    RETVAL = env->cds_enabled ;
+	OUTPUT:
+	    RETVAL
+
+
+int
+set_encrypt(env, passwd, flags)
+	BerkeleyDB::Env env
+	const char * passwd
+	u_int32_t flags
+    CODE:
+#ifndef AT_LEAST_DB_4_1
+	    softCrash("$env->set_encrypt needs Berkeley DB 4.1 or better") ;
+#else
+        dieIfEnvOpened(env, "set_encrypt");
+        RETVAL = env->Env->set_encrypt(env->Env, passwd, flags);
+	env->opened = TRUE;
+#endif
+    OUTPUT:
+        RETVAL
+
+
+
 
 BerkeleyDB::Env::Raw
-_db_appinit(self, ref)
+_db_appinit(self, ref, errfile=NULL)
 	char *		self
 	SV * 		ref
+	SV * 		errfile 
 	CODE:
 	{
 	    HV *	hash ;
 	    SV *	sv ;
+	    char *	enc_passwd = NULL ;
+	    int		enc_flags = 0 ;
 	    char *	home = NULL ;
-	    char *	errfile = NULL ;
 	    char * 	server = NULL ;
 	    char **	config = NULL ;
 	    int		flags = 0 ;
 	    int		setflags = 0 ;
 	    int		cachesize = 0 ;
 	    int		lk_detect = 0 ;
+	    long	shm_key = 0 ;
 	    SV *	errprefix = NULL;
 	    DB_ENV *	env ;
 	    int status ;
@@ -1560,6 +1698,8 @@ _db_appinit(self, ref)
 	    Trace(("in _db_appinit [%s] %d\n", self, ref)) ;
 	    hash = (HV*) SvRV(ref) ;
 	    SetValue_pv(home,      "Home", char *) ;
+	    SetValue_pv(enc_passwd,"Enc_Passwd", char *) ;
+	    SetValue_iv(enc_flags, "Enc_Flags") ;
 	    SetValue_pv(config,    "Config", char **) ;
 	    SetValue_sv(errprefix, "ErrPrefix") ;
 	    SetValue_iv(flags,     "Flags") ;
@@ -1567,14 +1707,21 @@ _db_appinit(self, ref)
 	    SetValue_pv(server,    "Server", char *) ;
 	    SetValue_iv(cachesize, "Cachesize") ;
 	    SetValue_iv(lk_detect, "LockDetect") ;
+	    SetValue_iv(shm_key,   "SharedMemKey") ;
 #ifndef AT_LEAST_DB_3_2
 	    if (setflags)
 	        softCrash("-SetFlags needs Berkeley DB 3.x or better") ;
 #endif /* ! AT_LEAST_DB_3 */
 #ifndef AT_LEAST_DB_3_1
+	    if (shm_key)
+	        softCrash("-SharedMemKey needs Berkeley DB 3.1 or better") ;
 	    if (server)
 	        softCrash("-Server needs Berkeley DB 3.1 or better") ;
 #endif /* ! AT_LEAST_DB_3_1 */
+#ifndef AT_LEAST_DB_4_1
+	    if (enc_passwd)
+	        softCrash("-Encrypt needs Berkeley DB 4.x or better") ;
+#endif /* ! AT_LEAST_DB_4_1 */
 	    Trace(("_db_appinit(config=[%d], home=[%s],errprefix=[%s],flags=[%d]\n",
 			config, home, errprefix, flags)) ;
 #ifdef TRACE
@@ -1601,26 +1748,33 @@ _db_appinit(self, ref)
 	        Trace(("copying errprefix\n" )) ;
 		RETVAL->ErrPrefix = newSVsv(errprefix) ;
 		SvPOK_only(RETVAL->ErrPrefix) ;
-	    }
+	    } 
 	    if (RETVAL->ErrPrefix)
 	        RETVAL->Env->db_errpfx = SvPVX(RETVAL->ErrPrefix) ;
 
-	    SetValue_pv(errfile,      "ErrFile", char *) ;
-	    if (errfile) {
-	    	RETVAL->ErrHandle = env->db_errfile = fopen(errfile, "w");
-	    	if (RETVAL->ErrHandle == NULL)
-		    croak("Cannot open file %s: %s\n", errfile,  Strerror(errno));
+	    if (SvGMAGICAL(errfile))
+		    mg_get(errfile);
+	    if (SvOK(errfile)) {
+	        FILE * ef = GetFILEptr(errfile) ;
+	    	if (! ef)
+		    croak("Cannot open file ErrFile", Strerror(errno));
+		RETVAL->ErrHandle = newSVsv(errfile) ;
+	    	env->db_errfile = ef;
 	    }
 	    SetValue_iv(env->db_verbose, "Verbose") ;
 	    env->db_errcall = db_errcall_cb ;
 	    RETVAL->active = TRUE ;
+	    RETVAL->opened = TRUE;
+	    RETVAL->cds_enabled = ((flags & DB_INIT_CDB) != 0 ? TRUE : FALSE) ;
 	    status = db_appinit(home, config, env, flags) ;
+	    printf("  status = %d errno %d \n", status, errno) ;
 	    Trace(("  status = %d env %d Env %d\n", status, RETVAL, env)) ;
 	    if (status == 0)
 	        hash_store_iv("BerkeleyDB::Term::Env", (char *)RETVAL, 1) ;
 	    else {
+
                 if (RETVAL->ErrHandle)
-                    fclose(RETVAL->ErrHandle) ;
+                    SvREFCNT_dec(RETVAL->ErrHandle) ;
                 if (RETVAL->ErrPrefix)
                     SvREFCNT_dec(RETVAL->ErrPrefix) ;
                 Safefree(RETVAL->Env) ;
@@ -1631,6 +1785,9 @@ _db_appinit(self, ref)
 #else /* DB_VERSION_MAJOR > 2 */
 #ifndef AT_LEAST_DB_3_1
 #    define DB_CLIENT	0
+#endif
+#ifdef AT_LEAST_DB_4_2
+#    define DB_CLIENT	DB_RPCCLIENT
 #endif
 	  status = db_env_create(&RETVAL->Env, server ? DB_CLIENT : 0) ;
 	  Trace(("db_env_create flags = %d returned %s\n", flags,
@@ -1639,6 +1796,13 @@ _db_appinit(self, ref)
 #ifdef AT_LEAST_DB_3_3
 	  env->set_alloc(env, safemalloc, MyRealloc, safefree) ;
 #endif
+#ifdef AT_LEAST_DB_3_1
+	  if (status == 0 && shm_key) {
+	      status = env->set_shm_key(env, shm_key) ;
+	      Trace(("set_shm_key [%d] returned %s\n", shm_key,
+			my_db_strerror(status)));
+	  }
+#endif	  
 	  if (status == 0 && cachesize) {
 	      status = env->set_cachesize(env, 0, cachesize, 0) ;
 	      Trace(("set_cachesize [%d] returned %s\n",
@@ -1650,6 +1814,16 @@ _db_appinit(self, ref)
 	      Trace(("set_lk_detect [%d] returned %s\n",
 	              lk_detect, my_db_strerror(status)));
 	  }
+#ifdef AT_LEAST_DB_4_1
+	  /* set encryption */
+	  if (enc_passwd && status == 0)
+	  {
+	      status = env->set_encrypt(env, enc_passwd, enc_flags);
+	      Trace(("ENV->set_encrypt passwd = %s, flags %d returned %s\n", 
+				      		enc_passwd, enc_flags,
+	  					my_db_strerror(status))) ;
+	  }
+#endif	  
 #ifdef AT_LEAST_DB_4
 	  /* set the server */
 	  if (server && status == 0)
@@ -1689,22 +1863,27 @@ _db_appinit(self, ref)
 	    if (RETVAL->ErrPrefix)
 	        env->set_errpfx(env, SvPVX(RETVAL->ErrPrefix)) ;
 
-	    SetValue_pv(errfile,      "ErrFile", char *) ;
-	    if (errfile) {
-	    	RETVAL->ErrHandle = fopen(errfile, "w");
-	    	if (RETVAL->ErrHandle == NULL)
-		    croak("Cannot open file %s: %s\n", errfile,  Strerror(errno));
-	    	env->set_errfile(env, RETVAL->ErrHandle) ;
+	    if (SvGMAGICAL(errfile))
+		    mg_get(errfile);
+	    if (SvOK(errfile)) {
+	        FILE * ef = GetFILEptr(errfile);
+	    	if (! ef)
+		    croak("Cannot open file ErrFile", Strerror(errno));
+		RETVAL->ErrHandle = newSVsv(errfile) ;
+	    	env->set_errfile(env, ef) ;
+
 	    }
 
 	    SetValue_iv(mode, "Mode") ;
 	    env->set_errcall(env, db_errcall_cb) ;
 	    RETVAL->active = TRUE ;
+	    RETVAL->cds_enabled = ((flags & DB_INIT_CDB) != 0 ? TRUE : FALSE) ; 
 #ifdef IS_DB_3_0_x
 	    status = (env->open)(env, home, config, flags, mode) ;
 #else /* > 3.0 */
 	    status = (env->open)(env, home, flags, mode) ;
 #endif
+	    Trace(("ENV->open(env=%s,home=%s,flags=%d,mode=%d)\n",env,home,flags,mode)) ;
 	    Trace(("ENV->open returned %s\n", my_db_strerror(status))) ;
 	  }
 
@@ -1713,17 +1892,31 @@ _db_appinit(self, ref)
 	  else {
 	      (env->close)(env, 0) ;
               if (RETVAL->ErrHandle)
-                  fclose(RETVAL->ErrHandle) ;
+                  SvREFCNT_dec(RETVAL->ErrHandle) ;
               if (RETVAL->ErrPrefix)
                   SvREFCNT_dec(RETVAL->ErrPrefix) ;
               Safefree(RETVAL) ;
 	      RETVAL = NULL ;
 	  }
 #endif /* DB_VERSION_MAJOR > 2 */
+	  {
+	      SV * sv_err = perl_get_sv(ERR_BUFF, FALSE);
+	      sv_setpv(sv_err, db_strerror(status));
+	  }
 	}
 	OUTPUT:
 	    RETVAL
 
+DB_ENV*
+DB_ENV(env)
+	BerkeleyDB::Env		env
+	CODE:
+	    if (env->active)
+	        RETVAL = env->Env ;
+	    else
+	        RETVAL = NULL;
+
+
 void
 log_archive(env, flags=0)
 	u_int32_t		flags
@@ -1920,6 +2113,8 @@ status(env)
 	OUTPUT:
 	    RETVAL
 
+
+
 DualType
 db_appexit(env)
         BerkeleyDB::Env 	env
@@ -1957,7 +2152,7 @@ _DESTROY(env)
 	      (env->Env->close)(env->Env, 0) ;
 #endif
           if (env->ErrHandle)
-              fclose(env->ErrHandle) ;
+              SvREFCNT_dec(env->ErrHandle) ;
           if (env->ErrPrefix)
               SvREFCNT_dec(env->ErrPrefix) ;
 #if DB_VERSION_MAJOR == 2
@@ -1981,6 +2176,23 @@ _TxnMgr(env)
 	OUTPUT:
 	    RETVAL
 
+int
+get_shm_key(env, id)
+        BerkeleyDB::Env  env
+	long  		 id = NO_INIT
+	INIT:
+	  ckActive_Database(env->active) ;
+	CODE:
+#ifndef AT_LEAST_DB_4_2
+	    softCrash("$env->get_shm_key needs Berkeley DB 4.2 or better") ;
+#else
+	    RETVAL = env->Env->get_shm_key(env->Env, &id);
+#endif	    
+	OUTPUT:
+	    RETVAL
+	    id
+
+
 int
 set_lg_dir(env, dir)
         BerkeleyDB::Env  env
@@ -2036,6 +2248,7 @@ set_data_dir(env, dir)
 #ifndef AT_LEAST_DB_3_1
 	    softCrash("$env->set_data_dir needs Berkeley DB 3.1 or better") ;
 #else
+            dieIfEnvOpened(env, "set_data_dir");
 	    RETVAL = env->Status = env->Env->set_data_dir(env->Env, dir);
 #endif
 	OUTPUT:
@@ -2141,6 +2354,8 @@ _db_open_hash(self, ref)
 	    int			mode = 0 ;
     	    BerkeleyDB 		db ;
     	    BerkeleyDB__Txn 	txn = NULL ;
+	    char *	enc_passwd = NULL ;
+	    int		enc_flags = 0 ;
 
     	    Trace(("_db_open_hash start\n")) ;
 	    hash = (HV*) SvRV(ref) ;
@@ -2151,6 +2366,8 @@ _db_open_hash(self, ref)
 	    ref_dbenv = sv ;
 	    SetValue_iv(flags, "Flags") ;
 	    SetValue_iv(mode, "Mode") ;
+	    SetValue_pv(enc_passwd,"Enc_Passwd", char *) ;
+	    SetValue_iv(enc_flags, "Enc_Flags") ;
 
        	    Zero(&info, 1, DB_INFO) ;
 	    SetValue_iv(info.db_cachesize, "Cachesize") ;
@@ -2174,7 +2391,7 @@ _db_open_hash(self, ref)
 	        croak("DupCompare needs Berkeley DB 2.5.9 or later") ;
 #endif
 	    }
-	    RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, txn, file, subname, DB_HASH, flags, mode, &info) ;
+	    RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, txn, file, subname, DB_HASH, flags, mode, &info, enc_passwd, enc_flags) ;
     	    Trace(("_db_open_hash end\n")) ;
 	}
 	OUTPUT:
@@ -2194,10 +2411,14 @@ db_stat(db, flags=0)
 	    softCrash("$db->db_stat for a Hash needs Berkeley DB 3.x or better") ;
 #else
 	    DB_HASH_STAT *	stat ;
+#ifdef AT_LEAST_DB_4_3
+	    db->Status = ((db->dbp)->stat)(db->dbp, db->txn, &stat, flags) ;
+#else        
 #ifdef AT_LEAST_DB_3_3
 	    db->Status = ((db->dbp)->stat)(db->dbp, &stat, flags) ;
 #else
 	    db->Status = ((db->dbp)->stat)(db->dbp, &stat, safemalloc, flags) ;
+#endif
 #endif
 	    if (db->Status == 0) {
 	    	RETVAL = (HV*)sv_2mortal((SV*)newHV()) ;
@@ -2254,6 +2475,8 @@ _db_open_unknown(ref)
 	    BerkeleyDB		RETVAL ;
     	    BerkeleyDB__Txn 	txn = NULL ;
 	    static char * 		Names[] = {"", "Btree", "Hash", "Recno"} ;
+	    char *	enc_passwd = NULL ;
+	    int		enc_flags = 0 ;
 
 	    hash = (HV*) SvRV(ref) ;
 	    SetValue_pv(file, "Filename", char *) ;
@@ -2263,6 +2486,8 @@ _db_open_unknown(ref)
 	    ref_dbenv = sv ;
 	    SetValue_iv(flags, "Flags") ;
 	    SetValue_iv(mode, "Mode") ;
+	    SetValue_pv(enc_passwd,"Enc_Passwd", char *) ;
+	    SetValue_iv(enc_flags, "Enc_Flags") ;
 
        	    Zero(&info, 1, DB_INFO) ;
 	    SetValue_iv(info.db_cachesize, "Cachesize") ;
@@ -2273,7 +2498,7 @@ _db_open_unknown(ref)
 	    SetValue_iv(info.flags, "Property") ;
 	    ZMALLOC(db, BerkeleyDB_type) ;
 
-	    RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, txn, file, subname, DB_UNKNOWN, flags, mode, &info) ;
+	    RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, txn, file, subname, DB_UNKNOWN, flags, mode, &info, enc_passwd, enc_flags) ;
 	    XPUSHs(sv_2mortal(newSViv(PTR2IV(RETVAL))));
 	    if (RETVAL)
 	        XPUSHs(sv_2mortal(newSVpv(Names[RETVAL->type], 0))) ;
@@ -2302,6 +2527,8 @@ _db_open_btree(self, ref)
 	    int			mode = 0 ;
     	    BerkeleyDB  	db ;
     	    BerkeleyDB__Txn 	txn = NULL ;
+	    char *	enc_passwd = NULL ;
+	    int		enc_flags = 0 ;
 
 	    Trace(("In _db_open_btree\n"));
 	    hash = (HV*) SvRV(ref) ;
@@ -2312,6 +2539,8 @@ _db_open_btree(self, ref)
 	    ref_dbenv = sv ;
 	    SetValue_iv(flags, "Flags") ;
 	    SetValue_iv(mode, "Mode") ;
+	    SetValue_pv(enc_passwd,"Enc_Passwd", char *) ;
+	    SetValue_iv(enc_flags, "Enc_Flags") ;
 
        	    Zero(&info, 1, DB_INFO) ;
 	    SetValue_iv(info.db_cachesize, "Cachesize") ;
@@ -2342,7 +2571,7 @@ _db_open_btree(self, ref)
 		db->prefix = newSVsv(sv) ;
 	    }
 
-	    RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, txn, file, subname, DB_BTREE, flags, mode, &info) ;
+	    RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, txn, file, subname, DB_BTREE, flags, mode, &info, enc_passwd, enc_flags) ;
 	}
 	OUTPUT:
 	    RETVAL
@@ -2358,10 +2587,14 @@ db_stat(db, flags=0)
 	CODE:
 	{
 	    DB_BTREE_STAT *	stat ;
+#ifdef AT_LEAST_DB_4_3
+	    db->Status = ((db->dbp)->stat)(db->dbp, db->txn, &stat, flags) ;
+#else        
 #ifdef AT_LEAST_DB_3_3
 	    db->Status = ((db->dbp)->stat)(db->dbp, &stat, flags) ;
 #else
 	    db->Status = ((db->dbp)->stat)(db->dbp, &stat, safemalloc, flags) ;
+#endif
 #endif
 	    if (db->Status == 0) {
 	    	RETVAL = (HV*)sv_2mortal((SV*)newHV()) ;
@@ -2432,14 +2665,19 @@ _db_open_recno(self, ref)
 	    int			mode = 0 ;
     	    BerkeleyDB 		db ;
     	    BerkeleyDB__Txn 	txn = NULL ;
+	    char *	enc_passwd = NULL ;
+	    int		enc_flags = 0 ;
 
 	    hash = (HV*) SvRV(ref) ;
 	    SetValue_pv(file, "Fname", char*) ;
+	    SetValue_pv(subname, "Subname", char *) ;
 	    SetValue_ov(dbenv, "Env", BerkeleyDB__Env) ;
 	    ref_dbenv = sv ;
 	    SetValue_ov(txn, "Txn", BerkeleyDB__Txn) ;
 	    SetValue_iv(flags, "Flags") ;
 	    SetValue_iv(mode, "Mode") ;
+	    SetValue_pv(enc_passwd,"Enc_Passwd", char *) ;
+	    SetValue_iv(enc_flags, "Enc_Flags") ;
 
        	    Zero(&info, 1, DB_INFO) ;
 	    SetValue_iv(info.db_cachesize, "Cachesize") ;
@@ -2467,7 +2705,7 @@ _db_open_recno(self, ref)
 	    db->array_base = (db->array_base == 0 ? 1 : 0) ;
 #endif /* ALLOW_RECNO_OFFSET */
 
-	    RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, txn, file, subname, DB_RECNO, flags, mode, &info) ;
+	    RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, txn, file, subname, DB_RECNO, flags, mode, &info, enc_passwd, enc_flags) ;
 	}
 	OUTPUT:
 	    RETVAL
@@ -2495,14 +2733,19 @@ _db_open_queue(self, ref)
 	    int			mode = 0 ;
     	    BerkeleyDB 		db ;
     	    BerkeleyDB__Txn 	txn = NULL ;
+	    char *	enc_passwd = NULL ;
+	    int		enc_flags = 0 ;
 
 	    hash = (HV*) SvRV(ref) ;
 	    SetValue_pv(file, "Fname", char*) ;
+	    SetValue_pv(subname, "Subname", char *) ;
 	    SetValue_ov(dbenv, "Env", BerkeleyDB__Env) ;
 	    ref_dbenv = sv ;
 	    SetValue_ov(txn, "Txn", BerkeleyDB__Txn) ;
 	    SetValue_iv(flags, "Flags") ;
 	    SetValue_iv(mode, "Mode") ;
+	    SetValue_pv(enc_passwd,"Enc_Passwd", char *) ;
+	    SetValue_iv(enc_flags, "Enc_Flags") ;
 
        	    Zero(&info, 1, DB_INFO) ;
 	    SetValue_iv(info.db_cachesize, "Cachesize") ;
@@ -2527,7 +2770,7 @@ _db_open_queue(self, ref)
 	    db->array_base = (db->array_base == 0 ? 1 : 0) ;
 #endif /* ALLOW_RECNO_OFFSET */
 
-	    RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, txn, file, subname, DB_QUEUE, flags, mode, &info) ;
+	    RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, txn, file, subname, DB_QUEUE, flags, mode, &info, enc_passwd, enc_flags) ;
 #endif
 	}
 	OUTPUT:
@@ -2546,10 +2789,14 @@ db_stat(db, flags=0)
 	    softCrash("$db->db_stat for a Queue needs Berkeley DB 3.x or better") ;
 #else /* Berkeley DB 3, or better */
 	    DB_QUEUE_STAT *	stat ;
+#ifdef AT_LEAST_DB_4_3
+	    db->Status = ((db->dbp)->stat)(db->dbp, db->txn, &stat, flags) ;
+#else        
 #ifdef AT_LEAST_DB_3_3
 	    db->Status = ((db->dbp)->stat)(db->dbp, &stat, flags) ;
 #else
 	    db->Status = ((db->dbp)->stat)(db->dbp, &stat, safemalloc, flags) ;
+#endif
 #endif
 	    if (db->Status == 0) {
 	    	RETVAL = (HV*)sv_2mortal((SV*)newHV()) ;
@@ -2592,7 +2839,7 @@ db_close(db,flags=0)
         BerkeleyDB::Common 	db
 	INIT:
 	    ckActive_Database(db->active) ;
-	    CurrentDB = db ;
+	    saveCurrentDB(db) ;
 	CODE:
 	    Trace(("BerkeleyDB::Common::db_close %d\n", db));
 #ifdef STRICT_CLOSE
@@ -2616,7 +2863,7 @@ void
 dab__DESTROY(db)
 	BerkeleyDB::Common	db
 	CODE:
-	  CurrentDB = db ;
+	  saveCurrentDB(db) ;
 	  Trace(("In BerkeleyDB::Common::_DESTROY db %d dirty=%d\n", db, PL_dirty)) ;
 	  destroyDB(db) ;
 	  Trace(("End of BerkeleyDB::Common::DESTROY \n")) ;
@@ -2631,12 +2878,20 @@ _db_cursor(db, flags=0)
 	u_int32_t		flags
         BerkeleyDB::Common 	db
         BerkeleyDB::Cursor 	RETVAL = NULL ;
+	ALIAS: __db_write_cursor = 1
 	INIT:
 	    ckActive_Database(db->active) ;
 	CODE:
 	{
-	  DBC *		cursor ;
-	  CurrentDB = db ;
+	  DBC *	cursor ;
+	  saveCurrentDB(db) ;
+	  if (ix == 1 && db->cds_enabled) {
+#ifdef AT_LEAST_DB_3
+	      flags |= DB_WRITECURSOR;
+#else	      
+	      flags |= DB_RMW;
+#endif	      
+	  }
 	  if ((db->Status = db_cursor(db, db->txn, &cursor, flags)) == 0){
 	      ZMALLOC(RETVAL, BerkeleyDB__Cursor_type) ;
 	      db->open_cursors ++ ;
@@ -2646,6 +2901,7 @@ _db_cursor(db, flags=0)
 	      RETVAL->txn     = db->txn ;
               RETVAL->type    = db->type ;
               RETVAL->recno_or_queue    = db->recno_or_queue ;
+              RETVAL->cds_enabled    = db->cds_enabled ;
               RETVAL->filename    = my_strdup(db->filename) ;
               RETVAL->compare = db->compare ;
               RETVAL->dup_compare = db->dup_compare ;
@@ -2693,7 +2949,7 @@ _db_join(db, cursors, flags=0)
 	  DBC **	cursor_list ;
 	  I32		count = av_len(cursors) + 1 ;
 	  int		i ;
-	  CurrentDB = db ;
+	  saveCurrentDB(db) ;
 	  if (count < 1 )
 	      softCrash("db_join: No cursors in parameter list") ;
 	  cursor_list = (DBC **)safemalloc(sizeof(DBC*) * (count + 1));
@@ -2701,6 +2957,8 @@ _db_join(db, cursors, flags=0)
 	      SV * obj = (SV*) * av_fetch(cursors, i, FALSE) ;
 	      IV tmp = SvIV(getInnerObject(obj)) ;
 	      BerkeleyDB__Cursor cur = INT2PTR(BerkeleyDB__Cursor, tmp);
+	      if (cur->dbp == db->dbp)
+	          softCrash("attempted to do a self-join");
 	      cursor_list[i] = cur->cursor ;
 	  }
 	  cursor_list[i] = NULL ;
@@ -2761,6 +3019,19 @@ ArrayOffset(db)
 	OUTPUT:
 	    RETVAL
 
+
+bool
+cds_enabled(db)
+        BerkeleyDB::Common 	db
+	INIT:
+	    ckActive_Database(db->active) ;
+	CODE:
+	    RETVAL = db->cds_enabled ;
+	OUTPUT:
+	    RETVAL
+
+
+
 int
 type(db)
         BerkeleyDB::Common 	db
@@ -2899,7 +3170,7 @@ db_del(db, key, flags=0)
 	INIT:
 	    Trace(("db_del db[%p] in [%p] txn[%p] key[%.*s] flags[%d]\n", db->dbp, db, db->txn, key.size, key.data, flags)) ;
 	    ckActive_Database(db->active) ;
-	    CurrentDB = db ;
+	    saveCurrentDB(db) ;
 
 
 #ifdef AT_LEAST_DB_3
@@ -2921,7 +3192,7 @@ db_get(db, key, data, flags=0)
 	DBT_OPT		data
 	CODE:
 	  ckActive_Database(db->active) ;
-	  CurrentDB = db ;
+	  saveCurrentDB(db) ;
 	  SetPartial(data,db) ;
 	  Trace(("db_get db[%p] in [%p] txn[%p] key [%.*s] flags[%d]\n", db->dbp, db, db->txn, key.size, key.data, flags)) ;
 	  RETVAL = db_get(db, key, data, flags);
@@ -2946,7 +3217,7 @@ db_pget(db, key, pkey, data, flags=0)
 #else
 	  Trace(("db_pget db [%p] in [%p] txn [%p] flags [%d]\n", db->dbp, db, db->txn, flags)) ;
 	  ckActive_Database(db->active) ;
-	  CurrentDB = db ;
+	  saveCurrentDB(db) ;
 	  SetPartial(data,db) ;
 	  DBT_clear(pkey);
 	  RETVAL = db_pget(db, key, pkey, data, flags);
@@ -2968,7 +3239,7 @@ db_put(db, key, data, flags=0)
 	DBT			data
 	CODE:
 	  ckActive_Database(db->active) ;
-	  CurrentDB = db ;
+	  saveCurrentDB(db) ;
 	  /* SetPartial(data,db) ; */
 	  Trace(("db_put db[%p] in [%p] txn[%p] key[%.*s] data [%.*s] flags[%d]\n", db->dbp, db, db->txn, key.size, key.data, data.size, data.data, flags)) ;
 	  RETVAL = db_put(db, key, data, flags);
@@ -2995,7 +3266,7 @@ db_key_range(db, key, less, equal, greater, flags=0)
           DB_KEY_RANGE range ;
           range.less = range.equal = range.greater = 0.0 ;
 	  ckActive_Database(db->active) ;
-	  CurrentDB = db ;
+	  saveCurrentDB(db) ;
 	  RETVAL = db_key_range(db, key, range, flags);
 	  if (RETVAL == 0) {
 	        less = range.less ;
@@ -3012,13 +3283,13 @@ db_key_range(db, key, less, equal, greater, flags=0)
 
 
 #define db_fd(d, x)	(db->Status = (db->dbp->fd)(db->dbp, &x))
-DualType
+int
 db_fd(db)
 	BerkeleyDB::Common	db
 	INIT:
 	  ckActive_Database(db->active) ;
 	CODE:
-	  CurrentDB = db ;
+	  saveCurrentDB(db) ;
 	  db_fd(db, RETVAL) ;
 	OUTPUT:
 	  RETVAL
@@ -3031,7 +3302,7 @@ db_sync(db, flags=0)
 	BerkeleyDB::Common	db
 	INIT:
 	  ckActive_Database(db->active) ;
-	  CurrentDB = db ;
+	  saveCurrentDB(db) ;
 
 void
 _Txn(db, txn=NULL)
@@ -3064,7 +3335,7 @@ truncate(db, countp, flags=0)
 #ifndef AT_LEAST_DB_3_3
           softCrash("truncate needs Berkeley DB 3.3 or later") ;
 #else
-	  CurrentDB = db ;
+	  saveCurrentDB(db) ;
 	  RETVAL = db_truncate(db, countp, flags);
 #endif
 	OUTPUT:
@@ -3090,7 +3361,7 @@ associate(db, secondary, callback, flags=0)
 #ifndef AT_LEAST_DB_3_3
           softCrash("associate needs Berkeley DB 3.3 or later") ;
 #else
-	  CurrentDB = db ;
+	  saveCurrentDB(db) ;
 	  /* db->associated = newSVsv(callback) ; */
 	  secondary->associated = newSVsv(callback) ;
 	  /* secondary->dbp->app_private = secondary->associated ; */
@@ -3109,7 +3380,7 @@ _c_dup(db, flags=0)
     	BerkeleyDB::Cursor	db
         BerkeleyDB::Cursor 	RETVAL = NULL ;
 	INIT:
-	    CurrentDB = db->parent_db ;
+	    saveCurrentDB(db->parent_db);
 	    ckActive_Database(db->active) ;
 	CODE:
 	{
@@ -3126,6 +3397,7 @@ _c_dup(db, flags=0)
 	      RETVAL->dbp     = db->dbp ;
               RETVAL->type    = db->type ;
               RETVAL->recno_or_queue    = db->recno_or_queue ;
+              RETVAL->cds_enabled    = db->cds_enabled ;
               RETVAL->filename    = my_strdup(db->filename) ;
               RETVAL->compare = db->compare ;
               RETVAL->dup_compare = db->dup_compare ;
@@ -3160,7 +3432,7 @@ DualType
 _c_close(db)
     BerkeleyDB::Cursor	db
 	INIT:
-	  CurrentDB = db->parent_db ;
+	  saveCurrentDB(db->parent_db);
 	  ckActive_Cursor(db->active) ;
 	  hash_delete("BerkeleyDB::Term::Cursor", (char *)db) ;
 	CODE:
@@ -3176,7 +3448,7 @@ void
 _DESTROY(db)
     BerkeleyDB::Cursor	db
 	CODE:
-	  CurrentDB = db->parent_db ;
+	  saveCurrentDB(db->parent_db);
 	  Trace(("In BerkeleyDB::Cursor::_DESTROY db %d dirty=%d active=%d\n", db, PL_dirty, db->active));
 	  hash_delete("BerkeleyDB::Term::Cursor", (char *)db) ;
 	  if (db->active)
@@ -3202,7 +3474,7 @@ cu_c_del(db, flags=0)
     int			flags
     BerkeleyDB::Cursor	db
 	INIT:
-	  CurrentDB = db->parent_db ;
+	  saveCurrentDB(db->parent_db);
 	  ckActive_Cursor(db->active) ;
 	OUTPUT:
 	  RETVAL
@@ -3213,12 +3485,14 @@ DualType
 cu_c_get(db, key, data, flags=0)
     int			flags
     BerkeleyDB::Cursor	db
-    DBTKEY_B		key
-    DBT_B		data
+    DBTKEY_B		key 
+    DBT_B		data 
 	INIT:
 	  Trace(("c_get db [%p] in [%p] flags [%d]\n", db->dbp, db, flags)) ;
-	  CurrentDB = db->parent_db ;
+	  saveCurrentDB(db->parent_db);
 	  ckActive_Cursor(db->active) ;
+	  /* DBT_clear(key); */
+	  /* DBT_clear(data); */
 	  SetPartial(data,db) ;
 	  Trace(("c_get end\n")) ;
 	OUTPUT:
@@ -3239,7 +3513,7 @@ cu_c_pget(db, key, pkey, data, flags=0)
           softCrash("db_c_pget needs at least Berkeley DB 3.3");
 #else
 	  Trace(("c_pget db [%d] flags [%d]\n", db, flags)) ;
-	  CurrentDB = db->parent_db ;
+	  saveCurrentDB(db->parent_db);
 	  ckActive_Cursor(db->active) ;
 	  SetPartial(data,db) ;
 	  DBT_clear(pkey);
@@ -3250,7 +3524,7 @@ cu_c_pget(db, key, pkey, data, flags=0)
 	  RETVAL
 	  key
 	  pkey
-	  data		if (! flagSet(DB_JOIN_ITEM)) OutputValue_B(ST(2), data) ;
+	  data		
 
 
 
@@ -3262,7 +3536,7 @@ cu_c_put(db, key, data, flags=0)
     DBTKEY		key
     DBT			data
 	INIT:
-	  CurrentDB = db->parent_db ;
+	  saveCurrentDB(db->parent_db);
 	  ckActive_Cursor(db->active) ;
 	  /* SetPartial(data,db) ; */
 	OUTPUT:
@@ -3279,7 +3553,7 @@ cu_c_count(db, count, flags=0)
           softCrash("c_count needs at least Berkeley DB 3.1.x");
 #else
 	  Trace(("c_get count [%d] flags [%d]\n", db, flags)) ;
-	  CurrentDB = db->parent_db ;
+	  saveCurrentDB(db->parent_db);
 	  ckActive_Cursor(db->active) ;
 	  RETVAL = cu_c_count(db, count, flags) ;
 	  Trace(("    c_count got %d duplicates\n", count)) ;
@@ -3549,7 +3823,7 @@ FIRSTKEY(db)
 		restore at the end.
 
 	     */
-            CurrentDB = db ;
+            saveCurrentDB(db) ;
 	    DBT_clear(key) ;
 	    DBT_clear(value) ;
 	    /* If necessary create a cursor for FIRSTKEY/NEXTKEY use */
@@ -3581,7 +3855,7 @@ NEXTKEY(db, key)
         {
             DBT         value ;
 
-            CurrentDB = db ;
+            saveCurrentDB(db) ;
 	    DBT_clear(key) ;
 	    DBT_clear(value) ;
 	    key.flags = 0 ;
@@ -3603,7 +3877,7 @@ I32
 FETCHSIZE(db)
         BerkeleyDB::Common         db
         CODE:
-            CurrentDB = db ;
+            saveCurrentDB(db) ;
             RETVAL = GetArrayLength(db) ;
         OUTPUT:
             RETVAL
diff --git a/storage/bdb/perl/BerkeleyDB/Changes b/storage/bdb/perl/BerkeleyDB/Changes
index cbeb1a34d73e64a6e44a6219ea5723e515031f81..8f3718a7f2be00f268e51a2fc1032a862eb8438a 100644
--- a/storage/bdb/perl/BerkeleyDB/Changes
+++ b/storage/bdb/perl/BerkeleyDB/Changes
@@ -1,5 +1,87 @@
 Revision history for Perl extension BerkeleyDB.
 
+0.26  10th October 2004
+
+        * Changed to allow Building with Berkeley DB 4.3
+
+        * added cds_lock and associated methods as a convenience to allow
+          safe updaing of database records when using Berkeley DB CDS mode.
+
+        * added t/cds.t and t/pod.t
+
+        * Modified the test suite to use "-ErrFile => *STDOUT" where 
+          possible. This will make it easier to diagnose build issues.
+
+	* -Errfile will now accept a filehandle as well as a filename
+          This means that -ErrFile => *STDOUT will get all extended error
+          messages displayed directly on screen.
+
+	* Added support for set_shm_key & get_shm_key.
+
+	* Patch from Mark Jason Dominus to add a better error message
+	  when an odd number of parameters are passed to ParseParameters.
+
+	* fixed off-by-one error in my_strdup
+
+	* Fixed a problem with push, pop, shift & unshift with Queue &
+	  Recno when used in CDS mode. These methods were not using
+	  a write cursor behind the scenes. 
+	  Problem reported by Pavel Hlavnicka.
+
+0.25  1st November 2003
+
+	* Minor update to dbinfo
+
+	* Fixed a bug in the test harnesses that is only apparent in
+	  perl 5.8.2.  Original patch courtesy of Michael Schwern.
+
+0.24 27th September 2003
+
+        * Mentioned comp.databases.berkeley-db in README
+
+        * Builds with Berkeley DB 4.2
+
+        * The return type for db->db_fd was wrongly set at DualType -
+          should be int.
+
+0.23 15th June 2003
+
+        * Fixed problem where a secondary index would use the same
+          compare callback as the primary key, regardless of what was
+          defined for the secondary index. 
+	  Problem spotted by Dave Tallman.
+
+        * Also fixed a problem with the associate callback. If the value
+          for the secondary key was not a string, the secondary key was
+          being set incorrectly. This is now fixed.
+
+        * When built with Berkeley DB 3.2 or better, all callbacks now use
+          the BackRef pointer instead of the global CurrentDB. This was
+          done partially to fix the secondary index problem, above.
+
+        * The test harness was failing under cygwin. Now fixed. 
+
+        * Previous release broke TRACE. Fixed.
+
+0.22 17th May 2003
+
+        * win32 problem with open macro fixed.
+
+0.21 12th May 2003
+
+        * adding support for env->set_flags 
+	* adding recursion detection
+	* win32 problem with rename fixed.
+	* problem with sub-database name in Recno & Queue fixed.
+	* fixed the mldbm.t test harness to work with perl 5.8.0
+	* added a note about not using a network drive when running the
+	  test harness.
+	* fixed c_pget
+	* added BerkeleyDB::Env::DB_ENV method
+	* added support for encryption
+	* the dbinfo script will now indicate if the database is encrypted
+	* The CLEAR method is now CDB safe.
+
 0.20 2nd September 2002
 
         * More support for building with Berkeley DB 4.1.x
diff --git a/storage/bdb/perl/BerkeleyDB/MANIFEST b/storage/bdb/perl/BerkeleyDB/MANIFEST
index 7da51ef7d7cfde68dda4553d93042738d5de5ed1..7c090a175842a7ef32beafdd354670ae3d3d402e 100644
--- a/storage/bdb/perl/BerkeleyDB/MANIFEST
+++ b/storage/bdb/perl/BerkeleyDB/MANIFEST
@@ -19,11 +19,13 @@ mkpod
 ppport.h
 README
 t/btree.t
+t/cds.t
 t/db-3.0.t
 t/db-3.1.t
 t/db-3.2.t
 t/db-3.3.t
 t/destroy.t
+t/encrypt.t
 t/env.t
 t/examples.t
 t/examples.t.T
@@ -33,6 +35,7 @@ t/filter.t
 t/hash.t
 t/join.t
 t/mldbm.t
+t/pod.t
 t/queue.t
 t/recno.t
 t/strict.t
@@ -54,3 +57,4 @@ patches/5.005_02
 patches/5.005_03
 patches/5.6.0
 scan
+META.yml                                 Module meta-data (added by MakeMaker)
diff --git a/storage/bdb/perl/BerkeleyDB/META.yml b/storage/bdb/perl/BerkeleyDB/META.yml
new file mode 100644
index 0000000000000000000000000000000000000000..3b205c9ce4e13dfd2ea8f89cb4dda8e9a05195c5
--- /dev/null
+++ b/storage/bdb/perl/BerkeleyDB/META.yml
@@ -0,0 +1,10 @@
+# http://module-build.sourceforge.net/META-spec.html
+#XXXXXXX This is a prototype!!!  It will change in the future!!! XXXXX#
+name:         BerkeleyDB
+version:      0.25
+version_from: BerkeleyDB.pm
+installdirs:  site
+requires:
+
+distribution_type: module
+generated_by: ExtUtils::MakeMaker version 6.17
diff --git a/storage/bdb/perl/BerkeleyDB/Makefile.PL b/storage/bdb/perl/BerkeleyDB/Makefile.PL
index 86da9a845af3645af18c03795c1075bf50e06183..0c926a394ba4e9139409cc3b8de09359268c0d81 100644
--- a/storage/bdb/perl/BerkeleyDB/Makefile.PL
+++ b/storage/bdb/perl/BerkeleyDB/Makefile.PL
@@ -27,11 +27,16 @@ my $LIBS ;
 
 ParseCONFIG() ;
 
-if (defined $DB_NAME) 
+if (defined $DB_NAME)
   { $LIBS = $DB_NAME }
-else { 
+else {
     if ($^O eq 'MSWin32')
       { $LIBS = '-llibdb' }
+    elsif ($^O =~ /aix/i )  {
+      $LIBS .= '-ldb -lpthread ';
+      if ($Config{'cc'} eq 'gcc' && $Config{'osvers'} eq '5.1')
+        { $LIBS .= '-lgcc_s' }
+    }
     else
       { $LIBS = '-ldb' }
 }
@@ -40,6 +45,10 @@ else {
 my $OS2 = "" ;
 $OS2 = "-DOS2" if $^O eq 'os2' ;
 
+my $WALL = '';
+#$WALL = ' -Wall ' if $Config{'cc'} =~ /gcc/ ;
+
+
 WriteMakefile(
 	NAME 		=> 'BerkeleyDB',
 	LIBS 		=> ["-L${LIB_DIR} $LIBS"],
@@ -47,12 +56,12 @@ WriteMakefile(
 	INC		=> "-I$INC_DIR",
 	VERSION_FROM	=> 'BerkeleyDB.pm',
 	XSPROTOARG	=> '-noprototypes',
-	DEFINE		=> "$OS2",
+	DEFINE		=> "$OS2 $WALL",
 	#'macro'		=> { INSTALLDIRS => 'perl' },
         'dist'          => {COMPRESS=>'gzip', SUFFIX=>'gz'},    
 	($] >= 5.005
 	    ? (ABSTRACT_FROM	=> 'BerkeleyDB.pod',
-	       AUTHOR  	=> 'Paul Marquess <Paul.Marquess@btinternet.com>')
+	       AUTHOR  	=> 'Paul Marquess <pmqs@cpan.org>')
 	    : ()
 	),
 	);
@@ -115,7 +124,9 @@ sub ParseCONFIG
 
     $INC_DIR =  $ENV{'BERKELEYDB_INCLUDE'} || $Info{'INCLUDE'} ;
     $LIB_DIR =  $ENV{'BERKELEYDB_LIB'} || $Info{'LIB'} ;
-    $DB_NAME = $Info{'DBNAME'} if defined $Info{'DBNAME'} ;
+    $DB_NAME = $ENV{BERKELEYDB_NAME} || $Info{'DBNAME'} ;
+    #$DB_NAME =  $ENV{} || $Info{'DBNAME'} if defined $Info{'DBNAME'} ;
+
     print "Looks Good.\n" ;
 
 }
diff --git a/storage/bdb/perl/BerkeleyDB/README b/storage/bdb/perl/BerkeleyDB/README
index a600e3131934848c9314377dbf93c1f98974a8c1..3c08d2c822e3592b4d69dcf4208606952b9b8e3d 100644
--- a/storage/bdb/perl/BerkeleyDB/README
+++ b/storage/bdb/perl/BerkeleyDB/README
@@ -1,10 +1,10 @@
                                    BerkeleyDB
 
-                                  Version 0.20
+                                  Version 0.26
 
-                                  2nd Sept 2002
+                                 10th Oct 2004
 
-	Copyright (c) 1997-2002 Paul Marquess. All rights reserved. This
+	Copyright (c) 1997-2004 Paul Marquess. All rights reserved. This
 	program is free software; you can redistribute it and/or modify
 	it under the same terms as Perl itself.
 
@@ -30,6 +30,10 @@ PREREQUISITES
 Before you can build BerkeleyDB you need to have the following
 installed on your system:
 
+    * To run the test harness for this module, you must make sure that the
+      directory where you have untarred this module is NOT a network
+      drive, e.g. NFS or AFS.
+
     * Perl 5.004_04 or greater.
 
     * Berkeley DB Version 2.6.4 or greater
@@ -57,7 +61,6 @@ Step 1 : If you are running Solaris 2.5, 2.7 or HP-UX 10 read either
 	 If you are running Linux please read the Linux Notes section
          before proceeding.
 
-
 Step 2 : Edit the file config.in to suit you local installation.
          Instructions are given in the file.
 
@@ -279,10 +282,147 @@ Solution: Setting the LIB & INCLUDE variables in config.in to point to the
 	  If you are running Linux, please read the Linux Notes section below.
 
 
+
+Solaris build fails with "language optional software package not installed"
+---------------------------------------------------------------------------
+
+If you are trying to build this module under Solaris and you get an
+error message like this
+
+    /usr/ucb/cc: language optional software package not installed
+
+it means that Perl cannot find the C compiler on your system. The cryptic
+message is just Sun's way of telling you that you haven't bought their
+C compiler.
+
+When you build a Perl module that needs a C compiler, the Perl build
+system tries to use the same C compiler that was used to build perl
+itself. In this case your Perl binary was built with a C compiler that
+lived in /usr/ucb.
+
+To continue with building this module, you need to get a C compiler,
+or tell Perl where your C compiler is, if you already have one.
+
+Assuming you have now got a C compiler, what you do next will be dependant
+on what C compiler you have installed. If you have just installed Sun's
+C compiler, you shouldn't have to do anything. Just try rebuilding
+this module.
+
+If you have installed another C compiler, say gcc, you have to tell perl
+how to use it instead of /usr/ucb/cc.
+
+This set of options seems to work if you want to use gcc. Your mileage
+may vary.
+
+    perl Makefile.PL CC=gcc CCCDLFLAGS=-fPIC OPTIMIZE=" "
+    make test
+
+If that doesn't work for you, it's time to make changes to the Makefile
+by hand. Good luck!
+
+
+
+Solaris build fails with "gcc: unrecognized option `-KPIC'"
+-----------------------------------------------------------
+
+You are running Solaris and you get an error like this when you try to
+build this Perl module
+
+    gcc: unrecognized option `-KPIC'
+
+This symptom usually means that you are using a Perl binary that has been
+built with the Sun C compiler, but you are using gcc to build this module.
+
+When Perl builds modules that need a C compiler, it will attempt to use
+the same C compiler and command line options that was used to build perl
+itself. In this case "-KPIC" is a valid option for the Sun C compiler,
+but not for gcc. The equivalent option for gcc is "-fPIC".
+
+The solution is either:
+
+    1. Build both Perl and this module with the same C compiler, either
+       by using the Sun C compiler for both or gcc for both.
+
+    2. Try generating the Makefile for this module like this perl
+
+           perl Makefile.PL CC=gcc CCCDLFLAGS=-fPIC OPTIMIZE=" " LD=gcc
+           make test
+
+       This second option seems to work when mixing a Perl binary built
+       with the Sun C compiler and this module built with gcc. Your
+       mileage may vary.
+
+
+
+Network Drive
+-------------
+
+BerkeleyDB seems to have built correctly, but you get a series of errors
+like this when you run the test harness:
+
+
+t/btree........NOK 178Can't call method "txn_begin" on an undefined value at t/btree.t line 637.
+t/btree........dubious                                                       
+        Test returned status 11 (wstat 2816, 0xb00)
+DIED. FAILED tests 28, 178-244
+        Failed 68/244 tests, 72.13% okay
+t/db-3.0.......NOK 2Can't call method "set_mutexlocks" on an undefined value at t/db-3.0.t line 39.
+t/db-3.0.......dubious                                                       
+        Test returned status 11 (wstat 2816, 0xb00)
+DIED. FAILED tests 2-14
+        Failed 13/14 tests, 7.14% okay
+t/db-3.1.......ok                                                            
+t/db-3.2.......NOK 5Can't call method "set_flags" on an undefined value at t/db-3.2.t line 62.
+t/db-3.2.......dubious                                                       
+        Test returned status 11 (wstat 2816, 0xb00)
+DIED. FAILED tests 3, 5-6
+        Failed 3/6 tests, 50.00% okay
+t/db-3.3.......ok                  
+
+This pattern of errors happens if you have built the module in a directory
+that is network mounted (e.g. NFS ar AFS).
+
+The solution is to use a local drive. Berkeley DB doesn't support
+network drives.
+
+
+Berkeley DB library configured to support only DB_PRIVATE environments
+----------------------------------------------------------------------
+
+BerkeleyDB seems to have built correctly, but you get a series of errors
+like this when you run the test harness:
+
+  t/btree........ok 27/244
+  # : Berkeley DB library configured to support only DB_PRIVATE environments
+  t/btree........ok 177/244
+  # : Berkeley DB library configured to support only DB_PRIVATE environments
+  t/btree........NOK 178Can't call method "txn_begin" on an undefined value at t/btree.t line 638.
+  t/btree........dubious
+          Test returned status 2 (wstat 512, 0x200)
+  Scalar found where operator expected at (eval 153) line 1, near "'int'  $__val"
+        (Missing operator before   $__val?)
+  DIED. FAILED tests 28, 178-244
+          Failed 68/244 tests, 72.13% okay
+
+
+Some versions of Redhat Linux, and possibly some other Linux
+distributions, include a seriously restricted build of the
+Berkeley DB library that is incompatible with this module. See
+https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=91933 for an
+exhaustive discussion on the reasons for this.
+
+
+Solution:
+
+You will have to build a private copy of the Berkeley DB library and
+use it when building this Perl module.
+
+
+
 Linux Notes
 -----------
 
-Newer versions of Linux (e.g. RedHat 6, SuSe 6) ship with a C library
+Some versions of Linux (e.g. RedHat 6, SuSe 6) ship with a C library
 that has version 2.x of Berkeley DB linked into it. This makes it
 difficult to build this module with anything other than the version of
 Berkeley DB that shipped with your Linux release. If you do try to use
@@ -386,6 +526,7 @@ Sun patch 103187-25 (or later revisions) fixes this problem.
 To find out if you have the patch installed, the command "showrev -p"
 will display the patches that are currently installed on your system.
 
+
 Solaris 2.7 Notes
 -----------------
 
@@ -426,7 +567,14 @@ following steps should do the trick:
 FEEDBACK
 --------
 
+General feedback/questions/bug reports can be sent to me at pmqs@cpan.org.
+
+Alternatively, if you have Usenet access, you can try the
+comp.databases.berkeley-db or comp.lang.perl.modules groups.
+
+
 How to report a problem with BerkeleyDB.
+----------------------------------------
 
 To help me help you, I need of the following information:
 
@@ -441,6 +589,10 @@ To help me help you, I need of the following information:
 
        perl -MBerkeleyDB -e 'print qq{BerkeleyDB ver $BerkeleyDB::VERSION\n}'
 
+    If you are running windows use this
+
+       perl -MBerkeleyDB -e "print qq{BerkeleyDB ver $BerkeleyDB::VERSION\n}"
+
     If you haven't installed BerkeleyDB then search BerkeleyDB.pm for a
     line like this:
 
@@ -451,6 +603,10 @@ To help me help you, I need of the following information:
 
         perl -MBerkeleyDB -e 'print BerkeleyDB::DB_VERSION_STRING.qq{\n}'
 
+    If you are running windows use this
+
+        perl -MBerkeleyDB -e "print BerkeleyDB::DB_VERSION_STRING.qq{\n}"
+
     If you haven't installed BerkeleyDB then search db.h for a line
     like this:
 
@@ -480,5 +636,5 @@ CHANGES
 
 See the Changes file.
 
-Paul Marquess <Paul.Marquess@btinternet.com>
+Paul Marquess <pmqs@cpan.org>
 
diff --git a/storage/bdb/perl/BerkeleyDB/config.in b/storage/bdb/perl/BerkeleyDB/config.in
index fd1bb1caede4aa42b2bb1e7a08313e7d339be737..3c37ea937a93a0a9c81e66a3e2a439fc6a27b685 100644
--- a/storage/bdb/perl/BerkeleyDB/config.in
+++ b/storage/bdb/perl/BerkeleyDB/config.in
@@ -7,16 +7,18 @@
 #    Change the path below to point to the directory where db.h is
 #    installed on your system.
 
-INCLUDE	= /usr/local/include
-#INCLUDE	= /usr/local/BerkeleyDB/include
+#INCLUDE	= /usr/local/include
+#INCLUDE	= ../..
+INCLUDE	= /usr/local/BerkeleyDB/include
 
 # 2. Where is libdb?
 #
 #    Change the path below to point to the directory where libdb is
 #    installed on your system.
 
-LIB	= /usr/local/lib
-#LIB	= /usr/local/BerkeleyDB/lib
+#LIB	= /usr/local/lib
+#LIB	= ../..
+LIB	= /usr/local/BerkeleyDB/lib
 
 # 3. Is the library called libdb?
 #
diff --git a/storage/bdb/perl/BerkeleyDB/constants.h b/storage/bdb/perl/BerkeleyDB/constants.h
index d86cef1551307710243816e4f5b855aae3194276..98dc5eb162185923518261e5b3b47a48e3c61569 100644
--- a/storage/bdb/perl/BerkeleyDB/constants.h
+++ b/storage/bdb/perl/BerkeleyDB/constants.h
@@ -99,7 +99,7 @@ constant_7 (pTHX_ const char *name, IV *iv_return) {
 #if (DB_VERSION_MAJOR > 2) || \
     (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \
     (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \
-     DB_VERSION_PATCH >= 0)
+     DB_VERSION_PATCH >= 3)
       *iv_return = DB_HASH;
       return PERL_constant_ISIV;
 #else
@@ -148,7 +148,7 @@ static int
 constant_8 (pTHX_ const char *name, IV *iv_return) {
   /* When generated this function returned values for the list of names given
      here.  However, subsequent manual editing may have added or removed some.
-     DB_AFTER DB_BTREE DB_FIRST DB_FLUSH DB_FORCE DB_QUEUE DB_RECNO */
+     DB_AFTER DB_BTREE DB_FIRST DB_FLUSH DB_FORCE DB_QUEUE DB_RECNO DB_UNREF */
   /* Offset 4 gives the best switch position.  */
   switch (name[4]) {
   case 'E':
@@ -157,7 +157,7 @@ constant_8 (pTHX_ const char *name, IV *iv_return) {
 #if (DB_VERSION_MAJOR > 2) || \
     (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \
     (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \
-     DB_VERSION_PATCH >= 0)
+     DB_VERSION_PATCH >= 3)
       *iv_return = DB_RECNO;
       return PERL_constant_ISIV;
 #else
@@ -195,6 +195,17 @@ constant_8 (pTHX_ const char *name, IV *iv_return) {
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 'N':
+    if (memEQ(name, "DB_UNREF", 8)) {
+    /*                   ^         */
+#ifdef DB_UNREF
+      *iv_return = DB_UNREF;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
 #endif
     }
     break;
@@ -215,7 +226,7 @@ constant_8 (pTHX_ const char *name, IV *iv_return) {
 #if (DB_VERSION_MAJOR > 2) || \
     (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \
     (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \
-     DB_VERSION_PATCH >= 0)
+     DB_VERSION_PATCH >= 3)
       *iv_return = DB_BTREE;
       return PERL_constant_ISIV;
 #else
@@ -245,9 +256,9 @@ static int
 constant_9 (pTHX_ const char *name, IV *iv_return) {
   /* When generated this function returned values for the list of names given
      here.  However, subsequent manual editing may have added or removed some.
-     DB_APPEND DB_BEFORE DB_CLIENT DB_COMMIT DB_CREATE DB_CURLSN DB_DIRECT
-     DB_EXTENT DB_GETREC DB_NOCOPY DB_NOMMAP DB_NOSYNC DB_RDONLY DB_RECNUM
-     DB_THREAD DB_VERIFY */
+     DB_APPEND DB_BEFORE DB_CHKSUM DB_CLIENT DB_COMMIT DB_CREATE DB_CURLSN
+     DB_DIRECT DB_EXTENT DB_GETREC DB_NOCOPY DB_NOMMAP DB_NOSYNC DB_RDONLY
+     DB_RECNUM DB_THREAD DB_VERIFY */
   /* Offset 7 gives the best switch position.  */
   switch (name[7]) {
   case 'A':
@@ -408,6 +419,15 @@ constant_9 (pTHX_ const char *name, IV *iv_return) {
     }
     break;
   case 'U':
+    if (memEQ(name, "DB_CHKSUM", 9)) {
+    /*                      ^       */
+#ifdef DB_CHKSUM
+      *iv_return = DB_CHKSUM;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
     if (memEQ(name, "DB_RECNUM", 9)) {
     /*                      ^       */
 #ifdef DB_RECNUM
@@ -427,23 +447,34 @@ constant_10 (pTHX_ const char *name, IV *iv_return) {
   /* When generated this function returned values for the list of names given
      here.  However, subsequent manual editing may have added or removed some.
      DB_CONSUME DB_CURRENT DB_DELETED DB_DUPSORT DB_ENCRYPT DB_ENV_CDB
-     DB_ENV_TXN DB_JOINENV DB_KEYLAST DB_NOPANIC DB_OK_HASH DB_PRIVATE
-     DB_PR_PAGE DB_RECOVER DB_SALVAGE DB_TIMEOUT DB_TXN_CKP DB_UNKNOWN
-     DB_UPGRADE */
-  /* Offset 8 gives the best switch position.  */
-  switch (name[8]) {
-  case 'D':
-    if (memEQ(name, "DB_ENV_CDB", 10)) {
-    /*                       ^        */
-#ifdef DB_ENV_CDB
-      *iv_return = DB_ENV_CDB;
+     DB_ENV_TXN DB_INORDER DB_JOINENV DB_KEYLAST DB_NOPANIC DB_OK_HASH
+     DB_PRIVATE DB_PR_PAGE DB_RECOVER DB_SALVAGE DB_SEQ_DEC DB_SEQ_INC
+     DB_TIMEOUT DB_TXN_CKP DB_UNKNOWN DB_UPGRADE */
+  /* Offset 5 gives the best switch position.  */
+  switch (name[5]) {
+  case 'C':
+    if (memEQ(name, "DB_ENCRYPT", 10)) {
+    /*                    ^           */
+#ifdef DB_ENCRYPT
+      *iv_return = DB_ENCRYPT;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_RECOVER", 10)) {
+    /*                    ^           */
+#ifdef DB_RECOVER
+      *iv_return = DB_RECOVER;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
+    break;
+  case 'G':
     if (memEQ(name, "DB_UPGRADE", 10)) {
-    /*                       ^        */
+    /*                    ^           */
 #ifdef DB_UPGRADE
       *iv_return = DB_UPGRADE;
       return PERL_constant_ISIV;
@@ -452,38 +483,52 @@ constant_10 (pTHX_ const char *name, IV *iv_return) {
 #endif
     }
     break;
-  case 'E':
-    if (memEQ(name, "DB_DELETED", 10)) {
-    /*                       ^        */
-#ifdef DB_DELETED
-      *iv_return = DB_DELETED;
+  case 'I':
+    if (memEQ(name, "DB_JOINENV", 10)) {
+    /*                    ^           */
+#ifdef DB_JOINENV
+      *iv_return = DB_JOINENV;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_RECOVER", 10)) {
-    /*                       ^        */
-#ifdef DB_RECOVER
-      *iv_return = DB_RECOVER;
+    if (memEQ(name, "DB_PRIVATE", 10)) {
+    /*                    ^           */
+#ifdef DB_PRIVATE
+      *iv_return = DB_PRIVATE;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
     break;
-  case 'G':
-    if (memEQ(name, "DB_PR_PAGE", 10)) {
-    /*                       ^        */
-#ifdef DB_PR_PAGE
-      *iv_return = DB_PR_PAGE;
+  case 'K':
+    if (memEQ(name, "DB_UNKNOWN", 10)) {
+    /*                    ^           */
+#if (DB_VERSION_MAJOR > 2) || \
+    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \
+    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \
+     DB_VERSION_PATCH >= 3)
+      *iv_return = DB_UNKNOWN;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 'L':
+    if (memEQ(name, "DB_DELETED", 10)) {
+    /*                    ^           */
+#ifdef DB_DELETED
+      *iv_return = DB_DELETED;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
     if (memEQ(name, "DB_SALVAGE", 10)) {
-    /*                       ^        */
+    /*                    ^           */
 #ifdef DB_SALVAGE
       *iv_return = DB_SALVAGE;
       return PERL_constant_ISIV;
@@ -492,20 +537,29 @@ constant_10 (pTHX_ const char *name, IV *iv_return) {
 #endif
     }
     break;
-  case 'I':
-    if (memEQ(name, "DB_NOPANIC", 10)) {
-    /*                       ^        */
-#ifdef DB_NOPANIC
-      *iv_return = DB_NOPANIC;
+  case 'M':
+    if (memEQ(name, "DB_TIMEOUT", 10)) {
+    /*                    ^           */
+#ifdef DB_TIMEOUT
+      *iv_return = DB_TIMEOUT;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
     break;
-  case 'K':
+  case 'N':
+    if (memEQ(name, "DB_CONSUME", 10)) {
+    /*                    ^           */
+#ifdef DB_CONSUME
+      *iv_return = DB_CONSUME;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
     if (memEQ(name, "DB_TXN_CKP", 10)) {
-    /*                       ^        */
+    /*                    ^           */
 #ifdef DB_TXN_CKP
       *iv_return = DB_TXN_CKP;
       return PERL_constant_ISIV;
@@ -514,120 +568,113 @@ constant_10 (pTHX_ const char *name, IV *iv_return) {
 #endif
     }
     break;
-  case 'M':
-    if (memEQ(name, "DB_CONSUME", 10)) {
-    /*                       ^        */
-#ifdef DB_CONSUME
-      *iv_return = DB_CONSUME;
+  case 'O':
+    if (memEQ(name, "DB_INORDER", 10)) {
+    /*                    ^           */
+#ifdef DB_INORDER
+      *iv_return = DB_INORDER;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
     break;
-  case 'N':
-    if (memEQ(name, "DB_CURRENT", 10)) {
-    /*                       ^        */
-#ifdef DB_CURRENT
-      *iv_return = DB_CURRENT;
+  case 'P':
+    if (memEQ(name, "DB_DUPSORT", 10)) {
+    /*                    ^           */
+#ifdef DB_DUPSORT
+      *iv_return = DB_DUPSORT;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_JOINENV", 10)) {
-    /*                       ^        */
-#ifdef DB_JOINENV
-      *iv_return = DB_JOINENV;
+    if (memEQ(name, "DB_NOPANIC", 10)) {
+    /*                    ^           */
+#ifdef DB_NOPANIC
+      *iv_return = DB_NOPANIC;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
     break;
-  case 'P':
-    if (memEQ(name, "DB_ENCRYPT", 10)) {
-    /*                       ^        */
-#ifdef DB_ENCRYPT
-      *iv_return = DB_ENCRYPT;
+  case 'Q':
+    if (memEQ(name, "DB_SEQ_DEC", 10)) {
+    /*                    ^           */
+#ifdef DB_SEQ_DEC
+      *iv_return = DB_SEQ_DEC;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    break;
-  case 'R':
-    if (memEQ(name, "DB_DUPSORT", 10)) {
-    /*                       ^        */
-#ifdef DB_DUPSORT
-      *iv_return = DB_DUPSORT;
+    if (memEQ(name, "DB_SEQ_INC", 10)) {
+    /*                    ^           */
+#ifdef DB_SEQ_INC
+      *iv_return = DB_SEQ_INC;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
     break;
-  case 'S':
-    if (memEQ(name, "DB_KEYLAST", 10)) {
-    /*                       ^        */
-#ifdef DB_KEYLAST
-      *iv_return = DB_KEYLAST;
+  case 'R':
+    if (memEQ(name, "DB_CURRENT", 10)) {
+    /*                    ^           */
+#ifdef DB_CURRENT
+      *iv_return = DB_CURRENT;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_OK_HASH", 10)) {
-    /*                       ^        */
-#ifdef DB_OK_HASH
-      *iv_return = DB_OK_HASH;
+    break;
+  case 'V':
+    if (memEQ(name, "DB_ENV_CDB", 10)) {
+    /*                    ^           */
+#ifdef DB_ENV_CDB
+      *iv_return = DB_ENV_CDB;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    break;
-  case 'T':
-    if (memEQ(name, "DB_PRIVATE", 10)) {
-    /*                       ^        */
-#ifdef DB_PRIVATE
-      *iv_return = DB_PRIVATE;
+    if (memEQ(name, "DB_ENV_TXN", 10)) {
+    /*                    ^           */
+#ifdef DB_ENV_TXN
+      *iv_return = DB_ENV_TXN;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
     break;
-  case 'U':
-    if (memEQ(name, "DB_TIMEOUT", 10)) {
-    /*                       ^        */
-#ifdef DB_TIMEOUT
-      *iv_return = DB_TIMEOUT;
+  case 'Y':
+    if (memEQ(name, "DB_KEYLAST", 10)) {
+    /*                    ^           */
+#ifdef DB_KEYLAST
+      *iv_return = DB_KEYLAST;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
     break;
-  case 'W':
-    if (memEQ(name, "DB_UNKNOWN", 10)) {
-    /*                       ^        */
-#if (DB_VERSION_MAJOR > 2) || \
-    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \
-    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \
-     DB_VERSION_PATCH >= 0)
-      *iv_return = DB_UNKNOWN;
+  case '_':
+    if (memEQ(name, "DB_OK_HASH", 10)) {
+    /*                    ^           */
+#ifdef DB_OK_HASH
+      *iv_return = DB_OK_HASH;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    break;
-  case 'X':
-    if (memEQ(name, "DB_ENV_TXN", 10)) {
-    /*                       ^        */
-#ifdef DB_ENV_TXN
-      *iv_return = DB_ENV_TXN;
+    if (memEQ(name, "DB_PR_PAGE", 10)) {
+    /*                    ^           */
+#ifdef DB_PR_PAGE
+      *iv_return = DB_PR_PAGE;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
@@ -642,11 +689,12 @@ static int
 constant_11 (pTHX_ const char *name, IV *iv_return) {
   /* When generated this function returned values for the list of names given
      here.  However, subsequent manual editing may have added or removed some.
-     DB_APP_INIT DB_ARCH_ABS DB_ARCH_LOG DB_FIXEDLEN DB_GET_BOTH DB_INIT_CDB
-     DB_INIT_LOG DB_INIT_TXN DB_KEYEMPTY DB_KEYEXIST DB_KEYFIRST DB_LOCKDOWN
-     DB_LOCK_GET DB_LOCK_PUT DB_LOGMAGIC DB_LOG_DISK DB_MULTIPLE DB_NEXT_DUP
-     DB_NOSERVER DB_NOTFOUND DB_OK_BTREE DB_OK_QUEUE DB_OK_RECNO DB_POSITION
-     DB_QAMMAGIC DB_RENUMBER DB_SNAPSHOT DB_TRUNCATE DB_TXNMAGIC DB_TXN_LOCK
+     DB_APP_INIT DB_ARCH_ABS DB_ARCH_LOG DB_DEGREE_2 DB_FILEOPEN DB_FIXEDLEN
+     DB_GET_BOTH DB_INIT_CDB DB_INIT_LOG DB_INIT_REP DB_INIT_TXN DB_KEYEMPTY
+     DB_KEYEXIST DB_KEYFIRST DB_LOCKDOWN DB_LOCK_GET DB_LOCK_PUT DB_LOGMAGIC
+     DB_LOG_DISK DB_LOG_PERM DB_MULTIPLE DB_NEXT_DUP DB_NOSERVER DB_NOTFOUND
+     DB_OK_BTREE DB_OK_QUEUE DB_OK_RECNO DB_POSITION DB_QAMMAGIC DB_RENUMBER
+     DB_SEQ_WRAP DB_SNAPSHOT DB_STAT_ALL DB_TRUNCATE DB_TXNMAGIC DB_TXN_LOCK
      DB_TXN_REDO DB_TXN_SYNC DB_TXN_UNDO DB_WRNOSYNC DB_YIELDCPU */
   /* Offset 8 gives the best switch position.  */
   switch (name[8]) {
@@ -658,6 +706,15 @@ constant_11 (pTHX_ const char *name, IV *iv_return) {
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_STAT_ALL", 11)) {
+    /*                       ^         */
+#ifdef DB_STAT_ALL
+      *iv_return = DB_STAT_ALL;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
 #endif
     }
     if (memEQ(name, "DB_TRUNCATE", 11)) {
@@ -722,6 +779,24 @@ constant_11 (pTHX_ const char *name, IV *iv_return) {
     }
     break;
   case 'E':
+    if (memEQ(name, "DB_DEGREE_2", 11)) {
+    /*                       ^         */
+#ifdef DB_DEGREE_2
+      *iv_return = DB_DEGREE_2;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_LOG_PERM", 11)) {
+    /*                       ^         */
+#ifdef DB_LOG_PERM
+      *iv_return = DB_LOG_PERM;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
     if (memEQ(name, "DB_OK_QUEUE", 11)) {
     /*                       ^         */
 #ifdef DB_OK_QUEUE
@@ -747,7 +822,7 @@ constant_11 (pTHX_ const char *name, IV *iv_return) {
 #if (DB_VERSION_MAJOR > 2) || \
     (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \
     (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \
-     DB_VERSION_PATCH >= 0)
+     DB_VERSION_PATCH >= 3)
       *iv_return = DB_LOCK_GET;
       return PERL_constant_ISIV;
 #else
@@ -901,6 +976,15 @@ constant_11 (pTHX_ const char *name, IV *iv_return) {
     }
     break;
   case 'P':
+    if (memEQ(name, "DB_FILEOPEN", 11)) {
+    /*                       ^         */
+#ifdef DB_FILEOPEN
+      *iv_return = DB_FILEOPEN;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
     if (memEQ(name, "DB_KEYEMPTY", 11)) {
     /*                       ^         */
 #ifdef DB_KEYEMPTY
@@ -915,7 +999,7 @@ constant_11 (pTHX_ const char *name, IV *iv_return) {
 #if (DB_VERSION_MAJOR > 2) || \
     (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \
     (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \
-     DB_VERSION_PATCH >= 0)
+     DB_VERSION_PATCH >= 3)
       *iv_return = DB_LOCK_PUT;
       return PERL_constant_ISIV;
 #else
@@ -933,6 +1017,15 @@ constant_11 (pTHX_ const char *name, IV *iv_return) {
     }
     break;
   case 'R':
+    if (memEQ(name, "DB_INIT_REP", 11)) {
+    /*                       ^         */
+#ifdef DB_INIT_REP
+      *iv_return = DB_INIT_REP;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
     if (memEQ(name, "DB_KEYFIRST", 11)) {
     /*                       ^         */
 #ifdef DB_KEYFIRST
@@ -949,6 +1042,15 @@ constant_11 (pTHX_ const char *name, IV *iv_return) {
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_SEQ_WRAP", 11)) {
+    /*                       ^         */
+#ifdef DB_SEQ_WRAP
+      *iv_return = DB_SEQ_WRAP;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
 #endif
     }
     break;
@@ -1014,13 +1116,14 @@ constant_12 (pTHX_ const char *name, IV *iv_return) {
   /* When generated this function returned values for the list of names given
      here.  However, subsequent manual editing may have added or removed some.
      DB_ARCH_DATA DB_CDB_ALLDB DB_CL_WRITER DB_DELIMITER DB_DIRECT_DB
-     DB_DUPCURSOR DB_ENV_FATAL DB_FAST_STAT DB_GET_BOTHC DB_GET_RECNO
-     DB_HASHMAGIC DB_INIT_LOCK DB_JOIN_ITEM DB_LOCKMAGIC DB_LOCK_DUMP
-     DB_LOCK_RW_N DB_LOGOLDVER DB_MAX_PAGES DB_MPOOL_NEW DB_NEEDSPLIT
-     DB_NODUPDATA DB_NOLOCKING DB_NORECURSE DB_OVERWRITE DB_PAGEYIELD
-     DB_PAGE_LOCK DB_PERMANENT DB_POSITIONI DB_PRINTABLE DB_QAMOLDVER
-     DB_SET_RANGE DB_SET_RECNO DB_SWAPBYTES DB_TEMPORARY DB_TXN_ABORT
-     DB_TXN_APPLY DB_TXN_PRINT DB_WRITELOCK DB_WRITEOPEN DB_XA_CREATE */
+     DB_DSYNC_LOG DB_DUPCURSOR DB_ENV_FATAL DB_FAST_STAT DB_GET_BOTHC
+     DB_GET_RECNO DB_HASHMAGIC DB_INIT_LOCK DB_JOIN_ITEM DB_LOCKMAGIC
+     DB_LOCK_DUMP DB_LOCK_RW_N DB_LOGOLDVER DB_MAX_PAGES DB_MPOOL_NEW
+     DB_NEEDSPLIT DB_NODUPDATA DB_NOLOCKING DB_NORECURSE DB_OVERWRITE
+     DB_PAGEYIELD DB_PAGE_LOCK DB_PERMANENT DB_POSITIONI DB_PRINTABLE
+     DB_QAMOLDVER DB_RPCCLIENT DB_SET_RANGE DB_SET_RECNO DB_SWAPBYTES
+     DB_TEMPORARY DB_TXN_ABORT DB_TXN_APPLY DB_TXN_PRINT DB_WRITELOCK
+     DB_WRITEOPEN DB_XA_CREATE */
   /* Offset 3 gives the best switch position.  */
   switch (name[3]) {
   case 'A':
@@ -1071,6 +1174,15 @@ constant_12 (pTHX_ const char *name, IV *iv_return) {
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_DSYNC_LOG", 12)) {
+    /*                  ^               */
+#ifdef DB_DSYNC_LOG
+      *iv_return = DB_DSYNC_LOG;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
 #endif
     }
     if (memEQ(name, "DB_DUPCURSOR", 12)) {
@@ -1173,7 +1285,7 @@ constant_12 (pTHX_ const char *name, IV *iv_return) {
 #if (DB_VERSION_MAJOR > 2) || \
     (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \
     (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \
-     DB_VERSION_PATCH >= 0)
+     DB_VERSION_PATCH >= 3)
       *iv_return = DB_LOCK_DUMP;
       return PERL_constant_ISIV;
 #else
@@ -1323,6 +1435,17 @@ constant_12 (pTHX_ const char *name, IV *iv_return) {
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 'R':
+    if (memEQ(name, "DB_RPCCLIENT", 12)) {
+    /*                  ^               */
+#ifdef DB_RPCCLIENT
+      *iv_return = DB_RPCCLIENT;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
 #endif
     }
     break;
@@ -1370,7 +1493,7 @@ constant_12 (pTHX_ const char *name, IV *iv_return) {
 #if (DB_VERSION_MAJOR > 3) || \
     (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \
     (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \
-     DB_VERSION_PATCH >= 12)
+     DB_VERSION_PATCH >= 14)
       *iv_return = DB_TXN_ABORT;
       return PERL_constant_ISIV;
 #else
@@ -1382,7 +1505,7 @@ constant_12 (pTHX_ const char *name, IV *iv_return) {
 #if (DB_VERSION_MAJOR > 4) || \
     (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \
     (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \
-     DB_VERSION_PATCH >= 7)
+     DB_VERSION_PATCH >= 14)
       *iv_return = DB_TXN_APPLY;
       return PERL_constant_ISIV;
 #else
@@ -1394,7 +1517,7 @@ constant_12 (pTHX_ const char *name, IV *iv_return) {
 #if (DB_VERSION_MAJOR > 4) || \
     (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \
     (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \
-     DB_VERSION_PATCH >= 17)
+     DB_VERSION_PATCH >= 24)
       *iv_return = DB_TXN_PRINT;
       return PERL_constant_ISIV;
 #else
@@ -1443,12 +1566,14 @@ constant_13 (pTHX_ const char *name, IV *iv_return) {
      here.  However, subsequent manual editing may have added or removed some.
      DB_AGGRESSIVE DB_BTREEMAGIC DB_CHECKPOINT DB_DIRECT_LOG DB_DIRTY_READ
      DB_DONOTINDEX DB_ENV_CREATE DB_ENV_NOMMAP DB_ENV_THREAD DB_HASHOLDVER
-     DB_INCOMPLETE DB_INIT_MPOOL DB_LOCK_NORUN DB_LOCK_RIW_N DB_LOCK_TRADE
-     DB_LOGVERSION DB_LOG_LOCKED DB_MPOOL_LAST DB_MUTEXDEBUG DB_MUTEXLOCKS
-     DB_NEXT_NODUP DB_NOORDERCHK DB_PREV_NODUP DB_PR_HEADERS DB_QAMVERSION
-     DB_RDWRMASTER DB_REGISTERED DB_REP_CLIENT DB_REP_MASTER DB_SEQUENTIAL
-     DB_STAT_CLEAR DB_SYSTEM_MEM DB_TXNVERSION DB_TXN_NOSYNC DB_TXN_NOWAIT
-     DB_VERIFY_BAD */
+     DB_INCOMPLETE DB_INIT_MPOOL DB_LOCK_ABORT DB_LOCK_NORUN DB_LOCK_RIW_N
+     DB_LOCK_TRADE DB_LOGVERSION DB_LOG_CHKPNT DB_LOG_COMMIT DB_LOG_LOCKED
+     DB_LOG_NOCOPY DB_LOG_RESEND DB_MPOOL_FREE DB_MPOOL_LAST DB_MUTEXDEBUG
+     DB_MUTEXLOCKS DB_NEXT_NODUP DB_NOORDERCHK DB_PREV_NODUP DB_PR_HEADERS
+     DB_QAMVERSION DB_RDWRMASTER DB_REGISTERED DB_REP_CLIENT DB_REP_CREATE
+     DB_REP_ISPERM DB_REP_MASTER DB_SEQUENTIAL DB_STAT_CLEAR DB_SYSTEM_MEM
+     DB_TXNVERSION DB_TXN_NOSYNC DB_TXN_NOWAIT DB_VERIFY_BAD DB_debug_FLAG
+     DB_user_BEGIN */
   /* Offset 5 gives the best switch position.  */
   switch (name[5]) {
   case 'A':
@@ -1470,6 +1595,15 @@ constant_13 (pTHX_ const char *name, IV *iv_return) {
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_LOCK_ABORT", 13)) {
+    /*                    ^              */
+#ifdef DB_LOCK_ABORT
+      *iv_return = DB_LOCK_ABORT;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
 #endif
     }
     if (memEQ(name, "DB_LOCK_NORUN", 13)) {
@@ -1495,7 +1629,7 @@ constant_13 (pTHX_ const char *name, IV *iv_return) {
 #if (DB_VERSION_MAJOR > 4) || \
     (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \
     (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \
-     DB_VERSION_PATCH >= 17)
+     DB_VERSION_PATCH >= 24)
       *iv_return = DB_LOCK_TRADE;
       return PERL_constant_ISIV;
 #else
@@ -1540,6 +1674,24 @@ constant_13 (pTHX_ const char *name, IV *iv_return) {
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_LOG_CHKPNT", 13)) {
+    /*                    ^              */
+#ifdef DB_LOG_CHKPNT
+      *iv_return = DB_LOG_CHKPNT;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_LOG_COMMIT", 13)) {
+    /*                    ^              */
+#ifdef DB_LOG_COMMIT
+      *iv_return = DB_LOG_COMMIT;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
 #endif
     }
     if (memEQ(name, "DB_LOG_LOCKED", 13)) {
@@ -1549,6 +1701,24 @@ constant_13 (pTHX_ const char *name, IV *iv_return) {
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_LOG_NOCOPY", 13)) {
+    /*                    ^              */
+#ifdef DB_LOG_NOCOPY
+      *iv_return = DB_LOG_NOCOPY;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_LOG_RESEND", 13)) {
+    /*                    ^              */
+#ifdef DB_LOG_RESEND
+      *iv_return = DB_LOG_RESEND;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
 #endif
     }
     if (memEQ(name, "DB_REGISTERED", 13)) {
@@ -1622,6 +1792,15 @@ constant_13 (pTHX_ const char *name, IV *iv_return) {
     }
     break;
   case 'O':
+    if (memEQ(name, "DB_MPOOL_FREE", 13)) {
+    /*                    ^              */
+#ifdef DB_MPOOL_FREE
+      *iv_return = DB_MPOOL_FREE;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
     if (memEQ(name, "DB_MPOOL_LAST", 13)) {
     /*                    ^              */
 #ifdef DB_MPOOL_LAST
@@ -1651,10 +1830,28 @@ constant_13 (pTHX_ const char *name, IV *iv_return) {
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_REP_MASTER", 13)) {
+    if (memEQ(name, "DB_REP_CREATE", 13)) {
     /*                    ^              */
-#ifdef DB_REP_MASTER
-      *iv_return = DB_REP_MASTER;
+#ifdef DB_REP_CREATE
+      *iv_return = DB_REP_CREATE;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_REP_ISPERM", 13)) {
+    /*                    ^              */
+#ifdef DB_REP_ISPERM
+      *iv_return = DB_REP_ISPERM;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_REP_MASTER", 13)) {
+    /*                    ^              */
+#ifdef DB_REP_MASTER
+      *iv_return = DB_REP_MASTER;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
@@ -1809,6 +2006,28 @@ constant_13 (pTHX_ const char *name, IV *iv_return) {
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 'b':
+    if (memEQ(name, "DB_debug_FLAG", 13)) {
+    /*                    ^              */
+#ifdef DB_debug_FLAG
+      *iv_return = DB_debug_FLAG;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 'e':
+    if (memEQ(name, "DB_user_BEGIN", 13)) {
+    /*                    ^              */
+#ifdef DB_user_BEGIN
+      *iv_return = DB_user_BEGIN;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
 #endif
     }
     break;
@@ -1820,16 +2039,16 @@ static int
 constant_14 (pTHX_ const char *name, IV *iv_return) {
   /* When generated this function returned values for the list of names given
      here.  However, subsequent manual editing may have added or removed some.
-     DB_AUTO_COMMIT DB_BTREEOLDVER DB_CHKSUM_SHA1 DB_EID_INVALID DB_ENCRYPT_AES
-     DB_ENV_APPINIT DB_ENV_DBLOCAL DB_ENV_LOCKING DB_ENV_LOGGING DB_ENV_NOPANIC
-     DB_ENV_PRIVATE DB_FILE_ID_LEN DB_HANDLE_LOCK DB_HASHVERSION DB_INVALID_EID
+     DB_ARCH_REMOVE DB_AUTO_COMMIT DB_BTREEOLDVER DB_CHKSUM_SHA1 DB_EID_INVALID
+     DB_ENCRYPT_AES DB_ENV_APPINIT DB_ENV_DBLOCAL DB_ENV_LOCKING DB_ENV_LOGGING
+     DB_ENV_NOPANIC DB_ENV_PRIVATE DB_FILE_ID_LEN DB_HANDLE_LOCK DB_HASHVERSION
      DB_JOIN_NOSORT DB_LOCKVERSION DB_LOCK_EXPIRE DB_LOCK_NOWAIT DB_LOCK_OLDEST
      DB_LOCK_RANDOM DB_LOCK_RECORD DB_LOCK_REMOVE DB_LOCK_SWITCH DB_MAX_RECORDS
      DB_MPOOL_CLEAN DB_MPOOL_DIRTY DB_NOOVERWRITE DB_NOSERVER_ID DB_ODDFILESIZE
      DB_OLD_VERSION DB_OPEN_CALLED DB_RECORDCOUNT DB_RECORD_LOCK DB_REGION_ANON
-     DB_REGION_INIT DB_REGION_NAME DB_RENAMEMAGIC DB_REP_NEWSITE DB_REP_UNAVAIL
-     DB_REVSPLITOFF DB_RUNRECOVERY DB_SET_TXN_NOW DB_USE_ENVIRON DB_WRITECURSOR
-     DB_XIDDATASIZE */
+     DB_REGION_INIT DB_REGION_NAME DB_RENAMEMAGIC DB_REP_EGENCHG DB_REP_NEWSITE
+     DB_REP_NOTPERM DB_REP_UNAVAIL DB_REVSPLITOFF DB_RUNRECOVERY DB_SET_TXN_NOW
+     DB_USE_ENVIRON DB_WRITECURSOR DB_XIDDATASIZE */
   /* Offset 9 gives the best switch position.  */
   switch (name[9]) {
   case 'A':
@@ -1918,26 +2137,26 @@ constant_14 (pTHX_ const char *name, IV *iv_return) {
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_INVALID_EID", 14)) {
+    if (memEQ(name, "DB_MPOOL_DIRTY", 14)) {
     /*                        ^           */
-#ifdef DB_INVALID_EID
-      *iv_return = DB_INVALID_EID;
+#ifdef DB_MPOOL_DIRTY
+      *iv_return = DB_MPOOL_DIRTY;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_MPOOL_DIRTY", 14)) {
+    break;
+  case 'E':
+    if (memEQ(name, "DB_ARCH_REMOVE", 14)) {
     /*                        ^           */
-#ifdef DB_MPOOL_DIRTY
-      *iv_return = DB_MPOOL_DIRTY;
+#ifdef DB_ARCH_REMOVE
+      *iv_return = DB_ARCH_REMOVE;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    break;
-  case 'E':
     if (memEQ(name, "DB_LOCK_RECORD", 14)) {
     /*                        ^           */
 #ifdef DB_LOCK_RECORD
@@ -1972,6 +2191,15 @@ constant_14 (pTHX_ const char *name, IV *iv_return) {
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_REP_EGENCHG", 14)) {
+    /*                        ^           */
+#ifdef DB_REP_EGENCHG
+      *iv_return = DB_REP_EGENCHG;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
 #endif
     }
     break;
@@ -2152,6 +2380,15 @@ constant_14 (pTHX_ const char *name, IV *iv_return) {
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_REP_NOTPERM", 14)) {
+    /*                        ^           */
+#ifdef DB_REP_NOTPERM
+      *iv_return = DB_REP_NOTPERM;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
 #endif
     }
     break;
@@ -2290,14 +2527,16 @@ static int
 constant_15 (pTHX_ const char *name, IV *iv_return) {
   /* When generated this function returned values for the list of names given
      here.  However, subsequent manual editing may have added or removed some.
-     DB_APPLY_LOGREG DB_BTREEVERSION DB_CONSUME_WAIT DB_ENV_LOCKDOWN
-     DB_ENV_PANIC_OK DB_ENV_YIELDCPU DB_LOCK_DEFAULT DB_LOCK_INHERIT
-     DB_LOCK_NOTHELD DB_LOCK_PUT_ALL DB_LOCK_PUT_OBJ DB_LOCK_TIMEOUT
-     DB_LOCK_UPGRADE DB_MPOOL_CREATE DB_MPOOL_EXTENT DB_MULTIPLE_KEY
-     DB_OPFLAGS_MASK DB_ORDERCHKONLY DB_PRIORITY_LOW DB_REGION_MAGIC
-     DB_REP_LOGSONLY DB_REP_OUTDATED DB_SURPRISE_KID DB_TEST_POSTLOG
-     DB_TEST_PREOPEN DB_TXN_GETPGNOS DB_TXN_LOCK_2PL DB_TXN_LOG_MASK
-     DB_TXN_LOG_REDO DB_TXN_LOG_UNDO DB_VERIFY_FATAL */
+     DB_APPLY_LOGREG DB_BTREEVERSION DB_BUFFER_SMALL DB_CONSUME_WAIT
+     DB_ENV_LOCKDOWN DB_ENV_PANIC_OK DB_ENV_YIELDCPU DB_LOCK_DEFAULT
+     DB_LOCK_INHERIT DB_LOCK_NOTHELD DB_LOCK_PUT_ALL DB_LOCK_PUT_OBJ
+     DB_LOCK_TIMEOUT DB_LOCK_UPGRADE DB_LOG_INMEMORY DB_LOG_WRNOSYNC
+     DB_MPOOL_CREATE DB_MPOOL_EXTENT DB_MPOOL_NOFILE DB_MPOOL_UNLINK
+     DB_MULTIPLE_KEY DB_OPFLAGS_MASK DB_ORDERCHKONLY DB_PRIORITY_LOW
+     DB_REGION_MAGIC DB_REP_LOGREADY DB_REP_LOGSONLY DB_REP_NOBUFFER
+     DB_REP_OUTDATED DB_REP_PAGEDONE DB_SURPRISE_KID DB_TEST_POSTLOG
+     DB_TEST_PREOPEN DB_TXN_LOCK_2PL DB_TXN_LOG_MASK DB_TXN_LOG_REDO
+     DB_TXN_LOG_UNDO DB_VERIFY_FATAL */
   /* Offset 10 gives the best switch position.  */
   switch (name[10]) {
   case 'D':
@@ -2312,6 +2551,15 @@ constant_15 (pTHX_ const char *name, IV *iv_return) {
     }
     break;
   case 'E':
+    if (memEQ(name, "DB_LOG_INMEMORY", 15)) {
+    /*                         ^           */
+#ifdef DB_LOG_INMEMORY
+      *iv_return = DB_LOG_INMEMORY;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
     if (memEQ(name, "DB_MULTIPLE_KEY", 15)) {
     /*                         ^           */
 #ifdef DB_MULTIPLE_KEY
@@ -2319,6 +2567,15 @@ constant_15 (pTHX_ const char *name, IV *iv_return) {
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_REP_PAGEDONE", 15)) {
+    /*                         ^           */
+#ifdef DB_REP_PAGEDONE
+      *iv_return = DB_REP_PAGEDONE;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
 #endif
     }
     if (memEQ(name, "DB_SURPRISE_KID", 15)) {
@@ -2442,7 +2699,7 @@ constant_15 (pTHX_ const char *name, IV *iv_return) {
 #if (DB_VERSION_MAJOR > 4) || \
     (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \
     (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \
-     DB_VERSION_PATCH >= 7)
+     DB_VERSION_PATCH >= 14)
       *iv_return = DB_LOCK_TIMEOUT;
       return PERL_constant_ISIV;
 #else
@@ -2456,6 +2713,17 @@ constant_15 (pTHX_ const char *name, IV *iv_return) {
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 'N':
+    if (memEQ(name, "DB_MPOOL_UNLINK", 15)) {
+    /*                         ^           */
+#ifdef DB_MPOOL_UNLINK
+      *iv_return = DB_MPOOL_UNLINK;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
 #endif
     }
     break;
@@ -2469,15 +2737,19 @@ constant_15 (pTHX_ const char *name, IV *iv_return) {
       return PERL_constant_NOTDEF;
 #endif
     }
-    break;
-  case 'P':
-    if (memEQ(name, "DB_TXN_GETPGNOS", 15)) {
+    if (memEQ(name, "DB_LOG_WRNOSYNC", 15)) {
     /*                         ^           */
-#if (DB_VERSION_MAJOR > 4) || \
-    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \
-    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \
-     DB_VERSION_PATCH >= 17)
-      *iv_return = DB_TXN_GETPGNOS;
+#ifdef DB_LOG_WRNOSYNC
+      *iv_return = DB_LOG_WRNOSYNC;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_MPOOL_NOFILE", 15)) {
+    /*                         ^           */
+#ifdef DB_MPOOL_NOFILE
+      *iv_return = DB_MPOOL_NOFILE;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
@@ -2501,10 +2773,28 @@ constant_15 (pTHX_ const char *name, IV *iv_return) {
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_REP_LOGREADY", 15)) {
+    /*                         ^           */
+#ifdef DB_REP_LOGREADY
+      *iv_return = DB_REP_LOGREADY;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
 #endif
     }
     break;
   case 'S':
+    if (memEQ(name, "DB_BUFFER_SMALL", 15)) {
+    /*                         ^           */
+#ifdef DB_BUFFER_SMALL
+      *iv_return = DB_BUFFER_SMALL;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
     if (memEQ(name, "DB_REP_LOGSONLY", 15)) {
     /*                         ^           */
 #ifdef DB_REP_LOGSONLY
@@ -2539,7 +2829,7 @@ constant_15 (pTHX_ const char *name, IV *iv_return) {
 #if (DB_VERSION_MAJOR > 2) || \
     (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \
     (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \
-     DB_VERSION_PATCH >= 0)
+     DB_VERSION_PATCH >= 3)
       *iv_return = DB_LOCK_PUT_ALL;
       return PERL_constant_ISIV;
 #else
@@ -2551,11 +2841,22 @@ constant_15 (pTHX_ const char *name, IV *iv_return) {
 #if (DB_VERSION_MAJOR > 2) || \
     (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \
     (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \
-     DB_VERSION_PATCH >= 0)
+     DB_VERSION_PATCH >= 3)
       *iv_return = DB_LOCK_PUT_OBJ;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 'U':
+    if (memEQ(name, "DB_REP_NOBUFFER", 15)) {
+    /*                         ^           */
+#ifdef DB_REP_NOBUFFER
+      *iv_return = DB_REP_NOBUFFER;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
 #endif
     }
     break;
@@ -2576,7 +2877,7 @@ constant_15 (pTHX_ const char *name, IV *iv_return) {
 #if (DB_VERSION_MAJOR > 4) || \
     (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \
     (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \
-     DB_VERSION_PATCH >= 17)
+     DB_VERSION_PATCH >= 24)
       *iv_return = DB_PRIORITY_LOW;
       return PERL_constant_ISIV;
 #else
@@ -2639,53 +2940,51 @@ static int
 constant_16 (pTHX_ const char *name, IV *iv_return) {
   /* When generated this function returned values for the list of names given
      here.  However, subsequent manual editing may have added or removed some.
-     DB_BROADCAST_EID DB_CACHED_COUNTS DB_EID_BROADCAST DB_ENV_CDB_ALLDB
-     DB_ENV_DIRECT_DB DB_ENV_NOLOCKING DB_ENV_OVERWRITE DB_ENV_RPCCLIENT
+     DB_CACHED_COUNTS DB_EID_BROADCAST DB_ENV_CDB_ALLDB DB_ENV_DIRECT_DB
+     DB_ENV_DSYNC_LOG DB_ENV_NOLOCKING DB_ENV_OVERWRITE DB_ENV_RPCCLIENT
      DB_FCNTL_LOCKING DB_JAVA_CALLBACK DB_LOCK_CONFLICT DB_LOCK_DEADLOCK
-     DB_LOCK_MAXLOCKS DB_LOCK_MINLOCKS DB_LOCK_MINWRITE DB_LOCK_NOTEXIST
-     DB_LOCK_PUT_READ DB_LOCK_YOUNGEST DB_LOGC_BUF_SIZE DB_MPOOL_DISCARD
-     DB_MPOOL_PRIVATE DB_NOSERVER_HOME DB_PAGE_NOTFOUND DB_PRIORITY_HIGH
-     DB_RECOVER_FATAL DB_REP_DUPMASTER DB_REP_NEWMASTER DB_REP_PERMANENT
-     DB_SECONDARY_BAD DB_TEST_POSTOPEN DB_TEST_POSTSYNC DB_TXN_LOCK_MASK
-     DB_TXN_OPENFILES DB_VERB_CHKPOINT DB_VERB_DEADLOCK DB_VERB_RECOVERY
-     DB_VERB_WAITSFOR DB_VERSION_MAJOR DB_VERSION_MINOR DB_VERSION_PATCH
-     DB_VRFY_FLAGMASK */
-  /* Offset 12 gives the best switch position.  */
-  switch (name[12]) {
+     DB_LOCK_MAXLOCKS DB_LOCK_MAXWRITE DB_LOCK_MINLOCKS DB_LOCK_MINWRITE
+     DB_LOCK_NOTEXIST DB_LOCK_PUT_READ DB_LOCK_YOUNGEST DB_LOGC_BUF_SIZE
+     DB_MPOOL_DISCARD DB_MPOOL_PRIVATE DB_NOSERVER_HOME DB_PAGE_NOTFOUND
+     DB_PRIORITY_HIGH DB_RECOVER_FATAL DB_REP_DUPMASTER DB_REP_NEWMASTER
+     DB_REP_PERMANENT DB_SECONDARY_BAD DB_SEQ_RANGE_SET DB_TEST_POSTOPEN
+     DB_TEST_POSTSYNC DB_TXN_LOCK_MASK DB_TXN_OPENFILES DB_VERB_CHKPOINT
+     DB_VERB_DEADLOCK DB_VERB_RECOVERY DB_VERB_WAITSFOR DB_VERSION_MAJOR
+     DB_VERSION_MINOR DB_VERSION_PATCH DB_VRFY_FLAGMASK */
+  /* Offset 10 gives the best switch position.  */
+  switch (name[10]) {
   case 'A':
-    if (memEQ(name, "DB_RECOVER_FATAL", 16)) {
-    /*                           ^          */
-#ifdef DB_RECOVER_FATAL
-      *iv_return = DB_RECOVER_FATAL;
+    if (memEQ(name, "DB_EID_BROADCAST", 16)) {
+    /*                         ^            */
+#ifdef DB_EID_BROADCAST
+      *iv_return = DB_EID_BROADCAST;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_VERSION_MAJOR", 16)) {
-    /*                           ^          */
-#ifdef DB_VERSION_MAJOR
-      *iv_return = DB_VERSION_MAJOR;
+    if (memEQ(name, "DB_LOCK_DEADLOCK", 16)) {
+    /*                         ^            */
+#ifdef DB_LOCK_DEADLOCK
+      *iv_return = DB_LOCK_DEADLOCK;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_VERSION_PATCH", 16)) {
-    /*                           ^          */
-#ifdef DB_VERSION_PATCH
-      *iv_return = DB_VERSION_PATCH;
+    if (memEQ(name, "DB_VERB_DEADLOCK", 16)) {
+    /*                         ^            */
+#ifdef DB_VERB_DEADLOCK
+      *iv_return = DB_VERB_DEADLOCK;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    break;
-  case 'B':
-    if (memEQ(name, "DB_JAVA_CALLBACK", 16)) {
-    /*                           ^          */
-#ifdef DB_JAVA_CALLBACK
-      *iv_return = DB_JAVA_CALLBACK;
+    if (memEQ(name, "DB_VRFY_FLAGMASK", 16)) {
+    /*                         ^            */
+#ifdef DB_VRFY_FLAGMASK
+      *iv_return = DB_VRFY_FLAGMASK;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
@@ -2693,85 +2992,81 @@ constant_16 (pTHX_ const char *name, IV *iv_return) {
     }
     break;
   case 'C':
-    if (memEQ(name, "DB_EID_BROADCAST", 16)) {
-    /*                           ^          */
-#ifdef DB_EID_BROADCAST
-      *iv_return = DB_EID_BROADCAST;
+    if (memEQ(name, "DB_CACHED_COUNTS", 16)) {
+    /*                         ^            */
+#ifdef DB_CACHED_COUNTS
+      *iv_return = DB_CACHED_COUNTS;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_MPOOL_DISCARD", 16)) {
-    /*                           ^          */
-#ifdef DB_MPOOL_DISCARD
-      *iv_return = DB_MPOOL_DISCARD;
+    if (memEQ(name, "DB_ENV_RPCCLIENT", 16)) {
+    /*                         ^            */
+#ifdef DB_ENV_RPCCLIENT
+      *iv_return = DB_ENV_RPCCLIENT;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    break;
-  case 'G':
-    if (memEQ(name, "DB_LOCK_YOUNGEST", 16)) {
-    /*                           ^          */
-#ifdef DB_LOCK_YOUNGEST
-      *iv_return = DB_LOCK_YOUNGEST;
+    if (memEQ(name, "DB_VERB_RECOVERY", 16)) {
+    /*                         ^            */
+#ifdef DB_VERB_RECOVERY
+      *iv_return = DB_VERB_RECOVERY;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
     break;
-  case 'H':
-    if (memEQ(name, "DB_NOSERVER_HOME", 16)) {
-    /*                           ^          */
-#ifdef DB_NOSERVER_HOME
-      *iv_return = DB_NOSERVER_HOME;
+  case 'E':
+    if (memEQ(name, "DB_ENV_DIRECT_DB", 16)) {
+    /*                         ^            */
+#ifdef DB_ENV_DIRECT_DB
+      *iv_return = DB_ENV_DIRECT_DB;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_PRIORITY_HIGH", 16)) {
-    /*                           ^          */
-#if (DB_VERSION_MAJOR > 4) || \
-    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \
-    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \
-     DB_VERSION_PATCH >= 17)
-      *iv_return = DB_PRIORITY_HIGH;
+    break;
+  case 'F':
+    if (memEQ(name, "DB_LOGC_BUF_SIZE", 16)) {
+    /*                         ^            */
+#ifdef DB_LOGC_BUF_SIZE
+      *iv_return = DB_LOGC_BUF_SIZE;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
     break;
-  case 'I':
-    if (memEQ(name, "DB_ENV_RPCCLIENT", 16)) {
-    /*                           ^          */
-#ifdef DB_ENV_RPCCLIENT
-      *iv_return = DB_ENV_RPCCLIENT;
+  case 'G':
+    if (memEQ(name, "DB_SEQ_RANGE_SET", 16)) {
+    /*                         ^            */
+#ifdef DB_SEQ_RANGE_SET
+      *iv_return = DB_SEQ_RANGE_SET;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_TXN_OPENFILES", 16)) {
-    /*                           ^          */
-#if (DB_VERSION_MAJOR > 3) || \
-    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \
-    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \
-     DB_VERSION_PATCH >= 12)
-      *iv_return = DB_TXN_OPENFILES;
+    break;
+  case 'I':
+    if (memEQ(name, "DB_MPOOL_DISCARD", 16)) {
+    /*                         ^            */
+#ifdef DB_MPOOL_DISCARD
+      *iv_return = DB_MPOOL_DISCARD;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_VERSION_MINOR", 16)) {
-    /*                           ^          */
-#ifdef DB_VERSION_MINOR
-      *iv_return = DB_VERSION_MINOR;
+    if (memEQ(name, "DB_VERB_WAITSFOR", 16)) {
+    /*                         ^            */
+#ifdef DB_VERB_WAITSFOR
+      *iv_return = DB_VERB_WAITSFOR;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
@@ -2779,19 +3074,19 @@ constant_16 (pTHX_ const char *name, IV *iv_return) {
     }
     break;
   case 'K':
-    if (memEQ(name, "DB_ENV_NOLOCKING", 16)) {
-    /*                           ^          */
-#ifdef DB_ENV_NOLOCKING
-      *iv_return = DB_ENV_NOLOCKING;
+    if (memEQ(name, "DB_TXN_LOCK_MASK", 16)) {
+    /*                         ^            */
+#ifdef DB_TXN_LOCK_MASK
+      *iv_return = DB_TXN_LOCK_MASK;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_FCNTL_LOCKING", 16)) {
-    /*                           ^          */
-#ifdef DB_FCNTL_LOCKING
-      *iv_return = DB_FCNTL_LOCKING;
+    if (memEQ(name, "DB_VERB_CHKPOINT", 16)) {
+    /*                         ^            */
+#ifdef DB_VERB_CHKPOINT
+      *iv_return = DB_VERB_CHKPOINT;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
@@ -2799,115 +3094,109 @@ constant_16 (pTHX_ const char *name, IV *iv_return) {
     }
     break;
   case 'L':
-    if (memEQ(name, "DB_ENV_CDB_ALLDB", 16)) {
-    /*                           ^          */
-#ifdef DB_ENV_CDB_ALLDB
-      *iv_return = DB_ENV_CDB_ALLDB;
+    if (memEQ(name, "DB_JAVA_CALLBACK", 16)) {
+    /*                         ^            */
+#ifdef DB_JAVA_CALLBACK
+      *iv_return = DB_JAVA_CALLBACK;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_LOCK_CONFLICT", 16)) {
-    /*                           ^          */
-#ifdef DB_LOCK_CONFLICT
-      *iv_return = DB_LOCK_CONFLICT;
+    break;
+  case 'M':
+    if (memEQ(name, "DB_REP_DUPMASTER", 16)) {
+    /*                         ^            */
+#ifdef DB_REP_DUPMASTER
+      *iv_return = DB_REP_DUPMASTER;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_LOCK_DEADLOCK", 16)) {
-    /*                           ^          */
-#ifdef DB_LOCK_DEADLOCK
-      *iv_return = DB_LOCK_DEADLOCK;
+    if (memEQ(name, "DB_REP_NEWMASTER", 16)) {
+    /*                         ^            */
+#ifdef DB_REP_NEWMASTER
+      *iv_return = DB_REP_NEWMASTER;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_VERB_DEADLOCK", 16)) {
-    /*                           ^          */
-#ifdef DB_VERB_DEADLOCK
-      *iv_return = DB_VERB_DEADLOCK;
+    if (memEQ(name, "DB_REP_PERMANENT", 16)) {
+    /*                         ^            */
+#ifdef DB_REP_PERMANENT
+      *iv_return = DB_REP_PERMANENT;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
     break;
-  case 'M':
-    if (memEQ(name, "DB_TXN_LOCK_MASK", 16)) {
-    /*                           ^          */
-#ifdef DB_TXN_LOCK_MASK
-      *iv_return = DB_TXN_LOCK_MASK;
+  case 'N':
+    if (memEQ(name, "DB_ENV_DSYNC_LOG", 16)) {
+    /*                         ^            */
+#ifdef DB_ENV_DSYNC_LOG
+      *iv_return = DB_ENV_DSYNC_LOG;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_VRFY_FLAGMASK", 16)) {
-    /*                           ^          */
-#ifdef DB_VRFY_FLAGMASK
-      *iv_return = DB_VRFY_FLAGMASK;
+    if (memEQ(name, "DB_LOCK_CONFLICT", 16)) {
+    /*                         ^            */
+#ifdef DB_LOCK_CONFLICT
+      *iv_return = DB_LOCK_CONFLICT;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    break;
-  case 'N':
-    if (memEQ(name, "DB_REP_PERMANENT", 16)) {
-    /*                           ^          */
-#ifdef DB_REP_PERMANENT
-      *iv_return = DB_REP_PERMANENT;
+    if (memEQ(name, "DB_LOCK_MINLOCKS", 16)) {
+    /*                         ^            */
+#ifdef DB_LOCK_MINLOCKS
+      *iv_return = DB_LOCK_MINLOCKS;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    break;
-  case 'O':
-    if (memEQ(name, "DB_LOCK_MAXLOCKS", 16)) {
-    /*                           ^          */
-#ifdef DB_LOCK_MAXLOCKS
-      *iv_return = DB_LOCK_MAXLOCKS;
+    if (memEQ(name, "DB_LOCK_MINWRITE", 16)) {
+    /*                         ^            */
+#ifdef DB_LOCK_MINWRITE
+      *iv_return = DB_LOCK_MINWRITE;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_LOCK_MINLOCKS", 16)) {
-    /*                           ^          */
-#ifdef DB_LOCK_MINLOCKS
-      *iv_return = DB_LOCK_MINLOCKS;
-      return PERL_constant_ISIV;
-#else
-      return PERL_constant_NOTDEF;
-#endif
-    }
-    if (memEQ(name, "DB_PAGE_NOTFOUND", 16)) {
-    /*                           ^          */
-#ifdef DB_PAGE_NOTFOUND
-      *iv_return = DB_PAGE_NOTFOUND;
+    if (memEQ(name, "DB_TXN_OPENFILES", 16)) {
+    /*                         ^            */
+#if (DB_VERSION_MAJOR > 3) || \
+    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \
+    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \
+     DB_VERSION_PATCH >= 14)
+      *iv_return = DB_TXN_OPENFILES;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_TEST_POSTOPEN", 16)) {
-    /*                           ^          */
-#ifdef DB_TEST_POSTOPEN
-      *iv_return = DB_TEST_POSTOPEN;
+    break;
+  case 'O':
+    if (memEQ(name, "DB_ENV_NOLOCKING", 16)) {
+    /*                         ^            */
+#ifdef DB_ENV_NOLOCKING
+      *iv_return = DB_ENV_NOLOCKING;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_VERB_CHKPOINT", 16)) {
-    /*                           ^          */
-#ifdef DB_VERB_CHKPOINT
-      *iv_return = DB_VERB_CHKPOINT;
+    if (memEQ(name, "DB_FCNTL_LOCKING", 16)) {
+    /*                         ^            */
+#ifdef DB_FCNTL_LOCKING
+      *iv_return = DB_FCNTL_LOCKING;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
@@ -2916,7 +3205,7 @@ constant_16 (pTHX_ const char *name, IV *iv_return) {
     break;
   case 'R':
     if (memEQ(name, "DB_ENV_OVERWRITE", 16)) {
-    /*                           ^          */
+    /*                         ^            */
 #ifdef DB_ENV_OVERWRITE
       *iv_return = DB_ENV_OVERWRITE;
       return PERL_constant_ISIV;
@@ -2924,80 +3213,80 @@ constant_16 (pTHX_ const char *name, IV *iv_return) {
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_LOCK_MINWRITE", 16)) {
-    /*                           ^          */
-#ifdef DB_LOCK_MINWRITE
-      *iv_return = DB_LOCK_MINWRITE;
+    if (memEQ(name, "DB_MPOOL_PRIVATE", 16)) {
+    /*                         ^            */
+#ifdef DB_MPOOL_PRIVATE
+      *iv_return = DB_MPOOL_PRIVATE;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_LOCK_PUT_READ", 16)) {
-    /*                           ^          */
-#if (DB_VERSION_MAJOR > 4) || \
-    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \
-    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \
-     DB_VERSION_PATCH >= 7)
-      *iv_return = DB_LOCK_PUT_READ;
+    if (memEQ(name, "DB_NOSERVER_HOME", 16)) {
+    /*                         ^            */
+#ifdef DB_NOSERVER_HOME
+      *iv_return = DB_NOSERVER_HOME;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    break;
-  case 'S':
-    if (memEQ(name, "DB_LOGC_BUF_SIZE", 16)) {
-    /*                           ^          */
-#ifdef DB_LOGC_BUF_SIZE
-      *iv_return = DB_LOGC_BUF_SIZE;
+    if (memEQ(name, "DB_SECONDARY_BAD", 16)) {
+    /*                         ^            */
+#ifdef DB_SECONDARY_BAD
+      *iv_return = DB_SECONDARY_BAD;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_REP_DUPMASTER", 16)) {
-    /*                           ^          */
-#ifdef DB_REP_DUPMASTER
-      *iv_return = DB_REP_DUPMASTER;
+    break;
+  case 'S':
+    if (memEQ(name, "DB_TEST_POSTOPEN", 16)) {
+    /*                         ^            */
+#ifdef DB_TEST_POSTOPEN
+      *iv_return = DB_TEST_POSTOPEN;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_REP_NEWMASTER", 16)) {
-    /*                           ^          */
-#ifdef DB_REP_NEWMASTER
-      *iv_return = DB_REP_NEWMASTER;
+    if (memEQ(name, "DB_TEST_POSTSYNC", 16)) {
+    /*                         ^            */
+#ifdef DB_TEST_POSTSYNC
+      *iv_return = DB_TEST_POSTSYNC;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_TEST_POSTSYNC", 16)) {
-    /*                           ^          */
-#ifdef DB_TEST_POSTSYNC
-      *iv_return = DB_TEST_POSTSYNC;
+    break;
+  case 'T':
+    if (memEQ(name, "DB_LOCK_NOTEXIST", 16)) {
+    /*                         ^            */
+#ifdef DB_LOCK_NOTEXIST
+      *iv_return = DB_LOCK_NOTEXIST;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_VERB_WAITSFOR", 16)) {
-    /*                           ^          */
-#ifdef DB_VERB_WAITSFOR
-      *iv_return = DB_VERB_WAITSFOR;
+    if (memEQ(name, "DB_LOCK_PUT_READ", 16)) {
+    /*                         ^            */
+#if (DB_VERSION_MAJOR > 4) || \
+    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \
+    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \
+     DB_VERSION_PATCH >= 14)
+      *iv_return = DB_LOCK_PUT_READ;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    break;
-  case 'T':
-    if (memEQ(name, "DB_ENV_DIRECT_DB", 16)) {
-    /*                           ^          */
-#ifdef DB_ENV_DIRECT_DB
-      *iv_return = DB_ENV_DIRECT_DB;
+    if (memEQ(name, "DB_PAGE_NOTFOUND", 16)) {
+    /*                         ^            */
+#ifdef DB_PAGE_NOTFOUND
+      *iv_return = DB_PAGE_NOTFOUND;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
@@ -3005,41 +3294,44 @@ constant_16 (pTHX_ const char *name, IV *iv_return) {
     }
     break;
   case 'U':
-    if (memEQ(name, "DB_CACHED_COUNTS", 16)) {
-    /*                           ^          */
-#ifdef DB_CACHED_COUNTS
-      *iv_return = DB_CACHED_COUNTS;
+    if (memEQ(name, "DB_LOCK_YOUNGEST", 16)) {
+    /*                         ^            */
+#ifdef DB_LOCK_YOUNGEST
+      *iv_return = DB_LOCK_YOUNGEST;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
     break;
-  case 'V':
-    if (memEQ(name, "DB_MPOOL_PRIVATE", 16)) {
-    /*                           ^          */
-#ifdef DB_MPOOL_PRIVATE
-      *iv_return = DB_MPOOL_PRIVATE;
+  case 'X':
+    if (memEQ(name, "DB_LOCK_MAXLOCKS", 16)) {
+    /*                         ^            */
+#ifdef DB_LOCK_MAXLOCKS
+      *iv_return = DB_LOCK_MAXLOCKS;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_VERB_RECOVERY", 16)) {
-    /*                           ^          */
-#ifdef DB_VERB_RECOVERY
-      *iv_return = DB_VERB_RECOVERY;
+    if (memEQ(name, "DB_LOCK_MAXWRITE", 16)) {
+    /*                         ^            */
+#ifdef DB_LOCK_MAXWRITE
+      *iv_return = DB_LOCK_MAXWRITE;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
     break;
-  case 'X':
-    if (memEQ(name, "DB_LOCK_NOTEXIST", 16)) {
-    /*                           ^          */
-#ifdef DB_LOCK_NOTEXIST
-      *iv_return = DB_LOCK_NOTEXIST;
+  case 'Y':
+    if (memEQ(name, "DB_PRIORITY_HIGH", 16)) {
+    /*                         ^            */
+#if (DB_VERSION_MAJOR > 4) || \
+    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \
+    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \
+     DB_VERSION_PATCH >= 24)
+      *iv_return = DB_PRIORITY_HIGH;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
@@ -3047,19 +3339,46 @@ constant_16 (pTHX_ const char *name, IV *iv_return) {
     }
     break;
   case '_':
-    if (memEQ(name, "DB_BROADCAST_EID", 16)) {
-    /*                           ^          */
-#ifdef DB_BROADCAST_EID
-      *iv_return = DB_BROADCAST_EID;
+    if (memEQ(name, "DB_ENV_CDB_ALLDB", 16)) {
+    /*                         ^            */
+#ifdef DB_ENV_CDB_ALLDB
+      *iv_return = DB_ENV_CDB_ALLDB;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_SECONDARY_BAD", 16)) {
-    /*                           ^          */
-#ifdef DB_SECONDARY_BAD
-      *iv_return = DB_SECONDARY_BAD;
+    if (memEQ(name, "DB_RECOVER_FATAL", 16)) {
+    /*                         ^            */
+#ifdef DB_RECOVER_FATAL
+      *iv_return = DB_RECOVER_FATAL;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_VERSION_MAJOR", 16)) {
+    /*                         ^            */
+#ifdef DB_VERSION_MAJOR
+      *iv_return = DB_VERSION_MAJOR;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_VERSION_MINOR", 16)) {
+    /*                         ^            */
+#ifdef DB_VERSION_MINOR
+      *iv_return = DB_VERSION_MINOR;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_VERSION_PATCH", 16)) {
+    /*                         ^            */
+#ifdef DB_VERSION_PATCH
+      *iv_return = DB_VERSION_PATCH;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
@@ -3076,138 +3395,133 @@ constant_17 (pTHX_ const char *name, IV *iv_return, const char **pv_return) {
      here.  However, subsequent manual editing may have added or removed some.
      DB_ENV_DIRECT_LOG DB_ENV_REP_CLIENT DB_ENV_REP_MASTER DB_ENV_STANDALONE
      DB_ENV_SYSTEM_MEM DB_ENV_TXN_NOSYNC DB_ENV_USER_ALLOC DB_GET_BOTH_RANGE
-     DB_LOG_SILENT_ERR DB_RPC_SERVERPROG DB_RPC_SERVERVERS DB_TEST_ELECTINIT
-     DB_TEST_ELECTSEND DB_TEST_PRERENAME DB_TXN_POPENFILES DB_VERSION_STRING */
-  /* Offset 14 gives the best switch position.  */
-  switch (name[14]) {
+     DB_LOG_AUTOREMOVE DB_LOG_SILENT_ERR DB_NO_AUTO_COMMIT DB_RPC_SERVERPROG
+     DB_RPC_SERVERVERS DB_STAT_LOCK_CONF DB_STAT_MEMP_HASH DB_STAT_SUBSYSTEM
+     DB_TEST_ELECTINIT DB_TEST_ELECTSEND DB_TEST_PRERENAME DB_TXN_POPENFILES
+     DB_VERSION_STRING */
+  /* Offset 13 gives the best switch position.  */
+  switch (name[13]) {
   case 'A':
-    if (memEQ(name, "DB_TEST_PRERENAME", 17)) {
-    /*                             ^         */
-#ifdef DB_TEST_PRERENAME
-      *iv_return = DB_TEST_PRERENAME;
+    if (memEQ(name, "DB_GET_BOTH_RANGE", 17)) {
+    /*                            ^          */
+#ifdef DB_GET_BOTH_RANGE
+      *iv_return = DB_GET_BOTH_RANGE;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
     break;
-  case 'E':
-    if (memEQ(name, "DB_ENV_REP_CLIENT", 17)) {
-    /*                             ^         */
-#ifdef DB_ENV_REP_CLIENT
-      *iv_return = DB_ENV_REP_CLIENT;
+  case 'C':
+    if (memEQ(name, "DB_STAT_LOCK_CONF", 17)) {
+    /*                            ^          */
+#ifdef DB_STAT_LOCK_CONF
+      *iv_return = DB_STAT_LOCK_CONF;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_LOG_SILENT_ERR", 17)) {
-    /*                             ^         */
-#ifdef DB_LOG_SILENT_ERR
-      *iv_return = DB_LOG_SILENT_ERR;
+    break;
+  case 'H':
+    if (memEQ(name, "DB_STAT_MEMP_HASH", 17)) {
+    /*                            ^          */
+#ifdef DB_STAT_MEMP_HASH
+      *iv_return = DB_STAT_MEMP_HASH;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_RPC_SERVERVERS", 17)) {
-    /*                             ^         */
-#ifdef DB_RPC_SERVERVERS
-      *iv_return = DB_RPC_SERVERVERS;
+    break;
+  case 'I':
+    if (memEQ(name, "DB_ENV_REP_CLIENT", 17)) {
+    /*                            ^          */
+#ifdef DB_ENV_REP_CLIENT
+      *iv_return = DB_ENV_REP_CLIENT;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_TEST_ELECTSEND", 17)) {
-    /*                             ^         */
-#ifdef DB_TEST_ELECTSEND
-      *iv_return = DB_TEST_ELECTSEND;
+    if (memEQ(name, "DB_TEST_ELECTINIT", 17)) {
+    /*                            ^          */
+#ifdef DB_TEST_ELECTINIT
+      *iv_return = DB_TEST_ELECTINIT;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    break;
-  case 'I':
-    if (memEQ(name, "DB_VERSION_STRING", 17)) {
-    /*                             ^         */
-#ifdef DB_VERSION_STRING
-      *pv_return = DB_VERSION_STRING;
-      return PERL_constant_ISPV;
+    if (memEQ(name, "DB_TXN_POPENFILES", 17)) {
+    /*                            ^          */
+#if (DB_VERSION_MAJOR > 3) || \
+    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 3) || \
+    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3 && \
+     DB_VERSION_PATCH >= 11)
+      *iv_return = DB_TXN_POPENFILES;
+      return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
     break;
   case 'L':
-    if (memEQ(name, "DB_ENV_DIRECT_LOG", 17)) {
-    /*                             ^         */
-#ifdef DB_ENV_DIRECT_LOG
-      *iv_return = DB_ENV_DIRECT_LOG;
+    if (memEQ(name, "DB_ENV_STANDALONE", 17)) {
+    /*                            ^          */
+#ifdef DB_ENV_STANDALONE
+      *iv_return = DB_ENV_STANDALONE;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
     if (memEQ(name, "DB_ENV_USER_ALLOC", 17)) {
-    /*                             ^         */
+    /*                            ^          */
 #ifdef DB_ENV_USER_ALLOC
       *iv_return = DB_ENV_USER_ALLOC;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
-#endif
-    }
-    if (memEQ(name, "DB_TXN_POPENFILES", 17)) {
-    /*                             ^         */
-#if (DB_VERSION_MAJOR > 3) || \
-    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 3) || \
-    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3 && \
-     DB_VERSION_PATCH >= 4)
-      *iv_return = DB_TXN_POPENFILES;
-      return PERL_constant_ISIV;
-#else
-      return PERL_constant_NOTDEF;
 #endif
     }
     break;
   case 'M':
-    if (memEQ(name, "DB_ENV_SYSTEM_MEM", 17)) {
-    /*                             ^         */
-#ifdef DB_ENV_SYSTEM_MEM
-      *iv_return = DB_ENV_SYSTEM_MEM;
+    if (memEQ(name, "DB_LOG_AUTOREMOVE", 17)) {
+    /*                            ^          */
+#ifdef DB_LOG_AUTOREMOVE
+      *iv_return = DB_LOG_AUTOREMOVE;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    break;
-  case 'N':
-    if (memEQ(name, "DB_GET_BOTH_RANGE", 17)) {
-    /*                             ^         */
-#ifdef DB_GET_BOTH_RANGE
-      *iv_return = DB_GET_BOTH_RANGE;
+    if (memEQ(name, "DB_NO_AUTO_COMMIT", 17)) {
+    /*                            ^          */
+#ifdef DB_NO_AUTO_COMMIT
+      *iv_return = DB_NO_AUTO_COMMIT;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_TEST_ELECTINIT", 17)) {
-    /*                             ^         */
-#ifdef DB_TEST_ELECTINIT
-      *iv_return = DB_TEST_ELECTINIT;
+    break;
+  case 'N':
+    if (memEQ(name, "DB_TEST_PRERENAME", 17)) {
+    /*                            ^          */
+#ifdef DB_TEST_PRERENAME
+      *iv_return = DB_TEST_PRERENAME;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
     break;
-  case 'O':
-    if (memEQ(name, "DB_ENV_STANDALONE", 17)) {
-    /*                             ^         */
-#ifdef DB_ENV_STANDALONE
-      *iv_return = DB_ENV_STANDALONE;
+  case 'P':
+    if (memEQ(name, "DB_RPC_SERVERPROG", 17)) {
+    /*                            ^          */
+#ifdef DB_RPC_SERVERPROG
+      *iv_return = DB_RPC_SERVERPROG;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
@@ -3215,19 +3529,19 @@ constant_17 (pTHX_ const char *name, IV *iv_return, const char **pv_return) {
     }
     break;
   case 'R':
-    if (memEQ(name, "DB_RPC_SERVERPROG", 17)) {
-    /*                             ^         */
-#ifdef DB_RPC_SERVERPROG
-      *iv_return = DB_RPC_SERVERPROG;
-      return PERL_constant_ISIV;
+    if (memEQ(name, "DB_VERSION_STRING", 17)) {
+    /*                            ^          */
+#ifdef DB_VERSION_STRING
+      *pv_return = DB_VERSION_STRING;
+      return PERL_constant_ISPV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
     break;
-  case 'T':
+  case 'S':
     if (memEQ(name, "DB_ENV_REP_MASTER", 17)) {
-    /*                             ^         */
+    /*                            ^          */
 #ifdef DB_ENV_REP_MASTER
       *iv_return = DB_ENV_REP_MASTER;
       return PERL_constant_ISIV;
@@ -3235,15 +3549,71 @@ constant_17 (pTHX_ const char *name, IV *iv_return, const char **pv_return) {
       return PERL_constant_NOTDEF;
 #endif
     }
-    break;
-  case 'Y':
     if (memEQ(name, "DB_ENV_TXN_NOSYNC", 17)) {
-    /*                             ^         */
+    /*                            ^          */
 #ifdef DB_ENV_TXN_NOSYNC
       *iv_return = DB_ENV_TXN_NOSYNC;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_STAT_SUBSYSTEM", 17)) {
+    /*                            ^          */
+#ifdef DB_STAT_SUBSYSTEM
+      *iv_return = DB_STAT_SUBSYSTEM;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_TEST_ELECTSEND", 17)) {
+    /*                            ^          */
+#ifdef DB_TEST_ELECTSEND
+      *iv_return = DB_TEST_ELECTSEND;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 'V':
+    if (memEQ(name, "DB_RPC_SERVERVERS", 17)) {
+    /*                            ^          */
+#ifdef DB_RPC_SERVERVERS
+      *iv_return = DB_RPC_SERVERVERS;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case '_':
+    if (memEQ(name, "DB_ENV_DIRECT_LOG", 17)) {
+    /*                            ^          */
+#ifdef DB_ENV_DIRECT_LOG
+      *iv_return = DB_ENV_DIRECT_LOG;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_ENV_SYSTEM_MEM", 17)) {
+    /*                            ^          */
+#ifdef DB_ENV_SYSTEM_MEM
+      *iv_return = DB_ENV_SYSTEM_MEM;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_LOG_SILENT_ERR", 17)) {
+    /*                            ^          */
+#ifdef DB_LOG_SILENT_ERR
+      *iv_return = DB_LOG_SILENT_ERR;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
 #endif
     }
     break;
@@ -3255,11 +3625,13 @@ static int
 constant_18 (pTHX_ const char *name, IV *iv_return) {
   /* When generated this function returned values for the list of names given
      here.  However, subsequent manual editing may have added or removed some.
-     DB_ALREADY_ABORTED DB_ENV_AUTO_COMMIT DB_ENV_OPEN_CALLED
-     DB_ENV_REGION_INIT DB_LOCK_NOTGRANTED DB_MPOOL_NEW_GROUP
-     DB_PR_RECOVERYTEST DB_SET_TXN_TIMEOUT DB_TEST_ELECTVOTE1
-     DB_TEST_ELECTVOTE2 DB_TEST_ELECTWAIT1 DB_TEST_ELECTWAIT2
-     DB_TEST_POSTRENAME DB_TEST_PREDESTROY DB_TEST_PREEXTOPEN */
+     DB_ALREADY_ABORTED DB_DURABLE_UNKNOWN DB_ENV_AUTO_COMMIT
+     DB_ENV_OPEN_CALLED DB_ENV_REGION_INIT DB_LOCK_NOTGRANTED
+     DB_LOG_BUFFER_FULL DB_LOG_NOT_DURABLE DB_MPOOL_NEW_GROUP
+     DB_PR_RECOVERYTEST DB_REP_HANDLE_DEAD DB_REP_STARTUPDONE
+     DB_SET_TXN_TIMEOUT DB_TEST_ELECTVOTE1 DB_TEST_ELECTVOTE2
+     DB_TEST_ELECTWAIT1 DB_TEST_ELECTWAIT2 DB_TEST_POSTRENAME
+     DB_TEST_PREDESTROY DB_TIME_NOTGRANTED DB_TXN_NOT_DURABLE */
   /* Offset 13 gives the best switch position.  */
   switch (name[13]) {
   case 'A':
@@ -3279,6 +3651,15 @@ constant_18 (pTHX_ const char *name, IV *iv_return) {
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_TIME_NOTGRANTED", 18)) {
+    /*                            ^           */
+#ifdef DB_TIME_NOTGRANTED
+      *iv_return = DB_TIME_NOTGRANTED;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
 #endif
     }
     break;
@@ -3301,6 +3682,17 @@ constant_18 (pTHX_ const char *name, IV *iv_return) {
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 'K':
+    if (memEQ(name, "DB_DURABLE_UNKNOWN", 18)) {
+    /*                            ^           */
+#ifdef DB_DURABLE_UNKNOWN
+      *iv_return = DB_DURABLE_UNKNOWN;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
 #endif
     }
     break;
@@ -3335,22 +3727,42 @@ constant_18 (pTHX_ const char *name, IV *iv_return) {
 #endif
     }
     break;
-  case 'S':
-    if (memEQ(name, "DB_TEST_PREDESTROY", 18)) {
+  case 'P':
+    if (memEQ(name, "DB_REP_STARTUPDONE", 18)) {
     /*                            ^           */
-#ifdef DB_TEST_PREDESTROY
-      *iv_return = DB_TEST_PREDESTROY;
+#ifdef DB_REP_STARTUPDONE
+      *iv_return = DB_REP_STARTUPDONE;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
     break;
-  case 'T':
-    if (memEQ(name, "DB_TEST_PREEXTOPEN", 18)) {
+  case 'R':
+    if (memEQ(name, "DB_LOG_NOT_DURABLE", 18)) {
+    /*                            ^           */
+#ifdef DB_LOG_NOT_DURABLE
+      *iv_return = DB_LOG_NOT_DURABLE;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_TXN_NOT_DURABLE", 18)) {
     /*                            ^           */
-#ifdef DB_TEST_PREEXTOPEN
-      *iv_return = DB_TEST_PREEXTOPEN;
+#ifdef DB_TXN_NOT_DURABLE
+      *iv_return = DB_TXN_NOT_DURABLE;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 'S':
+    if (memEQ(name, "DB_TEST_PREDESTROY", 18)) {
+    /*                            ^           */
+#ifdef DB_TEST_PREDESTROY
+      *iv_return = DB_TEST_PREDESTROY;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
@@ -3416,6 +3828,24 @@ constant_18 (pTHX_ const char *name, IV *iv_return) {
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_LOG_BUFFER_FULL", 18)) {
+    /*                            ^           */
+#ifdef DB_LOG_BUFFER_FULL
+      *iv_return = DB_LOG_BUFFER_FULL;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    if (memEQ(name, "DB_REP_HANDLE_DEAD", 18)) {
+    /*                            ^           */
+#ifdef DB_REP_HANDLE_DEAD
+      *iv_return = DB_REP_HANDLE_DEAD;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
 #endif
     }
     break;
@@ -3427,15 +3857,25 @@ static int
 constant_19 (pTHX_ const char *name, IV *iv_return) {
   /* When generated this function returned values for the list of names given
      here.  However, subsequent manual editing may have added or removed some.
-     DB_ENV_REP_LOGSONLY DB_LOCK_FREE_LOCKER DB_LOCK_GET_TIMEOUT
-     DB_LOCK_SET_TIMEOUT DB_PRIORITY_DEFAULT DB_REP_HOLDELECTION
-     DB_SET_LOCK_TIMEOUT DB_TEST_POSTDESTROY DB_TEST_POSTEXTOPEN
-     DB_TEST_POSTLOGMETA DB_TEST_SUBDB_LOCKS DB_TXN_FORWARD_ROLL
-     DB_TXN_LOG_UNDOREDO DB_TXN_WRITE_NOSYNC DB_UNRESOLVED_CHILD
-     DB_UPDATE_SECONDARY DB_USE_ENVIRON_ROOT DB_VERB_REPLICATION */
+     DB_ENV_LOG_INMEMORY DB_ENV_REP_LOGSONLY DB_LOCK_FREE_LOCKER
+     DB_LOCK_GET_TIMEOUT DB_LOCK_SET_TIMEOUT DB_PRIORITY_DEFAULT
+     DB_REP_HOLDELECTION DB_SEQUENCE_VERSION DB_SET_LOCK_TIMEOUT
+     DB_STAT_LOCK_PARAMS DB_TEST_POSTDESTROY DB_TEST_POSTLOGMETA
+     DB_TEST_SUBDB_LOCKS DB_TXN_FORWARD_ROLL DB_TXN_LOG_UNDOREDO
+     DB_TXN_WRITE_NOSYNC DB_UPDATE_SECONDARY DB_USE_ENVIRON_ROOT
+     DB_VERB_REPLICATION DB_VERSION_MISMATCH */
   /* Offset 9 gives the best switch position.  */
   switch (name[9]) {
   case 'C':
+    if (memEQ(name, "DB_SEQUENCE_VERSION", 19)) {
+    /*                        ^                */
+#ifdef DB_SEQUENCE_VERSION
+      *iv_return = DB_SEQUENCE_VERSION;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
     if (memEQ(name, "DB_SET_LOCK_TIMEOUT", 19)) {
     /*                        ^                */
 #ifdef DB_SET_LOCK_TIMEOUT
@@ -3452,7 +3892,7 @@ constant_19 (pTHX_ const char *name, IV *iv_return) {
 #if (DB_VERSION_MAJOR > 4) || \
     (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \
     (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \
-     DB_VERSION_PATCH >= 7)
+     DB_VERSION_PATCH >= 14)
       *iv_return = DB_LOCK_GET_TIMEOUT;
       return PERL_constant_ISIV;
 #else
@@ -3479,6 +3919,15 @@ constant_19 (pTHX_ const char *name, IV *iv_return) {
     }
     break;
   case 'G':
+    if (memEQ(name, "DB_ENV_LOG_INMEMORY", 19)) {
+    /*                        ^                */
+#ifdef DB_ENV_LOG_INMEMORY
+      *iv_return = DB_ENV_LOG_INMEMORY;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
     if (memEQ(name, "DB_TXN_LOG_UNDOREDO", 19)) {
     /*                        ^                */
 #ifdef DB_TXN_LOG_UNDOREDO
@@ -3510,10 +3959,12 @@ constant_19 (pTHX_ const char *name, IV *iv_return) {
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_UNRESOLVED_CHILD", 19)) {
+    break;
+  case 'N':
+    if (memEQ(name, "DB_VERSION_MISMATCH", 19)) {
     /*                        ^                */
-#ifdef DB_UNRESOLVED_CHILD
-      *iv_return = DB_UNRESOLVED_CHILD;
+#ifdef DB_VERSION_MISMATCH
+      *iv_return = DB_VERSION_MISMATCH;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
@@ -3521,19 +3972,19 @@ constant_19 (pTHX_ const char *name, IV *iv_return) {
     }
     break;
   case 'O':
-    if (memEQ(name, "DB_TEST_POSTDESTROY", 19)) {
+    if (memEQ(name, "DB_STAT_LOCK_PARAMS", 19)) {
     /*                        ^                */
-#ifdef DB_TEST_POSTDESTROY
-      *iv_return = DB_TEST_POSTDESTROY;
+#ifdef DB_STAT_LOCK_PARAMS
+      *iv_return = DB_STAT_LOCK_PARAMS;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_TEST_POSTEXTOPEN", 19)) {
+    if (memEQ(name, "DB_TEST_POSTDESTROY", 19)) {
     /*                        ^                */
-#ifdef DB_TEST_POSTEXTOPEN
-      *iv_return = DB_TEST_POSTEXTOPEN;
+#ifdef DB_TEST_POSTDESTROY
+      *iv_return = DB_TEST_POSTDESTROY;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
@@ -3575,7 +4026,7 @@ constant_19 (pTHX_ const char *name, IV *iv_return) {
 #if (DB_VERSION_MAJOR > 3) || \
     (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \
     (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \
-     DB_VERSION_PATCH >= 12)
+     DB_VERSION_PATCH >= 14)
       *iv_return = DB_TXN_FORWARD_ROLL;
       return PERL_constant_ISIV;
 #else
@@ -3589,7 +4040,7 @@ constant_19 (pTHX_ const char *name, IV *iv_return) {
 #if (DB_VERSION_MAJOR > 4) || \
     (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \
     (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \
-     DB_VERSION_PATCH >= 17)
+     DB_VERSION_PATCH >= 24)
       *iv_return = DB_PRIORITY_DEFAULT;
       return PERL_constant_ISIV;
 #else
@@ -3639,47 +4090,46 @@ constant_20 (pTHX_ const char *name, IV *iv_return) {
   /* When generated this function returned values for the list of names given
      here.  However, subsequent manual editing may have added or removed some.
      DB_CXX_NO_EXCEPTIONS DB_LOGFILEID_INVALID DB_PANIC_ENVIRONMENT
-     DB_PRIORITY_VERY_LOW DB_TEST_PREEXTDELETE DB_TEST_PREEXTUNLINK
+     DB_PRIORITY_VERY_LOW DB_STAT_LOCK_LOCKERS DB_STAT_LOCK_OBJECTS
      DB_TXN_BACKWARD_ROLL DB_TXN_LOCK_OPTIMIST */
-  /* Offset 14 gives the best switch position.  */
-  switch (name[14]) {
-  case 'D':
-    if (memEQ(name, "DB_TEST_PREEXTDELETE", 20)) {
-    /*                             ^            */
-#ifdef DB_TEST_PREEXTDELETE
-      *iv_return = DB_TEST_PREEXTDELETE;
+  /* Offset 15 gives the best switch position.  */
+  switch (name[15]) {
+  case 'C':
+    if (memEQ(name, "DB_STAT_LOCK_LOCKERS", 20)) {
+    /*                              ^           */
+#ifdef DB_STAT_LOCK_LOCKERS
+      *iv_return = DB_STAT_LOCK_LOCKERS;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
-    if (memEQ(name, "DB_TXN_BACKWARD_ROLL", 20)) {
-    /*                             ^            */
-#if (DB_VERSION_MAJOR > 3) || \
-    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \
-    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \
-     DB_VERSION_PATCH >= 12)
-      *iv_return = DB_TXN_BACKWARD_ROLL;
+    break;
+  case 'I':
+    if (memEQ(name, "DB_TXN_LOCK_OPTIMIST", 20)) {
+    /*                              ^           */
+#ifdef DB_TXN_LOCK_OPTIMIST
+      *iv_return = DB_TXN_LOCK_OPTIMIST;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
     break;
-  case 'N':
-    if (memEQ(name, "DB_LOGFILEID_INVALID", 20)) {
-    /*                             ^            */
-#ifdef DB_LOGFILEID_INVALID
-      *iv_return = DB_LOGFILEID_INVALID;
+  case 'J':
+    if (memEQ(name, "DB_STAT_LOCK_OBJECTS", 20)) {
+    /*                              ^           */
+#ifdef DB_STAT_LOCK_OBJECTS
+      *iv_return = DB_STAT_LOCK_OBJECTS;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
     break;
-  case 'O':
+  case 'N':
     if (memEQ(name, "DB_PANIC_ENVIRONMENT", 20)) {
-    /*                             ^            */
+    /*                              ^           */
 #ifdef DB_PANIC_ENVIRONMENT
       *iv_return = DB_PANIC_ENVIRONMENT;
       return PERL_constant_ISIV;
@@ -3688,9 +4138,9 @@ constant_20 (pTHX_ const char *name, IV *iv_return) {
 #endif
     }
     break;
-  case 'P':
+  case 'T':
     if (memEQ(name, "DB_CXX_NO_EXCEPTIONS", 20)) {
-    /*                             ^            */
+    /*                              ^           */
 #ifdef DB_CXX_NO_EXCEPTIONS
       *iv_return = DB_CXX_NO_EXCEPTIONS;
       return PERL_constant_ISIV;
@@ -3699,36 +4149,39 @@ constant_20 (pTHX_ const char *name, IV *iv_return) {
 #endif
     }
     break;
-  case 'R':
-    if (memEQ(name, "DB_PRIORITY_VERY_LOW", 20)) {
-    /*                             ^            */
-#if (DB_VERSION_MAJOR > 4) || \
-    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \
-    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \
-     DB_VERSION_PATCH >= 17)
-      *iv_return = DB_PRIORITY_VERY_LOW;
+  case 'V':
+    if (memEQ(name, "DB_LOGFILEID_INVALID", 20)) {
+    /*                              ^           */
+#ifdef DB_LOGFILEID_INVALID
+      *iv_return = DB_LOGFILEID_INVALID;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
     break;
-  case 'T':
-    if (memEQ(name, "DB_TXN_LOCK_OPTIMIST", 20)) {
-    /*                             ^            */
-#ifdef DB_TXN_LOCK_OPTIMIST
-      *iv_return = DB_TXN_LOCK_OPTIMIST;
+  case 'Y':
+    if (memEQ(name, "DB_PRIORITY_VERY_LOW", 20)) {
+    /*                              ^           */
+#if (DB_VERSION_MAJOR > 4) || \
+    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \
+    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \
+     DB_VERSION_PATCH >= 24)
+      *iv_return = DB_PRIORITY_VERY_LOW;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
     break;
-  case 'U':
-    if (memEQ(name, "DB_TEST_PREEXTUNLINK", 20)) {
-    /*                             ^            */
-#ifdef DB_TEST_PREEXTUNLINK
-      *iv_return = DB_TEST_PREEXTUNLINK;
+  case '_':
+    if (memEQ(name, "DB_TXN_BACKWARD_ROLL", 20)) {
+    /*                              ^           */
+#if (DB_VERSION_MAJOR > 3) || \
+    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \
+    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \
+     DB_VERSION_PATCH >= 14)
+      *iv_return = DB_TXN_BACKWARD_ROLL;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
@@ -3743,17 +4196,56 @@ static int
 constant_21 (pTHX_ const char *name, IV *iv_return) {
   /* When generated this function returned values for the list of names given
      here.  However, subsequent manual editing may have added or removed some.
-     DB_LOCK_UPGRADE_WRITE DB_PRIORITY_VERY_HIGH DB_TEST_POSTEXTDELETE
-     DB_TEST_POSTEXTUNLINK DB_TXN_BACKWARD_ALLOC */
-  /* Offset 16 gives the best switch position.  */
-  switch (name[16]) {
-  case 'A':
+     DB_ENV_LOG_AUTOREMOVE DB_LOCK_UPGRADE_WRITE DB_PRIORITY_VERY_HIGH
+     DB_TXN_BACKWARD_ALLOC */
+  /* Offset 4 gives the best switch position.  */
+  switch (name[4]) {
+  case 'N':
+    if (memEQ(name, "DB_ENV_LOG_AUTOREMOVE", 21)) {
+    /*                   ^                       */
+#ifdef DB_ENV_LOG_AUTOREMOVE
+      *iv_return = DB_ENV_LOG_AUTOREMOVE;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 'O':
+    if (memEQ(name, "DB_LOCK_UPGRADE_WRITE", 21)) {
+    /*                   ^                       */
+#if (DB_VERSION_MAJOR > 3) || \
+    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 3) || \
+    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3 && \
+     DB_VERSION_PATCH >= 11)
+      *iv_return = DB_LOCK_UPGRADE_WRITE;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 'R':
+    if (memEQ(name, "DB_PRIORITY_VERY_HIGH", 21)) {
+    /*                   ^                       */
+#if (DB_VERSION_MAJOR > 4) || \
+    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \
+    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \
+     DB_VERSION_PATCH >= 24)
+      *iv_return = DB_PRIORITY_VERY_HIGH;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 'X':
     if (memEQ(name, "DB_TXN_BACKWARD_ALLOC", 21)) {
-    /*                               ^           */
+    /*                   ^                       */
 #if (DB_VERSION_MAJOR > 4) || \
     (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \
     (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \
-     DB_VERSION_PATCH >= 17)
+     DB_VERSION_PATCH >= 24)
       *iv_return = DB_TXN_BACKWARD_ALLOC;
       return PERL_constant_ISIV;
 #else
@@ -3761,50 +4253,56 @@ constant_21 (pTHX_ const char *name, IV *iv_return) {
 #endif
     }
     break;
-  case 'E':
-    if (memEQ(name, "DB_TEST_POSTEXTDELETE", 21)) {
-    /*                               ^           */
-#ifdef DB_TEST_POSTEXTDELETE
-      *iv_return = DB_TEST_POSTEXTDELETE;
+  }
+  return PERL_constant_NOTFOUND;
+}
+
+static int
+constant_22 (pTHX_ const char *name, IV *iv_return) {
+  /* When generated this function returned values for the list of names given
+     here.  However, subsequent manual editing may have added or removed some.
+     DB_ENV_RPCCLIENT_GIVEN DB_ENV_TIME_NOTGRANTED DB_ENV_TXN_NOT_DURABLE
+     DB_TXN_LOCK_OPTIMISTIC */
+  /* Offset 21 gives the best switch position.  */
+  switch (name[21]) {
+  case 'C':
+    if (memEQ(name, "DB_TXN_LOCK_OPTIMISTI", 21)) {
+    /*                                    C      */
+#ifdef DB_TXN_LOCK_OPTIMISTIC
+      *iv_return = DB_TXN_LOCK_OPTIMISTIC;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
     break;
-  case 'N':
-    if (memEQ(name, "DB_TEST_POSTEXTUNLINK", 21)) {
-    /*                               ^           */
-#ifdef DB_TEST_POSTEXTUNLINK
-      *iv_return = DB_TEST_POSTEXTUNLINK;
+  case 'D':
+    if (memEQ(name, "DB_ENV_TIME_NOTGRANTE", 21)) {
+    /*                                    D      */
+#ifdef DB_ENV_TIME_NOTGRANTED
+      *iv_return = DB_ENV_TIME_NOTGRANTED;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
     break;
-  case 'W':
-    if (memEQ(name, "DB_LOCK_UPGRADE_WRITE", 21)) {
-    /*                               ^           */
-#if (DB_VERSION_MAJOR > 3) || \
-    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 3) || \
-    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3 && \
-     DB_VERSION_PATCH >= 4)
-      *iv_return = DB_LOCK_UPGRADE_WRITE;
+  case 'E':
+    if (memEQ(name, "DB_ENV_TXN_NOT_DURABL", 21)) {
+    /*                                    E      */
+#ifdef DB_ENV_TXN_NOT_DURABLE
+      *iv_return = DB_ENV_TXN_NOT_DURABLE;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
 #endif
     }
     break;
-  case '_':
-    if (memEQ(name, "DB_PRIORITY_VERY_HIGH", 21)) {
-    /*                               ^           */
-#if (DB_VERSION_MAJOR > 4) || \
-    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \
-    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \
-     DB_VERSION_PATCH >= 17)
-      *iv_return = DB_PRIORITY_VERY_HIGH;
+  case 'N':
+    if (memEQ(name, "DB_ENV_RPCCLIENT_GIVE", 21)) {
+    /*                                    N      */
+#ifdef DB_ENV_RPCCLIENT_GIVEN
+      *iv_return = DB_ENV_RPCCLIENT_GIVEN;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
@@ -3828,53 +4326,60 @@ constant (pTHX_ const char *name, STRLEN len, IV *iv_return, const char **pv_ret
      Regenerate these constant functions by feeding this entire source file to
      perl -x
 
-#!/home/paul/perl/install/redhat6.1/5.8.0/bin/perl5.8.0 -w
+#!/usr/bin/perl5.8.3 -w
 use ExtUtils::Constant qw (constant_types C_constant XS_constant);
 
 my $types = {map {($_, 1)} qw(IV PV)};
 my @names = (qw(DB_AFTER DB_AGGRESSIVE DB_ALREADY_ABORTED DB_APPEND
 	       DB_APPLY_LOGREG DB_APP_INIT DB_ARCH_ABS DB_ARCH_DATA DB_ARCH_LOG
-	       DB_AUTO_COMMIT DB_BEFORE DB_BROADCAST_EID DB_BTREEMAGIC
-	       DB_BTREEOLDVER DB_BTREEVERSION DB_CACHED_COUNTS DB_CDB_ALLDB
-	       DB_CHECKPOINT DB_CHKSUM_SHA1 DB_CLIENT DB_CL_WRITER DB_COMMIT
-	       DB_CONSUME DB_CONSUME_WAIT DB_CREATE DB_CURLSN DB_CURRENT
-	       DB_CXX_NO_EXCEPTIONS DB_DELETED DB_DELIMITER DB_DIRECT
-	       DB_DIRECT_DB DB_DIRECT_LOG DB_DIRTY_READ DB_DONOTINDEX DB_DUP
-	       DB_DUPCURSOR DB_DUPSORT DB_EID_BROADCAST DB_EID_INVALID
-	       DB_ENCRYPT DB_ENCRYPT_AES DB_ENV_APPINIT DB_ENV_AUTO_COMMIT
-	       DB_ENV_CDB DB_ENV_CDB_ALLDB DB_ENV_CREATE DB_ENV_DBLOCAL
-	       DB_ENV_DIRECT_DB DB_ENV_DIRECT_LOG DB_ENV_FATAL DB_ENV_LOCKDOWN
-	       DB_ENV_LOCKING DB_ENV_LOGGING DB_ENV_NOLOCKING DB_ENV_NOMMAP
+	       DB_ARCH_REMOVE DB_AUTO_COMMIT DB_BEFORE DB_BTREEMAGIC
+	       DB_BTREEOLDVER DB_BTREEVERSION DB_BUFFER_SMALL DB_CACHED_COUNTS
+	       DB_CDB_ALLDB DB_CHECKPOINT DB_CHKSUM DB_CHKSUM_SHA1 DB_CLIENT
+	       DB_CL_WRITER DB_COMMIT DB_CONSUME DB_CONSUME_WAIT DB_CREATE
+	       DB_CURLSN DB_CURRENT DB_CXX_NO_EXCEPTIONS DB_DEGREE_2 DB_DELETED
+	       DB_DELIMITER DB_DIRECT DB_DIRECT_DB DB_DIRECT_LOG DB_DIRTY_READ
+	       DB_DONOTINDEX DB_DSYNC_LOG DB_DUP DB_DUPCURSOR DB_DUPSORT
+	       DB_DURABLE_UNKNOWN DB_EID_BROADCAST DB_EID_INVALID DB_ENCRYPT
+	       DB_ENCRYPT_AES DB_ENV_APPINIT DB_ENV_AUTO_COMMIT DB_ENV_CDB
+	       DB_ENV_CDB_ALLDB DB_ENV_CREATE DB_ENV_DBLOCAL DB_ENV_DIRECT_DB
+	       DB_ENV_DIRECT_LOG DB_ENV_DSYNC_LOG DB_ENV_FATAL DB_ENV_LOCKDOWN
+	       DB_ENV_LOCKING DB_ENV_LOGGING DB_ENV_LOG_AUTOREMOVE
+	       DB_ENV_LOG_INMEMORY DB_ENV_NOLOCKING DB_ENV_NOMMAP
 	       DB_ENV_NOPANIC DB_ENV_OPEN_CALLED DB_ENV_OVERWRITE
 	       DB_ENV_PANIC_OK DB_ENV_PRIVATE DB_ENV_REGION_INIT
 	       DB_ENV_REP_CLIENT DB_ENV_REP_LOGSONLY DB_ENV_REP_MASTER
 	       DB_ENV_RPCCLIENT DB_ENV_RPCCLIENT_GIVEN DB_ENV_STANDALONE
-	       DB_ENV_SYSTEM_MEM DB_ENV_THREAD DB_ENV_TXN DB_ENV_TXN_NOSYNC
+	       DB_ENV_SYSTEM_MEM DB_ENV_THREAD DB_ENV_TIME_NOTGRANTED
+	       DB_ENV_TXN DB_ENV_TXN_NOSYNC DB_ENV_TXN_NOT_DURABLE
 	       DB_ENV_TXN_WRITE_NOSYNC DB_ENV_USER_ALLOC DB_ENV_YIELDCPU
-	       DB_EXCL DB_EXTENT DB_FAST_STAT DB_FCNTL_LOCKING DB_FILE_ID_LEN
-	       DB_FIRST DB_FIXEDLEN DB_FLUSH DB_FORCE DB_GETREC DB_GET_BOTH
-	       DB_GET_BOTHC DB_GET_BOTH_RANGE DB_GET_RECNO DB_HANDLE_LOCK
-	       DB_HASHMAGIC DB_HASHOLDVER DB_HASHVERSION DB_INCOMPLETE
-	       DB_INIT_CDB DB_INIT_LOCK DB_INIT_LOG DB_INIT_MPOOL DB_INIT_TXN
-	       DB_INVALID_EID DB_JAVA_CALLBACK DB_JOINENV DB_JOIN_ITEM
-	       DB_JOIN_NOSORT DB_KEYEMPTY DB_KEYEXIST DB_KEYFIRST DB_KEYLAST
-	       DB_LAST DB_LOCKDOWN DB_LOCKMAGIC DB_LOCKVERSION DB_LOCK_CONFLICT
-	       DB_LOCK_DEADLOCK DB_LOCK_DEFAULT DB_LOCK_EXPIRE
-	       DB_LOCK_FREE_LOCKER DB_LOCK_MAXLOCKS DB_LOCK_MINLOCKS
-	       DB_LOCK_MINWRITE DB_LOCK_NORUN DB_LOCK_NOTEXIST
-	       DB_LOCK_NOTGRANTED DB_LOCK_NOTHELD DB_LOCK_NOWAIT DB_LOCK_OLDEST
-	       DB_LOCK_RANDOM DB_LOCK_RECORD DB_LOCK_REMOVE DB_LOCK_RIW_N
-	       DB_LOCK_RW_N DB_LOCK_SET_TIMEOUT DB_LOCK_SWITCH DB_LOCK_UPGRADE
-	       DB_LOCK_YOUNGEST DB_LOGC_BUF_SIZE DB_LOGFILEID_INVALID
-	       DB_LOGMAGIC DB_LOGOLDVER DB_LOGVERSION DB_LOG_DISK DB_LOG_LOCKED
-	       DB_LOG_SILENT_ERR DB_MAX_PAGES DB_MAX_RECORDS DB_MPOOL_CLEAN
+	       DB_EXCL DB_EXTENT DB_FAST_STAT DB_FCNTL_LOCKING DB_FILEOPEN
+	       DB_FILE_ID_LEN DB_FIRST DB_FIXEDLEN DB_FLUSH DB_FORCE DB_GETREC
+	       DB_GET_BOTH DB_GET_BOTHC DB_GET_BOTH_RANGE DB_GET_RECNO
+	       DB_HANDLE_LOCK DB_HASHMAGIC DB_HASHOLDVER DB_HASHVERSION
+	       DB_INCOMPLETE DB_INIT_CDB DB_INIT_LOCK DB_INIT_LOG DB_INIT_MPOOL
+	       DB_INIT_REP DB_INIT_TXN DB_INORDER DB_JAVA_CALLBACK DB_JOINENV
+	       DB_JOIN_ITEM DB_JOIN_NOSORT DB_KEYEMPTY DB_KEYEXIST DB_KEYFIRST
+	       DB_KEYLAST DB_LAST DB_LOCKDOWN DB_LOCKMAGIC DB_LOCKVERSION
+	       DB_LOCK_ABORT DB_LOCK_CONFLICT DB_LOCK_DEADLOCK DB_LOCK_DEFAULT
+	       DB_LOCK_EXPIRE DB_LOCK_FREE_LOCKER DB_LOCK_MAXLOCKS
+	       DB_LOCK_MAXWRITE DB_LOCK_MINLOCKS DB_LOCK_MINWRITE DB_LOCK_NORUN
+	       DB_LOCK_NOTEXIST DB_LOCK_NOTGRANTED DB_LOCK_NOTHELD
+	       DB_LOCK_NOWAIT DB_LOCK_OLDEST DB_LOCK_RANDOM DB_LOCK_RECORD
+	       DB_LOCK_REMOVE DB_LOCK_RIW_N DB_LOCK_RW_N DB_LOCK_SET_TIMEOUT
+	       DB_LOCK_SWITCH DB_LOCK_UPGRADE DB_LOCK_YOUNGEST DB_LOGC_BUF_SIZE
+	       DB_LOGFILEID_INVALID DB_LOGMAGIC DB_LOGOLDVER DB_LOGVERSION
+	       DB_LOG_AUTOREMOVE DB_LOG_BUFFER_FULL DB_LOG_CHKPNT DB_LOG_COMMIT
+	       DB_LOG_DISK DB_LOG_INMEMORY DB_LOG_LOCKED DB_LOG_NOCOPY
+	       DB_LOG_NOT_DURABLE DB_LOG_PERM DB_LOG_RESEND DB_LOG_SILENT_ERR
+	       DB_LOG_WRNOSYNC DB_MAX_PAGES DB_MAX_RECORDS DB_MPOOL_CLEAN
 	       DB_MPOOL_CREATE DB_MPOOL_DIRTY DB_MPOOL_DISCARD DB_MPOOL_EXTENT
-	       DB_MPOOL_LAST DB_MPOOL_NEW DB_MPOOL_NEW_GROUP DB_MPOOL_PRIVATE
-	       DB_MULTIPLE DB_MULTIPLE_KEY DB_MUTEXDEBUG DB_MUTEXLOCKS
-	       DB_NEEDSPLIT DB_NEXT DB_NEXT_DUP DB_NEXT_NODUP DB_NOCOPY
-	       DB_NODUPDATA DB_NOLOCKING DB_NOMMAP DB_NOORDERCHK DB_NOOVERWRITE
-	       DB_NOPANIC DB_NORECURSE DB_NOSERVER DB_NOSERVER_HOME
-	       DB_NOSERVER_ID DB_NOSYNC DB_NOTFOUND DB_ODDFILESIZE DB_OK_BTREE
+	       DB_MPOOL_FREE DB_MPOOL_LAST DB_MPOOL_NEW DB_MPOOL_NEW_GROUP
+	       DB_MPOOL_NOFILE DB_MPOOL_PRIVATE DB_MPOOL_UNLINK DB_MULTIPLE
+	       DB_MULTIPLE_KEY DB_MUTEXDEBUG DB_MUTEXLOCKS DB_NEEDSPLIT DB_NEXT
+	       DB_NEXT_DUP DB_NEXT_NODUP DB_NOCOPY DB_NODUPDATA DB_NOLOCKING
+	       DB_NOMMAP DB_NOORDERCHK DB_NOOVERWRITE DB_NOPANIC DB_NORECURSE
+	       DB_NOSERVER DB_NOSERVER_HOME DB_NOSERVER_ID DB_NOSYNC
+	       DB_NOTFOUND DB_NO_AUTO_COMMIT DB_ODDFILESIZE DB_OK_BTREE
 	       DB_OK_HASH DB_OK_QUEUE DB_OK_RECNO DB_OLD_VERSION DB_OPEN_CALLED
 	       DB_OPFLAGS_MASK DB_ORDERCHKONLY DB_OVERWRITE DB_PAD DB_PAGEYIELD
 	       DB_PAGE_LOCK DB_PAGE_NOTFOUND DB_PANIC_ENVIRONMENT DB_PERMANENT
@@ -3884,63 +4389,68 @@ my @names = (qw(DB_AFTER DB_AGGRESSIVE DB_ALREADY_ABORTED DB_APPEND
 	       DB_RECNUM DB_RECORDCOUNT DB_RECORD_LOCK DB_RECOVER
 	       DB_RECOVER_FATAL DB_REGION_ANON DB_REGION_INIT DB_REGION_MAGIC
 	       DB_REGION_NAME DB_REGISTERED DB_RENAMEMAGIC DB_RENUMBER
-	       DB_REP_CLIENT DB_REP_DUPMASTER DB_REP_HOLDELECTION
-	       DB_REP_LOGSONLY DB_REP_MASTER DB_REP_NEWMASTER DB_REP_NEWSITE
-	       DB_REP_OUTDATED DB_REP_PERMANENT DB_REP_UNAVAIL DB_REVSPLITOFF
-	       DB_RMW DB_RPC_SERVERPROG DB_RPC_SERVERVERS DB_RUNRECOVERY
-	       DB_SALVAGE DB_SECONDARY_BAD DB_SEQUENTIAL DB_SET
+	       DB_REP_CLIENT DB_REP_CREATE DB_REP_DUPMASTER DB_REP_EGENCHG
+	       DB_REP_HANDLE_DEAD DB_REP_HOLDELECTION DB_REP_ISPERM
+	       DB_REP_LOGREADY DB_REP_LOGSONLY DB_REP_MASTER DB_REP_NEWMASTER
+	       DB_REP_NEWSITE DB_REP_NOBUFFER DB_REP_NOTPERM DB_REP_OUTDATED
+	       DB_REP_PAGEDONE DB_REP_PERMANENT DB_REP_STARTUPDONE
+	       DB_REP_UNAVAIL DB_REVSPLITOFF DB_RMW DB_RPCCLIENT
+	       DB_RPC_SERVERPROG DB_RPC_SERVERVERS DB_RUNRECOVERY DB_SALVAGE
+	       DB_SECONDARY_BAD DB_SEQUENCE_VERSION DB_SEQUENTIAL DB_SEQ_DEC
+	       DB_SEQ_INC DB_SEQ_RANGE_SET DB_SEQ_WRAP DB_SET
 	       DB_SET_LOCK_TIMEOUT DB_SET_RANGE DB_SET_RECNO DB_SET_TXN_NOW
-	       DB_SET_TXN_TIMEOUT DB_SNAPSHOT DB_STAT_CLEAR DB_SURPRISE_KID
-	       DB_SWAPBYTES DB_SYSTEM_MEM DB_TEMPORARY DB_TEST_ELECTINIT
-	       DB_TEST_ELECTSEND DB_TEST_ELECTVOTE1 DB_TEST_ELECTVOTE2
-	       DB_TEST_ELECTWAIT1 DB_TEST_ELECTWAIT2 DB_TEST_POSTDESTROY
-	       DB_TEST_POSTEXTDELETE DB_TEST_POSTEXTOPEN DB_TEST_POSTEXTUNLINK
-	       DB_TEST_POSTLOG DB_TEST_POSTLOGMETA DB_TEST_POSTOPEN
-	       DB_TEST_POSTRENAME DB_TEST_POSTSYNC DB_TEST_PREDESTROY
-	       DB_TEST_PREEXTDELETE DB_TEST_PREEXTOPEN DB_TEST_PREEXTUNLINK
-	       DB_TEST_PREOPEN DB_TEST_PRERENAME DB_TEST_SUBDB_LOCKS DB_THREAD
-	       DB_TIMEOUT DB_TRUNCATE DB_TXNMAGIC DB_TXNVERSION DB_TXN_CKP
-	       DB_TXN_LOCK DB_TXN_LOCK_2PL DB_TXN_LOCK_MASK
-	       DB_TXN_LOCK_OPTIMIST DB_TXN_LOCK_OPTIMISTIC DB_TXN_LOG_MASK
-	       DB_TXN_LOG_REDO DB_TXN_LOG_UNDO DB_TXN_LOG_UNDOREDO
-	       DB_TXN_NOSYNC DB_TXN_NOWAIT DB_TXN_REDO DB_TXN_SYNC DB_TXN_UNDO
-	       DB_TXN_WRITE_NOSYNC DB_UNRESOLVED_CHILD DB_UPDATE_SECONDARY
+	       DB_SET_TXN_TIMEOUT DB_SNAPSHOT DB_STAT_ALL DB_STAT_CLEAR
+	       DB_STAT_LOCK_CONF DB_STAT_LOCK_LOCKERS DB_STAT_LOCK_OBJECTS
+	       DB_STAT_LOCK_PARAMS DB_STAT_MEMP_HASH DB_STAT_SUBSYSTEM
+	       DB_SURPRISE_KID DB_SWAPBYTES DB_SYSTEM_MEM DB_TEMPORARY
+	       DB_TEST_ELECTINIT DB_TEST_ELECTSEND DB_TEST_ELECTVOTE1
+	       DB_TEST_ELECTVOTE2 DB_TEST_ELECTWAIT1 DB_TEST_ELECTWAIT2
+	       DB_TEST_POSTDESTROY DB_TEST_POSTLOG DB_TEST_POSTLOGMETA
+	       DB_TEST_POSTOPEN DB_TEST_POSTRENAME DB_TEST_POSTSYNC
+	       DB_TEST_PREDESTROY DB_TEST_PREOPEN DB_TEST_PRERENAME
+	       DB_TEST_SUBDB_LOCKS DB_THREAD DB_TIMEOUT DB_TIME_NOTGRANTED
+	       DB_TRUNCATE DB_TXNMAGIC DB_TXNVERSION DB_TXN_CKP DB_TXN_LOCK
+	       DB_TXN_LOCK_2PL DB_TXN_LOCK_MASK DB_TXN_LOCK_OPTIMIST
+	       DB_TXN_LOCK_OPTIMISTIC DB_TXN_LOG_MASK DB_TXN_LOG_REDO
+	       DB_TXN_LOG_UNDO DB_TXN_LOG_UNDOREDO DB_TXN_NOSYNC
+	       DB_TXN_NOT_DURABLE DB_TXN_NOWAIT DB_TXN_REDO DB_TXN_SYNC
+	       DB_TXN_UNDO DB_TXN_WRITE_NOSYNC DB_UNREF DB_UPDATE_SECONDARY
 	       DB_UPGRADE DB_USE_ENVIRON DB_USE_ENVIRON_ROOT DB_VERB_CHKPOINT
 	       DB_VERB_DEADLOCK DB_VERB_RECOVERY DB_VERB_REPLICATION
 	       DB_VERB_WAITSFOR DB_VERIFY DB_VERIFY_BAD DB_VERIFY_FATAL
-	       DB_VERSION_MAJOR DB_VERSION_MINOR DB_VERSION_PATCH
-	       DB_VRFY_FLAGMASK DB_WRITECURSOR DB_WRITELOCK DB_WRITEOPEN
-	       DB_WRNOSYNC DB_XA_CREATE DB_XIDDATASIZE DB_YIELDCPU),
-            {name=>"DB_BTREE", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n     DB_VERSION_PATCH >= 0)\n", "#endif\n"]},
-            {name=>"DB_HASH", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n     DB_VERSION_PATCH >= 0)\n", "#endif\n"]},
-            {name=>"DB_LOCK_DUMP", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n     DB_VERSION_PATCH >= 0)\n", "#endif\n"]},
-            {name=>"DB_LOCK_GET", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n     DB_VERSION_PATCH >= 0)\n", "#endif\n"]},
-            {name=>"DB_LOCK_GET_TIMEOUT", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \\\n     DB_VERSION_PATCH >= 7)\n", "#endif\n"]},
+	       DB_VERSION_MAJOR DB_VERSION_MINOR DB_VERSION_MISMATCH
+	       DB_VERSION_PATCH DB_VRFY_FLAGMASK DB_WRITECURSOR DB_WRITELOCK
+	       DB_WRITEOPEN DB_WRNOSYNC DB_XA_CREATE DB_XIDDATASIZE DB_YIELDCPU
+	       DB_debug_FLAG DB_user_BEGIN),
+            {name=>"DB_BTREE", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n     DB_VERSION_PATCH >= 3)\n", "#endif\n"]},
+            {name=>"DB_HASH", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n     DB_VERSION_PATCH >= 3)\n", "#endif\n"]},
+            {name=>"DB_LOCK_DUMP", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n     DB_VERSION_PATCH >= 3)\n", "#endif\n"]},
+            {name=>"DB_LOCK_GET", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n     DB_VERSION_PATCH >= 3)\n", "#endif\n"]},
+            {name=>"DB_LOCK_GET_TIMEOUT", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \\\n     DB_VERSION_PATCH >= 14)\n", "#endif\n"]},
             {name=>"DB_LOCK_INHERIT", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 7) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 7 && \\\n     DB_VERSION_PATCH >= 1)\n", "#endif\n"]},
-            {name=>"DB_LOCK_PUT", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n     DB_VERSION_PATCH >= 0)\n", "#endif\n"]},
-            {name=>"DB_LOCK_PUT_ALL", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n     DB_VERSION_PATCH >= 0)\n", "#endif\n"]},
-            {name=>"DB_LOCK_PUT_OBJ", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n     DB_VERSION_PATCH >= 0)\n", "#endif\n"]},
-            {name=>"DB_LOCK_PUT_READ", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \\\n     DB_VERSION_PATCH >= 7)\n", "#endif\n"]},
-            {name=>"DB_LOCK_TIMEOUT", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \\\n     DB_VERSION_PATCH >= 7)\n", "#endif\n"]},
-            {name=>"DB_LOCK_TRADE", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n     DB_VERSION_PATCH >= 17)\n", "#endif\n"]},
-            {name=>"DB_LOCK_UPGRADE_WRITE", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 3) || \\\n    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 3) || \\\n    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3 && \\\n     DB_VERSION_PATCH >= 4)\n", "#endif\n"]},
-            {name=>"DB_PRIORITY_DEFAULT", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n     DB_VERSION_PATCH >= 17)\n", "#endif\n"]},
-            {name=>"DB_PRIORITY_HIGH", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n     DB_VERSION_PATCH >= 17)\n", "#endif\n"]},
-            {name=>"DB_PRIORITY_LOW", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n     DB_VERSION_PATCH >= 17)\n", "#endif\n"]},
-            {name=>"DB_PRIORITY_VERY_HIGH", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n     DB_VERSION_PATCH >= 17)\n", "#endif\n"]},
-            {name=>"DB_PRIORITY_VERY_LOW", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n     DB_VERSION_PATCH >= 17)\n", "#endif\n"]},
+            {name=>"DB_LOCK_PUT", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n     DB_VERSION_PATCH >= 3)\n", "#endif\n"]},
+            {name=>"DB_LOCK_PUT_ALL", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n     DB_VERSION_PATCH >= 3)\n", "#endif\n"]},
+            {name=>"DB_LOCK_PUT_OBJ", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n     DB_VERSION_PATCH >= 3)\n", "#endif\n"]},
+            {name=>"DB_LOCK_PUT_READ", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \\\n     DB_VERSION_PATCH >= 14)\n", "#endif\n"]},
+            {name=>"DB_LOCK_TIMEOUT", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \\\n     DB_VERSION_PATCH >= 14)\n", "#endif\n"]},
+            {name=>"DB_LOCK_TRADE", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n     DB_VERSION_PATCH >= 24)\n", "#endif\n"]},
+            {name=>"DB_LOCK_UPGRADE_WRITE", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 3) || \\\n    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 3) || \\\n    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3 && \\\n     DB_VERSION_PATCH >= 11)\n", "#endif\n"]},
+            {name=>"DB_PRIORITY_DEFAULT", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n     DB_VERSION_PATCH >= 24)\n", "#endif\n"]},
+            {name=>"DB_PRIORITY_HIGH", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n     DB_VERSION_PATCH >= 24)\n", "#endif\n"]},
+            {name=>"DB_PRIORITY_LOW", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n     DB_VERSION_PATCH >= 24)\n", "#endif\n"]},
+            {name=>"DB_PRIORITY_VERY_HIGH", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n     DB_VERSION_PATCH >= 24)\n", "#endif\n"]},
+            {name=>"DB_PRIORITY_VERY_LOW", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n     DB_VERSION_PATCH >= 24)\n", "#endif\n"]},
             {name=>"DB_QUEUE", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 3) || \\\n    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 0) || \\\n    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 0 && \\\n     DB_VERSION_PATCH >= 55)\n", "#endif\n"]},
-            {name=>"DB_RECNO", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n     DB_VERSION_PATCH >= 0)\n", "#endif\n"]},
-            {name=>"DB_TXN_ABORT", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 3) || \\\n    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \\\n    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \\\n     DB_VERSION_PATCH >= 12)\n", "#endif\n"]},
-            {name=>"DB_TXN_APPLY", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \\\n     DB_VERSION_PATCH >= 7)\n", "#endif\n"]},
-            {name=>"DB_TXN_BACKWARD_ALLOC", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n     DB_VERSION_PATCH >= 17)\n", "#endif\n"]},
-            {name=>"DB_TXN_BACKWARD_ROLL", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 3) || \\\n    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \\\n    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \\\n     DB_VERSION_PATCH >= 12)\n", "#endif\n"]},
-            {name=>"DB_TXN_FORWARD_ROLL", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 3) || \\\n    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \\\n    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \\\n     DB_VERSION_PATCH >= 12)\n", "#endif\n"]},
-            {name=>"DB_TXN_GETPGNOS", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n     DB_VERSION_PATCH >= 17)\n", "#endif\n"]},
-            {name=>"DB_TXN_OPENFILES", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 3) || \\\n    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \\\n    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \\\n     DB_VERSION_PATCH >= 12)\n", "#endif\n"]},
-            {name=>"DB_TXN_POPENFILES", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 3) || \\\n    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 3) || \\\n    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3 && \\\n     DB_VERSION_PATCH >= 4)\n", "#endif\n"]},
-            {name=>"DB_TXN_PRINT", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n     DB_VERSION_PATCH >= 17)\n", "#endif\n"]},
-            {name=>"DB_UNKNOWN", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n     DB_VERSION_PATCH >= 0)\n", "#endif\n"]},
+            {name=>"DB_RECNO", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n     DB_VERSION_PATCH >= 3)\n", "#endif\n"]},
+            {name=>"DB_TXN_ABORT", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 3) || \\\n    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \\\n    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \\\n     DB_VERSION_PATCH >= 14)\n", "#endif\n"]},
+            {name=>"DB_TXN_APPLY", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \\\n     DB_VERSION_PATCH >= 14)\n", "#endif\n"]},
+            {name=>"DB_TXN_BACKWARD_ALLOC", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n     DB_VERSION_PATCH >= 24)\n", "#endif\n"]},
+            {name=>"DB_TXN_BACKWARD_ROLL", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 3) || \\\n    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \\\n    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \\\n     DB_VERSION_PATCH >= 14)\n", "#endif\n"]},
+            {name=>"DB_TXN_FORWARD_ROLL", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 3) || \\\n    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \\\n    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \\\n     DB_VERSION_PATCH >= 14)\n", "#endif\n"]},
+            {name=>"DB_TXN_OPENFILES", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 3) || \\\n    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \\\n    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \\\n     DB_VERSION_PATCH >= 14)\n", "#endif\n"]},
+            {name=>"DB_TXN_POPENFILES", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 3) || \\\n    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 3) || \\\n    (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3 && \\\n     DB_VERSION_PATCH >= 11)\n", "#endif\n"]},
+            {name=>"DB_TXN_PRINT", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n    (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n     DB_VERSION_PATCH >= 24)\n", "#endif\n"]},
+            {name=>"DB_UNKNOWN", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n    (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n     DB_VERSION_PATCH >= 3)\n", "#endif\n"]},
             {name=>"DB_VERSION_STRING", type=>"PV"});
 
 print constant_types(); # macro defs
@@ -4002,33 +4512,7 @@ __END__
     return constant_21 (aTHX_ name, iv_return);
     break;
   case 22:
-    /* Names all of length 22.  */
-    /* DB_ENV_RPCCLIENT_GIVEN DB_TXN_LOCK_OPTIMISTIC */
-    /* Offset 8 gives the best switch position.  */
-    switch (name[8]) {
-    case 'O':
-      if (memEQ(name, "DB_TXN_LOCK_OPTIMISTIC", 22)) {
-      /*                       ^                    */
-#ifdef DB_TXN_LOCK_OPTIMISTIC
-        *iv_return = DB_TXN_LOCK_OPTIMISTIC;
-        return PERL_constant_ISIV;
-#else
-        return PERL_constant_NOTDEF;
-#endif
-      }
-      break;
-    case 'P':
-      if (memEQ(name, "DB_ENV_RPCCLIENT_GIVEN", 22)) {
-      /*                       ^                    */
-#ifdef DB_ENV_RPCCLIENT_GIVEN
-        *iv_return = DB_ENV_RPCCLIENT_GIVEN;
-        return PERL_constant_ISIV;
-#else
-        return PERL_constant_NOTDEF;
-#endif
-      }
-      break;
-    }
+    return constant_22 (aTHX_ name, iv_return);
     break;
   case 23:
     if (memEQ(name, "DB_ENV_TXN_WRITE_NOSYNC", 23)) {
diff --git a/storage/bdb/perl/BerkeleyDB/dbinfo b/storage/bdb/perl/BerkeleyDB/dbinfo
index af2c45facf5c03850efdd224969210c79aac9344..421d36c62602a6622108ffb112b562aabfd16c8b 100755
--- a/storage/bdb/perl/BerkeleyDB/dbinfo
+++ b/storage/bdb/perl/BerkeleyDB/dbinfo
@@ -4,10 +4,10 @@
 #			  a database file
 #
 # Author:	Paul Marquess  <Paul.Marquess@btinternet.com>
-# Version: 	1.03 
-# Date		17th September 2000
+# Version: 	1.05 
+# Date		1sh November 2003
 #
-#     Copyright (c) 1998-2002 Paul Marquess. All rights reserved.
+#     Copyright (c) 1998-2003 Paul Marquess. All rights reserved.
 #     This program is free software; you can redistribute it and/or
 #     modify it under the same terms as Perl itself.
 
@@ -22,39 +22,39 @@ my %Data =
 			  Type 	   => "Btree",
 			  Versions => 
 				{
-				  1	=> "Unknown (older than 1.71)",
-				  2	=> "Unknown (older than 1.71)",
-				  3	=> "1.71 -> 1.85, 1.86",
-				  4	=> "Unknown",
-				  5	=> "2.0.0 -> 2.3.0",
-				  6	=> "2.3.1 -> 2.7.7",
-				  7	=> "3.0.x",
-				  8	=> "3.1.x -> 4.0.x",
-				  9	=> "4.1.x or greater",
+				  1	=> [0, "Unknown (older than 1.71)"],
+				  2	=> [0, "Unknown (older than 1.71)"],
+				  3	=> [0, "1.71 -> 1.85, 1.86"],
+				  4	=> [0, "Unknown"],
+				  5	=> [0, "2.0.0 -> 2.3.0"],
+				  6	=> [0, "2.3.1 -> 2.7.7"],
+				  7	=> [0, "3.0.x"],
+				  8	=> [0, "3.1.x -> 4.0.x"],
+				  9	=> [1, "4.1.x or greater"],
 				}
 			},
 	0x061561 => 	{
 			  Type     => "Hash",
 			  Versions =>
 				{
-				  1	=> "Unknown (older than 1.71)",
-        			  2     => "1.71 -> 1.85",
-        			  3     => "1.86",
-        			  4     => "2.0.0 -> 2.1.0",
-        			  5     => "2.2.6 -> 2.7.7",
-        			  6     => "3.0.x",
-				  7	=> "3.1.x -> 4.0.x",
-				  8	=> "4.1.x or greater",
+				  1	=> [0, "Unknown (older than 1.71)"],
+        			  2     => [0, "1.71 -> 1.85"],
+        			  3     => [0, "1.86"],
+        			  4     => [0, "2.0.0 -> 2.1.0"],
+        			  5     => [0, "2.2.6 -> 2.7.7"],
+        			  6     => [0, "3.0.x"],
+				  7	=> [0, "3.1.x -> 4.0.x"],
+				  8	=> [1, "4.1.x or greater"],
 				}
 			},
 	0x042253 => 	{
 			  Type     => "Queue",
 			  Versions =>
 				{
-				  1	=> "3.0.x",
-				  2	=> "3.1.x",
-				  3	=> "3.2.x -> 4.0.x",
-				  4	=> "4.1.x or greater",
+				  1	=> [0, "3.0.x"],
+				  2	=> [0, "3.1.x"],
+				  3	=> [0, "3.2.x -> 4.0.x"],
+				  4	=> [1, "4.1.x or greater"],
 				}
 			},
 	) ;
@@ -65,17 +65,26 @@ print "testing file $ARGV[0]...\n\n" ;
 open (F, "<$ARGV[0]") or die "Cannot open file $ARGV[0]: $!\n" ;
 
 my $buff ;
-read F, $buff, 20 ;
+read F, $buff, 30 ;
 
-my (@info) = unpack("NNNNN", $buff) ;
-my (@info1) = unpack("VVVVV", $buff) ;
-my ($magic, $version, $endian) ;
 
-if ($Data{$info[0]}) # first try DB 1.x format
+my (@info) = unpack("NNNNNNC", $buff) ;
+my (@info1) = unpack("VVVVVVC", $buff) ;
+my ($magic, $version, $endian, $encrypt) ;
+
+if ($Data{$info[0]}) # first try DB 1.x format, big endian
 {
     $magic = $info[0] ;
     $version = $info[1] ;
-    $endian  = "Unknown" ;
+    $endian  = "Big Endian" ;
+    $encrypt = "Not Supported";
+}
+elsif ($Data{$info1[0]}) # first try DB 1.x format, little endian
+{
+    $magic = $info1[0] ;
+    $version = $info1[1] ;
+    $endian  = "Little Endian" ;
+    $encrypt = "Not Supported";
 }
 elsif ($Data{$info[3]}) # next DB 2.x big endian
 {
@@ -96,8 +105,15 @@ my $type = $Data{$magic} ;
 $magic = sprintf "%06X", $magic ;
 
 my $ver_string = "Unknown" ;
-$ver_string = $type->{Versions}{$version}
-	if defined $type->{Versions}{$version} ;
+
+if ( defined $type->{Versions}{$version} )
+{
+     $ver_string = $type->{Versions}{$version}[1];
+     if ($type->{Versions}{$version}[0] )
+       { $encrypt = $info[6] ? "Enabled" : "Disabled" }
+     else
+       { $encrypt = "Not Supported" }
+}
 
 print <<EOM ;
 File Type:		Berkeley DB $type->{Type} file.
@@ -105,6 +121,7 @@ File Version ID:	$version
 Built with Berkeley DB:	$ver_string
 Byte Order:		$endian
 Magic:			$magic
+Encryption:             $encrypt
 EOM
 
 close F ;
diff --git a/storage/bdb/perl/BerkeleyDB/mkconsts b/storage/bdb/perl/BerkeleyDB/mkconsts
index 7e0964333ccfd95a086f2d813935c88fd534ae44..0383378e423ea007bce2022e6a84b3cbb6adee20 100644
--- a/storage/bdb/perl/BerkeleyDB/mkconsts
+++ b/storage/bdb/perl/BerkeleyDB/mkconsts
@@ -8,8 +8,9 @@ use constant IGNORE => 'ignore' ;
 
 %constants = (
 
+
 	#########
-	# 2.0.0
+	# 2.0.3
 	#########
 
 	DBM_INSERT                 => IGNORE,
@@ -92,10 +93,12 @@ use constant IGNORE => 'ignore' ;
 	DB_RDONLY                  => DEFINE,
 	DB_REGISTERED              => DEFINE,
 	DB_RE_MODIFIED             => IGNORE,
+	DB_SEQUENTIAL              => DEFINE,
 	DB_SET                     => DEFINE,
 	DB_SET_RANGE               => DEFINE,
 	DB_SNAPSHOT                => DEFINE,
 	DB_SWAPBYTES               => DEFINE,
+	DB_TEMPORARY               => DEFINE,
 	DB_TRUNCATE                => DEFINE,
 	DB_TXNMAGIC                => DEFINE,
 	DB_TXNVERSION              => DEFINE,
@@ -122,36 +125,29 @@ use constant IGNORE => 'ignore' ;
 	const                      => IGNORE,
 
 	# enum DBTYPE
-	DB_BTREE                   => '2.0.0',
-	DB_HASH                    => '2.0.0',
-	DB_RECNO                   => '2.0.0',
-	DB_UNKNOWN                 => '2.0.0',
+	DB_BTREE                   => '2.0.3',
+	DB_HASH                    => '2.0.3',
+	DB_RECNO                   => '2.0.3',
+	DB_UNKNOWN                 => '2.0.3',
 
 	# enum db_lockop_t
-	DB_LOCK_DUMP               => '2.0.0',
-	DB_LOCK_GET                => '2.0.0',
-	DB_LOCK_PUT                => '2.0.0',
-	DB_LOCK_PUT_ALL            => '2.0.0',
-	DB_LOCK_PUT_OBJ            => '2.0.0',
+	DB_LOCK_DUMP               => '2.0.3',
+	DB_LOCK_GET                => '2.0.3',
+	DB_LOCK_PUT                => '2.0.3',
+	DB_LOCK_PUT_ALL            => '2.0.3',
+	DB_LOCK_PUT_OBJ            => '2.0.3',
 
 	# enum db_lockmode_t
-	DB_LOCK_NG                 => IGNORE, # 2.0.0
-	DB_LOCK_READ               => IGNORE, # 2.0.0
-	DB_LOCK_WRITE              => IGNORE, # 2.0.0
-	DB_LOCK_IREAD              => IGNORE, # 2.0.0
-	DB_LOCK_IWRITE             => IGNORE, # 2.0.0
-	DB_LOCK_IWR                => IGNORE, # 2.0.0
+	DB_LOCK_NG                 => IGNORE, # 2.0.3
+	DB_LOCK_READ               => IGNORE, # 2.0.3
+	DB_LOCK_WRITE              => IGNORE, # 2.0.3
+	DB_LOCK_IREAD              => IGNORE, # 2.0.3
+	DB_LOCK_IWRITE             => IGNORE, # 2.0.3
+	DB_LOCK_IWR                => IGNORE, # 2.0.3
 
 	# enum ACTION
-	FIND                       => IGNORE, # 2.0.0
-	ENTER                      => IGNORE, # 2.0.0
-
-	#########
-	# 2.0.3
-	#########
-
-	DB_SEQUENTIAL              => DEFINE,
-	DB_TEMPORARY               => DEFINE,
+	FIND                       => IGNORE, # 2.0.3
+	ENTER                      => IGNORE, # 2.0.3
 
 	#########
 	# 2.1.0
@@ -199,22 +195,12 @@ use constant IGNORE => 'ignore' ;
 	DB_RE_SNAPSHOT             => IGNORE,
 
 	#########
-	# 2.3.1
+	# 2.3.10
 	#########
 
+	DB_APPEND                  => DEFINE,
 	DB_GET_RECNO               => DEFINE,
 	DB_SET_RECNO               => DEFINE,
-
-	#########
-	# 2.3.3
-	#########
-
-	DB_APPEND                  => DEFINE,
-
-	#########
-	# 2.3.6
-	#########
-
 	DB_TXN_CKP                 => DEFINE,
 
 	#########
@@ -295,7 +281,7 @@ use constant IGNORE => 'ignore' ;
 	__UNUSED_4000              => IGNORE,
 
 	#########
-	# 2.5.2
+	# 2.5.9
 	#########
 
 	DBC_CONTINUE               => IGNORE,
@@ -303,20 +289,15 @@ use constant IGNORE => 'ignore' ;
 	DBC_RECOVER                => IGNORE,
 	DBC_RMW                    => IGNORE,
 	DB_DBM_ERROR               => IGNORE,
+	DB_DUPSORT                 => DEFINE,
 	DB_GET_BOTH                => DEFINE,
+	DB_JOIN_ITEM               => DEFINE,
 	DB_NEXT_DUP                => DEFINE,
 	DB_OPFLAGS_MASK            => DEFINE,
 	DB_RMW                     => DEFINE,
 	DB_RUNRECOVERY             => DEFINE,
 	dbmclose                   => IGNORE,
 
-	#########
-	# 2.5.9
-	#########
-
-	DB_DUPSORT                 => DEFINE,
-	DB_JOIN_ITEM               => DEFINE,
-
 	#########
 	# 2.6.4
 	#########
@@ -409,7 +390,7 @@ use constant IGNORE => 'ignore' ;
 	DB_QUEUE                   => '3.0.55',
 
 	#########
-	# 3.1.12
+	# 3.1.14
 	#########
 
 	DBC_ACTIVE                 => IGNORE,
@@ -443,49 +424,34 @@ use constant IGNORE => 'ignore' ;
 	DB_VRFY_FLAGMASK           => DEFINE,
 
 	# enum db_recops
-	DB_TXN_ABORT               => '3.1.12',
-	DB_TXN_BACKWARD_ROLL       => '3.1.12',
-	DB_TXN_FORWARD_ROLL        => '3.1.12',
-	DB_TXN_OPENFILES           => '3.1.12',
+	DB_TXN_ABORT               => '3.1.14',
+	DB_TXN_BACKWARD_ROLL       => '3.1.14',
+	DB_TXN_FORWARD_ROLL        => '3.1.14',
+	DB_TXN_OPENFILES           => '3.1.14',
 
 	#########
-	# 3.2.3
+	# 3.2.9
 	#########
 
 	DBC_COMPENSATE             => IGNORE,
+	DB_ALREADY_ABORTED         => DEFINE,
 	DB_AM_VERIFYING            => IGNORE,
 	DB_CDB_ALLDB               => DEFINE,
+	DB_CONSUME_WAIT            => DEFINE,
 	DB_ENV_CDB_ALLDB           => DEFINE,
 	DB_EXTENT                  => DEFINE,
+	DB_JAVA_CALLBACK           => DEFINE,
 	DB_JOINENV                 => DEFINE,
 	DB_LOCK_SWITCH             => DEFINE,
 	DB_MPOOL_EXTENT            => DEFINE,
 	DB_REGION_MAGIC            => DEFINE,
-	DB_UNRESOLVED_CHILD        => DEFINE,
 	DB_VERIFY                  => DEFINE,
 
-	# enum db_notices
-	DB_NOTICE_LOGFILE_CHANGED  => IGNORE, # 3.2.3
-
-	#########
-	# 3.2.6
-	#########
-
-	DB_ALREADY_ABORTED         => DEFINE,
-	DB_CONSUME_WAIT            => DEFINE,
-	DB_JAVA_CALLBACK           => DEFINE,
-	DB_TEST_POSTEXTDELETE      => DEFINE,
-	DB_TEST_POSTEXTOPEN        => DEFINE,
-	DB_TEST_POSTEXTUNLINK      => DEFINE,
-	DB_TEST_PREEXTDELETE       => DEFINE,
-	DB_TEST_PREEXTOPEN         => DEFINE,
-	DB_TEST_PREEXTUNLINK       => DEFINE,
-
 	# enum db_lockmode_t
-	DB_LOCK_WAIT               => IGNORE, # 3.2.6
+	DB_LOCK_WAIT               => IGNORE, # 3.2.9
 
 	#########
-	# 3.3.4
+	# 3.3.11
 	#########
 
 	DBC_DIRTY_READ             => IGNORE,
@@ -508,35 +474,31 @@ use constant IGNORE => 'ignore' ;
 	DB_PAGE_NOTFOUND           => DEFINE,
 	DB_RPC_SERVERPROG          => DEFINE,
 	DB_RPC_SERVERVERS          => DEFINE,
+	DB_SECONDARY_BAD           => DEFINE,
+	DB_SURPRISE_KID            => DEFINE,
+	DB_TEST_POSTDESTROY        => DEFINE,
+	DB_TEST_PREDESTROY         => DEFINE,
 	DB_UPDATE_SECONDARY        => DEFINE,
 	DB_XIDDATASIZE             => DEFINE,
 
 	# enum db_recops
-	DB_TXN_POPENFILES          => '3.3.4',
+	DB_TXN_POPENFILES          => '3.3.11',
 
 	# enum db_lockop_t
-	DB_LOCK_UPGRADE_WRITE      => '3.3.4',
+	DB_LOCK_UPGRADE_WRITE      => '3.3.11',
 
 	# enum db_lockmode_t
-	DB_LOCK_DIRTY              => IGNORE, # 3.3.4
-	DB_LOCK_WWRITE             => IGNORE, # 3.3.4
-
-	#########
-	# 3.3.11
-	#########
-
-	DB_SECONDARY_BAD           => DEFINE,
-	DB_SURPRISE_KID            => DEFINE,
-	DB_TEST_POSTDESTROY        => DEFINE,
-	DB_TEST_PREDESTROY         => DEFINE,
+	DB_LOCK_DIRTY              => IGNORE, # 3.3.11
+	DB_LOCK_WWRITE             => IGNORE, # 3.3.11
 
 	#########
-	# 4.0.7
+	# 4.0.14
 	#########
 
 	DB_APPLY_LOGREG            => DEFINE,
-	DB_BROADCAST_EID           => DEFINE,
 	DB_CL_WRITER               => DEFINE,
+	DB_EID_BROADCAST           => DEFINE,
+	DB_EID_INVALID             => DEFINE,
 	DB_ENV_NOLOCKING           => DEFINE,
 	DB_ENV_NOPANIC             => DEFINE,
 	DB_ENV_REGION_INIT         => DEFINE,
@@ -545,7 +507,6 @@ use constant IGNORE => 'ignore' ;
 	DB_ENV_REP_MASTER          => DEFINE,
 	DB_ENV_YIELDCPU            => DEFINE,
 	DB_GET_BOTH_RANGE          => DEFINE,
-	DB_INVALID_EID             => DEFINE,
 	DB_LOCK_EXPIRE             => DEFINE,
 	DB_LOCK_FREE_LOCKER        => DEFINE,
 	DB_LOCK_SET_TIMEOUT        => DEFINE,
@@ -571,6 +532,7 @@ use constant IGNORE => 'ignore' ;
 	DB_SET_TXN_TIMEOUT         => DEFINE,
 	DB_STAT_CLEAR              => DEFINE,
 	DB_TIMEOUT                 => DEFINE,
+	DB_VERB_REPLICATION        => DEFINE,
 	DB_YIELDCPU                => DEFINE,
 	MP_FLUSH                   => IGNORE,
 	MP_OPEN_CALLED             => IGNORE,
@@ -587,26 +549,18 @@ use constant IGNORE => 'ignore' ;
 	TXN_SYNC                   => IGNORE,
 
 	# enum db_recops
-	DB_TXN_APPLY               => '4.0.7',
+	DB_TXN_APPLY               => '4.0.14',
 
 	# enum db_lockop_t
-	DB_LOCK_GET_TIMEOUT        => '4.0.7',
-	DB_LOCK_PUT_READ           => '4.0.7',
-	DB_LOCK_TIMEOUT            => '4.0.7',
+	DB_LOCK_GET_TIMEOUT        => '4.0.14',
+	DB_LOCK_PUT_READ           => '4.0.14',
+	DB_LOCK_TIMEOUT            => '4.0.14',
 
 	# enum db_status_t
-	DB_LSTAT_EXPIRED           => IGNORE, # 4.0.7
-
-	#########
-	# 4.0.14
-	#########
-
-	DB_EID_BROADCAST           => DEFINE,
-	DB_EID_INVALID             => DEFINE,
-	DB_VERB_REPLICATION        => DEFINE,
+	DB_LSTAT_EXPIRED           => IGNORE, # 4.0.14
 
 	#########
-	# 4.1.17
+	# 4.1.24
 	#########
 
 	DBC_OWN_LID                => IGNORE,
@@ -661,22 +615,97 @@ use constant IGNORE => 'ignore' ;
 	_DB_EXT_PROT_IN_           => IGNORE,
 
 	# enum db_lockop_t
-	DB_LOCK_TRADE              => '4.1.17',
+	DB_LOCK_TRADE              => '4.1.24',
 
 	# enum db_status_t
-	DB_LSTAT_NOTEXIST          => IGNORE, # 4.1.17
+	DB_LSTAT_NOTEXIST          => IGNORE, # 4.1.24
 
 	# enum DB_CACHE_PRIORITY
-	DB_PRIORITY_VERY_LOW       => '4.1.17',
-	DB_PRIORITY_LOW            => '4.1.17',
-	DB_PRIORITY_DEFAULT        => '4.1.17',
-	DB_PRIORITY_HIGH           => '4.1.17',
-	DB_PRIORITY_VERY_HIGH      => '4.1.17',
+	DB_PRIORITY_VERY_LOW       => '4.1.24',
+	DB_PRIORITY_LOW            => '4.1.24',
+	DB_PRIORITY_DEFAULT        => '4.1.24',
+	DB_PRIORITY_HIGH           => '4.1.24',
+	DB_PRIORITY_VERY_HIGH      => '4.1.24',
 
 	# enum db_recops
-	DB_TXN_BACKWARD_ALLOC      => '4.1.17',
-	DB_TXN_GETPGNOS            => '4.1.17',
-	DB_TXN_PRINT               => '4.1.17',
+	DB_TXN_BACKWARD_ALLOC      => '4.1.24',
+	DB_TXN_PRINT               => '4.1.24',
+
+	#########
+	# 4.2.50
+	#########
+
+	DB_AM_NOT_DURABLE          => IGNORE,
+	DB_AM_REPLICATION          => IGNORE,
+	DB_ARCH_REMOVE             => DEFINE,
+	DB_CHKSUM                  => DEFINE,
+	DB_ENV_LOG_AUTOREMOVE      => DEFINE,
+	DB_ENV_TIME_NOTGRANTED     => DEFINE,
+	DB_ENV_TXN_NOT_DURABLE     => DEFINE,
+	DB_FILEOPEN                => DEFINE,
+	DB_INIT_REP                => DEFINE,
+	DB_LOG_AUTOREMOVE          => DEFINE,
+	DB_LOG_CHKPNT              => DEFINE,
+	DB_LOG_COMMIT              => DEFINE,
+	DB_LOG_NOCOPY              => DEFINE,
+	DB_LOG_NOT_DURABLE         => DEFINE,
+	DB_LOG_PERM                => DEFINE,
+	DB_LOG_WRNOSYNC            => DEFINE,
+	DB_MPOOL_NOFILE            => DEFINE,
+	DB_MPOOL_UNLINK            => DEFINE,
+	DB_NO_AUTO_COMMIT          => DEFINE,
+	DB_REP_CREATE              => DEFINE,
+	DB_REP_HANDLE_DEAD         => DEFINE,
+	DB_REP_ISPERM              => DEFINE,
+	DB_REP_NOBUFFER            => DEFINE,
+	DB_REP_NOTPERM             => DEFINE,
+	DB_RPCCLIENT               => DEFINE,
+	DB_TIME_NOTGRANTED         => DEFINE,
+	DB_TXN_NOT_DURABLE         => DEFINE,
+	DB_debug_FLAG              => DEFINE,
+	DB_user_BEGIN              => DEFINE,
+	MP_FILEID_SET              => IGNORE,
+	TXN_RESTORED               => IGNORE,
+
+	#########
+	# 4.3.12
+	#########
+
+	DBC_DEGREE_2               => IGNORE,
+	DB_AM_INORDER              => IGNORE,
+	DB_BUFFER_SMALL            => DEFINE,
+	DB_DEGREE_2                => DEFINE,
+	DB_DSYNC_LOG               => DEFINE,
+	DB_DURABLE_UNKNOWN         => DEFINE,
+	DB_ENV_DSYNC_LOG           => DEFINE,
+	DB_ENV_LOG_INMEMORY        => DEFINE,
+	DB_INORDER                 => DEFINE,
+	DB_LOCK_ABORT              => DEFINE,
+	DB_LOCK_MAXWRITE           => DEFINE,
+	DB_LOG_BUFFER_FULL         => DEFINE,
+	DB_LOG_INMEMORY            => DEFINE,
+	DB_LOG_RESEND              => DEFINE,
+	DB_MPOOL_FREE              => DEFINE,
+	DB_REP_EGENCHG             => DEFINE,
+	DB_REP_LOGREADY            => DEFINE,
+	DB_REP_PAGEDONE            => DEFINE,
+	DB_REP_STARTUPDONE         => DEFINE,
+	DB_SEQUENCE_VERSION        => DEFINE,
+	DB_SEQ_DEC                 => DEFINE,
+	DB_SEQ_INC                 => DEFINE,
+	DB_SEQ_RANGE_SET           => DEFINE,
+	DB_SEQ_WRAP                => DEFINE,
+	DB_STAT_ALL                => DEFINE,
+	DB_STAT_LOCK_CONF          => DEFINE,
+	DB_STAT_LOCK_LOCKERS       => DEFINE,
+	DB_STAT_LOCK_OBJECTS       => DEFINE,
+	DB_STAT_LOCK_PARAMS        => DEFINE,
+	DB_STAT_MEMP_HASH          => DEFINE,
+	DB_STAT_SUBSYSTEM          => DEFINE,
+	DB_UNREF                   => DEFINE,
+	DB_VERSION_MISMATCH        => DEFINE,
+	TXN_DEADLOCK               => IGNORE,
+	TXN_DEGREE_2               => IGNORE,
 
 	) ;
 
diff --git a/storage/bdb/perl/BerkeleyDB/patches/5.004 b/storage/bdb/perl/BerkeleyDB/patches/5.004
index 143ec95afbc457e383256e48266e38fa147a3c0f..0665d1f6c4068b56da4f3a2cef17f83fdd81883f 100644
--- a/storage/bdb/perl/BerkeleyDB/patches/5.004
+++ b/storage/bdb/perl/BerkeleyDB/patches/5.004
@@ -1,44 +1,93 @@
-diff perl5.004.orig/Configure perl5.004/Configure
-190a191
-> perllibs=''
-9904a9906,9913
-> : Remove libraries needed only for extensions
-> : The appropriate ext/Foo/Makefile.PL will add them back in, if
-> : necessary.
-> set X `echo " $libs " | 
->   sed -e 's@ -lndbm @ @' -e 's@ -lgdbm @ @' -e 's@ -ldbm @ @' -e 's@ -ldb @ @'` 
-> shift
-> perllibs="$*"
-> 
-10372a10382
-> perllibs='$perllibs'
-diff perl5.004.orig/Makefile.SH perl5.004/Makefile.SH
-122c122
-< libs = $libs $cryptlib
----
-> libs = $perllibs $cryptlib
-Common subdirectories: perl5.004.orig/Porting and perl5.004/Porting
-Common subdirectories: perl5.004.orig/cygwin32 and perl5.004/cygwin32
-Common subdirectories: perl5.004.orig/eg and perl5.004/eg
-Common subdirectories: perl5.004.orig/emacs and perl5.004/emacs
-Common subdirectories: perl5.004.orig/ext and perl5.004/ext
-Common subdirectories: perl5.004.orig/h2pl and perl5.004/h2pl
-Common subdirectories: perl5.004.orig/hints and perl5.004/hints
-Common subdirectories: perl5.004.orig/lib and perl5.004/lib
-diff perl5.004.orig/myconfig perl5.004/myconfig
-38c38
-<     libs=$libs
----
->     libs=$perllibs
-Common subdirectories: perl5.004.orig/os2 and perl5.004/os2
-diff perl5.004.orig/patchlevel.h perl5.004/patchlevel.h
-40a41
-> 	,"NODB-1.0 - remove -ldb from core perl binary."
-Common subdirectories: perl5.004.orig/plan9 and perl5.004/plan9
-Common subdirectories: perl5.004.orig/pod and perl5.004/pod
-Common subdirectories: perl5.004.orig/qnx and perl5.004/qnx
-Common subdirectories: perl5.004.orig/t and perl5.004/t
-Common subdirectories: perl5.004.orig/utils and perl5.004/utils
-Common subdirectories: perl5.004.orig/vms and perl5.004/vms
-Common subdirectories: perl5.004.orig/win32 and perl5.004/win32
-Common subdirectories: perl5.004.orig/x2p and perl5.004/x2p
+diff -rc perl5.004.orig/Configure perl5.004/Configure
+*** perl5.004.orig/Configure	1997-05-13 18:20:34.000000000 +0100
+--- perl5.004/Configure	2003-04-26 16:36:53.000000000 +0100
+***************
+*** 188,193 ****
+--- 188,194 ----
+  mv=''
+  nroff=''
+  perl=''
++ perllibs=''
+  pg=''
+  pmake=''
+  pr=''
+***************
+*** 9902,9907 ****
+--- 9903,9916 ----
+  shift
+  extensions="$*"
+  
++ : Remove libraries needed only for extensions
++ : The appropriate ext/Foo/Makefile.PL will add them back in, if
++ : necessary.
++ set X `echo " $libs " | 
++   sed -e 's@ -lndbm @ @' -e 's@ -lgdbm @ @' -e 's@ -ldbm @ @' -e 's@ -ldb @ @'` 
++ shift
++ perllibs="$*"
++ 
+  : Remove build directory name from cppstdin so it can be used from
+  : either the present location or the final installed location.
+  echo " "
+***************
+*** 10370,10375 ****
+--- 10379,10385 ----
+  patchlevel='$patchlevel'
+  path_sep='$path_sep'
+  perl='$perl'
++ perllibs='$perllibs'
+  perladmin='$perladmin'
+  perlpath='$perlpath'
+  pg='$pg'
+diff -rc perl5.004.orig/Makefile.SH perl5.004/Makefile.SH
+*** perl5.004.orig/Makefile.SH	1997-05-01 15:22:39.000000000 +0100
+--- perl5.004/Makefile.SH	2003-04-26 16:37:23.000000000 +0100
+***************
+*** 119,125 ****
+  ext = \$(dynamic_ext) \$(static_ext)
+  DYNALOADER = lib/auto/DynaLoader/DynaLoader\$(LIB_EXT)
+  
+! libs = $libs $cryptlib
+  
+  public = perl $suidperl utilities translators
+  
+--- 119,125 ----
+  ext = \$(dynamic_ext) \$(static_ext)
+  DYNALOADER = lib/auto/DynaLoader/DynaLoader\$(LIB_EXT)
+  
+! libs = $perllibs $cryptlib
+  
+  public = perl $suidperl utilities translators
+  
+diff -rc perl5.004.orig/myconfig perl5.004/myconfig
+*** perl5.004.orig/myconfig	1996-12-21 01:13:20.000000000 +0000
+--- perl5.004/myconfig	2003-04-26 16:37:51.000000000 +0100
+***************
+*** 35,41 ****
+    Linker and Libraries:
+      ld='$ld', ldflags ='$ldflags'
+      libpth=$libpth
+!     libs=$libs
+      libc=$libc, so=$so
+      useshrplib=$useshrplib, libperl=$libperl
+    Dynamic Linking:
+--- 35,41 ----
+    Linker and Libraries:
+      ld='$ld', ldflags ='$ldflags'
+      libpth=$libpth
+!     libs=$perllibs
+      libc=$libc, so=$so
+      useshrplib=$useshrplib, libperl=$libperl
+    Dynamic Linking:
+diff -rc perl5.004.orig/patchlevel.h perl5.004/patchlevel.h
+*** perl5.004.orig/patchlevel.h	1997-05-15 23:15:17.000000000 +0100
+--- perl5.004/patchlevel.h	2003-04-26 16:38:11.000000000 +0100
+***************
+*** 38,43 ****
+--- 38,44 ----
+   */
+  static	char	*local_patches[] = {
+  	NULL
++ 	,"NODB-1.0 - remove -ldb from core perl binary."
+  	,NULL
+  };
+  
diff --git a/storage/bdb/perl/BerkeleyDB/ppport.h b/storage/bdb/perl/BerkeleyDB/ppport.h
index 0887c2159a9a86b75f886cceccc3bbc62c4227a4..0815cf2d88fc3e886b0825b0b4f35c77f285f4bc 100644
--- a/storage/bdb/perl/BerkeleyDB/ppport.h
+++ b/storage/bdb/perl/BerkeleyDB/ppport.h
@@ -86,6 +86,11 @@
 /* Replace: 0 */
 #endif
 
+#ifndef SvGETMAGIC
+#  define SvGETMAGIC(x)                  STMT_START { if (SvGMAGICAL(x)) mg_get(x); } STMT_END
+#endif
+
+
 /* DEFSV appears first in 5.004_56 */
 #ifndef DEFSV
 #  define DEFSV	GvSV(PL_defgv)
@@ -279,6 +284,13 @@ SV *sv;
 #endif /* START_MY_CXT */
 
 
+#if 1
+#ifdef DBM_setFilter
+#undef DBM_setFilter
+#undef DBM_ckFilter
+#endif
+#endif
+
 #ifndef DBM_setFilter
 
 /* 
@@ -305,6 +317,7 @@ SV *sv;
 
 #define DBM_ckFilter(arg,type,name)				\
 	if (db->type) {						\
+	    /* printf("Filtering %s\n", name); */		\
 	    if (db->filtering) {				\
 	        croak("recursion detected in %s", name) ;	\
 	    }                     				\
@@ -313,15 +326,22 @@ SV *sv;
 	    SAVEINT(db->filtering) ;				\
 	    db->filtering = TRUE ;				\
 	    SAVESPTR(DEFSV) ;					\
+	    if (name[7] == 's')  				\
+	        arg = newSVsv(arg);				\
 	    DEFSV = arg ;					\
 	    SvTEMP_off(arg) ;					\
 	    PUSHMARK(SP) ;					\
 	    PUTBACK ;						\
 	    (void) perl_call_sv(db->type, G_DISCARD); 		\
+	    arg = DEFSV ;					\
 	    SPAGAIN ;						\
 	    PUTBACK ;						\
 	    FREETMPS ;						\
 	    LEAVE ;						\
+	    if (name[7] == 's'){ 				\
+	        arg = sv_2mortal(arg);				\
+	    }							\
+	    SvOKp(arg);						\
 	}
 
 #endif /* DBM_setFilter */
diff --git a/storage/bdb/perl/BerkeleyDB/scan b/storage/bdb/perl/BerkeleyDB/scan
index eb064950b2ecbb5f3dc3b93197c6242fce2182f8..c501f3c453208a6b857551269c3ef9d595393dae 100644
--- a/storage/bdb/perl/BerkeleyDB/scan
+++ b/storage/bdb/perl/BerkeleyDB/scan
@@ -16,18 +16,26 @@ my $ignore_re = '^(' . join("|",
 		DB_TSL
 		MP
 		TXN
+                DB_TXN_GETPGNOS
 	)) . ')' ;
 
 my %ignore_def = map {$_, 1} qw() ;
 
 %ignore_enums = map {$_, 1} qw( ACTION db_status_t db_notices db_lockmode_t ) ;
 
+my %ignore_exact_enum = map { $_ => 1}
+	qw(
+                DB_TXN_GETPGNOS
+                );
+
 my $filler = ' ' x 26 ;
 
 chdir "libraries" || die "Cannot chdir into './libraries': $!\n";
 
 foreach my $name (sort tuple glob "[2-9]*")
 {
+    next if $name =~ /(NC|private)$/;
+
     my $inc = "$name/include/db.h" ;
     next unless -f $inc ;
 
@@ -121,6 +129,7 @@ sub scan
             my $out = $filler ;
 	    foreach $name (@new)
 	    {
+                next if $ignore_exact_enum{$name} ;
 	        $out = $filler ;
 	        substr($out,0, length $name) = $name;
                 $result .= "\t$out => $value\n" ;
diff --git a/storage/bdb/perl/BerkeleyDB/t/btree.t b/storage/bdb/perl/BerkeleyDB/t/btree.t
index fd6ed8f1268283253b8874f4a607aabf02f13fca..152c366015aafa9c50bc62a27842f41077f7243f 100644
--- a/storage/bdb/perl/BerkeleyDB/t/btree.t
+++ b/storage/bdb/perl/BerkeleyDB/t/btree.t
@@ -104,7 +104,7 @@ umask(0) ;
     ok 27, my $lexD = new LexDir($home) ;
 
     ok 28, my $env = new BerkeleyDB::Env -Flags => DB_CREATE|DB_INIT_MPOOL,
-    					 -Home => $home ;
+    					 @StdErrFile, -Home => $home ;
     ok 29, my $db = new BerkeleyDB::Btree -Filename => $Dfile, 
 				    -Env      => $env,
 				    -Flags    => DB_CREATE ;
@@ -127,6 +127,7 @@ umask(0) ;
     my ($k, $v) ;
     ok 33, my $db = new BerkeleyDB::Btree -Filename => $Dfile, 
 				     -Flags    => DB_CREATE ;
+print "[$db] [$!] $BerkeleyDB::Error\n" ;				     
 
     # create some data
     my %data =  (
@@ -631,7 +632,7 @@ umask(0) ;
 
     my $home = "./fred" ;
     ok 177, my $lexD = new LexDir($home) ;
-    ok 178, my $env = new BerkeleyDB::Env -Home => $home,
+    ok 178, my $env = new BerkeleyDB::Env -Home => $home, @StdErrFile,
 				     -Flags => DB_CREATE|DB_INIT_TXN|
 					  	DB_INIT_MPOOL|DB_INIT_LOCK ;
     ok 179, my $txn = $env->txn_begin() ;
@@ -783,7 +784,7 @@ umask(0) ;
 
    require Exporter ;
    use BerkeleyDB;
-   @ISA=qw(BerkeleyDB::Btree);
+   @ISA=qw(BerkeleyDB BerkeleyDB::Btree );
    @EXPORT = @BerkeleyDB::EXPORT ;
 
    sub db_put { 
diff --git a/storage/bdb/perl/BerkeleyDB/t/cds.t b/storage/bdb/perl/BerkeleyDB/t/cds.t
new file mode 100644
index 0000000000000000000000000000000000000000..4d129a0a66cc7c06e1ac717a99564e7c574a4907
--- /dev/null
+++ b/storage/bdb/perl/BerkeleyDB/t/cds.t
@@ -0,0 +1,80 @@
+#!./perl -w
+
+# Tests for Concurrent Data Store mode
+
+use strict ;
+
+BEGIN {
+    unless(grep /blib/, @INC) {
+        chdir 't' if -d 't';
+        @INC = '../lib' if -d '../lib';
+    }
+}
+
+use BerkeleyDB; 
+use t::util ;
+
+BEGIN
+{
+    if ($BerkeleyDB::db_version < 2) {
+        print "1..0 # Skip: this needs Berkeley DB 2.x.x or better\n" ;
+        exit 0 ;
+    }
+}
+
+
+
+print "1..12\n";
+
+my $Dfile = "dbhash.tmp";
+unlink $Dfile;
+
+umask(0) ;
+
+{
+    # Error case -- env not opened in CDS mode
+
+    my $lex = new LexFile $Dfile ;
+
+    my $home = "./fred" ;
+    ok 1, my $lexD = new LexDir($home) ;
+
+    ok 2, my $env = new BerkeleyDB::Env -Flags => DB_CREATE|DB_INIT_MPOOL,
+    					 -Home => $home, @StdErrFile ;
+
+    ok 3, my $db = new BerkeleyDB::Btree -Filename => $Dfile, 
+				    -Env      => $env,
+				    -Flags    => DB_CREATE ;
+
+    ok 4, ! $env->cds_enabled() ;
+    ok 5, ! $db->cds_enabled() ;
+
+    eval { $db->cds_lock() };
+    ok 6, $@ =~ /CDS not enabled for this database/;
+
+    undef $db;
+    undef $env ;
+}
+
+{
+    my $lex = new LexFile $Dfile ;
+
+    my $home = "./fred" ;
+    ok 7, my $lexD = new LexDir($home) ;
+
+    ok 8, my $env = new BerkeleyDB::Env -Flags => DB_INIT_CDB|DB_CREATE|DB_INIT_MPOOL,
+    					 -Home => $home, @StdErrFile ;
+
+    ok 9, my $db = new BerkeleyDB::Btree -Filename => $Dfile, 
+				    -Env      => $env,
+				    -Flags    => DB_CREATE ;
+
+    ok 10,   $env->cds_enabled() ;
+    ok 11,   $db->cds_enabled() ;
+
+    my $cds = $db->cds_lock() ;
+    ok 12, $cds ;
+
+    undef $db;
+    undef $env ;
+}
diff --git a/storage/bdb/perl/BerkeleyDB/t/destroy.t b/storage/bdb/perl/BerkeleyDB/t/destroy.t
index 7457d36c583373f986c0067e3007577400778de2..445d07407708ed3c053cdbd8c09acfb9e872f08d 100644
--- a/storage/bdb/perl/BerkeleyDB/t/destroy.t
+++ b/storage/bdb/perl/BerkeleyDB/t/destroy.t
@@ -27,7 +27,7 @@ umask(0);
     my $value ;
 
     ok 1, my $lexD = new LexDir($home) ;
-    ok 2, my $env = new BerkeleyDB::Env -Home => $home,
+    ok 2, my $env = new BerkeleyDB::Env -Home => $home,  @StdErrFile,
 				     -Flags => DB_CREATE|DB_INIT_TXN|
 					  	DB_INIT_MPOOL|DB_INIT_LOCK ;
     ok 3, my $txn = $env->txn_begin() ;
diff --git a/storage/bdb/perl/BerkeleyDB/t/encrypt.t b/storage/bdb/perl/BerkeleyDB/t/encrypt.t
new file mode 100644
index 0000000000000000000000000000000000000000..b3cc13821efdf27f0b52c6a1af8609a9cee33e07
--- /dev/null
+++ b/storage/bdb/perl/BerkeleyDB/t/encrypt.t
@@ -0,0 +1,646 @@
+#!./perl -w
+
+# ID: %I%, %G%   
+
+use strict ;
+
+BEGIN {
+    unless(grep /blib/, @INC) {
+        chdir 't' if -d 't';
+        @INC = '../lib' if -d '../lib';
+    }
+}
+
+use BerkeleyDB; 
+use t::util ;
+
+BEGIN
+{
+    if ($BerkeleyDB::db_version < 4.1) {
+        print "1..0 # Skip: this needs Berkeley DB 4.1.x or better\n" ;
+        exit 0 ;
+    }
+
+    # Is encryption available?
+    my $env = new BerkeleyDB::Env @StdErrFile,
+             -Encrypt => {Password => "abc",
+	                  Flags    => DB_ENCRYPT_AES
+	                 };
+
+    if ($BerkeleyDB::Error =~ /Operation not supported/)
+    {
+        print "1..0 # Skip: encryption support not present\n" ;
+        exit 0 ;
+    }
+}     
+
+umask(0);
+
+print "1..80\n";        
+
+{    
+    eval
+    {
+        my $env = new BerkeleyDB::Env @StdErrFile,
+             -Encrypt => 1,
+             -Flags => DB_CREATE ;
+     };
+     ok 1, $@ =~ /^Encrypt parameter must be a hash reference at/;
+
+    eval
+    {
+        my $env = new BerkeleyDB::Env @StdErrFile,
+             -Encrypt => {},
+             -Flags => DB_CREATE ;
+     };
+     ok 2, $@ =~ /^Must specify Password and Flags with Encrypt parameter at/;
+
+    eval
+    {
+        my $env = new BerkeleyDB::Env @StdErrFile,
+             -Encrypt => {Password => "fred"},
+             -Flags => DB_CREATE ;
+     };
+     ok 3, $@ =~ /^Must specify Password and Flags with Encrypt parameter at/;
+
+    eval
+    {
+        my $env = new BerkeleyDB::Env @StdErrFile,
+             -Encrypt => {Flags => 1},
+             -Flags => DB_CREATE ;
+     };
+     ok 4, $@ =~ /^Must specify Password and Flags with Encrypt parameter at/;
+
+    eval
+    {
+        my $env = new BerkeleyDB::Env @StdErrFile,
+             -Encrypt => {Fred => 1},
+             -Flags => DB_CREATE ;
+     };
+     ok 5, $@ =~ /^\Qunknown key value(s) Fred at/;
+
+}
+
+{
+    # new BerkeleyDB::Env -Encrypt =>
+
+    # create an environment with a Home
+    my $home = "./fred" ;
+    #mkdir $home;
+    ok 6, my $lexD = new LexDir($home) ;
+    ok 7, my $env = new BerkeleyDB::Env @StdErrFile,
+             -Home => $home,
+             -Encrypt => {Password => "abc",
+	                  Flags    => DB_ENCRYPT_AES
+	                 },
+             -Flags => DB_CREATE | DB_INIT_MPOOL ;
+
+
+
+    my $Dfile = "abc.enc";
+    my $lex = new LexFile $Dfile ;
+    my %hash ;
+    my ($k, $v) ;
+    ok 8, my $db = new BerkeleyDB::Hash -Filename => $Dfile, 
+	                             -Env         => $env,
+				     -Flags       => DB_CREATE, 
+				     -Property    => DB_ENCRYPT ;
+
+    # create some data
+    my %data =  (
+		"red"	=> 2,
+		"green"	=> "house",
+		"blue"	=> "sea",
+		) ;
+
+    my $ret = 0 ;
+    while (($k, $v) = each %data) {
+        $ret += $db->db_put($k, $v) ;
+    }
+    ok 9, $ret == 0 ;
+
+    # check there are three records
+    ok 10, countRecords($db) == 3 ;
+
+    undef $db;
+
+    # once the database is created, do not need to specify DB_ENCRYPT
+    ok 11, my $db1 = new BerkeleyDB::Hash -Filename => $Dfile, 
+	                              -Env      => $env,
+				      -Flags    => DB_CREATE ;
+    $v = '';				      
+    ok 12, ! $db1->db_get("red", $v) ;
+    ok 13, $v eq $data{"red"},
+    undef $db1;
+    undef $env;
+
+    # open a database without specifying encryption
+    ok 14,  ! new BerkeleyDB::Hash -Filename => "$home/$Dfile"; 
+
+    ok 15,  ! new BerkeleyDB::Env 
+             -Home => $home,
+             -Encrypt => {Password => "def",
+	                  Flags    => DB_ENCRYPT_AES
+	                 },
+             -Flags => DB_CREATE | DB_INIT_MPOOL ;
+}
+
+{    
+    eval
+    {
+        my $env = new BerkeleyDB::Hash 
+             -Encrypt => 1,
+             -Flags => DB_CREATE ;
+     };
+     ok 16, $@ =~ /^Encrypt parameter must be a hash reference at/;
+
+    eval
+    {
+        my $env = new BerkeleyDB::Hash 
+             -Encrypt => {},
+             -Flags => DB_CREATE ;
+     };
+     ok 17, $@ =~ /^Must specify Password and Flags with Encrypt parameter at/;
+
+    eval
+    {
+        my $env = new BerkeleyDB::Hash 
+             -Encrypt => {Password => "fred"},
+             -Flags => DB_CREATE ;
+     };
+     ok 18, $@ =~ /^Must specify Password and Flags with Encrypt parameter at/;
+
+    eval
+    {
+        my $env = new BerkeleyDB::Hash 
+             -Encrypt => {Flags => 1},
+             -Flags => DB_CREATE ;
+     };
+     ok 19, $@ =~ /^Must specify Password and Flags with Encrypt parameter at/;
+
+    eval
+    {
+        my $env = new BerkeleyDB::Hash 
+             -Encrypt => {Fred => 1},
+             -Flags => DB_CREATE ;
+     };
+     ok 20, $@ =~ /^\Qunknown key value(s) Fred at/;
+
+}
+
+{    
+    eval
+    {
+        my $env = new BerkeleyDB::Btree 
+             -Encrypt => 1,
+             -Flags => DB_CREATE ;
+     };
+     ok 21, $@ =~ /^Encrypt parameter must be a hash reference at/;
+
+    eval
+    {
+        my $env = new BerkeleyDB::Btree 
+             -Encrypt => {},
+             -Flags => DB_CREATE ;
+     };
+     ok 22, $@ =~ /^Must specify Password and Flags with Encrypt parameter at/;
+
+    eval
+    {
+        my $env = new BerkeleyDB::Btree 
+             -Encrypt => {Password => "fred"},
+             -Flags => DB_CREATE ;
+     };
+     ok 23, $@ =~ /^Must specify Password and Flags with Encrypt parameter at/;
+
+    eval
+    {
+        my $env = new BerkeleyDB::Btree 
+             -Encrypt => {Flags => 1},
+             -Flags => DB_CREATE ;
+     };
+     ok 24, $@ =~ /^Must specify Password and Flags with Encrypt parameter at/;
+
+    eval
+    {
+        my $env = new BerkeleyDB::Btree 
+             -Encrypt => {Fred => 1},
+             -Flags => DB_CREATE ;
+     };
+     ok 25, $@ =~ /^\Qunknown key value(s) Fred at/;
+
+}
+
+{    
+    eval
+    {
+        my $env = new BerkeleyDB::Queue 
+             -Encrypt => 1,
+             -Flags => DB_CREATE ;
+     };
+     ok 26, $@ =~ /^Encrypt parameter must be a hash reference at/;
+
+    eval
+    {
+        my $env = new BerkeleyDB::Queue 
+             -Encrypt => {},
+             -Flags => DB_CREATE ;
+     };
+     ok 27, $@ =~ /^Must specify Password and Flags with Encrypt parameter at/;
+
+    eval
+    {
+        my $env = new BerkeleyDB::Queue 
+             -Encrypt => {Password => "fred"},
+             -Flags => DB_CREATE ;
+     };
+     ok 28, $@ =~ /^Must specify Password and Flags with Encrypt parameter at/;
+
+    eval
+    {
+        my $env = new BerkeleyDB::Queue 
+             -Encrypt => {Flags => 1},
+             -Flags => DB_CREATE ;
+     };
+     ok 29, $@ =~ /^Must specify Password and Flags with Encrypt parameter at/;
+
+    eval
+    {
+        my $env = new BerkeleyDB::Queue 
+             -Encrypt => {Fred => 1},
+             -Flags => DB_CREATE ;
+     };
+     ok 30, $@ =~ /^\Qunknown key value(s) Fred at/;
+
+}
+
+{    
+    eval
+    {
+        my $env = new BerkeleyDB::Recno 
+             -Encrypt => 1,
+             -Flags => DB_CREATE ;
+     };
+     ok 31, $@ =~ /^Encrypt parameter must be a hash reference at/;
+
+    eval
+    {
+        my $env = new BerkeleyDB::Recno 
+             -Encrypt => {},
+             -Flags => DB_CREATE ;
+     };
+     ok 32, $@ =~ /^Must specify Password and Flags with Encrypt parameter at/;
+
+    eval
+    {
+        my $env = new BerkeleyDB::Recno 
+             -Encrypt => {Password => "fred"},
+             -Flags => DB_CREATE ;
+     };
+     ok 33, $@ =~ /^Must specify Password and Flags with Encrypt parameter at/;
+
+    eval
+    {
+        my $env = new BerkeleyDB::Recno 
+             -Encrypt => {Flags => 1},
+             -Flags => DB_CREATE ;
+     };
+     ok 34, $@ =~ /^Must specify Password and Flags with Encrypt parameter at/;
+
+    eval
+    {
+        my $env = new BerkeleyDB::Recno 
+             -Encrypt => {Fred => 1},
+             -Flags => DB_CREATE ;
+     };
+     ok 35, $@ =~ /^\Qunknown key value(s) Fred at/;
+
+}
+
+
+{
+    # new BerkeleyDB::Hash -Encrypt =>
+
+    my $Dfile = "abcd.enc";
+    my $lex = new LexFile $Dfile ;
+    my %hash ;
+    my ($k, $v) ;
+    ok 36, my $db = new BerkeleyDB::Hash 
+                           -Filename => $Dfile, 
+		           -Flags    => DB_CREATE, 
+                           -Encrypt  => {Password => "beta",
+	                                 Flags    => DB_ENCRYPT_AES
+	                                },
+		           -Property => DB_ENCRYPT ;
+
+    # create some data
+    my %data =  (
+		"red"	=> 2,
+		"green"	=> "house",
+		"blue"	=> "sea",
+		) ;
+
+    my $ret = 0 ;
+    while (($k, $v) = each %data) {
+        $ret += $db->db_put($k, $v) ;
+    }
+    ok 37, $ret == 0 ;
+
+    # check there are three records
+    ok 38, countRecords($db) == 3 ;
+
+    undef $db;
+
+    # attempt to open a database without specifying encryption
+    ok 39, ! new BerkeleyDB::Hash -Filename => $Dfile, 
+				      -Flags    => DB_CREATE ;
+
+
+    # try opening with the wrong password				      
+    ok 40, ! new BerkeleyDB::Hash -Filename => $Dfile, 
+                           -Filename => $Dfile, 
+                           -Encrypt => {Password => "def",
+	                                Flags    => DB_ENCRYPT_AES
+	                               },
+		           -Property    => DB_ENCRYPT ;
+
+
+    # read the encrypted data				      
+    ok 41, my $db1 = new BerkeleyDB::Hash -Filename => $Dfile, 
+                           -Filename => $Dfile, 
+                           -Encrypt => {Password => "beta",
+	                                Flags    => DB_ENCRYPT_AES
+	                               },
+		           -Property    => DB_ENCRYPT ;
+
+
+    $v = '';				      
+    ok 42, ! $db1->db_get("red", $v) ;
+    ok 43, $v eq $data{"red"};
+    # check there are three records
+    ok 44, countRecords($db1) == 3 ;
+    undef $db1;
+}
+
+{
+    # new BerkeleyDB::Btree -Encrypt =>
+
+    my $Dfile = "abcd.enc";
+    my $lex = new LexFile $Dfile ;
+    my %hash ;
+    my ($k, $v) ;
+    ok 45, my $db = new BerkeleyDB::Btree 
+                           -Filename => $Dfile, 
+		           -Flags    => DB_CREATE, 
+                           -Encrypt  => {Password => "beta",
+	                                 Flags    => DB_ENCRYPT_AES
+	                                },
+		           -Property => DB_ENCRYPT ;
+
+    # create some data
+    my %data =  (
+		"red"	=> 2,
+		"green"	=> "house",
+		"blue"	=> "sea",
+		) ;
+
+    my $ret = 0 ;
+    while (($k, $v) = each %data) {
+        $ret += $db->db_put($k, $v) ;
+    }
+    ok 46, $ret == 0 ;
+
+    # check there are three records
+    ok 47, countRecords($db) == 3 ;
+
+    undef $db;
+
+    # attempt to open a database without specifying encryption
+    ok 48, ! new BerkeleyDB::Btree -Filename => $Dfile, 
+				      -Flags    => DB_CREATE ;
+
+
+    # try opening with the wrong password				      
+    ok 49, ! new BerkeleyDB::Btree -Filename => $Dfile, 
+                           -Filename => $Dfile, 
+                           -Encrypt => {Password => "def",
+	                                Flags    => DB_ENCRYPT_AES
+	                               },
+		           -Property    => DB_ENCRYPT ;
+
+
+    # read the encrypted data				      
+    ok 50, my $db1 = new BerkeleyDB::Btree -Filename => $Dfile, 
+                           -Filename => $Dfile, 
+                           -Encrypt => {Password => "beta",
+	                                Flags    => DB_ENCRYPT_AES
+	                               },
+		           -Property    => DB_ENCRYPT ;
+
+
+    $v = '';				      
+    ok 51, ! $db1->db_get("red", $v) ;
+    ok 52, $v eq $data{"red"};
+    # check there are three records
+    ok 53, countRecords($db1) == 3 ;
+    undef $db1;
+}
+
+{
+    # new BerkeleyDB::Queue -Encrypt =>
+
+    my $Dfile = "abcd.enc";
+    my $lex = new LexFile $Dfile ;
+    my %hash ;
+    my ($k, $v) ;
+    ok 54, my $db = new BerkeleyDB::Queue 
+                           -Filename => $Dfile, 
+                           -Len      => 5,
+                           -Pad      => "x",
+		           -Flags    => DB_CREATE, 
+                           -Encrypt  => {Password => "beta",
+	                                 Flags    => DB_ENCRYPT_AES
+	                                },
+		           -Property => DB_ENCRYPT ;
+
+    # create some data
+    my %data =  (
+		1	=> 2,
+		2	=> "house",
+		3	=> "sea",
+		) ;
+
+    my $ret = 0 ;
+    while (($k, $v) = each %data) {
+        $ret += $db->db_put($k, $v) ;
+    }
+    ok 55, $ret == 0 ;
+
+    # check there are three records
+    ok 56, countRecords($db) == 3 ;
+
+    undef $db;
+
+    # attempt to open a database without specifying encryption
+    ok 57, ! new BerkeleyDB::Queue -Filename => $Dfile, 
+                                   -Len      => 5,
+                                   -Pad      => "x",
+				   -Flags    => DB_CREATE ;
+
+
+    # try opening with the wrong password				      
+    ok 58, ! new BerkeleyDB::Queue -Filename => $Dfile, 
+                                   -Len      => 5,
+                                   -Pad      => "x",
+                                   -Encrypt => {Password => "def",
+	                                        Flags    => DB_ENCRYPT_AES
+	                                       },
+		                   -Property    => DB_ENCRYPT ;
+
+
+    # read the encrypted data				      
+    ok 59, my $db1 = new BerkeleyDB::Queue -Filename => $Dfile, 
+                                           -Len      => 5,
+                                           -Pad      => "x",
+                                           -Encrypt => {Password => "beta",
+	                                        Flags    => DB_ENCRYPT_AES
+	                                       },
+		                           -Property    => DB_ENCRYPT ;
+
+
+    $v = '';				      
+    ok 60, ! $db1->db_get(3, $v) ;
+    ok 61, $v eq fillout($data{3}, 5, 'x');
+    # check there are three records
+    ok 62, countRecords($db1) == 3 ;
+    undef $db1;
+}
+
+{
+    # new BerkeleyDB::Recno -Encrypt =>
+
+    my $Dfile = "abcd.enc";
+    my $lex = new LexFile $Dfile ;
+    my %hash ;
+    my ($k, $v) ;
+    ok 63, my $db = new BerkeleyDB::Recno 
+                           -Filename => $Dfile, 
+		           -Flags    => DB_CREATE, 
+                           -Encrypt  => {Password => "beta",
+	                                 Flags    => DB_ENCRYPT_AES
+	                                },
+		           -Property => DB_ENCRYPT ;
+
+    # create some data
+    my %data =  (
+		1	=> 2,
+		2	=> "house",
+		3	=> "sea",
+		) ;
+
+    my $ret = 0 ;
+    while (($k, $v) = each %data) {
+        $ret += $db->db_put($k, $v) ;
+    }
+    ok 64, $ret == 0 ;
+
+    # check there are three records
+    ok 65, countRecords($db) == 3 ;
+
+    undef $db;
+
+    # attempt to open a database without specifying encryption
+    ok 66, ! new BerkeleyDB::Recno -Filename => $Dfile, 
+				      -Flags    => DB_CREATE ;
+
+
+    # try opening with the wrong password				      
+    ok 67, ! new BerkeleyDB::Recno -Filename => $Dfile, 
+                           -Filename => $Dfile, 
+                           -Encrypt => {Password => "def",
+	                                Flags    => DB_ENCRYPT_AES
+	                               },
+		           -Property    => DB_ENCRYPT ;
+
+
+    # read the encrypted data				      
+    ok 68, my $db1 = new BerkeleyDB::Recno -Filename => $Dfile, 
+                           -Filename => $Dfile, 
+                           -Encrypt => {Password => "beta",
+	                                Flags    => DB_ENCRYPT_AES
+	                               },
+		           -Property    => DB_ENCRYPT ;
+
+
+    $v = '';				      
+    ok 69, ! $db1->db_get(3, $v) ;
+    ok 70, $v eq $data{3};
+    # check there are three records
+    ok 71, countRecords($db1) == 3 ;
+    undef $db1;
+}
+
+{
+    # new BerkeleyDB::Unknown -Encrypt =>
+
+    my $Dfile = "abcd.enc";
+    my $lex = new LexFile $Dfile ;
+    my %hash ;
+    my ($k, $v) ;
+    ok 72, my $db = new BerkeleyDB::Hash 
+                           -Filename => $Dfile, 
+		           -Flags    => DB_CREATE, 
+                           -Encrypt  => {Password => "beta",
+	                                 Flags    => DB_ENCRYPT_AES
+	                                },
+		           -Property => DB_ENCRYPT ;
+
+    # create some data
+    my %data =  (
+		"red"	=> 2,
+		"green"	=> "house",
+		"blue"	=> "sea",
+		) ;
+
+    my $ret = 0 ;
+    while (($k, $v) = each %data) {
+        $ret += $db->db_put($k, $v) ;
+    }
+    ok 73, $ret == 0 ;
+
+    # check there are three records
+    ok 74, countRecords($db) == 3 ;
+
+    undef $db;
+
+    # attempt to open a database without specifying encryption
+    ok 75, ! new BerkeleyDB::Unknown -Filename => $Dfile, 
+				      -Flags    => DB_CREATE ;
+
+
+    # try opening with the wrong password				      
+    ok 76, ! new BerkeleyDB::Unknown -Filename => $Dfile, 
+                           -Filename => $Dfile, 
+                           -Encrypt => {Password => "def",
+	                                Flags    => DB_ENCRYPT_AES
+	                               },
+		           -Property    => DB_ENCRYPT ;
+
+
+    # read the encrypted data				      
+    ok 77, my $db1 = new BerkeleyDB::Unknown -Filename => $Dfile, 
+                           -Filename => $Dfile, 
+                           -Encrypt => {Password => "beta",
+	                                Flags    => DB_ENCRYPT_AES
+	                               },
+		           -Property    => DB_ENCRYPT ;
+
+
+    $v = '';				      
+    ok 78, ! $db1->db_get("red", $v) ;
+    ok 79, $v eq $data{"red"};
+    # check there are three records
+    ok 80, countRecords($db1) == 3 ;
+    undef $db1;
+}
+
diff --git a/storage/bdb/perl/BerkeleyDB/t/env.t b/storage/bdb/perl/BerkeleyDB/t/env.t
index 3905abfae43ff0849d55d134c2145ac814a18f57..6729ed92bdddd73dd1719fb4b5686ad676478f13 100644
--- a/storage/bdb/perl/BerkeleyDB/t/env.t
+++ b/storage/bdb/perl/BerkeleyDB/t/env.t
@@ -11,23 +11,30 @@ BEGIN {
     }
 }
 
+
+BEGIN {
+    $ENV{LC_ALL} = 'de_DE@euro';
+}
+
 use BerkeleyDB; 
 use t::util ;
 
-print "1..47\n";
+print "1..53\n";
 
 my $Dfile = "dbhash.tmp";
 
 umask(0);
 
+my $version_major  = 0;
+
 {
     # db version stuff
     my ($major, $minor, $patch) = (0, 0, 0) ;
 
     ok 1, my $VER = BerkeleyDB::DB_VERSION_STRING ;
-    ok 2, my $ver = BerkeleyDB::db_version($major, $minor, $patch) ;
+    ok 2, my $ver = BerkeleyDB::db_version($version_major, $minor, $patch) ;
     ok 3, $VER eq $ver ;
-    ok 4, $major > 1 ;
+    ok 4, $version_major > 1 ;
     ok 5, defined $minor ;
     ok 6, defined $patch ;
 }
@@ -43,7 +50,8 @@ umask(0);
 
     eval ' $env = new BerkeleyDB::Env (-Config => {"fred" => " "} ) ; ' ;
     ok 9, !$env ;
-    ok 10, $BerkeleyDB::Error =~ /^illegal name-value pair/ ;
+    ok 10, $BerkeleyDB::Error =~ /^(illegal name-value pair|Invalid argument)/ ;
+    #print " $BerkeleyDB::Error\n";
 }
 
 {
@@ -51,7 +59,8 @@ umask(0);
     my $home = "./fred" ;
     ok 11, my $lexD = new LexDir($home) ;
     chdir "./fred" ;
-    ok 12, my $env = new BerkeleyDB::Env -Flags => DB_CREATE ;
+    ok 12, my $env = new BerkeleyDB::Env -Flags => DB_CREATE,
+					@StdErrFile;
     chdir ".." ;
     undef $env ;
 }
@@ -71,7 +80,7 @@ umask(0);
     my $home = "./not_there" ;
     rmtree $home ;
     ok 15, ! -d $home ;
-    my $env = new BerkeleyDB::Env -Home => $home,
+    my $env = new BerkeleyDB::Env -Home => $home, @StdErrFile,
 			          -Flags => DB_INIT_LOCK ;
     ok 16, ! $env ;
     ok 17,   $! != 0 || $^E != 0 ;
@@ -90,7 +99,7 @@ umask(0);
     ok 18, my $lexD = new LexDir($home) ;
     ok 19, -d $data_dir ? chmod 0777, $data_dir : mkdir($data_dir, 0777) ;
     ok 20, -d $log_dir ? chmod 0777, $log_dir : mkdir($log_dir, 0777) ;
-    my $env = new BerkeleyDB::Env -Home   => $home,
+    my $env = new BerkeleyDB::Env -Home   => $home, @StdErrFile,
 			      -Config => { DB_DATA_DIR => $data_dir,
 					   DB_LOG_DIR  => $log_dir
 					 },
@@ -141,49 +150,63 @@ umask(0);
 }
 
 {
-    # -ErrFile with a filehandle/reference -- should fail
+    # -ErrFile with a filehandle
+    use IO::File ;
+    my $errfile = "./errfile" ;
     my $home = "./fred" ;
     ok 30, my $lexD = new LexDir($home) ;
-    eval { my $env = new BerkeleyDB::Env( -ErrFile => [],
+    my $lex = new LexFile $errfile ;
+    my $fh = new IO::File ">$errfile" ;
+    ok 31, my $env = new BerkeleyDB::Env( -ErrFile => $fh, 
     					  -Flags => DB_CREATE,
-					  -Home   => $home) ; };
-    ok 31, $@ =~ /ErrFile parameter must be a file name/;
+					  -Home   => $home) ;
+    my $db = new BerkeleyDB::Hash -Filename => $Dfile,
+			     -Env      => $env,
+			     -Flags    => -1;
+    ok 32, !$db ;
+
+    ok 33, $BerkeleyDB::Error =~ /^illegal flag specified to (db_open|DB->open)/;
+    ok 34, -e $errfile ;
+    my $contents = docat($errfile) ;
+    chomp $contents ;
+    ok 35, $BerkeleyDB::Error eq $contents ;
+
+    undef $env ;
 }
 
 {
     # -ErrPrefix
-    use IO ;
     my $home = "./fred" ;
-    ok 32, my $lexD = new LexDir($home) ;
+    ok 36, my $lexD = new LexDir($home) ;
     my $errfile = "./errfile" ;
     my $lex = new LexFile $errfile ;
-    ok 33, my $env = new BerkeleyDB::Env( -ErrFile => $errfile,
+    ok 37, my $env = new BerkeleyDB::Env( -ErrFile => $errfile,
 					-ErrPrefix => "PREFIX",
     					  -Flags => DB_CREATE,
 					  -Home   => $home) ;
     my $db = new BerkeleyDB::Hash -Filename => $Dfile,
 			     -Env      => $env,
 			     -Flags    => -1;
-    ok 34, !$db ;
+    ok 38, !$db ;
 
-    ok 35, $BerkeleyDB::Error =~ /^PREFIX: illegal flag specified to (db_open|DB->open)/;
-    ok 36, -e $errfile ;
+    ok 39, $BerkeleyDB::Error =~ /^PREFIX: illegal flag specified to (db_open|DB->open)/;
+    ok 40, -e $errfile ;
     my $contents = docat($errfile) ;
     chomp $contents ;
-    ok 37, $BerkeleyDB::Error eq $contents ;
+    ok 41, $BerkeleyDB::Error eq $contents ;
 
     # change the prefix on the fly
     my $old = $env->errPrefix("NEW ONE") ;
-    ok 38, $old eq "PREFIX" ;
+    ok 42, $old eq "PREFIX" ;
 
     $db = new BerkeleyDB::Hash -Filename => $Dfile,
 			     -Env      => $env,
 			     -Flags    => -1;
-    ok 39, !$db ;
-    ok 40, $BerkeleyDB::Error =~ /^NEW ONE: illegal flag specified to (db_open|DB->open)/;
+    ok 43, !$db ;
+    ok 44, $BerkeleyDB::Error =~ /^NEW ONE: illegal flag specified to (db_open|DB->open)/;
     $contents = docat($errfile) ;
     chomp $contents ;
-    ok 41, $contents =~ /$BerkeleyDB::Error$/ ;
+    ok 45, $contents =~ /$BerkeleyDB::Error$/ ;
     undef $env ;
 }
 
@@ -195,21 +218,41 @@ umask(0);
     my $data_dir = "$home/data_dir" ;
     my $log_dir = "$home/log_dir" ;
     my $data_file = "data.db" ;
-    ok 42, my $lexD = new LexDir($home);
-    ok 43, -d $data_dir ? chmod 0777, $data_dir : mkdir($data_dir, 0777) ;
-    ok 44, -d $log_dir ? chmod 0777, $log_dir : mkdir($log_dir, 0777) ;
-    my $env = new BerkeleyDB::Env -Home   => $home,
+    ok 46, my $lexD = new LexDir($home);
+    ok 47, -d $data_dir ? chmod 0777, $data_dir : mkdir($data_dir, 0777) ;
+    ok 48, -d $log_dir ? chmod 0777, $log_dir : mkdir($log_dir, 0777) ;
+    my $env = new BerkeleyDB::Env -Home   => $home, @StdErrFile,
 			      -Config => { DB_DATA_DIR => $data_dir,
 					   DB_LOG_DIR  => $log_dir
 					 },
 			      -Flags  => DB_CREATE|DB_INIT_TXN|DB_INIT_LOG|
 					 DB_INIT_MPOOL|DB_INIT_LOCK ;
-    ok 45, $env ;
+    ok 49, $env ;
+
+    ok 50, my $txn_mgr = $env->TxnMgr() ;
 
-    ok 46, my $txn_mgr = $env->TxnMgr() ;
+    ok 51, $env->db_appexit() == 0 ;
 
-    ok 47, $env->db_appexit() == 0 ;
+}
+
+{
+    # attempt to open a new environment without DB_CREATE
+    # should fail with Berkeley DB 3.x or better.
 
+    my $home = "./fred" ;
+    ok 52, my $lexD = new LexDir($home) ;
+    chdir "./fred" ;
+    my $env = new BerkeleyDB::Env -Home => $home, -Flags => DB_CREATE ;
+    ok 53, $version_major == 2 ? $env : ! $env ;
+
+    # The test below is not portable -- the error message returned by
+    # $BerkeleyDB::Error is locale dependant.
+
+    #ok 54, $version_major == 2 ? 1 
+    #                           : $BerkeleyDB::Error =~ /No such file or directory/ ;
+    #    or print "# BerkeleyDB::Error is $BerkeleyDB::Error\n";
+    chdir ".." ;
+    undef $env ;
 }
 
 # test -Verbose
diff --git a/storage/bdb/perl/BerkeleyDB/t/filter.t b/storage/bdb/perl/BerkeleyDB/t/filter.t
index 47a7c107acf1462b01cb38039e407ed8e379149b..ff1435ae75ede0407ee2eea9965a41f8d12f9531 100644
--- a/storage/bdb/perl/BerkeleyDB/t/filter.t
+++ b/storage/bdb/perl/BerkeleyDB/t/filter.t
@@ -14,7 +14,7 @@ BEGIN {
 use BerkeleyDB; 
 use t::util ;
 
-print "1..46\n";
+print "1..52\n";
 
 my $Dfile = "dbhash.tmp";
 unlink $Dfile;
@@ -80,6 +80,7 @@ umask(0) ;
 
    ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
    ok 8, $h{"Fred"} eq "[Jxe]";
+   print "$h{'Fred'}\n";
    #                   fk   sk     fv    sv
    ok 9, checkOutput( "", "fred", "[Jxe]", "") ;
 
@@ -207,11 +208,123 @@ umask(0) ;
    $db->filter_store_key (sub { $_ = $h{$_} }) ;
 
    eval '$h{1} = 1234' ;
-   ok 46, $@ =~ /^BerkeleyDB Aborting: recursion detected in filter_store_key at/ ;
-   #print "[$@]\n" ;
+   ok 46, $@ =~ /^recursion detected in filter_store_key at/ ;
    
    undef $db ;
    untie %h;
    unlink $Dfile;
 }
 
+{
+   # Check that DBM Filter can cope with read-only $_
+
+   #use warnings ;
+   use strict ;
+   my (%h, $db) ;
+   unlink $Dfile;
+
+   ok 47, $db = tie %h, 'BerkeleyDB::Hash', 
+    		-Filename   => $Dfile, 
+	        -Flags      => DB_CREATE; 
+
+   $db->filter_fetch_key   (sub { }) ;
+   $db->filter_store_key   (sub { }) ;
+   $db->filter_fetch_value (sub { }) ;
+   $db->filter_store_value (sub { }) ;
+
+   $_ = "original" ;
+
+   $h{"fred"} = "joe" ;
+   ok(48, $h{"fred"} eq "joe");
+
+   eval { grep { $h{$_} } (1, 2, 3) };
+   ok (49, ! $@);
+
+
+   # delete the filters
+   $db->filter_fetch_key   (undef);
+   $db->filter_store_key   (undef);
+   $db->filter_fetch_value (undef);
+   $db->filter_store_value (undef);
+
+   $h{"fred"} = "joe" ;
+
+   ok(50, $h{"fred"} eq "joe");
+
+   ok(51, $db->FIRSTKEY() eq "fred") ;
+   
+   eval { grep { $h{$_} } (1, 2, 3) };
+   ok (52, ! $@);
+
+   undef $db ;
+   untie %h;
+   unlink $Dfile;
+}
+
+if(0)
+{
+    # Filter without tie
+    use strict ;
+    my (%h, $db) ;
+
+    unlink $Dfile;
+    ok 53, $db = tie %h, 'BerkeleyDB::Hash', 
+    		-Filename   => $Dfile, 
+	        -Flags      => DB_CREATE; 
+
+    my %result = () ;
+
+    sub INC { return ++ $_[0] }
+    sub DEC { return -- $_[0] }
+    #$db->filter_fetch_key   (sub { warn "FFK $_\n"; $_ = INC($_); warn "XX\n" }) ;
+    #$db->filter_store_key   (sub { warn "FSK $_\n"; $_ = DEC($_); warn "XX\n" }) ;
+    #$db->filter_fetch_value (sub { warn "FFV $_\n"; $_ = INC($_); warn "XX\n"}) ;
+    #$db->filter_store_value (sub { warn "FSV $_\n"; $_ = DEC($_); warn "XX\n" }) ;
+
+    $db->filter_fetch_key   (sub { warn "FFK $_\n"; $_ = pack("i", $_); warn "XX\n" }) ;
+    $db->filter_store_key   (sub { warn "FSK $_\n"; $_ = unpack("i", $_); warn "XX\n" }) ;
+    $db->filter_fetch_value (sub { warn "FFV $_\n"; $_ = pack("i", $_); warn "XX\n"}) ;
+    #$db->filter_store_value (sub { warn "FSV $_\n"; $_ = unpack("i", $_); warn "XX\n" }) ;
+
+    #$db->filter_fetch_key   (sub { ++ $_ }) ;
+    #$db->filter_store_key   (sub { -- $_ }) ;
+    #$db->filter_fetch_value (sub { ++ $_ }) ;
+    #$db->filter_store_value (sub { -- $_ }) ;
+
+    my ($k, $v) = (0,0);
+    ok 54, ! $db->db_put(3,5);
+    exit;
+    ok 55, ! $db->db_get(3, $v);
+    ok 56, $v == 5 ;
+
+    $h{4} = 7 ;
+    ok 57, $h{4} == 7;
+
+    $k = 10;
+    $v = 30;
+    $h{$k} = $v ;
+    ok 58, $k == 10;
+    ok 59, $v == 30;
+    ok 60, $h{$k} == 30;
+
+    $k = 3;
+    ok 61, ! $db->db_get($k, $v, DB_GET_BOTH);
+    ok 62, $k == 3 ;
+    ok 63, $v == 5 ;
+
+    my $cursor = $db->db_cursor();
+
+    my %tmp = ();
+    while ($cursor->c_get($k, $v, DB_NEXT) == 0)
+    {
+	$tmp{$k} = $v;
+    }
+
+    ok 64, keys %tmp == 3 ;
+    ok 65, $tmp{3} == 5;
+
+    undef $cursor ;
+    undef $db ;
+    untie %h;
+    unlink $Dfile;
+}
diff --git a/storage/bdb/perl/BerkeleyDB/t/hash.t b/storage/bdb/perl/BerkeleyDB/t/hash.t
index 0e683851c3de2d320da8ff9cea989da346822b78..25b8b20cd119af24dea00d18cac80bf07b2b997a 100644
--- a/storage/bdb/perl/BerkeleyDB/t/hash.t
+++ b/storage/bdb/perl/BerkeleyDB/t/hash.t
@@ -103,7 +103,7 @@ umask(0) ;
     my $home = "./fred" ;
     ok 28, my $lexD = new LexDir($home);
 
-    ok 29, my $env = new BerkeleyDB::Env -Flags => DB_CREATE| DB_INIT_MPOOL,
+    ok 29, my $env = new BerkeleyDB::Env -Flags => DB_CREATE| DB_INIT_MPOOL,@StdErrFile,
     					 -Home  => $home ;
     ok 30, my $db = new BerkeleyDB::Hash -Filename => $Dfile, 
 				    -Env      => $env,
@@ -118,6 +118,7 @@ umask(0) ;
     undef $env ;
 }
 
+
 {
     # override default hash
     my $lex = new LexFile $Dfile ;
@@ -437,7 +438,7 @@ umask(0) ;
 
     my $home = "./fred" ;
     ok 146, my $lexD = new LexDir($home);
-    ok 147, my $env = new BerkeleyDB::Env -Home => $home,
+    ok 147, my $env = new BerkeleyDB::Env -Home => $home,@StdErrFile,
 				     -Flags => DB_CREATE|DB_INIT_TXN|
 					  	DB_INIT_MPOOL|DB_INIT_LOCK ;
     ok 148, my $txn = $env->txn_begin() ;
@@ -664,7 +665,7 @@ umask(0) ;
 
    require Exporter ;
    use BerkeleyDB;
-   @ISA=qw(BerkeleyDB::Hash);
+   @ISA=qw(BerkeleyDB BerkeleyDB::Hash);
    @EXPORT = @BerkeleyDB::EXPORT ;
 
    sub db_put { 
diff --git a/storage/bdb/perl/BerkeleyDB/t/join.t b/storage/bdb/perl/BerkeleyDB/t/join.t
index ed9b6a269cbe6232a631351622653b277412b814..ae7942f2c6b2f7d56ea80add70d076c26dc3f999 100644
--- a/storage/bdb/perl/BerkeleyDB/t/join.t
+++ b/storage/bdb/perl/BerkeleyDB/t/join.t
@@ -21,7 +21,7 @@ if ($BerkeleyDB::db_ver < 2.005002)
 }
 
 
-print "1..37\n";
+print "1..42\n";
 
 my $Dfile1 = "dbhash1.tmp";
 my $Dfile2 = "dbhash2.tmp";
@@ -46,18 +46,24 @@ umask(0) ;
 
     # no cursors supplied
     eval '$cursor = $db1->db_join() ;' ;
-    ok 2, $@ =~ /Usage: \$db->BerkeleyDB::Common::db_join\Q([cursors], flags=0)/;
+    ok 2, $@ =~ /Usage: \$db->BerkeleyDB::db_join\Q([cursors], flags=0)/;
 
     # empty list
     eval '$cursor = $db1->db_join([]) ;' ;
     ok 3, $@ =~ /db_join: No cursors in parameter list/;
 
-    # cursor list, isn't a []
+    # cursor list, isn not a []
     eval '$cursor = $db1->db_join({}) ;' ;
-    ok 4, $@ =~ /cursors is not an array reference at/ ;
+    ok 4, $@ =~ /db_join: first parameter is not an array reference/;
 
     eval '$cursor = $db1->db_join(\1) ;' ;
-    ok 5, $@ =~ /cursors is not an array reference at/ ;
+    ok 5, $@ =~ /db_join: first parameter is not an array reference/;
+
+    my ($a, $b) = ("a", "b");
+    $a = bless [], "fred";
+    $b = bless [], "fred";
+    eval '$cursor = $db1->db_join($a, $b) ;' ;
+    ok 6, $@ =~ /db_join: first parameter is not an array reference/;
 
 }
 
@@ -71,14 +77,16 @@ umask(0) ;
     my $value ;
     my $status ;
 
-    my $home = "./fred" ;
-    ok 6, my $lexD = new LexDir($home);
-    ok 7, my $env = new BerkeleyDB::Env -Home => $home,
+    my $home = "./fred7" ;
+    rmtree $home;
+    ok 7, ! -d $home;
+    ok 8, my $lexD = new LexDir($home);
+    ok 9, my $env = new BerkeleyDB::Env -Home => $home, @StdErrFile,
 				     -Flags => DB_CREATE|DB_INIT_TXN
 					  	|DB_INIT_MPOOL;
 					  	#|DB_INIT_MPOOL| DB_INIT_LOCK;
-    ok 8, my $txn = $env->txn_begin() ;
-    ok 9, my $db1 = tie %hash1, 'BerkeleyDB::Hash', 
+    ok 10, my $txn = $env->txn_begin() ;
+    ok 11, my $db1 = tie %hash1, 'BerkeleyDB::Hash', 
 				-Filename => $Dfile1,
                                	-Flags     => DB_CREATE,
                                 -DupCompare   => sub { $_[0] cmp $_[1] },
@@ -87,7 +95,7 @@ umask(0) ;
 			    	-Txn	   => $txn  ;
 				;
 
-    ok 10, my $db2 = tie %hash2, 'BerkeleyDB::Hash', 
+    ok 12, my $db2 = tie %hash2, 'BerkeleyDB::Hash', 
 				-Filename => $Dfile2,
                                	-Flags     => DB_CREATE,
                                 -DupCompare   => sub { $_[0] cmp $_[1] },
@@ -95,7 +103,7 @@ umask(0) ;
 			       	-Env 	   => $env,
 			    	-Txn	   => $txn  ;
 
-    ok 11, my $db3 = tie %hash3, 'BerkeleyDB::Btree', 
+    ok 13, my $db3 = tie %hash3, 'BerkeleyDB::Btree', 
 				-Filename => $Dfile3,
                                	-Flags     => DB_CREATE,
                                 -DupCompare   => sub { $_[0] cmp $_[1] },
@@ -104,7 +112,7 @@ umask(0) ;
 			    	-Txn	   => $txn  ;
 
     
-    ok 12, addData($db1, qw( 	apple		Convenience
+    ok 14, addData($db1, qw( 	apple		Convenience
     				peach		Shopway
 				pear		Farmer
 				raspberry	Shopway
@@ -113,7 +121,7 @@ umask(0) ;
 				blueberry	Farmer
     			));
 
-    ok 13, addData($db2, qw( 	red	apple
+    ok 15, addData($db2, qw( 	red	apple
     				red	raspberry
     				red	strawberry
 				yellow	peach
@@ -121,7 +129,7 @@ umask(0) ;
 				green	gooseberry
 				blue	blueberry)) ;
 
-    ok 14, addData($db3, qw( 	expensive	apple
+    ok 16, addData($db3, qw( 	expensive	apple
     				reasonable	raspberry
     				expensive	strawberry
 				reasonable	peach
@@ -129,13 +137,13 @@ umask(0) ;
 				expensive	gooseberry
 				reasonable	blueberry)) ;
 
-    ok 15, my $cursor2 = $db2->db_cursor() ;
+    ok 17, my $cursor2 = $db2->db_cursor() ;
     my $k = "red" ;
     my $v = "" ;
-    ok 16, $cursor2->c_get($k, $v, DB_SET) == 0 ;
+    ok 18, $cursor2->c_get($k, $v, DB_SET) == 0 ;
 
     # Two way Join
-    ok 17, my $cursor1 = $db1->db_join([$cursor2]) ;
+    ok 19, my $cursor1 = $db1->db_join([$cursor2]) ;
 
     my %expected = qw( apple Convenience
 			raspberry Shopway
@@ -148,20 +156,20 @@ umask(0) ;
 	    if defined $expected{$k} && $expected{$k} eq $v ;
 	#print "[$k] [$v]\n" ;
     }
-    ok 18, keys %expected == 0 ;
-    ok 19, $cursor1->status() == DB_NOTFOUND ;
+    ok 20, keys %expected == 0 ;
+    ok 21, $cursor1->status() == DB_NOTFOUND ;
 
     # Three way Join
-    ok 20, $cursor2 = $db2->db_cursor() ;
+    ok 22, $cursor2 = $db2->db_cursor() ;
     $k = "red" ;
     $v = "" ;
-    ok 21, $cursor2->c_get($k, $v, DB_SET) == 0 ;
+    ok 23, $cursor2->c_get($k, $v, DB_SET) == 0 ;
 
-    ok 22, my $cursor3 = $db3->db_cursor() ;
+    ok 24, my $cursor3 = $db3->db_cursor() ;
     $k = "expensive" ;
     $v = "" ;
-    ok 23, $cursor3->c_get($k, $v, DB_SET) == 0 ;
-    ok 24, $cursor1 = $db1->db_join([$cursor2, $cursor3]) ;
+    ok 25, $cursor3->c_get($k, $v, DB_SET) == 0 ;
+    ok 26, $cursor1 = $db1->db_join([$cursor2, $cursor3]) ;
 
     %expected = qw( apple Convenience
 			strawberry Shopway
@@ -173,21 +181,21 @@ umask(0) ;
 	    if defined $expected{$k} && $expected{$k} eq $v ;
 	#print "[$k] [$v]\n" ;
     }
-    ok 25, keys %expected == 0 ;
-    ok 26, $cursor1->status() == DB_NOTFOUND ;
+    ok 27, keys %expected == 0 ;
+    ok 28, $cursor1->status() == DB_NOTFOUND ;
 
     # test DB_JOIN_ITEM
     # #################
-    ok 27, $cursor2 = $db2->db_cursor() ;
+    ok 29, $cursor2 = $db2->db_cursor() ;
     $k = "red" ;
     $v = "" ;
-    ok 28, $cursor2->c_get($k, $v, DB_SET) == 0 ;
+    ok 30, $cursor2->c_get($k, $v, DB_SET) == 0 ;
  
-    ok 29, $cursor3 = $db3->db_cursor() ;
+    ok 31, $cursor3 = $db3->db_cursor() ;
     $k = "expensive" ;
     $v = "" ;
-    ok 30, $cursor3->c_get($k, $v, DB_SET) == 0 ;
-    ok 31, $cursor1 = $db1->db_join([$cursor2, $cursor3]) ;
+    ok 32, $cursor3->c_get($k, $v, DB_SET) == 0 ;
+    ok 33, $cursor1 = $db1->db_join([$cursor2, $cursor3]) ;
  
     %expected = qw( apple 1
                         strawberry 1
@@ -201,16 +209,24 @@ umask(0) ;
             if defined $expected{$k} ;
         #print "[$k]\n" ;
     }
-    ok 32, keys %expected == 0 ;
-    ok 33, $cursor1->status() == DB_NOTFOUND ;
+    ok 34, keys %expected == 0 ;
+    ok 35, $cursor1->status() == DB_NOTFOUND ;
 
-    ok 34, $cursor1->c_close() == 0 ;
-    ok 35, $cursor2->c_close() == 0 ;
-    ok 36, $cursor3->c_close() == 0 ;
+    ok 36, $cursor1->c_close() == 0 ;
+    ok 37, $cursor2->c_close() == 0 ;
+    ok 38, $cursor3->c_close() == 0 ;
 
-    ok 37, ($status = $txn->txn_commit) == 0;
+    ok 39, ($status = $txn->txn_commit()) == 0;
 
     undef $txn ;
+
+    ok 40, my $cursor1a = $db1->db_cursor() ;
+    eval { $cursor1 = $db1->db_join([$cursor1a]) };
+    ok 41, $@ =~ /BerkeleyDB Aborting: attempted to do a self-join at/;
+    eval { $cursor1 = $db1->db_join([$cursor1]) } ;
+    ok 42, $@ =~ /BerkeleyDB Aborting: attempted to do a self-join at/;
+
+    undef $cursor1a;
     #undef $cursor1;
     #undef $cursor2;
     #undef $cursor3;
@@ -222,4 +238,5 @@ umask(0) ;
     untie %hash2 ;
     untie %hash3 ;
 }
+
 print "# at the end\n";
diff --git a/storage/bdb/perl/BerkeleyDB/t/mldbm.t b/storage/bdb/perl/BerkeleyDB/t/mldbm.t
index d35f7e158959a466aa5937aafe08531bc5687d8b..215d34f4265bda83e551a883139c3ca6572b6d7f 100644
--- a/storage/bdb/perl/BerkeleyDB/t/mldbm.t
+++ b/storage/bdb/perl/BerkeleyDB/t/mldbm.t
@@ -5,22 +5,22 @@ use strict ;
 BEGIN 
 {
     if ($] < 5.005) {
-	print "1..0 # This is Perl $], skipping test\n" ;
+	print "1..0 # Skip: this is Perl $], skipping test\n" ;
 	exit 0 ;
     }
 
     eval { require Data::Dumper ; };
     if ($@) {
-	print "1..0 # Data::Dumper is not installed on this system.\n";
+	print "1..0 # Skip: Data::Dumper is not installed on this system.\n";
 	exit 0 ;
     }
     if ($Data::Dumper::VERSION < 2.08) {
-	print "1..0 # Data::Dumper 2.08 or better required (found $Data::Dumper::VERSION).\n";
+	print "1..0 # Skip: Data::Dumper 2.08 or better required (found $Data::Dumper::VERSION).\n";
 	exit 0 ;
     }
     eval { require MLDBM ; };
     if ($@) {
-	print "1..0 # MLDBM is not installed on this system.\n";
+	print "1..0 # Skip: MLDBM is not installed on this system.\n";
 	exit 0 ;
     }
 }
@@ -57,36 +57,9 @@ print "1..12\n";
     $o{d} = "{once upon a time}";
     $o{e} = 1024;
     $o{f} = 1024.1024;
-    my $first = Data::Dumper->new([@o{qw(a b c)}], [qw(a b c)])->Quotekeys(0)->Dump;
-    my $second = <<'EOT';
-$a = [
-       1,
-       {
-         a => $a,
-         b => $a->[1],
-         c => [
-                \'c'
-              ]
-       },
-       $a->[1]{c}
-     ];
-$b = {
-       a => [
-              1,
-              $b,
-              [
-                \'c'
-              ]
-            ],
-       b => $b,
-       c => $b->{a}[2]
-     };
-$c = [
-       \'c'
-     ];
-EOT
     
-    ::ok 3, $first eq $second ;
+    my $struct = [@o{qw(a b c)}];
+    ::ok 3, ::_compare([$a, $b, $c], $struct);
     ::ok 4, $o{d} eq "{once upon a time}" ;
     ::ok 5, $o{e} == 1024 ;
     ::ok 6, $o{f} eq 1024.1024 ;
@@ -124,36 +97,9 @@ EOT
     $o{d} = "{once upon a time}";
     $o{e} = 1024;
     $o{f} = 1024.1024;
-    my $first = Data::Dumper->new([@o{qw(a b c)}], [qw(a b c)])->Quotekeys(0)->Dump;
-    my $second = <<'EOT';
-$a = [
-       1,
-       {
-         a => $a,
-         b => $a->[1],
-         c => [
-                \'c'
-              ]
-       },
-       $a->[1]{c}
-     ];
-$b = {
-       a => [
-              1,
-              $b,
-              [
-                \'c'
-              ]
-            ],
-       b => $b,
-       c => $b->{a}[2]
-     };
-$c = [
-       \'c'
-     ];
-EOT
 
-    ::ok 9, $first eq $second ;
+    my $struct = [@o{qw(a b c)}];
+    ::ok 9, ::_compare([$a, $b, $c], $struct);
     ::ok 10, $o{d} eq "{once upon a time}" ;
     ::ok 11, $o{e} == 1024 ;
     ::ok 12, $o{f} eq 1024.1024 ;
diff --git a/storage/bdb/perl/BerkeleyDB/t/pod.t b/storage/bdb/perl/BerkeleyDB/t/pod.t
new file mode 100644
index 0000000000000000000000000000000000000000..230df4bd9c3d04eb5fa60bb367a3065a02e24485
--- /dev/null
+++ b/storage/bdb/perl/BerkeleyDB/t/pod.t
@@ -0,0 +1,18 @@
+eval " use Test::More " ;
+
+if ($@)
+{
+    print "1..0 # Skip: Test::More required for testing POD\n" ;
+    exit 0;
+}
+
+eval "use Test::Pod 1.00";
+
+if ($@)
+{
+    print "1..0 # Skip: Test::Pod 1.00 required for testing POD\n" ;
+    exit 0;
+}
+
+all_pod_files_ok();
+
diff --git a/storage/bdb/perl/BerkeleyDB/t/queue.t b/storage/bdb/perl/BerkeleyDB/t/queue.t
index 86add129ca4b620d3b1cc1fd6cf377c8d9b11ab8..00291641c4f66d252daf836200e72bc0d4ba73af 100644
--- a/storage/bdb/perl/BerkeleyDB/t/queue.t
+++ b/storage/bdb/perl/BerkeleyDB/t/queue.t
@@ -17,23 +17,13 @@ use t::util ;
 BEGIN 
 {
     if ($BerkeleyDB::db_version < 3.3) {
-	print "1..0 # Skipping test, Queue needs Berkeley DB 3.3.x or better\n" ;
+	print "1..0 # Skip: Queue needs Berkeley DB 3.3.x or better\n" ;
 	exit 0 ;
     }
 }    
 
-print "1..201\n";
+print "1..200\n";
 
-sub fillout
-{
-    my $var = shift ;
-    my $length = shift ;
-    my $pad = shift || " " ;
-    my $template = $pad x $length ;
-    substr($template, 0, length($var)) = $var ;
-    return $template ;
-}
- 
 my $Dfile = "dbhash.tmp";
 my $Dfile2 = "dbhash2.tmp";
 my $Dfile3 = "dbhash3.tmp";
@@ -85,29 +75,32 @@ umask(0) ;
     ok 11, $db->db_put(2, "value") == 0  ;
     ok 12, $db->db_get(2, $value) == 0 ;
     ok 13, $value eq fillout("value", $rec_len, $pad) ;
-    ok 14, $db->db_del(1) == 0 ;
-    ok 15, ($status = $db->db_get(1, $value)) == DB_KEYEMPTY ;
-    ok 16, $db->status() == DB_KEYEMPTY ;
-    ok 17, $db->status() eq $DB_errors{'DB_KEYEMPTY'} ;
+    ok 14, $db->db_put(3, "value") == 0  ;
+    ok 15, $db->db_get(3, $value) == 0 ;
+    ok 16, $value eq fillout("value", $rec_len, $pad) ;
+    ok 17, $db->db_del(2) == 0 ;
+    ok 18, ($status = $db->db_get(2, $value)) == DB_KEYEMPTY ;
+    ok 19, $db->status() == DB_KEYEMPTY ;
+    ok 20, $db->status() eq $DB_errors{'DB_KEYEMPTY'} ;
 
-    ok 18, ($status = $db->db_get(7, $value)) == DB_NOTFOUND ;
-    ok 19, $db->status() == DB_NOTFOUND ;
-    ok 20, $db->status() eq $DB_errors{'DB_NOTFOUND'} ;
+    ok 21, ($status = $db->db_get(7, $value)) == DB_NOTFOUND ;
+    ok 22, $db->status() == DB_NOTFOUND ;
+    ok 23, $db->status() eq $DB_errors{'DB_NOTFOUND'} ;
 
-    ok 21, $db->db_sync() == 0 ;
+    ok 24, $db->db_sync() == 0 ;
 
     # Check NOOVERWRITE will make put fail when attempting to overwrite
     # an existing record.
 
-    ok 22, $db->db_put( 2, 'x', DB_NOOVERWRITE) == DB_KEYEXIST ;
-    ok 23, $db->status() eq $DB_errors{'DB_KEYEXIST'} ;
-    ok 24, $db->status() == DB_KEYEXIST ;
+    ok 25, $db->db_put( 1, 'x', DB_NOOVERWRITE) == DB_KEYEXIST ;
+    ok 26, $db->status() eq $DB_errors{'DB_KEYEXIST'} ;
+    ok 27, $db->status() == DB_KEYEXIST ;
 
 
     # check that the value of the key  has not been changed by the
     # previous test
-    ok 25, $db->db_get(2, $value) == 0 ;
-    ok 26, $value eq fillout("value", $rec_len, $pad) ;
+    ok 28, $db->db_get(1, $value) == 0 ;
+    ok 29, $value eq fillout("some value", $rec_len, $pad) ;
 
 
 }
@@ -120,20 +113,20 @@ umask(0) ;
 
     my $home = "./fred" ;
     my $rec_len = 11 ;
-    ok 27, my $lexD = new LexDir($home);
+    ok 30, my $lexD = new LexDir($home);
 
-    ok 28, my $env = new BerkeleyDB::Env -Flags => DB_CREATE|DB_INIT_MPOOL,
+    ok 31, my $env = new BerkeleyDB::Env -Flags => DB_CREATE|DB_INIT_MPOOL,@StdErrFile,
     					 -Home => $home ;
-    ok 29, my $db = new BerkeleyDB::Queue -Filename => $Dfile, 
+    ok 32, my $db = new BerkeleyDB::Queue -Filename => $Dfile, 
 				    -Env      => $env,
 				    -Flags    => DB_CREATE,
 				    -Len      => $rec_len;
 
     # Add a k/v pair
     my $value ;
-    ok 30, $db->db_put(1, "some value") == 0 ;
-    ok 31, $db->db_get(1, $value) == 0 ;
-    ok 32, $value eq fillout("some value", $rec_len)  ;
+    ok 33, $db->db_put(1, "some value") == 0 ;
+    ok 34, $db->db_get(1, $value) == 0 ;
+    ok 35, $value eq fillout("some value", $rec_len)  ;
     undef $db ;
     undef $env ;
 }
@@ -146,7 +139,7 @@ umask(0) ;
     my @array ;
     my ($k, $v) ;
     my $rec_len = 5 ;
-    ok 33, my $db = new BerkeleyDB::Queue -Filename  => $Dfile, 
+    ok 36, my $db = new BerkeleyDB::Queue -Filename  => $Dfile, 
 				    	  -ArrayBase => 0,
 				    	  -Flags     => DB_CREATE ,
 				    	  -Len       => $rec_len;
@@ -165,10 +158,10 @@ umask(0) ;
         $ret += $db->db_put($i, $data[$i]) ;
 	$data{$i} = $data[$i] ;
     }
-    ok 34, $ret == 0 ;
+    ok 37, $ret == 0 ;
 
     # create the cursor
-    ok 35, my $cursor = $db->db_cursor() ;
+    ok 38, my $cursor = $db->db_cursor() ;
 
     $k = 0 ; $v = "" ;
     my %copy = %data;
@@ -182,10 +175,10 @@ umask(0) ;
 	    { ++ $extras }
     }
 
-    ok 36, $cursor->status() == DB_NOTFOUND ;
-    ok 37, $cursor->status() eq $DB_errors{'DB_NOTFOUND'} ;
-    ok 38, keys %copy == 0 ;
-    ok 39, $extras == 0 ;
+    ok 39, $cursor->status() == DB_NOTFOUND ;
+    ok 40, $cursor->status() eq $DB_errors{'DB_NOTFOUND'} ;
+    ok 41, keys %copy == 0 ;
+    ok 42, $extras == 0 ;
 
     # sequence backwards
     %copy = %data ;
@@ -199,12 +192,12 @@ umask(0) ;
 	else
 	    { ++ $extras }
     }
-    ok 40, $status == DB_NOTFOUND ;
-    ok 41, $status eq $DB_errors{'DB_NOTFOUND'} ;
-    ok 42, $cursor->status() == $status ;
-    ok 43, $cursor->status() eq $status ;
-    ok 44, keys %copy == 0 ;
-    ok 45, $extras == 0 ;
+    ok 43, $status == DB_NOTFOUND ;
+    ok 44, $status eq $DB_errors{'DB_NOTFOUND'} ;
+    ok 45, $cursor->status() == $status ;
+    ok 46, $cursor->status() eq $status ;
+    ok 47, keys %copy == 0 ;
+    ok 48, $extras == 0 ;
 }
  
 {
@@ -214,37 +207,32 @@ umask(0) ;
     my @array ;
     my $db ;
     my $rec_len = 10 ;
-    ok 46, $db = tie @array, 'BerkeleyDB::Queue', -Filename  => $Dfile,
+    ok 49, $db = tie @array, 'BerkeleyDB::Queue', -Filename  => $Dfile,
 				    	    -ArrayBase => 0,
                                             -Flags     => DB_CREATE ,
 				    	    -Len       => $rec_len;
 
-    ok 47, my $cursor = (tied @array)->db_cursor() ;
+    ok 50, my $cursor = (tied @array)->db_cursor() ;
     # check the database is empty
     my $count = 0 ;
     my ($k, $v) = (0,"") ;
     while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
 	++ $count ;
     }
-    ok 48, $cursor->status() == DB_NOTFOUND ;
-    ok 49, $count == 0 ;
+    ok 51, $cursor->status() == DB_NOTFOUND ;
+    ok 52, $count == 0 ;
 
-    ok 50, @array == 0 ;
+    ok 53, @array == 0 ;
 
     # Add a k/v pair
     my $value ;
     $array[1] = "some value";
-    ok 51, (tied @array)->status() == 0 ;
-    ok 52, $array[1] eq fillout("some value", $rec_len);
-    ok 53, defined $array[1];
     ok 54, (tied @array)->status() == 0 ;
-    ok 55, !defined $array[3];
-    ok 56, (tied @array)->status() == DB_NOTFOUND ;
-
-    ok 57, (tied @array)->db_del(1) == 0 ;
-    ok 58, (tied @array)->status() == 0 ;
-    ok 59, ! defined $array[1];
-    ok 60, (tied @array)->status() == DB_KEYEMPTY ;
+    ok 55, $array[1] eq fillout("some value", $rec_len);
+    ok 56, defined $array[1];
+    ok 57, (tied @array)->status() == 0 ;
+    ok 58, !defined $array[3];
+    ok 59, (tied @array)->status() == DB_NOTFOUND ;
 
     $array[1] = 2 ;
     $array[10] = 20 ;
@@ -259,9 +247,9 @@ umask(0) ;
 	$values += $v ;
 	++ $count ;
     }
-    ok 61, $count == 3 ;
-    ok 62, $keys == 1011 ;
-    ok 63, $values == 2022 ;
+    ok 60, $count == 3 ;
+    ok 61, $keys == 1011 ;
+    ok 62, $values == 2022 ;
 
     # unshift isn't allowed
 #    eval {
@@ -273,51 +261,51 @@ umask(0) ;
     $array[1] = "green" ;
     $array[2] = "blue" ;
     $array[4] = 2 ;
-    ok 64, $array[0] eq fillout("red", $rec_len) ;
-    ok 65, $cursor->c_get($k, $v, DB_FIRST) == 0 ;
-    ok 66, $k == 0 ;
-    ok 67, $v eq fillout("red", $rec_len) ;
-    ok 68, $array[1] eq fillout("green", $rec_len) ;
-    ok 69, $cursor->c_get($k, $v, DB_NEXT) == 0 ;
-    ok 70, $k == 1 ;
-    ok 71, $v eq fillout("green", $rec_len) ;
-    ok 72, $array[2] eq fillout("blue", $rec_len) ;
-    ok 73, $cursor->c_get($k, $v, DB_NEXT) == 0 ;
-    ok 74, $k == 2 ;
-    ok 75, $v eq fillout("blue", $rec_len) ;
-    ok 76, $array[4] == 2 ;
-    ok 77, $cursor->c_get($k, $v, DB_NEXT) == 0 ;
-    ok 78, $k == 4 ;
-    ok 79, $v == 2 ;
+    ok 63, $array[0] eq fillout("red", $rec_len) ;
+    ok 64, $cursor->c_get($k, $v, DB_FIRST) == 0 ;
+    ok 65, $k == 0 ;
+    ok 66, $v eq fillout("red", $rec_len) ;
+    ok 67, $array[1] eq fillout("green", $rec_len) ;
+    ok 68, $cursor->c_get($k, $v, DB_NEXT) == 0 ;
+    ok 69, $k == 1 ;
+    ok 70, $v eq fillout("green", $rec_len) ;
+    ok 71, $array[2] eq fillout("blue", $rec_len) ;
+    ok 72, $cursor->c_get($k, $v, DB_NEXT) == 0 ;
+    ok 73, $k == 2 ;
+    ok 74, $v eq fillout("blue", $rec_len) ;
+    ok 75, $array[4] == 2 ;
+    ok 76, $cursor->c_get($k, $v, DB_NEXT) == 0 ;
+    ok 77, $k == 4 ;
+    ok 78, $v == 2 ;
 
     # shift
-    ok 80, ($FA ? shift @array : $db->shift()) eq fillout("red", $rec_len) ;
-    ok 81, ($FA ? shift @array : $db->shift()) eq fillout("green", $rec_len) ;
-    ok 82, ($FA ? shift @array : $db->shift()) eq fillout("blue", $rec_len) ;
-    ok 83, ($FA ? shift @array : $db->shift()) == 2 ;
+    ok 79, ($FA ? shift @array : $db->shift()) eq fillout("red", $rec_len) ;
+    ok 80, ($FA ? shift @array : $db->shift()) eq fillout("green", $rec_len) ;
+    ok 81, ($FA ? shift @array : $db->shift()) eq fillout("blue", $rec_len) ;
+    ok 82, ($FA ? shift @array : $db->shift()) == 2 ;
 
     # push
     $FA ? push @array, "the", "end" 
         : $db->push("the", "end") ;
-    ok 84, $cursor->c_get($k, $v, DB_LAST) == 0 ;
-    ok 85, $k == 1002 ;
-    ok 86, $v eq fillout("end", $rec_len) ;
-    ok 87, $cursor->c_get($k, $v, DB_PREV) == 0 ;
-    ok 88, $k == 1001 ;
-    ok 89, $v eq fillout("the", $rec_len) ;
-    ok 90, $cursor->c_get($k, $v, DB_PREV) == 0 ;
-    ok 91, $k == 1000 ;
-    ok 92, $v == 2000 ;
+    ok 83, $cursor->c_get($k, $v, DB_LAST) == 0 ;
+    ok 84, $k == 1002 ;
+    ok 85, $v eq fillout("end", $rec_len) ;
+    ok 86, $cursor->c_get($k, $v, DB_PREV) == 0 ;
+    ok 87, $k == 1001 ;
+    ok 88, $v eq fillout("the", $rec_len) ;
+    ok 89, $cursor->c_get($k, $v, DB_PREV) == 0 ;
+    ok 90, $k == 1000 ;
+    ok 91, $v == 2000 ;
 
     # pop
-    ok 93, ( $FA ? pop @array : $db->pop ) eq fillout("end", $rec_len) ;
-    ok 94, ( $FA ? pop @array : $db->pop ) eq fillout("the", $rec_len) ;
-    ok 95, ( $FA ? pop @array : $db->pop ) == 2000  ;
+    ok 92, ( $FA ? pop @array : $db->pop ) eq fillout("end", $rec_len) ;
+    ok 93, ( $FA ? pop @array : $db->pop ) eq fillout("the", $rec_len) ;
+    ok 94, ( $FA ? pop @array : $db->pop ) == 2000  ;
 
     # now clear the array 
     $FA ? @array = () 
         : $db->clear() ;
-    ok 96, $cursor->c_get($k, $v, DB_FIRST) == DB_NOTFOUND ;
+    ok 95, $cursor->c_get($k, $v, DB_FIRST) == DB_NOTFOUND ;
 
     undef $cursor ;
     undef $db ;
@@ -331,12 +319,12 @@ umask(0) ;
     my $fd ;
     my $value ;
     my $rec_len = 15 ;
-    ok 97, my $db = tie @array, 'BerkeleyDB::Queue',
+    ok 96, my $db = tie @array, 'BerkeleyDB::Queue',
 				    	    -Len       => $rec_len;
 
-    ok 98, $db->db_put(1, "some value") == 0  ;
-    ok 99, $db->db_get(1, $value) == 0 ;
-    ok 100, $value eq fillout("some value", $rec_len) ;
+    ok 97, $db->db_put(1, "some value") == 0  ;
+    ok 98, $db->db_get(1, $value) == 0 ;
+    ok 99, $value eq fillout("some value", $rec_len) ;
 
 }
  
@@ -347,7 +335,7 @@ umask(0) ;
     my $lex = new LexFile $Dfile ;
     my $value ;
     my $rec_len = 8 ;
-    ok 101, my $db = new BerkeleyDB::Queue  -Filename => $Dfile,
+    ok 100, my $db = new BerkeleyDB::Queue  -Filename => $Dfile,
                                       	    -Flags    => DB_CREATE ,
 				    	    -Len      => $rec_len,
 				    	    -Pad      => " " ;
@@ -366,65 +354,65 @@ umask(0) ;
         my $r = $db->db_put($i, $data[$i]) ;
         $ret += $r ;
     }
-    ok 102, $ret == 0 ;
+    ok 101, $ret == 0 ;
 
     # do a partial get
     my ($pon, $off, $len) = $db->partial_set(0,2) ;
-    ok 103, ! $pon && $off == 0 && $len == 0 ;
-    ok 104, $db->db_get(1, $value) == 0 && $value eq "bo" ;
-    ok 105, $db->db_get(2, $value) == 0 && $value eq "ho" ;
-    ok 106, $db->db_get(3, $value) == 0 && $value eq "se" ;
+    ok 102, ! $pon && $off == 0 && $len == 0 ;
+    ok 103, $db->db_get(1, $value) == 0 && $value eq "bo" ;
+    ok 104, $db->db_get(2, $value) == 0 && $value eq "ho" ;
+    ok 105, $db->db_get(3, $value) == 0 && $value eq "se" ;
 
     # do a partial get, off end of data
     ($pon, $off, $len) = $db->partial_set(3,2) ;
-    ok 107, $pon ;
-    ok 108, $off == 0 ;
-    ok 109, $len == 2 ;
-    ok 110, $db->db_get(1, $value) == 0 && $value eq fillout("t", 2) ;
-    ok 111, $db->db_get(2, $value) == 0 && $value eq "se" ;
-    ok 112, $db->db_get(3, $value) == 0 && $value eq "  " ;
+    ok 106, $pon ;
+    ok 107, $off == 0 ;
+    ok 108, $len == 2 ;
+    ok 109, $db->db_get(1, $value) == 0 && $value eq fillout("t", 2) ;
+    ok 110, $db->db_get(2, $value) == 0 && $value eq "se" ;
+    ok 111, $db->db_get(3, $value) == 0 && $value eq "  " ;
 
     # switch of partial mode
     ($pon, $off, $len) = $db->partial_clear() ;
-    ok 113, $pon ;
-    ok 114, $off == 3 ;
-    ok 115, $len == 2 ;
-    ok 116, $db->db_get(1, $value) == 0 && $value eq fillout("boat", $rec_len) ;
-    ok 117, $db->db_get(2, $value) == 0 && $value eq fillout("house", $rec_len) ;
-    ok 118, $db->db_get(3, $value) == 0 && $value eq fillout("sea", $rec_len) ;
+    ok 112, $pon ;
+    ok 113, $off == 3 ;
+    ok 114, $len == 2 ;
+    ok 115, $db->db_get(1, $value) == 0 && $value eq fillout("boat", $rec_len) ;
+    ok 116, $db->db_get(2, $value) == 0 && $value eq fillout("house", $rec_len) ;
+    ok 117, $db->db_get(3, $value) == 0 && $value eq fillout("sea", $rec_len) ;
 
     # now partial put
     $db->partial_set(0,2) ;
-    ok 119, $db->db_put(1, "") != 0 ;
-    ok 120, $db->db_put(2, "AB") == 0 ;
-    ok 121, $db->db_put(3, "XY") == 0 ;
-    ok 122, $db->db_put(4, "KLM") != 0 ;
-    ok 123, $db->db_put(4, "KL") == 0 ;
+    ok 118, $db->db_put(1, "") != 0 ;
+    ok 119, $db->db_put(2, "AB") == 0 ;
+    ok 120, $db->db_put(3, "XY") == 0 ;
+    ok 121, $db->db_put(4, "KLM") != 0 ;
+    ok 122, $db->db_put(4, "KL") == 0 ;
 
     ($pon, $off, $len) = $db->partial_clear() ;
-    ok 124, $pon ;
-    ok 125, $off == 0 ;
-    ok 126, $len == 2 ;
-    ok 127, $db->db_get(1, $value) == 0 && $value eq fillout("boat", $rec_len) ;
-    ok 128, $db->db_get(2, $value) == 0 && $value eq fillout("ABuse", $rec_len) ;
-    ok 129, $db->db_get(3, $value) == 0 && $value eq fillout("XYa", $rec_len) ;
-    ok 130, $db->db_get(4, $value) == 0 && $value eq fillout("KL", $rec_len) ;
+    ok 123, $pon ;
+    ok 124, $off == 0 ;
+    ok 125, $len == 2 ;
+    ok 126, $db->db_get(1, $value) == 0 && $value eq fillout("boat", $rec_len) ;
+    ok 127, $db->db_get(2, $value) == 0 && $value eq fillout("ABuse", $rec_len) ;
+    ok 128, $db->db_get(3, $value) == 0 && $value eq fillout("XYa", $rec_len) ;
+    ok 129, $db->db_get(4, $value) == 0 && $value eq fillout("KL", $rec_len) ;
 
     # now partial put
     ($pon, $off, $len) = $db->partial_set(3,2) ;
-    ok 131, ! $pon ;
-    ok 132, $off == 0 ;
-    ok 133, $len == 0 ;
-    ok 134, $db->db_put(1, "PP") == 0 ;
-    ok 135, $db->db_put(2, "Q") != 0 ;
-    ok 136, $db->db_put(3, "XY") == 0 ;
-    ok 137, $db->db_put(4, "TU") == 0 ;
+    ok 130, ! $pon ;
+    ok 131, $off == 0 ;
+    ok 132, $len == 0 ;
+    ok 133, $db->db_put(1, "PP") == 0 ;
+    ok 134, $db->db_put(2, "Q") != 0 ;
+    ok 135, $db->db_put(3, "XY") == 0 ;
+    ok 136, $db->db_put(4, "TU") == 0 ;
 
     $db->partial_clear() ;
-    ok 138, $db->db_get(1, $value) == 0 && $value eq fillout("boaPP", $rec_len) ;
-    ok 139, $db->db_get(2, $value) == 0 && $value eq fillout("ABuse",$rec_len) ;
-    ok 140, $db->db_get(3, $value) == 0 && $value eq fillout("XYaXY", $rec_len) ;
-    ok 141, $db->db_get(4, $value) == 0 && $value eq fillout("KL TU", $rec_len) ;
+    ok 137, $db->db_get(1, $value) == 0 && $value eq fillout("boaPP", $rec_len) ;
+    ok 138, $db->db_get(2, $value) == 0 && $value eq fillout("ABuse",$rec_len) ;
+    ok 139, $db->db_get(3, $value) == 0 && $value eq fillout("XYaXY", $rec_len) ;
+    ok 140, $db->db_get(4, $value) == 0 && $value eq fillout("KL TU", $rec_len) ;
 }
 
 {
@@ -435,7 +423,7 @@ umask(0) ;
     my @array ;
     my $value ;
     my $rec_len = 8 ;
-    ok 142, my $db = tie @array, 'BerkeleyDB::Queue', -Filename => $Dfile,
+    ok 141, my $db = tie @array, 'BerkeleyDB::Queue', -Filename => $Dfile,
                                       	        -Flags    => DB_CREATE ,
 				    	        -Len       => $rec_len,
 				    	        -Pad       => " " ;
@@ -455,59 +443,59 @@ umask(0) ;
 	$status += $db->status() ;
     }
 
-    ok 143, $status == 0 ;
+    ok 142, $status == 0 ;
 
     # do a partial get
     $db->partial_set(0,2) ;
-    ok 144, $array[1] eq fillout("bo", 2) ;
-    ok 145, $array[2] eq fillout("ho", 2) ;
-    ok 146, $array[3]  eq fillout("se", 2) ;
+    ok 143, $array[1] eq fillout("bo", 2) ;
+    ok 144, $array[2] eq fillout("ho", 2) ;
+    ok 145, $array[3]  eq fillout("se", 2) ;
 
     # do a partial get, off end of data
     $db->partial_set(3,2) ;
-    ok 147, $array[1] eq fillout("t", 2) ;
-    ok 148, $array[2] eq fillout("se", 2) ;
-    ok 149, $array[3] eq fillout("", 2) ;
+    ok 146, $array[1] eq fillout("t", 2) ;
+    ok 147, $array[2] eq fillout("se", 2) ;
+    ok 148, $array[3] eq fillout("", 2) ;
 
     # switch of partial mode
     $db->partial_clear() ;
-    ok 150, $array[1] eq fillout("boat", $rec_len) ;
-    ok 151, $array[2] eq fillout("house", $rec_len) ;
-    ok 152, $array[3] eq fillout("sea", $rec_len) ;
+    ok 149, $array[1] eq fillout("boat", $rec_len) ;
+    ok 150, $array[2] eq fillout("house", $rec_len) ;
+    ok 151, $array[3] eq fillout("sea", $rec_len) ;
 
     # now partial put
     $db->partial_set(0,2) ;
     $array[1] = "" ;
-    ok 153, $db->status() != 0 ;
+    ok 152, $db->status() != 0 ;
     $array[2] = "AB" ;
-    ok 154, $db->status() == 0 ;
+    ok 153, $db->status() == 0 ;
     $array[3] = "XY" ;
-    ok 155, $db->status() == 0 ;
+    ok 154, $db->status() == 0 ;
     $array[4] = "KL" ;
-    ok 156, $db->status() == 0 ;
+    ok 155, $db->status() == 0 ;
 
     $db->partial_clear() ;
-    ok 157, $array[1] eq fillout("boat", $rec_len) ;
-    ok 158, $array[2] eq fillout("ABuse", $rec_len) ;
-    ok 159, $array[3] eq fillout("XYa", $rec_len) ;
-    ok 160, $array[4] eq fillout("KL", $rec_len) ;
+    ok 156, $array[1] eq fillout("boat", $rec_len) ;
+    ok 157, $array[2] eq fillout("ABuse", $rec_len) ;
+    ok 158, $array[3] eq fillout("XYa", $rec_len) ;
+    ok 159, $array[4] eq fillout("KL", $rec_len) ;
 
     # now partial put
     $db->partial_set(3,2) ;
     $array[1] = "PP" ;
-    ok 161, $db->status() == 0 ;
+    ok 160, $db->status() == 0 ;
     $array[2] = "Q" ;
-    ok 162, $db->status() != 0 ;
+    ok 161, $db->status() != 0 ;
     $array[3] = "XY" ;
-    ok 163, $db->status() == 0 ;
+    ok 162, $db->status() == 0 ;
     $array[4] = "TU" ;
-    ok 164, $db->status() == 0 ;
+    ok 163, $db->status() == 0 ;
 
     $db->partial_clear() ;
-    ok 165, $array[1] eq fillout("boaPP", $rec_len) ;
-    ok 166, $array[2] eq fillout("ABuse", $rec_len) ;
-    ok 167, $array[3] eq fillout("XYaXY", $rec_len) ;
-    ok 168, $array[4] eq fillout("KL TU", $rec_len) ;
+    ok 164, $array[1] eq fillout("boaPP", $rec_len) ;
+    ok 165, $array[2] eq fillout("ABuse", $rec_len) ;
+    ok 166, $array[3] eq fillout("XYaXY", $rec_len) ;
+    ok 167, $array[4] eq fillout("KL TU", $rec_len) ;
 }
 
 {
@@ -518,13 +506,13 @@ umask(0) ;
     my $value ;
 
     my $home = "./fred" ;
-    ok 169, my $lexD = new LexDir($home);
+    ok 168, my $lexD = new LexDir($home);
     my $rec_len = 9 ;
-    ok 170, my $env = new BerkeleyDB::Env -Home => $home,
+    ok 169, my $env = new BerkeleyDB::Env -Home => $home,@StdErrFile,
 				     -Flags => DB_CREATE|DB_INIT_TXN|
 					  	DB_INIT_MPOOL|DB_INIT_LOCK ;
-    ok 171, my $txn = $env->txn_begin() ;
-    ok 172, my $db1 = tie @array, 'BerkeleyDB::Queue', 
+    ok 170, my $txn = $env->txn_begin() ;
+    ok 171, my $db1 = tie @array, 'BerkeleyDB::Queue', 
 				-Filename => $Dfile,
 				-ArrayBase => 0,
                       		-Flags    =>  DB_CREATE ,
@@ -534,8 +522,8 @@ umask(0) ;
 				-Pad      => " " ;
 
     
-    ok 173, $txn->txn_commit() == 0 ;
-    ok 174, $txn = $env->txn_begin() ;
+    ok 172, $txn->txn_commit() == 0 ;
+    ok 173, $txn = $env->txn_begin() ;
     $db1->Txn($txn);
 
     # create some data
@@ -550,31 +538,31 @@ umask(0) ;
     for ($i = 0 ; $i < @data ; ++$i) {
         $ret += $db1->db_put($i, $data[$i]) ;
     }
-    ok 175, $ret == 0 ;
+    ok 174, $ret == 0 ;
 
     # should be able to see all the records
 
-    ok 176, my $cursor = $db1->db_cursor() ;
+    ok 175, my $cursor = $db1->db_cursor() ;
     my ($k, $v) = (0, "") ;
     my $count = 0 ;
     # sequence forwards
     while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
         ++ $count ;
     }
-    ok 177, $count == 3 ;
+    ok 176, $count == 3 ;
     undef $cursor ;
 
     # now abort the transaction
-    ok 178, $txn->txn_abort() == 0 ;
+    ok 177, $txn->txn_abort() == 0 ;
 
     # there shouldn't be any records in the database
     $count = 0 ;
     # sequence forwards
-    ok 179, $cursor = $db1->db_cursor() ;
+    ok 178, $cursor = $db1->db_cursor() ;
     while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
         ++ $count ;
     }
-    ok 180, $count == 0 ;
+    ok 179, $count == 0 ;
 
     undef $txn ;
     undef $cursor ;
@@ -592,7 +580,7 @@ umask(0) ;
     my @array ;
     my ($k, $v) ;
     my $rec_len = 7 ;
-    ok 181, my $db = new BerkeleyDB::Queue -Filename 	=> $Dfile, 
+    ok 180, my $db = new BerkeleyDB::Queue -Filename 	=> $Dfile, 
 				     	   -Flags    	=> DB_CREATE,
 					   -Pagesize	=> 4 * 1024,
 				           -Len       => $rec_len,
@@ -600,8 +588,8 @@ umask(0) ;
 					;
 
     my $ref = $db->db_stat() ; 
-    ok 182, $ref->{$recs} == 0;
-    ok 183, $ref->{'qs_pagesize'} == 4 * 1024;
+    ok 181, $ref->{$recs} == 0;
+    ok 182, $ref->{'qs_pagesize'} == 4 * 1024;
 
     # create some data
     my @data =  (
@@ -615,10 +603,10 @@ umask(0) ;
     for ($i = $db->ArrayOffset ; @data ; ++$i) {
         $ret += $db->db_put($i, shift @data) ;
     }
-    ok 184, $ret == 0 ;
+    ok 183, $ret == 0 ;
 
     $ref = $db->db_stat() ; 
-    ok 185, $ref->{$recs} == 3;
+    ok 184, $ref->{$recs} == 3;
 }
 
 {
@@ -638,7 +626,7 @@ umask(0) ;
 
    require Exporter ;
    use BerkeleyDB;
-   @ISA=qw(BerkeleyDB::Queue);
+   @ISA=qw(BerkeleyDB BerkeleyDB::Queue);
    @EXPORT = @BerkeleyDB::EXPORT ;
 
    sub db_put { 
@@ -669,7 +657,7 @@ EOM
 
     BEGIN { push @INC, '.'; }    
     eval 'use SubDB ; ';
-    main::ok 186, $@ eq "" ;
+    main::ok 185, $@ eq "" ;
     my @h ;
     my $X ;
     my $rec_len = 34 ;
@@ -682,24 +670,24 @@ EOM
 			);		   
 	' ;
 
-    main::ok 187, $@ eq "" ;
+    main::ok 186, $@ eq "" ;
 
     my $ret = eval '$h[1] = 3 ; return $h[1] ' ;
-    main::ok 188, $@ eq "" ;
-    main::ok 189, $ret == 7 ;
+    main::ok 187, $@ eq "" ;
+    main::ok 188, $ret == 7 ;
 
     my $value = 0;
     $ret = eval '$X->db_put(1, 4) ; $X->db_get(1, $value) ; return $value' ;
-    main::ok 190, $@ eq "" ;
-    main::ok 191, $ret == 10 ;
+    main::ok 189, $@ eq "" ;
+    main::ok 190, $ret == 10 ;
 
     $ret = eval ' DB_NEXT eq main::DB_NEXT ' ;
-    main::ok 192, $@ eq ""  ;
-    main::ok 193, $ret == 1 ;
+    main::ok 191, $@ eq ""  ;
+    main::ok 192, $ret == 1 ;
 
     $ret = eval '$X->A_new_method(1) ' ;
-    main::ok 194, $@ eq "" ;
-    main::ok 195, $ret eq "[[10]]" ;
+    main::ok 193, $@ eq "" ;
+    main::ok 194, $ret eq "[[10]]" ;
 
     undef $X ;
     untie @h ;
@@ -714,7 +702,7 @@ EOM
     my @array ;
     my $value ;
     my $rec_len = 21 ;
-    ok 196, my $db = tie @array, 'BerkeleyDB::Queue', 
+    ok 195, my $db = tie @array, 'BerkeleyDB::Queue', 
 					-Filename  => $Dfile,
                                        	-Flags     => DB_CREATE ,
 	                		-Len       => $rec_len,
@@ -725,9 +713,9 @@ EOM
     $array[3] = "ghi" ;
 
     my $k = 0 ;
-    ok 197, $db->db_put($k, "fred", DB_APPEND) == 0 ;
-    ok 198, $k == 4 ;
-    ok 199, $array[4] eq fillout("fred", $rec_len) ;
+    ok 196, $db->db_put($k, "fred", DB_APPEND) == 0 ;
+    ok 197, $k == 4 ;
+    ok 198, $array[4] eq fillout("fred", $rec_len) ;
 
     undef $db ;
     untie @array ;
@@ -739,7 +727,7 @@ EOM
     my @array ;
     my $db ;
     my $rec_len = 21 ;
-    ok 200, $db = tie @array, 'BerkeleyDB::Queue', 
+    ok 199, $db = tie @array, 'BerkeleyDB::Queue', 
                                       	       	-Flags  => DB_CREATE ,
 				    	        -ArrayBase => 0,
 	                		        -Len       => $rec_len,
@@ -748,7 +736,7 @@ EOM
     $FA ? push @array, "first"
         : $db->push("first") ;
 
-    ok 201, ($FA ? pop @array : $db->pop()) eq fillout("first", $rec_len) ;
+    ok 200, ($FA ? pop @array : $db->pop()) eq fillout("first", $rec_len) ;
 
     undef $db;
     untie @array ;
diff --git a/storage/bdb/perl/BerkeleyDB/t/recno.t b/storage/bdb/perl/BerkeleyDB/t/recno.t
index 64b1803f7365c78fffac330a667b9a5b686f99f1..7bbb50169fba6b2f9fe34ccfc255e7000b8105f4 100644
--- a/storage/bdb/perl/BerkeleyDB/t/recno.t
+++ b/storage/bdb/perl/BerkeleyDB/t/recno.t
@@ -97,7 +97,7 @@ umask(0) ;
     my $home = "./fred" ;
     ok 27, my $lexD = new LexDir($home);
 
-    ok 28, my $env = new BerkeleyDB::Env -Flags => DB_CREATE|DB_INIT_MPOOL,
+    ok 28, my $env = new BerkeleyDB::Env -Flags => DB_CREATE|DB_INIT_MPOOL,@StdErrFile,
     					 -Home => $home ;
 
     ok 29, my $db = new BerkeleyDB::Recno -Filename => $Dfile, 
@@ -465,7 +465,7 @@ umask(0) ;
 
     my $home = "./fred" ;
     ok 167, my $lexD = new LexDir($home);
-    ok 168, my $env = new BerkeleyDB::Env -Home => $home,
+    ok 168, my $env = new BerkeleyDB::Env -Home => $home,@StdErrFile,
 				     -Flags => DB_CREATE|DB_INIT_TXN|
 					  	DB_INIT_MPOOL|DB_INIT_LOCK ;
     ok 169, my $txn = $env->txn_begin() ;
@@ -578,7 +578,7 @@ umask(0) ;
 
    require Exporter ;
    use BerkeleyDB;
-   @ISA=qw(BerkeleyDB::Recno);
+   @ISA=qw(BerkeleyDB BerkeleyDB::Recno);
    @EXPORT = @BerkeleyDB::EXPORT ;
 
    sub db_put { 
diff --git a/storage/bdb/perl/BerkeleyDB/t/strict.t b/storage/bdb/perl/BerkeleyDB/t/strict.t
index ab41d44cb41083d3779f026505eeb0986e1b2ccd..4774cd15dad7f947af4f29926ddb3c45a656397e 100644
--- a/storage/bdb/perl/BerkeleyDB/t/strict.t
+++ b/storage/bdb/perl/BerkeleyDB/t/strict.t
@@ -26,7 +26,7 @@ umask(0);
     my $status ;
 
     ok 1, my $lexD = new LexDir($home);
-    ok 2, my $env = new BerkeleyDB::Env -Home => $home,
+    ok 2, my $env = new BerkeleyDB::Env -Home => $home,@StdErrFile,
                                      -Flags => DB_CREATE|DB_INIT_TXN|
                                                 DB_INIT_MPOOL|DB_INIT_LOCK ;
 					  	
@@ -49,7 +49,7 @@ umask(0);
     my %hash ;
 
     ok 7, my $lexD = new LexDir($home);
-    ok 8, my $env = new BerkeleyDB::Env -Home => $home,
+    ok 8, my $env = new BerkeleyDB::Env -Home => $home,@StdErrFile,
                                      -Flags => DB_CREATE|DB_INIT_TXN|
                                                 DB_INIT_MPOOL|DB_INIT_LOCK ;
 					  	
@@ -73,7 +73,7 @@ umask(0);
     my $status ;
 
     ok 11, my $lexD = new LexDir($home);
-    ok 12, my $env = new BerkeleyDB::Env -Home => $home,
+    ok 12, my $env = new BerkeleyDB::Env -Home => $home,@StdErrFile,
                                      -Flags => DB_CREATE|DB_INIT_TXN|
                                                 DB_INIT_MPOOL|DB_INIT_LOCK ;
 
@@ -100,7 +100,7 @@ umask(0);
     my %hash ;
 
     ok 20, my $lexD = new LexDir($home);
-    ok 21, my $env = new BerkeleyDB::Env -Home => $home,
+    ok 21, my $env = new BerkeleyDB::Env -Home => $home,@StdErrFile,
                                      -Flags => DB_CREATE|DB_INIT_TXN|
                                                 DB_INIT_MPOOL|DB_INIT_LOCK ;
 
@@ -113,6 +113,8 @@ umask(0);
     eval { $db->db_close() ; } ;
     ok 24, $@ =~ /BerkeleyDB Aborting: attempted to close a database while a transaction was still open at/ ;
     #print "[$@]\n" ;
+    $txn->txn_abort();
+    $db->db_close();
 }
 
 {
@@ -147,9 +149,10 @@ umask(0);
     my $lex = new LexFile $Dfile ;
     my %hash ;
     my $status ;
+    my $home = 'fred1';
 
     ok 33, my $lexD = new LexDir($home);
-    ok 34, my $env = new BerkeleyDB::Env -Home => $home,
+    ok 34, my $env = new BerkeleyDB::Env -Home => $home,@StdErrFile,
                                      -Flags => DB_CREATE|DB_INIT_TXN|
                                                 DB_INIT_MPOOL|DB_INIT_LOCK ;
     ok 35, my $txn = $env->txn_begin() ;
diff --git a/storage/bdb/perl/BerkeleyDB/t/subdb.t b/storage/bdb/perl/BerkeleyDB/t/subdb.t
index 23016d6463fd9e28d1073972bcabb50d761e3799..4e56332eba3c01b17c480c1f4f924dd2402127cc 100644
--- a/storage/bdb/perl/BerkeleyDB/t/subdb.t
+++ b/storage/bdb/perl/BerkeleyDB/t/subdb.t
@@ -15,7 +15,7 @@ use t::util ;
 BEGIN 
 {
     if ($BerkeleyDB::db_version < 3) {
-	print "1..0 # Skipping test, this needs Berkeley DB 3.x or better\n" ;
+	print "1..0 # Skip: this needs Berkeley DB 3.x or better\n" ;
 	exit 0 ;
     }
 }
diff --git a/storage/bdb/perl/BerkeleyDB/t/txn.t b/storage/bdb/perl/BerkeleyDB/t/txn.t
index ba6b636cdc82713c674f8863f526a0aeabd700cd..f8fa2ceb89756323da0bd2e2b7cd8152006b3466 100644
--- a/storage/bdb/perl/BerkeleyDB/t/txn.t
+++ b/storage/bdb/perl/BerkeleyDB/t/txn.t
@@ -27,7 +27,7 @@ umask(0);
 
     my $home = "./fred" ;
     ok 1, my $lexD = new LexDir($home);
-    ok 2, my $env = new BerkeleyDB::Env -Home => $home,
+    ok 2, my $env = new BerkeleyDB::Env -Home => $home, @StdErrFile,
 				     -Flags => DB_CREATE| DB_INIT_MPOOL;
     eval { $env->txn_begin() ; } ;
     ok 3, $@ =~ /^BerkeleyDB Aborting: Transaction Manager not enabled at/ ;
@@ -47,7 +47,7 @@ umask(0);
 
     my $home = "./fred" ;
     ok 5, my $lexD = new LexDir($home);
-    ok 6, my $env = new BerkeleyDB::Env -Home => $home,
+    ok 6, my $env = new BerkeleyDB::Env -Home => $home, @StdErrFile,
 				     -Flags => DB_CREATE|DB_INIT_TXN|
 					  	DB_INIT_MPOOL|DB_INIT_LOCK ;
     ok 7, my $txn = $env->txn_begin() ;
@@ -117,7 +117,7 @@ umask(0);
 
     my $home = "./fred" ;
     ok 18, my $lexD = new LexDir($home);
-    ok 19, my $env = new BerkeleyDB::Env -Home => $home,
+    ok 19, my $env = new BerkeleyDB::Env -Home => $home, @StdErrFile,
 				     -Flags => DB_CREATE|DB_INIT_TXN|
 					  	DB_INIT_MPOOL|DB_INIT_LOCK ;
     ok 20, my $txn_mgr = $env->TxnMgr() ;
@@ -188,7 +188,7 @@ umask(0);
 
     my $home = "./fred" ;
     ok 32, my $lexD = new LexDir($home);
-    ok 33, my $env = new BerkeleyDB::Env -Home => $home,
+    ok 33, my $env = new BerkeleyDB::Env -Home => $home, @StdErrFile,
 				     -Flags => DB_CREATE|DB_INIT_TXN|
 					  	DB_INIT_MPOOL|DB_INIT_LOCK ;
     ok 34, my $txn = $env->txn_begin() ;
@@ -257,7 +257,7 @@ umask(0);
 
     my $home = "./fred" ;
     ok 45, my $lexD = new LexDir($home);
-    ok 46, my $env = new BerkeleyDB::Env -Home => $home,
+    ok 46, my $env = new BerkeleyDB::Env -Home => $home, @StdErrFile,
 				     -Flags => DB_CREATE|DB_INIT_TXN|
 					  	DB_INIT_MPOOL|DB_INIT_LOCK ;
     ok 47, my $txn_mgr = $env->TxnMgr() ;
diff --git a/storage/bdb/perl/BerkeleyDB/t/util.pm b/storage/bdb/perl/BerkeleyDB/t/util.pm
index 1a1449751eb0789fa53b079f1ea8f6166f02c991..9f55c40d8c270960388d3b7e313547414c4eceb3 100644
--- a/storage/bdb/perl/BerkeleyDB/t/util.pm
+++ b/storage/bdb/perl/BerkeleyDB/t/util.pm
@@ -7,6 +7,10 @@ use BerkeleyDB ;
 use File::Path qw(rmtree);
 use vars qw(%DB_errors $FA) ;
 
+use vars qw( @StdErrFile );
+
+@StdErrFile = ( -ErrFile => *STDERR, -ErrPrefix => "\n# " ) ;
+
 $| = 1;
 
 %DB_errors = (
@@ -122,6 +126,16 @@ $FA = 0 ;
     }
 }
 
+sub normalise
+{
+    my $data = shift ;
+    $data =~ s#\r\n#\n#g
+        if $^O eq 'cygwin' ;
+
+    return $data ;
+}
+
+
 sub docat
 {
     my $file = shift;
@@ -129,6 +143,7 @@ sub docat
     open(CAT,$file) || die "Cannot open $file:$!";
     my $result = <CAT>;
     close(CAT);
+    $result = normalise($result);
     return $result;
 }
 
@@ -140,6 +155,7 @@ sub docat_del
     my $result = <CAT> || "" ;
     close(CAT);
     unlink $file ;
+    $result = normalise($result);
     return $result;
 }   
 
@@ -176,6 +192,41 @@ sub joiner
     (scalar(@data), join($sep, @data)) ;
 }
 
+sub joinkeys
+{
+    my $db = shift ;
+    my $sep = shift || " " ;
+    my ($k, $v) = (0, "") ;
+    my @data = () ;
+
+    my $cursor = $db->db_cursor()  or return () ;
+    for ( my $status = $cursor->c_get($k, $v, DB_FIRST) ;
+          $status == 0 ;
+          $status = $cursor->c_get($k, $v, DB_NEXT)) {
+	push @data, $k ;
+    }
+
+    return join($sep, @data) ;
+
+}
+
+sub dumpdb
+{
+    my $db = shift ;
+    my $sep = shift || " " ;
+    my ($k, $v) = (0, "") ;
+    my @data = () ;
+
+    my $cursor = $db->db_cursor()  or return () ;
+    for ( my $status = $cursor->c_get($k, $v, DB_FIRST) ;
+          $status == 0 ;
+          $status = $cursor->c_get($k, $v, DB_NEXT)) {
+	print "  [$k][$v]\n" ;
+    }
+
+
+}
+
 sub countRecords
 {
    my $db = shift ;
@@ -217,4 +268,59 @@ sub ok
 }
 
 
+# These two subs lifted directly from MLDBM.pm
+#
+sub _compare {
+    use vars qw(%compared);
+    local %compared;
+    return _cmp(@_);
+}
+
+sub _cmp {
+    my($a, $b) = @_;
+
+    # catch circular loops
+    return(1) if $compared{$a.'&*&*&*&*&*'.$b}++;
+#    print "$a $b\n";
+#    print &Data::Dumper::Dumper($a, $b);
+
+    if(ref($a) and ref($a) eq ref($b)) {
+	if(eval { @$a }) {
+#	    print "HERE ".@$a." ".@$b."\n";
+	    @$a == @$b or return 0;
+#	    print @$a, ' ', @$b, "\n";
+#	    print "HERE2\n";
+
+	    for(0..@$a-1) {
+		&_cmp($a->[$_], $b->[$_]) or return 0;
+	    }
+	} elsif(eval { %$a }) {
+	    keys %$a == keys %$b or return 0;
+	    for (keys %$a) {
+		&_cmp($a->{$_}, $b->{$_}) or return 0;
+	    }
+	} elsif(eval { $$a }) {
+	    &_cmp($$a, $$b) or return 0;
+	} else {
+	    die("data $a $b not handled");
+	}
+	return 1;
+    } elsif(! ref($a) and ! ref($b)) {
+	return ($a eq $b);
+    } else {
+	return 0;
+    }
+
+}
+
+sub fillout
+{
+    my $var = shift ;
+    my $length = shift ;
+    my $pad = shift || " " ;
+    my $template = $pad x $length ;
+    substr($template, 0, length($var)) = $var ;
+    return $template ;
+}
+
 1;
diff --git a/storage/bdb/perl/BerkeleyDB/typemap b/storage/bdb/perl/BerkeleyDB/typemap
index 81ead2c36d985cae1d04970c8c5110ba99d9e5e4..66c622bd0480e1fa1d8ea7a3bd505415c8fc5194 100644
--- a/storage/bdb/perl/BerkeleyDB/typemap
+++ b/storage/bdb/perl/BerkeleyDB/typemap
@@ -2,7 +2,7 @@
 #
 # SCCS: %I%, %G%     
 #
-# written by Paul Marquess <Paul.Marquess@btinternet.com>
+# written by Paul Marquess <pmqs@cpan.org>
 #
 #################################### DB SECTION
 #
@@ -61,6 +61,7 @@ BerkeleyDB_TxnMgr_type * T_IV
 BerkeleyDB_Txn_type *	T_IV
 BerkeleyDB__Cursor_type * T_IV
 DB *			T_IV
+DB_ENV *		T_IV
 
 INPUT
 
@@ -173,46 +174,60 @@ T_PTROBJ_AV
             croak(\"$var is not of type ${ntype}\")
 
 T_dbtkeydatum
-	DBM_ckFilter($arg, filter_store_key, \"filter_store_key\");
-	DBT_clear($var) ;
-	if (db->recno_or_queue) {
-	    Value = GetRecnoKey(db, SvIV($arg)) ; 
-	    $var.data = & Value; 
-	    $var.size = (int)sizeof(db_recno_t);
-	}
-	else {
-	    $var.data = SvPV($arg, PL_na);
-	    $var.size = (int)PL_na;
+	{
+	    SV* my_sv = $arg ;
+	    DBM_ckFilter(my_sv, filter_store_key, \"filter_store_key\");
+	    DBT_clear($var) ;
+            SvGETMAGIC($arg) ;
+	    if (db->recno_or_queue) {
+	        Value = GetRecnoKey(db, SvIV(my_sv)) ; 
+	        $var.data = & Value; 
+	        $var.size = (int)sizeof(db_recno_t);
+	    }
+	    else {
+	        $var.data = SvPV(my_sv, PL_na);
+	        $var.size = (int)PL_na;
+	    }
 	}
 
 T_dbtkeydatum_btree
-	DBM_ckFilter($arg, filter_store_key, \"filter_store_key\");
-	DBT_clear($var) ;
-	if (db->recno_or_queue ||
-		(db->type == DB_BTREE && flagSet(DB_SET_RECNO))) {
-	    Value = GetRecnoKey(db, SvIV($arg)) ; 
-	    $var.data = & Value; 
-	    $var.size = (int)sizeof(db_recno_t);
-	}
-	else {
-	    $var.data = SvPV($arg, PL_na);
-	    $var.size = (int)PL_na;
+	{
+	    SV* my_sv = $arg ;
+	    DBM_ckFilter(my_sv, filter_store_key, \"filter_store_key\");
+	    DBT_clear($var) ;
+            SvGETMAGIC($arg) ;
+	    if (db->recno_or_queue ||
+		    (db->type == DB_BTREE && flagSet(DB_SET_RECNO))) {
+	        Value = GetRecnoKey(db, SvIV(my_sv)) ; 
+	        $var.data = & Value; 
+	        $var.size = (int)sizeof(db_recno_t);
+	    }
+	    else {
+	        $var.data = SvPV(my_sv, PL_na);
+	        $var.size = (int)PL_na;
+	    }
 	}
 
 T_dbtdatum
-	DBM_ckFilter($arg, filter_store_value, \"filter_store_value\");
-	DBT_clear($var) ;
-	$var.data = SvPV($arg, PL_na);
-	$var.size = (int)PL_na;
-  	$var.flags = db->partial ;
-    	$var.dlen  = db->dlen ;
-	$var.doff  = db->doff ;
+	{
+	    SV* my_sv = $arg ;
+	    DBM_ckFilter(my_sv, filter_store_value, \"filter_store_value\");
+	    DBT_clear($var) ;
+            SvGETMAGIC($arg) ;
+	    $var.data = SvPV(my_sv, PL_na);
+	    $var.size = (int)PL_na;
+  	    $var.flags = db->partial ;
+    	    $var.dlen  = db->dlen ;
+	    $var.doff  = db->doff ;
+	}
 	
 T_dbtdatum_opt
 	DBT_clear($var) ;
 	if (flagSet(DB_GET_BOTH)) {
-	   DBM_ckFilter($arg, filter_store_value, \"filter_store_value\");
-	   $var.data = SvPV($arg, PL_na);
+	   SV* my_sv = $arg ;
+	   DBM_ckFilter(my_sv, filter_store_value, \"filter_store_value\");
+           SvGETMAGIC($arg) ;
+	   $var.data = SvPV(my_sv, PL_na);
 	   $var.size = (int)PL_na;
   	   $var.flags = db->partial ;
     	   $var.dlen  = db->dlen ;
@@ -222,8 +237,10 @@ T_dbtdatum_opt
 T_dbtdatum_btree
 	DBT_clear($var) ;
 	if (flagSet(DB_GET_BOTH)) {
-	    DBM_ckFilter($arg, filter_store_value, \"filter_store_value\");
-	    $var.data = SvPV($arg, PL_na);
+	    SV* my_sv = $arg ;
+	    DBM_ckFilter(my_sv, filter_store_value, \"filter_store_value\");
+            SvGETMAGIC($arg) ;
+	    $var.data = SvPV(my_sv, PL_na);
 	    $var.size = (int)PL_na;
   	    $var.flags = db->partial ;
     	    $var.dlen  = db->dlen ;
diff --git a/storage/bdb/perl/DB_File/Changes b/storage/bdb/perl/DB_File/Changes
index 7883cbdfef0f1c2a3d8072999b57df04070b0567..89027d13f607de3b0382f45fa40a94c9a935ca74 100644
--- a/storage/bdb/perl/DB_File/Changes
+++ b/storage/bdb/perl/DB_File/Changes
@@ -1,4 +1,46 @@
 
+
+1.810 7th August 2004
+
+   * Fixed db-hash.t for Cygwin
+
+   * Added substr tests to db-hast.t
+
+1.809 20th June 2004
+
+   * Merged core patch 22258
+
+   * Merged core patch 22741
+
+   * Fixed core bug 30237. 
+     Using substr to pass parameters to the low-level Berkeley DB interface
+     causes problems with Perl 5.8.1 or better.
+     typemap fix supplied by Marcus Holland-Moritz.
+
+1.808 22nd December 2003
+
+   * Added extra DBM Filter tests.
+
+   * Fixed a memory leak in ParseOpenInfo, which whould occur if the
+     opening of the database failed. Leak spotted by Adrian Enache.
+
+1.807 1st November 2003
+
+   * Fixed minor typos on pod documetation - reported by Jeremy Mates &
+     Mark Jason Dominus.
+
+   * dbinfo updated to report when a database is encrypted.
+
+1.806 22nd October 2002
+
+   * Fixed problem when trying to build with a multi-threaded perl.
+
+   * Tidied up the recursion detetion code.
+
+   * merged core patch 17844 - missing dTHX declarations.
+
+   * merged core patch 17838 
+
 1.805 1st September 2002
 
    * Added support to allow DB_File to build with Berkeley DB 4.1.X
diff --git a/storage/bdb/perl/DB_File/DB_File.pm b/storage/bdb/perl/DB_File/DB_File.pm
index 49004ffa148ee741adbd685a7d57a12e1f461105..5ddac46c963d1c759c5998ed62260caa7a627840 100644
--- a/storage/bdb/perl/DB_File/DB_File.pm
+++ b/storage/bdb/perl/DB_File/DB_File.pm
@@ -1,10 +1,10 @@
 # DB_File.pm -- Perl 5 interface to Berkeley DB 
 #
-# written by Paul Marquess (Paul.Marquess@btinternet.com)
-# last modified 1st September 2002
-# version 1.805
+# written by Paul Marquess (pmqs@cpan.org)
+# last modified 7th August 2004
+# version 1.810
 #
-#     Copyright (c) 1995-2002 Paul Marquess. All rights reserved.
+#     Copyright (c) 1995-2004 Paul Marquess. All rights reserved.
 #     This program is free software; you can redistribute it and/or
 #     modify it under the same terms as Perl itself.
 
@@ -165,7 +165,7 @@ our ($db_version, $use_XSLoader, $splice_end_array);
 use Carp;
 
 
-$VERSION = "1.805" ;
+$VERSION = "1.810" ;
 
 {
     local $SIG{__WARN__} = sub {$splice_end_array = "@_";};
@@ -266,7 +266,8 @@ sub tie_hash_or_array
     $arg[2] = O_CREAT()|O_RDWR() if @arg >=3 && ! defined $arg[2];
     $arg[3] = 0666               if @arg >=4 && ! defined $arg[3];
 
-    # make recno in Berkeley DB version 2 work like recno in version 1.
+    # make recno in Berkeley DB version 2 (or better) work like 
+    # recno in version 1.
     if ($db_version > 1 and defined $arg[4] and $arg[4] =~ /RECNO/ and 
 	$arg[1] and ! -e $arg[1]) {
 	open(FH, ">$arg[1]") or return undef ;
@@ -966,7 +967,7 @@ Duplicate keys are entirely defined by the comparison function.
 In the case-insensitive example above, the keys: 'KEY' and 'key'
 would be considered duplicates, and assigning to the second one
 would overwrite the first. If duplicates are allowed for (with the
-R_DUPS flag discussed below), only a single copy of duplicate keys
+R_DUP flag discussed below), only a single copy of duplicate keys
 is stored in the database --- so (again with example above) assigning
 three values to the keys: 'KEY', 'Key', and 'key' would leave just
 the first key: 'KEY' in the database with three values. For some
@@ -1362,7 +1363,7 @@ still have bval default to C<"\n"> for variable length records, and
 space for fixed length records.
 
 Also note that the bval option only allows you to specify a single byte
-as a delimeter.
+as a delimiter.
 
 =head2 A Simple Example
 
@@ -1454,7 +1455,7 @@ Returns the number of elements in the array.
 
 =item B<$X-E<gt>splice(offset, length, elements);>
 
-Returns a splice of the the array.
+Returns a splice of the array.
 
 =back
 
@@ -1821,7 +1822,7 @@ fix very easily.
     use DB_File ;
 
     my %hash ;
-    my $filename = "/tmp/filt" ;
+    my $filename = "filt" ;
     unlink $filename ;
 
     my $db = tie %hash, 'DB_File', $filename, O_CREAT|O_RDWR, 0666, $DB_HASH 
@@ -1863,7 +1864,7 @@ Here is a DBM Filter that does it:
     use strict ;
     use DB_File ;
     my %hash ;
-    my $filename = "/tmp/filt" ;
+    my $filename = "filt" ;
     unlink $filename ;
 
 
@@ -1894,8 +1895,8 @@ peril!
 
 The locking technique went like this. 
 
-    $db = tie(%db, 'DB_File', '/tmp/foo.db', O_CREAT|O_RDWR, 0666)
-        || die "dbcreat /tmp/foo.db $!";
+    $db = tie(%db, 'DB_File', 'foo.db', O_CREAT|O_RDWR, 0644)
+        || die "dbcreat foo.db $!";
     $fd = $db->fd;
     open(DB_FH, "+<&=$fd") || die "dup $!";
     flock (DB_FH, LOCK_EX) || die "flock: $!";
@@ -2233,7 +2234,7 @@ B<DB_File> comes with the standard Perl source distribution. Look in
 the directory F<ext/DB_File>. Given the amount of time between releases
 of Perl the version that ships with Perl is quite likely to be out of
 date, so the most recent version can always be found on CPAN (see
-L<perlmod/CPAN> for details), in the directory
+L<perlmodlib/CPAN> for details), in the directory
 F<modules/by-module/DB_File>.
 
 This version of B<DB_File> will work with either version 1.x, 2.x or
@@ -2252,7 +2253,7 @@ compile properly on IRIX 5.3.
 
 =head1 COPYRIGHT
 
-Copyright (c) 1995-2002 Paul Marquess. All rights reserved. This program
+Copyright (c) 1995-2004 Paul Marquess. All rights reserved. This program
 is free software; you can redistribute it and/or modify it under the
 same terms as Perl itself.
 
@@ -2278,14 +2279,14 @@ Berkeley DB authors or the author of DB_File. See L<"AUTHOR"> for details.
 
 =head1 SEE ALSO
 
-L<perl(1)>, L<dbopen(3)>, L<hash(3)>, L<recno(3)>, L<btree(3)>,
-L<dbmfilter>
+L<perl>, L<dbopen(3)>, L<hash(3)>, L<recno(3)>, L<btree(3)>,
+L<perldbmfilter>
 
 =head1 AUTHOR
 
 The DB_File interface was written by Paul Marquess
-E<lt>Paul.Marquess@btinternet.comE<gt>.
+E<lt>pmqs@cpan.orgE<gt>.
 Questions about the DB system itself may be addressed to
-E<lt>db@sleepycat.com<gt>.
+E<lt>db@sleepycat.comE<gt>.
 
 =cut
diff --git a/storage/bdb/perl/DB_File/DB_File.xs b/storage/bdb/perl/DB_File/DB_File.xs
index fba8dede791c45e19fa248c7d026a80b6ed25164..8f6cec1cc39bafa32c4636ebe910a0c99036d021 100644
--- a/storage/bdb/perl/DB_File/DB_File.xs
+++ b/storage/bdb/perl/DB_File/DB_File.xs
@@ -2,13 +2,13 @@
 
  DB_File.xs -- Perl 5 interface to Berkeley DB 
 
- written by Paul Marquess <Paul.Marquess@btinternet.com>
- last modified 1st September 2002
- version 1.805
+ written by Paul Marquess <pmqs@cpan.org>
+ last modified 7th August 2004
+ version 1.810
 
  All comments/suggestions/problems are welcome
 
-     Copyright (c) 1995-2002 Paul Marquess. All rights reserved.
+     Copyright (c) 1995-2004 Paul Marquess. All rights reserved.
      This program is free software; you can redistribute it and/or
      modify it under the same terms as Perl itself.
 
@@ -105,6 +105,11 @@
         1.805 - recursion detection added to the callbacks
                 Support for 4.1.X added.
                 Filter code can now cope with read-only $_
+        1.806 - recursion detection beefed up.
+        1.807 - no change
+        1.808 - leak fixed in ParseOpenInfo
+        1.809 - no change
+        1.810 - no change
 
 */
 
@@ -393,9 +398,11 @@ typedef DBT DBTKEY ;
 
 #define OutputValue(arg, name)  					\
 	{ if (RETVAL == 0) {						\
+	      SvGETMAGIC(arg) ;          				\
 	      my_sv_setpvn(arg, name.data, name.size) ;			\
-	      TAINT;                                       	\
+	      TAINT;                                       		\
 	      SvTAINTED_on(arg);                                       	\
+	      SvUTF8_off(arg);                                       	\
 	      DBM_ckFilter(arg, filter_fetch_value,"filter_fetch_value") ; 	\
 	  }								\
 	}
@@ -403,13 +410,15 @@ typedef DBT DBTKEY ;
 #define OutputKey(arg, name)	 					\
 	{ if (RETVAL == 0) 						\
 	  { 								\
+		SvGETMAGIC(arg) ;          				\
 		if (db->type != DB_RECNO) {				\
 		    my_sv_setpvn(arg, name.data, name.size); 		\
 		}							\
 		else 							\
 		    sv_setiv(arg, (I32)*(I32*)name.data - 1); 		\
-	      TAINT;                                       	\
+	      TAINT;                                       		\
 	      SvTAINTED_on(arg);                                       	\
+	      SvUTF8_off(arg);                                       	\
 	      DBM_ckFilter(arg, filter_fetch_key,"filter_fetch_key") ; 	\
 	  } 								\
 	}
@@ -505,7 +514,6 @@ u_int		flags ;
 static void
 tidyUp(DB_File db)
 {
-    /* db_DESTROY(db); */
     db->aborted = TRUE ;
 }
 
@@ -543,7 +551,6 @@ const DBT * key2 ;
     void * data1, * data2 ;
     int retval ;
     int count ;
-    DB_File	keep_CurrentDB = CurrentDB;
     
 
     if (CurrentDB->in_compare) {
@@ -567,6 +574,10 @@ const DBT * key2 ;
 
     ENTER ;
     SAVETMPS;
+    SAVESPTR(CurrentDB);
+    CurrentDB->in_compare = FALSE;
+    SAVEINT(CurrentDB->in_compare);
+    CurrentDB->in_compare = TRUE;
 
     PUSHMARK(SP) ;
     EXTEND(SP,2) ;
@@ -574,13 +585,8 @@ const DBT * key2 ;
     PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
     PUTBACK ;
 
-    CurrentDB->in_compare = TRUE;
-
     count = perl_call_sv(CurrentDB->compare, G_SCALAR); 
 
-    CurrentDB = keep_CurrentDB;
-    CurrentDB->in_compare = FALSE;
-
     SPAGAIN ;
 
     if (count != 1){
@@ -630,7 +636,6 @@ const DBT * key2 ;
     char * data1, * data2 ;
     int retval ;
     int count ;
-    DB_File	keep_CurrentDB = CurrentDB;
     
     if (CurrentDB->in_prefix){
         tidyUp(CurrentDB);
@@ -653,6 +658,10 @@ const DBT * key2 ;
 
     ENTER ;
     SAVETMPS;
+    SAVESPTR(CurrentDB);
+    CurrentDB->in_prefix = FALSE;
+    SAVEINT(CurrentDB->in_prefix);
+    CurrentDB->in_prefix = TRUE;
 
     PUSHMARK(SP) ;
     EXTEND(SP,2) ;
@@ -660,13 +669,8 @@ const DBT * key2 ;
     PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
     PUTBACK ;
 
-    CurrentDB->in_prefix = TRUE;
-
     count = perl_call_sv(CurrentDB->prefix, G_SCALAR); 
 
-    CurrentDB = keep_CurrentDB;
-    CurrentDB->in_prefix = FALSE;
-
     SPAGAIN ;
 
     if (count != 1){
@@ -719,9 +723,8 @@ HASH_CB_SIZE_TYPE size ;
 #endif    
     dSP ;
     dMY_CXT;
-    int retval ;
+    int retval = 0;
     int count ;
-    DB_File	keep_CurrentDB = CurrentDB;
 
     if (CurrentDB->in_hash){
         tidyUp(CurrentDB);
@@ -736,19 +739,19 @@ HASH_CB_SIZE_TYPE size ;
      /* DGH - Next two lines added to fix corrupted stack problem */
     ENTER ;
     SAVETMPS;
+    SAVESPTR(CurrentDB);
+    CurrentDB->in_hash = FALSE;
+    SAVEINT(CurrentDB->in_hash);
+    CurrentDB->in_hash = TRUE;
 
     PUSHMARK(SP) ;
 
+
     XPUSHs(sv_2mortal(newSVpvn((char*)data,size)));
     PUTBACK ;
 
-    keep_CurrentDB->in_hash = TRUE;
-
     count = perl_call_sv(CurrentDB->hash, G_SCALAR); 
 
-    CurrentDB = keep_CurrentDB;
-    CurrentDB->in_hash = FALSE;
-
     SPAGAIN ;
 
     if (count != 1){
@@ -765,6 +768,7 @@ HASH_CB_SIZE_TYPE size ;
     return (retval) ;
 }
 
+#if 0
 static void
 #ifdef CAN_PROTOTYPE
 db_errcall_cb(const char * db_errpfx, char * buffer)
@@ -774,6 +778,9 @@ const char * db_errpfx;
 char * buffer;
 #endif
 {
+#ifdef dTHX
+    dTHX;
+#endif    
     SV * sv = perl_get_sv(ERR_BUFF, FALSE) ;
     if (sv) {
         if (db_errpfx)
@@ -782,6 +789,7 @@ char * buffer;
             sv_setpv(sv, buffer) ;
     }
 } 
+#endif
 
 #if defined(TRACE) && defined(BERKELEY_DB_1_OR_2)
 
@@ -817,7 +825,7 @@ INFO * recno ;
     printf ("  cachesize = %d\n", recno->db_RE_cachesize) ;
     printf ("  psize     = %d\n", recno->db_RE_psize) ;
     printf ("  lorder    = %d\n", recno->db_RE_lorder) ;
-    printf ("  reclen    = %ul\n", (unsigned long)recno->db_RE_reclen) ;
+    printf ("  reclen    = %lu\n", (unsigned long)recno->db_RE_reclen) ;
     printf ("  bval      = %d 0x%x\n", recno->db_RE_bval, recno->db_RE_bval) ;
     printf ("  bfname    = %d [%s]\n", recno->db_RE_bfname, recno->db_RE_bfname) ;
 }
@@ -928,7 +936,10 @@ SV *   sv ;
     STRLEN	n_a;
     dMY_CXT;
 
-/* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ;  */
+#ifdef TRACE    
+    printf("In ParseOpenInfo name=[%s] flags=[%d] mode=[%d] SV NULL=[%d]\n", 
+		    name, flags, mode, sv == NULL) ;  
+#endif
     Zero(RETVAL, 1, DB_File_type) ;
 
     /* Default to HASH */
@@ -1428,7 +1439,7 @@ SV *   sv ;
 	/* printf("open returned %d %s\n", status, db_strerror(status)) ; */
 
         if (status == 0) {
-	    RETVAL->dbp->set_errcall(RETVAL->dbp, db_errcall_cb) ;
+	    /* RETVAL->dbp->set_errcall(RETVAL->dbp, db_errcall_cb) ;*/
 
             status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
 			0) ;
@@ -1455,7 +1466,10 @@ INCLUDE: constants.xs
 
 BOOT:
   {
-    SV * sv_err = perl_get_sv(ERR_BUFF, GV_ADD|GV_ADDMULTI) ;    
+#ifdef dTHX
+    dTHX;
+#endif    
+    /* SV * sv_err = perl_get_sv(ERR_BUFF, GV_ADD|GV_ADDMULTI) ;  */
     MY_CXT_INIT;
     __getBerkeleyDBInfo() ;
  
@@ -1485,8 +1499,10 @@ db_DoTie_(isHASH, dbtype, name=undef, flags=O_CREAT|O_RDWR, mode=0666, type=DB_H
 	        sv = ST(5) ;
 
 	    RETVAL = ParseOpenInfo(aTHX_ isHASH, name, flags, mode, sv) ;
-	    if (RETVAL->dbp == NULL)
+	    if (RETVAL->dbp == NULL) {
+	        Safefree(RETVAL);
 	        RETVAL = NULL ;
+	    }
 	}
 	OUTPUT:	
 	    RETVAL
@@ -1649,7 +1665,8 @@ unshift(db, ...)
 #endif
 	    for (i = items-1 ; i > 0 ; --i)
 	    {
-	        value.data = SvPV(ST(i), n_a) ;
+		DBM_ckFilter(ST(i), filter_store_value, "filter_store_value");
+	        value.data = SvPVbyte(ST(i), n_a) ;
 	        value.size = n_a ;
 	        One = 1 ;
 	        key.data = &One ;
@@ -1758,7 +1775,8 @@ push(db, ...)
 		    keyval = 0 ;
 	        for (i = 1 ; i < items ; ++i)
 	        {
-	            value.data = SvPV(ST(i), n_a) ;
+		    DBM_ckFilter(ST(i), filter_store_value, "filter_store_value");
+	            value.data = SvPVbyte(ST(i), n_a) ;
 	            value.size = n_a ;
 		    ++ keyval ;
 	            key.data = &keyval ;
diff --git a/storage/bdb/perl/DB_File/MANIFEST b/storage/bdb/perl/DB_File/MANIFEST
index b3e1a7bd85b92d1064f1537bd693774546dc7ffc..06b70ee68663794f99155ee8fe6a280607a85b2b 100644
--- a/storage/bdb/perl/DB_File/MANIFEST
+++ b/storage/bdb/perl/DB_File/MANIFEST
@@ -28,3 +28,4 @@ t/db-hash.t
 t/db-recno.t
 typemap
 version.c
+META.yml                                 Module meta-data (added by MakeMaker)
diff --git a/storage/bdb/perl/DB_File/META.yml b/storage/bdb/perl/DB_File/META.yml
new file mode 100644
index 0000000000000000000000000000000000000000..2cb481b8cdbfd11ed2252df02e418a3ca1eed0b5
--- /dev/null
+++ b/storage/bdb/perl/DB_File/META.yml
@@ -0,0 +1,10 @@
+# http://module-build.sourceforge.net/META-spec.html
+#XXXXXXX This is a prototype!!!  It will change in the future!!! XXXXX#
+name:         DB_File
+version:      1.810
+version_from: DB_File.pm
+installdirs:  site
+requires:
+
+distribution_type: module
+generated_by: ExtUtils::MakeMaker version 6.21_02
diff --git a/storage/bdb/perl/DB_File/Makefile.PL b/storage/bdb/perl/DB_File/Makefile.PL
index 4c1565d8d01b7306cacffe2ae488e84ec1513475..a8c671002ba0f1443f039eda666d0c19b7a43d77 100644
--- a/storage/bdb/perl/DB_File/Makefile.PL
+++ b/storage/bdb/perl/DB_File/Makefile.PL
@@ -38,6 +38,9 @@ $LIBS .= " -lpthread" if $^O eq 'aix' ;
 my $OS2 = "" ;
 $OS2 = "-DOS2" if $Config{'osname'} eq 'os2' ;
 
+my $WALL = '' ;
+#$WALL = ' -Wall ';
+
 WriteMakefile(
 	NAME 		=> 'DB_File',
 	LIBS 		=> ["-L${LIB_DIR} $LIBS"],
@@ -45,7 +48,7 @@ WriteMakefile(
 	INC		=> "-I$INC_DIR",
 	VERSION_FROM	=> 'DB_File.pm',
 	XSPROTOARG	=> '-noprototypes',
-	DEFINE		=> "-D_NOT_CORE $OS2 $VER_INFO $COMPAT185",
+	DEFINE		=> "-D_NOT_CORE $OS2 $VER_INFO $COMPAT185 $WALL",
 	OBJECT		=> 'version$(OBJ_EXT) DB_File$(OBJ_EXT)',
 	#OPTIMIZE	=> '-g',
 	'depend'	=> { 'Makefile'          => 'config.in',
@@ -214,7 +217,7 @@ sub ParseCONFIG
 
     $INC_DIR = $ENV{'DB_FILE_INCLUDE'} || $Info{'INCLUDE'} ;
     $LIB_DIR = $ENV{'DB_FILE_LIB'} || $Info{'LIB'} ;
-    $DB_NAME = $Info{'DBNAME'} if defined $Info{'DBNAME'} ;
+    $DB_NAME = $ENV{'DB_FILE_NAME'} || $Info{'DBNAME'} ;
     $COMPAT185 = "-DCOMPAT185 -DDB_LIBRARY_COMPATIBILITY_API" 
         if (defined $ENV{'DB_FILE_COMPAT185'} && 
 		$ENV{'DB_FILE_COMPAT185'} =~ /^\s*(on|true|1)\s*$/i) ||
diff --git a/storage/bdb/perl/DB_File/README b/storage/bdb/perl/DB_File/README
index b09aa9d8aeeded9d1c4cc94b7b1fadba30b98bee..5a435fd0ceeb39b37e54ba8ff84a11346cbc2f84 100644
--- a/storage/bdb/perl/DB_File/README
+++ b/storage/bdb/perl/DB_File/README
@@ -1,10 +1,10 @@
                                      DB_File
 
-                                  Version 1.805
+                                  Version 1.810
 
-                                  1st Sep 2002
+                                 7th August 2004
 
- 	Copyright (c) 1995-2002 Paul Marquess. All rights reserved. This
+ 	Copyright (c) 1995-2004 Paul Marquess. All rights reserved. This
 	program is free software; you can redistribute it and/or modify
 	it under the same terms as Perl itself.
 
@@ -96,6 +96,12 @@ INSTALLATION
 
     make install
 
+UPDATES
+=======
+
+The most recent version of DB_File is always available at 
+
+    http://www.cpan.org/modules/by-module/DB_File/
 
 TROUBLESHOOTING
 ===============
@@ -220,6 +226,78 @@ Solution: Setting the LIB & INCLUDE variables in config.in to point to the
           below.
 
 
+Solaris build fails with "language optional software package not installed"
+---------------------------------------------------------------------------
+
+If you are trying to build this module under Solaris and you get an
+error message like this
+
+    /usr/ucb/cc: language optional software package not installed
+
+it means that Perl cannot find the C compiler on your system. The cryptic
+message is just Sun's way of telling you that you haven't bought their
+C compiler.
+
+When you build a Perl module that needs a C compiler, the Perl build
+system tries to use the same C compiler that was used to build perl
+itself. In this case your Perl binary was built with a C compiler that
+lived in /usr/ucb.
+
+To continue with building this module, you need to get a C compiler,
+or tell Perl where your C compiler is, if you already have one.
+
+Assuming you have now got a C compiler, what you do next will be dependant
+on what C compiler you have installed. If you have just installed Sun's
+C compiler, you shouldn't have to do anything. Just try rebuilding
+this module.
+
+If you have installed another C compiler, say gcc, you have to tell perl
+how to use it instead of /usr/ucb/cc.
+
+This set of options seems to work if you want to use gcc. Your mileage
+may vary.
+
+    perl Makefile.PL CC=gcc CCCDLFLAGS=-fPIC OPTIMIZE=" "
+    make test
+
+If that doesn't work for you, it's time to make changes to the Makefile
+by hand. Good luck!
+
+
+
+Solaris build fails with "gcc: unrecognized option `-KPIC'"
+-----------------------------------------------------------
+
+You are running Solaris and you get an error like this when you try to
+build this Perl module
+
+    gcc: unrecognized option `-KPIC'
+
+This symptom usually means that you are using a Perl binary that has been
+built with the Sun C compiler, but you are using gcc to build this module.
+
+When Perl builds modules that need a C compiler, it will attempt to use
+the same C compiler and command line options that was used to build perl
+itself. In this case "-KPIC" is a valid option for the Sun C compiler,
+but not for gcc. The equivalent option for gcc is "-fPIC".
+
+The solution is either:
+
+    1. Build both Perl and this module with the same C compiler, either
+       by using the Sun C compiler for both or gcc for both.
+
+    2. Try generating the Makefile for this module like this perl
+
+           perl Makefile.PL CC=gcc CCCDLFLAGS=-fPIC OPTIMIZE=" " LD=gcc
+           make test
+
+       This second option seems to work when mixing a Perl binary built
+       with the Sun C compiler and this module built with gcc. Your
+       mileage may vary.
+
+
+
+
 Linux Notes
 -----------
 
@@ -377,11 +455,50 @@ If you are running IRIX, and want to use Berkeley DB version 1, you can
 get it from http://reality.sgi.com/ariel. It has the patches necessary
 to compile properly on IRIX 5.3.
 
+AIX NOTES
+---------
+
+I've had replrts of a build failure like this on AIX 5.2 using the
+xlC compiler.
+
+        rm -f blib/arch/auto/DB_File/DB_File.so
+        LD_RUN_PATH="" ld  -bhalt:4 -bM:SRE -bI:/usr/local/5.8.1/lib/perl5/5.8.1/aix/CORE/perl.exp -bE:DB_File.exp -bnoentry -lc
+    -L/usr/local/lib version.o DB_File.o  -o blib/arch/auto/DB_File/DB_File.so
+    -L/usr/local/BerkeleyDB/lib -ldb -lpthread
+    ld: 0711-317 ERROR: Undefined symbol: .mutex_lock
+    ld: 0711-317 ERROR: Undefined symbol: .cond_signal
+    ld: 0711-317 ERROR: Undefined symbol: .mutex_unlock
+    ld: 0711-317 ERROR: Undefined symbol: .mutex_trylock
+    ld: 0711-317 ERROR: Undefined symbol: .cond_wait
+    ld: 0711-317 ERROR: Undefined symbol: .mutex_init
+    ld: 0711-317 ERROR: Undefined symbol: .cond_init
+    ld: 0711-317 ERROR: Undefined symbol: .mutex_destroy
+    ld: 0711-345 Use the -bloadmap or -bnoquiet option to obtain more information.
+    make: 1254-004 The error code from the last command is 8.
+
+Editing Makefile.PL, and changing the line 
+
+    $LIBS .= " -lpthread" if $^O eq 'aix' ;
+
+to this
+
+    $LIBS .= " -lthread" if $^O eq 'aix' ;
+
+fixed the problem.
+
 
 FEEDBACK
 ========
 
+General feedback/questions/bug reports can be sent to me at pmqs@cpan.org.
+
+Alternatively, if you have Usenet access, you can try the
+comp.databases.berkeley-db or comp.lang.perl.modules groups.
+
+
+
 How to report a problem with DB_File.
+-------------------------------------
 
 When reporting any problem, I need the information requested below. 
 
@@ -401,6 +518,10 @@ When reporting any problem, I need the information requested below.
 
        perl -e 'use DB_File; print qq{DB_File ver $DB_File::VERSION\n}'
 
+    If you are running windows use this
+    
+       perl -e "use DB_File; print qq{DB_File ver $DB_File::VERSION\n}"
+
     If you haven't installed DB_File then search DB_File.pm for a line
     like this:
 
@@ -416,6 +537,10 @@ When reporting any problem, I need the information requested below.
 
        perl -e 'use DB_File; print qq{Berkeley DB ver $DB_File::db_ver\n}'
 
+    If you are running windows use this
+
+       perl -e "use DB_File; print qq{Berkeley DB ver $DB_File::db_ver\n}"
+    
  4. A copy the file config.in from the DB_File main source directory.
 
  5. A listing of directories where Berkeley DB is installed.
@@ -455,4 +580,4 @@ CHANGES
 
 See the Changes file.
 
-Paul Marquess <Paul.Marquess@btinternet.com>
+Paul Marquess <pmqs@cpan.org>
diff --git a/storage/bdb/perl/DB_File/dbinfo b/storage/bdb/perl/DB_File/dbinfo
index af2c45facf5c03850efdd224969210c79aac9344..421d36c62602a6622108ffb112b562aabfd16c8b 100644
--- a/storage/bdb/perl/DB_File/dbinfo
+++ b/storage/bdb/perl/DB_File/dbinfo
@@ -4,10 +4,10 @@
 #			  a database file
 #
 # Author:	Paul Marquess  <Paul.Marquess@btinternet.com>
-# Version: 	1.03 
-# Date		17th September 2000
+# Version: 	1.05 
+# Date		1sh November 2003
 #
-#     Copyright (c) 1998-2002 Paul Marquess. All rights reserved.
+#     Copyright (c) 1998-2003 Paul Marquess. All rights reserved.
 #     This program is free software; you can redistribute it and/or
 #     modify it under the same terms as Perl itself.
 
@@ -22,39 +22,39 @@ my %Data =
 			  Type 	   => "Btree",
 			  Versions => 
 				{
-				  1	=> "Unknown (older than 1.71)",
-				  2	=> "Unknown (older than 1.71)",
-				  3	=> "1.71 -> 1.85, 1.86",
-				  4	=> "Unknown",
-				  5	=> "2.0.0 -> 2.3.0",
-				  6	=> "2.3.1 -> 2.7.7",
-				  7	=> "3.0.x",
-				  8	=> "3.1.x -> 4.0.x",
-				  9	=> "4.1.x or greater",
+				  1	=> [0, "Unknown (older than 1.71)"],
+				  2	=> [0, "Unknown (older than 1.71)"],
+				  3	=> [0, "1.71 -> 1.85, 1.86"],
+				  4	=> [0, "Unknown"],
+				  5	=> [0, "2.0.0 -> 2.3.0"],
+				  6	=> [0, "2.3.1 -> 2.7.7"],
+				  7	=> [0, "3.0.x"],
+				  8	=> [0, "3.1.x -> 4.0.x"],
+				  9	=> [1, "4.1.x or greater"],
 				}
 			},
 	0x061561 => 	{
 			  Type     => "Hash",
 			  Versions =>
 				{
-				  1	=> "Unknown (older than 1.71)",
-        			  2     => "1.71 -> 1.85",
-        			  3     => "1.86",
-        			  4     => "2.0.0 -> 2.1.0",
-        			  5     => "2.2.6 -> 2.7.7",
-        			  6     => "3.0.x",
-				  7	=> "3.1.x -> 4.0.x",
-				  8	=> "4.1.x or greater",
+				  1	=> [0, "Unknown (older than 1.71)"],
+        			  2     => [0, "1.71 -> 1.85"],
+        			  3     => [0, "1.86"],
+        			  4     => [0, "2.0.0 -> 2.1.0"],
+        			  5     => [0, "2.2.6 -> 2.7.7"],
+        			  6     => [0, "3.0.x"],
+				  7	=> [0, "3.1.x -> 4.0.x"],
+				  8	=> [1, "4.1.x or greater"],
 				}
 			},
 	0x042253 => 	{
 			  Type     => "Queue",
 			  Versions =>
 				{
-				  1	=> "3.0.x",
-				  2	=> "3.1.x",
-				  3	=> "3.2.x -> 4.0.x",
-				  4	=> "4.1.x or greater",
+				  1	=> [0, "3.0.x"],
+				  2	=> [0, "3.1.x"],
+				  3	=> [0, "3.2.x -> 4.0.x"],
+				  4	=> [1, "4.1.x or greater"],
 				}
 			},
 	) ;
@@ -65,17 +65,26 @@ print "testing file $ARGV[0]...\n\n" ;
 open (F, "<$ARGV[0]") or die "Cannot open file $ARGV[0]: $!\n" ;
 
 my $buff ;
-read F, $buff, 20 ;
+read F, $buff, 30 ;
 
-my (@info) = unpack("NNNNN", $buff) ;
-my (@info1) = unpack("VVVVV", $buff) ;
-my ($magic, $version, $endian) ;
 
-if ($Data{$info[0]}) # first try DB 1.x format
+my (@info) = unpack("NNNNNNC", $buff) ;
+my (@info1) = unpack("VVVVVVC", $buff) ;
+my ($magic, $version, $endian, $encrypt) ;
+
+if ($Data{$info[0]}) # first try DB 1.x format, big endian
 {
     $magic = $info[0] ;
     $version = $info[1] ;
-    $endian  = "Unknown" ;
+    $endian  = "Big Endian" ;
+    $encrypt = "Not Supported";
+}
+elsif ($Data{$info1[0]}) # first try DB 1.x format, little endian
+{
+    $magic = $info1[0] ;
+    $version = $info1[1] ;
+    $endian  = "Little Endian" ;
+    $encrypt = "Not Supported";
 }
 elsif ($Data{$info[3]}) # next DB 2.x big endian
 {
@@ -96,8 +105,15 @@ my $type = $Data{$magic} ;
 $magic = sprintf "%06X", $magic ;
 
 my $ver_string = "Unknown" ;
-$ver_string = $type->{Versions}{$version}
-	if defined $type->{Versions}{$version} ;
+
+if ( defined $type->{Versions}{$version} )
+{
+     $ver_string = $type->{Versions}{$version}[1];
+     if ($type->{Versions}{$version}[0] )
+       { $encrypt = $info[6] ? "Enabled" : "Disabled" }
+     else
+       { $encrypt = "Not Supported" }
+}
 
 print <<EOM ;
 File Type:		Berkeley DB $type->{Type} file.
@@ -105,6 +121,7 @@ File Version ID:	$version
 Built with Berkeley DB:	$ver_string
 Byte Order:		$endian
 Magic:			$magic
+Encryption:             $encrypt
 EOM
 
 close F ;
diff --git a/storage/bdb/perl/DB_File/patches/5.004 b/storage/bdb/perl/DB_File/patches/5.004
index 143ec95afbc457e383256e48266e38fa147a3c0f..0665d1f6c4068b56da4f3a2cef17f83fdd81883f 100644
--- a/storage/bdb/perl/DB_File/patches/5.004
+++ b/storage/bdb/perl/DB_File/patches/5.004
@@ -1,44 +1,93 @@
-diff perl5.004.orig/Configure perl5.004/Configure
-190a191
-> perllibs=''
-9904a9906,9913
-> : Remove libraries needed only for extensions
-> : The appropriate ext/Foo/Makefile.PL will add them back in, if
-> : necessary.
-> set X `echo " $libs " | 
->   sed -e 's@ -lndbm @ @' -e 's@ -lgdbm @ @' -e 's@ -ldbm @ @' -e 's@ -ldb @ @'` 
-> shift
-> perllibs="$*"
-> 
-10372a10382
-> perllibs='$perllibs'
-diff perl5.004.orig/Makefile.SH perl5.004/Makefile.SH
-122c122
-< libs = $libs $cryptlib
----
-> libs = $perllibs $cryptlib
-Common subdirectories: perl5.004.orig/Porting and perl5.004/Porting
-Common subdirectories: perl5.004.orig/cygwin32 and perl5.004/cygwin32
-Common subdirectories: perl5.004.orig/eg and perl5.004/eg
-Common subdirectories: perl5.004.orig/emacs and perl5.004/emacs
-Common subdirectories: perl5.004.orig/ext and perl5.004/ext
-Common subdirectories: perl5.004.orig/h2pl and perl5.004/h2pl
-Common subdirectories: perl5.004.orig/hints and perl5.004/hints
-Common subdirectories: perl5.004.orig/lib and perl5.004/lib
-diff perl5.004.orig/myconfig perl5.004/myconfig
-38c38
-<     libs=$libs
----
->     libs=$perllibs
-Common subdirectories: perl5.004.orig/os2 and perl5.004/os2
-diff perl5.004.orig/patchlevel.h perl5.004/patchlevel.h
-40a41
-> 	,"NODB-1.0 - remove -ldb from core perl binary."
-Common subdirectories: perl5.004.orig/plan9 and perl5.004/plan9
-Common subdirectories: perl5.004.orig/pod and perl5.004/pod
-Common subdirectories: perl5.004.orig/qnx and perl5.004/qnx
-Common subdirectories: perl5.004.orig/t and perl5.004/t
-Common subdirectories: perl5.004.orig/utils and perl5.004/utils
-Common subdirectories: perl5.004.orig/vms and perl5.004/vms
-Common subdirectories: perl5.004.orig/win32 and perl5.004/win32
-Common subdirectories: perl5.004.orig/x2p and perl5.004/x2p
+diff -rc perl5.004.orig/Configure perl5.004/Configure
+*** perl5.004.orig/Configure	1997-05-13 18:20:34.000000000 +0100
+--- perl5.004/Configure	2003-04-26 16:36:53.000000000 +0100
+***************
+*** 188,193 ****
+--- 188,194 ----
+  mv=''
+  nroff=''
+  perl=''
++ perllibs=''
+  pg=''
+  pmake=''
+  pr=''
+***************
+*** 9902,9907 ****
+--- 9903,9916 ----
+  shift
+  extensions="$*"
+  
++ : Remove libraries needed only for extensions
++ : The appropriate ext/Foo/Makefile.PL will add them back in, if
++ : necessary.
++ set X `echo " $libs " | 
++   sed -e 's@ -lndbm @ @' -e 's@ -lgdbm @ @' -e 's@ -ldbm @ @' -e 's@ -ldb @ @'` 
++ shift
++ perllibs="$*"
++ 
+  : Remove build directory name from cppstdin so it can be used from
+  : either the present location or the final installed location.
+  echo " "
+***************
+*** 10370,10375 ****
+--- 10379,10385 ----
+  patchlevel='$patchlevel'
+  path_sep='$path_sep'
+  perl='$perl'
++ perllibs='$perllibs'
+  perladmin='$perladmin'
+  perlpath='$perlpath'
+  pg='$pg'
+diff -rc perl5.004.orig/Makefile.SH perl5.004/Makefile.SH
+*** perl5.004.orig/Makefile.SH	1997-05-01 15:22:39.000000000 +0100
+--- perl5.004/Makefile.SH	2003-04-26 16:37:23.000000000 +0100
+***************
+*** 119,125 ****
+  ext = \$(dynamic_ext) \$(static_ext)
+  DYNALOADER = lib/auto/DynaLoader/DynaLoader\$(LIB_EXT)
+  
+! libs = $libs $cryptlib
+  
+  public = perl $suidperl utilities translators
+  
+--- 119,125 ----
+  ext = \$(dynamic_ext) \$(static_ext)
+  DYNALOADER = lib/auto/DynaLoader/DynaLoader\$(LIB_EXT)
+  
+! libs = $perllibs $cryptlib
+  
+  public = perl $suidperl utilities translators
+  
+diff -rc perl5.004.orig/myconfig perl5.004/myconfig
+*** perl5.004.orig/myconfig	1996-12-21 01:13:20.000000000 +0000
+--- perl5.004/myconfig	2003-04-26 16:37:51.000000000 +0100
+***************
+*** 35,41 ****
+    Linker and Libraries:
+      ld='$ld', ldflags ='$ldflags'
+      libpth=$libpth
+!     libs=$libs
+      libc=$libc, so=$so
+      useshrplib=$useshrplib, libperl=$libperl
+    Dynamic Linking:
+--- 35,41 ----
+    Linker and Libraries:
+      ld='$ld', ldflags ='$ldflags'
+      libpth=$libpth
+!     libs=$perllibs
+      libc=$libc, so=$so
+      useshrplib=$useshrplib, libperl=$libperl
+    Dynamic Linking:
+diff -rc perl5.004.orig/patchlevel.h perl5.004/patchlevel.h
+*** perl5.004.orig/patchlevel.h	1997-05-15 23:15:17.000000000 +0100
+--- perl5.004/patchlevel.h	2003-04-26 16:38:11.000000000 +0100
+***************
+*** 38,43 ****
+--- 38,44 ----
+   */
+  static	char	*local_patches[] = {
+  	NULL
++ 	,"NODB-1.0 - remove -ldb from core perl binary."
+  	,NULL
+  };
+  
diff --git a/storage/bdb/perl/DB_File/ppport.h b/storage/bdb/perl/DB_File/ppport.h
index 0887c2159a9a86b75f886cceccc3bbc62c4227a4..effa5072936b598d5945096a90db875d76b7a5fb 100644
--- a/storage/bdb/perl/DB_File/ppport.h
+++ b/storage/bdb/perl/DB_File/ppport.h
@@ -278,7 +278,35 @@ SV *sv;
 
 #endif /* START_MY_CXT */
 
+#ifdef SvPVbyte
+#   if PERL_REVISION == 5 && PERL_VERSION < 7
+       /* SvPVbyte does not work in perl-5.6.1, borrowed version for 5.7.3 */
+#       undef SvPVbyte
+#       define SvPVbyte(sv, lp) \
+          ((SvFLAGS(sv) & (SVf_POK|SVf_UTF8)) == (SVf_POK) \
+           ? ((lp = SvCUR(sv)), SvPVX(sv)) : my_sv_2pvbyte(aTHX_ sv, &lp))
+       static char *
+       my_sv_2pvbyte(pTHX_ register SV *sv, STRLEN *lp)
+       {
+           sv_utf8_downgrade(sv,0);
+           return SvPV(sv,*lp);
+       }
+#   endif
+#else
+#   define SvPVbyte SvPV
+#endif
+	
+#ifndef SvUTF8_off
+#    define SvUTF8_off(s)
+#endif
 
+#if 1
+#ifdef DBM_setFilter
+#undef DBM_setFilter
+#undef DBM_ckFilter
+#endif
+#endif
+	
 #ifndef DBM_setFilter
 
 /* 
@@ -305,6 +333,7 @@ SV *sv;
 
 #define DBM_ckFilter(arg,type,name)				\
 	if (db->type) {						\
+	    /*printf("ckFilter %s\n", name);*/			\
 	    if (db->filtering) {				\
 	        croak("recursion detected in %s", name) ;	\
 	    }                     				\
@@ -313,6 +342,8 @@ SV *sv;
 	    SAVEINT(db->filtering) ;				\
 	    db->filtering = TRUE ;				\
 	    SAVESPTR(DEFSV) ;					\
+            if (name[7] == 's')                                 \
+                arg = newSVsv(arg);                             \
 	    DEFSV = arg ;					\
 	    SvTEMP_off(arg) ;					\
 	    PUSHMARK(SP) ;					\
@@ -322,6 +353,10 @@ SV *sv;
 	    PUTBACK ;						\
 	    FREETMPS ;						\
 	    LEAVE ;						\
+            if (name[7] == 's'){                                \
+                arg = sv_2mortal(arg);                          \
+            }                                                   \
+            SvOKp(arg);                                         \
 	}
 
 #endif /* DBM_setFilter */
diff --git a/storage/bdb/perl/DB_File/t/db-btree.t b/storage/bdb/perl/DB_File/t/db-btree.t
index a990a5c4ba555f05ff72bda99e6b7f99676d13ae..deab41010eb38865960fa4778c8dfd750ff82351 100644
--- a/storage/bdb/perl/DB_File/t/db-btree.t
+++ b/storage/bdb/perl/DB_File/t/db-btree.t
@@ -24,7 +24,7 @@ BEGIN {
 	&& $Config{db_version_patch} == 0) {
 	warn <<EOM;
 #
-# This test is known to crash in Mac OS X versions 10.1.4 (or earlier)
+# This test is known to crash in Mac OS X versions 10.2 (or earlier)
 # because of the buggy Berkeley DB version included with the OS.
 #
 EOM
@@ -34,7 +34,9 @@ EOM
 use DB_File; 
 use Fcntl;
 
-print "1..177\n";
+print "1..197\n";
+
+unlink glob "__db.*";
 
 sub ok
 {
@@ -1384,28 +1386,30 @@ EOM
 }
 
 
-{
-    # recursion detection in btree
-    my %hash ;
-    unlink $Dfile;
-    my $dbh = new DB_File::BTREEINFO ;
-    $dbh->{compare} = sub { $hash{3} = 4 ; length $_[0] } ;
- 
- 
-    my (%h);
-    ok(164, tie(%hash, 'DB_File',$Dfile, O_RDWR|O_CREAT, 0640, $dbh ) );
-
-    eval {	$hash{1} = 2;
-    		$hash{4} = 5;
-	 };
-
-    ok(165, $@ =~ /^DB_File btree_compare: recursion detected/);
-    {
-        no warnings;
-        untie %hash;
-    }
-    unlink $Dfile;
-}
+#{
+#    # recursion detection in btree
+#    my %hash ;
+#    unlink $Dfile;
+#    my $dbh = new DB_File::BTREEINFO ;
+#    $dbh->{compare} = sub { $hash{3} = 4 ; length $_[0] } ;
+# 
+# 
+#    my (%h);
+#    ok(164, tie(%hash, 'DB_File',$Dfile, O_RDWR|O_CREAT, 0640, $dbh ) );
+#
+#    eval {	$hash{1} = 2;
+#    		$hash{4} = 5;
+#	 };
+#
+#    ok(165, $@ =~ /^DB_File btree_compare: recursion detected/);
+#    {
+#        no warnings;
+#        untie %hash;
+#    }
+#    unlink $Dfile;
+#}
+ok(164,1);
+ok(165,1);
 
 {
     # Check that two callbacks don't interact
@@ -1486,4 +1490,169 @@ EOM
    unlink $Dfile;
 }
 
+{
+   # Check low-level API works with filter
+
+   use warnings ;
+   use strict ;
+   my (%h, $db) ;
+   my $Dfile = "xxy.db";
+   unlink $Dfile;
+
+   ok(178, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE ) );
+
+
+   $db->filter_fetch_key   (sub { $_ = unpack("i", $_) } );
+   $db->filter_store_key   (sub { $_ = pack("i", $_) } );
+   $db->filter_fetch_value (sub { $_ = unpack("i", $_) } );
+   $db->filter_store_value (sub { $_ = pack("i", $_) } );
+
+   $_ = 'fred';
+
+   my $key = 22 ;
+   my $value = 34 ;
+
+   $db->put($key, $value) ;
+   ok 179, $key == 22;
+   ok 180, $value == 34 ;
+   ok 181, $_ eq 'fred';
+   #print "k [$key][$value]\n" ;
+
+   my $val ;
+   $db->get($key, $val) ;
+   ok 182, $key == 22;
+   ok 183, $val == 34 ;
+   ok 184, $_ eq 'fred';
+
+   $key = 51 ;
+   $value = 454;
+   $h{$key} = $value ;
+   ok 185, $key == 51;
+   ok 186, $value == 454 ;
+   ok 187, $_ eq 'fred';
+
+   undef $db ;
+   untie %h;
+   unlink $Dfile;
+}
+
+
+
+{
+    # Regression Test for bug 30237
+    # Check that substr can be used in the key to db_put
+    # and that db_put does not trigger the warning
+    # 
+    #     Use of uninitialized value in subroutine entry
+
+
+    use warnings ;
+    use strict ;
+    my (%h, $db) ;
+    my $Dfile = "xxy.db";
+    unlink $Dfile;
+
+    ok(188, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE ));
+
+    my $warned = '';
+    local $SIG{__WARN__} = sub {$warned = $_[0]} ;
+
+    # db-put with substr of key
+    my %remember = () ;
+    for my $ix ( 10 .. 12 )
+    {
+        my $key = $ix . "data" ;
+        my $value = "value$ix" ;
+        $remember{$key} = $value ;
+        $db->put(substr($key,0), $value) ;
+    }
+
+    ok 189, $warned eq '' 
+      or print "# Caught warning [$warned]\n" ;
+
+    # db-put with substr of value
+    $warned = '';
+    for my $ix ( 20 .. 22 )
+    {
+        my $key = $ix . "data" ;
+        my $value = "value$ix" ;
+        $remember{$key} = $value ;
+        $db->put($key, substr($value,0)) ;
+    }
+
+    ok 190, $warned eq '' 
+      or print "# Caught warning [$warned]\n" ;
+
+    # via the tied hash is not a problem, but check anyway
+    # substr of key
+    $warned = '';
+    for my $ix ( 30 .. 32 )
+    {
+        my $key = $ix . "data" ;
+        my $value = "value$ix" ;
+        $remember{$key} = $value ;
+        $h{substr($key,0)} = $value ;
+    }
+
+    ok 191, $warned eq '' 
+      or print "# Caught warning [$warned]\n" ;
+
+    # via the tied hash is not a problem, but check anyway
+    # substr of value
+    $warned = '';
+    for my $ix ( 40 .. 42 )
+    {
+        my $key = $ix . "data" ;
+        my $value = "value$ix" ;
+        $remember{$key} = $value ;
+        $h{$key} = substr($value,0) ;
+    }
+
+    ok 192, $warned eq '' 
+      or print "# Caught warning [$warned]\n" ;
+
+    my %bad = () ;
+    $key = '';
+    for ($status = $db->seq($key, $value, R_FIRST ) ;
+         $status == 0 ;
+         $status = $db->seq($key, $value, R_NEXT ) ) {
+
+        #print "# key [$key] value [$value]\n" ;
+        if (defined $remember{$key} && defined $value && 
+             $remember{$key} eq $value) {
+            delete $remember{$key} ;
+        }
+        else {
+            $bad{$key} = $value ;
+        }
+    }
+    
+    ok 193, keys %bad == 0 ;
+    ok 194, keys %remember == 0 ;
+
+    print "# missing -- $key $value\n" while ($key, $value) = each %remember;
+    print "# bad     -- $key $value\n" while ($key, $value) = each %bad;
+
+    # Make sure this fix does not break code to handle an undef key
+    # Berkeley DB undef key is bron between versions 2.3.16 and 
+    my $value = 'fred';
+    $warned = '';
+    $db->put(undef, $value) ;
+    ok 195, $warned eq '' 
+      or print "# Caught warning [$warned]\n" ;
+    $warned = '';
+
+    my $no_NULL = ($DB_File::db_ver >= 2.003016 && $DB_File::db_ver < 3.001) ;
+    print "# db_ver $DB_File::db_ver\n";
+    $value = '' ;
+    $db->get(undef, $value) ;
+    ok 196, $no_NULL || $value eq 'fred' or print "# got [$value]\n" ;
+    ok 197, $warned eq '' 
+      or print "# Caught warning [$warned]\n" ;
+    $warned = '';
+
+    undef $db ;
+    untie %h;
+    unlink $Dfile;
+}
 exit ;
diff --git a/storage/bdb/perl/DB_File/t/db-hash.t b/storage/bdb/perl/DB_File/t/db-hash.t
index 10623cc82a7736fc6421a2dcf98906c1d54aeda4..018952f9d4960824cdb8b1acf4a7c74d8a382660 100644
--- a/storage/bdb/perl/DB_File/t/db-hash.t
+++ b/storage/bdb/perl/DB_File/t/db-hash.t
@@ -23,7 +23,9 @@ BEGIN {
 use DB_File; 
 use Fcntl;
 
-print "1..143\n";
+print "1..166\n";
+
+unlink glob "__db.*";
 
 sub ok
 {
@@ -32,6 +34,8 @@ sub ok
  
     print "not " unless $result ;
     print "ok $no\n" ;
+
+    return $result ;
 }
 
 {
@@ -578,7 +582,8 @@ EOM
    ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
    $k = 'Fred'; $v ='';
    ok(74, ! $db->seq($k, $v, R_FIRST) ) ;
-   ok(75, $k eq "FRED") ;
+   ok(75, $k eq "Fred") ;
+    #print "k [$k]\n" ;
    ok(76, $v eq "[Jxe]") ;
    #                   fk   sk     fv    sv
    ok(77, checkOutput( "FRED", "fred", "[Jxe]", "")) ;
@@ -854,28 +859,32 @@ EOM
 
 }
 
-{
-    # recursion detection in hash
-    my %hash ;
-    unlink $Dfile;
-    my $dbh = new DB_File::HASHINFO ;
-    $dbh->{hash} = sub { $hash{3} = 4 ; length $_[0] } ;
- 
- 
-    my (%h);
-    ok(127, tie(%hash, 'DB_File',$Dfile, O_RDWR|O_CREAT, 0640, $dbh ) );
-
-    eval {	$hash{1} = 2;
-    		$hash{4} = 5;
-	 };
 
-    ok(128, $@ =~ /^DB_File hash callback: recursion detected/);
-    {
-        no warnings;
-        untie %hash;
-    }
-    unlink $Dfile;
-}
+#{
+#    # recursion detection in hash
+#    my %hash ;
+#    my $Dfile = "xxx.db";
+#    unlink $Dfile;
+#    my $dbh = new DB_File::HASHINFO ;
+#    $dbh->{hash} = sub { $hash{3} = 4 ; length $_[0] } ;
+# 
+# 
+#    ok(127, tie(%hash, 'DB_File',$Dfile, O_RDWR|O_CREAT, 0640, $dbh ) );
+#
+#    eval {	$hash{1} = 2;
+#    		$hash{4} = 5;
+#	 };
+#
+#    ok(128, $@ =~ /^DB_File hash callback: recursion detected/);
+#    {
+#        no warnings;
+#        untie %hash;
+#    }
+#    unlink $Dfile;
+#}
+
+#ok(127, 1);
+#ok(128, 1);
 
 {
     # Check that two hash's don't interact
@@ -893,8 +902,8 @@ EOM
  
  
     my (%h);
-    ok(129, tie(%hash1, 'DB_File',$Dfile, O_RDWR|O_CREAT, 0640, $dbh1 ) );
-    ok(130, tie(%hash2, 'DB_File',$Dfile2, O_RDWR|O_CREAT, 0640, $dbh2 ) );
+    ok(127, tie(%hash1, 'DB_File',$Dfile, O_RDWR|O_CREAT, 0640, $dbh1 ) );
+    ok(128, tie(%hash2, 'DB_File',$Dfile2, O_RDWR|O_CREAT, 0640, $dbh2 ) );
 
     $hash1{DEFG} = 5;
     $hash1{XYZ} = 2;
@@ -904,11 +913,11 @@ EOM
     $hash2{xyz} = 2;
     $hash2{abcde} = 5;
 
-    ok(131, $h1_count > 0);
-    ok(132, $h1_count == $h2_count);
+    ok(129, $h1_count > 0);
+    ok(130, $h1_count == $h2_count);
 
-    ok(133, safeUntie \%hash1);
-    ok(134, safeUntie \%hash2);
+    ok(131, safeUntie \%hash1);
+    ok(132, safeUntie \%hash2);
     unlink $Dfile, $Dfile2;
 }
 
@@ -923,14 +932,19 @@ EOM
     unlink $Dfile;
 
     tie %hash1, 'DB_File',$Dfile, undef;
-    ok(135, $warn_count == 0);
+    ok(133, $warn_count == 0);
     $warn_count = 0;
+    untie %hash1;
+    unlink $Dfile;
     tie %hash1, 'DB_File',$Dfile, O_RDWR|O_CREAT, undef;
-    ok(136, $warn_count == 0);
+    ok(134, $warn_count == 0);
+    untie %hash1;
+    unlink $Dfile;
     tie %hash1, 'DB_File',$Dfile, undef, undef;
-    ok(137, $warn_count == 0);
+    ok(135, $warn_count == 0);
     $warn_count = 0;
 
+    untie %hash1;
     unlink $Dfile;
 }
 
@@ -940,9 +954,10 @@ EOM
    use warnings ;
    use strict ;
    my (%h, $db) ;
+   my $Dfile = "xxy.db";
    unlink $Dfile;
 
-   ok(138, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) );
+   ok(136, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) );
 
    $db->filter_fetch_key   (sub { }) ;
    $db->filter_store_key   (sub { }) ;
@@ -952,10 +967,10 @@ EOM
    $_ = "original" ;
 
    $h{"fred"} = "joe" ;
-   ok(139, $h{"fred"} eq "joe");
+   ok(137, $h{"fred"} eq "joe");
 
    eval { grep { $h{$_} } (1, 2, 3) };
-   ok (140, ! $@);
+   ok (138, ! $@);
 
 
    # delete the filters
@@ -966,13 +981,248 @@ EOM
 
    $h{"fred"} = "joe" ;
 
-   ok(141, $h{"fred"} eq "joe");
+   ok(139, $h{"fred"} eq "joe");
 
-   ok(142, $db->FIRSTKEY() eq "fred") ;
+   ok(140, $db->FIRSTKEY() eq "fred") ;
    
    eval { grep { $h{$_} } (1, 2, 3) };
-   ok (143, ! $@);
+   ok (141, ! $@);
+
+   undef $db ;
+   untie %h;
+   unlink $Dfile;
+}
+
+{
+   # Check low-level API works with filter
+
+   use warnings ;
+   use strict ;
+   my (%h, $db) ;
+   my $Dfile = "xxy.db";
+   unlink $Dfile;
+
+   ok(142, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) );
+
+
+   $db->filter_fetch_key   (sub { $_ = unpack("i", $_) } );
+   $db->filter_store_key   (sub { $_ = pack("i", $_) } );
+   $db->filter_fetch_value (sub { $_ = unpack("i", $_) } );
+   $db->filter_store_value (sub { $_ = pack("i", $_) } );
+
+   $_ = 'fred';
+
+   my $key = 22 ;
+   my $value = 34 ;
+
+   $db->put($key, $value) ;
+   ok 143, $key == 22;
+   ok 144, $value == 34 ;
+   ok 145, $_ eq 'fred';
+   #print "k [$key][$value]\n" ;
+
+   my $val ;
+   $db->get($key, $val) ;
+   ok 146, $key == 22;
+   ok 147, $val == 34 ;
+   ok 148, $_ eq 'fred';
+
+   $key = 51 ;
+   $value = 454;
+   $h{$key} = $value ;
+   ok 149, $key == 51;
+   ok 150, $value == 454 ;
+   ok 151, $_ eq 'fred';
+
+   undef $db ;
+   untie %h;
+   unlink $Dfile;
+}
+
+
+{
+    # Regression Test for bug 30237
+    # Check that substr can be used in the key to db_put
+    # and that db_put does not trigger the warning
+    # 
+    #     Use of uninitialized value in subroutine entry
+
+
+    use warnings ;
+    use strict ;
+    my (%h, $db) ;
+    my $Dfile = "xxy.db";
+    unlink $Dfile;
+
+    ok(152, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) );
+
+    my $warned = '';
+    local $SIG{__WARN__} = sub {$warned = $_[0]} ;
+
+    # db-put with substr of key
+    my %remember = () ;
+    for my $ix ( 1 .. 2 )
+    {
+        my $key = $ix . "data" ;
+        my $value = "value$ix" ;
+        $remember{$key} = $value ;
+        $db->put(substr($key,0), $value) ;
+    }
+
+    ok 153, $warned eq '' 
+      or print "# Caught warning [$warned]\n" ;
+
+    # db-put with substr of value
+    $warned = '';
+    for my $ix ( 10 .. 12 )
+    {
+        my $key = $ix . "data" ;
+        my $value = "value$ix" ;
+        $remember{$key} = $value ;
+        $db->put($key, substr($value,0)) ;
+    }
+
+    ok 154, $warned eq '' 
+      or print "# Caught warning [$warned]\n" ;
+
+    # via the tied hash is not a problem, but check anyway
+    # substr of key
+    $warned = '';
+    for my $ix ( 30 .. 32 )
+    {
+        my $key = $ix . "data" ;
+        my $value = "value$ix" ;
+        $remember{$key} = $value ;
+        $h{substr($key,0)} = $value ;
+    }
+
+    ok 155, $warned eq '' 
+      or print "# Caught warning [$warned]\n" ;
+
+    # via the tied hash is not a problem, but check anyway
+    # substr of value
+    $warned = '';
+    for my $ix ( 40 .. 42 )
+    {
+        my $key = $ix . "data" ;
+        my $value = "value$ix" ;
+        $remember{$key} = $value ;
+        $h{$key} = substr($value,0) ;
+    }
+
+    ok 156, $warned eq '' 
+      or print "# Caught warning [$warned]\n" ;
+
+    my %bad = () ;
+    $key = '';
+    for ($status = $db->seq(substr($key,0), substr($value,0), R_FIRST ) ;
+         $status == 0 ;
+         $status = $db->seq(substr($key,0), substr($value,0), R_NEXT ) ) {
+
+        #print "# key [$key] value [$value]\n" ;
+        if (defined $remember{$key} && defined $value && 
+             $remember{$key} eq $value) {
+            delete $remember{$key} ;
+        }
+        else {
+            $bad{$key} = $value ;
+        }
+    }
+    
+    ok 157, keys %bad == 0 ;
+    ok 158, keys %remember == 0 ;
+
+    print "# missing -- $key=>$value\n" while ($key, $value) = each %remember;
+    print "# bad     -- $key=>$value\n" while ($key, $value) = each %bad;
+
+    # Make sure this fix does not break code to handle an undef key
+    # Berkeley DB undef key is broken between versions 2.3.16 and 3.1
+    my $value = 'fred';
+    $warned = '';
+    $db->put(undef, $value) ;
+    ok 159, $warned eq '' 
+      or print "# Caught warning [$warned]\n" ;
+    $warned = '';
+
+    my $no_NULL = ($DB_File::db_ver >= 2.003016 && $DB_File::db_ver < 3.001) ;
+    print "# db_ver $DB_File::db_ver\n";
+    $value = '' ;
+    $db->get(undef, $value) ;
+    ok 160, $no_NULL || $value eq 'fred' or print "# got [$value]\n" ;
+    ok 161, $warned eq '' 
+      or print "# Caught warning [$warned]\n" ;
+    $warned = '';
+
+    undef $db ;
+    untie %h;
+    unlink $Dfile;
+}
+
+{
+   # Check filter + substr
+
+   use warnings ;
+   use strict ;
+   my (%h, $db) ;
+   my $Dfile = "xxy.db";
+   unlink $Dfile;
+
+   ok(162, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) );
+
+
+   {
+       $db->filter_fetch_key   (sub { lc $_ } );
+       $db->filter_store_key   (sub { uc $_ } );
+       $db->filter_fetch_value (sub { lc $_ } );
+       $db->filter_store_value (sub { uc $_ } );
+   }
+
+   $_ = 'fred';
+
+    # db-put with substr of key
+    my %remember = () ;
+    my $status = 0 ;
+    for my $ix ( 1 .. 2 )
+    {
+        my $key = $ix . "data" ;
+        my $value = "value$ix" ;
+        $remember{$key} = $value ;
+        $status += $db->put(substr($key,0), substr($value,0)) ;
+    }
+
+    ok 163, $status == 0 or print "# Status $status\n" ;
+
+    if (1)
+    {
+       $db->filter_fetch_key   (undef);
+       $db->filter_store_key   (undef);
+       $db->filter_fetch_value (undef);
+       $db->filter_store_value (undef);
+    }
+
+    my %bad = () ;
+    my $key = '';
+    my $value = '';
+    for ($status = $db->seq($key, $value, R_FIRST ) ;
+         $status == 0 ;
+         $status = $db->seq($key, $value, R_NEXT ) ) {
+
+        #print "# key [$key] value [$value]\n" ;
+        if (defined $remember{$key} && defined $value && 
+             $remember{$key} eq $value) {
+            delete $remember{$key} ;
+        }
+        else {
+            $bad{$key} = $value ;
+        }
+    }
+    
+    ok 164, $_ eq 'fred';
+    ok 165, keys %bad == 0 ;
+    ok 166, keys %remember == 0 ;
 
+    print "# missing -- $key $value\n" while ($key, $value) = each %remember;
+    print "# bad     -- $key $value\n" while ($key, $value) = each %bad;
    undef $db ;
    untie %h;
    unlink $Dfile;
diff --git a/storage/bdb/perl/DB_File/t/db-recno.t b/storage/bdb/perl/DB_File/t/db-recno.t
index 5390b5493767bce6bc98560a32b12da82493a8e6..23bf0cdec5e8a90356312501f5f56bc3e1484f21 100644
--- a/storage/bdb/perl/DB_File/t/db-recno.t
+++ b/storage/bdb/perl/DB_File/t/db-recno.t
@@ -104,7 +104,7 @@ sub bad_one
 	print STDERR <<EOM ;
 #
 # Some older versions of Berkeley DB version 1 will fail db-recno
-# tests 61, 63 and 65.
+# tests 61, 63, 64 and 65.
 EOM
         if ($^O eq 'darwin'
 	    && $Config{db_version_major} == 1
@@ -112,7 +112,7 @@ EOM
 	    && $Config{db_version_patch} == 0) {
 	    print STDERR <<EOM ;
 #
-# For example Mac OS X 10.1.4 (or earlier) has such an old
+# For example Mac OS X 10.2 (or earlier) has such an old
 # version of Berkeley DB.
 EOM
 	}
@@ -151,7 +151,7 @@ BEGIN
 }
 
 my $splice_tests = 10 + 12 + 1; # ten regressions, plus the randoms
-my $total_tests = 158 ;
+my $total_tests = 181 ;
 $total_tests += $splice_tests if $FA ;
 print "1..$total_tests\n";   
 
@@ -1014,6 +1014,175 @@ EOM
    unlink $Dfile;
 }
 
+{
+   # Check low-level API works with filter
+
+   use warnings ;
+   use strict ;
+   my (@h, $db) ;
+   my $Dfile = "xxy.db";
+   unlink $Dfile;
+
+   ok(159, $db = tie(@h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_RECNO ) );
+
+
+   $db->filter_fetch_key   (sub { ++ $_ } );
+   $db->filter_store_key   (sub { -- $_ } );
+   $db->filter_fetch_value (sub { $_ = unpack("i", $_) } );
+   $db->filter_store_value (sub { $_ = pack("i", $_) } );
+
+   $_ = 'fred';
+
+   my $key = 22 ;
+   my $value = 34 ;
+
+   $db->put($key, $value) ;
+   ok 160, $key == 22;
+   ok 161, $value == 34 ;
+   ok 162, $_ eq 'fred';
+   #print "k [$key][$value]\n" ;
+
+   my $val ;
+   $db->get($key, $val) ;
+   ok 163, $key == 22;
+   ok 164, $val == 34 ;
+   ok 165, $_ eq 'fred';
+
+   $key = 51 ;
+   $value = 454;
+   $h[$key] = $value ;
+   ok 166, $key == 51;
+   ok 167, $value == 454 ;
+   ok 168, $_ eq 'fred';
+
+   undef $db ;
+   untie @h;
+   unlink $Dfile;
+}
+
+
+{
+    # Regression Test for bug 30237
+    # Check that substr can be used in the key to db_put
+    # and that db_put does not trigger the warning
+    # 
+    #     Use of uninitialized value in subroutine entry
+
+
+    use warnings ;
+    use strict ;
+    my (@h, $db) ;
+    my $status ;
+    my $Dfile = "xxy.db";
+    unlink $Dfile;
+
+    ok(169, $db = tie(@h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_RECNO) );
+
+    my $warned = '';
+    local $SIG{__WARN__} = sub {$warned = $_[0]} ;
+
+    # db-put with substr of key
+    my %remember = () ;
+    for my $ix ( 0 .. 2 )
+    {
+        my $key = $ix . "data" ;
+        my $value = "value$ix" ;
+        $remember{substr($key,0, 1)} = $value ;
+        $db->put(substr($key,0, 1), $value) ;
+    }
+
+    ok 170, $warned eq '' 
+      or print "# Caught warning [$warned]\n" ;
+
+    # db-put with substr of value
+    $warned = '';
+    for my $ix ( 3 .. 5 )
+    {
+        my $key = $ix . "data" ;
+        my $value = "value$ix" ;
+        $remember{$ix} = $value ;
+        $db->put($ix, substr($value,0)) ;
+    }
+
+    ok 171, $warned eq '' 
+      or print "# Caught warning [$warned]\n" ;
+
+    # via the tied array is not a problem, but check anyway
+    # substr of key
+    $warned = '';
+    for my $ix ( 6 .. 8 )
+    {
+        my $key = $ix . "data" ;
+        my $value = "value$ix" ;
+        $remember{substr($key,0,1)} = $value ;
+        $h[substr($key,0,1)] = $value ;
+    }
+
+    ok 172, $warned eq '' 
+      or print "# Caught warning [$warned]\n" ;
+
+    # via the tied array is not a problem, but check anyway
+    # substr of value
+    $warned = '';
+    for my $ix ( 9 .. 10 )
+    {
+        my $key = $ix . "data" ;
+        my $value = "value$ix" ;
+        $remember{$ix} = $value ;
+        $h[$ix] = substr($value,0) ;
+    }
+
+    ok 173, $warned eq '' 
+      or print "# Caught warning [$warned]\n" ;
+
+    my %bad = () ;
+    my $key = '';
+    for (my $status = $db->seq($key, $value, R_FIRST ) ;
+         $status == 0 ;
+         $status = $db->seq($key, $value, R_NEXT ) ) {
+
+        #print "# key [$key] value [$value]\n" ;
+        if (defined $remember{$key} && defined $value && 
+             $remember{$key} eq $value) {
+            delete $remember{$key} ;
+        }
+        else {
+            $bad{$key} = $value ;
+        }
+    }
+    
+    ok 174, keys %bad == 0 ;
+    ok 175, keys %remember == 0 ;
+
+    print "# missing -- $key $value\n" while ($key, $value) = each %remember;
+    print "# bad     -- $key $value\n" while ($key, $value) = each %bad;
+
+    # Make sure this fix does not break code to handle an undef key
+    my $value = 'fred';
+    $warned = '';
+    $status = $db->put(undef, $value) ;
+    ok 176, $status == 0
+      or print "# put failed - status $status\n";
+    ok 177, $warned eq '' 
+      or print "# Caught warning [$warned]\n" ;
+    $warned = '';
+
+    print "# db_ver $DB_File::db_ver\n";
+    $value = '' ;
+    $status = $db->get(undef, $value) ;
+    ok 178, $status == 0
+	or print "# get failed - status $status\n" ;
+    ok(179, $db->get(undef, $value) == 0) or print "# get failed\n" ;
+    ok 180, $value eq 'fred' or print "# got [$value]\n" ;
+    ok 181, $warned eq '' 
+      or print "# Caught warning [$warned]\n" ;
+    $warned = '';
+
+    undef $db ;
+    untie @h;
+    unlink $Dfile;
+}
+
 # Only test splice if this is a newish version of Perl
 exit unless $FA ;
 
@@ -1041,36 +1210,36 @@ exit unless $FA ;
     my $offset ;
     $a = '';
     splice(@a, $offset);
-    ok(159, $a =~ /^Use of uninitialized value /);
+    ok(182, $a =~ /^Use of uninitialized value /);
     $a = '';
     splice(@tied, $offset);
-    ok(160, $a =~ /^Use of uninitialized value in splice/);
+    ok(183, $a =~ /^Use of uninitialized value in splice/);
 
     no warnings 'uninitialized';
     $a = '';
     splice(@a, $offset);
-    ok(161, $a eq '');
+    ok(184, $a eq '');
     $a = '';
     splice(@tied, $offset);
-    ok(162, $a eq '');
+    ok(185, $a eq '');
 
     # uninitialized length
     use warnings;
     my $length ;
     $a = '';
     splice(@a, 0, $length);
-    ok(163, $a =~ /^Use of uninitialized value /);
+    ok(186, $a =~ /^Use of uninitialized value /);
     $a = '';
     splice(@tied, 0, $length);
-    ok(164, $a =~ /^Use of uninitialized value in splice/);
+    ok(187, $a =~ /^Use of uninitialized value in splice/);
 
     no warnings 'uninitialized';
     $a = '';
     splice(@a, 0, $length);
-    ok(165, $a eq '');
+    ok(188, $a eq '');
     $a = '';
     splice(@tied, 0, $length);
-    ok(166, $a eq '');
+    ok(189, $a eq '');
 
     # offset past end of array
     use warnings;
@@ -1079,17 +1248,17 @@ exit unless $FA ;
     my $splice_end_array = ($a =~ /^splice\(\) offset past end of array/);
     $a = '';
     splice(@tied, 3);
-    ok(167, !$splice_end_array || $a =~ /^splice\(\) offset past end of array/);
+    ok(190, !$splice_end_array || $a =~ /^splice\(\) offset past end of array/);
 
     no warnings 'misc';
     $a = '';
     splice(@a, 3);
-    ok(168, $a eq '');
+    ok(191, $a eq '');
     $a = '';
     splice(@tied, 3);
-    ok(169, $a eq '');
+    ok(192, $a eq '');
 
-    ok(170, safeUntie \@tied);
+    ok(193, safeUntie \@tied);
     unlink $Dfile;
 }
 
@@ -1150,9 +1319,9 @@ my @tests = ([ [ 'falsely', 'dinosaur', 'remedy', 'commotion',
 	       'void' ],
 	    );
 
-my $testnum = 171;
+my $testnum = 194;
 my $failed = 0;
-require POSIX; my $tmp = POSIX::tmpnam();
+my $tmp = "dbr$$";
 foreach my $test (@tests) {
     my $err = test_splice(@$test);
     if (defined $err) {
@@ -1267,6 +1436,8 @@ sub test_splice {
     foreach ($s_error, @s_warnings) {
 	chomp;
 	s/ at \S+ line \d+\.$//;
+	# only built-in splice identifies name of uninit value
+	s/(uninitialized value) \$\w+/$1/;
     }
 
     # Now do the same for DB_File's version of splice
@@ -1347,6 +1518,8 @@ sub test_splice {
 	   . Dumper(\@array) . ' vs ' . Dumper(\@h))
       if list_diff(\@array, \@h);
 
+    unlink $tmp;
+
     return undef; # success
 }
 
diff --git a/storage/bdb/perl/DB_File/typemap b/storage/bdb/perl/DB_File/typemap
index 8ad7b1282dcae9ff780079c69fd5cd783e7f7421..f159995080bfaea8c8b5ed945c6925ab6cbc8948 100644
--- a/storage/bdb/perl/DB_File/typemap
+++ b/storage/bdb/perl/DB_File/typemap
@@ -1,8 +1,8 @@
 # typemap for Perl 5 interface to Berkeley 
 #
 # written by Paul Marquess <Paul.Marquess@btinternet.com>
-# last modified 10th December 2000
-# version 1.74
+# last modified 20th June 2004
+# version 1.809
 #
 #################################### DB SECTION
 #
@@ -17,22 +17,25 @@ INPUT
 T_dbtkeydatum
 	DBM_ckFilter($arg, filter_store_key, \"filter_store_key\");
 	DBT_clear($var) ;
-	if (SvOK($arg)){
-	    if (db->type != DB_RECNO) {
-	        $var.data = SvPV($arg, PL_na);
-	        $var.size = (int)PL_na;
-	    }
-	    else {
-	        Value =  GetRecnoKey(aTHX_ db, SvIV($arg)) ; 
-	        $var.data = & Value; 
-	        $var.size = (int)sizeof(recno_t);
-	    }
+	SvGETMAGIC($arg) ;
+        if (db->type == DB_RECNO) {
+	    if (SvOK($arg))
+	        Value = GetRecnoKey(aTHX_ db, SvIV($arg)) ; 
+            else
+	        Value = 1 ;
+	    $var.data = & Value; 
+	    $var.size = (int)sizeof(recno_t);
+        }
+        else if (SvOK($arg)) {
+	    $var.data = SvPVbyte($arg, PL_na);
+	    $var.size = (int)PL_na;
 	}
 T_dbtdatum
 	DBM_ckFilter($arg, filter_store_value, \"filter_store_value\");
 	DBT_clear($var) ;
+	SvGETMAGIC($arg) ;
 	if (SvOK($arg)) {
-	    $var.data = SvPV($arg, PL_na);
+	    $var.data = SvPVbyte($arg, PL_na);
 	    $var.size = (int)PL_na;
 	}
 
diff --git a/storage/bdb/qam/qam.c b/storage/bdb/qam/qam.c
index b10f8743439acd166d2b8d8a40f318caacd02d34..3ae2f90d0886f4029e6c80528ad38d8872b5ae1e 100644
--- a/storage/bdb/qam/qam.c
+++ b/storage/bdb/qam/qam.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: qam.c,v 11.187 2004/10/18 20:21:13 ubell Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: qam.c,v 11.134 2002/08/13 20:46:08 ubell Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -23,6 +21,7 @@ static const char revid[] = "$Id: qam.c,v 11.134 2002/08/13 20:46:08 ubell Exp $
 #include "dbinc/btree.h"
 #include "dbinc/lock.h"
 #include "dbinc/log.h"
+#include "dbinc/mp.h"
 #include "dbinc/qam.h"
 
 static int __qam_bulk __P((DBC *, DBT *, u_int32_t));
@@ -52,7 +51,7 @@ __qam_position(dbc, recnop, mode, exactp)
 	DB *dbp;
 	QAMDATA  *qp;
 	db_pgno_t pg;
-	int ret;
+	int ret, t_ret;
 
 	dbp = dbc->dbp;
 	cp = (QUEUE_CURSOR *)dbc->internal;
@@ -67,11 +66,13 @@ __qam_position(dbc, recnop, mode, exactp)
 	*exactp = 0;
 	if ((ret = __qam_fget(dbp, &pg,
 	    mode == QAM_WRITE ? DB_MPOOL_CREATE : 0, &cp->page)) != 0) {
-		/* We did not fetch it, we can release the lock. */
-		(void)__LPUT(dbc, cp->lock);
 		if (mode != QAM_WRITE &&
 		    (ret == DB_PAGE_NOTFOUND || ret == ENOENT))
-			return (0);
+			ret = 0;
+
+		/* We did not fetch it, we can release the lock. */
+		if ((t_ret = __LPUT(dbc, cp->lock)) != 0 && ret == 0)
+			ret = t_ret;
 		return (ret);
 	}
 	cp->pgno = pg;
@@ -111,37 +112,36 @@ __qam_pitem(dbc, pagep, indx, recno, data)
 	db_recno_t recno;
 	DBT *data;
 {
+	DB_ENV *dbenv;
 	DB *dbp;
 	DBT olddata, pdata, *datap;
 	QAMDATA *qp;
 	QUEUE *t;
-	u_int32_t alloced;
 	u_int8_t *dest, *p;
-	int ret;
-
-	alloced = ret = 0;
+	int allocated, ret;
 
 	dbp = dbc->dbp;
+	dbenv = dbp->dbenv;
 	t = (QUEUE *)dbp->q_internal;
+	allocated = ret = 0;
 
 	if (data->size > t->re_len)
-		goto len_err;
-
+		return (__db_rec_toobig(dbenv, data->size, t->re_len));
 	qp = QAM_GET_RECORD(dbp, pagep, indx);
 
 	p = qp->data;
 	datap = data;
 	if (F_ISSET(data, DB_DBT_PARTIAL)) {
 		if (data->doff + data->dlen > t->re_len) {
-			alloced = data->dlen;
-			goto len_err;
-		}
-		if (data->size != data->dlen) {
-len_err:		__db_err(dbp->dbenv,
-			    "Length improper for fixed length record %lu",
-			    (u_long)(alloced ? alloced : data->size));
+			__db_err(dbenv,
+		"%s: data offset plus length larger than record size of %lu",
+			    "Record length error", (u_long)t->re_len);
 			return (EINVAL);
 		}
+
+		if (data->size != data->dlen)
+			return (__db_rec_repl(dbenv, data->size, data->dlen));
+
 		if (data->size == t->re_len)
 			goto no_partial;
 
@@ -161,10 +161,10 @@ len_err:		__db_err(dbp->dbenv,
 			datap = &pdata;
 			memset(datap, 0, sizeof(*datap));
 
-			if ((ret = __os_malloc(dbp->dbenv,
+			if ((ret = __os_malloc(dbenv,
 			    t->re_len, &datap->data)) != 0)
 				return (ret);
-			alloced = 1;
+			allocated = 1;
 			datap->size = t->re_len;
 
 			/*
@@ -204,8 +204,8 @@ no_partial:
 	if (!F_ISSET(data, DB_DBT_PARTIAL))
 		memset(p + datap->size,  t->re_pad, t->re_len - datap->size);
 
-err:	if (alloced)
-		__os_free(dbp->dbenv, datap->data);
+err:	if (allocated)
+		__os_free(dbenv, datap->data);
 
 	return (ret);
 }
@@ -249,7 +249,7 @@ __qam_c_put(dbc, key, data, flags, pgnop)
 	default:
 		/* The interface shouldn't let anything else through. */
 		DB_ASSERT(0);
-		return (__db_ferr(dbp->dbenv, "__qam_c_put", flags));
+		return (__db_ferr(dbp->dbenv, "DBC->put", 0));
 	}
 
 	/* Write lock the record. */
@@ -257,10 +257,9 @@ __qam_c_put(dbc, key, data, flags, pgnop)
 	    0, cp->recno, DB_LOCK_WRITE, DB_LOCK_RECORD, &lock)) != 0)
 		return (ret);
 
-	if ((ret = __qam_position(dbc,
-	    &cp->recno, QAM_WRITE, &exact)) != 0) {
+	if ((ret = __qam_position(dbc, &cp->recno, QAM_WRITE, &exact)) != 0) {
 		/* We could not get the page, we can release the record lock. */
-		__LPUT(dbc, lock);
+		(void)__LPUT(dbc, lock);
 		return (ret);
 	}
 
@@ -286,10 +285,10 @@ __qam_c_put(dbc, key, data, flags, pgnop)
 	 * Get the meta page first, we don't want to write lock it while
 	 * trying to pin it.
 	 */
-	if ((ret = mpf->get(mpf, &pg, 0, &meta)) != 0)
+	if ((ret = __memp_fget(mpf, &pg, 0, &meta)) != 0)
 		return (ret);
 	if ((ret = __db_lget(dbc, 0, pg,  DB_LOCK_WRITE, 0, &lock)) != 0) {
-		(void)mpf->put(mpf, meta, 0);
+		(void)__memp_fput(mpf, meta, 0);
 		return (ret);
 	}
 
@@ -345,7 +344,7 @@ __qam_c_put(dbc, key, data, flags, pgnop)
 	if (opcode & QAM_SETFIRST)
 		meta->first_recno = new_first;
 
-	if ((t_ret = mpf->put(
+	if ((t_ret = __memp_fput(
 	    mpf, meta, opcode != 0 ? DB_MPOOL_DIRTY : 0)) != 0 && ret == 0)
 		ret = t_ret;
 
@@ -386,11 +385,11 @@ __qam_append(dbc, key, data)
 	 * Get the meta page first, we don't want to write lock it while
 	 * trying to pin it.
 	 */
-	if ((ret = mpf->get(mpf, &pg, 0, &meta)) != 0)
+	if ((ret = __memp_fget(mpf, &pg, 0, &meta)) != 0)
 		return (ret);
 	/* Write lock the meta page. */
 	if ((ret = __db_lget(dbc, 0, pg,  DB_LOCK_WRITE, 0, &lock)) != 0) {
-		(void)mpf->put(mpf, meta, 0);
+		(void)__memp_fput(mpf, meta, 0);
 		return (ret);
 	}
 
@@ -403,8 +402,10 @@ __qam_append(dbc, key, data)
 		meta->cur_recno--;
 		if (meta->cur_recno == RECNO_OOB)
 			meta->cur_recno--;
-		(void)__LPUT(dbc, lock);
-		ret = EFBIG;
+		ret = __LPUT(dbc, lock);
+
+		if (ret == 0)
+			ret = EFBIG;
 		goto err;
 	}
 
@@ -412,18 +413,24 @@ __qam_append(dbc, key, data)
 		meta->first_recno = recno;
 
 	/* Lock the record and release meta page lock. */
-	if ((ret = __db_lget(dbc, LCK_COUPLE_ALWAYS,
-	    recno, DB_LOCK_WRITE, DB_LOCK_RECORD, &lock)) != 0) {
-		(void)__LPUT(dbc, lock);
-		goto err;
-	}
+	ret = __db_lget(dbc, LCK_COUPLE_ALWAYS,
+	    recno, DB_LOCK_WRITE, DB_LOCK_RECORD, &lock);
 
 	/*
 	 * The application may modify the data based on the selected record
-	 * number.
+	 * number.  We always want to call this even if we ultimately end
+	 * up aborting, because we are allocating a record number, regardless.
 	 */
 	if (dbc->dbp->db_append_recno != NULL &&
-	    (ret = dbc->dbp->db_append_recno(dbc->dbp, data, recno)) != 0) {
+	    (t_ret = dbc->dbp->db_append_recno(dbc->dbp, data, recno)) != 0 &&
+	    ret == 0)
+		ret = t_ret;
+
+	/*
+	 * Capture errors from either the lock couple or the call to
+	 * dbp->db_append_recno.
+	 */
+	if (ret != 0) {
 		(void)__LPUT(dbc, lock);
 		goto err;
 	}
@@ -456,8 +463,8 @@ __qam_append(dbc, key, data)
 	if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
 		ret = t_ret;
 
-	if ((t_ret
-	    = __qam_fput(dbp, pg, page, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+	if ((t_ret =
+	    __qam_fput(dbp, pg, page, DB_MPOOL_DIRTY)) != 0 && ret == 0)
 		ret = t_ret;
 
 	/* Return the record number to the user. */
@@ -472,19 +479,19 @@ __qam_append(dbc, key, data)
 	qp = (QUEUE *) dbp->q_internal;
 	if (qp->page_ext != 0 &&
 	    (recno % (qp->page_ext * qp->rec_page) == 0 ||
-	    recno == UINT32_T_MAX)) {
+	    recno == UINT32_MAX)) {
 		if ((ret = __db_lget(dbc,
 		    0, ((QUEUE *)dbp->q_internal)->q_meta,
 		    DB_LOCK_WRITE, 0, &lock)) != 0)
 			goto err;
 		if (!QAM_AFTER_CURRENT(meta, recno))
 			ret = __qam_fclose(dbp, pg);
-		(void)__LPUT(dbc, lock);
+		if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
+			ret = t_ret;
 	}
 
-err:
-	/* Release the meta page. */
-	if ((t_ret = mpf->put(mpf, meta, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+err:	/* Release the meta page. */
+	if ((t_ret = __memp_fput(mpf, meta, DB_MPOOL_DIRTY)) != 0 && ret == 0)
 		ret = t_ret;
 
 	return (ret);
@@ -500,7 +507,7 @@ __qam_c_del(dbc)
 {
 	DB *dbp;
 	DBT data;
-	DB_LOCK lock;
+	DB_LOCK lock, metalock;
 	DB_MPOOLFILE *mpf;
 	PAGE *pagep;
 	QAMDATA *qp;
@@ -519,11 +526,11 @@ __qam_c_del(dbc)
 	 * Get the meta page first, we don't want to write lock it while
 	 * trying to pin it.
 	 */
-	if ((ret = mpf->get(mpf, &pg, 0, &meta)) != 0)
+	if ((ret = __memp_fget(mpf, &pg, 0, &meta)) != 0)
 		return (ret);
 	/* Write lock the meta page. */
-	if ((ret = __db_lget(dbc, 0, pg,  DB_LOCK_READ, 0, &lock)) != 0) {
-		(void)mpf->put(mpf, meta, 0);
+	if ((ret = __db_lget(dbc, 0, pg,  DB_LOCK_READ, 0, &metalock)) != 0) {
+		(void)__memp_fput(mpf, meta, 0);
 		return (ret);
 	}
 
@@ -533,26 +540,24 @@ __qam_c_del(dbc)
 	first = meta->first_recno;
 
 	/* Don't hold the meta page long term. */
-	if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
+	if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0)
 		ret = t_ret;
 
 	if (ret != 0)
-		goto err1;
+		goto err;
 
 	if ((ret = __db_lget(dbc,
 	    0, cp->recno, DB_LOCK_WRITE, DB_LOCK_RECORD, &lock)) != 0)
-		goto err1;
-
+		goto err;
 	cp->lock_mode = DB_LOCK_WRITE;
+
 	/* Find the record ; delete only deletes exact matches. */
-	if ((ret = __qam_position(dbc,
-	    &cp->recno, QAM_WRITE, &exact)) != 0) {
-		cp->lock = lock;
-		goto err1;
-	}
+	if ((ret = __qam_position(dbc, &cp->recno, QAM_WRITE, &exact)) != 0)
+		goto err;
+
 	if (!exact) {
 		ret = DB_NOTFOUND;
-		goto err1;
+		goto err;
 	}
 
 	pagep = cp->page;
@@ -564,14 +569,14 @@ __qam_c_del(dbc)
 			if ((ret = __qam_del_log(dbp,
 			    dbc->txn, &LSN(pagep), 0, &LSN(pagep),
 			    pagep->pgno, cp->indx, cp->recno)) != 0)
-				goto err1;
+				goto err;
 		} else {
 			data.size = ((QUEUE *)dbp->q_internal)->re_len;
 			data.data = qp->data;
 			if ((ret = __qam_delext_log(dbp,
 			    dbc->txn, &LSN(pagep), 0, &LSN(pagep),
 			    pagep->pgno, cp->indx, cp->recno, &data)) != 0)
-				goto err1;
+				goto err;
 		}
 	}
 
@@ -580,15 +585,14 @@ __qam_c_del(dbc)
 	if (cp->recno == first) {
 		pg = ((QUEUE *)dbp->q_internal)->q_meta;
 		if ((ret =
-		    __db_lget(dbc, 0, pg,  DB_LOCK_WRITE, 0, &lock)) != 0)
-			goto err1;
+		    __db_lget(dbc, 0, pg,  DB_LOCK_WRITE, 0, &metalock)) != 0)
+			goto err;
 		ret = __qam_consume(dbc, meta, first);
-		if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
+		if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0)
 			ret = t_ret;
 	}
 
-err1:
-	if ((t_ret = mpf->put(mpf, meta, 0)) != 0 && ret == 0)
+err:	if ((t_ret = __memp_fput(mpf, meta, 0)) != 0 && ret == 0)
 		ret = t_ret;
 	if (cp->page != NULL && (t_ret = __qam_fput(dbp, cp->pgno,
 	    cp->page, ret == 0 ? DB_MPOOL_DIRTY : 0)) != 0 && ret == 0)
@@ -633,8 +637,8 @@ __qam_c_get(dbc, key, data, flags, pgnop)
 	db_pgno_t metapno;
 	db_recno_t first;
 	qam_position_mode mode;
-	int exact, is_first, locked, ret, t_ret, wait, with_delete;
-	int put_mode, meta_dirty, retrying;
+	int exact, inorder, is_first, locked, ret, t_ret, wait, with_delete;
+	int put_mode, retrying;
 
 	dbp = dbc->dbp;
 	dbenv = dbp->dbenv;
@@ -647,6 +651,8 @@ __qam_c_get(dbc, key, data, flags, pgnop)
 	with_delete = 0;
 	retrying = 0;
 	lock_mode = DB_LOCK_READ;
+	meta = NULL;
+	inorder = F_ISSET(dbp, DB_AM_INORDER);
 	put_mode = 0;
 	t_ret = 0;
 	*pgnop = 0;
@@ -663,9 +669,6 @@ __qam_c_get(dbc, key, data, flags, pgnop)
 		flags = DB_CONSUME;
 	}
 	if (flags == DB_CONSUME) {
-		if ((ret = __db_check_txn(dbp, dbc->txn, dbc->locker, 0)) != 0)
-			return (ret);
-
 		with_delete = 1;
 		flags = DB_FIRST;
 		lock_mode = DB_LOCK_WRITE;
@@ -676,7 +679,6 @@ __qam_c_get(dbc, key, data, flags, pgnop)
 	    flags == DB_SET || flags == DB_SET_RANGE ? key : NULL, NULL, flags);
 
 	/* Make lint and friends happy. */
-	meta_dirty = 0;
 	locked = 0;
 
 	is_first = 0;
@@ -689,7 +691,7 @@ __qam_c_get(dbc, key, data, flags, pgnop)
 	 * trying to pin it.  This is because someone my have it pinned
 	 * but not locked.
 	 */
-	if ((ret = mpf->get(mpf, &metapno, 0, &meta)) != 0)
+	if ((ret = __memp_fget(mpf, &metapno, 0, &meta)) != 0)
 		return (ret);
 	if ((ret = __db_lget(dbc, 0, metapno, lock_mode, 0, &metalock)) != 0)
 		goto err;
@@ -698,7 +700,8 @@ __qam_c_get(dbc, key, data, flags, pgnop)
 	first = 0;
 
 	/* Release any previous lock if not in a transaction. */
-	(void)__TLPUT(dbc, cp->lock);
+	if ((ret = __TLPUT(dbc, cp->lock)) != 0)
+		goto err;
 
 retry:	/* Update the record number. */
 	switch (flags) {
@@ -710,11 +713,95 @@ retry:	/* Update the record number. */
 		/* NOTREACHED */
 	case DB_NEXT:
 	case DB_NEXT_NODUP:
-		if (cp->recno != RECNO_OOB) {
+get_next:	if (cp->recno != RECNO_OOB) {
 			++cp->recno;
 			/* Wrap around, skipping zero. */
 			if (cp->recno == RECNO_OOB)
 				cp->recno++;
+			/*
+			 * Check to see if we are out of data.
+			 */
+			if (cp->recno == meta->cur_recno ||
+			    QAM_AFTER_CURRENT(meta, cp->recno)) {
+				pg = NULL;
+				if (!wait) {
+					ret = DB_NOTFOUND;
+					goto err;
+				}
+				flags = DB_FIRST;
+				/*
+				 * If first is not set, then we skipped
+				 * a locked record, go back and find it.
+				 * If we find a locked record again
+				 * wait for it.
+				 */
+				if (first == 0) {
+					retrying = 1;
+					goto retry;
+				}
+
+				if (CDB_LOCKING(dbenv)) {
+					/* Drop the metapage before we wait. */
+					if ((ret =
+					    __memp_fput(mpf, meta, 0)) != 0)
+						goto err;
+					meta = NULL;
+					if ((ret = __lock_get(
+					    dbenv, dbc->locker,
+					    DB_LOCK_SWITCH, &dbc->lock_dbt,
+					    DB_LOCK_WAIT, &dbc->mylock)) != 0)
+						goto err;
+
+					if ((ret = __memp_fget(mpf,
+					     &metapno, 0, &meta)) != 0)
+						goto err;
+					if ((ret = __lock_get(
+					    dbenv, dbc->locker,
+					    DB_LOCK_UPGRADE, &dbc->lock_dbt,
+					    DB_LOCK_WRITE, &dbc->mylock)) != 0)
+						goto err;
+					goto retry;
+				}
+				/*
+				 * Wait for someone to update the meta page.
+				 * This will probably mean there is something
+				 * in the queue.  We then go back up and
+				 * try again.
+				 */
+				if (locked == 0) {
+					if ((ret = __db_lget(dbc, 0, metapno,
+					     lock_mode, 0, &metalock)) != 0)
+						goto err;
+					locked = 1;
+					if (cp->recno != meta->cur_recno &&
+					    cp->recno != RECNO_OOB &&
+					    !QAM_AFTER_CURRENT(meta, cp->recno))
+						goto retry;
+				}
+				/* Drop the metapage before we wait. */
+				if ((ret = __memp_fput(mpf, meta, 0)) != 0)
+					goto err;
+				meta = NULL;
+				if ((ret = __db_lget(dbc,
+				     0, metapno, DB_LOCK_WAIT,
+				     DB_LOCK_SWITCH, &metalock)) != 0) {
+					if (ret == DB_LOCK_DEADLOCK)
+						ret = DB_LOCK_NOTGRANTED;
+					goto err;
+				}
+				if ((ret = __memp_fget(
+				     mpf, &metapno, 0, &meta)) != 0)
+					goto err;
+				if ((ret = __db_lget(dbc, 0,
+				     PGNO_INVALID, DB_LOCK_WRITE,
+				     DB_LOCK_UPGRADE, &metalock)) != 0) {
+					if (ret == DB_LOCK_DEADLOCK)
+						ret = DB_LOCK_NOTGRANTED;
+					goto err;
+				}
+				locked = 1;
+				goto retry;
+			}
 			break;
 		}
 		/* FALLTHROUGH */
@@ -729,8 +816,8 @@ retry:	/* Update the record number. */
 	case DB_PREV:
 	case DB_PREV_NODUP:
 		if (cp->recno != RECNO_OOB) {
-			if (QAM_BEFORE_FIRST(meta, cp->recno) ||
-			    cp->recno == meta->first_recno) {
+			if (cp->recno == meta->first_recno ||
+			   QAM_BEFORE_FIRST(meta, cp->recno)) {
 				ret = DB_NOTFOUND;
 				goto err;
 			}
@@ -756,74 +843,16 @@ retry:	/* Update the record number. */
 	case DB_GET_BOTH_RANGE:
 		if ((ret = __qam_getno(dbp, key, &cp->recno)) != 0)
 			goto err;
+		if (QAM_NOT_VALID(meta, cp->recno)) {
+			ret = DB_NOTFOUND;
+			goto err;
+		}
 		break;
 	default:
 		ret = __db_unknown_flag(dbenv, "__qam_c_get", flags);
 		goto err;
 	}
 
-	/*
-	 * Check to see if we are out of data.  Current points to
-	 * the first free slot.
-	 */
-	if (cp->recno == meta->cur_recno ||
-	    QAM_AFTER_CURRENT(meta, cp->recno)) {
-		ret = DB_NOTFOUND;
-		pg = NULL;
-		if (wait) {
-			flags = DB_FIRST;
-			/*
-			 * If first is not set, then we skipped a
-			 * locked record, go back and find it.
-			 * If we find a locked record again
-			 * wait for it.
-			 */
-			if (first == 0) {
-				retrying = 1;
-				goto retry;
-			}
-			if (CDB_LOCKING(dbenv)) {
-				if ((ret = dbenv->lock_get(
-				    dbenv, dbc->locker,
-				    DB_LOCK_SWITCH, &dbc->lock_dbt,
-				    DB_LOCK_WAIT, &dbc->mylock)) != 0)
-					goto err;
-				if ((ret = dbenv->lock_get(
-				    dbenv, dbc->locker,
-				    DB_LOCK_UPGRADE, &dbc->lock_dbt,
-				    DB_LOCK_WRITE, &dbc->mylock)) != 0)
-					goto err;
-				goto retry;
-			}
-			/*
-			 * Wait for someone to update the meta page.
-			 * This will probably mean there is something
-			 * in the queue.  We then go back up and
-			 * try again.
-			 */
-			if (locked == 0) {
-				if ((ret = __db_lget( dbc,
-				    0, metapno, lock_mode, 0, &metalock)) != 0)
-					goto err;
-				locked = 1;
-				if (cp->recno != RECNO_OOB &&
-				    !QAM_AFTER_CURRENT(meta, cp->recno))
-					goto retry;
-			}
-			if ((ret = __db_lget(dbc, 0, metapno,
-			    DB_LOCK_WAIT, DB_LOCK_SWITCH, &metalock)) != 0)
-				goto err;
-			if ((ret = dbenv->lock_get(dbenv, dbc->locker,
-			    DB_LOCK_UPGRADE, &dbc->lock_dbt, DB_LOCK_WRITE,
-			    &metalock)) != 0)
-				goto err;
-			locked = 1;
-			goto retry;
-		}
-
-		goto err;
-	}
-
 	/* Don't hold the meta page long term. */
 	if (locked) {
 		if ((ret = __LPUT(dbc, metalock)) != 0)
@@ -835,7 +864,7 @@ retry:	/* Update the record number. */
 	if ((ret = __db_lget(dbc, 0, cp->recno, lock_mode,
 	    (with_delete && !retrying) ?
 	    DB_LOCK_NOWAIT | DB_LOCK_RECORD : DB_LOCK_RECORD,
-	    &lock)) == DB_LOCK_NOTGRANTED && with_delete) {
+	    &lock)) == DB_LOCK_DEADLOCK && with_delete) {
 #ifdef QDEBUG
 		__db_logmsg(dbenv,
 		    dbc->txn, "Queue S", 0, "%x %d %d %d",
@@ -857,13 +886,15 @@ retry:	/* Update the record number. */
 	 * since the first/last may have moved while we slept.
 	 * We release our locks and try again.
 	 */
-	if ((!with_delete && is_first) || flags == DB_LAST) {
+	if (((inorder || !with_delete) && is_first) || flags == DB_LAST) {
+get_first:
 		if ((ret =
 		    __db_lget(dbc, 0, metapno, lock_mode, 0, &metalock)) != 0)
 			goto err;
 		if (cp->recno !=
 		    (is_first ? meta->first_recno : (meta->cur_recno - 1))) {
-			__LPUT(dbc, lock);
+			if ((ret = __LPUT(dbc, lock)) != 0)
+				goto err;
 			if (is_first)
 				flags = DB_FIRST;
 			locked = 1;
@@ -887,36 +918,44 @@ retry:	/* Update the record number. */
 	cp->lock_mode = lock_mode;
 
 	if (!exact) {
-		if (flags == DB_NEXT || flags == DB_NEXT_NODUP ||
-		    flags == DB_PREV || flags == DB_PREV_NODUP ||
-		    flags == DB_LAST) {
-			/* Release locks and try again. */
-			if (pg != NULL)
-				(void)__qam_fput(dbp, cp->pgno, pg, 0);
-			cp->page = pg = NULL;
-			(void)__LPUT(dbc, pglock);
-			(void)__LPUT(dbc, cp->lock);
-			if (flags == DB_LAST)
-				flags = DB_PREV;
+release_retry:	/* Release locks and retry, if possible. */
+		if (pg != NULL)
+			(void)__qam_fput(dbp, cp->pgno, pg, 0);
+		cp->page = pg = NULL;
+		if ((ret = __LPUT(dbc, pglock)) != 0)
+			goto err1;
+
+		switch (flags) {
+		case DB_GET_BOTH_RANGE:
+			flags = DB_SET_RANGE;
+			/* FALLTHROUGH */
+		case DB_NEXT:
+		case DB_NEXT_NODUP:
+		case DB_SET_RANGE:
 			if (!with_delete)
 				is_first = 0;
+			/* Peek at the meta page unlocked. */
+			if (QAM_BEFORE_FIRST(meta, cp->recno))
+				goto get_first;
+			/* FALLTHROUGH */
+		case DB_PREV:
+		case DB_PREV_NODUP:
+		case DB_LAST:
+			if (flags == DB_LAST)
+				flags = DB_PREV;
 			retrying = 0;
-			goto retry;
-		}
-		/* this is for the SET and SET_RANGE cases */
-		ret = DB_KEYEMPTY;
-		goto err1;
-	}
+			if ((ret = __LPUT(dbc, cp->lock)) != 0)
+				goto err1;
+			if (flags == DB_SET_RANGE)
+				goto get_next;
+			else
+				goto retry;
 
-	/* Return the key if the user didn't give us one. */
-	if (key != NULL) {
-		if (flags != DB_GET_BOTH && flags != DB_GET_BOTH_RANGE &&
-		    flags != DB_SET && flags != DB_SET_RANGE &&
-		    (ret = __db_retcopy(dbp->dbenv,
-		    key, &cp->recno, sizeof(cp->recno),
-		    &dbc->rkey->data, &dbc->rkey->ulen)) != 0)
+		default:
+			/* this is for the SET and GET_BOTH cases */
+			ret = DB_KEYEMPTY;
 			goto err1;
-		F_SET(key, DB_DBT_ISSET);
+		}
 	}
 
 	qp = QAM_GET_RECORD(dbp, pg, cp->indx);
@@ -929,18 +968,30 @@ retry:	/* Update the record number. */
 		tmp.data = qp->data;
 		tmp.size = t->re_len;
 		if ((ret = __bam_defcmp(dbp, data, &tmp)) != 0) {
+			if (flags == DB_GET_BOTH_RANGE)
+				goto release_retry;
 			ret = DB_NOTFOUND;
 			goto err1;
 		}
 	}
-	if (data != NULL &&
-	    !F_ISSET(dbc, DBC_MULTIPLE|DBC_MULTIPLE_KEY) &&
-	    (ret = __db_retcopy(dbp->dbenv, data,
-	    qp->data, t->re_len, &dbc->rdata->data, &dbc->rdata->ulen)) != 0)
-		goto err1;
 
-	if (data != NULL)
+	/* Return the key if the user didn't give us one. */
+	if (key != NULL) {
+		if (flags != DB_GET_BOTH && flags != DB_SET &&
+		    (ret = __db_retcopy(dbp->dbenv,
+		    key, &cp->recno, sizeof(cp->recno),
+		    &dbc->rkey->data, &dbc->rkey->ulen)) != 0)
+			goto err1;
+		F_SET(key, DB_DBT_ISSET);
+	}
+
+	if (data != NULL) {
+		if (!F_ISSET(dbc, DBC_MULTIPLE|DBC_MULTIPLE_KEY) &&
+		    (ret = __db_retcopy(dbp->dbenv, data, qp->data, t->re_len,
+		    &dbc->rdata->data, &dbc->rdata->ulen)) != 0)
+			goto err1;
 		F_SET(data, DB_DBT_ISSET);
+	}
 
 	/* Finally, if we are doing DB_CONSUME mark the record. */
 	if (with_delete) {
@@ -964,7 +1015,7 @@ retry:	/* Update the record number. */
 		 */
 		if (LIST_FIRST(&dbp->s_secondaries) != NULL) {
 			if ((ret = __db_c_idup(dbc,
-			    &dbcdup, DB_POSITIONI)) != 0)
+			    &dbcdup, DB_POSITION)) != 0)
 				goto err1;
 
 			if ((ret = __db_c_del_primary(dbcdup)) != 0) {
@@ -972,11 +1023,11 @@ retry:	/* Update the record number. */
 				 * The __db_c_del_primary return is more
 				 * interesting.
 				 */
-				(void)dbcdup->c_close(dbcdup);
+				(void)__db_c_close(dbcdup);
 				goto err1;
 			}
 
-			if ((ret = dbcdup->c_close(dbcdup)) != 0)
+			if ((ret = __db_c_close(dbcdup)) != 0)
 				goto err1;
 		}
 
@@ -1041,46 +1092,37 @@ retry:	/* Update the record number. */
 
 done:
 err1:	if (cp->page != NULL) {
-		t_ret = __qam_fput(dbp, cp->pgno, cp->page, put_mode);
-
-		if (!ret)
+		if ((t_ret = __qam_fput(
+		    dbp, cp->pgno, cp->page, put_mode)) != 0 && ret == 0)
 			ret = t_ret;
+
 		/* Doing record locking, release the page lock */
-		t_ret = __LPUT(dbc, pglock);
+		if ((t_ret = __LPUT(dbc, pglock)) != 0 && ret == 0)
+			ret = t_ret;
 		cp->page = NULL;
 	}
 
-err:	if (!ret)
-		ret = t_ret;
-	if (meta) {
-
-		/* release the meta page */
-		t_ret = mpf->put(mpf, meta, meta_dirty ? DB_MPOOL_DIRTY : 0);
-
-		if (!ret)
+err:	if (meta) {
+		/* Release the meta page. */
+		if ((t_ret = __memp_fput(mpf, meta, 0)) != 0 && ret == 0)
 			ret = t_ret;
 
 		/* Don't hold the meta page long term. */
 		if (locked)
-			t_ret = __LPUT(dbc, metalock);
+			if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0)
+				ret = t_ret;
 	}
 	DB_ASSERT(!LOCK_ISSET(metalock));
 
-	/*
-	 * There is no need to keep the record locked if we are
-	 * not in a transaction.
-	 */
-	if (t_ret == 0)
-		t_ret = __TLPUT(dbc, cp->lock);
-
-	return (ret ? ret : t_ret);
+	return ((ret == DB_LOCK_NOTGRANTED &&
+	     !F_ISSET(dbenv, DB_ENV_TIME_NOTGRANTED)) ?
+	     DB_LOCK_DEADLOCK : ret);
 }
 
 /*
  * __qam_consume -- try to reset the head of the queue.
  *
  */
-
 static int
 __qam_consume(dbc, meta, first)
 	DBC *dbc;
@@ -1094,14 +1136,14 @@ __qam_consume(dbc, meta, first)
 	db_indx_t save_indx;
 	db_pgno_t save_page;
 	db_recno_t current, save_recno;
-	u_int32_t rec_extent;
-	int exact, put_mode, ret, t_ret, wrapped;
+	u_int32_t put_mode, rec_extent;
+	int exact, ret, t_ret, wrapped;
 
 	dbp = dbc->dbp;
 	mpf = dbp->mpf;
 	cp = (QUEUE_CURSOR *)dbc->internal;
 	put_mode = DB_MPOOL_DIRTY;
-	ret = t_ret = 0;
+	ret = 0;
 
 	save_page = cp->pgno;
 	save_indx = cp->indx;
@@ -1116,7 +1158,7 @@ __qam_consume(dbc, meta, first)
 	if (first != cp->recno) {
 		ret = __db_lget(dbc, 0, first, DB_LOCK_READ,
 		    DB_LOCK_NOWAIT | DB_LOCK_RECORD, &lock);
-		if (ret == DB_LOCK_NOTGRANTED) {
+		if (ret == DB_LOCK_DEADLOCK) {
 			ret = 0;
 			goto done;
 		}
@@ -1157,7 +1199,7 @@ __qam_consume(dbc, meta, first)
 		if (cp->page != NULL && rec_extent != 0 &&
 		    ((exact = (first % rec_extent == 0)) ||
 		    first % meta->rec_page == 0 ||
-		    first == UINT32_T_MAX)) {
+		    first == UINT32_MAX)) {
 			if (exact == 1 && (ret = __db_lget(dbc,
 			    0, cp->pgno, DB_LOCK_WRITE, 0, &cp->lock)) != 0)
 				break;
@@ -1175,14 +1217,12 @@ __qam_consume(dbc, meta, first)
 
 			if (exact == 1) {
 				ret = __qam_fremove(dbp, cp->pgno);
-				t_ret = __LPUT(dbc, cp->lock);
+				if ((t_ret =
+				    __LPUT(dbc, cp->lock)) != 0 && ret == 0)
+					ret = t_ret;
 			}
 			if (ret != 0)
 				break;
-			if (t_ret != 0) {
-				ret = t_ret;
-				break;
-			}
 		} else if (cp->page != NULL && (ret =
 		    __qam_fput(dbp, cp->pgno, cp->page, put_mode)) != 0)
 			break;
@@ -1202,7 +1242,7 @@ __qam_consume(dbc, meta, first)
 
 		ret = __db_lget(dbc, 0, first, DB_LOCK_READ,
 		    DB_LOCK_NOWAIT | DB_LOCK_RECORD, &lock);
-		if (ret == DB_LOCK_NOTGRANTED) {
+		if (ret == DB_LOCK_DEADLOCK) {
 			ret = 0;
 			break;
 		}
@@ -1246,7 +1286,7 @@ __qam_consume(dbc, meta, first)
 			    cp->recno, PGNO_BASE_MD)) != 0)
 				goto done;
 		meta->first_recno = first;
-		(void)mpf->set(mpf, meta, DB_MPOOL_DIRTY);
+		(void)__memp_fset(mpf, meta, DB_MPOOL_DIRTY);
 	}
 
 done:
@@ -1260,13 +1300,14 @@ __qam_bulk(dbc, data, flags)
 	u_int32_t flags;
 {
 	DB *dbp;
-	DB_LOCK metalock;
+	DB_LOCK metalock, rlock;
 	DB_MPOOLFILE *mpf;
 	PAGE *pg;
 	QMETA *meta;
 	QAMDATA *qp;
 	QUEUE_CURSOR *cp;
 	db_indx_t indx;
+	db_lockmode_t lkmode;
 	db_pgno_t metapno;
 	qam_position_mode mode;
 	int32_t  *endp, *offp;
@@ -1279,8 +1320,11 @@ __qam_bulk(dbc, data, flags)
 	cp = (QUEUE_CURSOR *)dbc->internal;
 
 	mode = QAM_READ;
-	if (F_ISSET(dbc, DBC_RMW))
+	lkmode = DB_LOCK_READ;
+	if (F_ISSET(dbc, DBC_RMW)) {
 		mode = QAM_WRITE;
+		lkmode = DB_LOCK_WRITE;
+	}
 
 	pagesize = dbp->pgsize;
 	re_len = ((QUEUE *)dbp->q_internal)->re_len;
@@ -1292,7 +1336,7 @@ __qam_bulk(dbc, data, flags)
 
 	if ((ret = __db_lget(dbc, 0, metapno, DB_LOCK_READ, 0, &metalock)) != 0)
 		return (ret);
-	if ((ret = mpf->get(mpf, &metapno, 0, &meta)) != 0) {
+	if ((ret = __memp_fget(mpf, &metapno, 0, &meta)) != 0) {
 		/* We did not fetch it, we can release the lock. */
 		(void)__LPUT(dbc, metalock);
 		return (ret);
@@ -1309,8 +1353,14 @@ __qam_bulk(dbc, data, flags)
 	endp = (int32_t *) ((u_int8_t *)dbuf + data->ulen);
 	endp--;
 	offp = endp;
+	/* Save the lock on the current position of the cursor. */
+	rlock = cp->lock;
+	LOCK_INIT(cp->lock);
 
 next_pg:
+	/* Wrap around, skipping zero. */
+	if (cp->recno == RECNO_OOB)
+		cp->recno++;
 	if ((ret = __qam_position(dbc, &cp->recno, mode, &exact)) != 0)
 		goto done;
 
@@ -1327,10 +1377,10 @@ next_pg:
 		 */
 		valid = 0;
 
-		/* Wrap around, skipping zero. */
-		if (cp->recno == RECNO_OOB)
-			cp->recno++;
 		if (pg != NULL) {
+			if ((ret = __db_lget(dbc, LCK_COUPLE,
+			     cp->recno, lkmode, DB_LOCK_RECORD, &rlock)) != 0)
+				goto done;
 			qp = QAM_GET_RECORD(dbp, pg, indx);
 			if (F_ISSET(qp, QAM_VALID)) {
 				valid = 1;
@@ -1343,16 +1393,17 @@ next_pg:
 					if (space < size) {
 get_space:
 						if (offp == endp) {
-							data->size =
-							    ALIGN(size +
+							data->size = (u_int32_t)
+							    DB_ALIGN(size +
 							    pagesize,
 							    sizeof(u_int32_t));
-							ret = ENOMEM;
+							ret = DB_BUFFER_SMALL;
 							break;
 						}
 						if (indx != 0)
 							indx--;
 						cp->recno--;
+						space = 0;
 						break;
 					}
 					memcpy(dp,
@@ -1374,11 +1425,12 @@ get_space:
 			*offp-- = 0;
 		}
 		cp->recno++;
-	} while (++indx < recs && indx != RECNO_OOB
-	    && cp->recno != meta->cur_recno
-	    && !QAM_AFTER_CURRENT(meta, cp->recno));
+	} while (++indx < recs && cp->recno != RECNO_OOB &&
+	    cp->recno != meta->cur_recno &&
+	    !QAM_AFTER_CURRENT(meta, cp->recno));
 
-	if ((t_ret = __TLPUT(dbc, cp->lock)) != 0 && ret == 0)
+	/* Drop the page lock. */
+	if ((t_ret = __LPUT(dbc, cp->lock)) != 0 && ret == 0)
 		ret = t_ret;
 
 	if (cp->page != NULL) {
@@ -1388,25 +1440,32 @@ get_space:
 		cp->page = NULL;
 	}
 
-	if (ret == 0
-	    && (indx >= recs || indx == RECNO_OOB)
-	    && cp->recno != meta->cur_recno
-	    && !QAM_AFTER_CURRENT(meta, cp->recno))
+	if (ret == 0 && space > 0 &&
+	    (indx >= recs || cp->recno == RECNO_OOB) &&
+	    cp->recno != meta->cur_recno &&
+	    !QAM_AFTER_CURRENT(meta, cp->recno))
 		goto next_pg;
 
+	/*
+	 * Correct recno in two cases:
+	 * 1) If we just wrapped fetch must start at record 1 not a FIRST.
+	 * 2) We ran out of space exactly at the end of a page.
+	 */
+	if (cp->recno == RECNO_OOB || (space == 0 && indx == recs))
+		cp->recno--;
+
 	if (is_key == 1)
 		*offp = RECNO_OOB;
 	else
 		*offp = -1;
 
-done:
-	/* release the meta page */
-	t_ret = mpf->put(mpf, meta, 0);
-
-	if (!ret)
+done:	/* Release the meta page. */
+	if ((t_ret = __memp_fput(mpf, meta, 0)) != 0 && ret == 0)
+		ret = t_ret;
+	if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0)
 		ret = t_ret;
 
-	t_ret = __LPUT(dbc, metalock);
+	cp->lock = rlock;
 
 	return (ret);
 }
@@ -1422,6 +1481,7 @@ __qam_c_close(dbc, root_pgno, rmroot)
 	int *rmroot;
 {
 	QUEUE_CURSOR *cp;
+	int ret;
 
 	COMPQUIET(root_pgno, 0);
 	COMPQUIET(rmroot, NULL);
@@ -1429,9 +1489,9 @@ __qam_c_close(dbc, root_pgno, rmroot)
 	cp = (QUEUE_CURSOR *)dbc->internal;
 
 	/* Discard any locks not acquired inside of a transaction. */
-	(void)__TLPUT(dbc, cp->lock);
-	LOCK_INIT(cp->lock);
+	ret = __TLPUT(dbc, cp->lock);
 
+	LOCK_INIT(cp->lock);
 	cp->page = NULL;
 	cp->pgno = PGNO_INVALID;
 	cp->indx = 0;
@@ -1439,7 +1499,7 @@ __qam_c_close(dbc, root_pgno, rmroot)
 	cp->recno = RECNO_OOB;
 	cp->flags = 0;
 
-	return (0);
+	return (ret);
 }
 
 /*
@@ -1454,19 +1514,20 @@ __qam_c_dup(orig_dbc, new_dbc)
 	DBC *orig_dbc, *new_dbc;
 {
 	QUEUE_CURSOR *orig, *new;
+	int ret;
 
 	orig = (QUEUE_CURSOR *)orig_dbc->internal;
 	new = (QUEUE_CURSOR *)new_dbc->internal;
 
 	new->recno = orig->recno;
 
-	/* reget the long term lock if we are not in a xact */
-	if (orig_dbc->txn != NULL ||
-	    !STD_LOCKING(orig_dbc) || !LOCK_ISSET(orig->lock))
-		return (0);
+	/* Acquire the long term lock if we are not in a transaction. */
+	if (orig_dbc->txn == NULL && LOCK_ISSET(orig->lock))
+		if ((ret = __db_lget(new_dbc, 0, new->recno,
+		    new->lock_mode, DB_LOCK_RECORD, &new->lock)) != 0)
+			return (ret);
 
-	return (__db_lget(new_dbc,
-	    0, new->recno, new->lock_mode, DB_LOCK_RECORD, &new->lock));
+	return (0);
 }
 
 /*
@@ -1495,12 +1556,12 @@ __qam_c_init(dbc)
 
 	/* Initialize methods. */
 	dbc->c_close = __db_c_close;
-	dbc->c_count = __db_c_count;
-	dbc->c_del = __db_c_del;
-	dbc->c_dup = __db_c_dup;
-	dbc->c_get = dbc->c_real_get = __db_c_get;
-	dbc->c_pget = __db_c_pget;
-	dbc->c_put = __db_c_put;
+	dbc->c_count = __db_c_count_pp;
+	dbc->c_del = __db_c_del_pp;
+	dbc->c_dup = __db_c_dup_pp;
+	dbc->c_get = __db_c_get_pp;
+	dbc->c_pget = __db_c_pget_pp;
+	dbc->c_put = __db_c_put_pp;
 	dbc->c_am_bulk = __qam_bulk;
 	dbc->c_am_close = __qam_c_close;
 	dbc->c_am_del = __qam_c_del;
@@ -1547,54 +1608,49 @@ __qam_getno(dbp, key, rep)
  * __qam_truncate --
  *	Truncate a queue database
  *
- * PUBLIC: int __qam_truncate __P((DB *, DB_TXN *, u_int32_t *));
+ * PUBLIC: int __qam_truncate __P((DBC *, u_int32_t *));
  */
 int
-__qam_truncate(dbp, txn, countp)
-	DB *dbp;
-	DB_TXN *txn;
+__qam_truncate(dbc, countp)
+	DBC *dbc;
 	u_int32_t *countp;
 {
-	DBC *dbc;
+	DB *dbp;
 	DB_LOCK metalock;
 	DB_MPOOLFILE *mpf;
 	QMETA *meta;
 	db_pgno_t metapno;
-	int count, ret, t_ret;
-
-	mpf = dbp->mpf;
+	u_int32_t count;
+	int ret, t_ret;
 
-	/* Acquire a cursor. */
-	if ((ret = dbp->cursor(dbp, txn, &dbc, 0)) != 0)
-		return (ret);
+	dbp = dbc->dbp;
 
 	/* Walk the queue, counting rows. */
-	count = 0;
-	while ((ret = __qam_c_get(dbc, NULL, NULL, DB_CONSUME, &metapno)) == 0)
+	for (count = 0;
+	    (ret = __qam_c_get(dbc, NULL, NULL, DB_CONSUME, &metapno)) == 0;)
 		count++;
-
-	if (ret == DB_NOTFOUND)
-		ret = 0;
-
-	/* Discard the cursor. */
-	if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
-		ret = t_ret;
-
-	if (ret != 0)
+	if (ret != DB_NOTFOUND)
 		return (ret);
 
-	/* update the meta page */
-	/* get the meta page */
+	/* Update the meta page. */
 	metapno = ((QUEUE *)dbp->q_internal)->q_meta;
 	if ((ret =
 	    __db_lget(dbc, 0, metapno, DB_LOCK_WRITE, 0, &metalock)) != 0)
 		return (ret);
 
-	if ((ret = mpf->get(mpf, &metapno, 0, &meta)) != 0) {
+	mpf = dbp->mpf;
+	if ((ret = __memp_fget(mpf, &metapno, 0, &meta)) != 0) {
 		/* We did not fetch it, we can release the lock. */
 		(void)__LPUT(dbc, metalock);
 		return (ret);
 	}
+	/* Remove the last extent file. */
+	if (meta->cur_recno > 1 && ((QUEUE *)dbp->q_internal)->page_ext != 0) {
+		if ((ret = __qam_fremove(dbp,
+		     QAM_RECNO_PAGE(dbp, meta->cur_recno - 1))) != 0)
+			return (ret);
+	}
+
 	if (DBC_LOGGING(dbc)) {
 		ret = __qam_mvptr_log(dbp, dbc->txn, &meta->dbmeta.lsn, 0,
 		    QAM_SETCUR | QAM_SETFIRST | QAM_TRUNCATE, meta->first_recno,
@@ -1603,8 +1659,8 @@ __qam_truncate(dbp, txn, countp)
 	if (ret == 0)
 		meta->first_recno = meta->cur_recno = 1;
 
-	if ((t_ret =
-	    mpf->put(mpf, meta, ret == 0 ? DB_MPOOL_DIRTY: 0)) != 0 && ret == 0)
+	if ((t_ret = __memp_fput(mpf,
+	    meta, ret == 0 ? DB_MPOOL_DIRTY: 0)) != 0 && ret == 0)
 		ret = t_ret;
 	if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0)
 		ret = t_ret;
diff --git a/storage/bdb/qam/qam.src b/storage/bdb/qam/qam.src
index f8bf4da4dd05ed3356b68424f1797afc7f1fc197..71063f0b66f85ab99d8147b645d5b7f7feef9571 100644
--- a/storage/bdb/qam/qam.src
+++ b/storage/bdb/qam/qam.src
@@ -1,17 +1,15 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: qam.src,v 11.28 2002/04/17 19:03:13 krinsky Exp $
+ * $Id: qam.src,v 11.33 2004/06/17 17:35:22 bostic Exp $
  */
 
 PREFIX	__qam
 DBPRIVATE
 
-INCLUDE	#include "db_config.h"
-INCLUDE
 INCLUDE #ifndef NO_SYSTEM_INCLUDES
 INCLUDE #include <sys/types.h>
 INCLUDE
@@ -26,7 +24,6 @@ INCLUDE #include "dbinc/db_dispatch.h"
 INCLUDE #include "dbinc/db_am.h"
 INCLUDE #include "dbinc/log.h"
 INCLUDE #include "dbinc/qam.h"
-INCLUDE #include "dbinc/rep.h"
 INCLUDE #include "dbinc/txn.h"
 INCLUDE
 
@@ -37,7 +34,7 @@ INCLUDE
 BEGIN incfirst		84
 DB	fileid		int32_t		ld
 ARG	recno		db_recno_t	lu
-WRLOCK	meta_pgno	db_pgno_t	lu
+ARG	meta_pgno	db_pgno_t	lu
 END
 
 /*
@@ -52,7 +49,7 @@ ARG	new_first	db_recno_t	lu
 ARG	old_cur		db_recno_t	lu
 ARG	new_cur		db_recno_t	lu
 POINTER	metalsn		DB_LSN *	lu
-WRLOCK	meta_pgno	db_pgno_t	lu
+ARG	meta_pgno	db_pgno_t	lu
 END
 
 
@@ -64,7 +61,7 @@ END
 BEGIN del		79
 DB	fileid		int32_t		ld
 POINTER	lsn		DB_LSN *	lu
-WRLOCK	pgno		db_pgno_t	lu
+ARG	pgno		db_pgno_t	lu
 ARG	indx		u_int32_t	lu
 ARG	recno		db_recno_t	lu
 END
@@ -78,7 +75,7 @@ END
 BEGIN add		80
 DB	fileid		int32_t		ld
 POINTER	lsn		DB_LSN *	lu
-WRLOCK	pgno		db_pgno_t	lu
+ARG	pgno		db_pgno_t	lu
 ARG	indx		u_int32_t	lu
 ARG	recno		db_recno_t	lu
 DBT	data		DBT		s
diff --git a/storage/bdb/qam/qam_conv.c b/storage/bdb/qam/qam_conv.c
index d89fe06b0cf0271e6dd553c8d8986416ae602e40..c2b7d53a44eabb0b5e416cb597dd90293dd72889 100644
--- a/storage/bdb/qam/qam_conv.c
+++ b/storage/bdb/qam/qam_conv.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: qam_conv.c,v 11.17 2004/01/28 03:36:19 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: qam_conv.c,v 11.14 2002/08/06 06:17:02 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #endif
@@ -19,6 +17,7 @@ static const char revid[] = "$Id: qam_conv.c,v 11.14 2002/08/06 06:17:02 bostic
 #include "dbinc/db_page.h"
 #include "dbinc/db_swap.h"
 #include "dbinc/db_am.h"
+#include "dbinc/qam.h"
 
 /*
  * __qam_mswap --
diff --git a/storage/bdb/qam/qam_files.c b/storage/bdb/qam/qam_files.c
index f15a88d546d5e8e1124859b3d98c77125727fed8..d3f04060370128249143c103fe732ed57d940414 100644
--- a/storage/bdb/qam/qam_files.c
+++ b/storage/bdb/qam/qam_files.c
@@ -1,27 +1,34 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: qam_files.c,v 1.88 2004/10/21 14:54:42 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: qam_files.c,v 1.52 2002/08/26 17:52:18 margo Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #include <stdlib.h>
 
 #include <string.h>
+#include <ctype.h>
 #endif
 
 #include "db_int.h"
 #include "dbinc/db_page.h"
-#include "dbinc/qam.h"
+#include "dbinc/db_shash.h"
 #include "dbinc/db_am.h"
+#include "dbinc/log.h"
+#include "dbinc/fop.h"
+#include "dbinc/mp.h"
+#include "dbinc/qam.h"
+
+#define	QAM_EXNAME(Q, I, B, L)						\
+	snprintf((B), (L),						\
+	    QUEUE_EXTENT, (Q)->dir, PATH_SEPARATOR[0], (Q)->name, (I))
 
 /*
  * __qam_fprobe -- calculate and open extent
@@ -44,9 +51,9 @@ __qam_fprobe(dbp, pgno, addrp, mode, flags)
 	MPFARRAY *array;
 	QUEUE *qp;
 	u_int8_t fid[DB_FILE_ID_LEN];
-	u_int32_t extid, maxext, openflags;
+	u_int32_t extid, maxext, numext, offset, oldext, openflags;
 	char buf[MAXPATHLEN];
-	int numext, offset, oldext, ret;
+	int ftype, less, ret, t_ret;
 
 	dbenv = dbp->dbenv;
 	qp = (QUEUE *)dbp->q_internal;
@@ -55,8 +62,8 @@ __qam_fprobe(dbp, pgno, addrp, mode, flags)
 	if (qp->page_ext == 0) {
 		mpf = dbp->mpf;
 		return (mode == QAM_PROBE_GET ?
-		    mpf->get(mpf, &pgno, flags, addrp) :
-		    mpf->put(mpf, addrp, flags));
+		    __memp_fget(mpf, &pgno, flags, addrp) :
+		    __memp_fput(mpf, addrp, flags));
 	}
 
 	mpf = NULL;
@@ -67,25 +74,38 @@ __qam_fprobe(dbp, pgno, addrp, mode, flags)
 	 * in that file.
 	 */
 	MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
-	extid = (pgno - 1) / qp->page_ext;
+	extid = QAM_PAGE_EXTENT(dbp, pgno);
 
 	/* Array1 will always be in use if array2 is in use. */
 	array = &qp->array1;
 	if (array->n_extent == 0) {
 		/* Start with 4 extents */
-		oldext = 0;
 		array->n_extent = 4;
 		array->low_extent = extid;
-		offset = 0;
-		numext = 0;
+		numext = offset = oldext = 0;
+		less = 0;
 		goto alloc;
 	}
 
-	offset = extid - qp->array1.low_extent;
+	if (extid < array->low_extent) {
+		less = 1;
+		offset = array->low_extent - extid;
+	} else {
+		less = 0;
+		offset = extid - array->low_extent;
+	}
 	if (qp->array2.n_extent != 0 &&
-	    abs(offset) > abs(extid - qp->array2.low_extent)) {
+	    (extid >= qp->array2.low_extent ?
+	    offset > extid - qp->array2.low_extent :
+	    offset > qp->array2.low_extent - extid)) {
 		array = &qp->array2;
-		offset = extid - array->low_extent;
+		if (extid < array->low_extent) {
+			less = 1;
+			offset = array->low_extent - extid;
+		} else {
+			less = 0;
+			offset = extid - array->low_extent;
+		}
 	}
 
 	/*
@@ -93,31 +113,35 @@ __qam_fprobe(dbp, pgno, addrp, mode, flags)
 	 * extents in the array.  This is true by default if there are
 	 * no extents here yet.
 	 */
-	if (offset < 0 || (unsigned) offset >= array->n_extent) {
+	if (less == 1 || offset >= array->n_extent) {
 		oldext = array->n_extent;
-		numext = array->hi_extent - array->low_extent  + 1;
-		if (offset < 0 &&
-		    (unsigned) -offset + numext <= array->n_extent) {
+		numext = (array->hi_extent - array->low_extent) + 1;
+		if (less == 1 && offset + numext <= array->n_extent) {
 			/*
 			 * If we can fit this one into the existing array by
 			 * shifting the existing entries then we do not have
 			 * to allocate.
 			 */
-			memmove(&array->mpfarray[-offset],
+			memmove(&array->mpfarray[offset],
 			    array->mpfarray, numext
 			    * sizeof(array->mpfarray[0]));
-			memset(array->mpfarray, 0, -offset
+			memset(array->mpfarray, 0, offset
 			    * sizeof(array->mpfarray[0]));
 			offset = 0;
-		} else if ((u_int32_t)offset == array->n_extent &&
+		} else if (less == 0 && offset == array->n_extent &&
 		    mode != QAM_PROBE_MPF && array->mpfarray[0].pinref == 0) {
 			/*
 			 * If this is at the end of the array and the file at
-			 * the begining has a zero pin count we can close
+			 * the beginning has a zero pin count we can close
 			 * the bottom extent and put this one at the end.
+			 * TODO: If this process is "slow" then it might be
+			 * appending but miss one or more extents.
+			 * We could check to see if all the extents
+			 * are unpinned and close them in the else
+			 * clause below.
 			 */
 			mpf = array->mpfarray[0].mpf;
-			if (mpf != NULL && (ret = mpf->close(mpf, 0)) != 0)
+			if (mpf != NULL && (ret = __memp_fclose(mpf, 0)) != 0)
 				goto err;
 			memmove(&array->mpfarray[0], &array->mpfarray[1],
 			    (array->n_extent - 1) * sizeof(array->mpfarray[0]));
@@ -132,9 +156,9 @@ __qam_fprobe(dbp, pgno, addrp, mode, flags)
 			 * If it has then allocate the second array.
 			 * Otherwise just expand the one we are using.
 			 */
-			maxext = (u_int32_t) UINT32_T_MAX
+			maxext = (u_int32_t) UINT32_MAX
 			    / (qp->page_ext * qp->rec_page);
-			if ((u_int32_t) abs(offset) >= maxext/2) {
+			if (offset >= maxext/2) {
 				array = &qp->array2;
 				DB_ASSERT(array->n_extent == 0);
 				oldext = 0;
@@ -147,21 +171,19 @@ __qam_fprobe(dbp, pgno, addrp, mode, flags)
 				 * Increase the size to at least include
 				 * the new one and double it.
 				 */
-				array->n_extent += abs(offset);
+				array->n_extent += offset;
 				array->n_extent <<= 2;
 			}
-	alloc:
-			if ((ret = __os_realloc(dbenv,
+alloc:			if ((ret = __os_realloc(dbenv,
 			    array->n_extent * sizeof(struct __qmpf),
 			    &array->mpfarray)) != 0)
 				goto err;
 
-			if (offset < 0) {
+			if (less == 1) {
 				/*
 				 * Move the array up and put the new one
 				 * in the first slot.
 				 */
-				offset = -offset;
 				memmove(&array->mpfarray[offset],
 				    array->mpfarray,
 				    numext * sizeof(array->mpfarray[0]));
@@ -188,18 +210,19 @@ __qam_fprobe(dbp, pgno, addrp, mode, flags)
 
 	/* If the extent file is not yet open, open it. */
 	if (array->mpfarray[offset].mpf == NULL) {
-		snprintf(buf, sizeof(buf),
-		    QUEUE_EXTENT, qp->dir, PATH_SEPARATOR[0], qp->name, extid);
-		if ((ret = dbenv->memp_fcreate(
-		    dbenv, &array->mpfarray[offset].mpf, 0)) != 0)
+		QAM_EXNAME(qp, extid, buf, sizeof(buf));
+		if ((ret = __memp_fcreate(
+		    dbenv, &array->mpfarray[offset].mpf)) != 0)
 			goto err;
 		mpf = array->mpfarray[offset].mpf;
-		(void)mpf->set_lsn_offset(mpf, 0);
-		(void)mpf->set_pgcookie(mpf, &qp->pgcookie);
+		(void)__memp_set_lsn_offset(mpf, 0);
+		(void)__memp_set_pgcookie(mpf, &qp->pgcookie);
+		(void)__memp_get_ftype(dbp->mpf, &ftype);
+		(void)__memp_set_ftype(mpf, ftype);
 
 		/* Set up the fileid for this extent. */
 		__qam_exid(dbp, fid, extid);
-		(void)mpf->set_fileid(mpf, fid);
+		(void)__memp_set_fileid(mpf, fid);
 		openflags = DB_EXTENT;
 		if (LF_ISSET(DB_MPOOL_CREATE))
 			openflags |= DB_CREATE;
@@ -207,19 +230,29 @@ __qam_fprobe(dbp, pgno, addrp, mode, flags)
 			openflags |= DB_RDONLY;
 		if (F_ISSET(dbenv, DB_ENV_DIRECT_DB))
 			openflags |= DB_DIRECT;
-		if ((ret = mpf->open(
-		    mpf, buf, openflags, qp->mode, dbp->pgsize)) != 0) {
+		if ((ret = __memp_fopen(
+		    mpf, NULL, buf, openflags, qp->mode, dbp->pgsize)) != 0) {
 			array->mpfarray[offset].mpf = NULL;
-			(void)mpf->close(mpf, 0);
+			(void)__memp_fclose(mpf, 0);
 			goto err;
 		}
 	}
 
+	/*
+	 * We have found the right file.  Update its ref count
+	 * before dropping the dbp mutex so it does not go away.
+	 */
 	mpf = array->mpfarray[offset].mpf;
 	if (mode == QAM_PROBE_GET)
 		array->mpfarray[offset].pinref++;
+
+	/*
+	 * If we may create the page, then we are writing,
+	 * the file may nolonger be empty after this operation
+	 * so we clear the UNLINK flag.
+	 */
 	if (LF_ISSET(DB_MPOOL_CREATE))
-		mpf->set_unlink(mpf, 0);
+		(void)__memp_set_flags(mpf, DB_MPOOL_UNLINK, 0);
 
 err:
 	MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
@@ -231,11 +264,27 @@ err:
 		}
 		pgno--;
 		pgno %= qp->page_ext;
-		if (mode == QAM_PROBE_GET)
-			return (mpf->get(mpf, &pgno, flags, addrp));
-		ret = mpf->put(mpf, addrp, flags);
+		if (mode == QAM_PROBE_GET) {
+			if ((ret = __memp_fget(mpf, &pgno, flags, addrp)) == 0)
+				return (ret);
+		} else
+			ret = __memp_fput(mpf, addrp, flags);
+
 		MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
-		array->mpfarray[offset].pinref--;
+		/* Recalculate because we dropped the lock. */
+		offset = extid - array->low_extent;
+		DB_ASSERT(array->mpfarray[offset].pinref > 0);
+		if (--array->mpfarray[offset].pinref == 0 &&
+		    (mode == QAM_PROBE_GET || ret == 0)) {
+			/* Check to see if this file will be unlinked. */
+			(void)__memp_get_flags(mpf, &flags);
+			if (LF_ISSET(DB_MPOOL_UNLINK)) {
+				array->mpfarray[offset].mpf = NULL;
+				if ((t_ret =
+				    __memp_fclose(mpf, 0)) != 0 && ret == 0)
+					ret = t_ret;
+			}
+		}
 		MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
 	}
 	return (ret);
@@ -258,8 +307,8 @@ __qam_fclose(dbp, pgnoaddr)
 	DB_MPOOLFILE *mpf;
 	MPFARRAY *array;
 	QUEUE *qp;
-	u_int32_t extid;
-	int offset, ret;
+	u_int32_t extid, offset;
+	int ret;
 
 	ret = 0;
 	dbenv = dbp->dbenv;
@@ -267,13 +316,13 @@ __qam_fclose(dbp, pgnoaddr)
 
 	MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
 
-	extid = (pgnoaddr - 1) / qp->page_ext;
+	extid = QAM_PAGE_EXTENT(dbp, pgnoaddr);
 	array = &qp->array1;
 	if (array->low_extent > extid || array->hi_extent < extid)
 		array = &qp->array2;
 	offset = extid - array->low_extent;
 
-	DB_ASSERT(offset >= 0 && (unsigned) offset < array->n_extent);
+	DB_ASSERT(extid >= array->low_extent && offset < array->n_extent);
 
 	/* If other threads are still using this file, leave it. */
 	if (array->mpfarray[offset].pinref != 0)
@@ -281,7 +330,7 @@ __qam_fclose(dbp, pgnoaddr)
 
 	mpf = array->mpfarray[offset].mpf;
 	array->mpfarray[offset].mpf = NULL;
-	ret = mpf->close(mpf, 0);
+	ret = __memp_fclose(mpf, 0);
 
 done:
 	MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
@@ -306,11 +355,11 @@ __qam_fremove(dbp, pgnoaddr)
 	DB_MPOOLFILE *mpf;
 	MPFARRAY *array;
 	QUEUE *qp;
-	u_int32_t extid;
-#if CONFIG_TEST
+	u_int32_t extid, offset;
+#ifdef CONFIG_TEST
 	char buf[MAXPATHLEN], *real_name;
 #endif
-	int offset, ret;
+	int ret;
 
 	qp = (QUEUE *)dbp->q_internal;
 	dbenv = dbp->dbenv;
@@ -318,19 +367,18 @@ __qam_fremove(dbp, pgnoaddr)
 
 	MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
 
-	extid = (pgnoaddr - 1) / qp->page_ext;
+	extid = QAM_PAGE_EXTENT(dbp, pgnoaddr);
 	array = &qp->array1;
 	if (array->low_extent > extid || array->hi_extent < extid)
 		array = &qp->array2;
 	offset = extid - array->low_extent;
 
-	DB_ASSERT(offset >= 0 && (unsigned) offset < array->n_extent);
+	DB_ASSERT(extid >= array->low_extent && offset < array->n_extent);
 
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 	real_name = NULL;
 	/* Find the real name of the file. */
-	snprintf(buf, sizeof(buf),
-	    QUEUE_EXTENT, qp->dir, PATH_SEPARATOR[0], qp->name, extid);
+	QAM_EXNAME(qp, extid, buf, sizeof(buf));
 	if ((ret = __db_appname(dbenv,
 	    DB_APP_DATA, buf, 0, NULL, &real_name)) != 0)
 		goto err;
@@ -339,13 +387,16 @@ __qam_fremove(dbp, pgnoaddr)
 	 * The log must be flushed before the file is deleted.  We depend on
 	 * the log record of the last delete to recreate the file if we crash.
 	 */
-	if (LOGGING_ON(dbenv) && (ret = dbenv->log_flush(dbenv, NULL)) != 0)
+	if (LOGGING_ON(dbenv) && (ret = __log_flush(dbenv, NULL)) != 0)
 		goto err;
 
 	mpf = array->mpfarray[offset].mpf;
+	(void)__memp_set_flags(mpf, DB_MPOOL_UNLINK, 1);
+	/* Someone could be real slow, let them close it down. */
+	if (array->mpfarray[offset].pinref != 0)
+		goto err;
 	array->mpfarray[offset].mpf = NULL;
-	mpf->set_unlink(mpf, 1);
-	if ((ret = mpf->close(mpf, 0)) != 0)
+	if ((ret = __memp_fclose(mpf, 0)) != 0)
 		goto err;
 
 	/*
@@ -367,7 +418,7 @@ __qam_fremove(dbp, pgnoaddr)
 
 err:
 	MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 	if (real_name != NULL)
 		__os_free(dbenv, real_name);
 #endif
@@ -378,87 +429,31 @@ err:
  * __qam_sync --
  *	Flush the database cache.
  *
- * PUBLIC: int __qam_sync __P((DB *, u_int32_t));
+ * PUBLIC: int __qam_sync __P((DB *));
  */
 int
-__qam_sync(dbp, flags)
+__qam_sync(dbp)
 	DB *dbp;
-	u_int32_t flags;
 {
 	DB_ENV *dbenv;
 	DB_MPOOLFILE *mpf;
-	MPFARRAY *array;
-	QUEUE *qp;
-	QUEUE_FILELIST *filelist;
-	struct __qmpf *mpfp;
-	u_int32_t i;
-	int done, ret;
 
 	dbenv = dbp->dbenv;
 	mpf = dbp->mpf;
 
-	PANIC_CHECK(dbenv);
-	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->sync");
-
-	if ((ret = __db_syncchk(dbp, flags)) != 0)
-		return (ret);
-
-	/* Read-only trees never need to be sync'd. */
-	if (F_ISSET(dbp, DB_AM_RDONLY))
-		return (0);
-
-	/* If the tree was never backed by a database file, we're done. */
-	if (F_ISSET(dbp, DB_AM_INMEM))
-		return (0);
-
-	/* Flush any dirty pages from the cache to the backing file. */
-	if ((ret = mpf->sync(dbp->mpf)) != 0)
-		return (ret);
-
-	qp = (QUEUE *)dbp->q_internal;
-	if (qp->page_ext == 0)
-		return (0);
-
-	/* We do this for the side effect of opening all active extents. */
-	if ((ret = __qam_gen_filelist(dbp, &filelist)) != 0)
-		return (ret);
-
-	if (filelist == NULL)
-		return (0);
-
-	__os_free(dbp->dbenv, filelist);
-
-	done = 0;
-	qp = (QUEUE *)dbp->q_internal;
-	array = &qp->array1;
-
-	MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
-again:
-	mpfp = array->mpfarray;
-	for (i = array->low_extent; i <= array->hi_extent; i++, mpfp++)
-		if ((mpf = mpfp->mpf) != NULL) {
-			if ((ret = mpf->sync(mpf)) != 0)
-				goto err;
-			/*
-			 * If we are the only ones with this file open
-			 * then close it so it might be removed.
-			 */
-			if (mpfp->pinref == 0) {
-				mpfp->mpf = NULL;
-				if ((ret = mpf->close(mpf, 0)) != 0)
-					goto err;
-			}
-		}
-
-	if (done == 0 && qp->array2.n_extent != 0) {
-		array = &qp->array2;
-		done = 1;
-		goto again;
-	}
+	/*
+	 * We need to flush all extent files.  There is no easy way to find
+	 * all the extents for this queue which are currently open. For now
+	 * just flush the whole cache.  An alternative would be to have a
+	 * call into the cache layer that would flush all of the queue extent
+	 * files it has open (there's a flag when we open a queue extent file,
+	 * so the cache layer can identify them).
+	 */
 
-err:
-	MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
-	return (ret);
+	if (((QUEUE *)dbp->q_internal)->page_ext == 0)
+		return (__memp_fsync(mpf));
+	else
+		return (__memp_sync(dbenv, NULL));
 }
 
 /*
@@ -477,8 +472,8 @@ __qam_gen_filelist(dbp, filelistp)
 	DB_MPOOLFILE *mpf;
 	QUEUE *qp;
 	QMETA *meta;
-	db_pgno_t i, last, start;
-	db_recno_t current, first;
+	size_t extent_cnt;
+	db_recno_t i, current, first, stop, rec_extent;
 	QUEUE_FILELIST *fp;
 	int ret;
 
@@ -494,45 +489,66 @@ __qam_gen_filelist(dbp, filelistp)
 	if (qp->name == NULL)
 		return (0);
 
-	/* Find out the page number of the last page in the database. */
+	/* Find out the first and last record numbers in the database. */
 	i = PGNO_BASE_MD;
-	if ((ret = mpf->get(mpf, &i, 0, &meta)) != 0)
+	if ((ret = __memp_fget(mpf, &i, 0, &meta)) != 0)
 		return (ret);
 
 	current = meta->cur_recno;
 	first = meta->first_recno;
 
-	if ((ret = mpf->put(mpf, meta, 0)) != 0)
+	if ((ret = __memp_fput(mpf, meta, 0)) != 0)
 		return (ret);
 
-	last = QAM_RECNO_PAGE(dbp, current);
-	start = QAM_RECNO_PAGE(dbp, first);
-
-	/* Allocate the worst case plus 1 for null termination. */
-	if (last >= start)
-		ret = last - start + 2;
+	/*
+	 * Allocate the extent array.  Calculate the worst case number of
+	 * pages and convert that to a count of extents.   The count of
+	 * extents has 3 or 4 extra slots:
+	 *   roundoff at first (e.g., current record in extent);
+	 *   roundoff at current (e.g., first record in extent);
+	 *   NULL termination; and
+	 *   UINT32_MAX wraparound (the last extent can be small).
+	 */
+	rec_extent = qp->rec_page * qp->page_ext;
+	if (current >= first)
+		extent_cnt = (current - first) / rec_extent + 3;
 	else
-		ret = last + (QAM_RECNO_PAGE(dbp, UINT32_T_MAX) - start) + 1;
+		extent_cnt =
+		    (current + (UINT32_MAX - first)) / rec_extent + 4;
 	if ((ret = __os_calloc(dbenv,
-	    ret, sizeof(QUEUE_FILELIST), filelistp)) != 0)
+	    extent_cnt, sizeof(QUEUE_FILELIST), filelistp)) != 0)
 		return (ret);
 	fp = *filelistp;
-	i = start;
 
-again:	for (; i <= last; i += qp->page_ext) {
-		if ((ret =
-		    __qam_fprobe(dbp, i, &fp->mpf, QAM_PROBE_MPF, 0)) != 0) {
+again:
+	if (current >= first)
+		stop = current;
+	else
+		stop = UINT32_MAX;
+
+	/*
+	 * Make sure that first is at the same offset in the extent as stop.
+	 * This guarantees that the stop will be reached in the loop below,
+	 * even if it is the only record in its extent.  This calculation is
+	 * safe because first won't move out of its extent.
+	 */
+	first -= first % rec_extent;
+	first += stop % rec_extent;
+
+	for (i = first; i >= first && i <= stop; i += rec_extent) {
+		if ((ret = __qam_fprobe(dbp, QAM_RECNO_PAGE(dbp, i), &fp->mpf,
+		    QAM_PROBE_MPF, 0)) != 0) {
 			if (ret == ENOENT)
 				continue;
 			return (ret);
 		}
-		fp->id = (i - 1) / qp->page_ext;
+		fp->id = QAM_RECNO_EXTENT(dbp, i);
 		fp++;
+		DB_ASSERT((size_t)(fp - *filelistp) < extent_cnt);
 	}
 
-	if (last < start) {
-		i = 1;
-		start = 0;
+	if (current < first) {
+		first = 1;
 		goto again;
 	}
 
@@ -553,15 +569,16 @@ __qam_extent_names(dbenv, name, namelistp)
 	DB *dbp;
 	QUEUE *qp;
 	QUEUE_FILELIST *filelist, *fp;
-	char buf[MAXPATHLEN], *dir, **cp, *freep;
-	int cnt, len, ret;
+	size_t len;
+	int cnt, ret, t_ret;
+	char buf[MAXPATHLEN], **cp, *freep;
 
 	*namelistp = NULL;
 	filelist = NULL;
 	if ((ret = db_create(&dbp, dbenv, 0)) != 0)
 		return (ret);
-	if ((ret =
-	    __db_open(dbp, NULL, name, NULL, DB_QUEUE, DB_RDONLY, 0)) != 0)
+	if ((ret = __db_open(dbp,
+	    NULL, name, NULL, DB_QUEUE, DB_RDONLY, 0, PGNO_BASE_MD)) != 0)
 		return (ret);
 	qp = dbp->q_internal;
 	if (qp->page_ext == 0)
@@ -576,24 +593,20 @@ __qam_extent_names(dbenv, name, namelistp)
 	cnt = 0;
 	for (fp = filelist; fp->mpf != NULL; fp++)
 		cnt++;
-	dir = ((QUEUE *)dbp->q_internal)->dir;
-	name = ((QUEUE *)dbp->q_internal)->name;
 
 	/* QUEUE_EXTENT contains extra chars, but add 6 anyway for the int. */
-	len = (u_int32_t)(cnt * (sizeof(**namelistp)
-	    + strlen(QUEUE_EXTENT) + strlen(dir) + strlen(name) + 6));
+	len = (size_t)cnt * (sizeof(**namelistp) +
+	    strlen(QUEUE_EXTENT) + strlen(qp->dir) + strlen(qp->name) + 6);
 
-	if ((ret =
-	    __os_malloc(dbp->dbenv, len, namelistp)) != 0)
+	if ((ret = __os_malloc(dbp->dbenv, len, namelistp)) != 0)
 		goto done;
 	cp = *namelistp;
 	freep = (char *)(cp + cnt + 1);
 	for (fp = filelist; fp->mpf != NULL; fp++) {
-		snprintf(buf, sizeof(buf),
-		    QUEUE_EXTENT, dir, PATH_SEPARATOR[0], name, fp->id);
-		len = (u_int32_t)strlen(buf);
+		QAM_EXNAME(qp, fp->id, buf, sizeof(buf));
+		len = strlen(buf);
 		*cp++ = freep;
-		strcpy(freep, buf);
+		(void)strcpy(freep, buf);
 		freep += len + 1;
 	}
 	*cp = NULL;
@@ -601,7 +614,8 @@ __qam_extent_names(dbenv, name, namelistp)
 done:
 	if (filelist != NULL)
 		__os_free(dbp->dbenv, filelist);
-	(void)dbp->close(dbp, DB_NOSYNC);
+	if ((t_ret = __db_close(dbp, NULL, DB_NOSYNC)) != 0 && ret == 0)
+		ret = t_ret;
 
 	return (ret);
 }
@@ -640,3 +654,170 @@ __qam_exid(dbp, fidp, exnum)
 	for (p = (u_int8_t *)&exnum, i = sizeof(u_int32_t); i > 0; --i)
 		*fidp++ = *p++;
 }
+
+/*
+ * __qam_nameop --
+ *	Remove or rename  extent files associated with a particular file.
+ * This is to remove or rename (both in mpool and the file system) any
+ * extent files associated with the given dbp.
+ * This is either called from the QUEUE remove or rename methods or
+ * when undoing a transaction that created the database.
+ *
+ * PUBLIC: int __qam_nameop __P((DB *, DB_TXN *, const char *, qam_name_op));
+ */
+int __qam_nameop(dbp, txn, newname, op)
+	DB *dbp;
+	DB_TXN *txn;
+	const char *newname;
+	qam_name_op op;
+{
+	DB_ENV *dbenv;
+	QUEUE *qp;
+	size_t exlen, fulllen, len;
+	u_int8_t fid[DB_FILE_ID_LEN];
+	u_int32_t exid;
+	int cnt, i, ret, t_ret;
+	char buf[MAXPATHLEN], nbuf[MAXPATHLEN], sepsave;
+	char *endname, *endpath, *exname, *fullname, **names;
+	char *ndir, *namep, *new, *cp;
+
+	dbenv = dbp->dbenv;
+	qp = (QUEUE *)dbp->q_internal;
+	cnt = ret = t_ret = 0;
+	namep = exname = fullname = NULL;
+	names = NULL;
+
+	/* If this isn't a queue with extents, we're done. */
+	if (qp->page_ext == 0)
+		return (0);
+
+	/*
+	 * Generate the list of all queue extents for this file (from the
+	 * file system) and then cycle through removing them and evicting
+	 * from mpool.  We have two modes of operation here.  If we are
+	 * undoing log operations, then do not write log records and try
+	 * to keep going even if we encounter failures in nameop.  If we
+	 * are in mainline code, then return as soon as we have a problem.
+	 * Memory allocation errors (__db_appname, __os_malloc) are always
+	 * considered failure.
+	 *
+	 * Set buf to : dir/__dbq.NAME.0 and fullname to HOME/dir/__dbq.NAME.0
+	 * or, in the case of an absolute path: /dir/__dbq.NAME.0
+	 */
+	QAM_EXNAME(qp, 0, buf, sizeof(buf));
+	if ((ret =
+	    __db_appname(dbenv, DB_APP_DATA, buf, 0, NULL, &fullname)) != 0)
+		return (ret);
+
+	/* We should always have a path separator here. */
+	if ((endpath = __db_rpath(fullname)) == NULL) {
+		ret = EINVAL;
+		goto err;
+	}
+	sepsave = *endpath;
+	*endpath = '\0';
+
+	/*
+	 * Get the list of all names in the directory and restore the
+	 * path separator.
+	 */
+	if ((ret = __os_dirlist(dbenv, fullname, &names, &cnt)) != 0)
+		goto err;
+	*endpath = sepsave;
+
+	/* If there aren't any names, don't allocate any space. */
+	if (cnt == 0)
+		goto err;
+
+	/*
+	 * Now, make endpath reference the queue extent names upon which
+	 * we can match.  Then we set the end of the path to be the
+	 * beginning of the extent number, and we can compare the bytes
+	 * between endpath and endname (__dbq.NAME.).
+	 */
+	endpath++;
+	endname = strrchr(endpath, '.');
+	if (endname == NULL) {
+		ret = EINVAL;
+		goto err;
+	}
+	++endname;
+	*endname = '\0';
+	len = strlen(endpath);
+	fulllen = strlen(fullname);
+
+	/* Allocate space for a full extent name.  */
+	exlen = fulllen + 20;
+	if ((ret = __os_malloc(dbenv, exlen, &exname)) != 0)
+		goto err;
+
+	ndir = new = NULL;
+	if (newname != NULL) {
+		if ((ret = __os_strdup(dbenv, newname, &namep)) != 0)
+			goto err;
+		ndir = namep;
+		if ((new = __db_rpath(namep)) != NULL)
+			*new++ = '\0';
+		else {
+			new = namep;
+			ndir = PATH_DOT;
+		}
+	}
+	for (i = 0; i < cnt; i++) {
+		/* Check if this is a queue extent file. */
+		if (strncmp(names[i], endpath, len) != 0)
+			continue;
+		/* Make sure we have all numbers. foo.db vs. foo.db.0. */
+		for (cp = &names[i][len]; *cp != '\0'; cp++)
+			if (!isdigit(*cp))
+				break;
+		if (*cp != '\0')
+			continue;
+
+		/*
+		 * We have a queue extent file.  We need to generate its
+		 * name and its fileid.
+		 */
+		exid = (u_int32_t)strtoul(names[i] + len, NULL, 10);
+		__qam_exid(dbp, fid, exid);
+
+		switch (op) {
+		case QAM_NAME_DISCARD:
+			snprintf(exname, exlen,
+			     "%s%s", fullname, names[i] + len);
+			if ((t_ret = __memp_nameop(dbenv,
+			    fid, NULL, exname, NULL)) != 0 && ret == 0)
+				ret = t_ret;
+			break;
+
+		case QAM_NAME_RENAME:
+			snprintf(nbuf, sizeof(nbuf), QUEUE_EXTENT,
+			     ndir, PATH_SEPARATOR[0], new, exid);
+			QAM_EXNAME(qp, exid, buf, sizeof(buf));
+			if ((ret = __fop_rename(dbenv,
+			    txn, buf, nbuf, fid, DB_APP_DATA,
+			    F_ISSET(dbp, DB_AM_NOT_DURABLE) ?
+			    DB_LOG_NOT_DURABLE : 0)) != 0)
+				goto err;
+			break;
+
+		case QAM_NAME_REMOVE:
+			QAM_EXNAME(qp, exid, buf, sizeof(buf));
+			if ((ret = __fop_remove(dbenv, txn, fid, buf,
+			    DB_APP_DATA, F_ISSET(dbp, DB_AM_NOT_DURABLE) ?
+			    DB_LOG_NOT_DURABLE : 0)) != 0)
+				goto err;
+			break;
+		}
+	}
+
+err:	if (fullname != NULL)
+		__os_free(dbenv, fullname);
+	if (exname != NULL)
+		__os_free(dbenv, exname);
+	if (namep != NULL)
+		__os_free(dbenv, namep);
+	if (names != NULL)
+		__os_dirfree(dbenv, names, cnt);
+	return (ret);
+}
diff --git a/storage/bdb/qam/qam_method.c b/storage/bdb/qam/qam_method.c
index 5415fc5d00c2096f79023b5646c0a8d7b3ab3b40..e3526fa3c9e78d543dd196e7088057938e20f0ad 100644
--- a/storage/bdb/qam/qam_method.c
+++ b/storage/bdb/qam/qam_method.c
@@ -1,38 +1,31 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: qam_method.c,v 11.84 2004/10/14 18:09:32 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: qam_method.c,v 11.55 2002/08/26 17:52:19 margo Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
-
-#include <string.h>
 #endif
 
 #include "db_int.h"
 #include "dbinc/db_page.h"
 #include "dbinc/db_shash.h"
 #include "dbinc/db_am.h"
-#include "dbinc/fop.h"
 #include "dbinc/lock.h"
+#include "dbinc/mp.h"
 #include "dbinc/qam.h"
 #include "dbinc/txn.h"
 
+static int __qam_rr __P((DB *, DB_TXN *,
+	       const char *, const char *, const char *, qam_name_op));
 static int __qam_set_extentsize __P((DB *, u_int32_t));
 
-struct __qam_cookie {
-	DB_LSN lsn;
-	QUEUE_FILELIST *filelist;
-};
-
 /*
  * __qam_db_create --
  *	Queue specific initialization of the DB structure.
@@ -50,6 +43,7 @@ __qam_db_create(dbp)
 	if ((ret = __os_calloc(dbp->dbenv, 1, sizeof(QUEUE), &t)) != 0)
 		return (ret);
 	dbp->q_internal = t;
+	dbp->get_q_extentsize = __qam_get_extentsize;
 	dbp->set_q_extentsize = __qam_set_extentsize;
 
 	t->re_pad = ' ';
@@ -61,11 +55,12 @@ __qam_db_create(dbp)
  * __qam_db_close --
  *	Queue specific discard of the DB structure.
  *
- * PUBLIC: int __qam_db_close __P((DB *));
+ * PUBLIC: int __qam_db_close __P((DB *, u_int32_t));
  */
 int
-__qam_db_close(dbp)
+__qam_db_close(dbp, flags)
 	DB *dbp;
+	u_int32_t flags;
 {
 	DB_MPOOLFILE *mpf;
 	MPFARRAY *array;
@@ -86,8 +81,9 @@ again:
 		    i <= array->hi_extent; i++, mpfp++) {
 			mpf = mpfp->mpf;
 			mpfp->mpf = NULL;
-			if (mpf != NULL &&
-			    (t_ret = mpf->close(mpf, 0)) != 0 && ret == 0)
+			if (mpf != NULL && (t_ret = __memp_fclose(mpf,
+			    LF_ISSET(DB_AM_DISCARD) ? DB_MPOOL_DISCARD : 0))
+			    != 0 && ret == 0)
 				ret = t_ret;
 		}
 		__os_free(dbp->dbenv, array->mpfarray);
@@ -98,6 +94,11 @@ again:
 		goto again;
 	}
 
+	if (LF_ISSET(DB_AM_DISCARD) &&
+	     (t_ret = __qam_nameop(dbp, NULL,
+	     NULL, QAM_NAME_DISCARD)) != 0 && ret == 0)
+		ret = t_ret;
+
 	if (t->path != NULL)
 		__os_free(dbp->dbenv, t->path);
 	__os_free(dbp->dbenv, t);
@@ -106,12 +107,27 @@ again:
 	return (ret);
 }
 
+/*
+ * __qam_get_extentsize --
+ *	The DB->q_get_extentsize method.
+ *
+ * PUBLIC: int __qam_get_extentsize __P((DB *, u_int32_t *));
+ */
+int
+__qam_get_extentsize(dbp, q_extentsizep)
+	DB *dbp;
+	u_int32_t *q_extentsizep;
+{
+	*q_extentsizep = ((QUEUE*)dbp->q_internal)->page_ext;
+	return (0);
+}
+
 static int
 __qam_set_extentsize(dbp, extentsize)
 	DB *dbp;
 	u_int32_t extentsize;
 {
-	DB_ILLEGAL_AFTER_OPEN(dbp, "set_extentsize");
+	DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_extentsize");
 
 	if (extentsize < 1) {
 		__db_err(dbp->dbenv, "Extent size must be at least 1");
@@ -124,43 +140,82 @@ __qam_set_extentsize(dbp, extentsize)
 }
 
 /*
- * __db_prqueue --
- *	Print out a queue
+ * __queue_pageinfo -
+ *	Given a dbp, get first/last page information about a queue.
  *
- * PUBLIC: int __db_prqueue __P((DB *, FILE *, u_int32_t));
+ * PUBLIC: int __queue_pageinfo __P((DB *, db_pgno_t *, db_pgno_t *,
+ * PUBLIC:       int *, int, u_int32_t));
  */
 int
-__db_prqueue(dbp, fp, flags)
+__queue_pageinfo(dbp, firstp, lastp, emptyp, prpage, flags)
 	DB *dbp;
-	FILE *fp;
+	db_pgno_t *firstp, *lastp;
+	int *emptyp;
+	int prpage;
 	u_int32_t flags;
 {
 	DB_MPOOLFILE *mpf;
-	PAGE *h;
 	QMETA *meta;
-	db_pgno_t first, i, last, pg_ext, stop;
-	int ret, t_ret;
+	db_pgno_t first, i, last;
+	int empty, ret, t_ret;
 
 	mpf = dbp->mpf;
 
 	/* Find out the page number of the last page in the database. */
 	i = PGNO_BASE_MD;
-	if ((ret = mpf->get(mpf, &i, 0, &meta)) != 0)
+	if ((ret = __memp_fget(mpf, &i, 0, &meta)) != 0)
 		return (ret);
 
 	first = QAM_RECNO_PAGE(dbp, meta->first_recno);
-	last = QAM_RECNO_PAGE(dbp, meta->cur_recno);
+	last = QAM_RECNO_PAGE(
+	    dbp, meta->cur_recno == 1 ? 1 : meta->cur_recno - 1);
+
+	empty = meta->cur_recno == meta->first_recno;
+	if (firstp != NULL)
+		*firstp = first;
+	if (lastp != NULL)
+		*lastp = last;
+	if (emptyp != NULL)
+		*emptyp = empty;
+#ifdef HAVE_STATISTICS
+	if (prpage)
+		ret = __db_prpage(dbp, (PAGE *)meta, flags);
+#else
+	COMPQUIET(prpage, 0);
+	COMPQUIET(flags, 0);
+#endif
 
-	ret = __db_prpage(dbp, (PAGE *)meta, fp, flags);
-	if ((t_ret = mpf->put(mpf, meta, 0)) != 0 && ret == 0)
+	if ((t_ret = __memp_fput(mpf, meta, 0)) != 0 && ret == 0)
 		ret = t_ret;
 
-	if (ret != 0)
+	return (ret);
+}
+
+#ifdef HAVE_STATISTICS
+/*
+ * __db_prqueue --
+ *	Print out a queue
+ *
+ * PUBLIC: int __db_prqueue __P((DB *, u_int32_t));
+ */
+int
+__db_prqueue(dbp, flags)
+	DB *dbp;
+	u_int32_t flags;
+{
+	PAGE *h;
+	db_pgno_t first, i, last, pg_ext, stop;
+	int empty, ret;
+
+	if ((ret = __queue_pageinfo(dbp, &first, &last, &empty, 1, flags)) != 0)
+		return (ret);
+
+	if (empty || ret != 0)
 		return (ret);
 
 	i = first;
 	if (first > last)
-		stop = QAM_RECNO_PAGE(dbp, UINT32_T_MAX);
+		stop = QAM_RECNO_PAGE(dbp, UINT32_MAX);
 	else
 		stop = last;
 
@@ -175,12 +230,12 @@ begin:
 				return (ret);
 			}
 			if (ret == ENOENT || ret == DB_PAGE_NOTFOUND) {
-				i += pg_ext - ((i - 1) % pg_ext) - 1;
+				i += (pg_ext - ((i - 1) % pg_ext)) - 1;
 				continue;
 			}
 			return (ret);
 		}
-		(void)__db_prpage(dbp, h, fp, flags);
+		(void)__db_prpage(dbp, h, flags);
 		if ((ret = __qam_fput(dbp, i, h, 0)) != 0)
 			return (ret);
 	}
@@ -193,51 +248,68 @@ begin:
 	}
 	return (0);
 }
+#endif
 
 /*
- * __qam_remove
+ * __qam_remove --
  *	Remove method for a Queue.
  *
- * PUBLIC: int __qam_remove __P((DB *,
- * PUBLIC:     DB_TXN *, const char *, const char *, DB_LSN *));
+ * PUBLIC: int __qam_remove __P((DB *, DB_TXN *, const char *, const char *));
  */
 int
-__qam_remove(dbp, txn, name, subdb, lsnp)
+__qam_remove(dbp, txn, name, subdb)
 	DB *dbp;
 	DB_TXN *txn;
 	const char *name, *subdb;
-	DB_LSN *lsnp;
+{
+	return (__qam_rr(dbp, txn, name, subdb, NULL, QAM_NAME_REMOVE));
+}
+
+/*
+ * __qam_rename --
+ *	Rename method for a Queue.
+ *
+ * PUBLIC: int __qam_rename __P((DB *,
+ * PUBLIC:         DB_TXN *, const char *, const char *, const char *));
+ */
+int
+__qam_rename(dbp, txn, name, subdb, newname)
+	DB *dbp;
+	DB_TXN *txn;
+	const char *name, *subdb, *newname;
+{
+	return (__qam_rr(dbp, txn, name, subdb, newname, QAM_NAME_RENAME));
+}
+
+/*
+ * __qam_rr --
+ *	Remove/Rename method for a Queue.
+ */
+static int
+__qam_rr(dbp, txn, name, subdb, newname, op)
+	DB *dbp;
+	DB_TXN *txn;
+	const char *name, *subdb, *newname;
+	qam_name_op op;
 {
 	DB_ENV *dbenv;
 	DB *tmpdbp;
-	MPFARRAY *ap;
 	QUEUE *qp;
-	QUEUE_FILELIST *filelist, *fp;
-	int ret, needclose, t_ret;
-	char buf[MAXPATHLEN];
-	u_int8_t fid[DB_FILE_ID_LEN];
-
-	COMPQUIET(lsnp, NULL);
+	int ret, t_ret;
 
 	dbenv = dbp->dbenv;
 	ret = 0;
-	filelist = NULL;
-	needclose = 0;
 
 	PANIC_CHECK(dbenv);
 
-	/*
-	 * Subdatabases.
-	 */
 	if (subdb != NULL) {
 		__db_err(dbenv,
 		    "Queue does not support multiple databases per file");
-		ret = EINVAL;
-		goto err;
+		return (EINVAL);
 	}
 
 	/*
-	 * Since regular remove no longer opens the database, we may have
+	 * Since regular rename no longer opens the database, we may have
 	 * to do it here.
 	 */
 	if (F_ISSET(dbp, DB_AM_OPEN_CALLED))
@@ -245,169 +317,71 @@ __qam_remove(dbp, txn, name, subdb, lsnp)
 	else {
 		if ((ret = db_create(&tmpdbp, dbenv, 0)) != 0)
 			return (ret);
+
 		/*
 		 * We need to make sure we don't self-deadlock, so give
 		 * this dbp the same locker as the incoming one.
 		 */
 		tmpdbp->lid = dbp->lid;
-
-		/*
-		 * If this is a transactional dbp and the open fails, then
-		 * the transactional abort will close the dbp.  If it's not
-		 * a transactional open, then we always have to close it
-		 * even if the open fails.  Once the open has succeeded,
-		 * then we will always want to close it.
-		 */
-		if (txn == NULL)
-			needclose = 1;
-		if ((ret = tmpdbp->open(tmpdbp,
-		    txn, name, NULL, DB_QUEUE, 0, 0)) != 0)
+		if ((ret = __db_open(tmpdbp, txn,
+		    name, NULL, DB_QUEUE, DB_RDONLY, 0, PGNO_BASE_MD)) != 0)
 			goto err;
-		needclose = 1;
 	}
 
 	qp = (QUEUE *)tmpdbp->q_internal;
+	if (qp->page_ext != 0)
+		ret = __qam_nameop(tmpdbp, txn, newname, op);
 
-	if (qp->page_ext != 0 &&
-	    (ret = __qam_gen_filelist(tmpdbp, &filelist)) != 0)
-		goto err;
-
-	if (filelist == NULL)
-		goto err;
-
-	for (fp = filelist; fp->mpf != NULL; fp++) {
-		snprintf(buf, sizeof(buf),
-		    QUEUE_EXTENT, qp->dir, PATH_SEPARATOR[0], qp->name, fp->id);
-		if ((ret = fp->mpf->close(fp->mpf, DB_MPOOL_DISCARD)) != 0)
-			goto err;
-		if (qp->array2.n_extent == 0 || qp->array2.low_extent > fp->id)
-			ap = &qp->array1;
-		else
-			ap = &qp->array2;
-		ap->mpfarray[fp->id - ap->low_extent].mpf = NULL;
-
-		/* Take care of object reclamation. */
-		__qam_exid(tmpdbp, fid, fp->id);
-		if ((ret = __fop_remove(dbenv,
-		    txn, fid, buf, DB_APP_DATA)) != 0)
-			goto err;
-	}
-
-err:	if (filelist != NULL)
-		__os_free(dbenv, filelist);
-	if (needclose) {
-		/*
-		 * Since we copied the lid from the dbp, we'd better not
+	if (!F_ISSET(dbp, DB_AM_OPEN_CALLED)) {
+err:		/*
+		 * Since we copied the locker ID from the dbp, we'd better not
 		 * free it here.
 		 */
 		tmpdbp->lid = DB_LOCK_INVALIDID;
 
-		/* We need to remove the lockevent we associated with this. */
+		/* We need to remove the lock event we associated with this. */
 		if (txn != NULL)
 			__txn_remlock(dbenv,
 			    txn, &tmpdbp->handle_lock, DB_LOCK_INVALIDID);
 
 		if ((t_ret =
-		    __db_close_i(tmpdbp, txn, DB_NOSYNC)) != 0 && ret == 0)
+		    __db_close(tmpdbp, txn, DB_NOSYNC)) != 0 && ret == 0)
 			ret = t_ret;
 	}
-
 	return (ret);
 }
 
 /*
- * __qam_rename
- *	Rename method for Queue.
+ * __qam_map_flags --
+ *	Map queue-specific flags from public to the internal values.
  *
- * PUBLIC: int __qam_rename __P((DB *, DB_TXN *,
- * PUBLIC:     const char *, const char *, const char *));
+ * PUBLIC: void __qam_map_flags __P((DB *, u_int32_t *, u_int32_t *));
  */
-int
-__qam_rename(dbp, txn, filename, subdb, newname)
+void
+__qam_map_flags(dbp, inflagsp, outflagsp)
 	DB *dbp;
-	DB_TXN *txn;
-	const char *filename, *subdb, *newname;
+	u_int32_t *inflagsp, *outflagsp;
 {
-	DB_ENV *dbenv;
-	DB *tmpdbp;
-	MPFARRAY *ap;
-	QUEUE *qp;
-	QUEUE_FILELIST *fp, *filelist;
-	char buf[MAXPATHLEN], nbuf[MAXPATHLEN];
-	char *namep;
-	int ret, needclose, t_ret;
-	u_int8_t fid[DB_FILE_ID_LEN], *fidp;
-
-	dbenv = dbp->dbenv;
-	ret = 0;
-	filelist = NULL;
-	needclose = 0;
-
-	if (subdb != NULL) {
-		__db_err(dbenv,
-		    "Queue does not support multiple databases per file");
-		ret = EINVAL;
-		goto err;
-	}
-
-	/*
-	 * Since regular rename no longer opens the database, we may have
-	 * to do it here.
-	 */
-	if (F_ISSET(dbp, DB_AM_OPEN_CALLED))
-		tmpdbp = dbp;
-	else {
-		if ((ret = db_create(&tmpdbp, dbenv, 0)) != 0)
-			return (ret);
-		/* Copy the incoming locker so we don't self-deadlock. */
-		tmpdbp->lid = dbp->lid;
-		needclose = 1;
-		if ((ret = tmpdbp->open(tmpdbp, txn, filename, NULL,
-		    DB_QUEUE, 0, 0)) != 0)
-			goto err;
-	}
-
-	qp = (QUEUE *)tmpdbp->q_internal;
+	COMPQUIET(dbp, NULL);
 
-	if (qp->page_ext != 0 &&
-	    (ret = __qam_gen_filelist(tmpdbp, &filelist)) != 0)
-		goto err;
-	if ((namep = __db_rpath(newname)) != NULL)
-		newname = namep + 1;
-
-	fidp = fid;
-	for (fp = filelist; fp != NULL && fp->mpf != NULL; fp++) {
-		fp->mpf->get_fileid(fp->mpf, fidp);
-		if ((ret = fp->mpf->close(fp->mpf, DB_MPOOL_DISCARD)) != 0)
-			goto err;
-		if (qp->array2.n_extent == 0 || qp->array2.low_extent > fp->id)
-			ap = &qp->array1;
-		else
-			ap = &qp->array2;
-		ap->mpfarray[fp->id - ap->low_extent].mpf = NULL;
-		snprintf(buf, sizeof(buf),
-		    QUEUE_EXTENT, qp->dir, PATH_SEPARATOR[0], qp->name, fp->id);
-		snprintf(nbuf, sizeof(nbuf),
-		    QUEUE_EXTENT, qp->dir, PATH_SEPARATOR[0], newname, fp->id);
-		if ((ret = __fop_rename(dbenv,
-		    txn, buf, nbuf, fidp, DB_APP_DATA)) != 0)
-			goto err;
+	if (FLD_ISSET(*inflagsp, DB_INORDER)) {
+		FLD_SET(*outflagsp, DB_AM_INORDER);
+		FLD_CLR(*inflagsp, DB_INORDER);
 	}
+}
 
-err:	if (filelist != NULL)
-		__os_free(dbenv, filelist);
-	if (needclose) {
-		/* We copied this, so we mustn't free it. */
-		tmpdbp->lid = DB_LOCK_INVALIDID;
-
-		/* We need to remove the lockevent we associated with this. */
-		if (txn != NULL)
-		    __txn_remlock(dbenv,
-			txn, &tmpdbp->handle_lock, DB_LOCK_INVALIDID);
+/*
+ * __qam_set_flags --
+ *	Set queue-specific flags.
+ *
+ * PUBLIC: int __qam_set_flags __P((DB *, u_int32_t *flagsp));
+ */
+int
+__qam_set_flags(dbp, flagsp)
+	DB *dbp;
+	u_int32_t *flagsp;
+{
 
-		if ((t_ret =
-		    __db_close_i(tmpdbp, txn, DB_NOSYNC)) != 0 && ret == 0)
-			ret = t_ret;
-	}
-	return (ret);
+	__qam_map_flags(dbp, flagsp, &dbp->flags);
+	return (0);
 }
diff --git a/storage/bdb/qam/qam_open.c b/storage/bdb/qam/qam_open.c
index efe4dfc540e9dd02dc8caab9340b2eeb4712177e..595d74dac4a2f67d9e7f6bb8c494af7bb69b482e 100644
--- a/storage/bdb/qam/qam_open.c
+++ b/storage/bdb/qam/qam_open.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: qam_open.c,v 11.68 2004/02/27 12:38:31 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: qam_open.c,v 11.55 2002/09/04 19:06:45 margo Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -24,6 +22,7 @@ static const char revid[] = "$Id: qam_open.c,v 11.55 2002/09/04 19:06:45 margo E
 #include "dbinc/db_swap.h"
 #include "dbinc/db_am.h"
 #include "dbinc/lock.h"
+#include "dbinc/mp.h"
 #include "dbinc/qam.h"
 #include "dbinc/fop.h"
 
@@ -58,9 +57,13 @@ __qam_open(dbp, txn, name, base_pgno, mode, flags)
 	ret = 0;
 	qmeta = NULL;
 
+	if (name == NULL && t->page_ext != 0) {
+		__db_err(dbenv,
+	"Extent size may not be specified for in-memory queue database");
+		return (EINVAL);
+	}
+
 	/* Initialize the remaining fields/methods of the DB. */
-	dbp->stat = __qam_stat;
-	dbp->sync = __qam_sync;
 	dbp->db_am_remove = __qam_remove;
 	dbp->db_am_rename = __qam_rename;
 
@@ -70,9 +73,9 @@ __qam_open(dbp, txn, name, base_pgno, mode, flags)
 	 * In STD_LOCKING mode, we'll synchronize using the meta page
 	 * lock instead.
 	 */
-	if ((ret = dbp->cursor(dbp, txn, &dbc,
-	    LF_ISSET(DB_CREATE) && CDB_LOCKING(dbenv) ?  DB_WRITECURSOR : 0))
-	    != 0)
+	if ((ret = __db_cursor(dbp, txn, &dbc,
+	    LF_ISSET(DB_CREATE) && CDB_LOCKING(dbenv) ?
+	    DB_WRITECURSOR : 0)) != 0)
 		return (ret);
 
 	/*
@@ -83,8 +86,7 @@ __qam_open(dbp, txn, name, base_pgno, mode, flags)
 	if ((ret =
 	    __db_lget(dbc, 0, base_pgno, DB_LOCK_READ, 0, &metalock)) != 0)
 		goto err;
-	if ((ret =
-	    mpf->get(mpf, &base_pgno, 0, (PAGE **)&qmeta)) != 0)
+	if ((ret = __memp_fget(mpf, &base_pgno, 0, &qmeta)) != 0)
 		goto err;
 
 	/* If the magic number is incorrect, that's a fatal error. */
@@ -97,34 +99,12 @@ __qam_open(dbp, txn, name, base_pgno, mode, flags)
 	/* Setup information needed to open extents. */
 	t->page_ext = qmeta->page_ext;
 
-	if (t->page_ext != 0) {
-		t->pginfo.db_pagesize = dbp->pgsize;
-		t->pginfo.flags =
-		    F_ISSET(dbp, (DB_AM_CHKSUM | DB_AM_ENCRYPT | DB_AM_SWAP));
-		t->pginfo.type = dbp->type;
-		t->pgcookie.data = &t->pginfo;
-		t->pgcookie.size = sizeof(DB_PGINFO);
-
-		if ((ret = __os_strdup(dbp->dbenv, name,  &t->path)) != 0)
-			return (ret);
-		t->dir = t->path;
-		if ((t->name = __db_rpath(t->path)) == NULL) {
-			t->name = t->path;
-			t->dir = PATH_DOT;
-		} else
-			*t->name++ = '\0';
-
-		if (mode == 0)
-			mode = __db_omode("rwrw--");
-		t->mode = mode;
-	}
-
-	if (name == NULL && t->page_ext != 0) {
-		__db_err(dbenv,
-	"Extent size may not be specified for in-memory queue database");
-		return (EINVAL);
-	}
+	if (t->page_ext != 0 && (ret = __qam_set_ext_data(dbp, name)) != 0)
+		goto err;
 
+	if (mode == 0)
+		mode = __db_omode("rwrw--");
+	t->mode = mode;
 	t->re_pad = qmeta->re_pad;
 	t->re_len = qmeta->re_len;
 	t->rec_page = qmeta->rec_page;
@@ -132,18 +112,54 @@ __qam_open(dbp, txn, name, base_pgno, mode, flags)
 	t->q_meta = base_pgno;
 	t->q_root = base_pgno + 1;
 
-err:	if (qmeta != NULL && (t_ret = mpf->put(mpf, qmeta, 0)) != 0 && ret == 0)
+err:	if (qmeta != NULL &&
+	    (t_ret = __memp_fput(mpf, qmeta, 0)) != 0 && ret == 0)
 		ret = t_ret;
 
 	/* Don't hold the meta page long term. */
-	(void)__LPUT(dbc, metalock);
+	if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0)
+		ret = t_ret;
 
-	if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
+	if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
 		ret = t_ret;
 
 	return (ret);
 }
 
+/*
+ * __qam_set_ext_data --
+ *	Setup DBP data for opening queue extents.
+ *
+ * PUBLIC: int __qam_set_ext_data __P((DB*, const char *));
+ */
+int
+__qam_set_ext_data(dbp, name)
+	DB *dbp;
+	const char *name;
+{
+	QUEUE *t;
+	int ret;
+
+	t = dbp->q_internal;
+	t->pginfo.db_pagesize = dbp->pgsize;
+	t->pginfo.flags =
+	    F_ISSET(dbp, (DB_AM_CHKSUM | DB_AM_ENCRYPT | DB_AM_SWAP));
+	t->pginfo.type = dbp->type;
+	t->pgcookie.data = &t->pginfo;
+	t->pgcookie.size = sizeof(DB_PGINFO);
+
+	if ((ret = __os_strdup(dbp->dbenv, name,  &t->path)) != 0)
+		return (ret);
+	t->dir = t->path;
+	if ((t->name = __db_rpath(t->path)) == NULL) {
+		t->name = t->path;
+		t->dir = PATH_DOT;
+	} else
+		*t->name++ = '\0';
+
+	return (0);
+}
+
 /*
  * __qam_metachk --
  *
@@ -264,8 +280,8 @@ __qam_init_meta(dbp, meta)
  * This code appears more complex than it is because of the two cases (named
  * and unnamed).  The way to read the code is that for each page being created,
  * there are three parts: 1) a "get page" chunk (which either uses malloc'd
- * memory or calls mpf->get), 2) the initialization, and 3) the "put page"
- * chunk which either does a fop write or an mpf->put.
+ * memory or calls __memp_fget), 2) the initialization, and 3) the "put page"
+ * chunk which either does a fop write or an __memp_fput.
  *
  * PUBLIC: int __qam_new_file __P((DB *, DB_TXN *, DB_FH *, const char *));
  */
@@ -294,7 +310,7 @@ __qam_new_file(dbp, txn, fhp, name)
 
 	if (name == NULL) {
 		pgno = PGNO_BASE_MD;
-		ret = mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &meta);
+		ret = __memp_fget(mpf, &pgno, DB_MPOOL_CREATE, &meta);
 	} else {
 		ret = __os_calloc(dbp->dbenv, 1, dbp->pgsize, &buf);
 		meta = (QMETA *)buf;
@@ -306,7 +322,7 @@ __qam_new_file(dbp, txn, fhp, name)
 		goto err;
 
 	if (name == NULL)
-		ret = mpf->put(mpf, meta, DB_MPOOL_DIRTY);
+		ret = __memp_fput(mpf, meta, DB_MPOOL_DIRTY);
 	else {
 		pginfo.db_pagesize = dbp->pgsize;
 		pginfo.flags =
@@ -316,8 +332,9 @@ __qam_new_file(dbp, txn, fhp, name)
 		pdbt.size = sizeof(pginfo);
 		if ((ret = __db_pgout(dbenv, PGNO_BASE_MD, meta, &pdbt)) != 0)
 			goto err;
-		ret = __fop_write(dbenv,
-		    txn, name, DB_APP_DATA, fhp, 0, buf, dbp->pgsize, 1);
+		ret = __fop_write(dbenv, txn, name,
+		    DB_APP_DATA, fhp, dbp->pgsize, 0, 0, buf, dbp->pgsize, 1,
+		    F_ISSET(dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0);
 	}
 	if (ret != 0)
 		goto err;
@@ -326,6 +343,6 @@ __qam_new_file(dbp, txn, fhp, name)
 err:	if (name != NULL)
 		__os_free(dbenv, buf);
 	else if (meta != NULL)
-		(void)mpf->put(mpf, meta, 0);
+		(void)__memp_fput(mpf, meta, 0);
 	return (ret);
 }
diff --git a/storage/bdb/qam/qam_rec.c b/storage/bdb/qam/qam_rec.c
index 2c0f1227752cca0096fa5bddbf5441642ba6281e..e92141ddda3b681c2cbb4760226a44a9858ef65e 100644
--- a/storage/bdb/qam/qam_rec.c
+++ b/storage/bdb/qam/qam_rec.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: qam_rec.c,v 11.78 2004/05/11 14:04:51 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: qam_rec.c,v 11.69 2002/08/06 06:17:10 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -23,6 +21,7 @@ static const char revid[] = "$Id: qam_rec.c,v 11.69 2002/08/06 06:17:10 bostic E
 #include "dbinc/db_am.h"
 #include "dbinc/lock.h"
 #include "dbinc/log.h"
+#include "dbinc/mp.h"
 #include "dbinc/qam.h"
 
 /*
@@ -44,13 +43,14 @@ __qam_incfirst_recover(dbenv, dbtp, lsnp, op, info)
 	DB *file_dbp;
 	DBC *dbc;
 	DB_LOCK lock;
+	DB_LSN trunc_lsn;
 	DB_MPOOLFILE *mpf;
 	QMETA *meta;
 	QUEUE_CURSOR *cp;
 	db_pgno_t metapg;
-	int exact, modified, ret, rec_ext;
+	u_int32_t rec_ext;
+	int exact, modified, ret, t_ret;
 
-	COMPQUIET(info, NULL);
 	REC_PRINT(__qam_incfirst_print);
 	REC_INTRO(__qam_incfirst_read, 1);
 
@@ -59,9 +59,9 @@ __qam_incfirst_recover(dbenv, dbtp, lsnp, op, info)
 	if ((ret = __db_lget(dbc,
 	    LCK_ROLLBACK, metapg,  DB_LOCK_WRITE, 0, &lock)) != 0)
 		goto done;
-	if ((ret = mpf->get(mpf, &metapg, 0, &meta)) != 0) {
+	if ((ret = __memp_fget(mpf, &metapg, 0, &meta)) != 0) {
 		if (DB_REDO(op)) {
-			if ((ret = mpf->get(mpf,
+			if ((ret = __memp_fget(mpf,
 			    &metapg, DB_MPOOL_CREATE, &meta)) != 0) {
 				(void)__LPUT(dbc, lock);
 				goto out;
@@ -70,8 +70,7 @@ __qam_incfirst_recover(dbenv, dbtp, lsnp, op, info)
 			meta->dbmeta.type = P_QAMMETA;
 		} else {
 			*lsnp = argp->prev_lsn;
-			ret = 0;
-			(void)__LPUT(dbc, lock);
+			ret = __LPUT(dbc, lock);
 			goto out;
 		}
 	}
@@ -88,13 +87,22 @@ __qam_incfirst_recover(dbenv, dbtp, lsnp, op, info)
 			meta->first_recno = argp->recno;
 			modified = 1;
 		}
+
+		trunc_lsn = ((DB_TXNHEAD *)info)->trunc_lsn;
+		/* if we are truncating, update the LSN */
+		if (!IS_ZERO_LSN(trunc_lsn) &&
+		    log_compare(&LSN(meta), &trunc_lsn) > 0) {
+			LSN(meta) = trunc_lsn;
+			modified = 1;
+		}
 	} else {
 		if (log_compare(&LSN(meta), lsnp) < 0) {
 			LSN(meta) = *lsnp;
 			modified = 1;
 		}
-		rec_ext = 0;
-		if (meta->page_ext != 0)
+		if (meta->page_ext == 0)
+			rec_ext = 0;
+		else
 			rec_ext = meta->page_ext * meta->rec_page;
 		cp = (QUEUE_CURSOR *)dbc->internal;
 		if (meta->first_recno == RECNO_OOB)
@@ -104,8 +112,9 @@ __qam_incfirst_recover(dbenv, dbtp, lsnp, op, info)
 			if ((ret = __qam_position(dbc,
 			    &meta->first_recno, QAM_READ, &exact)) != 0)
 				goto err;
-			if (cp->page != NULL)
-				__qam_fput(file_dbp, cp->pgno, cp->page, 0);
+			if (cp->page != NULL && (ret =
+			    __qam_fput(file_dbp, cp->pgno, cp->page, 0)) != 0)
+				goto err;
 
 			if (exact == 1)
 				break;
@@ -121,17 +130,18 @@ __qam_incfirst_recover(dbenv, dbtp, lsnp, op, info)
 		}
 	}
 
-	if ((ret = mpf->put(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
-		goto err1;
-
-	(void)__LPUT(dbc, lock);
+	ret = __memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0);
+	if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
+		ret = t_ret;
+	if (ret != 0)
+		goto out;
 
 done:	*lsnp = argp->prev_lsn;
 	ret = 0;
 
 	if (0) {
-err:		(void)mpf->put(mpf, meta, 0);
-err1:		(void)__LPUT(dbc, lock);
+err:		(void)__memp_fput(mpf, meta, 0);
+		(void)__LPUT(dbc, lock);
 	}
 
 out:	REC_CLOSE;
@@ -155,13 +165,13 @@ __qam_mvptr_recover(dbenv, dbtp, lsnp, op, info)
 	__qam_mvptr_args *argp;
 	DB *file_dbp;
 	DBC *dbc;
+	DB_LSN trunc_lsn;
 	DB_LOCK lock;
 	DB_MPOOLFILE *mpf;
 	QMETA *meta;
 	db_pgno_t metapg;
 	int cmp_n, cmp_p, modified, ret;
 
-	COMPQUIET(info, NULL);
 	REC_PRINT(__qam_mvptr_print);
 	REC_INTRO(__qam_mvptr_read, 1);
 
@@ -170,9 +180,9 @@ __qam_mvptr_recover(dbenv, dbtp, lsnp, op, info)
 	if ((ret = __db_lget(dbc,
 	    LCK_ROLLBACK, metapg,  DB_LOCK_WRITE, 0, &lock)) != 0)
 		goto done;
-	if ((ret = mpf->get(mpf, &metapg, 0, &meta)) != 0) {
+	if ((ret = __memp_fget(mpf, &metapg, 0, &meta)) != 0) {
 		if (DB_REDO(op)) {
-			if ((ret = mpf->get(mpf,
+			if ((ret = __memp_fget(mpf,
 			    &metapg, DB_MPOOL_CREATE, &meta)) != 0) {
 				(void)__LPUT(dbc, lock);
 				goto out;
@@ -181,8 +191,7 @@ __qam_mvptr_recover(dbenv, dbtp, lsnp, op, info)
 			meta->dbmeta.type = P_QAMMETA;
 		} else {
 			*lsnp = argp->prev_lsn;
-			ret = 0;
-			(void)__LPUT(dbc, lock);
+			ret = __LPUT(dbc, lock);
 			goto out;
 		}
 	}
@@ -198,14 +207,21 @@ __qam_mvptr_recover(dbenv, dbtp, lsnp, op, info)
 	 * If we're undoing a truncate, we need to reset the pointers to
 	 * their state before the truncate.
 	 */
-	if (DB_UNDO(op) && (argp->opcode & QAM_TRUNCATE)) {
-		if (cmp_n == 0) {
+	if (DB_UNDO(op)) {
+		if ((argp->opcode & QAM_TRUNCATE) && cmp_n <= 0) {
 			meta->first_recno = argp->old_first;
 			meta->cur_recno = argp->old_cur;
+			LSN(meta) = argp->metalsn;
+			modified = 1;
+		}
+		/* If the page lsn is beyond the truncate point, move it back */
+		trunc_lsn = ((DB_TXNHEAD *)info)->trunc_lsn;
+		if (!IS_ZERO_LSN(trunc_lsn) &&
+		    log_compare(&trunc_lsn, &LSN(meta)) < 0) {
+			LSN(meta) = argp->metalsn;
 			modified = 1;
-			meta->dbmeta.lsn = argp->metalsn;
 		}
-	} else if (cmp_p == 0) {
+	} else if (op == DB_TXN_APPLY || cmp_p == 0) {
 		if (argp->opcode & QAM_SETFIRST)
 			meta->first_recno = argp->new_first;
 
@@ -216,10 +232,11 @@ __qam_mvptr_recover(dbenv, dbtp, lsnp, op, info)
 		meta->dbmeta.lsn = *lsnp;
 	}
 
-	if ((ret = mpf->put(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+	if ((ret = __memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
 		goto out;
 
-	(void)__LPUT(dbc, lock);
+	if ((ret = __LPUT(dbc, lock)) != 0)
+		goto out;
 
 done:	*lsnp = argp->prev_lsn;
 	ret = 0;
@@ -252,7 +269,7 @@ __qam_del_recover(dbenv, dbtp, lsnp, op, info)
 	QMETA *meta;
 	QPAGE *pagep;
 	db_pgno_t metapg;
-	int cmp_n, modified, ret;
+	int cmp_n, modified, ret, t_ret;
 
 	COMPQUIET(info, NULL);
 	REC_PRINT(__qam_del_print);
@@ -277,7 +294,7 @@ __qam_del_recover(dbenv, dbtp, lsnp, op, info)
 		if ((ret = __db_lget(dbc,
 		    LCK_ROLLBACK, metapg, DB_LOCK_WRITE, 0, &lock)) != 0)
 			goto err;
-		if ((ret = mpf->get(mpf, &metapg, 0, &meta)) != 0) {
+		if ((ret = __memp_fget(mpf, &metapg, 0, &meta)) != 0) {
 			(void)__LPUT(dbc, lock);
 			goto err;
 		}
@@ -287,10 +304,13 @@ __qam_del_recover(dbenv, dbtp, lsnp, op, info)
 		    meta->first_recno -
 		    argp->recno < argp->recno - meta->cur_recno))) {
 			meta->first_recno = argp->recno;
-			(void)mpf->put(mpf, meta, DB_MPOOL_DIRTY);
+			ret = __memp_fput(mpf, meta, DB_MPOOL_DIRTY);
 		} else
-			(void)mpf->put(mpf, meta, 0);
-		(void)__LPUT(dbc, lock);
+			ret = __memp_fput(mpf, meta, 0);
+		if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
+			ret = t_ret;
+		if (ret != 0)
+			goto err;
 
 		/* Need to undo delete - mark the record as present */
 		qp = QAM_GET_RECORD(file_dbp, pagep, argp->indx);
@@ -307,7 +327,7 @@ __qam_del_recover(dbenv, dbtp, lsnp, op, info)
 		if (op == DB_TXN_BACKWARD_ROLL && cmp_n <= 0)
 			LSN(pagep) = argp->lsn;
 		modified = 1;
-	} else if (cmp_n > 0 && DB_REDO(op)) {
+	} else if (op == DB_TXN_APPLY || (cmp_n > 0 && DB_REDO(op))) {
 		/* Need to redo delete - clear the valid bit */
 		qp = QAM_GET_RECORD(file_dbp, pagep, argp->indx);
 		F_CLR(qp, QAM_VALID);
@@ -351,7 +371,7 @@ __qam_delext_recover(dbenv, dbtp, lsnp, op, info)
 	QMETA *meta;
 	QPAGE *pagep;
 	db_pgno_t metapg;
-	int cmp_n, modified, ret;
+	int cmp_n, modified, ret, t_ret;
 
 	COMPQUIET(info, NULL);
 	REC_PRINT(__qam_delext_print);
@@ -386,7 +406,7 @@ __qam_delext_recover(dbenv, dbtp, lsnp, op, info)
 		if ((ret = __db_lget(dbc,
 		    LCK_ROLLBACK, metapg, DB_LOCK_WRITE, 0, &lock)) != 0)
 			goto err;
-		if ((ret = mpf->get(mpf, &metapg, 0, &meta)) != 0) {
+		if ((ret = __memp_fget(mpf, &metapg, 0, &meta)) != 0) {
 			(void)__LPUT(dbc, lock);
 			goto err;
 		}
@@ -396,10 +416,13 @@ __qam_delext_recover(dbenv, dbtp, lsnp, op, info)
 		    meta->first_recno -
 		    argp->recno < argp->recno - meta->cur_recno))) {
 			meta->first_recno = argp->recno;
-			(void)mpf->put(mpf, meta, DB_MPOOL_DIRTY);
+			ret = __memp_fput(mpf, meta, DB_MPOOL_DIRTY);
 		} else
-			(void)mpf->put(mpf, meta, 0);
-		(void)__LPUT(dbc, lock);
+			ret = __memp_fput(mpf, meta, 0);
+		if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
+			ret = t_ret;
+		if (ret != 0)
+			goto err;
 
 		if ((ret = __qam_pitem(dbc, pagep,
 		    argp->indx, argp->recno, &argp->data)) != 0)
@@ -416,7 +439,7 @@ __qam_delext_recover(dbenv, dbtp, lsnp, op, info)
 		if (op == DB_TXN_BACKWARD_ROLL && cmp_n <= 0)
 			LSN(pagep) = argp->lsn;
 		modified = 1;
-	} else if (cmp_n > 0 && DB_REDO(op)) {
+	} else if (op == DB_TXN_APPLY || (cmp_n > 0 && DB_REDO(op))) {
 		/* Need to redo delete - clear the valid bit */
 		qp = QAM_GET_RECORD(file_dbp, pagep, argp->indx);
 		F_CLR(qp, QAM_VALID);
@@ -491,7 +514,7 @@ __qam_add_recover(dbenv, dbtp, lsnp, op, info)
 	if (DB_REDO(op)) {
 		/* Fix meta-data page. */
 		metapg = ((QUEUE *)file_dbp->q_internal)->q_meta;
-		if ((ret = mpf->get(mpf, &metapg, 0, &meta)) != 0)
+		if ((ret = __memp_fget(mpf, &metapg, 0, &meta)) != 0)
 			goto err;
 		meta_dirty = 0;
 		if (QAM_BEFORE_FIRST(meta, argp->recno)) {
@@ -503,20 +526,18 @@ __qam_add_recover(dbenv, dbtp, lsnp, op, info)
 			meta->cur_recno = argp->recno + 1;
 			meta_dirty = 1;
 		}
-		if ((ret =
-		    mpf->put(mpf, meta, meta_dirty? DB_MPOOL_DIRTY : 0)) != 0)
+		if ((ret = __memp_fput(mpf,
+		    meta, meta_dirty? DB_MPOOL_DIRTY : 0)) != 0)
 			goto err;
 
 		/* Now update the actual page if necessary. */
-		if (cmp_n > 0) {
+		if (op == DB_TXN_APPLY || cmp_n > 0) {
 			/* Need to redo add - put the record on page */
 			if ((ret = __qam_pitem(dbc,
 			    pagep, argp->indx, argp->recno, &argp->data)) != 0)
 				goto err;
 			LSN(pagep) = *lsnp;
 			modified = 1;
-			/* Make sure pointers include this record. */
-			metapg = ((QUEUE *)file_dbp->q_internal)->q_meta;
 		}
 	} else if (DB_UNDO(op)) {
 		/*
diff --git a/storage/bdb/qam/qam_stat.c b/storage/bdb/qam/qam_stat.c
index 57c67da4292980988da1efc3faf9ff0f2a673038..c5264bd019fa052ec0d8045bdf341f2c94652fd5 100644
--- a/storage/bdb/qam/qam_stat.c
+++ b/storage/bdb/qam/qam_stat.c
@@ -1,19 +1,18 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: qam_stat.c,v 11.47 2004/09/22 16:29:47 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: qam_stat.c,v 11.32 2002/05/11 13:40:11 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
+#include <ctype.h>
 #include <string.h>
 #endif
 
@@ -22,22 +21,23 @@ static const char revid[] = "$Id: qam_stat.c,v 11.32 2002/05/11 13:40:11 bostic
 #include "dbinc/db_shash.h"
 #include "dbinc/db_am.h"
 #include "dbinc/lock.h"
-#include "dbinc/log.h"
+#include "dbinc/mp.h"
 #include "dbinc/qam.h"
 
+#ifdef HAVE_STATISTICS
 /*
  * __qam_stat --
  *	Gather/print the qam statistics
  *
- * PUBLIC: int __qam_stat __P((DB *, void *, u_int32_t));
+ * PUBLIC: int __qam_stat __P((DBC *, void *, u_int32_t));
  */
 int
-__qam_stat(dbp, spp, flags)
-	DB *dbp;
+__qam_stat(dbc, spp, flags)
+	DBC *dbc;
 	void *spp;
 	u_int32_t flags;
 {
-	DBC *dbc;
+	DB *dbp;
 	DB_LOCK lock;
 	DB_MPOOLFILE *mpf;
 	DB_QUEUE_STAT *sp;
@@ -50,27 +50,16 @@ __qam_stat(dbp, spp, flags)
 	u_int32_t re_len;
 	int ret, t_ret;
 
-	PANIC_CHECK(dbp->dbenv);
-	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->stat");
+	dbp = dbc->dbp;
 
 	LOCK_INIT(lock);
 	mpf = dbp->mpf;
 	sp = NULL;
 	t = dbp->q_internal;
 
-	/* Check for invalid flags. */
-	if ((ret = __db_statchk(dbp, flags)) != 0)
-		return (ret);
-
 	if (spp == NULL)
 		return (0);
 
-	/* Acquire a cursor. */
-	if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0)
-		return (ret);
-
-	DEBUG_LWRITE(dbc, NULL, "qam_stat", NULL, NULL, flags);
-
 	/* Allocate and clear the structure. */
 	if ((ret = __os_umalloc(dbp->dbenv, sizeof(*sp), &sp)) != 0)
 		goto err;
@@ -79,10 +68,9 @@ __qam_stat(dbp, spp, flags)
 	re_len = ((QUEUE *)dbp->q_internal)->re_len;
 
 	/* Determine the last page of the database. */
-	if ((ret = __db_lget(dbc,
-	    0, t->q_meta, DB_LOCK_READ, 0, &lock)) != 0)
+	if ((ret = __db_lget(dbc, 0, t->q_meta, DB_LOCK_READ, 0, &lock)) != 0)
 		goto err;
-	if ((ret = mpf->get(mpf, &t->q_meta, 0, (PAGE **)&meta)) != 0)
+	if ((ret = __memp_fget(mpf, &t->q_meta, 0, &meta)) != 0)
 		goto err;
 
 	if (flags == DB_FAST_STAT || flags == DB_CACHED_COUNTS) {
@@ -94,13 +82,15 @@ __qam_stat(dbp, spp, flags)
 	first = QAM_RECNO_PAGE(dbp, meta->first_recno);
 	last = QAM_RECNO_PAGE(dbp, meta->cur_recno);
 
-	if ((ret = mpf->put(mpf, meta, 0)) != 0)
+	ret = __memp_fput(mpf, meta, 0);
+	if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
+		ret = t_ret;
+	if (ret != 0)
 		goto err;
-	(void)__LPUT(dbc, lock);
 
 	pgno = first;
 	if (first > last)
-		stop = QAM_RECNO_PAGE(dbp, UINT32_T_MAX);
+		stop = QAM_RECNO_PAGE(dbp, UINT32_MAX);
 	else
 		stop = last;
 
@@ -124,7 +114,7 @@ begin:
 				ret = 0;
 				break;
 			}
-			pgno += pg_ext - ((pgno - 1) % pg_ext) - 1;
+			pgno += (pg_ext - ((pgno - 1) % pg_ext)) - 1;
 			continue;
 		}
 		if (ret != 0)
@@ -142,12 +132,15 @@ begin:
 				sp->qs_pgfree += re_len;
 		}
 
-		if ((ret = __qam_fput(dbp, pgno, h, 0)) != 0)
+		ret = __qam_fput(dbp, pgno, h, 0);
+		if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
+			ret = t_ret;
+		if (ret != 0)
 			goto err;
-		(void)__LPUT(dbc, lock);
 	}
 
-	(void)__LPUT(dbc, lock);
+	if ((ret = __LPUT(dbc, lock)) != 0)
+		goto err;
 	if (first > last) {
 		pgno = 1;
 		stop = last;
@@ -160,7 +153,7 @@ begin:
 	    0, t->q_meta, F_ISSET(dbp, DB_AM_RDONLY) ?
 	    DB_LOCK_READ : DB_LOCK_WRITE, 0, &lock)) != 0)
 		goto err;
-	if ((ret = mpf->get(mpf, &t->q_meta, 0, (PAGE **)&meta)) != 0)
+	if ((ret = __memp_fget(mpf, &t->q_meta, 0, &meta)) != 0)
 		goto err;
 
 	if (!F_ISSET(dbp, DB_AM_RDONLY))
@@ -181,23 +174,88 @@ meta_only:
 	sp->qs_cur_recno = meta->cur_recno;
 
 	/* Discard the meta-data page. */
-	if ((ret = mpf->put(mpf,
-	    meta, F_ISSET(dbp, DB_AM_RDONLY) ? 0 : DB_MPOOL_DIRTY)) != 0)
+	ret = __memp_fput(mpf,
+	    meta, F_ISSET(dbp, DB_AM_RDONLY) ? 0 : DB_MPOOL_DIRTY);
+	if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
+		ret = t_ret;
+	if (ret != 0)
 		goto err;
-	(void)__LPUT(dbc, lock);
 
 	*(DB_QUEUE_STAT **)spp = sp;
-	ret = 0;
 
 	if (0) {
 err:		if (sp != NULL)
 			__os_ufree(dbp->dbenv, sp);
 	}
 
-	(void)__LPUT(dbc, lock);
-
-	if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
+	if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
 		ret = t_ret;
 
 	return (ret);
 }
+
+/*
+ * __qam_stat_print --
+ *	Display queue statistics.
+ *
+ * PUBLIC: int __qam_stat_print __P((DBC *, u_int32_t));
+ */
+int
+__qam_stat_print(dbc, flags)
+	DBC *dbc;
+	u_int32_t flags;
+{
+	DB *dbp;
+	DB_ENV *dbenv;
+	DB_QUEUE_STAT *sp;
+	int ret;
+
+	dbp = dbc->dbp;
+	dbenv = dbp->dbenv;
+
+	if ((ret = __qam_stat(dbc, &sp, 0)) != 0)
+		return (ret);
+
+	if (LF_ISSET(DB_STAT_ALL)) {
+		__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+		__db_msg(dbenv, "Default Queue database information:");
+	}
+	__db_msg(dbenv, "%lx\tQueue magic number", (u_long)sp->qs_magic);
+	__db_msg(dbenv, "%lu\tQueue version number", (u_long)sp->qs_version);
+	__db_dl(dbenv, "Fixed-length record size", (u_long)sp->qs_re_len);
+	__db_msg(dbenv, "%#x\tFixed-length record pad", (int)sp->qs_re_pad);
+	__db_dl(dbenv,
+	    "Underlying database page size", (u_long)sp->qs_pagesize);
+	__db_dl(dbenv,
+	    "Underlying database extent size", (u_long)sp->qs_extentsize);
+	__db_dl(dbenv,
+	    "Number of records in the database", (u_long)sp->qs_nkeys);
+	__db_dl(dbenv, "Number of database pages", (u_long)sp->qs_pages);
+	__db_dl_pct(dbenv,
+	    "Number of bytes free in database pages",
+	    (u_long)sp->qs_pgfree,
+	    DB_PCT_PG(sp->qs_pgfree, sp->qs_pages, sp->qs_pagesize), "ff");
+	__db_msg(dbenv,
+	    "%lu\tFirst undeleted record", (u_long)sp->qs_first_recno);
+	__db_msg(dbenv,
+	    "%lu\tNext available record number", (u_long)sp->qs_cur_recno);
+
+	__os_ufree(dbenv, sp);
+
+	return (0);
+}
+
+#else /* !HAVE_STATISTICS */
+
+int
+__qam_stat(dbc, spp, flags)
+	DBC *dbc;
+	void *spp;
+	u_int32_t flags;
+{
+	COMPQUIET(spp, NULL);
+	COMPQUIET(flags, 0);
+
+	return (__db_stat_not_built(dbc->dbp->dbenv));
+}
+#endif
diff --git a/storage/bdb/qam/qam_stub.c b/storage/bdb/qam/qam_stub.c
new file mode 100644
index 0000000000000000000000000000000000000000..1c22aaa520b396cf80206ab3397ab0204207b394
--- /dev/null
+++ b/storage/bdb/qam/qam_stub.c
@@ -0,0 +1,334 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: qam_stub.c,v 1.12 2004/06/14 15:23:33 bostic Exp $
+ */
+
+#include "db_config.h"
+
+#ifndef	HAVE_QUEUE
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/qam.h"
+
+/*
+ * If the library wasn't compiled with the Queue access method, various
+ * routines aren't available.  Stub them here, returning an appropriate
+ * error.
+ */
+
+/*
+ * __db_no_queue_am --
+ *	Error when a Berkeley DB build doesn't include the access method.
+ *
+ * PUBLIC: int __db_no_queue_am __P((DB_ENV *));
+ */
+int
+__db_no_queue_am(dbenv)
+	DB_ENV *dbenv;
+{
+	__db_err(dbenv,
+    "library build did not include support for the Queue access method");
+	return (DB_OPNOTSUP);
+}
+
+int
+__db_prqueue(dbp, flags)
+	DB *dbp;
+	u_int32_t flags;
+{
+	COMPQUIET(flags, 0);
+	return (__db_no_queue_am(dbp->dbenv));
+}
+
+int
+__qam_31_qammeta(dbp, real_name, buf)
+	DB *dbp;
+	char *real_name;
+	u_int8_t *buf;
+{
+	COMPQUIET(real_name, NULL);
+	COMPQUIET(buf, NULL);
+	return (__db_no_queue_am(dbp->dbenv));
+}
+
+int
+__qam_32_qammeta(dbp, real_name, buf)
+	DB *dbp;
+	char *real_name;
+	u_int8_t *buf;
+{
+	COMPQUIET(real_name, NULL);
+	COMPQUIET(buf, NULL);
+	return (__db_no_queue_am(dbp->dbenv));
+}
+
+int
+__qam_append(dbc, key, data)
+	DBC *dbc;
+	DBT *key, *data;
+{
+	COMPQUIET(key, NULL);
+	COMPQUIET(data, NULL);
+	return (__db_no_queue_am(dbc->dbp->dbenv));
+}
+
+int
+__qam_c_dup(orig_dbc, new_dbc)
+	DBC *orig_dbc, *new_dbc;
+{
+	COMPQUIET(new_dbc, NULL);
+	return (__db_no_queue_am(orig_dbc->dbp->dbenv));
+}
+
+int
+__qam_c_init(dbc)
+	DBC *dbc;
+{
+	return (__db_no_queue_am(dbc->dbp->dbenv));
+}
+
+int
+__qam_db_close(dbp, flags)
+	DB *dbp;
+	u_int32_t flags;
+{
+	COMPQUIET(dbp, NULL);
+	COMPQUIET(flags, 0);
+	return (0);
+}
+
+int
+__qam_db_create(dbp)
+	DB *dbp;
+{
+	COMPQUIET(dbp, NULL);
+	return (0);
+}
+
+int
+__qam_extent_names(dbenv, name, namelistp)
+	DB_ENV *dbenv;
+	char *name;
+	char ***namelistp;
+{
+	COMPQUIET(name, NULL);
+	COMPQUIET(namelistp, NULL);
+	return (__db_no_queue_am(dbenv));
+}
+
+int
+__qam_gen_filelist(dbp, filelistp)
+	DB *dbp;
+	QUEUE_FILELIST **filelistp;
+{
+	COMPQUIET(filelistp, NULL);
+	return (__db_no_queue_am(dbp->dbenv));
+}
+
+int
+__qam_init_print(dbenv, dtabp, dtabsizep)
+	DB_ENV *dbenv;
+	int (***dtabp)__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+	size_t *dtabsizep;
+{
+	COMPQUIET(dbenv, NULL);
+	COMPQUIET(dtabp, NULL);
+	COMPQUIET(dtabsizep, NULL);
+	return (0);
+}
+
+int
+__qam_init_recover(dbenv, dtabp, dtabsizep)
+	DB_ENV *dbenv;
+	int (***dtabp)__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+	size_t *dtabsizep;
+{
+	COMPQUIET(dbenv, NULL);
+	COMPQUIET(dtabp, NULL);
+	COMPQUIET(dtabsizep, NULL);
+	return (0);
+}
+
+int
+__qam_metachk(dbp, name, qmeta)
+	DB *dbp;
+	const char *name;
+	QMETA *qmeta;
+{
+	COMPQUIET(name, NULL);
+	COMPQUIET(qmeta, NULL);
+	return (__db_no_queue_am(dbp->dbenv));
+}
+
+int
+__qam_new_file(dbp, txn, fhp, name)
+	DB *dbp;
+	DB_TXN *txn;
+	DB_FH *fhp;
+	const char *name;
+{
+	COMPQUIET(txn, NULL);
+	COMPQUIET(fhp, NULL);
+	COMPQUIET(name, NULL);
+	return (__db_no_queue_am(dbp->dbenv));
+}
+
+int
+__qam_open(dbp, txn, name, base_pgno, mode, flags)
+	DB *dbp;
+	DB_TXN *txn;
+	const char *name;
+	db_pgno_t base_pgno;
+	int mode;
+	u_int32_t flags;
+{
+	COMPQUIET(txn, NULL);
+	COMPQUIET(name, NULL);
+	COMPQUIET(base_pgno, 0);
+	COMPQUIET(mode, 0);
+	COMPQUIET(flags, 0);
+	return (__db_no_queue_am(dbp->dbenv));
+}
+
+int
+__qam_pgin_out(dbenv, pg, pp, cookie)
+	DB_ENV *dbenv;
+	db_pgno_t pg;
+	void *pp;
+	DBT *cookie;
+{
+	COMPQUIET(pg, 0);
+	COMPQUIET(pp, NULL);
+	COMPQUIET(cookie, NULL);
+	return (__db_no_queue_am(dbenv));
+}
+
+int
+__qam_salvage(dbp, vdp, pgno, h, handle, callback, flags)
+	DB *dbp;
+	VRFY_DBINFO *vdp;
+	db_pgno_t pgno;
+	PAGE *h;
+	void *handle;
+	int (*callback) __P((void *, const void *));
+	u_int32_t flags;
+{
+	COMPQUIET(vdp, NULL);
+	COMPQUIET(pgno, 0);
+	COMPQUIET(h, NULL);
+	COMPQUIET(handle, NULL);
+	COMPQUIET(callback, NULL);
+	COMPQUIET(flags, 0);
+	return (__db_no_queue_am(dbp->dbenv));
+}
+
+int
+__qam_set_ext_data(dbp, name)
+	DB *dbp;
+	const char *name;
+{
+	COMPQUIET(name, NULL);
+	return (__db_no_queue_am(dbp->dbenv));
+}
+
+int
+__qam_stat(dbc, spp, flags)
+	DBC *dbc;
+	void *spp;
+	u_int32_t flags;
+{
+	COMPQUIET(spp, NULL);
+	COMPQUIET(flags, 0);
+	return (__db_no_queue_am(dbc->dbp->dbenv));
+}
+
+int
+__qam_stat_print(dbc, flags)
+	DBC *dbc;
+	u_int32_t flags;
+{
+	COMPQUIET(flags, 0);
+	return (__db_no_queue_am(dbc->dbp->dbenv));
+}
+
+int
+__qam_sync(dbp)
+	DB *dbp;
+{
+	return (__db_no_queue_am(dbp->dbenv));
+}
+
+int
+__qam_truncate(dbc, countp)
+	DBC *dbc;
+	u_int32_t *countp;
+{
+	COMPQUIET(dbc, NULL);
+	COMPQUIET(countp, NULL);
+	return (__db_no_queue_am(dbc->dbp->dbenv));
+}
+
+int
+__qam_vrfy_data(dbp, vdp, h, pgno, flags)
+	DB *dbp;
+	VRFY_DBINFO *vdp;
+	QPAGE *h;
+	db_pgno_t pgno;
+	u_int32_t flags;
+{
+	COMPQUIET(vdp, NULL);
+	COMPQUIET(h, NULL);
+	COMPQUIET(pgno, 0);
+	COMPQUIET(flags, 0);
+	return (__db_no_queue_am(dbp->dbenv));
+}
+
+int
+__qam_vrfy_meta(dbp, vdp, meta, pgno, flags)
+	DB *dbp;
+	VRFY_DBINFO *vdp;
+	QMETA *meta;
+	db_pgno_t pgno;
+	u_int32_t flags;
+{
+	COMPQUIET(vdp, NULL);
+	COMPQUIET(meta, NULL);
+	COMPQUIET(pgno, 0);
+	COMPQUIET(flags, 0);
+	return (__db_no_queue_am(dbp->dbenv));
+}
+
+int
+__qam_vrfy_structure(dbp, vdp, flags)
+	DB *dbp;
+	VRFY_DBINFO *vdp;
+	u_int32_t flags;
+{
+	COMPQUIET(vdp, NULL);
+	COMPQUIET(flags, 0);
+	return (__db_no_queue_am(dbp->dbenv));
+}
+
+int
+__qam_vrfy_walkqueue(dbp, vdp, handle, callback, flags)
+	DB *dbp;
+	VRFY_DBINFO *vdp;
+	void *handle;
+	int (*callback) __P((void *, const void *));
+	u_int32_t flags;
+{
+	COMPQUIET(vdp, NULL);
+	COMPQUIET(handle, NULL);
+	COMPQUIET(callback, NULL);
+	COMPQUIET(flags, 0);
+	return (__db_no_queue_am(dbp->dbenv));
+}
+#endif	/* !HAVE_QUEUE */
diff --git a/storage/bdb/qam/qam_upgrade.c b/storage/bdb/qam/qam_upgrade.c
index 6bd79fc948a62b32a0cb86e14a14ffbfabe3c79d..dff82404acf2677ee0f143dce437cd7c297a5145 100644
--- a/storage/bdb/qam/qam_upgrade.c
+++ b/storage/bdb/qam/qam_upgrade.c
@@ -1,24 +1,24 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: qam_upgrade.c,v 11.16 2004/05/10 21:29:43 bostic Exp $
  */
-#include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: qam_upgrade.c,v 11.12 2002/03/29 20:46:48 bostic Exp $";
-#endif /* not lint */
+#include "db_config.h"
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
-#include <limits.h>
 #include <string.h>
 #endif
 
 #include "db_int.h"
 #include "dbinc/db_upgrade.h"
+#include "dbinc/db_page.h"
+#include "dbinc/qam.h"
 
 /*
  * __qam_31_qammeta --
diff --git a/storage/bdb/qam/qam_verify.c b/storage/bdb/qam/qam_verify.c
index 5b020c2c33544e668451aaf5f4c9d1d09dfc5f58..571157b8fac309007630e1998427829c689e665c 100644
--- a/storage/bdb/qam/qam_verify.c
+++ b/storage/bdb/qam/qam_verify.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: qam_verify.c,v 1.51 2004/10/11 18:47:51 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: qam_verify.c,v 1.30 2002/06/26 20:49:27 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -19,8 +17,12 @@ static const char revid[] = "$Id: qam_verify.c,v 1.30 2002/06/26 20:49:27 bostic
 #include "db_int.h"
 #include "dbinc/db_page.h"
 #include "dbinc/db_verify.h"
-#include "dbinc/qam.h"
 #include "dbinc/db_am.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/mp.h"
+#include "dbinc/qam.h"
+#include <stdlib.h>
+#include <string.h>
 
 /*
  * __qam_vrfy_meta --
@@ -37,8 +39,22 @@ __qam_vrfy_meta(dbp, vdp, meta, pgno, flags)
 	db_pgno_t pgno;
 	u_int32_t flags;
 {
+	DB_ENV *dbenv;
+	QUEUE *qp;
 	VRFY_PAGEINFO *pip;
-	int isbad, ret, t_ret;
+	db_pgno_t *extents, extid, first, last;
+	size_t len;
+	int count, i, isbad, nextents, ret, t_ret;
+	char *buf, **names;
+
+	COMPQUIET(count, 0);
+
+	dbenv = dbp->dbenv;
+	qp = (QUEUE *)dbp->q_internal;
+	extents = NULL;
+	first = last = 0;
+	buf = NULL;
+	names = NULL;
 
 	if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
 		return (ret);
@@ -49,42 +65,121 @@ __qam_vrfy_meta(dbp, vdp, meta, pgno, flags)
 	 * something very odd is going on.
 	 */
 	if (!F_ISSET(pip, VRFY_INCOMPLETE))
-		EPRINT((dbp->dbenv,
-		    "Page %lu: queue databases must be one-per-file",
+		EPRINT((dbenv, "Page %lu: queue databases must be one-per-file",
 		    (u_long)pgno));
 
 	/*
-	 * cur_recno/rec_page
-	 * Cur_recno may be one beyond the end of the page and
-	 * we start numbering from 1.
+	 * Because the metapage pointers are rolled forward by
+	 * aborting transactions, the extent of the queue may
+	 * extend beyond the allocated pages, so we do
+	 * not check that meta_current is within the allocated
+	 * pages.
 	 */
-	if (vdp->last_pgno > 0 && meta->cur_recno > 0 &&
-	    meta->cur_recno - 1 > meta->rec_page * vdp->last_pgno) {
-		EPRINT((dbp->dbenv,
-    "Page %lu: current recno %lu references record past last page number %lu",
-		    (u_long)pgno,
-		    (u_long)meta->cur_recno, (u_long)vdp->last_pgno));
-		isbad = 1;
-	}
 
 	/*
 	 * re_len:  If this is bad, we can't safely verify queue data pages, so
 	 * return DB_VERIFY_FATAL
 	 */
-	if (ALIGN(meta->re_len + sizeof(QAMDATA) - 1, sizeof(u_int32_t)) *
+	if (DB_ALIGN(meta->re_len + sizeof(QAMDATA) - 1, sizeof(u_int32_t)) *
 	    meta->rec_page + QPAGE_SZ(dbp) > dbp->pgsize) {
-		EPRINT((dbp->dbenv,
+		EPRINT((dbenv,
    "Page %lu: queue record length %lu too high for page size and recs/page",
 		    (u_long)pgno, (u_long)meta->re_len));
 		ret = DB_VERIFY_FATAL;
 		goto err;
 	} else {
-		vdp->re_len = meta->re_len;
-		vdp->rec_page = meta->rec_page;
+		/*
+		 * We initialize the Queue internal pointer;  we may need
+		 * it when handling extents.  It would get set up in open,
+		 * if we called open normally, but we don't.
+		 */
+		qp->re_len = vdp->re_len = meta->re_len;
+		qp->rec_page = vdp->rec_page = meta->rec_page;
+		qp->page_ext = vdp->page_ext = meta->page_ext;
+	}
+
+	/*
+	 * There's no formal maximum extentsize, and a 0 value represents
+	 * no extents, so there's nothing to verify.
+	 *
+	 * Note that since QUEUE databases can't have subdatabases, it's an
+	 * error to see more than one QUEUE metadata page in a single
+	 * verifier run.  Theoretically, this should really be a structure
+	 * rather than a per-page check, but since we're setting qp fields
+	 * here (and have only one qp to set) we raise the alarm now if
+	 * this assumption fails.  (We need the qp info to be reasonable
+	 * before we do per-page verification of queue extents.)
+	 */
+	if (F_ISSET(vdp, VRFY_QMETA_SET)) {
+		isbad = 1;
+		EPRINT((dbenv,
+		    "Page %lu: database contains multiple Queue metadata pages",
+		    (u_long)pgno));
+		goto err;
+	}
+	F_SET(vdp, VRFY_QMETA_SET);
+	qp->page_ext = meta->page_ext;
+	dbp->pgsize = meta->dbmeta.pagesize;
+	qp->q_meta = pgno;
+	qp->q_root = pgno + 1;
+	vdp->first_recno = meta->first_recno;
+	vdp->last_recno = meta->cur_recno;
+	if (qp->page_ext != 0) {
+		first = QAM_RECNO_EXTENT(dbp, vdp->first_recno);
+		last = QAM_RECNO_EXTENT(dbp, vdp->last_recno);
+	}
+
+	/*
+	 * Look in the data directory to see if there are any extents
+	 * around that are not in the range of the queue.  If so,
+	 * then report that and look there if we are salvaging.
+	 */
+
+	if ((ret = __db_appname(dbenv,
+	    DB_APP_DATA, qp->dir, 0, NULL, &buf)) != 0)
+		goto err;
+	if ((ret = __os_dirlist(dbenv, buf, &names, &count)) != 0)
+		goto err;
+	__os_free(dbenv, buf);
+	buf = NULL;
+
+	len = strlen(QUEUE_EXTENT_HEAD) + strlen(qp->name) + 1;
+	if ((ret = __os_malloc(dbenv, len, &buf)) != 0)
+		goto err;
+	len = (size_t)snprintf(buf, len, QUEUE_EXTENT_HEAD, qp->name);
+	for (i = nextents = 0; i < count; i++) {
+		if (strncmp(names[i], buf, len) == 0) {
+			/* Only save extents out of bounds. */
+			extid = (db_pgno_t)strtoul(&names[i][len], NULL, 10);
+			if (qp->page_ext != 0 &&
+			    (last > first ?
+			    (extid >= first && extid <= last) :
+			    (extid >= first || extid <= last)))
+				continue;
+			if (extents == NULL && (ret = __os_malloc(
+			     dbenv, (size_t)(count - i) * sizeof(extid),
+			     &extents)) != 0)
+				goto err;
+			extents[nextents] = extid;
+			nextents++;
+		}
 	}
+	if (nextents > 0)
+		__db_err(dbenv,
+		     "Warning: %d extra extent files found", nextents);
+	vdp->nextents = nextents;
+	vdp->extents = extents;
 
-err:	if ((t_ret =
-	    __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
+err:	if ((t_ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0 && ret == 0)
+		ret = t_ret;
+	if (names != NULL)
+		__os_dirfree(dbenv, names, count);
+	if (buf != NULL)
+		__os_free(dbenv, buf);
+	if (ret != 0 && extents != NULL)
+		__os_free(dbenv, extents);
+	if (LF_ISSET(DB_SALVAGE) &&
+	   (t_ret = __db_salvage_markdone(vdp, pgno)) != 0 && ret == 0)
 		ret = t_ret;
 	return (ret == 0 && isbad == 1 ? DB_VERIFY_BAD : ret);
 }
@@ -108,7 +203,6 @@ __qam_vrfy_data(dbp, vdp, h, pgno, flags)
 	struct __queue fakeq;
 	QAMDATA *qp;
 	db_recno_t i;
-	u_int8_t qflags;
 
 	/*
 	 * Not much to do here, except make sure that flags are reasonable.
@@ -130,12 +224,10 @@ __qam_vrfy_data(dbp, vdp, h, pgno, flags)
 			return (DB_VERIFY_BAD);
 		}
 
-		qflags = qp->flags;
-		qflags &= !(QAM_VALID | QAM_SET);
-		if (qflags != 0) {
+		if (qp->flags & ~(QAM_VALID | QAM_SET)) {
 			EPRINT((dbp->dbenv,
-			    "Page %lu: queue record %lu has bad flags",
-			    (u_long)pgno, (u_long)i));
+			    "Page %lu: queue record %lu has bad flags (%#lx)",
+			    (u_long)pgno, (u_long)i, (u_long)qp->flags));
 			return (DB_VERIFY_BAD);
 		}
 	}
@@ -198,3 +290,229 @@ err:	if ((ret = __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0)
 		return (ret);
 	return (isbad == 1 ? DB_VERIFY_BAD : 0);
 }
+
+/*
+ * __qam_vrfy_walkqueue --
+ *    Do a "walkpages" per-page verification pass over the set of Queue
+ * extent pages.
+ *
+ * PUBLIC: int __qam_vrfy_walkqueue __P((DB *, VRFY_DBINFO *, void *,
+ * PUBLIC:    int (*)(void *, const void *), u_int32_t));
+ */
+int
+__qam_vrfy_walkqueue(dbp, vdp, handle, callback, flags)
+	DB *dbp;
+	VRFY_DBINFO *vdp;
+	void *handle;
+	int (*callback) __P((void *, const void *));
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	PAGE *h;
+	QUEUE *qp;
+	VRFY_PAGEINFO *pip;
+	db_pgno_t first, i, last, pg_ext, stop;
+	int isbad, nextents, ret, t_ret;
+
+	COMPQUIET(h, NULL);
+
+	dbenv = dbp->dbenv;
+	qp = dbp->q_internal;
+	pip = NULL;
+	pg_ext = qp->page_ext;
+	isbad = ret = t_ret = 0;
+
+	/* If this database has no extents, we've seen all the pages already. */
+	if (pg_ext == 0)
+		return (0);
+
+	first = QAM_RECNO_PAGE(dbp, vdp->first_recno);
+	last = QAM_RECNO_PAGE(dbp, vdp->last_recno);
+
+	i = first;
+	if (first > last)
+		stop = QAM_RECNO_PAGE(dbp, UINT32_MAX);
+	else
+		stop = last;
+	nextents = vdp->nextents;
+
+	/* Verify/salvage each page. */
+begin:	for (; i <= stop; i++) {
+		/*
+		 * If DB_SALVAGE is set, we inspect our database of completed
+		 * pages, and skip any we've already printed in the subdb pass.
+		 */
+		if (LF_ISSET(DB_SALVAGE) && (__db_salvage_isdone(vdp, i) != 0))
+			continue;
+		if ((t_ret = __qam_fget(dbp, &i, 0, &h)) != 0) {
+			if (t_ret == ENOENT || t_ret == DB_PAGE_NOTFOUND) {
+				i += (pg_ext - ((i - 1) % pg_ext)) - 1;
+				continue;
+			}
+
+			/*
+			 * If an individual page get fails, keep going iff
+			 * we're salvaging.
+			 */
+			if (LF_ISSET(DB_SALVAGE)) {
+				if (ret == 0)
+					ret = t_ret;
+				continue;
+			} else
+				return (t_ret);
+		}
+
+		if (LF_ISSET(DB_SALVAGE)) {
+			/*
+			 * We pretty much don't want to quit unless a
+			 * bomb hits.  May as well return that something
+			 * was screwy, however.
+			 */
+			if ((t_ret = __db_salvage(dbp,
+			    vdp, i, h, handle, callback, flags)) != 0) {
+				if (ret == 0)
+					ret = t_ret;
+				isbad = 1;
+			}
+		} else {
+			/*
+			 * If we are not salvaging, and we get any error
+			 * other than DB_VERIFY_BAD, return immediately;
+			 * it may not be safe to proceed.  If we get
+			 * DB_VERIFY_BAD, keep going;  listing more errors
+			 * may make it easier to diagnose problems and
+			 * determine the magnitude of the corruption.
+			 */
+			if ((ret = __db_vrfy_common(dbp,
+			    vdp, h, i, flags)) == DB_VERIFY_BAD)
+				isbad = 1;
+			else if (ret != 0)
+				goto err;
+
+			__db_vrfy_struct_feedback(dbp, vdp);
+
+			if ((ret = __db_vrfy_getpageinfo(vdp, i, &pip)) != 0)
+				return (ret);
+			if (F_ISSET(pip, VRFY_IS_ALLZEROES))
+				goto put;
+			if (pip->type != P_QAMDATA) {
+				EPRINT((dbenv,
+		    "Page %lu: queue database page of incorrect type %lu",
+				    (u_long)i, (u_long)pip->type));
+				isbad = 1;
+				goto err;
+			}
+			if ((ret = __db_vrfy_pgset_inc(vdp->pgset, i)) != 0)
+				goto err;
+			if ((ret = __qam_vrfy_data(dbp, vdp,
+			    (QPAGE *)h, i, flags)) == DB_VERIFY_BAD)
+				isbad = 1;
+			else if (ret != 0)
+				goto err;
+
+put:			if ((ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0)
+				goto err;
+			pip = NULL;
+		}
+
+		/* Again, keep going iff we're salvaging. */
+		if ((t_ret = __qam_fput(dbp, i, h, 0)) != 0) {
+			if (LF_ISSET(DB_SALVAGE)) {
+				if (ret == 0)
+					ret = t_ret;
+				continue;
+			} else
+				return (t_ret);
+		}
+	}
+
+	if (first > last) {
+		i = 1;
+		stop = last;
+		first = last;
+		goto begin;
+	}
+
+	/*
+	 * Now check to see if there were any lingering
+	 * extents and dump their data.
+	 */
+	if (LF_ISSET(DB_SALVAGE) && nextents != 0) {
+		nextents--;
+		i = 1 +
+		    vdp->extents[nextents] * vdp->page_ext;
+		stop = i + vdp->page_ext;
+		goto begin;
+	}
+
+	if (0) {
+err:		if ((t_ret = __qam_fput(dbp, i, h, 0)) != 0)
+			return (ret == 0 ? t_ret : ret);
+		if (pip != NULL &&
+		     (t_ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0)
+			return (ret == 0 ? t_ret : ret);
+	}
+	return ((isbad == 1 && ret == 0) ? DB_VERIFY_BAD : ret);
+}
+
+/*
+ * __qam_salvage --
+ *	Safely dump out all recnos and data on a queue page.
+ *
+ * PUBLIC: int __qam_salvage __P((DB *, VRFY_DBINFO *, db_pgno_t, PAGE *,
+ * PUBLIC:     void *, int (*)(void *, const void *), u_int32_t));
+ */
+int
+__qam_salvage(dbp, vdp, pgno, h, handle, callback, flags)
+	DB *dbp;
+	VRFY_DBINFO *vdp;
+	db_pgno_t pgno;
+	PAGE *h;
+	void *handle;
+	int (*callback) __P((void *, const void *));
+	u_int32_t flags;
+{
+	DBT dbt, key;
+	QAMDATA *qp, *qep;
+	db_recno_t recno;
+	int ret, err_ret, t_ret;
+	u_int32_t pagesize, qlen;
+	u_int32_t i;
+
+	memset(&dbt, 0, sizeof(DBT));
+	memset(&key, 0, sizeof(DBT));
+
+	err_ret = ret = 0;
+
+	pagesize = (u_int32_t)dbp->mpf->mfp->stat.st_pagesize;
+	qlen = ((QUEUE *)dbp->q_internal)->re_len;
+	dbt.size = qlen;
+	key.data = &recno;
+	key.size = sizeof(recno);
+	recno = (pgno - 1) * QAM_RECNO_PER_PAGE(dbp) + 1;
+	i = 0;
+	qep = (QAMDATA *)((u_int8_t *)h + pagesize - qlen);
+	for (qp = QAM_GET_RECORD(dbp, h, i); qp < qep;
+	    recno++, i++, qp = QAM_GET_RECORD(dbp, h, i)) {
+		if (F_ISSET(qp, ~(QAM_VALID|QAM_SET)))
+			continue;
+		if (!F_ISSET(qp, QAM_SET))
+			continue;
+
+		if (!LF_ISSET(DB_AGGRESSIVE) && !F_ISSET(qp, QAM_VALID))
+			continue;
+
+		dbt.data = qp->data;
+		if ((ret = __db_vrfy_prdbt(&key,
+		    0, " ", handle, callback, 1, vdp)) != 0)
+			err_ret = ret;
+
+		if ((ret = __db_vrfy_prdbt(&dbt,
+		    0, " ", handle, callback, 0, vdp)) != 0)
+			err_ret = ret;
+	}
+
+	if ((t_ret = __db_salvage_markdone(vdp, pgno)) != 0)
+		return (t_ret);
+	return ((ret == 0 && err_ret != 0) ? err_ret : ret);
+}
diff --git a/storage/bdb/rep/rep.src b/storage/bdb/rep/rep.src
new file mode 100644
index 0000000000000000000000000000000000000000..ffabca3fa02b408849a850c49de1eeb0ed15d7a6
--- /dev/null
+++ b/storage/bdb/rep/rep.src
@@ -0,0 +1,48 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2004
+ *      Sleepycat Software.  All rights reserved.
+ *
+ * $Id: rep.src,v 1.5 2004/09/22 18:01:04 bostic Exp $
+ */
+
+PREFIX  __rep
+DBPRIVATE
+
+INCLUDE #ifndef NO_SYSTEM_INCLUDES
+INCLUDE #include <stdlib.h>
+INCLUDE #include <string.h>
+INCLUDE #endif
+INCLUDE
+INCLUDE #include "db_int.h"
+INCLUDE #include "dbinc/db_page.h"
+INCLUDE #include "dbinc/db_shash.h"
+INCLUDE #include "dbinc/db_am.h"
+INCLUDE #include "dbinc/log.h"
+INCLUDE #include "dbinc/mp.h"
+INCLUDE #include "dbinc/txn.h"
+INCLUDE
+
+/*
+ * update - send update information
+ */
+BEGIN_BUF update
+POINTER	first_lsn	DB_LSN *	lu
+ARG	num_files	int		d
+END
+
+/*
+ * file info
+ */
+BEGIN_BUF fileinfo
+ARG	pgsize		size_t		lu
+ARG	pgno		db_pgno_t	lu
+ARG	max_pgno	db_pgno_t	lu
+ARG	filenum		int		d
+ARG	id		int32_t		d
+ARG	type		u_int32_t	lu
+ARG	flags		u_int32_t	lu
+DBT	uid		DBT		s
+DBT	info		DBT		s
+END
diff --git a/storage/bdb/rep/rep_backup.c b/storage/bdb/rep/rep_backup.c
new file mode 100644
index 0000000000000000000000000000000000000000..64c538fb5c91ceb0593ddf8a3dcb31a9a53ac8f1
--- /dev/null
+++ b/storage/bdb/rep/rep_backup.c
@@ -0,0 +1,1805 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: rep_backup.c,v 1.33 2004/10/29 18:08:09 bostic Exp $
+ */
+
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#if TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#endif
+
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/db_am.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
+#include "dbinc/mp.h"
+#include "dbinc/qam.h"
+#include "dbinc/txn.h"
+
+static int __rep_filedone __P((DB_ENV *, int, REP *, __rep_fileinfo_args *,
+    u_int32_t));
+static int __rep_files_data __P((DB_ENV *, u_int8_t *, size_t *,
+    size_t *, int *));
+static int __rep_files_inmem __P((DB_ENV *, u_int8_t *, size_t *,
+    size_t *, int *));
+static int __rep_get_fileinfo __P((DB_ENV *, const char *,
+    __rep_fileinfo_args *, u_int8_t *, int *));
+static int __rep_log_setup __P((DB_ENV *, REP *));
+static int __rep_mpf_open __P((DB_ENV *, DB_MPOOLFILE **,
+    __rep_fileinfo_args *));
+static int __rep_page_gap __P((DB_ENV *, REP *, __rep_fileinfo_args *,
+    u_int32_t));
+static int __rep_page_sendpages __P((DB_ENV *, int,
+    __rep_fileinfo_args *, DB_MPOOLFILE *, DB *));
+static int __rep_queue_filedone __P((DB_ENV *, REP *, __rep_fileinfo_args *));
+static int __rep_walk_dir __P((DB_ENV *, const char *, u_int8_t *,
+    size_t *, size_t *, int *));
+static int __rep_write_page __P((DB_ENV *, REP *, __rep_fileinfo_args *));
+
+/*
+ * __rep_update_req -
+ *	Process an update_req and send the file information to the client.
+ *
+ * PUBLIC: int __rep_update_req __P((DB_ENV *, int));
+ */
+int
+__rep_update_req(dbenv, eid)
+	DB_ENV *dbenv;
+	int eid;
+{
+	DBT updbt;
+	DB_LOG *dblp;
+	DB_LOGC *logc;
+	DB_LSN lsn;
+	DBT data_dbt;
+	size_t filelen, filesz, updlen;
+	u_int8_t *buf, *fp;
+	int filecnt, ret, t_ret;
+
+	/*
+	 * Allocate enough for all currently open files and then some.
+	 * Optimize for the common use of having most databases open.
+	 * Allocate dbentry_cnt * 2 plus an estimated 60 bytes per
+	 * file for the filename/path (or multiplied by 120).
+	 *
+	 * The data we send looks like this:
+	 *	__rep_update_args
+	 *	__rep_fileinfo_args
+	 *	__rep_fileinfo_args
+	 *	...
+	 */
+	dblp = dbenv->lg_handle;
+	filecnt = 0;
+	filelen = 0;
+	updlen = 0;
+	filesz = MEGABYTE;
+	if ((ret = __os_calloc(dbenv, 1, filesz, &buf)) != 0)
+		return (ret);
+
+	/*
+	 * First get our file information.  Get in-memory files first
+	 * then get on-disk files.
+	 */
+	fp = buf + sizeof(__rep_update_args);
+	if ((ret = __rep_files_inmem(dbenv, fp, &filesz, &filelen,
+	    &filecnt)) != 0)
+		goto err;
+	if ((ret = __rep_files_data(dbenv, fp, &filesz, &filelen,
+	    &filecnt)) != 0)
+		goto err;
+
+	/*
+	 * Now get our first LSN.
+	 */
+	if ((ret = __log_cursor(dbenv, &logc)) != 0)
+		goto err;
+	memset(&data_dbt, 0, sizeof(data_dbt));
+	ret = __log_c_get(logc, &lsn, &data_dbt, DB_FIRST);
+	if ((t_ret = __log_c_close(logc)) != 0 && ret == 0)
+		ret = t_ret;
+	if (ret != 0)
+		goto err;
+
+	/*
+	 * Package up the update information.
+	 */
+	if ((ret = __rep_update_buf(buf, filesz, &updlen, &lsn, filecnt)) != 0)
+		goto err;
+	/*
+	 * We have all the file information now.  Send it to the client.
+	 */
+	memset(&updbt, 0, sizeof(updbt));
+	updbt.data = buf;
+	updbt.size = (u_int32_t)(filelen + updlen);
+	R_LOCK(dbenv, &dblp->reginfo);
+	lsn = ((LOG *)dblp->reginfo.primary)->lsn;
+	R_UNLOCK(dbenv, &dblp->reginfo);
+	(void)__rep_send_message(dbenv, eid, REP_UPDATE, &lsn, &updbt, 0);
+
+err:
+	__os_free(dbenv, buf);
+	return (ret);
+}
+
+/*
+ * __rep_files_data -
+ *	Walk through all the files in the env's data_dirs.  We need to
+ *	open them, gather the necessary information and then close them.
+ *	Then we need to figure out if they're already in the dbentry array.
+ */
+static int
+__rep_files_data(dbenv, fp, fileszp, filelenp, filecntp)
+	DB_ENV *dbenv;
+	u_int8_t *fp;
+	size_t *fileszp, *filelenp;
+	int *filecntp;
+{
+	int ret;
+	char **ddir;
+
+	ret = 0;
+	if (dbenv->db_data_dir == NULL) {
+		/*
+		 * If we don't have a data dir, we have just the
+		 * env home dir.
+		 */
+		ret = __rep_walk_dir(dbenv, dbenv->db_home, fp,
+		    fileszp, filelenp, filecntp);
+	} else {
+		for (ddir = dbenv->db_data_dir; *ddir != NULL; ++ddir)
+			if ((ret = __rep_walk_dir(dbenv, *ddir, fp,
+			    fileszp, filelenp, filecntp)) != 0)
+				break;
+	}
+	return (ret);
+}
+
+static int
+__rep_walk_dir(dbenv, dir, fp, fileszp, filelenp, filecntp)
+	DB_ENV *dbenv;
+	const char *dir;
+	u_int8_t *fp;
+	size_t *fileszp, *filelenp;
+	int *filecntp;
+{
+	DBT namedbt, uiddbt;
+	__rep_fileinfo_args tmpfp;
+	size_t len, offset;
+	int cnt, i, ret;
+	u_int8_t *rfp, uid[DB_FILE_ID_LEN];
+	char **names;
+#ifdef DIAGNOSTIC
+	REP *rep;
+	DB_MSGBUF mb;
+	DB_REP *db_rep;
+
+	db_rep = dbenv->rep_handle;
+	rep = db_rep->region;
+#endif
+	memset(&namedbt, 0, sizeof(namedbt));
+	memset(&uiddbt, 0, sizeof(uiddbt));
+	RPRINT(dbenv, rep, (dbenv, &mb,
+	    "Walk_dir: Getting info for dir: %s", dir));
+	if ((ret = __os_dirlist(dbenv, dir, &names, &cnt)) != 0)
+		return (ret);
+	rfp = fp;
+	RPRINT(dbenv, rep, (dbenv, &mb,
+	    "Walk_dir: Dir %s has %d files", dir, cnt));
+	for (i = 0; i < cnt; i++) {
+		RPRINT(dbenv, rep, (dbenv, &mb,
+		    "Walk_dir: File %d name: %s", i, names[i]));
+		/*
+		 * Skip DB-owned files: ., ..,  __db*, DB_CONFIG, log*
+		 */
+		if (strcmp(names[i], ".") == 0)
+			continue;
+		if (strcmp(names[i], "..") == 0)
+			continue;
+		if (strncmp(names[i], "__db", 4) == 0)
+			continue;
+		if (strncmp(names[i], "DB_CONFIG", 9) == 0)
+			continue;
+		if (strncmp(names[i], "log", 3) == 0)
+			continue;
+		/*
+		 * We found a file to process.  Check if we need
+		 * to allocate more space.
+		 */
+		if ((ret = __rep_get_fileinfo(dbenv, names[i], &tmpfp, uid,
+		    filecntp)) != 0) {
+			/*
+			 * If we find a file that isn't a database, skip it.
+			 */
+			RPRINT(dbenv, rep, (dbenv, &mb,
+			    "Walk_dir: File %d %s: returned error %s",
+			    i, names[i], db_strerror(ret)));
+			ret = 0;
+			continue;
+		}
+		RPRINT(dbenv, rep, (dbenv, &mb,
+		    "Walk_dir: File %d (of %d) %s: pgsize %lu, max_pgno %lu",
+		    tmpfp.filenum, i, names[i],
+		    (u_long)tmpfp.pgsize, (u_long)tmpfp.max_pgno));
+		namedbt.data = names[i];
+		namedbt.size = (u_int32_t)strlen(names[i]) + 1;
+		uiddbt.data = uid;
+		uiddbt.size = DB_FILE_ID_LEN;
+retry:
+		ret = __rep_fileinfo_buf(rfp, *fileszp, &len,
+		    tmpfp.pgsize, tmpfp.pgno, tmpfp.max_pgno,
+		    tmpfp.filenum, tmpfp.id, tmpfp.type,
+		    tmpfp.flags, &uiddbt, &namedbt);
+		if (ret == ENOMEM) {
+			offset = (size_t)(rfp - fp);
+			*fileszp *= 2;
+			/*
+			 * Need to account for update info on both sides
+			 * of the allocation.
+			 */
+			fp -= sizeof(__rep_update_args);
+			if ((ret = __os_realloc(dbenv, *fileszp, fp)) != 0)
+				break;
+			fp += sizeof(__rep_update_args);
+			rfp = fp + offset;
+			/*
+			 * Now that we've reallocated the space, try to
+			 * store it again.
+			 */
+			goto retry;
+		}
+		rfp += len;
+		*filelenp += len;
+	}
+	__os_dirfree(dbenv, names, cnt);
+	return (ret);
+}
+
+static int
+__rep_get_fileinfo(dbenv, file, rfp, uid, filecntp)
+	DB_ENV *dbenv;
+	const char *file;
+	__rep_fileinfo_args *rfp;
+	u_int8_t *uid;
+	int *filecntp;
+{
+
+	DB *dbp, *entdbp;
+	DB_LOCK lk;
+	DB_LOG *dblp;
+	DB_MPOOLFILE *mpf;
+	DBC *dbc;
+	DBMETA *dbmeta;
+	PAGE *pagep;
+	int i, ret, t_ret;
+
+	dbp = NULL;
+	dbc = NULL;
+	pagep = NULL;
+	mpf = NULL;
+	LOCK_INIT(lk);
+
+	dblp = dbenv->lg_handle;
+	if ((ret = db_create(&dbp, dbenv, 0)) != 0)
+		goto err;
+	if ((ret = __db_open(dbp, NULL, file, NULL, DB_UNKNOWN,
+	    DB_RDONLY | (F_ISSET(dbenv, DB_ENV_THREAD) ? DB_THREAD : 0),
+	    0, PGNO_BASE_MD)) != 0)
+		goto err;
+
+	if ((ret = __db_cursor(dbp, NULL, &dbc, 0)) != 0)
+		goto err;
+	if ((ret = __db_lget(
+	    dbc, 0, dbp->meta_pgno, DB_LOCK_READ, 0, &lk)) != 0)
+		goto err;
+	if ((ret = __memp_fget(dbp->mpf, &dbp->meta_pgno, 0, &pagep)) != 0)
+		goto err;
+	/*
+	 * We have the meta page.  Set up our information.
+	 */
+	dbmeta = (DBMETA *)pagep;
+	rfp->pgno = 0;
+	/*
+	 * Queue is a special-case.  We need to set max_pgno to 0 so that
+	 * the client can compute the pages from the meta-data.
+	 */
+	if (dbp->type == DB_QUEUE)
+		rfp->max_pgno = 0;
+	else
+		rfp->max_pgno = dbmeta->last_pgno;
+	rfp->pgsize = dbp->pgsize;
+	memcpy(uid, dbp->fileid, DB_FILE_ID_LEN);
+	rfp->filenum = (*filecntp)++;
+	rfp->type = dbp->type;
+	rfp->flags = dbp->flags;
+	rfp->id = DB_LOGFILEID_INVALID;
+	ret = __memp_fput(dbp->mpf, pagep, 0);
+	pagep = NULL;
+	if ((t_ret = __LPUT(dbc, lk)) != 0 && ret == 0)
+		ret = t_ret;
+	if (ret != 0)
+		goto err;
+err:
+	if ((t_ret = __LPUT(dbc, lk)) != 0 && ret == 0)
+		ret = t_ret;
+	if (dbc != NULL && (t_ret = __db_c_close(dbc)) != 0 && ret == 0)
+		ret = t_ret;
+	if (pagep != NULL &&
+	    (t_ret = __memp_fput(mpf, pagep, 0)) != 0 && ret == 0)
+		ret = t_ret;
+	if (dbp != NULL && (t_ret = __db_close(dbp, NULL, 0)) != 0 && ret == 0)
+		ret = t_ret;
+	/*
+	 * We walk the entry table now, after closing the dbp because
+	 * otherwise we find the open from this function and the id
+	 * is useless in that case.
+	 */
+	if (ret == 0) {
+		MUTEX_THREAD_LOCK(dbenv, dblp->mutexp);
+		/*
+		 * Walk entry table looking for this uid.
+		 * If we find it, save the id.
+		 */
+		for (i = 0; i < dblp->dbentry_cnt; i++) {
+			entdbp = dblp->dbentry[i].dbp;
+			if (entdbp == NULL)
+				break;
+			DB_ASSERT(entdbp->log_filename != NULL);
+			if (memcmp(uid,
+			    entdbp->log_filename->ufid,
+			    DB_FILE_ID_LEN) == 0)
+				rfp->id = i;
+		}
+		MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+	}
+	return (ret);
+}
+
+/*
+ * __rep_files_inmem -
+ *	Gather all the information about in-memory files.
+ */
+static int
+__rep_files_inmem(dbenv, fp, fileszp, filelenp, filecntp)
+	DB_ENV *dbenv;
+	u_int8_t *fp;
+	size_t *fileszp, *filelenp;
+	int *filecntp;
+{
+
+	int ret;
+
+	COMPQUIET(dbenv, NULL);
+	COMPQUIET(fp, NULL);
+	COMPQUIET(fileszp, NULL);
+	COMPQUIET(filelenp, NULL);
+	COMPQUIET(filecntp, NULL);
+	ret = 0;
+	return (ret);
+}
+
+/*
+ * __rep_page_req
+ *	Process a page_req and send the page information to the client.
+ *
+ * PUBLIC: int __rep_page_req __P((DB_ENV *, int, DBT *));
+ */
+int
+__rep_page_req(dbenv, eid, rec)
+	DB_ENV *dbenv;
+	int eid;
+	DBT *rec;
+{
+	DB *dbp;
+	DBT msgdbt;
+	DB_LOG *dblp;
+	DB_MPOOLFILE *mpf;
+	__rep_fileinfo_args *msgfp;
+	int ret, t_ret;
+	void *next;
+#ifdef DIAGNOSTIC
+	DB_MSGBUF mb;
+	DB_REP *db_rep;
+	REP *rep;
+
+	db_rep = dbenv->rep_handle;
+	rep = db_rep->region;
+#endif
+	dblp = dbenv->lg_handle;
+	if ((ret = __rep_fileinfo_read(dbenv, rec->data, &next, &msgfp)) != 0)
+		return (ret);
+	/*
+	 * See if we can find it already.  If so we can quickly
+	 * access its mpool and process.  Otherwise we have to
+	 * open the file ourselves.
+	 */
+	RPRINT(dbenv, rep, (dbenv, &mb, "page_req: file %d page %lu to %lu",
+	    msgfp->filenum, (u_long)msgfp->pgno, (u_long)msgfp->max_pgno));
+	MUTEX_THREAD_LOCK(dbenv, dblp->mutexp);
+	if (msgfp->id >= 0 && dblp->dbentry_cnt > msgfp->id) {
+		dbp = dblp->dbentry[msgfp->id].dbp;
+		if (dbp != NULL) {
+			DB_ASSERT(dbp->log_filename != NULL);
+			if (memcmp(msgfp->uid.data, dbp->log_filename->ufid,
+			    DB_FILE_ID_LEN) == 0) {
+				MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+				RPRINT(dbenv, rep, (dbenv, &mb,
+				    "page_req: found %d in dbreg",
+				    msgfp->filenum));
+				ret = __rep_page_sendpages(dbenv, eid,
+				    msgfp, dbp->mpf, dbp);
+				goto err;
+			}
+		}
+	}
+	MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+
+	/*
+	 * If we get here, we do not have the file open via dbreg.
+	 * We need to open the file and then send its pages.
+	 * If we cannot open the file, we send REP_FILE_FAIL.
+	 */
+	RPRINT(dbenv, rep, (dbenv, &mb, "page_req: Open %d via mpf_open",
+	    msgfp->filenum));
+	if ((ret = __rep_mpf_open(dbenv, &mpf, msgfp)) != 0) {
+		memset(&msgdbt, 0, sizeof(msgdbt));
+		msgdbt.data = msgfp;
+		msgdbt.size = sizeof(*msgfp);
+		RPRINT(dbenv, rep, (dbenv, &mb, "page_req: Open %d failed",
+		    msgfp->filenum));
+		(void)__rep_send_message(dbenv, eid, REP_FILE_FAIL,
+		    NULL, &msgdbt, 0);
+		goto err;
+	}
+
+	ret = __rep_page_sendpages(dbenv, eid, msgfp, mpf, NULL);
+	t_ret = __memp_fclose(mpf, 0);
+	if (ret == 0 && t_ret != 0)
+		ret = t_ret;
+err:
+	__os_free(dbenv, msgfp);
+	return (ret);
+}
+
+static int
+__rep_page_sendpages(dbenv, eid, msgfp, mpf, dbp)
+	DB_ENV *dbenv;
+	int eid;
+	__rep_fileinfo_args *msgfp;
+	DB_MPOOLFILE *mpf;
+	DB *dbp;
+{
+	DB *qdbp;
+	DBT msgdbt, pgdbt;
+	DB_LOG *dblp;
+	DB_LSN lsn;
+	DB_MSGBUF mb;
+	DB_REP *db_rep;
+	PAGE *pagep;
+	REP *rep;
+	db_pgno_t p;
+	size_t len, msgsz;
+	u_int32_t bytes, gbytes, type;
+	int check_limit, opened, ret, t_ret;
+	u_int8_t *buf;
+
+#ifndef DIAGNOSTIC
+	DB_MSGBUF_INIT(&mb);
+#endif
+	db_rep = dbenv->rep_handle;
+	rep = db_rep->region;
+	opened = 0;
+	gbytes = bytes = 0;
+	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+	gbytes = rep->gbytes;
+	bytes = rep->bytes;
+	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+	check_limit = gbytes != 0 || bytes != 0;
+	qdbp = NULL;
+	buf = NULL;
+	if (msgfp->type == DB_QUEUE) {
+		if (dbp == NULL) {
+			if ((ret = db_create(&qdbp, dbenv, 0)) != 0)
+				goto err;
+			if ((ret = __db_open(qdbp, NULL, msgfp->info.data,
+			    NULL, DB_UNKNOWN,
+			    DB_RDONLY | (F_ISSET(dbenv, DB_ENV_THREAD) ?
+			    DB_THREAD : 0), 0, PGNO_BASE_MD)) != 0)
+				goto err;
+			opened = 1;
+		} else
+			qdbp = dbp;
+	}
+	msgsz = sizeof(__rep_fileinfo_args) + DB_FILE_ID_LEN + msgfp->pgsize;
+	if ((ret = __os_calloc(dbenv, 1, msgsz, &buf)) != 0)
+		return (ret);
+	memset(&msgdbt, 0, sizeof(msgdbt));
+	memset(&pgdbt, 0, sizeof(pgdbt));
+	RPRINT(dbenv, rep, (dbenv, &mb, "sendpages: file %d page %lu to %lu",
+	    msgfp->filenum, (u_long)msgfp->pgno, (u_long)msgfp->max_pgno));
+	for (p = msgfp->pgno; p <= msgfp->max_pgno; p++) {
+		if (msgfp->type == DB_QUEUE && p != 0)
+#ifdef HAVE_QUEUE
+			ret = __qam_fget(qdbp, &p, DB_MPOOL_CREATE, &pagep);
+#else
+			ret = DB_PAGE_NOTFOUND;
+#endif
+		else
+			ret = __memp_fget(mpf, &p, DB_MPOOL_CREATE, &pagep);
+		type = REP_PAGE;
+		if (ret == DB_PAGE_NOTFOUND) {
+			memset(&pgdbt, 0, sizeof(pgdbt));
+			ret = 0;
+			ZERO_LSN(lsn);
+			RPRINT(dbenv, rep, (dbenv, &mb,
+			    "sendpages: PAGE_FAIL on page %lu", (u_long)p));
+			type = REP_PAGE_FAIL;
+			msgfp->pgno = p;
+			goto send;
+		} else if (ret != 0)
+			goto err;
+		else {
+			pgdbt.data = pagep;
+			pgdbt.size = (u_int32_t)msgfp->pgsize;
+		}
+		len = 0;
+		ret = __rep_fileinfo_buf(buf, msgsz, &len,
+		    msgfp->pgsize, p, msgfp->max_pgno,
+		    msgfp->filenum, msgfp->id, msgfp->type,
+		    msgfp->flags, &msgfp->uid, &pgdbt);
+		if (ret != 0)
+			goto err;
+
+		DB_ASSERT(len <= msgsz);
+		msgdbt.data = buf;
+		msgdbt.size = (u_int32_t)len;
+
+		dblp = dbenv->lg_handle;
+		R_LOCK(dbenv, &dblp->reginfo);
+		lsn = ((LOG *)dblp->reginfo.primary)->lsn;
+		R_UNLOCK(dbenv, &dblp->reginfo);
+		if (check_limit) {
+			/*
+			 * msgdbt.size is only the size of the page and
+			 * other information we're sending.  It doesn't
+			 * count the size of the control structure.  Factor
+			 * that in as well so we're not off by a lot if
+			 * pages are small.
+			 */
+			while (bytes < msgdbt.size + sizeof(REP_CONTROL)) {
+				if (gbytes > 0) {
+					bytes += GIGABYTE;
+					--gbytes;
+					continue;
+				}
+				/*
+				 * We don't hold the rep mutex, and may
+				 * miscount.
+				 */
+				rep->stat.st_nthrottles++;
+				type = REP_PAGE_MORE;
+				goto send;
+			}
+			bytes -= (msgdbt.size + sizeof(REP_CONTROL));
+		}
+send:
+		RPRINT(dbenv, rep, (dbenv, &mb,
+		    "sendpages: %s %lu, lsn [%lu][%lu]",
+		    (type == REP_PAGE ? "PAGE" :
+		    (type == REP_PAGE_MORE ? "PAGE_MORE" : "PAGE_FAIL")),
+		    (u_long)p, (u_long)lsn.file, (u_long)lsn.offset));
+		(void)__rep_send_message(dbenv, eid, type, &lsn, &msgdbt, 0);
+		/*
+		 * If we have REP_PAGE_FAIL we need to break before trying
+		 * to give the page back to mpool.  If we have REP_PAGE_MORE
+		 * we need to break this loop after giving the page back
+		 * to mpool.  Otherwise, with REP_PAGE, we keep going.
+		 */
+		if (type == REP_PAGE_FAIL)
+			break;
+		if (msgfp->type != DB_QUEUE || p == 0)
+			ret = __memp_fput(mpf, pagep, 0);
+#ifdef HAVE_QUEUE
+		else
+			/*
+			 * We don't need an #else for HAVE_QUEUE here because if
+			 * we're not compiled with queue, then we're guaranteed
+			 * to have set REP_PAGE_FAIL above.
+			 */
+			ret = __qam_fput(qdbp, p, pagep, 0);
+#endif
+		if (type == REP_PAGE_MORE)
+			break;
+	}
+err:
+	if (opened && (t_ret = __db_close(qdbp, NULL, DB_NOSYNC)) != 0 &&
+	    ret == 0)
+		ret = t_ret;
+	if (buf != NULL)
+		__os_free(dbenv, buf);
+	return (ret);
+}
+
+/*
+ * __rep_update_setup
+ *	Process and setup with this file information.
+ *
+ * PUBLIC: int __rep_update_setup __P((DB_ENV *, int, REP_CONTROL *, DBT *));
+ */
+int
+__rep_update_setup(dbenv, eid, rp, rec)
+	DB_ENV *dbenv;
+	int eid;
+	REP_CONTROL *rp;
+	DBT *rec;
+{
+	DB_LOG *dblp;
+	DB_LSN lsn;
+	DB_REP *db_rep;
+	DBT pagereq_dbt;
+	LOG *lp;
+	REGENV *renv;
+	REGINFO *infop;
+	REP *rep;
+	__rep_update_args *rup;
+	int ret;
+	u_int32_t count, infolen;
+	void *next;
+#ifdef DIAGNOSTIC
+	__rep_fileinfo_args *msgfp;
+	DB_MSGBUF mb;
+#endif
+
+	db_rep = dbenv->rep_handle;
+	rep = db_rep->region;
+	dblp = dbenv->lg_handle;
+	lp = dblp->reginfo.primary;
+	ret = 0;
+
+	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+	if (!F_ISSET(rep, REP_F_RECOVER_UPDATE)) {
+		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+		return (0);
+	}
+	F_CLR(rep, REP_F_RECOVER_UPDATE);
+	/*
+	 * We know we're the first to come in here due to the
+	 * REP_F_RECOVER_UPDATE flag.  REP_F_READY should not be set.
+	 */
+	DB_ASSERT(!F_ISSET(rep, REP_F_READY));
+	F_SET(rep, REP_F_RECOVER_PAGE);
+	/*
+	 * We do not clear REP_F_READY or rep->in_recovery in this code.
+	 * We'll eventually call the normal __rep_verify_match recovery
+	 * code and that will clear all the flags and allow others to
+	 * proceed.
+	 */
+	__rep_lockout(dbenv, db_rep, rep, 1);
+	/*
+	 * We need to update the timestamp and kill any open handles
+	 * on this client.  The files are changing completely.
+	 */
+	infop = dbenv->reginfo;
+	renv = infop->primary;
+	(void)time(&renv->rep_timestamp);
+
+	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+	MUTEX_LOCK(dbenv, db_rep->db_mutexp);
+	lp->wait_recs = rep->request_gap;
+	lp->rcvd_recs = 0;
+	ZERO_LSN(lp->ready_lsn);
+	ZERO_LSN(lp->waiting_lsn);
+	ZERO_LSN(lp->max_wait_lsn);
+	ZERO_LSN(lp->max_perm_lsn);
+	MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+	if ((ret = __rep_update_read(dbenv, rec->data, &next, &rup)) != 0)
+		goto err;
+	R_LOCK(dbenv, &dblp->reginfo);
+	lsn = lp->lsn;
+	R_UNLOCK(dbenv, &dblp->reginfo);
+
+	/*
+	 * We need to empty out any old log records that might be in the
+	 * temp database.
+	 */
+	if ((ret = __db_truncate(db_rep->rep_db, NULL, &count)) != 0)
+		goto err;
+
+	/*
+	 * If our log is before the master's beginning of log,
+	 * we need to request from the master's beginning.
+	 * If we have some log, we need the earlier of the
+	 * master's last checkpoint LSN or our current LSN.
+	 */
+	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+	if (log_compare(&lsn, &rup->first_lsn) < 0)
+		rep->first_lsn = rup->first_lsn;
+	else
+		rep->first_lsn = lsn;
+	rep->last_lsn = rp->lsn;
+	rep->nfiles = rup->num_files;
+	rep->curfile = 0;
+	rep->ready_pg = 0;
+	rep->npages = 0;
+	rep->waiting_pg = PGNO_INVALID;
+	rep->max_wait_pg = PGNO_INVALID;
+
+	__os_free(dbenv, rup);
+
+	RPRINT(dbenv, rep, (dbenv, &mb,
+	    "Update setup for %d files.", rep->nfiles));
+	RPRINT(dbenv, rep, (dbenv, &mb, "Update setup:  First LSN [%lu][%lu].",
+	    (u_long)rep->first_lsn.file, (u_long)rep->first_lsn.offset));
+	RPRINT(dbenv, rep, (dbenv, &mb, "Update setup:  Last LSN [%lu][%lu]",
+	    (u_long)rep->last_lsn.file, (u_long)rep->last_lsn.offset));
+
+	infolen = rec->size - sizeof(__rep_update_args);
+	if ((ret = __os_calloc(dbenv, 1, infolen, &rep->originfo)) != 0)
+		goto err;
+	memcpy(rep->originfo, next, infolen);
+	rep->finfo = rep->originfo;
+	if ((ret = __rep_fileinfo_read(dbenv,
+	    rep->finfo, &next, &rep->curinfo)) != 0) {
+		RPRINT(dbenv, rep, (dbenv, &mb,
+		    "Update setup: Fileinfo read: %s", db_strerror(ret)));
+		goto errmem1;
+	}
+	rep->nextinfo = next;
+
+#ifdef DIAGNOSTIC
+	msgfp = rep->curinfo;
+	DB_ASSERT(msgfp->pgno == 0);
+#endif
+
+	/*
+	 * We want to create/open our dbp to the database
+	 * where we'll keep our page information.
+	 */
+	if ((ret = __rep_client_dbinit(dbenv, 1, REP_PG)) != 0) {
+		RPRINT(dbenv, rep, (dbenv, &mb,
+		    "Update setup: Client_dbinit %s", db_strerror(ret)));
+		goto errmem;
+	}
+
+	/*
+	 * We should get file info 'ready to go' to avoid data copies.
+	 */
+	memset(&pagereq_dbt, 0, sizeof(pagereq_dbt));
+	pagereq_dbt.data = rep->finfo;
+	pagereq_dbt.size = (u_int32_t)((u_int8_t *)rep->nextinfo -
+	    (u_int8_t *)rep->finfo);
+
+	RPRINT(dbenv, rep, (dbenv, &mb,
+	    "Update PAGE_REQ file 0: pgsize %lu, maxpg %lu",
+	    (u_long)rep->curinfo->pgsize,
+	    (u_long)rep->curinfo->max_pgno));
+	/*
+	 * We set up pagereq_dbt as we went along.  Send it now.
+	 */
+	(void)__rep_send_message(dbenv, eid, REP_PAGE_REQ,
+	    NULL, &pagereq_dbt, 0);
+	if (0) {
+errmem:		__os_free(dbenv, rep->curinfo);
+errmem1:	__os_free(dbenv, rep->originfo);
+		rep->finfo = NULL;
+		rep->curinfo = NULL;
+		rep->originfo = NULL;
+	}
+err:
+	/*
+	 * If we get an error, we cannot leave ourselves in the
+	 * RECOVER_PAGE state because we have no file information.
+	 * That also means undo'ing the rep_lockout.
+	 * We need to move back to the RECOVER_UPDATE stage.
+	 */
+	if (ret != 0) {
+		RPRINT(dbenv, rep, (dbenv, &mb,
+		    "Update_setup: Error: Clear PAGE, set UPDATE again. %s",
+		    db_strerror(ret)));
+		F_CLR(rep, REP_F_RECOVER_PAGE | REP_F_READY);
+		rep->in_recovery = 0;
+		F_SET(rep, REP_F_RECOVER_UPDATE);
+	}
+	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+	return (ret);
+}
+
+/*
+ * __rep_page
+ *	Process a page message.
+ *
+ * PUBLIC: int __rep_page __P((DB_ENV *, int, REP_CONTROL *, DBT *));
+ */
+int
+__rep_page(dbenv, eid, rp, rec)
+	DB_ENV *dbenv;
+	int eid;
+	REP_CONTROL *rp;
+	DBT *rec;
+{
+
+	DB_REP *db_rep;
+	DBT key, data;
+	REP *rep;
+	__rep_fileinfo_args *msgfp;
+	db_recno_t recno;
+	int ret;
+	void *next;
+#ifdef DIAGNOSTIC
+	DB_MSGBUF mb;
+#endif
+
+	ret = 0;
+	db_rep = dbenv->rep_handle;
+	rep = db_rep->region;
+
+	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+	if (!F_ISSET(rep, REP_F_RECOVER_PAGE)) {
+		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+		return (0);
+	}
+	if ((ret = __rep_fileinfo_read(dbenv, rec->data, &next, &msgfp)) != 0) {
+		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+		return (ret);
+	}
+	RPRINT(dbenv, rep, (dbenv, &mb,
+	    "PAGE: Received page %lu from file %d",
+	    (u_long)msgfp->pgno, msgfp->filenum));
+	/*
+	 * Check if this page is from the file we're expecting.
+	 * This may be an old or delayed page message.
+	 */
+	/*
+	 * !!!
+	 * If we allow dbrename/dbremove on the master while a client
+	 * is updating, then we'd have to verify the file's uid here too.
+	 */
+	if (msgfp->filenum != rep->curfile) {
+		RPRINT(dbenv, rep,
+		    (dbenv, &mb, "Msg file %d != curfile %d",
+		    msgfp->filenum, rep->curfile));
+		goto err;
+	}
+	/*
+	 * We want to create/open our dbp to the database
+	 * where we'll keep our page information.
+	 */
+	if ((ret = __rep_client_dbinit(dbenv, 1, REP_PG)) != 0)
+		goto err;
+
+	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+	memset(&key, 0, sizeof(key));
+	memset(&data, 0, sizeof(data));
+	recno = (db_recno_t)(msgfp->pgno + 1);
+	key.data = &recno;
+	key.ulen = key.size = sizeof(db_recno_t);
+	key.flags = DB_DBT_USERMEM;
+
+	/*
+	 * If we already have this page, then we don't want to bother
+	 * rewriting it into the file.  Otherwise, any other error
+	 * we want to return.
+	 */
+	ret = __db_put(rep->file_dbp, NULL, &key, &data, DB_NOOVERWRITE);
+	if (ret == DB_KEYEXIST) {
+		RPRINT(dbenv, rep, (dbenv, &mb,
+		    "PAGE: Received duplicate page %lu from file %d",
+		    (u_long)msgfp->pgno, msgfp->filenum));
+		rep->stat.st_pg_duplicated++;
+		ret = 0;
+		goto err_nolock;
+	}
+	if (ret != 0)
+		goto err_nolock;
+
+	RPRINT(dbenv, rep, (dbenv, &mb,
+	    "PAGE: Write page %lu into mpool", (u_long)msgfp->pgno));
+	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+	/*
+	 * We put the page in the database file itself.
+	 */
+	ret = __rep_write_page(dbenv, rep, msgfp);
+	if (ret != 0) {
+		/*
+		 * We got an error storing the page, therefore, we need
+		 * remove this page marker from the page database too.
+		 * !!!
+		 * I'm ignoring errors from the delete because we want to
+		 * return the original error.  If we cannot write the page
+		 * and we cannot delete the item we just put, what should
+		 * we do?  Panic the env and return DB_RUNRECOVERY?
+		 */
+		(void)__db_del(rep->file_dbp, NULL, &key, 0);
+		goto err;
+	}
+	rep->stat.st_pg_records++;
+	rep->npages++;
+
+	/*
+	 * Now check the LSN on the page and save it if it is later
+	 * than the one we have.
+	 */
+	if (log_compare(&rp->lsn, &rep->last_lsn) > 0)
+		rep->last_lsn = rp->lsn;
+
+	/*
+	 * We've successfully written the page.  Now we need to see if
+	 * we're done with this file.  __rep_filedone will check if we
+	 * have all the pages expected and if so, set up for the next
+	 * file and send out a page request for the next file's pages.
+	 */
+	ret = __rep_filedone(dbenv, eid, rep, msgfp, rp->rectype);
+
+err:
+	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+err_nolock:
+	__os_free(dbenv, msgfp);
+	return (ret);
+}
+
+/*
+ * __rep_page_fail
+ *	Process a page fail message.
+ *
+ * PUBLIC: int __rep_page_fail __P((DB_ENV *, int, DBT *));
+ */
+int
+__rep_page_fail(dbenv, eid, rec)
+	DB_ENV *dbenv;
+	int eid;
+	DBT *rec;
+{
+
+	DB_REP *db_rep;
+	REP *rep;
+	__rep_fileinfo_args *msgfp, *rfp;
+	int ret;
+	void *next;
+#ifdef DIAGNOSTIC
+	DB_MSGBUF mb;
+#endif
+
+	ret = 0;
+	db_rep = dbenv->rep_handle;
+	rep = db_rep->region;
+
+	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+	if (!F_ISSET(rep, REP_F_RECOVER_PAGE)) {
+		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+		return (0);
+	}
+	if ((ret = __rep_fileinfo_read(dbenv, rec->data, &next, &msgfp)) != 0) {
+		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+		return (ret);
+	}
+	/*
+	 * Check if this page is from the file we're expecting.
+	 * This may be an old or delayed page message.
+	 */
+	/*
+	 * !!!
+	 * If we allow dbrename/dbremove on the master while a client
+	 * is updating, then we'd have to verify the file's uid here too.
+	 */
+	if (msgfp->filenum != rep->curfile) {
+		RPRINT(dbenv, rep, (dbenv, &mb, "Msg file %d != curfile %d",
+		    msgfp->filenum, rep->curfile));
+		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+		return (0);
+	}
+	rfp = rep->curinfo;
+	if (rfp->type != DB_QUEUE)
+		--rfp->max_pgno;
+	else {
+		/*
+		 * Queue is special.  Pages at the beginning of the queue
+		 * may disappear, as well as at the end.  Use msgfp->pgno
+		 * to adjust accordingly.
+		 */
+		RPRINT(dbenv, rep, (dbenv, &mb,
+	    "page_fail: BEFORE page %lu failed. ready %lu, max %lu, npages %d",
+		    (u_long)msgfp->pgno, (u_long)rep->ready_pg,
+		    (u_long)rfp->max_pgno, rep->npages));
+		if (msgfp->pgno == rfp->max_pgno)
+			--rfp->max_pgno;
+		if (msgfp->pgno >= rep->ready_pg) {
+			rep->ready_pg = msgfp->pgno + 1;
+			rep->npages = rep->ready_pg;
+		}
+		RPRINT(dbenv, rep, (dbenv, &mb,
+	    "page_fail: AFTER page %lu failed. ready %lu, max %lu, npages %d",
+		    (u_long)msgfp->pgno, (u_long)rep->ready_pg,
+		    (u_long)rfp->max_pgno, rep->npages));
+	}
+	/*
+	 * We've lowered the number of pages expected.  It is possible that
+	 * this was the last page we were expecting.  Now we need to see if
+	 * we're done with this file.  __rep_filedone will check if we have
+	 * all the pages expected and if so, set up for the next file and
+	 * send out a page request for the next file's pages.
+	 */
+	ret = __rep_filedone(dbenv, eid, rep, msgfp, REP_PAGE_FAIL);
+	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+	return (ret);
+}
+
+/*
+ * __rep_write_page -
+ *	Write this page into a database.
+ */
+static int
+__rep_write_page(dbenv, rep, msgfp)
+	DB_ENV *dbenv;
+	REP *rep;
+	__rep_fileinfo_args *msgfp;
+{
+	__rep_fileinfo_args *rfp;
+	DB_FH *rfh;
+	int ret;
+	void *dst;
+	char *real_name;
+
+	real_name = NULL;
+
+	/*
+	 * If this is the first page we're putting in this database, we need
+	 * to create the mpool file.  Otherwise call memp_fget to create the
+	 * page in mpool.  Then copy the data to the page, and memp_fput the
+	 * page to give it back to mpool.
+	 *
+	 * We need to create the file, removing any existing file and associate
+	 * the correct file ID with the new one.
+	 */
+	if (rep->file_mpf == NULL) {
+		rfp = rep->curinfo;
+
+		if (!F_ISSET(rfp, DB_AM_INMEM)) {
+			if ((ret = __db_appname(dbenv, DB_APP_DATA,
+			    rfp->info.data, 0, NULL, &real_name)) != 0)
+				goto err;
+			/*
+			 * Calling memp_nameop will both purge any matching
+			 * fileid from mpool and unlink it on disk.
+			 */
+			if ((ret = __memp_nameop(dbenv,
+			    rfp->uid.data, NULL, real_name, NULL)) != 0)
+				goto err;
+			/*
+			 * Create the file on disk.  We'll be putting the data
+			 * into the file via mpool.
+			 */
+			if ((ret = __os_open(dbenv, real_name,
+			    DB_OSO_CREATE, dbenv->db_mode, &rfh)) == 0)
+				ret = __os_closehandle(dbenv, rfh);
+			if (ret != 0)
+				goto err;
+		}
+
+		if ((ret =
+		    __rep_mpf_open(dbenv, &rep->file_mpf, rep->curinfo)) != 0)
+			goto err;
+	}
+	/*
+	 * Handle queue specially.  If we're a QUEUE database, we need to
+	 * use the __qam_fget/put calls.  We need to use rep->queue_dbp for
+	 * that.  That dbp is opened after getting the metapage for the
+	 * queue database.  Since the meta-page is always in the queue file,
+	 * we'll use the normal path for that first page.  After that we
+	 * can assume the dbp is opened.
+	 */
+	if (msgfp->type == DB_QUEUE && msgfp->pgno != 0) {
+#ifdef HAVE_QUEUE
+		if ((ret = __qam_fget(
+		    rep->queue_dbp, &msgfp->pgno, DB_MPOOL_CREATE, &dst)) != 0)
+#else
+		if ((ret = __db_no_queue_am(dbenv)) != 0)
+#endif
+			goto err;
+	} else if ((ret = __memp_fget(
+		    rep->file_mpf, &msgfp->pgno, DB_MPOOL_CREATE, &dst)) != 0)
+			goto err;
+
+	memcpy(dst, msgfp->info.data, msgfp->pgsize);
+	if (msgfp->type != DB_QUEUE || msgfp->pgno == 0)
+		ret = __memp_fput(rep->file_mpf, dst, DB_MPOOL_DIRTY);
+#ifdef HAVE_QUEUE
+	else
+		ret = __qam_fput(rep->queue_dbp, msgfp->pgno, dst,
+		    DB_MPOOL_DIRTY);
+#endif
+
+err:	if (real_name != NULL)
+		 __os_free(dbenv, real_name);
+	return (ret);
+}
+
+/*
+ * __rep_page_gap -
+ *	After we've put the page into the database, we need to check if
+ *	we have a page gap and whether we need to request pages.
+ */
+static int
+__rep_page_gap(dbenv, rep, msgfp, type)
+	DB_ENV *dbenv;
+	REP *rep;
+	__rep_fileinfo_args *msgfp;
+	u_int32_t type;
+{
+	DB_LOG *dblp;
+	DB_REP *db_rep;
+	DBT data, key;
+	LOG *lp;
+	__rep_fileinfo_args *rfp;
+	db_recno_t recno;
+	int ret;
+#ifdef DIAGNOSTIC
+	DB_MSGBUF mb;
+#endif
+
+	db_rep = dbenv->rep_handle;
+	ret = 0;
+	dblp = dbenv->lg_handle;
+	lp = dblp->reginfo.primary;
+
+	/*
+	 * We've successfully put this page into our file.
+	 * Now we need to account for it and re-request new pages
+	 * if necessary.
+	 */
+	/*
+	 * We already hold the rep mutex, but we also need the db mutex.
+	 * So we need to drop it, acquire both in the right order and
+	 * then recheck the state of the world.
+	 */
+	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+	MUTEX_LOCK(dbenv, db_rep->db_mutexp);
+	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+	rfp = rep->curinfo;
+
+	/*
+	 * Make sure we're still talking about the same file.
+	 * If not, we're done here.
+	 */
+	if (rfp->filenum != msgfp->filenum) {
+		ret = DB_REP_PAGEDONE;
+		goto err;
+	}
+
+	/*
+	 * We have 3 possible states:
+	 * 1.  We receive a page we already have.
+	 *	msg pgno < ready pgno
+	 * 2.  We receive a page that is beyond a gap.
+	 *	msg pgno > ready pgno
+	 * 3.  We receive the page we're expecting.
+	 *	msg pgno == ready pgno
+	 */
+	/*
+	 * State 1.  This should not happen because this function
+	 * should only be called once per page received because we
+	 * check for DB_KEY_EXIST when we save the page information.
+	 */
+	DB_ASSERT(msgfp->pgno >= rep->ready_pg);
+
+	/*
+	 * State 2.  This page is beyond the page we're expecting.
+	 * We need to update waiting_pg if this page is less than
+	 * (earlier) the current waiting_pg.  There is nothing
+	 * to do but see if we need to request.
+	 */
+	RPRINT(dbenv, rep, (dbenv, &mb,
+    "PAGE_GAP: pgno %lu, max_pg %lu ready %lu, waiting %lu max_wait %lu",
+	    (u_long)msgfp->pgno, (u_long)rfp->max_pgno, (u_long)rep->ready_pg,
+	    (u_long)rep->waiting_pg, (u_long)rep->max_wait_pg));
+	if (msgfp->pgno > rep->ready_pg) {
+		if (rep->waiting_pg == PGNO_INVALID ||
+		    msgfp->pgno < rep->waiting_pg)
+			rep->waiting_pg = msgfp->pgno;
+	} else {
+		/*
+		 * We received the page we're expecting.
+		 */
+		rep->ready_pg++;
+		lp->rcvd_recs = 0;
+		while (ret == 0 && rep->ready_pg == rep->waiting_pg) {
+			/*
+			 * If we get here we know we just filled a gap.
+			 */
+			lp->wait_recs = 0;
+			lp->rcvd_recs = 0;
+			rep->max_wait_pg = PGNO_INVALID;
+			/*
+			 * We need to walk the recno database looking for the
+			 * next page we need or expect.
+			 */
+			memset(&key, 0, sizeof(key));
+			memset(&data, 0, sizeof(data));
+			recno = (db_recno_t)rep->ready_pg;
+			key.data = &recno;
+			key.ulen = key.size = sizeof(db_recno_t);
+			key.flags = DB_DBT_USERMEM;
+			ret = __db_get(rep->file_dbp, NULL, &key, &data, 0);
+			if (ret == DB_NOTFOUND || ret == DB_KEYEMPTY)
+				break;
+			else if (ret != 0)
+				goto err;
+			rep->ready_pg++;
+		}
+	}
+
+	/*
+	 * If we filled a gap and now have the entire file, there's
+	 * nothing to do.  We're done when ready_pg is > max_pgno
+	 * because ready_pg is larger than the last page we received.
+	 */
+	if (rep->ready_pg > rfp->max_pgno)
+		goto err;
+
+	/*
+	 * Check if we need to ask for more pages.
+	 */
+	if ((rep->waiting_pg != PGNO_INVALID &&
+	    rep->ready_pg != rep->waiting_pg) || type == REP_PAGE_MORE) {
+		/*
+		 * We got a page but we may still be waiting for more.
+		 */
+		if (lp->wait_recs == 0) {
+			/*
+			 * This is a new gap. Initialize the number of
+			 * records that we should wait before requesting
+			 * that it be resent.  We grab the limits out of
+			 * the rep without the mutex.
+			 */
+			lp->wait_recs = rep->request_gap;
+			lp->rcvd_recs = 0;
+			rep->max_wait_pg = PGNO_INVALID;
+		}
+		/*
+		 * If we got REP_PAGE_MORE we always want to ask for more.
+		 */
+		if ((__rep_check_doreq(dbenv, rep) || type == REP_PAGE_MORE) &&
+		    ((ret = __rep_pggap_req(dbenv, rep, rfp,
+		    type == REP_PAGE_MORE)) != 0))
+			goto err;
+	} else {
+		lp->wait_recs = 0;
+		rep->max_wait_pg = PGNO_INVALID;
+	}
+
+err:
+	MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+	return (ret);
+}
+
+/*
+ * __rep_filedone -
+ *	We need to check if we're done with the current file after
+ *	processing the current page.  Stat the database to see if
+ *	we have all the pages.  If so, we need to clean up/close
+ *	this one, set up for the next one, and ask for its pages,
+ *	or if this is the last file, request the log records and
+ *	move to the REP_RECOVER_LOG state.
+ */
+static int
+__rep_filedone(dbenv, eid, rep, msgfp, type)
+	DB_ENV *dbenv;
+	int eid;
+	REP *rep;
+	__rep_fileinfo_args *msgfp;
+	u_int32_t type;
+{
+	DBT dbt;
+	DB_REP *db_rep;
+	__rep_fileinfo_args *rfp;
+	int ret;
+#ifdef DIAGNOSTIC
+	DB_MSGBUF mb;
+#endif
+
+	db_rep = dbenv->rep_handle;
+	/*
+	 * We've put our page, now we need to do any gap processing
+	 * that might be needed to re-request pages.
+	 */
+	ret = __rep_page_gap(dbenv, rep, msgfp, type);
+	/*
+	 * The world changed while we were doing gap processing.
+	 * We're done here.
+	 */
+	if (ret == DB_REP_PAGEDONE)
+		return (0);
+
+	rfp = rep->curinfo;
+	/*
+	 * max_pgno is 0-based and npages is 1-based, so we don't have
+	 * all the pages until npages is > max_pgno.
+	 */
+	RPRINT(dbenv, rep, (dbenv, &mb, "FILEDONE: have %lu pages. Need %lu.",
+	    (u_long)rep->npages, (u_long)rfp->max_pgno + 1));
+	if (rep->npages <= rfp->max_pgno)
+		return (0);
+
+	/*
+	 * If we're queue and we think we have all the pages for this file,
+	 * we need to do special queue processing.  Queue is handled in
+	 * several stages.
+	 */
+	if (rfp->type == DB_QUEUE &&
+	    ((ret = __rep_queue_filedone(dbenv, rep, rfp)) !=
+	    DB_REP_PAGEDONE))
+		return (ret);
+	/*
+	 * We have all the pages for this file.  We need to:
+	 * 1.  Close up the file data pointer we used.
+	 * 2.  Close/reset the page database.
+	 * 3.  Check if we have all file data.  If so, request logs.
+	 * 4.  If not, set curfile to next file and request its pages.
+	 */
+	/*
+	 * 1.  Close up the file data pointer we used.
+	 */
+	if (rep->file_mpf != NULL) {
+		ret = __memp_fclose(rep->file_mpf, 0);
+		rep->file_mpf = NULL;
+		if (ret != 0)
+			goto err;
+	}
+
+	/*
+	 * 2.  Close/reset the page database.
+	 */
+	ret = __db_close(rep->file_dbp, NULL, DB_NOSYNC);
+	rep->file_dbp = NULL;
+	if (ret != 0)
+		goto err;
+
+	/*
+	 * 3.  Check if we have all file data.  If so, request logs.
+	 */
+	__os_free(dbenv, rep->curinfo);
+	if (++rep->curfile == rep->nfiles) {
+		RPRINT(dbenv, rep, (dbenv, &mb,
+		    "FILEDONE: have %d files.  RECOVER_LOG now", rep->nfiles));
+		/*
+		 * Move to REP_RECOVER_LOG state.
+		 * Request logs.
+		 */
+		__os_free(dbenv, rep->originfo);
+		/*
+		 * We need to do a sync here so that any later opens
+		 * can find the file and file id.  We need to do it
+		 * before we clear REP_F_RECOVER_PAGE so that we do not
+		 * try to flush the log.
+		 */
+		if ((ret = __memp_sync(dbenv, NULL)) != 0)
+			goto err;
+		F_CLR(rep, REP_F_RECOVER_PAGE);
+		F_SET(rep, REP_F_RECOVER_LOG);
+		memset(&dbt, 0, sizeof(dbt));
+		dbt.data = &rep->last_lsn;
+		dbt.size = sizeof(rep->last_lsn);
+		RPRINT(dbenv, rep, (dbenv, &mb,
+		    "FILEDONE: LOG_REQ from LSN [%lu][%lu] to [%lu][%lu]",
+		    (u_long)rep->first_lsn.file, (u_long)rep->first_lsn.offset,
+		    (u_long)rep->last_lsn.file, (u_long)rep->last_lsn.offset));
+		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+		if ((ret = __rep_log_setup(dbenv, rep)) != 0)
+			goto err;
+		(void)__rep_send_message(dbenv, eid,
+		    REP_LOG_REQ, &rep->first_lsn, &dbt, 0);
+		MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+		return (0);
+	}
+
+	/*
+	 * 4.  If not, set curinfo to next file and request its pages.
+	 */
+	rep->finfo = rep->nextinfo;
+	if ((ret = __rep_fileinfo_read(dbenv, rep->finfo, &rep->nextinfo,
+	    &rep->curinfo)) != 0)
+		goto err;
+	DB_ASSERT(rep->curinfo->pgno == 0);
+	rep->ready_pg = 0;
+	rep->npages = 0;
+	rep->waiting_pg = PGNO_INVALID;
+	rep->max_wait_pg = PGNO_INVALID;
+	memset(&dbt, 0, sizeof(dbt));
+	RPRINT(dbenv, rep, (dbenv, &mb,
+	    "FILEDONE: Next file %d.  Request pages 0 to %lu",
+	    rep->curinfo->filenum, (u_long)rep->curinfo->max_pgno));
+	dbt.data = rep->finfo;
+	dbt.size = (u_int32_t)((u_int8_t *)rep->nextinfo -
+	    (u_int8_t *)rep->finfo);
+	(void)__rep_send_message(dbenv, eid, REP_PAGE_REQ,
+	    NULL, &dbt, 0);
+err:
+	return (ret);
+}
+
+/*
+ * __rep_mpf_open -
+ *	Create and open the mpool file for a database.
+ *	Used by both master and client to bring files into mpool.
+ */
+static int
+__rep_mpf_open(dbenv, mpfp, rfp)
+	DB_ENV *dbenv;
+	DB_MPOOLFILE **mpfp;
+	__rep_fileinfo_args *rfp;
+{
+	DB db;
+	int ret;
+
+	if ((ret = __memp_fcreate(dbenv, mpfp)) != 0)
+		return (ret);
+
+	/*
+	 * We need a dbp to pass into to __db_dbenv_mpool.  Set up
+	 * only the parts that it needs.
+	 */
+	db.type = rfp->type;
+	db.pgsize = (u_int32_t)rfp->pgsize;
+	memcpy(db.fileid, rfp->uid.data, DB_FILE_ID_LEN);
+	db.flags = rfp->flags;
+	db.mpf = *mpfp;
+	db.dbenv = dbenv;
+	if ((ret = __db_dbenv_mpool(&db, rfp->info.data, 0)) != 0) {
+		(void)__memp_fclose(*mpfp, 0);
+		*mpfp = NULL;
+	}
+	return (ret);
+}
+
+/*
+ * __rep_pggap_req -
+ *	Request a page gap.  Assumes the caller holds the rep_mutexp.
+ *
+ * PUBLIC: int __rep_pggap_req __P((DB_ENV *, REP *, __rep_fileinfo_args *,
+ * PUBLIC:    int));
+ */
+int
+__rep_pggap_req(dbenv, rep, reqfp, moregap)
+	DB_ENV *dbenv;
+	REP *rep;
+	__rep_fileinfo_args *reqfp;
+	int moregap;
+{
+	DBT max_pg_dbt;
+	__rep_fileinfo_args *tmpfp;
+	size_t len;
+	int alloc, ret;
+
+	ret = 0;
+	alloc = 0;
+	/*
+	 * There is a window where we have to set REP_RECOVER_PAGE when
+	 * we receive the update information to transition from getting
+	 * file information to getting page information.  However, that
+	 * thread does release and then reacquire mutexes.  So, we might
+	 * try re-requesting before the original thread can get curinfo
+	 * setup.  If curinfo isn't set up there is nothing to do.
+	 */
+	if (rep->curinfo == NULL)
+		return (0);
+	if (reqfp == NULL) {
+		if ((ret = __rep_finfo_alloc(dbenv, rep->curinfo, &tmpfp)) != 0)
+			return (ret);
+		alloc = 1;
+	} else
+		tmpfp = reqfp;
+
+	/*
+	 * If we've never requested this page, then
+	 * request everything between it and the first
+	 * page we have.  If we have requested this page
+	 * then only request this record, not the entire gap.
+	 */
+	memset(&max_pg_dbt, 0, sizeof(max_pg_dbt));
+	tmpfp->pgno = rep->ready_pg;
+	max_pg_dbt.data = rep->finfo;
+	max_pg_dbt.size = (u_int32_t)((u_int8_t *)rep->nextinfo -
+	    (u_int8_t *)rep->finfo);
+	if (rep->max_wait_pg == PGNO_INVALID || moregap) {
+		/*
+		 * Request the gap - set max to waiting_pg - 1 or if
+		 * there is no waiting_pg, just ask for one.
+		 */
+		if (rep->waiting_pg == PGNO_INVALID) {
+			if (moregap)
+				rep->max_wait_pg = rep->curinfo->max_pgno;
+			else
+				rep->max_wait_pg = rep->ready_pg;
+		} else
+			rep->max_wait_pg = rep->waiting_pg - 1;
+		tmpfp->max_pgno = rep->max_wait_pg;
+	} else {
+		/*
+		 * Request 1 page - set max to ready_pg.
+		 */
+		rep->max_wait_pg = rep->ready_pg;
+		tmpfp->max_pgno = rep->ready_pg;
+	}
+	if (rep->master_id != DB_EID_INVALID) {
+		rep->stat.st_pg_requested++;
+		/*
+		 * We need to request the pages, but we need to get the
+		 * new info into rep->finfo.  Assert that the sizes never
+		 * change.  The only thing this should do is change
+		 * the pgno field.  Everything else remains the same.
+		 */
+		ret = __rep_fileinfo_buf(rep->finfo, max_pg_dbt.size, &len,
+		    tmpfp->pgsize, tmpfp->pgno, tmpfp->max_pgno,
+		    tmpfp->filenum, tmpfp->id, tmpfp->type,
+		    tmpfp->flags, &tmpfp->uid, &tmpfp->info);
+		DB_ASSERT(len == max_pg_dbt.size);
+		(void)__rep_send_message(dbenv, rep->master_id,
+		    REP_PAGE_REQ, NULL, &max_pg_dbt, 0);
+	} else
+		(void)__rep_send_message(dbenv, DB_EID_BROADCAST,
+		    REP_MASTER_REQ, NULL, NULL, 0);
+
+	if (alloc)
+		__os_free(dbenv, tmpfp);
+	return (ret);
+}
+
+/*
+ * __rep_loggap_req -
+ *	Request a log gap.  Assumes the caller holds the db_mutexp.
+ *
+ * PUBLIC: void __rep_loggap_req __P((DB_ENV *, REP *, DB_LSN *, int));
+ */
+void
+__rep_loggap_req(dbenv, rep, lsnp, moregap)
+	DB_ENV *dbenv;
+	REP *rep;
+	DB_LSN *lsnp;
+	int moregap;
+{
+	DB_LOG *dblp;
+	DBT max_lsn_dbt, *max_lsn_dbtp;
+	DB_LSN next_lsn;
+	LOG *lp;
+
+	dblp = dbenv->lg_handle;
+	lp = dblp->reginfo.primary;
+	R_LOCK(dbenv, &dblp->reginfo);
+	next_lsn = lp->lsn;
+	R_UNLOCK(dbenv, &dblp->reginfo);
+
+	if (moregap ||
+	    (lsnp != NULL &&
+	    (log_compare(lsnp, &lp->max_wait_lsn) == 0 ||
+	    IS_ZERO_LSN(lp->max_wait_lsn)))) {
+		/*
+		 * We need to ask for the gap.  Either we never asked
+		 * for records before, or we asked for a single record
+		 * and received it.
+		 */
+		lp->max_wait_lsn = lp->waiting_lsn;
+		memset(&max_lsn_dbt, 0, sizeof(max_lsn_dbt));
+		max_lsn_dbt.data = &lp->waiting_lsn;
+		max_lsn_dbt.size = sizeof(lp->waiting_lsn);
+		max_lsn_dbtp = &max_lsn_dbt;
+	} else {
+		max_lsn_dbtp = NULL;
+		lp->max_wait_lsn = next_lsn;
+	}
+	if (rep->master_id != DB_EID_INVALID) {
+		rep->stat.st_log_requested++;
+		(void)__rep_send_message(dbenv, rep->master_id,
+		    REP_LOG_REQ, &next_lsn, max_lsn_dbtp, 0);
+	} else
+		(void)__rep_send_message(dbenv, DB_EID_BROADCAST,
+		    REP_MASTER_REQ, NULL, NULL, 0);
+
+	return;
+}
+
+/*
+ * __rep_finfo_alloc -
+ *	Allocate and initialize a fileinfo structure.
+ *
+ * PUBLIC: int __rep_finfo_alloc __P((DB_ENV *, __rep_fileinfo_args *,
+ * PUBLIC:    __rep_fileinfo_args **));
+ */
+int
+__rep_finfo_alloc(dbenv, rfpsrc, rfpp)
+	DB_ENV *dbenv;
+	__rep_fileinfo_args *rfpsrc, **rfpp;
+{
+	size_t size;
+	int ret;
+
+	size = sizeof(__rep_fileinfo_args) + rfpsrc->uid.size +
+	    rfpsrc->info.size;
+	if ((ret = __os_malloc(dbenv, size, rfpp)) != 0)
+		return (ret);
+
+	memcpy(*rfpp, rfpsrc, size);
+	return (ret);
+}
+
+/*
+ * __rep_log_setup -
+ *	We know our first LSN and need to reset the log subsystem
+ *	to get our logs set up for the proper file.
+ */
+static int
+__rep_log_setup(dbenv, rep)
+	DB_ENV *dbenv;
+	REP *rep;
+{
+	DB_LOG *dblp;
+	DB_LSN lsn;
+	u_int32_t fnum;
+	int ret;
+	char *name;
+
+	dblp = dbenv->lg_handle;
+	/*
+	 * Set up the log starting at the file number of the first LSN we
+	 * need to get from the master.
+	 */
+	if ((ret = __log_newfile(dblp, &lsn, rep->first_lsn.file)) == 0) {
+		/*
+		 * We do know we want to start this client's log at
+		 * log file 'first_lsn.file'.  So we want to forcibly
+		 * remove any log files earlier than that number.
+		 * We don't know what might be in any earlier log files
+		 * so we cannot just use __log_autoremove.
+		 */
+		for (fnum = 1; fnum < rep->first_lsn.file; fnum++) {
+			if ((ret = __log_name(dblp, fnum, &name, NULL, 0)) != 0)
+				goto err;
+			(void)__os_unlink(dbenv, name);
+			__os_free(dbenv, name);
+		}
+	}
+err:
+	return (ret);
+}
+
+/*
+ * __rep_queue_filedone -
+ *	Determine if we're really done getting the pages for a queue file.
+ *	Queue is handled in several steps.
+ *	1.  First we get the meta page only.
+ *	2.  We use the meta-page information to figure out first and last
+ *	    page numbers (and if queue wraps, first can be > last.
+ *	3.  If first < last, we do a REP_PAGE_REQ for all pages.
+ *	4.  If first > last, we REP_PAGE_REQ from first -> max page number.
+ *	    Then we'll ask for page 1 -> last.
+ *
+ * This function can return several things:
+ *	DB_REP_PAGEDONE - if we're done with this file.
+ *	0 - if we're not doen with this file.
+ *	error - if we get an error doing some operations.
+ *
+ * This function will open a dbp handle to the queue file.  This is needed
+ * by most of the QAM macros.  We'll open it on the first pass through
+ * here and we'll close it whenever we decide we're done.
+ */
+static int
+__rep_queue_filedone(dbenv, rep, rfp)
+	DB_ENV *dbenv;
+	REP *rep;
+	__rep_fileinfo_args *rfp;
+{
+#ifndef HAVE_QUEUE
+	COMPQUIET(rep, NULL);
+	COMPQUIET(rfp, NULL);
+	return (__db_no_queue_am(dbenv));
+#else
+	db_pgno_t first, last;
+	u_int32_t flags;
+	int empty, ret, t_ret;
+#ifdef DIAGNOSTIC
+	DB_MSGBUF mb;
+#endif
+
+	ret = 0;
+	if (rep->queue_dbp == NULL) {
+		/*
+		 * We need to do a sync here so that the open
+		 * can find the file and file id.
+		 */
+		if ((ret = __memp_sync(dbenv, NULL)) != 0)
+			goto out;
+		if ((ret = db_create(&rep->queue_dbp, dbenv,
+		    DB_REP_CREATE)) != 0)
+			goto out;
+		flags = DB_NO_AUTO_COMMIT |
+		    (F_ISSET(dbenv, DB_ENV_THREAD) ? DB_THREAD : 0);
+		if ((ret = __db_open(rep->queue_dbp, NULL, rfp->info.data,
+		    NULL, DB_QUEUE, flags, 0, PGNO_BASE_MD)) != 0)
+			goto out;
+	}
+	if ((ret = __queue_pageinfo(rep->queue_dbp,
+	    &first, &last, &empty, 0, 0)) != 0)
+		goto out;
+	RPRINT(dbenv, rep, (dbenv, &mb,
+	    "Queue fileinfo: first %lu, last %lu, empty %d",
+	    (u_long)first, (u_long)last, empty));
+	/*
+	 * We can be at the end of 3 possible states.
+	 * 1.  We have received the meta-page and now need to get the
+	 *     rest of the pages in the database.
+	 * 2.  We have received from first -> max_pgno.  We might be done,
+	 *     or we might need to ask for wrapped pages.
+	 * 3.  We have received all pages in the file.  We're done.
+	 */
+	if (rfp->max_pgno == 0) {
+		/*
+		 * We have just received the meta page.  Set up the next
+		 * pages to ask for and check if the file is empty.
+		 */
+		if (empty)
+			goto out;
+		if (first > last) {
+			rfp->max_pgno =
+			    QAM_RECNO_PAGE(rep->queue_dbp, UINT32_MAX);
+		} else
+			rfp->max_pgno = last;
+		RPRINT(dbenv, rep, (dbenv, &mb,
+		    "Queue fileinfo: First req: first %lu, last %lu",
+		    (u_long)first, (u_long)rfp->max_pgno));
+		goto req;
+	} else if (rfp->max_pgno != last) {
+		/*
+		 * If max_pgno != last that means we're dealing with a
+		 * wrapped situation.  Request next batch of pages.
+		 * Set npages to 1 because we already have page 0, the
+		 * meta-page, now we need pages 1-max_pgno.
+		 */
+		first = 1;
+		rfp->max_pgno = last;
+		RPRINT(dbenv, rep, (dbenv, &mb,
+		    "Queue fileinfo: Wrap req: first %lu, last %lu",
+		    (u_long)first, (u_long)last));
+req:
+		/*
+		 * Since we're simulating a "gap" to resend new PAGE_REQ
+		 * for this file, we need to set waiting page to last + 1
+		 * so that we'll ask for all from ready_pg -> last.
+		 */
+		rep->npages = first;
+		rep->ready_pg = first;
+		rep->waiting_pg = rfp->max_pgno + 1;
+		rep->max_wait_pg = PGNO_INVALID;
+		ret = __rep_pggap_req(dbenv, rep, rfp, 0);
+		return (ret);
+	}
+	/*
+	 * max_pgno == last
+	 * If we get here, we have all the pages we need.
+	 * Close the dbp and return.
+	 */
+out:
+	if (rep->queue_dbp != NULL &&
+	    (t_ret = __db_close(rep->queue_dbp, NULL, DB_NOSYNC)) != 0 &&
+	    ret == 0)
+		ret = t_ret;
+	rep->queue_dbp = NULL;
+	if (ret == 0)
+		ret = DB_REP_PAGEDONE;
+	return (ret);
+#endif
+}
diff --git a/storage/bdb/rep/rep_method.c b/storage/bdb/rep/rep_method.c
index 6773a537f4faae8f671ae1c13407076a853d30fb..9e83dd7295097b624712d1dbf727499cd9d38767 100644
--- a/storage/bdb/rep/rep_method.c
+++ b/storage/bdb/rep/rep_method.c
@@ -1,14 +1,13 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
+ * Copyright (c) 2001-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: rep_method.c,v 1.167 2004/10/07 17:20:12 bostic Exp $
  */
-#include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: rep_method.c,v 1.78 2002/09/10 12:58:07 bostic Exp $";
-#endif /* not lint */
+#include "db_config.h"
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
@@ -19,58 +18,58 @@ static const char revid[] = "$Id: rep_method.c,v 1.78 2002/09/10 12:58:07 bostic
 
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
+#endif
+
+#ifdef HAVE_RPC
+#include "db_server.h"
 #endif
 
 #include "db_int.h"
 #include "dbinc/db_page.h"
-#include "dbinc/db_am.h"
+#include "dbinc/btree.h"
 #include "dbinc/log.h"
-#include "dbinc/rep.h"
 #include "dbinc/txn.h"
 
 #ifdef HAVE_RPC
-#include "dbinc_auto/db_server.h"
 #include "dbinc_auto/rpc_client_ext.h"
 #endif
 
 static int __rep_abort_prepared __P((DB_ENV *));
 static int __rep_bt_cmp __P((DB *, const DBT *, const DBT *));
-static int __rep_client_dbinit __P((DB_ENV *, int));
-static int __rep_elect __P((DB_ENV *, int, int, u_int32_t, int *));
-static int __rep_elect_init __P((DB_ENV *, DB_LSN *, int, int, int, int *));
+static int __rep_elect
+	       __P((DB_ENV *, int, int, int, u_int32_t, int *, u_int32_t));
+static int __rep_elect_init
+	       __P((DB_ENV *, DB_LSN *, int, int, int, int *, u_int32_t *));
 static int __rep_flush __P((DB_ENV *));
 static int __rep_restore_prepared __P((DB_ENV *));
+static int __rep_get_limit __P((DB_ENV *, u_int32_t *, u_int32_t *));
 static int __rep_set_limit __P((DB_ENV *, u_int32_t, u_int32_t));
 static int __rep_set_request __P((DB_ENV *, u_int32_t, u_int32_t));
 static int __rep_set_rep_transport __P((DB_ENV *, int,
-    int (*)(DB_ENV *, const DBT *, const DBT *, int, u_int32_t)));
+    int (*)(DB_ENV *, const DBT *, const DBT *, const DB_LSN *,
+    int, u_int32_t)));
 static int __rep_start __P((DB_ENV *, DBT *, u_int32_t));
-static int __rep_stat __P((DB_ENV *, DB_REP_STAT **, u_int32_t));
 static int __rep_wait __P((DB_ENV *, u_int32_t, int *, u_int32_t));
 
 /*
  * __rep_dbenv_create --
  *	Replication-specific initialization of the DB_ENV structure.
  *
- * PUBLIC: int __rep_dbenv_create __P((DB_ENV *));
+ * PUBLIC: void __rep_dbenv_create __P((DB_ENV *));
  */
-int
+void
 __rep_dbenv_create(dbenv)
 	DB_ENV *dbenv;
 {
-	DB_REP *db_rep;
-	int ret;
-
 #ifdef HAVE_RPC
 	if (F_ISSET(dbenv, DB_ENV_RPCCLIENT)) {
-		COMPQUIET(db_rep, NULL);
-		COMPQUIET(ret, 0);
 		dbenv->rep_elect = __dbcl_rep_elect;
 		dbenv->rep_flush = __dbcl_rep_flush;
 		dbenv->rep_process_message = __dbcl_rep_process_message;
 		dbenv->rep_start = __dbcl_rep_start;
 		dbenv->rep_stat = __dbcl_rep_stat;
+		dbenv->rep_stat_print = NULL;
+		dbenv->get_rep_limit = __dbcl_rep_get_limit;
 		dbenv->set_rep_limit = __dbcl_rep_set_limit;
 		dbenv->set_rep_request = __dbcl_rep_set_request;
 		dbenv->set_rep_transport = __dbcl_rep_set_rep_transport;
@@ -82,26 +81,33 @@ __rep_dbenv_create(dbenv)
 		dbenv->rep_flush = __rep_flush;
 		dbenv->rep_process_message = __rep_process_message;
 		dbenv->rep_start = __rep_start;
-		dbenv->rep_stat = __rep_stat;
+		dbenv->rep_stat = __rep_stat_pp;
+		dbenv->rep_stat_print = __rep_stat_print_pp;
+		dbenv->get_rep_limit = __rep_get_limit;
 		dbenv->set_rep_limit = __rep_set_limit;
 		dbenv->set_rep_request = __rep_set_request;
 		dbenv->set_rep_transport = __rep_set_rep_transport;
-		/*
-		 * !!!
-		 * Our caller has not yet had the opportunity to reset the panic
-		 * state or turn off mutex locking, and so we can neither check
-		 * the panic state or acquire a mutex in the DB_ENV create path.
-		 */
-
-		if ((ret = __os_calloc(dbenv, 1, sizeof(DB_REP), &db_rep)) != 0)
-			return (ret);
-		dbenv->rep_handle = db_rep;
-
-		/* Initialize the per-process replication structure. */
-		db_rep->rep_send = NULL;
 	}
+}
 
-	return (0);
+/*
+ * __rep_open --
+ *	Replication-specific initialization of the DB_ENV structure.
+ *
+ * PUBLIC: int __rep_open __P((DB_ENV *));
+ */
+int
+__rep_open(dbenv)
+	DB_ENV *dbenv;
+{
+	DB_REP *db_rep;
+	int ret;
+
+	if ((ret = __os_calloc(dbenv, 1, sizeof(DB_REP), &db_rep)) != 0)
+		return (ret);
+	dbenv->rep_handle = db_rep;
+	ret = __rep_region_init(dbenv);
+	return (ret);
 }
 
 /*
@@ -109,6 +115,26 @@ __rep_dbenv_create(dbenv)
  *	Become a master or client, and start sending messages to participate
  * in the replication environment.  Must be called after the environment
  * is open.
+ *
+ * We must protect rep_start, which may change the world, with the rest
+ * of the DB library.  Each API interface will count itself as it enters
+ * the library.  Rep_start checks the following:
+ *
+ * rep->msg_th - this is the count of threads currently in rep_process_message
+ * rep->start_th - this is set if a thread is in rep_start.
+ * rep->handle_cnt - number of threads actively using a dbp in library.
+ * rep->txn_cnt - number of active txns.
+ * REP_F_READY - Replication flag that indicates that we wish to run
+ * recovery, and want to prohibit new transactions from entering and cause
+ * existing ones to return immediately (with a DB_LOCK_DEADLOCK error).
+ *
+ * There is also the renv->rep_timestamp which is updated whenever significant
+ * events (i.e., new masters, log rollback, etc).  Upon creation, a handle
+ * is associated with the current timestamp.  Each time a handle enters the
+ * library it must check if the handle timestamp is the same as the one
+ * stored in the replication region.  This prevents the use of handles on
+ * clients that reference non-existent files whose creation was backed out
+ * during a synchronizing recovery.
  */
 static int
 __rep_start(dbenv, dbt, flags)
@@ -120,53 +146,92 @@ __rep_start(dbenv, dbt, flags)
 	DB_LSN lsn;
 	DB_REP *db_rep;
 	REP *rep;
-	int announce, init_db, redo_prepared, ret;
+	u_int32_t repflags;
+	int announce, init_db, redo_prepared, ret, role_chg;
+	int sleep_cnt, t_ret;
+#ifdef DIAGNOSTIC
+	DB_MSGBUF mb;
+#endif
 
 	PANIC_CHECK(dbenv);
-	ENV_ILLEGAL_BEFORE_OPEN(dbenv, "rep_start");
-	ENV_REQUIRES_CONFIG(dbenv, dbenv->tx_handle, "rep_stat", DB_INIT_TXN);
+	ENV_ILLEGAL_BEFORE_OPEN(dbenv, "DB_ENV->rep_start");
+	ENV_REQUIRES_CONFIG(dbenv, dbenv->rep_handle, "rep_start", DB_INIT_REP);
 
 	db_rep = dbenv->rep_handle;
 	rep = db_rep->region;
 
 	if ((ret = __db_fchk(dbenv, "DB_ENV->rep_start", flags,
-	    DB_REP_CLIENT | DB_REP_LOGSONLY | DB_REP_MASTER)) != 0)
+	    DB_REP_CLIENT | DB_REP_MASTER)) != 0)
 		return (ret);
 
 	/* Exactly one of CLIENT and MASTER must be specified. */
 	if ((ret = __db_fcchk(dbenv,
 	    "DB_ENV->rep_start", flags, DB_REP_CLIENT, DB_REP_MASTER)) != 0)
 		return (ret);
-	if (!LF_ISSET(DB_REP_CLIENT | DB_REP_MASTER | DB_REP_LOGSONLY)) {
+	if (!LF_ISSET(DB_REP_CLIENT | DB_REP_MASTER)) {
 		__db_err(dbenv,
 	"DB_ENV->rep_start: replication mode must be specified");
 		return (EINVAL);
 	}
 
-	/* Masters can't be logs-only. */
-	if ((ret = __db_fcchk(dbenv,
-	    "DB_ENV->rep_start", flags, DB_REP_LOGSONLY, DB_REP_MASTER)) != 0)
-		return (ret);
-
 	/* We need a transport function. */
-	if (db_rep->rep_send == NULL) {
+	if (dbenv->rep_send == NULL) {
 		__db_err(dbenv,
     "DB_ENV->set_rep_transport must be called before DB_ENV->rep_start");
 		return (EINVAL);
 	}
-	
-	/* We'd better not have any logged files open if we are a client. */
-	if (LF_ISSET(DB_REP_CLIENT) && (ret = __dbreg_nofiles(dbenv)) != 0) {
-		__db_err(dbenv, "DB_ENV->rep_start called with open files");
+
+	/*
+	 * If we are about to become (or stay) a master.  Let's flush the log
+	 * to close any potential holes that might happen when upgrading from
+	 * client to master status.
+	 */
+	if (LF_ISSET(DB_REP_MASTER) && (ret = __log_flush(dbenv, NULL)) != 0)
 		return (ret);
+
+	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+	/*
+	 * We only need one thread to start-up replication, so if
+	 * there is another thread in rep_start, we'll let it finish
+	 * its work and have this thread simply return.
+	 */
+	if (rep->start_th != 0) {
+		/*
+		 * There is already someone in rep_start.  Return.
+		 */
+		RPRINT(dbenv, rep, (dbenv, &mb, "Thread already in rep_start"));
+		goto err;
+	} else
+		rep->start_th = 1;
+
+	role_chg = (F_ISSET(rep, REP_F_CLIENT) && LF_ISSET(DB_REP_MASTER)) ||
+	    (F_ISSET(rep, REP_F_MASTER) && LF_ISSET(DB_REP_CLIENT));
+
+	/*
+	 * Wait for any active txns or mpool ops to complete, and
+	 * prevent any new ones from occurring, only if we're
+	 * changing roles.  If we are not changing roles, then we
+	 * only need to coordinate with msg_th.
+	 */
+	if (role_chg)
+		__rep_lockout(dbenv, db_rep, rep, 0);
+	else {
+		for (sleep_cnt = 0; rep->msg_th != 0;) {
+			if (++sleep_cnt % 60 == 0)
+				__db_err(dbenv,
+	"DB_ENV->rep_start waiting %d minutes for replication message thread",
+				    sleep_cnt / 60);
+			MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+			__os_sleep(dbenv, 1, 0);
+			MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+		}
 	}
 
-	MUTEX_LOCK(dbenv, db_rep->mutexp);
 	if (rep->eid == DB_EID_INVALID)
 		rep->eid = dbenv->rep_eid;
 
 	if (LF_ISSET(DB_REP_MASTER)) {
-		if (F_ISSET(dbenv, DB_ENV_REP_CLIENT)) {
+		if (role_chg) {
 			/*
 			 * If we're upgrading from having been a client,
 			 * preclose, so that we close our temporary database.
@@ -180,72 +245,96 @@ __rep_start(dbenv, dbt, flags)
 			 * that opened them becomes a master again.
 			 */
 			if ((ret = __rep_preclose(dbenv, 0)) != 0)
-				return (ret);
-
-			/*
-			 * Now write a __txn_recycle record so that
-			 * clients don't get confused with our txnids
-			 * and txnids of previous masters.
-			 */
-			F_CLR(dbenv, DB_ENV_REP_CLIENT);
-			if ((ret = __txn_reset(dbenv)) != 0)
-				return (ret);
+				goto errunlock;
 		}
 
 		redo_prepared = 0;
 		if (!F_ISSET(rep, REP_F_MASTER)) {
 			/* Master is not yet set. */
-			if (F_ISSET(rep, REP_ISCLIENT)) {
-				F_CLR(rep, REP_ISCLIENT);
-				rep->gen = ++rep->w_gen;
+			if (role_chg) {
+				if (rep->w_gen > rep->recover_gen)
+					rep->gen = ++rep->w_gen;
+				else if (rep->gen > rep->recover_gen)
+					rep->gen++;
+				else
+					rep->gen = rep->recover_gen + 1;
+				/*
+				 * There could have been any number of failed
+				 * elections, so jump the gen if we need to now.
+				 */
+				if (rep->egen > rep->gen)
+					rep->gen = rep->egen;
 				redo_prepared = 1;
 			} else if (rep->gen == 0)
-				rep->gen = 1;
+				rep->gen = rep->recover_gen + 1;
+			if (F_ISSET(rep, REP_F_MASTERELECT)) {
+				__rep_elect_done(dbenv, rep);
+				F_CLR(rep, REP_F_MASTERELECT);
+			}
+			if (rep->egen <= rep->gen)
+				rep->egen = rep->gen + 1;
+			RPRINT(dbenv, rep, (dbenv, &mb,
+			    "New master gen %lu, egen %lu",
+			    (u_long)rep->gen, (u_long)rep->egen));
 		}
-
-		F_SET(rep, REP_F_MASTER);
-		F_SET(dbenv, DB_ENV_REP_MASTER);
-		MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+		rep->master_id = rep->eid;
+		/*
+		 * Note, setting flags below implicitly clears out
+		 * REP_F_NOARCHIVE, REP_F_INIT and REP_F_READY.
+		 */
+		rep->flags = REP_F_MASTER;
+		rep->start_th = 0;
+		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
 		dblp = (DB_LOG *)dbenv->lg_handle;
 		R_LOCK(dbenv, &dblp->reginfo);
 		lsn = ((LOG *)dblp->reginfo.primary)->lsn;
 		R_UNLOCK(dbenv, &dblp->reginfo);
 
 		/*
-		 * Send the NEWMASTER message, then restore prepared txns
-		 * if and only if we just upgraded from being a client.
+		 * Send the NEWMASTER message first so that clients know
+		 * subsequent messages are coming from the right master.
+		 * We need to perform all actions below no master what
+		 * regarding errors.
+		 */
+		(void)__rep_send_message(dbenv,
+		    DB_EID_BROADCAST, REP_NEWMASTER, &lsn, NULL, 0);
+		ret = 0;
+		if (role_chg) {
+			ret = __txn_reset(dbenv);
+			MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+			F_CLR(rep, REP_F_READY);
+			rep->in_recovery = 0;
+			MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+		}
+		/*
+		 * Take a transaction checkpoint so that our new generation
+		 * number get written to the log.
 		 */
-		if ((ret = __rep_send_message(dbenv,
-		    DB_EID_BROADCAST, REP_NEWMASTER, &lsn, NULL, 0)) == 0 &&
-		    redo_prepared)
-			ret = __rep_restore_prepared(dbenv);
+		if ((t_ret = __txn_checkpoint(dbenv, 0, 0, DB_FORCE)) != 0 &&
+		    ret == 0)
+			ret = t_ret;
+		if (redo_prepared &&
+		    (t_ret = __rep_restore_prepared(dbenv)) != 0 && ret == 0)
+			ret = t_ret;
 	} else {
-		F_CLR(dbenv, DB_ENV_REP_MASTER);
-		F_SET(dbenv, DB_ENV_REP_CLIENT);
-		if (LF_ISSET(DB_REP_LOGSONLY))
-			F_SET(dbenv, DB_ENV_REP_LOGSONLY);
-
-		announce = !F_ISSET(rep, REP_ISCLIENT) ||
-		    rep->master_id == DB_EID_INVALID;
 		init_db = 0;
-		if (!F_ISSET(rep, REP_ISCLIENT)) {
-			F_CLR(rep, REP_F_MASTER);
-			if (LF_ISSET(DB_REP_LOGSONLY))
-				F_SET(rep, REP_F_LOGSONLY);
-			else
-				F_SET(rep, REP_F_UPGRADE);
+		announce = role_chg || rep->master_id == DB_EID_INVALID;
 
-			/*
-			 * We initialize the client's generation number to 0.
-			 * Upon startup, it looks for a master and updates the
-			 * generation number as necessary, exactly as it does
-			 * during normal operation and a master failure.
-			 */
-			rep->gen = 0;
+		/*
+		 * If we're changing roles from master to client or if
+		 * we never were any role at all, we need to init the db.
+		 */
+		if (role_chg || !F_ISSET(rep, REP_F_CLIENT)) {
 			rep->master_id = DB_EID_INVALID;
 			init_db = 1;
 		}
-		MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+		/* Zero out everything except recovery and tally flags. */
+		repflags = F_ISSET(rep, REP_F_NOARCHIVE |
+		    REP_F_RECOVER_MASK | REP_F_TALLY);
+		FLD_SET(repflags, REP_F_CLIENT);
+
+		rep->flags = repflags;
+		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
 
 		/*
 		 * Abort any prepared transactions that were restored
@@ -256,10 +345,20 @@ __rep_start(dbenv, dbt, flags)
 		 * records come in.  Aborts will simply be ignored.
 		 */
 		if ((ret = __rep_abort_prepared(dbenv)) != 0)
-			return (ret);
-
-		if ((ret = __rep_client_dbinit(dbenv, init_db)) != 0)
-			return (ret);
+			goto errlock;
+
+		MUTEX_LOCK(dbenv, db_rep->db_mutexp);
+		ret = __rep_client_dbinit(dbenv, init_db, REP_DB);
+		MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+		if (ret != 0)
+			goto errlock;
+		MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+		rep->start_th = 0;
+		if (role_chg) {
+			F_CLR(rep, REP_F_READY);
+			rep->in_recovery = 0;
+		}
+		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
 
 		/*
 		 * If this client created a newly replicated environment,
@@ -270,8 +369,30 @@ __rep_start(dbenv, dbt, flags)
 		 * simply join in.
 		 */
 		if (announce)
-			ret = __rep_send_message(dbenv,
+			(void)__rep_send_message(dbenv,
 			    DB_EID_BROADCAST, REP_NEWCLIENT, NULL, dbt, 0);
+		else
+			(void)__rep_send_message(dbenv,
+			    DB_EID_BROADCAST, REP_ALIVE_REQ, NULL, NULL, 0);
+	}
+
+	if (0) {
+		/*
+		 * We have separate labels for errors.  If we're returning an
+		 * error before we've set start_th, we use 'err'.  If
+		 * we are erroring while holding the rep_mutex, then we use
+		 * 'errunlock' label.  If we're erroring without holding the rep
+		 * mutex we must use 'errlock'.
+		 */
+errlock:
+		MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+errunlock:
+		rep->start_th = 0;
+		if (role_chg) {
+			F_CLR(rep, REP_F_READY);
+			rep->in_recovery = 0;
+		}
+err:		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
 	}
 	return (ret);
 }
@@ -284,64 +405,80 @@ __rep_start(dbenv, dbt, flags)
  * this is the first thread/process starting up and therefore should create
  * the LSN database.  This routine must be called once by each process acting
  * as a client.
+ *
+ * Assumes caller holds appropriate mutex.
+ *
+ * PUBLIC: int __rep_client_dbinit __P((DB_ENV *, int, repdb_t));
  */
-static int
-__rep_client_dbinit(dbenv, startup)
+int
+__rep_client_dbinit(dbenv, startup, which)
 	DB_ENV *dbenv;
 	int startup;
+	repdb_t which;
 {
 	DB_REP *db_rep;
-	DB *dbp;
+	DB *dbp, **rdbpp;
+	REP *rep;
 	int ret, t_ret;
 	u_int32_t flags;
+	const char *name;
 
 	PANIC_CHECK(dbenv);
 	db_rep = dbenv->rep_handle;
+	rep = db_rep->region;
 	dbp = NULL;
 
 #define	REPDBNAME	"__db.rep.db"
+#define	REPPAGENAME     "__db.reppg.db"
 
+	if (which == REP_DB) {
+		name = REPDBNAME;
+		rdbpp = &db_rep->rep_db;
+	} else {
+		name = REPPAGENAME;
+		rdbpp = &rep->file_dbp;
+	}
 	/* Check if this has already been called on this environment. */
-	if (db_rep->rep_db != NULL)
+	if (*rdbpp != NULL)
 		return (0);
 
-	MUTEX_LOCK(dbenv, db_rep->db_mutexp);
-
 	if (startup) {
-		if ((ret = db_create(&dbp, dbenv, 0)) != 0)
+		if ((ret = db_create(&dbp, dbenv, DB_REP_CREATE)) != 0)
 			goto err;
 		/*
 		 * Ignore errors, because if the file doesn't exist, this
 		 * is perfectly OK.
 		 */
-		(void)dbp->remove(dbp, REPDBNAME, NULL, 0);
+		(void)__db_remove(dbp, NULL, name, NULL, DB_FORCE);
 	}
 
-	if ((ret = db_create(&dbp, dbenv, 0)) != 0)
+	if ((ret = db_create(&dbp, dbenv, DB_REP_CREATE)) != 0)
 		goto err;
-	if ((ret = dbp->set_bt_compare(dbp, __rep_bt_cmp)) != 0)
+	if (which == REP_DB &&
+	    (ret = __bam_set_bt_compare(dbp, __rep_bt_cmp)) != 0)
 		goto err;
 
 	/* Allow writes to this database on a client. */
 	F_SET(dbp, DB_AM_CL_WRITER);
 
-	flags = (F_ISSET(dbenv, DB_ENV_THREAD) ? DB_THREAD : 0) |
-	    (startup ? DB_CREATE : 0);
-	if ((ret = dbp->open(dbp, NULL,
-	    "__db.rep.db", NULL, DB_BTREE, flags, 0)) != 0)
+	flags = DB_NO_AUTO_COMMIT |
+	    (startup ? DB_CREATE : 0) |
+	    (F_ISSET(dbenv, DB_ENV_THREAD) ? DB_THREAD : 0);
+
+	if ((ret = __db_open(dbp, NULL, name, NULL,
+	    (which == REP_DB ? DB_BTREE : DB_RECNO),
+	    flags, 0, PGNO_BASE_MD)) != 0)
 		goto err;
 
-	db_rep->rep_db = dbp;
+	*rdbpp= dbp;
 
 	if (0) {
 err:		if (dbp != NULL &&
-		    (t_ret = dbp->close(dbp, DB_NOSYNC)) != 0 && ret == 0)
+		    (t_ret = __db_close(dbp, NULL, DB_NOSYNC)) != 0 && ret == 0)
 			ret = t_ret;
-		db_rep->rep_db = NULL;
+		*rdbpp = NULL;
 	}
 
-	MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
-
 	return (ret);
 }
 
@@ -366,8 +503,8 @@ __rep_bt_cmp(dbp, dbt1, dbt2)
 	rp1 = dbt1->data;
 	rp2 = dbt2->data;
 
-	__ua_memcpy(&lsn1, &rp1->lsn, sizeof(DB_LSN));
-	__ua_memcpy(&lsn2, &rp2->lsn, sizeof(DB_LSN));
+	(void)__ua_memcpy(&lsn1, &rp1->lsn, sizeof(DB_LSN));
+	(void)__ua_memcpy(&lsn2, &rp2->lsn, sizeof(DB_LSN));
 
 	if (lsn1.file > lsn2.file)
 		return (1);
@@ -416,12 +553,12 @@ __rep_abort_prepared(dbenv)
 	if (do_aborts) {
 		op = DB_FIRST;
 		do {
-			if ((ret = dbenv->txn_recover(dbenv,
+			if ((ret = __txn_recover(dbenv,
 			    prep, PREPLISTSIZE, &count, op)) != 0)
 				return (ret);
 			for (i = 0; i < count; i++) {
 				p = &prep[i];
-				if ((ret = p->txn->abort(p->txn)) != 0)
+				if ((ret = __txn_abort(p->txn)) != 0)
 					return (ret);
 			}
 			op = DB_NEXT;
@@ -452,7 +589,7 @@ __rep_restore_prepared(dbenv)
 	__txn_regop_args *regop_args;
 	__txn_xa_regop_args *prep_args;
 	int ret, t_ret;
-	u_int32_t hi_txn, low_txn, rectype;
+	u_int32_t hi_txn, low_txn, rectype, status;
 	void *txninfo;
 
 	txninfo = NULL;
@@ -462,7 +599,7 @@ __rep_restore_prepared(dbenv)
 	ZERO_LSN(ckp_lsn);
 	ZERO_LSN(lsn);
 
-	if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+	if ((ret = __log_cursor(dbenv, &logc)) != 0)
 		return (ret);
 
 	/*
@@ -478,7 +615,7 @@ __rep_restore_prepared(dbenv)
 	 */
 	memset(&rec, 0, sizeof(DBT));
 	if ((ret = __txn_getckp(dbenv, &lsn)) == 0) {
-		if ((ret = logc->get(logc, &lsn, &rec, DB_SET)) != 0)  {
+		if ((ret = __log_c_get(logc, &lsn, &rec, DB_SET)) != 0)  {
 			__db_err(dbenv,
 			    "Checkpoint record at LSN [%lu][%lu] not found",
 			    (u_long)lsn.file, (u_long)lsn.offset);
@@ -495,13 +632,13 @@ __rep_restore_prepared(dbenv)
 		ckp_lsn = ckp_args->ckp_lsn;
 		__os_free(dbenv, ckp_args);
 
-		if ((ret = logc->get(logc, &ckp_lsn, &rec, DB_SET)) != 0) {
+		if ((ret = __log_c_get(logc, &ckp_lsn, &rec, DB_SET)) != 0) {
 			__db_err(dbenv,
 			    "Checkpoint LSN record [%lu][%lu] not found",
 			    (u_long)ckp_lsn.file, (u_long)ckp_lsn.offset);
 			goto err;
 		}
-	} else if ((ret = logc->get(logc, &lsn, &rec, DB_FIRST)) != 0) {
+	} else if ((ret = __log_c_get(logc, &lsn, &rec, DB_FIRST)) != 0) {
 		if (ret == DB_NOTFOUND) {
 			/* An empty log means no PBNYC txns. */
 			ret = 0;
@@ -524,7 +661,7 @@ __rep_restore_prepared(dbenv)
 		    (u_int8_t *)rec.data + sizeof(u_int32_t), sizeof(low_txn));
 		if (low_txn != 0)
 			break;
-	} while ((ret = logc->get(logc, &lsn, &rec, DB_NEXT)) == 0);
+	} while ((ret = __log_c_get(logc, &lsn, &rec, DB_NEXT)) == 0);
 
 	/* If there are no txns, there are no PBNYC txns. */
 	if (ret == DB_NOTFOUND) {
@@ -534,7 +671,7 @@ __rep_restore_prepared(dbenv)
 		goto err;
 
 	/* Now, the high txnid. */
-	if ((ret = logc->get(logc, &lsn, &rec, DB_LAST)) != 0) {
+	if ((ret = __log_c_get(logc, &lsn, &rec, DB_LAST)) != 0) {
 		/*
 		 * Note that DB_NOTFOUND is unacceptable here because we
 		 * had to have looked at some log record to get this far.
@@ -548,7 +685,7 @@ __rep_restore_prepared(dbenv)
 		    (u_int8_t *)rec.data + sizeof(u_int32_t), sizeof(hi_txn));
 		if (hi_txn != 0)
 			break;
-	} while ((ret = logc->get(logc, &lsn, &rec, DB_PREV)) == 0);
+	} while ((ret = __log_c_get(logc, &lsn, &rec, DB_PREV)) == 0);
 	if (ret == DB_NOTFOUND) {
 		ret = 0;
 		goto done;
@@ -570,9 +707,9 @@ __rep_restore_prepared(dbenv)
 	 * Since all PBNYC txns still held locks on the old master and
 	 * were isolated, this should be safe.
 	 */
-	for (ret = logc->get(logc, &lsn, &rec, DB_LAST);
+	for (ret = __log_c_get(logc, &lsn, &rec, DB_LAST);
 	    ret == 0 && log_compare(&lsn, &ckp_lsn) > 0;
-	    ret = logc->get(logc, &lsn, &rec, DB_PREV)) {
+	    ret = __log_c_get(logc, &lsn, &rec, DB_PREV)) {
 		memcpy(&rectype, rec.data, sizeof(rectype));
 		switch (rectype) {
 		case DB___txn_regop:
@@ -586,28 +723,37 @@ __rep_restore_prepared(dbenv)
 				goto err;
 
 			ret = __db_txnlist_find(dbenv,
-			    txninfo, regop_args->txnid->txnid);
+			    txninfo, regop_args->txnid->txnid, &status);
 			if (ret == DB_NOTFOUND)
 				ret = __db_txnlist_add(dbenv, txninfo,
 				    regop_args->txnid->txnid,
 				    regop_args->opcode, &lsn);
+			else if (ret != 0)
+				goto err;
 			__os_free(dbenv, regop_args);
 			break;
 		case DB___txn_xa_regop:
 			/*
-			 * It's a prepare.  If we haven't put the
-			 * txn on our list yet, it hasn't been
-			 * resolved, so apply and restore it.
+			 * It's a prepare.  If its not aborted and
+			 * we haven't put the txn on our list yet, it
+			 * hasn't been resolved, so apply and restore it.
 			 */
 			if ((ret = __txn_xa_regop_read(dbenv, rec.data,
 			    &prep_args)) != 0)
 				goto err;
 			ret = __db_txnlist_find(dbenv, txninfo,
-			    prep_args->txnid->txnid);
-			if (ret == DB_NOTFOUND)
-				if ((ret = __rep_process_txn(dbenv, &rec)) == 0)
+			    prep_args->txnid->txnid, &status);
+			if (ret == DB_NOTFOUND) {
+				if (prep_args->opcode == TXN_ABORT)
+					ret = __db_txnlist_add(dbenv, txninfo,
+					    prep_args->txnid->txnid,
+					    prep_args->opcode, &lsn);
+				else if ((ret =
+				    __rep_process_txn(dbenv, &rec)) == 0)
 					ret = __txn_restore_txn(dbenv,
 					    &lsn, prep_args);
+			} else if (ret != 0)
+				goto err;
 			__os_free(dbenv, prep_args);
 			break;
 		default:
@@ -620,7 +766,7 @@ __rep_restore_prepared(dbenv)
 		ret = 0;
 
 done:
-err:	t_ret = logc->close(logc, 0);
+err:	t_ret = __log_c_close(logc);
 
 	if (txninfo != NULL)
 		__db_txnlist_end(dbenv, txninfo);
@@ -628,6 +774,34 @@ err:	t_ret = logc->close(logc, 0);
 	return (ret == 0 ? t_ret : ret);
 }
 
+static int
+__rep_get_limit(dbenv, gbytesp, bytesp)
+	DB_ENV *dbenv;
+	u_int32_t *gbytesp, *bytesp;
+{
+	DB_REP *db_rep;
+	REP *rep;
+
+	PANIC_CHECK(dbenv);
+	ENV_REQUIRES_CONFIG(dbenv, dbenv->rep_handle, "rep_get_limit",
+	    DB_INIT_REP);
+
+	if (!REP_ON(dbenv)) {
+		__db_err(dbenv,
+    "DB_ENV->get_rep_limit: database environment not properly initialized");
+		return (__db_panic(dbenv, EINVAL));
+	}
+	db_rep = dbenv->rep_handle;
+	rep = db_rep->region;
+
+	if (gbytesp != NULL)
+		*gbytesp = rep->gbytes;
+	if (bytesp != NULL)
+		*bytesp = rep->bytes;
+
+	return (0);
+}
+
 /*
  * __rep_set_limit --
  *	Set a limit on the amount of data that will be sent during a single
@@ -636,28 +810,31 @@ err:	t_ret = logc->close(logc, 0);
 static int
 __rep_set_limit(dbenv, gbytes, bytes)
 	DB_ENV *dbenv;
-	u_int32_t gbytes;
-	u_int32_t bytes;
+	u_int32_t gbytes, bytes;
 {
 	DB_REP *db_rep;
 	REP *rep;
 
 	PANIC_CHECK(dbenv);
+	ENV_ILLEGAL_BEFORE_OPEN(dbenv, "DB_ENV->rep_set_limit");
+	ENV_REQUIRES_CONFIG(dbenv, dbenv->rep_handle, "rep_set_limit",
+	    DB_INIT_REP);
 
-	if ((db_rep = dbenv->rep_handle) == NULL) {
+	if (!REP_ON(dbenv)) {
 		__db_err(dbenv,
     "DB_ENV->set_rep_limit: database environment not properly initialized");
 		return (__db_panic(dbenv, EINVAL));
 	}
+	db_rep = dbenv->rep_handle;
 	rep = db_rep->region;
-	MUTEX_LOCK(dbenv, db_rep->mutexp);
+	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
 	if (bytes > GIGABYTE) {
 		gbytes += bytes / GIGABYTE;
 		bytes = bytes % GIGABYTE;
 	}
 	rep->gbytes = gbytes;
 	rep->bytes = bytes;
-	MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
 
 	return (0);
 }
@@ -671,8 +848,7 @@ __rep_set_limit(dbenv, gbytes, bytes)
 static int
 __rep_set_request(dbenv, min, max)
 	DB_ENV *dbenv;
-	u_int32_t min;
-	u_int32_t max;
+	u_int32_t min, max;
 {
 	LOG *lp;
 	DB_LOG *dblp;
@@ -680,24 +856,32 @@ __rep_set_request(dbenv, min, max)
 	REP *rep;
 
 	PANIC_CHECK(dbenv);
+	ENV_ILLEGAL_BEFORE_OPEN(dbenv, "DB_ENV->rep_set_request");
+	ENV_REQUIRES_CONFIG(dbenv, dbenv->rep_handle, "rep_set_request",
+	    DB_INIT_REP);
 
-	if ((db_rep = dbenv->rep_handle) == NULL) {
+	if (!REP_ON(dbenv)) {
 		__db_err(dbenv,
     "DB_ENV->set_rep_request: database environment not properly initialized");
 		return (__db_panic(dbenv, EINVAL));
 	}
+	db_rep = dbenv->rep_handle;
 	rep = db_rep->region;
-	MUTEX_LOCK(dbenv, db_rep->mutexp);
+	/*
+	 * Note we acquire the rep_mutexp or the db_mutexp as needed.
+	 */
+	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
 	rep->request_gap = min;
 	rep->max_gap = max;
-	MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+
+	MUTEX_LOCK(dbenv, db_rep->db_mutexp);
 	dblp = dbenv->lg_handle;
 	if (dblp != NULL && (lp = dblp->reginfo.primary) != NULL) {
-		R_LOCK(dbenv, &dblp->reginfo);
 		lp->wait_recs = 0;
 		lp->rcvd_recs = 0;
-		R_UNLOCK(dbenv, &dblp->reginfo);
 	}
+	MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
 
 	return (0);
 }
@@ -710,32 +894,22 @@ static int
 __rep_set_rep_transport(dbenv, eid, f_send)
 	DB_ENV *dbenv;
 	int eid;
-	int (*f_send) __P((DB_ENV *, const DBT *, const DBT *, int, u_int32_t));
+	int (*f_send) __P((DB_ENV *, const DBT *, const DBT *, const DB_LSN *,
+	    int, u_int32_t));
 {
-	DB_REP *db_rep;
-
 	PANIC_CHECK(dbenv);
 
-	if ((db_rep = dbenv->rep_handle) == NULL) {
-		__db_err(dbenv,
-    "DB_ENV->set_rep_transport: database environment not properly initialized");
-		return (__db_panic(dbenv, EINVAL));
-	}
-
 	if (f_send == NULL) {
 		__db_err(dbenv,
 	"DB_ENV->set_rep_transport: no send function specified");
 		return (EINVAL);
 	}
-
 	if (eid < 0) {
 		__db_err(dbenv,
 	"DB_ENV->set_rep_transport: eid must be greater than or equal to 0");
 		return (EINVAL);
 	}
-
-	db_rep->rep_send = f_send;
-
+	dbenv->rep_send = f_send;
 	dbenv->rep_eid = eid;
 	return (0);
 }
@@ -746,21 +920,26 @@ __rep_set_rep_transport(dbenv, eid, f_send)
  *	a new master.
  */
 static int
-__rep_elect(dbenv, nsites, priority, timeout, eidp)
+__rep_elect(dbenv, nsites, nvotes, priority, timeout, eidp, flags)
 	DB_ENV *dbenv;
-	int nsites, priority;
+	int nsites, nvotes, priority;
 	u_int32_t timeout;
 	int *eidp;
+	u_int32_t flags;
 {
 	DB_LOG *dblp;
 	DB_LSN lsn;
 	DB_REP *db_rep;
 	REP *rep;
-	int in_progress, ret, send_vote, tiebreaker;
-	u_int32_t pid, sec, usec;
+	int ack, done, in_progress, ret, send_vote;
+	u_int32_t egen, orig_tally, tiebreaker, to;
+#ifdef DIAGNOSTIC
+	DB_MSGBUF mb;
+#endif
 
 	PANIC_CHECK(dbenv);
-	ENV_REQUIRES_CONFIG(dbenv, dbenv->tx_handle, "rep_elect", DB_INIT_TXN);
+	COMPQUIET(flags, 0);
+	ENV_REQUIRES_CONFIG(dbenv, dbenv->rep_handle, "rep_elect", DB_INIT_REP);
 
 	/* Error checking. */
 	if (nsites <= 0) {
@@ -768,60 +947,160 @@ __rep_elect(dbenv, nsites, priority, timeout, eidp)
 		    "DB_ENV->rep_elect: nsites must be greater than 0");
 		return (EINVAL);
 	}
+	if (nvotes < 0) {
+		__db_err(dbenv,
+		    "DB_ENV->rep_elect: nvotes may not be negative");
+		return (EINVAL);
+	}
 	if (priority < 0) {
 		__db_err(dbenv,
 		    "DB_ENV->rep_elect: priority may not be negative");
 		return (EINVAL);
 	}
+	if (nsites < nvotes) {
+		__db_err(dbenv,
+    "DB_ENV->rep_elect: nvotes (%d) is larger than nsites (%d)",
+		    nvotes, nsites);
+		return (EINVAL);
+	}
+
+	ack = nvotes;
+	/* If they give us a 0 for nvotes, default to simple majority.  */
+	if (nvotes == 0)
+		ack = (nsites / 2) + 1;
+
+	/*
+	 * XXX
+	 * If users give us less than a majority, they run the risk of
+	 * having a network partition.  However, this also allows the
+	 * scenario of master/1 client to elect the client.  Allow
+	 * sub-majority values, but give a warning.
+	 */
+	if (nvotes <= (nsites / 2)) {
+		__db_err(dbenv,
+    "DB_ENV->rep_elect:WARNING: nvotes (%d) is sub-majority with nsites (%d)",
+		    nvotes, nsites);
+	}
 
 	db_rep = dbenv->rep_handle;
 	rep = db_rep->region;
 	dblp = dbenv->lg_handle;
 
+	RPRINT(dbenv, rep,
+	    (dbenv, &mb, "Start election nsites %d, ack %d, priority %d",
+	    nsites, ack, priority));
+
 	R_LOCK(dbenv, &dblp->reginfo);
 	lsn = ((LOG *)dblp->reginfo.primary)->lsn;
 	R_UNLOCK(dbenv, &dblp->reginfo);
 
-	/* Generate a randomized tiebreaker value. */
-	__os_id(&pid);
-	if ((ret = __os_clock(dbenv, &sec, &usec)) != 0)
-		return (ret);
-	tiebreaker = pid ^ sec ^ usec ^ (u_int)rand() ^ P_TO_UINT32(&pid);
-
+	orig_tally = 0;
+	to = timeout;
 	if ((ret = __rep_elect_init(dbenv,
-	    &lsn, nsites, priority, tiebreaker, &in_progress)) != 0) {
+	    &lsn, nsites, ack, priority, &in_progress, &orig_tally)) != 0) {
 		if (ret == DB_REP_NEWMASTER) {
 			ret = 0;
 			*eidp = dbenv->rep_eid;
 		}
-		return (ret);
+		goto err;
 	}
-
-	if (!in_progress) {
-#ifdef DIAGNOSTIC
-		if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION))
-			__db_err(dbenv, "Beginning an election");
-#endif
-		if ((ret = __rep_send_message(dbenv,
-		    DB_EID_BROADCAST, REP_ELECT, NULL, NULL, 0)) != 0)
+	/*
+	 * If another thread is in the middle of an election we
+	 * just quietly return and not interfere.
+	 */
+	if (in_progress) {
+		*eidp = rep->master_id;
+		return (0);
+	}
+	(void)__rep_send_message(dbenv,
+	    DB_EID_BROADCAST, REP_MASTER_REQ, NULL, NULL, 0);
+	ret = __rep_wait(dbenv, to/4, eidp, REP_F_EPHASE1);
+	switch (ret) {
+		case 0:
+			/* Check if we found a master. */
+			if (*eidp != DB_EID_INVALID) {
+				RPRINT(dbenv, rep, (dbenv, &mb,
+				    "Found master %d", *eidp));
+				goto edone;
+			}
+			/*
+			 * If we didn't find a master, continue
+			 * the election.
+			 */
+			break;
+		case DB_REP_EGENCHG:
+			/*
+			 * Egen changed, just continue with election.
+			 */
+			break;
+		case DB_TIMEOUT:
+			RPRINT(dbenv, rep, (dbenv, &mb,
+			    "Did not find master.  Sending vote1"));
+			break;
+		default:
 			goto err;
-		DB_ENV_TEST_RECOVERY(dbenv, DB_TEST_ELECTSEND, ret, NULL);
 	}
+restart:
+	/* Generate a randomized tiebreaker value. */
+	__os_unique_id(dbenv, &tiebreaker);
+
+	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+	F_SET(rep, REP_F_EPHASE1 | REP_F_NOARCHIVE);
+	F_CLR(rep, REP_F_TALLY);
+
+	/*
+	 * We are about to participate at this egen.  We must
+	 * write out the next egen before participating in this one
+	 * so that if we crash we can never participate in this egen
+	 * again.
+	 */
+	if ((ret = __rep_write_egen(dbenv, rep->egen + 1)) != 0)
+		goto lockdone;
+
+	/* Tally our own vote */
+	if (__rep_tally(dbenv, rep, rep->eid, &rep->sites, rep->egen,
+	    rep->tally_off) != 0) {
+		ret = EINVAL;
+		goto lockdone;
+	}
+	__rep_cmp_vote(dbenv, rep, &rep->eid, &lsn, priority, rep->gen,
+	    tiebreaker);
+
+	RPRINT(dbenv, rep, (dbenv, &mb, "Beginning an election"));
 
 	/* Now send vote */
-	if ((ret =
-	    __rep_send_vote(dbenv, &lsn, nsites, priority, tiebreaker)) != 0)
-		goto err;
+	send_vote = DB_EID_INVALID;
+	egen = rep->egen;
+	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+	__rep_send_vote(dbenv, &lsn, nsites, ack, priority, tiebreaker, egen,
+	    DB_EID_BROADCAST, REP_VOTE1);
 	DB_ENV_TEST_RECOVERY(dbenv, DB_TEST_ELECTVOTE1, ret, NULL);
-
-	ret = __rep_wait(dbenv, timeout, eidp, REP_F_EPHASE1);
-	DB_ENV_TEST_RECOVERY(dbenv, DB_TEST_ELECTWAIT1, ret, NULL);
+	ret = __rep_wait(dbenv, to, eidp, REP_F_EPHASE1);
 	switch (ret) {
 		case 0:
 			/* Check if election complete or phase complete. */
-			if (*eidp != DB_EID_INVALID)
-				return (0);
+			if (*eidp != DB_EID_INVALID) {
+				RPRINT(dbenv, rep, (dbenv, &mb,
+				    "Ended election phase 1 %d", ret));
+				goto edone;
+			}
 			goto phase2;
+		case DB_REP_EGENCHG:
+			if (to > timeout)
+				to = timeout;
+			to = (to * 8) / 10;
+			RPRINT(dbenv, rep, (dbenv, &mb,
+"Egen changed while waiting. Now %lu.  New timeout %lu, orig timeout %lu",
+			    (u_long)rep->egen, (u_long)to, (u_long)timeout));
+			/*
+			 * If the egen changed while we were sleeping, that
+			 * means we're probably late to the next election,
+			 * so we'll backoff our timeout so that we don't get
+			 * into an out-of-phase election scenario.
+			 *
+			 * Backoff to 80% of the current timeout.
+			 */
+			goto restart;
 		case DB_TIMEOUT:
 			break;
 		default:
@@ -833,61 +1112,136 @@ __rep_elect(dbenv, nsites, priority, timeout, eidp)
 	 * votes to pick a winner and if so, to send out a vote to
 	 * the winner.
 	 */
-	MUTEX_LOCK(dbenv, db_rep->mutexp);
-	send_vote = DB_EID_INVALID;
-	if (rep->sites > rep->nsites / 2) {
+	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+	/*
+	 * If our egen changed while we were waiting.  We need to
+	 * essentially reinitialize our election.
+	 */
+	if (egen != rep->egen) {
+		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+		RPRINT(dbenv, rep, (dbenv, &mb, "Egen changed from %lu to %lu",
+		    (u_long)egen, (u_long)rep->egen));
+		goto restart;
+	}
+	if (rep->sites >= rep->nvotes) {
+
 		/* We think we've seen enough to cast a vote. */
 		send_vote = rep->winner;
-		if (rep->winner == rep->eid)
-			rep->votes++;
-		F_CLR(rep, REP_F_EPHASE1);
+		/*
+		 * See if we won.  This will make sure we
+		 * don't count ourselves twice if we're racing
+		 * with incoming votes.
+		 */
+		if (rep->winner == rep->eid) {
+			(void)__rep_tally(dbenv, rep, rep->eid, &rep->votes,
+			    egen, rep->v2tally_off);
+			RPRINT(dbenv, rep, (dbenv, &mb,
+			    "Counted my vote %d", rep->votes));
+		}
 		F_SET(rep, REP_F_EPHASE2);
+		F_CLR(rep, REP_F_EPHASE1);
 	}
-	MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
 	if (send_vote == DB_EID_INVALID) {
 		/* We do not have enough votes to elect. */
-#ifdef DIAGNOSTIC
-		if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION))
-			__db_err(dbenv,
-			    "Not enough votes to elect: received %d of %d",
-			    rep->sites, rep->nsites);
-#endif
+		RPRINT(dbenv, rep, (dbenv, &mb,
+		    "Not enough votes to elect: recvd %d of %d from %d sites",
+		    rep->sites, rep->nvotes, rep->nsites));
 		ret = DB_REP_UNAVAIL;
 		goto err;
 
-	}
-#ifdef DIAGNOSTIC
-	if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION) &&
-	    send_vote != rep->eid)
-		__db_err(dbenv, "Sending vote");
-#endif
+	} else {
+		/*
+		 * We have seen enough vote1's.  Now we need to wait
+		 * for all the vote2's.
+		 */
+		if (send_vote != rep->eid) {
+			RPRINT(dbenv, rep, (dbenv, &mb, "Sending vote"));
+			__rep_send_vote(dbenv, NULL, 0, 0, 0, 0, egen,
+			    send_vote, REP_VOTE2);
+			/*
+			 * If we are NOT the new master we want to send
+			 * our vote to the winner, and wait longer.  The
+			 * reason is that the winner may be "behind" us
+			 * in the election waiting and if the master is
+			 * down, the winner will wait the full timeout
+			 * and we want to give the winner enough time to
+			 * process all the votes.  Otherwise we could
+			 * incorrectly return DB_REP_UNAVAIL and start a
+			 * new election before the winner can declare
+			 * itself.
+			 */
+			to = to * 2;
 
-	if (send_vote != rep->eid && (ret = __rep_send_message(dbenv,
-	    send_vote, REP_VOTE2, NULL, NULL, 0)) != 0)
-		goto err;
-	DB_ENV_TEST_RECOVERY(dbenv, DB_TEST_ELECTVOTE2, ret, NULL);
+		}
 
-phase2:	ret = __rep_wait(dbenv, timeout, eidp, REP_F_EPHASE2);
-	DB_ENV_TEST_RECOVERY(dbenv, DB_TEST_ELECTWAIT2, ret, NULL);
-	switch (ret) {
-		case 0:
-			return (0);
-		case DB_TIMEOUT:
-			ret = DB_REP_UNAVAIL;
-			break;
-		default:
-			goto err;
+phase2:		ret = __rep_wait(dbenv, to, eidp, REP_F_EPHASE2);
+		RPRINT(dbenv, rep, (dbenv, &mb,
+		    "Ended election phase 2 %d", ret));
+		switch (ret) {
+			case 0:
+				goto edone;
+			case DB_REP_EGENCHG:
+				if (to > timeout)
+					to = timeout;
+				to = (to * 8) / 10;
+				RPRINT(dbenv, rep, (dbenv, &mb,
+"While waiting egen changed to %lu.  Phase 2 New timeout %lu, orig timeout %lu",
+				    (u_long)rep->egen,
+				    (u_long)to, (u_long)timeout));
+				goto restart;
+			case DB_TIMEOUT:
+				ret = DB_REP_UNAVAIL;
+				break;
+			default:
+				goto err;
+		}
+		MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+		if (egen != rep->egen) {
+			MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+			RPRINT(dbenv, rep, (dbenv, &mb,
+			    "Egen ph2 changed from %lu to %lu",
+			    (u_long)egen, (u_long)rep->egen));
+			goto restart;
+		}
+		done = rep->votes >= rep->nvotes;
+		RPRINT(dbenv, rep, (dbenv, &mb,
+		    "After phase 2: done %d, votes %d, nsites %d",
+		    done, rep->votes, rep->nsites));
+		if (send_vote == rep->eid && done) {
+			__rep_elect_master(dbenv, rep, eidp);
+			ret = 0;
+			goto lockdone;
+		}
+		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
 	}
 
-DB_TEST_RECOVERY_LABEL
-err:	MUTEX_LOCK(dbenv, db_rep->mutexp);
-	ELECTION_DONE(rep);
-	MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+err:	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+lockdone:
+	/*
+	 * If we get here because of a non-election error, then we
+	 * did not tally our vote.  The only non-election error is
+	 * from elect_init where we were unable to grow_sites.  In
+	 * that case we do not want to discard all known election info.
+	 */
+	if (ret == 0 || ret == DB_REP_UNAVAIL)
+		__rep_elect_done(dbenv, rep);
+	else if (orig_tally)
+		F_SET(rep, orig_tally);
 
-#ifdef DIAGNOSTIC
-	if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION))
-		__db_err(dbenv, "Ended election with %d", ret);
-#endif
+	/*
+	 * If the election finished elsewhere, we need to decrement
+	 * the elect_th anyway.
+	 */
+	if (0)
+edone:		MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+	rep->elect_th = 0;
+
+	RPRINT(dbenv, rep, (dbenv, &mb,
+	    "Ended election with %d, sites %d, egen %lu, flags 0x%lx",
+	    ret, rep->sites, (u_long)rep->egen, (u_long)rep->flags));
+	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+DB_TEST_RECOVERY_LABEL
 	return (ret);
 }
 
@@ -897,14 +1251,16 @@ err:	MUTEX_LOCK(dbenv, db_rep->mutexp);
  * already in progress; makes it 0 otherwise.
  */
 static int
-__rep_elect_init(dbenv, lsnp, nsites, priority, tiebreaker, beginp)
+__rep_elect_init(dbenv, lsnp, nsites, nvotes, priority, beginp, otally)
 	DB_ENV *dbenv;
 	DB_LSN *lsnp;
-	int nsites, priority, tiebreaker, *beginp;
+	int nsites, nvotes, priority;
+	int *beginp;
+	u_int32_t *otally;
 {
 	DB_REP *db_rep;
 	REP *rep;
-	int ret, *tally;
+	int ret;
 
 	db_rep = dbenv->rep_handle;
 	rep = db_rep->region;
@@ -915,15 +1271,17 @@ __rep_elect_init(dbenv, lsnp, nsites, priority, tiebreaker, beginp)
 	rep->stat.st_elections++;
 
 	/* If we are already a master; simply broadcast that fact and return. */
-	if (F_ISSET(dbenv, DB_ENV_REP_MASTER)) {
+	if (F_ISSET(rep, REP_F_MASTER)) {
 		(void)__rep_send_message(dbenv,
 		    DB_EID_BROADCAST, REP_NEWMASTER, lsnp, NULL, 0);
 		rep->stat.st_elections_won++;
 		return (DB_REP_NEWMASTER);
 	}
 
-	MUTEX_LOCK(dbenv, db_rep->mutexp);
-	*beginp = IN_ELECTION(rep);
+	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+	if (otally != NULL)
+		*otally = F_ISSET(rep, REP_F_TALLY);
+	*beginp = IN_ELECTION(rep) || rep->elect_th;
 	if (!*beginp) {
 		/*
 		 * Make sure that we always initialize all the election fields
@@ -935,37 +1293,45 @@ __rep_elect_init(dbenv, lsnp, nsites, priority, tiebreaker, beginp)
 		    (ret = __rep_grow_sites(dbenv, nsites)) != 0)
 			goto err;
 		DB_ENV_TEST_RECOVERY(dbenv, DB_TEST_ELECTINIT, ret, NULL);
+		rep->elect_th = 1;
 		rep->nsites = nsites;
+		rep->nvotes = nvotes;
 		rep->priority = priority;
-		rep->votes = 0;
 		rep->master_id = DB_EID_INVALID;
-		F_SET(rep, REP_F_EPHASE1);
-
-		/* We have always heard from ourselves. */
-		rep->sites = 1;
-		tally = R_ADDR((REGINFO *)dbenv->reginfo, rep->tally_off);
-		tally[0] = rep->eid;
-
-		if (priority != 0) {
-			/* Make ourselves the winner to start. */
-			rep->winner = rep->eid;
-			rep->w_priority = priority;
-			rep->w_gen = rep->gen;
-			rep->w_lsn = *lsnp;
-			rep->w_tiebreaker = tiebreaker;
-		} else {
-			rep->winner = DB_EID_INVALID;
-			rep->w_priority = 0;
-			rep->w_gen = 0;
-			ZERO_LSN(rep->w_lsn);
-			rep->w_tiebreaker = 0;
-		}
 	}
 DB_TEST_RECOVERY_LABEL
-err:	MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+err:	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
 	return (ret);
 }
 
+/*
+ * __rep_elect_master
+ *	Set up for new master from election.  Must be called with
+ *	the db_rep->rep_mutex held.
+ *
+ * PUBLIC: void __rep_elect_master __P((DB_ENV *, REP *, int *));
+ */
+void
+__rep_elect_master(dbenv, rep, eidp)
+	DB_ENV *dbenv;
+	REP *rep;
+	int *eidp;
+{
+#ifdef DIAGNOSTIC
+	DB_MSGBUF mb;
+#else
+	COMPQUIET(dbenv, NULL);
+#endif
+	rep->master_id = rep->eid;
+	F_SET(rep, REP_F_MASTERELECT);
+	if (eidp != NULL)
+		*eidp = rep->master_id;
+	rep->stat.st_elections_won++;
+	RPRINT(dbenv, rep, (dbenv, &mb,
+	    "Got enough votes to win; election done; winner is %d, gen %lu",
+	    rep->master_id, (u_long)rep->gen));
+}
+
 static int
 __rep_wait(dbenv, timeout, eidp, flags)
 	DB_ENV *dbenv;
@@ -975,12 +1341,13 @@ __rep_wait(dbenv, timeout, eidp, flags)
 {
 	DB_REP *db_rep;
 	REP *rep;
-	int done, ret;
-	u_int32_t sleeptime;
+	int done, echg;
+	u_int32_t egen, sleeptime;
 
-	done = 0;
+	done = echg = 0;
 	db_rep = dbenv->rep_handle;
 	rep = db_rep->region;
+	egen = rep->egen;
 
 	/*
 	 * The user specifies an overall timeout function, but checking
@@ -991,17 +1358,20 @@ __rep_wait(dbenv, timeout, eidp, flags)
 	if (sleeptime == 0)
 		sleeptime++;
 	while (timeout > 0) {
-		if ((ret = __os_sleep(dbenv, 0, sleeptime)) != 0)
-			return (ret);
-		MUTEX_LOCK(dbenv, db_rep->mutexp);
+		__os_sleep(dbenv, 0, sleeptime);
+		MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+		echg = egen != rep->egen;
 		done = !F_ISSET(rep, flags) && rep->master_id != DB_EID_INVALID;
 
 		*eidp = rep->master_id;
-		MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
 
 		if (done)
 			return (0);
 
+		if (echg)
+			return (DB_REP_EGENCHG);
+
 		if (timeout > sleeptime)
 			timeout -= sleeptime;
 		else
@@ -1025,120 +1395,21 @@ __rep_flush(dbenv)
 	int ret, t_ret;
 
 	PANIC_CHECK(dbenv);
-	ENV_REQUIRES_CONFIG(dbenv, dbenv->tx_handle, "rep_stat", DB_INIT_TXN);
+	ENV_REQUIRES_CONFIG(dbenv, dbenv->rep_handle, "rep_flush", DB_INIT_REP);
 
-	if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+	if ((ret = __log_cursor(dbenv, &logc)) != 0)
 		return (ret);
 
 	memset(&rec, 0, sizeof(rec));
 	memset(&lsn, 0, sizeof(lsn));
 
-	if ((ret = logc->get(logc, &lsn, &rec, DB_LAST)) != 0)
+	if ((ret = __log_c_get(logc, &lsn, &rec, DB_LAST)) != 0)
 		goto err;
 
-	ret = __rep_send_message(dbenv,
+	(void)__rep_send_message(dbenv,
 	    DB_EID_BROADCAST, REP_LOG, &lsn, &rec, 0);
 
-err:	if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+err:	if ((t_ret = __log_c_close(logc)) != 0 && ret == 0)
 		ret = t_ret;
 	return (ret);
 }
-
-/*
- * __rep_stat --
- *	Fetch replication statistics.
- */
-static int
-__rep_stat(dbenv, statp, flags)
-	DB_ENV *dbenv;
-	DB_REP_STAT **statp;
-	u_int32_t flags;
-{
-	DB_LOG *dblp;
-	DB_REP *db_rep;
-	DB_REP_STAT *stats;
-	LOG *lp;
-	REP *rep;
-	u_int32_t queued;
-	int ret;
-
-	PANIC_CHECK(dbenv);
-	ENV_REQUIRES_CONFIG(dbenv, dbenv->tx_handle, "rep_stat", DB_INIT_TXN);
-
-	db_rep = dbenv->rep_handle;
-	rep = db_rep->region;
-	dblp = dbenv->lg_handle;
-	lp = dblp->reginfo.primary;
-
-	*statp = NULL;
-	if ((ret = __db_fchk(dbenv,
-	    "DB_ENV->rep_stat", flags, DB_STAT_CLEAR)) != 0)
-		return (ret);
-
-	/* Allocate a stat struct to return to the user. */
-	if ((ret = __os_umalloc(dbenv, sizeof(DB_REP_STAT), &stats)) != 0)
-		return (ret);
-
-	MUTEX_LOCK(dbenv, db_rep->mutexp);
-	memcpy(stats, &rep->stat, sizeof(*stats));
-
-	/* Copy out election stats. */
-	if (IN_ELECTION(rep)) {
-		if (F_ISSET(rep, REP_F_EPHASE1))
-			stats->st_election_status = 1;
-		else if (F_ISSET(rep, REP_F_EPHASE2))
-			stats->st_election_status = 2;
-
-		stats->st_election_nsites = rep->sites;
-		stats->st_election_cur_winner = rep->winner;
-		stats->st_election_priority = rep->w_priority;
-		stats->st_election_gen = rep->w_gen;
-		stats->st_election_lsn = rep->w_lsn;
-		stats->st_election_votes = rep->votes;
-		stats->st_election_tiebreaker = rep->w_tiebreaker;
-	}
-
-	/* Copy out other info that's protected by the rep mutex. */
-	stats->st_env_id = rep->eid;
-	stats->st_env_priority = rep->priority;
-	stats->st_nsites = rep->nsites;
-	stats->st_master = rep->master_id;
-	stats->st_gen = rep->gen;
-
-	if (F_ISSET(rep, REP_F_MASTER))
-		stats->st_status = DB_REP_MASTER;
-	else if (F_ISSET(rep, REP_F_LOGSONLY))
-		stats->st_status = DB_REP_LOGSONLY;
-	else if (F_ISSET(rep, REP_F_UPGRADE))
-		stats->st_status = DB_REP_CLIENT;
-	else
-		stats->st_status = 0;
-
-	if (LF_ISSET(DB_STAT_CLEAR)) {
-		queued = rep->stat.st_log_queued;
-		memset(&rep->stat, 0, sizeof(rep->stat));
-		rep->stat.st_log_queued = rep->stat.st_log_queued_total =
-		    rep->stat.st_log_queued_max = queued;
-	}
-	MUTEX_UNLOCK(dbenv, db_rep->mutexp);
-
-	/*
-	 * Log-related replication info is stored in the log system and
-	 * protected by the log region lock.
-	 */
-	R_LOCK(dbenv, &dblp->reginfo);
-	if (F_ISSET(rep, REP_ISCLIENT)) {
-		stats->st_next_lsn = lp->ready_lsn;
-		stats->st_waiting_lsn = lp->waiting_lsn;
-	} else {
-		if (F_ISSET(rep, REP_F_MASTER))
-			stats->st_next_lsn = lp->lsn;
-		else
-			ZERO_LSN(stats->st_next_lsn);
-		ZERO_LSN(stats->st_waiting_lsn);
-	}
-	R_UNLOCK(dbenv, &dblp->reginfo);
-
-	*statp = stats;
-	return (0);
-}
diff --git a/storage/bdb/rep/rep_record.c b/storage/bdb/rep/rep_record.c
index d3619f509b47f86a3129cb14534fc82f944b96ba..2421c5af294a298e122a68c33519a9418ca20176 100644
--- a/storage/bdb/rep/rep_record.c
+++ b/storage/bdb/rep/rep_record.c
@@ -1,35 +1,104 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
+ * Copyright (c) 2001-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: rep_record.c,v 1.255 2004/11/04 18:35:29 sue Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: rep_record.c,v 1.111 2002/09/11 19:39:11 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
+#if TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#endif
+
 #include <stdlib.h>
 #include <string.h>
 #endif
 
 #include "db_int.h"
 #include "dbinc/db_page.h"
+#include "dbinc/db_shash.h"
 #include "dbinc/db_am.h"
+#include "dbinc/lock.h"
 #include "dbinc/log.h"
-#include "dbinc/rep.h"
+#include "dbinc/mp.h"
 #include "dbinc/txn.h"
 
-static int __rep_apply __P((DB_ENV *, REP_CONTROL *, DBT *));
+static int __rep_apply __P((DB_ENV *, REP_CONTROL *, DBT *, DB_LSN *, int *));
 static int __rep_collect_txn __P((DB_ENV *, DB_LSN *, LSN_COLLECTION *));
+static int __rep_do_ckp __P((DB_ENV *, DBT *, REP_CONTROL *));
+static int __rep_dorecovery __P((DB_ENV *, DB_LSN *, DB_LSN *));
+static int __rep_getnext __P((DB_ENV *));
 static int __rep_lsn_cmp __P((const void *, const void *));
-static int __rep_newfile __P((DB_ENV *, REP_CONTROL *, DBT *, DB_LSN *));
-
-#define	IS_SIMPLE(R)	((R) != DB___txn_regop && \
-    (R) != DB___txn_ckp && (R) != DB___dbreg_register)
+static int __rep_newfile __P((DB_ENV *, REP_CONTROL *, DB_LSN *));
+static int __rep_process_rec __P((DB_ENV *,
+    REP_CONTROL *, DBT *, u_int32_t *, DB_LSN *));
+static int __rep_remfirst __P((DB_ENV *, DBT *, DBT *));
+static int __rep_resend_req __P((DB_ENV *, int));
+static int __rep_verify_match __P((DB_ENV *, DB_LSN *, time_t));
+
+/* Used to consistently designate which messages ought to be received where. */
+
+#define	MASTER_ONLY(rep, rp) do {					\
+	if (!F_ISSET(rep, REP_F_MASTER)) {				\
+		RPRINT(dbenv, rep,					\
+		(dbenv, &mb, "Master record received on client"));	\
+		REP_PRINT_MESSAGE(dbenv,				\
+		    *eidp, rp, "rep_process_message");			\
+		ret = EINVAL;						\
+		goto errlock;						\
+	}								\
+} while (0)
+
+#define	CLIENT_ONLY(rep, rp) do {					\
+	if (!F_ISSET(rep, REP_F_CLIENT)) {				\
+		RPRINT(dbenv, rep,					\
+		    (dbenv, &mb, "Client record received on master"));	\
+		REP_PRINT_MESSAGE(dbenv,				\
+		    *eidp, rp, "rep_process_message");			\
+		(void)__rep_send_message(dbenv,				\
+		    DB_EID_BROADCAST, REP_DUPMASTER, NULL, NULL, 0);	\
+		ret = DB_REP_DUPMASTER;					\
+		goto errlock;						\
+	}								\
+} while (0)
+
+#define	MASTER_CHECK(dbenv, eid, rep) do {				\
+	if (rep->master_id == DB_EID_INVALID) {				\
+		RPRINT(dbenv, rep, (dbenv, &mb,				\
+		    "Received record from %d, master is INVALID", eid));\
+		ret = 0;						\
+		(void)__rep_send_message(dbenv,				\
+		    DB_EID_BROADCAST, REP_MASTER_REQ, NULL, NULL, 0);	\
+		goto errlock;						\
+	}								\
+	if (eid != rep->master_id) {					\
+		__db_err(dbenv,						\
+		   "Received master record from %d, master is %d",	\
+		   eid, rep->master_id);				\
+		ret = EINVAL;						\
+		goto errlock;						\
+	}								\
+} while (0)
+
+#define	MASTER_UPDATE(dbenv, renv) do {					\
+	MUTEX_LOCK((dbenv), &(renv)->mutex);				\
+	F_SET((renv), DB_REGENV_REPLOCKED);				\
+	(void)time(&(renv)->op_timestamp);				\
+	MUTEX_UNLOCK((dbenv), &(renv)->mutex);				\
+} while (0)
+
+#define	ANYSITE(rep)
 
 /*
  * __rep_process_message --
@@ -41,30 +110,42 @@ static int __rep_newfile __P((DB_ENV *, REP_CONTROL *, DBT *, DB_LSN *));
  * eidp: contains the machine id of the sender of the message;
  *	in the case of a DB_NEWMASTER message, returns the eid
  *	of the new master.
+ * ret_lsnp: On DB_REP_ISPERM and DB_REP_NOTPERM returns, contains the
+ *	lsn of the maximum permanent or current not permanent log record
+ *	(respectively).
  *
- * PUBLIC: int __rep_process_message __P((DB_ENV *, DBT *, DBT *, int *));
+ * PUBLIC: int __rep_process_message __P((DB_ENV *, DBT *, DBT *, int *,
+ * PUBLIC:     DB_LSN *));
  */
 int
-__rep_process_message(dbenv, control, rec, eidp)
+__rep_process_message(dbenv, control, rec, eidp, ret_lsnp)
 	DB_ENV *dbenv;
 	DBT *control, *rec;
 	int *eidp;
+	DB_LSN *ret_lsnp;
 {
 	DB_LOG *dblp;
 	DB_LOGC *logc;
-	DB_LSN init_lsn, lsn, newfilelsn, oldfilelsn;
+	DB_LSN endlsn, lsn, oldfilelsn;
 	DB_REP *db_rep;
-	DBT *d, data_dbt, lsndbt, mylog;
+	DBT *d, data_dbt, mylog;
 	LOG *lp;
+	REGENV *renv;
+	REGINFO *infop;
 	REP *rep;
 	REP_CONTROL *rp;
 	REP_VOTE_INFO *vi;
-	u_int32_t bytes, gen, gbytes, type, unused;
-	int check_limit, cmp, done, do_req, i;
-	int master, old, recovering, ret, t_ret, *tally;
+	u_int32_t bytes, egen, flags, gen, gbytes, rectype, type;
+	int check_limit, cmp, done, do_req, is_dup;
+	int master, match, old, recovering, ret, t_ret;
+	time_t savetime;
+#ifdef DIAGNOSTIC
+	DB_MSGBUF mb;
+#endif
 
 	PANIC_CHECK(dbenv);
-	ENV_REQUIRES_CONFIG(dbenv, dbenv->tx_handle, "rep_stat", DB_INIT_TXN);
+	ENV_REQUIRES_CONFIG(dbenv, dbenv->rep_handle, "rep_process_message",
+	    DB_INIT_REP);
 
 	/* Control argument must be non-Null. */
 	if (control == NULL || control->size == 0) {
@@ -73,37 +154,61 @@ __rep_process_message(dbenv, control, rec, eidp)
 		return (EINVAL);
 	}
 
+	if (!IS_REP_MASTER(dbenv) && !IS_REP_CLIENT(dbenv)) {
+		__db_err(dbenv,
+	"Environment not configured as replication master or client");
+		return (EINVAL);
+	}
+
 	ret = 0;
 	db_rep = dbenv->rep_handle;
 	rep = db_rep->region;
 	dblp = dbenv->lg_handle;
 	lp = dblp->reginfo.primary;
+	infop = dbenv->reginfo;
+	renv = infop->primary;
+	rp = (REP_CONTROL *)control->data;
+	if (ret_lsnp != NULL)
+		ZERO_LSN(*ret_lsnp);
 
-	MUTEX_LOCK(dbenv, db_rep->mutexp);
+	/*
+	 * Acquire the replication lock.
+	 */
+	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+	if (rep->start_th != 0) {
+		/*
+		 * If we're racing with a thread in rep_start, then
+		 * just ignore the message and return.
+		 */
+		RPRINT(dbenv, rep, (dbenv, &mb,
+		    "Racing rep_start, ignore message."));
+		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+		goto out;
+	}
+	rep->msg_th++;
 	gen = rep->gen;
-	recovering = F_ISSET(rep, REP_F_RECOVER);
+	recovering = rep->in_recovery || F_ISSET(rep, REP_F_RECOVER_MASK);
+	savetime = renv->rep_timestamp;
 
 	rep->stat.st_msgs_processed++;
-	MUTEX_UNLOCK(dbenv, db_rep->mutexp);
-
-	rp = (REP_CONTROL *)control->data;
+	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
 
-#if 0
-	__rep_print_message(dbenv, *eidp, rp, "rep_process_message");
-#endif
+	REP_PRINT_MESSAGE(dbenv, *eidp, rp, "rep_process_message");
 
 	/* Complain if we see an improper version number. */
 	if (rp->rep_version != DB_REPVERSION) {
 		__db_err(dbenv,
-		    "unexpected replication message version %d, expected %d",
-		    rp->rep_version, DB_REPVERSION);
-		return (EINVAL);
+		    "unexpected replication message version %lu, expected %d",
+		    (u_long)rp->rep_version, DB_REPVERSION);
+		ret = EINVAL;
+		goto errlock;
 	}
 	if (rp->log_version != DB_LOGVERSION) {
 		__db_err(dbenv,
-		    "unexpected log record version %d, expected %d",
-		    rp->log_version, DB_LOGVERSION);
-		return (EINVAL);
+		    "unexpected log record version %lu, expected %d",
+		    (u_long)rp->log_version, DB_LOGVERSION);
+		ret = EINVAL;
+		goto errlock;
 	}
 
 	/*
@@ -112,250 +217,506 @@ __rep_process_message(dbenv, control, rec, eidp)
 	 * to get in sync.
 	 */
 	if (rp->gen < gen && rp->rectype != REP_ALIVE_REQ &&
-	    rp->rectype != REP_NEWCLIENT && rp->rectype != REP_MASTER_REQ) {
+	    rp->rectype != REP_NEWCLIENT && rp->rectype != REP_MASTER_REQ &&
+	    rp->rectype != REP_DUPMASTER) {
 		/*
 		 * We don't hold the rep mutex, and could miscount if we race.
 		 */
 		rep->stat.st_msgs_badgen++;
-		return (0);
+		goto errlock;
+	}
+
+	if (rp->gen > gen) {
+		/*
+		 * If I am a master and am out of date with a lower generation
+		 * number, I am in bad shape and should downgrade.
+		 */
+		if (F_ISSET(rep, REP_F_MASTER)) {
+			rep->stat.st_dupmasters++;
+			ret = DB_REP_DUPMASTER;
+			if (rp->rectype != REP_DUPMASTER)
+				(void)__rep_send_message(dbenv,
+				    DB_EID_BROADCAST, REP_DUPMASTER,
+				    NULL, NULL, 0);
+			goto errlock;
+		}
+
+		/*
+		 * I am a client and am out of date.  If this is an election,
+		 * or a response from the first site I contacted, then I can
+		 * accept the generation number and participate in future
+		 * elections and communication. Otherwise, I need to hear about
+		 * a new master and sync up.
+		 */
+		if (rp->rectype == REP_ALIVE ||
+		    rp->rectype == REP_VOTE1 || rp->rectype == REP_VOTE2) {
+			MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+			RPRINT(dbenv, rep, (dbenv, &mb,
+			    "Updating gen from %lu to %lu",
+			    (u_long)gen, (u_long)rp->gen));
+			rep->master_id = DB_EID_INVALID;
+			gen = rep->gen = rp->gen;
+			/*
+			 * Updating of egen will happen when we process the
+			 * message below for each message type.
+			 */
+			MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+			if (rp->rectype == REP_ALIVE)
+				(void)__rep_send_message(dbenv,
+				    DB_EID_BROADCAST, REP_MASTER_REQ, NULL,
+				    NULL, 0);
+		} else if (rp->rectype != REP_NEWMASTER) {
+			(void)__rep_send_message(dbenv,
+			    DB_EID_BROADCAST, REP_MASTER_REQ, NULL, NULL, 0);
+			goto errlock;
+		}
+
+		/*
+		 * If you get here, then you're a client and either you're
+		 * in an election or you have a NEWMASTER or an ALIVE message
+		 * whose processing will do the right thing below.
+		 */
+
 	}
-	if (rp->gen > gen && rp->rectype != REP_ALIVE &&
-	    rp->rectype != REP_NEWMASTER)
-		return (__rep_send_message(dbenv,
-		    DB_EID_BROADCAST, REP_MASTER_REQ, NULL, NULL, 0));
 
 	/*
 	 * We need to check if we're in recovery and if we are
-	 * then we need to ignore any messages except VERIFY, VOTE,
-	 * ELECT (the master might fail while we are recovering), and
-	 * ALIVE_REQ.
+	 * then we need to ignore any messages except VERIFY*, VOTE*,
+	 * NEW* and ALIVE_REQ, or backup related messages: UPDATE*,
+	 * PAGE* and FILE*.  We need to also accept LOG messages
+	 * if we're copying the log for recovery/backup.
 	 */
-	if (recovering)
-		switch(rp->rectype) {
-			case REP_ALIVE:
-			case REP_ALIVE_REQ:
-			case REP_ELECT:
-			case REP_NEWCLIENT:
-			case REP_NEWMASTER:
-			case REP_NEWSITE:
-			case REP_VERIFY:
-				R_LOCK(dbenv, &dblp->reginfo);
-				cmp = log_compare(&lp->verify_lsn, &rp->lsn);
-				R_UNLOCK(dbenv, &dblp->reginfo);
-				if (cmp != 0)
-					goto skip;
-				/* FALLTHROUGH */
-			case REP_VOTE1:
-			case REP_VOTE2:
-				break;
-			default:
-skip:				/*
-				 * We don't hold the rep mutex, and could
-				 * miscount if we race.
+	if (recovering) {
+		switch (rp->rectype) {
+		case REP_VERIFY:
+			MUTEX_LOCK(dbenv, db_rep->db_mutexp);
+			cmp = log_compare(&lp->verify_lsn, &rp->lsn);
+			MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+			if (cmp != 0)
+				goto skip;
+			break;
+		case REP_NEWFILE:
+		case REP_LOG:
+		case REP_LOG_MORE:
+			if (!F_ISSET(rep, REP_F_RECOVER_LOG))
+				goto skip;
+			/*
+			 * If we're recovering the log we only want
+			 * log records that are in the range we need
+			 * to recover.  Otherwise we can end up storing
+			 * a huge number of "new" records, only to
+			 * truncate the temp database later after we
+			 * run recovery.
+			 */
+			if (log_compare(&rp->lsn, &rep->last_lsn) > 0)
+				goto skip;
+			break;
+		case REP_ALIVE:
+		case REP_ALIVE_REQ:
+		case REP_DUPMASTER:
+		case REP_FILE_FAIL:
+		case REP_NEWCLIENT:
+		case REP_NEWMASTER:
+		case REP_NEWSITE:
+		case REP_PAGE:
+		case REP_PAGE_FAIL:
+		case REP_PAGE_MORE:
+		case REP_PAGE_REQ:
+		case REP_UPDATE:
+		case REP_UPDATE_REQ:
+		case REP_VERIFY_FAIL:
+		case REP_VOTE1:
+		case REP_VOTE2:
+			break;
+		default:
+skip:
+			/* Check for need to retransmit. */
+			/* Not holding rep_mutex, may miscount */
+			rep->stat.st_msgs_recover++;
+			MUTEX_LOCK(dbenv, db_rep->db_mutexp);
+			do_req = __rep_check_doreq(dbenv, rep);
+			MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+			if (do_req) {
+				/*
+				 * Don't respond to a MASTER_REQ with
+				 * a MASTER_REQ.
 				 */
-				rep->stat.st_msgs_recover++;
-
-				/* Check for need to retransmit. */
-				R_LOCK(dbenv, &dblp->reginfo);
-				do_req = *eidp == rep->master_id &&
-				    ++lp->rcvd_recs >= lp->wait_recs;
-				if (do_req) {
-					lp->wait_recs *= 2;
-					if (lp->wait_recs + rep->max_gap)
-						lp->wait_recs = rep->max_gap;
-					lp->rcvd_recs = 0;
-					lsn = lp->verify_lsn;
-				}
-				R_UNLOCK(dbenv, &dblp->reginfo);
-				if (do_req)
-					ret = __rep_send_message(dbenv, *eidp,
-					    REP_VERIFY_REQ, &lsn, NULL, 0);
-
-				return (ret);
+				if (rep->master_id == DB_EID_INVALID &&
+				    rp->rectype != REP_MASTER_REQ)
+					(void)__rep_send_message(dbenv,
+					    DB_EID_BROADCAST,
+					    REP_MASTER_REQ,
+					    NULL, NULL, 0);
+				else if (*eidp == rep->master_id)
+					ret = __rep_resend_req(dbenv, *eidp);
+			}
+			goto errlock;
 		}
+	}
 
-	switch(rp->rectype) {
+	switch (rp->rectype) {
 	case REP_ALIVE:
-		ANYSITE(dbenv);
-		if (rp->gen > gen && rp->flags)
-			return (__rep_new_master(dbenv, rp, *eidp));
+		ANYSITE(rep);
+		egen = *(u_int32_t *)rec->data;
+		MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+		RPRINT(dbenv, rep, (dbenv, &mb,
+		    "Received ALIVE egen of %lu, mine %lu",
+		    (u_long)egen, (u_long)rep->egen));
+		if (egen > rep->egen) {
+			/*
+			 * We're changing egen, need to clear out any old
+			 * election information.
+			 */
+			__rep_elect_done(dbenv, rep);
+			rep->egen = egen;
+		}
+		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
 		break;
 	case REP_ALIVE_REQ:
-		ANYSITE(dbenv);
+		ANYSITE(rep);
 		dblp = dbenv->lg_handle;
 		R_LOCK(dbenv, &dblp->reginfo);
 		lsn = ((LOG *)dblp->reginfo.primary)->lsn;
 		R_UNLOCK(dbenv, &dblp->reginfo);
-		return (__rep_send_message(dbenv,
-		    *eidp, REP_ALIVE, &lsn, NULL,
-		    F_ISSET(dbenv, DB_ENV_REP_MASTER) ? 1 : 0));
+		MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+		egen = rep->egen;
+		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+		data_dbt.data = &egen;
+		data_dbt.size = sizeof(egen);
+		(void)__rep_send_message(dbenv,
+		    *eidp, REP_ALIVE, &lsn, &data_dbt, 0);
+		goto errlock;
+	case REP_DUPMASTER:
+		if (F_ISSET(rep, REP_F_MASTER))
+			ret = DB_REP_DUPMASTER;
+		goto errlock;
 	case REP_ALL_REQ:
-		MASTER_ONLY(dbenv);
+		MASTER_ONLY(rep, rp);
 		gbytes  = bytes = 0;
-		MUTEX_LOCK(dbenv, db_rep->mutexp);
+		MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
 		gbytes = rep->gbytes;
 		bytes = rep->bytes;
-		MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
 		check_limit = gbytes != 0 || bytes != 0;
-		if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
-			return (ret);
+		if ((ret = __log_cursor(dbenv, &logc)) != 0)
+			goto errlock;
 		memset(&data_dbt, 0, sizeof(data_dbt));
 		oldfilelsn = lsn = rp->lsn;
 		type = REP_LOG;
-		for (ret = logc->get(logc, &rp->lsn, &data_dbt, DB_SET);
+		flags = IS_ZERO_LSN(rp->lsn) ||
+		    IS_INIT_LSN(rp->lsn) ?  DB_FIRST : DB_SET;
+		for (ret = __log_c_get(logc, &lsn, &data_dbt, flags);
 		    ret == 0 && type == REP_LOG;
-		    ret = logc->get(logc, &lsn, &data_dbt, DB_NEXT)) {
+		    ret = __log_c_get(logc, &lsn, &data_dbt, DB_NEXT)) {
 			/*
-			 * lsn.offset will only be 0 if this is the
-			 * beginning of the log;  DB_SET, but not DB_NEXT,
-			 * can set the log cursor to [n][0].
+			 * When a log file changes, we'll have a real log
+			 * record with some lsn [n][m], and we'll also want
+			 * to send a NEWFILE message with lsn [n-1][MAX].
 			 */
-			if (lsn.offset == 0)
-				ret = __rep_send_message(dbenv, *eidp,
-				    REP_NEWFILE, &lsn, NULL, 0);
-			else {
+			if (lsn.file != oldfilelsn.file)
+				(void)__rep_send_message(dbenv,
+				    *eidp, REP_NEWFILE, &oldfilelsn, NULL, 0);
+			if (check_limit) {
 				/*
-				 * DB_NEXT will never run into offsets
-				 * of 0;  thus, when a log file changes,
-				 * we'll have a real log record with
-				 * some lsn [n][m], and we'll also want to send
-				 * a NEWFILE message with lsn [n][0].
-				 * So that the client can detect gaps,
-				 * send in the rec parameter the
-				 * last LSN in the old file.
+				 * data_dbt.size is only the size of the log
+				 * record;  it doesn't count the size of the
+				 * control structure. Factor that in as well
+				 * so we're not off by a lot if our log records
+				 * are small.
 				 */
-				if (lsn.file != oldfilelsn.file) {
-					newfilelsn.file = lsn.file;
-					newfilelsn.offset = 0;
-
-					memset(&lsndbt, 0, sizeof(DBT));
-					lsndbt.size = sizeof(DB_LSN);
-					lsndbt.data = &oldfilelsn;
-
-					if ((ret = __rep_send_message(dbenv,
-					    *eidp, REP_NEWFILE, &newfilelsn,
-					    &lsndbt, 0)) != 0)
-						break;
-				}
-				if (check_limit) {
+				while (bytes <
+				    data_dbt.size + sizeof(REP_CONTROL)) {
+					if (gbytes > 0) {
+						bytes += GIGABYTE;
+						--gbytes;
+						continue;
+					}
 					/*
-					 * data_dbt.size is only the size of
-					 * the log record;  it doesn't count
-					 * the size of the control structure.
-					 * Factor that in as well so we're
-					 * not off by a lot if our log
-					 * records are small.
+					 * We don't hold the rep mutex,
+					 * and may miscount.
 					 */
-					while (bytes < data_dbt.size +
-					    sizeof(REP_CONTROL)) {
-						if (gbytes > 0) {
-							bytes += GIGABYTE;
-							--gbytes;
-							continue;
-						}
-						/*
-						 * We don't hold the rep mutex,
-						 * and may miscount.
-						 */
-						rep->stat.st_nthrottles++;
-						type = REP_LOG_MORE;
-						goto send;
-					}
-					bytes -= (data_dbt.size +
-					    sizeof(REP_CONTROL));
+					rep->stat.st_nthrottles++;
+					type = REP_LOG_MORE;
+					goto send;
 				}
-send:				ret = __rep_send_message(dbenv, *eidp,
-				    type, &lsn, &data_dbt, 0);
+				bytes -= (data_dbt.size + sizeof(REP_CONTROL));
 			}
 
+send:			if (__rep_send_message(dbenv, *eidp, type,
+			    &lsn, &data_dbt, DB_LOG_RESEND) != 0)
+				break;
+
 			/*
-			 * In case we're about to change files and need it
-			 * for a NEWFILE message, save the current LSN.
+			 * If we are about to change files, then we'll need the
+			 * last LSN in the previous file.  Save it here.
 			 */
 			oldfilelsn = lsn;
+			oldfilelsn.offset += logc->c_len;
 		}
 
 		if (ret == DB_NOTFOUND)
 			ret = 0;
-		if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+		if ((t_ret = __log_c_close(logc)) != 0 && ret == 0)
 			ret = t_ret;
-		return (ret);
-	case REP_ELECT:
-		if (F_ISSET(dbenv, DB_ENV_REP_MASTER)) {
-			R_LOCK(dbenv, &dblp->reginfo);
-			lsn = lp->lsn;
-			R_UNLOCK(dbenv, &dblp->reginfo);
-			MUTEX_LOCK(dbenv, db_rep->mutexp);
-			rep->gen++;
-			MUTEX_UNLOCK(dbenv, db_rep->mutexp);
-			return (__rep_send_message(dbenv,
-			    *eidp, REP_NEWMASTER, &lsn, NULL, 0));
-		}
-		MUTEX_LOCK(dbenv, db_rep->mutexp);
-		ret = IN_ELECTION(rep) ? 0 : DB_REP_HOLDELECTION;
-		MUTEX_UNLOCK(dbenv, db_rep->mutexp);
-		return (ret);
+		goto errlock;
 #ifdef NOTYET
 	case REP_FILE: /* TODO */
-		CLIENT_ONLY(dbenv);
+		CLIENT_ONLY(rep, rp);
+		MASTER_CHECK(dbenv, *eidp, rep);
 		break;
 	case REP_FILE_REQ:
-		MASTER_ONLY(dbenv);
-		return (__rep_send_file(dbenv, rec, *eidp));
-		break;
+		MASTER_ONLY(rep, rp);
+		ret = __rep_send_file(dbenv, rec, *eidp);
+		goto errlock;
 #endif
+	case REP_FILE_FAIL:
+		CLIENT_ONLY(rep, rp);
+		MASTER_CHECK(dbenv, *eidp, rep);
+		/*
+		 * XXX
+		 */
+		break;
 	case REP_LOG:
 	case REP_LOG_MORE:
-		CLIENT_ONLY(dbenv);
-		if ((ret = __rep_apply(dbenv, rp, rec)) != 0)
-			return (ret);
+		CLIENT_ONLY(rep, rp);
+		MASTER_CHECK(dbenv, *eidp, rep);
+		is_dup = 0;
+		ret = __rep_apply(dbenv, rp, rec, ret_lsnp, &is_dup);
+		switch (ret) {
+		/*
+		 * We're in an internal backup and we've gotten 
+		 * all the log we need to run recovery.  Do so now.
+		 */
+		case DB_REP_LOGREADY:
+			if ((ret = __log_flush(dbenv, NULL)) != 0)
+				goto errlock;
+			if ((ret = __rep_verify_match(dbenv, &rep->last_lsn,
+			    savetime)) == 0) {
+				MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+				ZERO_LSN(rep->first_lsn);
+				ZERO_LSN(rep->last_lsn);
+				F_CLR(rep, REP_F_RECOVER_LOG);
+				MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+			}
+			break;
+		/*
+		 * If we get any of the "normal" returns, we only process
+		 * LOG_MORE if this is not a duplicate record.  If the 
+		 * record is a duplicate we don't want to handle LOG_MORE
+		 * and request a multiple data stream (or trigger internal
+		 * initialization) since this could be a very old record
+		 * that no longer exists on the master.
+		 */
+		case DB_REP_ISPERM:
+		case DB_REP_NOTPERM:
+		case 0:
+			if (is_dup)
+				goto errlock;
+			else
+				break;
+		/*
+		 * Any other return (errors), we're done.
+		 */
+		default:
+			goto errlock;
+		}
 		if (rp->rectype == REP_LOG_MORE) {
-			MUTEX_LOCK(dbenv, db_rep->db_mutexp);
+			MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
 			master = rep->master_id;
-			MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+			MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
 			R_LOCK(dbenv, &dblp->reginfo);
 			lsn = lp->lsn;
 			R_UNLOCK(dbenv, &dblp->reginfo);
-			ret = __rep_send_message(dbenv, master,
-			    REP_ALL_REQ, &lsn, NULL, 0);
+			/*
+			 * If the master_id is invalid, this means that since
+			 * the last record was sent, somebody declared an
+			 * election and we may not have a master to request
+			 * things of.
+			 *
+			 * This is not an error;  when we find a new master,
+			 * we'll re-negotiate where the end of the log is and
+			 * try to bring ourselves up to date again anyway.
+			 */
+			MUTEX_LOCK(dbenv, db_rep->db_mutexp);
+			if (master == DB_EID_INVALID)
+				ret = 0;
+			/*
+			 * If we've asked for a bunch of records, it could
+			 * either be from a LOG_REQ or ALL_REQ.  If we're
+			 * waiting for a gap to be filled, call loggap_req,
+			 * otherwise use ALL_REQ again.
+			 */
+			else if (IS_ZERO_LSN(lp->waiting_lsn)) {
+				MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+				if (__rep_send_message(dbenv,
+				    master, REP_ALL_REQ, &lsn, NULL, 0) != 0)
+					break;
+			} else {
+				__rep_loggap_req(dbenv, rep, &lsn, 1);
+				MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+			}
 		}
-		return (ret);
+		goto errlock;
 	case REP_LOG_REQ:
-		MASTER_ONLY(dbenv);
-		if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
-			return (ret);
-		memset(&data_dbt, 0, sizeof(data_dbt));
-		lsn = rp->lsn;
-
+		MASTER_ONLY(rep, rp);
+		if (rec != NULL && rec->size != 0) {
+			RPRINT(dbenv, rep, (dbenv, &mb,
+			    "[%lu][%lu]: LOG_REQ max lsn: [%lu][%lu]",
+			    (u_long) rp->lsn.file, (u_long)rp->lsn.offset,
+			    (u_long)((DB_LSN *)rec->data)->file,
+			    (u_long)((DB_LSN *)rec->data)->offset));
+		}
 		/*
 		 * There are three different cases here.
 		 * 1. We asked for a particular LSN and got it.
-		 * 2. We asked for an LSN of X,0 which is invalid and got the
-		 * 	first log record in a particular file.
-		 * 3. We asked for an LSN and it's not found because it is
+		 * 2. We asked for an LSN and it's not found because it is
 		 *	beyond the end of a log file and we need a NEWFILE msg.
+		 *	and then the record that was requested.
+		 * 3. We asked for an LSN and it simply doesn't exist, but
+		 *    doesn't meet any of those other criteria, in which case
+		 *    it's an error (that should never happen).
+		 * If we have a valid LSN and the request has a data_dbt with
+		 * it, then we need to send all records up to the LSN in the
+		 * data dbt.
+		 */
+		oldfilelsn = lsn = rp->lsn;
+		if ((ret = __log_cursor(dbenv, &logc)) != 0)
+			goto errlock;
+		memset(&data_dbt, 0, sizeof(data_dbt));
+		ret = __log_c_get(logc, &lsn, &data_dbt, DB_SET);
+
+		if (ret == 0) /* Case 1 */
+			(void)__rep_send_message(dbenv,
+			   *eidp, REP_LOG, &lsn, &data_dbt, DB_LOG_RESEND);
+		else if (ret == DB_NOTFOUND) {
+			R_LOCK(dbenv, &dblp->reginfo);
+			endlsn = lp->lsn;
+			R_UNLOCK(dbenv, &dblp->reginfo);
+			if (endlsn.file > lsn.file) {
+				/*
+				 * Case 2:
+				 * Need to find the LSN of the last record in
+				 * file lsn.file so that we can send it with
+				 * the NEWFILE call.  In order to do that, we
+				 * need to try to get {lsn.file + 1, 0} and
+				 * then backup.
+				 */
+				endlsn.file = lsn.file + 1;
+				endlsn.offset = 0;
+				if ((ret = __log_c_get(logc,
+				    &endlsn, &data_dbt, DB_SET)) != 0 ||
+				    (ret = __log_c_get(logc,
+					&endlsn, &data_dbt, DB_PREV)) != 0) {
+					RPRINT(dbenv, rep, (dbenv, &mb,
+					    "Unable to get prev of [%lu][%lu]",
+					    (u_long)lsn.file,
+					    (u_long)lsn.offset));
+					/*
+					 * We want to push the error back
+					 * to the client so that the client
+					 * does an internal backup.  The
+					 * client asked for a log record
+					 * we no longer have and it is
+					 * outdated.
+					 * XXX - This could be optimized by
+					 * having the master perform and
+					 * send a REP_UPDATE message.  We
+					 * currently want the client to set
+					 * up its 'update' state prior to
+					 * requesting REP_UPDATE_REQ.
+					 */
+					ret = 0;
+					(void)__rep_send_message(dbenv, *eidp,
+					    REP_VERIFY_FAIL, &rp->lsn, NULL, 0);
+				} else {
+					endlsn.offset += logc->c_len;
+					(void)__rep_send_message(dbenv, *eidp,
+					    REP_NEWFILE, &endlsn, NULL, 0);
+				}
+			} else {
+				/* Case 3 */
+				__db_err(dbenv,
+				    "Request for LSN [%lu][%lu] fails",
+				    (u_long)lsn.file, (u_long)lsn.offset);
+				DB_ASSERT(0);
+				ret = EINVAL;
+			}
+		}
+
+		/*
+		 * If the user requested a gap, send the whole thing,
+		 * while observing the limits from set_rep_limit.
 		 */
-		ret = logc->get(logc, &rp->lsn, &data_dbt, DB_SET);
-		cmp = log_compare(&lsn, &rp->lsn);
-
-		if (ret == 0 && cmp == 0) /* Case 1 */
-			ret = __rep_send_message(dbenv, *eidp,
-				    REP_LOG, &rp->lsn, &data_dbt, 0);
-		else if (ret == DB_NOTFOUND ||
-		    (ret == 0 && cmp < 0 && rp->lsn.offset == 0))
-			/* Cases 2 and 3: Send a NEWFILE message. */
-			ret = __rep_send_message(dbenv, *eidp,
-			    REP_NEWFILE, &lsn, NULL, 0);
-
-		if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+		MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+		gbytes = rep->gbytes;
+		bytes = rep->bytes;
+		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+		check_limit = gbytes != 0 || bytes != 0;
+		type = REP_LOG;
+		while (ret == 0 && rec != NULL && rec->size != 0 &&
+		    type == REP_LOG) {
+			if ((ret =
+			    __log_c_get(logc, &lsn, &data_dbt, DB_NEXT)) != 0) {
+				if (ret == DB_NOTFOUND)
+					ret = 0;
+				break;
+			}
+			if (log_compare(&lsn, (DB_LSN *)rec->data) >= 0)
+				break;
+			/*
+			 * When a log file changes, we'll have a real log
+			 * record with some lsn [n][m], and we'll also want
+			 * to send a NEWFILE message with lsn [n-1][MAX].
+			 */
+			if (lsn.file != oldfilelsn.file)
+				(void)__rep_send_message(dbenv,
+				    *eidp, REP_NEWFILE, &oldfilelsn, NULL, 0);
+			if (check_limit) {
+				/*
+				 * data_dbt.size is only the size of the log
+				 * record;  it doesn't count the size of the
+				 * control structure. Factor that in as well
+				 * so we're not off by a lot if our log records
+				 * are small.
+				 */
+				while (bytes <
+				    data_dbt.size + sizeof(REP_CONTROL)) {
+					if (gbytes > 0) {
+						bytes += GIGABYTE;
+						--gbytes;
+						continue;
+					}
+					/*
+					 * We don't hold the rep mutex,
+					 * and may miscount.
+					 */
+					rep->stat.st_nthrottles++;
+					type = REP_LOG_MORE;
+					goto send1;
+				}
+				bytes -= (data_dbt.size + sizeof(REP_CONTROL));
+			}
+
+send1:			 if (__rep_send_message(dbenv, *eidp, type,
+			    &lsn, &data_dbt, DB_LOG_RESEND) != 0)
+				break;
+			/*
+			 * If we are about to change files, then we'll need the
+			 * last LSN in the previous file.  Save it here.
+			 */
+			oldfilelsn = lsn;
+			oldfilelsn.offset += logc->c_len;
+		}
+
+		if ((t_ret = __log_c_close(logc)) != 0 && ret == 0)
 			ret = t_ret;
-		return (ret);
+		goto errlock;
 	case REP_NEWSITE:
 		/* We don't hold the rep mutex, and may miscount. */
 		rep->stat.st_newsites++;
 
 		/* This is a rebroadcast; simply tell the application. */
-		if (F_ISSET(dbenv, DB_ENV_REP_MASTER)) {
+		if (F_ISSET(rep, REP_F_MASTER)) {
 			dblp = dbenv->lg_handle;
 			lp = dblp->reginfo.primary;
 			R_LOCK(dbenv, &dblp->reginfo);
@@ -364,164 +725,229 @@ send:				ret = __rep_send_message(dbenv, *eidp,
 			(void)__rep_send_message(dbenv,
 			    *eidp, REP_NEWMASTER, &lsn, NULL, 0);
 		}
-		return (DB_REP_NEWSITE);
+		ret = DB_REP_NEWSITE;
+		goto errlock;
 	case REP_NEWCLIENT:
 		/*
 		 * This message was received and should have resulted in the
 		 * application entering the machine ID in its machine table.
 		 * We respond to this with an ALIVE to send relevant information
-		 * to the new client.  But first, broadcast the new client's
-		 * record to all the clients.
+		 * to the new client (if we are a master, we'll send a
+		 * NEWMASTER, so we only need to send the ALIVE if we're a
+		 * client).  But first, broadcast the new client's record to
+		 * all the clients.
 		 */
-		if ((ret = __rep_send_message(dbenv,
-		    DB_EID_BROADCAST, REP_NEWSITE, &rp->lsn, rec, 0)) != 0)
-			return (ret);
-
-		if (F_ISSET(dbenv, DB_ENV_REP_CLIENT))
-			return (0);
-
-		 /* FALLTHROUGH */
+		(void)__rep_send_message(dbenv,
+		    DB_EID_BROADCAST, REP_NEWSITE, &rp->lsn, rec, 0);
+
+		ret = DB_REP_NEWSITE;
+
+		if (F_ISSET(rep, REP_F_CLIENT)) {
+			MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+			egen = rep->egen;
+			if (*eidp == rep->master_id)
+				rep->master_id = DB_EID_INVALID;
+			MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+			data_dbt.data = &egen;
+			data_dbt.size = sizeof(egen);
+			(void)__rep_send_message(dbenv, DB_EID_BROADCAST,
+			    REP_ALIVE, &rp->lsn, &data_dbt, 0);
+			goto errlock;
+		}
+		/* FALLTHROUGH */
 	case REP_MASTER_REQ:
-		ANYSITE(dbenv);
-		if (F_ISSET(dbenv, DB_ENV_REP_CLIENT))
-			return (0);
-		dblp = dbenv->lg_handle;
-		lp = dblp->reginfo.primary;
-		R_LOCK(dbenv, &dblp->reginfo);
-		lsn = lp->lsn;
-		R_UNLOCK(dbenv, &dblp->reginfo);
-		return (__rep_send_message(dbenv,
-		    *eidp, REP_NEWMASTER, &lsn, NULL, 0));
+		if (F_ISSET(rep, REP_F_MASTER)) {
+			R_LOCK(dbenv, &dblp->reginfo);
+			lsn = lp->lsn;
+			R_UNLOCK(dbenv, &dblp->reginfo);
+			(void)__rep_send_message(dbenv,
+			    DB_EID_BROADCAST, REP_NEWMASTER, &lsn, NULL, 0);
+		}
+		/*
+		 * If there is no master, then we could get into a state
+		 * where an old client lost the initial ALIVE message and
+		 * is calling an election under an old gen and can
+		 * never get to the current gen.
+		 */
+		if (F_ISSET(rep, REP_F_CLIENT) && rp->gen < gen) {
+			MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+			egen = rep->egen;
+			if (*eidp == rep->master_id)
+				rep->master_id = DB_EID_INVALID;
+			MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+			data_dbt.data = &egen;
+			data_dbt.size = sizeof(egen);
+			(void)__rep_send_message(dbenv, *eidp,
+			    REP_ALIVE, &rp->lsn, &data_dbt, 0);
+			goto errlock;
+		}
+		goto errlock;
 	case REP_NEWFILE:
-		CLIENT_ONLY(dbenv);
-		return (__rep_apply(dbenv, rp, rec));
+		CLIENT_ONLY(rep, rp);
+		MASTER_CHECK(dbenv, *eidp, rep);
+		ret = __rep_apply(dbenv, rp, rec, ret_lsnp, NULL);
+		goto errlock;
 	case REP_NEWMASTER:
-		ANYSITE(dbenv);
-		if (F_ISSET(dbenv, DB_ENV_REP_MASTER) &&
+		ANYSITE(rep);
+		if (F_ISSET(rep, REP_F_MASTER) &&
 		    *eidp != dbenv->rep_eid) {
 			/* We don't hold the rep mutex, and may miscount. */
 			rep->stat.st_dupmasters++;
-			return (DB_REP_DUPMASTER);
+			ret = DB_REP_DUPMASTER;
+			(void)__rep_send_message(dbenv,
+			    DB_EID_BROADCAST, REP_DUPMASTER, NULL, NULL, 0);
+			goto errlock;
 		}
-		return (__rep_new_master(dbenv, rp, *eidp));
-	case REP_PAGE: /* TODO */
-		CLIENT_ONLY(dbenv);
+		ret = __rep_new_master(dbenv, rp, *eidp);
+		goto errlock;
+	case REP_PAGE:
+	case REP_PAGE_MORE:
+		CLIENT_ONLY(rep, rp);
+		MASTER_CHECK(dbenv, *eidp, rep);
+		ret = __rep_page(dbenv, *eidp, rp, rec);
+		break;
+	case REP_PAGE_FAIL:
+		CLIENT_ONLY(rep, rp);
+		MASTER_CHECK(dbenv, *eidp, rep);
+		ret = __rep_page_fail(dbenv, *eidp, rec);
 		break;
-	case REP_PAGE_REQ: /* TODO */
-		MASTER_ONLY(dbenv);
+	case REP_PAGE_REQ:
+		MASTER_ONLY(rep, rp);
+		MASTER_UPDATE(dbenv, renv);
+		ret = __rep_page_req(dbenv, *eidp, rec);
 		break;
-	case REP_PLIST: /* TODO */
-		CLIENT_ONLY(dbenv);
+	case REP_UPDATE:
+		CLIENT_ONLY(rep, rp);
+		MASTER_CHECK(dbenv, *eidp, rep);
+
+		ret = __rep_update_setup(dbenv, *eidp, rp, rec);
 		break;
-	case REP_PLIST_REQ: /* TODO */
-		MASTER_ONLY(dbenv);
+	case REP_UPDATE_REQ:
+		MASTER_ONLY(rep, rp);
+		infop = dbenv->reginfo;
+		renv = infop->primary;
+		MASTER_UPDATE(dbenv, renv);
+		ret = __rep_update_req(dbenv, *eidp);
 		break;
 	case REP_VERIFY:
-		CLIENT_ONLY(dbenv);
-		DB_ASSERT((F_ISSET(rep, REP_F_RECOVER) &&
-		    !IS_ZERO_LSN(lp->verify_lsn)) ||
-		    (!F_ISSET(rep, REP_F_RECOVER) &&
-		    IS_ZERO_LSN(lp->verify_lsn)));
+		CLIENT_ONLY(rep, rp);
+		MASTER_CHECK(dbenv, *eidp, rep);
 		if (IS_ZERO_LSN(lp->verify_lsn))
-			return (0);
+			goto errlock;
 
-		if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
-			return (ret);
+		if ((ret = __log_cursor(dbenv, &logc)) != 0)
+			goto errlock;
 		memset(&mylog, 0, sizeof(mylog));
-		if ((ret = logc->get(logc, &rp->lsn, &mylog, DB_SET)) != 0)
+		if ((ret = __log_c_get(logc, &rp->lsn, &mylog, DB_SET)) != 0)
 			goto rep_verify_err;
+		match = 0;
+		memcpy(&rectype, mylog.data, sizeof(rectype));
 		if (mylog.size == rec->size &&
-		    memcmp(mylog.data, rec->data, rec->size) == 0) {
-			/*
-			 * If we're a logs-only client, we can simply truncate
-			 * the log to the point where it last agreed with the
-			 * master's;  otherwise, recover to that point.
-			 */
-			R_LOCK(dbenv, &dblp->reginfo);
-			ZERO_LSN(lp->verify_lsn);
-			R_UNLOCK(dbenv, &dblp->reginfo);
-			if (F_ISSET(dbenv, DB_ENV_REP_LOGSONLY)) {
-				INIT_LSN(init_lsn);
-				if ((ret = dbenv->log_flush(dbenv,
-				    &rp->lsn)) != 0 ||
-				    (ret = __log_vtruncate(dbenv,
-				    &rp->lsn, &init_lsn)) != 0)
-					goto rep_verify_err;
-			} else if ((ret = __db_apprec(dbenv, &rp->lsn, 0)) != 0)
-				goto rep_verify_err;
-
-			/*
-			 * The log has been truncated (either by __db_apprec or
-			 * directly).  We want to make sure we're waiting for
-			 * the LSN at the new end-of-log, not some later point.
-			 */
-			R_LOCK(dbenv, &dblp->reginfo);
-			lp->ready_lsn = lp->lsn;
-			ZERO_LSN(lp->waiting_lsn);
-			R_UNLOCK(dbenv, &dblp->reginfo);
-
-			/*
-			 * Discard any log records we have queued;  we're
-			 * about to re-request them, and can't trust the
-			 * ones in the queue.
-			 */
-			MUTEX_LOCK(dbenv, db_rep->db_mutexp);
-			if ((ret = db_rep->rep_db->truncate(db_rep->rep_db,
-			    NULL, &unused, 0)) != 0) {
+		    memcmp(mylog.data, rec->data, rec->size) == 0)
+			match = 1;
+		DB_ASSERT(rectype == DB___txn_ckp);
+		/*
+		 * If we don't have a match, backup to the previous
+		 * checkpoint and try again.
+		 */
+		if (match == 0) {
+			ZERO_LSN(lsn);
+			if ((ret = __log_backup(dbenv, logc, &rp->lsn, &lsn,
+			    LASTCKP_CMP)) == 0) {
+				MUTEX_LOCK(dbenv, db_rep->db_mutexp);
+				lp->verify_lsn = lsn;
+				lp->rcvd_recs = 0;
+				lp->wait_recs = rep->request_gap;
 				MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
-				goto rep_verify_err;
-			}
-			rep->stat.st_log_queued = 0;
-			MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
-
-			MUTEX_LOCK(dbenv, db_rep->mutexp);
-			F_CLR(rep, REP_F_RECOVER);
-
-			/*
-			 * If the master_id is invalid, this means that since
-			 * the last record was sent, somebody declared an
-			 * election and we may not have a master to request
-			 * things of.
-			 *
-			 * This is not an error;  when we find a new master,
-			 * we'll re-negotiate where the end of the log is and
-			 * try to bring ourselves up to date again anyway.
-			 */
-			if ((master = rep->master_id) == DB_EID_INVALID) {
-				DB_ASSERT(IN_ELECTION(rep));
-				MUTEX_UNLOCK(dbenv, db_rep->mutexp);
-				ret = 0;
-			} else {
-				MUTEX_UNLOCK(dbenv, db_rep->mutexp);
-				ret = __rep_send_message(dbenv, master,
-				    REP_ALL_REQ, &rp->lsn, NULL, 0);
+				(void)__rep_send_message(dbenv,
+				    *eidp, REP_VERIFY_REQ, &lsn, NULL, 0);
+			} else if (ret == DB_NOTFOUND) {
+				/*
+				 * We've either run out of records because
+				 * logs have been removed or we've rolled back
+				 * all the way to the beginning.  In the latter
+				 * we don't think these sites were ever part of
+				 * the same environment and we'll say so.
+				 * In the former, request internal backup.
+				 */
+				if (rp->lsn.file == 1) {
+					__db_err(dbenv,
+			"Client was never part of master's environment");
+					ret = EINVAL;
+				} else {
+					rep->stat.st_outdated++;
+
+					R_LOCK(dbenv, &dblp->reginfo);
+					lsn = lp->lsn;
+					R_UNLOCK(dbenv, &dblp->reginfo);
+					MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+					F_CLR(rep, REP_F_RECOVER_VERIFY);
+					F_SET(rep, REP_F_RECOVER_UPDATE);
+					ZERO_LSN(rep->first_lsn);
+					MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+					(void)__rep_send_message(dbenv,
+					    *eidp, REP_UPDATE_REQ, NULL,
+					    NULL, 0);
+				}
 			}
-		} else if ((ret =
-		    logc->get(logc, &lsn, &mylog, DB_PREV)) == 0) {
-			R_LOCK(dbenv, &dblp->reginfo);
-			lp->verify_lsn = lsn;
-			lp->rcvd_recs = 0;
-			lp->wait_recs = rep->request_gap;
-			R_UNLOCK(dbenv, &dblp->reginfo);
-			ret = __rep_send_message(dbenv,
-			    *eidp, REP_VERIFY_REQ, &lsn, NULL, 0);
-		}
+		} else
+			ret = __rep_verify_match(dbenv, &rp->lsn, savetime);
 
-rep_verify_err:	if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+rep_verify_err:	if ((t_ret = __log_c_close(logc)) != 0 && ret == 0)
 			ret = t_ret;
-		return (ret);
+		goto errlock;
 	case REP_VERIFY_FAIL:
+		CLIENT_ONLY(rep, rp);
+		MASTER_CHECK(dbenv, *eidp, rep);
+		/*
+		 * If any recovery flags are set, but not VERIFY,
+		 * then we ignore this message.  We are already
+		 * in the middle of updating.
+		 */
+		if (F_ISSET(rep, REP_F_RECOVER_MASK) &&
+		    !F_ISSET(rep, REP_F_RECOVER_VERIFY))
+			goto errlock;
 		rep->stat.st_outdated++;
-		return (DB_REP_OUTDATED);
+
+		MUTEX_LOCK(dbenv, db_rep->db_mutexp);
+		MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+		/*
+		 * We don't want an old or delayed VERIFY_FAIL
+		 * message to throw us into internal initialization
+		 * when we shouldn't be.  
+		 *
+		 * Only go into internal initialization if:
+		 * We are in RECOVER_VERIFY and this LSN == verify_lsn.
+		 * We are not in any RECOVERY and we are expecting
+		 *    an LSN that no longer exists on the master.
+		 * Otherwise, ignore this message.
+		 */
+		if (((F_ISSET(rep, REP_F_RECOVER_VERIFY)) &&
+		    log_compare(&rp->lsn, &lp->verify_lsn) == 0) ||
+		    (F_ISSET(rep, REP_F_RECOVER_MASK) == 0 &&
+		    log_compare(&rp->lsn, &lp->ready_lsn) >= 0)) {
+			F_CLR(rep, REP_F_RECOVER_VERIFY);
+			F_SET(rep, REP_F_RECOVER_UPDATE);
+			ZERO_LSN(rep->first_lsn);
+			lp->wait_recs = rep->request_gap;
+			MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+			MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+			(void)__rep_send_message(dbenv,
+			    *eidp, REP_UPDATE_REQ, NULL, NULL, 0);
+		} else {
+			MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+			MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+		}
+		goto errlock;
 	case REP_VERIFY_REQ:
-		MASTER_ONLY(dbenv);
+		MASTER_ONLY(rep, rp);
 		type = REP_VERIFY;
-		if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
-			return (ret);
+		if ((ret = __log_cursor(dbenv, &logc)) != 0)
+			goto errlock;
 		d = &data_dbt;
 		memset(d, 0, sizeof(data_dbt));
 		F_SET(logc, DB_LOG_SILENT_ERR);
-		ret = logc->get(logc, &rp->lsn, d, DB_SET);
+		ret = __log_c_get(logc, &rp->lsn, d, DB_SET);
 		/*
 		 * If the LSN was invalid, then we might get a not
 		 * found, we might get an EIO, we could get anything.
@@ -538,204 +964,258 @@ rep_verify_err:	if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0)
 		if (ret != 0)
 			d = NULL;
 
-		ret = __rep_send_message(dbenv, *eidp, type, &rp->lsn, d, 0);
-		if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0)
-			ret = t_ret;
-		return (ret);
+		(void)__rep_send_message(dbenv, *eidp, type, &rp->lsn, d, 0);
+		ret = __log_c_close(logc);
+		goto errlock;
 	case REP_VOTE1:
-		if (F_ISSET(dbenv, DB_ENV_REP_MASTER)) {
-#ifdef DIAGNOSTIC
-			if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION))
-				__db_err(dbenv, "Master received vote");
-#endif
+		if (F_ISSET(rep, REP_F_MASTER)) {
+			RPRINT(dbenv, rep,
+			    (dbenv, &mb, "Master received vote"));
 			R_LOCK(dbenv, &dblp->reginfo);
 			lsn = lp->lsn;
 			R_UNLOCK(dbenv, &dblp->reginfo);
-			return (__rep_send_message(dbenv,
-			    *eidp, REP_NEWMASTER, &lsn, NULL, 0));
+			(void)__rep_send_message(dbenv,
+			    *eidp, REP_NEWMASTER, &lsn, NULL, 0);
+			goto errlock;
 		}
 
 		vi = (REP_VOTE_INFO *)rec->data;
-		MUTEX_LOCK(dbenv, db_rep->mutexp);
+		MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
 
 		/*
-		 * If you get a vote and you're not in an election, simply
-		 * return an indicator to hold an election which will trigger
-		 * this site to send its vote again.
+		 * If we get a vote from a later election gen, we
+		 * clear everything from the current one, and we'll
+		 * start over by tallying it.  If we get an old vote,
+		 * send an ALIVE to the old participant.
 		 */
-		if (!IN_ELECTION(rep)) {
-#ifdef DIAGNOSTIC
-			if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION))
-				__db_err(dbenv,
-				    "Not in election, but received vote1");
-#endif
-			ret = DB_REP_HOLDELECTION;
-			goto unlock;
+		RPRINT(dbenv, rep, (dbenv, &mb,
+		    "Received vote1 egen %lu, egen %lu",
+		    (u_long)vi->egen, (u_long)rep->egen));
+		if (vi->egen < rep->egen) {
+			RPRINT(dbenv, rep, (dbenv, &mb,
+			    "Received old vote %lu, egen %lu, ignoring vote1",
+			    (u_long)vi->egen, (u_long)rep->egen));
+			egen = rep->egen;
+			MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+			data_dbt.data = &egen;
+			data_dbt.size = sizeof(egen);
+			(void)__rep_send_message(dbenv,
+			    *eidp, REP_ALIVE, &rp->lsn, &data_dbt, 0);
+			goto errlock;
 		}
-
-		if (F_ISSET(rep, REP_F_EPHASE2))
-			goto unlock;
+		if (vi->egen > rep->egen) {
+			RPRINT(dbenv, rep, (dbenv, &mb,
+			    "Received VOTE1 from egen %lu, my egen %lu; reset",
+			    (u_long)vi->egen, (u_long)rep->egen));
+			__rep_elect_done(dbenv, rep);
+			rep->egen = vi->egen;
+		}
+		if (!IN_ELECTION(rep))
+			F_SET(rep, REP_F_TALLY);
 
 		/* Check if this site knows about more sites than we do. */
 		if (vi->nsites > rep->nsites)
 			rep->nsites = vi->nsites;
 
-		/* Check if we've heard from this site already. */
-		tally = R_ADDR((REGINFO *)dbenv->reginfo, rep->tally_off);
-		for (i = 0; i < rep->sites; i++) {
-			if (tally[i] == *eidp)
-				/* Duplicate vote. */
-				goto unlock;
-		}
+		/* Check if this site requires more votes than we do. */
+		if (vi->nvotes > rep->nvotes)
+			rep->nvotes = vi->nvotes;
 
 		/*
-		 * We are keeping vote, let's see if that changes our count of
-		 * the number of sites.
+		 * We are keeping the vote, let's see if that changes our
+		 * count of the number of sites.
 		 */
 		if (rep->sites + 1 > rep->nsites)
 			rep->nsites = rep->sites + 1;
 		if (rep->nsites > rep->asites &&
-		    (ret = __rep_grow_sites(dbenv, rep->nsites)) != 0)
-				goto unlock;
+		    (ret = __rep_grow_sites(dbenv, rep->nsites)) != 0) {
+			RPRINT(dbenv, rep, (dbenv, &mb,
+			    "Grow sites returned error %d", ret));
+			goto errunlock;
+		}
 
-		tally[rep->sites] = *eidp;
-		rep->sites++;
+		/*
+		 * Ignore vote1's if we're in phase 2.
+		 */
+		if (F_ISSET(rep, REP_F_EPHASE2)) {
+			RPRINT(dbenv, rep, (dbenv, &mb,
+			    "In phase 2, ignoring vote1"));
+			goto errunlock;
+		}
 
 		/*
-		 * Change winners if the incoming record has a higher
-		 * priority, or an equal priority but a larger LSN, or
-		 * an equal priority and LSN but higher "tiebreaker" value.
+		 * Record this vote.  If we get back non-zero, we
+		 * ignore the vote.
 		 */
-#ifdef DIAGNOSTIC
-		if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION)) {
-			__db_err(dbenv,
-			    "%s(eid)%d (pri)%d (gen)%d (sites)%d [%d,%d]",
-			    "Existing vote: ",
-			    rep->winner, rep->w_priority, rep->w_gen,
-			    rep->sites, rep->w_lsn.file, rep->w_lsn.offset);
-			__db_err(dbenv,
-			    "Incoming vote: (eid)%d (pri)%d (gen)%d [%d,%d]",
-			    *eidp, vi->priority, rp->gen, rp->lsn.file,
-			    rp->lsn.offset);
+		if ((ret = __rep_tally(dbenv, rep, *eidp, &rep->sites,
+		    vi->egen, rep->tally_off)) != 0) {
+			RPRINT(dbenv, rep, (dbenv, &mb,
+			    "Tally returned %d, sites %d",
+			    ret, rep->sites));
+			ret = 0;
+			goto errunlock;
 		}
-#endif
-		cmp = log_compare(&rp->lsn, &rep->w_lsn);
-		if (vi->priority > rep->w_priority ||
-		    (vi->priority != 0 && vi->priority == rep->w_priority &&
-		    (cmp > 0 ||
-		    (cmp == 0 && vi->tiebreaker > rep->w_tiebreaker)))) {
+		RPRINT(dbenv, rep, (dbenv, &mb,
+	    "Incoming vote: (eid)%d (pri)%d (gen)%lu (egen)%lu [%lu,%lu]",
+		    *eidp, vi->priority,
+		    (u_long)rp->gen, (u_long)vi->egen,
+		    (u_long)rp->lsn.file, (u_long)rp->lsn.offset));
 #ifdef DIAGNOSTIC
-			if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION))
-				__db_err(dbenv, "Accepting new vote");
+		if (rep->sites > 1)
+			RPRINT(dbenv, rep, (dbenv, &mb,
+	    "Existing vote: (eid)%d (pri)%d (gen)%lu (sites)%d [%lu,%lu]",
+			    rep->winner, rep->w_priority,
+			    (u_long)rep->w_gen, rep->sites,
+			    (u_long)rep->w_lsn.file,
+			    (u_long)rep->w_lsn.offset));
 #endif
-			rep->winner = *eidp;
-			rep->w_priority = vi->priority;
-			rep->w_lsn = rp->lsn;
-			rep->w_gen = rp->gen;
+		__rep_cmp_vote(dbenv, rep, eidp, &rp->lsn, vi->priority,
+		    rp->gen, vi->tiebreaker);
+		/*
+		 * If you get a vote and you're not in an election, we've
+		 * already recorded this vote.  But that is all we need
+		 * to do.
+		 */
+		if (!IN_ELECTION(rep)) {
+			RPRINT(dbenv, rep, (dbenv, &mb,
+			    "Not in election, but received vote1 0x%x",
+			    rep->flags));
+			ret = DB_REP_HOLDELECTION;
+			goto errunlock;
 		}
+
 		master = rep->winner;
 		lsn = rep->w_lsn;
-		done = rep->sites == rep->nsites && rep->w_priority != 0;
+		/*
+		 * We need to check sites == nsites, not more than half
+		 * like we do in __rep_elect and the VOTE2 code below.  The
+		 * reason is that we want to process all the incoming votes
+		 * and not short-circuit once we reach more than half.  The
+		 * real winner's vote may be in the last half.
+		 */
+		done = rep->sites >= rep->nsites && rep->w_priority != 0;
 		if (done) {
-#ifdef DIAGNOSTIC
-			if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION)) {
-				__db_err(dbenv, "Phase1 election done");
-				__db_err(dbenv, "Voting for %d%s",
-				    master, master == rep->eid ? "(self)" : "");
-			}
-#endif
-			F_CLR(rep, REP_F_EPHASE1);
+			RPRINT(dbenv, rep,
+			    (dbenv, &mb, "Phase1 election done"));
+			RPRINT(dbenv, rep, (dbenv, &mb, "Voting for %d%s",
+			    master, master == rep->eid ? "(self)" : ""));
+			egen = rep->egen;
 			F_SET(rep, REP_F_EPHASE2);
-		}
-
-		if (done && master == rep->eid) {
-			rep->votes++;
-			MUTEX_UNLOCK(dbenv, db_rep->mutexp);
-			return (0);
-		}
-		MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+			F_CLR(rep, REP_F_EPHASE1);
+			if (master == rep->eid) {
+				(void)__rep_tally(dbenv, rep, rep->eid,
+				    &rep->votes, egen, rep->v2tally_off);
+				goto errunlock;
+			}
+			MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
 
-		/* Vote for someone else. */
-		if (done)
-			return (__rep_send_message(dbenv,
-			    master, REP_VOTE2, NULL, NULL, 0));
+			/* Vote for someone else. */
+			__rep_send_vote(dbenv, NULL, 0, 0, 0, 0, egen,
+			    master, REP_VOTE2);
+		} else
+			MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
 
 		/* Election is still going on. */
 		break;
 	case REP_VOTE2:
-#ifdef DIAGNOSTIC
-		if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION))
-			__db_err(dbenv, "We received a vote%s",
-			    F_ISSET(dbenv, DB_ENV_REP_MASTER) ?
-			    " (master)" : "");
-#endif
-		if (F_ISSET(dbenv, DB_ENV_REP_MASTER)) {
+		RPRINT(dbenv, rep, (dbenv, &mb, "We received a vote%s",
+		    F_ISSET(rep, REP_F_MASTER) ? " (master)" : ""));
+		if (F_ISSET(rep, REP_F_MASTER)) {
 			R_LOCK(dbenv, &dblp->reginfo);
 			lsn = lp->lsn;
 			R_UNLOCK(dbenv, &dblp->reginfo);
 			rep->stat.st_elections_won++;
-			return (__rep_send_message(dbenv,
-			    *eidp, REP_NEWMASTER, &lsn, NULL, 0));
+			(void)__rep_send_message(dbenv,
+			    *eidp, REP_NEWMASTER, &lsn, NULL, 0);
+			goto errlock;
 		}
 
-		MUTEX_LOCK(dbenv, db_rep->mutexp);
+		MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
 
 		/* If we have priority 0, we should never get a vote. */
 		DB_ASSERT(rep->priority != 0);
 
-		if (!IN_ELECTION(rep)) {
-#ifdef DIAGNOSTIC
-			if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION))
-				__db_err(dbenv, "Not in election, got vote");
-#endif
-			MUTEX_UNLOCK(dbenv, db_rep->mutexp);
-			return (DB_REP_HOLDELECTION);
-		}
-		/* avoid counting duplicates. */
-		rep->votes++;
-		done = rep->votes > rep->nsites / 2;
-		if (done) {
-			rep->master_id = rep->eid;
-			rep->gen = rep->w_gen + 1;
-			ELECTION_DONE(rep);
-			F_CLR(rep, REP_F_UPGRADE);
-			F_SET(rep, REP_F_MASTER);
-			*eidp = rep->master_id;
-#ifdef DIAGNOSTIC
-			if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION))
-				__db_err(dbenv,
-			"Got enough votes to win; election done; winner is %d",
-				    rep->master_id);
-#endif
+		/*
+		 * We might be the last to the party and we haven't had
+		 * time to tally all the vote1's, but others have and
+		 * decided we're the winner.  So, if we're in the process
+		 * of tallying sites, keep the vote so that when our
+		 * election thread catches up we'll have the votes we
+		 * already received.
+		 */
+		vi = (REP_VOTE_INFO *)rec->data;
+		if (!IN_ELECTION_TALLY(rep) && vi->egen >= rep->egen) {
+			RPRINT(dbenv, rep, (dbenv, &mb,
+			    "Not in election gen %lu, at %lu, got vote",
+			    (u_long)vi->egen, (u_long)rep->egen));
+			ret = DB_REP_HOLDELECTION;
+			goto errunlock;
 		}
-		MUTEX_UNLOCK(dbenv, db_rep->mutexp);
-		if (done) {
-			R_LOCK(dbenv, &dblp->reginfo);
-			lsn = lp->lsn;
-			R_UNLOCK(dbenv, &dblp->reginfo);
 
-			/* Declare me the winner. */
-#ifdef DIAGNOSTIC
-			if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION))
-				__db_err(dbenv, "I won, sending NEWMASTER");
-#endif
-			rep->stat.st_elections_won++;
-			if ((ret = __rep_send_message(dbenv, DB_EID_BROADCAST,
-			    REP_NEWMASTER, &lsn, NULL, 0)) != 0)
-				break;
-			return (DB_REP_NEWMASTER);
+		/*
+		 * Record this vote.  In a VOTE2, the only valid entry
+		 * in the REP_VOTE_INFO is the election generation.
+		 *
+		 * There are several things which can go wrong that we
+		 * need to account for:
+		 * 1. If we receive a latent VOTE2 from an earlier election,
+		 * we want to ignore it.
+		 * 2. If we receive a VOTE2 from a site from which we never
+		 * received a VOTE1, we want to ignore it.
+		 * 3. If we have received a duplicate VOTE2 from this election
+		 * from the same site we want to ignore it.
+		 * 4. If this is from the current election and someone is
+		 * really voting for us, then we finally get to record it.
+		 */
+		/*
+		 * __rep_cmp_vote2 checks for cases 1 and 2.
+		 */
+		if ((ret = __rep_cmp_vote2(dbenv, rep, *eidp, vi->egen)) != 0) {
+			ret = 0;
+			goto errunlock;
+		}
+		/*
+		 * __rep_tally takes care of cases 3 and 4.
+		 */
+		if ((ret = __rep_tally(dbenv, rep, *eidp, &rep->votes,
+		    vi->egen, rep->v2tally_off)) != 0) {
+			ret = 0;
+			goto errunlock;
 		}
+		done = rep->votes >= rep->nvotes;
+		RPRINT(dbenv, rep, (dbenv, &mb, "Counted vote %d of %d",
+		    rep->votes, rep->nvotes));
+		if (done) {
+			__rep_elect_master(dbenv, rep, eidp);
+			ret = DB_REP_NEWMASTER;
+			goto errunlock;
+		} else
+			MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
 		break;
 	default:
 		__db_err(dbenv,
 	"DB_ENV->rep_process_message: unknown replication message: type %lu",
 		   (u_long)rp->rectype);
-		return (EINVAL);
+		ret = EINVAL;
+		goto errlock;
 	}
 
-	return (0);
-
-unlock:	MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+	/*
+	 * If we already hold rep_mutexp then we goto 'errunlock'
+	 * Otherwise we goto 'errlock' to acquire it before we
+	 * decrement our message thread count.
+	 */
+errlock:
+	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+errunlock:
+	rep->msg_th--;
+	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+out:
+	if (ret == 0 && F_ISSET(rp, DB_LOG_PERM)) {
+		if (ret_lsnp != NULL)
+			*ret_lsnp = rp->lsn;
+		ret = DB_REP_NOTPERM;
+	}
 	return (ret);
 }
 
@@ -743,344 +1223,123 @@ unlock:	MUTEX_UNLOCK(dbenv, db_rep->mutexp);
  * __rep_apply --
  *
  * Handle incoming log records on a client, applying when possible and
- * entering into the bookkeeping table otherwise.  This is the guts of
- * the routine that handles the state machine that describes how we
- * process and manage incoming log records.
+ * entering into the bookkeeping table otherwise.  This routine manages
+ * the state of the incoming message stream -- processing records, via
+ * __rep_process_rec, when possible and enqueuing in the __db.rep.db
+ * when necessary.  As gaps in the stream are filled in, this is where
+ * we try to process as much as possible from __db.rep.db to catch up.
  */
 static int
-__rep_apply(dbenv, rp, rec)
+__rep_apply(dbenv, rp, rec, ret_lsnp, is_dupp)
 	DB_ENV *dbenv;
 	REP_CONTROL *rp;
 	DBT *rec;
+	DB_LSN *ret_lsnp;
+	int *is_dupp;
 {
-	__dbreg_register_args dbreg_args;
-	__txn_ckp_args ckp_args;
 	DB_REP *db_rep;
-	DBT control_dbt, key_dbt, lsn_dbt, nextrec_dbt, rec_dbt;
+	DBT control_dbt, key_dbt;
+	DBT rec_dbt;
 	DB *dbp;
-	DBC *dbc;
 	DB_LOG *dblp;
-	DB_LSN ckp_lsn, lsn, newfile_lsn, next_lsn, waiting_lsn;
+	DB_LSN max_lsn;
 	LOG *lp;
 	REP *rep;
-	REP_CONTROL lsn_rc;
-	u_int32_t rectype, txnid;
-	int cmp, do_req, eid, have_mutex, ret, t_ret;
+	u_int32_t rectype;
+	int cmp, ret;
+#ifdef DIAGNOSTIC
+	DB_MSGBUF mb;
+#endif
 
 	db_rep = dbenv->rep_handle;
 	rep = db_rep->region;
 	dbp = db_rep->rep_db;
-	dbc = NULL;
-	have_mutex = ret = 0;
+	rectype = 0;
+	ret = 0;
 	memset(&control_dbt, 0, sizeof(control_dbt));
 	memset(&rec_dbt, 0, sizeof(rec_dbt));
+	ZERO_LSN(max_lsn);
 
-	/*
-	 * If this is a log record and it's the next one in line, simply
-	 * write it to the log.  If it's a "normal" log record, i.e., not
-	 * a COMMIT or CHECKPOINT or something that needs immediate processing,
-	 * just return.  If it's a COMMIT, CHECKPOINT or LOG_REGISTER (i.e.,
-	 * not SIMPLE), handle it now.  If it's a NEWFILE record, then we
-	 * have to be prepared to deal with a logfile change.
-	 */
 	dblp = dbenv->lg_handle;
-	R_LOCK(dbenv, &dblp->reginfo);
+	MUTEX_LOCK(dbenv, db_rep->db_mutexp);
 	lp = dblp->reginfo.primary;
+	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+	if (F_ISSET(rep, REP_F_RECOVER_LOG) &&
+	    log_compare(&lp->ready_lsn, &rep->first_lsn) < 0)
+		lp->ready_lsn = rep->first_lsn;
+	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
 	cmp = log_compare(&rp->lsn, &lp->ready_lsn);
 
-	/*
-	 * This is written to assume that you don't end up with a lot of
-	 * records after a hole.  That is, it optimizes for the case where
-	 * there is only a record or two after a hole.  If you have a lot
-	 * of records after a hole, what you'd really want to do is write
-	 * all of them and then process all the commits, checkpoints, etc.
-	 * together.  That is more complicated processing that we can add
-	 * later if necessary.
-	 *
-	 * That said, I really don't want to do db operations holding the
-	 * log mutex, so the synchronization here is tricky.
-	 */
 	if (cmp == 0) {
-		/* We got the log record that we are expecting. */
-		if (rp->rectype == REP_NEWFILE) {
-newfile:		ret = __rep_newfile(dbenv, rp, rec, &lp->ready_lsn);
+		if ((ret =
+		    __rep_process_rec(dbenv, rp, rec, &rectype, &max_lsn)) != 0)
+			goto err;
+		/*
+		 * If we get the record we are expecting, reset
+		 * the count of records we've received and are applying
+		 * towards the request interval.
+		 */
+		lp->rcvd_recs = 0;
 
-			/* Make this evaluate to a simple rectype. */
-			rectype = 0;
-		} else {
-			DB_ASSERT(log_compare(&rp->lsn, &lp->lsn) == 0);
-			ret = __log_rep_put(dbenv, &rp->lsn, rec);
-			lp->ready_lsn = lp->lsn;
-			memcpy(&rectype, rec->data, sizeof(rectype));
-			if (ret == 0)
-				/*
-				 * We may miscount if we race, since we
-				 * don't currently hold the rep mutex.
-				 */
-				rep->stat.st_log_records++;
-		}
-		while (ret == 0 && IS_SIMPLE(rectype) &&
+		while (ret == 0 &&
 		    log_compare(&lp->ready_lsn, &lp->waiting_lsn) == 0) {
 			/*
 			 * We just filled in a gap in the log record stream.
 			 * Write subsequent records to the log.
 			 */
-gap_check:		lp->wait_recs = 0;
+gap_check:
 			lp->rcvd_recs = 0;
-			R_UNLOCK(dbenv, &dblp->reginfo);
-			if (have_mutex == 0) {
-				MUTEX_LOCK(dbenv, db_rep->db_mutexp);
-				have_mutex = 1;
-			}
-			if (dbc == NULL &&
-			    (ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0)
-				goto err;
-
-			/* The DBTs need to persist through another call. */
-			F_SET(&control_dbt, DB_DBT_REALLOC);
-			F_SET(&rec_dbt, DB_DBT_REALLOC);
-			if ((ret = dbc->c_get(dbc,
-			    &control_dbt, &rec_dbt, DB_RMW | DB_FIRST)) != 0)
+			ZERO_LSN(lp->max_wait_lsn);
+			if ((ret =
+			    __rep_remfirst(dbenv, &control_dbt, &rec_dbt)) != 0)
 				goto err;
 
 			rp = (REP_CONTROL *)control_dbt.data;
 			rec = &rec_dbt;
-			memcpy(&rectype, rec->data, sizeof(rectype));
-			R_LOCK(dbenv, &dblp->reginfo);
+			if ((ret = __rep_process_rec(dbenv,
+			    rp, rec, &rectype, &max_lsn)) != 0)
+				goto err;
+
 			/*
-			 * We need to check again, because it's possible that
-			 * some other thread of control changed the waiting_lsn
-			 * or removed that record from the database.
+			 * We may miscount, as we don't hold the rep mutex.
 			 */
-			if (log_compare(&lp->ready_lsn, &rp->lsn) == 0) {
-				if (rp->rectype != REP_NEWFILE) {
-					DB_ASSERT(log_compare
-					    (&rp->lsn, &lp->lsn) == 0);
-					ret = __log_rep_put(dbenv,
-					    &rp->lsn, rec);
-					lp->ready_lsn = lp->lsn;
-
-					/*
-					 * We may miscount if we race, since we
-					 * don't currently hold the rep mutex.
-					 */
-					if (ret == 0)
-						rep->stat.st_log_records++;
-				} else {
-					ret = __rep_newfile(dbenv,
-					    rp, rec, &lp->ready_lsn);
-					rectype = 0;
-				}
-				waiting_lsn = lp->waiting_lsn;
-				R_UNLOCK(dbenv, &dblp->reginfo);
-				if ((ret = dbc->c_del(dbc, 0)) != 0)
-					goto err;
-
-				/*
-				 * We may miscount, as we don't hold the rep
-				 * mutex.
-				 */
-				--rep->stat.st_log_queued;
-
-				/*
-				 * Update waiting_lsn.  We need to move it
-				 * forward to the LSN of the next record
-				 * in the queue.
-				 */
-				memset(&lsn_dbt, 0, sizeof(lsn_dbt));
-				F_SET(&lsn_dbt, DB_DBT_USERMEM);
-				lsn_dbt.data = &lsn_rc;
-				lsn_dbt.ulen = sizeof(lsn_rc);
-				memset(&lsn_rc, 0, sizeof(lsn_rc));
-
-				/*
-				 * If the next item in the database is a log
-				 * record--the common case--we're not
-				 * interested in its contents, just in its LSN.
-				 * If it's a newfile message, though, the
-				 * data field may be the LSN of the last
-				 * record in the old file, and we need to use
-				 * that to determine whether or not there's
-				 * a gap.
-				 *
-				 * Optimize both these cases by doing a partial
-				 * get of the data item.  If it's a newfile
-				 * record, we'll get the whole LSN, and if
-				 * it's not, we won't waste time allocating.
-				 */
-				memset(&nextrec_dbt, 0, sizeof(nextrec_dbt));
-				F_SET(&nextrec_dbt,
-				    DB_DBT_USERMEM | DB_DBT_PARTIAL);
-				nextrec_dbt.ulen =
-				    nextrec_dbt.dlen = sizeof(newfile_lsn);
-				ZERO_LSN(newfile_lsn);
-				nextrec_dbt.data = &newfile_lsn;
-
-				ret = dbc->c_get(dbc,
-				    &lsn_dbt, &nextrec_dbt, DB_NEXT);
-				if (ret != DB_NOTFOUND && ret != 0)
-					goto err;
-
-				R_LOCK(dbenv, &dblp->reginfo);
-				if (ret == DB_NOTFOUND) {
-					/*
-					 * Do a quick double-check to make
-					 * sure waiting_lsn hasn't changed.
-					 * It's possible that between the
-					 * DB_NOTFOUND return and the R_LOCK,
-					 * some record was added to the
-					 * database, and we don't want to lose
-					 * sight of the fact that it's there.
-					 */
-					if (log_compare(&waiting_lsn,
-					    &lp->waiting_lsn) == 0)
-						ZERO_LSN(
-						    lp->waiting_lsn);
-
-					/*
-					 * Whether or not the current record is
-					 * simple, there's no next one, and
-					 * therefore we haven't got anything
-					 * else to do right now.  Break out.
-					 */
-					break;
-				}
+			--rep->stat.st_log_queued;
 
-				DB_ASSERT(lsn_dbt.size == sizeof(lsn_rc));
-
-				/*
-				 * NEWFILE records have somewhat convoluted
-				 * semantics, so there are five cases
-				 * pertaining to what the newly-gotten record
-				 * is and what we want to do about it.
-				 *
-				 * 1) This isn't a NEWFILE record.  Advance
-				 *    waiting_lsn and proceed.
-				 *
-				 * 2) NEWFILE, no LSN stored as the datum,
-				 *    lsn_rc.lsn == ready_lsn.  The NEWFILE
-				 *    record is next, so set waiting_lsn =
-				 *    ready_lsn.
-				 *
-				 * 3) NEWFILE, no LSN stored as the datum, but
-				 *    lsn_rc.lsn > ready_lsn.  There's still a
-				 *    gap; set waiting_lsn = lsn_rc.lsn.
-				 *
-				 * 4) NEWFILE, newfile_lsn in datum, and it's <
-				 *    ready_lsn. (If the datum is non-empty,
-				 *    it's the LSN of the last record in a log
-				 *    file, not the end of the log, and
-				 *    lsn_rc.lsn is the LSN of the start of
-				 *    the new file--we didn't have the end of
-				 *    the old log handy when we sent the
-				 *    record.)  No gap--we're ready to
-				 *    proceed.  Set both waiting and ready_lsn
-				 *    to lsn_rc.lsn.
-				 *
-				 * 5) NEWFILE, newfile_lsn in datum, and it's >=
-				 *    ready_lsn.  We're still missing at
-				 *    least one record;  set waiting_lsn,
-				 *    but not ready_lsn, to lsn_rc.lsn.
-				 */
-				if (lsn_rc.rectype == REP_NEWFILE &&
-				    nextrec_dbt.size > 0 && log_compare(
-				    &newfile_lsn, &lp->ready_lsn) < 0)
-					/* Case 4. */
-					lp->ready_lsn =
-					    lp->waiting_lsn = lsn_rc.lsn;
-				else {
-					/* Cases 1, 2, 3, and 5. */
-					DB_ASSERT(log_compare(&lsn_rc.lsn,
-					    &lp->ready_lsn) >= 0);
-					lp->waiting_lsn = lsn_rc.lsn;
-				}
-
-				/*
-				 * If the current rectype is simple, we're
-				 * done with it, and we should check and see
-				 * whether the next record queued is the next
-				 * one we're ready for.  This is just the loop
-				 * condition, so we continue.
-				 *
-				 * Otherwise, we need to break out of this loop
-				 * and process this record first.
-				 */
-				if (!IS_SIMPLE(rectype))
-					break;
-			}
+			if ((ret = __rep_getnext(dbenv)) == DB_NOTFOUND) {
+				ret = 0;
+				break;
+			} else if (ret != 0)
+				goto err;
 		}
 
 		/*
 		 * Check if we're at a gap in the table and if so, whether we
 		 * need to ask for any records.
 		 */
-		do_req = 0;
 		if (!IS_ZERO_LSN(lp->waiting_lsn) &&
 		    log_compare(&lp->ready_lsn, &lp->waiting_lsn) != 0) {
-			next_lsn = lp->ready_lsn;
-			do_req = ++lp->rcvd_recs >= lp->wait_recs;
-			if (do_req) {
-				lp->wait_recs = rep->request_gap;
-				lp->rcvd_recs = 0;
-			}
+			/*
+			 * We got a record and processed it, but we may
+			 * still be waiting for more records.
+			 */
+			if (__rep_check_doreq(dbenv, rep))
+				__rep_loggap_req(dbenv, rep, &rp->lsn, 0);
+		} else {
+			lp->wait_recs = 0;
+			ZERO_LSN(lp->max_wait_lsn);
 		}
 
-		R_UNLOCK(dbenv, &dblp->reginfo);
-		if (dbc != NULL) {
-			if ((ret = dbc->c_close(dbc)) != 0)
-				goto err;
-			MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
-			have_mutex = 0;
-		}
-		dbc = NULL;
-
-		if (do_req) {
-			MUTEX_LOCK(dbenv, db_rep->mutexp);
-			eid = db_rep->region->master_id;
-			MUTEX_UNLOCK(dbenv, db_rep->mutexp);
-			if (eid != DB_EID_INVALID) {
-				rep->stat.st_log_requested++;
-				if ((ret = __rep_send_message(dbenv,
-				    eid, REP_LOG_REQ, &next_lsn, NULL, 0)) != 0)
-					goto err;
-			}
-		}
 	} else if (cmp > 0) {
 		/*
 		 * The LSN is higher than the one we were waiting for.
-		 * If it is a NEWFILE message, this may not mean that
-		 * there's a gap;  in some cases, NEWFILE messages contain
-		 * the LSN of the beginning of the new file instead
-		 * of the end of the old.
-		 *
-		 * In these cases, the rec DBT will contain the last LSN
-		 * of the old file, so we can tell whether there's a gap.
-		 */
-		if (rp->rectype == REP_NEWFILE &&
-		    rp->lsn.file == lp->ready_lsn.file + 1 &&
-		    rp->lsn.offset == 0) {
-			DB_ASSERT(rec != NULL && rec->data != NULL &&
-			    rec->size == sizeof(DB_LSN));
-			memcpy(&lsn, rec->data, sizeof(DB_LSN));
-			if (log_compare(&lp->ready_lsn, &lsn) > 0)
-				/*
-				 * The last LSN in the old file is smaller
-				 * than the one we're expecting, so there's
-				 * no gap--the one we're expecting just
-				 * doesn't exist.
-				 */
-				goto newfile;
-		}
-
-		/*
-		 * This record isn't in sequence; add it to the table and
-		 * update waiting_lsn if necessary.
+		 * This record isn't in sequence; add it to the temporary
+		 * database, update waiting_lsn if necessary, and perform
+		 * calculations to determine if we should issue requests
+		 * for new records.
 		 */
 		memset(&key_dbt, 0, sizeof(key_dbt));
 		key_dbt.data = rp;
 		key_dbt.size = sizeof(*rp);
-		next_lsn = lp->lsn;
-		do_req = 0;
 		if (lp->wait_recs == 0) {
 			/*
 			 * This is a new gap. Initialize the number of
@@ -1090,156 +1349,116 @@ gap_check:		lp->wait_recs = 0;
 			 */
 			lp->wait_recs = rep->request_gap;
 			lp->rcvd_recs = 0;
+			ZERO_LSN(lp->max_wait_lsn);
 		}
+		if (__rep_check_doreq(dbenv, rep))
+			__rep_loggap_req(dbenv, rep, &rp->lsn, 0);
 
-		if (++lp->rcvd_recs >= lp->wait_recs) {
-			/*
-			 * If we've waited long enough, request the record
-			 * and double the wait interval.
-			 */
-			do_req = 1;
-			lp->wait_recs <<= 1;
-			lp->rcvd_recs = 0;
-			if (lp->wait_recs > rep->max_gap)
-				lp->wait_recs = rep->max_gap;
-		}
-		R_UNLOCK(dbenv, &dblp->reginfo);
-
-		MUTEX_LOCK(dbenv, db_rep->db_mutexp);
-		ret = dbp->put(dbp, NULL, &key_dbt, rec, 0);
+		ret = __db_put(dbp, NULL, &key_dbt, rec, DB_NOOVERWRITE);
 		rep->stat.st_log_queued++;
 		rep->stat.st_log_queued_total++;
 		if (rep->stat.st_log_queued_max < rep->stat.st_log_queued)
 			rep->stat.st_log_queued_max = rep->stat.st_log_queued;
-		MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
 
+		if (ret == DB_KEYEXIST)
+			ret = 0;
 		if (ret != 0)
-			return (ret);
+			goto done;
 
-		R_LOCK(dbenv, &dblp->reginfo);
 		if (IS_ZERO_LSN(lp->waiting_lsn) ||
 		    log_compare(&rp->lsn, &lp->waiting_lsn) < 0)
 			lp->waiting_lsn = rp->lsn;
-		R_UNLOCK(dbenv, &dblp->reginfo);
-
-		if (do_req) {
-			/* Request the LSN we are still waiting for. */
-			MUTEX_LOCK(dbenv, db_rep->mutexp);
 
-			/* May as well do this after we grab the mutex. */
-			eid = db_rep->region->master_id;
-
-			/*
-			 * If the master_id is invalid, this means that since
-			 * the last record was sent, somebody declared an
-			 * election and we may not have a master to request
-			 * things of.
-			 *
-			 * This is not an error;  when we find a new master,
-			 * we'll re-negotiate where the end of the log is and
-			 * try to to bring ourselves up to date again anyway.
-			 */
-			if (eid != DB_EID_INVALID) {
-				rep->stat.st_log_requested++;
-				MUTEX_UNLOCK(dbenv, db_rep->mutexp);
-				ret = __rep_send_message(dbenv,
-				    eid, REP_LOG_REQ, &next_lsn, NULL, 0);
-			} else
-				MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+		/*
+		 * If this is permanent; let the caller know that we have
+		 * not yet written it to disk, but we've accepted it.
+		 */
+		if (ret == 0 && F_ISSET(rp, DB_LOG_PERM)) {
+			max_lsn = rp->lsn;
+			ret = DB_REP_NOTPERM;
 		}
-		return (ret);
+		goto done;
 	} else {
-		R_UNLOCK(dbenv, &dblp->reginfo);
-
 		/*
 		 * We may miscount if we race, since we
 		 * don't currently hold the rep mutex.
 		 */
 		rep->stat.st_log_duplicated++;
-	}
-	if (ret != 0 || cmp < 0 || (cmp == 0 && IS_SIMPLE(rectype)))
+		if (is_dupp != NULL)
+			*is_dupp = 1;
+		if (F_ISSET(rp, DB_LOG_PERM))
+			max_lsn = lp->max_perm_lsn;
 		goto done;
-
-	/*
-	 * If we got here, then we've got a log record in rp and rec that
-	 * we need to process.
-	 */
-	switch(rectype) {
-	case DB___dbreg_register:
-		/*
-		 * DB opens occur in the context of a transaction, so we can
-		 * simply handle them when we process the transaction.  Closes,
-		 * however, are not transaction-protected, so we have to
-		 * handle them here.
-		 *
-		 * Note that it should be unsafe for the master to do a close
-		 * of a file that was opened in an active transaction, so we
-		 * should be guaranteed to get the ordering right.
-		 */
-		memcpy(&txnid, (u_int8_t *)rec->data +
-		    ((u_int8_t *)&dbreg_args.txnid - (u_int8_t *)&dbreg_args),
-		    sizeof(u_int32_t));
-		if (txnid == TXN_INVALID &&
-		    !F_ISSET(dbenv, DB_ENV_REP_LOGSONLY))
-			ret = __db_dispatch(dbenv, dbenv->recover_dtab,
-			    dbenv->recover_dtab_size, rec, &rp->lsn,
-			    DB_TXN_APPLY, NULL);
-		break;
-	case DB___txn_ckp:
-		/* Sync the memory pool. */
-		memcpy(&ckp_lsn, (u_int8_t *)rec->data +
-		    ((u_int8_t *)&ckp_args.ckp_lsn - (u_int8_t *)&ckp_args),
-		    sizeof(DB_LSN));
-		if (!F_ISSET(dbenv, DB_ENV_REP_LOGSONLY))
-			ret = dbenv->memp_sync(dbenv, &ckp_lsn);
-		else
-			/*
-			 * We ought to make sure the logs on a logs-only
-			 * replica get flushed now and again.
-			 */
-			ret = dbenv->log_flush(dbenv, &ckp_lsn);
-		/* Update the last_ckp in the txn region. */
-		if (ret == 0)
-			__txn_updateckp(dbenv, &rp->lsn);
-		break;
-	case DB___txn_regop:
-		if (!F_ISSET(dbenv, DB_ENV_REP_LOGSONLY))
-			do {
-				/*
-				 * If an application is doing app-specific
-				 * recovery and acquires locks while applying
-				 * a transaction, it can deadlock.  Any other
-				 * locks held by this thread should have been
-				 * discarded in the __rep_process_txn error
-				 * path, so if we simply retry, we should
-				 * eventually succeed.
-				 */
-				ret = __rep_process_txn(dbenv, rec);
-			} while (ret == DB_LOCK_DEADLOCK);
-		break;
-	default:
-		goto err;
 	}
 
 	/* Check if we need to go back into the table. */
-	if (ret == 0) {
-		R_LOCK(dbenv, &dblp->reginfo);
-		if (log_compare(&lp->ready_lsn, &lp->waiting_lsn) == 0)
-			goto gap_check;
-		R_UNLOCK(dbenv, &dblp->reginfo);
-	}
+	if (ret == 0 && log_compare(&lp->ready_lsn, &lp->waiting_lsn) == 0)
+		goto gap_check;
 
 done:
-err:	if (dbc != NULL && (t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
-		ret = t_ret;
-	if (have_mutex)
-		MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+err:	/* Check if we need to go back into the table. */
+	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+	if (ret == 0 &&
+	    F_ISSET(rep, REP_F_RECOVER_LOG) &&
+	    log_compare(&lp->ready_lsn, &rep->last_lsn) >= 0) {
+		rep->last_lsn = max_lsn;
+		ZERO_LSN(max_lsn);
+		ret = DB_REP_LOGREADY;
+	}
+	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+
+	if (ret == 0 && !F_ISSET(rep, REP_F_RECOVER_LOG) &&
+	    !IS_ZERO_LSN(max_lsn)) {
+		if (ret_lsnp != NULL)
+			*ret_lsnp = max_lsn;
+		ret = DB_REP_ISPERM;
+		DB_ASSERT(log_compare(&max_lsn, &lp->max_perm_lsn) >= 0);
+		lp->max_perm_lsn = max_lsn;
+	}
+	MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
 
+	/*
+	 * Startup is complete when we process our first live record.  However,
+	 * we want to return DB_REP_STARTUPDONE on the first record we can --
+	 * but other return values trump this one.  We know we've processed at
+	 * least one record when rectype is non-zero.
+	 */
+	if (ret == 0 && !F_ISSET(rp, DB_LOG_RESEND) &&
+	    rectype != 0 && rep->stat.st_startup_complete == 0) {
+		rep->stat.st_startup_complete = 1;
+		ret = DB_REP_STARTUPDONE;
+	}
+	if (ret == 0 && rp->rectype == REP_NEWFILE && lp->db_log_autoremove)
+		__log_autoremove(dbenv);
 	if (control_dbt.data != NULL)
 		__os_ufree(dbenv, control_dbt.data);
 	if (rec_dbt.data != NULL)
 		__os_ufree(dbenv, rec_dbt.data);
 
+	if (ret == DB_REP_NOTPERM && !F_ISSET(rep, REP_F_RECOVER_LOG) &&
+	    !IS_ZERO_LSN(max_lsn) && ret_lsnp != NULL)
+		*ret_lsnp = max_lsn;
+
+#ifdef DIAGNOSTIC
+	if (ret == DB_REP_ISPERM)
+		RPRINT(dbenv, rep, (dbenv, &mb, "Returning ISPERM [%lu][%lu]",
+		    (u_long)max_lsn.file, (u_long)max_lsn.offset));
+	else if (ret == DB_REP_LOGREADY)
+		RPRINT(dbenv, rep, (dbenv, &mb,
+		    "Returning LOGREADY up to [%lu][%lu]",
+		    (u_long)rep->last_lsn.file,
+		    (u_long)rep->last_lsn.offset));
+	else if (ret == DB_REP_NOTPERM)
+		RPRINT(dbenv, rep, (dbenv, &mb, "Returning NOTPERM [%lu][%lu]",
+		    (u_long)max_lsn.file, (u_long)max_lsn.offset));
+	else if (ret == DB_REP_STARTUPDONE)
+		RPRINT(dbenv, rep, (dbenv, &mb,
+		    "Returning STARTUPDONE [%lu][%lu]",
+		    (u_long)rp->lsn.file, (u_long)rp->lsn.offset));
+	else if (ret != 0)
+		RPRINT(dbenv, rep, (dbenv, &mb, "Returning %d [%lu][%lu]", ret,
+		    (u_long)max_lsn.file, (u_long)max_lsn.offset));
+#endif
 	return (ret);
 }
 
@@ -1256,7 +1475,7 @@ __rep_process_txn(dbenv, rec)
 	DB_ENV *dbenv;
 	DBT *rec;
 {
-	DBT data_dbt;
+	DBT data_dbt, *lock_dbt;
 	DB_LOCKREQ req, *lvp;
 	DB_LOGC *logc;
 	DB_LSN prev_lsn, *lsnp;
@@ -1265,34 +1484,30 @@ __rep_process_txn(dbenv, rec)
 	REP *rep;
 	__txn_regop_args *txn_args;
 	__txn_xa_regop_args *prep_args;
-	u_int32_t lockid, op, rectype;
-	int i, ret, t_ret;
-	int (**dtab)__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-	size_t dtabsize;
+	u_int32_t lockid, rectype;
+	u_int i;
+	int ret, t_ret;
 	void *txninfo;
 
 	db_rep = dbenv->rep_handle;
 	rep = db_rep->region;
-
 	logc = NULL;
+	txn_args = NULL;
+	prep_args = NULL;
 	txninfo = NULL;
+
 	memset(&data_dbt, 0, sizeof(data_dbt));
 	if (F_ISSET(dbenv, DB_ENV_THREAD))
 		F_SET(&data_dbt, DB_DBT_REALLOC);
 
 	/*
-	 * There are two phases:  First, we have to traverse
-	 * backwards through the log records gathering the list
-	 * of all LSNs in the transaction.  Once we have this information,
-	 * we can loop through, acquire the locks we need for each record,
-	 * and then apply it.
-	 */
-	dtab = NULL;
-
-	/*
-	 * We may be passed a prepare (if we're restoring a prepare
-	 * on upgrade) instead of a commit (the common case).
-	 * Check which and behave appropriately.
+	 * There are two phases:  First, we have to traverse backwards through
+	 * the log records gathering the list of all LSNs in the transaction.
+	 * Once we have this information, we can loop through and then apply it.
+	 *
+	 * We may be passed a prepare (if we're restoring a prepare on upgrade)
+	 * instead of a commit (the common case).  Check which it is and behave
+	 * appropriately.
 	 */
 	memcpy(&rectype, rec->data, sizeof(rectype));
 	memset(&lc, 0, sizeof(lc));
@@ -1303,11 +1518,12 @@ __rep_process_txn(dbenv, rec)
 		 */
 		if ((ret = __txn_regop_read(dbenv, rec->data, &txn_args)) != 0)
 			return (ret);
-		op = txn_args->opcode;
-		prev_lsn = txn_args->prev_lsn;
-		__os_free(dbenv, txn_args);
-		if (op != TXN_COMMIT)
+		if (txn_args->opcode != TXN_COMMIT) {
+			__os_free(dbenv, txn_args);
 			return (0);
+		}
+		prev_lsn = txn_args->prev_lsn;
+		lock_dbt = &txn_args->locks;
 	} else {
 		/* We're a prepare. */
 		DB_ASSERT(rectype == DB___txn_xa_regop);
@@ -1316,20 +1532,21 @@ __rep_process_txn(dbenv, rec)
 		    __txn_xa_regop_read(dbenv, rec->data, &prep_args)) != 0)
 			return (ret);
 		prev_lsn = prep_args->prev_lsn;
-		__os_free(dbenv, prep_args);
+		lock_dbt = &prep_args->locks;
 	}
 
-	/* Phase 1.  Get a list of the LSNs in this transaction, and sort it. */
-	if ((ret = __rep_collect_txn(dbenv, &prev_lsn, &lc)) != 0)
-		return (ret);
-	qsort(lc.array, lc.nlsns, sizeof(DB_LSN), __rep_lsn_cmp);
+	/* Get locks. */
+	if ((ret = __lock_id(dbenv, &lockid)) != 0)
+		goto err1;
 
-	if ((ret = dbenv->lock_id(dbenv, &lockid)) != 0)
+	if ((ret =
+	      __lock_get_list(dbenv, lockid, 0, DB_LOCK_WRITE, lock_dbt)) != 0)
 		goto err;
 
-	/* Initialize the getpgno dispatch table. */
-	if ((ret = __rep_lockpgno_init(dbenv, &dtab, &dtabsize)) != 0)
+	/* Phase 1.  Get a list of the LSNs in this transaction, and sort it. */
+	if ((ret = __rep_collect_txn(dbenv, &prev_lsn, &lc)) != 0)
 		goto err;
+	qsort(lc.array, lc.nlsns, sizeof(DB_LSN), __rep_lsn_cmp);
 
 	/*
 	 * The set of records for a transaction may include dbreg_register
@@ -1340,34 +1557,40 @@ __rep_process_txn(dbenv, rec)
 		goto err;
 
 	/* Phase 2: Apply updates. */
-	if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+	if ((ret = __log_cursor(dbenv, &logc)) != 0)
 		goto err;
 	for (lsnp = &lc.array[0], i = 0; i < lc.nlsns; i++, lsnp++) {
-		if ((ret = __rep_lockpages(dbenv,
-		    dtab, dtabsize, lsnp, NULL, NULL, lockid)) != 0)
-			goto err;
-		if ((ret = logc->get(logc, lsnp, &data_dbt, DB_SET)) != 0)
+		if ((ret = __log_c_get(logc, lsnp, &data_dbt, DB_SET)) != 0) {
+			__db_err(dbenv, "failed to read the log at [%lu][%lu]",
+			    (u_long)lsnp->file, (u_long)lsnp->offset);
 			goto err;
+		}
 		if ((ret = __db_dispatch(dbenv, dbenv->recover_dtab,
 		    dbenv->recover_dtab_size, &data_dbt, lsnp,
-		    DB_TXN_APPLY, txninfo)) != 0)
+		    DB_TXN_APPLY, txninfo)) != 0) {
+			__db_err(dbenv, "transaction failed at [%lu][%lu]",
+			    (u_long)lsnp->file, (u_long)lsnp->offset);
 			goto err;
+		}
 	}
 
 err:	memset(&req, 0, sizeof(req));
 	req.op = DB_LOCK_PUT_ALL;
-	if ((t_ret = dbenv->lock_vec(dbenv, lockid,
-	    DB_LOCK_FREE_LOCKER, &req, 1, &lvp)) != 0 && ret == 0)
+	if ((t_ret =
+	     __lock_vec(dbenv, lockid, 0, &req, 1, &lvp)) != 0 && ret == 0)
 		ret = t_ret;
 
-	if (lc.nalloc != 0)
-		__os_free(dbenv, lc.array);
-
-	if ((t_ret =
-	    dbenv->lock_id_free(dbenv, lockid)) != 0 && ret == 0)
+	if ((t_ret = __lock_id_free(dbenv, lockid)) != 0 && ret == 0)
 		ret = t_ret;
 
-	if (logc != NULL && (t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+err1:	if (txn_args != NULL)
+		__os_free(dbenv, txn_args);
+	if (prep_args != NULL)
+		__os_free(dbenv, prep_args);
+	if (lc.array != NULL)
+		__os_free(dbenv, lc.array);
+
+	if (logc != NULL && (t_ret = __log_c_close(logc)) != 0 && ret == 0)
 		ret = t_ret;
 
 	if (txninfo != NULL)
@@ -1376,9 +1599,6 @@ err:	memset(&req, 0, sizeof(req));
 	if (F_ISSET(&data_dbt, DB_DBT_REALLOC) && data_dbt.data != NULL)
 		__os_ufree(dbenv, data_dbt.data);
 
-	if (dtab != NULL)
-		__os_free(dbenv, dtab);
-
 	if (ret == 0)
 		/*
 		 * We don't hold the rep mutex, and could miscount if we race.
@@ -1405,16 +1625,17 @@ __rep_collect_txn(dbenv, lsnp, lc)
 	DB_LSN c_lsn;
 	DBT data;
 	u_int32_t rectype;
-	int nalloc, ret, t_ret;
+	u_int nalloc;
+	int ret, t_ret;
 
 	memset(&data, 0, sizeof(data));
 	F_SET(&data, DB_DBT_REALLOC);
 
-	if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+	if ((ret = __log_cursor(dbenv, &logc)) != 0)
 		return (ret);
 
 	while (!IS_ZERO_LSN(*lsnp) &&
-	    (ret = logc->get(logc, lsnp, &data, DB_SET)) == 0) {
+	    (ret = __log_c_get(logc, lsnp, &data, DB_SET)) == 0) {
 		memcpy(&rectype, data.data, sizeof(rectype));
 		if (rectype == DB___txn_child) {
 			if ((ret = __txn_child_read(dbenv,
@@ -1449,8 +1670,11 @@ __rep_collect_txn(dbenv, lsnp, lc)
 		if (ret != 0)
 			goto err;
 	}
+	if (ret != 0)
+		__db_err(dbenv, "collect failed at: [%lu][%lu]",
+		    (u_long)lsnp->file, (u_long)lsnp->offset);
 
-err:	if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+err:	if ((t_ret = __log_c_close(logc)) != 0 && ret == 0)
 		ret = t_ret;
 	if (data.data != NULL)
 		__os_ufree(dbenv, data.data);
@@ -1471,43 +1695,839 @@ __rep_lsn_cmp(lsn1, lsn2)
 
 /*
  * __rep_newfile --
- *	NEWFILE messages can contain either the last LSN of the old file
- * or the first LSN of the new one, depending on which we have available
- * when the message is sent.  When applying a NEWFILE message, make sure
- * we haven't already swapped files, as it's possible (given the right sequence
- * of out-of-order messages) to wind up with a NEWFILE message of each
- * variety, and __rep_apply won't detect the two as duplicates of each other.
+ *	NEWFILE messages have the LSN of the last record in the previous
+ * log file.  When applying a NEWFILE message, make sure we haven't already
+ * swapped files.
  */
 static int
-__rep_newfile(dbenv, rc, msgdbt, lsnp)
+__rep_newfile(dbenv, rc, lsnp)
 	DB_ENV *dbenv;
 	REP_CONTROL *rc;
-	DBT *msgdbt;
 	DB_LSN *lsnp;
 {
 	DB_LOG *dblp;
 	LOG *lp;
-	u_int32_t newfile;
 
 	dblp = dbenv->lg_handle;
 	lp = dblp->reginfo.primary;
 
-	/*
-	 * A NEWFILE message containing the old file's LSN will be
-	 * accompanied by a NULL rec DBT;  one containing the new one's LSN
-	 * will need to supply the last record in the old file by
-	 * sending it in the rec DBT.
-	 */
-	if (msgdbt == NULL || msgdbt->size == 0)
-		newfile = rc->lsn.file + 1;
-	else
-		newfile = rc->lsn.file;
-
-	if (newfile > lp->lsn.file)
-		return (__log_newfile(dblp, lsnp));
+	if (rc->lsn.file + 1 > lp->lsn.file)
+		return (__log_newfile(dblp, lsnp, 0));
 	else {
 		/* We've already applied this NEWFILE.  Just ignore it. */
 		*lsnp = lp->lsn;
 		return (0);
 	}
 }
+
+/*
+ * __rep_tally --
+ * PUBLIC: int __rep_tally __P((DB_ENV *, REP *, int, int *,
+ * PUBLIC:    u_int32_t, roff_t));
+ *
+ * Handle incoming vote1 message on a client.  Called with the db_rep
+ * mutex held.  This function will return 0 if we successfully tally
+ * the vote and non-zero if the vote is ignored.  This will record
+ * both VOTE1 and VOTE2 records, depending on which region offset the
+ * caller passed in.
+ */
+int
+__rep_tally(dbenv, rep, eid, countp, egen, vtoff)
+	DB_ENV *dbenv;
+	REP *rep;
+	int eid, *countp;
+	u_int32_t egen;
+	roff_t vtoff;
+{
+	REP_VTALLY *tally, *vtp;
+	int i;
+#ifdef DIAGNOSTIC
+	DB_MSGBUF mb;
+#else
+	COMPQUIET(rep, NULL);
+#endif
+
+	tally = R_ADDR((REGINFO *)dbenv->reginfo, vtoff);
+	i = 0;
+	vtp = &tally[i];
+	while (i < *countp) {
+		/*
+		 * Ignore votes from earlier elections (i.e. we've heard
+		 * from this site in this election, but its vote from an
+		 * earlier election got delayed and we received it now).
+		 * However, if we happened to hear from an earlier vote
+		 * and we recorded it and we're now hearing from a later
+		 * election we want to keep the updated one.  Note that
+		 * updating the entry will not increase the count.
+		 * Also ignore votes that are duplicates.
+		 */
+		if (vtp->eid == eid) {
+			RPRINT(dbenv, rep, (dbenv, &mb,
+			    "Tally found[%d] (%d, %lu), this vote (%d, %lu)",
+				    i, vtp->eid, (u_long)vtp->egen,
+				    eid, (u_long)egen));
+			if (vtp->egen >= egen)
+				return (1);
+			else {
+				vtp->egen = egen;
+				return (0);
+			}
+		}
+		i++;
+		vtp = &tally[i];
+	}
+	/*
+	 * If we get here, we have a new voter we haven't
+	 * seen before.  Tally this vote.
+	 */
+#ifdef DIAGNOSTIC
+	if (vtoff == rep->tally_off)
+		RPRINT(dbenv, rep, (dbenv, &mb, "Tallying VOTE1[%d] (%d, %lu)",
+		    i, eid, (u_long)egen));
+	else
+		RPRINT(dbenv, rep, (dbenv, &mb, "Tallying VOTE2[%d] (%d, %lu)",
+		    i, eid, (u_long)egen));
+#endif
+	vtp->eid = eid;
+	vtp->egen = egen;
+	(*countp)++;
+	return (0);
+}
+
+/*
+ * __rep_cmp_vote --
+ * PUBLIC: void __rep_cmp_vote __P((DB_ENV *, REP *, int *, DB_LSN *,
+ * PUBLIC:     int, u_int32_t, u_int32_t));
+ *
+ * Compare incoming vote1 message on a client.  Called with the db_rep
+ * mutex held.
+ */
+void
+__rep_cmp_vote(dbenv, rep, eidp, lsnp, priority, gen, tiebreaker)
+	DB_ENV *dbenv;
+	REP *rep;
+	int *eidp;
+	DB_LSN *lsnp;
+	int priority;
+	u_int32_t gen, tiebreaker;
+{
+	int cmp;
+
+#ifdef DIAGNOSTIC
+	DB_MSGBUF mb;
+#else
+	COMPQUIET(dbenv, NULL);
+#endif
+	cmp = log_compare(lsnp, &rep->w_lsn);
+	/*
+	 * If we've seen more than one, compare us to the best so far.
+	 * If we're the first, make ourselves the winner to start.
+	 */
+	if (rep->sites > 1 && priority != 0) {
+		/*
+		 * LSN is primary determinant. Then priority if LSNs
+		 * are equal, then tiebreaker if both are equal.
+		 */
+		if (cmp > 0 ||
+		    (cmp == 0 && (priority > rep->w_priority ||
+		    (priority == rep->w_priority &&
+		    (tiebreaker > rep->w_tiebreaker))))) {
+			RPRINT(dbenv, rep, (dbenv, &mb, "Accepting new vote"));
+			rep->winner = *eidp;
+			rep->w_priority = priority;
+			rep->w_lsn = *lsnp;
+			rep->w_gen = gen;
+			rep->w_tiebreaker = tiebreaker;
+		}
+	} else if (rep->sites == 1) {
+		if (priority != 0) {
+			/* Make ourselves the winner to start. */
+			rep->winner = *eidp;
+			rep->w_priority = priority;
+			rep->w_gen = gen;
+			rep->w_lsn = *lsnp;
+			rep->w_tiebreaker = tiebreaker;
+		} else {
+			rep->winner = DB_EID_INVALID;
+			rep->w_priority = 0;
+			rep->w_gen = 0;
+			ZERO_LSN(rep->w_lsn);
+			rep->w_tiebreaker = 0;
+		}
+	}
+	return;
+}
+
+/*
+ * __rep_cmp_vote2 --
+ * PUBLIC: int __rep_cmp_vote2 __P((DB_ENV *, REP *, int, u_int32_t));
+ *
+ * Compare incoming vote2 message with vote1's we've recorded.  Called
+ * with the db_rep mutex held.  We return 0 if the VOTE2 is from a
+ * site we've heard from and it is from this election.  Otherwise we return 1.
+ */
+int
+__rep_cmp_vote2(dbenv, rep, eid, egen)
+	DB_ENV *dbenv;
+	REP *rep;
+	int eid;
+	u_int32_t egen;
+{
+	int i;
+	REP_VTALLY *tally, *vtp;
+#ifdef DIAGNOSTIC
+	DB_MSGBUF mb;
+#endif
+
+	tally = R_ADDR((REGINFO *)dbenv->reginfo, rep->tally_off);
+	i = 0;
+	vtp = &tally[i];
+	for (i = 0; i < rep->sites; i++) {
+		vtp = &tally[i];
+		if (vtp->eid == eid && vtp->egen == egen) {
+			RPRINT(dbenv, rep, (dbenv, &mb,
+			    "Found matching vote1 (%d, %lu), at %d of %d",
+			    eid, (u_long)egen, i, rep->sites));
+			return (0);
+		}
+	}
+	RPRINT(dbenv, rep,
+	    (dbenv, &mb, "Didn't find vote1 for eid %d, egen %lu",
+	    eid, (u_long)egen));
+	return (1);
+}
+
+static int
+__rep_dorecovery(dbenv, lsnp, trunclsnp)
+	DB_ENV *dbenv;
+	DB_LSN *lsnp, *trunclsnp;
+{
+	DB_LSN lsn;
+	DB_REP *db_rep;
+	DBT mylog;
+	DB_LOGC *logc;
+	int ret, t_ret, update;
+	u_int32_t rectype;
+	__txn_regop_args *txnrec;
+
+	db_rep = dbenv->rep_handle;
+
+	/* Figure out if we are backing out any committed transactions. */
+	if ((ret = __log_cursor(dbenv, &logc)) != 0)
+		return (ret);
+
+	memset(&mylog, 0, sizeof(mylog));
+	update = 0;
+	while (update == 0 &&
+	    (ret = __log_c_get(logc, &lsn, &mylog, DB_PREV)) == 0 &&
+	    log_compare(&lsn, lsnp) > 0) {
+		memcpy(&rectype, mylog.data, sizeof(rectype));
+		if (rectype == DB___txn_regop) {
+			if ((ret =
+			    __txn_regop_read(dbenv, mylog.data, &txnrec)) != 0)
+				goto err;
+			if (txnrec->opcode != TXN_ABORT)
+				update = 1;
+			__os_free(dbenv, txnrec);
+		}
+	}
+
+	/*
+	 * If we successfully run recovery, we've opened all the necessary
+	 * files.  We are guaranteed to be single-threaded here, so no mutex
+	 * is necessary.
+	 */
+	if ((ret = __db_apprec(dbenv, lsnp, trunclsnp, update, 0)) == 0)
+		F_SET(db_rep, DBREP_OPENFILES);
+
+err:	if ((t_ret = __log_c_close(logc)) != 0 && ret == 0)
+		ret = t_ret;
+
+	return (ret);
+}
+
+/*
+ * __rep_verify_match --
+ *	We have just received a matching log record during verification.
+ * Figure out if we're going to need to run recovery. If so, wait until
+ * everything else has exited the library.  If not, set up the world
+ * correctly and move forward.
+ */
+static int
+__rep_verify_match(dbenv, reclsnp, savetime)
+	DB_ENV *dbenv;
+	DB_LSN *reclsnp;
+	time_t savetime;
+{
+	DB_LOG *dblp;
+	DB_LSN trunclsn;
+	DB_REP *db_rep;
+	LOG *lp;
+	REGENV *renv;
+	REGINFO *infop;
+	REP *rep;
+	int done, master, ret;
+	u_int32_t unused;
+
+	dblp = dbenv->lg_handle;
+	db_rep = dbenv->rep_handle;
+	rep = db_rep->region;
+	lp = dblp->reginfo.primary;
+	ret = 0;
+	infop = dbenv->reginfo;
+	renv = infop->primary;
+
+	/*
+	 * Check if the savetime is different than our current time stamp.
+	 * If it is, then we're racing with another thread trying to recover
+	 * and we lost.  We must give up.
+	 */
+	MUTEX_LOCK(dbenv, db_rep->db_mutexp);
+	done = savetime != renv->rep_timestamp;
+	if (done) {
+		MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+		return (0);
+	}
+	ZERO_LSN(lp->verify_lsn);
+	MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+
+	/*
+	 * Make sure the world hasn't changed while we tried to get
+	 * the lock.  If it hasn't then it's time for us to kick all
+	 * operations out of DB and run recovery.
+	 */
+	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+	if (!F_ISSET(rep, REP_F_RECOVER_LOG) &&
+	    (F_ISSET(rep, REP_F_READY) || rep->in_recovery != 0)) {
+		rep->stat.st_msgs_recover++;
+		goto errunlock;
+	}
+
+	__rep_lockout(dbenv, db_rep, rep, 1);
+
+	/* OK, everyone is out, we can now run recovery. */
+	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+
+	if ((ret = __rep_dorecovery(dbenv, reclsnp, &trunclsn)) != 0) {
+		MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+		rep->in_recovery = 0;
+		F_CLR(rep, REP_F_READY);
+		goto errunlock;
+	}
+
+	/*
+	 * The log has been truncated (either directly by us or by __db_apprec)
+	 * We want to make sure we're waiting for the LSN at the new end-of-log,
+	 * not some later point.
+	 */
+	MUTEX_LOCK(dbenv, db_rep->db_mutexp);
+	lp->ready_lsn = trunclsn;
+	ZERO_LSN(lp->waiting_lsn);
+	ZERO_LSN(lp->max_wait_lsn);
+	lp->max_perm_lsn = *reclsnp;
+	lp->wait_recs = 0;
+	lp->rcvd_recs = 0;
+	ZERO_LSN(lp->verify_lsn);
+
+	/*
+	 * Discard any log records we have queued;  we're about to re-request
+	 * them, and can't trust the ones in the queue.  We need to set the
+	 * DB_AM_RECOVER bit in this handle, so that the operation doesn't
+	 * deadlock.
+	 */
+	F_SET(db_rep->rep_db, DB_AM_RECOVER);
+	MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+	ret = __db_truncate(db_rep->rep_db, NULL, &unused);
+	MUTEX_LOCK(dbenv, db_rep->db_mutexp);
+	F_CLR(db_rep->rep_db, DB_AM_RECOVER);
+	MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+
+	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+	rep->stat.st_log_queued = 0;
+	rep->in_recovery = 0;
+	F_CLR(rep, REP_F_NOARCHIVE | REP_F_RECOVER_MASK);
+
+	if (ret != 0)
+		goto errunlock;
+
+	/*
+	 * If the master_id is invalid, this means that since
+	 * the last record was sent, somebody declared an
+	 * election and we may not have a master to request
+	 * things of.
+	 *
+	 * This is not an error;  when we find a new master,
+	 * we'll re-negotiate where the end of the log is and
+	 * try to bring ourselves up to date again anyway.
+	 *
+	 * !!!
+	 * We cannot assert the election flags though because
+	 * somebody may have declared an election and then
+	 * got an error, thus clearing the election flags
+	 * but we still have an invalid master_id.
+	 */
+	master = rep->master_id;
+	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+	if (master == DB_EID_INVALID)
+		ret = 0;
+	else
+		(void)__rep_send_message(dbenv,
+		    master, REP_ALL_REQ, reclsnp, NULL, 0);
+	if (0) {
+errunlock:
+		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+	}
+	return (ret);
+}
+
+/*
+ * __rep_do_ckp --
+ * Perform the memp_sync necessary for this checkpoint without holding
+ * the db_rep->db_mutexp.  All callers of this function must hold the
+ * db_rep->db_mutexp and must not be holding the db_rep->rep_mutexp.
+ */
+static int
+__rep_do_ckp(dbenv, rec, rp)
+	DB_ENV *dbenv;
+	DBT *rec;
+	REP_CONTROL *rp;
+{
+	DB_LSN ckp_lsn;
+	DB_REP *db_rep;
+	int ret;
+
+	db_rep = dbenv->rep_handle;
+
+	MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+
+	DB_TEST_CHECKPOINT(dbenv, dbenv->test_check);
+
+	/* Sync the memory pool. */
+	memcpy(&ckp_lsn, (u_int8_t *)rec->data +
+	    SSZ(__txn_ckp_args, ckp_lsn), sizeof(DB_LSN));
+	ret = __memp_sync(dbenv, &ckp_lsn);
+
+	/* Update the last_ckp in the txn region. */
+	if (ret == 0)
+		__txn_updateckp(dbenv, &rp->lsn);
+	else {
+		__db_err(dbenv, "Error syncing ckp [%lu][%lu]",
+		    (u_long)ckp_lsn.file, (u_long)ckp_lsn.offset);
+		ret = __db_panic(dbenv, ret);
+	}
+	MUTEX_LOCK(dbenv, db_rep->db_mutexp);
+
+	return (ret);
+}
+
+/*
+ * __rep_remfirst --
+ * Remove the first entry from the __db.rep.db
+ */
+static int
+__rep_remfirst(dbenv, cntrl, rec)
+	DB_ENV *dbenv;
+	DBT *cntrl;
+	DBT *rec;
+{
+	DB *dbp;
+	DBC *dbc;
+	DB_REP *db_rep;
+	int ret, t_ret;
+	u_int32_t rectype;
+
+	db_rep = dbenv->rep_handle;
+	dbp = db_rep->rep_db;
+
+	if ((ret = __db_cursor(dbp, NULL, &dbc, 0)) != 0)
+		return (ret);
+
+	/* The DBTs need to persist through another call. */
+	F_SET(cntrl, DB_DBT_REALLOC);
+	F_SET(rec, DB_DBT_REALLOC);
+	if ((ret = __db_c_get(dbc, cntrl, rec, DB_RMW | DB_FIRST)) == 0) {
+		memcpy(&rectype, rec->data, sizeof(rectype));
+		ret = __db_c_del(dbc, 0);
+	}
+	if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
+		ret = t_ret;
+
+	return (ret);
+}
+
+/*
+ * __rep_getnext --
+ * Get the next record out of the __db.rep.db table.
+ */
+static int
+__rep_getnext(dbenv)
+	DB_ENV *dbenv;
+{
+	DB *dbp;
+	DB_REP *db_rep;
+	DB_LOG *dblp;
+	DBC *dbc;
+	DBT lsn_dbt, nextrec_dbt;
+	LOG *lp;
+	REP_CONTROL *rp;
+	int ret, t_ret;
+
+	dblp = dbenv->lg_handle;
+	lp = dblp->reginfo.primary;
+
+	db_rep = dbenv->rep_handle;
+	dbp = db_rep->rep_db;
+
+	if ((ret = __db_cursor(dbp, NULL, &dbc, 0)) != 0)
+		return (ret);
+
+	/*
+	 * Update waiting_lsn.  We need to move it
+	 * forward to the LSN of the next record
+	 * in the queue.
+	 *
+	 * If the next item in the database is a log
+	 * record--the common case--we're not
+	 * interested in its contents, just in its LSN.
+	 * Optimize by doing a partial get of the data item.
+	 */
+	memset(&nextrec_dbt, 0, sizeof(nextrec_dbt));
+	F_SET(&nextrec_dbt, DB_DBT_PARTIAL);
+	nextrec_dbt.ulen = nextrec_dbt.dlen = 0;
+
+	memset(&lsn_dbt, 0, sizeof(lsn_dbt));
+	ret = __db_c_get(dbc, &lsn_dbt, &nextrec_dbt, DB_FIRST);
+	if (ret != DB_NOTFOUND && ret != 0)
+		goto err;
+
+	if (ret == DB_NOTFOUND) {
+		ZERO_LSN(lp->waiting_lsn);
+		/*
+		 * Whether or not the current record is
+		 * simple, there's no next one, and
+		 * therefore we haven't got anything
+		 * else to do right now.  Break out.
+		 */
+		goto err;
+	}
+	rp = (REP_CONTROL *)lsn_dbt.data;
+	lp->waiting_lsn = rp->lsn;
+
+err:	if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
+		ret = t_ret;
+	return (ret);
+}
+
+/*
+ * __rep_process_rec --
+ *
+ * Given a record in 'rp', process it.  In the case of a NEWFILE, that means
+ * potentially switching files.  In the case of a checkpoint, it means doing
+ * the checkpoint, and in other cases, it means simply writing the record into
+ * the log.
+ */
+static int
+__rep_process_rec(dbenv, rp, rec, typep, ret_lsnp)
+	DB_ENV *dbenv;
+	REP_CONTROL *rp;
+	DBT *rec;
+	u_int32_t *typep;
+	DB_LSN *ret_lsnp;
+{
+	DB *dbp;
+	DB_LOG *dblp;
+	DB_REP *db_rep;
+	DBT control_dbt, key_dbt, rec_dbt;
+	LOG *lp;
+	REP *rep;
+	u_int32_t txnid;
+	int ret, t_ret;
+
+	db_rep = dbenv->rep_handle;
+	rep = db_rep->region;
+	dbp = db_rep->rep_db;
+	dblp = dbenv->lg_handle;
+	lp = dblp->reginfo.primary;
+	ret = 0;
+
+	if (rp->rectype == REP_NEWFILE) {
+		ret = __rep_newfile(dbenv, rp, &lp->ready_lsn);
+
+		/* Make this evaluate to a simple rectype. */
+		*typep = 0;
+		return (0);
+	}
+
+	memcpy(typep, rec->data, sizeof(*typep));
+	memset(&control_dbt, 0, sizeof(control_dbt));
+	memset(&rec_dbt, 0, sizeof(rec_dbt));
+
+	/*
+	 * We write all records except for checkpoint records here.
+	 * All non-checkpoint records need to appear in the log before
+	 * we take action upon them (i.e., we enforce write-ahead logging).
+	 * However, we can't write the checkpoint record here until the
+	 * data buffers are actually written to disk, else we are creating
+	 * an invalid log -- one that says all data before a certain point
+	 * has been written to disk.
+	 *
+	 * If two threads are both processing the same checkpoint record
+	 * (because, for example, it was resent and the original finally
+	 * arrived), we handle that below by checking for the existence of
+	 * the log record when we add it to the replication database.
+	 *
+	 * Any log records that arrive while we are processing the checkpoint
+	 * are added to the bookkeeping database because ready_lsn is not yet
+	 * updated to point after the checkpoint record.
+	 */
+	if (*typep != DB___txn_ckp || F_ISSET(rep, REP_F_RECOVER_LOG)) {
+		if ((ret = __log_rep_put(dbenv, &rp->lsn, rec)) != 0)
+			return (ret);
+		rep->stat.st_log_records++;
+		if (F_ISSET(rep, REP_F_RECOVER_LOG)) {
+			*ret_lsnp = rp->lsn;
+			goto out;
+		}
+	}
+
+	switch (*typep) {
+	case DB___dbreg_register:
+		/*
+		 * DB opens occur in the context of a transaction, so we can
+		 * simply handle them when we process the transaction.  Closes,
+		 * however, are not transaction-protected, so we have to
+		 * handle them here.
+		 *
+		 * Note that it should be unsafe for the master to do a close
+		 * of a file that was opened in an active transaction, so we
+		 * should be guaranteed to get the ordering right.
+		 */
+		memcpy(&txnid, (u_int8_t *)rec->data +
+		    SSZ(__dbreg_register_args, txnid), sizeof(u_int32_t));
+		if (txnid == TXN_INVALID)
+			ret = __db_dispatch(dbenv, dbenv->recover_dtab,
+			    dbenv->recover_dtab_size, rec, &rp->lsn,
+			    DB_TXN_APPLY, NULL);
+		break;
+	case DB___txn_regop:
+		/*
+		 * If an application is doing app-specific recovery
+		 * and acquires locks while applying a transaction,
+		 * it can deadlock.  Any other locks held by this
+		 * thread should have been discarded in the
+		 * __rep_process_txn error path, so if we simply
+		 * retry, we should eventually succeed.
+		 */
+		do {
+			ret = 0;
+			if (!F_ISSET(db_rep, DBREP_OPENFILES)) {
+				ret = __txn_openfiles(dbenv, NULL, 1);
+				F_SET(db_rep, DBREP_OPENFILES);
+			}
+			if (ret == 0)
+				ret = __rep_process_txn(dbenv, rec);
+		} while (ret == DB_LOCK_DEADLOCK);
+
+		/* Now flush the log unless we're running TXN_NOSYNC. */
+		if (ret == 0 && !F_ISSET(dbenv, DB_ENV_TXN_NOSYNC))
+			ret = __log_flush(dbenv, NULL);
+		if (ret != 0) {
+			__db_err(dbenv, "Error processing txn [%lu][%lu]",
+			    (u_long)rp->lsn.file, (u_long)rp->lsn.offset);
+			ret = __db_panic(dbenv, ret);
+		}
+		break;
+	case DB___txn_xa_regop:
+		ret = __log_flush(dbenv, NULL);
+		break;
+	case DB___txn_ckp:
+		/*
+		 * We do not want to hold the db_rep->db_mutexp
+		 * mutex while syncing the mpool, so if we get
+		 * a checkpoint record that we are supposed to
+		 * process, we add it to the __db.rep.db, do
+		 * the memp_sync and then go back and process
+		 * it later, when the sync has finished.  If
+		 * this record is already in the table, then
+		 * some other thread will process it, so simply
+		 * return REP_NOTPERM;
+		 */
+		memset(&key_dbt, 0, sizeof(key_dbt));
+		key_dbt.data = rp;
+		key_dbt.size = sizeof(*rp);
+
+		/*
+		 * We want to put this record into the tmp DB only if
+		 * it doesn't exist, so use DB_NOOVERWRITE.
+		 */
+		ret = __db_put(dbp, NULL, &key_dbt, rec, DB_NOOVERWRITE);
+		if (ret == DB_KEYEXIST) {
+			if (ret_lsnp != NULL)
+				*ret_lsnp = rp->lsn;
+			ret = DB_REP_NOTPERM;
+		}
+		if (ret != 0)
+			break;
+
+		/*
+		 * Now, do the checkpoint.  Regardless of
+		 * whether the checkpoint succeeds or not,
+		 * we need to remove the record we just put
+		 * in the temporary database.  If the
+		 * checkpoint failed, return an error.  We
+		 * will act like we never received the
+		 * checkpoint.
+		 */
+		if ((ret = __rep_do_ckp(dbenv, rec, rp)) == 0)
+			ret = __log_rep_put(dbenv, &rp->lsn, rec);
+		if ((t_ret = __rep_remfirst(dbenv,
+		    &control_dbt, &rec_dbt)) != 0 && ret == 0)
+			ret = t_ret;
+		break;
+	default:
+		break;
+	}
+
+out:
+	if (ret == 0 && F_ISSET(rp, DB_LOG_PERM))
+		*ret_lsnp = rp->lsn;
+	if (control_dbt.data != NULL)
+		__os_ufree(dbenv, control_dbt.data);
+	if (rec_dbt.data != NULL)
+		__os_ufree(dbenv, rec_dbt.data);
+
+	return (ret);
+}
+
+/*
+ * __rep_resend_req --
+ *	We might have dropped a message, we need to resend our request.
+ *	The request we send is dependent on what recovery state we're in.
+ *	The caller holds no locks.
+ */
+static int
+__rep_resend_req(dbenv, eid)
+	DB_ENV *dbenv;
+	int eid;
+{
+
+	DB_LOG *dblp;
+	DB_LSN lsn;
+	DB_REP *db_rep;
+	LOG *lp;
+	REP *rep;
+	int ret;
+	u_int32_t repflags;
+
+	ret = 0;
+	db_rep = dbenv->rep_handle;
+	rep = db_rep->region;
+	dblp = dbenv->lg_handle;
+	lp = dblp->reginfo.primary;
+
+	repflags = rep->flags;
+	if (FLD_ISSET(repflags, REP_F_RECOVER_VERIFY)) {
+		MUTEX_LOCK(dbenv, db_rep->db_mutexp);
+		lsn = lp->verify_lsn;
+		MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+		if (!IS_ZERO_LSN(lsn))
+			(void)__rep_send_message(dbenv, eid,
+			    REP_VERIFY_REQ, &lsn, NULL, 0);
+		goto out;
+	} else if (FLD_ISSET(repflags, REP_F_RECOVER_UPDATE)) {
+		(void)__rep_send_message(dbenv, eid,
+		    REP_UPDATE_REQ, NULL, NULL, 0);
+	} else if (FLD_ISSET(repflags, REP_F_RECOVER_PAGE)) {
+		MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+		ret = __rep_pggap_req(dbenv, rep, NULL, 0);
+		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+	} else if (FLD_ISSET(repflags, REP_F_RECOVER_LOG)) {
+		MUTEX_LOCK(dbenv, db_rep->db_mutexp);
+		__rep_loggap_req(dbenv, rep, NULL, 0);
+		MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+	}
+
+out:
+	return (ret);
+}
+
+/*
+ * __rep_check_doreq --
+ * PUBLIC: int __rep_check_doreq __P((DB_ENV *, REP *));
+ *
+ * Check if we need to send another request.  If so, compare with
+ * the request limits the user might have set.  This assumes the
+ * caller holds the db_rep->db_mutexp mutex.  Returns 1 if a request
+ * needs to be made, and 0 if it does not.
+ */
+int
+__rep_check_doreq(dbenv, rep)
+	DB_ENV *dbenv;
+	REP *rep;
+{
+
+	DB_LOG *dblp;
+	LOG *lp;
+	int req;
+
+	dblp = dbenv->lg_handle;
+	lp = dblp->reginfo.primary;
+	req = ++lp->rcvd_recs >= lp->wait_recs;
+	if (req) {
+		lp->wait_recs *= 2;
+		if (lp->wait_recs > rep->max_gap)
+			lp->wait_recs = rep->max_gap;
+		lp->rcvd_recs = 0;
+	}
+	return (req);
+}
+
+/*
+ * __rep_lockout --
+ * PUBLIC: void __rep_lockout __P((DB_ENV *, DB_REP *, REP *, u_int32_t));
+ *
+ * Coordinate with other threads in the library and active txns so
+ * that we can run single-threaded, for recovery or internal backup.
+ * Assumes the caller holds rep_mutexp.
+ */
+void
+__rep_lockout(dbenv, db_rep, rep, msg_th)
+	DB_ENV *dbenv;
+	DB_REP *db_rep;
+	REP *rep;
+	u_int32_t msg_th;
+{
+	int wait_cnt;
+
+	/* Phase 1: set REP_F_READY and wait for op_cnt to go to 0. */
+	F_SET(rep, REP_F_READY);
+	for (wait_cnt = 0; rep->op_cnt != 0;) {
+		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+		__os_sleep(dbenv, 1, 0);
+#ifdef DIAGNOSTIC
+		if (++wait_cnt % 60 == 0)
+			__db_err(dbenv,
+	"Waiting for txn_cnt to run replication recovery/backup for %d minutes",
+			wait_cnt / 60);
+#endif
+		MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+	}
+
+	/*
+	 * Phase 2: set in_recovery and wait for handle count to go
+	 * to 0 and for the number of threads in __rep_process_message
+	 * to go to 1 (us).
+	 */
+	rep->in_recovery = 1;
+	for (wait_cnt = 0; rep->handle_cnt != 0 || rep->msg_th > msg_th;) {
+		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+		__os_sleep(dbenv, 1, 0);
+#ifdef DIAGNOSTIC
+		if (++wait_cnt % 60 == 0)
+			__db_err(dbenv,
+"Waiting for handle count to run replication recovery/backup for %d minutes",
+			wait_cnt / 60);
+#endif
+		MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+	}
+}
diff --git a/storage/bdb/rep/rep_region.c b/storage/bdb/rep/rep_region.c
index 1ac3fb8a20c55f420388475d91c3c11bb82dcd89..b163e3456e63324c6cb9a27d32542fd193523fd6 100644
--- a/storage/bdb/rep/rep_region.c
+++ b/storage/bdb/rep/rep_region.c
@@ -1,23 +1,35 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
+ * Copyright (c) 2001-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: rep_region.c,v 1.53 2004/10/15 16:59:44 bostic Exp $
  */
-#include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: rep_region.c,v 1.29 2002/08/06 04:50:36 bostic Exp $";
-#endif /* not lint */
+#include "db_config.h"
 
 #ifndef NO_SYSTEM_INCLUDES
+#if TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
 #endif
 
 #include <string.h>
+#endif
 
 #include "db_int.h"
-#include "dbinc/rep.h"
+#include "dbinc/db_page.h"
 #include "dbinc/log.h"
+#include "dbinc/db_am.h"
+
+static int __rep_egen_init  __P((DB_ENV *, REP *));
 
 /*
  * __rep_region_init --
@@ -44,11 +56,12 @@ __rep_region_init(dbenv)
 	MUTEX_LOCK(dbenv, &renv->mutex);
 	if (renv->rep_off == INVALID_ROFF) {
 		/* Must create the region. */
-		if ((ret = __db_shalloc(infop->addr,
-		    sizeof(REP), MUTEX_ALIGN, &rep)) != 0)
+		if ((ret =
+		    __db_shalloc(infop, sizeof(REP), MUTEX_ALIGN, &rep)) != 0)
 			goto err;
 		memset(rep, 0, sizeof(*rep));
 		rep->tally_off = INVALID_ROFF;
+		rep->v2tally_off = INVALID_ROFF;
 		renv->rep_off = R_OFFSET(infop, rep);
 
 		if ((ret = __db_mutex_setup(dbenv, infop, &rep->mutex,
@@ -61,7 +74,7 @@ __rep_region_init(dbenv)
 		 * to guarantee that is to make sure they're at the beginning
 		 * of a shalloc'ed chunk.
 		 */
-		if ((ret = __db_shalloc(infop->addr, sizeof(DB_MUTEX),
+		if ((ret = __db_shalloc(infop, sizeof(DB_MUTEX),
 		    MUTEX_ALIGN, &db_mutexp)) != 0)
 			goto err;
 		rep->db_mutex_off = R_OFFSET(infop, db_mutexp);
@@ -81,18 +94,23 @@ __rep_region_init(dbenv)
 		rep->eid = DB_EID_INVALID;
 		rep->master_id = DB_EID_INVALID;
 		rep->gen = 0;
-
+		if ((ret = __rep_egen_init(dbenv, rep)) != 0)
+			goto err;
 		/*
 		 * Set default values for the min and max log records that we
 		 * wait before requesting a missing log record.
 		 */
 		rep->request_gap = DB_REP_REQUEST_GAP;
 		rep->max_gap = DB_REP_MAX_GAP;
+		F_SET(rep, REP_F_NOARCHIVE);
+		(void)time(&renv->rep_timestamp);
+		renv->op_timestamp = 0;
+		F_CLR(renv, DB_REGENV_REPLOCKED);
 	} else
 		rep = R_ADDR(infop, renv->rep_off);
 	MUTEX_UNLOCK(dbenv, &renv->mutex);
 
-	db_rep->mutexp = &rep->mutex;
+	db_rep->rep_mutexp = &rep->mutex;
 	db_rep->db_mutexp = R_ADDR(infop, rep->db_mutex_off);
 	db_rep->region = rep;
 
@@ -116,11 +134,11 @@ __rep_region_destroy(dbenv)
 	int ret, t_ret;
 
 	ret = t_ret = 0;
-	db_rep = (DB_REP *)dbenv->rep_handle;
+	db_rep = dbenv->rep_handle;
 
 	if (db_rep != NULL) {
-		if (db_rep->mutexp != NULL)
-			ret = __db_mutex_destroy(db_rep->mutexp);
+		if (db_rep->rep_mutexp != NULL)
+			ret = __db_mutex_destroy(db_rep->rep_mutexp);
 		if (db_rep->db_mutexp != NULL)
 			t_ret = __db_mutex_destroy(db_rep->db_mutexp);
 	}
@@ -128,6 +146,21 @@ __rep_region_destroy(dbenv)
 	return (ret == 0 ? t_ret : ret);
 }
 
+/*
+ * __rep_dbenv_refresh --
+ *	Replication-specific refresh of the DB_ENV structure.
+ *
+ * PUBLIC: void __rep_dbenv_refresh __P((DB_ENV *));
+ */
+void
+__rep_dbenv_refresh(dbenv)
+	DB_ENV *dbenv;
+{
+	if (REP_ON(dbenv))
+		((DB_REP *)dbenv->rep_handle)->region = NULL;
+	return;
+}
+
 /*
  * __rep_dbenv_close --
  *	Replication-specific destruction of the DB_ENV structure.
@@ -138,13 +171,10 @@ int
 __rep_dbenv_close(dbenv)
 	DB_ENV *dbenv;
 {
-	DB_REP *db_rep;
-
-	db_rep = (DB_REP *)dbenv->rep_handle;
-
-	if (db_rep != NULL) {
-		__os_free(dbenv, db_rep);
+	if (REP_ON(dbenv)) {
+		__os_free(dbenv, dbenv->rep_handle);
 		dbenv->rep_handle = NULL;
+		dbenv->rep_send = NULL;
 	}
 
 	return (0);
@@ -163,25 +193,101 @@ __rep_preclose(dbenv, do_closefiles)
 	DB_ENV *dbenv;
 	int do_closefiles;
 {
-	DB *dbp;
 	DB_REP *db_rep;
 	int ret, t_ret;
 
-	ret = t_ret = 0;
-
-	/* If replication is not initialized, we have nothing to do. */
-	if ((db_rep = (DB_REP *)dbenv->rep_handle) == NULL)
-		return (0);
+	ret = 0;
 
-	if ((dbp = db_rep->rep_db) != NULL) {
-		MUTEX_LOCK(dbenv, db_rep->db_mutexp);
-		ret = dbp->close(dbp, 0);
+	db_rep = dbenv->rep_handle;
+	MUTEX_LOCK(dbenv, db_rep->db_mutexp);
+	if (db_rep->rep_db != NULL) {
+		ret = __db_close(db_rep->rep_db, NULL, DB_NOSYNC);
 		db_rep->rep_db = NULL;
-		MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
 	}
 
-	if (do_closefiles)
-		t_ret = __dbreg_close_files(dbenv);
+	if (do_closefiles) {
+		if ((t_ret = __dbreg_close_files(dbenv)) != 0 && ret == 0)
+			ret = t_ret;
+		F_CLR(db_rep, DBREP_OPENFILES);
+	}
+	MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+	return (ret);
+}
+
+/*
+ * __rep_egen_init --
+ *	Initialize the value of egen in the region.  Called
+ * only from __rep_region_init, which is guaranteed to be
+ * single-threaded as we create the rep region.  We set the
+ * rep->egen field which is normally protected by db_rep->rep_mutex.
+ */
+static int
+__rep_egen_init(dbenv, rep)
+	DB_ENV *dbenv;
+	REP *rep;
+{
+	DB_FH *fhp;
+	int ret;
+	size_t cnt;
+	char *p;
+#ifdef DIAGNOSTIC
+	DB_MSGBUF mb;
+#endif
+
+	if ((ret =
+	    __db_appname(dbenv, DB_APP_NONE, REP_EGENNAME, 0, NULL, &p)) != 0)
+		return (ret);
+	/*
+	 * If the file doesn't exist, create it now and initialize with 1.
+	 */
+	if (__os_exists(p, NULL) != 0) {
+		rep->egen = rep->gen + 1;
+		if ((ret = __rep_write_egen(dbenv, rep->egen)) != 0)
+			goto err;
+	} else {
+		/*
+		 * File exists, open it and read in our egen.
+		 */
+		if ((ret = __os_open(dbenv, p, DB_OSO_RDONLY,
+		    __db_omode("rw----"), &fhp)) != 0)
+			goto err;
+		if ((ret = __os_read(dbenv, fhp, &rep->egen, sizeof(u_int32_t),
+		    &cnt)) < 0 || cnt == 0)
+			goto err1;
+		RPRINT(dbenv, rep, (dbenv, &mb, "Read in egen %lu",
+		    (u_long)rep->egen));
+err1:		 (void)__os_closehandle(dbenv, fhp);
+	}
+err:	__os_free(dbenv, p);
+	return (ret);
+}
+
+/*
+ * __rep_write_egen --
+ *	Write out the egen into the env file.
+ *
+ * PUBLIC: int __rep_write_egen __P((DB_ENV *, u_int32_t));
+ */
+int
+__rep_write_egen(dbenv, egen)
+	DB_ENV *dbenv;
+	u_int32_t egen;
+{
+	DB_FH *fhp;
+	int ret;
+	size_t cnt;
+	char *p;
 
-	return (ret == 0 ? t_ret : ret);
+	if ((ret =
+	    __db_appname(dbenv, DB_APP_NONE, REP_EGENNAME, 0, NULL, &p)) != 0)
+		return (ret);
+	if ((ret = __os_open(dbenv, p, DB_OSO_CREATE | DB_OSO_TRUNC,
+	    __db_omode("rw----"), &fhp)) == 0) {
+		if ((ret = __os_write(dbenv, fhp, &egen, sizeof(u_int32_t),
+		    &cnt)) != 0 || ((ret = __os_fsync(dbenv, fhp)) != 0))
+			__db_err(dbenv, "%s: %s", p, db_strerror(ret));
+		(void)__os_closehandle(dbenv, fhp);
+	}
+	__os_free(dbenv, p);
+	return (ret);
 }
diff --git a/storage/bdb/rep/rep_stat.c b/storage/bdb/rep/rep_stat.c
new file mode 100644
index 0000000000000000000000000000000000000000..d740c2b40c416080dfc14248290c3f3882dc356a
--- /dev/null
+++ b/storage/bdb/rep/rep_stat.c
@@ -0,0 +1,491 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2001-2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: rep_stat.c,v 1.155 2004/09/29 15:36:38 bostic Exp $
+ */
+
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#if TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#endif
+
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
+#include "dbinc/log.h"
+
+#ifdef HAVE_STATISTICS
+static int __rep_print_all __P((DB_ENV *, u_int32_t));
+static int __rep_print_stats __P((DB_ENV *, u_int32_t));
+static int __rep_stat __P((DB_ENV *, DB_REP_STAT **, u_int32_t));
+
+/*
+ * __rep_stat_pp --
+ *	DB_ENV->rep_stat pre/post processing.
+ *
+ * PUBLIC: int __rep_stat_pp __P((DB_ENV *, DB_REP_STAT **, u_int32_t));
+ */
+int
+__rep_stat_pp(dbenv, statp, flags)
+	DB_ENV *dbenv;
+	DB_REP_STAT **statp;
+	u_int32_t flags;
+{
+	int ret;
+
+	PANIC_CHECK(dbenv);
+	ENV_REQUIRES_CONFIG(dbenv,
+	    dbenv->rep_handle, "DB_ENV->rep_stat", DB_INIT_REP);
+
+	if ((ret = __db_fchk(dbenv,
+	    "DB_ENV->rep_stat", flags, DB_STAT_CLEAR)) != 0)
+		return (ret);
+
+	return (__rep_stat(dbenv, statp, flags));
+}
+
+/*
+ * __rep_stat --
+ *	DB_ENV->rep_stat.
+ */
+static int
+__rep_stat(dbenv, statp, flags)
+	DB_ENV *dbenv;
+	DB_REP_STAT **statp;
+	u_int32_t flags;
+{
+	DB_LOG *dblp;
+	DB_REP *db_rep;
+	DB_REP_STAT *stats;
+	LOG *lp;
+	REP *rep;
+	u_int32_t queued;
+	int dolock, ret;
+
+	db_rep = dbenv->rep_handle;
+	rep = db_rep->region;
+	dblp = dbenv->lg_handle;
+	lp = dblp->reginfo.primary;
+
+	*statp = NULL;
+
+	/* Allocate a stat struct to return to the user. */
+	if ((ret = __os_umalloc(dbenv, sizeof(DB_REP_STAT), &stats)) != 0)
+		return (ret);
+
+	/*
+	 * Read without holding the lock.  If we are in client recovery, we
+	 * copy just the stats struct so we won't block.  We only copy out
+	 * those stats that don't require acquiring any mutex.
+	 */
+	dolock = FLD_ISSET(rep->flags, REP_F_RECOVER_MASK) ? 0 : 1;
+	memcpy(stats, &rep->stat, sizeof(*stats));
+
+	/* Copy out election stats. */
+	if (IN_ELECTION_TALLY(rep)) {
+		if (F_ISSET(rep, REP_F_EPHASE1))
+			stats->st_election_status = 1;
+		else if (F_ISSET(rep, REP_F_EPHASE2))
+			stats->st_election_status = 2;
+
+		stats->st_election_nsites = rep->sites;
+		stats->st_election_cur_winner = rep->winner;
+		stats->st_election_priority = rep->w_priority;
+		stats->st_election_gen = rep->w_gen;
+		stats->st_election_lsn = rep->w_lsn;
+		stats->st_election_votes = rep->votes;
+		stats->st_election_tiebreaker = rep->w_tiebreaker;
+	}
+
+	/* Copy out other info that's protected by the rep mutex. */
+	stats->st_env_id = rep->eid;
+	stats->st_env_priority = rep->priority;
+	stats->st_nsites = rep->nsites;
+	stats->st_master = rep->master_id;
+	stats->st_gen = rep->gen;
+	stats->st_egen = rep->egen;
+
+	if (F_ISSET(rep, REP_F_MASTER))
+		stats->st_status = DB_REP_MASTER;
+	else if (F_ISSET(rep, REP_F_CLIENT))
+		stats->st_status = DB_REP_CLIENT;
+	else
+		stats->st_status = 0;
+
+	if (LF_ISSET(DB_STAT_CLEAR)) {
+		queued = rep->stat.st_log_queued;
+		memset(&rep->stat, 0, sizeof(rep->stat));
+		rep->stat.st_log_queued = rep->stat.st_log_queued_total =
+		    rep->stat.st_log_queued_max = queued;
+	}
+
+	/*
+	 * Log-related replication info is stored in the log system and
+	 * protected by the log region lock.
+	 */
+	if (dolock)
+		MUTEX_LOCK(dbenv, db_rep->db_mutexp);
+	if (F_ISSET(rep, REP_F_CLIENT)) {
+		stats->st_next_lsn = lp->ready_lsn;
+		stats->st_waiting_lsn = lp->waiting_lsn;
+		stats->st_next_pg = rep->ready_pg;
+		stats->st_waiting_pg = rep->waiting_pg;
+	} else {
+		if (F_ISSET(rep, REP_F_MASTER))
+			stats->st_next_lsn = lp->lsn;
+		else
+			ZERO_LSN(stats->st_next_lsn);
+		ZERO_LSN(stats->st_waiting_lsn);
+	}
+	if (dolock)
+		MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+
+	*statp = stats;
+	return (0);
+}
+
+/*
+ * __rep_stat_print_pp --
+ *	DB_ENV->rep_stat_print pre/post processing.
+ *
+ * PUBLIC: int __rep_stat_print_pp __P((DB_ENV *, u_int32_t));
+ */
+int
+__rep_stat_print_pp(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	int ret;
+
+	PANIC_CHECK(dbenv);
+	ENV_REQUIRES_CONFIG(dbenv,
+	    dbenv->rep_handle, "DB_ENV->rep_stat_print", DB_INIT_REP);
+
+	if ((ret = __db_fchk(dbenv, "DB_ENV->rep_stat_print",
+	    flags, DB_STAT_ALL | DB_STAT_CLEAR)) != 0)
+		return (ret);
+
+	return (__rep_stat_print(dbenv, flags));
+}
+
+/*
+ * __rep_stat_print --
+ *	DB_ENV->rep_stat_print method.
+ *
+ * PUBLIC: int __rep_stat_print __P((DB_ENV *, u_int32_t));
+ */
+int
+__rep_stat_print(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	u_int32_t orig_flags;
+	int ret;
+
+	orig_flags = flags;
+	LF_CLR(DB_STAT_CLEAR);
+	if (flags == 0 || LF_ISSET(DB_STAT_ALL)) {
+		ret = __rep_print_stats(dbenv, orig_flags);
+		if (flags == 0 || ret != 0)
+			return (ret);
+	}
+
+	if (LF_ISSET(DB_STAT_ALL) &&
+	    (ret = __rep_print_all(dbenv, orig_flags)) != 0)
+		return (ret);
+
+	return (0);
+}
+
+/*
+ * __rep_print_stats --
+ *	Print out default statistics.
+ */
+static int
+__rep_print_stats(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	DB_REP_STAT *sp;
+	int is_client, ret;
+	char *p;
+
+	if ((ret = __rep_stat(dbenv, &sp, flags)) != 0)
+		return (ret);
+
+	if (LF_ISSET(DB_STAT_ALL))
+		__db_msg(dbenv, "Default replication region information:");
+	is_client = 0;
+	switch (sp->st_status) {
+	case DB_REP_MASTER:
+		__db_msg(dbenv,
+		    "Environment configured as a replication master");
+		break;
+	case DB_REP_CLIENT:
+		__db_msg(dbenv,
+		    "Environment configured as a replication client");
+		is_client = 1;
+		break;
+	default:
+		__db_msg(dbenv,
+		    "Environment not configured for replication");
+		break;
+	}
+
+	__db_msg(dbenv, "%lu/%lu\t%s",
+	    (u_long)sp->st_next_lsn.file, (u_long)sp->st_next_lsn.offset,
+	    is_client ? "Next LSN expected" : "Next LSN to be used");
+	__db_msg(dbenv, "%lu/%lu\t%s",
+	    (u_long)sp->st_waiting_lsn.file, (u_long)sp->st_waiting_lsn.offset,
+	    sp->st_waiting_lsn.file == 0 ?
+	    "Not waiting for any missed log records" :
+	    "LSN of first log record we have after missed log records");
+
+	__db_dl(dbenv, "Next page number expected.", (u_long)sp->st_next_pg);
+	p = sp->st_waiting_pg == PGNO_INVALID ?
+	    "Not waiting for any missed pages." :
+	    "Page number of first page we have after missed pages.";
+	__db_msg(dbenv, "%lu\t%s", (u_long)sp->st_waiting_pg, p);
+	__db_dl(dbenv, "Number of duplicate master conditions detected.",
+	    (u_long)sp->st_dupmasters);
+	if (sp->st_env_id != DB_EID_INVALID)
+		__db_dl(dbenv, "Current environment ID", (u_long)sp->st_env_id);
+	else
+		__db_msg(dbenv, "No current environment ID");
+	__db_dl(dbenv,
+	    "Current environment priority", (u_long)sp->st_env_priority);
+	__db_dl(dbenv, "Current generation number", (u_long)sp->st_gen);
+	__db_dl(dbenv,
+	    "Current election generation number", (u_long)sp->st_egen);
+	__db_dl(dbenv, "Number of duplicate log records received",
+	    (u_long)sp->st_log_duplicated);
+	__db_dl(dbenv, "Number of log records currently queued",
+	    (u_long)sp->st_log_queued);
+	__db_dl(dbenv, "Maximum number of log records ever queued at once",
+	    (u_long)sp->st_log_queued_max);
+	__db_dl(dbenv, "Total number of log records queued",
+	    (u_long)sp->st_log_queued_total);
+	__db_dl(dbenv,
+	    "Number of log records received and appended to the log",
+	    (u_long)sp->st_log_records);
+	__db_dl(dbenv, "Number of log records missed and requested",
+	    (u_long)sp->st_log_requested);
+	if (sp->st_master != DB_EID_INVALID)
+		__db_dl(dbenv, "Current master ID", (u_long)sp->st_master);
+	else
+		__db_msg(dbenv, "No current master ID");
+	__db_dl(dbenv, "Number of times the master has changed",
+	    (u_long)sp->st_master_changes);
+	__db_dl(dbenv,
+	    "Number of messages received with a bad generation number",
+	    (u_long)sp->st_msgs_badgen);
+	__db_dl(dbenv, "Number of messages received and processed",
+	    (u_long)sp->st_msgs_processed);
+	__db_dl(dbenv, "Number of messages ignored due to pending recovery",
+	    (u_long)sp->st_msgs_recover);
+	__db_dl(dbenv, "Number of failed message sends",
+	    (u_long)sp->st_msgs_send_failures);
+	__db_dl(dbenv, "Number of messages sent", (u_long)sp->st_msgs_sent);
+	__db_dl(dbenv,
+	    "Number of new site messages received", (u_long)sp->st_newsites);
+	__db_dl(dbenv,
+	    "Number of environments believed to be in the replication group",
+	    (u_long)sp->st_nsites);
+	__db_dl(dbenv, "Transmission limited", (u_long)sp->st_nthrottles);
+	__db_dl(dbenv, "Number of outdated conditions detected",
+	    (u_long)sp->st_outdated);
+	__db_dl(dbenv, "Number of duplicate page records received",
+	    (u_long)sp->st_pg_duplicated);
+	__db_dl(dbenv, "Number of page records received and added to databases",
+	    (u_long)sp->st_pg_records);
+	__db_dl(dbenv, "Number of page records missed and requested",
+	    (u_long)sp->st_pg_requested);
+	if (sp->st_startup_complete == 0)
+		__db_msg(dbenv, "Startup incomplete");
+	else
+		__db_msg(dbenv, "Startup complete");
+	__db_dl(dbenv,
+	    "Number of transactions applied", (u_long)sp->st_txns_applied);
+
+	__db_dl(dbenv, "Number of elections held", (u_long)sp->st_elections);
+	__db_dl(dbenv,
+	    "Number of elections won", (u_long)sp->st_elections_won);
+
+	if (sp->st_election_status == 0)
+		__db_msg(dbenv, "No election in progress");
+	else {
+		__db_dl(dbenv, "Current election phase",
+		    (u_long)sp->st_election_status);
+		__db_dl(dbenv, "Election winner",
+		    (u_long)sp->st_election_cur_winner);
+		__db_dl(dbenv, "Election generation number",
+		    (u_long)sp->st_election_gen);
+		__db_msg(dbenv, "%lu/%lu\tMaximum LSN of election winner",
+		    (u_long)sp->st_election_lsn.file,
+		    (u_long)sp->st_election_lsn.offset);
+		__db_dl(dbenv,
+		    "Number of sites expected to participate in elections",
+		    (u_long)sp->st_election_nsites);
+		__db_dl(dbenv, "Number of votes needed to win an election",
+		    (u_long)sp->st_election_nvotes);
+		__db_dl(dbenv,
+		    "Election priority", (u_long)sp->st_election_priority);
+		__db_dl(dbenv, "Election tiebreaker value",
+		    (u_long)sp->st_election_tiebreaker);
+		__db_dl(dbenv, "Votes received this election round",
+		    (u_long)sp->st_election_votes);
+	}
+
+	__os_ufree(dbenv, sp);
+
+	return (0);
+}
+
+/*
+ * __rep_print_all --
+ *	Display debugging replication region statistics.
+ */
+static int
+__rep_print_all(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	static const FN rep_fn[] = {
+		{ REP_F_CLIENT,		"REP_F_CLIENT" },
+		{ REP_F_EPHASE1,	"REP_F_EPHASE1" },
+		{ REP_F_EPHASE2,	"REP_F_EPHASE2" },
+		{ REP_F_MASTER,		"REP_F_MASTER" },
+		{ REP_F_MASTERELECT,	"REP_F_MASTERELECT" },
+		{ REP_F_NOARCHIVE,	"REP_F_NOARCHIVE" },
+		{ REP_F_READY,		"REP_F_READY" },
+		{ REP_F_RECOVER_LOG,	"REP_F_RECOVER_LOG" },
+		{ REP_F_RECOVER_PAGE,	"REP_F_RECOVER_PAGE" },
+		{ REP_F_RECOVER_UPDATE,	"REP_F_RECOVER_UPDATE" },
+		{ REP_F_RECOVER_VERIFY,	"REP_F_RECOVER_VERIFY" },
+		{ REP_F_TALLY,		"REP_F_TALLY" },
+		{ 0,			NULL }
+	};
+	static const FN dbrep_fn[] = {
+		{ DBREP_OPENFILES,	"DBREP_OPENFILES" },
+		{ 0,			NULL }
+	};
+	DB_LOG *dblp;
+	DB_REP *db_rep;
+	LOG *lp;
+	REGENV *renv;
+	REGINFO *infop;
+	REP *rep;
+
+	db_rep = dbenv->rep_handle;
+	rep = db_rep->region;
+	infop = dbenv->reginfo;
+	renv = infop->primary;
+
+	__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+	__db_msg(dbenv, "DB_REP handle information:");
+	__db_print_mutex(dbenv, NULL,
+	    db_rep->rep_mutexp, "Replication region mutex", flags);
+	__db_print_mutex(dbenv, NULL,
+	    db_rep->db_mutexp, "Bookkeeping database mutex", flags);
+
+	if (db_rep->rep_db == NULL)
+		STAT_ISSET("Bookkeeping database", db_rep->rep_db);
+	else
+		(void)__db_stat_print(db_rep->rep_db, flags);
+
+	__db_prflags(dbenv, NULL, db_rep->flags, dbrep_fn, NULL, "\tFlags");
+
+	__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+	__db_msg(dbenv, "REP handle information:");
+	__db_print_mutex(dbenv, NULL, &rep->mutex, "REP mutex", flags);
+
+	STAT_LONG("Environment ID", rep->eid);
+	STAT_LONG("Master environment ID", rep->master_id);
+	STAT_ULONG("Election generation", rep->egen);
+	STAT_ULONG("Election generation number", rep->gen);
+	STAT_ULONG("Last generation number in log", rep->recover_gen);
+	STAT_LONG("Space allocated for sites", rep->asites);
+	STAT_LONG("Sites in group", rep->nsites);
+	STAT_LONG("Votes needed for election", rep->nvotes);
+	STAT_LONG("Priority in election", rep->priority);
+	__db_dlbytes(dbenv, "Limit on data sent in a single call",
+	    rep->gbytes, (u_long)0, rep->bytes);
+	STAT_ULONG("Request gap", rep->request_gap);
+	STAT_ULONG("Maximum gap", rep->max_gap);
+
+	STAT_LONG("Thread is in rep_elect", rep->elect_th);
+	STAT_ULONG("Callers in rep_proc_msg", rep->msg_th);
+	STAT_LONG("Thread is in rep_start", rep->start_th);
+	STAT_ULONG("Library handle count", rep->handle_cnt);
+	STAT_ULONG("Multi-step operation count", rep->op_cnt);
+	STAT_LONG("Running recovery", rep->in_recovery);
+	__db_msg(dbenv, "%.24s\tRecovery timestamp",
+	    renv->rep_timestamp == 0 ? "0" : ctime(&renv->rep_timestamp));
+
+	STAT_LONG("Sites heard from", rep->sites);
+	STAT_LONG("Current winner", rep->winner);
+	STAT_LONG("Winner priority", rep->w_priority);
+	STAT_ULONG("Winner generation", rep->w_gen);
+	STAT_LSN("Winner LSN", &rep->w_lsn);
+	STAT_LONG("Winner tiebreaker", rep->w_tiebreaker);
+	STAT_LONG("Votes for this site", rep->votes);
+
+	__db_prflags(dbenv, NULL, rep->flags, rep_fn, NULL, "\tFlags");
+
+	__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+	__db_msg(dbenv, "LOG replication information:");
+	MUTEX_LOCK(dbenv, db_rep->db_mutexp);
+	dblp = dbenv->lg_handle;
+	lp = (LOG *)dblp->reginfo.primary;
+	STAT_LSN("First log record after a gap", &lp->waiting_lsn);
+	STAT_LSN("LSN waiting to verify", &lp->verify_lsn);
+	STAT_LSN("Maximum LSN requested", &lp->max_wait_lsn);
+	STAT_ULONG("Records to wait before requesting", lp->wait_recs);
+	STAT_ULONG("Records received while waiting", lp->rcvd_recs);
+	STAT_LSN("Next LSN expected", &lp->ready_lsn);
+	MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+
+	return (0);
+}
+
+#else /* !HAVE_STATISTICS */
+
+int
+__rep_stat_pp(dbenv, statp, flags)
+	DB_ENV *dbenv;
+	DB_REP_STAT **statp;
+	u_int32_t flags;
+{
+	COMPQUIET(statp, NULL);
+	COMPQUIET(flags, 0);
+
+	return (__db_stat_not_built(dbenv));
+}
+
+int
+__rep_stat_print_pp(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	COMPQUIET(flags, 0);
+
+	return (__db_stat_not_built(dbenv));
+}
+#endif
diff --git a/storage/bdb/rep/rep_stub.c b/storage/bdb/rep/rep_stub.c
new file mode 100644
index 0000000000000000000000000000000000000000..c2851915d1e678f89eadd28971b1d0efd3d4c663
--- /dev/null
+++ b/storage/bdb/rep/rep_stub.c
@@ -0,0 +1,319 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996-2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: rep_stub.c,v 1.22 2004/09/29 15:36:04 bostic Exp $
+ */
+
+#include "db_config.h"
+
+#ifndef HAVE_REPLICATION
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
+
+/*
+ * If the library wasn't compiled with replication support, various routines
+ * aren't available.  Stub them here, returning an appropriate error.
+ */
+
+static int __db_norep __P((DB_ENV *));
+static int __rep_elect
+    __P((DB_ENV *, int, int, int, u_int32_t, int *, u_int32_t));
+static int __rep_flush __P((DB_ENV *));
+static int __rep_start __P((DB_ENV *, DBT *, u_int32_t));
+static int __rep_get_limit __P((DB_ENV *, u_int32_t *, u_int32_t *));
+static int __rep_set_limit __P((DB_ENV *, u_int32_t, u_int32_t));
+static int __rep_set_request __P((DB_ENV *, u_int32_t, u_int32_t));
+static int __rep_set_rep_transport __P((DB_ENV *, int, int (*)
+    (DB_ENV *, const DBT *, const DBT *, const DB_LSN *, int, u_int32_t)));
+
+/*
+ * __db_norep --
+ *	Error when a Berkeley DB build doesn't include the access method.
+ */
+static int
+__db_norep(dbenv)
+	DB_ENV *dbenv;
+{
+	__db_err(dbenv,
+	    "library build did not include support for replication");
+	return (DB_OPNOTSUP);
+}
+
+int
+__db_rep_enter(dbp, checkgen, checklock, return_now)
+	DB *dbp;
+	int checkgen, checklock, return_now;
+{
+	COMPQUIET(checkgen, 0);
+	COMPQUIET(checklock, 0);
+	COMPQUIET(return_now, 0);
+	return (__db_norep(dbp->dbenv));
+}
+
+void
+__env_rep_enter(dbenv)
+	DB_ENV *dbenv;
+{
+	COMPQUIET(dbenv, NULL);
+	return;
+}
+
+void
+__env_db_rep_exit(dbenv)
+	DB_ENV *dbenv;
+{
+	COMPQUIET(dbenv, NULL);
+	return;
+}
+
+void
+__op_rep_enter(dbenv)
+	DB_ENV *dbenv;
+{
+	COMPQUIET(dbenv, NULL);
+	return;
+}
+
+void
+__op_rep_exit(dbenv)
+	DB_ENV *dbenv;
+{
+	COMPQUIET(dbenv, NULL);
+	return;
+}
+
+int
+__rep_dbenv_close(dbenv)
+	DB_ENV *dbenv;
+{
+	COMPQUIET(dbenv, NULL);
+	return (0);
+}
+
+void
+__rep_dbenv_create(dbenv)
+	DB_ENV *dbenv;
+{
+	dbenv->rep_elect = __rep_elect;
+	dbenv->rep_flush = __rep_flush;
+	dbenv->rep_process_message = __rep_process_message;
+	dbenv->rep_start = __rep_start;
+	dbenv->rep_stat = __rep_stat_pp;
+	dbenv->rep_stat_print = __rep_stat_print_pp;
+	dbenv->get_rep_limit = __rep_get_limit;
+	dbenv->set_rep_limit = __rep_set_limit;
+	dbenv->set_rep_request = __rep_set_request;
+	dbenv->set_rep_transport = __rep_set_rep_transport;
+}
+
+void
+__rep_dbenv_refresh(dbenv)
+	DB_ENV *dbenv;
+{
+	COMPQUIET(dbenv, NULL);
+	return;
+}
+
+static int
+__rep_elect(dbenv, nsites, nvotes, priority, timeout, eidp, flags)
+	DB_ENV *dbenv;
+	int nsites, nvotes, priority;
+	u_int32_t timeout, flags;
+	int *eidp;
+{
+	COMPQUIET(nsites, 0);
+	COMPQUIET(nvotes, 0);
+	COMPQUIET(priority, 0);
+	COMPQUIET(timeout, 0);
+	COMPQUIET(eidp, NULL);
+	COMPQUIET(flags, 0);
+	return (__db_norep(dbenv));
+}
+
+static int
+__rep_flush(dbenv)
+	DB_ENV *dbenv;
+{
+	return (__db_norep(dbenv));
+}
+
+static int
+__rep_get_limit(dbenv, gbytesp, bytesp)
+	DB_ENV *dbenv;
+	u_int32_t *gbytesp, *bytesp;
+{
+	COMPQUIET(gbytesp, NULL);
+	COMPQUIET(bytesp, NULL);
+	return (__db_norep(dbenv));
+}
+
+void
+__rep_get_gen(dbenv, genp)
+	DB_ENV *dbenv;
+	u_int32_t *genp;
+{
+	COMPQUIET(dbenv, NULL);
+	COMPQUIET(genp, NULL);
+	return;
+}
+
+int
+__rep_is_client(dbenv)
+	DB_ENV *dbenv;
+{
+	COMPQUIET(dbenv, NULL);
+	return (0);
+}
+
+int
+__rep_noarchive(dbenv)
+	DB_ENV *dbenv;
+{
+	COMPQUIET(dbenv, NULL);
+	return (0);
+}
+
+int
+__rep_open(dbenv)
+	DB_ENV *dbenv;
+{
+	COMPQUIET(dbenv, NULL);
+	return (0);
+}
+
+int
+__rep_preclose(dbenv, do_closefiles)
+	DB_ENV *dbenv;
+	int do_closefiles;
+{
+	COMPQUIET(do_closefiles, 0);
+	return (__db_norep(dbenv));
+}
+
+int
+__rep_process_message(dbenv, control, rec, eidp, ret_lsnp)
+	DB_ENV *dbenv;
+	DBT *control, *rec;
+	int *eidp;
+	DB_LSN *ret_lsnp;
+{
+	COMPQUIET(control, NULL);
+	COMPQUIET(rec, NULL);
+	COMPQUIET(eidp, NULL);
+	COMPQUIET(ret_lsnp, NULL);
+	return (__db_norep(dbenv));
+}
+
+int
+__rep_region_destroy(dbenv)
+	DB_ENV *dbenv;
+{
+	COMPQUIET(dbenv, NULL);
+	return (0);
+}
+
+int
+__rep_region_init(dbenv)
+	DB_ENV *dbenv;
+{
+	COMPQUIET(dbenv, NULL);
+	return (0);
+}
+
+int
+__rep_send_message(dbenv, eid, rtype, lsnp, dbtp, flags)
+	DB_ENV *dbenv;
+	int eid;
+	u_int32_t rtype;
+	DB_LSN *lsnp;
+	const DBT *dbtp;
+	u_int32_t flags;
+{
+	COMPQUIET(eid, 0);
+	COMPQUIET(rtype, 0);
+	COMPQUIET(lsnp, NULL);
+	COMPQUIET(dbtp, NULL);
+	COMPQUIET(flags, 0);
+	return (__db_norep(dbenv));
+}
+
+static int
+__rep_set_limit(dbenv, gbytes, bytes)
+	DB_ENV *dbenv;
+	u_int32_t gbytes, bytes;
+{
+	COMPQUIET(gbytes, 0);
+	COMPQUIET(bytes, 0);
+	return (__db_norep(dbenv));
+}
+
+static int
+__rep_set_rep_transport(dbenv, eid, f_send)
+	DB_ENV *dbenv;
+	int eid;
+	int (*f_send) __P((DB_ENV *, const DBT *, const DBT *, const DB_LSN *,
+	    int, u_int32_t));
+{
+	COMPQUIET(eid, 0);
+	COMPQUIET(f_send, NULL);
+	return (__db_norep(dbenv));
+}
+
+static int
+__rep_set_request(dbenv, min, max)
+	DB_ENV *dbenv;
+	u_int32_t min, max;
+{
+	COMPQUIET(min, 0);
+	COMPQUIET(max, 0);
+	return (__db_norep(dbenv));
+}
+
+static int
+__rep_start(dbenv, dbt, flags)
+	DB_ENV *dbenv;
+	DBT *dbt;
+	u_int32_t flags;
+{
+	COMPQUIET(dbt, NULL);
+	COMPQUIET(flags, 0);
+	return (__db_norep(dbenv));
+}
+
+int
+__rep_stat_pp(dbenv, statp, flags)
+	DB_ENV *dbenv;
+	DB_REP_STAT **statp;
+	u_int32_t flags;
+{
+	COMPQUIET(statp, NULL);
+	COMPQUIET(flags, 0);
+	return (__db_norep(dbenv));
+}
+
+int
+__rep_stat_print_pp(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	COMPQUIET(flags, 0);
+	return (__db_norep(dbenv));
+}
+
+int
+__rep_stat_print(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	COMPQUIET(flags, 0);
+	return (__db_norep(dbenv));
+}
+#endif /* !HAVE_REPLICATION */
diff --git a/storage/bdb/rep/rep_util.c b/storage/bdb/rep/rep_util.c
index 9c99d33ed4a3bd020e9528b782b8e6680c54d3e0..b6e72a6b47ce81841821b0c6344d1e98ed1c18f9 100644
--- a/storage/bdb/rep/rep_util.c
+++ b/storage/bdb/rep/rep_util.c
@@ -1,29 +1,31 @@
 /*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 2001-2002
+ * See the file LICENSE for redistribution information.  *
+ * Copyright (c) 2001-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: rep_util.c,v 1.135 2004/10/15 16:59:44 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: rep_util.c,v 1.51 2002/09/05 02:30:00 margo Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
+#if TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#endif
+
 #include <stdlib.h>
 #include <string.h>
 #endif
 
 #include "db_int.h"
-#include "dbinc/db_page.h"
-#include "dbinc/btree.h"
-#include "dbinc/fop.h"
-#include "dbinc/hash.h"
 #include "dbinc/log.h"
-#include "dbinc/qam.h"
-#include "dbinc/rep.h"
 #include "dbinc/txn.h"
 
 /*
@@ -31,42 +33,22 @@ static const char revid[] = "$Id: rep_util.c,v 1.51 2002/09/05 02:30:00 margo Ex
  *	Miscellaneous replication-related utility functions, including
  *	those called by other subsystems.
  */
-static int __rep_cmp_bylsn __P((const void *, const void *));
-static int __rep_cmp_bypage __P((const void *, const void *));
+
+#define	TIMESTAMP_CHECK(dbenv, ts, renv)			\
+do {								\
+	if (renv->op_timestamp != 0 &&				\
+	    renv->op_timestamp + DB_REGENV_TIMEOUT < ts) {		\
+		MUTEX_LOCK(dbenv, &renv->mutex);		\
+		F_CLR(renv, DB_REGENV_REPLOCKED);		\
+		renv->op_timestamp = 0;				\
+		MUTEX_UNLOCK(dbenv, &renv->mutex);		\
+	}							\
+} while (0)
 
 #ifdef REP_DIAGNOSTIC
 static void __rep_print_logmsg __P((DB_ENV *, const DBT *, DB_LSN *));
 #endif
 
-/*
- * __rep_check_alloc --
- *	Make sure the array of TXN_REC entries is of at least size n.
- *	(This function is called by the __*_getpgnos() functions in
- *	*.src.)
- *
- * PUBLIC: int __rep_check_alloc __P((DB_ENV *, TXN_RECS *, int));
- */
-int
-__rep_check_alloc(dbenv, r, n)
-	DB_ENV *dbenv;
-	TXN_RECS *r;
-	int n;
-{
-	int nalloc, ret;
-
-	while (r->nalloc < r->npages + n) {
-		nalloc = r->nalloc == 0 ? 20 : r->nalloc * 2;
-
-		if ((ret = __os_realloc(dbenv, nalloc * sizeof(LSN_PAGE),
-		    &r->array)) != 0)
-			return (ret);
-
-		r->nalloc = nalloc;
-	}
-
-	return (0);
-}
-
 /*
  * __rep_send_message --
  *	This is a wrapper for sending a message.  It takes care of constructing
@@ -88,8 +70,11 @@ __rep_send_message(dbenv, eid, rtype, lsnp, dbtp, flags)
 	REP *rep;
 	DBT cdbt, scrap_dbt;
 	REP_CONTROL cntrl;
-	u_int32_t send_flags;
 	int ret;
+	u_int32_t myflags, rectype;
+#ifdef DIAGNOSTIC
+	DB_MSGBUF mb;
+#endif
 
 	db_rep = dbenv->rep_handle;
 	rep = db_rep->region;
@@ -104,9 +89,7 @@ __rep_send_message(dbenv, eid, rtype, lsnp, dbtp, flags)
 	cntrl.flags = flags;
 	cntrl.rep_version = DB_REPVERSION;
 	cntrl.log_version = DB_LOGVERSION;
-	MUTEX_LOCK(dbenv, db_rep->mutexp);
 	cntrl.gen = rep->gen;
-	MUTEX_UNLOCK(dbenv, db_rep->mutexp);
 
 	memset(&cdbt, 0, sizeof(cdbt));
 	cdbt.data = &cntrl;
@@ -118,16 +101,40 @@ __rep_send_message(dbenv, eid, rtype, lsnp, dbtp, flags)
 		dbtp = &scrap_dbt;
 	}
 
-	send_flags = (LF_ISSET(DB_PERMANENT) ? DB_REP_PERMANENT : 0);
-
-#if 0
-	__rep_print_message(dbenv, eid, &cntrl, "rep_send_message");
-#endif
+	REP_PRINT_MESSAGE(dbenv, eid, &cntrl, "rep_send_message");
 #ifdef REP_DIAGNOSTIC
 	if (rtype == REP_LOG)
 		__rep_print_logmsg(dbenv, dbtp, lsnp);
 #endif
-	ret = db_rep->rep_send(dbenv, &cdbt, dbtp, eid, send_flags);
+	/*
+	 * There are three types of records: commit and checkpoint records
+	 * that affect database durability, regular log records that might
+	 * be buffered on the master before being transmitted, and control
+	 * messages which don't require the guarantees of permanency, but
+	 * should not be buffered.
+	 */
+	myflags = 0;
+	if (LF_ISSET(DB_LOG_PERM))
+		myflags = DB_REP_PERMANENT;
+	else if (rtype != REP_LOG || LF_ISSET(DB_LOG_RESEND))
+		myflags = DB_REP_NOBUFFER;
+	if (rtype == REP_LOG && !LF_ISSET(DB_LOG_PERM)) {
+		/*
+		 * Check if this is a log record we just read that
+		 * may need a DB_LOG_PERM.  This is of type REP_LOG,
+		 * so we know that dbtp is a log record.
+		 */
+		memcpy(&rectype, dbtp->data, sizeof(rectype));
+		if (rectype == DB___txn_regop || rectype == DB___txn_ckp)
+			F_SET(&cntrl, DB_LOG_PERM);
+	 }
+
+	/*
+	 * We set the LSN above to something valid.  Give the master the
+	 * actual LSN so that they can coordinate with permanent records from
+	 * the client if they want to.
+	 */
+	ret = dbenv->rep_send(dbenv, &cdbt, dbtp, &cntrl.lsn, eid, myflags);
 
 	/*
 	 * We don't hold the rep lock, so this could miscount if we race.
@@ -136,9 +143,11 @@ __rep_send_message(dbenv, eid, rtype, lsnp, dbtp, flags)
 	 */
 	if (ret == 0)
 		rep->stat.st_msgs_sent++;
-	else
+	else {
 		rep->stat.st_msgs_send_failures++;
-
+		RPRINT(dbenv, rep, (dbenv, &mb,
+		    "rep_send_function returned: %d", ret));
+	}
 	return (ret);
 }
 
@@ -168,8 +177,8 @@ __rep_print_logmsg(dbenv, logdbt, lsnp)
 		(void)__db_init_print(dbenv, &ptab, &ptabsize);
 		(void)__dbreg_init_print(dbenv, &ptab, &ptabsize);
 		(void)__fop_init_print(dbenv, &ptab, &ptabsize);
-		(void)__qam_init_print(dbenv, &ptab, &ptabsize);
 		(void)__ham_init_print(dbenv, &ptab, &ptabsize);
+		(void)__qam_init_print(dbenv, &ptab, &ptabsize);
 		(void)__txn_init_print(dbenv, &ptab, &ptabsize);
 	}
 
@@ -197,457 +206,253 @@ __rep_new_master(dbenv, cntrl, eid)
 	int eid;
 {
 	DB_LOG *dblp;
-	DB_LOGC *logc;
-	DB_LSN last_lsn, lsn;
+	DB_LSN ckp_lsn, lsn;
 	DB_REP *db_rep;
-	DBT dbt;
+	DB_TXNMGR *mgr;
+	DB_TXNREGION *region;
 	LOG *lp;
+	REGENV *renv;
+	REGINFO *infop;
 	REP *rep;
-	int change, ret, t_ret;
+	int change, do_req, ret;
+#ifdef DIAGNOSTIC
+	DB_MSGBUF mb;
+#endif
 
 	db_rep = dbenv->rep_handle;
+	mgr = dbenv->tx_handle;
+	region = mgr->reginfo.primary;
 	rep = db_rep->region;
-	MUTEX_LOCK(dbenv, db_rep->mutexp);
-	ELECTION_DONE(rep);
+	ret = 0;
+	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+	__rep_elect_done(dbenv, rep);
 	change = rep->gen != cntrl->gen || rep->master_id != eid;
 	if (change) {
+		RPRINT(dbenv, rep, (dbenv, &mb,
+		    "Updating gen from %lu to %lu from master %d",
+		    (u_long)rep->gen, (u_long)cntrl->gen, eid));
 		rep->gen = cntrl->gen;
+		if (rep->egen <= rep->gen)
+			rep->egen = rep->gen + 1;
+		RPRINT(dbenv, rep, (dbenv, &mb,
+		    "Egen is %lu", (u_long)rep->egen));
 		rep->master_id = eid;
-		F_SET(rep, REP_F_RECOVER);
 		rep->stat.st_master_changes++;
+		rep->stat.st_startup_complete = 0;
+		F_SET(rep, REP_F_NOARCHIVE | REP_F_RECOVER_VERIFY);
 	}
-	MUTEX_UNLOCK(dbenv, db_rep->mutexp);
+	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
 
-	if (!change)
-		return (0);
-
-	/*
-	 * If the master changed, we need to start the process of
-	 * figuring out what our last valid log record is.  However,
-	 * if both the master and we agree that the max LSN is 0,0,
-	 * then there is no recovery to be done.  If we are at 0 and
-	 * the master is not, then we just need to request all the log
-	 * records from the master.
-	 */
 	dblp = dbenv->lg_handle;
 	lp = dblp->reginfo.primary;
 	R_LOCK(dbenv, &dblp->reginfo);
-	last_lsn = lsn = lp->lsn;
-	if (last_lsn.offset > sizeof(LOGP))
-		last_lsn.offset -= lp->len;
+	lsn = lp->lsn;
 	R_UNLOCK(dbenv, &dblp->reginfo);
-	if (IS_INIT_LSN(lsn) || IS_ZERO_LSN(lsn)) {
-empty:		MUTEX_LOCK(dbenv, db_rep->mutexp);
-		F_CLR(rep, REP_F_RECOVER);
-		MUTEX_UNLOCK(dbenv, db_rep->mutexp);
-
-		if (IS_INIT_LSN(cntrl->lsn))
-			ret = 0;
-		else
-			ret = __rep_send_message(dbenv, rep->master_id,
-			    REP_ALL_REQ, &lsn, NULL, 0);
+	R_LOCK(dbenv, &mgr->reginfo);
+	ckp_lsn = region->last_ckp;
+	R_UNLOCK(dbenv, &mgr->reginfo);
 
-		if (ret == 0)
-			ret = DB_REP_NEWMASTER;
-		return (ret);
-	} else if (last_lsn.offset <= sizeof(LOGP)) {
+	if (!change) {
 		/*
-		 * We have just changed log files and need to set lastlsn
-		 * to the last record in the previous log files.
+		 * If there wasn't a change, we might still have some
+		 * catching up or verification to do.
 		 */
-		if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
-			return (ret);
-		memset(&dbt, 0, sizeof(dbt));
-		ret = logc->get(logc, &last_lsn, &dbt, DB_LAST);
-		if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0)
-			ret = t_ret;
-		if (ret == DB_NOTFOUND)
-			goto empty;
-		if (ret != 0)
-			return (ret);
-	}
-
-	R_LOCK(dbenv, &dblp->reginfo);
-	lp->verify_lsn = last_lsn;
-	R_UNLOCK(dbenv, &dblp->reginfo);
-	if ((ret = __rep_send_message(dbenv,
-	    eid, REP_VERIFY_REQ, &last_lsn, NULL, 0)) != 0)
-		return (ret);
-
-	return (DB_REP_NEWMASTER);
-}
-
-/*
- * __rep_lockpgno_init
- *	Create a dispatch table for acquiring locks on each log record.
- *
- * PUBLIC: int __rep_lockpgno_init __P((DB_ENV *,
- * PUBLIC:     int (***)(DB_ENV *, DBT *, DB_LSN *, db_recops, void *),
- * PUBLIC:     size_t *));
- */
-int
-__rep_lockpgno_init(dbenv, dtabp, dtabsizep)
-	DB_ENV *dbenv;
-	int (***dtabp)__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-	size_t *dtabsizep;
-{
-	int ret;
-
-	/* Initialize dispatch table. */
-	*dtabsizep = 0;
-	*dtabp = NULL;
-	if ((ret = __bam_init_getpgnos(dbenv, dtabp, dtabsizep)) != 0 ||
-	    (ret = __crdel_init_getpgnos(dbenv, dtabp, dtabsizep)) != 0 ||
-	    (ret = __db_init_getpgnos(dbenv, dtabp, dtabsizep)) != 0 ||
-	    (ret = __dbreg_init_getpgnos(dbenv, dtabp, dtabsizep)) != 0 ||
-	    (ret = __fop_init_getpgnos(dbenv, dtabp, dtabsizep)) != 0 ||
-	    (ret = __qam_init_getpgnos(dbenv, dtabp, dtabsizep)) != 0 ||
-	    (ret = __ham_init_getpgnos(dbenv, dtabp, dtabsizep)) != 0 ||
-	    (ret = __txn_init_getpgnos(dbenv, dtabp, dtabsizep)) != 0)
+		ret = 0;
+		MUTEX_LOCK(dbenv, db_rep->db_mutexp);
+		do_req = __rep_check_doreq(dbenv, rep);
+		if (F_ISSET(rep, REP_F_RECOVER_VERIFY)) {
+			lsn = lp->verify_lsn;
+			MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+			if (!IS_ZERO_LSN(lsn) && do_req)
+				(void)__rep_send_message(dbenv, eid,
+				    REP_VERIFY_REQ, &lsn, NULL, 0);
+		} else {
+			MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+			if (log_compare(&lsn, &cntrl->lsn) < 0 && do_req)
+				(void)__rep_send_message(dbenv,
+				    eid, REP_ALL_REQ, &lsn, NULL, 0);
+			MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+			F_CLR(rep, REP_F_NOARCHIVE);
+			MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+		}
 		return (ret);
-
-	return (0);
-}
-
-/*
- * __rep_unlockpages --
- *	Unlock the pages locked in __rep_lockpages.
- *
- * PUBLIC: int __rep_unlockpages __P((DB_ENV *, u_int32_t));
- */
-int
-__rep_unlockpages(dbenv, lid)
-	DB_ENV *dbenv;
-	u_int32_t lid;
-{
-	DB_LOCKREQ req, *lvp;
-
-	req.op = DB_LOCK_PUT_ALL;
-	return (dbenv->lock_vec(dbenv, lid, 0, &req, 1, &lvp));
-}
-
-/*
- * __rep_lockpages --
- *	Called to gather and lock pages in preparation for both
- *	single transaction apply as well as client synchronization
- *	with a new master.  A non-NULL key_lsn means that we're locking
- *	in order to apply a single log record during client recovery
- *	to the joint LSN.  A non-NULL max_lsn means that we are applying
- *	a transaction whose commit is at max_lsn.
- *
- * PUBLIC: int __rep_lockpages __P((DB_ENV *,
- * PUBLIC:     int (**)(DB_ENV *, DBT *, DB_LSN *, db_recops, void *),
- * PUBLIC:     size_t, DB_LSN *, DB_LSN *, TXN_RECS *, u_int32_t));
- */
-int
-__rep_lockpages(dbenv, dtab, dtabsize, key_lsn, max_lsn, recs, lid)
-	DB_ENV *dbenv;
-	int (**dtab)__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-	size_t dtabsize;
-	DB_LSN *key_lsn, *max_lsn;
-	TXN_RECS *recs;
-	u_int32_t lid;
-{
-	DBT data_dbt, lo;
-	DB_LOCK l;
-	DB_LOCKREQ *lvp;
-	DB_LOGC *logc;
-	DB_LSN tmp_lsn;
-	TXN_RECS tmp, *t;
-	db_pgno_t cur_pgno;
-	linfo_t locks;
-	int i, ret, t_ret, unique;
-	u_int32_t cur_fid;
-
-	/*
-	 * There are two phases:  First, we have to traverse backwards through
-	 * the log records gathering the list of all the pages accessed.  Once
-	 * we have this information we can acquire all the locks we need.
-	 */
-
-	/* Initialization */
-	memset(&locks, 0, sizeof(locks));
-	ret = 0;
-
-	t = recs != NULL ? recs : &tmp;
-	t->npages = t->nalloc = 0;
-	t->array = NULL;
-
-	/*
-	 * We've got to be in one mode or the other; else life will either
-	 * be excessively boring or overly exciting.
-	 */
-	DB_ASSERT(key_lsn != NULL || max_lsn != NULL);
-	DB_ASSERT(key_lsn == NULL || max_lsn == NULL);
+	}
 
 	/*
-	 * Phase 1:  Fill in the pgno array.
+	 * If the master changed, we need to start the process of
+	 * figuring out what our last valid log record is.  However,
+	 * if both the master and we agree that the max LSN is 0,0,
+	 * then there is no recovery to be done.  If we are at 0 and
+	 * the master is not, then we just need to request all the log
+	 * records from the master.
 	 */
-	memset(&data_dbt, 0, sizeof(data_dbt));
-	if (F_ISSET(dbenv, DB_ENV_THREAD))
-		F_SET(&data_dbt, DB_DBT_REALLOC);
-
-	/* Single transaction apply. */
-	if (max_lsn != NULL) {
-		DB_ASSERT(0); /* XXX */
-		/*
-		tmp_lsn = *max_lsn;
-		if ((ret = __rep_apply_thread(dbenv, dtab, dtabsize,
-		    &data_dbt, &tmp_lsn, t)) != 0)
-			goto err;
-			*/
-	}
-
-	/* In recovery. */
-	if (key_lsn != NULL) {
-		if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
-			goto err;
-		ret = logc->get(logc, key_lsn, &data_dbt, DB_SET);
-
-		/* Save lsn values, since dispatch functions can change them. */
-		tmp_lsn = *key_lsn;
-		ret = __db_dispatch(dbenv,
-		    dtab, dtabsize, &data_dbt, &tmp_lsn, DB_TXN_GETPGNOS, t);
-
-		if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0)
-			ret = t_ret;
-
+	if (IS_INIT_LSN(lsn) || IS_ZERO_LSN(lsn) || IS_ZERO_LSN(ckp_lsn)) {
 		/*
-		 * If ret == DB_DELETED, this record refers to a temporary
-		 * file and there's nothing to apply.
+		 * If we don't have a checkpoint, we still might have
+		 * some log records but we're discarding them to sync
+		 * up with the master from the start.  Therefore,
+		 * truncate our log.
 		 */
-		if (ret == DB_DELETED) {
-			ret = 0;
-			goto out;
-		} else if (ret != 0)
-			goto err;
-	}
-
-	if (t->npages == 0)
-		goto out;
-
-	/* Phase 2: Write lock all the pages. */
-
-	/* Sort the entries in the array by page number. */
-	qsort(t->array, t->npages, sizeof(LSN_PAGE), __rep_cmp_bypage);
-
-	/* Count the number of unique pages. */
-	cur_fid = DB_LOGFILEID_INVALID;
-	cur_pgno = PGNO_INVALID;
-	unique = 0;
-	for (i = 0; i < t->npages; i++) {
-		if (F_ISSET(&t->array[i], LSN_PAGE_NOLOCK))
-			continue;
-		if (t->array[i].pgdesc.pgno != cur_pgno ||
-		    t->array[i].fid != cur_fid) {
-			cur_pgno = t->array[i].pgdesc.pgno;
-			cur_fid = t->array[i].fid;
-			unique++;
+		if (IS_ZERO_LSN(ckp_lsn)) {
+			INIT_LSN(lsn);
+			(void)__log_vtruncate(dbenv, &lsn, &ckp_lsn, NULL);
+			infop = dbenv->reginfo;
+			renv = infop->primary;
+			(void)time(&renv->rep_timestamp);
 		}
-	}
-
-	if (unique == 0)
-		goto out;
 
-	/* Handle single lock case specially, else allocate space for locks. */
-	if (unique == 1) {
-		memset(&lo, 0, sizeof(lo));
-		lo.data = &t->array[0].pgdesc;
-		lo.size = sizeof(t->array[0].pgdesc);
-		ret = dbenv->lock_get(dbenv, lid, 0, &lo, DB_LOCK_WRITE, &l);
-		goto out2;
-	}
-
-	/* Multi-lock case. */
-	locks.n = unique;
-	if ((ret = __os_calloc(dbenv,
-	    unique, sizeof(DB_LOCKREQ), &locks.reqs)) != 0)
-		goto err;
-	if ((ret = __os_calloc(dbenv, unique, sizeof(DBT), &locks.objs)) != 0)
-		goto err;
-
-	unique = 0;
-	cur_fid = DB_LOGFILEID_INVALID;
-	cur_pgno = PGNO_INVALID;
-	for (i = 0; i < t->npages; i++) {
-		if (F_ISSET(&t->array[i], LSN_PAGE_NOLOCK))
-			continue;
-		if (t->array[i].pgdesc.pgno != cur_pgno ||
-		    t->array[i].fid != cur_fid) {
-			cur_pgno = t->array[i].pgdesc.pgno;
-			cur_fid = t->array[i].fid;
-			locks.reqs[unique].op = DB_LOCK_GET;
-			locks.reqs[unique].mode = DB_LOCK_WRITE;
-			locks.reqs[unique].obj = &locks.objs[unique];
-			locks.objs[unique].data = &t->array[i].pgdesc;
-			locks.objs[unique].size = sizeof(t->array[i].pgdesc);
-			unique++;
-		}
-	}
-
-	/* Finally, get the locks. */
-	if ((ret =
-	    dbenv->lock_vec(dbenv, lid, 0, locks.reqs, unique, &lvp)) != 0) {
 		/*
-		 * If we were unsuccessful, unlock any locks we acquired before
-		 * the error and return the original error value.
+		 * If we have no log, then we have no files to open
+		 * in recovery, but we've opened what we can, which
+		 * is none.  Mark DBREP_OPENFILES here.
 		 */
-		(void)__rep_unlockpages(dbenv, lid);
-	}
-
-err:
-out:	if (locks.objs != NULL)
-		__os_free(dbenv, locks.objs);
-	if (locks.reqs != NULL)
-		__os_free(dbenv, locks.reqs);
-
-	/*
-	 * Before we return, sort by LSN so that we apply records in the
-	 * right order.
-	 */
-	qsort(t->array, t->npages, sizeof(LSN_PAGE), __rep_cmp_bylsn);
+		MUTEX_LOCK(dbenv, db_rep->db_mutexp);
+		F_SET(db_rep, DBREP_OPENFILES);
+		MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+		F_CLR(rep, REP_F_NOARCHIVE | REP_F_RECOVER_MASK);
+		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+		MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+
+		if (!IS_INIT_LSN(cntrl->lsn))
+			(void)__rep_send_message(dbenv, rep->master_id,
+			    REP_ALL_REQ, &lsn, NULL, 0);
 
-out2:	if ((ret != 0 || recs == NULL) && t->nalloc != 0) {
-		__os_free(dbenv, t->array);
-		t->array = NULL;
-		t->npages = t->nalloc = 0;
+		return (DB_REP_NEWMASTER);
 	}
 
-	if (F_ISSET(&data_dbt, DB_DBT_REALLOC) && data_dbt.data != NULL)
-		__os_ufree(dbenv, data_dbt.data);
+	MUTEX_LOCK(dbenv, db_rep->db_mutexp);
+	lp->verify_lsn = ckp_lsn;
+	MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
+	(void)__rep_send_message(dbenv,
+	    eid, REP_VERIFY_REQ, &ckp_lsn, NULL, 0);
 
-	return (ret);
+	return (DB_REP_NEWMASTER);
 }
 
 /*
- * __rep_cmp_bypage and __rep_cmp_bylsn --
- *	Sort functions for qsort.  "bypage" sorts first by page numbers and
- *	then by the LSN.  "bylsn" sorts first by the LSN, then by page numbers.
+ * __rep_is_client
+ *	Used by other subsystems to figure out if this is a replication
+ * client site.
+ *
+ * PUBLIC: int __rep_is_client __P((DB_ENV *));
  */
-static int
-__rep_cmp_bypage(a, b)
-	const void *a, *b;
-{
-	LSN_PAGE *ap, *bp;
-
-	ap = (LSN_PAGE *)a;
-	bp = (LSN_PAGE *)b;
-
-	if (ap->fid < bp->fid)
-		return (-1);
-
-	if (ap->fid > bp->fid)
-		return (1);
-
-	if (ap->pgdesc.pgno < bp->pgdesc.pgno)
-		return (-1);
-
-	if (ap->pgdesc.pgno > bp->pgdesc.pgno)
-		return (1);
-
-	if (ap->lsn.file < bp->lsn.file)
-		return (-1);
-
-	if (ap->lsn.file > bp->lsn.file)
-		return (1);
-
-	if (ap->lsn.offset < bp->lsn.offset)
-		return (-1);
-
-	if (ap->lsn.offset > bp->lsn.offset)
-		return (1);
-
-	return (0);
-}
-
-static int
-__rep_cmp_bylsn(a, b)
-	const void *a, *b;
+int
+__rep_is_client(dbenv)
+	DB_ENV *dbenv;
 {
-	LSN_PAGE *ap, *bp;
-
-	ap = (LSN_PAGE *)a;
-	bp = (LSN_PAGE *)b;
-
-	if (ap->lsn.file < bp->lsn.file)
-		return (-1);
-
-	if (ap->lsn.file > bp->lsn.file)
-		return (1);
-
-	if (ap->lsn.offset < bp->lsn.offset)
-		return (-1);
-
-	if (ap->lsn.offset > bp->lsn.offset)
-		return (1);
-
-	if (ap->fid < bp->fid)
-		return (-1);
-
-	if (ap->fid > bp->fid)
-		return (1);
+	DB_REP *db_rep;
+	REP *rep;
 
-	if (ap->pgdesc.pgno < bp->pgdesc.pgno)
-		return (-1);
+	if (!REP_ON(dbenv))
+		return (0);
 
-	if (ap->pgdesc.pgno > bp->pgdesc.pgno)
-		return (1);
+	db_rep = dbenv->rep_handle;
+	rep = db_rep->region;
 
-	return (0);
+	/*
+	 * Don't just return F_ISSET since that converts unsigned
+	 * into signed.
+	 */
+	return (F_ISSET(rep, REP_F_CLIENT) ? 1 : 0);
 }
 
 /*
- * __rep_is_client
- *	Used by other subsystems to figure out if this is a replication
- * client sites.
+ * __rep_noarchive
+ *	Used by log_archive to determine if it is okay to remove
+ * log files.
  *
- * PUBLIC: int __rep_is_client __P((DB_ENV *));
+ * PUBLIC: int __rep_noarchive __P((DB_ENV *));
  */
 int
-__rep_is_client(dbenv)
+__rep_noarchive(dbenv)
 	DB_ENV *dbenv;
 {
 	DB_REP *db_rep;
+	REGENV *renv;
+	REGINFO *infop;
 	REP *rep;
-	int ret;
+	time_t timestamp;
 
-	if ((db_rep = dbenv->rep_handle) == NULL)
+	if (!REP_ON(dbenv))
 		return (0);
+	db_rep = dbenv->rep_handle;
 	rep = db_rep->region;
+	infop = dbenv->reginfo;
+	renv = infop->primary;
 
-	MUTEX_LOCK(dbenv, db_rep->mutexp);
-	ret = F_ISSET(rep, REP_F_UPGRADE | REP_F_LOGSONLY);
-	MUTEX_UNLOCK(dbenv, db_rep->mutexp);
-	return (ret);
+	if (F_ISSET(rep, REP_F_NOARCHIVE))
+		return (1);
+	if (F_ISSET(renv, DB_REGENV_REPLOCKED)) {
+		(void)time(&timestamp);
+		TIMESTAMP_CHECK(dbenv, timestamp, renv);
+		/*
+		 * Check if we're still locked out after checking
+		 * the timestamp.
+		 */
+		if (F_ISSET(renv, DB_REGENV_REPLOCKED))
+			return (EINVAL);
+	}
+	return (0);
 }
 
 /*
  * __rep_send_vote
  *	Send this site's vote for the election.
  *
- * PUBLIC: int __rep_send_vote __P((DB_ENV *, DB_LSN *, int, int, int));
+ * PUBLIC: void __rep_send_vote __P((DB_ENV *, DB_LSN *, int, int, int,
+ * PUBLIC:    u_int32_t, u_int32_t, int, u_int32_t));
  */
-int
-__rep_send_vote(dbenv, lsnp, nsites, pri, tiebreaker)
+void
+__rep_send_vote(dbenv, lsnp, nsites, nvotes, pri, tie, egen, eid, vtype)
 	DB_ENV *dbenv;
 	DB_LSN *lsnp;
-	int nsites, pri, tiebreaker;
+	int eid, nsites, nvotes, pri;
+	u_int32_t egen, tie, vtype;
 {
 	DBT vote_dbt;
 	REP_VOTE_INFO vi;
 
 	memset(&vi, 0, sizeof(vi));
 
+	vi.egen = egen;
 	vi.priority = pri;
 	vi.nsites = nsites;
-	vi.tiebreaker = tiebreaker;
+	vi.nvotes = nvotes;
+	vi.tiebreaker = tie;
 
 	memset(&vote_dbt, 0, sizeof(vote_dbt));
 	vote_dbt.data = &vi;
 	vote_dbt.size = sizeof(vi);
 
-	return (__rep_send_message(dbenv,
-	    DB_EID_BROADCAST, REP_VOTE1, lsnp, &vote_dbt, 0));
+	(void)__rep_send_message(dbenv, eid, vtype, lsnp, &vote_dbt, 0);
+}
+
+/*
+ * __rep_elect_done
+ *	Clear all election information for this site.  Assumes the
+ *	caller hold rep_mutex.
+ *
+ * PUBLIC: void __rep_elect_done __P((DB_ENV *, REP *));
+ */
+void
+__rep_elect_done(dbenv, rep)
+	DB_ENV *dbenv;
+	REP *rep;
+{
+	int inelect;
+#ifdef DIAGNOSTIC
+	DB_MSGBUF mb;
+#else
+	COMPQUIET(dbenv, NULL);
+#endif
+	inelect = IN_ELECTION_TALLY(rep);
+	F_CLR(rep, REP_F_EPHASE1 | REP_F_EPHASE2 | REP_F_TALLY);
+	rep->sites = 0;
+	rep->votes = 0;
+	if (inelect)
+		rep->egen++;
+	RPRINT(dbenv, rep, (dbenv, &mb,
+	    "Election done; egen %lu", (u_long)rep->egen));
 }
 
 /*
@@ -683,98 +488,273 @@ __rep_grow_sites(dbenv, nsites)
 	infop = dbenv->reginfo;
 	renv = infop->primary;
 	MUTEX_LOCK(dbenv, &renv->mutex);
-	if ((ret = __db_shalloc(infop->addr,
-	    sizeof(nalloc * sizeof(int)), sizeof(int), &tally)) == 0) {
+	/*
+	 * We allocate 2 tally regions, one for tallying VOTE1's and
+	 * one for VOTE2's.  Always grow them in tandem, because if we
+	 * get more VOTE1's we'll always expect more VOTE2's then too.
+	 */
+	if ((ret = __db_shalloc(infop,
+	    (size_t)nalloc * sizeof(REP_VTALLY), sizeof(REP_VTALLY),
+	    &tally)) == 0) {
 		if (rep->tally_off != INVALID_ROFF)
-			 __db_shalloc_free(infop->addr,
-			    R_ADDR(infop, rep->tally_off));
-		rep->asites = nalloc;
-		rep->nsites = nsites;
+			 __db_shalloc_free(
+			     infop, R_ADDR(infop, rep->tally_off));
 		rep->tally_off = R_OFFSET(infop, tally);
+		if ((ret = __db_shalloc(infop,
+		    (size_t)nalloc * sizeof(REP_VTALLY), sizeof(REP_VTALLY),
+		    &tally)) == 0) {
+			/* Success */
+			if (rep->v2tally_off != INVALID_ROFF)
+				 __db_shalloc_free(infop,
+				    R_ADDR(infop, rep->v2tally_off));
+			rep->v2tally_off = R_OFFSET(infop, tally);
+			rep->asites = nalloc;
+			rep->nsites = nsites;
+		} else {
+			/*
+			 * We were unable to allocate both.  So, we must
+			 * free the first one and reinitialize.  If
+			 * v2tally_off is valid, it is from an old
+			 * allocation and we are clearing it all out due
+			 * to the error.
+			 */
+			if (rep->v2tally_off != INVALID_ROFF)
+				 __db_shalloc_free(infop,
+				    R_ADDR(infop, rep->v2tally_off));
+			__db_shalloc_free(infop,
+			    R_ADDR(infop, rep->tally_off));
+			rep->v2tally_off = rep->tally_off = INVALID_ROFF;
+			rep->asites = 0;
+			rep->nsites = 0;
+		}
 	}
 	MUTEX_UNLOCK(dbenv, &renv->mutex);
 	return (ret);
 }
 
-#ifdef NOTYET
-static int __rep_send_file __P((DB_ENV *, DBT *, u_int32_t));
 /*
- * __rep_send_file --
- *	Send an entire file, one block at a time.
+ * __env_rep_enter --
+ *
+ *	Check if we are in the middle of replication initialization and/or
+ * recovery, and if so, disallow operations.  If operations are allowed,
+ * increment handle-counts, so that we do not start recovery while we
+ * are operating in the library.
+ *
+ * PUBLIC: void __env_rep_enter __P((DB_ENV *));
  */
-static int
-__rep_send_file(dbenv, rec, eid)
+void
+__env_rep_enter(dbenv)
 	DB_ENV *dbenv;
-	DBT *rec;
-	u_int32_t eid;
 {
+	DB_REP *db_rep;
+	REP *rep;
+	int cnt;
+
+        /* Check if locks have been globally turned off. */
+	if (F_ISSET(dbenv, DB_ENV_NOLOCKING))
+		return;
+
+	db_rep = dbenv->rep_handle;
+	rep = db_rep->region;
+
+	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+	for (cnt = 0; rep->in_recovery;) {
+		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+		__os_sleep(dbenv, 1, 0);
+		MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+		if (++cnt % 60 == 0)
+			__db_err(dbenv,
+    "DB_ENV handle waiting %d minutes for replication recovery to complete",
+			    cnt / 60);
+	}
+	rep->handle_cnt++;
+	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+}
+
+/*
+ * __env_db_rep_exit --
+ *
+ *	Decrement handle count upon routine exit.
+ *
+ * PUBLIC: void __env_db_rep_exit __P((DB_ENV *));
+ */
+void
+__env_db_rep_exit(dbenv)
+	DB_ENV *dbenv;
+{
+	DB_REP *db_rep;
+	REP *rep;
+
+        /* Check if locks have been globally turned off. */
+	if (F_ISSET(dbenv, DB_ENV_NOLOCKING))
+		return;
+
+	db_rep = dbenv->rep_handle;
+	rep = db_rep->region;
+
+	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+	rep->handle_cnt--;
+	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+}
+
+/*
+ * __db_rep_enter --
+ *	Called in replicated environments to keep track of in-use handles
+ * and prevent any concurrent operation during recovery.  If checkgen is
+ * non-zero, then we verify that the dbp has the same handle as the env.
+ * If return_now is non-zero, we'll return DB_DEADLOCK immediately, else we'll
+ * sleep before returning DB_DEADLOCK.
+ *
+ * PUBLIC: int __db_rep_enter __P((DB *, int, int, int));
+ */
+int
+__db_rep_enter(dbp, checkgen, checklock, return_now)
 	DB *dbp;
-	DB_LOCK lk;
-	DB_MPOOLFILE *mpf;
-	DBC *dbc;
-	DBT rec_dbt;
-	PAGE *pagep;
-	db_pgno_t last_pgno, pgno;
-	int ret, t_ret;
-
-	dbp = NULL;
-	dbc = NULL;
-	pagep = NULL;
-	mpf = NULL;
-	LOCK_INIT(lk);
-
-	if ((ret = db_create(&dbp, dbenv, 0)) != 0)
-		goto err;
-
-	if ((ret = dbp->open(dbp, rec->data, NULL, DB_UNKNOWN, 0, 0)) != 0)
-		goto err;
-
-	if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0)
-		goto err;
-	/*
-	 * Force last_pgno to some value that will let us read the meta-dat
-	 * page in the following loop.
-	 */
-	memset(&rec_dbt, 0, sizeof(rec_dbt));
-	last_pgno = 1;
-	for (pgno = 0; pgno <= last_pgno; pgno++) {
-		if ((ret = __db_lget(dbc, 0, pgno, DB_LOCK_READ, 0, &lk)) != 0)
-			goto err;
-
-		if ((ret = mpf->get(mpf, &pgno, 0, &pagep)) != 0)
-			goto err;
-
-		if (pgno == 0)
-			last_pgno = ((DBMETA *)pagep)->last_pgno;
-
-		rec_dbt.data = pagep;
-		rec_dbt.size = dbp->pgsize;
-		if ((ret = __rep_send_message(dbenv, eid,
-		    REP_FILE, NULL, &rec_dbt, pgno == last_pgno)) != 0)
-			goto err;
-		ret = mpf->put(mpf, pagep, 0);
-		pagep = NULL;
-		if (ret != 0)
-			goto err;
-		ret = __LPUT(dbc, lk);
-		LOCK_INIT(lk);
-		if (ret != 0)
-			goto err;
+	int checkgen, checklock, return_now;
+{
+	DB_ENV *dbenv;
+	DB_REP *db_rep;
+	REGENV *renv;
+	REGINFO *infop;
+	REP *rep;
+	time_t	timestamp;
+
+	dbenv = dbp->dbenv;
+	/* Check if locks have been globally turned off. */
+	if (F_ISSET(dbenv, DB_ENV_NOLOCKING))
+		return (0);
+
+	db_rep = dbenv->rep_handle;
+	rep = db_rep->region;
+	infop = dbenv->reginfo;
+	renv = infop->primary;
+
+	if (checklock && F_ISSET(renv, DB_REGENV_REPLOCKED)) {
+		(void)time(&timestamp);
+		TIMESTAMP_CHECK(dbenv, timestamp, renv);
+		/*
+		 * Check if we're still locked out after checking
+		 * the timestamp.
+		 */
+		if (F_ISSET(renv, DB_REGENV_REPLOCKED))
+			return (EINVAL);
+	}
+	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+	if (F_ISSET(rep, REP_F_READY)) {
+		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+		if (!return_now)
+			__os_sleep(dbenv, 5, 0);
+		return (DB_LOCK_DEADLOCK);
 	}
 
-err:	if (LOCK_ISSET(lk) && (t_ret = __LPUT(dbc, lk)) != 0 && ret == 0)
-		ret = t_ret;
-	if (dbc != NULL && (t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
-		ret = t_ret;
-	if (pagep != NULL && (t_ret = mpf->put(mpf, pagep, 0)) != 0 && ret == 0)
-		ret = t_ret;
-	if (dbp != NULL && (t_ret = dbp->close(dbp, 0)) != 0 && ret == 0)
-		ret = t_ret;
-	return (ret);
+	if (checkgen && dbp->timestamp != renv->rep_timestamp) {
+		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+		__db_err(dbenv, "%s %s",
+		    "replication recovery unrolled committed transactions;",
+		    "open DB and DBcursor handles must be closed");
+		return (DB_REP_HANDLE_DEAD);
+	}
+	rep->handle_cnt++;
+	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+
+	return (0);
 }
-#endif
 
-#if 0
+/*
+ * __op_rep_enter --
+ *
+ *	Check if we are in the middle of replication initialization and/or
+ * recovery, and if so, disallow new multi-step operations, such as
+ * transaction and memp gets.  If operations are allowed,
+ * increment the op_cnt, so that we do not start recovery while we have
+ * active operations.
+ *
+ * PUBLIC: void __op_rep_enter __P((DB_ENV *));
+ */
+void
+__op_rep_enter(dbenv)
+	DB_ENV *dbenv;
+{
+	DB_REP *db_rep;
+	REP *rep;
+	int cnt;
+
+        /* Check if locks have been globally turned off. */
+	if (F_ISSET(dbenv, DB_ENV_NOLOCKING))
+		return;
+
+	db_rep = dbenv->rep_handle;
+	rep = db_rep->region;
+
+	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+	for (cnt = 0; F_ISSET(rep, REP_F_READY);) {
+		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+		__os_sleep(dbenv, 5, 0);
+		MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+		if (++cnt % 60 == 0)
+			__db_err(dbenv,
+	"__op_rep_enter waiting %d minutes for op count to drain",
+			    cnt / 60);
+	}
+	rep->op_cnt++;
+	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+}
+
+/*
+ * __op_rep_exit --
+ *
+ *	Decrement op count upon transaction commit/abort/discard or
+ *	memp_fput.
+ *
+ * PUBLIC: void __op_rep_exit __P((DB_ENV *));
+ */
+void
+__op_rep_exit(dbenv)
+	DB_ENV *dbenv;
+{
+	DB_REP *db_rep;
+	REP *rep;
+
+        /* Check if locks have been globally turned off. */
+	if (F_ISSET(dbenv, DB_ENV_NOLOCKING))
+		return;
+
+	db_rep = dbenv->rep_handle;
+	rep = db_rep->region;
+
+	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+	DB_ASSERT(rep->op_cnt > 0);
+	rep->op_cnt--;
+	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+}
+
+/*
+ * __rep_get_gen --
+ *
+ *	Get the generation number from a replicated environment.
+ *
+ * PUBLIC: void __rep_get_gen __P((DB_ENV *, u_int32_t *));
+ */
+void
+__rep_get_gen(dbenv, genp)
+	DB_ENV *dbenv;
+	u_int32_t *genp;
+{
+	DB_REP *db_rep;
+	REP *rep;
+
+	db_rep = dbenv->rep_handle;
+	rep = db_rep->region;
+
+	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);
+	if (rep->recover_gen > rep->gen)
+		*genp = rep->recover_gen;
+	else
+		*genp = rep->gen;
+	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);
+}
+
+#ifdef DIAGNOSTIC
 /*
  * PUBLIC: void __rep_print_message __P((DB_ENV *, int, REP_CONTROL *, char *));
  */
@@ -785,7 +765,9 @@ __rep_print_message(dbenv, eid, rp, str)
 	REP_CONTROL *rp;
 	char *str;
 {
+	DB_MSGBUF mb;
 	char *type;
+
 	switch (rp->rectype) {
 	case REP_ALIVE:
 		type = "alive";
@@ -796,12 +778,15 @@ __rep_print_message(dbenv, eid, rp, str)
 	case REP_ALL_REQ:
 		type = "all_req";
 		break;
-	case REP_ELECT:
-		type = "elect";
+	case REP_DUPMASTER:
+		type = "dupmaster";
 		break;
 	case REP_FILE:
 		type = "file";
 		break;
+	case REP_FILE_FAIL:
+		type = "file_fail";
+		break;
 	case REP_FILE_REQ:
 		type = "file_req";
 		break;
@@ -832,14 +817,20 @@ __rep_print_message(dbenv, eid, rp, str)
 	case REP_PAGE:
 		type = "page";
 		break;
+	case REP_PAGE_FAIL:
+		type = "page_fail";
+		break;
+	case REP_PAGE_MORE:
+		type = "page_more";
+		break;
 	case REP_PAGE_REQ:
 		type = "page_req";
 		break;
-	case REP_PLIST:
-		type = "plist";
+	case REP_UPDATE:
+		type = "update";
 		break;
-	case REP_PLIST_REQ:
-		type = "plist_req";
+	case REP_UPDATE_REQ:
+		type = "update_req";
 		break;
 	case REP_VERIFY:
 		type = "verify";
@@ -860,8 +851,9 @@ __rep_print_message(dbenv, eid, rp, str)
 		type = "NOTYPE";
 		break;
 	}
-	printf("%s %s: gen = %d eid %d, type %s, LSN [%u][%u]\n",
-	    dbenv->db_home, str, rp->gen, eid, type, rp->lsn.file,
-	    rp->lsn.offset);
+	RPRINT(dbenv, ((REP *)((DB_REP *)(dbenv)->rep_handle)->region),
+	    (dbenv, &mb, "%s %s: gen = %lu eid %d, type %s, LSN [%lu][%lu]",
+	    dbenv->db_home, str, (u_long)rp->gen,
+	    eid, type, (u_long)rp->lsn.file, (u_long)rp->lsn.offset));
 }
 #endif
diff --git a/storage/bdb/rpc_client/client.c b/storage/bdb/rpc_client/client.c
index b6367e21449454fac37cd981042059fbfa471eb7..d96721ece607c660188cabaf537c812c520c91f7 100644
--- a/storage/bdb/rpc_client/client.c
+++ b/storage/bdb/rpc_client/client.c
@@ -1,17 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: client.c,v 1.60 2004/09/21 16:09:54 sue Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: client.c,v 1.51 2002/08/06 06:18:15 bostic Exp $";
-#endif /* not lint */
-
-#ifdef HAVE_RPC
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -23,15 +20,14 @@ static const char revid[] = "$Id: client.c,v 1.51 2002/08/06 06:18:15 bostic Exp
 #include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 #endif
 
+#include "db_server.h"
+
 #include "db_int.h"
 #include "dbinc/db_page.h"
 #include "dbinc/db_am.h"
 #include "dbinc/txn.h"
-
-#include "dbinc_auto/db_server.h"
 #include "dbinc_auto/rpc_client_ext.h"
 
 static int __dbcl_c_destroy __P((DBC *));
@@ -91,6 +87,30 @@ __dbcl_envrpcserver(dbenv, clnt, host, tsec, ssec, flags)
 	return (__dbcl_env_create(dbenv, ssec));
 }
 
+/*
+ * __dbcl_env_close_wrap --
+ *	Wrapper function for DB_ENV->close function for clients.
+ *	We need a wrapper function to deal with the case where we
+ *	either don't call dbenv->open or close gets an error.
+ *	We need to release the handle no matter what.
+ *
+ * PUBLIC: int __dbcl_env_close_wrap
+ * PUBLIC:     __P((DB_ENV *, u_int32_t));
+ */
+int
+__dbcl_env_close_wrap(dbenv, flags)
+	DB_ENV * dbenv;
+	u_int32_t flags;
+{
+	int ret, t_ret;
+
+	ret = __dbcl_env_close(dbenv, flags);
+	t_ret = __dbcl_refresh(dbenv);
+	if (ret == 0 && t_ret != 0)
+		ret = t_ret;
+	return (ret);
+}
+
 /*
  * __dbcl_env_open_wrap --
  *	Wrapper function for DB_ENV->open function for clients.
@@ -202,11 +222,17 @@ __dbcl_retcopy(dbenv, dbt, data, len, memp, memsize)
 
 	/*
 	 * The RPC server handles DB_DBT_PARTIAL, so we mask it out here to
-	 * avoid the handling of partials in __db_retcopy.
+	 * avoid the handling of partials in __db_retcopy.  Check first whether
+	 * the data has actually changed, so we don't try to copy over
+	 * read-only keys, which the RPC server always returns regardless.
 	 */
 	orig_flags = dbt->flags;
 	F_CLR(dbt, DB_DBT_PARTIAL);
-	ret = __db_retcopy(dbenv, dbt, data, len, memp, memsize);
+	if (dbt->data != NULL && dbt->size == len &&
+	    memcmp(dbt->data, data, len) == 0)
+		ret = 0;
+	else
+		ret = __db_retcopy(dbenv, dbt, data, len, memp, memsize);
 	dbt->flags = orig_flags;
 	return (ret);
 }
@@ -215,7 +241,7 @@ __dbcl_retcopy(dbenv, dbt, data, len, memp, memsize)
  * __dbcl_txn_close --
  *	Clean up an environment's transactions.
  */
-int
+static int
 __dbcl_txn_close(dbenv)
 	DB_ENV *dbenv;
 {
@@ -377,11 +403,11 @@ __dbcl_c_refresh(dbc)
  * __dbcl_c_setup --
  *	Allocate a cursor.
  *
- * PUBLIC: int __dbcl_c_setup __P((long, DB *, DBC **));
+ * PUBLIC: int __dbcl_c_setup __P((u_int, DB *, DBC **));
  */
 int
 __dbcl_c_setup(cl_id, dbp, dbcp)
-	long cl_id;
+	u_int cl_id;
 	DB *dbp;
 	DBC **dbcp;
 {
@@ -461,4 +487,3 @@ __dbcl_dbclose_common(dbp)
 	__os_free(NULL, dbp);
 	return (ret);
 }
-#endif /* HAVE_RPC */
diff --git a/storage/bdb/rpc_client/gen_client.c b/storage/bdb/rpc_client/gen_client.c
new file mode 100644
index 0000000000000000000000000000000000000000..72a3f7471a4d59adca69035af8a5b8f06a964712
--- /dev/null
+++ b/storage/bdb/rpc_client/gen_client.c
@@ -0,0 +1,4656 @@
+/* Do not edit: automatically built by gen_rpc.awk. */
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <rpc/rpc.h>
+
+#include <string.h>
+#endif
+
+#include "db_server.h"
+
+#include "db_int.h"
+#include "dbinc/txn.h"
+#include "dbinc_auto/rpc_client_ext.h"
+
+static int __dbcl_noserver __P((DB_ENV *));
+
+static int
+__dbcl_noserver(dbenv)
+	DB_ENV *dbenv;
+{
+	__db_err(dbenv, "No server environment");
+	return (DB_NOSERVER);
+}
+
+static int __dbcl_rpc_illegal __P((DB_ENV *, char *));
+
+static int
+__dbcl_rpc_illegal(dbenv, name)
+	DB_ENV *dbenv;
+	char *name;
+{
+	__db_err(dbenv, "%s method unsupported in RPC environments", name);
+	return (DB_OPNOTSUP);
+}
+
+/*
+ * PUBLIC: int __dbcl_env_alloc __P((DB_ENV *, void *(*)(size_t),
+ * PUBLIC:      void *(*)(void *, size_t), void (*)(void *)));
+ */
+int
+__dbcl_env_alloc(dbenv, func0, func1, func2)
+	DB_ENV * dbenv;
+	void *(*func0) __P((size_t));
+	void *(*func1) __P((void *, size_t));
+	void (*func2) __P((void *));
+{
+	COMPQUIET(func0, 0);
+	COMPQUIET(func1, 0);
+	COMPQUIET(func2, 0);
+	return (__dbcl_rpc_illegal(dbenv, "env_alloc"));
+}
+
+/*
+ * PUBLIC: int __dbcl_set_app_dispatch __P((DB_ENV *, int (*)(DB_ENV *, DBT *,
+ * PUBLIC:      DB_LSN *, db_recops)));
+ */
+int
+__dbcl_set_app_dispatch(dbenv, func0)
+	DB_ENV * dbenv;
+	int (*func0) __P((DB_ENV *, DBT *, DB_LSN *, db_recops));
+{
+	COMPQUIET(func0, 0);
+	return (__dbcl_rpc_illegal(dbenv, "set_app_dispatch"));
+}
+
+/*
+ * PUBLIC: int __dbcl_env_get_cachesize __P((DB_ENV *, u_int32_t *,
+ * PUBLIC:      u_int32_t *, int *));
+ */
+int
+__dbcl_env_get_cachesize(dbenv, gbytesp, bytesp, ncachep)
+	DB_ENV * dbenv;
+	u_int32_t * gbytesp;
+	u_int32_t * bytesp;
+	int * ncachep;
+{
+	CLIENT *cl;
+	__env_get_cachesize_msg msg;
+	__env_get_cachesize_reply *replyp = NULL;
+	int ret;
+
+	ret = 0;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(dbenv));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbenv == NULL)
+		msg.dbenvcl_id = 0;
+	else
+		msg.dbenvcl_id = dbenv->cl_id;
+
+	replyp = __db_env_get_cachesize_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+	if (gbytesp != NULL)
+		*gbytesp = replyp->gbytes;
+	if (bytesp != NULL)
+		*bytesp = replyp->bytes;
+	if (ncachep != NULL)
+		*ncachep = replyp->ncache;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___env_get_cachesize_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_env_cachesize __P((DB_ENV *, u_int32_t, u_int32_t, int));
+ */
+int
+__dbcl_env_cachesize(dbenv, gbytes, bytes, ncache)
+	DB_ENV * dbenv;
+	u_int32_t gbytes;
+	u_int32_t bytes;
+	int ncache;
+{
+	CLIENT *cl;
+	__env_cachesize_msg msg;
+	__env_cachesize_reply *replyp = NULL;
+	int ret;
+
+	ret = 0;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(dbenv));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbenv == NULL)
+		msg.dbenvcl_id = 0;
+	else
+		msg.dbenvcl_id = dbenv->cl_id;
+	msg.gbytes = gbytes;
+	msg.bytes = bytes;
+	msg.ncache = ncache;
+
+	replyp = __db_env_cachesize_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___env_cachesize_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_env_close __P((DB_ENV *, u_int32_t));
+ */
+int
+__dbcl_env_close(dbenv, flags)
+	DB_ENV * dbenv;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__env_close_msg msg;
+	__env_close_reply *replyp = NULL;
+	int ret;
+
+	ret = 0;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(dbenv));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbenv == NULL)
+		msg.dbenvcl_id = 0;
+	else
+		msg.dbenvcl_id = dbenv->cl_id;
+	msg.flags = flags;
+
+	replyp = __db_env_close_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___env_close_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_env_create __P((DB_ENV *, long));
+ */
+int
+__dbcl_env_create(dbenv, timeout)
+	DB_ENV * dbenv;
+	long timeout;
+{
+	CLIENT *cl;
+	__env_create_msg msg;
+	__env_create_reply *replyp = NULL;
+	int ret;
+
+	ret = 0;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(dbenv));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	msg.timeout = timeout;
+
+	replyp = __db_env_create_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = __dbcl_env_create_ret(dbenv, timeout, replyp);
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___env_create_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_get_data_dirs __P((DB_ENV *, const char ***));
+ */
+int
+__dbcl_get_data_dirs(dbenv, dirpp)
+	DB_ENV * dbenv;
+	const char *** dirpp;
+{
+	COMPQUIET(dirpp, NULL);
+	return (__dbcl_rpc_illegal(dbenv, "get_data_dirs"));
+}
+
+/*
+ * PUBLIC: int __dbcl_set_data_dir __P((DB_ENV *, const char *));
+ */
+int
+__dbcl_set_data_dir(dbenv, dir)
+	DB_ENV * dbenv;
+	const char * dir;
+{
+	COMPQUIET(dir, NULL);
+	return (__dbcl_rpc_illegal(dbenv, "set_data_dir"));
+}
+
+/*
+ * PUBLIC: int __dbcl_env_dbremove __P((DB_ENV *, DB_TXN *, const char *,
+ * PUBLIC:      const char *, u_int32_t));
+ */
+int
+__dbcl_env_dbremove(dbenv, txnp, name, subdb, flags)
+	DB_ENV * dbenv;
+	DB_TXN * txnp;
+	const char * name;
+	const char * subdb;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__env_dbremove_msg msg;
+	__env_dbremove_reply *replyp = NULL;
+	int ret;
+
+	ret = 0;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(dbenv));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbenv == NULL)
+		msg.dbenvcl_id = 0;
+	else
+		msg.dbenvcl_id = dbenv->cl_id;
+	if (txnp == NULL)
+		msg.txnpcl_id = 0;
+	else
+		msg.txnpcl_id = txnp->txnid;
+	if (name == NULL)
+		msg.name = "";
+	else
+		msg.name = (char *)name;
+	if (subdb == NULL)
+		msg.subdb = "";
+	else
+		msg.subdb = (char *)subdb;
+	msg.flags = flags;
+
+	replyp = __db_env_dbremove_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___env_dbremove_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_env_dbrename __P((DB_ENV *, DB_TXN *, const char *,
+ * PUBLIC:      const char *, const char *, u_int32_t));
+ */
+int
+__dbcl_env_dbrename(dbenv, txnp, name, subdb, newname, flags)
+	DB_ENV * dbenv;
+	DB_TXN * txnp;
+	const char * name;
+	const char * subdb;
+	const char * newname;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__env_dbrename_msg msg;
+	__env_dbrename_reply *replyp = NULL;
+	int ret;
+
+	ret = 0;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(dbenv));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbenv == NULL)
+		msg.dbenvcl_id = 0;
+	else
+		msg.dbenvcl_id = dbenv->cl_id;
+	if (txnp == NULL)
+		msg.txnpcl_id = 0;
+	else
+		msg.txnpcl_id = txnp->txnid;
+	if (name == NULL)
+		msg.name = "";
+	else
+		msg.name = (char *)name;
+	if (subdb == NULL)
+		msg.subdb = "";
+	else
+		msg.subdb = (char *)subdb;
+	if (newname == NULL)
+		msg.newname = "";
+	else
+		msg.newname = (char *)newname;
+	msg.flags = flags;
+
+	replyp = __db_env_dbrename_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___env_dbrename_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_env_get_encrypt_flags __P((DB_ENV *, u_int32_t *));
+ */
+int
+__dbcl_env_get_encrypt_flags(dbenv, flagsp)
+	DB_ENV * dbenv;
+	u_int32_t * flagsp;
+{
+	CLIENT *cl;
+	__env_get_encrypt_flags_msg msg;
+	__env_get_encrypt_flags_reply *replyp = NULL;
+	int ret;
+
+	ret = 0;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(dbenv));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbenv == NULL)
+		msg.dbenvcl_id = 0;
+	else
+		msg.dbenvcl_id = dbenv->cl_id;
+
+	replyp = __db_env_get_encrypt_flags_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+	if (flagsp != NULL)
+		*flagsp = replyp->flags;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___env_get_encrypt_flags_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_env_encrypt __P((DB_ENV *, const char *, u_int32_t));
+ */
+int
+__dbcl_env_encrypt(dbenv, passwd, flags)
+	DB_ENV * dbenv;
+	const char * passwd;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__env_encrypt_msg msg;
+	__env_encrypt_reply *replyp = NULL;
+	int ret;
+
+	ret = 0;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(dbenv));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbenv == NULL)
+		msg.dbenvcl_id = 0;
+	else
+		msg.dbenvcl_id = dbenv->cl_id;
+	if (passwd == NULL)
+		msg.passwd = "";
+	else
+		msg.passwd = (char *)passwd;
+	msg.flags = flags;
+
+	replyp = __db_env_encrypt_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___env_encrypt_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_env_set_feedback __P((DB_ENV *, void (*)(DB_ENV *, int,
+ * PUBLIC:      int)));
+ */
+int
+__dbcl_env_set_feedback(dbenv, func0)
+	DB_ENV * dbenv;
+	void (*func0) __P((DB_ENV *, int, int));
+{
+	COMPQUIET(func0, 0);
+	return (__dbcl_rpc_illegal(dbenv, "env_set_feedback"));
+}
+
+/*
+ * PUBLIC: int __dbcl_env_get_flags __P((DB_ENV *, u_int32_t *));
+ */
+int
+__dbcl_env_get_flags(dbenv, flagsp)
+	DB_ENV * dbenv;
+	u_int32_t * flagsp;
+{
+	CLIENT *cl;
+	__env_get_flags_msg msg;
+	__env_get_flags_reply *replyp = NULL;
+	int ret;
+
+	ret = 0;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(dbenv));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbenv == NULL)
+		msg.dbenvcl_id = 0;
+	else
+		msg.dbenvcl_id = dbenv->cl_id;
+
+	replyp = __db_env_get_flags_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+	if (flagsp != NULL)
+		*flagsp = replyp->flags;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___env_get_flags_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_env_flags __P((DB_ENV *, u_int32_t, int));
+ */
+int
+__dbcl_env_flags(dbenv, flags, onoff)
+	DB_ENV * dbenv;
+	u_int32_t flags;
+	int onoff;
+{
+	CLIENT *cl;
+	__env_flags_msg msg;
+	__env_flags_reply *replyp = NULL;
+	int ret;
+
+	ret = 0;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(dbenv));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbenv == NULL)
+		msg.dbenvcl_id = 0;
+	else
+		msg.dbenvcl_id = dbenv->cl_id;
+	msg.flags = flags;
+	msg.onoff = onoff;
+
+	replyp = __db_env_flags_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___env_flags_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_get_lg_bsize __P((DB_ENV *, u_int32_t *));
+ */
+int
+__dbcl_get_lg_bsize(dbenv, bsizep)
+	DB_ENV * dbenv;
+	u_int32_t * bsizep;
+{
+	COMPQUIET(bsizep, 0);
+	return (__dbcl_rpc_illegal(dbenv, "get_lg_bsize"));
+}
+
+/*
+ * PUBLIC: int __dbcl_set_lg_bsize __P((DB_ENV *, u_int32_t));
+ */
+int
+__dbcl_set_lg_bsize(dbenv, bsize)
+	DB_ENV * dbenv;
+	u_int32_t bsize;
+{
+	COMPQUIET(bsize, 0);
+	return (__dbcl_rpc_illegal(dbenv, "set_lg_bsize"));
+}
+
+/*
+ * PUBLIC: int __dbcl_get_lg_dir __P((DB_ENV *, const char * *));
+ */
+int
+__dbcl_get_lg_dir(dbenv, dirp)
+	DB_ENV * dbenv;
+	const char * * dirp;
+{
+	COMPQUIET(dirp, 0);
+	return (__dbcl_rpc_illegal(dbenv, "get_lg_dir"));
+}
+
+/*
+ * PUBLIC: int __dbcl_set_lg_dir __P((DB_ENV *, const char *));
+ */
+int
+__dbcl_set_lg_dir(dbenv, dir)
+	DB_ENV * dbenv;
+	const char * dir;
+{
+	COMPQUIET(dir, NULL);
+	return (__dbcl_rpc_illegal(dbenv, "set_lg_dir"));
+}
+
+/*
+ * PUBLIC: int __dbcl_get_lg_max __P((DB_ENV *, u_int32_t *));
+ */
+int
+__dbcl_get_lg_max(dbenv, maxp)
+	DB_ENV * dbenv;
+	u_int32_t * maxp;
+{
+	COMPQUIET(maxp, 0);
+	return (__dbcl_rpc_illegal(dbenv, "get_lg_max"));
+}
+
+/*
+ * PUBLIC: int __dbcl_set_lg_max __P((DB_ENV *, u_int32_t));
+ */
+int
+__dbcl_set_lg_max(dbenv, max)
+	DB_ENV * dbenv;
+	u_int32_t max;
+{
+	COMPQUIET(max, 0);
+	return (__dbcl_rpc_illegal(dbenv, "set_lg_max"));
+}
+
+/*
+ * PUBLIC: int __dbcl_get_lg_regionmax __P((DB_ENV *, u_int32_t *));
+ */
+int
+__dbcl_get_lg_regionmax(dbenv, maxp)
+	DB_ENV * dbenv;
+	u_int32_t * maxp;
+{
+	COMPQUIET(maxp, 0);
+	return (__dbcl_rpc_illegal(dbenv, "get_lg_regionmax"));
+}
+
+/*
+ * PUBLIC: int __dbcl_set_lg_regionmax __P((DB_ENV *, u_int32_t));
+ */
+int
+__dbcl_set_lg_regionmax(dbenv, max)
+	DB_ENV * dbenv;
+	u_int32_t max;
+{
+	COMPQUIET(max, 0);
+	return (__dbcl_rpc_illegal(dbenv, "set_lg_regionmax"));
+}
+
+/*
+ * PUBLIC: int __dbcl_get_lk_conflicts __P((DB_ENV *, const u_int8_t **,
+ * PUBLIC:      int *));
+ */
+int
+__dbcl_get_lk_conflicts(dbenv, conflicts, modes)
+	DB_ENV * dbenv;
+	const u_int8_t ** conflicts;
+	int * modes;
+{
+	COMPQUIET(conflicts, 0);
+	COMPQUIET(modes, 0);
+	return (__dbcl_rpc_illegal(dbenv, "get_lk_conflicts"));
+}
+
+/*
+ * PUBLIC: int __dbcl_set_lk_conflict __P((DB_ENV *, u_int8_t *, int));
+ */
+int
+__dbcl_set_lk_conflict(dbenv, conflicts, modes)
+	DB_ENV * dbenv;
+	u_int8_t * conflicts;
+	int modes;
+{
+	COMPQUIET(conflicts, 0);
+	COMPQUIET(modes, 0);
+	return (__dbcl_rpc_illegal(dbenv, "set_lk_conflict"));
+}
+
+/*
+ * PUBLIC: int __dbcl_get_lk_detect __P((DB_ENV *, u_int32_t *));
+ */
+int
+__dbcl_get_lk_detect(dbenv, detectp)
+	DB_ENV * dbenv;
+	u_int32_t * detectp;
+{
+	COMPQUIET(detectp, 0);
+	return (__dbcl_rpc_illegal(dbenv, "get_lk_detect"));
+}
+
+/*
+ * PUBLIC: int __dbcl_set_lk_detect __P((DB_ENV *, u_int32_t));
+ */
+int
+__dbcl_set_lk_detect(dbenv, detect)
+	DB_ENV * dbenv;
+	u_int32_t detect;
+{
+	COMPQUIET(detect, 0);
+	return (__dbcl_rpc_illegal(dbenv, "set_lk_detect"));
+}
+
+/*
+ * PUBLIC: int __dbcl_set_lk_max __P((DB_ENV *, u_int32_t));
+ */
+int
+__dbcl_set_lk_max(dbenv, max)
+	DB_ENV * dbenv;
+	u_int32_t max;
+{
+	COMPQUIET(max, 0);
+	return (__dbcl_rpc_illegal(dbenv, "set_lk_max"));
+}
+
+/*
+ * PUBLIC: int __dbcl_get_lk_max_locks __P((DB_ENV *, u_int32_t *));
+ */
+int
+__dbcl_get_lk_max_locks(dbenv, maxp)
+	DB_ENV * dbenv;
+	u_int32_t * maxp;
+{
+	COMPQUIET(maxp, 0);
+	return (__dbcl_rpc_illegal(dbenv, "get_lk_max_locks"));
+}
+
+/*
+ * PUBLIC: int __dbcl_set_lk_max_locks __P((DB_ENV *, u_int32_t));
+ */
+int
+__dbcl_set_lk_max_locks(dbenv, max)
+	DB_ENV * dbenv;
+	u_int32_t max;
+{
+	COMPQUIET(max, 0);
+	return (__dbcl_rpc_illegal(dbenv, "set_lk_max_locks"));
+}
+
+/*
+ * PUBLIC: int __dbcl_get_lk_max_lockers __P((DB_ENV *, u_int32_t *));
+ */
+int
+__dbcl_get_lk_max_lockers(dbenv, maxp)
+	DB_ENV * dbenv;
+	u_int32_t * maxp;
+{
+	COMPQUIET(maxp, 0);
+	return (__dbcl_rpc_illegal(dbenv, "get_lk_max_lockers"));
+}
+
+/*
+ * PUBLIC: int __dbcl_set_lk_max_lockers __P((DB_ENV *, u_int32_t));
+ */
+int
+__dbcl_set_lk_max_lockers(dbenv, max)
+	DB_ENV * dbenv;
+	u_int32_t max;
+{
+	COMPQUIET(max, 0);
+	return (__dbcl_rpc_illegal(dbenv, "set_lk_max_lockers"));
+}
+
+/*
+ * PUBLIC: int __dbcl_get_lk_max_objects __P((DB_ENV *, u_int32_t *));
+ */
+int
+__dbcl_get_lk_max_objects(dbenv, maxp)
+	DB_ENV * dbenv;
+	u_int32_t * maxp;
+{
+	COMPQUIET(maxp, 0);
+	return (__dbcl_rpc_illegal(dbenv, "get_lk_max_objects"));
+}
+
+/*
+ * PUBLIC: int __dbcl_set_lk_max_objects __P((DB_ENV *, u_int32_t));
+ */
+int
+__dbcl_set_lk_max_objects(dbenv, max)
+	DB_ENV * dbenv;
+	u_int32_t max;
+{
+	COMPQUIET(max, 0);
+	return (__dbcl_rpc_illegal(dbenv, "set_lk_max_objects"));
+}
+
+/*
+ * PUBLIC: int __dbcl_get_mp_max_openfd __P((DB_ENV *, int *));
+ */
+int
+__dbcl_get_mp_max_openfd(dbenv, nopenp)
+	DB_ENV * dbenv;
+	int * nopenp;
+{
+	COMPQUIET(nopenp, 0);
+	return (__dbcl_rpc_illegal(dbenv, "get_mp_max_openfd"));
+}
+
+/*
+ * PUBLIC: int __dbcl_set_mp_max_openfd __P((DB_ENV *, int));
+ */
+int
+__dbcl_set_mp_max_openfd(dbenv, nopen)
+	DB_ENV * dbenv;
+	int nopen;
+{
+	COMPQUIET(nopen, 0);
+	return (__dbcl_rpc_illegal(dbenv, "set_mp_max_openfd"));
+}
+
+/*
+ * PUBLIC: int __dbcl_get_mp_max_write __P((DB_ENV *, int *, int *));
+ */
+int
+__dbcl_get_mp_max_write(dbenv, nwritep, nsleepp)
+	DB_ENV * dbenv;
+	int * nwritep;
+	int * nsleepp;
+{
+	COMPQUIET(nwritep, 0);
+	COMPQUIET(nsleepp, 0);
+	return (__dbcl_rpc_illegal(dbenv, "get_mp_max_write"));
+}
+
+/*
+ * PUBLIC: int __dbcl_set_mp_max_write __P((DB_ENV *, int, int));
+ */
+int
+__dbcl_set_mp_max_write(dbenv, nwrite, nsleep)
+	DB_ENV * dbenv;
+	int nwrite;
+	int nsleep;
+{
+	COMPQUIET(nwrite, 0);
+	COMPQUIET(nsleep, 0);
+	return (__dbcl_rpc_illegal(dbenv, "set_mp_max_write"));
+}
+
+/*
+ * PUBLIC: int __dbcl_get_mp_mmapsize __P((DB_ENV *, size_t *));
+ */
+int
+__dbcl_get_mp_mmapsize(dbenv, mmapsizep)
+	DB_ENV * dbenv;
+	size_t * mmapsizep;
+{
+	COMPQUIET(mmapsizep, 0);
+	return (__dbcl_rpc_illegal(dbenv, "get_mp_mmapsize"));
+}
+
+/*
+ * PUBLIC: int __dbcl_set_mp_mmapsize __P((DB_ENV *, size_t));
+ */
+int
+__dbcl_set_mp_mmapsize(dbenv, mmapsize)
+	DB_ENV * dbenv;
+	size_t mmapsize;
+{
+	COMPQUIET(mmapsize, 0);
+	return (__dbcl_rpc_illegal(dbenv, "set_mp_mmapsize"));
+}
+
+/*
+ * PUBLIC: int __dbcl_env_get_home __P((DB_ENV *, const char * *));
+ */
+int
+__dbcl_env_get_home(dbenv, homep)
+	DB_ENV * dbenv;
+	const char * * homep;
+{
+	CLIENT *cl;
+	__env_get_home_msg msg;
+	__env_get_home_reply *replyp = NULL;
+	int ret;
+
+	ret = 0;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(dbenv));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbenv == NULL)
+		msg.dbenvcl_id = 0;
+	else
+		msg.dbenvcl_id = dbenv->cl_id;
+
+	replyp = __db_env_get_home_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+	if (homep != NULL)
+		*homep = replyp->home;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___env_get_home_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_env_get_open_flags __P((DB_ENV *, u_int32_t *));
+ */
+int
+__dbcl_env_get_open_flags(dbenv, flagsp)
+	DB_ENV * dbenv;
+	u_int32_t * flagsp;
+{
+	CLIENT *cl;
+	__env_get_open_flags_msg msg;
+	__env_get_open_flags_reply *replyp = NULL;
+	int ret;
+
+	ret = 0;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(dbenv));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbenv == NULL)
+		msg.dbenvcl_id = 0;
+	else
+		msg.dbenvcl_id = dbenv->cl_id;
+
+	replyp = __db_env_get_open_flags_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+	if (flagsp != NULL)
+		*flagsp = replyp->flags;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___env_get_open_flags_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_env_open __P((DB_ENV *, const char *, u_int32_t, int));
+ */
+int
+__dbcl_env_open(dbenv, home, flags, mode)
+	DB_ENV * dbenv;
+	const char * home;
+	u_int32_t flags;
+	int mode;
+{
+	CLIENT *cl;
+	__env_open_msg msg;
+	__env_open_reply *replyp = NULL;
+	int ret;
+
+	ret = 0;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(dbenv));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbenv == NULL)
+		msg.dbenvcl_id = 0;
+	else
+		msg.dbenvcl_id = dbenv->cl_id;
+	if (home == NULL)
+		msg.home = "";
+	else
+		msg.home = (char *)home;
+	msg.flags = flags;
+	msg.mode = mode;
+
+	replyp = __db_env_open_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = __dbcl_env_open_ret(dbenv, home, flags, mode, replyp);
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___env_open_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_env_paniccall __P((DB_ENV *, void (*)(DB_ENV *, int)));
+ */
+int
+__dbcl_env_paniccall(dbenv, func0)
+	DB_ENV * dbenv;
+	void (*func0) __P((DB_ENV *, int));
+{
+	COMPQUIET(func0, 0);
+	return (__dbcl_rpc_illegal(dbenv, "env_paniccall"));
+}
+
+/*
+ * PUBLIC: int __dbcl_env_remove __P((DB_ENV *, const char *, u_int32_t));
+ */
+int
+__dbcl_env_remove(dbenv, home, flags)
+	DB_ENV * dbenv;
+	const char * home;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__env_remove_msg msg;
+	__env_remove_reply *replyp = NULL;
+	int ret;
+
+	ret = 0;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(dbenv));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbenv == NULL)
+		msg.dbenvcl_id = 0;
+	else
+		msg.dbenvcl_id = dbenv->cl_id;
+	if (home == NULL)
+		msg.home = "";
+	else
+		msg.home = (char *)home;
+	msg.flags = flags;
+
+	replyp = __db_env_remove_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = __dbcl_env_remove_ret(dbenv, home, flags, replyp);
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___env_remove_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_get_shm_key __P((DB_ENV *, long *));
+ */
+int
+__dbcl_get_shm_key(dbenv, shm_keyp)
+	DB_ENV * dbenv;
+	long * shm_keyp;
+{
+	COMPQUIET(shm_keyp, 0);
+	return (__dbcl_rpc_illegal(dbenv, "get_shm_key"));
+}
+
+/*
+ * PUBLIC: int __dbcl_set_shm_key __P((DB_ENV *, long));
+ */
+int
+__dbcl_set_shm_key(dbenv, shm_key)
+	DB_ENV * dbenv;
+	long shm_key;
+{
+	COMPQUIET(shm_key, 0);
+	return (__dbcl_rpc_illegal(dbenv, "set_shm_key"));
+}
+
+/*
+ * PUBLIC: int __dbcl_get_tas_spins __P((DB_ENV *, u_int32_t *));
+ */
+int
+__dbcl_get_tas_spins(dbenv, tas_spinsp)
+	DB_ENV * dbenv;
+	u_int32_t * tas_spinsp;
+{
+	COMPQUIET(tas_spinsp, 0);
+	return (__dbcl_rpc_illegal(dbenv, "get_tas_spins"));
+}
+
+/*
+ * PUBLIC: int __dbcl_set_tas_spins __P((DB_ENV *, u_int32_t));
+ */
+int
+__dbcl_set_tas_spins(dbenv, tas_spins)
+	DB_ENV * dbenv;
+	u_int32_t tas_spins;
+{
+	COMPQUIET(tas_spins, 0);
+	return (__dbcl_rpc_illegal(dbenv, "set_tas_spins"));
+}
+
+/*
+ * PUBLIC: int __dbcl_get_timeout __P((DB_ENV *, u_int32_t *, u_int32_t));
+ */
+int
+__dbcl_get_timeout(dbenv, timeoutp, flags)
+	DB_ENV * dbenv;
+	u_int32_t * timeoutp;
+	u_int32_t flags;
+{
+	COMPQUIET(timeoutp, 0);
+	COMPQUIET(flags, 0);
+	return (__dbcl_rpc_illegal(dbenv, "get_timeout"));
+}
+
+/*
+ * PUBLIC: int __dbcl_set_timeout __P((DB_ENV *, u_int32_t, u_int32_t));
+ */
+int
+__dbcl_set_timeout(dbenv, timeout, flags)
+	DB_ENV * dbenv;
+	u_int32_t timeout;
+	u_int32_t flags;
+{
+	COMPQUIET(timeout, 0);
+	COMPQUIET(flags, 0);
+	return (__dbcl_rpc_illegal(dbenv, "set_timeout"));
+}
+
+/*
+ * PUBLIC: int __dbcl_get_tmp_dir __P((DB_ENV *, const char * *));
+ */
+int
+__dbcl_get_tmp_dir(dbenv, dirp)
+	DB_ENV * dbenv;
+	const char * * dirp;
+{
+	COMPQUIET(dirp, 0);
+	return (__dbcl_rpc_illegal(dbenv, "get_tmp_dir"));
+}
+
+/*
+ * PUBLIC: int __dbcl_set_tmp_dir __P((DB_ENV *, const char *));
+ */
+int
+__dbcl_set_tmp_dir(dbenv, dir)
+	DB_ENV * dbenv;
+	const char * dir;
+{
+	COMPQUIET(dir, NULL);
+	return (__dbcl_rpc_illegal(dbenv, "set_tmp_dir"));
+}
+
+/*
+ * PUBLIC: int __dbcl_get_tx_max __P((DB_ENV *, u_int32_t *));
+ */
+int
+__dbcl_get_tx_max(dbenv, maxp)
+	DB_ENV * dbenv;
+	u_int32_t * maxp;
+{
+	COMPQUIET(maxp, 0);
+	return (__dbcl_rpc_illegal(dbenv, "get_tx_max"));
+}
+
+/*
+ * PUBLIC: int __dbcl_set_tx_max __P((DB_ENV *, u_int32_t));
+ */
+int
+__dbcl_set_tx_max(dbenv, max)
+	DB_ENV * dbenv;
+	u_int32_t max;
+{
+	COMPQUIET(max, 0);
+	return (__dbcl_rpc_illegal(dbenv, "set_tx_max"));
+}
+
+/*
+ * PUBLIC: int __dbcl_get_tx_timestamp __P((DB_ENV *, time_t *));
+ */
+int
+__dbcl_get_tx_timestamp(dbenv, maxp)
+	DB_ENV * dbenv;
+	time_t * maxp;
+{
+	COMPQUIET(maxp, 0);
+	return (__dbcl_rpc_illegal(dbenv, "get_tx_timestamp"));
+}
+
+/*
+ * PUBLIC: int __dbcl_set_tx_timestamp __P((DB_ENV *, time_t *));
+ */
+int
+__dbcl_set_tx_timestamp(dbenv, max)
+	DB_ENV * dbenv;
+	time_t * max;
+{
+	COMPQUIET(max, 0);
+	return (__dbcl_rpc_illegal(dbenv, "set_tx_timestamp"));
+}
+
+/*
+ * PUBLIC: int __dbcl_get_verbose __P((DB_ENV *, u_int32_t, int *));
+ */
+int
+__dbcl_get_verbose(dbenv, which, onoffp)
+	DB_ENV * dbenv;
+	u_int32_t which;
+	int * onoffp;
+{
+	COMPQUIET(which, 0);
+	COMPQUIET(onoffp, 0);
+	return (__dbcl_rpc_illegal(dbenv, "get_verbose"));
+}
+
+/*
+ * PUBLIC: int __dbcl_set_verbose __P((DB_ENV *, u_int32_t, int));
+ */
+int
+__dbcl_set_verbose(dbenv, which, onoff)
+	DB_ENV * dbenv;
+	u_int32_t which;
+	int onoff;
+{
+	COMPQUIET(which, 0);
+	COMPQUIET(onoff, 0);
+	return (__dbcl_rpc_illegal(dbenv, "set_verbose"));
+}
+
+/*
+ * PUBLIC: int __dbcl_txn_abort __P((DB_TXN *));
+ */
+int
+__dbcl_txn_abort(txnp)
+	DB_TXN * txnp;
+{
+	CLIENT *cl;
+	__txn_abort_msg msg;
+	__txn_abort_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = txnp->mgrp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (txnp == NULL)
+		msg.txnpcl_id = 0;
+	else
+		msg.txnpcl_id = txnp->txnid;
+
+	replyp = __db_txn_abort_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = __dbcl_txn_abort_ret(txnp, replyp);
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___txn_abort_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_txn_begin __P((DB_ENV *, DB_TXN *, DB_TXN **,
+ * PUBLIC:      u_int32_t));
+ */
+int
+__dbcl_txn_begin(dbenv, parent, txnpp, flags)
+	DB_ENV * dbenv;
+	DB_TXN * parent;
+	DB_TXN ** txnpp;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__txn_begin_msg msg;
+	__txn_begin_reply *replyp = NULL;
+	int ret;
+
+	ret = 0;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(dbenv));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbenv == NULL)
+		msg.dbenvcl_id = 0;
+	else
+		msg.dbenvcl_id = dbenv->cl_id;
+	if (parent == NULL)
+		msg.parentcl_id = 0;
+	else
+		msg.parentcl_id = parent->txnid;
+	msg.flags = flags;
+
+	replyp = __db_txn_begin_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = __dbcl_txn_begin_ret(dbenv, parent, txnpp, flags, replyp);
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___txn_begin_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_txn_checkpoint __P((DB_ENV *, u_int32_t, u_int32_t,
+ * PUBLIC:      u_int32_t));
+ */
+int
+__dbcl_txn_checkpoint(dbenv, kbyte, min, flags)
+	DB_ENV * dbenv;
+	u_int32_t kbyte;
+	u_int32_t min;
+	u_int32_t flags;
+{
+	COMPQUIET(kbyte, 0);
+	COMPQUIET(min, 0);
+	COMPQUIET(flags, 0);
+	return (__dbcl_rpc_illegal(dbenv, "txn_checkpoint"));
+}
+
+/*
+ * PUBLIC: int __dbcl_txn_commit __P((DB_TXN *, u_int32_t));
+ */
+int
+__dbcl_txn_commit(txnp, flags)
+	DB_TXN * txnp;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__txn_commit_msg msg;
+	__txn_commit_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = txnp->mgrp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (txnp == NULL)
+		msg.txnpcl_id = 0;
+	else
+		msg.txnpcl_id = txnp->txnid;
+	msg.flags = flags;
+
+	replyp = __db_txn_commit_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = __dbcl_txn_commit_ret(txnp, flags, replyp);
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___txn_commit_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_txn_discard __P((DB_TXN *, u_int32_t));
+ */
+int
+__dbcl_txn_discard(txnp, flags)
+	DB_TXN * txnp;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__txn_discard_msg msg;
+	__txn_discard_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = txnp->mgrp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (txnp == NULL)
+		msg.txnpcl_id = 0;
+	else
+		msg.txnpcl_id = txnp->txnid;
+	msg.flags = flags;
+
+	replyp = __db_txn_discard_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = __dbcl_txn_discard_ret(txnp, flags, replyp);
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___txn_discard_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_txn_prepare __P((DB_TXN *, u_int8_t *));
+ */
+int
+__dbcl_txn_prepare(txnp, gid)
+	DB_TXN * txnp;
+	u_int8_t * gid;
+{
+	CLIENT *cl;
+	__txn_prepare_msg msg;
+	__txn_prepare_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = txnp->mgrp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (txnp == NULL)
+		msg.txnpcl_id = 0;
+	else
+		msg.txnpcl_id = txnp->txnid;
+	memcpy(msg.gid, gid, 128);
+
+	replyp = __db_txn_prepare_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___txn_prepare_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_txn_recover __P((DB_ENV *, DB_PREPLIST *, long, long *,
+ * PUBLIC:      u_int32_t));
+ */
+int
+__dbcl_txn_recover(dbenv, preplist, count, retp, flags)
+	DB_ENV * dbenv;
+	DB_PREPLIST * preplist;
+	long count;
+	long * retp;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__txn_recover_msg msg;
+	__txn_recover_reply *replyp = NULL;
+	int ret;
+
+	ret = 0;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(dbenv));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbenv == NULL)
+		msg.dbenvcl_id = 0;
+	else
+		msg.dbenvcl_id = dbenv->cl_id;
+	msg.count = count;
+	msg.flags = flags;
+
+	replyp = __db_txn_recover_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = __dbcl_txn_recover_ret(dbenv, preplist, count, retp, flags, replyp);
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___txn_recover_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_txn_stat __P((DB_ENV *, DB_TXN_STAT **, u_int32_t));
+ */
+int
+__dbcl_txn_stat(dbenv, statp, flags)
+	DB_ENV * dbenv;
+	DB_TXN_STAT ** statp;
+	u_int32_t flags;
+{
+	COMPQUIET(statp, 0);
+	COMPQUIET(flags, 0);
+	return (__dbcl_rpc_illegal(dbenv, "txn_stat"));
+}
+
+/*
+ * PUBLIC: int __dbcl_txn_timeout __P((DB_TXN *, u_int32_t, u_int32_t));
+ */
+int
+__dbcl_txn_timeout(txnp, timeout, flags)
+	DB_TXN * txnp;
+	u_int32_t timeout;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+
+	dbenv = txnp->mgrp->dbenv;
+	COMPQUIET(timeout, 0);
+	COMPQUIET(flags, 0);
+	return (__dbcl_rpc_illegal(dbenv, "txn_timeout"));
+}
+
+/*
+ * PUBLIC: int __dbcl_rep_elect __P((DB_ENV *, int, int, int, u_int32_t, int *,
+ * PUBLIC:      u_int32_t));
+ */
+int
+__dbcl_rep_elect(dbenv, nsites, nvotes, pri, timeout, idp, flags)
+	DB_ENV * dbenv;
+	int nsites;
+	int nvotes;
+	int pri;
+	u_int32_t timeout;
+	int * idp;
+	u_int32_t flags;
+{
+	COMPQUIET(nsites, 0);
+	COMPQUIET(nvotes, 0);
+	COMPQUIET(pri, 0);
+	COMPQUIET(timeout, 0);
+	COMPQUIET(idp, 0);
+	COMPQUIET(flags, 0);
+	return (__dbcl_rpc_illegal(dbenv, "rep_elect"));
+}
+
+/*
+ * PUBLIC: int __dbcl_rep_flush __P((DB_ENV *));
+ */
+int
+__dbcl_rep_flush(dbenv)
+	DB_ENV * dbenv;
+{
+	return (__dbcl_rpc_illegal(dbenv, "rep_flush"));
+}
+
+/*
+ * PUBLIC: int __dbcl_rep_process_message __P((DB_ENV *, DBT *, DBT *, int *,
+ * PUBLIC:      DB_LSN *));
+ */
+int
+__dbcl_rep_process_message(dbenv, rec, control, idp, ret_lsnp)
+	DB_ENV * dbenv;
+	DBT * rec;
+	DBT * control;
+	int * idp;
+	DB_LSN * ret_lsnp;
+{
+	COMPQUIET(rec, NULL);
+	COMPQUIET(control, NULL);
+	COMPQUIET(idp, 0);
+	COMPQUIET(ret_lsnp, 0);
+	return (__dbcl_rpc_illegal(dbenv, "rep_process_message"));
+}
+
+/*
+ * PUBLIC: int __dbcl_rep_get_limit __P((DB_ENV *, u_int32_t *, u_int32_t *));
+ */
+int
+__dbcl_rep_get_limit(dbenv, mbytesp, bytesp)
+	DB_ENV * dbenv;
+	u_int32_t * mbytesp;
+	u_int32_t * bytesp;
+{
+	COMPQUIET(mbytesp, 0);
+	COMPQUIET(bytesp, 0);
+	return (__dbcl_rpc_illegal(dbenv, "rep_get_limit"));
+}
+
+/*
+ * PUBLIC: int __dbcl_rep_set_limit __P((DB_ENV *, u_int32_t, u_int32_t));
+ */
+int
+__dbcl_rep_set_limit(dbenv, mbytes, bytes)
+	DB_ENV * dbenv;
+	u_int32_t mbytes;
+	u_int32_t bytes;
+{
+	COMPQUIET(mbytes, 0);
+	COMPQUIET(bytes, 0);
+	return (__dbcl_rpc_illegal(dbenv, "rep_set_limit"));
+}
+
+/*
+ * PUBLIC: int __dbcl_rep_set_request __P((DB_ENV *, u_int32_t, u_int32_t));
+ */
+int
+__dbcl_rep_set_request(dbenv, min, max)
+	DB_ENV * dbenv;
+	u_int32_t min;
+	u_int32_t max;
+{
+	COMPQUIET(min, 0);
+	COMPQUIET(max, 0);
+	return (__dbcl_rpc_illegal(dbenv, "rep_set_request"));
+}
+
+/*
+ * PUBLIC: int __dbcl_rep_set_rep_transport __P((DB_ENV *, int,
+ * PUBLIC:      int (*)(DB_ENV *, const DBT *, const DBT *, const DB_LSN *, int, u_int32_t)));
+ */
+int
+__dbcl_rep_set_rep_transport(dbenv, id, func0)
+	DB_ENV * dbenv;
+	int id;
+	int (*func0) __P((DB_ENV *, const DBT *, const DBT *, const DB_LSN *, int, u_int32_t));
+{
+	COMPQUIET(id, 0);
+	COMPQUIET(func0, 0);
+	return (__dbcl_rpc_illegal(dbenv, "rep_set_rep_transport"));
+}
+
+/*
+ * PUBLIC: int __dbcl_rep_start __P((DB_ENV *, DBT *, u_int32_t));
+ */
+int
+__dbcl_rep_start(dbenv, cdata, flags)
+	DB_ENV * dbenv;
+	DBT * cdata;
+	u_int32_t flags;
+{
+	COMPQUIET(cdata, NULL);
+	COMPQUIET(flags, 0);
+	return (__dbcl_rpc_illegal(dbenv, "rep_start"));
+}
+
+/*
+ * PUBLIC: int __dbcl_rep_stat __P((DB_ENV *, DB_REP_STAT **, u_int32_t));
+ */
+int
+__dbcl_rep_stat(dbenv, statp, flags)
+	DB_ENV * dbenv;
+	DB_REP_STAT ** statp;
+	u_int32_t flags;
+{
+	COMPQUIET(statp, 0);
+	COMPQUIET(flags, 0);
+	return (__dbcl_rpc_illegal(dbenv, "rep_stat"));
+}
+
+/*
+ * PUBLIC: int __dbcl_db_alloc __P((DB *, void *(*)(size_t), void *(*)(void *,
+ * PUBLIC:      size_t), void (*)(void *)));
+ */
+int
+__dbcl_db_alloc(dbp, func0, func1, func2)
+	DB * dbp;
+	void *(*func0) __P((size_t));
+	void *(*func1) __P((void *, size_t));
+	void (*func2) __P((void *));
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbp->dbenv;
+	COMPQUIET(func0, 0);
+	COMPQUIET(func1, 0);
+	COMPQUIET(func2, 0);
+	return (__dbcl_rpc_illegal(dbenv, "db_alloc"));
+}
+
+/*
+ * PUBLIC: int __dbcl_db_associate __P((DB *, DB_TXN *, DB *, int (*)(DB *,
+ * PUBLIC:      const DBT *, const DBT *, DBT *), u_int32_t));
+ */
+int
+__dbcl_db_associate(dbp, txnp, sdbp, func0, flags)
+	DB * dbp;
+	DB_TXN * txnp;
+	DB * sdbp;
+	int (*func0) __P((DB *, const DBT *, const DBT *, DBT *));
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__db_associate_msg msg;
+	__db_associate_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (func0 != NULL) {
+		__db_err(dbenv, "User functions not supported in RPC");
+		return (EINVAL);
+	}
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+	if (txnp == NULL)
+		msg.txnpcl_id = 0;
+	else
+		msg.txnpcl_id = txnp->txnid;
+	if (sdbp == NULL)
+		msg.sdbpcl_id = 0;
+	else
+		msg.sdbpcl_id = sdbp->cl_id;
+	msg.flags = flags;
+
+	replyp = __db_db_associate_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_associate_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_bt_compare __P((DB *, int (*)(DB *, const DBT *,
+ * PUBLIC:      const DBT *)));
+ */
+int
+__dbcl_db_bt_compare(dbp, func0)
+	DB * dbp;
+	int (*func0) __P((DB *, const DBT *, const DBT *));
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbp->dbenv;
+	COMPQUIET(func0, 0);
+	return (__dbcl_rpc_illegal(dbenv, "db_bt_compare"));
+}
+
+/*
+ * PUBLIC: int __dbcl_db_bt_maxkey __P((DB *, u_int32_t));
+ */
+int
+__dbcl_db_bt_maxkey(dbp, maxkey)
+	DB * dbp;
+	u_int32_t maxkey;
+{
+	CLIENT *cl;
+	__db_bt_maxkey_msg msg;
+	__db_bt_maxkey_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+	msg.maxkey = maxkey;
+
+	replyp = __db_db_bt_maxkey_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_bt_maxkey_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_get_bt_minkey __P((DB *, u_int32_t *));
+ */
+int
+__dbcl_db_get_bt_minkey(dbp, minkeyp)
+	DB * dbp;
+	u_int32_t * minkeyp;
+{
+	CLIENT *cl;
+	__db_get_bt_minkey_msg msg;
+	__db_get_bt_minkey_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+
+	replyp = __db_db_get_bt_minkey_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+	if (minkeyp != NULL)
+		*minkeyp = replyp->minkey;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_get_bt_minkey_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_bt_minkey __P((DB *, u_int32_t));
+ */
+int
+__dbcl_db_bt_minkey(dbp, minkey)
+	DB * dbp;
+	u_int32_t minkey;
+{
+	CLIENT *cl;
+	__db_bt_minkey_msg msg;
+	__db_bt_minkey_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+	msg.minkey = minkey;
+
+	replyp = __db_db_bt_minkey_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_bt_minkey_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_bt_prefix __P((DB *, size_t(*)(DB *, const DBT *,
+ * PUBLIC:      const DBT *)));
+ */
+int
+__dbcl_db_bt_prefix(dbp, func0)
+	DB * dbp;
+	size_t (*func0) __P((DB *, const DBT *, const DBT *));
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbp->dbenv;
+	COMPQUIET(func0, 0);
+	return (__dbcl_rpc_illegal(dbenv, "db_bt_prefix"));
+}
+
+/*
+ * PUBLIC: int __dbcl_db_set_append_recno __P((DB *, int (*)(DB *, DBT *,
+ * PUBLIC:      db_recno_t)));
+ */
+int
+__dbcl_db_set_append_recno(dbp, func0)
+	DB * dbp;
+	int (*func0) __P((DB *, DBT *, db_recno_t));
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbp->dbenv;
+	COMPQUIET(func0, 0);
+	return (__dbcl_rpc_illegal(dbenv, "db_set_append_recno"));
+}
+
+/*
+ * PUBLIC: int __dbcl_db_get_cachesize __P((DB *, u_int32_t *, u_int32_t *,
+ * PUBLIC:      int *));
+ */
+int
+__dbcl_db_get_cachesize(dbp, gbytesp, bytesp, ncachep)
+	DB * dbp;
+	u_int32_t * gbytesp;
+	u_int32_t * bytesp;
+	int * ncachep;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbp->dbenv;
+	COMPQUIET(gbytesp, 0);
+	COMPQUIET(bytesp, 0);
+	COMPQUIET(ncachep, 0);
+	return (__dbcl_rpc_illegal(dbenv, "db_get_cachesize"));
+}
+
+/*
+ * PUBLIC: int __dbcl_db_cachesize __P((DB *, u_int32_t, u_int32_t, int));
+ */
+int
+__dbcl_db_cachesize(dbp, gbytes, bytes, ncache)
+	DB * dbp;
+	u_int32_t gbytes;
+	u_int32_t bytes;
+	int ncache;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbp->dbenv;
+	COMPQUIET(gbytes, 0);
+	COMPQUIET(bytes, 0);
+	COMPQUIET(ncache, 0);
+	return (__dbcl_rpc_illegal(dbenv, "db_cachesize"));
+}
+
+/*
+ * PUBLIC: int __dbcl_db_close __P((DB *, u_int32_t));
+ */
+int
+__dbcl_db_close(dbp, flags)
+	DB * dbp;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__db_close_msg msg;
+	__db_close_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+	msg.flags = flags;
+
+	replyp = __db_db_close_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = __dbcl_db_close_ret(dbp, flags, replyp);
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_close_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_create __P((DB *, DB_ENV *, u_int32_t));
+ */
+int
+__dbcl_db_create(dbp, dbenv, flags)
+	DB * dbp;
+	DB_ENV * dbenv;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__db_create_msg msg;
+	__db_create_reply *replyp = NULL;
+	int ret;
+
+	ret = 0;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(dbenv));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbenv == NULL)
+		msg.dbenvcl_id = 0;
+	else
+		msg.dbenvcl_id = dbenv->cl_id;
+	msg.flags = flags;
+
+	replyp = __db_db_create_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = __dbcl_db_create_ret(dbp, dbenv, flags, replyp);
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_create_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_del __P((DB *, DB_TXN *, DBT *, u_int32_t));
+ */
+int
+__dbcl_db_del(dbp, txnp, key, flags)
+	DB * dbp;
+	DB_TXN * txnp;
+	DBT * key;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__db_del_msg msg;
+	__db_del_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+	if (txnp == NULL)
+		msg.txnpcl_id = 0;
+	else
+		msg.txnpcl_id = txnp->txnid;
+	msg.keydlen = key->dlen;
+	msg.keydoff = key->doff;
+	msg.keyulen = key->ulen;
+	msg.keyflags = key->flags;
+	msg.keydata.keydata_val = key->data;
+	msg.keydata.keydata_len = key->size;
+	msg.flags = flags;
+
+	replyp = __db_db_del_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_del_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_dup_compare __P((DB *, int (*)(DB *, const DBT *,
+ * PUBLIC:      const DBT *)));
+ */
+int
+__dbcl_db_dup_compare(dbp, func0)
+	DB * dbp;
+	int (*func0) __P((DB *, const DBT *, const DBT *));
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbp->dbenv;
+	COMPQUIET(func0, 0);
+	return (__dbcl_rpc_illegal(dbenv, "db_dup_compare"));
+}
+
+/*
+ * PUBLIC: int __dbcl_db_get_encrypt_flags __P((DB *, u_int32_t *));
+ */
+int
+__dbcl_db_get_encrypt_flags(dbp, flagsp)
+	DB * dbp;
+	u_int32_t * flagsp;
+{
+	CLIENT *cl;
+	__db_get_encrypt_flags_msg msg;
+	__db_get_encrypt_flags_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+
+	replyp = __db_db_get_encrypt_flags_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+	if (flagsp != NULL)
+		*flagsp = replyp->flags;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_get_encrypt_flags_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_encrypt __P((DB *, const char *, u_int32_t));
+ */
+int
+__dbcl_db_encrypt(dbp, passwd, flags)
+	DB * dbp;
+	const char * passwd;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__db_encrypt_msg msg;
+	__db_encrypt_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+	if (passwd == NULL)
+		msg.passwd = "";
+	else
+		msg.passwd = (char *)passwd;
+	msg.flags = flags;
+
+	replyp = __db_db_encrypt_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_encrypt_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_get_extentsize __P((DB *, u_int32_t *));
+ */
+int
+__dbcl_db_get_extentsize(dbp, extentsizep)
+	DB * dbp;
+	u_int32_t * extentsizep;
+{
+	CLIENT *cl;
+	__db_get_extentsize_msg msg;
+	__db_get_extentsize_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+
+	replyp = __db_db_get_extentsize_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+	if (extentsizep != NULL)
+		*extentsizep = replyp->extentsize;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_get_extentsize_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_extentsize __P((DB *, u_int32_t));
+ */
+int
+__dbcl_db_extentsize(dbp, extentsize)
+	DB * dbp;
+	u_int32_t extentsize;
+{
+	CLIENT *cl;
+	__db_extentsize_msg msg;
+	__db_extentsize_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+	msg.extentsize = extentsize;
+
+	replyp = __db_db_extentsize_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_extentsize_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_fd __P((DB *, int *));
+ */
+int
+__dbcl_db_fd(dbp, fdp)
+	DB * dbp;
+	int * fdp;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbp->dbenv;
+	COMPQUIET(fdp, 0);
+	return (__dbcl_rpc_illegal(dbenv, "db_fd"));
+}
+
+/*
+ * PUBLIC: int __dbcl_db_feedback __P((DB *, void (*)(DB *, int, int)));
+ */
+int
+__dbcl_db_feedback(dbp, func0)
+	DB * dbp;
+	void (*func0) __P((DB *, int, int));
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbp->dbenv;
+	COMPQUIET(func0, 0);
+	return (__dbcl_rpc_illegal(dbenv, "db_feedback"));
+}
+
+/*
+ * PUBLIC: int __dbcl_db_get_flags __P((DB *, u_int32_t *));
+ */
+int
+__dbcl_db_get_flags(dbp, flagsp)
+	DB * dbp;
+	u_int32_t * flagsp;
+{
+	CLIENT *cl;
+	__db_get_flags_msg msg;
+	__db_get_flags_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+
+	replyp = __db_db_get_flags_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+	if (flagsp != NULL)
+		*flagsp = replyp->flags;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_get_flags_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_flags __P((DB *, u_int32_t));
+ */
+int
+__dbcl_db_flags(dbp, flags)
+	DB * dbp;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__db_flags_msg msg;
+	__db_flags_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+	msg.flags = flags;
+
+	replyp = __db_db_flags_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_flags_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_get __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
+ */
+int
+__dbcl_db_get(dbp, txnp, key, data, flags)
+	DB * dbp;
+	DB_TXN * txnp;
+	DBT * key;
+	DBT * data;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__db_get_msg msg;
+	__db_get_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+	if (txnp == NULL)
+		msg.txnpcl_id = 0;
+	else
+		msg.txnpcl_id = txnp->txnid;
+	msg.keydlen = key->dlen;
+	msg.keydoff = key->doff;
+	msg.keyulen = key->ulen;
+	msg.keyflags = key->flags;
+	msg.keydata.keydata_val = key->data;
+	msg.keydata.keydata_len = key->size;
+	msg.datadlen = data->dlen;
+	msg.datadoff = data->doff;
+	msg.dataulen = data->ulen;
+	msg.dataflags = data->flags;
+	msg.datadata.datadata_val = data->data;
+	msg.datadata.datadata_len = data->size;
+	msg.flags = flags;
+
+	replyp = __db_db_get_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = __dbcl_db_get_ret(dbp, txnp, key, data, flags, replyp);
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_get_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_get_name __P((DB *, const char * *, const char * *));
+ */
+int
+__dbcl_db_get_name(dbp, filenamep, dbnamep)
+	DB * dbp;
+	const char * * filenamep;
+	const char * * dbnamep;
+{
+	CLIENT *cl;
+	__db_get_name_msg msg;
+	__db_get_name_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+
+	replyp = __db_db_get_name_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+	if (filenamep != NULL)
+		*filenamep = replyp->filename;
+	if (dbnamep != NULL)
+		*dbnamep = replyp->dbname;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_get_name_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_get_open_flags __P((DB *, u_int32_t *));
+ */
+int
+__dbcl_db_get_open_flags(dbp, flagsp)
+	DB * dbp;
+	u_int32_t * flagsp;
+{
+	CLIENT *cl;
+	__db_get_open_flags_msg msg;
+	__db_get_open_flags_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+
+	replyp = __db_db_get_open_flags_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+	if (flagsp != NULL)
+		*flagsp = replyp->flags;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_get_open_flags_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_get_h_ffactor __P((DB *, u_int32_t *));
+ */
+int
+__dbcl_db_get_h_ffactor(dbp, ffactorp)
+	DB * dbp;
+	u_int32_t * ffactorp;
+{
+	CLIENT *cl;
+	__db_get_h_ffactor_msg msg;
+	__db_get_h_ffactor_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+
+	replyp = __db_db_get_h_ffactor_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+	if (ffactorp != NULL)
+		*ffactorp = replyp->ffactor;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_get_h_ffactor_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_h_ffactor __P((DB *, u_int32_t));
+ */
+int
+__dbcl_db_h_ffactor(dbp, ffactor)
+	DB * dbp;
+	u_int32_t ffactor;
+{
+	CLIENT *cl;
+	__db_h_ffactor_msg msg;
+	__db_h_ffactor_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+	msg.ffactor = ffactor;
+
+	replyp = __db_db_h_ffactor_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_h_ffactor_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_h_hash __P((DB *, u_int32_t(*)(DB *, const void *,
+ * PUBLIC:      u_int32_t)));
+ */
+int
+__dbcl_db_h_hash(dbp, func0)
+	DB * dbp;
+	u_int32_t (*func0) __P((DB *, const void *, u_int32_t));
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbp->dbenv;
+	COMPQUIET(func0, 0);
+	return (__dbcl_rpc_illegal(dbenv, "db_h_hash"));
+}
+
+/*
+ * PUBLIC: int __dbcl_db_get_h_nelem __P((DB *, u_int32_t *));
+ */
+int
+__dbcl_db_get_h_nelem(dbp, nelemp)
+	DB * dbp;
+	u_int32_t * nelemp;
+{
+	CLIENT *cl;
+	__db_get_h_nelem_msg msg;
+	__db_get_h_nelem_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+
+	replyp = __db_db_get_h_nelem_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+	if (nelemp != NULL)
+		*nelemp = replyp->nelem;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_get_h_nelem_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_h_nelem __P((DB *, u_int32_t));
+ */
+int
+__dbcl_db_h_nelem(dbp, nelem)
+	DB * dbp;
+	u_int32_t nelem;
+{
+	CLIENT *cl;
+	__db_h_nelem_msg msg;
+	__db_h_nelem_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+	msg.nelem = nelem;
+
+	replyp = __db_db_h_nelem_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_h_nelem_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_key_range __P((DB *, DB_TXN *, DBT *, DB_KEY_RANGE *,
+ * PUBLIC:      u_int32_t));
+ */
+int
+__dbcl_db_key_range(dbp, txnp, key, range, flags)
+	DB * dbp;
+	DB_TXN * txnp;
+	DBT * key;
+	DB_KEY_RANGE * range;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__db_key_range_msg msg;
+	__db_key_range_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+	if (txnp == NULL)
+		msg.txnpcl_id = 0;
+	else
+		msg.txnpcl_id = txnp->txnid;
+	msg.keydlen = key->dlen;
+	msg.keydoff = key->doff;
+	msg.keyulen = key->ulen;
+	msg.keyflags = key->flags;
+	msg.keydata.keydata_val = key->data;
+	msg.keydata.keydata_len = key->size;
+	msg.flags = flags;
+
+	replyp = __db_db_key_range_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = __dbcl_db_key_range_ret(dbp, txnp, key, range, flags, replyp);
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_key_range_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_get_lorder __P((DB *, int *));
+ */
+int
+__dbcl_db_get_lorder(dbp, lorderp)
+	DB * dbp;
+	int * lorderp;
+{
+	CLIENT *cl;
+	__db_get_lorder_msg msg;
+	__db_get_lorder_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+
+	replyp = __db_db_get_lorder_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+	if (lorderp != NULL)
+		*lorderp = replyp->lorder;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_get_lorder_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_lorder __P((DB *, int));
+ */
+int
+__dbcl_db_lorder(dbp, lorder)
+	DB * dbp;
+	int lorder;
+{
+	CLIENT *cl;
+	__db_lorder_msg msg;
+	__db_lorder_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+	msg.lorder = lorder;
+
+	replyp = __db_db_lorder_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_lorder_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_open __P((DB *, DB_TXN *, const char *, const char *,
+ * PUBLIC:      DBTYPE, u_int32_t, int));
+ */
+int
+__dbcl_db_open(dbp, txnp, name, subdb, type, flags, mode)
+	DB * dbp;
+	DB_TXN * txnp;
+	const char * name;
+	const char * subdb;
+	DBTYPE type;
+	u_int32_t flags;
+	int mode;
+{
+	CLIENT *cl;
+	__db_open_msg msg;
+	__db_open_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+	if (txnp == NULL)
+		msg.txnpcl_id = 0;
+	else
+		msg.txnpcl_id = txnp->txnid;
+	if (name == NULL)
+		msg.name = "";
+	else
+		msg.name = (char *)name;
+	if (subdb == NULL)
+		msg.subdb = "";
+	else
+		msg.subdb = (char *)subdb;
+	msg.type = type;
+	msg.flags = flags;
+	msg.mode = mode;
+
+	replyp = __db_db_open_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = __dbcl_db_open_ret(dbp, txnp, name, subdb, type, flags, mode, replyp);
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_open_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_get_pagesize __P((DB *, u_int32_t *));
+ */
+int
+__dbcl_db_get_pagesize(dbp, pagesizep)
+	DB * dbp;
+	u_int32_t * pagesizep;
+{
+	CLIENT *cl;
+	__db_get_pagesize_msg msg;
+	__db_get_pagesize_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+
+	replyp = __db_db_get_pagesize_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+	if (pagesizep != NULL)
+		*pagesizep = replyp->pagesize;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_get_pagesize_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_pagesize __P((DB *, u_int32_t));
+ */
+int
+__dbcl_db_pagesize(dbp, pagesize)
+	DB * dbp;
+	u_int32_t pagesize;
+{
+	CLIENT *cl;
+	__db_pagesize_msg msg;
+	__db_pagesize_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+	msg.pagesize = pagesize;
+
+	replyp = __db_db_pagesize_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_pagesize_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_panic __P((DB *, void (*)(DB_ENV *, int)));
+ */
+int
+__dbcl_db_panic(dbp, func0)
+	DB * dbp;
+	void (*func0) __P((DB_ENV *, int));
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbp->dbenv;
+	COMPQUIET(func0, 0);
+	return (__dbcl_rpc_illegal(dbenv, "db_panic"));
+}
+
+/*
+ * PUBLIC: int __dbcl_db_pget __P((DB *, DB_TXN *, DBT *, DBT *, DBT *,
+ * PUBLIC:      u_int32_t));
+ */
+int
+__dbcl_db_pget(dbp, txnp, skey, pkey, data, flags)
+	DB * dbp;
+	DB_TXN * txnp;
+	DBT * skey;
+	DBT * pkey;
+	DBT * data;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__db_pget_msg msg;
+	__db_pget_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+	if (txnp == NULL)
+		msg.txnpcl_id = 0;
+	else
+		msg.txnpcl_id = txnp->txnid;
+	msg.skeydlen = skey->dlen;
+	msg.skeydoff = skey->doff;
+	msg.skeyulen = skey->ulen;
+	msg.skeyflags = skey->flags;
+	msg.skeydata.skeydata_val = skey->data;
+	msg.skeydata.skeydata_len = skey->size;
+	msg.pkeydlen = pkey->dlen;
+	msg.pkeydoff = pkey->doff;
+	msg.pkeyulen = pkey->ulen;
+	msg.pkeyflags = pkey->flags;
+	msg.pkeydata.pkeydata_val = pkey->data;
+	msg.pkeydata.pkeydata_len = pkey->size;
+	msg.datadlen = data->dlen;
+	msg.datadoff = data->doff;
+	msg.dataulen = data->ulen;
+	msg.dataflags = data->flags;
+	msg.datadata.datadata_val = data->data;
+	msg.datadata.datadata_len = data->size;
+	msg.flags = flags;
+
+	replyp = __db_db_pget_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = __dbcl_db_pget_ret(dbp, txnp, skey, pkey, data, flags, replyp);
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_pget_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_put __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
+ */
+int
+__dbcl_db_put(dbp, txnp, key, data, flags)
+	DB * dbp;
+	DB_TXN * txnp;
+	DBT * key;
+	DBT * data;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__db_put_msg msg;
+	__db_put_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+	if (txnp == NULL)
+		msg.txnpcl_id = 0;
+	else
+		msg.txnpcl_id = txnp->txnid;
+	msg.keydlen = key->dlen;
+	msg.keydoff = key->doff;
+	msg.keyulen = key->ulen;
+	msg.keyflags = key->flags;
+	msg.keydata.keydata_val = key->data;
+	msg.keydata.keydata_len = key->size;
+	msg.datadlen = data->dlen;
+	msg.datadoff = data->doff;
+	msg.dataulen = data->ulen;
+	msg.dataflags = data->flags;
+	msg.datadata.datadata_val = data->data;
+	msg.datadata.datadata_len = data->size;
+	msg.flags = flags;
+
+	replyp = __db_db_put_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = __dbcl_db_put_ret(dbp, txnp, key, data, flags, replyp);
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_put_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_get_re_delim __P((DB *, int *));
+ */
+int
+__dbcl_db_get_re_delim(dbp, delimp)
+	DB * dbp;
+	int * delimp;
+{
+	CLIENT *cl;
+	__db_get_re_delim_msg msg;
+	__db_get_re_delim_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+
+	replyp = __db_db_get_re_delim_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+	if (delimp != NULL)
+		*delimp = replyp->delim;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_get_re_delim_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_re_delim __P((DB *, int));
+ */
+int
+__dbcl_db_re_delim(dbp, delim)
+	DB * dbp;
+	int delim;
+{
+	CLIENT *cl;
+	__db_re_delim_msg msg;
+	__db_re_delim_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+	msg.delim = delim;
+
+	replyp = __db_db_re_delim_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_re_delim_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_get_re_len __P((DB *, u_int32_t *));
+ */
+int
+__dbcl_db_get_re_len(dbp, lenp)
+	DB * dbp;
+	u_int32_t * lenp;
+{
+	CLIENT *cl;
+	__db_get_re_len_msg msg;
+	__db_get_re_len_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+
+	replyp = __db_db_get_re_len_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+	if (lenp != NULL)
+		*lenp = replyp->len;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_get_re_len_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_re_len __P((DB *, u_int32_t));
+ */
+int
+__dbcl_db_re_len(dbp, len)
+	DB * dbp;
+	u_int32_t len;
+{
+	CLIENT *cl;
+	__db_re_len_msg msg;
+	__db_re_len_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+	msg.len = len;
+
+	replyp = __db_db_re_len_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_re_len_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_re_pad __P((DB *, int));
+ */
+int
+__dbcl_db_re_pad(dbp, pad)
+	DB * dbp;
+	int pad;
+{
+	CLIENT *cl;
+	__db_re_pad_msg msg;
+	__db_re_pad_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+	msg.pad = pad;
+
+	replyp = __db_db_re_pad_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_re_pad_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_get_re_pad __P((DB *, int *));
+ */
+int
+__dbcl_db_get_re_pad(dbp, padp)
+	DB * dbp;
+	int * padp;
+{
+	CLIENT *cl;
+	__db_get_re_pad_msg msg;
+	__db_get_re_pad_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+
+	replyp = __db_db_get_re_pad_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+	if (padp != NULL)
+		*padp = replyp->pad;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_get_re_pad_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_get_re_source __P((DB *, const char * *));
+ */
+int
+__dbcl_db_get_re_source(dbp, re_sourcep)
+	DB * dbp;
+	const char * * re_sourcep;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbp->dbenv;
+	COMPQUIET(re_sourcep, 0);
+	return (__dbcl_rpc_illegal(dbenv, "db_get_re_source"));
+}
+
+/*
+ * PUBLIC: int __dbcl_db_re_source __P((DB *, const char *));
+ */
+int
+__dbcl_db_re_source(dbp, re_source)
+	DB * dbp;
+	const char * re_source;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbp->dbenv;
+	COMPQUIET(re_source, NULL);
+	return (__dbcl_rpc_illegal(dbenv, "db_re_source"));
+}
+
+/*
+ * PUBLIC: int __dbcl_db_remove __P((DB *, const char *, const char *,
+ * PUBLIC:      u_int32_t));
+ */
+int
+__dbcl_db_remove(dbp, name, subdb, flags)
+	DB * dbp;
+	const char * name;
+	const char * subdb;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__db_remove_msg msg;
+	__db_remove_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+	if (name == NULL)
+		msg.name = "";
+	else
+		msg.name = (char *)name;
+	if (subdb == NULL)
+		msg.subdb = "";
+	else
+		msg.subdb = (char *)subdb;
+	msg.flags = flags;
+
+	replyp = __db_db_remove_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = __dbcl_db_remove_ret(dbp, name, subdb, flags, replyp);
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_remove_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_rename __P((DB *, const char *, const char *,
+ * PUBLIC:      const char *, u_int32_t));
+ */
+int
+__dbcl_db_rename(dbp, name, subdb, newname, flags)
+	DB * dbp;
+	const char * name;
+	const char * subdb;
+	const char * newname;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__db_rename_msg msg;
+	__db_rename_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+	if (name == NULL)
+		msg.name = "";
+	else
+		msg.name = (char *)name;
+	if (subdb == NULL)
+		msg.subdb = "";
+	else
+		msg.subdb = (char *)subdb;
+	if (newname == NULL)
+		msg.newname = "";
+	else
+		msg.newname = (char *)newname;
+	msg.flags = flags;
+
+	replyp = __db_db_rename_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = __dbcl_db_rename_ret(dbp, name, subdb, newname, flags, replyp);
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_rename_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_stat __P((DB *, DB_TXN *, void *, u_int32_t));
+ */
+int
+__dbcl_db_stat(dbp, txnp, sp, flags)
+	DB * dbp;
+	DB_TXN * txnp;
+	void * sp;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__db_stat_msg msg;
+	__db_stat_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+	if (txnp == NULL)
+		msg.txnpcl_id = 0;
+	else
+		msg.txnpcl_id = txnp->txnid;
+	msg.flags = flags;
+
+	replyp = __db_db_stat_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = __dbcl_db_stat_ret(dbp, txnp, sp, flags, replyp);
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_stat_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_sync __P((DB *, u_int32_t));
+ */
+int
+__dbcl_db_sync(dbp, flags)
+	DB * dbp;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__db_sync_msg msg;
+	__db_sync_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+	msg.flags = flags;
+
+	replyp = __db_db_sync_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_sync_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_truncate __P((DB *, DB_TXN *, u_int32_t  *,
+ * PUBLIC:      u_int32_t));
+ */
+int
+__dbcl_db_truncate(dbp, txnp, countp, flags)
+	DB * dbp;
+	DB_TXN * txnp;
+	u_int32_t  * countp;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__db_truncate_msg msg;
+	__db_truncate_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+	if (txnp == NULL)
+		msg.txnpcl_id = 0;
+	else
+		msg.txnpcl_id = txnp->txnid;
+	msg.flags = flags;
+
+	replyp = __db_db_truncate_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = __dbcl_db_truncate_ret(dbp, txnp, countp, flags, replyp);
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_truncate_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_upgrade __P((DB *, const char *, u_int32_t));
+ */
+int
+__dbcl_db_upgrade(dbp, fname, flags)
+	DB * dbp;
+	const char * fname;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbp->dbenv;
+	COMPQUIET(fname, NULL);
+	COMPQUIET(flags, 0);
+	return (__dbcl_rpc_illegal(dbenv, "db_upgrade"));
+}
+
+/*
+ * PUBLIC: int __dbcl_db_verify __P((DB *, const char *, const char *, FILE *,
+ * PUBLIC:      u_int32_t));
+ */
+int
+__dbcl_db_verify(dbp, fname, subdb, outfile, flags)
+	DB * dbp;
+	const char * fname;
+	const char * subdb;
+	FILE * outfile;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbp->dbenv;
+	COMPQUIET(fname, NULL);
+	COMPQUIET(subdb, NULL);
+	COMPQUIET(outfile, 0);
+	COMPQUIET(flags, 0);
+	return (__dbcl_rpc_illegal(dbenv, "db_verify"));
+}
+
+/*
+ * PUBLIC: int __dbcl_db_cursor __P((DB *, DB_TXN *, DBC **, u_int32_t));
+ */
+int
+__dbcl_db_cursor(dbp, txnp, dbcpp, flags)
+	DB * dbp;
+	DB_TXN * txnp;
+	DBC ** dbcpp;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__db_cursor_msg msg;
+	__db_cursor_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+	if (txnp == NULL)
+		msg.txnpcl_id = 0;
+	else
+		msg.txnpcl_id = txnp->txnid;
+	msg.flags = flags;
+
+	replyp = __db_db_cursor_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = __dbcl_db_cursor_ret(dbp, txnp, dbcpp, flags, replyp);
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_cursor_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_db_join __P((DB *, DBC **, DBC **, u_int32_t));
+ */
+int
+__dbcl_db_join(dbp, curs, dbcp, flags)
+	DB * dbp;
+	DBC ** curs;
+	DBC ** dbcp;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__db_join_msg msg;
+	__db_join_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+	DBC ** cursp;
+	int cursi;
+	u_int32_t * cursq;
+
+	ret = 0;
+	dbenv = dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbp == NULL)
+		msg.dbpcl_id = 0;
+	else
+		msg.dbpcl_id = dbp->cl_id;
+	for (cursi = 0, cursp = curs; *cursp != 0;  cursi++, cursp++)
+		;
+	msg.curs.curs_len = cursi;
+	if ((ret = __os_calloc(dbenv,
+	    msg.curs.curs_len, sizeof(u_int32_t), &msg.curs.curs_val)) != 0)
+		return (ret);
+	for (cursq = msg.curs.curs_val, cursp = curs; cursi--; cursq++, cursp++)
+		*cursq = (*cursp)->cl_id;
+	msg.flags = flags;
+
+	replyp = __db_db_join_4003(&msg, cl);
+	__os_free(dbenv, msg.curs.curs_val);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = __dbcl_db_join_ret(dbp, curs, dbcp, flags, replyp);
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___db_join_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_dbc_close __P((DBC *));
+ */
+int
+__dbcl_dbc_close(dbc)
+	DBC * dbc;
+{
+	CLIENT *cl;
+	__dbc_close_msg msg;
+	__dbc_close_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbc->dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbc == NULL)
+		msg.dbccl_id = 0;
+	else
+		msg.dbccl_id = dbc->cl_id;
+
+	replyp = __db_dbc_close_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = __dbcl_dbc_close_ret(dbc, replyp);
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___dbc_close_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_dbc_count __P((DBC *, db_recno_t *, u_int32_t));
+ */
+int
+__dbcl_dbc_count(dbc, countp, flags)
+	DBC * dbc;
+	db_recno_t * countp;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__dbc_count_msg msg;
+	__dbc_count_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbc->dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbc == NULL)
+		msg.dbccl_id = 0;
+	else
+		msg.dbccl_id = dbc->cl_id;
+	msg.flags = flags;
+
+	replyp = __db_dbc_count_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = __dbcl_dbc_count_ret(dbc, countp, flags, replyp);
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___dbc_count_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_dbc_del __P((DBC *, u_int32_t));
+ */
+int
+__dbcl_dbc_del(dbc, flags)
+	DBC * dbc;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__dbc_del_msg msg;
+	__dbc_del_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbc->dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbc == NULL)
+		msg.dbccl_id = 0;
+	else
+		msg.dbccl_id = dbc->cl_id;
+	msg.flags = flags;
+
+	replyp = __db_dbc_del_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = replyp->status;
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___dbc_del_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_dbc_dup __P((DBC *, DBC **, u_int32_t));
+ */
+int
+__dbcl_dbc_dup(dbc, dbcp, flags)
+	DBC * dbc;
+	DBC ** dbcp;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__dbc_dup_msg msg;
+	__dbc_dup_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbc->dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbc == NULL)
+		msg.dbccl_id = 0;
+	else
+		msg.dbccl_id = dbc->cl_id;
+	msg.flags = flags;
+
+	replyp = __db_dbc_dup_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = __dbcl_dbc_dup_ret(dbc, dbcp, flags, replyp);
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___dbc_dup_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_dbc_get __P((DBC *, DBT *, DBT *, u_int32_t));
+ */
+int
+__dbcl_dbc_get(dbc, key, data, flags)
+	DBC * dbc;
+	DBT * key;
+	DBT * data;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__dbc_get_msg msg;
+	__dbc_get_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbc->dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbc == NULL)
+		msg.dbccl_id = 0;
+	else
+		msg.dbccl_id = dbc->cl_id;
+	msg.keydlen = key->dlen;
+	msg.keydoff = key->doff;
+	msg.keyulen = key->ulen;
+	msg.keyflags = key->flags;
+	msg.keydata.keydata_val = key->data;
+	msg.keydata.keydata_len = key->size;
+	msg.datadlen = data->dlen;
+	msg.datadoff = data->doff;
+	msg.dataulen = data->ulen;
+	msg.dataflags = data->flags;
+	msg.datadata.datadata_val = data->data;
+	msg.datadata.datadata_len = data->size;
+	msg.flags = flags;
+
+	replyp = __db_dbc_get_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = __dbcl_dbc_get_ret(dbc, key, data, flags, replyp);
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___dbc_get_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_dbc_pget __P((DBC *, DBT *, DBT *, DBT *, u_int32_t));
+ */
+int
+__dbcl_dbc_pget(dbc, skey, pkey, data, flags)
+	DBC * dbc;
+	DBT * skey;
+	DBT * pkey;
+	DBT * data;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__dbc_pget_msg msg;
+	__dbc_pget_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbc->dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbc == NULL)
+		msg.dbccl_id = 0;
+	else
+		msg.dbccl_id = dbc->cl_id;
+	msg.skeydlen = skey->dlen;
+	msg.skeydoff = skey->doff;
+	msg.skeyulen = skey->ulen;
+	msg.skeyflags = skey->flags;
+	msg.skeydata.skeydata_val = skey->data;
+	msg.skeydata.skeydata_len = skey->size;
+	msg.pkeydlen = pkey->dlen;
+	msg.pkeydoff = pkey->doff;
+	msg.pkeyulen = pkey->ulen;
+	msg.pkeyflags = pkey->flags;
+	msg.pkeydata.pkeydata_val = pkey->data;
+	msg.pkeydata.pkeydata_len = pkey->size;
+	msg.datadlen = data->dlen;
+	msg.datadoff = data->doff;
+	msg.dataulen = data->ulen;
+	msg.dataflags = data->flags;
+	msg.datadata.datadata_val = data->data;
+	msg.datadata.datadata_len = data->size;
+	msg.flags = flags;
+
+	replyp = __db_dbc_pget_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = __dbcl_dbc_pget_ret(dbc, skey, pkey, data, flags, replyp);
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___dbc_pget_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_dbc_put __P((DBC *, DBT *, DBT *, u_int32_t));
+ */
+int
+__dbcl_dbc_put(dbc, key, data, flags)
+	DBC * dbc;
+	DBT * key;
+	DBT * data;
+	u_int32_t flags;
+{
+	CLIENT *cl;
+	__dbc_put_msg msg;
+	__dbc_put_reply *replyp = NULL;
+	int ret;
+	DB_ENV *dbenv;
+
+	ret = 0;
+	dbenv = dbc->dbp->dbenv;
+	if (dbenv == NULL || !RPC_ON(dbenv))
+		return (__dbcl_noserver(NULL));
+
+	cl = (CLIENT *)dbenv->cl_handle;
+
+	if (dbc == NULL)
+		msg.dbccl_id = 0;
+	else
+		msg.dbccl_id = dbc->cl_id;
+	msg.keydlen = key->dlen;
+	msg.keydoff = key->doff;
+	msg.keyulen = key->ulen;
+	msg.keyflags = key->flags;
+	msg.keydata.keydata_val = key->data;
+	msg.keydata.keydata_len = key->size;
+	msg.datadlen = data->dlen;
+	msg.datadoff = data->doff;
+	msg.dataulen = data->ulen;
+	msg.dataflags = data->flags;
+	msg.datadata.datadata_val = data->data;
+	msg.datadata.datadata_len = data->size;
+	msg.flags = flags;
+
+	replyp = __db_dbc_put_4003(&msg, cl);
+	if (replyp == NULL) {
+		__db_err(dbenv, clnt_sperror(cl, "Berkeley DB"));
+		ret = DB_NOSERVER;
+		goto out;
+	}
+	ret = __dbcl_dbc_put_ret(dbc, key, data, flags, replyp);
+out:
+	if (replyp != NULL)
+		xdr_free((xdrproc_t)xdr___dbc_put_reply, (void *)replyp);
+	return (ret);
+}
+
+/*
+ * PUBLIC: int __dbcl_lock_detect __P((DB_ENV *, u_int32_t, u_int32_t, int *));
+ */
+int
+__dbcl_lock_detect(dbenv, flags, atype, aborted)
+	DB_ENV * dbenv;
+	u_int32_t flags;
+	u_int32_t atype;
+	int * aborted;
+{
+	COMPQUIET(flags, 0);
+	COMPQUIET(atype, 0);
+	COMPQUIET(aborted, 0);
+	return (__dbcl_rpc_illegal(dbenv, "lock_detect"));
+}
+
+/*
+ * PUBLIC: int __dbcl_lock_get __P((DB_ENV *, u_int32_t, u_int32_t,
+ * PUBLIC:      const DBT *, db_lockmode_t, DB_LOCK *));
+ */
+int
+__dbcl_lock_get(dbenv, locker, flags, obj, mode, lock)
+	DB_ENV * dbenv;
+	u_int32_t locker;
+	u_int32_t flags;
+	const DBT * obj;
+	db_lockmode_t mode;
+	DB_LOCK * lock;
+{
+	COMPQUIET(locker, 0);
+	COMPQUIET(flags, 0);
+	COMPQUIET(obj, NULL);
+	COMPQUIET(mode, 0);
+	COMPQUIET(lock, 0);
+	return (__dbcl_rpc_illegal(dbenv, "lock_get"));
+}
+
+/*
+ * PUBLIC: int __dbcl_lock_id __P((DB_ENV *, u_int32_t *));
+ */
+int
+__dbcl_lock_id(dbenv, idp)
+	DB_ENV * dbenv;
+	u_int32_t * idp;
+{
+	COMPQUIET(idp, 0);
+	return (__dbcl_rpc_illegal(dbenv, "lock_id"));
+}
+
+/*
+ * PUBLIC: int __dbcl_lock_id_free __P((DB_ENV *, u_int32_t));
+ */
+int
+__dbcl_lock_id_free(dbenv, id)
+	DB_ENV * dbenv;
+	u_int32_t id;
+{
+	COMPQUIET(id, 0);
+	return (__dbcl_rpc_illegal(dbenv, "lock_id_free"));
+}
+
+/*
+ * PUBLIC: int __dbcl_lock_put __P((DB_ENV *, DB_LOCK *));
+ */
+int
+__dbcl_lock_put(dbenv, lock)
+	DB_ENV * dbenv;
+	DB_LOCK * lock;
+{
+	COMPQUIET(lock, 0);
+	return (__dbcl_rpc_illegal(dbenv, "lock_put"));
+}
+
+/*
+ * PUBLIC: int __dbcl_lock_stat __P((DB_ENV *, DB_LOCK_STAT **, u_int32_t));
+ */
+int
+__dbcl_lock_stat(dbenv, statp, flags)
+	DB_ENV * dbenv;
+	DB_LOCK_STAT ** statp;
+	u_int32_t flags;
+{
+	COMPQUIET(statp, 0);
+	COMPQUIET(flags, 0);
+	return (__dbcl_rpc_illegal(dbenv, "lock_stat"));
+}
+
+/*
+ * PUBLIC: int __dbcl_lock_vec __P((DB_ENV *, u_int32_t, u_int32_t,
+ * PUBLIC:      DB_LOCKREQ *, int, DB_LOCKREQ **));
+ */
+int
+__dbcl_lock_vec(dbenv, locker, flags, list, nlist, elistp)
+	DB_ENV * dbenv;
+	u_int32_t locker;
+	u_int32_t flags;
+	DB_LOCKREQ * list;
+	int nlist;
+	DB_LOCKREQ ** elistp;
+{
+	COMPQUIET(locker, 0);
+	COMPQUIET(flags, 0);
+	COMPQUIET(list, 0);
+	COMPQUIET(nlist, 0);
+	COMPQUIET(elistp, 0);
+	return (__dbcl_rpc_illegal(dbenv, "lock_vec"));
+}
+
+/*
+ * PUBLIC: int __dbcl_log_archive __P((DB_ENV *, char ***, u_int32_t));
+ */
+int
+__dbcl_log_archive(dbenv, listp, flags)
+	DB_ENV * dbenv;
+	char *** listp;
+	u_int32_t flags;
+{
+	COMPQUIET(listp, 0);
+	COMPQUIET(flags, 0);
+	return (__dbcl_rpc_illegal(dbenv, "log_archive"));
+}
+
+/*
+ * PUBLIC: int __dbcl_log_cursor __P((DB_ENV *, DB_LOGC **, u_int32_t));
+ */
+int
+__dbcl_log_cursor(dbenv, logcp, flags)
+	DB_ENV * dbenv;
+	DB_LOGC ** logcp;
+	u_int32_t flags;
+{
+	COMPQUIET(logcp, 0);
+	COMPQUIET(flags, 0);
+	return (__dbcl_rpc_illegal(dbenv, "log_cursor"));
+}
+
+/*
+ * PUBLIC: int __dbcl_log_file __P((DB_ENV *, const DB_LSN *, char *, size_t));
+ */
+int
+__dbcl_log_file(dbenv, lsn, namep, len)
+	DB_ENV * dbenv;
+	const DB_LSN * lsn;
+	char * namep;
+	size_t len;
+{
+	COMPQUIET(lsn, NULL);
+	COMPQUIET(namep, NULL);
+	COMPQUIET(len, 0);
+	return (__dbcl_rpc_illegal(dbenv, "log_file"));
+}
+
+/*
+ * PUBLIC: int __dbcl_log_flush __P((DB_ENV *, const DB_LSN *));
+ */
+int
+__dbcl_log_flush(dbenv, lsn)
+	DB_ENV * dbenv;
+	const DB_LSN * lsn;
+{
+	COMPQUIET(lsn, NULL);
+	return (__dbcl_rpc_illegal(dbenv, "log_flush"));
+}
+
+/*
+ * PUBLIC: int __dbcl_log_put __P((DB_ENV *, DB_LSN *, const DBT *,
+ * PUBLIC:      u_int32_t));
+ */
+int
+__dbcl_log_put(dbenv, lsn, data, flags)
+	DB_ENV * dbenv;
+	DB_LSN * lsn;
+	const DBT * data;
+	u_int32_t flags;
+{
+	COMPQUIET(lsn, 0);
+	COMPQUIET(data, NULL);
+	COMPQUIET(flags, 0);
+	return (__dbcl_rpc_illegal(dbenv, "log_put"));
+}
+
+/*
+ * PUBLIC: int __dbcl_log_stat __P((DB_ENV *, DB_LOG_STAT **, u_int32_t));
+ */
+int
+__dbcl_log_stat(dbenv, statp, flags)
+	DB_ENV * dbenv;
+	DB_LOG_STAT ** statp;
+	u_int32_t flags;
+{
+	COMPQUIET(statp, 0);
+	COMPQUIET(flags, 0);
+	return (__dbcl_rpc_illegal(dbenv, "log_stat"));
+}
+
+/*
+ * PUBLIC: int __dbcl_memp_register __P((DB_ENV *, int, int (*)(DB_ENV *,
+ * PUBLIC:      db_pgno_t, void *, DBT *), int (*)(DB_ENV *, db_pgno_t, void *, DBT *)));
+ */
+int
+__dbcl_memp_register(dbenv, ftype, func0, func1)
+	DB_ENV * dbenv;
+	int ftype;
+	int (*func0) __P((DB_ENV *, db_pgno_t, void *, DBT *));
+	int (*func1) __P((DB_ENV *, db_pgno_t, void *, DBT *));
+{
+	COMPQUIET(ftype, 0);
+	COMPQUIET(func0, 0);
+	COMPQUIET(func1, 0);
+	return (__dbcl_rpc_illegal(dbenv, "memp_register"));
+}
+
+/*
+ * PUBLIC: int __dbcl_memp_stat __P((DB_ENV *, DB_MPOOL_STAT **,
+ * PUBLIC:      DB_MPOOL_FSTAT ***, u_int32_t));
+ */
+int
+__dbcl_memp_stat(dbenv, gstatp, fstatp, flags)
+	DB_ENV * dbenv;
+	DB_MPOOL_STAT ** gstatp;
+	DB_MPOOL_FSTAT *** fstatp;
+	u_int32_t flags;
+{
+	COMPQUIET(gstatp, 0);
+	COMPQUIET(fstatp, 0);
+	COMPQUIET(flags, 0);
+	return (__dbcl_rpc_illegal(dbenv, "memp_stat"));
+}
+
+/*
+ * PUBLIC: int __dbcl_memp_sync __P((DB_ENV *, DB_LSN *));
+ */
+int
+__dbcl_memp_sync(dbenv, lsn)
+	DB_ENV * dbenv;
+	DB_LSN * lsn;
+{
+	COMPQUIET(lsn, 0);
+	return (__dbcl_rpc_illegal(dbenv, "memp_sync"));
+}
+
+/*
+ * PUBLIC: int __dbcl_memp_trickle __P((DB_ENV *, int, int *));
+ */
+int
+__dbcl_memp_trickle(dbenv, pct, nwrotep)
+	DB_ENV * dbenv;
+	int pct;
+	int * nwrotep;
+{
+	COMPQUIET(pct, 0);
+	COMPQUIET(nwrotep, 0);
+	return (__dbcl_rpc_illegal(dbenv, "memp_trickle"));
+}
+
+/*
+ * PUBLIC: int __dbcl_memp_fget __P((DB_MPOOLFILE *, u_int32_t *, u_int32_t,
+ * PUBLIC:      void *));
+ */
+int
+__dbcl_memp_fget(dbmfp, pgnoaddr, flags, addrp)
+	DB_MPOOLFILE * dbmfp;
+	u_int32_t * pgnoaddr;
+	u_int32_t flags;
+	void * addrp;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbmfp->dbenv;
+	COMPQUIET(pgnoaddr, 0);
+	COMPQUIET(flags, 0);
+	COMPQUIET(addrp, 0);
+	return (__dbcl_rpc_illegal(dbenv, "memp_fget"));
+}
+
+/*
+ * PUBLIC: int __dbcl_memp_fopen __P((DB_MPOOLFILE *, const char *, u_int32_t,
+ * PUBLIC:      int, size_t));
+ */
+int
+__dbcl_memp_fopen(dbmfp, path, flags, mode, pagesize)
+	DB_MPOOLFILE * dbmfp;
+	const char * path;
+	u_int32_t flags;
+	int mode;
+	size_t pagesize;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbmfp->dbenv;
+	COMPQUIET(path, 0);
+	COMPQUIET(flags, 0);
+	COMPQUIET(mode, 0);
+	COMPQUIET(pagesize, 0);
+	return (__dbcl_rpc_illegal(dbenv, "memp_fopen"));
+}
+
+/*
+ * PUBLIC: int __dbcl_memp_fput __P((DB_MPOOLFILE *, void *, u_int32_t));
+ */
+int
+__dbcl_memp_fput(dbmfp, pgaddr, flags)
+	DB_MPOOLFILE * dbmfp;
+	void * pgaddr;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbmfp->dbenv;
+	COMPQUIET(pgaddr, 0);
+	COMPQUIET(flags, 0);
+	return (__dbcl_rpc_illegal(dbenv, "memp_fput"));
+}
+
+/*
+ * PUBLIC: int __dbcl_memp_fset __P((DB_MPOOLFILE *, void *, u_int32_t));
+ */
+int
+__dbcl_memp_fset(dbmfp, pgaddr, flags)
+	DB_MPOOLFILE * dbmfp;
+	void * pgaddr;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbmfp->dbenv;
+	COMPQUIET(pgaddr, 0);
+	COMPQUIET(flags, 0);
+	return (__dbcl_rpc_illegal(dbenv, "memp_fset"));
+}
+
+/*
+ * PUBLIC: int __dbcl_memp_get_clear_len __P((DB_MPOOLFILE *, u_int32_t *));
+ */
+int
+__dbcl_memp_get_clear_len(dbmfp, clear_lenp)
+	DB_MPOOLFILE * dbmfp;
+	u_int32_t * clear_lenp;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbmfp->dbenv;
+	COMPQUIET(clear_lenp, 0);
+	return (__dbcl_rpc_illegal(dbenv, "memp_get_clear_len"));
+}
+
+/*
+ * PUBLIC: int __dbcl_memp_set_clear_len __P((DB_MPOOLFILE *, u_int32_t));
+ */
+int
+__dbcl_memp_set_clear_len(dbmfp, clear_len)
+	DB_MPOOLFILE * dbmfp;
+	u_int32_t clear_len;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbmfp->dbenv;
+	COMPQUIET(clear_len, 0);
+	return (__dbcl_rpc_illegal(dbenv, "memp_set_clear_len"));
+}
+
+/*
+ * PUBLIC: int __dbcl_memp_get_fileid __P((DB_MPOOLFILE *, u_int8_t *));
+ */
+int
+__dbcl_memp_get_fileid(dbmfp, fileid)
+	DB_MPOOLFILE * dbmfp;
+	u_int8_t * fileid;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbmfp->dbenv;
+	COMPQUIET(fileid, 0);
+	return (__dbcl_rpc_illegal(dbenv, "memp_get_fileid"));
+}
+
+/*
+ * PUBLIC: int __dbcl_memp_set_fileid __P((DB_MPOOLFILE *, u_int8_t *));
+ */
+int
+__dbcl_memp_set_fileid(dbmfp, fileid)
+	DB_MPOOLFILE * dbmfp;
+	u_int8_t * fileid;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbmfp->dbenv;
+	COMPQUIET(fileid, 0);
+	return (__dbcl_rpc_illegal(dbenv, "memp_set_fileid"));
+}
+
+/*
+ * PUBLIC: int __dbcl_memp_get_flags __P((DB_MPOOLFILE *, u_int32_t *));
+ */
+int
+__dbcl_memp_get_flags(dbmfp, flagsp)
+	DB_MPOOLFILE * dbmfp;
+	u_int32_t * flagsp;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbmfp->dbenv;
+	COMPQUIET(flagsp, 0);
+	return (__dbcl_rpc_illegal(dbenv, "memp_get_flags"));
+}
+
+/*
+ * PUBLIC: int __dbcl_memp_set_flags __P((DB_MPOOLFILE *, u_int32_t, int));
+ */
+int
+__dbcl_memp_set_flags(dbmfp, flags, onoff)
+	DB_MPOOLFILE * dbmfp;
+	u_int32_t flags;
+	int onoff;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbmfp->dbenv;
+	COMPQUIET(flags, 0);
+	COMPQUIET(onoff, 0);
+	return (__dbcl_rpc_illegal(dbenv, "memp_set_flags"));
+}
+
+/*
+ * PUBLIC: int __dbcl_memp_get_ftype __P((DB_MPOOLFILE *, int *));
+ */
+int
+__dbcl_memp_get_ftype(dbmfp, ftype)
+	DB_MPOOLFILE * dbmfp;
+	int * ftype;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbmfp->dbenv;
+	COMPQUIET(ftype, 0);
+	return (__dbcl_rpc_illegal(dbenv, "memp_get_ftype"));
+}
+
+/*
+ * PUBLIC: int __dbcl_memp_set_ftype __P((DB_MPOOLFILE *, int));
+ */
+int
+__dbcl_memp_set_ftype(dbmfp, ftype)
+	DB_MPOOLFILE * dbmfp;
+	int ftype;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbmfp->dbenv;
+	COMPQUIET(ftype, 0);
+	return (__dbcl_rpc_illegal(dbenv, "memp_set_ftype"));
+}
+
+/*
+ * PUBLIC: int __dbcl_memp_get_lsn_offset __P((DB_MPOOLFILE *, int32_t *));
+ */
+int
+__dbcl_memp_get_lsn_offset(dbmfp, lsn_offsetp)
+	DB_MPOOLFILE * dbmfp;
+	int32_t * lsn_offsetp;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbmfp->dbenv;
+	COMPQUIET(lsn_offsetp, 0);
+	return (__dbcl_rpc_illegal(dbenv, "memp_get_lsn_offset"));
+}
+
+/*
+ * PUBLIC: int __dbcl_memp_set_lsn_offset __P((DB_MPOOLFILE *, int32_t));
+ */
+int
+__dbcl_memp_set_lsn_offset(dbmfp, lsn_offset)
+	DB_MPOOLFILE * dbmfp;
+	int32_t lsn_offset;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbmfp->dbenv;
+	COMPQUIET(lsn_offset, 0);
+	return (__dbcl_rpc_illegal(dbenv, "memp_set_lsn_offset"));
+}
+
+/*
+ * PUBLIC: int __dbcl_memp_get_maxsize __P((DB_MPOOLFILE *, u_int32_t *,
+ * PUBLIC:      u_int32_t *));
+ */
+int
+__dbcl_memp_get_maxsize(dbmfp, gbytesp, bytesp)
+	DB_MPOOLFILE * dbmfp;
+	u_int32_t * gbytesp;
+	u_int32_t * bytesp;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbmfp->dbenv;
+	COMPQUIET(gbytesp, 0);
+	COMPQUIET(bytesp, 0);
+	return (__dbcl_rpc_illegal(dbenv, "memp_get_maxsize"));
+}
+
+/*
+ * PUBLIC: int __dbcl_memp_set_maxsize __P((DB_MPOOLFILE *, u_int32_t,
+ * PUBLIC:      u_int32_t));
+ */
+int
+__dbcl_memp_set_maxsize(dbmfp, gbytes, bytes)
+	DB_MPOOLFILE * dbmfp;
+	u_int32_t gbytes;
+	u_int32_t bytes;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbmfp->dbenv;
+	COMPQUIET(gbytes, 0);
+	COMPQUIET(bytes, 0);
+	return (__dbcl_rpc_illegal(dbenv, "memp_set_maxsize"));
+}
+
+/*
+ * PUBLIC: int __dbcl_memp_get_pgcookie __P((DB_MPOOLFILE *, DBT *));
+ */
+int
+__dbcl_memp_get_pgcookie(dbmfp, pgcookie)
+	DB_MPOOLFILE * dbmfp;
+	DBT * pgcookie;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbmfp->dbenv;
+	COMPQUIET(pgcookie, 0);
+	return (__dbcl_rpc_illegal(dbenv, "memp_get_pgcookie"));
+}
+
+/*
+ * PUBLIC: int __dbcl_memp_set_pgcookie __P((DB_MPOOLFILE *, DBT *));
+ */
+int
+__dbcl_memp_set_pgcookie(dbmfp, pgcookie)
+	DB_MPOOLFILE * dbmfp;
+	DBT * pgcookie;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbmfp->dbenv;
+	COMPQUIET(pgcookie, 0);
+	return (__dbcl_rpc_illegal(dbenv, "memp_set_pgcookie"));
+}
+
+/*
+ * PUBLIC: int __dbcl_memp_get_priority __P((DB_MPOOLFILE *,
+ * PUBLIC:      DB_CACHE_PRIORITY *));
+ */
+int
+__dbcl_memp_get_priority(dbmfp, priorityp)
+	DB_MPOOLFILE * dbmfp;
+	DB_CACHE_PRIORITY * priorityp;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbmfp->dbenv;
+	COMPQUIET(priorityp, 0);
+	return (__dbcl_rpc_illegal(dbenv, "memp_get_priority"));
+}
+
+/*
+ * PUBLIC: int __dbcl_memp_set_priority __P((DB_MPOOLFILE *,
+ * PUBLIC:      DB_CACHE_PRIORITY));
+ */
+int
+__dbcl_memp_set_priority(dbmfp, priority)
+	DB_MPOOLFILE * dbmfp;
+	DB_CACHE_PRIORITY priority;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbmfp->dbenv;
+	COMPQUIET(priority, 0);
+	return (__dbcl_rpc_illegal(dbenv, "memp_set_priority"));
+}
+
+/*
+ * PUBLIC: int __dbcl_memp_fsync __P((DB_MPOOLFILE *));
+ */
+int
+__dbcl_memp_fsync(dbmfp)
+	DB_MPOOLFILE * dbmfp;
+{
+	DB_ENV *dbenv;
+
+	dbenv = dbmfp->dbenv;
+	return (__dbcl_rpc_illegal(dbenv, "memp_fsync"));
+}
+
diff --git a/storage/bdb/rpc_client/gen_client_ret.c b/storage/bdb/rpc_client/gen_client_ret.c
index f35589738cd5a9c72df50c4d76bdd9473d39c879..7285afc25620aa35f24ee457996f9a7b8a86632f 100644
--- a/storage/bdb/rpc_client/gen_client_ret.c
+++ b/storage/bdb/rpc_client/gen_client_ret.c
@@ -1,17 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2000-2002
+ * Copyright (c) 2000-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: gen_client_ret.c,v 1.69 2004/09/22 16:29:51 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: gen_client_ret.c,v 1.57 2002/08/06 06:18:37 bostic Exp $";
-#endif /* not lint */
-
-#ifdef HAVE_RPC
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -20,35 +17,20 @@ static const char revid[] = "$Id: gen_client_ret.c,v 1.57 2002/08/06 06:18:37 bo
 #include <string.h>
 #endif
 
+#include "db_server.h"
+
 #include "db_int.h"
 #include "dbinc/db_page.h"
 #include "dbinc/db_am.h"
 #include "dbinc/txn.h"
-
-#include "dbinc_auto/db_server.h"
 #include "dbinc_auto/rpc_client_ext.h"
 
-/*
- * PUBLIC: int __dbcl_env_close_ret
- * PUBLIC:     __P((DB_ENV *, u_int32_t, __env_close_reply *));
- */
-int
-__dbcl_env_close_ret(dbenv, flags, replyp)
-	DB_ENV *dbenv;
-	u_int32_t flags;
-	__env_close_reply *replyp;
-{
-	int ret;
-
-	COMPQUIET(flags, 0);
-
-	ret = __dbcl_refresh(dbenv);
-	__os_free(NULL, dbenv);
-	if (replyp->status == 0 && ret != 0)
-		return (ret);
-	else
-		return (replyp->status);
-}
+#define	FREE_IF_CHANGED(dbtp, orig)	do {				\
+	if ((dbtp)->data != NULL && (dbtp)->data != orig) {		\
+		__os_free(dbenv, (dbtp)->data);				\
+		(dbtp)->data = NULL;					\
+	}								\
+} while (0)
 
 /*
  * PUBLIC: int __dbcl_env_create_ret
@@ -167,7 +149,13 @@ __dbcl_txn_begin_ret(envp, parent, txnpp, flags, replyp)
 
 	if ((ret = __os_calloc(envp, 1, sizeof(DB_TXN), &txn)) != 0)
 		return (ret);
-	__dbcl_txn_setup(envp, txn, parent, replyp->txnidcl_id);
+	/*
+	 * !!!
+	 * Cast the txnidcl_id to 32-bits.  We don't want to change the
+	 * size of the txn structure.  But if we're running on 64-bit
+	 * machines, we could overflow.  Ignore for now.
+	 */
+	__dbcl_txn_setup(envp, txn, parent, (u_int32_t)replyp->txnidcl_id);
 	*txnpp = txn;
 	return (replyp->status);
 }
@@ -249,7 +237,7 @@ __dbcl_txn_recover_ret(dbenv, preplist, count, retp, flags, replyp)
 	while (i++ < replyp->retcount) {
 		__dbcl_txn_setup(dbenv, txn, NULL, *txnid);
 		prep->txn = txn;
-		memcpy(&prep->gid, gid, DB_XIDDATASIZE);
+		memcpy(prep->gid, gid, DB_XIDDATASIZE);
 		/*
 		 * Now increment all our array pointers.
 		 */
@@ -341,8 +329,8 @@ __dbcl_db_get_ret(dbp, txnp, key, data, flags, replyp)
 	 * If an error on copying 'data' and we allocated for 'key'
 	 * free it before returning the error.
 	 */
-	if (ret && oldkey != NULL)
-		__os_free(dbenv, key->data);
+	if (ret)
+		FREE_IF_CHANGED(key, oldkey);
 	return (ret);
 }
 
@@ -389,13 +377,13 @@ __dbcl_db_open_ret(dbp, txn, name, subdb, type, flags, mode, replyp)
 	COMPQUIET(txn, NULL);
 	COMPQUIET(name, NULL);
 	COMPQUIET(subdb, NULL);
-	COMPQUIET(type, 0);
+	COMPQUIET(type, DB_UNKNOWN);
 	COMPQUIET(flags, 0);
 	COMPQUIET(mode, 0);
 
 	if (replyp->status == 0) {
 		dbp->cl_id = replyp->dbcl_id;
-		dbp->type = replyp->type;
+		dbp->type = (DBTYPE)replyp->type;
 		/*
 		 * We get back the database's byteorder on the server.
 		 * Determine if our byteorder is the same or not by
@@ -409,11 +397,10 @@ __dbcl_db_open_ret(dbp, txn, name, subdb, type, flags, mode, replyp)
 		(void)__db_set_lorder(dbp, replyp->lorder);
 
 		/*
-		 * XXX
-		 * This is only for Tcl which peeks at the dbp flags.
-		 * When dbp->get_flags exists, this should go away.
+		 * Explicitly set DB_AM_OPEN_CALLED since open is now
+		 * successfully completed.
 		 */
-		dbp->flags = replyp->dbflags;
+		F_SET(dbp, DB_AM_OPEN_CALLED);
 	}
 	return (replyp->status);
 }
@@ -453,25 +440,17 @@ __dbcl_db_pget_ret(dbp, txnp, skey, pkey, data, flags, replyp)
 		return (ret);
 
 	oldpkey = pkey->data;
-	ret = __dbcl_retcopy(dbenv, pkey, replyp->pkeydata.pkeydata_val,
+	if ((ret = __dbcl_retcopy(dbenv, pkey, replyp->pkeydata.pkeydata_val,
 	    replyp->pkeydata.pkeydata_len, &dbp->my_rkey.data,
-	    &dbp->my_rkey.ulen);
-	if (ret && oldskey != NULL) {
-		__os_free(dbenv, skey->data);
-		return (ret);
-	}
+	    &dbp->my_rkey.ulen)) != 0)
+		goto err;
 	ret = __dbcl_retcopy(dbenv, data, replyp->datadata.datadata_val,
 	    replyp->datadata.datadata_len, &dbp->my_rdata.data,
 	    &dbp->my_rdata.ulen);
-	/*
-	 * If an error on copying 'data' and we allocated for '*key'
-	 * free it before returning the error.
-	 */
+
 	if (ret) {
-		if (oldskey != NULL)
-			__os_free(dbenv, skey->data);
-		if (oldpkey != NULL)
-			__os_free(dbenv, pkey->data);
+err:		FREE_IF_CHANGED(skey, oldskey);
+		FREE_IF_CHANGED(pkey, oldpkey);
 	}
 	return (ret);
 }
@@ -554,19 +533,22 @@ __dbcl_db_rename_ret(dbp, name, subdb, newname, flags, replyp)
 
 /*
  * PUBLIC: int __dbcl_db_stat_ret
- * PUBLIC:     __P((DB *, void *, u_int32_t, __db_stat_reply *));
+ * PUBLIC:     __P((DB *, DB_TXN *, void *, u_int32_t, __db_stat_reply *));
  */
 int
-__dbcl_db_stat_ret(dbp, sp, flags, replyp)
+__dbcl_db_stat_ret(dbp, txnp, sp, flags, replyp)
 	DB *dbp;
+	DB_TXN *txnp;
 	void *sp;
 	u_int32_t flags;
 	__db_stat_reply *replyp;
 {
-	int len, ret;
+	size_t len;
 	u_int32_t i, *q, *p, *retsp;
+	int ret;
 
 	COMPQUIET(flags, 0);
+	COMPQUIET(txnp, NULL);
 
 	if (replyp->status != 0 || sp == NULL)
 		return (replyp->status);
@@ -738,8 +720,8 @@ __dbcl_dbc_get_ret(dbc, key, data, flags, replyp)
 	 * If an error on copying 'data' and we allocated for 'key'
 	 * free it before returning the error.
 	 */
-	if (ret && oldkey != NULL)
-		__os_free(dbenv, key->data);
+	if (ret)
+		FREE_IF_CHANGED(key, oldkey);
 	return (ret);
 }
 
@@ -776,25 +758,21 @@ __dbcl_dbc_pget_ret(dbc, skey, pkey, data, flags, replyp)
 		return (ret);
 
 	oldpkey = pkey->data;
-	ret = __dbcl_retcopy(dbenv, pkey, replyp->pkeydata.pkeydata_val,
+	if ((ret = __dbcl_retcopy(dbenv, pkey, replyp->pkeydata.pkeydata_val,
 	    replyp->pkeydata.pkeydata_len, &dbc->my_rkey.data,
-	    &dbc->my_rkey.ulen);
-	if (ret && oldskey != NULL) {
-		__os_free(dbenv, skey->data);
-		return (ret);
-	}
+	    &dbc->my_rkey.ulen)) != 0)
+		goto err;
 	ret = __dbcl_retcopy(dbenv, data, replyp->datadata.datadata_val,
 	    replyp->datadata.datadata_len, &dbc->my_rdata.data,
 	    &dbc->my_rdata.ulen);
+
 	/*
 	 * If an error on copying 'data' and we allocated for '*key'
 	 * free it before returning the error.
 	 */
 	if (ret) {
-		if (oldskey != NULL)
-			__os_free(dbenv, skey->data);
-		if (oldpkey != NULL)
-			__os_free(dbenv, pkey->data);
+err:		FREE_IF_CHANGED(skey, oldskey);
+		FREE_IF_CHANGED(pkey, oldpkey);
 	}
 	return (ret);
 }
@@ -821,4 +799,3 @@ __dbcl_dbc_put_ret(dbc, key, data, flags, replyp)
 		    *(db_recno_t *)replyp->keydata.keydata_val;
 	return (replyp->status);
 }
-#endif /* HAVE_RPC */
diff --git a/storage/bdb/rpc_server/c/db_server_proc.c b/storage/bdb/rpc_server/c/db_server_proc.c
new file mode 100644
index 0000000000000000000000000000000000000000..1793df42f001853190127b48d77cd5f8d8d2e84d
--- /dev/null
+++ b/storage/bdb/rpc_server/c/db_server_proc.c
@@ -0,0 +1,2710 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2000-2004
+ *      Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_server_proc.c,v 1.106 2004/09/22 17:30:12 bostic Exp $
+ */
+
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <rpc/rpc.h>
+
+#include <string.h>
+#endif
+
+#include "db_server.h"
+
+#include "db_int.h"
+#include "dbinc/db_server_int.h"
+#include "dbinc_auto/rpc_server_ext.h"
+
+/*
+ * PUBLIC: void __env_get_cachesize_proc __P((long,
+ * PUBLIC:      __env_get_cachesize_reply *));
+ */
+void
+__env_get_cachesize_proc(dbenvcl_id, replyp)
+	long dbenvcl_id;
+	__env_get_cachesize_reply *replyp;
+{
+	DB_ENV *dbenv;
+	ct_entry *dbenv_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+	replyp->status = dbenv->get_cachesize(dbenv, &replyp->gbytes,
+	    &replyp->bytes, (int *)&replyp->ncache);
+}
+
+/*
+ * PUBLIC: void __env_cachesize_proc __P((long, u_int32_t, u_int32_t,
+ * PUBLIC:      u_int32_t, __env_cachesize_reply *));
+ */
+void
+__env_cachesize_proc(dbenvcl_id, gbytes, bytes, ncache, replyp)
+	long dbenvcl_id;
+	u_int32_t gbytes;
+	u_int32_t bytes;
+	u_int32_t ncache;
+	__env_cachesize_reply *replyp;
+{
+	DB_ENV *dbenv;
+	ct_entry *dbenv_ctp;
+	int ret;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+	ret = dbenv->set_cachesize(dbenv, gbytes, bytes, ncache);
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __env_close_proc __P((long, u_int32_t, __env_close_reply *));
+ */
+void
+__env_close_proc(dbenvcl_id, flags, replyp)
+	long dbenvcl_id;
+	u_int32_t flags;
+	__env_close_reply *replyp;
+{
+	ct_entry *dbenv_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	replyp->status = __dbenv_close_int(dbenvcl_id, flags, 0);
+	return;
+}
+
+/*
+ * PUBLIC: void __env_create_proc __P((u_int32_t, __env_create_reply *));
+ */
+void
+__env_create_proc(timeout, replyp)
+	u_int32_t timeout;
+	__env_create_reply *replyp;
+{
+	DB_ENV *dbenv;
+	ct_entry *ctp;
+	int ret;
+
+	ctp = new_ct_ent(&replyp->status);
+	if (ctp == NULL)
+		return;
+	if ((ret = db_env_create(&dbenv, 0)) == 0) {
+		ctp->ct_envp = dbenv;
+		ctp->ct_type = CT_ENV;
+		ctp->ct_parent = NULL;
+		ctp->ct_envparent = ctp;
+		__dbsrv_settimeout(ctp, timeout);
+		__dbsrv_active(ctp);
+		replyp->envcl_id = ctp->ct_id;
+	} else
+		__dbclear_ctp(ctp);
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __env_dbremove_proc __P((long, long, char *, char *, u_int32_t,
+ * PUBLIC:      __env_dbremove_reply *));
+ */
+void
+__env_dbremove_proc(dbenvcl_id, txnpcl_id, name, subdb, flags, replyp)
+	long dbenvcl_id;
+	long txnpcl_id;
+	char *name;
+	char *subdb;
+	u_int32_t flags;
+	__env_dbremove_reply *replyp;
+{
+	int ret;
+	DB_ENV * dbenv;
+	ct_entry *dbenv_ctp;
+	DB_TXN * txnp;
+	ct_entry *txnp_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+	if (txnpcl_id != 0) {
+		ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+		txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+	} else
+		txnp = NULL;
+
+	ret = dbenv->dbremove(dbenv, txnp, name, subdb, flags);
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __env_dbrename_proc __P((long, long, char *, char *, char *,
+ * PUBLIC:      u_int32_t, __env_dbrename_reply *));
+ */
+void
+__env_dbrename_proc(dbenvcl_id, txnpcl_id, name, subdb, newname, flags, replyp)
+	long dbenvcl_id;
+	long txnpcl_id;
+	char *name;
+	char *subdb;
+	char *newname;
+	u_int32_t flags;
+	__env_dbrename_reply *replyp;
+{
+	int ret;
+	DB_ENV * dbenv;
+	ct_entry *dbenv_ctp;
+	DB_TXN * txnp;
+	ct_entry *txnp_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+	if (txnpcl_id != 0) {
+		ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+		txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+	} else
+		txnp = NULL;
+
+	ret = dbenv->dbrename(dbenv, txnp, name, subdb, newname, flags);
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __env_get_encrypt_flags_proc __P((long,
+ * PUBLIC:      __env_get_encrypt_flags_reply *));
+ */
+void
+__env_get_encrypt_flags_proc(dbenvcl_id, replyp)
+	long dbenvcl_id;
+	__env_get_encrypt_flags_reply *replyp;
+{
+	DB_ENV *dbenv;
+	ct_entry *dbenv_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+	replyp->status = dbenv->get_encrypt_flags(dbenv, &replyp->flags);
+}
+
+/*
+ * PUBLIC: void __env_encrypt_proc __P((long, char *, u_int32_t,
+ * PUBLIC:      __env_encrypt_reply *));
+ */
+void
+__env_encrypt_proc(dbenvcl_id, passwd, flags, replyp)
+	long dbenvcl_id;
+	char *passwd;
+	u_int32_t flags;
+	__env_encrypt_reply *replyp;
+{
+	int ret;
+	DB_ENV * dbenv;
+	ct_entry *dbenv_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+	ret = dbenv->set_encrypt(dbenv, passwd, flags);
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __env_get_flags_proc __P((long, __env_get_flags_reply *));
+ */
+void
+__env_get_flags_proc(dbenvcl_id, replyp)
+	long dbenvcl_id;
+	__env_get_flags_reply *replyp;
+{
+	DB_ENV *dbenv;
+	ct_entry *dbenv_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+	replyp->status = dbenv->get_flags(dbenv, &replyp->flags);
+}
+
+/*
+ * PUBLIC: void __env_flags_proc __P((long, u_int32_t, u_int32_t,
+ * PUBLIC:      __env_flags_reply *));
+ */
+void
+__env_flags_proc(dbenvcl_id, flags, onoff, replyp)
+	long dbenvcl_id;
+	u_int32_t flags;
+	u_int32_t onoff;
+	__env_flags_reply *replyp;
+{
+	DB_ENV *dbenv;
+	ct_entry *dbenv_ctp;
+	int ret;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+	ret = dbenv->set_flags(dbenv, flags, onoff);
+	if (onoff)
+		dbenv_ctp->ct_envdp.onflags = flags;
+	else
+		dbenv_ctp->ct_envdp.offflags = flags;
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __env_get_home_proc __P((long, __env_get_home_reply *));
+ */
+void
+__env_get_home_proc(dbenvcl_id, replyp)
+	long dbenvcl_id;
+	__env_get_home_reply *replyp;
+{
+	DB_ENV *dbenv;
+	ct_entry *dbenv_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+	replyp->status = dbenv->get_home(dbenv,
+	    (const char **)&replyp->home);
+}
+
+/*
+ * PUBLIC: void __env_get_open_flags_proc __P((long,
+ * PUBLIC:      __env_get_open_flags_reply *));
+ */
+void
+__env_get_open_flags_proc(dbenvcl_id, replyp)
+	long dbenvcl_id;
+	__env_get_open_flags_reply *replyp;
+{
+	DB_ENV *dbenv;
+	ct_entry *dbenv_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+	replyp->status = dbenv->get_open_flags(dbenv, &replyp->flags);
+}
+
+/*
+ * PUBLIC: void __env_open_proc __P((long, char *, u_int32_t, u_int32_t,
+ * PUBLIC:      __env_open_reply *));
+ */
+void
+__env_open_proc(dbenvcl_id, home, flags, mode, replyp)
+	long dbenvcl_id;
+	char *home;
+	u_int32_t flags;
+	u_int32_t mode;
+	__env_open_reply *replyp;
+{
+	DB_ENV *dbenv;
+	ct_entry *dbenv_ctp, *new_ctp;
+	u_int32_t newflags, shareflags;
+	int ret;
+	home_entry *fullhome;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+	fullhome = get_fullhome(home);
+	if (fullhome == NULL) {
+		ret = DB_NOSERVER_HOME;
+		goto out;
+	}
+
+	/*
+	 * If they are using locking do deadlock detection for them,
+	 * internally.
+	 */
+	if ((flags & DB_INIT_LOCK) &&
+	    (ret = dbenv->set_lk_detect(dbenv, DB_LOCK_DEFAULT)) != 0)
+		goto out;
+
+	if (__dbsrv_verbose) {
+		dbenv->set_errfile(dbenv, stderr);
+		dbenv->set_errpfx(dbenv, fullhome->home);
+	}
+
+	/*
+	 * Mask off flags we ignore
+	 */
+	newflags = (flags & ~DB_SERVER_FLAGMASK);
+	shareflags = (newflags & DB_SERVER_ENVFLAGS);
+	/*
+	 * Check now whether we can share a handle for this env.
+	 */
+	replyp->envcl_id = dbenvcl_id;
+	if ((new_ctp = __dbsrv_shareenv(dbenv_ctp, fullhome, shareflags))
+	    != NULL) {
+		/*
+		 * We can share, clean up old  ID, set new one.
+		 */
+		if (__dbsrv_verbose)
+			printf("Sharing env ID %ld\n", new_ctp->ct_id);
+		replyp->envcl_id = new_ctp->ct_id;
+		ret = __dbenv_close_int(dbenvcl_id, 0, 0);
+	} else {
+		ret = dbenv->open(dbenv, fullhome->home, newflags, mode);
+		dbenv_ctp->ct_envdp.home = fullhome;
+		dbenv_ctp->ct_envdp.envflags = shareflags;
+	}
+out:	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __env_remove_proc __P((long, char *, u_int32_t,
+ * PUBLIC:      __env_remove_reply *));
+ */
+void
+__env_remove_proc(dbenvcl_id, home, flags, replyp)
+	long dbenvcl_id;
+	char *home;
+	u_int32_t flags;
+	__env_remove_reply *replyp;
+{
+	DB_ENV *dbenv;
+	ct_entry *dbenv_ctp;
+	int ret;
+	home_entry *fullhome;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+	fullhome = get_fullhome(home);
+	if (fullhome == NULL) {
+		replyp->status = DB_NOSERVER_HOME;
+		return;
+	}
+
+	ret = dbenv->remove(dbenv, fullhome->home, flags);
+	__dbdel_ctp(dbenv_ctp);
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __txn_abort_proc __P((long, __txn_abort_reply *));
+ */
+void
+__txn_abort_proc(txnpcl_id, replyp)
+	long txnpcl_id;
+	__txn_abort_reply *replyp;
+{
+	DB_TXN *txnp;
+	ct_entry *txnp_ctp;
+	int ret;
+
+	ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+	txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+
+	ret = txnp->abort(txnp);
+	__dbdel_ctp(txnp_ctp);
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __txn_begin_proc __P((long, long, u_int32_t,
+ * PUBLIC:      __txn_begin_reply *));
+ */
+void
+__txn_begin_proc(dbenvcl_id, parentcl_id, flags, replyp)
+	long dbenvcl_id;
+	long parentcl_id;
+	u_int32_t flags;
+	__txn_begin_reply *replyp;
+{
+	DB_ENV *dbenv;
+	DB_TXN *parent, *txnp;
+	ct_entry *ctp, *dbenv_ctp, *parent_ctp;
+	int ret;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+	parent_ctp = NULL;
+
+	ctp = new_ct_ent(&replyp->status);
+	if (ctp == NULL)
+		return;
+
+	if (parentcl_id != 0) {
+		ACTIVATE_CTP(parent_ctp, parentcl_id, CT_TXN);
+		parent = (DB_TXN *)parent_ctp->ct_anyp;
+		ctp->ct_activep = parent_ctp->ct_activep;
+	} else
+		parent = NULL;
+
+	/*
+	 * Need to set DB_TXN_NOWAIT or the RPC server may deadlock
+	 * itself and no one can break the lock.
+	 */
+	ret = dbenv->txn_begin(dbenv, parent, &txnp, flags | DB_TXN_NOWAIT);
+	if (ret == 0) {
+		ctp->ct_txnp = txnp;
+		ctp->ct_type = CT_TXN;
+		ctp->ct_parent = parent_ctp;
+		ctp->ct_envparent = dbenv_ctp;
+		replyp->txnidcl_id = ctp->ct_id;
+		__dbsrv_settimeout(ctp, dbenv_ctp->ct_timeout);
+		__dbsrv_active(ctp);
+	} else
+		__dbclear_ctp(ctp);
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __txn_commit_proc __P((long, u_int32_t,
+ * PUBLIC:      __txn_commit_reply *));
+ */
+void
+__txn_commit_proc(txnpcl_id, flags, replyp)
+	long txnpcl_id;
+	u_int32_t flags;
+	__txn_commit_reply *replyp;
+{
+	DB_TXN *txnp;
+	ct_entry *txnp_ctp;
+	int ret;
+
+	ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+	txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+
+	ret = txnp->commit(txnp, flags);
+	__dbdel_ctp(txnp_ctp);
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __txn_discard_proc __P((long, u_int32_t,
+ * PUBLIC:      __txn_discard_reply *));
+ */
+void
+__txn_discard_proc(txnpcl_id, flags, replyp)
+	long txnpcl_id;
+	u_int32_t flags;
+	__txn_discard_reply *replyp;
+{
+	DB_TXN *txnp;
+	ct_entry *txnp_ctp;
+	int ret;
+
+	ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+	txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+
+	ret = txnp->discard(txnp, flags);
+	__dbdel_ctp(txnp_ctp);
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __txn_prepare_proc __P((long, u_int8_t *,
+ * PUBLIC:      __txn_prepare_reply *));
+ */
+void
+__txn_prepare_proc(txnpcl_id, gid, replyp)
+	long txnpcl_id;
+	u_int8_t *gid;
+	__txn_prepare_reply *replyp;
+{
+	DB_TXN *txnp;
+	ct_entry *txnp_ctp;
+	int ret;
+
+	ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+	txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+
+	ret = txnp->prepare(txnp, gid);
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __txn_recover_proc __P((long, u_int32_t, u_int32_t,
+ * PUBLIC:      __txn_recover_reply *, int *));
+ */
+void
+__txn_recover_proc(dbenvcl_id, count, flags, replyp, freep)
+	long dbenvcl_id;
+	u_int32_t count;
+	u_int32_t flags;
+	__txn_recover_reply *replyp;
+	int * freep;
+{
+	DB_ENV *dbenv;
+	DB_PREPLIST *dbprep, *p;
+	ct_entry *dbenv_ctp, *ctp;
+	long erri, i, retcount;
+	u_int32_t *txnidp;
+	int ret;
+	u_int8_t *gid;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+	dbprep = NULL;
+	*freep = 0;
+
+	if ((ret =
+	    __os_malloc(dbenv, count * sizeof(DB_PREPLIST), &dbprep)) != 0)
+		goto out;
+	if ((ret =
+	    dbenv->txn_recover(dbenv, dbprep, count, &retcount, flags)) != 0)
+		goto out;
+	/*
+	 * If there is nothing, success, but it's easy.
+	 */
+	replyp->retcount = retcount;
+	if (retcount == 0) {
+		replyp->txn.txn_val = NULL;
+		replyp->txn.txn_len = 0;
+		replyp->gid.gid_val = NULL;
+		replyp->gid.gid_len = 0;
+	}
+
+	/*
+	 * We have our txn list.  Now we need to allocate the space for
+	 * the txn ID array and the GID array and set them up.
+	 */
+	if ((ret = __os_calloc(dbenv, retcount, sizeof(u_int32_t),
+	    &replyp->txn.txn_val)) != 0)
+		goto out;
+	replyp->txn.txn_len = retcount * sizeof(u_int32_t);
+	if ((ret = __os_calloc(dbenv, retcount, DB_XIDDATASIZE,
+	    &replyp->gid.gid_val)) != 0) {
+		__os_free(dbenv, replyp->txn.txn_val);
+		goto out;
+	}
+	replyp->gid.gid_len = retcount * DB_XIDDATASIZE;
+
+	/*
+	 * Now walk through our results, creating parallel arrays
+	 * to send back.  For each entry we need to create a new
+	 * txn ctp and then fill in the array info.
+	 */
+	i = 0;
+	p = dbprep;
+	gid = replyp->gid.gid_val;
+	txnidp = replyp->txn.txn_val;
+	while (i++ < retcount) {
+		ctp = new_ct_ent(&ret);
+		if (ret != 0) {
+			i--;
+			goto out2;
+		}
+		ctp->ct_txnp = p->txn;
+		ctp->ct_type = CT_TXN;
+		ctp->ct_parent = NULL;
+		ctp->ct_envparent = dbenv_ctp;
+		__dbsrv_settimeout(ctp, dbenv_ctp->ct_timeout);
+		__dbsrv_active(ctp);
+
+		*txnidp = ctp->ct_id;
+		memcpy(gid, p->gid, DB_XIDDATASIZE);
+
+		p++;
+		txnidp++;
+		gid += DB_XIDDATASIZE;
+	}
+	/*
+	 * If we get here, we have success and we have to set freep
+	 * so it'll get properly freed next time.
+	 */
+	*freep = 1;
+out:
+	if (dbprep != NULL)
+		__os_free(dbenv, dbprep);
+	replyp->status = ret;
+	return;
+out2:
+	/*
+	 * We had an error in the middle of creating our new txn
+	 * ct entries.  We have to unwind all that we have done.  Ugh.
+	 */
+	for (txnidp = replyp->txn.txn_val, erri = 0;
+	    erri < i; erri++, txnidp++) {
+		ctp = get_tableent(*txnidp);
+		__dbclear_ctp(ctp);
+	}
+	__os_free(dbenv, replyp->txn.txn_val);
+	__os_free(dbenv, replyp->gid.gid_val);
+	__os_free(dbenv, dbprep);
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __db_bt_maxkey_proc __P((long, u_int32_t,
+ * PUBLIC:      __db_bt_maxkey_reply *));
+ */
+void
+__db_bt_maxkey_proc(dbpcl_id, maxkey, replyp)
+	long dbpcl_id;
+	u_int32_t maxkey;
+	__db_bt_maxkey_reply *replyp;
+{
+	DB *dbp;
+	ct_entry *dbp_ctp;
+	int ret;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	ret = dbp->set_bt_maxkey(dbp, maxkey);
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __db_associate_proc __P((long, long, long, u_int32_t,
+ * PUBLIC:      __db_associate_reply *));
+ */
+void
+__db_associate_proc(dbpcl_id, txnpcl_id, sdbpcl_id, flags, replyp)
+	long dbpcl_id;
+	long txnpcl_id;
+	long sdbpcl_id;
+	u_int32_t flags;
+	__db_associate_reply *replyp;
+{
+	DB *dbp, *sdbp;
+	DB_TXN *txnp;
+	ct_entry *dbp_ctp, *sdbp_ctp, *txnp_ctp;
+	int ret;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+	ACTIVATE_CTP(sdbp_ctp, sdbpcl_id, CT_DB);
+	sdbp = (DB *)sdbp_ctp->ct_anyp;
+	if (txnpcl_id != 0) {
+		ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+		txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+	} else
+		txnp = NULL;
+
+	/*
+	 * We do not support DB_CREATE for associate or the callbacks
+	 * implemented in the Java and JE RPC servers.   Users can only
+	 * access secondary indices on a read-only basis, so whatever they
+	 * are looking for needs to be there already.
+	 */
+#ifdef CONFIG_TEST
+	if (LF_ISSET(DB_RPC2ND_MASK | DB_CREATE))
+#else
+	if (LF_ISSET(DB_CREATE))
+#endif
+		ret = EINVAL;
+	else
+		ret = dbp->associate(dbp, txnp, sdbp, NULL, flags);
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __db_get_bt_minkey_proc __P((long,
+ * PUBLIC:      __db_get_bt_minkey_reply *));
+ */
+void
+__db_get_bt_minkey_proc(dbpcl_id, replyp)
+	long dbpcl_id;
+	__db_get_bt_minkey_reply *replyp;
+{
+	DB *dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	replyp->status = dbp->get_bt_minkey(dbp, &replyp->minkey);
+}
+
+/*
+ * PUBLIC: void __db_bt_minkey_proc __P((long, u_int32_t,
+ * PUBLIC:      __db_bt_minkey_reply *));
+ */
+void
+__db_bt_minkey_proc(dbpcl_id, minkey, replyp)
+	long dbpcl_id;
+	u_int32_t minkey;
+	__db_bt_minkey_reply *replyp;
+{
+	DB *dbp;
+	ct_entry *dbp_ctp;
+	int ret;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	ret = dbp->set_bt_minkey(dbp, minkey);
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __db_close_proc __P((long, u_int32_t, __db_close_reply *));
+ */
+void
+__db_close_proc(dbpcl_id, flags, replyp)
+	long dbpcl_id;
+	u_int32_t flags;
+	__db_close_reply *replyp;
+{
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	replyp->status = __db_close_int(dbpcl_id, flags);
+	return;
+}
+
+/*
+ * PUBLIC: void __db_create_proc __P((long, u_int32_t, __db_create_reply *));
+ */
+void
+__db_create_proc(dbenvcl_id, flags, replyp)
+	long dbenvcl_id;
+	u_int32_t flags;
+	__db_create_reply *replyp;
+{
+	DB *dbp;
+	DB_ENV *dbenv;
+	ct_entry *dbenv_ctp, *dbp_ctp;
+	int ret;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DB_ENV *)dbenv_ctp->ct_anyp;
+
+	dbp_ctp = new_ct_ent(&replyp->status);
+	if (dbp_ctp == NULL)
+		return ;
+	/*
+	 * We actually require env's for databases.  The client should
+	 * have caught it, but just in case.
+	 */
+	DB_ASSERT(dbenv != NULL);
+	if ((ret = db_create(&dbp, dbenv, flags)) == 0) {
+		dbp_ctp->ct_dbp = dbp;
+		dbp_ctp->ct_type = CT_DB;
+		dbp_ctp->ct_parent = dbenv_ctp;
+		dbp_ctp->ct_envparent = dbenv_ctp;
+		replyp->dbcl_id = dbp_ctp->ct_id;
+	} else
+		__dbclear_ctp(dbp_ctp);
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __db_del_proc __P((long, long, u_int32_t, u_int32_t, u_int32_t,
+ * PUBLIC:      u_int32_t, void *, u_int32_t, u_int32_t, __db_del_reply *));
+ */
+void
+__db_del_proc(dbpcl_id, txnpcl_id, keydlen, keydoff, keyulen, keyflags,
+    keydata, keysize, flags, replyp)
+	long dbpcl_id;
+	long txnpcl_id;
+	u_int32_t keydlen;
+	u_int32_t keydoff;
+	u_int32_t keyulen;
+	u_int32_t keyflags;
+	void *keydata;
+	u_int32_t keysize;
+	u_int32_t flags;
+	__db_del_reply *replyp;
+{
+	DB *dbp;
+	DBT key;
+	DB_TXN *txnp;
+	ct_entry *dbp_ctp, *txnp_ctp;
+	int ret;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+	if (txnpcl_id != 0) {
+		ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+		txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+	} else
+		txnp = NULL;
+
+	memset(&key, 0, sizeof(key));
+
+	/* Set up key DBT */
+	key.dlen = keydlen;
+	key.ulen = keyulen;
+	key.doff = keydoff;
+	key.flags = keyflags;
+	key.size = keysize;
+	key.data = keydata;
+
+	ret = dbp->del(dbp, txnp, &key, flags);
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __db_get_encrypt_flags_proc __P((long,
+ * PUBLIC:      __db_get_encrypt_flags_reply *));
+ */
+void
+__db_get_encrypt_flags_proc(dbpcl_id, replyp)
+	long dbpcl_id;
+	__db_get_encrypt_flags_reply *replyp;
+{
+	DB *dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	replyp->status = dbp->get_encrypt_flags(dbp, &replyp->flags);
+}
+
+/*
+ * PUBLIC: void __db_encrypt_proc __P((long, char *, u_int32_t,
+ * PUBLIC:      __db_encrypt_reply *));
+ */
+void
+__db_encrypt_proc(dbpcl_id, passwd, flags, replyp)
+	long dbpcl_id;
+	char *passwd;
+	u_int32_t flags;
+	__db_encrypt_reply *replyp;
+{
+	int ret;
+	DB * dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	ret = dbp->set_encrypt(dbp, passwd, flags);
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __db_get_extentsize_proc __P((long,
+ * PUBLIC:      __db_get_extentsize_reply *));
+ */
+void
+__db_get_extentsize_proc(dbpcl_id, replyp)
+	long dbpcl_id;
+	__db_get_extentsize_reply *replyp;
+{
+	DB *dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	replyp->status = dbp->get_q_extentsize(dbp, &replyp->extentsize);
+}
+
+/*
+ * PUBLIC: void __db_extentsize_proc __P((long, u_int32_t,
+ * PUBLIC:      __db_extentsize_reply *));
+ */
+void
+__db_extentsize_proc(dbpcl_id, extentsize, replyp)
+	long dbpcl_id;
+	u_int32_t extentsize;
+	__db_extentsize_reply *replyp;
+{
+	DB *dbp;
+	ct_entry *dbp_ctp;
+	int ret;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	ret = dbp->set_q_extentsize(dbp, extentsize);
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __db_get_flags_proc __P((long, __db_get_flags_reply *));
+ */
+void
+__db_get_flags_proc(dbpcl_id, replyp)
+	long dbpcl_id;
+	__db_get_flags_reply *replyp;
+{
+	DB *dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	replyp->status = dbp->get_flags(dbp, &replyp->flags);
+}
+
+/*
+ * PUBLIC: void __db_flags_proc __P((long, u_int32_t, __db_flags_reply *));
+ */
+void
+__db_flags_proc(dbpcl_id, flags, replyp)
+	long dbpcl_id;
+	u_int32_t flags;
+	__db_flags_reply *replyp;
+{
+	DB *dbp;
+	ct_entry *dbp_ctp;
+	int ret;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	ret = dbp->set_flags(dbp, flags);
+	dbp_ctp->ct_dbdp.setflags |= flags;
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __db_get_proc __P((long, long, u_int32_t, u_int32_t, u_int32_t,
+ * PUBLIC:     u_int32_t, void *, u_int32_t, u_int32_t, u_int32_t, u_int32_t,
+ * PUBLIC:     u_int32_t, void *, u_int32_t, u_int32_t, __db_get_reply *,
+ * PUBLIC:     int *));
+ */
+void
+__db_get_proc(dbpcl_id, txnpcl_id, keydlen, keydoff, keyulen, keyflags,
+    keydata, keysize, datadlen, datadoff, dataulen, dataflags, datadata,
+    datasize, flags, replyp, freep)
+	long dbpcl_id;
+	long txnpcl_id;
+	u_int32_t keydlen;
+	u_int32_t keydoff;
+	u_int32_t keyulen;
+	u_int32_t keyflags;
+	void *keydata;
+	u_int32_t keysize;
+	u_int32_t datadlen;
+	u_int32_t datadoff;
+	u_int32_t dataulen;
+	u_int32_t dataflags;
+	void *datadata;
+	u_int32_t datasize;
+	u_int32_t flags;
+	__db_get_reply *replyp;
+	int * freep;
+{
+	DB *dbp;
+	DBT key, data;
+	DB_TXN *txnp;
+	ct_entry *dbp_ctp, *txnp_ctp;
+	int key_alloc, bulk_alloc, ret;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+	if (txnpcl_id != 0) {
+		ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+		txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+	} else
+		txnp = NULL;
+
+	*freep = 0;
+	bulk_alloc = 0;
+	memset(&key, 0, sizeof(key));
+	memset(&data, 0, sizeof(data));
+
+	/* Set up key and data DBT */
+	key.dlen = keydlen;
+	key.doff = keydoff;
+	/*
+	 * Ignore memory related flags on server.
+	 */
+	key.flags = DB_DBT_MALLOC;
+	if (keyflags & DB_DBT_PARTIAL)
+		key.flags |= DB_DBT_PARTIAL;
+	key.size = keysize;
+	key.ulen = keyulen;
+	key.data = keydata;
+
+	data.dlen = datadlen;
+	data.doff = datadoff;
+	data.ulen = dataulen;
+	/*
+	 * Ignore memory related flags on server.
+	 */
+	data.size = datasize;
+	data.data = datadata;
+	if (flags & DB_MULTIPLE) {
+		if (data.data == 0) {
+			ret = __os_umalloc(dbp->dbenv,
+			    data.ulen, &data.data);
+			if (ret != 0)
+				goto err;
+			bulk_alloc = 1;
+		}
+		data.flags |= DB_DBT_USERMEM;
+	} else
+		data.flags |= DB_DBT_MALLOC;
+	if (dataflags & DB_DBT_PARTIAL)
+		data.flags |= DB_DBT_PARTIAL;
+
+	/* Got all our stuff, now do the get */
+	ret = dbp->get(dbp, txnp, &key, &data, flags);
+	/*
+	 * Otherwise just status.
+	 */
+	if (ret == 0) {
+		/*
+		 * XXX
+		 * We need to xdr_free whatever we are returning, next time.
+		 * However, DB does not allocate a new key if one was given
+		 * and we'd be free'ing up space allocated in the request.
+		 * So, allocate a new key/data pointer if it is the same one
+		 * as in the request.
+		 */
+		*freep = 1;
+		/*
+		 * Key
+		 */
+		key_alloc = 0;
+		if (key.data == keydata) {
+			ret = __os_umalloc(dbp->dbenv,
+			    key.size, &replyp->keydata.keydata_val);
+			if (ret != 0) {
+				__os_ufree(dbp->dbenv, key.data);
+				__os_ufree(dbp->dbenv, data.data);
+				goto err;
+			}
+			key_alloc = 1;
+			memcpy(replyp->keydata.keydata_val, key.data, key.size);
+		} else
+			replyp->keydata.keydata_val = key.data;
+
+		replyp->keydata.keydata_len = key.size;
+
+		/*
+		 * Data
+		 */
+		if (data.data == datadata) {
+			ret = __os_umalloc(dbp->dbenv,
+			     data.size, &replyp->datadata.datadata_val);
+			if (ret != 0) {
+				__os_ufree(dbp->dbenv, key.data);
+				__os_ufree(dbp->dbenv, data.data);
+				if (key_alloc)
+					__os_ufree(dbp->dbenv,
+					    replyp->keydata.keydata_val);
+				goto err;
+			}
+			memcpy(replyp->datadata.datadata_val, data.data,
+			    data.size);
+		} else
+			replyp->datadata.datadata_val = data.data;
+		replyp->datadata.datadata_len = data.size;
+	} else {
+err:		replyp->keydata.keydata_val = NULL;
+		replyp->keydata.keydata_len = 0;
+		replyp->datadata.datadata_val = NULL;
+		replyp->datadata.datadata_len = 0;
+		*freep = 0;
+		if (bulk_alloc)
+			__os_ufree(dbp->dbenv, data.data);
+	}
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __db_get_h_ffactor_proc __P((long,
+ * PUBLIC:      __db_get_h_ffactor_reply *));
+ */
+void
+__db_get_h_ffactor_proc(dbpcl_id, replyp)
+	long dbpcl_id;
+	__db_get_h_ffactor_reply *replyp;
+{
+	DB *dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	replyp->status = dbp->get_h_ffactor(dbp, &replyp->ffactor);
+}
+
+/*
+ * PUBLIC: void __db_h_ffactor_proc __P((long, u_int32_t,
+ * PUBLIC:      __db_h_ffactor_reply *));
+ */
+void
+__db_h_ffactor_proc(dbpcl_id, ffactor, replyp)
+	long dbpcl_id;
+	u_int32_t ffactor;
+	__db_h_ffactor_reply *replyp;
+{
+	DB *dbp;
+	ct_entry *dbp_ctp;
+	int ret;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	ret = dbp->set_h_ffactor(dbp, ffactor);
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __db_get_h_nelem_proc __P((long, __db_get_h_nelem_reply *));
+ */
+void
+__db_get_h_nelem_proc(dbpcl_id, replyp)
+	long dbpcl_id;
+	__db_get_h_nelem_reply *replyp;
+{
+	DB *dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	replyp->status = dbp->get_h_nelem(dbp, &replyp->nelem);
+}
+
+/*
+ * PUBLIC: void __db_h_nelem_proc __P((long, u_int32_t,
+ * PUBLIC:      __db_h_nelem_reply *));
+ */
+void
+__db_h_nelem_proc(dbpcl_id, nelem, replyp)
+	long dbpcl_id;
+	u_int32_t nelem;
+	__db_h_nelem_reply *replyp;
+{
+	DB *dbp;
+	ct_entry *dbp_ctp;
+	int ret;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	ret = dbp->set_h_nelem(dbp, nelem);
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __db_key_range_proc __P((long, long, u_int32_t, u_int32_t,
+ * PUBLIC:     u_int32_t, u_int32_t, void *, u_int32_t, u_int32_t,
+ * PUBLIC:     __db_key_range_reply *));
+ */
+void
+__db_key_range_proc(dbpcl_id, txnpcl_id, keydlen, keydoff, keyulen,
+    keyflags, keydata, keysize, flags, replyp)
+	long dbpcl_id;
+	long txnpcl_id;
+	u_int32_t keydlen;
+	u_int32_t keydoff;
+	u_int32_t keyulen;
+	u_int32_t keyflags;
+	void *keydata;
+	u_int32_t keysize;
+	u_int32_t flags;
+	__db_key_range_reply *replyp;
+{
+	DB *dbp;
+	DBT key;
+	DB_KEY_RANGE range;
+	DB_TXN *txnp;
+	ct_entry *dbp_ctp, *txnp_ctp;
+	int ret;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+	if (txnpcl_id != 0) {
+		ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+		txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+	} else
+		txnp = NULL;
+
+	memset(&key, 0, sizeof(key));
+	/* Set up key and data DBT */
+	key.dlen = keydlen;
+	key.ulen = keyulen;
+	key.doff = keydoff;
+	key.size = keysize;
+	key.data = keydata;
+	key.flags = keyflags;
+
+	ret = dbp->key_range(dbp, txnp, &key, &range, flags);
+
+	replyp->status = ret;
+	replyp->less = range.less;
+	replyp->equal = range.equal;
+	replyp->greater = range.greater;
+	return;
+}
+
+/*
+ * PUBLIC: void __db_get_lorder_proc __P((long, __db_get_lorder_reply *));
+ */
+void
+__db_get_lorder_proc(dbpcl_id, replyp)
+	long dbpcl_id;
+	__db_get_lorder_reply *replyp;
+{
+	DB *dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	replyp->status = dbp->get_lorder(dbp, (int *)&replyp->lorder);
+}
+
+/*
+ * PUBLIC: void __db_lorder_proc __P((long, u_int32_t, __db_lorder_reply *));
+ */
+void
+__db_lorder_proc(dbpcl_id, lorder, replyp)
+	long dbpcl_id;
+	u_int32_t lorder;
+	__db_lorder_reply *replyp;
+{
+	DB *dbp;
+	ct_entry *dbp_ctp;
+	int ret;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	ret = dbp->set_lorder(dbp, lorder);
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __db_get_name_proc __P((long, __db_get_name_reply *));
+ */
+void
+__db_get_name_proc(dbpcl_id, replyp)
+	long dbpcl_id;
+	__db_get_name_reply *replyp;
+{
+	DB *dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	replyp->status = dbp->get_dbname(dbp,
+	    (const char **)&replyp->filename, (const char **)&replyp->dbname);
+}
+
+/*
+ * PUBLIC: void __db_get_open_flags_proc __P((long,
+ * PUBLIC:      __db_get_open_flags_reply *));
+ */
+void
+__db_get_open_flags_proc(dbpcl_id, replyp)
+	long dbpcl_id;
+	__db_get_open_flags_reply *replyp;
+{
+	DB *dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	replyp->status = dbp->get_open_flags(dbp, &replyp->flags);
+}
+
+/*
+ * PUBLIC: void __db_open_proc __P((long, long, char *, char *, u_int32_t,
+ * PUBLIC:      u_int32_t, u_int32_t, __db_open_reply *));
+ */
+void
+__db_open_proc(dbpcl_id, txnpcl_id, name, subdb, type, flags, mode, replyp)
+	long dbpcl_id;
+	long txnpcl_id;
+	char *name;
+	char *subdb;
+	u_int32_t type;
+	u_int32_t flags;
+	u_int32_t mode;
+	__db_open_reply *replyp;
+{
+	DB *dbp;
+	DB_TXN *txnp;
+	DBTYPE dbtype;
+	ct_entry *dbp_ctp, *new_ctp, *txnp_ctp;
+	int isswapped, ret;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	if (txnpcl_id != 0) {
+		ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+		txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+	} else
+		txnp = NULL;
+
+	replyp->dbcl_id = dbpcl_id;
+	if ((new_ctp = __dbsrv_sharedb(dbp_ctp, name, subdb, type, flags))
+	    != NULL) {
+		/*
+		 * We can share, clean up old ID, set new one.
+		 */
+		if (__dbsrv_verbose)
+			printf("Sharing db ID %ld\n", new_ctp->ct_id);
+		replyp->dbcl_id = new_ctp->ct_id;
+		ret = __db_close_int(dbpcl_id, 0);
+		goto out;
+	}
+	ret = dbp->open(dbp, txnp, name, subdb, (DBTYPE)type, flags, mode);
+	if (ret == 0) {
+		(void)dbp->get_type(dbp, &dbtype);
+		replyp->type = dbtype;
+		/*
+		 * We need to determine the byte order of the database
+		 * and send it back to the client.  Determine it by
+		 * the server's native order and the swapped value of
+		 * the DB itself.
+		 */
+		(void)dbp->get_byteswapped(dbp, &isswapped);
+		if (__db_byteorder(NULL, 1234) == 0) {
+			if (isswapped == 0)
+				replyp->lorder = 1234;
+			else
+				replyp->lorder = 4321;
+		} else {
+			if (isswapped == 0)
+				replyp->lorder = 4321;
+			else
+				replyp->lorder = 1234;
+		}
+		dbp_ctp->ct_dbdp.type = dbtype;
+		dbp_ctp->ct_dbdp.dbflags = LF_ISSET(DB_SERVER_DBFLAGS);
+		if (name == NULL)
+			dbp_ctp->ct_dbdp.db = NULL;
+		else if ((ret = __os_strdup(dbp->dbenv, name,
+		    &dbp_ctp->ct_dbdp.db)) != 0)
+			goto out;
+		if (subdb == NULL)
+			dbp_ctp->ct_dbdp.subdb = NULL;
+		else if ((ret = __os_strdup(dbp->dbenv, subdb,
+		    &dbp_ctp->ct_dbdp.subdb)) != 0)
+			goto out;
+	}
+out:
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __db_get_pagesize_proc __P((long, __db_get_pagesize_reply *));
+ */
+void
+__db_get_pagesize_proc(dbpcl_id, replyp)
+	long dbpcl_id;
+	__db_get_pagesize_reply *replyp;
+{
+	DB *dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	replyp->status = dbp->get_pagesize(dbp, &replyp->pagesize);
+}
+
+/*
+ * PUBLIC: void __db_pagesize_proc __P((long, u_int32_t,
+ * PUBLIC:      __db_pagesize_reply *));
+ */
+void
+__db_pagesize_proc(dbpcl_id, pagesize, replyp)
+	long dbpcl_id;
+	u_int32_t pagesize;
+	__db_pagesize_reply *replyp;
+{
+	DB *dbp;
+	ct_entry *dbp_ctp;
+	int ret;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	ret = dbp->set_pagesize(dbp, pagesize);
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __db_pget_proc __P((long, long, u_int32_t, u_int32_t, u_int32_t,
+ * PUBLIC:     u_int32_t, void *, u_int32_t, u_int32_t, u_int32_t, u_int32_t,
+ * PUBLIC:     u_int32_t, void *, u_int32_t, u_int32_t, u_int32_t, u_int32_t,
+ * PUBLIC:     u_int32_t, void *, u_int32_t, u_int32_t, __db_pget_reply *,
+ * PUBLIC:     int *));
+ */
+void
+__db_pget_proc(dbpcl_id, txnpcl_id, skeydlen, skeydoff, skeyulen,
+    skeyflags, skeydata, skeysize, pkeydlen, pkeydoff, pkeyulen, pkeyflags,
+    pkeydata, pkeysize, datadlen, datadoff, dataulen, dataflags, datadata,
+    datasize, flags, replyp, freep)
+	long dbpcl_id;
+	long txnpcl_id;
+	u_int32_t skeydlen;
+	u_int32_t skeydoff;
+	u_int32_t skeyulen;
+	u_int32_t skeyflags;
+	void *skeydata;
+	u_int32_t skeysize;
+	u_int32_t pkeydlen;
+	u_int32_t pkeydoff;
+	u_int32_t pkeyulen;
+	u_int32_t pkeyflags;
+	void *pkeydata;
+	u_int32_t pkeysize;
+	u_int32_t datadlen;
+	u_int32_t datadoff;
+	u_int32_t dataulen;
+	u_int32_t dataflags;
+	void *datadata;
+	u_int32_t datasize;
+	u_int32_t flags;
+	__db_pget_reply *replyp;
+	int * freep;
+{
+	DB *dbp;
+	DBT skey, pkey, data;
+	DB_TXN *txnp;
+	ct_entry *dbp_ctp, *txnp_ctp;
+	int key_alloc, ret;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+	if (txnpcl_id != 0) {
+		ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+		txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+	} else
+		txnp = NULL;
+
+	*freep = 0;
+	memset(&skey, 0, sizeof(skey));
+	memset(&pkey, 0, sizeof(pkey));
+	memset(&data, 0, sizeof(data));
+
+	/*
+	 * Ignore memory related flags on server.
+	 */
+	/* Set up key and data DBT */
+	skey.flags = DB_DBT_MALLOC;
+	skey.dlen = skeydlen;
+	skey.ulen = skeyulen;
+	skey.doff = skeydoff;
+	if (skeyflags & DB_DBT_PARTIAL)
+		skey.flags |= DB_DBT_PARTIAL;
+	skey.size = skeysize;
+	skey.data = skeydata;
+
+	pkey.flags = DB_DBT_MALLOC;
+	pkey.dlen = pkeydlen;
+	pkey.ulen = pkeyulen;
+	pkey.doff = pkeydoff;
+	if (pkeyflags & DB_DBT_PARTIAL)
+		pkey.flags |= DB_DBT_PARTIAL;
+	pkey.size = pkeysize;
+	pkey.data = pkeydata;
+
+	data.flags = DB_DBT_MALLOC;
+	data.dlen = datadlen;
+	data.ulen = dataulen;
+	data.doff = datadoff;
+	if (dataflags & DB_DBT_PARTIAL)
+		data.flags |= DB_DBT_PARTIAL;
+	data.size = datasize;
+	data.data = datadata;
+
+	/* Got all our stuff, now do the get */
+	ret = dbp->pget(dbp, txnp, &skey, &pkey, &data, flags);
+	/*
+	 * Otherwise just status.
+	 */
+	if (ret == 0) {
+		/*
+		 * XXX
+		 * We need to xdr_free whatever we are returning, next time.
+		 * However, DB does not allocate a new key if one was given
+		 * and we'd be free'ing up space allocated in the request.
+		 * So, allocate a new key/data pointer if it is the same one
+		 * as in the request.
+		 */
+		*freep = 1;
+		/*
+		 * Key
+		 */
+		key_alloc = 0;
+		if (skey.data == skeydata) {
+			ret = __os_umalloc(dbp->dbenv,
+			    skey.size, &replyp->skeydata.skeydata_val);
+			if (ret != 0) {
+				__os_ufree(dbp->dbenv, skey.data);
+				__os_ufree(dbp->dbenv, pkey.data);
+				__os_ufree(dbp->dbenv, data.data);
+				goto err;
+			}
+			key_alloc = 1;
+			memcpy(replyp->skeydata.skeydata_val, skey.data,
+			    skey.size);
+		} else
+			replyp->skeydata.skeydata_val = skey.data;
+
+		replyp->skeydata.skeydata_len = skey.size;
+
+		/*
+		 * Primary key
+		 */
+		if (pkey.data == pkeydata) {
+			ret = __os_umalloc(dbp->dbenv,
+			     pkey.size, &replyp->pkeydata.pkeydata_val);
+			if (ret != 0) {
+				__os_ufree(dbp->dbenv, skey.data);
+				__os_ufree(dbp->dbenv, pkey.data);
+				__os_ufree(dbp->dbenv, data.data);
+				if (key_alloc)
+					__os_ufree(dbp->dbenv,
+					    replyp->skeydata.skeydata_val);
+				goto err;
+			}
+			/*
+			 * We can set it to 2, because they cannot send the
+			 * pkey over without sending the skey over too.
+			 * So if they did send a pkey, they must have sent
+			 * the skey as well.
+			 */
+			key_alloc = 2;
+			memcpy(replyp->pkeydata.pkeydata_val, pkey.data,
+			    pkey.size);
+		} else
+			replyp->pkeydata.pkeydata_val = pkey.data;
+		replyp->pkeydata.pkeydata_len = pkey.size;
+
+		/*
+		 * Data
+		 */
+		if (data.data == datadata) {
+			ret = __os_umalloc(dbp->dbenv,
+			     data.size, &replyp->datadata.datadata_val);
+			if (ret != 0) {
+				__os_ufree(dbp->dbenv, skey.data);
+				__os_ufree(dbp->dbenv, pkey.data);
+				__os_ufree(dbp->dbenv, data.data);
+				/*
+				 * If key_alloc is 1, just skey needs to be
+				 * freed, if key_alloc is 2, both skey and pkey
+				 * need to be freed.
+				 */
+				if (key_alloc--)
+					__os_ufree(dbp->dbenv,
+					    replyp->skeydata.skeydata_val);
+				if (key_alloc)
+					__os_ufree(dbp->dbenv,
+					    replyp->pkeydata.pkeydata_val);
+				goto err;
+			}
+			memcpy(replyp->datadata.datadata_val, data.data,
+			    data.size);
+		} else
+			replyp->datadata.datadata_val = data.data;
+		replyp->datadata.datadata_len = data.size;
+	} else {
+err:		replyp->skeydata.skeydata_val = NULL;
+		replyp->skeydata.skeydata_len = 0;
+		replyp->pkeydata.pkeydata_val = NULL;
+		replyp->pkeydata.pkeydata_len = 0;
+		replyp->datadata.datadata_val = NULL;
+		replyp->datadata.datadata_len = 0;
+		*freep = 0;
+	}
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __db_put_proc __P((long, long, u_int32_t, u_int32_t, u_int32_t,
+ * PUBLIC:     u_int32_t, void *, u_int32_t, u_int32_t, u_int32_t, u_int32_t,
+ * PUBLIC:     u_int32_t, void *, u_int32_t, u_int32_t, __db_put_reply *,
+ * PUBLIC:     int *));
+ */
+void
+__db_put_proc(dbpcl_id, txnpcl_id, keydlen, keydoff, keyulen, keyflags,
+    keydata, keysize, datadlen, datadoff, dataulen, dataflags, datadata,
+    datasize, flags, replyp, freep)
+	long dbpcl_id;
+	long txnpcl_id;
+	u_int32_t keydlen;
+	u_int32_t keydoff;
+	u_int32_t keyulen;
+	u_int32_t keyflags;
+	void *keydata;
+	u_int32_t keysize;
+	u_int32_t datadlen;
+	u_int32_t datadoff;
+	u_int32_t dataulen;
+	u_int32_t dataflags;
+	void *datadata;
+	u_int32_t datasize;
+	u_int32_t flags;
+	__db_put_reply *replyp;
+	int * freep;
+{
+	DB *dbp;
+	DBT key, data;
+	DB_TXN *txnp;
+	ct_entry *dbp_ctp, *txnp_ctp;
+	int ret;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+	if (txnpcl_id != 0) {
+		ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+		txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+	} else
+		txnp = NULL;
+
+	*freep = 0;
+	memset(&key, 0, sizeof(key));
+	memset(&data, 0, sizeof(data));
+
+	/* Set up key and data DBT */
+	key.dlen = keydlen;
+	key.ulen = keyulen;
+	key.doff = keydoff;
+	/*
+	 * Ignore memory related flags on server.
+	 */
+	key.flags = DB_DBT_MALLOC;
+	if (keyflags & DB_DBT_PARTIAL)
+		key.flags |= DB_DBT_PARTIAL;
+	key.size = keysize;
+	key.data = keydata;
+
+	data.dlen = datadlen;
+	data.ulen = dataulen;
+	data.doff = datadoff;
+	data.flags = dataflags;
+	data.size = datasize;
+	data.data = datadata;
+
+	/* Got all our stuff, now do the put */
+	ret = dbp->put(dbp, txnp, &key, &data, flags);
+	/*
+	 * If the client did a DB_APPEND, set up key in reply.
+	 * Otherwise just status.
+	 */
+	if (ret == 0 && (flags == DB_APPEND)) {
+		/*
+		 * XXX
+		 * We need to xdr_free whatever we are returning, next time.
+		 * However, DB does not allocate a new key if one was given
+		 * and we'd be free'ing up space allocated in the request.
+		 * So, allocate a new key/data pointer if it is the same one
+		 * as in the request.
+		 */
+		*freep = 1;
+		/*
+		 * Key
+		 */
+		if (key.data == keydata) {
+			ret = __os_umalloc(dbp->dbenv,
+			    key.size, &replyp->keydata.keydata_val);
+			if (ret != 0) {
+				__os_ufree(dbp->dbenv, key.data);
+				goto err;
+			}
+			memcpy(replyp->keydata.keydata_val, key.data, key.size);
+		} else
+			replyp->keydata.keydata_val = key.data;
+
+		replyp->keydata.keydata_len = key.size;
+	} else {
+err:		replyp->keydata.keydata_val = NULL;
+		replyp->keydata.keydata_len = 0;
+		*freep = 0;
+	}
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __db_get_re_delim_proc __P((long, __db_get_re_delim_reply *));
+ */
+void
+__db_get_re_delim_proc(dbpcl_id, replyp)
+	long dbpcl_id;
+	__db_get_re_delim_reply *replyp;
+{
+	DB *dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	replyp->status = dbp->get_re_delim(dbp, (int *)&replyp->delim);
+}
+
+/*
+ * PUBLIC: void __db_re_delim_proc __P((long, u_int32_t,
+ * PUBLIC:      __db_re_delim_reply *));
+ */
+void
+__db_re_delim_proc(dbpcl_id, delim, replyp)
+	long dbpcl_id;
+	u_int32_t delim;
+	__db_re_delim_reply *replyp;
+{
+	DB *dbp;
+	ct_entry *dbp_ctp;
+	int ret;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	ret = dbp->set_re_delim(dbp, delim);
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __db_get_re_len_proc __P((long, __db_get_re_len_reply *));
+ */
+void
+__db_get_re_len_proc(dbpcl_id, replyp)
+	long dbpcl_id;
+	__db_get_re_len_reply *replyp;
+{
+	DB *dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	replyp->status = dbp->get_re_len(dbp, &replyp->len);
+}
+
+/*
+ * PUBLIC: void __db_re_len_proc __P((long, u_int32_t, __db_re_len_reply *));
+ */
+void
+__db_re_len_proc(dbpcl_id, len, replyp)
+	long dbpcl_id;
+	u_int32_t len;
+	__db_re_len_reply *replyp;
+{
+	DB *dbp;
+	ct_entry *dbp_ctp;
+	int ret;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	ret = dbp->set_re_len(dbp, len);
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __db_get_re_pad_proc __P((long, __db_get_re_pad_reply *));
+ */
+void
+__db_get_re_pad_proc(dbpcl_id, replyp)
+	long dbpcl_id;
+	__db_get_re_pad_reply *replyp;
+{
+	DB *dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	replyp->status = dbp->get_re_pad(dbp, (int *)&replyp->pad);
+}
+
+/*
+ * PUBLIC: void __db_re_pad_proc __P((long, u_int32_t, __db_re_pad_reply *));
+ */
+void
+__db_re_pad_proc(dbpcl_id, pad, replyp)
+	long dbpcl_id;
+	u_int32_t pad;
+	__db_re_pad_reply *replyp;
+{
+	DB *dbp;
+	ct_entry *dbp_ctp;
+	int ret;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	ret = dbp->set_re_pad(dbp, pad);
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __db_remove_proc __P((long, char *, char *, u_int32_t,
+ * PUBLIC:      __db_remove_reply *));
+ */
+void
+__db_remove_proc(dbpcl_id, name, subdb, flags, replyp)
+	long dbpcl_id;
+	char *name;
+	char *subdb;
+	u_int32_t flags;
+	__db_remove_reply *replyp;
+{
+	DB *dbp;
+	ct_entry *dbp_ctp;
+	int ret;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	ret = dbp->remove(dbp, name, subdb, flags);
+	__dbdel_ctp(dbp_ctp);
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __db_rename_proc __P((long, char *, char *, char *, u_int32_t,
+ * PUBLIC:      __db_rename_reply *));
+ */
+void
+__db_rename_proc(dbpcl_id, name, subdb, newname, flags, replyp)
+	long dbpcl_id;
+	char *name;
+	char *subdb;
+	char *newname;
+	u_int32_t flags;
+	__db_rename_reply *replyp;
+{
+	DB *dbp;
+	ct_entry *dbp_ctp;
+	int ret;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	ret = dbp->rename(dbp, name, subdb, newname, flags);
+	__dbdel_ctp(dbp_ctp);
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __db_stat_proc __P((long, long, u_int32_t, __db_stat_reply *,
+ * PUBLIC:      int *));
+ */
+void
+__db_stat_proc(dbpcl_id, txnpcl_id, flags, replyp, freep)
+	long dbpcl_id;
+	long txnpcl_id;
+	u_int32_t flags;
+	__db_stat_reply *replyp;
+	int * freep;
+{
+	DB *dbp;
+	DB_TXN *txnp;
+	DBTYPE type;
+	ct_entry *dbp_ctp, *txnp_ctp;
+	u_int32_t *q, *p, *retsp;
+	int i, len, ret;
+	void *sp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+	if (txnpcl_id != 0) {
+		ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+		txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+	} else
+		txnp = NULL;
+
+	ret = dbp->stat(dbp, txnp, &sp, flags);
+	replyp->status = ret;
+	if (ret != 0)
+		return;
+	/*
+	 * We get here, we have success.  Allocate an array so that
+	 * we can use the list generator.  Generate the reply, free
+	 * up the space.
+	 */
+	/*
+	 * XXX This assumes that all elements of all stat structures
+	 * are u_int32_t fields.  They are, currently.
+	 */
+	(void)dbp->get_type(dbp, &type);
+	if (type == DB_HASH)
+		len = sizeof(DB_HASH_STAT);
+	else if (type == DB_QUEUE)
+		len = sizeof(DB_QUEUE_STAT);
+	else            /* BTREE or RECNO are same stats */
+		len = sizeof(DB_BTREE_STAT);
+	replyp->stats.stats_len = len / sizeof(u_int32_t);
+
+	if ((ret = __os_umalloc(dbp->dbenv, len * replyp->stats.stats_len,
+	    &retsp)) != 0)
+		goto out;
+	for (i = 0, q = retsp, p = sp; i < len;
+	    i++, q++, p++)
+		*q = *p;
+	replyp->stats.stats_val = retsp;
+	__os_ufree(dbp->dbenv, sp);
+	if (ret == 0)
+		*freep = 1;
+out:
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __db_sync_proc __P((long, u_int32_t, __db_sync_reply *));
+ */
+void
+__db_sync_proc(dbpcl_id, flags, replyp)
+	long dbpcl_id;
+	u_int32_t flags;
+	__db_sync_reply *replyp;
+{
+	DB *dbp;
+	ct_entry *dbp_ctp;
+	int ret;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	ret = dbp->sync(dbp, flags);
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __db_truncate_proc __P((long, long, u_int32_t,
+ * PUBLIC:      __db_truncate_reply *));
+ */
+void
+__db_truncate_proc(dbpcl_id, txnpcl_id, flags, replyp)
+	long dbpcl_id;
+	long txnpcl_id;
+	u_int32_t flags;
+	__db_truncate_reply *replyp;
+{
+	DB *dbp;
+	DB_TXN *txnp;
+	ct_entry *dbp_ctp, *txnp_ctp;
+	u_int32_t count;
+	int ret;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+	if (txnpcl_id != 0) {
+		ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+		txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+	} else
+		txnp = NULL;
+
+	ret = dbp->truncate(dbp, txnp, &count, flags);
+	replyp->status = ret;
+	if (ret == 0)
+		replyp->count = count;
+	return;
+}
+
+/*
+ * PUBLIC: void __db_cursor_proc __P((long, long, u_int32_t,
+ * PUBLIC:      __db_cursor_reply *));
+ */
+void
+__db_cursor_proc(dbpcl_id, txnpcl_id, flags, replyp)
+	long dbpcl_id;
+	long txnpcl_id;
+	u_int32_t flags;
+	__db_cursor_reply *replyp;
+{
+	DB *dbp;
+	DBC *dbc;
+	DB_TXN *txnp;
+	ct_entry *dbc_ctp, *env_ctp, *dbp_ctp, *txnp_ctp;
+	int ret;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+	dbc_ctp = new_ct_ent(&replyp->status);
+	if (dbc_ctp == NULL)
+		return;
+
+	if (txnpcl_id != 0) {
+		ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+		txnp = (DB_TXN *)txnp_ctp->ct_anyp;
+		dbc_ctp->ct_activep = txnp_ctp->ct_activep;
+	} else
+		txnp = NULL;
+
+	if ((ret = dbp->cursor(dbp, txnp, &dbc, flags)) == 0) {
+		dbc_ctp->ct_dbc = dbc;
+		dbc_ctp->ct_type = CT_CURSOR;
+		dbc_ctp->ct_parent = dbp_ctp;
+		env_ctp = dbp_ctp->ct_envparent;
+		dbc_ctp->ct_envparent = env_ctp;
+		__dbsrv_settimeout(dbc_ctp, env_ctp->ct_timeout);
+		__dbsrv_active(dbc_ctp);
+		replyp->dbcidcl_id = dbc_ctp->ct_id;
+	} else
+		__dbclear_ctp(dbc_ctp);
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __db_join_proc __P((long, u_int32_t *, u_int32_t, u_int32_t,
+ * PUBLIC:      __db_join_reply *));
+ */
+void
+__db_join_proc(dbpcl_id, curs, curslen, flags, replyp)
+	long dbpcl_id;
+	u_int32_t * curs;
+	u_int32_t curslen;
+	u_int32_t flags;
+	__db_join_reply *replyp;
+{
+	DB *dbp;
+	DBC **jcurs, **c;
+	DBC *dbc;
+	ct_entry *dbc_ctp, *ctp, *dbp_ctp;
+	size_t size;
+	u_int32_t *cl, i;
+	int ret;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (DB *)dbp_ctp->ct_anyp;
+
+	dbc_ctp = new_ct_ent(&replyp->status);
+	if (dbc_ctp == NULL)
+		return;
+
+	size = (curslen + 1) * sizeof(DBC *);
+	if ((ret = __os_calloc(dbp->dbenv,
+	    curslen + 1, sizeof(DBC *), &jcurs)) != 0) {
+		replyp->status = ret;
+		__dbclear_ctp(dbc_ctp);
+		return;
+	}
+	/*
+	 * If our curslist has a parent txn, we need to use it too
+	 * for the activity timeout.  All cursors must be part of
+	 * the same transaction, so just check the first.
+	 */
+	ctp = get_tableent(*curs);
+	DB_ASSERT(ctp->ct_type == CT_CURSOR);
+	/*
+	 * If we are using a transaction, set the join activity timer
+	 * to point to the parent transaction.
+	 */
+	if (ctp->ct_activep != &ctp->ct_active)
+		dbc_ctp->ct_activep = ctp->ct_activep;
+	for (i = 0, cl = curs, c = jcurs; i < curslen; i++, cl++, c++) {
+		ctp = get_tableent(*cl);
+		if (ctp == NULL) {
+			replyp->status = DB_NOSERVER_ID;
+			goto out;
+		}
+		/*
+		 * If we are using a txn, the join cursor points to the
+		 * transaction timeout.  If we are not using a transaction,
+		 * then all the curslist cursors must point to the join
+		 * cursor's timeout so that we do not timeout any of the
+		 * curlist cursors while the join cursor is active.
+		 * Change the type of the curslist ctps to CT_JOIN so that
+		 * we know they are part of a join list and we can distinguish
+		 * them and later restore them when the join cursor is closed.
+		 */
+		DB_ASSERT(ctp->ct_type == CT_CURSOR);
+		ctp->ct_type |= CT_JOIN;
+		ctp->ct_origp = ctp->ct_activep;
+		/*
+		 * Setting this to the ct_active field of the dbc_ctp is
+		 * really just a way to distinguish which join dbc this
+		 * cursor is part of.  The ct_activep of this cursor is
+		 * not used at all during its lifetime as part of a join
+		 * cursor.
+		 */
+		ctp->ct_activep = &dbc_ctp->ct_active;
+		*c = ctp->ct_dbc;
+	}
+	*c = NULL;
+	if ((ret = dbp->join(dbp, jcurs, &dbc, flags)) == 0) {
+		dbc_ctp->ct_dbc = dbc;
+		dbc_ctp->ct_type = (CT_JOINCUR | CT_CURSOR);
+		dbc_ctp->ct_parent = dbp_ctp;
+		dbc_ctp->ct_envparent = dbp_ctp->ct_envparent;
+		__dbsrv_settimeout(dbc_ctp, dbp_ctp->ct_envparent->ct_timeout);
+		__dbsrv_active(dbc_ctp);
+		replyp->dbcidcl_id = dbc_ctp->ct_id;
+	} else {
+		__dbclear_ctp(dbc_ctp);
+		/*
+		 * If we get an error, undo what we did above to any cursors.
+		 */
+		for (cl = curs; *cl != 0; cl++) {
+			ctp = get_tableent(*cl);
+			ctp->ct_type = CT_CURSOR;
+			ctp->ct_activep = ctp->ct_origp;
+		}
+	}
+
+	replyp->status = ret;
+out:
+	__os_free(dbp->dbenv, jcurs);
+	return;
+}
+
+/*
+ * PUBLIC: void __dbc_close_proc __P((long, __dbc_close_reply *));
+ */
+void
+__dbc_close_proc(dbccl_id, replyp)
+	long dbccl_id;
+	__dbc_close_reply *replyp;
+{
+	ct_entry *dbc_ctp;
+
+	ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+	replyp->status = __dbc_close_int(dbc_ctp);
+	return;
+}
+
+/*
+ * PUBLIC: void __dbc_count_proc __P((long, u_int32_t, __dbc_count_reply *));
+ */
+void
+__dbc_count_proc(dbccl_id, flags, replyp)
+	long dbccl_id;
+	u_int32_t flags;
+	__dbc_count_reply *replyp;
+{
+	DBC *dbc;
+	ct_entry *dbc_ctp;
+	db_recno_t num;
+	int ret;
+
+	ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+	dbc = (DBC *)dbc_ctp->ct_anyp;
+
+	ret = dbc->c_count(dbc, &num, flags);
+	replyp->status = ret;
+	if (ret == 0)
+		replyp->dupcount = num;
+	return;
+}
+
+/*
+ * PUBLIC: void __dbc_del_proc __P((long, u_int32_t, __dbc_del_reply *));
+ */
+void
+__dbc_del_proc(dbccl_id, flags, replyp)
+	long dbccl_id;
+	u_int32_t flags;
+	__dbc_del_reply *replyp;
+{
+	DBC *dbc;
+	ct_entry *dbc_ctp;
+	int ret;
+
+	ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+	dbc = (DBC *)dbc_ctp->ct_anyp;
+
+	ret = dbc->c_del(dbc, flags);
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __dbc_dup_proc __P((long, u_int32_t, __dbc_dup_reply *));
+ */
+void
+__dbc_dup_proc(dbccl_id, flags, replyp)
+	long dbccl_id;
+	u_int32_t flags;
+	__dbc_dup_reply *replyp;
+{
+	DBC *dbc, *newdbc;
+	ct_entry *dbc_ctp, *new_ctp;
+	int ret;
+
+	ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+	dbc = (DBC *)dbc_ctp->ct_anyp;
+
+	new_ctp = new_ct_ent(&replyp->status);
+	if (new_ctp == NULL)
+		return;
+
+	if ((ret = dbc->c_dup(dbc, &newdbc, flags)) == 0) {
+		new_ctp->ct_dbc = newdbc;
+		new_ctp->ct_type = CT_CURSOR;
+		new_ctp->ct_parent = dbc_ctp->ct_parent;
+		new_ctp->ct_envparent = dbc_ctp->ct_envparent;
+		/*
+		 * If our cursor has a parent txn, we need to use it too.
+		 */
+		if (dbc_ctp->ct_activep != &dbc_ctp->ct_active)
+			new_ctp->ct_activep = dbc_ctp->ct_activep;
+		__dbsrv_settimeout(new_ctp, dbc_ctp->ct_timeout);
+		__dbsrv_active(new_ctp);
+		replyp->dbcidcl_id = new_ctp->ct_id;
+	} else
+		__dbclear_ctp(new_ctp);
+
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __dbc_get_proc __P((long, u_int32_t, u_int32_t, u_int32_t,
+ * PUBLIC:     u_int32_t, void *, u_int32_t, u_int32_t, u_int32_t, u_int32_t,
+ * PUBLIC:     u_int32_t, void *, u_int32_t, u_int32_t, __dbc_get_reply *,
+ * PUBLIC:     int *));
+ */
+void
+__dbc_get_proc(dbccl_id, keydlen, keydoff, keyulen, keyflags, keydata,
+    keysize, datadlen, datadoff, dataulen, dataflags, datadata, datasize,
+    flags, replyp, freep)
+	long dbccl_id;
+	u_int32_t keydlen;
+	u_int32_t keydoff;
+	u_int32_t keyulen;
+	u_int32_t keyflags;
+	void *keydata;
+	u_int32_t keysize;
+	u_int32_t datadlen;
+	u_int32_t datadoff;
+	u_int32_t dataulen;
+	u_int32_t dataflags;
+	void *datadata;
+	u_int32_t datasize;
+	u_int32_t flags;
+	__dbc_get_reply *replyp;
+	int * freep;
+{
+	DBC *dbc;
+	DBT key, data;
+	DB_ENV *dbenv;
+	ct_entry *dbc_ctp;
+	int key_alloc, bulk_alloc, ret;
+
+	ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+	dbc = (DBC *)dbc_ctp->ct_anyp;
+	dbenv = dbc->dbp->dbenv;
+
+	*freep = 0;
+	bulk_alloc = 0;
+	memset(&key, 0, sizeof(key));
+	memset(&data, 0, sizeof(data));
+
+	/* Set up key and data DBT */
+	key.dlen = keydlen;
+	key.ulen = keyulen;
+	key.doff = keydoff;
+	/*
+	 * Ignore memory related flags on server.
+	 */
+	key.flags = DB_DBT_MALLOC;
+	if (keyflags & DB_DBT_PARTIAL)
+		key.flags |= DB_DBT_PARTIAL;
+	key.size = keysize;
+	key.data = keydata;
+
+	data.dlen = datadlen;
+	data.ulen = dataulen;
+	data.doff = datadoff;
+	data.size = datasize;
+	data.data = datadata;
+	if (flags & DB_MULTIPLE || flags & DB_MULTIPLE_KEY) {
+		if (data.data == 0) {
+			ret = __os_umalloc(dbenv, data.ulen, &data.data);
+			if (ret != 0)
+				goto err;
+			bulk_alloc = 1;
+		}
+		data.flags |= DB_DBT_USERMEM;
+	} else
+		data.flags |= DB_DBT_MALLOC;
+	if (dataflags & DB_DBT_PARTIAL)
+		data.flags |= DB_DBT_PARTIAL;
+
+	/* Got all our stuff, now do the get */
+	ret = dbc->c_get(dbc, &key, &data, flags);
+
+	/*
+	 * Otherwise just status.
+	 */
+	if (ret == 0) {
+		/*
+		 * XXX
+		 * We need to xdr_free whatever we are returning, next time.
+		 * However, DB does not allocate a new key if one was given
+		 * and we'd be free'ing up space allocated in the request.
+		 * So, allocate a new key/data pointer if it is the same one
+		 * as in the request.
+		 */
+		*freep = 1;
+		/*
+		 * Key
+		 */
+		key_alloc = 0;
+		if (key.data == keydata) {
+			ret = __os_umalloc(dbenv, key.size,
+			    &replyp->keydata.keydata_val);
+			if (ret != 0) {
+				__os_ufree(dbenv, key.data);
+				__os_ufree(dbenv, data.data);
+				goto err;
+			}
+			key_alloc = 1;
+			memcpy(replyp->keydata.keydata_val, key.data, key.size);
+		} else
+			replyp->keydata.keydata_val = key.data;
+
+		replyp->keydata.keydata_len = key.size;
+
+		/*
+		 * Data
+		 */
+		if (data.data == datadata) {
+			ret = __os_umalloc(dbenv, data.size,
+			    &replyp->datadata.datadata_val);
+			if (ret != 0) {
+				__os_ufree(dbenv, key.data);
+				__os_ufree(dbenv, data.data);
+				if (key_alloc)
+					__os_ufree(
+					    dbenv, replyp->keydata.keydata_val);
+				goto err;
+			}
+			memcpy(replyp->datadata.datadata_val, data.data,
+			    data.size);
+		} else
+			replyp->datadata.datadata_val = data.data;
+		replyp->datadata.datadata_len = data.size;
+	} else {
+err:		replyp->keydata.keydata_val = NULL;
+		replyp->keydata.keydata_len = 0;
+		replyp->datadata.datadata_val = NULL;
+		replyp->datadata.datadata_len = 0;
+		*freep = 0;
+		if (bulk_alloc)
+			__os_ufree(dbenv, data.data);
+	}
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __dbc_pget_proc __P((long, u_int32_t, u_int32_t, u_int32_t,
+ * PUBLIC:     u_int32_t, void *, u_int32_t, u_int32_t, u_int32_t, u_int32_t,
+ * PUBLIC:     u_int32_t, void *, u_int32_t, u_int32_t, u_int32_t, u_int32_t,
+ * PUBLIC:     u_int32_t, void *, u_int32_t, u_int32_t, __dbc_pget_reply *,
+ * PUBLIC:     int *));
+ */
+void
+__dbc_pget_proc(dbccl_id, skeydlen, skeydoff, skeyulen, skeyflags,
+    skeydata, skeysize, pkeydlen, pkeydoff, pkeyulen, pkeyflags, pkeydata,
+    pkeysize, datadlen, datadoff, dataulen, dataflags, datadata, datasize,
+    flags, replyp, freep)
+	long dbccl_id;
+	u_int32_t skeydlen;
+	u_int32_t skeydoff;
+	u_int32_t skeyulen;
+	u_int32_t skeyflags;
+	void *skeydata;
+	u_int32_t skeysize;
+	u_int32_t pkeydlen;
+	u_int32_t pkeydoff;
+	u_int32_t pkeyulen;
+	u_int32_t pkeyflags;
+	void *pkeydata;
+	u_int32_t pkeysize;
+	u_int32_t datadlen;
+	u_int32_t datadoff;
+	u_int32_t dataulen;
+	u_int32_t dataflags;
+	void *datadata;
+	u_int32_t datasize;
+	u_int32_t flags;
+	__dbc_pget_reply *replyp;
+	int * freep;
+{
+	DBC *dbc;
+	DBT skey, pkey, data;
+	DB_ENV *dbenv;
+	ct_entry *dbc_ctp;
+	int key_alloc, ret;
+
+	ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+	dbc = (DBC *)dbc_ctp->ct_anyp;
+	dbenv = dbc->dbp->dbenv;
+
+	*freep = 0;
+	memset(&skey, 0, sizeof(skey));
+	memset(&pkey, 0, sizeof(pkey));
+	memset(&data, 0, sizeof(data));
+
+	/*
+	 * Ignore memory related flags on server.
+	 */
+	/* Set up key and data DBT */
+	skey.flags = DB_DBT_MALLOC;
+	skey.dlen = skeydlen;
+	skey.ulen = skeyulen;
+	skey.doff = skeydoff;
+	if (skeyflags & DB_DBT_PARTIAL)
+		skey.flags |= DB_DBT_PARTIAL;
+	skey.size = skeysize;
+	skey.data = skeydata;
+
+	pkey.flags = DB_DBT_MALLOC;
+	pkey.dlen = pkeydlen;
+	pkey.ulen = pkeyulen;
+	pkey.doff = pkeydoff;
+	if (pkeyflags & DB_DBT_PARTIAL)
+		pkey.flags |= DB_DBT_PARTIAL;
+	pkey.size = pkeysize;
+	pkey.data = pkeydata;
+
+	data.flags = DB_DBT_MALLOC;
+	data.dlen = datadlen;
+	data.ulen = dataulen;
+	data.doff = datadoff;
+	if (dataflags & DB_DBT_PARTIAL)
+		data.flags |= DB_DBT_PARTIAL;
+	data.size = datasize;
+	data.data = datadata;
+
+	/* Got all our stuff, now do the get */
+	ret = dbc->c_pget(dbc, &skey, &pkey, &data, flags);
+	/*
+	 * Otherwise just status.
+	 */
+	if (ret == 0) {
+		/*
+		 * XXX
+		 * We need to xdr_free whatever we are returning, next time.
+		 * However, DB does not allocate a new key if one was given
+		 * and we'd be free'ing up space allocated in the request.
+		 * So, allocate a new key/data pointer if it is the same one
+		 * as in the request.
+		 */
+		*freep = 1;
+		/*
+		 * Key
+		 */
+		key_alloc = 0;
+		if (skey.data == skeydata) {
+			ret = __os_umalloc(dbenv,
+			    skey.size, &replyp->skeydata.skeydata_val);
+			if (ret != 0) {
+				__os_ufree(dbenv, skey.data);
+				__os_ufree(dbenv, pkey.data);
+				__os_ufree(dbenv, data.data);
+				goto err;
+			}
+			key_alloc = 1;
+			memcpy(replyp->skeydata.skeydata_val, skey.data,
+			    skey.size);
+		} else
+			replyp->skeydata.skeydata_val = skey.data;
+		replyp->skeydata.skeydata_len = skey.size;
+
+		/*
+		 * Primary key
+		 */
+		if (pkey.data == pkeydata) {
+			ret = __os_umalloc(dbenv,
+			     pkey.size, &replyp->pkeydata.pkeydata_val);
+			if (ret != 0) {
+				__os_ufree(dbenv, skey.data);
+				__os_ufree(dbenv, pkey.data);
+				__os_ufree(dbenv, data.data);
+				if (key_alloc)
+					__os_ufree(dbenv,
+					    replyp->skeydata.skeydata_val);
+				goto err;
+			}
+			/*
+			 * We can set it to 2, because they cannot send the
+			 * pkey over without sending the skey over too.
+			 * So if they did send a pkey, they must have sent
+			 * the skey as well.
+			 */
+			key_alloc = 2;
+			memcpy(replyp->pkeydata.pkeydata_val, pkey.data,
+			    pkey.size);
+		} else
+			replyp->pkeydata.pkeydata_val = pkey.data;
+		replyp->pkeydata.pkeydata_len = pkey.size;
+
+		/*
+		 * Data
+		 */
+		if (data.data == datadata) {
+			ret = __os_umalloc(dbenv,
+			     data.size, &replyp->datadata.datadata_val);
+			if (ret != 0) {
+				__os_ufree(dbenv, skey.data);
+				__os_ufree(dbenv, pkey.data);
+				__os_ufree(dbenv, data.data);
+				/*
+				 * If key_alloc is 1, just skey needs to be
+				 * freed, if key_alloc is 2, both skey and pkey
+				 * need to be freed.
+				 */
+				if (key_alloc--)
+					__os_ufree(dbenv,
+					    replyp->skeydata.skeydata_val);
+				if (key_alloc)
+					__os_ufree(dbenv,
+					    replyp->pkeydata.pkeydata_val);
+				goto err;
+			}
+			memcpy(replyp->datadata.datadata_val, data.data,
+			    data.size);
+		} else
+			replyp->datadata.datadata_val = data.data;
+		replyp->datadata.datadata_len = data.size;
+	} else {
+err:		replyp->skeydata.skeydata_val = NULL;
+		replyp->skeydata.skeydata_len = 0;
+		replyp->pkeydata.pkeydata_val = NULL;
+		replyp->pkeydata.pkeydata_len = 0;
+		replyp->datadata.datadata_val = NULL;
+		replyp->datadata.datadata_len = 0;
+		*freep = 0;
+	}
+	replyp->status = ret;
+	return;
+}
+
+/*
+ * PUBLIC: void __dbc_put_proc __P((long, u_int32_t, u_int32_t, u_int32_t,
+ * PUBLIC:     u_int32_t, void *, u_int32_t, u_int32_t, u_int32_t, u_int32_t,
+ * PUBLIC:     u_int32_t, void *, u_int32_t, u_int32_t, __dbc_put_reply *,
+ * PUBLIC:     int *));
+ */
+void
+__dbc_put_proc(dbccl_id, keydlen, keydoff, keyulen, keyflags, keydata,
+    keysize, datadlen, datadoff, dataulen, dataflags, datadata, datasize,
+    flags, replyp, freep)
+	long dbccl_id;
+	u_int32_t keydlen;
+	u_int32_t keydoff;
+	u_int32_t keyulen;
+	u_int32_t keyflags;
+	void *keydata;
+	u_int32_t keysize;
+	u_int32_t datadlen;
+	u_int32_t datadoff;
+	u_int32_t dataulen;
+	u_int32_t dataflags;
+	void *datadata;
+	u_int32_t datasize;
+	u_int32_t flags;
+	__dbc_put_reply *replyp;
+	int * freep;
+{
+	DB *dbp;
+	DBC *dbc;
+	DBT key, data;
+	ct_entry *dbc_ctp;
+	int ret;
+
+	ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
+	dbc = (DBC *)dbc_ctp->ct_anyp;
+	dbp = (DB *)dbc_ctp->ct_parent->ct_anyp;
+
+	memset(&key, 0, sizeof(key));
+	memset(&data, 0, sizeof(data));
+
+	/* Set up key and data DBT */
+	key.dlen = keydlen;
+	key.ulen = keyulen;
+	key.doff = keydoff;
+	/*
+	 * Ignore memory related flags on server.
+	 */
+	key.flags = 0;
+	if (keyflags & DB_DBT_PARTIAL)
+		key.flags |= DB_DBT_PARTIAL;
+	key.size = keysize;
+	key.data = keydata;
+
+	data.dlen = datadlen;
+	data.ulen = dataulen;
+	data.doff = datadoff;
+	data.flags = dataflags;
+	data.size = datasize;
+	data.data = datadata;
+
+	/* Got all our stuff, now do the put */
+	ret = dbc->c_put(dbc, &key, &data, flags);
+
+	*freep = 0;
+	if (ret == 0 && (flags == DB_AFTER || flags == DB_BEFORE) &&
+	    dbp->type == DB_RECNO) {
+		/*
+		 * We need to xdr_free whatever we are returning, next time.
+		 */
+		replyp->keydata.keydata_val = key.data;
+		replyp->keydata.keydata_len = key.size;
+	} else {
+		replyp->keydata.keydata_val = NULL;
+		replyp->keydata.keydata_len = 0;
+	}
+	replyp->status = ret;
+	return;
+}
diff --git a/storage/bdb/rpc_server/c/db_server_util.c b/storage/bdb/rpc_server/c/db_server_util.c
index 2ea270c2d198e5f188af04b30568aa4712d9aa1e..11bc4deb39c05423c4977197799bda82b9760d17 100644
--- a/storage/bdb/rpc_server/c/db_server_util.c
+++ b/storage/bdb/rpc_server/c/db_server_util.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2000-2002
+ * Copyright (c) 2000-2004
  *      Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_server_util.c,v 1.72 2004/09/22 17:30:12 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_server_util.c,v 1.59 2002/03/27 04:32:50 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -34,15 +32,15 @@ static const char revid[] = "$Id: db_server_util.c,v 1.59 2002/03/27 04:32:50 bo
 #include <string.h>
 #include <unistd.h>
 #endif
-#include "dbinc_auto/db_server.h"
+
+#include "db_server.h"
 
 #include "db_int.h"
 #include "dbinc_auto/clib_ext.h"
 #include "dbinc/db_server_int.h"
-#include "dbinc_auto/rpc_server_ext.h"
 #include "dbinc_auto/common_ext.h"
+#include "dbinc_auto/rpc_server_ext.h"
 
-extern int __dbsrv_main	 __P((void));
 static int add_home __P((char *));
 static int add_passwd __P((char *));
 static int env_recover __P((char *));
@@ -56,7 +54,7 @@ static long __dbsrv_idleto = DB_SERVER_IDLETIMEOUT;
 static char *logfile = NULL;
 static char *prog;
 
-static void usage __P((char *));
+static void usage __P((void));
 static void version_check __P((void));
 
 int __dbsrv_verbose = 0;
@@ -66,6 +64,7 @@ main(argc, argv)
 	int argc;
 	char **argv;
 {
+	extern int __dbsrv_main();
 	extern char *optarg;
 	CLIENT *cl;
 	int ch, ret;
@@ -141,7 +140,7 @@ main(argc, argv)
 			__dbsrv_verbose = 1;
 			break;
 		default:
-			usage(prog);
+			usage();
 		}
 	/*
 	 * Check default timeout against maximum timeout
@@ -155,7 +154,7 @@ main(argc, argv)
 	 */
 	if (__dbsrv_defto > __dbsrv_idleto)
 		fprintf(stderr,
-		    "%s: WARNING: Idle timeout %ld is less than resource timeout %ld\n",
+	    "%s: WARNING: Idle timeout %ld is less than resource timeout %ld\n",
 		    prog, __dbsrv_idleto, __dbsrv_defto);
 
 	LIST_INIT(&__dbsrv_head);
@@ -185,13 +184,14 @@ main(argc, argv)
 		printf("%s:  Ready to receive requests\n", prog);
 	__dbsrv_main();
 
-	/* NOTREACHED */
 	abort();
+
+	/* NOTREACHED */
+	return (0);
 }
 
 static void
-usage(prog)
-	char *prog;
+usage()
 {
 	fprintf(stderr, "usage: %s %s\n\t%s\n", prog,
 	    "[-Vv] [-h home] [-P passwd]",
@@ -416,7 +416,7 @@ new_ct_ent(errp)
 	octp = LIST_FIRST(&__dbsrv_head);
 	if (octp != NULL && octp->ct_id >= t)
 		t = octp->ct_id + 1;
-	ctp->ct_id = t;
+	ctp->ct_id = (long)t;
 	ctp->ct_idle = __dbsrv_idleto;
 	ctp->ct_activep = &ctp->ct_active;
 	ctp->ct_origp = NULL;
@@ -504,7 +504,8 @@ __dbsrv_sharedb(db_ctp, name, subdb, type, flags)
 }
 
 /*
- * PUBLIC: ct_entry *__dbsrv_shareenv __P((ct_entry *, home_entry *, u_int32_t));
+ * PUBLIC: ct_entry *__dbsrv_shareenv
+ * PUBLIC:     __P((ct_entry *, home_entry *, u_int32_t));
  */
 ct_entry *
 __dbsrv_shareenv(env_ctp, home, flags)
@@ -652,7 +653,7 @@ __dbenv_close_int(id, flags, force)
 {
 	DB_ENV *dbenv;
 	int ret;
-	ct_entry *ctp;
+	ct_entry *ctp, *dbctp, *nextctp;
 
 	ret = 0;
 	ctp = get_tableent(id);
@@ -672,6 +673,31 @@ __dbenv_close_int(id, flags, force)
 	if (__dbsrv_verbose)
 		printf("Closing env id %ld\n", id);
 
+	/*
+	 * If we're timing out an env, we want to close all of its
+	 * database handles as well.  All of the txns and cursors
+	 * must have been timed out prior to timing out the env.
+	 */
+	if (force)
+		for (dbctp = LIST_FIRST(&__dbsrv_head);
+		    dbctp != NULL; dbctp = nextctp) {
+			nextctp = LIST_NEXT(dbctp, entries);
+			if (dbctp->ct_type != CT_DB)
+				continue;
+			if (dbctp->ct_envparent != ctp)
+				continue;
+			/*
+			 * We found a DB handle that is part of this
+			 * environment.  Close it.
+			 */
+			__db_close_int(dbctp->ct_id, 0);
+			/*
+			 * If we timed out a dbp, we may have removed
+			 * multiple ctp entries.  Start over with a
+			 * guaranteed good ctp.
+			 */
+			nextctp = LIST_FIRST(&__dbsrv_head);
+		}
 	ret = dbenv->close(dbenv, flags);
 	__dbdel_ctp(ctp);
 	return (ret);
@@ -696,8 +722,11 @@ add_home(home)
 	 * to assure hp->name points to the last component.
 	 */
 	hp->name = __db_rpath(home);
-	*(hp->name) = '\0';
-	hp->name++;
+	if (hp->name != NULL) {
+		*(hp->name) = '\0';
+		hp->name++;
+	} else
+		hp->name = home;
 	while (*(hp->name) == '\0') {
 		hp->name = __db_rpath(home);
 		*(hp->name) = '\0';
@@ -745,14 +774,16 @@ add_passwd(passwd)
 }
 
 /*
- * PUBLIC: home_entry *get_home __P((char *));
+ * PUBLIC: home_entry *get_fullhome __P((char *));
  */
 home_entry *
-get_home(name)
+get_fullhome(name)
 	char *name;
 {
 	home_entry *hp;
 
+	if (name == NULL)
+		return (NULL);
 	for (hp = LIST_FIRST(&__dbsrv_home); hp != NULL;
 	    hp = LIST_NEXT(hp, entries))
 		if (strcmp(name, hp->name) == 0)
@@ -777,10 +808,8 @@ env_recover(progname)
 			    progname, db_strerror(ret));
 			exit(EXIT_FAILURE);
 		}
-		if (__dbsrv_verbose == 1) {
+		if (__dbsrv_verbose == 1)
 			(void)dbenv->set_verbose(dbenv, DB_VERB_RECOVERY, 1);
-			(void)dbenv->set_verbose(dbenv, DB_VERB_CHKPOINT, 1);
-		}
 		dbenv->set_errfile(dbenv, stderr);
 		dbenv->set_errpfx(dbenv, progname);
 		if (hp->passwd != NULL)
diff --git a/storage/bdb/rpc_server/c/gen_db_server.c b/storage/bdb/rpc_server/c/gen_db_server.c
new file mode 100644
index 0000000000000000000000000000000000000000..c5f3a7e0b242aa80bf2df032a0dcb53aefceeeeb
--- /dev/null
+++ b/storage/bdb/rpc_server/c/gen_db_server.c
@@ -0,0 +1,1222 @@
+/* Do not edit: automatically built by gen_rpc.awk. */
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <rpc/rpc.h>
+
+#include <string.h>
+#endif
+
+#include "db_server.h"
+
+#include "db_int.h"
+#include "dbinc/db_server_int.h"
+#include "dbinc_auto/rpc_server_ext.h"
+
+__env_get_cachesize_reply *
+__db_env_get_cachesize_4003__SVCSUFFIX__(msg, req)
+	__env_get_cachesize_msg *msg;
+	struct svc_req *req;
+{
+	static __env_get_cachesize_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__env_get_cachesize_proc(msg->dbenvcl_id,
+	    &reply);
+
+	return (&reply);
+}
+
+__env_cachesize_reply *
+__db_env_cachesize_4003__SVCSUFFIX__(msg, req)
+	__env_cachesize_msg *msg;
+	struct svc_req *req;
+{
+	static __env_cachesize_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__env_cachesize_proc(msg->dbenvcl_id,
+	    msg->gbytes,
+	    msg->bytes,
+	    msg->ncache,
+	    &reply);
+
+	return (&reply);
+}
+
+__env_close_reply *
+__db_env_close_4003__SVCSUFFIX__(msg, req)
+	__env_close_msg *msg;
+	struct svc_req *req;
+{
+	static __env_close_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__env_close_proc(msg->dbenvcl_id,
+	    msg->flags,
+	    &reply);
+
+	return (&reply);
+}
+
+__env_create_reply *
+__db_env_create_4003__SVCSUFFIX__(msg, req)
+	__env_create_msg *msg;
+	struct svc_req *req;
+{
+	static __env_create_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__env_create_proc(msg->timeout,
+	    &reply);
+
+	return (&reply);
+}
+
+__env_dbremove_reply *
+__db_env_dbremove_4003__SVCSUFFIX__(msg, req)
+	__env_dbremove_msg *msg;
+	struct svc_req *req;
+{
+	static __env_dbremove_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__env_dbremove_proc(msg->dbenvcl_id,
+	    msg->txnpcl_id,
+	    (*msg->name == '\0') ? NULL : msg->name,
+	    (*msg->subdb == '\0') ? NULL : msg->subdb,
+	    msg->flags,
+	    &reply);
+
+	return (&reply);
+}
+
+__env_dbrename_reply *
+__db_env_dbrename_4003__SVCSUFFIX__(msg, req)
+	__env_dbrename_msg *msg;
+	struct svc_req *req;
+{
+	static __env_dbrename_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__env_dbrename_proc(msg->dbenvcl_id,
+	    msg->txnpcl_id,
+	    (*msg->name == '\0') ? NULL : msg->name,
+	    (*msg->subdb == '\0') ? NULL : msg->subdb,
+	    (*msg->newname == '\0') ? NULL : msg->newname,
+	    msg->flags,
+	    &reply);
+
+	return (&reply);
+}
+
+__env_get_encrypt_flags_reply *
+__db_env_get_encrypt_flags_4003__SVCSUFFIX__(msg, req)
+	__env_get_encrypt_flags_msg *msg;
+	struct svc_req *req;
+{
+	static __env_get_encrypt_flags_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__env_get_encrypt_flags_proc(msg->dbenvcl_id,
+	    &reply);
+
+	return (&reply);
+}
+
+__env_encrypt_reply *
+__db_env_encrypt_4003__SVCSUFFIX__(msg, req)
+	__env_encrypt_msg *msg;
+	struct svc_req *req;
+{
+	static __env_encrypt_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__env_encrypt_proc(msg->dbenvcl_id,
+	    (*msg->passwd == '\0') ? NULL : msg->passwd,
+	    msg->flags,
+	    &reply);
+
+	return (&reply);
+}
+
+__env_get_flags_reply *
+__db_env_get_flags_4003__SVCSUFFIX__(msg, req)
+	__env_get_flags_msg *msg;
+	struct svc_req *req;
+{
+	static __env_get_flags_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__env_get_flags_proc(msg->dbenvcl_id,
+	    &reply);
+
+	return (&reply);
+}
+
+__env_flags_reply *
+__db_env_flags_4003__SVCSUFFIX__(msg, req)
+	__env_flags_msg *msg;
+	struct svc_req *req;
+{
+	static __env_flags_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__env_flags_proc(msg->dbenvcl_id,
+	    msg->flags,
+	    msg->onoff,
+	    &reply);
+
+	return (&reply);
+}
+
+__env_get_home_reply *
+__db_env_get_home_4003__SVCSUFFIX__(msg, req)
+	__env_get_home_msg *msg;
+	struct svc_req *req;
+{
+	static __env_get_home_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__env_get_home_proc(msg->dbenvcl_id,
+	    &reply);
+
+	return (&reply);
+}
+
+__env_get_open_flags_reply *
+__db_env_get_open_flags_4003__SVCSUFFIX__(msg, req)
+	__env_get_open_flags_msg *msg;
+	struct svc_req *req;
+{
+	static __env_get_open_flags_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__env_get_open_flags_proc(msg->dbenvcl_id,
+	    &reply);
+
+	return (&reply);
+}
+
+__env_open_reply *
+__db_env_open_4003__SVCSUFFIX__(msg, req)
+	__env_open_msg *msg;
+	struct svc_req *req;
+{
+	static __env_open_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__env_open_proc(msg->dbenvcl_id,
+	    (*msg->home == '\0') ? NULL : msg->home,
+	    msg->flags,
+	    msg->mode,
+	    &reply);
+
+	return (&reply);
+}
+
+__env_remove_reply *
+__db_env_remove_4003__SVCSUFFIX__(msg, req)
+	__env_remove_msg *msg;
+	struct svc_req *req;
+{
+	static __env_remove_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__env_remove_proc(msg->dbenvcl_id,
+	    (*msg->home == '\0') ? NULL : msg->home,
+	    msg->flags,
+	    &reply);
+
+	return (&reply);
+}
+
+__txn_abort_reply *
+__db_txn_abort_4003__SVCSUFFIX__(msg, req)
+	__txn_abort_msg *msg;
+	struct svc_req *req;
+{
+	static __txn_abort_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__txn_abort_proc(msg->txnpcl_id,
+	    &reply);
+
+	return (&reply);
+}
+
+__txn_begin_reply *
+__db_txn_begin_4003__SVCSUFFIX__(msg, req)
+	__txn_begin_msg *msg;
+	struct svc_req *req;
+{
+	static __txn_begin_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__txn_begin_proc(msg->dbenvcl_id,
+	    msg->parentcl_id,
+	    msg->flags,
+	    &reply);
+
+	return (&reply);
+}
+
+__txn_commit_reply *
+__db_txn_commit_4003__SVCSUFFIX__(msg, req)
+	__txn_commit_msg *msg;
+	struct svc_req *req;
+{
+	static __txn_commit_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__txn_commit_proc(msg->txnpcl_id,
+	    msg->flags,
+	    &reply);
+
+	return (&reply);
+}
+
+__txn_discard_reply *
+__db_txn_discard_4003__SVCSUFFIX__(msg, req)
+	__txn_discard_msg *msg;
+	struct svc_req *req;
+{
+	static __txn_discard_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__txn_discard_proc(msg->txnpcl_id,
+	    msg->flags,
+	    &reply);
+
+	return (&reply);
+}
+
+__txn_prepare_reply *
+__db_txn_prepare_4003__SVCSUFFIX__(msg, req)
+	__txn_prepare_msg *msg;
+	struct svc_req *req;
+{
+	static __txn_prepare_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__txn_prepare_proc(msg->txnpcl_id,
+	    (u_int8_t *)msg->gid,
+	    &reply);
+
+	return (&reply);
+}
+
+__txn_recover_reply *
+__db_txn_recover_4003__SVCSUFFIX__(msg, req)
+	__txn_recover_msg *msg;
+	struct svc_req *req;
+{
+	static __txn_recover_reply reply; /* must be static */
+	static int __txn_recover_free = 0; /* must be static */
+
+	COMPQUIET(req, NULL);
+	if (__txn_recover_free)
+		xdr_free((xdrproc_t)xdr___txn_recover_reply, (void *)&reply);
+	__txn_recover_free = 0;
+
+	/* Reinitialize allocated fields */
+	reply.txn.txn_val = NULL;
+	reply.gid.gid_val = NULL;
+
+	__txn_recover_proc(msg->dbenvcl_id,
+	    msg->count,
+	    msg->flags,
+	    &reply,
+	    &__txn_recover_free);
+	return (&reply);
+}
+
+__db_associate_reply *
+__db_db_associate_4003__SVCSUFFIX__(msg, req)
+	__db_associate_msg *msg;
+	struct svc_req *req;
+{
+	static __db_associate_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_associate_proc(msg->dbpcl_id,
+	    msg->txnpcl_id,
+	    msg->sdbpcl_id,
+	    msg->flags,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_bt_maxkey_reply *
+__db_db_bt_maxkey_4003__SVCSUFFIX__(msg, req)
+	__db_bt_maxkey_msg *msg;
+	struct svc_req *req;
+{
+	static __db_bt_maxkey_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_bt_maxkey_proc(msg->dbpcl_id,
+	    msg->maxkey,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_get_bt_minkey_reply *
+__db_db_get_bt_minkey_4003__SVCSUFFIX__(msg, req)
+	__db_get_bt_minkey_msg *msg;
+	struct svc_req *req;
+{
+	static __db_get_bt_minkey_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_get_bt_minkey_proc(msg->dbpcl_id,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_bt_minkey_reply *
+__db_db_bt_minkey_4003__SVCSUFFIX__(msg, req)
+	__db_bt_minkey_msg *msg;
+	struct svc_req *req;
+{
+	static __db_bt_minkey_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_bt_minkey_proc(msg->dbpcl_id,
+	    msg->minkey,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_close_reply *
+__db_db_close_4003__SVCSUFFIX__(msg, req)
+	__db_close_msg *msg;
+	struct svc_req *req;
+{
+	static __db_close_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_close_proc(msg->dbpcl_id,
+	    msg->flags,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_create_reply *
+__db_db_create_4003__SVCSUFFIX__(msg, req)
+	__db_create_msg *msg;
+	struct svc_req *req;
+{
+	static __db_create_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_create_proc(msg->dbenvcl_id,
+	    msg->flags,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_del_reply *
+__db_db_del_4003__SVCSUFFIX__(msg, req)
+	__db_del_msg *msg;
+	struct svc_req *req;
+{
+	static __db_del_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_del_proc(msg->dbpcl_id,
+	    msg->txnpcl_id,
+	    msg->keydlen,
+	    msg->keydoff,
+	    msg->keyulen,
+	    msg->keyflags,
+	    msg->keydata.keydata_val,
+	    msg->keydata.keydata_len,
+	    msg->flags,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_get_encrypt_flags_reply *
+__db_db_get_encrypt_flags_4003__SVCSUFFIX__(msg, req)
+	__db_get_encrypt_flags_msg *msg;
+	struct svc_req *req;
+{
+	static __db_get_encrypt_flags_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_get_encrypt_flags_proc(msg->dbpcl_id,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_encrypt_reply *
+__db_db_encrypt_4003__SVCSUFFIX__(msg, req)
+	__db_encrypt_msg *msg;
+	struct svc_req *req;
+{
+	static __db_encrypt_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_encrypt_proc(msg->dbpcl_id,
+	    (*msg->passwd == '\0') ? NULL : msg->passwd,
+	    msg->flags,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_get_extentsize_reply *
+__db_db_get_extentsize_4003__SVCSUFFIX__(msg, req)
+	__db_get_extentsize_msg *msg;
+	struct svc_req *req;
+{
+	static __db_get_extentsize_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_get_extentsize_proc(msg->dbpcl_id,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_extentsize_reply *
+__db_db_extentsize_4003__SVCSUFFIX__(msg, req)
+	__db_extentsize_msg *msg;
+	struct svc_req *req;
+{
+	static __db_extentsize_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_extentsize_proc(msg->dbpcl_id,
+	    msg->extentsize,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_get_flags_reply *
+__db_db_get_flags_4003__SVCSUFFIX__(msg, req)
+	__db_get_flags_msg *msg;
+	struct svc_req *req;
+{
+	static __db_get_flags_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_get_flags_proc(msg->dbpcl_id,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_flags_reply *
+__db_db_flags_4003__SVCSUFFIX__(msg, req)
+	__db_flags_msg *msg;
+	struct svc_req *req;
+{
+	static __db_flags_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_flags_proc(msg->dbpcl_id,
+	    msg->flags,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_get_reply *
+__db_db_get_4003__SVCSUFFIX__(msg, req)
+	__db_get_msg *msg;
+	struct svc_req *req;
+{
+	static __db_get_reply reply; /* must be static */
+	static int __db_get_free = 0; /* must be static */
+
+	COMPQUIET(req, NULL);
+	if (__db_get_free)
+		xdr_free((xdrproc_t)xdr___db_get_reply, (void *)&reply);
+	__db_get_free = 0;
+
+	/* Reinitialize allocated fields */
+	reply.keydata.keydata_val = NULL;
+	reply.datadata.datadata_val = NULL;
+
+	__db_get_proc(msg->dbpcl_id,
+	    msg->txnpcl_id,
+	    msg->keydlen,
+	    msg->keydoff,
+	    msg->keyulen,
+	    msg->keyflags,
+	    msg->keydata.keydata_val,
+	    msg->keydata.keydata_len,
+	    msg->datadlen,
+	    msg->datadoff,
+	    msg->dataulen,
+	    msg->dataflags,
+	    msg->datadata.datadata_val,
+	    msg->datadata.datadata_len,
+	    msg->flags,
+	    &reply,
+	    &__db_get_free);
+	return (&reply);
+}
+
+__db_get_name_reply *
+__db_db_get_name_4003__SVCSUFFIX__(msg, req)
+	__db_get_name_msg *msg;
+	struct svc_req *req;
+{
+	static __db_get_name_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_get_name_proc(msg->dbpcl_id,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_get_open_flags_reply *
+__db_db_get_open_flags_4003__SVCSUFFIX__(msg, req)
+	__db_get_open_flags_msg *msg;
+	struct svc_req *req;
+{
+	static __db_get_open_flags_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_get_open_flags_proc(msg->dbpcl_id,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_get_h_ffactor_reply *
+__db_db_get_h_ffactor_4003__SVCSUFFIX__(msg, req)
+	__db_get_h_ffactor_msg *msg;
+	struct svc_req *req;
+{
+	static __db_get_h_ffactor_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_get_h_ffactor_proc(msg->dbpcl_id,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_h_ffactor_reply *
+__db_db_h_ffactor_4003__SVCSUFFIX__(msg, req)
+	__db_h_ffactor_msg *msg;
+	struct svc_req *req;
+{
+	static __db_h_ffactor_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_h_ffactor_proc(msg->dbpcl_id,
+	    msg->ffactor,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_get_h_nelem_reply *
+__db_db_get_h_nelem_4003__SVCSUFFIX__(msg, req)
+	__db_get_h_nelem_msg *msg;
+	struct svc_req *req;
+{
+	static __db_get_h_nelem_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_get_h_nelem_proc(msg->dbpcl_id,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_h_nelem_reply *
+__db_db_h_nelem_4003__SVCSUFFIX__(msg, req)
+	__db_h_nelem_msg *msg;
+	struct svc_req *req;
+{
+	static __db_h_nelem_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_h_nelem_proc(msg->dbpcl_id,
+	    msg->nelem,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_key_range_reply *
+__db_db_key_range_4003__SVCSUFFIX__(msg, req)
+	__db_key_range_msg *msg;
+	struct svc_req *req;
+{
+	static __db_key_range_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_key_range_proc(msg->dbpcl_id,
+	    msg->txnpcl_id,
+	    msg->keydlen,
+	    msg->keydoff,
+	    msg->keyulen,
+	    msg->keyflags,
+	    msg->keydata.keydata_val,
+	    msg->keydata.keydata_len,
+	    msg->flags,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_get_lorder_reply *
+__db_db_get_lorder_4003__SVCSUFFIX__(msg, req)
+	__db_get_lorder_msg *msg;
+	struct svc_req *req;
+{
+	static __db_get_lorder_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_get_lorder_proc(msg->dbpcl_id,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_lorder_reply *
+__db_db_lorder_4003__SVCSUFFIX__(msg, req)
+	__db_lorder_msg *msg;
+	struct svc_req *req;
+{
+	static __db_lorder_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_lorder_proc(msg->dbpcl_id,
+	    msg->lorder,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_open_reply *
+__db_db_open_4003__SVCSUFFIX__(msg, req)
+	__db_open_msg *msg;
+	struct svc_req *req;
+{
+	static __db_open_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_open_proc(msg->dbpcl_id,
+	    msg->txnpcl_id,
+	    (*msg->name == '\0') ? NULL : msg->name,
+	    (*msg->subdb == '\0') ? NULL : msg->subdb,
+	    msg->type,
+	    msg->flags,
+	    msg->mode,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_get_pagesize_reply *
+__db_db_get_pagesize_4003__SVCSUFFIX__(msg, req)
+	__db_get_pagesize_msg *msg;
+	struct svc_req *req;
+{
+	static __db_get_pagesize_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_get_pagesize_proc(msg->dbpcl_id,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_pagesize_reply *
+__db_db_pagesize_4003__SVCSUFFIX__(msg, req)
+	__db_pagesize_msg *msg;
+	struct svc_req *req;
+{
+	static __db_pagesize_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_pagesize_proc(msg->dbpcl_id,
+	    msg->pagesize,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_pget_reply *
+__db_db_pget_4003__SVCSUFFIX__(msg, req)
+	__db_pget_msg *msg;
+	struct svc_req *req;
+{
+	static __db_pget_reply reply; /* must be static */
+	static int __db_pget_free = 0; /* must be static */
+
+	COMPQUIET(req, NULL);
+	if (__db_pget_free)
+		xdr_free((xdrproc_t)xdr___db_pget_reply, (void *)&reply);
+	__db_pget_free = 0;
+
+	/* Reinitialize allocated fields */
+	reply.skeydata.skeydata_val = NULL;
+	reply.pkeydata.pkeydata_val = NULL;
+	reply.datadata.datadata_val = NULL;
+
+	__db_pget_proc(msg->dbpcl_id,
+	    msg->txnpcl_id,
+	    msg->skeydlen,
+	    msg->skeydoff,
+	    msg->skeyulen,
+	    msg->skeyflags,
+	    msg->skeydata.skeydata_val,
+	    msg->skeydata.skeydata_len,
+	    msg->pkeydlen,
+	    msg->pkeydoff,
+	    msg->pkeyulen,
+	    msg->pkeyflags,
+	    msg->pkeydata.pkeydata_val,
+	    msg->pkeydata.pkeydata_len,
+	    msg->datadlen,
+	    msg->datadoff,
+	    msg->dataulen,
+	    msg->dataflags,
+	    msg->datadata.datadata_val,
+	    msg->datadata.datadata_len,
+	    msg->flags,
+	    &reply,
+	    &__db_pget_free);
+	return (&reply);
+}
+
+__db_put_reply *
+__db_db_put_4003__SVCSUFFIX__(msg, req)
+	__db_put_msg *msg;
+	struct svc_req *req;
+{
+	static __db_put_reply reply; /* must be static */
+	static int __db_put_free = 0; /* must be static */
+
+	COMPQUIET(req, NULL);
+	if (__db_put_free)
+		xdr_free((xdrproc_t)xdr___db_put_reply, (void *)&reply);
+	__db_put_free = 0;
+
+	/* Reinitialize allocated fields */
+	reply.keydata.keydata_val = NULL;
+
+	__db_put_proc(msg->dbpcl_id,
+	    msg->txnpcl_id,
+	    msg->keydlen,
+	    msg->keydoff,
+	    msg->keyulen,
+	    msg->keyflags,
+	    msg->keydata.keydata_val,
+	    msg->keydata.keydata_len,
+	    msg->datadlen,
+	    msg->datadoff,
+	    msg->dataulen,
+	    msg->dataflags,
+	    msg->datadata.datadata_val,
+	    msg->datadata.datadata_len,
+	    msg->flags,
+	    &reply,
+	    &__db_put_free);
+	return (&reply);
+}
+
+__db_get_re_delim_reply *
+__db_db_get_re_delim_4003__SVCSUFFIX__(msg, req)
+	__db_get_re_delim_msg *msg;
+	struct svc_req *req;
+{
+	static __db_get_re_delim_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_get_re_delim_proc(msg->dbpcl_id,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_re_delim_reply *
+__db_db_re_delim_4003__SVCSUFFIX__(msg, req)
+	__db_re_delim_msg *msg;
+	struct svc_req *req;
+{
+	static __db_re_delim_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_re_delim_proc(msg->dbpcl_id,
+	    msg->delim,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_get_re_len_reply *
+__db_db_get_re_len_4003__SVCSUFFIX__(msg, req)
+	__db_get_re_len_msg *msg;
+	struct svc_req *req;
+{
+	static __db_get_re_len_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_get_re_len_proc(msg->dbpcl_id,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_re_len_reply *
+__db_db_re_len_4003__SVCSUFFIX__(msg, req)
+	__db_re_len_msg *msg;
+	struct svc_req *req;
+{
+	static __db_re_len_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_re_len_proc(msg->dbpcl_id,
+	    msg->len,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_re_pad_reply *
+__db_db_re_pad_4003__SVCSUFFIX__(msg, req)
+	__db_re_pad_msg *msg;
+	struct svc_req *req;
+{
+	static __db_re_pad_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_re_pad_proc(msg->dbpcl_id,
+	    msg->pad,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_get_re_pad_reply *
+__db_db_get_re_pad_4003__SVCSUFFIX__(msg, req)
+	__db_get_re_pad_msg *msg;
+	struct svc_req *req;
+{
+	static __db_get_re_pad_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_get_re_pad_proc(msg->dbpcl_id,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_remove_reply *
+__db_db_remove_4003__SVCSUFFIX__(msg, req)
+	__db_remove_msg *msg;
+	struct svc_req *req;
+{
+	static __db_remove_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_remove_proc(msg->dbpcl_id,
+	    (*msg->name == '\0') ? NULL : msg->name,
+	    (*msg->subdb == '\0') ? NULL : msg->subdb,
+	    msg->flags,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_rename_reply *
+__db_db_rename_4003__SVCSUFFIX__(msg, req)
+	__db_rename_msg *msg;
+	struct svc_req *req;
+{
+	static __db_rename_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_rename_proc(msg->dbpcl_id,
+	    (*msg->name == '\0') ? NULL : msg->name,
+	    (*msg->subdb == '\0') ? NULL : msg->subdb,
+	    (*msg->newname == '\0') ? NULL : msg->newname,
+	    msg->flags,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_stat_reply *
+__db_db_stat_4003__SVCSUFFIX__(msg, req)
+	__db_stat_msg *msg;
+	struct svc_req *req;
+{
+	static __db_stat_reply reply; /* must be static */
+	static int __db_stat_free = 0; /* must be static */
+
+	COMPQUIET(req, NULL);
+	if (__db_stat_free)
+		xdr_free((xdrproc_t)xdr___db_stat_reply, (void *)&reply);
+	__db_stat_free = 0;
+
+	/* Reinitialize allocated fields */
+	reply.stats.stats_val = NULL;
+
+	__db_stat_proc(msg->dbpcl_id,
+	    msg->txnpcl_id,
+	    msg->flags,
+	    &reply,
+	    &__db_stat_free);
+	return (&reply);
+}
+
+__db_sync_reply *
+__db_db_sync_4003__SVCSUFFIX__(msg, req)
+	__db_sync_msg *msg;
+	struct svc_req *req;
+{
+	static __db_sync_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_sync_proc(msg->dbpcl_id,
+	    msg->flags,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_truncate_reply *
+__db_db_truncate_4003__SVCSUFFIX__(msg, req)
+	__db_truncate_msg *msg;
+	struct svc_req *req;
+{
+	static __db_truncate_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_truncate_proc(msg->dbpcl_id,
+	    msg->txnpcl_id,
+	    msg->flags,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_cursor_reply *
+__db_db_cursor_4003__SVCSUFFIX__(msg, req)
+	__db_cursor_msg *msg;
+	struct svc_req *req;
+{
+	static __db_cursor_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_cursor_proc(msg->dbpcl_id,
+	    msg->txnpcl_id,
+	    msg->flags,
+	    &reply);
+
+	return (&reply);
+}
+
+__db_join_reply *
+__db_db_join_4003__SVCSUFFIX__(msg, req)
+	__db_join_msg *msg;
+	struct svc_req *req;
+{
+	static __db_join_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__db_join_proc(msg->dbpcl_id,
+	    msg->curs.curs_val,
+	    msg->curs.curs_len,
+	    msg->flags,
+	    &reply);
+
+	return (&reply);
+}
+
+__dbc_close_reply *
+__db_dbc_close_4003__SVCSUFFIX__(msg, req)
+	__dbc_close_msg *msg;
+	struct svc_req *req;
+{
+	static __dbc_close_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__dbc_close_proc(msg->dbccl_id,
+	    &reply);
+
+	return (&reply);
+}
+
+__dbc_count_reply *
+__db_dbc_count_4003__SVCSUFFIX__(msg, req)
+	__dbc_count_msg *msg;
+	struct svc_req *req;
+{
+	static __dbc_count_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__dbc_count_proc(msg->dbccl_id,
+	    msg->flags,
+	    &reply);
+
+	return (&reply);
+}
+
+__dbc_del_reply *
+__db_dbc_del_4003__SVCSUFFIX__(msg, req)
+	__dbc_del_msg *msg;
+	struct svc_req *req;
+{
+	static __dbc_del_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__dbc_del_proc(msg->dbccl_id,
+	    msg->flags,
+	    &reply);
+
+	return (&reply);
+}
+
+__dbc_dup_reply *
+__db_dbc_dup_4003__SVCSUFFIX__(msg, req)
+	__dbc_dup_msg *msg;
+	struct svc_req *req;
+{
+	static __dbc_dup_reply reply; /* must be static */
+	COMPQUIET(req, NULL);
+
+	__dbc_dup_proc(msg->dbccl_id,
+	    msg->flags,
+	    &reply);
+
+	return (&reply);
+}
+
+__dbc_get_reply *
+__db_dbc_get_4003__SVCSUFFIX__(msg, req)
+	__dbc_get_msg *msg;
+	struct svc_req *req;
+{
+	static __dbc_get_reply reply; /* must be static */
+	static int __dbc_get_free = 0; /* must be static */
+
+	COMPQUIET(req, NULL);
+	if (__dbc_get_free)
+		xdr_free((xdrproc_t)xdr___dbc_get_reply, (void *)&reply);
+	__dbc_get_free = 0;
+
+	/* Reinitialize allocated fields */
+	reply.keydata.keydata_val = NULL;
+	reply.datadata.datadata_val = NULL;
+
+	__dbc_get_proc(msg->dbccl_id,
+	    msg->keydlen,
+	    msg->keydoff,
+	    msg->keyulen,
+	    msg->keyflags,
+	    msg->keydata.keydata_val,
+	    msg->keydata.keydata_len,
+	    msg->datadlen,
+	    msg->datadoff,
+	    msg->dataulen,
+	    msg->dataflags,
+	    msg->datadata.datadata_val,
+	    msg->datadata.datadata_len,
+	    msg->flags,
+	    &reply,
+	    &__dbc_get_free);
+	return (&reply);
+}
+
+__dbc_pget_reply *
+__db_dbc_pget_4003__SVCSUFFIX__(msg, req)
+	__dbc_pget_msg *msg;
+	struct svc_req *req;
+{
+	static __dbc_pget_reply reply; /* must be static */
+	static int __dbc_pget_free = 0; /* must be static */
+
+	COMPQUIET(req, NULL);
+	if (__dbc_pget_free)
+		xdr_free((xdrproc_t)xdr___dbc_pget_reply, (void *)&reply);
+	__dbc_pget_free = 0;
+
+	/* Reinitialize allocated fields */
+	reply.skeydata.skeydata_val = NULL;
+	reply.pkeydata.pkeydata_val = NULL;
+	reply.datadata.datadata_val = NULL;
+
+	__dbc_pget_proc(msg->dbccl_id,
+	    msg->skeydlen,
+	    msg->skeydoff,
+	    msg->skeyulen,
+	    msg->skeyflags,
+	    msg->skeydata.skeydata_val,
+	    msg->skeydata.skeydata_len,
+	    msg->pkeydlen,
+	    msg->pkeydoff,
+	    msg->pkeyulen,
+	    msg->pkeyflags,
+	    msg->pkeydata.pkeydata_val,
+	    msg->pkeydata.pkeydata_len,
+	    msg->datadlen,
+	    msg->datadoff,
+	    msg->dataulen,
+	    msg->dataflags,
+	    msg->datadata.datadata_val,
+	    msg->datadata.datadata_len,
+	    msg->flags,
+	    &reply,
+	    &__dbc_pget_free);
+	return (&reply);
+}
+
+__dbc_put_reply *
+__db_dbc_put_4003__SVCSUFFIX__(msg, req)
+	__dbc_put_msg *msg;
+	struct svc_req *req;
+{
+	static __dbc_put_reply reply; /* must be static */
+	static int __dbc_put_free = 0; /* must be static */
+
+	COMPQUIET(req, NULL);
+	if (__dbc_put_free)
+		xdr_free((xdrproc_t)xdr___dbc_put_reply, (void *)&reply);
+	__dbc_put_free = 0;
+
+	/* Reinitialize allocated fields */
+	reply.keydata.keydata_val = NULL;
+
+	__dbc_put_proc(msg->dbccl_id,
+	    msg->keydlen,
+	    msg->keydoff,
+	    msg->keyulen,
+	    msg->keyflags,
+	    msg->keydata.keydata_val,
+	    msg->keydata.keydata_len,
+	    msg->datadlen,
+	    msg->datadoff,
+	    msg->dataulen,
+	    msg->dataflags,
+	    msg->datadata.datadata_val,
+	    msg->datadata.datadata_len,
+	    msg->flags,
+	    &reply,
+	    &__dbc_put_free);
+	return (&reply);
+}
+
diff --git a/storage/bdb/rpc_server/cxx/db_server_cxxproc.cpp b/storage/bdb/rpc_server/cxx/db_server_cxxproc.cpp
index 25278273555dd138cafb15548d7cd270d54027b8..e536a70518b9aff787a9f67cb828836be52445e3 100644
--- a/storage/bdb/rpc_server/cxx/db_server_cxxproc.cpp
+++ b/storage/bdb/rpc_server/cxx/db_server_cxxproc.cpp
@@ -1,17 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
+ * Copyright (c) 2001-2004
  *      Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_server_cxxproc.cpp,v 1.23 2004/09/22 17:30:12 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifdef HAVE_RPC
-#ifndef lint
-static const char revid[] = "$Id: db_server_cxxproc.cpp,v 1.12 2002/08/09 01:56:08 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -19,7 +16,8 @@ static const char revid[] = "$Id: db_server_cxxproc.cpp,v 1.12 2002/08/09 01:56:
 
 #include <string.h>
 #endif
-#include "dbinc_auto/db_server.h"
+
+#include "db_server.h"
 
 #include "db_int.h"
 #include "db_cxx.h"
@@ -29,7 +27,21 @@ extern "C" {
 #include "dbinc_auto/rpc_server_ext.h"
 }
 
-/* BEGIN __env_cachesize_proc */
+extern "C" void
+__env_get_cachesize_proc(
+	long dbenvcl_id,
+	__env_get_cachesize_reply *replyp)
+{
+	DbEnv *dbenv;
+	ct_entry *dbenv_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
+
+	replyp->status = dbenv->get_cachesize(&replyp->gbytes,
+	    &replyp->bytes, (int *)&replyp->ncache);
+}
+
 extern "C" void
 __env_cachesize_proc(
 	long dbenvcl_id,
@@ -37,7 +49,6 @@ __env_cachesize_proc(
 	u_int32_t bytes,
 	u_int32_t ncache,
 	__env_cachesize_reply *replyp)
-/* END __env_cachesize_proc */
 {
 	DbEnv *dbenv;
 	ct_entry *dbenv_ctp;
@@ -52,13 +63,11 @@ __env_cachesize_proc(
 	return;
 }
 
-/* BEGIN __env_close_proc */
 extern "C" void
 __env_close_proc(
 	long dbenvcl_id,
 	u_int32_t flags,
 	__env_close_reply *replyp)
-/* END __env_close_proc */
 {
 	ct_entry *dbenv_ctp;
 
@@ -67,12 +76,10 @@ __env_close_proc(
 	return;
 }
 
-/* BEGIN __env_create_proc */
 extern "C" void
 __env_create_proc(
 	u_int32_t timeout,
 	__env_create_reply *replyp)
-/* END __env_create_proc */
 {
 	DbEnv *dbenv;
 	ct_entry *ctp;
@@ -94,7 +101,6 @@ __env_create_proc(
 	return;
 }
 
-/* BEGIN __env_dbremove_proc */
 extern "C" void
 __env_dbremove_proc(
 	long dbenvcl_id,
@@ -103,7 +109,6 @@ __env_dbremove_proc(
 	char *subdb,
 	u_int32_t flags,
 	__env_dbremove_reply *replyp)
-/* END __env_dbremove_proc */
 {
 	int ret;
 	DbEnv *dbenv;
@@ -125,7 +130,6 @@ __env_dbremove_proc(
 	return;
 }
 
-/* BEGIN __env_dbrename_proc */
 void
 __env_dbrename_proc(
 	long dbenvcl_id,
@@ -135,7 +139,6 @@ __env_dbrename_proc(
 	char *newname,
 	u_int32_t flags,
 	__env_dbrename_reply *replyp)
-/* END __env_dbrename_proc */
 {
 	int ret;
 	DbEnv *dbenv;
@@ -157,14 +160,26 @@ __env_dbrename_proc(
 	return;
 }
 
-/* BEGIN __env_encrypt_proc */
+extern "C" void
+__env_get_encrypt_flags_proc(
+	long dbenvcl_id,
+	__env_get_encrypt_flags_reply *replyp)
+{
+	DbEnv *dbenv;
+	ct_entry *dbenv_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
+
+	replyp->status = dbenv->get_encrypt_flags(&replyp->flags);
+}
+
 extern "C" void
 __env_encrypt_proc(
 	long dbenvcl_id,
 	char *passwd,
 	u_int32_t flags,
 	__env_encrypt_reply *replyp)
-/* END __env_encrypt_proc */
 {
 	DbEnv *dbenv;
 	ct_entry *dbenv_ctp;
@@ -179,14 +194,26 @@ __env_encrypt_proc(
 	return;
 }
 
-/* BEGIN __env_flags_proc */
+extern "C" void
+__env_get_flags_proc(
+	long dbenvcl_id,
+	__env_get_flags_reply *replyp)
+{
+	DbEnv *dbenv;
+	ct_entry *dbenv_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
+
+	replyp->status = dbenv->get_flags(&replyp->flags);
+}
+
 extern "C" void
 __env_flags_proc(
 	long dbenvcl_id,
 	u_int32_t flags,
 	u_int32_t onoff,
 	__env_flags_reply *replyp)
-/* END __env_flags_proc */
 {
 	DbEnv *dbenv;
 	ct_entry *dbenv_ctp;
@@ -204,7 +231,35 @@ __env_flags_proc(
 	replyp->status = ret;
 	return;
 }
-/* BEGIN __env_open_proc */
+
+extern "C" void
+__env_get_home_proc(
+	long dbenvcl_id,
+	__env_get_home_reply *replyp)
+{
+	DbEnv *dbenv;
+	ct_entry *dbenv_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
+
+	replyp->status = dbenv->get_home((const char **)&replyp->home);
+}
+
+extern "C" void
+__env_get_open_flags_proc(
+	long dbenvcl_id,
+	__env_get_open_flags_reply *replyp)
+{
+	DbEnv *dbenv;
+	ct_entry *dbenv_ctp;
+
+	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
+	dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
+
+	replyp->status = dbenv->get_open_flags(&replyp->flags);
+}
+
 extern "C" void
 __env_open_proc(
 	long dbenvcl_id,
@@ -212,7 +267,6 @@ __env_open_proc(
 	u_int32_t flags,
 	u_int32_t mode,
 	__env_open_reply *replyp)
-/* END __env_open_proc */
 {
 	DbEnv *dbenv;
 	ct_entry *dbenv_ctp, *new_ctp;
@@ -222,7 +276,7 @@ __env_open_proc(
 
 	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
 	dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
-	fullhome = get_home(home);
+	fullhome = get_fullhome(home);
 	if (fullhome == NULL) {
 		ret = DB_NOSERVER_HOME;
 		goto out;
@@ -268,14 +322,12 @@ out:	replyp->status = ret;
 	return;
 }
 
-/* BEGIN __env_remove_proc */
 extern "C" void
 __env_remove_proc(
 	long dbenvcl_id,
 	char *home,
 	u_int32_t flags,
 	__env_remove_reply *replyp)
-/* END __env_remove_proc */
 {
 	DbEnv *dbenv;
 	ct_entry *dbenv_ctp;
@@ -284,7 +336,7 @@ __env_remove_proc(
 
 	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
 	dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
-	fullhome = get_home(home);
+	fullhome = get_fullhome(home);
 	if (fullhome == NULL) {
 		replyp->status = DB_NOSERVER_HOME;
 		return;
@@ -296,12 +348,10 @@ __env_remove_proc(
 	return;
 }
 
-/* BEGIN __txn_abort_proc */
 extern "C" void
 __txn_abort_proc(
 	long txnpcl_id,
 	__txn_abort_reply *replyp)
-/* END __txn_abort_proc */
 {
 	DbTxn *txnp;
 	ct_entry *txnp_ctp;
@@ -316,14 +366,12 @@ __txn_abort_proc(
 	return;
 }
 
-/* BEGIN __txn_begin_proc */
 extern "C" void
 __txn_begin_proc(
 	long dbenvcl_id,
 	long parentcl_id,
 	u_int32_t flags,
 	__txn_begin_reply *replyp)
-/* END __txn_begin_proc */
 {
 	DbEnv *dbenv;
 	DbTxn *parent, *txnp;
@@ -345,7 +393,7 @@ __txn_begin_proc(
 	} else
 		parent = NULL;
 
-	ret = dbenv->txn_begin(parent, &txnp, flags);
+	ret = dbenv->txn_begin(parent, &txnp, flags | DB_TXN_NOWAIT);
 	if (ret == 0) {
 		ctp->ct_txnp = txnp;
 		ctp->ct_type = CT_TXN;
@@ -361,13 +409,11 @@ __txn_begin_proc(
 	return;
 }
 
-/* BEGIN __txn_commit_proc */
 extern "C" void
 __txn_commit_proc(
 	long txnpcl_id,
 	u_int32_t flags,
 	__txn_commit_reply *replyp)
-/* END __txn_commit_proc */
 {
 	DbTxn *txnp;
 	ct_entry *txnp_ctp;
@@ -383,13 +429,11 @@ __txn_commit_proc(
 	return;
 }
 
-/* BEGIN __txn_discard_proc */
 extern "C" void
 __txn_discard_proc(
 	long txnpcl_id,
 	u_int32_t flags,
 	__txn_discard_reply *replyp)
-/* END __txn_discard_proc */
 {
 	DbTxn *txnp;
 	ct_entry *txnp_ctp;
@@ -405,13 +449,11 @@ __txn_discard_proc(
 	return;
 }
 
-/* BEGIN __txn_prepare_proc */
 extern "C" void
 __txn_prepare_proc(
 	long txnpcl_id,
 	u_int8_t *gid,
 	__txn_prepare_reply *replyp)
-/* END __txn_prepare_proc */
 {
 	DbTxn *txnp;
 	ct_entry *txnp_ctp;
@@ -425,7 +467,6 @@ __txn_prepare_proc(
 	return;
 }
 
-/* BEGIN __txn_recover_proc */
 extern "C" void
 __txn_recover_proc(
 	long dbenvcl_id,
@@ -433,7 +474,6 @@ __txn_recover_proc(
 	u_int32_t flags,
 	__txn_recover_reply *replyp,
 	int * freep)
-/* END __txn_recover_proc */
 {
 	DbEnv *dbenv;
 	DbPreplist *dbprep, *p;
@@ -447,11 +487,10 @@ __txn_recover_proc(
 	dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
 	*freep = 0;
 
-	if ((ret =
-	    __os_malloc(dbenv->get_DB_ENV(), count * sizeof(DbPreplist), &dbprep)) != 0)
+	if ((ret = __os_malloc(
+	    dbenv->get_DB_ENV(), count * sizeof(DbPreplist), &dbprep)) != 0)
 		goto out;
-	if ((ret =
-	    dbenv->txn_recover(dbprep, count, &retcount, flags)) != 0)
+	if ((ret = dbenv->txn_recover(dbprep, count, &retcount, flags)) != 0)
 		goto out;
 	/*
 	 * If there is nothing, success, but it's easy.
@@ -535,13 +574,11 @@ out2:
 	return;
 }
 
-/* BEGIN __db_bt_maxkey_proc */
 extern "C" void
 __db_bt_maxkey_proc(
 	long dbpcl_id,
 	u_int32_t maxkey,
 	__db_bt_maxkey_reply *replyp)
-/* END __db_bt_maxkey_proc */
 {
 	Db *dbp;
 	ct_entry *dbp_ctp;
@@ -556,7 +593,6 @@ __db_bt_maxkey_proc(
 	return;
 }
 
-/* BEGIN __db_associate_proc */
 extern "C" void
 __db_associate_proc(
 	long dbpcl_id,
@@ -564,7 +600,6 @@ __db_associate_proc(
 	long sdbpcl_id,
 	u_int32_t flags,
 	__db_associate_reply *replyp)
-/* END __db_associate_proc */
 {
 	Db *dbp, *sdbp;
 	DbTxn *txnp;
@@ -582,11 +617,12 @@ __db_associate_proc(
 		txnp = NULL;
 
 	/*
-	 * We do not support DB_CREATE for associate.   Users
-	 * can only access secondary indices on a read-only basis,
-	 * so whatever they are looking for needs to be there already.
+	 * We do not support DB_CREATE for associate or the callbacks
+	 * implemented in the Java and JE RPC servers.   Users can only
+	 * access secondary indices on a read-only basis, so whatever they
+	 * are looking for needs to be there already.
 	 */
-	if (flags != 0)
+	if (LF_ISSET(DB_RPC2ND_MASK | DB_CREATE))
 		ret = EINVAL;
 	else
 		ret = dbp->associate(txnp, sdbp, NULL, flags);
@@ -595,13 +631,25 @@ __db_associate_proc(
 	return;
 }
 
-/* BEGIN __db_bt_minkey_proc */
+extern "C" void
+__db_get_bt_minkey_proc(
+	long dbpcl_id,
+	__db_get_bt_minkey_reply *replyp)
+{
+	Db *dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (Db *)dbp_ctp->ct_anyp;
+
+	replyp->status = dbp->get_bt_minkey(&replyp->minkey);
+}
+
 extern "C" void
 __db_bt_minkey_proc(
 	long dbpcl_id,
 	u_int32_t minkey,
 	__db_bt_minkey_reply *replyp)
-/* END __db_bt_minkey_proc */
 {
 	Db *dbp;
 	ct_entry *dbp_ctp;
@@ -616,13 +664,11 @@ __db_bt_minkey_proc(
 	return;
 }
 
-/* BEGIN __db_close_proc */
 extern "C" void
 __db_close_proc(
 	long dbpcl_id,
 	u_int32_t flags,
 	__db_close_reply *replyp)
-/* END __db_close_proc */
 {
 	ct_entry *dbp_ctp;
 
@@ -631,13 +677,11 @@ __db_close_proc(
 	return;
 }
 
-/* BEGIN __db_create_proc */
 extern "C" void
 __db_create_proc(
 	long dbenvcl_id,
 	u_int32_t flags,
 	__db_create_reply *replyp)
-/* END __db_create_proc */
 {
 	Db *dbp;
 	DbEnv *dbenv;
@@ -664,7 +708,6 @@ __db_create_proc(
 	return;
 }
 
-/* BEGIN __db_del_proc */
 extern "C" void
 __db_del_proc(
 	long dbpcl_id,
@@ -677,7 +720,6 @@ __db_del_proc(
 	u_int32_t keysize,
 	u_int32_t flags,
 	__db_del_reply *replyp)
-/* END __db_del_proc */
 {
 	Db *dbp;
 	DbTxn *txnp;
@@ -705,14 +747,26 @@ __db_del_proc(
 	return;
 }
 
-/* BEGIN __db_encrypt_proc */
+extern "C" void
+__db_get_encrypt_flags_proc(
+	long dbpcl_id,
+	__db_get_encrypt_flags_reply *replyp)
+{
+	Db *dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (Db *)dbp_ctp->ct_anyp;
+
+	replyp->status = dbp->get_encrypt_flags(&replyp->flags);
+}
+
 extern "C" void
 __db_encrypt_proc(
 	long dbpcl_id,
 	char *passwd,
 	u_int32_t flags,
 	__db_encrypt_reply *replyp)
-/* END __db_encrypt_proc */
 {
 	Db *dbp;
 	ct_entry *dbp_ctp;
@@ -726,13 +780,25 @@ __db_encrypt_proc(
 	return;
 }
 
-/* BEGIN __db_extentsize_proc */
+extern "C" void
+__db_get_extentsize_proc(
+	long dbpcl_id,
+	__db_get_extentsize_reply *replyp)
+{
+	Db *dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (Db *)dbp_ctp->ct_anyp;
+
+	replyp->status = dbp->get_q_extentsize(&replyp->extentsize);
+}
+
 extern "C" void
 __db_extentsize_proc(
 	long dbpcl_id,
 	u_int32_t extentsize,
 	__db_extentsize_reply *replyp)
-/* END __db_extentsize_proc */
 {
 	Db *dbp;
 	ct_entry *dbp_ctp;
@@ -747,13 +813,25 @@ __db_extentsize_proc(
 	return;
 }
 
-/* BEGIN __db_flags_proc */
+extern "C" void
+__db_get_flags_proc(
+	long dbpcl_id,
+	__db_get_flags_reply *replyp)
+{
+	Db *dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (Db *)dbp_ctp->ct_anyp;
+
+	replyp->status = dbp->get_flags(&replyp->flags);
+}
+
 extern "C" void
 __db_flags_proc(
 	long dbpcl_id,
 	u_int32_t flags,
 	__db_flags_reply *replyp)
-/* END __db_flags_proc */
 {
 	Db *dbp;
 	ct_entry *dbp_ctp;
@@ -769,7 +847,6 @@ __db_flags_proc(
 	return;
 }
 
-/* BEGIN __db_get_proc */
 extern "C" void
 __db_get_proc(
 	long dbpcl_id,
@@ -789,7 +866,6 @@ __db_get_proc(
 	u_int32_t flags,
 	__db_get_reply *replyp,
 	int * freep)
-/* END __db_get_proc */
 {
 	Db *dbp;
 	DbTxn *txnp;
@@ -863,12 +939,15 @@ __db_get_proc(
 			ret = __os_umalloc(dbp->get_DB()->dbenv,
 			    key.get_size(), &replyp->keydata.keydata_val);
 			if (ret != 0) {
-				__os_ufree(dbp->get_DB()->dbenv, key.get_data());
-				__os_ufree(dbp->get_DB()->dbenv, data.get_data());
+				__os_ufree(
+				    dbp->get_DB()->dbenv, key.get_data());
+				__os_ufree(
+				    dbp->get_DB()->dbenv, data.get_data());
 				goto err;
 			}
 			key_alloc = 1;
-			memcpy(replyp->keydata.keydata_val, key.get_data(), key.get_size());
+			memcpy(replyp->keydata.keydata_val,
+			    key.get_data(), key.get_size());
 		} else
 			replyp->keydata.keydata_val = (char *)key.get_data();
 
@@ -881,8 +960,10 @@ __db_get_proc(
 			ret = __os_umalloc(dbp->get_DB()->dbenv,
 			     data.get_size(), &replyp->datadata.datadata_val);
 			if (ret != 0) {
-				__os_ufree(dbp->get_DB()->dbenv, key.get_data());
-				__os_ufree(dbp->get_DB()->dbenv, data.get_data());
+				__os_ufree(
+				    dbp->get_DB()->dbenv, key.get_data());
+				__os_ufree(
+				    dbp->get_DB()->dbenv, data.get_data());
 				if (key_alloc)
 					__os_ufree(dbp->get_DB()->dbenv,
 					    replyp->keydata.keydata_val);
@@ -906,13 +987,25 @@ err:		replyp->keydata.keydata_val = NULL;
 	return;
 }
 
-/* BEGIN __db_h_ffactor_proc */
+extern "C" void
+__db_get_h_ffactor_proc(
+	long dbpcl_id,
+	__db_get_h_ffactor_reply *replyp)
+{
+	Db *dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (Db *)dbp_ctp->ct_anyp;
+
+	replyp->status = dbp->get_h_ffactor(&replyp->ffactor);
+}
+
 extern "C" void
 __db_h_ffactor_proc(
 	long dbpcl_id,
 	u_int32_t ffactor,
 	__db_h_ffactor_reply *replyp)
-/* END __db_h_ffactor_proc */
 {
 	Db *dbp;
 	ct_entry *dbp_ctp;
@@ -927,13 +1020,25 @@ __db_h_ffactor_proc(
 	return;
 }
 
-/* BEGIN __db_h_nelem_proc */
+extern "C" void
+__db_get_h_nelem_proc(
+	long dbpcl_id,
+	__db_get_h_nelem_reply *replyp)
+{
+	Db *dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (Db *)dbp_ctp->ct_anyp;
+
+	replyp->status = dbp->get_h_nelem(&replyp->nelem);
+}
+
 extern "C" void
 __db_h_nelem_proc(
 	long dbpcl_id,
 	u_int32_t nelem,
 	__db_h_nelem_reply *replyp)
-/* END __db_h_nelem_proc */
 {
 	Db *dbp;
 	ct_entry *dbp_ctp;
@@ -948,7 +1053,6 @@ __db_h_nelem_proc(
 	return;
 }
 
-/* BEGIN __db_key_range_proc */
 extern "C" void
 __db_key_range_proc(
 	long dbpcl_id,
@@ -961,7 +1065,6 @@ __db_key_range_proc(
 	u_int32_t keysize,
 	u_int32_t flags,
 	__db_key_range_reply *replyp)
-/* END __db_key_range_proc */
 {
 	Db *dbp;
 	DB_KEY_RANGE range;
@@ -993,13 +1096,25 @@ __db_key_range_proc(
 	return;
 }
 
-/* BEGIN __db_lorder_proc */
+extern "C" void
+__db_get_lorder_proc(
+	long dbpcl_id,
+	__db_get_lorder_reply *replyp)
+{
+	Db *dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (Db *)dbp_ctp->ct_anyp;
+
+	replyp->status = dbp->get_lorder((int *)&replyp->lorder);
+}
+
 extern "C" void
 __db_lorder_proc(
 	long dbpcl_id,
 	u_int32_t lorder,
 	__db_lorder_reply *replyp)
-/* END __db_lorder_proc */
 {
 	Db *dbp;
 	ct_entry *dbp_ctp;
@@ -1014,7 +1129,35 @@ __db_lorder_proc(
 	return;
 }
 
-/* BEGIN __db_open_proc */
+extern "C" void
+__db_get_name_proc(
+	long dbpcl_id,
+	__db_get_name_reply *replyp)
+{
+	Db *dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (Db *)dbp_ctp->ct_anyp;
+
+	replyp->status = dbp->get_dbname(
+	    (const char **)&replyp->filename, (const char **)&replyp->dbname);
+}
+
+extern "C" void
+__db_get_open_flags_proc(
+	long dbpcl_id,
+	__db_get_open_flags_reply *replyp)
+{
+	Db *dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (Db *)dbp_ctp->ct_anyp;
+
+	replyp->status = dbp->get_open_flags(&replyp->flags);
+}
+
 extern "C" void
 __db_open_proc(
 	long dbpcl_id,
@@ -1025,7 +1168,6 @@ __db_open_proc(
 	u_int32_t flags,
 	u_int32_t mode,
 	__db_open_reply *replyp)
-/* END __db_open_proc */
 {
 	Db *dbp;
 	DbTxn *txnp;
@@ -1042,8 +1184,8 @@ __db_open_proc(
 		txnp = NULL;
 
 	replyp->dbcl_id = dbpcl_id;
-	if ((new_ctp = __dbsrv_sharedb(dbp_ctp, name, subdb, (DBTYPE)type, flags))
-	    != NULL) {
+	if ((new_ctp = __dbsrv_sharedb(
+	    dbp_ctp, name, subdb, (DBTYPE)type, flags)) != NULL) {
 		/*
 		 * We can share, clean up old ID, set new one.
 		 */
@@ -1057,11 +1199,6 @@ __db_open_proc(
 	if (ret == 0) {
 		(void)dbp->get_type(&dbtype);
 		replyp->type = dbtype;
-		/* XXX
-		 * Tcl needs to peek at dbp->flags for DB_AM_DUP.  Send
-		 * this dbp's flags back.
-		 */
-		replyp->dbflags = (int) dbp->get_DB()->flags;
 		/*
 		 * We need to determine the byte order of the database
 		 * and send it back to the client.  Determine it by
@@ -1098,13 +1235,25 @@ out:
 	return;
 }
 
-/* BEGIN __db_pagesize_proc */
+extern "C" void
+__db_get_pagesize_proc(
+	long dbpcl_id,
+	__db_get_pagesize_reply *replyp)
+{
+	Db *dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (Db *)dbp_ctp->ct_anyp;
+
+	replyp->status = dbp->get_pagesize(&replyp->pagesize);
+}
+
 extern "C" void
 __db_pagesize_proc(
 	long dbpcl_id,
 	u_int32_t pagesize,
 	__db_pagesize_reply *replyp)
-/* END __db_pagesize_proc */
 {
 	Db *dbp;
 	ct_entry *dbp_ctp;
@@ -1119,7 +1268,6 @@ __db_pagesize_proc(
 	return;
 }
 
-/* BEGIN __db_pget_proc */
 extern "C" void
 __db_pget_proc(
 	long dbpcl_id,
@@ -1145,7 +1293,6 @@ __db_pget_proc(
 	u_int32_t flags,
 	__db_pget_reply *replyp,
 	int * freep)
-/* END __db_pget_proc */
 {
 	Db *dbp;
 	DbTxn *txnp;
@@ -1207,9 +1354,12 @@ __db_pget_proc(
 			ret = __os_umalloc(dbp->get_DB()->dbenv,
 			    skey.get_size(), &replyp->skeydata.skeydata_val);
 			if (ret != 0) {
-				__os_ufree(dbp->get_DB()->dbenv, skey.get_data());
-				__os_ufree(dbp->get_DB()->dbenv, pkey.get_data());
-				__os_ufree(dbp->get_DB()->dbenv, data.get_data());
+				__os_ufree(
+				    dbp->get_DB()->dbenv, skey.get_data());
+				__os_ufree(
+				    dbp->get_DB()->dbenv, pkey.get_data());
+				__os_ufree(
+				    dbp->get_DB()->dbenv, data.get_data());
 				goto err;
 			}
 			key_alloc = 1;
@@ -1227,9 +1377,12 @@ __db_pget_proc(
 			ret = __os_umalloc(dbp->get_DB()->dbenv,
 			     pkey.get_size(), &replyp->pkeydata.pkeydata_val);
 			if (ret != 0) {
-				__os_ufree(dbp->get_DB()->dbenv, skey.get_data());
-				__os_ufree(dbp->get_DB()->dbenv, pkey.get_data());
-				__os_ufree(dbp->get_DB()->dbenv, data.get_data());
+				__os_ufree(
+				    dbp->get_DB()->dbenv, skey.get_data());
+				__os_ufree(
+				    dbp->get_DB()->dbenv, pkey.get_data());
+				__os_ufree(
+				    dbp->get_DB()->dbenv, data.get_data());
 				if (key_alloc)
 					__os_ufree(dbp->get_DB()->dbenv,
 					    replyp->skeydata.skeydata_val);
@@ -1255,9 +1408,12 @@ __db_pget_proc(
 			ret = __os_umalloc(dbp->get_DB()->dbenv,
 			     data.get_size(), &replyp->datadata.datadata_val);
 			if (ret != 0) {
-				__os_ufree(dbp->get_DB()->dbenv, skey.get_data());
-				__os_ufree(dbp->get_DB()->dbenv, pkey.get_data());
-				__os_ufree(dbp->get_DB()->dbenv, data.get_data());
+				__os_ufree(
+				    dbp->get_DB()->dbenv, skey.get_data());
+				__os_ufree(
+				    dbp->get_DB()->dbenv, pkey.get_data());
+				__os_ufree(
+				    dbp->get_DB()->dbenv, data.get_data());
 				/*
 				 * If key_alloc is 1, just skey needs to be
 				 * freed, if key_alloc is 2, both skey and pkey
@@ -1289,7 +1445,6 @@ err:		replyp->skeydata.skeydata_val = NULL;
 	return;
 }
 
-/* BEGIN __db_put_proc */
 extern "C" void
 __db_put_proc(
 	long dbpcl_id,
@@ -1309,7 +1464,6 @@ __db_put_proc(
 	u_int32_t flags,
 	__db_put_reply *replyp,
 	int * freep)
-/* END __db_put_proc */
 {
 	Db *dbp;
 	DbTxn *txnp;
@@ -1362,10 +1516,12 @@ __db_put_proc(
 			ret = __os_umalloc(dbp->get_DB()->dbenv,
 			    key.get_size(), &replyp->keydata.keydata_val);
 			if (ret != 0) {
-				__os_ufree(dbp->get_DB()->dbenv, key.get_data());
+				__os_ufree(
+				    dbp->get_DB()->dbenv, key.get_data());
 				goto err;
 			}
-			memcpy(replyp->keydata.keydata_val, key.get_data(), key.get_size());
+			memcpy(replyp->keydata.keydata_val,
+			    key.get_data(), key.get_size());
 		} else
 			replyp->keydata.keydata_val = (char *)key.get_data();
 
@@ -1379,13 +1535,25 @@ err:		replyp->keydata.keydata_val = NULL;
 	return;
 }
 
-/* BEGIN __db_re_delim_proc */
+extern "C" void
+__db_get_re_delim_proc(
+	long dbpcl_id,
+	__db_get_re_delim_reply *replyp)
+{
+	Db *dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (Db *)dbp_ctp->ct_anyp;
+
+	replyp->status = dbp->get_re_delim((int *)&replyp->delim);
+}
+
 extern "C" void
 __db_re_delim_proc(
 	long dbpcl_id,
 	u_int32_t delim,
 	__db_re_delim_reply *replyp)
-/* END __db_re_delim_proc */
 {
 	Db *dbp;
 	ct_entry *dbp_ctp;
@@ -1400,13 +1568,25 @@ __db_re_delim_proc(
 	return;
 }
 
-/* BEGIN __db_re_len_proc */
+extern "C" void
+__db_get_re_len_proc(
+	long dbpcl_id,
+	__db_get_re_len_reply *replyp)
+{
+	Db *dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (Db *)dbp_ctp->ct_anyp;
+
+	replyp->status = dbp->get_re_len(&replyp->len);
+}
+
 extern "C" void
 __db_re_len_proc(
 	long dbpcl_id,
 	u_int32_t len,
 	__db_re_len_reply *replyp)
-/* END __db_re_len_proc */
 {
 	Db *dbp;
 	ct_entry *dbp_ctp;
@@ -1421,13 +1601,25 @@ __db_re_len_proc(
 	return;
 }
 
-/* BEGIN __db_re_pad_proc */
+void
+__db_get_re_pad_proc(
+	long dbpcl_id,
+	__db_get_re_pad_reply *replyp)
+{
+	Db *dbp;
+	ct_entry *dbp_ctp;
+
+	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
+	dbp = (Db *)dbp_ctp->ct_anyp;
+
+	replyp->status = dbp->get_re_pad((int *)&replyp->pad);
+}
+
 extern "C" void
 __db_re_pad_proc(
 	long dbpcl_id,
 	u_int32_t pad,
 	__db_re_pad_reply *replyp)
-/* END __db_re_pad_proc */
 {
 	Db *dbp;
 	ct_entry *dbp_ctp;
@@ -1442,7 +1634,6 @@ __db_re_pad_proc(
 	return;
 }
 
-/* BEGIN __db_remove_proc */
 extern "C" void
 __db_remove_proc(
 	long dbpcl_id,
@@ -1450,7 +1641,6 @@ __db_remove_proc(
 	char *subdb,
 	u_int32_t flags,
 	__db_remove_reply *replyp)
-/* END __db_remove_proc */
 {
 	Db *dbp;
 	ct_entry *dbp_ctp;
@@ -1466,7 +1656,6 @@ __db_remove_proc(
 	return;
 }
 
-/* BEGIN __db_rename_proc */
 extern "C" void
 __db_rename_proc(
 	long dbpcl_id,
@@ -1475,7 +1664,6 @@ __db_rename_proc(
 	char *newname,
 	u_int32_t flags,
 	__db_rename_reply *replyp)
-/* END __db_rename_proc */
 {
 	Db *dbp;
 	ct_entry *dbp_ctp;
@@ -1491,26 +1679,31 @@ __db_rename_proc(
 	return;
 }
 
-/* BEGIN __db_stat_proc */
 extern "C" void
 __db_stat_proc(
 	long dbpcl_id,
+	long txnpcl_id,
 	u_int32_t flags,
 	__db_stat_reply *replyp,
 	int * freep)
-/* END __db_stat_proc */
 {
 	Db *dbp;
+	DbTxn *txnp;
 	DBTYPE type;
-	ct_entry *dbp_ctp;
+	ct_entry *dbp_ctp, *txnp_ctp;
 	u_int32_t *q, *p, *retsp;
 	int i, len, ret;
 	void *sp;
 
 	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
 	dbp = (Db *)dbp_ctp->ct_anyp;
+	if (txnpcl_id != 0) {
+		ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
+		txnp = (DbTxn *)txnp_ctp->ct_anyp;
+	} else
+		txnp = NULL;
 
-	ret = dbp->stat(&sp, flags);
+	ret = dbp->stat(txnp, &sp, flags);
 	replyp->status = ret;
 	if (ret != 0)
 		return;
@@ -1547,13 +1740,11 @@ out:
 	return;
 }
 
-/* BEGIN __db_sync_proc */
 extern "C" void
 __db_sync_proc(
 	long dbpcl_id,
 	u_int32_t flags,
 	__db_sync_reply *replyp)
-/* END __db_sync_proc */
 {
 	Db *dbp;
 	ct_entry *dbp_ctp;
@@ -1568,14 +1759,12 @@ __db_sync_proc(
 	return;
 }
 
-/* BEGIN __db_truncate_proc */
 extern "C" void
 __db_truncate_proc(
 	long dbpcl_id,
 	long txnpcl_id,
 	u_int32_t flags,
 	__db_truncate_reply *replyp)
-/* END __db_truncate_proc */
 {
 	Db *dbp;
 	DbTxn *txnp;
@@ -1598,14 +1787,12 @@ __db_truncate_proc(
 	return;
 }
 
-/* BEGIN __db_cursor_proc */
 extern "C" void
 __db_cursor_proc(
 	long dbpcl_id,
 	long txnpcl_id,
 	u_int32_t flags,
 	__db_cursor_reply *replyp)
-/* END __db_cursor_proc */
 {
 	Db *dbp;
 	Dbc *dbc;
@@ -1642,7 +1829,6 @@ __db_cursor_proc(
 	return;
 }
 
-/* BEGIN __db_join_proc */
 extern "C" void
 __db_join_proc(
 	long dbpcl_id,
@@ -1650,7 +1836,6 @@ __db_join_proc(
 	u_int32_t curslen,
 	u_int32_t flags,
 	__db_join_reply *replyp)
-/* END __db_join_proc */
 {
 	Db *dbp;
 	Dbc **jcurs, **c;
@@ -1743,12 +1928,10 @@ out:
 	return;
 }
 
-/* BEGIN __dbc_close_proc */
 extern "C" void
 __dbc_close_proc(
 	long dbccl_id,
 	__dbc_close_reply *replyp)
-/* END __dbc_close_proc */
 {
 	ct_entry *dbc_ctp;
 
@@ -1757,13 +1940,11 @@ __dbc_close_proc(
 	return;
 }
 
-/* BEGIN __dbc_count_proc */
 extern "C" void
 __dbc_count_proc(
 	long dbccl_id,
 	u_int32_t flags,
 	__dbc_count_reply *replyp)
-/* END __dbc_count_proc */
 {
 	Dbc *dbc;
 	ct_entry *dbc_ctp;
@@ -1780,13 +1961,11 @@ __dbc_count_proc(
 	return;
 }
 
-/* BEGIN __dbc_del_proc */
 extern "C" void
 __dbc_del_proc(
 	long dbccl_id,
 	u_int32_t flags,
 	__dbc_del_reply *replyp)
-/* END __dbc_del_proc */
 {
 	Dbc *dbc;
 	ct_entry *dbc_ctp;
@@ -1801,13 +1980,11 @@ __dbc_del_proc(
 	return;
 }
 
-/* BEGIN __dbc_dup_proc */
 extern "C" void
 __dbc_dup_proc(
 	long dbccl_id,
 	u_int32_t flags,
 	__dbc_dup_reply *replyp)
-/* END __dbc_dup_proc */
 {
 	Dbc *dbc, *newdbc;
 	ct_entry *dbc_ctp, *new_ctp;
@@ -1840,7 +2017,6 @@ __dbc_dup_proc(
 	return;
 }
 
-/* BEGIN __dbc_get_proc */
 extern "C" void
 __dbc_get_proc(
 	long dbccl_id,
@@ -1859,7 +2035,6 @@ __dbc_get_proc(
 	u_int32_t flags,
 	__dbc_get_reply *replyp,
 	int * freep)
-/* END __dbc_get_proc */
 {
 	Dbc *dbc;
 	DbEnv *dbenv;
@@ -1925,11 +2100,13 @@ __dbc_get_proc(
 			    &replyp->keydata.keydata_val);
 			if (ret != 0) {
 				__os_ufree(dbenv->get_DB_ENV(), key.get_data());
-				__os_ufree(dbenv->get_DB_ENV(), data.get_data());
+				__os_ufree(
+				    dbenv->get_DB_ENV(), data.get_data());
 				goto err;
 			}
 			key_alloc = 1;
-			memcpy(replyp->keydata.keydata_val, key.get_data(), key.get_size());
+			memcpy(replyp->keydata.keydata_val,
+			    key.get_data(), key.get_size());
 		} else
 			replyp->keydata.keydata_val = (char *)key.get_data();
 
@@ -1943,7 +2120,8 @@ __dbc_get_proc(
 			    &replyp->datadata.datadata_val);
 			if (ret != 0) {
 				__os_ufree(dbenv->get_DB_ENV(), key.get_data());
-				__os_ufree(dbenv->get_DB_ENV(), data.get_data());
+				__os_ufree(
+				    dbenv->get_DB_ENV(), data.get_data());
 				if (key_alloc)
 					__os_ufree(dbenv->get_DB_ENV(),
 					    replyp->keydata.keydata_val);
@@ -1967,7 +2145,6 @@ err:		replyp->keydata.keydata_val = NULL;
 	return;
 }
 
-/* BEGIN __dbc_pget_proc */
 extern "C" void
 __dbc_pget_proc(
 	long dbccl_id,
@@ -1992,7 +2169,6 @@ __dbc_pget_proc(
 	u_int32_t flags,
 	__dbc_pget_reply *replyp,
 	int * freep)
-/* END __dbc_pget_proc */
 {
 	Dbc *dbc;
 	DbEnv *dbenv;
@@ -2050,9 +2226,12 @@ __dbc_pget_proc(
 			ret = __os_umalloc(dbenv->get_DB_ENV(),
 			    skey.get_size(), &replyp->skeydata.skeydata_val);
 			if (ret != 0) {
-				__os_ufree(dbenv->get_DB_ENV(), skey.get_data());
-				__os_ufree(dbenv->get_DB_ENV(), pkey.get_data());
-				__os_ufree(dbenv->get_DB_ENV(), data.get_data());
+				__os_ufree(
+				    dbenv->get_DB_ENV(), skey.get_data());
+				__os_ufree(
+				    dbenv->get_DB_ENV(), pkey.get_data());
+				__os_ufree(
+				    dbenv->get_DB_ENV(), data.get_data());
 				goto err;
 			}
 			key_alloc = 1;
@@ -2069,9 +2248,12 @@ __dbc_pget_proc(
 			ret = __os_umalloc(dbenv->get_DB_ENV(),
 			     pkey.get_size(), &replyp->pkeydata.pkeydata_val);
 			if (ret != 0) {
-				__os_ufree(dbenv->get_DB_ENV(), skey.get_data());
-				__os_ufree(dbenv->get_DB_ENV(), pkey.get_data());
-				__os_ufree(dbenv->get_DB_ENV(), data.get_data());
+				__os_ufree(
+				    dbenv->get_DB_ENV(), skey.get_data());
+				__os_ufree(
+				    dbenv->get_DB_ENV(), pkey.get_data());
+				__os_ufree(
+				    dbenv->get_DB_ENV(), data.get_data());
 				if (key_alloc)
 					__os_ufree(dbenv->get_DB_ENV(),
 					    replyp->skeydata.skeydata_val);
@@ -2097,9 +2279,12 @@ __dbc_pget_proc(
 			ret = __os_umalloc(dbenv->get_DB_ENV(),
 			     data.get_size(), &replyp->datadata.datadata_val);
 			if (ret != 0) {
-				__os_ufree(dbenv->get_DB_ENV(), skey.get_data());
-				__os_ufree(dbenv->get_DB_ENV(), pkey.get_data());
-				__os_ufree(dbenv->get_DB_ENV(), data.get_data());
+				__os_ufree(
+				    dbenv->get_DB_ENV(), skey.get_data());
+				__os_ufree(
+				    dbenv->get_DB_ENV(), pkey.get_data());
+				__os_ufree(
+				    dbenv->get_DB_ENV(), data.get_data());
 				/*
 				 * If key_alloc is 1, just skey needs to be
 				 * freed, if key_alloc is 2, both skey and pkey
@@ -2131,7 +2316,6 @@ err:		replyp->skeydata.skeydata_val = NULL;
 	return;
 }
 
-/* BEGIN __dbc_put_proc */
 extern "C" void
 __dbc_put_proc(
 	long dbccl_id,
@@ -2150,7 +2334,6 @@ __dbc_put_proc(
 	u_int32_t flags,
 	__dbc_put_reply *replyp,
 	int * freep)
-/* END __dbc_put_proc */
 {
 	Db *dbp;
 	Dbc *dbc;
@@ -2188,7 +2371,8 @@ __dbc_put_proc(
 		ret = dbp->get_type(&dbtype);
 		if (ret == 0 && dbtype == DB_RECNO) {
 			/*
-			 * We need to xdr_free whatever we are returning, next time.
+			 * We need to xdr_free whatever we are returning, next
+			 * time.
 			 */
 			replyp->keydata.keydata_val = (char *)key.get_data();
 			replyp->keydata.keydata_len = key.get_size();
@@ -2197,4 +2381,3 @@ __dbc_put_proc(
 	replyp->status = ret;
 	return;
 }
-#endif /* HAVE_RPC */
diff --git a/storage/bdb/rpc_server/cxx/db_server_cxxutil.cpp b/storage/bdb/rpc_server/cxx/db_server_cxxutil.cpp
index 60865264c00ea529694f4c80aa16d64c2f58f8e4..d5aacdc0f99f0869ab3948d72e138cf1aecd573e 100644
--- a/storage/bdb/rpc_server/cxx/db_server_cxxutil.cpp
+++ b/storage/bdb/rpc_server/cxx/db_server_cxxutil.cpp
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2000-2002
+ * Copyright (c) 2000-2004
  *      Sleepycat Software.  All rights reserved.
+ *
+ * $Id: db_server_cxxutil.cpp,v 1.17 2004/09/22 17:30:13 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: db_server_cxxutil.cpp,v 1.8 2002/05/23 07:49:34 mjc Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -34,7 +32,8 @@ static const char revid[] = "$Id: db_server_cxxutil.cpp,v 1.8 2002/05/23 07:49:3
 #include <string.h>
 #include <unistd.h>
 #endif
-#include "dbinc_auto/db_server.h"
+
+#include "db_server.h"
 
 #include "db_int.h"
 #include "db_cxx.h"
@@ -159,7 +158,7 @@ main(
 	 */
 	if (__dbsrv_defto > __dbsrv_idleto)
 		fprintf(stderr,
-		    "%s: WARNING: Idle timeout %ld is less than resource timeout %ld\n",
+	    "%s: WARNING: Idle timeout %ld is less than resource timeout %ld\n",
 		    prog, __dbsrv_idleto, __dbsrv_defto);
 
 	LIST_INIT(&__dbsrv_head);
@@ -421,7 +420,8 @@ get_tableent(long id)
 }
 
 extern "C" ct_entry *
-__dbsrv_sharedb(ct_entry *db_ctp, const char *name, const char *subdb, DBTYPE type, u_int32_t flags)
+__dbsrv_sharedb(ct_entry *db_ctp,
+    const char *name, const char *subdb, DBTYPE type, u_int32_t flags)
 {
 	ct_entry *ctp;
 
@@ -597,7 +597,7 @@ __dbenv_close_int(long id, u_int32_t flags, int force)
 {
 	DbEnv *dbenv;
 	int ret;
-	ct_entry *ctp;
+	ct_entry *ctp, *dbctp, *nextctp;
 
 	ret = 0;
 	ctp = get_tableent(id);
@@ -617,6 +617,32 @@ __dbenv_close_int(long id, u_int32_t flags, int force)
 	if (__dbsrv_verbose)
 		printf("Closing env id %ld\n", id);
 
+	/*
+	 * If we're timing out an env, we want to close all of its
+	 * database handles as well.  All of the txns and cursors
+	 * must have been timed out prior to timing out the env.
+	 */
+	if (force)
+		for (dbctp = LIST_FIRST(&__dbsrv_head);
+		    dbctp != NULL; dbctp = nextctp) {
+			nextctp = LIST_NEXT(dbctp, entries);
+			if (dbctp->ct_type != CT_DB)
+				continue;
+			if (dbctp->ct_envparent != ctp)
+				continue;
+			/*
+			 * We found a DB handle that is part of this
+			 * environment.  Close it.
+			 */
+			__db_close_int(dbctp->ct_id, 0);
+			/*
+			 * If we timed out a dbp, we may have removed
+			 * multiple ctp entries.  Start over with a
+			 * guaranteed good ctp.
+			 */
+			nextctp = LIST_FIRST(&__dbsrv_head);
+		}
+
 	ret = dbenv->close(flags);
 	__dbdel_ctp(ctp);
 	return (ret);
@@ -640,8 +666,11 @@ add_home(char *home)
 	 * to assure hp->name points to the last component.
 	 */
 	hp->name = __db_rpath(home);
-	*(hp->name) = '\0';
-	hp->name++;
+	if (hp->name != NULL) {
+		*(hp->name) = '\0';
+		hp->name++;
+	} else
+		hp->name = home;
 	while (*(hp->name) == '\0') {
 		hp->name = __db_rpath(home);
 		*(hp->name) = '\0';
@@ -686,10 +715,13 @@ add_passwd(char *passwd)
 }
 
 extern "C" home_entry *
-get_home(char *name)
+get_fullhome(char *name)
 {
 	home_entry *hp;
 
+	if (name == NULL)
+		return (NULL);
+
 	for (hp = LIST_FIRST(&__dbsrv_home); hp != NULL;
 	    hp = LIST_NEXT(hp, entries))
 		if (strcmp(name, hp->name) == 0)
@@ -709,10 +741,8 @@ env_recover(char *progname)
 	    hp = LIST_NEXT(hp, entries)) {
 		exitval = 0;
 		dbenv = new DbEnv(DB_CXX_NO_EXCEPTIONS);
-		if (__dbsrv_verbose == 1) {
+		if (__dbsrv_verbose == 1)
 			(void)dbenv->set_verbose(DB_VERB_RECOVERY, 1);
-			(void)dbenv->set_verbose(DB_VERB_CHKPOINT, 1);
-		}
 		dbenv->set_errfile(stderr);
 		dbenv->set_errpfx(progname);
 		if (hp->passwd != NULL)
diff --git a/storage/bdb/rpc_server/db_server.x b/storage/bdb/rpc_server/db_server.x
new file mode 100644
index 0000000000000000000000000000000000000000..26b8de8e67965cc91d689961ba9e97167fdaade0
--- /dev/null
+++ b/storage/bdb/rpc_server/db_server.x
@@ -0,0 +1,902 @@
+/* Do not edit: automatically built by gen_rpc.awk. */
+
+struct __env_get_cachesize_msg {
+	unsigned int dbenvcl_id;
+};
+
+struct __env_get_cachesize_reply {
+	/* num return vars: 3 */
+	int status;
+	unsigned int gbytes;
+	unsigned int bytes;
+	unsigned int ncache;
+};
+
+struct __env_cachesize_msg {
+	unsigned int dbenvcl_id;
+	unsigned int gbytes;
+	unsigned int bytes;
+	unsigned int ncache;
+};
+
+struct __env_cachesize_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __env_close_msg {
+	unsigned int dbenvcl_id;
+	unsigned int flags;
+};
+
+struct __env_close_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __env_create_msg {
+	unsigned int timeout;
+};
+
+struct __env_create_reply {
+	/* num return vars: 1 */
+	int status;
+	unsigned int envcl_id;
+};
+
+struct __env_dbremove_msg {
+	unsigned int dbenvcl_id;
+	unsigned int txnpcl_id;
+	string name<>;
+	string subdb<>;
+	unsigned int flags;
+};
+
+struct __env_dbremove_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __env_dbrename_msg {
+	unsigned int dbenvcl_id;
+	unsigned int txnpcl_id;
+	string name<>;
+	string subdb<>;
+	string newname<>;
+	unsigned int flags;
+};
+
+struct __env_dbrename_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __env_get_encrypt_flags_msg {
+	unsigned int dbenvcl_id;
+};
+
+struct __env_get_encrypt_flags_reply {
+	/* num return vars: 1 */
+	int status;
+	unsigned int flags;
+};
+
+struct __env_encrypt_msg {
+	unsigned int dbenvcl_id;
+	string passwd<>;
+	unsigned int flags;
+};
+
+struct __env_encrypt_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __env_get_flags_msg {
+	unsigned int dbenvcl_id;
+};
+
+struct __env_get_flags_reply {
+	/* num return vars: 1 */
+	int status;
+	unsigned int flags;
+};
+
+struct __env_flags_msg {
+	unsigned int dbenvcl_id;
+	unsigned int flags;
+	unsigned int onoff;
+};
+
+struct __env_flags_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __env_get_home_msg {
+	unsigned int dbenvcl_id;
+};
+
+struct __env_get_home_reply {
+	/* num return vars: 1 */
+	int status;
+	string home<>;
+};
+
+struct __env_get_open_flags_msg {
+	unsigned int dbenvcl_id;
+};
+
+struct __env_get_open_flags_reply {
+	/* num return vars: 1 */
+	int status;
+	unsigned int flags;
+};
+
+struct __env_open_msg {
+	unsigned int dbenvcl_id;
+	string home<>;
+	unsigned int flags;
+	unsigned int mode;
+};
+
+struct __env_open_reply {
+	/* num return vars: 1 */
+	int status;
+	unsigned int envcl_id;
+};
+
+struct __env_remove_msg {
+	unsigned int dbenvcl_id;
+	string home<>;
+	unsigned int flags;
+};
+
+struct __env_remove_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __txn_abort_msg {
+	unsigned int txnpcl_id;
+};
+
+struct __txn_abort_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __txn_begin_msg {
+	unsigned int dbenvcl_id;
+	unsigned int parentcl_id;
+	unsigned int flags;
+};
+
+struct __txn_begin_reply {
+	/* num return vars: 1 */
+	int status;
+	unsigned int txnidcl_id;
+};
+
+struct __txn_commit_msg {
+	unsigned int txnpcl_id;
+	unsigned int flags;
+};
+
+struct __txn_commit_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __txn_discard_msg {
+	unsigned int txnpcl_id;
+	unsigned int flags;
+};
+
+struct __txn_discard_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __txn_prepare_msg {
+	unsigned int txnpcl_id;
+	opaque gid[128];
+};
+
+struct __txn_prepare_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __txn_recover_msg {
+	unsigned int dbenvcl_id;
+	unsigned int count;
+	unsigned int flags;
+};
+
+struct __txn_recover_reply {
+	/* num return vars: 3 */
+	int status;
+	unsigned int txn<>;
+	opaque gid<>;
+	unsigned int retcount;
+};
+
+struct __db_associate_msg {
+	unsigned int dbpcl_id;
+	unsigned int txnpcl_id;
+	unsigned int sdbpcl_id;
+	unsigned int flags;
+};
+
+struct __db_associate_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __db_bt_maxkey_msg {
+	unsigned int dbpcl_id;
+	unsigned int maxkey;
+};
+
+struct __db_bt_maxkey_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __db_get_bt_minkey_msg {
+	unsigned int dbpcl_id;
+};
+
+struct __db_get_bt_minkey_reply {
+	/* num return vars: 1 */
+	int status;
+	unsigned int minkey;
+};
+
+struct __db_bt_minkey_msg {
+	unsigned int dbpcl_id;
+	unsigned int minkey;
+};
+
+struct __db_bt_minkey_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __db_close_msg {
+	unsigned int dbpcl_id;
+	unsigned int flags;
+};
+
+struct __db_close_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __db_create_msg {
+	unsigned int dbenvcl_id;
+	unsigned int flags;
+};
+
+struct __db_create_reply {
+	/* num return vars: 1 */
+	int status;
+	unsigned int dbcl_id;
+};
+
+struct __db_del_msg {
+	unsigned int dbpcl_id;
+	unsigned int txnpcl_id;
+	unsigned int keydlen;
+	unsigned int keydoff;
+	unsigned int keyulen;
+	unsigned int keyflags;
+	opaque keydata<>;
+	unsigned int flags;
+};
+
+struct __db_del_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __db_get_encrypt_flags_msg {
+	unsigned int dbpcl_id;
+};
+
+struct __db_get_encrypt_flags_reply {
+	/* num return vars: 1 */
+	int status;
+	unsigned int flags;
+};
+
+struct __db_encrypt_msg {
+	unsigned int dbpcl_id;
+	string passwd<>;
+	unsigned int flags;
+};
+
+struct __db_encrypt_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __db_get_extentsize_msg {
+	unsigned int dbpcl_id;
+};
+
+struct __db_get_extentsize_reply {
+	/* num return vars: 1 */
+	int status;
+	unsigned int extentsize;
+};
+
+struct __db_extentsize_msg {
+	unsigned int dbpcl_id;
+	unsigned int extentsize;
+};
+
+struct __db_extentsize_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __db_get_flags_msg {
+	unsigned int dbpcl_id;
+};
+
+struct __db_get_flags_reply {
+	/* num return vars: 1 */
+	int status;
+	unsigned int flags;
+};
+
+struct __db_flags_msg {
+	unsigned int dbpcl_id;
+	unsigned int flags;
+};
+
+struct __db_flags_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __db_get_msg {
+	unsigned int dbpcl_id;
+	unsigned int txnpcl_id;
+	unsigned int keydlen;
+	unsigned int keydoff;
+	unsigned int keyulen;
+	unsigned int keyflags;
+	opaque keydata<>;
+	unsigned int datadlen;
+	unsigned int datadoff;
+	unsigned int dataulen;
+	unsigned int dataflags;
+	opaque datadata<>;
+	unsigned int flags;
+};
+
+struct __db_get_reply {
+	/* num return vars: 2 */
+	int status;
+	opaque keydata<>;
+	opaque datadata<>;
+};
+
+struct __db_get_name_msg {
+	unsigned int dbpcl_id;
+};
+
+struct __db_get_name_reply {
+	/* num return vars: 2 */
+	int status;
+	string filename<>;
+	string dbname<>;
+};
+
+struct __db_get_open_flags_msg {
+	unsigned int dbpcl_id;
+};
+
+struct __db_get_open_flags_reply {
+	/* num return vars: 1 */
+	int status;
+	unsigned int flags;
+};
+
+struct __db_get_h_ffactor_msg {
+	unsigned int dbpcl_id;
+};
+
+struct __db_get_h_ffactor_reply {
+	/* num return vars: 1 */
+	int status;
+	unsigned int ffactor;
+};
+
+struct __db_h_ffactor_msg {
+	unsigned int dbpcl_id;
+	unsigned int ffactor;
+};
+
+struct __db_h_ffactor_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __db_get_h_nelem_msg {
+	unsigned int dbpcl_id;
+};
+
+struct __db_get_h_nelem_reply {
+	/* num return vars: 1 */
+	int status;
+	unsigned int nelem;
+};
+
+struct __db_h_nelem_msg {
+	unsigned int dbpcl_id;
+	unsigned int nelem;
+};
+
+struct __db_h_nelem_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __db_key_range_msg {
+	unsigned int dbpcl_id;
+	unsigned int txnpcl_id;
+	unsigned int keydlen;
+	unsigned int keydoff;
+	unsigned int keyulen;
+	unsigned int keyflags;
+	opaque keydata<>;
+	unsigned int flags;
+};
+
+struct __db_key_range_reply {
+	/* num return vars: 3 */
+	int status;
+	double less;
+	double equal;
+	double greater;
+};
+
+struct __db_get_lorder_msg {
+	unsigned int dbpcl_id;
+};
+
+struct __db_get_lorder_reply {
+	/* num return vars: 1 */
+	int status;
+	unsigned int lorder;
+};
+
+struct __db_lorder_msg {
+	unsigned int dbpcl_id;
+	unsigned int lorder;
+};
+
+struct __db_lorder_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __db_open_msg {
+	unsigned int dbpcl_id;
+	unsigned int txnpcl_id;
+	string name<>;
+	string subdb<>;
+	unsigned int type;
+	unsigned int flags;
+	unsigned int mode;
+};
+
+struct __db_open_reply {
+	/* num return vars: 3 */
+	int status;
+	unsigned int dbcl_id;
+	unsigned int type;
+	unsigned int lorder;
+};
+
+struct __db_get_pagesize_msg {
+	unsigned int dbpcl_id;
+};
+
+struct __db_get_pagesize_reply {
+	/* num return vars: 1 */
+	int status;
+	unsigned int pagesize;
+};
+
+struct __db_pagesize_msg {
+	unsigned int dbpcl_id;
+	unsigned int pagesize;
+};
+
+struct __db_pagesize_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __db_pget_msg {
+	unsigned int dbpcl_id;
+	unsigned int txnpcl_id;
+	unsigned int skeydlen;
+	unsigned int skeydoff;
+	unsigned int skeyulen;
+	unsigned int skeyflags;
+	opaque skeydata<>;
+	unsigned int pkeydlen;
+	unsigned int pkeydoff;
+	unsigned int pkeyulen;
+	unsigned int pkeyflags;
+	opaque pkeydata<>;
+	unsigned int datadlen;
+	unsigned int datadoff;
+	unsigned int dataulen;
+	unsigned int dataflags;
+	opaque datadata<>;
+	unsigned int flags;
+};
+
+struct __db_pget_reply {
+	/* num return vars: 3 */
+	int status;
+	opaque skeydata<>;
+	opaque pkeydata<>;
+	opaque datadata<>;
+};
+
+struct __db_put_msg {
+	unsigned int dbpcl_id;
+	unsigned int txnpcl_id;
+	unsigned int keydlen;
+	unsigned int keydoff;
+	unsigned int keyulen;
+	unsigned int keyflags;
+	opaque keydata<>;
+	unsigned int datadlen;
+	unsigned int datadoff;
+	unsigned int dataulen;
+	unsigned int dataflags;
+	opaque datadata<>;
+	unsigned int flags;
+};
+
+struct __db_put_reply {
+	/* num return vars: 1 */
+	int status;
+	opaque keydata<>;
+};
+
+struct __db_get_re_delim_msg {
+	unsigned int dbpcl_id;
+};
+
+struct __db_get_re_delim_reply {
+	/* num return vars: 1 */
+	int status;
+	unsigned int delim;
+};
+
+struct __db_re_delim_msg {
+	unsigned int dbpcl_id;
+	unsigned int delim;
+};
+
+struct __db_re_delim_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __db_get_re_len_msg {
+	unsigned int dbpcl_id;
+};
+
+struct __db_get_re_len_reply {
+	/* num return vars: 1 */
+	int status;
+	unsigned int len;
+};
+
+struct __db_re_len_msg {
+	unsigned int dbpcl_id;
+	unsigned int len;
+};
+
+struct __db_re_len_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __db_re_pad_msg {
+	unsigned int dbpcl_id;
+	unsigned int pad;
+};
+
+struct __db_re_pad_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __db_get_re_pad_msg {
+	unsigned int dbpcl_id;
+};
+
+struct __db_get_re_pad_reply {
+	/* num return vars: 1 */
+	int status;
+	unsigned int pad;
+};
+
+struct __db_remove_msg {
+	unsigned int dbpcl_id;
+	string name<>;
+	string subdb<>;
+	unsigned int flags;
+};
+
+struct __db_remove_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __db_rename_msg {
+	unsigned int dbpcl_id;
+	string name<>;
+	string subdb<>;
+	string newname<>;
+	unsigned int flags;
+};
+
+struct __db_rename_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __db_stat_msg {
+	unsigned int dbpcl_id;
+	unsigned int txnpcl_id;
+	unsigned int flags;
+};
+
+struct __db_stat_reply {
+	/* num return vars: 1 */
+	int status;
+	unsigned int stats<>;
+};
+
+struct __db_sync_msg {
+	unsigned int dbpcl_id;
+	unsigned int flags;
+};
+
+struct __db_sync_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __db_truncate_msg {
+	unsigned int dbpcl_id;
+	unsigned int txnpcl_id;
+	unsigned int flags;
+};
+
+struct __db_truncate_reply {
+	/* num return vars: 1 */
+	int status;
+	unsigned int count;
+};
+
+struct __db_cursor_msg {
+	unsigned int dbpcl_id;
+	unsigned int txnpcl_id;
+	unsigned int flags;
+};
+
+struct __db_cursor_reply {
+	/* num return vars: 1 */
+	int status;
+	unsigned int dbcidcl_id;
+};
+
+struct __db_join_msg {
+	unsigned int dbpcl_id;
+	unsigned int curs<>;
+	unsigned int flags;
+};
+
+struct __db_join_reply {
+	/* num return vars: 1 */
+	int status;
+	unsigned int dbcidcl_id;
+};
+
+struct __dbc_close_msg {
+	unsigned int dbccl_id;
+};
+
+struct __dbc_close_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __dbc_count_msg {
+	unsigned int dbccl_id;
+	unsigned int flags;
+};
+
+struct __dbc_count_reply {
+	/* num return vars: 1 */
+	int status;
+	unsigned int dupcount;
+};
+
+struct __dbc_del_msg {
+	unsigned int dbccl_id;
+	unsigned int flags;
+};
+
+struct __dbc_del_reply {
+	/* num return vars: 0 */
+	int status;
+};
+
+struct __dbc_dup_msg {
+	unsigned int dbccl_id;
+	unsigned int flags;
+};
+
+struct __dbc_dup_reply {
+	/* num return vars: 1 */
+	int status;
+	unsigned int dbcidcl_id;
+};
+
+struct __dbc_get_msg {
+	unsigned int dbccl_id;
+	unsigned int keydlen;
+	unsigned int keydoff;
+	unsigned int keyulen;
+	unsigned int keyflags;
+	opaque keydata<>;
+	unsigned int datadlen;
+	unsigned int datadoff;
+	unsigned int dataulen;
+	unsigned int dataflags;
+	opaque datadata<>;
+	unsigned int flags;
+};
+
+struct __dbc_get_reply {
+	/* num return vars: 2 */
+	int status;
+	opaque keydata<>;
+	opaque datadata<>;
+};
+
+struct __dbc_pget_msg {
+	unsigned int dbccl_id;
+	unsigned int skeydlen;
+	unsigned int skeydoff;
+	unsigned int skeyulen;
+	unsigned int skeyflags;
+	opaque skeydata<>;
+	unsigned int pkeydlen;
+	unsigned int pkeydoff;
+	unsigned int pkeyulen;
+	unsigned int pkeyflags;
+	opaque pkeydata<>;
+	unsigned int datadlen;
+	unsigned int datadoff;
+	unsigned int dataulen;
+	unsigned int dataflags;
+	opaque datadata<>;
+	unsigned int flags;
+};
+
+struct __dbc_pget_reply {
+	/* num return vars: 3 */
+	int status;
+	opaque skeydata<>;
+	opaque pkeydata<>;
+	opaque datadata<>;
+};
+
+struct __dbc_put_msg {
+	unsigned int dbccl_id;
+	unsigned int keydlen;
+	unsigned int keydoff;
+	unsigned int keyulen;
+	unsigned int keyflags;
+	opaque keydata<>;
+	unsigned int datadlen;
+	unsigned int datadoff;
+	unsigned int dataulen;
+	unsigned int dataflags;
+	opaque datadata<>;
+	unsigned int flags;
+};
+
+struct __dbc_put_reply {
+	/* num return vars: 1 */
+	int status;
+	opaque keydata<>;
+};
+program DB_RPC_SERVERPROG {
+	version DB_RPC_SERVERVERS {
+		__env_get_cachesize_reply __DB_env_get_cachesize(__env_get_cachesize_msg) = 1;
+		__env_cachesize_reply __DB_env_cachesize(__env_cachesize_msg) = 2;
+		__env_close_reply __DB_env_close(__env_close_msg) = 3;
+		__env_create_reply __DB_env_create(__env_create_msg) = 4;
+		__env_dbremove_reply __DB_env_dbremove(__env_dbremove_msg) = 5;
+		__env_dbrename_reply __DB_env_dbrename(__env_dbrename_msg) = 6;
+		__env_get_encrypt_flags_reply __DB_env_get_encrypt_flags(__env_get_encrypt_flags_msg) = 7;
+		__env_encrypt_reply __DB_env_encrypt(__env_encrypt_msg) = 8;
+		__env_get_flags_reply __DB_env_get_flags(__env_get_flags_msg) = 9;
+		__env_flags_reply __DB_env_flags(__env_flags_msg) = 10;
+		__env_get_home_reply __DB_env_get_home(__env_get_home_msg) = 11;
+		__env_get_open_flags_reply __DB_env_get_open_flags(__env_get_open_flags_msg) = 12;
+		__env_open_reply __DB_env_open(__env_open_msg) = 13;
+		__env_remove_reply __DB_env_remove(__env_remove_msg) = 14;
+		__txn_abort_reply __DB_txn_abort(__txn_abort_msg) = 15;
+		__txn_begin_reply __DB_txn_begin(__txn_begin_msg) = 16;
+		__txn_commit_reply __DB_txn_commit(__txn_commit_msg) = 17;
+		__txn_discard_reply __DB_txn_discard(__txn_discard_msg) = 18;
+		__txn_prepare_reply __DB_txn_prepare(__txn_prepare_msg) = 19;
+		__txn_recover_reply __DB_txn_recover(__txn_recover_msg) = 20;
+		__db_associate_reply __DB_db_associate(__db_associate_msg) = 21;
+		__db_bt_maxkey_reply __DB_db_bt_maxkey(__db_bt_maxkey_msg) = 22;
+		__db_get_bt_minkey_reply __DB_db_get_bt_minkey(__db_get_bt_minkey_msg) = 23;
+		__db_bt_minkey_reply __DB_db_bt_minkey(__db_bt_minkey_msg) = 24;
+		__db_close_reply __DB_db_close(__db_close_msg) = 25;
+		__db_create_reply __DB_db_create(__db_create_msg) = 26;
+		__db_del_reply __DB_db_del(__db_del_msg) = 27;
+		__db_get_encrypt_flags_reply __DB_db_get_encrypt_flags(__db_get_encrypt_flags_msg) = 28;
+		__db_encrypt_reply __DB_db_encrypt(__db_encrypt_msg) = 29;
+		__db_get_extentsize_reply __DB_db_get_extentsize(__db_get_extentsize_msg) = 30;
+		__db_extentsize_reply __DB_db_extentsize(__db_extentsize_msg) = 31;
+		__db_get_flags_reply __DB_db_get_flags(__db_get_flags_msg) = 32;
+		__db_flags_reply __DB_db_flags(__db_flags_msg) = 33;
+		__db_get_reply __DB_db_get(__db_get_msg) = 34;
+		__db_get_name_reply __DB_db_get_name(__db_get_name_msg) = 35;
+		__db_get_open_flags_reply __DB_db_get_open_flags(__db_get_open_flags_msg) = 36;
+		__db_get_h_ffactor_reply __DB_db_get_h_ffactor(__db_get_h_ffactor_msg) = 37;
+		__db_h_ffactor_reply __DB_db_h_ffactor(__db_h_ffactor_msg) = 38;
+		__db_get_h_nelem_reply __DB_db_get_h_nelem(__db_get_h_nelem_msg) = 39;
+		__db_h_nelem_reply __DB_db_h_nelem(__db_h_nelem_msg) = 40;
+		__db_key_range_reply __DB_db_key_range(__db_key_range_msg) = 41;
+		__db_get_lorder_reply __DB_db_get_lorder(__db_get_lorder_msg) = 42;
+		__db_lorder_reply __DB_db_lorder(__db_lorder_msg) = 43;
+		__db_open_reply __DB_db_open(__db_open_msg) = 44;
+		__db_get_pagesize_reply __DB_db_get_pagesize(__db_get_pagesize_msg) = 45;
+		__db_pagesize_reply __DB_db_pagesize(__db_pagesize_msg) = 46;
+		__db_pget_reply __DB_db_pget(__db_pget_msg) = 47;
+		__db_put_reply __DB_db_put(__db_put_msg) = 48;
+		__db_get_re_delim_reply __DB_db_get_re_delim(__db_get_re_delim_msg) = 49;
+		__db_re_delim_reply __DB_db_re_delim(__db_re_delim_msg) = 50;
+		__db_get_re_len_reply __DB_db_get_re_len(__db_get_re_len_msg) = 51;
+		__db_re_len_reply __DB_db_re_len(__db_re_len_msg) = 52;
+		__db_re_pad_reply __DB_db_re_pad(__db_re_pad_msg) = 53;
+		__db_get_re_pad_reply __DB_db_get_re_pad(__db_get_re_pad_msg) = 54;
+		__db_remove_reply __DB_db_remove(__db_remove_msg) = 55;
+		__db_rename_reply __DB_db_rename(__db_rename_msg) = 56;
+		__db_stat_reply __DB_db_stat(__db_stat_msg) = 57;
+		__db_sync_reply __DB_db_sync(__db_sync_msg) = 58;
+		__db_truncate_reply __DB_db_truncate(__db_truncate_msg) = 59;
+		__db_cursor_reply __DB_db_cursor(__db_cursor_msg) = 60;
+		__db_join_reply __DB_db_join(__db_join_msg) = 61;
+		__dbc_close_reply __DB_dbc_close(__dbc_close_msg) = 62;
+		__dbc_count_reply __DB_dbc_count(__dbc_count_msg) = 63;
+		__dbc_del_reply __DB_dbc_del(__dbc_del_msg) = 64;
+		__dbc_dup_reply __DB_dbc_dup(__dbc_dup_msg) = 65;
+		__dbc_get_reply __DB_dbc_get(__dbc_get_msg) = 66;
+		__dbc_pget_reply __DB_dbc_pget(__dbc_pget_msg) = 67;
+		__dbc_put_reply __DB_dbc_put(__dbc_put_msg) = 68;
+	} = 4003;
+} = 351457;
diff --git a/storage/bdb/rpc_server/java/FreeList.java b/storage/bdb/rpc_server/java/FreeList.java
index e831c46613756f3c8a72e5681ca4b3589d6b980c..bec2b87727655128355f203ab484d5d23cb3888c 100644
--- a/storage/bdb/rpc_server/java/FreeList.java
+++ b/storage/bdb/rpc_server/java/FreeList.java
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
- *      Sleepycat Software.  All rights reserved.
+ * Copyright (c) 2001-2004
+ *	Sleepycat Software.  All rights reserved.
  *
- * $Id: FreeList.java,v 1.3 2002/08/09 01:56:09 bostic Exp $
+ * $Id: FreeList.java,v 1.7 2004/04/06 20:43:41 mjc Exp $
  */
 
 package com.sleepycat.db.rpcserver;
@@ -15,88 +15,87 @@ import java.util.*;
  * Keep track of a list of objects by id with a free list.
  * Intentionally package-protected exposure.
  */
-class FreeList
-{
-	class FreeIndex {
-		int index;
-		FreeIndex(int index) { this.index = index; }
-		int getIndex() { return index; }
-	}
+class FreeList {
+    class FreeIndex {
+        int index;
+        FreeIndex(int index) { this.index = index; }
+        int getIndex() { return index; }
+    }
 
-	Vector items = new Vector();
-	FreeIndex free_head = null;
+    Vector items = new Vector();
+    FreeIndex free_head = null;
 
-	public synchronized int add(Object obj) {
-		int pos;
-		if (free_head == null) {
-			pos = items.size();
-			items.addElement(obj);
-			if (pos % 1000 == 0)
-				DbServer.err.println(this + " grew to size " + pos);
-		} else {
-			pos = free_head.getIndex();
-			free_head = (FreeIndex)items.elementAt(pos);
-			items.setElementAt(obj, pos);
-		}
-		return pos;
-	}
+    public synchronized int add(Object obj) {
+        int pos;
+        if (free_head == null) {
+            pos = items.size();
+            items.addElement(obj);
+            if (pos + 1 % 1000 == 0)
+                Server.err.println(this + " grew to size " + (pos + 1));
+        } else {
+            pos = free_head.getIndex();
+            free_head = (FreeIndex)items.elementAt(pos);
+            items.setElementAt(obj, pos);
+        }
+        return pos;
+    }
 
-	public synchronized void del(int pos) {
-		Object obj = items.elementAt(pos);
-		if (obj != null && obj instanceof FreeIndex)
-			throw new NoSuchElementException("index " + pos + " has already been freed");
-		items.setElementAt(free_head, pos);
-		free_head = new FreeIndex(pos);
-	}
+    public synchronized void del(int pos) {
+        Object obj = items.elementAt(pos);
+        if (obj != null && obj instanceof FreeIndex)
+            throw new NoSuchElementException("index " + pos + " has already been freed");
+        items.setElementAt(free_head, pos);
+        free_head = new FreeIndex(pos);
+    }
 
-	public void del(Object obj) {
-		del(items.indexOf(obj));
-	}
+    public void del(Object obj) {
+        del(items.indexOf(obj));
+    }
 
-	public Object get(int pos) {
-		Object obj = items.elementAt(pos);
-		if (obj instanceof FreeIndex)
-			obj = null;
-		return obj;
-	}
+    public Object get(int pos) {
+        Object obj = items.elementAt(pos);
+        if (obj instanceof FreeIndex)
+            obj = null;
+        return obj;
+    }
 
-	public LocalIterator iterator() {
-		return new FreeListIterator();
-	}
+    public LocalIterator iterator() {
+        return new FreeListIterator();
+    }
 
-	/**
-	 * Iterator for a FreeList.  Note that this class doesn't implement
-	 * java.util.Iterator to maintain compatibility with Java 1.1
-	 * Intentionally package-protected exposure.
-	 */
-	class FreeListIterator implements LocalIterator {
-		int current;
+    /**
+     * Iterator for a FreeList.  Note that this class doesn't implement
+     * java.util.Iterator to maintain compatibility with Java 1.1
+     * Intentionally package-protected exposure.
+     */
+    class FreeListIterator implements LocalIterator {
+        int current;
 
-		FreeListIterator() { current = findNext(-1); }
+        FreeListIterator() { current = findNext(-1); }
 
-		private int findNext(int start) {
-			int next = start;
-			while (++next < items.size()) {
-				Object obj = items.elementAt(next);
-				if (obj == null || !(obj instanceof FreeIndex))
-					break;
-			}
-			return next;
-		}
+        private int findNext(int start) {
+            int next = start;
+            while (++next < items.size()) {
+                Object obj = items.elementAt(next);
+                if (obj == null || !(obj instanceof FreeIndex))
+                    break;
+            }
+            return next;
+        }
 
-		public boolean hasNext() {
-			return (findNext(current) < items.size());
-		}
+        public boolean hasNext() {
+            return (findNext(current) < items.size());
+        }
 
-		public Object next() {
-			current = findNext(current);
-			if (current == items.size())
-				throw new NoSuchElementException("enumerated past end of FreeList");
-			return items.elementAt(current);
-		}
+        public Object next() {
+            current = findNext(current);
+            if (current == items.size())
+                throw new NoSuchElementException("enumerated past end of FreeList");
+            return items.elementAt(current);
+        }
 
-		public void remove() {
-			del(current);
-		}
-	}
+        public void remove() {
+            del(current);
+        }
+    }
 }
diff --git a/storage/bdb/rpc_server/java/LocalIterator.java b/storage/bdb/rpc_server/java/LocalIterator.java
index eecb0b5e78d825c9abf5d479492e5bfa81724176..f142eb318324e91f30093298264135f883aadee6 100644
--- a/storage/bdb/rpc_server/java/LocalIterator.java
+++ b/storage/bdb/rpc_server/java/LocalIterator.java
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
- *      Sleepycat Software.  All rights reserved.
+ * Copyright (c) 2001-2004
+ *	Sleepycat Software.  All rights reserved.
  *
- * $Id: LocalIterator.java,v 1.2 2002/08/09 01:56:09 bostic Exp $
+ * $Id: LocalIterator.java,v 1.5 2004/04/06 20:43:41 mjc Exp $
  */
 
 package com.sleepycat.db.rpcserver;
@@ -17,7 +17,7 @@ import java.util.*;
  * Intentionally package-protected exposure.
  */
 interface LocalIterator {
-	boolean hasNext();
-	Object next();
-	void remove();
+    boolean hasNext();
+    Object next();
+    void remove();
 }
diff --git a/storage/bdb/rpc_server/java/README b/storage/bdb/rpc_server/java/README
index c2d8f3abd5762a91713efd85f3ec1e418b56d8d3..f29c87805cc81298378b064d0d4d43879ffa0f40 100644
--- a/storage/bdb/rpc_server/java/README
+++ b/storage/bdb/rpc_server/java/README
@@ -1,4 +1,7 @@
-Berkeley DB Java RPC server, copyright (C) 2002 Sleepycat Software
+Berkeley DB Java RPC server.
+
+Copyright (c) 2002-2004
+	Sleepycat Software.  All rights reserved.
 
 The Java implementation of the Berkeley DB RPC server is intended
 primarily for testing purposes.  It provides the same interface
diff --git a/storage/bdb/rpc_server/java/RpcDb.java b/storage/bdb/rpc_server/java/RpcDb.java
index 59da9be67dc5f4078fe27d4e6d9843999525ac8a..bcdb861e3d4e3e7b9c055807b51be25c7bd2f1f2 100644
--- a/storage/bdb/rpc_server/java/RpcDb.java
+++ b/storage/bdb/rpc_server/java/RpcDb.java
@@ -1,694 +1,780 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
- *      Sleepycat Software.  All rights reserved.
+ * Copyright (c) 2001-2004
+ *	Sleepycat Software.  All rights reserved.
  *
- * $Id: RpcDb.java,v 1.8 2002/08/09 01:56:09 bostic Exp $
+ * $Id: RpcDb.java,v 1.24 2004/11/05 00:42:40 mjc Exp $
  */
 
 package com.sleepycat.db.rpcserver;
 
 import com.sleepycat.db.*;
-import java.io.IOException;
+import com.sleepycat.db.internal.DbConstants;
 import java.io.*;
 import java.util.*;
 
 /**
  * RPC wrapper around a db object for the Java RPC server.
  */
-public class RpcDb extends Timer
-{
-	static final byte[] empty = new byte[0];
-	Db db;
-	RpcDbEnv rdbenv;
-	int refcount = 1;
-	String dbname, subdbname;
-	int type, setflags, openflags;
-
-	public RpcDb(RpcDbEnv rdbenv)
-	{
-		this.rdbenv = rdbenv;
-	}
-
-	void dispose()
-	{
-		if (db != null) {
-			try {
-				db.close(0);
-			} catch(DbException e) {
-				e.printStackTrace(DbServer.err);
-			}
-			db = null;
-		}
-	}
-
-	public  void associate(DbDispatcher server,
-		__db_associate_msg args, __db_associate_reply reply)
-	{
-		try {
-			RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
-			DbTxn txn = (rtxn != null) ? rtxn.txn : null;
-			/*
-			 * We do not support DB_CREATE for associate.   Users
-			 * can only access secondary indices on a read-only basis,
-			 * so whatever they are looking for needs to be there already.
-			 */
-			db.associate(txn, server.getDb(args.sdbpcl_id).db, null, args.flags);
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	public  void close(DbDispatcher server,
-		__db_close_msg args, __db_close_reply reply)
-	{
-		if (--refcount != 0) {
-			reply.status = 0;
-			return;
-		}
-
-		try {
-			db.close(args.flags);
-			db = null;
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		} finally {
-			server.delDb(this);
-		}
-	}
-
-	public  void create(DbDispatcher server,
-		__db_create_msg args, __db_create_reply reply)
-	{
-		try {
-			db = new Db(server.getEnv(args.dbenvcl_id).dbenv, args.flags);
-			reply.dbcl_id = server.addDb(this);
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	public  void cursor(DbDispatcher server,
-		__db_cursor_msg args, __db_cursor_reply reply)
-	{
-		try {
-			RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
-			DbTxn txn = (rtxn != null) ? rtxn.txn : null;
-			Dbc dbc = db.cursor(txn, args.flags);
-			RpcDbc rdbc = new RpcDbc(this, dbc, false);
-			rdbc.timer = (rtxn != null) ? rtxn.timer : this;
-			reply.dbcidcl_id = server.addCursor(rdbc);
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	public  void del(DbDispatcher server,
-		__db_del_msg args, __db_del_reply reply)
-	{
-		try {
-			RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
-			DbTxn txn = (rtxn != null) ? rtxn.txn : null;
-			Dbt key = new Dbt(args.keydata);
-			key.set_dlen(args.keydlen);
-			key.set_doff(args.keydoff);
-			key.set_ulen(args.keyulen);
-			key.set_flags(args.keyflags);
-
-			db.del(txn, key, args.flags);
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	public  void get(DbDispatcher server,
-		__db_get_msg args, __db_get_reply reply)
-	{
-		try {
-			RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
-			DbTxn txn = (rtxn != null) ? rtxn.txn : null;
-			Dbt key = new Dbt(args.keydata);
-			key.set_dlen(args.keydlen);
-			key.set_doff(args.keydoff);
-			key.set_ulen(args.keyulen);
-			key.set_flags(Db.DB_DBT_MALLOC |
-				    (args.keyflags & Db.DB_DBT_PARTIAL));
-
-			Dbt data = new Dbt(args.datadata);
-			data.set_dlen(args.datadlen);
-			data.set_doff(args.datadoff);
-			data.set_ulen(args.dataulen);
-			if ((args.flags & Db.DB_MULTIPLE) != 0) {
-				if (data.get_data().length == 0)
-					data.set_data(new byte[data.get_ulen()]);
-				data.set_flags(Db.DB_DBT_USERMEM |
-				    (args.dataflags & Db.DB_DBT_PARTIAL));
-			} else
-				data.set_flags(Db.DB_DBT_MALLOC |
-				    (args.dataflags & Db.DB_DBT_PARTIAL));
-
-			reply.status = db.get(txn, key, data, args.flags);
-
-			if (key.get_data() == args.keydata ||
-			    key.get_data().length != key.get_size()) {
-				reply.keydata = new byte[key.get_size()];
-				System.arraycopy(key.get_data(), 0, reply.keydata, 0, key.get_size());
-			} else
-				reply.keydata = key.get_data();
-
-			if (data.get_data() == args.datadata ||
-			    data.get_data().length != data.get_size()) {
-				reply.datadata = new byte[data.get_size()];
-				System.arraycopy(data.get_data(), 0, reply.datadata, 0, data.get_size());
-			} else
-				reply.datadata = data.get_data();
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-			reply.keydata = reply.datadata = empty;
-		}
-	}
-
-	public  void join(DbDispatcher server,
-		__db_join_msg args, __db_join_reply reply)
-	{
-		try {
-			Dbc[] cursors = new Dbc[args.curs.length + 1];
-			for(int i = 0; i < args.curs.length; i++) {
-				RpcDbc rdbc = server.getCursor(args.curs[i]);
-				if (rdbc == null) {
-					reply.status = Db.DB_NOSERVER_ID;
-					return;
-				}
-				cursors[i] = rdbc.dbc;
-			}
-			cursors[args.curs.length] = null;
-
-			Dbc jdbc = db.join(cursors, args.flags);
-
-			RpcDbc rjdbc = new RpcDbc(this, jdbc, true);
-			/*
-			 * If our curslist has a parent txn, we need to use it too
-			 * for the activity timeout.  All cursors must be part of
-			 * the same transaction, so just check the first.
-			 */
-			RpcDbc rdbc0 = server.getCursor(args.curs[0]);
-			if (rdbc0.timer != rdbc0)
-				rjdbc.timer = rdbc0.timer;
-
-			/*
-			 * All of the curslist cursors must point to the join
-			 * cursor's timeout so that we do not timeout any of the
-			 * curlist cursors while the join cursor is active.
-			 */
-			for(int i = 0; i < args.curs.length; i++) {
-				RpcDbc rdbc = server.getCursor(args.curs[i]);
-				rdbc.orig_timer = rdbc.timer;
-				rdbc.timer = rjdbc;
-			}
-			reply.dbcidcl_id = server.addCursor(rjdbc);
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	public  void key_range(DbDispatcher server,
-		__db_key_range_msg args, __db_key_range_reply reply)
-	{
-		try {
-			RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
-			DbTxn txn = (rtxn != null) ? rtxn.txn : null;
-			Dbt key = new Dbt(args.keydata);
-			key.set_dlen(args.keydlen);
-			key.set_doff(args.keydoff);
-			key.set_ulen(args.keyulen);
-			key.set_flags(args.keyflags);
-
-			DbKeyRange range = new DbKeyRange();
-
-			db.key_range(txn, key, range, args.flags);
-			reply.status = 0;
-			reply.less = range.less;
-			reply.equal = range.equal;
-			reply.greater = range.greater;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	private boolean findSharedDb(DbDispatcher server, __db_open_reply reply)
-		throws DbException
-	{
-		RpcDb rdb = null;
-		boolean matchFound = false;
-		LocalIterator i = ((DbServer)server).db_list.iterator();
-
-		while (!matchFound && i.hasNext()) {
-			rdb = (RpcDb)i.next();
-			if (rdb != null && rdb != this && rdb.rdbenv == rdbenv &&
-			    (type == Db.DB_UNKNOWN || rdb.type == type) &&
-			    openflags == rdb.openflags &&
-			    setflags == rdb.setflags &&
-			    dbname != null && rdb.dbname != null &&
-			    dbname.equals(rdb.dbname) &&
-			    (subdbname == rdb.subdbname ||
-			     (subdbname != null && rdb.subdbname != null &&
-			      subdbname.equals(rdb.subdbname))))
-				matchFound = true;
-		}
-
-		if (matchFound) {
-			++rdb.refcount;
-			reply.dbcl_id = ((FreeList.FreeListIterator)i).current;
-			reply.type = rdb.db.get_type();
-			reply.dbflags = rdb.db.get_flags_raw();
-			// FIXME: not possible to work out byteorder from Java?
-			reply.lorder = rdb.db.get_byteswapped() ? 4321 : 1234;
-			reply.status = 0;
-
-			DbServer.err.println("Sharing Db: " + reply.dbcl_id);
-		}
-
-		return matchFound;
-	}
-
-	public  void open(DbDispatcher server,
-		__db_open_msg args, __db_open_reply reply)
-	{
-		try {
-			dbname = (args.name.length() > 0) ? args.name : null;
-			subdbname = (args.subdb.length() > 0) ? args.subdb : null;
-			type = args.type;
-			openflags = args.flags & DbServer.DB_SERVER_DBFLAGS;
-
-			if (findSharedDb(server, reply)) {
-				db.close(0);
-				db = null;
-				server.delDb(this);
-			} else {
-				DbServer.err.println("Calling db.open(" + null + ", " + dbname + ", " + subdbname + ", " + args.type + ", " + Integer.toHexString(args.flags) + ", " + args.mode + ")");
-				db.open(null, dbname, subdbname, args.type, args.flags, args.mode);
-
-				reply.dbcl_id = args.dbpcl_id;
-				reply.type = this.type = db.get_type();
-				reply.dbflags = db.get_flags_raw();
-				// FIXME: not possible to work out byteorder from Java?
-				reply.lorder = db.get_byteswapped() ? 4321 : 1234;
-				reply.status = 0;
-			}
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		} catch(FileNotFoundException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = Db.DB_NOTFOUND;
-		}
-
-		// System.err.println("Db.open: reply.status = " + reply.status + ", reply.dbcl_id = " + reply.dbcl_id);
-	}
-
-	public  void pget(DbDispatcher server,
-		__db_pget_msg args, __db_pget_reply reply)
-	{
-		try {
-			RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
-			DbTxn txn = (rtxn != null) ? rtxn.txn : null;
-			Dbt skey = new Dbt(args.skeydata);
-			skey.set_dlen(args.skeydlen);
-			skey.set_doff(args.skeydoff);
-			skey.set_ulen(args.skeyulen);
-			skey.set_flags(Db.DB_DBT_MALLOC |
-			    (args.skeyflags & Db.DB_DBT_PARTIAL));
-
-			Dbt pkey = new Dbt(args.pkeydata);
-			pkey.set_dlen(args.pkeydlen);
-			pkey.set_doff(args.pkeydoff);
-			pkey.set_ulen(args.pkeyulen);
-			pkey.set_flags(Db.DB_DBT_MALLOC |
-			    (args.pkeyflags & Db.DB_DBT_PARTIAL));
-
-			Dbt data = new Dbt(args.datadata);
-			data.set_dlen(args.datadlen);
-			data.set_doff(args.datadoff);
-			data.set_ulen(args.dataulen);
-			data.set_flags(Db.DB_DBT_MALLOC |
-			    (args.dataflags & Db.DB_DBT_PARTIAL));
-
-			db.pget(txn, skey, pkey, data, args.flags);
-
-			if (skey.get_data() == args.skeydata ||
-			    skey.get_data().length != skey.get_size()) {
-				reply.skeydata = new byte[skey.get_size()];
-				System.arraycopy(skey.get_data(), 0, reply.skeydata, 0, skey.get_size());
-			} else
-				reply.skeydata = skey.get_data();
-
-			if (pkey.get_data() == args.pkeydata ||
-			    pkey.get_data().length != pkey.get_size()) {
-				reply.pkeydata = new byte[pkey.get_size()];
-				System.arraycopy(pkey.get_data(), 0, reply.pkeydata, 0, pkey.get_size());
-			} else
-				reply.pkeydata = pkey.get_data();
-
-			if (data.get_data() == args.datadata ||
-			    data.get_data().length != data.get_size()) {
-				reply.datadata = new byte[data.get_size()];
-				System.arraycopy(data.get_data(), 0, reply.datadata, 0, data.get_size());
-			} else
-				reply.datadata = data.get_data();
-
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-			reply.skeydata = reply.pkeydata = reply.datadata = empty;
-		}
-	}
-
-	public  void put(DbDispatcher server,
-		__db_put_msg args, __db_put_reply reply)
-	{
-		try {
-			RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
-			DbTxn txn = (rtxn != null) ? rtxn.txn : null;
-
-			Dbt key = new Dbt(args.keydata);
-			key.set_dlen(args.keydlen);
-			key.set_doff(args.keydoff);
-			key.set_ulen(args.keyulen);
-			key.set_flags(Db.DB_DBT_MALLOC |
-			    (args.keyflags & Db.DB_DBT_PARTIAL));
-
-			Dbt data = new Dbt(args.datadata);
-			data.set_dlen(args.datadlen);
-			data.set_doff(args.datadoff);
-			data.set_ulen(args.dataulen);
-			data.set_flags(args.dataflags);
-
-			reply.status = db.put(txn, key, data, args.flags);
-
-			/*
-			 * If the client did a DB_APPEND, set up key in reply.
-			 * Otherwise just status.
-			 */
-			if ((args.flags & Db.DB_APPEND) != 0) {
-				if (key.get_data() == args.keydata ||
-				    key.get_data().length != key.get_size()) {
-					reply.keydata = new byte[key.get_size()];
-					System.arraycopy(key.get_data(), 0, reply.keydata, 0, key.get_size());
-				} else
-					reply.keydata = key.get_data();
-			} else
-				reply.keydata = empty;
-		} catch(DbException e) {
-			reply.keydata = empty;
-			reply.status = e.get_errno();
-			DbServer.err.println("Exception, setting status to " + reply.status);
-			e.printStackTrace(DbServer.err);
-		}
-	}
-
-	public  void remove(DbDispatcher server,
-		__db_remove_msg args, __db_remove_reply reply)
-	{
-		try {
-			args.name = (args.name.length() > 0) ? args.name : null;
-			args.subdb = (args.subdb.length() > 0) ? args.subdb : null;
-			db.remove(args.name, args.subdb, args.flags);
-			db = null;
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		} catch(FileNotFoundException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = Db.DB_NOTFOUND;
-		} finally {
-			server.delDb(this);
-		}
-	}
-
-	public  void rename(DbDispatcher server,
-		__db_rename_msg args, __db_rename_reply reply)
-	{
-		try {
-			args.name = (args.name.length() > 0) ? args.name : null;
-			args.subdb = (args.subdb.length() > 0) ? args.subdb : null;
-			args.newname = (args.newname.length() > 0) ? args.newname : null;
-			db.rename(args.name, args.subdb, args.newname, args.flags);
-			db = null;
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		} catch(FileNotFoundException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = Db.DB_NOTFOUND;
-		} finally {
-			server.delDb(this);
-		}
-	}
-
-	public  void set_bt_maxkey(DbDispatcher server,
-		__db_bt_maxkey_msg args, __db_bt_maxkey_reply reply)
-	{
-		try {
-			db.set_bt_maxkey(args.maxkey);
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	public  void set_bt_minkey(DbDispatcher server,
-		__db_bt_minkey_msg args, __db_bt_minkey_reply reply)
-	{
-		try {
-			db.set_bt_minkey(args.minkey);
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	public  void set_encrypt(DbDispatcher server,
-		__db_encrypt_msg args, __db_encrypt_reply reply)
-	{
-		try {
-			db.set_encrypt(args.passwd, args.flags);
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	public  void set_flags(DbDispatcher server,
-		__db_flags_msg args, __db_flags_reply reply)
-	{
-		try {
-			// DbServer.err.println("Calling db.setflags(" + Integer.toHexString(args.flags) + ")");
-			db.set_flags(args.flags);
-			setflags |= args.flags;
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	public  void set_h_ffactor(DbDispatcher server,
-		__db_h_ffactor_msg args, __db_h_ffactor_reply reply)
-	{
-		try {
-			db.set_h_ffactor(args.ffactor);
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	public  void set_h_nelem(DbDispatcher server,
-		__db_h_nelem_msg args, __db_h_nelem_reply reply)
-	{
-		try {
-			db.set_h_nelem(args.nelem);
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	public  void set_lorder(DbDispatcher server,
-		__db_lorder_msg args, __db_lorder_reply reply)
-	{
-		try {
-			db.set_lorder(args.lorder);
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	public  void set_pagesize(DbDispatcher server,
-		__db_pagesize_msg args, __db_pagesize_reply reply)
-	{
-		try {
-			db.set_pagesize(args.pagesize);
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	public  void set_q_extentsize(DbDispatcher server,
-		__db_extentsize_msg args, __db_extentsize_reply reply)
-	{
-		try {
-			db.set_q_extentsize(args.extentsize);
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	public  void set_re_delim(DbDispatcher server,
-		__db_re_delim_msg args, __db_re_delim_reply reply)
-	{
-		try {
-			db.set_re_delim(args.delim);
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	public  void set_re_len(DbDispatcher server,
-		__db_re_len_msg args, __db_re_len_reply reply)
-	{
-		try {
-			db.set_re_len(args.len);
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	public  void set_re_pad(DbDispatcher server,
-		__db_re_pad_msg args, __db_re_pad_reply reply)
-	{
-		try {
-			db.set_re_pad(args.pad);
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	public  void stat(DbDispatcher server,
-		__db_stat_msg args, __db_stat_reply reply)
-	{
-		try {
-			Object raw_stat = db.stat(args.flags);
-
-			if (raw_stat instanceof DbHashStat) {
-				DbHashStat hs = (DbHashStat)raw_stat;
-				int[] raw_stats = {
-					hs.hash_magic, hs.hash_version,
-					hs.hash_metaflags, hs.hash_nkeys,
-					hs.hash_ndata, hs.hash_pagesize,
-					hs.hash_ffactor, hs.hash_buckets,
-					hs.hash_free, hs.hash_bfree,
-					hs.hash_bigpages, hs.hash_big_bfree,
-					hs.hash_overflows, hs.hash_ovfl_free,
-					hs.hash_dup, hs.hash_dup_free
-				};
-				reply.stats = raw_stats;
-			} else if (raw_stat instanceof DbQueueStat) {
-				DbQueueStat qs = (DbQueueStat)raw_stat;
-				int[] raw_stats = {
-					qs.qs_magic, qs.qs_version,
-					qs.qs_metaflags, qs.qs_nkeys,
-					qs.qs_ndata, qs.qs_pagesize,
-					qs.qs_extentsize, qs.qs_pages,
-					qs.qs_re_len, qs.qs_re_pad,
-					qs.qs_pgfree, qs.qs_first_recno,
-					qs.qs_cur_recno
-				};
-				reply.stats = raw_stats;
-			} else if (raw_stat instanceof DbBtreeStat) {
-				DbBtreeStat bs = (DbBtreeStat)raw_stat;
-				int[] raw_stats = {
-					bs.bt_magic, bs.bt_version,
-					bs.bt_metaflags, bs.bt_nkeys,
-					bs.bt_ndata, bs.bt_pagesize,
-					bs.bt_maxkey, bs.bt_minkey,
-					bs.bt_re_len, bs.bt_re_pad,
-					bs.bt_levels, bs.bt_int_pg,
-					bs.bt_leaf_pg, bs.bt_dup_pg,
-					bs.bt_over_pg, bs.bt_free,
-					bs.bt_int_pgfree, bs.bt_leaf_pgfree,
-					bs.bt_dup_pgfree, bs.bt_over_pgfree
-				};
-				reply.stats = raw_stats;
-			} else
-				throw new DbException("Invalid return type from db.stat()", Db.DB_NOTFOUND);
-
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-			reply.stats = new int[0];
-		}
-	}
-
-	public  void sync(DbDispatcher server,
-		__db_sync_msg args, __db_sync_reply reply)
-	{
-		try {
-			db.sync(args.flags);
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	public  void truncate(DbDispatcher server,
-		__db_truncate_msg args, __db_truncate_reply reply)
-	{
-		try {
-			RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
-			DbTxn txn = (rtxn != null) ? rtxn.txn : null;
-			reply.count = db.truncate(txn, args.flags);
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
+public class RpcDb extends Timer {
+    static final byte[] empty = new byte[0];
+    DatabaseConfig config;
+    Database db;
+    RpcDbEnv rdbenv;
+    int refcount = 0;
+    String dbname, subdbname;
+    int type, setflags, openflags;
+
+    public RpcDb(RpcDbEnv rdbenv) {
+        this.rdbenv = rdbenv;
+    }
+
+    void dispose() {
+        if (db != null) {
+            try {
+                db.close();
+            } catch (Throwable t) {
+                Util.handleException(t);
+            }
+            db = null;
+        }
+    }
+
+    public  void associate(Dispatcher server,
+                           __db_associate_msg args, __db_associate_reply reply) {
+        try {
+            // The semantics of the new API are a little different.
+            // The secondary database will already be open, here, so we first
+            // have to close it and then call openSecondaryDatabase.
+            RpcDb secondary = server.getDatabase(args.sdbpcl_id);
+            try {
+                secondary.db.close();
+            } finally {
+                secondary.db = null;
+            }
+
+            RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
+            Transaction txn = (rtxn != null) ? rtxn.txn : null;
+
+            args.flags &= ~AssociateCallbacks.DB_RPC2ND_MASK;
+            SecondaryConfig secondaryConfig = new SecondaryConfig();
+            // The secondary has already been opened once, so we don't
+            // need all of the settings here, only a few:
+            secondaryConfig.setReadOnly(secondary.config.getReadOnly());
+            secondaryConfig.setTransactional(secondary.config.getTransactional());
+            secondaryConfig.setKeyCreator(AssociateCallbacks.getCallback(args.flags));
+            secondaryConfig.setAllowPopulate((args.flags & DbConstants.DB_CREATE) != 0);
+            secondary.db = rdbenv.dbenv.openSecondaryDatabase(txn, secondary.dbname, secondary.subdbname, db, secondaryConfig);
+            secondary.config = secondary.db.getConfig();
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public void close(Dispatcher server,
+                       __db_close_msg args, __db_close_reply reply) {
+        if (refcount == 0 || --refcount > 0) {
+            reply.status = 0;
+            return;
+        }
+
+        try {
+            server.delDatabase(this, false);
+            if (db != null)
+                db.close((args.flags & DbConstants.DB_NOSYNC) != 0);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        } finally {
+            db = null;
+        }
+    }
+
+    public  void create(Dispatcher server,
+                        __db_create_msg args, __db_create_reply reply) {
+        try {
+            config = new DatabaseConfig();
+            config.setXACreate((args.flags & DbConstants.DB_XA_CREATE) != 0);
+            reply.dbcl_id = server.addDatabase(this);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void cursor(Dispatcher server,
+                        __db_cursor_msg args, __db_cursor_reply reply) {
+        try {
+            RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
+            Transaction txn = (rtxn != null) ? rtxn.txn : null;
+
+            CursorConfig config = new CursorConfig();
+            config.setDirtyRead((args.flags & DbConstants.DB_DIRTY_READ) != 0);
+            config.setDegree2((args.flags & DbConstants.DB_DEGREE_2) != 0);
+            config.setWriteCursor((args.flags & DbConstants.DB_WRITECURSOR) != 0);
+
+            Cursor dbc = db.openCursor(txn, config);
+            RpcDbc rdbc = new RpcDbc(this, dbc, false);
+            rdbc.timer = (rtxn != null) ? rtxn.timer : this;
+            reply.dbcidcl_id = server.addCursor(rdbc);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void del(Dispatcher server,
+                     __db_del_msg args, __db_del_reply reply) {
+        try {
+            RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
+            Transaction txn = (rtxn != null) ? rtxn.txn : null;
+            DatabaseEntry key = Util.makeDatabaseEntry(args.keydata, args.keydlen, args.keydoff, args.keyulen, args.keyflags);
+
+            db.delete(txn, key /* args.flags == 0 */);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void get(Dispatcher server,
+                     __db_get_msg args, __db_get_reply reply) {
+        try {
+            RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
+            Transaction txn = (rtxn != null) ? rtxn.txn : null;
+            DatabaseEntry key = Util.makeDatabaseEntry(args.keydata, args.keydlen, args.keydoff, args.keyulen, args.keyflags);
+            DatabaseEntry data = Util.makeDatabaseEntry(args.datadata,
+                args.datadlen, args.datadoff, args.dataulen, args.dataflags,
+                args.flags & DbConstants.DB_MULTIPLE);
+
+            OperationStatus status;
+            switch(args.flags & ~Server.DB_MODIFIER_MASK) {
+            case 0:
+                status = db.get(txn, key, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_CONSUME:
+                status = db.consume(txn, key, data, false);
+                break;
+
+            case DbConstants.DB_CONSUME_WAIT:
+                status = db.consume(txn, key, data, true);
+                break;
+
+            case DbConstants.DB_GET_BOTH:
+                status = db.getSearchBoth(txn, key, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_SET_RECNO:
+                status = db.getSearchRecordNumber(txn, key, data, Util.getLockMode(args.flags));
+                break;
+
+            default:
+                throw new UnsupportedOperationException("Unknown flag: " + (args.flags & ~Server.DB_MODIFIER_MASK));
+            }
+            reply.status = Util.getStatus(status);
+
+            reply.keydata = Util.returnDatabaseEntry(key);
+            reply.datadata = Util.returnDatabaseEntry(data);
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+            reply.keydata = reply.datadata = empty;
+        }
+    }
+
+    public  void join(Dispatcher server,
+                      __db_join_msg args, __db_join_reply reply) {
+        try {
+            Cursor[] cursors = new Cursor[args.curs.length + 1];
+            for (int i = 0; i < args.curs.length; i++) {
+                RpcDbc rdbc = server.getCursor(args.curs[i]);
+                if (rdbc == null) {
+                    reply.status = DbConstants.DB_NOSERVER_ID;
+                    return;
+                }
+                cursors[i] = rdbc.dbc;
+            }
+            cursors[args.curs.length] = null;
+
+            JoinConfig config = new JoinConfig();
+            config.setNoSort(args.flags == DbConstants.DB_JOIN_NOSORT);
+            JoinCursor jdbc = db.join(cursors, config);
+
+            RpcDbc rjdbc = new RpcDbc(this, new JoinCursorAdapter(db, jdbc), true);
+            /*
+             * If our curslist has a parent txn, we need to use it too
+             * for the activity timeout.  All cursors must be part of
+             * the same transaction, so just check the first.
+             */
+            RpcDbc rdbc0 = server.getCursor(args.curs[0]);
+            if (rdbc0.timer != rdbc0)
+                rjdbc.timer = rdbc0.timer;
+
+            /*
+             * All of the curslist cursors must point to the join
+             * cursor's timeout so that we do not timeout any of the
+             * curlist cursors while the join cursor is active.
+             */
+            for (int i = 0; i < args.curs.length; i++) {
+                RpcDbc rdbc = server.getCursor(args.curs[i]);
+                rdbc.orig_timer = rdbc.timer;
+                rdbc.timer = rjdbc;
+            }
+            reply.dbcidcl_id = server.addCursor(rjdbc);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void key_range(Dispatcher server,
+                           __db_key_range_msg args, __db_key_range_reply reply) {
+        try {
+            RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
+            Transaction txn = (rtxn != null) ? rtxn.txn : null;
+            DatabaseEntry key = Util.makeDatabaseEntry(args.keydata, args.keydlen, args.keydoff, args.keyulen, args.keyflags);
+
+            KeyRange range = db.getKeyRange(txn, key /*, args.flags == 0 */);
+            reply.status = 0;
+            reply.less = range.less;
+            reply.equal = range.equal;
+            reply.greater = range.greater;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    private boolean findSharedDatabase(Dispatcher server, __db_open_reply reply)
+        throws DatabaseException {
+        RpcDb rdb = null;
+        boolean matchFound = false;
+        LocalIterator i = ((Server)server).db_list.iterator();
+
+        while (!matchFound && i.hasNext()) {
+            rdb = (RpcDb)i.next();
+            if (rdb != null && rdb != this && rdb.rdbenv == rdbenv &&
+                (type == DbConstants.DB_UNKNOWN || rdb.type == type) &&
+                openflags == rdb.openflags &&
+                setflags == rdb.setflags &&
+                dbname != null && rdb.dbname != null &&
+                dbname.equals(rdb.dbname) &&
+                (subdbname == rdb.subdbname ||
+                 (subdbname != null && rdb.subdbname != null &&
+                  subdbname.equals(rdb.subdbname))))
+                matchFound = true;
+        }
+
+        if (matchFound) {
+            ++rdb.refcount;
+            reply.dbcl_id = ((FreeList.FreeListIterator)i).current;
+            reply.type = Util.fromDatabaseType(rdb.config.getType());
+            reply.lorder = rdb.config.getByteOrder();
+            reply.status = 0;
+
+            // Server.err.println("Sharing Database: " + reply.dbcl_id);
+        }
+
+        return matchFound;
+    }
+
+    public  void get_name(Dispatcher server,
+                          __db_get_name_msg args, __db_get_name_reply reply) {
+        reply.filename = dbname;
+        reply.dbname = subdbname;
+        reply.status = 0;
+    }
+
+    public  void get_open_flags(Dispatcher server,
+                                __db_get_open_flags_msg args, __db_get_open_flags_reply reply) {
+        try {
+            reply.flags = 0;
+            if (config.getAllowCreate()) reply.flags |= DbConstants.DB_CREATE;
+            if (config.getExclusiveCreate()) reply.flags |= DbConstants.DB_EXCL;
+            if (config.getReadOnly()) reply.flags |= DbConstants.DB_RDONLY;
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void open(Dispatcher server,
+                      __db_open_msg args, __db_open_reply reply) {
+        try {
+            dbname = (args.name.length() > 0) ? args.name : null;
+            subdbname = (args.subdb.length() > 0) ? args.subdb : null;
+            type = args.type;
+            openflags = args.flags & Server.DB_SERVER_DBFLAGS;
+
+            if (findSharedDatabase(server, reply)) {
+                server.delDatabase(this, true);
+            } else {
+                RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
+                Transaction txn = (rtxn != null) ? rtxn.txn : null;
+
+                // Server.err.println("Calling db.open(" + null + ", " + dbname + ", " + subdbname + ", " + args.type + ", " + Integer.toHexString(args.flags) + ", " + args.mode + ")");
+
+                config.setAllowCreate((args.flags & DbConstants.DB_CREATE) != 0);
+                config.setExclusiveCreate((args.flags & DbConstants.DB_EXCL) != 0);
+                config.setReadOnly((args.flags & DbConstants.DB_RDONLY) != 0);
+                config.setTransactional(txn != null || (args.flags & DbConstants.DB_AUTO_COMMIT) != 0);
+                config.setTruncate((args.flags & DbConstants.DB_TRUNCATE) != 0);
+                config.setType(Util.toDatabaseType(args.type));
+                config.setMode(args.mode);
+
+                db = rdbenv.dbenv.openDatabase(txn, dbname, subdbname, config);
+                ++refcount;
+
+                // Refresh config in case we didn't know the full story before opening
+                config = db.getConfig();
+
+                reply.dbcl_id = args.dbpcl_id;
+                type = reply.type = Util.fromDatabaseType(config.getType());
+                reply.lorder = config.getByteOrder();
+                reply.status = 0;
+            }
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+
+        // System.err.println("Database.open: reply.status = " + reply.status + ", reply.dbcl_id = " + reply.dbcl_id);
+    }
+
+    public  void pget(Dispatcher server,
+                      __db_pget_msg args, __db_pget_reply reply) {
+        try {
+            RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
+            Transaction txn = (rtxn != null) ? rtxn.txn : null;
+            DatabaseEntry skey = Util.makeDatabaseEntry(args.skeydata, args.skeydlen, args.skeydoff, args.skeyulen, args.skeyflags);
+            DatabaseEntry pkey = Util.makeDatabaseEntry(args.pkeydata, args.pkeydlen, args.pkeydoff, args.pkeyulen, args.pkeyflags);
+            DatabaseEntry data = Util.makeDatabaseEntry(args.datadata, args.datadlen, args.datadoff, args.dataulen, args.dataflags);
+
+            OperationStatus status;
+            switch(args.flags & ~Server.DB_MODIFIER_MASK) {
+            case 0:
+                status = ((SecondaryDatabase)db).get(txn, skey, pkey, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_GET_BOTH:
+                status = ((SecondaryDatabase)db).getSearchBoth(txn, skey, pkey, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_SET_RECNO:
+                status = ((SecondaryDatabase)db).getSearchRecordNumber(txn, skey, pkey, data, Util.getLockMode(args.flags));
+                break;
+
+            default:
+                throw new UnsupportedOperationException("Unknown flag: " + (args.flags & ~Server.DB_MODIFIER_MASK));
+            }
+            reply.status = Util.getStatus(status);
+
+            reply.skeydata = Util.returnDatabaseEntry(skey);
+            reply.pkeydata = Util.returnDatabaseEntry(pkey);
+            reply.datadata = Util.returnDatabaseEntry(data);
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+            reply.skeydata = reply.pkeydata = reply.datadata = empty;
+        }
+    }
+
+    public  void put(Dispatcher server,
+                     __db_put_msg args, __db_put_reply reply) {
+        try {
+            RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
+            Transaction txn = (rtxn != null) ? rtxn.txn : null;
+
+            DatabaseEntry key = Util.makeDatabaseEntry(args.keydata, args.keydlen, args.keydoff, args.keyulen, args.keyflags);
+            DatabaseEntry data = Util.makeDatabaseEntry(args.datadata, args.datadlen, args.datadoff, args.dataulen, args.dataflags);
+
+            reply.keydata = empty;
+            OperationStatus status;
+            switch(args.flags & ~Server.DB_MODIFIER_MASK) {
+            case 0:
+                status = db.put(txn, key, data);
+                break;
+
+            case DbConstants.DB_APPEND:
+                status = db.append(txn, key, data);
+                reply.keydata = Util.returnDatabaseEntry(key);
+                break;
+
+            case DbConstants.DB_NODUPDATA:
+                status = db.putNoDupData(txn, key, data);
+                break;
+
+            case DbConstants.DB_NOOVERWRITE:
+                status = db.putNoOverwrite(txn, key, data);
+                break;
+
+            default:
+                throw new UnsupportedOperationException("Unknown flag: " + (args.flags & ~Server.DB_MODIFIER_MASK));
+            }
+            reply.status = Util.getStatus(status);
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+            reply.keydata = empty;
+        }
+    }
+
+    public  void remove(Dispatcher server,
+                        __db_remove_msg args, __db_remove_reply reply) {
+        try {
+            args.name = (args.name.length() > 0) ? args.name : null;
+            args.subdb = (args.subdb.length() > 0) ? args.subdb : null;
+            Database.remove(args.name, args.subdb, config);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        } finally {
+            server.delDatabase(this, false);
+        }
+    }
+
+    public  void rename(Dispatcher server,
+                        __db_rename_msg args, __db_rename_reply reply) {
+        try {
+            args.name = (args.name.length() > 0) ? args.name : null;
+            args.subdb = (args.subdb.length() > 0) ? args.subdb : null;
+            args.newname = (args.newname.length() > 0) ? args.newname : null;
+            Database.rename(args.name, args.subdb, args.newname, config);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        } finally {
+            server.delDatabase(this, false);
+        }
+    }
+
+    public  void set_bt_maxkey(Dispatcher server,
+                               __db_bt_maxkey_msg args, __db_bt_maxkey_reply reply) {
+        try {
+            // XXX: check what to do about: config.setBtreeMaxKey(args.maxkey);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void get_bt_minkey(Dispatcher server,
+                               __db_get_bt_minkey_msg args, __db_get_bt_minkey_reply reply) {
+        try {
+            reply.minkey = config.getBtreeMinKey();
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void set_bt_minkey(Dispatcher server,
+                               __db_bt_minkey_msg args, __db_bt_minkey_reply reply) {
+        try {
+            config.setBtreeMinKey(args.minkey);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void get_encrypt_flags(Dispatcher server,
+                                   __db_get_encrypt_flags_msg args, __db_get_encrypt_flags_reply reply) {
+        try {
+            reply.flags = config.getEncrypted() ? DbConstants.DB_ENCRYPT_AES : 0;
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void set_encrypt(Dispatcher server,
+                             __db_encrypt_msg args, __db_encrypt_reply reply) {
+        try {
+            config.setEncrypted(args.passwd /*, args.flags == 0 */);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void get_flags(Dispatcher server,
+                           __db_get_flags_msg args, __db_get_flags_reply reply) {
+        try {
+            reply.flags = 0;
+            if (config.getChecksum()) reply.flags |= DbConstants.DB_CHKSUM;
+            if (config.getEncrypted()) reply.flags |= DbConstants.DB_ENCRYPT;
+            if (config.getBtreeRecordNumbers()) reply.flags |= DbConstants.DB_RECNUM;
+            if (config.getRenumbering()) reply.flags |= DbConstants.DB_RENUMBER;
+            if (config.getReverseSplitOff()) reply.flags |= DbConstants.DB_REVSPLITOFF;
+            if (config.getSortedDuplicates()) reply.flags |= DbConstants.DB_DUPSORT;
+            if (config.getSnapshot()) reply.flags |= DbConstants.DB_SNAPSHOT;
+            if (config.getUnsortedDuplicates()) reply.flags |= DbConstants.DB_DUP;
+            if (config.getTransactionNotDurable()) reply.flags |= DbConstants.DB_TXN_NOT_DURABLE;
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void set_flags(Dispatcher server,
+                           __db_flags_msg args, __db_flags_reply reply) {
+        try {
+            // Server.err.println("Calling db.setflags(" + Integer.toHexString(args.flags) + ")");
+            config.setChecksum((args.flags & DbConstants.DB_CHKSUM) != 0);
+            config.setBtreeRecordNumbers((args.flags & DbConstants.DB_RECNUM) != 0);
+            config.setRenumbering((args.flags & DbConstants.DB_RENUMBER) != 0);
+            config.setReverseSplitOff((args.flags & DbConstants.DB_REVSPLITOFF) != 0);
+            config.setSortedDuplicates((args.flags & DbConstants.DB_DUPSORT) != 0);
+            config.setSnapshot((args.flags & DbConstants.DB_SNAPSHOT) != 0);
+            config.setUnsortedDuplicates((args.flags & DbConstants.DB_DUP) != 0);
+            config.setTransactionNotDurable((args.flags & DbConstants.DB_TXN_NOT_DURABLE) != 0);
+
+            setflags |= args.flags;
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void get_h_ffactor(Dispatcher server,
+                               __db_get_h_ffactor_msg args, __db_get_h_ffactor_reply reply) {
+        try {
+            reply.ffactor = config.getHashFillFactor();
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void set_h_ffactor(Dispatcher server,
+                               __db_h_ffactor_msg args, __db_h_ffactor_reply reply) {
+        try {
+            config.setHashFillFactor(args.ffactor);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void get_h_nelem(Dispatcher server,
+                             __db_get_h_nelem_msg args, __db_get_h_nelem_reply reply) {
+        try {
+            reply.nelem = config.getHashNumElements();
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void set_h_nelem(Dispatcher server,
+                             __db_h_nelem_msg args, __db_h_nelem_reply reply) {
+        try {
+            config.setHashNumElements(args.nelem);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void get_lorder(Dispatcher server,
+                            __db_get_lorder_msg args, __db_get_lorder_reply reply) {
+        try {
+            reply.lorder = config.getByteOrder();
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void set_lorder(Dispatcher server,
+                            __db_lorder_msg args, __db_lorder_reply reply) {
+        try {
+            config.setByteOrder(args.lorder);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void get_pagesize(Dispatcher server,
+                              __db_get_pagesize_msg args, __db_get_pagesize_reply reply) {
+        try {
+            reply.pagesize = config.getPageSize();
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void set_pagesize(Dispatcher server,
+                              __db_pagesize_msg args, __db_pagesize_reply reply) {
+        try {
+            config.setPageSize(args.pagesize);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void get_q_extentsize(Dispatcher server,
+                                  __db_get_extentsize_msg args, __db_get_extentsize_reply reply) {
+        try {
+            reply.extentsize = config.getQueueExtentSize();
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void set_q_extentsize(Dispatcher server,
+                                  __db_extentsize_msg args, __db_extentsize_reply reply) {
+        try {
+            config.setQueueExtentSize(args.extentsize);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void get_re_delim(Dispatcher server,
+                              __db_get_re_delim_msg args, __db_get_re_delim_reply reply) {
+        try {
+            reply.delim = config.getRecordDelimiter();
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void set_re_delim(Dispatcher server,
+                              __db_re_delim_msg args, __db_re_delim_reply reply) {
+        try {
+            config.setRecordDelimiter(args.delim);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void get_re_len(Dispatcher server,
+                            __db_get_re_len_msg args, __db_get_re_len_reply reply) {
+        try {
+            reply.len = config.getRecordLength();
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void set_re_len(Dispatcher server,
+                            __db_re_len_msg args, __db_re_len_reply reply) {
+        try {
+            config.setRecordLength(args.len);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void get_re_pad(Dispatcher server,
+                            __db_get_re_pad_msg args, __db_get_re_pad_reply reply) {
+        try {
+            reply.pad = config.getRecordPad();
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void set_re_pad(Dispatcher server,
+                            __db_re_pad_msg args, __db_re_pad_reply reply) {
+        try {
+            config.setRecordPad(args.pad);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void stat(Dispatcher server,
+                      __db_stat_msg args, __db_stat_reply reply) {
+        try {
+            RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
+            Transaction txn = (rtxn != null) ? rtxn.txn : null;
+            StatsConfig config = new StatsConfig();
+            config.setClear((args.flags & DbConstants.DB_STAT_CLEAR) != 0);
+            config.setFast((args.flags & DbConstants.DB_FAST_STAT) != 0);
+            DatabaseStats raw_stat = db.getStats(txn, config);
+
+            if (raw_stat instanceof BtreeStats) {
+                BtreeStats bs = (BtreeStats)raw_stat;
+                int[] raw_stats = {
+                    bs.getMagic(), bs.getVersion(),
+                    bs.getMetaFlags(), bs.getNumKeys(),
+                    bs.getNumData(), bs.getPageSize(),
+                    bs.getMaxKey(), bs.getMinKey(),
+                    bs.getReLen(), bs.getRePad(),
+                    bs.getLevels(), bs.getIntPages(),
+                    bs.getLeafPages(), bs.getDupPages(),
+                    bs.getOverPages(), bs.getFree(),
+                    bs.getIntPagesFree(), bs.getLeafPagesFree(),
+                    bs.getDupPagesFree(), bs.getOverPagesFree()
+                };
+                reply.stats = raw_stats;
+            } else if (raw_stat instanceof HashStats) {
+                HashStats hs = (HashStats)raw_stat;
+                int[] raw_stats = {
+                    hs.getMagic(), hs.getVersion(),
+                    hs.getMetaFlags(), hs.getNumKeys(),
+                    hs.getNumData(), hs.getPageSize(),
+                    hs.getFfactor(), hs.getBuckets(),
+                    hs.getFree(), hs.getBFree(),
+                    hs.getBigPages(), hs.getBigBFree(),
+                    hs.getOverflows(), hs.getOvflFree(),
+                    hs.getDup(), hs.getDupFree()
+                };
+                reply.stats = raw_stats;
+            } else if (raw_stat instanceof QueueStats) {
+                QueueStats qs = (QueueStats)raw_stat;
+                int[] raw_stats = {
+                    qs.getMagic(), qs.getVersion(),
+                    qs.getMetaFlags(), qs.getNumKeys(),
+                    qs.getNumData(), qs.getPageSize(),
+                    qs.getExtentSize(), qs.getPages(),
+                    qs.getReLen(), qs.getRePad(),
+                    qs.getPagesFree(), qs.getFirstRecno(),
+                    qs.getCurRecno()
+                };
+                reply.stats = raw_stats;
+            } else
+                throw new DatabaseException("Invalid return type from db.stat()", DbConstants.DB_NOTFOUND);
+
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+            reply.stats = new int[0];
+        }
+    }
+
+    public  void sync(Dispatcher server,
+                      __db_sync_msg args, __db_sync_reply reply) {
+        try {
+            db.sync(/* args.flags == 0 */);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void truncate(Dispatcher server,
+                          __db_truncate_msg args, __db_truncate_reply reply) {
+        try {
+            RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
+            Transaction txn = (rtxn != null) ? rtxn.txn : null;
+            reply.count = db.truncate(txn, true /*, args.flags == 0 */);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+            reply.count = 0;
+        }
+    }
 }
diff --git a/storage/bdb/rpc_server/java/RpcDbEnv.java b/storage/bdb/rpc_server/java/RpcDbEnv.java
index 9d9f1ba432432c0d0eed015ca032c79dc0c3e2f0..71e134f7f35f579e17ac09e301c523a1c1ed5a68 100644
--- a/storage/bdb/rpc_server/java/RpcDbEnv.java
+++ b/storage/bdb/rpc_server/java/RpcDbEnv.java
@@ -1,269 +1,369 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
- *      Sleepycat Software.  All rights reserved.
+ * Copyright (c) 2001-2004
+ *	Sleepycat Software.  All rights reserved.
  *
- * $Id: RpcDbEnv.java,v 1.6 2002/08/23 08:45:59 mjc Exp $
+ * $Id: RpcDbEnv.java,v 1.15 2004/04/21 01:09:11 mjc Exp $
  */
 
 package com.sleepycat.db.rpcserver;
 
 import com.sleepycat.db.*;
-import java.io.IOException;
+import com.sleepycat.db.internal.DbConstants;
 import java.io.*;
 import java.util.*;
 
 /**
  * RPC wrapper around a dbenv for the Java RPC server.
  */
-public class RpcDbEnv extends Timer
-{
-	DbEnv dbenv;
-	String home;
-	long idletime, timeout;
-	int openflags, onflags, offflags;
-	int refcount = 1;
-
-	void dispose()
-	{
-		if (dbenv != null) {
-			try {
-				dbenv.close(0);
-			} catch(DbException e) {
-				e.printStackTrace(DbServer.err);
-			}
-			dbenv = null;
-		}
-	}
-
-	public  void close(DbDispatcher server,
-		__env_close_msg args, __env_close_reply reply)
-	{
-		if (--refcount != 0) {
-			reply.status = 0;
-			return;
-		}
-
-		try {
-			dbenv.close(args.flags);
-			dbenv = null;
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		} finally {
-			server.delEnv(this);
-		}
-	}
-
-	public  void create(DbDispatcher server,
-		__env_create_msg args, __env_create_reply reply)
-	{
-		this.idletime = (args.timeout != 0) ? args.timeout : DbServer.idleto;
-		this.timeout = DbServer.defto;
-		try {
-			dbenv = new DbEnv(0);
-			reply.envcl_id = server.addEnv(this);
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	public  void dbremove(DbDispatcher server,
-		__env_dbremove_msg args, __env_dbremove_reply reply)
-	{
-		try {
-			args.name = (args.name.length() > 0) ? args.name : null;
-			args.subdb = (args.subdb.length() > 0) ? args.subdb : null;
-
-			RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
-			DbTxn txn = (rtxn != null) ? rtxn.txn : null;
-			dbenv.dbremove(txn, args.name, args.subdb, args.flags);
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	public  void dbrename(DbDispatcher server,
-		__env_dbrename_msg args, __env_dbrename_reply reply)
-	{
-		try {
-			args.name = (args.name.length() > 0) ? args.name : null;
-			args.subdb = (args.subdb.length() > 0) ? args.subdb : null;
-			args.newname = (args.newname.length() > 0) ? args.newname : null;
-
-			RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
-			DbTxn txn = (rtxn != null) ? rtxn.txn : null;
-			dbenv.dbrename(txn, args.name, args.subdb, args.newname, args.flags);
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	private boolean findSharedDbEnv(DbDispatcher server, __env_open_reply reply)
-		throws DbException
-	{
-		RpcDbEnv rdbenv = null;
-		boolean matchFound = false;
-		LocalIterator i = ((DbServer)server).env_list.iterator();
-
-		while (!matchFound && i.hasNext()) {
-			rdbenv = (RpcDbEnv)i.next();
-			if (rdbenv != null && rdbenv != this &&
-			    (home == rdbenv.home ||
-			     (home != null && home.equals(rdbenv.home))) &&
-			    openflags == rdbenv.openflags &&
-			    onflags == rdbenv.onflags &&
-			    offflags == rdbenv.offflags)
-				matchFound = true;
-		}
-
-		if (matchFound) {
-			/*
-			 * The only thing left to check is the timeout.
-			 * Since the server timeout set by the client is a hint, for sharing
-			 * we'll give them the benefit of the doubt and grant them the
-			 * longer timeout.
-			 */
-			if (rdbenv.timeout < timeout)
-				rdbenv.timeout = timeout;
-
-			++rdbenv.refcount;
-			reply.envcl_id = ((FreeList.FreeListIterator)i).current;
-			reply.status = 0;
-
-			DbServer.err.println("Sharing DbEnv: " + reply.envcl_id);
-		}
-
-		return matchFound;
-	}
-
-	public  void open(DbDispatcher server,
-		__env_open_msg args, __env_open_reply reply)
-	{
-		try {
-			home = (args.home.length() > 0) ? args.home : null;
-
-			/*
-			 * If they are using locking do deadlock detection for them,
-			 * internally.
-			 */
-			if ((args.flags & Db.DB_INIT_LOCK) != 0)
-				dbenv.set_lk_detect(Db.DB_LOCK_DEFAULT);
-
-			// adjust flags for RPC
-			int newflags = (args.flags & ~DbServer.DB_SERVER_FLAGMASK);
-			openflags = (newflags & DbServer.DB_SERVER_ENVFLAGS);
-
-			if (findSharedDbEnv(server, reply)) {
-				dbenv.close(0);
-				dbenv = null;
-				server.delEnv(this);
-			} else {
-				// TODO: check home?
-				dbenv.open(home, newflags, args.mode);
-				reply.status = 0;
-				reply.envcl_id = args.dbenvcl_id;
-			}
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		} catch(FileNotFoundException e) {
-			reply.status = Db.DB_NOTFOUND;
-		}
-
-		// System.err.println("DbEnv.open: reply.status = " + reply.status + ", reply.envcl_id = " + reply.envcl_id);
-	}
-
-	public  void remove(DbDispatcher server,
-		__env_remove_msg args, __env_remove_reply reply)
-	{
-		try {
-			args.home = (args.home.length() > 0) ? args.home : null;
-			// TODO: check home?
-
-			dbenv.remove(args.home, args.flags);
-			dbenv = null;
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		} catch(FileNotFoundException e) {
-			reply.status = Db.DB_NOTFOUND;
-		} finally {
-			server.delEnv(this);
-		}
-	}
-
-	public  void set_cachesize(DbDispatcher server,
-		__env_cachesize_msg args, __env_cachesize_reply reply)
-	{
-		try {
-			dbenv.set_cachesize(args.gbytes, args.bytes, args.ncache);
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	public  void set_encrypt(DbDispatcher server,
-		__env_encrypt_msg args, __env_encrypt_reply reply)
-	{
-		try {
-			dbenv.set_encrypt(args.passwd, args.flags);
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	public  void set_flags(DbDispatcher server,
-		__env_flags_msg args, __env_flags_reply reply)
-	{
-		try {
-			dbenv.set_flags(args.flags, args.onoff != 0);
-			if (args.onoff != 0)
-				onflags |= args.flags;
-			else
-				offflags |= args.flags;
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	// txn_recover implementation
-	public  void txn_recover(DbDispatcher server,
-		__txn_recover_msg args, __txn_recover_reply reply)
-	{
-		try {
-			DbPreplist[] prep_list = dbenv.txn_recover(args.count, args.flags);
-			if (prep_list != null && prep_list.length > 0) {
-				int count = prep_list.length;
-				reply.retcount = count;
-				reply.txn = new int[count];
-				reply.gid = new byte[count * Db.DB_XIDDATASIZE];
-
-				for(int i = 0; i < count; i++) {
-					reply.txn[i] = server.addTxn(new RpcDbTxn(this, prep_list[i].txn));
-					System.arraycopy(prep_list[i].gid, 0, reply.gid, i * Db.DB_XIDDATASIZE, Db.DB_XIDDATASIZE);
-				}
-			}
-
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
+public class RpcDbEnv extends Timer {
+    EnvironmentConfig config;
+    Environment dbenv;
+    String home;
+    long idletime, timeout;
+    int openflags, onflags, offflags;
+    int refcount = 1;
+
+    void dispose() {
+        if (dbenv != null) {
+            try {
+                dbenv.close();
+            } catch (Throwable t) {
+                Util.handleException(t);
+            }
+            dbenv = null;
+        }
+    }
+
+    public  void close(Dispatcher server,
+                       __env_close_msg args, __env_close_reply reply) {
+        if (--refcount != 0) {
+            reply.status = 0;
+            return;
+        }
+
+        try {
+            server.delEnv(this, false);
+            if (dbenv != null)
+                dbenv.close(/* args.flags == 0 */);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        } finally {
+            dbenv = null;
+        }
+    }
+
+    public  void create(Dispatcher server,
+                        __env_create_msg args, __env_create_reply reply) {
+        this.idletime = (args.timeout != 0) ? args.timeout : Server.idleto;
+        this.timeout = Server.defto;
+        try {
+            config = new EnvironmentConfig();
+            config.setErrorStream(Server.errstream);
+            reply.envcl_id = server.addEnv(this);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void dbremove(Dispatcher server,
+                          __env_dbremove_msg args, __env_dbremove_reply reply) {
+        try {
+            args.name = (args.name.length() > 0) ? args.name : null;
+            args.subdb = (args.subdb.length() > 0) ? args.subdb : null;
+
+            RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
+            Transaction txn = (rtxn != null) ? rtxn.txn : null;
+            dbenv.removeDatabase(txn, args.name, args.subdb /*, args.flags == 0 */);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void dbrename(Dispatcher server,
+                          __env_dbrename_msg args, __env_dbrename_reply reply) {
+        try {
+            args.name = (args.name.length() > 0) ? args.name : null;
+            args.subdb = (args.subdb.length() > 0) ? args.subdb : null;
+            args.newname = (args.newname.length() > 0) ? args.newname : null;
+
+            RpcDbTxn rtxn = server.getTxn(args.txnpcl_id);
+            Transaction txn = (rtxn != null) ? rtxn.txn : null;
+            dbenv.renameDatabase(txn, args.name, args.subdb, args.newname /*, args.flags == 0 */);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    private boolean findSharedEnvironment(Dispatcher server, __env_open_reply reply)
+        throws DatabaseException {
+        RpcDbEnv rdbenv = null;
+        boolean matchFound = false;
+        LocalIterator i = ((Server)server).env_list.iterator();
+
+        while (!matchFound && i.hasNext()) {
+            rdbenv = (RpcDbEnv)i.next();
+            if (rdbenv != null && rdbenv != this &&
+                (home == rdbenv.home ||
+                 (home != null && home.equals(rdbenv.home))) &&
+                openflags == rdbenv.openflags &&
+                onflags == rdbenv.onflags &&
+                offflags == rdbenv.offflags)
+                matchFound = true;
+        }
+
+        if (matchFound) {
+            /*
+             * The only thing left to check is the timeout.
+             * Since the server timeout set by the client is a hint, for sharing
+             * we'll give them the benefit of the doubt and grant them the
+             * longer timeout.
+             */
+            if (rdbenv.timeout < timeout)
+                rdbenv.timeout = timeout;
+
+            ++rdbenv.refcount;
+            reply.envcl_id = ((FreeList.FreeListIterator)i).current;
+            reply.status = 0;
+
+            Server.err.println("Sharing Environment: " + reply.envcl_id);
+        }
+
+        return matchFound;
+    }
+
+    public  void get_home(Dispatcher server,
+                          __env_get_home_msg args, __env_get_home_reply reply) {
+        try {
+            reply.home = dbenv.getHome().toString();
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void get_open_flags(Dispatcher server,
+                                __env_get_open_flags_msg args, __env_get_open_flags_reply reply) {
+        try {
+            reply.flags = 0;
+            if (config.getAllowCreate()) reply.flags |= DbConstants.DB_CREATE;
+            if (config.getInitializeCache()) reply.flags |= DbConstants.DB_INIT_MPOOL;
+            if (config.getInitializeCDB()) reply.flags |= DbConstants.DB_INIT_CDB;
+            if (config.getInitializeLocking()) reply.flags |= DbConstants.DB_INIT_LOCK;
+            if (config.getInitializeLogging()) reply.flags |= DbConstants.DB_INIT_LOG;
+            if (config.getInitializeReplication()) reply.flags |= DbConstants.DB_INIT_REP;
+            if (config.getJoinEnvironment()) reply.flags |= DbConstants.DB_JOINENV;
+            if (config.getLockDown()) reply.flags |= DbConstants.DB_LOCKDOWN;
+            if (config.getPrivate()) reply.flags |= DbConstants.DB_PRIVATE;
+            if (config.getReadOnly()) reply.flags |= DbConstants.DB_RDONLY;
+            if (config.getRunRecovery()) reply.flags |= DbConstants.DB_RECOVER;
+            if (config.getRunFatalRecovery()) reply.flags |= DbConstants.DB_RECOVER_FATAL;
+            if (config.getSystemMemory()) reply.flags |= DbConstants.DB_SYSTEM_MEM;
+            if (config.getTransactional()) reply.flags |= DbConstants.DB_INIT_TXN;
+            if (config.getUseEnvironment()) reply.flags |= DbConstants.DB_USE_ENVIRON;
+            if (config.getUseEnvironmentRoot()) reply.flags |= DbConstants.DB_USE_ENVIRON_ROOT;
+
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void open(Dispatcher server,
+                      __env_open_msg args, __env_open_reply reply) {
+        try {
+            home = (args.home.length() > 0) ? args.home : null;
+
+            /*
+             * If they are using locking do deadlock detection for
+             * them, internally.
+             */
+            if ((args.flags & DbConstants.DB_INIT_LOCK) != 0)
+                config.setLockDetectMode(LockDetectMode.DEFAULT);
+
+            // adjust flags for RPC
+            int newflags = (args.flags & ~Server.DB_SERVER_FLAGMASK);
+            openflags = (newflags & Server.DB_SERVER_ENVFLAGS);
+
+            config.setAllowCreate((args.flags & DbConstants.DB_CREATE) != 0);
+            config.setInitializeCache((args.flags & DbConstants.DB_INIT_MPOOL) != 0);
+            config.setInitializeCDB((args.flags & DbConstants.DB_INIT_CDB) != 0);
+            config.setInitializeLocking((args.flags & DbConstants.DB_INIT_LOCK) != 0);
+            config.setInitializeLogging((args.flags & DbConstants.DB_INIT_LOG) != 0);
+            config.setInitializeReplication((args.flags & DbConstants.DB_INIT_REP) != 0);
+            config.setJoinEnvironment((args.flags & DbConstants.DB_JOINENV) != 0);
+            config.setLockDown((args.flags & DbConstants.DB_LOCKDOWN) != 0);
+            config.setPrivate((args.flags & DbConstants.DB_PRIVATE) != 0);
+            config.setReadOnly((args.flags & DbConstants.DB_RDONLY) != 0);
+            config.setRunRecovery((args.flags & DbConstants.DB_RECOVER) != 0);
+            config.setRunFatalRecovery((args.flags & DbConstants.DB_RECOVER_FATAL) != 0);
+            config.setSystemMemory((args.flags & DbConstants.DB_SYSTEM_MEM) != 0);
+            config.setTransactional((args.flags & DbConstants.DB_INIT_TXN) != 0);
+            config.setUseEnvironment((args.flags & DbConstants.DB_USE_ENVIRON) != 0);
+            config.setUseEnvironmentRoot((args.flags & DbConstants.DB_USE_ENVIRON_ROOT) != 0);
+
+            if (findSharedEnvironment(server, reply))
+                dbenv = null;
+            else if (Server.check_home(home)) {
+                dbenv = new Environment(new File(home), config);
+                // Get the configuration after opening -- it may have changed if we're joining an environment
+                config = dbenv.getConfig();
+                reply.status = 0;
+                reply.envcl_id = args.dbenvcl_id;
+            } else
+                reply.status = DbConstants.DB_NOSERVER_HOME;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+
+        // System.err.println("Environment.open: reply.status = " + reply.status + ", reply.envcl_id = " + reply.envcl_id);
+    }
+
+    public  void remove(Dispatcher server,
+                        __env_remove_msg args, __env_remove_reply reply) {
+        Server.err.println("RpcDbEnv.remove(" + args.home + ")");
+        try {
+            args.home = (args.home.length() > 0) ? args.home : null;
+            // TODO: check home?
+
+            boolean force = (args.flags & DbConstants.DB_FORCE) != 0;
+            config.setUseEnvironment((args.flags & DbConstants.DB_USE_ENVIRON) != 0);
+            config.setUseEnvironmentRoot((args.flags & DbConstants.DB_USE_ENVIRON_ROOT) != 0);
+
+            Environment.remove(new File(args.home), force, config);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        } finally {
+            server.delEnv(this, false);
+        }
+    }
+
+    public  void get_cachesize(Dispatcher server,
+                               __env_get_cachesize_msg args, __env_get_cachesize_reply reply) {
+        try {
+            long cachesize = config.getCacheSize();
+            final long GIGABYTE = 1073741824;
+            reply.gbytes = (int)(cachesize / GIGABYTE);
+            reply.bytes = (int)(cachesize % GIGABYTE);
+            reply.ncache = config.getCacheCount();
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void set_cachesize(Dispatcher server,
+                               __env_cachesize_msg args, __env_cachesize_reply reply) {
+        try {
+            long bytes = (long)args.gbytes * 1024 * 1024 * 1024;
+            bytes += args.bytes;
+            config.setCacheSize(bytes);
+            config.setCacheCount(args.ncache);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void get_encrypt_flags(Dispatcher server,
+                                   __env_get_encrypt_flags_msg args, __env_get_encrypt_flags_reply reply) {
+        try {
+            reply.flags = config.getEncrypted() ? DbConstants.DB_ENCRYPT_AES : 0;
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void set_encrypt(Dispatcher server,
+                             __env_encrypt_msg args, __env_encrypt_reply reply) {
+        try {
+            config.setEncrypted(args.passwd);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void get_flags(Dispatcher server,
+                           __env_get_flags_msg args, __env_get_flags_reply reply) {
+        try {
+            reply.flags = 0;
+            if (config.getCDBLockAllDatabases()) reply.flags |= DbConstants.DB_CDB_ALLDB;
+            if (config.getDirectDatabaseIO()) reply.flags |= DbConstants.DB_DIRECT_DB;
+            if (config.getDirectLogIO()) reply.flags |= DbConstants.DB_DIRECT_LOG;
+            if (config.getInitializeRegions()) reply.flags |= DbConstants.DB_REGION_INIT;
+            if (config.getLogAutoRemove()) reply.flags |= DbConstants.DB_LOG_AUTOREMOVE;
+            if (config.getNoLocking()) reply.flags |= DbConstants.DB_NOLOCKING;
+            if (config.getNoMMap()) reply.flags |= DbConstants.DB_NOMMAP;
+            if (config.getNoPanic()) reply.flags |= DbConstants.DB_NOPANIC;
+            if (config.getOverwrite()) reply.flags |= DbConstants.DB_OVERWRITE;
+            if (config.getTxnNoSync()) reply.flags |= DbConstants.DB_TXN_NOSYNC;
+            if (config.getTxnNotDurable()) reply.flags |= DbConstants.DB_TXN_NOT_DURABLE;
+            if (config.getTxnWriteNoSync()) reply.flags |= DbConstants.DB_TXN_WRITE_NOSYNC;
+            if (config.getYieldCPU()) reply.flags |= DbConstants.DB_YIELDCPU;
+
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void set_flags(Dispatcher server,
+                           __env_flags_msg args, __env_flags_reply reply) {
+        try {
+            boolean onoff = (args.onoff != 0);
+            if (onoff)
+                onflags |= args.flags;
+            else
+                offflags |= args.flags;
+
+            if ((args.flags & DbConstants.DB_CDB_ALLDB) != 0) config.setCDBLockAllDatabases(onoff);
+            if ((args.flags & DbConstants.DB_DIRECT_DB) != 0) config.setDirectDatabaseIO(onoff);
+            if ((args.flags & DbConstants.DB_DIRECT_LOG) != 0) config.setDirectLogIO(onoff);
+            if ((args.flags & DbConstants.DB_REGION_INIT) != 0) config.setInitializeRegions(onoff);
+            if ((args.flags & DbConstants.DB_LOG_AUTOREMOVE) != 0) config.setLogAutoRemove(onoff);
+            if ((args.flags & DbConstants.DB_NOLOCKING) != 0) config.setNoLocking(onoff);
+            if ((args.flags & DbConstants.DB_NOMMAP) != 0) config.setNoMMap(onoff);
+            if ((args.flags & DbConstants.DB_NOPANIC) != 0) config.setNoPanic(onoff);
+            if ((args.flags & DbConstants.DB_OVERWRITE) != 0) config.setOverwrite(onoff);
+            if ((args.flags & DbConstants.DB_TXN_NOSYNC) != 0) config.setTxnNoSync(onoff);
+            if ((args.flags & DbConstants.DB_TXN_NOT_DURABLE) != 0) config.setTxnNotDurable(onoff);
+            if ((args.flags & DbConstants.DB_TXN_WRITE_NOSYNC) != 0) config.setTxnWriteNoSync(onoff);
+            if ((args.flags & DbConstants.DB_YIELDCPU) != 0) config.setYieldCPU(onoff);
+
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    // txn_recover implementation
+    public  void txn_recover(Dispatcher server,
+                             __txn_recover_msg args, __txn_recover_reply reply) {
+        try {
+            PreparedTransaction[] prep_list = dbenv.recover(args.count, args.flags == DbConstants.DB_NEXT);
+            if (prep_list != null && prep_list.length > 0) {
+                int count = prep_list.length;
+                reply.retcount = count;
+                reply.txn = new int[count];
+                reply.gid = new byte[count * DbConstants.DB_XIDDATASIZE];
+
+                for (int i = 0; i < count; i++) {
+                    reply.txn[i] = server.addTxn(new RpcDbTxn(this, prep_list[i].getTransaction()));
+                    System.arraycopy(prep_list[i].getGID(), 0, reply.gid, i * DbConstants.DB_XIDDATASIZE, DbConstants.DB_XIDDATASIZE);
+                }
+            }
+
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
 }
diff --git a/storage/bdb/rpc_server/java/RpcDbTxn.java b/storage/bdb/rpc_server/java/RpcDbTxn.java
index a3207b5e35d9330d7196dd0f111d44a8c8d46f3e..85cdad0380afaa4b6ee5877e006fdf660a6eaf6f 100644
--- a/storage/bdb/rpc_server/java/RpcDbTxn.java
+++ b/storage/bdb/rpc_server/java/RpcDbTxn.java
@@ -1,123 +1,132 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
- *      Sleepycat Software.  All rights reserved.
+ * Copyright (c) 2001-2004
+ *	Sleepycat Software.  All rights reserved.
  *
- * $Id: RpcDbTxn.java,v 1.2 2002/08/09 01:56:10 bostic Exp $
+ * $Id: RpcDbTxn.java,v 1.9 2004/05/04 13:45:33 sue Exp $
  */
 
 package com.sleepycat.db.rpcserver;
 
 import com.sleepycat.db.*;
-import java.io.IOException;
+import com.sleepycat.db.internal.DbConstants;
 import java.io.*;
 import java.util.*;
 
 /**
  * RPC wrapper around a txn object for the Java RPC server.
  */
-public class RpcDbTxn extends Timer
-{
-	RpcDbEnv rdbenv;
-	DbTxn txn;
-
-	public RpcDbTxn(RpcDbEnv rdbenv, DbTxn txn)
-	{
-		this.rdbenv = rdbenv;
-		this.txn = txn;
-	}
-
-	void dispose()
-	{
-		if (txn != null) {
-			try {
-				txn.abort();
-			} catch(DbException e) {
-				e.printStackTrace(DbServer.err);
-			}
-			txn = null;
-		}
-	}
-
-	public  void abort(DbDispatcher server,
-		__txn_abort_msg args, __txn_abort_reply reply)
-	{
-		try {
-			txn.abort();
-			txn = null;
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		} finally {
-			server.delTxn(this);
-		}
-	}
-
-	public  void begin(DbDispatcher server,
-		__txn_begin_msg args, __txn_begin_reply reply)
-	{
-		try {
-			if (rdbenv == null) {
-				reply.status = Db.DB_NOSERVER_ID;
-				return;
-			}
-			DbEnv dbenv = rdbenv.dbenv;
-			RpcDbTxn rparent = server.getTxn(args.parentcl_id);
-			DbTxn parent = (rparent != null) ? rparent.txn : null;
-
-			txn = dbenv.txn_begin(parent, args.flags);
-
-			if (rparent != null)
-				timer = rparent.timer;
-			reply.txnidcl_id = server.addTxn(this);
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	public  void commit(DbDispatcher server,
-		__txn_commit_msg args, __txn_commit_reply reply)
-	{
-		try {
-			txn.commit(args.flags);
-			txn = null;
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		} finally {
-			server.delTxn(this);
-		}
-	}
-
-	public  void discard(DbDispatcher server,
-		__txn_discard_msg args, __txn_discard_reply reply)
-	{
-		try {
-			txn.discard(args.flags);
-			txn = null;
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		} finally {
-			server.delTxn(this);
-		}
-	}
-
-	public  void prepare(DbDispatcher server,
-		__txn_prepare_msg args, __txn_prepare_reply reply)
-	{
-		try {
-			txn.prepare(args.gid);
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
+public class RpcDbTxn extends Timer {
+    RpcDbEnv rdbenv;
+    Transaction txn;
+
+    public RpcDbTxn(RpcDbEnv rdbenv, Transaction txn) {
+        this.rdbenv = rdbenv;
+        this.txn = txn;
+    }
+
+    void dispose() {
+        if (txn != null) {
+            try {
+                txn.abort();
+            } catch (DatabaseException e) {
+                e.printStackTrace(Server.err);
+            }
+            txn = null;
+        }
+    }
+
+    public  void abort(Dispatcher server,
+                       __txn_abort_msg args, __txn_abort_reply reply) {
+        try {
+            txn.abort();
+            txn = null;
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        } finally {
+            server.delTxn(this, false);
+        }
+    }
+
+    public  void begin(Dispatcher server,
+                       __txn_begin_msg args, __txn_begin_reply reply) {
+        try {
+            if (rdbenv == null) {
+                reply.status = DbConstants.DB_NOSERVER_ID;
+                return;
+            }
+            Environment dbenv = rdbenv.dbenv;
+            RpcDbTxn rparent = server.getTxn(args.parentcl_id);
+            Transaction parent = (rparent != null) ? rparent.txn : null;
+
+            TransactionConfig config = new TransactionConfig();
+            config.setDegree2((args.flags & DbConstants.DB_DEGREE_2) != 0);
+            config.setDirtyRead((args.flags & DbConstants.DB_DIRTY_READ) != 0);
+            config.setNoSync((args.flags & DbConstants.DB_TXN_NOSYNC) != 0);
+            config.setNoWait(true);
+            config.setSync((args.flags & DbConstants.DB_TXN_SYNC) != 0);
+
+            txn = dbenv.beginTransaction(parent, config);
+
+            if (rparent != null)
+                timer = rparent.timer;
+            reply.txnidcl_id = server.addTxn(this);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void commit(Dispatcher server,
+                        __txn_commit_msg args, __txn_commit_reply reply) {
+        try {
+            switch(args.flags) {
+            case 0:
+                txn.commit();
+                break;
+
+            case DbConstants.DB_TXN_SYNC:
+                txn.commitSync();
+                break;
+
+            case DbConstants.DB_TXN_NOSYNC:
+                txn.commitSync();
+                break;
+
+            default:
+                throw new UnsupportedOperationException("Unknown flag: " + (args.flags & ~Server.DB_MODIFIER_MASK));
+            }
+            txn = null;
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        } finally {
+            server.delTxn(this, false);
+        }
+    }
+
+    public  void discard(Dispatcher server,
+                         __txn_discard_msg args, __txn_discard_reply reply) {
+        try {
+            txn.discard(/* args.flags == 0 */);
+            txn = null;
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        } finally {
+            server.delTxn(this, false);
+        }
+    }
+
+    public  void prepare(Dispatcher server,
+                         __txn_prepare_msg args, __txn_prepare_reply reply) {
+        try {
+            txn.prepare(args.gid);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
 }
diff --git a/storage/bdb/rpc_server/java/RpcDbc.java b/storage/bdb/rpc_server/java/RpcDbc.java
index a37b4ee48966335e977eff98f9a99529556104f0..75f644c4b1330ae4c64ae098785944ed80764907 100644
--- a/storage/bdb/rpc_server/java/RpcDbc.java
+++ b/storage/bdb/rpc_server/java/RpcDbc.java
@@ -1,238 +1,317 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
- *      Sleepycat Software.  All rights reserved.
+ * Copyright (c) 2001-2004
+ *	Sleepycat Software.  All rights reserved.
  *
- * $Id: RpcDbc.java,v 1.3 2002/08/09 01:56:10 bostic Exp $
+ * $Id: RpcDbc.java,v 1.13 2004/11/05 01:08:31 mjc Exp $
  */
 
 package com.sleepycat.db.rpcserver;
 
 import com.sleepycat.db.*;
-import java.io.IOException;
+import com.sleepycat.db.internal.DbConstants;
 import java.io.*;
 import java.util.*;
 
 /**
  * RPC wrapper around a dbc object for the Java RPC server.
  */
-public class RpcDbc extends Timer
-{
-	static final byte[] empty = new byte[0];
-	RpcDbEnv rdbenv;
-	RpcDb rdb;
-	Dbc dbc;
-	Timer orig_timer;
-	boolean isJoin;
-
-	public RpcDbc(RpcDb rdb, Dbc dbc, boolean isJoin)
-	{
-		this.rdb = rdb;
-		this.rdbenv = rdb.rdbenv;
-		this.dbc = dbc;
-		this.isJoin = isJoin;
-	}
-
-	void dispose()
-	{
-		if (dbc != null) {
-			try {
-				dbc.close();
-			} catch(DbException e) {
-				e.printStackTrace(DbServer.err);
-			}
-			dbc = null;
-		}
-	}
-
-	public  void close(DbDispatcher server,
-		__dbc_close_msg args, __dbc_close_reply reply)
-	{
-		try {
-			dbc.close();
-			dbc = null;
-
-			if (isJoin)
-				for(LocalIterator i = ((DbServer)server).cursor_list.iterator(); i.hasNext(); ) {
-					RpcDbc rdbc = (RpcDbc)i.next();
-					// Unjoin cursors that were joined to create this
-					if (rdbc != null && rdbc.timer == this)
-						rdbc.timer = rdbc.orig_timer;
-				}
-
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		} finally {
-			server.delCursor(this);
-		}
-	}
-
-	public  void count(DbDispatcher server,
-		__dbc_count_msg args, __dbc_count_reply reply)
-	{
-		try {
-			reply.dupcount = dbc.count(args.flags);
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	public  void del(DbDispatcher server,
-		__dbc_del_msg args, __dbc_del_reply reply)
-	{
-		try {
-			reply.status = dbc.del(args.flags);
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	public  void dup(DbDispatcher server,
-		__dbc_dup_msg args, __dbc_dup_reply reply)
-	{
-		try {
-			Dbc newdbc = dbc.dup(args.flags);
-			RpcDbc rdbc = new RpcDbc(rdb, newdbc, false);
-			/* If this cursor has a parent txn, we need to use it too. */
-			if (timer != this)
-				rdbc.timer = timer;
-			reply.dbcidcl_id = server.addCursor(rdbc);
-			reply.status = 0;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	public  void get(DbDispatcher server,
-		__dbc_get_msg args, __dbc_get_reply reply)
-	{
-		try {
-			Dbt key = new Dbt(args.keydata);
-			key.set_dlen(args.keydlen);
-			key.set_ulen(args.keyulen);
-			key.set_doff(args.keydoff);
-			key.set_flags(Db.DB_DBT_MALLOC |
-			    (args.keyflags & Db.DB_DBT_PARTIAL));
-
-			Dbt data = new Dbt(args.datadata);
-			data.set_dlen(args.datadlen);
-			data.set_ulen(args.dataulen);
-			data.set_doff(args.datadoff);
-			if ((args.flags & Db.DB_MULTIPLE) != 0 ||
-			    (args.flags & Db.DB_MULTIPLE_KEY) != 0) {
-				if (data.get_data().length == 0)
-					data.set_data(new byte[data.get_ulen()]);
-				data.set_flags(Db.DB_DBT_USERMEM |
-				    (args.dataflags & Db.DB_DBT_PARTIAL));
-			} else
-				data.set_flags(Db.DB_DBT_MALLOC |
-				    (args.dataflags & Db.DB_DBT_PARTIAL));
-
-			reply.status = dbc.get(key, data, args.flags);
-
-			if (key.get_data() == args.keydata) {
-				reply.keydata = new byte[key.get_size()];
-				System.arraycopy(key.get_data(), 0, reply.keydata, 0, key.get_size());
-			} else
-				reply.keydata = key.get_data();
-
-			if (data.get_data() == args.datadata) {
-				reply.datadata = new byte[data.get_size()];
-				System.arraycopy(data.get_data(), 0, reply.datadata, 0, data.get_size());
-			} else
-				reply.datadata = data.get_data();
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-			reply.keydata = reply.datadata = empty;
-		}
-	}
-
-	public  void pget(DbDispatcher server,
-		__dbc_pget_msg args, __dbc_pget_reply reply)
-	{
-		try {
-			Dbt skey = new Dbt(args.skeydata);
-			skey.set_dlen(args.skeydlen);
-			skey.set_doff(args.skeydoff);
-			skey.set_ulen(args.skeyulen);
-			skey.set_flags(Db.DB_DBT_MALLOC |
-			    (args.skeyflags & Db.DB_DBT_PARTIAL));
-
-			Dbt pkey = new Dbt(args.pkeydata);
-			pkey.set_dlen(args.pkeydlen);
-			pkey.set_doff(args.pkeydoff);
-			pkey.set_ulen(args.pkeyulen);
-			pkey.set_flags(Db.DB_DBT_MALLOC |
-			    (args.pkeyflags & Db.DB_DBT_PARTIAL));
-
-			Dbt data = new Dbt(args.datadata);
-			data.set_dlen(args.datadlen);
-			data.set_doff(args.datadoff);
-			data.set_ulen(args.dataulen);
-			data.set_flags(Db.DB_DBT_MALLOC |
-			    (args.dataflags & Db.DB_DBT_PARTIAL));
-
-			reply.status = dbc.pget(skey, pkey, data, args.flags);
-
-			if (skey.get_data() == args.skeydata) {
-				reply.skeydata = new byte[skey.get_size()];
-				System.arraycopy(skey.get_data(), 0, reply.skeydata, 0, skey.get_size());
-			} else
-				reply.skeydata = skey.get_data();
-
-			if (pkey.get_data() == args.pkeydata) {
-				reply.pkeydata = new byte[pkey.get_size()];
-				System.arraycopy(pkey.get_data(), 0, reply.pkeydata, 0, pkey.get_size());
-			} else
-				reply.pkeydata = pkey.get_data();
-
-			if (data.get_data() == args.datadata) {
-				reply.datadata = new byte[data.get_size()];
-				System.arraycopy(data.get_data(), 0, reply.datadata, 0, data.get_size());
-			} else
-				reply.datadata = data.get_data();
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-		}
-	}
-
-	public  void put(DbDispatcher server,
-		__dbc_put_msg args, __dbc_put_reply reply)
-	{
-		try {
-			Dbt key = new Dbt(args.keydata);
-			key.set_dlen(args.keydlen);
-			key.set_ulen(args.keyulen);
-			key.set_doff(args.keydoff);
-			key.set_flags(args.keyflags & Db.DB_DBT_PARTIAL);
-
-			Dbt data = new Dbt(args.datadata);
-			data.set_dlen(args.datadlen);
-			data.set_ulen(args.dataulen);
-			data.set_doff(args.datadoff);
-			data.set_flags(args.dataflags);
-
-			reply.status = dbc.put(key, data, args.flags);
-
-			if (reply.status == 0 &&
-			    (args.flags == Db.DB_AFTER || args.flags == Db.DB_BEFORE) &&
-			    rdb.db.get_type() == Db.DB_RECNO)
-				reply.keydata = key.get_data();
-			else
-				reply.keydata = empty;
-		} catch(DbException e) {
-			e.printStackTrace(DbServer.err);
-			reply.status = e.get_errno();
-			reply.keydata = empty;
-		}
-	}
+public class RpcDbc extends Timer {
+    static final byte[] empty = new byte[0];
+    RpcDbEnv rdbenv;
+    RpcDb rdb;
+    Cursor dbc;
+    Timer orig_timer;
+    boolean isJoin;
+
+    public RpcDbc(RpcDb rdb, Cursor dbc, boolean isJoin) {
+        this.rdb = rdb;
+        this.rdbenv = rdb.rdbenv;
+        this.dbc = dbc;
+        this.isJoin = isJoin;
+    }
+
+    void dispose() {
+        if (dbc != null) {
+            try {
+                dbc.close();
+            } catch (Throwable t) {
+                Util.handleException(t);
+            }
+            dbc = null;
+        }
+    }
+
+    public  void close(Dispatcher server,
+                       __dbc_close_msg args, __dbc_close_reply reply) {
+        try {
+            dbc.close();
+            dbc = null;
+
+            if (isJoin)
+                for (LocalIterator i = ((Server)server).cursor_list.iterator(); i.hasNext();) {
+                    RpcDbc rdbc = (RpcDbc)i.next();
+                    // Unjoin cursors that were joined to create this
+                    if (rdbc != null && rdbc.timer == this)
+                        rdbc.timer = rdbc.orig_timer;
+                }
+
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        } finally {
+            server.delCursor(this, false);
+        }
+    }
+
+    public  void count(Dispatcher server,
+                       __dbc_count_msg args, __dbc_count_reply reply) {
+        try {
+            reply.dupcount = dbc.count(/* args.flags == 0 */);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void del(Dispatcher server,
+                     __dbc_del_msg args, __dbc_del_reply reply) {
+        try {
+            reply.status = Util.getStatus(dbc.delete(/* args.flags == 0 */));
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void dup(Dispatcher server,
+                     __dbc_dup_msg args, __dbc_dup_reply reply) {
+        try {
+            Cursor newdbc = dbc.dup(args.flags == DbConstants.DB_POSITION);
+            RpcDbc rdbc = new RpcDbc(rdb, newdbc, false);
+            /* If this cursor has a parent txn, we need to use it too. */
+            if (timer != this)
+                rdbc.timer = timer;
+            reply.dbcidcl_id = server.addCursor(rdbc);
+            reply.status = 0;
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+        }
+    }
+
+    public  void get(Dispatcher server,
+                     __dbc_get_msg args, __dbc_get_reply reply) {
+        try {
+            DatabaseEntry key = Util.makeDatabaseEntry(args.keydata, args.keydlen, args.keydoff, args.keyulen, args.keyflags);
+            DatabaseEntry data = Util.makeDatabaseEntry(args.datadata,
+                args.datadlen, args.datadoff, args.dataulen, args.dataflags,
+                args.flags & (DbConstants.DB_MULTIPLE | DbConstants.DB_MULTIPLE_KEY));
+
+            OperationStatus status;
+            switch(args.flags & ~Server.DB_MODIFIER_MASK) {
+            case DbConstants.DB_CURRENT:
+                status = dbc.getCurrent(key, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_FIRST:
+                status = dbc.getFirst(key, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_LAST:
+                status = dbc.getLast(key, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_NEXT:
+                status = dbc.getNext(key, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_NEXT_DUP:
+                status = dbc.getNextDup(key, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_NEXT_NODUP:
+                status = dbc.getNextNoDup(key, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_PREV:
+                status = dbc.getPrev(key, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_PREV_NODUP:
+                status = dbc.getPrevNoDup(key, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_GET_RECNO:
+                status = dbc.getRecordNumber(data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_SET:
+                status = dbc.getSearchKey(key, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_SET_RANGE:
+                status = dbc.getSearchKeyRange(key, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_GET_BOTH:
+                status = dbc.getSearchBoth(key, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_GET_BOTH_RANGE:
+                status = dbc.getSearchBothRange(key, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_SET_RECNO:
+                status = dbc.getSearchRecordNumber(key, data, Util.getLockMode(args.flags));
+                break;
+
+                /* Join cursors */
+            case 0:
+                status = ((JoinCursorAdapter)dbc).jc.getNext(key, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_JOIN_ITEM:
+                status = ((JoinCursorAdapter)dbc).jc.getNext(key, Util.getLockMode(args.flags));
+                break;
+
+            default:
+                throw new UnsupportedOperationException("Unknown flag: " + (args.flags & ~Server.DB_MODIFIER_MASK));
+            }
+            reply.status = Util.getStatus(status);
+            reply.keydata = Util.returnDatabaseEntry(key);
+            reply.datadata = Util.returnDatabaseEntry(data);
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+            reply.keydata = reply.datadata = empty;
+        }
+    }
+
+    public  void pget(Dispatcher server,
+                      __dbc_pget_msg args, __dbc_pget_reply reply) {
+        try {
+            DatabaseEntry skey = Util.makeDatabaseEntry(args.skeydata, args.skeydlen, args.skeydoff, args.skeyulen, args.skeyflags);
+            DatabaseEntry pkey = Util.makeDatabaseEntry(args.pkeydata, args.pkeydlen, args.pkeydoff, args.pkeyulen, args.pkeyflags);
+            DatabaseEntry data = Util.makeDatabaseEntry(args.datadata, args.datadlen, args.datadoff, args.dataulen, args.dataflags);
+
+            OperationStatus status;
+            switch(args.flags & ~Server.DB_MODIFIER_MASK) {
+            case DbConstants.DB_CURRENT:
+                status = ((SecondaryCursor)dbc).getCurrent(skey, pkey, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_FIRST:
+                status = ((SecondaryCursor)dbc).getFirst(skey, pkey, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_LAST:
+                status = ((SecondaryCursor)dbc).getLast(skey, pkey, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_NEXT:
+                status = ((SecondaryCursor)dbc).getNext(skey, pkey, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_NEXT_DUP:
+                status = ((SecondaryCursor)dbc).getNextDup(skey, pkey, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_NEXT_NODUP:
+                status = ((SecondaryCursor)dbc).getNextNoDup(skey, pkey, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_PREV:
+                status = ((SecondaryCursor)dbc).getPrev(skey, pkey, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_PREV_NODUP:
+                status = ((SecondaryCursor)dbc).getPrevNoDup(skey, pkey, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_GET_RECNO:
+                status = ((SecondaryCursor)dbc).getRecordNumber(pkey, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_SET:
+                status = ((SecondaryCursor)dbc).getSearchKey(skey, pkey, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_SET_RANGE:
+                status = ((SecondaryCursor)dbc).getSearchKeyRange(skey, pkey, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_GET_BOTH:
+                status = ((SecondaryCursor)dbc).getSearchBoth(skey, pkey, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_GET_BOTH_RANGE:
+                status = ((SecondaryCursor)dbc).getSearchBothRange(skey, pkey, data, Util.getLockMode(args.flags));
+                break;
+
+            case DbConstants.DB_SET_RECNO:
+                status = ((SecondaryCursor)dbc).getSearchRecordNumber(skey, pkey, data, Util.getLockMode(args.flags));
+                break;
+
+            default:
+                throw new UnsupportedOperationException("Unknown flag: " + (args.flags & ~Server.DB_MODIFIER_MASK));
+            }
+            reply.status = Util.getStatus(status);
+            reply.skeydata = Util.returnDatabaseEntry(skey);
+            reply.pkeydata = Util.returnDatabaseEntry(pkey);
+            reply.datadata = Util.returnDatabaseEntry(data);
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+            reply.skeydata = reply.pkeydata = reply.datadata = empty;
+        }
+    }
+
+    public  void put(Dispatcher server,
+                     __dbc_put_msg args, __dbc_put_reply reply) {
+        try {
+            DatabaseEntry key = Util.makeDatabaseEntry(args.keydata, args.keydlen, args.keydoff, args.keyulen, args.keyflags);
+            DatabaseEntry data = Util.makeDatabaseEntry(args.datadata, args.datadlen, args.datadoff, args.dataulen, args.dataflags);
+
+            OperationStatus status;
+            switch(args.flags & ~Server.DB_MODIFIER_MASK) {
+            case 0:
+                status = dbc.put(key, data);
+                break;
+
+            case DbConstants.DB_AFTER:
+                status = dbc.putAfter(key, data);
+                break;
+
+            case DbConstants.DB_BEFORE:
+                status = dbc.putBefore(key, data);
+                break;
+
+            case DbConstants.DB_NOOVERWRITE:
+                status = dbc.putNoOverwrite(key, data);
+                break;
+
+            case DbConstants.DB_KEYFIRST:
+                status = dbc.putKeyFirst(key, data);
+                break;
+
+            case DbConstants.DB_KEYLAST:
+                status = dbc.putKeyLast(key, data);
+                break;
+
+            case DbConstants.DB_NODUPDATA:
+                status = dbc.putNoDupData(key, data);
+                break;
+
+            case DbConstants.DB_CURRENT:
+                status = dbc.putCurrent(data);
+                break;
+
+            default:
+                throw new UnsupportedOperationException("Unknown flag: " + (args.flags & ~Server.DB_MODIFIER_MASK));
+            }
+            reply.status = Util.getStatus(status);
+            reply.keydata = Util.returnDatabaseEntry(key);
+        } catch (Throwable t) {
+            reply.status = Util.handleException(t);
+            reply.keydata = empty;
+        }
+    }
 }
diff --git a/storage/bdb/rpc_server/java/Timer.java b/storage/bdb/rpc_server/java/Timer.java
index e16f3084f959d7e3a724f11510ff6ff5618d4e65..469ad1ad4d4c0166a4f8c6c7882b694d11f102a5 100644
--- a/storage/bdb/rpc_server/java/Timer.java
+++ b/storage/bdb/rpc_server/java/Timer.java
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
- *      Sleepycat Software.  All rights reserved.
+ * Copyright (c) 2001-2004
+ *	Sleepycat Software.  All rights reserved.
  *
- * $Id: Timer.java,v 1.1 2002/01/03 02:59:39 mjc Exp $
+ * $Id: Timer.java,v 1.4 2004/04/06 20:43:42 mjc Exp $
  */
 
 package com.sleepycat.db.rpcserver;
@@ -15,8 +15,7 @@ package com.sleepycat.db.rpcserver;
  * used to group/share access times. This is done to keep the Java code
  * close to the canonical C implementation of the RPC server.
  */
-public class Timer
-{
-	Timer timer = this;
-	long last_access;
+public class Timer {
+    Timer timer = this;
+    long last_access;
 }
diff --git a/storage/bdb/rpc_server/java/gen/__db_open_reply.java b/storage/bdb/rpc_server/java/gen/__db_open_reply.java
index d90c3754c2fee87d81974d988fa8a015cb4859b7..9b36b44a626fbdef53e80fb39329f1b8635bf270 100644
--- a/storage/bdb/rpc_server/java/gen/__db_open_reply.java
+++ b/storage/bdb/rpc_server/java/gen/__db_open_reply.java
@@ -1,5 +1,5 @@
 /*
- * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * Automatically generated by jrpcgen 0.95.1 on 7/15/04 4:39 PM
  * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
  * See http://acplt.org/ks/remotetea.html for details
  */
@@ -11,7 +11,6 @@ public class __db_open_reply implements XdrAble {
     public int status;
     public int dbcl_id;
     public int type;
-    public int dbflags;
     public int lorder;
 
     public __db_open_reply() {
@@ -27,7 +26,6 @@ public class __db_open_reply implements XdrAble {
         xdr.xdrEncodeInt(status);
         xdr.xdrEncodeInt(dbcl_id);
         xdr.xdrEncodeInt(type);
-        xdr.xdrEncodeInt(dbflags);
         xdr.xdrEncodeInt(lorder);
     }
 
@@ -36,7 +34,6 @@ public class __db_open_reply implements XdrAble {
         status = xdr.xdrDecodeInt();
         dbcl_id = xdr.xdrDecodeInt();
         type = xdr.xdrDecodeInt();
-        dbflags = xdr.xdrDecodeInt();
         lorder = xdr.xdrDecodeInt();
     }
 
diff --git a/storage/bdb/rpc_server/java/gen/__db_stat_msg.java b/storage/bdb/rpc_server/java/gen/__db_stat_msg.java
index af536b5f70789fedf3b0659225ba8d171679a741..419ee14a66e19b0a6f4b91b8cfaab93c9a6aa61d 100644
--- a/storage/bdb/rpc_server/java/gen/__db_stat_msg.java
+++ b/storage/bdb/rpc_server/java/gen/__db_stat_msg.java
@@ -1,5 +1,5 @@
 /*
- * Automatically generated by jrpcgen 0.95.1 on 12/18/01 7:23 PM
+ * Automatically generated by jrpcgen 0.95.1 on 7/15/04 4:39 PM
  * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
  * See http://acplt.org/ks/remotetea.html for details
  */
@@ -9,6 +9,7 @@ import java.io.IOException;
 
 public class __db_stat_msg implements XdrAble {
     public int dbpcl_id;
+    public int txnpcl_id;
     public int flags;
 
     public __db_stat_msg() {
@@ -22,12 +23,14 @@ public class __db_stat_msg implements XdrAble {
     public void xdrEncode(XdrEncodingStream xdr)
            throws OncRpcException, IOException {
         xdr.xdrEncodeInt(dbpcl_id);
+        xdr.xdrEncodeInt(txnpcl_id);
         xdr.xdrEncodeInt(flags);
     }
 
     public void xdrDecode(XdrDecodingStream xdr)
            throws OncRpcException, IOException {
         dbpcl_id = xdr.xdrDecodeInt();
+        txnpcl_id = xdr.xdrDecodeInt();
         flags = xdr.xdrDecodeInt();
     }
 
diff --git a/storage/bdb/rpc_server/java/gen/db_server.java b/storage/bdb/rpc_server/java/gen/db_server.java
index a14a77028a2353ce2f4cdf85d0c692966d74cd9d..dccc3d8ad168be64fb5dd768cb916512f87240de 100644
--- a/storage/bdb/rpc_server/java/gen/db_server.java
+++ b/storage/bdb/rpc_server/java/gen/db_server.java
@@ -1,5 +1,5 @@
 /*
- * Automatically generated by jrpcgen 0.95.1 on 3/19/02 10:30 AM
+ * Automatically generated by jrpcgen 0.95.1 on 2/11/04 1:28 PM
  * jrpcgen is part of the "Remote Tea" ONC/RPC package for Java
  * See http://acplt.org/ks/remotetea.html for details
  */
@@ -11,57 +11,75 @@ import java.io.IOException;
  * A collection of constants used by the "db_server" ONC/RPC program.
  */
 public interface db_server {
-    public static final int __DB_db_close_4001 = 19;
-    public static final int __DB_db_flags_4001 = 24;
-    public static final int __DB_dbc_dup_4001 = 47;
-    public static final int __DB_db_encrypt_4001 = 22;
-    public static final int __DB_env_dbrename_4001 = 5;
-    public static final int __DB_env_remove_4001 = 9;
-    public static final int __DB_dbc_pget_4001 = 49;
-    public static final int __DB_env_cachesize_4001 = 1;
-    public static final int __DB_db_lorder_4001 = 29;
-    public static final int __DB_db_key_range_4001 = 28;
-    public static final int __DB_db_bt_minkey_4001 = 18;
-    public static final int __DB_db_sync_4001 = 40;
-    public static final int __DB_dbc_close_4001 = 44;
-    public static final int __DB_db_join_4001 = 43;
-    public static final int __DB_db_pagesize_4001 = 31;
-    public static final int DB_RPC_SERVERVERS = 4001;
-    public static final int __DB_db_open_4001 = 30;
-    public static final int __DB_dbc_get_4001 = 48;
-    public static final int __DB_db_cursor_4001 = 42;
-    public static final int __DB_txn_commit_4001 = 12;
-    public static final int __DB_dbc_del_4001 = 46;
-    public static final int __DB_env_create_4001 = 3;
-    public static final int __DB_env_open_4001 = 8;
-    public static final int __DB_txn_prepare_4001 = 14;
-    public static final int __DB_db_pget_4001 = 32;
-    public static final int __DB_db_stat_4001 = 39;
-    public static final int __DB_db_h_nelem_4001 = 27;
-    public static final int __DB_db_remove_4001 = 37;
-    public static final int __DB_db_re_delim_4001 = 34;
-    public static final int __DB_db_re_pad_4001 = 36;
-    public static final int __DB_txn_abort_4001 = 10;
-    public static final int __DB_txn_recover_4001 = 15;
-    public static final int __DB_db_get_4001 = 25;
-    public static final int __DB_db_extentsize_4001 = 23;
+    public static final int __DB_db_get_re_delim_4003 = 49;
+    public static final int __DB_db_close_4003 = 25;
+    public static final int __DB_db_flags_4003 = 33;
+    public static final int __DB_dbc_dup_4003 = 65;
+    public static final int __DB_db_get_open_flags_4003 = 36;
+    public static final int __DB_db_encrypt_4003 = 29;
+    public static final int __DB_env_remove_4003 = 14;
+    public static final int __DB_env_dbrename_4003 = 6;
+    public static final int __DB_dbc_pget_4003 = 67;
+    public static final int __DB_env_get_cachesize_4003 = 1;
+    public static final int __DB_env_cachesize_4003 = 2;
+    public static final int __DB_db_get_lorder_4003 = 42;
+    public static final int __DB_db_lorder_4003 = 43;
+    public static final int __DB_db_key_range_4003 = 41;
+    public static final int __DB_env_get_open_flags_4003 = 12;
+    public static final int __DB_db_bt_minkey_4003 = 24;
+    public static final int __DB_db_sync_4003 = 58;
+    public static final int __DB_dbc_close_4003 = 62;
+    public static final int __DB_db_join_4003 = 61;
+    public static final int __DB_db_pagesize_4003 = 46;
+    public static final int DB_RPC_SERVERVERS = 4003;
+    public static final int __DB_db_open_4003 = 44;
+    public static final int __DB_db_get_extentsize_4003 = 30;
+    public static final int __DB_dbc_get_4003 = 66;
+    public static final int __DB_db_cursor_4003 = 60;
+    public static final int __DB_txn_commit_4003 = 17;
+    public static final int __DB_dbc_del_4003 = 64;
+    public static final int __DB_env_create_4003 = 4;
+    public static final int __DB_env_open_4003 = 13;
+    public static final int __DB_txn_prepare_4003 = 19;
+    public static final int __DB_db_get_re_pad_4003 = 54;
+    public static final int __DB_db_pget_4003 = 47;
+    public static final int __DB_db_stat_4003 = 57;
+    public static final int __DB_db_h_nelem_4003 = 40;
+    public static final int __DB_db_remove_4003 = 55;
+    public static final int __DB_db_get_flags_4003 = 32;
+    public static final int __DB_db_re_delim_4003 = 50;
+    public static final int __DB_db_re_pad_4003 = 53;
+    public static final int __DB_env_get_flags_4003 = 9;
+    public static final int __DB_txn_abort_4003 = 15;
+    public static final int __DB_env_get_encrypt_flags_4003 = 7;
+    public static final int __DB_db_get_encrypt_flags_4003 = 28;
+    public static final int __DB_db_get_h_ffactor_4003 = 37;
+    public static final int __DB_txn_recover_4003 = 20;
+    public static final int __DB_db_get_4003 = 34;
+    public static final int __DB_db_extentsize_4003 = 31;
+    public static final int __DB_db_get_h_nelem_4003 = 39;
+    public static final int __DB_dbc_put_4003 = 68;
     public static final int DB_RPC_SERVERPROG = 351457;
-    public static final int __DB_dbc_put_4001 = 50;
-    public static final int __DB_db_truncate_4001 = 41;
-    public static final int __DB_db_del_4001 = 21;
-    public static final int __DB_db_bt_maxkey_4001 = 17;
-    public static final int __DB_env_dbremove_4001 = 4;
-    public static final int __DB_txn_discard_4001 = 13;
-    public static final int __DB_db_re_len_4001 = 35;
-    public static final int __DB_env_close_4001 = 2;
-    public static final int __DB_env_flags_4001 = 7;
-    public static final int __DB_db_rename_4001 = 38;
-    public static final int __DB_db_associate_4001 = 16;
-    public static final int __DB_txn_begin_4001 = 11;
-    public static final int __DB_env_encrypt_4001 = 6;
-    public static final int __DB_db_h_ffactor_4001 = 26;
-    public static final int __DB_db_put_4001 = 33;
-    public static final int __DB_db_create_4001 = 20;
-    public static final int __DB_dbc_count_4001 = 45;
+    public static final int __DB_db_get_re_len_4003 = 51;
+    public static final int __DB_db_truncate_4003 = 59;
+    public static final int __DB_db_del_4003 = 27;
+    public static final int __DB_db_bt_maxkey_4003 = 22;
+    public static final int __DB_env_dbremove_4003 = 5;
+    public static final int __DB_db_get_pagesize_4003 = 45;
+    public static final int __DB_db_get_name_4003 = 35;
+    public static final int __DB_txn_discard_4003 = 18;
+    public static final int __DB_db_re_len_4003 = 52;
+    public static final int __DB_env_close_4003 = 3;
+    public static final int __DB_env_flags_4003 = 10;
+    public static final int __DB_db_rename_4003 = 56;
+    public static final int __DB_db_get_bt_minkey_4003 = 23;
+    public static final int __DB_db_associate_4003 = 21;
+    public static final int __DB_txn_begin_4003 = 16;
+    public static final int __DB_env_encrypt_4003 = 8;
+    public static final int __DB_db_h_ffactor_4003 = 38;
+    public static final int __DB_db_put_4003 = 48;
+    public static final int __DB_db_create_4003 = 26;
+    public static final int __DB_env_get_home_4003 = 11;
+    public static final int __DB_dbc_count_4003 = 63;
 }
 // End of db_server.java
diff --git a/storage/bdb/rpc_server/java/s_jrpcgen b/storage/bdb/rpc_server/java/s_jrpcgen
index fed8cbf56bba393d370eb91b0bb841e609d995f2..b585f431f0bd8cabaae8d1f94c220e3e976d7da7 100644
--- a/storage/bdb/rpc_server/java/s_jrpcgen
+++ b/storage/bdb/rpc_server/java/s_jrpcgen
@@ -1,3 +1,3 @@
 #!/bin/sh
 
-java -jar jrpcgen.jar -d gen -noclient -nobackup -p com.sleepycat.db.rpcserver -s DbServerStub ../db_server.x
+java -jar jrpcgen.jar -d gen -noclient -nobackup -p com.sleepycat.db.rpcserver -s ServerStubs ../db_server.x
diff --git a/storage/bdb/rpc_server/rpc.src b/storage/bdb/rpc_server/rpc.src
index 7afee49b066d9d265e4f809177e2c7425571304c..fd6af9f96b1bf1d0d7a52531c27d334bb3fe4644 100644
--- a/storage/bdb/rpc_server/rpc.src
+++ b/storage/bdb/rpc_server/rpc.src
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #       Sleepycat Software.  All rights reserved.
 #
-# $Id: rpc.src,v 1.75 2002/07/18 02:57:19 margo Exp $
+# $Id: rpc.src,v 1.90 2004/07/15 19:54:11 sue Exp $
 #
 # Syntax:
 # BEGIN	function_name  {CODE | RETCODE | NOFUNC}
@@ -39,7 +39,8 @@
 # All messages automatically return "status" and return that from
 # the call to the function.  RET's are additional things the server
 # may return.  RET is like ARG but does not need the IGNORE option.
-# RET	{STRING | INT | DBT | LIST | ID} varname [GID | INT | ID]
+# ARETs are RETs which are returned in arguments by the client.
+# {RET | ARET}	{STRING | INT | DBT | LIST | ID} varname [GID | INT | ID]
 #	STRING:	string from server
 #	DBT:	DBT arg from server
 #	LIST:	list from server (NULL-terminated list)
@@ -65,13 +66,19 @@ ARG	ID	DB_ENV *	dbenv
 FUNCPROT	int (*)(DB_ENV *, DBT *, DB_LSN *, db_recops)
 FUNCARG	int (*func0) __P((DB_ENV *, DBT *, DB_LSN *, db_recops))
 END
+BEGIN	env_get_cachesize	CODE
+ARG	ID	DB_ENV *	dbenv
+ARET	INT	u_int32_t	gbytes
+ARET	INT	u_int32_t	bytes
+ARET	INT	int		ncache
+END
 BEGIN	env_cachesize	CODE
 ARG	ID	DB_ENV *	dbenv
 ARG	INT	u_int32_t	gbytes
 ARG	INT	u_int32_t	bytes
 ARG	INT	int		ncache
 END
-BEGIN	env_close	RETCODE
+BEGIN	env_close	CODE
 ARG	ID	DB_ENV *	dbenv
 ARG	INT	u_int32_t	flags
 END
@@ -80,6 +87,10 @@ ARG	IGNORE	DB_ENV *	dbenv
 ARG	INT	long		timeout
 RET	ID	long		env
 END
+BEGIN	get_data_dirs	NOFUNC
+ARG	ID	DB_ENV *	dbenv
+ARG	STRING	const char ***	dirpp
+END
 BEGIN	set_data_dir	NOFUNC
 ARG	ID	DB_ENV *	dbenv
 ARG	STRING	const char *	dir
@@ -99,6 +110,10 @@ ARG	STRING	const char *	subdb
 ARG	STRING	const char *	newname
 ARG	INT	u_int32_t	flags
 END
+BEGIN	env_get_encrypt_flags		CODE
+ARG	ID	DB_ENV *	dbenv
+ARET	INT	u_int32_t	flags
+END
 BEGIN	env_encrypt		CODE
 ARG	ID	DB_ENV *	dbenv
 ARG	STRING	const char *	passwd
@@ -109,32 +124,61 @@ ARG	ID	DB_ENV *	dbenv
 FUNCPROT	void (*)(DB_ENV *, int, int)
 FUNCARG	void (*func0) __P((DB_ENV *, int, int))
 END
+BEGIN	env_get_flags	CODE
+ARG	ID	DB_ENV *	dbenv
+ARET	INT	u_int32_t	flags
+END
 BEGIN	env_flags	CODE
 ARG	ID	DB_ENV *	dbenv
 ARG	INT	u_int32_t	flags
 ARG	INT	int		onoff
 END
+BEGIN	get_lg_bsize	NOFUNC
+ARG	ID	DB_ENV *	dbenv
+ARET	INT	u_int32_t	bsize
+END
 BEGIN	set_lg_bsize	NOFUNC
 ARG	ID	DB_ENV *	dbenv
 ARG	INT	u_int32_t	bsize
 END
+BEGIN	get_lg_dir	NOFUNC
+ARG	ID	DB_ENV *	dbenv
+ARET	STRING	const char *	dir
+END
 BEGIN	set_lg_dir	NOFUNC
 ARG	ID	DB_ENV *	dbenv
 ARG	STRING	const char *	dir
 END
+BEGIN	get_lg_max	NOFUNC
+ARG	ID	DB_ENV *	dbenv
+ARET	INT	u_int32_t	max
+END
 BEGIN	set_lg_max	NOFUNC
 ARG	ID	DB_ENV *	dbenv
 ARG	INT	u_int32_t	max
 END
+BEGIN	get_lg_regionmax	NOFUNC
+ARG	ID	DB_ENV *	dbenv
+ARET	INT	u_int32_t	max
+END
 BEGIN	set_lg_regionmax	NOFUNC
 ARG	ID	DB_ENV *	dbenv
 ARG	INT	u_int32_t	max
 END
+BEGIN	get_lk_conflicts	NOFUNC
+ARG	ID	DB_ENV *	dbenv
+ARG	IGNORE	const u_int8_t **	conflicts
+ARG	IGNORE	int *		modes
+END
 BEGIN	set_lk_conflict	NOFUNC
 ARG	ID	DB_ENV *	dbenv
 ARG	INT	u_int8_t *	conflicts
 ARG	INT	int		modes
 END
+BEGIN	get_lk_detect	NOFUNC
+ARG	ID	DB_ENV *	dbenv
+ARET	INT	u_int32_t	detect
+END
 BEGIN	set_lk_detect	NOFUNC
 ARG	ID	DB_ENV *	dbenv
 ARG	INT	u_int32_t	detect
@@ -143,22 +187,64 @@ BEGIN	set_lk_max	NOFUNC
 ARG	ID	DB_ENV *	dbenv
 ARG	INT	u_int32_t	max
 END
+BEGIN	get_lk_max_locks	NOFUNC
+ARG	ID	DB_ENV *	dbenv
+ARET	INT	u_int32_t	max
+END
 BEGIN	set_lk_max_locks	NOFUNC
 ARG	ID	DB_ENV *	dbenv
 ARG	INT	u_int32_t	max
 END
+BEGIN	get_lk_max_lockers	NOFUNC
+ARG	ID	DB_ENV *	dbenv
+ARET	INT	u_int32_t	max
+END
 BEGIN	set_lk_max_lockers	NOFUNC
 ARG	ID	DB_ENV *	dbenv
 ARG	INT	u_int32_t	max
 END
+BEGIN	get_lk_max_objects	NOFUNC
+ARG	ID	DB_ENV *	dbenv
+ARET	INT	u_int32_t	max
+END
 BEGIN	set_lk_max_objects	NOFUNC
 ARG	ID	DB_ENV *	dbenv
 ARG	INT	u_int32_t	max
 END
+BEGIN	get_mp_max_openfd	NOFUNC
+ARG	ID	DB_ENV *	dbenv
+ARET	INT	int		nopen
+END
+BEGIN	set_mp_max_openfd	NOFUNC
+ARG	ID	DB_ENV *	dbenv
+ARG	INT	int		nopen
+END
+BEGIN	get_mp_max_write	NOFUNC
+ARG	ID	DB_ENV *	dbenv
+ARET	INT	int		nwrite
+ARET	INT	int		nsleep
+END
+BEGIN	set_mp_max_write	NOFUNC
+ARG	ID	DB_ENV *	dbenv
+ARG	INT	int		nwrite
+ARG	INT	int		nsleep
+END
+BEGIN	get_mp_mmapsize	NOFUNC
+ARG	ID	DB_ENV *	dbenv
+ARET	INT	size_t		mmapsize
+END
 BEGIN	set_mp_mmapsize	NOFUNC
 ARG	ID	DB_ENV *	dbenv
 ARG	INT	size_t		mmapsize
 END
+BEGIN	env_get_home	CODE
+ARG	ID	DB_ENV *	dbenv
+ARET	STRING	const char *	home
+END
+BEGIN	env_get_open_flags	CODE
+ARG	ID	DB_ENV *	dbenv
+ARET	INT	u_int32_t	flags
+END
 BEGIN	env_open	RETCODE
 ARG	ID	DB_ENV *	dbenv
 ARG	STRING	const char *	home
@@ -176,31 +262,61 @@ ARG	ID	DB_ENV *	dbenv
 ARG	STRING	const char *	home
 ARG	INT	u_int32_t	flags
 END
+BEGIN	get_shm_key	NOFUNC
+ARG	ID	DB_ENV *	dbenv
+ARET	INT	long		shm_key
+END
 BEGIN	set_shm_key	NOFUNC
 ARG	ID	DB_ENV *	dbenv
 ARG	INT	long		shm_key
 END
+BEGIN	get_tas_spins	NOFUNC
+ARG	ID	DB_ENV *	dbenv
+ARET	INT	u_int32_t	tas_spins
+END
 BEGIN	set_tas_spins	NOFUNC
 ARG	ID	DB_ENV *	dbenv
 ARG	INT	u_int32_t	tas_spins
 END
+BEGIN	get_timeout	NOFUNC
+ARG	ID	DB_ENV *	dbenv
+ARET	INT	u_int32_t	timeout
+ARG	INT	u_int32_t	flags
+END
 BEGIN	set_timeout	NOFUNC
 ARG	ID	DB_ENV *	dbenv
 ARG	INT	u_int32_t	timeout
 ARG	INT	u_int32_t	flags
 END
+BEGIN	get_tmp_dir	NOFUNC
+ARG	ID	DB_ENV *	dbenv
+ARET	STRING	const char *	dir
+END
 BEGIN	set_tmp_dir	NOFUNC
 ARG	ID	DB_ENV *	dbenv
 ARG	STRING	const char *	dir
 END
+BEGIN	get_tx_max	NOFUNC
+ARG	ID	DB_ENV *	dbenv
+ARET	INT	u_int32_t	max
+END
 BEGIN	set_tx_max	NOFUNC
 ARG	ID	DB_ENV *	dbenv
 ARG	INT	u_int32_t	max
 END
+BEGIN	get_tx_timestamp	NOFUNC
+ARG	ID	DB_ENV *	dbenv
+ARET	INT	time_t	max
+END
 BEGIN	set_tx_timestamp	NOFUNC
 ARG	ID	DB_ENV *	dbenv
 ARG	INT	time_t *	max
 END
+BEGIN	get_verbose	NOFUNC
+ARG	ID	DB_ENV *	dbenv
+ARG	INT	u_int32_t	which
+ARET	INT	int		onoff
+END
 BEGIN	set_verbose	NOFUNC
 ARG	ID	DB_ENV *	dbenv
 ARG	INT	u_int32_t	which
@@ -263,9 +379,11 @@ END
 BEGIN	rep_elect	NOFUNC
 ARG	ID	DB_ENV *	dbenv
 ARG	INT	int		nsites
+ARG	INT	int		nvotes
 ARG	INT	int		pri
 ARG	INT	u_int32_t	timeout
 ARG	IGNORE	int *		idp
+ARG	INT	u_int32_t	flags
 END
 BEGIN	rep_flush	NOFUNC
 ARG	ID	DB_ENV *	dbenv
@@ -275,6 +393,12 @@ ARG	ID	DB_ENV *	dbenv
 ARG	DBT	DBT *		rec
 ARG	DBT	DBT *		control
 ARG	IGNORE	int *		idp
+ARG	IGNORE	DB_LSN *	ret_lsnp
+END
+BEGIN	rep_get_limit		NOFUNC
+ARG	ID	DB_ENV *	dbenv
+ARET	INT	u_int32_t	mbytes
+ARET	INT	u_int32_t	bytes
 END
 BEGIN	rep_set_limit		NOFUNC
 ARG	ID	DB_ENV *	dbenv
@@ -289,8 +413,8 @@ END
 BEGIN	rep_set_rep_transport	NOFUNC
 ARG	ID	DB_ENV *	dbenv
 ARG	INT	int		id
-FUNCPROT	int (*)(DB_ENV *, const DBT *, const DBT *, int, u_int32_t)
-FUNCARG	int (*func0) __P((DB_ENV *, const DBT *, const DBT *, int, u_int32_t))
+FUNCPROT	int (*)(DB_ENV *, const DBT *, const DBT *, const DB_LSN *, int, u_int32_t)
+FUNCARG	int (*func0) __P((DB_ENV *, const DBT *, const DBT *, const DB_LSN *, int, u_int32_t))
 END
 BEGIN	rep_start	NOFUNC
 ARG	ID	DB_ENV *	dbenv
@@ -332,6 +456,10 @@ BEGIN	db_bt_maxkey	CODE
 ARG	ID	DB *		dbp
 ARG	INT	u_int32_t	maxkey
 END
+BEGIN	db_get_bt_minkey	CODE
+ARG	ID	DB *		dbp
+ARET	INT	u_int32_t	minkey
+END
 BEGIN	db_bt_minkey	CODE
 ARG	ID	DB *		dbp
 ARG	INT	u_int32_t	minkey
@@ -346,9 +474,11 @@ ARG	ID	DB *		dbp
 FUNCPROT	int (*)(DB *, DBT *, db_recno_t)
 FUNCARG	int (*func0) __P((DB *, DBT *, db_recno_t))
 END
-BEGIN	db_cache_priority	NOFUNC
+BEGIN	db_get_cachesize	NOFUNC
 ARG	ID	DB *		dbp
-ARG	INT	DB_CACHE_PRIORITY	priority
+ARET	INT	u_int32_t	gbytes
+ARET	INT	u_int32_t	bytes
+ARET	INT	int		ncache
 END
 BEGIN	db_cachesize	NOFUNC
 ARG	ID	DB *		dbp
@@ -377,11 +507,19 @@ ARG	ID	DB *		dbp
 FUNCPROT	int (*)(DB *, const DBT *, const DBT *)
 FUNCARG	int (*func0) __P((DB *, const DBT *, const DBT *))
 END
+BEGIN	db_get_encrypt_flags		CODE
+ARG	ID	DB *		dbp
+ARET	INT	u_int32_t	flags
+END
 BEGIN	db_encrypt		CODE
 ARG	ID	DB *		dbp
 ARG	STRING	const char *	passwd
 ARG	INT	u_int32_t	flags
 END
+BEGIN	db_get_extentsize	CODE
+ARG	ID	DB *		dbp
+ARET	INT	u_int32_t	extentsize
+END
 BEGIN	db_extentsize	CODE
 ARG	ID	DB *		dbp
 ARG	INT	u_int32_t	extentsize
@@ -395,6 +533,10 @@ ARG	ID	DB *		dbp
 FUNCPROT	void (*)(DB *, int, int)
 FUNCARG	void (*func0) __P((DB *, int, int))
 END
+BEGIN	db_get_flags	CODE
+ARG	ID	DB *		dbp
+ARET	INT	u_int32_t	flags
+END
 BEGIN	db_flags	CODE
 ARG	ID	DB *		dbp
 ARG	INT	u_int32_t	flags
@@ -408,6 +550,19 @@ ARG	INT	u_int32_t	flags
 RET	DBT	DBT *		key
 RET	DBT	DBT *		data
 END
+BEGIN	db_get_name	CODE
+ARG	ID	DB *		dbp
+ARET	STRING	const char *	filename
+ARET	STRING	const char *	dbname
+END
+BEGIN	db_get_open_flags	CODE
+ARG	ID	DB *		dbp
+ARET	INT	u_int32_t	flags
+END
+BEGIN	db_get_h_ffactor	CODE
+ARG	ID	DB *		dbp
+ARET	INT	u_int32_t	ffactor
+END
 BEGIN	db_h_ffactor	CODE
 ARG	ID	DB *		dbp
 ARG	INT	u_int32_t	ffactor
@@ -417,6 +572,10 @@ ARG	ID	DB *		dbp
 FUNCPROT	u_int32_t(*)(DB *, const void *, u_int32_t)
 FUNCARG	u_int32_t (*func0) __P((DB *, const void *, u_int32_t))
 END
+BEGIN	db_get_h_nelem	CODE
+ARG	ID	DB *		dbp
+ARET	INT	u_int32_t	nelem
+END
 BEGIN	db_h_nelem	CODE
 ARG	ID	DB *		dbp
 ARG	INT	u_int32_t	nelem
@@ -431,6 +590,10 @@ RET	DBL	double		less
 RET	DBL	double		equal
 RET	DBL	double		greater
 END
+BEGIN	db_get_lorder	CODE
+ARG	ID	DB *		dbp
+ARET	INT	int		lorder
+END
 BEGIN	db_lorder	CODE
 ARG	ID	DB *		dbp
 ARG	INT	int		lorder
@@ -451,9 +614,12 @@ ARG	INT	u_int32_t	flags
 ARG	INT	int		mode
 RET	ID	long		db
 RET	INT	DBTYPE		type
-RET	INT	u_int32_t	dbflags
 RET	INT	int		lorder
 END
+BEGIN	db_get_pagesize	CODE
+ARG	ID	DB *		dbp
+ARET	INT	u_int32_t	pagesize
+END
 BEGIN	db_pagesize	CODE
 ARG	ID	DB *		dbp
 ARG	INT	u_int32_t	pagesize
@@ -482,10 +648,18 @@ ARG	DBT	DBT *		data
 ARG	INT	u_int32_t	flags
 RET	DBT	DBT *		key
 END
+BEGIN	db_get_re_delim	CODE
+ARG	ID	DB *		dbp
+ARET	INT	int		delim
+END
 BEGIN	db_re_delim	CODE
 ARG	ID	DB *		dbp
 ARG	INT	int		delim
 END
+BEGIN	db_get_re_len	CODE
+ARG	ID	DB *		dbp
+ARET	INT	u_int32_t	len
+END
 BEGIN	db_re_len	CODE
 ARG	ID	DB *		dbp
 ARG	INT	u_int32_t	len
@@ -494,6 +668,14 @@ BEGIN	db_re_pad	CODE
 ARG	ID	DB *		dbp
 ARG	INT	int		pad
 END
+BEGIN	db_get_re_pad	CODE
+ARG	ID	DB *		dbp
+ARET	INT	int		pad
+END
+BEGIN	db_get_re_source	NOFUNC
+ARG	ID	DB *		dbp
+ARET	STRING	const char *	re_source
+END
 BEGIN	db_re_source	NOFUNC
 ARG	ID	DB *		dbp
 ARG	STRING	const char *	re_source
@@ -513,6 +695,7 @@ ARG	INT	u_int32_t	flags
 END
 BEGIN	db_stat		RETCODE
 ARG	ID	DB *		dbp
+ARG	ID	DB_TXN *	txnp
 ARG	IGNORE	void *		sp
 ARG	INT	u_int32_t	flags
 RET	LIST	u_int32_t *	stats	INT
@@ -685,14 +868,10 @@ ARG	ID	DB_ENV *	dbenv
 ARG	IGNORE	DB_LOG_STAT **	statp
 ARG	INT	u_int32_t	flags
 END
+
 #
-# Mpool Subsystem
+# DB_MPOOL methods.
 #
-BEGIN	memp_fcreate	NOFUNC
-ARG	ID	DB_ENV *	dbenv
-ARG	IGNORE	DB_MPOOLFILE **	mpf
-ARG	IGNORE	u_int32_t	flags
-END
 BEGIN	memp_register	NOFUNC
 ARG	ID	DB_ENV *	dbenv
 ARG	INT	int		ftype
@@ -716,3 +895,100 @@ ARG	ID	DB_ENV *	dbenv
 ARG	INT	int		pct
 ARG	IGNORE	int *		nwrotep
 END
+
+#
+# DB_MPOOLFILE methods.
+#
+BEGIN	memp_fget		NOFUNC
+ARG	ID	DB_MPOOLFILE *	dbmfp
+ARG	IGNORE	u_int32_t *	pgnoaddr
+ARG	IGNORE	u_int32_t	flags
+ARG	IGNORE	void *		addrp
+END
+BEGIN	memp_fopen		NOFUNC
+ARG	ID	DB_MPOOLFILE *	dbmfp
+ARG	IGNORE	const char *	path
+ARG	IGNORE	u_int32_t	flags
+ARG	IGNORE	int		mode
+ARG	IGNORE	size_t		pagesize
+END
+BEGIN	memp_fput		NOFUNC
+ARG	ID	DB_MPOOLFILE *	dbmfp
+ARG	IGNORE	void *		pgaddr
+ARG	IGNORE	u_int32_t	flags
+END
+BEGIN	memp_fset		NOFUNC
+ARG	ID	DB_MPOOLFILE *	dbmfp
+ARG	IGNORE	void *		pgaddr
+ARG	IGNORE	u_int32_t	flags
+END
+BEGIN	memp_get_clear_len	NOFUNC
+ARG	ID	DB_MPOOLFILE *	dbmfp
+ARG	IGNORE	u_int32_t *	clear_lenp
+END
+BEGIN	memp_set_clear_len	NOFUNC
+ARG	ID	DB_MPOOLFILE *	dbmfp
+ARG	IGNORE	u_int32_t	clear_len
+END
+BEGIN	memp_get_fileid		NOFUNC
+ARG	ID	DB_MPOOLFILE *	dbmfp
+ARG	IGNORE	u_int8_t *	fileid
+END
+BEGIN	memp_set_fileid		NOFUNC
+ARG	ID	DB_MPOOLFILE *	dbmfp
+ARG	IGNORE	u_int8_t *	fileid
+END
+BEGIN	memp_get_flags		NOFUNC
+ARG	ID	DB_MPOOLFILE *	dbmfp
+ARG	IGNORE	u_int32_t *	flagsp
+END
+BEGIN	memp_set_flags		NOFUNC
+ARG	ID	DB_MPOOLFILE *	dbmfp
+ARG	IGNORE	u_int32_t	flags
+ARG	IGNORE	int		onoff
+END
+BEGIN	memp_get_ftype		NOFUNC
+ARG	ID	DB_MPOOLFILE *	dbmfp
+ARG	IGNORE	int *		ftype
+END
+BEGIN	memp_set_ftype		NOFUNC
+ARG	ID	DB_MPOOLFILE *	dbmfp
+ARG	IGNORE	int		ftype
+END
+BEGIN	memp_get_lsn_offset	NOFUNC
+ARG	ID	DB_MPOOLFILE *	dbmfp
+ARG	IGNORE	int32_t *	lsn_offsetp
+END
+BEGIN	memp_set_lsn_offset	NOFUNC
+ARG	ID	DB_MPOOLFILE *	dbmfp
+ARG	IGNORE	int32_t		lsn_offset
+END
+BEGIN	memp_get_maxsize	NOFUNC
+ARG	ID	DB_MPOOLFILE *	dbmfp
+ARG	IGNORE	u_int32_t *	gbytesp
+ARG	IGNORE	u_int32_t *	bytesp
+END
+BEGIN	memp_set_maxsize	NOFUNC
+ARG	ID	DB_MPOOLFILE *	dbmfp
+ARG	IGNORE	u_int32_t	gbytes
+ARG	IGNORE	u_int32_t	bytes
+END
+BEGIN	memp_get_pgcookie	NOFUNC
+ARG	ID	DB_MPOOLFILE *	dbmfp
+ARG	IGNORE	DBT *		pgcookie
+END
+BEGIN	memp_set_pgcookie	NOFUNC
+ARG	ID	DB_MPOOLFILE *	dbmfp
+ARG	IGNORE	DBT *		pgcookie
+END
+BEGIN	memp_get_priority	NOFUNC
+ARG	ID	DB_MPOOLFILE *	dbmfp
+ARG	IGNORE	DB_CACHE_PRIORITY *	priorityp
+END
+BEGIN	memp_set_priority	NOFUNC
+ARG	ID	DB_MPOOLFILE *	dbmfp
+ARG	IGNORE	DB_CACHE_PRIORITY	priority
+END
+BEGIN	memp_fsync		NOFUNC
+ARG	ID	DB_MPOOLFILE *	dbmfp
+END
diff --git a/storage/bdb/sequence/seq_stat.c b/storage/bdb/sequence/seq_stat.c
new file mode 100644
index 0000000000000000000000000000000000000000..af38c1a553b950a1077d374120e03501f30b59af
--- /dev/null
+++ b/storage/bdb/sequence/seq_stat.c
@@ -0,0 +1,244 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: seq_stat.c,v 1.19 2004/09/28 17:28:15 bostic Exp $
+ */
+
+#include "db_config.h"
+
+#ifdef HAVE_SEQUENCE
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc_auto/sequence_ext.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
+
+#ifdef HAVE_STATISTICS
+static int __seq_print_all __P((DB_SEQUENCE *, u_int32_t));
+static int __seq_print_stats __P((DB_SEQUENCE *, u_int32_t));
+
+/*
+ * __seq_stat --
+ *	Get statistics from the sequence.
+ *
+ * PUBLIC: int __seq_stat __P((DB_SEQUENCE *, DB_SEQUENCE_STAT **, u_int32_t));
+ */
+int
+__seq_stat(seq, spp, flags)
+	DB_SEQUENCE *seq;
+	DB_SEQUENCE_STAT **spp;
+	u_int32_t flags;
+{
+	DB *dbp;
+	DB_ENV *dbenv;
+	DB_SEQ_RECORD record;
+	DB_SEQUENCE_STAT *sp;
+	DBT data;
+	int ret;
+
+	dbp = seq->seq_dbp;
+	dbenv = dbp->dbenv;
+	switch (flags) {
+	case DB_STAT_CLEAR:
+	case DB_STAT_ALL:
+	case 0:
+		break;
+	default:
+		return (__db_ferr(dbenv, "DB_SEQUENCE->stat", 0));
+	}
+
+	/* Allocate and clear the structure. */
+	if ((ret = __os_umalloc(dbenv, sizeof(*sp), &sp)) != 0)
+		return (ret);
+	memset(sp, 0, sizeof(*sp));
+
+	if (seq->seq_mutexp != NULL) {
+		sp->st_wait = seq->seq_mutexp->mutex_set_wait;
+		sp->st_nowait = seq->seq_mutexp->mutex_set_nowait;
+
+		if (LF_ISSET(DB_STAT_CLEAR))
+			MUTEX_CLEAR(seq->seq_mutexp);
+	}
+	memset(&data, 0, sizeof(data));
+	data.data = &record;
+	data.ulen = sizeof(record);
+	data.flags = DB_DBT_USERMEM;
+retry:	if ((ret = dbp->get(dbp, NULL, &seq->seq_key, &data, 0)) != 0) {
+		if (ret == DB_BUFFER_SMALL &&
+		    data.size > sizeof(seq->seq_record)) {
+			if ((ret = __os_malloc(dbenv,
+			    data.size, &data.data)) != 0)
+				return (ret);
+			data.ulen = data.size;
+			goto retry;
+		}
+		return (ret);
+	}
+
+	if (data.data != &record)
+		memcpy(&record, data.data, sizeof(record));
+	sp->st_current = record.seq_value;
+	sp->st_value = seq->seq_record.seq_value;
+	sp->st_last_value = seq->seq_last_value;
+	sp->st_min = seq->seq_record.seq_min;
+	sp->st_max = seq->seq_record.seq_max;
+	sp->st_cache_size = seq->seq_cache_size;
+	sp->st_flags = seq->seq_record.flags;
+
+	*spp = sp;
+	if (data.data != &record)
+		__os_free(dbenv, data.data);
+	return (0);
+}
+
+/*
+ * __seq_stat_print --
+ *	Print statistics from the sequence.
+ *
+ * PUBLIC: int __seq_stat_print __P((DB_SEQUENCE *, u_int32_t));
+ */
+int
+__seq_stat_print(seq, flags)
+	DB_SEQUENCE *seq;
+	u_int32_t flags;
+{
+	int ret;
+
+	if ((ret = __seq_print_stats(seq, flags)) != 0)
+		return (ret);
+
+	if (LF_ISSET(DB_STAT_ALL) &&
+	    (ret = __seq_print_all(seq, flags)) != 0)
+		return (ret);
+
+	return (0);
+
+}
+
+static const FN __db_seq_flags_fn[] = {
+	{ DB_SEQ_DEC,		"decrement" },
+	{ DB_SEQ_INC,		"increment" },
+	{ DB_SEQ_RANGE_SET,	"range set (internal)" },
+	{ DB_SEQ_WRAP,		"wraparound at end" },
+	{ 0,			NULL }
+};
+
+/*
+ * __db_get_seq_flags_fn --
+ *	Return the __db_seq_flags_fn array.
+ *
+ * PUBLIC: const FN * __db_get_seq_flags_fn __P((void));
+ */
+const FN *
+__db_get_seq_flags_fn()
+{
+	return (__db_seq_flags_fn);
+}
+
+/*
+ * __seq_print_stats --
+ *	Display sequence stat structure.
+ */
+static int
+__seq_print_stats(seq, flags)
+	DB_SEQUENCE *seq;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	DB_SEQUENCE_STAT *sp;
+	int ret;
+
+	dbenv = seq->seq_dbp->dbenv;
+
+	if ((ret = __seq_stat(seq, &sp, flags)) != 0)
+		return (ret);
+	__db_dl_pct(dbenv,
+	    "The number of sequence locks that required waiting",
+	    (u_long)sp->st_wait,
+	     DB_PCT(sp->st_wait, sp->st_wait + sp->st_nowait), NULL);
+	STAT_FMT("The current sequence value",
+	     INT64_FMT, int64_t, sp->st_current);
+	STAT_FMT("The cached sequence value",
+	    INT64_FMT, int64_t, sp->st_value);
+	STAT_FMT("The last cached sequence value",
+	    INT64_FMT, int64_t, sp->st_last_value);
+	STAT_FMT("The minimum sequence value",
+	    INT64_FMT, int64_t, sp->st_value);
+	STAT_FMT("The maximum sequence value",
+	    INT64_FMT, int64_t, sp->st_value);
+	STAT_ULONG("The cache size", sp->st_cache_size);
+	__db_prflags(dbenv, NULL,
+	    sp->st_flags, __db_seq_flags_fn, NULL, "\tSequence flags");
+	__os_ufree(seq->seq_dbp->dbenv, sp);
+	return (0);
+}
+
+/*
+ * __seq_print_all --
+ *	Display sequence debugging information - none for now.
+ *	(The name seems a bit strange, no?)
+ */
+static int
+__seq_print_all(seq, flags)
+	DB_SEQUENCE *seq;
+	u_int32_t flags;
+{
+	COMPQUIET(seq, NULL);
+	COMPQUIET(flags, 0);
+	return (0);
+}
+
+#else /* !HAVE_STATISTICS */
+
+int
+__seq_stat(seq, statp, flags)
+	DB_SEQUENCE *seq;
+	DB_SEQUENCE_STAT **statp;
+	u_int32_t flags;
+{
+	COMPQUIET(statp, NULL);
+	COMPQUIET(flags, 0);
+
+	return (__db_stat_not_built(seq->seq_dbp->dbenv));
+}
+
+int
+__seq_stat_print(seq, flags)
+	DB_SEQUENCE *seq;
+	u_int32_t flags;
+{
+	COMPQUIET(flags, 0);
+
+	return (__db_stat_not_built(seq->seq_dbp->dbenv));
+}
+
+/*
+ * __db_get_seq_flags_fn --
+ *	Return the __db_seq_flags_fn array.
+ *
+ * PUBLIC: const FN * __db_get_seq_flags_fn __P((void));
+ */
+const FN *
+__db_get_seq_flags_fn()
+{
+	static const FN __db_seq_flags_fn[] = {
+		{ 0,	NULL }
+	};
+
+	/*
+	 * !!!
+	 * The Tcl API uses this interface, stub it off.
+	 */
+	return (__db_seq_flags_fn);
+}
+#endif /* !HAVE_STATISTICS */
+#endif /* HAVE_SEQUENCE */
diff --git a/storage/bdb/sequence/sequence.c b/storage/bdb/sequence/sequence.c
new file mode 100644
index 0000000000000000000000000000000000000000..26f741951a3d628af90a7d9f463a21d9e30aba14
--- /dev/null
+++ b/storage/bdb/sequence/sequence.c
@@ -0,0 +1,747 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: sequence.c,v 1.26 2004/10/25 17:59:28 bostic Exp $
+ */
+
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_swap.h"
+#include "dbinc/db_am.h"
+#include "dbinc/mp.h"
+#include "dbinc_auto/sequence_ext.h"
+
+#ifdef HAVE_SEQUENCE
+#define	SEQ_ILLEGAL_AFTER_OPEN(seq, name)				\
+	if (seq->seq_key.data != NULL)					\
+		return (__db_mi_open((seq)->seq_dbp->dbenv, name, 1));
+
+#define	SEQ_ILLEGAL_BEFORE_OPEN(seq, name)				\
+	if (seq->seq_key.data == NULL)					\
+		return (__db_mi_open((seq)->seq_dbp->dbenv, name, 0));
+
+#define SEQ_SWAP(rp)	\
+	do {							\
+		M_32_SWAP((rp)->seq_version);			\
+		M_32_SWAP((rp)->flags);				\
+		M_64_SWAP((rp)->seq_value);			\
+		M_64_SWAP((rp)->seq_max);			\
+		M_64_SWAP((rp)->seq_min);			\
+	} while (0)
+
+#define SEQ_SWAP_IN(seq) \
+	do {								\
+		if (__db_isbigendian()) {				\
+			memcpy(&seq->seq_record, seq->seq_data.data,	\
+			     sizeof(seq->seq_record));			\
+			SEQ_SWAP(&seq->seq_record);			\
+		}							\
+	} while (0)
+		
+#define SEQ_SWAP_OUT(seq) \
+	do {								\
+		if (__db_isbigendian()) {				\
+			memcpy(seq->seq_data.data,			\
+			     &seq->seq_record, sizeof(seq->seq_record));\
+			SEQ_SWAP((DB_SEQ_RECORD*)seq->seq_data.data);	\
+		}							\
+	} while (0)
+		
+
+static int __seq_close __P((DB_SEQUENCE *, u_int32_t));
+static int __seq_get __P((DB_SEQUENCE *,
+			    DB_TXN *, int32_t,  db_seq_t *, u_int32_t));
+static int __seq_get_cachesize __P((DB_SEQUENCE *, int32_t *));
+static int __seq_get_flags __P((DB_SEQUENCE *, u_int32_t *));
+static int __seq_get_key __P((DB_SEQUENCE *, DBT *));
+static int __seq_get_range __P((DB_SEQUENCE *, db_seq_t *, db_seq_t *));
+static int __seq_set_range __P((DB_SEQUENCE *, db_seq_t, db_seq_t));
+static int __seq_get_db __P((DB_SEQUENCE *, DB **));
+static int __seq_initial_value __P((DB_SEQUENCE *, db_seq_t));
+static int __seq_open __P((DB_SEQUENCE *, DB_TXN *, DBT *, u_int32_t));
+static int __seq_remove __P((DB_SEQUENCE *, DB_TXN *, u_int32_t));
+static int __seq_set_cachesize __P((DB_SEQUENCE *, int32_t));
+static int __seq_set_flags __P((DB_SEQUENCE *, u_int32_t));
+static int __seq_update __P((DB_SEQUENCE *, DB_TXN *, int32_t, u_int32_t));
+
+/*
+ * db_sequence_create --
+ *	DB_SEQUENCE constructor.
+ *
+ * EXTERN: int db_sequence_create __P((DB_SEQUENCE **, DB *, u_int32_t));
+ */
+int
+db_sequence_create(seqp, dbp, flags)
+	DB_SEQUENCE **seqp;
+	DB *dbp;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	DB_SEQUENCE *seq;
+	int ret;
+
+	dbenv = dbp->dbenv;
+
+	/* Check for invalid function flags. */
+	switch (flags) {
+	case 0:
+		break;
+	default:
+		return (__db_ferr(dbenv, "db_sequence_create", 0));
+	}
+
+	DB_ILLEGAL_BEFORE_OPEN(dbp, "db_sequence_create");
+
+	/* Allocate the sequence. */
+	if ((ret = __os_calloc(dbenv, 1, sizeof(*seq), &seq)) != 0)
+		return (ret);
+
+	seq->seq_dbp = dbp;
+	seq->close = __seq_close;
+	seq->get = __seq_get;
+	seq->get_cachesize = __seq_get_cachesize;
+	seq->set_cachesize = __seq_set_cachesize;
+	seq->get_db = __seq_get_db;
+	seq->get_flags = __seq_get_flags;
+	seq->get_key = __seq_get_key;
+	seq->get_range = __seq_get_range;
+	seq->initial_value = __seq_initial_value;
+	seq->open = __seq_open;
+	seq->remove = __seq_remove;
+	seq->set_flags = __seq_set_flags;
+	seq->set_range = __seq_set_range;
+	seq->stat = __seq_stat;
+	seq->stat_print = __seq_stat_print;
+	seq->seq_rp = &seq->seq_record;
+	*seqp = seq;
+
+	return (0);
+}
+
+/*
+ * __seq_open --
+ *	DB_SEQUENCE->open method.
+ *
+ */
+static int
+__seq_open(seq, txn, keyp, flags)
+	DB_SEQUENCE *seq;
+	DB_TXN *txn;
+	DBT *keyp;
+	u_int32_t flags;
+{
+	DB *dbp;
+	DB_ENV *dbenv;
+	DB_MPOOL *dbmp;
+	DB_SEQ_RECORD *rp;
+	u_int32_t tflags;
+	int txn_local, ret;
+#define	SEQ_OPEN_FLAGS (DB_AUTO_COMMIT | DB_CREATE | DB_EXCL | DB_THREAD)
+
+	dbp = seq->seq_dbp;
+	dbenv = dbp->dbenv;
+	txn_local = 0;
+
+	SEQ_ILLEGAL_AFTER_OPEN(seq, "DB_SEQUENCE->open");
+	if (keyp->size == 0) {
+		__db_err(dbenv, "Zero length sequence key specified");
+		return (EINVAL);
+	}
+
+	if (LF_ISSET(~SEQ_OPEN_FLAGS))
+		return (__db_ferr(dbenv, "DB_SEQUENCE->open", 0));
+
+	if ((ret = dbp->get_flags(dbp, &tflags)) != 0)
+		return (ret);
+
+	if (FLD_ISSET(tflags, DB_DUP)) {
+		__db_err(dbenv,
+	"Sequences not supported in databases configured for duplicate data");
+		return (EINVAL);
+	}
+
+	if (LF_ISSET(DB_THREAD)) {
+		dbmp = dbenv->mp_handle;
+		if ((ret = __db_mutex_setup(dbenv, dbmp->reginfo,
+		     &seq->seq_mutexp, MUTEX_ALLOC | MUTEX_THREAD)) != 0)
+			return (ret);
+	}
+
+	memset(&seq->seq_data, 0, sizeof(DBT));
+	if (__db_isbigendian()) {
+		if ((ret = __os_umalloc(dbenv,
+		     sizeof(seq->seq_record), &seq->seq_data.data)) != 0)
+			goto err;
+		seq->seq_data.flags = DB_DBT_REALLOC;
+	} else {
+		seq->seq_data.data = &seq->seq_record;
+		seq->seq_data.flags = DB_DBT_USERMEM;
+	}
+
+	seq->seq_data.ulen = seq->seq_data.size = sizeof(seq->seq_record);
+	seq->seq_rp = &seq->seq_record;
+
+	memset(&seq->seq_key, 0, sizeof(DBT));
+	if ((ret = __os_malloc(dbenv, keyp->size, &seq->seq_key.data)) != 0)
+		return (ret);
+	memcpy(seq->seq_key.data, keyp->data, keyp->size);
+	seq->seq_key.size = seq->seq_key.ulen = keyp->size;
+	seq->seq_key.flags = DB_DBT_USERMEM;
+
+		
+
+retry:	if ((ret = dbp->get(dbp, txn, &seq->seq_key, &seq->seq_data, 0)) != 0) {
+		if (ret == DB_BUFFER_SMALL &&
+		    seq->seq_data.size > sizeof(seq->seq_record)) {
+			seq->seq_data.flags = DB_DBT_REALLOC;
+			seq->seq_data.data = NULL;
+			goto retry;
+		}
+		if ((ret != DB_NOTFOUND && ret != DB_KEYEMPTY) ||
+		    !LF_ISSET(DB_CREATE))
+			goto err;
+		ret = 0;
+
+		rp = &seq->seq_record;
+		tflags = DB_NOOVERWRITE;
+		tflags |= LF_ISSET(DB_AUTO_COMMIT);
+		if (!F_ISSET(rp, DB_SEQ_RANGE_SET)) {
+			rp->seq_max = INT64_MAX;
+			rp->seq_min = INT64_MIN;
+		}
+		/* INC is the default. */
+		if (!F_ISSET(rp, DB_SEQ_DEC))
+			F_SET(rp, DB_SEQ_INC);
+
+		rp->seq_version = DB_SEQUENCE_VERSION;
+
+		if (rp->seq_value > rp->seq_max ||
+		    rp->seq_value < rp->seq_min) {
+			__db_err(dbenv, "Sequence value out of range");
+			ret = EINVAL;
+			goto err;
+		} else {
+			SEQ_SWAP_OUT(seq);
+			if ((ret = dbp->put(dbp, txn,
+			    &seq->seq_key, &seq->seq_data, tflags)) != 0) {
+				__db_err(dbenv, "Sequence create failed");
+				goto err;
+			}
+		}
+	} else if (LF_ISSET(DB_CREATE) && LF_ISSET(DB_EXCL)) {
+		ret = EEXIST;
+		goto err;
+	} else if (seq->seq_data.size < sizeof(seq->seq_record)) {
+		__db_err(dbenv, "Bad sequence record format");
+		ret = EINVAL;
+		goto err;
+	}
+
+	if (!__db_isbigendian())
+		seq->seq_rp = seq->seq_data.data;
+
+	/*
+	 * The first release was stored in native mode.
+	 * Check the verison number before swapping.
+	 */
+	rp = seq->seq_data.data;
+	if (rp->seq_version == DB_SEQUENCE_OLDVER) {
+oldver:		rp->seq_version = DB_SEQUENCE_VERSION;
+		if (__db_isbigendian()) {
+			if (IS_AUTO_COMMIT(dbp, txn, flags)) {
+				if ((ret =
+				     __db_txn_auto_init(dbenv, &txn)) != 0)
+					return (ret);
+				txn_local = 1;
+				LF_CLR(DB_AUTO_COMMIT);
+				goto retry;
+			} else
+				txn_local = 0;
+			memcpy(&seq->seq_record, rp, sizeof(seq->seq_record));
+			SEQ_SWAP_OUT(seq);
+		}
+		if ((ret = dbp->put(dbp,
+		     txn, &seq->seq_key, &seq->seq_data, 0)) != 0)
+			goto err;
+	}
+	rp = seq->seq_rp;
+
+	SEQ_SWAP_IN(seq);
+
+	if (rp->seq_version != DB_SEQUENCE_VERSION) {
+		/*
+		 * The database may have moved from one type
+		 * of machine to another, check here.
+		 * If we moved from little-end to big-end then
+		 * the swap above will make the version correct.
+		 * If the move was from big to little
+		 * then we need to swap to see if this
+		 * is an old version.
+		 */
+		if (rp->seq_version == DB_SEQUENCE_OLDVER)
+			goto oldver;
+		M_32_SWAP(rp->seq_version);
+		if (rp->seq_version == DB_SEQUENCE_OLDVER) {
+			SEQ_SWAP(rp);
+			goto oldver;
+		}
+		M_32_SWAP(rp->seq_version);
+		__db_err(dbenv,
+		     "Unknown sequence version: %d", rp->seq_version);
+		goto err;
+	}
+
+	seq->seq_last_value = rp->seq_value;
+	if (F_ISSET(rp, DB_SEQ_INC))
+		seq->seq_last_value--;
+	else
+		seq->seq_last_value++;
+
+err:	if (ret != 0) {
+		__os_free(dbenv, seq->seq_key.data);
+		seq->seq_key.data = NULL;
+	}
+	return (txn_local ? __db_txn_auto_resolve(dbenv, txn, 0, ret) : ret);
+}
+
+/*
+ * __seq_get_cachesize --
+ *	Accessor for value passed into DB_SEQUENCE->set_cachesize call.
+ *
+ */
+static int
+__seq_get_cachesize(seq, cachesize)
+	DB_SEQUENCE *seq;
+	int32_t *cachesize;
+{
+	SEQ_ILLEGAL_BEFORE_OPEN(seq, "DB_SEQUENCE->get_cachesize");
+
+	*cachesize = seq->seq_cache_size;
+	return (0);
+}
+
+/*
+ * __seq_set_cachesize --
+ *	DB_SEQUENCE->set_cachesize.
+ *
+ */
+static int
+__seq_set_cachesize(seq, cachesize)
+	DB_SEQUENCE *seq;
+	int32_t cachesize;
+{
+	if (cachesize < 0) {
+		__db_err(seq->seq_dbp->dbenv,
+		     "Illegal cache size: %d", cachesize);
+		return (EINVAL);
+	}
+	seq->seq_cache_size = cachesize;
+	return (0);
+}
+
+#define	SEQ_SET_FLAGS	(DB_SEQ_WRAP | DB_SEQ_INC | DB_SEQ_DEC)
+/*
+ * __seq_get_flags --
+ *	Accessor for flags passed into DB_SEQUENCE->open call
+ *
+ */
+static int
+__seq_get_flags(seq, flagsp)
+	DB_SEQUENCE *seq;
+	u_int32_t *flagsp;
+{
+	SEQ_ILLEGAL_BEFORE_OPEN(seq, "DB_SEQUENCE->get_flags");
+
+	*flagsp = F_ISSET(seq->seq_rp, SEQ_SET_FLAGS);
+	return (0);
+}
+
+/*
+ * __seq_set_flags --
+ *	DB_SEQUENCE->set_flags.
+ *
+ */
+static int
+__seq_set_flags(seq, flags)
+	DB_SEQUENCE *seq;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	DB_SEQ_RECORD *rp;
+	int ret;
+
+	dbenv = seq->seq_dbp->dbenv;
+	rp = seq->seq_rp;
+	SEQ_ILLEGAL_AFTER_OPEN(seq, "DB_SEQUENCE->set_flags");
+
+	if (LF_ISSET(~SEQ_SET_FLAGS))
+		return (__db_ferr(dbenv, "DB_SEQUENCE->set_flags", 0));
+
+	if ((ret = __db_fcchk(dbenv,
+	     "DB_SEQUENCE->set_flags", flags, DB_SEQ_DEC, DB_SEQ_INC)) != 0)
+		return (ret);
+
+	if (LF_ISSET(DB_SEQ_DEC | DB_SEQ_INC))
+		F_CLR(rp, DB_SEQ_DEC | DB_SEQ_INC);
+	F_SET(rp, flags);
+
+	return (0);
+}
+
+/*
+ * __seq_initial_value --
+ *	DB_SEQUENCE->init_value.
+ *
+ */
+static int
+__seq_initial_value(seq, value)
+	DB_SEQUENCE *seq;
+	db_seq_t value;
+{
+	DB_ENV *dbenv;
+	DB_SEQ_RECORD *rp;
+
+	dbenv = seq->seq_dbp->dbenv;
+	SEQ_ILLEGAL_AFTER_OPEN(seq, "DB_SEQUENCE->init_value");
+
+	rp = seq->seq_rp;
+	if (F_ISSET(rp, DB_SEQ_RANGE_SET) &&
+	     (value > rp->seq_max || value < rp->seq_min)) {
+		__db_err(dbenv, "Sequence value out of range");
+		return (EINVAL);
+	}
+
+	rp->seq_value = value;
+
+	return (0);
+}
+
+/*
+ * __seq_get_range --
+ *	Accessor for range passed into DB_SEQUENCE->set_range call
+ *
+ */
+static int
+__seq_get_range(seq, minp, maxp)
+	DB_SEQUENCE *seq;
+	db_seq_t *minp, *maxp;
+{
+	SEQ_ILLEGAL_BEFORE_OPEN(seq, "DB_SEQUENCE->get_range");
+
+	F_SET(seq->seq_rp, DB_SEQ_RANGE_SET);
+	*minp = seq->seq_rp->seq_min;
+	*maxp = seq->seq_rp->seq_max;
+	return (0);
+}
+
+/*
+ * __seq_set_range --
+ *	SEQUENCE->set_range.
+ *
+ */
+static int
+__seq_set_range(seq, min, max)
+	DB_SEQUENCE *seq;
+	db_seq_t min, max;
+{
+	DB_ENV *dbenv;
+
+	dbenv = seq->seq_dbp->dbenv;
+	SEQ_ILLEGAL_AFTER_OPEN(seq, "DB_SEQUENCE->set_range");
+
+	if (min >= max) {
+		__db_err(dbenv, "Illegal sequence range");
+		return (EINVAL);
+	}
+
+	seq->seq_rp->seq_min = min;
+	seq->seq_rp->seq_max = max;
+	F_SET(seq->seq_rp, DB_SEQ_RANGE_SET);
+
+	return (0);
+}
+
+static int
+__seq_update(seq, txn, delta, flags)
+	DB_SEQUENCE *seq;
+	DB_TXN *txn;
+	int32_t delta;
+	u_int32_t flags;
+{
+	DB *dbp;
+	DB_ENV *dbenv;
+	DB_SEQ_RECORD *rp;
+	int32_t adjust;
+	int ret;
+
+	dbp = seq->seq_dbp;
+	dbenv = dbp->dbenv;
+
+	if (LF_ISSET(DB_AUTO_COMMIT) &&
+	    (ret = __db_txn_auto_init(dbenv, &txn)) != 0)
+		return (ret);
+retry:
+	if ((ret = dbp->get(dbp, txn, &seq->seq_key, &seq->seq_data, 0)) != 0) {
+		if (ret == DB_BUFFER_SMALL &&
+		    seq->seq_data.size > sizeof(seq->seq_record)) {
+			seq->seq_data.flags = DB_DBT_REALLOC;
+			seq->seq_data.data = NULL;
+			goto retry;
+		}
+		goto err;
+	}
+
+	if (!__db_isbigendian())
+		seq->seq_rp = seq->seq_data.data;
+	SEQ_SWAP_IN(seq);
+	rp = seq->seq_rp;
+
+	if (seq->seq_data.size < sizeof(seq->seq_record)) {
+		__db_err(dbenv, "Bad sequence record format");
+		ret = EINVAL;
+		goto err;
+	}
+
+	adjust = delta > seq->seq_cache_size ? delta : seq->seq_cache_size;
+
+	/*
+	 * Check whether this operation will cause the sequence to wrap.
+	 *
+	 * The sequence minimum and maximum values can be INT64_MIN and
+	 * INT64_MAX, so we need to do the test carefully to cope with
+	 * arithmetic overflow.  That means we need to check whether the value
+	 * is in a range, we can't get away with a single comparison.
+	 *
+	 * For example, if seq_value == -1 and seq_max == INT64_MAX, the first
+	 * test below will be true, since -1 - (INT64_MAX + 1) == INT64_MAX.
+	 * The second part of the test makes sure that seq_value is close
+	 * enough to the maximum to really cause wrapping.
+	 */
+	if (F_ISSET(rp, DB_SEQ_INC)) {
+		if (rp->seq_value - ((rp->seq_max - adjust) + 2) >= 0 &&
+		    (rp->seq_max + 1) - rp->seq_value >= 0) {
+			if (F_ISSET(rp, DB_SEQ_WRAP))
+				rp->seq_value = rp->seq_min;
+			else {
+overflow:			__db_err(dbenv, "Sequence overflow");
+				ret = EINVAL;
+				goto err;
+			}
+		}
+	} else {
+		if (rp->seq_value - (rp->seq_min - 1) >= 0 &&
+		    (rp->seq_min + adjust - 2) - rp->seq_value >= 0) {
+			if (F_ISSET(rp, DB_SEQ_WRAP))
+				rp->seq_value = rp->seq_max;
+			else
+				goto overflow;
+		}
+		adjust = -adjust;
+	}
+
+	rp->seq_value += adjust;
+	SEQ_SWAP_OUT(seq);
+	ret = dbp->put(dbp, txn, &seq->seq_key, &seq->seq_data, 0);
+	rp->seq_value -= adjust;
+	if (ret != 0) {
+		__db_err(dbenv, "Sequence update failed");
+		goto err;
+	}
+	seq->seq_last_value = rp->seq_value + adjust;
+	if (F_ISSET(rp, DB_SEQ_INC))
+		seq->seq_last_value--;
+	else
+		seq->seq_last_value++;
+
+err:	if (LF_ISSET(DB_AUTO_COMMIT))
+		ret = __db_txn_auto_resolve(dbenv,
+		    txn, LF_ISSET(DB_TXN_NOSYNC), ret);
+	return (ret);
+
+}
+
+static int
+__seq_get(seq, txn, delta, retp, flags)
+	DB_SEQUENCE *seq;
+	DB_TXN *txn;
+	int32_t delta;
+	db_seq_t *retp;
+	u_int32_t flags;
+{
+	DB *dbp;
+	DB_ENV *dbenv;
+	DB_SEQ_RECORD *rp;
+	int ret;
+
+	dbp = seq->seq_dbp;
+	dbenv = dbp->dbenv;
+	rp = seq->seq_rp;
+	ret = 0;
+
+	SEQ_ILLEGAL_BEFORE_OPEN(seq, "DB_SEQUENCE->get");
+
+	if (delta <= 0) {
+		__db_err(dbenv, "Sequence delta must be greater than 0");
+		return (EINVAL);
+	}
+	MUTEX_THREAD_LOCK(dbenv, seq->seq_mutexp);
+
+	if (rp->seq_min + delta > rp->seq_max) {
+		__db_err(dbenv, "Sequence overflow");
+		ret = EINVAL;
+		goto err;
+	}
+
+	if (F_ISSET(rp, DB_SEQ_INC)) {
+		if (seq->seq_last_value + 1 - rp->seq_value < delta &&
+		   (ret = __seq_update(seq, txn, delta, flags)) != 0)
+			goto err;
+
+		rp = seq->seq_rp;
+		*retp = rp->seq_value;
+		rp->seq_value += delta;
+	} else {
+		if ((rp->seq_value - seq->seq_last_value) + 1 < delta &&
+		    (ret = __seq_update(seq, txn, delta, flags)) != 0)
+			goto err;
+
+		rp = seq->seq_rp;
+		*retp = rp->seq_value;
+		rp->seq_value -= delta;
+	}
+
+err:	MUTEX_THREAD_UNLOCK(dbenv, seq->seq_mutexp);
+
+	return (ret);
+}
+
+/*
+ * __seq_get_db --
+ *	Accessor for dbp passed into DB_SEQUENCE->open call
+ *
+ */
+static int
+__seq_get_db(seq, dbpp)
+	DB_SEQUENCE *seq;
+	DB **dbpp;
+{
+	SEQ_ILLEGAL_BEFORE_OPEN(seq, "DB_SEQUENCE->get_db");
+
+	*dbpp = seq->seq_dbp;
+	return (0);
+}
+
+/*
+ * __seq_get_key --
+ *	Accessor for key passed into DB_SEQUENCE->open call
+ *
+ */
+static int
+__seq_get_key(seq, key)
+	DB_SEQUENCE *seq;
+	DBT *key;
+{
+	SEQ_ILLEGAL_BEFORE_OPEN(seq, "DB_SEQUENCE->get_key");
+
+	key->data = seq->seq_key.data;
+	key->size = key->ulen = seq->seq_key.size;
+	key->flags = seq->seq_key.flags;
+	return (0);
+}
+
+/*
+ * __seq_close --
+ *	Close a sequence
+ *
+ */
+static int
+__seq_close(seq, flags)
+	DB_SEQUENCE *seq;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	DB_MPOOL *dbmp;
+	int ret;
+
+	ret = 0;
+	dbenv = seq->seq_dbp->dbenv;
+
+	if (flags != 0)
+		ret = __db_ferr(dbenv, "DB_SEQUENCE->close", 0);
+	if (seq->seq_mutexp != NULL) {
+		dbmp = dbenv->mp_handle;
+		__db_mutex_free(dbenv, dbmp->reginfo, seq->seq_mutexp);
+	}
+	if (seq->seq_key.data != NULL)
+		__os_free(dbenv, seq->seq_key.data);
+	if (seq->seq_data.data != NULL &&
+	    seq->seq_data.data != &seq->seq_record)
+		__os_ufree(dbenv, seq->seq_data.data);
+	seq->seq_key.data = NULL;
+	memset(seq, CLEAR_BYTE, sizeof(*seq));
+	__os_free(dbenv, seq);
+	return (ret);
+}
+
+/*
+ * __seq_remove --
+ *	Remove a sequence from the database.
+ */
+static int
+__seq_remove(seq, txn, flags)
+	DB_SEQUENCE *seq;
+	DB_TXN *txn;
+	u_int32_t flags;
+{
+	DB *dbp;
+	DB_ENV *dbenv;
+	int ret, t_ret;
+
+	dbp = seq->seq_dbp;
+	dbenv = dbp->dbenv;
+
+	SEQ_ILLEGAL_BEFORE_OPEN(seq, "DB_SEQUENCE->remove");
+
+	if (LF_ISSET(DB_AUTO_COMMIT) &&
+	    (ret = __db_txn_auto_init(dbenv, &txn)) != 0)
+		goto err;
+
+	ret = dbp->del(dbp, txn, &seq->seq_key, 0);
+
+	if (LF_ISSET(DB_AUTO_COMMIT))
+		ret = __db_txn_auto_resolve(dbenv,
+		    txn, LF_ISSET(DB_TXN_NOSYNC), ret);
+
+err: if ((t_ret = __seq_close(seq, 0)) != 0 && ret == 0)
+		ret = t_ret;
+	return (ret);
+}
+
+#else /* !HAVE_SEQUENCE */
+
+int
+db_sequence_create(seqp, dbp, flags)
+	DB_SEQUENCE **seqp;
+	DB *dbp;
+	u_int32_t flags;
+{
+	COMPQUIET(seqp, NULL);
+	COMPQUIET(flags, 0);
+	__db_err(dbp->dbenv,
+	    "library build did not include support for sequences");
+	return (DB_OPNOTSUP);
+}
+#endif /* HAVE_SEQUENCE */
diff --git a/storage/bdb/tcl/docs/db.html b/storage/bdb/tcl/docs/db.html
index 4f04c2c4f963d475806be32438f3799cfeb28693..db8382b759fe3fd92c40a66c3222213f7a0f2def 100644
--- a/storage/bdb/tcl/docs/db.html
+++ b/storage/bdb/tcl/docs/db.html
@@ -1,4 +1,4 @@
-<!--Copyright 1999-2002 by Sleepycat Software, Inc.-->
+<!--Copyright 1999-2004 by Sleepycat Software, Inc.-->
 <!--All rights reserved.-->
 <HTML>
 <HEAD>
diff --git a/storage/bdb/tcl/docs/env.html b/storage/bdb/tcl/docs/env.html
index 79c349841ac22ecb14b1dd4f443886063572d19c..3203a02b8d925e5d41aa759c06e8c69381a5ca18 100644
--- a/storage/bdb/tcl/docs/env.html
+++ b/storage/bdb/tcl/docs/env.html
@@ -1,4 +1,4 @@
-<!--Copyright 1999-2002 by Sleepycat Software, Inc.-->
+<!--Copyright 1999-2004 by Sleepycat Software, Inc.-->
 <!--All rights reserved.-->
 <html>
 <head>
@@ -273,10 +273,6 @@ subsystem to control, and indicates whether debug messages should be turned
 or <b>off</b> for that subsystem.&nbsp; The value of <b><i>which</i></b>
 must be one of the following:
 <ul>
-<li>
-<b>chkpt</b> - Chooses the checkpointing code by using the DB_VERB_CHKPOINT
-value</li>
-
 <li>
 <b>deadlock </b>- Chooses the deadlocking code by using the DB_VERB_DEADLOCK
 value</li>
diff --git a/storage/bdb/tcl/docs/historic.html b/storage/bdb/tcl/docs/historic.html
index 85f474fbc0f07a2137270006b10dc2a07c687ec9..f5a43e14de637f9d933bb895c277722f1fff8940 100644
--- a/storage/bdb/tcl/docs/historic.html
+++ b/storage/bdb/tcl/docs/historic.html
@@ -1,4 +1,4 @@
-<!--Copyright 1999-2002 by Sleepycat Software, Inc.-->
+<!--Copyright 1999-2004 by Sleepycat Software, Inc.-->
 <!--All rights reserved.-->
 <HTML>
 <HEAD>
diff --git a/storage/bdb/tcl/docs/index.html b/storage/bdb/tcl/docs/index.html
index 845b6ca81e2f856531b506332a8b5e9eea554167..4f4e1e90c918c286120ea340b0fcb6be5f03b3e7 100644
--- a/storage/bdb/tcl/docs/index.html
+++ b/storage/bdb/tcl/docs/index.html
@@ -1,4 +1,4 @@
-<!--Copyright 1999-2002 by Sleepycat Software, Inc.-->
+<!--Copyright 1999-2004 by Sleepycat Software, Inc.-->
 <!--All rights reserved.-->
 <HTML>
 <HEAD>
diff --git a/storage/bdb/tcl/docs/library.html b/storage/bdb/tcl/docs/library.html
index bfb1588c3f2699727aebee096c67b2abc283f17d..217213ed8c2f24ea648f6153c6b5b1f94b343573 100644
--- a/storage/bdb/tcl/docs/library.html
+++ b/storage/bdb/tcl/docs/library.html
@@ -1,4 +1,4 @@
-<!--Copyright 1999-2002 by Sleepycat Software, Inc.-->
+<!--Copyright 1999-2004 by Sleepycat Software, Inc.-->
 <!--All rights reserved.-->
 <HTML>
 <HEAD>
diff --git a/storage/bdb/tcl/docs/lock.html b/storage/bdb/tcl/docs/lock.html
index d65142b798bcd61827d9da9508fa4ed64feaa8e7..75e0bb2de6d419fddcd223256d4647fe8843a95e 100644
--- a/storage/bdb/tcl/docs/lock.html
+++ b/storage/bdb/tcl/docs/lock.html
@@ -1,4 +1,4 @@
-<!--Copyright 1999-2002 by Sleepycat Software, Inc.-->
+<!--Copyright 1999-2004 by Sleepycat Software, Inc.-->
 <!--All rights reserved.-->
 <html>
 <head>
diff --git a/storage/bdb/tcl/docs/log.html b/storage/bdb/tcl/docs/log.html
index 49f2f0ad2e02923d33948a7b1c7f85fcff24a555..5fdd132d5da20aa1b774081ff7003c03de626586 100644
--- a/storage/bdb/tcl/docs/log.html
+++ b/storage/bdb/tcl/docs/log.html
@@ -1,4 +1,4 @@
-<!--Copyright 1999-2002 by Sleepycat Software, Inc.-->
+<!--Copyright 1999-2004 by Sleepycat Software, Inc.-->
 <!--All rights reserved.-->
 <HTML>
 <HEAD>
diff --git a/storage/bdb/tcl/docs/mpool.html b/storage/bdb/tcl/docs/mpool.html
index 7f2359b36e92d07464f82957d73a192e2544b4eb..83c1f452c3c289bb976c59d8e60bd9c402dfed34 100644
--- a/storage/bdb/tcl/docs/mpool.html
+++ b/storage/bdb/tcl/docs/mpool.html
@@ -1,4 +1,4 @@
-<!--Copyright 1999-2002 by Sleepycat Software, Inc.-->
+<!--Copyright 1999-2004 by Sleepycat Software, Inc.-->
 <!--All rights reserved.-->
 <HTML>
 <HEAD>
diff --git a/storage/bdb/tcl/docs/rep.html b/storage/bdb/tcl/docs/rep.html
index 079fe443a63b2417d9e6868ced94d08503a2fac4..d50b62375e625aabaee0ddbde608acc60127a919 100644
--- a/storage/bdb/tcl/docs/rep.html
+++ b/storage/bdb/tcl/docs/rep.html
@@ -1,4 +1,4 @@
-<!--Copyright 1999-2002 by Sleepycat Software, Inc.-->
+<!--Copyright 1999-2004 by Sleepycat Software, Inc.-->
 <!--All rights reserved.-->
 <html>
 <head>
diff --git a/storage/bdb/tcl/docs/test.html b/storage/bdb/tcl/docs/test.html
index 603ae56a51efd7a75a5205aee108ae21b1f4d005..a011401838ad8be5608996cd9377c6b1feda4f22 100644
--- a/storage/bdb/tcl/docs/test.html
+++ b/storage/bdb/tcl/docs/test.html
@@ -1,4 +1,4 @@
-<!--Copyright 1999-2002 by Sleepycat Software, Inc.-->
+<!--Copyright 1999-2004 by Sleepycat Software, Inc.-->
 <!--All rights reserved.-->
 <HTML>
 <HEAD>
diff --git a/storage/bdb/tcl/docs/txn.html b/storage/bdb/tcl/docs/txn.html
index 07c88c0fe1de7daaf210d442b6aeda3b69395ec4..8abef4b31b2d613934977aee5acb2e6532d2d582 100644
--- a/storage/bdb/tcl/docs/txn.html
+++ b/storage/bdb/tcl/docs/txn.html
@@ -1,4 +1,4 @@
-<!--Copyright 1999-2002 by Sleepycat Software, Inc.-->
+<!--Copyright 1999-2004 by Sleepycat Software, Inc.-->
 <!--All rights reserved.-->
 <html>
 <head>
@@ -25,12 +25,15 @@ It returns either a 0 (for success), a DB error message or it throws a
 Tcl error with a system message.&nbsp; The arguments are:
 <ul>
 <li>
-<b>-kbyte </b>causes the checkpoint to occur only if <b><i>kb</i></b> kilobytes
-of log data has been written since the last checkpoint</li>
+<b>-force</b>causes the checkpoint to occur regardless of inactivity
+
+<li>
+<b>-kbyte</b>causes the checkpoint to occur only if <b><i>kb</i></b> kilobytes
+of log data has been written since the last checkpoint
 
 <li>
 <b>-min</b> causes the checkpoint to occur only if <b><i>min</i></b> minutes
-have passed since the last checkpoint</li>
+have passed since the last checkpoint
 </ul>
 
 <hr WIDTH="100%">
diff --git a/storage/bdb/tcl/tcl_compat.c b/storage/bdb/tcl/tcl_compat.c
index e77bc32aedf18b95bd70bb7f3892bd2b7976a0a4..8b518f761c7a1a2ef94f61cdc0c6e03e646934ad 100644
--- a/storage/bdb/tcl/tcl_compat.c
+++ b/storage/bdb/tcl/tcl_compat.c
@@ -1,17 +1,15 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2001
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: tcl_compat.c,v 11.46 2004/10/07 16:48:39 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: tcl_compat.c,v 11.39 2002/08/15 14:05:38 bostic Exp $";
-#endif /* not lint */
-
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
@@ -39,7 +37,7 @@ bdb_HCommand(interp, objc, objv)
 	int objc;			/* How many arguments? */
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 {
-	static char *hcmds[] = {
+	static const char *hcmds[] = {
 		"hcreate",
 		"hdestroy",
 		"hsearch",
@@ -50,7 +48,7 @@ bdb_HCommand(interp, objc, objv)
 		HHDESTROY,
 		HHSEARCH
 	};
-	static char *srchacts[] = {
+	static const char *srchacts[] = {
 		"enter",
 		"find",
 		NULL
@@ -87,8 +85,9 @@ bdb_HCommand(interp, objc, objv)
 		result = Tcl_GetIntFromObj(interp, objv[2], &nelem);
 		if (result == TCL_OK) {
 			_debug_check();
-			ret = hcreate(nelem) == 0 ? 1: 0;
-			_ReturnSetup(interp, ret, DB_RETOK_STD(ret), "hcreate");
+			ret = hcreate((size_t)nelem) == 0 ? 1: 0;
+			(void)_ReturnSetup(
+			    interp, ret, DB_RETOK_STD(ret), "hcreate");
 		}
 		break;
 	case HHSEARCH:
@@ -133,7 +132,7 @@ bdb_HCommand(interp, objc, objv)
 			return (TCL_ERROR);
 		}
 		_debug_check();
-		(void)hdestroy();
+		hdestroy();
 		res = Tcl_NewIntObj(0);
 		break;
 	}
@@ -162,7 +161,7 @@ bdb_NdbmOpen(interp, objc, objv, dbpp)
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 	DBM **dbpp;			/* Dbm pointer */
 {
-	static char *ndbopen[] = {
+	static const char *ndbopen[] = {
 		"-create",
 		"-mode",
 		"-rdonly",
@@ -178,14 +177,11 @@ bdb_NdbmOpen(interp, objc, objv, dbpp)
 		NDB_ENDARG
 	};
 
-	u_int32_t open_flags;
-	int endarg, i, mode, optindex, read_only, result, ret;
+	int endarg, i, mode, open_flags, optindex, read_only, result, ret;
 	char *arg, *db;
 
 	result = TCL_OK;
-	open_flags = 0;
-	endarg = mode = 0;
-	read_only = 0;
+	endarg = mode = open_flags = read_only = 0;
 
 	if (objc < 2) {
 		Tcl_WrongNumArgs(interp, 2, objv, "?args?");
@@ -237,7 +233,7 @@ bdb_NdbmOpen(interp, objc, objv, dbpp)
 		case NDB_ENDARG:
 			endarg = 1;
 			break;
-		} /* switch */
+		}
 
 		/*
 		 * If, at any time, parsing the args we get an error,
@@ -307,7 +303,7 @@ bdb_DbmCommand(interp, objc, objv, flag, dbm)
 	int flag;			/* Which db interface */
 	DBM *dbm;			/* DBM pointer */
 {
-	static char *dbmcmds[] = {
+	static const char *dbmcmds[] = {
 		"dbmclose",
 		"dbminit",
 		"delete",
@@ -326,7 +322,7 @@ bdb_DbmCommand(interp, objc, objv, flag, dbm)
 		DBMNEXT,
 		DBMSTORE
 	};
-	static char *stflag[] = {
+	static const char *stflag[] = {
 		"insert",	"replace",
 		NULL
 	};
@@ -341,6 +337,8 @@ bdb_DbmCommand(interp, objc, objv, flag, dbm)
 
 	result = TCL_OK;
 	freekey = freedata = 0;
+	dtmp = ktmp = NULL;
+
 	/*
 	 * Get the command name index from the object based on the cmds
 	 * defined above.  This SHOULD NOT fail because we already checked
@@ -367,7 +365,7 @@ bdb_DbmCommand(interp, objc, objv, flag, dbm)
 			    "Bad interface flag for command", TCL_STATIC);
 			return (TCL_ERROR);
 		}
-		_ReturnSetup(interp, ret, DB_RETOK_STD(ret), "dbmclose");
+		(void)_ReturnSetup(interp, ret, DB_RETOK_STD(ret), "dbmclose");
 		break;
 	case DBMINIT:
 		/*
@@ -385,7 +383,7 @@ bdb_DbmCommand(interp, objc, objv, flag, dbm)
 			    TCL_STATIC);
 			return (TCL_ERROR);
 		}
-		_ReturnSetup(interp, ret, DB_RETOK_STD(ret), "dbminit");
+		(void)_ReturnSetup(interp, ret, DB_RETOK_STD(ret), "dbminit");
 		break;
 	case DBMFETCH:
 		/*
@@ -401,7 +399,7 @@ bdb_DbmCommand(interp, objc, objv, flag, dbm)
 			    DB_RETOK_STD(ret), "dbm fetch");
 			goto out;
 		}
-		key.dsize = size;
+		key.dsize = (int)size;
 		key.dptr = (char *)ktmp;
 		_debug_check();
 		if (flag == DBTCL_DBM)
@@ -415,10 +413,10 @@ bdb_DbmCommand(interp, objc, objv, flag, dbm)
 			goto out;
 		}
 		if (data.dptr == NULL ||
-		    (ret = __os_malloc(NULL, data.dsize + 1, &t)) != 0)
+		    (ret = __os_malloc(NULL, (size_t)data.dsize + 1, &t)) != 0)
 			Tcl_SetResult(interp, "-1", TCL_STATIC);
 		else {
-			memcpy(t, data.dptr, data.dsize);
+			memcpy(t, data.dptr, (size_t)data.dsize);
 			t[data.dsize] = '\0';
 			Tcl_SetResult(interp, t, TCL_VOLATILE);
 			__os_free(NULL, t);
@@ -442,7 +440,7 @@ bdb_DbmCommand(interp, objc, objv, flag, dbm)
 			    DB_RETOK_STD(ret), "dbm fetch");
 			goto out;
 		}
-		key.dsize = size;
+		key.dsize = (int)size;
 		key.dptr = (char *)ktmp;
 		if ((ret = _CopyObjBytes(
 		    interp, objv[3], &dtmp, &size, &freedata)) != 0) {
@@ -450,7 +448,7 @@ bdb_DbmCommand(interp, objc, objv, flag, dbm)
 			    DB_RETOK_STD(ret), "dbm fetch");
 			goto out;
 		}
-		data.dsize = size;
+		data.dsize = (int)size;
 		data.dptr = (char *)dtmp;
 		_debug_check();
 		if (flag == DBTCL_DBM)
@@ -473,7 +471,7 @@ bdb_DbmCommand(interp, objc, objv, flag, dbm)
 			    "Bad interface flag for command", TCL_STATIC);
 			return (TCL_ERROR);
 		}
-		_ReturnSetup(interp, ret, DB_RETOK_STD(ret), "store");
+		(void)_ReturnSetup(interp, ret, DB_RETOK_STD(ret), "store");
 		break;
 	case DBMDELETE:
 		/*
@@ -489,7 +487,7 @@ bdb_DbmCommand(interp, objc, objv, flag, dbm)
 			    DB_RETOK_STD(ret), "dbm fetch");
 			goto out;
 		}
-		key.dsize = size;
+		key.dsize = (int)size;
 		key.dptr = (char *)ktmp;
 		_debug_check();
 		if (flag == DBTCL_DBM)
@@ -501,7 +499,7 @@ bdb_DbmCommand(interp, objc, objv, flag, dbm)
 			    "Bad interface flag for command", TCL_STATIC);
 			return (TCL_ERROR);
 		}
-		_ReturnSetup(interp, ret, DB_RETOK_STD(ret), "delete");
+		(void)_ReturnSetup(interp, ret, DB_RETOK_STD(ret), "delete");
 		break;
 	case DBMFIRST:
 		/*
@@ -522,10 +520,10 @@ bdb_DbmCommand(interp, objc, objv, flag, dbm)
 			return (TCL_ERROR);
 		}
 		if (key.dptr == NULL ||
-		    (ret = __os_malloc(NULL, key.dsize + 1, &t)) != 0)
+		    (ret = __os_malloc(NULL, (size_t)key.dsize + 1, &t)) != 0)
 			Tcl_SetResult(interp, "-1", TCL_STATIC);
 		else {
-			memcpy(t, key.dptr, key.dsize);
+			memcpy(t, key.dptr, (size_t)key.dsize);
 			t[key.dsize] = '\0';
 			Tcl_SetResult(interp, t, TCL_VOLATILE);
 			__os_free(NULL, t);
@@ -547,7 +545,7 @@ bdb_DbmCommand(interp, objc, objv, flag, dbm)
 				    DB_RETOK_STD(ret), "dbm fetch");
 				goto out;
 			}
-			key.dsize = size;
+			key.dsize = (int)size;
 			key.dptr = (char *)ktmp;
 			data = nextkey(key);
 		} else if (flag == DBTCL_NDBM) {
@@ -562,21 +560,21 @@ bdb_DbmCommand(interp, objc, objv, flag, dbm)
 			return (TCL_ERROR);
 		}
 		if (data.dptr == NULL ||
-		    (ret = __os_malloc(NULL, data.dsize + 1, &t)) != 0)
+		    (ret = __os_malloc(NULL, (size_t)data.dsize + 1, &t)) != 0)
 			Tcl_SetResult(interp, "-1", TCL_STATIC);
 		else {
-			memcpy(t, data.dptr, data.dsize);
+			memcpy(t, data.dptr, (size_t)data.dsize);
 			t[data.dsize] = '\0';
 			Tcl_SetResult(interp, t, TCL_VOLATILE);
 			__os_free(NULL, t);
 		}
 		break;
 	}
-out:
-	if (freedata)
-		(void)__os_free(NULL, dtmp);
-	if (freekey)
-		(void)__os_free(NULL, ktmp);
+
+out:	if (dtmp != NULL && freedata)
+		__os_free(NULL, dtmp);
+	if (ktmp != NULL && freekey)
+		__os_free(NULL, ktmp);
 	return (result);
 }
 
@@ -593,7 +591,7 @@ ndbm_Cmd(clientData, interp, objc, objv)
 	int objc;			/* How many arguments? */
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 {
-	static char *ndbcmds[] = {
+	static const char *ndbcmds[] = {
 		"clearerr",
 		"close",
 		"delete",
@@ -677,8 +675,8 @@ ndbm_Cmd(clientData, interp, objc, objv)
 		_debug_check();
 		ret = dbm_clearerr(dbp);
 		if (ret)
-			_ReturnSetup(interp, ret, DB_RETOK_STD(ret),
-			    "clearerr");
+			(void)_ReturnSetup(
+			    interp, ret, DB_RETOK_STD(ret), "clearerr");
 		else
 			res = Tcl_NewIntObj(ret);
 		break;
@@ -717,7 +715,8 @@ ndbm_Cmd(clientData, interp, objc, objv)
 		_debug_check();
 		ret = dbm_error(dbp);
 		Tcl_SetErrno(ret);
-		Tcl_SetResult(interp, Tcl_PosixError(interp), TCL_STATIC);
+		Tcl_SetResult(interp,
+		    (char *)Tcl_PosixError(interp), TCL_STATIC);
 		break;
 	case NDBRDONLY:
 		/*
@@ -730,14 +729,16 @@ ndbm_Cmd(clientData, interp, objc, objv)
 		_debug_check();
 		ret = dbm_rdonly(dbp);
 		if (ret)
-			_ReturnSetup(interp, ret, DB_RETOK_STD(ret), "rdonly");
+			(void)_ReturnSetup(
+			    interp, ret, DB_RETOK_STD(ret), "rdonly");
 		else
 			res = Tcl_NewIntObj(ret);
 		break;
 	}
+
 	/*
-	 * Only set result if we have a res.  Otherwise, lower
-	 * functions have already done so.
+	 * Only set result if we have a res.  Otherwise, lower functions have
+	 * already done so.
 	 */
 	if (result == TCL_OK && res)
 		Tcl_SetObjResult(interp, res);
diff --git a/storage/bdb/tcl/tcl_db.c b/storage/bdb/tcl/tcl_db.c
index 7df2e48311cca07786696491ff6d699c466c891f..f60be3f43814530f92063e5fa006b6fb4741e167 100644
--- a/storage/bdb/tcl/tcl_db.c
+++ b/storage/bdb/tcl/tcl_db.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: tcl_db.c,v 11.145 2004/10/07 16:48:39 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: tcl_db.c,v 11.107 2002/08/06 06:20:31 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -33,7 +31,9 @@ static int	tcl_DbClose __P((Tcl_Interp *,
     int, Tcl_Obj * CONST*, DB *, DBTCL_INFO *));
 static int	tcl_DbDelete __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB *));
 static int	tcl_DbGet __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB *, int));
+#ifdef CONFIG_TEST
 static int	tcl_DbKeyRange __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB *));
+#endif
 static int	tcl_DbPut __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB *));
 static int	tcl_DbStat __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB *));
 static int	tcl_DbTruncate __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB *));
@@ -41,6 +41,9 @@ static int	tcl_DbCursor __P((Tcl_Interp *,
     int, Tcl_Obj * CONST*, DB *, DBC **));
 static int	tcl_DbJoin __P((Tcl_Interp *,
     int, Tcl_Obj * CONST*, DB *, DBC **));
+static int	tcl_DbGetFlags __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB *));
+static int	tcl_DbGetOpenFlags __P((Tcl_Interp *,
+    int, Tcl_Obj * CONST*, DB *));
 static int	tcl_DbGetjoin __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB *));
 static int	tcl_DbCount __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB *));
 static int	tcl_second_call __P((DB *, const DBT *, const DBT *, DBT *));
@@ -90,8 +93,8 @@ db_Cmd(clientData, interp, objc, objv)
 	int objc;			/* How many arguments? */
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 {
-	static char *dbcmds[] = {
-#if CONFIG_TEST
+	static const char *dbcmds[] = {
+#ifdef CONFIG_TEST
 		"keyrange",
 		"pget",
 		"rpcid",
@@ -103,7 +106,24 @@ db_Cmd(clientData, interp, objc, objv)
 		"cursor",
 		"del",
 		"get",
+		"get_bt_minkey",
+		"get_cachesize",
+		"get_dbname",
+		"get_encrypt_flags",
+		"get_env",
+		"get_errpfx",
+		"get_flags",
+		"get_h_ffactor",
+		"get_h_nelem",
 		"get_join",
+		"get_lorder",
+		"get_open_flags",
+		"get_pagesize",
+		"get_q_extentsize",
+		"get_re_delim",
+		"get_re_len",
+		"get_re_pad",
+		"get_re_source",
 		"get_type",
 		"is_byteswapped",
 		"join",
@@ -114,7 +134,7 @@ db_Cmd(clientData, interp, objc, objv)
 		NULL
 	};
 	enum dbcmds {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 		DBKEYRANGE,
 		DBPGET,
 		DBRPCID,
@@ -126,7 +146,24 @@ db_Cmd(clientData, interp, objc, objv)
 		DBCURSOR,
 		DBDELETE,
 		DBGET,
+		DBGETBTMINKEY,
+		DBGETCACHESIZE,
+		DBGETDBNAME,
+		DBGETENCRYPTFLAGS,
+		DBGETENV,
+		DBGETERRPFX,
+		DBGETFLAGS,
+		DBGETHFFACTOR,
+		DBGETHNELEM,
 		DBGETJOIN,
+		DBGETLORDER,
+		DBGETOPENFLAGS,
+		DBGETPAGESIZE,
+		DBGETQEXTENTSIZE,
+		DBGETREDELIM,
+		DBGETRELEN,
+		DBGETREPAD,
+		DBGETRESOURCE,
 		DBGETTYPE,
 		DBSWAPPED,
 		DBJOIN,
@@ -136,13 +173,15 @@ db_Cmd(clientData, interp, objc, objv)
 		DBTRUNCATE
 	};
 	DB *dbp;
+	DB_ENV *dbenv;
 	DBC *dbc;
-	DBTCL_INFO *dbip;
-	DBTCL_INFO *ip;
+	DBTCL_INFO *dbip, *ip;
 	DBTYPE type;
-	Tcl_Obj *res;
-	int cmdindex, isswapped, result, ret;
+	Tcl_Obj *res, *myobjv[3];
+	int cmdindex, intval, ncache, result, ret;
 	char newname[MSG_SIZE];
+	u_int32_t bytes, gbytes, value;
+	const char *strval, *filename, *dbname, *envid;
 
 	Tcl_ResetResult(interp);
 	dbp = (DB *)clientData;
@@ -172,7 +211,7 @@ db_Cmd(clientData, interp, objc, objv)
 
 	res = NULL;
 	switch ((enum dbcmds)cmdindex) {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 	case DBKEYRANGE:
 		result = tcl_DbKeyRange(interp, objc, objv, dbp);
 		break;
@@ -191,7 +230,7 @@ db_Cmd(clientData, interp, objc, objv)
 		 * !!! Retrieve the client ID from the dbp handle directly.
 		 * This is for testing purposes only.  It is dbp-private data.
 		 */
-		res = Tcl_NewLongObj(dbp->cl_id);
+		res = Tcl_NewLongObj((long)dbp->cl_id);
 		break;
 	case DBTEST:
 		result = tcl_EnvTest(interp, objc, objv, dbp->dbenv);
@@ -224,8 +263,8 @@ db_Cmd(clientData, interp, objc, objv)
 			return (TCL_ERROR);
 		}
 		_debug_check();
-		ret = dbp->get_byteswapped(dbp, &isswapped);
-		res = Tcl_NewIntObj(isswapped);
+		ret = dbp->get_byteswapped(dbp, &intval);
+		res = Tcl_NewIntObj(intval);
 		break;
 	case DBGETTYPE:
 		/*
@@ -238,13 +277,13 @@ db_Cmd(clientData, interp, objc, objv)
 		_debug_check();
 		ret = dbp->get_type(dbp, &type);
 		if (type == DB_BTREE)
-			res = Tcl_NewStringObj("btree", strlen("btree"));
+			res = NewStringObj("btree", strlen("btree"));
 		else if (type == DB_HASH)
-			res = Tcl_NewStringObj("hash", strlen("hash"));
+			res = NewStringObj("hash", strlen("hash"));
 		else if (type == DB_RECNO)
-			res = Tcl_NewStringObj("recno", strlen("recno"));
+			res = NewStringObj("recno", strlen("recno"));
 		else if (type == DB_QUEUE)
-			res = Tcl_NewStringObj("queue", strlen("queue"));
+			res = NewStringObj("queue", strlen("queue"));
 		else {
 			Tcl_SetResult(interp,
 			    "db gettype: Returned unknown type\n", TCL_STATIC);
@@ -279,11 +318,10 @@ db_Cmd(clientData, interp, objc, objv)
 			if (result == TCL_OK) {
 				dbip->i_dbdbcid++;
 				ip->i_parent = dbip;
-				Tcl_CreateObjCommand(interp, newname,
+				(void)Tcl_CreateObjCommand(interp, newname,
 				    (Tcl_ObjCmdProc *)dbc_Cmd,
 				    (ClientData)dbc, NULL);
-				res =
-				    Tcl_NewStringObj(newname, strlen(newname));
+				res = NewStringObj(newname, strlen(newname));
 				_SetInfoData(ip, dbc);
 			} else
 				_DeleteInfo(ip);
@@ -302,11 +340,10 @@ db_Cmd(clientData, interp, objc, objv)
 			if (result == TCL_OK) {
 				dbip->i_dbdbcid++;
 				ip->i_parent = dbip;
-				Tcl_CreateObjCommand(interp, newname,
+				(void)Tcl_CreateObjCommand(interp, newname,
 				    (Tcl_ObjCmdProc *)dbc_Cmd,
 				    (ClientData)dbc, NULL);
-				res =
-				    Tcl_NewStringObj(newname, strlen(newname));
+				res = NewStringObj(newname, strlen(newname));
 				_SetInfoData(ip, dbc);
 			} else
 				_DeleteInfo(ip);
@@ -316,9 +353,167 @@ db_Cmd(clientData, interp, objc, objv)
 			result = TCL_ERROR;
 		}
 		break;
+	case DBGETBTMINKEY:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbp->get_bt_minkey(dbp, &value);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "db get_bt_minkey")) == TCL_OK)
+			res = Tcl_NewIntObj((int)value);
+		break;
+	case DBGETCACHESIZE:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbp->get_cachesize(dbp, &gbytes, &bytes, &ncache);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "db get_cachesize")) == TCL_OK) {
+			myobjv[0] = Tcl_NewIntObj((int)gbytes);
+			myobjv[1] = Tcl_NewIntObj((int)bytes);
+			myobjv[2] = Tcl_NewIntObj((int)ncache);
+			res = Tcl_NewListObj(3, myobjv);
+		}
+		break;
+	case DBGETDBNAME:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbp->get_dbname(dbp, &filename, &dbname);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "db get_dbname")) == TCL_OK) {
+			myobjv[0] = NewStringObj(filename, strlen(filename));
+			myobjv[1] = NewStringObj(dbname, strlen(dbname));
+			res = Tcl_NewListObj(2, myobjv);
+		}
+		break;
+	case DBGETENCRYPTFLAGS:
+		result = tcl_EnvGetEncryptFlags(interp, objc, objv, dbp->dbenv);
+		break;
+	case DBGETENV:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		dbenv = dbp->get_env(dbp);
+		if (dbenv != NULL && (ip = _PtrToInfo(dbenv)) != NULL) {
+			envid = ip->i_name;
+			res = NewStringObj(envid, strlen(envid));
+		} else
+			Tcl_ResetResult(interp);
+		break;
+	case DBGETERRPFX:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		dbp->get_errpfx(dbp, &strval);
+		res = NewStringObj(strval, strlen(strval));
+		break;
+	case DBGETFLAGS:
+		result = tcl_DbGetFlags(interp, objc, objv, dbp);
+		break;
+	case DBGETHFFACTOR:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbp->get_h_ffactor(dbp, &value);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "db get_h_ffactor")) == TCL_OK)
+			res = Tcl_NewIntObj((int)value);
+		break;
+	case DBGETHNELEM:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbp->get_h_nelem(dbp, &value);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "db get_h_nelem")) == TCL_OK)
+			res = Tcl_NewIntObj((int)value);
+		break;
 	case DBGETJOIN:
 		result = tcl_DbGetjoin(interp, objc, objv, dbp);
 		break;
+	case DBGETLORDER:
+		/*
+		 * No args for this.  Error if there are some.
+		 */
+		if (objc > 2) {
+			Tcl_WrongNumArgs(interp, 2, objv, NULL);
+			return (TCL_ERROR);
+		}
+		_debug_check();
+		ret = dbp->get_lorder(dbp, &intval);
+		res = Tcl_NewIntObj(intval);
+		break;
+	case DBGETOPENFLAGS:
+		result = tcl_DbGetOpenFlags(interp, objc, objv, dbp);
+		break;
+	case DBGETPAGESIZE:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbp->get_pagesize(dbp, &value);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "db get_pagesize")) == TCL_OK)
+			res = Tcl_NewIntObj((int)value);
+		break;
+	case DBGETQEXTENTSIZE:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbp->get_q_extentsize(dbp, &value);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "db get_q_extentsize")) == TCL_OK)
+			res = Tcl_NewIntObj((int)value);
+		break;
+	case DBGETREDELIM:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbp->get_re_delim(dbp, &intval);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "db get_re_delim")) == TCL_OK)
+			res = Tcl_NewIntObj(intval);
+		break;
+	case DBGETRELEN:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbp->get_re_len(dbp, &value);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "db get_re_len")) == TCL_OK)
+			res = Tcl_NewIntObj((int)value);
+		break;
+	case DBGETREPAD:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbp->get_re_pad(dbp, &intval);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "db get_re_pad")) == TCL_OK)
+			res = Tcl_NewIntObj((int)intval);
+		break;
+	case DBGETRESOURCE:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbp->get_re_source(dbp, &strval);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "db get_re_source")) == TCL_OK)
+			res = NewStringObj(strval, strlen(strval));
+		break;
 	case DBTRUNCATE:
 		result = tcl_DbTruncate(interp, objc, objv, dbp);
 		break;
@@ -342,37 +537,82 @@ tcl_DbStat(interp, objc, objv, dbp)
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 	DB *dbp;			/* Database pointer */
 {
+	static const char *dbstatopts[] = {
+#ifdef CONFIG_TEST
+		"-degree_2",
+		"-dirty",
+#endif
+		"-faststat",
+		"-txn",
+		NULL
+	};
+	enum dbstatopts {
+#ifdef CONFIG_TEST
+		DBCUR_DEGREE2,
+		DBCUR_DIRTY,
+#endif
+		DBCUR_FASTSTAT,
+		DBCUR_TXN
+	};
+	DBTYPE type;
 	DB_BTREE_STAT *bsp;
 	DB_HASH_STAT *hsp;
 	DB_QUEUE_STAT *qsp;
-	void *sp;
+	DB_TXN *txn;
 	Tcl_Obj *res, *flaglist, *myobjv[2];
-	DBTYPE type;
 	u_int32_t flag;
-	int result, ret;
-	char *arg;
+	int i, optindex, result, ret;
+	char *arg, msg[MSG_SIZE];
+	void *sp;
 
 	result = TCL_OK;
 	flag = 0;
-
-	if (objc > 3) {
-		Tcl_WrongNumArgs(interp, 2, objv, "?-faststat?");
-		return (TCL_ERROR);
-	}
-
-	if (objc == 3) {
-		arg = Tcl_GetStringFromObj(objv[2], NULL);
-		if (strcmp(arg, "-faststat") == 0)
-			flag = DB_FAST_STAT;
-		else {
-			Tcl_SetResult(interp,
-			    "db stat: unknown arg", TCL_STATIC);
-			return (TCL_ERROR);
+	txn = NULL;
+	sp = NULL;
+	i = 2;
+	while (i < objc) {
+		if (Tcl_GetIndexFromObj(interp, objv[i], dbstatopts, "option",
+		    TCL_EXACT, &optindex) != TCL_OK) {
+			result = IS_HELP(objv[i]);
+			goto error;
 		}
+		i++;
+		switch ((enum dbstatopts)optindex) {
+#ifdef CONFIG_TEST
+		case DBCUR_DEGREE2:
+			flag |= DB_DEGREE_2;
+			break;
+		case DBCUR_DIRTY:
+			flag |= DB_DIRTY_READ;
+			break;
+#endif
+		case DBCUR_FASTSTAT:
+			flag |= DB_FAST_STAT;
+			break;
+		case DBCUR_TXN:
+			if (i == objc) {
+				Tcl_WrongNumArgs(interp, 2, objv, "?-txn id?");
+				result = TCL_ERROR;
+				break;
+			}
+			arg = Tcl_GetStringFromObj(objv[i++], NULL);
+			txn = NAME_TO_TXN(arg);
+			if (txn == NULL) {
+				snprintf(msg, MSG_SIZE,
+				    "Stat: Invalid txn: %s\n", arg);
+				Tcl_SetResult(interp, msg, TCL_VOLATILE);
+				result = TCL_ERROR;
+			}
+			break;
+		}
+		if (result != TCL_OK)
+			break;
 	}
+	if (result != TCL_OK)
+		goto error;
 
 	_debug_check();
-	ret = dbp->stat(dbp, &sp, flag);
+	ret = dbp->stat(dbp, txn, &sp, flag);
 	result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "db stat");
 	if (result == TCL_ERROR)
 		return (result);
@@ -441,6 +681,7 @@ tcl_DbStat(interp, objc, objv, dbp)
 			MAKE_STAT_LIST("Leaf pages", bsp->bt_leaf_pg);
 			MAKE_STAT_LIST("Duplicate pages", bsp->bt_dup_pg);
 			MAKE_STAT_LIST("Overflow pages", bsp->bt_over_pg);
+			MAKE_STAT_LIST("Empty pages", bsp->bt_empty_pg);
 			MAKE_STAT_LIST("Pages on freelist", bsp->bt_free);
 			MAKE_STAT_LIST("Internal pages bytes free",
 			    bsp->bt_int_pgfree);
@@ -459,8 +700,8 @@ tcl_DbStat(interp, objc, objv, dbp)
 	 * include all the interesting flags, and the integer value
 	 * isn't useful from Tcl--return the strings instead.
 	 */
-	myobjv[0] = Tcl_NewStringObj("Flags", strlen("Flags"));
-	myobjv[1] = _GetFlagsList(interp, dbp->flags, __db_inmemdbflags);
+	myobjv[0] = NewStringObj("Flags", strlen("Flags"));
+	myobjv[1] = _GetFlagsList(interp, dbp->flags, __db_get_flags_fn());
 	flaglist = Tcl_NewListObj(2, myobjv);
 	if (flaglist == NULL) {
 		result = TCL_ERROR;
@@ -472,7 +713,8 @@ tcl_DbStat(interp, objc, objv, dbp)
 
 	Tcl_SetObjResult(interp, res);
 error:
-	free(sp);
+	if (sp != NULL)
+		__os_ufree(dbp->dbenv, sp);
 	return (result);
 }
 
@@ -487,7 +729,7 @@ tcl_DbClose(interp, objc, objv, dbp, dbip)
 	DB *dbp;			/* Database pointer */
 	DBTCL_INFO *dbip;		/* Info pointer */
 {
-	static char *dbclose[] = {
+	static const char *dbclose[] = {
 		"-nosync", "--", NULL
 	};
 	enum dbclose {
@@ -506,8 +748,7 @@ tcl_DbClose(interp, objc, objv, dbp, dbip)
 		return (TCL_ERROR);
 	}
 
-	i = 2;
-	while (i < objc) {
+	for (i = 2; i < objc; ++i) {
 		if (Tcl_GetIndexFromObj(interp, objv[i], dbclose,
 		    "option", TCL_EXACT, &optindex) != TCL_OK) {
 			arg = Tcl_GetStringFromObj(objv[i], NULL);
@@ -517,7 +758,6 @@ tcl_DbClose(interp, objc, objv, dbp, dbip)
 				Tcl_ResetResult(interp);
 			break;
 		}
-		i++;
 		switch ((enum dbclose)optindex) {
 		case TCL_DBCLOSE_NOSYNC:
 			flag = DB_NOSYNC;
@@ -556,8 +796,8 @@ tcl_DbPut(interp, objc, objv, dbp)
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 	DB *dbp;			/* Database pointer */
 {
-	static char *dbputopts[] = {
-#if CONFIG_TEST
+	static const char *dbputopts[] = {
+#ifdef CONFIG_TEST
 		"-nodupdata",
 #endif
 		"-append",
@@ -568,7 +808,7 @@ tcl_DbPut(interp, objc, objv, dbp)
 		NULL
 	};
 	enum dbputopts {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 		DBGET_NODUPDATA,
 #endif
 		DBPUT_APPEND,
@@ -577,7 +817,7 @@ tcl_DbPut(interp, objc, objv, dbp)
 		DBPUT_PART,
 		DBPUT_TXN
 	};
-	static char *dbputapp[] = {
+	static const char *dbputapp[] = {
 		"-append",	NULL
 	};
 	enum dbputapp { DBPUT_APPEND0 };
@@ -600,6 +840,7 @@ tcl_DbPut(interp, objc, objv, dbp)
 		return (TCL_ERROR);
 	}
 
+	dtmp = ktmp = NULL;
 	freekey = freedata = 0;
 	memset(&key, 0, sizeof(key));
 	memset(&data, 0, sizeof(data));
@@ -647,7 +888,7 @@ tcl_DbPut(interp, objc, objv, dbp)
 			return (IS_HELP(objv[i]));
 		i++;
 		switch ((enum dbputopts)optindex) {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 		case DBGET_NODUPDATA:
 			FLAG_CHECK(flag);
 			flag = DB_NODUPDATA;
@@ -714,8 +955,6 @@ tcl_DbPut(interp, objc, objv, dbp)
 		if (result != TCL_OK)
 			break;
 	}
-	if (auto_commit)
-		flag |= DB_AUTO_COMMIT;
 
 	if (result == TCL_ERROR)
 		return (result);
@@ -736,6 +975,8 @@ tcl_DbPut(interp, objc, objv, dbp)
 				return (result);
 		}
 	} else {
+		COMPQUIET(recno, 0);
+
 		ret = _CopyObjBytes(interp, objv[objc-2], &ktmp,
 		    &key.size, &freekey);
 		if (ret != 0) {
@@ -745,8 +986,9 @@ tcl_DbPut(interp, objc, objv, dbp)
 		}
 		key.data = ktmp;
 	}
-	ret = _CopyObjBytes(interp, objv[objc-1], &dtmp,
-	    &data.size, &freedata);
+	if (auto_commit)
+		flag |= DB_AUTO_COMMIT;
+	ret = _CopyObjBytes(interp, objv[objc-1], &dtmp, &data.size, &freedata);
 	if (ret != 0) {
 		result = _ReturnSetup(interp, ret,
 		    DB_RETOK_DBPUT(ret), "db put");
@@ -756,16 +998,18 @@ tcl_DbPut(interp, objc, objv, dbp)
 	_debug_check();
 	ret = dbp->put(dbp, txn, &key, &data, flag);
 	result = _ReturnSetup(interp, ret, DB_RETOK_DBPUT(ret), "db put");
+
+	/* We may have a returned record number. */
 	if (ret == 0 &&
-	    (type == DB_RECNO || type == DB_QUEUE) && flag == DB_APPEND) {
-		res = Tcl_NewLongObj((long)recno);
+	    (type == DB_QUEUE || type == DB_RECNO) && flag == DB_APPEND) {
+		res = Tcl_NewWideIntObj((Tcl_WideInt)recno);
 		Tcl_SetObjResult(interp, res);
 	}
-out:
-	if (freedata)
-		(void)__os_free(dbp->dbenv, dtmp);
-	if (freekey)
-		(void)__os_free(dbp->dbenv, ktmp);
+
+out:	if (dtmp != NULL && freedata)
+		__os_free(dbp->dbenv, dtmp);
+	if (ktmp != NULL && freekey)
+		__os_free(dbp->dbenv, ktmp);
 	return (result);
 }
 
@@ -780,11 +1024,13 @@ tcl_DbGet(interp, objc, objv, dbp, ispget)
 	DB *dbp;			/* Database pointer */
 	int ispget;			/* 1 for pget, 0 for get */
 {
-	static char *dbgetopts[] = {
-#if CONFIG_TEST
+	static const char *dbgetopts[] = {
+#ifdef CONFIG_TEST
+		"-degree2",
 		"-dirty",
 		"-multi",
 #endif
+		"-auto_commit",
 		"-consume",
 		"-consume_wait",
 		"-get_both",
@@ -797,10 +1043,12 @@ tcl_DbGet(interp, objc, objv, dbp, ispget)
 		NULL
 	};
 	enum dbgetopts {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
+		DBGET_DEGREE2,
 		DBGET_DIRTY,
 		DBGET_MULTI,
 #endif
+		DBGET_AUTO_COMMIT,
 		DBGET_CONSUME,
 		DBGET_CONSUME_WAIT,
 		DBGET_BOTH,
@@ -813,22 +1061,29 @@ tcl_DbGet(interp, objc, objv, dbp, ispget)
 	};
 	DBC *dbc;
 	DBT key, pkey, data, save;
-	DBTYPE type;
+	DBTYPE ptype, type;
 	DB_TXN *txn;
 	Tcl_Obj **elemv, *retlist;
-	void *dtmp, *ktmp;
-	u_int32_t flag, cflag, isdup, mflag, rmw;
-	int bufsize, elemc, end, endarg, freekey, freedata, i;
+	db_recno_t precno, recno;
+	u_int32_t aflag, flag, cflag, isdup, mflag, rmw;
+	int elemc, end, endarg, freekey, freedata, i;
 	int optindex, result, ret, useglob, useprecno, userecno;
 	char *arg, *pattern, *prefix, msg[MSG_SIZE];
-	db_recno_t precno, recno;
+	void *dtmp, *ktmp;
+#ifdef CONFIG_TEST
+	int bufsize;
+#endif
 
 	result = TCL_OK;
 	freekey = freedata = 0;
-	cflag = endarg = flag = mflag = rmw = 0;
-	useglob = userecno = useprecno = 0;
+	aflag = cflag = endarg = flag = mflag = rmw = 0;
+	useglob = userecno = 0;
 	txn = NULL;
 	pattern = prefix = NULL;
+	dtmp = ktmp = NULL;
+#ifdef CONFIG_TEST
+	COMPQUIET(bufsize, 0);
+#endif
 
 	if (objc < 3) {
 		Tcl_WrongNumArgs(interp, 2, objv, "?-args? key");
@@ -862,10 +1117,13 @@ tcl_DbGet(interp, objc, objv, dbp, ispget)
 		}
 		i++;
 		switch ((enum dbgetopts)optindex) {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 		case DBGET_DIRTY:
 			rmw |= DB_DIRTY_READ;
 			break;
+		case DBGET_DEGREE2:
+			rmw |= DB_DEGREE_2;
+			break;
 		case DBGET_MULTI:
 			mflag |= DB_MULTIPLE;
 			result = Tcl_GetIntFromObj(interp, objv[i], &bufsize);
@@ -874,6 +1132,9 @@ tcl_DbGet(interp, objc, objv, dbp, ispget)
 			i++;
 			break;
 #endif
+		case DBGET_AUTO_COMMIT:
+			aflag |= DB_AUTO_COMMIT;
+			break;
 		case DBGET_BOTH:
 			/*
 			 * Change 'end' and make sure we aren't already past
@@ -922,6 +1183,7 @@ tcl_DbGet(interp, objc, objv, dbp, ispget)
 			if (type != DB_RECNO && type != DB_QUEUE) {
 				FLAG_CHECK(flag);
 				flag = DB_SET_RECNO;
+				key.flags |= DB_DBT_MALLOC;
 			}
 			break;
 		case DBGET_RMW:
@@ -962,7 +1224,7 @@ tcl_DbGet(interp, objc, objv, dbp, ispget)
 		case DBGET_ENDARG:
 			endarg = 1;
 			break;
-		} /* switch */
+		}
 		if (result != TCL_OK)
 			break;
 		if (endarg)
@@ -995,17 +1257,13 @@ tcl_DbGet(interp, objc, objv, dbp, ispget)
 	}
 
 	/*
-	 * XXX
-	 * We technically shouldn't be looking inside the dbp like this,
-	 * but this is the only way to figure out whether the primary
-	 * key should also be a recno.
+	 * Find out whether the primary key should also be a recno.
 	 */
-	if (ispget) {
-		if (dbp->s_primary != NULL &&
-		    (dbp->s_primary->type == DB_RECNO ||
-		    dbp->s_primary->type == DB_QUEUE))
-			useprecno = 1;
-	}
+	if (ispget && dbp->s_primary != NULL) {
+		(void)dbp->s_primary->get_type(dbp->s_primary, &ptype);
+		useprecno = ptype == DB_RECNO || ptype == DB_QUEUE;
+	} else
+		useprecno = 0;
 
 	/*
 	 * Check for illegal combos of options.
@@ -1038,13 +1296,12 @@ tcl_DbGet(interp, objc, objv, dbp, ispget)
 	/*
 	 * isdup is used to know if we support duplicates.  If not, we
 	 * can just do a db->get call and avoid using cursors.
-	 * XXX
-	 * When there is a db->get_flags method, it should be used.
-	 * isdup = dbp->get_flags(dbp) & DB_DUP;
-	 * For now we illegally peek.
-	 * XXX
 	 */
-	isdup = dbp->flags & DB_AM_DUP;
+	if ((ret = dbp->get_flags(dbp, &isdup)) != 0) {
+		result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "db get");
+		goto out;
+	}
+	isdup &= DB_DUP;
 
 	/*
 	 * If the database doesn't support duplicates or we're performing
@@ -1129,17 +1386,19 @@ tcl_DbGet(interp, objc, objv, dbp, ispget)
 				}
 				key.data = ktmp;
 			}
+#ifdef CONFIG_TEST
 			if (mflag & DB_MULTIPLE) {
 				if ((ret = __os_malloc(dbp->dbenv,
-				    bufsize, &save.data)) != 0) {
+				    (size_t)bufsize, &save.data)) != 0) {
 					Tcl_SetResult(interp,
 					    db_strerror(ret), TCL_STATIC);
 					goto out;
 				}
-				save.ulen = bufsize;
+				save.ulen = (u_int32_t)bufsize;
 				F_CLR(&save, DB_DBT_MALLOC);
 				F_SET(&save, DB_DBT_USERMEM);
 			}
+#endif
 		}
 
 		data = save;
@@ -1158,7 +1417,7 @@ tcl_DbGet(interp, objc, objv, dbp, ispget)
 		} else {
 			_debug_check();
 			ret = dbp->get(dbp,
-			    txn, &key, &data, flag | rmw | mflag);
+			    txn, &key, &data, flag | aflag | rmw | mflag);
 		}
 		result = _ReturnSetup(interp, ret, DB_RETOK_DBGET(ret),
 		    "db get");
@@ -1194,16 +1453,21 @@ tcl_DbGet(interp, objc, objv, dbp, ispget)
 		/*
 		 * Free space from DBT.
 		 *
-		 * If we set DB_DBT_MALLOC, we need to free the space if
-		 * and only if we succeeded (and thus if DB allocated
-		 * anything).  If DB_DBT_MALLOC is not set, this is a bulk
-		 * get buffer, and needs to be freed no matter what.
+		 * If we set DB_DBT_MALLOC, we need to free the space if and
+		 * only if we succeeded and if DB allocated anything (the
+		 * pointer has changed from what we passed in).  If
+		 * DB_DBT_MALLOC is not set, this is a bulk get buffer, and
+		 * needs to be freed no matter what.
 		 */
-		if (F_ISSET(&data, DB_DBT_MALLOC) && ret == 0)
+		if (F_ISSET(&key, DB_DBT_MALLOC) && ret == 0 &&
+		    key.data != ktmp)
+			__os_ufree(dbp->dbenv, key.data);
+		if (F_ISSET(&data, DB_DBT_MALLOC) && ret == 0 &&
+		    data.data != dtmp)
 			__os_ufree(dbp->dbenv, data.data);
 		else if (!F_ISSET(&data, DB_DBT_MALLOC))
 			__os_free(dbp->dbenv, data.data);
-		if (ispget && ret == 0)
+		if (ispget && ret == 0 && pkey.data != save.data)
 			__os_ufree(dbp->dbenv, pkey.data);
 		if (result == TCL_OK)
 			Tcl_SetObjResult(interp, retlist);
@@ -1285,17 +1549,17 @@ tcl_DbGet(interp, objc, objv, dbp, ispget)
 	    "db get (cursor)");
 	if (result == TCL_ERROR)
 		goto out1;
-	if (ret == 0 && pattern &&
-	    memcmp(key.data, prefix, strlen(prefix)) != 0) {
-		/*
-		 * Free space from DB_DBT_MALLOC
-		 */
-		free(data.data);
-		goto out1;
-	}
-	if (pattern)
+	if (pattern) {
+		if (ret == 0 && prefix != NULL &&
+		    memcmp(key.data, prefix, strlen(prefix)) != 0) {
+			/*
+			 * Free space from DB_DBT_MALLOC
+			 */
+			__os_ufree(dbp->dbenv, data.data);
+			goto out1;
+		}
 		cflag = DB_NEXT;
-	 else
+	} else
 		cflag = DB_NEXT_DUP;
 
 	while (ret == 0 && result == TCL_OK) {
@@ -1312,8 +1576,8 @@ tcl_DbGet(interp, objc, objv, dbp, ispget)
 		 * Free space from DB_DBT_MALLOC
 		 */
 		if (ispget)
-			free(pkey.data);
-		free(data.data);
+			__os_ufree(dbp->dbenv, pkey.data);
+		__os_ufree(dbp->dbenv, data.data);
 		if (result != TCL_OK)
 			break;
 		/*
@@ -1331,17 +1595,17 @@ tcl_DbGet(interp, objc, objv, dbp, ispget)
 			ret = dbc->c_pget(dbc, &key, &pkey, &data, cflag | rmw);
 		} else
 			ret = dbc->c_get(dbc, &key, &data, cflag | rmw);
-		if (ret == 0 && pattern &&
+		if (ret == 0 && prefix != NULL &&
 		    memcmp(key.data, prefix, strlen(prefix)) != 0) {
 			/*
 			 * Free space from DB_DBT_MALLOC
 			 */
-			free(data.data);
+			__os_ufree(dbp->dbenv, data.data);
 			break;
 		}
 	}
 out1:
-	dbc->c_close(dbc);
+	(void)dbc->c_close(dbc);
 	if (result == TCL_OK)
 		Tcl_SetObjResult(interp, retlist);
 out:
@@ -1352,10 +1616,10 @@ out:
 	 */
 	if (prefix != NULL)
 		__os_free(dbp->dbenv, prefix);
-	if (freedata)
-		(void)__os_free(dbp->dbenv, dtmp);
-	if (freekey)
-		(void)__os_free(dbp->dbenv, ktmp);
+	if (dtmp != NULL && freedata)
+		__os_free(dbp->dbenv, dtmp);
+	if (ktmp != NULL && freekey)
+		__os_free(dbp->dbenv, ktmp);
 	return (result);
 }
 
@@ -1369,7 +1633,7 @@ tcl_DbDelete(interp, objc, objv, dbp)
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 	DB *dbp;			/* Database pointer */
 {
-	static char *dbdelopts[] = {
+	static const char *dbdelopts[] = {
 		"-auto_commit",
 		"-glob",
 		"-txn",
@@ -1400,6 +1664,7 @@ tcl_DbDelete(interp, objc, objv, dbp)
 		return (TCL_ERROR);
 	}
 
+	ktmp = NULL;
 	memset(&key, 0, sizeof(key));
 	/*
 	 * The first arg must be -auto_commit, -glob, -txn or a list of keys.
@@ -1536,8 +1801,8 @@ tcl_DbDelete(interp, objc, objv, dbp)
 		 * If we have any error, set up return result and stop
 		 * processing keys.
 		 */
-		if (freekey)
-			(void)__os_free(dbp->dbenv, ktmp);
+		if (ktmp != NULL && freekey)
+			__os_free(dbp->dbenv, ktmp);
 		if (ret != 0)
 			break;
 	}
@@ -1604,7 +1869,7 @@ tcl_DbDelete(interp, objc, objv, dbp)
 		 * have multiple nuls at the end, so we free using __os_free().
 		 */
 		__os_free(dbp->dbenv, prefix);
-		dbc->c_close(dbc);
+		(void)dbc->c_close(dbc);
 		result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "db del");
 	}
 out:
@@ -1622,8 +1887,9 @@ tcl_DbCursor(interp, objc, objv, dbp, dbcp)
 	DB *dbp;			/* Database pointer */
 	DBC **dbcp;			/* Return cursor pointer */
 {
-	static char *dbcuropts[] = {
-#if CONFIG_TEST
+	static const char *dbcuropts[] = {
+#ifdef CONFIG_TEST
+		"-degree_2",
 		"-dirty",
 		"-update",
 #endif
@@ -1631,7 +1897,8 @@ tcl_DbCursor(interp, objc, objv, dbp, dbcp)
 		NULL
 	};
 	enum dbcuropts {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
+		DBCUR_DEGREE2,
 		DBCUR_DIRTY,
 		DBCUR_UPDATE,
 #endif
@@ -1654,7 +1921,10 @@ tcl_DbCursor(interp, objc, objv, dbp, dbcp)
 		}
 		i++;
 		switch ((enum dbcuropts)optindex) {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
+		case DBCUR_DEGREE2:
+			flag |= DB_DEGREE_2;
+			break;
 		case DBCUR_DIRTY:
 			flag |= DB_DIRTY_READ;
 			break;
@@ -1703,7 +1973,7 @@ tcl_DbAssociate(interp, objc, objv, dbp)
 	Tcl_Obj *CONST objv[];
 	DB *dbp;
 {
-	static char *dbaopts[] = {
+	static const char *dbaopts[] = {
 		"-auto_commit",
 		"-create",
 		"-txn",
@@ -1720,6 +1990,31 @@ tcl_DbAssociate(interp, objc, objv, dbp)
 	int i, optindex, result, ret;
 	char *arg, msg[MSG_SIZE];
 	u_int32_t flag;
+#ifdef CONFIG_TEST
+	/*
+	 * When calling DB->associate over RPC, the Tcl API uses
+	 * special flags that the RPC server interprets to set the
+	 * callback correctly.
+	 */
+	const char *cbname;
+	struct {
+		const char *name;
+		u_int32_t flag;
+	} *cb, callbacks[] = {
+		{ "", 0 }, /* A NULL callback in Tcl. */
+		{ "_s_reversedata", DB_RPC2ND_REVERSEDATA },
+		{ "_s_noop", DB_RPC2ND_NOOP },
+		{ "_s_concatkeydata", DB_RPC2ND_CONCATKEYDATA },
+		{ "_s_concatdatakey", DB_RPC2ND_CONCATDATAKEY },
+		{ "_s_reverseconcat", DB_RPC2ND_REVERSECONCAT },
+		{ "_s_truncdata", DB_RPC2ND_TRUNCDATA },
+		{ "_s_reversedata", DB_RPC2ND_REVERSEDATA },
+		{ "_s_constant", DB_RPC2ND_CONSTANT },
+		{ "sj_getzip", DB_RPC2ND_GETZIP },
+		{ "sj_getname", DB_RPC2ND_GETNAME },
+		{ NULL, 0 }
+	};
+#endif
 
 	txn = NULL;
 	result = TCL_OK;
@@ -1792,7 +2087,48 @@ tcl_DbAssociate(interp, objc, objv, dbp)
 	 * callbacks.
 	 */
 	sdbip = (DBTCL_INFO *)sdbp->api_internal;
+
+#ifdef CONFIG_TEST
+	if (i != objc - 1 && RPC_ON(dbp->dbenv)) {
+		/*
+		 * The flag values allowed to DB->associate may have changed to
+		 * overlap with the range we've chosen.  If this happens, we
+		 * need to reset all of the RPC_2ND_* flags to a new range.
+		 */
+		if ((flag & DB_RPC2ND_MASK) != 0) {
+			snprintf(msg, MSG_SIZE,
+			    "RPC secondary flags overlap -- recalculate!\n");
+			Tcl_SetResult(interp, msg, TCL_VOLATILE);
+			return (TCL_ERROR);
+		}
+
+		cbname = Tcl_GetStringFromObj(objv[objc - 2], NULL);
+		for (cb = callbacks; cb->name != NULL; cb++)
+			if (strcmp(cb->name, cbname) == 0) {
+				flag |= cb->flag;
+				break;
+			}
+
+		if (cb->name == NULL) {
+			snprintf(msg, MSG_SIZE,
+			    "Associate: unknown callback: %s\n", cbname);
+			Tcl_SetResult(interp, msg, TCL_VOLATILE);
+			return (TCL_ERROR);
+		}
+
+		ret = dbp->associate(dbp, txn, sdbp, NULL, flag);
+
+		/*
+		 * The primary reference isn't set when calling through
+		 * the RPC server, but the Tcl API peeks at it in other
+		 * places (see tcl_DbGet).
+		 */
+		if (ret == 0)
+			sdbp->s_primary = dbp;
+	} else if (i != objc - 1) {
+#else
 	if (i != objc - 1) {
+#endif
 		/*
 		 * We have 2 args, get the callback.
 		 */
@@ -1828,7 +2164,8 @@ tcl_second_call(dbp, pkey, data, skey)
 	DBTCL_INFO *ip;
 	Tcl_Interp *interp;
 	Tcl_Obj *pobj, *dobj, *objv[3];
-	int len, result, ret;
+	size_t len;
+	int ilen, result, ret;
 	void *retbuf, *databuf;
 
 	ip = (DBTCL_INFO *)dbp->api_internal;
@@ -1839,9 +2176,9 @@ tcl_second_call(dbp, pkey, data, skey)
 	 * Create two ByteArray objects, with the contents of the pkey
 	 * and data DBTs that are our inputs.
 	 */
-	pobj = Tcl_NewByteArrayObj(pkey->data, pkey->size);
+	pobj = Tcl_NewByteArrayObj(pkey->data, (int)pkey->size);
 	Tcl_IncrRefCount(pobj);
-	dobj = Tcl_NewByteArrayObj(data->data, data->size);
+	dobj = Tcl_NewByteArrayObj(data->data, (int)data->size);
 	Tcl_IncrRefCount(dobj);
 
 	objv[1] = pobj;
@@ -1858,8 +2195,8 @@ tcl_second_call(dbp, pkey, data, skey)
 		return (EINVAL);
 	}
 
-	retbuf =
-	    Tcl_GetByteArrayFromObj(Tcl_GetObjResult(interp), &len);
+	retbuf = Tcl_GetByteArrayFromObj(Tcl_GetObjResult(interp), &ilen);
+	len = (size_t)ilen;
 
 	/*
 	 * retbuf is owned by Tcl; copy it into malloc'ed memory.
@@ -1889,7 +2226,7 @@ tcl_DbJoin(interp, objc, objv, dbp, dbcp)
 	DB *dbp;			/* Database pointer */
 	DBC **dbcp;			/* Cursor pointer */
 {
-	static char *dbjopts[] = {
+	static const char *dbjopts[] = {
 		"-nosort",
 		NULL
 	};
@@ -1897,8 +2234,9 @@ tcl_DbJoin(interp, objc, objv, dbp, dbcp)
 		DBJ_NOSORT
 	};
 	DBC **listp;
+	size_t size;
 	u_int32_t flag;
-	int adj, i, j, optindex, size, result, ret;
+	int adj, i, j, optindex, result, ret;
 	char *arg, msg[MSG_SIZE];
 
 	result = TCL_OK;
@@ -1908,9 +2246,7 @@ tcl_DbJoin(interp, objc, objv, dbp, dbcp)
 		return (TCL_ERROR);
 	}
 
-	i = 2;
-	adj = i;
-	while (i < objc) {
+	for (adj = i = 2; i < objc; i++) {
 		if (Tcl_GetIndexFromObj(interp, objv[i], dbjopts, "option",
 		    TCL_EXACT, &optindex) != TCL_OK) {
 			result = IS_HELP(objv[i]);
@@ -1920,7 +2256,6 @@ tcl_DbJoin(interp, objc, objv, dbp, dbcp)
 			Tcl_ResetResult(interp);
 			break;
 		}
-		i++;
 		switch ((enum dbjopts)optindex) {
 		case DBJ_NOSORT:
 			flag |= DB_JOIN_NOSORT;
@@ -1933,7 +2268,7 @@ tcl_DbJoin(interp, objc, objv, dbp, dbcp)
 	/*
 	 * Allocate one more for NULL ptr at end of list.
 	 */
-	size = sizeof(DBC *) * ((objc - adj) + 1);
+	size = sizeof(DBC *) * (size_t)((objc - adj) + 1);
 	ret = __os_malloc(dbp->dbenv, size, &listp);
 	if (ret != 0) {
 		Tcl_SetResult(interp, db_strerror(ret), TCL_STATIC);
@@ -1972,15 +2307,15 @@ tcl_DbGetjoin(interp, objc, objv, dbp)
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 	DB *dbp;			/* Database pointer */
 {
-	static char *dbgetjopts[] = {
-#if CONFIG_TEST
+	static const char *dbgetjopts[] = {
+#ifdef CONFIG_TEST
 		"-nosort",
 #endif
 		"-txn",
 		NULL
 	};
 	enum dbgetjopts {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 		DBGETJ_NOSORT,
 #endif
 		DBGETJ_TXN
@@ -1992,12 +2327,14 @@ tcl_DbGetjoin(interp, objc, objv, dbp)
 	DBT key, data;
 	Tcl_Obj **elemv, *retlist;
 	void *ktmp;
+	size_t size;
 	u_int32_t flag;
-	int adj, elemc, freekey, i, j, optindex, result, ret, size;
+	int adj, elemc, freekey, i, j, optindex, result, ret;
 	char *arg, msg[MSG_SIZE];
 
 	result = TCL_OK;
 	flag = 0;
+	ktmp = NULL;
 	freekey = 0;
 	if (objc < 3) {
 		Tcl_WrongNumArgs(interp, 2, objv, "{db1 key1} {db2 key2} ...");
@@ -2019,7 +2356,7 @@ tcl_DbGetjoin(interp, objc, objv, dbp)
 		}
 		i++;
 		switch ((enum dbgetjopts)optindex) {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 		case DBGETJ_NOSORT:
 			flag |= DB_JOIN_NOSORT;
 			adj++;
@@ -2045,7 +2382,7 @@ tcl_DbGetjoin(interp, objc, objv, dbp)
 	}
 	if (result != TCL_OK)
 		return (result);
-	size = sizeof(DBC *) * ((objc - adj) + 1);
+	size = sizeof(DBC *) * (size_t)((objc - adj) + 1);
 	ret = __os_malloc(NULL, size, &listp);
 	if (ret != 0) {
 		Tcl_SetResult(interp, db_strerror(ret), TCL_STATIC);
@@ -2117,25 +2454,138 @@ tcl_DbGetjoin(interp, objc, objv, dbp)
 			result = _SetListElem(interp, retlist,
 			    key.data, key.size,
 			    data.data, data.size);
-			free(key.data);
-			free(data.data);
+			__os_ufree(dbp->dbenv, key.data);
+			__os_ufree(dbp->dbenv, data.data);
 		}
 	}
-	dbc->c_close(dbc);
+	(void)dbc->c_close(dbc);
 	if (result == TCL_OK)
 		Tcl_SetObjResult(interp, retlist);
 out:
-	if (freekey)
-		(void)__os_free(dbp->dbenv, ktmp);
+	if (ktmp != NULL && freekey)
+		__os_free(dbp->dbenv, ktmp);
 	while (j) {
 		if (listp[j])
-			(listp[j])->c_close(listp[j]);
+			(void)(listp[j])->c_close(listp[j]);
 		j--;
 	}
 	__os_free(dbp->dbenv, listp);
 	return (result);
 }
 
+/*
+ * tcl_DbGetFlags --
+ */
+static int
+tcl_DbGetFlags(interp, objc, objv, dbp)
+	Tcl_Interp *interp;		/* Interpreter */
+	int objc;			/* How many arguments? */
+	Tcl_Obj *CONST objv[];		/* The argument objects */
+	DB *dbp;			/* Database pointer */
+{
+	int i, ret, result;
+	u_int32_t flags;
+	char buf[512];
+	Tcl_Obj *res;
+
+	static const struct {
+		u_int32_t flag;
+		char *arg;
+	} db_flags[] = {
+		{ DB_CHKSUM, "-chksum" },
+		{ DB_DUP, "-dup" },
+		{ DB_DUPSORT, "-dupsort" },
+		{ DB_ENCRYPT, "-encrypt" },
+		{ DB_INORDER, "-inorder" },
+		{ DB_TXN_NOT_DURABLE, "-notdurable" },
+		{ DB_RECNUM, "-recnum" },
+		{ DB_RENUMBER, "-renumber" },
+		{ DB_REVSPLITOFF, "-revsplitoff" },
+		{ DB_SNAPSHOT, "-snapshot" },
+		{ 0, NULL }
+	};
+
+	if (objc != 2) {
+		Tcl_WrongNumArgs(interp, 1, objv, NULL);
+		return (TCL_ERROR);
+	}
+
+	ret = dbp->get_flags(dbp, &flags);
+	if ((result = _ReturnSetup(
+	    interp, ret, DB_RETOK_STD(ret), "db get_flags")) == TCL_OK) {
+		buf[0] = '\0';
+
+		for (i = 0; db_flags[i].flag != 0; i++)
+			if (LF_ISSET(db_flags[i].flag)) {
+				if (strlen(buf) > 0)
+					(void)strncat(buf, " ", sizeof(buf));
+				(void)strncat(
+				    buf, db_flags[i].arg, sizeof(buf));
+			}
+
+		res = NewStringObj(buf, strlen(buf));
+		Tcl_SetObjResult(interp, res);
+	}
+
+	return (result);
+}
+
+/*
+ * tcl_DbGetOpenFlags --
+ */
+static int
+tcl_DbGetOpenFlags(interp, objc, objv, dbp)
+	Tcl_Interp *interp;		/* Interpreter */
+	int objc;			/* How many arguments? */
+	Tcl_Obj *CONST objv[];		/* The argument objects */
+	DB *dbp;			/* Database pointer */
+{
+	int i, ret, result;
+	u_int32_t flags;
+	char buf[512];
+	Tcl_Obj *res;
+
+	static const struct {
+		u_int32_t flag;
+		char *arg;
+	} open_flags[] = {
+		{ DB_AUTO_COMMIT, "-auto_commit" },
+		{ DB_CREATE, "-create" },
+		{ DB_DEGREE_2, "-degree_2" },
+		{ DB_DIRTY_READ, "-dirty" },
+		{ DB_EXCL, "-excl" },
+		{ DB_NOMMAP, "-nommap" },
+		{ DB_RDONLY, "-rdonly" },
+		{ DB_THREAD, "-thread" },
+		{ DB_TRUNCATE, "-truncate" },
+		{ 0, NULL }
+	};
+
+	if (objc != 2) {
+		Tcl_WrongNumArgs(interp, 1, objv, NULL);
+		return (TCL_ERROR);
+	}
+
+	ret = dbp->get_open_flags(dbp, &flags);
+	if ((result = _ReturnSetup(
+	    interp, ret, DB_RETOK_STD(ret), "db get_open_flags")) == TCL_OK) {
+		buf[0] = '\0';
+
+		for (i = 0; open_flags[i].flag != 0; i++)
+			if (LF_ISSET(open_flags[i].flag)) {
+				if (strlen(buf) > 0)
+					(void)strncat(buf, " ", sizeof(buf));
+				(void)strncat(
+				    buf, open_flags[i].arg, sizeof(buf));
+			}
+
+		res = NewStringObj(buf, strlen(buf));
+		Tcl_SetObjResult(interp, res);
+	}
+
+	return (result);
+}
+
 /*
  * tcl_DbCount --
  */
@@ -2153,25 +2603,25 @@ tcl_DbCount(interp, objc, objv, dbp)
 	db_recno_t count, recno;
 	int freekey, result, ret;
 
-	result = TCL_OK;
-	count = 0;
-	freekey = 0;
 	res = NULL;
+	count = 0;
+	freekey = ret = 0;
+	ktmp = NULL;
+	result = TCL_OK;
+
 	if (objc != 3) {
 		Tcl_WrongNumArgs(interp, 2, objv, "key");
 		return (TCL_ERROR);
 	}
 
-	memset(&key, 0, sizeof(key));
-
 	/*
 	 * Get the count for our key.
 	 * We do this by getting a cursor for this DB.  Moving the cursor
 	 * to the set location, and getting a count on that cursor.
 	 */
-	ret = 0;
 	memset(&key, 0, sizeof(key));
 	memset(&data, 0, sizeof(data));
+
 	/*
 	 * If it's a queue or recno database, we must make sure to
 	 * treat the key as a recno rather than as a byte string.
@@ -2204,7 +2654,7 @@ tcl_DbCount(interp, objc, objv, dbp)
 	 * Move our cursor to the key.
 	 */
 	ret = dbc->c_get(dbc, &key, &data, DB_SET);
-	if (ret == DB_NOTFOUND)
+	if (ret == DB_KEYEMPTY || ret == DB_NOTFOUND)
 		count = 0;
 	else {
 		ret = dbc->c_count(dbc, &count, 0);
@@ -2214,16 +2664,16 @@ tcl_DbCount(interp, objc, objv, dbp)
 			goto out;
 		}
 	}
-	res = Tcl_NewLongObj((long)count);
+	res = Tcl_NewWideIntObj((Tcl_WideInt)count);
 	Tcl_SetObjResult(interp, res);
-out:
-	if (freekey)
-		(void)__os_free(dbp->dbenv, ktmp);
+
+out:	if (ktmp != NULL && freekey)
+		__os_free(dbp->dbenv, ktmp);
 	(void)dbc->c_close(dbc);
 	return (result);
 }
 
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 /*
  * tcl_DbKeyRange --
  */
@@ -2234,7 +2684,7 @@ tcl_DbKeyRange(interp, objc, objv, dbp)
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 	DB *dbp;			/* Database pointer */
 {
-	static char *dbkeyropts[] = {
+	static const char *dbkeyropts[] = {
 		"-txn",
 		NULL
 	};
@@ -2252,17 +2702,17 @@ tcl_DbKeyRange(interp, objc, objv, dbp)
 	int freekey, i, myobjc, optindex, result, ret;
 	char *arg, msg[MSG_SIZE];
 
-	result = TCL_OK;
+	ktmp = NULL;
 	flag = 0;
 	freekey = 0;
+	result = TCL_OK;
 	if (objc < 3) {
 		Tcl_WrongNumArgs(interp, 2, objv, "?-txn id? key");
 		return (TCL_ERROR);
 	}
 
 	txn = NULL;
-	i = 2;
-	while (i < objc) {
+	for (i = 2; i < objc;) {
 		if (Tcl_GetIndexFromObj(interp, objv[i], dbkeyropts, "option",
 		    TCL_EXACT, &optindex) != TCL_OK) {
 			result = IS_HELP(objv[i]);
@@ -2337,9 +2787,9 @@ tcl_DbKeyRange(interp, objc, objv, dbp)
 	retlist = Tcl_NewListObj(myobjc, myobjv);
 	if (result == TCL_OK)
 		Tcl_SetObjResult(interp, retlist);
-out:
-	if (freekey)
-		(void)__os_free(dbp->dbenv, ktmp);
+
+out:	if (ktmp != NULL && freekey)
+		__os_free(dbp->dbenv, ktmp);
 	return (result);
 }
 #endif
@@ -2354,7 +2804,7 @@ tcl_DbTruncate(interp, objc, objv, dbp)
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 	DB *dbp;			/* Database pointer */
 {
-	static char *dbcuropts[] = {
+	static const char *dbcuropts[] = {
 		"-auto_commit",
 		"-txn",
 		NULL
@@ -2413,7 +2863,7 @@ tcl_DbTruncate(interp, objc, objv, dbp)
 		result = _ErrorSetup(interp, ret, "db truncate");
 
 	else {
-		res = Tcl_NewLongObj((long)count);
+		res = Tcl_NewWideIntObj((Tcl_WideInt)count);
 		Tcl_SetObjResult(interp, res);
 	}
 out:
diff --git a/storage/bdb/tcl/tcl_db_pkg.c b/storage/bdb/tcl/tcl_db_pkg.c
index ce37598dc1adb4231f82093f97bc08f9fdf8e0ab..ce55df8429846862511cfbb3121045212dfc3a79 100644
--- a/storage/bdb/tcl/tcl_db_pkg.c
+++ b/storage/bdb/tcl/tcl_db_pkg.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: tcl_db_pkg.c,v 11.190 2004/10/27 16:48:32 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: tcl_db_pkg.c,v 11.141 2002/08/14 20:15:47 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -19,7 +17,7 @@ static const char revid[] = "$Id: tcl_db_pkg.c,v 11.141 2002/08/14 20:15:47 bost
 #include <tcl.h>
 #endif
 
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 #define	DB_DBM_HSEARCH 1
 #endif
 
@@ -42,23 +40,26 @@ static int	bdb_DbOpen __P((Tcl_Interp *, int, Tcl_Obj * CONST*,
     DBTCL_INFO *, DB **));
 static int	bdb_DbRemove __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
 static int	bdb_DbRename __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
+static int	bdb_Version __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
+static int	bdb_SeqOpen __P((Tcl_Interp *, int, Tcl_Obj * CONST*,
+    DBTCL_INFO *, DB_SEQUENCE **));
+
+#ifdef CONFIG_TEST
 static int	bdb_DbUpgrade __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
 static int	bdb_DbVerify __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
-static int	bdb_Version __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
 static int	bdb_Handles __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
+static int	bdb_MsgType __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
 
 static int	tcl_bt_compare __P((DB *, const DBT *, const DBT *));
 static int	tcl_compare_callback __P((DB *, const DBT *, const DBT *,
     Tcl_Obj *, char *));
+static void	tcl_db_free __P((void *));
+static void *	tcl_db_malloc __P((size_t));
+static void *	tcl_db_realloc __P((void *, size_t));
 static int	tcl_dup_compare __P((DB *, const DBT *, const DBT *));
 static u_int32_t tcl_h_hash __P((DB *, const void *, u_int32_t));
 static int	tcl_rep_send __P((DB_ENV *,
-    const DBT *, const DBT *, int, u_int32_t));
-
-#ifdef TEST_ALLOC
-static void *	tcl_db_malloc __P((size_t));
-static void *	tcl_db_realloc __P((void *, size_t));
-static void	tcl_db_free __P((void *));
+    const DBT *, const DBT *, const DB_LSN *, int, u_int32_t));
 #endif
 
 /*
@@ -75,22 +76,26 @@ Db_tcl_Init(interp)
 					 * to be made available. */
 {
 	int code;
+	char pkg[12];
 
-	code = Tcl_PkgProvide(interp, "Db_tcl", "1.0");
+	snprintf(pkg, sizeof(pkg), "%d.%d", DB_VERSION_MAJOR, DB_VERSION_MINOR);
+	code = Tcl_PkgProvide(interp, "Db_tcl", pkg);
 	if (code != TCL_OK)
 		return (code);
 
-	Tcl_CreateObjCommand(interp, "berkdb", (Tcl_ObjCmdProc *)berkdb_Cmd,
-	    (ClientData)0, NULL);
+	(void)Tcl_CreateObjCommand(interp,
+	    "berkdb", (Tcl_ObjCmdProc *)berkdb_Cmd, (ClientData)0, NULL);
 	/*
 	 * Create shared global debugging variables
 	 */
-	Tcl_LinkVar(interp, "__debug_on", (char *)&__debug_on, TCL_LINK_INT);
-	Tcl_LinkVar(interp, "__debug_print", (char *)&__debug_print,
-	    TCL_LINK_INT);
-	Tcl_LinkVar(interp, "__debug_stop", (char *)&__debug_stop,
-	    TCL_LINK_INT);
-	Tcl_LinkVar(interp, "__debug_test", (char *)&__debug_test,
+	(void)Tcl_LinkVar(
+	    interp, "__debug_on", (char *)&__debug_on, TCL_LINK_INT);
+	(void)Tcl_LinkVar(
+	    interp, "__debug_print", (char *)&__debug_print, TCL_LINK_INT);
+	(void)Tcl_LinkVar(
+	    interp, "__debug_stop", (char *)&__debug_stop, TCL_LINK_INT);
+	(void)Tcl_LinkVar(
+	    interp, "__debug_test", (char *)&__debug_test,
 	    TCL_LINK_INT);
 	LIST_INIT(&__db_infohead);
 	return (TCL_OK);
@@ -116,10 +121,11 @@ berkdb_Cmd(notused, interp, objc, objv)
 	int objc;			/* How many arguments? */
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 {
-	static char *berkdbcmds[] = {
-#if CONFIG_TEST
+	static const char *berkdbcmds[] = {
+#ifdef CONFIG_TEST
 		"dbverify",
 		"handles",
+		"msgtype",
 		"upgrade",
 #endif
 		"dbremove",
@@ -127,8 +133,11 @@ berkdb_Cmd(notused, interp, objc, objv)
 		"env",
 		"envremove",
 		"open",
+#ifdef HAVE_SEQUENCE
+		"sequence",
+#endif
 		"version",
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 		/* All below are compatibility functions */
 		"hcreate",	"hsearch",	"hdestroy",
 		"dbminit",	"fetch",	"store",
@@ -144,9 +153,10 @@ berkdb_Cmd(notused, interp, objc, objv)
 	 * All commands enums below ending in X are compatibility
 	 */
 	enum berkdbcmds {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 		BDB_DBVERIFY,
 		BDB_HANDLES,
+		BDB_MSGTYPE,
 		BDB_UPGRADE,
 #endif
 		BDB_DBREMOVE,
@@ -154,8 +164,11 @@ berkdb_Cmd(notused, interp, objc, objv)
 		BDB_ENV,
 		BDB_ENVREMOVE,
 		BDB_OPEN,
+#ifdef HAVE_SEQUENCE
+		BDB_SEQUENCE,
+#endif
 		BDB_VERSION,
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 		BDB_HCREATEX,	BDB_HSEARCHX,	BDB_HDESTROYX,
 		BDB_DBMINITX,	BDB_FETCHX,	BDB_STOREX,
 		BDB_DELETEX,	BDB_FIRSTKEYX,	BDB_NEXTKEYX,
@@ -166,9 +179,15 @@ berkdb_Cmd(notused, interp, objc, objv)
 	};
 	static int env_id = 0;
 	static int db_id = 0;
+#ifdef HAVE_SEQUENCE
+	static int seq_id = 0;
+#endif
 
 	DB *dbp;
-#if CONFIG_TEST
+#ifdef HAVE_SEQUENCE
+	DB_SEQUENCE *seq;
+#endif
+#ifdef CONFIG_TEST
 	DBM *ndbmp;
 	static int ndbm_id = 0;
 #endif
@@ -197,13 +216,16 @@ berkdb_Cmd(notused, interp, objc, objv)
 		return (IS_HELP(objv[1]));
 	res = NULL;
 	switch ((enum berkdbcmds)cmdindex) {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 	case BDB_DBVERIFY:
 		result = bdb_DbVerify(interp, objc, objv);
 		break;
 	case BDB_HANDLES:
 		result = bdb_Handles(interp, objc, objv);
 		break;
+	case BDB_MSGTYPE:
+		result = bdb_MsgType(interp, objc, objv);
+		break;
 	case BDB_UPGRADE:
 		result = bdb_DbUpgrade(interp, objc, objv);
 		break;
@@ -219,12 +241,11 @@ berkdb_Cmd(notused, interp, objc, objv)
 			result = bdb_EnvOpen(interp, objc, objv, ip, &envp);
 			if (result == TCL_OK && envp != NULL) {
 				env_id++;
-				Tcl_CreateObjCommand(interp, newname,
+				(void)Tcl_CreateObjCommand(interp, newname,
 				    (Tcl_ObjCmdProc *)env_Cmd,
 				    (ClientData)envp, NULL);
 				/* Use ip->i_name - newname is overwritten */
-				res =
-				    Tcl_NewStringObj(newname, strlen(newname));
+				res = NewStringObj(newname, strlen(newname));
 				_SetInfoData(ip, envp);
 			} else
 				_DeleteInfo(ip);
@@ -250,12 +271,11 @@ berkdb_Cmd(notused, interp, objc, objv)
 			result = bdb_DbOpen(interp, objc, objv, ip, &dbp);
 			if (result == TCL_OK && dbp != NULL) {
 				db_id++;
-				Tcl_CreateObjCommand(interp, newname,
+				(void)Tcl_CreateObjCommand(interp, newname,
 				    (Tcl_ObjCmdProc *)db_Cmd,
 				    (ClientData)dbp, NULL);
 				/* Use ip->i_name - newname is overwritten */
-				res =
-				    Tcl_NewStringObj(newname, strlen(newname));
+				res = NewStringObj(newname, strlen(newname));
 				_SetInfoData(ip, dbp);
 			} else
 				_DeleteInfo(ip);
@@ -265,7 +285,30 @@ berkdb_Cmd(notused, interp, objc, objv)
 			result = TCL_ERROR;
 		}
 		break;
-#if CONFIG_TEST
+#ifdef HAVE_SEQUENCE
+	case BDB_SEQUENCE:
+		snprintf(newname, sizeof(newname), "seq%d", seq_id);
+		ip = _NewInfo(interp, NULL, newname, I_SEQ);
+		if (ip != NULL) {
+			result = bdb_SeqOpen(interp, objc, objv, ip, &seq);
+			if (result == TCL_OK && seq != NULL) {
+				seq_id++;
+				(void)Tcl_CreateObjCommand(interp, newname,
+				    (Tcl_ObjCmdProc *)seq_Cmd,
+				    (ClientData)seq, NULL);
+				/* Use ip->i_name - newname is overwritten */
+				res = NewStringObj(newname, strlen(newname));
+				_SetInfoData(ip, seq);
+			} else
+				_DeleteInfo(ip);
+		} else {
+			Tcl_SetResult(interp, "Could not set up info",
+			    TCL_STATIC);
+			result = TCL_ERROR;
+		}
+		break;
+#endif
+#ifdef CONFIG_TEST
 	case BDB_HCREATEX:
 	case BDB_HSEARCHX:
 	case BDB_HDESTROYX:
@@ -287,12 +330,11 @@ berkdb_Cmd(notused, interp, objc, objv)
 			result = bdb_NdbmOpen(interp, objc, objv, &ndbmp);
 			if (result == TCL_OK) {
 				ndbm_id++;
-				Tcl_CreateObjCommand(interp, newname,
+				(void)Tcl_CreateObjCommand(interp, newname,
 				    (Tcl_ObjCmdProc *)ndbm_Cmd,
 				    (ClientData)ndbmp, NULL);
 				/* Use ip->i_name - newname is overwritten */
-				res =
-				    Tcl_NewStringObj(newname, strlen(newname));
+				res = NewStringObj(newname, strlen(newname));
 				_SetInfoData(ip, ndbmp);
 			} else
 				_DeleteInfo(ip);
@@ -342,8 +384,9 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
 	DBTCL_INFO *ip;			/* Our internal info */
 	DB_ENV **env;			/* Environment pointer */
 {
-	static char *envopen[] = {
-#if CONFIG_TEST
+	static const char *envopen[] = {
+#ifdef CONFIG_TEST
+		"-alloc",
 		"-auto_commit",
 		"-cdb",
 		"-cdb_alldb",
@@ -358,18 +401,24 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
 		"-lock_timeout",
 		"-log",
 		"-log_buffer",
+		"-log_inmemory",
 		"-log_max",
 		"-log_regionmax",
-		"-mmapsize",
-		"-nommap",
+		"-log_remove",
+		"-mpool_max_openfd",
+		"-mpool_max_write",
+		"-mpool_mmap_size",
+		"-mpool_nommap",
 		"-overwrite",
 		"-region_init",
 		"-rep_client",
-		"-rep_logsonly",
 		"-rep_master",
 		"-rep_transport",
 		"-server",
 		"-server_timeout",
+		"-set_intermediate_dir",
+		"-thread",
+		"-time_notgranted",
 		"-txn_timeout",
 		"-txn_timestamp",
 		"-verbose",
@@ -403,7 +452,8 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
 	 * which is close to but not quite alphabetical.
 	 */
 	enum envopen {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
+		ENV_ALLOC,
 		ENV_AUTO_COMMIT,
 		ENV_CDB,
 		ENV_CDB_ALLDB,
@@ -418,18 +468,24 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
 		ENV_LOCK_TIMEOUT,
 		ENV_LOG,
 		ENV_LOG_BUFFER,
+		ENV_LOG_INMEMORY,
 		ENV_LOG_MAX,
 		ENV_LOG_REGIONMAX,
-		ENV_MMAPSIZE,
-		ENV_NOMMAP,
+		ENV_LOG_REMOVE,
+		ENV_MPOOL_MAX_OPENFD,
+		ENV_MPOOL_MAX_WRITE,
+		ENV_MPOOL_MMAP_SIZE,
+		ENV_MPOOL_NOMMAP,
 		ENV_OVERWRITE,
 		ENV_REGION_INIT,
 		ENV_REP_CLIENT,
-		ENV_REP_LOGSONLY,
 		ENV_REP_MASTER,
 		ENV_REP_TRANSPORT,
 		ENV_SERVER,
 		ENV_SERVER_TO,
+		ENV_SET_INTERMEDIATE_DIR,
+		ENV_THREAD,
+		ENV_TIME_NOTGRANTED,
 		ENV_TXN_TIMEOUT,
 		ENV_TXN_TIME,
 		ENV_VERBOSE,
@@ -456,41 +512,41 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
 		ENV_USE_ENVIRON,
 		ENV_USE_ENVIRON_ROOT
 	};
-	Tcl_Obj **myobjv, **myobjv1;
-	time_t timestamp;
-	u_int32_t detect, gbytes, bytes, ncaches, logbufset, logmaxset;
-	u_int32_t open_flags, rep_flags, set_flags, size, uintarg;
-	u_int8_t *conflicts;
-	int i, intarg, j, mode, myobjc, nmodes, optindex;
-	int result, ret, temp;
+	Tcl_Obj **myobjv;
+	u_int32_t cr_flags, gbytes, bytes, logbufset, logmaxset;
+	u_int32_t open_flags, rep_flags, set_flags, uintarg;
+	int i, mode, myobjc, ncaches, optindex, result, ret;
 	long client_to, server_to, shm;
 	char *arg, *home, *passwd, *server;
+#ifdef CONFIG_TEST
+	Tcl_Obj **myobjv1;
+	time_t timestamp;
+	long v;
+	u_int32_t detect;
+	u_int8_t *conflicts;
+	int intarg, intarg2, j, nmodes, temp;
+#endif
 
 	result = TCL_OK;
 	mode = 0;
-	rep_flags = set_flags = 0;
+	rep_flags = set_flags = cr_flags = 0;
 	home = NULL;
 
 	/*
 	 * XXX
 	 * If/when our Tcl interface becomes thread-safe, we should enable
-	 * DB_THREAD here in all cases.  For now, turn it on only when testing
-	 * so that we exercise MUTEX_THREAD_LOCK cases.
+	 * DB_THREAD here in all cases.  For now, we turn it on later in this
+	 * function, and only when we're in testing and we specify the
+	 * -thread flag, so that we can exercise MUTEX_THREAD_LOCK cases.
 	 *
-	 * Historically, a key stumbling block was the log_get interface,
-	 * which could only do relative operations in a non-threaded
-	 * environment.  This is no longer an issue, thanks to log cursors,
-	 * but we need to look at making sure DBTCL_INFO structs
-	 * are safe to share across threads (they're not mutex-protected)
-	 * before we declare the Tcl interface thread-safe.  Meanwhile,
-	 * there's no strong reason to enable DB_THREAD.
+	 * In order to become truly thread-safe, we need to look at making sure
+	 * DBTCL_INFO structs are safe to share across threads (they're not
+	 * mutex-protected) before we declare the Tcl interface thread-safe.
+	 * Meanwhile, there's no strong reason to enable DB_THREAD when not
+	 * testing.
 	 */
-	open_flags = DB_JOINENV |
-#ifdef TEST_THREAD
-	    DB_THREAD;
-#else
-	    0;
-#endif
+	open_flags = DB_JOINENV;
+
 	logmaxset = logbufset = 0;
 
 	if (objc <= 2) {
@@ -510,8 +566,8 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
 			Tcl_ResetResult(interp);
 			continue;
 		}
+#ifdef CONFIG_TEST
 		switch ((enum envopen)optindex) {
-#if CONFIG_TEST
 		case ENV_SERVER:
 			if (i >= objc) {
 				Tcl_WrongNumArgs(interp, 2, objv,
@@ -519,6 +575,7 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
 				result = TCL_ERROR;
 				break;
 			}
+			FLD_SET(cr_flags, DB_RPCCLIENT);
 			server = Tcl_GetStringFromObj(objv[i++], NULL);
 			break;
 		case ENV_SERVER_TO:
@@ -528,6 +585,7 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
 				result = TCL_ERROR;
 				break;
 			}
+			FLD_SET(cr_flags, DB_RPCCLIENT);
 			result = Tcl_GetLongFromObj(interp, objv[i++],
 			    &server_to);
 			break;
@@ -538,19 +596,26 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
 				result = TCL_ERROR;
 				break;
 			}
+			FLD_SET(cr_flags, DB_RPCCLIENT);
 			result = Tcl_GetLongFromObj(interp, objv[i++],
 			    &client_to);
 			break;
-#endif
 		default:
 			break;
 		}
+#endif
 	}
+	if (result != TCL_OK)
+		return (TCL_ERROR);
+	ret = db_env_create(env, cr_flags);
+	if (ret)
+		return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "db_env_create"));
+	/*
+	 * From here on we must 'goto error' in order to clean up the
+	 * env from db_env_create.
+	 */
 	if (server != NULL) {
-		ret = db_env_create(env, DB_CLIENT);
-		if (ret)
-			return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret),
-			    "db_env_create"));
 		(*env)->set_errpfx((*env), ip->i_name);
 		(*env)->set_errcall((*env), _ErrorFunc);
 		if ((ret = (*env)->set_rpc_server((*env), NULL, server,
@@ -563,10 +628,6 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
 		 * Create the environment handle before parsing the args
 		 * since we'll be modifying the environment as we parse.
 		 */
-		ret = db_env_create(env, 0);
-		if (ret)
-			return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret),
-			    "db_env_create"));
 		(*env)->set_errpfx((*env), ip->i_name);
 		(*env)->set_errcall((*env), _ErrorFunc);
 	}
@@ -574,14 +635,6 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
 	/* Hang our info pointer on the env handle, so we can do callbacks. */
 	(*env)->app_private = ip;
 
-	/*
-	 * Use a Tcl-local alloc and free function so that we're sure to
-	 * test whether we use umalloc/ufree in the right places.
-	 */
-#ifdef TEST_ALLOC
-	(*env)->set_alloc(*env, tcl_db_malloc, tcl_db_realloc, tcl_db_free);
-#endif
-
 	/*
 	 * Get the command name index from the object based on the bdbcmds
 	 * defined above.
@@ -596,7 +649,7 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
 		}
 		i++;
 		switch ((enum envopen)optindex) {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 		case ENV_SERVER:
 		case ENV_SERVER_TO:
 		case ENV_CLIENT_TO:
@@ -605,6 +658,15 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
 			 */
 			i++;
 			break;
+		case ENV_ALLOC:
+			/*
+			 * Use a Tcl-local alloc and free function so that
+			 * we're sure to test whether we use umalloc/ufree in
+			 * the right places.
+			 */
+			(void)(*env)->set_alloc(*env,
+			    tcl_db_malloc, tcl_db_realloc, tcl_db_free);
+			break;
 		case ENV_AUTO_COMMIT:
 			FLD_SET(set_flags, DB_AUTO_COMMIT);
 			break;
@@ -650,8 +712,9 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
 				result = TCL_ERROR;
 				break;
 			}
-			size = sizeof(u_int8_t) * nmodes*nmodes;
-			ret = __os_malloc(*env, size, &conflicts);
+
+			ret = __os_malloc(*env, sizeof(u_int8_t) *
+			    (size_t)nmodes * (size_t)nmodes, &conflicts);
 			if (ret != 0) {
 				result = TCL_ERROR;
 				break;
@@ -686,6 +749,8 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
 				detect = DB_LOCK_EXPIRE;
 			else if (strcmp(arg, "maxlocks") == 0)
 				detect = DB_LOCK_MAXLOCKS;
+			else if (strcmp(arg, "maxwrites") == 0)
+				detect = DB_LOCK_MAXWRITE;
 			else if (strcmp(arg, "minlocks") == 0)
 				detect = DB_LOCK_MINLOCKS;
 			else if (strcmp(arg, "minwrites") == 0)
@@ -753,22 +818,23 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
 				result = TCL_ERROR;
 				break;
 			}
-			result = Tcl_GetLongFromObj(interp, objv[i++],
-			    (long *)&timestamp);
-			if (result == TCL_OK) {
-				_debug_check();
-				if (optindex == ENV_TXN_TIME)
-					ret = (*env)->
-					    set_tx_timestamp(*env, &timestamp);
-				else
-					ret = (*env)->set_timeout(*env,
-					    (db_timeout_t)timestamp,
-					    optindex == ENV_TXN_TIMEOUT ?
-					    DB_SET_TXN_TIMEOUT :
-					    DB_SET_LOCK_TIMEOUT);
-				result = _ReturnSetup(interp, ret,
-				    DB_RETOK_STD(ret), "txn_timestamp");
-			}
+
+			if ((result = Tcl_GetLongFromObj(
+			   interp, objv[i++], &v)) != TCL_OK)
+				break;
+			timestamp = (time_t)v;
+
+			_debug_check();
+			if ((enum envopen)optindex == ENV_TXN_TIME)
+				ret =
+				    (*env)->set_tx_timestamp(*env, &timestamp);
+			else
+				ret = (*env)->set_timeout(*env,
+				    (db_timeout_t)timestamp,
+				    (enum envopen)optindex == ENV_TXN_TIMEOUT ?
+				    DB_SET_TXN_TIMEOUT : DB_SET_LOCK_TIMEOUT);
+			result = _ReturnSetup(interp, ret,
+			    DB_RETOK_STD(ret), "txn_timestamp");
 			break;
 		case ENV_LOG:
 			FLD_SET(open_flags, DB_INIT_LOG | DB_INIT_MPOOL);
@@ -799,6 +865,9 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
 				}
 			}
 			break;
+		case ENV_LOG_INMEMORY:
+			FLD_SET(set_flags, DB_LOG_INMEMORY);
+			break;
 		case ENV_LOG_MAX:
 			if (i >= objc) {
 				Tcl_WrongNumArgs(interp, 2, objv,
@@ -832,10 +901,52 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
 					"log_regionmax");
 			}
 			break;
-		case ENV_MMAPSIZE:
+		case ENV_LOG_REMOVE:
+			FLD_SET(set_flags, DB_LOG_AUTOREMOVE);
+			break;
+		case ENV_MPOOL_MAX_OPENFD:
 			if (i >= objc) {
 				Tcl_WrongNumArgs(interp, 2, objv,
-				    "?-mmapsize size?");
+				    "?-mpool_max_openfd fd_count?");
+				result = TCL_ERROR;
+				break;
+			}
+			result = Tcl_GetIntFromObj(interp, objv[i++], &intarg);
+			if (result == TCL_OK) {
+				_debug_check();
+				ret = (*env)->set_mp_max_openfd(*env, intarg);
+				result = _ReturnSetup(interp, ret,
+				    DB_RETOK_STD(ret), "mpool_max_openfd");
+			}
+			break;
+		case ENV_MPOOL_MAX_WRITE:
+			result = Tcl_ListObjGetElements(interp, objv[i],
+			    &myobjc, &myobjv);
+			if (result == TCL_OK)
+				i++;
+			else
+				break;
+			if (myobjc != 2) {
+				Tcl_WrongNumArgs(interp, 2, objv,
+				    "?-mpool_max_write {nwrite nsleep}?");
+				result = TCL_ERROR;
+				break;
+			}
+			result = Tcl_GetIntFromObj(interp, myobjv[0], &intarg);
+			if (result != TCL_OK)
+				break;
+			result = Tcl_GetIntFromObj(interp, myobjv[1], &intarg2);
+			if (result != TCL_OK)
+				break;
+			_debug_check();
+			ret = (*env)->set_mp_max_write(*env, intarg, intarg2);
+			result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+			    "set_mp_max_write");
+			break;
+		case ENV_MPOOL_MMAP_SIZE:
+			if (i >= objc) {
+				Tcl_WrongNumArgs(interp, 2, objv,
+				    "?-mpool_mmap_size size?");
 				result = TCL_ERROR;
 				break;
 			}
@@ -845,10 +956,10 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
 				ret = (*env)->set_mp_mmapsize(*env,
 				    (size_t)intarg);
 				result = _ReturnSetup(interp, ret,
-				    DB_RETOK_STD(ret), "mmapsize");
+				    DB_RETOK_STD(ret), "mpool_mmap_size");
 			}
 			break;
-		case ENV_NOMMAP:
+		case ENV_MPOOL_NOMMAP:
 			FLD_SET(set_flags, DB_NOMMAP);
 			break;
 		case ENV_OVERWRITE:
@@ -860,14 +971,29 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
 			result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
 			    "region_init");
 			break;
+		case ENV_SET_INTERMEDIATE_DIR:
+			if (i >= objc) {
+				Tcl_WrongNumArgs(interp,
+				    2, objv, "?-set_intermediate_dir mode?");
+				result = TCL_ERROR;
+				break;
+			}
+			result = Tcl_GetIntFromObj(interp, objv[i++], &intarg);
+			if (result == TCL_OK) {
+				_debug_check();
+				ret = (*env)->
+				    set_intermediate_dir(*env, intarg, 0);
+				result = _ReturnSetup(interp, ret,
+				    DB_RETOK_STD(ret), "set_intermediate_dir");
+			}
+			break;
 		case ENV_REP_CLIENT:
 			rep_flags = DB_REP_CLIENT;
-			break;
-		case ENV_REP_LOGSONLY:
-			rep_flags = DB_REP_LOGSONLY;
+			FLD_SET(open_flags, DB_INIT_REP);
 			break;
 		case ENV_REP_MASTER:
 			rep_flags = DB_REP_MASTER;
+			FLD_SET(open_flags, DB_INIT_REP);
 			break;
 		case ENV_REP_TRANSPORT:
 			if (i >= objc) {
@@ -899,6 +1025,7 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
 				break;
 			}
 
+			FLD_SET(open_flags, DB_INIT_REP);
 			/*
 			 * Check that the machine ID is an int.  Note that
 			 * we do want to use GetIntFromObj;  the machine
@@ -919,6 +1046,13 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
 			result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
 			    "set_rep_transport");
 			break;
+		case ENV_THREAD:
+			/* Enable DB_THREAD when specified in testing. */
+			FLD_SET(open_flags, DB_THREAD);
+			break;
+		case ENV_TIME_NOTGRANTED:
+			FLD_SET(set_flags, DB_TIME_NOTGRANTED);
+			break;
 		case ENV_VERBOSE:
 			result = Tcl_ListObjGetElements(interp, objv[i],
 			    &myobjc, &myobjv);
@@ -1047,7 +1181,7 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
 			result = _GetUInt32(interp, myobjv[1], &bytes);
 			if (result != TCL_OK)
 				break;
-			result = _GetUInt32(interp, myobjv[2], &ncaches);
+			result = Tcl_GetIntFromObj(interp, myobjv[2], &ncaches);
 			if (result != TCL_OK)
 				break;
 			_debug_check();
@@ -1094,16 +1228,7 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
 				break;
 			}
 			arg = Tcl_GetStringFromObj(objv[i++], NULL);
-			/*
-			 * If the user already set one, close it.
-			 */
-			if (ip->i_err != NULL)
-				fclose(ip->i_err);
-			ip->i_err = fopen(arg, "a");
-			if (ip->i_err != NULL) {
-				_debug_check();
-				(*env)->set_errfile(*env, ip->i_err);
-			}
+			tcl_EnvSetErrfile(interp, *env, ip, arg);
 			break;
 		case ENV_ERRPFX:
 			if (i >= objc) {
@@ -1113,21 +1238,8 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
 				break;
 			}
 			arg = Tcl_GetStringFromObj(objv[i++], NULL);
-			/*
-			 * If the user already set one, free it.
-			 */
-			if (ip->i_errpfx != NULL)
-				__os_free(NULL, ip->i_errpfx);
-			if ((ret =
-			    __os_strdup(*env, arg, &ip->i_errpfx)) != 0) {
-				result = _ReturnSetup(interp, ret,
-				    DB_RETOK_STD(ret), "__os_strdup");
-				break;
-			}
-			if (ip->i_errpfx != NULL) {
-				_debug_check();
-				(*env)->set_errpfx(*env, ip->i_errpfx);
-			}
+			_debug_check();
+			result = tcl_EnvSetErrpfx(interp, *env, ip, arg);
 			break;
 		case ENV_DATA_DIR:
 			if (i >= objc) {
@@ -1226,8 +1338,8 @@ bdb_EnvOpen(interp, objc, objv, ip, env)
 	}
 
 error:	if (result == TCL_ERROR) {
-		if (ip->i_err) {
-			fclose(ip->i_err);
+		if (ip->i_err && ip->i_err != stdout && ip->i_err != stderr) {
+			(void)fclose(ip->i_err);
 			ip->i_err = NULL;
 		}
 		(void)(*env)->close(*env, 0);
@@ -1257,14 +1369,14 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
 	DBTCL_INFO *ip;			/* Our internal info */
 	DB **dbp;			/* DB handle */
 {
-	static char *bdbenvopen[] = {
+	static const char *bdbenvopen[] = {
 		"-env",	NULL
 	};
 	enum bdbenvopen {
 		TCL_DB_ENV0
 	};
-	static char *bdbopen[] = {
-#if CONFIG_TEST
+	static const char *bdbopen[] = {
+#ifdef CONFIG_TEST
 		"-btcompare",
 		"-dirty",
 		"-dupcompare",
@@ -1272,8 +1384,10 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
 		"-lorder",
 		"-minkey",
 		"-nommap",
+		"-notdurable",
 		"-revsplitoff",
 		"-test",
+		"-thread",
 #endif
 		"-auto_commit",
 		"-btree",
@@ -1293,7 +1407,9 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
 		"-extent",
 		"-ffactor",
 		"-hash",
+		"-inorder",
 		"-len",
+		"-maxsize",
 		"-mode",
 		"-nelem",
 		"-pad",
@@ -1312,7 +1428,7 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
 		NULL
 	};
 	enum bdbopen {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 		TCL_DB_BTCOMPARE,
 		TCL_DB_DIRTY,
 		TCL_DB_DUPCOMPARE,
@@ -1320,8 +1436,10 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
 		TCL_DB_LORDER,
 		TCL_DB_MINKEY,
 		TCL_DB_NOMMAP,
+		TCL_DB_NOTDURABLE,
 		TCL_DB_REVSPLIT,
 		TCL_DB_TEST,
+		TCL_DB_THREAD,
 #endif
 		TCL_DB_AUTO_COMMIT,
 		TCL_DB_BTREE,
@@ -1341,7 +1459,9 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
 		TCL_DB_EXTENT,
 		TCL_DB_FFACTOR,
 		TCL_DB_HASH,
+		TCL_DB_INORDER,
 		TCL_DB_LEN,
+		TCL_DB_MAXSIZE,
 		TCL_DB_MODE,
 		TCL_DB_NELEM,
 		TCL_DB_PAD,
@@ -1364,9 +1484,9 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
 	DBTYPE type;
 	DB_ENV *envp;
 	Tcl_Obj **myobjv;
-	u_int32_t gbytes, bytes, ncaches, open_flags, uintarg;
-	int endarg, i, intarg, mode, myobjc;
-	int optindex, result, ret, set_err, set_flags, set_pfx, subdblen;
+	u_int32_t gbytes, bytes, open_flags, set_flags, uintarg;
+	int endarg, i, intarg, mode, myobjc, ncaches;
+	int optindex, result, ret, set_err, set_pfx, subdblen;
 	u_char *subdbtmp;
 	char *arg, *db, *passwd, *subdb, msg[MSG_SIZE];
 
@@ -1379,16 +1499,18 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
 	/*
 	 * XXX
 	 * If/when our Tcl interface becomes thread-safe, we should enable
-	 * DB_THREAD here in all cases.  See comment in bdb_EnvOpen().
-	 * For now, just turn it on when testing so that we exercise
-	 * MUTEX_THREAD_LOCK cases.
+	 * DB_THREAD here in all cases.  For now, we turn it on later in this
+	 * function, and only when we're in testing and we specify the
+	 * -thread flag, so that we can exercise MUTEX_THREAD_LOCK cases.
+	 *
+	 * In order to become truly thread-safe, we need to look at making sure
+	 * DBTCL_INFO structs are safe to share across threads (they're not
+	 * mutex-protected) before we declare the Tcl interface thread-safe.
+	 * Meanwhile, there's no strong reason to enable DB_THREAD when not
+	 * testing.
 	 */
-	open_flags =
-#ifdef TEST_THREAD
-	    DB_THREAD;
-#else
-	    0;
-#endif
+	open_flags = 0;
+
 	envp = NULL;
 	txn = NULL;
 
@@ -1479,7 +1601,7 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
 		}
 		i++;
 		switch ((enum bdbopen)optindex) {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 		case TCL_DB_BTCOMPARE:
 			if (i >= objc) {
 				Tcl_WrongNumArgs(interp, 2, objv,
@@ -1550,10 +1672,10 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
 				result = TCL_ERROR;
 				break;
 			}
-			result = _GetUInt32(interp, objv[i++], &uintarg);
+			result = Tcl_GetIntFromObj(interp, objv[i++], &intarg);
 			if (result == TCL_OK) {
 				_debug_check();
-				ret = (*dbp)->set_lorder(*dbp, uintarg);
+				ret = (*dbp)->set_lorder(*dbp, intarg);
 				result = _ReturnSetup(interp, ret,
 				    DB_RETOK_STD(ret), "set_lorder");
 			}
@@ -1576,11 +1698,20 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
 		case TCL_DB_NOMMAP:
 			open_flags |= DB_NOMMAP;
 			break;
+		case TCL_DB_NOTDURABLE:
+			set_flags |= DB_TXN_NOT_DURABLE;
+			break;
 		case TCL_DB_REVSPLIT:
 			set_flags |= DB_REVSPLITOFF;
 			break;
 		case TCL_DB_TEST:
-			(*dbp)->set_h_hash(*dbp, __ham_test);
+			ret = (*dbp)->set_h_hash(*dbp, __ham_test);
+			result = _ReturnSetup(interp, ret,
+			    DB_RETOK_STD(ret), "set_h_hash");
+			break;
+		case TCL_DB_THREAD:
+			/* Enable DB_THREAD when specified in testing. */
+			open_flags |= DB_THREAD;
 			break;
 #endif
 		case TCL_DB_AUTO_COMMIT:
@@ -1602,7 +1733,7 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
 			txn = NAME_TO_TXN(arg);
 			if (txn == NULL) {
 				snprintf(msg, MSG_SIZE,
-				    "Put: Invalid txn: %s\n", arg);
+				    "Open: Invalid txn: %s\n", arg);
 				Tcl_SetResult(interp, msg, TCL_VOLATILE);
 				result = TCL_ERROR;
 			}
@@ -1684,6 +1815,9 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
 		case TCL_DB_DUPSORT:
 			set_flags |= DB_DUPSORT;
 			break;
+		case TCL_DB_INORDER:
+			set_flags |= DB_INORDER;
+			break;
 		case TCL_DB_RECNUM:
 			set_flags |= DB_RECNUM;
 			break;
@@ -1694,7 +1828,7 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
 			set_flags |= DB_SNAPSHOT;
 			break;
 		case TCL_DB_CHKSUM:
-			set_flags |= DB_CHKSUM_SHA1;
+			set_flags |= DB_CHKSUM;
 			break;
 		case TCL_DB_ENCRYPT:
 			set_flags |= DB_ENCRYPT;
@@ -1787,6 +1921,22 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
 				    DB_RETOK_STD(ret), "set_re_len");
 			}
 			break;
+		case TCL_DB_MAXSIZE:
+			if (i >= objc) {
+				Tcl_WrongNumArgs(interp, 2, objv,
+				    "-len length");
+				result = TCL_ERROR;
+				break;
+			}
+			result = _GetUInt32(interp, objv[i++], &uintarg);
+			if (result == TCL_OK) {
+				_debug_check();
+				ret = (*dbp)->mpf->set_maxsize(
+				    (*dbp)->mpf, 0, uintarg);
+				result = _ReturnSetup(interp, ret,
+				    DB_RETOK_STD(ret), "set_re_len");
+			}
+			break;
 		case TCL_DB_PAD:
 			if (i >= objc) {
 				Tcl_WrongNumArgs(interp, 2, objv,
@@ -1847,7 +1997,7 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
 			result = _GetUInt32(interp, myobjv[1], &bytes);
 			if (result != TCL_OK)
 				break;
-			result = _GetUInt32(interp, myobjv[2], &ncaches);
+			result = Tcl_GetIntFromObj(interp, myobjv[2], &ncaches);
 			if (result != TCL_OK)
 				break;
 			_debug_check();
@@ -1883,9 +2033,15 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
 			/*
 			 * If the user already set one, close it.
 			 */
-			if (errip->i_err != NULL)
-				fclose(errip->i_err);
-			errip->i_err = fopen(arg, "a");
+			if (errip->i_err != NULL &&
+			    errip->i_err != stdout && errip->i_err != stderr)
+				(void)fclose(errip->i_err);
+			if (strcmp(arg, "/dev/stdout") == 0)
+				errip->i_err = stdout;
+			else if (strcmp(arg, "/dev/stderr") == 0)
+				errip->i_err = stderr;
+			else
+				errip->i_err = fopen(arg, "a");
 			if (errip->i_err != NULL) {
 				_debug_check();
 				(*dbp)->set_errfile(*dbp, errip->i_err);
@@ -1950,12 +2106,12 @@ bdb_DbOpen(interp, objc, objv, ip, dbp)
 			subdbtmp =
 			    Tcl_GetByteArrayFromObj(objv[i++], &subdblen);
 			if ((ret = __os_malloc(envp,
-			   subdblen + 1, &subdb)) != 0) {
+			   (size_t)subdblen + 1, &subdb)) != 0) {
 				Tcl_SetResult(interp, db_strerror(ret),
 				    TCL_STATIC);
 				return (0);
 			}
-			memcpy(subdb, subdbtmp, subdblen);
+			memcpy(subdb, subdbtmp, (size_t)subdblen);
 			subdb[subdblen] = '\0';
 		}
 	}
@@ -1999,8 +2155,9 @@ error:
 		 * if (ip->i_err)
 		 *	fclose(ip->i_err);
 		 */
-		if (set_err && errip && errip->i_err != NULL) {
-			fclose(errip->i_err);
+		if (set_err && errip && errip->i_err != NULL &&
+		    errip->i_err != stdout && errip->i_err != stderr) {
+			(void)fclose(errip->i_err);
 			errip->i_err = NULL;
 		}
 		if (set_pfx && errip && errip->i_errpfx != NULL) {
@@ -2012,6 +2169,245 @@ error:
 	return (result);
 }
 
+#ifdef HAVE_SEQUENCE
+/*
+ * bdb_SeqOpen --
+ *	Implements the "Seq_create/Seq_open" command.
+ */
+static int
+bdb_SeqOpen(interp, objc, objv, ip, seqp)
+	Tcl_Interp *interp;		/* Interpreter */
+	int objc;			/* How many arguments? */
+	Tcl_Obj *CONST objv[];		/* The argument objects */
+	DBTCL_INFO *ip;			/* Our internal info */
+	DB_SEQUENCE **seqp;		/* DB_SEQUENCE handle */
+{
+	static const char *seqopen[] = {
+		"-auto_commit",
+		"-cachesize",
+		"-create",
+		"-inc",
+		"-init",
+		"-dec",
+		"-max",
+		"-min",
+		"-txn",
+		"-wrap",
+		"--",
+		NULL
+	} ;
+	enum seqopen {
+		TCL_SEQ_AUTO_COMMIT,
+		TCL_SEQ_CACHESIZE,
+		TCL_SEQ_CREATE,
+		TCL_SEQ_INC,
+		TCL_SEQ_INIT,
+		TCL_SEQ_DEC,
+		TCL_SEQ_MAX,
+		TCL_SEQ_MIN,
+		TCL_SEQ_TXN,
+		TCL_SEQ_WRAP,
+		TCL_SEQ_ENDARG
+	};
+	DB *dbp;
+	DBT key;
+	DBTYPE type;
+	DB_TXN *txn;
+	db_recno_t recno;
+	db_seq_t min, max, value;
+	u_int32_t flags, oflags;
+	int cache, endarg, i, optindex, result, ret, setrange, setvalue, v;
+	char *arg, *db, msg[MSG_SIZE];
+
+	COMPQUIET(ip, NULL);
+	COMPQUIET(value, 0);
+
+	if (objc < 2) {
+		Tcl_WrongNumArgs(interp, 2, objv, "?args?");
+		return (TCL_ERROR);
+	}
+
+	txn = NULL;
+	endarg = 0;
+	flags = oflags = 0;
+	setrange = setvalue = 0;
+	min = INT64_MIN;
+	max = INT64_MAX;
+	cache = 0;
+
+	for (i = 2; i < objc;) {
+		Tcl_ResetResult(interp);
+		if (Tcl_GetIndexFromObj(interp, objv[i], seqopen, "option",
+		    TCL_EXACT, &optindex) != TCL_OK) {
+			arg = Tcl_GetStringFromObj(objv[i], NULL);
+			if (arg[0] == '-') {
+				result = IS_HELP(objv[i]);
+				goto error;
+			} else
+				Tcl_ResetResult(interp);
+			break;
+		}
+		i++;
+		result = TCL_OK;
+		switch ((enum seqopen)optindex) {
+		case TCL_SEQ_AUTO_COMMIT:
+			oflags |= DB_AUTO_COMMIT;
+			break;
+		case TCL_SEQ_CREATE:
+			oflags |= DB_CREATE;
+			break;
+		case TCL_SEQ_INC:
+			LF_SET(DB_SEQ_INC);
+			break;
+		case TCL_SEQ_CACHESIZE:
+			if (i >= objc) {
+				Tcl_WrongNumArgs(interp, 2, objv,
+				    "?-cachesize value?");
+				result = TCL_ERROR;
+				break;
+			}
+			result = Tcl_GetIntFromObj(interp, objv[i++], &cache);
+			break;
+		case TCL_SEQ_INIT:
+			if (i >= objc) {
+				Tcl_WrongNumArgs(interp, 2, objv,
+				    "?-init value?");
+				result = TCL_ERROR;
+				break;
+			}
+			result =
+			     Tcl_GetWideIntFromObj(interp, objv[i++], &value);
+			setvalue = 1;
+			break;
+		case TCL_SEQ_DEC:
+			LF_SET(DB_SEQ_DEC);
+			break;
+		case TCL_SEQ_MAX:
+			if (i >= objc) {
+				Tcl_WrongNumArgs(interp, 2, objv,
+				    "?-max value?");
+				result = TCL_ERROR;
+				break;
+			}
+			if ((result =
+			     Tcl_GetWideIntFromObj(interp,
+			     objv[i++], &max)) != TCL_OK)
+				goto error;
+			setrange = 1;
+			break;
+		case TCL_SEQ_MIN:
+			if (i >= objc) {
+				Tcl_WrongNumArgs(interp, 2, objv,
+				    "?-min value?");
+				result = TCL_ERROR;
+				break;
+			}
+			if ((result =
+			     Tcl_GetWideIntFromObj(interp,
+			     objv[i++], &min)) != TCL_OK)
+				goto error;
+			setrange = 1;
+			break;
+		case TCL_SEQ_TXN:
+			if (i > (objc - 1)) {
+				Tcl_WrongNumArgs(interp, 2, objv, "?-txn id?");
+				result = TCL_ERROR;
+				break;
+			}
+			arg = Tcl_GetStringFromObj(objv[i++], NULL);
+			txn = NAME_TO_TXN(arg);
+			if (txn == NULL) {
+				snprintf(msg, MSG_SIZE,
+				    "Sequence: Invalid txn: %s\n", arg);
+				Tcl_SetResult(interp, msg, TCL_VOLATILE);
+				result = TCL_ERROR;
+			}
+			break;
+		case TCL_SEQ_WRAP:
+			LF_SET(DB_SEQ_WRAP);
+			break;
+		case TCL_SEQ_ENDARG:
+			endarg = 1;
+			break;
+		}
+		/*
+		 * If, at any time, parsing the args we get an error,
+		 * bail out and return.
+		 */
+		if (result != TCL_OK)
+			goto error;
+		if (endarg)
+			break;
+	}
+
+	if (objc - i != 2) {
+		Tcl_WrongNumArgs(interp, 2, objv, "?args?");
+		return (TCL_ERROR);
+	}
+	/*
+	 * The db must be a string but the sequence key may
+	 * be anything.
+	 */
+	db = Tcl_GetStringFromObj(objv[i++], NULL);
+	if ((dbp = NAME_TO_DB(db)) == NULL) {
+		Tcl_SetResult(interp, "No such dbp", TCL_STATIC);
+		return (TCL_ERROR);
+	}
+	(void)dbp->get_type(dbp, &type);
+
+	memset(&key, 0, sizeof(key));
+	if (type == DB_QUEUE || type == DB_RECNO) {
+		result = _GetUInt32(interp, objv[i++], &recno);
+		if (result != TCL_OK)
+			return (result);
+		key.data = &recno;
+		key.size = sizeof(recno);
+	} else {
+		key.data = Tcl_GetByteArrayFromObj(objv[i++], &v);
+		key.size = (u_int32_t)v;
+	}
+	ret = db_sequence_create(seqp, dbp, 0);
+	if ((result = _ReturnSetup(interp,
+	    ret, DB_RETOK_STD(ret), "sequence create")) != TCL_OK) {
+		*seqp = NULL;
+		return (result);
+	}
+
+	ret = (*seqp)->set_flags(*seqp, flags);
+	if ((result = _ReturnSetup(interp,
+	    ret, DB_RETOK_STD(ret), "sequence set_flags")) != TCL_OK)
+		goto error;
+	if (setrange) {
+		ret = (*seqp)->set_range(*seqp, min, max);
+		if ((result = _ReturnSetup(interp,
+		    ret, DB_RETOK_STD(ret), "sequence set_range")) != TCL_OK)
+			goto error;
+	}
+	if (cache) {
+		ret = (*seqp)->set_cachesize(*seqp, cache);
+		if ((result = _ReturnSetup(interp,
+		    ret, DB_RETOK_STD(ret), "sequence cachesize")) != TCL_OK)
+			goto error;
+	}
+	if (setvalue) {
+		ret = (*seqp)->initial_value(*seqp, value);
+		if ((result = _ReturnSetup(interp,
+		    ret, DB_RETOK_STD(ret), "sequence init")) != TCL_OK)
+			goto error;
+	}
+	ret = (*seqp)->open(*seqp, txn, &key, oflags);
+	if ((result = _ReturnSetup(interp,
+	    ret, DB_RETOK_STD(ret), "sequence open")) != TCL_OK)
+		goto error;
+
+	if (0) {
+error:		(void)(*seqp)->close(*seqp, 0);
+		*seqp = NULL;
+	}
+	return (result);
+}
+#endif
+
 /*
  * bdb_DbRemove --
  *	Implements the DB_ENV->remove and DB->remove command.
@@ -2022,7 +2418,7 @@ bdb_DbRemove(interp, objc, objv)
 	int objc;			/* How many arguments? */
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 {
-	static char *bdbrem[] = {
+	static const char *bdbrem[] = {
 		"-auto_commit",
 		"-encrypt",
 		"-encryptaes",
@@ -2166,12 +2562,12 @@ bdb_DbRemove(interp, objc, objv)
 		if (i != objc) {
 			subdbtmp =
 			    Tcl_GetByteArrayFromObj(objv[i++], &subdblen);
-			if ((ret = __os_malloc(envp, subdblen + 1,
+			if ((ret = __os_malloc(envp, (size_t)subdblen + 1,
 			    &subdb)) != 0) { Tcl_SetResult(interp,
 				    db_strerror(ret), TCL_STATIC);
 				return (0);
 			}
-			memcpy(subdb, subdbtmp, subdblen);
+			memcpy(subdb, subdbtmp, (size_t)subdblen);
 			subdb[subdblen] = '\0';
 		}
 	} else {
@@ -2200,7 +2596,7 @@ bdb_DbRemove(interp, objc, objv)
 	}
 
 	/*
-	 * No matter what, we NULL out dbp after this call.
+	 * The dbremove method is a destructor, NULL out the dbp.
 	 */
 	_debug_check();
 	if (dbp == NULL)
@@ -2220,7 +2616,7 @@ error:
 
 /*
  * bdb_DbRename --
- *	Implements the DBENV->dbrename and DB->rename commands.
+ *	Implements the DB_ENV->dbrename and DB->rename commands.
  */
 static int
 bdb_DbRename(interp, objc, objv)
@@ -2228,7 +2624,7 @@ bdb_DbRename(interp, objc, objv)
 	int objc;			/* How many arguments? */
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 {
-	static char *bdbmv[] = {
+	static const char *bdbmv[] = {
 		"-auto_commit",
 		"-encrypt",
 		"-encryptaes",
@@ -2373,24 +2769,24 @@ bdb_DbRename(interp, objc, objv)
 		if (i == objc - 2) {
 			subdbtmp =
 			    Tcl_GetByteArrayFromObj(objv[i++], &subdblen);
-			if ((ret = __os_malloc(envp, subdblen + 1,
+			if ((ret = __os_malloc(envp, (size_t)subdblen + 1,
 			    &subdb)) != 0) {
 				Tcl_SetResult(interp,
 				    db_strerror(ret), TCL_STATIC);
 				return (0);
 			}
-			memcpy(subdb, subdbtmp, subdblen);
+			memcpy(subdb, subdbtmp, (size_t)subdblen);
 			subdb[subdblen] = '\0';
 		}
 		subdbtmp =
 		    Tcl_GetByteArrayFromObj(objv[i++], &newlen);
-		if ((ret = __os_malloc(envp, newlen + 1,
+		if ((ret = __os_malloc(envp, (size_t)newlen + 1,
 		    &newname)) != 0) {
 			Tcl_SetResult(interp,
 			    db_strerror(ret), TCL_STATIC);
 			return (0);
 		}
-		memcpy(newname, subdbtmp, newlen);
+		memcpy(newname, subdbtmp, (size_t)newlen);
 		newname[newlen] = '\0';
 	} else {
 		Tcl_WrongNumArgs(
@@ -2418,8 +2814,9 @@ bdb_DbRename(interp, objc, objv)
 	}
 
 	/*
-	 * No matter what, we NULL out dbp after this call.
+	 * The dbrename method is a destructor, NULL out the dbp.
 	 */
+	_debug_check();
 	if (dbp == NULL)
 		ret = envp->dbrename(envp, txn, db, subdb, newname, iflags);
 	else
@@ -2436,7 +2833,7 @@ error:
 	return (result);
 }
 
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 /*
  * bdb_DbVerify --
  *	Implements the DB->verify command.
@@ -2447,13 +2844,14 @@ bdb_DbVerify(interp, objc, objv)
 	int objc;			/* How many arguments? */
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 {
-	static char *bdbverify[] = {
+	static const char *bdbverify[] = {
 		"-encrypt",
 		"-encryptaes",
 		"-encryptany",
 		"-env",
 		"-errfile",
 		"-errpfx",
+		"-unref",
 		"--",
 		NULL
 	};
@@ -2464,6 +2862,7 @@ bdb_DbVerify(interp, objc, objv)
 		TCL_DBVRFY_ENV,
 		TCL_DBVRFY_ERRFILE,
 		TCL_DBVRFY_ERRPFX,
+		TCL_DBVRFY_UNREF,
 		TCL_DBVRFY_ENDARG
 	};
 	DB_ENV *envp;
@@ -2553,9 +2952,14 @@ bdb_DbVerify(interp, objc, objv)
 			/*
 			 * If the user already set one, close it.
 			 */
-			if (errf != NULL)
-				fclose(errf);
-			errf = fopen(arg, "a");
+			if (errf != NULL && errf != stdout && errf != stderr)
+				(void)fclose(errf);
+			if (strcmp(arg, "/dev/stdout") == 0)
+				errf = stdout;
+			else if (strcmp(arg, "/dev/stderr") == 0)
+				errf = stderr;
+			else
+				errf = fopen(arg, "a");
 			break;
 		case TCL_DBVRFY_ERRPFX:
 			if (i >= objc) {
@@ -2576,6 +2980,9 @@ bdb_DbVerify(interp, objc, objv)
 				break;
 			}
 			break;
+		case TCL_DBVRFY_UNREF:
+			flags |= DB_UNREF;
+			break;
 		case TCL_DBVRFY_ENDARG:
 			endarg = 1;
 			break;
@@ -2624,11 +3031,15 @@ bdb_DbVerify(interp, objc, objv)
 	if (errpfx != NULL)
 		dbp->set_errpfx(dbp, errpfx);
 
+	/*
+	 * The verify method is a destructor, NULL out the dbp.
+	 */
 	ret = dbp->verify(dbp, db, NULL, NULL, flags);
 	result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "db verify");
+	dbp = NULL;
 error:
-	if (errf != NULL)
-		fclose(errf);
+	if (errf != NULL && errf != stdout && errf != stderr)
+		(void)fclose(errf);
 	if (errpfx != NULL)
 		__os_free(envp, errpfx);
 	if (dbp)
@@ -2647,7 +3058,7 @@ bdb_Version(interp, objc, objv)
 	int objc;			/* How many arguments? */
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 {
-	static char *bdbver[] = {
+	static const char *bdbver[] = {
 		"-string", NULL
 	};
 	enum bdbver {
@@ -2699,7 +3110,7 @@ bdb_Version(interp, objc, objv)
 
 	v = db_version(&maj, &min, &patch);
 	if (string)
-		res = Tcl_NewStringObj(v, strlen(v));
+		res = NewStringObj(v, strlen(v));
 	else {
 		verobjc = 3;
 		verobjv[0] = Tcl_NewIntObj(maj);
@@ -2712,7 +3123,7 @@ error:
 	return (result);
 }
 
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 /*
  * bdb_Handles --
  *	Implements the handles command.
@@ -2737,16 +3148,66 @@ bdb_Handles(interp, objc, objv)
 
 	for (p = LIST_FIRST(&__db_infohead); p != NULL;
 	    p = LIST_NEXT(p, entries)) {
-		handle = Tcl_NewStringObj(p->i_name, strlen(p->i_name));
+		handle = NewStringObj(p->i_name, strlen(p->i_name));
 		if (Tcl_ListObjAppendElement(interp, res, handle) != TCL_OK)
 			return (TCL_ERROR);
 	}
 	Tcl_SetObjResult(interp, res);
 	return (TCL_OK);
 }
-#endif
 
-#if CONFIG_TEST
+/*
+ * bdb_MsgType -
+ *	Implements the msgtype command.
+ *	Given a replication message return its message type name.
+ */
+static int
+bdb_MsgType(interp, objc, objv)
+	Tcl_Interp *interp;		/* Interpreter */
+	int objc;			/* How many arguments? */
+	Tcl_Obj *CONST objv[];		/* The argument objects */
+{
+	REP_CONTROL *rp;
+	Tcl_Obj *msgname;
+	u_int32_t len, msgtype;
+	int freerp, ret;
+
+	/*
+	 * If the messages in rep.h change, this must change too!
+	 * Add "no_type" for 0 so that we directly index.
+	 */
+	static const char *msgnames[] = {
+		"no_type", "alive", "alive_req", "all_req",
+		"dupmaster", "file", "file_fail", "file_req", "log",
+		"log_more", "log_req", "master_req", "newclient",
+		"newfile", "newmaster", "newsite", "page",
+		"page_fail", "page_req", "update", "update_req",
+		"verify", "verify_fail", "verify_req",
+		"vote1", "vote2", NULL
+	};
+
+	/*
+	 * 1 arg, the message.  Error if different.
+	 */
+	if (objc != 3) {
+		Tcl_WrongNumArgs(interp, 3, objv, "msgtype msg");
+		return (TCL_ERROR);
+	}
+
+	ret = _CopyObjBytes(interp, objv[2], (void **)&rp, &len, &freerp);
+	if (ret != TCL_OK) {
+		Tcl_SetResult(interp,
+		    "msgtype: bad control message", TCL_STATIC);
+		return (TCL_ERROR);
+	}
+	msgtype = rp->rectype;
+	msgname = NewStringObj(msgnames[msgtype], strlen(msgnames[msgtype]));
+	Tcl_SetObjResult(interp, msgname);
+	if (rp != NULL && freerp)
+		__os_free(NULL, rp);
+	return (TCL_OK);
+}
+
 /*
  * bdb_DbUpgrade --
  *	Implements the DB->upgrade command.
@@ -2757,7 +3218,7 @@ bdb_DbUpgrade(interp, objc, objv)
 	int objc;			/* How many arguments? */
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 {
-	static char *bdbupg[] = {
+	static const char *bdbupg[] = {
 		"-dupsort", "-env", "--", NULL
 	};
 	enum bdbupg {
@@ -2848,7 +3309,6 @@ error:
 		(void)dbp->close(dbp, 0);
 	return (result);
 }
-#endif
 
 /*
  * tcl_bt_compare and tcl_dup_compare --
@@ -2902,9 +3362,9 @@ tcl_compare_callback(dbp, dbta, dbtb, procobj, errname)
 	 * This will involve a copy, which is unpleasantly slow, but there's
 	 * little we can do to avoid this (I think).
 	 */
-	a = Tcl_NewByteArrayObj(dbta->data, dbta->size);
+	a = Tcl_NewByteArrayObj(dbta->data, (int)dbta->size);
 	Tcl_IncrRefCount(a);
-	b = Tcl_NewByteArrayObj(dbtb->data, dbtb->size);
+	b = Tcl_NewByteArrayObj(dbtb->data, (int)dbtb->size);
 	Tcl_IncrRefCount(b);
 
 	objv[1] = a;
@@ -2966,26 +3426,30 @@ tcl_h_hash(dbp, buf, len)
 	/*
 	 * Create a ByteArray for the buffer.
 	 */
-	objv[1] = Tcl_NewByteArrayObj((void *)buf, len);
+	objv[1] = Tcl_NewByteArrayObj((void *)buf, (int)len);
 	Tcl_IncrRefCount(objv[1]);
 	result = Tcl_EvalObjv(interp, 2, objv, 0);
-	if (result != TCL_OK) {
-		/*
-		 * XXX
-		 * We drop core on error.  See the comment in
-		 * tcl_compare_callback.
-		 */
-panic:		__db_err(dbp->dbenv, "Tcl h_hash callback failed");
-		DB_ASSERT(0);
-		return (__db_panic(dbp->dbenv, DB_RUNRECOVERY));
-	}
+	if (result != TCL_OK)
+		goto panic;
 
 	result = Tcl_GetIntFromObj(interp, Tcl_GetObjResult(interp), &hval);
 	if (result != TCL_OK)
 		goto panic;
 
 	Tcl_DecrRefCount(objv[1]);
-	return (hval);
+	return ((u_int32_t)hval);
+
+panic:	/*
+	 * We drop core on error, in diagnostic mode.  See the comment in
+	 * tcl_compare_callback.
+	 */
+	__db_err(dbp->dbenv, "Tcl h_hash callback failed");
+	(void)__db_panic(dbp->dbenv, DB_RUNRECOVERY);
+
+	DB_ASSERT(0);
+
+	/* NOTREACHED */
+	return (0);
 }
 
 /*
@@ -2993,36 +3457,52 @@ panic:		__db_err(dbp->dbenv, "Tcl h_hash callback failed");
  *	Replication send callback.
  */
 static int
-tcl_rep_send(dbenv, control, rec, eid, flags)
+tcl_rep_send(dbenv, control, rec, lsnp, eid, flags)
 	DB_ENV *dbenv;
 	const DBT *control, *rec;
+	const DB_LSN *lsnp;
 	int eid;
 	u_int32_t flags;
 {
+#define	TCLDB_SENDITEMS	7
 	DBTCL_INFO *ip;
 	Tcl_Interp *interp;
-	Tcl_Obj *control_o, *eid_o, *origobj, *rec_o, *resobj, *objv[5];
-	int result, ret;
-
-	COMPQUIET(flags, 0);
+	Tcl_Obj *control_o, *eid_o, *flags_o, *lsn_o, *origobj, *rec_o;
+	Tcl_Obj *myobjv[2], *resobj, *objv[TCLDB_SENDITEMS];
+	int myobjc, result, ret;
 
 	ip = (DBTCL_INFO *)dbenv->app_private;
 	interp = ip->i_interp;
 	objv[0] = ip->i_rep_send;
 
-	control_o = Tcl_NewByteArrayObj(control->data, control->size);
+	control_o = Tcl_NewByteArrayObj(control->data, (int)control->size);
 	Tcl_IncrRefCount(control_o);
 
-	rec_o = Tcl_NewByteArrayObj(rec->data, rec->size);
+	rec_o = Tcl_NewByteArrayObj(rec->data, (int)rec->size);
 	Tcl_IncrRefCount(rec_o);
 
 	eid_o = Tcl_NewIntObj(eid);
 	Tcl_IncrRefCount(eid_o);
 
+	if (LF_ISSET(DB_REP_PERMANENT))
+		flags_o = NewStringObj("perm", strlen("perm"));
+	else if (LF_ISSET(DB_REP_NOBUFFER))
+		flags_o = NewStringObj("nobuffer", strlen("nobuffer"));
+	else
+		flags_o = NewStringObj("none", strlen("none"));
+	Tcl_IncrRefCount(flags_o);
+
+	myobjc = 2;
+	myobjv[0] = Tcl_NewLongObj((long)lsnp->file);
+	myobjv[1] = Tcl_NewLongObj((long)lsnp->offset);
+	lsn_o = Tcl_NewListObj(myobjc, myobjv);
+
 	objv[1] = control_o;
 	objv[2] = rec_o;
 	objv[3] = ip->i_rep_eid;	/* From ID */
 	objv[4] = eid_o;		/* To ID */
+	objv[5] = flags_o;		/* Flags */
+	objv[6] = lsn_o;		/* LSN */
 
 	/*
 	 * We really want to return the original result to the
@@ -3032,7 +3512,7 @@ tcl_rep_send(dbenv, control, rec, eid, flags)
 	 */
 	origobj = Tcl_GetObjResult(interp);
 	Tcl_IncrRefCount(origobj);
-	result = Tcl_EvalObjv(interp, 5, objv, 0);
+	result = Tcl_EvalObjv(interp, TCLDB_SENDITEMS, objv, 0);
 	if (result != TCL_OK) {
 		/*
 		 * XXX
@@ -3054,11 +3534,13 @@ err:		__db_err(dbenv, "Tcl rep_send failure");
 	Tcl_DecrRefCount(control_o);
 	Tcl_DecrRefCount(rec_o);
 	Tcl_DecrRefCount(eid_o);
+	Tcl_DecrRefCount(flags_o);
 
 	return (ret);
 }
+#endif
 
-#ifdef TEST_ALLOC
+#ifdef CONFIG_TEST
 /*
  * tcl_db_malloc, tcl_db_realloc, tcl_db_free --
  *	Tcl-local malloc, realloc, and free functions to use for user data
@@ -3077,7 +3559,7 @@ tcl_db_malloc(size)
 		return (NULL);
 	Tcl_IncrRefCount(obj);
 
-	Tcl_SetObjLength(obj, size + sizeof(Tcl_Obj *));
+	Tcl_SetObjLength(obj, (int)(size + sizeof(Tcl_Obj *)));
 	buf = Tcl_GetString(obj);
 	memcpy(buf, &obj, sizeof(&obj));
 
@@ -3096,7 +3578,7 @@ tcl_db_realloc(ptr, size)
 		return (tcl_db_malloc(size));
 
 	obj = *(Tcl_Obj **)((Tcl_Obj **)ptr - 1);
-	Tcl_SetObjLength(obj, size + sizeof(Tcl_Obj *));
+	Tcl_SetObjLength(obj, (int)(size + sizeof(Tcl_Obj *)));
 
 	ptr = Tcl_GetString(obj);
 	memcpy(ptr, &obj, sizeof(&obj));
diff --git a/storage/bdb/tcl/tcl_dbcursor.c b/storage/bdb/tcl/tcl_dbcursor.c
index fb426e53f48c4000d678d1ef62fb97d4cb210b47..f0ca788f4cadda9abb9035810b9074780ea0e536 100644
--- a/storage/bdb/tcl/tcl_dbcursor.c
+++ b/storage/bdb/tcl/tcl_dbcursor.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2001
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: tcl_dbcursor.c,v 11.65 2004/10/07 16:48:39 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: tcl_dbcursor.c,v 11.51 2002/08/06 06:20:59 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -42,8 +40,8 @@ dbc_Cmd(clientData, interp, objc, objv)
 	int objc;			/* How many arguments? */
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 {
-	static char *dbccmds[] = {
-#if CONFIG_TEST
+	static const char *dbccmds[] = {
+#ifdef CONFIG_TEST
 		"pget",
 #endif
 		"close",
@@ -54,7 +52,7 @@ dbc_Cmd(clientData, interp, objc, objv)
 		NULL
 	};
 	enum dbccmds {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 		DBCPGET,
 #endif
 		DBCCLOSE,
@@ -93,7 +91,7 @@ dbc_Cmd(clientData, interp, objc, objv)
 	    TCL_EXACT, &cmdindex) != TCL_OK)
 		return (IS_HELP(objv[1]));
 	switch ((enum dbccmds)cmdindex) {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 	case DBCPGET:
 		result = tcl_DbcGet(interp, objc, objv, dbc, 1);
 		break;
@@ -151,8 +149,8 @@ tcl_DbcPut(interp, objc, objv, dbc)
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 	DBC *dbc;			/* Cursor pointer */
 {
-	static char *dbcutopts[] = {
-#if CONFIG_TEST
+	static const char *dbcutopts[] = {
+#ifdef CONFIG_TEST
 		"-nodupdata",
 #endif
 		"-after",
@@ -164,7 +162,7 @@ tcl_DbcPut(interp, objc, objv, dbc)
 		NULL
 	};
 	enum dbcutopts {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 		DBCPUT_NODUPDATA,
 #endif
 		DBCPUT_AFTER,
@@ -184,6 +182,9 @@ tcl_DbcPut(interp, objc, objv, dbc)
 	u_int32_t flag;
 	int elemc, freekey, freedata, i, optindex, result, ret;
 
+	COMPQUIET(dtmp, NULL);
+	COMPQUIET(ktmp, NULL);
+
 	result = TCL_OK;
 	flag = 0;
 	freekey = freedata = 0;
@@ -217,7 +218,7 @@ tcl_DbcPut(interp, objc, objv, dbc)
 		}
 		i++;
 		switch ((enum dbcutopts)optindex) {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 		case DBCPUT_NODUPDATA:
 			FLAG_CHECK(flag);
 			flag = DB_NODUPDATA;
@@ -358,14 +359,14 @@ tcl_DbcPut(interp, objc, objv, dbc)
 	    "dbc put");
 	if (ret == 0 &&
 	    (flag == DB_AFTER || flag == DB_BEFORE) && type == DB_RECNO) {
-		res = Tcl_NewLongObj((long)*(db_recno_t *)key.data);
+		res = Tcl_NewWideIntObj((Tcl_WideInt)*(db_recno_t *)key.data);
 		Tcl_SetObjResult(interp, res);
 	}
 out:
 	if (freedata)
-		(void)__os_free(NULL, dtmp);
+		__os_free(NULL, dtmp);
 	if (freekey)
-		(void)__os_free(NULL, ktmp);
+		__os_free(NULL, ktmp);
 	return (result);
 }
 
@@ -380,8 +381,9 @@ tcl_DbcGet(interp, objc, objv, dbc, ispget)
 	DBC *dbc;			/* Cursor pointer */
 	int ispget;			/* 1 for pget, 0 for get */
 {
-	static char *dbcgetopts[] = {
-#if CONFIG_TEST
+	static const char *dbcgetopts[] = {
+#ifdef CONFIG_TEST
+		"-degree_2",
 		"-dirty",
 		"-get_both_range",
 		"-multi",
@@ -406,7 +408,8 @@ tcl_DbcGet(interp, objc, objv, dbc, ispget)
 		NULL
 	};
 	enum dbcgetopts {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
+		DBCGET_DEGREE2,
 		DBCGET_DIRTY,
 		DBCGET_BOTH_RANGE,
 		DBCGET_MULTI,
@@ -437,7 +440,14 @@ tcl_DbcGet(interp, objc, objv, dbc, ispget)
 	void *dtmp, *ktmp;
 	db_recno_t precno, recno;
 	u_int32_t flag, op;
-	int bufsize, elemc, freekey, freedata, i, optindex, result, ret;
+	int elemc, freekey, freedata, i, optindex, result, ret;
+#ifdef CONFIG_TEST
+	int bufsize;
+
+	bufsize = 0;
+#endif
+	COMPQUIET(dtmp, NULL);
+	COMPQUIET(ktmp, NULL);
 
 	result = TCL_OK;
 	flag = 0;
@@ -471,7 +481,10 @@ tcl_DbcGet(interp, objc, objv, dbc, ispget)
 		}
 		i++;
 		switch ((enum dbcgetopts)optindex) {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
+		case DBCGET_DEGREE2:
+			flag |= DB_DEGREE_2;
+			break;
 		case DBCGET_DIRTY:
 			flag |= DB_DIRTY_READ;
 			break;
@@ -640,7 +653,7 @@ tcl_DbcGet(interp, objc, objv, dbc, ispget)
 	op = flag & DB_OPFLAGS_MASK;
 	switch (op) {
 	case DB_GET_BOTH:
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 	case DB_GET_BOTH_RANGE:
 #endif
 		if (i != (objc - 2)) {
@@ -700,11 +713,13 @@ tcl_DbcGet(interp, objc, objv, dbc, ispget)
 			result = TCL_ERROR;
 			goto out;
 		}
+#ifdef CONFIG_TEST
 		if (flag & (DB_MULTIPLE|DB_MULTIPLE_KEY)) {
-			(void)__os_malloc(NULL, bufsize, &data.data);
-			data.ulen = bufsize;
+			(void)__os_malloc(NULL, (size_t)bufsize, &data.data);
+			data.ulen = (u_int32_t)bufsize;
 			data.flags |= DB_DBT_USERMEM;
 		} else
+#endif
 			data.flags |= DB_DBT_MALLOC;
 		if (op == DB_SET_RECNO ||
 		    type == DB_RECNO || type == DB_QUEUE) {
@@ -734,11 +749,13 @@ tcl_DbcGet(interp, objc, objv, dbc, ispget)
 			goto out;
 		}
 		key.flags |= DB_DBT_MALLOC;
+#ifdef CONFIG_TEST
 		if (flag & (DB_MULTIPLE|DB_MULTIPLE_KEY)) {
-			(void)__os_malloc(NULL, bufsize, &data.data);
-			data.ulen = bufsize;
+			(void)__os_malloc(NULL, (size_t)bufsize, &data.data);
+			data.ulen = (u_int32_t)bufsize;
 			data.flags |= DB_DBT_USERMEM;
 		} else
+#endif
 			data.flags |= DB_DBT_MALLOC;
 	}
 
@@ -754,11 +771,11 @@ tcl_DbcGet(interp, objc, objv, dbc, ispget)
 		goto out;
 
 	retlist = Tcl_NewListObj(0, NULL);
-	if (ret == DB_NOTFOUND)
+	if (ret != 0)
 		goto out1;
 	if (op == DB_GET_RECNO) {
 		recno = *((db_recno_t *)data.data);
-		myobj = Tcl_NewLongObj((long)recno);
+		myobj = Tcl_NewWideIntObj((Tcl_WideInt)recno);
 		result = Tcl_ListObjAppendElement(interp, retlist, myobj);
 	} else {
 		if (flag & (DB_MULTIPLE|DB_MULTIPLE_KEY))
@@ -799,9 +816,9 @@ out:
 	if (data.data != NULL && flag & (DB_MULTIPLE|DB_MULTIPLE_KEY))
 		__os_free(dbc->dbp->dbenv, data.data);
 	if (freedata)
-		(void)__os_free(NULL, dtmp);
+		__os_free(NULL, dtmp);
 	if (freekey)
-		(void)__os_free(NULL, ktmp);
+		__os_free(NULL, ktmp);
 	return (result);
 
 }
@@ -816,7 +833,7 @@ tcl_DbcDup(interp, objc, objv, dbc)
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 	DBC *dbc;			/* Cursor pointer */
 {
-	static char *dbcdupopts[] = {
+	static const char *dbcdupopts[] = {
 		"-position",
 		NULL
 	};
@@ -894,7 +911,6 @@ tcl_DbcDup(interp, objc, objv, dbc)
 	 * Now duplicate the cursor.  If successful, we need to create
 	 * a new cursor command.
 	 */
-
 	snprintf(newname, sizeof(newname),
 	    "%s.c%d", dbip->i_name, dbip->i_dbdbcid);
 	newdbcip = _NewInfo(interp, NULL, newname, I_DBC);
@@ -903,10 +919,10 @@ tcl_DbcDup(interp, objc, objv, dbc)
 		if (ret == 0) {
 			dbip->i_dbdbcid++;
 			newdbcip->i_parent = dbip;
-			Tcl_CreateObjCommand(interp, newname,
+			(void)Tcl_CreateObjCommand(interp, newname,
 			    (Tcl_ObjCmdProc *)dbc_Cmd,
 			    (ClientData)newdbc, NULL);
-			res = Tcl_NewStringObj(newname, strlen(newname));
+			res = NewStringObj(newname, strlen(newname));
 			_SetInfoData(newdbcip, newdbc);
 			Tcl_SetObjResult(interp, res);
 		} else {
diff --git a/storage/bdb/tcl/tcl_env.c b/storage/bdb/tcl/tcl_env.c
index cdf4890e9fce88ed45699f3eb4ea2f472d77db5f..e513b961d22d1e1d607cb8e35fd78657b0ece425 100644
--- a/storage/bdb/tcl/tcl_env.c
+++ b/storage/bdb/tcl/tcl_env.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: tcl_env.c,v 11.121 2004/10/07 16:48:39 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: tcl_env.c,v 11.84 2002/08/06 06:21:03 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -20,6 +18,9 @@ static const char revid[] = "$Id: tcl_env.c,v 11.84 2002/08/06 06:21:03 bostic E
 #endif
 
 #include "db_int.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/lock.h"
+#include "dbinc/txn.h"
 #include "dbinc/tcl_db.h"
 
 /*
@@ -28,6 +29,13 @@ static const char revid[] = "$Id: tcl_env.c,v 11.84 2002/08/06 06:21:03 bostic E
 static void _EnvInfoDelete __P((Tcl_Interp *, DBTCL_INFO *));
 static int  env_DbRemove __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *));
 static int  env_DbRename __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *));
+static int  env_GetFlags __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *));
+static int  env_GetOpenFlag
+		__P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *));
+static int  env_GetLockDetect
+		__P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *));
+static int  env_GetTimeout __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *));
+static int  env_GetVerbose __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *));
 
 /*
  * PUBLIC: int env_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));
@@ -42,9 +50,11 @@ env_Cmd(clientData, interp, objc, objv)
 	int objc;			/* How many arguments? */
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 {
-	static char *envcmds[] = {
-#if CONFIG_TEST
+	static const char *envcmds[] = {
+#ifdef CONFIG_TEST
 		"attributes",
+		"errfile",
+		"errpfx",
 		"lock_detect",
 		"lock_id",
 		"lock_id_free",
@@ -74,8 +84,8 @@ env_Cmd(clientData, interp, objc, objv)
 		"rep_start",
 		"rep_stat",
 		"rpcid",
+		"set_flags",
 		"test",
-		"txn_checkpoint",
 		"txn_id_set",
 		"txn_recover",
 		"txn_stat",
@@ -85,12 +95,41 @@ env_Cmd(clientData, interp, objc, objv)
 		"close",
 		"dbremove",
 		"dbrename",
+		"get_cachesize",
+		"get_data_dirs",
+		"get_encrypt_flags",
+		"get_errpfx",
+		"get_flags",
+		"get_home",
+		"get_lg_bsize",
+		"get_lg_dir",
+		"get_lg_max",
+		"get_lg_regionmax",
+		"get_lk_detect",
+		"get_lk_max_lockers",
+		"get_lk_max_locks",
+		"get_lk_max_objects",
+		"get_mp_max_openfd",
+		"get_mp_max_write",
+		"get_mp_mmapsize",
+		"get_open_flags",
+		"get_rep_limit",
+		"get_shm_key",
+		"get_tas_spins",
+		"get_timeout",
+		"get_tmp_dir",
+		"get_tx_max",
+		"get_tx_timestamp",
+		"get_verbose",
 		"txn",
+		"txn_checkpoint",
 		NULL
 	};
 	enum envcmds {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 		ENVATTR,
+		ENVERRFILE,
+		ENVERRPFX,
 		ENVLKDETECT,
 		ENVLKID,
 		ENVLKFREEID,
@@ -120,8 +159,8 @@ env_Cmd(clientData, interp, objc, objv)
 		ENVREPSTART,
 		ENVREPSTAT,
 		ENVRPCID,
+		ENVSETFLAGS,
 		ENVTEST,
-		ENVTXNCKP,
 		ENVTXNSETID,
 		ENVTXNRECOVER,
 		ENVTXNSTAT,
@@ -131,17 +170,51 @@ env_Cmd(clientData, interp, objc, objv)
 		ENVCLOSE,
 		ENVDBREMOVE,
 		ENVDBRENAME,
-		ENVTXN
+		ENVGETCACHESIZE,
+		ENVGETDATADIRS,
+		ENVGETENCRYPTFLAGS,
+		ENVGETERRPFX,
+		ENVGETFLAGS,
+		ENVGETHOME,
+		ENVGETLGBSIZE,
+		ENVGETLGDIR,
+		ENVGETLGMAX,
+		ENVGETLGREGIONMAX,
+		ENVGETLKDETECT,
+		ENVGETLKMAXLOCKERS,
+		ENVGETLKMAXLOCKS,
+		ENVGETLKMAXOBJECTS,
+		ENVGETMPMAXOPENFD,
+		ENVGETMPMAXWRITE,
+		ENVGETMPMMAPSIZE,
+		ENVGETOPENFLAG,
+		ENVGETREPLIMIT,
+		ENVGETSHMKEY,
+		ENVGETTASSPINS,
+		ENVGETTIMEOUT,
+		ENVGETTMPDIR,
+		ENVGETTXMAX,
+		ENVGETTXTIMESTAMP,
+		ENVGETVERBOSE,
+		ENVTXN,
+		ENVTXNCKP
 	};
-	DBTCL_INFO *envip, *logcip;
+	DBTCL_INFO *envip;
 	DB_ENV *dbenv;
-	DB_LOGC *logc;
-	Tcl_Obj *res;
+	Tcl_Obj *res, *myobjv[3];
 	char newname[MSG_SIZE];
-	int cmdindex, result, ret;
-	u_int32_t newval;
-#if CONFIG_TEST
-	u_int32_t otherval;
+	int cmdindex, i, intvalue1, intvalue2, ncache, result, ret;
+	u_int32_t bytes, gbytes, value;
+	size_t size;
+	long shm_key;
+	time_t timeval;
+	const char *strval, **dirs;
+#ifdef CONFIG_TEST
+	DBTCL_INFO *logcip;
+	DB_LOGC *logc;
+	char *strarg;
+	u_int32_t lockid;
+	long newval, otherval;
 #endif
 
 	Tcl_ResetResult(interp);
@@ -172,7 +245,7 @@ env_Cmd(clientData, interp, objc, objv)
 		return (IS_HELP(objv[1]));
 	res = NULL;
 	switch ((enum envcmds)cmdindex) {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 	case ENVLKDETECT:
 		result = tcl_LockDetect(interp, objc, objv, dbenv);
 		break;
@@ -191,21 +264,21 @@ env_Cmd(clientData, interp, objc, objv)
 			return (TCL_ERROR);
 		}
 		_debug_check();
-		ret = dbenv->lock_id(dbenv, &newval);
+		ret = dbenv->lock_id(dbenv, &lockid);
 		result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
 		    "lock_id");
 		if (result == TCL_OK)
-			res = Tcl_NewLongObj((long)newval);
+			res = Tcl_NewWideIntObj((Tcl_WideInt)lockid);
 		break;
 	case ENVLKFREEID:
 		if (objc != 3) {
 			Tcl_WrongNumArgs(interp, 3, objv, NULL);
 			return (TCL_ERROR);
 		}
-		result = Tcl_GetLongFromObj(interp, objv[2], (long *)&newval);
+		result = Tcl_GetLongFromObj(interp, objv[2], &newval);
 		if (result != TCL_OK)
 			return (result);
-		ret = dbenv->lock_id_free(dbenv, newval);
+		ret = dbenv->lock_id_free(dbenv, (u_int32_t)newval);
 		result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
 		    "lock id_free");
 		break;
@@ -214,13 +287,14 @@ env_Cmd(clientData, interp, objc, objv)
 			Tcl_WrongNumArgs(interp, 4, objv, "current max");
 			return (TCL_ERROR);
 		}
-		result = Tcl_GetLongFromObj(interp, objv[2], (long *)&newval);
+		result = Tcl_GetLongFromObj(interp, objv[2], &newval);
 		if (result != TCL_OK)
 			return (result);
-		result = Tcl_GetLongFromObj(interp, objv[3], (long *)&otherval);
+		result = Tcl_GetLongFromObj(interp, objv[3], &otherval);
 		if (result != TCL_OK)
 			return (result);
-		ret = dbenv->lock_id_set(dbenv, newval, otherval);
+		ret = __lock_id_set(dbenv,
+		    (u_int32_t)newval, (u_int32_t)otherval);
 		result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
 		    "lock id_free");
 		break;
@@ -251,11 +325,10 @@ env_Cmd(clientData, interp, objc, objv)
 				 * not "tied" to the env.  That is, they
 				 * are NOT closed if the env is closed.
 				 */
-				Tcl_CreateObjCommand(interp, newname,
+				(void)Tcl_CreateObjCommand(interp, newname,
 				    (Tcl_ObjCmdProc *)logc_Cmd,
 				    (ClientData)logc, NULL);
-				res =
-				    Tcl_NewStringObj(newname, strlen(newname));
+				res = NewStringObj(newname, strlen(newname));
 				_SetInfoData(logcip, logc);
 			} else {
 				_DeleteInfo(logcip);
@@ -327,25 +400,23 @@ env_Cmd(clientData, interp, objc, objv)
 		 * !!! Retrieve the client ID from the dbp handle directly.
 		 * This is for testing purposes only.  It is dbp-private data.
 		 */
-		res = Tcl_NewLongObj(dbenv->cl_id);
-		break;
-	case ENVTXNCKP:
-		result = tcl_TxnCheckpoint(interp, objc, objv, dbenv);
+		res = Tcl_NewLongObj((long)dbenv->cl_id);
 		break;
 	case ENVTXNSETID:
 		if (objc != 4) {
 			Tcl_WrongNumArgs(interp, 4, objv, "current max");
 			return (TCL_ERROR);
 		}
-		result = Tcl_GetLongFromObj(interp, objv[2], (long *)&newval);
+		result = Tcl_GetLongFromObj(interp, objv[2], &newval);
 		if (result != TCL_OK)
 			return (result);
-		result = Tcl_GetLongFromObj(interp, objv[3], (long *)&otherval);
+		result = Tcl_GetLongFromObj(interp, objv[3], &otherval);
 		if (result != TCL_OK)
 			return (result);
-		ret = dbenv->txn_id_set(dbenv, newval, otherval);
+		ret = __txn_id_set(dbenv,
+		    (u_int32_t)newval, (u_int32_t)otherval);
 		result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
-		    "lock id_free");
+		    "txn setid");
 		break;
 	case ENVTXNRECOVER:
 		result = tcl_TxnRecover(interp, objc, objv, dbenv, envip);
@@ -362,6 +433,39 @@ env_Cmd(clientData, interp, objc, objv)
 	case ENVATTR:
 		result = tcl_EnvAttr(interp, objc, objv, dbenv);
 		break;
+	case ENVERRFILE:
+		/*
+		 * One args for this.  Error if different.
+		 */
+		if (objc != 3) {
+			Tcl_WrongNumArgs(interp, 2, objv, "errfile");
+			return (TCL_ERROR);
+		}
+		strarg = Tcl_GetStringFromObj(objv[2], NULL);
+		tcl_EnvSetErrfile(interp, dbenv, envip, strarg);
+		result = TCL_OK;
+		break;
+	case ENVERRPFX:
+		/*
+		 * One args for this.  Error if different.
+		 */
+		if (objc != 3) {
+			Tcl_WrongNumArgs(interp, 2, objv, "pfx");
+			return (TCL_ERROR);
+		}
+		strarg = Tcl_GetStringFromObj(objv[2], NULL);
+		result = tcl_EnvSetErrpfx(interp, dbenv, envip, strarg);
+		break;
+	case ENVSETFLAGS:
+		/*
+		 * Two args for this.  Error if different.
+		 */
+		if (objc != 4) {
+			Tcl_WrongNumArgs(interp, 2, objv, "which on|off");
+			return (TCL_ERROR);
+		}
+		result = tcl_EnvSetFlags(interp, dbenv, objv[2], objv[3]);
+		break;
 	case ENVTEST:
 		result = tcl_EnvTest(interp, objc, objv, dbenv);
 		break;
@@ -405,9 +509,242 @@ env_Cmd(clientData, interp, objc, objv)
 	case ENVDBRENAME:
 		result = env_DbRename(interp, objc, objv, dbenv);
 		break;
+	case ENVGETCACHESIZE:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbenv->get_cachesize(dbenv, &gbytes, &bytes, &ncache);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "env get_cachesize")) == TCL_OK) {
+			myobjv[0] = Tcl_NewLongObj((long)gbytes);
+			myobjv[1] = Tcl_NewLongObj((long)bytes);
+			myobjv[2] = Tcl_NewLongObj((long)ncache);
+			res = Tcl_NewListObj(3, myobjv);
+		}
+		break;
+	case ENVGETDATADIRS:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbenv->get_data_dirs(dbenv, &dirs);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "env get_data_dirs")) == TCL_OK) {
+			res = Tcl_NewListObj(0, NULL);
+			for (i = 0; result == TCL_OK && dirs[i] != NULL; i++)
+				result = Tcl_ListObjAppendElement(interp, res,
+				    NewStringObj(dirs[i], strlen(dirs[i])));
+		}
+		break;
+	case ENVGETENCRYPTFLAGS:
+		result = tcl_EnvGetEncryptFlags(interp, objc, objv, dbenv);
+		break;
+	case ENVGETERRPFX:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		dbenv->get_errpfx(dbenv, &strval);
+		res = NewStringObj(strval, strlen(strval));
+		break;
+	case ENVGETFLAGS:
+		result = env_GetFlags(interp, objc, objv, dbenv);
+		break;
+	case ENVGETHOME:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbenv->get_home(dbenv, &strval);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "env get_home")) == TCL_OK)
+			res = NewStringObj(strval, strlen(strval));
+		break;
+	case ENVGETLGBSIZE:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbenv->get_lg_bsize(dbenv, &value);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "env get_lg_bsize")) == TCL_OK)
+			res = Tcl_NewLongObj((long)value);
+		break;
+	case ENVGETLGDIR:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbenv->get_lg_dir(dbenv, &strval);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "env get_lg_dir")) == TCL_OK)
+			res = NewStringObj(strval, strlen(strval));
+		break;
+	case ENVGETLGMAX:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbenv->get_lg_max(dbenv, &value);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "env get_lg_max")) == TCL_OK)
+			res = Tcl_NewLongObj((long)value);
+		break;
+	case ENVGETLGREGIONMAX:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbenv->get_lg_regionmax(dbenv, &value);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "env get_lg_regionmax")) == TCL_OK)
+			res = Tcl_NewLongObj((long)value);
+		break;
+	case ENVGETLKDETECT:
+		result = env_GetLockDetect(interp, objc, objv, dbenv);
+		break;
+	case ENVGETLKMAXLOCKERS:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbenv->get_lk_max_lockers(dbenv, &value);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "env get_lk_max_lockers")) == TCL_OK)
+			res = Tcl_NewLongObj((long)value);
+		break;
+	case ENVGETLKMAXLOCKS:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbenv->get_lk_max_locks(dbenv, &value);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "env get_lk_max_locks")) == TCL_OK)
+			res = Tcl_NewLongObj((long)value);
+		break;
+	case ENVGETLKMAXOBJECTS:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbenv->get_lk_max_objects(dbenv, &value);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "env get_lk_max_objects")) == TCL_OK)
+			res = Tcl_NewLongObj((long)value);
+		break;
+	case ENVGETMPMAXOPENFD:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbenv->get_mp_max_openfd(dbenv, &intvalue1);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "env get_mp_max_openfd")) == TCL_OK)
+			res = Tcl_NewIntObj(intvalue1);
+		break;
+	case ENVGETMPMAXWRITE:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbenv->get_mp_max_write(dbenv, &intvalue1, &intvalue2);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "env get_mp_max_write")) == TCL_OK) {
+			myobjv[0] = Tcl_NewIntObj(intvalue1);
+			myobjv[1] = Tcl_NewIntObj(intvalue2);
+			res = Tcl_NewListObj(2, myobjv);
+		}
+		break;
+	case ENVGETMPMMAPSIZE:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbenv->get_mp_mmapsize(dbenv, &size);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "env get_mp_mmapsize")) == TCL_OK)
+			res = Tcl_NewLongObj((long)size);
+		break;
+	case ENVGETOPENFLAG:
+		result = env_GetOpenFlag(interp, objc, objv, dbenv);
+		break;
+	case ENVGETREPLIMIT:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbenv->get_rep_limit(dbenv, &gbytes, &bytes);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "env get_rep_limit")) == TCL_OK) {
+			myobjv[0] = Tcl_NewLongObj((long)gbytes);
+			myobjv[1] = Tcl_NewLongObj((long)bytes);
+			res = Tcl_NewListObj(2, myobjv);
+		}
+		break;
+	case ENVGETSHMKEY:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbenv->get_shm_key(dbenv, &shm_key);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "env shm_key")) == TCL_OK)
+			res = Tcl_NewLongObj(shm_key);
+		break;
+	case ENVGETTASSPINS:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbenv->get_tas_spins(dbenv, &value);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "env get_tas_spins")) == TCL_OK)
+			res = Tcl_NewLongObj((long)value);
+		break;
+	case ENVGETTIMEOUT:
+		result = env_GetTimeout(interp, objc, objv, dbenv);
+		break;
+	case ENVGETTMPDIR:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbenv->get_tmp_dir(dbenv, &strval);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "env get_tmp_dir")) == TCL_OK)
+			res = NewStringObj(strval, strlen(strval));
+		break;
+	case ENVGETTXMAX:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbenv->get_tx_max(dbenv, &value);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "env get_tx_max")) == TCL_OK)
+			res = Tcl_NewLongObj((long)value);
+		break;
+	case ENVGETTXTIMESTAMP:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = dbenv->get_tx_timestamp(dbenv, &timeval);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "env get_tx_timestamp")) == TCL_OK)
+			res = Tcl_NewLongObj((long)timeval);
+		break;
+	case ENVGETVERBOSE:
+		result = env_GetVerbose(interp, objc, objv, dbenv);
+		break;
 	case ENVTXN:
 		result = tcl_Txn(interp, objc, objv, dbenv, envip);
 		break;
+	case ENVTXNCKP:
+		result = tcl_TxnCheckpoint(interp, objc, objv, dbenv);
+		break;
 	}
 	/*
 	 * Only set result if we have a res.  Otherwise, lower
@@ -432,8 +769,8 @@ tcl_EnvRemove(interp, objc, objv, dbenv, envip)
 	DB_ENV *dbenv;			/* Env pointer */
 	DBTCL_INFO *envip;		/* Info pointer */
 {
-	static char *envremopts[] = {
-#if CONFIG_TEST
+	static const char *envremopts[] = {
+#ifdef CONFIG_TEST
 		"-overwrite",
 		"-server",
 #endif
@@ -449,7 +786,7 @@ tcl_EnvRemove(interp, objc, objv, dbenv, envip)
 		NULL
 	};
 	enum envremopts {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 		ENVREM_OVERWRITE,
 		ENVREM_SERVER,
 #endif
@@ -490,7 +827,7 @@ tcl_EnvRemove(interp, objc, objv, dbenv, envip)
 		}
 		i++;
 		switch ((enum envremopts)optindex) {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 		case ENVREM_SERVER:
 			/* Make sure we have an arg to check against! */
 			if (i >= objc) {
@@ -500,7 +837,7 @@ tcl_EnvRemove(interp, objc, objv, dbenv, envip)
 				break;
 			}
 			server = Tcl_GetStringFromObj(objv[i++], NULL);
-			cflag = DB_CLIENT;
+			cflag = DB_RPCCLIENT;
 			break;
 #endif
 		case ENVREM_ENCRYPT_AES:
@@ -538,7 +875,7 @@ tcl_EnvRemove(interp, objc, objv, dbenv, envip)
 			}
 			home = Tcl_GetStringFromObj(objv[i++], NULL);
 			break;
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 		case ENVREM_OVERWRITE:
 			sflag |= DB_OVERWRITE;
 			break;
@@ -690,7 +1027,7 @@ _EnvInfoDelete(interp, envip)
 		 * Other types like log cursors and locks will just
 		 * get cleaned up here.
 		 */
-		 if (p->i_parent == envip) {
+		if (p->i_parent == envip) {
 			switch (p->i_type) {
 			case I_TXN:
 				_TxnInfoDelete(interp, p);
@@ -698,7 +1035,15 @@ _EnvInfoDelete(interp, envip)
 			case I_MP:
 				_MpInfoDelete(interp, p);
 				break;
-			default:
+			case I_DB:
+			case I_DBC:
+			case I_ENV:
+			case I_LOCK:
+			case I_LOGC:
+			case I_MUTEX:
+			case I_NDBM:
+			case I_PG:
+			case I_SEQ:
 				Tcl_SetResult(interp,
 				    "_EnvInfoDelete: bad info type",
 				    TCL_STATIC);
@@ -714,7 +1059,7 @@ _EnvInfoDelete(interp, envip)
 	_DeleteInfo(envip);
 }
 
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 /*
  * PUBLIC: int tcl_EnvVerbose __P((Tcl_Interp *, DB_ENV *, Tcl_Obj *,
  * PUBLIC:    Tcl_Obj *));
@@ -728,8 +1073,7 @@ tcl_EnvVerbose(interp, dbenv, which, onoff)
 	Tcl_Obj *which;			/* Which subsystem */
 	Tcl_Obj *onoff;			/* On or off */
 {
-	static char *verbwhich[] = {
-		"chkpt",
+	static const char *verbwhich[] = {
 		"deadlock",
 		"recovery",
 		"rep",
@@ -737,13 +1081,12 @@ tcl_EnvVerbose(interp, dbenv, which, onoff)
 		NULL
 	};
 	enum verbwhich {
-		ENVVERB_CHK,
 		ENVVERB_DEAD,
 		ENVVERB_REC,
 		ENVVERB_REP,
 		ENVVERB_WAIT
 	};
-	static char *verbonoff[] = {
+	static const char *verbonoff[] = {
 		"off",
 		"on",
 		NULL
@@ -760,9 +1103,6 @@ tcl_EnvVerbose(interp, dbenv, which, onoff)
 		return (IS_HELP(which));
 
 	switch ((enum verbwhich)optindex) {
-	case ENVVERB_CHK:
-		wh = DB_VERB_CHKPOINT;
-		break;
 	case ENVVERB_DEAD:
 		wh = DB_VERB_DEADLOCK;
 		break;
@@ -797,7 +1137,7 @@ tcl_EnvVerbose(interp, dbenv, which, onoff)
 }
 #endif
 
-#if	CONFIG_TEST
+#ifdef CONFIG_TEST
 /*
  * PUBLIC: int tcl_EnvAttr __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *));
  *
@@ -826,52 +1166,58 @@ tcl_EnvAttr(interp, objc, objv, dbenv)
 	 * We peek at the dbenv to determine what subsystems
 	 * we have available in this env.
 	 */
-	myobj = Tcl_NewStringObj("-home", strlen("-home"));
+	myobj = NewStringObj("-home", strlen("-home"));
 	if ((result = Tcl_ListObjAppendElement(interp,
 	    retlist, myobj)) != TCL_OK)
 		goto err;
-	myobj = Tcl_NewStringObj(dbenv->db_home, strlen(dbenv->db_home));
+	myobj = NewStringObj(dbenv->db_home, strlen(dbenv->db_home));
 	if ((result = Tcl_ListObjAppendElement(interp,
 	    retlist, myobj)) != TCL_OK)
 		goto err;
 	if (CDB_LOCKING(dbenv)) {
-		myobj = Tcl_NewStringObj("-cdb", strlen("-cdb"));
+		myobj = NewStringObj("-cdb", strlen("-cdb"));
 		if ((result = Tcl_ListObjAppendElement(interp,
 		    retlist, myobj)) != TCL_OK)
 			goto err;
 	}
 	if (CRYPTO_ON(dbenv)) {
-		myobj = Tcl_NewStringObj("-crypto", strlen("-crypto"));
+		myobj = NewStringObj("-crypto", strlen("-crypto"));
 		if ((result = Tcl_ListObjAppendElement(interp,
 		    retlist, myobj)) != TCL_OK)
 			goto err;
 	}
 	if (LOCKING_ON(dbenv)) {
-		myobj = Tcl_NewStringObj("-lock", strlen("-lock"));
+		myobj = NewStringObj("-lock", strlen("-lock"));
 		if ((result = Tcl_ListObjAppendElement(interp,
 		    retlist, myobj)) != TCL_OK)
 			goto err;
 	}
 	if (LOGGING_ON(dbenv)) {
-		myobj = Tcl_NewStringObj("-log", strlen("-log"));
+		myobj = NewStringObj("-log", strlen("-log"));
 		if ((result = Tcl_ListObjAppendElement(interp,
 		    retlist, myobj)) != TCL_OK)
 			goto err;
 	}
 	if (MPOOL_ON(dbenv)) {
-		myobj = Tcl_NewStringObj("-mpool", strlen("-mpool"));
+		myobj = NewStringObj("-mpool", strlen("-mpool"));
 		if ((result = Tcl_ListObjAppendElement(interp,
 		    retlist, myobj)) != TCL_OK)
 			goto err;
 	}
 	if (RPC_ON(dbenv)) {
-		myobj = Tcl_NewStringObj("-rpc", strlen("-rpc"));
+		myobj = NewStringObj("-rpc", strlen("-rpc"));
+		if ((result = Tcl_ListObjAppendElement(interp,
+		    retlist, myobj)) != TCL_OK)
+			goto err;
+	}
+	if (REP_ON(dbenv)) {
+		myobj = NewStringObj("-rep", strlen("-rep"));
 		if ((result = Tcl_ListObjAppendElement(interp,
 		    retlist, myobj)) != TCL_OK)
 			goto err;
 	}
 	if (TXN_ON(dbenv)) {
-		myobj = Tcl_NewStringObj("-txn", strlen("-txn"));
+		myobj = NewStringObj("-txn", strlen("-txn"));
 		if ((result = Tcl_ListObjAppendElement(interp,
 		    retlist, myobj)) != TCL_OK)
 			goto err;
@@ -881,6 +1227,128 @@ err:
 	return (result);
 }
 
+/*
+ * PUBLIC: int tcl_EnvSetFlags __P((Tcl_Interp *, DB_ENV *, Tcl_Obj *,
+ * PUBLIC:    Tcl_Obj *));
+ *
+ * tcl_EnvSetFlags --
+ *	Set flags in an env.
+ */
+int
+tcl_EnvSetFlags(interp, dbenv, which, onoff)
+	Tcl_Interp *interp;		/* Interpreter */
+	DB_ENV *dbenv;			/* Env pointer */
+	Tcl_Obj *which;			/* Which subsystem */
+	Tcl_Obj *onoff;			/* On or off */
+{
+	static const char *sfwhich[] = {
+		"-auto_commit",
+		"-direct_db",
+		"-direct_log",
+		"-dsync_log",
+		"-log_inmemory",
+		"-log_remove",
+		"-nolock",
+		"-nommap",
+		"-nopanic",
+		"-nosync",
+		"-overwrite",
+		"-panic",
+		"-wrnosync",
+		NULL
+	};
+	enum sfwhich {
+		ENVSF_AUTOCOMMIT,
+		ENVSF_DIRECTDB,
+		ENVSF_DIRECTLOG,
+		ENVSF_DSYNCLOG,
+		ENVSF_LOG_INMEMORY,
+		ENVSF_LOG_REMOVE,
+		ENVSF_NOLOCK,
+		ENVSF_NOMMAP,
+		ENVSF_NOPANIC,
+		ENVSF_NOSYNC,
+		ENVSF_OVERWRITE,
+		ENVSF_PANIC,
+		ENVSF_WRNOSYNC
+	};
+	static const char *sfonoff[] = {
+		"off",
+		"on",
+		NULL
+	};
+	enum sfonoff {
+		ENVSF_OFF,
+		ENVSF_ON
+	};
+	int on, optindex, ret;
+	u_int32_t wh;
+
+	if (Tcl_GetIndexFromObj(interp, which, sfwhich, "option",
+	    TCL_EXACT, &optindex) != TCL_OK)
+		return (IS_HELP(which));
+
+	switch ((enum sfwhich)optindex) {
+	case ENVSF_AUTOCOMMIT:
+		wh = DB_AUTO_COMMIT;
+		break;
+	case ENVSF_DIRECTDB:
+		wh = DB_DIRECT_DB;
+		break;
+	case ENVSF_DIRECTLOG:
+		wh = DB_DIRECT_LOG;
+		break;
+	case ENVSF_DSYNCLOG:
+		wh = DB_DSYNC_LOG;
+		break;
+	case ENVSF_LOG_INMEMORY:
+		wh = DB_LOG_INMEMORY;
+		break;
+	case ENVSF_LOG_REMOVE:
+		wh = DB_LOG_AUTOREMOVE;
+		break;
+	case ENVSF_NOLOCK:
+		wh = DB_NOLOCKING;
+		break;
+	case ENVSF_NOMMAP:
+		wh = DB_NOMMAP;
+		break;
+	case ENVSF_NOSYNC:
+		wh = DB_TXN_NOSYNC;
+		break;
+	case ENVSF_NOPANIC:
+		wh = DB_NOPANIC;
+		break;
+	case ENVSF_PANIC:
+		wh = DB_PANIC_ENVIRONMENT;
+		break;
+	case ENVSF_OVERWRITE:
+		wh = DB_OVERWRITE;
+		break;
+	case ENVSF_WRNOSYNC:
+		wh = DB_TXN_WRITE_NOSYNC;
+		break;
+	default:
+		return (TCL_ERROR);
+	}
+	if (Tcl_GetIndexFromObj(interp, onoff, sfonoff, "option",
+	    TCL_EXACT, &optindex) != TCL_OK)
+		return (IS_HELP(onoff));
+	switch ((enum sfonoff)optindex) {
+	case ENVSF_OFF:
+		on = 0;
+		break;
+	case ENVSF_ON:
+		on = 1;
+		break;
+	default:
+		return (TCL_ERROR);
+	}
+	ret = dbenv->set_flags(dbenv, wh, on);
+	return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+	    "env set verbose"));
+}
+
 /*
  * PUBLIC: int tcl_EnvTest __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *));
  *
@@ -893,22 +1361,20 @@ tcl_EnvTest(interp, objc, objv, dbenv)
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 	DB_ENV *dbenv;			/* Env pointer */
 {
-	static char *envtestcmd[] = {
+	static const char *envtestcmd[] = {
 		"abort",
+		"check",
 		"copy",
 		NULL
 	};
 	enum envtestcmd {
 		ENVTEST_ABORT,
+		ENVTEST_CHECK,
 		ENVTEST_COPY
 	};
-	static char *envtestat[] = {
+	static const char *envtestat[] = {
 		"electinit",
-		"electsend",
 		"electvote1",
-		"electvote2",
-		"electwait1",
-		"electwait2",
 		"none",
 		"predestroy",
 		"preopen",
@@ -922,11 +1388,7 @@ tcl_EnvTest(interp, objc, objv, dbenv)
 	};
 	enum envtestat {
 		ENVTEST_ELECTINIT,
-		ENVTEST_ELECTSEND,
 		ENVTEST_ELECTVOTE1,
-		ENVTEST_ELECTVOTE2,
-		ENVTEST_ELECTWAIT1,
-		ENVTEST_ELECTWAIT2,
 		ENVTEST_NONE,
 		ENVTEST_PREDESTROY,
 		ENVTEST_PREOPEN,
@@ -948,7 +1410,7 @@ tcl_EnvTest(interp, objc, objv, dbenv)
 	}
 
 	/*
-	 * This must be the "copy" or "abort" portion of the command.
+	 * This must be the "check", "copy" or "abort" portion of the command.
 	 */
 	if (Tcl_GetIndexFromObj(interp, objv[2], envtestcmd, "command",
 	    TCL_EXACT, &optindex) != TCL_OK) {
@@ -959,6 +1421,13 @@ tcl_EnvTest(interp, objc, objv, dbenv)
 	case ENVTEST_ABORT:
 		loc = &dbenv->test_abort;
 		break;
+	case ENVTEST_CHECK:
+		loc = &dbenv->test_check;
+		if (Tcl_GetIntFromObj(interp, objv[3], &testval) != TCL_OK) {
+			result = IS_HELP(objv[3]);
+			return (result);
+		}
+		goto done;
 	case ENVTEST_COPY:
 		loc = &dbenv->test_copy;
 		break;
@@ -980,26 +1449,10 @@ tcl_EnvTest(interp, objc, objv, dbenv)
 		DB_ASSERT(loc == &dbenv->test_abort);
 		testval = DB_TEST_ELECTINIT;
 		break;
-	case ENVTEST_ELECTSEND:
-		DB_ASSERT(loc == &dbenv->test_abort);
-		testval = DB_TEST_ELECTSEND;
-		break;
 	case ENVTEST_ELECTVOTE1:
 		DB_ASSERT(loc == &dbenv->test_abort);
 		testval = DB_TEST_ELECTVOTE1;
 		break;
-	case ENVTEST_ELECTVOTE2:
-		DB_ASSERT(loc == &dbenv->test_abort);
-		testval = DB_TEST_ELECTVOTE2;
-		break;
-	case ENVTEST_ELECTWAIT1:
-		DB_ASSERT(loc == &dbenv->test_abort);
-		testval = DB_TEST_ELECTWAIT1;
-		break;
-	case ENVTEST_ELECTWAIT2:
-		DB_ASSERT(loc == &dbenv->test_abort);
-		testval = DB_TEST_ELECTWAIT2;
-		break;
 	case ENVTEST_NONE:
 		testval = 0;
 		break;
@@ -1032,7 +1485,7 @@ tcl_EnvTest(interp, objc, objv, dbenv)
 		Tcl_SetResult(interp, "Illegal test location", TCL_STATIC);
 		return (TCL_ERROR);
 	}
-
+done:
 	*loc = testval;
 	Tcl_SetResult(interp, "0", TCL_STATIC);
 	return (result);
@@ -1050,7 +1503,7 @@ env_DbRemove(interp, objc, objv, dbenv)
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 	DB_ENV *dbenv;
 {
-	static char *envdbrem[] = {
+	static const char *envdbrem[] = {
 		"-auto_commit",
 		"-txn",
 		"--",
@@ -1144,13 +1597,13 @@ env_DbRemove(interp, objc, objv, dbenv)
 		if (i != objc) {
 			subdbtmp =
 			    Tcl_GetByteArrayFromObj(objv[i++], &subdblen);
-			if ((ret = __os_malloc(dbenv, subdblen + 1,
-			    &subdb)) != 0) {
+			if ((ret = __os_malloc(
+			    dbenv, (size_t)subdblen + 1, &subdb)) != 0) {
 				Tcl_SetResult(interp,
 				    db_strerror(ret), TCL_STATIC);
 				return (0);
 			}
-			memcpy(subdb, subdbtmp, subdblen);
+			memcpy(subdb, subdbtmp, (size_t)subdblen);
 			subdb[subdblen] = '\0';
 		}
 	} else {
@@ -1178,7 +1631,7 @@ env_DbRename(interp, objc, objv, dbenv)
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 	DB_ENV *dbenv;
 {
-	static char *envdbmv[] = {
+	static const char *envdbmv[] = {
 		"-auto_commit",
 		"-txn",
 		"--",
@@ -1273,24 +1726,23 @@ env_DbRename(interp, objc, objv, dbenv)
 		if (i == objc - 2) {
 			subdbtmp =
 			    Tcl_GetByteArrayFromObj(objv[i++], &subdblen);
-			if ((ret = __os_malloc(dbenv, subdblen + 1,
-			    &subdb)) != 0) {
+			if ((ret = __os_malloc(
+			    dbenv, (size_t)subdblen + 1, &subdb)) != 0) {
 				Tcl_SetResult(interp,
 				    db_strerror(ret), TCL_STATIC);
 				return (0);
 			}
-			memcpy(subdb, subdbtmp, subdblen);
+			memcpy(subdb, subdbtmp, (size_t)subdblen);
 			subdb[subdblen] = '\0';
 		}
-		subdbtmp =
-		    Tcl_GetByteArrayFromObj(objv[i++], &newlen);
-		if ((ret = __os_malloc(dbenv, newlen + 1,
-		    &newname)) != 0) {
+		subdbtmp = Tcl_GetByteArrayFromObj(objv[i++], &newlen);
+		if ((ret = __os_malloc(
+		    dbenv, (size_t)newlen + 1, &newname)) != 0) {
 			Tcl_SetResult(interp,
 			    db_strerror(ret), TCL_STATIC);
 			return (0);
 		}
-		memcpy(newname, subdbtmp, newlen);
+		memcpy(newname, subdbtmp, (size_t)newlen);
 		newname[newlen] = '\0';
 	} else {
 		Tcl_WrongNumArgs(interp, 3, objv,
@@ -1308,3 +1760,405 @@ error:
 		__os_free(dbenv, newname);
 	return (result);
 }
+
+/*
+ * env_GetFlags --
+ *	Implements the ENV->get_flags command.
+ */
+static int
+env_GetFlags(interp, objc, objv, dbenv)
+	Tcl_Interp *interp;		/* Interpreter */
+	int objc;			/* How many arguments? */
+	Tcl_Obj *CONST objv[];		/* The argument objects */
+	DB_ENV *dbenv;
+{
+	int i, ret, result;
+	u_int32_t flags;
+	char buf[512];
+	Tcl_Obj *res;
+
+	static const struct {
+		u_int32_t flag;
+		char *arg;
+	} open_flags[] = {
+		{ DB_AUTO_COMMIT, "-auto_commit" },
+		{ DB_CDB_ALLDB, "-cdb_alldb" },
+		{ DB_DIRECT_DB, "-direct_db" },
+		{ DB_DIRECT_LOG, "-direct_log" },
+		{ DB_DSYNC_LOG, "-dsync_log" },
+		{ DB_LOG_AUTOREMOVE, "-log_remove" },
+		{ DB_LOG_INMEMORY, "-log_inmemory" },
+		{ DB_NOLOCKING, "-nolock" },
+		{ DB_NOMMAP, "-nommap" },
+		{ DB_NOPANIC, "-nopanic" },
+		{ DB_OVERWRITE, "-overwrite" },
+		{ DB_PANIC_ENVIRONMENT, "-panic" },
+		{ DB_REGION_INIT, "-region_init" },
+		{ DB_TXN_NOSYNC, "-nosync" },
+		{ DB_TXN_WRITE_NOSYNC, "-wrnosync" },
+		{ DB_YIELDCPU, "-yield" },
+		{ 0, NULL }
+	};
+
+	if (objc != 2) {
+		Tcl_WrongNumArgs(interp, 1, objv, NULL);
+		return (TCL_ERROR);
+	}
+
+	ret = dbenv->get_flags(dbenv, &flags);
+	if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+	    "env get_flags")) == TCL_OK) {
+		buf[0] = '\0';
+
+		for (i = 0; open_flags[i].flag != 0; i++)
+			if (LF_ISSET(open_flags[i].flag)) {
+				if (strlen(buf) > 0)
+					(void)strncat(buf, " ", sizeof(buf));
+				(void)strncat(
+				    buf, open_flags[i].arg, sizeof(buf));
+			}
+
+		res = NewStringObj(buf, strlen(buf));
+		Tcl_SetObjResult(interp, res);
+	}
+
+	return (result);
+}
+
+/*
+ * env_GetOpenFlag --
+ *	Implements the ENV->get_open_flags command.
+ */
+static int
+env_GetOpenFlag(interp, objc, objv, dbenv)
+	Tcl_Interp *interp;		/* Interpreter */
+	int objc;			/* How many arguments? */
+	Tcl_Obj *CONST objv[];		/* The argument objects */
+	DB_ENV *dbenv;
+{
+	int i, ret, result;
+	u_int32_t flags;
+	char buf[512];
+	Tcl_Obj *res;
+
+	static const struct {
+		u_int32_t flag;
+		char *arg;
+	} open_flags[] = {
+		{ DB_INIT_CDB, "-cdb" },
+		{ DB_INIT_LOCK, "-lock" },
+		{ DB_INIT_LOG, "-log" },
+		{ DB_INIT_MPOOL, "-mpool" },
+		{ DB_INIT_TXN, "-txn" },
+		{ DB_RECOVER, "-recover" },
+		{ DB_RECOVER_FATAL, "-recover_fatal" },
+		{ DB_USE_ENVIRON, "-use_environ" },
+		{ DB_USE_ENVIRON_ROOT, "-use_environ_root" },
+		{ DB_CREATE, "-create" },
+		{ DB_LOCKDOWN, "-lockdown" },
+		{ DB_PRIVATE, "-private" },
+		{ DB_SYSTEM_MEM, "-system_mem" },
+		{ DB_THREAD, "-thread" },
+		{ 0, NULL }
+	};
+
+	if (objc != 2) {
+		Tcl_WrongNumArgs(interp, 1, objv, NULL);
+		return (TCL_ERROR);
+	}
+
+	ret = dbenv->get_open_flags(dbenv, &flags);
+	if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+	    "env get_open_flags")) == TCL_OK) {
+		buf[0] = '\0';
+
+		for (i = 0; open_flags[i].flag != 0; i++)
+			if (LF_ISSET(open_flags[i].flag)) {
+				if (strlen(buf) > 0)
+					(void)strncat(buf, " ", sizeof(buf));
+				(void)strncat(
+				    buf, open_flags[i].arg, sizeof(buf));
+			}
+
+		res = NewStringObj(buf, strlen(buf));
+		Tcl_SetObjResult(interp, res);
+	}
+
+	return (result);
+}
+
+/*
+ * PUBLIC: int tcl_EnvGetEncryptFlags __P((Tcl_Interp *, int, Tcl_Obj * CONST*,
+ * PUBLIC:      DB_ENV *));
+ *
+ * tcl_EnvGetEncryptFlags --
+ *	Implements the ENV->get_encrypt_flags command.
+ */
+int
+tcl_EnvGetEncryptFlags(interp, objc, objv, dbenv)
+	Tcl_Interp *interp;		/* Interpreter */
+	int objc;			/* How many arguments? */
+	Tcl_Obj *CONST objv[];		/* The argument objects */
+	DB_ENV *dbenv;			/* Database pointer */
+{
+	int i, ret, result;
+	u_int32_t flags;
+	char buf[512];
+	Tcl_Obj *res;
+
+	static const struct {
+		u_int32_t flag;
+		char *arg;
+	} encrypt_flags[] = {
+		{ DB_ENCRYPT_AES, "-encryptaes" },
+		{ 0, NULL }
+	};
+
+	if (objc != 2) {
+		Tcl_WrongNumArgs(interp, 1, objv, NULL);
+		return (TCL_ERROR);
+	}
+
+	ret = dbenv->get_encrypt_flags(dbenv, &flags);
+	if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+	    "env get_encrypt_flags")) == TCL_OK) {
+		buf[0] = '\0';
+
+		for (i = 0; encrypt_flags[i].flag != 0; i++)
+			if (LF_ISSET(encrypt_flags[i].flag)) {
+				if (strlen(buf) > 0)
+					(void)strncat(buf, " ", sizeof(buf));
+				(void)strncat(
+				    buf, encrypt_flags[i].arg, sizeof(buf));
+			}
+
+		res = NewStringObj(buf, strlen(buf));
+		Tcl_SetObjResult(interp, res);
+	}
+
+	return (result);
+}
+
+/*
+ * env_GetLockDetect --
+ *	Implements the ENV->get_lk_detect command.
+ */
+static int
+env_GetLockDetect(interp, objc, objv, dbenv)
+	Tcl_Interp *interp;		/* Interpreter */
+	int objc;			/* How many arguments? */
+	Tcl_Obj *CONST objv[];		/* The argument objects */
+	DB_ENV *dbenv;
+{
+	int i, ret, result;
+	u_int32_t lk_detect;
+	const char *answer;
+	Tcl_Obj *res;
+	static const struct {
+		u_int32_t flag;
+		char *name;
+	} lk_detect_returns[] = {
+		{ DB_LOCK_DEFAULT, "default" },
+		{ DB_LOCK_EXPIRE, "expire" },
+		{ DB_LOCK_MAXLOCKS, "maxlocks" },
+		{ DB_LOCK_MAXWRITE, "maxwrite" },
+		{ DB_LOCK_MINLOCKS, "minlocks" },
+		{ DB_LOCK_MINWRITE, "minwrite" },
+		{ DB_LOCK_OLDEST, "oldest" },
+		{ DB_LOCK_RANDOM, "random" },
+		{ DB_LOCK_YOUNGEST, "youngest" },
+		{ 0, NULL }
+	};
+
+	if (objc != 2) {
+		Tcl_WrongNumArgs(interp, 1, objv, NULL);
+		return (TCL_ERROR);
+	}
+	ret = dbenv->get_lk_detect(dbenv, &lk_detect);
+	if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+	    "env get_lk_detect")) == TCL_OK) {
+		answer = "unknown";
+		for (i = 0; lk_detect_returns[i].flag != 0; i++)
+			if (lk_detect == lk_detect_returns[i].flag)
+				answer = lk_detect_returns[i].name;
+
+		res = NewStringObj(answer, strlen(answer));
+		Tcl_SetObjResult(interp, res);
+	}
+
+	return (result);
+}
+
+/*
+ * env_GetTimeout --
+ *	Implements the ENV->get_timeout command.
+ */
+static int
+env_GetTimeout(interp, objc, objv, dbenv)
+	Tcl_Interp *interp;		/* Interpreter */
+	int objc;			/* How many arguments? */
+	Tcl_Obj *CONST objv[];		/* The argument objects */
+	DB_ENV *dbenv;
+{
+	static const struct {
+		u_int32_t flag;
+		char *arg;
+	} timeout_flags[] = {
+		{ DB_SET_TXN_TIMEOUT, "txn" },
+		{ DB_SET_LOCK_TIMEOUT, "lock" },
+		{ 0, NULL }
+	};
+	Tcl_Obj *res;
+	db_timeout_t timeout;
+	u_int32_t which;
+	int i, ret, result;
+	const char *arg;
+
+	COMPQUIET(timeout, 0);
+
+	if (objc != 3) {
+		Tcl_WrongNumArgs(interp, 1, objv, NULL);
+		return (TCL_ERROR);
+	}
+
+	arg = Tcl_GetStringFromObj(objv[2], NULL);
+	which = 0;
+	for (i = 0; timeout_flags[i].flag != 0; i++)
+		if (strcmp(arg, timeout_flags[i].arg) == 0)
+			which = timeout_flags[i].flag;
+	if (which == 0) {
+		ret = EINVAL;
+		goto err;
+	}
+
+	ret = dbenv->get_timeout(dbenv, &timeout, which);
+err:	if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+	    "env get_timeout")) == TCL_OK) {
+		res = Tcl_NewLongObj((long)timeout);
+		Tcl_SetObjResult(interp, res);
+	}
+
+	return (result);
+}
+
+/*
+ * env_GetVerbose --
+ *	Implements the ENV->get_open_flags command.
+ */
+static int
+env_GetVerbose(interp, objc, objv, dbenv)
+	Tcl_Interp *interp;		/* Interpreter */
+	int objc;			/* How many arguments? */
+	Tcl_Obj *CONST objv[];		/* The argument objects */
+	DB_ENV *dbenv;
+{
+	static const struct {
+		u_int32_t flag;
+		char *arg;
+	} verbose_flags[] = {
+		{ DB_VERB_DEADLOCK, "deadlock" },
+		{ DB_VERB_RECOVERY, "recovery" },
+		{ DB_VERB_REPLICATION, "rep" },
+		{ DB_VERB_WAITSFOR, "wait" },
+		{ 0, NULL }
+	};
+	Tcl_Obj *res;
+	u_int32_t which;
+	int i, onoff, ret, result;
+	const char *arg, *answer;
+
+	COMPQUIET(onoff, 0);
+
+	if (objc != 3) {
+		Tcl_WrongNumArgs(interp, 1, objv, NULL);
+		return (TCL_ERROR);
+	}
+
+	arg = Tcl_GetStringFromObj(objv[2], NULL);
+	which = 0;
+	for (i = 0; verbose_flags[i].flag != 0; i++)
+		if (strcmp(arg, verbose_flags[i].arg) == 0)
+			which = verbose_flags[i].flag;
+	if (which == 0) {
+		ret = EINVAL;
+		goto err;
+	}
+
+	ret = dbenv->get_verbose(dbenv, which, &onoff);
+err:	if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+	    "env get_timeout")) == 0) {
+		answer = onoff ? "on" : "off";
+		res = NewStringObj(answer, strlen(answer));
+		Tcl_SetObjResult(interp, res);
+	}
+
+	return (result);
+}
+
+/*
+ * PUBLIC: void tcl_EnvSetErrfile __P((Tcl_Interp *, DB_ENV *, DBTCL_INFO *,
+ * PUBLIC:    char *));
+ *
+ * tcl_EnvSetErrfile --
+ *	Implements the ENV->set_errfile command.
+ */
+void
+tcl_EnvSetErrfile(interp, dbenv, ip, errf)
+	Tcl_Interp *interp;		/* Interpreter */
+	DB_ENV *dbenv;			/* Database pointer */
+	DBTCL_INFO *ip;			/* Our internal info */
+	char *errf;
+{
+	COMPQUIET(interp, NULL);
+	/*
+	 * If the user already set one, free it.
+	 */
+	if (ip->i_err != NULL && ip->i_err != stdout &&
+	    ip->i_err != stderr)
+		(void)fclose(ip->i_err);
+	if (strcmp(errf, "/dev/stdout") == 0)
+		ip->i_err = stdout;
+	else if (strcmp(errf, "/dev/stderr") == 0)
+		ip->i_err = stderr;
+	else
+		ip->i_err = fopen(errf, "a");
+	if (ip->i_err != NULL)
+		dbenv->set_errfile(dbenv, ip->i_err);
+}
+
+/*
+ * PUBLIC: int tcl_EnvSetErrpfx __P((Tcl_Interp *, DB_ENV *, DBTCL_INFO *,
+ * PUBLIC:    char *));
+ *
+ * tcl_EnvSetErrpfx --
+ *	Implements the ENV->set_errpfx command.
+ */
+int
+tcl_EnvSetErrpfx(interp, dbenv, ip, pfx)
+	Tcl_Interp *interp;		/* Interpreter */
+	DB_ENV *dbenv;			/* Database pointer */
+	DBTCL_INFO *ip;			/* Our internal info */
+	char *pfx;
+{
+	int result, ret;
+
+	/*
+	 * Assume success.  The only thing that can fail is
+	 * the __os_strdup.
+	 */
+	result = TCL_OK;
+	Tcl_SetResult(interp, "0", TCL_STATIC);
+	/*
+	 * If the user already set one, free it.
+	 */
+	if (ip->i_errpfx != NULL)
+		__os_free(dbenv, ip->i_errpfx);
+	if ((ret = __os_strdup(dbenv, pfx, &ip->i_errpfx)) != 0) {
+		result = _ReturnSetup(interp, ret,
+		    DB_RETOK_STD(ret), "__os_strdup");
+		ip->i_errpfx = NULL;
+	}
+	if (ip->i_errpfx != NULL)
+		dbenv->set_errpfx(dbenv, ip->i_errpfx);
+	return (result);
+}
diff --git a/storage/bdb/tcl/tcl_internal.c b/storage/bdb/tcl/tcl_internal.c
index 2d6ad4df4447113768b5bbbe966c97a7396c1064..6927b3018931a297583341b723a26bc2f2eec031 100644
--- a/storage/bdb/tcl/tcl_internal.c
+++ b/storage/bdb/tcl/tcl_internal.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2001
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: tcl_internal.c,v 11.70 2004/10/25 18:04:44 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: tcl_internal.c,v 11.54 2002/08/15 02:47:46 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -23,7 +21,6 @@ static const char revid[] = "$Id: tcl_internal.c,v 11.54 2002/08/15 02:47:46 bos
 #include "dbinc/tcl_db.h"
 #include "dbinc/db_page.h"
 #include "dbinc/db_am.h"
-#include "dbinc_auto/db_ext.h"
 
 /*
  *
@@ -43,20 +40,6 @@ static const char revid[] = "$Id: tcl_internal.c,v 11.54 2002/08/15 02:47:46 bos
  *	get/manipulate the info structure.
  */
 
-/*
- * Prototypes for procedures defined later in this file:
- */
-static void tcl_flag_callback __P((u_int32_t, const FN *, void *));
-
-/*
- * Private structure type used to pass both an interp and an object into
- * a callback's single void *.
- */
-struct __tcl_callback_bundle {
-	Tcl_Interp *interp;
-	Tcl_Obj *obj;
-};
-
 #define	GLOB_CHAR(c)	((c) == '*' || (c) == '?')
 
 /*
@@ -184,8 +167,8 @@ _DeleteInfo(p)
 	LIST_REMOVE(p, entries);
 	if (p->i_lockobj.data != NULL)
 		__os_free(NULL, p->i_lockobj.data);
-	if (p->i_err != NULL) {
-		fclose(p->i_err);
+	if (p->i_err != NULL && p->i_err != stderr) {
+		(void)fclose(p->i_err);
 		p->i_err = NULL;
 	}
 	if (p->i_errpfx != NULL)
@@ -210,21 +193,21 @@ _DeleteInfo(p)
 
 /*
  * PUBLIC: int _SetListElem __P((Tcl_Interp *,
- * PUBLIC:    Tcl_Obj *, void *, int, void *, int));
+ * PUBLIC:    Tcl_Obj *, void *, u_int32_t, void *, u_int32_t));
  */
 int
 _SetListElem(interp, list, elem1, e1cnt, elem2, e2cnt)
 	Tcl_Interp *interp;
 	Tcl_Obj *list;
 	void *elem1, *elem2;
-	int e1cnt, e2cnt;
+	u_int32_t e1cnt, e2cnt;
 {
 	Tcl_Obj *myobjv[2], *thislist;
 	int myobjc;
 
 	myobjc = 2;
-	myobjv[0] = Tcl_NewByteArrayObj((u_char *)elem1, e1cnt);
-	myobjv[1] = Tcl_NewByteArrayObj((u_char *)elem2, e2cnt);
+	myobjv[0] = Tcl_NewByteArrayObj((u_char *)elem1, (int)e1cnt);
+	myobjv[1] = Tcl_NewByteArrayObj((u_char *)elem2, (int)e2cnt);
 	thislist = Tcl_NewListObj(myobjc, myobjv);
 	if (thislist == NULL)
 		return (TCL_ERROR);
@@ -233,30 +216,62 @@ _SetListElem(interp, list, elem1, e1cnt, elem2, e2cnt)
 }
 
 /*
- * PUBLIC: int _SetListElemInt __P((Tcl_Interp *, Tcl_Obj *, void *, int));
+ * PUBLIC: int _SetListElemInt __P((Tcl_Interp *, Tcl_Obj *, void *, long));
  */
 int
 _SetListElemInt(interp, list, elem1, elem2)
 	Tcl_Interp *interp;
 	Tcl_Obj *list;
 	void *elem1;
-	int elem2;
+	long elem2;
+{
+	Tcl_Obj *myobjv[2], *thislist;
+	int myobjc;
+
+	myobjc = 2;
+	myobjv[0] =
+	    Tcl_NewByteArrayObj((u_char *)elem1, (int)strlen((char *)elem1));
+	myobjv[1] = Tcl_NewLongObj(elem2);
+	thislist = Tcl_NewListObj(myobjc, myobjv);
+	if (thislist == NULL)
+		return (TCL_ERROR);
+	return (Tcl_ListObjAppendElement(interp, list, thislist));
+}
+
+/*
+ * Don't compile this code if we don't have sequences compiled into the DB
+ * library, it's likely because we don't have a 64-bit type, and trying to
+ * use int64_t is going to result in syntax errors.
+ */
+#ifdef HAVE_SEQUENCE
+/*
+ * PUBLIC: int _SetListElemWideInt __P((Tcl_Interp *,
+ * PUBLIC:     Tcl_Obj *, void *, int64_t));
+ */
+int
+_SetListElemWideInt(interp, list, elem1, elem2)
+	Tcl_Interp *interp;
+	Tcl_Obj *list;
+	void *elem1;
+	int64_t elem2;
 {
 	Tcl_Obj *myobjv[2], *thislist;
 	int myobjc;
 
 	myobjc = 2;
-	myobjv[0] = Tcl_NewByteArrayObj((u_char *)elem1, strlen((char *)elem1));
-	myobjv[1] = Tcl_NewIntObj(elem2);
+	myobjv[0] =
+	    Tcl_NewByteArrayObj((u_char *)elem1, (int)strlen((char *)elem1));
+	myobjv[1] = Tcl_NewWideIntObj(elem2);
 	thislist = Tcl_NewListObj(myobjc, myobjv);
 	if (thislist == NULL)
 		return (TCL_ERROR);
 	return (Tcl_ListObjAppendElement(interp, list, thislist));
 }
+#endif /* HAVE_SEQUENCE */
 
 /*
  * PUBLIC: int _SetListRecnoElem __P((Tcl_Interp *, Tcl_Obj *,
- * PUBLIC:     db_recno_t, u_char *, int));
+ * PUBLIC:     db_recno_t, u_char *, u_int32_t));
  */
 int
 _SetListRecnoElem(interp, list, elem1, elem2, e2size)
@@ -264,14 +279,14 @@ _SetListRecnoElem(interp, list, elem1, elem2, e2size)
 	Tcl_Obj *list;
 	db_recno_t elem1;
 	u_char *elem2;
-	int e2size;
+	u_int32_t e2size;
 {
 	Tcl_Obj *myobjv[2], *thislist;
 	int myobjc;
 
 	myobjc = 2;
-	myobjv[0] = Tcl_NewLongObj((long)elem1);
-	myobjv[1] = Tcl_NewByteArrayObj(elem2, e2size);
+	myobjv[0] = Tcl_NewWideIntObj((Tcl_WideInt)elem1);
+	myobjv[1] = Tcl_NewByteArrayObj(elem2, (int)e2size);
 	thislist = Tcl_NewListObj(myobjc, myobjv);
 	if (thislist == NULL)
 		return (TCL_ERROR);
@@ -306,18 +321,21 @@ _Set3DBTList(interp, list, elem1, is1recno, elem2, is2recno, elem3)
 	Tcl_Obj *myobjv[3], *thislist;
 
 	if (is1recno)
-		myobjv[0] = Tcl_NewLongObj((long)*(db_recno_t *)elem1->data);
+		myobjv[0] = Tcl_NewWideIntObj(
+		    (Tcl_WideInt)*(db_recno_t *)elem1->data);
 	else
-		myobjv[0] =
-		    Tcl_NewByteArrayObj((u_char *)elem1->data, elem1->size);
+		myobjv[0] = Tcl_NewByteArrayObj(
+		    (u_char *)elem1->data, (int)elem1->size);
 
 	if (is2recno)
-		myobjv[1] = Tcl_NewLongObj((long)*(db_recno_t *)elem2->data);
+		myobjv[1] = Tcl_NewWideIntObj(
+		    (Tcl_WideInt)*(db_recno_t *)elem2->data);
 	else
-		myobjv[1] =
-		    Tcl_NewByteArrayObj((u_char *)elem2->data, elem2->size);
+		myobjv[1] = Tcl_NewByteArrayObj(
+		    (u_char *)elem2->data, (int)elem2->size);
 
-	myobjv[2] = Tcl_NewByteArrayObj((u_char *)elem3->data, elem3->size);
+	myobjv[2] = Tcl_NewByteArrayObj(
+	    (u_char *)elem3->data, (int)elem3->size);
 
 	thislist = Tcl_NewListObj(3, myobjv);
 
@@ -330,14 +348,15 @@ _Set3DBTList(interp, list, elem1, is1recno, elem2, is2recno, elem3)
  * _SetMultiList -- build a list for return from multiple get.
  *
  * PUBLIC: int _SetMultiList __P((Tcl_Interp *,
- * PUBLIC:	    Tcl_Obj *, DBT *, DBT*, int, int));
+ * PUBLIC:	    Tcl_Obj *, DBT *, DBT*, DBTYPE, u_int32_t));
  */
 int
 _SetMultiList(interp, list, key, data, type, flag)
 	Tcl_Interp *interp;
 	Tcl_Obj *list;
 	DBT *key, *data;
-	int type, flag;
+	DBTYPE type;
+	u_int32_t flag;
 {
 	db_recno_t recno;
 	u_int32_t dlen, klen;
@@ -374,6 +393,9 @@ _SetMultiList(interp, list, key, data, type, flag)
 			result =
 			    _SetListRecnoElem(interp, list, recno, dp, dlen);
 			recno++;
+			/* Wrap around and skip zero. */
+			if (recno == 0)
+				recno++;
 		} else
 			result = _SetListElem(interp, list, kp, klen, dp, dlen);
 	} while (result == TCL_OK);
@@ -463,18 +485,21 @@ _ErrorSetup(interp, ret, errmsg)
 }
 
 /*
- * PUBLIC: void _ErrorFunc __P((CONST char *, char *));
+ * PUBLIC: void _ErrorFunc __P((const DB_ENV *, CONST char *, const char *));
  */
 void
-_ErrorFunc(pfx, msg)
+_ErrorFunc(dbenv, pfx, msg)
+	const DB_ENV *dbenv;
 	CONST char *pfx;
-	char *msg;
+	const char *msg;
 {
 	DBTCL_INFO *p;
 	Tcl_Interp *interp;
-	int size;
+	size_t size;
 	char *err;
 
+	COMPQUIET(dbenv, NULL);
+
 	p = _NameToInfo(pfx);
 	if (p == NULL)
 		return;
@@ -573,70 +598,41 @@ _GetUInt32(interp, obj, resp)
 }
 
 /*
- * tcl_flag_callback --
- *	Callback for db_pr.c functions that contain the FN struct mapping
- * flag values to meaningful strings.  This function appends a Tcl_Obj
- * containing each pertinent flag string to the specified Tcl list.
+ * _GetFlagsList --
+ *	Get a new Tcl object, containing a list of the string values
+ * associated with a particular set of flag values.
+ *
+ * PUBLIC: Tcl_Obj *_GetFlagsList __P((Tcl_Interp *, u_int32_t, const FN *));
  */
-static void
-tcl_flag_callback(flags, fn, vtcbp)
+Tcl_Obj *
+_GetFlagsList(interp, flags, fnp)
+	Tcl_Interp *interp;
 	u_int32_t flags;
-	const FN *fn;
-	void *vtcbp;
-{
 	const FN *fnp;
-	Tcl_Interp *interp;
-	Tcl_Obj *newobj, *listobj;
+{
+	Tcl_Obj *newlist, *newobj;
 	int result;
-	struct __tcl_callback_bundle *tcbp;
 
-	tcbp = (struct __tcl_callback_bundle *)vtcbp;
-	interp = tcbp->interp;
-	listobj = tcbp->obj;
+	newlist = Tcl_NewObj();
 
-	for (fnp = fn; fnp->mask != 0; ++fnp)
+	/*
+	 * Append a Tcl_Obj containing each pertinent flag string to the
+	 * specified Tcl list.
+	 */
+	for (; fnp->mask != 0; ++fnp)
 		if (LF_ISSET(fnp->mask)) {
-			newobj = Tcl_NewStringObj(fnp->name, strlen(fnp->name));
+			newobj = NewStringObj(fnp->name, strlen(fnp->name));
 			result =
-			    Tcl_ListObjAppendElement(interp, listobj, newobj);
+			    Tcl_ListObjAppendElement(interp, newlist, newobj);
 
 			/*
 			 * Tcl_ListObjAppendElement is defined to return TCL_OK
-			 * unless listobj isn't actually a list (or convertible
+			 * unless newlist isn't actually a list (or convertible
 			 * into one).  If this is the case, we screwed up badly
 			 * somehow.
 			 */
 			DB_ASSERT(result == TCL_OK);
 		}
-}
-
-/*
- * _GetFlagsList --
- *	Get a new Tcl object, containing a list of the string values
- * associated with a particular set of flag values, given a function
- * that can extract the right names for the right flags.
- *
- * PUBLIC: Tcl_Obj *_GetFlagsList __P((Tcl_Interp *, u_int32_t,
- * PUBLIC:     void (*)(u_int32_t, void *,
- * PUBLIC:     void (*)(u_int32_t, const FN *, void *))));
- */
-Tcl_Obj *
-_GetFlagsList(interp, flags, func)
-	Tcl_Interp *interp;
-	u_int32_t flags;
-	void (*func)
-	    __P((u_int32_t, void *, void (*)(u_int32_t, const FN *, void *)));
-{
-	Tcl_Obj *newlist;
-	struct __tcl_callback_bundle tcb;
-
-	newlist = Tcl_NewObj();
-
-	memset(&tcb, 0, sizeof(tcb));
-	tcb.interp = interp;
-	tcb.obj = newlist;
-
-	func(flags, &tcb, tcl_flag_callback);
 
 	return (newlist);
 }
@@ -654,7 +650,7 @@ _debug_check()
 
 	if (__debug_print != 0) {
 		printf("\r%7d:", __debug_on);
-		fflush(stdout);
+		(void)fflush(stdout);
 	}
 	if (__debug_on++ == __debug_test || __debug_stop)
 		__db_loadme();
@@ -696,7 +692,7 @@ _CopyObjBytes(interp, obj, newp, sizep, freep)
 	*freep = 0;
 	ret = Tcl_GetIntFromObj(interp, obj, &i);
 	tmp = Tcl_GetByteArrayFromObj(obj, &len);
-	*sizep = len;
+	*sizep = (u_int32_t)len;
 	if (ret == TCL_ERROR) {
 		Tcl_ResetResult(interp);
 		*newp = tmp;
@@ -708,9 +704,9 @@ _CopyObjBytes(interp, obj, newp, sizep, freep)
 	 * at some other point so we cannot count on GetByteArray
 	 * keeping our pointer valid.
 	 */
-	if ((ret = __os_malloc(NULL, len, &new)) != 0)
+	if ((ret = __os_malloc(NULL, (size_t)len, &new)) != 0)
 		return (ret);
-	memcpy(new, tmp, len);
+	memcpy(new, tmp, (size_t)len);
 	*newp = new;
 	*freep = 1;
 	return (0);
diff --git a/storage/bdb/tcl/tcl_lock.c b/storage/bdb/tcl/tcl_lock.c
index 6cb96dbb0da1ae5e1afce285554c97d43e4eb57b..4a3de36bd598a8a7196371f3a2f60be43a306337 100644
--- a/storage/bdb/tcl/tcl_lock.c
+++ b/storage/bdb/tcl/tcl_lock.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2001
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: tcl_lock.c,v 11.59 2004/10/07 16:48:39 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: tcl_lock.c,v 11.47 2002/08/08 15:27:10 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -25,30 +23,13 @@ static const char revid[] = "$Id: tcl_lock.c,v 11.47 2002/08/08 15:27:10 bostic
 /*
  * Prototypes for procedures defined later in this file:
  */
+#ifdef CONFIG_TEST
 static int      lock_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));
 static int	_LockMode __P((Tcl_Interp *, Tcl_Obj *, db_lockmode_t *));
 static int	_GetThisLock __P((Tcl_Interp *, DB_ENV *, u_int32_t,
 				     u_int32_t, DBT *, db_lockmode_t, char *));
 static void	_LockPutInfo __P((Tcl_Interp *, db_lockop_t, DB_LOCK *,
 				     u_int32_t, DBT *));
-#if CONFIG_TEST
-static char *lkmode[] = {
-	"ng",
-	"read",
-	"write",
-	"iwrite",
-	"iread",
-	"iwr",
-	 NULL
-};
-enum lkmode {
-	LK_NG,
-	LK_READ,
-	LK_WRITE,
-	LK_IWRITE,
-	LK_IREAD,
-	LK_IWR
-};
 
 /*
  * tcl_LockDetect --
@@ -63,10 +44,11 @@ tcl_LockDetect(interp, objc, objv, envp)
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 	DB_ENV *envp;			/* Environment pointer */
 {
-	static char *ldopts[] = {
-		"expire",
+	static const char *ldopts[] = {
 		"default",
+		"expire",
 		"maxlocks",
+		"maxwrites",
 		"minlocks",
 		"minwrites",
 		"oldest",
@@ -75,9 +57,10 @@ tcl_LockDetect(interp, objc, objv, envp)
 		 NULL
 	};
 	enum ldopts {
-		LD_EXPIRE,
 		LD_DEFAULT,
+		LD_EXPIRE,
 		LD_MAXLOCKS,
+		LD_MAXWRITES,
 		LD_MINLOCKS,
 		LD_MINWRITES,
 		LD_OLDEST,
@@ -96,38 +79,42 @@ tcl_LockDetect(interp, objc, objv, envp)
 			return (IS_HELP(objv[i]));
 		i++;
 		switch ((enum ldopts)optindex) {
-		case LD_EXPIRE:
-			FLAG_CHECK(policy);
-			policy = DB_LOCK_EXPIRE;
-			break;
 		case LD_DEFAULT:
 			FLAG_CHECK(policy);
 			policy = DB_LOCK_DEFAULT;
 			break;
+		case LD_EXPIRE:
+			FLAG_CHECK(policy);
+			policy = DB_LOCK_EXPIRE;
+			break;
 		case LD_MAXLOCKS:
 			FLAG_CHECK(policy);
 			policy = DB_LOCK_MAXLOCKS;
 			break;
-		case LD_MINWRITES:
+		case LD_MAXWRITES:
 			FLAG_CHECK(policy);
-			policy = DB_LOCK_MINWRITE;
+			policy = DB_LOCK_MAXWRITE;
 			break;
 		case LD_MINLOCKS:
 			FLAG_CHECK(policy);
 			policy = DB_LOCK_MINLOCKS;
 			break;
-		case LD_OLDEST:
+		case LD_MINWRITES:
 			FLAG_CHECK(policy);
-			policy = DB_LOCK_OLDEST;
+			policy = DB_LOCK_MINWRITE;
 			break;
-		case LD_YOUNGEST:
+		case LD_OLDEST:
 			FLAG_CHECK(policy);
-			policy = DB_LOCK_YOUNGEST;
+			policy = DB_LOCK_OLDEST;
 			break;
 		case LD_RANDOM:
 			FLAG_CHECK(policy);
 			policy = DB_LOCK_RANDOM;
 			break;
+		case LD_YOUNGEST:
+			FLAG_CHECK(policy);
+			policy = DB_LOCK_YOUNGEST;
+			break;
 		}
 	}
 
@@ -150,7 +137,7 @@ tcl_LockGet(interp, objc, objv, envp)
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 	DB_ENV *envp;			/* Environment pointer */
 {
-	static char *lgopts[] = {
+	static const char *lgopts[] = {
 		"-nowait",
 		 NULL
 	};
@@ -212,12 +199,12 @@ tcl_LockGet(interp, objc, objv, envp)
 
 	result = _GetThisLock(interp, envp, lockid, flag, &obj, mode, newname);
 	if (result == TCL_OK) {
-		res = Tcl_NewStringObj(newname, strlen(newname));
+		res = NewStringObj(newname, strlen(newname));
 		Tcl_SetObjResult(interp, res);
 	}
 out:
 	if (freeobj)
-		(void)__os_free(envp, otmp);
+		__os_free(envp, otmp);
 	return (result);
 }
 
@@ -285,7 +272,7 @@ tcl_LockStat(interp, objc, objv, envp)
 	MAKE_STAT_LIST("Number of transaction timeouts", sp->st_ntxntimeouts);
 	Tcl_SetObjResult(interp, res);
 error:
-	free(sp);
+	__os_ufree(envp, sp);
 	return (result);
 }
 
@@ -332,7 +319,7 @@ lock_Cmd(clientData, interp, objc, objv)
 	int objc;			/* How many arguments? */
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 {
-	static char *lkcmds[] = {
+	static const char *lkcmds[] = {
 		"put",
 		NULL
 	};
@@ -400,14 +387,14 @@ tcl_LockVec(interp, objc, objv, envp)
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 	DB_ENV *envp;			/* environment pointer */
 {
-	static char *lvopts[] = {
+	static const char *lvopts[] = {
 		"-nowait",
 		 NULL
 	};
 	enum lvopts {
 		LVNOWAIT
 	};
-	static char *lkops[] = {
+	static const char *lkops[] = {
 		"get",
 		"put",
 		"put_all",
@@ -422,6 +409,7 @@ tcl_LockVec(interp, objc, objv, envp)
 		LKPUTOBJ,
 		LKTIMEOUT
 	};
+
 	DB_LOCK *lock;
 	DB_LOCKREQ list;
 	DBT obj;
@@ -433,8 +421,10 @@ tcl_LockVec(interp, objc, objv, envp)
 
 	result = TCL_OK;
 	memset(newname, 0, MSG_SIZE);
+	memset(&list, 0, sizeof(DB_LOCKREQ));
 	flag = 0;
 	freeobj = 0;
+	otmp = NULL;
 
 	/*
 	 * If -nowait is given, it MUST be first arg.
@@ -518,10 +508,10 @@ tcl_LockVec(interp, objc, objv, envp)
 				    thisop);
 				goto error;
 			}
-			thisop = Tcl_NewStringObj(newname, strlen(newname));
+			thisop = NewStringObj(newname, strlen(newname));
 			(void)Tcl_ListObjAppendElement(interp, res, thisop);
-			if (freeobj) {
-				(void)__os_free(envp, otmp);
+			if (freeobj && otmp != NULL) {
+				__os_free(envp, otmp);
 				freeobj = 0;
 			}
 			continue;
@@ -591,8 +581,8 @@ tcl_LockVec(interp, objc, objv, envp)
 		if (ret != 0 && result == TCL_OK)
 			result = _ReturnSetup(interp, ret,
 			    DB_RETOK_STD(ret), "lock put");
-		if (freeobj) {
-			(void)__os_free(envp, otmp);
+		if (freeobj && otmp != NULL) {
+			__os_free(envp, otmp);
 			freeobj = 0;
 		}
 		/*
@@ -615,6 +605,23 @@ _LockMode(interp, obj, mode)
 	Tcl_Obj *obj;
 	db_lockmode_t *mode;
 {
+	static const char *lkmode[] = {
+		"ng",
+		"read",
+		"write",
+		"iwrite",
+		"iread",
+		"iwr",
+		 NULL
+	};
+	enum lkmode {
+		LK_NG,
+		LK_READ,
+		LK_WRITE,
+		LK_IWRITE,
+		LK_IREAD,
+		LK_IWR
+	};
 	int optindex;
 
 	if (Tcl_GetIndexFromObj(interp, obj, lkmode, "option",
@@ -731,7 +738,7 @@ _GetThisLock(interp, envp, lockid, flag, objp, mode, newname)
 	ip->i_parent = envip;
 	ip->i_locker = lockid;
 	_SetInfoData(ip, lock);
-	Tcl_CreateObjCommand(interp, newname,
+	(void)Tcl_CreateObjCommand(interp, newname,
 	    (Tcl_ObjCmdProc *)lock_Cmd, (ClientData)lock, NULL);
 error:
 	return (result);
diff --git a/storage/bdb/tcl/tcl_log.c b/storage/bdb/tcl/tcl_log.c
index be6eebfb013413e6e3d1115133f63065f79c0605..68c678101fe9b8dc221bc1c6d55d74564ef7e917 100644
--- a/storage/bdb/tcl/tcl_log.c
+++ b/storage/bdb/tcl/tcl_log.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: tcl_log.c,v 11.61 2004/04/05 20:18:32 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: tcl_log.c,v 11.52 2002/08/14 20:11:57 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -40,12 +38,12 @@ tcl_LogArchive(interp, objc, objv, envp)
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 	DB_ENV *envp;			/* Environment pointer */
 {
-	static char *archopts[] = {
-		"-arch_abs",	"-arch_data",	"-arch_log",
+	static const char *archopts[] = {
+		"-arch_abs",	"-arch_data",	"-arch_log",	"-arch_remove",
 		NULL
 	};
 	enum archopts {
-		ARCH_ABS,	ARCH_DATA,	ARCH_LOG
+		ARCH_ABS,	ARCH_DATA,	ARCH_LOG,	ARCH_REMOVE
 	};
 	Tcl_Obj *fileobj, *res;
 	u_int32_t flag;
@@ -74,6 +72,9 @@ tcl_LogArchive(interp, objc, objv, envp)
 		case ARCH_LOG:
 			flag |= DB_ARCH_LOG;
 			break;
+		case ARCH_REMOVE:
+			flag |= DB_ARCH_REMOVE;
+			break;
 		}
 	}
 	_debug_check();
@@ -83,7 +84,7 @@ tcl_LogArchive(interp, objc, objv, envp)
 	if (result == TCL_OK) {
 		res = Tcl_NewListObj(0, NULL);
 		for (file = list; file != NULL && *file != NULL; file++) {
-			fileobj = Tcl_NewStringObj(*file, strlen(*file));
+			fileobj = NewStringObj(*file, strlen(*file));
 			result = Tcl_ListObjAppendElement(interp, res, fileobj);
 			if (result != TCL_OK)
 				break;
@@ -183,7 +184,7 @@ tcl_LogFile(interp, objc, objv, envp)
 	}
 	result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "log_file");
 	if (ret == 0) {
-		res = Tcl_NewStringObj(name, strlen(name));
+		res = NewStringObj(name, strlen(name));
 		Tcl_SetObjResult(interp, res);
 	}
 
@@ -267,7 +268,7 @@ tcl_LogPut(interp, objc, objv, envp)
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 	DB_ENV *envp;			/* Environment pointer */
 {
-	static char *logputopts[] = {
+	static const char *logputopts[] = {
 		"-flush",
 		NULL
 	};
@@ -327,13 +328,13 @@ tcl_LogPut(interp, objc, objv, envp)
 	if (result == TCL_ERROR)
 		return (result);
 	res = Tcl_NewListObj(0, NULL);
-	intobj = Tcl_NewLongObj((long)lsn.file);
+	intobj = Tcl_NewWideIntObj((Tcl_WideInt)lsn.file);
 	result = Tcl_ListObjAppendElement(interp, res, intobj);
-	intobj = Tcl_NewLongObj((long)lsn.offset);
+	intobj = Tcl_NewWideIntObj((Tcl_WideInt)lsn.offset);
 	result = Tcl_ListObjAppendElement(interp, res, intobj);
 	Tcl_SetObjResult(interp, res);
 	if (freedata)
-		(void)__os_free(NULL, dtmp);
+		__os_free(NULL, dtmp);
 	return (result);
 }
 /*
@@ -400,7 +401,7 @@ tcl_LogStat(interp, objc, objv, envp)
 	MAKE_STAT_LIST("Number of region lock nowaits", sp->st_region_nowait);
 	Tcl_SetObjResult(interp, res);
 error:
-	free(sp);
+	__os_ufree(envp, sp);
 	return (result);
 }
 
@@ -417,7 +418,7 @@ logc_Cmd(clientData, interp, objc, objv)
 	int objc;			/* How many arguments? */
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 {
-	static char *logccmds[] = {
+	static const char *logccmds[] = {
 		"close",
 		"get",
 		NULL
@@ -487,7 +488,7 @@ tcl_LogcGet(interp, objc, objv, logc)
 	Tcl_Obj * CONST *objv;
 	DB_LOGC *logc;
 {
-	static char *logcgetopts[] = {
+	static const char *logcgetopts[] = {
 		"-current",
 		"-first",
 		"-last",
@@ -581,14 +582,14 @@ tcl_LogcGet(interp, objc, objv, logc)
 		 * is a sublist {file offset}.
 		 */
 		myobjc = 2;
-		myobjv[0] = Tcl_NewLongObj((long)lsn.file);
-		myobjv[1] = Tcl_NewLongObj((long)lsn.offset);
+		myobjv[0] = Tcl_NewWideIntObj((Tcl_WideInt)lsn.file);
+		myobjv[1] = Tcl_NewWideIntObj((Tcl_WideInt)lsn.offset);
 		lsnlist = Tcl_NewListObj(myobjc, myobjv);
 		if (lsnlist == NULL)
 			goto memerr;
 
 		result = Tcl_ListObjAppendElement(interp, res, lsnlist);
-		dataobj = Tcl_NewStringObj(data.data, data.size);
+		dataobj = NewStringObj(data.data, data.size);
 		if (dataobj == NULL) {
 			goto memerr;
 		}
diff --git a/storage/bdb/tcl/tcl_mp.c b/storage/bdb/tcl/tcl_mp.c
index 0c4411cb58a4a0d70c0dbfa8124c16261b3d5605..29691a31c50c4dba5fe38428bd9c33074bbc3b23 100644
--- a/storage/bdb/tcl/tcl_mp.c
+++ b/storage/bdb/tcl/tcl_mp.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2001
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: tcl_mp.c,v 11.58 2004/10/07 16:48:39 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: tcl_mp.c,v 11.39 2002/08/06 06:21:27 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -25,6 +23,7 @@ static const char revid[] = "$Id: tcl_mp.c,v 11.39 2002/08/06 06:21:27 bostic Ex
 /*
  * Prototypes for procedures defined later in this file:
  */
+#ifdef CONFIG_TEST
 static int      mp_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));
 static int      pg_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));
 static int      tcl_MpGet __P((Tcl_Interp *, int, Tcl_Obj * CONST*,
@@ -35,6 +34,7 @@ static int      tcl_PgInit __P((Tcl_Interp *, int, Tcl_Obj * CONST*,
     void *, DBTCL_INFO *));
 static int      tcl_PgIsset __P((Tcl_Interp *, int, Tcl_Obj * CONST*,
     void *, DBTCL_INFO *));
+#endif
 
 /*
  * _MpInfoDelete --
@@ -56,14 +56,14 @@ _MpInfoDelete(interp, mpip)
 		 * mp.  Remove its commands and info structure.
 		 */
 		nextp = LIST_NEXT(p, entries);
-		 if (p->i_parent == mpip && p->i_type == I_PG) {
+		if (p->i_parent == mpip && p->i_type == I_PG) {
 			(void)Tcl_DeleteCommand(interp, p->i_name);
 			_DeleteInfo(p);
 		}
 	}
 }
 
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 /*
  * tcl_MpSync --
  *
@@ -98,8 +98,7 @@ tcl_MpSync(interp, objc, objv, envp)
 
 	_debug_check();
 	ret = envp->memp_sync(envp, lsnp);
-	result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "memp sync");
-	return (result);
+	return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret), "memp sync"));
 }
 
 /*
@@ -116,11 +115,8 @@ tcl_MpTrickle(interp, objc, objv, envp)
 	DB_ENV *envp;			/* Environment pointer */
 {
 
-	int pages;
-	int percent;
-	int result;
-	int ret;
 	Tcl_Obj *res;
+	int pages, percent, result, ret;
 
 	result = TCL_OK;
 	/*
@@ -161,7 +157,7 @@ tcl_Mp(interp, objc, objv, envp, envip)
 	DB_ENV *envp;			/* Environment pointer */
 	DBTCL_INFO *envip;		/* Info pointer */
 {
-	static char *mpopts[] = {
+	static const char *mpopts[] = {
 		"-create",
 		"-mode",
 		"-nommap",
@@ -296,9 +292,9 @@ tcl_Mp(interp, objc, objv, envp, envip)
 	ip->i_parent = envip;
 	ip->i_pgsz = pgsize;
 	_SetInfoData(ip, mpf);
-	Tcl_CreateObjCommand(interp, newname,
+	(void)Tcl_CreateObjCommand(interp, newname,
 	    (Tcl_ObjCmdProc *)mp_Cmd, (ClientData)mpf, NULL);
-	res = Tcl_NewStringObj(newname, strlen(newname));
+	res = NewStringObj(newname, strlen(newname));
 	Tcl_SetObjResult(interp, res);
 
 error:
@@ -351,6 +347,11 @@ tcl_MpStat(interp, objc, objv, envp)
 	MAKE_STAT_LIST("Cache size (bytes)", sp->st_bytes);
 	MAKE_STAT_LIST("Number of caches", sp->st_ncache);
 	MAKE_STAT_LIST("Region size", sp->st_regsize);
+	MAKE_STAT_LIST("Maximum memory-mapped file size", sp->st_mmapsize);
+	MAKE_STAT_LIST("Maximum open file descriptors", sp->st_maxopenfd);
+	MAKE_STAT_LIST("Maximum sequential buffer writes", sp->st_maxwrite);
+	MAKE_STAT_LIST(
+	    "Sleep after writing maximum buffers", sp->st_maxwrite_sleep);
 	MAKE_STAT_LIST("Pages mapped into address space", sp->st_map);
 	MAKE_STAT_LIST("Cache hits", sp->st_cache_hit);
 	MAKE_STAT_LIST("Cache misses", sp->st_cache_miss);
@@ -413,9 +414,9 @@ tcl_MpStat(interp, objc, objv, envp)
 	}
 	Tcl_SetObjResult(interp, res1);
 error:
-	free(sp);
+	__os_ufree(envp, sp);
 	if (savefsp != NULL)
-		free(savefsp);
+		__os_ufree(envp, savefsp);
 	return (result);
 }
 
@@ -430,22 +431,36 @@ mp_Cmd(clientData, interp, objc, objv)
 	int objc;			/* How many arguments? */
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 {
-	static char *mpcmds[] = {
+	static const char *mpcmds[] = {
 		"close",
 		"fsync",
 		"get",
+		"get_clear_len",
+		"get_fileid",
+		"get_ftype",
+		"get_lsn_offset",
+		"get_pgcookie",
 		NULL
 	};
 	enum mpcmds {
 		MPCLOSE,
 		MPFSYNC,
-		MPGET
+		MPGET,
+		MPGETCLEARLEN,
+		MPGETFILEID,
+		MPGETFTYPE,
+		MPGETLSNOFFSET,
+		MPGETPGCOOKIE
 	};
 	DB_MPOOLFILE *mp;
-	int cmdindex, length, result, ret;
+	int cmdindex, ftype, length, result, ret;
 	DBTCL_INFO *mpip;
 	Tcl_Obj *res;
 	char *obj_name;
+	u_int32_t value;
+	int32_t intval;
+	u_int8_t fileid[DB_FILE_ID_LEN];
+	DBT cookie;
 
 	Tcl_ResetResult(interp);
 	mp = (DB_MPOOLFILE *)clientData;
@@ -497,6 +512,58 @@ mp_Cmd(clientData, interp, objc, objv)
 	case MPGET:
 		result = tcl_MpGet(interp, objc, objv, mp, mpip);
 		break;
+	case MPGETCLEARLEN:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = mp->get_clear_len(mp, &value);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "mp get_clear_len")) == TCL_OK)
+			res = Tcl_NewIntObj((int)value);
+		break;
+	case MPGETFILEID:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = mp->get_fileid(mp, fileid);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "mp get_fileid")) == TCL_OK)
+			res = NewStringObj((char *)fileid, DB_FILE_ID_LEN);
+		break;
+	case MPGETFTYPE:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = mp->get_ftype(mp, &ftype);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "mp get_ftype")) == TCL_OK)
+			res = Tcl_NewIntObj(ftype);
+		break;
+	case MPGETLSNOFFSET:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = mp->get_lsn_offset(mp, &intval);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "mp get_lsn_offset")) == TCL_OK)
+			res = Tcl_NewIntObj(intval);
+		break;
+	case MPGETPGCOOKIE:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		memset(&cookie, 0, sizeof(DBT));
+		ret = mp->get_pgcookie(mp, &cookie);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "mp get_pgcookie")) == TCL_OK)
+			res = Tcl_NewByteArrayObj((u_char *)cookie.data,
+			    (int)cookie.size);
+		break;
 	}
 	/*
 	 * Only set result if we have a res.  Otherwise, lower
@@ -518,7 +585,7 @@ tcl_MpGet(interp, objc, objv, mp, mpip)
 	DB_MPOOLFILE *mp;		/* mp pointer */
 	DBTCL_INFO *mpip;		/* mp info pointer */
 {
-	static char *mpget[] = {
+	static const char *mpget[] = {
 		"-create",
 		"-last",
 		"-new",
@@ -594,7 +661,7 @@ tcl_MpGet(interp, objc, objv, mp, mpip)
 		return (TCL_ERROR);
 	}
 	_debug_check();
-	pgno = ipgno;
+	pgno = (db_pgno_t)ipgno;
 	ret = mp->get(mp, &pgno, flag, &page);
 	result = _ReturnSetup(interp, ret, DB_RETOK_MPGET(ret), "mpool get");
 	if (result == TCL_ERROR)
@@ -609,9 +676,9 @@ tcl_MpGet(interp, objc, objv, mp, mpip)
 		ip->i_pgno = pgno;
 		ip->i_pgsz = mpip->i_pgsz;
 		_SetInfoData(ip, page);
-		Tcl_CreateObjCommand(interp, newname,
+		(void)Tcl_CreateObjCommand(interp, newname,
 		    (Tcl_ObjCmdProc *)pg_Cmd, (ClientData)page, NULL);
-		res = Tcl_NewStringObj(newname, strlen(newname));
+		res = NewStringObj(newname, strlen(newname));
 		Tcl_SetObjResult(interp, res);
 	}
 error:
@@ -629,7 +696,7 @@ pg_Cmd(clientData, interp, objc, objv)
 	int objc;			/* How many arguments? */
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 {
-	static char *pgcmds[] = {
+	static const char *pgcmds[] = {
 		"init",
 		"is_setto",
 		"pgnum",
@@ -684,15 +751,15 @@ pg_Cmd(clientData, interp, objc, objv)
 	res = NULL;
 	switch ((enum pgcmds)cmdindex) {
 	case PGNUM:
-		res = Tcl_NewLongObj((long)pgip->i_pgno);
+		res = Tcl_NewWideIntObj((Tcl_WideInt)pgip->i_pgno);
 		break;
 	case PGSIZE:
-		res = Tcl_NewLongObj(pgip->i_pgsz);
+		res = Tcl_NewWideIntObj((Tcl_WideInt)pgip->i_pgsz);
 		break;
 	case PGSET:
 	case PGPUT:
 		result = tcl_Pg(interp, objc, objv, page, mp, pgip,
-		    cmdindex == PGSET ? 0 : 1);
+		    (enum pgcmds)cmdindex == PGSET ? 0 : 1);
 		break;
 	case PGINIT:
 		result = tcl_PgInit(interp, objc, objv, page, pgip);
@@ -701,11 +768,12 @@ pg_Cmd(clientData, interp, objc, objv)
 		result = tcl_PgIsset(interp, objc, objv, page, pgip);
 		break;
 	}
+
 	/*
 	 * Only set result if we have a res.  Otherwise, lower
 	 * functions have already done so.
 	 */
-	if (result == TCL_OK && res)
+	if (result == TCL_OK && res != NULL)
 		Tcl_SetObjResult(interp, res);
 	return (result);
 }
@@ -720,7 +788,7 @@ tcl_Pg(interp, objc, objv, page, mp, pgip, putop)
 	DBTCL_INFO *pgip;		/* Info pointer */
 	int putop;			/* Operation */
 {
-	static char *pgopt[] = {
+	static const char *pgopt[] = {
 		"-clean",
 		"-dirty",
 		"-discard",
@@ -779,9 +847,8 @@ tcl_PgInit(interp, objc, objv, page, pgip)
 	DBTCL_INFO *pgip;		/* Info pointer */
 {
 	Tcl_Obj *res;
-	size_t pgsz;
 	long *p, *endp, newval;
-	int length, result;
+	int length, pgsz, result;
 	u_char *s;
 
 	result = TCL_OK;
@@ -796,12 +863,11 @@ tcl_PgInit(interp, objc, objv, page, pgip)
 		s = Tcl_GetByteArrayFromObj(objv[2], &length);
 		if (s == NULL)
 			return (TCL_ERROR);
-		memcpy(page, s,
-		    ((size_t)length < pgsz) ? (size_t)length : pgsz);
+		memcpy(page, s, (size_t)((length < pgsz) ? length : pgsz));
 		result = TCL_OK;
 	} else {
 		p = (long *)page;
-		for (endp = p + (pgsz / sizeof(long)); p < endp; p++)
+		for (endp = p + ((u_int)pgsz / sizeof(long)); p < endp; p++)
 			*p = newval;
 	}
 	res = Tcl_NewIntObj(0);
@@ -818,9 +884,8 @@ tcl_PgIsset(interp, objc, objv, page, pgip)
 	DBTCL_INFO *pgip;		/* Info pointer */
 {
 	Tcl_Obj *res;
-	size_t pgsz;
 	long *p, *endp, newval;
-	int length, result;
+	int length, pgsz, result;
 	u_char *s;
 
 	result = TCL_OK;
@@ -837,7 +902,7 @@ tcl_PgIsset(interp, objc, objv, page, pgip)
 		result = TCL_OK;
 
 		if (memcmp(page, s,
-		    ((size_t)length < pgsz) ? (size_t)length : pgsz ) != 0) {
+		    (size_t)((length < pgsz) ? length : pgsz)) != 0) {
 			res = Tcl_NewIntObj(0);
 			Tcl_SetObjResult(interp, res);
 			return (result);
@@ -849,7 +914,7 @@ tcl_PgIsset(interp, objc, objv, page, pgip)
 		 * this value).  Otherwise, if we finish the loop, we return 1
 		 * (is set to this value).
 		 */
-		for (endp = p + (pgsz/sizeof(long)); p < endp; p++)
+		for (endp = p + ((u_int)pgsz / sizeof(long)); p < endp; p++)
 			if (*p != newval) {
 				res = Tcl_NewIntObj(0);
 				Tcl_SetObjResult(interp, res);
diff --git a/storage/bdb/tcl/tcl_rep.c b/storage/bdb/tcl/tcl_rep.c
index c72c9971338f6d7c23cd4e475a91e581f593e9c4..e0e6a1a883c3fdd25140bde203e6bbd33f85c2b2 100644
--- a/storage/bdb/tcl/tcl_rep.c
+++ b/storage/bdb/tcl/tcl_rep.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2002
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: tcl_rep.c,v 11.106 2004/10/14 18:09:00 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: tcl_rep.c,v 11.85 2002/08/06 04:45:44 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -22,7 +20,7 @@ static const char revid[] = "$Id: tcl_rep.c,v 11.85 2002/08/06 04:45:44 bostic E
 #include "db_int.h"
 #include "dbinc/tcl_db.h"
 
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 /*
  * tcl_RepElect --
  *	Call DB_ENV->rep_elect().
@@ -37,23 +35,26 @@ tcl_RepElect(interp, objc, objv, dbenv)
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 	DB_ENV *dbenv;			/* Environment pointer */
 {
-	int eid, nsites, pri, result, ret;
+	int eid, nsites, nvotes, pri, result, ret;
 	u_int32_t timeout;
 
-	if (objc != 5) {
-		Tcl_WrongNumArgs(interp, 5, objv, "nsites pri timeout");
+	if (objc != 6) {
+		Tcl_WrongNumArgs(interp, 6, objv, "nsites pri timeout");
 		return (TCL_ERROR);
 	}
 
 	if ((result = Tcl_GetIntFromObj(interp, objv[2], &nsites)) != TCL_OK)
 		return (result);
-	if ((result = Tcl_GetIntFromObj(interp, objv[3], &pri)) != TCL_OK)
+	if ((result = Tcl_GetIntFromObj(interp, objv[3], &nvotes)) != TCL_OK)
 		return (result);
-	if ((result = _GetUInt32(interp, objv[4], &timeout)) != TCL_OK)
+	if ((result = Tcl_GetIntFromObj(interp, objv[4], &pri)) != TCL_OK)
+		return (result);
+	if ((result = _GetUInt32(interp, objv[5], &timeout)) != TCL_OK)
 		return (result);
 
 	_debug_check();
-	if ((ret = dbenv->rep_elect(dbenv, nsites, pri, timeout, &eid)) != 0)
+	if ((ret = dbenv->rep_elect(dbenv, nsites, nvotes,
+	    pri, timeout, &eid, 0)) != 0)
 		return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret),
 		    "env rep_elect"));
 
@@ -63,7 +64,7 @@ tcl_RepElect(interp, objc, objv, dbenv)
 }
 #endif
 
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 /*
  * tcl_RepFlush --
  *	Call DB_ENV->rep_flush().
@@ -90,7 +91,7 @@ tcl_RepFlush(interp, objc, objv, dbenv)
 	return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret), "env rep_flush"));
 }
 #endif
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 /*
  * tcl_RepLimit --
  *	Call DB_ENV->set_rep_limit().
@@ -128,7 +129,7 @@ tcl_RepLimit(interp, objc, objv, dbenv)
 }
 #endif
 
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 /*
  * tcl_RepRequest --
  *	Call DB_ENV->set_rep_request().
@@ -166,7 +167,7 @@ tcl_RepRequest(interp, objc, objv, dbenv)
 }
 #endif
 
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 /*
  * tcl_RepStart --
  *	Call DB_ENV->rep_start().
@@ -185,7 +186,7 @@ tcl_RepStart(interp, objc, objv, dbenv)
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 	DB_ENV *dbenv;
 {
-	static char *tclrpstrt[] = {
+	static const char *tclrpstrt[] = {
 		"-client",
 		"-master",
 		NULL
@@ -233,7 +234,7 @@ tcl_RepStart(interp, objc, objv, dbenv)
 }
 #endif
 
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 /*
  * tcl_RepProcessMessage --
  *	Call DB_ENV->rep_process_message().
@@ -249,10 +250,12 @@ tcl_RepProcessMessage(interp, objc, objv, dbenv)
 	DB_ENV *dbenv;			/* Environment pointer */
 {
 	DBT control, rec;
-	Tcl_Obj *res;
+	DB_LSN permlsn;
+	Tcl_Obj *lsnlist, *myobjv[2], *res;
 	void *ctmp, *rtmp;
+	char *msg;
 	int eid;
-	int freectl, freerec, result, ret;
+	int freectl, freerec, myobjc, result, ret;
 
 	if (objc != 5) {
 		Tcl_WrongNumArgs(interp, 5, objv, "id control rec");
@@ -283,32 +286,100 @@ tcl_RepProcessMessage(interp, objc, objv, dbenv)
 	}
 	rec.data = rtmp;
 	_debug_check();
-	ret = dbenv->rep_process_message(dbenv, &control, &rec, &eid);
-	result = _ReturnSetup(interp, ret, DB_RETOK_REPPMSG(ret),
+	ret = dbenv->rep_process_message(dbenv, &control, &rec, &eid, &permlsn);
+	/*
+	 * !!!
+	 * The TCL API diverges from the C++/Java APIs here.  For us, it
+	 * is OK to get DUPMASTER and HOLDELECTION for testing purposes.
+	 */
+	result = _ReturnSetup(interp, ret,
+	    DB_RETOK_REPPMSG(ret) || ret == DB_REP_DUPMASTER ||
+	    ret == DB_REP_HOLDELECTION,
 	    "env rep_process_message");
 
+	if (result != TCL_OK)
+		goto out;
+
 	/*
-	 * If we have a new master, return its environment ID.
-	 *
-	 * XXX
-	 * We should do something prettier to differentiate success
-	 * from an env ID, and figure out how to represent HOLDELECTION.
+	 * We have a valid return.  We need to return a variety of information.
+	 * It will be one of the following:
+	 * {0 0} -  Make a 0 return a list for consistent return structure.
+	 * {DUPMASTER 0} -  DUPMASTER, no other info needed.
+	 * {HOLDELECTION 0} -  HOLDELECTION, no other info needed.
+	 * {NEWMASTER #} - NEWMASTER and its ID.
+	 * {NEWSITE 0} - NEWSITE, no other info needed.
+	 * {STARTUPDONE 0} - STARTUPDONE, no other info needed.
+	 * {ISPERM {LSN list}} - ISPERM and the perm LSN.
+	 * {NOTPERM {LSN list}} - NOTPERM and this msg's LSN.
 	 */
-	if (result == TCL_OK && ret == DB_REP_NEWMASTER) {
-		res = Tcl_NewIntObj(eid);
-		Tcl_SetObjResult(interp, res);
+	myobjc = 2;
+	switch (ret) {
+	case 0:
+		myobjv[0] = Tcl_NewIntObj(0);
+		myobjv[1] = Tcl_NewIntObj(0);
+		break;
+	case DB_REP_DUPMASTER:
+		myobjv[0] = Tcl_NewByteArrayObj(
+		    (u_char *)"DUPMASTER", (int)strlen("DUPMASTER"));
+		myobjv[1] = Tcl_NewIntObj(0);
+		break;
+	case DB_REP_HOLDELECTION:
+		myobjv[0] = Tcl_NewByteArrayObj(
+		    (u_char *)"HOLDELECTION", (int)strlen("HOLDELECTION"));
+		myobjv[1] = Tcl_NewIntObj(0);
+		break;
+	case DB_REP_ISPERM:
+		myobjv[0] = Tcl_NewLongObj((long)permlsn.file);
+		myobjv[1] = Tcl_NewLongObj((long)permlsn.offset);
+		lsnlist = Tcl_NewListObj(myobjc, myobjv);
+		myobjv[0] = Tcl_NewByteArrayObj(
+		    (u_char *)"ISPERM", (int)strlen("ISPERM"));
+		myobjv[1] = lsnlist;
+		break;
+	case DB_REP_NEWMASTER:
+		myobjv[0] = Tcl_NewByteArrayObj(
+		    (u_char *)"NEWMASTER", (int)strlen("NEWMASTER"));
+		myobjv[1] = Tcl_NewIntObj(eid);
+		break;
+	case DB_REP_NEWSITE:
+		myobjv[0] = Tcl_NewByteArrayObj(
+		    (u_char *)"NEWSITE", (int)strlen("NEWSITE"));
+		myobjv[1] = Tcl_NewIntObj(0);
+		break;
+	case DB_REP_NOTPERM:
+		myobjv[0] = Tcl_NewLongObj((long)permlsn.file);
+		myobjv[1] = Tcl_NewLongObj((long)permlsn.offset);
+		lsnlist = Tcl_NewListObj(myobjc, myobjv);
+		myobjv[0] = Tcl_NewByteArrayObj(
+		    (u_char *)"NOTPERM", (int)strlen("NOTPERM"));
+		myobjv[1] = lsnlist;
+		break;
+	case DB_REP_STARTUPDONE:
+		myobjv[0] = Tcl_NewByteArrayObj(
+		    (u_char *)"STARTUPDONE", (int)strlen("STARTUPDONE"));
+		myobjv[1] = Tcl_NewIntObj(0);
+		break;
+	default:
+		msg = db_strerror(ret);
+		Tcl_AppendResult(interp, msg, NULL);
+		Tcl_SetErrorCode(interp, "BerkeleyDB", msg, NULL);
+		result = TCL_ERROR;
+		goto out;
 	}
+	res = Tcl_NewListObj(myobjc, myobjv);
+	if (res != NULL)
+		Tcl_SetObjResult(interp, res);
 out:
 	if (freectl)
-		(void)__os_free(NULL, ctmp);
+		__os_free(NULL, ctmp);
 	if (freerec)
-		(void)__os_free(NULL, rtmp);
+		__os_free(NULL, rtmp);
 
 	return (result);
 }
 #endif
 
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 /*
  * tcl_RepStat --
  *	Call DB_ENV->rep_stat().
@@ -362,12 +433,18 @@ tcl_RepStat(interp, objc, objv, dbenv)
 	/*
 	 * MAKE_STAT_* assumes 'res' and 'error' label.
 	 */
+	if (sp->st_status == DB_REP_MASTER)
+		MAKE_STAT_LIST("Master", 1);
+	else
+		MAKE_STAT_LIST("Client", 1);
 	MAKE_STAT_LSN("Next LSN expected", &sp->st_next_lsn);
 	MAKE_STAT_LSN("First missed LSN", &sp->st_waiting_lsn);
 	MAKE_STAT_LIST("Duplicate master conditions", sp->st_dupmasters);
 	MAKE_STAT_LIST("Environment ID", sp->st_env_id);
 	MAKE_STAT_LIST("Environment priority", sp->st_env_priority);
 	MAKE_STAT_LIST("Generation number", sp->st_gen);
+	MAKE_STAT_LIST("Election generation number", sp->st_egen);
+	MAKE_STAT_LIST("Startup complete", sp->st_startup_complete);
 	MAKE_STAT_LIST("Duplicate log records received", sp->st_log_duplicated);
 	MAKE_STAT_LIST("Current log records queued", sp->st_log_queued);
 	MAKE_STAT_LIST("Maximum log records queued", sp->st_log_queued_max);
@@ -383,9 +460,15 @@ tcl_RepStat(interp, objc, objv, dbenv)
 	MAKE_STAT_LIST("Message send failures", sp->st_msgs_send_failures);
 	MAKE_STAT_LIST("Messages sent", sp->st_msgs_sent);
 	MAKE_STAT_LIST("New site messages", sp->st_newsites);
+	MAKE_STAT_LIST("Number of sites in replication group", sp->st_nsites);
 	MAKE_STAT_LIST("Transmission limited", sp->st_nthrottles);
 	MAKE_STAT_LIST("Outdated conditions", sp->st_outdated);
 	MAKE_STAT_LIST("Transactions applied", sp->st_txns_applied);
+	MAKE_STAT_LIST("Next page expected", sp->st_next_pg);
+	MAKE_STAT_LIST("First missed page", sp->st_waiting_pg);
+	MAKE_STAT_LIST("Duplicate pages received", sp->st_pg_duplicated);
+	MAKE_STAT_LIST("Pages received", sp->st_pg_records);
+	MAKE_STAT_LIST("Pages requested", sp->st_pg_requested);
 	MAKE_STAT_LIST("Elections held", sp->st_elections);
 	MAKE_STAT_LIST("Elections won", sp->st_elections_won);
 	MAKE_STAT_LIST("Election phase", sp->st_election_status);
@@ -393,13 +476,14 @@ tcl_RepStat(interp, objc, objv, dbenv)
 	MAKE_STAT_LIST("Election generation number", sp->st_election_gen);
 	MAKE_STAT_LSN("Election max LSN", &sp->st_election_lsn);
 	MAKE_STAT_LIST("Election sites", sp->st_election_nsites);
+	MAKE_STAT_LIST("Election votes", sp->st_election_nvotes);
 	MAKE_STAT_LIST("Election priority", sp->st_election_priority);
 	MAKE_STAT_LIST("Election tiebreaker", sp->st_election_tiebreaker);
 	MAKE_STAT_LIST("Election votes", sp->st_election_votes);
 
 	Tcl_SetObjResult(interp, res);
 error:
-	free(sp);
+	__os_ufree(dbenv, sp);
 	return (result);
 }
 #endif
diff --git a/storage/bdb/tcl/tcl_seq.c b/storage/bdb/tcl/tcl_seq.c
new file mode 100644
index 0000000000000000000000000000000000000000..de3e4dd616155e2ff810780c13cc9fbfe5f7abe4
--- /dev/null
+++ b/storage/bdb/tcl/tcl_seq.c
@@ -0,0 +1,526 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2004
+ *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: tcl_seq.c,v 11.12 2004/10/25 18:02:56 bostic Exp $
+ */
+
+#include "db_config.h"
+
+#ifdef HAVE_SEQUENCE
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#include <tcl.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/tcl_db.h"
+#include "dbinc_auto/sequence_ext.h"
+
+/*
+ * Prototypes for procedures defined later in this file:
+ */
+static int	tcl_SeqClose __P((Tcl_Interp *,
+    int, Tcl_Obj * CONST*, DB_SEQUENCE *, DBTCL_INFO *));
+static int	tcl_SeqGet __P((Tcl_Interp *,
+    int, Tcl_Obj * CONST*, DB_SEQUENCE *));
+static int	tcl_SeqRemove __P((Tcl_Interp *,
+    int, Tcl_Obj * CONST*, DB_SEQUENCE *, DBTCL_INFO *));
+static int	tcl_SeqStat __P((Tcl_Interp *,
+    int, Tcl_Obj * CONST*, DB_SEQUENCE *));
+static int	tcl_SeqGetFlags __P((Tcl_Interp *,
+    int, Tcl_Obj * CONST*, DB_SEQUENCE *));
+
+/*
+ *
+ * PUBLIC: int seq_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));
+ *
+ * seq_Cmd --
+ *	Implements the "seq" widget.
+ */
+int
+seq_Cmd(clientData, interp, objc, objv)
+	ClientData clientData;		/* SEQ handle */
+	Tcl_Interp *interp;		/* Interpreter */
+	int objc;			/* How many arguments? */
+	Tcl_Obj *CONST objv[];		/* The argument objects */
+{
+	static const char *seqcmds[] = {
+		"close",
+		"get",
+		"get_cachesize",
+		"get_db",
+		"get_flags",
+		"get_key",
+		"get_range",
+		"remove",
+		"stat",
+		NULL
+	};
+	enum seqcmds {
+		SEQCLOSE,
+		SEQGET,
+		SEQGETCACHESIZE,
+		SEQGETDB,
+		SEQGETFLAGS,
+		SEQGETKEY,
+		SEQGETRANGE,
+		SEQREMOVE,
+		SEQSTAT
+	};
+	DB *dbp;
+	DBT key;
+	DBTCL_INFO *dbip, *ip;
+	DB_SEQUENCE *seq;
+	Tcl_Obj *myobjv[2], *res;
+	db_seq_t min, max;
+	int cmdindex, ncache, result, ret;
+
+	Tcl_ResetResult(interp);
+	seq = (DB_SEQUENCE *)clientData;
+	result = TCL_OK;
+	dbip = NULL;
+	if (objc <= 1) {
+		Tcl_WrongNumArgs(interp, 1, objv, "command cmdargs");
+		return (TCL_ERROR);
+	}
+	if (seq == NULL) {
+		Tcl_SetResult(interp, "NULL sequence pointer", TCL_STATIC);
+		return (TCL_ERROR);
+	}
+
+	ip = _PtrToInfo((void *)seq);
+	if (ip == NULL) {
+		Tcl_SetResult(interp, "NULL info pointer", TCL_STATIC);
+		return (TCL_ERROR);
+	}
+
+	/*
+	 * Get the command name index from the object based on the dbcmds
+	 * defined above.
+	 */
+	if (Tcl_GetIndexFromObj(interp,
+	    objv[1], seqcmds, "command", TCL_EXACT, &cmdindex) != TCL_OK)
+		return (IS_HELP(objv[1]));
+
+	res = NULL;
+	switch ((enum seqcmds)cmdindex) {
+	case SEQGETRANGE:
+		ret = seq->get_range(seq, &min, &max);
+		if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+		    "sequence get_range")) == TCL_OK) {
+			myobjv[0] = Tcl_NewWideIntObj(min);
+			myobjv[1] = Tcl_NewWideIntObj(max);
+			res = Tcl_NewListObj(2, myobjv);
+		}
+		break;
+	case SEQCLOSE:
+		result = tcl_SeqClose(interp, objc, objv, seq, ip);
+		break;
+	case SEQREMOVE:
+		result = tcl_SeqRemove(interp, objc, objv, seq, ip);
+		break;
+	case SEQGET:
+		result = tcl_SeqGet(interp, objc, objv, seq);
+		break;
+	case SEQSTAT:
+		result = tcl_SeqStat(interp, objc, objv, seq);
+		break;
+	case SEQGETCACHESIZE:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = seq->get_cachesize(seq, &ncache);
+		if ((result = _ReturnSetup(interp, ret,
+		    DB_RETOK_STD(ret), "sequence get_cachesize")) == TCL_OK)
+			res = Tcl_NewIntObj(ncache);
+		break;
+	case SEQGETDB:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = seq->get_db(seq, &dbp);
+		if (ret == 0 && (dbip = _PtrToInfo((void *)dbp)) == NULL) {
+			Tcl_SetResult(interp,
+			     "NULL db info pointer", TCL_STATIC);
+			return (TCL_ERROR);
+		}
+
+		if ((result = _ReturnSetup(interp, ret,
+		    DB_RETOK_STD(ret), "sequence get_db")) == TCL_OK)
+			res = NewStringObj(dbip->i_name, strlen(dbip->i_name));
+		break;
+	case SEQGETKEY:
+		if (objc != 2) {
+			Tcl_WrongNumArgs(interp, 1, objv, NULL);
+			return (TCL_ERROR);
+		}
+		ret = seq->get_key(seq, &key);
+		if ((result = _ReturnSetup(interp, ret,
+		    DB_RETOK_STD(ret), "sequence get_key")) == TCL_OK)
+			res = Tcl_NewByteArrayObj(
+			    (u_char *)key.data, (int)key.size);
+		break;
+	case SEQGETFLAGS:
+		result = tcl_SeqGetFlags(interp, objc, objv, seq);
+		break;
+	}
+
+	/*
+	 * Only set result if we have a res.  Otherwise, lower functions have
+	 * already done so.
+	 */
+	if (result == TCL_OK && res)
+		Tcl_SetObjResult(interp, res);
+	return (result);
+}
+
+/*
+ * tcl_db_stat --
+ */
+static int
+tcl_SeqStat(interp, objc, objv, seq)
+	Tcl_Interp *interp;		/* Interpreter */
+	int objc;			/* How many arguments? */
+	Tcl_Obj *CONST objv[];		/* The argument objects */
+	DB_SEQUENCE *seq;		/* Database pointer */
+{
+	DB_SEQUENCE_STAT *sp;
+	u_int32_t flag;
+	Tcl_Obj *res, *flaglist, *myobjv[2];
+	int result, ret;
+	char *arg;
+
+	result = TCL_OK;
+	flag = 0;
+
+	if (objc > 3) {
+		Tcl_WrongNumArgs(interp, 2, objv, "?-clear?");
+		return (TCL_ERROR);
+	}
+
+	if (objc == 3) {
+		arg = Tcl_GetStringFromObj(objv[2], NULL);
+		if (strcmp(arg, "-clear") == 0)
+			flag = DB_STAT_CLEAR;
+		else {
+			Tcl_SetResult(interp,
+			    "db stat: unknown arg", TCL_STATIC);
+			return (TCL_ERROR);
+		}
+	}
+
+	_debug_check();
+	ret = seq->stat(seq, &sp, flag);
+	result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "db stat");
+	if (result == TCL_ERROR)
+		return (result);
+
+	res = Tcl_NewObj();
+	MAKE_STAT_LIST("Wait", sp->st_wait);
+	MAKE_STAT_LIST("No wait", sp->st_nowait);
+	MAKE_WSTAT_LIST("Current", sp->st_current);
+	MAKE_WSTAT_LIST("Cached", sp->st_value);
+	MAKE_WSTAT_LIST("Max Cached", sp->st_last_value);
+	MAKE_WSTAT_LIST("Min", sp->st_min);
+	MAKE_WSTAT_LIST("Max", sp->st_max);
+	MAKE_STAT_LIST("Cache size", sp->st_cache_size);
+	/*
+	 * Construct a {name {flag1 flag2 ... flagN}} list for the
+	 * seq flags.
+	 */
+	myobjv[0] = NewStringObj("Flags", strlen("Flags"));
+	myobjv[1] =
+	    _GetFlagsList(interp, sp->st_flags, __db_get_seq_flags_fn());
+	flaglist = Tcl_NewListObj(2, myobjv);
+	if (flaglist == NULL) {
+		result = TCL_ERROR;
+		goto error;
+	}
+	if ((result =
+	    Tcl_ListObjAppendElement(interp, res, flaglist)) != TCL_OK)
+		goto error;
+
+	Tcl_SetObjResult(interp, res);
+
+error:	__os_ufree(seq->seq_dbp->dbenv, sp);
+	return (result);
+}
+
+/*
+ * tcl_db_close --
+ */
+static int
+tcl_SeqClose(interp, objc, objv, seq, ip)
+	Tcl_Interp *interp;		/* Interpreter */
+	int objc;			/* How many arguments? */
+	Tcl_Obj *CONST objv[];		/* The argument objects */
+	DB_SEQUENCE *seq;		/* Database pointer */
+	DBTCL_INFO *ip;			/* Info pointer */
+{
+	int result, ret;
+
+	result = TCL_OK;
+	if (objc > 2) {
+		Tcl_WrongNumArgs(interp, 2, objv, "");
+		return (TCL_ERROR);
+	}
+
+	_DeleteInfo(ip);
+	_debug_check();
+
+	ret = seq->close(seq, 0);
+	result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "sequence close");
+	return (result);
+}
+
+/*
+ * tcl_SeqGet --
+ */
+static int
+tcl_SeqGet(interp, objc, objv, seq)
+	Tcl_Interp *interp;		/* Interpreter */
+	int objc;			/* How many arguments? */
+	Tcl_Obj *CONST objv[];		/* The argument objects */
+	DB_SEQUENCE *seq;		/* Sequence pointer */
+{
+	static const char *seqgetopts[] = {
+		"-auto_commit",
+		"-nosync",
+		"-txn",
+		NULL
+	};
+	enum seqgetopts {
+		SEQGET_AUTO_COMMIT,
+		SEQGET_NOSYNC,
+		SEQGET_TXN
+	};
+	DB_TXN *txn;
+	Tcl_Obj *res;
+	db_seq_t value;
+	u_int32_t aflag, delta;
+	int i, end, optindex, result, ret;
+	char *arg, msg[MSG_SIZE];
+
+	result = TCL_OK;
+	txn = NULL;
+	aflag = 0;
+
+	if (objc < 3) {
+		Tcl_WrongNumArgs(interp, 2, objv, "?-args? delta");
+		return (TCL_ERROR);
+	}
+
+	/*
+	 * Get the command name index from the object based on the options
+	 * defined above.
+	 */
+	i = 2;
+	end = objc;
+	while (i < end) {
+		if (Tcl_GetIndexFromObj(interp, objv[i], seqgetopts, "option",
+		    TCL_EXACT, &optindex) != TCL_OK) {
+			arg = Tcl_GetStringFromObj(objv[i], NULL);
+			if (arg[0] == '-') {
+				result = IS_HELP(objv[i]);
+				goto out;
+			} else
+				Tcl_ResetResult(interp);
+			break;
+		}
+		i++;
+		switch ((enum seqgetopts)optindex) {
+		case SEQGET_AUTO_COMMIT:
+			aflag |= DB_AUTO_COMMIT;
+			break;
+		case SEQGET_NOSYNC:
+			aflag |= DB_TXN_NOSYNC;
+			break;
+		case SEQGET_TXN:
+			if (i >= end) {
+				Tcl_WrongNumArgs(interp, 2, objv, "?-txn id?");
+				result = TCL_ERROR;
+				break;
+			}
+			arg = Tcl_GetStringFromObj(objv[i++], NULL);
+			txn = NAME_TO_TXN(arg);
+			if (txn == NULL) {
+				snprintf(msg, MSG_SIZE,
+				    "Get: Invalid txn: %s\n", arg);
+				Tcl_SetResult(interp, msg, TCL_VOLATILE);
+				result = TCL_ERROR;
+			}
+			break;
+		} /* switch */
+		if (result != TCL_OK)
+			break;
+	}
+	if (result != TCL_OK)
+		goto out;
+
+	if (i != objc - 1) {
+		Tcl_SetResult(interp,
+		    "Wrong number of key/data given\n", TCL_STATIC);
+		result = TCL_ERROR;
+		goto out;
+	}
+
+	if ((result = _GetUInt32(interp, objv[objc - 1], &delta)) != TCL_OK)
+		goto out;
+
+	ret = seq->get(seq, txn, (int32_t)delta, &value, aflag);
+	result = _ReturnSetup(interp, ret, DB_RETOK_DBGET(ret), "sequence get");
+	if (ret == 0) {
+		res = Tcl_NewWideIntObj((Tcl_WideInt)value);
+		Tcl_SetObjResult(interp, res);
+	}
+out:
+	return (result);
+}
+/*
+ */
+static int
+tcl_SeqRemove(interp, objc, objv, seq, ip)
+	Tcl_Interp *interp;		/* Interpreter */
+	int objc;			/* How many arguments? */
+	Tcl_Obj *CONST objv[];		/* The argument objects */
+	DB_SEQUENCE *seq;		/* Sequence pointer */
+	DBTCL_INFO *ip;			/* Info pointer */
+{
+	static const char *seqgetopts[] = {
+		"-auto_commit",
+		"-nosync",
+		"-txn",
+		NULL
+	};
+	enum seqgetopts {
+		SEQGET_AUTO_COMMIT,
+		SEQGET_NOSYNC,
+		SEQGET_TXN
+	};
+	DB_TXN *txn;
+	u_int32_t aflag;
+	int i, end, optindex, result, ret;
+	char *arg, msg[MSG_SIZE];
+
+	result = TCL_OK;
+	txn = NULL;
+	aflag = 0;
+
+	_DeleteInfo(ip);
+
+	if (objc < 2) {
+		Tcl_WrongNumArgs(interp, 2, objv, "?-args?");
+		return (TCL_ERROR);
+	}
+
+	/*
+	 * Get the command name index from the object based on the options
+	 * defined above.
+	 */
+	i = 2;
+	end = objc;
+	while (i < end) {
+		if (Tcl_GetIndexFromObj(interp, objv[i], seqgetopts, "option",
+		    TCL_EXACT, &optindex) != TCL_OK) {
+			arg = Tcl_GetStringFromObj(objv[i], NULL);
+			if (arg[0] == '-') {
+				result = IS_HELP(objv[i]);
+				goto out;
+			} else
+				Tcl_ResetResult(interp);
+			break;
+		}
+		i++;
+		switch ((enum seqgetopts)optindex) {
+		case SEQGET_AUTO_COMMIT:
+			aflag |= DB_AUTO_COMMIT;
+			break;
+		case SEQGET_NOSYNC:
+			aflag |= DB_TXN_NOSYNC;
+			break;
+		case SEQGET_TXN:
+			if (i >= end) {
+				Tcl_WrongNumArgs(interp, 2, objv, "?-txn id?");
+				result = TCL_ERROR;
+				break;
+			}
+			arg = Tcl_GetStringFromObj(objv[i++], NULL);
+			txn = NAME_TO_TXN(arg);
+			if (txn == NULL) {
+				snprintf(msg, MSG_SIZE,
+				    "Remove: Invalid txn: %s\n", arg);
+				Tcl_SetResult(interp, msg, TCL_VOLATILE);
+				result = TCL_ERROR;
+			}
+			break;
+		} /* switch */
+		if (result != TCL_OK)
+			break;
+	}
+	if (result != TCL_OK)
+		goto out;
+
+	ret = seq->remove(seq, txn, aflag);
+	result = _ReturnSetup(interp,
+	    ret, DB_RETOK_DBGET(ret), "sequence remove");
+out:
+	return (result);
+}
+
+/*
+ * tcl_SeqGetFlags --
+ */
+static int
+tcl_SeqGetFlags(interp, objc, objv, seq)
+	Tcl_Interp *interp;		/* Interpreter */
+	int objc;			/* How many arguments? */
+	Tcl_Obj *CONST objv[];		/* The argument objects */
+	DB_SEQUENCE *seq;		/* Sequence pointer */
+{
+	int i, ret, result;
+	u_int32_t flags;
+	char buf[512];
+	Tcl_Obj *res;
+
+	static const struct {
+		u_int32_t flag;
+		char *arg;
+	} seq_flags[] = {
+		{ DB_SEQ_INC, "-inc" },
+		{ DB_SEQ_DEC, "-dec" },
+		{ DB_SEQ_WRAP, "-wrap" },
+		{ 0, NULL }
+	};
+
+	if (objc != 2) {
+		Tcl_WrongNumArgs(interp, 1, objv, NULL);
+		return (TCL_ERROR);
+	}
+
+	ret = seq->get_flags(seq, &flags);
+	if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
+	    "db get_flags")) == TCL_OK) {
+		buf[0] = '\0';
+
+		for (i = 0; seq_flags[i].flag != 0; i++)
+			if (LF_ISSET(seq_flags[i].flag)) {
+				if (strlen(buf) > 0)
+					(void)strncat(buf, " ", sizeof(buf));
+				(void)strncat(
+				    buf, seq_flags[i].arg, sizeof(buf));
+			}
+
+		res = NewStringObj(buf, strlen(buf));
+		Tcl_SetObjResult(interp, res);
+	}
+
+	return (result);
+}
+#endif /* HAVE_SEQUENCE */
diff --git a/storage/bdb/tcl/tcl_txn.c b/storage/bdb/tcl/tcl_txn.c
index b5fab637943a91de9bf4628cd709a380f62d6a91..b819c24b788ffa5ec68dc549d3d7f9f803df2a66 100644
--- a/storage/bdb/tcl/tcl_txn.c
+++ b/storage/bdb/tcl/tcl_txn.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2001
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: tcl_txn.c,v 11.70 2004/10/27 16:48:32 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: tcl_txn.c,v 11.57 2002/08/06 06:21:36 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -48,7 +46,7 @@ _TxnInfoDelete(interp, txnip)
 		 * txn.  Remove its commands and info structure.
 		 */
 		nextp = LIST_NEXT(p, entries);
-		 if (p->i_parent == txnip && p->i_type == I_TXN) {
+		if (p->i_parent == txnip && p->i_type == I_TXN) {
 			_TxnInfoDelete(interp, p);
 			(void)Tcl_DeleteCommand(interp, p->i_name);
 			_DeleteInfo(p);
@@ -69,16 +67,22 @@ tcl_TxnCheckpoint(interp, objc, objv, envp)
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 	DB_ENV *envp;			/* Environment pointer */
 {
-	static char *txnckpopts[] = {
-		"-kbyte",	"-min",
+	static const char *txnckpopts[] = {
+		"-force",
+		"-kbyte",
+		"-min",
 		NULL
 	};
 	enum txnckpopts {
-		TXNCKP_KB,	TXNCKP_MIN
+		TXNCKP_FORCE,
+		TXNCKP_KB,
+		TXNCKP_MIN
 	};
+	u_int32_t flags;
 	int i, kb, min, optindex, result, ret;
 
 	result = TCL_OK;
+	flags = 0;
 	kb = min = 0;
 
 	/*
@@ -93,6 +97,9 @@ tcl_TxnCheckpoint(interp, objc, objv, envp)
 		}
 		i++;
 		switch ((enum txnckpopts)optindex) {
+		case TXNCKP_FORCE:
+			flags = DB_FORCE;
+			break;
 		case TXNCKP_KB:
 			if (i == objc) {
 				Tcl_WrongNumArgs(interp, 2, objv,
@@ -113,7 +120,7 @@ tcl_TxnCheckpoint(interp, objc, objv, envp)
 		}
 	}
 	_debug_check();
-	ret = envp->txn_checkpoint(envp, (u_int32_t)kb, (u_int32_t)min, 0);
+	ret = envp->txn_checkpoint(envp, (u_int32_t)kb, (u_int32_t)min, flags);
 	result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
 	    "txn checkpoint");
 	return (result);
@@ -133,8 +140,9 @@ tcl_Txn(interp, objc, objv, envp, envip)
 	DB_ENV *envp;			/* Environment pointer */
 	DBTCL_INFO *envip;		/* Info pointer */
 {
-	static char *txnopts[] = {
-#if CONFIG_TEST
+	static const char *txnopts[] = {
+#ifdef CONFIG_TEST
+		"-degree_2",
 		"-dirty",
 		"-lock_timeout",
 		"-txn_timeout",
@@ -146,7 +154,8 @@ tcl_Txn(interp, objc, objv, envp, envip)
 		NULL
 	};
 	enum txnopts {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
+		TXNDEGREE2,
 		TXNDIRTY,
 		TXN_LOCK_TIMEOUT,
 		TXN_TIMEOUT,
@@ -160,17 +169,24 @@ tcl_Txn(interp, objc, objv, envp, envip)
 	DB_TXN *parent;
 	DB_TXN *txn;
 	Tcl_Obj *res;
-	db_timeout_t lk_time, tx_time;
-	u_int32_t flag, lk_timeflag, tx_timeflag;
+	u_int32_t flag;
 	int i, optindex, result, ret;
 	char *arg, msg[MSG_SIZE], newname[MSG_SIZE];
+#ifdef CONFIG_TEST
+	db_timeout_t lk_time, tx_time;
+	u_int32_t lk_timeflag, tx_timeflag;
+#endif
 
 	result = TCL_OK;
 	memset(newname, 0, MSG_SIZE);
 
 	parent = NULL;
 	flag = 0;
+#ifdef CONFIG_TEST
+	COMPQUIET(tx_time, 0);
+	COMPQUIET(lk_time, 0);
 	lk_timeflag = tx_timeflag = 0;
+#endif
 	i = 2;
 	while (i < objc) {
 		if (Tcl_GetIndexFromObj(interp, objv[i],
@@ -180,6 +196,9 @@ tcl_Txn(interp, objc, objv, envp, envip)
 		i++;
 		switch ((enum txnopts)optindex) {
 #ifdef CONFIG_TEST
+		case TXNDEGREE2:
+			flag |= DB_DEGREE_2;
+			break;
 		case TXNDIRTY:
 			flag |= DB_DIRTY_READ;
 			break;
@@ -188,14 +207,13 @@ tcl_Txn(interp, objc, objv, envp, envip)
 			goto getit;
 		case TXN_TIMEOUT:
 			tx_timeflag = DB_SET_TXN_TIMEOUT;
-getit:
-			if (i >= objc) {
+getit:			if (i >= objc) {
 				Tcl_WrongNumArgs(interp, 2, objv,
 				    "?-txn_timestamp time?");
 				return (TCL_ERROR);
 			}
-			result = Tcl_GetLongFromObj(interp, objv[i++],
-			    (long *)(optindex == TXN_LOCK_TIMEOUT ?
+			result = Tcl_GetLongFromObj(interp, objv[i++], (long *)
+			    ((enum txnopts)optindex == TXN_LOCK_TIMEOUT ?
 			    &lk_time : &tx_time));
 			if (result != TCL_OK)
 				return (TCL_ERROR);
@@ -257,10 +275,11 @@ getit:
 		else
 			ip->i_parent = envip;
 		_SetInfoData(ip, txn);
-		Tcl_CreateObjCommand(interp, newname,
+		(void)Tcl_CreateObjCommand(interp, newname,
 		    (Tcl_ObjCmdProc *)txn_Cmd, (ClientData)txn, NULL);
-		res = Tcl_NewStringObj(newname, strlen(newname));
+		res = NewStringObj(newname, strlen(newname));
 		Tcl_SetObjResult(interp, res);
+#ifdef CONFIG_TEST
 		if (tx_timeflag != 0) {
 			ret = txn->set_timeout(txn, tx_time, tx_timeflag);
 			if (ret != 0) {
@@ -279,6 +298,7 @@ getit:
 				_DeleteInfo(ip);
 			}
 		}
+#endif
 	}
 	return (result);
 }
@@ -357,7 +377,7 @@ tcl_TxnStat(interp, objc, objv, envp)
 		}
 	Tcl_SetObjResult(interp, res);
 error:
-	free(sp);
+	__os_ufree(envp, sp);
 	return (result);
 }
 
@@ -405,8 +425,8 @@ txn_Cmd(clientData, interp, objc, objv)
 	int objc;			/* How many arguments? */
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 {
-	static char *txncmds[] = {
-#if CONFIG_TEST
+	static const char *txncmds[] = {
+#ifdef CONFIG_TEST
 		"discard",
 		"id",
 		"prepare",
@@ -416,7 +436,7 @@ txn_Cmd(clientData, interp, objc, objv)
 		NULL
 	};
 	enum txncmds {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 		TXNDISCARD,
 		TXNID,
 		TXNPREPARE,
@@ -428,7 +448,9 @@ txn_Cmd(clientData, interp, objc, objv)
 	DB_TXN *txnp;
 	Tcl_Obj *res;
 	int cmdindex, result, ret;
+#ifdef CONFIG_TEST
 	u_int8_t *gid;
+#endif
 
 	Tcl_ResetResult(interp);
 	txnp = (DB_TXN *)clientData;
@@ -453,7 +475,7 @@ txn_Cmd(clientData, interp, objc, objv)
 
 	res = NULL;
 	switch ((enum txncmds)cmdindex) {
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 	case TXNDISCARD:
 		if (objc != 2) {
 			Tcl_WrongNumArgs(interp, 1, objv, NULL);
@@ -473,8 +495,7 @@ txn_Cmd(clientData, interp, objc, objv)
 			return (TCL_ERROR);
 		}
 		_debug_check();
-		ret = txnp->id(txnp);
-		res = Tcl_NewIntObj(ret);
+		res = Tcl_NewIntObj((int)txnp->id(txnp));
 		break;
 	case TXNPREPARE:
 		if (objc != 3) {
@@ -533,7 +554,7 @@ tcl_TxnCommit(interp, objc, objv, txnp, txnip)
 	DB_TXN *txnp;			/* Transaction pointer */
 	DBTCL_INFO *txnip;		/* Info pointer */
 {
-	static char *commitopt[] = {
+	static const char *commitopt[] = {
 		"-nosync",
 		"-sync",
 		NULL
@@ -576,7 +597,7 @@ tcl_TxnCommit(interp, objc, objv, txnp, txnip)
 	return (result);
 }
 
-#if CONFIG_TEST
+#ifdef CONFIG_TEST
 /*
  * tcl_TxnRecover --
  *
@@ -605,7 +626,7 @@ for (i = 0; i < count; i++) {						\
 	ip->i_parent = envip;						\
 	p = &prep[i];							\
 	_SetInfoData(ip, p->txn);					\
-	Tcl_CreateObjCommand(interp, newname,				\
+	(void)Tcl_CreateObjCommand(interp, newname,			\
 	    (Tcl_ObjCmdProc *)txn_Cmd, (ClientData)p->txn, NULL);	\
 	result = _SetListElem(interp, res, newname, strlen(newname),	\
 	    p->gid, DB_XIDDATASIZE);					\
diff --git a/storage/bdb/tcl/tcl_util.c b/storage/bdb/tcl/tcl_util.c
index 3c0665f9e38f4316b3a2d4dffdee0267c510369c..13a6d6a9dd77185dc125717923a442718f454b0b 100644
--- a/storage/bdb/tcl/tcl_util.c
+++ b/storage/bdb/tcl/tcl_util.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1999-2001
+ * Copyright (c) 1999-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: tcl_util.c,v 11.43 2004/06/10 17:20:57 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: tcl_util.c,v 11.35 2002/08/06 06:21:42 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -40,17 +38,15 @@ bdb_RandCommand(interp, objc, objv)
 	int objc;			/* How many arguments? */
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 {
-	static char *rcmds[] = {
+	static const char *rcmds[] = {
 		"rand",	"random_int",	"srand",
 		NULL
 	};
 	enum rcmds {
 		RRAND, RRAND_INT, RSRAND
 	};
-	long t;
-	int cmdindex, hi, lo, result, ret;
 	Tcl_Obj *res;
-	char msg[MSG_SIZE];
+	int cmdindex, hi, lo, result, ret;
 
 	result = TCL_OK;
 	/*
@@ -83,29 +79,21 @@ bdb_RandCommand(interp, objc, objv)
 			Tcl_WrongNumArgs(interp, 2, objv, "lo hi");
 			return (TCL_ERROR);
 		}
-		result = Tcl_GetIntFromObj(interp, objv[2], &lo);
-		if (result != TCL_OK)
-			break;
-		result = Tcl_GetIntFromObj(interp, objv[3], &hi);
-		if (result == TCL_OK) {
-#ifndef RAND_MAX
-#define	RAND_MAX	0x7fffffff
-#endif
-			t = rand();
-			if (t > RAND_MAX) {
-				snprintf(msg, MSG_SIZE,
-				    "Max random is higher than %ld\n",
-				    (long)RAND_MAX);
-				Tcl_SetResult(interp, msg, TCL_VOLATILE);
-				result = TCL_ERROR;
-				break;
-			}
-			_debug_check();
-			ret = (int)(((double)t / ((double)(RAND_MAX) + 1)) *
-			    (hi - lo + 1));
-			ret += lo;
-			res = Tcl_NewIntObj(ret);
+		if ((result =
+		    Tcl_GetIntFromObj(interp, objv[2], &lo)) != TCL_OK)
+			return (result);
+		if ((result =
+		    Tcl_GetIntFromObj(interp, objv[3], &hi)) != TCL_OK)
+			return (result);
+		if (lo < 0 || hi < 0) {
+			Tcl_SetResult(interp,
+			    "Range value less than 0", TCL_STATIC);
+			return (TCL_ERROR);
 		}
+
+		_debug_check();
+		ret = lo + rand() % ((hi - lo) + 1);
+		res = Tcl_NewIntObj(ret);
 		break;
 	case RSRAND:
 		/*
@@ -115,16 +103,17 @@ bdb_RandCommand(interp, objc, objv)
 			Tcl_WrongNumArgs(interp, 2, objv, "seed");
 			return (TCL_ERROR);
 		}
-		result = Tcl_GetIntFromObj(interp, objv[2], &lo);
-		if (result == TCL_OK) {
+		if ((result =
+		    Tcl_GetIntFromObj(interp, objv[2], &lo)) == TCL_OK) {
 			srand((u_int)lo);
 			res = Tcl_NewIntObj(0);
 		}
 		break;
 	}
+
 	/*
-	 * Only set result if we have a res.  Otherwise, lower
-	 * functions have already done so.
+	 * Only set result if we have a res.  Otherwise, lower functions have
+	 * already done so.
 	 */
 	if (result == TCL_OK && res)
 		Tcl_SetObjResult(interp, res);
@@ -150,13 +139,12 @@ tcl_Mutex(interp, objc, objv, envp, envip)
 	DBTCL_INFO *ip;
 	Tcl_Obj *res;
 	_MUTEX_DATA *md;
-	int i, mode, nitems, result, ret;
+	int i, nitems, mode, result, ret;
 	char newname[MSG_SIZE];
 
 	md = NULL;
 	result = TCL_OK;
-	mode = nitems = ret = 0;
-	memset(newname, 0, MSG_SIZE);
+	ret = 0;
 
 	if (objc != 4) {
 		Tcl_WrongNumArgs(interp, 2, objv, "mode nitems");
@@ -169,6 +157,7 @@ tcl_Mutex(interp, objc, objv, envp, envip)
 	if (result != TCL_OK)
 		return (TCL_ERROR);
 
+	memset(newname, 0, MSG_SIZE);
 	snprintf(newname, sizeof(newname),
 	    "%s.mutex%d", envip->i_name, envip->i_envmutexid);
 	ip = _NewInfo(interp, NULL, newname, I_MUTEX);
@@ -192,12 +181,11 @@ tcl_Mutex(interp, objc, objv, envp, envip)
 	if (__os_calloc(NULL, 1, sizeof(_MUTEX_DATA), &md) != 0)
 		goto posixout;
 	md->env = envp;
-	md->n_mutex = nitems;
-	md->size = sizeof(_MUTEX_ENTRY) * nitems;
+	md->size = sizeof(_MUTEX_ENTRY) * (u_int)nitems;
 
+	md->reginfo.dbenv = envp;
 	md->reginfo.type = REGION_TYPE_MUTEX;
-	md->reginfo.id = INVALID_REGION_TYPE;
-	md->reginfo.mode = mode;
+	md->reginfo.id = INVALID_REGION_ID;
 	md->reginfo.flags = REGION_CREATE_OK | REGION_JOIN_OK;
 	if ((ret = __db_r_attach(envp, &md->reginfo, md->size)) != 0)
 		goto posixout;
@@ -220,23 +208,22 @@ tcl_Mutex(interp, objc, objv, envp, envip)
 	envip->i_envmutexid++;
 	ip->i_parent = envip;
 	_SetInfoData(ip, md);
-	Tcl_CreateObjCommand(interp, newname,
+	(void)Tcl_CreateObjCommand(interp, newname,
 	    (Tcl_ObjCmdProc *)mutex_Cmd, (ClientData)md, NULL);
-	res = Tcl_NewStringObj(newname, strlen(newname));
+	res = NewStringObj(newname, strlen(newname));
 	Tcl_SetObjResult(interp, res);
 
 	return (TCL_OK);
 
 posixout:
 	if (ret > 0)
-		Tcl_PosixError(interp);
+		(void)Tcl_PosixError(interp);
 	result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "mutex");
 	_DeleteInfo(ip);
 
 	if (md != NULL) {
 		if (md->reginfo.addr != NULL)
-			(void)__db_r_detach(md->env,
-			    &md->reginfo, F_ISSET(&md->reginfo, REGION_CREATE));
+			(void)__db_r_detach(md->env, &md->reginfo, 0);
 		__os_free(md->env, md);
 	}
 	return (result);
@@ -253,7 +240,7 @@ mutex_Cmd(clientData, interp, objc, objv)
 	int objc;			/* How many arguments? */
 	Tcl_Obj *CONST objv[];		/* The argument objects */
 {
-	static char *mxcmds[] = {
+	static const char *mxcmds[] = {
 		"close",
 		"get",
 		"getval",
diff --git a/storage/bdb/test/archive.tcl b/storage/bdb/test/archive.tcl
index 9b5e764b2b4fc4fdd0beca9954120ca944e00bea..fa68f633b0f352419a890fd3e2169b6ff4228c14 100644
--- a/storage/bdb/test/archive.tcl
+++ b/storage/bdb/test/archive.tcl
@@ -1,20 +1,26 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: archive.tcl,v 11.20 2002/04/30 19:21:21 sue Exp $
+# $Id: archive.tcl,v 11.26 2004/09/22 18:01:04 bostic Exp $
 #
 # Options are:
 # -checkrec <checkpoint frequency"
 # -dir <dbhome directory>
 # -maxfilesize <maxsize of log file>
-proc archive { args } {
+proc archive { { inmem 0 } args } {
 	global alphabet
 	source ./include.tcl
 
 	# Set defaults
-	set maxbsize [expr 8 * 1024]
+	if { $inmem == 1 } {
+		set maxbsize [expr 8 * [expr 1024 * 1024]]
+		set desc "in-memory"
+	} else {
+		set maxbsize [expr 8 * 1024]
+		set desc "on-disk"
+	}
 	set maxfile [expr 32 * 1024]
 	set checkrec 500
 	for { set i 0 } { $i < [llength $args] } {incr i} {
@@ -28,71 +34,92 @@ proc archive { args } {
 	    -dir <directory> -maxfilesize <max size of log files>"
 				return
 			}
-
 		}
 	}
 
 	# Clean out old log if it existed
-	puts "Archive: Log archive test"
+	puts "Archive: Log archive test (using $desc logging)."
 	puts "Unlinking log: error message OK"
 	env_cleanup $testdir
 
 	# Now run the various functionality tests
-	set eflags "-create -txn -home $testdir \
-	    -log_buffer $maxbsize -log_max $maxfile"
+	if { $inmem == 0 } {
+		set eflags "-create -txn -home $testdir \
+		    -log_buffer $maxbsize -log_max $maxfile"
+	} else {
+		set eflags "-create -txn -home $testdir -log_inmemory \
+		    -log_buffer $maxbsize -log_max $maxfile"
+	}
 	set dbenv [eval {berkdb_env} $eflags]
-	error_check_bad dbenv $dbenv NULL
-	error_check_good dbenv [is_substr $dbenv env] 1
+	error_check_good dbenv [is_valid_env $dbenv] TRUE
 
 	set logc [$dbenv log_cursor]
 	error_check_good log_cursor [is_valid_logc $logc $dbenv] TRUE
 
 	# The basic test structure here is that we write a lot of log
 	# records (enough to fill up 100 log files; each log file it
-	# small).  We take periodic checkpoints.  Between each pair
-	# of checkpoints, we refer to 2 files, overlapping them each
-	# checkpoint.  We also start transactions and let them overlap
-	# checkpoints as well.  The pattern that we try to create is:
-	# ---- write log records----|||||--- write log records ---
-	# -T1 T2 T3 --- D1 D2 ------CHECK--- CT1 --- D2 D3 CD1 ----CHECK
-	# where TX is begin transaction, CTx is commit transaction, DX is
-	# open data file and CDx is close datafile.
+	# small).  We start with three txns and open a database in
+	# each transaction.  Then, in a loop, we take periodic
+	# checkpoints.  Between each pair of checkpoints, we end one
+	# transaction; when no transactions are left, we start up three
+	# new ones, letting them overlap checkpoints as well.
+	#
+	# The pattern that we create is:
+	# 1.  Create TXN1, TXN2, TXN3 and open dbs within the txns.
+	# 2.  Write a bunch of additional log records.
+	# 3.  Checkpoint.
+	# 4.  Archive, checking that we list the right files.
+	# 5.  Commit one transaction.
+	# 6.  If no txns left, start 3 new ones.
+	# 7.  Until we've gone through enough records, return to step 2.
 
 	set baserec "1:$alphabet:2:$alphabet:3:$alphabet:4:$alphabet"
 	puts "\tArchive.a: Writing log records; checkpoint every $checkrec records"
 	set nrecs $maxfile
 	set rec 0:$baserec
 
-	# Begin transaction and write a log record
+	# Begin 1st transaction and record current log file.  Open
+	# a database in the transaction; the log file won't be
+	# removable until the transaction is aborted or committed.
 	set t1 [$dbenv txn]
-	error_check_good t1:txn_begin [is_substr $t1 "txn"] 1
+	error_check_good t1:txn_begin [is_valid_txn $t1 $dbenv] TRUE
 
-	set l1 [$dbenv log_put $rec]
-	error_check_bad l1:log_put [llength $l1] 0
+	set l1 [lindex [lindex [$logc get -last] 0] 0]
+	set lsnlist [list $l1]
 
-	set lsnlist [list [lindex $l1 0]]
+	set tdb1 [eval {berkdb_open -create -mode 0644} \
+	    -env $dbenv -txn $t1 -btree tdb1.db]
+	error_check_good dbopen [is_valid_db $tdb1] TRUE
 
+	# Do the same for a 2nd and 3rd transaction.
 	set t2 [$dbenv txn]
-	error_check_good t2:txn_begin [is_substr $t2 "txn"] 1
-
-	set l1 [$dbenv log_put $rec]
-	lappend lsnlist [lindex $l1 0]
+	error_check_good t2:txn_begin [is_valid_txn $t2 $dbenv] TRUE
+	set l2 [lindex [lindex [$logc get -last] 0] 0]
+	lappend lsnlist $l2
+	set tdb2 [eval {berkdb_open -create -mode 0644} \
+	    -env $dbenv -txn $t2 -btree tdb2.db]
+	error_check_good dbopen [is_valid_db $tdb2] TRUE
 
 	set t3 [$dbenv txn]
-	set l1 [$dbenv log_put $rec]
-	lappend lsnlist [lindex $l1 0]
-
-	set txnlist [list $t1 $t2 $t3]
-	set db1 [eval {berkdb_open} "-create -mode 0644 -hash -env $dbenv ar1"]
-	set db2 [eval {berkdb_open} "-create -mode 0644 -btree -env $dbenv ar2"]
-	set dbcount 3
-	set dblist [list $db1 $db2]
-
+	error_check_good t3:txn_begin [is_valid_txn $t3 $dbenv] TRUE
+	set l3 [lindex [lindex [$logc get -last] 0] 0]
+	lappend lsnlist $l3
+	set tdb3 [eval {berkdb_open -create -mode 0644} \
+	    -env $dbenv -txn $t3 -btree tdb3.db]
+	error_check_good dbopen [is_valid_db $tdb3] TRUE
+
+	# Keep a list of active transactions and databases opened
+	# within those transactions.
+	set txnlist [list "$t1 $tdb1" "$t2 $tdb2" "$t3 $tdb3"]
+
+	# Loop through a large number of log records, checkpointing
+	# and checking db_archive periodically.
 	for { set i 1 } { $i <= $nrecs } { incr i } {
 		set rec $i:$baserec
 		set lsn [$dbenv log_put $rec]
 		error_check_bad log_put [llength $lsn] 0
 		if { [expr $i % $checkrec] == 0 } {
+
 			# Take a checkpoint
 			$dbenv txn_checkpoint
 			set ckp_file [lindex [lindex [$logc get -last] 0] 0]
@@ -108,16 +135,24 @@ proc archive { args } {
 			catch { archive_command -h $testdir -a -s } \
 			    res_data_full
 			catch { archive_command -h $testdir -s } res_data
-			error_check_good nlogfiles [llength $res_alllog] \
-			    [lindex [lindex [$logc get -last] 0] 0]
+
+			if { $inmem == 0 } {
+				error_check_good nlogfiles [llength $res_alllog] \
+				    [lindex [lindex [$logc get -last] 0] 0]
+			} else {
+				error_check_good nlogfiles [llength $res_alllog] 0
+			}
+
 			error_check_good logs_match [llength $res_log_full] \
 			    [llength $res_log]
 			error_check_good data_match [llength $res_data_full] \
 			    [llength $res_data]
 
 			# Check right number of log files
-			error_check_good nlogs [llength $res_log] \
-			    [expr [lindex $lsnlist 0] - 1]
+			if { $inmem == 0 } {
+				set expected [min $ckp_file [expr [lindex $lsnlist 0] - 1]]
+				error_check_good nlogs [llength $res_log] $expected
+			}
 
 			# Check that the relative names are a subset of the
 			# full names
@@ -137,68 +172,59 @@ proc archive { args } {
 				incr n
 			}
 
-			# Begin/commit any transactions
-			set t [lindex $txnlist 0]
+			# Commit a transaction and close the associated db.
+			set t [lindex [lindex $txnlist 0] 0]
+			set tdb [lindex [lindex $txnlist 0] 1]
 			if { [string length $t] != 0 } {
 				error_check_good txn_commit:$t [$t commit] 0
+				error_check_good tdb_close:$tdb [$tdb close] 0
 				set txnlist [lrange $txnlist 1 end]
+				set lsnlist [lrange $lsnlist 1 end]
 			}
-			set lsnlist [lrange $lsnlist 1 end]
 
+			# If we're down to no transactions, start some new ones.
 			if { [llength $txnlist] == 0 } {
 				set t1 [$dbenv txn]
 				error_check_bad tx_begin $t1 NULL
 				error_check_good \
 				    tx_begin [is_substr $t1 $dbenv] 1
-				set l1 [lindex [$dbenv log_put $rec] 0]
-				lappend lsnlist [min $l1 $ckp_file]
+				set tdb1 [eval {berkdb_open -create -mode 0644} \
+				    -env $dbenv -txn $t1 -btree tdb1.db]
+				error_check_good dbopen [is_valid_db $tdb1] TRUE
+				set l1 [lindex [lindex [$logc get -last] 0] 0]
+				lappend lsnlist $l1
 
 				set t2 [$dbenv txn]
 				error_check_bad tx_begin $t2 NULL
 				error_check_good \
 				    tx_begin [is_substr $t2 $dbenv] 1
-				set l1 [lindex [$dbenv log_put $rec] 0]
-				lappend lsnlist [min $l1 $ckp_file]
+				set tdb2 [eval {berkdb_open -create -mode 0644} \
+				    -env $dbenv -txn $t2 -btree tdb2.db]
+				error_check_good dbopen [is_valid_db $tdb2] TRUE
+				set l2 [lindex [lindex [$logc get -last] 0] 0]
+				lappend lsnlist $l2
 
 				set t3 [$dbenv txn]
 				error_check_bad tx_begin $t3 NULL
 				error_check_good \
 				    tx_begin [is_substr $t3 $dbenv] 1
-				set l1 [lindex [$dbenv log_put $rec] 0]
-				lappend lsnlist [min $l1 $ckp_file]
-
-				set txnlist [list $t1 $t2 $t3]
-			}
+				set tdb3 [eval {berkdb_open -create -mode 0644} \
+				    -env $dbenv -txn $t3 -btree tdb3.db]
+				error_check_good dbopen [is_valid_db $tdb3] TRUE
+				set l3 [lindex [lindex [$logc get -last] 0] 0]
+				lappend lsnlist $l3
 
-			# Open/close some DB files
-			if { [expr $dbcount % 2] == 0 } {
-				set type "-hash"
-			} else {
-				set type "-btree"
+				set txnlist [list "$t1 $tdb1" "$t2 $tdb2" "$t3 $tdb3"]
 			}
-			set db [eval {berkdb_open} \
-			    "-create -mode 0644 $type -env $dbenv ar$dbcount"]
-			error_check_bad db_open:$dbcount $db NULL
-			error_check_good db_open:$dbcount [is_substr $db db] 1
-			incr dbcount
-
-			lappend dblist $db
-			set db [lindex $dblist 0]
-			error_check_good db_close:$db [$db close] 0
-			set dblist [lrange $dblist 1 end]
-
 		}
 	}
 	# Commit any transactions still running.
 	puts "\tArchive.b: Commit any transactions still running."
-	foreach t $txnlist {
+	foreach pair $txnlist {
+		set t [lindex $pair 0]
+		set tdb [lindex $pair 1]
 		error_check_good txn_commit:$t [$t commit] 0
-	}
-
-	# Close any files that are still open.
-	puts "\tArchive.c: Close open files."
-	foreach d $dblist {
-		error_check_good db_close:$db [$d close] 0
+		error_check_good tdb_close:$tdb [$tdb close] 0
 	}
 
 	# Close and unlink the file
diff --git a/storage/bdb/test/bigfile001.tcl b/storage/bdb/test/bigfile001.tcl
index 78dcd940f5e8346e5b95f712462ed8e9e34b9667..39981413829c909cbf522b3347a50dcb448649d9 100644
--- a/storage/bdb/test/bigfile001.tcl
+++ b/storage/bdb/test/bigfile001.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2001-2002
+# Copyright (c) 2001-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: bigfile001.tcl,v 11.7 2002/08/10 13:39:26 bostic Exp $
+# $Id: bigfile001.tcl,v 11.9 2004/01/28 03:36:26 bostic Exp $
 #
 # TEST	bigfile001
 # TEST	Create a database greater than 4 GB in size.  Close, verify.
diff --git a/storage/bdb/test/bigfile002.tcl b/storage/bdb/test/bigfile002.tcl
index f3e6defeaba7f26d8a41f5b880debd0c55e5de0e..6686f9ac62739dc276c0479c9e31e44f0fdaa48f 100644
--- a/storage/bdb/test/bigfile002.tcl
+++ b/storage/bdb/test/bigfile002.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2001-2002
+# Copyright (c) 2001-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: bigfile002.tcl,v 11.7 2002/08/10 13:39:26 bostic Exp $
+# $Id: bigfile002.tcl,v 11.9 2004/01/28 03:36:26 bostic Exp $
 #
 # TEST	bigfile002
 # TEST	This one should be faster and not require so much disk space,
diff --git a/storage/bdb/test/byteorder.tcl b/storage/bdb/test/byteorder.tcl
index 823ca46270d9fbb8de3a126b0c2ac61d96039c07..d94f5a0146a81f9c05418944afccfd570612bfde 100644
--- a/storage/bdb/test/byteorder.tcl
+++ b/storage/bdb/test/byteorder.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: byteorder.tcl,v 11.12 2002/07/29 18:09:25 sue Exp $
+# $Id: byteorder.tcl,v 11.16 2004/01/28 03:36:26 bostic Exp $
 #
 # Byte Order Test
 # Use existing tests and run with both byte orders.
@@ -11,21 +11,21 @@ proc byteorder { method {nentries 1000} } {
 	source ./include.tcl
 	puts "Byteorder: $method $nentries"
 
-	eval {test001 $method $nentries 0 "01" 0 -lorder 1234}
+	eval {test001 $method $nentries 0 0 "001" -lorder 1234}
 	eval {verify_dir $testdir}
-	eval {test001 $method $nentries 0 "01" 0 -lorder 4321}
+	eval {test001 $method $nentries 0 0 "001" -lorder 4321}
 	eval {verify_dir $testdir}
 	eval {test003 $method -lorder 1234}
 	eval {verify_dir $testdir}
 	eval {test003 $method -lorder 4321}
 	eval {verify_dir $testdir}
-	eval {test010 $method $nentries 5 10 -lorder 1234}
+	eval {test010 $method $nentries 5 "010" -lorder 1234}
 	eval {verify_dir $testdir}
-	eval {test010 $method $nentries 5 10 -lorder 4321}
+	eval {test010 $method $nentries 5 "010" -lorder 4321}
 	eval {verify_dir $testdir}
-	eval {test011 $method $nentries 5 11 -lorder 1234}
+	eval {test011 $method $nentries 5 "011" -lorder 1234}
 	eval {verify_dir $testdir}
-	eval {test011 $method $nentries 5 11 -lorder 4321}
+	eval {test011 $method $nentries 5 "011" -lorder 4321}
 	eval {verify_dir $testdir}
 	eval {test018 $method $nentries -lorder 1234}
 	eval {verify_dir $testdir}
diff --git a/storage/bdb/test/conscript.tcl b/storage/bdb/test/conscript.tcl
index fd12c6e51a0cab8da2cb5f8e613e8d1f4ad6a49e..8740ae21425a20a9c4dca27f0e930cc9724c0657 100644
--- a/storage/bdb/test/conscript.tcl
+++ b/storage/bdb/test/conscript.tcl
@@ -1,15 +1,15 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: conscript.tcl,v 11.17 2002/03/22 21:43:06 krinsky Exp $
+# $Id: conscript.tcl,v 11.25 2004/01/28 03:36:26 bostic Exp $
 #
 # Script for DB_CONSUME test (test070.tcl).
 # Usage: conscript dir file runtype nitems outputfile tnum args
 # dir: DBHOME directory
 # file: db file on which to operate
-# runtype: PRODUCE or CONSUME--which am I?
+# runtype: PRODUCE, CONSUME or WAIT -- which am I?
 # nitems: number of items to put or get
 # outputfile: where to log consumer results
 # tnum: test number
@@ -19,7 +19,7 @@ proc consumescript_produce { db_cmd nitems tnum args } {
 	global mydata
 
 	set pid [pid]
-	puts "\tTest0$tnum: Producer $pid starting, producing $nitems items."
+	puts "\tTest$tnum: Producer $pid starting, producing $nitems items."
 
 	set db [eval $db_cmd]
 	error_check_good db_open:$pid [is_valid_db $db] TRUE
@@ -33,26 +33,26 @@ proc consumescript_produce { db_cmd nitems tnum args } {
 		}
 		set ret [$db put -append [chop_data q $mydata]]
 		error_check_good db_put \
-		    [expr $ret > 0 ? $oret < $ret : \
-		    $oret < 0 ? $oret < $ret : $oret > $ret] 1
+		    [expr $oret > $ret ? \
+		    ($oret > 0x7fffffff && $ret < 0x7fffffff) : 1] 1
 
 	}
 
 	set ret [catch {$db close} res]
 	error_check_good db_close:$pid $ret 0
-	puts "\t\tTest0$tnum: Producer $pid finished."
+	puts "\t\tTest$tnum: Producer $pid finished."
 }
 
 proc consumescript_consume { db_cmd nitems tnum outputfile mode args } {
 	source ./include.tcl
 	global mydata
 	set pid [pid]
-	puts "\tTest0$tnum: Consumer $pid starting, seeking $nitems items."
+	puts "\tTest$tnum: Consumer $pid starting, seeking $nitems items."
 
 	set db [eval $db_cmd]
 	error_check_good db_open:$pid [is_valid_db $db] TRUE
 
-	set oid [open $outputfile w]
+	set oid [open $outputfile a]
 
 	for { set ndx 0 } { $ndx < $nitems } { } {
 		set ret [$db get $mode]
@@ -71,7 +71,7 @@ proc consumescript_consume { db_cmd nitems tnum outputfile mode args } {
 
 	set ret [catch {$db close} res]
 	error_check_good db_close:$pid $ret 0
-	puts "\t\tTest0$tnum: Consumer $pid finished."
+	puts "\t\tTest$tnum: Consumer $pid finished."
 }
 
 source ./include.tcl
@@ -117,7 +117,8 @@ if { $runtype == "PRODUCE" } {
 	consumescript_consume $db_cmd $nitems $tnum $outputfile -consume_wait \
 		$args
 } else {
-	error_check_good bad_args $runtype "either PRODUCE, CONSUME or WAIT"
+	error_check_good bad_args $runtype \
+	    "either PRODUCE, CONSUME, or WAIT"
 }
 error_check_good env_close [$dbenv close] 0
 exit
diff --git a/storage/bdb/test/dbm.tcl b/storage/bdb/test/dbm.tcl
index a392c7a9f3adceb118cfc2a0b189239f2fb7bebf..49a0f3e13d10f0b04db9efd6968ff12dac27579f 100644
--- a/storage/bdb/test/dbm.tcl
+++ b/storage/bdb/test/dbm.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: dbm.tcl,v 11.15 2002/01/11 15:53:19 bostic Exp $
+# $Id: dbm.tcl,v 11.17 2004/01/28 03:36:26 bostic Exp $
 #
 # TEST	dbm
 # TEST	Historic DBM interface test.  Use the first 1000 entries from the
diff --git a/storage/bdb/test/dbscript.tcl b/storage/bdb/test/dbscript.tcl
index 5decc493e9e29ad1ec6a55a70d507b32cfcc4976..8ddcec09d3517625d4525b17200be61b23c7587e 100644
--- a/storage/bdb/test/dbscript.tcl
+++ b/storage/bdb/test/dbscript.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: dbscript.tcl,v 11.14 2002/04/01 16:28:16 bostic Exp $
+# $Id: dbscript.tcl,v 11.16 2004/01/28 03:36:26 bostic Exp $
 #
 # Random db tester.
 # Usage: dbscript file numops min_del max_add key_avg data_avgdups
diff --git a/storage/bdb/test/ddoyscript.tcl b/storage/bdb/test/ddoyscript.tcl
index 5478a1a98e0d6b1595cdcc0c47ed60506caf1779..30e6c34e0bcddd809bb60e9c9fac48e06109baab 100644
--- a/storage/bdb/test/ddoyscript.tcl
+++ b/storage/bdb/test/ddoyscript.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: ddoyscript.tcl,v 11.6 2002/02/20 16:35:18 sandstro Exp $
+# $Id: ddoyscript.tcl,v 11.8 2004/01/28 03:36:26 bostic Exp $
 #
 # Deadlock detector script tester.
 # Usage: ddoyscript dir lockerid numprocs
diff --git a/storage/bdb/test/ddscript.tcl b/storage/bdb/test/ddscript.tcl
index 621906233a978948ce097cc08ba5b940b8667bf1..173cb2a69b428ac0e80031e06c5bcbb9beaf8c62 100644
--- a/storage/bdb/test/ddscript.tcl
+++ b/storage/bdb/test/ddscript.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: ddscript.tcl,v 11.12 2002/02/20 16:35:18 sandstro Exp $
+# $Id: ddscript.tcl,v 11.15 2004/03/18 20:58:14 carol Exp $
 #
 # Deadlock detector script tester.
 # Usage: ddscript dir test lockerid objid numprocs
@@ -27,7 +27,7 @@ if { $argc != 5 } {
 
 # Initialize arguments
 set dir [lindex $argv 0]
-set tnum [ lindex $argv 1 ]
+set test [ lindex $argv 1 ]
 set lockerid [ lindex $argv 2 ]
 set objid [ lindex $argv 3 ]
 set numprocs [ lindex $argv 4 ]
@@ -36,7 +36,7 @@ set myenv [berkdb_env -lock -home $dir -create -mode 0644 ]
 error_check_bad lock_open $myenv NULL
 error_check_good lock_open [is_substr $myenv "env"] 1
 
-puts [eval $tnum $myenv $lockerid $objid $numprocs]
+puts [eval $test $myenv $lockerid $objid $numprocs]
 
 error_check_good lock_id_free [$myenv lock_id_free $lockerid] 0
 error_check_good envclose [$myenv close] 0
diff --git a/storage/bdb/test/dead001.tcl b/storage/bdb/test/dead001.tcl
index e9853a87e533b0a38e1d6aa8d5e66bdb4e202123..fca094bf17c610fe262a794bcd530850cd2de8bf 100644
--- a/storage/bdb/test/dead001.tcl
+++ b/storage/bdb/test/dead001.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: dead001.tcl,v 11.33 2002/09/05 17:23:05 sandstro Exp $
+# $Id: dead001.tcl,v 11.37 2004/01/28 03:36:26 bostic Exp $
 #
 # TEST	dead001
 # TEST	Use two different configurations to test deadlock detection among a
@@ -23,7 +23,7 @@ proc dead001 { { procs "2 4 10" } {tests "ring clump" } \
 	# Create the environment.
 	puts "\tDead$tnum.a: creating environment"
 	set env [berkdb_env -create \
-	     -mode 0644 -lock -txn_timeout $timeout -home $testdir]
+	     -mode 0644 -lock -lock_timeout $timeout -home $testdir]
 	error_check_good lock_env:open [is_valid_env $env] TRUE
 
 	foreach t $tests {
@@ -72,7 +72,7 @@ proc dead001 { { procs "2 4 10" } {tests "ring clump" } \
 				close $did
 			}
 			tclkill $dpid
-			puts "dead check..."
+			puts "\tDead$tnum: dead check..."
 			dead_check $t $n $timeout $dead $clean $other
 		}
 	}
diff --git a/storage/bdb/test/dead002.tcl b/storage/bdb/test/dead002.tcl
index bc19e7127e5230df4b23b3165dfc37f201100211..7493216d22d3d936d9890320d90f2585b9b8e80a 100644
--- a/storage/bdb/test/dead002.tcl
+++ b/storage/bdb/test/dead002.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: dead002.tcl,v 11.23 2002/09/05 17:23:05 sandstro Exp $
+# $Id: dead002.tcl,v 11.30 2004/07/07 17:05:55 carol Exp $
 #
 # TEST	dead002
 # TEST	Same test as dead001, but use "detect on every collision" instead
@@ -12,7 +12,7 @@ proc dead002 { { procs "2 4 10" } {tests "ring clump" } \
     {timeout 0} {tnum 002} } {
 	source ./include.tcl
 
-	puts "Dead$tnum: Deadlock detector tests"
+	puts "Dead$tnum: Deadlock detector tests (detect on every collision)"
 
 	env_cleanup $testdir
 
@@ -24,7 +24,7 @@ proc dead002 { { procs "2 4 10" } {tests "ring clump" } \
 	}
 	set env [berkdb_env \
 	    -create -mode 0644 -home $testdir \
-	    -lock -txn_timeout $timeout -lock_detect $lmode]
+	    -lock -lock_timeout $timeout -lock_detect $lmode]
 	error_check_good lock_env:open [is_valid_env $env] TRUE
 
 	foreach t $tests {
@@ -44,6 +44,11 @@ proc dead002 { { procs "2 4 10" } {tests "ring clump" } \
 					ddscript.tcl $testdir/dead$tnum.log.$i \
 					$testdir $t $locker $i $n &]
 				lappend pidlist $p
+				# If we're running with timeouts, pause so that
+				# locks will have a chance to time out.
+				if { $timeout != 0 } {
+					tclsleep 2
+				}
 			}
 			watch_procs $pidlist 5
 
@@ -62,6 +67,8 @@ proc dead002 { { procs "2 4 10" } {tests "ring clump" } \
 				}
 				close $did
 			}
+
+			puts "\tDead$tnum: dead check ..."
 			dead_check $t $n $timeout $dead $clean $other
 		}
 	}
diff --git a/storage/bdb/test/dead003.tcl b/storage/bdb/test/dead003.tcl
index 48088e1427c1771ac448cff09be09c0c204d8477..2a74ce4237b87a108778c4fa157728fa10e97102 100644
--- a/storage/bdb/test/dead003.tcl
+++ b/storage/bdb/test/dead003.tcl
@@ -1,26 +1,26 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: dead003.tcl,v 1.17 2002/09/05 17:23:05 sandstro Exp $
+# $Id: dead003.tcl,v 1.20 2004/01/28 03:36:26 bostic Exp $
 #
 # TEST	dead003
 # TEST
 # TEST	Same test as dead002, but explicitly specify DB_LOCK_OLDEST and
 # TEST	DB_LOCK_YOUNGEST.  Verify the correct lock was aborted/granted.
-proc dead003 { { procs "2 4 10" } {tests "ring clump" } } {
+proc dead003 { {procs "2 4 10"} {tests "ring clump"} {tnum "003"} } {
 	source ./include.tcl
 	global lock_curid
 	global lock_maxid
 
 	set detects { oldest youngest }
-	puts "Dead003: Deadlock detector tests: $detects"
+	puts "Dead$tnum: Deadlock detector tests: $detects"
 
 	# Create the environment.
 	foreach d $detects {
 		env_cleanup $testdir
-		puts "\tDead003.a: creating environment for $d"
+		puts "\tDead$tnum.a: creating environment for $d"
 		set env [berkdb_env \
 		    -create -mode 0644 -home $testdir -lock -lock_detect $d]
 		error_check_good lock_env:open [is_valid_env $env] TRUE
@@ -34,17 +34,17 @@ proc dead003 { { procs "2 4 10" } {tests "ring clump" } } {
 				error_check_good lock_id_set $ret 0
 
 				# Fire off the tests
-				puts "\tDead003: $n procs of test $t"
+				puts "\tDead$tnum: $n procs of test $t"
 				for { set i 0 } { $i < $n } { incr i } {
 					set locker [$env lock_id]
 					puts "$tclsh_path\
 					    test_path/ddscript.tcl $testdir \
 					    $t $locker $i $n >& \
-					    $testdir/dead003.log.$i"
+					    $testdir/dead$tnum.log.$i"
 					set p [exec $tclsh_path \
 					    $test_path/wrap.tcl \
 					    ddscript.tcl \
-					    $testdir/dead003.log.$i $testdir \
+					    $testdir/dead$tnum.log.$i $testdir \
 					    $t $locker $i $n &]
 					lappend pidlist $p
 				}
@@ -55,7 +55,7 @@ proc dead003 { { procs "2 4 10" } {tests "ring clump" } } {
 				set clean 0
 				set other 0
 				for { set i 0 } { $i < $n } { incr i } {
-					set did [open $testdir/dead003.log.$i]
+					set did [open $testdir/dead$tnum.log.$i]
 					while { [gets $did val] != -1 } {
 						switch $val {
 							DEADLOCK { incr dead }
@@ -65,13 +65,14 @@ proc dead003 { { procs "2 4 10" } {tests "ring clump" } } {
 					}
 					close $did
 				}
+				puts "\tDead$tnum: dead check..."
 				dead_check $t $n 0 $dead $clean $other
 				#
 				# If we get here we know we have the
 				# correct number of dead/clean procs, as
 				# checked by dead_check above.  Now verify
 				# that the right process was the one.
-				puts "\tDead003: Verify $d locks were aborted"
+				puts "\tDead$tnum: Verify $d locks were aborted"
 				set l ""
 				if { $d == "oldest" } {
 					set l [expr $n - 1]
@@ -79,7 +80,7 @@ proc dead003 { { procs "2 4 10" } {tests "ring clump" } } {
 				if { $d == "youngest" } {
 					set l 0
 				}
-				set did [open $testdir/dead003.log.$l]
+				set did [open $testdir/dead$tnum.log.$l]
 				while { [gets $did val] != -1 } {
 					error_check_good check_abort \
 					    $val 1
@@ -91,7 +92,7 @@ proc dead003 { { procs "2 4 10" } {tests "ring clump" } } {
 		fileremove -f $testdir/dd.out
 		# Remove log files
 		for { set i 0 } { $i < $n } { incr i } {
-			fileremove -f $testdir/dead003.log.$i
+			fileremove -f $testdir/dead$tnum.log.$i
 		}
 		error_check_good lock_env:close [$env close] 0
 	}
diff --git a/storage/bdb/test/dead004.tcl b/storage/bdb/test/dead004.tcl
index f5306a0d8924ce94509cacc35f463bfb37b78cfe..4f33dcd75a955735d22d58086b7e19f8e899b41e 100644
--- a/storage/bdb/test/dead004.tcl
+++ b/storage/bdb/test/dead004.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: dead004.tcl,v 11.11 2002/09/05 17:23:05 sandstro Exp $
+# $Id: dead004.tcl,v 11.15 2004/01/28 03:36:27 bostic Exp $
 #
 # Deadlock Test 4.
 # This test is designed to make sure that we handle youngest and oldest
@@ -20,17 +20,17 @@
 # a lock on (N+1) mod 4.  The deadlock detector ought to pick locker 1 or 4
 # to abort  and not 0 or 5.
 
-proc dead004 { } {
+proc dead004 { {tnum "004"} } {
 	source ./include.tcl
 	global lock_curid
 	global lock_maxid
 
 	foreach a { o y } {
-		puts "Dead004: Deadlock detector test -a $a"
+		puts "Dead$tnum: Deadlock detector test -a $a"
 		env_cleanup $testdir
 
 		# Create the environment.
-		puts "\tDead004.a: creating environment"
+		puts "\tDead$tnum.a: creating environment"
 		set env [berkdb_env -create -mode 0644 -lock -home $testdir]
 		error_check_good lock_env:open [is_valid_env $env] TRUE
 
@@ -47,15 +47,15 @@ proc dead004 { } {
 			error_check_good lock_id_set $ret 0
 
 			# Fire off the tests
-			puts "\tDead004: $n procs"
+			puts "\tDead$tnum: $n procs"
 			for { set i 0 } { $i < $n } { incr i } {
 				set locker [$env lock_id]
 				puts "$tclsh_path $test_path/wrap.tcl \
-				    $testdir/dead004.log.$i \
+				    $testdir/dead$tnum.log.$i \
 				    ddoyscript.tcl $testdir $locker $n $a $i"
 				set p [exec $tclsh_path \
 					$test_path/wrap.tcl \
-					ddoyscript.tcl $testdir/dead004.log.$i \
+					ddoyscript.tcl $testdir/dead$tnum.log.$i \
 					$testdir $locker $n $a $i &]
 				lappend pidlist $p
 			}
@@ -67,7 +67,7 @@ proc dead004 { } {
 		set clean 0
 		set other 0
 		for { set i 0 } { $i < $n } { incr i } {
-			set did [open $testdir/dead004.log.$i]
+			set did [open $testdir/dead$tnum.log.$i]
 			while { [gets $did val] != -1 } {
 				switch $val {
 					DEADLOCK { incr dead }
@@ -79,17 +79,17 @@ proc dead004 { } {
 		}
 		tclkill $dpid
 
-		puts "dead check..."
+		puts "\tDead$tnum: dead check..."
 		dead_check oldyoung $n 0 $dead $clean $other
 
 		# Now verify that neither the oldest nor the
 		# youngest were the deadlock.
-		set did [open $testdir/dead004.log.0]
+		set did [open $testdir/dead$tnum.log.0]
 		error_check_bad file:young [gets $did val] -1
 		error_check_good read:young $val 1
 		close $did
 
-		set did [open $testdir/dead004.log.[expr $procs - 1]]
+		set did [open $testdir/dead$tnum.log.[expr $procs - 1]]
 		error_check_bad file:old [gets $did val] -1
 		error_check_good read:old $val 1
 		close $did
@@ -101,7 +101,7 @@ proc dead004 { } {
 
 		# Remove log files
 		for { set i 0 } { $i < $n } { incr i } {
-			fileremove -f $testdir/dead004.log.$i
+			fileremove -f $testdir/dead$tnum.log.$i
 		}
 		error_check_good lock_env:close [$env close] 0
 	}
diff --git a/storage/bdb/test/dead005.tcl b/storage/bdb/test/dead005.tcl
index 71be8b1713f62381d1d257dcb0d8c78028dc36ab..78e9ce838d7d8e41f689ec35e6d58c77891f6741 100644
--- a/storage/bdb/test/dead005.tcl
+++ b/storage/bdb/test/dead005.tcl
@@ -1,27 +1,28 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: dead005.tcl,v 11.10 2002/09/05 17:23:05 sandstro Exp $
+# $Id: dead005.tcl,v 11.15 2004/03/17 15:17:17 bostic Exp $
 #
 # Deadlock Test 5.
 # Test out the minlocks, maxlocks, and minwrites options
 # to the deadlock detector.
-proc dead005 { { procs "4 6 10" } {tests "maxlocks minwrites minlocks" } } {
+proc dead005 { { procs "4 6 10" } \
+    {tests "maxlocks maxwrites minlocks minwrites" } { tnum "005" } } {
 	source ./include.tcl
 
-	puts "Dead005: minlocks, maxlocks, and minwrites deadlock detection tests"
 	foreach t $tests {
-		puts "Dead005.$t: creating environment"
+		puts "Dead$tnum.$t: deadlock detection tests"
 		env_cleanup $testdir
 
 		# Create the environment.
 		set env [berkdb_env -create -mode 0644 -lock -home $testdir]
 		error_check_good lock_env:open [is_valid_env $env] TRUE
 		case $t {
-			minlocks { set to n }
 			maxlocks { set to m }
+			maxwrites { set to W }
+			minlocks { set to n }
 			minwrites { set to w }
 		}
 		foreach n $procs {
@@ -31,15 +32,15 @@ proc dead005 { { procs "4 6 10" } {tests "maxlocks minwrites minlocks" } } {
 			set pidlist ""
 
 			# Fire off the tests
-			puts "\tDead005: $t test with $n procs"
+			puts "\tDead$tnum: $t test with $n procs"
 			for { set i 0 } { $i < $n } { incr i } {
 				set locker [$env lock_id]
 				puts "$tclsh_path $test_path/wrap.tcl \
-				    $testdir/dead005.log.$i \
+				    $testdir/dead$tnum.log.$i \
 				    ddscript.tcl $testdir $t $locker $i $n"
 				set p [exec $tclsh_path \
 					$test_path/wrap.tcl \
-					ddscript.tcl $testdir/dead005.log.$i \
+					ddscript.tcl $testdir/dead$tnum.log.$i \
 					$testdir $t $locker $i $n &]
 				lappend pidlist $p
 			}
@@ -50,7 +51,7 @@ proc dead005 { { procs "4 6 10" } {tests "maxlocks minwrites minlocks" } } {
 			set clean 0
 			set other 0
 			for { set i 0 } { $i < $n } { incr i } {
-				set did [open $testdir/dead005.log.$i]
+				set did [open $testdir/dead$tnum.log.$i]
 				while { [gets $did val] != -1 } {
 					switch $val {
 						DEADLOCK { incr dead }
@@ -61,16 +62,17 @@ proc dead005 { { procs "4 6 10" } {tests "maxlocks minwrites minlocks" } } {
 				close $did
 			}
 			tclkill $dpid
-			puts "dead check..."
+			puts "\tDead$tnum: dead check..."
 			dead_check $t $n 0 $dead $clean $other
 			# Now verify that the correct participant
 			# got deadlocked.
 			switch $t {
+				maxlocks {set f [expr $n - 1]}
+				maxwrites {set f 2}
 				minlocks {set f 0}
 				minwrites {set f 1}
-				maxlocks {set f [expr $n - 1]}
 			}
-			set did [open $testdir/dead005.log.$f]
+			set did [open $testdir/dead$tnum.log.$f]
 			error_check_bad file:$t [gets $did val] -1
 			error_check_good read($f):$t $val DEADLOCK
 			close $did
diff --git a/storage/bdb/test/dead006.tcl b/storage/bdb/test/dead006.tcl
index b70e011fb744136ab6ee1d2fb1a4f64a28eca13d..4d80af41894751fcb39e28056e85b8a4eb7c01be 100644
--- a/storage/bdb/test/dead006.tcl
+++ b/storage/bdb/test/dead006.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: dead006.tcl,v 1.4 2002/01/11 15:53:21 bostic Exp $
+# $Id: dead006.tcl,v 1.6 2004/01/28 03:36:27 bostic Exp $
 #
 # TEST	dead006
 # TEST	use timeouts rather than the normal dd algorithm.
diff --git a/storage/bdb/test/dead007.tcl b/storage/bdb/test/dead007.tcl
index 2b6a78cb4b92f6f285d099daccd5fab2620ae9c5..e9aefa9c0ba1eec1d896afadd446cf37bb31db9e 100644
--- a/storage/bdb/test/dead007.tcl
+++ b/storage/bdb/test/dead007.tcl
@@ -1,34 +1,36 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: dead007.tcl,v 1.3 2002/01/11 15:53:22 bostic Exp $
+# $Id: dead007.tcl,v 1.6 2004/01/28 03:36:27 bostic Exp $
 #
 # TEST	dead007
-# TEST	use timeouts rather than the normal dd algorithm.
-proc dead007 { } {
+# TEST	Tests for locker and txn id wraparound.
+proc dead007 { {tnum "007"} } {
 	source ./include.tcl
 	global lock_curid
 	global lock_maxid
 
 	set save_curid $lock_curid
 	set save_maxid $lock_maxid
-	puts "Dead007.a -- wrap around"
+	puts "Dead$tnum.a -- wrap around"
 	set lock_curid [expr $lock_maxid - 2]
-	dead001 "2 10"
+	dead001 "2 10" "ring clump" "0" $tnum
 	## Oldest/youngest breaks when the id wraps
 	# dead003 "4 10"
-	dead004
+	dead004 $tnum
 
-	puts "Dead007.b -- extend space"
+	puts "Dead$tnum.b -- extend space"
 	set lock_maxid [expr $lock_maxid - 3]
 	set lock_curid [expr $lock_maxid - 1]
-	dead001 "4 10"
+	dead001 "4 10" "ring clump" "0" $tnum
 	## Oldest/youngest breaks when the id wraps
 	# dead003 "10"
-	dead004
+	dead004 $tnum
 
 	set lock_curid $save_curid
 	set lock_maxid $save_maxid
+	# Return the empty string so we don't return lock_maxid.
+	return ""
 }
diff --git a/storage/bdb/test/env001.tcl b/storage/bdb/test/env001.tcl
index 781029f6a5cf0d3a2faa26e701d1587045c90dd2..4e2c070e579a8ac2012e5b1b0f141de3e1b0b910 100644
--- a/storage/bdb/test/env001.tcl
+++ b/storage/bdb/test/env001.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: env001.tcl,v 11.26 2002/05/08 19:01:43 margo Exp $
+# $Id: env001.tcl,v 11.28 2004/01/28 03:36:27 bostic Exp $
 #
 # TEST	env001
 # TEST	Test of env remove interface (formerly env_remove).
diff --git a/storage/bdb/test/env002.tcl b/storage/bdb/test/env002.tcl
index 89c44f63a1233da4d2f4131bdf7861cfaa789a09..70f573c29801ee391920678937706b0ebc3ce37c 100644
--- a/storage/bdb/test/env002.tcl
+++ b/storage/bdb/test/env002.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: env002.tcl,v 11.15 2002/02/20 16:35:20 sandstro Exp $
+# $Id: env002.tcl,v 11.17 2004/01/28 03:36:27 bostic Exp $
 #
 # TEST	env002
 # TEST	Test of DB_LOG_DIR and env name resolution.
diff --git a/storage/bdb/test/env003.tcl b/storage/bdb/test/env003.tcl
index c16b54dd5e01085ca660f74c049bec929ba1969d..247fcd3c9a882f39b0d2a4e63eeb30459c73740c 100644
--- a/storage/bdb/test/env003.tcl
+++ b/storage/bdb/test/env003.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: env003.tcl,v 11.21 2002/08/08 15:38:06 bostic Exp $
+# $Id: env003.tcl,v 11.23 2004/01/28 03:36:27 bostic Exp $
 #
 # TEST	env003
 # TEST	Test DB_TMP_DIR and env name resolution
diff --git a/storage/bdb/test/env004.tcl b/storage/bdb/test/env004.tcl
index e93a0d953086e67b14896a4ecc75af32396fb9fe..fe975d700fd9ef61d73d365c925148fa67ba4c62 100644
--- a/storage/bdb/test/env004.tcl
+++ b/storage/bdb/test/env004.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: env004.tcl,v 11.18 2002/02/20 17:08:21 sandstro Exp $
+# $Id: env004.tcl,v 11.22 2004/04/23 15:40:12 sue Exp $
 #
 # TEST	env004
 # TEST	Test multiple data directories.  Do a bunch of different opens
@@ -32,15 +32,9 @@ proc env004 { } {
 	puts $cid "set_data_dir data3"
 	close $cid
 
-	# Now get pathnames
-	set curdir [pwd]
-	cd $testdir
-	set fulldir [pwd]
-	cd $curdir
-
 	set e [berkdb_env -create -private -home $testdir]
 	error_check_good dbenv [is_valid_env $e] TRUE
-	ddir_test $fulldir $method $e $args
+	ddir_test $method $e $args
 	error_check_good env_close [$e close] 0
 
 	puts "\tEnv004.b: Multiple data directories in berkdb_env call."
@@ -54,13 +48,11 @@ proc env004 { } {
 	    -data_dir . -data_dir data1 -data_dir data2 \
 	    -data_dir data3 -home $testdir]
 	error_check_good dbenv [is_valid_env $e] TRUE
-	ddir_test $fulldir $method $e $args
+	ddir_test $method $e $args
 	error_check_good env_close [$e close] 0
-
-	env_cleanup $testdir
 }
 
-proc ddir_test { fulldir method e args } {
+proc ddir_test { method e args } {
 	source ./include.tcl
 
 	set args [convert_args $args]
@@ -87,13 +79,13 @@ proc ddir_test { fulldir method e args } {
 	# Now, reopen the files without complete pathnames and make
 	# sure that we find them.
 
-	set db1 [berkdb_open -env $e $fulldir/data1/datafile1.db]
+	set db1 [berkdb_open -env $e datafile1.db]
 	error_check_good dbopen1 [is_valid_db $db1] TRUE
 
-	set db2 [berkdb_open -env $e $fulldir/data2/datafile2.db]
+	set db2 [berkdb_open -env $e datafile2.db]
 	error_check_good dbopen2 [is_valid_db $db2] TRUE
 
-	set db3 [berkdb_open -env $e $fulldir/data3/datafile3.db]
+	set db3 [berkdb_open -env $e datafile3.db]
 	error_check_good dbopen3 [is_valid_db $db3] TRUE
 
 	# Finally close all the files
diff --git a/storage/bdb/test/env005.tcl b/storage/bdb/test/env005.tcl
index 03bb1b40b34f9e1b1f05da5d70016c06ba72f664..fc08bc97fa14177f5bd5464992fd5945d8266e82 100644
--- a/storage/bdb/test/env005.tcl
+++ b/storage/bdb/test/env005.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: env005.tcl,v 11.15 2002/02/22 14:28:37 sandstro Exp $
+# $Id: env005.tcl,v 11.20 2004/01/28 03:36:27 bostic Exp $
 #
 # TEST	env005
 # TEST	Test that using subsystems without initializing them correctly
@@ -16,7 +16,6 @@ proc env005 { } {
 
 	env_cleanup $testdir
 	puts "\tEnv005.a: Creating env with no subsystems."
-
 	set e [berkdb_env_noerr -create -home $testdir]
 	error_check_good dbenv [is_valid_env $e] TRUE
 	set db [berkdb_open -create -btree $testdir/env005.db]
diff --git a/storage/bdb/test/env006.tcl b/storage/bdb/test/env006.tcl
index 48fc6982772e1e2a4d05b1d2484325cd5be67e6f..9f220335749ceea0a5452946f207590094a4669c 100644
--- a/storage/bdb/test/env006.tcl
+++ b/storage/bdb/test/env006.tcl
@@ -1,12 +1,13 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: env006.tcl,v 11.8 2002/01/11 15:53:23 bostic Exp $
+# $Id: env006.tcl,v 11.11 2004/04/27 19:56:44 carol Exp $
 #
 # TEST	env006
 # TEST	Make sure that all the utilities exist and run.
+# TEST	Test that db_load -r options don't blow up.
 proc env006 { } {
 	source ./include.tcl
 
@@ -39,4 +40,52 @@ proc env006 { } {
 		#
 		error_check_good $cmd.err [is_substr $ret sage] 1
 	}
+
+	env_cleanup $testdir
+	set env [eval berkdb_env -create -home $testdir -txn]
+	error_check_good env_open [is_valid_env $env] TRUE
+
+	set sub SUBDB
+	foreach case { noenv env } {
+		if { $case == "env" } {
+			set envargs " -env $env "
+			set homeargs " -h $testdir "
+			set testfile env006.db
+		} else {
+			set envargs ""
+			set homeargs ""
+			set testfile $testdir/env006.db
+		}
+
+		puts "\tEnv006.i: Testing db_load -r with $case."
+		set db [eval berkdb_open -create $envargs -btree $testfile]
+		error_check_good db_open [is_valid_db $db] TRUE
+		error_check_good db_close [$db close] 0
+
+		set ret [eval \
+		    exec $util_path/db_load -r lsn $homeargs $testfile]
+		error_check_good db_load_r_lsn $ret ""
+		set ret [eval \
+		    exec $util_path/db_load -r fileid $homeargs $testfile]
+		error_check_good db_load_r_fileid $ret ""
+
+		error_check_good db_remove \
+		    [eval {berkdb dbremove} $envargs $testfile] 0
+
+		puts "\tEnv006.j: Testing db_load -r with $case and subdbs."
+		set db [eval berkdb_open -create $envargs -btree $testfile $sub]
+		error_check_good db_open [is_valid_db $db] TRUE
+		error_check_good db_close [$db close] 0
+
+		set ret [eval \
+		    exec {$util_path/db_load} -r lsn $homeargs $testfile]
+		error_check_good db_load_r_lsn $ret ""
+		set ret [eval \
+		    exec {$util_path/db_load} -r fileid $homeargs $testfile]
+		error_check_good db_load_r_fileid $ret ""
+
+		error_check_good \
+		    db_remove [eval {berkdb dbremove} $envargs $testfile] 0
+	}
+	error_check_good env_close [$env close] 0
 }
diff --git a/storage/bdb/test/env007.tcl b/storage/bdb/test/env007.tcl
index 5748d2dbc897fcdde209c4c4ac21df00b014ef83..efbb17d55c71f726bf9381ba7c0d7744c3967544 100644
--- a/storage/bdb/test/env007.tcl
+++ b/storage/bdb/test/env007.tcl
@@ -1,50 +1,102 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: env007.tcl,v 11.21 2002/08/12 20:49:36 sandstro Exp $
+# $Id: env007.tcl,v 11.41 2004/09/22 18:01:04 bostic Exp $
 #
 # TEST	env007
-# TEST	Test various DB_CONFIG config file options.
+# TEST	Test DB_CONFIG config file options for berkdb env.
 # TEST	1) Make sure command line option is respected
 # TEST	2) Make sure that config file option is respected
 # TEST	3) Make sure that if -both- DB_CONFIG and the set_<whatever>
-# TEST		method is used,	only the file is respected.
+# TEST		method is used, only the file is respected.
 # TEST	Then test all known config options.
+# TEST	Also test config options on berkdb open.  This isn't
+# TEST	really env testing, but there's no better place to put it.
 proc env007 { } {
 	global errorInfo
-
-	#   env007 is essentially just a small driver that runs
-	# env007_body twice.  First, it supplies a "set" argument
-	# to use with environment opens, and the second time it sets
-	# DB_CONFIG instead.
-	#   Note that env007_body itself calls env007_run_test to run
-	# the body of the actual test.
-
+	global passwd
+	global has_crypto
 	source ./include.tcl
 
-	puts "Env007: DB_CONFIG test."
+	puts "Env007: DB_CONFIG and getters test."
+	puts "Env007.a: Test berkdb env options using getters and stat."
 
-	#
-	# Test only those options we can easily check via stat
+	# Set up options we can check via stat or getters.  Structure
+	# of the list is:
+	# 	0.  Arg used in berkdb env command
+	# 	1.  Arg used in DB_CONFIG file
+	#	2.  Value assigned in berkdb env command
+	#	3.  Value assigned in DB_CONFIG file
+	# 	4.  Message output during test
+	#	5.  Stat command to run (empty if we can't get the info
+	#		from stat).
+	# 	6.  String to search for in stat output
+	#	7.  Which arg to check in stat (needed for cases where
+	#         we set more than one args at a time, but stat can
+	# 	    only check one args, like cachesize)
+	# 	8.  Arg used in getter
 	#
 	set rlist {
-	{ " -txn_max " "set_tx_max" "19" "31" "Env007.a: Txn Max"
-	    "txn_stat" "Max Txns"}
-	{ " -lock_max_locks " "set_lk_max_locks" "17" "29" "Env007.b: Lock Max"
-	    "lock_stat" "Maximum locks"}
+	{ " -txn_max " "set_tx_max" "19" "31"
+	    "Env007.a1: Txn Max" "txn_stat"
+	    "Max Txns" "0" "get_tx_max" }
+	{ " -lock_max_locks " "set_lk_max_locks" "17" "29"
+	    "Env007.a2: Lock Max" "lock_stat"
+	    "Maximum locks" "0" "get_lk_max_locks" }
 	{ " -lock_max_lockers " "set_lk_max_lockers" "1500" "2000"
-	    "Env007.c: Max Lockers" "lock_stat" "Maximum lockers"}
+	    "Env007.a3: Max Lockers" "lock_stat"
+	    "Maximum lockers" "0" "get_lk_max_lockers" }
 	{ " -lock_max_objects " "set_lk_max_objects" "1500" "2000"
-	    "Env007.d: Max Objects" "lock_stat" "Maximum objects"}
-	{ " -log_buffer " "set_lg_bsize" "65536" "131072" "Env007.e: Log Bsize"
-	    "log_stat" "Log record cache size"}
-	{ " -log_max " "set_lg_max" "8388608" "9437184" "Env007.f: Log Max"
-	    "log_stat" "Current log file size"}
+	    "Env007.a4: Max Objects" "lock_stat"
+	    "Maximum objects" "0" "get_lk_max_objects" }
+	{ " -log_buffer " "set_lg_bsize" "65536" "131072"
+	    "Env007.a5: Log Bsize" "log_stat"
+	    "Log record cache size" "0" "get_lg_bsize" }
+	{ " -log_max " "set_lg_max" "8388608" "9437184"
+	    "Env007.a6: Log Max" "log_stat"
+	    "Current log file size" "0" "get_lg_max" }
+	{ " -cachesize " "set_cachesize" "0 536870912 1" "1 0 1"
+	    "Env007.a7.0: Cachesize" "mpool_stat"
+	    "Cache size (gbytes)" "0" "get_cachesize" }
+	{ " -cachesize " "set_cachesize" "0 536870912 1" "1 0 1"
+	    "Env007.a7.1: Cachesize" "mpool_stat"
+	    "Cache size (bytes)" "1" "get_cachesize" }
+	{ " -cachesize " "set_cachesize" "0 536870912 1" "1 0 1"
+	    "Env007.a7.2: Cachesize" "mpool_stat"
+	    "Number of caches" "2" "get_cachesize" }
+	{ " -lock_timeout " "set_lock_timeout" "100" "120"
+	    "Env007.a8: Lock Timeout" "lock_stat"
+	    "Lock timeout value" "0" "get_timeout lock" }
+	{ " -log_regionmax " "set_lg_regionmax" "8388608" "4194304"
+	    "Env007.a9: Log Regionmax" "log_stat"
+	    "Region size" "0" "get_lg_regionmax" }
+	{ " -mpool_max_openfd " "set_mp_max_openfd" "17" "27"
+	    "Env007.a10: Mmap max openfd" "mpool_stat"
+	    "Maximum open file descriptors" "0" "get_mp_max_openfd" }
+	{ " -mpool_max_write " "set_mp_max_write" "37 47" "57 67"
+	    "Env007.a11.0: Mmap max write" "mpool_stat"
+	    "Maximum sequential buffer writes" "0" "get_mp_max_write" }
+	{ " -mpool_max_write " "set_mp_max_write" "37 47" "57 67"
+	    "Env007.a11.1: Mmap max write" "mpool_stat"
+	    "Sleep after writing maximum buffers" "1" "get_mp_max_write" }
+	{ " -mpool_mmap_size " "set_mp_mmapsize" "12582912" "8388608"
+	    "Env007.a12: Mmapsize" "mpool_stat"
+	    "Maximum memory-mapped file size" "0" "get_mp_mmapsize" }
+	{ " -shm_key " "set_shm_key" "15" "35"
+	    "Env007.a13: Shm Key" ""
+	    "" "" "get_shm_key" }
+	{ " -tmp_dir " "set_tmp_dir" "." "./TEMPDIR"
+	    "Env007.a14: Temp dir" ""
+	    "" "" "get_tmp_dir" }
+	{ " -txn_timeout " "set_txn_timeout" "100" "120"
+	    "Env007.a15: Txn timeout" "lock_stat"
+	    "Transaction timeout value" "0" "get_timeout txn" }
 	}
 
-	set e "berkdb_env -create -mode 0644 -home $testdir -log -lock -txn "
+	set e "berkdb_env_noerr -create -mode 0644 -home $testdir -txn "
+	set qnxexclude {set_cachesize}
 	foreach item $rlist {
 		set envarg [lindex $item 0]
 		set configarg [lindex $item 1]
@@ -53,99 +105,295 @@ proc env007 { } {
 		set msg [lindex $item 4]
 		set statcmd [lindex $item 5]
 		set statstr [lindex $item 6]
+		set index [lindex $item 7]
+		set getter [lindex $item 8]
+
+		if { $is_qnx_test &&
+		    [lsearch $qnxexclude $configarg] != -1 } {
+			puts "\tEnv007.a: Skipping $configarg for QNX"
+			continue
+		}
 
 		env_cleanup $testdir
+
 		# First verify using just env args
 		puts "\t$msg Environment argument only"
-		set env [eval $e $envarg $envval]
+		set env [eval $e $envarg {$envval}]
 		error_check_good envopen:0 [is_valid_env $env] TRUE
-		env007_check $env $statcmd $statstr $envval
+		error_check_good get_envval [eval $env $getter] $envval
+		if { $statcmd != "" } {
+			set statenvval [lindex $envval $index]
+			# log_stat reports the sum of the specified
+			# region size and the log buffer size.
+			if { $statstr == "Region size" } {
+				set lbufsize 32768
+				set statenvval [expr $statenvval + $lbufsize]
+			}
+			env007_check $env $statcmd $statstr $statenvval
+		}
 		error_check_good envclose:0 [$env close] 0
 
 		env_cleanup $testdir
 		env007_make_config $configarg $configval
 
-		#  verify using just config file
+		# Verify using just config file
 		puts "\t$msg Config file only"
 		set env [eval $e]
 		error_check_good envopen:1 [is_valid_env $env] TRUE
-		env007_check $env $statcmd $statstr $configval
+		error_check_good get_configval1 [eval $env $getter] $configval
+		if { $statcmd != "" } {
+			set statconfigval [lindex $configval $index]
+			if { $statstr == "Region size" } {
+				set statconfigval [expr $statconfigval + $lbufsize]
+			}
+			env007_check $env $statcmd $statstr $statconfigval
+		}
 		error_check_good envclose:1 [$env close] 0
 
-		# First verify using just env args
+		# Now verify using env args and config args
 		puts "\t$msg Environment arg and config file"
-		set env [eval $e $envarg $envval]
+		set env [eval $e $envarg {$envval}]
 		error_check_good envopen:2 [is_valid_env $env] TRUE
-		env007_check $env $statcmd $statstr $configval
+		# Getter should retrieve config val, not envval.
+		error_check_good get_configval2 [eval $env $getter] $configval
+		if { $statcmd != "" } {
+			env007_check $env $statcmd $statstr $statconfigval
+		}
 		error_check_good envclose:2 [$env close] 0
 	}
 
 	#
-	# Test all options.  For all config options, write it out
-	# to the file and make sure we can open the env.  We cannot
-	# necessarily check via stat that it worked but this execs
-	# the config file code itself.
+	# Test all options that can be set in DB_CONFIG.  Write it out
+	# to the file and make sure we can open the env.  This execs
+	# the config file code.  Also check with a getter that the
+	# expected value is returned.
 	#
+	puts "\tEnv007.b: Test berkdb env config options using getters\
+	    and env open."
+
+	# The cfglist variable contains options that can be set in DB_CONFIG.
 	set cfglist {
-	{ "set_cachesize" "0 1048576 0" }
-	{ "set_data_dir" "." }
-	{ "set_flags" "db_cdb_alldb" }
-	{ "set_flags" "db_direct_db" }
-	{ "set_flags" "db_direct_log" }
-	{ "set_flags" "db_nolocking" }
-	{ "set_flags" "db_nommap" }
-	{ "set_flags" "db_nopanic" }
-	{ "set_flags" "db_overwrite" }
-	{ "set_flags" "db_region_init" }
-	{ "set_flags" "db_txn_nosync" }
-	{ "set_flags" "db_txn_write_nosync" }
-	{ "set_flags" "db_yieldcpu" }
-	{ "set_lg_bsize" "65536" }
-	{ "set_lg_dir" "." }
-	{ "set_lg_max" "8388608" }
-	{ "set_lg_regionmax" "65536" }
-	{ "set_lk_detect" "db_lock_default" }
-	{ "set_lk_detect" "db_lock_expire" }
-	{ "set_lk_detect" "db_lock_maxlocks" }
-	{ "set_lk_detect" "db_lock_minlocks" }
-	{ "set_lk_detect" "db_lock_minwrite" }
-	{ "set_lk_detect" "db_lock_oldest" }
-	{ "set_lk_detect" "db_lock_random" }
-	{ "set_lk_detect" "db_lock_youngest" }
-	{ "set_lk_max" "50" }
-	{ "set_lk_max_lockers" "1500" }
-	{ "set_lk_max_locks" "29" }
-	{ "set_lk_max_objects" "1500" }
-	{ "set_lock_timeout" "100" }
-	{ "set_mp_mmapsize" "12582912" }
-	{ "set_region_init" "1" }
-	{ "set_shm_key" "15" }
-	{ "set_tas_spins" "15" }
-	{ "set_tmp_dir" "." }
-	{ "set_tx_max" "31" }
-	{ "set_txn_timeout" "100" }
-	{ "set_verbose" "db_verb_chkpoint" }
-	{ "set_verbose" "db_verb_deadlock" }
-	{ "set_verbose" "db_verb_recovery" }
-	{ "set_verbose" "db_verb_waitsfor" }
-	}
-
-	puts "\tEnv007.g: Config file settings"
-	set e "berkdb_env -create -mode 0644 -home $testdir -log -lock -txn "
+	{ "set_data_dir" "." "get_data_dirs" "." }
+	{ "set_flags" "db_auto_commit" "get_flags" "-auto_commit" }
+	{ "set_flags" "db_cdb_alldb" "get_flags" "-cdb_alldb" }
+	{ "set_flags" "db_direct_db" "get_flags" "-direct_db" }
+	{ "set_flags" "db_direct_log" "get_flags" "-direct_log" }
+	{ "set_flags" "db_dsync_log" "get_flags" "-dsync_log" }
+	{ "set_flags" "db_log_autoremove" "get_flags" "-log_remove" }
+	{ "set_flags" "db_nolocking" "get_flags" "-nolock" }
+	{ "set_flags" "db_nommap" "get_flags" "-nommap" }
+	{ "set_flags" "db_nopanic" "get_flags" "-nopanic" }
+	{ "set_flags" "db_overwrite" "get_flags" "-overwrite" }
+	{ "set_flags" "db_region_init" "get_flags" "-region_init" }
+	{ "set_flags" "db_txn_nosync" "get_flags" "-nosync" }
+	{ "set_flags" "db_txn_write_nosync" "get_flags" "-wrnosync" }
+	{ "set_flags" "db_yieldcpu" "get_flags" "-yield" }
+	{ "set_lg_bsize" "65536" "get_lg_bsize" "65536" }
+	{ "set_lg_dir" "." "get_lg_dir" "." }
+	{ "set_lg_max" "8388608" "get_lg_max" "8388608" }
+	{ "set_lg_regionmax" "65536" "get_lg_regionmax" "65536" }
+	{ "set_lk_detect" "db_lock_default" "get_lk_detect" "default" }
+	{ "set_lk_detect" "db_lock_expire" "get_lk_detect" "expire" }
+	{ "set_lk_detect" "db_lock_maxlocks" "get_lk_detect" "maxlocks" }
+	{ "set_lk_detect" "db_lock_minlocks" "get_lk_detect" "minlocks" }
+	{ "set_lk_detect" "db_lock_minwrite" "get_lk_detect" "minwrite" }
+	{ "set_lk_detect" "db_lock_oldest" "get_lk_detect" "oldest" }
+	{ "set_lk_detect" "db_lock_random" "get_lk_detect" "random" }
+	{ "set_lk_detect" "db_lock_youngest" "get_lk_detect" "youngest" }
+	{ "set_lk_max_lockers" "1500" "get_lk_max_lockers" "1500" }
+	{ "set_lk_max_locks" "29" "get_lk_max_locks" "29" }
+	{ "set_lk_max_objects" "1500" "get_lk_max_objects" "1500" }
+	{ "set_lock_timeout" "100" "get_timeout lock" "100" }
+	{ "set_mp_mmapsize" "12582912" "get_mp_mmapsize" "12582912" }
+	{ "set_mp_max_write" "10 20" "get_mp_max_write" "10 20" }
+	{ "set_mp_max_openfd" "10" "get_mp_max_openfd" "10" }
+	{ "set_region_init" "1" "get_flags" "-region_init" }
+	{ "set_shm_key" "15" "get_shm_key" "15" }
+	{ "set_tas_spins" "15" "get_tas_spins" "15" }
+	{ "set_tmp_dir" "." "get_tmp_dir" "." }
+	{ "set_tx_max" "31" "get_tx_max" "31" }
+	{ "set_txn_timeout" "50" "get_timeout txn" "50" }
+	{ "set_verbose" "db_verb_deadlock" "get_verbose deadlock" "on" }
+	{ "set_verbose" "db_verb_recovery" "get_verbose recovery" "on" }
+	{ "set_verbose" "db_verb_replication" "get_verbose rep" "on" }
+	{ "set_verbose" "db_verb_waitsfor" "get_verbose wait" "on" }
+	}
+
+	env_cleanup $testdir
+	set e "berkdb_env_noerr -create -mode 0644 -home $testdir -txn"
+	set directlist {db_direct_db db_direct_log}
 	foreach item $cfglist {
 		env_cleanup $testdir
 		set configarg [lindex $item 0]
 		set configval [lindex $item 1]
+		set getter [lindex $item 2]
+		set getval [lindex $item 3]
 
 		env007_make_config $configarg $configval
 
-		#  verify using just config file
-		puts "\t\t $configarg $configval"
-		set env [eval $e]
+		# Verify using config file
+		puts "\t\tEnv007.b: $configarg $configval"
+
+		# Unconfigured/unsupported direct I/O is not reported
+		# as a failure.
+		set directmsg \
+		    "direct I/O either not configured or not supported"
+		if {[catch { eval $e } env ]} {
+			if { [lsearch $directlist $configval] != -1 && \
+			    [is_substr $env $directmsg] == 1 } {
+				continue
+			} else {
+				puts "FAIL: $env"
+				continue
+			}
+		}
 		error_check_good envvalid:1 [is_valid_env $env] TRUE
+		error_check_good getter:1 [eval $env $getter] $getval
 		error_check_good envclose:1 [$env close] 0
 	}
 
+	puts "\tEnv007.c: Test berkdb env options using getters and env open."
+	# The envopenlist variable contains options that can be set using
+	# berkdb env.  We always set -mpool.
+	set envopenlist {
+	{ "-cdb" "" "-cdb" "get_open_flags" }
+	{ "-errpfx" "FOO" "FOO" "get_errpfx" }
+	{ "-lock" "" "-lock" "get_open_flags" }
+	{ "-log" "" "-log" "get_open_flags" }
+	{ "" "" "-mpool" "get_open_flags" }
+	{ "-system_mem" "-shm_key 1" "-system_mem" "get_open_flags" }
+	{ "-txn" "" "-txn" "get_open_flags" }
+	{ "-recover" "-txn" "-recover" "get_open_flags" }
+	{ "-recover_fatal" "-txn" "-recover_fatal" "get_open_flags" }
+	{ "-use_environ" "" "-use_environ" "get_open_flags" }
+	{ "-use_environ_root" "" "-use_environ_root" "get_open_flags" }
+	{ "" "" "-create" "get_open_flags" }
+	{ "-private" ""  "-private" "get_open_flags" }
+	{ "-thread" "" "-thread" "get_open_flags" }
+	{ "-txn_timestamp" "100000000" "100000000" "get_tx_timestamp" }
+	}
+
+	if { $has_crypto == 1 } {
+		lappend envopenlist \
+		    { "-encryptaes" "$passwd" "-encryptaes" "get_encrypt_flags" }
+	}
+
+	set e "berkdb_env -create -mode 0644 -home $testdir"
+	set qnxexclude {-system_mem}
+	foreach item $envopenlist {
+		set envarg [lindex $item 0]
+		set envval [lindex $item 1]
+		set retval [lindex $item 2]
+		set getter [lindex $item 3]
+
+		if { $is_qnx_test &&
+		    [lsearch $qnxexclude $envarg] != -1} {
+			puts "\t\tEnv007: Skipping $envarg for QNX"
+			continue
+		}
+		env_cleanup $testdir
+		# Set up env
+		set env [eval $e $envarg $envval]
+		error_check_good envopen [is_valid_env $env] TRUE
+
+		# Check that getter retrieves expected retval.
+		set get_retval [eval $env $getter]
+		if { [is_substr $get_retval $retval] != 1 } {
+			puts "FAIL: $retval\
+			    should be a substring of $get_retval"
+			continue
+		}
+		error_check_good envclose [$env close] 0
+
+		# The -encryptany flag can only be tested on an existing
+		# environment that supports encryption, so do it here.
+		if { $has_crypto == 1 } {
+			if { $envarg == "-encryptaes" } {
+				set env [eval berkdb_env -home $testdir\
+				    -encryptany $passwd]
+				error_check_good get_encryptany \
+				    [eval $env get_encrypt_flags] "-encryptaes"
+				error_check_good env_close [$env close] 0
+			}
+		}
+	}
+
+	puts "\tEnv007.d: Test berkdb env options using set_flags and getters."
+
+	# The flaglist variable contains options that can be set using
+	# $env set_flags.
+	set flaglist {
+	{ "-direct_db" }
+	{ "-direct_log" }
+	{ "-dsync_log" }
+	{ "-log_remove" }
+	{ "-nolock" }
+	{ "-nommap" }
+	{ "-nopanic" }
+	{ "-nosync" }
+	{ "-overwrite" }
+	{ "-panic" }
+	{ "-wrnosync" }
+	}
+	set e "berkdb_env_noerr -create -mode 0644 -home $testdir"
+	set directlist {-direct_db -direct_log}
+	foreach item $flaglist {
+		set flag [lindex $item 0]
+		env_cleanup $testdir
+
+		# Set up env
+		set env [eval $e]
+		error_check_good envopen [is_valid_env $env] TRUE
+
+		# Use set_flags to turn on new env characteristics.
+		#
+		# Unconfigured/unsupported direct I/O is not reported
+		# as a failure.
+		if {[catch { $env set_flags $flag on } res ]} {
+			if { [lsearch $directlist $flag] != -1 && \
+			    [is_substr $res $directmsg] == 1 } {
+				error_check_good env_close [$env close] 0
+				continue
+			} else {
+				puts "FAIL: $res"
+				error_check_good env_close [$env close] 0
+				continue
+			}
+		} else {
+			error_check_good "flag $flag on" $res 0
+		}
+
+		# Check that getter retrieves expected retval.
+		set get_retval [eval $env get_flags]
+		if { [is_substr $get_retval $flag] != 1 } {
+			puts "FAIL: $flag should be a substring of $get_retval"
+			error_check_good env_close [$env close] 0
+			continue
+		}
+		# Use set_flags to turn off env characteristics, make sure
+		# they are gone.
+		error_check_good "flag $flag off" [$env set_flags $flag off] 0
+		set get_retval [eval $env get_flags]
+		if { [is_substr $get_retval $flag] == 1 } {
+			puts "FAIL: $flag should not be in $get_retval"
+			error_check_good env_close [$env close] 0
+			continue
+		}
+
+		error_check_good envclose [$env close] 0
+	}
+
+	puts "\tEnv007.e: Test env get_home."
+	env_cleanup $testdir
+	# Set up env
+	set env [eval $e]
+	error_check_good env_open [is_valid_env $env] TRUE
+	# Test for correct value.
+	set get_retval [eval $env get_home]
+	error_check_good get_home $get_retval $testdir
+	error_check_good envclose [$env close] 0
+
+	puts "\tEnv007.f: Test that bad config values are rejected."
 	set cfglist {
 	{ "set_cachesize" "1048576" }
 	{ "set_flags" "db_xxx" }
@@ -161,6 +409,8 @@ proc env007 { } {
 	{ "set_lk_max_locks" "db_xxx" }
 	{ "set_lk_max_lockers" "db_xxx" }
 	{ "set_lk_max_objects" "db_xxx" }
+	{ "set_mp_max_openfd" "1 2" }
+	{ "set_mp_max_write" "1 2 3" }
 	{ "set_mp_mmapsize" "db_xxx" }
 	{ "set_region_init" "db_xxx" }
 	{ "set_shm_key" "db_xxx" }
@@ -170,7 +420,7 @@ proc env007 { } {
 	{ "set_verbose" "1" }
 	{ "set_verbose" "db_verb_recovery x" }
 	}
-	puts "\tEnv007.h: Config value errors"
+
 	set e "berkdb_env_noerr -create -mode 0644 \
 	    -home $testdir -log -lock -txn "
 	foreach item $cfglist {
@@ -180,14 +430,13 @@ proc env007 { } {
 		env007_make_config $configarg $configval
 
 		#  verify using just config file
-		puts "\t\t $configarg $configval"
 		set stat [catch {eval $e} ret]
 		error_check_good envopen $stat 1
 		error_check_good error [is_substr $errorInfo \
 		    "incorrect arguments for name-value pair"] 1
 	}
 
-	puts "\tEnv007.i: Config name error set_xxx"
+	puts "\tEnv007.g: Config name error set_xxx"
 	set e "berkdb_env_noerr -create -mode 0644 \
 	    -home $testdir -log -lock -txn "
 	env007_make_config "set_xxx" 1
@@ -195,6 +444,139 @@ proc env007 { } {
 	error_check_good envopen $stat 1
 	error_check_good error [is_substr $errorInfo \
 		    "unrecognized name-value pair"] 1
+
+	puts "\tEnv007.h: Test berkdb open flags and getters."
+	# Check options that we configure with berkdb open and
+	# query via getters.  Structure of the list is:
+	# 	0.  Flag used in berkdb open command
+	#	1.  Value specified to flag
+	#	2.  Specific method, if needed
+	# 	3.  Arg used in getter
+
+	set olist {
+	{ "-minkey" "4" " -btree " "get_bt_minkey" }
+	{ "-cachesize" "0 1048576 1" "" "get_cachesize" }
+	{ "" "FILENAME DBNAME" "" "get_dbname" }
+	{ "" "" "" "get_env" }
+	{ "-errpfx" "ERROR:" "" "get_errpfx" }
+	{ "" "-chksum" "" "get_flags" }
+	{ "-delim" "58" "-recno" "get_re_delim" }
+	{ "" "-dup" "" "get_flags" }
+	{ "" "-dup -dupsort" "" "get_flags" }
+	{ "" "-recnum" "" "get_flags" }
+	{ "" "-revsplitoff" "" "get_flags" }
+	{ "" "-renumber" "-recno" "get_flags" }
+	{ "" "-snapshot" "-recno" "get_flags" }
+	{ "" "-create" "" "get_open_flags" }
+	{ "" "-create -dirty" "" "get_open_flags" }
+	{ "" "-create -excl" "" "get_open_flags" }
+	{ "" "-create -nommap" "" "get_open_flags" }
+	{ "" "-create -thread" "" "get_open_flags" }
+	{ "" "-create -truncate" "" "get_open_flags" }
+	{ "-ffactor" "40" " -hash " "get_h_ffactor" }
+	{ "-lorder" "4321" "" "get_lorder" }
+	{ "-nelem" "10000" " -hash " "get_h_nelem" }
+	{ "-pagesize" "4096" "" "get_pagesize" }
+	{ "-extent" "4" "-queue" "get_q_extentsize" }
+	{ "-len" "20" "-recno" "get_re_len" }
+	{ "-pad" "0" "-recno" "get_re_pad" }
+	{ "-source" "include.tcl" "-recno" "get_re_source" }
+	}
+
+	set o "berkdb_open -create -mode 0644"
+	foreach item $olist {
+		cleanup $testdir NULL
+		set flag [lindex $item 0]
+		set flagval [lindex $item 1]
+		set method [lindex $item 2]
+		if { $method == "" } {
+			set method " -btree "
+		}
+		set getter [lindex $item 3]
+
+		# Check that open is successful with the flag.
+		# The option -cachesize requires grouping for $flagval.
+		if { $flag == "-cachesize" } {
+			set db [eval $o $method $flag {$flagval}\
+			    $testdir/a.db]
+		} else {
+			set db [eval $o $method $flag $flagval\
+			    $testdir/a.db]
+		}
+		error_check_good dbopen:0 [is_valid_db $db] TRUE
+
+		# Check that getter retrieves the correct value.
+		# Cachesizes under 500MB are adjusted upward to
+		# about 25% so just make sure we're in the right
+		# ballpark, between 1.2 and 1.3 of the original value.
+		if { $flag == "-cachesize" } {
+			set retval [eval $db $getter]
+			set retbytes [lindex $retval 1]
+			set setbytes [lindex $flagval 1]
+			error_check_good cachesize_low\
+			    [expr $retbytes > [expr $setbytes * 6 / 5]] 1
+			error_check_good cachesize_high\
+			    [expr $retbytes < [expr $setbytes * 13 / 10]] 1
+		} else {
+			error_check_good get_flagval \
+			    [eval $db $getter] $flagval
+		}
+		error_check_good dbclose:0 [$db close] 0
+	}
+
+	puts "\tEnv007.i: Test berkdb_open -rdonly."
+	# This test is done separately because -rdonly can only be specified
+	# on an already existing database.
+	set flag "-rdonly"
+	set db [eval berkdb_open $flag $testdir/a.db]
+	error_check_good open_rdonly [is_valid_db $db] TRUE
+
+	error_check_good get_rdonly [eval $db get_open_flags] $flag
+	error_check_good dbclose:0 [$db close] 0
+
+	puts "\tEnv007.j: Test berkdb open flags and getters\
+	    requiring environments."
+	# Check options that we configure with berkdb open and
+	# query via getters.  Structure of the list is:
+	# 	0.  Flag used in berkdb open command
+	#	1.  Value specified to flag
+	#	2.  Specific method, if needed
+	# 	3.  Arg used in getter
+	# 	4.  Additional flags needed in setting up env
+
+	set elist {
+	{ "" "-auto_commit" "" "get_open_flags" "" }
+	}
+
+	if { $has_crypto == 1 } {
+		lappend elist \
+		    { "" "-encrypt" "" "get_flags" "-encryptaes $passwd" }
+	}
+
+	set e "berkdb_env -create -home $testdir -txn "
+	set o "berkdb_open -create -btree -mode 0644 "
+	foreach item $elist {
+		env_cleanup $testdir
+		set flag [lindex $item 0]
+		set flagval [lindex $item 1]
+		set method [lindex $item 2]
+		if { $method == "" } {
+			set method " -btree "
+		}
+		set getter [lindex $item 3]
+		set envflag [lindex $item 4]
+
+		# Check that open is successful with the flag.
+		set env [eval $e $envflag]
+		set db [eval $o -env $env $flag $flagval a.db]
+		error_check_good dbopen:0 [is_valid_db $db] TRUE
+
+		# Check that getter retrieves the correct value
+		set get_flagval [eval $db $getter]
+		error_check_good get_flagval [is_substr $get_flagval $flagval] 1
+		error_check_good dbclose [$db close] 0
+		error_check_good envclose [$env close] 0
+	}
 }
 
 proc env007_check { env statcmd statstr testval } {
diff --git a/storage/bdb/test/env008.tcl b/storage/bdb/test/env008.tcl
index dccdb41f61227c3a9dfb75f4c7ac8cf6e6d7ead6..c203d55d4dd0d97700577172a5c80909ee50a31b 100644
--- a/storage/bdb/test/env008.tcl
+++ b/storage/bdb/test/env008.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: env008.tcl,v 11.6 2002/02/22 14:29:34 sandstro Exp $
+# $Id: env008.tcl,v 11.8 2004/01/28 03:36:27 bostic Exp $
 #
 # TEST	env008
 # TEST	Test environments and subdirectories.
diff --git a/storage/bdb/test/env009.tcl b/storage/bdb/test/env009.tcl
index 264d5e2dfeca2e4ba8a2b437b6744a16ba886ba2..e6fd3a563737d2884219d88d334b8b00b4ad062b 100644
--- a/storage/bdb/test/env009.tcl
+++ b/storage/bdb/test/env009.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: env009.tcl,v 11.5 2002/08/12 20:40:36 sandstro Exp $
+# $Id: env009.tcl,v 11.9 2004/09/23 21:45:21 mjc Exp $
 #
 # TEST	env009
 # TEST	Test calls to all the various stat functions.  We have several
@@ -12,7 +12,7 @@
 proc env009 { } {
 	source ./include.tcl
 
-	puts "Env009: Various stat function test."
+	puts "Env009: Various stat functions test."
 
 	env_cleanup $testdir
 	puts "\tEnv009.a: Setting up env and a database."
@@ -23,35 +23,60 @@ proc env009 { } {
 	error_check_good dbopen [is_valid_db $dbbt] TRUE
 	set dbh [berkdb_open -create -hash $testdir/env009h.db]
 	error_check_good dbopen [is_valid_db $dbh] TRUE
-	set dbq [berkdb_open -create -btree $testdir/env009q.db]
+	set dbq [berkdb_open -create -queue $testdir/env009q.db]
 	error_check_good dbopen [is_valid_db $dbq] TRUE
 
+	puts "\tEnv009.b: Setting up replication master and client envs."
+	replsetup $testdir/MSGQUEUEDIR
+	set masterdir $testdir/MASTERDIR
+	set clientdir $testdir/CLIENTDIR
+	file mkdir $masterdir
+	file mkdir $clientdir
+
+	repladd 1
+	set repenv(M) [berkdb_env -create -home $masterdir \
+	    -txn -rep_master -rep_transport [list 1 replsend]]
+	repladd 2
+	set repenv(C) [berkdb_env -create -home $clientdir \
+	    -txn -rep_client -rep_transport [list 2 replsend]]
+
 	set rlist {
-	{ "lock_stat" "Maximum locks" "Env009.b"}
-	{ "log_stat" "Magic" "Env009.c"}
-	{ "mpool_stat" "Number of caches" "Env009.d"}
-	{ "txn_stat" "Max Txns" "Env009.e"}
+	{ "lock_stat" "Maximum locks" "Env009.c" $e }
+	{ "log_stat" "Magic" "Env009.d" "$e" }
+	{ "mpool_stat" "Number of caches" "Env009.e" "$e"}
+	{ "txn_stat" "Max Txns" "Env009.f" "$e" }
+	{ "rep_stat" "{Environment ID} 1" "Env009.g (Master)" "$repenv(M)"}
+	{ "rep_stat" "{Environment ID} 2" "Env009.h (Client)" "$repenv(C)"}
 	}
 
-	foreach pair $rlist {
-		set cmd [lindex $pair 0]
-		set str [lindex $pair 1]
-		set msg [lindex $pair 2]
+	foreach set $rlist {
+		set cmd [lindex $set 0]
+		set str [lindex $set 1]
+		set msg [lindex $set 2]
+		set env [lindex $set 3]
 		puts "\t$msg: $cmd"
-		set ret [$e $cmd]
+		set ret [eval $env $cmd]
 		error_check_good $cmd [is_substr $ret $str] 1
 	}
-	puts "\tEnv009.f: btree stats"
+
+	puts "\tEnv009.i: btree stats"
 	set ret [$dbbt stat]
-	error_check_good $cmd [is_substr $ret "Magic"] 1
-	puts "\tEnv009.g: hash stats"
+	error_check_good $cmd [is_substr $ret "Leaf pages"] 1
+
+	puts "\tEnv009.j: hash stats"
 	set ret [$dbh stat]
-	error_check_good $cmd [is_substr $ret "Magic"] 1
-	puts "\tEnv009.f: queue stats"
+	error_check_good $cmd [is_substr $ret "Buckets"] 1
+
+	puts "\tEnv009.k: queue stats"
 	set ret [$dbq stat]
-	error_check_good $cmd [is_substr $ret "Magic"] 1
+	error_check_good $cmd [is_substr $ret "Extent size"] 1
+
+	# Clean up.
 	error_check_good dbclose [$dbbt close] 0
 	error_check_good dbclose [$dbh close] 0
 	error_check_good dbclose [$dbq close] 0
+	error_check_good masterenvclose [$repenv(M) close] 0
+	error_check_good clientenvclose [$repenv(C) close] 0
+	replclose $testdir/MSGQUEUEDIR
 	error_check_good envclose [$e close] 0
 }
diff --git a/storage/bdb/test/env010.tcl b/storage/bdb/test/env010.tcl
index 4444e34e43980696ad82c99318c7adfcfe6abe6a..403f0cd9dd63408054c5d25c846458dcd845dca2 100644
--- a/storage/bdb/test/env010.tcl
+++ b/storage/bdb/test/env010.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #       Sleepycat Software.  All rights reserved.
 #
-# $Id: env010.tcl,v 1.4 2002/02/20 17:08:21 sandstro Exp $
+# $Id: env010.tcl,v 1.7 2004/01/28 03:36:27 bostic Exp $
 #
 # TEST	env010
 # TEST	Run recovery in an empty directory, and then make sure we can still
@@ -28,7 +28,8 @@ proc env010 { } {
 
 		puts "\tEnv010: Creating env for $rmethod test."
 		env_cleanup $testdir/EMPTYDIR
-		set e [berkdb_env -create -home $testdir/EMPTYDIR -$rmethod]
+		set e [berkdb_env \
+		    -create -home $testdir/EMPTYDIR -txn -$rmethod]
 		error_check_good dbenv [is_valid_env $e] TRUE
 
 		# Open and close a database
diff --git a/storage/bdb/test/env011.tcl b/storage/bdb/test/env011.tcl
index 4061bb3fe512d1acd0ab7b63db0b1c157d402ec3..de6c82b367059bf1189df9365bd6c64c530aa32e 100644
--- a/storage/bdb/test/env011.tcl
+++ b/storage/bdb/test/env011.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #       Sleepycat Software.  All rights reserved.
 #
-# $Id: env011.tcl,v 1.2 2002/02/20 17:08:21 sandstro Exp $
+# $Id: env011.tcl,v 1.4 2004/01/28 03:36:27 bostic Exp $
 #
 # TEST	env011
 # TEST	Run with region overwrite flag.
diff --git a/storage/bdb/test/hsearch.tcl b/storage/bdb/test/hsearch.tcl
index afeed93f74efcdb38bc3b06cee222713a560b839..f2d223264d4a368dfaa36f4091387c73946d8a2d 100644
--- a/storage/bdb/test/hsearch.tcl
+++ b/storage/bdb/test/hsearch.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: hsearch.tcl,v 11.9 2002/01/11 15:53:24 bostic Exp $
+# $Id: hsearch.tcl,v 11.11 2004/01/28 03:36:28 bostic Exp $
 #
 # Historic Hsearch interface test.
 # Use the first 1000 entries from the dictionary.
diff --git a/storage/bdb/test/join.tcl b/storage/bdb/test/join.tcl
index 87b0d1fae581213c4e9ddfea7bca86bb3c30d770..eba811dfdc7c0c03ae16c2b50e77bb0f8d2615f3 100644
--- a/storage/bdb/test/join.tcl
+++ b/storage/bdb/test/join.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: join.tcl,v 11.21 2002/02/20 17:08:22 sandstro Exp $
+# $Id: join.tcl,v 11.23 2004/01/28 03:36:28 bostic Exp $
 #
 # TEST	jointest
 # TEST	Test duplicate assisted joins.  Executes 1, 2, 3 and 4-way joins
diff --git a/storage/bdb/test/lock001.tcl b/storage/bdb/test/lock001.tcl
index 1afcc471fc1eb2ce62c60ce413defe586d8db9aa..48eb95515cb84eb4ca7f80c9627a769af92be7d7 100644
--- a/storage/bdb/test/lock001.tcl
+++ b/storage/bdb/test/lock001.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: lock001.tcl,v 11.19 2002/04/25 19:30:28 sue Exp $
+# $Id: lock001.tcl,v 11.21 2004/01/28 03:36:28 bostic Exp $
 #
 
 # TEST	lock001
diff --git a/storage/bdb/test/lock002.tcl b/storage/bdb/test/lock002.tcl
index a1ad8760c9d2cf39e3b5d10eface4a4aa4d96c24..1fdea56cdb4e14f883e680b9acf662efba0d7ca6 100644
--- a/storage/bdb/test/lock002.tcl
+++ b/storage/bdb/test/lock002.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: lock002.tcl,v 11.19 2002/04/25 19:30:29 sue Exp $
+# $Id: lock002.tcl,v 11.21 2004/01/28 03:36:28 bostic Exp $
 #
 # TEST	lock002
 # TEST	Exercise basic multi-process aspects of lock.
diff --git a/storage/bdb/test/lock003.tcl b/storage/bdb/test/lock003.tcl
index 91a8a2e90f625c33c6fb0c23f6b303880ef762a6..a535142838c3991fc46a6df0ea727b9078d84c40 100644
--- a/storage/bdb/test/lock003.tcl
+++ b/storage/bdb/test/lock003.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: lock003.tcl,v 11.25 2002/09/05 17:23:06 sandstro Exp $
+# $Id: lock003.tcl,v 11.28 2004/01/28 03:36:28 bostic Exp $
 #
 # TEST	lock003
 # TEST	Exercise multi-process aspects of lock.  Generate a bunch of parallel
@@ -55,8 +55,10 @@ proc lock003 { {iter 500} {max 1000} {procs 5} } {
 	watch_procs $pidlist 30 10800
 
 	# Check for test failure
-	set e [eval findfail [glob $testdir/lock003.*.out]]
-	error_check_good "FAIL: error message(s) in log files" $e 0
+	set errstrings [eval findfail [glob $testdir/lock003.*.out]]
+	foreach str $errstrings {
+		puts "FAIL: error message in .out file: $str"
+	}
 
 	# Remove log files
 	for { set i 0 } {$i < $procs} {incr i} {
diff --git a/storage/bdb/test/lock004.tcl b/storage/bdb/test/lock004.tcl
index 7fd51ee42f20482410afd48f17a2cf25715a4310..e71a51f9ba79d5b76d2db15acf27b66aed1cbed0 100644
--- a/storage/bdb/test/lock004.tcl
+++ b/storage/bdb/test/lock004.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: lock004.tcl,v 11.5 2002/04/25 19:30:30 sue Exp $
+# $Id: lock004.tcl,v 11.7 2004/01/28 03:36:28 bostic Exp $
 #
 # TEST	lock004
 # TEST	Test locker ids wraping around.
diff --git a/storage/bdb/test/lock005.tcl b/storage/bdb/test/lock005.tcl
index 5afe7344d36fd259487ff485f1a01111a241c83f..8b3b977ad31763b327bd8b0c56d3dfcde2366be7 100644
--- a/storage/bdb/test/lock005.tcl
+++ b/storage/bdb/test/lock005.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2001
+# Copyright (c) 1996-2004
 # Sleepycat Software. All rights reserved.
 #
-# $Id: lock005.tcl,v 1.7 2002/08/08 15:38:07 bostic Exp $
+# $Id: lock005.tcl,v 1.10 2004/01/28 03:36:28 bostic Exp $
 #
 # TEST lock005
 # TEST Check that page locks are being released properly.
@@ -41,7 +41,7 @@ proc lock005 { } {
 	# ... and try to get a record from the first txn (should fail)
 	set ret [catch {$db get -txn $txn2 $recno1} res]
 	error_check_good dbget_wrong_record \
-	    [is_substr $res "Lock not granted"] 1
+	    [is_substr $res "deadlock"] 1
 
 	# End transactions
 	error_check_good txn1commit [$txn1 commit] 0
diff --git a/storage/bdb/test/lockscript.tcl b/storage/bdb/test/lockscript.tcl
index 812339a4a70d8fba4cf5c3abbba0a2f6d5b070ad..f542c100b1f59b09e8ce72c066ef32f0569bac9f 100644
--- a/storage/bdb/test/lockscript.tcl
+++ b/storage/bdb/test/lockscript.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: lockscript.tcl,v 11.17 2002/02/20 17:08:23 sandstro Exp $
+# $Id: lockscript.tcl,v 11.19 2004/01/28 03:36:28 bostic Exp $
 #
 # Random lock tester.
 # Usage: lockscript dir numiters numobjs sleepint degree readratio
diff --git a/storage/bdb/test/log001.tcl b/storage/bdb/test/log001.tcl
index 87df780cb5a559d0b84551b3c9bc6a2f35004fb4..cec09b84fd60d82d38a103f3666fb305385b705f 100644
--- a/storage/bdb/test/log001.tcl
+++ b/storage/bdb/test/log001.tcl
@@ -1,44 +1,68 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: log001.tcl,v 11.29 2002/04/30 20:27:56 sue Exp $
+# $Id: log001.tcl,v 11.34 2004/09/22 18:01:05 bostic Exp $
 #
 
 # TEST	log001
 # TEST	Read/write log records.
+# TEST	Test with and without fixed-length, in-memory logging,
+# TEST	and encryption.
 proc log001 { } {
 	global passwd
+	global has_crypto
 	global rand_init
 
 	berkdb srand $rand_init
 	set iter 1000
+
 	set max [expr 1024 * 128]
-	log001_body $max $iter 1
-	log001_body $max $iter 0
-	log001_body $max $iter 1 "-encryptaes $passwd"
-	log001_body $max $iter 0 "-encryptaes $passwd"
-	log001_body $max [expr $iter * 15] 1
-	log001_body $max [expr $iter * 15] 0
-	log001_body $max [expr $iter * 15] 1 "-encryptaes $passwd"
-	log001_body $max [expr $iter * 15] 0 "-encryptaes $passwd"
+	foreach fixedlength { 0 1 } {
+		foreach inmem { 1 0 } {
+			log001_body $max $iter $fixedlength $inmem
+			log001_body $max [expr $iter * 15] $fixedlength $inmem
+
+			# Skip encrypted tests if not supported.
+			if { $has_crypto == 0 } {
+				continue
+			}
+			log001_body $max\
+			    $iter $fixedlength $inmem "-encryptaes $passwd"
+			log001_body $max\
+			    [expr $iter * 15] $fixedlength $inmem "-encryptaes $passwd"
+		}
+	}
 }
 
-proc log001_body { max nrecs fixedlength {encargs ""} } {
+proc log001_body { max nrecs fixedlength inmem {encargs ""} } {
 	source ./include.tcl
 
-	puts -nonewline "Log001: Basic put/get log records "
+	puts -nonewline "Log001: Basic put/get log records: "
 	if { $fixedlength == 1 } {
-		puts "(fixed-length $encargs)"
+		puts -nonewline "fixed-length ($encargs)"
 	} else {
-		puts "(variable-length $encargs)"
+		puts -nonewline "variable-length ($encargs)"
+	}
+
+	# In-memory logging requires a large enough log buffer that
+	# any active transaction can be aborted.
+	if { $inmem == 1 } {
+		set lbuf [expr 8 * [expr 1024 * 1024]]
+		puts " with in-memory logging."
+	} else {
+		puts " with on-disk logging."
 	}
 
 	env_cleanup $testdir
 
+	set logargs ""
+	if { $inmem == 1 } {
+		set logargs "-log_inmemory -log_buffer $lbuf"
+	}
 	set env [eval {berkdb_env -log -create -home $testdir -mode 0644} \
-	    $encargs -log_max $max]
+	    $encargs $logargs -log_max $max]
 	error_check_good envopen [is_valid_env $env] TRUE
 
 	# We will write records to the log and make sure we can
diff --git a/storage/bdb/test/log002.tcl b/storage/bdb/test/log002.tcl
index 6e91f55398f5cba69cfd964840b6152852bf8e39..1c8f2b9197919ea839e2dd30c12d539679312566 100644
--- a/storage/bdb/test/log002.tcl
+++ b/storage/bdb/test/log002.tcl
@@ -1,16 +1,24 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: log002.tcl,v 11.28 2002/04/29 20:07:54 sue Exp $
+# $Id: log002.tcl,v 11.33 2004/09/22 18:01:05 bostic Exp $
 #
-
 # TEST	log002
 # TEST	Tests multiple logs
 # TEST		Log truncation
 # TEST		LSN comparison and file functionality.
 proc log002 { } {
+	global rand_init
+	error_check_good set_random_seed [berkdb srand $rand_init] 0
+
+	foreach inmem { 1 0 } {
+		log002_body $inmem
+	}
+}
+
+proc log002_body { inmem } {
 	source ./include.tcl
 
 	puts "Log002: Multiple log test w/trunc, file, compare functionality"
@@ -18,11 +26,20 @@ proc log002 { } {
 	env_cleanup $testdir
 
 	set max [expr 1024 * 128]
-	set env [berkdb_env -create -home $testdir -mode 0644 \
-	    -log -log_max $max]
+
+	set logargs ""
+	if { $inmem == 0 } {
+		puts "Log002: Using on-disk logging."
+	} else {
+		puts "Log002: Using in-memory logging."
+		set lbuf [expr 8 * [expr 1024 * 1024]]
+		set logargs "-log_inmemory -log_buffer $lbuf"
+	}
+	set env [eval {berkdb_env} -create -home $testdir -log \
+	    -mode 0644 $logargs -log_max $max]
 	error_check_good envopen [is_valid_env $env] TRUE
 
-	# We'll record every hundred'th record for later use
+	# We'll record every hundredth record for later use
 	set info_list {}
 
 	puts "\tLog002.a: Writing log records"
@@ -54,17 +71,17 @@ proc log002 { } {
 	}
 
 	puts "\tLog002.c: Checking log_file"
-	set flist [glob $testdir/log*]
-	foreach p $info_list {
-
-		set lsn [lindex $p 0]
-		set f [$env log_file $lsn]
-
-		# Change all backslash separators on Windows to forward slash
-		# separators, which is what the rest of the test suite expects.
-		regsub -all {\\} $f {/} f
-
-		error_check_bad log_file:$f [lsearch $flist $f] -1
+	if { $inmem == 0 } {
+		set flist [glob $testdir/log*]
+		foreach p $info_list {
+			set lsn [lindex $p 0]
+			set f [$env log_file $lsn]
+
+			# Change backslash separators on Windows to forward
+			# slashes, as the rest of the test suite expects.
+			regsub -all {\\} $f {/} f
+			error_check_bad log_file:$f [lsearch $flist $f] -1
+		}
 	}
 
 	puts "\tLog002.d: Verifying records"
diff --git a/storage/bdb/test/log003.tcl b/storage/bdb/test/log003.tcl
index 11297b59d50a93eb71a9237b8ba90be1f7a37d6a..e8d10dbfc9bce829738b4f7a8ebf21e53bf02c99 100644
--- a/storage/bdb/test/log003.tcl
+++ b/storage/bdb/test/log003.tcl
@@ -1,17 +1,33 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: log003.tcl,v 11.28 2002/04/29 20:07:54 sue Exp $
+# $Id: log003.tcl,v 11.34 2004/09/22 18:01:05 bostic Exp $
 #
-
 # TEST	log003
 # TEST	Verify that log_flush is flushing records correctly.
 proc log003 { } {
+	global rand_init
+	error_check_good set_random_seed [berkdb srand $rand_init] 0
+
+	# Even though log_flush doesn't do anything for in-memory
+	# logging, we want to make sure calling it doesn't break
+	# anything.
+	foreach inmem { 1 0 } {
+		log003_body $inmem
+	}
+}
+
+proc log003_body { inmem } {
 	source ./include.tcl
 
-	puts "Log003: Verify log_flush behavior"
+	puts -nonewline "Log003: Verify log_flush behavior"
+	if { $inmem == 0 } {
+		puts " (on-disk logging)."
+	} else {
+		puts " (in-memory logging)."
+	}
 
 	set max [expr 1024 * 128]
 	env_cleanup $testdir
@@ -22,8 +38,12 @@ proc log003 { } {
 	foreach rec "$short_rec $long_rec $very_long_rec" {
 		puts "\tLog003.a: Verify flush on [string length $rec] byte rec"
 
-		set env [berkdb_env -log -home $testdir \
-				-create -mode 0644 -log_max $max]
+		set logargs ""
+		if { $inmem == 1 } {
+			set logargs "-log_inmemory -log_buffer [expr $max * 2]"
+		}
+		set env [eval {berkdb_env} -log -home $testdir -create \
+		    -mode 0644 $logargs -log_max $max]
 		error_check_good envopen [is_valid_env $env] TRUE
 
 		set lsn [$env log_put $rec]
@@ -59,11 +79,18 @@ proc log003 { } {
 		log_cleanup $testdir
 	}
 
+	if { $inmem == 1 } {
+		puts "Log003: Skipping remainder of test for in-memory logging."
+		return
+	}
+
 	foreach rec "$short_rec $long_rec $very_long_rec" {
 		puts "\tLog003.b: \
 		    Verify flush on non-last record [string length $rec]"
-		set env [berkdb_env \
-		    -create -log -home $testdir -mode 0644 -log_max $max]
+
+		set env [berkdb_env -log -home $testdir \
+		    -create -mode 0644 -log_max $max]
+
 		error_check_good envopen [is_valid_env $env] TRUE
 
 		# Put 10 random records
@@ -90,8 +117,7 @@ proc log003 { } {
 
 		# Now, we want to crash the region and recheck.  Closing the
 		# log does not flush any records, so we'll use a close to
-		# do the "crash"
-
+		# do the "crash".
 		#
 		# Now, close and remove the log region
 		error_check_good env:close:$env [$env close] 0
@@ -99,8 +125,8 @@ proc log003 { } {
 		error_check_good env:remove $ret 0
 
 		# Re-open the log and try to read the record.
-		set env [berkdb_env \
-		    -home $testdir -create -log -mode 0644 -log_max $max]
+		set env [berkdb_env -log -home $testdir \
+		    -create -mode 0644 -log_max $max]
 		error_check_good envopen [is_valid_env $env] TRUE
 
 		set logc [$env log_cursor]
diff --git a/storage/bdb/test/log004.tcl b/storage/bdb/test/log004.tcl
index 66968a8c1b41e0630e4caca27aa52cf5e55115d5..15af405f5cede00737a6ec09a35472cd1745c393 100644
--- a/storage/bdb/test/log004.tcl
+++ b/storage/bdb/test/log004.tcl
@@ -1,22 +1,28 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: log004.tcl,v 11.28 2002/04/29 20:07:54 sue Exp $
+# $Id: log004.tcl,v 11.31 2004/07/19 16:08:36 carol Exp $
 #
 
 # TEST	log004
 # TEST	Make sure that if we do PREVs on a log, but the beginning of the
 # TEST	log has been truncated, we do the right thing.
 proc log004 { } {
+	foreach inmem { 1 0 } {
+		log004_body $inmem
+	}
+}
+
+proc log004_body { inmem } {
 	source ./include.tcl
 
 	puts "Log004: Prev on log when beginning of log has been truncated."
 	# Use archive test to populate log
 	env_cleanup $testdir
 	puts "\tLog004.a: Call archive to populate log."
-	archive
+	archive $inmem
 
 	# Delete all log files under 100
 	puts "\tLog004.b: Delete all log files under 100."
diff --git a/storage/bdb/test/log005.tcl b/storage/bdb/test/log005.tcl
index ab2ad703c55dded25589c878df8eacf812626196..ea6e3fa33045ae2fcd9c72ed83f719914da11504 100644
--- a/storage/bdb/test/log005.tcl
+++ b/storage/bdb/test/log005.tcl
@@ -1,22 +1,46 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: log005.tcl,v 11.1 2002/05/30 22:16:49 bostic Exp $
+# $Id: log005.tcl,v 11.6 2004/09/22 18:01:05 bostic Exp $
 #
 # TEST	log005
 # TEST	Check that log file sizes can change on the fly.
 proc log005 { } {
-	source ./include.tcl
 
-	puts "Log005: Check that log file sizes can change."
+	# Skip the test for HP-UX, where we can't do the second
+	# env open.
+	global is_hp_test
+	if { $is_hp_test == 1 } {
+		puts "Log005: Skipping for HP-UX."
+		return
+	}
+
+	foreach inmem { 1 0 } {
+		log005_body $inmem
+	}
+}
+proc log005_body { inmem } {
+	source ./include.tcl
 	env_cleanup $testdir
 
+	puts -nonewline "Log005: Check that log file sizes can change"
+	if { $inmem == 0 } {
+		puts " (on-disk logging)."
+	} else {
+		puts " (in-memory logging)."
+	}
+
 	# Open the environment, set and check the log file size.
 	puts "\tLog005.a: open, set and check the log file size."
-	set env [berkdb_env \
-	    -create -home $testdir -log_buffer 10000 -log_max 1000000 -txn]
+	set logargs ""
+	if { $inmem == 1 } {
+		set lbuf [expr 1024 * 1024]
+		set logargs "-log_inmemory -log_buffer $lbuf"
+	}
+	set env [eval {berkdb_env} -create -home $testdir \
+	    $logargs -log_max 1000000 -txn]
 	error_check_good envopen [is_valid_env $env] TRUE
 	set db [berkdb_open \
 	    -env $env -create -mode 0644 -btree -auto_commit a.db]
@@ -61,6 +85,11 @@ proc log005 { } {
 	error_check_good db_close [$db close] 0
 	error_check_good env_close [$env close] 0
 
+	if { $inmem == 1 } {
+		puts "Log005: Skipping remainder of test for in-memory logging."
+		return
+	}
+
 	puts "\tLog005.d: check the log file size is unchanged after recovery."
 	# Open again, running recovery.  Verify the log file size is as we
 	# left it.
diff --git a/storage/bdb/test/logtrack.tcl b/storage/bdb/test/logtrack.tcl
index ad6b480b4e3252773820b46dbf1f3b5dc711e60b..50851932fc483579ef82c3a73a4d2b74f0f868ac 100644
--- a/storage/bdb/test/logtrack.tcl
+++ b/storage/bdb/test/logtrack.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information
 #
-# Copyright (c) 2000-2002
+# Copyright (c) 2000-2004
 #       Sleepycat Software.  All rights reserved.
 #
-# $Id: logtrack.tcl,v 11.11 2002/09/03 16:44:37 sue Exp $
+# $Id: logtrack.tcl,v 11.15 2004/04/14 16:08:42 carol Exp $
 #
 # logtrack.tcl:  A collection of routines, formerly implemented in Perl
 # as log.pl, to track which log record types the test suite hits.
@@ -66,6 +66,7 @@ proc logtrack_read { dirname } {
 # seen and the log record types that were not seen but should have been seen.
 proc logtrack_summary { } {
 	global ltsname ltlist testdir
+	global one_test
 
 	set seendb [berkdb_open $ltsname]
 	error_check_good seendb_open [is_valid_db $seendb] TRUE
@@ -109,8 +110,8 @@ proc logtrack_summary { } {
 	    [is_valid_cursor [set ec [$existdb cursor]] $existdb] TRUE
 	while { [llength [set dbt [$ec get -next]]] != 0 } {
 		set rec [lindex [lindex $dbt 0] 0]
-		if { [$seendb count $rec] == 0 } {
-			puts "FAIL: log record type $rec not seen"
+		if { [$seendb count $rec] == 0 && $one_test == "ALL" } {
+			puts "WARNING: log record type $rec: not tested"
 		}
 	}
 	error_check_good exist_curs_close [$ec close] 0
@@ -121,9 +122,10 @@ proc logtrack_summary { } {
 		set rec [lindex [lindex $dbt 0] 0]
 		if { [$existdb count $rec] == 0 } {
 			if { [$deprecdb count $rec] == 0 } {
-			       puts "FAIL: unknown log record type $rec seen"
+			       puts "WARNING: log record type $rec: unknown"
 			} else {
-			       puts "FAIL: deprecated log record type $rec seen"
+			       puts \
+			   "WARNING: log record type $rec: deprecated"
 			}
 		}
 	}
diff --git a/storage/bdb/test/mdbscript.tcl b/storage/bdb/test/mdbscript.tcl
index 9f3c971ee3c1da80c4b1782bb8029bb82a61c616..88433485a942f4a6275e30884ad2d8e3c135f1b1 100644
--- a/storage/bdb/test/mdbscript.tcl
+++ b/storage/bdb/test/mdbscript.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: mdbscript.tcl,v 11.29 2002/03/22 21:43:06 krinsky Exp $
+# $Id: mdbscript.tcl,v 11.33 2004/01/28 03:36:28 bostic Exp $
 #
 # Process script for the multi-process db tester.
 
@@ -96,7 +96,6 @@ error_check_good dbopen [is_valid_db $db] TRUE
 # Init globals (no data)
 set nkeys [db_init $db 0]
 puts "Initial number of keys: $nkeys"
-error_check_good db_init $nkeys $nentries
 tclsleep 5
 
 proc get_lock { k } {
@@ -124,6 +123,23 @@ proc get_lock { k } {
 	return 0
 }
 
+# If we are renumbering, then each time we delete an item, the number of
+# items in the file is temporarily decreased, so the highest record numbers
+# do not exist.  To make sure this doesn't happen, we never generate the
+# highest few record numbers as keys.
+#
+# For record-based methods, record numbers begin at 1, while for other keys,
+# we begin at 0 to index into an array.
+proc rand_key { method nkeys renum procs} {
+	if { $renum == 1 } {
+		return [berkdb random_int 1 [expr $nkeys - $procs]]
+	} elseif { [is_record_based $method] == 1 } {
+		return [berkdb random_int 1 $nkeys]
+	} else {
+		return [berkdb random_int 0 [expr $nkeys - 1]]
+	}
+}
+
 # On each iteration we're going to randomly pick a key.
 # 1. We'll either get it (verifying that its contents are reasonable).
 # 2. Put it (using an overwrite to make the data be datastr:ID).
diff --git a/storage/bdb/test/memp001.tcl b/storage/bdb/test/memp001.tcl
index c4bbf99b9b2813c598f65e6f1337f9f550dc0cef..4818072debd200891a4200bd4a67c3de455e25e6 100644
--- a/storage/bdb/test/memp001.tcl
+++ b/storage/bdb/test/memp001.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: memp001.tcl,v 11.50 2002/08/07 16:46:28 bostic Exp $
+# $Id: memp001.tcl,v 11.53 2004/01/28 03:36:28 bostic Exp $
 #
 
 # TEST	memp001
@@ -174,7 +174,7 @@ proc mem_chk { flags } {
 	env_cleanup $testdir
 
 	set cachearg " -cachesize {0 400000 3}"
-	set ret [catch {eval {berkdb_env -create -mode 0644}\
+	set ret [catch {eval {berkdb_env_noerr -create -mode 0644}\
 	    $cachearg {-region_init -home $testdir} $flags} env]
 	if { $ret != 0 } {
 		# If the env open failed, it may be because we're on a platform
diff --git a/storage/bdb/test/memp002.tcl b/storage/bdb/test/memp002.tcl
index d55f2987f06930a9e29a39580d5745e2cd98a05d..763ef923d352d07df575e6a8d7cd2eae45677418 100644
--- a/storage/bdb/test/memp002.tcl
+++ b/storage/bdb/test/memp002.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: memp002.tcl,v 11.47 2002/09/05 17:23:06 sandstro Exp $
+# $Id: memp002.tcl,v 11.49 2004/01/28 03:36:28 bostic Exp $
 #
 
 # TEST	memp002
diff --git a/storage/bdb/test/memp003.tcl b/storage/bdb/test/memp003.tcl
index 31eb55b757c35e6e7fe0c4906e939cc6fba06c95..a4e68bfd58dd30ee0aeddba9e5df842be4d72f8a 100644
--- a/storage/bdb/test/memp003.tcl
+++ b/storage/bdb/test/memp003.tcl
@@ -1,15 +1,16 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: memp003.tcl,v 11.46 2002/04/30 17:26:06 sue Exp $
+# $Id: memp003.tcl,v 11.51 2004/01/28 03:36:28 bostic Exp $
 #
-
 # TEST	memp003
 # TEST	Test reader-only/writer process combinations; we use the access methods
 # TEST	for testing.
 proc memp003 { } {
+	global rand_init
+	error_check_good set_random_seed [berkdb srand $rand_init] 0
 	#
 	# Multiple processes not supported by private memory so don't
 	# run memp003_body with -private.
@@ -42,7 +43,7 @@ proc memp003_body { flags } {
 	error_check_good dbenv [is_valid_env $dbenv] TRUE
 
 	# First open and create the file.
-	set db [berkdb_open -env $dbenv -create -truncate \
+	set db [berkdb_open -env $dbenv -create \
 	    -mode 0644 -pagesize $psize -btree $testfile]
 	error_check_good dbopen/RW [is_valid_db $db] TRUE
 
diff --git a/storage/bdb/test/mpoolscript.tcl b/storage/bdb/test/mpoolscript.tcl
index c13f70eb9458fb19e6b9813adc982a6d4592cc52..38d689c9666a3541202fad580706eede26301ce7 100644
--- a/storage/bdb/test/mpoolscript.tcl
+++ b/storage/bdb/test/mpoolscript.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: mpoolscript.tcl,v 11.16 2002/04/29 14:47:16 sandstro Exp $
+# $Id: mpoolscript.tcl,v 11.18 2004/01/28 03:36:28 bostic Exp $
 #
 # Random multiple process mpool tester.
 # Usage: mpoolscript dir id numiters numfiles numpages sleepint
diff --git a/storage/bdb/test/mutex001.tcl b/storage/bdb/test/mutex001.tcl
index 93f858993a562f912191da98fb69a83fb0da1a96..66d14c41c956085a9ebc2889bdf3238f752021ea 100644
--- a/storage/bdb/test/mutex001.tcl
+++ b/storage/bdb/test/mutex001.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: mutex001.tcl,v 11.23 2002/04/30 19:37:36 sue Exp $
+# $Id: mutex001.tcl,v 11.25 2004/01/28 03:36:28 bostic Exp $
 #
 
 # TEST	mutex001
diff --git a/storage/bdb/test/mutex002.tcl b/storage/bdb/test/mutex002.tcl
index 193e600fe8b42a38edcad543f531fad1c20f1efe..f03a63ac13989cea2aace17925e0486babe9ec46 100644
--- a/storage/bdb/test/mutex002.tcl
+++ b/storage/bdb/test/mutex002.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: mutex002.tcl,v 11.23 2002/04/30 19:37:36 sue Exp $
+# $Id: mutex002.tcl,v 11.25 2004/01/28 03:36:28 bostic Exp $
 #
 
 # TEST	mutex002
diff --git a/storage/bdb/test/mutex003.tcl b/storage/bdb/test/mutex003.tcl
index da35ac0d1150e350cfdb0af0d68fdcdd5b43897b..7efd0883e0ee35e518c018da47d1b874232c598c 100644
--- a/storage/bdb/test/mutex003.tcl
+++ b/storage/bdb/test/mutex003.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: mutex003.tcl,v 11.24 2002/09/05 17:23:06 sandstro Exp $
+# $Id: mutex003.tcl,v 11.26 2004/01/28 03:36:28 bostic Exp $
 #
 
 # TEST	mutex003
diff --git a/storage/bdb/test/mutexscript.tcl b/storage/bdb/test/mutexscript.tcl
index bc410f2716de59d94fc28556614ac3e5303ff278..7bf1bbe9552c45f7810abdc7f5e92442248898ad 100644
--- a/storage/bdb/test/mutexscript.tcl
+++ b/storage/bdb/test/mutexscript.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: mutexscript.tcl,v 11.16 2002/04/29 14:58:16 sandstro Exp $
+# $Id: mutexscript.tcl,v 11.18 2004/01/28 03:36:28 bostic Exp $
 #
 # Random mutex tester.
 # Usage: mutexscript dir numiters mlocks sleepint degree
diff --git a/storage/bdb/test/ndbm.tcl b/storage/bdb/test/ndbm.tcl
index 0bf8e0cc87c3e4b76356db58cc5629d2fbd3bd80..00ee1f4fdbfcb9ca8cedc9dfc2e1206c4fb39f67 100644
--- a/storage/bdb/test/ndbm.tcl
+++ b/storage/bdb/test/ndbm.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: ndbm.tcl,v 11.16 2002/07/08 13:11:30 mjc Exp $
+# $Id: ndbm.tcl,v 11.18 2004/01/28 03:36:28 bostic Exp $
 #
 # Historic NDBM interface test.
 # Use the first 1000 entries from the dictionary.
diff --git a/storage/bdb/test/parallel.tcl b/storage/bdb/test/parallel.tcl
index 4e101c088cbf9bdc708eb6146ac1f1437342819b..bd1f468fa5d0588ba8280e841f2f82edea27a287 100644
--- a/storage/bdb/test/parallel.tcl
+++ b/storage/bdb/test/parallel.tcl
@@ -1,6 +1,9 @@
 # Code to load up the tests in to the Queue database
-# $Id: parallel.tcl,v 11.28 2002/09/05 17:23:06 sandstro Exp $
+# $Id: parallel.tcl,v 11.46 2004/09/22 18:01:05 bostic Exp $
 proc load_queue { file  {dbdir RUNQUEUE} nitems } {
+	global serial_tests
+	global num_serial
+	global num_parallel
 
 	puts -nonewline "Loading run queue with $nitems items..."
 	flush stdout
@@ -8,9 +11,15 @@ proc load_queue { file  {dbdir RUNQUEUE} nitems } {
 	set env [berkdb_env -create -lock -home $dbdir]
 	error_check_good dbenv [is_valid_env $env] TRUE
 
-	set db [eval {berkdb_open -env $env -create -truncate \
-            -mode 0644 -len 120 -queue queue.db} ]
+	# Open two databases, one for tests that may be run
+	# in parallel, the other for tests we want to run
+	# while only a single process is testing.
+	set db [eval {berkdb_open -env $env -create \
+            -mode 0644 -len 200 -queue queue.db} ]
         error_check_good dbopen [is_valid_db $db] TRUE
+	set serialdb [eval {berkdb_open -env $env -create \
+            -mode 0644 -len 200 -queue serialqueue.db} ]
+        error_check_good dbopen [is_valid_db $serialdb] TRUE
 
 	set fid [open $file]
 
@@ -27,9 +36,26 @@ proc load_queue { file  {dbdir RUNQUEUE} nitems } {
 	puts -nonewline "randomizing..."
 	flush stdout
 	for { set i 0 } { $i < $count } { incr i } {
-		set j [berkdb random_int $i [expr $count - 1]]
-
 		set tmp $testarr($i)
+
+		# RPC test is very long so force it to run first
+		# in full runs.  If we find 'r rpc' as we walk the
+		# array, arrange to put it in slot 0 ...
+		if { [is_substr $tmp "r rpc"] == 1 && \
+		    [string match $nitems ALL] } {
+			set j 0
+		} else {
+			set j [berkdb random_int $i [expr $count - 1]]
+		}
+		# ... and if 'r rpc' is selected to be swapped with the
+		# current item in the array, skip the swap.  If we
+		# did the swap and moved to the next item, "r rpc" would
+		# never get moved to slot 0.
+		if { [is_substr $testarr($j) "r rpc"] && \
+		    [string match $nitems ALL] } {
+			continue
+		}
+
 		set testarr($i) $testarr($j)
 		set testarr($j) $tmp
 	}
@@ -42,15 +68,29 @@ proc load_queue { file  {dbdir RUNQUEUE} nitems } {
 
 	puts "loading..."
 	flush stdout
+	set num_serial 0
+	set num_parallel 0
 	for { set i 0 } { $i < $maxload } { incr i } {
 		set str $testarr($i)
-                set ret [eval {$db put -append $str} ]
-                error_check_good put:$db $ret [expr $i + 1]
+		# Push serial tests into serial testing db, others
+		# into parallel db.
+		if { [is_serial $str] } {
+			set ret [eval {$serialdb put -append $str}]
+			error_check_good put:serialdb [expr $ret > 0] 1
+			incr num_serial
+		} else {
+			set ret [eval {$db put -append $str}]
+			error_check_good put:paralleldb [expr $ret > 0] 1
+			incr num_parallel
+		}
         }
 
-	puts "Loaded $maxload records (out of $count)."
+	error_check_good maxload $maxload [expr $num_serial + $num_parallel]
+	puts "Loaded $maxload records: $num_serial in serial,\
+	    $num_parallel in parallel."
 	close $fid
 	$db close
+	$serialdb close
 	$env close
 }
 
@@ -60,14 +100,27 @@ proc init_runqueue { {dbdir RUNQUEUE} nitems list} {
 		file mkdir $dbdir
 	}
 	puts "Creating test list..."
-	$list -n
+	$list ALL -n
 	load_queue ALL.OUT $dbdir $nitems
 	file delete TEST.LIST
 	file rename ALL.OUT TEST.LIST
-#	file delete ALL.OUT
 }
 
 proc run_parallel { nprocs {list run_all} {nitems ALL} } {
+	global num_serial
+	global num_parallel
+
+	# Forcibly remove stuff from prior runs, if it's still there.
+	fileremove -f ./RUNQUEUE
+	set dirs [glob -nocomplain ./PARALLEL_TESTDIR.*]
+	set files [glob -nocomplain ALL.OUT.*]
+	foreach file $files {
+		fileremove -f $file
+	}
+	foreach dir $dirs {
+		fileremove -f $dir
+	}
+
 	set basename ./PARALLEL_TESTDIR
 	set queuedir ./RUNQUEUE
 	source ./include.tcl
@@ -77,16 +130,19 @@ proc run_parallel { nprocs {list run_all} {nitems ALL} } {
 	init_runqueue $queuedir $nitems $list
 
 	set basedir [pwd]
-	set pidlist {}
 	set queuedir ../../[string range $basedir \
 	    [string last "/" $basedir] end]/$queuedir
 
+	# Run serial tests in parallel testdir 0.
+	run_queue 0 $basename.0 $queuedir serial $num_serial
+
+	set pidlist {}
+	# Run parallel tests in testdirs 1 through n.
 	for { set i 1 } { $i <= $nprocs } { incr i } {
-		fileremove -f ALL.OUT.$i
 		set ret [catch {
 			set p [exec $tclsh_path << \
-			    "source $test_path/test.tcl;\
-			    run_queue $i $basename.$i $queuedir $nitems" &]
+			    "source $test_path/test.tcl; run_queue $i \
+			    $basename.$i $queuedir parallel $num_parallel" &]
 			lappend pidlist $p
 			set f [open $testdir/begin.$p w]
 			close $f
@@ -95,23 +151,30 @@ proc run_parallel { nprocs {list run_all} {nitems ALL} } {
 	watch_procs $pidlist 300 360000
 
 	set failed 0
-	for { set i 1 } { $i <= $nprocs } { incr i } {
-		if { [check_failed_run ALL.OUT.$i] != 0 } {
-			set failed 1
-			puts "Regression tests failed in process $i."
+	for { set i 0 } { $i <= $nprocs } { incr i } {
+		if { [file exists ALL.OUT.$i] == 1 } {
+			puts -nonewline "Checking output from ALL.OUT.$i ... "
+			if { [check_output ALL.OUT.$i] == 1 } {
+				set failed 1
+			}
+			puts " done."
 		}
 	}
 	if { $failed == 0 } {
 		puts "Regression tests succeeded."
+	} else {
+		puts "Regression tests failed."
+		puts "Review UNEXPECTED OUTPUT lines above for errors."
+		puts "Complete logs found in ALL.OUT.x files"
 	}
 }
 
-proc run_queue { i rundir queuedir nitems } {
+proc run_queue { i rundir queuedir {qtype parallel} {nitems 0} } {
 	set builddir [pwd]
 	file delete $builddir/ALL.OUT.$i
 	cd $rundir
 
-	puts "Parallel run_queue process $i (pid [pid]) starting."
+	puts "Starting $qtype run_queue process $i (pid [pid])."
 
 	source ./include.tcl
 	global env
@@ -119,15 +182,24 @@ proc run_queue { i rundir queuedir nitems } {
 	set dbenv [berkdb_env -create -lock -home $queuedir]
 	error_check_good dbenv [is_valid_env $dbenv] TRUE
 
-	set db [eval {berkdb_open -env $dbenv \
-            -mode 0644 -len 120 -queue queue.db} ]
-        error_check_good dbopen [is_valid_db $db] TRUE
+	if { $qtype == "parallel" } {
+		set db [eval {berkdb_open -env $dbenv \
+     	 	    -mode 0644 -queue queue.db} ]
+		error_check_good dbopen [is_valid_db $db] TRUE
+	} elseif { $qtype == "serial" } {
+		set db [eval {berkdb_open -env $dbenv \
+		    -mode 0644 -queue serialqueue.db} ]
+		error_check_good serialdbopen [is_valid_db $db] TRUE
+	} else {
+		puts "FAIL: queue type $qtype not recognized"
+	}
 
-	set dbc  [eval $db cursor]
+	set dbc [eval $db cursor]
         error_check_good cursor [is_valid_cursor $dbc $db] TRUE
 
 	set count 0
 	set waitcnt 0
+	set starttime [timestamp -r]
 
 	while { $waitcnt < 5 } {
 		set line [$db get -consume]
@@ -140,10 +212,22 @@ proc run_queue { i rundir queuedir nitems } {
 			regsub {TESTDIR} $cmd $tdir cmd
 			puts $o $cmd
 			close $o
-			if { [expr {$num % 10} == 0] } {
-				puts "Starting test $num of $nitems"
+			if { [expr {$num % 10} == 0] && $nitems != 0 } {
+				puts -nonewline \
+				    "Starting test $num of $nitems $qtype items.  "
+				set now [timestamp -r]
+				set elapsed [expr $now - $starttime]
+				set esttotal [expr $nitems * $elapsed / $num]
+				set remaining [expr $esttotal - $elapsed]
+				if { $remaining < 3600 } {
+					puts "\tRough guess: less than 1\
+					    hour left."
+				} else {
+					puts "\tRough guess: \
+					[expr $remaining / 3600] hour(s) left."
+				}
 			}
-			#puts "Process $i, record $num:\n$cmd"
+#			puts "Process $i, record $num:\n$cmd"
 			set env(PURIFYOPTIONS) \
 	"-log-file=./test$num.%p -follow-child-processes -messages=first"
 			set env(PURECOVOPTIONS) \
@@ -166,11 +250,14 @@ proc run_queue { i rundir queuedir nitems } {
 		}
 	}
 
-	puts "Process $i: $count commands executed"
+	set now [timestamp -r]
+	set elapsed [expr $now - $starttime]
+	puts "Process $i: $count commands executed in [format %02u:%02u \
+	    [expr $elapsed / 3600] [expr ($elapsed % 3600) / 60]]"
 
-	$dbc close
-	$db close
-	$dbenv close
+	error_check_good close_parallel_cursor_$i [$dbc close] 0
+	error_check_good close_parallel_db_$i [$db close] 0
+	error_check_good close_parallel_env_$i [$dbenv close] 0
 
 	#
 	# We need to put the pid file in the builddir's idea
@@ -183,6 +270,7 @@ proc run_queue { i rundir queuedir nitems } {
 
 	set f [open $builddir/$testdir/end.[pid] w]
 	close $f
+	cd $builddir
 }
 
 proc mkparalleldirs { nprocs basename queuedir } {
@@ -194,7 +282,7 @@ proc mkparalleldirs { nprocs basename queuedir } {
 	} else {
 		set EXE ".exe"
         }
-	for { set i 1 } { $i <= $nprocs } { incr i } {
+	for { set i 0 } { $i <= $nprocs } { incr i } {
 		set destdir $basename.$i
 		catch {file mkdir $destdir}
 		puts "Created $destdir"
@@ -280,7 +368,7 @@ proc exec_ptest { nprocs basename test args } {
 	watch_procs $pidlist 30 36000
 	set failed 0
 	for { set i 1 } { $i <= $nprocs } { incr i } {
-		if { [check_failed_run ALL.OUT.$i] != 0 } {
+		if { [check_output ALL.OUT.$i] == 1 } {
 			set failed 1
 			puts "Test $test failed in process $i."
 		}
diff --git a/storage/bdb/test/recd001.tcl b/storage/bdb/test/recd001.tcl
index bc7ac6d896ad2e2478d8056488866b3cec4cee5c..67ad8004cc2756e85245a029d56ff98d3f54ed78 100644
--- a/storage/bdb/test/recd001.tcl
+++ b/storage/bdb/test/recd001.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: recd001.tcl,v 11.40 2002/05/08 19:36:18 sandstro Exp $
+# $Id: recd001.tcl,v 11.43 2004/01/28 03:36:28 bostic Exp $
 #
 # TEST	recd001
 # TEST	Per-operation recovery tests for non-duplicate, non-split
@@ -111,10 +111,10 @@ proc recd001 { method {select 0} args} {
 	{ {DB del -txn TXNID $key}		"Recd001.g: big data delete"}
 	{ {DB put -txn TXNID $key $data}	"Recd001.h: put (change state)"}
 	{ {DB put -txn TXNID $key $newdata}	"Recd001.i: overwrite"}
-	{ {DB put -txn TXNID -partial {$off $len} $key $partial_grow}
+	{ {DB put -txn TXNID -partial "$off $len" $key $partial_grow}
 	  "Recd001.j: partial put growing"}
 	{ {DB put -txn TXNID $key $newdata}	"Recd001.k: overwrite (fix)"}
-	{ {DB put -txn TXNID -partial {$off $len} $key $partial_shrink}
+	{ {DB put -txn TXNID -partial "$off $len" $key $partial_shrink}
 	  "Recd001.l: partial put shrinking"}
 	{ {DB put -txn TXNID -append $data}	"Recd001.m: put -append"}
 	{ {DB get -txn TXNID -consume}		"Recd001.n: db get -consume"}
@@ -208,7 +208,7 @@ proc recd001 { method {select 0} args} {
 	set part_data [replicate "abcdefgh" 32]
 	set p [list 0 $len]
 	set cmd [subst \
-	    {DB put -txn TXNID -partial {$len $len2} $key $part_data}]
+	    {DB put -txn TXNID -partial "$len $len2" $key $part_data}]
 	set msg "Recd001.o: partial put prepopulated/expanding"
 	foreach op {abort commit prepare-abort prepare-discard prepare-commit} {
 		env_cleanup $testdir
diff --git a/storage/bdb/test/recd002.tcl b/storage/bdb/test/recd002.tcl
index ed579291283800915ef8dcc718e9f872339567a8..6189c5e2304063dd260fe1d93e11ec7e6101aa99 100644
--- a/storage/bdb/test/recd002.tcl
+++ b/storage/bdb/test/recd002.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: recd002.tcl,v 11.30 2002/02/25 16:44:24 sandstro Exp $
+# $Id: recd002.tcl,v 11.32 2004/01/28 03:36:28 bostic Exp $
 #
 # TEST	recd002
 # TEST	Split recovery tests.  For every known split log message, makes sure
diff --git a/storage/bdb/test/recd003.tcl b/storage/bdb/test/recd003.tcl
index 0fd054832ce3c26cf1eb7fe557387841ce67044f..b6e799b3c181ea0aaccfa78f72d5211fcba1a9b6 100644
--- a/storage/bdb/test/recd003.tcl
+++ b/storage/bdb/test/recd003.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: recd003.tcl,v 11.30 2002/02/25 16:44:24 sandstro Exp $
+# $Id: recd003.tcl,v 11.32 2004/01/28 03:36:28 bostic Exp $
 #
 # TEST	recd003
 # TEST	Duplicate recovery tests.  For every known duplicate log message,
diff --git a/storage/bdb/test/recd004.tcl b/storage/bdb/test/recd004.tcl
index 74504ac3cd756cbaa28ac55920ee045175bd9fc5..72e66b5e6743bb14e4118ec66e0397d03bcca8dc 100644
--- a/storage/bdb/test/recd004.tcl
+++ b/storage/bdb/test/recd004.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: recd004.tcl,v 11.29 2002/02/25 16:44:25 sandstro Exp $
+# $Id: recd004.tcl,v 11.31 2004/01/28 03:36:28 bostic Exp $
 #
 # TEST	recd004
 # TEST	Big key test where big key gets elevated to internal page.
diff --git a/storage/bdb/test/recd005.tcl b/storage/bdb/test/recd005.tcl
index 7668c9e3be31223c2b0f3a4ae631b0e8e0987123..df6a2df3a539da61e1dcfa1c14f1de77669a1781 100644
--- a/storage/bdb/test/recd005.tcl
+++ b/storage/bdb/test/recd005.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: recd005.tcl,v 11.34 2002/05/22 15:42:39 sue Exp $
+# $Id: recd005.tcl,v 11.36 2004/01/28 03:36:28 bostic Exp $
 #
 # TEST	recd005
 # TEST	Verify reuse of file ids works on catastrophic recovery.
diff --git a/storage/bdb/test/recd006.tcl b/storage/bdb/test/recd006.tcl
index fc35e755b08390190708f765d562f73e9a57baf8..bca968e5bb37e81b5ca2f494bbefc3d2a45194e8 100644
--- a/storage/bdb/test/recd006.tcl
+++ b/storage/bdb/test/recd006.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: recd006.tcl,v 11.26 2002/03/15 16:30:53 sue Exp $
+# $Id: recd006.tcl,v 11.28 2004/01/28 03:36:28 bostic Exp $
 #
 # TEST	recd006
 # TEST	Nested transactions.
diff --git a/storage/bdb/test/recd007.tcl b/storage/bdb/test/recd007.tcl
index aeac3bea2c1a51273d5c43353bd4d736c780be73..9764d840f62ff5768770b383b936b2ceae35c0ee 100644
--- a/storage/bdb/test/recd007.tcl
+++ b/storage/bdb/test/recd007.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: recd007.tcl,v 11.60 2002/08/08 15:38:07 bostic Exp $
+# $Id: recd007.tcl,v 11.64 2004/07/07 19:08:21 carol Exp $
 #
 # TEST	recd007
 # TEST	File create/delete tests.
@@ -55,6 +55,9 @@ proc recd007 { method args} {
 
 	# Convert the args again because fixed_len is now real.
 	set opts [convert_args $method ""]
+	set save_opts $opts
+	set moreopts {" -lorder 1234 " " -lorder 1234 -chksum " \
+	    " -lorder 4321 " " -lorder 4321 -chksum "}
 
 	# List of recovery tests: {HOOKS MSG} pairs
 	# Where each HOOK is a list of {COPY ABORT}
@@ -85,8 +88,17 @@ proc recd007 { method args} {
 	foreach pair $rlist {
 		set cmd [lindex $pair 0]
 		set msg [lindex $pair 1]
+		#
+		# Run natively
+		#
 		file_recover_create $testdir $env_cmd $omethod \
-		    $opts $testfile $cmd $msg
+		    $save_opts $testfile $cmd $msg
+		foreach o $moreopts {
+			set opts $save_opts
+			append opts $o
+			file_recover_create $testdir $env_cmd $omethod \
+			    $opts $testfile $cmd $msg
+		}
 	}
 
 	set rlist {
@@ -103,7 +115,13 @@ proc recd007 { method args} {
 			set cmd [lindex $pair 0]
 			set msg [lindex $pair 1]
 			file_recover_delete $testdir $env_cmd $omethod \
-			$opts $testfile $cmd $msg $op
+			    $save_opts $testfile $cmd $msg $op
+			foreach o $moreopts {
+				set opts $save_opts
+				append opts $o
+				file_recover_delete $testdir $env_cmd $omethod \
+				    $opts $testfile $cmd $msg $op
+			}
 		}
 	}
 
@@ -118,6 +136,8 @@ proc recd007 { method args} {
 	    > $tmpfile} ret]
 	error_check_good db_printlog $stat 0
 	fileremove $tmpfile
+	set fixed_len $orig_fixed_len
+	return
 }
 
 proc file_recover_create { dir env_cmd method opts dbfile cmd msg } {
@@ -126,17 +146,17 @@ proc file_recover_create { dir env_cmd method opts dbfile cmd msg } {
 	# 1.  Creating just a database
 	# 2.  Creating a database with a subdb
 	# 3.  Creating a 2nd subdb in a database
-	puts "\t$msg create with a database"
+	puts "\t$msg ($opts) create with a database"
 	do_file_recover_create $dir $env_cmd $method $opts $dbfile \
 	    0 $cmd $msg
 	if { [is_queue $method] == 1 } {
 		puts "\tSkipping subdatabase tests for method $method"
 		return
 	}
-	puts "\t$msg create with a database and subdb"
+	puts "\t$msg ($opts) create with a database and subdb"
 	do_file_recover_create $dir $env_cmd $method $opts $dbfile \
 	    1 $cmd $msg
-	puts "\t$msg create with a database and 2nd subdb"
+	puts "\t$msg ($opts) create with a database and 2nd subdb"
 	do_file_recover_create $dir $env_cmd $method $opts $dbfile \
 	    2 $cmd $msg
 
@@ -346,17 +366,17 @@ proc file_recover_delete { dir env_cmd method opts dbfile cmd msg op } {
 	# 1.  Deleting/Renaming just a database
 	# 2.  Deleting/Renaming a database with a subdb
 	# 3.  Deleting/Renaming a 2nd subdb in a database
-	puts "\t$msg $op with a database"
+	puts "\t$msg $op ($opts) with a database"
 	do_file_recover_delete $dir $env_cmd $method $opts $dbfile \
 	    0 $cmd $msg $op
 	if { [is_queue $method] == 1 } {
 		puts "\tSkipping subdatabase tests for method $method"
 		return
 	}
-	puts "\t$msg $op with a database and subdb"
+	puts "\t$msg $op ($opts) with a database and subdb"
 	do_file_recover_delete $dir $env_cmd $method $opts $dbfile \
 	    1 $cmd $msg $op
-	puts "\t$msg $op with a database and 2nd subdb"
+	puts "\t$msg $op ($opts) with a database and 2nd subdb"
 	do_file_recover_delete $dir $env_cmd $method $opts $dbfile \
 	    2 $cmd $msg $op
 
diff --git a/storage/bdb/test/recd008.tcl b/storage/bdb/test/recd008.tcl
index 548813a403b7083a1d6008e0ee9733ef839573c2..b12c757854aa2a8df2e3f2cb7658018b8473ced5 100644
--- a/storage/bdb/test/recd008.tcl
+++ b/storage/bdb/test/recd008.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: recd008.tcl,v 1.26 2002/02/25 16:44:26 sandstro Exp $
+# $Id: recd008.tcl,v 1.30 2004/11/05 00:59:01 mjc Exp $
 #
 # TEST	recd008
 # TEST	Test deeply nested transactions and many-child transactions.
@@ -14,10 +14,6 @@ proc recd008 { method {breadth 4} {depth 4} args} {
 	set args [convert_args $method $args]
 	set omethod [convert_method $method]
 
-	if { [is_record_based $method] == 1 } {
-		puts "Recd008 skipping for method $method"
-		return
-	}
 	puts "Recd008: $method $breadth X $depth deeply nested transactions"
 
 	# Create the database and environment.
@@ -34,7 +30,7 @@ proc recd008 { method {breadth 4} {depth 4} args} {
 	set did [open $dict]
 	set count 0
 	while { [gets $did str] != -1 && $count < 1000 } {
-		if { [string compare $omethod "-recno"] == 0 } {
+		if { [is_record_based $method] == 1 } {
 			set key [expr $count + 1]
 		} else {
 			set key $str
@@ -43,7 +39,7 @@ proc recd008 { method {breadth 4} {depth 4} args} {
 			set p1 $key
 			set kvals($p1) $str
 		}
-		set ret [$db put $key $str]
+		set ret [$db put $key [chop_data $method $str]]
 		error_check_good put $ret 0
 
 		incr count
@@ -57,7 +53,8 @@ proc recd008 { method {breadth 4} {depth 4} args} {
 	}
 	puts "\tRecd008.b: create environment for $txn_max transactions"
 
-	set eflags "-mode 0644 -create -txn_max $txn_max \
+	set lock_max 2500
+	set eflags "-mode 0644 -create -lock_max $lock_max -txn_max $txn_max \
 	    -txn -home $testdir"
 	set env_cmd "berkdb_env $eflags"
 	set dbenv [eval $env_cmd]
@@ -66,9 +63,9 @@ proc recd008 { method {breadth 4} {depth 4} args} {
 	reset_env $dbenv
 
 	set rlist {
-	{ {recd008_parent abort ENV DB $p1 TXNID 1 1 $breadth $depth}
+	{ {recd008_parent abort ENV DB $method $p1 TXNID 1 1 $breadth $depth}
 		"Recd008.c: child abort parent" }
-	{ {recd008_parent commit ENV DB $p1 TXNID 1 1 $breadth $depth}
+	{ {recd008_parent commit ENV DB $method $p1 TXNID 1 1 $breadth $depth}
 		"Recd008.d: child commit parent" }
 	}
 	foreach pair $rlist {
@@ -95,6 +92,7 @@ proc recd008_setkval { dbfile p1 } {
 	set db [berkdb_open $testdir/$dbfile]
 	error_check_good dbopen [is_valid_db $db] TRUE
 	set ret [$db get $p1]
+	error_check_good dbclose [$db close] 0
 	set kvals($p1) [lindex [lindex $ret 0] 1]
 }
 
@@ -114,7 +112,7 @@ proc recd008_setkval { dbfile p1 } {
 #	Parent commit/abort (in op_recover)
 #	(Final file)
 #	Recovery test (in op_recover)
-proc recd008_parent { op env db p1key parent b0 d0 breadth depth } {
+proc recd008_parent { op env db method p1key parent b0 d0 breadth depth } {
 	global kvals
 	source ./include.tcl
 
@@ -122,7 +120,7 @@ proc recd008_parent { op env db p1key parent b0 d0 breadth depth } {
 	# Save copy of original data
 	# Acquire lock on data
 	#
-	set olddata $kvals($p1key)
+	set olddata [pad_data $method $kvals($p1key)]
 	set ret [$db get -rmw -txn $parent $p1key]
 	set Dret [lindex [lindex $ret 0] 1]
 	error_check_good get_parent_RMW $Dret $olddata
@@ -130,7 +128,7 @@ proc recd008_parent { op env db p1key parent b0 d0 breadth depth } {
 	#
 	# Parent spawns off children
 	#
-	set ret [recd008_txn $op $env $db $p1key $parent \
+	set ret [recd008_txn $op $env $db $method $p1key $parent \
 	    $b0 $d0 $breadth $depth]
 
 	puts "Child runs complete.  Parent modifies data."
@@ -139,7 +137,7 @@ proc recd008_parent { op env db p1key parent b0 d0 breadth depth } {
 	# Parent modifies p1
 	#
 	set newdata $olddata.parent
-	set ret [$db put -txn $parent $p1key $newdata]
+	set ret [$db put -txn $parent $p1key [chop_data $method $newdata]]
 	error_check_good db_put $ret 0
 
 	#
@@ -156,7 +154,7 @@ proc recd008_parent { op env db p1key parent b0 d0 breadth depth } {
 	return 0
 }
 
-proc recd008_txn { op env db p1key parent b0 d0 breadth depth } {
+proc recd008_txn { op env db method p1key parent b0 d0 breadth depth } {
 	global log_log_record_types
 	global kvals
 	source ./include.tcl
@@ -176,7 +174,7 @@ proc recd008_txn { op env db p1key parent b0 d0 breadth depth } {
 		error_check_good txn_begin [is_valid_txn $t $env] TRUE
 		set startd [expr $d0 + 1]
 		set child $b:$startd:$t
-		set olddata $kvals($p1key)
+		set olddata [pad_data $method $kvals($p1key)]
 		set newdata $olddata.$child
 		set ret [$db get -rmw -txn $t $p1key]
 		set Dret [lindex [lindex $ret 0] 1]
@@ -186,15 +184,15 @@ proc recd008_txn { op env db p1key parent b0 d0 breadth depth } {
 		# Recursively call to set up nested transactions/children
 		#
 		for {set d $startd} {$d <= $depth} {incr d} {
-			set ret [recd008_txn commit $env $db $p1key $t \
+			set ret [recd008_txn commit $env $db $method $p1key $t \
 			    $b $d $breadth $depth]
-			set ret [recd008_txn abort $env $db $p1key $t \
+			set ret [recd008_txn abort $env $db $method $p1key $t \
 			    $b $d $breadth $depth]
 		}
 		#
 		# Modifies p1.
 		#
-		set ret [$db put -txn $t $p1key $newdata]
+		set ret [$db put -txn $t $p1key [chop_data $method $newdata]]
 		error_check_good db_put $ret 0
 
 		#
@@ -210,6 +208,7 @@ proc recd008_txn { op env db p1key parent b0 d0 breadth depth } {
 		}
 		set ret [$db get -rmw -txn $parent $p1key]
 		set Dret [lindex [lindex $ret 0] 1]
+		set newdata [pad_data $method $newdata]
 		switch $op {
 			"commit" {
 				puts "Command executed and committed."
diff --git a/storage/bdb/test/recd009.tcl b/storage/bdb/test/recd009.tcl
index 5538d2d7652ccbfaef14d1b0d3fce6ed9a31313e..d6700a0bd54c7a02d43c16c70fb4731ef40de2e2 100644
--- a/storage/bdb/test/recd009.tcl
+++ b/storage/bdb/test/recd009.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: recd009.tcl,v 1.18 2002/04/01 20:11:44 krinsky Exp $
+# $Id: recd009.tcl,v 1.20 2004/01/28 03:36:28 bostic Exp $
 #
 # TEST	recd009
 # TEST	Verify record numbering across split/reverse splits and recovery.
diff --git a/storage/bdb/test/recd010.tcl b/storage/bdb/test/recd010.tcl
index 2549e03a2c06af6b25ee90ef834357e78dc08898..a2df7a47c6f4ac4d0d64c467f679d7c76de68c67 100644
--- a/storage/bdb/test/recd010.tcl
+++ b/storage/bdb/test/recd010.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: recd010.tcl,v 1.19 2002/03/15 19:05:07 sue Exp $
+# $Id: recd010.tcl,v 1.21 2004/01/28 03:36:28 bostic Exp $
 #
 # TEST	recd010
 # TEST	Test stability of btree duplicates across btree off-page dup splits
diff --git a/storage/bdb/test/recd011.tcl b/storage/bdb/test/recd011.tcl
index 74108a306502fc2bde07ce8087776f15f78f3b68..bf118905b98ce35c513a909757f4cac0094d1e6e 100644
--- a/storage/bdb/test/recd011.tcl
+++ b/storage/bdb/test/recd011.tcl
@@ -1,33 +1,40 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2000-2002
+# Copyright (c) 2000-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: recd011.tcl,v 11.19 2002/02/25 16:44:26 sandstro Exp $
+# $Id: recd011.tcl,v 11.26 2004/01/28 03:36:28 bostic Exp $
 #
 # TEST	recd011
 # TEST	Verify that recovery to a specific timestamp works.
 proc recd011 { method {niter 200} {ckpt_freq 15} {sleep_time 1} args } {
 	source ./include.tcl
+	global rand_init
+	berkdb srand $rand_init
 
 	set args [convert_args $method $args]
 	set omethod [convert_method $method]
-	set tnum 11
+	set tnum "011"
 
-	puts "Recd0$tnum ($args): Test recovery to a specific timestamp."
+	puts "Recd$tnum ($method $args): Test recovery to a specific timestamp."
 
-	set testfile recd0$tnum.db
+	set testfile recd$tnum.db
 	env_cleanup $testdir
 
 	set i 0
 	if { [is_record_based $method] == 1 } {
 		set key 1
+		set bigkey 1001
 	} else {
 		set key KEY
+		set bigkey BIGKEY
 	}
 
-	puts "\tRecd0$tnum.a: Create environment and database."
-	set flags "-create -txn -home $testdir"
+	puts "\tRecd$tnum.a: Create environment and database."
+	set bufsize [expr 8 * 1024]
+	set maxsize [expr 8 * $bufsize]
+	set flags "-create -txn -home $testdir -log_buffer $bufsize \
+	    -log_max $maxsize"
 
 	set env_cmd "berkdb_env $flags"
 	set dbenv [eval $env_cmd]
@@ -41,18 +48,29 @@ proc recd011 { method {niter 200} {ckpt_freq 15} {sleep_time 1} args } {
 	puts "\t\tInitial Checkpoint"
 	error_check_good "Initial Checkpoint" [$dbenv txn_checkpoint] 0
 
-	puts "\tRecd0$tnum.b ($niter iterations):\
+	puts "\tRecd$tnum.b ($niter iterations):\
 	    Transaction-protected increment loop."
 	for { set i 0 } { $i <= $niter } { incr i } {
+		set str [random_data 4096 0 NOTHING]
 		set data $i
+		set bigdata $i$str
 
 		# Put, in a txn.
 		set txn [$dbenv txn]
 		error_check_good txn_begin [is_valid_txn $txn $dbenv] TRUE
 		error_check_good db_put \
 		    [$db put -txn $txn $key [chop_data $method $data]] 0
+		error_check_good db_put \
+		    [$db put -txn $txn $bigkey [chop_data $method $bigdata]] 0
 		error_check_good txn_commit [$txn commit] 0
 
+		# We need to sleep before taking the timestamp to guarantee
+		# that the timestamp is *after* this transaction commits.
+		# Since the resolution of the system call used by Berkeley DB
+		# is less than a second, rounding to the nearest second can
+		# otherwise cause off-by-one errors in the test.
+		tclsleep $sleep_time
+
 		set timeof($i) [timestamp -r]
 
 		# If an appropriate period has elapsed, checkpoint.
@@ -61,7 +79,8 @@ proc recd011 { method {niter 200} {ckpt_freq 15} {sleep_time 1} args } {
 			error_check_good ckpt($i) [$dbenv txn_checkpoint] 0
 		}
 
-		# sleep for N seconds.
+		# Sleep again to ensure that the next operation definitely
+		# occurs after the timestamp.
 		tclsleep $sleep_time
 	}
 	error_check_good db_close [$db close] 0
@@ -69,14 +88,15 @@ proc recd011 { method {niter 200} {ckpt_freq 15} {sleep_time 1} args } {
 
 	# Now, loop through and recover to each timestamp, verifying the
 	# expected increment.
-	puts "\tRecd0$tnum.c: Recover to each timestamp and check."
+	puts "\tRecd$tnum.c: Recover to each timestamp and check."
 	for { set i $niter } { $i >= 0 } { incr i -1 } {
 
 		# Run db_recover.
 		set t [clock format $timeof($i) -format "%y%m%d%H%M.%S"]
+		# puts $t
 		berkdb debug_check
 		set ret [catch {exec $util_path/db_recover -h $testdir -t $t} r]
-		error_check_good db_recover($i,$t) $ret 0
+		error_check_good db_recover($i,$t,$r) $ret 0
 
 		# Now open the db and check the timestamp.
 		set db [eval {berkdb_open} $testdir/$testfile]
@@ -93,12 +113,12 @@ proc recd011 { method {niter 200} {ckpt_freq 15} {sleep_time 1} args } {
 	# and well after the last timestamp.  The latter should
 	# be just like the timestamp of the last test performed;
 	# the former should fail.
-	puts "\tRecd0$tnum.d: Recover to before the first timestamp."
+	puts "\tRecd$tnum.d: Recover to before the first timestamp."
 	set t [clock format [expr $timeof(0) - 1000] -format "%y%m%d%H%M.%S"]
 	set ret [catch {exec $util_path/db_recover -h $testdir -t $t} r]
 	error_check_bad db_recover(before,$t) $ret 0
 
-	puts "\tRecd0$tnum.e: Recover to after the last timestamp."
+	puts "\tRecd$tnum.e: Recover to after the last timestamp."
 	set t [clock format \
 	    [expr $timeof($niter) + 1000] -format "%y%m%d%H%M.%S"]
 	set ret [catch {exec $util_path/db_recover -h $testdir -t $t} r]
diff --git a/storage/bdb/test/recd012.tcl b/storage/bdb/test/recd012.tcl
index 8231e6485889710948211faa1cce93e092f27d01..abed99de809dac1a422bedadb2c9003d06d63565 100644
--- a/storage/bdb/test/recd012.tcl
+++ b/storage/bdb/test/recd012.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2000-2002
+# Copyright (c) 2000-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: recd012.tcl,v 11.27 2002/05/10 00:48:07 margo Exp $
+# $Id: recd012.tcl,v 11.31 2004/04/19 14:56:13 bostic Exp $
 #
 # TEST	recd012
 # TEST	Test of log file ID management. [#2288]
@@ -12,14 +12,14 @@ proc recd012 { method {start 0} \
     {niter 49} {noutiter 25} {niniter 100} {ndbs 5} args } {
 	source ./include.tcl
 
-	set tnum 12
+	set tnum "012"
 	set pagesize 512
 
 	if { $is_qnx_test } {
 		set niter 40
 	}
 
-	puts "Recd0$tnum $method ($args): Test recovery file management."
+	puts "Recd$tnum $method ($args): Test recovery file management."
 	set pgindex [lsearch -exact $args "-pagesize"]
 	if { $pgindex != -1 } {
 		puts "Recd012: skipping for specific pagesizes"
@@ -52,8 +52,8 @@ proc recd012_body { method {ndbs 5} iter noutiter niniter psz tnum {largs ""} }
 	set largs [convert_args $method $largs]
 	set omethod [convert_method $method]
 
-	puts "\tRecd0$tnum $method ($largs): Iteration $iter"
-	puts "\t\tRecd0$tnum.a: Create environment and $ndbs databases."
+	puts "\tRecd$tnum $method ($largs): Iteration $iter"
+	puts "\t\tRecd$tnum.a: Create environment and $ndbs databases."
 
 	# We run out of lockers during some of the recovery runs, so
 	# we need to make sure that we specify a DB_CONFIG that will
@@ -98,10 +98,10 @@ proc recd012_body { method {ndbs 5} iter noutiter niniter psz tnum {largs ""} }
 		# 50-50 chance of being a subdb, unless we're a queue.
 		if { [berkdb random_int 0 1] || [is_queue $method] } {
 			# not a subdb
-			set dbname recd0$tnum-$i.db
+			set dbname recd$tnum-$i.db
 		} else {
 			# subdb
-			set dbname "recd0$tnum-subdb.db s$i"
+			set dbname "recd$tnum-subdb.db s$i"
 		}
 		puts $f $dbname
 		set db [eval berkdb_open $oflags $dbname]
@@ -127,7 +127,7 @@ proc recd012_body { method {ndbs 5} iter noutiter niniter psz tnum {largs ""} }
 	# before we run recovery 50% of the time.
 	set out [berkdb random_int 1 $noutiter]
 	puts \
-    "\t\tRecd0$tnum.b: Performing $out recoveries of up to $niniter ops."
+    "\t\tRecd$tnum.b: Performing $out recoveries of up to $niniter ops."
 	for { set i 0 } { $i < $out } { incr i } {
 		set child [open "|$tclsh_path" w]
 
@@ -136,7 +136,7 @@ proc recd012_body { method {ndbs 5} iter noutiter niniter psz tnum {largs ""} }
 		puts $child "load $tcllib"
 		puts $child "set fixed_len $fixed_len"
 		puts $child "source $src_root/test/testutils.tcl"
-		puts $child "source $src_root/test/recd0$tnum.tcl"
+		puts $child "source $src_root/test/recd$tnum.tcl"
 
 		set rnd [expr $iter * 10000 + $i * 100 + $rand_init]
 
@@ -174,7 +174,7 @@ proc recd012_body { method {ndbs 5} iter noutiter niniter psz tnum {largs ""} }
 	}
 
 	# Make sure each datum is the correct filename.
-	puts "\t\tRecd0$tnum.c: Checking data integrity."
+	puts "\t\tRecd$tnum.c: Checking data integrity."
 	set dbenv [berkdb_env -create -private -home $testdir]
 	error_check_good env_open_integrity [is_valid_env $dbenv] TRUE
 	set f [open $testdir/dblist r]
@@ -199,7 +199,7 @@ proc recd012_body { method {ndbs 5} iter noutiter niniter psz tnum {largs ""} }
 
 	# Verify
 	error_check_good verify \
-	    [verify_dir $testdir "\t\tRecd0$tnum.d: " 0 0 1] 0
+	    [verify_dir $testdir "\t\tRecd$tnum.d: " 0 0 1] 0
 }
 
 proc recd012_dochild { env_cmd rnd outiter niniter ndbs tnum method\
@@ -268,6 +268,7 @@ proc recd012_dochild { env_cmd rnd outiter niniter ndbs tnum method\
 			if { $num_open == 0 } {
 				# If none are open, do an open first.
 				recd012_open
+				set num_open [llength $opendbs]
 			}
 			set n [berkdb random_int 0 [expr $num_open - 1]]
 			set pair [lindex $opendbs $n]
@@ -322,7 +323,7 @@ proc recd012_dochild { env_cmd rnd outiter niniter ndbs tnum method\
 
 		# One time in two hundred, checkpoint.
 		if { [berkdb random_int 0 199] == 0 } {
-			puts "\t\t\tRecd0$tnum:\
+			puts "\t\t\tRecd$tnum:\
 			    Random checkpoint after operation $outiter.$j."
 			error_check_good txn_ckpt \
 			    [$dbenv txn_checkpoint] 0
diff --git a/storage/bdb/test/recd013.tcl b/storage/bdb/test/recd013.tcl
index e08654f34e03e45b539edbae4ce720dac58c7d41..36cad9eb497cff1137467e1731706688bfc911a6 100644
--- a/storage/bdb/test/recd013.tcl
+++ b/storage/bdb/test/recd013.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2000-2002
+# Copyright (c) 2000-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: recd013.tcl,v 11.18 2002/02/25 16:44:27 sandstro Exp $
+# $Id: recd013.tcl,v 11.22 2004/09/20 17:06:15 sue Exp $
 #
 # TEST	recd013
 # TEST	Test of cursor adjustment on child transaction aborts. [#2373]
@@ -24,17 +24,17 @@ proc recd013 { method { nitems 100 } args } {
 
 	set args [convert_args $method $args]
 	set omethod [convert_method $method]
-	set tnum 13
+	set tnum "013"
 	set pgsz 512
 
-	puts "Recd0$tnum $method ($args): Test of aborted cursor adjustments."
+	puts "Recd$tnum $method ($args): Test of aborted cursor adjustments."
 	set pgindex [lsearch -exact $args "-pagesize"]
 	if { $pgindex != -1 } {
 		puts "Recd013: skipping for specific pagesizes"
 		return
 	}
 
-	set testfile recd0$tnum.db
+	set testfile recd$tnum.db
 	env_cleanup $testdir
 
 	set i 0
@@ -44,7 +44,7 @@ proc recd013 { method { nitems 100 } args } {
 		set keybase "key"
 	}
 
-	puts "\tRecd0$tnum.a:\
+	puts "\tRecd$tnum.a:\
 	    Create environment, database, and parent transaction."
 	set flags "-create -txn -home $testdir"
 
@@ -73,7 +73,7 @@ proc recd013 { method { nitems 100 } args } {
 		error_check_good fake_put($i) [$db put -txn $ctxn $key $data] 0
 		error_check_good ctxn_abort($i) [$ctxn abort] 0
 		for { set j 1 } { $j < $i } { incr j 2 } {
-			error_check_good dbc_get($j) [$dbc($j) get -current] \
+			error_check_good dbc_get($j):1 [$dbc($j) get -current] \
 			    [list [list $keybase$j \
 			    [pad_data $method $j$alphabet]]]
 		}
@@ -90,20 +90,20 @@ proc recd013 { method { nitems 100 } args } {
 		# And verify all the cursors, including the one we just
 		# created.
 		for { set j 1 } { $j <= $i } { incr j 2 } {
-			error_check_good dbc_get($j) [$dbc($j) get -current] \
+			error_check_good dbc_get($j):2 [$dbc($j) get -current] \
 			    [list [list $keybase$j \
 			    [pad_data $method $j$alphabet]]]
 		}
 	}
 
-	puts "\t\tRecd0$tnum.a.1: Verify cursor stability after init."
+	puts "\t\tRecd$tnum.a.1: Verify cursor stability after init."
 	for { set i 1 } { $i <= 2 * $nitems } { incr i 2 } {
-		error_check_good dbc_get($i) [$dbc($i) get -current] \
+		error_check_good dbc_get($i):3 [$dbc($i) get -current] \
 		    [list [list $keybase$i [pad_data $method $i$alphabet]]]
 	}
 
-	puts "\tRecd0$tnum.b: Put test."
-	puts "\t\tRecd0$tnum.b.1: Put items."
+	puts "\tRecd$tnum.b: Put test."
+	puts "\t\tRecd$tnum.b.1: Put items."
 	set ctxn [$env txn -parent $txn]
 	error_check_good txn [is_valid_txn $ctxn $env] TRUE
 	for { set i 2 } { $i <= 2 * $nitems } { incr i 2 } {
@@ -126,11 +126,11 @@ proc recd013 { method { nitems 100 } args } {
 		}
 	}
 
-	puts "\t\tRecd0$tnum.b.2: Verify cursor stability after abort."
+	puts "\t\tRecd$tnum.b.2: Verify cursor stability after abort."
 	error_check_good ctxn_abort [$ctxn abort] 0
 
 	for { set i 1 } { $i <= 2 * $nitems } { incr i 2 } {
-		error_check_good dbc_get($i) [$dbc($i) get -current] \
+		error_check_good dbc_get($i):4 [$dbc($i) get -current] \
 		    [list [list $keybase$i [pad_data $method $i$alphabet]]]
 	}
 
@@ -146,7 +146,7 @@ proc recd013 { method { nitems 100 } args } {
 
 	error_check_good db_sync [$db sync] 0
 	error_check_good db_verify \
-	    [verify_dir $testdir "\t\tRecd0$tnum.b.3: "] 0
+	    [verify_dir $testdir "\t\tRecd$tnum.b.3: "] 0
 
 	# Now put back all the even records, this time in the parent.
 	# Commit and re-begin the transaction so we can abort and
@@ -164,7 +164,7 @@ proc recd013 { method { nitems 100 } args } {
 	# in the parent and check cursor stability.  Then open a child
 	# transaction, and delete the odd ones.  Verify that the database
 	# is empty.
-	puts "\tRecd0$tnum.c: Delete test."
+	puts "\tRecd$tnum.c: Delete test."
 	unset dbc
 
 	# Create cursors pointing at each item.
@@ -176,7 +176,7 @@ proc recd013 { method { nitems 100 } args } {
 		    [list [list $keybase$i [pad_data $method $i$alphabet]]]
 	}
 
-	puts "\t\tRecd0$tnum.c.1: Delete even items in child txn and abort."
+	puts "\t\tRecd$tnum.c.1: Delete even items in child txn and abort."
 
 	if { [is_rrecno $method] != 1 } {
 		set init 2
@@ -198,11 +198,11 @@ proc recd013 { method { nitems 100 } args } {
 
 	# Verify that no items are deleted.
 	for { set i 1 } { $i <= 2 * $nitems } { incr i } {
-		error_check_good dbc_get($i) [$dbc($i) get -current] \
+		error_check_good dbc_get($i):5 [$dbc($i) get -current] \
 		    [list [list $keybase$i [pad_data $method $i$alphabet]]]
 	}
 
-	puts "\t\tRecd0$tnum.c.2: Delete even items in child txn and commit."
+	puts "\t\tRecd$tnum.c.2: Delete even items in child txn and commit."
 	set ctxn [$env txn -parent $txn]
 	for { set i $init } { $i <= $bound } { incr i $step } {
 		error_check_good del($i) [$db del -txn $ctxn $keybase$i] 0
@@ -216,15 +216,14 @@ proc recd013 { method { nitems 100 } args } {
 		} else {
 			set j [expr ($i - 1) / 2 + 1]
 		}
-		error_check_good dbc_get($i) [$dbc($i) get -current] \
+		error_check_good dbc_get($i):6 [$dbc($i) get -current] \
 		    [list [list $keybase$j [pad_data $method $i$alphabet]]]
 	}
 	for { set i 2 } { $i <= 2 * $nitems } { incr i 2 } {
-		error_check_good dbc_get($i) [$dbc($i) get -current] \
-		    [list [list "" ""]]
+		error_check_good dbc_get($i):7 [$dbc($i) get -current] ""
 	}
 
-	puts "\t\tRecd0$tnum.c.3: Delete odd items in child txn."
+	puts "\t\tRecd$tnum.c.3: Delete odd items in child txn."
 
 	set ctxn [$env txn -parent $txn]
 
@@ -246,7 +245,7 @@ proc recd013 { method { nitems 100 } args } {
 		    [llength [$db get -txn $ctxn $keybase$i]] 0
 	}
 
-	puts "\t\tRecd0$tnum.c.4: Verify cursor stability after abort."
+	puts "\t\tRecd$tnum.c.4: Verify cursor stability after abort."
 	error_check_good ctxn_abort [$ctxn abort] 0
 
 	# Verify that even items are deleted and odd items are not.
@@ -256,12 +255,11 @@ proc recd013 { method { nitems 100 } args } {
 		} else {
 			set j [expr ($i - 1) / 2 + 1]
 		}
-		error_check_good dbc_get($i) [$dbc($i) get -current] \
+		error_check_good dbc_get($i):8 [$dbc($i) get -current] \
 		    [list [list $keybase$j [pad_data $method $i$alphabet]]]
 	}
 	for { set i 2 } { $i <= 2 * $nitems } { incr i 2 } {
-		error_check_good dbc_get($i) [$dbc($i) get -current] \
-		    [list [list "" ""]]
+		error_check_good dbc_get($i):9 [$dbc($i) get -current] ""
 	}
 
 	# Clean up cursors.
@@ -272,14 +270,14 @@ proc recd013 { method { nitems 100 } args } {
 	# Sync and verify.
 	error_check_good db_sync [$db sync] 0
 	error_check_good db_verify \
-	    [verify_dir $testdir "\t\tRecd0$tnum.c.5: "] 0
+	    [verify_dir $testdir "\t\tRecd$tnum.c.5: "] 0
 
-	puts "\tRecd0$tnum.d: Clean up."
+	puts "\tRecd$tnum.d: Clean up."
 	error_check_good txn_commit [$txn commit] 0
 	error_check_good db_close [$db close] 0
 	error_check_good env_close [$env close] 0
 	error_check_good verify_dir \
-	    [verify_dir $testdir "\t\tRecd0$tnum.d.1: "] 0
+	    [verify_dir $testdir "\t\tRecd$tnum.d.1: "] 0
 
 	if { $log_log_record_types == 1 } {
 		logtrack_read $testdir
diff --git a/storage/bdb/test/recd014.tcl b/storage/bdb/test/recd014.tcl
index 6796341dca2b0eb28bcce0cd219f439cdef9bea8..da9207cb008c2b80ea307b0b9211e42f1a3bd313 100644
--- a/storage/bdb/test/recd014.tcl
+++ b/storage/bdb/test/recd014.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: recd014.tcl,v 1.19 2002/08/15 19:21:24 sandstro Exp $
+# $Id: recd014.tcl,v 1.21 2004/01/28 03:36:29 bostic Exp $
 #
 # TEST	recd014
 # TEST	This is a recovery test for create/delete of queue extents.  We
diff --git a/storage/bdb/test/recd015.tcl b/storage/bdb/test/recd015.tcl
index 8c3ad612419f9af4c361d610f6ff5e16478504b1..afe0ac8833b33f86b47d712e0dc0289518322d4e 100644
--- a/storage/bdb/test/recd015.tcl
+++ b/storage/bdb/test/recd015.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: recd015.tcl,v 1.13 2002/09/05 17:23:06 sandstro Exp $
+# $Id: recd015.tcl,v 1.16 2004/01/28 03:36:29 bostic Exp $
 #
 # TEST	recd015
 # TEST	This is a recovery test for testing lots of prepared txns.
@@ -11,6 +11,8 @@
 # TEST	DB_FIRST flag and then DB_NEXT.
 proc recd015 { method args } {
 	source ./include.tcl
+	global rand_init
+	error_check_good set_random_seed [berkdb srand $rand_init] 0
 
 	set args [convert_args $method $args]
 	set omethod [convert_method $method]
diff --git a/storage/bdb/test/recd016.tcl b/storage/bdb/test/recd016.tcl
index 504aca09617e0e9276ef3e40ae4ba4fbc7a023da..6f0d3d132f21f7b1df28a516429170412ad5d3db 100644
--- a/storage/bdb/test/recd016.tcl
+++ b/storage/bdb/test/recd016.tcl
@@ -1,183 +1,179 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: recd016.tcl,v 11.8 2002/09/05 17:23:07 sandstro Exp $
+# $Id: recd016.tcl,v 11.13 2004/07/07 19:08:21 carol Exp $
 #
 # TEST	recd016
-# TEST	This is a recovery test for testing running recovery while
-# TEST	recovery is already running.  While bad things may or may not
-# TEST	happen, if recovery is then run properly, things should be correct.
-proc recd016 { method args } {
+# TEST	Test recovery after checksum error.
+proc recd016 { method args} {
+	global fixed_len
+	global log_log_record_types
+	global datastr
 	source ./include.tcl
 
-	set args [convert_args $method $args]
-	set omethod [convert_method $method]
+	set pgindex [lsearch -exact $args "-pagesize"]
+	if { $pgindex != -1 } {
+		puts "Recd016: skipping for specific pagesizes"
+		return
+	}
+	if { [is_queueext $method] == 1 } {
+		puts "Recd016: skipping for method $method"
+		return
+	}
 
-	puts "Recd016: $method ($args) simultaneous recovery test"
-	puts "Recd016: Skipping; waiting on SR #6277" 
-	return
+	puts "Recd016: $method recovery after checksum error"
 
 	# Create the database and environment.
+	env_cleanup $testdir
+
 	set testfile recd016.db
+	set flags "-create -txn -home $testdir"
+
+	puts "\tRecd016.a: creating environment"
+	set env_cmd "berkdb_env $flags"
+	set dbenv [eval $env_cmd]
+	error_check_good dbenv [is_valid_env $dbenv] TRUE
+
+	set pgsize 512
+	set orig_fixed_len $fixed_len
+	set fixed_len [expr $pgsize / 4]
+	set opts [convert_args $method $args]
+	set omethod [convert_method $method]
+	set oflags "-create $omethod -mode 0644 \
+	    -auto_commit -chksum -pagesize $pgsize $opts $testfile"
+	set db [eval {berkdb_open} -env $dbenv $oflags]
 
 	#
-	# For this test we create our database ahead of time so that we
-	# don't need to send methods and args to the script.
+	# Put some data.
+	#
+	set nument 50
+	puts "\tRecd016.b: Put some data"
+	for { set i 1 } { $i <= $nument } { incr i } {
+		# Use 'i' as key so method doesn't matter
+		set key $i
+		set data $i$datastr
+
+		# Put, in a txn.
+		set txn [$dbenv txn]
+		error_check_good txn_begin [is_valid_txn $txn $dbenv] TRUE
+		error_check_good db_put \
+		    [$db put -txn $txn $key [chop_data $method $data]] 0
+		error_check_good txn_commit [$txn commit] 0
+	}
+	error_check_good db_close [$db close] 0
+	error_check_good env_close [$dbenv close] 0
+	#
+	# We need to remove the env so that we don't get cached
+	# pages.
 	#
-	cleanup $testdir NULL
+	error_check_good env_remove [berkdb envremove -home $testdir] 0
 
+	puts "\tRecd016.c: Overwrite part of database"
 	#
-	# Use a smaller log to make more files and slow down recovery.
+	# First just touch some bits in the file.  We want to go
+	# through the paging system, so touch some data pages,
+	# like the middle of page 2.
+	# We should get a checksum error for the checksummed file.
 	#
-	set gflags ""
-	set pflags ""
-	set log_max [expr 256 * 1024]
-	set nentries 10000
-	set nrec 6
-	set t1 $testdir/t1
-	set t2 $testdir/t2
-	set t3 $testdir/t3
-	set t4 $testdir/t4
-	set t5 $testdir/t5
-	# Since we are using txns, we need at least 1 lock per
-	# record (for queue).  So set lock_max accordingly.
-	set lkmax [expr $nentries * 2]
-
-	puts "\tRecd016.a: Create environment and database"
-	set env_cmd "berkdb_env -create -log_max $log_max \
-	    -lock_max $lkmax -txn -home $testdir"
-	set env [eval $env_cmd]
-	error_check_good dbenv [is_valid_env $env] TRUE
-	set db [eval {berkdb_open -create} \
-	    $omethod -auto_commit -env $env $args $testfile]
-	error_check_good dbopen [is_valid_db $db] TRUE
-	set did [open $dict]
-	set abid [open $t4 w]
-
-	if { [is_record_based $method] == 1 } {
-		set checkfunc recd016_recno.check
-		append gflags " -recno"
-	} else {
-		set checkfunc recd016.check
-	}
-	puts "\tRecd016.b: put/get loop"
-	# Here is the loop where we put and get each key/data pair
-	set count 0
-	while { [gets $did str] != -1 && $count < $nentries } {
-		if { [is_record_based $method] == 1 } {
-			global kvals
-
-			set key [expr $count + 1]
-			if { 0xffffffff > 0 && $key > 0xffffffff } {
-				set key [expr $key - 0x100000000]
-			}
-			if { $key == 0 || $key - 0xffffffff == 1 } {
-				incr key
-				incr count
-			}
-			set kvals($key) [pad_data $method $str]
-		} else {
-			set key $str
-			set str [reverse $str]
-		}
-		#
-		# Start a transaction.  Alternately abort and commit them.
-		# This will create a bigger log for recovery to collide.
-		#
-		set txn [$env txn]
-		set ret [eval \
-		    {$db put} -txn $txn $pflags {$key [chop_data $method $str]}]
-		error_check_good put $ret 0
-
-		if {[expr $count % 2] == 0} {
-			set ret [$txn commit]
-			error_check_good txn_commit $ret 0
-			set ret [eval {$db get} $gflags {$key}]
-			error_check_good commit_get \
-			    $ret [list [list $key [pad_data $method $str]]]
+	set pg 2
+	set fid [open $testdir/$testfile r+]
+	fconfigure $fid -translation binary
+	set seeklen [expr $pgsize * $pg + 200]
+	seek $fid $seeklen start
+	set byte [read $fid 1]
+	binary scan $byte c val
+	set newval [expr ~$val]
+	set newbyte [binary format c $newval]
+	seek $fid $seeklen start
+	puts -nonewline $fid $newbyte
+	close $fid
+
+	#
+	# Verify we get the checksum error.  When we get it, it should
+	# log the error as well, so when we run recovery we'll need to
+	# do catastrophic recovery.  We do this in a sub-process so that
+	# the files are closed after the panic.
+	#
+	set f1 [open |$tclsh_path r+]
+	puts $f1 "source $test_path/test.tcl"
+
+	set env_cmd "berkdb_env_noerr $flags"
+	set dbenv [send_cmd $f1 $env_cmd]
+	error_check_good dbenv [is_valid_env $dbenv] TRUE
+
+	set db [send_cmd $f1  "{berkdb_open_noerr} -env $dbenv $oflags"]
+	error_check_good db [is_valid_db $db] TRUE
+
+	# We need to set non-blocking mode so that after each command
+	# we can read all the remaining output from that command and
+	# we can know what the output from one command is.
+	fconfigure $f1 -blocking 0
+	set ret [read $f1]
+	set got_err 0
+	for { set i 1 } { $i <= $nument } { incr i } {
+		set stat [send_cmd $f1  "catch {$db get $i} r"]
+		set getret [send_cmd $f1  "puts \$r"]
+		set ret [read $f1]
+		if { $stat == 1 } {
+			error_check_good dbget:fail [is_substr $getret \
+			    "checksum error: page $pg"] 1
+			set got_err 1
+			break
 		} else {
-			set ret [$txn abort]
-			error_check_good txn_abort $ret 0
-			set ret [eval {$db get} $gflags {$key}]
-			error_check_good abort_get [llength $ret] 0
-			puts $abid $key
+			set key [lindex [lindex $getret 0] 0]
+			set data [lindex [lindex $getret 0] 1]
+			error_check_good keychk $key $i
+			error_check_good datachk $data \
+			    [pad_data $method $i$datastr]
 		}
-		incr count
-	}
-	close $did
-	close $abid
-	error_check_good dbclose [$db close] 0
-	error_check_good envclose [$env close] 0
-
-	set pidlist {}
-	puts "\tRecd016.c: Start up $nrec recovery processes at once"
-	for {set i 0} {$i < $nrec} {incr i} {
-		set p [exec $util_path/db_recover -h $testdir -c &]
-		lappend pidlist $p
 	}
-	watch_procs $pidlist 5
-	#
-	# Now that they are all done run recovery correctly
-	puts "\tRecd016.d: Run recovery process"
-	set stat [catch {exec $util_path/db_recover -h $testdir -c} result]
-	if { $stat == 1 } {
-		error "FAIL: Recovery error: $result."
-	}
-
-	puts "\tRecd016.e: Open, dump and check database"
-	# Now compare the keys to see if they match the dictionary (or ints)
-	if { [is_record_based $method] == 1 } {
-		set oid [open $t2 w]
-		for {set i 1} {$i <= $nentries} {incr i} {
-			set j $i
-			if { 0xffffffff > 0 && $j > 0xffffffff } {
-				set j [expr $j - 0x100000000]
-			}
-			if { $j == 0 } {
-				incr i
-				incr j
-			}
-			puts $oid $j
-		}
-		close $oid
-	} else {
-		set q q
-		filehead $nentries $dict $t2
+	error_check_good got_chksum $got_err 1
+	set ret [send_cmd $f1  "$db close"]
+	set extra [read $f1]
+	error_check_good db:fail [is_substr $ret "run recovery"] 1
+
+	set ret [send_cmd $f1  "$dbenv close"]
+	error_check_good env_close:fail [is_substr $ret "run recovery"] 1
+	close $f1
+
+        # Keep track of the log types we've seen
+	if { $log_log_record_types == 1} {
+		logtrack_read $testdir
 	}
-	filesort $t2 $t3
-	file rename -force $t3 $t2
-	filesort $t4 $t3
-	file rename -force $t3 $t4
-	fileextract $t2 $t4 $t3
-	file rename -force $t3 $t5
-
-	set env [eval $env_cmd]
-	error_check_good dbenv [is_valid_env $env] TRUE
-
-	open_and_dump_file $testfile $env $t1 $checkfunc \
-	    dump_file_direction "-first" "-next"
-	filesort $t1 $t3
-	error_check_good envclose [$env close] 0
-
-	error_check_good Recd016:diff($t5,$t3) \
-	    [filecmp $t5 $t3] 0
-
-	set stat [catch {exec $util_path/db_printlog -h $testdir \
-	    > $testdir/LOG } ret]
-	error_check_good db_printlog $stat 0
-	fileremove $testdir/LOG
-}
 
-# Check function for recd016; keys and data are identical
-proc recd016.check { key data } {
-	error_check_good "key/data mismatch" $data [reverse $key]
-}
+	puts "\tRecd016.d: Run normal recovery"
+	set ret [catch {exec $util_path/db_recover -h $testdir} r]
+	error_check_good db_recover $ret 1
+	error_check_good dbrec:fail \
+	    [is_substr $r "checksum error"] 1
 
-proc recd016_recno.check { key data } {
-	global kvals
+	catch {fileremove $testdir/$testfile} ret
+	puts "\tRecd016.e: Run catastrophic recovery"
+	set ret [catch {exec $util_path/db_recover -c -h $testdir} r]
+	error_check_good db_recover $ret 0
 
-	error_check_good key"$key"_exists [info exists kvals($key)] 1
-	error_check_good "key/data mismatch, key $key" $data $kvals($key)
+	#
+	# Now verify the data was reconstructed correctly.
+	#
+	set env_cmd "berkdb_env_noerr $flags"
+	set dbenv [eval $env_cmd]
+	error_check_good dbenv [is_valid_env $dbenv] TRUE
+
+	set db [eval {berkdb_open} -env $dbenv $oflags]
+	error_check_good db [is_valid_db $db] TRUE
+
+	for { set i 1 } { $i <= $nument } { incr i } {
+		set stat [catch {$db get $i} ret]
+		error_check_good stat $stat 0
+		set key [lindex [lindex $ret 0] 0]
+		set data [lindex [lindex $ret 0] 1]
+		error_check_good keychk $key $i
+		error_check_good datachk $data [pad_data $method $i$datastr]
+	}
+	error_check_good db_close [$db close] 0
+	error_check_good env_close [$dbenv close] 0
+	set fixed_len $orig_fixed_len
+	return
 }
diff --git a/storage/bdb/test/recd017.tcl b/storage/bdb/test/recd017.tcl
index 9f8208c1b3e47edc2155e2278955c916f04fcd79..43dfb64219441241704bc78a156d4f52513e0111 100644
--- a/storage/bdb/test/recd017.tcl
+++ b/storage/bdb/test/recd017.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: recd017.tcl,v 11.4 2002/09/03 16:44:37 sue Exp $
+# $Id: recd017.tcl,v 11.7 2004/01/28 03:36:29 bostic Exp $
 #
 # TEST	recd017
 # TEST  Test recovery and security.  This is basically a watered
@@ -13,8 +13,15 @@ proc recd017 { method {select 0} args} {
 	global fixed_len
 	global encrypt
 	global passwd
+	global has_crypto
 	source ./include.tcl
 
+	# Skip test if release does not support encryption.
+	if { $has_crypto == 0 } {
+		puts "Skipping recd017 for non-crypto release."
+		return
+	}
+
 	set orig_fixed_len $fixed_len
 	set opts [convert_args $method $args]
 	set omethod [convert_method $method]
diff --git a/storage/bdb/test/recd018.tcl b/storage/bdb/test/recd018.tcl
index fb5a589d851357f741ca60566cdb2c8af7ff4422..2f2300cf97b4d4aba108237184ed5b3aa640199d 100644
--- a/storage/bdb/test/recd018.tcl
+++ b/storage/bdb/test/recd018.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2000-2002
+# Copyright (c) 2000-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: recd018.tcl,v 11.2 2002/03/13 21:04:20 sue Exp $
+# $Id: recd018.tcl,v 11.5 2004/01/28 03:36:29 bostic Exp $
 #
 # TEST	recd018
 # TEST	Test recover of closely interspersed checkpoints and commits.
@@ -15,11 +15,11 @@ proc recd018 { method {ndbs 10} args } {
 
 	set args [convert_args $method $args]
 	set omethod [convert_method $method]
-	set tnum 18
+	set tnum "018"
 
-	puts "Recd0$tnum ($args): $method recovery of checkpoints and commits."
+	puts "Recd$tnum ($args): $method recovery of checkpoints and commits."
 
-	set tname recd0$tnum.db
+	set tname recd$tnum.db
 	env_cleanup $testdir
 
 	set i 0
@@ -31,7 +31,7 @@ proc recd018 { method {ndbs 10} args } {
 		set key2 KEY2
 	}
 
-	puts "\tRecd0$tnum.a: Create environment and database."
+	puts "\tRecd$tnum.a: Create environment and database."
 	set flags "-create -txn -home $testdir"
 
 	set env_cmd "berkdb_env $flags"
@@ -52,7 +52,7 @@ proc recd018 { method {ndbs 10} args } {
 	# Do a commit immediately followed by a checkpoint after each one.
 	error_check_good "Initial Checkpoint" [$dbenv txn_checkpoint] 0
 
-	puts "\tRecd0$tnum.b Put/Commit/Checkpoint to $ndbs databases"
+	puts "\tRecd$tnum.b Put/Commit/Checkpoint to $ndbs databases"
 	for { set i 0 } { $i < $ndbs } { incr i } {
 		set testfile $tname.$i
 		set data $i
@@ -81,11 +81,11 @@ proc recd018 { method {ndbs 10} args } {
 
 	# Now, loop through and recover to each timestamp, verifying the
 	# expected increment.
-	puts "\tRecd0$tnum.c: Run recovery (no-op)"
+	puts "\tRecd$tnum.c: Run recovery (no-op)"
 	set ret [catch {exec $util_path/db_recover -h $testdir} r]
 	error_check_good db_recover $ret 0
 
-	puts "\tRecd0$tnum.d: Run recovery (initial file)"
+	puts "\tRecd$tnum.d: Run recovery (initial file)"
 	for { set i 0 } {$i < $ndbs } { incr i } {
 		set testfile $tname.$i
 		set file $testdir/$testfile.init
@@ -96,7 +96,7 @@ proc recd018 { method {ndbs 10} args } {
 	set ret [catch {exec $util_path/db_recover -h $testdir} r]
 	error_check_good db_recover $ret 0
 
-	puts "\tRecd0$tnum.e: Run recovery (after file)"
+	puts "\tRecd$tnum.e: Run recovery (after file)"
 	for { set i 0 } {$i < $ndbs } { incr i } {
 		set testfile $tname.$i
 		set file $testdir/$testfile.afterop
diff --git a/storage/bdb/test/recd019.tcl b/storage/bdb/test/recd019.tcl
index dd67b7dcb2aa118afdca74cecbf961d5a08036ac..4e4e60517393710d6cf5ce8e6d8279ea31ee6854 100644
--- a/storage/bdb/test/recd019.tcl
+++ b/storage/bdb/test/recd019.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: recd019.tcl,v 11.3 2002/08/08 15:38:07 bostic Exp $
+# $Id: recd019.tcl,v 11.6 2004/07/07 19:08:21 carol Exp $
 #
 # TEST	recd019
 # TEST	Test txn id wrap-around and recovery.
@@ -118,4 +118,6 @@ proc recd019 { method {numid 50} args} {
 
 	set ret [catch {exec $util_path/db_recover -h $testdir} r]
 	error_check_good db_recover $ret 0
+	set fixed_len $orig_fixed_len
+	return
 }
diff --git a/storage/bdb/test/recd020.tcl b/storage/bdb/test/recd020.tcl
index 93a89f325787a2ee0c91b53575437002ed4c1493..6fbe4b78e23cdf095949772475557f2e0ee93c9b 100644
--- a/storage/bdb/test/recd020.tcl
+++ b/storage/bdb/test/recd020.tcl
@@ -1,180 +1,80 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: recd020.tcl,v 11.8 2002/08/08 15:38:08 bostic Exp $
+# $Id: recd020.tcl,v 11.3 2004/09/22 18:01:05 bostic Exp $
 #
 # TEST	recd020
-# TEST	Test recovery after checksum error.
-proc recd020 { method args} {
-	global fixed_len
-	global log_log_record_types
-	global datastr
+# TEST	Test creation of intermediate directories -- an
+# TEST	undocumented, UNIX-only feature.
+#
+proc recd020 { method args } {
 	source ./include.tcl
+	global tcl_platform
 
-	set pgindex [lsearch -exact $args "-pagesize"]
-	if { $pgindex != -1 } {
-		puts "Recd020: skipping for specific pagesizes"
-		return
-	}
-	if { [is_queueext $method] == 1 } {
-		puts "Recd020: skipping for method $method"
+	set args [convert_args $method $args]
+	set omethod [convert_method $method]
+	set tnum "020"
+	set nentries 10
+
+	if { $tcl_platform(platform) != "unix" } {
+		puts "Skipping recd$tnum for non-UNIX platform."
 		return
 	}
 
-	puts "Recd020: $method recovery after checksum error"
+	puts "Recd$tnum ($method):\
+	    Test creation of intermediate directories in recovery."
 
-	# Create the database and environment.
+	# Create the original intermediate directory.
 	env_cleanup $testdir
+	set intdir INTDIR
+	file mkdir $testdir/$intdir
 
-	set testfile recd020.db
+	set testfile recd$tnum.db
 	set flags "-create -txn -home $testdir"
 
-	puts "\tRecd020.a: creating environment"
+	puts "\tRecd$tnum.a: Create environment and populate database."
 	set env_cmd "berkdb_env $flags"
-	set dbenv [eval $env_cmd]
-	error_check_good dbenv [is_valid_env $dbenv] TRUE
-
-	set pgsize 512
-	set orig_fixed_len $fixed_len
-	set fixed_len [expr $pgsize / 4]
-	set opts [convert_args $method $args]
-	set omethod [convert_method $method]
-	set oflags "-create $omethod -mode 0644 \
-	    -auto_commit -chksum -pagesize $pgsize $opts $testfile"
-	set db [eval {berkdb_open} -env $dbenv $oflags]
-
-	#
-	# Put some data.
-	#
-	set nument 50
-	puts "\tRecd020.b: Put some data"
-	for { set i 1 } { $i <= $nument } { incr i } {
-		# Use 'i' as key so method doesn't matter
-		set key $i
-		set data $i$datastr
-
-		# Put, in a txn.
-		set txn [$dbenv txn]
-		error_check_good txn_begin [is_valid_txn $txn $dbenv] TRUE
-		error_check_good db_put \
-		    [$db put -txn $txn $key [chop_data $method $data]] 0
-		error_check_good txn_commit [$txn commit] 0
+	set env [eval $env_cmd]
+	error_check_good env [is_valid_env $env] TRUE
+
+	set db [eval berkdb_open \
+	    -create $omethod $args -env $env -auto_commit $intdir/$testfile]
+	error_check_good db_open [is_valid_db $db] TRUE
+
+	set txn [$env txn]
+	set data "data"
+	for { set i 1 } { $i <= $nentries } { incr i } {
+		error_check_good db_put [eval \
+		    {$db put} -txn $txn $i [chop_data $method $data.$i]] 0
 	}
+	error_check_good txn_commit [$txn commit] 0
 	error_check_good db_close [$db close] 0
-	error_check_good env_close [$dbenv close] 0
-	#
-	# We need to remove the env so that we don't get cached
-	# pages.
-	#
-	error_check_good env_remove [berkdb envremove -home $testdir] 0
-
-	puts "\tRecd020.c: Overwrite part of database"
-	#
-	# First just touch some bits in the file.  We want to go
-	# through the paging system, so touch some data pages,
-	# like the middle of page 2.
-	# We should get a checksum error for the checksummed file.
-	#
-	set pg 2
-	set fid [open $testdir/$testfile r+]
-	fconfigure $fid -translation binary
-	set seeklen [expr $pgsize * $pg + 200]
-	seek $fid $seeklen start
-	set byte [read $fid 1]
-	binary scan $byte c val
-	set newval [expr ~$val]
-	set newbyte [binary format c $newval]
-	seek $fid $seeklen start
-	puts -nonewline $fid $newbyte
-	close $fid
-
-	#
-	# Verify we get the checksum error.  When we get it, it should
-	# log the error as well, so when we run recovery we'll need to
-	# do catastrophic recovery.  We do this in a sub-process so that
-	# the files are closed after the panic.
-	#
-	set f1 [open |$tclsh_path r+]
-	puts $f1 "source $test_path/test.tcl"
-
-	set env_cmd "berkdb_env_noerr $flags"
-	set dbenv [send_cmd $f1 $env_cmd]
-	error_check_good dbenv [is_valid_env $dbenv] TRUE
-
-	set db [send_cmd $f1  "{berkdb_open_noerr} -env $dbenv $oflags"]
-	error_check_good db [is_valid_db $db] TRUE
-
-	# We need to set non-blocking mode so that after each command
-	# we can read all the remaining output from that command and
-	# we can know what the output from one command is.
-	fconfigure $f1 -blocking 0
-	set ret [read $f1]
-	set got_err 0
-	for { set i 1 } { $i <= $nument } { incr i } {
-		set stat [send_cmd $f1  "catch {$db get $i} r"]
-		set getret [send_cmd $f1  "puts \$r"]
-		set ret [read $f1]
-		if { $stat == 1 } {
-			error_check_good dbget:fail [is_substr $getret \
-			    "checksum error: catastrophic recovery required"] 1
-			set got_err 1
-			# Now verify that it was an error on the page we set.
-			error_check_good dbget:pg$pg [is_substr $ret \
-			    "failed for page $pg"] 1
-			break
-		} else {
-			set key [lindex [lindex $getret 0] 0]
-			set data [lindex [lindex $getret 0] 1]
-			error_check_good keychk $key $i
-			error_check_good datachk $data \
-			    [pad_data $method $i$datastr]
-		}
-	}
-	error_check_good got_chksum $got_err 1
-	set ret [send_cmd $f1  "$db close"]
-	set extra [read $f1]
-	error_check_good db:fail [is_substr $ret "run recovery"] 1
-
-	set ret [send_cmd $f1  "$dbenv close"]
-	error_check_good env_close:fail [is_substr $ret "run recovery"] 1
-	close $f1
-
-        # Keep track of the log types we've seen
-	if { $log_log_record_types == 1} {
-		logtrack_read $testdir
+	error_check_good env_close [$env close] 0
+
+	puts "\tRecd$tnum.b: Remove intermediate directory."
+	error_check_good directory_there [file exists $testdir/$intdir] 1
+	file delete -force $testdir/$intdir
+	error_check_good directory_gone [file exists $testdir/$intdir] 0
+
+	puts "\tRecd020.c: Run recovery, recreating intermediate directory."
+	set env [eval $env_cmd -set_intermediate_dir 0751 -recover]
+	error_check_good env [is_valid_env $env] TRUE
+
+	puts "\tRecd020.d: Reopen test file to verify success."
+	set db [berkdb_open -env $env $intdir/$testfile]
+	error_check_good db_open [is_valid_db $db] TRUE
+	for { set i 1 } { $i <= $nentries } { incr i } {
+		set ret [$db get $i]
+		set k [lindex [lindex $ret 0] 0]
+		set d [lindex [lindex $ret 0] 1]
+		error_check_good key $k $i
+		error_check_good data $d [pad_data $method $data.$i]
 	}
 
-	puts "\tRecd020.d: Run normal recovery"
-	set ret [catch {exec $util_path/db_recover -h $testdir} r]
-	error_check_good db_recover $ret 1
-	error_check_good dbrec:fail \
-	    [is_substr $r "checksum error: catastrophic recovery required"] 1
-
-	catch {fileremove $testdir/$testfile} ret
-	puts "\tRecd020.e: Run catastrophic recovery"
-	set ret [catch {exec $util_path/db_recover -c -h $testdir} r]
-	error_check_good db_recover $ret 0
-
-	#
-	# Now verify the data was reconstructed correctly.
-	#
-	set env_cmd "berkdb_env_noerr $flags"
-	set dbenv [eval $env_cmd]
-	error_check_good dbenv [is_valid_env $dbenv] TRUE
-
-	set db [eval {berkdb_open} -env $dbenv $oflags]
-	error_check_good db [is_valid_db $db] TRUE
-
-	for { set i 1 } { $i <= $nument } { incr i } {
-		set stat [catch {$db get $i} ret]
-		error_check_good stat $stat 0
-		set key [lindex [lindex $ret 0] 0]
-		set data [lindex [lindex $ret 0] 1]
-		error_check_good keychk $key $i
-		error_check_good datachk $data [pad_data $method $i$datastr]
-	}
+	# Clean up.
 	error_check_good db_close [$db close] 0
-	error_check_good env_close [$dbenv close] 0
+	error_check_good env_close [$env close] 0
+
 }
diff --git a/storage/bdb/test/recd15scr.tcl b/storage/bdb/test/recd15scr.tcl
index e1238907a715ab9205a701d0c1246849a3e8e214..ef6fe7d0332b64663d12380ab807594eed1f8615 100644
--- a/storage/bdb/test/recd15scr.tcl
+++ b/storage/bdb/test/recd15scr.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: recd15scr.tcl,v 1.5 2002/01/30 13:18:04 margo Exp $
+# $Id: recd15scr.tcl,v 1.7 2004/01/28 03:36:29 bostic Exp $
 #
 # Recd15 - lots of txns - txn prepare script
 # Usage: recd15script envcmd dbcmd gidf numtxns
diff --git a/storage/bdb/test/recdscript.tcl b/storage/bdb/test/recdscript.tcl
index a2afde46e4df8ce0b8d002e82204175893c9bb4b..559d3407a093f49b8d8405a2d0e9d0c8eca5e0c8 100644
--- a/storage/bdb/test/recdscript.tcl
+++ b/storage/bdb/test/recdscript.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: recdscript.tcl,v 11.4 2002/01/11 15:53:32 bostic Exp $
+# $Id: recdscript.tcl,v 11.6 2004/01/28 03:36:29 bostic Exp $
 #
 # Recovery txn prepare script
 # Usage: recdscript op dir envcmd dbfile cmd
diff --git a/storage/bdb/test/rep001.tcl b/storage/bdb/test/rep001.tcl
index 97a640029f556532d66b44b4a35a241a455b7c5b..94163986a048e51afb93139902468a113186a6dd 100644
--- a/storage/bdb/test/rep001.tcl
+++ b/storage/bdb/test/rep001.tcl
@@ -1,34 +1,63 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2001-2002
+# Copyright (c) 2001-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: rep001.tcl,v 1.16 2002/08/26 17:52:19 margo Exp $
+# $Id: rep001.tcl,v 1.35 2004/09/22 18:01:05 bostic Exp $
 #
 # TEST  rep001
 # TEST	Replication rename and forced-upgrade test.
 # TEST
-# TEST	Run a modified version of test001 in a replicated master environment;
-# TEST  verify that the database on the client is correct.
-# TEST	Next, remove the database, close the master, upgrade the 
-# TEST	client, reopen the master, and make sure the new master can correctly
-# TEST	run test001 and propagate it in the other direction.
+# TEST	Run rep_test in a replicated master environment.
+# TEST	Verify that the database on the client is correct.
+# TEST	Next, remove the database, close the master, upgrade the
+# TEST	client, reopen the master, and make sure the new master can
+# TEST	correctly run rep_test and propagate it in the other direction.
 
-proc rep001 { method { niter 1000 } { tnum "01" } args } {
+proc rep001 { method { niter 1000 } { tnum "001" } args } {
 	global passwd
-
-	puts "Rep0$tnum: Replication sanity test."
-
-	set envargs ""
-	rep001_sub $method $niter $tnum $envargs $args
-
-	puts "Rep0$tnum: Replication and security sanity test."
-	append envargs " -encryptaes $passwd "
-	append args " -encrypt "
-	rep001_sub $method $niter $tnum $envargs $args
+	global has_crypto
+
+	# Run tests with and without recovery.  If we're doing testing
+	# of in-memory logging, skip the combination of recovery
+	# and in-memory logging -- it doesn't make sense.
+	set logsets [create_logsets 2]
+	set saved_args $args
+
+	foreach recopt { "" "-recover" } {
+		foreach l $logsets {
+			set logindex [lsearch -exact $l "in-memory"]
+			if { $recopt == "-recover" && $logindex != -1 } {
+				puts "Skipping test with -recover for in-memory logs."
+				continue
+			}
+			set envargs ""
+			set args $saved_args
+			puts "Rep$tnum: Replication sanity test ($method $recopt)."
+			puts "Rep$tnum: Master logs are [lindex $l 0]"
+			puts "Rep$tnum: Client logs are [lindex $l 1]"
+			rep001_sub $method \
+			    $niter $tnum $envargs $l $recopt $args
+
+			# Skip encrypted tests if not supported.
+			if { $has_crypto == 0 } {
+				continue
+			}
+
+			# Run the same tests with security.
+			append envargs " -encryptaes $passwd "
+			append args " -encrypt "
+			puts "Rep$tnum: Replication and security sanity test\
+			    ($method $recopt)."
+			puts "Rep$tnum: Master logs are [lindex $l 0]"
+			puts "Rep$tnum: Client logs are [lindex $l 1]"
+			rep001_sub $method \
+			    $niter $tnum $envargs $l $recopt $args
+		}
+	}
 }
 
-proc rep001_sub { method niter tnum envargs largs } {
+proc rep001_sub { method niter tnum envargs logset recargs largs } {
 	source ./include.tcl
 	global testdir
 	global encrypt
@@ -43,200 +72,120 @@ proc rep001_sub { method niter tnum envargs largs } {
 	file mkdir $masterdir
 	file mkdir $clientdir
 
-	if { [is_record_based $method] == 1 } {
-		set checkfunc test001_recno.check
-	} else {
-		set checkfunc test001.check
-	}
+	set m_logtype [lindex $logset 0]
+	set c_logtype [lindex $logset 1]
+
+	# In-memory logs require a large log buffer, and cannot
+	# be used with -txn nosync.  Adjust the args for master
+	# and client.
+	set m_logargs [adjust_logargs $m_logtype]
+	set c_logargs [adjust_logargs $c_logtype]
+	set m_txnargs [adjust_txnargs $m_logtype]
+	set c_txnargs [adjust_txnargs $c_logtype]
 
 	# Open a master.
 	repladd 1
-	set masterenv \
-	    [eval {berkdb_env -create -lock_max 2500 -log_max 1000000} \
-	    $envargs {-home $masterdir -txn -rep_master -rep_transport \
-	    [list 1 replsend]}]
+	set env_cmd(M) "berkdb_env_noerr -create -lock_max 2500 \
+	    -log_max 1000000 $envargs $m_logargs $recargs \
+	    -home $masterdir -errpfx MASTER $m_txnargs -rep_master \
+	    -rep_transport \[list 1 replsend\]"
+#	set env_cmd(M) "berkdb_env_noerr -create -lock_max 2500 \
+#	    -log_max 1000000 $envargs $m_logargs $recargs \
+#	    -home $masterdir \
+#	    -verbose {rep on} -errfile /dev/stderr \
+#	    -errpfx MASTER $m_txnargs -rep_master \
+#	    -rep_transport \[list 1 replsend\]"
+	set masterenv [eval $env_cmd(M)]
 	error_check_good master_env [is_valid_env $masterenv] TRUE
 
 	# Open a client
 	repladd 2
-	set clientenv [eval {berkdb_env -create} $envargs -txn -lock_max 2500 \
-	    {-home $clientdir -rep_client -rep_transport [list 2 replsend]}]
+	set env_cmd(C) "berkdb_env_noerr -create -lock_max 2500 \
+	    -log_max 1000000 $envargs $c_logargs $recargs \
+	    -home $clientdir -errpfx CLIENT $c_txnargs -rep_client \
+	    -rep_transport \[list 2 replsend\]"
+#	set env_cmd(C) "berkdb_env_noerr -create -lock_max 2500 \
+#	    -log_max 1000000 $envargs $c_logargs $recargs \
+#	    -home $clientdir \
+#	    -verbose {rep on} -errfile /dev/stderr \
+#	    -errpfx CLIENT $c_txnargs -rep_client \
+#	    -rep_transport \[list 2 replsend\]"
+	set clientenv [eval $env_cmd(C)]
 	error_check_good client_env [is_valid_env $clientenv] TRUE
 
 	# Bring the client online by processing the startup messages.
-	set donenow 0
-	while { 1 } {
-		set nproced 0
+	set envlist "{$masterenv 1} {$clientenv 2}"
+	process_msgs $envlist
 
-		incr nproced [replprocessqueue $masterenv 1]
-		incr nproced [replprocessqueue $clientenv 2]
+	# Run rep_test in the master (and update client).
+	puts "\tRep$tnum.a:\
+	    Running rep_test in replicated env ($envargs $recargs)."
+	eval rep_test $method $masterenv NULL $niter 0 0 0 $largs
+	process_msgs $envlist
 
-		if { $nproced == 0 } {
-			break
-		}
-	}
+	puts "\tRep$tnum.b: Verifying client database contents."
+	set dbname "test.db"
+	set masterdb [berkdb_open -env $masterenv -auto_commit $dbname]
+	set clientdb [berkdb_open -env $clientenv -auto_commit $dbname]
 
-	# Open a test database on the master (so we can test having handles
-	# open across an upgrade).
-	puts "\tRep0$tnum.a:\
-	    Opening test database for post-upgrade client logging test."
-	set master_upg_db [berkdb_open \
-	    -create -auto_commit -btree -env $masterenv rep0$tnum-upg.db]
-	set puttxn [$masterenv txn]
-	error_check_good master_upg_db_put \
-	    [$master_upg_db put -txn $puttxn hello world] 0
-	error_check_good puttxn_commit [$puttxn commit] 0
-	error_check_good master_upg_db_close [$master_upg_db close] 0
-
-	# Run a modified test001 in the master (and update client).
-	puts "\tRep0$tnum.b: Running test001 in replicated env."
-	eval test001 $method $niter 0 $tnum 1 -env $masterenv $largs
-	set donenow 0
-	while { 1 } {
-		set nproced 0
-
-		incr nproced [replprocessqueue $masterenv 1]
-		incr nproced [replprocessqueue $clientenv 2]
-
-		if { $nproced == 0 } {
-			break
-		}
-	}
+	error_check_good compare_master_and_client [db_compare \
+	    $masterdb $clientdb $masterdir/$dbname $clientdir/$dbname] 0
 
-	# Open the cross-upgrade database on the client and check its contents.
-	set client_upg_db [berkdb_open \
-	     -create -auto_commit -btree -env $clientenv rep0$tnum-upg.db]
-	error_check_good client_upg_db_get [$client_upg_db get hello] \
-	     [list [list hello world]]
-	# !!! We use this handle later.  Don't close it here.
-
-	# Verify the database in the client dir.
-	puts "\tRep0$tnum.c: Verifying client database contents."
-	set testdir [get_home $masterenv]
-	set t1 $testdir/t1
-	set t2 $testdir/t2
-	set t3 $testdir/t3
-	open_and_dump_file test0$tnum.db $clientenv $t1 \
-	    $checkfunc dump_file_direction "-first" "-next"
+	error_check_good master_close [$masterdb close] 0
+	error_check_good client_close [$clientdb close] 0
 
 	# Remove the file (and update client).
-	puts "\tRep0$tnum.d: Remove the file on the master and close master."
+	puts "\tRep$tnum.c: Remove the file on the master and close master."
 	error_check_good remove \
-	    [$masterenv dbremove -auto_commit test0$tnum.db] 0
+	    [$masterenv dbremove -auto_commit $dbname] 0
 	error_check_good masterenv_close [$masterenv close] 0
-	set donenow 0
-	while { 1 } {
-		set nproced 0
-
-		incr nproced [replprocessqueue $masterenv 1]
-		incr nproced [replprocessqueue $clientenv 2]
-
-		if { $nproced == 0 } {
-			break
-		}
-	}
+	process_msgs $envlist
 
-	# Don't get confused in Tcl.
-	puts "\tRep0$tnum.e: Upgrade client."
+	puts "\tRep$tnum.d: Upgrade client."
 	set newmasterenv $clientenv
 	error_check_good upgrade_client [$newmasterenv rep_start -master] 0
 
-	# Run test001 in the new master
-	puts "\tRep0$tnum.f: Running test001 in new master."
-	eval test001 $method $niter 0 $tnum 1 -env $newmasterenv $largs
-	set donenow 0
-	while { 1 } {
-		set nproced 0
-
-		incr nproced [replprocessqueue $newmasterenv 2]
-
-		if { $nproced == 0 } {
-			break
-		}
-	}
+	# Run rep_test in the new master
+	puts "\tRep$tnum.e: Running rep_test in new master."
+	eval rep_test $method $newmasterenv NULL $niter 0 0 0 $largs
+	set envlist "{$newmasterenv 2}"
+	process_msgs $envlist
 
-	puts "\tRep0$tnum.g: Reopen old master as client and catch up."
+	puts "\tRep$tnum.f: Reopen old master as client and catch up."
 	# Throttle master so it can't send everything at once
 	$newmasterenv rep_limit 0 [expr 64 * 1024]
 	set newclientenv [eval {berkdb_env -create -recover} $envargs \
-	    -txn -lock_max 2500 \
+	    -txn nosync -lock_max 2500 \
 	    {-home $masterdir -rep_client -rep_transport [list 1 replsend]}]
 	error_check_good newclient_env [is_valid_env $newclientenv] TRUE
-	set donenow 0
-	while { 1 } {
-		set nproced 0
-
-		incr nproced [replprocessqueue $newclientenv 1]
-		incr nproced [replprocessqueue $newmasterenv 2]
-
-		if { $nproced == 0 } {
-			break
-		}
-	}
-	set stats [$newmasterenv rep_stat]
-	set nthrottles [getstats $stats {Transmission limited}]
-	error_check_bad nthrottles $nthrottles -1
-	error_check_bad nthrottles $nthrottles 0
-
-	# Run a modified test001 in the new master (and update client).
-	puts "\tRep0$tnum.h: Running test001 in new master."
-	eval test001 $method \
-	    $niter $niter $tnum 1 -env $newmasterenv $largs
-	set donenow 0
-	while { 1 } {
-		set nproced 0
-
-		incr nproced [replprocessqueue $newclientenv 1]
-		incr nproced [replprocessqueue $newmasterenv 2]
-
-		if { $nproced == 0 } {
-			break
-		}
+	set envlist "{$newclientenv 1} {$newmasterenv 2}"
+	process_msgs $envlist
+
+	# If we're running with a low number of iterations, we might
+	# not have had to throttle the data transmission; skip the check.
+	if { $niter > 200 } {
+		set nthrottles \
+		    [stat_field $newmasterenv rep_stat "Transmission limited"]
+		error_check_bad nthrottles $nthrottles -1
+		error_check_bad nthrottles $nthrottles 0
 	}
 
-	# Test put to the database handle we opened back when the new master
-	# was a client.
-	puts "\tRep0$tnum.i: Test put to handle opened before upgrade."
-	set puttxn [$newmasterenv txn]
-	error_check_good client_upg_db_put \
-	    [$client_upg_db put -txn $puttxn hello there] 0
-	error_check_good puttxn_commit [$puttxn commit] 0
-	set donenow 0
-	while { 1 } {
-		set nproced 0
-
-		incr nproced [replprocessqueue $newclientenv 1]
-		incr nproced [replprocessqueue $newmasterenv 2]
-
-		if { $nproced == 0 } {
-			break
-		}
-	}
-
-	# Close the new master's handle for the upgrade-test database;  we
-	# don't need it.  Then check to make sure the client did in fact
-	# update the database.
-	error_check_good client_upg_db_close [$client_upg_db close] 0
-	set newclient_upg_db [berkdb_open -env $newclientenv rep0$tnum-upg.db]
-	error_check_good newclient_upg_db_get [$newclient_upg_db get hello] \
-	    [list [list hello there]]
-	error_check_good newclient_upg_db_close [$newclient_upg_db close] 0
+	# Run a modified rep_test in the new master (and update client).
+	puts "\tRep$tnum.g: Running rep_test in new master."
+	eval rep_test $method \
+	    $newmasterenv NULL $niter $niter $niter 0 $largs
+	process_msgs $envlist
 
 	# Verify the database in the client dir.
-	puts "\tRep0$tnum.j: Verifying new client database contents."
-	set testdir [get_home $newmasterenv]
-	set t1 $testdir/t1
-	set t2 $testdir/t2
-	set t3 $testdir/t3
-	open_and_dump_file test0$tnum.db $newclientenv $t1 \
-	    $checkfunc dump_file_direction "-first" "-next"
-
-	if { [string compare [convert_method $method] -recno] != 0 } {
-		filesort $t1 $t3
-	}
-	error_check_good diff_files($t2,$t3) [filecmp $t2 $t3] 0
+	puts "\tRep$tnum.h: Verifying new client database contents."
+	set masterdb [berkdb_open -env $newmasterenv -auto_commit $dbname]
+	set clientdb [berkdb_open -env $newclientenv -auto_commit $dbname]
 
+	error_check_good compare_master_and_client [db_compare \
+	    $masterdb $clientdb $masterdir/$dbname $clientdir/$dbname] 0
 
+	error_check_good master_close [$masterdb close] 0
+	error_check_good client_close [$clientdb close] 0
 	error_check_good newmasterenv_close [$newmasterenv close] 0
 	error_check_good newclientenv_close [$newclientenv close] 0
 
@@ -244,6 +193,6 @@ proc rep001_sub { method niter tnum envargs largs } {
 		set encrypt 1
 	}
 	error_check_good verify \
-	    [verify_dir $clientdir "\tRep0$tnum.k: " 0 0 1] 0
+	    [verify_dir $clientdir "\tRep$tnum.k: " 0 0 1] 0
 	replclose $testdir/MSGQUEUEDIR
 }
diff --git a/storage/bdb/test/rep002.tcl b/storage/bdb/test/rep002.tcl
index 68666b0d0f0af5817b95cf59e1974f9568b7bb14..1a3683f2e59eeaea1299b563e3a6382698eb4ddf 100644
--- a/storage/bdb/test/rep002.tcl
+++ b/storage/bdb/test/rep002.tcl
@@ -1,28 +1,53 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2002
+# Copyright (c) 2002-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: rep002.tcl,v 11.11 2002/08/08 18:13:12 sue Exp $
+# $Id: rep002.tcl,v 11.37 2004/09/22 18:01:05 bostic Exp $
 #
-# TEST  rep002
+# TEST  	rep002
 # TEST	Basic replication election test.
 # TEST
-# TEST	Run a modified version of test001 in a replicated master environment;
-# TEST  hold an election among a group of clients to make sure they select
-# TEST  a proper master from amongst themselves, in various scenarios.
+# TEST	Run a modified version of test001 in a replicated master
+# TEST	environment; hold an election among a group of clients to
+# TEST	make sure they select a proper master from amongst themselves,
+# TEST	in various scenarios.
 
-proc rep002 { method { niter 10 } { nclients 3 } { tnum "02" } args } {
-	source ./include.tcl
-	global elect_timeout
-
-	set elect_timeout 1000000
+proc rep002 { method { niter 10 } { nclients 3 } { tnum "002" } args } {
 
 	if { [is_record_based $method] == 1 } {
 		puts "Rep002: Skipping for method $method."
 		return
 	}
 
+	set logsets [create_logsets [expr $nclients + 1]]
+
+	# Run the body of the test with and without recovery.
+	set recopts { "" "-recover" }
+	foreach r $recopts {
+		foreach l $logsets {
+			set logindex [lsearch -exact $l "in-memory"]
+			if { $r == "-recover" && $logindex != -1 } {
+				puts "Skipping test with -recover for in-memory logs."
+			}
+			puts "Rep$tnum ($method $r):\
+			    Replication election test with $nclients clients."
+			puts "Rep$tnum: Master logs are [lindex $l 0]"
+			for { set i 0 } { $i < $nclients } { incr i } {
+				puts "Rep$tnum: Client $i logs are\
+				    [lindex $l [expr $i + 1]]"
+			}
+			rep002_sub $method $niter $nclients $tnum $l $r $args
+		}
+	}
+}
+
+proc rep002_sub { method niter nclients tnum logset recargs largs } {
+	source ./include.tcl
+	global elect_timeout elect_serial
+	global is_windows_test
+	set elect_timeout 5000000
+
 	env_cleanup $testdir
 
 	set qdir $testdir/MSGQUEUEDIR
@@ -30,61 +55,71 @@ proc rep002 { method { niter 10 } { nclients 3 } { tnum "02" } args } {
 
 	set masterdir $testdir/MASTERDIR
 	file mkdir $masterdir
+	set m_logtype [lindex $logset 0]
+	set m_logargs [adjust_logargs $m_logtype]
+	set m_txnargs [adjust_txnargs $m_logtype]
 
 	for { set i 0 } { $i < $nclients } { incr i } {
 		set clientdir($i) $testdir/CLIENTDIR.$i
 		file mkdir $clientdir($i)
+		set c_logtype($i) [lindex $logset [expr $i + 1]]
+		set c_logargs($i) [adjust_logargs $c_logtype($i)]
+		set c_txnargs($i) [adjust_txnargs $c_logtype($i)]
 	}
 
-	puts "Rep0$tnum: Replication election test with $nclients clients."
-
 	# Open a master.
 	repladd 1
-	set env_cmd(M) "berkdb_env -create -log_max 1000000 -home \
-	    $masterdir -txn -rep_master -rep_transport \[list 1 replsend\]"
-	set masterenv [eval $env_cmd(M)]
+	set env_cmd(M) "berkdb_env_noerr -create -log_max 1000000 \
+	    -home $masterdir $m_logargs -errpfx MASTER \
+	    $m_txnargs -rep_master -rep_transport \[list 1 replsend\]"
+#	set env_cmd(M) "berkdb_env_noerr -create -log_max 1000000 \
+#	    -home $masterdir $m_logargs -errpfx MASTER -errfile /dev/stderr \
+#	    -verbose {rep on} $m_txnargs -rep_master \
+#	    -rep_transport \[list 1 replsend\]"
+	# In an election test, the -recovery arg must not go
+	# in the env_cmd string because that is going to be
+	# passed to a child process.
+	set masterenv [eval $env_cmd(M) $recargs]
 	error_check_good master_env [is_valid_env $masterenv] TRUE
 
 	# Open the clients.
 	for { set i 0 } { $i < $nclients } { incr i } {
 		set envid [expr $i + 2]
 		repladd $envid
-		set env_cmd($i) "berkdb_env -create -home $clientdir($i) \
-		    -txn -rep_client -rep_transport \[list $envid replsend\]"
-		set clientenv($i) [eval $env_cmd($i)]
+		set env_cmd($i) "berkdb_env_noerr -create -home $clientdir($i) \
+		    $c_logargs($i) $c_txnargs($i) -rep_client -errpfx CLIENT$i \
+		    -rep_transport \[list $envid replsend\]"
+#		set env_cmd($i) "berkdb_env_noerr -create -home $clientdir($i) \
+#		    $c_logargs($i) -verbose {rep on} -errfile /dev/stderr \
+#		    $c_txnargs($i) -rep_client -errpfx CLIENT$i \
+#		    -rep_transport \[list $envid replsend\]"
+		set clientenv($i) [eval $env_cmd($i) $recargs]
 		error_check_good \
 		    client_env($i) [is_valid_env $clientenv($i)] TRUE
 	}
 
-	# Run a modified test001 in the master.
-	puts "\tRep0$tnum.a: Running test001 in replicated env."
-	eval test001 $method $niter 0 $tnum 0 -env $masterenv $args
-
 	# Loop, processing first the master's messages, then the client's,
 	# until both queues are empty.
-	while { 1 } {
-		set nproced 0
-
-		incr nproced [replprocessqueue $masterenv 1]
-
-		for { set i 0 } { $i < $nclients } { incr i } { 	
-			set envid [expr $i + 2]
-			incr nproced [replprocessqueue $clientenv($i) $envid]
-		}
-
-		if { $nproced == 0 } {
-			break
-		}
+	set envlist {}
+	lappend envlist "$masterenv 1"
+	for { set i 0 } { $i < $nclients } { incr i } {
+		lappend envlist "$clientenv($i) [expr $i + 2]"
 	}
+	process_msgs $envlist
+
+	# Run a modified test001 in the master.
+	puts "\tRep$tnum.a: Running test001 in replicated env."
+	eval test001 $method $niter 0 0 $tnum -env $masterenv $largs
+	process_msgs $envlist
 
 	# Verify the database in the client dir.
 	for { set i 0 } { $i < $nclients } { incr i } {
-		puts "\tRep0$tnum.b: Verifying contents of client database $i."
+		puts "\tRep$tnum.b: Verifying contents of client database $i."
 		set testdir [get_home $masterenv]
 		set t1 $testdir/t1
 		set t2 $testdir/t2
 		set t3 $testdir/t3
-		open_and_dump_file test0$tnum.db $clientenv($i) $testdir/t1 \
+		open_and_dump_file test$tnum.db $clientenv($i) $testdir/t1 \
 	    	    test001.check dump_file_direction "-first" "-next"
 
 		if { [string compare [convert_method $method] -recno] != 0 } {
@@ -92,59 +127,77 @@ proc rep002 { method { niter 10 } { nclients 3 } { tnum "02" } args } {
 		}
 		error_check_good diff_files($t2,$t3) [filecmp $t2 $t3] 0
 
-		verify_dir $clientdir($i) "\tRep0$tnum.c: " 0 0 1
+		verify_dir $clientdir($i) "\tRep$tnum.c: " 0 0 1
 	}
 
 	# Start an election in the first client.
-	puts "\tRep0$tnum.d: Starting election without dead master."
-
-	set elect_pipe(0) [start_election \
-	    $qdir $env_cmd(0) [expr $nclients + 1] 20 $elect_timeout]
-
-	tclsleep 1
-
-	# We want to verify all the clients but the one that declared an 
-	# election get the election message.
-	# We also want to verify that the master declares the election
+	puts "\tRep$tnum.d: Starting election with existing master."
+	# We want to verify that the master declares the election
 	# over by fiat, even if everyone uses a lower priority than 20.
-	# Loop and process all messages, keeping track of which 
-	# sites got a HOLDELECTION and checking that the returned newmaster, 
+	# Loop and process all messages, keeping track of which
+	# sites got a HOLDELECTION and checking that the returned newmaster,
 	# if any, is 1 (the master's replication ID).
 	set got_hold_elect(M) 0
-	for { set i 0 } { $i < $nclients } { incr i } { 
-		set got_hold_elect($i) 0 
+	for { set i 0 } { $i < $nclients } { incr i } {
+		set got_hold_elect($i) 0
+		set elect_pipe($i) INVALID
 	}
+	set elect_pipe(0) [start_election C0 \
+	    $qdir $env_cmd(0) [expr $nclients + 1] $nclients 20 $elect_timeout]
+
+	tclsleep 2
+
+	set got_master 0
 	while { 1 } {
 		set nproced 0
 		set he 0
 		set nm 0
-		
+		set nm2 0
 
 		incr nproced [replprocessqueue $masterenv 1 0 he nm]
 
 		if { $he == 1 } {
-			set elect_pipe(M) [start_election $qdir \
-			    $env_cmd(M) [expr $nclients + 1] 0 $elect_timeout]
+			incr elect_serial
+			set elect_pipe(M) [start_election CM $qdir \
+			    $env_cmd(M) [expr $nclients + 1] $nclients \
+			    0 $elect_timeout]
 			set got_hold_elect(M) 1
 		}
 		if { $nm != 0 } {
 			error_check_good newmaster_is_master $nm 1
+			set got_master $nm
+		}
+		if { $nm2 != 0 } {
+			error_check_good newmaster_is_master $nm2 1
+			set got_master $nm2
 		}
 
-		for { set i 0 } { $i < $nclients } { incr i } { 	
+		for { set i 0 } { $i < $nclients } { incr i } {
 			set he 0
 			set envid [expr $i + 2]
 			incr nproced \
 			    [replprocessqueue $clientenv($i) $envid 0 he nm]
+			set child_done [check_election $elect_pipe($i) nm2]
 			if { $he == 1 } {
 				# error_check_bad client(0)_in_elect $i 0
-				set elect_pipe(M) [start_election $qdir \
-			    	    $env_cmd($i) [expr $nclients + 1] 0 \
+				if { $elect_pipe($i) != "INVALID" } {
+					close_election $elect_pipe($i)
+				}
+				incr elect_serial
+				set pfx CHILD$i.$elect_serial
+				set elect_pipe($i) [start_election $pfx $qdir \
+			    	    $env_cmd($i) [expr $nclients + 1] \
+				    $nclients 0 \
 				    $elect_timeout]
 				set got_hold_elect($i) 1
 			}
 			if { $nm != 0 } {
 				error_check_good newmaster_is_master $nm 1
+				set got_master $nm
+			}
+			if { $nm2 != 0 } {
+				error_check_good newmaster_is_master $nm2 1
+				set got_master $nm2
 			}
 		}
 
@@ -152,21 +205,12 @@ proc rep002 { method { niter 10 } { nclients 3 } { tnum "02" } args } {
 			break
 		}
 	}
-
-	error_check_good got_hold_elect(master) $got_hold_elect(M) 0
-	unset got_hold_elect(M)
-	# error_check_good got_hold_elect(0) $got_hold_elect(0) 0
-	unset got_hold_elect(0)
-	for { set i 1 } { $i < $nclients } { incr i } { 
-		error_check_good got_hold_elect($i) $got_hold_elect($i) 1
-		unset got_hold_elect($i)
-	}
-
+	error_check_good got_master $got_master 1
 	cleanup_elections
 
 	# We need multiple clients to proceed from here.
 	if { $nclients < 2 } {
-		puts "\tRep0$tnum: Skipping for less than two clients."
+		puts "\tRep$tnum: Skipping for less than two clients."
 		error_check_good masterenv_close [$masterenv close] 0
 		for { set i 0 } { $i < $nclients } { incr i } {
 			error_check_good clientenv_close($i) \
@@ -178,101 +222,102 @@ proc rep002 { method { niter 10 } { nclients 3 } { tnum "02" } args } {
 	# Make sure all the clients are synced up and ready to be good
 	# voting citizens.
 	error_check_good master_flush [$masterenv rep_flush] 0
-	while { 1 } {
-		set nproced 0
-		incr nproced [replprocessqueue $masterenv 1 0]
-		for { set i 0 } { $i < $nclients } { incr i } {
-			incr nproced [replprocessqueue $clientenv($i) \
-			    [expr $i + 2] 0]
-		}
-
-		if { $nproced == 0 } {
-			break
-		}
-	}
+	process_msgs $envlist
 
 	# Now hold another election in the first client, this time with
 	# a dead master.
-	puts "\tRep0$tnum.e: Starting election with dead master."
+	puts "\tRep$tnum.e: Starting election with dead master."
 	error_check_good masterenv_close [$masterenv close] 0
+	set envlist [lreplace $envlist 0 0]
 
+	set m "Rep$tnum.e"
+	# We're not going to be using err_cmd, so initialize to "none".
+	# Client #1 has priority 100; everyone else has priority 10.
 	for { set i 0 } { $i < $nclients } { incr i } {
-		replclear [expr $i + 2]
+		set err_cmd($i) "none"
+		set crash($i) 0
+		if { $i == 1 } {
+			set pri($i) 100
+		} else {
+			set pri($i) 10
+		}
 	}
-
-	set elect_pipe(0) [start_election \
-	    $qdir $env_cmd(0) [expr $nclients + 1] 20 $elect_timeout]
-
-	tclsleep 1
-
-	# Process messages, and verify that the client with the highest
-	# priority--client #1--wins.
-	set got_newmaster 0
-	set tries 10
-	while { 1 } {
-		set nproced 0
-		set he 0
-		set nm 0
-		
-		for { set i 0 } { $i < $nclients } { incr i } { 	
-			set he 0
-			set envid [expr $i + 2]
-			incr nproced \
-			    [replprocessqueue $clientenv($i) $envid 0 he nm]
-			if { $he == 1 } {
-
-				# Client #1 has priority 100;  everyone else
-				# has priority 10.
-				if { $i == 1 } {
-					set pri 100
-				} else {
-					set pri 10
-				}
-				# error_check_bad client(0)_in_elect $i 0
-				set elect_pipe(M) [start_election $qdir \
-			    	    $env_cmd($i) [expr $nclients + 1] $pri \
-				    $elect_timeout]
-				set got_hold_elect($i) 1
-			}
-			if { $nm != 0 } {
-				error_check_good newmaster_is_master $nm \
-				    [expr 1 + 2]
-				set got_newmaster $nm
-
-				# If this env is the new master, it needs to
-				# configure itself as such--this is a different
-				# env handle from the one that performed the
-				# election.
-				if { $nm == $envid } {
-					error_check_good make_master($i) \
-					    [$clientenv($i) rep_start -master] \
-					    0
-				}
-			}
+	set nsites $nclients
+	set nvotes $nclients
+	# The elector calls the first election.  The expected winner
+	# is $win.
+	set elector 1
+	set win 1
+	run_election env_cmd envlist err_cmd pri crash $qdir $m \
+	    $elector $nsites $nvotes $nclients $win 1 "test$tnum.db"
+
+	# Hold an election with two clients at the same (winning) priority.
+	# Make sure that the tie gets broken, and that the third client
+	# does not win.
+	puts "\tRep$tnum.f: Election with two clients at same priority."
+	set m "Rep$tnum.f"
+	# Clients 0 and 1 have high, matching priority.
+	for { set i 0 } { $i < $nclients } { incr i } {
+		if { $i >= 2 } {
+			set pri($i) 10
+		} else {
+			set pri($i) 100
 		}
+	}
 
-		# We need to wait around to make doubly sure that the
-		# election has finished...
-		if { $nproced == 0 } {
-			incr tries -1
-			if { $tries == 0 } {
-				break
-			} else {
-				tclsleep 1
-			}
+	# Run several elections.
+	set elections 5
+	for { set i 0 } { $i < $elections } { incr i } {
+		#
+		# The expected winner is 0 or 1.  Since run_election can only
+		# handle one expected winner, catch the result and inspect it.
+		#
+		set elector 0
+		set win 1
+		set altwin 0
+		if {[catch {eval run_election \
+		    env_cmd envlist err_cmd pri crash $qdir $m $elector $nsites \
+		    $nvotes $nclients $win 1 "test$tnum.db"} res]} {
+			#
+			# If the primary winner didn't win, make sure
+			# the alternative winner won.  Do all the cleanup
+			# for that winner normally done in run_election:
+			# open and close the new master, then reopen as a
+			# client for the next cycle.
+			#
+			puts "\t$m: Election $i: Alternate winner $altwin won."
+			error_check_good check_winner [is_substr \
+			    $res "expected 3, got [expr $altwin + 2]"] 1
+			error_check_good make_master \
+			    [$clientenv($altwin) rep_start -master] 0
+
+			cleanup_elections
+			process_msgs $envlist
+
+			error_check_good newmaster_close \
+			    [$clientenv($altwin) close] 0
+			set clientenv($altwin) [eval $env_cmd($altwin)]
+			error_check_good cl($altwin) \
+			    [is_valid_env $clientenv($altwin)] TRUE
+			set newelector "$clientenv($altwin) [expr $altwin + 2]"
+			set envlist [lreplace $envlist $altwin $altwin $newelector]
+		} else {
+			puts "\t$m: Election $i: Primary winner $win won."
 		}
+		process_msgs $envlist
 	}
 
-	# Verify that client #1 is actually the winner.
-	error_check_good "client 1 wins" $got_newmaster [expr 1 + 2]
-
-	cleanup_elections
-
-	for { set i 0 } { $i < $nclients } { incr i } {
-		error_check_good clientenv_close($i) [$clientenv($i) close] 0
+	foreach pair $envlist {
+		set cenv [lindex $pair 0]
+		error_check_good cenv_close [$cenv close] 0
 	}
 
 	replclose $testdir/MSGQUEUEDIR
-}
 
-proc reptwo { args } { eval rep002 $args }
+	# If we're on Windows, we need to forcibly remove some of the
+	# files created when the alternate winner won.
+	if { $is_windows_test == 1 } {
+		set filelist [glob -nocomplain $testdir/CLIENTDIR.$altwin/*]
+		fileremove -f $filelist
+	}
+}
diff --git a/storage/bdb/test/rep003.tcl b/storage/bdb/test/rep003.tcl
index 7bb7e00ddbf47c13238ae11b68d10c7f6c4efac7..13ef257da40796df5f6ce7f72461bdb248fdaa5a 100644
--- a/storage/bdb/test/rep003.tcl
+++ b/storage/bdb/test/rep003.tcl
@@ -1,58 +1,95 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2002
+# Copyright (c) 2002-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: rep003.tcl,v 11.9 2002/08/09 02:23:50 margo Exp $
+# $Id: rep003.tcl,v 11.19 2004/09/22 18:01:05 bostic Exp $
 #
-# TEST  rep003
+# TEST  	rep003
 # TEST	Repeated shutdown/restart replication test
 # TEST
-# TEST	Run a quick put test in a replicated master environment;  start up, 
-# TEST  shut down, and restart client processes, with and without recovery.
-# TEST  To ensure that environment state is transient, use DB_PRIVATE.
+# TEST	Run a quick put test in a replicated master environment;
+# TEST	start up, shut down, and restart client processes, with
+# TEST	and without recovery.  To ensure that environment state
+# TEST	is transient, use DB_PRIVATE.
 
-proc rep003 { method { tnum "03" } args } {
+proc rep003 { method { tnum "003" } args } {
 	source ./include.tcl
-	global testdir rep003_dbname rep003_omethod rep003_oargs
-
-	env_cleanup $testdir
-	set niter 10
-	set rep003_dbname rep003.db
+	global rep003_dbname rep003_omethod rep003_oargs
 
 	if { [is_record_based $method] } {
-		puts "Rep0$tnum: Skipping for method $method"
+		puts "Rep$tnum: Skipping for method $method"
 		return
 	}
 
+	set rep003_dbname rep003.db
 	set rep003_omethod [convert_method $method]
 	set rep003_oargs [convert_args $method $args]
 
+	# Run the body of the test with and without recovery.  If we're
+	# testing in-memory logging, skip the combination of recovery
+	# and in-memory logging -- it doesn't make sense.
+
+	set logsets [create_logsets 2]
+	foreach recopt { "" "-recover" } {
+		foreach l $logsets {
+			set logindex [lsearch -exact $l "in-memory"]
+			if { $recopt == "-recover" && $logindex != -1 } {
+				puts "Rep$tnum: Skipping for\
+				    in-memory logs with -recover."
+				continue
+			}
+			puts "Rep$tnum ($method $recopt):\
+			    Replication repeated-startup test."
+			puts "Rep$tnum: Master logs are [lindex $l 0]"
+			puts "Rep$tnum: Client logs are [lindex $l 1]"
+			rep003_sub $method $tnum $l $recopt $args
+		}
+	}
+}
+
+proc rep003_sub { method tnum logset recargs largs } {
+	source ./include.tcl
+
+	env_cleanup $testdir
+
 	replsetup $testdir/MSGQUEUEDIR
 
 	set masterdir $testdir/MASTERDIR
-	file mkdir $masterdir
-	
 	set clientdir $testdir/CLIENTDIR
+
+	file mkdir $masterdir
 	file mkdir $clientdir
 
-	puts "Rep0$tnum: Replication repeated-startup test"
+	set m_logtype [lindex $logset 0]
+	set c_logtype [lindex $logset 1]
+
+	# In-memory logs require a large log buffer, and cannot
+	# be used with -txn nosync.  This test already requires
+	# -txn, so adjust the logargs only.
+	set m_logargs [adjust_logargs $m_logtype]
+	set c_logargs [adjust_logargs $c_logtype]
 
 	# Open a master.
 	repladd 1
-	set masterenv [berkdb_env_noerr -create -log_max 1000000 \
-	    -home $masterdir -txn -rep_master -rep_transport [list 1 replsend]]
+	set env_cmd(M) "berkdb_env_noerr -create -log_max 1000000 \
+	    -errpfx MASTER -errfile /dev/stderr \
+	    -home $masterdir -txn $m_logargs -rep_master \
+	    -rep_transport \[list 1 replsend\]"
+	set masterenv [eval $env_cmd(M) $recargs]
 	error_check_good master_env [is_valid_env $masterenv] TRUE
 
-	puts "\tRep0$tnum.a: Simple client startup test."
+	puts "\tRep$tnum.a: Simple client startup test."
 
 	# Put item one.
 	rep003_put $masterenv A1 a-one
 
 	# Open a client.
 	repladd 2
-	set clientenv [berkdb_env_noerr -create -private -home $clientdir -txn \
-	    -rep_client -rep_transport [list 2 replsend]]
+	set env_cmd(C) "berkdb_env_noerr -create -private -home $clientdir \
+	    -txn $c_logargs -errpfx CLIENT -errfile /dev/stderr \
+	    -rep_client -rep_transport \[list 2 replsend\]"
+	set clientenv [eval $env_cmd(C) $recargs]
 	error_check_good client_env [is_valid_env $clientenv] TRUE
 
 	# Put another quick item.
@@ -60,16 +97,8 @@ proc rep003 { method { tnum "03" } args } {
 
 	# Loop, processing first the master's messages, then the client's,
 	# until both queues are empty.
-	while { 1 } {
-		set nproced 0
-
-		incr nproced [replprocessqueue $masterenv 1]
-		incr nproced [replprocessqueue $clientenv 2]
-
-		if { $nproced == 0 } {
-			break
-		}
-	}
+	set envlist "{$masterenv 1} {$clientenv 2}"
+	process_msgs $envlist
 
 	rep003_check $clientenv A1 a-one
 	rep003_check $clientenv A2 a-two
@@ -78,7 +107,7 @@ proc rep003 { method { tnum "03" } args } {
 	replclear 2
 
 	# Now reopen the client after doing another put.
-	puts "\tRep0$tnum.b: Client restart."
+	puts "\tRep$tnum.b: Client restart."
 	rep003_put $masterenv B1 b-one
 
 	unset clientenv
@@ -86,6 +115,17 @@ proc rep003 { method { tnum "03" } args } {
 	    -rep_client -rep_transport [list 2 replsend]]
 	error_check_good client_env [is_valid_env $clientenv] TRUE
 
+	# Loop letting the client and master sync up and get the
+	# environment initialized.  It's a new client env so
+	# reinitialize the envlist as well.
+	set envlist "{$masterenv 1} {$clientenv 2}"
+	process_msgs $envlist
+
+	# The items from part A should be present at all times--
+	# if we roll them back, we've screwed up. [#5709]
+	rep003_check $clientenv A1 a-one
+	rep003_check $clientenv A2 a-two
+
 	rep003_put $masterenv B2 b-two
 
 	# Loop, processing first the master's messages, then the client's,
@@ -93,14 +133,14 @@ proc rep003 { method { tnum "03" } args } {
 	while { 1 } {
 		set nproced 0
 
+		incr nproced [replprocessqueue $masterenv 1]
+		incr nproced [replprocessqueue $clientenv 2]
+
 		# The items from part A should be present at all times--
 		# if we roll them back, we've screwed up. [#5709]
 		rep003_check $clientenv A1 a-one
 		rep003_check $clientenv A2 a-two
 
-		incr nproced [replprocessqueue $masterenv 1]
-		incr nproced [replprocessqueue $clientenv 2]
-
 		if { $nproced == 0 } {
 			break
 		}
@@ -114,7 +154,7 @@ proc rep003 { method { tnum "03" } args } {
 	replclear 2
 
 	# Now reopen the client after a recovery.
-	puts "\tRep0$tnum.c: Client restart after recovery."
+	puts "\tRep$tnum.c: Client restart after recovery."
 	rep003_put $masterenv C1 c-one
 
 	unset clientenv
@@ -122,6 +162,18 @@ proc rep003 { method { tnum "03" } args } {
 	    -recover -rep_client -rep_transport [list 2 replsend]]
 	error_check_good client_env [is_valid_env $clientenv] TRUE
 
+	# Loop, processing first the master's messages, then the client's,
+	# until both queues are empty.
+	set envlist "{$masterenv 1} {$clientenv 2}"
+	process_msgs $envlist
+
+	# The items from part A should be present at all times--
+	# if we roll them back, we've screwed up. [#5709]
+	rep003_check $clientenv A1 a-one
+	rep003_check $clientenv A2 a-two
+	rep003_check $clientenv B1 b-one
+	rep003_check $clientenv B2 b-two
+
 	rep003_put $masterenv C2 c-two
 
 	# Loop, processing first the master's messages, then the client's,
@@ -133,7 +185,7 @@ proc rep003 { method { tnum "03" } args } {
 		# if we roll them back, we've screwed up. [#5709]
 		rep003_check $clientenv A1 a-one
 		rep003_check $clientenv A2 a-two
-		rep003_check $clientenv B1 b-one 
+		rep003_check $clientenv B1 b-one
 		rep003_check $clientenv B2 b-two
 
 		incr nproced [replprocessqueue $masterenv 1]
@@ -152,7 +204,7 @@ proc rep003 { method { tnum "03" } args } {
 	replclear 2
 
 	# Now reopen the client after a catastrophic recovery.
-	puts "\tRep0$tnum.d: Client restart after catastrophic recovery."
+	puts "\tRep$tnum.d: Client restart after catastrophic recovery."
 	rep003_put $masterenv D1 d-one
 
 	unset clientenv
@@ -160,6 +212,10 @@ proc rep003 { method { tnum "03" } args } {
 	    -recover_fatal -rep_client -rep_transport [list 2 replsend]]
 	error_check_good client_env [is_valid_env $clientenv] TRUE
 
+	# Loop, processing first the master's messages, then the client's,
+	# until both queues are empty.
+	set envlist "{$masterenv 1} {$clientenv 2}"
+	process_msgs $envlist
 	rep003_put $masterenv D2 d-two
 
 	# Loop, processing first the master's messages, then the client's,
@@ -171,9 +227,9 @@ proc rep003 { method { tnum "03" } args } {
 		# if we roll them back, we've screwed up. [#5709]
 		rep003_check $clientenv A1 a-one
 		rep003_check $clientenv A2 a-two
-		rep003_check $clientenv B1 b-one 
+		rep003_check $clientenv B1 b-one
 		rep003_check $clientenv B2 b-two
-		rep003_check $clientenv C1 c-one 
+		rep003_check $clientenv C1 c-one
 		rep003_check $clientenv C2 c-two
 
 		incr nproced [replprocessqueue $masterenv 1]
diff --git a/storage/bdb/test/rep005.tcl b/storage/bdb/test/rep005.tcl
index e0515f1cd629cac6cb44b24774a59aafe37f7556..517fa955d5d838da9ccd537df6811723f166007a 100644
--- a/storage/bdb/test/rep005.tcl
+++ b/storage/bdb/test/rep005.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2002
+# Copyright (c) 2002-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: rep005.tcl,v 11.3 2002/08/08 18:13:13 sue Exp $
+# $Id: rep005.tcl,v 11.41 2004/10/15 15:41:56 sue Exp $
 #
 # TEST  rep005
 # TEST	Replication election test with error handling.
@@ -13,15 +13,40 @@
 # TEST  a proper master from amongst themselves, forcing errors at various
 # TEST	locations in the election path.
 
-proc rep005 { method { niter 10 } { tnum "05" } args } {
-	source ./include.tcl
-
-	if { [is_record_based $method] == 1 } {
+proc rep005 { method args } {
+	if { [is_btree $method] == 0 } {
 		puts "Rep005: Skipping for method $method."
 		return
 	}
 
+	set tnum "005"
+	set niter 10
 	set nclients 3
+	set logsets [create_logsets [expr $nclients + 1]]
+
+	# We don't want to run this with -recover - it takes too
+	# long and doesn't cover any new ground.
+	set recargs ""
+	foreach l $logsets {
+		puts "Rep$tnum ($recargs): Replication election\
+		    error test with $nclients clients."
+		puts -nonewline "Rep$tnum: Started at: "
+		puts [clock format [clock seconds] -format "%H:%M %D"]
+		puts "Rep$tnum: Master logs are [lindex $l 0]"
+		for { set i 0 } { $i < $nclients } { incr i } {
+			puts "Rep$tnum: Client $i logs are\
+			    [lindex $l [expr $i + 1]]"
+		}
+		rep005_sub $method $tnum \
+		    $niter $nclients $l $recargs $args
+	}
+}
+
+proc rep005_sub { method tnum niter nclients logset recargs largs } {
+	source ./include.tcl
+	global rand_init
+	error_check_good set_random_seed [berkdb srand $rand_init] 0
+
 	env_cleanup $testdir
 
 	set qdir $testdir/MSGQUEUEDIR
@@ -29,88 +54,63 @@ proc rep005 { method { niter 10 } { tnum "05" } args } {
 
 	set masterdir $testdir/MASTERDIR
 	file mkdir $masterdir
+	set m_logtype [lindex $logset 0]
+	set m_logargs [adjust_logargs $m_logtype]
+	set m_txnargs [adjust_txnargs $m_logtype]
 
 	for { set i 0 } { $i < $nclients } { incr i } {
 		set clientdir($i) $testdir/CLIENTDIR.$i
 		file mkdir $clientdir($i)
+		set c_logtype($i) [lindex $logset [expr $i + 1]]
+		set c_logargs($i) [adjust_logargs $c_logtype($i)]
+		set c_txnargs($i) [adjust_txnargs $c_logtype($i)]
 	}
 
-	puts "Rep0$tnum: Replication election test with $nclients clients."
-
 	# Open a master.
 	repladd 1
-	set env_cmd(M) "berkdb_env -create -log_max 1000000 -home \
-	    $masterdir -txn -rep_master -rep_transport \[list 1 replsend\]"
-	set masterenv [eval $env_cmd(M)]
+	set env_cmd(M) "berkdb_env -create -log_max 1000000 \
+	    -home $masterdir $m_logargs \
+	    $m_txnargs -rep_master -rep_transport \[list 1 replsend\]"
+# To debug elections, uncomment the line below and further below
+# for the clients to turn on verbose.  Also edit reputils.tcl
+# in proc start_election and swap the 2 commented lines with
+# their counterpart.
+#	set env_cmd(M) "berkdb_env_noerr -create -log_max 1000000 \
+#	    -home $masterdir $m_logargs \
+#	    $m_txnargs -rep_master \
+#	    -verbose {rep on} -errpfx MASTER -errfile /dev/stderr \
+#	    -rep_transport \[list 1 replsend\]"
+	set masterenv [eval $env_cmd(M) $recargs]
 	error_check_good master_env [is_valid_env $masterenv] TRUE
 
+	set envlist {}
+	lappend envlist "$masterenv 1"
+
 	# Open the clients.
 	for { set i 0 } { $i < $nclients } { incr i } {
 		set envid [expr $i + 2]
 		repladd $envid
 		set env_cmd($i) "berkdb_env -create -home $clientdir($i) \
-		    -txn -rep_client -rep_transport \[list $envid replsend\]"
-		set clientenv($i) [eval $env_cmd($i)]
+		    $c_logargs($i) $c_txnargs($i) -rep_client \
+		    -rep_transport \[list $envid replsend\]"
+#		set env_cmd($i) "berkdb_env_noerr -create -home $clientdir($i) \
+#		    -verbose {rep on} -errpfx CLIENT$i -errfile /dev/stderr \
+#		    $c_logargs($i) $c_txnargs($i) -rep_client \
+#		    -rep_transport \[list $envid replsend\]"
+		set clientenv($i) [eval $env_cmd($i) $recargs]
 		error_check_good \
 		    client_env($i) [is_valid_env $clientenv($i)] TRUE
+		lappend envlist "$clientenv($i) $envid"
 	}
 
 	# Run a modified test001 in the master.
-	puts "\tRep0$tnum.a: Running test001 in replicated env."
-	eval test001 $method $niter 0 $tnum 0 -env $masterenv $args
-
-	# Loop, processing first the master's messages, then the client's,
-	# until both queues are empty.
-	while { 1 } {
-		set nproced 0
-
-		incr nproced [replprocessqueue $masterenv 1]
-
-		for { set i 0 } { $i < $nclients } { incr i } { 	
-			set envid [expr $i + 2]
-			incr nproced [replprocessqueue $clientenv($i) $envid]
-		}
-
-		if { $nproced == 0 } {
-			break
-		}
-	}
-
-	# Verify the database in the client dir.
-	for { set i 0 } { $i < $nclients } { incr i } {
-		puts "\tRep0$tnum.b: Verifying contents of client database $i."
-		set testdir [get_home $masterenv]
-		set t1 $testdir/t1
-		set t2 $testdir/t2
-		set t3 $testdir/t3
-		open_and_dump_file test0$tnum.db $clientenv($i) $testdir/t1 \
-	    	    test001.check dump_file_direction "-first" "-next"
-
-		if { [string compare [convert_method $method] -recno] != 0 } {
-			filesort $t1 $t3
-		}
-		error_check_good diff_files($t2,$t3) [filecmp $t2 $t3] 0
-
-		verify_dir $clientdir($i) "\tRep0$tnum.c: " 0 0 1
-	}
-
-	# Make sure all the clients are synced up and ready to be good
-	# voting citizens.
-	error_check_good master_flush [$masterenv rep_flush] 0
-	while { 1 } {
-		set nproced 0
-		incr nproced [replprocessqueue $masterenv 1 0]
-		for { set i 0 } { $i < $nclients } { incr i } {
-			incr nproced [replprocessqueue $clientenv($i) \
-			    [expr $i + 2] 0]
-		}
-
-		if { $nproced == 0 } {
-			break
-		}
-	}
+	puts "\tRep$tnum.a: Running test001 in replicated env."
+	eval rep_test $method $masterenv NULL $niter 0 0 0 $largs
 
+	# Process all the messages and close the master.
+	process_msgs $envlist
 	error_check_good masterenv_close [$masterenv close] 0
+	set envlist [lreplace $envlist 0 0]
 
 	for { set i 0 } { $i < $nclients } { incr i } {
 		replclear [expr $i + 2]
@@ -119,107 +119,189 @@ proc rep005 { method { niter 10 } { tnum "05" } args } {
 	# We set up the error list for each client.  We know that the
 	# first client is the one calling the election, therefore, add
 	# the error location on sending the message (electsend) for that one.
-	set m "Rep0$tnum"
+	set m "Rep$tnum"
 	set count 0
-	foreach c0 { electinit electsend electvote1 electwait1 electvote2 \
-	    electwait2 } {
-		foreach c1 { electinit electvote1 electwait1 electvote2 \
-		    electwait2 } {
-			foreach c2 { electinit electvote1 electwait1 \
-			    electvote2 electwait2 } {
+	set win -1
+	#
+	# A full test can take a long time to run.  For normal testing
+	# pare it down a lot so that it runs in a shorter time.
+	#
+	set c0err { none electinit none none }
+	set c1err $c0err
+	set c2err $c0err
+	set numtests [expr [llength $c0err] * [llength $c1err] * \
+	    [llength $c2err]]
+	puts "\t$m.b: Starting $numtests election with error tests"
+	set last_win -1
+	set win -1
+	foreach c0 $c0err {
+		foreach c1 $c1err {
+			foreach c2 $c2err {
 				set elist [list $c0 $c1 $c2]
-				rep005_elect env_cmd clientenv $qdir $m \
-				    $count $elist
+				rep005_elect env_cmd envlist $qdir \
+				    $m $count win last_win $elist $logset
 				incr count
 			}
 		}
 	}
 
-	for { set i 0 } { $i < $nclients } { incr i } {
-		error_check_good clientenv_close($i) [$clientenv($i) close] 0
+	foreach pair $envlist {
+		set cenv [lindex $pair 0]
+		error_check_good cenv_close [$cenv close] 0
 	}
 
 	replclose $testdir/MSGQUEUEDIR
+	puts -nonewline \
+	    "Rep$tnum: Completed at: "
+	puts [clock format [clock seconds] -format "%H:%M %D"]
 }
 
-proc rep005_elect { ecmd cenv qdir msg count elist } {
-	global elect_timeout
+proc rep005_elect { ecmd celist qdir msg count \
+    winner lsn_lose elist logset} {
+	global elect_timeout elect_serial
+	global is_windows_test
 	upvar $ecmd env_cmd
-	upvar $cenv clientenv
+	upvar $celist envlist
+	upvar $winner win
+	upvar $lsn_lose last_win
 
-	set elect_timeout 1000000
+	set elect_timeout 5000000
 	set nclients [llength $elist]
+	set nsites [expr $nclients + 1]
 
-	for { set i 0 } { $i < $nclients } { incr i } { 	
+	set cl_list {}
+	foreach pair $envlist {
+		set id [lindex $pair 1]
+		set i [expr $id - 2]
+		set clientenv($i) [lindex $pair 0]
 		set err_cmd($i) [lindex $elist $i]
+		set elect_pipe($i) INVALID
+		replclear $id
+		lappend cl_list $i
 	}
-	puts "\t$msg.d.$count: Starting election with errors $elist"
-	set elect_pipe(0) [start_election $qdir $env_cmd(0) \
-	    [expr $nclients + 1] 20 $elect_timeout $err_cmd(0)]
-
-	tclsleep 1
-
-	# Process messages, and verify that the client with the highest
-	# priority--client #1--wins.
-	set got_newmaster 0
-	set tries 10
-	while { 1 } {
-		set nproced 0
-		set he 0
-		set nm 0
-		
-		for { set i 0 } { $i < $nclients } { incr i } { 	
-			set he 0
-			set envid [expr $i + 2]
-# puts "Processing queue for client $i"
-			incr nproced \
-			    [replprocessqueue $clientenv($i) $envid 0 he nm]
-			if { $he == 1 } {
-				# Client #1 has priority 100;  everyone else
-				if { $i == 1 } {
-					set pri 100
-				} else {
-					set pri 10
-				}
-				# error_check_bad client(0)_in_elect $i 0
-# puts "Starting election on client $i"
-				set elect_pipe($i) [start_election $qdir \
-			    	    $env_cmd($i) [expr $nclients + 1] $pri \
-				    $elect_timeout $err_cmd($i)]
-				set got_hold_elect($i) 1
-			}
-			if { $nm != 0 } {
-				error_check_good newmaster_is_master $nm \
-				    [expr 1 + 2]
-				set got_newmaster $nm
-
-				# If this env is the new master, it needs to
-				# configure itself as such--this is a different
-				# env handle from the one that performed the
-				# election.
-				if { $nm == $envid } {
-					error_check_good make_master($i) \
-					    [$clientenv($i) rep_start -master] \
-					    0
-				}
-			}
+
+	# Select winner.  We want to test biggest LSN wins, and secondarily
+	# highest priority wins.  If we already have a master, make sure
+	# we don't start a client in that master.
+	set el 0
+	if { $win == -1 } {
+		if { $last_win != -1 } {
+			set cl_list [lreplace $cl_list $last_win $last_win]
+			set el $last_win
+		}
+		set windex [berkdb random_int 0 [expr [llength $cl_list] - 1]]
+		set win [lindex $cl_list $windex]
+	} else {
+		# Easy case, if we have a master, the winner must be the
+		# same one as last time, just use $win.
+		# If client0 is the current existing master, start the
+		# election in client 1.
+		if {$win == 0} {
+			set el 1
 		}
+	}
+	# Winner has priority 100.  If we are testing LSN winning, the
+	# make sure the lowest LSN client has the highest priority.
+	# Everyone else has priority 10.
+	for { set i 0 } { $i < $nclients } { incr i } {
+		set crash($i) 0
+		if { $i == $win } {
+			set pri($i) 100
+		} elseif { $i == $last_win } {
+			set pri($i) 200
+		} else {
+			set pri($i) 10
+		}
+	}
 
-		# We need to wait around to make doubly sure that the
-		# election has finished...
-		if { $nproced == 0 } {
-			incr tries -1
-			if { $tries == 0 } {
-				break
+	puts "\t$msg.b.$count: Start election (win=client$win) $elist"
+	set msg $msg.c.$count
+	set nsites $nclients
+	set nvotes $nsites
+	run_election env_cmd envlist err_cmd pri crash \
+	    $qdir $msg $el $nsites $nvotes $nclients $win
+	#
+	# Sometimes test elections with an existing master.
+	# Other times test elections without master by closing the
+	# master we just elected and creating a new client.
+	# We want to weight it to close the new master.  So, use
+	# a list to cause closing about 70% of the time.
+	#
+	set close_list { 0 0 0 1 1 1 1 1 1 1}
+	set close_len [expr [llength $close_list] - 1]
+	set close_index [berkdb random_int 0 $close_len]
+	if { [lindex $close_list $close_index] == 1 } {
+		puts -nonewline "\t\t$msg: Closing "
+		error_check_good newmaster_close [$clientenv($win) close] 0
+		#
+		# If the next test should win via LSN then remove the
+		# env before starting the new client so that we
+		# can guarantee this client doesn't win the next one.
+		set lsn_win { 0 0 0 0 1 1 1 1 1 1 }
+		set lsn_len [expr [llength $lsn_win] - 1]
+		set lsn_index [berkdb random_int 0 $lsn_len]
+		set rec_arg ""
+		set win_inmem [expr [string compare [lindex $logset \
+		    [expr $win + 1]] in-memory] == 0]
+		if { [lindex $lsn_win $lsn_index] == 1 } {
+			set last_win $win
+			set dirindex [lsearch -exact $env_cmd($win) "-home"]
+			incr dirindex
+			set lsn_dir [lindex $env_cmd($win) $dirindex]
+			env_cleanup $lsn_dir
+			puts -nonewline "and cleaning "
+		} else {
+			#
+			# If we're not cleaning the env, decide if we should
+			# run recovery upon reopening the env.  This causes
+			# two things:
+			# 1. Removal of region files which forces the env
+			# to read its __db.rep.egen file.
+			# 2. Adding a couple log records, so this client must
+			# be the next winner as well since it'll have the
+			# biggest LSN.
+			#
+			set rec_win { 0 0 0 0 0 0 1 1 1 1 }
+			set rec_len [expr [llength $rec_win] - 1]
+			set rec_index [berkdb random_int 0 $rec_len]
+			if { [lindex $rec_win $rec_index] == 1 } {
+				puts -nonewline "and recovering "
+				set rec_arg "-recover"
+				#
+				# If we're in memory and about to run
+				# recovery, we force ourselves not to win
+				# the next election because recovery will
+				# blow away the entire log in memory.
+				# However, we don't skip this entirely
+				# because we still want to force reading
+				# of __db.rep.egen.
+				#
+				if { $win_inmem } {
+					set last_win $win
+				} else {
+					set last_win -1
+				}
 			} else {
-				tclsleep 1
+				set last_win -1
 			}
 		}
+		puts "new master, new client $win"
+		set clientenv($win) [eval $env_cmd($win) $rec_arg]
+		error_check_good cl($win) [is_valid_env $clientenv($win)] TRUE
+		#
+		# Since we started a new client, we need to replace it
+		# in the message processing list so that we get the
+		# new Tcl handle name in there.
+		set newel "$clientenv($win) [expr $win + 2]"
+		set envlist [lreplace $envlist $win $win $newel]
+		if { $rec_arg == "" || $win_inmem } {
+			set win -1
+		}
+		#
+		# Since we started a new client we want to give them
+		# all a chance to process everything outstanding before
+		# the election on the next iteration.
+		#
+		process_msgs $envlist
 	}
-
-	# Verify that client #1 is actually the winner.
-	error_check_good "client 1 wins" $got_newmaster [expr 1 + 2]
-
-	cleanup_elections
-
 }
diff --git a/storage/bdb/test/reputils.tcl b/storage/bdb/test/reputils.tcl
index 340e359f26d296719d8f065b0d2a4590866fe719..f25da575ad17aea4667d56aa57526c4da2ff638f 100644
--- a/storage/bdb/test/reputils.tcl
+++ b/storage/bdb/test/reputils.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2001-2002
+# Copyright (c) 2001-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: reputils.tcl,v 11.34 2002/08/12 17:54:18 sandstro Exp $
+# $Id: reputils.tcl,v 11.84 2004/11/03 18:50:52 carol Exp $
 #
 # Replication testing utilities
 
@@ -33,16 +33,82 @@ global queueenv
 # messages.
 global queuedbs
 global machids
-
+global perm_response_list
+set perm_response_list {}
+global perm_sent_list
+set perm_sent_list {}
 global elect_timeout
 set elect_timeout 50000000
 set drop 0
 
+# The default for replication testing is for logs to be on-disk.
+# Mixed-mode log testing provides a mixture of on-disk and
+# in-memory logging, or even all in-memory.  When testing on a
+# 1-master/1-client test, we try all four options.  On a test
+# with more clients, we still try four options, randomly
+# selecting whether the later clients are on-disk or in-memory.
+#
+
+global mixed_mode_logging
+set mixed_mode_logging 0
+
+proc create_logsets { nsites } {
+	global mixed_mode_logging
+	global logsets
+	global rand_init
+
+	error_check_good set_random_seed [berkdb srand $rand_init] 0
+	if { $mixed_mode_logging == 0 } {
+		set loglist {}
+		for { set i 0 } { $i < $nsites } { incr i } {
+			lappend loglist "on-disk"
+		}
+		set logsets [list $loglist]
+	}
+	if { $mixed_mode_logging == 1 } {
+		set set1 {on-disk on-disk}
+		set set2 {on-disk in-memory}
+		set set3 {in-memory on-disk}
+		set set4 {in-memory in-memory}
+
+		# Start with nsites at 2 since we already set up
+		# the master and first client.
+		for { set i 2 } { $i < $nsites } { incr i } {
+			foreach set { set1 set2 set3 set4 } {
+				if { [berkdb random_int 0 1] == 0 } {
+					lappend $set "on-disk"
+				} else {
+					lappend $set "in-memory"
+				}
+			}
+		}
+		set logsets [list $set1 $set2 $set3 $set4]
+	}
+	return $logsets
+}
+
+proc run_mixedmode { method test {display 0} {run 1} \
+    {outfile stdout} {largs ""} } {
+	global mixed_mode_logging
+	set mixed_mode_logging 1
+
+	set prefix [string range $test 0 2]
+	if { $prefix != "rep" } {
+		puts "Skipping mixed-mode log testing for non-rep test."
+		set mixed_mode_logging 0
+		return
+	}
+
+	eval run_method $method $test $display $run $outfile $largs
+
+	# Reset to default values after run.
+	set mixed_mode_logging 0
+}
+
 # Create the directory structure for replication testing.
 # Open the master and client environments; store these in the global repenv
 # Return the master's environment: "-env masterenv"
-#
-proc repl_envsetup { envargs largs tnum {nclients 1} {droppct 0} { oob 0 } } {
+proc repl_envsetup { envargs largs test {nclients 1} {droppct 0} { oob 0 } } {
 	source ./include.tcl
 	global clientdir
 	global drop drop_msg
@@ -75,10 +141,17 @@ proc repl_envsetup { envargs largs tnum {nclients 1} {droppct 0} { oob 0 } } {
 	# but big enough so that the tests that use binary files
 	# as keys/data can run.
 	#
-	set lmax [expr 3 * 1024 * 1024]
-	set masterenv [eval {berkdb_env -create -log_max $lmax} $envargs \
-	    {-home $masterdir -txn -rep_master -rep_transport \
-	    [list 1 replsend]}]
+	set logmax [expr 3 * 1024 * 1024]
+	set ma_cmd "berkdb_env -create -log_max $logmax $envargs \
+	    -lock_max 10000 \
+	    -home $masterdir -txn nosync -rep_master -rep_transport \
+	    \[list 1 replsend\]"
+#	set ma_cmd "berkdb_env_noerr -create -log_max $logmax $envargs \
+#	    -lock_max 10000 -verbose {rep on} -errfile /dev/stderr \
+#	    -errpfx $masterdir \
+#	    -home $masterdir -txn nosync -rep_master -rep_transport \
+#	    \[list 1 replsend\]"
+	set masterenv [eval $ma_cmd]
 	error_check_good master_env [is_valid_env $masterenv] TRUE
 	set repenv(master) $masterenv
 
@@ -86,10 +159,16 @@ proc repl_envsetup { envargs largs tnum {nclients 1} {droppct 0} { oob 0 } } {
 	for { set i 0 } { $i < $nclients } { incr i } {
 		set envid [expr $i + 2]
 		repladd $envid
-		set clientenv [eval {berkdb_env -create} $envargs -txn \
-		    {-cachesize { 0 10000000 0 }} -lock_max 10000 \
-		    {-home $clientdir($i) -rep_client -rep_transport \
-		    [list $envid replsend]}]
+                set cl_cmd "berkdb_env -create $envargs -txn nosync \
+		    -cachesize { 0 10000000 0 } -lock_max 10000 \
+		     -home $clientdir($i) -rep_client -rep_transport \
+		    \[list $envid replsend\]"
+#		set cl_cmd "berkdb_env_noerr -create $envargs -txn nosync \
+#		    -cachesize { 0 10000000 0 } -lock_max 10000 \
+#		    -home $clientdir($i) -rep_client -rep_transport \
+#		    \[list $envid replsend\] -verbose {rep on} \
+#		    -errfile /dev/stderr -errpfx $clientdir($i)"
+                set clientenv [eval $cl_cmd]
 		error_check_good client_env [is_valid_env $clientenv] TRUE
 		set repenv($i) $clientenv
 	}
@@ -97,7 +176,7 @@ proc repl_envsetup { envargs largs tnum {nclients 1} {droppct 0} { oob 0 } } {
 	append largs " -env $masterenv "
 
 	# Process startup messages
-	repl_envprocq $tnum $nclients $oob
+	repl_envprocq $test $nclients $oob
 
 	return $largs
 }
@@ -109,8 +188,7 @@ proc repl_envsetup { envargs largs tnum {nclients 1} {droppct 0} { oob 0 } } {
 # with out-of-order delivery.  The replprocess procedure actually does
 # the real work of processing the queue -- this routine simply iterates
 # over the various queues and does the initial setup.
-
-proc repl_envprocq { tnum { nclients 1 } { oob 0 }} {
+proc repl_envprocq { test { nclients 1 } { oob 0 }} {
 	global repenv
 	global drop
 
@@ -122,9 +200,8 @@ proc repl_envprocq { tnum { nclients 1 } { oob 0 }} {
 	}
 	error_check_good i_nclients $nclients $i
 
-	set name [format "Repl%03d" $tnum]
 	berkdb debug_check
-	puts -nonewline "\t$name: Processing master/$i client queues"
+	puts -nonewline "\t$test: Processing master/$i client queues"
 	set rand_skip 0
 	if { $oob } {
 		puts " out-of-order"
@@ -157,18 +234,17 @@ proc repl_envprocq { tnum { nclients 1 } { oob 0 }} {
 			# number of messages that were enqueued.
 			for { set i 0 } { $i < $nclients } { incr i } {
 				set clientenv $repenv($i)
-				set stats [$clientenv rep_stat]
-				set queued [getstats $stats  \
-				   {Total log records queued}]
+				set queued [stat_field $clientenv rep_stat \
+				   "Total log records queued"]
 				error_check_bad queued_stats \
 				    $queued -1
-				set requested [getstats $stats \
-				   {Log records requested}]
+				set requested [stat_field $clientenv rep_stat \
+				   "Log records requested"]
 				error_check_bad requested_stats \
 				    $requested -1
 				if { $queued != 0 && $do_check != 0 } {
 					error_check_good num_requested \
-					    [expr $requested < $queued] 1
+					    [expr $requested <= $queued] 1
 				}
 
 				$clientenv rep_request 1 1
@@ -182,7 +258,7 @@ proc repl_envprocq { tnum { nclients 1 } { oob 0 }} {
 				set do_check 0
 				$masterenv rep_flush
 				berkdb debug_check
-				puts "\t$name: Flushing Master"
+				puts "\t$test: Flushing Master"
 			} else {
 				break
 			}
@@ -200,8 +276,7 @@ proc repl_envprocq { tnum { nclients 1 } { oob 0 }} {
 
 # Verify that the directories in the master are exactly replicated in
 # each of the client environments.
-
-proc repl_envver0 { tnum method { nclients 1 } } {
+proc repl_envver0 { test method { nclients 1 } } {
 	global clientdir
 	global masterdir
 	global repenv
@@ -212,7 +287,6 @@ proc repl_envver0 { tnum method { nclients 1 } } {
 	set t2 $masterdir/t2
 	set t3 $masterdir/t3
 	set omethod [convert_method $method]
-	set name [format "Repl%03d" $tnum]
 
 	#
 	# We are interested in the keys of whatever databases are present
@@ -237,8 +311,7 @@ proc repl_envver0 { tnum method { nclients 1 } } {
 			file rename -force $t3 $t2
 		}
 		for { set i 0 } { $i < $nclients } { incr i } {
-			puts "\t$name: Verifying client $i database \
-			    $testfile contents."
+	puts "\t$test: Verifying client $i database $testfile contents."
 			open_and_dump_file $testfile $repenv($i) \
 			    $t1 repl_noop dump_file_direction "-first" "-next"
 
@@ -254,14 +327,12 @@ proc repl_envver0 { tnum method { nclients 1 } } {
 
 # Remove all the elements from the master and verify that these
 # deletions properly propagated to the clients.
-
-proc repl_verdel { tnum method { nclients 1 } } {
+proc repl_verdel { test method { nclients 1 } } {
 	global clientdir
 	global masterdir
 	global repenv
 
 	# Delete all items in the master.
-	set name [format "Repl%03d" $tnum]
 	set cwd [pwd]
 	cd $masterdir
 	set stat [catch {glob test*.db} dbs]
@@ -270,7 +341,7 @@ proc repl_verdel { tnum method { nclients 1 } } {
 		return
 	}
 	foreach testfile $dbs {
-		puts "\t$name: Deleting all items from the master."
+		puts "\t$test: Deleting all items from the master."
 		set txn [$repenv(master) txn]
 		error_check_good txn_begin [is_valid_txn $txn \
 		    $repenv(master)] TRUE
@@ -287,11 +358,11 @@ proc repl_verdel { tnum method { nclients 1 } } {
 		error_check_good txn_commit [$txn commit] 0
 		error_check_good db_close [$db close] 0
 
-		repl_envprocq $tnum $nclients
+		repl_envprocq $test $nclients
 
 		# Check clients.
 		for { set i 0 } { $i < $nclients } { incr i } {
-			puts "\t$name: Verifying emptiness of client database $i."
+			puts "\t$test: Verifying client database $i is empty."
 
 			set db [berkdb_open -env $repenv($i) $testfile]
 			error_check_good reopen_client($i) \
@@ -316,7 +387,7 @@ proc repl_noop { k d } {
 }
 
 # Close all the master and client environments in a replication test directory.
-proc repl_envclose { tnum envargs } {
+proc repl_envclose { test envargs } {
 	source ./include.tcl
 	global clientdir
 	global encrypt
@@ -333,9 +404,8 @@ proc repl_envclose { tnum envargs } {
 	# process messages in order to flush all the clients.
 	set drop 0
 	set do_check 0
-	set name [format "Repl%03d" $tnum]
 	berkdb debug_check
-	puts "\t$name: Checkpointing master."
+	puts "\t$test: Checkpointing master."
 	error_check_good masterenv_ckp [$repenv(master) txn_checkpoint] 0
 
 	# Count clients.
@@ -344,13 +414,13 @@ proc repl_envclose { tnum envargs } {
 			break
 		}
 	}
-	repl_envprocq $tnum $ncli
+	repl_envprocq $test $ncli
 
 	error_check_good masterenv_close [$repenv(master) close] 0
-	verify_dir $masterdir "\t$name: " 0 0 1
+	verify_dir $masterdir "\t$test: " 0 0 1
 	for { set i 0 } { $i < $ncli } { incr i } {
 		error_check_good client($i)_close [$repenv($i) close] 0
-		verify_dir $clientdir($i) "\t$name: " 0 0 1
+		verify_dir $clientdir($i) "\t$test: " 0 0 1
 	}
 	replclose $testdir/MSGQUEUEDIR
 
@@ -374,7 +444,7 @@ proc replsetup { queuedir } {
 
 	file mkdir $queuedir
 	set queueenv \
-	    [berkdb_env -create -txn -lock_max 20000 -home $queuedir]
+	    [berkdb_env -create -txn nosync -lock_max 20000 -home $queuedir]
 	error_check_good queueenv [is_valid_env $queueenv] TRUE
 
 	if { [info exists queuedbs] } {
@@ -386,9 +456,14 @@ proc replsetup { queuedir } {
 }
 
 # Send function for replication.
-proc replsend { control rec fromid toid } {
+proc replsend { control rec fromid toid flags lsn } {
 	global queuedbs queueenv machids
 	global drop drop_msg
+	global perm_sent_list
+	if { [llength $perm_sent_list] != 0 && $flags == "perm" } {
+#		puts "replsend sent perm message, LSN $lsn"
+		lappend perm_sent_list $lsn
+	}
 
 	#
 	# If we are testing with dropped messages, then we drop every
@@ -428,7 +503,7 @@ proc replsend { control rec fromid toid } {
 	return 0
 }
 
-# Nuke all the pending messages for a particular site.
+# Discard all the pending messages for a particular site.
 proc replclear { machid } {
 	global queuedbs queueenv
 
@@ -462,14 +537,32 @@ proc repladd { machid } {
 	lappend machids $machid
 }
 
+# Acquire a handle to work with an existing machine's replication
+# queue.  This is for situations where more than one process
+# is working with a message queue.  In general, having more than one
+# process handle the queue is wrong.  However, in order to test some
+# things, we need two processes (since Tcl doesn't support threads).  We
+# go to great pain in the test harness to make sure this works, but we
+# don't let customers do it.
+proc repljoin { machid } {
+	global queueenv queuedbs machids
+
+	set queuedbs($machid) [berkdb open -auto_commit \
+	    -env $queueenv repqueue$machid.db]
+	error_check_good repqueue_create [is_valid_db $queuedbs($machid)] TRUE
+
+	lappend machids $machid
+}
+
 # Process a queue of messages, skipping every "skip_interval" entry.
 # We traverse the entire queue, but since we skip some messages, we
 # may end up leaving things in the queue, which should get picked up
 # on a later run.
-
-proc replprocessqueue { dbenv machid { skip_interval 0 } \
-    { hold_electp NONE } { newmasterp NONE } } {
+proc replprocessqueue { dbenv machid { skip_interval 0 } { hold_electp NONE } \
+    { newmasterp NONE } { dupmasterp NONE } { errp NONE } } {
 	global queuedbs queueenv errorCode
+	global perm_response_list
+	global startup_done
 
 	# hold_electp is a call-by-reference variable which lets our caller
 	# know we need to hold an election.
@@ -485,9 +578,30 @@ proc replprocessqueue { dbenv machid { skip_interval 0 } \
 	}
 	set newmaster 0
 
+	# dupmasterp is a call-by-reference variable which lets our caller
+	# know we have a duplicate master.
+	if { [string compare $dupmasterp NONE] != 0 } {
+		upvar $dupmasterp dupmaster
+	}
+	set dupmaster 0
+
+	# errp is a call-by-reference variable which lets our caller
+	# know we have gotten an error (that they expect).
+	if { [string compare $errp NONE] != 0 } {
+		upvar $errp errorp
+	}
+	set errorp 0
+
 	set nproced 0
 
 	set txn [$queueenv txn]
+
+	# If we are running separate processes, the second process has
+	# to join an existing message queue.
+	if { [info exists queuedbs($machid)] == 0 } {
+		repljoin $machid
+	}
+
 	set dbc [$queuedbs($machid) cursor -txn $txn]
 
 	error_check_good process_dbc($machid) \
@@ -495,8 +609,9 @@ proc replprocessqueue { dbenv machid { skip_interval 0 } \
 
 	for { set dbt [$dbc get -first] } \
 	    { [llength $dbt] != 0 } \
-	    { set dbt [$dbc get -next] } {
+	    { } {
 		set data [lindex [lindex $dbt 0] 1]
+		set recno [lindex [lindex $dbt 0] 0]
 
 		# If skip_interval is nonzero, we want to process messages
 		# out of order.  We do this in a simple but slimy way--
@@ -516,27 +631,44 @@ proc replprocessqueue { dbenv machid { skip_interval 0 } \
 		if { $skip_interval != 0 } {
 			if { $nproced % $skip_interval == 1 } {
 				incr nproced
+				set dbt [$dbc get -next]
 				continue
 			}
 		}
 
+		# We need to remove the current message from the queue,
+		# because we're about to end the transaction and someone
+		# else processing messages might come in and reprocess this
+		# message which would be bad.
+		error_check_good queue_remove [$dbc del] 0
+
 		# We have to play an ugly cursor game here:  we currently
 		# hold a lock on the page of messages, but rep_process_message
 		# might need to lock the page with a different cursor in
-		# order to send a response.  So save our recno, close
+		# order to send a response.  So save the next recno, close
 		# the cursor, and then reopen and reset the cursor.
-		set recno [lindex [lindex $dbt 0] 0]
+		# If someone else is processing this queue, our entry might
+		# have gone away, and we need to be able to handle that.
+
 		error_check_good dbc_process_close [$dbc close] 0
 		error_check_good txn_commit [$txn commit] 0
+
 		set ret [catch {$dbenv rep_process_message \
 		    [lindex $data 2] [lindex $data 0] [lindex $data 1]} res]
-		set txn [$queueenv txn]
-		set dbc [$queuedbs($machid) cursor -txn $txn]
-		set dbt [$dbc get -set $recno]
+
+		# Save all ISPERM and NOTPERM responses so we can compare their
+		# LSNs to the LSN in the log.  The variable perm_response_list
+		# holds the entire response so we can extract responses and
+		# LSNs as needed.
+		#
+		if { [llength $perm_response_list] != 0 && \
+		    ([is_substr $res ISPERM] || [is_substr $res NOTPERM]) } {
+			lappend perm_response_list $res
+		}
 
 		if { $ret != 0 } {
-			if { [is_substr $res DB_REP_HOLDELECTION] } {
-				set hold_elect 1
+			if { [string compare $errp NONE] != 0 } {
+				set errorp "$dbenv $machid $res"
 			} else {
 				error "FAIL:[timestamp]\
 				    rep_process_message returned $res"
@@ -545,23 +677,56 @@ proc replprocessqueue { dbenv machid { skip_interval 0 } \
 
 		incr nproced
 
-		$dbc del
+		# Now, re-establish the cursor position.  We fetch the
+		# current record number.  If there is something there,
+		# that is the record for the next iteration.  If there
+		# is nothing there, then we've consumed the last item
+		# in the queue.
 
-		if { $ret == 0 && $res != 0 } {
-			if { [is_substr $res DB_REP_NEWSITE] } {
-				# NEWSITE;  do nothing.
-			} else {
-				set newmaster $res
+		set txn [$queueenv txn]
+		set dbc [$queuedbs($machid) cursor -txn $txn]
+		set dbt [$dbc get -set_range $recno]
+
+		if { $ret == 0 } {
+			set rettype [lindex $res 0]
+			set retval [lindex $res 1]
+			#
+			# Do nothing for 0 and NEWSITE
+			#
+			if { [is_substr $rettype STARTUPDONE] } {
+				set startup_done 1
+			}
+			if { [is_substr $rettype HOLDELECTION] } {
+				set hold_elect 1
+			}
+			if { [is_substr $rettype DUPMASTER] } {
+				set dupmaster "1 $dbenv $machid"
+			}
+			if { [is_substr $rettype NOTPERM] || \
+			    [is_substr $rettype ISPERM] } {
+				set lsnfile [lindex $retval 0]
+				set lsnoff [lindex $retval 1]
+			}
+			if { [is_substr $rettype NEWMASTER] } {
+				set newmaster $retval
 				# Break as soon as we get a NEWMASTER message;
 				# our caller needs to handle it.
 				break
 			}
 		}
 
+		if { $errorp != 0 } {
+			# Break also on an error, caller wants to handle it.
+			break
+		}
 		if { $hold_elect == 1 } {
 			# Break also on a HOLDELECTION, for the same reason.
 			break
 		}
+		if { $dupmaster == 1 } {
+			# Break also on a DUPMASTER, for the same reason.
+			break
+		}
 
 	}
 
@@ -609,38 +774,337 @@ global elections_in_progress
 set elect_serial 0
 
 # Start an election in a sub-process.
-proc start_election { qdir envstring nsites pri timeout {err "none"}} {
+proc start_election \
+    { pfx qdir envstring nsites nvotes pri timeout {err "none"} {crash 0}} {
 	source ./include.tcl
 	global elect_serial elect_timeout elections_in_progress machids
 
-	incr elect_serial
+	set filelist {}
+	set ret [catch {glob $testdir/ELECTION*.$elect_serial} result]
+	if { $ret == 0 } {
+		set filelist [concat $filelist $result]
+	}
+	foreach f $filelist {
+		fileremove -f $f
+	}
 
-	set t [open "|$tclsh_path >& $testdir/ELECTION_OUTPUT.$elect_serial" w]
-
-	puts $t "source $test_path/test.tcl"
-	puts $t "replsetup $qdir"
-	foreach i $machids { puts $t "repladd $i" }
-	puts $t "set env_cmd \{$envstring\}"
-	puts $t "set dbenv \[eval \$env_cmd -errfile \
-	    $testdir/ELECTION_ERRFILE.$elect_serial -errpfx FAIL: \]"
-# puts "Start election err $err, env $envstring"
-	puts $t "\$dbenv test abort $err"
-	puts $t "set res \[catch \{\$dbenv rep_elect $nsites $pri \
+	set oid [open $testdir/ELECTION_SOURCE.$elect_serial w]
+
+	puts $oid "source $test_path/test.tcl"
+	puts $oid "replsetup $qdir"
+	foreach i $machids { puts $oid "repladd $i" }
+	puts $oid "set env_cmd \{$envstring\}"
+#	puts $oid "set dbenv \[eval \$env_cmd -errfile \
+#	    $testdir/ELECTION_ERRFILE.$elect_serial -errpfx $pfx \]"
+	puts $oid "set dbenv \[eval \$env_cmd -errfile \
+	    /dev/stdout -errpfx $pfx \]"
+	puts $oid "\$dbenv test abort $err"
+	puts $oid "set res \[catch \{\$dbenv rep_elect $nsites $nvotes $pri \
 	    $elect_timeout\} ret\]"
-	if { $err != "none" } {
-		puts $t "\$dbenv test abort none"
-		puts $t "set res \[catch \{\$dbenv rep_elect $nsites $pri \
-		    $elect_timeout\} ret\]"
+	puts $oid "set r \[open \$testdir/ELECTION_RESULT.$elect_serial w\]"
+	puts $oid "if \{\$res == 0 \} \{"
+	puts $oid "puts \$r \"NEWMASTER \$ret\""
+	puts $oid "\} else \{"
+	puts $oid "puts \$r \"ERROR \$ret\""
+	puts $oid "\}"
+	#
+	# This loop calls rep_elect a second time with the error cleared.
+	# We don't want to do that if we are simulating a crash.
+	if { $err != "none" && $crash != 1 } {
+		puts $oid "\$dbenv test abort none"
+		puts $oid "set res \[catch \{\$dbenv rep_elect $nsites \
+		    $nvotes $pri $elect_timeout\} ret\]"
+		puts $oid "if \{\$res == 0 \} \{"
+		puts $oid "puts \$r \"NEWMASTER \$ret\""
+		puts $oid "\} else \{"
+		puts $oid "puts \$r \"ERROR \$ret\""
+		puts $oid "\}"
 	}
+	puts $oid "close \$r"
+	close $oid
+
+#	set t [open "|$tclsh_path >& $testdir/ELECTION_OUTPUT.$elect_serial" w]
+	set t [open "|$tclsh_path" w]
+	puts $t "source ./include.tcl"
+	puts $t "source $testdir/ELECTION_SOURCE.$elect_serial"
 	flush $t
 
 	set elections_in_progress($elect_serial) $t
 	return $elect_serial
 }
 
+proc setpriority { priority nclients winner {start 0} } {
+	upvar $priority pri
+
+	for { set i $start } { $i < [expr $nclients + $start] } { incr i } {
+		if { $i == $winner } {
+			set pri($i) 100
+		} else {
+			set pri($i) 10
+		}
+	}
+}
+
+# run_election has the following arguments:
+# Arrays:
+#	ecmd 		Array of the commands for setting up each client env.
+#	cenv		Array of the handles to each client env.
+#	errcmd		Array of where errors should be forced.
+#	priority	Array of the priorities of each client env.
+#	crash		If an error is forced, should we crash or recover?
+# The upvar command takes care of making these arrays available to
+# the procedure.
+#
+# Ordinary variables:
+# 	qdir		Directory where the message queue is located.
+#	msg		Message prefixed to the output.
+#	elector		This client calls the first election.
+#	nsites		Number of sites in the replication group.
+#	nvotes		Number of votes required to win the election.
+# 	nclients	Number of clients participating in the election.
+#	win		The expected winner of the election.
+#	reopen		Should the new master (i.e. winner) be closed
+#			and reopened as a client?
+#	dbname		Name of the underlying database.  Defaults to
+# 			the name of the db created by rep_test.
+#
+proc run_election { ecmd celist errcmd priority crsh qdir msg elector \
+    nsites nvotes nclients win {reopen 0} {dbname "test.db"} } {
+	global elect_timeout elect_serial
+	global is_hp_test
+	global is_windows_test
+	global rand_init
+	upvar $ecmd env_cmd
+	upvar $celist cenvlist
+	upvar $errcmd err_cmd
+	upvar $priority pri
+	upvar $crsh crash
+
+	set elect_timeout 5000000
+
+	foreach pair $cenvlist {
+		set id [lindex $pair 1]
+		set i [expr $id - 2]
+		set elect_pipe($i) INVALID
+		replclear $id
+	}
+
+	#
+	# XXX
+	# We need to somehow check for the warning if nvotes is not
+	# a majority.  Problem is that warning will go into the child
+	# process' output.  Furthermore, we need a mechanism that can
+	# handle both sending the output to a file and sending it to
+	# /dev/stderr when debugging without failing the
+	# error_check_good check.
+	#
+	puts "\t\t$msg.1: Election with nsites=$nsites,\
+	    nvotes=$nvotes, nclients=$nclients"
+	puts "\t\t$msg.2: First elector is $elector,\
+	    expected winner is $win (eid [expr $win + 2])"
+	incr elect_serial
+	set pfx "CHILD$elector.$elect_serial"
+	# Windows and HP-UX require a longer timeout.
+	if { $is_windows_test == 1 || $is_hp_test == 1 } {
+		set elect_timeout [expr $elect_timeout * 3]
+	}
+	set elect_pipe($elector) [start_election \
+	    $pfx $qdir $env_cmd($elector) $nsites $nvotes $pri($elector) \
+	    $elect_timeout $err_cmd($elector) $crash($elector)]
+
+	tclsleep 2
+
+	set got_newmaster 0
+	set tries [expr [expr $elect_timeout * 4] / 1000000]
+
+	# If we're simulating a crash, skip the while loop and
+	# just give the initial election a chance to complete.
+	set crashing 0
+	for { set i 0 } { $i < $nclients } { incr i } {
+		if { $crash($i) == 1 } {
+			set crashing 1
+		}
+	}
+
+	if { $crashing == 1 } {
+		tclsleep 10
+	} else {
+		while { 1 } {
+			set nproced 0
+			set he 0
+			set nm 0
+			set nm2 0
+
+			foreach pair $cenvlist {
+				set he 0
+				set envid [lindex $pair 1]
+				set i [expr $envid - 2]
+				set clientenv($i) [lindex $pair 0]
+				set child_done [check_election $elect_pipe($i) nm2]
+				if { $got_newmaster == 0 && $nm2 != 0 } {
+					error_check_good newmaster_is_master2 $nm2 \
+					    [expr $win + 2]
+					set got_newmaster $nm2
+
+					# If this env is the new master, it needs to
+					# configure itself as such--this is a different
+					# env handle from the one that performed the
+					# election.
+					if { $nm2 == $envid } {
+						error_check_good make_master($i) \
+						    [$clientenv($i) rep_start -master] \
+						    0
+					}
+				}
+				incr nproced \
+				    [replprocessqueue $clientenv($i) $envid 0 he nm]
+# puts "Tries $tries: Processed queue for client $i, $nproced msgs he $he nm $nm nm2 $nm2"
+				if { $he == 1 } {
+					#
+					# Only close down the election pipe if the
+					# previously created one is done and
+					# waiting for new commands, otherwise
+					# if we try to close it while it's in
+					# progress we hang this main tclsh.
+					#
+					if { $elect_pipe($i) != "INVALID" && \
+					    $child_done == 1 } {
+						close_election $elect_pipe($i)
+						set elect_pipe($i) "INVALID"
+					}
+# puts "Starting election on client $i"
+					if { $elect_pipe($i) == "INVALID" } {
+						incr elect_serial
+						set pfx "CHILD$i.$elect_serial"
+						set elect_pipe($i) [start_election \
+						    $pfx $qdir \
+						    $env_cmd($i) $nsites \
+						    $nvotes $pri($i) $elect_timeout]
+						set got_hold_elect($i) 1
+					}
+				}
+				if { $nm != 0 } {
+					error_check_good newmaster_is_master $nm \
+					    [expr $win + 2]
+					set got_newmaster $nm
+
+					# If this env is the new master, it needs to
+					# configure itself as such--this is a different
+					# env handle from the one that performed the
+					# election.
+					if { $nm == $envid } {
+						error_check_good make_master($i) \
+						    [$clientenv($i) rep_start -master] \
+						    0
+						# Occasionally force new log records
+						# to be written.
+						set write [berkdb random_int 1 10]
+						if { $write == 1 } {
+							set db [berkdb_open -env \
+							    $clientenv($i) \
+							    -auto_commit $dbname]
+							error_check_good dbopen \
+							    [is_valid_db $db] TRUE
+							error_check_good dbclose \
+							    [$db close] 0
+						}
+					}
+				}
+			}
+
+			# We need to wait around to make doubly sure that the
+			# election has finished...
+			if { $nproced == 0 } {
+				incr tries -1
+				if { $tries == 0 } {
+					break
+				} else {
+					tclsleep 1
+				}
+			} else {
+				set tries $tries
+			}
+		}
+
+		# Verify that expected winner is actually the winner.
+		error_check_good "client $win wins" $got_newmaster [expr $win + 2]
+	}
+
+	cleanup_elections
+
+	#
+	# Make sure we've really processed all the post-election
+	# sync-up messages.  If we're simulating a crash, don't process
+	# any more messages.
+	#
+	if { $crashing == 0 } {
+		process_msgs $cenvlist
+	}
+
+	if { $reopen == 1 } {
+		puts "\t\t$msg.3: Closing new master and reopening as client"
+		error_check_good newmaster_close [$clientenv($win) close] 0
+
+		set clientenv($win) [eval $env_cmd($win)]
+		error_check_good cl($win) [is_valid_env $clientenv($win)] TRUE
+		set newelector "$clientenv($win) [expr $win + 2]"
+		set cenvlist [lreplace $cenvlist $win $win $newelector]
+		if { $crashing == 0 } {
+			process_msgs $cenvlist
+		}
+	}
+}
+
+proc got_newmaster { cenv i newmaster win {dbname "test.db"} } {
+	upvar $cenv clientenv
+
+	# Check that the new master we got is the one we expected.
+	error_check_good newmaster_is_master $newmaster [expr $win + 2]
+
+	# If this env is the new master, it needs to configure itself
+	# as such -- this is a different env handle from the one that
+	# performed the election.
+	if { $nm == $envid } {
+		error_check_good make_master($i) \
+		    [$clientenv($i) rep_start -master] 0
+		# Occasionally force new log records to be written.
+		set write [berkdb random_int 1 10]
+		if { $write == 1 } {
+			set db [berkdb_open -env $clientenv($i) -auto_commit \
+			    -create -btree $dbname]
+			error_check_good dbopen [is_valid_db $db] TRUE
+			error_check_good dbclose [$db close] 0
+		}
+	}
+}
+
+proc check_election { id newmasterp } {
+	source ./include.tcl
+
+	if { $id == "INVALID" } {
+		return 0
+	}
+	upvar $newmasterp newmaster
+	set newmaster 0
+	set res [catch {open $testdir/ELECTION_RESULT.$id} nmid]
+	if { $res != 0 } {
+		return 0
+	}
+	while { [gets $nmid val] != -1 } {
+#		puts "result $id: $val"
+		set str [lindex $val 0]
+		if { [is_substr $str NEWMASTER] } {
+			set newmaster [lindex $val 1]
+		}
+	}
+	close $nmid
+	return 1
+}
+
 proc close_election { i } {
 	global elections_in_progress
 	set t $elections_in_progress($i)
+	puts $t "replclose \$testdir/MSGQUEUEDIR"
 	puts $t "\$dbenv close"
 	close $t
 	unset elections_in_progress($i)
@@ -657,3 +1121,155 @@ proc cleanup_elections { } {
 
 	set elect_serial 0
 }
+
+#
+# This is essentially a copy of test001, but it only does the put/get
+# loop AND it takes an already-opened db handle.
+#
+proc rep_test { method env repdb {nentries 10000} \
+    {start 0} {skip 0} {needpad 0} args } {
+	source ./include.tcl
+
+	#
+	# Open the db if one isn't given.  Close before exit.
+	#
+	if { $repdb == "NULL" } {
+		set testfile "test.db"
+		set largs [convert_args $method $args]
+		set omethod [convert_method $method]
+		set db [eval {berkdb_open_noerr -env $env -auto_commit -create \
+		    -mode 0644} $largs $omethod $testfile]
+		error_check_good reptest_db [is_valid_db $db] TRUE
+	} else {
+		set db $repdb
+	}
+
+	#
+	# If we are using an env, then testfile should just be the db name.
+	# Otherwise it is the test directory and the name.
+	# If we are not using an external env, then test setting
+	# the database cache size and using multiple caches.
+	puts "\t\tRep_test: $method $nentries key/data pairs starting at $start"
+	set did [open $dict]
+
+	# The "start" variable determines the record number to start
+	# with, if we're using record numbers.  The "skip" variable
+	# determines which dictionary entry to start with.  In normal
+	# use, skip is equal to start.
+
+	if { $skip != 0 } {
+		for { set count 0 } { $count < $skip } { incr count } {
+			gets $did str
+		}
+	}
+	set pflags ""
+	set gflags ""
+	set txn ""
+
+	if { [is_record_based $method] == 1 } {
+		append gflags " -recno"
+	}
+	puts "\t\tRep_test.a: put/get loop"
+	# Here is the loop where we put and get each key/data pair
+	set count 0
+	while { [gets $did str] != -1 && $count < $nentries } {
+		if { [is_record_based $method] == 1 } {
+			global kvals
+
+			set key [expr $count + 1 + $start]
+			if { 0xffffffff > 0 && $key > 0xffffffff } {
+				set key [expr $key - 0x100000000]
+			}
+			if { $key == 0 || $key - 0xffffffff == 1 } {
+				incr key
+				incr count
+			}
+			set kvals($key) [pad_data $method $str]
+		} else {
+			set key $str
+			set str [reverse $str]
+		}
+		#
+		# We want to make sure we send in exactly the same
+		# length data so that LSNs match up for some tests
+		# in replication (rep021).
+		#
+		if { [is_fixed_length $method] == 1 && $needpad } {
+			#
+			# Make it something visible and obvious, 'A'.
+			#
+			set p 65
+			set str [make_fixed_length $method $str $p]
+			set kvals($key) $str
+		}
+		set t [$env txn]
+		error_check_good txn [is_valid_txn $t $env] TRUE
+		set txn "-txn $t"
+		set ret [eval \
+		    {$db put} $txn $pflags {$key [chop_data $method $str]}]
+		error_check_good put $ret 0
+		error_check_good txn [$t commit] 0
+
+		# Checkpoint 10 times during the run, but not more
+		# frequently than every 5 entries.
+		set checkfreq [expr $nentries / 10]
+		if { $checkfreq < 5 } {
+			set checkfreq 5
+		}
+		if { $count % $checkfreq == 0 } {
+			error_check_good txn_checkpoint($count) \
+			    [$env txn_checkpoint] 0
+		}
+		incr count
+	}
+	close $did
+	if { $repdb == "NULL" } {
+		error_check_good rep_close [$db close] 0
+	}
+}
+
+proc process_msgs { elist {perm_response 0} {dupp NONE} {errp NONE} } {
+	if { $perm_response == 1 } {
+		global perm_response_list
+		set perm_response_list {{}}
+	}
+
+	if { [string compare $dupp NONE] != 0 } {
+		upvar $dupp dupmaster
+		set dupmaster 0
+	} else {
+		set dupmaster NONE
+	}
+
+	if { [string compare $errp NONE] != 0 } {
+		upvar $errp errorp
+		set errorp 0
+	} else {
+		set errorp NONE
+	}
+
+	while { 1 } {
+		set nproced 0
+		foreach pair $elist {
+			set envname [lindex $pair 0]
+			set envid [lindex $pair 1]
+			#
+			# If we need to send in all the other args
+			incr nproced [replprocessqueue $envname $envid \
+			    0 NONE NONE dupmaster errorp]
+			#
+			# If the user is expecting to handle an error and we get
+			# one, return the error immediately.
+			#
+			if { $dupmaster != 0 && $dupmaster != "NONE" } {
+				return
+			}
+			if { $errorp != 0 && $errorp != "NONE" } {
+				return
+			}
+		}
+		if { $nproced == 0 } {
+			break
+		}
+	}
+}
diff --git a/storage/bdb/test/rpc001.tcl b/storage/bdb/test/rpc001.tcl
index 1b65639014f051a5218f8e38ac18a203e6677464..e07d5dcb162603df53f7ab36c56470fb8f3b35b9 100644
--- a/storage/bdb/test/rpc001.tcl
+++ b/storage/bdb/test/rpc001.tcl
@@ -1,18 +1,17 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: rpc001.tcl,v 11.33 2002/07/25 22:57:32 mjc Exp $
+# $Id: rpc001.tcl,v 11.41 2004/06/01 19:55:25 carol Exp $
 #
 # TEST	rpc001
 # TEST	Test RPC server timeouts for cursor, txn and env handles.
-# TEST	Test RPC specifics, primarily that unsupported functions return
-# TEST	errors and such.
 proc rpc001 { } {
 	global __debug_on
 	global __debug_print
 	global errorInfo
+	global is_je_test
 	global rpc_svc
 	source ./include.tcl
 
@@ -22,234 +21,251 @@ proc rpc001 { } {
 	set ttime 5
 	set itime 10
 	puts "Rpc001: Server timeouts: resource $ttime sec, idle $itime sec"
-	if { [string compare $rpc_server "localhost"] == 0 } {
-	       set dpid [exec $util_path/$rpc_svc \
-		   -h $rpc_testdir -t $ttime -I $itime &]
-	} else {
-	       set dpid [exec rsh $rpc_server $rpc_path/$rpc_svc \
-		   -h $rpc_testdir -t $ttime -I $itime&]
-	}
+	set dpid [rpc_server_start 0 30 -t $ttime -I $itime]
 	puts "\tRpc001.a: Started server, pid $dpid"
 
-	tclsleep 2
-	remote_cleanup $rpc_server $rpc_testdir $testdir
-	puts "\tRpc001.b: Creating environment"
-
-	set testfile "rpc001.db"
-	set home [file tail $rpc_testdir]
-
-	set env [eval {berkdb_env -create -mode 0644 -home $home \
-	    -server $rpc_server -client_timeout 10000 -txn}]
-	error_check_good lock_env:open [is_valid_env $env] TRUE
-
-	puts "\tRpc001.c: Opening a database"
-	#
-	# NOTE: the type of database doesn't matter, just use btree.
-	set db [eval {berkdb_open -auto_commit -create -btree -mode 0644} \
-	    -env $env $testfile]
-	error_check_good dbopen [is_valid_db $db] TRUE
-
-	set curs_list {}
-	set txn_list {}
-	puts "\tRpc001.d: Basic timeout test"
-	puts "\tRpc001.d1: Starting a transaction"
-	set txn [$env txn]
-	error_check_good txn_begin [is_valid_txn $txn $env] TRUE
-	lappend txn_list $txn
-
-	puts "\tRpc001.d2: Open a cursor in that transaction"
-	set dbc [$db cursor -txn $txn]
-	error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
-	lappend curs_list $dbc
-
-	puts "\tRpc001.d3: Duplicate that cursor"
-	set dbc [$dbc dup]
-	error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
-	lappend curs_list $dbc
-
-	puts "\tRpc001.d4: Starting a nested transaction"
-	set txn [$env txn -parent $txn]
-	error_check_good txn_begin [is_valid_txn $txn $env] TRUE
-	set txn_list [linsert $txn_list 0 $txn]
-
-	puts "\tRpc001.d5: Create a cursor, no transaction"
-	set dbc [$db cursor]
-	error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
-	lappend curs_list $dbc
-
-	puts "\tRpc001.d6: Timeout cursor and transactions"
-	set sleeptime [expr $ttime + 2]
-	tclsleep $sleeptime
-
 	#
-	# Perform a generic db operations to cause the timeout routine
-	# to trigger.
+	# Wrap the whole test in a catch statement so we can still kill
+	# the rpc server even if the test fails.
 	#
-	set stat [catch {$db stat} ret]
-	error_check_good dbstat $stat 0
+	set status [catch {
+		tclsleep 2
+		remote_cleanup $rpc_server $rpc_testdir $testdir
 
-	#
-	# Check that every handle we opened above is timed out
-	#
-	foreach c $curs_list {
-		set stat [catch {$c close} ret]
-		error_check_good dbc_close:$c $stat 1
-		error_check_good dbc_timeout:$c \
-		    [is_substr $errorInfo "DB_NOSERVER_ID"] 1
-	}
-	foreach t $txn_list {
-		set stat [catch {$t commit} ret]
-		error_check_good txn_commit:$t $stat 1
-		error_check_good txn_timeout:$t \
-		    [is_substr $errorInfo "DB_NOSERVER_ID"] 1
-	}
+		puts "\tRpc001.b: Creating environment"
 
-	set txn_list {}
-	set ntxns 8
-	puts "\tRpc001.e: Nested ($ntxns x $ntxns) transaction activity test"
-	puts "\tRpc001.e1: Starting parent transaction"
-	set txn [$env txn]
-	error_check_good txn_begin [is_valid_txn $txn $env] TRUE
-	set txn_list [linsert $txn_list 0 $txn]
-	set last_txn $txn
-	set parent_txn $txn
+		set testfile "rpc001.db"
+		set home [file tail $rpc_testdir]
 
-	#
-	# First set a breadth of 'ntxns'
-	# We need 2 from this set for testing later on.  Just set them
-	# up separately first.
-	#
-	puts "\tRpc001.e2: Creating $ntxns child transactions"
-	set child0 [$env txn -parent $parent_txn]
-	error_check_good txn_begin [is_valid_txn $child0 $env] TRUE
-	set child1 [$env txn -parent $parent_txn]
-	error_check_good txn_begin [is_valid_txn $child1 $env] TRUE
-
-	for {set i 2} {$i < $ntxns} {incr i} {
-		set txn [$env txn -parent $parent_txn]
-		error_check_good txn_begin [is_valid_txn $txn $env] TRUE
-		set txn_list [linsert $txn_list 0 $txn]
-	}
+		set env [eval {berkdb_env -create -mode 0644 -home $home \
+		    -server $rpc_server -client_timeout 10000 -txn}]
+		error_check_good lock_env:open [is_valid_env $env] TRUE
 
-	#
-	# Now make one 'ntxns' deeply nested.
-	# Add one more for testing later on separately.
-	#
-	puts "\tRpc001.e3: Creating $ntxns nested child transactions"
-	for {set i 0} {$i < $ntxns} {incr i} {
-		set txn [$env txn -parent $last_txn]
+		puts "\tRpc001.c: Opening a database"
+		#
+		# NOTE: the type of database doesn't matter, just use btree.
+		set db [eval {berkdb_open -auto_commit -create -btree \
+		    -mode 0644} -env $env $testfile]
+		error_check_good dbopen [is_valid_db $db] TRUE
+
+		set curs_list {}
+		set txn_list {}
+		puts "\tRpc001.d: Basic timeout test"
+		puts "\tRpc001.d1: Starting a transaction"
+		set txn [$env txn]
 		error_check_good txn_begin [is_valid_txn $txn $env] TRUE
-		set txn_list [linsert $txn_list 0 $txn]
-		set last_txn $txn
-	}
-	set last_parent $last_txn
-	set last_txn [$env txn -parent $last_parent]
-	error_check_good txn_begin [is_valid_txn $last_txn $env] TRUE
-
-	puts "\tRpc001.e4: Open a cursor in deepest transaction"
-	set dbc [$db cursor -txn $last_txn]
-	error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
+		lappend txn_list $txn
+
+		puts "\tRpc001.d2: Open a cursor in that transaction"
+		set dbc [$db cursor -txn $txn]
+		error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
+		lappend curs_list $dbc
+
+		puts "\tRpc001.d3: Duplicate that cursor"
+		set dbc [$dbc dup]
+		error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
+		lappend curs_list $dbc
+
+		if { !$is_je_test } {
+			puts "\tRpc001.d4: Starting a nested transaction"
+			set txn [$env txn -parent $txn]
+			error_check_good txn_begin [is_valid_txn $txn $env] TRUE
+			set txn_list [linsert $txn_list 0 $txn]
+		}
 
-	puts "\tRpc001.e5: Duplicate that cursor"
-	set dbcdup [$dbc dup]
-	error_check_good db_cursor [is_valid_cursor $dbcdup $db] TRUE
-	lappend curs_list $dbcdup
+		puts "\tRpc001.d5: Create a cursor, no transaction"
+		set dbc [$db cursor]
+		error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
+		lappend curs_list $dbc
 
-	puts "\tRpc001.f: Timeout then activate duplicate cursor"
-	tclsleep $sleeptime
-	set stat [catch {$dbcdup close} ret]
-	error_check_good dup_close:$dbcdup $stat 0
-	error_check_good dup_close:$dbcdup $ret 0
+		puts "\tRpc001.d6: Timeout cursor and transactions"
+		set sleeptime [expr $ttime + 2]
+		tclsleep $sleeptime
 
-	#
-	# Make sure that our parent txn is not timed out.  We will
-	# try to begin another child tnx using the parent.  We expect
-	# that to succeed.  Immediately commit that txn.
-	#
-	set stat [catch {$env txn -parent $parent_txn} newchild]
-	error_check_good newchildtxn $stat 0
-	error_check_good newcommit [$newchild commit] 0
+		#
+		# Perform a generic db operations to cause the timeout routine
+		# to trigger.
+		#
+		set stat [catch {$db stat} ret]
+		error_check_good dbstat $stat 0
 
-	puts "\tRpc001.g: Timeout, then activate cursor"
-	tclsleep $sleeptime
-	set stat [catch {$dbc close} ret]
-	error_check_good dbc_close:$dbc $stat 0
-	error_check_good dbc_close:$dbc $ret 0
+		#
+		# Check that every handle we opened above is timed out
+		#
+		foreach c $curs_list {
+			set stat [catch {$c close} ret]
+			error_check_good dbc_close:$c $stat 1
+			error_check_good dbc_timeout:$c \
+			    [is_substr $errorInfo "DB_NOSERVER_ID"] 1
+		}
+		foreach t $txn_list {
+			set stat [catch {$t commit} ret]
+			error_check_good txn_commit:$t $stat 1
+			error_check_good txn_timeout:$t \
+			    [is_substr $errorInfo "DB_NOSERVER_ID"] 1
+		}
 
-	#
-	# Make sure that our parent txn is not timed out.  We will
-	# try to begin another child tnx using the parent.  We expect
-	# that to succeed.  Immediately commit that txn.
-	#
-	set stat [catch {$env txn -parent $parent_txn} newchild]
-	error_check_good newchildtxn $stat 0
-	error_check_good newcommit [$newchild commit] 0
+		set txn_list {}
+
+		if { !$is_je_test } {
+			set ntxns 8
+			puts "\tRpc001.e: Nested ($ntxns x $ntxns) txn activity test"
+			puts "\tRpc001.e1: Starting parent transaction"
+			set txn [$env txn]
+			error_check_good txn_begin [is_valid_txn $txn $env] TRUE
+			set txn_list [linsert $txn_list 0 $txn]
+			set last_txn $txn
+			set parent_txn $txn
+
+			#
+			# First set a breadth of 'ntxns'
+			# We need 2 from this set for testing later on.  Just
+			# set them up separately first.
+			#
+			puts "\tRpc001.e2: Creating $ntxns child transactions"
+			set child0 [$env txn -parent $parent_txn]
+			error_check_good txn_begin \
+				[is_valid_txn $child0 $env] TRUE
+			set child1 [$env txn -parent $parent_txn]
+			error_check_good txn_begin \
+				[is_valid_txn $child1 $env] TRUE
+
+			for {set i 2} {$i < $ntxns} {incr i} {
+				set txn [$env txn -parent $parent_txn]
+				error_check_good txn_begin \
+					[is_valid_txn $txn $env] TRUE
+				set txn_list [linsert $txn_list 0 $txn]
+			}
+
+			#
+			# Now make one 'ntxns' deeply nested.
+			# Add one more for testing later on separately.
+			#
+			puts "\tRpc001.e3: Creating $ntxns nested child transactions"
+			for {set i 0} {$i < $ntxns} {incr i} {
+				set txn [$env txn -parent $last_txn]
+				error_check_good txn_begin \
+					[is_valid_txn $txn $env] TRUE
+				set txn_list [linsert $txn_list 0 $txn]
+				set last_txn $txn
+			}
+			set last_parent $last_txn
+			set last_txn [$env txn -parent $last_parent]
+			error_check_good txn_begin \
+				[is_valid_txn $last_txn $env] TRUE
+
+			puts "\tRpc001.e4: Open a cursor in deepest transaction"
+			set dbc [$db cursor -txn $last_txn]
+			error_check_good db_cursor \
+				[is_valid_cursor $dbc $db] TRUE
+
+			puts "\tRpc001.e5: Duplicate that cursor"
+			set dbcdup [$dbc dup]
+			error_check_good db_cursor \
+				[is_valid_cursor $dbcdup $db] TRUE
+			lappend curs_list $dbcdup
+
+			puts "\tRpc001.f: Timeout then activate duplicate cursor"
+			tclsleep $sleeptime
+			set stat [catch {$dbcdup close} ret]
+			error_check_good dup_close:$dbcdup $stat 0
+			error_check_good dup_close:$dbcdup $ret 0
+
+			#
+			# Make sure that our parent txn is not timed out.  We
+			# will try to begin another child tnx using the parent.
+			# We expect that to succeed.  Immediately commit that
+			# txn.
+			#
+			set stat [catch {$env txn -parent $parent_txn} newchild]
+			error_check_good newchildtxn $stat 0
+			error_check_good newcommit [$newchild commit] 0
+
+			puts "\tRpc001.g: Timeout, then activate cursor"
+			tclsleep $sleeptime
+			set stat [catch {$dbc close} ret]
+			error_check_good dbc_close:$dbc $stat 0
+			error_check_good dbc_close:$dbc $ret 0
+
+			#
+			# Make sure that our parent txn is not timed out.  We
+			# will try to begin another child tnx using the parent.
+			# We expect that to succeed.  Immediately commit that
+			# txn.
+			#
+			set stat [catch {$env txn -parent $parent_txn} newchild]
+			error_check_good newchildtxn $stat 0
+			error_check_good newcommit [$newchild commit] 0
+
+			puts "\tRpc001.h: Timeout, then activate child txn"
+			tclsleep $sleeptime
+			set stat [catch {$child0 commit} ret]
+			error_check_good child_commit $stat 0
+			error_check_good child_commit:$child0 $ret 0
+
+			#
+			# Make sure that our nested txn is not timed out.  We
+			# will try to begin another child tnx using the parent.
+			# We expect that to succeed.  Immediately commit that
+			# txn.
+			#
+			set stat \
+				[catch {$env txn -parent $last_parent} newchild]
+			error_check_good newchildtxn $stat 0
+			error_check_good newcommit [$newchild commit] 0
+
+			puts "\tRpc001.i: Timeout, then activate nested txn"
+			tclsleep $sleeptime
+			set stat [catch {$last_txn commit} ret]
+			error_check_good lasttxn_commit $stat 0
+			error_check_good lasttxn_commit:$child0 $ret 0
+
+			#
+			# Make sure that our child txn is not timed out.  We
+			# should be able to commit it.
+			#
+			set stat [catch {$child1 commit} ret]
+			error_check_good child_commit:$child1 $stat 0
+			error_check_good child_commit:$child1 $ret 0
+
+			#
+			# Clean up.  They were inserted in LIFO order, so we
+			# should just be able to commit them all.
+			#
+			foreach t $txn_list {
+				set stat [catch {$t commit} ret]
+				error_check_good txn_commit:$t $stat 0
+				error_check_good txn_commit:$t $ret 0
+			}
+		}
 
-	puts "\tRpc001.h: Timeout, then activate child txn"
-	tclsleep $sleeptime
-	set stat [catch {$child0 commit} ret]
-	error_check_good child_commit $stat 0
-	error_check_good child_commit:$child0 $ret 0
+		set stat [catch {$db close} ret]
+		error_check_good db_close $stat 0
 
-	#
-	#
-	# Make sure that our nested txn is not timed out.  We will
-	# try to begin another child tnx using the parent.  We expect
-	# that to succeed.  Immediately commit that txn.
-	#
-	set stat [catch {$env txn -parent $last_parent} newchild]
-	error_check_good newchildtxn $stat 0
-	error_check_good newcommit [$newchild commit] 0
+		rpc_timeoutjoin $env "Rpc001.j" $sleeptime 0
+		rpc_timeoutjoin $env "Rpc001.k" $sleeptime 1
 
-	puts "\tRpc001.i: Timeout, then activate nested txn"
-	tclsleep $sleeptime
-	set stat [catch {$last_txn commit} ret]
-	error_check_good lasttxn_commit $stat 0
-	error_check_good lasttxn_commit:$child0 $ret 0
+		puts "\tRpc001.l: Timeout idle env handle"
+		set sleeptime [expr $itime + 2]
+		tclsleep $sleeptime
 
-	#
-	# Make sure that our child txn is not timed out.  We should
-	# be able to commit it.
-	#
-	set stat [catch {$child1 commit} ret]
-	error_check_good child_commit:$child1 $stat 0
-	error_check_good child_commit:$child1 $ret 0
+		#
+		# We need to do another operation to time out the environment
+		# handle.  Open another environment, with an invalid home
+		# directory.
+		#
+		set stat [catch {eval {berkdb_env_noerr -home "$home.fail" \
+		    -server $rpc_server}} ret]
+		error_check_good env_open $stat 1
 
-	#
-	# Clean up.  They were inserted in LIFO order, so we should
-	# just be able to commit them all.
-	foreach t $txn_list {
-		set stat [catch {$t commit} ret]
-		error_check_good txn_commit:$t $stat 0
-		error_check_good txn_commit:$t $ret 0
+		set stat [catch {$env close} ret]
+		error_check_good env_close $stat 1
+		error_check_good env_timeout \
+		    [is_substr $errorInfo "DB_NOSERVER_ID"] 1
+	} res]
+	if { $status != 0 } {
+		puts $res
 	}
-
-	set stat [catch {$db close} ret]
-	error_check_good db_close $stat 0
-
-	rpc_timeoutjoin $env "Rpc001.j" $sleeptime 0
-	rpc_timeoutjoin $env "Rpc001.k" $sleeptime 1
-
-	#
-	# We need a 2nd env just to do an op to timeout the env.
-	# Make the flags different so we don't end up sharing a handle.
-	#
-	set env1 [eval {berkdb_env -create -mode 0644 -home $home \
-	    -server $rpc_server -client_timeout 10000}]
-	error_check_good lock_env:open [is_valid_env $env1] TRUE
-
-	puts "\tRpc001.l: Timeout idle env handle"
-	set sleeptime [expr $itime + 2]
-	tclsleep $sleeptime
-
-	set stat [catch {$env1 close} ret]
-	error_check_good env1_close $stat 0
-
-	set stat [catch {$env close} ret]
-	error_check_good env_close $stat 1
-	error_check_good env_timeout \
-	    [is_substr $errorInfo "DB_NOSERVER_ID"] 1
-
 	tclkill $dpid
 }
 
@@ -283,13 +299,13 @@ proc rpc_timeoutjoin {env msg sleeptime use_txn} {
 	    {apple pie} {raspberry pie} {lemon pie}
 	}
 	set fdb [eval {berkdb_open -create -btree -mode 0644} \
-	    $txnflag -env $env -dup fruit.db]
+	    $txnflag -env $env -dup -dupsort fruit.db]
 	error_check_good dbopen [is_valid_db $fdb] TRUE
 	set pdb [eval {berkdb_open -create -btree -mode 0644} \
-	    $txnflag -env $env -dup price.db]
+	    $txnflag -env $env -dup -dupsort price.db]
 	error_check_good dbopen [is_valid_db $pdb] TRUE
 	set ddb [eval {berkdb_open -create -btree -mode 0644} \
-	    $txnflag -env $env -dup dessert.db]
+	    $txnflag -env $env -dup -dupsort dessert.db]
 	error_check_good dbopen [is_valid_db $ddb] TRUE
 	foreach kd $fruit {
 		set k [lindex $kd 0]
@@ -319,10 +335,14 @@ proc rpc_timeoutjoin {env msg sleeptime use_txn} {
 	error_check_good ddb:close [$ddb close] 0
 	error_check_good pdb:close [$pdb close] 0
 	error_check_good fdb:close [$fdb close] 0
+	error_check_good ddb:remove [$env dbremove dessert.db] 0
+	error_check_good pdb:remove [$env dbremove price.db] 0
+	error_check_good fdb:remove [$env dbremove fruit.db] 0
 }
 
 proc rpc_join {env msg sleep fdb pdb ddb use_txn op} {
 	global errorInfo
+	global is_je_test
 
 	#
 	# Start a parent and child transaction.  We'll do our join in
@@ -337,12 +357,19 @@ proc rpc_join {env msg sleep fdb pdb ddb use_txn op} {
 		set txn [$env txn]
 		error_check_good txn_begin [is_valid_txn $txn $env] TRUE
 		set txn_list [linsert $txn_list 0 $txn]
-		set child0 [$env txn -parent $txn]
-		error_check_good txn_begin [is_valid_txn $child0 $env] TRUE
-		set txn_list [linsert $txn_list 0 $child0]
-		set child1 [$env txn -parent $txn]
-		error_check_good txn_begin [is_valid_txn $child1 $env] TRUE
-		set txn_list [linsert $txn_list 0 $child1]
+		if { !$is_je_test } {
+			set child0 [$env txn -parent $txn]
+			error_check_good txn_begin \
+				[is_valid_txn $child0 $env] TRUE
+			set txn_list [linsert $txn_list 0 $child0]
+			set child1 [$env txn -parent $txn]
+			error_check_good txn_begin \
+				[is_valid_txn $child1 $env] TRUE
+			set txn_list [linsert $txn_list 0 $child1]
+		} else {
+			set child0 $txn
+			set child1 $txn
+		}
 		set txncmd "-txn $child0"
 	} else {
 		puts "\t$msg$msgnum: Set up join cursor"
diff --git a/storage/bdb/test/rpc002.tcl b/storage/bdb/test/rpc002.tcl
index 4b69265bf3ab9afe05539cedf330fac073b3ad7e..505c23e7be7409dd5dd693ad633418d243e6991c 100644
--- a/storage/bdb/test/rpc002.tcl
+++ b/storage/bdb/test/rpc002.tcl
@@ -1,12 +1,13 @@
 # Sel the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: rpc002.tcl,v 1.17 2002/07/16 20:53:03 bostic Exp $
+# $Id: rpc002.tcl,v 1.25 2004/07/15 17:19:12 sue Exp $
 #
 # TEST	rpc002
 # TEST	Test invalid RPC functions and make sure we error them correctly
+# TEST	Test server home directory error cases
 proc rpc002 { } {
 	global __debug_on
 	global __debug_print
@@ -19,125 +20,142 @@ proc rpc002 { } {
 	#
 	# First start the server.
 	#
-	puts "Rpc002: Unsupported interface test"
-	if { [string compare $rpc_server "localhost"] == 0 } {
-	       set dpid [exec $util_path/$rpc_svc -h $rpc_testdir &]
-	} else {
-	       set dpid [exec rsh $rpc_server $rpc_path/$rpc_svc \
-		   -h $rpc_testdir &]
-	}
+	puts "Rpc002: Error and Unsupported interface test"
+	set dpid [rpc_server_start]
 	puts "\tRpc002.a: Started server, pid $dpid"
-	tclsleep 2
-	remote_cleanup $rpc_server $rpc_testdir $testdir
 
-	puts "\tRpc002.b: Unsupported env options"
 	#
-	# Test each "pre-open" option for env's.  These need to be
-	# tested on the 'berkdb_env' line.
+	# Wrap the whole test in a catch statement so we can still
+	# kill the rpc server even if the test fails.
 	#
-	set rlist {
-	{ "-data_dir $rpc_testdir"	"Rpc002.b0"}
-	{ "-log_buffer 512"		"Rpc002.b1"}
-	{ "-log_dir $rpc_testdir"	"Rpc002.b2"}
-	{ "-log_max 100"		"Rpc002.b3"}
-	{ "-lock_conflict {3 {0 0 0 0 0 1 0 1 1}}"	"Rpc002.b4"}
-	{ "-lock_detect default"	"Rpc002.b5"}
-	{ "-lock_max 100"		"Rpc002.b6"}
-	{ "-mmapsize 100"		"Rpc002.b7"}
-	{ "-shm_key 100"		"Rpc002.b9"}
-	{ "-tmp_dir $rpc_testdir"	"Rpc002.b10"}
-	{ "-txn_max 100"		"Rpc002.b11"}
-	{ "-txn_timestamp 100"		"Rpc002.b12"}
-	{ "-verbose {recovery on}"		"Rpc002.b13"}
-	}
+	set status [catch {
+		tclsleep 2
+		remote_cleanup $rpc_server $rpc_testdir $testdir
 
-	set e "berkdb_env_noerr -create -mode 0644 -home $home \
-	    -server $rpc_server -client_timeout 10000 -txn"
-	foreach pair $rlist {
-		set cmd [lindex $pair 0]
-		set msg [lindex $pair 1]
-		puts "\t$msg: $cmd"
+		puts "\tRpc002.b: Unsupported env options"
+		#
+		# Test each "pre-open" option for env's.  These need to be
+		# tested on the 'berkdb_env' line.
+		#
+		set rlist {
+		{ "-data_dir $rpc_testdir"	"Rpc002.b0"}
+		{ "-log_buffer 512"		"Rpc002.b1"}
+		{ "-log_dir $rpc_testdir"	"Rpc002.b2"}
+		{ "-log_max 100"		"Rpc002.b3"}
+		{ "-lock_conflict {3 {0 0 0 0 0 1 0 1 1}}"	"Rpc002.b4"}
+		{ "-lock_detect default"	"Rpc002.b5"}
+		{ "-lock_max 100"		"Rpc002.b6"}
+		{ "-mpool_mmap_size 100"	"Rpc002.b7"}
+		{ "-shm_key 100"		"Rpc002.b9"}
+		{ "-tmp_dir $rpc_testdir"	"Rpc002.b10"}
+		{ "-txn_max 100"		"Rpc002.b11"}
+		{ "-txn_timestamp 100"		"Rpc002.b12"}
+		{ "-verbose {recovery on}"		"Rpc002.b13"}
+		}
 
-		set stat [catch {eval $e $cmd} ret]
-		error_check_good $cmd $stat 1
-		error_check_good $cmd.err \
-		    [is_substr $errorInfo "meaningless in an RPC env"] 1
-	}
+		set e "berkdb_env_noerr -create -mode 0644 -home $home \
+		    -server $rpc_server -client_timeout 10000 -txn"
 
-	#
-	# Open an env with all the subsystems (-txn implies all
-	# the rest)
-	#
-	puts "\tRpc002.c: Unsupported env related interfaces"
-	set env [eval {berkdb_env_noerr -create -mode 0644 -home $home \
-	    -server $rpc_server -client_timeout 10000 -txn}]
-	error_check_good envopen [is_valid_env $env] TRUE
-	set dbcmd "berkdb_open_noerr -create -btree -mode 0644 -env $env \
-	    $testfile"
-	set db [eval $dbcmd]
-	error_check_good dbopen [is_valid_db $db] TRUE
+		foreach pair $rlist {
+			set cmd [lindex $pair 0]
+			set msg [lindex $pair 1]
+			puts "\t$msg: $cmd"
 
-	#
-	# Test each "post-open" option relating to envs, txns, locks,
-	# logs and mpools.
-	#
-	set rlist {
-	{ " lock_detect default"	"Rpc002.c0"}
-	{ " lock_get read 1 $env"	"Rpc002.c1"}
-	{ " lock_id"			"Rpc002.c2"}
-	{ " lock_stat"			"Rpc002.c3"}
-	{ " lock_vec 1 {get $env read}"	"Rpc002.c4"}
-	{ " log_archive"		"Rpc002.c5"}
-	{ " log_file {0 0}"		"Rpc002.c6"}
-	{ " log_flush"			"Rpc002.c7"}
-	{ " log_cursor"			"Rpc002.c8"}
-	{ " log_stat"			"Rpc002.c9"}
-	{ " mpool -create -pagesize 512"	"Rpc002.c10"}
-	{ " mpool_stat"			"Rpc002.c11"}
-	{ " mpool_sync {0 0}"		"Rpc002.c12"}
-	{ " mpool_trickle 50"		"Rpc002.c13"}
-	{ " txn_checkpoint -min 1"	"Rpc002.c14"}
-	{ " txn_stat"			"Rpc002.c15"}
-	}
+			set stat [catch {eval $e $cmd} ret]
+			error_check_good $cmd $stat 1
+			error_check_good $cmd.err [is_substr $errorInfo \
+			    "unsupported in RPC environments"] 1
+		}
 
-	foreach pair $rlist {
-		set cmd [lindex $pair 0]
-		set msg [lindex $pair 1]
-		puts "\t$msg: $cmd"
+		#
+		# Open an env with all the subsystems (-txn implies all
+		# the rest)
+		#
+		puts "\tRpc002.c: Unsupported env related interfaces"
+		set env [eval {berkdb_env_noerr -create -mode 0644 -home $home \
+		    -server $rpc_server -client_timeout 10000 -txn}]
+		error_check_good envopen [is_valid_env $env] TRUE
+		set dbcmd "berkdb_open_noerr -create -btree -mode 0644 \
+		    -env $env $testfile"
+		set db [eval $dbcmd]
+		error_check_good dbopen [is_valid_db $db] TRUE
 
-		set stat [catch {eval $env $cmd} ret]
-		error_check_good $cmd $stat 1
-		error_check_good $cmd.err \
-		    [is_substr $errorInfo "meaningless in an RPC env"] 1
-	}
-	error_check_good dbclose [$db close] 0
+		#
+		# Test each "post-open" option relating to envs, txns, locks,
+		# logs and mpools.
+		#
+		set rlist {
+		{ " lock_detect default"	"Rpc002.c0"}
+		{ " lock_get read 1 $env"	"Rpc002.c1"}
+		{ " lock_id"			"Rpc002.c2"}
+		{ " lock_stat"			"Rpc002.c3"}
+		{ " lock_vec 1 {get $env read}"	"Rpc002.c4"}
+		{ " log_archive"		"Rpc002.c5"}
+		{ " log_file {0 0}"		"Rpc002.c6"}
+		{ " log_flush"			"Rpc002.c7"}
+		{ " log_cursor"			"Rpc002.c8"}
+		{ " log_stat"			"Rpc002.c9"}
+		{ " mpool -create -pagesize 512"	"Rpc002.c10"}
+		{ " mpool_stat"			"Rpc002.c11"}
+		{ " mpool_sync {0 0}"		"Rpc002.c12"}
+		{ " mpool_trickle 50"		"Rpc002.c13"}
+		{ " txn_checkpoint -min 1"	"Rpc002.c14"}
+		{ " txn_stat"			"Rpc002.c15"}
+		}
 
-	#
-	# The database operations that aren't supported are few
-	# because mostly they are the ones Tcl doesn't support
-	# either so we have no way to get at them.  Test what we can.
-	#
-	puts "\tRpc002.d: Unsupported database related interfaces"
-	#
-	# NOTE: the type of database doesn't matter, just use btree.
-	#
-	puts "\tRpc002.d0: -cachesize"
-	set dbcmd "berkdb_open_noerr -create -btree -mode 0644 -env $env \
-	    -cachesize {0 65536 0} $testfile"
-	set stat [catch {eval $dbcmd} ret]
-	error_check_good dbopen_cache $stat 1
-	error_check_good dbopen_cache_err \
-	    [is_substr $errorInfo "meaningless in an RPC env"] 1
+		foreach pair $rlist {
+			set cmd [lindex $pair 0]
+			set msg [lindex $pair 1]
+			puts "\t$msg: $cmd"
 
-	puts "\tRpc002.d1: Try to upgrade a database"
-	#
-	# NOTE: the type of database doesn't matter, just use btree.
-	set stat [catch {eval {berkdb upgrade -env} $env $testfile} ret]
-	error_check_good dbupgrade $stat 1
-	error_check_good dbupgrade_err \
-	    [is_substr $errorInfo "meaningless in an RPC env"] 1
+			set stat [catch {eval $env $cmd} ret]
+			error_check_good $cmd $stat 1
+			error_check_good $cmd.err [is_substr $errorInfo \
+			    "unsupported in RPC environments"] 1
+		}
+		error_check_good dbclose [$db close] 0
+
+		#
+		# The database operations that aren't supported are few
+		# because mostly they are the ones Tcl doesn't support
+		# either so we have no way to get at them.  Test what we can.
+		#
+		puts "\tRpc002.d: Unsupported database related interfaces"
+		#
+		# NOTE: the type of database doesn't matter, just use btree.
+		#
+		puts "\tRpc002.d0: -cachesize"
+		set dbcmd "berkdb_open_noerr -create -btree -mode 0644 \
+		    -env $env -cachesize {0 65536 0} $testfile"
+		set stat [catch {eval $dbcmd} ret]
+		error_check_good dbopen_cache $stat 1
+		error_check_good dbopen_cache_err \
+		    [is_substr $errorInfo "unsupported in RPC environments"] 1
 
-	error_check_good envclose [$env close] 0
+		puts "\tRpc002.d1: Try to upgrade a database"
+		#
+		# NOTE: the type of database doesn't matter, just use btree.
+		set stat [catch {eval {berkdb upgrade -env} $env $testfile} ret]
+		error_check_good dbupgrade $stat 1
+		error_check_good dbupgrade_err [is_substr $errorInfo \
+		    "unsupported in RPC environments"] 1
+		error_check_good envclose [$env close] 0
 
+		puts "\tRpc002.e: Open env with unsupported home dir"
+		set stat [catch {eval {berkdb_env_noerr -create -mode 0644 \
+		    -home XXX -server $rpc_server -client_timeout 10000 \
+		    -txn}} ret]
+		error_check_good env2open $stat 1
+		error_check_good envfail [is_substr $ret "Home unrecognized"] 1
+
+		puts "\tRpc002.f: Open env with a NULL home dir"
+		set stat [catch {eval {berkdb_env_noerr -create -mode 0644 \
+		    -server $rpc_server -client_timeout 10000 -txn}} ret]
+		error_check_good env2open $stat 1
+		error_check_good envfail [is_substr $ret "Home unrecognized"] 1
+	} res]
+	if { $status != 0 } {
+		puts $res
+	}
 	tclkill $dpid
 }
diff --git a/storage/bdb/test/rpc003.tcl b/storage/bdb/test/rpc003.tcl
index 76f0dca6c077e64e4c54869d40aae62e43f3fee2..890cbc30f5eeb6ef440ce81ac58308af28b0b317 100644
--- a/storage/bdb/test/rpc003.tcl
+++ b/storage/bdb/test/rpc003.tcl
@@ -1,11 +1,12 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2001-2002
+# Copyright (c) 2001-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: rpc003.tcl,v 11.9 2002/07/16 20:53:03 bostic Exp $
+# $Id: rpc003.tcl,v 11.16 2004/03/02 18:44:41 mjc Exp $
 #
-# Test RPC and secondary indices.
+# TEST	rpc003
+# TEST	Test RPC and secondary indices.
 proc rpc003 { } {
 	source ./include.tcl
 	global dict nsecondaries
@@ -85,67 +86,80 @@ proc rpc003 { } {
 	# We have set up our databases, so now start the server and
 	# read them over RPC.
 	#
-	set dpid [exec $util_path/$rpc_svc -h $rpc_testdir &]
+	set dpid [rpc_server_start]
 	puts "\tRpc003.c: Started server, pid $dpid"
-	tclsleep 2
-
-	set home [file tail $rpc_testdir]
-	set env [eval {berkdb_env_noerr -create -mode 0644 -home $home \
-	    -server $rpc_server}]
-	error_check_good lock_env:open [is_valid_env $env] TRUE
 
 	#
-	# Attempt to send in a NULL callback to associate.  It will fail
-	# if the primary and secondary are not both read-only.
+	# Wrap the remainder of the test in a catch statement so we
+	# can still kill the rpc server even if the test fails.
 	#
-	set msg "\tRpc003.d"
-	puts "$msg: Using r/w primary and r/w secondary"
-	set popen "berkdb_open_noerr -env $env $pomethod $pargs $pname"
-	set sopen "berkdb_open_noerr -create -env $env \
-	    [lindex $omethods 0] [lindex $argses 0] $snamebase.0.db"
-	rpc003_assoc_err $popen $sopen $msg
-
-	set msg "\tRpc003.e"
-	puts "$msg: Using r/w primary and read-only secondary"
-	set popen "berkdb_open_noerr -env $env $pomethod $pargs $pname"
-	set sopen "berkdb_open_noerr -env $env -rdonly \
-	    [lindex $omethods 0] [lindex $argses 0] $snamebase.0.db"
-	rpc003_assoc_err $popen $sopen $msg
-
-	set msg "\tRpc003.f"
-	puts "$msg: Using read-only primary and r/w secondary"
-	set popen "berkdb_open_noerr -env $env $pomethod -rdonly $pargs $pname"
-	set sopen "berkdb_open_noerr -create -env $env \
-	    [lindex $omethods 0] [lindex $argses 0] $snamebase.0.db"
-	rpc003_assoc_err $popen $sopen $msg
-
-	# Open and associate the secondaries
-	puts "\tRpc003.g: Checking secondaries, both read-only"
-	set pdb [eval {berkdb_open_noerr -env} $env \
-	    -rdonly $pomethod $pargs $pname]
-	error_check_good primary_open2 [is_valid_db $pdb] TRUE
-
-	set sdbs {}
-	for { set i 0 } { $i < [llength $omethods] } { incr i } {
-		set sdb [eval {berkdb_open -env} $env -rdonly \
-		    [lindex $omethods $i] [lindex $argses $i] $snamebase.$i.db]
-		error_check_good second_open2($i) [is_valid_db $sdb] TRUE
-		error_check_good db_associate2($i) \
-		    [eval {$pdb associate} "" $sdb] 0
-		lappend sdbs $sdb
-	}
-	check_secondaries $pdb $sdbs $nentries keys data "Rpc003.h"
+	set status [catch {
+		tclsleep 2
+		set home [file tail $rpc_testdir]
+		set env [eval {berkdb_env_noerr -create -mode 0644 \
+		    -home $home -server $rpc_server}]
+		error_check_good lock_env:open [is_valid_env $env] TRUE
+
+		#
+		# Attempt to send in a NULL callback to associate.  It will
+		# fail if the primary and secondary are not both read-only.
+		#
+		set msg "\tRpc003.d"
+		puts "$msg: Using r/w primary and r/w secondary"
+		set popen "berkdb_open_noerr -env $env $pomethod $pargs $pname"
+		set sopen "berkdb_open_noerr -create -env $env \
+		    [lindex $omethods 0] [lindex $argses 0] $snamebase.0.db"
+		rpc003_assoc_err $popen $sopen $msg
+
+		set msg "\tRpc003.e"
+		puts "$msg: Using r/w primary and read-only secondary"
+		set popen "berkdb_open_noerr -env $env $pomethod $pargs $pname"
+		set sopen "berkdb_open_noerr -env $env -rdonly \
+		    [lindex $omethods 0] [lindex $argses 0] $snamebase.0.db"
+		rpc003_assoc_err $popen $sopen $msg
+
+		set msg "\tRpc003.f"
+		puts "$msg: Using read-only primary and r/w secondary"
+		set popen "berkdb_open_noerr -env $env \
+		    $pomethod -rdonly $pargs $pname"
+		set sopen "berkdb_open_noerr -create -env $env \
+		    [lindex $omethods 0] [lindex $argses 0] $snamebase.0.db"
+		rpc003_assoc_err $popen $sopen $msg
+
+		# Open and associate the secondaries
+		puts "\tRpc003.g: Checking secondaries, both read-only"
+		set pdb [eval {berkdb_open_noerr -env} $env \
+		    -rdonly $pomethod $pargs $pname]
+		error_check_good primary_open2 [is_valid_db $pdb] TRUE
+
+		set sdbs {}
+		for { set i 0 } { $i < [llength $omethods] } { incr i } {
+			set sdb [eval {berkdb_open -env} $env -rdonly \
+			    [lindex $omethods $i] [lindex $argses $i] \
+			    $snamebase.$i.db]
+			error_check_good second_open2($i) \
+			    [is_valid_db $sdb] TRUE
+			error_check_good db_associate2($i) \
+			    [eval {$pdb associate} "" $sdb] 0
+			lappend sdbs $sdb
+		}
+		check_secondaries $pdb $sdbs $nentries keys data "Rpc003.h"
 
-	foreach sdb $sdbs {
-		error_check_good secondary_close [$sdb close] 0
+		foreach sdb $sdbs {
+			error_check_good secondary_close [$sdb close] 0
+		}
+		error_check_good primary_close [$pdb close] 0
+		error_check_good env_close [$env close] 0
+	} res]
+	if { $status != 0 } {
+		puts $res
 	}
-	error_check_good primary_close [$pdb close] 0
-	error_check_good env_close [$env close] 0
-
 	tclkill $dpid
 }
 
 proc rpc003_assoc_err { popen sopen msg } {
+	global rpc_svc
+
 	set pdb [eval $popen]
 	error_check_good assoc_err_popen [is_valid_db $pdb] TRUE
 
@@ -156,11 +170,15 @@ proc rpc003_assoc_err { popen sopen msg } {
 	error_check_good db_associate:rdonly $stat 1
 	error_check_good db_associate:inval [is_substr $ret invalid] 1
 
-	puts "$msg.1: non-NULL callback"
-	set stat [catch {eval $pdb associate [callback_n 0] $sdb} ret]
-	error_check_good db_associate:callback $stat 1
-	error_check_good db_associate:rpc \
-	    [is_substr $ret "not supported in RPC"] 1
+	# The Java and JE RPC servers support callbacks.
+	if { $rpc_svc == "berkeley_db_svc" || \
+	     $rpc_svc == "berkeley_db_cxxsvc" } {
+		puts "$msg.1: non-NULL callback"
+		set stat [catch {eval $pdb associate [callback_n 0] $sdb} ret]
+		error_check_good db_associate:callback $stat 1
+		error_check_good db_associate:inval [is_substr $ret invalid] 1
+	}
+
 	error_check_good assoc_sclose [$sdb close] 0
 	error_check_good assoc_pclose [$pdb close] 0
 }
diff --git a/storage/bdb/test/rpc004.tcl b/storage/bdb/test/rpc004.tcl
index ca1462f3a89df9cb5033c32505af88c790a76ec1..468e27270762062aedb9b66759e8bcab6e038d2e 100644
--- a/storage/bdb/test/rpc004.tcl
+++ b/storage/bdb/test/rpc004.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: rpc004.tcl,v 11.6 2002/07/16 20:53:03 bostic Exp $
+# $Id: rpc004.tcl,v 11.12 2004/01/28 03:36:29 bostic Exp $
 #
 # TEST	rpc004
 # TEST	Test RPC server and security
@@ -12,65 +12,76 @@ proc rpc004 { } {
 	global __debug_print
 	global errorInfo
 	global passwd
+	global has_crypto
 	global rpc_svc
 	source ./include.tcl
 
 	puts "Rpc004: RPC server + security"
-	cleanup $testdir NULL
-	if { [string compare $rpc_server "localhost"] == 0 } {
-	       set dpid [exec $util_path/$rpc_svc \
-		   -h $rpc_testdir -P $passwd &]
-	} else {
-	       set dpid [exec rsh $rpc_server $rpc_path/$rpc_svc \
-		   -h $rpc_testdir -P $passwd &]
+	# Skip test if release does not support encryption.
+	if { $has_crypto == 0 } {
+		puts "Skipping test rpc004 for non-crypto release."
+		return
 	}
+
+	cleanup $testdir NULL
+	set dpid [rpc_server_start 1]
 	puts "\tRpc004.a: Started server, pid $dpid"
 
-	tclsleep 2
-	remote_cleanup $rpc_server $rpc_testdir $testdir
-	puts "\tRpc004.b: Creating environment"
+	#
+	# Wrap the test in a catch statement so we can still kill
+	# the rpc server even if the test fails.
+	#
+	set status [catch {
+		tclsleep 2
+		remote_cleanup $rpc_server $rpc_testdir $testdir
+
+		puts "\tRpc004.b: Creating environment"
 
-	set testfile "rpc004.db"
-	set testfile1 "rpc004a.db"
-	set home [file tail $rpc_testdir]
+		set testfile "rpc004.db"
+		set testfile1 "rpc004a.db"
+		set home [file tail $rpc_testdir]
 
-	set env [eval {berkdb_env -create -mode 0644 -home $home \
-	    -server $rpc_server -encryptaes $passwd -txn}]
-	error_check_good lock_env:open [is_valid_env $env] TRUE
+		set env [eval {berkdb_env -create -mode 0644 -home $home \
+		    -server $rpc_server -encryptaes $passwd -txn}]
+		error_check_good lock_env:open [is_valid_env $env] TRUE
 
-	puts "\tRpc004.c: Opening a non-encrypted database"
-	#
-	# NOTE: the type of database doesn't matter, just use btree.
-	set db [eval {berkdb_open -auto_commit -create -btree -mode 0644} \
-	    -env $env $testfile]
-	error_check_good dbopen [is_valid_db $db] TRUE
+		puts "\tRpc004.c: Opening a non-encrypted database"
+		#
+		# NOTE: the type of database doesn't matter, just use btree.
+		set db [eval {berkdb_open -auto_commit -create -btree \
+		    -mode 0644} -env $env $testfile]
+		error_check_good dbopen [is_valid_db $db] TRUE
 
-	puts "\tRpc004.d: Opening an encrypted database"
-	set db1 [eval {berkdb_open -auto_commit -create -btree -mode 0644} \
-	    -env $env -encrypt $testfile1]
-	error_check_good dbopen [is_valid_db $db1] TRUE
+		puts "\tRpc004.d: Opening an encrypted database"
+		set db1 [eval {berkdb_open -auto_commit -create -btree \
+		    -mode 0644} -env $env -encrypt $testfile1]
+		error_check_good dbopen [is_valid_db $db1] TRUE
 
-	set txn [$env txn]
-	error_check_good txn [is_valid_txn $txn $env] TRUE
-	puts "\tRpc004.e: Put/get on both databases"
-	set key "key"
-	set data "data"
+		set txn [$env txn]
+		error_check_good txn [is_valid_txn $txn $env] TRUE
+		puts "\tRpc004.e: Put/get on both databases"
+		set key "key"
+		set data "data"
 
-	set ret [$db put -txn $txn $key $data]
-	error_check_good db_put $ret 0
-	set ret [$db get -txn $txn $key]
-	error_check_good db_get $ret [list [list $key $data]]
-	set ret [$db1 put -txn $txn $key $data]
-	error_check_good db1_put $ret 0
-	set ret [$db1 get -txn $txn $key]
-	error_check_good db1_get $ret [list [list $key $data]]
+		set ret [$db put -txn $txn $key $data]
+		error_check_good db_put $ret 0
+		set ret [$db get -txn $txn $key]
+		error_check_good db_get $ret [list [list $key $data]]
+		set ret [$db1 put -txn $txn $key $data]
+		error_check_good db1_put $ret 0
+		set ret [$db1 get -txn $txn $key]
+		error_check_good db1_get $ret [list [list $key $data]]
 
-	error_check_good txn_commit [$txn commit] 0
-	error_check_good db_close [$db close] 0
-	error_check_good db1_close [$db1 close] 0
-	error_check_good env_close [$env close] 0
+		error_check_good txn_commit [$txn commit] 0
+		error_check_good db_close [$db close] 0
+		error_check_good db1_close [$db1 close] 0
+		error_check_good env_close [$env close] 0
 
-	# Cleanup our environment because it's encrypted
-	remote_cleanup $rpc_server $rpc_testdir $testdir
+		# Cleanup our environment because it's encrypted
+		remote_cleanup $rpc_server $rpc_testdir $testdir
+	} res]
+	if { $status != 0 } {
+		puts $res
+	}
 	tclkill $dpid
 }
diff --git a/storage/bdb/test/rpc005.tcl b/storage/bdb/test/rpc005.tcl
index f46e7355e5ad4e3a9ee6aa8578040aa581067c2e..3111f651b16d6ed5aa9dc00425b8b038eaff7ea5 100644
--- a/storage/bdb/test/rpc005.tcl
+++ b/storage/bdb/test/rpc005.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: rpc005.tcl,v 11.4 2002/07/16 20:53:03 bostic Exp $
+# $Id: rpc005.tcl,v 11.11 2004/09/22 18:01:06 bostic Exp $
 #
 # TEST	rpc005
 # TEST	Test RPC server handle ID sharing
@@ -12,126 +12,147 @@ proc rpc005 { } {
 	global __debug_print
 	global errorInfo
 	global rpc_svc
+	global is_hp_test
 	source ./include.tcl
 
 	puts "Rpc005: RPC server handle sharing"
-	if { [string compare $rpc_server "localhost"] == 0 } {
-	       set dpid [exec $util_path/$rpc_svc \
-		   -h $rpc_testdir &]
-	} else {
-	       set dpid [exec rsh $rpc_server $rpc_path/$rpc_svc \
-		   -h $rpc_testdir &]
-	}
+	set dpid [rpc_server_start]
 	puts "\tRpc005.a: Started server, pid $dpid"
 
-	tclsleep 2
-	remote_cleanup $rpc_server $rpc_testdir $testdir
-	puts "\tRpc005.b: Creating environment"
-
-	set testfile "rpc005.db"
-	set testfile1 "rpc005a.db"
-	set subdb1 "subdb1"
-	set subdb2 "subdb2"
-	set home [file tail $rpc_testdir]
-
-	set env [eval {berkdb_env -create -mode 0644 -home $home \
-	    -server $rpc_server -txn}]
-	error_check_good lock_env:open [is_valid_env $env] TRUE
-
-	puts "\tRpc005.c: Compare identical and different configured envs"
-	set env_ident [eval {berkdb_env -home $home \
-	    -server $rpc_server -txn}]
-	error_check_good lock_env:open [is_valid_env $env_ident] TRUE
-
-	set env_diff [eval {berkdb_env -home $home \
-	    -server $rpc_server -txn nosync}]
-	error_check_good lock_env:open [is_valid_env $env_diff] TRUE
-
-	error_check_good ident:id [$env rpcid] [$env_ident rpcid]
-	error_check_bad diff:id [$env rpcid] [$env_diff rpcid]
-
-	error_check_good envclose [$env_diff close] 0
-	error_check_good envclose [$env_ident close] 0
-
-	puts "\tRpc005.d: Opening a database"
-	set db [eval {berkdb_open -auto_commit -create -btree -mode 0644} \
-	    -env $env $testfile]
-	error_check_good dbopen [is_valid_db $db] TRUE
-
-	puts "\tRpc005.e: Compare identical and different configured dbs"
-	set db_ident [eval {berkdb_open -btree} -env $env $testfile]
-	error_check_good dbopen [is_valid_db $db_ident] TRUE
-
-	set db_diff [eval {berkdb_open -btree} -env $env -rdonly $testfile]
-	error_check_good dbopen [is_valid_db $db_diff] TRUE
-
-	set db_diff2 [eval {berkdb_open -btree} -env $env -rdonly $testfile]
-	error_check_good dbopen [is_valid_db $db_diff2] TRUE
-
-	error_check_good ident:id [$db rpcid] [$db_ident rpcid]
-	error_check_bad diff:id [$db rpcid] [$db_diff rpcid]
-	error_check_good ident2:id [$db_diff rpcid] [$db_diff2 rpcid]
-
-	error_check_good db_close [$db_ident close] 0
-	error_check_good db_close [$db_diff close] 0
-	error_check_good db_close [$db_diff2 close] 0
-	error_check_good db_close [$db close] 0
-
-	puts "\tRpc005.f: Compare with a database and subdatabases"
-	set db [eval {berkdb_open -auto_commit -create -btree -mode 0644} \
-	    -env $env $testfile1 $subdb1]
-	error_check_good dbopen [is_valid_db $db] TRUE
-	set dbid [$db rpcid]
-
-	set db2 [eval {berkdb_open -auto_commit -create -btree -mode 0644} \
-	    -env $env $testfile1 $subdb2]
-	error_check_good dbopen [is_valid_db $db2] TRUE
-	set db2id [$db2 rpcid]
-	error_check_bad 2subdb:id $dbid $db2id
-
-	set db_ident [eval {berkdb_open -btree} -env $env $testfile1 $subdb1]
-	error_check_good dbopen [is_valid_db $db_ident] TRUE
-	set identid [$db_ident rpcid]
-
-	set db_ident2 [eval {berkdb_open -btree} -env $env $testfile1 $subdb2]
-	error_check_good dbopen [is_valid_db $db_ident2] TRUE
-	set ident2id [$db_ident2 rpcid]
-
-	set db_diff1 [eval {berkdb_open -btree} -env $env -rdonly \
-	    $testfile1 $subdb1]
-	error_check_good dbopen [is_valid_db $db_diff1] TRUE
-	set diff1id [$db_diff1 rpcid]
-
-	set db_diff2 [eval {berkdb_open -btree} -env $env -rdonly \
-	    $testfile1 $subdb2]
-	error_check_good dbopen [is_valid_db $db_diff2] TRUE
-	set diff2id [$db_diff2 rpcid]
-
-	set db_diff [eval {berkdb_open -unknown} -env $env -rdonly $testfile1]
-	error_check_good dbopen [is_valid_db $db_diff] TRUE
-	set diffid [$db_diff rpcid]
-
-	set db_diff2a [eval {berkdb_open -btree} -env $env -rdonly \
-	    $testfile1 $subdb2]
-	error_check_good dbopen [is_valid_db $db_diff2a] TRUE
-	set diff2aid [$db_diff2a rpcid]
-
-	error_check_good ident:id $dbid $identid
-	error_check_good ident2:id $db2id $ident2id
-	error_check_bad diff:id $dbid $diffid
-	error_check_bad diff2:id $db2id $diffid
-	error_check_bad diff3:id $diff2id $diffid
-	error_check_bad diff4:id $diff1id $diffid
-	error_check_good diff2a:id $diff2id $diff2aid
-
-	error_check_good db_close [$db_ident close] 0
-	error_check_good db_close [$db_ident2 close] 0
-	error_check_good db_close [$db_diff close] 0
-	error_check_good db_close [$db_diff1 close] 0
-	error_check_good db_close [$db_diff2 close] 0
-	error_check_good db_close [$db_diff2a close] 0
-	error_check_good db_close [$db2 close] 0
-	error_check_good db_close [$db close] 0
-	error_check_good env_close [$env close] 0
+	#
+	# Wrap the test in a catch statement so we can still kill
+	# the rpc server even if the test fails.
+	#
+	set status [catch {
+		tclsleep 2
+		remote_cleanup $rpc_server $rpc_testdir $testdir
+		puts "\tRpc005.b: Creating environment"
+
+		set testfile "rpc005.db"
+		set testfile1 "rpc005a.db"
+		set subdb1 "subdb1"
+		set subdb2 "subdb2"
+		set home [file tail $rpc_testdir]
+
+		set env [eval {berkdb_env -create -mode 0644 -home $home \
+		    -server $rpc_server -txn}]
+		error_check_good lock_env:open [is_valid_env $env] TRUE
+
+		# You can't open two handles on the same env in
+		# HP-UX, so skip this piece.
+		if { $is_hp_test == 1 } {
+			puts "\tRpc005.c: Skipping for HP-UX."
+		} else {
+			puts "\tRpc005.c: Compare identical and different \
+			    configured envs"
+			set env_ident [eval {berkdb_env -home $home \
+			    -server $rpc_server -txn}]
+			error_check_good \
+			    lock_env:open [is_valid_env $env_ident] TRUE
+
+			set env_diff [eval {berkdb_env -home $home \
+			    -server $rpc_server -txn nosync}]
+			error_check_good \
+			    lock_env:open [is_valid_env $env_diff] TRUE
+
+			error_check_good \
+			    ident:id [$env rpcid] [$env_ident rpcid]
+			error_check_bad \
+			    diff:id [$env rpcid] [$env_diff rpcid]
+
+			error_check_good envclose [$env_diff close] 0
+			error_check_good envclose [$env_ident close] 0
+		}
+
+		puts "\tRpc005.d: Opening a database"
+		set db [eval {berkdb_open -auto_commit -create -btree \
+		    -mode 0644} -env $env $testfile]
+		error_check_good dbopen [is_valid_db $db] TRUE
+
+		puts "\tRpc005.e: Compare identical and different \
+		    configured dbs"
+		set db_ident [eval {berkdb_open -btree} -env $env $testfile]
+		error_check_good dbopen [is_valid_db $db_ident] TRUE
+
+		set db_diff [eval {berkdb_open -btree} -env $env -rdonly \
+		    $testfile]
+		error_check_good dbopen [is_valid_db $db_diff] TRUE
+
+		set db_diff2 [eval {berkdb_open -btree} -env $env -rdonly \
+		    $testfile]
+		error_check_good dbopen [is_valid_db $db_diff2] TRUE
+
+		error_check_good ident:id [$db rpcid] [$db_ident rpcid]
+		error_check_bad diff:id [$db rpcid] [$db_diff rpcid]
+		error_check_good ident2:id [$db_diff rpcid] [$db_diff2 rpcid]
+
+		error_check_good db_close [$db_ident close] 0
+		error_check_good db_close [$db_diff close] 0
+		error_check_good db_close [$db_diff2 close] 0
+		error_check_good db_close [$db close] 0
+
+		puts "\tRpc005.f: Compare with a database and subdatabases"
+		set db [eval {berkdb_open -auto_commit -create -btree \
+		    -mode 0644} -env $env $testfile1 $subdb1]
+		error_check_good dbopen [is_valid_db $db] TRUE
+		set dbid [$db rpcid]
+
+		set db2 [eval {berkdb_open -auto_commit -create -btree \
+		    -mode 0644} -env $env $testfile1 $subdb2]
+		error_check_good dbopen [is_valid_db $db2] TRUE
+		set db2id [$db2 rpcid]
+		error_check_bad 2subdb:id $dbid $db2id
+
+		set db_ident [eval {berkdb_open -btree} -env $env \
+		    $testfile1 $subdb1]
+		error_check_good dbopen [is_valid_db $db_ident] TRUE
+		set identid [$db_ident rpcid]
+
+		set db_ident2 [eval {berkdb_open -btree} -env $env \
+		    $testfile1 $subdb2]
+		error_check_good dbopen [is_valid_db $db_ident2] TRUE
+		set ident2id [$db_ident2 rpcid]
+
+		set db_diff1 [eval {berkdb_open -btree} -env $env -rdonly \
+		    $testfile1 $subdb1]
+		error_check_good dbopen [is_valid_db $db_diff1] TRUE
+		set diff1id [$db_diff1 rpcid]
+
+		set db_diff2 [eval {berkdb_open -btree} -env $env -rdonly \
+		    $testfile1 $subdb2]
+		error_check_good dbopen [is_valid_db $db_diff2] TRUE
+		set diff2id [$db_diff2 rpcid]
+
+		set db_diff [eval {berkdb_open -unknown} -env $env -rdonly \
+		    $testfile1]
+		error_check_good dbopen [is_valid_db $db_diff] TRUE
+		set diffid [$db_diff rpcid]
+
+		set db_diff2a [eval {berkdb_open -btree} -env $env -rdonly \
+		    $testfile1 $subdb2]
+		error_check_good dbopen [is_valid_db $db_diff2a] TRUE
+		set diff2aid [$db_diff2a rpcid]
+
+		error_check_good ident:id $dbid $identid
+		error_check_good ident2:id $db2id $ident2id
+		error_check_bad diff:id $dbid $diffid
+		error_check_bad diff2:id $db2id $diffid
+		error_check_bad diff3:id $diff2id $diffid
+		error_check_bad diff4:id $diff1id $diffid
+		error_check_good diff2a:id $diff2id $diff2aid
+
+		error_check_good db_close [$db_ident close] 0
+		error_check_good db_close [$db_ident2 close] 0
+		error_check_good db_close [$db_diff close] 0
+		error_check_good db_close [$db_diff1 close] 0
+		error_check_good db_close [$db_diff2 close] 0
+		error_check_good db_close [$db_diff2a close] 0
+		error_check_good db_close [$db2 close] 0
+		error_check_good db_close [$db close] 0
+		error_check_good env_close [$env close] 0
+	} res]
+	if { $status != 0 } {
+		puts $res
+	}
 	tclkill $dpid
 }
diff --git a/storage/bdb/test/rsrc001.tcl b/storage/bdb/test/rsrc001.tcl
index 1d57769fda2f12014135eb6c5a8b61b5efcc19b5..b44d5ebd642b13dca29bf20227e4700440190a52 100644
--- a/storage/bdb/test/rsrc001.tcl
+++ b/storage/bdb/test/rsrc001.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: rsrc001.tcl,v 11.23 2002/01/11 15:53:33 bostic Exp $
+# $Id: rsrc001.tcl,v 11.25 2004/01/28 03:36:29 bostic Exp $
 #
 # TEST	rsrc001
 # TEST	Recno backing file test.  Try different patterns of adding
diff --git a/storage/bdb/test/rsrc002.tcl b/storage/bdb/test/rsrc002.tcl
index 0cb3cf752e6aa7be43dcf0bf1b17165620735051..808159a01e08873a24538efbf37757d9a986f26d 100644
--- a/storage/bdb/test/rsrc002.tcl
+++ b/storage/bdb/test/rsrc002.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: rsrc002.tcl,v 11.14 2002/01/11 15:53:33 bostic Exp $
+# $Id: rsrc002.tcl,v 11.16 2004/01/28 03:36:29 bostic Exp $
 #
 # TEST	rsrc002
 # TEST	Recno backing file test #2: test of set_re_delim.  Specify a backing
diff --git a/storage/bdb/test/rsrc003.tcl b/storage/bdb/test/rsrc003.tcl
index f357a1e7f80d8629c6afe146a51b48975da36d1b..b62a6bcb15ea56ef2738956c11ba2600a3dd4c36 100644
--- a/storage/bdb/test/rsrc003.tcl
+++ b/storage/bdb/test/rsrc003.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: rsrc003.tcl,v 11.5 2002/01/11 15:53:33 bostic Exp $
+# $Id: rsrc003.tcl,v 11.7 2004/01/28 03:36:29 bostic Exp $
 #
 # TEST	rsrc003
 # TEST	Recno backing file test.  Try different patterns of adding
diff --git a/storage/bdb/test/rsrc004.tcl b/storage/bdb/test/rsrc004.tcl
index f6c2f997eb80b1928eb3e936d5577fde63e26061..20f11372a17c204febb53e0872071de0af48a162 100644
--- a/storage/bdb/test/rsrc004.tcl
+++ b/storage/bdb/test/rsrc004.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2001-2002
+# Copyright (c) 2001-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: rsrc004.tcl,v 11.3 2002/01/11 15:53:33 bostic Exp $
+# $Id: rsrc004.tcl,v 11.5 2004/01/28 03:36:29 bostic Exp $
 #
 # TEST	rsrc004
 # TEST	Recno backing file test for EOF-terminated records.
diff --git a/storage/bdb/test/scr001/chk.code b/storage/bdb/test/scr001/chk.code
index eb01d8614b3eacc7bf8f54f2d3755cf5beed9167..159524d27e135fb730e2c7c7d94a38844ae537c2 100644
--- a/storage/bdb/test/scr001/chk.code
+++ b/storage/bdb/test/scr001/chk.code
@@ -1,12 +1,12 @@
 #!/bin/sh -
 #
-# $Id: chk.code,v 1.10 2002/02/04 16:03:26 bostic Exp $
+# $Id: chk.code,v 1.14 2004/11/08 14:45:07 bostic Exp $
 #
 # Check to make sure that the code samples in the documents build.
 
-d=../..
+d=../../../db_docs
 
-[ -d $d/docs_src ] || {
+[ -d $d ] || {
 	echo 'FAIL: cannot find source distribution directory.'
 	exit 1
 }
@@ -15,7 +15,8 @@ d=../..
 	exit 1
 }
 
-for i in `find $d/docs_src -name '*.cs'`; do
+exitv=0
+for i in `find $d -name '*.cs'`; do
 	echo "	compiling $i"
 	sed -e 's/m4_include(\(.*\))/#include <\1>/g' \
 	    -e 's/m4_[a-z]*[(\[)]*//g' \
@@ -26,12 +27,12 @@ for i in `find $d/docs_src -name '*.cs'`; do
 	    -e 's/__LB__/[/g' \
 	    -e 's/__LT__/</g' \
 	    -e 's/__RB__/]/g' < $i > t.c
-	if cc -Wall -Werror -I.. t.c ../libdb.a -o t; then
+	if cc -pthread -Wall -Werror -I.. t.c ../libdb.a -o t; then
 		:
 	else
 		echo "FAIL: unable to compile $i"
-		exit 1
+		exitv=1
 	fi
 done
 
-exit 0
+exit $exitv
diff --git a/storage/bdb/test/scr003/chk.define b/storage/bdb/test/scr003/chk.define
index f73355eddf6d0431be2ea2d1540b4c31b73794a0..96c45c2b7d7af4471079b1914eb567e407d8a4f5 100644
--- a/storage/bdb/test/scr003/chk.define
+++ b/storage/bdb/test/scr003/chk.define
@@ -1,8 +1,9 @@
 #!/bin/sh -
 #
-# $Id: chk.define,v 1.21 2002/03/27 04:32:58 bostic Exp $
+# $Id: chk.define,v 1.25 2004/10/07 18:54:37 bostic Exp $
 #
 # Check to make sure that all #defines are actually used.
+# Check to make sure that all #defines start in column 1.
 
 d=../..
 
@@ -16,12 +17,20 @@ t1=__1
 t2=__2
 t3=__3
 
+find $d -name '*.c' -o -name '*.cpp' |
+    sed -e '/\/php_db4\//d' |
+    xargs egrep '^[	 ][	 ]*#' > $t1
+test -s $t1 && {
+	echo "FAIL: found #defines with leading white space:"
+	cat $t1
+	exit 1
+}
+
 egrep '^#define' $d/dbinc/*.h $d/dbinc/*.in |
-    sed -e '/db_185.in/d' -e '/xa.h/d' |
+    sed -e '/db_185.in/d' -e '/queue.h/d' -e '/xa.h/d' |
     awk '{print $2}' |
     sed -e '/^B_DELETE/d' \
 	-e '/^B_MAX/d' \
-	-e '/^CIRCLEQ_/d' \
 	-e '/^DB_BTREEOLDVER/d' \
 	-e '/^DB_HASHOLDVER/d' \
 	-e '/^DB_LOCKVERSION/d' \
@@ -31,10 +40,11 @@ egrep '^#define' $d/dbinc/*.h $d/dbinc/*.in |
 	-e '/^DB_UNUSED/d' \
 	-e '/^DEFINE_DB_CLASS/d' \
 	-e '/^HASH_UNUSED/d' \
-	-e '/^LIST_/d' \
+	-e '/^HPUX_MUTEX_PAD/d' \
 	-e '/^LOG_OP/d' \
 	-e '/^MINFILL/d' \
 	-e '/^MUTEX_FIELDS/d' \
+	-e '/^NAME_TO_SEQUENCE/d' \
 	-e '/^NCACHED2X/d' \
 	-e '/^NCACHED30/d' \
 	-e '/^PAIR_MASK/d' \
@@ -45,11 +55,10 @@ egrep '^#define' $d/dbinc/*.h $d/dbinc/*.in |
 	-e '/^QPAGE_CHKSUM/d' \
 	-e '/^QPAGE_NORMAL/d' \
 	-e '/^QPAGE_SEC/d' \
-	-e '/^SH_CIRCLEQ_/d' \
-	-e '/^SH_LIST_/d' \
-	-e '/^SH_TAILQ_/d' \
 	-e '/^SIZEOF_PAGE/d' \
 	-e '/^TAILQ_/d' \
+	-e '/^UINT64_FMT/d' \
+	-e '/^UINT64_MAX/d' \
 	-e '/^WRAPPED_CLASS/d' \
 	-e '/^__BIT_TYPES_DEFINED__/d' \
 	-e '/^__DBC_INTERNAL/d' \
diff --git a/storage/bdb/test/scr004/chk.javafiles b/storage/bdb/test/scr004/chk.javafiles
index d30c5e3e779900445ec192ff574f38e066c05599..98fb1aff23f2f4a22a219bc0c41139d5f4316af2 100644
--- a/storage/bdb/test/scr004/chk.javafiles
+++ b/storage/bdb/test/scr004/chk.javafiles
@@ -1,6 +1,6 @@
 #!/bin/sh -
 #
-# $Id: chk.javafiles,v 1.5 2002/01/30 19:50:52 bostic Exp $
+# $Id: chk.javafiles,v 1.7 2003/08/01 18:14:45 gburd Exp $
 #
 # Check to make sure we haven't forgotten to add any Java files to the list
 # of source files in the Makefile.
@@ -13,14 +13,13 @@ d=../..
 }
 
 f=$d/dist/Makefile.in
-j=$d/java/src/com/sleepycat
 
 t1=__1
 t2=__2
 
-find $j/db/ $j/examples $d/rpc_server/java -name \*.java -print |
-    sed -e 's/^.*\///' | sort > $t1
-tr ' \t' '\n' < $f | sed -e '/\.java$/!d' -e 's/^.*\///' | sort > $t2
+find $d/java $d/examples_java $d/rpc_server/java -name \*.java -print |
+    sed -e 's/^.*\///' | sort -u > $t1
+tr ' \t' '\n' < $f | sed -e '/\.java$/!d' -e 's/^.*\///' | sort -u > $t2
 
 cmp $t1 $t2 > /dev/null || {
 	echo "<<< java source files >>> Makefile"
diff --git a/storage/bdb/test/scr005/chk.nl b/storage/bdb/test/scr005/chk.nl
index 47c7ff74d4beb82c5369d25da8b4c76a7b326ae6..c6ccaab692011fe44fde2324e8b1f2080b1d9a02 100644
--- a/storage/bdb/test/scr005/chk.nl
+++ b/storage/bdb/test/scr005/chk.nl
@@ -1,6 +1,6 @@
 #!/bin/sh -
 #
-# $Id: chk.nl,v 1.6 2002/01/07 15:12:12 bostic Exp $
+# $Id: chk.nl,v 1.7 2003/09/30 19:16:42 bostic Exp $
 #
 # Check to make sure that there are no trailing newlines in __db_err calls.
 
@@ -54,7 +54,8 @@ chk(fp, name)
 			++line;
 			continue;
 		}
-		if (ch != '_') continue;
+		if (!isspace(ch)) continue;
+		if ((ch = getc(fp)) != '_') continue;
 		if ((ch = getc(fp)) != '_') continue;
 		if ((ch = getc(fp)) != 'd') continue;
 		if ((ch = getc(fp)) != 'b') continue;
@@ -62,6 +63,7 @@ chk(fp, name)
 		if ((ch = getc(fp)) != 'e') continue;
 		if ((ch = getc(fp)) != 'r') continue;
 		if ((ch = getc(fp)) != 'r') continue;
+		if ((ch = getc(fp)) != '(') continue;
 		while ((ch = getc(fp)) != '"') {
 			if (ch == EOF)
 				return (exitv);
diff --git a/storage/bdb/test/scr006/chk.offt b/storage/bdb/test/scr006/chk.offt
index 6800268d2a2357031327f7ac8efed7c9564eb45c..69bf7cc92190184474a11d88c8467b769bf7c39d 100644
--- a/storage/bdb/test/scr006/chk.offt
+++ b/storage/bdb/test/scr006/chk.offt
@@ -1,6 +1,6 @@
 #!/bin/sh -
 #
-# $Id: chk.offt,v 1.9 2001/10/26 13:40:15 bostic Exp $
+# $Id: chk.offt,v 1.13 2004/10/07 18:57:53 bostic Exp $
 #
 # Make sure that no off_t's have snuck into the release.
 
@@ -15,14 +15,30 @@ t=__1
 
 egrep -w off_t $d/*/*.[ch] $d/*/*.in |
 sed -e "/#undef off_t/d" \
+    -e "/db_env_set_func_ftruncate/d" \
+    -e "/db_env_set_func_pread/d" \
+    -e "/db_env_set_func_pwrite/d" \
+    -e "/db_env_set_func_seek/d" \
+    -e "/j_ftruncate/d" \
+    -e "/j_pread/d" \
+    -e "/j_pwrite/d" \
+    -e "/j_seek/d" \
     -e "/mp_fopen.c:.*can't use off_t's here/d" \
     -e "/mp_fopen.c:.*size or type off_t's or/d" \
     -e "/mp_fopen.c:.*where an off_t is 32-bits/d" \
     -e "/mutex\/tm.c:/d" \
     -e "/os_map.c:.*(off_t)0))/d" \
-    -e "/os_rw.c:.*(off_t)db_iop->pgno/d" \
+    -e "/os_method.c.*func_ftruncate/d" \
+    -e "/os_method.c.*func_pread/d" \
+    -e "/os_method.c.*func_pwrite/d" \
+    -e "/os_method.c.*func_seek/d" \
+    -e "/os_method.c.*__P.*off_t/d" \
+    -e "/os_rw.c:/d" \
     -e "/os_seek.c:.*off_t offset;/d" \
     -e "/os_seek.c:.*offset = /d" \
+    -e "/os_truncate.c:.*off_t offset;/d" \
+    -e "/os_truncate.c:.*off_t stat_offset;/d" \
+    -e "/os_truncate.c:.*offset = /d" \
     -e "/test_perf\/perf_misc.c:/d" \
     -e "/test_server\/dbs.c:/d" \
     -e "/test_vxworks\/vx_mutex.c:/d" > $t
diff --git a/storage/bdb/test/scr007/chk.proto b/storage/bdb/test/scr007/chk.proto
index ae406fa23fef19a68b1437245819a20d146ba6d9..05e980ce6fca69e5dd9b62ca53286eb96427ca25 100644
--- a/storage/bdb/test/scr007/chk.proto
+++ b/storage/bdb/test/scr007/chk.proto
@@ -1,6 +1,6 @@
 #!/bin/sh -
 #
-# $Id: chk.proto,v 1.8 2002/03/27 04:32:59 bostic Exp $
+# $Id: chk.proto,v 1.10 2003/12/08 19:28:26 bostic Exp $
 #
 # Check to make sure that prototypes are actually needed.
 
@@ -26,13 +26,12 @@ egrep '__P' $d/dbinc_auto/*.h |
     -e '/__db_util_arg/d' \
     -e '/__ham_func2/d' \
     -e '/__ham_func3/d' \
-    -e '/_getpgnos/d' \
     -e '/_print$/d' \
     -e '/_read$/d' > $t1
 
 find $d -name '*.in' -o -name '*.[ch]' -o -name '*.cpp' > $t2
 for i in `cat $t1`; do
-	c=$(egrep -low $i $(cat $t2) | wc -l)
+	c=$(egrep -Hlw $i $(cat $t2) | wc -l)
 	echo "$i: $c"
 done | egrep ' 1$' > $t3
 
diff --git a/storage/bdb/test/scr008/chk.pubdef b/storage/bdb/test/scr008/chk.pubdef
index 4f59e831b25d9c16235c80c6d4595c671560efed..f5e66ccbc69e7a85ec935d8280238c67af47703a 100644
--- a/storage/bdb/test/scr008/chk.pubdef
+++ b/storage/bdb/test/scr008/chk.pubdef
@@ -3,6 +3,7 @@
 # Reconcile the list of public defines with the man pages and the Java files.
 
 d=../..
+docs=$d/../db_docs
 
 [ -f $d/LICENSE ] || {
 	echo 'FAIL: cannot find source distribution directory.'
@@ -13,8 +14,13 @@ p=$d/dist/pubdef.in
 
 exitv=0
 
-# Check that pubdef.in has everything listed in m4.links.
-f=$d/docs_src/m4/m4.links
+cat <<END_OF_TEXT
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+Check that pubdef.in has everything listed in m4.links.
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+END_OF_TEXT
+
+f=$docs/m4/m4.links
 sed -n \
     -e 's/^\$1, \(DB_[^,]*\).*/\1/p' \
     -e d < $f |
@@ -27,8 +33,13 @@ while read name; do
 	fi
 done
 
-# Check that m4.links has everything listed in pubdef.in.
-f=$d/docs_src/m4/m4.links
+cat <<END_OF_TEXT
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+Check that m4.links has everything listed in pubdef.in.
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+END_OF_TEXT
+
+f=$docs/m4/m4.links
 sed '/^#/d' $p |
 while read name isdoc isinc isjava; do
 	if `egrep -w "^.1, $name" $f > /dev/null`; then
@@ -44,10 +55,15 @@ while read name isdoc isinc isjava; do
 	fi
 done
 
-# Check that pubdef.in has everything listed in db.in.
+cat <<END_OF_TEXT
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+Check that pubdef.in has everything listed in db.in.
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+END_OF_TEXT
+
 f=$d/dbinc/db.in
 sed -n \
-    -e 's/^#define[	 ]*\(DB_[A-Z_0-9]*\).*/\1/p' \
+    -e 's/^#define[	 ]*\(DB_[A-Z_0-9][A-Z_0-9]*\).*/\1/p' \
     -e 's/^[	 ]*\(DB_[A-Z_]*\)=[0-9].*/\1/p' \
     -e d < $f |
 while read name; do
@@ -59,7 +75,12 @@ while read name; do
 	fi
 done
 
-# Check that db.in has everything listed in pubdef.in.
+cat <<END_OF_TEXT
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+Check that db.in has everything listed in pubdef.in.
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+END_OF_TEXT
+
 f=$d/dbinc/db.in
 sed '/^#/d' $p |
 while read name isdoc isinc isjava; do
@@ -77,9 +98,15 @@ while read name isdoc isinc isjava; do
 	fi
 done
 
-# Check that pubdef.in has everything listed in DbConstants.java.
-f=$d/java/src/com/sleepycat/db/DbConstants.java
-sed -n -e 's/.*static final int[	 ]*\([^ 	]*\).*/\1/p' < $f |
+cat <<END_OF_TEXT
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+Check that pubdef.in has everything listed in DbConstants.java.
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+END_OF_TEXT
+
+j=$d/java/src/com/sleepycat/db
+f=$j/internal/DbConstants.java
+sed -n -e 's/.*int[	 ]\([^ 	]*\).*;/\1/p' < $f |
 while read name; do
 	if `egrep -w "$name" $p > /dev/null`; then
 		:
@@ -89,11 +116,16 @@ while read name; do
 	fi
 done
 
-# Check that DbConstants.java has everything listed in pubdef.in.
-f=$d/java/src/com/sleepycat/db/DbConstants.java
+cat <<END_OF_TEXT
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+Check that DbConstants.java has everything listed in pubdef.in.
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+END_OF_TEXT
+
+f=$j/internal/DbConstants.java
 sed '/^#/d' $p |
 while read name isdoc isinc isjava; do
-	if `egrep -w "static final int[	 ]$name =" $f > /dev/null`; then
+	if `egrep -w "int[	 ]$name =" $f > /dev/null`; then
 		[ "X$isjava" != "XJ" ] && {
 			echo "$name should not appear in $f"
 			exitv=1
@@ -106,71 +138,45 @@ while read name isdoc isinc isjava; do
 	fi
 done
 
-# Check that pubdef.in has everything listed in Db.java.
-f=$d/java/src/com/sleepycat/db/Db.java
-sed -n -e 's/.*static final int[	 ]*\([^ 	;]*\).*/\1/p' < $f |
-while read name; do
-	if `egrep -w "$name" $p > /dev/null`; then
-		:
-	else
-		echo "$f: $name is missing from $p"
-		exitv=1;
-	fi
-done
-sed -n -e 's/^[	 ]*\([^	 ]*\) = DbConstants\..*/\1/p' < $f |
-while read name; do
-	if `egrep -w "$name" $p > /dev/null`; then
-		:
-	else
-		echo "$f: $name is missing from $p"
-		exitv=1
-	fi
-done
+cat <<END_OF_TEXT
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+Check that all constants in pubdef.in are wrapped by the Java API.
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+END_OF_TEXT
 
-# Check that Db.java has all of the Java case values listed in pubdef.in.
-# Any J entries should appear twice -- once as a static final int, with
-# no initialization value, and once assigned to the DbConstants value.  Any
-# C entries should appear once as a static final int, with an initialization
-# value.
-f=$d/java/src/com/sleepycat/db/Db.java
-sed '/^#/d' $p |
-while read name isdoc isinc isjava; do
-	if `egrep -w "static final int[	 ]$name;$" $f > /dev/null`; then
-		[ "X$isjava" != "XJ" ] && {
-			echo "$name should not appear in $f"
-			exitv=1
-		}
-	else
-		[ "X$isjava" = "XJ" ] && {
-			echo "$name does not appear in $f"
-			exitv=1
-		}
-	fi
-done
 sed '/^#/d' $p |
 while read name isdoc isinc isjava; do
-	if `egrep -w "= DbConstants.$name;" $f > /dev/null`; then
+	if `egrep -w "$name" $j/*.java $d/rpc_server/java/*.java \
+	    $j/internal/Db.java $j/internal/DbEnv.java \
+	    $j/internal/db_javaJNI.java > /dev/null`; then
 		[ "X$isjava" != "XJ" ] && {
-			echo "$name should not appear in $f"
+			echo "$name should not appear in the Java API"
 			exitv=1
 		}
 	else
 		[ "X$isjava" = "XJ" ] && {
-			echo "$name does not appear in $f"
+			echo "$name does not appear in the Java API"
 			exitv=1
 		}
 	fi
 done
+
+cat <<END_OF_TEXT
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+Check that all constants in pubdef.in are wrapped by the Java native layer.
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+END_OF_TEXT
+
 sed '/^#/d' $p |
 while read name isdoc isinc isjava; do
-	if `egrep "static final int[	 ]$name =.*;" $f > /dev/null`; then
-		[ "X$isjava" != "XC" ] && {
-			echo "$name should not appear in $f"
+	if `egrep -w "$name" $d/libdb_java/db_java_wrap.c > /dev/null`; then
+		[ "X$isjava" != "XN" ] && [ "X$isjava" != "XJ" ] && {
+			echo "$name should not appear in the Java native layer"
 			exitv=1
 		}
 	else
-		[ "X$isjava" = "XC" ] && {
-			echo "$name does not appear in $f"
+		[ "X$isjava" = "XN" ] && {
+			echo "$name does not appear in the Java native layer"
 			exitv=1
 		}
 	fi
diff --git a/storage/bdb/test/scr009/chk.srcfiles b/storage/bdb/test/scr009/chk.srcfiles
index 4f09a2890f614bdefa1fd65927e6a37ff27b2e74..18fc636928863aa234ac474bb3dffb35f5586ded 100644
--- a/storage/bdb/test/scr009/chk.srcfiles
+++ b/storage/bdb/test/scr009/chk.srcfiles
@@ -1,6 +1,6 @@
 #!/bin/sh -
 #
-# $Id: chk.srcfiles,v 1.10 2002/02/04 22:25:33 bostic Exp $
+# $Id: chk.srcfiles,v 1.13 2004/10/07 19:16:43 bostic Exp $
 #
 # Check to make sure we haven't forgotten to add any files to the list
 # of source files Win32 uses to build its dsp files.
@@ -17,17 +17,25 @@ t1=__1
 t2=__2
 
 sed -e '/^[ 	#]/d' \
+    -e '/^db_server_clnt.c/d' \
+    -e '/^db_server_svc.c/d' \
+    -e '/^db_server_xdr.c/d' \
+    -e '/^gen_db_server.c/d' \
     -e '/^$/d' < $f |
     awk '{print $1}' > $t1
 find $d -type f |
     sed -e 's/^\.\.\/\.\.\///' \
         -e '/^build[^_]/d' \
+        -e '/^libdb_java\/java_stat_auto.c/d' \
+        -e '/^mod_db4\//d' \
+        -e '/^perl\//d' \
+        -e '/^php_db4\//d' \
+        -e '/^rpc_server\/c\/gen_db_server.c/d' \
         -e '/^test\//d' \
         -e '/^test_server/d' \
         -e '/^test_thread/d' \
         -e '/^test_vxworks/d' |
     egrep '\.c$|\.cpp$|\.def$|\.rc$' |
-    sed -e '/perl.DB_File\/version.c/d' |
     sort > $t2
 
 cmp $t1 $t2 > /dev/null || {
diff --git a/storage/bdb/test/scr010/chk.str b/storage/bdb/test/scr010/chk.str
index 2b5698c0ff224a641006513cd0bb283f6357d721..873fdb0124acab76d3b7d35d45bf929e1036f9a5 100644
--- a/storage/bdb/test/scr010/chk.str
+++ b/storage/bdb/test/scr010/chk.str
@@ -1,6 +1,6 @@
 #!/bin/sh -
 #
-# $Id: chk.str,v 1.5 2001/10/12 17:55:36 bostic Exp $
+# $Id: chk.str,v 1.9 2004/09/22 18:01:06 bostic Exp $
 #
 # Check spelling in quoted strings.
 
@@ -14,12 +14,13 @@ d=../..
 t1=__t1
 
 sed -e '/^#include/d' \
-    -e '/revid/d' \
     -e '/"/!d' \
     -e 's/^[^"]*//' \
     -e 's/%s/ /g' \
     -e 's/[^"]*$//' \
-    -e 's/\\[nt]/ /g' $d/*/*.c $d/*/*.cpp |
+    -e 's/\\[nt]/ /g' \
+    `find $d -name '*.[ch]' -o -name '*.cpp' -o -name '*.java' |
+    sed '/\/perl\//d'` |
 spell | sort | comm -23 /dev/stdin spell.ok > $t1
 
 test -s $t1 && {
@@ -28,4 +29,14 @@ test -s $t1 && {
 	exit 1
 }
 
+egrep -h '/\* | \* ' \
+    `find $d -name '*.[ch]' -o -name '*.cpp' | sed '/\/perl\//d'` |
+spell | sort | comm -23 /dev/stdin spell.ok | tee /tmp/f/1 > $t1
+
+test -s $t1 && {
+	cat $t1
+	echo "FAIL: found questionable spelling in comments."
+	exit 1
+}
+
 exit 0
diff --git a/storage/bdb/test/scr010/spell.ok b/storage/bdb/test/scr010/spell.ok
index 18af8d1306ddd416d1222884f276c65345ef25ca..6a557279b67b9827477f21e51d71ced6d666d08c 100644
--- a/storage/bdb/test/scr010/spell.ok
+++ b/storage/bdb/test/scr010/spell.ok
@@ -1,66 +1,264 @@
+AAAA
+ABS
+ADDR
 AES
+AIX's
 AJVX
+ALG
+ALLBACK
 ALLDB
+ALLOC
+ALLZEROES
 API
+APIs
 APP
+APPMALLOC
+APPNAME
+APPREC
+ASYNC
+ATOI
+AUTOCOMMIT
+AUTOREMOVE
 AccessExample
+AccesssExample
 Acflmo
+Acknowledgements
 Aclmop
+Aclop
+Adata
+Addr
 Ahlm
 Ahm
+Antoon
+Applock
+ArithmeticException
+Arntzen
+ArrayList
+AssociateCallbacks
+AttachCurrentThread
+Aug
+BBBB
+BC
 BCFILprRsvVxX
 BCc
+BDBXXXXX
 BDBXXXXXX
+BEGID
 BH
+BH's
 BI
 BII
 BINTERNAL
+BITSPERBLOCK
+BKEYDATA
+BLKSIZE
+BNF
+BOTHC
+BOVERFLOW
+BR
+BSIZE
+BTCOMPARE
+BTMETA
 BTREE
+BTREEMAGIC
+BTREEMETA
+BTREEOLDVER
+BTREEVERSION
+BUF
+Backoff
+Barreto
 Bc
+Bdata
 BerkeleyDB
+BigInteger
+BindingSpeedTest
+Bosselaers
 BtRecExample
 Btree
+BtreeStat
+BtreeStats
+Btrees
+BulkAccessExample
+ByteArray
+ByteArrayBinding
+ByteArrayFormat
+ByteArrayInputStream
+ByteArrayOutputStream
+C'est
+CALLBACK
+CALLPGIN
+CBC
+CC
+CCCC
+CCYYMMDDhhmm
 CD
 CDB
 CDS
 CDdFILTVvX
+CFB
 CFILpRsv
 CFLprsvVxX
 CFh
+CHARKEY
+CHGPG
+CHILDCOMMIT
+CHILDINFO
+CHILDINFOs
+CHK
+CHKPNT
+CHKPOINT
 CHKSUM
+CKP
+CKPLSN
+CL
+CLASSPATH
+CLOSEFP
+CLR
+CLRDBC
 CLpsvxX
+CMP
+CNT
+COMPQUIET
+CONCAT
+CONCATDATAKEY
+CONCATKEYDATA
+CONF
 CONFIG
+CONST
+CRTL
+CRYPTO
+CT
+CTX
+CXX
+CacheFilePriority
+CacheFileStats
+CacheStats
+Callback
 CdFILTvX
+Ch
+ClassCastException
+ClassCatalog
+ClassCatalogDB
+ClassInfo
 ClassNotFoundException
+ClientData
+CloseHandle
+Cmd
+Cmp
+CollectionTest
 Config
+CopyObjBytes
+CreateFile
+CreateFileMapping
+CreateHashEntry
+Crypto
+CurrentTransaction
+Cygwin
+DATAHOME
 DBC
+DBCursor
 DBENV
+DBHOME
+DBINFO
+DBLOCAL
+DBLOG
+DBM
+DBMETA
+DBMETASIZE
+DBNAME
 DBP
+DBP's
+DBREG
+DBREP
 DBS
 DBSDIR
 DBT
+DBT's
+DBTCL
+DBTList
 DBTYPE
+DBTs
+DBa
+DBaa
+DBaz
+DBba
 DBcursor
+DBz
+DEADFILE
+DECLS
+DEF
+DEFMINKEYPAGE
+DELNO
+DGREE
+DIR
+DIRECTIO
+DIRENT
+DIST
+DJ
+DLFCN
+DLL
+DOALL
 DONOTINDEX
 DS
+DST
+DSYNC
 DUP
+DUPFIRST
+DUPID
+DUPLAST
 DUPMASTER
+DUPOK
+DUPONLY
+DUPS
+DUPSET
 DUPSORT
+DataBinding
+DataBuffer
+DataCursor
+DataDb
+DataEnvironment
+DataFormat
+DataIndex
+DataInput
+DataInputStream
+DataOutput
+DataOutputStream
+DataStore
+DataThang
+DataType
+DataView
+DatabaseEntry
+DatabaseException
+DatabaseType
 Db
+DbAppDispatch
 DbAppendRecno
+DbAssociate
 DbAttachImpl
 DbBtreeCompare
 DbBtreePrefix
 DbBtreeStat
+DbClient
+DbCount
 DbDeadlockException
+DbDelete
+DbDispatcher
 DbDupCompare
 DbEnv
 DbEnvFeedback
+DbEnvFeedbackHandler
 DbErrcall
+DbErrorHandler
 DbException
 DbFeedback
+DbFeedbackHandler
+DbGet
+DbGetFlags
+DbGetOpenFlags
+DbGetjoin
 DbHash
 DbHashStat
+DbInfoDelete
 DbKeyRange
 DbLock
 DbLockNotGrantedException
@@ -72,214 +270,1351 @@ DbLsn
 DbMemoryException
 DbMpoolFStat
 DbMpoolFile
+DbMpoolFileStat
 DbMpoolStat
+DbMultiple
+DbMultipleDataIterator
+DbMultipleIterator
+DbMultipleKeyDataIterator
+DbMultipleRecnoDataIterator
+DbOpen
+DbOutputStreamErrcall
+DbPanicHandler
 DbPreplist
+DbPut
 DbQueueStat
 DbRecoveryInit
+DbRemove
+DbRename
 DbRepStat
 DbRepTransport
 DbRunRecoveryException
 DbSecondaryKeyCreate
+DbSequence
+DbServer
+DbStat
+DbTestUtil
+DbTruncate
 DbTxn
 DbTxnRecover
 DbTxnStat
+DbUpgrade
 DbUtil
+DbVerify
+DbXA
 DbXAResource
 DbXid
 Dbc
+DbcDup
+DbcGet
+DbcPut
+Dbm
+DbmCommand
+Dbp
+Dbs
 Dbt
+Dbt's
+Dbts
 Dde
+Deadfile
+DeadlockException
+Debian
+DeleteInfo
 Deref'ing
+Dir
+Dups
+EAGAIN
+EBUSY
+ECB
+EEXIST
+EEXISTS
+EFAULT
+EGENCHG
+EID
+EINTR
+EINVAL
 EIO
 EIRT
 EIi
+ELECTINIT
+ELECTVOTE
+EMSG
+ENOENT
+ENOMEM
+ENT
 ENV
+ENV's
+EOFException
+EPG
+EPGNO
+EPHASE
+EPRINT
+EPRINTed
+ETIME
+ETIMEDOUT
+EXCL
+EXT
+Eefh
+Egen
+Elp
+Endian
+EntityBinding
+EnvAttr
 EnvExample
+EnvGetEncryptFlags
 EnvInfoDelete
+EnvOpen
+EnvRemove
+EnvSetErrfile
+EnvSetErrpfx
+EnvSetFlags
+EnvTest
+EnvVerbose
+Equidistributed
+Errcall
+Errfile
+ErrorFunc
+ErrorSetup
+Errpfx
+EvalObjv
+ExampleDatabaseLoad
+ExampleDatabaseRead
+ExceptionUnwrapper
+ExceptionWrapper
+ExceptionWrapperTest
 Exp
+Externalizable
+FALLTHROUGH
+FCNTL
+FCONTROL
+FD
+FDATASYNC
+FF
+FH
+FILEDONE
+FILEID
+FILELIST
+FILENO
+FILEOPEN
+FILEWRITTEN
 FIXEDLEN
+FIXLEN
+FIXME
+FMAP
+FMT
+FN
+FNAME
+FOREACH
+FP
+FST
+FSTAT
+FSTATI
+FTRUNCATE
+FTYPE
+FastInputStream
+FastOutputStream
+FatalRecover
 Fd
 Ff
 Fh
+FileIndexHigh
+FileIndexLow
 FileNotFoundException
+Fileinfo
+FindHashEntry
+FooImp
+Foreach
+ForeignKeyIndex
+ForeignKeyTest
+FreeBSD
+FreeBSD's
+FreeFunc
+FreeList
+Friedl
+GCC
+GETALL
+GETCWD
+GETDYNAMIC
+GETNAME
+GETOPT
+GETRUSAGE
+GETTIME
+GETTIMEOFDAY
+GETUID
+GETZIP
+Gb
+Gcc
+Gentles
+Get's
+GetByteArray
+GetByteArrayFromObj
+GetDiskFreeSpace
 GetFileInformationByHandle
+GetFlags
+GetFlagsList
+GetGlobPrefix
+GetHashValue
+GetIndexFromObj
+GetIntFromObj
 GetJavaVM
 GetJoin
+GetLockDetect
+GetLongFromObj
+GetLsn
+GetOpenFlag
+GetTimeout
+GetUInt
+GetUnsignedIntFromObj
+GetVerbose
+GetVersion
+Gh
+GlobalRefs
+GotRange
+HANDSOFF
+HASHC
+HASHC's
+HASHHDR
+HASHINSERT
+HASHLOOKUP
+HASHMAGIC
+HASHMETA
+HASHOLDVER
+HASHREMOVE
+HASHTAB
+HASHVERSION
+HCommand
+HDR
+HDRs
+HEURCOM
+HEURHAZ
+HEURMIX
+HEURRB
+HKEYDATA
+HMAC
+HMETA
+HOFFDUP
+HOFFPAGE
 HOFFSET
 HOLDELECTION
+HPPA
+HPUX
+HSEARCH
+Harbison
+HashStats
 Hashtable
+HelloDatabaseWorld
+Holder's
+Hsearch
+IA
+IAFTER
+IBEFORE
+IBTREE
+ICURRENT
+IDLETIMEOUT
+IDs
+IIL
+IL
+ILOCK
 ILo
 ILprR
 INDX
+INFOTYPE
+INI
 INIT
+INITED
+INITENV
+INITSPIN
+INMEM
+INMEMORY
+INORDER
+INTTYPES
+INVAL
+INVALIDID
+IOException
+IOExceptionWrapper
+IOSIZE
+IPC
+IR
 IREAD
+IRECNO
+IRGRP
+IRIX
+IROTH
+IRUSR
+ISDUP
+ISPERM
 ISSET
+IV's
+IW
+IWGRP
+IWOTH
 IWR
 IWRITE
+IWUSR
+Ick
+Ids
 Ik
+IllegalArgumentException
+IllegalStateException
+IncrRefCount
+IndexOutOfBoundsException
+Init
+Initialise
+IntegrityConstraintException
+Interp
+InventoryDB
+Istmp
+ItemNameIndexDB
+Itemname
+IterDeadlockTest
+JDB
+JE
+JHB
+JKL
+JNI
+JNIEnv
+JNIs
+JOINCUR
+JOINENV
+JVM
+JZ
+JavaIO
+JavaRPCServer
+JoinTest
+KEYDATA
 KEYEMPTY
 KEYEXIST
+KEYFIRST
+KEYGROUP
+KEYGRP
+KEYLAST
+KEYLEN
+KL
+Kerberos
+KeyExtractor
 KeyRange
+KeyRangeException
+KeyRangeTest
+Krinsky
+LANGLVL
+LASTCKP
 LBTREE
+LCK
+LDF
+LDUP
+LEAFCHAIN
+LEAFLEVEL
+LEAFSEEN
+LFNAME
+LFPREFIX
+LG
+LGPL
+LIBNSL
+LL
 LOCKDOWN
+LOCKOBJ
+LOCKREGION
+LOCKREQ
+LOCKTAB
+LOCKTIMEOUT
+LOCKVERSION
 LOGC
+LOGFILEID
+LOGMAGIC
+LOGOLDVER
+LOGP
+LOGREADY
+LOGSONLY
+LOGVERSION
+LORDER
 LRECNO
+LRECNODUP
 LRU
+LRUness
 LSN
+LSN's
+LSNfile
+LSNoffset
+LSNs
+LSTAT
+LV
+LWARX
+LWP
+LWZ
+Landon
+Lastp
 Lcom
+ListIterator
+ListObjAppendElement
 Ljava
 Ll
+LocalIterator
+LockDetect
+LockDetectMode
 LockExample
+LockGet
+LockMode
+LockNotGrantedException
+LockOperation
+LockRequest
+LockRequestMode
+LockStat
+LockStats
+LockTimeout
+LockVec
+Lockfhp
+LogArchive
+LogCompare
+LogFile
+LogFlush
+LogGet
+LogPut
 LogRegister
+LogSequenceNumber
+LogStat
+LogStats
+Logc
+LogcGet
 LpRsS
 LprRsS
+Lsn
+LtoR
+MALLOC
+MAMAMIA
+MARGO
+MASTERELECT
+MAXARGS
+MAXBQUALSIZE
+MAXBTREELEVEL
+MAXFIELD
+MAXGTRIDSIZE
+MAXID
+MAXINFOSIZE
+MAXLOCKS
+MAXMMAPSIZE
+MAXNR
+MAXPATHLEN
+MAXSIZE
+MAXSIZEONPAGE
+MAXTIMEOUT
+MAXWRITE
+MC
 MEM
+MEMCMP
+MEMCPY
+MEMMAPPED
+MEMMOVE
+MEMP
+METADIRTY
+MFT
+MINCACHE
+MINFO
+MINIT
+MINLOCKS
+MINPAGECACHE
+MINWRITE
+MKS
+MLOCK
+MMAP
 MMDDhhmm
+MNO
+MP
+MPE
+MPFARRAY
 MPOOL
 MPOOLFILE
+MPOOLFILE's
+MPOOLFILEs
+MPREG
+MPREGs
+MSB
+MSC
+MSEM
+MSG
+MSGBUF
+MSHUTDOWN
+MSTR
+MSVC
+MT
+MUNLOCK
+MUNMAP
+MUTEXes
+MYDIRECTORY
+Makoto
+Malloc
+MapEntry
 MapViewOfFile
+Margo
+MarshalledEnt
+MarshalledEntityBinding
+MarshalledKey
+MarshalledKeyBinding
+MarshalledObject
+MarshalledTupleData
+MarshalledTupleEntry
+MarshalledTupleKeyEntity
+Matsumoto
 Maxid
+Maxkey
 Mb
 Mbytes
+MemoryException
+Mempool
+Mersenne
 Metadata
 Metapage
+MinGW
+Minkey
+Misc
+MixColumn
+MoveFile
+MoveFileEx
+Mp
+MpGet
+MpInfoDelete
+MpStat
+MpSync
+MpTrickle
 Mpool
 MpoolExample
+Mpoolfile
+Msg
+MsgType
 Mutex
+Mv
+MyDbs
+NB
+NBUCKET
+NCACHE
+NCACHED
+NDBM
+NDIR
+NEEDSPLIT
+NEEDSWAP
+NEWCLIENT
+NEWFILE
 NEWMASTER
 NEWSITE
 NG
+NOARCHIVE
+NOAUTO
+NOBUFFER
+NOCOPY
 NODUP
 NODUPDATA
+NODUPS
+NOFILE
+NOHEADER
+NOKEY
+NOLOCK
 NOLOCKING
+NOMIGRATE
 NOMMAP
 NOMORE
 NOORDERCHK
+NOOVERWRITE
 NOPANIC
+NOPROMOTE
+NORUN
 NOSERVER
+NOSORT
 NOSYNC
+NOTA
+NOTEXIST
 NOTFOUND
 NOTGRANTED
+NOTPERM
+NOTREACHED
+NOTSET
+NOTUSED
 NOTYPE
+NOTZERO
 NOWAIT
 NP
+NRECS
+NT
+NTFS
+NULL'ing
+NULLXID
+NULLing
+NULLs
+NULs
+NUM
+NUMWRITES
+NameToInfo
+NameToPtr
+Ndbm
+NdbmOpen
+NewInfo
+NewStringObj
+Nishimura
 NoP
 NoqV
 NqV
+Nr
 NrV
 NsV
+Nuff
+NullClassCatalog
+NullPointerException
+NullTransactionRunner
+Num
+Nxt
+OBJ
+ODDFILESIZE
+OFFDUP
+OFFPAGE
 OLDVERSION
+ONC
+OOB
+OP
+OPD
+OPENFILES
+OPFLAGS
+OR'd
 ORDERCHKONLY
+OSF
+OSO
+OUTFILE
+OVFL
+Obj
+ObjectInputStream
+ObjectOutputStream
+ObjectStreamClass
+Objs
 Offpage
+Ol
 OpenFileMapping
+OpenServer
+OperationStatus
+Ops
+Optimised
+OutOfMemoryError
 OutputStream
+PAGEDONE
+PAGEINFO
+PAGEINFOs
+PAGELIST
+PAGEs
+PANIC'd
+PARAMS
+PARENT's
+PBNYC
+PG
+PGDEF
+PGINFO
 PGNO
+PGSIZE
+PHP
 PID
+PKG
+PLIST
+POPENFILES
+POSTDESTROY
+POSTLOG
+POSTLOGMETA
+POSTOPEN
+POSTSYNC
+PPC
+PR
+PREAD
+PREPLIST
 PREV
+PRI
+PRINTFOOTER
+PRINTHEADER
+PROT
+PSIZE
+PSTAT
+PTHREAD
+PWRITE
+PaRisc
+Pagesize
+Pagesizes
+Params
+Part's
+PartBinding
+PartData
+PartKey
+PartKeyBinding
+PartValue
+Paulo
+Perl
+Pg
+PgInit
+PgIsset
+Pgin
 Pgno
+Phong
+PlatformSDK
+Posix
+PowerPC
+PreparedTransaction
+Prev
+PrimaryKeyAssigner
+Proc
+Pthread
+PtrToInfo
+QAM
+QAMDATA
+QAMMAGIC
+QAMMETA
+QAMOLDVER
+QAMVERSION
+QMETA
+QNX
+QPAGE
+QUOTESERVER
+QueueStats
+RB
+RBBASE
+RBCOMMFAIL
+RBDEADLOCK
+RBEND
+RBINTEGRITY
+RBOTHER
+RBPROTO
+RBROLLBACK
+RBTIMEOUT
+RBTRANSIENT
+RCLOSE
+RDONLY
+RDWRMASTER
+READONLY
+REALLOC
+REALLOC'ed
+REC
+RECLEN
 RECNO
 RECNOSYNC
 RECNUM
+RECORDCOUNT
+RECOVERYTEST
+REGENV
+REGINFO
+REGIONs
+REGMAINT
+RELEN
+RELIANTUNIX
+RENAMEMAGIC
+REPLOCKED
+REPQUOTE
+REPVERSION
+REQ
+REQs
+REVERSECONCAT
+REVERSEDATA
+REVSPLITOFF
+RIJNDAEL
 RINTERNAL
+RIW
+RLOCK
+RM
+RMERR
+RMFAIL
+RMID
+RMNAMESZ
 RMW
+RMs
+ROP
 RPC
+RPCCLIENT
+RPCExample
+RPCGEN
+RPRINT
 RT
+RTTarget
+RUNLOG
 RUNRECOVERY
+RUSAGE
+RandCommand
+RangeExceeded
+RangeKeyNotEqual
+RangeNotFound
+Realloc
+Rec
 Recno
+Recnos
+RecordNumberBinding
+RecordNumberFormat
+RecoveryOperation
+Reinit
+RepElect
 RepElectResult
+RepFlush
+RepLimit
 RepProcessMessage
+RepRequest
+RepStart
+RepStat
+ReplicationHandleDeadException
+ReplicationStats
+ReplicationStatus
+ResetResult
+ReturnSetup
+Rieffel
+Rijmen
+Rijndael
+Roeber
+Rp
+RpcDb
+RpcDbEnv
+RpcDbTxn
+RpcDbc
+RtoL
+RunRecoveryException
+RuntimeException
+RuntimeExceptionWrapper
+Rusage
+SCHED
+SCO
+SCO's
+SEGDATA
+SEGID
+SEM
+SEMA
+SEP
+SEQ
 SERVERPROG
 SERVERVERS
+SETALL
+SETCURSOR
 SETFD
+SETVAL
+SGI
 SHA
+SHALLOC
+SHASH
+SHMEM
+SHMGET
+SHQUEUE
+SIGALRM
+SIGPIPE
+SIZEOF
+SKIPFIRSTKEY
+SKU
+SNPRINTF
+SPL
+SPLITOLD
+SPRINTF
 SS
+SSLeay
+SSZ
+STAILQ
+STARTUPDONE
+STAT
+STATS
+STCWX
+STD
+STDC
+STDERR
+STDINT
+STK
+STR
+STRCASECMP
+STRDUP
+STRLIST
+STROFFSET
+STRTOUL
+STRUCT
+STWCX
+SUBDB
+SWAPBYTES
+SWIG's
+SWITCHes
+SWR
+SYSCONF
+SampleDatabase
+SampleViews
+Schlossnagle
+SecondaryDeadlockTest
+Sedgewick
+Seq
+SeqGet
+SeqGetFlags
+SeqOpen
+SequenceExample
+SequenceStats
+SerialBinding
+SerialBindingTest
+SerialFormat
+SerialInput
+SerialOutput
+SerialSerialBinding
+SerialSerialKeyExtractor
+SetEndOfFile
+SetInfoData
+SetListElem
+SetListElemInt
+SetListElemWideInt
+SetListRecnoElem
+SetMultiList
+SetObjResult
+ShipmentBinding
+ShipmentByPart
+ShipmentBySupplier
+ShipmentData
+ShipmentKey
+ShipmentKeyBinding
+ShipmentValue
 Shm
+Signalling
+SimpleBuffer
+Skiplist
+Skodon
 Sleepycat
+Something's
+SortedMap
+SortedSet
+Sparc
+Splitp
+Stat
+Stats
+Std
+Stdout
+Steele
+StoredClassCatalog
+StoredClassCatalogTest
+StoredClassCatalogTestInit
+StoredCollection
+StoredCollections
+StoredContainer
+StoredEntrySet
+StoredIterator
+StoredKeySet
+StoredList
+StoredMap
+StoredMapEntry
+StoredSortedEntrySet
+StoredSortedKeySet
+StoredSortedMap
+StoredSortedValueSet
+StoredValueSet
+StringBuffer
+StringDbt
 Subdatabase
+Subdb
+Subname
+SunOS
+SupplierBinding
+SupplierByCity
+SupplierData
+SupplierKey
+SupplierKeyBinding
+SupplierValue
+SystemInfo
+TAILQ
+TCHAR
+TCL
 TDS
 TESTDIR
+TESTTESTEST
+TESTXADIR
+THR
 TID
+TLPUT
+TM
+TMASYNC
+TMENDRSCAN
+TMER
+TMERR
+TMFAIL
+TMJOIN
+TMMIGRATE
+TMMULTIPLE
+TMNOFLAGGS
+TMNOFLAGS
+TMNOMIGRATE
+TMNOWAIT
+TMONEPHASE
 TMP
 TMPDIR
+TMREGISTER
+TMRESUME
+TMSTARTRSCAN
+TMSUCCESS
+TMSUSPEND
+TMUSEASYNC
+TMs
 TODO
+TOPLEVEL
+TPC
+TPCB
 TPS
+TRU
+TRUNC
+TRUNCDATA
+TSTRING
 TXN
+TXNAPP
+TXNHEAD
 TXNID
+TXNLIST
+TXNLOGREC
+TXNMGR
+TXNREGION
+TXNS
+TXNVERSION
 TXNs
+Takuji
 Tcl
+Tcl's
 TempFolder
+TestAppendRecno
+TestAssociate
+TestCallback
+TestClassCatalog
+TestClosedDb
+TestConstruct
+TestDataBinding
+TestDbtFlags
+TestEntity
+TestEntityBinding
+TestEnv
+TestGetSetMethods
+TestKeyAssigner
+TestKeyExtractor
 TestKeyRange
+TestLockVec
 TestLogc
+TestOpenEmpty
+TestReplication
+TestRpcServer
+TestSameDbt
+TestSerial
+TestSimpleAccess
+TestStat
+TestStore
+TestTruncate
+TestUtil
+TestXAServlet
+Thang
+Thies
+Threshhold
+Throwable
+TimeUnits
+Tmp
+Topher
 TpcbExample
+TransactionRunner
+TransactionStats
+TransactionTest
+TransactionTests
+TransactionWorker
+Tru
 Tt
+TupleBinding
+TupleBindingTest
+TupleFormat
+TupleFormatTest
+TupleInput
+TupleInputBinding
+TupleMarshalledBinding
+TupleOrderingTest
+TupleOutput
+TupleSerialBinding
+TupleSerialDbFactory
+TupleSerialDbFactoryTest
+TupleSerialEntityBinding
+TupleSerialKeyExtractor
+TupleSerialMarshalledBinding
+TupleSerialMarshalledKeyExtractor
+TupleTupleBinding
+TupleTupleKeyExtractor
+TupleTupleMarshalledBinding
+TupleTupleMarshalledKeyExtractor
 Txn
+TxnCheckpoint
+TxnInfoDelete
+TxnRecover
+TxnStat
+TxnTimeout
 Txnid
 Txns
+UI
 UID
+UINT
+ULONG
+UMRW
 UNAVAIL
+UNDEF
+UNDOC
+UNICODE
+UNISTD
+UNREF
+UOC
+UPDATEROOT
+UPREFIX
+USEC
 USERMEM
+UTF
+UTFDataFormatException
+UTS
+UX
 Unencrypted
+Unicode
+UnixLib
+UnixWare
+Unixware
+UnknownError
 UnmapViewOfFile
+UnsupportedOperationException
+UtfOps
+UtfTest
+Util
+VC
+VER
 VM
+VMPAGESIZE
+VRFY
+VSNPRINTF
+VTALLY
 VX
+Var
+Vc
+VendorDB
+Vo
+Voter's
 Vv
 VvW
 VvXxZ
 Vvw
 Vx
 VxWorks
+WAITSFOR
+WAKEME
+WATCOM
+WLInitialContextFactory
+WORDLIST
+WRITECURSOR
+WRITELOCK
+WRITEOPEN
+WRNOSYNC
+WRONLY
+WT
+WW
+WWRITE
 Waitsfor
+WebLogic
+WinNT
+WriteFile
+X's
 XA
+XAER
 XAException
+XAResource
+XID
+XIDDATASIZE
+XOR'd
+XP
+XPG
+XXX
 Xid
 XxZ
 YIELDCPU
 YY
+YYMMDDhhmm
+ZED
+ZF
+Zero'd
+aa
+aaA
+aaB
+aaC
+aaD
+aaa
+aaaaaa
+aaaaab
+aaaaac
+aab
+aac
+aad
+ab
 abc
 abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq
 abcdef
 abs
+absname
+abspath
+ac
+aca
+accessor
+ack
+acplt
+activekids
+activep
+activepips
+actualData
+actualKey
+acurs
+ada
+addAll
+addfamilylocker
 addpage
 addr
 addrem
+addrp
+adh
 adj
+adjindx
+adlsVv
+admin
 afterop
 ahr
+alfred
+alg
+algsetup
+alignp
 alldb
 alloc
+alloc'ed
+alloc'ing
+alloced
+allocs
 alsVv
+alsn
 amx
+antoon
 anum
+aparts
+apologise
+app's
+appexit
 appl
 appname
+appnotes
+apprec
+apps
+aq
 archivedir
+areDuplicatesAllowed
+areDuplicatesOrdered
+areKeysRenumbered
 arg
+argp
 args
+argv
+arr
+arraycopy
+arraysz
+asites
+assertEquals
+astubble
 ata
+atoi
+atol
+att
+autoCommit
+autocommit
+autoconf
+autoconfig
+autoremove
+avg
+awk
+baaaaa
+backoff
+badend
+badgen
 badkey
+badnum
+bak
+barreto
+baseClass
+bb
+bba
+bcopy
+bcurs
+bd
+bdb
+bdbcmds
+beginInclusive
+beginKey
+beq
 berkdb
+berkdbcmds
 berkeley
 bfname
 bfree
+bh
+bharray
+bhfree
+bhp
+bhwrite
+bi
+bigint
 bigpages
+bigpair
+binding's
+bitmasks
+bk
+blbs
+blk
+blksize
+blockDecrypt
+blockEncrypt
+blocknum
+blocksize
+bmeta
+bmp
+bndx
+bne
 bnum
+bosselaers
 bostic
+bp
 bqual
+br
+broot
+bs
+bshift
 bsize
+bsizep
 bt
 btcompare
 btrec
 btree
+btreemeta
+btrees
 buf
+bufp
+bufs
+bufsize
+buildpartial
+builtin
+bumpSize
+bval
 bylsn
 bypage
+byteLen
+byteOffset
+byteorder
+bytesToChars
+bytesize
+bytesp
 byteswap
 byteswapped
 bytevalue
+cEelmNrtVZ
+caaaaa
+cachep
 cachesize
 cadjust
+callback
+callback's
+callbk
+calloc
+callocs
 callpgin
+carray
+catalogtest
+cbts
+cc
+ccclose
+ccnext
+ccset
+ccurs
 cd
+cdata
 cdb
 cdel
 ceVv
@@ -288,195 +1623,885 @@ celmNrtVZ
 celmNtV
 celmNtVZ
 cget
+cgetchk
+ch
+char's
+charLen
+charLength
+charOffset
 charkey
 charset
+checkgen
+checklocker
 chgpg
+childcursor
+childinc
+childproof
+childput
+chk
 chkpoint
 chkpt
+chkspace
 chksum
+chmod
+chongo
+ci
+cip
+cipherInit
+cipherInstance
+cipherUpdateRounds
 ckp
+ckplsn
 cksum
+cl
+classCatalog
+classID
+className
+classpath
+cleandir
+clearIndexKey
 clearerr
+clib
+clientData
 clientrun
+clist
+clnt
+closeevent
+closehandle
+closeme
+cls
+cmap
+cmd
 cmdargs
+cmds
+cmp
+cmpwi
 cnt
+com
+comm
+compareDuplicates
 compareproc
+comparitors
 compat
+concatdatakey
+concatkeydata
 conf
 config
+const
+containsAll
+containsKey
+containsValue
+conv
+convprintable
+copyFrom
+copyin
+copyleft
+copymap
+copyout
 copypage
+countElements
+countp
 cp
+cpage
+cpp
+cputchk
+cq
+cr
 crdel
 creat
+createflag
+crypto
+cs
+csp
+ct
+ctp
+ctp's
+ctps
+ctx
+ctxn
 curadj
+curfile
+curinfo
+curinval
+curlist
 curlsn
+curslen
+curslist
+cursp
+cursq
+cutlim
+cxx
+cxxproc
+cxxthis
+cxxutil
+dat
+dataBinding
+dataInput
+dataOutput
+dataToObject
+databuf
 datalen
+datap
+datapage
+datastr
 db
+dbFileName
+dbOpenFlags
 dbc
+dbc's
+dbca
+dbcb
+dbcl
+dbclear
 dbclient
 dbclose
+dbcmds
+dbcp
+dbcursor
+dbdata
+dbdel
+dbdemo
+dbdp
 dbe
+dbentry
 dbenv
+dbh
+dbinc
+dbinfo
+dbinit
+dbip
+dbj
+dbjoin
 dbkill
+dblist
+dblistlinks
+dblp
 dbm
 dbmclose
+dbmeta
+dbmfp
 dbminit
+dbmp
+dbname
+dbnamep
 dbobj
 dbopen
 dbp
+dbp's
+dbpp
+dbprep
+dbps
+dbq
+dbrdonly
 dbreg
 dbremove
 dbrename
 dbs
+dbsizes
+dbsrv
 dbt
+dbta
+dbtb
+dbtp
 dbtruncate
+dbts
+dbtxn
+dbtype
+dbuf
 dbverify
+dbx
+dcursor
 dd
+deadfile
+deadlocker
+deadmap
+dec
+decrpyting
 def
+defcmp
+defg
+defpfx
+defto
 del
+deletable
+deleteAction
 delext
 delim
+delimp
+delpg
+denom
+dereffing
+des
+deserialize
+deserialized
+deserializing
+dest
+detectp
 dev
 df
 dh
+diff
+difflen
 dir
+directio
+dirent
+dirf
 dirfno
+dirfree
+dirlist
+dirname
+dirp
+dirs
+dirtyRead
 dist
 dists
+ditem
+dl
+dlbytes
 dlen
+dlfcn
+dll
+dlopen
+dm
+dname
+dndx
+doGet
+doTimeouts
+doWork
+dobj
+docRoot
+doevents
+donext
+doreq
+doubleToLongBits
+dp
+dpagep
+dpages
+dpair
+dpgno
+dr
+dremoved
 ds
+dsearch
 dsize
+dst
+dsync
+dtab
+dtabsize
+dumptree
 dup
 dup'ed
 dupcompare
+duperr
+dupmaster
+dupmasters
+dupped
 dups
 dupset
 dupsort
+duptree
+duptype
+dwNumberOfProcessors
+dx
+eax
+ebuf
+edu
+efg
 efh
+egen
 eid
+eid's
+eidp
+ek
+ele
 electinit
 electsend
+electtally
 electvote
 electwait
+elem
+elp
+emap
+emt
+encrpyting
 encryptaes
 encryptany
+endInclusive
+endKey
 endian
+endianness
+endif
+endname
+endodata
+endofile
+endpath
+enqueuing
+ent
+entityBinding
+entrySet
+entryp
+enum
+enums
 env
+env's
+envFlags
+envcl
+envdata
+envdp
 envid
+envip
+envlock
+envp
+envpanic
+envparent
 envremove
+envrpcserver
+envs
 eof
+eor
+erlangen
+errbuf
 errcall
 errfile
+errlock
 errno
+errnum
+erroring
+errorret
 errpfx
+errunlock
+errx
+esat
+esp
+eval
+exactp
 excl
+exe
+exid
+exnum
+expandtab
+expr
+ext
 extentsize
+extentsizep
+externalizable
+extid
+extractIndexKey
+fN
+faq
 faststat
+faultmem
+fc
+fcchk
+fchk
 fclose
+fcn
 fcntl
 fcreate
 fd
+fd's
+fdatasync
+fdm
+fdp
+fdupcurs
+feedback's
+ferr
 ff
 ffactor
+ffactorp
 fget
 fh
+fhp
 fid
+fids
+fileID
+fileIDs
+filedone
+filehandle
 fileid
+fileids
+fileinfo
+fileinit
+filelist
+filenamep
+filenum
 fileopen
+fileops
+fillf
+finalcount
+findFirst
+finddatum
+findlastckp
+finfo
+firstKey
 firstkey
 fiv
+fixup
+fixups
+flagN
+flagsp
+floatToIntBits
 flushcommit
+fmax
+fmethod
+fn
+fname
+fnl
+fnp
+fns
+fnum
 foo
 fopen
+forName
+foreignStore
+form's
+format's
 formatID
+fp
+fprobe
+fptr
 fput
+fq
+freakin
+free'd
+free'ing
+freeable
+freedata
+freefamilylocker
 freelist
+freelock
+freelocker
+freep
+fremove
+freq
+friedl
+fromInclusive
+fromIndex
+fromKey
+fromMapEntry
+fromValue
+frotzed
+fs
 fset
+fst
 fstat
+fstati
 fsync
+ftruncate
 ftype
+fullhome
+fullname
 func
+funcs
 fv
+fwd
 gbytes
+gbytesp
+gc
 gc'ed
+gcc
+gdb
 gen
+genrand
+george
 getBranchQualifier
+getBytes
+getCity
+getClassFormat
+getCollection
+getCurrentKey
+getData
+getDbEnv
+getDbt
+getDbtString
+getDetail
+getEnvironment
+getErrno
+getFlags
 getFormatId
 getGlobalTransactionId
+getIndex
+getInstance
+getLock
+getMode
+getNext
+getObj
+getObject
+getOffset
+getOp
+getPartialLength
+getPartialOffset
+getPrimaryKeyFormat
+getPrimitiveBinding
+getRecordNumber
+getSize
+getString
+getTimeout
+getUserBufferLength
+getValue
+getValueFormat
+getactive
+getboth
+getbothc
+getckp
+getcwd
+getdata
+getdynamic
+getenv
+getinfo
+getjoin
+getlocker
+getlong
+getname
+getnext
+getno
+getobj
+getopt
+getpageinfo
+getpid
+getrusage
+getstack
+getsubopt
 gettime
 gettimeofday
+gettingstarted
 gettype
+getuid
+getulong
 getval
+getzip
+ghi
 gid
+gotkey
+gotta
 groupalloc
+gsf
+gsp
 gtrid
+guesspgsize
+hEvent
+handle's
+handleException
+happend
+hardcode
+hardcoding
+hasNext
+hasPrevious
+hashCode
+hashhdr
+hashinit
+hashmeta
+hashp
 hashproc
+hc
+hcp
 hcreate
 hdestroy
 hdr
+hdrbuf
+hdrchk
+hdrpages
+hdrs
+headMap
+headSet
+header's
+headp
+heldby
+helloworld
+hf
+hijkl
+himark
+histdbt
+hlock
+hmac
+hmeta
+holdl
+homep
+homeroot
+hostaddr
 hostname
+hotcopy
+hp
+hq
+href
+hs
 hsearch
+htab
+htonl
+httpd
+iX
+ia
 icursor
+idbase
 idletimeout
+idleto
+idmap
+idnum
+idp
 ids
+idspace
 idup
+idup'ed
+iface
+ifdef
+iff
+ifndef
+ihold
 iitem
+ik
+ilock
+ilocks
 inc
 incfirst
+incomp
+incr
+incursor
+indexCursor
+indexKey
+indexKeyData
+indexKeyFormat
+indexKeyOutput
+indexKeys
+indexOf
+indexViews
+indexlist
 indx
+info's
+infop
+informatik
+ini
 init
+init'ing
+inited
+initialSize
+inits
+initspin
 inlen
+inline
+inmem
+inmemdbflags
+inmemory
+ino
+inode
+inorder
 inp
+inpitem
+inputOctets
+inregion
 insdel
 int
+intBitsToFloat
 intValue
+intel
+interp
+intial
+ints
+inttypes
+inuse
+inventoryDB
+inventorydb
 io
+ioinfo
+iopsize
+iosDevFind
+ip
+ipcs
 iread
+isAutoCommit
+isByteLen
+isDirtyReadAllowed
+isDirtyReadEnabled
+isEmpty
+isIndexed
+isOrdered
+isTransactional
+isWriteAllowed
+isbad
+isbigendian
 isdeleted
+isdone
+isdst
+isdup
+isolder
+isopd
+ispget
+isroot
+isspace
+istmp
+isvalid
+isync
+itemname
+itemnameDB
 itemorder
 iter
+ith
 iwr
 iwrite
+java
+java's
 javax
+jbyte
+jc
+jenv
+jhi
+jl
+jlong
+jmsjdbc
+jndi
+journaling
+jp
+jq
+jrpcgen
+jta
 kb
 kbyte
 kbytes
+keio
+key's
+keyAssigner
+keyBinding
+keyClass
+keyExtractor
+keyFormat
+keyInput
+keyInstance
+keyLen
+keyMaterial
+keyName
+keyOutput
+keySet
+keybuf
 keyfirst
+keyflag
 keygroup
 keygroups
 keygrp
 keylast
+keynum
+keyp
 keyrange
+keystr
+kgnum
+ki
+killid
 killinterval
 killiteration
 killtest
 klNpP
 klNprRV
 klNprRs
+klinks
+kow
+kp
+kpv
 krinsky
+ks
+kuleuven
 lM
 lP
+lSN
 lang
+last's
+lastError
+lastIndexOf
+lastKey
+lastfile
 lastid
+lastpgno
+later's
+lbtree
+lbucket
+lc
 ld
+ldata
+ldbp
+ldbt
+ldbtsize
+ldcws
+ldl
+ldstub
+le
 len
+lenp
+les
 lf
+lfhp
+lfname
 lg
+lget
+lh
+lhash
+lhi
 libdb
+libfile
+libname
+libpthread
+libthread
+lineno
+listIterator
+listobj
+listp
 lk
+lkrs
+ll
+lld
 llsn
+llu
+lm
+ln
+lnP
+lnsl
+loadme
 localhost
 localtime
+lockForWrite
+lockGet
+lockVector
+lockcount
+lockdown
+locker's
+lockerid
+lockevent
+lockfhp
 lockid
+lockinfo
+lockmgr
+lockmode
+lockobj
+lockop
+lockreq
+lockstep
+locktimeout
+logbuf
 logc
 logclean
+logdir
 logfile
+logfiles
 logflush
+loggap
+logmaxset
+logmsg
+logrec
+logset
 logsonly
+longBitsToDouble
 lorder
+lorderp
+lowlsn
+lp
 lpgno
+lprint
+lput
+lrand
+lrp
+lru
 lsVv
 lsn
+lsnadd
+lsninit
+lsnoff
+lsnp
 lsynch
 lt
 lu
@@ -487,339 +2512,1186 @@ luKb
 luM
 luMB
 luMb
+lvalue
+lwarx
+lwp
 lx
 mNP
 mNs
 machid
+machtab
+maddr
+magicno
+maintinit
+maj
+majver
+makeKey
 makedup
 malloc
+malloc'd
+malloc'ed
+malloc's
+mallocing
+mallocs
+mapEntry
+mapfile
 margo
+markdone
+markneeded
+markus
+marshalIndexKey
+marshalled
+marshalling
+matumoto
+maxRetries
+maxb
 maxcommitperflush
+maxid
 maxkey
+maxkeypage
 maxlockers
 maxlocks
+maxlsn
+maxn
 maxnactive
 maxnlockers
 maxnlocks
 maxnobjects
 maxobjects
+maxopenfd
 maxops
+maxp
+maxperm
+maxpg
+maxpgno
+maxrec
+maxsites
+maxsize
 maxtimeout
+maxto
+maxtxn
 maxtxns
+maxwrite
+maxwrites
+mb
+mbp
+mbucket
 mbytes
+mbytesp
+md
 mem
+membar
+memcmp
+memcmps
+memcpy
+memmove
 memp
+memset
+metachk
 metadata
 metaflags
 metagroup
 metalsn
 metapage
 metasub
+metaswap
 methodID
+mf
+mfp
+mgrp
+midpage
+millitm
 mincommitperflush
 minkey
+minkeyp
+minkeypage
 minlocks
+minp
+minval
+minver
 minwrite
 minwrites
+mip
 mis
+misc
 mjc
 mkdir
+mkdir's
 mlock
 mmap
+mmap'd
+mmap'ing
 mmapped
 mmapsize
+mmapsizep
 mmetalsn
 mmpgno
+modeFlag
+moremiddle
+mortem
+movl
 mp
 mpf
+mpfarray
+mpfq
 mpgno
+mpip
 mpool
+mpoolfile
+mpools
+mpreg
+mps
+msem
+msemaphore
 msg
+msg's
+msgadd
+msgbuf
+msgcall
+msgdbt
+msgfile
+msgfp
+msgs
+msgtype
+msize
+mswap
+mt
+mti
+munlock
 munmap
+mut
 mutex
 mutexes
 mutexlocks
+mutexp
+muxfile
 mv
 mvptr
 mydrive
 mydrivexxx
+myfree
+mylock
+myobjc
+myval
+n'th
 nO
 nP
 nTV
 nTt
 naborts
 nactive
+nalloc
+namelistp
+nameop
+namep
+namesp
+nargc
+nargv
 nbegins
 nbytes
+ncache
+ncachep
 ncaches
+ncommit
 ncommits
 nconflicts
+ncurs
+ndary
 ndata
 ndbm
+ndeadalloc
 ndeadlocks
+ndir
 ndx
 needswap
+neg
 nelem
+nelemp
+nentries
 nevict
 newalloc
 newclient
+newdata
+newdatabase
+newfh
 newfile
 newitem
+newlist
 newmaster
 newname
+newopd
 newpage
 newpgno
 newsite
+newsites
+newsize
+next's
+nextIndex
 nextdup
+nextents
+nextinfo
 nextkey
 nextlsn
 nextnodup
 nextpgno
+nfid
+nfiles
 ng
 nitems
 nkeys
+nlist
 nlockers
 nlocks
+nlocktimeouts
 nlsn
 nmodes
 nnext
 nnextlsn
 nnowaits
+noWait
+noarchive
 nobjects
+nobuffer
 nodup
 nodupdata
+noet
 nogrant
+nohasham
+nolock
 nolocking
+nolonger
+nomem
 nommap
 noop
 nooverwrite
+nop
 nopanic
+nopenp
+norep
 nosort
 nosync
+nosystemmem
+notdurable
 notfound
 notgranted
+notused
+notzero
+novrfy
 nowait
 nowaits
+np
 npages
 npgno
+nprocs
+nptr
+nr
+nread
+nreaders
 nrec
 nrecords
+nrecs
+nreg
 nreleases
+nrepeat
 nrequests
 nrestores
 nsites
+nsize
+nsl
+nsleep
+nsleepp
 ntasks
 nthreads
+nthrottles
+ntohl
+ntxns
+ntxntimeouts
+nuls
 num
+numberOfKeysRead
 numdup
+numdups
+numext
+numlocks
+nval
+nvotes
+nwrite
+nwritep
+nwriters
+nwrites
+nwrotep
+nxt
 obj
+objc
+objectArrayToString
+objectToData
+objectToKey
+objectToValue
+objp
+objs
+objv
+octets
+offdup
+offp
 offpage
+offsetp
+oflags
+ohash
 ok
+oldValue
+oldValues
 olddata
 olditem
 oldname
+oldrec
+oldsize
+oli
+omniti
+omode
+ondisk
+onefile
+onint
+onoff
+onoffp
+onpage
+op
 opd
+openCursors
+openFlags
+openfd
+openfiles
+openhandle
+opensub
 opflags
 opmods
+ops
+optarg
+opterr
+optind
+optopt
+optreset
+orderchkonly
+org
 orig
+originfo
+origline
+origmap
+origp
 os
 osynch
+outBuffer
+outbuf
+outdatedp
+outfd
+outfile
+outfp
 outlen
+outstr
 ovfl
+ovflok
+ovflpage
 ovflpoint
 ovflsize
+ovput
 ovref
+padDecrypt
+padEncrypt
+padp
 pageimage
+pageinfo
+pagelayout
+pagelist
 pagelsn
 pageno
+pagep
+pagereq
 pagesize
+pagesizep
 pagesizes
+pagespace
+pagetype
+pagezero
+pagf
 pagfno
+panic'd
 panic'ing
 paniccall
 panicstate
+params
 parentid
+parseLong
+partsize
 passwd
+passwds
+paulo
+pct
+pdbp
+pdf
+penv
 perf
 perfdb
+perftool
+perms
 pflag
+pfx
 pg
+pgaddr
 pgcookie
+pgdbp
 pgdbt
+pgerr
 pget
+pgfmt
 pgfree
+pggap
 pgin
+pginfo
+pgip
+pgmax
 pgno
+pgnoadd
+pgnoaddr
+pgnop
+pgnos
 pgnum
 pgout
+pgread
+pgs
+pgset
 pgsize
+pgwrite
+ph
+php
+physdel
+physwrite
 pid
+pids
+pinref
+pinsert
+pitem
+pk
 pkey
+pkey's
+pkeys
+pkg
+placeholder
 plist
+pmap
 pn
+poff
+portmapper
+pos
 postdestroy
 postlog
 postlogmeta
 postopen
 postsync
+pp
+ppc
+pr
 prR
+prdb
+prdbt
+pre
+pread
 prec
 predestroy
 preopen
+preparse
+preplist
+preprocess
+preprocessed
+preread
+prereq
+presorted
 prev
+prev's
+prevfile
+previousIndex
 prevlsn
 prevnodup
+prflags
+prfooter
 prheader
 pri
+primaryKey
+primaryKeyData
+primaryKeyFormat
+primaryKeyInput
+primaryKeyThang
+primget
+printf
+printlock
 printlog
+priorityp
+prnpage
 proc
 procs
+proff
+progname
+progpath
+protos
+prpage
+prqueue
+prtree
+pseudorandom
+psize
+psplit
+pstat
+ptail
 pthread
 pthreads
+ptr
+ptrdiff
 ptype
+putAll
+putall
+putchar
+putitem
+putobj
+putop
+putpageinfo
+putr
 pv
+pwrite
 qV
 qam
+qammeta
+qmeta
+qmpf
+qnx
+qp
 qs
 qtest
+quV
+queuestart
+quicksort
+quotedStr
 rRV
 rRs
 rV
 rand
+randtbl
+rbtree
+rcon
 rcuradj
+rcursor
+rcvd
+rdata
+rdbc
+rdbenv
 rdonly
+rdump
+reacquired
+reacquires
+readBoolean
+readByte
+readBytes
+readChar
+readChars
+readDouble
+readFloat
+readInt
+readLong
+readShort
+readString
+readUnsignedByte
+readUnsignedInt
+readUnsignedShort
 readd
+readdir
+readn
 readonly
+readratio
 realloc
+realloc'd
+realloc'ed
+reallocing
 rec
+recfill
+reclen
 reclength
 recno
+recnop
+recnos
 recnum
 recnums
+recops
+record's
+recordNumber
+recordlen
 recs
+rectype
+recvd
+refcnt
 refcount
+refcounting
+reffed
+regids
+reginfo
 regionmax
+reglocks
+regmutex
+regmutexes
 regop
 regsize
+relen
 relink
+rem
+remevent
+remfile
+remfirst
+remlock
+removeAll
+remrem
+renum
+renv
+rep's
+repdb
 repl
+replication's
+replpair
+replyp
+reppg
+repquote
+repsite
+reput
+reputpair
+req
+resizep
+resync
+retPrimaryKey
+retValue
+retbuf
+retcopy
+retcount
+rethrown
+reties
+retp
+retsp
+retval
+reverseconcat
+reversedata
 revsplitoff
 rf
+rfd
+rfp
+rget
+rheader
+ri
+rijmen
+rijndael
+rijndaelDecrypt
+rijndaelDecryptRound
+rijndaelEncrypt
+rijndaelEncryptRound
+rijndaelKeySetupDec
+rijndaelKeySetupEnc
+ritem
+riw
+rk
 rkey
+rlen
 rlsn
+rlsnp
 rm
+rmdir
+rmdir's
 rmid
 rmw
 ro
+roff
+rollforward
 rootent
 rootlsn
+rp
+rp's
+rpath
 rpc
+rpcgen
 rpcid
+rpcserver
+rprint
+rptr
+rq
+rr
+rrecno
 rs
+rsearch
+rskey
 rsplit
+rtree
+rtxn
+rundb
 runlog
+rusage
 rw
 rwrw
 rwrwrw
 sS
 sV
 sVv
+salloc
+salvager's
+savetime
+sched
 scount
+sdb
+sdbp
+seckey
 secon
+secondary's
+secondaryKeyCreate
 secs
+secsp
+sectorsize
+segdata
+segid
+sema
+semid
+seminfo
+semun
+sendpages
 sendproc
+sep
 seq
+seqnum
+seqp
+serialobj
+servlet
+setAppDispatch
+setAppendRecno
+setBtreeCompare
+setBtreePrefix
+setCacheSize
+setData
+setDuplicatelicateCompare
+setEncrypted
+setErrorHandler
+setErrorPrefix
+setFeedback
+setFeedbackHandler
+setFlags
+setHash
+setLock
+setMode
+setObj
+setObject
+setOffset
+setOp
+setPanicHandler
+setPartialLength
+setPartialOffset
+setRecno
+setRecordNumber
+setReplicationLimit
+setReplicationTransport
+setSize
+setTimeout
+setUserBufferLength
+setValue
+setflags
+setid
+setlsn
+settimeout
 setto
 setval
+sexing
+sgenrand
 sh
 shalloc
+shalloc'ed
+shalloced
+sharedb
+shareenv
+shash
 shm
 shmat
 shmctl
 shmdt
 shmem
 shmget
+shmname
+shortread
+shownull
+shqueue
 shr
+shreg
+siginit
+signo
+sigresend
+singleKey
+sizeAdded
+sizeNeeded
+sizefix
+sizeof
+sj
+skiplist
+skiplists
+skodonj
+sl
+sle
 sleepycat
+slh
+slumber'd
+smap
+smax
+snapshotting
+sniglet
+snprintf
+sortdups
+sourcep
+sp
+sparc
+spawnl
+spinlock
+spinlocks
+spinsp
 splitdata
 splitmeta
+splitp
+sprintf
 srand
+srandom
+src
+sread
+ss
+sscanf
+sse
+sshift
+ssize
+sslll
+sss
 stat
+stati
+stats
+stbar
+std
+stddev
+stderr
+stdfd
+stdin
+stdint
+stdlib
+stdmode
+stdout
+stkgrow
+stkrel
+stl
+storedCollection
+storedIterator
+storedList
+storedMap
+storedSet
+storedSortedMap
+storedSortedSet
+stqe
+stqh
 str
+strcasecmp
 strcmp
 strdup
+strdup'ed
 strerror
+stringToBytes
+stringp
 strlen
+strncasecmp
+strncmp
+strsep
+strtol
+strtoul
+struct
+structs
+structure's
+sts
+stwcx
+subList
+subMap
+subSet
+subcases
+subclassed
 subdatabase
+subdatabase's
 subdb
+subdbname
+subdbpg
+subdbs
+subdistribution
+subdistributions
+submap
+subname
+subpackages
+subtransaction
+subtransactions
+sullivan
 sv
 svc
+sw
+swigCPtr
+swpb
+sync'd
+sync'ed
+synced
+syncs
+sysattach
+sysconf
+sysdetach
+sz
+t's
 tV
 tVZ
+tableent
+tablesize
+tailMap
+tailSet
+tailq
 tas
+taskLock
+tc
 tcl
 tcp
+td
+tdata
+tearDown
+terra
+testName
+testcopy
+testdata
+testdestdir
+testdigits
+testdocopy
+tffsp
+tfsp
+thang
+theVendor
+thies
 thr
+thread's
 threadID
+threadedness
 tid
+tids
 tiebreaker
+tiebreaking
+timeoutp
 timestamp
+timeval
+timout
+timouts
 tlen
 tm
+tmap
+tmax
 tmp
 tmpdir
+tmpmap
+tmpname
 tmutex
 tnum
+toArray
+toBuf
+toHexString
+toInclusive
+toIndex
+toKey
+toList
+toMapEntry
+toString
+toValue
+toched
+todo
+toobig
 tp
 tpcb
+tput
+tqe
+tqh
+tr
+transport's
 treeorder
+tregion
+trinomials
+trunc
+truncdata
+ts
+tsl
+tstart
 ttpcbddlk
 ttpcbi
 ttpcbr
 ttype
+tv
 tx
 txn
+txnal
+txnapp
 txnarray
 txnid
+txnidcl
+txnids
+txnip
+txnlist
+txnp
 txns
+txntimeout
 txt
+ua
 ubell
 ud
+udbt
+ufid
+ufree
 uid
+uintmax
+uintptr
+ul
 ulen
+ulens
+ulinks
+umalloc
 uncorrect
+undef
 undeleting
+undo'ing
+undodup
+undosplit
+uni
+unicode
+unindexed
+uniq
+unistd
+unix
 unmap
+unmapfile
+unmark
+unmarshalData
+unmarshalled
 unpinned
+unpinning
+unref
+unregistry
 upd
+updateDatabaseEntry
+updateDbt
+updateckp
+upg
 upi
+urealloc
+useCurrentKey
+usePrimaryKey
+useValue
 usec
 usecs
+usecsp
+usermem
 usr
+usrAppInit
 util
 vVxXZ
+vVxXyZ
 vZ
+va
 val
+value's
+valueBinding
+valueData
+valueEntityBinding
+valueFormat
+valueInput
+valueInputOutput
+valueOf
+valueOutput
 var
+variadic
+vars
+vdp
+vdp's
 vec
+vendorDB
+vendordb
 ver
+verbage
 vflag
+vica
+view's
 vrfy
+vrfyutil
+vsnprintf
+vsprintf
+vtruncate
 vw
 vx
 vxmutex
 vxtmp
+vxtpcb
+vxworks
+wDay
+wHour
+wMinute
+wMonth
+wSecond
+wYear
+waitl
+waitlist
 waitsfor
 walkdupint
 walkpages
+walkqueue
 wb
 wc
 wcount
+weblogic
+weblogic's
+webquill
+windsh
+winnt
+wmask
+wnt
 wordlist
+workcurs
+writeAllowed
+writeBoolean
+writeByte
+writeBytes
+writeChar
+writeChars
+writeCursor
+writeDouble
+writeFloat
+writeInt
+writeLong
+writeShort
+writeString
+writeUnsignedByte
+writeUnsignedInt
+writeUnsignedShort
 writeable
+writeback
+writelock
+writelocks
+wrlock
 wrnosync
+wsize
 wt
+wthread
 xa
+xact
+xalinks
+xchg
+xchgb
+xdr
 xid
+xids
+xml
+xor
+xorl
 xxx
+xyz
 yieldcpu
+zend
+zero'd
+zeroeth
+zerofill
+zipcode
+zl
diff --git a/storage/bdb/test/scr011/chk.tags b/storage/bdb/test/scr011/chk.tags
index 14a3c4e011dd0a2972e906a8452a6971cdd0d272..f1d680ac7d77fc0d04bffd306a66cbadaf1c9964 100644
--- a/storage/bdb/test/scr011/chk.tags
+++ b/storage/bdb/test/scr011/chk.tags
@@ -1,6 +1,6 @@
 #!/bin/sh -
 #
-# $Id: chk.tags,v 1.10 2001/10/12 17:55:36 bostic Exp $
+# $Id: chk.tags,v 1.14 2004/10/07 20:30:32 bostic Exp $
 #
 # Check to make sure we don't need any more symbolic links to tags files.
 
@@ -20,14 +20,19 @@ t2=__2
 	-e '/^CVS$/d' \
 	-e '/^build_vxworks$/d' \
 	-e '/^build_win32$/d' \
+	-e '/^build_win64$/d' \
 	-e '/^docs$/d' \
 	-e '/^docs_book$/d' \
 	-e '/^docs_src$/d' \
+	-e '/^examples_java$/d' \
 	-e '/^java$/d' \
+	-e '/^mod_db4$/d' \
 	-e '/^perl$/d' \
+	-e '/^php_db4$/d' \
 	-e '/^test$/d' \
 	-e '/^test_cxx$/d' \
 	-e '/^test_purify$/d' \
+	-e '/^test_server$/d' \
 	-e '/^test_thread$/d' \
 	-e '/^test_vxworks$/d') > $t1
 
diff --git a/storage/bdb/test/scr012/chk.vx_code b/storage/bdb/test/scr012/chk.vx_code
index 8d7ca608f933ce0d21f6fb7ad969e098a52e46da..8b7916053aeb91cb6dc1e1afca260fc68634fecd 100644
--- a/storage/bdb/test/scr012/chk.vx_code
+++ b/storage/bdb/test/scr012/chk.vx_code
@@ -1,6 +1,6 @@
 #!/bin/sh -
 #
-# $Id: chk.vx_code,v 1.6 2002/03/27 20:20:25 bostic Exp $
+# $Id: chk.vx_code,v 1.7 2004/09/16 17:21:11 bostic Exp $
 #
 # Check to make sure the auto-generated utility code in the VxWorks build
 # directory compiles.
@@ -18,6 +18,9 @@ d=../..
 
 rm -f t.c t1.c t2.c
 
+F="$d/clib/getopt.c $d/common/util_arg.c $d/common/util_cache.c
+	$d/common/util_log.c $d/common/util_sig.c $d/*/*_autop.c"
+
 header()
 {
 	echo "int"
@@ -34,12 +37,7 @@ for i in db_archive db_checkpoint db_deadlock db_dump db_load \
     db_printlog db_recover db_stat db_upgrade db_verify dbdemo; do
 	echo "	compiling build_vxworks/$i"
 	(cat $d/build_vxworks/$i/$i.c; header $i) > t.c
-	if cc -Wall -I.. -I$d t.c \
-	    $d/clib/getopt.c \
-	    $d/common/util_arg.c \
-	    $d/common/util_cache.c \
-	    $d/common/util_log.c \
-	    $d/common/util_sig.c ../libdb.a -o t; then
+	if cc -Wall -I.. -I$d t.c $F ../libdb.a -o t; then
 		:
 	else
 		echo "FAIL: unable to compile $i"
@@ -53,12 +51,7 @@ done
 (cat t2.c t1.c; echo "return (0); }") > t.c
 
 echo "	compiling build_vxworks utility composite"
-if cc -Dlint -Wall -I.. -I$d t.c \
-    $d/clib/getopt.c \
-    $d/common/util_arg.c \
-    $d/common/util_cache.c \
-    $d/common/util_log.c \
-    $d/common/util_sig.c ../libdb.a -o t; then
+if cc -Dlint -Wall -I.. -I$d t.c $F ../libdb.a -o t; then
 	:
 else
 	echo "FAIL: unable to compile utility composite"
diff --git a/storage/bdb/test/scr013/chk.stats b/storage/bdb/test/scr013/chk.stats
index 3a4046996680d56a4e18902883f5e9acdb714476..7ee71392e1cc668c4d5d5f60742472c345256a84 100644
--- a/storage/bdb/test/scr013/chk.stats
+++ b/storage/bdb/test/scr013/chk.stats
@@ -1,12 +1,13 @@
 #!/bin/sh -
 #
-# $Id: chk.stats,v 1.6 2002/08/19 18:35:18 bostic Exp $
+# $Id: chk.stats,v 1.9 2004/11/08 14:49:42 bostic Exp $
 #
 # Check to make sure all of the stat structure members are included in
 # all of the possible formats.
 
 # Top-level directory.
 d=../..
+docs=../../../db_docs
 
 # Path names are from a top-level directory.
 [ -f $d/README ] || {
@@ -47,7 +48,7 @@ inc()
 			continue
 		fi
 		for j in $2; do
-			if egrep -w $i $d/$j > /dev/null; then
+			if egrep -w $i $j > /dev/null; then
 				:;
 			else
 				echo "	$1: $i not found in $j."
@@ -57,20 +58,23 @@ inc()
 	done
 }
 
-inc	"__db_bt_stat" \
-	"tcl/tcl_db.c db_stat/db_stat.c docs_src/db/db_stat.so"
-inc	"__db_h_stat" \
-	"tcl/tcl_db.c db_stat/db_stat.c docs_src/db/db_stat.so"
-inc	"__db_qam_stat" \
-	"tcl/tcl_db.c db_stat/db_stat.c docs_src/db/db_stat.so"
+inc	"__db_bt_stat" "$d/tcl/tcl_db.c $d/btree/bt_stat.c $docs/db/db_stat.so"
+inc	"__db_h_stat" "$d/tcl/tcl_db.c $d/hash/hash_stat.c $docs/db/db_stat.so"
 inc	__db_lock_stat \
-	"tcl/tcl_lock.c db_stat/db_stat.c docs_src/lock/lock_stat.so"
-inc	__db_log_stat \
-	"tcl/tcl_log.c db_stat/db_stat.c docs_src/log/log_stat.so"
+	"$d/tcl/tcl_lock.c $d/lock/lock_stat.c $docs/lock/lock_stat.so"
+inc	__db_log_stat "$d/tcl/tcl_log.c $d/log/log_stat.c $docs/log/log_stat.so"
+inc	__db_mpool_fstat \
+	"$d/tcl/tcl_mp.c $d/mp/mp_stat.c $docs/memp/memp_stat.so"
 inc	__db_mpool_stat \
-	"tcl/tcl_mp.c db_stat/db_stat.c docs_src/memp/memp_stat.so"
+	"$d/tcl/tcl_mp.c $d/mp/mp_stat.c $docs/memp/memp_stat.so"
+inc	"__db_qam_stat" \
+	"$d/tcl/tcl_db.c $d/qam/qam_stat.c $docs/db/db_stat.so"
+inc	__db_rep_stat \
+	"$d/tcl/tcl_rep.c $d/rep/rep_stat.c $docs/rep/rep_stat.so"
+inc	__db_seq_stat \
+	"$d/tcl/tcl_seq.c $d/sequence/seq_stat.c $docs/seq/seq_stat.so"
 inc	__db_txn_stat \
-	"tcl/tcl_txn.c db_stat/db_stat.c docs_src/txn/txn_stat.so"
+	"$d/tcl/tcl_txn.c $d/txn/txn_stat.c $docs/txn/txn_stat.so"
 
 # Check to make sure the elements from a man page appears in db.in.
 man()
@@ -89,26 +93,33 @@ man()
 	done
 }
 
-sed -e '/m4_stat(/!d' \
-    -e 's/.*m4_stat(\([^)]*\)).*/\1/' < $d/docs_src/db/db_stat.so > $t
+sed -e '/m4_field(/!d' \
+    -e 's/.*m4_field[^,]*,[ ]*\([^,]*\).*/\1/' < $docs/db/db_stat.so > $t
 man "checking db_stat.so against db.h"
 
-sed -e '/m4_stat(/!d' \
-    -e 's/.*m4_stat(\([^)]*\)).*/\1/' \
-    -e 's/.* //' < $d/docs_src/lock/lock_stat.so > $t
+sed -e '/m4_field(/!d' \
+    -e 's/.*m4_field[^,]*,[ ]*\([^,]*\).*/\1/' < $docs/lock/lock_stat.so > $t
 man "checking lock_stat.so against db.h"
 
-sed -e '/m4_stat[12](/!d' \
-    -e 's/.*m4_stat[12](\([^)]*\)).*/\1/' < $d/docs_src/log/log_stat.so > $t
+sed -e '/m4_field(/!d' \
+    -e 's/.*m4_field[^,]*,[ ]*\([^,]*\).*/\1/' < $docs/log/log_stat.so > $t
 man "checking log_stat.so against db.h"
 
-sed -e '/m4_stat[123](/!d' \
-    -e 's/.*m4_stat[123](\([^)]*\)).*/\1/' < $d/docs_src/memp/memp_stat.so > $t
+sed -e '/m4_field(/!d' \
+    -e 's/.*m4_field[^,]*,[ ]*\([^,]*\).*/\1/' < $docs/memp/memp_stat.so > $t
 man "checking memp_stat.so against db.h"
 
-sed -e '/m4_stat(/!d' \
-    -e 's/.*m4_stat(.*, \([^)]*\)).*/\1/' \
-    -e 's/__[LR]B__//g' < $d/docs_src/txn/txn_stat.so > $t
+sed -e '/m4_field(/!d' \
+    -e 's/.*m4_field[^,]*,[ ]*\([^,]*\).*/\1/' < $docs/rep/rep_stat.so > $t
+man "checking rep_stat.so against db.h"
+
+sed -e '/m4_field(/!d' \
+    -e 's/.*m4_field[^,]*,[ ]*\([^,]*\).*/\1/' < $docs/seq/seq_stat.so > $t
+man "checking seq_stat.so against db.h"
+
+sed -e '/m4_field(/!d' \
+    -e 's/.*m4_field[^,]*,[ ]*\([^,]*\).*/\1/' \
+    -e 's/__LB__.*//' < $docs/txn/txn_stat.so > $t
 man "checking txn_stat.so against db.h"
 
 exit $exitv
diff --git a/storage/bdb/test/scr015/TestConstruct01.cpp b/storage/bdb/test/scr015/TestConstruct01.cpp
index 7ae328d458c1307081d188cf8ad459fe2fdfcfef..0b0495ce9ceaed82f3e06e9ecff6612e324b7f56 100644
--- a/storage/bdb/test/scr015/TestConstruct01.cpp
+++ b/storage/bdb/test/scr015/TestConstruct01.cpp
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2000-2002
+ * Copyright (c) 2000-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: TestConstruct01.cpp,v 1.5 2002/01/23 14:26:40 bostic Exp $
+ * $Id: TestConstruct01.cpp,v 1.8 2004/01/28 03:36:33 bostic Exp $
  */
 
 /*
@@ -252,13 +252,6 @@ void t6(int except_flag)
 	}
 	delete penv;
 
-	// Make sure we get a message from C++ layer reminding us to close.
-	cerr << "expected error: ";
-	{
-		DbEnv foo(DB_CXX_NO_EXCEPTIONS);
-		foo.open(CONSTRUCT01_DBDIR, DB_CREATE, 0);
-	}
-	cerr << "should have received error.\n";
 	cout << "  finished.\n";
 }
 
diff --git a/storage/bdb/test/scr015/TestConstruct01.testerr b/storage/bdb/test/scr015/TestConstruct01.testerr
index 1ba627d103b9db1652b45dfb5fc4521f672daf99..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
--- a/storage/bdb/test/scr015/TestConstruct01.testerr
+++ b/storage/bdb/test/scr015/TestConstruct01.testerr
@@ -1,4 +0,0 @@
-expected error: DbEnv::_destroy_check: open DbEnv object destroyed
-should have received error.
-expected error: DbEnv::_destroy_check: open DbEnv object destroyed
-should have received error.
diff --git a/storage/bdb/test/scr015/TestGetSetMethods.cpp b/storage/bdb/test/scr015/TestGetSetMethods.cpp
index 81ef914eac364509cee3fc46e40eaaf4a791a602..1d896766db3f27cbdc124953f8c1fad2fd034490 100644
--- a/storage/bdb/test/scr015/TestGetSetMethods.cpp
+++ b/storage/bdb/test/scr015/TestGetSetMethods.cpp
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2000-2002
+ * Copyright (c) 2000-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: TestGetSetMethods.cpp,v 1.4 2002/01/11 15:53:59 bostic Exp $
+ * $Id: TestGetSetMethods.cpp,v 1.6 2004/01/28 03:36:33 bostic Exp $
  */
 
 /*
diff --git a/storage/bdb/test/scr015/TestKeyRange.cpp b/storage/bdb/test/scr015/TestKeyRange.cpp
index 980d2f518e0e2d32f335a566f957c693e1841229..d875cb20b814ec34620dd6863dc9c62d830e08b0 100644
--- a/storage/bdb/test/scr015/TestKeyRange.cpp
+++ b/storage/bdb/test/scr015/TestKeyRange.cpp
@@ -1,15 +1,16 @@
-/*NOTE: AccessExample changed to test Db.key_range.
- * We made a global change of /AccessExample/TestKeyRange/,
- * the only other changes are marked with comments that
- * are notated as 'ADDED'.
- */
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: TestKeyRange.cpp,v 1.4 2002/01/23 14:26:41 bostic Exp $
+ * $Id: TestKeyRange.cpp,v 1.6 2004/01/28 03:36:33 bostic Exp $
+ */
+
+/*
+ * NOTE: AccessExample changed to test Db.key_range.  We made a global
+ * change of /AccessExample/TestKeyRange/, the only other changes are
+ * marked with comments that are notated as 'ADDED'.
  */
 
 #ifndef NO_SYSTEM_INCLUDES
diff --git a/storage/bdb/test/scr015/TestLogc.cpp b/storage/bdb/test/scr015/TestLogc.cpp
index 94fcfa0b3ec910de81b2473b7b72414a444b6a13..636db4530c089510f6cc15f3da9340f68835d659 100644
--- a/storage/bdb/test/scr015/TestLogc.cpp
+++ b/storage/bdb/test/scr015/TestLogc.cpp
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2000-2002
+ * Copyright (c) 2000-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: TestLogc.cpp,v 1.6 2002/01/23 14:26:41 bostic Exp $
+ * $Id: TestLogc.cpp,v 1.8 2004/01/28 03:36:33 bostic Exp $
  */
 
 /*
diff --git a/storage/bdb/test/scr015/TestSimpleAccess.cpp b/storage/bdb/test/scr015/TestSimpleAccess.cpp
index 2450b9b3030531483ebd4a38c568ecc5ce7af3b0..8415cda78d9e8a76e9f532f758f0438b7d4e57b4 100644
--- a/storage/bdb/test/scr015/TestSimpleAccess.cpp
+++ b/storage/bdb/test/scr015/TestSimpleAccess.cpp
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2000-2002
+ * Copyright (c) 2000-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: TestSimpleAccess.cpp,v 1.5 2002/01/23 14:26:41 bostic Exp $
+ * $Id: TestSimpleAccess.cpp,v 1.7 2004/01/28 03:36:33 bostic Exp $
  */
 
 /*
diff --git a/storage/bdb/test/scr015/TestTruncate.cpp b/storage/bdb/test/scr015/TestTruncate.cpp
index d5c0dc6de290f73b8b59a5b45b21997321b748f2..54ecf81c8efbdcfe2d6885a3e6fe6a9b67574f9b 100644
--- a/storage/bdb/test/scr015/TestTruncate.cpp
+++ b/storage/bdb/test/scr015/TestTruncate.cpp
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2000-2002
+ * Copyright (c) 2000-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: TestTruncate.cpp,v 1.5 2002/01/23 14:26:41 bostic Exp $
+ * $Id: TestTruncate.cpp,v 1.7 2004/01/28 03:36:34 bostic Exp $
  */
 
 /*
diff --git a/storage/bdb/test/scr015/chk.cxxtests b/storage/bdb/test/scr015/chk.cxxtests
index 5c21e27208c7df910248ac688be23a46379aaaf3..3d1e3947c4c50a3d99aa9090028f4f5334b0767c 100644
--- a/storage/bdb/test/scr015/chk.cxxtests
+++ b/storage/bdb/test/scr015/chk.cxxtests
@@ -1,15 +1,17 @@
 #!/bin/sh -
 #
-# $Id: chk.cxxtests,v 1.5 2002/07/05 22:17:59 dda Exp $
+# $Id: chk.cxxtests,v 1.8 2004/09/28 19:58:42 mjc Exp $
 #
 # Check to make sure that regression tests for C++ run.
 
 TEST_CXX_SRCDIR=../test/scr015  # must be a relative directory
 
 # All paths must be relative to a subdirectory of the build directory
-LIBS="-L.. -ldb -ldb_cxx"
+LIBS="-L.. -ldb_cxx"
 CXXFLAGS="-I.. -I../../dbinc"
 
+[ `uname` = "Linux" ] && LIBS="$LIBS -lpthread"
+
 # Test must be run from a local build directory, not from a test
 # directory.
 cd ..
@@ -17,7 +19,7 @@ cd ..
 	echo 'FAIL: chk.cxxtests must be run from a local build directory.'
 	exit 1
 }
-[ -d ../docs_src ] || {
+[ -d ../env ] || {
 	echo 'FAIL: chk.cxxtests must be run from a local build directory.'
 	exit 1
 }
diff --git a/storage/bdb/test/scr016/CallbackTest.java b/storage/bdb/test/scr016/CallbackTest.java
index eede964a027599ff7acf722094864bdd25a43383..14abcf44f18c4eda452173d991886306ce7e8c15 100644
--- a/storage/bdb/test/scr016/CallbackTest.java
+++ b/storage/bdb/test/scr016/CallbackTest.java
@@ -7,7 +7,7 @@ public class CallbackTest
     {
         try {
             Db db = new Db(null, 0);
-            db.set_bt_compare(new BtreeCompare());
+            db.setBtreeCompare(new BtreeCompare());
             db.open(null, "test.db", "", Db.DB_BTREE, Db.DB_CREATE, 0666);
             StringDbt[] keys = new StringDbt[10];
             StringDbt[] datas = new StringDbt[10];
@@ -37,11 +37,11 @@ class BtreeCompare
     /* A weird comparator, for example.
      * In fact, it may not be legal, since it's not monotonically increasing.
      */
-    public int bt_compare(Db db, Dbt dbt1, Dbt dbt2)
+    public int compare(Db db, Dbt dbt1, Dbt dbt2)
     {
         System.out.println("compare function called");
-        byte b1[] = dbt1.get_data();
-        byte b2[] = dbt2.get_data();
+        byte b1[] = dbt1.getData();
+        byte b2[] = dbt2.getData();
         System.out.println("  " + (new String(b1)) + ", " + (new String(b2)));
         int len1 = b1.length;
         int len2 = b2.length;
@@ -61,23 +61,23 @@ class StringDbt extends Dbt
 {
     StringDbt()
     {
-        set_flags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
+        setFlags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
     }
 
     StringDbt(String value)
     {
         setString(value);
-        set_flags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
+        setFlags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
     }
 
     void setString(String value)
     {
-        set_data(value.getBytes());
-        set_size(value.length());
+        setData(value.getBytes());
+        setSize(value.length());
     }
 
     String getString()
     {
-        return new String(get_data(), 0, get_size());
+        return new String(getData(), 0, getSize());
     }
 }
diff --git a/storage/bdb/test/scr016/CallbackTest.testout b/storage/bdb/test/scr016/CallbackTest.testout
index 68797d4a2de3cf8c76b53c9eb3d488ad7800d1d7..447888285abbd4eb597b1457a6c3ad8bf92b2aa4 100644
--- a/storage/bdb/test/scr016/CallbackTest.testout
+++ b/storage/bdb/test/scr016/CallbackTest.testout
@@ -6,13 +6,11 @@ put 6
 compare function called
   key6, key3
 put 9
+compare function called
+  key9, key3
 compare function called
   key9, key6
 put 2
-compare function called
-  key2, key9
-compare function called
-  key2, key0
 compare function called
   key2, key6
 compare function called
@@ -34,10 +32,6 @@ compare function called
 compare function called
   key8, key6
 put 1
-compare function called
-  key1, key9
-compare function called
-  key1, key0
 compare function called
   key1, key5
 compare function called
diff --git a/storage/bdb/test/scr016/TestAppendRecno.java b/storage/bdb/test/scr016/TestAppendRecno.java
index f4ea70ca08401b01d4d49b75dd16142f2cf65014..4237b99db7d846c1d68e249794745b0206dbd13f 100644
--- a/storage/bdb/test/scr016/TestAppendRecno.java
+++ b/storage/bdb/test/scr016/TestAppendRecno.java
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: TestAppendRecno.java,v 1.4 2002/08/16 19:35:53 dda Exp $
+ * $Id: TestAppendRecno.java,v 1.6 2004/01/28 03:36:34 bostic Exp $
  */
 
 package com.sleepycat.test;
diff --git a/storage/bdb/test/scr016/TestAssociate.java b/storage/bdb/test/scr016/TestAssociate.java
index 4105b9cb0a1ae21b5f61438d6208ceeabb3b2f52..80451d1e66bf9ddd33f44b568354176d16a0f0d0 100644
--- a/storage/bdb/test/scr016/TestAssociate.java
+++ b/storage/bdb/test/scr016/TestAssociate.java
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: TestAssociate.java,v 1.4 2002/08/16 19:35:54 dda Exp $
+ * $Id: TestAssociate.java,v 1.8 2004/01/28 03:36:34 bostic Exp $
  */
 
 package com.sleepycat.test;
@@ -247,7 +247,7 @@ public class TestAssociate
      */
     public static class Capitalize implements DbSecondaryKeyCreate
     {
-	public int secondary_key_create(Db secondary, Dbt key, Dbt value,
+	public int secondaryKeyCreate(Db secondary, Dbt key, Dbt value,
 					Dbt result)
             throws DbException
         {
@@ -258,7 +258,7 @@ public class TestAssociate
             else if (saveddb2.equals(secondary)) {
                 which = "secondary";
             }
-            System.out.println("secondary_key_create, Db: " + shownull(secondary) + "(" + which + "), key: " + show_dbt(key) + ", data: " + show_dbt(value));
+            System.out.println("secondaryKeyCreate, Db: " + shownull(secondary) + "(" + which + "), key: " + show_dbt(key) + ", data: " + show_dbt(value));
             int len = key.get_size();
             byte[] arr = key.get_data();
             boolean capped = true;
@@ -289,7 +289,7 @@ public class TestAssociate
         }
     }
 
-    public int dup_compare(Db db, Dbt dbt1, Dbt dbt2)
+    public int compareDuplicates(Db db, Dbt dbt1, Dbt dbt2)
     {
         System.out.println("compare");
         int sz1 = dbt1.get_size();
diff --git a/storage/bdb/test/scr016/TestClosedDb.java b/storage/bdb/test/scr016/TestClosedDb.java
index 3bd6e5380f8560b66ab5211a295ef6433133dd9b..50ccdcc88005647ce42756fe5c98f5ab52910eee 100644
--- a/storage/bdb/test/scr016/TestClosedDb.java
+++ b/storage/bdb/test/scr016/TestClosedDb.java
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: TestClosedDb.java,v 1.4 2002/01/23 14:29:51 bostic Exp $
+ * $Id: TestClosedDb.java,v 1.8 2004/01/28 03:36:34 bostic Exp $
  */
 
 /*
@@ -34,7 +34,7 @@ public class TestClosedDb
             Dbt goodkeydbt = new Dbt("key".getBytes());
             Dbt badkeydbt = new Dbt("badkey".getBytes());
             Dbt resultdbt = new Dbt();
-            resultdbt.set_flags(Db.DB_DBT_MALLOC);
+            resultdbt.setFlags(Db.DB_DBT_MALLOC);
 
             int ret;
 
@@ -45,8 +45,8 @@ public class TestClosedDb
                 db.get(null, goodkeydbt, resultdbt, 0);
                 System.out.println("Error - did not expect to get this far.");
             }
-            catch (DbException dbe) {
-                System.out.println("Got expected Db Exception: " + dbe);
+            catch (IllegalArgumentException dbe) {
+                System.out.println("Got expected exception: " + dbe);
             }
             System.out.println("finished test");
         }
diff --git a/storage/bdb/test/scr016/TestClosedDb.testout b/storage/bdb/test/scr016/TestClosedDb.testout
index ce13883f63a0352efcc7460fe18eb1e93142d328..ffa537136352c3342bb3ad6f9481182e846a70e2 100644
--- a/storage/bdb/test/scr016/TestClosedDb.testout
+++ b/storage/bdb/test/scr016/TestClosedDb.testout
@@ -1,2 +1,2 @@
-Got expected Db Exception: com.sleepycat.db.DbException: null object: Invalid argument
+Got expected exception: java.lang.IllegalArgumentException: call on closed handle
 finished test
diff --git a/storage/bdb/test/scr016/TestConstruct01.java b/storage/bdb/test/scr016/TestConstruct01.java
index b60073ebc0d691fbbd7cc4d3d7dc2b48a1ffda1c..6309409c7b49e300456427c2f9284b4a136a0799 100644
--- a/storage/bdb/test/scr016/TestConstruct01.java
+++ b/storage/bdb/test/scr016/TestConstruct01.java
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2000-2002
+ * Copyright (c) 2000-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: TestConstruct01.java,v 1.6 2002/01/23 14:29:51 bostic Exp $
+ * $Id: TestConstruct01.java,v 1.10 2004/01/28 03:36:34 bostic Exp $
  */
 
 /*
@@ -123,7 +123,7 @@ public class TestConstruct01
 	Dbt key = new Dbt(outbuf, 0, i);
 	Dbt data = new Dbt(outbuf, 0, i);
 
-	//DEBUGOUT("Put: " + (char)outbuf[0] + ": " + new String(outbuf));
+	//DEBUGOUT("Put: " + (char)outbuf[0] + ": " + new String(outbuf, 0, i));
 	db.put(null, key, data, Db.DB_NOOVERWRITE);
 
 	// Acquire a cursor for the table.
@@ -139,8 +139,10 @@ public class TestConstruct01
 
 	//DEBUGOUT("Dbc.get");
 	while (dbcp.get(readkey, readdata, Db.DB_NEXT) == 0) {
-	    String key_string = new String(readkey.get_data());
-	    String data_string = new String(readdata.get_data());
+	    String key_string =
+              new String(readkey.get_data(), 0, readkey.get_size());
+	    String data_string =
+              new String(readdata.get_data(), 0, readkey.get_size());
 	    //DEBUGOUT("Got: " + key_string + ": " + data_string);
 	    int len = key_string.length();
 	    if (len <= 0 || key_string.charAt(len-1) != 'x') {
@@ -179,6 +181,7 @@ public class TestConstruct01
 	    System.out.print(" expected more keys, bitmap is: " + expected + "\n");
 	    ERR("missing keys in database");
 	}
+
 	dbcp.close();
 	db.close(0);
     }
@@ -433,7 +436,7 @@ public class TestConstruct01
                 //
                 System.gc();
                 System.runFinalization();
-                VERBOSEOUT("gc complete");
+                VERBOSEOUT("gc complete, bytes free == " + Runtime.getRuntime().freeMemory());
             }
         }
 
diff --git a/storage/bdb/test/scr016/TestConstruct01.testout b/storage/bdb/test/scr016/TestConstruct01.testout
index 5d2041cd197eb7679f08462cabbb1565c802dea1..2de13da003617bf3596f7798c7b28610df86a024 100644
--- a/storage/bdb/test/scr016/TestConstruct01.testout
+++ b/storage/bdb/test/scr016/TestConstruct01.testout
@@ -1,3 +1,3 @@
 ALL TESTS SUCCESSFUL
 delta for total mem: <10
-delta for free mem: <10000
+delta for free mem: <1000
diff --git a/storage/bdb/test/scr016/TestConstruct02.java b/storage/bdb/test/scr016/TestConstruct02.java
index 5bbb55ccd56330416b5eb3ab87151f31322c6aa7..2e55cfc6f3245fc819f866d7767c6f630aa48862 100644
--- a/storage/bdb/test/scr016/TestConstruct02.java
+++ b/storage/bdb/test/scr016/TestConstruct02.java
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2000-2002
+ * Copyright (c) 2000-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: TestConstruct02.java,v 1.6 2002/08/16 19:35:54 dda Exp $
+ * $Id: TestConstruct02.java,v 1.8 2004/01/28 03:36:34 bostic Exp $
  */
 
 /*
diff --git a/storage/bdb/test/scr016/TestDbtFlags.java b/storage/bdb/test/scr016/TestDbtFlags.java
index 98527e6b3e79acbc271fa9533ab86cf16ef2c289..0e2110ad137439e4ab072143af53e0a31effd55d 100644
--- a/storage/bdb/test/scr016/TestDbtFlags.java
+++ b/storage/bdb/test/scr016/TestDbtFlags.java
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: TestDbtFlags.java,v 1.4 2002/08/16 19:35:54 dda Exp $
+ * $Id: TestDbtFlags.java,v 1.8 2004/01/28 03:36:34 bostic Exp $
  */
 
 package com.sleepycat.test;
@@ -25,7 +25,7 @@ public class TestDbtFlags
 
     /*zippy quotes for test input*/
     static final String[] input_lines = {
-        "If we shadows have offended", 
+        "If we shadows have offended",
         "Think but this, and all is mended",
         "That you have but slumber'd here",
         "While these visions did appear",
@@ -97,8 +97,8 @@ public class TestDbtFlags
         // Create the database object.
         // There is no environment for this simple example.
         Db table = new Db(null, 0);
-        table.set_error_stream(System.err);
-        table.set_errpfx("TestDbtFlags");
+        table.setErrorStream(System.err);
+        table.setErrorPrefix("TestDbtFlags");
         table.open(null, FileName, null, Db.DB_BTREE, Db.DB_CREATE, 0644);
 
         //
@@ -165,12 +165,12 @@ public class TestDbtFlags
                  */
                 System.err.println("exception, iteration " + iteration_count +
                                    ": " + dme);
-                System.err.println("  key size: " + key.get_size() +
-                                   " ulen: " + key.get_ulen());
-                System.err.println("  data size: " + key.get_size() +
-                                   " ulen: " + key.get_ulen());
+                System.err.println("  key size: " + key.getSize() +
+                                   " ulen: " + key.getUserBufferLength());
+                System.err.println("  data size: " + key.getSize() +
+                                   " ulen: " + key.getUserBufferLength());
 
-                dme.get_dbt().set_size(buf_size);
+                dme.getDbt().setSize(buf_size);
                 StringDbt tempkey = new StringDbt(Db.DB_DBT_MALLOC, -1);
                 StringDbt tempdata = new StringDbt(Db.DB_DBT_MALLOC, -1);
                 if ((dbreturn = iterator.get(tempkey, tempdata, Db.DB_NEXT)) != 0) {
@@ -202,36 +202,36 @@ public class TestDbtFlags
         StringDbt(int flags, int buf_size)
         {
             this.saved_flags = flags;
-            set_flags(saved_flags);
+            setFlags(saved_flags);
             if (buf_size != -1) {
-                set_data(new byte[buf_size]);
-                set_ulen(buf_size);
+                setData(new byte[buf_size]);
+                setUserBufferLength(buf_size);
             }
         }
 
         StringDbt(String value, int flags)
         {
             this.saved_flags = flags;
-            set_flags(saved_flags);
+            setFlags(saved_flags);
             set_string(value);
         }
 
         void set_string(String value)
         {
-            set_data(value.getBytes());
-            set_size(value.length());
+            setData(value.getBytes());
+            setSize(value.length());
             check_flags();
         }
 
         String get_string()
         {
             check_flags();
-            return new String(get_data(), 0, get_size());
+            return new String(getData(), 0, getSize());
         }
 
         void check_flags()
         {
-            int actual_flags = get_flags();
+            int actual_flags = getFlags();
             if (actual_flags != saved_flags) {
                 System.err.println("flags botch: expected " + saved_flags +
                                    ", got " + actual_flags);
diff --git a/storage/bdb/test/scr016/TestGetSetMethods.java b/storage/bdb/test/scr016/TestGetSetMethods.java
index a1b2722d8fdefa820e2c64ab15a3e4e0d0af318c..06a52c5ad0e76037bb9ffb34e4fc0c8df3bf9853 100644
--- a/storage/bdb/test/scr016/TestGetSetMethods.java
+++ b/storage/bdb/test/scr016/TestGetSetMethods.java
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2000-2002
+ * Copyright (c) 2000-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: TestGetSetMethods.java,v 1.3 2002/01/11 15:54:02 bostic Exp $
+ * $Id: TestGetSetMethods.java,v 1.7 2004/01/28 03:36:34 bostic Exp $
  */
 
 /*
@@ -26,21 +26,21 @@ public class TestGetSetMethods
         DbTxn dbtxn;
         byte[][] conflicts = new byte[10][10];
 
-        dbenv.set_timeout(0x90000000,
+        dbenv.setTimeout(0x90000000,
                           Db.DB_SET_LOCK_TIMEOUT);
-        dbenv.set_lg_bsize(0x1000);
-        dbenv.set_lg_dir(".");
-        dbenv.set_lg_max(0x10000000);
-        dbenv.set_lg_regionmax(0x100000);
-        dbenv.set_lk_conflicts(conflicts);
-        dbenv.set_lk_detect(Db.DB_LOCK_DEFAULT);
+        dbenv.setLogBufferSize(0x1000);
+        dbenv.setLogDir(".");
+        dbenv.setLogMax(0x10000000);
+        dbenv.setLogRegionMax(0x100000);
+        dbenv.setLockConflicts(conflicts);
+        dbenv.setLockDetect(Db.DB_LOCK_DEFAULT);
         // exists, but is deprecated:
         // dbenv.set_lk_max(0);
-        dbenv.set_lk_max_lockers(100);
-        dbenv.set_lk_max_locks(10);
-        dbenv.set_lk_max_objects(1000);
-        dbenv.set_mp_mmapsize(0x10000);
-        dbenv.set_tas_spins(1000);
+        dbenv.setLockMaxLockers(100);
+        dbenv.setLockMaxLocks(10);
+        dbenv.setLockMaxObjects(1000);
+        dbenv.setMemoryPoolMapSize(0x10000);
+        dbenv.setTestAndSetSpins(1000);
 
         // Need to open the environment so we
         // can get a transaction.
@@ -50,39 +50,39 @@ public class TestGetSetMethods
                    Db.DB_INIT_MPOOL,
                    0644);
 
-        dbtxn = dbenv.txn_begin(null, Db.DB_TXN_NOWAIT);
-        dbtxn.set_timeout(0xA0000000, Db.DB_SET_TXN_TIMEOUT);
+        dbtxn = dbenv.txnBegin(null, Db.DB_TXN_NOWAIT);
+        dbtxn.setTimeout(0xA0000000, Db.DB_SET_TXN_TIMEOUT);
         dbtxn.abort();
 
         dbenv.close(0);
 
         // We get a db, one for each type.
         // That's because once we call (for instance)
-        // set_bt_maxkey, DB 'knows' that this is a
+        // setBtreeMinKey, DB 'knows' that this is a
         // Btree Db, and it cannot be used to try Hash
         // or Recno functions.
         //
         Db db_bt = new Db(null, 0);
-        db_bt.set_bt_maxkey(10000);
-        db_bt.set_bt_minkey(100);
-        db_bt.set_cachesize(0, 0x100000, 0);
+        db_bt.setBtreeMinKey(100);
+        db_bt.setCacheSize(0x100000, 0);
         db_bt.close(0);
 
         Db db_h = new Db(null, 0);
-        db_h.set_h_ffactor(0x10);
-        db_h.set_h_nelem(100);
-        db_h.set_lorder(0);
-        db_h.set_pagesize(0x10000);
+        db_h.setHashFillFactor(0x10);
+        db_h.setHashNumElements(100);
+        db_h.setByteOrder(0);
+        db_h.setPageSize(0x10000);
         db_h.close(0);
 
         Db db_re = new Db(null, 0);
-        db_re.set_re_delim('@');
-        db_re.set_re_pad(10);
-        db_re.set_re_source("re.in");
+        db_re.setRecordDelimiter('@');
+        db_re.setRecordPad(10);
+        db_re.setRecordSource("re.in");
+        db_re.setRecordLength(1000);
         db_re.close(0);
 
         Db db_q = new Db(null, 0);
-        db_q.set_q_extentsize(200);
+        db_q.setQueueExtentSize(200);
         db_q.close(0);
     }
 
diff --git a/storage/bdb/test/scr016/TestKeyRange.java b/storage/bdb/test/scr016/TestKeyRange.java
index 8eda2de426f62aec3fbd0aea78b9cc97ed7e8063..57a776b014a1a990fa0dfd03301e8dd12c7c504f 100644
--- a/storage/bdb/test/scr016/TestKeyRange.java
+++ b/storage/bdb/test/scr016/TestKeyRange.java
@@ -1,13 +1,15 @@
-/*NOTE: TestKeyRange is AccessExample changed to test Db.key_range.
- * See comments with ADDED for specific areas of change.
- */
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: TestKeyRange.java,v 1.4 2002/08/16 19:35:55 dda Exp $
+ * $Id: TestKeyRange.java,v 1.7 2004/01/28 03:36:34 bostic Exp $
+ */
+
+/*
+ * NOTE: TestKeyRange is AccessExample changed to test Db.key_range.
+ * See comments with ADDED for specific areas of change.
  */
 
 package com.sleepycat.test;
@@ -103,8 +105,8 @@ public class TestKeyRange
         // Create the database object.
         // There is no environment for this simple example.
         Db table = new Db(null, 0);
-        table.set_error_stream(System.err);
-        table.set_errpfx("TestKeyRange");
+        table.setErrorStream(System.err);
+        table.setErrorPrefix("TestKeyRange");
         table.open(null, FileName, null, Db.DB_BTREE, Db.DB_CREATE, 0644);
 
         //
@@ -143,7 +145,7 @@ public class TestKeyRange
 	    {
 		    if (count++ > 0) {
 			    DbKeyRange range = new DbKeyRange();
-			    table.key_range(null, key, range, 0);
+			    table.keyRange(null, key, range, 0);
 			    System.out.println("less: " + range.less);
 			    System.out.println("equal: " + range.equal);
 			    System.out.println("greater: " + range.greater);
@@ -180,24 +182,24 @@ public class TestKeyRange
     {
         StringDbt()
         {
-            set_flags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
+            setFlags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
         }
 
         StringDbt(String value)
         {
             setString(value);
-            set_flags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
+            setFlags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
         }
 
         void setString(String value)
         {
-            set_data(value.getBytes());
-            set_size(value.length());
+            setData(value.getBytes());
+            setSize(value.length());
         }
 
         String getString()
         {
-            return new String(get_data(), 0, get_size());
+            return new String(getData(), 0, getSize());
         }
     }
 }
diff --git a/storage/bdb/test/scr016/TestLockVec.java b/storage/bdb/test/scr016/TestLockVec.java
index ad48e9f2f9a362dcc8647977f38138bad8a426fc..b14a20c684802a874eae6cea7f5413058e476f3c 100644
--- a/storage/bdb/test/scr016/TestLockVec.java
+++ b/storage/bdb/test/scr016/TestLockVec.java
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: TestLockVec.java,v 1.4 2002/08/16 19:35:55 dda Exp $
+ * $Id: TestLockVec.java,v 1.7 2004/01/28 03:36:34 bostic Exp $
  */
 
 /*
@@ -40,8 +40,8 @@ public class TestLockVec
                        Db.DB_CREATE | Db.DB_INIT_LOCK | Db.DB_INIT_MPOOL, 0);
             dbenv2.open(".",
                        Db.DB_CREATE | Db.DB_INIT_LOCK | Db.DB_INIT_MPOOL, 0);
-            locker1 = dbenv1.lock_id();
-            locker2 = dbenv1.lock_id();
+            locker1 = dbenv1.lockId();
+            locker2 = dbenv1.lockId();
             Db db1 = new Db(dbenv1, 0);
             db1.open(null, "my.db", null, Db.DB_BTREE, Db.DB_CREATE, 0);
             Db db2 = new Db(dbenv2, 0);
@@ -73,7 +73,7 @@ public class TestLockVec
             catch (DbException dbe1) {
                 expectedErrs += 1;
             }
-            DbLock tmplock = dbenv1.lock_get(locker1, Db.DB_LOCK_NOWAIT,
+            DbLock tmplock = dbenv1.lockGet(locker1, Db.DB_LOCK_NOWAIT,
                                             Akey, Db.DB_LOCK_READ);
             lock_check_held(dbenv2, Akey, Db.DB_LOCK_READ);
             try {
@@ -86,7 +86,7 @@ public class TestLockVec
                 System.err.println("lock check mechanism is broken");
                 System.exit(1);
             }
-            dbenv1.lock_put(tmplock);
+            dbenv1.lockPut(tmplock);
 
             /* Now on with the test, a series of lock_vec requests,
              * with checks between each call.
@@ -103,7 +103,7 @@ public class TestLockVec
             reqs[2] = new DbLockRequest(Db.DB_LOCK_GET, Db.DB_LOCK_READ,
                                         Bkeyagain, null);
 
-            dbenv1.lock_vec(locker1, Db.DB_LOCK_NOWAIT, reqs, 0, 3);
+            dbenv1.lockVector(locker1, Db.DB_LOCK_NOWAIT, reqs, 0, 3);
 
             /* Locks held: A(W), B(R), B(R) */
             lock_check_held(dbenv2, Bkey, Db.DB_LOCK_READ);
@@ -111,10 +111,10 @@ public class TestLockVec
 
             System.out.println("put a couple");
             /* Request: put A, B(first) */
-            reqs[0].set_op(Db.DB_LOCK_PUT);
-            reqs[1].set_op(Db.DB_LOCK_PUT);
+            reqs[0].setOp(Db.DB_LOCK_PUT);
+            reqs[1].setOp(Db.DB_LOCK_PUT);
 
-            dbenv1.lock_vec(locker1, Db.DB_LOCK_NOWAIT, reqs, 0, 2);
+            dbenv1.lockVector(locker1, Db.DB_LOCK_NOWAIT, reqs, 0, 2);
 
             /* Locks held: B(R) */
             lock_check_free(dbenv2, Akey);
@@ -122,9 +122,9 @@ public class TestLockVec
 
             System.out.println("put one more, test index offset");
             /* Request: put B(second) */
-            reqs[2].set_op(Db.DB_LOCK_PUT);
+            reqs[2].setOp(Db.DB_LOCK_PUT);
 
-            dbenv1.lock_vec(locker1, Db.DB_LOCK_NOWAIT, reqs, 2, 1);
+            dbenv1.lockVector(locker1, Db.DB_LOCK_NOWAIT, reqs, 2, 1);
 
             /* Locks held: <none> */
             lock_check_free(dbenv2, Akey);
@@ -138,7 +138,7 @@ public class TestLockVec
                                         Akeyagain, null);
             reqs[2] = new DbLockRequest(Db.DB_LOCK_GET, Db.DB_LOCK_READ,
                                         Bkey, null);
-            dbenv1.lock_vec(locker1, Db.DB_LOCK_NOWAIT, reqs, 0, 3);
+            dbenv1.lockVector(locker1, Db.DB_LOCK_NOWAIT, reqs, 0, 3);
 
             /* Locks held: A(R), B(R), B(R) */
             lock_check_held(dbenv2, Akey, Db.DB_LOCK_READ);
@@ -150,7 +150,7 @@ public class TestLockVec
                                         Bkey, null);
             reqs[2] = new DbLockRequest(Db.DB_LOCK_PUT_OBJ, 0,
                                         Akey, null);
-            dbenv1.lock_vec(locker1, Db.DB_LOCK_NOWAIT, reqs, 1, 2);
+            dbenv1.lockVector(locker1, Db.DB_LOCK_NOWAIT, reqs, 1, 2);
 
             /* Locks held: B(R), B(R) */
             lock_check_free(dbenv2, Akey);
@@ -160,7 +160,7 @@ public class TestLockVec
             /* Request: get A(W) */
             reqs[0] = new DbLockRequest(Db.DB_LOCK_GET, Db.DB_LOCK_WRITE,
                                         Akey, null);
-            dbenv1.lock_vec(locker1, Db.DB_LOCK_NOWAIT, reqs, 0, 1);
+            dbenv1.lockVector(locker1, Db.DB_LOCK_NOWAIT, reqs, 0, 1);
 
             /* Locks held: A(W), B(R), B(R) */
             lock_check_held(dbenv2, Akey, Db.DB_LOCK_WRITE);
@@ -170,7 +170,7 @@ public class TestLockVec
             /* Request: putall */
             reqs[0] = new DbLockRequest(Db.DB_LOCK_PUT_ALL, 0,
                                         null, null);
-            dbenv1.lock_vec(locker1, Db.DB_LOCK_NOWAIT, reqs, 0, 1);
+            dbenv1.lockVector(locker1, Db.DB_LOCK_NOWAIT, reqs, 0, 1);
 
             lock_check_free(dbenv2, Akey);
             lock_check_free(dbenv2, Bkey);
@@ -198,9 +198,9 @@ public class TestLockVec
     static void lock_check_free(DbEnv dbenv, Dbt dbt)
         throws DbException
     {
-        DbLock tmplock = dbenv.lock_get(locker2, Db.DB_LOCK_NOWAIT,
-                                        dbt, Db.DB_LOCK_WRITE);
-        dbenv.lock_put(tmplock);
+        DbLock tmplock = dbenv.lockGet(locker2, Db.DB_LOCK_NOWAIT,
+                                       dbt, Db.DB_LOCK_WRITE);
+        dbenv.lockPut(tmplock);
     }
 
     /* Verify that the lock is held with the mode, throw an exception if not.
@@ -215,15 +215,15 @@ public class TestLockVec
 
         try {
             if (mode == Db.DB_LOCK_WRITE) {
-                never = dbenv.lock_get(locker2, Db.DB_LOCK_NOWAIT,
-                                       dbt, Db.DB_LOCK_READ);
+                never = dbenv.lockGet(locker2, Db.DB_LOCK_NOWAIT,
+                                      dbt, Db.DB_LOCK_READ);
             }
             else if (mode == Db.DB_LOCK_READ) {
-                DbLock rlock = dbenv.lock_get(locker2, Db.DB_LOCK_NOWAIT,
-                                              dbt, Db.DB_LOCK_READ);
-                dbenv.lock_put(rlock);
-                never = dbenv.lock_get(locker2, Db.DB_LOCK_NOWAIT,
-                                              dbt, Db.DB_LOCK_WRITE);
+                DbLock rlock = dbenv.lockGet(locker2, Db.DB_LOCK_NOWAIT,
+                                             dbt, Db.DB_LOCK_READ);
+                dbenv.lockPut(rlock);
+                never = dbenv.lockGet(locker2, Db.DB_LOCK_NOWAIT,
+                                      dbt, Db.DB_LOCK_WRITE);
             }
             else {
                 throw new DbException("lock_check_held bad mode");
@@ -236,7 +236,7 @@ public class TestLockVec
         /* make sure we failed */
         if (never != null) {
           try {
-            dbenv.lock_put(never);
+            dbenv.lockPut(never);
           }
           catch (DbException dbe2) {
             System.err.println("Got some real troubles now");
diff --git a/storage/bdb/test/scr016/TestLogc.java b/storage/bdb/test/scr016/TestLogc.java
index ec9c373a93b9a293d628111888f1bd9e3b9c32d0..8f406831829016212b5c660bf1d4f8fdcb09ee59 100644
--- a/storage/bdb/test/scr016/TestLogc.java
+++ b/storage/bdb/test/scr016/TestLogc.java
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: TestLogc.java,v 1.7 2002/08/16 19:35:55 dda Exp $
+ * $Id: TestLogc.java,v 1.9 2004/01/28 03:36:34 bostic Exp $
  */
 
 /*
diff --git a/storage/bdb/test/scr016/TestOpenEmpty.java b/storage/bdb/test/scr016/TestOpenEmpty.java
index ae92fd363d9f96752c378f5e8796a60ae3fba6da..ab5fb5a8d92172259fc283b90224b3217e16334a 100644
--- a/storage/bdb/test/scr016/TestOpenEmpty.java
+++ b/storage/bdb/test/scr016/TestOpenEmpty.java
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: TestOpenEmpty.java,v 1.4 2002/08/16 19:35:55 dda Exp $
+ * $Id: TestOpenEmpty.java,v 1.8 2004/01/28 03:36:34 bostic Exp $
  */
 
 package com.sleepycat.test;
@@ -12,6 +12,7 @@ package com.sleepycat.test;
 import com.sleepycat.db.*;
 import java.io.File;
 import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
 import java.io.InputStreamReader;
 import java.io.IOException;
 import java.io.PrintStream;
@@ -47,6 +48,11 @@ public class TestOpenEmpty
             System.err.println("TestOpenEmpty: " + fnfe.toString());
             System.exit(1);
         }
+        catch (Exception ex)
+        {
+            System.err.println("TestOpenEmpty: " + ex.toString());
+            System.exit(1);
+        }
         System.exit(0);
     }
 
@@ -96,14 +102,18 @@ public class TestOpenEmpty
         // Remove the previous database.
         new File(FileName).delete();
 
-        try { (new java.io.FileOutputStream(FileName)).close(); }
+        try {
+          FileOutputStream os = new FileOutputStream(FileName);
+          os.write("abc".getBytes());
+          os.close();
+        }
         catch (IOException ioe) { }
 
         // Create the database object.
         // There is no environment for this simple example.
         Db table = new Db(null, 0);
-        table.set_error_stream(System.err);
-        table.set_errpfx("TestOpenEmpty");
+        table.setErrorStream(System.err);
+        table.setErrorPrefix("TestOpenEmpty");
         table.open(null, FileName, null, Db.DB_BTREE, Db.DB_CREATE, 0644);
 
         //
@@ -166,24 +176,24 @@ public class TestOpenEmpty
     {
         StringDbt()
         {
-            set_flags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
+            setFlags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
         }
 
         StringDbt(String value)
         {
             setString(value);
-            set_flags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
+            setFlags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
         }
 
         void setString(String value)
         {
-            set_data(value.getBytes());
-            set_size(value.length());
+            setData(value.getBytes());
+            setSize(value.length());
         }
 
         String getString()
         {
-            return new String(get_data(), 0, get_size());
+            return new String(getData(), 0, getSize());
         }
     }
 }
diff --git a/storage/bdb/test/scr016/TestOpenEmpty.testerr b/storage/bdb/test/scr016/TestOpenEmpty.testerr
index dd3e01c7ab7327e936be33219bb084c40bf01c6f..c08da27b36e6dad70073552643872074065edfa4 100644
--- a/storage/bdb/test/scr016/TestOpenEmpty.testerr
+++ b/storage/bdb/test/scr016/TestOpenEmpty.testerr
@@ -1,2 +1,2 @@
 TestOpenEmpty: access.db: unexpected file type or format
-TestOpenEmpty: com.sleepycat.db.DbException: Invalid argument: Invalid argument
+TestOpenEmpty: java.lang.IllegalArgumentException: Invalid argument
diff --git a/storage/bdb/test/scr016/TestReplication.java b/storage/bdb/test/scr016/TestReplication.java
index 87cb683d60fa55ff0e647e484e569c3e4cf46684..e20b9a929014605f1a916ed3591c40b05126d599 100644
--- a/storage/bdb/test/scr016/TestReplication.java
+++ b/storage/bdb/test/scr016/TestReplication.java
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: TestReplication.java,v 1.3 2002/01/23 14:29:51 bostic Exp $
+ * $Id: TestReplication.java,v 1.7 2004/01/28 03:36:34 bostic Exp $
  */
 
 /*
@@ -39,7 +39,7 @@ public class TestReplication extends Thread
     {
         (new File(name)).mkdir();
     }
-    
+
 
     // The client thread runs this
     public void run()
@@ -66,7 +66,7 @@ public class TestReplication extends Thread
 
             while (running) {
                 int msgtype = 0;
-                
+
                 System.err.println("c30");
                 synchronized (queue) {
                     if (queue.size() == 0) {
@@ -79,7 +79,7 @@ public class TestReplication extends Thread
                         byte[] data;
 
                         System.err.println("c50 " + msgtype);
-                        
+
                         switch (msgtype) {
                             case -1:
                                 running = false;
@@ -105,12 +105,12 @@ public class TestReplication extends Thread
                                 rec.set_size(0);
                                 break;
                         }
-                        
+
                     }
                 }
                 System.err.println("c60");
                 if (msgtype == 3 || msgtype == 4) {
-                    System.out.println("cLIENT: Got message");
+                    System.out.println("client: Got message");
                     client_env.rep_process_message(control, rec,
                                                    processMsg);
                 }
@@ -140,9 +140,9 @@ public class TestReplication extends Thread
             System.err.println("Unexpected envid = " + envid);
             return 0;
         }
-        
+
         int nbytes = 0;
-        
+
         synchronized (queue) {
             System.out.println("Sending message");
             byte[] data = control.get_data();
@@ -153,11 +153,11 @@ public class TestReplication extends Thread
                 System.arraycopy(data, 0, newdata, 0, data.length);
                 queue.addElement(newdata);
             }
-            else 
+            else
             {
                 queue.addElement(new Integer(2));
             }
-            
+
             data = rec.get_data();
             if (data != null && data.length > 0) {
                 queue.addElement(new Integer(3));
@@ -166,7 +166,7 @@ public class TestReplication extends Thread
                 System.arraycopy(data, 0, newdata, 0, data.length);
                 queue.addElement(newdata);
             }
-            else 
+            else
             {
                 queue.addElement(new Integer(4));
             }
@@ -184,14 +184,14 @@ public class TestReplication extends Thread
         {
         }
     }
-    
+
     public void send_terminator()
     {
         synchronized (queue) {
             queue.addElement(new Integer(-1));
         }
     }
-    
+
     public void master()
     {
         try {
@@ -256,7 +256,7 @@ class TimelimitThread extends Thread
 {
     long nmillis;
     boolean finished = false;
-    
+
     TimelimitThread(long nmillis)
     {
         this.nmillis = nmillis;
@@ -266,12 +266,12 @@ class TimelimitThread extends Thread
     {
         finished = true;
     }
-    
+
     public void run()
     {
         long targetTime = System.currentTimeMillis() + nmillis;
         long curTime;
-        
+
         while (!finished &&
                ((curTime = System.currentTimeMillis()) < targetTime)) {
             long diff = targetTime - curTime;
diff --git a/storage/bdb/test/scr016/TestRpcServer.java b/storage/bdb/test/scr016/TestRpcServer.java
index ef325cef075791c7d9c2376bf6f69f801ba4256e..ee040f0cfd688990c7f2fad322ace4a7f28c64da 100644
--- a/storage/bdb/test/scr016/TestRpcServer.java
+++ b/storage/bdb/test/scr016/TestRpcServer.java
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: TestRpcServer.java,v 1.3 2002/01/11 15:54:03 bostic Exp $
+ * $Id: TestRpcServer.java,v 1.5 2004/01/28 03:36:34 bostic Exp $
  */
 
 package com.sleepycat.test;
diff --git a/storage/bdb/test/scr016/TestSameDbt.java b/storage/bdb/test/scr016/TestSameDbt.java
index 9866ed49307481d59e848f870a0ea8f03423d12f..28a46af31e98f5bf0aea9f285ebe8a03e9a562f7 100644
--- a/storage/bdb/test/scr016/TestSameDbt.java
+++ b/storage/bdb/test/scr016/TestSameDbt.java
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: TestSameDbt.java,v 1.4 2002/01/23 14:29:51 bostic Exp $
+ * $Id: TestSameDbt.java,v 1.6 2004/01/28 03:36:34 bostic Exp $
  */
 
 /*
diff --git a/storage/bdb/test/scr016/TestSimpleAccess.java b/storage/bdb/test/scr016/TestSimpleAccess.java
index ba7390cada11f53f1c0f39fcd9de11d010ac20aa..72886b5d240a24d80d486b61f92ca6112ab260cc 100644
--- a/storage/bdb/test/scr016/TestSimpleAccess.java
+++ b/storage/bdb/test/scr016/TestSimpleAccess.java
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: TestSimpleAccess.java,v 1.5 2002/08/16 19:35:55 dda Exp $
+ * $Id: TestSimpleAccess.java,v 1.7 2004/01/28 03:36:34 bostic Exp $
  */
 
 /*
diff --git a/storage/bdb/test/scr016/TestStat.java b/storage/bdb/test/scr016/TestStat.java
index 55ba982311590225ce263a21d6d16e3e301a8540..84add875e04ab9b028071faf56116b41a25fde28 100644
--- a/storage/bdb/test/scr016/TestStat.java
+++ b/storage/bdb/test/scr016/TestStat.java
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: TestStat.java,v 1.1 2002/08/16 19:35:56 dda Exp $
+ * $Id: TestStat.java,v 1.10 2004/01/28 03:36:34 bostic Exp $
  */
 
 /*
@@ -21,11 +21,22 @@ public class TestStat
     public static void main(String[] args)
     {
         int envflags =
-            Db.DB_INIT_MPOOL | Db.DB_INIT_LOCK |
-            Db.DB_INIT_LOG | Db.DB_INIT_TXN | Db.DB_CREATE;
+            Db.DB_INIT_MPOOL | Db.DB_INIT_LOCK | Db.DB_INIT_LOG |
+            Db.DB_INIT_REP | Db.DB_INIT_TXN | Db.DB_CREATE;
         try {
             DbEnv dbenv = new DbEnv(0);
             dbenv.open(".", envflags, 0);
+
+            // Use a separate environment that has no activity
+            // to do the replication stats.  We don't want to get
+            // into configuring a real replication environment here.
+            DbEnv repenv = new DbEnv(0);
+            repenv.open(".", envflags, 0);
+
+            // Keep a couple transactions open so DbTxnStat active
+            // array will have some entries.
+            DbTxn dbtxn1 = dbenv.txnBegin(null, 0);
+            DbTxn dbtxn2 = dbenv.txnBegin(dbtxn1, 0);
             Db db = new Db(dbenv, 0);
             db.open(null, "my.db", null, Db.DB_BTREE, Db.DB_CREATE, 0);
 
@@ -35,12 +46,38 @@ public class TestStat
             System.out.println("  bt_magic: " + stat.bt_magic);
 
             System.out.println("LogStat:");
-            DbLogStat logstat = dbenv.log_stat(0);
+            DbLogStat logstat = dbenv.logStat(0);
             System.out.println("  st_magic: " + logstat.st_magic);
             System.out.println("  st_cur_file: " + logstat.st_cur_file);
 
+            System.out.println("TxnStat:");
+            DbTxnStat txnstat = dbenv.txnStat(0);
+            System.out.println("  st_ncommits: " + txnstat.st_ncommits);
+            System.out.println("  st_nactive: " + txnstat.st_nactive);
+
+            DbTxnStat.Active active0 = txnstat.st_txnarray[0];
+            DbTxnStat.Active active1 = txnstat.st_txnarray[1];
+            if (active0.txnid != active1.parentid &&
+                active1.txnid != active0.parentid) {
+              System.out.println("Missing PARENT/CHILD txn relationship:");
+              System.out.println("  st_active[0].txnid: " + active0.txnid);
+              System.out.println("  st_active[0].parentid: " +
+                                 active0.parentid);
+              System.out.println("  st_active[1].txnid: " + active1.txnid);
+              System.out.println("  st_active[1].parentid: " +
+                                 active1.parentid);
+            }
+
+	    System.out.println("DbMpoolStat:");
+	    DbMpoolStat mpstat = dbenv.memoryPoolStat(0);
+	    System.out.println("  st_gbytes: " + mpstat.st_gbytes);
+
+	    System.out.println("DbMpoolFileStat:");
+	    DbMpoolFStat[] mpfstat = dbenv.memoryPoolFileStat(0);
+	    System.out.println("  num files: " + mpfstat.length);
+
             System.out.println("RepStat:");
-            DbRepStat repstat = dbenv.rep_stat(0);
+            DbRepStat repstat = repenv.replicationStat(0);
             System.out.println("  st_status: " + repstat.st_status);
             System.out.println("  st_log_duplication: " +
                                repstat.st_log_duplicated);
diff --git a/storage/bdb/test/scr016/TestStat.testout b/storage/bdb/test/scr016/TestStat.testout
index caf9db1fb13715eb8356a006f2e085e4db5a73cd..bd21aa7638de5f1003cd4f6e9bd16688e92cf612 100644
--- a/storage/bdb/test/scr016/TestStat.testout
+++ b/storage/bdb/test/scr016/TestStat.testout
@@ -5,6 +5,13 @@ BtreeStat:
 LogStat:
   st_magic: 264584
   st_cur_file: 1
+TxnStat:
+  st_ncommits: 0
+  st_nactive: 2
+DbMpoolStat:
+  st_gbytes: 0
+DbMpoolFileStat:
+  num files: 1
 RepStat:
   st_status: 0
   st_log_duplication: 0
diff --git a/storage/bdb/test/scr016/TestTruncate.java b/storage/bdb/test/scr016/TestTruncate.java
index 713772362469e690801b262ba812fe93ddd307c9..c84f68db4ee9f7a17da988dec1503a4f75389eb8 100644
--- a/storage/bdb/test/scr016/TestTruncate.java
+++ b/storage/bdb/test/scr016/TestTruncate.java
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: TestTruncate.java,v 1.4 2002/01/23 14:29:52 bostic Exp $
+ * $Id: TestTruncate.java,v 1.8 2004/01/28 03:36:34 bostic Exp $
  */
 
 /*
@@ -34,7 +34,7 @@ public class TestTruncate
             Dbt goodkeydbt = new Dbt("key".getBytes());
             Dbt badkeydbt = new Dbt("badkey".getBytes());
             Dbt resultdbt = new Dbt();
-            resultdbt.set_flags(Db.DB_DBT_MALLOC);
+            resultdbt.setFlags(Db.DB_DBT_MALLOC);
 
             int ret;
 
@@ -43,7 +43,7 @@ public class TestTruncate
             }
             else {
                 String result =
-                    new String(resultdbt.get_data(), 0, resultdbt.get_size());
+                    new String(resultdbt.getData(), 0, resultdbt.getSize());
                 System.out.println("got data: " + result);
             }
 
@@ -53,7 +53,7 @@ public class TestTruncate
             }
             else {
                 String result =
-                    new String(resultdbt.get_data(), 0, resultdbt.get_size());
+                    new String(resultdbt.getData(), 0, resultdbt.getSize());
                 System.out.println("*** got data using bad key!!: " + result);
             }
 
@@ -63,12 +63,12 @@ public class TestTruncate
             System.out.println("truncate returns " + nrecords);
             if ((ret = db.get(null, goodkeydbt, resultdbt, 0)) != 0) {
                 // We expect this...
-                System.out.println("after trunctate get: " +
+                System.out.println("after truncate get: " +
                                    DbEnv.strerror(ret));
             }
             else {
                 String result =
-                    new String(resultdbt.get_data(), 0, resultdbt.get_size());
+                    new String(resultdbt.getData(), 0, resultdbt.getSize());
                 System.out.println("got data: " + result);
             }
 
diff --git a/storage/bdb/test/scr016/TestTruncate.testout b/storage/bdb/test/scr016/TestTruncate.testout
index 23f291df7540245324172d4fa3310e890543fd9a..0a4bc98165d304f262437a59e32ea8f64e2b0ffd 100644
--- a/storage/bdb/test/scr016/TestTruncate.testout
+++ b/storage/bdb/test/scr016/TestTruncate.testout
@@ -2,5 +2,5 @@ got data: data
 get using bad key: DB_NOTFOUND: No matching key/data pair found
 truncating data...
 truncate returns 1
-after trunctate get: DB_NOTFOUND: No matching key/data pair found
+after truncate get: DB_NOTFOUND: No matching key/data pair found
 finished test
diff --git a/storage/bdb/test/scr016/TestUtil.java b/storage/bdb/test/scr016/TestUtil.java
index 1bddfb0b0140a8beb04c11c2afcc52b321cce8cc..799d326cde7b54f2655c2d06f2870e315610033b 100644
--- a/storage/bdb/test/scr016/TestUtil.java
+++ b/storage/bdb/test/scr016/TestUtil.java
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997-2002
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: TestUtil.java,v 1.1 2002/08/16 19:35:56 dda Exp $
+ * $Id: TestUtil.java,v 1.5 2004/01/28 03:36:34 bostic Exp $
  */
 
 /*
@@ -25,32 +25,32 @@ public class TestUtil
         Dbt keydbt = new Dbt("key".getBytes());
         Dbt datadbt = new Dbt("data".getBytes());
         db.put(null, keydbt, datadbt, 0);
-        
+
         // Now, retrieve.  We could use keydbt over again,
         // but that wouldn't be typical in an application.
         Dbt goodkeydbt = new Dbt("key".getBytes());
         Dbt badkeydbt = new Dbt("badkey".getBytes());
         Dbt resultdbt = new Dbt();
-        resultdbt.set_flags(Db.DB_DBT_MALLOC);
-        
+        resultdbt.setFlags(Db.DB_DBT_MALLOC);
+
         int ret;
-        
+
         if ((ret = db.get(null, goodkeydbt, resultdbt, 0)) != 0) {
             System.out.println("get: " + DbEnv.strerror(ret));
         }
         else {
             String result =
-                new String(resultdbt.get_data(), 0, resultdbt.get_size());
+                new String(resultdbt.getData(), 0, resultdbt.getSize());
             System.out.println("got data: " + result);
         }
-        
+
         if ((ret = db.get(null, badkeydbt, resultdbt, 0)) != 0) {
             // We expect this...
             System.out.println("get using bad key: " + DbEnv.strerror(ret));
         }
         else {
             String result =
-                new String(resultdbt.get_data(), 0, resultdbt.get_size());
+                new String(resultdbt.getData(), 0, resultdbt.getSize());
             System.out.println("*** got data using bad key!!: " + result);
         }
     }
diff --git a/storage/bdb/test/scr016/TestXAServlet.java b/storage/bdb/test/scr016/TestXAServlet.java
index 8b9fe57e26183c7d37321689ec925d78f5754f26..29545b3b93a9ec8c340f0ad2baebe36157db09f5 100644
--- a/storage/bdb/test/scr016/TestXAServlet.java
+++ b/storage/bdb/test/scr016/TestXAServlet.java
@@ -1,10 +1,10 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: TestXAServlet.java,v 1.1 2002/04/24 03:26:33 dda Exp $
+ * $Id: TestXAServlet.java,v 1.4 2004/01/28 03:36:34 bostic Exp $
  */
 
 /*
@@ -143,7 +143,7 @@ public class TestXAServlet extends HttpServlet
                     key = "key" + counter;
             if (value == null || value.equals(""))
                     value = "value" + counter;
-            
+
             out.println("Adding (\"" + key + "\", \"" + value + "\")");
 
             System.out.println("XA transaction begin");
@@ -209,7 +209,7 @@ public class TestXAServlet extends HttpServlet
             e.printStackTrace();
         }
     }
-        
+
     private static Xid getBogusXid()
         throws XAException
     {
@@ -304,7 +304,7 @@ public class TestXAServlet extends HttpServlet
         throws NamingException
     {
         Hashtable env = new Hashtable();
-        env.put(Context.INITIAL_CONTEXT_FACTORY, 
+        env.put(Context.INITIAL_CONTEXT_FACTORY,
                 "weblogic.jndi.WLInitialContextFactory");
         env.put(Context.PROVIDER_URL, url);
         return new InitialContext(env);
diff --git a/storage/bdb/test/scr016/chk.javatests b/storage/bdb/test/scr016/chk.javatests
index 34d7dfe78d7ae082ba1a2675b9cdfd7d03c30870..2e2217dc720b00267c2b1e9efa2cb242cb3333a6 100644
--- a/storage/bdb/test/scr016/chk.javatests
+++ b/storage/bdb/test/scr016/chk.javatests
@@ -1,6 +1,6 @@
 #!/bin/sh -
 #
-# $Id: chk.javatests,v 1.5 2002/08/16 19:35:56 dda Exp $
+# $Id: chk.javatests,v 1.6 2003/11/21 02:35:46 bostic Exp $
 #
 # Check to make sure that regression tests for Java run.
 
@@ -26,7 +26,7 @@ cd ..
 	echo 'FAIL: chk.javatests must be run from a local build directory.'
 	exit 1
 }
-[ -d ../docs_src ] || {
+[ -d ../env ] || {
 	echo 'FAIL: chk.javatests must be run from a local build directory.'
 	exit 1
 }
diff --git a/storage/bdb/test/scr016/ignore b/storage/bdb/test/scr016/ignore
index 1dfaf6adea4e06d21be7255db4c64d4089a0a133..03469ecdc519baec52a29571d4fa493e7b738555 100644
--- a/storage/bdb/test/scr016/ignore
+++ b/storage/bdb/test/scr016/ignore
@@ -1,20 +1,23 @@
 #
-# $Id: ignore,v 1.4 2002/08/16 19:35:56 dda Exp $
+# $Id: ignore,v 1.7 2003/08/07 15:48:03 mjc Exp $
 #
 # A list of tests to ignore
 
-# TestRpcServer is not debugged
+# These tests are not debugged
 TestRpcServer
-
-# TestReplication is not debugged
 TestReplication
 
 # These are currently not working
 TestAppendRecno
 TestAssociate
 TestLogc
+TestConstruct01
 TestConstruct02
 
+# We no longer check to see that a Dbt is used more than
+# once simultaneously.  It's no longer a disastrous error.
+TestSameDbt
+
 # TestUtil is used by the other tests, it does not stand on its own
 TestUtil
 
diff --git a/storage/bdb/test/scr016/testone b/storage/bdb/test/scr016/testone
index 5f5d2e0017d1b22a493859fc84c5effba52cfd56..ff654da3af8bb0209e8fb7de46abf8f878224300 100644
--- a/storage/bdb/test/scr016/testone
+++ b/storage/bdb/test/scr016/testone
@@ -1,5 +1,5 @@
 #!/bin/sh -
-#	$Id: testone,v 1.5 2002/08/16 19:35:56 dda Exp $
+#	$Id: testone,v 1.7 2003/05/06 17:09:44 dda Exp $
 #
 # Run just one Java regression test, the single argument
 # is the classname within this package.
@@ -83,12 +83,16 @@ fi
 rm -rf TESTDIR; mkdir TESTDIR
 cd ./TESTDIR
 mkdir -p $classdir
-${JAVAC} -d $classdir ../$name.java ../TestUtil.java > ../$name.compileout 2>&1
-if [ $? != 0 -o -s ../$name.compileout ]; then
+${JAVAC} -deprecation -d $classdir ../$name.java ../TestUtil.java > ../$name.compileout 2>&1
+ERR=$?
+if [ $ERR != 0 -o -s ../$name.compileout ]; then
 	error "compilation of $name failed, see $name.compileout"
-	exit 1
+	if [ "$ERR" != 0 ]; then
+		exit 1
+	fi
+else
+	rm -f ../$name.compileout
 fi
-rm -f ../$name.compileout
 
 # find input and error file
 infile=../$name.testin
diff --git a/storage/bdb/test/scr017/chk.db185 b/storage/bdb/test/scr017/chk.db185
index c2a07c51d26c5bdac062fa451162c34935afd34c..e6bfef84562e0e970556f0b7bee8ee655ce773ef 100644
--- a/storage/bdb/test/scr017/chk.db185
+++ b/storage/bdb/test/scr017/chk.db185
@@ -1,6 +1,6 @@
 #!/bin/sh -
 #
-# $Id: chk.db185,v 1.2 2001/10/12 17:55:38 bostic Exp $
+# $Id: chk.db185,v 1.3 2003/09/30 19:31:36 bostic Exp $
 #
 # Check to make sure we can run DB 1.85 code.
 
@@ -23,4 +23,7 @@ else
 	exit 1
 fi
 
+# Clean up so the next test doesn't get confused.
+rm -rf *
+
 exit 0
diff --git a/storage/bdb/test/scr019/chk.include b/storage/bdb/test/scr019/chk.include
index 444217bedb4b9fd65567183f9113392e7042e5be..edd2bf6b4513b06fcb73158f43305e3d8e23fc30 100644
--- a/storage/bdb/test/scr019/chk.include
+++ b/storage/bdb/test/scr019/chk.include
@@ -1,6 +1,6 @@
 #!/bin/sh -
 #
-# $Id: chk.include,v 1.3 2002/03/27 04:33:09 bostic Exp $
+# $Id: chk.include,v 1.4 2004/10/07 20:34:39 bostic Exp $
 #
 # Check for inclusion of files already included in db_int.h.
 
@@ -29,8 +29,12 @@ sed -e '/^build/d' \
     -e '/^examples_c/d' \
     -e '/^libdb_java.*errno.h/d' \
     -e '/^libdb_java.*java_util.h/d' \
+    -e '/^mod_db4/d' \
+    -e '/^mutex\/tm.c/d' \
+    -e '/^perl/d' \
+    -e '/^php_db4/d' \
     -e '/^test_/d' \
-    -e '/^mutex\/tm.c/d' > $t2
+    > $t2
 
 [ -s $t2 ] && {
 	echo 'FAIL: found extraneous includes in the source'
diff --git a/storage/bdb/test/scr020/chk.inc b/storage/bdb/test/scr020/chk.inc
index 189126b10c313687f25541fc1dafa5aea152e29c..24c1a47c10d469a1c20869a6e82db2b947bf5d5a 100644
--- a/storage/bdb/test/scr020/chk.inc
+++ b/storage/bdb/test/scr020/chk.inc
@@ -1,6 +1,6 @@
 #!/bin/sh -
 #
-# $Id: chk.inc,v 1.1 2002/02/10 17:14:33 bostic Exp $
+# $Id: chk.inc,v 1.2 2003/08/01 16:49:29 bostic Exp $
 #
 # Check for inclusion of db_config.h after "const" or other includes.
 
@@ -16,12 +16,13 @@ t1=__1
 t2=__2
 
 (cd $d && find . -name '*.[chys]' -o -name '*.cpp' |
-    xargs egrep -l '#include.*db_config.h') > $t1
+    xargs egrep -l '#include.*db_config.h') | tee /tmp/o |
+    sed -e '/dbdemo.c$/d' \
+        -e '/db_java_wrap.c$/d' > $t1
 
-:> $t2
-for i in `cat $t1`; do
-	egrep -w 'db_config.h|const' /dev/null $d/$i | head -1 >> $t2
-done
+(for i in `cat $t1`; do
+	egrep -w 'db_config.h|const' /dev/null $d/$i | head -1
+done) > $t2
 
 if egrep const $t2 > /dev/null; then
 	echo 'FAIL: found const before include of db_config.h'
diff --git a/storage/bdb/test/scr021/chk.flags b/storage/bdb/test/scr021/chk.flags
index 1b2bb62cca74bcd13b4b20dab605281bc23df7f5..2f32b82e63634ecd46ddaed62211d8a431f8535d 100644
--- a/storage/bdb/test/scr021/chk.flags
+++ b/storage/bdb/test/scr021/chk.flags
@@ -1,88 +1,109 @@
 #!/bin/sh -
 #
-# $Id: chk.flags,v 1.8 2002/08/14 02:19:55 bostic Exp $
+# $Id: chk.flags,v 1.12 2004/10/19 02:28:19 bostic Exp $
 #
 # Check flag name-spaces.
 
 d=../..
-
 t1=__1
+t2=__2
 
-# Check for DB_ENV flags.
-(grep 'F_ISSET([^ ]*dbenv,' $d/*/*.[chys];
- grep 'F_SET([^ ]*dbenv,' $d/*/*.[chys];
- grep 'F_CLR([^ ]*dbenv,' $d/*/*.[chys]) |
- sed -e '/DB_ENV_/d' -e '/F_SET([^ ]*dbenv, db_env_reset)/d' > $t1
-[ -s $t1 ] && {
-	cat $t1
+if cc -g -Wall -I.. t.c -o t; then
+	:
+else
+	echo "FAIL: unable to compile test program t.c"
+	exit 1
+fi
+
+if ./t $d/*/*.[ch] $d/*/*.in > $t1; then
+	:
+else
+	echo "FAIL: test program failed"
+	exit 1
+fi
+
+echo Checking DB_ENV flags...
+cat $t1 |
+grep '(dbenv,' |
+sed -e '/DB_ENV_/d' \
+    -e '/env_method.c.*, mapped_flags*)/d' \
+    -e '/env_region.c.*, db_env_reset)/d' \
+    > $t2
+[ -s $t2 ] && {
+	cat $t2
 	exit 1
 }
 
-grep 'DB_ENV_' $d/*/*.c |
-sed -e '/F_.*dbenv,/d' \
-    -e '/DB_ENV_TEST_RECOVERY(.*DB_TEST_/d' \
-    -e '/\/libdb_java\//d' > $t1
-[ -s $t1 ] && {
-	cat $t1
+grep 'DB_ENV_' $t1 |
+sed -e '/((*dbenv)*,/d' \
+    -e '/((*dbp)*->dbenv,/d' \
+    -e '/((*infop)*->dbenv,/d' \
+    -e '/((*reginfop)*->dbenv,/d' \
+    -e '/((*sdbp)*->dbenv,/d' \
+    > $t2
+[ -s $t2 ] && {
+	cat $t2
 	exit 1
 }
 
-# Check for DB flags.
-(grep 'F_ISSET([^ ]*dbp,' $d/*/*.[chys];
- grep 'F_SET([^ ]*dbp,' $d/*/*.[chys];
- grep 'F_CLR([^ ]*dbp,' $d/*/*.[chys]) |
- sed -e '/DB_AM_/d' \
-     -e '/db.c:.*F_SET.*F_ISSET(subdbp,/d' > $t1
-[ -s $t1 ] && {
-	cat $t1
+echo Checking DB flags...
+cp $t1 /tmp/_f
+cat $t1 |
+grep '(dbp,' |
+sed -e '/DB_AM_/d' \
+    -e '/dbp, mapped_flag)/d' \
+    > $t2
+[ -s $t2 ] && {
+	cat $t2
 	exit 1
 }
 
-grep 'DB_AM_' $d/*/*.c |
-sed -e '/F_.*dbp/d' \
-    -e '/"DB->open", dbp->flags, DB_AM_DUP,/d' \
-    -e '/"DB_NODUPDATA" behavior for databases with/d' \
-    -e '/If DB_AM_OPEN_CALLED is not set, then we/d' \
-    -e '/This was checked in set_flags when DB_AM_ENCRYPT/d' \
-    -e '/XA_ABORT, we can safely set DB_AM_RECOVER/d' \
-    -e '/ DB_AM_RECNUM\./d' \
-    -e '/ DB_AM_RECOVER set\./d' \
-    -e '/isdup = dbp->flags & DB_AM_DUP/d' \
-    -e '/otherwise we simply do/d' \
-    -e '/pginfo/d' \
-    -e '/setting DB_AM_RECOVER, we guarantee that we don/d' \
-    -e '/:[	 {]*DB_AM_/d' > $t1
-[ -s $t1 ] && {
-	cat $t1
+grep 'DB_AM_' $t1 |
+sed -e '/((*[	 ]*db_rep->rep_db)*,/d' \
+    -e '/((*[	 ]*dbc)*->dbp,/d' \
+    -e '/((*[	 ]*dbc_arg->dbp)*,/d' \
+    -e '/((*[	 ]*dbp)*,/d' \
+    -e '/((*[	 ]*dbp)*->s_primary,/d' \
+    -e '/((D),/d' \
+    -e '/(mdbp,/d' \
+    -e '/(pdbp,/d' \
+    -e '/(pginfo, /d' \
+    -e '/(sdbp,/d' \
+    -e '/(subdbp,/d' \
+    -e '/fop_util.c:.*(t2dbp,/d' \
+    -e '/rep_backup.c.*(rfp,/d' \
+    > $t2
+[ -s $t2 ] && {
+	cat $t2
 	exit 1
 }
 
-# Check for DBC flags.
-(grep 'F_ISSET([^ ]*dbc,' $d/*/*.[chys];
- grep 'F_SET([^ ]*dbc,' $d/*/*.[chys];
- grep 'F_CLR([^ ]*dbc,' $d/*/*.[chys]) |
- sed -e '/DBC_/d' > $t1
-[ -s $t1 ] && {
-	cat $t1
+echo Checking DBC flags...
+cat $t1 |
+grep '(dbc,' |
+sed -e '/DBC_/d' \
+    > $t2
+[ -s $t2 ] && {
+	cat $t2
 	exit 1
 }
 
-grep 'DBC_' $d/*/*.c |
-sed -e '/F_.*dbc/d' \
-    -e '/DBC_INTERNAL/d' \
-    -e '/DBC_LOGGING/d' \
-    -e '/Do the actual get.  Set DBC_TRANSIENT/d' \
-    -e '/If DBC_WRITEDUP is set, the cursor is an in/d' \
-    -e '/The DBC_TRANSIENT flag indicates that we/d' \
-    -e '/This function replaces the DBC_CONTINUE and DBC_KEYSET/d' \
-    -e '/db_cam.c:.*F_CLR(opd, DBC_ACTIVE);/d' \
-    -e '/{ DBC_/d' > $t1
-[ -s $t1 ] && {
-	cat $t1
+grep 'DBC_' $t1 |
+sed -e '/((*dbc)*,/d' \
+    -e '/(dbc_arg,/d' \
+    -e '/(dbc_c,/d' \
+    -e '/(dbc_n,/d' \
+    -e '/(dbc_orig,/d' \
+    -e '/(opd,/d' \
+    -e '/(pdbc,/d' \
+    -e '/(sdbc,/d' \
+    > $t2
+[ -s $t2 ] && {
+	cat $t2
 	exit 1
 }
 
-# Check for bad use of macros.
+echo Checking for bad use of macros...
 egrep 'case .*F_SET\(|case .*F_CLR\(' $d/*/*.c > $t1
 egrep 'for .*F_SET\(|for .*F_CLR\(' $d/*/*.c >> $t1
 egrep 'if .*F_SET\(|if .*F_CLR\(' $d/*/*.c >> $t1
diff --git a/storage/bdb/test/scr022/chk.rr b/storage/bdb/test/scr022/chk.rr
index df23031529977a6d9262195527e4885c9f7f7205..53d8bb1583300eecec8be1c5f8f4a719b07b441c 100644
--- a/storage/bdb/test/scr022/chk.rr
+++ b/storage/bdb/test/scr022/chk.rr
@@ -1,6 +1,6 @@
 #!/bin/sh -
 #
-# $Id: chk.rr,v 1.1 2002/04/19 15:13:05 bostic Exp $
+# $Id: chk.rr,v 1.5 2004/10/07 20:40:43 bostic Exp $
 
 d=../..
 
@@ -8,11 +8,16 @@ t1=__1
 
 # Check for DB_RUNRECOVERY being specified instead of a call to db_panic.
 egrep DB_RUNRECOVERY $d/*/*.c |
-    sed -e '/common\/db_err.c:/d' \
-        -e '/libdb_java\/java_util.c:/d' \
+    sed -e '/__db_panic(.*, DB_RUNRECOVERY)/d' \
+	-e '/case DB_RUNRECOVERY:/d' \
 	-e '/db_dispatch.c:.*if (ret == DB_RUNRECOVERY/d' \
+	-e '/db_err.c:/d' \
+	-e '/os_errno.c:.*evalue == DB_RUNRECOVERY/d' \
+	-e '/\/php_db4\//d' \
+	-e '/rep_backup.c:.*Panic the env and return DB_RUNRECOVERY/d' \
 	-e '/txn.c:.* \* DB_RUNRECOVERY and we need to/d' \
-	-e '/__db_panic(.*, DB_RUNRECOVERY)/d' > $t1
+	-e '/txn.c:.*returned DB_RUNRECOVERY and we need to/d' \
+	> $t1
 [ -s $t1 ] && {
 	echo "DB_RUNRECOVERY used; should be a call to db_panic."
 	cat $t1
diff --git a/storage/bdb/test/sdb001.tcl b/storage/bdb/test/sdb001.tcl
index a03160e0ab72fa28acba51cd6b249b0f252bf218..4ebb24dea295006ef9557b0a545b02a1c480bd71 100644
--- a/storage/bdb/test/sdb001.tcl
+++ b/storage/bdb/test/sdb001.tcl
@@ -1,11 +1,11 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: sdb001.tcl,v 11.18 2002/06/10 15:39:36 sue Exp $
+# $Id: sdb001.tcl,v 11.23 2004/04/05 17:49:25 carol Exp $
 #
-# TEST	subdb001	Tests mixing db and subdb operations
+# TEST	sdb001	Tests mixing db and subdb operations
 # TEST	Tests mixing db and subdb operations
 # TEST	Create a db, add data, try to create a subdb.
 # TEST	Test naming db and subdb with a leading - for correct parsing
@@ -14,7 +14,7 @@
 # TEST	Test non-subdb and subdb operations
 # TEST	Test naming (filenames begin with -)
 # TEST	Test existence (cannot create subdb of same name with -excl)
-proc subdb001 { method args } {
+proc sdb001 { method args } {
 	source ./include.tcl
 	global errorInfo
 
@@ -53,7 +53,6 @@ proc subdb001 { method args } {
 
 	set pflags ""
 	set gflags ""
-	set txn ""
 	set count 0
 
 	if { [is_record_based $method] == 1 } {
@@ -69,7 +68,7 @@ proc subdb001 { method args } {
 			set key $str
 		}
 		set ret [eval \
-		    {$db put} $txn $pflags {$key [chop_data $method $str]}]
+		    {$db put} $pflags {$key [chop_data $method $str]}]
 		error_check_good put $ret 0
 
 		set ret [eval {$db get} $gflags {$key}]
@@ -132,16 +131,8 @@ proc subdb001 { method args } {
 	# Create 1 db with 1 subdb.  Try to create another subdb of
 	# the same name.  Should fail.
 	#
-	puts "\tSubdb001.c: Truncate check"
-	set testfile $testdir/subdb001c.db
-	set subdb subdb
-	set stat [catch {eval {berkdb_open_noerr -create -truncate -mode 0644} \
-	    $args {$omethod $testfile $subdb}} ret]
-	error_check_bad dbopen $stat 0
-	error_check_good trunc [is_substr $ret \
-	    "illegal with multiple databases"] 1
 
-	puts "\tSubdb001.d: Existence check"
+	puts "\tSubdb001.c: Existence check"
 	set testfile $testdir/subdb001d.db
 	set subdb subdb
 	set ret [catch {eval {berkdb_open -create -excl -mode 0644} $args \
diff --git a/storage/bdb/test/sdb002.tcl b/storage/bdb/test/sdb002.tcl
index 4757e12afc78c03075c948434d8f2c1b9342cc9b..d951d7163104bea3e24429c885229b416111f40e 100644
--- a/storage/bdb/test/sdb002.tcl
+++ b/storage/bdb/test/sdb002.tcl
@@ -1,11 +1,11 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: sdb002.tcl,v 11.35 2002/08/23 18:01:53 sandstro Exp $
+# $Id: sdb002.tcl,v 11.41 2004/04/05 17:49:26 carol Exp $
 #
-# TEST	subdb002
+# TEST	sdb002
 # TEST	Tests basic subdb functionality
 # TEST		Small keys, small data
 # TEST		Put/get per key
@@ -18,8 +18,9 @@
 # TEST	After all are entered, retrieve all; compare output to original.
 # TEST	Close file, reopen, do retrieve and re-verify.
 # TEST	Then repeat using an environment.
-proc subdb002 { method {nentries 10000} args } {
+proc sdb002 { method {nentries 10000} args } {
 	global passwd
+	global has_crypto
 
 	set eindex [lsearch -exact $args "-env"]
 	if { $eindex != -1 } {
@@ -33,6 +34,12 @@ proc subdb002 { method {nentries 10000} args } {
 	subdb002_main $method $nentries $largs
 	append largs " -chksum "
 	subdb002_main $method $nentries $largs
+
+	# Skip remainder of test if release does not support encryption.
+	if { $has_crypto == 0 } {
+		return
+	}
+
 	append largs "-encryptaes $passwd "
 	subdb002_main $method $nentries $largs
 }
@@ -50,7 +57,7 @@ proc subdb002_main { method nentries largs } {
 	set testfile $testdir/subdb002.db
 	subdb002_body $method $omethod $nentries $largs $testfile NULL
 
-	# Run convert_encrypt so that old_encrypt will be reset to 
+	# Run convert_encrypt so that old_encrypt will be reset to
 	# the proper value and cleanup will work.
 	convert_encrypt $largs
 	set encargs ""
@@ -63,7 +70,7 @@ proc subdb002_main { method nentries largs } {
 		set sdb002_env berkdb_env
 	}
 	set env [eval {$sdb002_env -create -cachesize {0 10000000 0} \
-	    -mode 0644 -txn} -home $testdir $encargs]
+	    -mode 0644} -home $testdir $encargs]
 	error_check_good env_open [is_valid_env $env] TRUE
 	puts "Subdb002: $method ($largs) basic subdb tests in an environment"
 
@@ -115,7 +122,6 @@ proc subdb002_body { method omethod nentries largs testfile env } {
 
 	set pflags ""
 	set gflags ""
-	set txn ""
 	set count 0
 
 	if { [is_record_based $method] == 1 } {
@@ -136,7 +142,7 @@ proc subdb002_body { method omethod nentries largs testfile env } {
 			set key $str
 		}
 		set ret [eval \
-		    {$db put} $txn $pflags {$key [chop_data $method $str]}]
+		    {$db put} $pflags {$key [chop_data $method $str]}]
 		error_check_good put $ret 0
 
 		set ret [eval {$db get} $gflags {$key}]
@@ -148,6 +154,7 @@ proc subdb002_body { method omethod nentries largs testfile env } {
 	# Now we will get each key from the DB and compare the results
 	# to the original.
 	puts "\tSubdb002.b: dump file"
+	set txn ""
 	dump_file $db $txn $t1 $checkfunc
 	error_check_good db_close [$db close] 0
 
diff --git a/storage/bdb/test/sdb003.tcl b/storage/bdb/test/sdb003.tcl
index 5d1536d8c84201e54031e0d1bd6042e811377a40..c652a76d63f06be6f5c4dd93059fd76609e53cdb 100644
--- a/storage/bdb/test/sdb003.tcl
+++ b/storage/bdb/test/sdb003.tcl
@@ -1,20 +1,20 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: sdb003.tcl,v 11.24 2002/06/10 15:39:37 sue Exp $
+# $Id: sdb003.tcl,v 11.29 2004/01/28 03:36:29 bostic Exp $
 #
-# TEST	subdb003
+# TEST	sdb003
 # TEST	Tests many subdbs
 # TEST		Creates many subdbs and puts a small amount of
-# TEST		data in each (many defaults to 2000)
+# TEST		data in each (many defaults to 1000)
 # TEST
-# TEST	Use the first 10,000 entries from the dictionary as subdbnames.
+# TEST	Use the first 1000 entries from the dictionary as subdbnames.
 # TEST	Insert each with entry as name of subdatabase and a partial list
 # TEST	as key/data.  After all are entered, retrieve all; compare output
 # TEST	to original.  Close file, reopen, do retrieve and re-verify.
-proc subdb003 { method {nentries 1000} args } {
+proc sdb003 { method {nentries 1000} args } {
 	source ./include.tcl
 
 	set args [convert_args $method $args]
@@ -70,6 +70,9 @@ proc subdb003 { method {nentries 1000} args } {
 	set ndataent 10
 	set fdid [open $dict]
 	while { [gets $fdid str] != -1 && $fcount < $nentries } {
+		if { $str == "" } {
+			continue
+		}
 		set subdb $str
 		set db [eval {berkdb_open -create -mode 0644} \
 		    $args {$omethod $testfile $subdb}]
diff --git a/storage/bdb/test/sdb004.tcl b/storage/bdb/test/sdb004.tcl
index d3d95f1fde0e14472934b67a1c38366dfbf3f7f0..273bda9bf4b69fb6936d47e3705e3dfce184f76c 100644
--- a/storage/bdb/test/sdb004.tcl
+++ b/storage/bdb/test/sdb004.tcl
@@ -1,11 +1,11 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: sdb004.tcl,v 11.22 2002/07/11 18:53:45 sandstro Exp $
+# $Id: sdb004.tcl,v 11.25 2004/01/28 03:36:29 bostic Exp $
 #
-# TEST	subdb004
+# TEST	sdb004
 # TEST	Tests large subdb names
 # TEST		subdb name = filecontents,
 # TEST		key = filename, data = filecontents
@@ -18,7 +18,7 @@
 # TEST	the key with their contents as data.  After all are entered, retrieve
 # TEST	all; compare output to original. Close file, reopen, do retrieve and
 # TEST	re-verify.
-proc subdb004 { method args} {
+proc sdb004 { method args} {
 	global names
 	source ./include.tcl
 
diff --git a/storage/bdb/test/sdb005.tcl b/storage/bdb/test/sdb005.tcl
index 98cea5b348baf24ab52819dd411cf130a0796998..7173bef009ccae29166301c4c31f9010cc873537 100644
--- a/storage/bdb/test/sdb005.tcl
+++ b/storage/bdb/test/sdb005.tcl
@@ -1,11 +1,11 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: sdb005.tcl,v 11.18 2002/07/11 18:53:46 sandstro Exp $
+# $Id: sdb005.tcl,v 11.21 2004/01/28 03:36:29 bostic Exp $
 #
-# TEST	subdb005
+# TEST	sdb005
 # TEST	Tests cursor operations in subdbs
 # TEST		Put/get per key
 # TEST		Verify cursor operations work within subdb
@@ -13,7 +13,7 @@
 # TEST
 #
 # We should test this on all btrees, all hash, and a combination thereof
-proc subdb005 {method {nentries 100} args } {
+proc sdb005 {method {nentries 100} args } {
 	source ./include.tcl
 
 	set args [convert_args $method $args]
diff --git a/storage/bdb/test/sdb006.tcl b/storage/bdb/test/sdb006.tcl
index fd6066b08d6e4a7a4a0e82c9b7f5809014691a88..ffe3e47007486bf8c343e49afe74f101a159fa14 100644
--- a/storage/bdb/test/sdb006.tcl
+++ b/storage/bdb/test/sdb006.tcl
@@ -1,11 +1,11 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: sdb006.tcl,v 11.20 2002/06/20 19:01:02 sue Exp $
+# $Id: sdb006.tcl,v 11.23 2004/01/28 03:36:29 bostic Exp $
 #
-# TEST	subdb006
+# TEST	sdb006
 # TEST	Tests intra-subdb join
 # TEST
 # TEST	We'll test 2-way, 3-way, and 4-way joins and figure that if those work,
@@ -17,7 +17,7 @@
 # TEST	All of these are within a single database.
 #
 # We should test this on all btrees, all hash, and a combination thereof
-proc subdb006 {method {nentries 100} args } {
+proc sdb006 {method {nentries 100} args } {
 	source ./include.tcl
 	global rand_init
 
diff --git a/storage/bdb/test/sdb007.tcl b/storage/bdb/test/sdb007.tcl
index 0f9488a92a1edd7b1d53a650e7eed52bfcd2a42f..86f46599296ebbd46dc159be5f81c99cf1a1b9bc 100644
--- a/storage/bdb/test/sdb007.tcl
+++ b/storage/bdb/test/sdb007.tcl
@@ -1,11 +1,11 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: sdb007.tcl,v 11.20 2002/07/11 18:53:46 sandstro Exp $
+# $Id: sdb007.tcl,v 11.25 2004/09/22 18:01:06 bostic Exp $
 #
-# TEST	subdb007
+# TEST	sdb007
 # TEST	Tests page size difference errors between subdbs.
 # TEST  Test 3 different scenarios for page sizes.
 # TEST 	1.  Create/open with a default page size, 2nd subdb create with
@@ -15,8 +15,9 @@
 # TEST  3.  Create/open with specified page size, 2nd subdb create with
 # TEST      same specified size, should succeed.
 # TEST  (4th combo of using all defaults is a basic test, done elsewhere)
-proc subdb007 { method args } {
+proc sdb007 { method args } {
 	source ./include.tcl
+	global is_envmethod
 
 	set db2args [convert_args -btree $args]
 	set args [convert_args $method $args]
@@ -88,8 +89,14 @@ proc subdb007 { method args } {
 	set stat [catch {eval {berkdb_open_noerr -create -btree} \
 	    $db2args {-pagesize $pgsz2 $testfile $sub2}} ret]
 	error_check_good subdb:pgsz $stat 1
-	error_check_good subdb:fail [is_substr $ret \
-	    "Different pagesize specified"] 1
+	# We'll get a different error if running in an env,
+	# because the env won't have been opened with noerr.
+	# Skip the test for what the error is, just getting the
+	# error is enough.
+	if { $is_envmethod == 0 } {
+		error_check_good subdb:fail [is_substr $ret \
+		    "Different pagesize specified"] 1
+	}
 
 	set ret [eval {berkdb dbremove} $envargs {$testfile}]
 
@@ -112,8 +119,10 @@ proc subdb007 { method args } {
 	set stat [catch {eval {berkdb_open_noerr -create -btree} \
 	    $db2args {-pagesize $pgsz $testfile $sub2}} ret]
 	error_check_good subdb:pgsz $stat 1
-	error_check_good subdb:fail [is_substr $ret \
-	    "Different pagesize specified"] 1
+	if { $is_envmethod == 0 } {
+		error_check_good subdb:fail [is_substr $ret \
+		    "Different pagesize specified"] 1
+	}
 
 	set ret [eval {berkdb dbremove} $envargs {$testfile}]
 
diff --git a/storage/bdb/test/sdb008.tcl b/storage/bdb/test/sdb008.tcl
index 1c46aed20872d391cac7777dfadce9e13a5c8bfe..3beb8313b67062bc34780678cee8b935b83112a9 100644
--- a/storage/bdb/test/sdb008.tcl
+++ b/storage/bdb/test/sdb008.tcl
@@ -1,23 +1,16 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: sdb008.tcl,v 11.25 2002/07/11 18:53:46 sandstro Exp $
-# TEST	subdb008
-# TEST	Tests lorder difference errors between subdbs.
-# TEST  Test 3 different scenarios for lorder.
-# TEST  1.  Create/open with specific lorder, 2nd subdb create with
-# TEST      different one, should error.
-# TEST 	2.  Create/open with a default lorder 2nd subdb create with
-# TEST      specified different one, should error.
-# TEST  3.  Create/open with specified lorder, 2nd subdb create with
-# TEST      same specified lorder, should succeed.
-# TEST  (4th combo of using all defaults is a basic test, done elsewhere)
-proc subdb008 { method args } {
+# $Id: sdb008.tcl,v 11.31 2004/01/28 03:36:29 bostic Exp $
+#
+# TEST	sdb008
+# TEST	Tests explicit setting of lorders for subdatabases -- the
+# TEST	lorder should be ignored.
+proc sdb008 { method args } {
 	source ./include.tcl
 
-	set db2args [convert_args -btree $args]
 	set args [convert_args $method $args]
 	set omethod [convert_method $method]
 
@@ -25,97 +18,77 @@ proc subdb008 { method args } {
 		puts "Subdb008: skipping for method $method"
 		return
 	}
-	set txnenv 0
-	set envargs ""
 	set eindex [lsearch -exact $args "-env"]
-	#
+
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/subdb008.db
+		set testfile1 $testdir/subdb008a.db
+		set testfile2 $testdir/subdb008b.db
 		set env NULL
 	} else {
-		set testfile subdb008.db
+		set testfile1 subdb008a.db
+		set testfile2 subdb008b.db
 		incr eindex
 		set env [lindex $args $eindex]
-		set envargs "-env $env"
 		set txnenv [is_txnenv $env]
 		if { $txnenv == 1 } {
 			append args " -auto_commit "
-			append db2args " -auto_commit "
-			append envargs " -auto_commit "
 		}
 		set testdir [get_home $env]
 	}
-	puts "Subdb008: $method ($args) subdb tests with different lorders"
-
-	set sub1 "sub1"
-	set sub2 "sub2"
 	cleanup $testdir $env
 
-	puts "\tSubdb008.b.0: create subdb with specified lorder"
+	puts "Subdb008: $method ($args) subdb tests with different lorders"
+
+	puts "\tSubdb008.a.0: create subdb with system default lorder"
+	set lorder "1234"
+	if { [big_endian] } {
+		set lorder "4321"
+	}
 	set db [eval {berkdb_open -create -mode 0644} \
-	    $args {-lorder 4321 $omethod $testfile $sub1}]
+	    $args {$omethod $testfile1 "sub1"}]
 	error_check_good subdb [is_valid_db $db] TRUE
-	# Figure out what the default lorder is so that we can
-	# guarantee we create it with a different value later.
-	set is_swap [$db is_byteswapped]
-	if { $is_swap } {
-		set other 4321
-	} else {
- 		set other 1234
-	}
 	error_check_good dbclose [$db close] 0
 
-	puts "\tSubdb008.b.1: create 2nd subdb with different lorder"
-	set stat [catch {eval {berkdb_open_noerr -create $omethod} \
-	    $args {-lorder 1234 $testfile $sub2}} ret]
-	error_check_good subdb:lorder $stat 1
-	error_check_good subdb:fail [is_substr $ret \
-	    "Different lorder specified"] 1
-
-	set ret [eval {berkdb dbremove} $envargs {$testfile}]
-
-	puts "\tSubdb008.c.0: create subdb with opposite specified lorder"
+	# Explicitly try to create subdb's of each byte order.  In both
+	# cases the subdb should be forced to the byte order of the
+	# parent database.
+	puts "\tSubdb008.a.1: Try to create subdb with -1234 lorder"
 	set db [eval {berkdb_open -create -mode 0644} \
-	    $args {-lorder 1234 $omethod $testfile $sub1}]
+	    $args {-lorder 1234 $omethod $testfile1 "sub2"}]
+	error_check_good lorder_1234 [eval $db get_lorder] $lorder
 	error_check_good subdb [is_valid_db $db] TRUE
 	error_check_good dbclose [$db close] 0
 
-	puts "\tSubdb008.c.1: create 2nd subdb with different lorder"
-	set stat [catch {eval {berkdb_open_noerr -create $omethod} \
-	    $args {-lorder 4321 $testfile $sub2}} ret]
-	error_check_good subdb:lorder $stat 1
-	error_check_good subdb:fail [is_substr $ret \
-	    "Different lorder specified"] 1
-
-	set ret [eval {berkdb dbremove} $envargs {$testfile}]
-
-	puts "\tSubdb008.d.0: create subdb with default lorder"
+	puts "\tSubdb008.a.2: Try to create subdb with -4321 lorder"
 	set db [eval {berkdb_open -create -mode 0644} \
-	    $args {$omethod $testfile $sub1}]
+	    $args {-lorder 4321 $omethod $testfile1 "sub3"}]
+	error_check_good lorder_4321 [eval $db get_lorder] $lorder
 	error_check_good subdb [is_valid_db $db] TRUE
 	error_check_good dbclose [$db close] 0
 
-	puts "\tSubdb008.d.1: create 2nd subdb with different lorder"
-	set stat [catch {eval {berkdb_open_noerr -create -btree} \
-	    $db2args {-lorder $other $testfile $sub2}} ret]
-	error_check_good subdb:lorder $stat 1
-	error_check_good subdb:fail [is_substr $ret \
-	    "Different lorder specified"] 1
-
-	set ret [eval {berkdb dbremove} $envargs {$testfile}]
-
-	puts "\tSubdb008.e.0: create subdb with specified lorder"
+	puts "\tSubdb008.b.0: create subdb with non-default lorder"
+	set reverse_lorder "4321"
+	if { [big_endian] } {
+		set reverse_lorder "1234"
+	}
 	set db [eval {berkdb_open -create -mode 0644} \
-	    $args {-lorder $other $omethod $testfile $sub1}]
+	    {-lorder $reverse_lorder} $args {$omethod $testfile2 "sub1"}]
 	error_check_good subdb [is_valid_db $db] TRUE
 	error_check_good dbclose [$db close] 0
 
-	puts "\tSubdb008.e.1: create 2nd subdb with same specified lorder"
+	puts "\tSubdb008.b.1: Try to create subdb with -1234 lorder"
 	set db [eval {berkdb_open -create -mode 0644} \
-	    $args {-lorder $other $omethod $testfile $sub2}]
+	    $args {-lorder 1234 $omethod $testfile2 "sub2"}]
+	error_check_good lorder_1234 [eval $db get_lorder] $reverse_lorder
 	error_check_good subdb [is_valid_db $db] TRUE
 	error_check_good dbclose [$db close] 0
 
+	puts "\tSubdb008.b.2: Try to create subdb with -4321 lorder"
+	set db [eval {berkdb_open -create -mode 0644} \
+	    $args {-lorder 4321 $omethod $testfile2 "sub3"}]
+	error_check_good lorder_4321 [eval $db get_lorder] $reverse_lorder
+	error_check_good subdb [is_valid_db $db] TRUE
+	error_check_good dbclose [$db close] 0
 }
diff --git a/storage/bdb/test/sdb009.tcl b/storage/bdb/test/sdb009.tcl
index 4e4869643ef97965616fce011f2ec6502fa080ea..3f36a27d7816405b6562bf97917e130f1e3df3df 100644
--- a/storage/bdb/test/sdb009.tcl
+++ b/storage/bdb/test/sdb009.tcl
@@ -1,13 +1,13 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2000-2002
+# Copyright (c) 2000-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: sdb009.tcl,v 11.9 2002/07/11 18:53:46 sandstro Exp $
+# $Id: sdb009.tcl,v 11.12 2004/01/28 03:36:29 bostic Exp $
 #
-# TEST	subdb009
+# TEST	sdb009
 # TEST	Test DB->rename() method for subdbs
-proc subdb009 { method args } {
+proc sdb009 { method args } {
 	global errorCode
 	source ./include.tcl
 
diff --git a/storage/bdb/test/sdb010.tcl b/storage/bdb/test/sdb010.tcl
index 51f25976c56efa33e19c5c71131189127a316028..8f1d6f8a17150acdcadba9be8e87af1a3721bf0f 100644
--- a/storage/bdb/test/sdb010.tcl
+++ b/storage/bdb/test/sdb010.tcl
@@ -1,13 +1,13 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2000-2002
+# Copyright (c) 2000-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: sdb010.tcl,v 11.14 2002/07/11 18:53:47 sandstro Exp $
+# $Id: sdb010.tcl,v 11.19 2004/10/18 17:34:17 carol Exp $
 #
-# TEST	subdb010
+# TEST	sdb010
 # TEST	Test DB->remove() method and DB->truncate() for subdbs
-proc subdb010 { method args } {
+proc sdb010 { method args } {
 	global errorCode
 	source ./include.tcl
 
@@ -25,25 +25,24 @@ proc subdb010 { method args } {
 	set envargs ""
 	set eindex [lsearch -exact $args "-env"]
 	#
-	# If we are using an env, then testfile should just be the db name.
-	# Otherwise it is the test directory and the name.
+	# If we are not given an env, create one.
 	if { $eindex == -1 } {
-		set testfile $testdir/subdb010.db
-		set tfpath $testfile
-		set env NULL
+		set env [berkdb_env -create -home $testdir -mode 0644] 
+		error_check_good env_open [is_valid_env $env] TRUE
 	} else {
-		set testfile subdb010.db
 		incr eindex
 		set env [lindex $args $eindex]
-		set envargs " -env $env "
-		set txnenv [is_txnenv $env]
-		if { $txnenv == 1 } {
-			append args " -auto_commit "
-			append envargs " -auto_commit "
-		}
-		set testdir [get_home $env]
-		set tfpath $testdir/$testfile
 	}
+	set testfile subdb010.db
+	set envargs " -env $env "
+	set txnenv [is_txnenv $env]
+	if { $txnenv == 1 } {
+		append args " -auto_commit "
+		append envargs " -auto_commit "
+	}
+	set testdir [get_home $env]
+	set tfpath $testdir/$testfile
+
 	cleanup $testdir $env
 
 	set txn ""
@@ -51,7 +50,7 @@ proc subdb010 { method args } {
 	set testdb2 DATABASE2
 
 	set db [eval {berkdb_open -create -mode 0644} $omethod \
-	    $args $testfile $testdb]
+	    $args $envargs $testfile $testdb]
 	error_check_good db_open [is_valid_db $db] TRUE
 	error_check_good db_close [$db close] 0
 
@@ -64,7 +63,8 @@ proc subdb010 { method args } {
 	error_check_good file_exists_after [file exists $tfpath] 1
 
 	# But database should not.
-	set ret [catch {eval berkdb_open $omethod $args $testfile $testdb} res]
+	set ret [catch {eval berkdb_open $omethod \
+	    $args $envargs $testfile $testdb} res]
 	error_check_bad open_failed ret 0
 	error_check_good open_failed_ret [is_substr $errorCode ENOENT] 1
 
@@ -77,7 +77,7 @@ proc subdb010 { method args } {
 	set data2 [pad_data $method data2]
 
 	set db [eval {berkdb_open -create -mode 0644} $omethod \
-	    $args {$testfile $testdb}]
+	    $args $envargs {$testfile $testdb}]
 	error_check_good db_open [is_valid_db $db] TRUE
 	if { $txnenv == 1 } {
 		set t [$env txn]
@@ -90,7 +90,7 @@ proc subdb010 { method args } {
 	}
 
 	set db2 [eval {berkdb_open -create -mode 0644} $omethod \
-	    $args $testfile $testdb2]
+	    $args $envargs $testfile $testdb2]
 	error_check_good db_open [is_valid_db $db2] TRUE
 	if { $txnenv == 1 } {
 		set t [$env txn]
@@ -110,7 +110,7 @@ proc subdb010 { method args } {
 	# Return value should be 1, the count of how many items were
 	# destroyed when we truncated.
 	set db [eval {berkdb_open -create -mode 0644} $omethod \
-	    $args $testfile $testdb]
+	    $args $envargs $testfile $testdb]
 	error_check_good db_open [is_valid_db $db] TRUE
 	if { $txnenv == 1 } {
 		set t [$env txn]
@@ -124,7 +124,7 @@ proc subdb010 { method args } {
 	error_check_good db_close [$db close] 0
 
 	puts "\tSubdb010.d: check"
-	set db [eval {berkdb_open} $args {$testfile $testdb}]
+	set db [eval {berkdb_open} $args $envargs {$testfile $testdb}]
 	error_check_good db_open [is_valid_db $db] TRUE
 	if { $txnenv == 1 } {
 		set t [$env txn]
@@ -140,7 +140,7 @@ proc subdb010 { method args } {
 		error_check_good txn [$t commit] 0
 	}
 
-	set db2 [eval {berkdb_open} $args {$testfile $testdb2}]
+	set db2 [eval {berkdb_open} $args $envargs {$testfile $testdb2}]
 	error_check_good db_open [is_valid_db $db2] TRUE
 	if { $txnenv == 1 } {
 		set t [$env txn]
@@ -162,5 +162,9 @@ proc subdb010 { method args } {
 
 	error_check_good db_close [$db close] 0
 	error_check_good db_close [$db2 close] 0
-	puts "\tSubdb010 succeeded."
+
+	# If we created our env, close it.
+	if { $eindex == -1 } {
+		error_check_good env_close [$env close] 0
+	}
 }
diff --git a/storage/bdb/test/sdb011.tcl b/storage/bdb/test/sdb011.tcl
index 862e32f73ed51702eb9e7246783d8653f7d0244c..d36b83e5df2ab50d0cf0e95e4c2bcff37aba2902 100644
--- a/storage/bdb/test/sdb011.tcl
+++ b/storage/bdb/test/sdb011.tcl
@@ -1,17 +1,19 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: sdb011.tcl,v 11.9 2002/07/11 18:53:47 sandstro Exp $
+# $Id: sdb011.tcl,v 11.14 2004/01/28 03:36:29 bostic Exp $
 #
-# TEST	subdb011
+# TEST	sdb011
 # TEST	Test deleting Subdbs with overflow pages
 # TEST	Create 1 db with many large subdbs.
 # TEST	Test subdatabases with overflow pages.
-proc subdb011 { method {ndups 13} {nsubdbs 10} args} {
+proc sdb011 { method {ndups 13} {nsubdbs 10} args} {
 	global names
 	source ./include.tcl
+	global rand_init
+	error_check_good set_random_seed [berkdb srand $rand_init] 0
 
 	set args [convert_args $method $args]
 	set omethod [convert_method $method]
@@ -56,10 +58,6 @@ proc subdb011 { method {ndups 13} {nsubdbs 10} args} {
 
 	# Here is the loop where we put and get each key/data pair
 	set file_list [get_file_list]
-	if { $max_files != 0 && [llength $file_list] > $max_files } {
-		set fend [expr $max_files - 1]
-		set file_list [lrange $file_list 0 $fend]
-	}
 	set flen [llength $file_list]
 	puts "Subdb011: $method ($args) $ndups overflow dups with \
 	    $flen filename=key filecontents=data pairs"
diff --git a/storage/bdb/test/sdb012.tcl b/storage/bdb/test/sdb012.tcl
index 9c05d977daf178014602ee153ab6e7ca39fb014f..d316acb711191d943c917e1f01a473ee8f28356e 100644
--- a/storage/bdb/test/sdb012.tcl
+++ b/storage/bdb/test/sdb012.tcl
@@ -1,16 +1,16 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: sdb012.tcl,v 1.3 2002/08/08 15:38:10 bostic Exp $
+# $Id: sdb012.tcl,v 1.6 2004/01/28 03:36:29 bostic Exp $
 #
-# TEST	subdb012
+# TEST	sdb012
 # TEST	Test subdbs with locking and transactions
 # TEST  Tests creating and removing subdbs while handles
 # TEST  are open works correctly, and in the face of txns.
 #
-proc subdb012 { method args } {
+proc sdb012 { method args } {
 	source ./include.tcl
 
 	set args [convert_args $method $args]
diff --git a/storage/bdb/test/sdbscript.tcl b/storage/bdb/test/sdbscript.tcl
index d1978ccb0482e7723866e6927902803d16a12ddc..645351b077e712003db98ba01b171170a64ddc39 100644
--- a/storage/bdb/test/sdbscript.tcl
+++ b/storage/bdb/test/sdbscript.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: sdbscript.tcl,v 11.9 2002/01/11 15:53:36 bostic Exp $
+# $Id: sdbscript.tcl,v 11.11 2004/01/28 03:36:29 bostic Exp $
 #
 # Usage: subdbscript testfile subdbnumber factor
 # testfile: name of DB itself
diff --git a/storage/bdb/test/sdbtest001.tcl b/storage/bdb/test/sdbtest001.tcl
index b8b4508c2a47009ecb045cb97bd5e46069bb8dc9..65b64dac2d380bef9aeeaf931870e980128944f0 100644
--- a/storage/bdb/test/sdbtest001.tcl
+++ b/storage/bdb/test/sdbtest001.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: sdbtest001.tcl,v 11.19 2002/05/22 15:42:42 sue Exp $
+# $Id: sdbtest001.tcl,v 11.21 2004/01/28 03:36:29 bostic Exp $
 #
 # TEST	sdbtest001
 # TEST	Tests multiple access methods in one subdb
diff --git a/storage/bdb/test/sdbtest002.tcl b/storage/bdb/test/sdbtest002.tcl
index 95717413a7be796cebed67eaec5e83cc3b6ef807..4e51809fbb5e8bbb22bce38a1aeb20432c9ab5da 100644
--- a/storage/bdb/test/sdbtest002.tcl
+++ b/storage/bdb/test/sdbtest002.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: sdbtest002.tcl,v 11.26 2002/09/05 17:23:07 sandstro Exp $
+# $Id: sdbtest002.tcl,v 11.29 2004/01/28 03:36:30 bostic Exp $
 #
 # TEST	sdbtest002
 # TEST	Tests multiple access methods in one subdb access by multiple
@@ -43,8 +43,7 @@ proc sdbtest002 { {nentries 10000} } {
 	set methods \
 	    [list "-rbtree" "-recno" "-btree" "-btree" "-recno" "-rbtree"]
 	cleanup $testdir NULL
-	puts "\tSubdbtest002.a: create subdbs of different access methods:"
-	puts "\t\t$methods"
+	puts "\tSubdbtest002.a: create subdbs of different methods: $methods"
 	set psize 4096
 	set nsubdbs [llength $methods]
 	set duplist ""
diff --git a/storage/bdb/test/sdbutils.tcl b/storage/bdb/test/sdbutils.tcl
index 3221a422e18b14cd0a93a630c4834060c0d45fbe..5c6deb3b47be48207def9e56117de897465e587b 100644
--- a/storage/bdb/test/sdbutils.tcl
+++ b/storage/bdb/test/sdbutils.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: sdbutils.tcl,v 11.14 2002/06/10 15:39:39 sue Exp $
+# $Id: sdbutils.tcl,v 11.16 2004/01/28 03:36:30 bostic Exp $
 #
 proc build_all_subdb { dbname methods psize dups {nentries 100} {dbargs ""}} {
 	set nsubdbs [llength $dups]
diff --git a/storage/bdb/test/sec001.tcl b/storage/bdb/test/sec001.tcl
index eb4bcc24dd2282d308d9ebca74f3d59b78e43375..ed2ca81f9d4a2fd833471de23274aa4d3ddefdb1 100644
--- a/storage/bdb/test/sec001.tcl
+++ b/storage/bdb/test/sec001.tcl
@@ -1,17 +1,24 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2001
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: sec001.tcl,v 11.7 2002/05/31 16:19:30 sue Exp $
+# $Id: sec001.tcl,v 11.12 2004/09/22 18:01:06 bostic Exp $
 #
 # TEST	sec001
 # TEST	Test of security interface
 proc sec001 { } {
 	global errorInfo
 	global errorCode
+	global has_crypto
+	global is_hp_test
 
 	source ./include.tcl
+	# Skip test if release does not support encryption.
+	if { $has_crypto == 0 } {
+		puts "Skipping test sec001 for non-crypto release."
+		return
+	}
 
 	set testfile1 env1.db
 	set testfile2 $testdir/env2.db
@@ -117,12 +124,16 @@ proc sec001 { } {
 	set env [berkdb_env -create -home $testdir]
 	error_check_good env [is_valid_env $env] TRUE
 
-	puts "\tSec001.f.4: Open again with encryption."
-	set stat [catch {berkdb_env_noerr -home $testdir \
-	    -encryptaes $passwd1} ret]
-	error_check_good env:unencrypted $stat 1
-	error_check_good env:fail [is_substr $ret \
-	    "Joining non-encrypted environment"] 1
+	# Skip this piece of the test on HP-UX, where we can't
+	# join the env.
+	if { $is_hp_test != 1 } {
+		puts "\tSec001.f.4: Open again with encryption."
+		set stat [catch {berkdb_env_noerr -home $testdir \
+		    -encryptaes $passwd1} ret]
+		error_check_good env:unencrypted $stat 1
+		error_check_good env:fail [is_substr $ret \
+		    "Joining non-encrypted environment"] 1
+	}
 
 	error_check_good envclose [$env close] 0
 
@@ -138,6 +149,13 @@ proc sec001 { } {
 	set env [berkdb_env_noerr -create -home $testdir -encryptaes $passwd1]
 	error_check_good env [is_valid_env $env] TRUE
 
+	# We can't open an env twice in HP-UX, so skip the rest.
+	if { $is_hp_test == 1 } {
+		puts "Skipping remainder of test for HP-UX."
+		error_check_good env_close [$env close] 0
+		return
+	}
+
 	puts "\tSec001.g.2: Open again with encryption - same passwd."
 	set env1 [berkdb_env -home $testdir -encryptaes $passwd1]
 	error_check_good env [is_valid_env $env1] TRUE
diff --git a/storage/bdb/test/sec002.tcl b/storage/bdb/test/sec002.tcl
index d790162f1d7219a61a010888278c56efc5dcf477..5bdd4af3bcc063b9b1560f720e2e33fb4a24340a 100644
--- a/storage/bdb/test/sec002.tcl
+++ b/storage/bdb/test/sec002.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2001
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: sec002.tcl,v 11.3 2002/04/24 19:04:59 bostic Exp $
+# $Id: sec002.tcl,v 11.13 2004/11/02 16:12:04 carol Exp $
 #
 # TEST	sec002
 # TEST	Test of security interface and catching errors in the
@@ -11,9 +11,16 @@
 proc sec002 { } {
 	global errorInfo
 	global errorCode
+	global has_crypto
 
 	source ./include.tcl
 
+	# Skip test if release does not support encryption.
+	if { $has_crypto == 0 } {
+		puts "Skipping test sec002 for non-crypto release."
+		return
+	}
+
 	set testfile1 $testdir/sec002-1.db
 	set testfile2 $testdir/sec002-2.db
 	set testfile3 $testdir/sec002-3.db
@@ -56,6 +63,27 @@ proc sec002 { } {
 	error_check_good dbput [$db put $key $data] 0
 	error_check_good dbclose [$db close] 0
 
+	#
+	# If we reopen the normal file with the -chksum flag, there
+	# should be no error and checksumming should be ignored.
+	# If we reopen a checksummed file without the -chksum flag,
+	# checksumming should still be in effect.  [#6959]
+	#
+	puts "\tSec002.b: Inheritance of chksum properties"
+	puts "\t\tSec002.b1: Reopen ordinary file with -chksum flag"
+	set db [eval {berkdb_open} -chksum $testfile4]
+	error_check_good open_with_chksum [is_valid_db $db] TRUE
+	set retdata [$db get $key]
+	error_check_good testfile4_get [lindex [lindex $retdata 0] 1] $data
+	error_check_good dbclose [$db close] 0
+
+	puts "\t\tSec002.b2: Reopen checksummed file without -chksum flag"
+	set db [eval {berkdb_open} $testfile3]
+	error_check_good open_wo_chksum [is_valid_db $db] TRUE
+	set retdata [$db get $key]
+	error_check_good testfile3_get [lindex [lindex $retdata 0] 1] $data
+	error_check_good dbclose [$db close] 0
+
 	#
 	# First just touch some bits in the file.  We know that in btree
 	# meta pages, bytes 92-459 are unused.  Scribble on them in both
@@ -71,7 +99,7 @@ proc sec002 { } {
 	set fid [open $testfile4 r+]
 	lappend fidlist $fid
 
-	puts "\tSec002.b: Overwrite unused space in meta-page"
+	puts "\tSec002.c: Overwrite unused space in meta-page"
 	foreach f $fidlist {
 		fconfigure $f -translation binary
 		seek $f 100 start
@@ -83,7 +111,7 @@ proc sec002 { } {
 		puts -nonewline $f $newbyte
 		close $f
 	}
-	puts "\tSec002.c: Reopen modified databases"
+	puts "\tSec002.d: Reopen modified databases"
 	set stat [catch {berkdb_open_noerr -encryptaes $passwd1 $testfile1} ret]
 	error_check_good db:$testfile1 $stat 1
 	error_check_good db:$testfile1:fail \
@@ -98,34 +126,45 @@ proc sec002 { } {
 	error_check_good db:$testfile4 $stat 0
 	error_check_good dbclose [$db close] 0
 
-	puts "\tSec002.d: Replace root page in encrypted w/ encrypted"
+	# Skip the remainder of the test for Windows platforms.
+	# Forcing the error which causes DB_RUNRECOVERY to be
+	# returned ends up leaving open files that cannot be removed.
+	if { $is_windows_test == 1 } {
+		cleanup $testdir NULL 1
+		puts "Skipping remainder of test for Windows"
+		return
+	}
+
+	puts "\tSec002.e: Replace root page in encrypted w/ encrypted"
 	set fid1 [open $testfile1 r+]
+	fconfigure $fid1 -translation binary
 	set fid2 [open $testfile2 r+]
+	fconfigure $fid2 -translation binary
 	seek $fid1 $pagesize start
 	seek $fid2 $pagesize start
-	set root1 [read $fid1 $pagesize]
+	fcopy $fid1 $fid2 -size $pagesize
 	close $fid1
-	puts -nonewline $fid2 $root1
 	close $fid2
 
 	set db [berkdb_open_noerr -encryptaes $passwd2 $testfile2]
 	error_check_good db [is_valid_db $db] TRUE
 	set stat [catch {$db get $key} ret]
 	error_check_good dbget $stat 1
-	error_check_good db:$testfile2:fail \
-	    [is_substr $ret "checksum error: catastrophic recovery required"] 1
+	error_check_good db:$testfile2:fail1 \
+	    [is_substr $ret "checksum error"] 1
 	set stat [catch {$db close} ret]
 	error_check_good dbclose $stat 1
-	error_check_good db:$testfile2:fail [is_substr $ret "DB_RUNRECOVERY"] 1
+	error_check_good db:$testfile2:fail2 [is_substr $ret "DB_RUNRECOVERY"] 1
 
-	puts "\tSec002.e: Replace root page in encrypted w/ unencrypted"
+	puts "\tSec002.f: Replace root page in encrypted w/ unencrypted"
 	set fid2 [open $testfile2 r+]
+	fconfigure $fid2 -translation binary
 	set fid4 [open $testfile4 r+]
+	fconfigure $fid4 -translation binary
 	seek $fid2 $pagesize start
 	seek $fid4 $pagesize start
-	set root4 [read $fid4 $pagesize]
+	fcopy $fid4 $fid2 -size $pagesize
 	close $fid4
-	puts -nonewline $fid2 $root4
 	close $fid2
 
 	set db [berkdb_open_noerr -encryptaes $passwd2 $testfile2]
@@ -133,11 +172,10 @@ proc sec002 { } {
 	set stat [catch {$db get $key} ret]
 	error_check_good dbget $stat 1
 	error_check_good db:$testfile2:fail \
-	    [is_substr $ret "checksum error: catastrophic recovery required"] 1
+	    [is_substr $ret "checksum error"] 1
 	set stat [catch {$db close} ret]
 	error_check_good dbclose $stat 1
 	error_check_good db:$testfile2:fail [is_substr $ret "DB_RUNRECOVERY"] 1
 
 	cleanup $testdir NULL 1
-	puts "\tSec002 complete."
 }
diff --git a/storage/bdb/test/shelltest.tcl b/storage/bdb/test/shelltest.tcl
index 6190bac1f8d34f0a59c91f402589276233bccacb..cb588f13378260e36fd86f8eb14118b49c5c1f33 100644
--- a/storage/bdb/test/shelltest.tcl
+++ b/storage/bdb/test/shelltest.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2001-2002
+# Copyright (c) 2001-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: shelltest.tcl,v 1.20 2002/04/19 15:42:20 bostic Exp $
+# $Id: shelltest.tcl,v 1.31 2004/03/15 21:09:49 bostic Exp $
 #
 # TEST	scr###
 # TEST	The scr### directories are shell scripts that test a variety of
@@ -13,9 +13,10 @@
 # shelltest.tcl:
 #	Code to run shell script tests, to incorporate Java, C++,
 #	example compilation, etc. test scripts into the Tcl framework.
-proc shelltest { { run_one 0 }} {
+proc shelltest {{ run_one 0 } { xml 0 }} {
 	source ./include.tcl
 	global shelltest_list
+	global xmlshelltest_list
 
 	set SH /bin/sh
 	if { [file executable $SH] != 1 } {
@@ -24,6 +25,10 @@ proc shelltest { { run_one 0 }} {
 		return 0
 	}
 
+	if { $xml == 1 } {
+		set shelltest_list $xmlshelltest_list
+	}
+
 	if { $run_one == 0 } {
 		puts "Running shell script tests..."
 
@@ -86,3 +91,11 @@ proc scr019 {} { shelltest 19 }
 proc scr020 {} { shelltest 20 }
 proc scr021 {} { shelltest 21 }
 proc scr022 {} { shelltest 22 }
+proc scr023 {} { shelltest 23 }
+proc scr024 {} { shelltest 24 }
+proc scr025 {} { shelltest 25 }
+proc scr026 {} { shelltest 26 }
+proc scr027 {} { shelltest 27 }
+proc scr028 {} { shelltest 28 }
+proc scr029 {} { shelltest 29 }
+proc scr030 {} { shelltest 30 }
diff --git a/storage/bdb/test/si001.tcl b/storage/bdb/test/si001.tcl
index 1a2247c5f8bfd57deae33bceffe6275680fb48dd..e5cffc0e11a9fbdd89453f77e7dd047704bcbc66 100644
--- a/storage/bdb/test/si001.tcl
+++ b/storage/bdb/test/si001.tcl
@@ -1,13 +1,21 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2001-2002
+# Copyright (c) 2001-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: si001.tcl,v 1.7 2002/04/29 17:12:02 sandstro Exp $
+# $Id: si001.tcl,v 1.18 2004/10/27 20:40:25 carol Exp $
 #
-# TEST	sindex001
+# TEST	si001
 # TEST	Basic secondary index put/delete test
-proc sindex001 { methods {nentries 200} {tnum 1} args } {
+# TEST
+# TEST  Put data in primary db and check that pget on secondary
+# TEST  index finds the right entries.  Alter the primary in the
+# TEST  following ways, checking for correct data each time:
+# TEST          Overwrite data in primary database.
+# TEST          Delete half of entries through primary.
+# TEST          Delete half of remaining entries through secondary.
+# TEST          Append data (for record-based primaries only).
+proc si001 { methods {nentries 200} {tnum "001"} args } {
 	source ./include.tcl
 	global dict nsecondaries
 
@@ -29,11 +37,11 @@ proc sindex001 { methods {nentries 200} {tnum 1} args } {
 	set argses [convert_argses $methods $args]
 	set omethods [convert_methods $methods]
 
-	puts "Sindex00$tnum ($pmethod/$methods) $nentries equal key/data pairs"
+	puts "si$tnum \{\[ list $pmethod $methods \]\} $nentries" 
 	env_cleanup $testdir
 
-	set pname "primary00$tnum.db"
-	set snamebase "secondary00$tnum"
+	set pname "primary$tnum.db"
+	set snamebase "secondary$tnum"
 
 	# Open an environment
 	# XXX if one is not supplied!
@@ -56,7 +64,9 @@ proc sindex001 { methods {nentries 200} {tnum 1} args } {
 		lappend sdbs $sdb
 	}
 
-	puts "\tSindex00$tnum.a: Put loop"
+	puts "\tSi$tnum.a: Put loop"
+	# Open dictionary and leave open until done with test .e so append
+	# won't require configuration for duplicates.
 	set did [open $dict]
 	for { set n 0 } { [gets $did str] != -1 && $n < $nentries } { incr n } {
 		if { [is_record_based $pmethod] == 1 } {
@@ -72,32 +82,32 @@ proc sindex001 { methods {nentries 200} {tnum 1} args } {
 		set ret [eval {$pdb put} {$key [chop_data $pmethod $datum]}]
 		error_check_good put($n) $ret 0
 	}
-	close $did
-	check_secondaries $pdb $sdbs $nentries keys data "Sindex00$tnum.a"
 
-	puts "\tSindex00$tnum.b: Put/overwrite loop"
+	check_secondaries $pdb $sdbs $nentries keys data "Si$tnum.a"
+
+	puts "\tSi$tnum.b: Put/overwrite loop"
 	for { set n 0 } { $n < $nentries } { incr n } {
 		set newd $data($n).$keys($n)
 		set ret [eval {$pdb put} {$keys($n) [chop_data $pmethod $newd]}]
 		error_check_good put_overwrite($n) $ret 0
 		set data($n) [pad_data $pmethod $newd]
 	}
-	check_secondaries $pdb $sdbs $nentries keys data "Sindex00$tnum.b"
+	check_secondaries $pdb $sdbs $nentries keys data "Si$tnum.b"
 
 	# Delete the second half of the entries through the primary.
 	# We do the second half so we can just pass keys(0 ... n/2)
 	# to check_secondaries.
 	set half [expr $nentries / 2]
-	puts "\tSindex00$tnum.c: Primary delete loop: deleting $half entries"
+	puts "\tSi$tnum.c: Primary delete loop: deleting $half entries"
 	for { set n $half } { $n < $nentries } { incr n } {
 		set ret [$pdb del $keys($n)]
 		error_check_good pdel($n) $ret 0
 	}
-	check_secondaries $pdb $sdbs $half keys data "Sindex00$tnum.c"
+	check_secondaries $pdb $sdbs $half keys data "Si$tnum.c"
 
 	# Delete half of what's left, through the first secondary.
 	set quar [expr $half / 2]
-	puts "\tSindex00$tnum.d: Secondary delete loop: deleting $quar entries"
+	puts "\tSi$tnum.d: Secondary delete loop: deleting $quar entries"
 	set sdb [lindex $sdbs 0]
 	set callback [callback_n 0]
 	for { set n $quar } { $n < $half } { incr n } {
@@ -105,12 +115,64 @@ proc sindex001 { methods {nentries 200} {tnum 1} args } {
 		set ret [$sdb del $skey]
 		error_check_good sdel($n) $ret 0
 	}
-	check_secondaries $pdb $sdbs $quar keys data "Sindex00$tnum.d"
+	check_secondaries $pdb $sdbs $quar keys data "Si$tnum.d"
+	set left $quar
+
+	# For queue and recno only, test append, adding back a quarter of
+	# the original number of entries.
+	if { [is_record_based $pmethod] == 1 } {
+		puts "\tSi$tnum.e: Append loop: append $quar entries"
+		for { set n $quar } { [gets $did str] != -1 && $n < $half } \
+		    { incr n } {
+			set key [expr $n + 1]
+			set datum $str
+			set keys($n) $key
+			set data($n) [pad_data $pmethod $datum]
+
+			set ret [eval {$pdb put} \
+			    {$key [chop_data $pmethod $datum]}]
+			error_check_good put($n) $ret 0
+		}
+		check_secondaries $pdb $sdbs $half keys data "Si$tnum.e"
+		set left $half
+	}
+
+	close $did
+
+	puts "\tSi$tnum.f: Truncate primary, check secondaries are empty."
+	error_check_good truncate [$pdb truncate] $left
+	foreach sdb $sdbs {
+		set scursor [$sdb cursor]
+		error_check_good db_cursor [is_substr $scursor $sdb] 1
+		set ret [$scursor get -first]
+		error_check_good sec_empty [string length $ret] 0
+		error_check_good cursor_close [$scursor close] 0
+	}
+
 
-	puts "\tSindex00$tnum.e: Closing/disassociating primary first"
+	puts "\tSi$tnum.g: Closing/disassociating primary first"
 	error_check_good primary_close [$pdb close] 0
 	foreach sdb $sdbs {
 		error_check_good secondary_close [$sdb close] 0
 	}
 	error_check_good env_close [$env close] 0
+
+	# Reopen with _noerr for test of truncate secondary.
+	puts "\tSi$tnum.h: Truncate secondary (should fail)"
+
+	set env [berkdb_env_noerr -create -home $testdir]
+	error_check_good env_open [is_valid_env $env] TRUE
+
+	set pdb [eval {berkdb_open_noerr -create -env} $env \
+	    $pomethod $pargs $pname]
+	set sdb [eval {berkdb_open_noerr -create -env} $env \
+	    [lindex $omethods 0] [lindex $argses 0] $snamebase.0.db ]
+	$pdb associate [callback_n 0] $sdb
+
+	set ret [catch {$sdb truncate} ret]
+	error_check_good trunc_secondary $ret 1
+
+	error_check_good primary_close [$pdb close] 0
+	error_check_good secondary_close [$sdb close] 0
+	error_check_good env_close [$env close] 0
 }
diff --git a/storage/bdb/test/si002.tcl b/storage/bdb/test/si002.tcl
index 46ba86e7560ba38a53cb0cb0d32d80573c15b66d..9e38c8a98e6364c30fc272ffcaca2087690010ef 100644
--- a/storage/bdb/test/si002.tcl
+++ b/storage/bdb/test/si002.tcl
@@ -1,13 +1,21 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2001-2002
+# Copyright (c) 2001-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: si002.tcl,v 1.6 2002/04/29 17:12:02 sandstro Exp $
+# $Id: si002.tcl,v 1.14 2004/10/27 20:40:25 carol Exp $
 #
-# TEST	sindex002
+# TEST	si002
 # TEST	Basic cursor-based secondary index put/delete test
-proc sindex002 { methods {nentries 200} {tnum 2} args } {
+# TEST
+# TEST  Cursor put data in primary db and check that pget
+# TEST  on secondary index finds the right entries.
+# TEST  Overwrite while walking primary, check pget again.
+# TEST      Overwrite while walking secondary (use c_pget), check
+# TEST  pget again.
+# TEST  Cursor delete half of entries through primary, check.
+# TEST  Cursor delete half of remainder through secondary, check.
+proc si002 { methods {nentries 200} {tnum "002"} args } {
 	source ./include.tcl
 	global dict nsecondaries
 
@@ -29,11 +37,11 @@ proc sindex002 { methods {nentries 200} {tnum 2} args } {
 	set argses [convert_argses $methods $args]
 	set omethods [convert_methods $methods]
 
-	puts "Sindex00$tnum ($pmethod/$methods) $nentries equal key/data pairs"
+	puts "si$tnum \{\[ list $pmethod $methods \]\} $nentries"
 	env_cleanup $testdir
 
-	set pname "primary00$tnum.db"
-	set snamebase "secondary00$tnum"
+	set pname "primary$tnum.db"
+	set snamebase "secondary$tnum"
 
 	# Open an environment
 	# XXX if one is not supplied!
@@ -56,7 +64,7 @@ proc sindex002 { methods {nentries 200} {tnum 2} args } {
 		lappend sdbs $sdb
 	}
 
-	puts "\tSindex00$tnum.a: Cursor put (-keyfirst/-keylast) loop"
+	puts "\tSi$tnum.a: Cursor put (-keyfirst/-keylast) loop"
 	set did [open $dict]
 	set pdbc [$pdb cursor]
 	error_check_good pdb_cursor [is_valid_cursor $pdbc $pdb] TRUE
@@ -84,9 +92,9 @@ proc sindex002 { methods {nentries 200} {tnum 2} args } {
 	}
 	close $did
 	error_check_good pdbc_close [$pdbc close] 0
-	check_secondaries $pdb $sdbs $nentries keys data "Sindex00$tnum.a"
+	check_secondaries $pdb $sdbs $nentries keys data "Si$tnum.a"
 
-	puts "\tSindex00$tnum.b: Cursor put overwrite (-current) loop"
+	puts "\tSi$tnum.b: Cursor put overwrite (-current) loop"
 	set pdbc [$pdb cursor]
 	error_check_good pdb_cursor [is_valid_cursor $pdbc $pdb] TRUE
 	for { set dbt [$pdbc get -first] } { [llength $dbt] > 0 } \
@@ -99,9 +107,9 @@ proc sindex002 { methods {nentries 200} {tnum 2} args } {
 		set data($ns($key)) [pad_data $pmethod $newd]
 	}
 	error_check_good pdbc_close [$pdbc close] 0
-	check_secondaries $pdb $sdbs $nentries keys data "Sindex00$tnum.b"
+	check_secondaries $pdb $sdbs $nentries keys data "Si$tnum.b"
 
-	puts "\tSindex00$tnum.c: Secondary c_pget/primary put overwrite loop"
+	puts "\tSi$tnum.c: Secondary c_pget/primary put overwrite loop"
 	# We walk the first secondary, then put-overwrite each primary key/data
 	# pair we find.  This doubles as a DBC->c_pget test.
 	set sdb [lindex $sdbs 0]
@@ -127,13 +135,13 @@ proc sindex002 { methods {nentries 200} {tnum 2} args } {
 		set data($ns($pkey)) [pad_data $pmethod $newd]
 	}
 	error_check_good sdbc_close [$sdbc close] 0
-	check_secondaries $pdb $sdbs $nentries keys data "Sindex00$tnum.c"
+	check_secondaries $pdb $sdbs $nentries keys data "Si$tnum.c"
 
 	# Delete the second half of the entries through the primary.
 	# We do the second half so we can just pass keys(0 ... n/2)
 	# to check_secondaries.
 	set half [expr $nentries / 2]
-	puts "\tSindex00$tnum.d:\
+	puts "\tSi$tnum.d:\
 	    Primary cursor delete loop: deleting $half entries"
 	set pdbc [$pdb cursor]
 	error_check_good pdb_cursor [is_valid_cursor $pdbc $pdb] TRUE
@@ -143,11 +151,11 @@ proc sindex002 { methods {nentries 200} {tnum 2} args } {
 		set dbt [$pdbc get -next]
 	}
 	error_check_good pdbc_close [$pdbc close] 0
-	cursor_check_secondaries $pdb $sdbs $half "Sindex00$tnum.d"
+	cursor_check_secondaries $pdb $sdbs $half "Si$tnum.d"
 
 	# Delete half of what's left, through the first secondary.
 	set quar [expr $half / 2]
-	puts "\tSindex00$tnum.e:\
+	puts "\tSi$tnum.e:\
 	    Secondary cursor delete loop: deleting $quar entries"
 	set sdb [lindex $sdbs 0]
 	set sdbc [$sdb cursor]
@@ -157,7 +165,7 @@ proc sindex002 { methods {nentries 200} {tnum 2} args } {
 		set dbt [$sdbc get -next]
 	}
 	error_check_good sdbc_close [$sdbc close] 0
-	cursor_check_secondaries $pdb $sdbs $quar "Sindex00$tnum.e"
+	cursor_check_secondaries $pdb $sdbs $quar "Si$tnum.e"
 
 	foreach sdb $sdbs {
 		error_check_good secondary_close [$sdb close] 0
diff --git a/storage/bdb/test/si003.tcl b/storage/bdb/test/si003.tcl
index 1cc8c884e752395c41365cd1eec9f8b0c8a28e6a..60ddba6a35fa2dbb13e57c90441b9507b3c7cefd 100644
--- a/storage/bdb/test/si003.tcl
+++ b/storage/bdb/test/si003.tcl
@@ -1,18 +1,24 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2001-2002
+# Copyright (c) 2001-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: si003.tcl,v 1.6 2002/04/29 17:12:03 sandstro Exp $
+# $Id: si003.tcl,v 1.12 2004/10/27 20:40:25 carol Exp $
 #
-# TEST	sindex003
-# TEST	sindex001 with secondaries created and closed mid-test
+# TEST	si003
+# TEST	si001 with secondaries created and closed mid-test
 # TEST	Basic secondary index put/delete test with secondaries
 # TEST	created mid-test.
-proc sindex003 { methods {nentries 200} {tnum 3} args } {
+proc si003 { methods {nentries 200} {tnum "003"} args } {
 	source ./include.tcl
 	global dict nsecondaries
 
+	# There's no reason to run this test on large lists.
+	if { $nentries > 1000 } {
+		puts "Skipping si003 for large lists (over 1000 items)"
+		return
+	}
+
 	# Primary method/args.
 	set pmethod [lindex $methods 0]
 	set pargs [convert_args $pmethod $args]
@@ -31,11 +37,11 @@ proc sindex003 { methods {nentries 200} {tnum 3} args } {
 	set argses [convert_argses $methods $args]
 	set omethods [convert_methods $methods]
 
-	puts "Sindex00$tnum ($pmethod/$methods) $nentries equal key/data pairs"
+	puts "si$tnum \{\[ list $pmethod $methods \]\} $nentries" 
 	env_cleanup $testdir
 
-	set pname "primary00$tnum.db"
-	set snamebase "secondary00$tnum"
+	set pname "primary$tnum.db"
+	set snamebase "secondary$tnum"
 
 	# Open an environment
 	# XXX if one is not supplied!
@@ -46,7 +52,7 @@ proc sindex003 { methods {nentries 200} {tnum 3} args } {
 	set pdb [eval {berkdb_open -create -env} $env $pomethod $pargs $pname]
 	error_check_good primary_open [is_valid_db $pdb] TRUE
 
-	puts -nonewline "\tSindex00$tnum.a: Put loop ... "
+	puts -nonewline "\tSi$tnum.a: Put loop ... "
 	set did [open $dict]
 	for { set n 0 } { [gets $did str] != -1 && $n < $nentries } { incr n } {
 		if { [is_record_based $pmethod] == 1 } {
@@ -76,9 +82,9 @@ proc sindex003 { methods {nentries 200} {tnum 3} args } {
 		    [$pdb associate -create [callback_n $i] $sdb] 0
 		lappend sdbs $sdb
 	}
-	check_secondaries $pdb $sdbs $nentries keys data "Sindex00$tnum.a"
+	check_secondaries $pdb $sdbs $nentries keys data "Si$tnum.a"
 
-	puts -nonewline "\tSindex00$tnum.b: Put/overwrite loop ... "
+	puts -nonewline "\tSi$tnum.b: Put/overwrite loop ... "
 	for { set n 0 } { $n < $nentries } { incr n } {
 		set newd $data($n).$keys($n)
 		set ret [eval {$pdb put} {$keys($n) [chop_data $pmethod $newd]}]
@@ -93,7 +99,7 @@ proc sindex003 { methods {nentries 200} {tnum 3} args } {
 		error_check_good second_close($sdb) [$sdb close] 0
 		set sdbs [lrange $sdbs 0 end-1]
 		check_secondaries \
-		    $pdb $sdbs $nentries keys data "Sindex00$tnum.b"
+		    $pdb $sdbs $nentries keys data "Si$tnum.b"
 	}
 
 	# Delete the second half of the entries through the primary.
@@ -101,7 +107,7 @@ proc sindex003 { methods {nentries 200} {tnum 3} args } {
 	# to check_secondaries.
 	set half [expr $nentries / 2]
 	puts -nonewline \
-	    "\tSindex00$tnum.c: Primary delete loop: deleting $half entries ..."
+	    "\tSi$tnum.c: Primary delete loop: deleting $half entries ..."
 	for { set n $half } { $n < $nentries } { incr n } {
 		set ret [$pdb del $keys($n)]
 		error_check_good pdel($n) $ret 0
@@ -120,11 +126,11 @@ proc sindex003 { methods {nentries 200} {tnum 3} args } {
 		    [$pdb associate -create [callback_n $i] $sdb] 0
 		lappend sdbs $sdb
 	}
-	check_secondaries $pdb $sdbs $half keys data "Sindex00$tnum.c"
+	check_secondaries $pdb $sdbs $half keys data "Si$tnum.c"
 
 	# Delete half of what's left, through the first secondary.
 	set quar [expr $half / 2]
-	puts "\tSindex00$tnum.d: Secondary delete loop: deleting $quar entries"
+	puts "\tSi$tnum.d: Secondary delete loop: deleting $quar entries"
 	set sdb [lindex $sdbs 0]
 	set callback [callback_n 0]
 	for { set n $quar } { $n < $half } { incr n } {
@@ -132,7 +138,7 @@ proc sindex003 { methods {nentries 200} {tnum 3} args } {
 		set ret [$sdb del $skey]
 		error_check_good sdel($n) $ret 0
 	}
-	check_secondaries $pdb $sdbs $quar keys data "Sindex00$tnum.d"
+	check_secondaries $pdb $sdbs $quar keys data "Si$tnum.d"
 
 	foreach sdb $sdbs {
 		error_check_good secondary_close [$sdb close] 0
diff --git a/storage/bdb/test/si004.tcl b/storage/bdb/test/si004.tcl
index 291100da6b310b0e74fedb9ea8605c902ff209c0..08af8b261cea695ef24b6d553a43138f2f594792 100644
--- a/storage/bdb/test/si004.tcl
+++ b/storage/bdb/test/si004.tcl
@@ -1,18 +1,24 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2001-2002
+# Copyright (c) 2001-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: si004.tcl,v 1.6 2002/04/29 17:12:03 sandstro Exp $
+# $Id: si004.tcl,v 1.12 2004/10/27 20:40:25 carol Exp $
 #
-# TEST	sindex004
-# TEST	sindex002 with secondaries created and closed mid-test
+# TEST	si004
+# TEST	si002 with secondaries created and closed mid-test
 # TEST	Basic cursor-based secondary index put/delete test, with
 # TEST	secondaries created mid-test.
-proc sindex004 { methods {nentries 200} {tnum 4} args } {
+proc si004 { methods {nentries 200} {tnum "004"} args } {
 	source ./include.tcl
 	global dict nsecondaries
 
+	# There's no reason to run this test on large lists.
+	if { $nentries > 1000 } {
+		puts "Skipping si004 for large lists (over 1000 items)."
+		return
+	}
+
 	# Primary method/args.
 	set pmethod [lindex $methods 0]
 	set pargs [convert_args $pmethod $args]
@@ -31,11 +37,11 @@ proc sindex004 { methods {nentries 200} {tnum 4} args } {
 	set argses [convert_argses $methods $args]
 	set omethods [convert_methods $methods]
 
-	puts "Sindex00$tnum ($pmethod/$methods) $nentries equal key/data pairs"
+	puts "si$tnum \{\[ list $pmethod $methods \]\} $nentries"
 	env_cleanup $testdir
 
-	set pname "primary00$tnum.db"
-	set snamebase "secondary00$tnum"
+	set pname "primary$tnum.db"
+	set snamebase "secondary$tnum"
 
 	# Open an environment
 	# XXX if one is not supplied!
@@ -47,7 +53,7 @@ proc sindex004 { methods {nentries 200} {tnum 4} args } {
 	error_check_good primary_open [is_valid_db $pdb] TRUE
 
 	puts -nonewline \
-	    "\tSindex00$tnum.a: Cursor put (-keyfirst/-keylast) loop ... "
+	    "\tSi$tnum.a: Cursor put (-keyfirst/-keylast) loop ... "
 	set did [open $dict]
 	set pdbc [$pdb cursor]
 	error_check_good pdb_cursor [is_valid_cursor $pdbc $pdb] TRUE
@@ -88,9 +94,9 @@ proc sindex004 { methods {nentries 200} {tnum 4} args } {
 		    [$pdb associate -create [callback_n $i] $sdb] 0
 		lappend sdbs $sdb
 	}
-	check_secondaries $pdb $sdbs $nentries keys data "Sindex00$tnum.a"
+	check_secondaries $pdb $sdbs $nentries keys data "Si$tnum.a"
 
-	puts "\tSindex00$tnum.b: Cursor put overwrite (-current) loop"
+	puts "\tSi$tnum.b: Cursor put overwrite (-current) loop"
 	set pdbc [$pdb cursor]
 	error_check_good pdb_cursor [is_valid_cursor $pdbc $pdb] TRUE
 	for { set dbt [$pdbc get -first] } { [llength $dbt] > 0 } \
@@ -103,9 +109,9 @@ proc sindex004 { methods {nentries 200} {tnum 4} args } {
 		set data($ns($key)) [pad_data $pmethod $newd]
 	}
 	error_check_good pdbc_close [$pdbc close] 0
-	check_secondaries $pdb $sdbs $nentries keys data "Sindex00$tnum.b"
+	check_secondaries $pdb $sdbs $nentries keys data "Si$tnum.b"
 
-	puts -nonewline "\tSindex00$tnum.c:\
+	puts -nonewline "\tSi$tnum.c:\
 	    Secondary c_pget/primary put overwrite loop ... "
 	# We walk the first secondary, then put-overwrite each primary key/data
 	# pair we find.  This doubles as a DBC->c_pget test.
@@ -140,14 +146,14 @@ proc sindex004 { methods {nentries 200} {tnum 4} args } {
 		error_check_good second_close($sdb) [$sdb close] 0
 		set sdbs [lrange $sdbs 0 end-1]
 		check_secondaries \
-		    $pdb $sdbs $nentries keys data "Sindex00$tnum.b"
+		    $pdb $sdbs $nentries keys data "Si$tnum.c"
 	}
 
 	# Delete the second half of the entries through the primary.
 	# We do the second half so we can just pass keys(0 ... n/2)
 	# to check_secondaries.
 	set half [expr $nentries / 2]
-	puts -nonewline "\tSindex00$tnum.d:\
+	puts -nonewline "\tSi$tnum.d:\
 	    Primary cursor delete loop: deleting $half entries ... "
 	set pdbc [$pdb cursor]
 	error_check_good pdb_cursor [is_valid_cursor $pdbc $pdb] TRUE
@@ -170,11 +176,11 @@ proc sindex004 { methods {nentries 200} {tnum 4} args } {
 		    [$pdb associate -create [callback_n $i] $sdb] 0
 		lappend sdbs $sdb
 	}
-	cursor_check_secondaries $pdb $sdbs $half "Sindex00$tnum.d"
+	cursor_check_secondaries $pdb $sdbs $half "Si$tnum.d"
 
 	# Delete half of what's left, through the first secondary.
 	set quar [expr $half / 2]
-	puts "\tSindex00$tnum.e:\
+	puts "\tSi$tnum.e:\
 	    Secondary cursor delete loop: deleting $quar entries"
 	set sdb [lindex $sdbs 0]
 	set sdbc [$sdb cursor]
@@ -184,7 +190,7 @@ proc sindex004 { methods {nentries 200} {tnum 4} args } {
 		set dbt [$sdbc get -next]
 	}
 	error_check_good sdbc_close [$sdbc close] 0
-	cursor_check_secondaries $pdb $sdbs $quar "Sindex00$tnum.e"
+	cursor_check_secondaries $pdb $sdbs $quar "Si$tnum.e"
 
 	foreach sdb $sdbs {
 		error_check_good secondary_close [$sdb close] 0
diff --git a/storage/bdb/test/si005.tcl b/storage/bdb/test/si005.tcl
index e5ed49175c95b689965fc2fd5b37ddee911c7d66..292cf1f6092efc715c580ebdca88a117adecce0e 100644
--- a/storage/bdb/test/si005.tcl
+++ b/storage/bdb/test/si005.tcl
@@ -1,179 +1,135 @@
-
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2001-2002
+# Copyright (c) 2001-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: si005.tcl,v 11.4 2002/04/29 17:12:03 sandstro Exp $
+# $Id: si005.tcl,v 11.11 2004/10/27 20:40:25 carol Exp $
 #
-# Sindex005: Secondary index and join test.
-proc sindex005 { methods {nitems 1000} {tnum 5} args } {
+# TEST	si005
+# TEST	Basic secondary index put/delete test with transactions
+proc si005 { methods {nentries 200} {tnum "005"} args } {
 	source ./include.tcl
+	global dict nsecondaries
 
 	# Primary method/args.
 	set pmethod [lindex $methods 0]
 	set pargs [convert_args $pmethod $args]
 	set pomethod [convert_method $pmethod]
 
-	# Sindex005 does a join within a simulated database schema
-	# in which the primary index maps a record ID to a ZIP code and
-	# name in the form "XXXXXname", and there are two secondaries:
-	# one mapping ZIP to ID, the other mapping name to ID.
-	# The primary may be of any database type;  the two secondaries
-	# must be either btree or hash.
-
 	# Method/args for all the secondaries.  If only one method
-	# was specified, assume the same method for the two secondaries.
+	# was specified, assume the same method and a standard N
+	# secondaries.
 	set methods [lrange $methods 1 end]
 	if { [llength $methods] == 0 } {
-		for { set i 0 } { $i < 2 } { incr i } {
+		for { set i 0 } { $i < $nsecondaries } { incr i } {
 			lappend methods $pmethod
 		}
-	} elseif { [llength $methods] != 2 } {
-		puts "FAIL: Sindex00$tnum requires exactly two secondaries."
+	}
+
+	# Since this is a transaction test, don't allow nentries to be large.
+	if { $nentries > 1000 } {
+		puts "Skipping si005 for large lists (over 1000 items)."
 		return
 	}
 
 	set argses [convert_argses $methods $args]
 	set omethods [convert_methods $methods]
 
-	puts "Sindex00$tnum ($pmethod/$methods) Secondary index join test."
+	puts "si$tnum \{\[ list $pmethod $methods \]\} $nentries" 
+	puts "\twith transactions"
 	env_cleanup $testdir
 
-	set pname "sindex00$tnum-primary.db"
-	set zipname "sindex00$tnum-zip.db"
-	set namename "sindex00$tnum-name.db"
+	set pname "primary$tnum.db"
+	set snamebase "secondary$tnum"
 
 	# Open an environment
 	# XXX if one is not supplied!
-	set env [berkdb_env -create -home $testdir]
+	set env [berkdb_env -create -home $testdir -txn]
 	error_check_good env_open [is_valid_env $env] TRUE
 
-	# Open the databases.
-	set pdb [eval {berkdb_open -create -env} $env $pomethod $pargs $pname]
+	# Open the primary.
+	set pdb [eval {berkdb_open -create -auto_commit -env} $env $pomethod \
+	    $pargs $pname]
 	error_check_good primary_open [is_valid_db $pdb] TRUE
 
-	set zipdb [eval {berkdb_open -create -dup -env} $env \
-	    [lindex $omethods 0] [lindex $argses 0] $zipname]
-	error_check_good zip_open [is_valid_db $zipdb] TRUE
-	error_check_good zip_associate [$pdb associate s5_getzip $zipdb] 0
-
-	set namedb [eval {berkdb_open -create -dup -env} $env \
-	    [lindex $omethods 1] [lindex $argses 1] $namename]
-	error_check_good name_open [is_valid_db $namedb] TRUE
-	error_check_good name_associate [$pdb associate s5_getname $namedb] 0
-
-	puts "\tSindex00$tnum.a: Populate database with $nitems \"names\""
-	s5_populate $pdb $nitems
-	puts "\tSindex00$tnum.b: Perform a join on each \"name\" and \"ZIP\""
-	s5_jointest $pdb $zipdb $namedb
-
-	error_check_good name_close [$namedb close] 0
-	error_check_good zip_close [$zipdb close] 0
-	error_check_good primary_close [$pdb close] 0
-	error_check_good env_close [$env close] 0
-}
+	# Open and associate the secondaries
+	set sdbs {}
+	for { set i 0 } { $i < [llength $omethods] } { incr i } {
+		set sdb [eval {berkdb_open -create -auto_commit -env} $env \
+		    [lindex $omethods $i] [lindex $argses $i] $snamebase.$i.db]
+		error_check_good second_open($i) [is_valid_db $sdb] TRUE
 
-proc s5_jointest { pdb zipdb namedb } {
-	set pdbc [$pdb cursor]
-	error_check_good pdb_cursor [is_valid_cursor $pdbc $pdb] TRUE
-	for { set dbt [$pdbc get -first] } { [llength $dbt] > 0 } \
-	    { set dbt [$pdbc get -next] } {
-		set item [lindex [lindex $dbt 0] 1]
-		set retlist [s5_dojoin $item $pdb $zipdb $namedb]
+		error_check_good db_associate($i) \
+		    [$pdb associate -auto_commit [callback_n $i] $sdb] 0
+		lappend sdbs $sdb
 	}
-}
-
-proc s5_dojoin { item pdb zipdb namedb } {
-	set name [s5_getname "" $item]
-	set zip [s5_getzip "" $item]
-
-	set zipc [$zipdb cursor]
-	error_check_good zipc($item) [is_valid_cursor $zipc $zipdb] TRUE
-
-	set namec [$namedb cursor]
-	error_check_good namec($item) [is_valid_cursor $namec $namedb] TRUE
-
-	set pc [$pdb cursor]
-	error_check_good pc($item) [is_valid_cursor $pc $pdb] TRUE
-
-	set ret [$zipc get -set $zip]
-	set zd [lindex [lindex $ret 0] 1]
-	error_check_good zipset($zip) [s5_getzip "" $zd] $zip
-
-	set ret [$namec get -set $name]
-	set nd [lindex [lindex $ret 0] 1]
-	error_check_good nameset($name) [s5_getname "" $nd] $name
-
-	set joinc [$pdb join $zipc $namec]
-
-	set anyreturned 0
-	for { set dbt [$joinc get] } { [llength $dbt] > 0 } \
-	    { set dbt [$joinc get] } {
-		set ritem [lindex [lindex $dbt 0] 1]
-		error_check_good returned_item($item) $ritem $item
-		incr anyreturned
-	}
-	error_check_bad anyreturned($item) $anyreturned 0
-
-	error_check_good joinc_close($item) [$joinc close] 0
-	error_check_good pc_close($item) [$pc close] 0
-	error_check_good namec_close($item) [$namec close] 0
-	error_check_good zipc_close($item) [$zipc close] 0
-}
-
-proc s5_populate { db nitems } {
-	global dict
 
+	puts "\tSi$tnum.a: Put loop"
 	set did [open $dict]
-	for { set i 1 } { $i <= $nitems } { incr i } {
-		gets $did word
-		if { [string length $word] < 3 } {
-			gets $did word
-			if { [string length $word] < 3 } {
-				puts "FAIL:\
-				    unexpected pair of words < 3 chars long"
-			}
-		}
-		set datalist [s5_name2zips $word]
-		foreach data $datalist {
-			error_check_good db_put($data) [$db put $i $data$word] 0
+	for { set n 0 } { [gets $did str] != -1 && $n < $nentries } { incr n } {
+		if { [is_record_based $pmethod] == 1 } {
+			set key [expr $n + 1]
+			set datum $str
+		} else {
+			set key $str
+			gets $did datum
 		}
+		set keys($n) $key
+		set data($n) [pad_data $pmethod $datum]
+
+		set txn [$env txn]
+		set ret [eval {$pdb put} -txn $txn \
+		    {$key [chop_data $pmethod $datum]}]
+		error_check_good put($n) $ret 0
+		error_check_good txn_commit($n) [$txn commit] 0
 	}
 	close $did
-}
-
-proc s5_getzip { key data } { return [string range $data 0 4] }
-proc s5_getname { key data } { return [string range $data 5 end] }
-
-# The dirty secret of this test is that the ZIP code is a function of the
-# name, so we can generate a database and then verify join results easily
-# without having to consult actual data.
-#
-# Any word passed into this function will generate from 1 to 26 ZIP
-# entries, out of the set {00000, 01000 ... 99000}.  The number of entries
-# is just the position in the alphabet of the word's first letter;  the
-# entries are then hashed to the set {00, 01 ... 99} N different ways.
-proc s5_name2zips { name } {
-	global alphabet
-
-	set n [expr [string first [string index $name 0] $alphabet] + 1]
-	error_check_bad starts_with_abc($name) $n -1
-
-	set ret {}
-	for { set i 0 } { $i < $n } { incr i } {
-		set b 0
-		for { set j 1 } { $j < [string length $name] } \
-		    { incr j } {
-			set b [s5_nhash $name $i $j $b]
-		}
-		lappend ret [format %05u [expr $b % 100]000]
+	check_secondaries $pdb $sdbs $nentries keys data "Si$tnum.a"
+
+	puts "\tSi$tnum.b: Put/overwrite loop"
+	for { set n 0 } { $n < $nentries } { incr n } {
+		set newd $data($n).$keys($n)
+
+		set txn [$env txn]
+		set ret [eval {$pdb put} -txn $txn \
+		    {$keys($n) [chop_data $pmethod $newd]}]
+		error_check_good put_overwrite($n) $ret 0
+		set data($n) [pad_data $pmethod $newd]
+		error_check_good txn_commit($n) [$txn commit] 0
 	}
-	return $ret
-}
-proc s5_nhash { name i j b } {
-	global alphabet
+	check_secondaries $pdb $sdbs $nentries keys data "Si$tnum.b"
+
+	# Delete the second half of the entries through the primary.
+	# We do the second half so we can just pass keys(0 ... n/2)
+	# to check_secondaries.
+	set half [expr $nentries / 2]
+	puts "\tSi$tnum.c: Primary delete loop: deleting $half entries"
+	for { set n $half } { $n < $nentries } { incr n } {
+		set txn [$env txn]
+		set ret [$pdb del -txn $txn $keys($n)]
+		error_check_good pdel($n) $ret 0
+		error_check_good txn_commit($n) [$txn commit] 0
+	}
+	check_secondaries $pdb $sdbs $half keys data "Si$tnum.c"
+
+	# Delete half of what's left, through the first secondary.
+	set quar [expr $half / 2]
+	puts "\tSi$tnum.d: Secondary delete loop: deleting $quar entries"
+	set sdb [lindex $sdbs 0]
+	set callback [callback_n 0]
+	for { set n $quar } { $n < $half } { incr n } {
+		set skey [$callback $keys($n) [pad_data $pmethod $data($n)]]
+		set txn [$env txn]
+		set ret [$sdb del -txn $txn $skey]
+		error_check_good sdel($n) $ret 0
+		error_check_good txn_commit($n) [$txn commit] 0
+	}
+	check_secondaries $pdb $sdbs $quar keys data "Si$tnum.d"
 
-	set c [string first [string index $name $j] $alphabet']
-	return [expr (($b * 991) + ($i * 997) + $c) % 10000000]
+	puts "\tSi$tnum.e: Closing/disassociating primary first"
+	error_check_good primary_close [$pdb close] 0
+	foreach sdb $sdbs {
+		error_check_good secondary_close [$sdb close] 0
+	}
+	error_check_good env_close [$env close] 0
 }
diff --git a/storage/bdb/test/sysscript.tcl b/storage/bdb/test/sysscript.tcl
index 810b0df6cef5e5c60e046e5e861c474b9ae49316..8386949a6ff9654d18d384a54c50f51008baaab8 100644
--- a/storage/bdb/test/sysscript.tcl
+++ b/storage/bdb/test/sysscript.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: sysscript.tcl,v 11.17 2002/07/29 17:05:24 sue Exp $
+# $Id: sysscript.tcl,v 11.19 2004/01/28 03:36:30 bostic Exp $
 #
 # System integration test script.
 # This script runs a single process that tests the full functionality of
diff --git a/storage/bdb/test/test.tcl b/storage/bdb/test/test.tcl
index 10ee9425b7aef4aa1f725c8b1dae5e0f0b01f9fe..3bd3e4d9c4005fc81db2613267ba1c7164edb422 100644
--- a/storage/bdb/test/test.tcl
+++ b/storage/bdb/test/test.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test.tcl,v 11.225 2002/09/10 18:51:38 sue Exp $
+# $Id: test.tcl,v 11.273 2004/11/01 14:48:23 carol Exp $
 
 source ./include.tcl
 
@@ -17,7 +17,6 @@ if { [file exists $testdir] != 1 } {
 global __debug_print
 global __debug_on
 global __debug_test
-global util_path
 
 #
 # Test if utilities work to figure out the path.  Most systems
@@ -35,53 +34,20 @@ set encrypt 0
 set old_encrypt 0
 set passwd test_passwd
 
-# This is where the test numbering and parameters now live.
-source $test_path/testparams.tcl
-
 # Error stream that (should!) always go to the console, even if we're
 # redirecting to ALL.OUT.
 set consoleerr stderr
 
-foreach sub $subs {
-	if { [info exists num_test($sub)] != 1 } {
-		puts stderr "Subsystem $sub has no number of tests specified in\
-		    testparams.tcl; skipping."
-		continue
-	}
-	set end $num_test($sub)
-	for { set i 1 } { $i <= $end } {incr i} {
-		set name [format "%s%03d.tcl" $sub $i]
-		source $test_path/$name
-	}
-}
-
-source $test_path/archive.tcl
-source $test_path/byteorder.tcl
-source $test_path/dbm.tcl
-source $test_path/hsearch.tcl
-source $test_path/join.tcl
-source $test_path/logtrack.tcl
-source $test_path/ndbm.tcl
-source $test_path/parallel.tcl
-source $test_path/reputils.tcl
-source $test_path/sdbutils.tcl
-source $test_path/shelltest.tcl
-source $test_path/sindex.tcl
-source $test_path/testutils.tcl
-source $test_path/upgrade.tcl
-
 set dict $test_path/wordlist
 set alphabet "abcdefghijklmnopqrstuvwxyz"
 set datastr "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
 
 # Random number seed.
 global rand_init
-set rand_init 101301
+set rand_init 12082003
 
-# Default record length and padding character for
-# fixed record length access method(s)
+# Default record length for fixed record length access method(s)
 set fixed_len 20
-set fixed_pad 0
 
 set recd_debug	0
 set log_log_record_types 0
@@ -102,19 +68,63 @@ global txn_maxid
 set txn_curid 2147483648
 set txn_maxid 4294967295
 
+# The variable one_test allows us to run all the permutations
+# of a test with run_all or run_std.
+global one_test
+if { [info exists one_test] != 1 } {
+	set one_test "ALL"
+}
+
+# This is where the test numbering and parameters now live.
+source $test_path/testparams.tcl
+
 # Set up any OS-specific values
 global tcl_platform
 set is_windows_test [is_substr $tcl_platform(os) "Win"]
 set is_hp_test [is_substr $tcl_platform(os) "HP-UX"]
+set is_je_test 0
 set is_qnx_test [is_substr $tcl_platform(os) "QNX"]
+set upgrade_be [big_endian]
+
+global EXE BAT
+if { $is_windows_test == 1 } {
+	set EXE ".exe"
+	set BAT ".bat"
+} else {
+	set EXE ""
+	set BAT ""
+}
+
+# Try to open an encrypted database.  If it fails, this release
+# doesn't support encryption, and encryption tests should be skipped.
+set has_crypto 1
+set stat [catch {set db \
+    [eval {berkdb open -create -btree -encryptaes test_passwd} ] } result ]
+if { $stat != 0 } {
+	# Make sure it's the right error for a non-crypto release.
+	error_check_good non_crypto_release \
+	    [expr [is_substr $result "operation not supported"] || \
+	    [is_substr $result "invalid argument"]] 1
+	set has_crypto 0
+} else {
+	# It is a crypto release.  Get rid of the db, we don't need it.
+	error_check_good close_encrypted_db [$db close] 0
+}
 
 # From here on out, test.tcl contains the procs that are used to
 # run all or part of the test suite.
 
-proc run_std { args } {
-	global num_test
+proc run_std { { testname ALL } args } {
+	global test_names
+	global one_test
 	source ./include.tcl
 
+	set one_test $testname
+	if { $one_test != "ALL" } {
+		# Source testparams again to adjust test_names.
+		source $test_path/testparams.tcl
+	}
+
 	set exflgs [eval extractflags $args]
 	set args [lindex $exflgs 0]
 	set flags [lindex $exflgs 1]
@@ -165,6 +175,7 @@ proc run_std { args } {
 	set test_list {
 	{"environment"		"env"}
 	{"archive"		"archive"}
+	{"file operations"	"fop"}
 	{"locking"		"lock"}
 	{"logging"		"log"}
 	{"memory pool"		"memp"}
@@ -186,11 +197,12 @@ proc run_std { args } {
 			set msg [lindex $pair 0]
 			set cmd [lindex $pair 1]
 			puts "Running $msg tests"
-			if [catch {exec $tclsh_path \
-			    << "source $test_path/test.tcl; r $rflags $cmd" \
+			if [catch {exec $tclsh_path << \
+			    "global one_test; set one_test $one_test; \
+			    source $test_path/test.tcl; r $rflags $cmd" \
 			    >>& ALL.OUT } res] {
 				set o [open ALL.OUT a]
-				puts $o "FAIL: $cmd test"
+				puts $o "FAIL: $cmd test: $res"
 				close $o
 			}
 		}
@@ -211,12 +223,13 @@ proc run_std { args } {
 		# stderr.
 		puts "Running recovery tests"
 		if [catch {
-		    exec $tclsh_path \
-			<< "source $test_path/test.tcl; r $rflags recd" \
+		    exec $tclsh_path << \
+		    "global one_test; set one_test $one_test; \
+		    source $test_path/test.tcl; r $rflags recd" \
 			2>@ stderr >> ALL.OUT
 		    } res] {
 			set o [open ALL.OUT a]
-			puts $o "FAIL: recd tests"
+			puts $o "FAIL: recd tests: $res"
 			close $o
 		}
 
@@ -225,14 +238,16 @@ proc run_std { args } {
 		# XXX
 		# Broken up into separate tclsh instantiations so we don't
 		# require so much memory.
-		puts "Running join test"
-		foreach i "join1 join2 join3 join4 join5 join6" {
-			if [catch {exec $tclsh_path \
-			    << "source $test_path/test.tcl; r $rflags $i" \
-			    >>& ALL.OUT } res] {
-				set o [open ALL.OUT a]
-				puts $o "FAIL: $i test"
-				close $o
+		if { $one_test == "ALL" } {
+			puts "Running join test"
+			foreach test "join1 join2 join3 join4 join5 join6" {
+				if [catch {exec $tclsh_path << \
+				    "source $test_path/test.tcl; r $rflags $test" \
+				    >>& ALL.OUT } res] {
+					set o [open ALL.OUT a]
+					puts $o "FAIL: $test test: $res"
+					close $o
+				}
 			}
 		}
 	}
@@ -243,23 +258,26 @@ proc run_std { args } {
 		# XXX
 		# Broken up into separate tclsh instantiations so we don't
 		# require so much memory.
-		foreach i \
+		foreach method \
 		    "btree hash queue queueext recno rbtree frecno rrecno" {
-			puts "Running $i tests"
-			for { set j 1 } { $j <= $num_test(test) } {incr j} {
+			puts "Running $method tests"
+			foreach test $test_names(test) {
 				if { $run == 0 } {
 					set o [open ALL.OUT a]
-					run_method -$i $j $j $display $run $o
+					run_method \
+					    -$method $test $display $run $o
 					close $o
 				}
 				if { $run } {
-					if [catch {exec $tclsh_path \
-					    << "source $test_path/test.tcl; \
-					    run_method -$i $j $j $display $run"\
+					if [catch {exec $tclsh_path << \
+					    "global one_test; \
+					    set one_test $one_test; \
+					    source $test_path/test.tcl; \
+					    run_method \
+					    -$method $test $display $run"\
 					    >>& ALL.OUT } res] {
 						set o [open ALL.OUT a]
-						puts $o "FAIL:\
-						    [format "test%03d" $j] $i"
+						puts $o "FAIL:$test $method: $res"
 						close $o
 					}
 				}
@@ -274,14 +292,16 @@ proc run_std { args } {
 		return
 	}
 
-	set failed [check_failed_run ALL.OUT]
+	set failed [check_output ALL.OUT]
 
 	set o [open ALL.OUT a]
 	if { $failed == 0 } {
 		puts "Regression Tests Succeeded"
 		puts $o "Regression Tests Succeeded"
 	} else {
-		puts "Regression Tests Failed; see ALL.OUT for log"
+		puts "Regression Tests Failed"
+		puts "Check UNEXPECTED OUTPUT lines."
+		puts "Review ALL.OUT.x for details."
 		puts $o "Regression Tests Failed"
 	}
 
@@ -292,22 +312,123 @@ proc run_std { args } {
 	close $o
 }
 
-proc check_failed_run { file {text "^FAIL"}} {
+proc check_output { file } {
+	# These are all the acceptable patterns.
+	set pattern {(?x)
+		^[:space:]*$|
+		.*?wrap\.tcl.*|
+		.*?dbscript\.tcl.*|
+		.*?ddscript\.tcl.*|
+		.*?mpoolscript\.tcl.*|
+		.*?mutexscript\.tcl.*|
+		^\d\d:\d\d:\d\d\s\(\d\d:\d\d:\d\d\)$|
+		^\d\d:\d\d:\d\d\s\(\d\d:\d\d:\d\d\)\sCrashing$|
+		^\d\d:\d\d:\d\d\s\(\d\d:\d\d:\d\d\)\s[p|P]rocesses\srunning:.*|
+		^\d\d:\d\d:\d\d\s\(\d\d:\d\d:\d\d\)\s5\sprocesses\srunning.*|
+		^\d:\sPut\s\d*\sstrings\srandom\soffsets.*|
+		^100.*|
+		^eval\s.*|
+		^exec\s.*|
+		^jointest.*$|
+		^r\sarchive\s*|
+		^r\sdbm\s*|
+		^r\shsearch\s*|
+		^r\sndbm\s*|
+		^r\srpc\s*|
+		^run_recd:\s.*|
+		^run_reptest:\s.*|
+		^run_rpcmethod:\s.*|
+		^run_secenv:\s.*|
+		^All\sprocesses\shave\sexited.$|
+		^Beginning\scycle\s\d$|
+		^Byteorder:.*|
+		^Child\sruns\scomplete\.\s\sParent\smodifies\sdata\.$|
+		^Deadlock\sdetector:\s\d*\sCheckpoint\sdaemon\s\d*$|
+		^Ending\srecord.*|
+		^Environment\s.*?specified;\s\sskipping\.$|
+		^Executing\srecord\s.*|
+		^Join\stest:\.*|
+		^Method:\s.*|
+		^Repl:\stest\d\d\d:.*|
+		^Repl:\ssdb\d\d\d:.*|
+		^Script\swatcher\sprocess\s.*|
+		^Sleepycat\sSoftware:\sBerkeley\sDB\s.*|
+		^Test\ssuite\srun\s.*|
+		^Unlinking\slog:\serror\smessage\sOK$|
+		^Verifying\s.*|
+		^\t*\.\.\.dbc->get.*$|
+		^\t*\.\.\.dbc->put.*$|
+		^\t*\.\.\.key\s\d*$|
+		^\t*\.\.\.Skipping\sdbc.*|
+		^\t*and\s\d*\sduplicate\sduplicates\.$|
+		^\t*About\sto\srun\srecovery\s.*complete$|
+		^\t*Archive[:\.].*|
+		^\t*Building\s.*|
+		^\t*closing\ssecondaries\.$|
+		^\t*Command\sexecuted\sand\s.*$|
+		^\t*DBM.*|
+		^\t*[d|D]ead[0-9][0-9][0-9].*|
+		^\t*Dump\/load\sof.*|
+		^\t*[e|E]nv[0-9][0-9][0-9].*|
+		^\t*Executing\scommand$|
+		^\t*Executing\stxn_.*|
+		^\t*File\srecd005\.\d\.db\sexecuted\sand\saborted\.$|
+		^\t*File\srecd005\.\d\.db\sexecuted\sand\scommitted\.$|
+		^\t*[f|F]op[0-9][0-9][0-9].*|
+		^\t*HSEARCH.*|
+		^\t*Initial\sCheckpoint$|
+		^\t*Iteration\s\d*:\sCheckpointing\.$|
+		^\t*Joining:\s.*|
+		^\t*Kid[1|2]\sabort\.\.\.complete$|
+		^\t*Kid[1|2]\scommit\.\.\.complete$|
+		^\t*[l|L]ock[0-9][0-9][0-9].*|
+		^\t*[l|L]og[0-9][0-9][0-9].*|
+		^\t*[m|M]emp[0-9][0-9][0-9].*|
+		^\t*[m|M]utex[0-9][0-9][0-9].*|
+		^\t*NDBM.*|
+		^\t*opening\ssecondaries\.$|
+		^\t*op_recover_rec:\sRunning\srecovery.*|
+		^\t*[r|R]ecd[0-9][0-9][0-9].*|
+		^\t*[r|R]ep[0-9][0-9][0-9].*|
+		^\t*[r|R]ep_test.*|
+		^\t*[r|R]pc[0-9][0-9][0-9].*|
+		^\t*[r|R]src[0-9][0-9][0-9].*|
+		^\t*Run_rpcmethod.*|
+		^\t*Running\srecovery\son\s.*|
+		^\t*[s|S]ec[0-9][0-9][0-9].*|
+		^\t*[s|S]i[0-9][0-9][0-9].*|
+		^\t*Sijoin.*|
+		^\t*sdb[0-9][0-9][0-9].*|
+		^\t*Skipping\s.*|
+		^\t*Subdb[0-9][0-9][0-9].*|
+		^\t*Subdbtest[0-9][0-9][0-9].*|
+		^\t*Syncing$|
+		^\t*[t|T]est[0-9][0-9][0-9].*|
+		^\t*[t|T]xn[0-9][0-9][0-9].*|
+		^\t*Txnscript.*|
+		^\t*Using\s.*?\senvironment\.$|
+		^\t*Verification\sof.*|
+		^\t*with\stransactions$}
+
 	set failed 0
-	set o [open $file r]
-	while { [gets $o line] >= 0 } {
-		set ret [regexp $text $line]
-		if { $ret != 0 } {
+	set f [open $file r]
+	while { [gets $f line] >= 0 } {
+		if { [regexp $pattern $line] == 0 } {
+			puts -nonewline "UNEXPECTED OUTPUT: "
+			puts $line
 			set failed 1
 		}
 	}
-	close $o
-
+	close $f
 	return $failed
 }
 
 proc r { args } {
-	global num_test
+	global test_names
+	global has_crypto
+	global rand_init
+	global one_test
+
 	source ./include.tcl
 
 	set exflgs [eval extractflags $args]
@@ -330,40 +451,45 @@ proc r { args } {
 	if {[catch {
 		set sub [ lindex $args 0 ]
 		switch $sub {
-			byte {
+			dead -
+			env -
+			lock -
+			log -
+			memp -
+			mutex -
+			rsrc -
+			sdbtest -
+			txn {
 				if { $display } {
-					puts "run_test byteorder"
+					run_subsystem $sub 1 0
 				}
 				if { $run } {
-					check_handles
-					run_test byteorder
+					run_subsystem $sub
+				}
+			}
+			byte {
+				if { $one_test == "ALL" } {
+					run_test byteorder $display $run
 				}
 			}
 			archive -
 			dbm -
 			hsearch -
 			ndbm -
-			shelltest -
-			sindex {
-				if { $display } { puts "r $sub" }
-				if { $run } {
-					check_handles
-					$sub
+			shelltest {
+				if { $one_test == "ALL" } {
+					if { $display } { puts "r $sub" }
+					if { $run } {
+						check_handles
+						$sub
+					}
 				}
 			}
 			bigfile -
-			dead -
-			env -
-			lock -
-			log -
-			memp -
-			mutex -
-			rsrc -
-			sdbtest -
-			txn {
-				if { $display } { run_subsystem $sub 1 0 }
-				if { $run } {
-					run_subsystem $sub
+			elect -
+			fop {
+				foreach test $test_names($sub) {
+					eval run_test $test $display $run
 				}
 			}
 			join {
@@ -429,104 +555,121 @@ proc r { args } {
 				run_recds $run $display [lrange $args 1 end]
 			}
 			rep {
-				for { set j 1 } { $j <= $num_test(test) } \
-				    { incr j } {
-					if { $display } {
-						puts "eval run_test \
-						    run_repmethod 0 $j $j"
-					}
-					if { $run } {
-						eval run_test \
-						    run_repmethod 0 $j $j
-					}
+				foreach test $test_names(rep) {
+					run_test $test $display $run
 				}
-				for { set i 1 } \
-				    { $i <= $num_test(rep) } {incr i} {
-					set test [format "%s%03d" $sub $i]
-					if { $i == 2 } {
-						if { $run } {
-							puts "Skipping rep002 \
-							    (waiting on SR #6195)"
-						}
-						continue
-					}
-					if { $display } {
-						puts "run_test $test"
-					}
-					if { $run } {
-						run_test $test
+				# We seed the random number generator here
+				# instead of in run_repmethod so that we
+				# aren't always reusing the first few
+				# responses from random_int.
+				#
+				berkdb srand $rand_init
+				foreach sub { test sdb } {
+					foreach test $test_names($sub) {
+						eval run_test run_repmethod \
+						    $display $run $test
 					}
 				}
 			}
 			rpc {
-				if { $display } { puts "r $sub" }
-				global rpc_svc svc_list
-				set old_rpc_src $rpc_svc
-				foreach rpc_svc $svc_list {
-					if { !$run || \
-					  ![file exist $util_path/$rpc_svc] } {
-						continue
+				if { $one_test == "ALL" } {
+					if { $display } { puts "r $sub" }
+					global BAT EXE rpc_svc svc_list
+					global rpc_svc svc_list is_je_test
+					set old_rpc_src $rpc_svc
+					foreach rpc_svc $svc_list {
+						if { $rpc_svc == "berkeley_dbje_svc" } {
+							set old_util_path $util_path
+							set util_path $je_root/dist
+							set is_je_test 1
+						}
+
+						if { !$run || \
+				      ![file exist $util_path/$rpc_svc$BAT] || \
+				      ![file exist $util_path/$rpc_svc$EXE] } {
+							continue
+						}
+
+						run_subsystem rpc
+						if { [catch {run_rpcmethod -txn} ret] != 0 } {
+							puts $ret
+						}
+
+						if { $is_je_test } {
+							check_handles
+							eval run_rpcmethod -btree
+							verify_dir $testdir "" 1
+						} else {
+							run_test run_rpcmethod $display $run
+						}
+
+						if { $is_je_test } {
+							set util_path $old_util_path
+							set is_je_test 0
+						}
+
 					}
-					run_subsystem rpc
-					if { [catch {run_rpcmethod -txn} ret] != 0 } {
-						puts $ret
+					set rpc_svc $old_rpc_src
 					}
-					run_test run_rpcmethod
 				}
-				set rpc_svc $old_rpc_src
-			}
 			sec {
+				# Skip secure mode tests if release
+				# does not support encryption.
+				if { $has_crypto == 0 } {
+					return
+				}
 				if { $display } {
 					run_subsystem $sub 1 0
 				}
 				if { $run } {
 					run_subsystem $sub 0 1
 				}
-				for { set j 1 } { $j <= $num_test(test) } \
-				    { incr j } {
+				foreach test $test_names(test) {
+					eval run_test run_secmethod \
+					    $display $run $test
+					eval run_test run_secenv \
+					    $display $run $test
+				}
+			}
+			sdb {
+				if { $one_test == "ALL" } {
 					if { $display } {
-						puts "eval run_test \
-						    run_secmethod $j $j"
-						puts "eval run_test \
-						    run_secenv $j $j"
+						run_subsystem sdbtest 1 0
 					}
 					if { $run } {
-						eval run_test \
-						    run_secmethod $j $j
-						eval run_test \
-						    run_secenv $j $j
+						run_subsystem sdbtest 0 1
 					}
 				}
+				foreach test $test_names(sdb) {
+					eval run_test $test $display $run
+				}
 			}
-			sdb {
-				if { $display } {
-					puts "eval r $saveflags sdbtest"
-					for { set j 1 } \
-					    { $j <= $num_test(sdb) } \
-					    { incr j } {
-						puts "eval run_test \
-						    subdb $j $j"
+			sindex {
+				if { $one_test == "ALL" } {
+					if { $display } {
+						sindex 1 0
+						sijoin 1 0
 					}
-				}
-				if { $run } {
-					eval r $saveflags sdbtest
-					for { set j 1 } \
-					    { $j <= $num_test(sdb) } \
-					    { incr j } {
-						eval run_test subdb $j $j
+					if { $run } {
+						sindex 0 1
+						sijoin 0 1
 					}
 				}
 			}
 			btree -
 			rbtree -
 			hash -
+			iqueue -
+			iqueueext -
 			queue -
 			queueext -
 			recno -
 			frecno -
 			rrecno {
-				eval run_method [lindex $args 0] \
-				    1 0 $display $run [lrange $args 1 end]
+				foreach test $test_names(test) {
+					eval run_method [lindex $args 0] $test \
+					    $display $run [lrange $args 1 end]
+				}
 			}
 
 			default {
@@ -549,78 +692,72 @@ proc r { args } {
 	}
 }
 
-proc run_subsystem { prefix { display 0 } { run 1} } {
-	global num_test
-	if { [info exists num_test($prefix)] != 1 } {
-		puts stderr "Subsystem $sub has no number of tests specified in\
+proc run_subsystem { sub { display 0 } { run 1} } {
+	global test_names
+
+	if { [info exists test_names($sub)] != 1 } {
+		puts stderr "Subsystem $sub has no tests specified in\
 		    testparams.tcl; skipping."
 		return
 	}
-	for { set i 1 } { $i <= $num_test($prefix) } {incr i} {
-		set name [format "%s%03d" $prefix $i]
+	foreach test $test_names($sub) {
 		if { $display } {
-			puts "eval $name"
+			puts "eval $test"
 		}
 		if { $run } {
 			check_handles
-			catch {eval $name}
+			if {[catch {eval $test} ret] != 0 } {
+				puts "FAIL: run_subsystem: $sub $test: \
+				    $ret"
+			}
 		}
 	}
 }
 
-proc run_test { testname args } {
+proc run_test { test {display 0} {run 1} args } {
 	source ./include.tcl
 	foreach method "hash queue queueext recno rbtree frecno rrecno btree" {
-	 	check_handles
-		eval $testname -$method $args
-		verify_dir $testdir "" 1
+		if { $display } {
+			puts "eval $test -$method $args; verify_dir $testdir \"\" 1"
+		}
+		if { $run } {
+	 		check_handles
+			eval $test -$method $args
+			verify_dir $testdir "" 1
+		}
 	}
 }
 
-proc run_method { method {start 1} {stop 0} {display 0} {run 1} \
+proc run_method { method test {display 0} {run 1} \
     { outfile stdout } args } {
 	global __debug_on
 	global __debug_print
-	global num_test
+	global __debug_test
+	global test_names
 	global parms
 	source ./include.tcl
 
-	if { $stop == 0 } {
-		set stop $num_test(test)
-	}
-	if { $run == 1 } {
-		puts $outfile "run_method: $method $start $stop $args"
-	}
-
 	if {[catch {
-		for { set i $start } { $i <= $stop } {incr i} {
-			set name [format "test%03d" $i]
-			if { [info exists parms($name)] != 1 } {
-				puts stderr "[format Test%03d $i] disabled in\
-				    testparams.tcl; skipping."
-				continue
-			}
-			if { $display } {
-				puts -nonewline $outfile "eval $name $method"
-				puts -nonewline $outfile " $parms($name) $args"
-				puts $outfile " ; verify_dir $testdir \"\" 1"
+		if { $display } {
+			puts -nonewline $outfile "eval $test $method"
+			puts -nonewline $outfile " $parms($test) $args"
+			puts $outfile " ; verify_dir $testdir \"\" 1"
+		}
+		if { $run } {
+			check_handles $outfile
+			puts $outfile "[timestamp]"
+			eval $test $method $parms($test) $args
+			if { $__debug_print != 0 } {
+				puts $outfile ""
 			}
-			if { $run } {
-				check_handles $outfile
-				puts $outfile "[timestamp]"
-				eval $name $method $parms($name) $args
-				if { $__debug_print != 0 } {
-					puts $outfile ""
-				}
-				# verify all databases the test leaves behind
-				verify_dir $testdir "" 1
-				if { $__debug_on != 0 } {
-					debug
-				}
+			# verify all databases the test leaves behind
+			verify_dir $testdir "" 1
+			if { $__debug_on != 0 } {
+				debug $__debug_test
 			}
-			flush stdout
-			flush stderr
 		}
+		flush stdout
+		flush stderr
 	} res] != 0} {
 		global errorInfo;
 
@@ -628,36 +765,28 @@ proc run_method { method {start 1} {stop 0} {display 0} {run 1} \
 		set theError [string range $errorInfo 0 [expr $fnl - 1]]
 		if {[string first FAIL $errorInfo] == -1} {
 			error "FAIL:[timestamp]\
-			    run_method: $method $i: $theError"
+			    run_method: $method $test: $theError"
 		} else {
 			error $theError;
 		}
 	}
 }
 
-proc run_rpcmethod { method {start 1} {stop 0} {largs ""} } {
+proc run_rpcmethod { method {largs ""} } {
 	global __debug_on
 	global __debug_print
-	global num_test
+	global __debug_test
+	global rpc_tests
 	global parms
 	global is_envmethod
 	global rpc_svc
 	source ./include.tcl
 
-	if { $stop == 0 } {
-		set stop $num_test(test)
-	}
-	puts "run_rpcmethod: $method $start $stop $largs"
+	puts "run_rpcmethod: $method $largs"
 
 	set save_largs $largs
-	if { [string compare $rpc_server "localhost"] == 0 } {
-	       set dpid [exec $util_path/$rpc_svc -h $rpc_testdir &]
-	} else {
-	       set dpid [exec rsh $rpc_server $rpc_path/$rpc_svc \
-		   -h $rpc_testdir &]
-	}
-	puts "\tRun_rpcmethod.a: starting server, pid $dpid"
-	tclsleep 10
+	set dpid [rpc_server_start]
+	puts "\tRun_rpcmethod.a: started server, pid $dpid"
 	remote_cleanup $rpc_server $rpc_testdir $testdir
 
 	set home [file tail $rpc_testdir]
@@ -668,11 +797,7 @@ proc run_rpcmethod { method {start 1} {stop 0} {largs ""} } {
 		set use_txn 1
 	}
 	if { $use_txn == 1 } {
-		if { $start == 1 } {
-			set ntxns 32
-		} else {
-			set ntxns $start
-		}
+		set ntxns 32
 		set i 1
 		check_handles
 		remote_cleanup $rpc_server $rpc_testdir $testdir
@@ -684,76 +809,75 @@ proc run_rpcmethod { method {start 1} {stop 0} {largs ""} } {
 		if { $stat == 0 } {
 			set stat [catch {eval txn001_subb $ntxns $env} res]
 		}
-		error_check_good envclose [$env close] 0
 		set stat [catch {eval txn003} res]
+		error_check_good envclose [$env close] 0
 	} else {
-		set stat [catch {
-			for { set i $start } { $i <= $stop } {incr i} {
+		foreach test $rpc_tests($rpc_svc) {
+			set stat [catch {
 				check_handles
-				set name [format "test%03d" $i]
-				if { [info exists parms($name)] != 1 } {
-					puts stderr "[format Test%03d $i]\
-					    disabled in testparams.tcl;\
-					    skipping."
-					continue
-				}
 				remote_cleanup $rpc_server $rpc_testdir $testdir
 				#
-				# Set server cachesize to 1Mb.  Otherwise some
-				# tests won't fit (like test084 -btree).
+				# Set server cachesize to 128Mb.  Otherwise
+				# some tests won't fit (like test084 -btree).
 				#
 				set env [eval {berkdb_env -create -mode 0644 \
 				    -home $home -server $rpc_server \
 				    -client_timeout 10000 \
-				    -cachesize {0 1048576 1}}]
+				    -cachesize {0 134217728 1}}]
 				error_check_good env_open \
 				    [is_valid_env $env] TRUE
+				set largs $save_largs
 				append largs " -env $env "
 
 				puts "[timestamp]"
-				eval $name $method $parms($name) $largs
+				eval $test $method $parms($test) $largs
 				if { $__debug_print != 0 } {
 					puts ""
 				}
 				if { $__debug_on != 0 } {
-					debug
+					debug $__debug_test
 				}
 				flush stdout
 				flush stderr
-				set largs $save_largs
 				error_check_good envclose [$env close] 0
-			}
-		} res]
-	}
-	if { $stat != 0} {
-		global errorInfo;
+				set env ""
+			} res]
 
-		set fnl [string first "\n" $errorInfo]
-		set theError [string range $errorInfo 0 [expr $fnl - 1]]
-		tclkill $dpid
-		if {[string first FAIL $errorInfo] == -1} {
-			error "FAIL:[timestamp]\
-			    run_rpcmethod: $method $i: $theError"
-		} else {
-			error $theError;
+			if { $stat != 0} {
+				global errorInfo;
+
+				puts "$res"
+
+				set fnl [string first "\n" $errorInfo]
+				set theError [string range $errorInfo 0 [expr $fnl - 1]]
+				if {[string first FAIL $errorInfo] == -1} {
+					puts "FAIL:[timestamp]\
+					    run_rpcmethod: $method $test: $errorInfo"
+				} else {
+					puts $theError;
+				}
+
+				catch { $env close } ignore
+				set env ""
+				tclkill $dpid
+				set dpid [rpc_server_start]
+			}
 		}
 	}
 	set is_envmethod 0
 	tclkill $dpid
 }
 
-proc run_rpcnoserver { method {start 1} {stop 0} {largs ""} } {
+proc run_rpcnoserver { method {largs ""} } {
 	global __debug_on
 	global __debug_print
-	global num_test
+	global __debug_test
+	global test_names
 	global parms
 	global is_envmethod
 	source ./include.tcl
 
-	if { $stop == 0 } {
-		set stop $num_test(test)
-	}
-	puts "run_rpcnoserver: $method $start $stop $largs"
+	puts "run_rpcnoserver: $method $largs"
 
 	set save_largs $largs
 	remote_cleanup $rpc_server $rpc_testdir $testdir
@@ -765,11 +889,7 @@ proc run_rpcnoserver { method {start 1} {stop 0} {largs ""} } {
 		set use_txn 1
 	}
 	if { $use_txn == 1 } {
-		if { $start == 1 } {
-			set ntxns 32
-		} else {
-			set ntxns $start
-		}
+		set ntxns 32
 		set i 1
 		check_handles
 		remote_cleanup $rpc_server $rpc_testdir $testdir
@@ -784,13 +904,11 @@ proc run_rpcnoserver { method {start 1} {stop 0} {largs ""} } {
 		error_check_good envclose [$env close] 0
 	} else {
 		set stat [catch {
-			for { set i $start } { $i <= $stop } {incr i} {
+			foreach test $test_names {
 				check_handles
-				set name [format "test%03d" $i]
-				if { [info exists parms($name)] != 1 } {
-					puts stderr "[format Test%03d $i]\
-					    disabled in testparams.tcl;\
-					    skipping."
+				if { [info exists parms($test)] != 1 } {
+					puts stderr "$test disabled in \
+					    testparams.tcl; skipping."
 					continue
 				}
 				remote_cleanup $rpc_server $rpc_testdir $testdir
@@ -807,12 +925,12 @@ proc run_rpcnoserver { method {start 1} {stop 0} {largs ""} } {
 				append largs " -env $env "
 
 				puts "[timestamp]"
-				eval $name $method $parms($name) $largs
+				eval $test $method $parms($test) $largs
 				if { $__debug_print != 0 } {
 					puts ""
 				}
 				if { $__debug_on != 0 } {
-					debug
+					debug $__debug_test
 				}
 				flush stdout
 				flush stderr
@@ -840,73 +958,80 @@ proc run_rpcnoserver { method {start 1} {stop 0} {largs ""} } {
 #
 # Run method tests in secure mode.
 #
-proc run_secmethod { method {start 1} {stop 0} {display 0} {run 1} \
+proc run_secmethod { method test {display 0} {run 1} \
     { outfile stdout } args } {
 	global passwd
+	global has_crypto
+
+	# Skip secure mode tests if release does not support encryption.
+	if { $has_crypto == 0 } {
+		return
+	}
 
+	set largs $args
 	append largs " -encryptaes $passwd "
-	eval run_method $method $start $stop $display $run $outfile $largs
+	eval run_method $method $test $display $run $outfile $largs
 }
 
 #
-# Run method tests in its own, new secure environment.
+# Run method tests each in its own, new secure environment.
 #
-proc run_secenv { method {start 1} {stop 0} {largs ""} } {
+proc run_secenv { method test {largs ""} } {
 	global __debug_on
 	global __debug_print
+	global __debug_test
 	global is_envmethod
-	global num_test
+	global has_crypto
+	global test_names
 	global parms
 	global passwd
 	source ./include.tcl
 
-	if { $stop == 0 } {
-		set stop $num_test(test)
+	# Skip secure mode tests if release does not support encryption.
+	if { $has_crypto == 0 } {
+		return
 	}
-	puts "run_secenv: $method $start $stop $largs"
+
+	puts "run_secenv: $method $test $largs"
 
 	set save_largs $largs
 	env_cleanup $testdir
 	set is_envmethod 1
 	set stat [catch {
-		for { set i $start } { $i <= $stop } {incr i} {
-			check_handles
-			set env [eval {berkdb_env -create -mode 0644 \
-			    -home $testdir -encryptaes $passwd \
-			    -cachesize {0 1048576 1}}]
-			error_check_good env_open [is_valid_env $env] TRUE
-			append largs " -env $env "
+		check_handles
+		set env [eval {berkdb_env -create -mode 0644 -home $testdir \
+		    -encryptaes $passwd -cachesize {0 1048576 1}}]
+		error_check_good env_open [is_valid_env $env] TRUE
+		append largs " -env $env "
 
-			puts "[timestamp]"
-			set name [format "test%03d" $i]
-			if { [info exists parms($name)] != 1 } {
-				puts stderr "[format Test%03d $i] disabled in\
-				    testparams.tcl; skipping."
-				continue
-			}
+		puts "[timestamp]"
+		if { [info exists parms($test)] != 1 } {
+			puts stderr "$test disabled in\
+			    testparams.tcl; skipping."
+			continue
+		}
 
-			#
-			# Run each test multiple times in the secure env.
-			# Once with a secure env + clear database
-			# Once with a secure env + secure database
-			#
-			eval $name $method $parms($name) $largs
-			append largs " -encrypt "
-			eval $name $method $parms($name) $largs
+		#
+		# Run each test multiple times in the secure env.
+		# Once with a secure env + clear database
+		# Once with a secure env + secure database
+		#
+		eval $test $method $parms($test) $largs
+		append largs " -encrypt "
+		eval $test $method $parms($test) $largs
 
-			if { $__debug_print != 0 } {
-				puts ""
-			}
-			if { $__debug_on != 0 } {
-				debug
-			}
-			flush stdout
-			flush stderr
-			set largs $save_largs
-			error_check_good envclose [$env close] 0
-			error_check_good envremove [berkdb envremove \
-			    -home $testdir -encryptaes $passwd] 0
+		if { $__debug_print != 0 } {
+			puts ""
 		}
+		if { $__debug_on != 0 } {
+			debug $__debug_test
+		}
+		flush stdout
+		flush stderr
+		set largs $save_largs
+		error_check_good envclose [$env close] 0
+		error_check_good envremove [berkdb envremove \
+		    -home $testdir -encryptaes $passwd] 0
 	} res]
 	if { $stat != 0} {
 		global errorInfo;
@@ -915,7 +1040,7 @@ proc run_secenv { method {start 1} {stop 0} {largs ""} } {
 		set theError [string range $errorInfo 0 [expr $fnl - 1]]
 		if {[string first FAIL $errorInfo] == -1} {
 			error "FAIL:[timestamp]\
-			    run_secenv: $method $i: $theError"
+			    run_secenv: $method $test: $theError"
 		} else {
 			error $theError;
 		}
@@ -934,26 +1059,16 @@ proc run_reptest { method test {droppct 0} {nclients 1} {do_del 0} \
 	global __debug_print
 	global __debug_test
 	global is_envmethod
-	global num_test
 	global parms
 	global passwd
-	global rand_init
+	global has_crypto
 
-	berkdb srand $rand_init
-	set c [string index $test 0]
-	if { $c == "s" } {
-		set i [string range $test 1 end]
-		set name [format "subdb%03d" $i]
-	} else {
-		set i $test
-		set name [format "test%03d" $i]
-	}
-	puts "run_reptest: $method $name"
+	puts "run_reptest: $method $test $droppct $nclients $do_del $do_sec $do_oob $largs"
 
 	env_cleanup $testdir
 	set is_envmethod 1
 	set stat [catch {
-		if { $do_sec } {
+		if { $do_sec && $has_crypto } {
 			set envargs "-encryptaes $passwd"
 			append largs " -encrypt "
 		} else {
@@ -964,18 +1079,18 @@ proc run_reptest { method test {droppct 0} {nclients 1} {do_del 0} \
 		# This will set up the master and client envs
 		# and will return us the args to pass to the
 		# test.
+
 		set largs [repl_envsetup \
 		    $envargs $largs $test $nclients $droppct $do_oob]
 
 		puts "[timestamp]"
-		if { [info exists parms($name)] != 1 } {
-			puts stderr "[format Test%03d $i] \
-			    disabled in\
+		if { [info exists parms($test)] != 1 } {
+			puts stderr "$test disabled in\
 			    testparams.tcl; skipping."
 			continue
 		}
 		puts -nonewline \
-		    "Repl: $name: dropping $droppct%, $nclients clients "
+		    "Repl: $test: dropping $droppct%, $nclients clients "
 		if { $do_del } {
 			puts -nonewline " with delete verification;"
 		} else {
@@ -993,7 +1108,7 @@ proc run_reptest { method test {droppct 0} {nclients 1} {do_del 0} \
 		}
 		puts ""
 
-		eval $name $method $parms($name) $largs
+		eval $test $method $parms($test) $largs
 
 		if { $__debug_print != 0 } {
 			puts ""
@@ -1003,12 +1118,12 @@ proc run_reptest { method test {droppct 0} {nclients 1} {do_del 0} \
 		}
 		flush stdout
 		flush stderr
-		repl_envprocq $i $nclients $do_oob
-		repl_envver0 $i $method $nclients
+		repl_envprocq $test $nclients $do_oob
+		repl_envver0 $test $method $nclients
 		if { $do_del } {
-			repl_verdel $i $method $nclients
+			repl_verdel $test $method $nclients
 		}
-		repl_envclose $i $envargs
+		repl_envclose $test $envargs
 	} res]
 	if { $stat != 0} {
 		global errorInfo;
@@ -1017,7 +1132,7 @@ proc run_reptest { method test {droppct 0} {nclients 1} {do_del 0} \
 		set theError [string range $errorInfo 0 [expr $fnl - 1]]
 		if {[string first FAIL $errorInfo] == -1} {
 			error "FAIL:[timestamp]\
-			    run_reptest: $method $i: $theError"
+			    run_reptest: $method $test: $theError"
 		} else {
 			error $theError;
 		}
@@ -1028,337 +1143,131 @@ proc run_reptest { method test {droppct 0} {nclients 1} {do_del 0} \
 #
 # Run replication method tests in master and client env.
 #
-proc run_repmethod { method {numcl 0} {start 1} {stop 0} {display 0}
-    {run 1} {outfile stdout} {largs ""} } {
+proc run_repmethod { method test {numcl 0} {display 0} {run 1} \
+    {outfile stdout} {largs ""} } {
 	source ./include.tcl
 	global __debug_on
 	global __debug_print
 	global __debug_test
 	global is_envmethod
-	global num_test
+	global test_names
 	global parms
+	global has_crypto
 	global passwd
-	global rand_init
 
-	set stopsdb $num_test(sdb)
-	if { $stop == 0 } {
-		set stop $num_test(test)
+	set save_largs $largs
+	env_cleanup $testdir
+
+	# Use an array for number of clients because we really don't
+	# want to evenly-weight all numbers of clients.  Favor smaller
+	# numbers but test more clients occasionally.
+	set drop_list { 0 0 0 0 0 1 1 5 5 10 20 }
+	set drop_len [expr [llength $drop_list] - 1]
+	set client_list { 1 1 2 1 1 1 2 2 3 1 }
+	set cl_len [expr [llength $client_list] - 1]
+
+	if { $numcl == 0 } {
+		set clindex [berkdb random_int 0 $cl_len]
+		set nclients [lindex $client_list $clindex]
 	} else {
-		if { $stopsdb > $stop } {
-			set stopsdb $stop
-		}
+		set nclients $numcl
 	}
-	berkdb srand $rand_init
+	set drindex [berkdb random_int 0 $drop_len]
+	set droppct [lindex $drop_list $drindex]
+ 	set do_sec [berkdb random_int 0 1]
+	set do_oob [berkdb random_int 0 1]
+	set do_del [berkdb random_int 0 1]
+
+	if { $display == 1 } {
+		puts $outfile "eval run_reptest $method $test $droppct \
+		    $nclients $do_del $do_sec $do_oob $largs"
+	}
+	if { $run == 1 } {
+		run_reptest $method $test $droppct $nclients $do_del \
+		    $do_sec $do_oob $largs
+	}
+}
+
+#
+# Run method tests, each in its own, new environment.  (As opposed to
+# run_envmethod1 which runs all the tests in a single environment.)
+#
+proc run_envmethod { method test {display 0} {run 1} {outfile stdout} \
+    { largs "" } } {
+	global __debug_on
+	global __debug_print
+	global __debug_test
+	global is_envmethod
+	global test_names
+	global parms
+	source ./include.tcl
 
-	#
-	# We want to run replication both normally and with crypto.
-	# So run it once and then run again with crypto.
-	#
 	set save_largs $largs
+	set envargs ""
 	env_cleanup $testdir
 
 	if { $display == 1 } {
-		for { set i $start } { $i <= $stop } { incr i } {
-			puts $outfile "eval run_repmethod $method \
-			    0 $i $i 0 1 stdout $largs"
+		puts $outfile "eval run_envmethod $method \
+		    $test 0 1 stdout $largs"
+	}
+
+	# To run a normal test using system memory, call run_envmethod
+	# with the flag -shm.
+	set sindex [lsearch -exact $largs "-shm"]
+	if { $sindex >= 0 } {
+		if { [mem_chk " -system_mem -shm_key 1 "] == 1 } {
+			break
+		} else {
+			append envargs " -system_mem -shm_key 1 "
+			set largs [lreplace $largs $sindex $sindex]
 		}
 	}
+
+	# Test for -thread option and pass to berkdb_env open.  Leave in
+	# $largs because -thread can also be passed to an individual
+	# test as an arg.  Double the number of lockers because a threaded
+	# env requires more than an ordinary env.
+	if { [lsearch -exact $largs "-thread"] != -1 } {
+		append envargs " -thread -lock_max_lockers 2000 "
+	}
+
+	# Test for -alloc option and pass to berkdb_env open only.
+	# Remove from largs because -alloc is not an allowed test arg.
+	set aindex [lsearch -exact $largs "-alloc"]
+	if { $aindex >= 0 } {
+		append envargs " -alloc "
+		set largs [lreplace $largs $aindex $aindex]
+	}
+
 	if { $run == 1 } {
 		set is_envmethod 1
-		#
-		# Use an array for number of clients because we really don't
-		# want to evenly-weight all numbers of clients.  Favor smaller
-		# numbers but test more clients occasionally.
-		set drop_list { 0 0 0 0 0 1 1 5 5 10 20 }
-		set drop_len [expr [llength $drop_list] - 1]
-		set client_list { 1 1 2 1 1 1 2 2 3 1 }
-		set cl_len [expr [llength $client_list] - 1]
 		set stat [catch {
-			for { set i $start } { $i <= $stopsdb } {incr i} {
-				if { $numcl == 0 } {
-					set clindex [berkdb random_int 0 $cl_len]
-					set nclients [lindex $client_list $clindex]
-				} else {
-					set nclients $numcl
-				}
-				set drindex [berkdb random_int 0 $drop_len]
-				set droppct [lindex $drop_list $drindex]
-	 			set do_sec [berkdb random_int 0 1]
-				set do_oob [berkdb random_int 0 1]
-	 			set do_del [berkdb random_int 0 1]
-
-				if { $do_sec } {
-					set envargs "-encryptaes $passwd"
-					append largs " -encrypt "
-				} else {
-					set envargs ""
-				}
-				check_handles
-				#
-				# This will set up the master and client envs
-				# and will return us the args to pass to the
-				# test.
-				set largs [repl_envsetup $envargs $largs \
-				    $i $nclients $droppct $do_oob]
-
-				puts "[timestamp]"
-				set name [format "subdb%03d" $i]
-				if { [info exists parms($name)] != 1 } {
-					puts stderr "[format Subdb%03d $i] \
-					    disabled in\
-					    testparams.tcl; skipping."
-					continue
-				}
-				puts -nonewline "Repl: $name: dropping $droppct%, \
-				    $nclients clients "
-				if { $do_del } {
-					puts -nonewline " with delete verification;"
-				} else {
-					puts -nonewline " no delete verification;"
-				}
-				if { $do_sec } {
-					puts -nonewline " with security;"
-				} else {
-					puts -nonewline " no security;"
-				}
-				if { $do_oob } {
-					puts -nonewline " with out-of-order msgs;"
-				} else {
-					puts -nonewline " no out-of-order msgs;"
-				}
-				puts ""
-
-				eval $name $method $parms($name) $largs
-
-				if { $__debug_print != 0 } {
-					puts ""
-				}
-				if { $__debug_on != 0 } {
-					debug $__debug_test
-				}
-				flush stdout
-				flush stderr
-				repl_envprocq $i $nclients $do_oob
-				repl_envver0 $i $method $nclients
-				if { $do_del } {
-					repl_verdel $i $method $nclients
-				}
-				repl_envclose $i $envargs
-				set largs $save_largs
-			}
-		} res]
-		if { $stat != 0} {
-			global errorInfo;
+			check_handles
+			set env [eval {berkdb_env -create -txn \
+			    -mode 0644 -home $testdir} $envargs]
+			error_check_good env_open [is_valid_env $env] TRUE
+			append largs " -env $env "
 
-			set fnl [string first "\n" $errorInfo]
-			set theError [string range $errorInfo 0 [expr $fnl - 1]]
-			if {[string first FAIL $errorInfo] == -1} {
-				error "FAIL:[timestamp]\
-				    run_repmethod: $method $i: $theError"
-			} else {
-				error $theError;
+			puts "[timestamp]"
+			if { [info exists parms($test)] != 1 } {
+				puts stderr "$test disabled in\
+				    testparams.tcl; skipping."
+				continue
 			}
-		}
-		set stat [catch {
-			for { set i $start } { $i <= $stop } {incr i} {
-				if { $numcl == 0 } {
-					set clindex [berkdb random_int 0 $cl_len]
-					set nclients [lindex $client_list $clindex]
-				} else {
-					set nclients $numcl
-				}
-				set drindex [berkdb random_int 0 $drop_len]
-				set droppct [lindex $drop_list $drindex]
-				set do_sec [berkdb random_int 0 1]
-				set do_oob [berkdb random_int 0 1]
-				set do_del [berkdb random_int 0 1]
-
-				if { $do_sec } {
-					set envargs "-encryptaes $passwd"
-					append largs " -encrypt "
-				} else {
-					set envargs ""
-				}
-				check_handles
-				#
-				# This will set up the master and client envs
-				# and will return us the args to pass to the
-				# test.
-				set largs [repl_envsetup $envargs $largs \
-				    $i $nclients $droppct $do_oob]
+			eval $test $method $parms($test) $largs
 
-				puts "[timestamp]"
-				set name [format "test%03d" $i]
-				if { [info exists parms($name)] != 1 } {
-					puts stderr "[format Test%03d $i] \
-					    disabled in\
-					    testparams.tcl; skipping."
-					continue
-				}
-				puts -nonewline "Repl: $name: dropping $droppct%, \
-				    $nclients clients "
-				if { $do_del } {
-					puts -nonewline " with delete verification;"
-				} else {
-					puts -nonewline " no delete verification;"
-				}
-				if { $do_sec } {
-					puts -nonewline " with security;"
-				} else {
-					puts -nonewline " no security;"
-				}
-				if { $do_oob } {
-					puts -nonewline " with out-of-order msgs;"
-				} else {
-					puts -nonewline " no out-of-order msgs;"
-				}
+			if { $__debug_print != 0 } {
 				puts ""
-
-				eval $name $method $parms($name) $largs
-
-				if { $__debug_print != 0 } {
-					puts ""
-				}
-				if { $__debug_on != 0 } {
-					debug $__debug_test
-				}
-				flush stdout
-				flush stderr
-				repl_envprocq $i $nclients $do_oob
-				repl_envver0 $i $method $nclients
-				if { $do_del } {
-					repl_verdel $i $method $nclients
-				}
-				repl_envclose $i $envargs
-				set largs $save_largs
 			}
-		} res]
-		if { $stat != 0} {
-			global errorInfo;
-
-			set fnl [string first "\n" $errorInfo]
-			set theError [string range $errorInfo 0 [expr $fnl - 1]]
-			if {[string first FAIL $errorInfo] == -1} {
-				error "FAIL:[timestamp]\
-				    run_repmethod: $method $i: $theError"
-			} else {
-				error $theError;
-			}
-		}
-		set is_envmethod 0
-	}
-}
-
-#
-# Run method tests, each in its own, new environment.  (As opposed to
-# run_envmethod1 which runs all the tests in a single environment.)
-#
-proc run_envmethod { method {start 1} {stop 0} {display 0} {run 1} \
-    {outfile stdout }  { largs "" } } {
-	global __debug_on
-	global __debug_print
-	global __debug_test
-	global is_envmethod
-	global num_test
-	global parms
-	source ./include.tcl
-
-	set stopsdb $num_test(sdb)
-	if { $stop == 0 } {
-		set stop $num_test(test)
-	} else {
-		if { $stopsdb > $stop } {
-			set stopsdb $stop
-		}
-	}
-
-	set save_largs $largs
-	env_cleanup $testdir
-
-	if { $display == 1 } {
-		for { set i $start } { $i <= $stop } { incr i } {
-			puts $outfile "eval run_envmethod $method \
-			    $i $i 0 1 stdout $largs"
-		}
-	}
-
-	if { $run == 1 } {
-		set is_envmethod 1
-		#
-		# Run both subdb and normal tests for as long as there are
-		# some of each type.  Start with the subdbs:
-		set stat [catch {
-			for { set i $start } { $i <= $stopsdb } {incr i} {
-				check_handles
-				set env [eval {berkdb_env -create -txn \
-				    -mode 0644 -home $testdir}]
-				error_check_good env_open \
-				    [is_valid_env $env] TRUE
-				append largs " -env $env "
-
-				puts "[timestamp]"
-				set name [format "subdb%03d" $i]
-				if { [info exists parms($name)] != 1 } {
-					puts stderr \
-					    "[format Subdb%03d $i] disabled in\
-				    	    testparams.tcl; skipping."
-					continue
-				}
-				eval $name $method $parms($name) $largs
-
-				error_check_good envclose [$env close] 0
-				error_check_good envremove [berkdb envremove \
-				    -home $testdir] 0
-				flush stdout
-				flush stderr
-				set largs $save_largs
-			}
-		} res]
-		if { $stat != 0} {
-			global errorInfo;
-
-			set fnl [string first "\n" $errorInfo]
-			set theError [string range $errorInfo 0 [expr $fnl - 1]]
-			if {[string first FAIL $errorInfo] == -1} {
-				error "FAIL:[timestamp]\
-				    run_envmethod: $method $i: $theError"
-			} else {
-			error $theError;
-			}
-		}
-		# Subdb tests are done, now run through the regular tests:
-		set stat [catch {
-			for { set i $start } { $i <= $stop } {incr i} {
-				check_handles
-				set env [eval {berkdb_env -create -txn \
-				    -mode 0644 -home $testdir}]
-				error_check_good env_open \
-				    [is_valid_env $env] TRUE
-				append largs " -env $env "
-
-				puts "[timestamp]"
-				set name [format "test%03d" $i]
-				if { [info exists parms($name)] != 1 } {
-					puts stderr \
-					    "[format Test%03d $i] disabled in\
-					    testparams.tcl; skipping."
-					continue
-				}
-				eval $name $method $parms($name) $largs
-
-				if { $__debug_print != 0 } {
-					puts ""
-				}
-				if { $__debug_on != 0 } {
-					debug $__debug_test
-				}
-				flush stdout
-				flush stderr
-				set largs $save_largs
-				error_check_good envclose [$env close] 0
-				error_check_good envremove [berkdb envremove \
-				    -home $testdir] 0
+			if { $__debug_on != 0 } {
+				debug $__debug_test
 			}
+			flush stdout
+			flush stderr
+			set largs $save_largs
+			error_check_good envclose [$env close] 0
+			error_check_good envremove [berkdb envremove \
+			    -home $testdir] 0
 		} res]
 		if { $stat != 0} {
 			global errorInfo;
@@ -1367,7 +1276,7 @@ proc run_envmethod { method {start 1} {stop 0} {display 0} {run 1} \
 			set theError [string range $errorInfo 0 [expr $fnl - 1]]
 			if {[string first FAIL $errorInfo] == -1} {
 				error "FAIL:[timestamp]\
-				    run_envmethod: $method $i: $theError"
+				    run_envmethod: $method $test: $theError"
 			} else {
 				error $theError;
 			}
@@ -1376,90 +1285,62 @@ proc run_envmethod { method {start 1} {stop 0} {display 0} {run 1} \
 	}
 }
 
-proc subdb { method {start 1} {stop 0} {display 0} {run 1} \
-    {outfile stdout} args} {
-	global num_test testdir
-	global parms
-
-	for { set i $start } { $i <= $stop } {incr i} {
-		set name [format "subdb%03d" $i]
-		if { [info exists parms($name)] != 1 } {
-			puts stderr "[format Subdb%03d $i] disabled in\
-			    testparams.tcl; skipping."
-			continue
-		}
-		if { $display } {
-			puts -nonewline $outfile "eval $name $method"
-			puts -nonewline $outfile " $parms($name) $args;"
-			puts $outfile "verify_dir $testdir \"\" 1"
-		}
-		if { $run } {
-			check_handles $outfile
-			eval $name $method $parms($name) $args
-			verify_dir $testdir "" 1
-		}
-		flush stdout
-		flush stderr
-	}
-}
-
-proc run_recd { method {start 1} {stop 0} {run 1} {display 0} args } {
+proc run_recd { method test {run 1} {display 0} args } {
 	global __debug_on
 	global __debug_print
 	global __debug_test
 	global parms
-	global num_test
+	global test_names
 	global log_log_record_types
+	global gen_upgrade_log
+	global upgrade_be
+	global upgrade_dir
+	global upgrade_method
+	global upgrade_name
 	source ./include.tcl
 
-	if { $stop == 0 } {
-		set stop $num_test(recd)
-	}
 	if { $run == 1 } {
-		puts "run_recd: $method $start $stop $args"
+		puts "run_recd: $method $test $parms($test) $args"
 	}
-
 	if {[catch {
-		for { set i $start } { $i <= $stop } {incr i} {
-			set name [format "recd%03d" $i]
-			if { [info exists parms($name)] != 1 } {
-				puts stderr "[format Recd%03d $i] disabled in\
-				    testparams.tcl; skipping."
-				continue
-			}
-			if { $display } {
-				puts "eval $name $method $parms($name) $args"
+		if { $display } {
+			puts "eval $test $method $parms($test) $args"
+		}
+		if { $run } {
+			check_handles
+			set upgrade_method $method
+			set upgrade_name $test
+			puts "[timestamp]"
+			# By redirecting stdout to stdout, we make exec
+			# print output rather than simply returning it.
+			# By redirecting stderr to stdout too, we make
+			# sure everything winds up in the ALL.OUT file.
+			set ret [catch { exec $tclsh_path << \
+			    "source $test_path/test.tcl; \
+			    set log_log_record_types $log_log_record_types;\
+			    set gen_upgrade_log $gen_upgrade_log;\
+			    set upgrade_be $upgrade_be; \
+			    set upgrade_dir $upgrade_dir; \
+			    set upgrade_method $upgrade_method; \
+			    set upgrade_name $upgrade_name; \
+			    eval $test $method $parms($test) $args" \
+			    >&@ stdout
+			} res]
+
+			# Don't die if the test failed;  we want
+			# to just proceed.
+			if { $ret != 0 } {
+				puts "FAIL:[timestamp] $res"
 			}
-			if { $run } {
-				check_handles
-				puts "[timestamp]"
-				# By redirecting stdout to stdout, we make exec
-				# print output rather than simply returning it.
-				# By redirecting stderr to stdout too, we make
-				# sure everything winds up in the ALL.OUT file.
-				set ret [catch { exec $tclsh_path << \
-				    "source $test_path/test.tcl; \
-				    set log_log_record_types \
-				    $log_log_record_types; eval $name \
-				    $method $parms($name) $args" \
-				    >&@ stdout
-				} res]
-
-				# Don't die if the test failed;  we want
-				# to just proceed.
-				if { $ret != 0 } {
-					puts "FAIL:[timestamp] $res"
-				}
 
-				if { $__debug_print != 0 } {
-					puts ""
-				}
-				if { $__debug_on != 0 } {
-					debug $__debug_test
-				}
-				flush stdout
-				flush stderr
+			if { $__debug_print != 0 } {
+				puts ""
 			}
+			if { $__debug_on != 0 } {
+				debug $__debug_test
+			}
+			flush stdout
+			flush stderr
 		}
 	} res] != 0} {
 		global errorInfo;
@@ -1468,7 +1349,7 @@ proc run_recd { method {start 1} {stop 0} {run 1} {display 0} args } {
 		set theError [string range $errorInfo 0 [expr $fnl - 1]]
 		if {[string first FAIL $errorInfo] == -1} {
 			error "FAIL:[timestamp]\
-			    run_recd: $method $i: $theError"
+			    run_recd: $method: $theError"
 		} else {
 			error $theError;
 		}
@@ -1476,30 +1357,66 @@ proc run_recd { method {start 1} {stop 0} {run 1} {display 0} args } {
 }
 
 proc run_recds { {run 1} {display 0} args } {
+	source ./include.tcl
 	global log_log_record_types
+	global test_names
+	global gen_upgrade_log
+	global encrypt
 
 	set log_log_record_types 1
 	logtrack_init
+
 	foreach method \
 	    "btree rbtree hash queue queueext recno frecno rrecno" {
 		check_handles
-		if { [catch {eval \
-		    run_recd -$method 1 0 $run $display $args} ret ] != 0 } {
-			puts $ret
+#set test_names(recd) "recd005 recd017"
+		foreach test $test_names(recd) {
+			# Skip recd017 for non-crypto upgrade testing.
+			# Run only recd017 for crypto upgrade testing.
+			if { $gen_upgrade_log == 1 && $test == "recd017" && \
+			    $encrypt == 0 } {
+				puts "Skipping recd017 for non-crypto run."
+				continue
+			}
+			if { $gen_upgrade_log == 1 && $test != "recd017" && \
+			    $encrypt == 1 } {
+				puts "Skipping $test for crypto run."
+				continue
+			}
+			if { [catch {eval \
+			    run_recd $method $test $run $display \
+			    $args} ret ] != 0 } {
+				puts $ret
+			}
+			if { $gen_upgrade_log == 1 } {
+				save_upgrade_files $testdir
+			}
 		}
 	}
+	# We can skip logtrack_summary during the crypto upgrade run -
+	# it doesn't introduce any new log types.
 	if { $run } {
-		logtrack_summary
+		if { $gen_upgrade_log == 0 || $encrypt == 0 } {
+			logtrack_summary
+		}
 	}
 	set log_log_record_types 0
 }
 
-proc run_all { args } {
-	global num_test
+proc run_all { { testname ALL } args } {
+	global test_names
+	global one_test
+	global has_crypto
 	source ./include.tcl
 
 	fileremove -f ALL.OUT
 
+	set one_test $testname
+	if { $one_test != "ALL" } {
+		# Source testparams again to adjust test_names.
+		source $test_path/testparams.tcl
+	}
+
 	set exflgs [eval extractflags $args]
 	set flags [lindex $exflgs 1]
 	set display 1
@@ -1538,7 +1455,7 @@ proc run_all { args } {
 	# print out start/end times.
 	#
 	lappend args -A
-	eval {run_std} $args
+	eval {run_std} $one_test $args
 
 	set test_pagesizes [get_test_pagesizes]
 	set args [lindex $exflgs 0]
@@ -1575,83 +1492,130 @@ proc run_all { args } {
 		}
 
 		# Access method tests.
-		#
+		# Run subdb tests with varying pagesizes too.
 		# XXX
 		# Broken up into separate tclsh instantiations so
 		# we don't require so much memory.
-		foreach i \
+		foreach method \
 		   "btree rbtree hash queue queueext recno frecno rrecno" {
-			puts "Running $i tests with pagesize $pgsz"
-			for { set j 1 } { $j <= $num_test(test) } {incr j} {
+			puts "Running $method tests with pagesize $pgsz"
+			foreach sub {test sdb} {
+				foreach test $test_names($sub) {
+					if { $run == 0 } {
+						set o [open ALL.OUT a]
+						eval {run_method -$method \
+						    $test $display $run $o} \
+						    $args
+						close $o
+					}
+					if { $run } {
+						if [catch {exec $tclsh_path << \
+						    "global one_test; \
+						    set one_test $one_test; \
+						    source $test_path/test.tcl; \
+						    eval {run_method -$method \
+						    $test $display $run \
+						    stdout} $args" \
+						    >>& ALL.OUT } res] {
+							set o [open ALL.OUT a]
+							puts $o "FAIL: \
+							    -$method $test: $res"
+							close $o
+						}
+					}
+				}
+			}
+		}
+	}
+	set args $save_args
+	#
+	# Run access method tests at default page size in one env.
+	#
+	foreach method "btree rbtree hash queue queueext recno frecno rrecno" {
+		puts "Running $method tests in a txn env"
+		foreach sub {test sdb} {
+			foreach test $test_names($sub) {
 				if { $run == 0 } {
 					set o [open ALL.OUT a]
-					eval {run_method -$i $j $j $display \
-					    $run $o} $args
+					run_envmethod -$method $test $display \
+					    $run $o $args
 					close $o
 				}
 				if { $run } {
-					if [catch {exec $tclsh_path \
-					    << "source $test_path/test.tcl; \
-					    eval {run_method -$i $j $j \
-					    $display $run stdout} $args" \
+					if [catch {exec $tclsh_path << \
+					    "global one_test; \
+					    set one_test $one_test; \
+					    source $test_path/test.tcl; \
+					    run_envmethod -$method $test \
+				  	    $display $run stdout $args" \
 					    >>& ALL.OUT } res] {
 						set o [open ALL.OUT a]
-						puts $o \
-						    "FAIL: [format \
-						    "test%03d" $j] $i"
+						puts $o "FAIL: run_envmethod \
+						    $method $test: $res"
 						close $o
 					}
 				}
 			}
-
-			#
-			# Run subdb tests with varying pagesizes too.
-			#
-			for { set j 1 } { $j <= $num_test(sdb) } {incr j} {
+		}
+	}
+	#
+	# Run access method tests at default page size in thread-enabled env.
+	# We're not truly running threaded tests, just testing the interface.
+	#
+	foreach method "btree rbtree hash queue queueext recno frecno rrecno" {
+		puts "Running $method tests in a threaded txn env"
+		foreach sub {test sdb} {
+			foreach test $test_names($sub) {
 				if { $run == 0 } {
 					set o [open ALL.OUT a]
-					eval {subdb -$i $j $j $display \
-					    $run $o} $args
+					eval {run_envmethod -$method $test \
+					    $display $run $o -thread}
 					close $o
 				}
-				if { $run == 1 } {
-					if [catch {exec $tclsh_path \
-					    << "source $test_path/test.tcl; \
-					    eval {subdb -$i $j $j $display \
-					    $run stdout} $args" \
+				if { $run } {
+					if [catch {exec $tclsh_path << \
+					    "global one_test; \
+					    set one_test $one_test; \
+					    source $test_path/test.tcl; \
+					    eval {run_envmethod -$method $test \
+				  	    $display $run stdout -thread}" \
 					    >>& ALL.OUT } res] {
 						set o [open ALL.OUT a]
-						puts $o "FAIL: subdb -$i $j $j"
+						puts $o "FAIL: run_envmethod \
+						    $method $test -thread: $res"
 						close $o
 					}
 				}
 			}
 		}
 	}
-	set args $save_args
 	#
-	# Run access method tests at default page size in one env.
+	# Run access method tests at default page size with -alloc enabled.
 	#
-	foreach i "btree rbtree hash queue queueext recno frecno rrecno" {
-		puts "Running $i tests in a txn env"
-		for { set j 1 } { $j <= $num_test(test) } { incr j } {
-			if { $run == 0 } {
-				set o [open ALL.OUT a]
-				run_envmethod -$i $j $j $display \
-				    $run $o $args
-				close $o
-			}
-			if { $run } {
-				if [catch {exec $tclsh_path \
-				    << "source $test_path/test.tcl; \
-				    run_envmethod -$i $j $j \
-			  	    $display $run stdout $args" \
-				    >>& ALL.OUT } res] {
+	foreach method "btree rbtree hash queue queueext recno frecno rrecno" {
+		puts "Running $method tests in an env with -alloc"
+		foreach sub {test sdb} {
+			foreach test $test_names($sub) {
+				if { $run == 0 } {
 					set o [open ALL.OUT a]
-					puts $o \
-					    "FAIL: run_envmethod $i $j $j"
+					eval {run_envmethod -$method $test \
+					    $display $run $o -alloc}
 					close $o
 				}
+				if { $run } {
+					if [catch {exec $tclsh_path << \
+					    "global one_test; \
+					    set one_test $one_test; \
+					    source $test_path/test.tcl; \
+					    eval {run_envmethod -$method $test \
+				  	    $display $run stdout -alloc}" \
+					    >>& ALL.OUT } res] {
+						set o [open ALL.OUT a]
+						puts $o "FAIL: run_envmethod \
+						    $method $test -alloc: $res"
+						close $o
+					}
+				}
 			}
 		}
 	}
@@ -1659,9 +1623,12 @@ proc run_all { args } {
 	# Run tests using proc r.  The replication tests have been
 	# moved from run_std to run_all.
 	#
-	set test_list {
-	{"replication"	"rep"}
-	{"security"	"sec"}
+	set test_list [list {"replication"	"rep"}]
+	#
+	# If release supports encryption, run security tests.
+	#
+	if { $has_crypto == 1 } {
+		lappend test_list {"security"	"sec"}
 	}
 	#
 	# If configured for RPC, then run rpc tests too.
@@ -1669,18 +1636,19 @@ proc run_all { args } {
 	if { [file exists ./berkeley_db_svc] ||
 	     [file exists ./berkeley_db_cxxsvc] ||
 	     [file exists ./berkeley_db_javasvc] } {
-		append test_list {{"RPC"	"rpc"}}
+		lappend test_list {"RPC"	"rpc"}
 	}
 
 	foreach pair $test_list {
 		set msg [lindex $pair 0]
 		set cmd [lindex $pair 1]
 		puts "Running $msg tests"
-		if [catch {exec $tclsh_path \
-		    << "source $test_path/test.tcl; \
+		if [catch {exec $tclsh_path << \
+		    "global one_test; set one_test $one_test; \
+		    source $test_path/test.tcl; \
 		    r $rflags $cmd $args" >>& ALL.OUT } res] {
 			set o [open ALL.OUT a]
-			puts $o "FAIL: $cmd test"
+			puts $o "FAIL: $cmd test: $res"
 			close $o
 		}
 	}
@@ -1718,26 +1686,17 @@ proc run_all { args } {
 # Run method tests in one environment.  (As opposed to run_envmethod
 # which runs each test in its own, new environment.)
 #
-proc run_envmethod1 { method {start 1} {stop 0} {display 0} {run 1} \
-    { outfile stdout } args } {
+proc run_envmethod1 { method {display 0} {run 1} { outfile stdout } args } {
 	global __debug_on
 	global __debug_print
 	global __debug_test
 	global is_envmethod
-	global num_test
+	global test_names
 	global parms
 	source ./include.tcl
 
-	set stopsdb $num_test(sdb)
-	if { $stop == 0 } {
-		set stop $num_test(test)
-	} else {
-		if { $stopsdb > $stop } {
-			set stopsdb $stop
-		}
-	}
 	if { $run == 1 } {
-		puts "run_envmethod1: $method $start $stop $args"
+		puts "run_envmethod1: $method $args"
 	}
 
 	set is_envmethod 1
@@ -1758,16 +1717,15 @@ proc run_envmethod1 { method {start 1} {stop 0} {display 0} {run 1} \
 	}
 
 	set stat [catch {
-		for { set i $start } { $i <= $stopsdb } {incr i} {
-			set name [format "subdb%03d" $i]
-			if { [info exists parms($name)] != 1 } {
-				puts stderr "[format Subdb%03d $i] disabled in\
+		foreach test $test_names(test) {
+			if { [info exists parms($test)] != 1 } {
+				puts stderr "$test disabled in\
 				    testparams.tcl; skipping."
 				continue
 			}
 			if { $run } {
 				puts $outfile "[timestamp]"
-				eval $name $method $parms($name) $largs
+				eval $test $method $parms($test) $largs
 				if { $__debug_print != 0 } {
 					puts $outfile ""
 				}
@@ -1786,22 +1744,21 @@ proc run_envmethod1 { method {start 1} {stop 0} {display 0} {run 1} \
 		set theError [string range $errorInfo 0 [expr $fnl - 1]]
 		if {[string first FAIL $errorInfo] == -1} {
 			error "FAIL:[timestamp]\
-			    run_envmethod: $method $i: $theError"
+			    run_envmethod: $method $test: $theError"
 		} else {
 			error $theError;
 		}
 	}
 	set stat [catch {
-		for { set i $start } { $i <= $stop } {incr i} {
-			set name [format "test%03d" $i]
-			if { [info exists parms($name)] != 1 } {
-				puts stderr "[format Test%03d $i] disabled in\
+		foreach test $test_names(test) {
+			if { [info exists parms($test)] != 1 } {
+				puts stderr "$test disabled in\
 				    testparams.tcl; skipping."
 				continue
 			}
 			if { $run } {
 				puts $outfile "[timestamp]"
-				eval $name $method $parms($name) $largs
+				eval $test $method $parms($test) $largs
 				if { $__debug_print != 0 } {
 					puts $outfile ""
 				}
@@ -1820,7 +1777,7 @@ proc run_envmethod1 { method {start 1} {stop 0} {display 0} {run 1} \
 		set theError [string range $errorInfo 0 [expr $fnl - 1]]
 		if {[string first FAIL $errorInfo] == -1} {
 			error "FAIL:[timestamp]\
-			    run_envmethod1: $method $i: $theError"
+			    run_envmethod1: $method $test: $theError"
 		} else {
 			error $theError;
 		}
@@ -1833,6 +1790,127 @@ proc run_envmethod1 { method {start 1} {stop 0} {display 0} {run 1} \
 
 }
 
+# Run the secondary index tests.
+proc sindex { {display 0} {run 1} {outfile stdout} {verbose 0} args } {
+	global test_names
+	global testdir
+	global verbose_check_secondaries
+	set verbose_check_secondaries $verbose
+	# Standard number of secondary indices to create if a single-element
+	# list of methods is passed into the secondary index tests.
+	global nsecondaries
+	set nsecondaries 2
+
+	# Run basic tests with a single secondary index and a small number
+	# of keys, then again with a larger number of keys.  (Note that
+	# we can't go above 5000, since we use two items from our
+	# 10K-word list for each key/data pair.)
+	foreach n { 200 5000 } {
+		foreach pm { btree hash recno frecno queue queueext } {
+			foreach sm { dbtree dhash ddbtree ddhash btree hash } {
+				foreach test $test_names(si) {
+					if { $display } {
+						puts -nonewline $outfile \
+						    "eval $test {\[list\
+						    $pm $sm $sm\]} $n ;"
+						puts $outfile " verify_dir \
+						    $testdir \"\" 1"
+					}
+					if { $run } {
+			 			check_handles $outfile
+						eval $test \
+						    {[list $pm $sm $sm]} $n
+						verify_dir $testdir "" 1
+					}
+				}
+			}
+		}
+	}
+
+	# Run tests with 20 secondaries.
+	foreach pm { btree hash } {
+		set methlist [list $pm]
+		for { set j 1 } { $j <= 20 } {incr j} {
+			# XXX this should incorporate hash after #3726
+			if { $j % 2 == 0 } {
+				lappend methlist "dbtree"
+			} else {
+				lappend methlist "ddbtree"
+			}
+		}
+		foreach test $test_names(si) {
+			if { $display } {
+				puts "eval $test {\[list $methlist\]} 500"
+			}
+			if { $run } {
+				eval $test {$methlist} 500
+			}
+		}
+	}
+}
+
+# Run secondary index join test.  (There's no point in running
+# this with both lengths, the primary is unhappy for now with fixed-
+# length records (XXX), and we need unsorted dups in the secondaries.)
+proc sijoin { {display 0} {run 1} {outfile stdout} } {
+	foreach pm { btree hash recno } {
+		if { $display } {
+			foreach sm { btree hash } {
+				puts $outfile "eval sijointest\
+				    {\[list $pm $sm $sm\]} 1000"
+			}
+			puts $outfile "eval sijointest\
+			    {\[list $pm btree hash\]} 1000"
+			puts $outfile "eval sijointest\
+			    {\[list $pm hash btree\]} 1000"
+		}
+		if { $run } {
+			foreach sm { btree hash } {
+				eval sijointest {[list $pm $sm $sm]} 1000
+			}
+			eval sijointest {[list $pm btree hash]} 1000
+			eval sijointest {[list $pm hash btree]} 1000
+		}
+	}
+}
+
+proc run { proc_suffix method {start 1} {stop 999} } {
+	global test_names
+
+	switch -exact -- $proc_suffix {
+		envmethod -
+		method -
+		recd -
+		repmethod -
+		reptest -
+		secenv -
+		secmethod {
+			# Run_recd runs the recd tests, all others
+			# run the "testxxx" tests.
+			if { $proc_suffix == "recd" } {
+				set testtype recd
+			} else {
+				set testtype test
+			}
+
+			for { set i $start } { $i <= $stop } { incr i } {
+				set name [format "%s%03d" $testtype $i]
+				# If a test number is missing, silently skip
+				# to next test; sparse numbering is allowed.
+				if { [lsearch -exact $test_names($testtype) \
+				    $name] == -1 } {
+					continue
+				}
+				run_$proc_suffix $method $name
+			}
+		}
+		default {
+			puts "$proc_suffix is not set up with to be used with run"
+		}
+	}
+}
+
+
 # We want to test all of 512b, 8Kb, and 64Kb pages, but chances are one
 # of these is the default pagesize.  We don't want to run all the AM tests
 # twice, so figure out what the default page size is, then return the
@@ -1854,10 +1932,10 @@ proc get_test_pagesizes { } {
 
 	error_check_bad gtp_pgsz $pgsz 0
 	switch $pgsz {
-		512 { return {8192 32768} }
-		8192 { return {512 32768} }
-		32768 { return {512 8192} }
-		default { return {512 8192 32768} }
+		512 { return {8192 65536} }
+		8192 { return {512 65536} }
+		65536 { return {512 8192} }
+		default { return {512 8192 65536} }
 	}
 	error_check_good NOTREACHED 0 1
 }
diff --git a/storage/bdb/test/test001.tcl b/storage/bdb/test/test001.tcl
index f0b562bbf24fc32c2e689012d1c59dfda6569678..2d7130fcbbc2bcffb0db482dfb2cecac7f2423e3 100644
--- a/storage/bdb/test/test001.tcl
+++ b/storage/bdb/test/test001.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test001.tcl,v 11.28 2002/08/08 15:38:11 bostic Exp $
+# $Id: test001.tcl,v 11.38 2004/09/22 18:01:06 bostic Exp $
 #
 # TEST	test001
 # TEST	Small keys/data
@@ -16,7 +16,8 @@
 # TEST	Insert each with self as key and data; retrieve each.
 # TEST	After all are entered, retrieve all; compare output to original.
 # TEST	Close file, reopen, do retrieve and re-verify.
-proc test001 { method {nentries 10000} {start 0} {tnum "01"} {noclean 0} args } {
+proc test001 { method {nentries 10000} \
+    {start 0} {skip 0} {tnum "001"} args } {
 	source ./include.tcl
 
 	set args [convert_args $method $args]
@@ -31,11 +32,11 @@ proc test001 { method {nentries 10000} {start 0} {tnum "01"} {noclean 0} args }
 	# the database cache size and using multiple caches.
 	set txnenv 0
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum.db
+		set testfile $testdir/test$tnum.db
 		append args " -cachesize {0 1048576 3} "
 		set env NULL
 	} else {
-		set testfile test0$tnum.db
+		set testfile test$tnum.db
 		incr eindex
 		set env [lindex $args $eindex]
 		set txnenv [is_txnenv $env]
@@ -51,37 +52,30 @@ proc test001 { method {nentries 10000} {start 0} {tnum "01"} {noclean 0} args }
 		}
 		set testdir [get_home $env]
 	}
-	puts "Test0$tnum: $method ($args) $nentries equal key/data pairs"
-	if { $start != 0 } {
-		# Sadly enough, we are using start in two different ways.
-		# In test090, it is used to test really big records numbers
-		# in queue.  In replication, it is used to be able to run
-		# different iterations of this test using different key/data
-		# pairs.  We try to hide all that magic here.
-		puts "\tStarting at $start"
-
-		if { $tnum != 90 } {
-			set did [open $dict]
-			for { set nlines 0 } { [gets $did str] != -1 } \
-			    { incr nlines} {
-			}
-			close $did
-			if { $start + $nentries > $nlines } {
-				set start [expr $nlines - $nentries]
-			}
+	puts "Test$tnum: $method ($args) $nentries equal key/data pairs"
+	set did [open $dict]
+
+	# The "start" variable determines the record number to start
+	# with, if we're using record numbers.  The "skip" variable
+	# determines the dictionary entry to start with.
+	# In normal use, skip will match start.
+
+	puts "\tTest$tnum: Starting at $start with dictionary entry $skip"
+	if { $skip != 0 } {
+		for { set count 0 } { $count < $skip } { incr count } {
+			gets $did str
 		}
 	}
 
 	set t1 $testdir/t1
 	set t2 $testdir/t2
 	set t3 $testdir/t3
-	if { $noclean == 0 } {
-		cleanup $testdir $env
-	}
+	set temp $testdir/temp
+	cleanup $testdir $env
+
 	set db [eval {berkdb_open \
 	     -create -mode 0644} $args $omethod $testfile]
 	error_check_good dbopen [is_valid_db $db] TRUE
-	set did [open $dict]
 
 	set pflags ""
 	set gflags ""
@@ -93,16 +87,9 @@ proc test001 { method {nentries 10000} {start 0} {tnum "01"} {noclean 0} args }
 	} else {
 		set checkfunc test001.check
 	}
-	puts "\tTest0$tnum.a: put/get loop"
+	puts "\tTest$tnum.a: put/get loop"
 	# Here is the loop where we put and get each key/data pair
 	set count 0
-	if { $start != 0 && $tnum != 90 } {
-		# Skip over "start" entries
-		for { set count 0 } { $count < $start } { incr count } {
-			gets $did str
-		}
-		set count 0
-	}
 	while { [gets $did str] != -1 && $count < $nentries } {
 		if { [is_record_based $method] == 1 } {
 			global kvals
@@ -159,7 +146,8 @@ proc test001 { method {nentries 10000} {start 0} {tnum "01"} {noclean 0} args }
 	}
 	# Now we will get each key from the DB and compare the results
 	# to the original.
-	puts "\tTest0$tnum.b: dump file"
+
+	puts "\tTest$tnum.b: dump file"
 	dump_file $db $txn $t1 $checkfunc
 	#
 	# dump_file should just have been "get" calls, so
@@ -173,42 +161,29 @@ proc test001 { method {nentries 10000} {start 0} {tnum "01"} {noclean 0} args }
 	# Now compare the keys to see if they match the dictionary (or ints)
 	if { [is_record_based $method] == 1 } {
 		set oid [open $t2 w]
-		# If this is test 90, we're checking wrap and we really
-		# only added nentries number of items starting at start.
-		# However, if this isn't 90, then we started at start and
-		# added an addition nentries number of items.
-		if { $tnum == 90 } {
-			for {set i 1} {$i <= $nentries} {incr i} {
-				set j [expr $i + $start]
-				if { 0xffffffff > 0 && $j > 0xffffffff } {
-					set j [expr $j - 0x100000000]
-				}
-				if { $j == 0 } {
-					incr i
-					incr j
-				}
-				puts $oid $j
+		for { set i 1 } { $i <= $nentries } { incr i } {
+			set j [expr $i + $start]
+			if { 0xffffffff > 0 && $j > 0xffffffff } {
+				set j [expr $j - 0x100000000]
 			}
-		} else {
-			for { set i 1 } { $i <= $nentries + $start } {incr i} {
-				puts $oid $i
+			if { $j == 0 } {
+				incr i
+				incr j
 			}
+			puts $oid $j
 		}
 		close $oid
 	} else {
-		set q q
-		# We assume that when this is used with start != 0, the
-		# test database accumulates data
-		filehead [expr $nentries + $start] $dict $t2
+		filehead [expr $nentries + $start] $dict $t2 [expr $start + 1]
 	}
-	filesort $t2 $t3
-	file rename -force $t3 $t2
+	filesort $t2 $temp
+	file rename -force $temp $t2
 	filesort $t1 $t3
 
-	error_check_good Test0$tnum:diff($t3,$t2) \
+	error_check_good Test$tnum:diff($t3,$t2) \
 	    [filecmp $t3 $t2] 0
 
-	puts "\tTest0$tnum.c: close, open, and dump file"
+	puts "\tTest$tnum.c: close, open, and dump file"
 	# Now, reopen the file and run the last test again.
 	open_and_dump_file $testfile $env $t1 $checkfunc \
 	    dump_file_direction "-first" "-next"
@@ -216,12 +191,12 @@ proc test001 { method {nentries 10000} {start 0} {tnum "01"} {noclean 0} args }
 		filesort $t1 $t3
 	}
 
-	error_check_good Test0$tnum:diff($t2,$t3) \
+	error_check_good Test$tnum:diff($t2,$t3) \
 	    [filecmp $t2 $t3] 0
 
 	# Now, reopen the file and run the last test again in the
 	# reverse direction.
-	puts "\tTest0$tnum.d: close, open, and dump file in reverse direction"
+	puts "\tTest$tnum.d: close, open, and dump file in reverse direction"
 	open_and_dump_file $testfile $env $t1 $checkfunc \
 	    dump_file_direction "-last" "-prev"
 
@@ -229,7 +204,7 @@ proc test001 { method {nentries 10000} {start 0} {tnum "01"} {noclean 0} args }
 		filesort $t1 $t3
 	}
 
-	error_check_good Test0$tnum:diff($t3,$t2) \
+	error_check_good Test$tnum:diff($t3,$t2) \
 	    [filecmp $t3 $t2] 0
 }
 
diff --git a/storage/bdb/test/test002.tcl b/storage/bdb/test/test002.tcl
index bc28994d6a7e012814c8182b561e8fb50c3c6f74..265f0640ff3c09e1e88f8be07496641d968ee7f7 100644
--- a/storage/bdb/test/test002.tcl
+++ b/storage/bdb/test/test002.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test002.tcl,v 11.19 2002/05/22 15:42:43 sue Exp $
+# $Id: test002.tcl,v 11.21 2004/01/28 03:36:30 bostic Exp $
 #
 # TEST	test002
 # TEST	Small keys/medium data
diff --git a/storage/bdb/test/test003.tcl b/storage/bdb/test/test003.tcl
index c7bfe6c15ad001d3693a2694a5395a4e85a26323..4e9c0125d3cde1a11d4cab7e3d26fded0d5a791d 100644
--- a/storage/bdb/test/test003.tcl
+++ b/storage/bdb/test/test003.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test003.tcl,v 11.25 2002/05/22 18:32:18 sue Exp $
+# $Id: test003.tcl,v 11.28 2004/01/28 03:36:30 bostic Exp $
 #
 # TEST	test003
 # TEST	Small keys/large data
@@ -71,11 +71,6 @@ proc test003 { method args} {
 
 	# Here is the loop where we put and get each key/data pair
 	set file_list [get_file_list]
-	if { $limit } {
-		if { [llength $file_list] > $limit } {
-			set file_list [lrange $file_list 1 $limit]
-		}
-	}
 	set len [llength $file_list]
 	puts "\tTest003.a: put/get loop $len entries"
 	set count 0
diff --git a/storage/bdb/test/test004.tcl b/storage/bdb/test/test004.tcl
index 7bea6f88ecabfec9a28aad8e2162f9fe09b04f0a..598e3eb2299875d3b49a429adc7642a335d16af0 100644
--- a/storage/bdb/test/test004.tcl
+++ b/storage/bdb/test/test004.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test004.tcl,v 11.21 2002/05/22 18:32:35 sue Exp $
+# $Id: test004.tcl,v 11.24 2004/01/28 03:36:30 bostic Exp $
 #
 # TEST	test004
 # TEST	Small keys/medium data
@@ -13,14 +13,14 @@
 # TEST	Check that cursor operations work.  Create a database.
 # TEST	Read through the database sequentially using cursors and
 # TEST	delete each element.
-proc test004 { method {nentries 10000} {reopen 4} {build_only 0} args} {
+proc test004 { method {nentries 10000} {reopen "004"} {build_only 0} args} {
 	source ./include.tcl
 
 	set do_renumber [is_rrecno $method]
 	set args [convert_args $method $args]
 	set omethod [convert_method $method]
 
-	set tnum test00$reopen
+	set tnum test$reopen
 
 	# Create the database and open the dictionary
 	set txnenv 0
@@ -51,7 +51,7 @@ proc test004 { method {nentries 10000} {reopen 4} {build_only 0} args} {
 
 	puts -nonewline "$tnum:\
 	    $method ($args) $nentries delete small key; medium data pairs"
-	if {$reopen == 5} {
+	if {$reopen == "005"} {
 		puts "(with close)"
 	} else {
 		puts ""
@@ -78,7 +78,7 @@ proc test004 { method {nentries 10000} {reopen 4} {build_only 0} args} {
 
 	# Here is the loop where we put and get each key/data pair
 	set kvals ""
-	puts "\tTest00$reopen.a: put/get loop"
+	puts "\tTest$reopen.a: put/get loop"
 	while { [gets $did str] != -1 && $count < $nentries } {
 		if { [is_record_based $method] == 1 } {
 			set key [expr $count + 1]
@@ -110,13 +110,13 @@ proc test004 { method {nentries 10000} {reopen 4} {build_only 0} args} {
 	if { $build_only == 1 } {
 		return $db
 	}
-	if { $reopen == 5 } {
+	if { $reopen == "005" } {
 		error_check_good db_close [$db close] 0
 
 		set db [eval {berkdb_open} $args {$testfile}]
 		error_check_good dbopen [is_valid_db $db] TRUE
 	}
-	puts "\tTest00$reopen.b: get/delete loop"
+	puts "\tTest$reopen.b: get/delete loop"
 	# Now we will get each key from the DB and compare the results
 	# to the original, then delete it.
 	set outf [open $t1 w]
@@ -155,13 +155,13 @@ proc test004 { method {nentries 10000} {reopen 4} {build_only 0} args} {
 
 	# Now compare the keys to see if they match the dictionary
 	if { [is_record_based $method] == 1 } {
-		error_check_good test00$reopen:keys_deleted $count $nentries
+		error_check_good test$reopen:keys_deleted $count $nentries
 	} else {
 		set q q
 		filehead $nentries $dict $t3
 		filesort $t3 $t2
 		filesort $t1 $t3
-		error_check_good Test00$reopen:diff($t3,$t2) \
+		error_check_good Test$reopen:diff($t3,$t2) \
 		    [filecmp $t3 $t2] 0
 	}
 
diff --git a/storage/bdb/test/test005.tcl b/storage/bdb/test/test005.tcl
index f3e37f2149d1465913a06c863361a05cbe4ebf10..e3972b5b1279e11a093efb3f4bfddfd176173943 100644
--- a/storage/bdb/test/test005.tcl
+++ b/storage/bdb/test/test005.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test005.tcl,v 11.7 2002/01/11 15:53:40 bostic Exp $
+# $Id: test005.tcl,v 11.10 2004/01/28 03:36:30 bostic Exp $
 #
 # TEST	test005
 # TEST	Small keys/medium data
@@ -15,5 +15,5 @@
 # TEST	it and reopen it.  Then read through the database sequentially
 # TEST	using cursors and delete each element.
 proc test005 { method {nentries 10000} args } {
-	eval {test004 $method $nentries 5 0} $args
+	eval {test004 $method $nentries "005" 0} $args
 }
diff --git a/storage/bdb/test/test006.tcl b/storage/bdb/test/test006.tcl
index fbaebfe8ac828850293eac56be2dbc04918ab644..4107bbf090cf66ba5596b1c46beeb89f49d6d25b 100644
--- a/storage/bdb/test/test006.tcl
+++ b/storage/bdb/test/test006.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test006.tcl,v 11.19 2002/05/22 15:42:44 sue Exp $
+# $Id: test006.tcl,v 11.26 2004/09/22 18:01:06 bostic Exp $
 #
 # TEST	test006
 # TEST	Small keys/medium data
@@ -13,36 +13,54 @@
 # TEST	Keyed delete test.
 # TEST	Create database.
 # TEST	Go through database, deleting all entries by key.
-proc test006 { method {nentries 10000} {reopen 0} {tnum 6} args} {
+# TEST	Then do the same for unsorted and sorted dups.
+proc test006 { method {nentries 10000} {reopen 0} {tnum "006"} \
+    {ndups 5} args } {
+
+	test006_body $method $nentries $reopen $tnum 1 "" "" $args
+
+	# For methods supporting dups, run the test with sorted and
+	# with unsorted dups.
+	if { [is_btree $method] == 1 || [is_hash $method] == 1 } {
+		foreach {sort flags} {unsorted -dup sorted "-dup -dupsort"} {
+			test006_body $method $nentries $reopen \
+			    $tnum $ndups $sort $flags $args
+		}
+	}
+}
+
+proc test006_body { method {nentries 10000} {reopen 0} {tnum "006"} \
+    {ndups 5} sort flags {largs ""} } {
+	global is_je_test
 	source ./include.tcl
 
 	set do_renumber [is_rrecno $method]
-	set args [convert_args $method $args]
-	set omethod [convert_method $method]
+        set largs [convert_args $method $largs]
+        set omethod [convert_method $method]
+
+	set tname Test$tnum
+	set dbname test$tnum
 
-	if { $tnum < 10 } {
-		set tname Test00$tnum
-		set dbname test00$tnum
-	} else {
-		set tname Test0$tnum
-		set dbname test0$tnum
-	}
 	# Create the database and open the dictionary
 	set txnenv 0
-	set eindex [lsearch -exact $args "-env"]
+	set eindex [lsearch -exact $largs "-env"]
 	#
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/$dbname.db
+		set basename $testdir/$dbname
 		set env NULL
 	} else {
-		set testfile $dbname.db
+		set basename $dbname
 		incr eindex
-		set env [lindex $args $eindex]
+		set env [lindex $largs $eindex]
+		if { $is_je_test && $sort == "unsorted" } {
+			puts "Test$tnum skipping $sort duplicates for JE"
+			return
+		}
 		set txnenv [is_txnenv $env]
 		if { $txnenv == 1 } {
-			append args " -auto_commit "
+			append largs " -auto_commit "
 			#
 			# If we are using txns and running with the
 			# default, set the default down a bit.
@@ -53,7 +71,7 @@ proc test006 { method {nentries 10000} {reopen 0} {tnum 6} args} {
 		}
 		set testdir [get_home $env]
 	}
-	puts -nonewline "$tname: $method ($args) "
+	puts -nonewline "$tname: $method ($flags $largs) "
 	puts -nonewline "$nentries equal small key; medium data pairs"
 	if {$reopen == 1} {
 		puts " (with close)"
@@ -64,87 +82,114 @@ proc test006 { method {nentries 10000} {reopen 0} {tnum 6} args} {
 	set pflags ""
 	set gflags ""
 	set txn ""
-	set count 0
 	if { [is_record_based $method] == 1 } {
 		append gflags " -recno"
 	}
 
-	# Here is the loop where we put and get each key/data pair
-
 	cleanup $testdir $env
-	set db [eval {berkdb_open \
-	    -create -mode 0644} $args {$omethod $testfile}]
+
+	# Here is the loop where we put and get each key/data pair.
+
+	set count 0
+	set testfile $basename$sort.db
+	set db [eval {berkdb_open -create \
+	    -mode 0644} $largs $flags {$omethod $testfile}]
 	error_check_good dbopen [is_valid_db $db] TRUE
 
+	puts "\t$tname.a: put/get loop"
 	set did [open $dict]
 	while { [gets $did str] != -1 && $count < $nentries } {
-		if { [is_record_based $method] == 1 } {
-			set key [expr $count + 1 ]
-		} else {
-			set key $str
-		}
-
-		set datastr [make_data_str $str]
-
-		if { $txnenv == 1 } {
-			set t [$env txn]
-			error_check_good txn [is_valid_txn $t $env] TRUE
-			set txn "-txn $t"
-		}
-		set ret [eval {$db put} \
-		    $txn $pflags {$key [chop_data $method $datastr]}]
-		error_check_good put $ret 0
-		if { $txnenv == 1 } {
-			error_check_good txn [$t commit] 0
+                if { [is_record_based $method] == 1 } {
+                        set key [expr $count + 1 ]
+                } else {
+                        set key $str
+                }
+
+		set str [make_data_str $str]
+		for { set j 1 } { $j <= $ndups } {incr j} {
+			set datastr $j$str
+			if { $txnenv == 1 } {
+	 			set t [$env txn]
+				error_check_good txn \
+				    [is_valid_txn $t $env] TRUE
+				set txn "-txn $t"
+			}
+			set ret [eval {$db put} $txn $pflags \
+			    {$key [chop_data $method $datastr]}]
+			error_check_good put $ret 0
+			if { $txnenv == 1 } {
+				error_check_good txn \
+				    [$t commit] 0
+			}
 		}
-
-		set ret [eval {$db get} $gflags {$key}]
-		error_check_good "$tname: put $datastr got $ret" \
-		    $ret [list [list $key [pad_data $method $datastr]]]
 		incr count
 	}
 	close $did
 
+	# Close and reopen database, if testing reopen.
+
 	if { $reopen == 1 } {
 		error_check_good db_close [$db close] 0
 
-		set db [eval {berkdb_open} $args {$testfile}]
+		set db [eval {berkdb_open} $largs {$testfile}]
 		error_check_good dbopen [is_valid_db $db] TRUE
 	}
 
 	# Now we will get each key from the DB and compare the results
 	# to the original, then delete it.
-	set count 0
-	set did [open $dict]
-	set key 0
-	while { [gets $did str] != -1 && $count < $nentries } {
-		if { $do_renumber == 1 } {
-			set key 1
-		} elseif { [is_record_based $method] == 1 } {
-			incr key
-		} else {
-			set key $str
-		}
 
-		set datastr [make_data_str $str]
-
-		set ret [eval {$db get} $gflags {$key}]
-		error_check_good "$tname: get $datastr got $ret" \
-		    $ret [list [list $key [pad_data $method $datastr]]]
+	puts "\t$tname.b: get/delete loop"
+	if { $txnenv == 1 } {
+		set t [$env txn]
+		error_check_good txn [is_valid_txn $t $env] TRUE
+		set txn "-txn $t"
+	}
+	set dbc [eval {$db cursor} $txn]
+	error_check_good db_cursor [is_substr $dbc $db] 1
+
+	set i 1
+	for { set ret [$dbc get -first] } \
+	    { [string length $ret] != 0 } \
+	    { set ret [$dbc get -next] } {
+		set key [lindex [lindex $ret 0] 0]
+		set data [lindex [lindex $ret 0] 1]
+		if { $i == 1 } {
+			set curkey $key
+		}
+		error_check_good seq_get:key $key $curkey
 
-		if { $txnenv == 1 } {
-			set t [$env txn]
-			error_check_good txn [is_valid_txn $t $env] TRUE
-			set txn "-txn $t"
+		if { $i == $ndups } {
+			set i 1
+		} else {
+			incr i
 		}
-		set ret [eval {$db del} $txn {$key}]
+
+		# Now delete the key
+		set ret [$dbc del]
 		error_check_good db_del:$key $ret 0
-		if { $txnenv == 1 } {
-			error_check_good txn [$t commit] 0
-		}
-		incr count
 	}
-	close $did
-
+	error_check_good dbc_close [$dbc close] 0
+	if { $txnenv == 1 } {
+		error_check_good txn [$t commit] 0
+	}
 	error_check_good db_close [$db close] 0
+
+	puts "\t$tname.c: verify empty file"
+	# Double check that file is now empty
+	set db [eval {berkdb_open} $largs $testfile]
+	error_check_good dbopen [is_valid_db $db] TRUE
+	if { $txnenv == 1 } {
+		set t [$env txn]
+		error_check_good txn [is_valid_txn $t $env] TRUE
+		set txn "-txn $t"
+	}
+	set dbc [eval {$db cursor} $txn]
+	error_check_good db_cursor [is_substr $dbc $db] 1
+	set ret [$dbc get -first]
+	error_check_good get_on_empty [string length $ret] 0
+	error_check_good dbc_close [$dbc close] 0
+	if { $txnenv == 1 } {
+	error_check_good txn [$t commit] 0
+	}
+error_check_good db_close [$db close] 0
 }
diff --git a/storage/bdb/test/test007.tcl b/storage/bdb/test/test007.tcl
index 1e99d107a2df01e45482cf9afd45c95102357629..6cb57495add17ae438ebbf51c00006b46f1cfd30 100644
--- a/storage/bdb/test/test007.tcl
+++ b/storage/bdb/test/test007.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test007.tcl,v 11.8 2002/01/11 15:53:40 bostic Exp $
+# $Id: test007.tcl,v 11.12 2004/01/28 03:36:30 bostic Exp $
 #
 # TEST	test007
 # TEST	Small keys/medium data
@@ -13,7 +13,7 @@
 # TEST
 # TEST	Check that delete operations work.  Create a database; close
 # TEST	database and reopen it.  Then issues delete by key for each
-# TEST	entry.
-proc test007 { method {nentries 10000} {tnum 7} args} {
-	eval {test006 $method $nentries 1 $tnum} $args
+# TEST	entry.  (Test006 plus reopen)
+proc test007 { method {nentries 10000} {tnum "007"} {ndups 5} args} {
+	eval {test006 $method $nentries 1 $tnum $ndups} $args
 }
diff --git a/storage/bdb/test/test008.tcl b/storage/bdb/test/test008.tcl
index 0af97a40110c724808441e7d1a62a6d4f812a55d..d798d3fb22d9f2ab155d1a378a70e7458bc47872 100644
--- a/storage/bdb/test/test008.tcl
+++ b/storage/bdb/test/test008.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test008.tcl,v 11.23 2002/05/22 15:42:45 sue Exp $
+# $Id: test008.tcl,v 11.26 2004/01/28 03:36:30 bostic Exp $
 #
 # TEST	test008
 # TEST	Small keys/large data
@@ -17,20 +17,20 @@
 # TEST	Take the source files and dbtest executable and enter their names as
 # TEST	the key with their contents as data.  After all are entered, begin
 # TEST	looping through the entries; deleting some pairs and then readding them.
-proc test008 { method {reopen 8} {debug 0} args} {
+proc test008 { method {reopen "008"} {debug 0} args} {
 	source ./include.tcl
 
-	set tnum test00$reopen
+	set tnum test$reopen
 	set args [convert_args $method $args]
 	set omethod [convert_method $method]
 
 	if { [is_record_based $method] == 1 } {
-		puts "Test00$reopen skipping for method $method"
+		puts "Test$reopen skipping for method $method"
 		return
 	}
 
 	puts -nonewline "$tnum: $method filename=key filecontents=data pairs"
-	if {$reopen == 9} {
+	if {$reopen == "009"} {
 		puts "(with close)"
 	} else {
 		puts ""
@@ -74,7 +74,7 @@ proc test008 { method {reopen 8} {debug 0} args} {
 	set file_list [get_file_list]
 
 	set count 0
-	puts "\tTest00$reopen.a: Initial put/get loop"
+	puts "\tTest$reopen.a: Initial put/get loop"
 	foreach f $file_list {
 		set names($count) $f
 		set key $f
@@ -99,13 +99,13 @@ proc test008 { method {reopen 8} {debug 0} args} {
 			error_check_good txn [$t commit] 0
 		}
 
-		error_check_good Test00$reopen:diff($f,$t4) \
+		error_check_good Test$reopen:diff($f,$t4) \
 		    [filecmp $f $t4] 0
 
 		incr count
 	}
 
-	if {$reopen == 9} {
+	if {$reopen == "009"} {
 		error_check_good db_close [$db close] 0
 
 		set db [eval {berkdb_open} $args $testfile]
@@ -115,7 +115,7 @@ proc test008 { method {reopen 8} {debug 0} args} {
 	# Now we will get step through keys again (by increments) and
 	# delete all the entries, then re-insert them.
 
-	puts "\tTest00$reopen.b: Delete re-add loop"
+	puts "\tTest$reopen.b: Delete re-add loop"
 	foreach i "1 2 4 8 16" {
 		for {set ndx 0} {$ndx < $count} { incr ndx $i} {
 			if { $txnenv == 1 } {
@@ -142,14 +142,14 @@ proc test008 { method {reopen 8} {debug 0} args} {
 		}
 	}
 
-	if {$reopen == 9} {
+	if {$reopen == "009"} {
 		error_check_good db_close [$db close] 0
 		set db [eval {berkdb_open} $args $testfile]
 		error_check_good dbopen [is_valid_db $db] TRUE
 	}
 
 	# Now, reopen the file and make sure the key/data pairs look right.
-	puts "\tTest00$reopen.c: Dump contents forward"
+	puts "\tTest$reopen.c: Dump contents forward"
 	if { $txnenv == 1 } {
 		set t [$env txn]
 		error_check_good txn [is_valid_txn $t $env] TRUE
@@ -169,11 +169,11 @@ proc test008 { method {reopen 8} {debug 0} args} {
 	fileremove $t2.tmp
 	filesort $t1 $t3
 
-	error_check_good Test00$reopen:diff($t3,$t2) \
+	error_check_good Test$reopen:diff($t3,$t2) \
 	    [filecmp $t3 $t2] 0
 
 	# Now, reopen the file and run the last test again in reverse direction.
-	puts "\tTest00$reopen.d: Dump contents backward"
+	puts "\tTest$reopen.d: Dump contents backward"
 	if { $txnenv == 1 } {
 		set t [$env txn]
 		error_check_good txn [is_valid_txn $t $env] TRUE
@@ -186,7 +186,7 @@ proc test008 { method {reopen 8} {debug 0} args} {
 
 	filesort $t1 $t3
 
-	error_check_good Test00$reopen:diff($t3,$t2) \
+	error_check_good Test$reopen:diff($t3,$t2) \
 	    [filecmp $t3 $t2] 0
 	error_check_good close:$db [$db close] 0
 }
diff --git a/storage/bdb/test/test009.tcl b/storage/bdb/test/test009.tcl
index 7ef46d8c81883a65fae4ae3f684ec3d12d36c975..258b01277ec049f3a0fba378008995b49d360c7b 100644
--- a/storage/bdb/test/test009.tcl
+++ b/storage/bdb/test/test009.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test009.tcl,v 11.8 2002/05/22 15:42:45 sue Exp $
+# $Id: test009.tcl,v 11.11 2004/01/28 03:36:30 bostic Exp $
 #
 # TEST	test009
 # TEST	Small keys/large data
@@ -14,5 +14,5 @@
 # TEST	randomly.  Then close the DB and make sure that we have everything
 # TEST	we think we should.
 proc test009 { method args} {
-	eval {test008 $method 9 0} $args
+	eval {test008 $method "009" 0} $args
 }
diff --git a/storage/bdb/test/test010.tcl b/storage/bdb/test/test010.tcl
index 0b5f5531795a2fcae7fe220758118792530bae07..bbf6fba679f1756898603a70f68aa18e619535dc 100644
--- a/storage/bdb/test/test010.tcl
+++ b/storage/bdb/test/test010.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test010.tcl,v 11.20 2002/06/11 14:09:56 sue Exp $
+# $Id: test010.tcl,v 11.23 2004/01/28 03:36:30 bostic Exp $
 #
 # TEST	test010
 # TEST	Duplicate test
@@ -14,7 +14,7 @@
 # TEST	After all are entered, retrieve all; verify output.
 # TEST	Close file, reopen, do retrieve and re-verify.
 # TEST	This does not work for recno
-proc test010 { method {nentries 10000} {ndups 5} {tnum 10} args } {
+proc test010 { method {nentries 10000} {ndups 5} {tnum "010"} args } {
 	source ./include.tcl
 
 	set omethod $method
@@ -23,7 +23,7 @@ proc test010 { method {nentries 10000} {ndups 5} {tnum 10} args } {
 
 	if { [is_record_based $method] == 1 || \
 	    [is_rbtree $method] == 1 } {
-		puts "Test0$tnum skipping for method $method"
+		puts "Test$tnum skipping for method $method"
 		return
 	}
 
@@ -34,10 +34,10 @@ proc test010 { method {nentries 10000} {ndups 5} {tnum 10} args } {
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum.db
+		set testfile $testdir/test$tnum.db
 		set env NULL
 	} else {
-		set testfile test0$tnum.db
+		set testfile test$tnum.db
 		incr eindex
 		set env [lindex $args $eindex]
 		set txnenv [is_txnenv $env]
@@ -54,7 +54,7 @@ proc test010 { method {nentries 10000} {ndups 5} {tnum 10} args } {
 		}
 		set testdir [get_home $env]
 	}
-	puts "Test0$tnum: $method ($args) $nentries \
+	puts "Test$tnum: $method ($args) $nentries \
 	    small $ndups dup key/data pairs"
 
 	set t1 $testdir/t1
@@ -111,12 +111,12 @@ proc test010 { method {nentries 10000} {ndups 5} {tnum 10} args } {
 			}
 			set datastr [lindex [lindex $ret 0] 1]
 			set d [data_of $datastr]
-			error_check_good "Test0$tnum:get" $d $str
+			error_check_good "Test$tnum:get" $d $str
 			set id [ id_of $datastr ]
-			error_check_good "Test0$tnum:dup#" $id $x
+			error_check_good "Test$tnum:dup#" $id $x
 			incr x
 		}
-		error_check_good "Test0$tnum:ndups:$str" [expr $x - 1] $ndups
+		error_check_good "Test$tnum:ndups:$str" [expr $x - 1] $ndups
 		error_check_good cursor_close [$dbc close] 0
 		if { $txnenv == 1 } {
 			error_check_good txn [$t commit] 0
@@ -128,7 +128,7 @@ proc test010 { method {nentries 10000} {ndups 5} {tnum 10} args } {
 
 	# Now we will get each key from the DB and compare the results
 	# to the original.
-	puts "\tTest0$tnum.a: Checking file for correct duplicates"
+	puts "\tTest$tnum.a: Checking file for correct duplicates"
 	set dlist ""
 	for { set i 1 } { $i <= $ndups } {incr i} {
 		lappend dlist $i
@@ -149,14 +149,14 @@ proc test010 { method {nentries 10000} {ndups 5} {tnum 10} args } {
 	filesort $t3 $t2
 	filesort $t1 $t3
 
-	error_check_good Test0$tnum:diff($t3,$t2) \
+	error_check_good Test$tnum:diff($t3,$t2) \
 	    [filecmp $t3 $t2] 0
 
 	error_check_good db_close [$db close] 0
 	set db [eval {berkdb_open} $args $testfile]
 	error_check_good dbopen [is_valid_db $db] TRUE
 
-	puts "\tTest0$tnum.b: Checking file for correct duplicates after close"
+	puts "\tTest$tnum.b: Checking file for correct duplicates after close"
 	if { $txnenv == 1 } {
 		set t [$env txn]
 		error_check_good txn [is_valid_txn $t $env] TRUE
@@ -169,7 +169,7 @@ proc test010 { method {nentries 10000} {ndups 5} {tnum 10} args } {
 
 	# Now compare the keys to see if they match the dictionary entries
 	filesort $t1 $t3
-	error_check_good Test0$tnum:diff($t3,$t2) \
+	error_check_good Test$tnum:diff($t3,$t2) \
 	    [filecmp $t3 $t2] 0
 
 	error_check_good db_close [$db close] 0
diff --git a/storage/bdb/test/test011.tcl b/storage/bdb/test/test011.tcl
index 63e2203efe455d620ce18e7fe5999fba539107cd..ad8439011c864c9ff525a62f837348643c1992d7 100644
--- a/storage/bdb/test/test011.tcl
+++ b/storage/bdb/test/test011.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test011.tcl,v 11.27 2002/06/11 14:09:56 sue Exp $
+# $Id: test011.tcl,v 11.30 2004/01/28 03:36:30 bostic Exp $
 #
 # TEST	test011
 # TEST	Duplicate test
@@ -18,7 +18,7 @@
 # TEST
 # TEST	To test if dups work when they fall off the main page, run this with
 # TEST	a very tiny page size.
-proc test011 { method {nentries 10000} {ndups 5} {tnum 11} args } {
+proc test011 { method {nentries 10000} {ndups 5} {tnum "011"} args } {
 	global dlist
 	global rand_init
 	source ./include.tcl
@@ -26,7 +26,7 @@ proc test011 { method {nentries 10000} {ndups 5} {tnum 11} args } {
 	set dlist ""
 
 	if { [is_rbtree $method] == 1 } {
-		puts "Test0$tnum skipping for method $method"
+		puts "Test$tnum skipping for method $method"
 		return
 	}
 	if { [is_record_based $method] == 1 } {
@@ -49,10 +49,10 @@ proc test011 { method {nentries 10000} {ndups 5} {tnum 11} args } {
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum.db
+		set testfile $testdir/test$tnum.db
 		set env NULL
 	} else {
-		set testfile test0$tnum.db
+		set testfile test$tnum.db
 		incr eindex
 		set env [lindex $args $eindex]
 		set txnenv [is_txnenv $env]
@@ -70,7 +70,7 @@ proc test011 { method {nentries 10000} {ndups 5} {tnum 11} args } {
 		set testdir [get_home $env]
 	}
 
-	puts -nonewline "Test0$tnum: $method $nentries small $ndups dup "
+	puts -nonewline "Test$tnum: $method $nentries small $ndups dup "
 	puts "key/data pairs, cursor ops"
 
 	set t1 $testdir/t1
@@ -93,7 +93,7 @@ proc test011 { method {nentries 10000} {ndups 5} {tnum 11} args } {
 	# We will add dups with values 1, 3, ... $ndups.  Then we'll add
 	# 0 and $ndups+1 using keyfirst/keylast.  We'll add 2 and 4 using
 	# add before and add after.
-	puts "\tTest0$tnum.a: put and get duplicate keys."
+	puts "\tTest$tnum.a: put and get duplicate keys."
 	set i ""
 	for { set i 1 } { $i <= $ndups } { incr i 2 } {
 		lappend dlist $i
@@ -135,12 +135,12 @@ proc test011 { method {nentries 10000} {ndups 5} {tnum 11} args } {
 			set datastr [lindex [lindex $ret 0] 1]
 			set d [data_of $datastr]
 
-			error_check_good Test0$tnum:put $d $str
+			error_check_good Test$tnum:put $d $str
 			set id [ id_of $datastr ]
-			error_check_good Test0$tnum:dup# $id $x
+			error_check_good Test$tnum:dup# $id $x
 			incr x 2
 		}
-		error_check_good Test0$tnum:numdups $x $maxodd
+		error_check_good Test$tnum:numdups $x $maxodd
 		error_check_good curs_close [$dbc close] 0
 		if { $txnenv == 1 } {
 			error_check_good txn [$t commit] 0
@@ -151,7 +151,7 @@ proc test011 { method {nentries 10000} {ndups 5} {tnum 11} args } {
 
 	# Now we will get each key from the DB and compare the results
 	# to the original.
-	puts "\tTest0$tnum.b: \
+	puts "\tTest$tnum.b: \
 	    traverse entire file checking duplicates before close."
 	if { $txnenv == 1 } {
 		set t [$env txn]
@@ -169,7 +169,7 @@ proc test011 { method {nentries 10000} {ndups 5} {tnum 11} args } {
 	filesort $t3 $t2
 	filesort $t1 $t3
 
-	error_check_good Test0$tnum:diff($t3,$t2) \
+	error_check_good Test$tnum:diff($t3,$t2) \
 	    [filecmp $t3 $t2] 0
 
 	error_check_good db_close [$db close] 0
@@ -177,7 +177,7 @@ proc test011 { method {nentries 10000} {ndups 5} {tnum 11} args } {
 	set db [eval {berkdb_open} $args $testfile]
 	error_check_good dbopen [is_valid_db $db] TRUE
 
-	puts "\tTest0$tnum.c: \
+	puts "\tTest$tnum.c: \
 	    traverse entire file checking duplicates after close."
 	if { $txnenv == 1 } {
 		set t [$env txn]
@@ -191,10 +191,10 @@ proc test011 { method {nentries 10000} {ndups 5} {tnum 11} args } {
 
 	# Now compare the keys to see if they match the dictionary entries
 	filesort $t1 $t3
-	error_check_good Test0$tnum:diff($t3,$t2) \
+	error_check_good Test$tnum:diff($t3,$t2) \
 	    [filecmp $t3 $t2] 0
 
-	puts "\tTest0$tnum.d: Testing key_first functionality"
+	puts "\tTest$tnum.d: Testing key_first functionality"
 	if { $txnenv == 1 } {
 		set t [$env txn]
 		error_check_good txn [is_valid_txn $t $env] TRUE
@@ -207,7 +207,7 @@ proc test011 { method {nentries 10000} {ndups 5} {tnum 11} args } {
 		error_check_good txn [$t commit] 0
 	}
 
-	puts "\tTest0$tnum.e: Testing key_last functionality"
+	puts "\tTest$tnum.e: Testing key_last functionality"
 	if { $txnenv == 1 } {
 		set t [$env txn]
 		error_check_good txn [is_valid_txn $t $env] TRUE
@@ -220,7 +220,7 @@ proc test011 { method {nentries 10000} {ndups 5} {tnum 11} args } {
 		error_check_good txn [$t commit] 0
 	}
 
-	puts "\tTest0$tnum.f: Testing add_before functionality"
+	puts "\tTest$tnum.f: Testing add_before functionality"
 	if { $txnenv == 1 } {
 		set t [$env txn]
 		error_check_good txn [is_valid_txn $t $env] TRUE
@@ -233,7 +233,7 @@ proc test011 { method {nentries 10000} {ndups 5} {tnum 11} args } {
 		error_check_good txn [$t commit] 0
 	}
 
-	puts "\tTest0$tnum.g: Testing add_after functionality"
+	puts "\tTest$tnum.g: Testing add_after functionality"
 	if { $txnenv == 1 } {
 		set t [$env txn]
 		error_check_good txn [is_valid_txn $t $env] TRUE
@@ -277,7 +277,7 @@ proc add_dup {db txn nentries flag dataval iter} {
 	$dbc close
 }
 
-proc test011_recno { method {nentries 10000} {tnum 11} largs } {
+proc test011_recno { method {nentries 10000} {tnum "011"} largs } {
 	global dlist
 	source ./include.tcl
 
@@ -285,7 +285,7 @@ proc test011_recno { method {nentries 10000} {tnum 11} largs } {
 	set omethod [convert_method $method]
 	set renum [is_rrecno $method]
 
-	puts "Test0$tnum: \
+	puts "Test$tnum: \
 	    $method ($largs) $nentries test cursor insert functionality"
 
 	# Create the database and open the dictionary
@@ -295,10 +295,10 @@ proc test011_recno { method {nentries 10000} {tnum 11} largs } {
 	# Otherwise it is the test directory and the name.
 	set txnenv 0
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum.db
+		set testfile $testdir/test$tnum.db
 		set env NULL
 	} else {
-		set testfile test0$tnum.db
+		set testfile test$tnum.db
 		incr eindex
 		set env [lindex $largs $eindex]
 		set txnenv [is_txnenv $env]
@@ -365,7 +365,7 @@ proc test011_recno { method {nentries 10000} {tnum 11} largs } {
 		set txn "-txn $t"
 	}
 	set dbc [eval {$db cursor} $txn]
-	puts "\tTest0$tnum.a: put and get entries"
+	puts "\tTest$tnum.a: put and get entries"
 	while { [gets $did str] != -1 && $count < $nentries } {
 		# Pick a random key
 		set key [berkdb random_int 1 $count]
@@ -433,7 +433,7 @@ proc test011_recno { method {nentries 10000} {tnum 11} largs } {
 	}
 	close $oid
 
-	puts "\tTest0$tnum.b: dump file"
+	puts "\tTest$tnum.b: dump file"
 	if { $txnenv == 1 } {
 		set t [$env txn]
 		error_check_good txn [is_valid_txn $t $env] TRUE
@@ -443,23 +443,23 @@ proc test011_recno { method {nentries 10000} {tnum 11} largs } {
 	if { $txnenv == 1 } {
 		error_check_good txn [$t commit] 0
 	}
-	error_check_good Test0$tnum:diff($t2,$t1) \
+	error_check_good Test$tnum:diff($t2,$t1) \
 	    [filecmp $t2 $t1] 0
 
 	error_check_good db_close [$db close] 0
 
-	puts "\tTest0$tnum.c: close, open, and dump file"
+	puts "\tTest$tnum.c: close, open, and dump file"
 	open_and_dump_file $testfile $env $t1 test011_check \
 	    dump_file_direction "-first" "-next"
-	error_check_good Test0$tnum:diff($t2,$t1) \
+	error_check_good Test$tnum:diff($t2,$t1) \
 	    [filecmp $t2 $t1] 0
 
-	puts "\tTest0$tnum.d: close, open, and dump file in reverse direction"
+	puts "\tTest$tnum.d: close, open, and dump file in reverse direction"
 	open_and_dump_file $testfile $env $t1 test011_check \
 	    dump_file_direction "-last" "-prev"
 
 	filesort $t1 $t3 -n
-	error_check_good Test0$tnum:diff($t2,$t3) \
+	error_check_good Test$tnum:diff($t2,$t3) \
 	    [filecmp $t2 $t3] 0
 }
 
diff --git a/storage/bdb/test/test012.tcl b/storage/bdb/test/test012.tcl
index e7237d27267c0d24c424b388d729684b495b80b8..42225d982cd8b27adbbde5425eb83382224aef84 100644
--- a/storage/bdb/test/test012.tcl
+++ b/storage/bdb/test/test012.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test012.tcl,v 11.20 2002/05/22 15:42:46 sue Exp $
+# $Id: test012.tcl,v 11.22 2004/01/28 03:36:30 bostic Exp $
 #
 # TEST	test012
 # TEST	Large keys/small data
diff --git a/storage/bdb/test/test013.tcl b/storage/bdb/test/test013.tcl
index 96d7757b0d8de88e3db9308346943d829a55f334..e456965bfd94c7e26ebff66155f17a9824ebe1c6 100644
--- a/storage/bdb/test/test013.tcl
+++ b/storage/bdb/test/test013.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test013.tcl,v 11.23 2002/05/22 15:42:46 sue Exp $
+# $Id: test013.tcl,v 11.26 2004/01/28 03:36:30 bostic Exp $
 #
 # TEST	test013
 # TEST	Partial put test
@@ -18,7 +18,6 @@
 proc test013 { method {nentries 10000} args } {
 	global errorCode
 	global errorInfo
-	global fixed_pad
 	global fixed_len
 
 	source ./include.tcl
diff --git a/storage/bdb/test/test014.tcl b/storage/bdb/test/test014.tcl
index 00d69d3352eab23a76d08fb2f4ddab2ea3a422c3..708d5dc09e580ed436ec4f671bfd4173b3b19b74 100644
--- a/storage/bdb/test/test014.tcl
+++ b/storage/bdb/test/test014.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test014.tcl,v 11.24 2002/05/22 15:42:46 sue Exp $
+# $Id: test014.tcl,v 11.26 2004/01/28 03:36:30 bostic Exp $
 #
 # TEST	test014
 # TEST	Exercise partial puts on short data
diff --git a/storage/bdb/test/test015.tcl b/storage/bdb/test/test015.tcl
index f129605a405b206cd20a597ec194c95fb9b08999..9401228116f0dd1feeab47db4312c755ddf58bae 100644
--- a/storage/bdb/test/test015.tcl
+++ b/storage/bdb/test/test015.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test015.tcl,v 11.27 2002/05/31 16:57:25 sue Exp $
+# $Id: test015.tcl,v 11.29 2004/01/28 03:36:30 bostic Exp $
 #
 # TEST	test015
 # TEST	Partial put test
diff --git a/storage/bdb/test/test016.tcl b/storage/bdb/test/test016.tcl
index af289f866f49fad57b4564da3142ed3d235bee67..481c85ec766b9bc856efceb8f6116e538ff24f8f 100644
--- a/storage/bdb/test/test016.tcl
+++ b/storage/bdb/test/test016.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test016.tcl,v 11.23 2002/05/22 15:42:46 sue Exp $
+# $Id: test016.tcl,v 11.25 2004/01/28 03:36:30 bostic Exp $
 #
 # TEST	test016
 # TEST	Partial put test
diff --git a/storage/bdb/test/test017.tcl b/storage/bdb/test/test017.tcl
index 1f99aa328fb944ad19d3365f17aebf5dd207f26e..6503b2cc140ed85146287457e5b4882b52625d82 100644
--- a/storage/bdb/test/test017.tcl
+++ b/storage/bdb/test/test017.tcl
@@ -1,50 +1,52 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test017.tcl,v 11.23 2002/06/20 19:01:02 sue Exp $
+# $Id: test017.tcl,v 11.29 2004/01/28 03:36:30 bostic Exp $
 #
 # TEST	test017
 # TEST	Basic offpage duplicate test.
 # TEST
 # TEST	Run duplicates with small page size so that we test off page duplicates.
 # TEST	Then after we have an off-page database, test with overflow pages too.
-proc test017 { method {contents 0} {ndups 19} {tnum 17} args } {
+proc test017 { method {contents 0} {ndups 19} {tnum "017"} args } {
 	source ./include.tcl
 
 	set args [convert_args $method $args]
 	set omethod [convert_method $method]
 
 	if { [is_record_based $method] == 1 || [is_rbtree $method] == 1 } {
-		puts "Test0$tnum skipping for method $method"
+		puts "Test$tnum skipping for method $method"
 		return
 	}
 	set pgindex [lsearch -exact $args "-pagesize"]
 	if { $pgindex != -1 } {
 		incr pgindex
 		if { [lindex $args $pgindex] > 8192 } {
-			puts "Test0$tnum: Skipping for large pagesizes"
+			puts "Test$tnum: Skipping for large pagesizes"
 			return
 		}
 	}
 
 	# Create the database and open the dictionary
+	set limit 0
 	set txnenv 0
 	set eindex [lsearch -exact $args "-env"]
 	#
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum.db
+		set testfile $testdir/test$tnum.db
 		set env NULL
 	} else {
-		set testfile test0$tnum.db
+		set testfile test$tnum.db
 		incr eindex
 		set env [lindex $args $eindex]
 		set txnenv [is_txnenv $env]
 		if { $txnenv == 1 } {
 			append args " -auto_commit "
+			set limit 100
 		}
 		set testdir [get_home $env]
 	}
@@ -66,15 +68,18 @@ proc test017 { method {contents 0} {ndups 19} {tnum 17} args } {
 
 	set file_list [get_file_list 1]
 	if { $txnenv == 1 } {
+		if { [llength $file_list] > $limit } {
+			set file_list [lrange $file_list 0 $limit]
+		}
 		set flen [llength $file_list]
 		reduce_dups flen ndups
-		set file_list [lrange $file_list 0 $flen]
 	}
-	puts "Test0$tnum: $method ($args) Off page duplicate tests with $ndups duplicates"
+	puts "Test$tnum: $method ($args) Off page duplicate tests\
+	    with $ndups duplicates"
 
 	set ovfl ""
 	# Here is the loop where we put and get each key/data pair
-	puts -nonewline "\tTest0$tnum.a: Creating duplicates with "
+	puts -nonewline "\tTest$tnum.a: Creating duplicates with "
 	if { $contents != 0 } {
 		puts "file contents as key/data"
 	} else {
@@ -136,12 +141,12 @@ proc test017 { method {contents 0} {ndups 19} {tnum 17} args } {
 			if {[string length $d] == 0} {
 				break
 			}
-			error_check_good "Test0$tnum:get" $d $str
+			error_check_good "Test$tnum:get" $d $str
 			set id [ id_of $datastr ]
-			error_check_good "Test0$tnum:$f:dup#" $id $x
+			error_check_good "Test$tnum:$f:dup#" $id $x
 			incr x
 		}
-		error_check_good "Test0$tnum:ndups:$str" [expr $x - 1] $ndups
+		error_check_good "Test$tnum:ndups:$str" [expr $x - 1] $ndups
 		error_check_good cursor_close [$dbc close] 0
 		if { $txnenv == 1 } {
 			error_check_good txn [$t commit] 0
@@ -151,7 +156,7 @@ proc test017 { method {contents 0} {ndups 19} {tnum 17} args } {
 
 	# Now we will get each key from the DB and compare the results
 	# to the original.
-	puts "\tTest0$tnum.b: Checking file for correct duplicates"
+	puts "\tTest$tnum.b: Checking file for correct duplicates"
 	set dlist ""
 	for { set i 1 } { $i <= $ndups } {incr i} {
 		lappend dlist $i
@@ -183,7 +188,7 @@ proc test017 { method {contents 0} {ndups 19} {tnum 17} args } {
 	if {$contents == 0} {
 		filesort $t1 $t3
 
-		error_check_good Test0$tnum:diff($t3,$t2) [filecmp $t3 $t2] 0
+		error_check_good Test$tnum:diff($t3,$t2) [filecmp $t3 $t2] 0
 
 		# Now compare the keys to see if they match the file names
 		if { $txnenv == 1 } {
@@ -197,14 +202,14 @@ proc test017 { method {contents 0} {ndups 19} {tnum 17} args } {
 		}
 		filesort $t1 $t3
 
-		error_check_good Test0$tnum:diff($t3,$t4) [filecmp $t3 $t4] 0
+		error_check_good Test$tnum:diff($t3,$t4) [filecmp $t3 $t4] 0
 	}
 
 	error_check_good db_close [$db close] 0
 	set db [eval {berkdb_open} $args $testfile]
 	error_check_good dbopen [is_valid_db $db] TRUE
 
-	puts "\tTest0$tnum.c: Checking file for correct duplicates after close"
+	puts "\tTest$tnum.c: Checking file for correct duplicates after close"
 	if { $txnenv == 1 } {
 		set t [$env txn]
 		error_check_good txn [is_valid_txn $t $env] TRUE
@@ -218,11 +223,11 @@ proc test017 { method {contents 0} {ndups 19} {tnum 17} args } {
 	if {$contents == 0} {
 		# Now compare the keys to see if they match the filenames
 		filesort $t1 $t3
-		error_check_good Test0$tnum:diff($t3,$t2) [filecmp $t3 $t2] 0
+		error_check_good Test$tnum:diff($t3,$t2) [filecmp $t3 $t2] 0
 	}
 	error_check_good db_close [$db close] 0
 
-	puts "\tTest0$tnum.d: Verify off page duplicates and overflow status"
+	puts "\tTest$tnum.d: Verify off page duplicates and overflow status"
 	set db [eval {berkdb_open} $args $testfile]
 	error_check_good dbopen [is_valid_db $db] TRUE
 	set stat [$db stat]
@@ -239,8 +244,13 @@ proc test017 { method {contents 0} {ndups 19} {tnum 17} args } {
 			    [is_substr $stat "{{Overflow pages} 0}"] 1
 		}
 	} else {
-		error_check_bad overflow \
-		    [is_substr $stat "{{Overflow pages} 0}"] 1
+		if { [is_hash $method] } {
+			error_check_bad overflow \
+			    [is_substr $stat "{{Number of big pages} 0}"] 1
+		} else {
+			error_check_bad overflow \
+			    [is_substr $stat "{{Overflow pages} 0}"] 1
+		}
 	}
 
 	#
@@ -252,7 +262,7 @@ proc test017 { method {contents 0} {ndups 19} {tnum 17} args } {
 		return
 	}
 
-	puts "\tTest0$tnum.e: Add overflow duplicate entries"
+	puts "\tTest$tnum.e: Add overflow duplicate entries"
 	set ovfldup [expr $ndups + 1]
 	foreach f $ovfl {
 		#
@@ -276,7 +286,7 @@ proc test017 { method {contents 0} {ndups 19} {tnum 17} args } {
 		}
 	}
 
-	puts "\tTest0$tnum.f: Verify overflow duplicate entries"
+	puts "\tTest$tnum.f: Verify overflow duplicate entries"
 	if { $txnenv == 1 } {
 		set t [$env txn]
 		error_check_good txn [is_valid_txn $t $env] TRUE
@@ -287,7 +297,7 @@ proc test017 { method {contents 0} {ndups 19} {tnum 17} args } {
 		error_check_good txn [$t commit] 0
 	}
 	filesort $t1 $t3
-	error_check_good Test0$tnum:diff($t3,$t2) [filecmp $t3 $t2] 0
+	error_check_good Test$tnum:diff($t3,$t2) [filecmp $t3 $t2] 0
 
 	set stat [$db stat]
 	if { [is_hash [$db get_type]] } {
diff --git a/storage/bdb/test/test018.tcl b/storage/bdb/test/test018.tcl
index 8fc8a14e95e94e60532c4322e3349cedb1b04328..bf2e3eb562e1c0c96a6c6e986d6de56b30a14f44 100644
--- a/storage/bdb/test/test018.tcl
+++ b/storage/bdb/test/test018.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test018.tcl,v 11.6 2002/01/11 15:53:43 bostic Exp $
+# $Id: test018.tcl,v 11.10 2004/01/28 03:36:30 bostic Exp $
 #
 # TEST	test018
 # TEST	Offpage duplicate test
@@ -12,5 +12,10 @@
 # TEST	duplicates.
 proc test018 { method {nentries 10000} args} {
 	puts "Test018: Off page duplicate tests"
-	eval {test011 $method $nentries 19 18 -pagesize 512} $args
+	set pgindex [lsearch -exact $args "-pagesize"]
+	if { $pgindex != -1 } {
+		puts "Test018: Skipping for specific pagesizes"
+		return
+	}
+	eval {test011 $method $nentries 19 "018" -pagesize 512} $args
 }
diff --git a/storage/bdb/test/test019.tcl b/storage/bdb/test/test019.tcl
index aa3a58a0bcd54e069b32c40de1b1765b240becf8..68f6487be4faa22b9618f08e2fd22c81c523de17 100644
--- a/storage/bdb/test/test019.tcl
+++ b/storage/bdb/test/test019.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test019.tcl,v 11.21 2002/05/22 15:42:47 sue Exp $
+# $Id: test019.tcl,v 11.24 2004/04/22 18:57:32 sue Exp $
 #
 # TEST	test019
 # TEST	Partial get test.
@@ -101,8 +101,13 @@ proc test019 { method {nentries 10000} args } {
 
 		set maxndx [expr [string length $data] - 1]
 
-		set beg [berkdb random_int 0 [expr $maxndx - 1]]
-		set len [berkdb random_int 0 [expr $maxndx * 2]]
+		if { $maxndx > 0 } {
+			set beg [berkdb random_int 0 [expr $maxndx - 1]]
+			set len [berkdb random_int 0 [expr $maxndx * 2]]
+		} else {
+			set beg 0
+			set len 0
+		}
 
 		if { $txnenv == 1 } {
 			set t [$env txn]
diff --git a/storage/bdb/test/test020.tcl b/storage/bdb/test/test020.tcl
index 9b6d939acadbf25aeea148bddb223c70c3577ff7..19eda9c313cd3fc4484a3ef565b04d0a04e182d4 100644
--- a/storage/bdb/test/test020.tcl
+++ b/storage/bdb/test/test020.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test020.tcl,v 11.17 2002/05/22 15:42:47 sue Exp $
+# $Id: test020.tcl,v 11.19 2004/01/28 03:36:30 bostic Exp $
 #
 # TEST	test020
 # TEST	In-Memory database tests.
diff --git a/storage/bdb/test/test021.tcl b/storage/bdb/test/test021.tcl
index 56936da389a820ed2774c761428c4dc0a60b8e5f..43a7a4bde144f3a763e029394ee511c131fb0aaf 100644
--- a/storage/bdb/test/test021.tcl
+++ b/storage/bdb/test/test021.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test021.tcl,v 11.15 2002/05/22 15:42:47 sue Exp $
+# $Id: test021.tcl,v 11.17 2004/01/28 03:36:30 bostic Exp $
 #
 # TEST	test021
 # TEST	Btree range tests.
diff --git a/storage/bdb/test/test022.tcl b/storage/bdb/test/test022.tcl
index d25d7ecdffeb774f9f340a512e3c38fb3510f1df..deded62e7a7442f269794f8dad1bb27b8480fdd8 100644
--- a/storage/bdb/test/test022.tcl
+++ b/storage/bdb/test/test022.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test022.tcl,v 11.14 2002/05/22 15:42:48 sue Exp $
+# $Id: test022.tcl,v 11.16 2004/01/28 03:36:30 bostic Exp $
 #
 # TEST	test022
 # TEST	Test of DB->getbyteswapped().
diff --git a/storage/bdb/test/test023.tcl b/storage/bdb/test/test023.tcl
index c37539a0f552f2c0da297191b5f626f1c5d19148..c4a707288ffd0499edcb30ccdc08e173971576a8 100644
--- a/storage/bdb/test/test023.tcl
+++ b/storage/bdb/test/test023.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test023.tcl,v 11.18 2002/05/22 15:42:48 sue Exp $
+# $Id: test023.tcl,v 11.21 2004/09/20 17:06:16 sue Exp $
 #
 # TEST	test023
 # TEST	Duplicate test
@@ -101,7 +101,7 @@ proc test023 { method args } {
 
 		# Now current should fail
 		set ret [$dbc get -current]
-		error_check_good dbc_get:CURRENT $ret [list [list [] []]]
+		error_check_good dbc_get:CURRENT $ret ""
 
 		# Now Prev should fail
 		set ret [$dbc get -prev]
@@ -123,8 +123,7 @@ proc test023 { method args } {
 
 		# Now current should fail
 		set ret [$dbc get -current]
-		error_check_good \
-		    dbc_get:deleted $ret [list [list [] []]]
+		error_check_good dbc_get:deleted $ret ""
 
 		# Prev and Next should work
 		set ret [$dbc get -next]
@@ -153,8 +152,7 @@ proc test023 { method args } {
 
 		# Now current should fail
 		set ret [$dbc get -current]
-		error_check_good \
-		    dbc_get:deleted $ret [list [list [] []]]
+		error_check_good dbc_get:deleted $ret ""
 
 		# Next should fail
 		set ret [$dbc get -next]
diff --git a/storage/bdb/test/test024.tcl b/storage/bdb/test/test024.tcl
index bbdc8fb225365a44577a5a0e7250c5a7115a2c09..4ac1fceaeb299423ccaf00025f83fdb20612da12 100644
--- a/storage/bdb/test/test024.tcl
+++ b/storage/bdb/test/test024.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test024.tcl,v 11.19 2002/05/22 15:42:48 sue Exp $
+# $Id: test024.tcl,v 11.21 2004/01/28 03:36:30 bostic Exp $
 #
 # TEST	test024
 # TEST	Record number retrieval test.
diff --git a/storage/bdb/test/test025.tcl b/storage/bdb/test/test025.tcl
index 180a1aa2939b2eef0d1b40e424e313565cae2ea3..8f3cb5c0cd38a0ab32230710b74fd412c93d5e0a 100644
--- a/storage/bdb/test/test025.tcl
+++ b/storage/bdb/test/test025.tcl
@@ -1,26 +1,26 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test025.tcl,v 11.19 2002/05/24 15:24:54 sue Exp $
+# $Id: test025.tcl,v 11.22 2004/01/28 03:36:30 bostic Exp $
 #
 # TEST	test025
 # TEST	DB_APPEND flag test.
-proc test025 { method {nentries 10000} {start 0 } {tnum "25" } args} {
+proc test025 { method {nentries 10000} {start 0 } {tnum "025"} args} {
 	global kvals
 	source ./include.tcl
 
 	set args [convert_args $method $args]
 	set omethod [convert_method $method]
-	puts "Test0$tnum: $method ($args)"
+	puts "Test$tnum: $method ($args)"
 
 	if { [string compare $omethod "-btree"] == 0 } {
-		puts "Test0$tnum skipping for method BTREE"
+		puts "Test$tnum skipping for method BTREE"
 		return
 	}
 	if { [string compare $omethod "-hash"] == 0 } {
-		puts "Test0$tnum skipping for method HASH"
+		puts "Test$tnum skipping for method HASH"
 		return
 	}
 
@@ -31,10 +31,10 @@ proc test025 { method {nentries 10000} {start 0 } {tnum "25" } args} {
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum.db
+		set testfile $testdir/test$tnum.db
 		set env NULL
 	} else {
-		set testfile test0$tnum.db
+		set testfile test$tnum.db
 		incr eindex
 		set env [lindex $args $eindex]
 		set txnenv [is_txnenv $env]
@@ -58,7 +58,7 @@ proc test025 { method {nentries 10000} {start 0 } {tnum "25" } args} {
 	error_check_good dbopen [is_valid_db $db] TRUE
 	set did [open $dict]
 
-	puts "\tTest0$tnum.a: put/get loop"
+	puts "\tTest$tnum.a: put/get loop"
 	set gflags " -recno"
 	set pflags " -append"
 	set txn ""
@@ -114,7 +114,7 @@ proc test025 { method {nentries 10000} {start 0 } {tnum "25" } args} {
 
 	# Now we will get each key from the DB and compare the results
 	# to the original.
-	puts "\tTest0$tnum.b: dump file"
+	puts "\tTest$tnum.b: dump file"
 	if { $txnenv == 1 } {
 		set t [$env txn]
 		error_check_good txn [is_valid_txn $t $env] TRUE
@@ -126,14 +126,14 @@ proc test025 { method {nentries 10000} {start 0 } {tnum "25" } args} {
 	}
 	error_check_good db_close [$db close] 0
 
-	puts "\tTest0$tnum.c: close, open, and dump file"
+	puts "\tTest$tnum.c: close, open, and dump file"
 	# Now, reopen the file and run the last test again.
 	open_and_dump_file $testfile $env $t1 $checkfunc \
 	    dump_file_direction -first -next
 
 	# Now, reopen the file and run the last test again in the
 	# reverse direction.
-	puts "\tTest0$tnum.d: close, open, and dump file in reverse direction"
+	puts "\tTest$tnum.d: close, open, and dump file in reverse direction"
 	open_and_dump_file $testfile $env $t1 $checkfunc \
 		dump_file_direction -last -prev
 }
diff --git a/storage/bdb/test/test026.tcl b/storage/bdb/test/test026.tcl
index ce65e925d35e6d9286591ce65e4e5bae2adc3171..ce91e2b464d597759ca55029a0a8a9abc82ee51e 100644
--- a/storage/bdb/test/test026.tcl
+++ b/storage/bdb/test/test026.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test026.tcl,v 11.20 2002/06/11 14:09:56 sue Exp $
+# $Id: test026.tcl,v 11.23 2004/01/28 03:36:30 bostic Exp $
 #
 # TEST	test026
 # TEST	Small keys/medium data w/duplicates
@@ -13,7 +13,7 @@
 # TEST
 # TEST	Keyed delete test through cursor.  If ndups is small; this will
 # TEST	test on-page dups; if it's large, it will test off-page dups.
-proc test026 { method {nentries 2000} {ndups 5} {tnum 26} args} {
+proc test026 { method {nentries 2000} {ndups 5} {tnum "026"} args} {
 	source ./include.tcl
 
 	set args [convert_args $method $args]
@@ -21,7 +21,7 @@ proc test026 { method {nentries 2000} {ndups 5} {tnum 26} args} {
 
 	if { [is_record_based $method] == 1 || \
 	    [is_rbtree $method] == 1 } {
-		puts "Test0$tnum skipping for method $method"
+		puts "Test$tnum skipping for method $method"
 		return
 	}
 	# Create the database and open the dictionary
@@ -31,10 +31,10 @@ proc test026 { method {nentries 2000} {ndups 5} {tnum 26} args} {
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum.db
+		set testfile $testdir/test$tnum.db
 		set env NULL
 	} else {
-		set testfile test0$tnum.db
+		set testfile test$tnum.db
 		incr eindex
 		set env [lindex $args $eindex]
 		set txnenv [is_txnenv $env]
@@ -54,7 +54,7 @@ proc test026 { method {nentries 2000} {ndups 5} {tnum 26} args} {
 		set testdir [get_home $env]
 	}
 	cleanup $testdir $env
-	puts "Test0$tnum: $method ($args) $nentries keys\
+	puts "Test$tnum: $method ($args) $nentries keys\
 		with $ndups dups; cursor delete test"
 
 	set pflags ""
@@ -64,7 +64,7 @@ proc test026 { method {nentries 2000} {ndups 5} {tnum 26} args} {
 
 	# Here is the loop where we put and get each key/data pair
 
-	puts "\tTest0$tnum.a: Put loop"
+	puts "\tTest$tnum.a: Put loop"
 	set db [eval {berkdb_open -create \
 		-mode 0644} $args {$omethod -dup $testfile}]
 	error_check_good dbopen [is_valid_db $db] TRUE
@@ -103,7 +103,7 @@ proc test026 { method {nentries 2000} {ndups 5} {tnum 26} args} {
 	set dbc [eval {$db cursor} $txn]
 	error_check_good db_cursor [is_substr $dbc $db] 1
 
-	puts "\tTest0$tnum.b: Get/delete loop"
+	puts "\tTest$tnum.b: Get/delete loop"
 	set i 1
 	for { set ret [$dbc get -first] } {
 	    [string length $ret] != 0 } {
@@ -134,7 +134,7 @@ proc test026 { method {nentries 2000} {ndups 5} {tnum 26} args} {
 	}
 	error_check_good db_close [$db close] 0
 
-	puts "\tTest0$tnum.c: Verify empty file"
+	puts "\tTest$tnum.c: Verify empty file"
 	# Double check that file is now empty
 	set db [eval {berkdb_open} $args $testfile]
 	error_check_good dbopen [is_valid_db $db] TRUE
diff --git a/storage/bdb/test/test027.tcl b/storage/bdb/test/test027.tcl
index a0f6dfa4dcbf637c2c7d0b09702db6049ab372ea..7f6d78c3ad61a4931f5f672897d564a707962ed5 100644
--- a/storage/bdb/test/test027.tcl
+++ b/storage/bdb/test/test027.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test027.tcl,v 11.7 2002/01/11 15:53:45 bostic Exp $
+# $Id: test027.tcl,v 11.10 2004/01/28 03:36:30 bostic Exp $
 #
 # TEST	test027
 # TEST	Off-page duplicate test
@@ -13,5 +13,5 @@
 # TEST	database and reopen it.  Then issues delete by key for each
 # TEST	entry.
 proc test027 { method {nentries 100} args} {
-	eval {test026 $method $nentries 100 27} $args
+	eval {test026 $method $nentries 100 "027"} $args
 }
diff --git a/storage/bdb/test/test028.tcl b/storage/bdb/test/test028.tcl
index a546744fdac0186de8bd7e7754c92d6e0c1806ce..3884d83e965b3864fdac6306501013dcb8b8d8eb 100644
--- a/storage/bdb/test/test028.tcl
+++ b/storage/bdb/test/test028.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test028.tcl,v 11.20 2002/07/01 15:03:45 krinsky Exp $
+# $Id: test028.tcl,v 11.22 2004/01/28 03:36:30 bostic Exp $
 #
 # TEST	test028
 # TEST	Cursor delete test
diff --git a/storage/bdb/test/test029.tcl b/storage/bdb/test/test029.tcl
index 8e4b8aa6e41e25df51655641efeb2c1c18d1f6e6..53622efeb73fb07f1414157fcb3145ea4eedafe8 100644
--- a/storage/bdb/test/test029.tcl
+++ b/storage/bdb/test/test029.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test029.tcl,v 11.20 2002/06/29 13:44:44 bostic Exp $
+# $Id: test029.tcl,v 11.24 2004/09/22 18:01:06 bostic Exp $
 #
 # TEST	test029
 # TEST	Test the Btree and Record number renumbering.
@@ -221,13 +221,15 @@ proc test029 { method {nentries 10000} args} {
 	    getn_after_cursor_del [lindex [lindex $ret 0] 1] $last_key
 
 	# Re-put the first key and make sure that we renumber the last
-	# key appropriately.
-	puts "\tTest029.e: put with cursor and verify renumber"
+	# key appropriately.  We can't do a c_put -current, so do
+	# a db put instead.
 	if { [string compare $omethod "-btree"] == 0 } {
-		set ret [eval {$dbc put} \
-		    $pflags {-current $first_key}]
-		error_check_good dbc_put:DB_CURRENT $ret 0
+		puts "\tTest029.e: put (non-cursor) and verify renumber"
+		set ret [eval {$db put} $txn \
+		    {$key [chop_data $method $first_key]}]
+		error_check_good db_put $ret 0
 	} else {
+		puts "\tTest029.e: put with cursor and verify renumber"
 		set ret [eval {$dbc put} $pflags {-before $first_key}]
 		error_check_bad dbc_put:DB_BEFORE $ret 0
 	}
diff --git a/storage/bdb/test/test030.tcl b/storage/bdb/test/test030.tcl
index d91359f07a009e286cc1dff934f344ed9b431026..3ee9daa3f507ad584f576e909bfa655097fb4a80 100644
--- a/storage/bdb/test/test030.tcl
+++ b/storage/bdb/test/test030.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test030.tcl,v 11.18 2002/05/22 15:42:50 sue Exp $
+# $Id: test030.tcl,v 11.20 2004/01/28 03:36:30 bostic Exp $
 #
 # TEST	test030
 # TEST	Test DB_NEXT_DUP Functionality.
diff --git a/storage/bdb/test/test031.tcl b/storage/bdb/test/test031.tcl
index 0006deb2d99297cf54653dcb11e95c57929c2653..2b4ad0d9878a97d6b61925cc928ae45f0a86433b 100644
--- a/storage/bdb/test/test031.tcl
+++ b/storage/bdb/test/test031.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test031.tcl,v 11.24 2002/06/26 06:22:44 krinsky Exp $
+# $Id: test031.tcl,v 11.27 2004/01/28 03:36:30 bostic Exp $
 #
 # TEST	test031
 # TEST	Duplicate sorting functionality
@@ -20,7 +20,7 @@
 # TEST	After all are entered, retrieve all; verify output.
 # TEST	Close file, reopen, do retrieve and re-verify.
 # TEST	This does not work for recno
-proc test031 { method {nentries 10000} {ndups 5} {tnum 31} args } {
+proc test031 { method {nentries 10000} {ndups 5} {tnum "031"} args } {
 	global alphabet
 	global rand_init
 	source ./include.tcl
@@ -37,11 +37,11 @@ proc test031 { method {nentries 10000} {ndups 5} {tnum 31} args } {
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum.db
+		set testfile $testdir/test$tnum.db
 		set checkdb $testdir/checkdb.db
 		set env NULL
 	} else {
-		set testfile test0$tnum.db
+		set testfile test$tnum.db
 		set checkdb checkdb.db
 		incr eindex
 		set env [lindex $args $eindex]
@@ -64,11 +64,11 @@ proc test031 { method {nentries 10000} {ndups 5} {tnum 31} args } {
 	set t3 $testdir/t3
 	cleanup $testdir $env
 
-	puts "Test0$tnum: \
+	puts "Test$tnum: \
 	    $method ($args) $nentries small $ndups sorted dup key/data pairs"
 	if { [is_record_based $method] == 1 || \
 	    [is_rbtree $method] == 1 } {
-		puts "Test0$tnum skipping for method $omethod"
+		puts "Test$tnum skipping for method $omethod"
 		return
 	}
 	set db [eval {berkdb_open -create \
@@ -86,7 +86,7 @@ proc test031 { method {nentries 10000} {ndups 5} {tnum 31} args } {
 	set count 0
 
 	# Here is the loop where we put and get each key/data pair
-	puts "\tTest0$tnum.a: Put/get loop, check nodupdata"
+	puts "\tTest$tnum.a: Put/get loop, check nodupdata"
 	if { $txnenv == 1 } {
 		set t [$env txn]
 		error_check_good txn [is_valid_txn $t $env] TRUE
@@ -151,7 +151,7 @@ proc test031 { method {nentries 10000} {ndups 5} {tnum 31} args } {
 			incr x
 			set lastdup $datastr
 		}
-		error_check_good "Test0$tnum:ndups:$str" $x $ndups
+		error_check_good "Test$tnum:ndups:$str" $x $ndups
 		incr count
 	}
 	error_check_good cursor_close [$dbc close] 0
@@ -162,7 +162,7 @@ proc test031 { method {nentries 10000} {ndups 5} {tnum 31} args } {
 
 	# Now we will get each key from the DB and compare the results
 	# to the original.
-	puts "\tTest0$tnum.b: Checking file for correct duplicates"
+	puts "\tTest$tnum.b: Checking file for correct duplicates"
 	if { $txnenv == 1 } {
 		set t [$env txn]
 		error_check_good txn [is_valid_txn $t $env] TRUE
diff --git a/storage/bdb/test/test032.tcl b/storage/bdb/test/test032.tcl
index 2076b744851b4f1f3104ed7c0c64b71f049f6c9b..e7cc49b47763706e6a9645baa7106cf7ad1e1a28 100644
--- a/storage/bdb/test/test032.tcl
+++ b/storage/bdb/test/test032.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test032.tcl,v 11.23 2002/06/11 14:09:57 sue Exp $
+# $Id: test032.tcl,v 11.26 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test032
 # TEST	DB_GET_BOTH, DB_GET_BOTH_RANGE
@@ -17,7 +17,7 @@
 # TEST	Test the DB_GET_BOTH functionality by retrieving each dup in the file
 # TEST	explicitly.  Test the DB_GET_BOTH_RANGE functionality by retrieving
 # TEST	the unique key prefix (cursor only).  Finally test the failure case.
-proc test032 { method {nentries 10000} {ndups 5} {tnum 32} args } {
+proc test032 { method {nentries 10000} {ndups 5} {tnum "032"} args } {
 	global alphabet rand_init
 	source ./include.tcl
 
@@ -33,11 +33,11 @@ proc test032 { method {nentries 10000} {ndups 5} {tnum 32} args } {
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum.db
+		set testfile $testdir/test$tnum.db
 		set checkdb $testdir/checkdb.db
 		set env NULL
 	} else {
-		set testfile test0$tnum.db
+		set testfile test$tnum.db
 		set checkdb checkdb.db
 		incr eindex
 		set env [lindex $args $eindex]
@@ -60,11 +60,11 @@ proc test032 { method {nentries 10000} {ndups 5} {tnum 32} args } {
 	set t3 $testdir/t3
 	cleanup $testdir $env
 
-	puts "Test0$tnum:\
+	puts "Test$tnum:\
 	    $method ($args) $nentries small sorted $ndups dup key/data pairs"
 	if { [is_record_based $method] == 1 || \
 	    [is_rbtree $method] == 1 } {
-		puts "Test0$tnum skipping for method $omethod"
+		puts "Test$tnum skipping for method $omethod"
 		return
 	}
 	set db [eval {berkdb_open -create -mode 0644 \
@@ -82,7 +82,7 @@ proc test032 { method {nentries 10000} {ndups 5} {tnum 32} args } {
 	set count 0
 
 	# Here is the loop where we put and get each key/data pair
-	puts "\tTest0$tnum.a: Put/get loop"
+	puts "\tTest$tnum.a: Put/get loop"
 	if { $txnenv == 1 } {
 		set t [$env txn]
 		error_check_good txn [is_valid_txn $t $env] TRUE
@@ -129,7 +129,7 @@ proc test032 { method {nentries 10000} {ndups 5} {tnum 32} args } {
 			set lastdup $datastr
 		}
 
-		error_check_good "Test0$tnum:ndups:$str" $x $ndups
+		error_check_good "Test$tnum:ndups:$str" $x $ndups
 		incr count
 	}
 	error_check_good cursor_close [$dbc close] 0
@@ -140,7 +140,7 @@ proc test032 { method {nentries 10000} {ndups 5} {tnum 32} args } {
 
 	# Now we will get each key from the DB and compare the results
 	# to the original.
-	puts "\tTest0$tnum.b: Checking file for correct duplicates (no cursor)"
+	puts "\tTest$tnum.b: Checking file for correct duplicates (no cursor)"
 	if { $txnenv == 1 } {
 		set t [$env txn]
 		error_check_good txn [is_valid_txn $t $env] TRUE
@@ -169,7 +169,7 @@ proc test032 { method {nentries 10000} {ndups 5} {tnum 32} args } {
 	$db sync
 
 	# Now repeat the above test using cursor ops
-	puts "\tTest0$tnum.c: Checking file for correct duplicates (cursor)"
+	puts "\tTest$tnum.c: Checking file for correct duplicates (cursor)"
 	set dbc [eval {$db cursor} $txn]
 	error_check_good cursor_open [is_valid_cursor $dbc $db] TRUE
 
@@ -194,7 +194,7 @@ proc test032 { method {nentries 10000} {ndups 5} {tnum 32} args } {
 	}
 
 	# Now check the error case
-	puts "\tTest0$tnum.d: Check error case (no cursor)"
+	puts "\tTest$tnum.d: Check error case (no cursor)"
 	for {set ret [$check_c get -first]} \
 	    {[llength $ret] != 0} \
 	    {set ret [$check_c get -next] } {
@@ -208,7 +208,7 @@ proc test032 { method {nentries 10000} {ndups 5} {tnum 32} args } {
 	}
 
 	# Now check the error case
-	puts "\tTest0$tnum.e: Check error case (cursor)"
+	puts "\tTest$tnum.e: Check error case (cursor)"
 	for {set ret [$check_c get -first]} \
 	    {[llength $ret] != 0} \
 	    {set ret [$check_c get -next] } {
diff --git a/storage/bdb/test/test033.tcl b/storage/bdb/test/test033.tcl
index a7796ce99d672d99d5fc165e31841fea11b78b0d..b606883c1a053ca531bdd575f16b2b6912e442d2 100644
--- a/storage/bdb/test/test033.tcl
+++ b/storage/bdb/test/test033.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test033.tcl,v 11.24 2002/08/08 15:38:11 bostic Exp $
+# $Id: test033.tcl,v 11.27 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test033
 # TEST	DB_GET_BOTH without comparison function
@@ -16,13 +16,13 @@
 # TEST
 # TEST	XXX
 # TEST	This does not work for rbtree.
-proc test033 { method {nentries 10000} {ndups 5} {tnum 33} args } {
+proc test033 { method {nentries 10000} {ndups 5} {tnum "033"} args } {
 	source ./include.tcl
 
 	set args [convert_args $method $args]
 	set omethod [convert_method $method]
 	if { [is_rbtree $method] == 1 } {
-		puts "Test0$tnum skipping for method $method"
+		puts "Test$tnum skipping for method $method"
 		return
 	}
 
@@ -32,10 +32,10 @@ proc test033 { method {nentries 10000} {ndups 5} {tnum 33} args } {
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum.db
+		set testfile $testdir/test$tnum.db
 		set env NULL
 	} else {
-		set testfile test0$tnum.db
+		set testfile test$tnum.db
 		incr eindex
 		set env [lindex $args $eindex]
 		set txnenv [is_txnenv $env]
@@ -53,7 +53,7 @@ proc test033 { method {nentries 10000} {ndups 5} {tnum 33} args } {
 		set testdir [get_home $env]
 	}
 
-	puts "Test0$tnum: $method ($args) $nentries small $ndups dup key/data pairs"
+	puts "Test$tnum: $method ($args) $nentries small $ndups dup key/data pairs"
 	set t1 $testdir/t1
 	set t2 $testdir/t2
 	set t3 $testdir/t3
@@ -82,7 +82,7 @@ proc test033 { method {nentries 10000} {ndups 5} {tnum 33} args } {
 	set dbc [eval {$db cursor} $txn]
 	error_check_good cursor_open [is_valid_cursor $dbc $db] TRUE
 
-	puts "\tTest0$tnum.a: Put/get loop."
+	puts "\tTest$tnum.a: Put/get loop."
 	# Here is the loop where we put and get each key/data pair
 	set count 0
 	set did [open $dict]
@@ -113,7 +113,7 @@ proc test033 { method {nentries 10000} {ndups 5} {tnum 33} args } {
 
 	close $did
 
-	puts "\tTest0$tnum.b: Verifying DB_GET_BOTH after creation."
+	puts "\tTest$tnum.b: Verifying DB_GET_BOTH after creation."
 	set count 0
 	set did [open $dict]
 	while { [gets $did str] != -1 && $count < $nentries } {
diff --git a/storage/bdb/test/test034.tcl b/storage/bdb/test/test034.tcl
index 647ad9408153bb60b37fca49f07a33d696cd6188..5da92052214302df885d0782f6e1134a971a5852 100644
--- a/storage/bdb/test/test034.tcl
+++ b/storage/bdb/test/test034.tcl
@@ -1,17 +1,23 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1998-2002
+# Copyright (c) 1998-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test034.tcl,v 11.8 2002/01/11 15:53:46 bostic Exp $
+# $Id: test034.tcl,v 11.12 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test034
 # TEST	test032 with off-page duplicates
 # TEST	DB_GET_BOTH, DB_GET_BOTH_RANGE functionality with off-page duplicates.
 proc test034 { method {nentries 10000} args} {
+	set pgindex [lsearch -exact $args "-pagesize"]
+	if { $pgindex != -1 } {
+		puts "Test034: Skipping for specific pagesizes"
+		return
+	}
 	# Test with off-page duplicates
-	eval {test032 $method $nentries 20 34 -pagesize 512} $args
+	eval {test032 $method $nentries 20 "034" -pagesize 512} $args
 
 	# Test with multiple pages of off-page duplicates
-	eval {test032 $method [expr $nentries / 10] 100 34 -pagesize 512} $args
+	eval {test032 $method [expr $nentries / 10] 100 "034" -pagesize 512} \
+	    $args
 }
diff --git a/storage/bdb/test/test035.tcl b/storage/bdb/test/test035.tcl
index 06796b1e9aa62d6b9ab00c7ac86a806cc376983f..63945c58875a4922cec331d837a75809e3743c36 100644
--- a/storage/bdb/test/test035.tcl
+++ b/storage/bdb/test/test035.tcl
@@ -1,16 +1,22 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test035.tcl,v 11.8 2002/07/22 17:00:39 sue Exp $
+# $Id: test035.tcl,v 11.12 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test035
 # TEST	Test033 with off-page duplicates
 # TEST	DB_GET_BOTH functionality with off-page duplicates.
 proc test035 { method {nentries 10000} args} {
+	set pgindex [lsearch -exact $args "-pagesize"]
+	if { $pgindex != -1 } {
+		puts "Test035: Skipping for specific pagesizes"
+		return
+	}
 	# Test with off-page duplicates
-	eval {test033 $method $nentries 20 35 -pagesize 512} $args
+	eval {test033 $method $nentries 20 "035" -pagesize 512} $args
 	# Test with multiple pages of off-page duplicates
-	eval {test033 $method [expr $nentries / 10] 100 35 -pagesize 512} $args
+	eval {test033 $method [expr $nentries / 10] 100 "035" -pagesize 512} \
+	    $args
 }
diff --git a/storage/bdb/test/test036.tcl b/storage/bdb/test/test036.tcl
index 4e54f363ff84ee531b338513b5ac75d8b1cd2119..5fe24cb21aebfd5df28a9959866f5a7a4c63b821 100644
--- a/storage/bdb/test/test036.tcl
+++ b/storage/bdb/test/test036.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test036.tcl,v 11.18 2002/05/22 15:42:51 sue Exp $
+# $Id: test036.tcl,v 11.20 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test036
 # TEST	Test KEYFIRST and KEYLAST when the key doesn't exist
diff --git a/storage/bdb/test/test037.tcl b/storage/bdb/test/test037.tcl
index 0b2e2989949a99d5f7346828f8255de177b64d29..c571ffa3e9dd2549c9775943f30f851210bfa85e 100644
--- a/storage/bdb/test/test037.tcl
+++ b/storage/bdb/test/test037.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test037.tcl,v 11.18 2002/03/15 16:30:54 sue Exp $
+# $Id: test037.tcl,v 11.20 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test037
 # TEST	Test DB_RMW
diff --git a/storage/bdb/test/test038.tcl b/storage/bdb/test/test038.tcl
index 3babde8fe0bedcd68b4eb017cf33288b9bdb0482..eaf934f5d133d743007dc3eb7660788043537b0f 100644
--- a/storage/bdb/test/test038.tcl
+++ b/storage/bdb/test/test038.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test038.tcl,v 11.23 2002/06/11 14:09:57 sue Exp $
+# $Id: test038.tcl,v 11.26 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test038
 # TEST	DB_GET_BOTH, DB_GET_BOTH_RANGE on deleted items
@@ -17,7 +17,7 @@
 # TEST	Test the DB_GET_BOTH and DB_GET_BOTH_RANGE functionality by retrieving
 # TEST	each dup in the file explicitly.  Then remove each duplicate and try
 # TEST	the retrieval again.
-proc test038 { method {nentries 10000} {ndups 5} {tnum 38} args } {
+proc test038 { method {nentries 10000} {ndups 5} {tnum "038"} args } {
 	global alphabet
 	global rand_init
 	source ./include.tcl
@@ -29,7 +29,7 @@ proc test038 { method {nentries 10000} {ndups 5} {tnum 38} args } {
 
 	if { [is_record_based $method] == 1 || \
 	    [is_rbtree $method] == 1 } {
-		puts "Test0$tnum skipping for method $method"
+		puts "Test$tnum skipping for method $method"
 		return
 	}
 	# Create the database and open the dictionary
@@ -39,11 +39,11 @@ proc test038 { method {nentries 10000} {ndups 5} {tnum 38} args } {
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum.db
+		set testfile $testdir/test$tnum.db
 		set checkdb $testdir/checkdb.db
 		set env NULL
 	} else {
-		set testfile test0$tnum.db
+		set testfile test$tnum.db
 		set checkdb checkdb.db
 		incr eindex
 		set env [lindex $args $eindex]
@@ -66,7 +66,7 @@ proc test038 { method {nentries 10000} {ndups 5} {tnum 38} args } {
 	set t3 $testdir/t3
 	cleanup $testdir $env
 
-	puts "Test0$tnum: \
+	puts "Test$tnum: \
 	    $method ($args) $nentries small sorted dup key/data pairs"
 	set db [eval {berkdb_open -create -mode 0644 \
 		$omethod -dup -dupsort} $args {$testfile}]
@@ -83,7 +83,7 @@ proc test038 { method {nentries 10000} {ndups 5} {tnum 38} args } {
 	set count 0
 
 	# Here is the loop where we put and get each key/data pair
-	puts "\tTest0$tnum.a: Put/get loop"
+	puts "\tTest$tnum.a: Put/get loop"
 	if { $txnenv == 1 } {
 		set t [$env txn]
 		error_check_good txn [is_valid_txn $t $env] TRUE
@@ -142,7 +142,7 @@ proc test038 { method {nentries 10000} {ndups 5} {tnum 38} args } {
 			incr x
 			set lastdup $datastr
 		}
-		error_check_good "Test0$tnum:ndups:$str" $x $ndups
+		error_check_good "Test$tnum:ndups:$str" $x $ndups
 		incr count
 	}
 	error_check_good cursor_close [$dbc close] 0
@@ -152,7 +152,7 @@ proc test038 { method {nentries 10000} {ndups 5} {tnum 38} args } {
 	close $did
 
 	# Now check the duplicates, then delete then recheck
-	puts "\tTest0$tnum.b: Checking and Deleting duplicates"
+	puts "\tTest$tnum.b: Checking and Deleting duplicates"
 	if { $txnenv == 1 } {
 		set t [$env txn]
 		error_check_good txn [is_valid_txn $t $env] TRUE
diff --git a/storage/bdb/test/test039.tcl b/storage/bdb/test/test039.tcl
index 2bbc83ebe05c3aed86e9e8c4df860bdfdb042517..67b2eaf33617dfb4be6331bc705e8be12bfcc9ac 100644
--- a/storage/bdb/test/test039.tcl
+++ b/storage/bdb/test/test039.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test039.tcl,v 11.20 2002/06/11 14:09:57 sue Exp $
+# $Id: test039.tcl,v 11.23 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test039
 # TEST	DB_GET_BOTH/DB_GET_BOTH_RANGE on deleted items without comparison
@@ -18,7 +18,7 @@
 # TEST	Test the DB_GET_BOTH and DB_GET_BOTH_RANGE functionality by retrieving
 # TEST	each dup in the file explicitly.  Then remove each duplicate and try
 # TEST	the retrieval again.
-proc test039 { method {nentries 10000} {ndups 5} {tnum 39} args } {
+proc test039 { method {nentries 10000} {ndups 5} {tnum "039"} args } {
 	global alphabet
 	global rand_init
 	source ./include.tcl
@@ -30,7 +30,7 @@ proc test039 { method {nentries 10000} {ndups 5} {tnum 39} args } {
 
 	if { [is_record_based $method] == 1 || \
 	    [is_rbtree $method] == 1 } {
-		puts "Test0$tnum skipping for method $method"
+		puts "Test$tnum skipping for method $method"
 		return
 	}
 	# Create the database and open the dictionary
@@ -40,11 +40,11 @@ proc test039 { method {nentries 10000} {ndups 5} {tnum 39} args } {
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum.db
+		set testfile $testdir/test$tnum.db
 		set checkdb $testdir/checkdb.db
 		set env NULL
 	} else {
-		set testfile test0$tnum.db
+		set testfile test$tnum.db
 		set checkdb checkdb.db
 		incr eindex
 		set env [lindex $args $eindex]
@@ -67,7 +67,7 @@ proc test039 { method {nentries 10000} {ndups 5} {tnum 39} args } {
 	set t3 $testdir/t3
 	cleanup $testdir $env
 
-	puts "Test0$tnum: $method $nentries \
+	puts "Test$tnum: $method $nentries \
 	    small $ndups unsorted dup key/data pairs"
 
 	set db [eval {berkdb_open -create -mode 0644 \
@@ -85,7 +85,7 @@ proc test039 { method {nentries 10000} {ndups 5} {tnum 39} args } {
 	set count 0
 
 	# Here is the loop where we put and get each key/data pair
-	puts "\tTest0$tnum.a: Put/get loop"
+	puts "\tTest$tnum.a: Put/get loop"
 	if { $txnenv == 1 } {
 		set t [$env txn]
 		error_check_good txn [is_valid_txn $t $env] TRUE
@@ -143,7 +143,7 @@ proc test039 { method {nentries 10000} {ndups 5} {tnum 39} args } {
 			error_check_good retrieve $datastr $check_data
 			incr x
 		}
-		error_check_good "Test0$tnum:ndups:$str" $x $ndups
+		error_check_good "Test$tnum:ndups:$str" $x $ndups
 		incr count
 	}
 	error_check_good cursor_close [$dbc close] 0
@@ -153,7 +153,7 @@ proc test039 { method {nentries 10000} {ndups 5} {tnum 39} args } {
 	close $did
 
 	# Now check the duplicates, then delete then recheck
-	puts "\tTest0$tnum.b: Checking and Deleting duplicates"
+	puts "\tTest$tnum.b: Checking and Deleting duplicates"
 	if { $txnenv == 1 } {
 		set t [$env txn]
 		error_check_good txn [is_valid_txn $t $env] TRUE
diff --git a/storage/bdb/test/test040.tcl b/storage/bdb/test/test040.tcl
index 1856f78fc2ef3fe8407c9c5d63851e84c4a181b2..61d5cd1f36647125439d6aaea52873ffc096f32b 100644
--- a/storage/bdb/test/test040.tcl
+++ b/storage/bdb/test/test040.tcl
@@ -1,17 +1,23 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1998-2002
+# Copyright (c) 1998-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test040.tcl,v 11.6 2002/01/11 15:53:47 bostic Exp $
+# $Id: test040.tcl,v 11.10 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test040
 # TEST	Test038 with off-page duplicates
 # TEST	DB_GET_BOTH functionality with off-page duplicates.
 proc test040 { method {nentries 10000} args} {
+	set pgindex [lsearch -exact $args "-pagesize"]
+	if { $pgindex != -1 } {
+		puts "Test040: skipping for specific pagesizes"
+		return
+	}
 	# Test with off-page duplicates
-	eval {test038 $method $nentries 20 40 -pagesize 512} $args
+	eval {test038 $method $nentries 20 "040" -pagesize 512} $args
 
 	# Test with multiple pages of off-page duplicates
-	eval {test038 $method [expr $nentries / 10] 100 40 -pagesize 512} $args
+	eval {test038 $method [expr $nentries / 10] 100 "040" -pagesize 512} \
+	    $args
 }
diff --git a/storage/bdb/test/test041.tcl b/storage/bdb/test/test041.tcl
index fdcbdbef3d766cdee69dd3a48d3f8ca2921971fd..790ece9437fbd2a976279d5b4fa3599b6c7305f1 100644
--- a/storage/bdb/test/test041.tcl
+++ b/storage/bdb/test/test041.tcl
@@ -1,17 +1,18 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test041.tcl,v 11.6 2002/01/11 15:53:47 bostic Exp $
+# $Id: test041.tcl,v 11.9 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test041
 # TEST	Test039 with off-page duplicates
 # TEST	DB_GET_BOTH functionality with off-page duplicates.
 proc test041 { method {nentries 10000} args} {
 	# Test with off-page duplicates
-	eval {test039 $method $nentries 20 41 -pagesize 512} $args
+	eval {test039 $method $nentries 20 "041" -pagesize 512} $args
 
 	# Test with multiple pages of off-page duplicates
-	eval {test039 $method [expr $nentries / 10] 100 41 -pagesize 512} $args
+	eval {test039 $method [expr $nentries / 10] 100 "041" -pagesize 512} \
+	    $args
 }
diff --git a/storage/bdb/test/test042.tcl b/storage/bdb/test/test042.tcl
index 9f444b8349cf4f71c4e989ad8572611a8bd3d271..b216ebf27d88f632ce92559e2eefb90a399ffa2a 100644
--- a/storage/bdb/test/test042.tcl
+++ b/storage/bdb/test/test042.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test042.tcl,v 11.37 2002/09/05 17:23:07 sandstro Exp $
+# $Id: test042.tcl,v 11.46 2004/09/22 18:01:06 bostic Exp $
 #
 # TEST	test042
 # TEST	Concurrent Data Store test (CDB)
@@ -69,7 +69,7 @@ proc test042_body { method nentries alldb args } {
 	}
 
 	# Create the database and open the dictionary
-	set testfile test042.db
+	set basename test042
 	set t1 $testdir/t1
 	set t2 $testdir/t2
 	set t3 $testdir/t3
@@ -80,11 +80,11 @@ proc test042_body { method nentries alldb args } {
 	error_check_good dbenv [is_valid_env $env] TRUE
 
 	# Env is created, now set up database
-	test042_dbinit $env $nentries $method $oargs $testfile 0
+	test042_dbinit $env $nentries $method $oargs $basename.0.db
 	if { $alldb } {
 		for { set i 1 } {$i < $procs} {incr i} {
 			test042_dbinit $env $nentries $method $oargs \
-			    $testfile $i
+			    $basename.$i.db
 		}
 	}
 
@@ -93,7 +93,8 @@ proc test042_body { method nentries alldb args } {
 	set ret [berkdb envremove -home $testdir]
 	error_check_good env_remove $ret 0
 
-	set env [eval {berkdb_env -create} $eflag -home $testdir]
+	set env [eval {berkdb_env \
+	    -create -cachesize {0 1048576 1}} $eflag -home $testdir]
 	error_check_good dbenv [is_valid_widget $env env] TRUE
 
 	if { $do_exit == 1 } {
@@ -107,9 +108,9 @@ proc test042_body { method nentries alldb args } {
 
 	for { set i 0 } {$i < $procs} {incr i} {
 		if { $alldb } {
-			set tf $testfile$i
+			set tf $basename.$i.db
 		} else {
-			set tf ${testfile}0
+			set tf $basename.0.db
 		}
 		puts "exec $tclsh_path $test_path/wrap.tcl \
 		    mdbscript.tcl $testdir/test042.$i.log \
@@ -120,40 +121,42 @@ proc test042_body { method nentries alldb args } {
 		lappend pidlist $p
 	}
 	puts "Test042: $procs independent processes now running"
-	watch_procs $pidlist 
+	watch_procs $pidlist
+
+	# Make sure we haven't added or lost any entries.
+	set dblist [glob $testdir/$basename.*.db]
+	foreach file $dblist {
+		set tf [file tail $file]
+		set db [eval {berkdb_open -env $env $tf}]
+		set statret [$db stat]
+		foreach pair $statret {
+			set fld [lindex $pair 0]
+			if { [string compare $fld {Number of records}] == 0 } {
+				set numrecs [lindex $pair 1]
+				break
+			}
+		}
+		error_check_good nentries $numrecs $nentries
+		error_check_good db_close [$db close] 0
+	}
 
 	# Check for test failure
-	set e [eval findfail [glob $testdir/test042.*.log]]
-	error_check_good "FAIL: error message(s) in log files" $e 0
+	set errstrings [eval findfail [glob $testdir/test042.*.log]]
+	foreach str $errstrings {
+		puts "FAIL: error message in log file: $str"
+	}
 
 	# Test is done, blow away lock and mpool region
 	reset_env $env
 }
 
-# If we are renumbering, then each time we delete an item, the number of
-# items in the file is temporarily decreased, so the highest record numbers
-# do not exist.  To make sure this doesn't happen, we never generate the
-# highest few record numbers as keys.
-#
-# For record-based methods, record numbers begin at 1, while for other keys,
-# we begin at 0 to index into an array.
-proc rand_key { method nkeys renum procs} {
-	if { $renum == 1 } {
-		return [berkdb random_int 1 [expr $nkeys - $procs]]
-	} elseif { [is_record_based $method] == 1 } {
-		return [berkdb random_int 1 $nkeys]
-	} else {
-		return [berkdb random_int 0 [expr $nkeys - 1]]
-	}
-}
-
-proc test042_dbinit { env nentries method oargs tf ext } {
+proc test042_dbinit { env nentries method oargs tf } {
 	global datastr
 	source ./include.tcl
 
 	set omethod [convert_method $method]
 	set db [eval {berkdb_open -env $env -create \
-	    -mode 0644 $omethod} $oargs {$tf$ext}]
+	    -mode 0644 $omethod} $oargs $tf]
 	error_check_good dbopen [is_valid_db $db] TRUE
 
 	set did [open $dict]
@@ -164,7 +167,7 @@ proc test042_dbinit { env nentries method oargs tf ext } {
 	set count 0
 
 	# Here is the loop where we put each key/data pair
-	puts "\tTest042.a: put loop $tf$ext"
+	puts "\tTest042.a: put loop $tf"
 	while { [gets $did str] != -1 && $count < $nentries } {
 		if { [is_record_based $method] == 1 } {
 			set key [expr $count + 1]
diff --git a/storage/bdb/test/test043.tcl b/storage/bdb/test/test043.tcl
index eea7ec86d5481cadeffb9aa4949f46a4f43ab2a6..bbb934ccef194fc0fe5389b91f45574750f8a85f 100644
--- a/storage/bdb/test/test043.tcl
+++ b/storage/bdb/test/test043.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test043.tcl,v 11.17 2002/05/22 15:42:52 sue Exp $
+# $Id: test043.tcl,v 11.19 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test043
 # TEST	Recno renumbering and implicit creation test
diff --git a/storage/bdb/test/test044.tcl b/storage/bdb/test/test044.tcl
index 67cf3ea24b8fa433e9531853a17920a2745aa268..22d56a4345e1eff6e6b6a90f17bb2e37e80f046c 100644
--- a/storage/bdb/test/test044.tcl
+++ b/storage/bdb/test/test044.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test044.tcl,v 11.32 2002/07/16 20:53:04 bostic Exp $
+# $Id: test044.tcl,v 11.35 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test044
 # TEST	Small system integration tests
@@ -146,8 +146,10 @@ proc test044 { method {nprocs 5} {nfiles 10} {cont 0} args } {
 		}
 
 		# Check for test failure
-		set e [eval findfail [glob $testdir/test044.*.log]]
-		error_check_good "FAIL: error message(s) in log files" $e 0
+		set errstrings [eval findfail [glob $testdir/test044.*.log]]
+		foreach str $errstrings {
+			puts "FAIL: error message in log file: $str"
+		}
 
 		# Now run recovery
 		test044_verify $testdir $nfiles
diff --git a/storage/bdb/test/test045.tcl b/storage/bdb/test/test045.tcl
index 3825135facd9ac865c1fb7ae953ccfb86863209a..2b4c517ca86190af5041de88a140e7b327e01982 100644
--- a/storage/bdb/test/test045.tcl
+++ b/storage/bdb/test/test045.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test045.tcl,v 11.24 2002/02/07 17:50:10 sue Exp $
+# $Id: test045.tcl,v 11.27 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test045
 # TEST	Small random tester
@@ -101,8 +101,10 @@ proc test045 { method {nops 10000} args } {
 		    > $testdir/test045.init
 	}
 	# Check for test failure
-	set e [findfail $testdir/test045.init]
-	error_check_good "FAIL: error message(s) in init file" $e 0
+	set initerrs [findfail $testdir/test045.init]
+	foreach str $initerrs {
+		puts "FAIL: error message in .init file: $str"
+	}
 
 	puts "\tTest045.b: Now firing off berkdb rand dbscript, running: "
 	# Now the database is initialized, run a test
@@ -117,7 +119,8 @@ proc test045 { method {nops 10000} args } {
 	    > $testdir/test045.log
 
 	# Check for test failure
-	set e [findfail $testdir/test045.log]
-	error_check_good "FAIL: error message(s) in log file" $e 0
-
+	set logerrs [findfail $testdir/test045.log]
+	foreach str $logerrs {
+		puts "FAIL: error message in log file: $str"
+	}
 }
diff --git a/storage/bdb/test/test046.tcl b/storage/bdb/test/test046.tcl
index 4136f30aaa79fe997fd35bf6368d5892244f7655..63d0ec7c4860e6e8608d76aa90edaca041456c71 100644
--- a/storage/bdb/test/test046.tcl
+++ b/storage/bdb/test/test046.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test046.tcl,v 11.33 2002/05/24 15:24:55 sue Exp $
+# $Id: test046.tcl,v 11.36 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test046
 # TEST	Overwrite test of small/big key/data with cursor checks.
@@ -40,10 +40,10 @@ proc test046 { method args } {
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/test046.db
+		set testfile $testdir/test046
 		set env NULL
 	} else {
-		set testfile test046.db
+		set testfile test046
 		incr eindex
 		set env [lindex $args $eindex]
 		set txnenv [is_txnenv $env]
@@ -56,7 +56,7 @@ proc test046 { method args } {
 	cleanup $testdir $env
 
 	set oflags "-create -mode 0644 $args $omethod"
-	set db [eval {berkdb_open} $oflags $testfile.a]
+	set db [eval {berkdb_open} $oflags $testfile.a.db]
 	error_check_good dbopen [is_valid_db $db] TRUE
 
 	# keep nkeys even
@@ -256,7 +256,7 @@ proc test046 { method args } {
 		return
 	} else {
 		# Reopen without printing __db_errs.
-		set db [eval {berkdb_open_noerr} $oflags $testfile.a]
+		set db [eval {berkdb_open_noerr} $oflags $testfile.a.db]
 		error_check_good dbopen [is_valid_db $db] TRUE
 		if { $txnenv == 1 } {
 			set t [$env txn]
@@ -310,7 +310,7 @@ proc test046 { method args } {
 	}
 	error_check_good db:close [$db close] 0
 
-	set db [eval {berkdb_open} $oflags $testfile.d]
+	set db [eval {berkdb_open} $oflags $testfile.d.db]
 	error_check_good dbopen [is_valid_db $db] TRUE
 	# Fill page w/ small key/data pairs
 	puts "\tTest046.d.0: Fill page with $nkeys small key/data pairs."
@@ -440,7 +440,7 @@ proc test046 { method args } {
 	}
 
 	puts "\tTest046.e.1: Open db with sorted dups."
-	set db [eval {berkdb_open_noerr} $oflags -dup -dupsort $testfile.e]
+	set db [eval {berkdb_open_noerr} $oflags -dup -dupsort $testfile.e.db]
 	error_check_good dbopen [is_valid_db $db] TRUE
 
 	# keep nkeys even
@@ -564,7 +564,7 @@ proc test046 { method args } {
 
 	# Reopen database without __db_err, reset cursor
 	error_check_good dbclose [$db close] 0
-	set db [eval {berkdb_open_noerr} $oflags -dup -dupsort $testfile.e]
+	set db [eval {berkdb_open_noerr} $oflags -dup -dupsort $testfile.e.db]
 	error_check_good dbopen [is_valid_db $db] TRUE
 	if { $txnenv == 1 } {
 		set t [$env txn]
@@ -646,7 +646,7 @@ proc test046 { method args } {
 	error_check_good db_close [$db close] 0
 
 	set db [eval {berkdb_open} \
-	    $oflags -dup $testfile.h]
+	    $oflags -dup $testfile.h.db]
 	error_check_good db_open [is_valid_db $db] TRUE
 	if { $txnenv == 1 } {
 		set t [$env txn]
diff --git a/storage/bdb/test/test047.tcl b/storage/bdb/test/test047.tcl
index 61c1d0864c51ec5891a614f77444f121e94d6b19..48b6fc759ab840b667428beaf44762e09f365632 100644
--- a/storage/bdb/test/test047.tcl
+++ b/storage/bdb/test/test047.tcl
@@ -1,47 +1,47 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test047.tcl,v 11.19 2002/08/05 19:23:51 sandstro Exp $
+# $Id: test047.tcl,v 11.22 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test047
 # TEST	DBcursor->c_get get test with SET_RANGE option.
 proc test047 { method args } {
 	source ./include.tcl
 
-	set tstn 047
+	set tnum 047
 	set args [convert_args $method $args]
 
 	if { [is_btree $method] != 1 } {
-		puts "Test$tstn skipping for method $method"
+		puts "Test$tnum skipping for method $method"
 		return
 	}
 
 	set method "-btree"
 
-	puts "\tTest$tstn: Test of SET_RANGE interface to DB->c_get ($method)."
+	puts "\tTest$tnum: Test of SET_RANGE interface to DB->c_get ($method)."
 
 	set key	"key"
 	set data	"data"
 	set txn ""
 	set flags ""
 
-	puts "\tTest$tstn.a: Create $method database."
+	puts "\tTest$tnum.a: Create $method database."
 	set eindex [lsearch -exact $args "-env"]
 	set txnenv 0
 	#
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tstn.db
-		set testfile1 $testdir/test0$tstn.a.db
-		set testfile2 $testdir/test0$tstn.b.db
+		set testfile $testdir/test$tnum.db
+		set testfile1 $testdir/test$tnum.a.db
+		set testfile2 $testdir/test$tnum.b.db
 		set env NULL
 	} else {
-		set testfile test0$tstn.db
-		set testfile1 test0$tstn.a.db
-		set testfile2 test0$tstn.b.db
+		set testfile test$tnum.db
+		set testfile1 test$tnum.a.db
+		set testfile2 test$tnum.b.db
 		incr eindex
 		set env [lindex $args $eindex]
 		set txnenv [is_txnenv $env]
@@ -60,7 +60,7 @@ proc test047 { method args } {
 	set nkeys 20
 	# Fill page w/ small key/data pairs
 	#
-	puts "\tTest$tstn.b: Fill page with $nkeys small key/data pairs."
+	puts "\tTest$tnum.b: Fill page with $nkeys small key/data pairs."
 	for { set i 0 } { $i < $nkeys } { incr i } {
 		if { $txnenv == 1 } {
 			set t [$env txn]
@@ -83,7 +83,7 @@ proc test047 { method args } {
 	set dbc [eval {$db cursor} $txn]
 	error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
 
-	puts "\tTest$tstn.c: Get data with SET_RANGE, then delete by cursor."
+	puts "\tTest$tnum.c: Get data with SET_RANGE, then delete by cursor."
 	set i 0
 	set ret [$dbc get -set_range $key$i]
 	error_check_bad dbc_get:set_range [llength $ret] 0
@@ -96,7 +96,7 @@ proc test047 { method args } {
 	error_check_bad dbc_get(post-delete):set_range [llength $ret] 0
 	error_check_bad dbc_get(no-match):set_range $ret $curr
 
-	puts "\tTest$tstn.d: \
+	puts "\tTest$tnum.d: \
 	    Use another cursor to fix item on page, delete by db."
 	set dbcurs2 [eval {$db cursor} $txn]
 	error_check_good db:cursor2 [is_valid_cursor $dbcurs2 $db] TRUE
@@ -112,7 +112,7 @@ proc test047 { method args } {
 	error_check_bad dbc2_get:set_range [llength $ret] 0
 	error_check_bad dbc2_get:set_range $ret $curr
 
-	puts "\tTest$tstn.e: Close for second part of test, close db/cursors."
+	puts "\tTest$tnum.e: Close for second part of test, close db/cursors."
 	error_check_good dbc:close [$dbc close] 0
 	error_check_good dbc2:close [$dbcurs2 close] 0
 	if { $txnenv == 1 } {
@@ -125,7 +125,7 @@ proc test047 { method args } {
 	error_check_good dbopen2 [is_valid_db $db] TRUE
 
 	set nkeys 10
-	puts "\tTest$tstn.f: Fill page with $nkeys pairs, one set of dups."
+	puts "\tTest$tnum.f: Fill page with $nkeys pairs, one set of dups."
 	for {set i 0} { $i < $nkeys } {incr i} {
 		# a pair
 		if { $txnenv == 1 } {
@@ -155,7 +155,7 @@ proc test047 { method args } {
 		}
 	}
 
-	puts "\tTest$tstn.g: \
+	puts "\tTest$tnum.g: \
 	    Get dups key w/ SET_RANGE, pin onpage with another cursor."
 	set i 0
 	if { $txnenv == 1 } {
@@ -174,7 +174,7 @@ proc test047 { method args } {
 	error_check_bad dbc2_get:set_range [llength $ret] 0
 
 	error_check_good dbc_compare $ret $ret2
-	puts "\tTest$tstn.h: \
+	puts "\tTest$tnum.h: \
 	    Delete duplicates' key, use SET_RANGE to get next dup."
 	set ret [$dbc2 del]
 	error_check_good dbc2_del $ret 0
@@ -195,7 +195,7 @@ proc test047 { method args } {
 	set nkeys 10
 	set ndups 1000
 
-	puts "\tTest$tstn.i: Fill page with $nkeys pairs and $ndups dups."
+	puts "\tTest$tnum.i: Fill page with $nkeys pairs and $ndups dups."
 	for {set i 0} { $i < $nkeys } { incr i} {
 		# a pair
 		if { $txnenv == 1 } {
@@ -228,7 +228,7 @@ proc test047 { method args } {
 	error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
 	set dbc2 [eval {$db cursor} $txn]
 	error_check_good db_cursor [is_valid_cursor $dbc2 $db] TRUE
-	puts "\tTest$tstn.j: \
+	puts "\tTest$tnum.j: \
 	    Get key of first dup with SET_RANGE, fix with 2 curs."
 	set ret [$dbc get -set_range $key$i]
 	error_check_bad dbc_get:set_range [llength $ret] 0
@@ -239,14 +239,14 @@ proc test047 { method args } {
 
 	error_check_good dbc_compare $ret $ret2
 
-	puts "\tTest$tstn.k: Delete item by cursor, use SET_RANGE to verify."
+	puts "\tTest$tnum.k: Delete item by cursor, use SET_RANGE to verify."
 	set ret [$dbc2 del]
 	error_check_good dbc2_del $ret 0
 	set ret [$dbc get -set_range $key$i]
 	error_check_bad dbc_get:set_range [llength $ret] 0
 	error_check_bad dbc_get:set_range $ret $curr
 
-	puts "\tTest$tstn.l: Cleanup."
+	puts "\tTest$tnum.l: Cleanup."
 	error_check_good dbc_close [$dbc close] 0
 	error_check_good dbc2_close [$dbc2 close] 0
 	if { $txnenv == 1 } {
@@ -254,5 +254,5 @@ proc test047 { method args } {
 	}
 	error_check_good db_close [$db close] 0
 
-	puts "\tTest$tstn complete."
+	puts "\tTest$tnum complete."
 }
diff --git a/storage/bdb/test/test048.tcl b/storage/bdb/test/test048.tcl
index 2131f6f553c41692415d266b95605c94006be3e2..db73b2b6dccb398b71f3b813818ffa9085e08762 100644
--- a/storage/bdb/test/test048.tcl
+++ b/storage/bdb/test/test048.tcl
@@ -1,21 +1,22 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test048.tcl,v 11.18 2002/07/29 20:27:49 sandstro Exp $
+# $Id: test048.tcl,v 11.22 2004/05/13 18:51:43 mjc Exp $
 #
 # TEST	test048
 # TEST	Cursor stability across Btree splits.
 proc test048 { method args } {
 	global errorCode
+	global is_je_test
 	source ./include.tcl
 
-	set tstn 048
+	set tnum 048
 	set args [convert_args $method $args]
 
 	if { [is_btree $method] != 1 } {
-		puts "Test$tstn skipping for method $method."
+		puts "Test$tnum skipping for method $method."
 		return
 	}
 	set pgindex [lsearch -exact $args "-pagesize"]
@@ -29,24 +30,24 @@ proc test048 { method args } {
 
 	set method "-btree"
 
-	puts "\tTest$tstn: Test of cursor stability across btree splits."
+	puts "\tTest$tnum: Test of cursor stability across btree splits."
 
 	set key	"key"
 	set data	"data"
 	set txn ""
 	set flags ""
 
-	puts "\tTest$tstn.a: Create $method database."
+	puts "\tTest$tnum.a: Create $method database."
 	set txnenv 0
 	set eindex [lsearch -exact $args "-env"]
 	#
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tstn.db
+		set testfile $testdir/test$tnum.db
 		set env NULL
 	} else {
-		set testfile test0$tstn.db
+		set testfile test$tnum.db
 		incr eindex
 		set env [lindex $args $eindex]
 		set txnenv [is_txnenv $env]
@@ -65,7 +66,7 @@ proc test048 { method args } {
 	set nkeys 5
 	# Fill page w/ small key/data pairs, keep at leaf
 	#
-	puts "\tTest$tstn.b: Fill page with $nkeys small key/data pairs."
+	puts "\tTest$tnum.b: Fill page with $nkeys small key/data pairs."
 	for { set i 0 } { $i < $nkeys } { incr i } {
 		if { $txnenv == 1 } {
 			set t [$env txn]
@@ -80,7 +81,7 @@ proc test048 { method args } {
 	}
 
 	# get db ordering, set cursors
-	puts "\tTest$tstn.c: Set cursors on each of $nkeys pairs."
+	puts "\tTest$tnum.c: Set cursors on each of $nkeys pairs."
 	if { $txnenv == 1 } {
 		set t [$env txn]
 		error_check_good txn [is_valid_txn $t $env] TRUE
@@ -101,7 +102,7 @@ proc test048 { method args } {
 
 	# if mkeys is above 1000, need to adjust below for lexical order
 	set mkeys 1000
-	puts "\tTest$tstn.d: Add $mkeys pairs to force split."
+	puts "\tTest$tnum.d: Add $mkeys pairs to force split."
 	for {set i $nkeys} { $i < $mkeys } { incr i } {
 		if { $i >= 100 } {
 			set ret [eval {$db put} $txn {key0$i $data$i}]
@@ -113,14 +114,14 @@ proc test048 { method args } {
 		error_check_good dbput:more $ret 0
 	}
 
-	puts "\tTest$tstn.e: Make sure split happened."
+	puts "\tTest$tnum.e: Make sure split happened."
 	# XXX We cannot call stat with active txns or we deadlock.
-	if { $txnenv != 1 } {
+	if { $txnenv != 1 && !$is_je_test } {
 		error_check_bad stat:check-split [is_substr [$db stat] \
 					"{{Internal pages} 0}"] 1
 	}
 
-	puts "\tTest$tstn.f: Check to see that cursors maintained reference."
+	puts "\tTest$tnum.f: Check to see that cursors maintained reference."
 	for {set i 0} { $i < $nkeys } {incr i} {
 		set ret [$dbc_set($i) get -current]
 		error_check_bad dbc$i:get:current [llength $ret] 0
@@ -129,7 +130,7 @@ proc test048 { method args } {
 		error_check_good dbc$i:get(match) $ret $ret2
 	}
 
-	puts "\tTest$tstn.g: Delete added keys to force reverse split."
+	puts "\tTest$tnum.g: Delete added keys to force reverse split."
 	for {set i $nkeys} { $i < $mkeys } { incr i } {
 		if { $i >= 100 } {
 			error_check_good db_del:$i \
@@ -143,7 +144,7 @@ proc test048 { method args } {
 		}
 	}
 
-	puts "\tTest$tstn.h: Verify cursor reference."
+	puts "\tTest$tnum.h: Verify cursor reference."
 	for {set i 0} { $i < $nkeys } {incr i} {
 		set ret [$dbc_set($i) get -current]
 		error_check_bad dbc$i:get:current [llength $ret] 0
@@ -152,7 +153,7 @@ proc test048 { method args } {
 		error_check_good dbc$i:get(match) $ret $ret2
 	}
 
-	puts "\tTest$tstn.i: Cleanup."
+	puts "\tTest$tnum.i: Cleanup."
 	# close cursors
 	for {set i 0} { $i < $nkeys } {incr i} {
 		error_check_good dbc_close:$i [$dbc_set($i) close] 0
@@ -160,11 +161,11 @@ proc test048 { method args } {
 	if { $txnenv == 1 } {
 		error_check_good txn [$t commit] 0
 	}
-	puts "\tTest$tstn.j: Verify reverse split."
+	puts "\tTest$tnum.j: Verify reverse split."
 	error_check_good stat:check-reverse_split [is_substr [$db stat] \
 					"{{Internal pages} 0}"] 1
 
 	error_check_good dbclose [$db close] 0
 
-	puts "\tTest$tstn complete."
+	puts "\tTest$tnum complete."
 }
diff --git a/storage/bdb/test/test049.tcl b/storage/bdb/test/test049.tcl
index 3040727c4691594ce395adff31d005a4bdc22a69..f8d173380c8a9f0c2668e1a3c4fc778edcab5449 100644
--- a/storage/bdb/test/test049.tcl
+++ b/storage/bdb/test/test049.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test049.tcl,v 11.21 2002/05/22 15:42:53 sue Exp $
+# $Id: test049.tcl,v 11.24 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test049
 # TEST	Cursor operations on uninitialized cursors.
@@ -12,13 +12,13 @@ proc test049 { method args } {
 	global errorCode
 	source ./include.tcl
 
-	set tstn 049
+	set tnum 049
 	set renum [is_rrecno $method]
 
 	set args [convert_args $method $args]
 	set omethod [convert_method $method]
 
-	puts "\tTest$tstn: Test of cursor routines with uninitialized cursors."
+	puts "\tTest$tnum: Test of cursor routines with uninitialized cursors."
 
 	set key	"key"
 	set data	"data"
@@ -30,17 +30,17 @@ proc test049 { method args } {
 		set key ""
 	}
 
-	puts "\tTest$tstn.a: Create $method database."
+	puts "\tTest$tnum.a: Create $method database."
 	set txnenv 0
 	set eindex [lsearch -exact $args "-env"]
 	#
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tstn.db
+		set testfile $testdir/test$tnum.db
 		set env NULL
 	} else {
-		set testfile test0$tstn.db
+		set testfile test$tnum.db
 		incr eindex
 		set env [lindex $args $eindex]
 		set txnenv [is_txnenv $env]
@@ -60,7 +60,7 @@ proc test049 { method args } {
 	error_check_good dbopen [is_valid_db $db] TRUE
 
 	set nkeys 10
-	puts "\tTest$tstn.b: Fill page with $nkeys small key/data pairs."
+	puts "\tTest$tnum.b: Fill page with $nkeys small key/data pairs."
 	for { set i 1 } { $i <= $nkeys } { incr i } {
 		if { $txnenv == 1 } {
 			set t [$env txn]
@@ -90,7 +90,7 @@ proc test049 { method args } {
 	set dbc_u [eval {$db cursor} $txn]
 	error_check_good db:cursor [is_valid_cursor $dbc_u $db] TRUE
 
-	puts "\tTest$tstn.c: Test dbc->get interfaces..."
+	puts "\tTest$tnum.c: Test dbc->get interfaces..."
 	set i 0
 	foreach flag { current first last next prev nextdup} {
 		puts "\t\t...dbc->get($flag)"
@@ -116,7 +116,7 @@ proc test049 { method args } {
 	catch {$dbc_u get -rmw -current } ret
 	error_check_good dbc_get:rmw [is_substr $errorCode EINVAL] 1
 
-	puts "\tTest$tstn.d: Test dbc->put interface..."
+	puts "\tTest$tnum.d: Test dbc->put interface..."
 	# partial...depends on another
 	foreach flag { after before current keyfirst keylast } {
 		puts "\t\t...dbc->put($flag)"
@@ -170,7 +170,7 @@ proc test049 { method args } {
 
 	# XXX dbc->dup, db->join (dbc->get join_item)
 	# dbc del
-	puts "\tTest$tstn.e: Test dbc->del interface."
+	puts "\tTest$tnum.e: Test dbc->del interface."
 	catch {$dbc_u del} ret
 	error_check_good dbc_del [is_substr $errorCode EINVAL] 1
 
@@ -180,5 +180,5 @@ proc test049 { method args } {
 	}
 	error_check_good db_close [$db close] 0
 
-	puts "\tTest$tstn complete."
+	puts "\tTest$tnum complete."
 }
diff --git a/storage/bdb/test/test050.tcl b/storage/bdb/test/test050.tcl
index dfaeddd035ca175ebac5c8fc7779b82561543b26..72be5af67f97c584343347469f5fb0430ec709d3 100644
--- a/storage/bdb/test/test050.tcl
+++ b/storage/bdb/test/test050.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test050.tcl,v 11.21 2002/05/24 14:15:13 bostic Exp $
+# $Id: test050.tcl,v 11.23 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test050
 # TEST	Overwrite test of small/big key/data with cursor checks for Recno.
diff --git a/storage/bdb/test/test051.tcl b/storage/bdb/test/test051.tcl
index 830b76307882998db55ae4a880e027376a40ce7b..5e09835e3c27a9e16e1318459732f9d48b10010f 100644
--- a/storage/bdb/test/test051.tcl
+++ b/storage/bdb/test/test051.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test051.tcl,v 11.21 2002/05/24 13:43:24 sue Exp $
+# $Id: test051.tcl,v 11.25 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test051
 # TEST	Fixed-length record Recno test.
@@ -99,15 +99,16 @@ proc test051 { method { args "" } } {
 			puts "\t\tTest051.e: dlen: $dlen, doff: $doff, \
 			    size: [expr $dlen+1]"
 			set data [repeat $test_char [expr $dlen + 1]]
-			error_check_good catch:put 1 [catch {eval {$db put -partial \
+			error_check_good \
+			    catch:put 1 [catch {eval {$db put -partial \
 			    [list $doff $dlen]} $txn {$key $data}} ret]
-			#
+
 			# We don't get back the server error string just
 			# the result.
-			#
 			if { $eindex == -1 } {
 				error_check_good "dbput:partial: dlen < size" \
-				    [is_substr $errorInfo "Length improper"] 1
+				    [is_substr \
+				    $errorInfo "Record length error"] 1
 			} else {
 				error_check_good "dbput:partial: dlen < size" \
 				    [is_substr $errorCode "EINVAL"] 1
@@ -117,11 +118,13 @@ proc test051 { method { args "" } } {
 			puts "\t\tTest051.e: dlen: $dlen, doff: $doff, \
 			    size: [expr $dlen-1]"
 			set data [repeat $test_char [expr $dlen - 1]]
-			error_check_good catch:put 1 [catch {eval {$db put -partial \
+			error_check_good \
+			    catch:put 1 [catch {eval {$db put -partial \
 			    [list $doff $dlen]} $txn {$key $data}} ret]
 			if { $eindex == -1 } {
 				error_check_good "dbput:partial: dlen > size" \
-				    [is_substr $errorInfo "Length improper"] 1
+				    [is_substr \
+				    $errorInfo "Record length error"] 1
 			} else {
 				error_check_good "dbput:partial: dlen < size" \
 				    [is_substr $errorCode "EINVAL"] 1
@@ -183,7 +186,7 @@ proc test051 { method { args "" } } {
 		set ret [eval {$db put} $txn {$key $data}]
 		error_check_good dbput:init $ret 0
 
-		puts "\t\t  Test051.g: Replace at offset $doff."
+		puts "\t\tTest051.g: Replace at offset $doff."
 		set ret [eval {$db put -partial [list $doff $dlen]} $txn \
 		    {$key $pdata}]
 		error_check_good dbput:partial $ret 0
diff --git a/storage/bdb/test/test052.tcl b/storage/bdb/test/test052.tcl
index 1f3864496302176409a2437827060efed4e092b8..c7d891d33c74b373f62565ae9528d6df80a9cfab 100644
--- a/storage/bdb/test/test052.tcl
+++ b/storage/bdb/test/test052.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test052.tcl,v 11.16 2002/07/08 20:48:58 sandstro Exp $
+# $Id: test052.tcl,v 11.20 2004/09/20 17:06:16 sue Exp $
 #
 # TEST	test052
 # TEST	Renumbering record Recno test.
@@ -88,7 +88,7 @@ proc test052 { method args } {
 	}
 
 	puts "\tTest052: Deletes by key."
-	puts "\t  Test052.a: Get data with SET, then delete before cursor."
+	puts "\tTest052.a: Get data with SET, then delete before cursor."
 	# get key in middle of page, call this the nth set curr to it
 	set i [expr $nkeys/2]
 	set k $keys($i)
@@ -106,7 +106,7 @@ proc test052 { method args } {
 	error_check_good dbc:keys \
 	    [lindex [lindex [$dbc get -current] 0] 0] $keys([expr $nkeys/2 - 1])
 
-	puts "\t  Test052.b: Delete cursor item by key."
+	puts "\tTest052.b: Delete cursor item by key."
 	set i [expr $nkeys/2 ]
 
 	set ret [$dbc get -set $keys($i)]
@@ -129,7 +129,7 @@ proc test052 { method args } {
 	error_check_good dbc:getnext:keys \
 	    [lindex [lindex $ret 0] 0] $keys($i)
 
-	puts "\t  Test052.c: Delete item after cursor."
+	puts "\tTest052.c: Delete item after cursor."
 	# should be { keys($nkeys/2), darray($nkeys/2 + 2) }
 	set i [expr $nkeys/2]
 	# deleting data for key after current (key $nkeys/2 + 1)
@@ -144,18 +144,14 @@ proc test052 { method args } {
 	    $darray([expr $i + 2])
 
 	puts "\tTest052: Deletes by cursor."
-	puts "\t  Test052.d: Delete, do DB_NEXT."
+	puts "\tTest052.d: Delete, do DB_NEXT."
 	set i 1
 	set ret [$dbc get -first]
 	error_check_bad dbc_get:first [llength $ret] 0
 	error_check_good dbc_get:first [lindex [lindex $ret 0] 1] $darray($i)
 	error_check_good dbc_del [$dbc del] 0
 	set ret [$dbc get -current]
-	error_check_bad dbc_get:current [llength $ret] 0
-	error_check_good dbc:getcurrent:key \
-	    [llength [lindex [lindex $ret 0] 0]] 0
-	error_check_good dbc:getcurrent:data \
-	    [llength [lindex [lindex $ret 0] 1]] 0
+	error_check_good dbc_get:current [llength $ret] 0
 
 	set ret [$dbc get -next]
 	error_check_bad dbc_get:next [llength $ret] 0
@@ -167,14 +163,10 @@ proc test052 { method args } {
 	# Move one more forward, so we're not on the first item.
 	error_check_bad dbc:getnext [llength [$dbc get -next]] 0
 
-	puts "\t  Test052.e: Delete, do DB_PREV."
+	puts "\tTest052.e: Delete, do DB_PREV."
 	error_check_good dbc:del [$dbc del] 0
 	set ret [$dbc get -current]
-	error_check_bad dbc:get:curr [llength $ret] 0
-	error_check_good dbc:getcurrent:key \
-	    [llength [lindex [lindex $ret 0] 0]] 0
-	error_check_good dbc:getcurrent:data \
-	    [llength [lindex [lindex $ret 0] 1]] 0
+	error_check_good dbc:get:curr [llength $ret] 0
 
 	# next should now reference the record that was previously after
 	# old current
@@ -185,6 +177,7 @@ proc test052 { method args } {
 	error_check_good dbc:get:next:keys \
 	    [lindex [lindex $ret 0] 0] $keys([expr $i + 1])
 
+
 	set ret [$dbc get -prev]
 	error_check_bad dbc:get:curr [llength $ret] 0
 	error_check_good dbc:get:curr:compare \
@@ -200,7 +193,7 @@ proc test052 { method args } {
 	error_check_good delfirst [$dbc del] 0
 
 	puts "\tTest052: Inserts."
-	puts "\t  Test052.g: Insert before (DB_BEFORE)."
+	puts "\tTest052.g: Insert before (DB_BEFORE)."
 	set i 1
 	set ret [$dbc get -first]
 	error_check_bad dbc:get:first [llength $ret] 0
@@ -227,7 +220,7 @@ proc test052 { method args } {
 	set ret [$dbc get -prev]
 	error_check_bad dbc_get:prev [llength $ret] 0
 
-	puts "\t  Test052.h: Insert by cursor after (DB_AFTER)."
+	puts "\tTest052.h: Insert by cursor after (DB_AFTER)."
 	set i [incr i]
 	set ret [$dbc put -after $darray($i)]
 	# should return new key, which should be $keys($i)
@@ -245,7 +238,7 @@ proc test052 { method args } {
 	error_check_good dbc:get:next:compare \
 	    $ret [list [list $keys([expr $i + 1]) $darray([expr $i + 2])]]
 
-	puts "\t  Test052.i: Insert (overwrite) current item (DB_CURRENT)."
+	puts "\tTest052.i: Insert (overwrite) current item (DB_CURRENT)."
 	set i 1
 	set ret [$dbc get -first]
 	error_check_bad dbc_get:first [llength $ret] 0
diff --git a/storage/bdb/test/test053.tcl b/storage/bdb/test/test053.tcl
index 3e217a2b55f6f4e6e693da9911e6c3648768e59e..5c5e060ec4802e6e31b70b07274f3d4f18aad09e 100644
--- a/storage/bdb/test/test053.tcl
+++ b/storage/bdb/test/test053.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test053.tcl,v 11.18 2002/05/24 15:24:55 sue Exp $
+# $Id: test053.tcl,v 11.21 2004/05/13 18:51:43 mjc Exp $
 #
 # TEST	test053
 # TEST	Test of the DB_REVSPLITOFF flag in the Btree and Btree-w-recnum
@@ -11,6 +11,7 @@
 proc test053 { method args } {
 	global alphabet
 	global errorCode
+	global is_je_test
 	source ./include.tcl
 
 	set args [convert_args $method $args]
@@ -97,9 +98,11 @@ proc test053 { method args } {
 		}
 	}
 
-	puts "\tTest053.c: Check page count."
-	error_check_good page_count:check \
-	    [is_substr [$db stat] "{Leaf pages} $npages"] 1
+	if { !$is_je_test } {
+		puts "\tTest053.c: Check page count."
+		error_check_good page_count:check \
+		    [is_substr [$db stat] "{Leaf pages} $npages"] 1
+	}
 
 	puts "\tTest053.d: Delete all but one key per page."
 	for {set i 0} { $i < $npages } {incr i } {
@@ -116,9 +119,12 @@ proc test053 { method args } {
 			}
 		}
 	}
-	puts "\tTest053.e: Check to make sure all pages are still there."
-	error_check_good page_count:check \
-	    [is_substr [$db stat] "{Leaf pages} $npages"] 1
+
+	if { !$is_je_test } {
+		puts "\tTest053.e: Check to make sure all pages are still there."
+		error_check_good page_count:check \
+		    [is_substr [$db stat] "{Leaf pages} $npages"] 1
+	}
 
 	if { $txnenv == 1 } {
 		set t [$env txn]
diff --git a/storage/bdb/test/test054.tcl b/storage/bdb/test/test054.tcl
index f53f5a658bfb841404c303b2b6ef0adff50e9dd7..44d0335f469ab51244d3680b9e987d944a579f47 100644
--- a/storage/bdb/test/test054.tcl
+++ b/storage/bdb/test/test054.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test054.tcl,v 11.23 2002/06/17 18:41:29 sue Exp $
+# $Id: test054.tcl,v 11.26 2004/09/20 17:06:16 sue Exp $
 #
 # TEST	test054
 # TEST	Cursor maintenance during key/data deletion.
@@ -191,7 +191,7 @@ proc test054 { method args } {
 	    db_del:$key_set(3) [eval {$db del} $txn {$key_set(3)}] 0
 	# NEEDS TO COME BACK IN, BUG CHECK
 	set ret [$curs get -current]
-	error_check_good current_after_del $ret [list [list [] []]]
+	error_check_good current_after_del $ret ""
 	error_check_good cursor_close [$curs close] 0
 	if { $txnenv == 1 } {
 		error_check_good txn [$t commit] 0
@@ -371,8 +371,7 @@ proc test054 { method args } {
 	# Verify curs1 and curs2
 	# current should fail
 	set ret [$curs get -current]
-	error_check_good \
-	    curs1_get_after_del $ret [list [list [] []]]
+	error_check_good curs1_get_after_del $ret ""
 
 	set r [$curs2 get -current]
 	error_check_bad curs2_get [llength $r] 0
@@ -386,10 +385,10 @@ proc test054 { method args } {
 
 	# Verify curs1 and curs2
 	set ret [$curs get -current]
-	error_check_good curs1_get:del2 $ret [list [list [] []]]
+	error_check_good curs1_get:del2 $ret ""
 
 	set ret [$curs2 get -current]
-	error_check_good curs2_get:del2 $ret [list [list [] []]]
+	error_check_good curs2_get:del2 $ret ""
 
 	# Now verify that next and prev work.
 
@@ -430,10 +429,10 @@ proc test054 { method args } {
 	# Verify gets on both 1 and 2
 	set ret [$curs get -current]
 	error_check_good \
-	    curs1_get:deleted $ret [list [list [] []]]
+	    curs1_get:deleted $ret ""
 	set ret [$curs2 get -current]
 	error_check_good \
-	    curs2_get:deleted $ret [list [list [] []]]
+	    curs2_get:deleted $ret ""
 
 	puts "\tTest054.b5: Now do a next on both cursors"
 
diff --git a/storage/bdb/test/test055.tcl b/storage/bdb/test/test055.tcl
index 25134dca4bebcf8bf007add3e1d31b25954ae35b..96bf108c308a0b7d8887a8166d5fe5ae2c0f1545 100644
--- a/storage/bdb/test/test055.tcl
+++ b/storage/bdb/test/test055.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test055.tcl,v 11.16 2002/05/22 15:42:55 sue Exp $
+# $Id: test055.tcl,v 11.18 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test055
 # TEST	Basic cursor operations.
diff --git a/storage/bdb/test/test056.tcl b/storage/bdb/test/test056.tcl
index ef310332ed1147cd194ee0e68402c3dd71edb7d5..f689d659230d54bf6649f0ae018dffcb3d7d1c88 100644
--- a/storage/bdb/test/test056.tcl
+++ b/storage/bdb/test/test056.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test056.tcl,v 11.18 2002/05/22 15:42:55 sue Exp $
+# $Id: test056.tcl,v 11.21 2004/09/20 17:06:16 sue Exp $
 #
 # TEST	test056
 # TEST	Cursor maintenance during deletes.
@@ -118,7 +118,7 @@ proc test056 { method args } {
 
 	# Now check the get current on the cursor.
 	set ret [$curs get -current]
-	error_check_good curs_after_del $ret [list [list [] []]]
+	error_check_good curs_after_del $ret ""
 
 	# Now check that the rest of the database looks intact.  There
 	# should be only two keys, 1 and 3.
diff --git a/storage/bdb/test/test057.tcl b/storage/bdb/test/test057.tcl
index 04fb09ef260422a60a2f93c7b48886fdb076a69f..56fe2bf44ec72a9e1e5d8afea55a3589613a7e18 100644
--- a/storage/bdb/test/test057.tcl
+++ b/storage/bdb/test/test057.tcl
@@ -1,17 +1,18 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test057.tcl,v 11.22 2002/05/22 15:42:56 sue Exp $
+# $Id: test057.tcl,v 11.26 2004/09/20 17:06:16 sue Exp $
 #
 # TEST	test057
 # TEST	Cursor maintenance during key deletes.
-# TEST	Check if we handle the case where we delete a key with the cursor on
-# TEST	it and then add the same key.  The cursor should not get the new item
-# TEST	returned, but the item shouldn't disappear.
-# TEST	Run test tests, one where the overwriting put is done with a put and
-# TEST	one where it's done with a cursor put.
+# TEST	1.  Delete a key with a cursor.  Add the key back with a regular
+# TEST	put.  Make sure the cursor can't get the new item.
+# TEST	2.  Put two cursors on one item.  Delete through one cursor,
+# TEST	check that the other sees the change.
+# TEST	3.  Same as 2, with the two cursors on a duplicate.
+
 proc test057 { method args } {
 	global errorInfo
 	source ./include.tcl
@@ -105,7 +106,7 @@ proc test057 { method args } {
 	error_check_good delete $r 0
 
 	# Now check the get current on the cursor.
-	error_check_good curs_get:del [$curs get -current] [list [list [] []]]
+	error_check_good curs_get:del [$curs get -current] ""
 
 	# Now do a put on the key
 	set r [eval {$db put} $txn $flags {$key_set(1) new_datum$key_set(1)}]
@@ -116,7 +117,7 @@ proc test057 { method args } {
 	error_check_good get [lindex [lindex $r 0] 1] new_datum$key_set(1)
 
 	# Recheck cursor
-	error_check_good curs_get:deleted [$curs get -current] [list [list [] []]]
+	error_check_good curs_get:deleted [$curs get -current] ""
 
 	# Move cursor and see if we get the key.
 	set r [$curs get -first]
@@ -149,37 +150,8 @@ proc test057 { method args } {
 	error_check_good curs1_del [$curs del] 0
 
 	# Verify gets on both 1 and 2
-	error_check_good curs_get:deleted [$curs get -current] \
-	    [list [list [] []]]
-	error_check_good curs_get:deleted [$curs2 get -current] \
-	    [list [list [] []]]
-
-	# Now do a replace through cursor 2
-	set pflags "-current"
-	if {[is_hash $method] == 1} {
-		error_check_good curs1_get_after_del [is_substr \
-		    [$curs2 put $pflags new_datum$key_set(3)] "DB_NOTFOUND"] 1
-
-		# Gets fail
-		error_check_good curs1_get:deleted  \
-		    [$curs get -current] \
-		    [list [list [] []]]
-		error_check_good curs2_get:deleted  \
-		    [$curs get -current] \
-		    [list [list [] []]]
-	} else {
-		# btree only, recno is skipped this test
-		set ret [$curs2 put $pflags new_datum$key_set(3)]
-		error_check_good curs_replace $ret 0
-	}
-
-	# Gets fail
-	#error_check_good curs1_get:deleted [catch {$curs get -current} r] 1
-	#error_check_good curs1_get_after_del \
-	    [is_substr $errorInfo "DB_KEYEMPTY"] 1
-	#error_check_good curs2_get:deleted [catch {$curs2 get -current} r] 1
-	#error_check_good curs2_get_after_del \
-	    [is_substr $errorInfo "DB_KEYEMPTY"] 1
+	error_check_good curs_get:deleted [$curs get -current] ""
+	error_check_good curs_get:deleted [$curs2 get -current] ""
 
 	puts "\tTest057.c:\
 	    Set two cursors on a dup, delete one, overwrite other"
@@ -217,27 +189,8 @@ proc test057 { method args } {
 	error_check_good curs1_del [$curs del] 0
 
 	# Verify gets on both 1 and 2
-	error_check_good curs_get:deleted [$curs get -current] \
-	    [list [list [] []]]
-	error_check_good curs_get:deleted [$curs2 get -current] \
-	    [list [list [] []]]
-
-	# Now do a replace through cursor 2 -- this will work on btree but
-	# not on hash
-	if {[is_hash $method] == 1} {
-		error_check_good hash_replace \
-		    [is_substr [$curs2 put -current new_dup_1] "DB_NOTFOUND"] 1
-	} else {
-		error_check_good curs_replace [$curs2 put -current new_dup_1] 0
-	}
-
-	# Both gets should fail
-	#error_check_good curs1_get:deleted [catch {$curs get -current} r] 1
-	#error_check_good curs1_get_after_del \
-	    [is_substr $errorInfo "DB_KEYEMPTY"] 1
-	#error_check_good curs2_get:deleted [catch {$curs2 get -current} r] 1
-	#error_check_good curs2_get_after_del \
-	    [is_substr $errorInfo "DB_KEYEMPTY"] 1
+	error_check_good curs_get:deleted [$curs get -current] ""
+	error_check_good curs_get:deleted [$curs2 get -current] ""
 
 	error_check_good curs2_close [$curs2 close] 0
 	error_check_good curs_close [$curs close] 0
diff --git a/storage/bdb/test/test058.tcl b/storage/bdb/test/test058.tcl
index daf164fd6e21787ad7c72da359537fe72aa1df51..4213e7279b463e2e8fce5ac24e870f2bc0efb251 100644
--- a/storage/bdb/test/test058.tcl
+++ b/storage/bdb/test/test058.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test058.tcl,v 11.20 2002/02/22 15:26:27 sandstro Exp $
+# $Id: test058.tcl,v 11.22 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test058
 # TEST	Verify that deleting and reading duplicates results in correct ordering.
diff --git a/storage/bdb/test/test059.tcl b/storage/bdb/test/test059.tcl
index 596ea7a3c944a9cea65bd274931da7a3acbfa18c..887ce6d94dba2890fe5630d5ee7b7c24eb1d9926 100644
--- a/storage/bdb/test/test059.tcl
+++ b/storage/bdb/test/test059.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test059.tcl,v 11.18 2002/06/11 15:10:16 sue Exp $
+# $Id: test059.tcl,v 11.20 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test059
 # TEST	Cursor ops work with a partial length of 0.
diff --git a/storage/bdb/test/test060.tcl b/storage/bdb/test/test060.tcl
index 4a18c97f42f3b2b6bb393028abab7daba6bbb29c..770fb5d052fbf54128223ab562d44ab283f3c21e 100644
--- a/storage/bdb/test/test060.tcl
+++ b/storage/bdb/test/test060.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test060.tcl,v 11.10 2002/05/22 15:42:56 sue Exp $
+# $Id: test060.tcl,v 11.12 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test060
 # TEST	Test of the DB_EXCL flag to DB->open().
diff --git a/storage/bdb/test/test061.tcl b/storage/bdb/test/test061.tcl
index 65544e88deb6aaa692fa4548e03bf3439922836e..f4b12c45df53cdc8e47c3e14ebe492943b94e9f0 100644
--- a/storage/bdb/test/test061.tcl
+++ b/storage/bdb/test/test061.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test061.tcl,v 11.18 2002/02/22 15:26:27 sandstro Exp $
+# $Id: test061.tcl,v 11.20 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test061
 # TEST	Test of txn abort and commit for in-memory databases.
diff --git a/storage/bdb/test/test062.tcl b/storage/bdb/test/test062.tcl
index 5cacd98a2c0493e3ab7baf4c1087b423afb57a9a..f26c66d6a1c6b0917053784183565631e1f398ef 100644
--- a/storage/bdb/test/test062.tcl
+++ b/storage/bdb/test/test062.tcl
@@ -1,16 +1,16 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test062.tcl,v 11.20 2002/06/11 14:09:57 sue Exp $
+# $Id: test062.tcl,v 11.23 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test062
 # TEST	Test of partial puts (using DB_CURRENT) onto duplicate pages.
 # TEST	Insert the first 200 words into the dictionary 200 times each with
 # TEST	self as key and <random letter>:self as data.  Use partial puts to
 # TEST	append self again to data;  verify correctness.
-proc test062 { method {nentries 200} {ndups 200} {tnum 62} args } {
+proc test062 { method {nentries 200} {ndups 200} {tnum "062"} args } {
 	global alphabet
 	global rand_init
 	source ./include.tcl
@@ -21,7 +21,7 @@ proc test062 { method {nentries 200} {ndups 200} {tnum 62} args } {
 	set omethod [convert_method $method]
 
 	if { [is_record_based $method] == 1 || [is_rbtree $method] == 1 } {
-		puts "Test0$tnum skipping for method $omethod"
+		puts "Test$tnum skipping for method $omethod"
 		return
 	}
 	# Create the database and open the dictionary
@@ -31,10 +31,10 @@ proc test062 { method {nentries 200} {ndups 200} {tnum 62} args } {
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum.db
+		set testfile $testdir/test$tnum.db
 		set env NULL
 	} else {
-		set testfile test0$tnum.db
+		set testfile test$tnum.db
 		incr eindex
 		set env [lindex $args $eindex]
 		set txnenv [is_txnenv $env]
@@ -53,7 +53,7 @@ proc test062 { method {nentries 200} {ndups 200} {tnum 62} args } {
 	}
 	cleanup $testdir $env
 
-	puts "Test0$tnum:\
+	puts "Test$tnum:\
 	    $method ($args) $nentries Partial puts and $ndups duplicates."
 	set db [eval {berkdb_open -create -mode 0644 \
 	    $omethod -dup} $args {$testfile} ]
@@ -66,7 +66,7 @@ proc test062 { method {nentries 200} {ndups 200} {tnum 62} args } {
 	set count 0
 
 	# Here is the loop where we put each key/data pair
-	puts "\tTest0$tnum.a: Put loop (initialize database)"
+	puts "\tTest$tnum.a: Put loop (initialize database)"
 	while { [gets $did str] != -1 && $count < $nentries } {
 		for { set i 1 } { $i <= $ndups } { incr i } {
 			set pref \
@@ -90,7 +90,7 @@ proc test062 { method {nentries 200} {ndups 200} {tnum 62} args } {
 	}
 	close $did
 
-	puts "\tTest0$tnum.b: Partial puts."
+	puts "\tTest$tnum.b: Partial puts."
 	if { $txnenv == 1 } {
 		set t [$env txn]
 		error_check_good txn [is_valid_txn $t $env] TRUE
@@ -131,7 +131,7 @@ proc test062 { method {nentries 200} {ndups 200} {tnum 62} args } {
 		}
 	}
 
-	puts "\tTest0$tnum.c: Double-checking get loop."
+	puts "\tTest$tnum.c: Double-checking get loop."
 	# Double-check that each datum in the regular db has
 	# been appropriately modified.
 
diff --git a/storage/bdb/test/test063.tcl b/storage/bdb/test/test063.tcl
index 2e8726c8f96215f7212007f90f77a392ff1ba5f5..8918fa4fa009d396e5a0a46435c328a38f805e74 100644
--- a/storage/bdb/test/test063.tcl
+++ b/storage/bdb/test/test063.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test063.tcl,v 11.17 2002/05/24 15:24:55 sue Exp $
+# $Id: test063.tcl,v 11.20 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test063
 # TEST	Test of the DB_RDONLY flag to DB->open
@@ -15,7 +15,7 @@ proc test063 { method args } {
 
 	set args [convert_args $method $args]
 	set omethod [convert_method $method]
-	set tnum 63
+	set tnum "063"
 
 	set txnenv 0
 	set eindex [lsearch -exact $args "-env"]
@@ -23,10 +23,10 @@ proc test063 { method args } {
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum.db
+		set testfile $testdir/test$tnum.db
 		set env NULL
 	} else {
-		set testfile test0$tnum.db
+		set testfile test$tnum.db
 		incr eindex
 		set env [lindex $args $eindex]
 		set txnenv [is_txnenv $env]
@@ -51,10 +51,10 @@ proc test063 { method args } {
 	    append gflags " -recno"
 	}
 
-	puts "Test0$tnum: $method ($args) DB_RDONLY test."
+	puts "Test$tnum: $method ($args) DB_RDONLY test."
 
 	# Create a test database.
-	puts "\tTest0$tnum.a: Creating test database."
+	puts "\tTest$tnum.a: Creating test database."
 	set db [eval {berkdb_open_noerr -create -mode 0644} \
 	    $omethod $args $testfile]
 	error_check_good db_create [is_valid_db $db] TRUE
@@ -84,7 +84,7 @@ proc test063 { method args } {
 		error_check_good writable [file writable $testfile] 1
 	}
 
-	puts "\tTest0$tnum.b: Re-opening DB_RDONLY and attempting to put."
+	puts "\tTest$tnum.b: Re-opening DB_RDONLY and attempting to put."
 
 	# Now open it read-only and make sure we can get but not put.
 	set db [eval {berkdb_open_noerr -rdonly} $args {$testfile}]
@@ -109,7 +109,7 @@ proc test063 { method args } {
 
 	set errorCode "NONE"
 
-	puts "\tTest0$tnum.c: Attempting cursor put."
+	puts "\tTest$tnum.c: Attempting cursor put."
 
 	if { $txnenv == 1 } {
 		set t [$env txn]
@@ -127,7 +127,7 @@ proc test063 { method args } {
 	set dbt [eval {$db get} $gflags {$key2}]
 	error_check_good db_get_key2 $dbt ""
 
-	puts "\tTest0$tnum.d: Attempting ordinary delete."
+	puts "\tTest$tnum.d: Attempting ordinary delete."
 
 	set errorCode "NONE"
 	set ret [catch {eval {$db del} $txn {$key}} 1]
@@ -138,7 +138,7 @@ proc test063 { method args } {
 	error_check_good db_get_key $dbt \
 	    [list [list $key [pad_data $method $data]]]
 
-	puts "\tTest0$tnum.e: Attempting cursor delete."
+	puts "\tTest$tnum.e: Attempting cursor delete."
 	# Just set the cursor to the beginning;  we don't care what's there...
 	# yet.
 	set dbt2 [$dbc get -first]
@@ -151,7 +151,7 @@ proc test063 { method args } {
 	set dbt2 [$dbc get -current]
 	error_check_good db_get_key $dbt2 $dbt
 
-	puts "\tTest0$tnum.f: Close, reopen db;  verify unchanged."
+	puts "\tTest$tnum.f: Close, reopen db;  verify unchanged."
 
 	error_check_good dbc_close [$dbc close] 0
 	if { $txnenv == 1 } {
diff --git a/storage/bdb/test/test064.tcl b/storage/bdb/test/test064.tcl
index c306b0d9d4600226106d498ad2111d9f29a6f8de..13a64657463720810892b8eaa58d643a7e069f70 100644
--- a/storage/bdb/test/test064.tcl
+++ b/storage/bdb/test/test064.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test064.tcl,v 11.13 2002/05/22 15:42:57 sue Exp $
+# $Id: test064.tcl,v 11.16 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test064
 # TEST	Test of DB->get_type
@@ -15,7 +15,7 @@ proc test064 { method args } {
 
 	set args [convert_args $method $args]
 	set omethod [convert_method $method]
-	set tnum 64
+	set tnum "064"
 
 	set txnenv 0
 	set eindex [lsearch -exact $args "-env"]
@@ -23,10 +23,10 @@ proc test064 { method args } {
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum.db
+		set testfile $testdir/test$tnum.db
 		set env NULL
 	} else {
-		set testfile test0$tnum.db
+		set testfile test$tnum.db
 		incr eindex
 		set env [lindex $args $eindex]
 		set txnenv [is_txnenv $env]
@@ -37,17 +37,17 @@ proc test064 { method args } {
 	}
 	cleanup $testdir $env
 
-	puts "Test0$tnum: $method ($args) DB->get_type test."
+	puts "Test$tnum: $method ($args) DB->get_type test."
 
 	# Create a test database.
-	puts "\tTest0$tnum.a: Creating test database of type $method."
+	puts "\tTest$tnum.a: Creating test database of type $method."
 	set db [eval {berkdb_open -create -mode 0644} \
 	    $omethod $args $testfile]
 	error_check_good db_create [is_valid_db $db] TRUE
 
 	error_check_good db_close [$db close] 0
 
-	puts "\tTest0$tnum.b: get_type after method specifier."
+	puts "\tTest$tnum.b: get_type after method specifier."
 
 	set db [eval {berkdb_open} $omethod $args {$testfile}]
 	error_check_good db_open [is_valid_db $db] TRUE
@@ -57,7 +57,7 @@ proc test064 { method args } {
 
 	error_check_good db_close [$db close] 0
 
-	puts "\tTest0$tnum.c: get_type after DB_UNKNOWN."
+	puts "\tTest$tnum.c: get_type after DB_UNKNOWN."
 
 	set db [eval {berkdb_open} $args $testfile]
 	error_check_good db_open [is_valid_db $db] TRUE
diff --git a/storage/bdb/test/test065.tcl b/storage/bdb/test/test065.tcl
index ea29b4d2db7301975cefad5eb73402e3a6d2c3c5..cb29b106d24ebfce3605ab2fc8d8c6974b6f03cd 100644
--- a/storage/bdb/test/test065.tcl
+++ b/storage/bdb/test/test065.tcl
@@ -1,12 +1,13 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test065.tcl,v 11.16 2002/08/22 18:18:50 sandstro Exp $
+# $Id: test065.tcl,v 11.22 2004/09/22 18:01:06 bostic Exp $
 #
 # TEST	test065
-# TEST	Test of DB->stat(DB_FASTSTAT)
+# TEST	Test of DB->stat, both -DB_FAST_STAT and row
+# TEST	counts with DB->stat -txn.
 proc test065 { method args } {
 	source ./include.tcl
 	global errorCode
@@ -15,7 +16,7 @@ proc test065 { method args } {
 	set nentries 10000
 	set args [convert_args $method $args]
 	set omethod [convert_method $method]
-	set tnum 65
+	set tnum "065"
 
 	set txnenv 0
 	set eindex [lsearch -exact $args "-env"]
@@ -23,17 +24,17 @@ proc test065 { method args } {
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum.db
+		set testfile $testdir/test$tnum.db
 		set env NULL
 	} else {
-		set testfile test0$tnum.db
+		set testfile test$tnum.db
 		incr eindex
 		set env [lindex $args $eindex]
 		set txnenv [is_txnenv $env]
 		if { $txnenv == 1 } {
 			append args " -auto_commit "
 			#
-			# If we are using txns and running with the 
+			# If we are using txns and running with the
 			# default, set the default down a bit.
 			#
 			if { $nentries == 10000 } {
@@ -44,9 +45,9 @@ proc test065 { method args } {
 	}
 	cleanup $testdir $env
 
-	puts "Test0$tnum: $method ($args) DB->stat(DB_FAST_STAT) test."
+	puts "Test$tnum: $method ($args) DB->stat(DB_FAST_STAT) test."
 
-	puts "\tTest0$tnum.a: Create database and check it while empty."
+	puts "\tTest$tnum.a: Create database and check it while empty."
 
 	set db [eval {berkdb_open_noerr -create -mode 0644} \
 	    $omethod $args $testfile]
@@ -61,7 +62,7 @@ proc test065 { method args } {
 		error_check_good recordcount_ok [is_substr $res \
 		    "{{Number of keys} 0}"] 1
 	} else {
-		puts "\tTest0$tnum: Test complete for method $method."
+		puts "\tTest$tnum: Test complete for method $method."
 		return
 	}
 
@@ -70,7 +71,7 @@ proc test065 { method args } {
 	# catch EINVALs, and no longer care about __db_errs.
 	set db [eval {berkdb_open -create -mode 0644} $omethod $args $testfile]
 
-	puts "\tTest0$tnum.b: put $nentries keys."
+	puts "\tTest$tnum.b: put $nentries keys."
 
 	if { [is_record_based $method] } {
 		set gflags " -recno "
@@ -91,6 +92,9 @@ proc test065 { method args } {
 		}
 		set ret [eval {$db put} $txn {$keypfx$ndx $data}]
 		error_check_good db_put $ret 0
+		set statret [eval {$db stat} $txn]
+		set rowcount [getstats $statret "Number of records"]
+		error_check_good rowcount $rowcount $ndx
 		if { $txnenv == 1 } {
 			error_check_good txn [$t commit] 0
 		}
@@ -100,7 +104,7 @@ proc test065 { method args } {
 	error_check_good recordcount_after_puts \
 	    [is_substr $ret "{{Number of keys} $nentries}"] 1
 
-	puts "\tTest0$tnum.c: delete 90% of keys."
+	puts "\tTest$tnum.c: delete 90% of keys."
 	set end [expr {$nentries / 10 * 9}]
 	for { set ndx 1 } { $ndx <= $end } { incr ndx } {
 		if { $txnenv == 1 } {
@@ -113,8 +117,13 @@ proc test065 { method args } {
 			# have deleted 5000 and we'll croak!  So delete key
 			# 1, repeatedly.
 			set ret [eval {$db del} $txn {[concat $keypfx 1]}]
+			set statret [eval {$db stat} $txn]
+			set rowcount [getstats $statret "Number of records"]
+			error_check_good rowcount $rowcount [expr $nentries - $ndx]
 		} else {
 			set ret [eval {$db del} $txn {$keypfx$ndx}]
+			set rowcount [getstats $statret "Number of records"]
+			error_check_good rowcount $rowcount $nentries
 		}
 		error_check_good db_del $ret 0
 		if { $txnenv == 1 } {
@@ -134,7 +143,7 @@ proc test065 { method args } {
 		    [is_substr $ret "{{Number of keys} $nentries}"] 1
 	}
 
-	puts "\tTest0$tnum.d: put new keys at the beginning."
+	puts "\tTest$tnum.d: put new keys at the beginning."
 	set end [expr {$nentries / 10 * 8}]
 	for { set ndx 1 } { $ndx <= $end } {incr ndx } {
 		if { $txnenv == 1 } {
@@ -151,7 +160,7 @@ proc test065 { method args } {
 
 	set ret [$db stat -faststat]
 	if { [is_rrecno $method] == 1 } {
-		# With renumbering we're back up to 80% of $nentries 
+		# With renumbering we're back up to 80% of $nentries
 		error_check_good recordcount_after_dels [is_substr $ret \
 		    "{{Number of keys} [expr {$nentries / 10 * 8}]}"] 1
 	} elseif { [is_rbtree $method] == 1 } {
@@ -164,7 +173,7 @@ proc test065 { method args } {
 		    "{{Number of keys} $nentries}"] 1
 	}
 
-	puts "\tTest0$tnum.e: put new keys at the end."
+	puts "\tTest$tnum.e: put new keys at the end."
 	set start [expr {1 + $nentries / 10 * 9}]
 	set end [expr {($nentries / 10 * 9) + ($nentries / 10 * 8)}]
 	for { set ndx $start } { $ndx <= $end } { incr ndx } {
@@ -189,7 +198,7 @@ proc test065 { method args } {
 		    "{{Number of keys} [expr {$start - 1 + $nentries / 10 * 8}]}"] 1
 	} else {
 		# In an rbtree, 1000 of those keys were overwrites, so there
-		# are (.7 x nentries) new keys and (.9 x nentries) old keys 
+		# are (.7 x nentries) new keys and (.9 x nentries) old keys
 		# for a total of (1.6 x nentries).
 		error_check_good recordcount_after_puts2 [is_substr $ret \
 		    "{{Number of keys} [expr {$start -1 + $nentries / 10 * 7}]}"] 1
diff --git a/storage/bdb/test/test066.tcl b/storage/bdb/test/test066.tcl
index 13d0894dcae8bdce8fea9771a334534f023ca1ce..6f31209071aa4e06f0674c185381662c3cdc5362 100644
--- a/storage/bdb/test/test066.tcl
+++ b/storage/bdb/test/test066.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test066.tcl,v 11.12 2002/05/24 15:24:56 sue Exp $
+# $Id: test066.tcl,v 11.15 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test066
 # TEST	Test of cursor overwrites of DB_CURRENT w/ duplicates.
@@ -14,14 +14,14 @@ proc test066 { method args } {
 	set omethod [convert_method $method]
 	set args [convert_args $method $args]
 
-	set tnum 66
+	set tnum "066"
 
 	if { [is_record_based $method] || [is_rbtree $method] } {
-	    puts "Test0$tnum: Skipping for method $method."
+	    puts "Test$tnum: Skipping for method $method."
 	    return
 	}
 
-	puts "Test0$tnum: Test of cursor put to DB_CURRENT with duplicates."
+	puts "Test$tnum: Test of cursor put to DB_CURRENT with duplicates."
 
 	source ./include.tcl
 
@@ -95,5 +95,5 @@ proc test066 { method args } {
 	}
 	error_check_good db_close [$db close] 0
 
-	puts "\tTest0$tnum: Test completed successfully."
+	puts "\tTest$tnum: Test completed successfully."
 }
diff --git a/storage/bdb/test/test067.tcl b/storage/bdb/test/test067.tcl
index 5f5a88c4be11bfa53a2c6bc32ea75b972e7fa3b9..710c6b9c2018f4d2c739ba7710a9b3b7fe2b355d 100644
--- a/storage/bdb/test/test067.tcl
+++ b/storage/bdb/test/test067.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test067.tcl,v 11.19 2002/06/11 15:19:16 sue Exp $
+# $Id: test067.tcl,v 11.25 2004/09/22 18:01:06 bostic Exp $
 #
 # TEST	test067
 # TEST	Test of DB_CURRENT partial puts onto almost empty duplicate
@@ -27,18 +27,15 @@
 # TEST	The partial change does not change how data items sort, but the
 # TEST	record to be put isn't built yet, and that record supplied is the
 # TEST	one that's checked for ordering compatibility.
-proc test067 { method {ndups 1000} {tnum 67} args } {
+proc test067 { method {ndups 1000} {tnum "067"} args } {
 	source ./include.tcl
 	global alphabet
 	global errorCode
+	global is_je_test
 
 	set args [convert_args $method $args]
 	set omethod [convert_method $method]
 
-	if { [is_record_based $method] == 1 || [is_rbtree $method] == 1 } {
-	    puts "\tTest0$tnum: skipping for method $method."
-	    return
-	}
 	set txn ""
 	set txnenv 0
 	set eindex [lsearch -exact $args "-env"]
@@ -46,10 +43,10 @@ proc test067 { method {ndups 1000} {tnum 67} args } {
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum.db
+		set testfile $testdir/test$tnum.db
 		set env NULL
 	} else {
-		set testfile test0$tnum.db
+		set testfile test$tnum.db
 		incr eindex
 		set env [lindex $args $eindex]
 		set txnenv [is_txnenv $env]
@@ -62,10 +59,20 @@ proc test067 { method {ndups 1000} {tnum 67} args } {
 		set testdir [get_home $env]
 	}
 
-	puts "Test0$tnum:\
+	cleanup $testdir $env
+	if { [is_record_based $method] == 1 || [is_rbtree $method] == 1 } {
+	    puts "\tTest$tnum: skipping for method $method."
+	    return
+	}
+
+	puts "Test$tnum:\
 	    $method ($args) Partial puts on near-empty duplicate pages."
 
 	foreach dupopt { "-dup" "-dup -dupsort" } {
+		if { $is_je_test && $dupopt == "-dup" } {
+			continue
+		}
+
 		#
 		# Testdir might get reset from the env's home dir back
 		# to the default if this calls something that sources
@@ -80,7 +87,7 @@ proc test067 { method {ndups 1000} {tnum 67} args } {
 		    $omethod} $args $dupopt {$testfile}]
 		error_check_good db_open [is_valid_db $db] TRUE
 
-		puts "\tTest0$tnum.a ($dupopt): Put $ndups duplicates."
+		puts "\tTest$tnum.a ($dupopt): Put $ndups duplicates."
 
 		set key "key_test$tnum"
 
@@ -102,7 +109,7 @@ proc test067 { method {ndups 1000} {tnum 67} args } {
 
 		# Sync so we can inspect database if the next section bombs.
 		error_check_good db_sync [$db sync] 0
-		puts "\tTest0$tnum.b ($dupopt):\
+		puts "\tTest$tnum.b ($dupopt):\
 		    Deleting dups (last first), overwriting each."
 
 		if { $txnenv == 1 } {
diff --git a/storage/bdb/test/test068.tcl b/storage/bdb/test/test068.tcl
index 31f4272ba55d1cfae9b485a68fa2618c7d6e04ba..a4fb56da09159a22267f56ca471867d65ef7ba8c 100644
--- a/storage/bdb/test/test068.tcl
+++ b/storage/bdb/test/test068.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test068.tcl,v 11.17 2002/06/11 15:34:47 sue Exp $
+# $Id: test068.tcl,v 11.21 2004/05/13 18:51:43 mjc Exp $
 #
 # TEST	test068
 # TEST	Test of DB_BEFORE and DB_AFTER with partial puts.
@@ -13,8 +13,9 @@ proc test068 { method args } {
 	source ./include.tcl
 	global alphabet
 	global errorCode
+	global is_je_test
 
-	set tnum 68
+	set tnum "068"
 
 	set args [convert_args $method $args]
 	set omethod [convert_method $method]
@@ -26,10 +27,10 @@ proc test068 { method args } {
 	# Otherwise it is the test directory and the name.
 	set nkeys 1000
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum.db
+		set testfile $testdir/test$tnum.db
 		set env NULL
 	} else {
-		set testfile test0$tnum.db
+		set testfile test$tnum.db
 		incr eindex
 		set env [lindex $args $eindex]
 		set txnenv [is_txnenv $env]
@@ -40,15 +41,15 @@ proc test068 { method args } {
 		set testdir [get_home $env]
 	}
 
-	puts "Test0$tnum:\
+	puts "Test$tnum:\
 	    $method ($args) Test of DB_BEFORE/DB_AFTER and partial puts."
 	if { [is_record_based $method] == 1 } {
-	    puts "\tTest0$tnum: skipping for method $method."
+	    puts "\tTest$tnum: skipping for method $method."
 	    return
 	}
 
 	# Create a list of $nkeys words to insert into db.
-	puts "\tTest0$tnum.a: Initialize word list."
+	puts "\tTest$tnum.a: Initialize word list."
 	set txn ""
 	set wordlist {}
 	set count 0
@@ -71,6 +72,10 @@ proc test068 { method args } {
 	}
 
 	foreach dupopt $dupoptlist {
+		if { $is_je_test && $dupopt == "-dup" } {
+			continue
+		}
+
 		#
 		# Testdir might be reset in the loop by some proc sourcing
 		# include.tcl.  Reset it to the env's home here, before
@@ -83,7 +88,7 @@ proc test068 { method args } {
 		    $omethod} $args $dupopt {$testfile}]
 		error_check_good db_open [is_valid_db $db] TRUE
 
-		puts "\tTest0$tnum.b ($dupopt): DB initialization: put loop."
+		puts "\tTest$tnum.b ($dupopt): DB initialization: put loop."
 		foreach word $wordlist {
 			if { $txnenv == 1 } {
 				set t [$env txn]
@@ -97,7 +102,7 @@ proc test068 { method args } {
 			}
 		}
 
-		puts "\tTest0$tnum.c ($dupopt): get loop."
+		puts "\tTest$tnum.c ($dupopt): get loop."
 		foreach word $wordlist {
 			# Make sure that the Nth word has been correctly
 			# inserted, and also that the Nth word is the
@@ -115,7 +120,7 @@ proc test068 { method args } {
 		set dbc [eval {$db cursor} $txn]
 		error_check_good cursor_open [is_valid_cursor $dbc $db] TRUE
 
-		puts "\tTest0$tnum.d ($dupopt): DBC->put w/ DB_AFTER."
+		puts "\tTest$tnum.d ($dupopt): DBC->put w/ DB_AFTER."
 
 		# Set cursor to the first key;  make sure it succeeds.
 		# With an unsorted wordlist, we can't be sure that the
@@ -135,15 +140,15 @@ proc test068 { method args } {
 			error_check_good dbc_put_after_fail $ret 1
 			error_check_good dbc_put_after_einval \
 				[is_substr $errorCode EINVAL] 1
-			puts "\tTest0$tnum ($dupopt): DB_AFTER returns EINVAL."
+			puts "\tTest$tnum ($dupopt): DB_AFTER returns EINVAL."
 			set errorCode "NONE"
 			set ret [catch {eval $dbc put -before \
 				{-partial [list 6 0]} "before"} res]
 			error_check_good dbc_put_before_fail $ret 1
 			error_check_good dbc_put_before_einval \
 				[is_substr $errorCode EINVAL] 1
-			puts "\tTest0$tnum ($dupopt): DB_BEFORE returns EINVAL."
-			puts "\tTest0$tnum ($dupopt): Correct error returns,\
+			puts "\tTest$tnum ($dupopt): DB_BEFORE returns EINVAL."
+			puts "\tTest$tnum ($dupopt): Correct error returns,\
 				skipping further test."
 			# continue with broad foreach
 			error_check_good dbc_close [$dbc close] 0
@@ -154,7 +159,7 @@ proc test068 { method args } {
 			continue
 		}
 
-		puts "\tTest0$tnum.e ($dupopt): DBC->put(DB_AFTER) loop."
+		puts "\tTest$tnum.e ($dupopt): DBC->put(DB_AFTER) loop."
 		foreach word $wordlist {
 			# set cursor to $word
 			set dbt [$dbc get -set $word]
@@ -165,7 +170,7 @@ proc test068 { method args } {
 			error_check_good dbc_put_after $ret 0
 		}
 
-		puts "\tTest0$tnum.f ($dupopt): DBC->put(DB_BEFORE) loop."
+		puts "\tTest$tnum.f ($dupopt): DBC->put(DB_BEFORE) loop."
 		foreach word $wordlist {
 			# set cursor to $word
 			set dbt [$dbc get -set $word]
@@ -182,7 +187,7 @@ proc test068 { method args } {
 		}
 
 		eval $db sync
-		puts "\tTest0$tnum.g ($dupopt): Verify correctness."
+		puts "\tTest$tnum.g ($dupopt): Verify correctness."
 
 		if { $txnenv == 1 } {
 			set t [$env txn]
diff --git a/storage/bdb/test/test069.tcl b/storage/bdb/test/test069.tcl
index d986c861358d8ccaa6085351916582202c938946..46104ffa28b84975ce0d13e3b846aee5fcef4059 100644
--- a/storage/bdb/test/test069.tcl
+++ b/storage/bdb/test/test069.tcl
@@ -1,14 +1,14 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test069.tcl,v 11.7 2002/01/11 15:53:52 bostic Exp $
+# $Id: test069.tcl,v 11.10 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test069
 # TEST	Test of DB_CURRENT partial puts without duplicates-- test067 w/
 # TEST	small ndups to ensure that partial puts to DB_CURRENT work
 # TEST	correctly in the absence of duplicate pages.
-proc test069 { method {ndups 50} {tnum 69} args } {
+proc test069 { method {ndups 50} {tnum "069"} args } {
 	eval test067 $method $ndups $tnum $args
 }
diff --git a/storage/bdb/test/test070.tcl b/storage/bdb/test/test070.tcl
index 986fd07958938480f793a19481715a9b6fe40a20..9d124a77b64bc82c0419455aa48e1e44466d48fd 100644
--- a/storage/bdb/test/test070.tcl
+++ b/storage/bdb/test/test070.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test070.tcl,v 11.27 2002/09/05 17:23:07 sandstro Exp $
+# $Id: test070.tcl,v 11.33 2004/02/17 16:29:07 dda Exp $
 #
 # TEST	test070
 # TEST	Test of DB_CONSUME (Four consumers, 1000 items.)
@@ -13,7 +13,7 @@
 # TEST	the consumers will each get 10000.
 # TEST	Then, verify that no record was lost or retrieved twice.
 proc test070 { method {nconsumers 4} {nproducers 2} \
-    {nitems 1000} {mode CONSUME } {start 0} {txn -txn} {tnum 70} args } {
+    {nitems 1000} {mode CONSUME } {start 0} {txn -txn} {tnum "070"} args } {
 	source ./include.tcl
 	global alphabet
 	global encrypt
@@ -24,29 +24,29 @@ proc test070 { method {nconsumers 4} {nproducers 2} \
 	if { $eindex != -1 } {
 		incr eindex
 		set env [lindex $args $eindex]
-		puts "Test0$tnum skipping for env $env"
+		puts "Test$tnum skipping for env $env"
 		return
 	}
 	set omethod [convert_method $method]
 	set args [convert_args $method $args]
 	if { $encrypt != 0 } {
-		puts "Test0$tnum skipping for security"
+		puts "Test$tnum skipping for security"
 		return
 	}
 
-	puts "Test0$tnum: $method ($args) Test of DB_$mode flag to DB->get."
+	puts "Test$tnum: $method ($args) Test of DB_$mode flag to DB->get."
 	puts "\tUsing $txn environment."
 
 	error_check_good enough_consumers [expr $nconsumers > 0] 1
 	error_check_good enough_producers [expr $nproducers > 0] 1
 
 	if { [is_queue $method] != 1 } {
-		puts "\tSkipping Test0$tnum for method $method."
+		puts "\tSkipping Test$tnum for method $method."
 		return
 	}
 
 	env_cleanup $testdir
-	set testfile test0$tnum.db
+	set testfile test$tnum.db
 
 	# Create environment
 	set dbenv [eval {berkdb_env -create $txn -home } $testdir]
@@ -59,7 +59,7 @@ proc test070 { method {nconsumers 4} {nproducers 2} \
 
 	if { $start != 0 } {
 		error_check_good set_seed [$db put $start "consumer data"] 0
-		puts "\tStarting at $start."
+		puts "\tTest$tnum: starting at $start."
 	} else {
 		incr start
 	}
@@ -97,30 +97,24 @@ proc test070 { method {nconsumers 4} {nproducers 2} \
 
 	# Verify: slurp all record numbers into list, sort, and make
 	# sure each appears exactly once.
-	puts "\tTest0$tnum: Verifying results."
+	puts "\tTest$tnum: Verifying results."
 	set reclist {}
 	for { set ndx 0 } { $ndx < $nconsumers } { incr ndx } {
 		set input $consumerlog$ndx
 		set iid [open $input r]
 		while { [gets $iid str] != -1 } {
-			# Convert high ints to negative ints, to
-			# simulate Tcl's behavior on a 32-bit machine
-			# even if we're on a 64-bit one.
-			if { $str > 0x7fffffff } {
-				set str [expr $str - 1 - 0xffffffff]
-			}
 			lappend reclist $str
 		}
 		close $iid
 	}
-	set sortreclist [lsort -integer $reclist]
+	set sortreclist [lsort -command int32_compare $reclist]
 
 	set nitems [expr $start + $nitems]
-	for { set ndx $start } { $ndx < $nitems } { incr ndx } {
-		# Convert high ints to negative ints, to simulate
-		# 32-bit behavior on 64-bit platforms.
-		if { $ndx > 0x7fffffff } {
-			set cmp [expr $ndx - 1 - 0xffffffff]
+	for { set ndx $start } { $ndx < $nitems } { set ndx [expr $ndx + 1] } {
+		# Wrap if $ndx goes beyond 32 bits because our
+		# recno wrapped if it did.
+		if { $ndx > 0xffffffff } {
+			set cmp [expr $ndx - 0xffffffff]
 		} else {
 			set cmp [expr $ndx + 0]
 		}
@@ -138,5 +132,5 @@ proc test070 { method {nconsumers 4} {nproducers 2} \
 	error_check_good db_close [$db close] 0
 	error_check_good dbenv_close [$dbenv close] 0
 
-	puts "\tTest0$tnum completed successfully."
+	puts "\tTest$tnum completed successfully."
 }
diff --git a/storage/bdb/test/test071.tcl b/storage/bdb/test/test071.tcl
index 3f2604022f1a11018a8a31a95683215ea6ac1bc6..7834c82ad4ddbc96db7d34c63b95400ddae67c1e 100644
--- a/storage/bdb/test/test071.tcl
+++ b/storage/bdb/test/test071.tcl
@@ -1,15 +1,15 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test071.tcl,v 11.9 2002/01/11 15:53:53 bostic Exp $
+# $Id: test071.tcl,v 11.14 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test071
 # TEST	Test of DB_CONSUME (One consumer, 10000 items.)
 # TEST	This is DB Test 70, with one consumer, one producers, and 10000 items.
-proc test071 { method {nconsumers 1} {nproducers 1}\
-    {nitems 10000} {mode CONSUME} {start 0 } {txn -txn} {tnum 71} args } {
+proc test071 { method {nconsumers 1} {nproducers 1} {nitems 10000} \
+    {mode CONSUME} {start 0 } {txn -txn} {tnum "071"} args } {
 
 	eval test070 $method \
 	    $nconsumers $nproducers $nitems $mode $start $txn $tnum $args
diff --git a/storage/bdb/test/test072.tcl b/storage/bdb/test/test072.tcl
index 3c08f93975db043ab716cb601cb5145d99858450..3a8ff7aa28e7e26c83dc2023a2bf8183515e6e1c 100644
--- a/storage/bdb/test/test072.tcl
+++ b/storage/bdb/test/test072.tcl
@@ -1,15 +1,16 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test072.tcl,v 11.27 2002/07/01 15:40:48 krinsky Exp $
+# $Id: test072.tcl,v 11.34 2004/05/13 18:51:44 mjc Exp $
 #
 # TEST	test072
 # TEST	Test of cursor stability when duplicates are moved off-page.
-proc test072 { method {pagesize 512} {ndups 20} {tnum 72} args } {
+proc test072 { method {pagesize 512} {ndups 20} {tnum "072"} args } {
 	source ./include.tcl
 	global alphabet
+	global is_je_test
 
 	set omethod [convert_method $method]
 	set args [convert_args $method $args]
@@ -17,13 +18,13 @@ proc test072 { method {pagesize 512} {ndups 20} {tnum 72} args } {
 	set txnenv 0
 	set eindex [lsearch -exact $args "-env"]
 	#
-	# If we are using an env, then testfile should just be the db name.
-	# Otherwise it is the test directory and the name.
+	# If we are using an env, then testfile name should just be
+	# the db name.  Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum.db
+		set basename $testdir/test$tnum
 		set env NULL
 	} else {
-		set testfile test0$tnum.db
+		set basename test$tnum
 		incr eindex
 		set env [lindex $args $eindex]
 		set txnenv [is_txnenv $env]
@@ -44,17 +45,17 @@ proc test072 { method {pagesize 512} {ndups 20} {tnum 72} args } {
 	set predatum "1234567890"
 	set postdatum "0987654321"
 
-	puts -nonewline "Test0$tnum $omethod ($args): "
+	puts -nonewline "Test$tnum $omethod ($args): "
 	if { [is_record_based $method] || [is_rbtree $method] } {
 		puts "Skipping for method $method."
 		return
 	} else {
-		puts "\n    Test of cursor stability when\
+		puts "\nTest$tnum: Test of cursor stability when\
 		    duplicates are moved off-page."
 	}
 	set pgindex [lsearch -exact $args "-pagesize"]
 	if { $pgindex != -1 } {
-		puts "Test0$tnum: skipping for specific pagesizes"
+		puts "Test$tnum: skipping for specific pagesizes"
 		return
 	}
 
@@ -64,14 +65,18 @@ proc test072 { method {pagesize 512} {ndups 20} {tnum 72} args } {
 	set dlist [list "-dup" "-dup -dupsort"]
 	set testid 0
 	foreach dupopt $dlist {
+		if { $is_je_test && $dupopt == "-dup" } {
+			continue
+		}
+
 		incr testid
-		set duptestfile $testfile$testid
+		set duptestfile $basename$testid.db
 		set db [eval {berkdb_open -create -mode 0644} \
 		    $omethod $args $dupopt {$duptestfile}]
 		error_check_good "db open" [is_valid_db $db] TRUE
 
 		puts \
-"\tTest0$tnum.a: ($dupopt) Set up surrounding keys and cursors."
+"\tTest$tnum.a: ($dupopt) Set up surrounding keys and cursors."
 		if { $txnenv == 1 } {
 			set t [$env txn]
 			error_check_good txn [is_valid_txn $t $env] TRUE
@@ -93,7 +98,7 @@ proc test072 { method {pagesize 512} {ndups 20} {tnum 72} args } {
 		error_check_good postset [$postcursor get -set $postkey] \
 			[list [list $postkey $postdatum]]
 
-		puts "\tTest0$tnum.b: Put/create cursor/verify all cursor loop."
+		puts "\tTest$tnum.b: Put/create cursor/verify all cursor loop."
 
 		for { set i 0 } { $i < $ndups } { incr i } {
 			set datum [format "%4d$alphabet" [expr $i + 1000]]
@@ -164,7 +169,7 @@ proc test072 { method {pagesize 512} {ndups 20} {tnum 72} args } {
 			    $post_dbt [list [list $postkey $postdatum]]
 		}
 
-		puts "\tTest0$tnum.c: Reverse Put/create cursor/verify all cursor loop."
+		puts "\tTest$tnum.c: Reverse Put/create cursor/verify all cursor loop."
 		set end [expr $ndups * 2 - 1]
 		for { set i $end } { $i >= $ndups } { set i [expr $i - 1] } {
 			set datum [format "%4d$alphabet" [expr $i + 1000]]
@@ -237,7 +242,7 @@ proc test072 { method {pagesize 512} {ndups 20} {tnum 72} args } {
 		}
 
 		# Close cursors.
-		puts "\tTest0$tnum.d: Closing cursors."
+		puts "\tTest$tnum.d: Closing cursors."
 		for { set i 0 } { $i <= $end } { incr i } {
 			error_check_good "dbc close ($i)" [$dbc($i) close] 0
 		}
diff --git a/storage/bdb/test/test073.tcl b/storage/bdb/test/test073.tcl
index 02a0f3b0d1905be18d9732958a2b1388dfa9b590..bac753ea6c5288253f60d3b0a07339c12c7d1aff 100644
--- a/storage/bdb/test/test073.tcl
+++ b/storage/bdb/test/test073.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test073.tcl,v 11.23 2002/05/22 15:42:59 sue Exp $
+# $Id: test073.tcl,v 11.26 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test073
 # TEST	Test of cursor stability on duplicate pages.
@@ -22,7 +22,7 @@
 # TEST	f. Ditto for the two sequence tests, only doing a
 # TEST	   DBC->c_put(DB_CURRENT) of a larger datum instead of adding a
 # TEST	   new one.
-proc test073 { method {pagesize 512} {ndups 50} {tnum 73} args } {
+proc test073 { method {pagesize 512} {ndups 50} {tnum "073"} args } {
 	source ./include.tcl
 	global alphabet
 
@@ -35,10 +35,10 @@ proc test073 { method {pagesize 512} {ndups 50} {tnum 73} args } {
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum.db
+		set testfile $testdir/test$tnum.db
 		set env NULL
 	} else {
-		set testfile test0$tnum.db
+		set testfile test$tnum.db
 		incr eindex
 		set env [lindex $args $eindex]
 		set txnenv [is_txnenv $env]
@@ -52,7 +52,7 @@ proc test073 { method {pagesize 512} {ndups 50} {tnum 73} args } {
 	set key "the key"
 	set txn ""
 
-	puts -nonewline "Test0$tnum $omethod ($args): "
+	puts -nonewline "Test$tnum $omethod ($args): "
 	if { [is_record_based $method] || [is_rbtree $method] } {
 		puts "Skipping for method $method."
 		return
@@ -74,7 +74,7 @@ proc test073 { method {pagesize 512} {ndups 50} {tnum 73} args } {
 	# Number of outstanding keys.
 	set keys 0
 
-	puts "\tTest0$tnum.a.1: Initializing put loop; $ndups dups, short data."
+	puts "\tTest$tnum.a.1: Initializing put loop; $ndups dups, short data."
 
 	for { set i 0 } { $i < $ndups } { incr i } {
 		set datum [makedatum_t73 $i 0]
@@ -94,7 +94,7 @@ proc test073 { method {pagesize 512} {ndups 50} {tnum 73} args } {
 		incr keys
 	}
 
-	puts "\tTest0$tnum.a.2: Initializing cursor get loop; $keys dups."
+	puts "\tTest$tnum.a.2: Initializing cursor get loop; $keys dups."
 	if { $txnenv == 1 } {
 		set t [$env txn]
 		error_check_good txn [is_valid_txn $t $env] TRUE
@@ -111,7 +111,7 @@ proc test073 { method {pagesize 512} {ndups 50} {tnum 73} args } {
 		    [list [list $key $datum]]
 	}
 
-	puts "\tTest0$tnum.b: Cursor put (DB_KEYLAST); $ndups new dups,\
+	puts "\tTest$tnum.b: Cursor put (DB_KEYLAST); $ndups new dups,\
 	    short data."
 
 	for { set i 0 } { $i < $ndups } { incr i } {
@@ -132,7 +132,7 @@ proc test073 { method {pagesize 512} {ndups 50} {tnum 73} args } {
 		verify_t73 is_long dbc $keys $key
 	}
 
-	puts "\tTest0$tnum.c: Cursor put (DB_KEYFIRST); $ndups new dups,\
+	puts "\tTest$tnum.c: Cursor put (DB_KEYFIRST); $ndups new dups,\
 	    short data."
 
 	for { set i 0 } { $i < $ndups } { incr i } {
@@ -153,7 +153,7 @@ proc test073 { method {pagesize 512} {ndups 50} {tnum 73} args } {
 		verify_t73 is_long dbc $keys $key
 	}
 
-	puts "\tTest0$tnum.d: Cursor put (DB_AFTER) first to last;\
+	puts "\tTest$tnum.d: Cursor put (DB_AFTER) first to last;\
 	    $keys new dups, short data"
 	# We want to add a datum after each key from 0 to the current
 	# value of $keys, which we thus need to save.
@@ -179,7 +179,7 @@ proc test073 { method {pagesize 512} {ndups 50} {tnum 73} args } {
 		verify_t73 is_long dbc $keys $key
 	}
 
-	puts "\tTest0$tnum.e: Cursor put (DB_BEFORE) last to first;\
+	puts "\tTest$tnum.e: Cursor put (DB_BEFORE) last to first;\
 	    $keys new dups, short data"
 
 	for { set i [expr $keys - 1] } { $i >= 0 } { incr i -1 } {
@@ -206,7 +206,7 @@ proc test073 { method {pagesize 512} {ndups 50} {tnum 73} args } {
 	}
 	verify_t73 is_long dbc $keys $key
 
-	puts "\tTest0$tnum.f: Cursor put (DB_CURRENT), first to last,\
+	puts "\tTest$tnum.f: Cursor put (DB_CURRENT), first to last,\
 	    growing $keys data."
 	set keysnow $keys
 	for { set i 0 } { $i < $keysnow } { incr i } {
@@ -233,7 +233,7 @@ proc test073 { method {pagesize 512} {ndups 50} {tnum 73} args } {
 	verify_t73 is_long dbc $keys $key
 
 	# Close cursors.
-	puts "\tTest0$tnum.g: Closing cursors."
+	puts "\tTest$tnum.g: Closing cursors."
 	for { set i 0 } { $i < $keys } { incr i } {
 		error_check_good "dbc close ($i)" [$dbc($i) close] 0
 	}
diff --git a/storage/bdb/test/test074.tcl b/storage/bdb/test/test074.tcl
index 7f620db2d97ed753f2363daf5414f7522844f2c7..8302a2302216e95990d1fc234dc418568a2452ef 100644
--- a/storage/bdb/test/test074.tcl
+++ b/storage/bdb/test/test074.tcl
@@ -1,15 +1,16 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test074.tcl,v 11.17 2002/05/24 15:24:56 sue Exp $
+# $Id: test074.tcl,v 11.22 2004/09/22 18:01:06 bostic Exp $
 #
 # TEST	test074
 # TEST	Test of DB_NEXT_NODUP.
-proc test074 { method {dir -nextnodup} {nitems 100} {tnum 74} args } {
+proc test074 { method {dir -nextnodup} {nitems 100} {tnum "074"} args } {
 	source ./include.tcl
 	global alphabet
+	global is_je_test
 	global rand_init
 
 	set omethod [convert_method $method]
@@ -25,12 +26,12 @@ proc test074 { method {dir -nextnodup} {nitems 100} {tnum 74} args } {
 		set globaldata [repeat $alphabet 4]
 	}
 
-	puts "Test0$tnum $omethod ($args): Test of $dir"
+	puts "Test$tnum $omethod ($args): Test of $dir"
 
 	# First, test non-dup (and not-very-interesting) case with
 	# all db types.
 
-	puts "\tTest0$tnum.a: No duplicates."
+	puts "\tTest$tnum.a: No duplicates."
 
 	set txnenv 0
 	set eindex [lsearch -exact $args "-env"]
@@ -38,10 +39,10 @@ proc test074 { method {dir -nextnodup} {nitems 100} {tnum 74} args } {
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum-nodup.db
+		set testfile $testdir/test$tnum-nodup.db
 		set env NULL
 	} else {
-		set testfile test0$tnum-nodup.db
+		set testfile test$tnum-nodup.db
 		incr eindex
 		set env [lindex $args $eindex]
 		set txnenv [is_txnenv $env]
@@ -57,7 +58,7 @@ proc test074 { method {dir -nextnodup} {nitems 100} {tnum 74} args } {
 	set txn ""
 
 	# Insert nitems items.
-	puts "\t\tTest0$tnum.a.1: Put loop."
+	puts "\t\tTest$tnum.a.1: Put loop."
 	for {set i 1} {$i <= $nitems} {incr i} {
 		#
 		# If record based, set key to $i * 2 to leave
@@ -82,7 +83,7 @@ proc test074 { method {dir -nextnodup} {nitems 100} {tnum 74} args } {
 		}
 	}
 
-	puts "\t\tTest0$tnum.a.2: Get($dir)"
+	puts "\t\tTest$tnum.a.2: Get($dir)"
 
 	# foundarray($i) is set when key number i is found in the database
 	if { $txnenv == 1 } {
@@ -118,10 +119,10 @@ proc test074 { method {dir -nextnodup} {nitems 100} {tnum 74} args } {
 		set foundarray($num) 1
 	}
 
-	puts "\t\tTest0$tnum.a.3: Final key."
+	puts "\t\tTest$tnum.a.3: Final key."
 	error_check_good last_db_get [$dbc get $dir] [list]
 
-	puts "\t\tTest0$tnum.a.4: Verify loop."
+	puts "\t\tTest$tnum.a.4: Verify loop."
 	for { set i 1 } { $i <= $nitems } { incr i } {
 		error_check_good found_key($i) $foundarray($i) 1
 	}
@@ -139,7 +140,7 @@ proc test074 { method {dir -nextnodup} {nitems 100} {tnum 74} args } {
 			error_check_good txn [is_valid_txn $t $env] TRUE
 			set txn "-txn $t"
 		}
-		puts "\t\tTest0$tnum.a.5: Check DB_NEXT_DUP for $method."
+		puts "\t\tTest$tnum.a.5: Check DB_NEXT_DUP for $method."
 		set dbc [eval {$db cursor} $txn]
 		error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
 
@@ -154,28 +155,31 @@ proc test074 { method {dir -nextnodup} {nitems 100} {tnum 74} args } {
 
 	# Quit here if we're a method that won't allow dups.
 	if { [is_record_based $method] == 1 || [is_rbtree $method] == 1 } {
-		puts "\tTest0$tnum: Skipping remainder for method $method."
+		puts "\tTest$tnum: Skipping remainder for method $method."
 		return
 	}
 
 	foreach opt { "-dup" "-dupsort" } {
+		if { $is_je_test && $opt == "-dup" } {
+			continue
+		}
 
 		#
 		# If we are using an env, then testfile should just be the
 		# db name.  Otherwise it is the test directory and the name.
 		if { $eindex == -1 } {
-			set testfile $testdir/test0$tnum$opt.db
+			set testfile $testdir/test$tnum$opt.db
 		} else {
-			set testfile test0$tnum$opt.db
+			set testfile test$tnum$opt.db
 		}
 
 		if { [string compare $opt "-dupsort"] == 0 } {
 			set opt "-dup -dupsort"
 		}
 
-		puts "\tTest0$tnum.b: Duplicates ($opt)."
+		puts "\tTest$tnum.b: Duplicates ($opt)."
 
-		puts "\t\tTest0$tnum.b.1 ($opt): Put loop."
+		puts "\t\tTest$tnum.b.1 ($opt): Put loop."
 		set db [eval {berkdb_open -create -mode 0644}\
 		    $opt $omethod $args {$testfile}]
 		error_check_good db_open [is_valid_db $db] TRUE
@@ -215,7 +219,7 @@ proc test074 { method {dir -nextnodup} {nitems 100} {tnum 74} args } {
 
 		# Get loop--after each get, move forward a random increment
 		# within the duplicate set.
-		puts "\t\tTest0$tnum.b.2 ($opt): Get loop."
+		puts "\t\tTest$tnum.b.2 ($opt): Get loop."
 		set one "001"
 		if { $txnenv == 1 } {
 			set t [$env txn]
@@ -253,11 +257,11 @@ proc test074 { method {dir -nextnodup} {nitems 100} {tnum 74} args } {
 			}
 		}
 
-		puts "\t\tTest0$tnum.b.3 ($opt): Final key."
+		puts "\t\tTest$tnum.b.3 ($opt): Final key."
 		error_check_good last_db_get($opt) [$dbc get $dir] [list]
 
 		# Verify
-		puts "\t\tTest0$tnum.b.4 ($opt): Verify loop."
+		puts "\t\tTest$tnum.b.4 ($opt): Verify loop."
 		for { set i 1 } { $i <= $nitems } { incr i } {
 			error_check_good found_key($i) $foundarray($i) 1
 		}
diff --git a/storage/bdb/test/test076.tcl b/storage/bdb/test/test076.tcl
index 9f7b1ed2972b8b7c2b7eab5898270cd129fbcfb0..49827d35306bf12e69535335a4a63714686cd465 100644
--- a/storage/bdb/test/test076.tcl
+++ b/storage/bdb/test/test076.tcl
@@ -1,13 +1,14 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2000-2002
+# Copyright (c) 2000-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test076.tcl,v 1.18 2002/07/08 20:16:31 sue Exp $
+# $Id: test076.tcl,v 1.22 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test076
 # TEST	Test creation of many small databases in a single environment. [#1528].
-proc test076 { method { ndbs 1000  } { tnum 76 } args } {
+proc test076 { method { ndbs 1000  } { tnum "076" } args } {
+	global is_qnx_test
 	source ./include.tcl
 
 	set args [convert_args $method $args]
@@ -44,7 +45,10 @@ proc test076 { method { ndbs 1000  } { tnum 76 } args } {
 		}
 		set testdir [get_home $env]
 	}
-	puts -nonewline "Test0$tnum $method ($args): "
+	if { $is_qnx_test && $ndbs > 100 } {
+		set ndbs 100
+	}
+	puts -nonewline "Test$tnum $method ($args): "
 	puts -nonewline "Create $ndbs"
 	puts " small databases in one env."
 
@@ -52,7 +56,7 @@ proc test076 { method { ndbs 1000  } { tnum 76 } args } {
 	set txn ""
 
 	for { set i 1 } { $i <= $ndbs } { incr i } {
-		set testfile test0$tnum.$i.db
+		set testfile test$tnum.$i.db
 
 		set db [eval {berkdb_open -create -mode 0644}\
 		    $args $omethod $testfile]
@@ -76,5 +80,5 @@ proc test076 { method { ndbs 1000  } { tnum 76 } args } {
 		error_check_good env_close [$env close] 0
 	}
 
-	puts "\tTest0$tnum passed."
+	puts "\tTest$tnum passed."
 }
diff --git a/storage/bdb/test/test077.tcl b/storage/bdb/test/test077.tcl
index 99cf432af208a734ec6c2931b2551539e3a53d26..3c1fd869b22cd0b6efa96e5ae1efaac9c5743b7d 100644
--- a/storage/bdb/test/test077.tcl
+++ b/storage/bdb/test/test077.tcl
@@ -1,23 +1,23 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2000-2002
+# Copyright (c) 2000-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test077.tcl,v 1.10 2002/05/24 15:24:57 sue Exp $
+# $Id: test077.tcl,v 1.14 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test077
 # TEST	Test of DB_GET_RECNO [#1206].
-proc test077 { method { nkeys 1000 } { pagesize 512 } { tnum 77 } args } {
+proc test077 { method { nkeys 1000 } { tnum "077" } args } {
 	source ./include.tcl
 	global alphabet
 
 	set omethod [convert_method $method]
 	set args [convert_args $method $args]
 
-	puts "Test0$tnum: Test of DB_GET_RECNO."
+	puts "Test$tnum: Test of DB_GET_RECNO."
 
 	if { [is_rbtree $method] != 1 } {
-		puts "\tTest0$tnum: Skipping for method $method."
+		puts "\tTest$tnum: Skipping for method $method."
 		return
 	}
 
@@ -26,10 +26,10 @@ proc test077 { method { nkeys 1000 } { pagesize 512 } { tnum 77 } args } {
 	set txnenv 0
 	set eindex [lsearch -exact $args "-env"]
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum.db
+		set testfile $testdir/test$tnum.db
 		set env NULL
 	} else {
-		set testfile test0$tnum.db
+		set testfile test$tnum.db
 		incr eindex
 		set env [lindex $args $eindex]
 		set txnenv [is_txnenv $env]
@@ -40,11 +40,11 @@ proc test077 { method { nkeys 1000 } { pagesize 512 } { tnum 77 } args } {
 	}
 	cleanup $testdir $env
 
-	set db [eval {berkdb_open -create -mode 0644\
-	    -pagesize $pagesize} $omethod $args {$testfile}]
+	set db [eval {berkdb_open -create -mode 0644} \
+	    $omethod $args {$testfile}]
 	error_check_good db_open [is_valid_db $db] TRUE
 
-	puts "\tTest0$tnum.a: Populating database."
+	puts "\tTest$tnum.a: Populating database."
 	set txn ""
 
 	for { set i 1 } { $i <= $nkeys } { incr i } {
@@ -61,7 +61,7 @@ proc test077 { method { nkeys 1000 } { pagesize 512 } { tnum 77 } args } {
 		}
 	}
 
-	puts "\tTest0$tnum.b: Verifying record numbers."
+	puts "\tTest$tnum.b: Verifying record numbers."
 
 	if { $txnenv == 1 } {
 		set t [$env txn]
diff --git a/storage/bdb/test/test078.tcl b/storage/bdb/test/test078.tcl
index 45a1d46466ee316c702e045230835ae743c96206..549fc13c7e7fd172e44dc635c6d321265e424b8a 100644
--- a/storage/bdb/test/test078.tcl
+++ b/storage/bdb/test/test078.tcl
@@ -1,20 +1,22 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2000-2002
+# Copyright (c) 2000-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test078.tcl,v 1.18 2002/06/20 19:01:02 sue Exp $
+# $Id: test078.tcl,v 1.26 2004/09/22 18:01:06 bostic Exp $
 #
 # TEST	test078
 # TEST	Test of DBC->c_count(). [#303]
-proc test078 { method { nkeys 100 } { pagesize 512 } { tnum 78 } args } {
+proc test078 { method { nkeys 100 } { pagesize 512 } { tnum "078" } args } {
 	source ./include.tcl
-	global alphabet rand_init
+	global alphabet
+	global is_je_test
+	global rand_init
 
 	set args [convert_args $method $args]
 	set omethod [convert_method $method]
 
-	puts "Test0$tnum: Test of key counts."
+	puts "Test$tnum ($method): Test of key counts."
 
 	berkdb srand $rand_init
 
@@ -25,26 +27,27 @@ proc test078 { method { nkeys 100 } { pagesize 512 } { tnum 78 } args } {
 	}
 
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum-a.db
+		set testfile $testdir/test$tnum-a.db
 		set env NULL
 	} else {
-		set testfile test0$tnum-a.db
+		set testfile test$tnum-a.db
 		set env [lindex $args $eindex]
 		set txnenv [is_txnenv $env]
 		if { $txnenv == 1 } {
+			set nkeys 50
 			append args " -auto_commit "
 		}
 		set testdir [get_home $env]
 	}
 	cleanup $testdir $env
 
-	puts "\tTest0$tnum.a: No duplicates, trivial answer."
 	set pgindex [lsearch -exact $args "-pagesize"]
 	if { $pgindex != -1 } {
 		puts "Test078: skipping for specific pagesizes"
 		return
 	}
-
+	puts "\tTest$tnum.a: No duplicates, trivial answer."
+	puts "\t\tTest$tnum.a.1: Populate database, verify dup counts."
 	set db [eval {berkdb_open -create -mode 0644\
 	    -pagesize $pagesize} $omethod $args {$testfile}]
 	error_check_good db_open [is_valid_db $db] TRUE
@@ -64,31 +67,55 @@ proc test078 { method { nkeys 100 } { pagesize 512 } { tnum 78 } args } {
 		}
 		error_check_good count.a [$db count $i] 1
 	}
+
+	if { [is_rrecno $method] == 1 } {
+		error_check_good db_close.a [$db close] 0
+		puts "\tTest$tnum.a2: Skipping remainder of test078 for -rrecno."
+		return
+	}
+
+	puts "\t\tTest$tnum.a.2: Delete items, verify dup counts again."
+	for { set i 1 } { $i <= $nkeys } { incr i } {
+		if { $txnenv == 1 } {
+			set t [$env txn]
+			error_check_good txn [is_valid_txn $t $env] TRUE
+			set txn "-txn $t"
+		}
+		set ret [eval {$db del} $txn $i]
+		error_check_good del.a($i) $ret 0
+		if { $txnenv == 1 } {
+			error_check_good txn [$t commit] 0
+		}
+		error_check_good count.a [$db count $i] 0
+	}
+
+
 	error_check_good db_close.a [$db close] 0
 
 	if { [is_record_based $method] == 1 || [is_rbtree $method] == 1 } {
 		puts \
-	    "\tTest0$tnum.b: Duplicates not supported in $method, skipping."
+	    "\tTest$tnum.b: Duplicates not supported in $method, skipping."
 		return
 	}
 
-	foreach tuple {{b sorted "-dup -dupsort"} {c unsorted "-dup"}} {
-		set letter [lindex $tuple 0]
-		set dupopt [lindex $tuple 2]
+	foreach {let descrip dupopt} \
+	    {b sorted "-dup -dupsort" c unsorted "-dup"} {
 
 		if { $eindex == -1 } {
-			set testfile $testdir/test0$tnum-b.db
+			set testfile $testdir/test$tnum-b.db
 			set env NULL
 		} else {
-			set testfile test0$tnum-b.db
+			set testfile test$tnum-b.db
 			set env [lindex $args $eindex]
+			if { $is_je_test && $dupopt == "-dup" } {
+				continue
+			}
 			set testdir [get_home $env]
 		}
 		cleanup $testdir $env
 
-		puts "\tTest0$tnum.$letter: Duplicates ([lindex $tuple 1])."
-
-		puts "\t\tTest0$tnum.$letter.1: Populating database."
+		puts "\tTest$tnum.$let: Duplicates ($descrip)."
+		puts "\t\tTest$tnum.$let.1: Populating database."
 
 		set db [eval {berkdb_open -create -mode 0644\
 		    -pagesize $pagesize} $dupopt $omethod $args {$testfile}]
@@ -104,27 +131,115 @@ proc test078 { method { nkeys 100 } { pagesize 512 } { tnum 78 } args } {
 				}
 				set ret [eval {$db put} $txn {$i\
 				    [pad_data $method $j$alphabet]}]
-				error_check_good put.$letter,$i $ret 0
+				error_check_good put.$let,$i $ret 0
 				if { $txnenv == 1 } {
 					error_check_good txn [$t commit] 0
 				}
 			}
 		}
 
-		puts -nonewline "\t\tTest0$tnum.$letter.2: "
-		puts "Verifying dup counts on first dup."
-		for { set i 1 } { $i < $nkeys } { incr i } {
-			error_check_good count.$letter,$i \
+		puts -nonewline "\t\tTest$tnum.$let.2: "
+		puts "Verifying duplicate counts."
+		for { set i 1 } { $i <= $nkeys } { incr i } {
+			error_check_good count.$let,$i \
 			    [$db count $i] $i
 		}
 
-		puts -nonewline "\t\tTest0$tnum.$letter.3: "
-		puts "Verifying dup counts on random dup."
-		for { set i 1 } { $i < $nkeys } { incr i } {
-			set key [berkdb random_int 1 $nkeys]
-			error_check_good count.$letter,$i \
-			    [$db count $i] $i
+		puts -nonewline "\t\tTest$tnum.$let.3: "
+		puts "Delete every other dup by cursor, verify counts."
+
+		# Delete every other item by cursor and check counts.
+ 		for { set i 1 } { $i <= $nkeys } { incr i } {
+			if { $txnenv == 1 } {
+				set t [$env txn]
+				error_check_good txn [is_valid_txn $t $env] TRUE
+				set txn "-txn $t"
+			}
+			set c [eval {$db cursor} $txn]
+			error_check_good db_cursor [is_valid_cursor $c $db] TRUE
+			set j 0
+
+			for { set ret [$c get -first]} { [llength $ret] > 0 } \
+			    { set ret [$c get -next]} {
+				set key [lindex [lindex $ret 0] 0]
+				if { $key == $i } {
+					set data [lindex [lindex $ret 0 ] 1]
+					set num [string range $data 0 \
+					    end-[string length $alphabet]]
+					if { [expr $num % 2] == 0 } {
+						error_check_good \
+						    c_del [$c del] 0
+						incr j
+					}
+					if { $txnenv == 0 } {
+						error_check_good count.$let.$i-$j \
+						    [$db count $i] [expr $i - $j]
+					}
+				}
+			}
+			error_check_good curs_close [$c close] 0
+			if { $txnenv == 1 } {
+				error_check_good txn_commit [$t commit] 0
+			}
+			error_check_good count.$let.$i-$j \
+			    [$db count $i] [expr $i - $j]
+		}
+
+		puts -nonewline "\t\tTest$tnum.$let.4: "
+		puts "Delete all items by cursor, verify counts."
+		for { set i 1 } { $i <= $nkeys } { incr i } {
+			if { $txnenv == 1 } {
+				set t [$env txn]
+				error_check_good txn [is_valid_txn $t $env] TRUE
+				set txn "-txn $t"
+			}
+			set c [eval {$db cursor} $txn]
+			error_check_good db_cursor [is_valid_cursor $c $db] TRUE
+			for { set ret [$c get -first]} { [llength $ret] > 0 } \
+			    { set ret [$c get -next]} {
+				set key [lindex [lindex $ret 0] 0]
+				if { $key == $i } {
+					error_check_good c_del [$c del] 0
+				}
+			}
+			error_check_good curs_close [$c close] 0
+			if { $txnenv == 1 } {
+				error_check_good txn_commit [$t commit] 0
+			}
+			error_check_good db_count_zero [$db count $i] 0
+		}
+
+		puts -nonewline "\t\tTest$tnum.$let.5: "
+		puts "Add back one item, verify counts."
+		for { set i 1 } { $i <= $nkeys } { incr i } {
+			if { $txnenv == 1 } {
+				set t [$env txn]
+				error_check_good txn [is_valid_txn $t $env] TRUE
+				set txn "-txn $t"
+			}
+			set ret [eval {$db put} $txn {$i\
+			    [pad_data $method $alphabet]}]
+			error_check_good put.$let,$i $ret 0
+			if { $txnenv == 1 } {
+				error_check_good txn [$t commit] 0
+			}
+			error_check_good add_one [$db count $i] 1
+		}
+
+		puts -nonewline "\t\tTest$tnum.$let.6: "
+		puts "Delete remaining entries, verify counts."
+		for { set i 1 } { $i <= $nkeys } { incr i } {
+			if { $txnenv == 1 } {
+				set t [$env txn]
+				error_check_good txn [is_valid_txn $t $env] TRUE
+				set txn "-txn $t"
+			}
+			error_check_good db_del [eval {$db del} $txn {$i}] 0
+			if { $txnenv == 1 } {
+				error_check_good txn [$t commit] 0
+			}
+			error_check_good count.$let.$i [$db count $i] 0
 		}
-		error_check_good db_close.$letter [$db close] 0
+		error_check_good db_close.$let [$db close] 0
 	}
 }
diff --git a/storage/bdb/test/test079.tcl b/storage/bdb/test/test079.tcl
index 70fd4e05090118bfcaa8b78aaad95679e25bc9c3..d5dbc330409d108bebf04241e4ffd9612f9fddd3 100644
--- a/storage/bdb/test/test079.tcl
+++ b/storage/bdb/test/test079.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2000-2002
+# Copyright (c) 2000-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test079.tcl,v 11.8 2002/01/11 15:53:54 bostic Exp $
+# $Id: test079.tcl,v 11.12 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test079
 # TEST	Test of deletes in large trees.  (test006 w/ sm. pagesize).
@@ -11,10 +11,19 @@
 # TEST	Check that delete operations work in large btrees.  10000 entries
 # TEST	and a pagesize of 512 push this out to a four-level btree, with a
 # TEST	small fraction of the entries going on overflow pages.
-proc test079 { method {nentries 10000} {pagesize 512} {tnum 79} args} {
+proc test079 { method {nentries 10000} {pagesize 512} {tnum "079"} \
+    {ndups 20} args} {
 	if { [ is_queueext $method ] == 1 } {
 		set method  "queue";
 		lappend args "-extent" "20"
 	}
-	eval {test006 $method $nentries 1 $tnum -pagesize $pagesize} $args
+
+        set pgindex [lsearch -exact $args "-pagesize"]
+        if { $pgindex != -1 } {
+                puts "Test$tnum: skipping for specific pagesizes"
+                return
+        }
+
+	eval {test006 $method $nentries 1 $tnum $ndups -pagesize \
+	    $pagesize} $args
 }
diff --git a/storage/bdb/test/test081.tcl b/storage/bdb/test/test081.tcl
index 37c2b44ac33f5542c76269ba9941a786ecd153fb..a9c7f5cfc868290bdc7b8ca72f4308c337a5ee9a 100644
--- a/storage/bdb/test/test081.tcl
+++ b/storage/bdb/test/test081.tcl
@@ -1,14 +1,14 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test081.tcl,v 11.6 2002/01/11 15:53:55 bostic Exp $
+# $Id: test081.tcl,v 11.9 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test081
 # TEST	Test off-page duplicates and overflow pages together with
 # TEST	very large keys (key/data as file contents).
-proc test081 { method {ndups 13} {tnum 81} args} {
+proc test081 { method {ndups 13} {tnum "081"} args} {
 	source ./include.tcl
 
 	eval {test017 $method 1 $ndups $tnum} $args
diff --git a/storage/bdb/test/test082.tcl b/storage/bdb/test/test082.tcl
index e8c1fa45a92921d4267c80b3837407c804f923ee..fb4d71c5c495111f1ded79d4af258cb265798518 100644
--- a/storage/bdb/test/test082.tcl
+++ b/storage/bdb/test/test082.tcl
@@ -1,13 +1,13 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2000-2002
+# Copyright (c) 2000-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test082.tcl,v 11.5 2002/01/11 15:53:55 bostic Exp $
+# $Id: test082.tcl,v 11.8 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test082
 # TEST	Test of DB_PREV_NODUP (uses test074).
-proc test082 { method {dir -prevnodup} {nitems 100} {tnum 82} args} {
+proc test082 { method {dir -prevnodup} {nitems 100} {tnum "082"} args} {
 	source ./include.tcl
 
 	eval {test074 $method $dir $nitems $tnum} $args
diff --git a/storage/bdb/test/test083.tcl b/storage/bdb/test/test083.tcl
index e4168ee1c435a208760b08ea421dc43cf1c9bda8..7e4a8b960a484647e7f3972c400a324c3f47eb77 100644
--- a/storage/bdb/test/test083.tcl
+++ b/storage/bdb/test/test083.tcl
@@ -1,14 +1,18 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2000-2002
+# Copyright (c) 2000-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test083.tcl,v 11.13 2002/06/24 14:06:38 sue Exp $
+# $Id: test083.tcl,v 11.16 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test083
 # TEST	Test of DB->key_range.
 proc test083 { method {pgsz 512} {maxitems 5000} {step 2} args} {
 	source ./include.tcl
+
+	global rand_init
+	error_check_good set_random_seed [berkdb srand $rand_init] 0
+
 	set omethod [convert_method $method]
 	set args [convert_args $method $args]
 
diff --git a/storage/bdb/test/test084.tcl b/storage/bdb/test/test084.tcl
index 89bc13978b02203c86027a4b2131f104ad249131..036c1c41118cd74a8802a7b2985aabfa4da38fa6 100644
--- a/storage/bdb/test/test084.tcl
+++ b/storage/bdb/test/test084.tcl
@@ -1,13 +1,13 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2000-2002
+# Copyright (c) 2000-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test084.tcl,v 11.11 2002/07/13 18:09:14 margo Exp $
+# $Id: test084.tcl,v 11.15 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test084
 # TEST	Basic sanity test (test001) with large (64K) pages.
-proc test084 { method {nentries 10000} {tnum 84} {pagesize 65536} args} {
+proc test084 { method {nentries 10000} {tnum "084"} {pagesize 65536} args} {
 	source ./include.tcl
 
 	set txnenv 0
@@ -16,10 +16,10 @@ proc test084 { method {nentries 10000} {tnum 84} {pagesize 65536} args} {
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum-empty.db
+		set testfile $testdir/test$tnum-empty.db
 		set env NULL
 	} else {
-		set testfile test0$tnum-empty.db
+		set testfile test$tnum-empty.db
 		incr eindex
 		set env [lindex $args $eindex]
 		set txnenv [is_txnenv $env]
@@ -39,7 +39,7 @@ proc test084 { method {nentries 10000} {tnum 84} {pagesize 65536} args} {
 
 	set args "-pagesize $pagesize $args"
 
-	eval {test001 $method $nentries 0 $tnum 0} $args
+	eval {test001 $method $nentries 0 0 $tnum} $args
 
 	set omethod [convert_method $method]
 	set args [convert_args $method $args]
diff --git a/storage/bdb/test/test085.tcl b/storage/bdb/test/test085.tcl
index b0412d6fe68a3219a792652d89c70f4fd411682e..373db33a5adcd39d7f5a66ef2b2c66c43d0b93cf 100644
--- a/storage/bdb/test/test085.tcl
+++ b/storage/bdb/test/test085.tcl
@@ -1,14 +1,14 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2000-2002
+# Copyright (c) 2000-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test085.tcl,v 1.13 2002/08/08 17:23:46 sandstro Exp $
+# $Id: test085.tcl,v 1.18 2004/09/20 17:29:32 carol Exp $
 #
 # TEST	test085
 # TEST	Test of cursor behavior when a cursor is pointing to a deleted
 # TEST	btree key which then has duplicates added. [#2473]
-proc test085 { method {pagesize 512} {onp 3} {offp 10} {tnum 85} args } {
+proc test085 { method {pagesize 512} {onp 3} {offp 10} {tnum "085"} args } {
 	source ./include.tcl
 	global alphabet
 
@@ -23,10 +23,10 @@ proc test085 { method {pagesize 512} {onp 3} {offp 10} {tnum 85} args } {
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum.db
+		set testfile $testdir/test$tnum.db
 		set env NULL
 	} else {
-		set testfile test0$tnum.db
+		set testfile test$tnum.db
 		incr eindex
 		set env [lindex $args $eindex]
 		set txnenv [is_txnenv $env]
@@ -57,7 +57,7 @@ proc test085 { method {pagesize 512} {onp 3} {offp 10} {tnum 85} args } {
 
 	append args " -pagesize $pagesize -dup"
 
-	puts -nonewline "Test0$tnum $omethod ($args): "
+	puts -nonewline "Test$tnum $omethod ($args): "
 
 	# Skip for all non-btrees.  (Rbtrees don't count as btrees, for
 	# now, since they don't support dups.)
@@ -69,7 +69,7 @@ proc test085 { method {pagesize 512} {onp 3} {offp 10} {tnum 85} args } {
 	}
 
 	# Repeat the test with both on-page and off-page numbers of dups.
-	foreach	ndups "$onp $offp" {
+	foreach ndups "$onp $offp" {
 		# Put operations we want to test on a cursor set to the
 		# deleted item, the key to use with them, and what should
 		# come before and after them given a placement of
@@ -78,8 +78,6 @@ proc test085 { method {pagesize 512} {onp 3} {offp 10} {tnum 85} args } {
 		set putops {
 		{{-before} "" $predatum	{[test085_ddatum 0]} beginning}
 		{{-before} "" {[test085_ddatum $final]} $postdatum end}
-		{{-current} "" $predatum {[test085_ddatum 0]} beginning}
-		{{-current} "" {[test085_ddatum $final]} $postdatum end}
 		{{-keyfirst} $key $predatum {[test085_ddatum 0]} beginning}
 		{{-keyfirst} $key $predatum {[test085_ddatum 0]} end}
 		{{-keylast} $key {[test085_ddatum $final]} $postdatum beginning}
@@ -112,7 +110,7 @@ proc test085 { method {pagesize 512} {onp 3} {offp 10} {tnum 85} args } {
 		set txn ""
 		foreach pair $getops {
 			set op [lindex $pair 0]
-			puts "\tTest0$tnum: Get ($op) with $ndups duplicates,\
+			puts "\tTest$tnum: Get ($op) with $ndups duplicates,\
 			    cursor at the [lindex $pair 4]."
 			set db [eval {berkdb_open -create \
 			    -mode 0644} $omethod $encargs $args $testfile]
@@ -153,7 +151,8 @@ proc test085 { method {pagesize 512} {onp 3} {offp 10} {tnum 85} args } {
 			eval set edata [lindex $pair 3]
 
 			set dbt [eval $dbc get $op $gargs]
-			if { [string compare $ekey EMPTYLIST] == 0 } {
+			if { [string compare $ekey EMPTYLIST] == 0 || \
+			     [string compare $op -current] == 0 } {
 				error_check_good dbt($op,$ndups) \
 				    [llength $dbt] 0
 			} else {
@@ -187,7 +186,7 @@ proc test085 { method {pagesize 512} {onp 3} {offp 10} {tnum 85} args } {
 		foreach pair $putops {
 			# Open and set up database.
 			set op [lindex $pair 0]
-			puts "\tTest0$tnum: Put ($op) with $ndups duplicates,\
+			puts "\tTest$tnum: Put ($op) with $ndups duplicates,\
 			    cursor at the [lindex $pair 4]."
 			set db [eval {berkdb_open -create \
 			    -mode 0644} $omethod $args $encargs $testfile]
diff --git a/storage/bdb/test/test086.tcl b/storage/bdb/test/test086.tcl
index e15aa1d8bb9b7858079016654b78e2e73d4bc374..8b2f7db81be3854975be499679e824db9edbfb77 100644
--- a/storage/bdb/test/test086.tcl
+++ b/storage/bdb/test/test086.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test086.tcl,v 11.9 2002/08/06 17:58:00 sandstro Exp $
+# $Id: test086.tcl,v 11.12 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test086
 # TEST	Test of cursor stability across btree splits/rsplits with
@@ -12,19 +12,19 @@ proc test086 { method args } {
 	global errorCode
 	source ./include.tcl
 
-	set tstn 086
+	set tnum 086
 	set args [convert_args $method $args]
 	set encargs ""
 	set args [split_encargs $args encargs]
 
 	if { [is_btree $method] != 1 } {
-		puts "Test$tstn skipping for method $method."
+		puts "Test$tnum skipping for method $method."
 		return
 	}
 
 	set method "-btree"
 
-	puts "\tTest$tstn: Test of cursor stability across aborted\
+	puts "\tTest$tnum: Test of cursor stability across aborted\
 	    btree splits."
 
 	set key "key"
@@ -37,9 +37,9 @@ proc test086 { method args } {
 	# If we are using an env, then this test won't work.
 	if { $eindex == -1 } {
 		# But we will be using our own env...
-		set testfile test0$tstn.db
+		set testfile test$tnum.db
 	} else {
-		puts "\tTest$tstn: Environment provided;  skipping test."
+		puts "\tTest$tnum: Environment provided;  skipping test."
 		return
 	}
 	set t1 $testdir/t1
@@ -48,7 +48,7 @@ proc test086 { method args } {
 	set env [eval {berkdb_env -create -home $testdir -txn} $encargs]
 	error_check_good berkdb_env [is_valid_env $env] TRUE
 
-	puts "\tTest$tstn.a: Create $method database."
+	puts "\tTest$tnum.a: Create $method database."
 	set oflags "-auto_commit -create -env $env -mode 0644 $args $method"
 	set db [eval {berkdb_open} $oflags $testfile]
 	error_check_good dbopen [is_valid_db $db] TRUE
@@ -56,7 +56,7 @@ proc test086 { method args } {
 	set nkeys 5
 	# Fill page w/ small key/data pairs, keep at leaf
 	#
-	puts "\tTest$tstn.b: Fill page with $nkeys small key/data pairs."
+	puts "\tTest$tnum.b: Fill page with $nkeys small key/data pairs."
 	set txn [$env txn]
 	error_check_good txn [is_valid_txn $txn $env] TRUE
 	for { set i 0 } { $i < $nkeys } { incr i } {
@@ -66,7 +66,7 @@ proc test086 { method args } {
 	error_check_good commit [$txn commit] 0
 
 	# get db ordering, set cursors
-	puts "\tTest$tstn.c: Set cursors on each of $nkeys pairs."
+	puts "\tTest$tnum.c: Set cursors on each of $nkeys pairs."
 	set txn [$env txn]
 	error_check_good txn [is_valid_txn $txn $env] TRUE
 	for {set i 0; set ret [$db get -txn $txn key000$i]} {\
@@ -87,7 +87,7 @@ proc test086 { method args } {
 
 	# if mkeys is above 1000, need to adjust below for lexical order
 	set mkeys 1000
-	puts "\tTest$tstn.d: Add $mkeys pairs to force split."
+	puts "\tTest$tnum.d: Add $mkeys pairs to force split."
 	for {set i $nkeys} { $i < $mkeys } { incr i } {
 		if { $i >= 100 } {
 			set ret [$db put -txn $ctxn key0$i $data$i]
@@ -99,10 +99,10 @@ proc test086 { method args } {
 		error_check_good dbput:more $ret 0
 	}
 
-	puts "\tTest$tstn.e: Abort."
+	puts "\tTest$tnum.e: Abort."
 	error_check_good ctxn_abort [$ctxn abort] 0
 
-	puts "\tTest$tstn.f: Check and see that cursors maintained reference."
+	puts "\tTest$tnum.f: Check and see that cursors maintained reference."
 	for {set i 0} { $i < $nkeys } {incr i} {
 		set ret [$dbc_set($i) get -current]
 		error_check_bad dbc$i:get:current [llength $ret] 0
@@ -113,7 +113,7 @@ proc test086 { method args } {
 
 	# Put (and this time keep) the keys that caused the split.
 	# We'll delete them to test reverse splits.
-	puts "\tTest$tstn.g: Put back added keys."
+	puts "\tTest$tnum.g: Put back added keys."
 	for {set i $nkeys} { $i < $mkeys } { incr i } {
 		if { $i >= 100 } {
 			set ret [$db put -txn $txn key0$i $data$i]
@@ -125,7 +125,7 @@ proc test086 { method args } {
 		error_check_good dbput:more $ret 0
 	}
 
-	puts "\tTest$tstn.h: Delete added keys to force reverse split."
+	puts "\tTest$tnum.h: Delete added keys to force reverse split."
 	set ctxn [$env txn -parent $txn]
 	error_check_good ctxn [is_valid_txn $txn $env] TRUE
 	for {set i $nkeys} { $i < $mkeys } { incr i } {
@@ -140,10 +140,10 @@ proc test086 { method args } {
 		}
 	}
 
-	puts "\tTest$tstn.i: Abort."
+	puts "\tTest$tnum.i: Abort."
 	error_check_good ctxn_abort [$ctxn abort] 0
 
-	puts "\tTest$tstn.j: Verify cursor reference."
+	puts "\tTest$tnum.j: Verify cursor reference."
 	for {set i 0} { $i < $nkeys } {incr i} {
 		set ret [$dbc_set($i) get -current]
 		error_check_bad dbc$i:get:current [llength $ret] 0
@@ -152,7 +152,7 @@ proc test086 { method args } {
 		error_check_good dbc$i:get(match) $ret $ret2
 	}
 
-	puts "\tTest$tstn.j: Cleanup."
+	puts "\tTest$tnum.j: Cleanup."
 	# close cursors
 	for {set i 0} { $i < $nkeys } {incr i} {
 		error_check_good dbc_close:$i [$dbc_set($i) close] 0
@@ -162,5 +162,5 @@ proc test086 { method args } {
 	error_check_good dbclose [$db close] 0
 	error_check_good envclose [$env close] 0
 
-	puts "\tTest$tstn complete."
+	puts "\tTest$tnum complete."
 }
diff --git a/storage/bdb/test/test087.tcl b/storage/bdb/test/test087.tcl
index 089664a00029cfe1a0e13fc8dfbe7bdba4b7d82a..7501f4ce3f6f9f1308cd836ec4bf2617197f9efc 100644
--- a/storage/bdb/test/test087.tcl
+++ b/storage/bdb/test/test087.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test087.tcl,v 11.14 2002/07/08 20:16:31 sue Exp $
+# $Id: test087.tcl,v 11.19 2004/01/28 03:36:31 bostic Exp $
 #
 # TEST	test087
 # TEST	Test of cursor stability when converting to and modifying
@@ -25,7 +25,7 @@
 # TEST	f. Ditto for the two sequence tests, only doing a
 # TEST	   DBC->c_put(DB_CURRENT) of a larger datum instead of adding a
 # TEST	   new one.
-proc test087 { method {pagesize 512} {ndups 50} {tnum 87} args } {
+proc test087 { method {pagesize 512} {ndups 50} {tnum "087"} args } {
 	source ./include.tcl
 	global alphabet
 
@@ -34,7 +34,7 @@ proc test087 { method {pagesize 512} {ndups 50} {tnum 87} args } {
 	set args [split_encargs $args encargs]
 	set omethod [convert_method $method]
 
-	puts "Test0$tnum $omethod ($args): "
+	puts "Test$tnum $omethod ($args): "
 	set eindex [lsearch -exact $args "-env"]
 	#
 	# If we are using an env, then return
@@ -48,7 +48,7 @@ proc test087 { method {pagesize 512} {ndups 50} {tnum 87} args } {
 		return
 	}
 	env_cleanup $testdir
-	set testfile test0$tnum.db
+	set testfile test$tnum.db
 	set key "the key"
 	append args " -pagesize $pagesize -dup"
 
@@ -56,7 +56,7 @@ proc test087 { method {pagesize 512} {ndups 50} {tnum 87} args } {
 		puts "Skipping for method $method."
 		return
 	} else {
-		puts "Cursor stability on dup. pages w/ aborts."
+		puts "Test$tnum: Cursor stability on dup. pages w/ aborts."
 	}
 
 	set env [eval {berkdb_env -create -home $testdir -txn} $encargs]
@@ -69,7 +69,7 @@ proc test087 { method {pagesize 512} {ndups 50} {tnum 87} args } {
 	# Number of outstanding keys.
 	set keys $ndups
 
-	puts "\tTest0$tnum.a: put/abort/put/commit loop;\
+	puts "\tTest$tnum.a: put/abort/put/commit loop;\
 	    $ndups dups, short data."
 	set txn [$env txn]
 	error_check_good txn [is_valid_txn $txn $env] TRUE
@@ -102,7 +102,7 @@ proc test087 { method {pagesize 512} {ndups 50} {tnum 87} args } {
 		verify_t73 is_long dbc $i $key
 	}
 
-	puts "\tTest0$tnum.b: Cursor put (DB_KEYLAST); $ndups new dups,\
+	puts "\tTest$tnum.b: Cursor put (DB_KEYLAST); $ndups new dups,\
 	    short data."
 
 	set ctxn [$env txn -parent $txn]
@@ -128,7 +128,7 @@ proc test087 { method {pagesize 512} {ndups 50} {tnum 87} args } {
 	error_check_good ctxn_abort [$ctxn abort] 0
 	verify_t73 is_long dbc $keys $key
 
-	puts "\tTest0$tnum.c: Cursor put (DB_KEYFIRST); $ndups new dups,\
+	puts "\tTest$tnum.c: Cursor put (DB_KEYFIRST); $ndups new dups,\
 	    short data."
 
 	set ctxn [$env txn -parent $txn]
@@ -152,7 +152,7 @@ proc test087 { method {pagesize 512} {ndups 50} {tnum 87} args } {
 	error_check_good ctxn_abort [$ctxn abort] 0
 	verify_t73 is_long dbc $keys $key
 
-	puts "\tTest0$tnum.d: Cursor put (DB_AFTER) first to last;\
+	puts "\tTest$tnum.d: Cursor put (DB_AFTER) first to last;\
 	    $keys new dups, short data"
 	# We want to add a datum after each key from 0 to the current
 	# value of $keys, which we thus need to save.
@@ -179,7 +179,7 @@ proc test087 { method {pagesize 512} {ndups 50} {tnum 87} args } {
 	error_check_good ctxn_abort [$ctxn abort] 0
 	verify_t73 is_long dbc $keys $key
 
-	puts "\tTest0$tnum.e: Cursor put (DB_BEFORE) last to first;\
+	puts "\tTest$tnum.e: Cursor put (DB_BEFORE) last to first;\
 	    $keys new dups, short data"
 	set ctxn [$env txn -parent $txn]
 	error_check_good ctxn($i) [is_valid_txn $ctxn $env] TRUE
@@ -203,7 +203,7 @@ proc test087 { method {pagesize 512} {ndups 50} {tnum 87} args } {
 	error_check_good ctxn_abort [$ctxn abort] 0
 	verify_t73 is_long dbc $keys $key
 
-	puts "\tTest0$tnum.f: Cursor put (DB_CURRENT), first to last,\
+	puts "\tTest$tnum.f: Cursor put (DB_CURRENT), first to last,\
 	    growing $keys data."
 	set ctxn [$env txn -parent $txn]
 	error_check_good ctxn($i) [is_valid_txn $ctxn $env] TRUE
@@ -233,7 +233,7 @@ proc test087 { method {pagesize 512} {ndups 50} {tnum 87} args } {
 
 	# Now delete the first item, abort the deletion, and make sure
 	# we're still sane.
-	puts "\tTest0$tnum.g: Cursor delete first item, then abort delete."
+	puts "\tTest$tnum.g: Cursor delete first item, then abort delete."
 	set ctxn [$env txn -parent $txn]
 	error_check_good ctxn($i) [is_valid_txn $ctxn $env] TRUE
 	set curs [$db cursor -txn $ctxn]
@@ -247,7 +247,7 @@ proc test087 { method {pagesize 512} {ndups 50} {tnum 87} args } {
 	verify_t73 is_long dbc $keys $key
 
 	# Ditto, for the last item.
-	puts "\tTest0$tnum.h: Cursor delete last item, then abort delete."
+	puts "\tTest$tnum.h: Cursor delete last item, then abort delete."
 	set ctxn [$env txn -parent $txn]
 	error_check_good ctxn($i) [is_valid_txn $ctxn $env] TRUE
 	set curs [$db cursor -txn $ctxn]
@@ -261,7 +261,7 @@ proc test087 { method {pagesize 512} {ndups 50} {tnum 87} args } {
 	verify_t73 is_long dbc $keys $key
 
 	# Ditto, for all the items.
-	puts "\tTest0$tnum.i: Cursor delete all items, then abort delete."
+	puts "\tTest$tnum.i: Cursor delete all items, then abort delete."
 	set ctxn [$env txn -parent $txn]
 	error_check_good ctxn($i) [is_valid_txn $ctxn $env] TRUE
 	set curs [$db cursor -txn $ctxn]
@@ -280,11 +280,11 @@ proc test087 { method {pagesize 512} {ndups 50} {tnum 87} args } {
 	verify_t73 is_long dbc $keys $key
 
 	# Close cursors.
-	puts "\tTest0$tnum.j: Closing cursors."
+	puts "\tTest$tnum.j: Closing cursors."
 	for { set i 0 } { $i < $keys } { incr i } {
 		error_check_good "dbc close ($i)" [$dbc($i) close] 0
 	}
-	error_check_good "db close" [$db close] 0
 	error_check_good txn_commit [$txn commit] 0
+	error_check_good "db close" [$db close] 0
 	error_check_good "env close" [$env close] 0
 }
diff --git a/storage/bdb/test/test088.tcl b/storage/bdb/test/test088.tcl
index 7065b4cd642f41797817b312a70f6d0366ec56af..2d3ec7396305823d6703cd3e6e5c7da33dc1ef01 100644
--- a/storage/bdb/test/test088.tcl
+++ b/storage/bdb/test/test088.tcl
@@ -1,16 +1,18 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test088.tcl,v 11.12 2002/08/05 19:23:51 sandstro Exp $
+# $Id: test088.tcl,v 11.15 2004/05/13 18:51:44 mjc Exp $
 #
 # TEST	test088
 # TEST	Test of cursor stability across btree splits with very
 # TEST	deep trees (a variant of test048). [#2514]
 proc test088 { method args } {
-	global errorCode alphabet
 	source ./include.tcl
+	global alphabet
+	global errorCode
+	global is_je_test
 
 	set tstn 088
 	set args [convert_args $method $args]
@@ -119,7 +121,7 @@ proc test088 { method args } {
 
 	puts "\tTest$tstn.e: Make sure splits happened."
 	# XXX cannot execute stat in presence of txns and cursors.
-	if { $txnenv == 0 } {
+	if { $txnenv == 0 && !$is_je_test } {
 		error_check_bad stat:check-split [is_substr [$db stat] \
 						"{{Internal pages} 0}"] 1
 	}
diff --git a/storage/bdb/test/test089.tcl b/storage/bdb/test/test089.tcl
index d378152f20343b95674c87a3ad49e11528fb0ac6..3eb2cd88d069eae580e43af9cf5da99e6c6b99f4 100644
--- a/storage/bdb/test/test089.tcl
+++ b/storage/bdb/test/test089.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test089.tcl,v 11.2 2002/08/08 15:38:12 bostic Exp $
+# $Id: test089.tcl,v 11.9 2004/01/28 03:36:32 bostic Exp $
 #
 # TEST	test089
 # TEST	Concurrent Data Store test (CDB)
@@ -55,7 +55,7 @@ proc test089 { method {nentries 1000} args } {
 	set count 0
 
 	# Here is the loop where we put each key/data pair
-	puts "\tTest089.a: put loop"
+	puts "\tTest089.a: Put loop"
 	set did [open $dict]
 	while { [gets $did str] != -1 && $count < $nentries } {
 		if { [is_record_based $method] == 1 } {
@@ -85,13 +85,53 @@ proc test089 { method {nentries 1000} args } {
 	set env [eval {berkdb_env_noerr -create -cdb} $encargs -home $testdir]
 	error_check_good dbenv [is_valid_widget $env env] TRUE
 
-	# This tests the failure found in #1923
-	puts "\tTest089.b: test delete then get"
+	puts "\tTest089.b: CDB cursor dups"
 
 	set db1 [eval {berkdb_open_noerr -env $env -create \
 	    -mode 0644 $omethod} $oargs {$testfile1}]
 	error_check_good dbopen [is_valid_db $db1] TRUE
 
+	# Create a read-only cursor and make sure we can't write with it.
+	set dbcr [$db1 cursor]
+	error_check_good dbcursor [is_valid_cursor $dbcr $db1] TRUE
+	set ret [$dbcr get -first]
+	catch { [$dbcr put -current data] } ret
+	error_check_good is_read_only \
+	    [is_substr $ret "Write attempted on read-only cursor"] 1
+	error_check_good dbcr_close [$dbcr close] 0
+
+	# Create a write cursor and duplicate it.
+	set dbcw [$db1 cursor -update]
+	error_check_good dbcursor [is_valid_cursor $dbcw $db1] TRUE
+	set dup_dbcw [$dbcw dup]
+	error_check_good dup_write_cursor [is_valid_cursor $dup_dbcw $db1] TRUE
+
+	# Position both cursors at get -first.  They should find the same data.
+	set get_first [$dbcw get -first]
+	set get_first_dup [$dup_dbcw get -first]
+	error_check_good dup_read $get_first $get_first_dup
+
+	# Test that the write cursors can both write and that they
+	# read each other's writes correctly.  First write reversed
+	# datastr with original cursor and read with dup cursor.
+	error_check_good put_current_orig \
+	    [$dbcw put -current [chop_data $method [reverse $datastr]]] 0
+	set reversed [$dup_dbcw get -current]
+	error_check_good check_with_dup [lindex [lindex $reversed 0] 1] \
+	    [chop_data $method [reverse $datastr]]
+
+	# Write forward datastr with dup cursor and read with original.
+	error_check_good put_current_dup \
+	    [$dup_dbcw put -current [chop_data $method $datastr]] 0
+	set forward [$dbcw get -current]
+	error_check_good check_with_orig $forward $get_first
+
+	error_check_good dbcw_close [$dbcw close] 0
+	error_check_good dup_dbcw_close [$dup_dbcw close] 0
+
+	# This tests the failure found in #1923
+	puts "\tTest089.c: Test delete then get"
+
 	set dbc [$db1 cursor -update]
 	error_check_good dbcursor [is_valid_cursor $dbc $db1] TRUE
 
@@ -100,23 +140,6 @@ proc test089 { method {nentries 1000} args } {
 		error_check_good dbcdel [$dbc del] 0
 	}
 	error_check_good dbc_close [$dbc close] 0
-
-	puts "\tTest089.c: CDB cursor dups"
-	set dbc [$db1 cursor -update]
-	error_check_good dbcursor [is_valid_cursor $dbc $db1] TRUE
-	set stat [catch {$dbc dup} ret]
-	error_check_bad wr_cdup_stat $stat 0
-	error_check_good wr_cdup [is_substr $ret \
-	    "Cannot duplicate writeable cursor"] 1
-
-	set dbc_ro [$db1 cursor]
-	error_check_good dbcursor [is_valid_cursor $dbc_ro $db1] TRUE
-	set dup_dbc [$dbc_ro dup]
-	error_check_good rd_cdup [is_valid_cursor $dup_dbc $db1] TRUE
-
-	error_check_good dbc_close [$dbc close] 0
-	error_check_good dbc_close [$dbc_ro close] 0
-	error_check_good dbc_close [$dup_dbc close] 0
 	error_check_good db_close [$db1 close] 0
 	error_check_good env_close [$env close] 0
 
@@ -136,7 +159,6 @@ proc test089 { method {nentries 1000} args } {
 }
 
 proc test089_dup { testdir encargs oargs method nentries } {
-
 	env_cleanup $testdir
 	set env [eval {berkdb_env -create -cdb} $encargs -home $testdir]
 	error_check_good dbenv [is_valid_env $env] TRUE
@@ -157,7 +179,7 @@ proc test089_dup { testdir encargs oargs method nentries } {
 	puts "\tTest089.e: Fill page with $nkeys keys, with $nentries dups"
 	for { set k 0 } { $k < $nkeys } { incr k } {
 		for { set i 0 } { $i < $nentries } { incr i } {
-			set ret [$db put $key $i$data$k]
+			set ret [$db put $key$k $i$data$k]
 			error_check_good dbput $ret 0
 		}
 	}
@@ -166,15 +188,77 @@ proc test089_dup { testdir encargs oargs method nentries } {
 	set stat [$db stat]
 	error_check_bad stat:offpage [is_substr $stat "{{Internal pages} 0}"] 1
 
-	set dbc [$db cursor -update]
-	error_check_good dbcursor [is_valid_cursor $dbc $db] TRUE
+	# This tests the failure reported in #6950.  Skip for -dupsort.
+	puts "\tTest089.f: Clear locks for duped off-page dup cursors."
+	if { [is_substr $oargs dupsort] != 1 } {
+		# Create a read cursor, put it on an off-page dup.
+		set dbcr [$db cursor]
+		error_check_good dbcr [is_valid_cursor $dbcr $db] TRUE
+		set offpage [$dbcr get -get_both test089_key4 900data4]
+		error_check_bad offpage [llength $offpage] 0
 
-	puts "\tTest089.f: test delete then get of off-page dups"
-	for {set kd [$dbc get -first] } { [llength $kd] != 0 } \
-	    {set kd [$dbc get -next] } {
-		error_check_good dbcdel [$dbc del] 0
+		# Create a write cursor, put it on an off-page dup.
+		set dbcw [$db cursor -update]
+		error_check_good dbcw [is_valid_cursor $dbcw $db] TRUE
+		set offpage [$dbcw get -get_both test089_key3 900data3]
+		error_check_bad offpage [llength $offpage] 0
+
+		# Add a new item using the write cursor, then close the cursor.
+		error_check_good add_dup [$dbcw put -after $data] 0
+		error_check_good close_dbcw [$dbcw close] 0
+
+		# Get next dup with read cursor, then close the cursor.
+		set nextdup [$dbcr get -nextdup]
+		error_check_good close_dbcr [$dbcr close] 0
 	}
-	error_check_good dbc_close [$dbc close] 0
+
+	puts "\tTest089.g: CDB duplicate write cursors with off-page dups"
+	# Create a write cursor and duplicate it.
+	set dbcw [$db cursor -update]
+	error_check_good dbcursor [is_valid_cursor $dbcw $db] TRUE
+	set dup_dbcw [$dbcw dup]
+	error_check_good dup_write_cursor [is_valid_cursor $dup_dbcw $db] TRUE
+
+	# Position both cursors at get -first.  They should find the same data.
+	set get_first [$dbcw get -first]
+	set get_first_dup [$dup_dbcw get -first]
+	error_check_good dup_read $get_first $get_first_dup
+
+	# Test with -after and -before.  Skip for -dupsort.
+	if { [is_substr $oargs dupsort] != 1 } {
+		# Original and duplicate cursors both point to first item.
+		# Do a put -before of new string with original cursor,
+		# and a put -after of new string with duplicate cursor.
+		set newdata "newdata"
+		error_check_good put_before [$dbcw put -before $newdata] 0
+		error_check_good put_after [$dup_dbcw put -after $newdata] 0
+
+		# Now walk forward with original cursor ...
+		set first [$dbcw get -first]
+		error_check_good check_first [lindex [lindex $first 0] 1] $newdata
+		set next1 [$dbcw get -next]
+		error_check_good check_next1 $next1 $get_first
+		set next2 [$dbcw get -next]
+		error_check_good check_next2 [lindex [lindex $next2 0] 1] $newdata
+
+		# ... and backward with duplicate cursor.
+		set current [$dup_dbcw get -current]
+		error_check_good check_current [lindex [lindex $current 0] 1] $newdata
+		set prev1 [$dup_dbcw get -prev]
+		error_check_good check_prev1 $prev1 $get_first
+		set prev2 [$dup_dbcw get -prev]
+		error_check_good check_prev2 [lindex [lindex $prev2 0] 1] $newdata
+	}
+
+	puts "\tTest089.h: test delete then get of off-page dups"
+	for {set kd [$dbcw get -first] } { [llength $kd] != 0 } \
+	    {set kd [$dbcw get -next] } {
+		error_check_good dbcdel [$dbcw del] 0
+	}
+
+	error_check_good dbcw_close [$dbcw close] 0
+	error_check_good dup_dbcw_close [$dup_dbcw close] 0
+
 	error_check_good db_close [$db close] 0
 	error_check_good env_close [$env close] 0
 }
diff --git a/storage/bdb/test/test090.tcl b/storage/bdb/test/test090.tcl
index da90688ffc59c8a09e968377c24224a40515f23a..7c46c56c0a73295e428e969eb0784b57abb64ae2 100644
--- a/storage/bdb/test/test090.tcl
+++ b/storage/bdb/test/test090.tcl
@@ -1,16 +1,16 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2000-2002
+# Copyright (c) 2000-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test090.tcl,v 11.10 2002/08/15 20:55:21 sandstro Exp $
+# $Id: test090.tcl,v 11.15 2004/01/28 03:36:32 bostic Exp $
 #
 # TEST	test090
 # TEST	Test for functionality near the end of the queue using test001.
-proc test090 { method {nentries 10000} {txn -txn} {tnum "90"} args} {
+proc test090 { method {nentries 10000} {tnum "090"} args} {
 	if { [is_queueext $method ] == 0 } {
-		puts "Skipping test0$tnum for $method."
+		puts "Skipping test$tnum for $method."
 		return;
 	}
-	eval {test001 $method $nentries 4294967000 $tnum 0} $args
+	eval {test001 $method $nentries 4294967000 0 $tnum} $args
 }
diff --git a/storage/bdb/test/test091.tcl b/storage/bdb/test/test091.tcl
index cfd2a60ebb5d4f24d3d8a0580777ebb376c6e12b..81cabb867b9d9c867109df8683e3aa6f89cf4f50 100644
--- a/storage/bdb/test/test091.tcl
+++ b/storage/bdb/test/test091.tcl
@@ -1,14 +1,14 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2000-2002
+# Copyright (c) 2000-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test091.tcl,v 11.7 2002/01/11 15:53:56 bostic Exp $
+# $Id: test091.tcl,v 11.10 2004/01/28 03:36:32 bostic Exp $
 #
 # TEST	test091
 # TEST	Test of DB_CONSUME_WAIT.
 proc test091 { method {nconsumers 4} \
-    {nproducers 2} {nitems 1000} {start 0 } {tnum "91"} args} {
+    {nproducers 2} {nitems 1000} {start 0 } {tnum "091"} args} {
 	if { [is_queue $method ] == 0 } {
 		puts "Skipping test0$tnum for $method."
 		return;
diff --git a/storage/bdb/test/test092.tcl b/storage/bdb/test/test092.tcl
index 29c1c55a9a9bf258ee0b34100d9a58b7434e8a0a..ef4c822d821ddf55b5012defa1f7c06dc299edeb 100644
--- a/storage/bdb/test/test092.tcl
+++ b/storage/bdb/test/test092.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test092.tcl,v 11.13 2002/02/22 15:26:28 sandstro Exp $
+# $Id: test092.tcl,v 11.18 2004/09/22 18:01:06 bostic Exp $
 #
 # TEST	test092
 # TEST	Test of DB_DIRTY_READ [#3395]
@@ -109,10 +109,16 @@ proc test092 { method {nentries 1000} args } {
 	set dbcdr1 [$dbdr cursor -dirty]
 	error_check_good dbcurs:dbdr1 [is_valid_cursor $dbcdr1 $dbdr] TRUE
 
+	# Test that $db stat can use -dirty flag.
+	puts "\tTest092.c: Smoke test for db_stat -txn -dirty"
+	if { [catch {set statret [$dbcl stat -txn $t -dirty]} res] } {
+		puts "FAIL: db_stat -txn -dirty returned $res"
+	}
+
 	#
 	# Now that we have all of our handles, change all the data in there
 	# to be the key and data the same, but data is capitalized.
-	puts "\tTest092.c: put/get data within a txn"
+	puts "\tTest092.d: put/get data within a txn"
 	set gflags ""
 	if { [is_record_based $method] == 1 } {
 		set checkfunc test092dr_recno.check
@@ -156,13 +162,13 @@ proc test092 { method {nentries 1000} args } {
 	}
 	close $did
 
-	puts "\tTest092.d: Check dirty data using dirty txn and clean db/cursor"
+	puts "\tTest092.e: Check dirty data using dirty txn and clean db/cursor"
 	dump_file_walk $dbccl $t1 $checkfunc "-first" "-next"
 
-	puts "\tTest092.e: Check dirty data using -dirty cget flag"
+	puts "\tTest092.f: Check dirty data using -dirty cget flag"
 	dump_file_walk $dbcdr0 $t2 $checkfunc "-first" "-next" "-dirty"
 
-	puts "\tTest092.f: Check dirty data using -dirty cursor"
+	puts "\tTest092.g: Check dirty data using -dirty cursor"
 	dump_file_walk $dbcdr1 $t3 $checkfunc "-first" "-next"
 
 	#
@@ -176,7 +182,7 @@ proc test092 { method {nentries 1000} args } {
 	#
 	# Now abort the modifying transaction and rerun the data checks.
 	#
-	puts "\tTest092.g: Aborting the write-txn"
+	puts "\tTest092.h: Aborting the write-txn"
 	error_check_good txnabort [$t abort] 0
 
 	set dbccl [$dbcl cursor -txn $tdr]
@@ -193,13 +199,13 @@ proc test092 { method {nentries 1000} args } {
 	} else {
 		set checkfunc test092cl.check
 	}
-	puts "\tTest092.h: Check clean data using -dirty cget flag"
+	puts "\tTest092.i: Check clean data using -dirty cget flag"
 	dump_file_walk $dbccl $t1 $checkfunc "-first" "-next"
 
-	puts "\tTest092.i: Check clean data using -dirty cget flag"
+	puts "\tTest092.j: Check clean data using -dirty cget flag"
 	dump_file_walk $dbcdr0 $t2 $checkfunc "-first" "-next" "-dirty"
 
-	puts "\tTest092.j: Check clean data using -dirty cursor"
+	puts "\tTest092.k: Check clean data using -dirty cursor"
 	dump_file_walk $dbcdr1 $t3 $checkfunc "-first" "-next"
 
 	# Clean up our handles
diff --git a/storage/bdb/test/test093.tcl b/storage/bdb/test/test093.tcl
index e3f8f0103c6a717b8b431c28a7a4c3ff4dfac9df..3ed4b596403db0f98822b2e517e53bf6061a38b6 100644
--- a/storage/bdb/test/test093.tcl
+++ b/storage/bdb/test/test093.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test093.tcl,v 11.20 2002/06/20 19:01:02 sue Exp $
+# $Id: test093.tcl,v 11.23 2004/01/28 03:36:32 bostic Exp $
 #
 # TEST	test093
 # TEST	Test using set_bt_compare.
@@ -12,7 +12,7 @@
 # TEST	Insert each with self as key and data; retrieve each.
 # TEST	After all are entered, retrieve all; compare output to original.
 # TEST	Close file, reopen, do retrieve and re-verify.
-proc test093 { method {nentries 10000} {tnum "93"} args} {
+proc test093 { method {nentries 10000} {tnum "093"} args} {
 	source ./include.tcl
 	global btvals
 	global btvalsck
@@ -22,18 +22,18 @@ proc test093 { method {nentries 10000} {tnum "93"} args} {
 	set omethod [convert_method $method]
 
 	if { [is_btree $method] != 1 } {
-		puts "Test0$tnum: skipping for method $method."
+		puts "Test$tnum: skipping for method $method."
 		return
 	}
 	set txnenv 0
 	set eindex [lsearch -exact $dbargs "-env"]
 	if { $eindex != -1 } {
-		set testfile test0$tnum.db
+		set testfile test$tnum.db
 		incr eindex
 		set env [lindex $dbargs $eindex]
 		set rpcenv [is_rpcenv $env]
 		if { $rpcenv == 1 } {
-			puts "Test0$tnum: skipping for RPC"
+			puts "Test$tnum: skipping for RPC"
 			return
 		}
 		set txnenv [is_txnenv $env]
@@ -46,7 +46,7 @@ proc test093 { method {nentries 10000} {tnum "93"} args} {
 		set testdir [get_home $env]
 		cleanup $testdir $env
 	}
-	puts "Test0$tnum: $method ($args) $nentries using btcompare"
+	puts "Test$tnum: $method ($args) $nentries using btcompare"
 
 
 	test093_run $omethod $dbargs $nentries $tnum test093_cmp1 test093_sort1
@@ -84,10 +84,10 @@ proc test093_run { method dbargs nentries tnum cmpfunc sortfunc } {
 	# Otherwise it is the test directory and the name.
 	set txnenv 0
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum.db
+		set testfile $testdir/test$tnum.db
 		set env NULL
 	} else {
-		set testfile test0$tnum.db
+		set testfile test$tnum.db
 		incr eindex
 		set env [lindex $dbargs $eindex]
 		set txnenv [is_txnenv $env]
@@ -109,7 +109,7 @@ proc test093_run { method dbargs nentries tnum cmpfunc sortfunc } {
 	set btvals {}
 	set btvalsck {}
 	set checkfunc test093_check
-	puts "\tTest0$tnum.a: put/get loop"
+	puts "\tTest$tnum.a: put/get loop"
 	# Here is the loop where we put and get each key/data pair
 	set count 0
 	while { [gets $did str] != -1 && $count < $nentries } {
@@ -138,7 +138,7 @@ proc test093_run { method dbargs nentries tnum cmpfunc sortfunc } {
 	close $did
 	# Now we will get each key from the DB and compare the results
 	# to the original.
-	puts "\tTest0$tnum.b: dump file"
+	puts "\tTest$tnum.b: dump file"
 	if { $txnenv == 1 } {
 		set t [$env txn]
 		error_check_good txn [is_valid_txn $t $env] TRUE
@@ -157,10 +157,10 @@ proc test093_run { method dbargs nentries tnum cmpfunc sortfunc } {
 	file rename -force $t3 $t2
 	filesort $t1 $t3
 
-	error_check_good Test0$tnum:diff($t3,$t2) \
+	error_check_good Test$tnum:diff($t3,$t2) \
 	    [filecmp $t3 $t2] 0
 
-	puts "\tTest0$tnum.c: dump file in order"
+	puts "\tTest$tnum.c: dump file in order"
 	# Now, reopen the file and run the last test again.
 	# We open it here, ourselves, because all uses of the db
 	# need to have the correct comparison func set.  Then
@@ -183,7 +183,7 @@ proc test093_run { method dbargs nentries tnum cmpfunc sortfunc } {
 	#
 	# We need to sort btvals according to the comparison function.
 	# Once that is done, btvalsck and btvals should be the same.
-	puts "\tTest0$tnum.d: check file order"
+	puts "\tTest$tnum.d: check file order"
 
 	$sortfunc
 
@@ -206,10 +206,10 @@ proc test093_runbig { method dbargs nentries tnum cmpfunc sortfunc } {
 	# Otherwise it is the test directory and the name.
 	set txnenv 0
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum.db
+		set testfile $testdir/test$tnum.db
 		set env NULL
 	} else {
-		set testfile test0$tnum.db
+		set testfile test$tnum.db
 		incr eindex
 		set env [lindex $dbargs $eindex]
 		set txnenv [is_txnenv $env]
@@ -232,7 +232,7 @@ proc test093_runbig { method dbargs nentries tnum cmpfunc sortfunc } {
 	set btvals {}
 	set btvalsck {}
 	set checkfunc test093_checkbig
-	puts "\tTest0$tnum.e:\
+	puts "\tTest$tnum.e:\
 	    big key put/get loop key=filecontents data=filename"
 
 	# Here is the loop where we put and get each key/data pair
@@ -285,7 +285,7 @@ proc test093_runbig { method dbargs nentries tnum cmpfunc sortfunc } {
 
 	# Now we will get each key from the DB and compare the results
 	# to the original.
-	puts "\tTest0$tnum.f: big dump file"
+	puts "\tTest$tnum.f: big dump file"
 	if { $txnenv == 1 } {
 		set t [$env txn]
 		error_check_good txn [is_valid_txn $t $env] TRUE
@@ -297,7 +297,7 @@ proc test093_runbig { method dbargs nentries tnum cmpfunc sortfunc } {
 	}
 	error_check_good db_close [$db close] 0
 
-	puts "\tTest0$tnum.g: dump file in order"
+	puts "\tTest$tnum.g: dump file in order"
 	# Now, reopen the file and run the last test again.
 	# We open it here, ourselves, because all uses of the db
 	# need to have the correct comparison func set.  Then
@@ -321,7 +321,7 @@ proc test093_runbig { method dbargs nentries tnum cmpfunc sortfunc } {
 	#
 	# We need to sort btvals according to the comparison function.
 	# Once that is done, btvalsck and btvals should be the same.
-	puts "\tTest0$tnum.h: check file order"
+	puts "\tTest$tnum.h: check file order"
 
 	$sortfunc
 	error_check_good btvals:len [llength $btvals] [llength $btvalsck]
diff --git a/storage/bdb/test/test094.tcl b/storage/bdb/test/test094.tcl
index 781052913f4d76ce65ce6eb02433a4f96a3ac51d..20f2b3af3abda3ab507e18fb8f816b6a00059489 100644
--- a/storage/bdb/test/test094.tcl
+++ b/storage/bdb/test/test094.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test094.tcl,v 11.16 2002/06/20 19:01:02 sue Exp $
+# $Id: test094.tcl,v 11.21 2004/06/29 14:26:17 carol Exp $
 #
 # TEST	test094
 # TEST	Test using set_dup_compare.
@@ -12,7 +12,7 @@
 # TEST	Insert each with self as key and data; retrieve each.
 # TEST	After all are entered, retrieve all; compare output to original.
 # TEST	Close file, reopen, do retrieve and re-verify.
-proc test094 { method {nentries 10000} {ndups 10} {tnum "94"} args} {
+proc test094 { method {nentries 10000} {ndups 10} {tnum "094"} args} {
 	source ./include.tcl
 	global errorInfo
 
@@ -20,7 +20,7 @@ proc test094 { method {nentries 10000} {ndups 10} {tnum "94"} args} {
 	set omethod [convert_method $method]
 
 	if { [is_btree $method] != 1 && [is_hash $method] != 1 } {
-		puts "Test0$tnum: skipping for method $method."
+		puts "Test$tnum: skipping for method $method."
 		return
 	}
 
@@ -31,15 +31,15 @@ proc test094 { method {nentries 10000} {ndups 10} {tnum "94"} args} {
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum-a.db
+		set testfile $testdir/test$tnum-a.db
 		set env NULL
 	} else {
-		set testfile test0$tnum-a.db
+		set testfile test$tnum-a.db
 		incr eindex
 		set env [lindex $dbargs $eindex]
 		set rpcenv [is_rpcenv $env]
 		if { $rpcenv == 1 } {
-			puts "Test0$tnum: skipping for RPC"
+			puts "Test$tnum: skipping for RPC"
 			return
 		}
 		set txnenv [is_txnenv $env]
@@ -52,12 +52,12 @@ proc test094 { method {nentries 10000} {ndups 10} {tnum "94"} args} {
 		}
 		set testdir [get_home $env]
 	}
-	puts "Test0$tnum: $method ($args) $nentries \
+	puts "Test$tnum: $method ($args) $nentries \
 	    with $ndups dups using dupcompare"
 
 	cleanup $testdir $env
 
-	set db [eval {berkdb_open_noerr -dupcompare test094_cmp \
+	set db [eval {berkdb_open -dupcompare test094_cmp \
 	    -dup -dupsort -create -mode 0644} $omethod $dbargs {$testfile}]
 	error_check_good dbopen [is_valid_db $db] TRUE
 
@@ -66,7 +66,7 @@ proc test094 { method {nentries 10000} {ndups 10} {tnum "94"} args} {
 	set pflags ""
 	set gflags ""
 	set txn ""
-	puts "\tTest0$tnum.a: $nentries put/get duplicates loop"
+	puts "\tTest$tnum.a: $nentries put/get duplicates loop"
 	# Here is the loop where we put and get each key/data pair
 	set count 0
 	set dlist {}
@@ -97,7 +97,7 @@ proc test094 { method {nentries 10000} {ndups 10} {tnum "94"} args} {
 	close $did
 	# Now we will get each key from the DB and compare the results
 	# to the original.
-	puts "\tTest0$tnum.b: traverse checking duplicates before close"
+	puts "\tTest$tnum.b: traverse checking duplicates before close"
 	if { $txnenv == 1 } {
 		set t [$env txn]
 		error_check_good txn [is_valid_txn $t $env] TRUE
@@ -113,10 +113,10 @@ proc test094 { method {nentries 10000} {ndups 10} {tnum "94"} args} {
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set testfile $testdir/test0$tnum-b.db
+		set testfile $testdir/test$tnum-b.db
 		set env NULL
 	} else {
-		set testfile test0$tnum-b.db
+		set testfile test$tnum-b.db
 		set env [lindex $dbargs $eindex]
 		set testdir [get_home $env]
 	}
@@ -125,7 +125,7 @@ proc test094 { method {nentries 10000} {ndups 10} {tnum "94"} args} {
 	#
 	# Test dupcompare with data items big enough to force offpage dups.
 	#
-	puts "\tTest0$tnum.c: big key put/get dup loop key=filename data=filecontents"
+	puts "\tTest$tnum.c: big key put/get dup loop key=filename data=filecontents"
 	set db [eval {berkdb_open -dupcompare test094_cmp -dup -dupsort \
 	     -create -mode 0644} $omethod $dbargs $testfile]
 	error_check_good dbopen [is_valid_db $db] TRUE
@@ -164,7 +164,7 @@ proc test094 { method {nentries 10000} {ndups 10} {tnum "94"} args} {
 		incr count
 	}
 
-	puts "\tTest0$tnum.d: traverse checking duplicates before close"
+	puts "\tTest$tnum.d: traverse checking duplicates before close"
 	if { $txnenv == 1 } {
 		set t [$env txn]
 		error_check_good txn [is_valid_txn $t $env] TRUE
@@ -187,65 +187,3 @@ proc test094 { method {nentries 10000} {ndups 10} {tnum "94"} args} {
 proc test094_cmp { a b } {
 	return [string compare $b $a]
 }
-
-# Check if each key appears exactly [llength dlist] times in the file with
-# the duplicate tags matching those that appear in dlist.
-proc test094_dup_big { db txn tmpfile dlist {extra 0}} {
-	source ./include.tcl
-
-	set outf [open $tmpfile w]
-	# Now we will get each key from the DB and dump to outfile
-	set c [eval {$db cursor} $txn]
-	set lastkey ""
-	set done 0
-	while { $done != 1} {
-		foreach did $dlist {
-			set rec [$c get "-next"]
-			if { [string length $rec] == 0 } {
-				set done 1
-				break
-			}
-			set key [lindex [lindex $rec 0] 0]
-			set fulldata [lindex [lindex $rec 0] 1]
-			set id [id_of $fulldata]
-			set d [data_of $fulldata]
-			if { [string compare $key $lastkey] != 0 && \
-			    $id != [lindex $dlist 0] } {
-				set e [lindex $dlist 0]
-				error "FAIL: \tKey \
-				    $key, expected dup id $e, got $id"
-			}
-			error_check_good dupget.data $d $key
-			error_check_good dupget.id $id $did
-			set lastkey $key
-		}
-		#
-		# Some tests add an extra dup (like overflow entries)
-		# Check id if it exists.
-		if { $extra != 0} {
-			set okey $key
-			set rec [$c get "-next"]
-			if { [string length $rec] != 0 } {
-				set key [lindex [lindex $rec 0] 0]
-				#
-				# If this key has no extras, go back for
-				# next iteration.
-				if { [string compare $key $lastkey] != 0 } {
-					set key $okey
-					set rec [$c get "-prev"]
-				} else {
-					set fulldata [lindex [lindex $rec 0] 1]
-					set id [id_of $fulldata]
-					set d [data_of $fulldata]
-					error_check_bad dupget.data1 $d $key
-					error_check_good dupget.id1 $id $extra
-				}
-			}
-		}
-		if { $done != 1 } {
-			puts $outf $key
-		}
-	}
-	close $outf
-	error_check_good curs_close [$c close] 0
-}
diff --git a/storage/bdb/test/test095.tcl b/storage/bdb/test/test095.tcl
index 5543f346b7e538be2867f3a43543bee244a16beb..9c62a6a51ef09dfe7e487e46878e092d28dae9b2 100644
--- a/storage/bdb/test/test095.tcl
+++ b/storage/bdb/test/test095.tcl
@@ -1,14 +1,17 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2000-2002
+# Copyright (c) 2000-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test095.tcl,v 11.16 2002/08/08 15:38:12 bostic Exp $
+# $Id: test095.tcl,v 11.30 2004/09/22 18:01:06 bostic Exp $
 #
 # TEST	test095
-# TEST	Bulk get test. [#2934]
-proc test095 { method {nsets 1000} {noverflows 25} {tnum 95} args } {
+# TEST	Bulk get test for methods supporting dups. [#2934]
+proc test095 { method {tnum "095"} args } {
 	source ./include.tcl
+	global is_je_test
+	global is_qnx_test
+
 	set args [convert_args $method $args]
 	set omethod [convert_method $method]
 
@@ -18,13 +21,13 @@ proc test095 { method {nsets 1000} {noverflows 25} {tnum 95} args } {
 	# If we are using an env, then testfile should just be the db name.
 	# Otherwise it is the test directory and the name.
 	if { $eindex == -1 } {
-		set basename $testdir/test0$tnum
+		set basename $testdir/test$tnum
 		set env NULL
 		# If we've our own env, no reason to swap--this isn't
 		# an mpool test.
 		set carg { -cachesize {0 25000000 0} }
 	} else {
-		set basename test0$tnum
+		set basename test$tnum
 		incr eindex
 		set env [lindex $args $eindex]
 		set txnenv [is_txnenv $env]
@@ -37,37 +40,81 @@ proc test095 { method {nsets 1000} {noverflows 25} {tnum 95} args } {
 	}
 	cleanup $testdir $env
 
-	puts "Test0$tnum: $method ($args) Bulk get test"
+	puts "Test$tnum: $method ($args) Bulk get test"
 
+	# Tcl leaves a lot of memory allocated after this test
+	# is run in the tclsh.  This ends up being a problem on
+	# QNX runs as later tests then run out of memory.
+	if { $is_qnx_test } {
+		puts "Test$tnum skipping for QNX"
+		return
+	}
 	if { [is_record_based $method] == 1 || [is_rbtree $method] == 1 } {
-		puts "Test0$tnum skipping for method $method"
+		puts "Test$tnum skipping for method $method"
 		return
 	}
 
+	# The test's success is dependent on the relationship between
+	# the amount of data loaded and the buffer sizes we pick, so
+	# these parameters don't belong on the command line.
+	set nsets 300
+	set noverflows 25
+
 	# We run the meat of the test twice: once with unsorted dups,
 	# once with sorted dups.
-	for { set dflag "-dup"; set sort "unsorted"; set diter 0 } \
-	    { $diter < 2 } \
-	    { set dflag "-dup -dupsort"; set sort "sorted"; incr diter } {
+	foreach { dflag sort } { -dup unsorted {-dup -dupsort} sorted } {
+		if { $is_je_test && $sort == "unsorted" } {
+			continue
+		}
+
 		set testfile $basename-$sort.db
 		set did [open $dict]
 
 		# Open and populate the database with $nsets sets of dups.
 		# Each set contains as many dups as its number
-		puts "\tTest0$tnum.a:\
+		puts "\tTest$tnum.a:\
 		    Creating database with $nsets sets of $sort dups."
 		set dargs "$dflag $carg $args"
-		set db [eval {berkdb_open -create} $omethod $dargs $testfile]
+		set db [eval {berkdb_open_noerr -create} \
+		    $omethod $dargs $testfile]
 		error_check_good db_open [is_valid_db $db] TRUE
 		t95_populate $db $did $nsets 0
 
+		# Determine the pagesize so we can use it to size the buffer.
+		set stat [$db stat]
+		set pagesize [get_pagesize $stat]
+
 		# Run basic get tests.
-		t95_gettest $db $tnum b [expr 8192] 1
-		t95_gettest $db $tnum c [expr 10 * 8192] 0
+		#
+		# A small buffer will fail if it is smaller than the pagesize.
+		# Skip small buffer tests if the page size is so small that
+		# we can't define a buffer smaller than the page size.
+		# (Buffers must be 1024 or multiples of 1024.)
+		#
+		# A big buffer of 66560 (64K + 1K) should always be large
+		# enough to contain the data, so the test should succeed
+		# on all platforms.  We picked this number because it
+		# is larger than the largest allowed pagesize, so the test
+		# always fills more than a page at some point.
+
+		set maxpage [expr 1024 * 64]
+		set bigbuf [expr $maxpage + 1024]
+		set smallbuf 1024
+
+		if { $pagesize > 1024 } {
+			t95_gettest $db $tnum b $smallbuf 1
+		} else {
+			puts "Skipping small buffer test Test$tnum.b"
+		}
+		t95_gettest $db $tnum c $bigbuf 0
 
 		# Run cursor get tests.
-		t95_cgettest $db $tnum d [expr 100] 1
-		t95_cgettest $db $tnum e [expr 10 * 8192] 0
+		if { $pagesize > 1024 } {
+			t95_cgettest $db $tnum b $smallbuf 1
+		} else {
+			puts "Skipping small buffer test Test$tnum.d"
+		}
+		t95_cgettest $db $tnum e $bigbuf 0
 
 		# Run invalid flag combination tests
 		# Sync and reopen test file so errors won't be sent to stderr
@@ -78,19 +125,23 @@ proc test095 { method {nsets 1000} {noverflows 25} {tnum 95} args } {
 		error_check_good noerrdb_close [$noerrdb close] 0
 
 		# Set up for overflow tests
-		set max [expr 4000 * $noverflows]
-		puts "\tTest0$tnum.h: Growing\
-	    database with $noverflows overflow sets (max item size $max)"
-		t95_populate $db $did $noverflows 4000
-
-		# Run overflow get tests.
-		t95_gettest $db $tnum i [expr 10 * 8192] 1
-		t95_gettest $db $tnum j [expr $max * 2] 1
+		set max [expr 4096 * $noverflows]
+		puts "\tTest$tnum.h: Add $noverflows overflow sets\
+		    to database (max item size $max)"
+		t95_populate $db $did $noverflows 4096
+
+		# Run overflow get tests.  The overflow test fails with
+		# our standard big buffer doubled, but succeeds with a
+		# buffer sized to handle $noverflows pairs of data of
+		# size $max.
+		t95_gettest $db $tnum i $bigbuf 1
+		t95_gettest $db $tnum j [expr $bigbuf * 2] 1
 		t95_gettest $db $tnum k [expr $max * $noverflows * 2] 0
 
 		# Run overflow cursor get tests.
-		t95_cgettest $db $tnum l [expr 10 * 8192] 1
-		t95_cgettest $db $tnum m [expr $max * 2] 0
+		t95_cgettest $db $tnum l $bigbuf 1
+		# Expand buffer to accommodate basekey as well as the padding.
+		t95_cgettest $db $tnum m [expr ($max + 512) * 2] 0
 
 		error_check_good db_close [$db close] 0
 		close $did
@@ -114,116 +165,138 @@ proc t95_cflagtest { db tnum letter bufsize } {
 proc t95_gettest_body { db tnum letter bufsize expectfail usecursor } {
 	global errorCode
 
-	if { $usecursor == 0 } {
-		set action "db get -multi"
-	} else {
-		set action "dbc get -multi -set/-next"
-	}
-	puts "\tTest0$tnum.$letter: $action with bufsize $bufsize"
-
-	set allpassed TRUE
-	set saved_err ""
-
-	# Cursor for $usecursor.
-	if { $usecursor != 0 } {
-		set getcurs [$db cursor]
-		error_check_good getcurs [is_valid_cursor $getcurs $db] TRUE
-	}
-
-	# Traverse DB with cursor;  do get/c_get(DB_MULTIPLE) on each item.
-	set dbc [$db cursor]
-	error_check_good is_valid_dbc [is_valid_cursor $dbc $db] TRUE
-	for { set dbt [$dbc get -first] } { [llength $dbt] != 0 } \
-	    { set dbt [$dbc get -nextnodup] } {
-		set key [lindex [lindex $dbt 0] 0]
-		set datum [lindex [lindex $dbt 0] 1]
-
+	foreach flag { multi multi_key } {
 		if { $usecursor == 0 } {
-			set ret [catch {eval $db get -multi $bufsize $key} res]
-		} else {
-			set res {}
-			for { set ret [catch {eval $getcurs get -multi $bufsize\
-			    -set $key} tres] } \
-			    { $ret == 0 && [llength $tres] != 0 } \
-			    { set ret [catch {eval $getcurs get -multi $bufsize\
-			    -nextdup} tres]} {
-				eval lappend res $tres
+			if { $flag == "multi_key" } {
+				# db->get does not allow multi_key
+				continue
+			} else {
+				set action "db get -$flag"
 			}
+		} else {
+			set action "dbc get -$flag -set/-next"
 		}
-
-		# If we expect a failure, be more tolerant if the above fails;
-		# just make sure it's an ENOMEM, mark it, and move along.
-		if { $expectfail != 0 && $ret != 0 } {
-			error_check_good multi_failure_errcode \
-			    [is_substr $errorCode ENOMEM] 1
-			set allpassed FALSE
-			continue
+		puts "\tTest$tnum.$letter: $action with bufsize $bufsize"
+		set allpassed TRUE
+		set saved_err ""
+
+		# Cursor for $usecursor.
+		if { $usecursor != 0 } {
+			set getcurs [$db cursor]
+			error_check_good getcurs [is_valid_cursor $getcurs $db] TRUE
 		}
-		error_check_good get_multi($key) $ret 0
-		t95_verify $res FALSE
-	}
 
-	set ret [catch {eval $db get -multi $bufsize} res]
+		# Traverse DB with cursor;  do get/c_get($flag) on each item.
+		set dbc [$db cursor]
+		error_check_good is_valid_dbc [is_valid_cursor $dbc $db] TRUE
+		for { set dbt [$dbc get -first] } { [llength $dbt] != 0 } \
+		    { set dbt [$dbc get -nextnodup] } {
+			set key [lindex [lindex $dbt 0] 0]
+			set datum [lindex [lindex $dbt 0] 1]
+
+			if { $usecursor == 0 } {
+				set ret [catch {eval $db get -$flag $bufsize $key} res]
+			} else {
+				set res {}
+				for { set ret [catch {eval $getcurs get -$flag $bufsize\
+				    -set $key} tres] } \
+				    { $ret == 0 && [llength $tres] != 0 } \
+				    { set ret [catch {eval $getcurs get -$flag $bufsize\
+				    -nextdup} tres]} {
+					eval lappend res $tres
+				}
+			}
 
-	if { $expectfail == 1 } {
-		error_check_good allpassed $allpassed FALSE
-		puts "\t\tTest0$tnum.$letter:\
-		    returned at least one ENOMEM (as expected)"
-	} else {
-		error_check_good allpassed $allpassed TRUE
-		puts "\t\tTest0$tnum.$letter: succeeded (as expected)"
-	}
+			# If we expect a failure, be more tolerant if the above
+			# fails; just make sure it's a DB_BUFFER_SMALL or an
+			# EINVAL (if the buffer is smaller than the pagesize,
+			# it's EINVAL), mark it, and move along.
+			if { $expectfail != 0 && $ret != 0 } {
+				if { [is_substr $errorCode DB_BUFFER_SMALL] != 1 && \
+				    [is_substr $errorCode EINVAL] != 1 } {
+					error_check_good \
+					    "$flag failure errcode" \
+					    $errorCode "DB_BUFFER_SMALL or EINVAL"
+				}
+				set allpassed FALSE
+				continue
+			}
+			error_check_good "get_$flag ($key)" $ret 0
+			if { $flag == "multi_key" } {
+				t95_verify $res TRUE
+			} else {
+				t95_verify $res FALSE
+			}
+		}
+		set ret [catch {eval $db get -$flag $bufsize} res]
+
+		if { $expectfail == 1 } {
+			error_check_good allpassed $allpassed FALSE
+			puts "\t\tTest$tnum.$letter:\
+			    returned at least one DB_BUFFER_SMALL (as expected)"
+		} else {
+			error_check_good allpassed $allpassed TRUE
+			puts "\t\tTest$tnum.$letter: succeeded (as expected)"
+		}
 
-	error_check_good dbc_close [$dbc close] 0
-	if { $usecursor != 0 } {
-		error_check_good getcurs_close [$getcurs close] 0
+		error_check_good dbc_close [$dbc close] 0
+		if { $usecursor != 0 } {
+			error_check_good getcurs_close [$getcurs close] 0
+		}
 	}
 }
 
-# Test of invalid flag combinations for -multi
+# Test of invalid flag combinations
 proc t95_flagtest_body { db tnum letter bufsize usecursor } {
 	global errorCode
 
-	if { $usecursor == 0 } {
-		set action "db get -multi "
-	} else {
-		set action "dbc get -multi "
-	}
-	puts "\tTest0$tnum.$letter: $action with invalid flag combinations"
+	foreach flag { multi multi_key } {
+		if { $usecursor == 0 } {
+			if { $flag == "multi_key" } {
+				# db->get does not allow multi_key
+				continue
+			} else {
+				set action "db get -$flag"
+			}
+		} else {
+			set action "dbc get -$flag"
+		}
+		puts "\tTest$tnum.$letter: $action with invalid flag combinations"
 
-	# Cursor for $usecursor.
-	if { $usecursor != 0 } {
-		set getcurs [$db cursor]
-		error_check_good getcurs [is_valid_cursor $getcurs $db] TRUE
-	}
+		# Cursor for $usecursor.
+		if { $usecursor != 0 } {
+			set getcurs [$db cursor]
+			error_check_good getcurs [is_valid_cursor $getcurs $db] TRUE
+		}
 
-	if { $usecursor == 0 } {
-		# Disallowed flags for basic -multi get
-		set badflags [list consume consume_wait {rmw some_key}]
+		if { $usecursor == 0 } {
+			# Disallowed flags for db->get
+			set badflags [list consume consume_wait {rmw some_key}]
 
-		foreach flag $badflags {
-			catch {eval $db get -multi $bufsize -$flag} ret
-			error_check_good \
-			    db:get:multi:$flag [is_substr $errorCode EINVAL] 1
+			foreach badflag $badflags {
+				catch {eval $db get -$flag $bufsize -$badflag} ret
+				error_check_good \
+				    db:get:$flag:$badflag [is_substr $errorCode EINVAL] 1
+			}
+		} else {
+			# Disallowed flags for db->cget
+			set cbadflags [list last get_recno join_item \
+			    {multi_key 1000} prev prevnodup]
+
+			set dbc [$db cursor]
+			$dbc get -first
+			foreach badflag $cbadflags {
+				catch {eval $dbc get -$flag $bufsize -$badflag} ret
+				error_check_good dbc:get:$flag:$badflag \
+					[is_substr $errorCode EINVAL] 1
+			}
+			error_check_good dbc_close [$dbc close] 0
 		}
-       } else {
-		# Disallowed flags for cursor -multi get
-		set cbadflags [list last get_recno join_item \
-		    {multi_key 1000} prev prevnodup]
-
-		set dbc [$db cursor]
-		$dbc get -first
-		foreach flag $cbadflags {
-			catch {eval $dbc get -multi $bufsize -$flag} ret
-			error_check_good dbc:get:multi:$flag \
-				[is_substr $errorCode EINVAL] 1
+		if { $usecursor != 0 } {
+			error_check_good getcurs_close [$getcurs close] 0
 		}
-		error_check_good dbc_close [$dbc close] 0
 	}
-	if { $usecursor != 0 } {
-		error_check_good getcurs_close [$getcurs close] 0
-	}
-	puts "\t\tTest0$tnum.$letter completed"
+	puts "\t\tTest$tnum.$letter completed"
 }
 
 # Verify that a passed-in list of key/data pairs all match the predicted
@@ -232,7 +305,6 @@ proc t95_verify { res multiple_keys } {
 	global alphabet
 
 	set i 0
-
 	set orig_key [lindex [lindex $res 0] 0]
 	set nkeys [string trim $orig_key $alphabet']
 	set base_key [string trim $orig_key 0123456789]
@@ -241,7 +313,6 @@ proc t95_verify { res multiple_keys } {
 	while { 1 } {
 		set key [lindex [lindex $res $i] 0]
 		set datum [lindex [lindex $res $i] 1]
-
 		if { $datum_count >= $nkeys } {
 			if { [llength $key] != 0 } {
 				# If there are keys beyond $nkeys, we'd
diff --git a/storage/bdb/test/test096.tcl b/storage/bdb/test/test096.tcl
index 042df19eac77659cd2a7081bf6af63a9672cd4a6..ac8450069cc80d6367a2f6afafea97dbe2ba38d8 100644
--- a/storage/bdb/test/test096.tcl
+++ b/storage/bdb/test/test096.tcl
@@ -1,14 +1,22 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test096.tcl,v 11.19 2002/08/19 20:09:29 margo Exp $
+# $Id: test096.tcl,v 11.26 2004/06/10 17:21:20 carol Exp $
 #
 # TEST	test096
 # TEST	Db->truncate test.
-proc test096 { method {pagesize 512} {nentries 50} {ndups 4} args} {
+# TEST	For all methods:
+# TEST		Test that truncate empties an existing database.
+# TEST		Test that truncate-write in an aborted txn doesn't
+# TEST 		  change the original contents.
+# TEST		Test that truncate-write in a committed txn does
+# TEST		  overwrite the original contents.
+# TEST	For btree and hash, do the same in a database with offpage dups.
+proc test096 { method {pagesize 512} {nentries 1000} {ndups 19} args} {
 	global fixed_len
+	global alphabet
 	source ./include.tcl
 
 	set orig_fixed_len $fixed_len
@@ -18,11 +26,6 @@ proc test096 { method {pagesize 512} {nentries 50} {ndups 4} args} {
 	set omethod [convert_method $method]
 
 	puts "Test096: $method db truncate method test"
-	if { [is_record_based $method] == 1 || \
-	    [is_rbtree $method] == 1 } {
-		puts "Test096 skipping for method $method"
-		return
-	}
 	set pgindex [lsearch -exact $args "-pagesize"]
 	if { $pgindex != -1 } {
 		puts "Test096: Skipping for specific pagesizes"
@@ -49,45 +52,25 @@ proc test096 { method {pagesize 512} {nentries 50} {ndups 4} args} {
 	} else {
 		env_cleanup $testdir
 
-		#
-		# We need an env for exclusive-use testing.
-		set env [eval {berkdb_env -create -home $testdir -txn} $encargs]
+		# We need an env for exclusive-use testing.  Since we are
+		# using txns, we need at least 1 lock per record for queue.
+		set lockmax [expr $nentries * 2]
+		set env [eval {berkdb_env -create -home $testdir \
+		    -lock_max $lockmax -txn} $encargs]
 		error_check_good env_create [is_valid_env $env] TRUE
 		set closeenv 1
 	}
 
 	set t1 $testdir/t1
 
-	puts "\tTest096.a: Create $nentries entries"
+	puts "\tTest096.a: Create database with $nentries entries"
 	set db [eval {berkdb_open -create -auto_commit \
 	    -env $env $omethod -mode 0644} $args $testfile]
 	error_check_good db_open [is_valid_db $db] TRUE
-
-	set did [open $dict]
-	set count 0
-	set txn ""
-	set pflags ""
-	set gflags ""
-	while { [gets $did str] != -1 && $count < $nentries } {
-		set key $str
-		set datastr [reverse $str]
-		set t [$env txn]
-		error_check_good txn [is_valid_txn $t $env] TRUE
-		set txn "-txn $t"
-		set ret [eval {$db put} \
-		    $txn $pflags {$key [chop_data $method $datastr]}]
-		error_check_good put $ret 0
-		error_check_good txn [$t commit] 0
-
-		set ret [eval {$db get} $gflags {$key}]
-		error_check_good $key:dbget [llength $ret] 1
-
-		incr count
-	}
-	close $did
+	t96_populate $db $omethod $env $nentries
+	error_check_good dbclose [$db close] 0
 
 	puts "\tTest096.b: Truncate database"
-	error_check_good dbclose [$db close] 0
 	set dbtr [eval {berkdb_open -create -auto_commit \
 	    -env $env $omethod -mode 0644} $args $testfile]
 	error_check_good db_open [is_valid_db $dbtr] TRUE
@@ -98,44 +81,91 @@ proc test096 { method {pagesize 512} {nentries 50} {ndups 4} args} {
 
 	set db [eval {berkdb_open -env $env} $args $testfile]
 	error_check_good dbopen [is_valid_db $db] TRUE
-	set ret [$db get -glob *]
-	error_check_good dbget [llength $ret] 0
+	set number [number_of_entries $db $method]
+	error_check_good number_of_entries $number 0
 	error_check_good dbclose [$db close] 0
 	error_check_good dbverify [verify_dir $testdir "\tTest096.c: "] 0
 
-	#
-	# Remove database, and create a new one with dups.
-	#
-	puts "\tTest096.d: Create $nentries entries with $ndups duplicates"
+	# Remove and recreate database.
+	puts "\tTest096.d: Recreate database with $nentries entries"
+	set db [eval {berkdb_open -create -auto_commit \
+	    -env $env $omethod -mode 0644} $args $testfile]
+	error_check_good db_open [is_valid_db $db] TRUE
+	t96_populate $db $omethod $env $nentries
+	error_check_good dbclose [$db close] 0
+
+	puts "\tTest096.e: Truncate and write in a txn, then abort"
+	txn_truncate $env $omethod $testfile $nentries abort 1
+
+	set db [eval {berkdb_open -env $env} $args $testfile]
+	error_check_good dbopen [is_valid_db $db] TRUE
+
+	# Database should have original contents since both the truncate
+	# and the write were aborted
+	set number [number_of_entries $db $method]
+	error_check_good number_of_entries $number $nentries
+	error_check_good dbclose [$db close] 0
+
+	error_check_good dbverify [verify_dir $testdir "\tTest096.f: "] 0
+
+	puts "\tTest096.g: Truncate and write in a txn, then commit"
+	txn_truncate $env $omethod $testfile $nentries commit 1
+
+	set db [eval {berkdb_open -env $env} $args $testfile]
+	error_check_good dbopen [is_valid_db $db] TRUE
+
+	# Database should contain only the new items
+	set number [number_of_entries $db $method]
+	error_check_good number_of_entries $number [expr $nentries / 2]
+	error_check_good dbclose [$db close] 0
+	error_check_good dbverify [verify_dir $testdir "\tTest096.h: "] 0
+
+	puts "\tTest096.i: Check proper handling of overflow pages."
+	# Large keys and data compared to page size guarantee
+	# overflow pages.
+	if { [is_fixed_length $method] == 1 } {
+		puts "Skipping overflow test for fixed-length method."
+	} else {
+		set overflowfile overflow096.db
+		set data [repeat $alphabet 600]
+		set db [eval {berkdb_open -create -auto_commit -pagesize 512 \
+		    -env $env $omethod -mode 0644} $args $overflowfile]
+		error_check_good db_open [is_valid_db $db] TRUE
+
+		set noverflows 100
+		for { set i 1 } { $i <= $noverflows } { incr i } {
+			set ret [eval {$db put} -auto_commit \
+			    $i [chop_data $method "$i$data"]]
+		}
+
+		set stat [$db stat]
+		error_check_bad stat:overflow [is_substr $stat \
+		    "{{Overflow pages} 0}"] 1
+
+		error_check_good overflow_truncate [$db truncate] $noverflows
+		error_check_good overflow_close [$db close] 0
+	}
+
+	# Remove database and create a new one with dups.  Skip
+	# the rest of the test for methods not supporting dups.
+	if { [is_record_based $method] == 1 || \
+	    [is_rbtree $method] == 1 } {
+		puts "Skipping remainder of test096 for method $method"
+		if { $closeenv == 1 } {
+			error_check_good envclose [$env close] 0
+		}
+		return
+	}
 	set ret [berkdb dbremove -env $env -auto_commit $testfile]
+	set ret [berkdb dbremove -env $env -auto_commit $overflowfile]
+
+	puts "\tTest096.j: Create $nentries entries with $ndups duplicates"
 	set db [eval {berkdb_open -pagesize $pagesize -dup -auto_commit \
 	    -create -env $env $omethod -mode 0644} $args $testfile]
 	error_check_good db_open [is_valid_db $db] TRUE
-	set did [open $dict]
-	set count 0
-	set txn ""
-	set pflags ""
-	set gflags ""
-	while { [gets $did str] != -1 && $count < $nentries } {
-		set key $str
-		for { set i 1 } { $i <= $ndups } { incr i } {
-			set datastr $i:$str
-			set t [$env txn]
-			error_check_good txn [is_valid_txn $t $env] TRUE
-			set txn "-txn $t"
-			set ret [eval {$db put} \
-			    $txn $pflags {$key [chop_data $method $datastr]}]
-			error_check_good put $ret 0
-			error_check_good txn [$t commit] 0
-		}
 
-		set ret [eval {$db get} $gflags {$key}]
-		error_check_bad $key:dbget_dups [llength $ret] 0
-		error_check_good $key:dbget_dups1 [llength $ret] $ndups
+	t96_populate $db $omethod $env $nentries $ndups
 
-		incr count
-	}
-	close $did
 	set dlist ""
 	for { set i 1 } {$i <= $ndups} {incr i} {
 		lappend dlist $i
@@ -145,58 +175,197 @@ proc test096 { method {pagesize 512} {nentries 50} {ndups 4} args} {
 	set txn "-txn $t"
 	dup_check $db $txn $t1 $dlist
 	error_check_good txn [$t commit] 0
-	puts "\tTest096.e: Verify off page duplicates status"
+	puts "\tTest096.k: Verify off page duplicates status"
 	set stat [$db stat]
 	error_check_bad stat:offpage [is_substr $stat \
 	    "{{Duplicate pages} 0}"] 1
 
-	set recs [expr $ndups * $count]
+	set recs [expr $ndups * $nentries]
 	error_check_good dbclose [$db close] 0
 
-	puts "\tTest096.f: Truncate database in a txn then abort"
-	set txn [$env txn]
+	puts "\tTest096.l: Truncate database in a txn then abort"
+	txn_truncate $env $omethod $testfile $recs abort
 
-	set dbtr [eval {berkdb_open -auto_commit -create \
-	    -env $env $omethod -mode 0644} $args $testfile]
-	error_check_good db_open [is_valid_db $dbtr] TRUE
-	error_check_good txnbegin [is_valid_txn $txn $env] TRUE
+	set db [eval {berkdb_open -auto_commit -env $env} $args $testfile]
+	error_check_good dbopen [is_valid_db $db] TRUE
 
-	set ret [$dbtr truncate -txn $txn]
-	error_check_good dbtrunc $ret $recs
+	set number [number_of_entries $db $method]
+	error_check_good number_of_entries $number $recs
+	error_check_good dbclose [$db close] 0
 
-	error_check_good txnabort [$txn abort] 0
-	error_check_good db_close [$dbtr close] 0
+	puts "\tTest096.m: Truncate database in a txn then commit"
+	txn_truncate $env $omethod $testfile $recs commit
 
-	set db [eval {berkdb_open -auto_commit -env $env} $args $testfile]
+	set db [berkdb_open -auto_commit -env $env $testfile]
 	error_check_good dbopen [is_valid_db $db] TRUE
-	set ret [$db get -glob *]
-	error_check_good dbget [llength $ret] $recs
+	set number [number_of_entries $db $method]
+	error_check_good number_of_entries $number 0
 	error_check_good dbclose [$db close] 0
 
-	puts "\tTest096.g: Truncate database in a txn then commit"
-	set txn [$env txn]
-	error_check_good txnbegin [is_valid_txn $txn $env] TRUE
+	set testdir [get_home $env]
+	error_check_good dbverify [verify_dir $testdir "\tTest096.n: "] 0
 
-	set dbtr [eval {berkdb_open -auto_commit -create \
-	    -env $env $omethod -mode 0644} $args $testfile]
-	error_check_good db_open [is_valid_db $dbtr] TRUE
+	# Remove database, and create a new one with dups.  Test
+	# truncate + write within a transaction.
+	puts "\tTest096.o: Create $nentries entries with $ndups duplicates"
+	set ret [berkdb dbremove -env $env -auto_commit $testfile]
+	set db [eval {berkdb_open -pagesize $pagesize -dup -auto_commit \
+	    -create -env $env $omethod -mode 0644} $args $testfile]
+	error_check_good db_open [is_valid_db $db] TRUE
 
-	set ret [$dbtr truncate -txn $txn]
-	error_check_good dbtrunc $ret $recs
+	t96_populate $db $omethod $env $nentries $ndups
 
-	error_check_good txncommit [$txn commit] 0
-	error_check_good db_close [$dbtr close] 0
+	set dlist ""
+	for { set i 1 } {$i <= $ndups} {incr i} {
+		lappend dlist $i
+	}
+	set t [$env txn]
+	error_check_good txn [is_valid_txn $t $env] TRUE
+	set txn "-txn $t"
+	dup_check $db $txn $t1 $dlist
+	error_check_good txn [$t commit] 0
+	puts "\tTest096.p: Verify off page duplicates status"
+	set stat [$db stat]
+	error_check_bad stat:offpage [is_substr $stat \
+	    "{{Duplicate pages} 0}"] 1
+
+	set recs [expr $ndups * $nentries]
+	error_check_good dbclose [$db close] 0
+
+	puts "\tTest096.q: Truncate and write in a txn, then abort"
+	txn_truncate $env $omethod $testfile $recs abort 1
+
+	set db [eval {berkdb_open -auto_commit -env $env} $args $testfile]
+	error_check_good dbopen [is_valid_db $db] TRUE
+	set number [number_of_entries $db $method]
+	error_check_good number_of_entries $number $recs
+	error_check_good dbclose [$db close] 0
+
+	puts "\tTest096.r: Truncate and write in a txn, then commit"
+	txn_truncate $env $omethod $testfile $recs commit 1
 
 	set db [berkdb_open -auto_commit -env $env $testfile]
 	error_check_good dbopen [is_valid_db $db] TRUE
-	set ret [$db get -glob *]
-	error_check_good dbget [llength $ret] 0
+	set number [number_of_entries $db $method]
+	error_check_good number_of_entries $number [expr $recs / 2]
 	error_check_good dbclose [$db close] 0
 
+	puts "\tTest096.s: Check overflow pages with dups."
+	set ndups 3
+	set db [eval {berkdb_open -create -auto_commit -pagesize 512 \
+	    -env $env $omethod -dup -mode 0644} $args $overflowfile]
+	error_check_good db_open [is_valid_db $db] TRUE
+
+	for { set i 1 } { $i <= $noverflows } { incr i } {
+		for { set j 0 } { $j < $ndups } { incr j } {
+			set ret [eval {$db put} -auto_commit \
+			    $i [chop_data $method "$i.$j$data"]]
+		}
+	}
+
+	set stat [$db stat]
+	error_check_bad stat:overflow [is_substr $stat \
+	    "{{Overflow pages} 0}"] 1
+
+	set nentries [expr $noverflows * $ndups]
+	error_check_good overflow_truncate [$db truncate] $nentries
+	error_check_good overflow_close [$db close] 0
+
 	set testdir [get_home $env]
-	error_check_good dbverify [verify_dir $testdir "\tTest096.h: "] 0
+	error_check_good dbverify [verify_dir $testdir "\tTest096.t: "] 0
 
 	if { $closeenv == 1 } {
 		error_check_good envclose [$env close] 0
 	}
 }
+
+proc t96_populate {db method env nentries {ndups 1}} {
+	global datastr
+	global pad_datastr
+	source ./include.tcl
+
+	set did [open $dict]
+	set count 0
+	set txn ""
+	set pflags ""
+	set gflags ""
+
+	if { [is_record_based $method] == 1 } {
+		append gflags "-recno"
+	}
+	set pad_datastr [pad_data $method $datastr]
+	while { [gets $did str] != -1 && $count < $nentries } {
+		if { [is_record_based $method] == 1 } {
+			set key [expr $count + 1]
+		} else {
+			set key $str
+		}
+		if { $ndups > 1 } {
+			for { set i 1 } { $i <= $ndups } { incr i } {
+				set datastr $i:$str
+				set t [$env txn]
+				error_check_good txn [is_valid_txn $t $env] TRUE
+				set txn "-txn $t"
+				set ret [eval {$db put} $txn $pflags \
+				    {$key [chop_data $method $datastr]}]
+				error_check_good put $ret 0
+				error_check_good txn [$t commit] 0
+			}
+		} else {
+			set datastr [reverse $str]
+			set t [$env txn]
+			error_check_good txn [is_valid_txn $t $env] TRUE
+			set txn "-txn $t"
+			set ret [eval {$db put} \
+			    $txn $pflags {$key [chop_data $method $datastr]}]
+			error_check_good put $ret 0
+			error_check_good txn [$t commit] 0
+		}
+		set ret [eval {$db get} $gflags {$key}]
+		error_check_good $key:dbget [llength $ret] $ndups
+		incr count
+	}
+	close $did
+}
+
+proc number_of_entries { db method } {
+	if { [is_record_based $method] == 1 } {
+		set dbc [$db cursor]
+		set last [$dbc get -last]
+		if {[llength $last] == 0} {
+			set number 0
+		} else {
+			set number [lindex [lindex $last 0] 0]
+		}
+	} else {
+		set ret [$db get -glob *]
+		set number [llength $ret]
+	}
+	return $number
+}
+
+# Open database.  Truncate in a transaction, optionally with a write
+# included in the transaction as well, then abort or commit.  Close database.
+
+proc txn_truncate { env method testfile nentries op {write 0}} {
+	set db [eval {berkdb_open -create -auto_commit \
+	    -env $env $method -mode 0644} $testfile]
+	error_check_good db_open [is_valid_db $db] TRUE
+
+	set txn [$env txn]
+	error_check_good txnbegin [is_valid_txn $txn $env] TRUE
+
+	set ret [$db truncate -txn $txn]
+	error_check_good dbtrunc $ret $nentries
+	if { $write == 1 } {
+		for {set i 1} {$i <= [expr $nentries / 2]} {incr i} {
+			set ret [eval {$db put} -txn $txn \
+			    {$i [chop_data $method "aaaaaaaaaa"]}]
+			error_check_good write $ret 0
+		}
+	}
+
+	error_check_good txn$op [$txn $op] 0
+	error_check_good db_close [$db close] 0
+}
+
diff --git a/storage/bdb/test/test097.tcl b/storage/bdb/test/test097.tcl
index 6e43b820b2fbc782a6c01e94b7bd53d7bc1031fc..2a6234e00a55676c94fc3f1218cc47e1b43b4b86 100644
--- a/storage/bdb/test/test097.tcl
+++ b/storage/bdb/test/test097.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test097.tcl,v 11.8 2002/09/04 18:47:42 sue Exp $
+# $Id: test097.tcl,v 11.11 2004/01/28 03:36:32 bostic Exp $
 #
 # TEST	test097
 # TEST	Open up a large set of database files simultaneously.
@@ -35,7 +35,7 @@ proc test097 { method {ndbs 500} {nentries 400} args } {
 	error_check_good dbenv [is_valid_env $env] TRUE
 
 	# Create the database and open the dictionary
-	set testfile test097.db
+	set basename test097
 	set t1 $testdir/t1
 	set t2 $testdir/t2
 	set t3 $testdir/t3
@@ -58,7 +58,7 @@ proc test097 { method {ndbs 500} {nentries 400} args } {
 	puts "$nentries entries in at most $ndbs simultaneous databases"
 
 	puts "\tTest097.a: Simultaneous open"
-	set numdb [test097_open tdb $ndbs $method $env $testfile $largs]
+	set numdb [test097_open tdb $ndbs $method $env $basename $largs]
 	if { $numdb == 0 } {
 		puts "\tTest097: Insufficient resources available -- skipping."
 		error_check_good envclose [$env close] 0
@@ -131,7 +131,7 @@ proc test097.check { key data } {
 	error_check_good "data mismatch for key $key" $data $pad_datastr
 }
 
-proc test097_open { tdb ndbs method env testfile largs } {
+proc test097_open { tdb ndbs method env basename largs } {
 	global errorCode
 	upvar $tdb db
 
@@ -144,7 +144,7 @@ proc test097_open { tdb ndbs method env testfile largs } {
 	for { set i 1 } {$i <= $numdb } { incr i } {
 		set stat [catch {eval {berkdb_open -env $env \
 		     -pagesize 512 -create -mode 0644} \
-		     $largs {$omethod $testfile.$i}} db($i)]
+		     $largs {$omethod $basename.$i.db}} db($i)]
 		#
 		# Check if we've reached our limit
 		#
diff --git a/storage/bdb/test/test098.tcl b/storage/bdb/test/test098.tcl
index 320e0258a84677a7db792f0ef31a09cf3ecee147..af6b6a6c607ca5cddf9ac97d999ba9cb57514825 100644
--- a/storage/bdb/test/test098.tcl
+++ b/storage/bdb/test/test098.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2002
+# Copyright (c) 2002-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test098.tcl,v 1.5 2002/07/11 20:38:36 sandstro Exp $
+# $Id: test098.tcl,v 1.7 2004/01/28 03:36:32 bostic Exp $
 #
 # TEST	test098
 # TEST	Test of DB_GET_RECNO and secondary indices.  Open a primary and
diff --git a/storage/bdb/test/test099.tcl b/storage/bdb/test/test099.tcl
index db177ce5fffed2e669405e212b78a69efca9acb4..9bdc0d7af4201752bbfba22f090b7869825aa780 100644
--- a/storage/bdb/test/test099.tcl
+++ b/storage/bdb/test/test099.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test099.tcl,v 1.2 2002/08/08 15:38:13 bostic Exp $
+# $Id: test099.tcl,v 1.7 2004/01/28 03:36:32 bostic Exp $
 #
 # TEST	test099
 # TEST
@@ -14,6 +14,11 @@
 # TEST	Open a cursor and do the same for DBC->c_get with set_recno.
 # TEST	Verify that set_recno sets the record number position properly.
 # TEST	Verify that get_recno returns the correct record numbers.
+# TEST
+# TEST	Using the same database, open 3 cursors and position one at
+# TEST	the beginning, one in the middle, and one at the end.  Delete
+# TEST	by cursor and check that record renumbering is done properly.
+#
 proc test099 { method {nentries 10000} args } {
 	source ./include.tcl
 
@@ -70,10 +75,7 @@ proc test099 { method {nentries 10000} args } {
 
 	puts "\tTest099.a: put loop"
 	# Here is the loop where we put each key/data pair
-	while { [gets $did str] != -1 && $count < $nentries } {
-#		global kvals
-#		set key [expr $count]
-#		set kvals($key) [pad_data $method $str]
+	while { [gets $did str] != -1 && $count <= $nentries } {
 		set key $str
 		if { $txnenv == 1 } {
 			set t [$env txn]
@@ -113,7 +115,7 @@ proc test099 { method {nentries 10000} args } {
 		set txn "-txn $t"
 	}
 	set dbc [eval {$db cursor} $txn]
-	error_check_good db_cursor [is_substr $dbc $db] 1
+	error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
 
 	set did [open $t1]
 	set recno 1
@@ -169,6 +171,103 @@ proc test099 { method {nentries 10000} args } {
 	}
 	error_check_good db_close [$db close] 0
 	close $did
+
+	puts "\tTest099.d: Test record renumbering with cursor deletes."
+	# Reopen the database, this time with write permission.
+	set db [eval {berkdb_open} $args $omethod $testfile ]
+	error_check_good dbopen [is_valid_db $db] TRUE
+
+	# Open three cursors.
+	if { $txnenv == 1 } {
+		set t [$env txn]
+		error_check_good txn [is_valid_txn $t $env] TRUE
+		set txn "-txn $t"
+	}
+	set dbc0 [eval {$db cursor} $txn]
+	error_check_good db_cursor [is_valid_cursor $dbc0 $db] TRUE
+	set dbc1 [eval {$db cursor} $txn]
+	error_check_good db_cursor [is_valid_cursor $dbc1 $db] TRUE
+	set dbc2 [eval {$db cursor} $txn]
+	error_check_good db_cursor [is_valid_cursor $dbc2 $db] TRUE
+
+	# Initialize cursor positions.  Set dbc0 at the beginning,
+	# dbc1 at the middle, and dbc2 at the end.
+	set ret [$dbc0 get -first]
+	error_check_bad dbc0_get_first [llength $ret] 0
+
+	set middle [expr $nentries / 2 + 1]
+	set ret [$dbc1 get -set_recno $middle]
+	error_check_bad dbc1_get_middle [llength $ret] 0
+
+	set ret [$dbc2 get -last]
+	error_check_bad dbc2_get_last [llength $ret] 0
+
+	# At each iteration, delete the first entry, delete the middle
+	# entry, and check the record number for beginning, middle and end.
+	set count 1
+	while { $count <= [expr $nentries / 2] } {
+		# Delete first item.
+		error_check_good dbc0_del [$dbc0 del] 0
+
+		# For non-txn env's, check that db_stat is recalculating
+		# to adjust for items marked for deletion.  We can't do this
+		# in txn env's because the live txn will cause deadlock.
+		if { $txnenv == 0 } {
+			set nkeys [expr $nentries - [expr $count * 2] + 1]
+			set stat [$db stat]
+			error_check_good keys_after_delete [is_substr $stat \
+			     "{Number of keys} $nkeys"] 1
+			error_check_good records_after_delete [is_substr $stat \
+			     "{Number of records} $nkeys"] 1
+
+			# Now delete the same entry again (which should not
+			# change the database) and make sure db->stat returns
+			# the same number of keys and records as before.
+			catch {[$dbc0 del]} result
+
+			set stat [$db stat]
+			error_check_good keys_after_baddelete [is_substr $stat \
+			     "{Number of keys} $nkeys"] 1
+			error_check_good recs_after_baddelete [is_substr $stat \
+			     "{Number of records} $nkeys"] 1
+		}
+
+		# Reposition cursor to new first item, check that record number
+		# is 1.
+		set ret0 [$dbc0 get -next]
+		error_check_good beginning_recno [$dbc0 get -get_recno] 1
+
+		# Calculate the current middle recno and compare to actual.
+		set middle [$dbc1 get -get_recno]
+		set calcmiddle [expr [expr $nentries / 2] - $count + 1]
+		error_check_good middle_recno $middle $calcmiddle
+
+		# Delete middle item, reposition cursor to next item.
+		error_check_good dbc1_del [$dbc1 del] 0
+		set ret1 [$dbc1 get -next]
+
+		# Calculate the expected end recno and compare to actual.
+		set end [$dbc2 get -get_recno]
+		set calcend [expr $nentries - [expr $count * 2]]
+		# On the last iteration, all items have been deleted so
+		# there is no recno.
+		if { $calcend == 0 } {
+			error_check_good end_recno $end ""
+		} else {
+			error_check_good end_recno $end $calcend
+		}
+		incr count
+	}
+
+	# Close all three cursors.
+	error_check_good cursor_close [$dbc0 close] 0
+	error_check_good cursor_close [$dbc1 close] 0
+	error_check_good cursor_close [$dbc2 close] 0
+
+	if { $txnenv == 1 } {
+		error_check_good txn [$t commit] 0
+	}
+	error_check_good db_close [$db close] 0
 }
 
 # Check function for dumped file; data should be fixed are identical
diff --git a/storage/bdb/test/test100.tcl b/storage/bdb/test/test100.tcl
index f80b2e526dd242183e1a509f8512a6e54f879a5d..9d87331dc08fa4a7908c2f8413255568e5f5f94d 100644
--- a/storage/bdb/test/test100.tcl
+++ b/storage/bdb/test/test100.tcl
@@ -1,16 +1,16 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2000-2002
+# Copyright (c) 2000-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test100.tcl,v 11.1 2002/08/15 20:55:20 sandstro Exp $
+# $Id: test100.tcl,v 11.5 2004/01/28 03:36:32 bostic Exp $
 #
 # TEST	test100
 # TEST	Test for functionality near the end of the queue
 # TEST	using test025 (DB_APPEND).
-proc test100 { method {nentries 10000} {txn -txn} {tnum "100"} args} {
+proc test100 { method {nentries 10000} {tnum "100"} args} {
 	if { [is_queueext $method ] == 0 } {
-		puts "Skipping test0$tnum for $method."
+		puts "Skipping test$tnum for $method."
 		return;
 	}
 	eval {test025 $method $nentries 4294967000 $tnum} $args
diff --git a/storage/bdb/test/test101.tcl b/storage/bdb/test/test101.tcl
index 7e5c8fc30fc76c6821cf6bebed06005147bc7356..63384dd1776bda1796868cdc2b07b59a52626e96 100644
--- a/storage/bdb/test/test101.tcl
+++ b/storage/bdb/test/test101.tcl
@@ -1,17 +1,17 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2000-2002
+# Copyright (c) 2000-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: test101.tcl,v 11.1 2002/08/15 20:55:20 sandstro Exp $
+# $Id: test101.tcl,v 11.6 2004/01/28 03:36:32 bostic Exp $
 #
 # TEST	test101
-# TEST	Test for functionality near the end of the queue 
+# TEST	Test for functionality near the end of the queue
 # TEST	using test070 (DB_CONSUME).
-proc test101 { method {nentries 10000} {txn -txn} {tnum "101"} args} {
+proc test101 { method {nentries 1000} {txn -txn} {tnum "101"} args} {
 	if { [is_queueext $method ] == 0 } {
-		puts "Skipping test0$tnum for $method."
+		puts "Skipping test$tnum for $method."
 		return;
 	}
-	eval {test070 $method 4 2 1000 WAIT 4294967000 $txn $tnum} $args
+	eval {test070 $method 4 2 $nentries WAIT 4294967000 $txn $tnum} $args
 }
diff --git a/storage/bdb/test/testparams.tcl b/storage/bdb/test/testparams.tcl
index 6628db532d7c15272ef7a14fbd48ca4d2e7cfe3c..16ef7c9b0b0b13d238ade6b3a0830db68abaf2a8 100644
--- a/storage/bdb/test/testparams.tcl
+++ b/storage/bdb/test/testparams.tcl
@@ -1,30 +1,111 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2000-2002
+# Copyright (c) 2000-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: testparams.tcl,v 11.117 2002/09/05 02:30:00 margo Exp $
+# $Id: testparams.tcl,v 11.200 2004/10/12 16:22:14 sue Exp $
 
-set subs {bigfile dead env lock log memp mutex recd rep rpc rsrc \
-    sdb sdbtest sec si test txn}
+global one_test
+global serial_tests
+set serial_tests {rep002 rep005}
 
-set num_test(bigfile)	  2
-set num_test(dead)	  7
-set num_test(env)	 11
-set num_test(lock)	  5
-set num_test(log)	  5
-set num_test(memp)	  3
-set num_test(mutex)	  3
-set num_test(recd)	 20
-set num_test(rep)	  5
-set num_test(rpc)	  5
-set num_test(rsrc)	  4
-set num_test(sdb)	 12
-set num_test(sdbtest)	  2
-set num_test(sec)	  2
-set num_test(si)	  6
-set num_test(test)	101 	
-set num_test(txn)	  9
+set subs {bigfile dead env fop lock log memp mutex recd rep rpc rsrc\
+	sdb sdbtest sec si test txn}
+
+set test_names(bigfile)	[list bigfile001 bigfile002]
+set test_names(dead)    [list dead001 dead002 dead003 dead004 dead005 dead006 \
+    dead007]
+set test_names(elect)	[list rep002 rep005 rep016 rep020 rep022]
+set test_names(env)	[list env001 env002 env003 env004 env005 env006 \
+    env007 env008 env009 env010 env011]
+set test_names(fop)	[list fop001 fop002 fop003 fop004 fop005 fop006]
+set test_names(lock)    [list lock001 lock002 lock003 lock004 lock005 lock006]
+set test_names(log)     [list log001 log002 log003 log004 log005 log006]
+set test_names(memp)	[list memp001 memp002 memp003 memp004]
+set test_names(mutex)	[list mutex001 mutex002 mutex003]
+set test_names(recd)	[list recd001 recd002 recd003 recd004 recd005 recd006 \
+    recd007 recd008 recd009 recd010 recd011 recd012 recd013 recd014 recd015 \
+    recd016 recd017 recd018 recd019 recd020 ]
+set test_names(rep)	[list rep001 rep002 rep003 rep005 rep006 rep007 \
+    rep008 rep009 rep010 rep011 rep012 rep013 rep014 rep015 rep016 rep017 \
+    rep018 rep019 rep020 rep021 rep022 rep023 rep024 rep026 rep027 rep028 \
+    rep029 rep030 rep031 rep032 rep033 rep034 rep035 rep036 rep037]
+set test_names(rpc)	[list rpc001 rpc002 rpc003 rpc004 rpc005 rpc006]
+set test_names(rsrc)	[list rsrc001 rsrc002 rsrc003 rsrc004]
+set test_names(sdb)	[list sdb001 sdb002 sdb003 sdb004 sdb005 sdb006 \
+    sdb007 sdb008 sdb009 sdb010 sdb011 sdb012]
+set test_names(sdbtest)	[list sdbtest001 sdbtest002]
+set test_names(sec)	[list sec001 sec002]
+set test_names(si)	[list si001 si002 si003 si004 si005]
+set test_names(test)	[list test001 test002 test003 test004 test005 \
+    test006 test007 test008 test009 test010 test011 test012 test013 test014 \
+    test015 test016 test017 test018 test019 test020 test021 test022 test023 \
+    test024 test025 test026 test027 test028 test029 test030 test031 test032 \
+    test033 test034 test035 test036 test037 test038 test039 test040 test041 \
+    test042 test043 test044 test045 test046 test047 test048 test049 test050 \
+    test051 test052 test053 test054 test055 test056 test057 test058 test059 \
+    test060 test061 test062 test063 test064 test065 test066 test067 test068 \
+    test069 test070 test071 test072 test073 test074 test076 test077 \
+    test078 test079 test081 test082 test083 test084 test085 test086 \
+    test087 test088 test089 test090 test091 test092 test093 test094 test095 \
+    test096 test097 test098 test099 test100 test101 test102 test103 test107 \
+    test109 ]
+set test_names(txn)	[list txn001 txn002 txn003 txn004 txn005 txn006 \
+    txn007 txn008 txn009 txn010 txn011]
+
+set rpc_tests(berkeley_db_svc) [concat $test_names(test) $test_names(sdb)]
+set rpc_tests(berkeley_db_cxxsvc) $test_names(test)
+set rpc_tests(berkeley_db_javasvc) $test_names(test)
+
+# JE tests are a subset of regular RPC tests -- exclude these ones.
+# be fixable by modifying tests dealing with unsorted duplicates, second line
+# will probably never work unless certain features are added to JE (record
+# numbers, bulk get, etc.).
+set je_exclude {(?x)    # Turn on extended syntax
+	test(010|026|027|028|030|031|032|033|034|   # These should be fixable by
+	     035|039|041|046|047|054|056|057|062|   # modifying tests to avoid
+	     066|073|081|085)|                      # unsorted dups, etc.
+
+	test(011|017|018|022|023|024|029|040|049|   # Not expected to work with
+	     062|083|095)                           # JE until / unless features
+						    # are added to JE (record
+						    # numbers, bulk gets, etc.)
+}
+set rpc_tests(berkeley_dbje_svc) [lsearch -all -inline -not -regexp \
+                                  $rpc_tests(berkeley_db_svc) $je_exclude]
+
+# Source all the tests, whether we're running one or many.
+foreach sub $subs {
+	foreach test $test_names($sub) {
+		source $test_path/$test.tcl
+	}
+}
+
+# Reset test_names if we're running only one test.
+if { $one_test != "ALL" } {
+	foreach sub $subs {
+		set test_names($sub) ""
+	}
+	set type [string trim $one_test 0123456789]
+	set test_names($type) [list $one_test]
+}
+
+source $test_path/archive.tcl
+source $test_path/byteorder.tcl
+source $test_path/dbm.tcl
+source $test_path/foputils.tcl
+source $test_path/hsearch.tcl
+source $test_path/join.tcl
+source $test_path/logtrack.tcl
+source $test_path/ndbm.tcl
+source $test_path/parallel.tcl
+source $test_path/reputils.tcl
+source $test_path/sdbutils.tcl
+source $test_path/shelltest.tcl
+source $test_path/sijointest.tcl
+source $test_path/siutils.tcl
+source $test_path/testutils.tcl
+source $test_path/upgrade.tcl
 
 set parms(recd001) 0
 set parms(recd002) 0
@@ -46,6 +127,40 @@ set parms(recd017) 0
 set parms(recd018) 10
 set parms(recd019) 50
 set parms(recd020) ""
+set parms(rep001) {1000 "001"}
+set parms(rep002) {10 3 "002"}
+set parms(rep003) "003"
+set parms(rep005) ""
+set parms(rep006) {1000 "006"}
+set parms(rep007) {10 "007"}
+set parms(rep008) {10 "008"}
+set parms(rep009) {10 "009"}
+set parms(rep010) {100 "010"}
+set parms(rep011) "011"
+set parms(rep012) {10 "012"}
+set parms(rep013) {10 "013"}
+set parms(rep014) {10 "014"}
+set parms(rep015) {100 "015" 3}
+set parms(rep016) ""
+set parms(rep017) {10 "017"}
+set parms(rep018) {10 "018"}
+set parms(rep019) {3 "019"}
+set parms(rep020) ""
+set parms(rep021) {3 "021"}
+set parms(rep022) ""
+set parms(rep023) {10 "023"}
+set parms(rep024) {1000 "024"}
+set parms(rep026) ""
+set parms(rep027) {1000 "027"}
+set parms(rep028) {100 "028"}
+set parms(rep029) {200 "029"}
+set parms(rep030) {500 "030"}
+set parms(rep031) {200 "031"}
+set parms(rep032) {200 "032"}
+set parms(rep033) {200 "033"}
+set parms(rep034) {2 "034"}
+set parms(rep035) {100 "035"}
+set parms(rep036) {200 "036"}
 set parms(subdb001) ""
 set parms(subdb002) 10000
 set parms(subdb003) 1000
@@ -58,23 +173,40 @@ set parms(subdb009) ""
 set parms(subdb010) ""
 set parms(subdb011) {13 10}
 set parms(subdb012) ""
-set parms(test001) {10000 0 "01" 0}
+set parms(sdb001) ""
+set parms(sdb002) 10000
+set parms(sdb003) 1000
+set parms(sdb004) ""
+set parms(sdb005) 100
+set parms(sdb006) 100
+set parms(sdb007) ""
+set parms(sdb008) ""
+set parms(sdb009) ""
+set parms(sdb010) ""
+set parms(sdb011) {13 10}
+set parms(sdb012) ""
+set parms(si001) {200 1}
+set parms(si002) {200 2}
+set parms(si003) {200 3}
+set parms(si004) {200 4}
+set parms(si005) {200 5}
+set parms(test001) {10000 0 0 "001"}
 set parms(test002) 10000
 set parms(test003) ""
-set parms(test004) {10000 4 0}
+set parms(test004) {10000 "004" 0}
 set parms(test005) 10000
-set parms(test006) {10000 0 6}
-set parms(test007) {10000 7}
-set parms(test008) {8 0}
+set parms(test006) {10000 0 "006" 5}
+set parms(test007) {10000 "007" 5}
+set parms(test008) {"008" 0}
 set parms(test009) ""
-set parms(test010) {10000 5 10}
-set parms(test011) {10000 5 11}
+set parms(test010) {10000 5 "010"}
+set parms(test011) {10000 5 "011"}
 set parms(test012)  ""
 set parms(test013) 10000
 set parms(test014) 10000
 set parms(test015) {7500 0}
 set parms(test016) 10000
-set parms(test017) {0 19 17}
+set parms(test017) {0 19 "017"}
 set parms(test018) 10000
 set parms(test019) 10000
 set parms(test020) 10000
@@ -82,21 +214,21 @@ set parms(test021) 10000
 set parms(test022) ""
 set parms(test023) ""
 set parms(test024) 10000
-set parms(test025) {10000 0 25}
-set parms(test026) {2000 5 26}
+set parms(test025) {10000 0 "025"}
+set parms(test026) {2000 5 "026"}
 set parms(test027) {100}
 set parms(test028) ""
 set parms(test029) 10000
 set parms(test030) 10000
-set parms(test031) {10000 5 31}
-set parms(test032) {10000 5 32}
-set parms(test033) {10000 5 33}
+set parms(test031) {10000 5 "031"}
+set parms(test032) {10000 5 "032"}
+set parms(test033) {10000 5 "033"}
 set parms(test034) 10000
 set parms(test035) 10000
 set parms(test036) 10000
 set parms(test037) 100
-set parms(test038) {10000 5 38}
-set parms(test039) {10000 5 39}
+set parms(test038) {10000 5 "038"}
+set parms(test039) {10000 5 "039"}
 set parms(test040) 10000
 set parms(test041) 10000
 set parms(test042) 1000
@@ -119,51 +251,53 @@ set parms(test058) ""
 set parms(test059) ""
 set parms(test060) ""
 set parms(test061) ""
-set parms(test062) {200 200 62}
+set parms(test062) {200 200 "062"}
 set parms(test063) ""
 set parms(test064) ""
 set parms(test065) ""
 set parms(test066) ""
-set parms(test067) {1000 67}
+set parms(test067) {1000 "067"}
 set parms(test068) ""
-set parms(test069) {50 69}
-set parms(test070) {4 2 1000 CONSUME 0 -txn 70}
-set parms(test071) {1 1 10000 CONSUME 0 -txn 71}
-set parms(test072) {512 20 72}
-set parms(test073) {512 50 73}
-set parms(test074) {-nextnodup 100 74}
-set parms(test075) {75}
-set parms(test076) {1000 76}
-set parms(test077) {1000 512 77}
-set parms(test078) {100 512 78}
-set parms(test079) {10000 512 79}
-set parms(test080) {80}
-set parms(test081) {13 81}
-set parms(test082) {-prevnodup 100 82}
+set parms(test069) {50 "069"}
+set parms(test070) {4 2 1000 CONSUME 0 -txn "070"}
+set parms(test071) {1 1 10000 CONSUME 0 -txn "071"}
+set parms(test072) {512 20 "072"}
+set parms(test073) {512 50 "073"}
+set parms(test074) {-nextnodup 100 "074"}
+set parms(test076) {1000 "076"}
+set parms(test077) {1000 "077"}
+set parms(test078) {100 512 "078"}
+set parms(test079) {10000 512 "079" 20}
+set parms(test081) {13 "081"}
+set parms(test082) {-prevnodup 100 "082"}
 set parms(test083) {512 5000 2}
-set parms(test084) {10000 84 65536}
-set parms(test085) {512 3 10 85}
+set parms(test084) {10000 "084" 65536}
+set parms(test085) {512 3 10 "085"}
 set parms(test086) ""
-set parms(test087) {512 50 87}
+set parms(test087) {512 50 "087"}
 set parms(test088) ""
 set parms(test089) 1000
-set parms(test090) {10000 -txn 90}
-set parms(test091) {4 2 1000 0 91}
+set parms(test090) {10000 "090"}
+set parms(test091) {4 2 1000 0 "091"}
 set parms(test092) {1000}
-set parms(test093) {10000 93}
-set parms(test094) {10000 10 94}
-set parms(test095) {1000 25 95}
+set parms(test093) {10000 "093"}
+set parms(test094) {10000 10 "094"}
+set parms(test095) {"095"}
 set parms(test096) {512 1000 19}
 set parms(test097) {500 400}
 set parms(test098) ""
 set parms(test099) 10000
-set parms(test100) {10000 -txn 100}
-set parms(test101) {10000 -txn 101}
+set parms(test100) {10000 "100"}
+set parms(test101) {1000 -txn "101"}
+set parms(test102) {1000 "102"}
+set parms(test103) {100 4294967250 "103"}
+set parms(test107) ""
+set parms(test109) {"109"}
 
 # RPC server executables.  Each of these is tested (if it exists)
 # when running the RPC tests.
 set svc_list { berkeley_db_svc berkeley_db_cxxsvc \
-    berkeley_db_javasvc }
+    berkeley_db_javasvc berkeley_dbje_svc }
 set rpc_svc berkeley_db_svc
 
 # Shell script tests.  Each list entry is a {directory filename} pair,
@@ -191,4 +325,12 @@ set shelltest_list {
 	{ scr020	chk.inc }
 	{ scr021	chk.flags }
 	{ scr022	chk.rr }
+	{ scr023	chk.q }
+	{ scr024	chk.bdb }
+	{ scr025	chk.cxxmulti }
+	{ scr026	chk.method }
+	{ scr027	chk.javas }
+	{ scr028	chk.rtc }
+	{ scr029	chk.get }
+	{ scr030	chk.build }
 }
diff --git a/storage/bdb/test/testutils.tcl b/storage/bdb/test/testutils.tcl
index d1f89dd1e1513bb4958d65a81c4932b55856ddf5..ded9bc5ce7d5eeb019815d6d2262c1972d92c00d 100644
--- a/storage/bdb/test/testutils.tcl
+++ b/storage/bdb/test/testutils.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: testutils.tcl,v 11.165 2002/09/05 17:54:04 sandstro Exp $
+# $Id: testutils.tcl,v 11.198 2004/09/28 15:02:18 carol Exp $
 #
 # Test system utilities
 #
@@ -351,6 +351,17 @@ proc is_substr { str sub } {
 	}
 }
 
+proc is_serial { str } {
+	global serial_tests
+
+	foreach test $serial_tests {
+		if { [is_substr $str $test]  == 1 } {
+			return 1
+		}
+	}
+	return 0
+}
+
 proc release_list { l } {
 
 	# Now release all the locks
@@ -645,12 +656,12 @@ proc watch_procs { pidlist {delay 30} {max 3600} {quiet 0} } {
 			tclsleep $delay
 			incr elapsed $delay
 			# If pids haven't been created in one-tenth
-			# of the time allowed for the whole test, 
+			# of the time allowed for the whole test,
 			# there's a problem.  Report an error and fail.
 			if { $elapsed > [expr {$max / 10}] } {
 				puts "FAIL: begin.pid not created"
 				break
-			}	
+			}
 		}
 	}
 
@@ -1086,73 +1097,13 @@ proc filecheck { file txn } {
 proc cleanup { dir env { quiet 0 } } {
 	global gen_upgrade
 	global is_qnx_test
+	global is_je_test
 	global old_encrypt
 	global passwd
-	global upgrade_dir
-	global upgrade_be
-	global upgrade_method
-	global upgrade_name
 	source ./include.tcl
 
 	if { $gen_upgrade == 1 } {
-		set vers [berkdb version]
-		set maj [lindex $vers 0]
-		set min [lindex $vers 1]
-
-		# Is this machine big or little endian?  We want to mark
-		# the test directories appropriately, since testing
-		# little-endian databases generated by a big-endian machine,
-		# and/or vice versa, is interesting.
-		if { [big_endian] } {
-			set myendianness be
-		} else {
-			set myendianness le
-		}
-
-		if { $upgrade_be == 1 } {
-			set version_dir "$myendianness-$maj.${min}be"
-			set en be
-		} else {
-			set version_dir "$myendianness-$maj.${min}le"
-			set en le
-		}
-
-		set dest $upgrade_dir/$version_dir/$upgrade_method
-		exec mkdir -p $dest
-
-		set dbfiles [glob -nocomplain $dir/*.db]
-		foreach dbfile $dbfiles {
-			set basename [string range $dbfile \
-			    [expr [string length $dir] + 1] end-3]
-
-			set newbasename $upgrade_name-$basename
-
-			# db_dump file
-			error_check_good db_dump($dbfile) \
-			    [catch {exec $util_path/db_dump -k $dbfile > \
-			    $dir/$newbasename.dump}] 0
-
-			# tcl_dump file
-			upgrade_dump $dbfile \
-			    $dir/$newbasename.tcldump
-
-			# Rename dbfile and any dbq files.
-			file rename $dbfile $dir/$newbasename-$en.db
-			foreach dbq \
-			    [glob -nocomplain $dir/__dbq.$basename.db.*] {
-				set s [string length $dir/__dbq.]
-				set newname [string replace $dbq $s \
-				    [expr [string length $basename] + $s - 1] \
-				    $newbasename-$en]
-				file rename $dbq $newname
-			}
-			set cwd [pwd]
-			cd $dir
-			catch {eval exec tar -cvf $dest/$newbasename.tar \
-			    [glob $newbasename* __dbq.$newbasename-$en.db.*]}
-			catch {exec gzip -9v $dest/$newbasename.tar}
-			cd $cwd
-		}
+		save_upgrade_files $dir
 	}
 
 #	check_handles
@@ -1173,7 +1124,8 @@ proc cleanup { dir env { quiet 0 } } {
 			switch -glob -- $fileorig {
 			*/DIR_* -
 			*/__db.* -
-			*/log.*	{
+			*/log.* -
+			*/*.jdb {
 				if { $env != "NULL" } {
 					continue
 				} else {
@@ -1213,18 +1165,24 @@ proc cleanup { dir env { quiet 0 } } {
 				set ret [catch \
 				    {eval {berkdb dbremove} $envargs $encarg \
 				    $file} res]
+				# If dbremove failed and we're not in an env,
+				# note that we don't have 100% certainty
+				# about whether the previous run used
+				# encryption.  Try to remove with crypto if
+				# we tried without, and vice versa.
 				if { $ret != 0 } {
-					# If it failed, there is a chance
-					# that the previous run was using
-					# encryption and we cannot know about
-					# it (different tclsh instantiation).
-					# Try to remove it with crypto.
 					if { $env == "NULL" && \
 					    $old_encrypt == 0} {
 						set ret [catch \
 				    		    {eval {berkdb dbremove} \
 						    -encryptany $passwd \
-				    		    $envargs $file} res]
+				    		    $file} res]
+					}
+					if { $env == "NULL" && \
+					    $old_encrypt == 1 } {
+						set ret [catch \
+						    {eval {berkdb dbremove} \
+						    $file} res]
 					}
 					if { $ret != 0 } {
 						if { $quiet == 0 } {
@@ -1242,13 +1200,43 @@ proc cleanup { dir env { quiet 0 } } {
 			}
 		}
 		if {[llength $remfiles] > 0} {
-			eval fileremove -f $remfiles
+			#
+			# In the HFS file system there are cases where not 
+			# all files are removed on the first attempt.  If 
+			# it fails, try again a few times. 
+			#
+			set count 0
+			while { [catch {eval fileremove -f $remfiles}] == 1 \
+			    && $count < 5 } {
+				incr count
+			}
+		}
+
+		if { $is_je_test } {
+			set rval [catch {eval {exec \
+			    $util_path/db_dump} -h $dir -l } res]
+			if { $rval == 0 } {
+				set envargs " -env $env "
+				if { [is_txnenv $env] } {
+					append envargs " -auto_commit "
+				}
+
+				foreach db $res {
+					set ret [catch {eval \
+					   {berkdb dbremove} $envargs $db } res]
+				}
+			}
 		}
 	}
 }
 
 proc log_cleanup { dir } {
 	source ./include.tcl
+	global gen_upgrade_log
+
+	if { $gen_upgrade_log == 1 } {
+		save_upgrade_files $dir
+	}
 
 	set files [glob -nocomplain $dir/log.*]
 	if { [llength $files] != 0} {
@@ -1288,6 +1276,52 @@ proc env_cleanup { dir } {
 	cleanup $dir NULL
 }
 
+# Start an RPC server.  Don't return to caller until the
+# server is up.  Wait up to $maxwait seconds.
+proc rpc_server_start { { encrypted 0 } { maxwait 30 } { args "" } } {
+	source ./include.tcl
+	global rpc_svc
+	global passwd
+
+	set encargs ""
+	if { $encrypted == 1 } {
+		set encargs " -P $passwd "
+	}
+
+	if { [string compare $rpc_server "localhost"] == 0 } {
+		set dpid [eval {exec $util_path/$rpc_svc \
+		    -h $rpc_testdir} $args $encargs &]
+	} else {
+		set dpid [eval {exec rsh $rpc_server \
+		    $rpc_path/$rpc_svc -h $rpc_testdir $args} &]
+	}
+
+	# Wait a couple of seconds before we start looking for
+	# the server.
+	tclsleep 2
+	set home [file tail $rpc_testdir]
+	if { $encrypted == 1 } {
+		set encargs " -encryptaes $passwd "
+	}
+	for { set i 0 } { $i < $maxwait } { incr i } {
+		# Try an operation -- while it fails with NOSERVER, sleep for
+		# a second and retry.
+		if {[catch {berkdb envremove -force -home "$home.FAIL" \
+		    -server $rpc_server} res] && \
+		    [is_substr $res DB_NOSERVER:]} {
+			tclsleep 1
+		} else {
+			# Server is up, clean up and return to caller
+			break
+		}
+		if { $i >= $maxwait } {
+			puts "FAIL: RPC server\
+			    not started after $maxwait seconds"
+		}
+	}
+	return $dpid
+}
+
 proc remote_cleanup { server dir localdir } {
 	set home [file tail $dir]
 	error_check_good cleanup:remove [berkdb envremove -home $home \
@@ -1773,11 +1807,15 @@ proc reset_env { env } {
 	error_check_good env_close [$env close] 0
 }
 
-proc minlocks { myenv locker_id obj_id num } {
+proc maxlocks { myenv locker_id obj_id num } {
 	return [countlocks $myenv $locker_id $obj_id $num ]
 }
 
-proc maxlocks { myenv locker_id obj_id num } {
+proc maxwrites { myenv locker_id obj_id num } {
+	return [countlocks $myenv $locker_id $obj_id $num ]
+}
+
+proc minlocks { myenv locker_id obj_id num } {
 	return [countlocks $myenv $locker_id $obj_id $num ]
 }
 
@@ -1799,7 +1837,8 @@ proc countlocks { myenv locker_id obj_id num } {
 		}
 	}
 
-	# Now acquire a write lock
+	# Now acquire one write lock, except for obj_id 1, which doesn't
+	# acquire any.  We'll use obj_id 1 to test minwrites.
 	if { $obj_id != 1 } {
 		set r [catch {$myenv lock_get write $locker_id \
 		    [expr $obj_id * 1000 + 10]} l ]
@@ -1812,6 +1851,21 @@ proc countlocks { myenv locker_id obj_id num } {
 		}
 	}
 
+	# Get one extra write lock for obj_id 2.  We'll use
+	# obj_id 2 to test maxwrites.
+	#
+	if { $obj_id == 2 } {
+		set extra [catch {$myenv lock_get write \
+		    $locker_id [expr $obj_id * 1000 + 11]} l ]
+		if { $extra != 0 } {
+			puts $l
+			return ERROR
+		} else {
+			error_check_good lockget:$obj_id [is_substr $l $myenv] 1
+			lappend locklist $l
+		}
+	}
+
 	set ret [ring $myenv $locker_id $obj_id $num]
 
 	foreach l $locklist {
@@ -1845,8 +1899,12 @@ proc ring { myenv locker_id obj_id num } {
 		if {[string match "*DEADLOCK*" $lock2] == 1} {
 			set ret DEADLOCK
 		} else {
-			puts $lock2
-			set ret ERROR
+			if {[string match "*NOTGRANTED*" $lock2] == 1} {
+				set ret DEADLOCK
+			} else {
+				puts $lock2
+				set ret ERROR
+			}
 		}
 	} else {
 		error_check_good lockget:$obj_id [is_substr $lock2 $myenv] 1
@@ -1888,7 +1946,12 @@ proc clump { myenv locker_id obj_id num } {
 		if {[string match "*DEADLOCK*" $lock2] == 1} {
 			set ret DEADLOCK
 		} else {
-			set ret ERROR
+			if {[string match "*NOTGRANTED*" $lock2] == 1} {
+				set ret DEADLOCK
+			} else {
+				puts $lock2
+				set ret ERROR
+			}
 		}
 	} else {
 		error_check_good \
@@ -1904,13 +1967,14 @@ proc clump { myenv locker_id obj_id num } {
 		error_check_good lockput:$lock2 [$lock2 put] 0
 	}
 	return $ret
- }
+}
 
 proc dead_check { t procs timeout dead clean other } {
 	error_check_good $t:$procs:other $other 0
 	switch $t {
 		ring {
-			# with timeouts the number of deadlocks is unpredictable
+			# With timeouts the number of deadlocks is
+			# unpredictable: test for at least one deadlock.
 			if { $timeout != 0 && $dead > 1 } {
 				set clean [ expr $clean + $dead - 1]
 				set dead 1
@@ -1920,6 +1984,13 @@ proc dead_check { t procs timeout dead clean other } {
 			    [expr $procs - 1]
 		}
 		clump {
+			# With timeouts the number of deadlocks is
+			# unpredictable: test for no more than one
+			# successful lock.
+			if { $timeout != 0 && $dead == $procs } {
+				set clean 1
+				set dead [expr $procs - 1]
+			}
 			error_check_good $t:$procs:deadlocks $dead \
 			    [expr $procs - 1]
 			error_check_good $t:$procs:success $clean 1
@@ -1929,12 +2000,17 @@ proc dead_check { t procs timeout dead clean other } {
 			error_check_good $t:$procs:success $clean \
 			    [expr $procs - 1]
 		}
-		minlocks {
+		maxlocks {
 			error_check_good $t:$procs:deadlocks $dead 1
 			error_check_good $t:$procs:success $clean \
 			    [expr $procs - 1]
 		}
-		maxlocks {
+		maxwrites {
+			error_check_good $t:$procs:deadlocks $dead 1
+			error_check_good $t:$procs:success $clean \
+			    [expr $procs - 1]
+		}
+		minlocks {
 			error_check_good $t:$procs:deadlocks $dead 1
 			error_check_good $t:$procs:success $clean \
 			    [expr $procs - 1]
@@ -2060,6 +2136,10 @@ proc is_valid_locker {l } {
 	return [is_valid_widget $l ""]
 }
 
+proc is_valid_seq { seq } {
+	return [is_valid_widget $seq seq]
+}
+
 proc send_cmd { fd cmd {sleep 2}} {
 	source ./include.tcl
 
@@ -2139,26 +2219,18 @@ proc pad_data {method data} {
 
 proc make_fixed_length {method data {pad 0}} {
 	global fixed_len
-	global fixed_pad
 
 	if {[is_fixed_length $method] == 1} {
 		if {[string length $data] > $fixed_len } {
 		    error_check_bad make_fixed_len:TOO_LONG 1 1
 		}
 		while { [string length $data] < $fixed_len } {
-			set data [format $data%c $fixed_pad]
+			set data [format $data%c $pad]
 		}
 	}
 	return $data
 }
 
-proc make_gid {data} {
-	while { [string length $data] < 127 } {
-		set data [format ${data}0]
-	}
-	return $data
-}
-
 proc make_gid {data} {
 	while { [string length $data] < 128 } {
 		set data [format ${data}0]
@@ -2200,6 +2272,21 @@ proc binary_compare { data1 data2 } {
 	}
 }
 
+# This is a comparison function used with the lsort command.
+# It treats its inputs as 32 bit signed integers for comparison,
+# and is coded to work with both 32 bit and 64 bit versions of tclsh.
+proc int32_compare { val1 val2 } {
+        # Big is set to 2^32 on a 64 bit machine, or 0 on 32 bit machine.
+        set big [expr 0xffffffff + 1]
+        if { $val1 >= 0x80000000 } {
+                set val1 [expr $val1 - $big]
+        }
+        if { $val2 >= 0x80000000 } {
+                set val2 [expr $val2 - $big]
+        }
+        return [expr $val1 - $val2]
+}
+
 proc convert_method { method } {
 	switch -- $method {
 		-btree -
@@ -2236,7 +2323,14 @@ proc convert_method { method } {
 		db_queue -
 		q -
 		qam -
-		queue { return "-queue" }
+		queue -
+		-iqueue -
+		DB_IQUEUE -
+		IQUEUE -
+		db_iqueue -
+		iq -
+		iqam -
+		iqueue { return "-queue" }
 
 		-queueextent -
 		QUEUEEXTENT -
@@ -2244,7 +2338,14 @@ proc convert_method { method } {
 		qamext -
 		-queueext -
 		queueextent -
-		queueext { return "-queue" }
+		queueext -
+		-iqueueextent -
+		IQUEUEEXTENT -
+		iqe -
+		iqamext -
+		-iqueueext -
+		iqueueextent -
+		iqueueext { return "-queue" }
 
 		-frecno -
 		-recno -
@@ -2300,7 +2401,6 @@ proc convert_encrypt { largs } {
 # -flags argument.
 proc convert_args { method {largs ""} } {
 	global fixed_len
-	global fixed_pad
 	global gen_upgrade
 	global upgrade_be
 	source ./include.tcl
@@ -2336,9 +2436,15 @@ proc convert_args { method {largs ""} } {
 		append largs " -dup "
 		append largs " -dupsort "
 	} elseif { [is_queueext $method] == 1 } {
-		append largs " -extent 2 "
+		append largs " -extent 4 "
 	}
 
+	if { [is_iqueue $method] == 1 || [is_iqueueext $method] == 1 } {
+		append largs " -inorder "
+	}
+
+	# Default padding character is ASCII nul.
+	set fixed_pad 0
 	if {[is_fixed_length $method] == 1} {
 		append largs " -len $fixed_len -pad $fixed_pad "
 	}
@@ -2436,7 +2542,8 @@ proc is_ddhash { method } {
 }
 
 proc is_queue { method } {
-	if { [is_queueext $method] == 1 } {
+	if { [is_queueext $method] == 1 || [is_iqueue $method] == 1 || \
+	    [is_iqueueext $method] == 1 } {
 		return 1
 	}
 
@@ -2449,6 +2556,10 @@ proc is_queue { method } {
 }
 
 proc is_queueext { method } {
+	if { [is_iqueueext $method] == 1 } {
+		return 1
+	}
+
 	set names { -queueextent queueextent QUEUEEXTENT qe qamext \
 	    queueext -queueext }
 	if { [lsearch $names $method] >= 0 } {
@@ -2458,6 +2569,29 @@ proc is_queueext { method } {
 	}
 }
 
+proc is_iqueue { method } {
+	if { [is_iqueueext $method] == 1 } {
+		return 1
+	}
+
+	set names { -iqueue DB_IQUEUE IQUEUE db_iqueue iq iqueue iqam }
+	if { [lsearch $names $method] >= 0 } {
+		return 1
+	} else {
+		return 0
+	}
+}
+
+proc is_iqueueext { method } {
+	set names { -iqueueextent iqueueextent IQUEUEEXTENT iqe iqamext \
+	    iqueueext -iqueueext }
+	if { [lsearch $names $method] >= 0 } {
+		return 1
+	} else {
+		return 0
+	}
+}
+
 proc is_record_based { method } {
 	if { [is_recno $method] || [is_frecno $method] ||
 	    [is_rrecno $method] || [is_queue $method] } {
@@ -2546,6 +2680,7 @@ proc fileremove { args } {
 }
 
 proc findfail { args } {
+	set errstring {}
 	foreach a $args {
 		if { [file exists $a] == 0 } {
 			continue
@@ -2553,13 +2688,12 @@ proc findfail { args } {
 		set f [open $a r]
 		while { [gets $f line] >= 0 } {
 			if { [string first FAIL $line] == 0 } {
-				close $f
-				return 1
+				lappend errstring $a:$line
 			}
 		}
 		close $f
 	}
-	return 0
+	return $errstring
 }
 
 # Sleep for s seconds.
@@ -2635,8 +2769,8 @@ proc fileextract { superset subset outfile } {
 }
 
 # Verify all .db files in the specified directory.
-proc verify_dir { {directory $testdir} \
-    { pref "" } { noredo 0 } { quiet 0 } { nodump 0 } { cachesize 0 } } {
+proc verify_dir { {directory $testdir} { pref "" } \
+    { noredo 0 } { quiet 0 } { nodump 0 } { cachesize 0 } { unref 1 } } {
 	global encrypt
 	global passwd
 
@@ -2650,7 +2784,7 @@ proc verify_dir { {directory $testdir} \
 			if { $quiet == 0 } {
 				puts "Skipping verification."
 			}
-			return
+			return 0
 		}
 		set f [open $directory/NOREVERIFY w]
 		close $f
@@ -2658,13 +2792,9 @@ proc verify_dir { {directory $testdir} \
 
 	if { [catch {glob $directory/*.db} dbs] != 0 } {
 		# No files matched
-		return
-	}
-	if { [file exists /dev/stderr] == 1 } {
-		set errfilearg "-errfile /dev/stderr "
-	} else {
-		set errfilearg ""
+		return 0
 	}
+	set errfilearg "-errfile /dev/stderr "
 	set errpfxarg {-errpfx "FAIL: verify" }
 	set errarg $errfilearg$errpfxarg
 	set ret 0
@@ -2684,8 +2814,19 @@ proc verify_dir { {directory $testdir} \
 	    {-cachesize [list 0 $cachesize 0]}]
 	set earg " -env $env $errarg "
 
+	# The 'unref' flag means that we report unreferenced pages
+	# at all times.  This is the default behavior.
+	# If we have a test which leaves unreferenced pages on systems
+	# where HAVE_FTRUNCATE is not on, then we call verify_dir with
+	# unref == 0.
+	set uflag "-unref"
+	if { $unref == 0 } {
+		set uflag ""
+	}
+
 	foreach db $dbs {
-		if { [catch {eval {berkdb dbverify} $earg $db} res] != 0 } {
+		if { [catch \
+		    {eval {berkdb dbverify} $uflag $earg $db} res] != 0 } {
 			puts $res
 			puts "FAIL:[timestamp] Verification of $db failed."
 			set ret 1
@@ -2735,108 +2876,101 @@ proc check_for_subdbs { db } {
 	return 0
 }
 
-proc dumploadtest { db {subdb ""} } {
+proc db_compare { olddb newdb olddbname newdbname } {
+	# Walk through olddb and newdb and make sure their contents
+	# are identical.
+	set oc [$olddb cursor]
+	set nc [$newdb cursor]
+	error_check_good orig_cursor($olddbname) \
+	    [is_valid_cursor $oc $olddb] TRUE
+	error_check_good new_cursor($olddbname) \
+	    [is_valid_cursor $nc $newdb] TRUE
+
+	for { set odbt [$oc get -first] } { [llength $odbt] > 0 } \
+	    { set odbt [$oc get -next] } {
+		set ndbt [$nc get -get_both \
+		    [lindex [lindex $odbt 0] 0] [lindex [lindex $odbt 0] 1]]
+		error_check_good db_compare($olddbname/$newdbname) $ndbt $odbt
+	}
+
+	for { set ndbt [$nc get -first] } { [llength $ndbt] > 0 } \
+	    { set ndbt [$nc get -next] } {
+		set odbt [$oc get -get_both \
+		    [lindex [lindex $ndbt 0] 0] [lindex [lindex $ndbt 0] 1]]
+		error_check_good db_compare_back($olddbname) $odbt $ndbt
+	}
+
+	error_check_good orig_cursor_close($olddbname) [$oc close] 0
+	error_check_good new_cursor_close($newdbname) [$nc close] 0
+
+	return 0
+}
+
+proc dumploadtest { db } {
 	global util_path
 	global encrypt
 	global passwd
 
 	set newdbname $db-dumpload.db
 
-	# Open original database, or subdb if we have one.
 	set dbarg ""
 	set utilflag ""
 	if { $encrypt != 0 } {
 		set dbarg "-encryptany $passwd"
 		set utilflag "-P $passwd"
 	}
-	set max_size [expr 15 * 1024]
-	if { [string length $subdb] == 0 } {
-		set olddb [eval {berkdb_open -rdonly} $dbarg $db]
-		error_check_good olddb($db) [is_valid_db $olddb] TRUE
-
-		if { [check_for_subdbs $olddb] } {
-			# If $db has subdatabases, dumploadtest each one
-			# separately.
-			set oc [$olddb cursor]
-			error_check_good orig_cursor($db) \
-	    		    [is_valid_cursor $oc $olddb] TRUE
-
-			for { set dbt [$oc get -first] } \
-			    { [llength $dbt] > 0 } \
-			    { set dbt [$oc get -next] } {
-				set subdb [lindex [lindex $dbt 0] 0]
-
-            	   		# Skip any files over this size. The problem is
-            	   		# that when when we dump/load it, files that are
-            	   		# too big result in E2BIG errors because the
-            	   		# arguments to db_dump are too long.  64K seems
-            	   		# to be the limit (on FreeBSD), cut it to 32K
-            	   		# just to be safe.
-				if {[string length $subdb] < $max_size && \
-				    [string length $subdb] != 0} {
-					dumploadtest $db $subdb
-				}
-			}
-			error_check_good oldcclose [$oc close] 0
-			error_check_good olddbclose [$olddb close] 0
-			return 0
-		}
-		# No subdatabase
-		set have_subdb 0
-	} else {
-		set olddb [eval {berkdb_open -rdonly} $dbarg {$db $subdb}]
-		error_check_good olddb($db) [is_valid_db $olddb] TRUE
 
-		set have_subdb 1
-	}
+	# Dump/load the whole file, including all subdbs.
+	set rval [catch {eval {exec $util_path/db_dump} $utilflag -k \
+	    $db | $util_path/db_load $utilflag $newdbname} res]
+	error_check_good db_dump/db_load($db:$res) $rval 0
 
-	# Do a db_dump test.  Dump/load each file.
-	if { $have_subdb } {
-		set rval [catch {eval {exec $util_path/db_dump} $utilflag -k \
-		    -s {$subdb} $db | \
-		    $util_path/db_load $utilflag $newdbname} res]
-	} else {
-		set rval [catch {eval {exec $util_path/db_dump} $utilflag -k \
-		    $db | $util_path/db_load $utilflag $newdbname} res]
+	# If the old file was empty, there's no new file and we're done.
+	if { [file exists $newdbname] == 0 } {
+		return 0
 	}
-	error_check_good db_dump/db_load($db:$res) $rval 0
 
-	# Now open new database.
-	set newdb [eval {berkdb_open -rdonly} $dbarg $newdbname]
-	error_check_good newdb($db) [is_valid_db $newdb] TRUE
+	# Open original database.
+	set olddb [eval {berkdb_open -rdonly} $dbarg $db]
+	error_check_good olddb($db) [is_valid_db $olddb] TRUE
 
-	# Walk through olddb and newdb and make sure their contents
-	# are identical.
-	set oc [$olddb cursor]
-	set nc [$newdb cursor]
-	error_check_good orig_cursor($db) \
-	    [is_valid_cursor $oc $olddb] TRUE
-	error_check_good new_cursor($db) \
-	    [is_valid_cursor $nc $newdb] TRUE
+	if { [check_for_subdbs $olddb] } {
+		# If $db has subdatabases, compare each one separately.
+		set oc [$olddb cursor]
+		error_check_good orig_cursor($db) \
+    		    [is_valid_cursor $oc $olddb] TRUE
 
-	for { set odbt [$oc get -first] } { [llength $odbt] > 0 } \
-	    { set odbt [$oc get -next] } {
-		set ndbt [$nc get -get_both \
-		    [lindex [lindex $odbt 0] 0] [lindex [lindex $odbt 0] 1]]
-		error_check_good db_compare($db/$newdbname) $ndbt $odbt
-	}
+		for { set dbt [$oc get -first] } \
+		    { [llength $dbt] > 0 } \
+		    { set dbt [$oc get -next] } {
+			set subdb [lindex [lindex $dbt 0] 0]
 
-	for { set ndbt [$nc get -first] } { [llength $ndbt] > 0 } \
-	    { set ndbt [$nc get -next] } {
-		set odbt [$oc get -get_both \
-		    [lindex [lindex $ndbt 0] 0] [lindex [lindex $ndbt 0] 1]]
-		error_check_good db_compare_back($db) $odbt $ndbt
-	}
+			set oldsubdb \
+			    [eval {berkdb_open -rdonly} $dbarg {$db $subdb}]
+			error_check_good olddb($db) [is_valid_db $oldsubdb] TRUE
 
-	error_check_good orig_cursor_close($db) [$oc close] 0
-	error_check_good new_cursor_close($db) [$nc close] 0
+			# Open the new database.
+			set newdb \
+			    [eval {berkdb_open -rdonly} $dbarg {$newdbname $subdb}]
+			error_check_good newdb($db) [is_valid_db $newdb] TRUE
 
-	error_check_good orig_db_close($db) [$olddb close] 0
-	error_check_good new_db_close($db) [$newdb close] 0
+			db_compare $oldsubdb $newdb $db $newdbname
+			error_check_good new_db_close($db) [$newdb close] 0
+			error_check_good old_subdb_close($oldsubdb) [$oldsubdb close] 0
+		}
 
-	eval berkdb dbremove $dbarg $newdbname
+		error_check_good oldcclose [$oc close] 0
+	} else {
+		# Open the new database.
+		set newdb [eval {berkdb_open -rdonly} $dbarg $newdbname]
+		error_check_good newdb($db) [is_valid_db $newdb] TRUE
 
-	return 0
+		db_compare $olddb $newdb $db $newdbname
+		error_check_good new_db_close($db) [$newdb close] 0
+	}
+
+	error_check_good orig_db_close($db) [$olddb close] 0
+	eval berkdb dbremove $dbarg $newdbname
 }
 
 # Generate randomly ordered, guaranteed-unique four-character strings that can
@@ -2952,7 +3086,7 @@ proc berkdb_open { args } {
 	}
 
 	set errargs {}
-	if { $is_envmethod == 0 && [file exists /dev/stderr] == 1 } {
+	if { $is_envmethod == 0 } {
 		append errargs " -errfile /dev/stderr "
 		append errargs " -errpfx \\F\\A\\I\\L"
 	}
@@ -2975,7 +3109,7 @@ proc berkdb_env { args } {
 	}
 
 	set errargs {}
-	if { $is_envmethod == 0 && [file exists /dev/stderr] == 1 } {
+	if { $is_envmethod == 0 } {
 		append errargs " -errfile /dev/stderr "
 		append errargs " -errpfx \\F\\A\\I\\L"
 	}
@@ -3081,21 +3215,42 @@ proc get_pagesize { stat } {
 proc get_file_list { {small 0} } {
 	global is_windows_test
 	global is_qnx_test
+	global is_je_test
 	global src_root
 
-	if { $is_qnx_test } {
+	# Skip libraries if we have a debug build.
+	if { $is_qnx_test || $is_je_test || [is_debug] == 1 } {
 		set small 1
 	}
+
 	if { $small && $is_windows_test } {
-		return [glob $src_root/*/*.c */env*.obj]
+		set templist [glob $src_root/*/*.c */env*.obj]
 	} elseif { $small } {
-		return [glob $src_root/*/*.c ./env*.o]
+		set templist [glob $src_root/*/*.c ./env*.o]
 	} elseif { $is_windows_test } {
-		return \
+		set templist \
 		    [glob $src_root/*/*.c */*.obj */libdb??.dll */libdb??d.dll]
 	} else {
-		return [glob $src_root/*/*.c ./*.o ./.libs/libdb-?.?.s?]
+		set templist [glob $src_root/*/*.c ./*.o ./.libs/libdb-?.?.s?]
 	}
+
+	# We don't want a huge number of files, but we do want a nice
+	# variety.  If there are more than 200 files, pick out a list
+	# by taking every other, or every third, or every nth file.
+	set filelist {}
+	set nfiles 200
+	if { [llength $templist] > $nfiles } {
+		set skip \
+		    [expr [llength $templist] / [expr [expr $nfiles / 3] * 2]]
+		set i $skip
+		while { $i < [llength $templist] } {
+			lappend filelist [lindex $templist $i]
+			incr i $skip
+		}
+	} else {
+		set filelist $templist
+	}
+	return $filelist
 }
 
 proc is_cdbenv { env } {
@@ -3134,6 +3289,15 @@ proc is_mpoolenv { env } {
 	}
 }
 
+proc is_repenv { env } {
+	set sys [$env attributes]
+	if { [lsearch $sys -rep] != -1 } {
+		return 1
+	} else {
+		return 0
+	}
+}
+
 proc is_rpcenv { env } {
 	set sys [$env attributes]
 	if { [lsearch $sys -rpc] != -1 } {
@@ -3196,6 +3360,14 @@ proc getstats { statlist field } {
 	return -1
 }
 
+# Return the value for a particular field in a set of statistics.
+# Works for regular db stat as well as env stats (log_stat,
+# lock_stat, txn_stat, rep_stat, etc.).
+proc stat_field { handle which_stat field } {
+	set stat [$handle $which_stat]
+	return [getstats $stat $field ]
+}
+
 proc big_endian { } {
 	global tcl_platform
 	set e $tcl_platform(byteOrder)
@@ -3207,3 +3379,80 @@ proc big_endian { } {
 		error "FAIL: Unknown endianness $e"
 	}
 }
+
+# Search logs to find if we have debug records.
+proc log_has_debug_records { dir } {
+	source ./include.tcl
+	global encrypt
+
+	set tmpfile $dir/printlog.out
+	set stat [catch \
+	    {exec $util_path/db_printlog -h $dir > $tmpfile} ret]
+	error_check_good db_printlog $stat 0
+
+	set f [open $tmpfile r]
+	while { [gets $f record] >= 0 } {
+		set r [regexp {\[[^\]]*\]\[[^\]]*\]([^\:]*)\:} $record whl name]
+		if { $r == 1 && [string match *_debug $name] != 1 } {
+			close $f
+			fileremove $tmpfile
+			return 1
+		}
+	}
+	close $f
+	fileremove $tmpfile
+	return 0
+}
+
+# Set up a temporary database to check if this is a debug build.
+proc is_debug { } {
+	source ./include.tcl
+
+	set tempdir $testdir/temp
+	file mkdir $tempdir
+	set env [berkdb_env -create -log -home $testdir/temp]
+	error_check_good temp_env_open [is_valid_env $env] TRUE
+
+	set file temp.db
+	set db [berkdb_open -create -env $env -btree $file]
+	error_check_good temp_db_open [is_valid_db $db] TRUE
+
+	set key KEY
+	set data DATA
+	error_check_good temp_db_put [$db put $key $data] 0
+	set ret [$db get $key]
+	error_check_good get_key [lindex [lindex $ret 0] 0] $key
+	error_check_good get_data [lindex [lindex $ret 0] 1] $data
+	error_check_good temp_db_close [$db close] 0
+	error_check_good temp_db_remove [$env dbremove $file] 0
+	error_check_good temp_env_close [$env close] 0
+
+	if { [log_has_debug_records $tempdir] == 1 } {
+		return 1
+	}
+	return 0
+}
+
+proc adjust_logargs { logtype } {
+	if { $logtype == "in-memory" } {
+		set lbuf [expr 8 * [expr 1024 * 1024]]
+		set logargs " -log_inmemory -log_buffer $lbuf "
+	} elseif { $logtype == "on-disk" } {
+		set logargs ""
+	} else {
+		puts "FAIL: unrecognized log type $logtype"
+	}
+	return $logargs
+}
+
+proc adjust_txnargs { logtype } {
+	if { $logtype == "in-memory" } {
+		set txnargs " -txn "
+	} elseif { $logtype == "on-disk" } {
+		set txnargs " -txn nosync "
+	} else {
+		puts "FAIL: unrecognized log type $logtype"
+	}
+	return $txnargs
+}
+
diff --git a/storage/bdb/test/txn001.tcl b/storage/bdb/test/txn001.tcl
index 406ef35751c3bfaee899cf21de8f5c5b174d5910..583b7f212402dc8f3dae050933dad9298b9e2b0a 100644
--- a/storage/bdb/test/txn001.tcl
+++ b/storage/bdb/test/txn001.tcl
@@ -1,21 +1,21 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: txn001.tcl,v 11.35 2002/05/10 17:44:28 sue Exp $
+# $Id: txn001.tcl,v 11.38 2004/01/28 03:36:32 bostic Exp $
 #
 
 # TEST	txn001
 # TEST	Begin, commit, abort testing.
-proc txn001 { {tnum "01"} { max 1024 } { ntxns 50 } } {
+proc txn001 { {tnum "001"} { max 1024 } { ntxns 50 } } {
 	source ./include.tcl
 	global txn_curid
 	global txn_maxid
 
-	puts -nonewline "Txn0$tnum: Basic begin, commit, abort"
+	puts -nonewline "Txn$tnum: Basic begin, commit, abort"
 
-	if { $tnum != "01"} {
+	if { $tnum != "001"} {
 		puts " (with ID wrap)"
 	} else {
 		puts ""
@@ -42,7 +42,7 @@ proc txn001_suba { ntxns env tnum } {
 	# We will create a bunch of transactions and commit them.
 	set txn_list {}
 	set tid_list {}
-	puts "\tTxn0$tnum.a: Beginning/Committing $ntxns Transactions in $env"
+	puts "\tTxn$tnum.a: Beginning/Committing $ntxns Transactions in $env"
 	for { set i 0 } { $i < $ntxns } { incr i } {
 		set txn [$env txn]
 		error_check_good txn_begin [is_valid_txn $txn $env] TRUE
@@ -65,7 +65,7 @@ proc txn001_subb { ntxns env tnum } {
 	# We will create a bunch of transactions and abort them.
 	set txn_list {}
 	set tid_list {}
-	puts "\tTxn0$tnum.b: Beginning/Aborting Transactions"
+	puts "\tTxn$tnum.b: Beginning/Aborting Transactions"
 	for { set i 0 } { $i < $ntxns } { incr i } {
 		set txn [$env txn]
 		error_check_good txn_begin [is_valid_txn $txn $env] TRUE
@@ -88,7 +88,7 @@ proc txn001_subc { ntxns env tnum } {
 	# We will create a bunch of transactions and commit them.
 	set txn_list {}
 	set tid_list {}
-	puts "\tTxn0$tnum.c: Beginning/Prepare/Committing Transactions"
+	puts "\tTxn$tnum.c: Beginning/Prepare/Committing Transactions"
 	for { set i 0 } { $i < $ntxns } { incr i } {
 		set txn [$env txn]
 		error_check_good txn_begin [is_valid_txn $txn $env] TRUE
diff --git a/storage/bdb/test/txn002.tcl b/storage/bdb/test/txn002.tcl
index 5107472644d8cd8710be80f58f73ea10400fc6a3..1ecbf9df9df899c4e9ff8ed7754b9b1bbab49e49 100644
--- a/storage/bdb/test/txn002.tcl
+++ b/storage/bdb/test/txn002.tcl
@@ -1,21 +1,21 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: txn002.tcl,v 11.38 2002/05/10 17:44:29 sue Exp $
+# $Id: txn002.tcl,v 11.41 2004/01/28 03:36:32 bostic Exp $
 #
 
 # TEST	txn002
 # TEST	Verify that  read-only transactions do not write log records.
-proc txn002 { {tnum "02" } { max 1024 } { ntxns 50 } } {
+proc txn002 { {tnum "002" } { max 1024 } { ntxns 50 } } {
 	source ./include.tcl
 	global txn_curid
 	global txn_maxid
 
-	puts -nonewline "Txn0$tnum: Read-only transaction test ($max) ($ntxns)"
+	puts -nonewline "Txn$tnum: Read-only transaction test ($max) ($ntxns)"
 
-	if { $tnum != "02" } {
+	if { $tnum != "002" } {
 		puts " (with ID wrap)"
 	} else {
 		puts ""
@@ -34,7 +34,7 @@ proc txn002 { {tnum "02" } { max 1024 } { ntxns 50 } } {
 	# We will create a bunch of transactions and commit them.
 	set txn_list {}
 	set tid_list {}
-	puts "\tTxn0$tnum.a: Beginning/Committing Transactions"
+	puts "\tTxn$tnum.a: Beginning/Committing Transactions"
 	for { set i 0 } { $i < $ntxns } { incr i } {
 		set txn [$env txn]
 		error_check_good txn_begin [is_valid_txn $txn $env] TRUE
diff --git a/storage/bdb/test/txn003.tcl b/storage/bdb/test/txn003.tcl
index 71e450cf9ce7024ecbbc7f2df224b848664ff0d5..e6a6d6d14b6453db98cbd03c11f5476278ef6641 100644
--- a/storage/bdb/test/txn003.tcl
+++ b/storage/bdb/test/txn003.tcl
@@ -1,21 +1,21 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: txn003.tcl,v 11.40 2002/09/05 17:23:08 sandstro Exp $
+# $Id: txn003.tcl,v 11.43 2004/01/28 03:36:33 bostic Exp $
 #
 
 # TEST	txn003
 # TEST	Test abort/commit/prepare of txns with outstanding child txns.
-proc txn003 { {tnum "03"} } {
+proc txn003 { {tnum "003"} } {
 	source ./include.tcl
 	global txn_curid
 	global txn_maxid
 
-	puts -nonewline "Txn0$tnum: Outstanding child transaction test"
+	puts -nonewline "Txn$tnum: Outstanding child transaction test"
 
-	if { $tnum != "03" } {
+	if { $tnum != "003" } {
 		puts " (with ID wrap)"
 	} else {
 		puts ""
@@ -49,7 +49,7 @@ proc txn003 { {tnum "03"} } {
 
 	txn003_check $db $key "Origdata" $origdata
 
-	puts "\tTxn0$tnum.a: Parent abort"
+	puts "\tTxn$tnum.a: Parent abort"
 	set parent [$env txn]
 	error_check_good txn_begin [is_valid_txn $parent $env] TRUE
 	set child [$env txn -parent $parent]
@@ -62,7 +62,7 @@ proc txn003 { {tnum "03"} } {
 	error_check_good child_handle $stat 1
 	error_check_good child_h2 [is_substr $ret "invalid command name"] 1
 
-	puts "\tTxn0$tnum.b: Parent commit"
+	puts "\tTxn$tnum.b: Parent commit"
 	set parent [$env txn]
 	error_check_good txn_begin [is_valid_txn $parent $env] TRUE
 	set child [$env txn -parent $parent]
@@ -81,7 +81,7 @@ proc txn003 { {tnum "03"} } {
 	# Since the data check assumes what has come before, the 'commit'
 	# operation must be last.
 	#
-	set hdr "\tTxn0$tnum"
+	set hdr "\tTxn$tnum"
 	set rlist {
 		{begin		".c"}
 		{prepare	".d"}
@@ -131,7 +131,7 @@ proc txn003 { {tnum "03"} } {
 		puts "Skipping remainder of test for Windows"
 		return
 	}
-	puts "\tTxn0$tnum.g: Attempt child prepare"
+	puts "\tTxn$tnum.g: Attempt child prepare"
 	set env [eval $env_cmd]
 	error_check_good dbenv [is_valid_env $env] TRUE
 	berkdb debug_check
@@ -148,7 +148,7 @@ proc txn003 { {tnum "03"} } {
 	error_check_good child_prepare $stat 1
 	error_check_good child_prep_err [is_substr $ret "txn prepare"] 1
 
-	puts "\tTxn0$tnum.h: Attempt child discard"
+	puts "\tTxn$tnum.h: Attempt child discard"
 	set stat [catch {$child discard} ret]
 	error_check_good child_discard $stat 1
 
diff --git a/storage/bdb/test/txn004.tcl b/storage/bdb/test/txn004.tcl
index 75e1b40043fb7fdb8ace15ec2d77ea9f8cce301f..c7accddd9b5ef368303a533184e245f9916ff111 100644
--- a/storage/bdb/test/txn004.tcl
+++ b/storage/bdb/test/txn004.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: txn004.tcl,v 11.39 2002/05/15 17:14:06 sandstro Exp $
+# $Id: txn004.tcl,v 11.42 2004/01/28 03:36:33 bostic Exp $
 #
 
 # TEST	txn004
@@ -17,11 +17,11 @@ proc txn004 { } {
 	set orig_maxid $txn_maxid
 	puts "\tTxn004.1: wraparound txnids"
 	set txn_curid [expr $txn_maxid - 2]
-	txn001 "04.1"
+	txn001 "004.1"
 	puts "\tTxn004.2: closer wraparound txnids"
 	set txn_curid [expr $txn_maxid - 3]
 	set txn_maxid [expr $txn_maxid - 2]
-	txn001 "04.2"
+	txn001 "004.2"
 
 	puts "\tTxn004.3: test wraparound txnids"
 	txn_idwrap_check $testdir
diff --git a/storage/bdb/test/txn005.tcl b/storage/bdb/test/txn005.tcl
index 604f3ad7de4aab4178972dbcb62d84d8ccd425f9..e22581cd12912652616cc94b8f6fa65c7584d162 100644
--- a/storage/bdb/test/txn005.tcl
+++ b/storage/bdb/test/txn005.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: txn005.tcl,v 11.35 2002/08/08 15:38:14 bostic Exp $
+# $Id: txn005.tcl,v 11.37 2004/01/28 03:36:33 bostic Exp $
 #
 
 # TEST	txn005
diff --git a/storage/bdb/test/txn006.tcl b/storage/bdb/test/txn006.tcl
index 7bf37d34dfcbc07cba3d2b4a9a941286bf94e1b9..14ada718e585855e2b0d4d2bd6f865d4cda72791 100644
--- a/storage/bdb/test/txn006.tcl
+++ b/storage/bdb/test/txn006.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: txn006.tcl,v 1.5 2002/08/01 19:59:19 sue Exp $
+# $Id: txn006.tcl,v 1.7 2004/01/28 03:36:33 bostic Exp $
 #
 #
 #TEST	txn006
diff --git a/storage/bdb/test/txn007.tcl b/storage/bdb/test/txn007.tcl
index f67dc209f921fe8109d88743463fc99cab22bfb2..2ef382b9714ada77e983861009f3fa4090ca940e 100644
--- a/storage/bdb/test/txn007.tcl
+++ b/storage/bdb/test/txn007.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: txn007.tcl,v 11.3 2002/08/08 15:38:14 bostic Exp $
+# $Id: txn007.tcl,v 11.5 2004/01/28 03:36:33 bostic Exp $
 #
 #TEST	txn007
 #TEST	Test of DB_TXN_WRITE_NOSYNC
diff --git a/storage/bdb/test/txn008.tcl b/storage/bdb/test/txn008.tcl
index ad57ea0eeaa274c7775eab52cdaa8071c6a904ca..8c89296f4491ba65420814007592146c38dc552f 100644
--- a/storage/bdb/test/txn008.tcl
+++ b/storage/bdb/test/txn008.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: txn008.tcl,v 11.3 2002/05/10 17:55:54 sue Exp $
+# $Id: txn008.tcl,v 11.6 2004/01/28 03:36:33 bostic Exp $
 #
 
 # TEST	txn008
@@ -17,11 +17,11 @@ proc txn008 { } {
 	set orig_maxid $txn_maxid
 	puts "\tTxn008.1: wraparound txnids"
 	set txn_curid [expr $txn_maxid - 2]
-	txn002 "08.1"
+	txn002 "008.1"
 	puts "\tTxn008.2: closer wraparound txnids"
 	set txn_curid [expr $txn_maxid - 3]
 	set txn_maxid [expr $txn_maxid - 2]
-	txn002 "08.2"
+	txn002 "008.2"
 
 	puts "\tTxn008.3: test wraparound txnids"
 	txn_idwrap_check $testdir
diff --git a/storage/bdb/test/txn009.tcl b/storage/bdb/test/txn009.tcl
index 784c0068a41ca15a6b6d00c957e737615f64717d..b45538d754572a52e4c6be31a450b5368d0ea8f3 100644
--- a/storage/bdb/test/txn009.tcl
+++ b/storage/bdb/test/txn009.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: txn009.tcl,v 11.3 2002/05/10 17:55:55 sue Exp $
+# $Id: txn009.tcl,v 11.6 2004/01/28 03:36:33 bostic Exp $
 #
 
 # TEST	txn009
@@ -17,11 +17,11 @@ proc txn009 { } {
 	set orig_maxid $txn_maxid
 	puts "\tTxn009.1: wraparound txnids"
 	set txn_curid [expr $txn_maxid - 2]
-	txn003 "09.1"
+	txn003 "009.1"
 	puts "\tTxn009.2: closer wraparound txnids"
 	set txn_curid [expr $txn_maxid - 3]
 	set txn_maxid [expr $txn_maxid - 2]
-	txn003 "09.2"
+	txn003 "009.2"
 
 	puts "\tTxn009.3: test wraparound txnids"
 	txn_idwrap_check $testdir
diff --git a/storage/bdb/test/txnscript.tcl b/storage/bdb/test/txnscript.tcl
index 1a4a1b6f2ec4377be9568438a9de3b0493053be8..980f6ed5118e6bd447dc0e487f1322b19fd1ba95 100644
--- a/storage/bdb/test/txnscript.tcl
+++ b/storage/bdb/test/txnscript.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1996-2002
+# Copyright (c) 1996-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: txnscript.tcl,v 11.3 2002/01/23 15:33:40 bostic Exp $
+# $Id: txnscript.tcl,v 11.5 2004/01/28 03:36:33 bostic Exp $
 #
 # Txn003 script - outstanding child prepare script
 # Usage: txnscript envcmd dbcmd gidf key data
diff --git a/storage/bdb/test/update.tcl b/storage/bdb/test/update.tcl
index 2bedfacc793d7ea688be5abe483e5e5f63a35ca2..85c1a80071f994e59c61496abd5bc24cf0b24c3d 100644
--- a/storage/bdb/test/update.tcl
+++ b/storage/bdb/test/update.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: update.tcl,v 11.11 2002/01/11 15:53:58 bostic Exp $
+# $Id: update.tcl,v 11.13 2004/01/28 03:36:33 bostic Exp $
 
 source ./include.tcl
 global update_dir
diff --git a/storage/bdb/test/upgrade.tcl b/storage/bdb/test/upgrade.tcl
index 1c0ffc5461ab4b407840b8c36fe3a5990571b9a8..0043c353afcc2486f9ea220d3d2e4a0070f0f753 100644
--- a/storage/bdb/test/upgrade.tcl
+++ b/storage/bdb/test/upgrade.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 1999-2002
+# Copyright (c) 1999-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: upgrade.tcl,v 11.22 2002/07/28 03:22:41 krinsky Exp $
+# $Id: upgrade.tcl,v 11.37 2004/10/27 20:29:29 carol Exp $
 
 source ./include.tcl
 
@@ -13,6 +13,10 @@ set upgrade_dir "$test_path/upgrade/databases"
 
 global gen_upgrade
 set gen_upgrade 0
+global gen_chksum
+set gen_chksum 0
+global gen_upgrade_log
+set gen_upgrade_log 0
 
 global upgrade_dir
 global upgrade_be
@@ -22,81 +26,168 @@ global upgrade_name
 proc upgrade { { archived_test_loc "DEFAULT" } } {
 	source ./include.tcl
 	global upgrade_dir
+	global tcl_platform
+	global saved_logvers
 
 	set saved_upgrade_dir $upgrade_dir
 
-	puts -nonewline "Upgrade test: "
+	# Identify endianness of the machine running upgrade.
+	if { [big_endian] == 1 } {
+		set myendianness be
+	} else {
+		set myendianness le
+	}
+	set e $tcl_platform(byteOrder)
+
+	if { [file exists $archived_test_loc/logversion] == 1 } {
+		set fd [open $archived_test_loc/logversion r]
+		set saved_logvers [read $fd]
+		close $fd
+	} else {
+		puts "Old log version number must be available \
+		    in $archived_test_loc/logversion"
+		return
+	}
+
+	fileremove -f UPGRADE.OUT
+	set o [open UPGRADE.OUT a]
+
+	puts -nonewline $o "Upgrade test started at: "
+	puts $o [clock format [clock seconds] -format "%H:%M %D"]
+	puts $o [berkdb version -string]
+	puts $o "Testing $e files"
+
+	puts -nonewline "Upgrade test started at: "
+	puts [clock format [clock seconds] -format "%H:%M %D"]
+	puts [berkdb version -string]
+	puts "Testing $e files"
+
 	if { $archived_test_loc == "DEFAULT" } {
-		puts "using default archived databases in $upgrade_dir."
+		puts $o "Using default archived databases in $upgrade_dir."
+		puts "Using default archived databases in $upgrade_dir."
 	} else {
 		set upgrade_dir $archived_test_loc
-		puts "using archived databases in $upgrade_dir."
+		puts $o "Using archived databases in $upgrade_dir."
+		puts "Using archived databases in $upgrade_dir."
 	}
+	close $o
 
 	foreach version [glob $upgrade_dir/*] {
 		if { [string first CVS $version] != -1 } { continue }
 		regexp \[^\/\]*$ $version version
-		foreach method [glob $upgrade_dir/$version/*] {
-			regexp \[^\/\]*$ $method method
-			foreach file [glob $upgrade_dir/$version/$method/*] {
-				regexp (\[^\/\]*)\.tar\.gz$ $file dummy name
 
-				cleanup $testdir NULL 1
-				#puts  "$upgrade_dir/$version/$method/$name.tar.gz"
-				set curdir [pwd]
-				cd $testdir
-				set tarfd [open "|tar xf -" w]
-				cd $curdir
-
-				catch {exec gunzip -c "$upgrade_dir/$version/$method/$name.tar.gz" >@$tarfd}
-				close $tarfd
-
-				set f [open $testdir/$name.tcldump {RDWR CREAT}]
-				close $f
-
-				# It may seem suboptimal to exec a separate
-				# tclsh for each subtest, but this is
-				# necessary to keep the testing process
-				# from consuming a tremendous amount of
-				# memory.
-				if { [file exists $testdir/$name-le.db] } {
-					set ret [catch {exec $tclsh_path\
-					    << "source $test_path/test.tcl;\
-					    _upgrade_test $testdir $version\
-					    $method\
-					    $name le"} message]
-					puts $message
-					if { $ret != 0 } {
-						#exit
+		# Test only files where the endianness of the db matches
+		# the endianness of the test platform.  These are the
+		# meaningful tests:
+		# 1.  File generated on le, tested on le
+		# 2.  File generated on be, tested on be
+		# 3.  Byte-swapped file generated on le, tested on be
+		# 4.  Byte-swapped file generated on be, tested on le
+		#
+		set dbendianness [string range $version end-1 end]
+		if { [string compare $myendianness $dbendianness] != 0 } {
+			puts "Skipping test of $version \
+			    on $myendianness platform."
+		} else {
+			set release [string trim $version -lbe]
+			set o [open UPGRADE.OUT a]
+			puts $o "Files created on release $release"
+			close $o
+			puts "Files created on release $release"
+
+			foreach method [glob $upgrade_dir/$version/*] {
+				regexp \[^\/\]*$ $method method
+				set o [open UPGRADE.OUT a]
+				puts $o "\nTesting $method files"
+				close $o
+				puts "\tTesting $method files"
+
+				foreach file [lsort -dictionary \
+				    [glob -nocomplain \
+				    $upgrade_dir/$version/$method/*]] {
+					regexp (\[^\/\]*)\.tar\.gz$ \
+					    $file dummy name
+
+					cleanup $testdir NULL 1
+					set curdir [pwd]
+					cd $testdir
+					set tarfd [open "|tar xf -" w]
+					cd $curdir
+
+					catch {exec gunzip -c \
+					    "$upgrade_dir/$version/$method/$name.tar.gz" \
+					    >@$tarfd}
+					close $tarfd
+
+					set f [open $testdir/$name.tcldump \
+					    {RDWR CREAT}]
+					close $f
+
+					# We exec a separate tclsh for each
+					# separate subtest to keep the
+					# testing process from consuming a
+					# tremendous amount of memory.
+					#
+					# First we test the .db files.
+					if { [file exists \
+					    $testdir/$name-$myendianness.db] } {
+						if { [catch {exec $tclsh_path \
+						    << "source \
+						    $test_path/test.tcl;\
+						    _upgrade_test $testdir \
+						    $version $method $name \
+						    $myendianness" >>& \
+						    UPGRADE.OUT } message] } {
+							set o [open \
+							    UPGRADE.OUT a]
+							puts $o "FAIL: $message"
+							close $o
+						}
+						if { [catch {exec $tclsh_path\
+						    << "source \
+						    $test_path/test.tcl;\
+						    _db_load_test $testdir \
+						    $version $method $name" >>&\
+						    UPGRADE.OUT } message] } {
+							set o [open \
+							    UPGRADE.OUT a]
+							puts $o "FAIL: $message"
+							close $o
+						}
 					}
-				}
-
-				if { [file exists $testdir/$name-be.db] } {
-					set ret [catch {exec $tclsh_path\
-					    << "source $test_path/test.tcl;\
-					    _upgrade_test $testdir $version\
-					    $method\
-					    $name be"} message]
-					puts $message
-					if { $ret != 0 } {
-						#exit
+					# Then we test log files.
+					if { [file exists \
+					    $testdir/$name.prlog] } {
+						if { [catch {exec $tclsh_path \
+						    << "source \
+						    $test_path/test.tcl;\
+						    global saved_logvers;\
+						    set saved_logvers \
+						    $saved_logvers;\
+						    _log_test $testdir \
+						    $release $method \
+						    $name" >>& \
+						    UPGRADE.OUT } message] } {
+							set o [open \
+							    UPGRADE.OUT a]
+							puts $o "FAIL: $message"
+							close $o
+						}
 					}
 				}
-
-				set ret [catch {exec $tclsh_path\
-				    << "source $test_path/test.tcl;\
-				    _db_load_test $testdir $version $method\
-				    $name"} message]
-					puts $message
-				if { $ret != 0 } {
-					#exit
-				}
-
 			}
 		}
 	}
 	set upgrade_dir $saved_upgrade_dir
 
+	set o [open UPGRADE.OUT a]
+	puts -nonewline $o "Completed at: "
+	puts $o [clock format [clock seconds] -format "%H:%M %D"]
+	close $o
+
+	puts -nonewline "Completed at: "
+	puts [clock format [clock seconds] -format "%H:%M %D"]
+
 	# Don't provide a return value.
 	return
 }
@@ -104,9 +195,14 @@ proc upgrade { { archived_test_loc "DEFAULT" } } {
 proc _upgrade_test { temp_dir version method file endianness } {
 	source include.tcl
 	global errorInfo
+	global encrypt
 
 	puts "Upgrade: $version $method $file $endianness"
 
+	# Check whether we're working with an encrypted file.
+	if { [string match c-* $file] } {
+		set encrypt 1
+	}
 	set ret [berkdb upgrade "$temp_dir/$file-$endianness.db"]
 	error_check_good dbupgrade $ret 0
 
@@ -122,7 +218,7 @@ proc _db_load_test { temp_dir version method file } {
 	source include.tcl
 	global errorInfo
 
-	puts "db_load: $version $method $file"
+	puts "Db_load: $version $method $file"
 
 	set ret [catch \
 	    {exec $util_path/db_load -f "$temp_dir/$file.dump" \
@@ -136,53 +232,393 @@ proc _db_load_test { temp_dir version method file } {
 	    [filecmp "$temp_dir/$file.tcldump" "$temp_dir/temp.dump"] 0
 }
 
-proc gen_upgrade { dir } {
+proc _log_test { temp_dir release method file } {
+	source ./include.tcl
+	global saved_logvers
+	global passwd
+	puts "Check log file: $temp_dir $release $method $file"
+
+	# Get log version number of current system
+	set env [berkdb_env -create -log -home $testdir]
+	error_check_good is_valid_env [is_valid_env $env] TRUE
+	set current_logvers [get_log_vers $env]
+	error_check_good env_close [$env close] 0
+	error_check_good env_remove [berkdb envremove -home $testdir] 0
+
+	# Rename recd001-x-log.000000000n to log.000000000n.
+	set logfiles [glob -nocomplain $temp_dir/*log.0*]
+	foreach logfile $logfiles {
+		set logname [string replace $logfile 0 \
+		    [string last - $logfile]]
+		file rename -force $logfile $temp_dir/$logname
+	}
+
+	# Use db_printlog to dump the logs.  If the current log file
+	# version is greater than the saved log file version, the log
+	# files are expected to be unreadable.  If the log file is
+	# readable, check that the current printlog dump matches the
+	# archived printlog.
+ 	#
+	set ret [catch {exec $util_path/db_printlog -h $temp_dir \
+	    > $temp_dir/logs.prlog} message]
+	if { [is_substr $message "magic number"] } {
+		# The failure is probably due to encryption, try
+		# crypto printlog.
+		set ret [catch {exec $util_path/db_printlog -h $temp_dir \
+		    -P $passwd > $temp_dir/logs.prlog} message]
+		if { $ret == 1 } {
+			# If the failure is because of a historic
+			# log version, that's okay.
+			if { $current_logvers <= $saved_logvers } {
+				puts "db_printlog failed: $message"
+		 	}	
+		}
+	}
+
+	if { $current_logvers > $saved_logvers } {
+		error_check_good historic_log_version \
+		    [is_substr $message "historic log version"] 1
+	} else {
+		error_check_good db_printlog:$message $ret 0
+		# Compare logs.prlog and $file.prlog (should match)
+		error_check_good "Compare printlogs" [filecmp \
+		    "$temp_dir/logs.prlog" "$temp_dir/$file.prlog"] 0
+	}
+}
+
+proc gen_upgrade { dir { save_crypto 1 } { save_non_crypto 1 } } {
 	global gen_upgrade
+	global gen_upgrade_log
+	global gen_chksum
 	global upgrade_dir
 	global upgrade_be
 	global upgrade_method
 	global upgrade_name
-	global num_test
+	global test_names
 	global parms
+	global encrypt
+	global passwd
 	source ./include.tcl
 
-	set gen_upgrade 1
 	set upgrade_dir $dir
+	env_cleanup $testdir
+
+	fileremove -f GENERATE.OUT
+	set o [open GENERATE.OUT a]
+
+	puts -nonewline $o "Generating upgrade files.  Started at: "
+	puts $o [clock format [clock seconds] -format "%H:%M %D"]
+	puts $o [berkdb version -string]
+
+	puts -nonewline "Generating upgrade files.  Started at: "
+	puts [clock format [clock seconds] -format "%H:%M %D"]
+	puts [berkdb version -string]
 
-	foreach i "btree rbtree hash recno rrecno frecno queue queueext" {
-		puts "Running $i tests"
-		set upgrade_method $i
-		set start 1
-		for { set j $start } { $j <= $num_test(test) } { incr j } {
-			set upgrade_name [format "test%03d" $j]
-			if { [info exists parms($upgrade_name)] != 1 } {
+	close $o
+
+	# Create a file that contains the log version number.
+	# If necessary, create the directory to contain the file.
+	set env [berkdb_env -create -log -home $testdir]
+	error_check_good is_valid_env [is_valid_env $env] TRUE
+
+	if { [file exists $dir] == 0 } {
+		file mkdir $dir
+	}
+	set lv [open $dir/logversion w]
+	puts $lv [get_log_vers $env]
+	close $lv
+
+	error_check_good env_close [$env close] 0
+
+	# Generate test databases for each access method and endianness.
+	set gen_upgrade 1
+	foreach method \
+	    "btree rbtree hash recno rrecno frecno queue queueext" {
+		set o [open GENERATE.OUT a]
+		puts $o "\nGenerating $method files"
+		close $o
+		puts "\tGenerating $method files"
+		set upgrade_method $method
+#set test_names(test) ""
+		foreach test $test_names(test) {
+			if { [info exists parms($test)] != 1 } {
 				continue
 			}
 
-			foreach upgrade_be { 0 1 } {
+			set o [open GENERATE.OUT a]
+			puts $o "\t\tGenerating files for $test"
+			close $o
+			puts "\t\tGenerating files for $test"
+
+			if { $save_non_crypto == 1 } {
+				set encrypt 0
+				foreach upgrade_be { 0 1 } {
+					set upgrade_name $test
+					if [catch {exec $tclsh_path \
+					    << "source $test_path/test.tcl;\
+					    global gen_upgrade upgrade_be;\
+					    global upgrade_method upgrade_name;\
+					    global encrypt;\
+					    set encrypt $encrypt;\
+					    set gen_upgrade 1;\
+					    set upgrade_be $upgrade_be;\
+					    set upgrade_method $upgrade_method;\
+					    set upgrade_name $upgrade_name;\
+					    run_method -$method $test" \
+					    >>& GENERATE.OUT} res] {
+						puts "FAIL: run_method \
+						    $test $method"
+					}
+					cleanup $testdir NULL 1
+				}
+				# Save checksummed files for only one test.
+				# Checksumming should work in all or no cases.
+				set gen_chksum 1
+				foreach upgrade_be { 0 1 } {
+					set upgrade_name $test
+					if { $test == "test001" } {
+						if { [catch {exec $tclsh_path \
+						    << "source $test_path/test.tcl;\
+						    global gen_upgrade;\
+						    global upgrade_be;\
+						    global upgrade_method;\
+						    global upgrade_name;\
+						    global encrypt gen_chksum;\
+						    set encrypt $encrypt;\
+						    set gen_upgrade 1;\
+						    set gen_chksum 1;\
+						    set upgrade_be $upgrade_be;\
+						    set upgrade_method \
+						    $upgrade_method;\
+						    set upgrade_name \
+						    $upgrade_name;\
+						    run_method -$method $test \
+						    0 1 stdout -chksum" \
+						    >>& GENERATE.OUT} res] } {
+							puts "FAIL: run_method \
+							    $test $method \
+							    -chksum: $res"
+						}
+						cleanup $testdir NULL 1
+					}
+				}
+				set gen_chksum 0
+			}
+			# Save encrypted db's only of native endianness.
+			# Encrypted files are not portable across endianness.
+			if { $save_crypto == 1 } {
+				set upgrade_be [big_endian]
+				set encrypt 1
+				set upgrade_name $test
 				if [catch {exec $tclsh_path \
 				    << "source $test_path/test.tcl;\
 				    global gen_upgrade upgrade_be;\
 				    global upgrade_method upgrade_name;\
+				    global encrypt passwd;\
+				    set encrypt $encrypt;\
+				    set passwd $passwd;\
 				    set gen_upgrade 1;\
 				    set upgrade_be $upgrade_be;\
 				    set upgrade_method $upgrade_method;\
 				    set upgrade_name $upgrade_name;\
-				    run_method -$i $j $j"} res] {
-					puts "FAIL: $upgrade_name $i"
+				    run_secmethod $method $test" \
+				    >>& GENERATE.OUT} res] {
+					puts "FAIL: run_secmethod \
+					    $test $method"
 				}
-				puts $res
 				cleanup $testdir NULL 1
 			}
 		}
 	}
 	set gen_upgrade 0
+	# Set upgrade_be to the native value so log files go to the
+	# right place.
+	set upgrade_be [big_endian]
+
+	# Generate log files.
+	set o [open GENERATE.OUT a]
+	puts $o "\tGenerating log files"
+	close $o
+	puts "\tGenerating log files"
+
+	set gen_upgrade_log 1
+	# Pass the global variables and their values to the new tclsh.
+	if { $save_non_crypto == 1 } {
+		set encrypt 0
+		if [catch {exec $tclsh_path  << "source $test_path/test.tcl;\
+		    global gen_upgrade_log upgrade_be upgrade_dir;\
+		    global encrypt;\
+		    set encrypt $encrypt;\
+		    set gen_upgrade_log $gen_upgrade_log; \
+		    set upgrade_be $upgrade_be;\
+		    set upgrade_dir $upgrade_dir;\
+		    run_recds" >>& GENERATE.OUT} res] {
+			puts "FAIL: run_recds: $res"
+		}
+	}
+	if { $save_crypto == 1 } {
+		set encrypt 1
+		if [catch {exec $tclsh_path  << "source $test_path/test.tcl;\
+		    global gen_upgrade_log upgrade_be upgrade_dir;\
+		    global encrypt;\
+		    set encrypt $encrypt;\
+		    set gen_upgrade_log $gen_upgrade_log; \
+		    set upgrade_be $upgrade_be;\
+		    set upgrade_dir $upgrade_dir;\
+		    run_recds "  >>& GENERATE.OUT} res] {
+			puts "FAIL: run_recds with crypto: $res"
+		}
+	}
+	set gen_upgrade_log 0
+
+	set o [open GENERATE.OUT a]
+	puts -nonewline $o "Completed at: "
+	puts $o [clock format [clock seconds] -format "%H:%M %D"]
+	puts -nonewline "Completed at: "
+	puts [clock format [clock seconds] -format "%H:%M %D"]
+	close $o
+}
+
+proc save_upgrade_files { dir } {
+	global upgrade_dir
+	global upgrade_be
+	global upgrade_method
+	global upgrade_name
+	global gen_upgrade
+	global gen_upgrade_log
+	global encrypt
+	global gen_chksum
+	global passwd
+	source ./include.tcl
+
+	set vers [berkdb version]
+	set maj [lindex $vers 0]
+	set min [lindex $vers 1]
+
+	# Is this machine big or little endian?  We want to mark
+	# the test directories appropriately, since testing
+	# little-endian databases generated by a big-endian machine,
+	# and/or vice versa, is interesting.
+	if { [big_endian] } {
+		set myendianness be
+	} else {
+		set myendianness le
+	}
+
+	if { $upgrade_be == 1 } {
+		set version_dir "$myendianness-$maj.${min}be"
+		set en be
+	} else {
+		set version_dir "$myendianness-$maj.${min}le"
+		set en le
+	}
+
+	set dest $upgrade_dir/$version_dir/$upgrade_method
+	exec mkdir -p $dest
+
+	if { $gen_upgrade == 1 } {
+		# Save db files from test001 - testxxx.
+		set dbfiles [glob -nocomplain $dir/*.db]
+		set dumpflag ""
+		# Encrypted files are identified by the prefix "c-".
+		if { $encrypt == 1 } {
+			set upgrade_name c-$upgrade_name
+			set dumpflag " -P $passwd "
+		}
+		# Checksummed files are identified by the prefix "s-".
+		if { $gen_chksum == 1 } {
+			set upgrade_name s-$upgrade_name
+		}
+		foreach dbfile $dbfiles {
+			set basename [string range $dbfile \
+			    [expr [string length $dir] + 1] end-3]
+
+			set newbasename $upgrade_name-$basename
+
+			# db_dump file
+			if { [catch {eval exec $util_path/db_dump -k $dumpflag \
+			    $dbfile > $dir/$newbasename.dump} res] } {
+				puts "FAIL: $res"
+			}
+
+			# tcl_dump file
+			upgrade_dump $dbfile $dir/$newbasename.tcldump
+
+			# Rename dbfile and any dbq files.
+			file rename $dbfile $dir/$newbasename-$en.db
+			foreach dbq \
+			    [glob -nocomplain $dir/__dbq.$basename.db.*] {
+				set s [string length $dir/__dbq.]
+				set newname [string replace $dbq $s \
+				    [expr [string length $basename] + $s - 1] \
+				    $newbasename-$en]
+				file rename $dbq $newname
+			}
+			set cwd [pwd]
+			cd $dir
+			catch {eval exec tar -cvf $dest/$newbasename.tar \
+			    [glob $newbasename* __dbq.$newbasename-$en.db.*]}
+			catch {exec gzip -9v $dest/$newbasename.tar} res
+			cd $cwd
+		}
+	}
+
+	if { $gen_upgrade_log == 1 } {
+		# Save log files from recd tests.
+		set logfiles [glob -nocomplain $dir/log.*]
+		if { [llength $logfiles] > 0 } {
+			# More than one log.0000000001 file may be produced
+			# per recd test, so we generate unique names:
+			# recd001-0-log.0000000001, recd001-1-log.0000000001,
+			# and so on.
+			# We may also have log.0000000001, log.0000000002,
+			# and so on, and they will all be dumped together
+			# by db_printlog.
+			set count 0
+			while { [file exists \
+			    $dest/$upgrade_name-$count-log.tar.gz] \
+			    == 1 } {
+				incr count
+			}
+			set newname $upgrade_name-$count-log
+
+			# Run db_printlog on all the log files
+			if {[catch {exec $util_path/db_printlog -h $dir > \
+			    $dir/$newname.prlog} res] != 0} {
+				puts "Regular printlog failed, try encryption"
+				eval {exec $util_path/db_printlog} -h $dir \
+				    -P $passwd > $dir/$newname.prlog
+			}
+
+			# Rename each log file so we can identify which
+			# recd test created it.
+			foreach logfile $logfiles {
+				set lognum [string range $logfile \
+				    end-9 end]
+				file rename $logfile $dir/$newname.$lognum
+			}
+
+			set cwd [pwd]
+			cd $dir
+
+			catch {eval exec tar -cvf $dest/$newname.tar \
+			    [glob $newname*]}
+			catch {exec gzip -9v $dest/$newname.tar}
+			cd $cwd
+		}
+	}
 }
 
 proc upgrade_dump { database file {stripnulls 0} } {
 	global errorInfo
+	global encrypt
+	global passwd
 
-	set db [berkdb open $database]
+	set encargs ""
+	if { $encrypt == 1 } {
+		set encargs " -encryptany $passwd "
+	}
+	set db [eval {berkdb open} -rdonly $encargs $database]
 	set dbc [$db cursor]
 
 	set f [open $file w+]
@@ -244,7 +680,8 @@ proc upgrade_dump { database file {stripnulls 0} } {
 		puts -nonewline $f $key
 		puts -nonewline $f [binary format i [llength $data_list]]
 		for { set j 0 } { $j < [llength $data_list] } { incr j } {
-			puts -nonewline $f [binary format i [string length [concat [lindex $data_list $j]]]]
+			puts -nonewline $f [binary format i [string length \
+			    [concat [lindex $data_list $j]]]]
 			puts -nonewline $f [concat [lindex $data_list $j]]
 		}
 		if { [llength $data_list] == 0 } {
@@ -292,3 +729,17 @@ proc strip_null { str } {
 
 	return $ret
 }
+
+proc get_log_vers { env } {
+	set stat [$env log_stat]
+	foreach pair $stat {
+		set msg [lindex $pair 0]
+		set val [lindex $pair 1]
+		if { $msg == "Log file Version" } {
+			return $val
+		}
+	}
+	puts "FAIL: Log file Version not found in log_stat"
+	return 0
+}
+
diff --git a/storage/bdb/test/wrap.tcl b/storage/bdb/test/wrap.tcl
index aaceb4f74e65d99932bebfed7fc47cd7682cfa7e..34ec451072c113f372c19049f328c74ab7554acb 100644
--- a/storage/bdb/test/wrap.tcl
+++ b/storage/bdb/test/wrap.tcl
@@ -1,9 +1,9 @@
 # See the file LICENSE for redistribution information.
 #
-# Copyright (c) 2000-2002
+# Copyright (c) 2000-2004
 #	Sleepycat Software.  All rights reserved.
 #
-# $Id: wrap.tcl,v 11.6 2002/04/25 13:35:02 bostic Exp $
+# $Id: wrap.tcl,v 11.8 2004/01/28 03:36:33 bostic Exp $
 #
 # Sentinel file wrapper for multi-process tests.  This is designed to avoid a
 # set of nasty bugs, primarily on Windows, where pid reuse causes watch_procs
diff --git a/storage/bdb/txn/txn.c b/storage/bdb/txn/txn.c
index 78c54791d0692edb0470000b4fd8034252cfd45f..f0e4f7d4c352bab85fed56045af61bca2ad6a8ee 100644
--- a/storage/bdb/txn/txn.c
+++ b/storage/bdb/txn/txn.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -34,14 +34,12 @@
  * 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.
+ *
+ * $Id: txn.c,v 11.249 2004/10/15 16:59:44 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: txn.c,v 11.179 2002/08/29 17:41:17 margo Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #include <stdlib.h>
@@ -68,17 +66,18 @@ static const char revid[] = "$Id: txn.c,v 11.179 2002/08/29 17:41:17 margo Exp $
 #include "dbinc/hash.h"
 #include "dbinc/lock.h"
 #include "dbinc/log.h"
+#include "dbinc/mp.h"
 #include "dbinc/txn.h"
 
 #define	SET_LOG_FLAGS(dbenv, txnp, lflags)				\
 	do {								\
-		lflags = DB_COMMIT | DB_PERMANENT;			\
+		lflags = DB_LOG_COMMIT | DB_LOG_PERM;			\
 		if (F_ISSET(txnp, TXN_SYNC))				\
 			lflags |= DB_FLUSH;				\
 		else if (!F_ISSET(txnp, TXN_NOSYNC) &&			\
 		    !F_ISSET(dbenv, DB_ENV_TXN_NOSYNC)) {		\
 			if (F_ISSET(dbenv, DB_ENV_TXN_WRITE_NOSYNC))	\
-				lflags |= DB_WRNOSYNC;			\
+				lflags |= DB_LOG_WRNOSYNC;		\
 			else						\
 				lflags |= DB_FLUSH;			\
 		}							\
@@ -96,68 +95,68 @@ typedef enum {
 	TXN_OP_PREPARE
 } txnop_t;
 
+static int  __txn_abort_pp __P((DB_TXN *));
 static int  __txn_begin_int __P((DB_TXN *, int));
+static int  __txn_commit_pp __P((DB_TXN *, u_int32_t));
+static int  __txn_discard_pp __P((DB_TXN *, u_int32_t));
 static int  __txn_end __P((DB_TXN *, int));
 static int  __txn_isvalid __P((const DB_TXN *, TXN_DETAIL **, txnop_t));
-static int  __txn_set_timeout __P(( DB_TXN *, db_timeout_t, u_int32_t));
 static int  __txn_undo __P((DB_TXN *));
+static int  __txn_dispatch_undo __P((DB_ENV *,
+		DB_TXN *, DBT *, DB_LSN *, void *));
+static void __txn_set_begin_lsnp __P((DB_TXN *txn, DB_LSN **));
 
-#ifndef db_create
 /*
- * txn_abort --
- * txn_begin --
- * txn_commit --
- *
- * When we switched to methods in 4.0, we guessed txn_{abort,begin,commit}
- * were the interfaces applications would likely use and not be willing to
- * change, due to the sheer volume of the calls.  Provide wrappers -- we
- * could do txn_abort and txn_commit using macros, but not txn_begin, as
- * the name of the field is txn_begin, we didn't want to modify it.
+ * __txn_begin_pp --
+ *	DB_ENV->txn_begin pre/post processing.
  *
- * The issue with txn_begin hits us in another way.  If configured with the
- * --with-uniquename option, we use #defines to re-define DB's interfaces
- * to unique names.  We can't do that for these functions because txn_begin
- * is also a field name in the DB_ENV structure, and the #defines we use go
- * at the end of the db.h file -- we get control too late to #define a field
- * name.  So, modify the script that generates the unique names #defines to
- * not generate them for these three functions, and don't include the three
- * functions in libraries built with that configuration option.
- *
- * EXTERN: int txn_abort __P((DB_TXN *));
- * EXTERN: int txn_begin __P((DB_ENV *, DB_TXN *, DB_TXN **, u_int32_t));
- * EXTERN: int txn_commit __P((DB_TXN *, u_int32_t));
+ * PUBLIC: int __txn_begin_pp __P((DB_ENV *, DB_TXN *, DB_TXN **, u_int32_t));
  */
 int
-txn_abort(txnp)
-	DB_TXN *txnp;
-{
-	return (txnp->abort(txnp));
-}
-
-int
-txn_begin(dbenv, parent, txnpp, flags)
+__txn_begin_pp(dbenv, parent, txnpp, flags)
 	DB_ENV *dbenv;
 	DB_TXN *parent, **txnpp;
 	u_int32_t flags;
 {
-	return (dbenv->txn_begin(dbenv, parent, txnpp, flags));
-}
+	int rep_check, ret;
 
-int
-txn_commit(txnp, flags)
-	DB_TXN *txnp;
-	u_int32_t flags;
-{
-	return (txnp->commit(txnp, flags));
+	PANIC_CHECK(dbenv);
+	ENV_REQUIRES_CONFIG(dbenv, dbenv->tx_handle, "txn_begin", DB_INIT_TXN);
+
+	if ((ret = __db_fchk(dbenv,
+	    "txn_begin", flags,
+	    DB_DEGREE_2 | DB_DIRTY_READ | DB_TXN_NOWAIT |
+	    DB_TXN_NOSYNC | DB_TXN_SYNC)) != 0)
+		return (ret);
+	if ((ret = __db_fcchk(dbenv,
+	    "txn_begin", flags, DB_TXN_NOSYNC, DB_TXN_SYNC)) != 0)
+		return (ret);
+
+	if (parent == NULL) {
+		rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+		if (rep_check)
+			__op_rep_enter(dbenv);
+	} else
+		rep_check = 0;
+	ret = __txn_begin(dbenv, parent, txnpp, flags);
+	/*
+	 * We only decrement the count if the operation fails.
+	 * Otherwise the count will be decremented when the
+	 * txn is resolved by txn_commit, txn_abort, etc.
+	 */
+	if (ret != 0 && rep_check)
+		__op_rep_exit(dbenv);
+
+	return (ret);
 }
-#endif /* !db_create */
 
 /*
  * __txn_begin --
- *	This is a wrapper to the actual begin process.  Normal transaction
- * begin allocates a DB_TXN structure for the caller, while XA transaction
- * begin does not.  Other than that, both call into common __txn_begin_int
- * code.
+ *	DB_ENV->txn_begin.
+ *
+ * This is a wrapper to the actual begin process.  Normal transaction begin
+ * allocates a DB_TXN structure for the caller, while XA transaction begin
+ * does not.  Other than that, both call into common __txn_begin_int code.
  *
  * Internally, we use TXN_DETAIL structures, but the DB_TXN structure
  * provides access to the transaction ID and the offset in the transaction
@@ -176,18 +175,6 @@ __txn_begin(dbenv, parent, txnpp, flags)
 	int ret;
 
 	*txnpp = NULL;
-	PANIC_CHECK(dbenv);
-	ENV_REQUIRES_CONFIG(dbenv, dbenv->tx_handle, "txn_begin", DB_INIT_TXN);
-
-	if ((ret = __db_fchk(dbenv,
-	    "txn_begin", flags,
-	    DB_DIRTY_READ | DB_TXN_NOWAIT |
-	    DB_TXN_NOSYNC | DB_TXN_SYNC)) != 0)
-		return (ret);
-	if ((ret = __db_fcchk(dbenv,
-	    "txn_begin", flags, DB_TXN_NOSYNC, DB_TXN_SYNC)) != 0)
-		return (ret);
-
 	if ((ret = __os_calloc(dbenv, 1, sizeof(DB_TXN), &txn)) != 0)
 		return (ret);
 
@@ -195,7 +182,10 @@ __txn_begin(dbenv, parent, txnpp, flags)
 	txn->parent = parent;
 	TAILQ_INIT(&txn->kids);
 	TAILQ_INIT(&txn->events);
+	STAILQ_INIT(&txn->logs);
 	txn->flags = TXN_MALLOC;
+	if (LF_ISSET(DB_DEGREE_2))
+		F_SET(txn, TXN_DEGREE_2);
 	if (LF_ISSET(DB_DIRTY_READ))
 		F_SET(txn, TXN_DIRTY_READ);
 	if (LF_ISSET(DB_TXN_NOSYNC))
@@ -256,11 +246,21 @@ __txn_xa_begin(dbenv, txn)
 {
 	PANIC_CHECK(dbenv);
 
-	memset(txn, 0, sizeof(DB_TXN));
-
+	/*
+	 * We need to initialize the transaction structure, but must be careful
+	 * not to smash the links.  We manually initialize the structure.
+	 */
 	txn->mgrp = dbenv->tx_handle;
 	TAILQ_INIT(&txn->kids);
 	TAILQ_INIT(&txn->events);
+	STAILQ_INIT(&txn->logs);
+	txn->parent = NULL;
+	ZERO_LSN(txn->last_lsn);
+	txn->txnid = TXN_INVALID;
+	txn->tid = 0;
+	txn->cursors = 0;
+	memset(&txn->lock_timeout, 0, sizeof(db_timeout_t));
+	memset(&txn->expire, 0, sizeof(db_timeout_t));
 
 	return (__txn_begin_int(txn, 0));
 }
@@ -289,8 +289,8 @@ __txn_compensate_begin(dbenv, txnpp)
 	txn->mgrp = dbenv->tx_handle;
 	TAILQ_INIT(&txn->kids);
 	TAILQ_INIT(&txn->events);
-	txn->flags = TXN_MALLOC;
-	F_SET(txn, TXN_COMPENSATE);
+	STAILQ_INIT(&txn->logs);
+	txn->flags = TXN_COMPENSATE | TXN_MALLOC;
 
 	*txnpp = txn;
 	return (__txn_begin_int(txn, 1));
@@ -306,7 +306,7 @@ __txn_begin_int(txn, internal)
 	int internal;
 {
 	DB_ENV *dbenv;
-	DB_LSN begin_lsn, null_lsn;
+	DB_LSN null_lsn;
 	DB_TXNMGR *mgr;
 	DB_TXNREGION *region;
 	TXN_DETAIL *td;
@@ -318,19 +318,6 @@ __txn_begin_int(txn, internal)
 	dbenv = mgr->dbenv;
 	region = mgr->reginfo.primary;
 
-	/*
-	 * We do not have to write begin records (and if we do not, then we
-	 * need never write records for read-only transactions).  However,
-	 * we do need to find the current LSN so that we can store it in the
-	 * transaction structure, so we can know where to take checkpoints.
-	 *
-	 * XXX
-	 * We should set this value when we write the first log record, not
-	 * here.
-	 */
-	if (DBENV_LOGGING(dbenv))
-		__log_txn_lsn(dbenv, &begin_lsn, NULL, NULL);
-
 	R_LOCK(dbenv, &mgr->reginfo);
 	if (!F_ISSET(txn, TXN_COMPENSATE) && F_ISSET(region, TXN_IN_RECOVERY)) {
 		__db_err(dbenv, "operation not permitted during recovery");
@@ -370,14 +357,14 @@ __txn_begin_int(txn, internal)
 			    &region->last_txnid, &region->cur_maxid);
 		__os_free(dbenv, ids);
 		if (DBENV_LOGGING(dbenv) &&
-		    (ret = __txn_recycle_log(dbenv, NULL,
-		    &null_lsn, 0, region->last_txnid, region->cur_maxid)) != 0)
+		    (ret = __txn_recycle_log(dbenv, NULL, &null_lsn,
+			0, region->last_txnid + 1, region->cur_maxid)) != 0)
 			goto err;
 	}
 
 	/* Allocate a new transaction detail structure. */
 	if ((ret =
-	    __db_shalloc(mgr->reginfo.addr, sizeof(TXN_DETAIL), 0, &td)) != 0) {
+	    __db_shalloc(&mgr->reginfo, sizeof(TXN_DETAIL), 0, &td)) != 0) {
 		__db_err(dbenv,
 		    "Unable to allocate memory for transaction detail");
 		goto err;
@@ -392,15 +379,16 @@ __txn_begin_int(txn, internal)
 		region->stat.st_maxnactive = region->stat.st_nactive;
 
 	td->txnid = id;
-	td->begin_lsn = begin_lsn;
 	ZERO_LSN(td->last_lsn);
-	td->status = TXN_RUNNING;
+	ZERO_LSN(td->begin_lsn);
 	if (txn->parent != NULL)
 		td->parent = txn->parent->off;
 	else
 		td->parent = INVALID_ROFF;
-
+	td->status = TXN_RUNNING;
 	td->flags = 0;
+	td->xa_status = 0;
+
 	off = R_OFFSET(&mgr->reginfo, td);
 	R_UNLOCK(dbenv, &mgr->reginfo);
 
@@ -408,12 +396,13 @@ __txn_begin_int(txn, internal)
 	txn->txnid = id;
 	txn->off = (u_int32_t)off;
 
-	txn->abort = __txn_abort;
-	txn->commit = __txn_commit;
-	txn->discard = __txn_discard;
+	txn->abort = __txn_abort_pp;
+	txn->commit = __txn_commit_pp;
+	txn->discard = __txn_discard_pp;
 	txn->id = __txn_id;
 	txn->prepare = __txn_prepare;
 	txn->set_timeout = __txn_set_timeout;
+	txn->set_begin_lsnp = __txn_set_begin_lsnp;
 
 	/*
 	 * If this is a transaction family, we must link the child to the
@@ -436,6 +425,26 @@ err:	R_UNLOCK(dbenv, &mgr->reginfo);
 	return (ret);
 }
 
+/*
+ * __txn_commit_pp --
+ *	Interface routine to TXN->commit.
+ */
+static int
+__txn_commit_pp(txnp, flags)
+	DB_TXN *txnp;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	int not_child, ret;
+
+	dbenv = txnp->mgrp->dbenv;
+	not_child = txnp->parent == NULL;
+	ret = __txn_commit(txnp, flags);
+	if (not_child && IS_ENV_REPLICATED(dbenv))
+		__op_rep_exit(dbenv);
+	return (ret);
+}
+
 /*
  * __txn_commit --
  *	Commit a transaction.
@@ -447,6 +456,7 @@ __txn_commit(txnp, flags)
 	DB_TXN *txnp;
 	u_int32_t flags;
 {
+	DBT list_dbt;
 	DB_ENV *dbenv;
 	DB_LOCKREQ request;
 	DB_TXN *kid;
@@ -489,29 +499,11 @@ __txn_commit(txnp, flags)
 	 * Abort should never fail; if it does, we bail out immediately.
 	 */
 	while ((kid = TAILQ_FIRST(&txnp->kids)) != NULL)
-		if ((ret = kid->commit(kid, flags)) != 0)
+		if ((ret = __txn_commit(kid, flags)) != 0)
 			while ((kid = TAILQ_FIRST(&txnp->kids)) != NULL)
-				if ((t_ret = kid->abort(kid)) != 0)
+				if ((t_ret = __txn_abort(kid)) != 0)
 					return (__db_panic(dbenv, t_ret));
 
-	/*
-	 * Process any aborted pages from our children.
-	 * We delay putting pages on the free list that are newly
-	 * allocated and then aborted so that we can undo other
-	 * allocations, if necessary, without worrying about
-	 * these pages which were not on the free list before.
-	 */
-	if (txnp->txn_list != NULL) {
-		t_ret = __db_do_the_limbo(dbenv, NULL, txnp, txnp->txn_list);
-		__db_txnlist_end(dbenv, txnp->txn_list);
-		txnp->txn_list = NULL;
-		if (t_ret != 0 && ret == 0)
-			ret = t_ret;
-	}
-
-	if (ret != 0)
-		goto err;
-
 	/*
 	 * If there are any log records, write a log record and sync the log,
 	 * else do no log writes.  If the commit is for a child transaction,
@@ -519,61 +511,124 @@ __txn_commit(txnp, flags)
 	 * abort (if its parent aborts), and otherwise its parent or ultimate
 	 * ancestor will write synchronously.
 	 */
-	if (DBENV_LOGGING(dbenv) && !IS_ZERO_LSN(txnp->last_lsn)) {
+	if (DBENV_LOGGING(dbenv) && (!IS_ZERO_LSN(txnp->last_lsn) ||
+	    STAILQ_FIRST(&txnp->logs) != NULL)) {
 		if (txnp->parent == NULL) {
 			/*
-			 * We are about to free all the read locks
-			 * for this transaction below.  Some of those
-			 * locks might be handle locks which should
-			 * not be freed, because they will be freed
-			 * when the handle is closed.  Check the
-			 * events and preprocess any trades now so
-			 * that we don't release the locks below.
+			 * We are about to free all the read locks for this
+			 * transaction below.  Some of those locks might be
+			 * handle locks which should not be freed, because
+			 * they will be freed when the handle is closed. Check
+			 * the events and preprocess any trades now so we don't
+			 * release the locks below.
 			 */
-			if ((ret = __txn_doevents(dbenv, txnp, 0, 1)) != 0)
-				goto err;
-			request.op = DB_LOCK_PUT_READ;
-			if (LOCKING_ON(dbenv) && (ret = dbenv->lock_vec(
-			   dbenv, txnp->txnid, 0, &request, 1, NULL)) != 0)
+			if ((ret =
+			    __txn_doevents(dbenv, txnp, TXN_PREPARE, 1)) != 0)
 				goto err;
 
-			SET_LOG_FLAGS(dbenv, txnp, lflags);
-			if ((ret = __txn_regop_log(dbenv,
-			    txnp, &txnp->last_lsn, lflags,
-			    TXN_COMMIT, (int32_t)time(NULL))) != 0)
+			memset(&request, 0, sizeof(request));
+			if (LOCKING_ON(dbenv)) {
+				request.op = DB_LOCK_PUT_READ;
+				if (IS_REP_MASTER(dbenv) &&
+				    !IS_ZERO_LSN(txnp->last_lsn)) {
+					memset(&list_dbt, 0, sizeof(list_dbt));
+					request.obj = &list_dbt;
+				}
+				ret = __lock_vec(dbenv,
+				    txnp->txnid, 0, &request, 1, NULL);
+			}
+
+			if (ret == 0 && !IS_ZERO_LSN(txnp->last_lsn)) {
+				SET_LOG_FLAGS(dbenv, txnp, lflags);
+				ret = __txn_regop_log(dbenv, txnp,
+				    &txnp->last_lsn, lflags, TXN_COMMIT,
+				    (int32_t)time(NULL), request.obj);
+			}
+
+			if (request.obj != NULL && request.obj->data != NULL)
+				__os_free(dbenv, request.obj->data);
+			if (ret != 0)
 				goto err;
 		} else {
 			/* Log the commit in the parent! */
-			if ((ret = __txn_child_log(dbenv,
+			if (!IS_ZERO_LSN(txnp->last_lsn) &&
+			    (ret = __txn_child_log(dbenv,
 			    txnp->parent, &txnp->parent->last_lsn,
 			    0, txnp->txnid, &txnp->last_lsn)) != 0) {
 				goto err;
 			}
+			if (STAILQ_FIRST(&txnp->logs) != NULL) {
+				/*
+				 * Put the child first so we back it out first.
+				 * All records are undone in reverse order.
+				 */
+				STAILQ_CONCAT(&txnp->logs, &txnp->parent->logs);
+				txnp->parent->logs = txnp->logs;
+				STAILQ_INIT(&txnp->logs);
+			}
 
 			F_SET(txnp->parent, TXN_CHILDCOMMIT);
 		}
 	}
 
+	/*
+	 * Process any aborted pages from our children.  We delay putting pages
+	 * on the free list that are newly allocated and then aborted so we can
+	 * undo other allocations, if necessary, without worrying about these
+	 * pages which were not on the free list before.
+	 */
+	if (txnp->txn_list != NULL) {
+#ifndef HAVE_FTRUNCATE
+		t_ret = __db_do_the_limbo(dbenv,
+		      NULL, txnp, txnp->txn_list, LIMBO_NORMAL);
+		if (t_ret != 0 && ret == 0)
+			ret = t_ret;
+#endif
+		__db_txnlist_end(dbenv, txnp->txn_list);
+		txnp->txn_list = NULL;
+	}
+
+	if (ret != 0)
+		goto err;
+
 	/* This is OK because __txn_end can only fail with a panic. */
 	return (__txn_end(txnp, 1));
 
 err:	/*
-	 * If we are prepared, then we "must" be able to commit.  We
-	 * panic here because even though the coordinator might be
-	 * able to retry it is not clear it would know to do that.
-	 * Otherwise  we'll try to abort.  If that is successful,
-	 * then we return whatever was in ret (i.e., the reason we failed).
-	 * If the abort was unsuccessful, then abort probably returned
-	 * DB_RUNRECOVERY and we need to propagate that up.
+	 * If we are prepared, then we "must" be able to commit.  We panic here
+	 * because even though the coordinator might be able to retry it is not
+	 * clear it would know to do that.  Otherwise  we'll try to abort.  If
+	 * that is successful, then we return whatever was in ret (that is, the
+	 * reason we failed).  If the abort was unsuccessful, abort probably
+	 * returned DB_RUNRECOVERY and we need to propagate that up.
 	 */
 	if (td->status == TXN_PREPARED)
 		return (__db_panic(dbenv, ret));
-		
-	if ((t_ret = txnp->abort(txnp)) != 0)
+
+	if ((t_ret = __txn_abort(txnp)) != 0)
 		ret = t_ret;
 	return (ret);
 }
 
+/*
+ * __txn_abort_pp --
+ *	Interface routine to TXN->abort.
+ */
+static int
+__txn_abort_pp(txnp)
+	DB_TXN *txnp;
+{
+	DB_ENV *dbenv;
+	int not_child, ret;
+
+	dbenv = txnp->mgrp->dbenv;
+	not_child = txnp->parent == NULL;
+	ret = __txn_abort(txnp);
+	if (not_child && IS_ENV_REPLICATED(dbenv))
+		__op_rep_exit(dbenv);
+	return (ret);
+}
+
 /*
  * __txn_abort --
  *	Abort a transaction.
@@ -607,7 +662,7 @@ __txn_abort(txnp)
 	 * up.
 	 */
 	while ((kid = TAILQ_FIRST(&txnp->kids)) != NULL)
-		if ((ret = kid->abort(kid)) != 0)
+		if ((ret = __txn_abort(kid)) != 0)
 			return (ret);
 
 	if (LOCKING_ON(dbenv)) {
@@ -618,7 +673,7 @@ __txn_abort(txnp)
 		 * handle is closed.  Check the events and preprocess any
 		 * trades now so that we don't release the locks below.
 		 */
-		if ((ret = __txn_doevents(dbenv, txnp, 0, 1)) != 0)
+		if ((ret = __txn_doevents(dbenv, txnp, TXN_ABORT, 1)) != 0)
 			return (__db_panic(dbenv, ret));
 
 		/* Turn off timeouts. */
@@ -631,8 +686,9 @@ __txn_abort(txnp)
 			return (__db_panic(dbenv, ret));
 
 		request.op = DB_LOCK_UPGRADE_WRITE;
-		if ((ret = dbenv->lock_vec(
-		    dbenv, txnp->txnid, 0, &request, 1, NULL)) != 0)
+		request.obj = NULL;
+		if ((ret = __lock_vec(
+		    dbenv, txnp->txnid, DB_LOCK_ABORT, &request, 1, NULL)) != 0)
 			return (__db_panic(dbenv, ret));
 	}
 	if ((ret = __txn_undo(txnp)) != 0)
@@ -647,13 +703,33 @@ __txn_abort(txnp)
 	SET_LOG_FLAGS(dbenv, txnp, lflags);
 	if (DBENV_LOGGING(dbenv) && td->status == TXN_PREPARED &&
 	    (ret = __txn_regop_log(dbenv, txnp, &txnp->last_lsn,
-	    lflags, TXN_ABORT, (int32_t)time(NULL))) != 0)
+	    lflags, TXN_ABORT, (int32_t)time(NULL), NULL)) != 0)
 		return (__db_panic(dbenv, ret));
 
 	/* __txn_end always panics if it errors, so pass the return along. */
 	return (__txn_end(txnp, 0));
 }
 
+/*
+ * __txn_discard_pp --
+ *	Interface routine to TXN->discard.
+ */
+static int
+__txn_discard_pp(txnp, flags)
+	DB_TXN *txnp;
+	u_int32_t flags;
+{
+	DB_ENV *dbenv;
+	int not_child, ret;
+
+	dbenv = txnp->mgrp->dbenv;
+	not_child = txnp->parent == NULL;
+	ret = __txn_discard(txnp, flags);
+	if (not_child && IS_ENV_REPLICATED(dbenv))
+		__op_rep_exit(dbenv);
+	return (ret);
+}
+
 /*
  * __txn_discard --
  *	Free the per-process resources associated with this txn handle.
@@ -682,7 +758,6 @@ __txn_discard(txnp, flags)
 
 	/* Should be no children. */
 	DB_ASSERT(TAILQ_FIRST(&txnp->kids) == NULL);
-	DB_ASSERT(F_ISSET(td, TXN_RESTORED));
 
 	/* Free the space. */
 	MUTEX_THREAD_LOCK(dbenv, txnp->mgrp->mutexp);
@@ -709,8 +784,9 @@ __txn_prepare(txnp, gid)
 	DB_TXN *txnp;
 	u_int8_t *gid;
 {
-	DBT xid;
+	DBT list_dbt, xid;
 	DB_ENV *dbenv;
+	DB_LOCKREQ request;
 	DB_TXN *kid;
 	TXN_DETAIL *td;
 	u_int32_t lflags;
@@ -725,9 +801,15 @@ __txn_prepare(txnp, gid)
 
 	/* Commit any unresolved children. */
 	while ((kid = TAILQ_FIRST(&txnp->kids)) != NULL)
-		if ((ret = kid->commit(kid, DB_TXN_NOSYNC)) != 0)
+		if ((ret = __txn_commit(kid, DB_TXN_NOSYNC)) != 0)
 			return (ret);
 
+#ifndef HAVE_FTRUNCATE
+	if (txnp->txn_list != NULL  &&
+	    (ret = __db_do_the_limbo(dbenv,
+	    NULL, txnp, txnp->txn_list, LIMBO_PREPARE)) != 0)
+		return (ret);
+#endif
 	/*
 	 * In XA, the global transaction ID in the txn_detail structure is
 	 * already set; in a non-XA environment, we must set it here.  XA
@@ -736,6 +818,21 @@ __txn_prepare(txnp, gid)
 	 * of those states, then we are calling prepare directly and we need
 	 * to fill in the td->xid.
 	 */
+	if ((ret = __txn_doevents(dbenv, txnp, TXN_PREPARE, 1)) != 0)
+		return (ret);
+	memset(&request, 0, sizeof(request));
+	if (LOCKING_ON(dbenv)) {
+		request.op = DB_LOCK_PUT_READ;
+		if (IS_REP_MASTER(dbenv) &&
+		    IS_ZERO_LSN(txnp->last_lsn)) {
+			memset(&list_dbt, 0, sizeof(list_dbt));
+			request.obj = &list_dbt;
+		}
+		if ((ret = __lock_vec(dbenv,
+		    txnp->txnid, 0, &request, 1, NULL)) != 0)
+			return (ret);
+
+	}
 	if (DBENV_LOGGING(dbenv)) {
 		memset(&xid, 0, sizeof(xid));
 		if (td->xa_status != TXN_XA_ENDED &&
@@ -746,14 +843,18 @@ __txn_prepare(txnp, gid)
 		xid.size = sizeof(td->xid);
 		xid.data = td->xid;
 
-		SET_LOG_FLAGS(dbenv, txnp, lflags);
+		lflags = DB_LOG_COMMIT | DB_LOG_PERM | DB_FLUSH;
 		if ((ret = __txn_xa_regop_log(dbenv, txnp, &txnp->last_lsn,
 		    lflags, TXN_PREPARE, &xid, td->format, td->gtrid, td->bqual,
-		    &td->begin_lsn)) != 0) {
+		    &td->begin_lsn, request.obj)) != 0) {
 			__db_err(dbenv, "DB_TXN->prepare: log_write failed %s",
 			    db_strerror(ret));
-			return (ret);
 		}
+		if (request.obj != NULL && request.obj->data != NULL)
+			__os_free(dbenv, request.obj->data);
+		if (ret != 0)
+			return (ret);
+
 	}
 
 	MUTEX_THREAD_LOCK(dbenv, txnp->mgrp->mutexp);
@@ -777,9 +878,11 @@ __txn_id(txnp)
 
 /*
  * __txn_set_timeout --
- *	Set timeout values in the txn structure.
+ *	DB_ENV->set_txn_timeout.
+ *
+ * PUBLIC: int  __txn_set_timeout __P((DB_TXN *, db_timeout_t, u_int32_t));
  */
-static int
+int
 __txn_set_timeout(txnp, timeout, op)
 	DB_TXN *txnp;
 	db_timeout_t timeout;
@@ -802,29 +905,30 @@ __txn_isvalid(txnp, tdp, op)
 	TXN_DETAIL **tdp;
 	txnop_t op;
 {
+	DB_ENV *dbenv;
 	DB_TXNMGR *mgrp;
 	DB_TXNREGION *region;
 	TXN_DETAIL *tp;
 
 	mgrp = txnp->mgrp;
+	dbenv = mgrp->dbenv;
 	region = mgrp->reginfo.primary;
 
 	/* Check for recovery. */
 	if (!F_ISSET(txnp, TXN_COMPENSATE) &&
 	    F_ISSET(region, TXN_IN_RECOVERY)) {
-		__db_err(mgrp->dbenv,
-		    "operation not permitted during recovery");
+		__db_err(dbenv, "operation not permitted during recovery");
 		goto err;
 	}
 
 	/* Check for live cursors. */
 	if (txnp->cursors != 0) {
-		__db_err(mgrp->dbenv, "transaction has active cursors");
+		__db_err(dbenv, "transaction has active cursors");
 		goto err;
 	}
 
 	/* Check transaction's state. */
-	tp = (TXN_DETAIL *)R_ADDR(&mgrp->reginfo, txnp->off);
+	tp = R_ADDR(&mgrp->reginfo, txnp->off);
 	if (tdp != NULL)
 		*tdp = tp;
 
@@ -840,10 +944,14 @@ __txn_isvalid(txnp, tdp, op)
 		if (txnp->txnid != tp->txnid)
 			return (0);
 
-		/* What we've got had better be a restored transaction. */
-		if (!F_ISSET(tp, TXN_RESTORED)) {
-			__db_err(mgrp->dbenv, "not a restored transaction");
-			return (__db_panic(mgrp->dbenv, EINVAL));
+		/*
+		 * What we've got had better be either a prepared or
+		 * restored transaction.
+		 */
+		if (tp->status != TXN_PREPARED &&
+		    !F_ISSET(tp, TXN_DTL_RESTORED)) {
+			__db_err(dbenv, "not a restored transaction");
+			return (__db_panic(dbenv, EINVAL));
 		}
 
 		return (0);
@@ -856,7 +964,7 @@ __txn_isvalid(txnp, tdp, op)
 			 * I'm not arguing this is good, but I could imagine
 			 * someone doing it.
 			 */
-			__db_err(mgrp->dbenv,
+			__db_err(dbenv,
 			    "Prepare disallowed on child transactions");
 			return (EINVAL);
 		}
@@ -870,7 +978,7 @@ __txn_isvalid(txnp, tdp, op)
 	switch (tp->status) {
 	case TXN_PREPARED:
 		if (op == TXN_OP_PREPARE) {
-			__db_err(mgrp->dbenv, "transaction already prepared");
+			__db_err(dbenv, "transaction already prepared");
 			/*
 			 * Txn_prepare doesn't blow away the user handle, so
 			 * in this case, give the user the opportunity to
@@ -884,7 +992,7 @@ __txn_isvalid(txnp, tdp, op)
 	case TXN_ABORTED:
 	case TXN_COMMITTED:
 	default:
-		__db_err(mgrp->dbenv, "transaction already %s",
+		__db_err(dbenv, "transaction already %s",
 		    tp->status == TXN_COMMITTED ? "committed" : "aborted");
 		goto err;
 	}
@@ -896,7 +1004,7 @@ err:	/*
 	 * handles are dead by definition when we return, and if you use
 	 * a cursor you forgot to close, we have no idea what will happen.
 	 */
-	return (__db_panic(mgrp->dbenv, EINVAL));
+	return (__db_panic(dbenv, EINVAL));
 }
 
 /*
@@ -910,6 +1018,7 @@ __txn_end(txnp, is_commit)
 {
 	DB_ENV *dbenv;
 	DB_LOCKREQ request;
+	DB_TXNLOGREC *lr;
 	DB_TXNMGR *mgr;
 	DB_TXNREGION *region;
 	TXN_DETAIL *tp;
@@ -921,35 +1030,39 @@ __txn_end(txnp, is_commit)
 	do_closefiles = 0;
 
 	/* Process commit events. */
-	if ((ret = __txn_doevents(dbenv, txnp, is_commit, 0)) != 0)
+	if ((ret = __txn_doevents(dbenv,
+	    txnp, is_commit ? TXN_COMMIT : TXN_ABORT, 0)) != 0)
 		return (__db_panic(dbenv, ret));
 
-	/* Release the locks. */
-	request.op = txnp->parent == NULL ||
-	    is_commit == 0 ? DB_LOCK_PUT_ALL : DB_LOCK_INHERIT;
-
 	/*
+	 * Release the locks.
+	 *
 	 * __txn_end cannot return an simple error, we MUST return
 	 * success/failure from commit or abort, ignoring any internal
 	 * errors.  So, we panic if something goes wrong.  We can't
 	 * deadlock here because we're not acquiring any new locks,
 	 * so DB_LOCK_DEADLOCK is just as fatal as any other error.
 	 */
-	if (LOCKING_ON(dbenv) && (ret = dbenv->lock_vec(
-	    dbenv, txnp->txnid, DB_LOCK_FREE_LOCKER, &request, 1, NULL)) != 0)
-		return (__db_panic(dbenv, ret));
+	if (LOCKING_ON(dbenv)) {
+		request.op = txnp->parent == NULL ||
+		    is_commit == 0 ? DB_LOCK_PUT_ALL : DB_LOCK_INHERIT;
+		request.obj = NULL;
+		if ((ret = __lock_vec(dbenv,
+		    txnp->txnid, 0, &request, 1, NULL)) != 0)
+			return (__db_panic(dbenv, ret));
+	}
 
 	/* End the transaction. */
 	R_LOCK(dbenv, &mgr->reginfo);
 
-	tp = (TXN_DETAIL *)R_ADDR(&mgr->reginfo, txnp->off);
+	tp = R_ADDR(&mgr->reginfo, txnp->off);
 	SH_TAILQ_REMOVE(&region->active_txn, tp, links, __txn_detail);
-	if (F_ISSET(tp, TXN_RESTORED)) {
+	if (F_ISSET(tp, TXN_DTL_RESTORED)) {
 		region->stat.st_nrestores--;
 		do_closefiles = region->stat.st_nrestores == 0;
 	}
 
-	__db_shalloc_free(mgr->reginfo.addr, tp);
+	__db_shalloc_free(&mgr->reginfo, tp);
 
 	if (is_commit)
 		region->stat.st_ncommits++;
@@ -970,6 +1083,10 @@ __txn_end(txnp, is_commit)
 		TAILQ_REMOVE(&txnp->parent->kids, txnp, klinks);
 
 	/* Free the space. */
+	while ((lr = STAILQ_FIRST(&txnp->logs)) != NULL) {
+		STAILQ_REMOVE(&txnp->logs, lr, __txn_logrec, links);
+		__os_free(dbenv, lr);
+	}
 	if (F_ISSET(txnp, TXN_MALLOC)) {
 		MUTEX_THREAD_LOCK(dbenv, mgr->mutexp);
 		TAILQ_REMOVE(&mgr->txn_chain, txnp, links);
@@ -983,15 +1100,39 @@ __txn_end(txnp, is_commit)
 		(void)__dbreg_close_files(dbenv);
 		F_CLR((DB_LOG *)dbenv->lg_handle, DBLOG_RECOVER);
 		mgr->n_discards = 0;
-		(void)dbenv->txn_checkpoint(dbenv, 0, 0, DB_FORCE);
+		(void)__txn_checkpoint(dbenv, 0, 0, DB_FORCE);
 	}
+
 	return (0);
 }
 
+static int
+__txn_dispatch_undo(dbenv, txnp, rdbt, key_lsn, txnlist)
+	DB_ENV *dbenv;
+	DB_TXN *txnp;
+	DBT *rdbt;
+	DB_LSN *key_lsn;
+	void *txnlist;
+{
+	int ret;
+
+	ret = __db_dispatch(dbenv, dbenv->recover_dtab,
+	    dbenv->recover_dtab_size, rdbt, key_lsn, DB_TXN_ABORT, txnlist);
+	if (F_ISSET(txnp, TXN_CHILDCOMMIT))
+		(void)__db_txnlist_lsnadd(dbenv,
+		    txnlist, key_lsn, 0);
+	if (ret == DB_SURPRISE_KID) {
+		if ((ret = __db_txnlist_lsninit(
+		    dbenv, txnlist, key_lsn)) == 0)
+			F_SET(txnp, TXN_CHILDCOMMIT);
+	}
+
+	return (ret);
+}
+
 /*
  * __txn_undo --
- *	Undo the transaction with id txnid.  Returns 0 on success and
- *	errno on failure.
+ *	Undo the transaction with id txnid.
  */
 static int
 __txn_undo(txnp)
@@ -1002,6 +1143,7 @@ __txn_undo(txnp)
 	DB_LOGC *logc;
 	DB_LSN key_lsn;
 	DB_TXN *ptxn;
+	DB_TXNLOGREC *lr;
 	DB_TXNMGR *mgr;
 	int ret, t_ret;
 	void *txnlist;
@@ -1010,6 +1152,7 @@ __txn_undo(txnp)
 	dbenv = mgr->dbenv;
 	logc = NULL;
 	txnlist = NULL;
+	ret = 0;
 
 	if (!DBENV_LOGGING(dbenv))
 		return (0);
@@ -1021,13 +1164,11 @@ __txn_undo(txnp)
 	 */
 	memset(&rdbt, 0, sizeof(rdbt));
 
-	key_lsn = txnp->last_lsn;
-
 	/*
 	 * Allocate a txnlist for children and aborted page allocs.
 	 * We need to associate the list with the maximal parent
 	 * so that aborted pages are recovered when that transaction
-	 * is commited or aborted.
+	 * is committed or aborted.
 	 */
 	for (ptxn = txnp->parent; ptxn != NULL && ptxn->parent != NULL;)
 		ptxn = ptxn->parent;
@@ -1045,27 +1186,43 @@ __txn_undo(txnp)
 	    (ret = __db_txnlist_lsninit(dbenv, txnlist, &txnp->last_lsn)) != 0)
 		return (ret);
 
-	if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+	/*
+	 * Take log records from the linked list stored in the transaction,
+	 * then from the log.
+	 */
+	for (lr = STAILQ_FIRST(&txnp->logs);
+	    lr != NULL; lr = STAILQ_NEXT(lr, links)) {
+		rdbt.data = lr->data;
+		rdbt.size = 0;
+		LSN_NOT_LOGGED(key_lsn);
+		ret =
+		    __txn_dispatch_undo(dbenv, txnp, &rdbt, &key_lsn, txnlist);
+		if (ret != 0) {
+			__db_err(dbenv,
+			    "DB_TXN->abort: In-memory log undo failed: %s",
+			    db_strerror(ret));
+			goto err;
+		}
+	}
+
+	key_lsn = txnp->last_lsn;
+
+	if (!IS_ZERO_LSN(key_lsn) &&
+	     (ret = __log_cursor(dbenv, &logc)) != 0)
 		goto err;
-	while (ret == 0 && !IS_ZERO_LSN(key_lsn)) {
+
+	while (!IS_ZERO_LSN(key_lsn)) {
 		/*
 		 * The dispatch routine returns the lsn of the record
 		 * before the current one in the key_lsn argument.
 		 */
-		if ((ret = logc->get(logc, &key_lsn, &rdbt, DB_SET)) == 0) {
-			ret = __db_dispatch(dbenv, dbenv->recover_dtab,
-			    dbenv->recover_dtab_size, &rdbt, &key_lsn,
-			    DB_TXN_ABORT, txnlist);
-			if (F_ISSET(txnp, TXN_CHILDCOMMIT))
-				(void)__db_txnlist_lsnadd(dbenv,
-				    txnlist, &key_lsn, 0);
+		if ((ret = __log_c_get(logc, &key_lsn, &rdbt, DB_SET)) == 0) {
+			ret = __txn_dispatch_undo(dbenv,
+			    txnp, &rdbt, &key_lsn, txnlist);
 		}
-		if (ret == DB_SURPRISE_KID) {
-			if ((ret = __db_txnlist_lsninit(
-			    dbenv, txnlist, &key_lsn)) == 0)
-				F_SET(txnp, TXN_CHILDCOMMIT);
-		} else if (ret != 0) {
-			__db_err(txnp->mgrp->dbenv,
+
+		if (ret != 0) {
+			__db_err(dbenv,
 		    "DB_TXN->abort: Log undo failed for LSN: %lu %lu: %s",
 			    (u_long)key_lsn.file, (u_long)key_lsn.offset,
 			    db_strerror(ret));
@@ -1073,9 +1230,11 @@ __txn_undo(txnp)
 		}
 	}
 
-	ret = __db_do_the_limbo(dbenv, ptxn, txnp, txnlist);
+#ifndef HAVE_FTRUNCATE
+	ret = __db_do_the_limbo(dbenv, ptxn, txnp, txnlist, LIMBO_NORMAL);
+#endif
 
-err:	if (logc != NULL && (t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+err:	if (logc != NULL && (t_ret = __log_c_close(logc)) != 0 && ret == 0)
 		ret = t_ret;
 
 	if (ptxn == NULL && txnlist != NULL)
@@ -1084,37 +1243,25 @@ err:	if (logc != NULL && (t_ret = logc->close(logc, 0)) != 0 && ret == 0)
 }
 
 /*
- * Transaction checkpoint.
- * If either kbytes or minutes is non-zero, then we only take the checkpoint
- * more than "minutes" minutes have passed since the last checkpoint or if
- * more than "kbytes" of log data have been written since the last checkpoint.
- * When taking a checkpoint, find the oldest active transaction and figure out
- * its first LSN.  This is the lowest LSN we can checkpoint, since any record
- * written after since that point may be involved in a transaction and may
- * therefore need to be undone in the case of an abort.
+ * __txn_checkpoint_pp --
+ *	DB_ENV->txn_checkpoint pre/post processing.
  *
- * PUBLIC: int __txn_checkpoint
+ * PUBLIC: int __txn_checkpoint_pp
  * PUBLIC:     __P((DB_ENV *, u_int32_t, u_int32_t, u_int32_t));
  */
 int
-__txn_checkpoint(dbenv, kbytes, minutes, flags)
+__txn_checkpoint_pp(dbenv, kbytes, minutes, flags)
 	DB_ENV *dbenv;
 	u_int32_t kbytes, minutes, flags;
 {
-	DB_LSN ckp_lsn, last_ckp;
-	DB_TXNMGR *mgr;
-	DB_TXNREGION *region;
-	TXN_DETAIL *txnp;
-	time_t last_ckp_time, now;
-	u_int32_t bytes, mbytes;
-	int ret;
+	int rep_check, ret;
 
 	PANIC_CHECK(dbenv);
 	ENV_REQUIRES_CONFIG(dbenv,
 	    dbenv->tx_handle, "txn_checkpoint", DB_INIT_TXN);
 
 	/*
-	 * On a replication client, all transactions are read-only;  therefore,
+	 * On a replication client, all transactions are read-only; therefore,
 	 * a checkpoint is a null-op.
 	 *
 	 * We permit txn_checkpoint, instead of just rendering it illegal,
@@ -1122,11 +1269,62 @@ __txn_checkpoint(dbenv, kbytes, minutes, flags)
 	 * to operate as it gets promoted or demoted between being a
 	 * master and a client.
 	 */
-	if (F_ISSET(dbenv, DB_ENV_REP_CLIENT))
+	if (IS_REP_CLIENT(dbenv))
 		return (0);
 
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __txn_checkpoint(dbenv, kbytes, minutes, flags);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
+/*
+ * __txn_checkpoint --
+ *	DB_ENV->txn_checkpoint.
+ *
+ * PUBLIC: int __txn_checkpoint
+ * PUBLIC:	__P((DB_ENV *, u_int32_t, u_int32_t, u_int32_t));
+ */
+int
+__txn_checkpoint(dbenv, kbytes, minutes, flags)
+	DB_ENV *dbenv;
+	u_int32_t kbytes, minutes, flags;
+{
+	DB_LSN ckp_lsn, last_ckp;
+	DB_TXNMGR *mgr;
+	DB_TXNREGION *region;
+	REGENV *renv;
+	REGINFO *infop;
+	time_t last_ckp_time, now;
+	u_int32_t bytes, gen, id, logflags, mbytes;
+	int ret;
+
+	ret = gen = 0;
+	/*
+	 * A client will only call through here during recovery,
+	 * so just sync the Mpool and go home.
+	 */
+	if (IS_REP_CLIENT(dbenv)) {
+		if (MPOOL_ON(dbenv) && (ret = __memp_sync(dbenv, NULL)) != 0) {
+			__db_err(dbenv,
+		    "txn_checkpoint: failed to flush the buffer cache %s",
+			    db_strerror(ret));
+			return (ret);
+		} else
+			return (0);
+	}
+
 	mgr = dbenv->tx_handle;
 	region = mgr->reginfo.primary;
+	infop = dbenv->reginfo;
+	renv = infop->primary;
+	/*
+	 * No mutex is needed as envid is read-only once it is set.
+	 */
+	id = renv->envid;
 
 	/*
 	 * The checkpoint LSN is an LSN such that all transactions begun before
@@ -1140,6 +1338,12 @@ __txn_checkpoint(dbenv, kbytes, minutes, flags)
 		if (bytes == 0 && mbytes == 0)
 			return (0);
 
+		/*
+		 * If either kbytes or minutes is non-zero, then only take the
+		 * checkpoint if more than "minutes" minutes have passed or if
+		 * more than "kbytes" of log data have been written since the
+		 * last checkpoint.
+		 */
 		if (kbytes != 0 &&
 		    mbytes * 1024 + bytes / 1024 >= (u_int32_t)kbytes)
 			goto do_ckp;
@@ -1163,17 +1367,10 @@ __txn_checkpoint(dbenv, kbytes, minutes, flags)
 			return (0);
 	}
 
-do_ckp:	/* Look through the active transactions for the lowest begin LSN. */
-	R_LOCK(dbenv, &mgr->reginfo);
-	for (txnp = SH_TAILQ_FIRST(&region->active_txn, __txn_detail);
-	    txnp != NULL;
-	    txnp = SH_TAILQ_NEXT(txnp, links, __txn_detail))
-		if (!IS_ZERO_LSN(txnp->begin_lsn) &&
-		    log_compare(&txnp->begin_lsn, &ckp_lsn) < 0)
-			ckp_lsn = txnp->begin_lsn;
-	R_UNLOCK(dbenv, &mgr->reginfo);
+do_ckp:
+	__txn_getactive(dbenv, &ckp_lsn);
 
-	if (MPOOL_ON(dbenv) && (ret = dbenv->memp_sync(dbenv, NULL)) != 0) {
+	if (MPOOL_ON(dbenv) && (ret = __memp_sync(dbenv, NULL)) != 0) {
 		__db_err(dbenv,
 		    "txn_checkpoint: failed to flush the buffer cache %s",
 		    db_strerror(ret));
@@ -1189,6 +1386,8 @@ do_ckp:	/* Look through the active transactions for the lowest begin LSN. */
 		R_LOCK(dbenv, &mgr->reginfo);
 		last_ckp = region->last_ckp;
 		R_UNLOCK(dbenv, &mgr->reginfo);
+		if (REP_ON(dbenv))
+			__rep_get_gen(dbenv, &gen);
 
 		/*
 		 * Put out records for the open files before we log
@@ -1198,10 +1397,12 @@ do_ckp:	/* Look through the active transactions for the lowest begin LSN. */
 		 * recovery from the ckp_lsn contained in this
 		 * checkpoint.
 		 */
-		if ((ret = __dbreg_open_files(dbenv)) != 0 ||
-		    (ret = __txn_ckp_log(dbenv,
-		    NULL, &ckp_lsn, DB_PERMANENT | DB_FLUSH, &ckp_lsn,
-		    &last_ckp, (int32_t)time(NULL))) != 0) {
+		logflags = DB_LOG_PERM | DB_LOG_CHKPNT;
+		if (!IS_RECOVERING(dbenv))
+			logflags |= DB_FLUSH;
+		if ((ret = __dbreg_log_files(dbenv)) != 0 ||
+		    (ret = __txn_ckp_log(dbenv, NULL, &ckp_lsn, logflags,
+		    &ckp_lsn, &last_ckp, (int32_t)time(NULL), id, gen)) != 0) {
 			__db_err(dbenv,
 			    "txn_checkpoint: log failed at LSN [%ld %ld] %s",
 			    (long)ckp_lsn.file, (long)ckp_lsn.offset,
@@ -1211,7 +1412,44 @@ do_ckp:	/* Look through the active transactions for the lowest begin LSN. */
 
 		__txn_updateckp(dbenv, &ckp_lsn);
 	}
-	return (0);
+	return (ret);
+}
+
+/*
+ * __txn_getactive --
+ *	 Find the oldest active transaction and figure out its "begin" LSN.
+ *	 This is the lowest LSN we can checkpoint, since any record written
+ *	 after it may be involved in a transaction and may therefore need
+ *	 to be undone in the case of an abort.
+ *
+ *	 We check both the file and offset for 0 since the lsn may be in
+ *	 transition.  If it is then we don't care about this txn becuase it
+ *	 must be starting after we set the initial value of lsnp in the caller.
+ *	 All txns must initalize their begin_lsn before writing to the log.
+ *
+ * PUBLIC: void __txn_getactive __P((DB_ENV *, DB_LSN *));
+ */
+void
+__txn_getactive(dbenv, lsnp)
+	DB_ENV *dbenv;
+	DB_LSN *lsnp;
+{
+	DB_TXNMGR *mgr;
+	DB_TXNREGION *region;
+	TXN_DETAIL *txnp;
+
+	mgr = dbenv->tx_handle;
+	region = mgr->reginfo.primary;
+
+	R_LOCK(dbenv, &mgr->reginfo);
+	for (txnp = SH_TAILQ_FIRST(&region->active_txn, __txn_detail);
+	    txnp != NULL;
+	    txnp = SH_TAILQ_NEXT(txnp, links, __txn_detail))
+		if (txnp->begin_lsn.file != 0 &&
+		    txnp->begin_lsn.offset != 0 &&
+		    log_compare(&txnp->begin_lsn, lsnp) < 0)
+			*lsnp = txnp->begin_lsn;
+	R_UNLOCK(dbenv, &mgr->reginfo);
 }
 
 /*
@@ -1257,7 +1495,7 @@ __txn_activekids(dbenv, rectype, txnp)
 {
 	/*
 	 * On a child commit, we know that there are children (i.e., the
-	 * commiting child at the least.  In that case, skip this check.
+	 * committing child at the least.  In that case, skip this check.
 	 */
 	if (F_ISSET(txnp, TXN_COMPENSATE) || rectype == DB___txn_child)
 		return (0);
@@ -1283,37 +1521,34 @@ __txn_force_abort(dbenv, buffer)
 {
 	DB_CIPHER *db_cipher;
 	HDR *hdr;
-	u_int32_t offset, opcode, rec_len, rec_type, sum_len;
+	u_int32_t hdrlen, offset, opcode, sum_len;
 	u_int8_t *bp, *key, chksum[DB_MAC_KEY];
-	size_t hdrsize;
+	size_t hdrsize, rec_len;
 	int ret;
 
 	db_cipher = dbenv->crypto_handle;
 
 	/*
 	 * This routine depends on the layout of HDR and the __txn_regop
-	 * record in txn.src.  We are passed the beginning of the commit
-	 * record in the log buffer and overwrite the commit with an abort
-	 * and recalculate the checksum.  We may be passed a txn_xa_regop
-	 * that is, an XA prepare), there's no need to overwrite that one.
+	 * __txn_xa_regop records in txn.src.  We are passed the beginning
+	 * of the commit record in the log buffer and overwrite the
+	 * commit with an abort and recalculate the checksum.
 	 */
+	hdrsize = CRYPTO_ON(dbenv) ? HDR_CRYPTO_SZ : HDR_NORMAL_SZ;
+
 	hdr = (HDR *)buffer;
-	memcpy(&rec_type, hdr, sizeof(rec_type));
-	if (rec_type == DB___txn_xa_regop)
-		return (0);
+	memcpy(&hdrlen, buffer + SSZ(HDR, len), sizeof(hdr->len));
+	rec_len = hdrlen - hdrsize;
 
 	offset = sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN);
-	rec_len = offset + sizeof(u_int32_t) + sizeof(int32_t);
 	if (CRYPTO_ON(dbenv)) {
 		key = db_cipher->mac_key;
-		hdrsize = HDR_CRYPTO_SZ;
 		sum_len = DB_MAC_KEY;
 		if ((ret = db_cipher->decrypt(dbenv, db_cipher->data,
 		    &hdr->iv[0], buffer + hdrsize, rec_len)) != 0)
 			return (__db_panic(dbenv, ret));
 	} else {
 		key = NULL;
-		hdrsize = HDR_NORMAL_SZ;
 		sum_len = sizeof(u_int32_t);
 	}
 	bp = buffer + hdrsize + offset;
@@ -1326,7 +1561,7 @@ __txn_force_abort(dbenv, buffer)
 		return (__db_panic(dbenv, ret));
 
 	__db_chksum(buffer + hdrsize, rec_len, key, chksum);
-	memcpy(buffer + SSZ(HDR, chksum), &chksum, sum_len);
+	memcpy(buffer + SSZA(HDR, chksum), chksum, sum_len);
 
 	return (0);
 }
@@ -1353,8 +1588,8 @@ __txn_preclose(dbenv)
 
 	R_LOCK(dbenv, &mgr->reginfo);
 	if (region != NULL &&
-	    region->stat.st_nrestores
-	    <= mgr->n_discards && mgr->n_discards != 0)
+	    region->stat.st_nrestores <= mgr->n_discards &&
+	    mgr->n_discards != 0)
 		do_closefiles = 1;
 	R_UNLOCK(dbenv, &mgr->reginfo);
 
@@ -1414,10 +1649,10 @@ __txn_updateckp(dbenv, lsnp)
 	region = mgr->reginfo.primary;
 
 	/*
-	 * We want to make sure last_ckp only moves forward;  since
-	 * we drop locks above and in log_put, it's possible
-	 * for two calls to __txn_ckp_log to finish in a different
-	 * order from how they were called.
+	 * We want to make sure last_ckp only moves forward;  since we drop
+	 * locks above and in log_put, it's possible for two calls to
+	 * __txn_ckp_log to finish in a different order from how they were
+	 * called.
 	 */
 	R_LOCK(dbenv, &mgr->reginfo);
 	if (log_compare(&region->last_ckp, lsnp) < 0) {
@@ -1426,3 +1661,24 @@ __txn_updateckp(dbenv, lsnp)
 	}
 	R_UNLOCK(dbenv, &mgr->reginfo);
 }
+
+/*
+ * txn_set_begin_lsnp --
+ *	Set the pointer to the begin_lsn field if that field is zero.
+ */
+static void
+__txn_set_begin_lsnp(txn, rlsnp)
+	DB_TXN *txn;
+	DB_LSN **rlsnp;
+{
+	DB_LSN *lsnp;
+	TXN_DETAIL *td;
+
+	td = R_ADDR(&txn->mgrp->reginfo, txn->off);
+	while (td->parent != INVALID_ROFF)
+		td = R_ADDR(&txn->mgrp->reginfo, td->parent);
+
+	lsnp = &td->begin_lsn;
+	if (IS_ZERO_LSN(*lsnp))
+		*rlsnp = lsnp;
+}
diff --git a/storage/bdb/txn/txn.src b/storage/bdb/txn/txn.src
index 3f69b29e3ffe7dab2f1b989f3a42a45afd8bb6fe..34bd8bd0b3ef66e2d0a0f1af3af62229dc7a88c2 100644
--- a/storage/bdb/txn/txn.src
+++ b/storage/bdb/txn/txn.src
@@ -1,20 +1,29 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  *
- * $Id: txn.src,v 11.19 2002/03/27 04:33:15 bostic Exp $
+ * $Id: txn.src,v 11.33 2004/07/27 12:35:19 bostic Exp $
  */
 
 PREFIX	__txn
 DBPRIVATE
 
-INCLUDE	#include "db_config.h"
-INCLUDE
 INCLUDE #ifndef NO_SYSTEM_INCLUDES
 INCLUDE #include <sys/types.h>
 INCLUDE
+INCLUDE #if TIME_WITH_SYS_TIME
+INCLUDE #include <sys/time.h>
+INCLUDE #include <time.h>
+INCLUDE #else
+INCLUDE #if HAVE_SYS_TIME_H
+INCLUDE #include <sys/time.h>
+INCLUDE #else
+INCLUDE #include <time.h>
+INCLUDE #endif /* HAVE_SYS_TIME_H */
+INCLUDE #endif /* TIME_WITH SYS_TIME */
+INCLUDE
 INCLUDE #include <ctype.h>
 INCLUDE #include <string.h>
 INCLUDE #endif
@@ -24,8 +33,9 @@ INCLUDE #include "dbinc/crypto.h"
 INCLUDE #include "dbinc/db_page.h"
 INCLUDE #include "dbinc/db_dispatch.h"
 INCLUDE #include "dbinc/db_am.h"
+INCLUDE #include "dbinc/db_shash.h"
+INCLUDE #include "dbinc/lock.h"
 INCLUDE #include "dbinc/log.h"
-INCLUDE #include "dbinc/rep.h"
 INCLUDE #include "dbinc/txn.h"
 INCLUDE
 
@@ -36,8 +46,9 @@ INCLUDE
  * either changes the Epoch or has a 64-bit offset.
  */
 BEGIN regop		10
-ARG	opcode		u_int32_t	lu
-ARG	timestamp	int32_t		ld
+ARG	opcode		u_int32_t	ld
+TIME	timestamp	int32_t		ld
+LOCKS	locks		DBT		s
 END
 
 /*
@@ -53,11 +64,17 @@ END
  *	The previous checkpoint.
  * timestamp:
  *	See comment in commit about timestamps.
+ * envid:
+ *	Environment ID of this checkpoint.
+ * rep_gen:
+ *	Persistent replication generation number.
  */
 BEGIN ckp		11
 POINTER	ckp_lsn		DB_LSN *	lu
 POINTER	last_ckp	DB_LSN *	lu
-ARG	timestamp	int32_t		ld
+TIME	timestamp	int32_t		ld
+ARG	envid		u_int32_t	ld
+ARG	rep_gen		u_int32_t	ld
 END
 
 /*
@@ -82,6 +99,7 @@ ARG	formatID	int32_t		ld
 ARG	gtrid		u_int32_t	u
 ARG	bqual		u_int32_t	u
 POINTER	begin_lsn	DB_LSN *	lu
+LOCKS	locks		DBT		s
 END
 
 /*
diff --git a/storage/bdb/txn/txn_method.c b/storage/bdb/txn/txn_method.c
index 60fdf30583e16168034264f25069884b68c05787..c13f86dee0f2be1f68eeef832c0afe29cf1adcce 100644
--- a/storage/bdb/txn/txn_method.c
+++ b/storage/bdb/txn/txn_method.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: txn_method.c,v 11.72 2004/03/23 17:24:18 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: txn_method.c,v 11.62 2002/05/09 20:09:35 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -21,15 +19,19 @@ static const char revid[] = "$Id: txn_method.c,v 11.62 2002/05/09 20:09:35 bosti
 #include <string.h>
 #endif
 
+#ifdef HAVE_RPC
+#include "db_server.h"
+#endif
+
 #include "db_int.h"
 #include "dbinc/txn.h"
 
 #ifdef HAVE_RPC
-#include "dbinc_auto/db_server.h"
 #include "dbinc_auto/rpc_client_ext.h"
 #endif
 
-static int __txn_set_tx_max __P((DB_ENV *, u_int32_t));
+static int __txn_get_tx_max __P((DB_ENV *, u_int32_t *));
+static int __txn_get_tx_timestamp __P((DB_ENV *, time_t *));
 static int __txn_set_tx_timestamp __P((DB_ENV *, time_t *));
 
 /*
@@ -53,42 +55,75 @@ __txn_dbenv_create(dbenv)
 
 #ifdef HAVE_RPC
 	if (F_ISSET(dbenv, DB_ENV_RPCCLIENT)) {
+		dbenv->get_tx_max = __dbcl_get_tx_max;
 		dbenv->set_tx_max = __dbcl_set_tx_max;
+		dbenv->get_tx_timestamp = __dbcl_get_tx_timestamp;
 		dbenv->set_tx_timestamp = __dbcl_set_tx_timestamp;
+
 		dbenv->txn_checkpoint = __dbcl_txn_checkpoint;
 		dbenv->txn_recover = __dbcl_txn_recover;
 		dbenv->txn_stat = __dbcl_txn_stat;
+		dbenv->txn_stat_print = NULL;
 		dbenv->txn_begin = __dbcl_txn_begin;
 	} else
 #endif
 	{
+		dbenv->get_tx_max = __txn_get_tx_max;
 		dbenv->set_tx_max = __txn_set_tx_max;
+		dbenv->get_tx_timestamp = __txn_get_tx_timestamp;
 		dbenv->set_tx_timestamp = __txn_set_tx_timestamp;
-		dbenv->txn_checkpoint = __txn_checkpoint;
-#ifdef CONFIG_TEST
-		dbenv->txn_id_set = __txn_id_set;
-#endif
-		dbenv->txn_recover = __txn_recover;
-		dbenv->txn_stat = __txn_stat;
-		dbenv->txn_begin = __txn_begin;
+
+		dbenv->txn_checkpoint = __txn_checkpoint_pp;
+		dbenv->txn_recover = __txn_recover_pp;
+		dbenv->txn_stat = __txn_stat_pp;
+		dbenv->txn_stat_print = __txn_stat_print_pp;
+		dbenv->txn_begin = __txn_begin_pp;
 	}
 }
 
+static int
+__txn_get_tx_max(dbenv, tx_maxp)
+	DB_ENV *dbenv;
+	u_int32_t *tx_maxp;
+{
+	ENV_NOT_CONFIGURED(dbenv,
+	    dbenv->tx_handle, "DB_ENV->get_tx_max", DB_INIT_TXN);
+
+	if (TXN_ON(dbenv)) {
+		/* Cannot be set after open, no lock required to read. */
+		*tx_maxp = ((DB_TXNREGION *)
+		    ((DB_TXNMGR *)dbenv->tx_handle)->reginfo.primary)->maxtxns;
+	} else
+		*tx_maxp = dbenv->tx_max;
+	return (0);
+}
+
 /*
  * __txn_set_tx_max --
- *	Set the size of the transaction table.
+ *	DB_ENV->set_tx_max.
+ *
+ * PUBLIC: int __txn_set_tx_max __P((DB_ENV *, u_int32_t));
  */
-static int
+int
 __txn_set_tx_max(dbenv, tx_max)
 	DB_ENV *dbenv;
 	u_int32_t tx_max;
 {
-	ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_tx_max");
+	ENV_ILLEGAL_AFTER_OPEN(dbenv, "DB_ENV->set_tx_max");
 
 	dbenv->tx_max = tx_max;
 	return (0);
 }
 
+static int
+__txn_get_tx_timestamp(dbenv, timestamp)
+	DB_ENV *dbenv;
+	time_t *timestamp;
+{
+	*timestamp = dbenv->tx_timestamp;
+	return (0);
+}
+
 /*
  * __txn_set_tx_timestamp --
  *	Set the transaction recovery timestamp.
@@ -98,7 +133,7 @@ __txn_set_tx_timestamp(dbenv, timestamp)
 	DB_ENV *dbenv;
 	time_t *timestamp;
 {
-	ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_tx_timestamp");
+	ENV_ILLEGAL_AFTER_OPEN(dbenv, "DB_ENV->set_tx_timestamp");
 
 	dbenv->tx_timestamp = *timestamp;
 	return (0);
diff --git a/storage/bdb/txn/txn_rec.c b/storage/bdb/txn/txn_rec.c
index 69af6a1f907ab4bd8a57bee7eef305e41b33017b..ea885528f82a900f32fc14e43dbc5c0edfb2d9a3 100644
--- a/storage/bdb/txn/txn_rec.c
+++ b/storage/bdb/txn/txn_rec.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -31,14 +31,12 @@
  * 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.
+ *
+ * $Id: txn_rec.c,v 11.64 2004/09/22 17:41:10 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: txn_rec.c,v 11.41 2002/08/06 04:42:37 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -49,9 +47,6 @@ static const char revid[] = "$Id: txn_rec.c,v 11.41 2002/08/06 04:42:37 bostic E
 #include "dbinc/db_page.h"
 #include "dbinc/txn.h"
 #include "dbinc/db_am.h"
-#include "dbinc/db_dispatch.h"
-
-#define	IS_XA_TXN(R) (R->xid.size != 0)
 
 /*
  * PUBLIC: int __txn_regop_recover
@@ -59,7 +54,7 @@ static const char revid[] = "$Id: txn_rec.c,v 11.41 2002/08/06 04:42:37 bostic E
  *
  * These records are only ever written for commits.  Normally, we redo any
  * committed transaction, however if we are doing recovery to a timestamp, then
- * we may treat transactions that commited after the timestamp as aborted.
+ * we may treat transactions that committed after the timestamp as aborted.
  */
 int
 __txn_regop_recover(dbenv, dbtp, lsnp, op, info)
@@ -72,6 +67,7 @@ __txn_regop_recover(dbenv, dbtp, lsnp, op, info)
 	DB_TXNHEAD *headp;
 	__txn_regop_args *argp;
 	int ret;
+	u_int32_t status;
 
 #ifdef DEBUG_RECOVER
 	(void)__txn_regop_print(dbenv, dbtp, lsnp, op, info);
@@ -87,14 +83,16 @@ __txn_regop_recover(dbenv, dbtp, lsnp, op, info)
 	 * apply to the BACKWARD_ROLL case.
 	 */
 
-	if (op == DB_TXN_FORWARD_ROLL)
+	if (op == DB_TXN_FORWARD_ROLL) {
 		/*
 		 * If this was a 2-phase-commit transaction, then it
 		 * might already have been removed from the list, and
 		 * that's OK.  Ignore the return code from remove.
 		 */
-		(void)__db_txnlist_remove(dbenv, info, argp->txnid->txnid);
-	else if ((dbenv->tx_timestamp != 0 &&
+		if ((ret = __db_txnlist_remove(dbenv,
+		    info, argp->txnid->txnid)) != DB_NOTFOUND && ret != 0)
+			goto err;
+	} else if ((dbenv->tx_timestamp != 0 &&
 	    argp->timestamp > (int32_t)dbenv->tx_timestamp) ||
 	    (!IS_ZERO_LSN(headp->trunc_lsn) &&
 	    log_compare(&headp->trunc_lsn, lsnp) < 0)) {
@@ -102,28 +100,24 @@ __txn_regop_recover(dbenv, dbtp, lsnp, op, info)
 		 * We failed either the timestamp check or the trunc_lsn check,
 		 * so we treat this as an abort even if it was a commit record.
 		 */
-		ret = __db_txnlist_update(dbenv,
-		    info, argp->txnid->txnid, TXN_ABORT, NULL);
-
-		if (ret == TXN_NOTFOUND)
-			ret = __db_txnlist_add(dbenv,
-			    info, argp->txnid->txnid, TXN_IGNORE, NULL);
-		else if (ret != TXN_OK)
+		if ((ret = __db_txnlist_update(dbenv, info,
+		    argp->txnid->txnid, TXN_ABORT, NULL, &status, 1)) != 0)
+			goto err;
+		else if (status != TXN_IGNORE && status != TXN_OK)
 			goto err;
-		/* else ret = 0; Not necessary because TXN_OK == 0 */
 	} else {
 		/* This is a normal commit; mark it appropriately. */
-		ret = __db_txnlist_update(dbenv,
-		    info, argp->txnid->txnid, argp->opcode, lsnp);
-
-		if (ret == TXN_NOTFOUND)
-			ret = __db_txnlist_add(dbenv,
+		if ((ret = __db_txnlist_update(dbenv,
+		    info, argp->txnid->txnid, argp->opcode, lsnp,
+		    &status, 0)) == DB_NOTFOUND) {
+			if ((ret = __db_txnlist_add(dbenv,
 			    info, argp->txnid->txnid,
 			    argp->opcode == TXN_ABORT ?
-			    TXN_IGNORE : argp->opcode, lsnp);
-		else if (ret != TXN_OK)
+			    TXN_IGNORE : argp->opcode, lsnp)) != 0)
+				goto err;
+		} else if (ret != 0 ||
+		    (status != TXN_IGNORE && status != TXN_OK))
 			goto err;
-		/* else ret = 0; Not necessary because TXN_OK == 0 */
 	}
 
 	if (ret == 0)
@@ -132,7 +126,7 @@ __txn_regop_recover(dbenv, dbtp, lsnp, op, info)
 	if (0) {
 err:		__db_err(dbenv,
 		    "txnid %lx commit record found, already on commit list",
-		    argp->txnid->txnid);
+		    (u_long)argp->txnid->txnid);
 		ret = EINVAL;
 	}
 	__os_free(dbenv, argp);
@@ -156,6 +150,7 @@ __txn_xa_regop_recover(dbenv, dbtp, lsnp, op, info)
 {
 	__txn_xa_regop_args *argp;
 	int ret;
+	u_int32_t status;
 
 #ifdef DEBUG_RECOVER
 	(void)__txn_xa_regop_print(dbenv, dbtp, lsnp, op, info);
@@ -164,12 +159,19 @@ __txn_xa_regop_recover(dbenv, dbtp, lsnp, op, info)
 	if ((ret = __txn_xa_regop_read(dbenv, dbtp->data, &argp)) != 0)
 		return (ret);
 
-	if (argp->opcode != TXN_PREPARE) {
+	if (argp->opcode != TXN_PREPARE && argp->opcode != TXN_ABORT) {
 		ret = EINVAL;
 		goto err;
 	}
 
-	ret = __db_txnlist_find(dbenv, info, argp->txnid->txnid);
+	/*
+	 * The return value here is either a DB_NOTFOUND or it is
+	 * the transaction status from the list.  It is not a normal
+	 * error return, so we must make sure that in each of the
+	 * cases below, we overwrite the ret value so we return
+	 * appropriately.
+	 */
+	ret = __db_txnlist_find(dbenv, info, argp->txnid->txnid, &status);
 
 	/*
 	 * If we are rolling forward, then an aborted prepare
@@ -180,26 +182,37 @@ __txn_xa_regop_recover(dbenv, dbtp, lsnp, op, info)
 
 	if (op == DB_TXN_FORWARD_ROLL) {
 		if ((ret = __db_txnlist_remove(dbenv,
-		    info, argp->txnid->txnid)) != TXN_OK)
+		    info, argp->txnid->txnid)) != 0)
 			goto txn_err;
-	} else if (op == DB_TXN_BACKWARD_ROLL && ret == TXN_PREPARE) {
+	} else if (op == DB_TXN_BACKWARD_ROLL && status == TXN_PREPARE) {
 		/*
-		 * On the backward pass, we have three possibilities:
+		 * On the backward pass, we have four possibilities:
 		 * 1. The transaction is already committed, no-op.
 		 * 2. The transaction is already aborted, no-op.
-		 * 3. The transaction is neither committed nor aborted.
+		 * 3. The prepare failed and was aborted, mark as abort.
+		 * 4. The transaction is neither committed nor aborted.
 		 *	 Treat this like a commit and roll forward so that
 		 *	 the transaction can be resurrected in the region.
-		 * We handle case 3 here; cases 1 and 2 are the final clause
-		 * below.
+		 * We handle cases 3 and 4 here; cases 1 and 2
+		 * are the final clause below.
+		 */
+		if (argp->opcode == TXN_ABORT) {
+			if ((ret = __db_txnlist_update(dbenv,
+			     info, argp->txnid->txnid,
+			     TXN_ABORT, NULL, &status, 0)) != 0 &&
+			     status != TXN_PREPARE)
+				goto txn_err;
+			ret = 0;
+		}
+		/*
 		 * This is prepared, but not yet committed transaction.  We
 		 * need to add it to the transaction list, so that it gets
 		 * rolled forward. We also have to add it to the region's
 		 * internal state so it can be properly aborted or committed
 		 * after recovery (see txn_recover).
 		 */
-		if ((ret = __db_txnlist_remove(dbenv,
-		   info, argp->txnid->txnid)) != TXN_OK) {
+		else if ((ret = __db_txnlist_remove(dbenv,
+		    info, argp->txnid->txnid)) != 0) {
 txn_err:		__db_err(dbenv,
 			    "Transaction not in list %x", argp->txnid->txnid);
 			ret = DB_NOTFOUND;
@@ -229,20 +242,30 @@ __txn_ckp_recover(dbenv, dbtp, lsnp, op, info)
 	db_recops op;
 	void *info;
 {
+	DB_REP *db_rep;
+	REP *rep;
 	__txn_ckp_args *argp;
 	int ret;
 
 #ifdef DEBUG_RECOVER
 	__txn_ckp_print(dbenv, dbtp, lsnp, op, info);
 #endif
-	COMPQUIET(dbenv, NULL);
-
 	if ((ret = __txn_ckp_read(dbenv, dbtp->data, &argp)) != 0)
 		return (ret);
 
 	if (op == DB_TXN_BACKWARD_ROLL)
 		__db_txnlist_ckp(dbenv, info, lsnp);
 
+	if (op == DB_TXN_FORWARD_ROLL) {
+		/* Record the max generation number that we've seen. */
+		if (REP_ON(dbenv)) {
+			db_rep = dbenv->rep_handle;
+			rep = db_rep->region;
+			if (argp->rep_gen > rep->recover_gen)
+				rep->recover_gen = argp->rep_gen;
+		}
+	}
+
 	*lsnp = argp->last_ckp;
 	__os_free(dbenv, argp);
 	return (DB_TXN_CKP);
@@ -264,7 +287,8 @@ __txn_child_recover(dbenv, dbtp, lsnp, op, info)
 	void *info;
 {
 	__txn_child_args *argp;
-	int c_stat, p_stat, ret;
+	int ret, t_ret;
+	u_int32_t c_stat, p_stat, tmpstat;
 
 #ifdef DEBUG_RECOVER
 	(void)__txn_child_print(dbenv, dbtp, lsnp, op, info);
@@ -274,9 +298,9 @@ __txn_child_recover(dbenv, dbtp, lsnp, op, info)
 
 	/*
 	 * This is a record in a PARENT's log trail indicating that a
-	 * child commited.  If we are aborting, we need to update the
+	 * child committed.  If we are aborting, we need to update the
 	 * parent's LSN array.  If we are in recovery, then if the
-	 * parent is commiting, we set ourselves up to commit, else
+	 * parent is committing, we set ourselves up to commit, else
 	 * we do nothing.
 	 */
 	if (op == DB_TXN_ABORT) {
@@ -287,21 +311,50 @@ __txn_child_recover(dbenv, dbtp, lsnp, op, info)
 		    info, &argp->c_lsn, TXNLIST_NEW);
 	} else if (op == DB_TXN_BACKWARD_ROLL) {
 		/* Child might exist -- look for it. */
-		c_stat = __db_txnlist_find(dbenv, info, argp->child);
-		p_stat = __db_txnlist_find(dbenv, info, argp->txnid->txnid);
+		ret = __db_txnlist_find(dbenv, info, argp->child, &c_stat);
+		t_ret =
+		    __db_txnlist_find(dbenv, info, argp->txnid->txnid, &p_stat);
+		if (ret != 0 && ret != DB_NOTFOUND)
+			goto out;
+		if (t_ret != 0 && t_ret != DB_NOTFOUND) {
+			ret = t_ret;
+			goto out;
+		}
+		/*
+		 * If the parent is in state COMMIT or IGNORE, then we apply
+		 * that to the child, else we need to abort the child.
+		 */
 
-		if (c_stat == TXN_EXPECTED) {
+		if (ret == DB_NOTFOUND  ||
+		    c_stat == TXN_OK || c_stat == TXN_COMMIT) {
+			if (t_ret == DB_NOTFOUND ||
+			     (p_stat != TXN_COMMIT  && p_stat != TXN_IGNORE))
+				c_stat = TXN_ABORT;
+			else
+				c_stat = p_stat;
+
+			if (ret == DB_NOTFOUND)
+				ret = __db_txnlist_add(dbenv,
+				     info, argp->child, c_stat, NULL);
+			else
+				ret = __db_txnlist_update(dbenv, info,
+				     argp->child, c_stat, NULL, &tmpstat, 0);
+		} else if (c_stat == TXN_EXPECTED) {
 			/*
 			 * The open after this create succeeded.  If the
 			 * parent succeeded, we don't want to redo; if the
 			 * parent aborted, we do want to undo.
 			 */
+			switch (p_stat) {
+			case TXN_COMMIT:
+			case TXN_IGNORE:
+				c_stat = TXN_IGNORE;
+				break;
+			default:
+				c_stat = TXN_ABORT;
+			}
 			ret = __db_txnlist_update(dbenv,
-			    info, argp->child,
-			    p_stat == TXN_COMMIT ? TXN_IGNORE : TXN_ABORT,
-			    NULL);
-			if (ret > 0)
-				ret = 0;
+			    info, argp->child, c_stat, NULL, &tmpstat, 0);
 		} else if (c_stat == TXN_UNEXPECTED) {
 			/*
 			 * The open after this create failed.  If the parent
@@ -312,28 +365,30 @@ __txn_child_recover(dbenv, dbtp, lsnp, op, info)
 			 */
 			ret = __db_txnlist_update(dbenv, info, argp->child,
 			    p_stat == TXN_COMMIT ? TXN_COMMIT : TXN_IGNORE,
-			    NULL);
-			if (ret > 0)
-				ret = 0;
-		} else if (c_stat != TXN_IGNORE) {
-			ret = __db_txnlist_add(dbenv, info, argp->child,
-			    p_stat == TXN_COMMIT ? TXN_COMMIT : TXN_ABORT,
-			    NULL);
+			    NULL, &tmpstat, 0);
 		}
-	} else {
+	} else if (op == DB_TXN_OPENFILES) {
+		/*
+		 * If we have a partial subtransaction, then the whole
+		 * transaction should be ignored.
+		 */
+		if ((ret = __db_txnlist_find(dbenv,
+		    info, argp->child, &c_stat)) == DB_NOTFOUND)
+			ret = __db_txnlist_update(dbenv, info,
+			     argp->txnid->txnid, TXN_IGNORE,
+			     NULL, &p_stat, 1);
+	} else if (DB_REDO(op)) {
 		/* Forward Roll */
 		if ((ret =
-		    __db_txnlist_remove(dbenv, info, argp->child)) != TXN_OK) {
+		    __db_txnlist_remove(dbenv, info, argp->child)) != 0)
 			__db_err(dbenv,
-			    "Transaction not in list %x", argp->txnid->txnid);
-			ret = DB_NOTFOUND;
-		}
+			    "Transaction not in list %x", argp->child);
 	}
 
 	if (ret == 0)
 		*lsnp = argp->prev_lsn;
 
-	__os_free(dbenv, argp);
+out:	__os_free(dbenv, argp);
 
 	return (ret);
 }
@@ -346,7 +401,7 @@ __txn_child_recover(dbenv, dbtp, lsnp, op, info)
  * or commit and we need to respond correctly.
  *
  * lsnp is the LSN of the returned LSN
- * argp is the perpare record (in an appropriate structure)
+ * argp is the prepare record (in an appropriate structure)
  *
  * PUBLIC: int __txn_restore_txn __P((DB_ENV *,
  * PUBLIC:     DB_LSN *, __txn_xa_regop_args *));
@@ -363,7 +418,7 @@ __txn_restore_txn(dbenv, lsnp, argp)
 	int ret;
 
 	if (argp->xid.size == 0)
-	return (0);
+		return (0);
 
 	mgr = dbenv->tx_handle;
 	region = mgr->reginfo.primary;
@@ -371,7 +426,7 @@ __txn_restore_txn(dbenv, lsnp, argp)
 
 	/* Allocate a new transaction detail structure. */
 	if ((ret =
-	    __db_shalloc(mgr->reginfo.addr, sizeof(TXN_DETAIL), 0, &td)) != 0) {
+	    __db_shalloc(&mgr->reginfo, sizeof(TXN_DETAIL), 0, &td)) != 0) {
 		R_UNLOCK(dbenv, &mgr->reginfo);
 		return (ret);
 	}
@@ -390,7 +445,7 @@ __txn_restore_txn(dbenv, lsnp, argp)
 	td->gtrid = argp->gtrid;
 	td->format = argp->formatID;
 	td->flags = 0;
-	F_SET(td, TXN_RESTORED);
+	F_SET(td, TXN_DTL_RESTORED);
 
 	region->stat.st_nrestores++;
 	region->stat.st_nactive++;
diff --git a/storage/bdb/txn/txn_recover.c b/storage/bdb/txn/txn_recover.c
index 732a82e50301375697f470a185eecf107bd3a286..79b88b72744ea613bf9672fe9f6cdbdde1b32ed4 100644
--- a/storage/bdb/txn/txn_recover.c
+++ b/storage/bdb/txn/txn_recover.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
+ * Copyright (c) 2001-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: txn_recover.c,v 1.54 2004/10/15 16:59:44 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: txn_recover.c,v 1.36 2002/08/19 16:59:15 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -20,6 +18,7 @@ static const char revid[] = "$Id: txn_recover.c,v 1.36 2002/08/19 16:59:15 bosti
 #include "db_int.h"
 #include "dbinc/txn.h"
 #include "dbinc/db_page.h"
+#include "dbinc/db_dispatch.h"
 #include "dbinc/log.h"
 #include "dbinc_auto/db_auto.h"
 #include "dbinc_auto/crdel_auto.h"
@@ -55,6 +54,8 @@ __txn_continue(env, txnp, td, off)
 	txnp->prepare = __txn_prepare;
 
 	txnp->flags = 0;
+	if (F_ISSET(td, TXN_DTL_RESTORED))
+		F_SET(txnp, TXN_RESTORED);
 }
 
 /*
@@ -62,14 +63,14 @@ __txn_continue(env, txnp, td, off)
  *	Return the txn that corresponds to this global ID.
  *
  * PUBLIC: int __txn_map_gid __P((DB_ENV *,
- * PUBLIC:     u_int8_t *, TXN_DETAIL **, size_t *));
+ * PUBLIC:     u_int8_t *, TXN_DETAIL **, roff_t *));
  */
 int
 __txn_map_gid(dbenv, gid, tdp, offp)
 	DB_ENV *dbenv;
 	u_int8_t *gid;
 	TXN_DETAIL **tdp;
-	size_t *offp;
+	roff_t *offp;
 {
 	DB_TXNMGR *mgr;
 	DB_TXNREGION *tmr;
@@ -98,21 +99,21 @@ __txn_map_gid(dbenv, gid, tdp, offp)
 }
 
 /*
- * __txn_recover --
- *	Public interface to retrieve the list of prepared, but not yet
- * commited transactions.  See __txn_get_prepared for details.  This
- * function and __db_xa_recover both wrap that one.
+ * __txn_recover_pp --
+ *	DB_ENV->txn_recover pre/post processing.
  *
- * PUBLIC: int __txn_recover
+ * PUBLIC: int __txn_recover_pp
  * PUBLIC:     __P((DB_ENV *, DB_PREPLIST *, long, long *, u_int32_t));
  */
 int
-__txn_recover(dbenv, preplist, count, retp, flags)
+__txn_recover_pp(dbenv, preplist, count, retp, flags)
 	DB_ENV *dbenv;
 	DB_PREPLIST *preplist;
 	long count, *retp;
 	u_int32_t flags;
 {
+	int rep_check, ret;
+
 	PANIC_CHECK(dbenv);
 	ENV_REQUIRES_CONFIG(
 	    dbenv, dbenv->tx_handle, "txn_recover", DB_INIT_TXN);
@@ -123,6 +124,35 @@ __txn_recover(dbenv, preplist, count, retp, flags)
 		__db_err(dbenv, "operation not permitted while in recovery");
 		return (EINVAL);
 	}
+
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __txn_recover(dbenv, preplist, count, retp, flags);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
+/*
+ * __txn_recover --
+ *	DB_ENV->txn_recover.
+ *
+ * PUBLIC: int __txn_recover
+ * PUBLIC:         __P((DB_ENV *, DB_PREPLIST *, long, long *, u_int32_t));
+ */
+int
+__txn_recover(dbenv, preplist, count, retp, flags)
+	DB_ENV *dbenv;
+	DB_PREPLIST *preplist;
+	long count, *retp;
+	u_int32_t flags;
+{
+	/*
+	 * Public API to retrieve the list of prepared, but not yet committed
+	 * transactions.  See __txn_get_prepared for details.  This function
+	 * and __db_xa_recover both wrap that one.
+	 */
 	return (__txn_get_prepared(dbenv, NULL, preplist, count, retp, flags));
 }
 
@@ -148,22 +178,17 @@ __txn_get_prepared(dbenv, xids, txns, count, retp, flags)
 	long  *retp;
 	u_int32_t flags;
 {
-	DBT data;
-	DB_LOGC *logc;
-	DB_LSN min, open_lsn;
+	DB_LSN min;
 	DB_PREPLIST *prepp;
 	DB_TXNMGR *mgr;
 	DB_TXNREGION *tmr;
 	TXN_DETAIL *td;
 	XID *xidp;
-	__txn_ckp_args *ckp_args;
 	long i;
-	int nrestores, open_files, ret, t_ret;
-	void *txninfo;
+	int nrestores, open_files, ret;
 
 	*retp = 0;
 
-	logc = NULL;
 	MAX_LSN(min);
 	prepp = txns;
 	xidp = xids;
@@ -193,11 +218,11 @@ __txn_get_prepared(dbenv, xids, txns, count, retp, flags)
 		for (td = SH_TAILQ_FIRST(&tmr->active_txn, __txn_detail);
 		    td != NULL;
 		    td = SH_TAILQ_NEXT(td, links, __txn_detail)) {
-			if (F_ISSET(td, TXN_RESTORED))
+			if (F_ISSET(td, TXN_DTL_RESTORED))
 				nrestores++;
-			if (F_ISSET(td, TXN_COLLECTED))
+			if (F_ISSET(td, TXN_DTL_COLLECTED))
 				open_files = 0;
-			F_CLR(td, TXN_COLLECTED);
+			F_CLR(td, TXN_DTL_COLLECTED);
 		}
 		mgr->n_discards = 0;
 	} else
@@ -207,21 +232,29 @@ __txn_get_prepared(dbenv, xids, txns, count, retp, flags)
 	for (td = SH_TAILQ_FIRST(&tmr->active_txn, __txn_detail);
 	    td != NULL && *retp < count;
 	    td = SH_TAILQ_NEXT(td, links, __txn_detail)) {
-		if (td->status != TXN_PREPARED || F_ISSET(td, TXN_COLLECTED))
+		if (td->status != TXN_PREPARED ||
+		    F_ISSET(td, TXN_DTL_COLLECTED))
 			continue;
 
 		if (xids != NULL) {
 			xidp->formatID = td->format;
-			xidp->gtrid_length = td->gtrid;
-			xidp->bqual_length = td->bqual;
+			/*
+			 * XID structure uses longs; we use u_int32_t's as we
+			 * log them to disk.  Cast them to make the conversion
+			 * explicit.
+			 */
+			xidp->gtrid_length = (long)td->gtrid;
+			xidp->bqual_length = (long)td->bqual;
 			memcpy(xidp->data, td->xid, sizeof(td->xid));
 			xidp++;
 		}
 
 		if (txns != NULL) {
 			if ((ret = __os_calloc(dbenv,
-			    1, sizeof(DB_TXN), &prepp->txn)) != 0)
+			    1, sizeof(DB_TXN), &prepp->txn)) != 0) {
+				R_UNLOCK(dbenv, &mgr->reginfo);
 				goto err;
+			}
 			__txn_continue(dbenv,
 			    prepp->txn, td, R_OFFSET(&mgr->reginfo, td));
 			F_SET(prepp->txn, TXN_MALLOC);
@@ -229,11 +262,12 @@ __txn_get_prepared(dbenv, xids, txns, count, retp, flags)
 			prepp++;
 		}
 
-		if (log_compare(&td->begin_lsn, &min) < 0)
+		if (!IS_ZERO_LSN(td->begin_lsn) &&
+		    log_compare(&td->begin_lsn, &min) < 0)
 			min = td->begin_lsn;
 
 		(*retp)++;
-		F_SET(td, TXN_COLLECTED);
+		F_SET(td, TXN_DTL_COLLECTED);
 	}
 	R_UNLOCK(dbenv, &mgr->reginfo);
 
@@ -248,59 +282,96 @@ __txn_get_prepared(dbenv, xids, txns, count, retp, flags)
 	}
 
 	if (open_files && nrestores && *retp != 0 && !IS_MAX_LSN(min)) {
-		/*
-		 * Figure out the last checkpoint before the smallest
-		 * start_lsn in the region.
-		 */
 		F_SET((DB_LOG *)dbenv->lg_handle, DBLOG_RECOVER);
+		ret = __txn_openfiles(dbenv, &min, 0);
+		F_CLR((DB_LOG *)dbenv->lg_handle, DBLOG_RECOVER);
+	}
+err:
+	return (ret);
+}
+
+/*
+ * __txn_openfiles --
+ *	Call env_openfiles.
+ *
+ * PUBLIC: int __txn_openfiles __P((DB_ENV *, DB_LSN *, int));
+ */
+int
+__txn_openfiles(dbenv, min, force)
+	DB_ENV *dbenv;
+	DB_LSN *min;
+	int force;
+{
+	DBT data;
+	DB_LOGC *logc;
+	DB_LSN open_lsn;
+	__txn_ckp_args *ckp_args;
+	int ret, t_ret;
+	void *txninfo;
 
-		if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
-			goto err;
-
-		memset(&data, 0, sizeof(data));
-		if ((ret = __txn_getckp(dbenv, &open_lsn)) == 0)
-			while (!IS_ZERO_LSN(open_lsn) && (ret =
-			    logc->get(logc, &open_lsn, &data, DB_SET)) == 0 &&
-			    log_compare(&min, &open_lsn) < 0) {
-				/* Format the log record. */
-				if ((ret = __txn_ckp_read(dbenv,
-				    data.data, &ckp_args)) != 0) {
-					__db_err(dbenv,
-				    "Invalid checkpoint record at [%lu][%lu]",
-					    (u_long)open_lsn.file,
-					    (u_long)open_lsn.offset);
+	/*
+	 * Figure out the last checkpoint before the smallest
+	 * start_lsn in the region.
+	 */
+	logc = NULL;
+	if ((ret = __log_cursor(dbenv, &logc)) != 0)
+		goto err;
+
+	memset(&data, 0, sizeof(data));
+	if ((ret = __txn_getckp(dbenv, &open_lsn)) == 0)
+		while (!IS_ZERO_LSN(open_lsn) && (ret =
+		    __log_c_get(logc, &open_lsn, &data, DB_SET)) == 0 &&
+		    (force ||
+		    (min != NULL && log_compare(min, &open_lsn) < 0))) {
+			/* Format the log record. */
+			if ((ret = __txn_ckp_read(dbenv,
+			    data.data, &ckp_args)) != 0) {
+				__db_err(dbenv,
+			    "Invalid checkpoint record at [%lu][%lu]",
+				    (u_long)open_lsn.file,
+				    (u_long)open_lsn.offset);
+				goto err;
+			}
+			/*
+			 * If force is set, then we're forcing ourselves
+			 * to go back far enough to open files.
+			 * Use ckp_lsn and then break out of the loop.
+			 */
+			open_lsn = force ? ckp_args->ckp_lsn :
+			    ckp_args->last_ckp;
+			__os_free(dbenv, ckp_args);
+			if (force) {
+				if ((ret = __log_c_get(logc, &open_lsn,
+				    &data, DB_SET)) != 0)
 					goto err;
-				}
-				open_lsn = ckp_args->last_ckp;
-				__os_free(dbenv, ckp_args);
+				break;
 			}
-
-		/*
-		 * There are three ways by which we may have gotten here.
-		 * - We got a DB_NOTFOUND -- we need to read the first
-		 *	log record.
-		 * - We found a checkpoint before min.  We're done.
-		 * - We found a checkpoint after min who's last_ckp is 0.  We
-		 *	need to start at the beginning of the log.
-		 */
-		if ((ret == DB_NOTFOUND || IS_ZERO_LSN(open_lsn)) &&
-		    (ret = logc->get(logc, &open_lsn, &data, DB_FIRST)) != 0) {
-			__db_err(dbenv, "No log records");
-			goto err;
 		}
 
-		if ((ret = __db_txnlist_init(dbenv, 0, 0, NULL, &txninfo)) != 0)
-			goto err;
-		ret = __env_openfiles(dbenv, logc,
-		    txninfo, &data, &open_lsn, NULL, 0, 0);
-		if (txninfo != NULL)
-			__db_txnlist_end(dbenv, txninfo);
+	/*
+	 * There are several ways by which we may have gotten here.
+	 * - We got a DB_NOTFOUND -- we need to read the first
+	 *	log record.
+	 * - We found a checkpoint before min.  We're done.
+	 * - We found a checkpoint after min who's last_ckp is 0.  We
+	 *	need to start at the beginning of the log.
+	 * - We are forcing an openfiles and we have our ckp_lsn.
+	 */
+	if ((ret == DB_NOTFOUND || IS_ZERO_LSN(open_lsn)) && (ret =
+	    __log_c_get(logc, &open_lsn, &data, DB_FIRST)) != 0) {
+		__db_err(dbenv, "No log records");
+		goto err;
 	}
 
-err:	F_CLR((DB_LOG *)dbenv->lg_handle, DBLOG_RECOVER);
+	if ((ret = __db_txnlist_init(dbenv, 0, 0, NULL, &txninfo)) != 0)
+		goto err;
+	ret = __env_openfiles(dbenv, logc,
+	    txninfo, &data, &open_lsn, NULL, 0, 0);
+	if (txninfo != NULL)
+		__db_txnlist_end(dbenv, txninfo);
 
-	if (logc != NULL && (t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+err:
+	if (logc != NULL && (t_ret = __log_c_close(logc)) != 0 && ret == 0)
 		ret = t_ret;
-
 	return (ret);
 }
diff --git a/storage/bdb/txn/txn_region.c b/storage/bdb/txn/txn_region.c
index bf72d4f1d2c178ebcd9c55ce38d56043be9f9592..82d4543af8994616153473f50aa04568adfc6d7e 100644
--- a/storage/bdb/txn/txn_region.c
+++ b/storage/bdb/txn/txn_region.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: txn_region.c,v 11.87 2004/10/15 16:59:44 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: txn_region.c,v 11.73 2002/08/06 04:42:37 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -32,7 +30,6 @@ static const char revid[] = "$Id: txn_region.c,v 11.73 2002/08/06 04:42:37 bosti
 #include "dbinc/log.h"
 #include "dbinc/txn.h"
 
-static int __txn_findlastckp __P((DB_ENV *, DB_LSN *));
 static int __txn_init __P((DB_ENV *, DB_TXNMGR *));
 static size_t __txn_region_size __P((DB_ENV *));
 
@@ -56,9 +53,9 @@ __txn_open(dbenv)
 	tmgrp->dbenv = dbenv;
 
 	/* Join/create the txn region. */
+	tmgrp->reginfo.dbenv = dbenv;
 	tmgrp->reginfo.type = REGION_TYPE_TXN;
 	tmgrp->reginfo.id = INVALID_REGION_ID;
-	tmgrp->reginfo.mode = dbenv->db_mode;
 	tmgrp->reginfo.flags = REGION_JOIN_OK;
 	if (F_ISSET(dbenv, DB_ENV_CREATE))
 		F_SET(&tmgrp->reginfo, REGION_CREATE_OK);
@@ -131,11 +128,11 @@ __txn_init(dbenv, tmgrp)
 		 * the last log file until we find the last checkpoint.
 		 */
 		if (IS_ZERO_LSN(last_ckp) &&
-		    (ret = __txn_findlastckp(dbenv, &last_ckp)) != 0)
+		    (ret = __txn_findlastckp(dbenv, &last_ckp, NULL)) != 0)
 			return (ret);
 	}
 
-	if ((ret = __db_shalloc(tmgrp->reginfo.addr,
+	if ((ret = __db_shalloc(&tmgrp->reginfo,
 	    sizeof(DB_TXNREGION), 0, &tmgrp->reginfo.primary)) != 0) {
 		__db_err(dbenv,
 		    "Unable to allocate memory for the transaction region");
@@ -152,20 +149,13 @@ __txn_init(dbenv, tmgrp)
 	region->last_ckp = last_ckp;
 	region->time_ckp = time(NULL);
 
-	/*
-	 * XXX
-	 * If we ever do more types of locking and logging, this changes.
-	 */
-	region->logtype = 0;
-	region->locktype = 0;
-
 	memset(&region->stat, 0, sizeof(region->stat));
 	region->stat.st_maxtxns = region->maxtxns;
 
 	SH_TAILQ_INIT(&region->active_txn);
 #ifdef	HAVE_MUTEX_SYSTEM_RESOURCES
 	/* Allocate room for the txn maintenance info and initialize it. */
-	if ((ret = __db_shalloc(tmgrp->reginfo.addr,
+	if ((ret = __db_shalloc(&tmgrp->reginfo,
 	    sizeof(REGMAINT) + TXN_MAINT_SIZE, 0, &addr)) != 0) {
 		__db_err(dbenv,
 		    "Unable to allocate memory for mutex maintenance");
@@ -180,13 +170,16 @@ __txn_init(dbenv, tmgrp)
 /*
  * __txn_findlastckp --
  *	Find the last checkpoint in the log, walking backwards from the
- *	beginning of the last log file.  (The log system looked through
- *	the last log file when it started up.)
+ *	max_lsn given or the beginning of the last log file.  (The
+ *	log system looked through the last log file when it started up.)
+ *
+ * PUBLIC: int __txn_findlastckp __P((DB_ENV *, DB_LSN *, DB_LSN *));
  */
-static int
-__txn_findlastckp(dbenv, lsnp)
+int
+__txn_findlastckp(dbenv, lsnp, max_lsn)
 	DB_ENV *dbenv;
 	DB_LSN *lsnp;
+	DB_LSN *max_lsn;
 {
 	DB_LOGC *logc;
 	DB_LSN lsn;
@@ -194,23 +187,30 @@ __txn_findlastckp(dbenv, lsnp)
 	int ret, t_ret;
 	u_int32_t rectype;
 
-	if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)
+	if ((ret = __log_cursor(dbenv, &logc)) != 0)
 		return (ret);
 
 	/* Get the last LSN. */
 	memset(&dbt, 0, sizeof(dbt));
-	if ((ret = logc->get(logc, &lsn, &dbt, DB_LAST)) != 0)
-		goto err;
-
-	/*
-	 * Twiddle the last LSN so it points to the beginning of the last
-	 * file;  we know there's no checkpoint after that, since the log
-	 * system already looked there.
-	 */
-	lsn.offset = 0;
+	if (max_lsn != NULL) {
+		lsn = *max_lsn;
+		ZERO_LSN(*lsnp);
+		if ((ret = __log_c_get(logc, &lsn, &dbt, DB_SET)) != 0)
+			goto err;
+	} else {
+		if ((ret = __log_c_get(logc, &lsn, &dbt, DB_LAST)) != 0)
+			goto err;
+		/*
+		 * Twiddle the last LSN so it points to the
+		 * beginning of the last file;  we know there's
+		 * no checkpoint after that, since the log
+		 * system already looked there.
+		 */
+		lsn.offset = 0;
+	}
 
 	/* Read backwards, looking for checkpoints. */
-	while ((ret = logc->get(logc, &lsn, &dbt, DB_PREV)) == 0) {
+	while ((ret = __log_c_get(logc, &lsn, &dbt, DB_PREV)) == 0) {
 		if (dbt.size < sizeof(u_int32_t))
 			continue;
 		memcpy(&rectype, dbt.data, sizeof(u_int32_t));
@@ -220,7 +220,7 @@ __txn_findlastckp(dbenv, lsnp)
 		}
 	}
 
-err:	if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0)
+err:	if ((t_ret = __log_c_close(logc)) != 0 && ret == 0)
 		ret = t_ret;
 	/*
 	 * Not finding a checkpoint is not an error;  there may not exist
@@ -232,7 +232,6 @@ err:	if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0)
 /*
  * __txn_dbenv_refresh --
  *	Clean up after the transaction system on a close or failed open.
- * Called only from __dbenv_refresh.  (Formerly called __txn_close.)
  *
  * PUBLIC: int __txn_dbenv_refresh __P((DB_ENV *));
  */
@@ -242,29 +241,43 @@ __txn_dbenv_refresh(dbenv)
 {
 	DB_TXN *txnp;
 	DB_TXNMGR *tmgrp;
+	REGINFO *reginfo;
+	TXN_DETAIL *td;
 	u_int32_t txnid;
-	int ret, t_ret;
+	int aborted, ret, t_ret;
 
 	ret = 0;
 	tmgrp = dbenv->tx_handle;
+	reginfo = &tmgrp->reginfo;
 
 	/*
 	 * This function can only be called once per process (i.e., not
 	 * once per thread), so no synchronization is required.
 	 *
-	 * The caller is doing something wrong if close is called with
-	 * active transactions.  Try and abort any active transactions,
-	 * but it's quite likely the aborts will fail because recovery
-	 * won't find open files.  If we can't abort any transaction,
-	 * panic, we have to run recovery to get back to a known state.
+	 * The caller is probably doing something wrong if close is called with
+	 * active transactions.  Try and abort any active transactions that are
+	 * not prepared, but it's quite likely the aborts will fail because
+	 * recovery won't find open files.  If we can't abort any of the
+	 * unprepared transaction, panic, we have to run recovery to get back
+	 * to a known state.
 	 */
+	aborted = 0;
 	if (TAILQ_FIRST(&tmgrp->txn_chain) != NULL) {
-		__db_err(dbenv,
-	"Error: closing the transaction region with active transactions");
-		ret = EINVAL;
 		while ((txnp = TAILQ_FIRST(&tmgrp->txn_chain)) != NULL) {
+			/* Prepared transactions are OK. */
+			td = R_ADDR(reginfo, txnp->off);
 			txnid = txnp->txnid;
-			if ((t_ret = txnp->abort(txnp)) != 0) {
+			if (td->status == TXN_PREPARED) {
+				if ((ret = __txn_discard(txnp, 0)) != 0) {
+					__db_err(dbenv,
+					    "Unable to discard txn 0x%x: %s",
+					    txnid, db_strerror(ret));
+					break;
+				}
+				continue;
+			}
+			aborted = 1;
+			if ((t_ret = __txn_abort(txnp)) != 0) {
 				__db_err(dbenv,
 				    "Unable to abort transaction 0x%x: %s",
 				    txnid, db_strerror(t_ret));
@@ -272,19 +285,25 @@ __txn_dbenv_refresh(dbenv)
 				break;
 			}
 		}
+		if (aborted) {
+			__db_err(dbenv,
+	"Error: closing the transaction region with active transactions");
+			if (ret == 0)
+				ret = EINVAL;
+		}
 	}
 
 	/* Flush the log. */
 	if (LOGGING_ON(dbenv) &&
-	    (t_ret = dbenv->log_flush(dbenv, NULL)) != 0 && ret == 0)
+	    (t_ret = __log_flush(dbenv, NULL)) != 0 && ret == 0)
 		ret = t_ret;
 
 	/* Discard the per-thread lock. */
 	if (tmgrp->mutexp != NULL)
-		__db_mutex_free(dbenv, &tmgrp->reginfo, tmgrp->mutexp);
+		__db_mutex_free(dbenv, reginfo, tmgrp->mutexp);
 
 	/* Detach from the region. */
-	if ((t_ret = __db_r_detach(dbenv, &tmgrp->reginfo, 0)) != 0 && ret == 0)
+	if ((t_ret = __db_r_detach(dbenv, reginfo, 0)) != 0 && ret == 0)
 		ret = t_ret;
 
 	__os_free(dbenv, tmgrp);
@@ -327,14 +346,27 @@ __txn_region_destroy(dbenv, infop)
 	DB_ENV *dbenv;
 	REGINFO *infop;
 {
-	__db_shlocks_destroy(infop, (REGMAINT *)R_ADDR(infop,
-	    ((DB_TXNREGION *)R_ADDR(infop, infop->rp->primary))->maint_off));
+	/*
+	 * This routine is called in two cases: when discarding the mutexes
+	 * from a previous Berkeley DB run, during recovery, and two, when
+	 * discarding the mutexes as we shut down the database environment.
+	 * In the latter case, we also need to discard shared memory segments,
+	 * this is the last time we use them, and the last region-specific
+	 * call we make.
+	 */
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
+	DB_TXNREGION *region;
+
+	region = R_ADDR(infop, infop->rp->primary);
 
-	COMPQUIET(dbenv, NULL);
-	COMPQUIET(infop, NULL);
+	__db_shlocks_destroy(infop, R_ADDR(infop, region->maint_off));
+	if (infop->primary != NULL && F_ISSET(dbenv, DB_ENV_PRIVATE))
+		__db_shalloc_free(infop, R_ADDR(infop, region->maint_off));
+#endif
+	if (infop->primary != NULL && F_ISSET(dbenv, DB_ENV_PRIVATE))
+		__db_shalloc_free(infop, infop->primary);
 }
 
-#ifdef CONFIG_TEST
 /*
  * __txn_id_set --
  *	Set the current transaction ID and current maximum unused ID (for
@@ -361,14 +393,13 @@ __txn_id_set(dbenv, cur_txnid, max_txnid)
 	ret = 0;
 	if (cur_txnid < TXN_MINIMUM) {
 		__db_err(dbenv, "Current ID value %lu below minimum",
-		    cur_txnid);
+		    (u_long)cur_txnid);
 		ret = EINVAL;
 	}
 	if (max_txnid < TXN_MINIMUM) {
 		__db_err(dbenv, "Maximum ID value %lu below minimum",
-		    max_txnid);
+		    (u_long)max_txnid);
 		ret = EINVAL;
 	}
 	return (ret);
 }
-#endif
diff --git a/storage/bdb/txn/txn_stat.c b/storage/bdb/txn/txn_stat.c
index f7d84e8f4c6aa2e4618feb925ebb01d830dd3ff9..2f9b8357c59fdb53a9dc58efb07e0890c51e8a3f 100644
--- a/storage/bdb/txn/txn_stat.c
+++ b/storage/bdb/txn/txn_stat.c
@@ -1,31 +1,81 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: txn_stat.c,v 11.37 2004/10/15 16:59:44 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: txn_stat.c,v 11.15 2002/04/26 23:00:36 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
+#if TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#endif
+
+#include <stdlib.h>
 #include <string.h>
 #endif
 
 #include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
+#include "dbinc/log.h"
 #include "dbinc/txn.h"
 
+#ifdef HAVE_STATISTICS
+static int  __txn_compare __P((const void *, const void *));
+static int  __txn_print_all __P((DB_ENV *, u_int32_t));
+static int  __txn_print_stats __P((DB_ENV *, u_int32_t));
+static int  __txn_stat __P((DB_ENV *, DB_TXN_STAT **, u_int32_t));
+static void __txn_xid_stats __P((DB_ENV *, DB_MSGBUF *, DB_TXN_ACTIVE *));
+
 /*
- * __txn_stat --
+ * __txn_stat_pp --
+ *	DB_ENV->txn_stat pre/post processing.
  *
- * PUBLIC: int __txn_stat __P((DB_ENV *, DB_TXN_STAT **, u_int32_t));
+ * PUBLIC: int __txn_stat_pp __P((DB_ENV *, DB_TXN_STAT **, u_int32_t));
  */
 int
+__txn_stat_pp(dbenv, statp, flags)
+	DB_ENV *dbenv;
+	DB_TXN_STAT **statp;
+	u_int32_t flags;
+{
+	int rep_check, ret;
+
+	PANIC_CHECK(dbenv);
+	ENV_REQUIRES_CONFIG(dbenv,
+	    dbenv->tx_handle, "DB_ENV->txn_stat", DB_INIT_TXN);
+
+	if ((ret = __db_fchk(dbenv,
+	    "DB_ENV->txn_stat", flags, DB_STAT_CLEAR)) != 0)
+		return (ret);
+
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __txn_stat(dbenv, statp, flags);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
+/*
+ * __txn_stat --
+ *	DB_ENV->txn_stat.
+ */
+static int
 __txn_stat(dbenv, statp, flags)
 	DB_ENV *dbenv;
 	DB_TXN_STAT **statp;
@@ -36,17 +86,10 @@ __txn_stat(dbenv, statp, flags)
 	DB_TXN_STAT *stats;
 	TXN_DETAIL *txnp;
 	size_t nbytes;
-	u_int32_t ndx;
+	u_int32_t maxtxn, ndx;
 	int ret;
 
-	PANIC_CHECK(dbenv);
-	ENV_REQUIRES_CONFIG(dbenv, dbenv->tx_handle, "txn_stat", DB_INIT_TXN);
-
 	*statp = NULL;
-	if ((ret = __db_fchk(dbenv,
-	    "DB_ENV->txn_stat", flags, DB_STAT_CLEAR)) != 0)
-		return (ret);
-
 	mgr = dbenv->tx_handle;
 	region = mgr->reginfo.primary;
 
@@ -56,8 +99,12 @@ __txn_stat(dbenv, statp, flags)
 	 * not going to be that large.  Don't have to lock anything to look
 	 * at the region's maximum active transactions value, it's read-only
 	 * and never changes after the region is created.
+	 *
+	 * The maximum active transactions isn't a hard limit, so allocate
+	 * some extra room, and don't walk off the end.
 	 */
-	nbytes = sizeof(DB_TXN_STAT) + sizeof(DB_TXN_ACTIVE) * region->maxtxns;
+	maxtxn = region->maxtxns + (region->maxtxns / 10) + 10;
+	nbytes = sizeof(DB_TXN_STAT) + sizeof(DB_TXN_ACTIVE) * maxtxn;
 	if ((ret = __os_umalloc(dbenv, nbytes, &stats)) != 0)
 		return (ret);
 
@@ -68,10 +115,10 @@ __txn_stat(dbenv, statp, flags)
 	stats->st_time_ckp = region->time_ckp;
 	stats->st_txnarray = (DB_TXN_ACTIVE *)&stats[1];
 
-	ndx = 0;
-	for (txnp = SH_TAILQ_FIRST(&region->active_txn, __txn_detail);
-	    txnp != NULL;
-	    txnp = SH_TAILQ_NEXT(txnp, links, __txn_detail)) {
+	for (ndx = 0,
+	    txnp = SH_TAILQ_FIRST(&region->active_txn, __txn_detail);
+	    txnp != NULL && ndx < maxtxn;
+	    txnp = SH_TAILQ_NEXT(txnp, links, __txn_detail), ++ndx) {
 		stats->st_txnarray[ndx].txnid = txnp->txnid;
 		if (txnp->parent == INVALID_ROFF)
 			stats->st_txnarray[ndx].parentid = TXN_INVALID;
@@ -80,7 +127,9 @@ __txn_stat(dbenv, statp, flags)
 			    ((TXN_DETAIL *)R_ADDR(&mgr->reginfo,
 			    txnp->parent))->txnid;
 		stats->st_txnarray[ndx].lsn = txnp->begin_lsn;
-		ndx++;
+		if ((stats->st_txnarray[ndx].xa_status = txnp->xa_status) != 0)
+			memcpy(stats->st_txnarray[ndx].xid,
+			    txnp->xid, DB_XIDDATASIZE);
 	}
 
 	stats->st_region_wait = mgr->reginfo.rp->mutex.mutex_set_wait;
@@ -100,3 +149,282 @@ __txn_stat(dbenv, statp, flags)
 	*statp = stats;
 	return (0);
 }
+
+/*
+ * __txn_stat_print_pp --
+ *	DB_ENV->txn_stat_print pre/post processing.
+ *
+ * PUBLIC: int __txn_stat_print_pp __P((DB_ENV *, u_int32_t));
+ */
+int
+__txn_stat_print_pp(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	int rep_check, ret;
+
+	PANIC_CHECK(dbenv);
+	ENV_REQUIRES_CONFIG(dbenv,
+	    dbenv->tx_handle, "DB_ENV->txn_stat_print", DB_INIT_TXN);
+
+	if ((ret = __db_fchk(dbenv, "DB_ENV->txn_stat",
+	    flags, DB_STAT_ALL | DB_STAT_CLEAR)) != 0)
+		return (ret);
+
+	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+	if (rep_check)
+		__env_rep_enter(dbenv);
+	ret = __txn_stat_print(dbenv, flags);
+	if (rep_check)
+		__env_db_rep_exit(dbenv);
+	return (ret);
+}
+
+/*
+ * __txn_stat_print
+ *	DB_ENV->txn_stat_print method.
+ *
+ * PUBLIC: int  __txn_stat_print __P((DB_ENV *, u_int32_t));
+ */
+int
+__txn_stat_print(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	u_int32_t orig_flags;
+	int ret;
+
+	orig_flags = flags;
+	LF_CLR(DB_STAT_CLEAR);
+	if (flags == 0 || LF_ISSET(DB_STAT_ALL)) {
+		ret = __txn_print_stats(dbenv, orig_flags);
+		if (flags == 0 || ret != 0)
+			return (ret);
+	}
+
+	if (LF_ISSET(DB_STAT_ALL) &&
+	    (ret = __txn_print_all(dbenv, orig_flags)) != 0)
+		return (ret);
+
+	return (0);
+}
+
+/*
+ * __txn_print_stats --
+ *	Display default transaction region statistics.
+ */
+static int
+__txn_print_stats(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	DB_MSGBUF mb;
+	DB_TXN_STAT *sp;
+	u_int32_t i;
+	int ret;
+
+	if ((ret = __txn_stat(dbenv, &sp, flags)) != 0)
+		return (ret);
+
+	if (LF_ISSET(DB_STAT_ALL))
+		__db_msg(dbenv, "Default transaction region information:");
+	__db_msg(dbenv, "%lu/%lu\t%s",
+	    (u_long)sp->st_last_ckp.file, (u_long)sp->st_last_ckp.offset,
+	    sp->st_last_ckp.file == 0 ?
+	    "No checkpoint LSN" : "File/offset for last checkpoint LSN");
+	if (sp->st_time_ckp == 0)
+		__db_msg(dbenv, "0\tNo checkpoint timestamp");
+	else
+		__db_msg(dbenv, "%.24s\tCheckpoint timestamp",
+		    ctime(&sp->st_time_ckp));
+	__db_msg(dbenv, "%#lx\tLast transaction ID allocated",
+	    (u_long)sp->st_last_txnid);
+	__db_dl(dbenv, "Maximum number of active transactions configured",
+	    (u_long)sp->st_maxtxns);
+	__db_dl(dbenv, "Active transactions", (u_long)sp->st_nactive);
+	__db_dl(dbenv,
+	    "Maximum active transactions", (u_long)sp->st_maxnactive);
+	__db_dl(dbenv,
+	    "Number of transactions begun", (u_long)sp->st_nbegins);
+	__db_dl(dbenv,
+	    "Number of transactions aborted", (u_long)sp->st_naborts);
+	__db_dl(dbenv,
+	    "Number of transactions committed", (u_long)sp->st_ncommits);
+	__db_dl(dbenv,
+	    "Number of transactions restored", (u_long)sp->st_nrestores);
+
+	__db_dlbytes(dbenv, "Transaction region size",
+	    (u_long)0, (u_long)0, (u_long)sp->st_regsize);
+	__db_dl_pct(dbenv,
+	    "The number of region locks that required waiting",
+	    (u_long)sp->st_region_wait, DB_PCT(sp->st_region_wait,
+	    sp->st_region_wait + sp->st_region_nowait), NULL);
+
+	qsort(sp->st_txnarray,
+	    sp->st_nactive, sizeof(sp->st_txnarray[0]), __txn_compare);
+	__db_msg(dbenv, "List of active transactions:");
+	DB_MSGBUF_INIT(&mb);
+	for (i = 0; i < sp->st_nactive; ++i) {
+		__db_msgadd(dbenv,
+		    &mb, "\tID: %lx; begin LSN: file/offset %lu/%lu",
+		    (u_long)sp->st_txnarray[i].txnid,
+		    (u_long)sp->st_txnarray[i].lsn.file,
+		    (u_long)sp->st_txnarray[i].lsn.offset);
+		if (sp->st_txnarray[i].parentid != 0)
+			__db_msgadd(dbenv, &mb, "; parent: %lx",
+			    (u_long)sp->st_txnarray[i].parentid);
+		if (sp->st_txnarray[i].xa_status != 0)
+			__txn_xid_stats(dbenv, &mb, &sp->st_txnarray[i]);
+		DB_MSGBUF_FLUSH(dbenv, &mb);
+	}
+
+	__os_ufree(dbenv, sp);
+
+	return (0);
+}
+
+/*
+ * __txn_print_all --
+ *	Display debugging transaction region statistics.
+ */
+static int
+__txn_print_all(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	static const FN fn[] = {
+		{ TXN_IN_RECOVERY,	"TXN_IN_RECOVERY" },
+		{ 0,			NULL }
+	};
+	DB_TXNMGR *mgr;
+	DB_TXNREGION *region;
+
+	mgr = dbenv->tx_handle;
+	region = mgr->reginfo.primary;
+
+	R_LOCK(dbenv, &mgr->reginfo);
+
+	__db_print_reginfo(dbenv, &mgr->reginfo, "Transaction");
+
+	__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+	__db_msg(dbenv, "DB_TXNMGR handle information:");
+
+	__db_print_mutex(dbenv, NULL, mgr->mutexp, "DB_TXNMGR mutex", flags);
+	__db_dl(dbenv,
+	    "Number of transactions discarded", (u_long)mgr->n_discards);
+
+	__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+	__db_msg(dbenv, "DB_TXNREGION handle information:");
+	STAT_ULONG("Maximum number of active txns", region->maxtxns);
+	STAT_HEX("Last transaction ID allocated", region->last_txnid);
+	STAT_HEX("Current maximum unused ID", region->cur_maxid);
+
+	STAT_LSN("Last checkpoint LSN", &region->last_ckp);
+	__db_msg(dbenv,
+	    "%.24s\tLast checkpoint timestamp",
+	    region->time_ckp == 0 ? "0" : ctime(&region->time_ckp));
+
+	__db_prflags(dbenv, NULL, region->flags, fn, NULL, "\tFlags");
+
+	__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+	__db_msg(dbenv, "XA information:");
+	STAT_LONG("XA RMID", dbenv->xa_rmid);
+	/*
+	 * XXX
+	 * Display list of XA transactions in the DB_ENV handle.
+	 */
+
+	R_UNLOCK(dbenv, &mgr->reginfo);
+
+	return (0);
+}
+
+static void
+__txn_xid_stats(dbenv, mbp, txnp)
+	DB_ENV *dbenv;
+	DB_MSGBUF *mbp;
+	DB_TXN_ACTIVE *txnp;
+{
+	u_int32_t v, *xp;
+	u_int i;
+	int cnt;
+	const char *s;
+
+	switch (txnp->xa_status) {
+	case TXN_XA_ABORTED:
+		s = "ABORTED";
+		break;
+	case TXN_XA_DEADLOCKED:
+		s = "DEADLOCKED";
+		break;
+	case TXN_XA_ENDED:
+		s = "ENDED";
+		break;
+	case TXN_XA_PREPARED:
+		s = "PREPARED";
+		break;
+	case TXN_XA_STARTED:
+		s = "STARTED";
+		break;
+	case TXN_XA_SUSPENDED:
+		s = "SUSPENDED";
+		break;
+	default:
+		s = "UNKNOWN STATE";
+		__db_err(dbenv,
+		    "XA: unknown state: %lu", (u_long)txnp->xa_status);
+		break;
+	}
+	__db_msgadd(dbenv, mbp, "\tXA: %s; XID:\n\t\t", s == NULL ? "" : s);
+	for (cnt = 0, xp = (u_int32_t *)txnp->xid,
+	    i = 0; i < DB_XIDDATASIZE; i += sizeof(u_int32_t)) {
+		memcpy(&v, xp++, sizeof(u_int32_t));
+		__db_msgadd(dbenv, mbp, "%#x ", v);
+		if (++cnt == 4) {
+			DB_MSGBUF_FLUSH(dbenv, mbp);
+			__db_msgadd(dbenv, mbp, "\t\t");
+			cnt = 0;
+		}
+	}
+}
+
+static int
+__txn_compare(a1, b1)
+	const void *a1, *b1;
+{
+	const DB_TXN_ACTIVE *a, *b;
+
+	a = a1;
+	b = b1;
+
+	if (a->txnid > b->txnid)
+		return (1);
+	if (a->txnid < b->txnid)
+		return (-1);
+	return (0);
+}
+
+#else /* !HAVE_STATISTICS */
+
+int
+__txn_stat_pp(dbenv, statp, flags)
+	DB_ENV *dbenv;
+	DB_TXN_STAT **statp;
+	u_int32_t flags;
+{
+	COMPQUIET(statp, NULL);
+	COMPQUIET(flags, 0);
+
+	return (__db_stat_not_built(dbenv));
+}
+
+int
+__txn_stat_print_pp(dbenv, flags)
+	DB_ENV *dbenv;
+	u_int32_t flags;
+{
+	COMPQUIET(flags, 0);
+
+	return (__db_stat_not_built(dbenv));
+}
+#endif
diff --git a/storage/bdb/txn/txn_util.c b/storage/bdb/txn/txn_util.c
index cbfbc41961586e36b4e2a9199a80cbebcc3a69da..ff94cd7dbb5654c27e7295d3b3aab24979acd69d 100644
--- a/storage/bdb/txn/txn_util.c
+++ b/storage/bdb/txn/txn_util.c
@@ -1,31 +1,36 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 2001-2002
+ * Copyright (c) 2001-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: txn_util.c,v 11.28 2004/09/16 17:55:19 margo Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: txn_util.c,v 11.18 2002/08/06 06:25:12 bostic Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #include <string.h>
 #endif
 
 #include "db_int.h"
+#include "dbinc/db_page.h"
 #include "dbinc/db_shash.h"
 #include "dbinc/lock.h"
+#include "dbinc/mp.h"
 #include "dbinc/txn.h"
+#include "dbinc/db_am.h"
 
 typedef struct __txn_event TXN_EVENT;
 struct __txn_event {
 	TXN_EVENT_T op;
 	TAILQ_ENTRY(__txn_event) links;
 	union {
+		struct {
+			/* Delayed close. */
+			DB *dbp;
+		} c;
 		struct {
 			/* Delayed remove. */
 			char *name;
@@ -40,6 +45,34 @@ struct __txn_event {
 	} u;
 };
 
+/*
+ * __txn_closeevent --
+ *
+ * Creates a close event that can be added to the [so-called] commit list, so
+ * that we can redo a failed DB handle close once we've aborted the transaction.
+ *
+ * PUBLIC: int __txn_closeevent __P((DB_ENV *, DB_TXN *, DB *));
+ */
+int
+__txn_closeevent(dbenv, txn, dbp)
+	DB_ENV *dbenv;
+	DB_TXN *txn;
+	DB *dbp;
+{
+	int ret;
+	TXN_EVENT *e;
+
+	e = NULL;
+	if ((ret = __os_calloc(dbenv, 1, sizeof(TXN_EVENT), &e)) != 0)
+		return (ret);
+
+	e->u.c.dbp = dbp;
+	e->op = TXN_CLOSE;
+	TAILQ_INSERT_TAIL(&txn->events, e, links);
+
+	return (0);
+}
+
 /*
  * __txn_remevent --
  *
@@ -82,6 +115,34 @@ err:	if (e != NULL)
 
 	return (ret);
 }
+/*
+ * __txn_remrem --
+ *	Remove a remove event because the remove has be superceeded,
+ * by a create of the same name, for example.
+ *
+ * PUBLIC: void __txn_remrem __P((DB_ENV *, DB_TXN *, const char *));
+ */
+void
+__txn_remrem(dbenv, txn, name)
+	DB_ENV *dbenv;
+	DB_TXN *txn;
+	const char *name;
+{
+	TXN_EVENT *e, *next_e;
+
+	for (e = TAILQ_FIRST(&txn->events); e != NULL; e = next_e) {
+		next_e = TAILQ_NEXT(e, links);
+		if (e->op != TXN_REMOVE || strcmp(name, e->u.r.name) != 0)
+			continue;
+		TAILQ_REMOVE(&txn->events, e, links);
+		__os_free(dbenv, e->u.r.name);
+		if (e->u.r.fileid != NULL)
+			__os_free(dbenv, e->u.r.fileid);
+		__os_free(dbenv, e);
+	}
+
+	return;
+}
 
 /*
  * __txn_lockevent --
@@ -169,10 +230,10 @@ __txn_remlock(dbenv, txn, lock, locker)
 } while (0)
 
 int
-__txn_doevents(dbenv, txn, is_commit, preprocess)
+__txn_doevents(dbenv, txn, opcode, preprocess)
 	DB_ENV *dbenv;
 	DB_TXN *txn;
-	int is_commit, preprocess;
+	int opcode, preprocess;
 {
 	DB_LOCKREQ req;
 	TXN_EVENT *e;
@@ -197,22 +258,39 @@ __txn_doevents(dbenv, txn, is_commit, preprocess)
 		return (ret);
 	}
 
+	/*
+	 * Prepare should only cause a preprocess, since the transaction
+	 * isn't over.
+	 */
+	DB_ASSERT(opcode != TXN_PREPARE);
 	while ((e = TAILQ_FIRST(&txn->events)) != NULL) {
 		TAILQ_REMOVE(&txn->events, e, links);
-		if (!is_commit)
+		/*
+		 * Most deferred events should only happen on
+		 * commits, not aborts or prepares.  The one exception
+		 * is a close which gets done on commit and abort, but
+		 * not prepare. If we're not doing operations, then we
+		 * can just go free resources.
+		 */
+		if (opcode == TXN_ABORT && e->op != TXN_CLOSE)
 			goto dofree;
 		switch (e->op) {
+		case TXN_CLOSE:
+			/* If we didn't abort this txn, we screwed up badly. */
+			DB_ASSERT(opcode == TXN_ABORT);
+			if ((t_ret = __db_close(e->u.c.dbp,
+			    NULL, DB_NOSYNC)) != 0 && ret == 0)
+				ret = t_ret;
+			break;
 		case TXN_REMOVE:
 			if (e->u.r.fileid != NULL) {
-				if ((t_ret = dbenv->memp_nameop(dbenv,
+				if ((t_ret = __memp_nameop(dbenv,
 				    e->u.r.fileid,
 				    NULL, e->u.r.name, NULL)) != 0 && ret == 0)
 					ret = t_ret;
-				__os_free(dbenv, e->u.r.fileid);
 			} else if ((t_ret =
 			    __os_unlink(dbenv, e->u.r.name)) != 0 && ret == 0)
 				ret = t_ret;
-			__os_free(dbenv, e->u.r.name);
 			break;
 		case TXN_TRADE:
 			DO_TRADE;
@@ -227,7 +305,21 @@ __txn_doevents(dbenv, txn, is_commit, preprocess)
 			/* This had better never happen. */
 			DB_ASSERT(0);
 		}
-dofree:		__os_free(dbenv, e);
+dofree:
+		/* Free resources here. */
+		switch (e->op) {
+		case TXN_REMOVE:
+			if (e->u.r.fileid != NULL)
+				__os_free(dbenv, e->u.r.fileid);
+			__os_free(dbenv, e->u.r.name);
+			break;
+		case TXN_CLOSE:
+		case TXN_TRADE:
+		case TXN_TRADED:
+		default:
+			break;
+		}
+		__os_free(dbenv, e);
 	}
 
 	return (ret);
diff --git a/storage/bdb/xa/xa.c b/storage/bdb/xa/xa.c
index 6667d14c2bf7b8f044d35ebbd518ce926411f59a..00f3461e3bad41f6cb69d8b5bcd93fd979cbb104 100644
--- a/storage/bdb/xa/xa.c
+++ b/storage/bdb/xa/xa.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1998-2002
+ * Copyright (c) 1998-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: xa.c,v 11.35 2004/10/15 16:59:45 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: xa.c,v 11.23 2002/08/29 14:22:25 margo Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -31,7 +29,7 @@ static int  __db_xa_prepare __P((XID *, int, long));
 static int  __db_xa_recover __P((XID *, long, int, long));
 static int  __db_xa_rollback __P((XID *, int, long));
 static int  __db_xa_start __P((XID *, int, long));
-static void __xa_txn_end __P((DB_TXN *));
+static void __xa_put_txn __P((DB_ENV *, DB_TXN *));
 
 /*
  * Possible flag values:
@@ -59,6 +57,129 @@ const struct xa_switch_t db_xa_switch = {
 	 __db_xa_complete	/* xa_complete_entry */
 };
 
+/*
+ * If you want your XA server to be multi-threaded, then you must
+ * edit this file and change:
+ *	#undef  XA_MULTI_THREAD
+ * to:
+ *	#define XA_MULTI_THREAD 1
+ *
+ * You must then modify the FILL ME IN; section below to assign a
+ * 32-bit unsigned, unique thread ID to the variable tid.  If no
+ * such thread ID is available, e.g., you're using pthreads on a POSIX
+ * 1003.1 system where a pthread_t is declared as a structure, you
+ * will probably want to change the tid field of the DB_TXN structure
+ * to be the correct type in which to define a thread ID on the system,
+ * and then modify both the FILL ME IN section and then subsequent
+ * comparison of the thread IDs in the XA transaction list, as the
+ * current simple equality tests may not work.
+ */
+
+#undef XA_MULTI_THREAD
+
+/*
+ * __xa_get_txn --
+ *	Return a pointer to the current transaction structure for the
+ * designated environment.  If do_init is non-zero and we don't find a
+ * structure for the current thread, then create a new structure for it.
+ *
+ * PUBLIC: int __xa_get_txn __P((DB_ENV *, DB_TXN **, int));
+ */
+int
+__xa_get_txn(dbenv, txnp, do_init)
+	DB_ENV *dbenv;
+	DB_TXN **txnp;
+	int do_init;
+{
+	int ret;
+#ifdef XA_MULTI_THREAD
+	DB_TXN *t;
+	u_int32_t tid;
+	DB_TXNMGR *mgr;
+#else
+	COMPQUIET(do_init, 0);
+#endif
+	ret = 0;
+
+#ifdef XA_MULTI_THREAD
+	/* Specify Thread-ID retrieval here. */
+	tid  = FILL ME IN
+	*txnp = NULL;
+	mgr = (DB_TXNMGR *)dbenv->tx_handle;
+
+	/*
+	 * We need to protect the xa_txn linked list, but the
+	 * environment does not have a mutex.  Since we are in
+	 * an XA transaction environment, we know that there is
+	 * a transaction structure, so use its mutex.
+	 */
+	DB_ASSERT(dbenv->tx_handle != NULL);
+	MUTEX_THREAD_LOCK(mgr->mutexp);
+	for (t = TAILQ_FIRST(&dbenv->xa_txn);
+	    t != NULL;
+	    t = TAILQ_NEXT(t, xalinks))
+		/*
+		 * FILL ME IN; if tids are not a 32-bit integral type;
+		 * put a comparison here that will work.
+		 */
+		if (t->tid == tid) {
+			*txnp = t;
+			break;
+		}
+	MUTEX_THREAD_UNLOCK(mgr-&gt;mutexp);
+
+	if (*txnp == NULL) {
+		if (!do_init)
+			ret = EINVAL;
+		else if ((ret =
+		    __os_malloc(dbenv, sizeof(DB_TXN), NULL, txnp)) == 0) {
+			(*txnp)->tid = tid;
+			MUTEX_THREAD_LOCK(mgr->mutexp);
+			TAILQ_INSERT_HEAD(&dbenv->xa_txn, *txnp, xalinks);
+			MUTEX_THREAD_UNLOCK(mgr->mutexp);
+		}
+	}
+#else
+	*txnp = TAILQ_FIRST(&dbenv->xa_txn);
+	if (*txnp == NULL &&
+	    (ret = __os_calloc(dbenv, 1, sizeof(DB_TXN), txnp)) == 0) {
+		(*txnp)->txnid = TXN_INVALID;
+		TAILQ_INSERT_HEAD(&dbenv->xa_txn, *txnp, xalinks);
+	}
+#endif
+
+	return (ret);
+}
+
+static void
+__xa_put_txn(dbenv, txnp)
+	DB_ENV *dbenv;
+	DB_TXN *txnp;
+{
+#ifdef XA_MULTI_THREAD
+	DB_TXNMGR *mgr;
+	mgr = (DB_TXNMGR *)dbenv->tx_handle;
+
+	MUTEX_THREAD_LOCK(mgr->mutexp);
+	TAILQ_REMOVE(&dbenv->xa_txn, txnp, xalinks);
+	MUTEX_THREAD_UNLOCK(mgr->mutexp);
+	__os_free(dbenv, txnp);
+#else
+	COMPQUIET(dbenv, NULL);
+	txnp->txnid = TXN_INVALID;
+#endif
+}
+
+#ifdef XA_MULTI_THREAD
+#define	XA_FLAGS \
+	(DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | \
+	DB_INIT_TXN | DB_THREAD)
+#else
+#define	XA_FLAGS \
+	(DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | \
+	DB_INIT_TXN)
+#endif
+
 /*
  * __db_xa_open --
  *	The open call in the XA protocol.  The rmid field is an id number
@@ -74,12 +195,15 @@ const struct xa_switch_t db_xa_switch = {
  * call.
  */
 static int
-__db_xa_open(xa_info, rmid, flags)
+__db_xa_open(xa_info, rmid, arg_flags)
 	char *xa_info;
 	int rmid;
-	long flags;
+	long arg_flags;
 {
-	DB_ENV *env;
+	DB_ENV *dbenv;
+	u_long flags;
+
+	flags = (u_long)arg_flags;	/* Conversion for bit operations. */
 
 	if (LF_ISSET(TMASYNC))
 		return (XAER_ASYNC);
@@ -87,31 +211,27 @@ __db_xa_open(xa_info, rmid, flags)
 		return (XAER_INVAL);
 
 	/* Verify if we already have this environment open. */
-	if (__db_rmid_to_env(rmid, &env) == 0)
+	if (__db_rmid_to_env(rmid, &dbenv) == 0)
 		return (XA_OK);
-	if (__os_calloc(env, 1, sizeof(DB_ENV), &env) != 0)
+	if (__os_calloc(dbenv, 1, sizeof(DB_ENV), &dbenv) != 0)
 		return (XAER_RMERR);
 
 	/* Open a new environment. */
-#define	XA_FLAGS \
-	DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN
-	if (db_env_create(&env, 0) != 0)
+	if (db_env_create(&dbenv, 0) != 0)
 		return (XAER_RMERR);
-	if (env->open(env, xa_info, XA_FLAGS, 0) != 0)
+	if (dbenv->open(dbenv, xa_info, XA_FLAGS, 0) != 0)
 		goto err;
 
 	/* Create the mapping. */
-	if (__db_map_rmid(rmid, env) != 0)
+	if (__db_map_rmid(rmid, dbenv) != 0)
 		goto err;
 
 	/* Allocate space for the current transaction. */
-	if (__os_calloc(env, 1, sizeof(DB_TXN), &env->xa_txn) != 0)
-		goto err;
-	env->xa_txn->txnid = TXN_INVALID;
+	TAILQ_INIT(&dbenv->xa_txn);
 
 	return (XA_OK);
 
-err:	(void)env->close(env, 0);
+err:	(void)dbenv->close(dbenv, 0);
 
 	return (XAER_RMERR);
 }
@@ -125,38 +245,45 @@ err:	(void)env->close(env, 0);
  * environment that has never been opened).
  */
 static int
-__db_xa_close(xa_info, rmid, flags)
+__db_xa_close(xa_info, rmid, arg_flags)
 	char *xa_info;
 	int rmid;
-	long flags;
+	long arg_flags;
 {
-	DB_ENV *env;
+	DB_ENV *dbenv;
+	DB_TXN *t;
 	int ret, t_ret;
+	u_long flags;
 
 	COMPQUIET(xa_info, NULL);
 
+	flags = (u_long)arg_flags;	/* Conversion for bit operations. */
+
 	if (LF_ISSET(TMASYNC))
 		return (XAER_ASYNC);
 	if (flags != TMNOFLAGS)
 		return (XAER_INVAL);
 
 	/* If the environment is closed, then we're done. */
-	if (__db_rmid_to_env(rmid, &env) != 0)
+	if (__db_rmid_to_env(rmid, &dbenv) != 0)
 		return (XA_OK);
 
 	/* Check if there are any pending transactions. */
-	if (env->xa_txn != NULL && env->xa_txn->txnid != TXN_INVALID)
+	if ((t = TAILQ_FIRST(&dbenv->xa_txn)) != NULL &&
+	    t->txnid != TXN_INVALID)
 		return (XAER_PROTO);
 
 	/* Destroy the mapping. */
 	ret = __db_unmap_rmid(rmid);
 
 	/* Discard space held for the current transaction. */
-	if (env->xa_txn != NULL)
-		__os_free(env, env->xa_txn);
+	while ((t = TAILQ_FIRST(&dbenv->xa_txn)) != NULL) {
+		TAILQ_REMOVE(&dbenv->xa_txn, t, xalinks);
+		__os_free(dbenv, t);
+	}
 
 	/* Close the environment. */
-	if ((t_ret = env->close(env, 0)) != 0 && ret == 0)
+	if ((t_ret = dbenv->close(dbenv, 0)) != 0 && ret == 0)
 		ret = t_ret;
 
 	return (ret == 0 ? XA_OK : XAER_RMERR);
@@ -167,16 +294,20 @@ __db_xa_close(xa_info, rmid, flags)
  *	Begin a transaction for the current resource manager.
  */
 static int
-__db_xa_start(xid, rmid, flags)
+__db_xa_start(xid, rmid, arg_flags)
 	XID *xid;
 	int rmid;
-	long flags;
+	long arg_flags;
 {
-	DB_ENV *env;
+	DB_ENV *dbenv;
+	DB_TXN *txnp;
 	TXN_DETAIL *td;
-	size_t off;
+	roff_t off;
+	u_long flags;
 	int is_known;
 
+	flags = (u_long)arg_flags;	/* Conversion for bit operations. */
+
 #define	OK_FLAGS	(TMJOIN | TMRESUME | TMNOWAIT | TMASYNC | TMNOFLAGS)
 	if (LF_ISSET(~OK_FLAGS))
 		return (XAER_INVAL);
@@ -187,10 +318,10 @@ __db_xa_start(xid, rmid, flags)
 	if (LF_ISSET(TMASYNC))
 		return (XAER_ASYNC);
 
-	if (__db_rmid_to_env(rmid, &env) != 0)
+	if (__db_rmid_to_env(rmid, &dbenv) != 0)
 		return (XAER_PROTO);
 
-	is_known = __db_xid_to_txn(env, xid, &off) == 0;
+	is_known = __db_xid_to_txn(dbenv, xid, &off) == 0;
 
 	if (is_known && !LF_ISSET(TMRESUME) && !LF_ISSET(TMJOIN))
 		return (XAER_DUPID);
@@ -204,8 +335,7 @@ __db_xa_start(xid, rmid, flags)
 	 * Other error conditions: RMERR, RMFAIL, OUTSIDE, PROTO, RB*
 	 */
 	if (is_known) {
-		td = (TXN_DETAIL *)
-		    R_ADDR(&((DB_TXNMGR *)env->tx_handle)->reginfo, off);
+		td = R_ADDR(&((DB_TXNMGR *)dbenv->tx_handle)->reginfo, off);
 		if (td->xa_status == TXN_XA_SUSPENDED &&
 		    !LF_ISSET(TMRESUME | TMJOIN))
 			return (XAER_PROTO);
@@ -215,15 +345,18 @@ __db_xa_start(xid, rmid, flags)
 			return (XA_RBOTHER);
 
 		/* Now, fill in the global transaction structure. */
-		__txn_continue(env, env->xa_txn, td, off);
+		if (__xa_get_txn(dbenv, &txnp, 1) != 0)
+			return (XAER_RMERR);
+		__txn_continue(dbenv, txnp, td, off);
 		td->xa_status = TXN_XA_STARTED;
 	} else {
-		if (__txn_xa_begin(env, env->xa_txn) != 0)
+		if (__xa_get_txn(dbenv, &txnp, 1) != 0)
+			return (XAER_RMERR);
+		if (__txn_xa_begin(dbenv, txnp))
 			return (XAER_RMERR);
-		(void)__db_map_xid(env, xid, env->xa_txn->off);
-		td = (TXN_DETAIL *)
-		    R_ADDR(&((DB_TXNMGR *)env->tx_handle)->reginfo,
-		    env->xa_txn->off);
+		(void)__db_map_xid(dbenv, xid, txnp->off);
+		td = R_ADDR(
+		    &((DB_TXNMGR *)dbenv->tx_handle)->reginfo, txnp->off);
 		td->xa_status = TXN_XA_STARTED;
 	}
 	return (XA_OK);
@@ -239,25 +372,27 @@ __db_xa_end(xid, rmid, flags)
 	int rmid;
 	long flags;
 {
-	DB_ENV *env;
+	DB_ENV *dbenv;
 	DB_TXN *txn;
 	TXN_DETAIL *td;
-	size_t off;
+	roff_t off;
 
 	if (flags != TMNOFLAGS && !LF_ISSET(TMSUSPEND | TMSUCCESS | TMFAIL))
 		return (XAER_INVAL);
 
-	if (__db_rmid_to_env(rmid, &env) != 0)
+	if (__db_rmid_to_env(rmid, &dbenv) != 0)
 		return (XAER_PROTO);
 
-	if (__db_xid_to_txn(env, xid, &off) != 0)
+	if (__db_xid_to_txn(dbenv, xid, &off) != 0)
 		return (XAER_NOTA);
 
-	txn = env->xa_txn;
+	if (__xa_get_txn(dbenv, &txn, 0) != 0)
+		return (XAER_RMERR);
+
 	if (off != txn->off)
 		return (XAER_PROTO);
 
-	td = (TXN_DETAIL *)R_ADDR(&((DB_TXNMGR *)env->tx_handle)->reginfo, off);
+	td = R_ADDR(&((DB_TXNMGR *)dbenv->tx_handle)->reginfo, off);
 	if (td->xa_status == TXN_XA_DEADLOCKED)
 		return (XA_RBDEADLOCK);
 
@@ -279,7 +414,7 @@ __db_xa_end(xid, rmid, flags)
 	else
 		td->xa_status = TXN_XA_ENDED;
 
-	txn->txnid = TXN_INVALID;
+	__xa_put_txn(dbenv, txn);
 	return (XA_OK);
 }
 
@@ -288,14 +423,18 @@ __db_xa_end(xid, rmid, flags)
  *	Sync the log to disk so we can guarantee recoverability.
  */
 static int
-__db_xa_prepare(xid, rmid, flags)
+__db_xa_prepare(xid, rmid, arg_flags)
 	XID *xid;
 	int rmid;
-	long flags;
+	long arg_flags;
 {
-	DB_ENV *env;
+	DB_ENV *dbenv;
+	DB_TXN *txnp;
 	TXN_DETAIL *td;
-	size_t off;
+	roff_t off;
+	u_long flags;
+
+	flags = (u_long)arg_flags;	/* Conversion for bit operations. */
 
 	if (LF_ISSET(TMASYNC))
 		return (XAER_ASYNC);
@@ -308,13 +447,12 @@ __db_xa_prepare(xid, rmid, flags)
 	 * reflect that fact that prepare has been called, and if
 	 * it's ever called again, it's an error.
 	 */
-	if (__db_rmid_to_env(rmid, &env) != 0)
+	if (__db_rmid_to_env(rmid, &dbenv) != 0)
 		return (XAER_PROTO);
 
-	if (__db_xid_to_txn(env, xid, &off) != 0)
+	if (__db_xid_to_txn(dbenv, xid, &off) != 0)
 		return (XAER_NOTA);
-
-	td = (TXN_DETAIL *)R_ADDR(&((DB_TXNMGR *)env->tx_handle)->reginfo, off);
+	td = R_ADDR(&((DB_TXNMGR *)dbenv->tx_handle)->reginfo, off);
 	if (td->xa_status == TXN_XA_DEADLOCKED)
 		return (XA_RBDEADLOCK);
 
@@ -322,15 +460,17 @@ __db_xa_prepare(xid, rmid, flags)
 		return (XAER_PROTO);
 
 	/* Now, fill in the global transaction structure. */
-	__txn_continue(env, env->xa_txn, td, off);
+	if (__xa_get_txn(dbenv, &txnp, 0) != 0)
+		return (XAER_PROTO);
+	__txn_continue(dbenv, txnp, td, off);
 
-	if (env->xa_txn->prepare(env->xa_txn, (u_int8_t *)xid->data) != 0)
+	if (txnp->prepare(txnp, (u_int8_t *)xid->data) != 0)
 		return (XAER_RMERR);
 
 	td->xa_status = TXN_XA_PREPARED;
 
 	/* No fatal value that would require an XAER_RMFAIL. */
-	__xa_txn_end(env->xa_txn);
+	__xa_put_txn(dbenv, txnp);
 	return (XA_OK);
 }
 
@@ -339,14 +479,18 @@ __db_xa_prepare(xid, rmid, flags)
  *	Commit the transaction
  */
 static int
-__db_xa_commit(xid, rmid, flags)
+__db_xa_commit(xid, rmid, arg_flags)
 	XID *xid;
 	int rmid;
-	long flags;
+	long arg_flags;
 {
-	DB_ENV *env;
+	DB_ENV *dbenv;
+	DB_TXN *txnp;
 	TXN_DETAIL *td;
-	size_t off;
+	roff_t off;
+	u_long flags;
+
+	flags = (u_long)arg_flags;	/* Conversion for bit operations. */
 
 	if (LF_ISSET(TMASYNC))
 		return (XAER_ASYNC);
@@ -359,13 +503,13 @@ __db_xa_commit(xid, rmid, flags)
 	 * We need to know if we've ever called prepare on this.
 	 * We can verify this by examining the xa_status field.
 	 */
-	if (__db_rmid_to_env(rmid, &env) != 0)
+	if (__db_rmid_to_env(rmid, &dbenv) != 0)
 		return (XAER_PROTO);
 
-	if (__db_xid_to_txn(env, xid, &off) != 0)
+	if (__db_xid_to_txn(dbenv, xid, &off) != 0)
 		return (XAER_NOTA);
 
-	td = (TXN_DETAIL *)R_ADDR(&((DB_TXNMGR *)env->tx_handle)->reginfo, off);
+	td = R_ADDR(&((DB_TXNMGR *)dbenv->tx_handle)->reginfo, off);
 	if (td->xa_status == TXN_XA_DEADLOCKED)
 		return (XA_RBDEADLOCK);
 
@@ -380,13 +524,15 @@ __db_xa_commit(xid, rmid, flags)
 		return (XAER_PROTO);
 
 	/* Now, fill in the global transaction structure. */
-	__txn_continue(env, env->xa_txn, td, off);
+	if (__xa_get_txn(dbenv, &txnp, 0) != 0)
+		return (XAER_RMERR);
+	__txn_continue(dbenv, txnp, td, off);
 
-	if (env->xa_txn->commit(env->xa_txn, 0) != 0)
+	if (txnp->commit(txnp, 0) != 0)
 		return (XAER_RMERR);
 
 	/* No fatal value that would require an XAER_RMFAIL. */
-	__xa_txn_end(env->xa_txn);
+	__xa_put_txn(dbenv, txnp);
 	return (XA_OK);
 }
 
@@ -404,12 +550,12 @@ __db_xa_recover(xids, count, rmid, flags)
 	long count, flags;
 	int rmid;
 {
-	DB_ENV *env;
+	DB_ENV *dbenv;
 	u_int32_t newflags;
 	long rval;
 
 	/* If the environment is closed, then we're done. */
-	if (__db_rmid_to_env(rmid, &env) != 0)
+	if (__db_rmid_to_env(rmid, &dbenv) != 0)
 		return (XAER_PROTO);
 
 	if (LF_ISSET(TMSTARTRSCAN))
@@ -420,7 +566,7 @@ __db_xa_recover(xids, count, rmid, flags)
 		newflags = DB_NEXT;
 
 	rval = 0;
-	if (__txn_get_prepared(env, xids, NULL, count, &rval, newflags) != 0)
+	if (__txn_get_prepared(dbenv, xids, NULL, count, &rval, newflags) != 0)
 		return (XAER_RMERR);
 	else
 		return (rval);
@@ -431,44 +577,51 @@ __db_xa_recover(xids, count, rmid, flags)
  *	Abort an XA transaction.
  */
 static int
-__db_xa_rollback(xid, rmid, flags)
+__db_xa_rollback(xid, rmid, arg_flags)
 	XID *xid;
 	int rmid;
-	long flags;
+	long arg_flags;
 {
-	DB_ENV *env;
+	DB_ENV *dbenv;
+	DB_TXN *txnp;
 	TXN_DETAIL *td;
-	size_t off;
+	roff_t off;
+	u_long flags;
+
+	flags = (u_long)arg_flags;	/* Conversion for bit operations. */
 
 	if (LF_ISSET(TMASYNC))
 		return (XAER_ASYNC);
 	if (flags != TMNOFLAGS)
 		return (XAER_INVAL);
 
-	if (__db_rmid_to_env(rmid, &env) != 0)
+	if (__db_rmid_to_env(rmid, &dbenv) != 0)
 		return (XAER_PROTO);
 
-	if (__db_xid_to_txn(env, xid, &off) != 0)
+	if (__db_xid_to_txn(dbenv, xid, &off) != 0)
 		return (XAER_NOTA);
 
-	td = (TXN_DETAIL *)R_ADDR(&((DB_TXNMGR *)env->tx_handle)->reginfo, off);
+	td = R_ADDR(&((DB_TXNMGR *)dbenv->tx_handle)->reginfo, off);
 	if (td->xa_status == TXN_XA_DEADLOCKED)
 		return (XA_RBDEADLOCK);
 
 	if (td->xa_status == TXN_XA_ABORTED)
 		return (XA_RBOTHER);
 
-	if (td->xa_status != TXN_XA_ENDED && td->xa_status != TXN_XA_SUSPENDED
-	    && td->xa_status != TXN_XA_PREPARED)
+	if (td->xa_status != TXN_XA_ENDED &&
+	    td->xa_status != TXN_XA_SUSPENDED &&
+	    td->xa_status != TXN_XA_PREPARED)
 		return (XAER_PROTO);
 
 	/* Now, fill in the global transaction structure. */
-	__txn_continue(env, env->xa_txn, td, off);
-	if (env->xa_txn->abort(env->xa_txn) != 0)
+	if (__xa_get_txn(dbenv, &txnp, 0) != 0)
+		return (XAER_RMERR);
+	__txn_continue(dbenv, txnp, td, off);
+	if (txnp->abort(txnp) != 0)
 		return (XAER_RMERR);
 
 	/* No fatal value that would require an XAER_RMFAIL. */
-	__xa_txn_end(env->xa_txn);
+	__xa_put_txn(dbenv, txnp);
 	return (XA_OK);
 }
 
@@ -480,29 +633,32 @@ __db_xa_rollback(xid, rmid, flags)
  * that we reclaim the slots in the txnid table.
  */
 static int
-__db_xa_forget(xid, rmid, flags)
+__db_xa_forget(xid, rmid, arg_flags)
 	XID *xid;
 	int rmid;
-	long flags;
+	long arg_flags;
 {
-	DB_ENV *env;
-	size_t off;
+	DB_ENV *dbenv;
+	roff_t off;
+	u_long flags;
+
+	flags = (u_long)arg_flags;	/* Conversion for bit operations. */
 
 	if (LF_ISSET(TMASYNC))
 		return (XAER_ASYNC);
 	if (flags != TMNOFLAGS)
 		return (XAER_INVAL);
 
-	if (__db_rmid_to_env(rmid, &env) != 0)
+	if (__db_rmid_to_env(rmid, &dbenv) != 0)
 		return (XAER_PROTO);
 
 	/*
 	 * If mapping is gone, then we're done.
 	 */
-	if (__db_xid_to_txn(env, xid, &off) != 0)
+	if (__db_xid_to_txn(dbenv, xid, &off) != 0)
 		return (XA_OK);
 
-	__db_unmap_xid(env, xid, off);
+	__db_unmap_xid(dbenv, xid, off);
 
 	/* No fatal value that would require an XAER_RMFAIL. */
 	return (XA_OK);
@@ -525,15 +681,3 @@ __db_xa_complete(handle, retval, rmid, flags)
 
 	return (XAER_INVAL);
 }
-
-/*
- * __xa_txn_end --
- *	Invalidate a transaction structure that was generated by __txn_continue.
- */
-static void
-__xa_txn_end(txn)
-	DB_TXN *txn;
-{
-	if (txn != NULL)
-		txn->txnid = TXN_INVALID;
-}
diff --git a/storage/bdb/xa/xa_db.c b/storage/bdb/xa/xa_db.c
index b84bb1c9fa9e2b152319d0da981cdabc5b0da287..550d47dd82abe149229dd4acf6ac95ad7c4577ba 100644
--- a/storage/bdb/xa/xa_db.c
+++ b/storage/bdb/xa/xa_db.c
@@ -1,22 +1,19 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1998-2002
+ * Copyright (c) 1998-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: xa_db.c,v 11.26 2004/01/28 03:36:40 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: xa_db.c,v 11.21 2002/08/29 14:22:25 margo Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 #endif
 
 #include "db_int.h"
-#include "dbinc/xa.h"
 #include "dbinc/txn.h"
 
 static int __xa_close __P((DB *, u_int32_t));
@@ -37,6 +34,18 @@ typedef struct __xa_methods {
 	int (*put) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
 } XA_METHODS;
 
+#define	SET_TXN(PARAM, LOCAL) {						\
+	(LOCAL) = NULL;							\
+	if (!LF_ISSET(DB_AUTO_COMMIT)) {				\
+		if ((PARAM) != NULL)					\
+			(LOCAL) = (PARAM);				\
+		else if (__xa_get_txn(dbp->dbenv, &(LOCAL), 0) != 0)	\
+			(LOCAL) = NULL;					\
+		else if ((LOCAL) != NULL && (LOCAL)->txnid == TXN_INVALID) \
+			(LOCAL) = NULL;					\
+	}								\
+}
+
 /*
  * __db_xa_create --
  *	DB XA constructor.
@@ -80,12 +89,14 @@ __xa_open(dbp, txn, name, subdb, type, flags, mode)
 	u_int32_t flags;
 	int mode;
 {
+	DB_TXN *t;
 	XA_METHODS *xam;
 	int ret;
 
 	xam = (XA_METHODS *)dbp->xa_internal;
 
-	if ((ret = xam->open(dbp, txn, name, subdb, type, flags, mode)) != 0)
+	SET_TXN(txn, t);
+	if ((ret = xam->open(dbp, t, name, subdb, type, flags, mode)) != 0)
 		return (ret);
 
 	xam->cursor = dbp->cursor;
@@ -109,8 +120,10 @@ __xa_cursor(dbp, txn, dbcp, flags)
 {
 	DB_TXN *t;
 
-	t = txn != NULL ? txn : dbp->dbenv->xa_txn;
-	if (t->txnid == TXN_INVALID)
+	if (txn != NULL)
+		t = txn;
+	else if (__xa_get_txn(dbp->dbenv, &t, 0) != 0 ||
+	    t->txnid== TXN_INVALID)
 		t = NULL;
 
 	return (((XA_METHODS *)dbp->xa_internal)->cursor (dbp, t, dbcp, flags));
@@ -125,10 +138,7 @@ __xa_del(dbp, txn, key, flags)
 {
 	DB_TXN *t;
 
-	t = txn != NULL ? txn : dbp->dbenv->xa_txn;
-	if (t->txnid == TXN_INVALID)
-		t = NULL;
-
+	SET_TXN(txn, t);
 	return (((XA_METHODS *)dbp->xa_internal)->del(dbp, t, key, flags));
 }
 
@@ -156,10 +166,7 @@ __xa_get(dbp, txn, key, data, flags)
 {
 	DB_TXN *t;
 
-	t = txn != NULL ? txn : dbp->dbenv->xa_txn;
-	if (t->txnid == TXN_INVALID)
-		t = NULL;
-
+	SET_TXN(txn, t);
 	return (((XA_METHODS *)dbp->xa_internal)->get
 	    (dbp, t, key, data, flags));
 }
@@ -173,9 +180,7 @@ __xa_put(dbp, txn, key, data, flags)
 {
 	DB_TXN *t;
 
-	t = txn != NULL ? txn : dbp->dbenv->xa_txn;
-	if (t->txnid == TXN_INVALID)
-		t = NULL;
+	SET_TXN(txn, t);
 
 	return (((XA_METHODS *)dbp->xa_internal)->put
 	    (dbp, t, key, data, flags));
diff --git a/storage/bdb/xa/xa_map.c b/storage/bdb/xa/xa_map.c
index 42fa4b20ed29ec235d16f2ecab2efbe8dc1450a8..80fb3dac48cd867b90180ba547a6cc7ae5d6d0df 100644
--- a/storage/bdb/xa/xa_map.c
+++ b/storage/bdb/xa/xa_map.c
@@ -1,16 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996-2002
+ * Copyright (c) 1996-2004
  *	Sleepycat Software.  All rights reserved.
+ *
+ * $Id: xa_map.c,v 11.25 2004/10/15 16:59:46 bostic Exp $
  */
 
 #include "db_config.h"
 
-#ifndef lint
-static const char revid[] = "$Id: xa_map.c,v 11.19 2002/09/03 14:58:27 sue Exp $";
-#endif /* not lint */
-
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
@@ -32,15 +30,15 @@ static const char revid[] = "$Id: xa_map.c,v 11.19 2002/09/03 14:58:27 sue Exp $
  * PUBLIC: int __db_rmid_to_env __P((int rmid, DB_ENV **envp));
  */
 int
-__db_rmid_to_env(rmid, envp)
+__db_rmid_to_env(rmid, dbenvp)
 	int rmid;
-	DB_ENV **envp;
+	DB_ENV **dbenvp;
 {
-	DB_ENV *env;
+	DB_ENV *dbenv;
 
-	env = TAILQ_FIRST(&DB_GLOBAL(db_envq));
-	if (env != NULL && env->xa_rmid == rmid) {
-		*envp = env;
+	dbenv = TAILQ_FIRST(&DB_GLOBAL(db_envq));
+	if (dbenv != NULL && dbenv->xa_rmid == rmid) {
+		*dbenvp = dbenv;
 		return (0);
 	}
 
@@ -49,11 +47,11 @@ __db_rmid_to_env(rmid, envp)
 	 * the list of environments, so we acquire the correct environment
 	 * in DB->open.
 	 */
-	for (; env != NULL; env = TAILQ_NEXT(env, links))
-		if (env->xa_rmid == rmid) {
-			TAILQ_REMOVE(&DB_GLOBAL(db_envq), env, links);
-			TAILQ_INSERT_HEAD(&DB_GLOBAL(db_envq), env, links);
-			*envp = env;
+	for (; dbenv != NULL; dbenv = TAILQ_NEXT(dbenv, links))
+		if (dbenv->xa_rmid == rmid) {
+			TAILQ_REMOVE(&DB_GLOBAL(db_envq), dbenv, links);
+			TAILQ_INSERT_HEAD(&DB_GLOBAL(db_envq), dbenv, links);
+			*dbenvp = dbenv;
 			return (0);
 		}
 
@@ -64,13 +62,13 @@ __db_rmid_to_env(rmid, envp)
  * __db_xid_to_txn
  *	Return the txn that corresponds to this XID.
  *
- * PUBLIC: int __db_xid_to_txn __P((DB_ENV *, XID *, size_t *));
+ * PUBLIC: int __db_xid_to_txn __P((DB_ENV *, XID *, roff_t *));
  */
 int
 __db_xid_to_txn(dbenv, xid, offp)
 	DB_ENV *dbenv;
 	XID *xid;
-	size_t *offp;
+	roff_t *offp;
 {
 	struct __txn_detail *td;
 
@@ -84,12 +82,12 @@ __db_xid_to_txn(dbenv, xid, offp)
  * PUBLIC: int __db_map_rmid __P((int, DB_ENV *));
  */
 int
-__db_map_rmid(rmid, env)
+__db_map_rmid(rmid, dbenv)
 	int rmid;
-	DB_ENV *env;
+	DB_ENV *dbenv;
 {
-	env->xa_rmid = rmid;
-	TAILQ_INSERT_TAIL(&DB_GLOBAL(db_envq), env, links);
+	dbenv->xa_rmid = rmid;
+	TAILQ_INSERT_TAIL(&DB_GLOBAL(db_envq), dbenv, links);
 	return (0);
 }
 
@@ -107,7 +105,8 @@ __db_unmap_rmid(rmid)
 
 	for (e = TAILQ_FIRST(&DB_GLOBAL(db_envq));
 	    e->xa_rmid != rmid;
-	    e = TAILQ_NEXT(e, links));
+	    e = TAILQ_NEXT(e, links))
+	    ;
 
 	if (e == NULL)
 		return (EINVAL);
@@ -124,23 +123,23 @@ __db_unmap_rmid(rmid)
  * PUBLIC: int __db_map_xid __P((DB_ENV *, XID *, size_t));
  */
 int
-__db_map_xid(env, xid, off)
-	DB_ENV *env;
+__db_map_xid(dbenv, xid, off)
+	DB_ENV *dbenv;
 	XID *xid;
 	size_t off;
 {
 	REGINFO *infop;
 	TXN_DETAIL *td;
 
-	infop = &((DB_TXNMGR *)env->tx_handle)->reginfo;
-	td = (TXN_DETAIL *)R_ADDR(infop, off);
+	infop = &((DB_TXNMGR *)dbenv->tx_handle)->reginfo;
+	td = R_ADDR(infop, off);
 
-	R_LOCK(env, infop);
+	R_LOCK(dbenv, infop);
 	memcpy(td->xid, xid->data, XIDDATASIZE);
 	td->bqual = (u_int32_t)xid->bqual_length;
 	td->gtrid = (u_int32_t)xid->gtrid_length;
 	td->format = (int32_t)xid->formatID;
-	R_UNLOCK(env, infop);
+	R_UNLOCK(dbenv, infop);
 
 	return (0);
 }
@@ -153,8 +152,8 @@ __db_map_xid(env, xid, off)
  */
 
 void
-__db_unmap_xid(env, xid, off)
-	DB_ENV *env;
+__db_unmap_xid(dbenv, xid, off)
+	DB_ENV *dbenv;
 	XID *xid;
 	size_t off;
 {
@@ -162,6 +161,6 @@ __db_unmap_xid(env, xid, off)
 
 	COMPQUIET(xid, NULL);
 
-	td = (TXN_DETAIL *)R_ADDR(&((DB_TXNMGR *)env->tx_handle)->reginfo, off);
+	td = R_ADDR(&((DB_TXNMGR *)dbenv->tx_handle)->reginfo, off);
 	memset(td->xid, 0, sizeof(td->xid));
 }