From 8897fff4f352923b91e776bf9bc0bf8dbd636e85 Mon Sep 17 00:00:00 2001
From: zhangqiumiao <zhangqiumiao1@huawei.com>
Date: Fri, 25 Sep 2020 21:54:05 +0800
Subject: [PATCH] backport delete back-bdb/back-hdb

---
 INSTALL                                       |    3 -
 build/openldap.m4                             |  292 ---
 build/top.mk                                  |    1 -
 configure.in                                  |   74 +-
 contrib/slapd-modules/allowed/allowed.c       |    2 +-
 contrib/slapd-modules/nssov/README            |    4 +-
 contrib/slapd-modules/nssov/slapo-nssov.5     |    2 +-
 doc/guide/admin/appendix-changes.sdf          |   27 +-
 doc/guide/admin/appendix-common-errors.sdf    |   10 +-
 doc/guide/admin/aspell.en.pws                 |    7 -
 doc/guide/admin/backends.sdf                  |   47 +-
 doc/guide/admin/install.sdf                   |   17 -
 doc/guide/admin/intro.sdf                     |   12 +-
 doc/guide/admin/maintenance.sdf               |   86 +-
 doc/guide/admin/monitoringslapd.sdf           |   25 +-
 doc/guide/admin/overlays.sdf                  |    6 +-
 doc/guide/admin/replication.sdf               |   12 +-
 doc/guide/admin/slapdconf2.sdf                |  237 +--
 doc/guide/admin/slapdconfig.sdf               |  218 ++-
 doc/guide/admin/tuning.sdf                    |  175 +-
 doc/guide/preamble.sdf                        |    2 -
 doc/guide/release/install.sdf                 |    2 +-
 doc/man/man5/slapd-bdb.5                      |  286 ---
 doc/man/man5/slapd-bdb.5.links                |    1 -
 doc/man/man5/slapd-config.5                   |    8 +-
 doc/man/man5/slapd-mdb.5                      |    7 +-
 doc/man/man5/slapd-sql.5                      |    2 +-
 doc/man/man5/slapd.access.5                   |    9 +-
 doc/man/man5/slapd.backends.5                 |   35 +-
 doc/man/man5/slapd.conf.5                     |    7 +-
 doc/man/man5/slapd.overlays.5                 |    6 +-
 doc/man/man8/slapcat.8                        |    2 -
 doc/man/man8/slapschema.8                     |    3 +-
 include/portable.hin                          |   12 -
 servers/slapd/DB_CONFIG                       |   28 -
 servers/slapd/Makefile.in                     |   12 +-
 servers/slapd/alock.c                         |  718 -------
 servers/slapd/alock.h                         |   74 -
 servers/slapd/back-bdb/Makefile.in            |   53 -
 servers/slapd/back-bdb/add.c                  |  547 ------
 servers/slapd/back-bdb/attr.c                 |  441 -----
 servers/slapd/back-bdb/back-bdb.h             |  377 ----
 servers/slapd/back-bdb/bind.c                 |  166 --
 servers/slapd/back-bdb/cache.c                | 1692 -----------------
 servers/slapd/back-bdb/compare.c              |  143 --
 servers/slapd/back-bdb/config.c               |  951 ---------
 servers/slapd/back-bdb/dbcache.c              |  210 --
 servers/slapd/back-bdb/delete.c               |  605 ------
 servers/slapd/back-bdb/dn2entry.c             |   84 -
 servers/slapd/back-bdb/dn2id.c                | 1215 ------------
 servers/slapd/back-bdb/error.c                |   62 -
 servers/slapd/back-bdb/extended.c             |   54 -
 servers/slapd/back-bdb/filterindex.c          | 1183 ------------
 servers/slapd/back-bdb/id2entry.c             |  446 -----
 servers/slapd/back-bdb/idl.c                  | 1570 ---------------
 servers/slapd/back-bdb/idl.h                  |   75 -
 servers/slapd/back-bdb/index.c                |  574 ------
 servers/slapd/back-bdb/init.c                 |  874 ---------
 servers/slapd/back-bdb/key.c                  |  104 -
 servers/slapd/back-bdb/modify.c               |  835 --------
 servers/slapd/back-bdb/modrdn.c               |  842 --------
 servers/slapd/back-bdb/monitor.c              |  724 -------
 servers/slapd/back-bdb/nextid.c               |   80 -
 servers/slapd/back-bdb/operational.c          |  151 --
 servers/slapd/back-bdb/proto-bdb.h            |  678 -------
 servers/slapd/back-bdb/referral.c             |  152 --
 servers/slapd/back-bdb/search.c               | 1388 --------------
 servers/slapd/back-bdb/tools.c                | 1327 -------------
 servers/slapd/back-bdb/trans.c                |   56 -
 servers/slapd/back-hdb/Makefile.in            |   70 -
 servers/slapd/back-hdb/back-bdb.h             |   31 -
 servers/slapd/back-monitor/init.c             |    8 +-
 servers/slapd/bconfig.c                       |    2 +-
 servers/slapd/dn.c                            |    3 +-
 servers/slapd/overlays/pcache.c               |    4 +-
 servers/slapd/slap.h                          |    1 -
 servers/slapd/slapd.ldif                      |    3 +-
 tests/Makefile.in                             |   36 -
 tests/README                                  |    2 -
 tests/data/regressions/its4184/its4184        |    4 -
 tests/data/regressions/its4448/its4448        |   16 -
 tests/data/slapd-proxyauthz.conf              |    4 -
 tests/data/slapd-proxycache.conf              |    4 -
 tests/data/slapd-ref-slave.conf               |    2 -
 tests/data/slapd.conf                         |    2 -
 tests/run.in                                  |    8 +-
 tests/scripts/test023-refint                  |   97 +-
 tests/scripts/test025-limits                  |    2 +-
 tests/scripts/test036-meta-concurrency        |   16 -
 tests/scripts/test040-subtree-rename          |    5 -
 tests/scripts/test043-delta-syncrepl          |    2 +-
 tests/scripts/test052-memberof                |    4 +-
 tests/scripts/test056-monitor                 |    6 +-
 tests/scripts/test057-memberof-refint         |    9 +-
 .../test061-syncreplication-initiation        |    1 -
 95 files changed, 418 insertions(+), 20054 deletions(-)
 delete mode 100644 doc/man/man5/slapd-bdb.5
 delete mode 100644 doc/man/man5/slapd-bdb.5.links
 delete mode 100644 servers/slapd/DB_CONFIG
 delete mode 100644 servers/slapd/alock.c
 delete mode 100644 servers/slapd/alock.h
 delete mode 100644 servers/slapd/back-bdb/Makefile.in
 delete mode 100644 servers/slapd/back-bdb/add.c
 delete mode 100644 servers/slapd/back-bdb/attr.c
 delete mode 100644 servers/slapd/back-bdb/back-bdb.h
 delete mode 100644 servers/slapd/back-bdb/bind.c
 delete mode 100644 servers/slapd/back-bdb/cache.c
 delete mode 100644 servers/slapd/back-bdb/compare.c
 delete mode 100644 servers/slapd/back-bdb/config.c
 delete mode 100644 servers/slapd/back-bdb/dbcache.c
 delete mode 100644 servers/slapd/back-bdb/delete.c
 delete mode 100644 servers/slapd/back-bdb/dn2entry.c
 delete mode 100644 servers/slapd/back-bdb/dn2id.c
 delete mode 100644 servers/slapd/back-bdb/error.c
 delete mode 100644 servers/slapd/back-bdb/extended.c
 delete mode 100644 servers/slapd/back-bdb/filterindex.c
 delete mode 100644 servers/slapd/back-bdb/id2entry.c
 delete mode 100644 servers/slapd/back-bdb/idl.c
 delete mode 100644 servers/slapd/back-bdb/idl.h
 delete mode 100644 servers/slapd/back-bdb/index.c
 delete mode 100644 servers/slapd/back-bdb/init.c
 delete mode 100644 servers/slapd/back-bdb/key.c
 delete mode 100644 servers/slapd/back-bdb/modify.c
 delete mode 100644 servers/slapd/back-bdb/modrdn.c
 delete mode 100644 servers/slapd/back-bdb/monitor.c
 delete mode 100644 servers/slapd/back-bdb/nextid.c
 delete mode 100644 servers/slapd/back-bdb/operational.c
 delete mode 100644 servers/slapd/back-bdb/proto-bdb.h
 delete mode 100644 servers/slapd/back-bdb/referral.c
 delete mode 100644 servers/slapd/back-bdb/search.c
 delete mode 100644 servers/slapd/back-bdb/tools.c
 delete mode 100644 servers/slapd/back-bdb/trans.c
 delete mode 100644 servers/slapd/back-hdb/Makefile.in
 delete mode 100644 servers/slapd/back-hdb/back-bdb.h

diff --git a/INSTALL b/INSTALL
index e8a4fb3..0805e1c 100644
--- a/INSTALL
+++ b/INSTALL
@@ -73,9 +73,6 @@ Making and Installing the OpenLDAP Distribution
 
 6.   Test the standalone system:
 
-     This step requires the standalone LDAP server, slapd(8), with HDB
-     and/or BDB support.
-
         % make test
 
      If all goes well, the system has been built as configured.  If
diff --git a/build/openldap.m4 b/build/openldap.m4
index 80fda16..fd768aa 100644
--- a/build/openldap.m4
+++ b/build/openldap.m4
@@ -243,298 +243,6 @@ OL_RESOLVER_TRY(ol_cv_resolver_none)
 OL_RESOLVER_TRY(ol_cv_resolver_resolv,[-lresolv])
 OL_RESOLVER_TRY(ol_cv_resolver_bind,[-lbind])
 ])
-dnl
-dnl ====================================================================
-dnl Berkeley DB macros
-dnl
-dnl --------------------------------------------------------------------
-dnl Try to link
-AC_DEFUN([OL_BERKELEY_DB_TRY],
-[if test $ol_cv_lib_db = no ; then
-	AC_CACHE_CHECK([for Berkeley DB link (]ifelse($2,,default,$2)[)],[$1],
-[
-	ol_DB_LIB=ifelse($2,,,$2)
-	ol_LIBS=$LIBS
-	LIBS="$ol_DB_LIB $LTHREAD_LIBS $LIBS"
-
-	AC_LINK_IFELSE([AC_LANG_PROGRAM([[
-#ifdef HAVE_DB_185_H
-# include <db_185.h>
-#else
-# include <db.h>
-#endif
-
-#ifndef DB_VERSION_MAJOR
-# define DB_VERSION_MAJOR 1
-#endif
-
-#ifndef NULL
-#define NULL ((void*)0)
-#endif
-]], [[
-#if DB_VERSION_MAJOR > 2
-	db_env_create( NULL, 0 );
-#elif DB_VERSION_MAJOR > 1
-	db_appexit( NULL );
-#else
-	(void) dbopen( NULL, 0, 0, 0, NULL);
-#endif
-]])],[$1=yes],[$1=no])
-
-	LIBS="$ol_LIBS"
-])
-
-	if test $$1 = yes ; then
-		ol_cv_lib_db=ifelse($2,,yes,$2)
-	fi
-fi
-])
-dnl
-dnl --------------------------------------------------------------------
-dnl Get major and minor version from <db.h>
-AC_DEFUN([OL_BDB_HEADER_VERSION],
-[AC_CACHE_CHECK([for Berkeley DB major version in db.h], [ol_cv_bdb_major],[
-	AC_LANG_CONFTEST([
-#include <db.h>
-#ifndef DB_VERSION_MAJOR
-#	define DB_VERSION_MAJOR 1
-#endif
-__db_version DB_VERSION_MAJOR
-])
-	set X `eval "$ac_cpp -P conftest.$ac_ext" | $EGREP __db_version` none none
-	ol_cv_bdb_major=${3}
-])
-case $ol_cv_bdb_major in [[1-9]]*) : ;; *)
-	AC_MSG_ERROR([Unknown Berkeley DB major version in db.h]) ;;
-esac
-
-dnl Determine minor version
-AC_CACHE_CHECK([for Berkeley DB minor version in db.h], [ol_cv_bdb_minor],[
-	AC_LANG_CONFTEST([
-#include <db.h>
-#ifndef DB_VERSION_MINOR
-#	define DB_VERSION_MINOR 0
-#endif
-__db_version DB_VERSION_MINOR
-])
-	set X `eval "$ac_cpp -P conftest.$ac_ext" | $EGREP __db_version` none none
-	ol_cv_bdb_minor=${3}
-])
-case $ol_cv_bdb_minor in [[0-9]]*) : ;; *)
-	AC_MSG_ERROR([Unknown Berkeley DB minor version in db.h]) ;;
-esac
-])
-dnl
-dnl --------------------------------------------------------------------
-dnl Try to locate appropriate library
-AC_DEFUN([OL_BERKELEY_DB_LINK],
-[ol_cv_lib_db=no
-
-if test $ol_cv_bdb_major = 5 ; then
-	OL_BERKELEY_DB_TRY(ol_cv_db_db_5_dot_m,[-ldb-5.$ol_cv_bdb_minor])
-	OL_BERKELEY_DB_TRY(ol_cv_db_db5m,[-ldb5$ol_cv_bdb_minor])
-	OL_BERKELEY_DB_TRY(ol_cv_db_db_5m,[-ldb-5$ol_cv_bdb_minor])
-	OL_BERKELEY_DB_TRY(ol_cv_db_db_5_m,[-ldb-5-$ol_cv_bdb_minor])
-	OL_BERKELEY_DB_TRY(ol_cv_db_db_5,[-ldb-5])
-	OL_BERKELEY_DB_TRY(ol_cv_db_db5,[-ldb5])
-elif test $ol_cv_bdb_major = 4 ; then
-	OL_BERKELEY_DB_TRY(ol_cv_db_db_4_dot_m,[-ldb-4.$ol_cv_bdb_minor])
-	OL_BERKELEY_DB_TRY(ol_cv_db_db4m,[-ldb4$ol_cv_bdb_minor])
-	OL_BERKELEY_DB_TRY(ol_cv_db_db_4m,[-ldb-4$ol_cv_bdb_minor])
-	OL_BERKELEY_DB_TRY(ol_cv_db_db_4_m,[-ldb-4-$ol_cv_bdb_minor])
-	OL_BERKELEY_DB_TRY(ol_cv_db_db_4,[-ldb-4])
-	OL_BERKELEY_DB_TRY(ol_cv_db_db4,[-ldb4])
-fi
-OL_BERKELEY_DB_TRY(ol_cv_db_db,[-ldb])
-OL_BERKELEY_DB_TRY(ol_cv_db_none)
-])
-dnl
-dnl --------------------------------------------------------------------
-dnl Check if Berkeley DB version
-AC_DEFUN([OL_BERKELEY_DB_VERSION],
-[AC_CACHE_CHECK([for Berkeley DB library and header version match], [ol_cv_berkeley_db_version], [
-	ol_LIBS="$LIBS"
-	LIBS="$LTHREAD_LIBS $LIBS"
-	if test $ol_cv_lib_db != yes ; then
-		LIBS="$ol_cv_lib_db $LIBS"
-	fi
-
-	AC_RUN_IFELSE([AC_LANG_SOURCE([[
-#ifdef HAVE_DB_185_H
-	choke me;
-#else
-#include <db.h>
-#endif
-#ifndef DB_VERSION_MAJOR
-# define DB_VERSION_MAJOR 1
-#endif
-#ifndef NULL
-#define NULL ((void *)0)
-#endif
-main()
-{
-#if DB_VERSION_MAJOR > 1
-	char *version;
-	int major, minor, patch;
-
-	version = db_version( &major, &minor, &patch );
-
-	if( major != DB_VERSION_MAJOR ||
-		minor != DB_VERSION_MINOR ||
-		patch != DB_VERSION_PATCH )
-	{
-		printf("Berkeley DB version mismatch\n"
-			"\theader: %s\n\tlibrary: %s\n",
-			DB_VERSION_STRING, version);
-		return 1;
-	}
-#endif
-
-	return 0;
-}]])],[ol_cv_berkeley_db_version=yes],[ol_cv_berkeley_db_version=no],[ol_cv_berkeley_db_version=cross])
-
-	LIBS="$ol_LIBS"
-])
-
-	if test $ol_cv_berkeley_db_version = no ; then
-		AC_MSG_ERROR([Berkeley DB version mismatch])
-	fi
-])dnl
-dnl
-dnl --------------------------------------------------------------------
-dnl Check if Berkeley DB supports DB_THREAD
-AC_DEFUN([OL_BERKELEY_DB_THREAD],
-[AC_CACHE_CHECK([for Berkeley DB thread support], [ol_cv_berkeley_db_thread], [
-	ol_LIBS="$LIBS"
-	LIBS="$LTHREAD_LIBS $LIBS"
-	if test $ol_cv_lib_db != yes ; then
-		LIBS="$ol_cv_lib_db $LIBS"
-	fi
-
-	AC_RUN_IFELSE([AC_LANG_SOURCE([[
-#ifdef HAVE_DB_185_H
-	choke me;
-#else
-#include <db.h>
-#endif
-#ifndef NULL
-#define NULL ((void *)0)
-#endif
-main()
-{
-	int rc;
-	u_int32_t flags = DB_CREATE |
-#ifdef DB_PRIVATE
-		DB_PRIVATE |
-#endif
-		DB_THREAD;
-
-#if DB_VERSION_MAJOR > 2
-	DB_ENV *env = NULL;
-
-	rc = db_env_create( &env, 0 );
-
-	flags |= DB_INIT_MPOOL;
-#ifdef DB_MPOOL_PRIVATE
-	flags |= DB_MPOOL_PRIVATE;
-#endif
-
-	if( rc ) {
-		printf("BerkeleyDB: %s\n", db_strerror(rc) );
-		return rc;
-	}
-
-#if (DB_VERSION_MAJOR > 3) || (DB_VERSION_MINOR >= 1)
-	rc = (env->open)( env, NULL, flags, 0 );
-#else
-	rc = (env->open)( env, NULL, NULL, flags, 0 );
-#endif
-
-	if ( rc == 0 ) {
-		rc = env->close( env, 0 );
-	}
-
-	if( rc ) {
-		printf("BerkeleyDB: %s\n", db_strerror(rc) );
-		return rc;
-	}
-
-#else
-	DB_ENV env;
-	memset( &env, '\0', sizeof(env) );
-
-	rc = db_appinit( NULL, NULL, &env, flags );
-
-	if( rc == 0 ) {
-		db_appexit( &env );
-	}
-
-	unlink("__db_mpool.share");
-	unlink("__db_lock.share");
-#endif
-
-	return rc;
-}]])],[ol_cv_berkeley_db_thread=yes],[ol_cv_berkeley_db_thread=no],[ol_cv_berkeley_db_thread=cross])
-
-	LIBS="$ol_LIBS"
-])
-
-	if test $ol_cv_berkeley_db_thread != no ; then
-		AC_DEFINE(HAVE_BERKELEY_DB_THREAD, 1,
-			[define if Berkeley DB has DB_THREAD support])
-	fi
-])dnl
-dnl
-dnl --------------------------------------------------------------------
-dnl Find any DB
-AC_DEFUN([OL_BERKELEY_DB],
-[ol_cv_berkeley_db=no
-AC_CHECK_HEADERS(db.h)
-if test $ac_cv_header_db_h = yes; then
-	OL_BDB_HEADER_VERSION
-	OL_BDB_COMPAT
-
-	if test $ol_cv_bdb_compat != yes ; then
-		AC_MSG_ERROR([BerkeleyDB version incompatible with BDB/HDB backends])
-	fi
-
-	OL_BERKELEY_DB_LINK
-	if test "$ol_cv_lib_db" != no ; then
-		ol_cv_berkeley_db=yes
-		OL_BERKELEY_DB_VERSION
-		OL_BERKELEY_DB_THREAD
-	fi
-fi
-])
-dnl --------------------------------------------------------------------
-dnl Check for version compatility with back-bdb
-AC_DEFUN([OL_BDB_COMPAT],
-[AC_CACHE_CHECK([if Berkeley DB version supported by BDB/HDB backends], [ol_cv_bdb_compat],[
-	AC_EGREP_CPP(__db_version_compat,[
-#include <db.h>
-
- /* this check could be improved */
-#ifndef DB_VERSION_MAJOR
-#	define DB_VERSION_MAJOR 1
-#endif
-#ifndef DB_VERSION_MINOR
-#	define DB_VERSION_MINOR 0
-#endif
-#ifndef DB_VERSION_PATCH
-#      define DB_VERSION_PATCH 0
-#endif
-
-#define DB_VERSION_FULL        ((DB_VERSION_MAJOR<<16)|(DB_VERSION_MINOR<<8)|DB_VERSION_PATCH)
-
-/* require 4.4 or later, but less than 6.0.20 */
-#if DB_VERSION_FULL >= 0x040400 && DB_VERSION_FULL < 0x060014
-	__db_version_compat
-#endif
-#if DB_VERSION_FULL >= 0x060014
-#error "BerkeleyDB 6.0.20+ license is incompatible with LDAP"
-#endif
-	], [ol_cv_bdb_compat=yes], [ol_cv_bdb_compat=no])])
-])
 
 dnl
 dnl ====================================================================
diff --git a/build/top.mk b/build/top.mk
index 6850121..a25c5fc 100644
--- a/build/top.mk
+++ b/build/top.mk
@@ -159,7 +159,6 @@ LDAP_LIBDIR= $(top_builddir)/libraries
 LUTIL_LIBS = @LUTIL_LIBS@
 LTHREAD_LIBS = @LTHREAD_LIBS@
 
-BDB_LIBS = @BDB_LIBS@
 SLAPD_NDB_LIBS = @SLAPD_NDB_LIBS@
 
 LDAP_LIBLBER_LA = $(LDAP_LIBDIR)/liblber/liblber.la
diff --git a/configure.in b/configure.in
index c70241a..065eae3 100644
--- a/configure.in
+++ b/configure.in
@@ -282,9 +282,7 @@ OL_ARG_ENABLE(wrappers,[    --enable-wrappers	  enable tcp wrapper support], no)
 
 dnl ----------------------------------------------------------------
 dnl SLAPD Backend Options
-Backends="bdb \
-	dnssrv \
-	hdb \
+Backends="dnssrv \
 	ldap \
 	mdb \
 	meta \
@@ -303,12 +301,8 @@ SLAPD Backend Options:])
 
 OL_ARG_ENABLE(backends,[    --enable-backends	  enable all available backends],
 	--, [no yes mod])dnl
-OL_ARG_ENABLE(bdb,[    --enable-bdb	  enable Berkeley DB backend],
-	yes, [no yes mod], ol_enable_backends)dnl
 OL_ARG_ENABLE(dnssrv,[    --enable-dnssrv	  enable dnssrv backend],
 	no, [no yes mod], ol_enable_backends)dnl
-OL_ARG_ENABLE(hdb,[    --enable-hdb	  enable Hierarchical DB backend],
-	yes, [no yes mod], ol_enable_backends)dnl
 OL_ARG_ENABLE(ldap,[    --enable-ldap	  enable ldap backend],
 	no, [no yes mod], ol_enable_backends)dnl
 OL_ARG_ENABLE(mdb,[    --enable-mdb	  enable mdb database backend],
@@ -471,9 +465,7 @@ if test $ol_enable_slapd = no ; then
 	ol_enable_rewrite=no
 
 elif test $ol_enable_modules != yes &&
-	test $ol_enable_bdb = no &&
 	test $ol_enable_dnssrv = no &&
-	test $ol_enable_hdb = no &&
 	test $ol_enable_ldap = no &&
 	test $ol_enable_mdb = no &&
 	test $ol_enable_meta = no &&
@@ -518,7 +510,6 @@ AC_MSG_RESULT(done)
 dnl ----------------------------------------------------------------
 dnl Initialize vars
 LDAP_LIBS=
-BDB_LIBS=
 SLAPD_NDB_LIBS=
 SLAPD_NDB_INCS=
 LTHREAD_LIBS=
@@ -533,9 +524,7 @@ BUILD_THREAD=no
 BUILD_SLAPI=no
 SLAPD_SLAPI_DEPEND=
 
-BUILD_BDB=no
 BUILD_DNSSRV=no
-BUILD_HDB=no
 BUILD_LDAP=no
 BUILD_MDB=no
 BUILD_META=no
@@ -1867,36 +1856,6 @@ else
  	ol_cv_func_gethostbyaddr_r_nargs=0
 fi
 
-dnl ----------------------------------------------------------------
-ol_link_bdb=no 
-
-if test $ol_enable_bdb/$ol_enable_hdb != no/no; then
-	OL_BERKELEY_DB
-
-	if test $ol_cv_berkeley_db = no ; then
-		AC_MSG_ERROR(BDB/HDB: BerkeleyDB not available)
-	fi
-
-	AC_DEFINE(HAVE_BERKELEY_DB,1,
-		[define this if Berkeley DB is available])
-
-	dnl $ol_cv_lib_db should be yes or -ldb
-	dnl (it could be no, but that would be an error
-	if test $ol_cv_lib_db != yes ; then
-		BDB_LIBS="$BDB_LIBS $ol_cv_lib_db"
-	fi
-
-	dnl link BDB library to slapd when there is a
-	dnl static BDB based backend in use
-	if test $ol_enable_bdb/$ol_enable_hdb != mod/mod ; then
-		if test $ol_enable_bdb = yes -o $ol_enable_hdb = yes ; then
-			SLAPD_LIBS="$SLAPD_LIBS \$(BDB_LIBS)"
-		fi
-	fi
-
-	ol_link_bdb=yes 
-fi
-
 dnl ----------------------------------------------------------------
 
 if test $ol_enable_dynamic = yes && test $enable_shared = yes ; then
@@ -2610,19 +2569,6 @@ if test "$ol_enable_monitor" != no ; then
 	AC_DEFINE_UNQUOTED(SLAPD_MONITOR,$MFLAG,[define to support cn=Monitor backend])
 fi
 
-if test "$ol_enable_bdb" != no ; then
-	BUILD_SLAPD=yes
-	BUILD_BDB=$ol_enable_bdb
-	if test "$ol_enable_bdb" = mod ; then
-		SLAPD_DYNAMIC_BACKENDS="$SLAPD_DYNAMIC_BACKENDS back-bdb"
-		MFLAG=SLAPD_MOD_DYNAMIC
-	else
-		SLAPD_STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS back-bdb"
-		MFLAG=SLAPD_MOD_STATIC
-	fi
-	AC_DEFINE_UNQUOTED(SLAPD_BDB,$MFLAG,[define to support BDB backend])
-fi
-
 if test "$ol_enable_dnssrv" != no ; then
 	BUILD_SLAPD=yes
 	BUILD_DNSSRV=$ol_enable_dnssrv
@@ -2636,19 +2582,6 @@ if test "$ol_enable_dnssrv" != no ; then
 	AC_DEFINE_UNQUOTED(SLAPD_DNSSRV,$MFLAG,[define to support DNS SRV backend])
 fi
 
-if test "$ol_enable_hdb" != no ; then
-	BUILD_SLAPD=yes
-	BUILD_HDB=$ol_enable_hdb
-	if test "$ol_enable_hdb" = mod ; then
-		SLAPD_DYNAMIC_BACKENDS="$SLAPD_DYNAMIC_BACKENDS back-hdb"
-		MFLAG=SLAPD_MOD_DYNAMIC
-	else
-		SLAPD_STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS back-hdb"
-		MFLAG=SLAPD_MOD_STATIC
-	fi
-	AC_DEFINE_UNQUOTED(SLAPD_HDB,$MFLAG,[define to support HDB backend])
-fi
-
 if test "$ol_enable_ldap" != no ; then
 	BUILD_SLAPD=yes
 	BUILD_LDAP=$ol_enable_ldap
@@ -3076,9 +3009,7 @@ dnl slapi
   AC_SUBST(BUILD_SLAPI)
   AC_SUBST(SLAPD_SLAPI_DEPEND)
 dnl backends
-  AC_SUBST(BUILD_BDB)
   AC_SUBST(BUILD_DNSSRV)
-  AC_SUBST(BUILD_HDB)
   AC_SUBST(BUILD_LDAP)
   AC_SUBST(BUILD_MDB)
   AC_SUBST(BUILD_META)
@@ -3117,7 +3048,6 @@ dnl overlays
 
 AC_SUBST(LDAP_LIBS)
 AC_SUBST(SLAPD_LIBS)
-AC_SUBST(BDB_LIBS)
 AC_SUBST(SLAPD_NDB_LIBS)
 AC_SUBST(SLAPD_NDB_INCS)
 AC_SUBST(LTHREAD_LIBS)
@@ -3181,9 +3111,7 @@ AC_CONFIG_FILES([Makefile:build/top.mk:Makefile.in:build/dir.mk]
 [libraries/librewrite/Makefile:build/top.mk:libraries/librewrite/Makefile.in:build/lib.mk:build/lib-static.mk]
 [servers/Makefile:build/top.mk:servers/Makefile.in:build/dir.mk]
 [servers/slapd/Makefile:build/top.mk:servers/slapd/Makefile.in:build/srv.mk]
-[servers/slapd/back-bdb/Makefile:build/top.mk:servers/slapd/back-bdb/Makefile.in:build/mod.mk]
 [servers/slapd/back-dnssrv/Makefile:build/top.mk:servers/slapd/back-dnssrv/Makefile.in:build/mod.mk]
-[servers/slapd/back-hdb/Makefile:build/top.mk:servers/slapd/back-hdb/Makefile.in:build/mod.mk]
 [servers/slapd/back-ldap/Makefile:build/top.mk:servers/slapd/back-ldap/Makefile.in:build/mod.mk]
 [servers/slapd/back-ldif/Makefile:build/top.mk:servers/slapd/back-ldif/Makefile.in:build/mod.mk]
 [servers/slapd/back-mdb/Makefile:build/top.mk:servers/slapd/back-mdb/Makefile.in:build/mod.mk]
diff --git a/contrib/slapd-modules/allowed/allowed.c b/contrib/slapd-modules/allowed/allowed.c
index 5f2810f..8ca0889 100644
--- a/contrib/slapd-modules/allowed/allowed.c
+++ b/contrib/slapd-modules/allowed/allowed.c
@@ -27,7 +27,7 @@
  * Caveats:
  * - right now, the overlay assumes that all values of the objectClass
  *   attribute will be returned in rs->sr_entry; this may not be true
- *   in general, but it usually is for back-bdb/back-hdb.  To generalize,
+ *   in general, but it usually is for back-mdb.  To generalize,
  *   the search request should be analyzed, and if allowedAttributes or
  *   allowedAttributesEffective are requested, add objectClass to the
  *   requested attributes
diff --git a/contrib/slapd-modules/nssov/README b/contrib/slapd-modules/nssov/README
index ced3872..f8538f9 100644
--- a/contrib/slapd-modules/nssov/README
+++ b/contrib/slapd-modules/nssov/README
@@ -21,7 +21,7 @@ To use the overlay, add:
 	moduleload <path to>nssov.so
 	...
 
-	database hdb
+	database mdb
 	...
 	overlay nssov
 
@@ -65,7 +65,7 @@ See the nss-ldapd/README for the original attribute names used in this code.
 The overlay also supports dynamic configuration in cn=config. The layout
 of the config entry is
 
-	dn: olcOverlay={0}nssov,ocDatabase={1}hdb,cn=config
+	dn: olcOverlay={0}nssov,ocDatabase={1}mdb,cn=config
 	objectClass: olcOverlayConfig
 	objectClass: olcNssOvConfig
 	olcOverlay: {0}nssov
diff --git a/contrib/slapd-modules/nssov/slapo-nssov.5 b/contrib/slapd-modules/nssov/slapo-nssov.5
index 816b661..83621bd 100644
--- a/contrib/slapd-modules/nssov/slapo-nssov.5
+++ b/contrib/slapd-modules/nssov/slapo-nssov.5
@@ -278,7 +278,7 @@ of the config entry is
 .LP 
 .RS
 .nf
-    dn: olcOverlay={0}nssov,ocDatabase={1}hdb,cn=config
+    dn: olcOverlay={0}nssov,ocDatabase={1}mdb,cn=config
     objectClass: olcOverlayConfig
     objectClass: olcNssOvConfig
     olcOverlay: {0}nssov
diff --git a/doc/guide/admin/appendix-changes.sdf b/doc/guide/admin/appendix-changes.sdf
index 5006672..7fe91d1 100644
--- a/doc/guide/admin/appendix-changes.sdf
+++ b/doc/guide/admin/appendix-changes.sdf
@@ -147,11 +147,6 @@ search over 500 thousand entries per second. The search was on an unindexed
 attribute using a filter that would not match any entry, forcing slapd to examine 
 every entry in the DB, testing the filter for a match.
 
-Essentially the slapd entry cache in back-bdb/back-hdb is so efficient the search 
-processing time is almost invisible; the runtime is limited only by the memory 
-bandwidth of the machine. (The search data rate corresponds to about 3.5GB/sec; 
-the memory bandwidth on the machine is only about 4GB/sec due to ECC and register latency.)
-
 H3: New overlays
 
 * slapo-constraint (Attribute value constraints)
@@ -199,21 +194,13 @@ H3: New build options
 * Support for building against GnuTLS
 
 
-H2: Obsolete Features Removed From 2.4
-
-These features were strongly deprecated in 2.3 and removed in 2.4.
-
-H3: Slurpd
+H2: Obsolete Features Removed From 2.5
 
-Please read the {{SECT:Replication}} section as to why this is no longer in
-OpenLDAP
+These features were strongly deprecated in 2.4 and removed in 2.5.
 
-H3: back-ldbm
+H3: back-bdb and back-hdb
 
-back-ldbm was both slow and unreliable. Its byzantine indexing code was
-prone to spontaneous corruption, as were the underlying database libraries
-that were commonly used (e.g. GDBM or NDBM). back-bdb and back-hdb are
-superior in every aspect, with simplified indexing to avoid index corruption,
-fine-grained locking for greater concurrency, hierarchical caching for
-greater performance, streamlined on-disk format for greater efficiency
-and portability, and full transaction support for greater reliability.
+back-bdb and back-hdb were signficantly slower than back-mdb and
+required significant tuning of multiple parameters to maximize
+performance. back-mdb requires no tuning and provides all the
+functionality previously provided via back-bdb and back-hdb.
diff --git a/doc/guide/admin/appendix-common-errors.sdf b/doc/guide/admin/appendix-common-errors.sdf
index 23eef9b..5ead0e1 100644
--- a/doc/guide/admin/appendix-common-errors.sdf
+++ b/doc/guide/admin/appendix-common-errors.sdf
@@ -636,7 +636,7 @@ values of <n>.
 
 H3: ldap_*: Internal (implementation specific) error (80) - additional info: entry index delete failed
 
-This seems to be related with wrong ownership of the BDB's dir (/var/lib/ldap) 
+This seems to be related with wrong ownership of the MDB's dir (/var/lib/ldap)
 and files. The files must be owned by the user that slapd runs as.
 
 >    chown -R ldap:ldap /var/lib/ldap 
@@ -652,11 +652,3 @@ immediately and client gets an error :
 >     SASL/GSSAPI authentication started ldap_sasl_interactive_bind_s: Can't contact LDAP server (-1)
 
 Then check the slapd service, it stopped.
-
-This may come from incompatible of using different versions of BerkeleyDB for 
-installing of SASL and installing of OpenLDAP. The problem arises in case of 
-using multiple version of BerkeleyDB. Solution: - Check which version of 
-BerkeleyDB when install Cyrus SASL. 
-
-Reinstall OpenLDAP with the version of BerkeleyDB above.
-
diff --git a/doc/guide/admin/aspell.en.pws b/doc/guide/admin/aspell.en.pws
index f486703..ae777e2 100644
--- a/doc/guide/admin/aspell.en.pws
+++ b/doc/guide/admin/aspell.en.pws
@@ -102,7 +102,6 @@ NOSYNC
 env
 pagedResultsControl
 dup
-hdb
 LDIFv
 syslog
 monitorTimestamp
@@ -887,7 +886,6 @@ proxyAttrSet
 proxyAttrset
 mary
 crlcheck
-olcBdbConfig
 kadmin
 mech
 slapcat
@@ -1190,7 +1188,6 @@ moddn
 calloc
 LDFLAGS
 attributeOrValueExists
-olcHdbConfig
 bsize
 auditObject
 dnssrv
@@ -1492,7 +1489,6 @@ ghenry
 odbcinst
 reqType
 slapover
-BerkeleyDB's
 attributename
 lwrap
 reqStart
@@ -1628,7 +1624,6 @@ DSAIT
 olcHidden
 mySNMP
 metainformation
-BerkeleyDB
 ldapuri
 auditAbandon
 RANDFILE
@@ -1662,7 +1657,6 @@ olcPasswordHash
 ldapc
 loopback
 ldapi
-BDB's
 GETREALM
 functionalities
 noplain
@@ -1670,7 +1664,6 @@ NOECHOPROMPT
 AES
 ldaps
 notoc
-bdb
 LDAPv
 IPsec
 olcServerID
diff --git a/doc/guide/admin/backends.sdf b/doc/guide/admin/backends.sdf
index 38e9ae2..6e005a6 100644
--- a/doc/guide/admin/backends.sdf
+++ b/doc/guide/admin/backends.sdf
@@ -14,38 +14,9 @@ name of the module for a backend is usually of the form:
 
 >	back_<backend name>.la
 
-So for example, if you need to load the {{hdb}} backend, you would configure
+So for example, if you need to load the {{mdb}} backend, you would configure
 
->	moduleload back_hdb.la
-
-H2: Berkeley DB Backends
-
-
-H3: Overview
-
-The {{hdb}} backend to {{slapd}}(8) is a backend for a 
-normal {{slapd}} database.  It uses the Oracle Berkeley DB ({{TERM:BDB}}) 
-package to store data. It makes extensive use of indexing and caching 
-(see the {{SECT:Tuning}} section) to speed data access.
-
-{{hdb}} is a variant of the original {{bdb}} backend which was first written for use with BDB.
-{{hdb}} uses a hierarchical database layout which supports subtree renames.
-It is otherwise identical to the {{bdb}}
-behavior, and all the same configuration options apply.
-
-Note: An {{hdb}} database needs a large {{idlcachesize}} for good search performance, 
-typically three times the {{cachesize}} (entry cache size) or larger.
-
-Note: The {{hdb}} backend has superseded the {{bdb}} backend, and both will
-soon be deprecated in favor of the new {{mdb}} backend. See below.
-
-H3: back-bdb/back-hdb Configuration
-
-MORE LATER
-
-H3: Further Information
-
-{{slapd-bdb}}(5)
+	moduleload back_mdb.la
 
 H2: LDAP
 
@@ -199,16 +170,16 @@ H3: Overview
 The {{mdb}} backend to {{slapd}}(8) is the recommended primary backend for a
 normal {{slapd}} database.  It uses OpenLDAP's own
 Lightning Memory-Mapped Database ({{TERM:LMDB}})
-library to store data and is intended to replace the Berkeley DB backends.
+library to store data and replace the BerkeleyDB backends used in older
+OpenLDAP releases.
 
-It supports indexing like the BDB backends, but it uses no caching and requires
-no tuning to deliver maximum search performance.  Like {{hdb}}, it is also
-fully hierarchical and supports subtree renames in constant time.
+It supports indexing, it uses no caching and requires no tuning to deliver
+maximum search performance.  It is fully hierarchical and supports subtree
+renames in constant time.
 
 H3: back-mdb Configuration
 
-Unlike the BDB backends, the {{mdb}} backend can be instantiated with very few
-configuration lines:
+The {{mdb}} backend can be instantiated with very few configuration lines:
 
 >	include ./schema/core.schema
 >
@@ -490,7 +461,7 @@ distribute information between different sites/applications that use RDBMSes
 and/or LDAP. Or whatever else...
 
 It is {{B:NOT}} designed as a general-purpose backend that uses RDBMS instead of 
-BerkeleyDB (as the standard BDB backend does), though it can be used as such with 
+LMDB (as the standard back-mdb backend does), though it can be used as such with
 several limitations. Please see {{SECT: LDAP vs RDBMS}} for discussion.
 
 The idea is to use some meta-information to translate LDAP queries to SQL queries, 
diff --git a/doc/guide/admin/install.sdf b/doc/guide/admin/install.sdf
index 9c47b24..4b4e85e 100644
--- a/doc/guide/admin/install.sdf
+++ b/doc/guide/admin/install.sdf
@@ -118,23 +118,6 @@ OpenLDAP's {{slapd}}(8) {{TERM:MDB}} primary database backend uses the {{TERM:LM
 software included with the OpenLDAP source.  There is no need to download any
 additional software to have {{MDB}} support.
 
-OpenLDAP's {{slapd}}(8) {{TERM:BDB}} and {{TERM:HDB}} deprecated database backends
-require {{ORG[expand]Oracle}}'s Berkeley DB.
-If not available at configure time, you will not be able to build
-{{slapd}}(8) with these deprecated database backends.
-
-Your operating system may provide a supported version of
-Berkeley DB in the base system or as an optional
-software component.  If not, you'll have to obtain and
-install it yourself.  Berkeley DB is available from
-{{ORG[expand]Oracle}}'s Berkeley DB download page if required.
-
-There are several versions available from {{ORG[expand]Oracle}}.
-Berkeley DB version 6.0.20 and later uses a software license that is
-incompatible with LDAP technology and should not be used with OpenLDAP.
-
-Note: Please see {{SECT:Recommended OpenLDAP Software Dependency Versions}} for
-more information.
 
 
 H3: Threads
diff --git a/doc/guide/admin/intro.sdf b/doc/guide/admin/intro.sdf
index c3dd92f..6aa2149 100644
--- a/doc/guide/admin/intro.sdf
+++ b/doc/guide/admin/intro.sdf
@@ -346,7 +346,7 @@ really have a "directory".
 
 Existing commercial LDAP server implementations that use a relational database 
 are either from the first kind or the third. I don't know of any implementation 
-that uses a relational database to do inefficiently what BDB does efficiently.
+that uses a relational database to do inefficiently what LMDB does efficiently.
 For those who are interested in "third way" (exposing EXISTING data from RDBMS 
 as LDAP tree, having some limitations compared to classic LDAP model, but making 
 it possible to interoperate between LDAP and SQL applications):
@@ -403,15 +403,9 @@ tags.
 {{B:Choice of database backends}}: {{slapd}} comes with a variety
 of different database backends you can choose from. They include
 {{TERM:MDB}}, a hierarchical high-performance transactional database backend;
-{{TERM:BDB}}, a high-performance transactional database backend (deprecated);
-{{TERM:HDB}}, a hierarchical high-performance transactional
-backend (deprecated); {{SHELL}}, a backend interface to arbitrary shell scripts;
+{{SHELL}}, a backend interface to arbitrary shell scripts;
 and PASSWD, a simple backend interface to the {{passwd}}(5) file.
-The MDB backend utilizes {{TERM:LMDB}}, a high performance replacement
-for {{ORG[expand]Oracle}}'s Berkeley DB.
-The BDB and HDB backends utilize {{ORG[expand]Oracle}} Berkeley DB. These
-backends have been deprecated as LMDB provides significantly higher read
-and write throughput and data reliability.
+The MDB backend utilizes {{TERM:LMDB}}.
 
 {{B:Multiple database instances}}: {{slapd}} can be configured to
 serve multiple databases at the same time. This means that a single
diff --git a/doc/guide/admin/maintenance.sdf b/doc/guide/admin/maintenance.sdf
index deb14b9..3b7503f 100644
--- a/doc/guide/admin/maintenance.sdf
+++ b/doc/guide/admin/maintenance.sdf
@@ -14,23 +14,7 @@ Backup strategies largely depend on the amount of change in the database
 and how much of that change an administrator might be willing to lose in a 
 catastrophic failure. There are two basic methods that can be used:
 
-1. Backup the Berkeley database itself and periodically back up the transaction 
-log files:
-
-Berkeley DB produces transaction logs that can be used to reconstruct
-changes from a given point in time. For example, if an administrator were willing to only
-lose one hour's worth of changes, they could take down the server in
-the middle of the night, copy the Berkeley database files offsite, and bring
-the server back online. Then, on an hourly basis, they could force a
-database checkpoint, capture the log files that have been generated in the
-past hour, and copy them offsite. The accumulated log files, in combination
-with the previous database backup, could be used with db_recover to
-reconstruct the database up to the time the last collection of log files was
-copied offsite. This method affords good protection, with minimal space
-overhead.
-
-
-2. Periodically run slapcat and back up the LDIF file:
+1. Periodically run slapcat and back up the LDIF file:
 
 Slapcat can be run while slapd is active. However, one runs the risk of an
 inconsistent database- not from the point of slapd, but from the point of
@@ -46,73 +30,11 @@ files can be rather large and the accumulation of the day's backups could
 add up to a substantial amount of space.
 
 You can use {{slapcat}}(8) to generate an LDIF file for each of your {{slapd}}(8) 
-back-bdb or back-hdb databases.
+back-mdb databases.
 
 >    slapcat -f slapd.conf -b "dc=example,dc=com"
 
-For back-bdb and back-hdb, this command may be ran while slapd(8) is running.
-
-MORE on actual Berkeley DB backups later covering db_recover etc.
-
-H2: Berkeley DB Logs
-
-Berkeley DB log files grow, and the administrator has to deal with it. The 
-procedure is known as log file archival or log file rotation. 
-
-Note: The actual log file rotation is handled by the Berkeley DB engine.
-
-Logs of current transactions need to be stored into files so that the database 
-can be recovered in the event of an application crash. Administrators can change 
-the size limit of a single log file (by default 10MB), and have old log files 
-removed automatically, by setting up DB environment (see below). The reason 
-Berkeley DB never deletes any log files by default is that the administrator 
-may wish to backup the log files before removal to make database recovery 
-possible even after a catastrophic failure, such as file system corruption.
-
-Log file names are {{F:log.XXXXXXXXXX}} (X is a digit). By default the log files 
-are located in the BDB backend directory. The {{F:db_archive}} tool knows what 
-log files are used in current transactions, and what are not. Administrators can 
-move unused log files to a backup media, and delete them. To have them removed 
-automatically, place set_flags {{DB_LOG_AUTOREMOVE}} directive in {{F:DB_CONFIG}}. 
-
-Note: If the log files are removed automatically, recovery after a catastrophic 
-failure is likely to be impossible.
-
-The files with names {{F:__db.001}}, {{F:__db.002}}, etc are just shared memory 
-regions (or whatever). These ARE NOT 'logs', they must be left alone. Don't be 
-afraid of them, they do not grow like logs do.
-
-To understand the {{F:db_archive}} interface, the reader should refer to 
-chapter 9 of the Berkeley DB guide. In particular, the following chapters are 
-recommended:
-
-* Database and log file archival - {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/ref/transapp/archival.html}}
-* Log file removal - {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/ref/transapp/logfile.html}}
-* Recovery procedures - {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/ref/transapp/recovery.html}}
-* Hot failover - {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/ref/transapp/hotfail.html}}
-* Complete list of Berkeley DB flags - {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/api_c/env_set_flags.html}}
-
-Advanced installations can use special environment settings to fine-tune some 
-Berkeley DB options (change the log file limit, etc). This can be done by using 
-the {{F:DB_CONFIG}} file. This magic file can be created in BDB backend directory 
-set up by {{slapd.conf}}(5). More information on this file can be found in File 
-naming chapter. Specific directives can be found in C Interface, look for 
-{{DB_ENV->set_XXXX}} calls.
-
-Note: options set in {{F:DB_CONFIG}} file override options set by OpenLDAP. 
-Use them with extreme caution. Do not use them unless You know what You are doing.
-
-The advantages of {{F:DB_CONFIG}} usage can be the following:
-
-* to keep data files and log files on different mediums (i.e. disks) to improve 
-  performance and/or reliability;
-* to fine-tune some specific options (such as shared memory region sizes);
-* to set the log file limit (please read Log file limits before doing this).
-
-To figure out the best-practice BDB backup scenario, the reader is highly 
-recommended to read the whole Chapter 9: Berkeley DB Transactional Data Store Applications. 
-This chapter is a set of small pages with examples in C language. Non-programming 
-people can skip these examples without loss of knowledge.
+For back-mdb this command may be ran while slapd(8) is running.
 
 
 H2: Checkpointing
@@ -148,7 +70,7 @@ type are:
 +{{B: slapcat the current data out}}
 
 .{{S: }}
-+{{B: Clear out the current data directory (/usr/local/var/openldap-data/) leaving DB_CONFIG in place}}
++{{B: Clear out the current data directory (/usr/local/var/openldap-data/)}}
 
 .{{S: }}
 +{{B: Perform the software upgrades}}
diff --git a/doc/guide/admin/monitoringslapd.sdf b/doc/guide/admin/monitoringslapd.sdf
index 2781e47..bca2ec5 100644
--- a/doc/guide/admin/monitoringslapd.sdf
+++ b/doc/guide/admin/monitoringslapd.sdf
@@ -214,11 +214,10 @@ backends, as well as backends loaded by modules.  For example:
 >	monitoredInfo: config                 
 >	monitoredInfo: ldif     
 >	monitoredInfo: monitor
->	monitoredInfo: bdb        
->	monitoredInfo: hdb
+>	monitoredInfo: mdb
 
-This indicates the {{config}}, {{ldif}}, {{monitor}}, {{bdb}},
-and {{hdb}} backends are available.
+This indicates the {{config}}, {{ldif}}, {{monitor}},
+and {{mdb}} backends are available.
 
 The {{EX:cn=Backends,cn=Monitor}} object is also a container
 for available backend objects.  Each available backend object
@@ -242,21 +241,7 @@ contains information about a particular backend.  For example:
 >	seeAlso: cn=Database 2,cn=Databases,cn=Monitor
 >	
 >	dn: cn=Backend 3,cn=Backends,cn=Monitor
->	monitoredInfo: bdb
->	monitorRuntimeConfig: TRUE
->	supportedControl: 1.3.6.1.1.12
->	supportedControl: 2.16.840.1.113730.3.4.2
->	supportedControl: 1.3.6.1.4.1.4203.666.5.2
->	supportedControl: 1.2.840.113556.1.4.319
->	supportedControl: 1.3.6.1.1.13.1
->	supportedControl: 1.3.6.1.1.13.2
->	supportedControl: 1.3.6.1.4.1.4203.1.10.1
->	supportedControl: 1.2.840.113556.1.4.1413
->	supportedControl: 1.3.6.1.4.1.4203.666.11.7.2
->	seeAlso: cn=Database 1,cn=Databases,cn=Monitor
->	
->	dn: cn=Backend 4,cn=Backends,cn=Monitor
->	monitoredInfo: hdb
+>	monitoredInfo: mdb
 >	monitorRuntimeConfig: TRUE
 >	supportedControl: 1.3.6.1.1.12
 >	supportedControl: 2.16.840.1.113730.3.4.2
@@ -271,7 +256,7 @@ contains information about a particular backend.  For example:
 For each of these objects, monitorInfo indicates which backend the
 information in the object is about.  For instance, the {{EX:cn=Backend
 3,cn=Backends,cn=Monitor}} object contains (in the example) information
-about the {{bdb}} backend. 
+about the {{mdb}} backend. 
 
 !block table
 Attribute|Description
diff --git a/doc/guide/admin/overlays.sdf b/doc/guide/admin/overlays.sdf
index 2eb115b..712cd1b 100644
--- a/doc/guide/admin/overlays.sdf
+++ b/doc/guide/admin/overlays.sdf
@@ -743,9 +743,9 @@ H4: Setting cache parameters
 This directive enables proxy caching and sets general cache
 parameters.  The <DB> parameter specifies which underlying database
 is to be used to hold cached entries.  It should be set to
-{{EX:mdb}}, {{EX:hdb}}, or {{EX:bdb}}.  The <maxentries> parameter
-specifies the total number of entries which may be held in the cache.
-The <nattrsets> parameter specifies the total number of attribute sets
+{{EX:mdb}}.  The <maxentries> parameter specifies the
+total number of entries which may be held in the cache.  The
+<nattrsets> parameter specifies the total number of attribute sets
 (as specified by the {{EX:pcacheAttrset}} directive) that may be
 defined.  The <entrylimit> parameter specifies the maximum number of
 entries in a cacheable query.  The <period> specifies the consistency
diff --git a/doc/guide/admin/replication.sdf b/doc/guide/admin/replication.sdf
index 87139b5..bbc91e4 100644
--- a/doc/guide/admin/replication.sdf
+++ b/doc/guide/admin/replication.sdf
@@ -225,8 +225,8 @@ in the replication context.
 
 The syncrepl engine, which is a consumer-side replication engine,
 can work with any backends. The LDAP Sync provider can be configured
-as an overlay on any backend, but works best with the {{back-bdb}},
-{{back-hdb}}, or {{back-mdb}} backends.
+as an overlay on any backend, but works best with the {{back-mdb}},
+backends.
 
 The LDAP Sync provider maintains a {{EX:contextCSN}} for each
 database as the current synchronization state indicator of the
@@ -423,9 +423,6 @@ writes have to go to just one of the mirror nodes at a time
 server (slapd in proxy mode) or device (hardware load balancer)
 is needed to manage which provider is currently active
 * Backups are managed slightly differently
-- If backing up the Berkeley database itself and periodically backing up the 
-transaction log files, then the same member of the mirror pair needs to be 
-used to collect logfiles until the next database backup is taken 
 
 For configuration, please see the {{SECT:MirrorMode}} section below
 
@@ -762,10 +759,7 @@ H4: Delta-syncrepl Consumer configuration
 
 
 The above configuration assumes that you have a replicator identity defined 
-in your database that can be used to bind to the provider. In addition, 
-all of the databases (primary, replica, and the accesslog 
-storage database) should also have properly tuned {{DB_CONFIG}} files that meet 
-your needs.
+in your database that can be used to bind to the provider.
 
 Note: An accesslog database is unique to a given master. It should
 never be replicated.
diff --git a/doc/guide/admin/slapdconf2.sdf b/doc/guide/admin/slapdconf2.sdf
index cb51d88..8a3e969 100644
--- a/doc/guide/admin/slapdconf2.sdf
+++ b/doc/guide/admin/slapdconf2.sdf
@@ -69,7 +69,7 @@ used to configure the software.
 the schema that is hard-coded in slapd).
 .. Child entries of {{EX:cn=schema,cn=config}} contain user schema as
 loaded from config files or added at runtime.
-* Backend-specific configuration 
+* Backend-specific configuration
 * Database-specific configuration
 .. Overlays are defined in children of the Database entry.
 .. Databases and Overlays may also have other miscellaneous children.
@@ -207,7 +207,7 @@ Level	Keyword		Description
 !endblock
 
 The desired log level can be input as a single integer that
-combines the (ORed) desired levels, both in decimal or in hexadecimal 
+combines the (ORed) desired levels, both in decimal or in hexadecimal
 notation, as a list of integers (that are ORed internally), or as a list of the names that are shown between brackets, such that
 
 >		olcLogLevel 129
@@ -364,10 +364,8 @@ supported backend types listed in Table 5.2.
 !block table; align=Center; coltags="EX,N"; \
 	title="Table 5.2: Database Backends"
 Types	Description
-bdb	Berkeley DB transactional backend (deprecated)
 config	Slapd configuration backend
 dnssrv	DNS SRV backend
-hdb	Hierarchical variant of bdb backend (deprecated)
 ldap	Lightweight Directory Access Protocol (Proxy) backend
 ldif	Lightweight Data Interchange Format backend
 mdb	Memory-Mapped DB backend
@@ -381,7 +379,7 @@ sql	SQL Programmable backend
 
 \Example:
 
->	olcBackend: bdb
+>	olcBackend: mdb
 
 There are no other directives defined for this entry.  Specific backend
 types may define additional attributes for their particular use but so
@@ -391,9 +389,9 @@ not appear in any actual configurations.
 
 H4: Sample Entry
 
-> dn: olcBackend=bdb,cn=config
+> dn: olcBackend=mdb,cn=config
 > objectClass: olcBackendConfig
-> olcBackend: bdb
+> olcBackend: mdb
 
 
 H3: Database-specific Directives
@@ -421,9 +419,9 @@ databases.
 
 \Example:
 
->	olcDatabase: bdb
+>	olcDatabase: mdb
 
-This marks the beginning of a new {{TERM:BDB}} database instance.
+This marks the beginning of a new {{TERM:MDB}} database instance.
 
 
 H4: olcAccess: to <what> [ by <who> [<accesslevel>] [<control>] ]+
@@ -642,7 +640,7 @@ schema conformance. The default is off.
 The {{EX:binddn}} parameter gives the DN to bind as for the
 syncrepl searches to the provider slapd. It should be a DN
 which has read access to the replication content in the
-master database. 
+master database.
 
 The {{EX:bindmethod}} is {{EX:simple}} or {{EX:sasl}},
 depending on whether simple password-based authentication or
@@ -683,8 +681,8 @@ conforms to the obsolete {{changelog}} format. If the {{EX:syncdata}}
 parameter is omitted or set to {{EX:"default"}} then the log
 parameters are ignored.
 
-The {{syncrepl}} replication mechanism is supported by the {{bdb}},
-{{hdb}}, and {{mdb}} backends.
+The {{syncrepl}} replication mechanism is supported by the {{mdb}}
+backend.
 
 See the {{SECT:LDAP Sync Replication}} chapter of this guide for
 more information on how to use this directive.
@@ -731,21 +729,20 @@ H4: Sample Entries
 >olcRootDN: cn=Manager,dc=example,dc=com
 
 
-H3: BDB and HDB Database Directives
+H3: MDB Database Directives
 
-Directives in this category apply to both the {{TERM:BDB}}
-and the {{TERM:HDB}} database.
+Directives in this category apply to the {{TERM:MDB}}
+database backend.
 They are used in an olcDatabase entry in addition to the generic
 database directives defined above.  For a complete reference
-of BDB/HDB configuration directives, see {{slapd-bdb}}(5). In
-addition to the {{EX:olcDatabaseConfig}} objectClass, BDB and HDB
-database entries must have the {{EX:olcBdbConfig}} and
-{{EX:olcHdbConfig}} objectClass, respectively.
+of MDB configuration directives, see {{slapd-mdb}}(5). In
+addition to the {{EX:olcDatabaseConfig}} objectClass, MDB
+database entries must have the {{EX:olcMdbConfig}} objectClass.
 
 
 H4: olcDbDirectory: <directory>
 
-This directive specifies the directory where the BDB files
+This directive specifies the directory where the MDB files
 containing the database and associated indices live.
 
 \Default:
@@ -753,98 +750,48 @@ containing the database and associated indices live.
 >	olcDbDirectory: /usr/local/var/openldap-data
 
 
-H4: olcDbCachesize: <integer>
-
-This directive specifies the size in entries of the in-memory
-cache maintained by the BDB backend database instance.
-
-\Default:
-
->	olcDbCachesize: 1000
-
-
 H4: olcDbCheckpoint: <kbyte> <min>
 
-This directive specifies how often to checkpoint the BDB transaction log.
-A checkpoint operation flushes the database buffers to disk and writes a
-checkpoint record in the log.
+This directive specifies the frequency for flushing the database disk
+buffers. This directive is only needed if the {{olcDbNoSync}} option is
+{{EX:TRUE}}.
 The checkpoint will occur if either <kbyte> data has been written or
 <min> minutes have passed since the last checkpoint. Both arguments default
 to zero, in which case they are ignored. When the <min> argument is
 non-zero, an internal task will run every <min> minutes to perform the
-checkpoint. See the Berkeley DB reference guide for more details.
+checkpoint. Note: currently the _kbyte_ setting is unimplemented.
 
 \Example:
 
 >	olcDbCheckpoint: 1024 10
 
 
-H4: olcDbConfig: <DB_CONFIG setting>
+H4: olcDbEnvFlags: {nosync,nometasync,writemap,mapasync,nordahead}
 
-This attribute specifies a configuration directive to be placed in the
-{{EX:DB_CONFIG}} file of the database directory. At server startup time, if
-no such file exists yet, the {{EX:DB_CONFIG}} file will be created and the
-settings in this attribute will be written to it. If the file exists,
-its contents will be read and displayed in this attribute. The attribute
-is multi-valued, to accommodate multiple configuration directives. No default
-is provided, but it is essential to use proper settings here to get the
-best server performance.
+This option specifies flags for finer-grained control of  the  LMDB  library's
+operation.
 
-Any changes made to this attribute will be written to the {{EX:DB_CONFIG}}
-file and will cause the database environment to be reset so the changes
-can take immediate effect. If the environment cache is large and has not
-been recently checkpointed, this reset operation may take a long time. It
-may be advisable to manually perform a single checkpoint using the Berkeley DB
-{{db_checkpoint}} utility before using LDAP Modify to change this
-attribute.
+* {{F:nosync}}: This is exactly the same as the dbnosync directive.
 
-\Example:
+* {{F:nometasync}}: Flush the data on a commit, but skip the sync of the meta
+page. This mode is slightly faster than doing a full sync, but can
+potentially lose the last committed transaction if the operating system
+crashes. If both nometasync and nosync are set, the nosync flag takes
+precedence.
 
->	olcDbConfig: set_cachesize 0 10485760 0
->	olcDbConfig: set_lg_bsize 2097512
->	olcDbConfig: set_lg_dir /var/tmp/bdb-log
->	olcDbConfig: set_flags DB_LOG_AUTOREMOVE
-
-In this example, the BDB cache is set to 10MB, the BDB transaction log
-buffer size is set to 2MB, and the transaction log files are to be stored
-in the /var/tmp/bdb-log directory. Also a flag is set to tell BDB to
-delete transaction log files as soon as their contents have been
-checkpointed and they are no longer needed. Without this setting the
-transaction log files will continue to accumulate until some other
-cleanup procedure removes them. See the Berkeley DB documentation for the
-{{EX:db_archive}} command for details. For a complete list of Berkeley DB 
-flags please see - {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/api_c/env_set_flags.html}}
-
-Ideally the BDB cache must be
-at least as large as the working set of the database, the log buffer size
-should be large enough to accommodate most transactions without overflowing,
-and the log directory must be on a separate physical disk from the main
-database files. And both the database directory and the log directory
-should be separate from disks used for regular system activities such as
-the root, boot, or swap filesystems. See the FAQ-o-Matic and the Berkeley DB
-documentation for more details.
+* {{F:writemap}}: Use a writable memory map instead of just read-only. This
+speeds up write operations but makes the database vulnerable to corruption in
+case any bugs in slapd cause stray writes into the mmap region.
 
+* {{F:mapasync}}: When using a writable memory map and performing flushes on
+each commit, use an asynchronous flush instead of a synchronous flush (the
+default). This option has no effect if writemap has not been set. It also has
+no effect if nosync is set.
 
-H4: olcDbNosync: { TRUE | FALSE }
-
-This option causes on-disk database contents to not be immediately
-synchronized with in memory changes upon change.  Setting this option
-to {{EX:TRUE}} may improve performance at the expense of data integrity. This
-directive has the same effect as using
->	olcDbConfig: set_flags DB_TXN_NOSYNC
-
-
-H4: olcDbIDLcacheSize: <integer>
-
-Specify the size of the in-memory index cache, in index slots. The
-default is zero. A larger value will speed up frequent searches of
-indexed entries. The optimal size will depend on the data and search
-characteristics of the database, but using a number three times
-the entry cache size is a good starting point.
-
-\Example:
-
->	olcDbIDLcacheSize: 3000
+* {{F:nordahead}}: Turn off file readahead. Usually the OS performs readahead
+on every read request. This usually boosts read performance but can be
+harmful to random access read performance if the system's memory is full and
+the DB is larger than RAM. This option is not implemented on Windows.
 
 
 H4: olcDbIndex: {<attrlist> | default} [pres,eq,approx,sub,none]
@@ -874,7 +821,7 @@ matches do not use an index. However, some attributes do support
 indexing for inequality matches, based on the equality index.
 
 A substring index can be more explicitly specified as {{EX:subinitial}},
-{{EX:subany}}, or {{EX:subfinal}}, corresponding to the three 
+{{EX:subany}}, or {{EX:subfinal}}, corresponding to the three
 possible components
 of a substring match filter. A subinitial index only indexes
 substrings that appear at the beginning of an attribute value.
@@ -890,7 +837,7 @@ attribute that inherits from {{EX:name}} to be indexed.
 By default, no indices are maintained.  It is generally advised
 that minimally an equality index upon objectClass be maintained.
 
->	olcDbindex: objectClass eq
+>	olcDbIndex: objectClass eq
 
 Additional indices should be configured corresponding to the
 most common searches that are used on the database.
@@ -907,18 +854,24 @@ stopped before the index task completes, indexing will have to be
 manually completed using the slapindex tool.
 
 
-H4: olcDbLinearIndex: { TRUE | FALSE }
+H4: olcDbMaxReaders: <integer>
+
+This directive specifies the maximum number of threads that may have
+concurrent read access to the database. Tools such as slapcat count as a
+single thread, in addition to threads in any active slapd processes. The
+default is 126.
+
 
-If this setting is {{EX:TRUE}} slapindex will index one attribute
-at a time. The default settings is {{EX:FALSE}} in which case all
-indexed attributes of an entry are processed at the same time. When
-enabled, each indexed attribute is processed individually, using
-multiple passes through the entire database. This option improves
-slapindex performance when the database size exceeds the BDB cache
-size. When the BDB cache is large enough, this option is not needed
-and will decrease performance. Also by default, slapadd performs
-full indexing and so a separate slapindex run is not needed. With
-this option, slapadd does no indexing and slapindex must be used.
+H4: olcDbMaxSize: <bytes>
+
+This directive specifies the maximum size of the database in bytes. A memory
+map of this size is allocated at startup time and the database will not be
+allowed to grow beyond this size. The default is 10485760 bytes (10MB). This
+setting may be changed upward if the configured limit needs to be increased.
+
+Note: It is important to set this to as large a value as possible, (relative
+to anticipated growth of the actual data over time) since growing the size
+later may not be practical when the system is under heavy load.
 
 
 H4: olcDbMode: { <octal> | <symbolic> }
@@ -932,6 +885,18 @@ created database index files should have. This can be in the form
 >	olcDbMode: 0600
 
 
+H4: olcDbRtxnsize: <entries>
+
+This directive specifies the maximum number of entries to process in a single
+read transaction when executing a large search. Long-lived read transactions
+prevent old database pages from being reused in write transactions, and so
+can cause significant growth of the database file when there is heavy write
+traffic. This setting causes the read transaction in large searches to be
+released and reacquired after the given number of entries has been read, to
+give writers the opportunity to reclaim old database pages. The default is
+10000.
+
+
 H4: olcDbSearchStack: <integer>
 
 Specify the depth of the stack used for search filter evaluation.
@@ -955,33 +920,21 @@ to take effect.
 >	olcDbSearchStack: 16
 
 
-H4: olcDbShmKey: <integer>
-
-Specify a key for a shared memory BDB environment. By default the BDB
-environment uses memory mapped files. If a non-zero value is specified,
-it will be used as the key to identify a shared memory region that will
-house the environment.
-
-\Example:
+H4: olcDbNosync: { TRUE | FALSE }
 
->	olcDbShmKey: 42
+This directive causes on-disk database contents to not be immediately
+synchronized with in memory changes upon change.  Setting this option
+to {{EX:TRUE}} may improve performance at the expense of data integrity.
 
 
 H4: Sample Entry
 
->dn: olcDatabase=hdb,cn=config
+>dn: olcDatabase=mdb,cn=config
 >objectClass: olcDatabaseConfig
->objectClass: olcHdbConfig
->olcDatabase: hdb
+>objectClass: olcMdbConfig
+>olcDatabase: mdb
 >olcSuffix: dc=example,dc=com
 >olcDbDirectory: /usr/local/var/openldap-data
->olcDbCacheSize: 1000
->olcDbCheckpoint: 1024 10
->olcDbConfig: set_cachesize 0 10485760 0
->olcDbConfig: set_lg_bsize 2097152
->olcDbConfig: set_lg_dir /var/tmp/bdb-log
->olcDbConfig: set_flags DB_LOG_AUTOREMOVE
->olcDbIDLcacheSize: 3000
 >olcDbIndex: objectClass eq
 
 
@@ -989,7 +942,7 @@ H2: Configuration Example
 
 The following is an example configuration, interspersed
 with explanatory text. It defines two databases to handle
-different parts of the {{TERM:X.500}} tree; both are {{TERM:BDB}}
+different parts of the {{TERM:X.500}} tree; both are {{TERM:MDB}}
 database instances. The line numbers shown are provided for
 reference only and are not included in the actual file. First, the
 global configuration section:
@@ -999,7 +952,7 @@ E:  2.    dn: cn=config
 E:  3.    objectClass: olcGlobal
 E:  4.    cn: config
 E:  5.    olcReferral: ldap://root.openldap.org
-E:  6.    
+E:  6. 
 
 Line 1 is a comment. Lines 2-4 identify this as the global
 configuration entry.
@@ -1013,7 +966,7 @@ E:  7.    # internal schema
 E:  8.    dn: cn=schema,cn=config
 E:  9.    objectClass: olcSchemaConfig
 E: 10.    cn: schema
-E: 11.    
+E: 11.
 
 Line 7 is a comment. Lines 8-10 identify this as the root of
 the schema subtree. The actual schema definitions in this entry
@@ -1022,7 +975,7 @@ Line 11 is a blank line, indicating the end of this entry.
 
 E: 12.    # include the core schema
 E: 13.    include: file:///usr/local/etc/openldap/schema/core.ldif
-E: 14.    
+E: 14.
 
 Line 12 is a comment. Line 13 is an LDIF include directive which
 accesses the {{core}} schema definitions in LDIF format. Line 14
@@ -1037,7 +990,7 @@ E: 16.    dn: olcDatabase=frontend,cn=config
 E: 17.    objectClass: olcDatabaseConfig
 E: 18.    olcDatabase: frontend
 E: 19.    olcAccess: to * by * read
-E: 20.    
+E: 20.
 
 Line 15 is a comment. Lines 16-18 identify this entry as the global
 database entry. Line 19 is a global access control. It applies to all
@@ -1066,16 +1019,16 @@ inaccessible.)
 
 Line 28 is a blank line.
 
-The next entry defines a BDB backend that will handle queries for things
+The next entry defines an MDB backend that will handle queries for things
 in the "dc=example,dc=com" portion of the tree. Indices are to be maintained
 for several attributes, and the {{EX:userPassword}} attribute is to be
 protected from unauthorized access.
 
-E: 29.    # BDB definition for example.com
-E: 30.    dn: olcDatabase=bdb,cn=config
+E: 29.    # MDB definition for example.com
+E: 30.    dn: olcDatabase=mdb,cn=config
 E: 31.    objectClass: olcDatabaseConfig
-E: 32.    objectClass: olcBdbConfig
-E: 33.    olcDatabase: bdb
+E: 32.    objectClass: olcMdbConfig
+E: 33.    olcDatabase: mdb
 E: 34.    olcSuffix: dc=example,dc=com
 E: 35.    olcDbDirectory: /usr/local/var/openldap-data
 E: 36.    olcRootDN: cn=Manager,dc=example,dc=com
@@ -1092,7 +1045,7 @@ E: 46.    olcAccess: to *
 E: 47.      by self write
 E: 48.      by dn.base="cn=Admin,dc=example,dc=com" write
 E: 49.      by * read
-E: 50.    
+E: 50.
 
 Line 29 is a comment. Lines 30-33 identify this entry as a BDB database
 configuration entry.  Line 34 specifies the DN suffix
@@ -1116,16 +1069,16 @@ entry, but may be read by all users (authenticated or not).
 Line 50 is a blank line, indicating the end of this entry.
 
 The next entry defines another
-BDB database. This one handles queries involving the
+MDB database. This one handles queries involving the
 {{EX:dc=example,dc=net}} subtree but is managed by the same entity
 as the first database.  Note that without line 60, the read access
 would be allowed due to the global access rule at line 19.
 
-E: 51.    # BDB definition for example.net
-E: 52.    dn: olcDatabase=bdb,cn=config
+E: 51.    # MDB definition for example.net
+E: 52.    dn: olcDatabase=mdb,cn=config
 E: 53.    objectClass: olcDatabaseConfig
-E: 54.    objectClass: olcBdbConfig
-E: 55.    olcDatabase: bdb
+E: 54.    objectClass: olcMdbConfig
+E: 55.    olcDatabase: mdb
 E: 56.    olcSuffix: dc=example,dc=net
 E: 57.    olcDbDirectory: /usr/local/var/openldap-data-net
 E: 58.    olcRootDN: cn=Manager,dc=example,dc=com
diff --git a/doc/guide/admin/slapdconfig.sdf b/doc/guide/admin/slapdconfig.sdf
index d943eb9..8b1162c 100644
--- a/doc/guide/admin/slapdconfig.sdf
+++ b/doc/guide/admin/slapdconfig.sdf
@@ -90,7 +90,7 @@ H4: access to <what> [ by <who> [<accesslevel>] [<control>] ]+
 
 This directive grants access (specified by <accesslevel>) to a set
 of entries and/or attributes (specified by <what>) by one or more
-requestors (specified by <who>).  See the {{SECT:Access Control}} section of 
+requestors (specified by <who>).  See the {{SECT:Access Control}} section of
 this guide for basic usage.
 
 !if 0
@@ -162,7 +162,7 @@ Level	Keyword		Description
 !endblock
 
 The desired log level can be input as a single integer that
-combines the (ORed) desired levels, both in decimal or in hexadecimal 
+combines the (ORed) desired levels, both in decimal or in hexadecimal
 notation, as a list of integers (that are ORed internally), or as a list of the names that are shown between brackets, such that
 
 >		loglevel 129
@@ -264,9 +264,7 @@ supported backend types listed in Table 6.2.
 !block table; align=Center; coltags="EX,N"; \
 	title="Table 6.2: Database Backends"
 Types	Description
-bdb	Berkeley DB transactional backend (deprecated)
 dnssrv	DNS SRV backend
-hdb	Hierarchical variant of bdb backend (deprecated)
 ldap	Lightweight Directory Access Protocol (Proxy) backend
 mdb	Memory-Mapped DB backend
 meta	Meta Directory backend
@@ -507,7 +505,7 @@ defaults for these parameters come from {{ldap.conf}}(5).
 The {{EX:binddn}} parameter gives the DN to bind as for the
 syncrepl searches to the provider slapd. It should be a DN
 which has read access to the replication content in the
-master database. 
+master database.
 
 The {{EX:bindmethod}} is {{EX:simple}} or {{EX:sasl}},
 depending on whether simple password-based authentication or
@@ -564,8 +562,7 @@ conforms to the obsolete {{changelog}} format. If the {{EX:syncdata}}
 parameter is omitted or set to {{EX:"default"}} then the log
 parameters are ignored.
 
-The {{syncrepl}} replication mechanism is supported by the {{bdb}},
-{{hdb}}, and {{mdb}} backends.
+The {{syncrepl}} replication mechanism is supported by the {{mdb}} backends.
 
 See the {{SECT:LDAP Sync Replication}} chapter of this guide for
 more information on how to use this directive.
@@ -584,19 +581,18 @@ If specified multiple times, each {{TERM:URL}} is provided.
 >	updateref	ldap://master.example.net
 
 
-H3: BDB and HDB Database Directives
+H3: MDB Database Directives
 
-Directives in this category only apply to both the {{TERM:BDB}}
-and the {{TERM:HDB}} database.
-That is, they must follow a "database bdb" or "database hdb" line
-and come before any
-subsequent "backend" or "database" line.  For a complete reference
-of BDB/HDB configuration directives, see {{slapd-bdb}}(5).
+Directives in this category only apply to the {{TERM:MDB}}
+database backend.
+That is, they must follow a "database mdb" line
+and come before any subsequent "backend" or "database" lines.
+For a complete reference of MDB configuration directives, see {{slapd-mdb}}(5).
 
 
 H4: directory <directory>
 
-This directive specifies the directory where the BDB files
+This directive specifies the directory where the MDB files
 containing the database and associated indices live.
 
 \Default:
@@ -604,11 +600,189 @@ containing the database and associated indices live.
 >	directory /usr/local/var/openldap-data
 
 
+H4: checkpoint <kbyte> <min>
+
+This directive specifies the frequency for flushing the database disk
+buffers. This directive is only needed if the {{dbnosync}} option is
+{{EX:TRUE}}.
+The checkpoint will occur if either <kbyte> data has been written or
+<min> minutes have passed since the last checkpoint. Both arguments default
+to zero, in which case they are ignored. When the <min> argument is
+non-zero, an internal task will run every <min> minutes to perform the
+checkpoint. Note: currently the _kbyte_ setting is unimplemented.
+
+\Example:
+
+>   checkpoint: 1024 10
+
+H4: dbnosync: { TRUE | FALSE }
+
+This directive causes on-disk database contents to not be immediately
+synchronized with in memory changes upon change.  Setting this option
+to {{EX:TRUE}} may improve performance at the expense of data integrity.
+
+
+H4: envflags: {nosync,nometasync,writemap,mapasync,nordahead}
+
+This option specifies flags for finer-grained control of  the  LMDB  library's
+operation.
+
+* {{F:nosync}}: This is exactly the same as the dbnosync directive.
+
+* {{F:nometasync}}: Flush the data on a commit, but skip the sync of the meta
+page. This mode is slightly faster than doing a full sync, but can
+potentially lose the last committed transaction if the operating system
+crashes. If both nometasync and nosync are set, the nosync flag takes
+precedence.
+
+* {{F:writemap}}: Use a writable memory map instead of just read-only. This
+speeds up write operations but makes the database vulnerable to corruption in
+case any bugs in slapd cause stray writes into the mmap region.
+
+* {{F:mapasync}}: When using a writable memory map and performing flushes on
+each commit, use an asynchronous flush instead of a synchronous flush (the
+default). This option has no effect if writemap has not been set. It also has
+no effect if nosync is set.
+
+* {{F:nordahead}}: Turn off file readahead. Usually the OS performs readahead
+on every read request. This usually boosts read performance but can be
+harmful to random access read performance if the system's memory is full and
+the DB is larger than RAM. This option is not implemented on Windows.
+
+
+H4: index: {<attrlist> | default} [pres,eq,approx,sub,none]
+
+This directive specifies the indices to maintain for the given
+attribute. If only an {{EX:<attrlist>}} is given, the default
+indices are maintained. The index keywords correspond to the
+common types of matches that may be used in an LDAP search filter.
+
+\Example:
+
+>   index: default pres,eq
+>   index: uid
+>   index: cn,sn pres,eq,sub
+>   index: objectClass eq
+
+The first line sets the default set of indices to maintain to
+present and equality.  The second line causes the default (pres,eq)
+set of indices to be maintained for the {{EX:uid}} attribute type.
+The third line causes present, equality, and substring indices to
+be maintained for {{EX:cn}} and {{EX:sn}} attribute types.  The
+fourth line causes an equality index for the {{EX:objectClass}}
+attribute type.
+
+There is no index keyword for inequality matches. Generally these
+matches do not use an index. However, some attributes do support
+indexing for inequality matches, based on the equality index.
+
+A substring index can be more explicitly specified as {{EX:subinitial}},
+{{EX:subany}}, or {{EX:subfinal}}, corresponding to the three
+possible components
+of a substring match filter. A subinitial index only indexes
+substrings that appear at the beginning of an attribute value.
+A subfinal index only indexes substrings that appear at the end
+of an attribute value, while subany indexes substrings that occur
+anywhere in a value.
+
+Note that by default, setting an index for an attribute also
+affects every subtype of that attribute. E.g., setting an equality
+index on the {{EX:name}} attribute causes {{EX:cn}}, {{EX:sn}}, and every other
+attribute that inherits from {{EX:name}} to be indexed.
+
+By default, no indices are maintained.  It is generally advised
+that minimally an equality index upon objectClass be maintained.
+
+>   index: objectClass eq
+
+Additional indices should be configured corresponding to the
+most common searches that are used on the database.
+Presence indexing should not be configured for an attribute
+unless the attribute occurs very rarely in the database, and
+presence searches on the attribute occur very frequently during
+normal use of the directory. Most applications don't use presence
+searches, so usually presence indexing is not very useful.
+
+
+H4: maxreaders: <integer>
+
+This directive specifies the maximum number of threads that may have
+concurrent read access to the database. Tools such as slapcat count as a
+single thread, in addition to threads in any active slapd processes. The
+default is 126.
+
+
+H4: maxsize: <bytes>
+
+This directive specifies the maximum size of the database in bytes. A memory
+map of this size is allocated at startup time and the database will not be
+allowed to grow beyond this size. The default is 10485760 bytes (10MB). This
+setting may be changed upward if the configured limit needs to be increased.
+
+Note: It is important to set this to as large a value as possible, (relative
+to anticipated growth of the actual data over time) since growing the size
+later may not be practical when the system is under heavy load.
+
+
+H4: mode: { <octal> | <symbolic> }
+
+This directive specifies the file protection mode that newly
+created database index files should have. This can be in the form
+{{EX:0600}} or {{EX:-rw-------}}
+
+\Default:
+
+>   mode: 0600
+
+
+H4: rtxnsize: <entries>
+
+This directive specifies the maximum number of entries to process in a single
+read transaction when executing a large search. Long-lived read transactions
+prevent old database pages from being reused in write transactions, and so
+can cause significant growth of the database file when there is heavy write
+traffic. This setting causes the read transaction in large searches to be
+released and reacquired after the given number of entries has been read, to
+give writers the opportunity to reclaim old database pages. The default is
+10000.
+
+
+H4: searchstack: <integer>
+
+Specify the depth of the stack used for search filter evaluation.
+Search filters are evaluated on a stack to accommodate nested {{EX:AND}} /
+{{EX:OR}} clauses. An individual stack is allocated for each server thread.
+The depth of the stack determines how complex a filter can be evaluated
+without requiring any additional memory allocation. Filters that are
+nested deeper than the search stack depth will cause a separate stack to
+be allocated for that particular search operation. These separate allocations
+can have a major negative impact on server performance, but specifying
+too much stack will also consume a great deal of memory. Each search
+uses 512K bytes per level on a 32-bit machine, or 1024K bytes per level
+on a 64-bit machine. The default stack depth is 16, thus 8MB or 16MB
+per thread is used on 32 and 64 bit machines, respectively. Also the
+512KB size of a single stack slot is set by a compile-time constant which
+may be changed if needed; the code must be recompiled for the change
+to take effect.
+
+\Default:
+
+>   searchstack: 16
+
+
+H4: Sample Entry
+
+>database mdb
+>suffix: "dc=example,dc=com"
+>directory: /usr/local/var/openldap-data
+>index: objectClass eq
+
+
 H2: Configuration File Example
 
 The following is an example configuration file, interspersed
 with explanatory text. It defines two databases to handle
-different parts of the {{TERM:X.500}} tree; both are {{TERM:BDB}}
+different parts of the {{TERM:X.500}} tree; both are {{TERM:MDB}}
 database instances. The line numbers shown are provided for
 reference only and are not included in the actual file. First, the
 global configuration section:
@@ -617,7 +791,7 @@ E:  1.    # example config file - global configuration section
 E:  2.    include /usr/local/etc/schema/core.schema
 E:  3.    referral ldap://root.openldap.org
 E:  4.    access to * by * read
- 
+
 Line 1 is a comment. Line 2 includes another config file
 which contains {{core}} schema definitions.
 The {{EX:referral}} directive on line 3
@@ -629,7 +803,7 @@ Line 4 is a global access control.  It applies to all
 entries (after any applicable database-specific access
 controls).
 
-The next section of the configuration file defines a BDB
+The next section of the configuration file defines a MDB
 backend that will handle queries for things in the
 "dc=example,dc=com" portion of the tree. The
 database is to be replicated to two slave slapds, one on
@@ -637,8 +811,8 @@ truelies, the other on judgmentday. Indices are to be
 maintained for several attributes, and the {{EX:userPassword}}
 attribute is to be protected from unauthorized access.
 
-E:  5.    # BDB definition for the example.com
-E:  6.    database bdb
+E:  5.    # MDB definition for the example.com
+E:  6.    database mdb
 E:  7.    suffix "dc=example,dc=com"
 E:  8.    directory /usr/local/var/openldap-data
 E:  9.    rootdn "cn=Manager,dc=example,dc=com"
@@ -683,8 +857,8 @@ BDB database. This one handles queries involving the
 as the first database.  Note that without line 39, the read access
 would be allowed due to the global access rule at line 4.
 
-E: 33.    # BDB definition for example.net
-E: 34.    database bdb
+E: 33.    # MDB definition for example.net
+E: 34.    database mdb
 E: 35.    suffix "dc=example,dc=net"
 E: 36.    directory /usr/local/var/openldap-data-net
 E: 37.    rootdn "cn=Manager,dc=example,dc=com"
diff --git a/doc/guide/admin/tuning.sdf b/doc/guide/admin/tuning.sdf
index 7074561..795c5ce 100644
--- a/doc/guide/admin/tuning.sdf
+++ b/doc/guide/admin/tuning.sdf
@@ -27,10 +27,6 @@ H3: Memory
 
 Scale your cache to use available memory and increase system memory if you can.
 
-See {{SECT:Caching}} for BDB cache tuning hints.
-Note that LMDB uses no cache of its own and has no tuning options, so the Caching
-section can be ignored when using LMDB.
-
 
 H3: Disks
 
@@ -39,15 +35,7 @@ types perform best with your workload. (On our own Linux testing, EXT2 and JFS
 tend to provide better write performance than everything else, including
 newer filesystems like EXT4, BTRFS, etc.)
 
-Use fast subsystems. Put each database and logs on separate disks
-(for BDB this is configurable via {{DB_CONFIG}}):
-
->       # Data Directory
->       set_data_dir /data/db
->       
->       # Transaction Log settings
->       set_lg_dir /logs
-
+Use fast subsystems. Put each database on separate disks
 
 H3: Network Topology
 
@@ -131,7 +119,7 @@ H3: What to watch out for
 
 The most common message you'll see that you should pay attention to is:
 
->       "<= bdb_equality_candidates: (foo) index_param failed (18)"
+>       "<= mdb_equality_candidates: (foo) index_param failed (18)"
 
 That means that some application tried to use an equality filter ({{foo=<somevalue>}}) 
 and attribute {{foo}} does not have an equality index. If you see a lot of these
@@ -163,165 +151,6 @@ For syslog-ng, add or modify the following line in {{syslog-ng.conf}}:
 where n is the number of lines which will be buffered before a write.
 
 
-H2: Caching
-
-We all know what caching is, don't we? 
-
-In brief, "A cache is a block of memory for temporary storage of data likely 
-to be used again" - {{URL:http://en.wikipedia.org/wiki/Cache}}
-
-There are 3 types of caches, BerkeleyDB's own cache, {{slapd}}(8) 
-entry cache and {{TERM:IDL}} (IDL) cache.
-
-
-H3: Berkeley DB Cache
-
-There are two ways to tune for the BDB cachesize:
-
-(a) BDB cache size necessary to load the database via slapadd in optimal time
-
-(b) BDB cache size necessary to have a high performing running slapd once the data is loaded
-
-For (a), the optimal cachesize is the size of the entire database.  If you 
-already have the database loaded, this is simply a 
-
->       du -c -h *.bdb 
-
-in the directory containing the OpenLDAP ({{/usr/local/var/openldap-data}}) data.
-
-For (b), the optimal cachesize is just the size of the {{id2entry.bdb}} file, 
-plus about 10% for growth.
-
-The tuning of {{DB_CONFIG}} should be done for each BDB type database 
-instantiated (back-bdb, back-hdb).
-
-Note that while the {{TERM:BDB}} cache is just raw chunks of memory and 
-configured as a memory size, the {{slapd}}(8) entry cache holds parsed entries, 
-and the size of each entry is variable. 
-
-There is also an IDL cache which is used for Index Data Lookups. 
-If you can fit all of your database into slapd's entry cache, and all of your 
-index lookups fit in the IDL cache, that will provide the maximum throughput. 
-
-If not, but you can fit the entire database into the BDB cache, then you 
-should do that and shrink the slapd entry cache as appropriate. 
-
-Failing that, you should balance the BDB cache against the entry cache.
-
-It is worth noting that it is not absolutely necessary to configure a BerkeleyDB 
-cache equal in size to your entire database. All that you need is a cache 
-that's large enough for your "working set." 
-
-That means, large enough to hold all of the most frequently accessed data, 
-plus a few less-frequently accessed items.
-
-For more information, please see: {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/ref/am_conf/cachesize.html}}
-
-H4: Calculating Cachesize
-
-The back-bdb database lives in two main files, {{F:dn2id.bdb}} and {{F:id2entry.bdb}}. 
-These are B-tree databases. We have never documented the back-bdb internal 
-layout before, because it didn't seem like something anyone should have to worry 
-about, nor was it necessarily cast in stone. But here's how it works today, 
-in OpenLDAP 2.4.
-
-A B-tree is a balanced tree; it stores data in its leaf nodes and bookkeeping 
-data in its interior nodes (If you don't know what tree data structures look
- like in general, Google for some references, because that's getting far too 
-elementary for the purposes of this discussion).
-
-For decent performance, you need enough cache memory to contain all the nodes 
-along the path from the root of the tree down to the particular data item 
-you're accessing. That's enough cache for a single search. For the general case, 
-you want enough cache to contain all the internal nodes in the database. 
-
->       db_stat -d
-
-will tell you how many internal pages are present in a database. You should 
-check this number for both dn2id and id2entry.
-
-Also note that {{id2entry}} always uses 16KB per "page", while {{dn2id}} uses whatever 
-the underlying filesystem uses, typically 4 or 8KB. To avoid thrashing,
-your cache must be at least as large as the number of internal pages in both 
-the {{dn2id}} and {{id2entry}} databases, plus some extra space to accommodate
-the actual leaf data pages.
-
-For example, in my OpenLDAP 2.4 test database, I have an input LDIF file that's 
-about 360MB. With the back-hdb backend this creates a {{dn2id.bdb}} that's 68MB, 
-and an {{id2entry}} that's 800MB. db_stat tells me that {{dn2id}} uses 4KB pages, has 
-433 internal pages, and 6378 leaf pages. The id2entry uses 16KB pages, has 52 
-internal pages, and 45912 leaf pages. In order to efficiently retrieve any 
-single entry in this database, the cache should be at least
-
->       (433+1) * 4KB + (52+1) * 16KB in size: 1736KB + 848KB =~ 2.5MB.
-
-This doesn't take into account other library overhead, so this is even lower 
-than the barest minimum. The default cache size, when nothing is configured, 
-is only 256KB. 
-
-This 2.5MB number also doesn't take indexing into account. Each indexed
-attribute results in another database file.  Earlier versions of OpenLDAP
-kept these index databases in Hash format, but from OpenLDAP 2.2 onward
-the index databases are in B-tree format so the same procedure can
-be used to calculate the necessary amount of cache for each index database.
-
-For example, if your only index is for the objectClass attribute and db_stat
-reveals that {{objectClass.bdb}} has 339 internal pages and uses 4096 byte
-pages, the additional cache needed for just this attribute index is
-
->       (339+1) * 4KB =~ 1.3MB.
-
-With only this index enabled, I'd figure at least a 4MB cache for this backend. 
-(Of course you're using a single cache shared among all of the database files, 
-so the cache pages will most likely get used for something other than what you 
-accounted for, but this gives you a fighting chance.)
-
-With this 4MB cache I can slapcat this entire database on my 1.3GHz PIII in 
-1 minute, 40 seconds. With the cache doubled to 8MB, it still takes the same 1:40s. 
-Once you've got enough cache to fit the B-tree internal pages, increasing it 
-further won't have any effect until the cache really is large enough to hold 
-100% of the data pages. I don't have enough free RAM to hold all the 800MB 
-id2entry data, so 4MB is good enough.
-
-With back-bdb and back-hdb you can use "db_stat -m" to check how well the 
-database cache is performing. 
-
-For more information on {{db_stat}}: {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/utility/db_stat.html}}
-
-H3: {{slapd}}(8) Entry Cache (cachesize)
-
-The {{slapd}}(8) entry cache operates on decoded entries. The rationale - entries 
-in the entry cache can be used directly, giving the fastest response. If an entry 
-isn't in the entry cache but can be extracted from the BDB page cache, that will 
-avoid an I/O but it will still require parsing, so this will be slower. 
-
-If the entry is in neither cache then BDB will have to flush some of its current 
-cached pages and bring in the needed pages, resulting in a couple of expensive 
-I/Os as well as parsing.
-
-The most optimal value is of course, the entire number of entries in the database.  
-However, most directory servers don't consistently serve out their entire database, so setting this to a lesser number that more closely matches the believed working set of data is 
-sufficient. This is the second most important parameter for the DB.
-
-As far as balancing the entry cache vs the BDB cache - parsed entries in memory 
-are generally about twice as large as they are on disk. 
-
-As we have already mentioned, not having a proper database cache size will 
-cause performance issues. These issues are not an indication of corruption 
-occurring in the database. It is merely the fact that the cache is thrashing 
-itself that causes performance/response time to slowdown. 
-
-
-H3: {{TERM:IDL}} Cache (idlcachesize)
-
-Each IDL holds the search results from a given query, so the IDL cache will 
-end up holding the most frequently requested search results.  For back-bdb, 
-it is generally recommended to match the "cachesize" setting.  For back-hdb, 
-it is generally recommended to be 3x"cachesize".
-
-{NOTE: The idlcachesize setting directly affects search performance}
-
-
 H2: {{slapd}}(8) Threads
 
 {{slapd}}(8) can process requests via a configurable number of threads, which
diff --git a/doc/guide/preamble.sdf b/doc/guide/preamble.sdf
index b4cc0dd..aa84f9b 100644
--- a/doc/guide/preamble.sdf
+++ b/doc/guide/preamble.sdf
@@ -167,7 +167,6 @@ AuthcId|Authentication Identity
 AuthzDN|Authorization DN
 AuthzId|Authorization Identity
 BCP|Best Current Practice
-BDB|Berkeley DB (Backend)
 BER|Basic Encoding Rules
 BNF|Backus-Naur Form
 C|The C Programming Language
@@ -201,7 +200,6 @@ FYI|For Your Information
 GSER|Generic String Encoding Rules
 GSS-API|Generic Security Service Application Program Interface
 GSSAPI|SASL Kerberos V GSS-API Authentication Mechanism
-HDB|Hierarchical Database (Backend)
 I-D|Internet-Draft
 IA5|International Alphabet 5
 IDNA|Internationalized Domain Names in Applications
diff --git a/doc/guide/release/install.sdf b/doc/guide/release/install.sdf
index 6770e6a..83c95ae 100644
--- a/doc/guide/release/install.sdf
+++ b/doc/guide/release/install.sdf
@@ -84,7 +84,7 @@ if you have not done so already.
 + Test the standalone system:
 
 .This step requires the standalone LDAP server, {{slapd}}(8),
-with {{HDB}} and/or {{BDB}} support.
+with {{MDB}} support.
 
 E:	% make test
 
diff --git a/doc/man/man5/slapd-bdb.5 b/doc/man/man5/slapd-bdb.5
deleted file mode 100644
index 3c8ad9c..0000000
--- a/doc/man/man5/slapd-bdb.5
+++ /dev/null
@@ -1,286 +0,0 @@
-.TH SLAPD-BDB 5 "RELEASEDATE" "OpenLDAP LDVERSION"
-.\" Copyright 1998-2020 The OpenLDAP Foundation All Rights Reserved.
-.\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
-.\" $OpenLDAP$
-.SH NAME
-slapd\-bdb, slapd\-hdb \- Berkeley DB backends to slapd
-.SH SYNOPSIS
-.B ETCDIR/slapd.conf
-.SH DESCRIPTION
-The \fBbdb\fP backend to
-.BR slapd (8)
-uses the Oracle Berkeley DB (BDB) package to store data.
-It makes extensive use of indexing and caching to speed data access.
-.LP
-Note that BDB is deprecated and support will be dropped in future
-OpenLDAP releases. Installations should use the \fBmdb\fP
-backend instead.
-.LP
-\fBhdb\fP is a variant of
-the \fBbdb\fP backend that uses a hierarchical database layout which
-supports subtree renames. It is both more space-efficient and more
-execution-efficient than the \fBbdb\fP backend.  It is otherwise identical
-to the \fBbdb\fP behavior, and all the same configuration options apply.
-.LP
-It is noted that these options are intended to complement
-Berkeley DB configuration options set in the environment's
-.B DB_CONFIG
-file.  See Berkeley DB documentation for details on
-.B DB_CONFIG
-configuration options.
-Where there is overlap, settings in
-.B DB_CONFIG
-take precedence.
-.SH CONFIGURATION
-These
-.B slapd.conf
-options apply to the \fBbdb\fP and \fBhdb\fP backend database.
-That is, they must follow a "database bdb" or "database hdb" line and
-come before any subsequent "backend" or "database" lines.
-Other database options are described in the
-.BR slapd.conf (5)
-manual page.
-.TP
-.BI cachesize \ <integer>
-Specify the size in entries of the in-memory entry cache maintained 
-by the \fBbdb\fP or \fBhdb\fP backend database instance.
-The default is 1000 entries.
-.TP
-.BI cachefree \ <integer>
-Specify the number of entries to free from the entry cache when the
-cache reaches the \fBcachesize\fP limit.
-The default is 1 entry.
-.TP
-.BI checkpoint \ <kbyte>\ <min>
-Specify the frequency for checkpointing the database transaction log.
-A checkpoint operation flushes the database buffers to disk and writes
-a checkpoint record in the log.
-The checkpoint will occur if either \fI<kbyte>\fP data has been written or
-\fI<min>\fP minutes have passed since the last checkpoint.
-Both arguments default to zero, in which case they are ignored. When
-the \fI<min>\fP argument is non-zero, an internal task will run every 
-\fI<min>\fP minutes to perform the checkpoint.
-See the Berkeley DB reference guide for more details.
-.TP
-.B checksum
-Enable checksum validation of DB pages whenever they are read from disk.
-This setting can only be configured before any database files are created.
-.TP
-.BI cryptfile \ <file>
-Specify the pathname of a file containing an encryption key to use for
-encrypting the database. Encryption is performed using Berkeley DB's
-implementation of AES. Note that encryption can only be configured before
-any database files are created, and changing the key can only be done
-after destroying the current database and recreating it. Encryption is
-not enabled by default, and some distributions of Berkeley DB do not
-support encryption.
-.TP
-.BI cryptkey \ <key>
-Specify an encryption key to use for encrypting the database. This option
-may be used when a separate
-.I cryptfile
-is not desired. Only one of
-.B cryptkey
-or
-.B cryptfile
-may be configured.
-.TP
-.BI dbconfig \ <Berkeley-DB-setting>
-Specify a configuration directive to be placed in the
-.B DB_CONFIG
-file of the database directory. The
-.B dbconfig
-directive is just a convenience
-to allow all necessary configuration to be set in the
-.B slapd.conf
-file.
-The options set using this directive will only be written to the 
-.B DB_CONFIG
-file if no such file existed at server startup time, otherwise
-they are completely ignored. This allows one
-to set initial values without overwriting/destroying a 
-.B DB_CONFIG 
-file that was already customized through other means. 
-This directive may be specified multiple times, as needed. 
-For example:
-.RS
-.nf
-	dbconfig set_cachesize 0 1048576 0
-	dbconfig set_lg_bsize 2097152
-.fi
-.RE
-.TP
-.B dbnosync
-Specify that on-disk database contents should not be immediately
-synchronized with in memory changes.
-Enabling this option may improve performance at the expense of data
-security.
-See the Berkeley DB reference guide for more details.
-.TP
-\fBdbpagesize \fR \fI<dbfile> <size>\fR
-Specify the page size to use for a particular database file, in units
-of 1024 bytes. The default for the
-.B id2entry
-file is 16, the default for all other files depends on the size of the
-underlying filesystem's block size (typically 4 or 8).
-The maximum that BerkeleyDB supports is 64. This
-setting usually should not need to be changed, but if BerkeleyDB's
-"db_stat \-d" shows a large amount of overflow pages in use in a file,
-setting a larger size may increase performance at the expense of
-data integrity. This setting only takes effect when a database is
-being newly created. See the Berkeley DB reference guide for more details.
-.TP
-.BI directory \ <directory>
-Specify the directory where the BDB files containing this database and
-associated indexes live.
-A separate directory must be specified for each database.
-The default is
-.BR LOCALSTATEDIR/openldap\-data .
-.TP
-.B dirtyread
-Allow reads of modified but not yet committed data.
-Usually transactions are isolated to prevent other operations from
-accessing uncommitted data.
-This option may improve performance, but may also return inconsistent
-results if the data comes from a transaction that is later aborted.
-In this case, the modified data is discarded and a subsequent search
-will return a different result.
-.TP
-.BI dncachesize \ <integer>
-Specify the maximum number of DNs in the in-memory DN cache.
-Ideally this cache should be
-large enough to contain the DNs of every entry in the database. If
-set to a smaller value than the \fBcachesize\fP it will be silently
-increased to equal the \fBcachesize\fP. The default value is 0 which
-means unlimited, i.e. the DN cache will grow without bound.
-
-It should be noted that the \fBDN cache\fP is allowed to temporarily
-grow beyond the configured size. It does this if many entries are 
-locked when it tries to do a purge, because that means they're
-legitimately in use. Also, the \fBDN cache\fP never purges entries
-that have cached children, so depending on the shape of the DIT, it 
-could have lots of cached DNs over the defined limit.
-.TP
-.BI idlcachesize \ <integer>
-Specify the size of the in-memory index cache, in index slots. The
-default is zero. A larger value will speed up frequent searches of
-indexed entries. An \fBhdb\fP database needs a large \fBidlcachesize\fP
-for good search performance, typically three times the 
-.B cachesize
-(entry cache size)
-or larger.
-.TP
-\fBindex \fR{\fI<attrlist>\fR|\fBdefault\fR} [\fBpres\fR,\fBeq\fR,\fBapprox\fR,\fBsub\fR,\fI<special>\fR]
-Specify the indexes to maintain for the given attribute (or
-list of attributes).
-Some attributes only support a subset of indexes.
-If only an \fI<attr>\fP is given, the indices specified for \fBdefault\fR
-are maintained.
-Note that setting a default does not imply that all attributes will be
-indexed. Also, for best performance, an
-.B eq
-index should always be configured for the
-.B objectClass
-attribute.
-
-A number of special index parameters may be specified.
-The index type
-.B sub
-can be decomposed into
-.BR subinitial ,
-.BR subany ,\ and
-.B subfinal
-indices.
-The special type
-.B nolang
-may be specified to disallow use of this index by language subtypes.
-The special type
-.B nosubtypes
-may be specified to disallow use of this index by named subtypes.
-Note: changing \fBindex\fP settings in 
-.BR slapd.conf (5)
-requires rebuilding indices, see
-.BR slapindex (8);
-changing \fBindex\fP settings
-dynamically by LDAPModifying "cn=config" automatically causes rebuilding
-of the indices online in a background task.
-.TP
-.B linearindex
-Tell 
-.B slapindex 
-to index one attribute at a time. By default, all indexed
-attributes in an entry are processed at the same time. With this option,
-each indexed attribute is processed individually, using multiple passes
-through the entire database. This option improves 
-.B slapindex 
-performance
-when the database size exceeds the \fBdbcache\fP size. When the \fBdbcache\fP is
-large enough, this option is not needed and will decrease performance.
-Also by default, 
-.B slapadd 
-performs full indexing and so a separate 
-.B slapindex
-run is not needed. With this option, 
-.B slapadd 
-does no indexing and 
-.B slapindex
-must be used.
-.TP
-.BR lockdetect \ { oldest | youngest | fewest | random | default }
-Specify which transaction to abort when a deadlock is detected.
-The default is
-.BR random .
-.TP
-.BI mode \ <integer>
-Specify the file protection mode that newly created database 
-index files should have.
-The default is 0600.
-.TP
-.BI searchstack \ <depth>
-Specify the depth of the stack used for search filter evaluation.
-Search filters are evaluated on a stack to accommodate nested AND / OR
-clauses. An individual stack is assigned to each server thread.
-The depth of the stack determines how complex a filter can be
-evaluated without requiring any additional memory allocation. Filters that
-are nested deeper than the search stack depth will cause a separate
-stack to be allocated for that particular search operation. These
-allocations can have a major negative impact on server performance,
-but specifying too much stack will also consume a great deal of memory.
-Each search stack uses 512K bytes per level. The default stack depth
-is 16, thus 8MB per thread is used.
-.TP
-.BI shm_key \ <integer>
-Specify a key for a shared memory BDB environment. By default the
-BDB environment uses memory mapped files. If a non-zero value is
-specified, it will be used as the key to identify a shared memory
-region that will house the environment.
-.SH ACCESS CONTROL
-The 
-.B bdb
-and
-.B hdb
-backends honor access control semantics as indicated in
-.BR slapd.access (5).
-.SH FILES
-.TP
-.B ETCDIR/slapd.conf
-default 
-.B slapd 
-configuration file
-.TP
-.B DB_CONFIG
-Berkeley DB configuration file
-.SH SEE ALSO
-.BR slapd.conf (5),
-.BR slapd\-config (5),
-.BR slapd\-mdb (5),
-.BR slapd (8),
-.BR slapadd (8),
-.BR slapcat (8),
-.BR slapindex (8),
-Berkeley DB documentation.
-.SH ACKNOWLEDGEMENTS
-.so ../Project
-Originally begun by Kurt Zeilenga. Caching mechanisms originally designed
-by Jong-Hyuk Choi. Completion and subsequent work, as well as
-back-hdb, by Howard Chu.
diff --git a/doc/man/man5/slapd-bdb.5.links b/doc/man/man5/slapd-bdb.5.links
deleted file mode 100644
index 3bc8c40..0000000
--- a/doc/man/man5/slapd-bdb.5.links
+++ /dev/null
@@ -1 +0,0 @@
-slapd-hdb.5
diff --git a/doc/man/man5/slapd-config.5 b/doc/man/man5/slapd-config.5
index 5753292..3061dcf 100644
--- a/doc/man/man5/slapd-config.5
+++ b/doc/man/man5/slapd-config.5
@@ -1123,10 +1123,8 @@ The entry must be named
 and must have the olcBackendConfig objectClass.
 <databasetype>
 should be one of
-.BR bdb ,
 .BR config ,
 .BR dnssrv ,
-.BR hdb ,
 .BR ldap ,
 .BR ldif ,
 .BR mdb ,
@@ -2059,10 +2057,10 @@ olcDatabase: config
 olcRootPW: {SSHA}XKYnrjvGT3wZFQrDD5040US592LxsdLy
 olcAccess: to * by * none
 
-dn: olcDatabase=bdb,cn=config
+dn: olcDatabase=mdb,cn=config
 objectClass: olcDatabaseConfig
-objectClass: olcBdbConfig
-olcDatabase: bdb
+objectClass: olcMdbConfig
+olcDatabase: mdb
 olcSuffix: "dc=our\-domain,dc=com"
 # The database directory MUST exist prior to
 # running slapd AND should only be accessible
diff --git a/doc/man/man5/slapd-mdb.5 b/doc/man/man5/slapd-mdb.5
index 62146b0..8955bbb 100644
--- a/doc/man/man5/slapd-mdb.5
+++ b/doc/man/man5/slapd-mdb.5
@@ -14,11 +14,8 @@ It relies completely on the underlying operating system for memory
 management and does no caching of its own. It is the recommended
 primary database backend.
 .LP
-The \fBmdb\fP backend is similar to the \fBhdb\fP backend in that
-it uses a hierarchical database layout which
-supports subtree renames. It is both more space-efficient and more
-execution-efficient than the \fBbdb\fP backend, while being overall
-much simpler to manage.
+The \fBmdb\fP backend uses a hierarchical database layout which
+supports subtree renames.
 .SH CONFIGURATION
 These
 .B slapd.conf
diff --git a/doc/man/man5/slapd-sql.5 b/doc/man/man5/slapd-sql.5
index 8492553..ccfa3a4 100644
--- a/doc/man/man5/slapd-sql.5
+++ b/doc/man/man5/slapd-sql.5
@@ -19,7 +19,7 @@ sites/applications that use RDBMSes and/or LDAP.
 Or whatever else...
 .LP
 It is NOT designed as a general-purpose backend that uses RDBMS instead
-of BerkeleyDB (as the standard BDB backend does), though it can be
+of MDB (as the standard MDB backend does), though it can be
 used as such with several limitations.
 You can take a look at
 .B http://www.openldap.org/faq/index.cgi?file=378 
diff --git a/doc/man/man5/slapd.access.5 b/doc/man/man5/slapd.access.5
index c62158b..ebad05a 100644
--- a/doc/man/man5/slapd.access.5
+++ b/doc/man/man5/slapd.access.5
@@ -920,9 +920,8 @@ identity, control is passed straight to the subsequent rules.
 
 .SH OPERATION REQUIREMENTS
 Operations require different privileges on different portions of entries.
-The following summary applies to primary MDB database backend and the
-deprecated BDB and HDB backends.   Requirements for other backends may
-(and often do) differ.
+The following summary applies to primary MDB database backend. Requirements
+for other backends may (and often do) differ.
 
 .LP
 The
@@ -1085,9 +1084,7 @@ Access control to search entries is checked by the frontend,
 so it is fully honored by all backends; for all other operations
 and for the discovery phase of the search operation,
 full ACL semantics is only supported by the primary backends, i.e.
-.BR back\-bdb (5),
-and
-.BR back\-hdb (5).
+.BR back\-mdb (5).
 
 Some other backend, like
 .BR back\-sql (5),
diff --git a/doc/man/man5/slapd.backends.5 b/doc/man/man5/slapd.backends.5
index b9f9190..25a70e6 100644
--- a/doc/man/man5/slapd.backends.5
+++ b/doc/man/man5/slapd.backends.5
@@ -19,14 +19,6 @@ corresponding
 .BR slapd\-<backend> (5)
 manual pages.
 .TP
-.B bdb
-This was the recommended primary backend through OpenLDAP 2.3, but it has
-since been superseded by the
-.BR mdb
-backend.  It takes care to configure it properly.
-It uses the transactional database interface of the Oracle Berkeley
-DB (BDB) package to store data.
-.TP
 .B config
 This backend is used to manage the configuration of slapd at run-time.
 Unlike other backends, only a single instance of the
@@ -41,22 +33,6 @@ This backend is experimental.
 It serves up referrals based upon SRV resource records held in the
 Domain Name System.
 .TP
-.B hdb
-This was the recommended primary backend through OpenLDAP 2.4.40 but it has
-since been superseded by the
-.BR mdb
-backend.  It takes care to configure it properly.
-.B hdb
-is a variant of the
-.B bdb
-backend that uses a hierarchical database
-layout.
-This layout stores entry DNs more efficiently than the
-.B bdb
-backend,
-using less space and requiring less work to create, delete, and rename
-entries. It is also one of the few backends to support subtree renames.
-.TP
 .B ldap
 This backend acts as a proxy to forward incoming requests to another
 LDAP server.
@@ -68,14 +44,9 @@ Its usage should be limited to very simple databases, where performance
 is not a requirement. This backend also supports subtree renames.
 .TP
 .B mdb
-This is the recommended primary backend, superseding
-.BR hdb .
+This is the recommended primary backend.
 This backend uses OpenLDAP's own MDB transactional database
-library. It is extremely compact and extremely efficient, delivering
-much higher performance than the Berkeley DB backends while using
-significantly less memory.  Also, unlike Berkeley DB, MDB is crash proof,
-and requires no special tuning or maintenance.
-This backend also supports subtree renames.
+library. This backend also supports subtree renames.
 .TP
 .B meta
 This backend performs basic LDAP proxying with respect to a set of
@@ -138,10 +109,8 @@ ETCDIR/slapd.d
 default slapd configuration directory
 .SH SEE ALSO
 .BR ldap (3),
-.BR slapd\-bdb (5),
 .BR slapd\-config (5),
 .BR slapd\-dnssrv (5),
-.BR slapd\-hdb (5),
 .BR slapd\-ldap (5),
 .BR slapd\-ldif (5),
 .BR slapd\-mdb (5),
diff --git a/doc/man/man5/slapd.conf.5 b/doc/man/man5/slapd.conf.5
index 78b2415..0fa62ce 100644
--- a/doc/man/man5/slapd.conf.5
+++ b/doc/man/man5/slapd.conf.5
@@ -1250,10 +1250,8 @@ type of backend.
 .B backend <databasetype>
 Mark the beginning of a backend definition. <databasetype>
 should be one of
-.BR bdb ,
 .BR config ,
 .BR dnssrv ,
-.BR hdb ,
 .BR ldap ,
 .BR ldif ,
 .BR mdb ,
@@ -1280,10 +1278,8 @@ option are mandatory for each database.
 .B database <databasetype>
 Mark the beginning of a new database instance definition. <databasetype>
 should be one of
-.BR bdb ,
 .BR config ,
 .BR dnssrv ,
-.BR hdb ,
 .BR ldap ,
 .BR ldif ,
 .BR mdb ,
@@ -1593,8 +1589,7 @@ By default, mirrormode is off.
 This option enables database-specific monitoring in the entry related
 to the current database in the "cn=Databases,cn=Monitor" subtree 
 of the monitor database, if the monitor database is enabled.
-Currently, only the BDB and the HDB databases provide database-specific
-monitoring.
+Currently, only the MDB databases provide database-specific monitoring.
 The default depends on the backend type.
 .TP
 .B overlay <overlay-name>
diff --git a/doc/man/man5/slapd.overlays.5 b/doc/man/man5/slapd.overlays.5
index 2345d81..8ca9783 100644
--- a/doc/man/man5/slapd.overlays.5
+++ b/doc/man/man5/slapd.overlays.5
@@ -91,7 +91,7 @@ password resets, etc.
 .B refint
 Referential Integrity.
 This overlay can be used with a backend database such as
-.BR slapd\-bdb (5)
+.BR slapd\-mdb (5)
 to maintain the cohesiveness of a schema which utilizes reference
 attributes.
 .TP
@@ -121,7 +121,7 @@ replication, including persistent search functionality.
 .B translucent
 Translucent Proxy.
 This overlay can be used with a backend database such as
-.BR slapd\-bdb (5)
+.BR slapd\-mdb (5)
 to create a "translucent proxy".
 Content of entries retrieved from a remote LDAP server can be partially
 overridden by the database.
@@ -129,7 +129,7 @@ overridden by the database.
 .B unique
 Attribute Uniqueness.
 This overlay can be used with a backend database such as
-.BR slapd\-bdb (5)
+.BR slapd\-mdb (5)
 to enforce the uniqueness of some or all attributes within a subtree.
 .TP
 .B valsort
diff --git a/doc/man/man8/slapcat.8 b/doc/man/man8/slapcat.8
index bd22637..a80ad36 100644
--- a/doc/man/man8/slapcat.8
+++ b/doc/man/man8/slapcat.8
@@ -177,8 +177,6 @@ mode) when you do this to ensure consistency of the database. It is
 always safe to run 
 .B slapcat
 with the
-.BR slapd\-bdb (5),
-.BR slapd\-hdb (5),
 .BR slapd\-mdb (5),
 and
 .BR slapd\-null (5)
diff --git a/doc/man/man8/slapschema.8 b/doc/man/man8/slapschema.8
index 704ab0c..f4ea0cd 100644
--- a/doc/man/man8/slapschema.8
+++ b/doc/man/man8/slapschema.8
@@ -168,8 +168,7 @@ mode) when you do this to ensure consistency of the database. It is
 always safe to run 
 .B slapschema
 with the
-.BR slapd\-bdb (5),
-.BR slapd\-hdb (5),
+.BR slapd\-mdb (5),
 and
 .BR slapd\-null (5)
 backends.
diff --git a/include/portable.hin b/include/portable.hin
index 3169f03..1b1be1a 100644
--- a/include/portable.hin
+++ b/include/portable.hin
@@ -99,12 +99,6 @@
 /* Define to 1 if you have the `bcopy' function. */
 #undef HAVE_BCOPY
 
-/* define this if Berkeley DB is available */
-#undef HAVE_BERKELEY_DB
-
-/* define if Berkeley DB has DB_THREAD support */
-#undef HAVE_BERKELEY_DB_THREAD
-
 /* Define to 1 if you have the <bits/types.h> header file. */
 #undef HAVE_BITS_TYPES_H
 
@@ -924,9 +918,6 @@
 /* define to support per-object ACIs */
 #undef SLAPD_ACI_ENABLED
 
-/* define to support BDB backend */
-#undef SLAPD_BDB
-
 /* define to support cleartext passwords */
 #undef SLAPD_CLEARTEXT
 
@@ -936,9 +927,6 @@
 /* define to support DNS SRV backend */
 #undef SLAPD_DNSSRV
 
-/* define to support HDB backend */
-#undef SLAPD_HDB
-
 /* define to support LDAP backend */
 #undef SLAPD_LDAP
 
diff --git a/servers/slapd/DB_CONFIG b/servers/slapd/DB_CONFIG
deleted file mode 100644
index d0f2c68..0000000
--- a/servers/slapd/DB_CONFIG
+++ /dev/null
@@ -1,28 +0,0 @@
-# $OpenLDAP$
-# Example DB_CONFIG file for use with slapd(8) BDB/HDB databases.
-#
-# See the Oracle Berkeley DB documentation
-#   <http://www.oracle.com/technology/documentation/berkeley-db/db/ref/env/db_config.html>
-# for detail description of DB_CONFIG syntax and semantics.
-#
-# Hints can also be found in the OpenLDAP Software FAQ
-#	<http://www.openldap.org/faq/index.cgi?file=2>
-# in particular:
-#   <http://www.openldap.org/faq/index.cgi?file=1075>
-
-# Note: most DB_CONFIG settings will take effect only upon rebuilding
-# the DB environment.
-
-# one 0.25 GB cache
-set_cachesize 0 268435456 1
-
-# Data Directory
-#set_data_dir db
-
-# Transaction Log settings
-set_lg_regionmax 262144
-set_lg_bsize 2097152
-#set_lg_dir logs
-
-# Note: special DB_CONFIG flags are no longer needed for "quick"
-# slapadd(8) or slapindex(8) access (see their -q option). 
diff --git a/servers/slapd/Makefile.in b/servers/slapd/Makefile.in
index b20564d..9a9f589 100644
--- a/servers/slapd/Makefile.in
+++ b/servers/slapd/Makefile.in
@@ -38,7 +38,7 @@ SRCS	= main.c globals.c bconfig.c config.c daemon.c \
 		backglue.c backover.c ctxcsn.c ldapsync.c frontend.c \
 		slapadd.c slapcat.c slapcommon.c slapdn.c slapindex.c \
 		slappasswd.c slaptest.c slapauth.c slapacl.c component.c \
-		aci.c alock.c txn.c slapschema.c \
+		aci.c txn.c slapschema.c \
 		$(@PLAT@_SRCS)
 
 OBJS	= main.o globals.o bconfig.o config.o daemon.o \
@@ -56,7 +56,7 @@ OBJS	= main.o globals.o bconfig.o config.o daemon.o \
 		backglue.o backover.o ctxcsn.o ldapsync.o frontend.o \
 		slapadd.o slapcat.o slapcommon.o slapdn.o slapindex.o \
 		slappasswd.o slaptest.o slapauth.o slapacl.o component.o \
-		aci.o alock.o txn.o slapschema.o \
+		aci.o txn.o slapschema.o \
 		$(@PLAT@_OBJS)
 
 LDAP_INCDIR= ../../include -I$(srcdir) -I$(srcdir)/slapi -I.
@@ -366,14 +366,8 @@ veryclean-local-srv: FORCE
 		fi; \
 	done
 
-install-dbc-maybe: install-dbc-@BUILD_BDB@ install-dbc-@BUILD_HDB@
-
-install-dbc-yes:	install-db-config
-install-dbc-mod:	install-db-config
-install-dbc-no:
-
 install-local-srv: install-slapd install-tools \
-	install-conf install-dbc-maybe install-schema install-tools
+	install-conf install-schema install-tools
 
 install-slapd: FORCE
 	-$(MKDIR) $(DESTDIR)$(libexecdir)
diff --git a/servers/slapd/alock.c b/servers/slapd/alock.c
deleted file mode 100644
index 4e85fad..0000000
--- a/servers/slapd/alock.c
+++ /dev/null
@@ -1,718 +0,0 @@
-/* alock.c - access lock library */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2005-2020 The OpenLDAP Foundation.
- * Portions Copyright 2004-2005 Symas Corporation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was initially developed by Emily Backes at Symas
- * Corporation for inclusion in OpenLDAP Software.
- */
-
-#include "portable.h"
-
-#if SLAPD_BDB || SLAPD_HDB
-
-#include <lber.h>
-#include "alock.h"
-#include "lutil.h"
-
-#include <ac/stdlib.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-#include <ac/errno.h>
-#include <ac/assert.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#ifdef HAVE_SYS_FILE_H
-#include <sys/file.h>
-#endif
-#include <fcntl.h>
-
-#ifdef _WIN32
-#include <windows.h>
-#include <stdio.h>
-#include <io.h>
-#endif
-
-
-static int
-alock_grab_lock ( int fd, int slot )
-{
-	int res;
-	
-#if defined( HAVE_LOCKF )
-	res = lseek (fd, (off_t) (ALOCK_SLOT_SIZE * slot), SEEK_SET);
-	if (res == -1) return -1;
-	res = lockf (fd, F_LOCK, (off_t) ALOCK_SLOT_SIZE);
-#elif defined( HAVE_FCNTL )
-	struct flock lock_info;
-	(void) memset ((void *) &lock_info, 0, sizeof (struct flock));
-
-	lock_info.l_type = F_WRLCK;
-	lock_info.l_whence = SEEK_SET;
-	lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
-	lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
-
-	res = fcntl (fd, F_SETLKW, &lock_info);
-#elif defined( _WIN32 )
-	OVERLAPPED ov;
-	HANDLE hh = _get_osfhandle ( fd );
-	ov.hEvent = 0;
-	ov.Offset = ALOCK_SLOT_SIZE*slot;
-	ov.OffsetHigh = 0;
-	res = LockFileEx( hh, LOCKFILE_EXCLUSIVE_LOCK, 0,
-		ALOCK_SLOT_SIZE, 0, &ov ) ? 0 : -1;
-#else
-#   error alock needs lockf, fcntl, or LockFile[Ex]
-#endif
-	if (res == -1) {
-		assert (errno != EDEADLK);
-		return -1;
-	}
-	return 0;
-}
-
-static int
-alock_release_lock ( int fd, int slot )
-{
-	int res;
-	
-#if defined( HAVE_LOCKF )
-	res = lseek (fd, (off_t) (ALOCK_SLOT_SIZE * slot), SEEK_SET);
-	if (res == -1) return -1;
-	res = lockf (fd, F_ULOCK, (off_t) ALOCK_SLOT_SIZE);
-	if (res == -1) return -1;
-#elif defined ( HAVE_FCNTL )
-	struct flock lock_info;
-	(void) memset ((void *) &lock_info, 0, sizeof (struct flock));
-
-	lock_info.l_type = F_UNLCK;
-	lock_info.l_whence = SEEK_SET;
-	lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
-	lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
-
-	res = fcntl (fd, F_SETLKW, &lock_info);
-	if (res == -1) return -1;
-#elif defined( _WIN32 )
-	HANDLE hh = _get_osfhandle ( fd );
-	if ( !UnlockFile ( hh, ALOCK_SLOT_SIZE*slot, 0,
-		ALOCK_SLOT_SIZE, 0 ))
-		return -1;
-#else
-#   error alock needs lockf, fcntl, or LockFile[Ex]
-#endif
-
-	return 0;
-}
-
-static int
-alock_share_lock ( int fd, int slot )
-{
-	int res;
-
-#if defined( HAVE_LOCKF )
-	res = 0;	/* lockf has no shared locks */
-#elif defined ( HAVE_FCNTL )
-	struct flock lock_info;
-	(void) memset ((void *) &lock_info, 0, sizeof (struct flock));
-
-	/* The shared lock replaces the existing lock */
-	lock_info.l_type = F_RDLCK;
-	lock_info.l_whence = SEEK_SET;
-	lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
-	lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
-
-	res = fcntl (fd, F_SETLK, &lock_info);
-	if (res == -1) return -1;
-#elif defined( _WIN32 )
-	OVERLAPPED ov;
-	HANDLE hh = _get_osfhandle ( fd );
-
-	/* Windows locks are mandatory, not advisory.
-	 * We must downgrade the lock to allow future
-	 * callers to read the slot data.
-	 *
-	 * First acquire a shared lock. Unlock will
-	 * release the existing exclusive lock.
-	 */
-	ov.hEvent = 0;
-	ov.Offset = ALOCK_SLOT_SIZE*slot;
-	ov.OffsetHigh = 0;
-	LockFileEx (hh, 0, 0, ALOCK_SLOT_SIZE, 0, &ov);
-	UnlockFile (hh, ALOCK_SLOT_SIZE*slot, 0, ALOCK_SLOT_SIZE, 0);
-#else
-#   error alock needs lockf, fcntl, or LockFile[Ex]
-#endif
-
-	return 0;
-}
-
-static int
-alock_test_lock ( int fd, int slot )
-{
-	int res;
-
-#if defined( HAVE_LOCKF )
-	res = lseek (fd, (off_t) (ALOCK_SLOT_SIZE * slot), SEEK_SET);
-	if (res == -1) return -1;
-
-	res = lockf (fd, F_TEST, (off_t) ALOCK_SLOT_SIZE);
-	if (res == -1) {
-		if (errno == EACCES || errno == EAGAIN) { 
-			return ALOCK_LOCKED;
-		} else {
-			return -1;
-		}
-	}
-#elif defined( HAVE_FCNTL )
-	struct flock lock_info;
-	(void) memset ((void *) &lock_info, 0, sizeof (struct flock));
-
-	lock_info.l_type = F_WRLCK;
-	lock_info.l_whence = SEEK_SET;
-	lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
-	lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
-
-	res = fcntl (fd, F_GETLK, &lock_info);
-	if (res == -1) return -1;
-
-	if (lock_info.l_type != F_UNLCK) return ALOCK_LOCKED;
-#elif defined( _WIN32 )
-	OVERLAPPED ov;
-	HANDLE hh = _get_osfhandle ( fd );
-	ov.hEvent = 0;
-	ov.Offset = ALOCK_SLOT_SIZE*slot;
-	ov.OffsetHigh = 0;
-	if( !LockFileEx( hh,
-		LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY, 0,
-		ALOCK_SLOT_SIZE, 0, &ov )) {
-		int err = GetLastError();
-		if ( err == ERROR_LOCK_VIOLATION )
-			return ALOCK_LOCKED;
-		else
-			return -1;
-	}
-#else
-#   error alock needs lockf, fcntl, or LockFile
-#endif
-	
-	return 0;
-}
-
-/* Read a 64bit LE value */
-static unsigned long int
-alock_read_iattr ( unsigned char * bufptr )
-{
-	unsigned long int val = 0;
-	int count;
-
-	assert (bufptr != NULL);
-
-	bufptr += sizeof (unsigned long int);
-	for (count=0; count <= (int) sizeof (unsigned long int); ++count) {
-		val <<= 8;
-		val += (unsigned long int) *bufptr--;
-	}
-
-	return val;
-}
-
-/* Write a 64bit LE value */
-static void
-alock_write_iattr ( unsigned char * bufptr,
-		    unsigned long int val )
-{
-	int count;
-
-	assert (bufptr != NULL);
-
-	for (count=0; count < 8; ++count) {
-		*bufptr++ = (unsigned char) (val & 0xff);
-		val >>= 8;
-	}
-}
-
-static int
-alock_read_slot ( alock_info_t * info,
-		  alock_slot_t * slot_data )
-{
-	unsigned char slotbuf [ALOCK_SLOT_SIZE];
-	int res, size, size_total, err;
-
-	assert (info != NULL);
-	assert (slot_data != NULL);
-	assert (info->al_slot > 0);
-
-	res = lseek (info->al_fd, 
-		     (off_t) (ALOCK_SLOT_SIZE * info->al_slot), 
-		     SEEK_SET);
-	if (res == -1) return -1;
-
-	size_total = 0;
-	while (size_total < ALOCK_SLOT_SIZE) {
-		size = read (info->al_fd, 
-			     slotbuf + size_total, 
-			     ALOCK_SLOT_SIZE - size_total);
-		if (size == 0) return -1;
-		if (size < 0) {
-			err = errno;
-			if (err != EINTR && err != EAGAIN) return -1;
-		} else {
-			size_total += size;
-		}
-	}
-	
-	if (alock_read_iattr (slotbuf) != ALOCK_MAGIC) {
-		return -1;
-	}
-	slot_data->al_lock  = alock_read_iattr (slotbuf+8);
-	slot_data->al_stamp = alock_read_iattr (slotbuf+16);
-	slot_data->al_pid   = alock_read_iattr (slotbuf+24);
-
-	if (slot_data->al_appname) ber_memfree (slot_data->al_appname);
-	slot_data->al_appname = ber_memcalloc (1, ALOCK_MAX_APPNAME);
-	if (slot_data->al_appname == NULL) {
-		return -1;
-	}
-	strncpy (slot_data->al_appname, (char *)slotbuf+32, ALOCK_MAX_APPNAME-1);
-	(slot_data->al_appname) [ALOCK_MAX_APPNAME-1] = '\0';
-
-	return 0;
-}
-
-static int
-alock_write_slot ( alock_info_t * info,
-		   alock_slot_t * slot_data )
-{
-	unsigned char slotbuf [ALOCK_SLOT_SIZE];
-	int res, size, size_total, err;
-
-	assert (info != NULL);
-	assert (slot_data != NULL);
-	assert (info->al_slot > 0);
-
-	(void) memset ((void *) slotbuf, 0, ALOCK_SLOT_SIZE);
-	
-	alock_write_iattr (slotbuf,    ALOCK_MAGIC);
-	assert (alock_read_iattr (slotbuf) == ALOCK_MAGIC);
-	alock_write_iattr (slotbuf+8,  slot_data->al_lock);
-	alock_write_iattr (slotbuf+16, slot_data->al_stamp);
-	alock_write_iattr (slotbuf+24, slot_data->al_pid);
-
-	if (slot_data->al_appname)
-		strncpy ((char *)slotbuf+32, slot_data->al_appname, ALOCK_MAX_APPNAME-1);
-	slotbuf[ALOCK_SLOT_SIZE-1] = '\0';
-
-	res = lseek (info->al_fd, 
-		     (off_t) (ALOCK_SLOT_SIZE * info->al_slot),
-		     SEEK_SET);
-	if (res == -1) return -1;
-
-	size_total = 0;
-	while (size_total < ALOCK_SLOT_SIZE) {
-		size = write (info->al_fd, 
-			      slotbuf + size_total, 
-			      ALOCK_SLOT_SIZE - size_total);
-		if (size == 0) return -1;
-		if (size < 0) {
-			err = errno;
-			if (err != EINTR && err != EAGAIN) return -1;
-		} else {
-			size_total += size;
-		}
-	}
-	
-	return 0;
-}
-
-static int
-alock_query_slot ( alock_info_t * info )
-{
-	int res, nosave;
-	alock_slot_t slot_data;
-
-	assert (info != NULL);
-	assert (info->al_slot > 0);
-	
-	(void) memset ((void *) &slot_data, 0, sizeof (alock_slot_t));
-	alock_read_slot (info, &slot_data);
-
-	if (slot_data.al_appname != NULL) ber_memfree (slot_data.al_appname);
-	slot_data.al_appname = NULL;
-
-	nosave = slot_data.al_lock & ALOCK_NOSAVE;
-
-	if ((slot_data.al_lock & ALOCK_SMASK) == ALOCK_UNLOCKED)
-		return slot_data.al_lock;
-
-	res = alock_test_lock (info->al_fd, info->al_slot);
-	if (res < 0) return -1;
-	if (res > 0) {
-		if ((slot_data.al_lock & ALOCK_SMASK) == ALOCK_UNIQUE) {
-			return slot_data.al_lock;
-		} else {
-			return ALOCK_LOCKED | nosave;
-		}
-	}
-	
-	return ALOCK_DIRTY | nosave;
-}
-
-int 
-alock_open ( alock_info_t * info,
-	     const char * appname,
-	     const char * envdir,
-	     int locktype )
-{
-	struct stat statbuf;
-	alock_info_t scan_info;
-	alock_slot_t slot_data;
-	char * filename;
-	int res, max_slot;
-	int dirty_count, live_count, nosave;
-	char *ptr;
-
-	assert (info != NULL);
-	assert (appname != NULL);
-	assert (envdir != NULL);
-	assert ((locktype & ALOCK_SMASK) >= 1 && (locktype & ALOCK_SMASK) <= 2);
-
-	slot_data.al_lock = locktype;
-	slot_data.al_stamp = time(NULL);
-	slot_data.al_pid = getpid();
-	slot_data.al_appname = ber_memcalloc (1, ALOCK_MAX_APPNAME);
-	if (slot_data.al_appname == NULL) {
-		return ALOCK_UNSTABLE;
-	}
-	strncpy (slot_data.al_appname, appname, ALOCK_MAX_APPNAME-1);
-	slot_data.al_appname [ALOCK_MAX_APPNAME-1] = '\0';
-
-	filename = ber_memcalloc (1, strlen (envdir) + strlen ("/alock") + 1);
-	if (filename == NULL ) {
-		ber_memfree (slot_data.al_appname);
-		return ALOCK_UNSTABLE;
-	}
-	ptr = lutil_strcopy(filename, envdir);
-	lutil_strcopy(ptr, "/alock");
-#ifdef _WIN32
-	{ HANDLE handle = CreateFile (filename, GENERIC_READ|GENERIC_WRITE,
-		FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,
-		FILE_ATTRIBUTE_NORMAL, NULL);
-		info->al_fd = _open_osfhandle (handle, 0);
-	}
-#else
-	info->al_fd = open (filename, O_CREAT|O_RDWR, 0666);
-#endif
-	ber_memfree (filename);
-	if (info->al_fd < 0) {
-		ber_memfree (slot_data.al_appname);
-		return ALOCK_UNSTABLE;
-	}
-	info->al_slot = 0;
-
-	res = alock_grab_lock (info->al_fd, 0);
-	if (res == -1) { 
-		close (info->al_fd);
-		ber_memfree (slot_data.al_appname);
-		return ALOCK_UNSTABLE;
-	}
-
-	res = fstat (info->al_fd, &statbuf);
-	if (res == -1) { 
-		close (info->al_fd);
-		ber_memfree (slot_data.al_appname);
-		return ALOCK_UNSTABLE;
-	}
-
-	max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE;
-	dirty_count = 0;
-	live_count = 0;
-	nosave = 0;
-	scan_info.al_fd = info->al_fd;
-	for (scan_info.al_slot = 1; 
-	     scan_info.al_slot < max_slot;
-	     ++ scan_info.al_slot) {
-		if (scan_info.al_slot != info->al_slot) {
-			res = alock_query_slot (&scan_info);
-
-			if (res & ALOCK_NOSAVE) {
-				nosave = ALOCK_NOSAVE;
-				res ^= ALOCK_NOSAVE;
-			}
-			if (res == ALOCK_UNLOCKED
-			    && info->al_slot == 0) {
-				info->al_slot = scan_info.al_slot;
-
-			} else if (res == ALOCK_LOCKED) {
-				++live_count;
-
-			} else if (res == ALOCK_UNIQUE
-				&& (( locktype & ALOCK_SMASK ) == ALOCK_UNIQUE
-				|| nosave )) {
-				close (info->al_fd);
-				ber_memfree (slot_data.al_appname);
-				return ALOCK_BUSY;
-
-			} else if (res == ALOCK_DIRTY) {
-				++dirty_count;
-
-			} else if (res == -1) {
-				close (info->al_fd);
-				ber_memfree (slot_data.al_appname);
-				return ALOCK_UNSTABLE;
-
-			}
-		}
-	}
-
-	if (dirty_count && live_count) {
-		close (info->al_fd);
-		ber_memfree (slot_data.al_appname);
-		return ALOCK_UNSTABLE;
-	}
-	
-	if (info->al_slot == 0) info->al_slot = max_slot + 1;
-	res = alock_grab_lock (info->al_fd,
-			       info->al_slot);
-	if (res == -1) { 
-		close (info->al_fd);
-		ber_memfree (slot_data.al_appname);
-		return ALOCK_UNSTABLE;
-	}
-	res = alock_write_slot (info, &slot_data);
-	ber_memfree (slot_data.al_appname);
-	if (res == -1) { 
-		close (info->al_fd);
-		return ALOCK_UNSTABLE;
-	}
-	alock_share_lock (info->al_fd, info->al_slot);
-
-	res = alock_release_lock (info->al_fd, 0);
-	if (res == -1) { 
-		close (info->al_fd);
-		return ALOCK_UNSTABLE;
-	}
-	
-	if (dirty_count) return ALOCK_RECOVER | nosave;
-	return ALOCK_CLEAN | nosave;
-}
-
-int 
-alock_scan ( alock_info_t * info )
-{
-	struct stat statbuf;
-	alock_info_t scan_info;
-	int res, max_slot;
-	int dirty_count, live_count, nosave;
-
-	assert (info != NULL);
-
-	scan_info.al_fd = info->al_fd;
-
-	res = alock_grab_lock (info->al_fd, 0);
-	if (res == -1) {
-		close (info->al_fd);
-		return ALOCK_UNSTABLE;
-	}
-
-	res = fstat (info->al_fd, &statbuf);
-	if (res == -1) {
-		close (info->al_fd);
-		return ALOCK_UNSTABLE;
-	}
-
-	max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE;
-	dirty_count = 0;
-	live_count = 0;
-	nosave = 0;
-	for (scan_info.al_slot = 1; 
-	     scan_info.al_slot < max_slot;
-	     ++ scan_info.al_slot) {
-		if (scan_info.al_slot != info->al_slot) {
-			res = alock_query_slot (&scan_info);
-
-			if (res & ALOCK_NOSAVE) {
-				nosave = ALOCK_NOSAVE;
-				res ^= ALOCK_NOSAVE;
-			}
-
-			if (res == ALOCK_LOCKED) {
-				++live_count;
-				
-			} else if (res == ALOCK_DIRTY) {
-				++dirty_count;
-
-			} else if (res == -1) {
-				close (info->al_fd);
-				return ALOCK_UNSTABLE;
-
-			}
-		}
-	}
-
-	res = alock_release_lock (info->al_fd, 0);
-	if (res == -1) {
-		close (info->al_fd);
-		return ALOCK_UNSTABLE;
-	}
-
-	if (dirty_count) {
-		if (live_count) {
-			close (info->al_fd);
-			return ALOCK_UNSTABLE;
-		} else {
-			return ALOCK_RECOVER | nosave;
-		}
-	}
-	
-	return ALOCK_CLEAN | nosave;
-}
-
-int
-alock_close ( alock_info_t * info, int nosave )
-{
-	alock_slot_t slot_data;
-	int res;
-
-	if ( !info->al_slot )
-		return ALOCK_CLEAN;
-
-	(void) memset ((void *) &slot_data, 0, sizeof(alock_slot_t));
-
-	res = alock_grab_lock (info->al_fd, 0);
-	if (res == -1) {
-fail:
-		/* Windows doesn't clean up locks immediately when a process exits.
-		 * Make sure we release our locks, to prevent stale locks from
-		 * hanging around.
-		 */
-		alock_release_lock (info->al_fd, 0);
-		close (info->al_fd);
-		return ALOCK_UNSTABLE;
-	}
-
-	/* mark our slot as clean */
-	res = alock_read_slot (info, &slot_data);
-	if (res == -1) {
-		if (slot_data.al_appname != NULL) 
-			ber_memfree (slot_data.al_appname);
-		goto fail;
-	}
-	slot_data.al_lock = ALOCK_UNLOCKED;
-	if ( nosave )
-		slot_data.al_lock |= ALOCK_NOSAVE;
-	/* since we have slot 0 locked, we don't need our slot lock */
-	res = alock_release_lock (info->al_fd, info->al_slot);
-	if (res == -1) {
-		goto fail;
-	}
-	res = alock_write_slot (info, &slot_data);
-	if (res == -1) {
-		if (slot_data.al_appname != NULL) 
-			ber_memfree (slot_data.al_appname);
-		goto fail;
-	}
-	if (slot_data.al_appname != NULL) {
-		ber_memfree (slot_data.al_appname);
-		slot_data.al_appname = NULL;
-	}
-
-	res = alock_release_lock (info->al_fd, 0);
-	if (res == -1) {
-		close (info->al_fd);
-		return ALOCK_UNSTABLE;
-	}
-
-	res = close (info->al_fd);
-	if (res == -1) return ALOCK_UNSTABLE;
-	
-	return ALOCK_CLEAN;
-}
-
-int 
-alock_recover ( alock_info_t * info )
-{
-	struct stat statbuf;
-	alock_slot_t slot_data;
-	alock_info_t scan_info;
-	int res, max_slot;
-
-	assert (info != NULL);
-
-	scan_info.al_fd = info->al_fd;
-
-	(void) memset ((void *) &slot_data, 0, sizeof(alock_slot_t));
-
-	res = alock_grab_lock (info->al_fd, 0);
-	if (res == -1) {
-		goto fail;
-	}
-
-	res = fstat (info->al_fd, &statbuf);
-	if (res == -1) {
-		goto fail;
-	}
-
-	max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE;
-	for (scan_info.al_slot = 1; 
-	     scan_info.al_slot < max_slot;
-	     ++ scan_info.al_slot) {
-		if (scan_info.al_slot != info->al_slot) {
-			res = alock_query_slot (&scan_info) & ~ALOCK_NOSAVE;
-
-			if (res == ALOCK_LOCKED
-			    || res == ALOCK_UNIQUE) {
-				/* recovery attempt on an active db? */
-				goto fail;
-				
-			} else if (res == ALOCK_DIRTY) {
-				/* mark it clean */
-				res = alock_read_slot (&scan_info, &slot_data);
-				if (res == -1) {
-					goto fail;
-				}
-				slot_data.al_lock = ALOCK_UNLOCKED;
-				res = alock_write_slot (&scan_info, &slot_data);
-				if (res == -1) {
-					if (slot_data.al_appname != NULL) 
-						ber_memfree (slot_data.al_appname);
-					goto fail;
-				}
-				if (slot_data.al_appname != NULL) {
-					ber_memfree (slot_data.al_appname);
-					slot_data.al_appname = NULL;
-				}
-				
-			} else if (res == -1) {
-				goto fail;
-
-			}
-		}
-	}
-
-	res = alock_release_lock (info->al_fd, 0);
-	if (res == -1) {
-		close (info->al_fd);
-		return ALOCK_UNSTABLE;
-	}
-
-	return ALOCK_CLEAN;
-
-fail:
-	alock_release_lock (info->al_fd, 0);
-	close (info->al_fd);
-	return ALOCK_UNSTABLE;
-}
-
-#endif /* SLAPD_BDB || SLAPD_HDB */
diff --git a/servers/slapd/alock.h b/servers/slapd/alock.h
deleted file mode 100644
index 56f03d8..0000000
--- a/servers/slapd/alock.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/* alock.h - access lock header */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2005-2020 The OpenLDAP Foundation.
- * Portions Copyright 2004-2005 Symas Corporation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was initially developed by Emily Backes at Symas
- * Corporation for inclusion in OpenLDAP Software.
- */
-
-#ifndef _ALOCK_H_
-#define _ALOCK_H_
-
-#include "portable.h"
-#include <ac/time.h>
-#include <ac/unistd.h>
-
-/* environment states (all the slots together) */
-#define ALOCK_CLEAN		(0)
-#define ALOCK_RECOVER	(1)
-#define ALOCK_BUSY		(2)
-#define ALOCK_UNSTABLE	(3)
-
-/* lock user types and states */
-#define ALOCK_UNLOCKED	(0)
-#define ALOCK_LOCKED	(1)
-#define ALOCK_UNIQUE	(2)
-#define ALOCK_DIRTY		(3)
-
-#define ALOCK_SMASK		3
-
-/* lock/state where recovery is not available */
-#define	ALOCK_NOSAVE	4
-
-/* constants */
-#define ALOCK_SLOT_SIZE		(1024)
-#define ALOCK_SLOT_IATTRS	(4)
-#define ALOCK_MAX_APPNAME	(ALOCK_SLOT_SIZE - 8 * ALOCK_SLOT_IATTRS)
-#define ALOCK_MAGIC			(0x12345678)
-
-LDAP_BEGIN_DECL
-
-typedef struct alock_info {
-	int al_fd;
-	int al_slot;
-} alock_info_t;
-
-typedef struct alock_slot {
-	unsigned int al_lock;
-	time_t al_stamp;
-	pid_t al_pid;
-	char * al_appname;
-} alock_slot_t;
-
-LDAP_SLAPD_F (int) alock_open LDAP_P(( alock_info_t * info, const char * appname,
-	const char * envdir, int locktype ));
-LDAP_SLAPD_F (int) alock_scan LDAP_P(( alock_info_t * info ));
-LDAP_SLAPD_F (int) alock_close LDAP_P(( alock_info_t * info, int nosave ));
-LDAP_SLAPD_F (int) alock_recover LDAP_P(( alock_info_t * info ));
-
-LDAP_END_DECL
-
-#endif
diff --git a/servers/slapd/back-bdb/Makefile.in b/servers/slapd/back-bdb/Makefile.in
deleted file mode 100644
index 8529202..0000000
--- a/servers/slapd/back-bdb/Makefile.in
+++ /dev/null
@@ -1,53 +0,0 @@
-# Makefile.in for back-bdb
-# $OpenLDAP$
-## This work is part of OpenLDAP Software <http://www.openldap.org/>.
-##
-## Copyright 1998-2020 The OpenLDAP Foundation.
-## All rights reserved.
-##
-## Redistribution and use in source and binary forms, with or without
-## modification, are permitted only as authorized by the OpenLDAP
-## Public License.
-##
-## A copy of this license is available in the file LICENSE in the
-## top-level directory of the distribution or, alternatively, at
-## <http://www.OpenLDAP.org/license.html>.
-
-SRCS = init.c tools.c config.c \
-	add.c bind.c compare.c delete.c modify.c modrdn.c search.c \
-	extended.c referral.c operational.c \
-	attr.c index.c key.c dbcache.c filterindex.c \
-	dn2entry.c dn2id.c error.c id2entry.c idl.c \
-	nextid.c cache.c trans.c monitor.c
-
-OBJS = init.lo tools.lo config.lo \
-	add.lo bind.lo compare.lo delete.lo modify.lo modrdn.lo search.lo \
-	extended.lo referral.lo operational.lo \
-	attr.lo index.lo key.lo dbcache.lo filterindex.lo \
-	dn2entry.lo dn2id.lo error.lo id2entry.lo idl.lo \
-	nextid.lo cache.lo trans.lo monitor.lo
-
-LDAP_INCDIR= ../../../include       
-LDAP_LIBDIR= ../../../libraries
-
-BUILD_OPT = "--enable-bdb"
-BUILD_MOD = @BUILD_BDB@
-
-mod_DEFS = -DSLAPD_IMPORT
-MOD_DEFS = $(@BUILD_BDB@_DEFS)
-MOD_LIBS = $(BDB_LIBS)
-
-shared_LDAP_LIBS = $(LDAP_LIBLDAP_R_LA) $(LDAP_LIBLBER_LA)
-NT_LINK_LIBS = -L.. -lslapd $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
-UNIX_LINK_LIBS = $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
-
-LIBBASE = back_bdb
-
-XINCPATH = -I.. -I$(srcdir)/..
-XDEFS = $(MODULES_CPPFLAGS)
-
-all-local-lib:	../.backend
-
-../.backend: lib$(LIBBASE).a
-	@touch $@
-
diff --git a/servers/slapd/back-bdb/add.c b/servers/slapd/back-bdb/add.c
deleted file mode 100644
index d842b55..0000000
--- a/servers/slapd/back-bdb/add.c
+++ /dev/null
@@ -1,547 +0,0 @@
-/* add.c - ldap BerkeleyDB back-end add routine */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "back-bdb.h"
-
-int
-bdb_add(Operation *op, SlapReply *rs )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	struct berval	pdn;
-	Entry		*p = NULL, *oe = op->ora_e;
-	EntryInfo	*ei;
-	char textbuf[SLAP_TEXT_BUFLEN];
-	size_t textlen = sizeof textbuf;
-	AttributeDescription *children = slap_schema.si_ad_children;
-	AttributeDescription *entry = slap_schema.si_ad_entry;
-	DB_TXN		*ltid = NULL, *lt2;
-	ID eid = NOID;
-	struct bdb_op_info opinfo = {{{ 0 }}};
-	int subentry;
-	DB_LOCK		lock;
-
-	int		num_retries = 0;
-	int		success;
-
-	LDAPControl **postread_ctrl = NULL;
-	LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
-	int num_ctrls = 0;
-
-#ifdef LDAP_X_TXN
-	int settle = 0;
-#endif
-
-	Debug(LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(bdb_add) ": %s\n",
-		op->ora_e->e_name.bv_val, 0, 0);
-
-#ifdef LDAP_X_TXN
-	if( op->o_txnSpec ) {
-		/* acquire connection lock */
-		ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
-		if( op->o_conn->c_txn == CONN_TXN_INACTIVE ) {
-			rs->sr_text = "invalid transaction identifier";
-			rs->sr_err = LDAP_X_TXN_ID_INVALID;
-			goto txnReturn;
-		} else if( op->o_conn->c_txn == CONN_TXN_SETTLE ) {
-			settle=1;
-			goto txnReturn;
-		}
-
-		if( op->o_conn->c_txn_backend == NULL ) {
-			op->o_conn->c_txn_backend = op->o_bd;
-
-		} else if( op->o_conn->c_txn_backend != op->o_bd ) {
-			rs->sr_text = "transaction cannot span multiple database contexts";
-			rs->sr_err = LDAP_AFFECTS_MULTIPLE_DSAS;
-			goto txnReturn;
-		}
-
-		/* insert operation into transaction */
-
-		rs->sr_text = "transaction specified";
-		rs->sr_err = LDAP_X_TXN_SPECIFY_OKAY;
-
-txnReturn:
-		/* release connection lock */
-		ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
-
-		if( !settle ) {
-			send_ldap_result( op, rs );
-			return rs->sr_err;
-		}
-	}
-#endif
-
-	ctrls[num_ctrls] = 0;
-
-	/* check entry's schema */
-	rs->sr_err = entry_schema_check( op, op->ora_e, NULL,
-		get_relax(op), 1, NULL, &rs->sr_text, textbuf, textlen );
-	if ( rs->sr_err != LDAP_SUCCESS ) {
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_add) ": entry failed schema check: "
-			"%s (%d)\n", rs->sr_text, rs->sr_err, 0 );
-		goto return_results;
-	}
-
-	/* add opattrs to shadow as well, only missing attrs will actually
-	 * be added; helps compatibility with older OL versions */
-	rs->sr_err = slap_add_opattrs( op, &rs->sr_text, textbuf, textlen, 1 );
-	if ( rs->sr_err != LDAP_SUCCESS ) {
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_add) ": entry failed op attrs add: "
-			"%s (%d)\n", rs->sr_text, rs->sr_err, 0 );
-		goto return_results;
-	}
-
-	if ( get_assert( op ) &&
-		( test_filter( op, op->ora_e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
-	{
-		rs->sr_err = LDAP_ASSERTION_FAILED;
-		goto return_results;
-	}
-
-	subentry = is_entry_subentry( op->ora_e );
-
-	if( 0 ) {
-retry:	/* transaction retry */
-		if( p ) {
-			/* free parent and reader lock */
-			if ( p != (Entry *)&slap_entry_root ) {
-				bdb_unlocked_cache_return_entry_r( bdb, p );
-			}
-			p = NULL;
-		}
-		rs->sr_err = TXN_ABORT( ltid );
-		ltid = NULL;
-		LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
-		opinfo.boi_oe.oe_key = NULL;
-		op->o_do_not_cache = opinfo.boi_acl_cache;
-		if( rs->sr_err != 0 ) {
-			rs->sr_err = LDAP_OTHER;
-			rs->sr_text = "internal error";
-			goto return_results;
-		}
-		if ( op->o_abandon ) {
-			rs->sr_err = SLAPD_ABANDON;
-			goto return_results;
-		}
-		bdb_trans_backoff( ++num_retries );
-	}
-
-	/* begin transaction */
-	rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, NULL, &ltid, 
-		bdb->bi_db_opflags );
-	rs->sr_text = NULL;
-	if( rs->sr_err != 0 ) {
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_add) ": txn_begin failed: %s (%d)\n",
-			db_strerror(rs->sr_err), rs->sr_err, 0 );
-		rs->sr_err = LDAP_OTHER;
-		rs->sr_text = "internal error";
-		goto return_results;
-	}
-	Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_add) ": txn1 id: %x\n",
-		ltid->id(ltid), 0, 0 );
-
-	opinfo.boi_oe.oe_key = bdb;
-	opinfo.boi_txn = ltid;
-	opinfo.boi_err = 0;
-	opinfo.boi_acl_cache = op->o_do_not_cache;
-	LDAP_SLIST_INSERT_HEAD( &op->o_extra, &opinfo.boi_oe, oe_next );
-
-	/*
-	 * Get the parent dn and see if the corresponding entry exists.
-	 */
-	if ( be_issuffix( op->o_bd, &op->ora_e->e_nname ) ) {
-		pdn = slap_empty_bv;
-	} else {
-		dnParent( &op->ora_e->e_nname, &pdn );
-	}
-
-	/* get entry or parent */
-	rs->sr_err = bdb_dn2entry( op, ltid, &op->ora_e->e_nname, &ei,
-		1, &lock );
-	switch( rs->sr_err ) {
-	case 0:
-		rs->sr_err = LDAP_ALREADY_EXISTS;
-		goto return_results;
-	case DB_NOTFOUND:
-		break;
-	case DB_LOCK_DEADLOCK:
-	case DB_LOCK_NOTGRANTED:
-		goto retry;
-	case LDAP_BUSY:
-		rs->sr_text = "ldap server busy";
-		goto return_results;
-	default:
-		rs->sr_err = LDAP_OTHER;
-		rs->sr_text = "internal error";
-		goto return_results;
-	}
-
-	p = ei->bei_e;
-	if ( !p )
-		p = (Entry *)&slap_entry_root;
-
-	if ( !bvmatch( &pdn, &p->e_nname ) ) {
-		rs->sr_matched = ber_strdup_x( p->e_name.bv_val,
-			op->o_tmpmemctx );
-		rs->sr_ref = is_entry_referral( p )
-			? get_entry_referrals( op, p )
-			: NULL;
-		if ( p != (Entry *)&slap_entry_root )
-			bdb_unlocked_cache_return_entry_r( bdb, p );
-		p = NULL;
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_add) ": parent "
-			"does not exist\n", 0, 0, 0 );
-
-		rs->sr_err = LDAP_REFERRAL;
-		rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
-		goto return_results;
-	}
-
-	rs->sr_err = access_allowed( op, p,
-		children, NULL, ACL_WADD, NULL );
-
-	if ( ! rs->sr_err ) {
-		switch( opinfo.boi_err ) {
-		case DB_LOCK_DEADLOCK:
-		case DB_LOCK_NOTGRANTED:
-			goto retry;
-		}
-
-		if ( p != (Entry *)&slap_entry_root )
-			bdb_unlocked_cache_return_entry_r( bdb, p );
-		p = NULL;
-
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_add) ": no write access to parent\n",
-			0, 0, 0 );
-		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
-		rs->sr_text = "no write access to parent";
-		goto return_results;;
-	}
-
-	if ( p != (Entry *)&slap_entry_root ) {
-		if ( is_entry_subentry( p ) ) {
-			bdb_unlocked_cache_return_entry_r( bdb, p );
-			p = NULL;
-			/* parent is a subentry, don't allow add */
-			Debug( LDAP_DEBUG_TRACE,
-				LDAP_XSTRING(bdb_add) ": parent is subentry\n",
-				0, 0, 0 );
-			rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION;
-			rs->sr_text = "parent is a subentry";
-			goto return_results;;
-		}
-
-		if ( is_entry_alias( p ) ) {
-			bdb_unlocked_cache_return_entry_r( bdb, p );
-			p = NULL;
-			/* parent is an alias, don't allow add */
-			Debug( LDAP_DEBUG_TRACE,
-				LDAP_XSTRING(bdb_add) ": parent is alias\n",
-				0, 0, 0 );
-			rs->sr_err = LDAP_ALIAS_PROBLEM;
-			rs->sr_text = "parent is an alias";
-			goto return_results;;
-		}
-
-		if ( is_entry_referral( p ) ) {
-			/* parent is a referral, don't allow add */
-			rs->sr_matched = ber_strdup_x( p->e_name.bv_val,
-				op->o_tmpmemctx );
-			rs->sr_ref = get_entry_referrals( op, p );
-			bdb_unlocked_cache_return_entry_r( bdb, p );
-			p = NULL;
-			Debug( LDAP_DEBUG_TRACE,
-				LDAP_XSTRING(bdb_add) ": parent is referral\n",
-				0, 0, 0 );
-
-			rs->sr_err = LDAP_REFERRAL;
-			rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
-			goto return_results;
-		}
-
-	}
-
-	if ( subentry ) {
-		/* FIXME: */
-		/* parent must be an administrative point of the required kind */
-	}
-
-	/* free parent and reader lock */
-	if ( p != (Entry *)&slap_entry_root ) {
-		if ( p->e_nname.bv_len ) {
-			struct berval ppdn;
-
-			/* ITS#5326: use parent's DN if differs from provided one */
-			dnParent( &op->ora_e->e_name, &ppdn );
-			if ( !dn_match( &p->e_name, &ppdn ) ) {
-				struct berval rdn;
-				struct berval newdn;
-
-				dnRdn( &op->ora_e->e_name, &rdn );
-
-				build_new_dn( &newdn, &p->e_name, &rdn, NULL ); 
-				if ( op->ora_e->e_name.bv_val != op->o_req_dn.bv_val )
-					ber_memfree( op->ora_e->e_name.bv_val );
-				op->ora_e->e_name = newdn;
-
-				/* FIXME: should check whether
-				 * dnNormalize(newdn) == e->e_nname ... */
-			}
-		}
-
-		bdb_unlocked_cache_return_entry_r( bdb, p );
-	}
-	p = NULL;
-
-	rs->sr_err = access_allowed( op, op->ora_e,
-		entry, NULL, ACL_WADD, NULL );
-
-	if ( ! rs->sr_err ) {
-		switch( opinfo.boi_err ) {
-		case DB_LOCK_DEADLOCK:
-		case DB_LOCK_NOTGRANTED:
-			goto retry;
-		}
-
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_add) ": no write access to entry\n",
-			0, 0, 0 );
-		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
-		rs->sr_text = "no write access to entry";
-		goto return_results;;
-	}
-
-	/* 
-	 * Check ACL for attribute write access
-	 */
-	if (!acl_check_modlist(op, oe, op->ora_modlist)) {
-		switch( opinfo.boi_err ) {
-		case DB_LOCK_DEADLOCK:
-		case DB_LOCK_NOTGRANTED:
-			goto retry;
-		}
-
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_add) ": no write access to attribute\n",
-			0, 0, 0 );
-		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
-		rs->sr_text = "no write access to attribute";
-		goto return_results;;
-	}
-
-	if ( eid == NOID ) {
-		rs->sr_err = bdb_next_id( op->o_bd, &eid );
-		if( rs->sr_err != 0 ) {
-			Debug( LDAP_DEBUG_TRACE,
-				LDAP_XSTRING(bdb_add) ": next_id failed (%d)\n",
-				rs->sr_err, 0, 0 );
-			rs->sr_err = LDAP_OTHER;
-			rs->sr_text = "internal error";
-			goto return_results;
-		}
-		op->ora_e->e_id = eid;
-	}
-
-	/* nested transaction */
-	rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, &lt2, 
-		bdb->bi_db_opflags );
-	rs->sr_text = NULL;
-	if( rs->sr_err != 0 ) {
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_add) ": txn_begin(2) failed: "
-			"%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
-		rs->sr_err = LDAP_OTHER;
-		rs->sr_text = "internal error";
-		goto return_results;
-	}
-	Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_add) ": txn2 id: %x\n",
-		lt2->id(lt2), 0, 0 );
-
-	/* dn2id index */
-	rs->sr_err = bdb_dn2id_add( op, lt2, ei, op->ora_e );
-	if ( rs->sr_err != 0 ) {
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_add) ": dn2id_add failed: %s (%d)\n",
-			db_strerror(rs->sr_err), rs->sr_err, 0 );
-
-		switch( rs->sr_err ) {
-		case DB_LOCK_DEADLOCK:
-		case DB_LOCK_NOTGRANTED:
-			goto retry;
-		case DB_KEYEXIST:
-			rs->sr_err = LDAP_ALREADY_EXISTS;
-			break;
-		default:
-			rs->sr_err = LDAP_OTHER;
-		}
-		goto return_results;
-	}
-
-	/* attribute indexes */
-	rs->sr_err = bdb_index_entry_add( op, lt2, op->ora_e );
-	if ( rs->sr_err != LDAP_SUCCESS ) {
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_add) ": index_entry_add failed\n",
-			0, 0, 0 );
-		switch( rs->sr_err ) {
-		case DB_LOCK_DEADLOCK:
-		case DB_LOCK_NOTGRANTED:
-			goto retry;
-		default:
-			rs->sr_err = LDAP_OTHER;
-		}
-		rs->sr_text = "index generation failed";
-		goto return_results;
-	}
-
-	/* id2entry index */
-	rs->sr_err = bdb_id2entry_add( op->o_bd, lt2, op->ora_e );
-	if ( rs->sr_err != 0 ) {
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_add) ": id2entry_add failed\n",
-			0, 0, 0 );
-		switch( rs->sr_err ) {
-		case DB_LOCK_DEADLOCK:
-		case DB_LOCK_NOTGRANTED:
-			goto retry;
-		default:
-			rs->sr_err = LDAP_OTHER;
-		}
-		rs->sr_text = "entry store failed";
-		goto return_results;
-	}
-
-	if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
-		rs->sr_err = LDAP_OTHER;
-		rs->sr_text = "txn_commit(2) failed";
-		goto return_results;
-	}
-
-	/* post-read */
-	if( op->o_postread ) {
-		if( postread_ctrl == NULL ) {
-			postread_ctrl = &ctrls[num_ctrls++];
-			ctrls[num_ctrls] = NULL;
-		}
-		if ( slap_read_controls( op, rs, op->ora_e,
-			&slap_post_read_bv, postread_ctrl ) )
-		{
-			Debug( LDAP_DEBUG_TRACE,
-				"<=- " LDAP_XSTRING(bdb_add) ": post-read "
-				"failed!\n", 0, 0, 0 );
-			if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
-				/* FIXME: is it correct to abort
-				 * operation if control fails? */
-				goto return_results;
-			}
-		}
-	}
-
-	if ( op->o_noop ) {
-		if (( rs->sr_err=TXN_ABORT( ltid )) != 0 ) {
-			rs->sr_text = "txn_abort (no-op) failed";
-		} else {
-			rs->sr_err = LDAP_X_NO_OPERATION;
-			ltid = NULL;
-			goto return_results;
-		}
-
-	} else {
-		struct berval nrdn;
-
-		/* pick the RDN if not suffix; otherwise pick the entire DN */
-		if (pdn.bv_len) {
-			nrdn.bv_val = op->ora_e->e_nname.bv_val;
-			nrdn.bv_len = pdn.bv_val - op->ora_e->e_nname.bv_val - 1;
-		} else {
-			nrdn = op->ora_e->e_nname;
-		}
-
-		bdb_cache_add( bdb, ei, op->ora_e, &nrdn, ltid, &lock );
-
-		if(( rs->sr_err=TXN_COMMIT( ltid, 0 )) != 0 ) {
-			rs->sr_text = "txn_commit failed";
-		} else {
-			rs->sr_err = LDAP_SUCCESS;
-		}
-	}
-
-	ltid = NULL;
-	LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
-	opinfo.boi_oe.oe_key = NULL;
-
-	if ( rs->sr_err != LDAP_SUCCESS ) {
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_add) ": %s : %s (%d)\n",
-			rs->sr_text, db_strerror(rs->sr_err), rs->sr_err );
-		rs->sr_err = LDAP_OTHER;
-		goto return_results;
-	}
-
-	Debug(LDAP_DEBUG_TRACE,
-		LDAP_XSTRING(bdb_add) ": added%s id=%08lx dn=\"%s\"\n",
-		op->o_noop ? " (no-op)" : "",
-		op->ora_e->e_id, op->ora_e->e_dn );
-
-	rs->sr_text = NULL;
-	if( num_ctrls ) rs->sr_ctrls = ctrls;
-
-return_results:
-	success = rs->sr_err;
-	send_ldap_result( op, rs );
-
-	if( ltid != NULL ) {
-		TXN_ABORT( ltid );
-	}
-	if ( opinfo.boi_oe.oe_key ) {
-		LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
-	}
-
-	if( success == LDAP_SUCCESS ) {
-		/* We own the entry now, and it can be purged at will
-		 * Check to make sure it's the same entry we entered with.
-		 * Possibly a callback may have mucked with it, although
-		 * in general callbacks should treat the entry as read-only.
-		 */
-		bdb_cache_deref( oe->e_private );
-		if ( op->ora_e == oe )
-			op->ora_e = NULL;
-
-		if ( bdb->bi_txn_cp_kbyte ) {
-			TXN_CHECKPOINT( bdb->bi_dbenv,
-				bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
-		}
-	}
-
-	slap_graduate_commit_csn( op );
-
-	if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) {
-		slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
-		slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
-	}
-	return rs->sr_err;
-}
diff --git a/servers/slapd/back-bdb/attr.c b/servers/slapd/back-bdb/attr.c
deleted file mode 100644
index 5d9990d..0000000
--- a/servers/slapd/back-bdb/attr.c
+++ /dev/null
@@ -1,441 +0,0 @@
-/* attr.c - backend routines for dealing with attributes */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/socket.h>
-#include <ac/string.h>
-
-#include "slap.h"
-#include "back-bdb.h"
-#include "config.h"
-#include "lutil.h"
-
-/* Find the ad, return -1 if not found,
- * set point for insertion if ins is non-NULL
- */
-int
-bdb_attr_slot( struct bdb_info *bdb, AttributeDescription *ad, int *ins )
-{
-	unsigned base = 0, cursor = 0;
-	unsigned n = bdb->bi_nattrs;
-	int val = 0;
-	
-	while ( 0 < n ) {
-		unsigned pivot = n >> 1;
-		cursor = base + pivot;
-
-		val = SLAP_PTRCMP( ad, bdb->bi_attrs[cursor]->ai_desc );
-		if ( val < 0 ) {
-			n = pivot;
-		} else if ( val > 0 ) {
-			base = cursor + 1;
-			n -= pivot + 1;
-		} else {
-			return cursor;
-		}
-	}
-	if ( ins ) {
-		if ( val > 0 )
-			++cursor;
-		*ins = cursor;
-	}
-	return -1;
-}
-
-static int
-ainfo_insert( struct bdb_info *bdb, AttrInfo *a )
-{
-	int x;
-	int i = bdb_attr_slot( bdb, a->ai_desc, &x );
-
-	/* Is it a dup? */
-	if ( i >= 0 )
-		return -1;
-
-	bdb->bi_attrs = ch_realloc( bdb->bi_attrs, ( bdb->bi_nattrs+1 ) * 
-		sizeof( AttrInfo * ));
-	if ( x < bdb->bi_nattrs )
-		AC_MEMCPY( &bdb->bi_attrs[x+1], &bdb->bi_attrs[x],
-			( bdb->bi_nattrs - x ) * sizeof( AttrInfo *));
-	bdb->bi_attrs[x] = a;
-	bdb->bi_nattrs++;
-	return 0;
-}
-
-AttrInfo *
-bdb_attr_mask(
-	struct bdb_info	*bdb,
-	AttributeDescription *desc )
-{
-	int i = bdb_attr_slot( bdb, desc, NULL );
-	return i < 0 ? NULL : bdb->bi_attrs[i];
-}
-
-int
-bdb_attr_index_config(
-	struct bdb_info	*bdb,
-	const char		*fname,
-	int			lineno,
-	int			argc,
-	char		**argv,
-	struct		config_reply_s *c_reply)
-{
-	int rc = 0;
-	int	i;
-	slap_mask_t mask;
-	char **attrs;
-	char **indexes = NULL;
-
-	attrs = ldap_str2charray( argv[0], "," );
-
-	if( attrs == NULL ) {
-		fprintf( stderr, "%s: line %d: "
-			"no attributes specified: %s\n",
-			fname, lineno, argv[0] );
-		return LDAP_PARAM_ERROR;
-	}
-
-	if ( argc > 1 ) {
-		indexes = ldap_str2charray( argv[1], "," );
-
-		if( indexes == NULL ) {
-			fprintf( stderr, "%s: line %d: "
-				"no indexes specified: %s\n",
-				fname, lineno, argv[1] );
-			rc = LDAP_PARAM_ERROR;
-			goto done;
-		}
-	}
-
-	if( indexes == NULL ) {
-		mask = bdb->bi_defaultmask;
-
-	} else {
-		mask = 0;
-
-		for ( i = 0; indexes[i] != NULL; i++ ) {
-			slap_mask_t index;
-			rc = slap_str2index( indexes[i], &index );
-
-			if( rc != LDAP_SUCCESS ) {
-				if ( c_reply )
-				{
-					snprintf(c_reply->msg, sizeof(c_reply->msg),
-						"index type \"%s\" undefined", indexes[i] );
-
-					fprintf( stderr, "%s: line %d: %s\n",
-						fname, lineno, c_reply->msg );
-				}
-				rc = LDAP_PARAM_ERROR;
-				goto done;
-			}
-
-			mask |= index;
-		}
-	}
-
-	if( !mask ) {
-		if ( c_reply )
-		{
-			snprintf(c_reply->msg, sizeof(c_reply->msg),
-				"no indexes selected" );
-			fprintf( stderr, "%s: line %d: %s\n",
-				fname, lineno, c_reply->msg );
-		}
-		rc = LDAP_PARAM_ERROR;
-		goto done;
-	}
-
-	for ( i = 0; attrs[i] != NULL; i++ ) {
-		AttrInfo	*a;
-		AttributeDescription *ad;
-		const char *text;
-#ifdef LDAP_COMP_MATCH
-		ComponentReference* cr = NULL;
-		AttrInfo *a_cr = NULL;
-#endif
-
-		if( strcasecmp( attrs[i], "default" ) == 0 ) {
-			bdb->bi_defaultmask |= mask;
-			continue;
-		}
-
-#ifdef LDAP_COMP_MATCH
-		if ( is_component_reference( attrs[i] ) ) {
-			rc = extract_component_reference( attrs[i], &cr );
-			if ( rc != LDAP_SUCCESS ) {
-				if ( c_reply )
-				{
-					snprintf(c_reply->msg, sizeof(c_reply->msg),
-						"index component reference\"%s\" undefined",
-						attrs[i] );
-					fprintf( stderr, "%s: line %d: %s\n",
-						fname, lineno, c_reply->msg );
-				}
-				goto done;
-			}
-			cr->cr_indexmask = mask;
-			/*
-			 * After extracting a component reference
-			 * only the name of a attribute will be remaining
-			 */
-		} else {
-			cr = NULL;
-		}
-#endif
-		ad = NULL;
-		rc = slap_str2ad( attrs[i], &ad, &text );
-
-		if( rc != LDAP_SUCCESS ) {
-			if ( c_reply )
-			{
-				snprintf(c_reply->msg, sizeof(c_reply->msg),
-					"index attribute \"%s\" undefined",
-					attrs[i] );
-
-				fprintf( stderr, "%s: line %d: %s\n",
-					fname, lineno, c_reply->msg );
-			}
-			goto done;
-		}
-
-		if( ad == slap_schema.si_ad_entryDN || slap_ad_is_binary( ad ) ) {
-			if (c_reply) {
-				snprintf(c_reply->msg, sizeof(c_reply->msg),
-					"index of attribute \"%s\" disallowed", attrs[i] );
-				fprintf( stderr, "%s: line %d: %s\n",
-					fname, lineno, c_reply->msg );
-			}
-			rc = LDAP_UNWILLING_TO_PERFORM;
-			goto done;
-		}
-
-		if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) && !(
-			ad->ad_type->sat_approx
-				&& ad->ad_type->sat_approx->smr_indexer
-				&& ad->ad_type->sat_approx->smr_filter ) )
-		{
-			if (c_reply) {
-				snprintf(c_reply->msg, sizeof(c_reply->msg),
-					"approx index of attribute \"%s\" disallowed", attrs[i] );
-				fprintf( stderr, "%s: line %d: %s\n",
-					fname, lineno, c_reply->msg );
-			}
-			rc = LDAP_INAPPROPRIATE_MATCHING;
-			goto done;
-		}
-
-		if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) && !(
-			ad->ad_type->sat_equality
-				&& ad->ad_type->sat_equality->smr_indexer
-				&& ad->ad_type->sat_equality->smr_filter ) )
-		{
-			if (c_reply) {
-				snprintf(c_reply->msg, sizeof(c_reply->msg),
-					"equality index of attribute \"%s\" disallowed", attrs[i] );
-				fprintf( stderr, "%s: line %d: %s\n",
-					fname, lineno, c_reply->msg );
-			}
-			rc = LDAP_INAPPROPRIATE_MATCHING;
-			goto done;
-		}
-
-		if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) && !(
-			ad->ad_type->sat_substr
-				&& ad->ad_type->sat_substr->smr_indexer
-				&& ad->ad_type->sat_substr->smr_filter ) )
-		{
-			if (c_reply) {
-				snprintf(c_reply->msg, sizeof(c_reply->msg),
-					"substr index of attribute \"%s\" disallowed", attrs[i] );
-				fprintf( stderr, "%s: line %d: %s\n",
-					fname, lineno, c_reply->msg );
-			}
-			rc = LDAP_INAPPROPRIATE_MATCHING;
-			goto done;
-		}
-
-		Debug( LDAP_DEBUG_CONFIG, "index %s 0x%04lx\n",
-			ad->ad_cname.bv_val, mask, 0 ); 
-
-		a = (AttrInfo *) ch_malloc( sizeof(AttrInfo) );
-
-#ifdef LDAP_COMP_MATCH
-		a->ai_cr = NULL;
-#endif
-		a->ai_desc = ad;
-
-		if ( bdb->bi_flags & BDB_IS_OPEN ) {
-			a->ai_indexmask = 0;
-			a->ai_newmask = mask;
-		} else {
-			a->ai_indexmask = mask;
-			a->ai_newmask = 0;
-		}
-
-#ifdef LDAP_COMP_MATCH
-		if ( cr ) {
-			a_cr = bdb_attr_mask( bdb, ad );
-			if ( a_cr ) {
-				/*
-				 * AttrInfo is already in AVL
-				 * just add the extracted component reference
-				 * in the AttrInfo
-				 */
-				rc = insert_component_reference( cr, &a_cr->ai_cr );
-				if ( rc != LDAP_SUCCESS) {
-					fprintf( stderr, " error during inserting component reference in %s ", attrs[i]);
-					rc = LDAP_PARAM_ERROR;
-					goto done;
-				}
-				continue;
-			} else {
-				rc = insert_component_reference( cr, &a->ai_cr );
-				if ( rc != LDAP_SUCCESS) {
-					fprintf( stderr, " error during inserting component reference in %s ", attrs[i]);
-					rc = LDAP_PARAM_ERROR;
-					goto done;
-				}
-			}
-		}
-#endif
-		rc = ainfo_insert( bdb, a );
-		if( rc ) {
-			if ( bdb->bi_flags & BDB_IS_OPEN ) {
-				AttrInfo *b = bdb_attr_mask( bdb, ad );
-				/* If there is already an index defined for this attribute
-				 * it must be replaced. Otherwise we end up with multiple 
-				 * olcIndex values for the same attribute */
-				if ( b->ai_indexmask & BDB_INDEX_DELETING ) {
-					/* If we were editing this attr, reset it */
-					b->ai_indexmask &= ~BDB_INDEX_DELETING;
-					/* If this is leftover from a previous add, commit it */
-					if ( b->ai_newmask )
-						b->ai_indexmask = b->ai_newmask;
-					b->ai_newmask = a->ai_newmask;
-					ch_free( a );
-					rc = 0;
-					continue;
-				}
-			}
-			if (c_reply) {
-				snprintf(c_reply->msg, sizeof(c_reply->msg),
-					"duplicate index definition for attr \"%s\"",
-					attrs[i] );
-				fprintf( stderr, "%s: line %d: %s\n",
-					fname, lineno, c_reply->msg );
-			}
-
-			rc = LDAP_PARAM_ERROR;
-			goto done;
-		}
-	}
-
-done:
-	ldap_charray_free( attrs );
-	if ( indexes != NULL ) ldap_charray_free( indexes );
-
-	return rc;
-}
-
-static int
-bdb_attr_index_unparser( void *v1, void *v2 )
-{
-	AttrInfo *ai = v1;
-	BerVarray *bva = v2;
-	struct berval bv;
-	char *ptr;
-
-	slap_index2bvlen( ai->ai_indexmask, &bv );
-	if ( bv.bv_len ) {
-		bv.bv_len += ai->ai_desc->ad_cname.bv_len + 1;
-		ptr = ch_malloc( bv.bv_len+1 );
-		bv.bv_val = lutil_strcopy( ptr, ai->ai_desc->ad_cname.bv_val );
-		*bv.bv_val++ = ' ';
-		slap_index2bv( ai->ai_indexmask, &bv );
-		bv.bv_val = ptr;
-		ber_bvarray_add( bva, &bv );
-	}
-	return 0;
-}
-
-static AttributeDescription addef = { NULL, NULL, BER_BVC("default") };
-static AttrInfo aidef = { &addef };
-
-void
-bdb_attr_index_unparse( struct bdb_info *bdb, BerVarray *bva )
-{
-	int i;
-
-	if ( bdb->bi_defaultmask ) {
-		aidef.ai_indexmask = bdb->bi_defaultmask;
-		bdb_attr_index_unparser( &aidef, bva );
-	}
-	for ( i=0; i<bdb->bi_nattrs; i++ )
-		bdb_attr_index_unparser( bdb->bi_attrs[i], bva );
-}
-
-void
-bdb_attr_info_free( AttrInfo *ai )
-{
-#ifdef LDAP_COMP_MATCH
-	free( ai->ai_cr );
-#endif
-	free( ai );
-}
-
-void
-bdb_attr_index_destroy( struct bdb_info *bdb )
-{
-	int i;
-
-	for ( i=0; i<bdb->bi_nattrs; i++ ) 
-		bdb_attr_info_free( bdb->bi_attrs[i] );
-
-	free( bdb->bi_attrs );
-}
-
-void bdb_attr_index_free( struct bdb_info *bdb, AttributeDescription *ad )
-{
-	int i;
-
-	i = bdb_attr_slot( bdb, ad, NULL );
-	if ( i >= 0 ) {
-		bdb_attr_info_free( bdb->bi_attrs[i] );
-		bdb->bi_nattrs--;
-		for (; i<bdb->bi_nattrs; i++)
-			bdb->bi_attrs[i] = bdb->bi_attrs[i+1];
-	}
-}
-
-void bdb_attr_flush( struct bdb_info *bdb )
-{
-	int i;
-
-	for ( i=0; i<bdb->bi_nattrs; i++ ) {
-		if ( bdb->bi_attrs[i]->ai_indexmask & BDB_INDEX_DELETING ) {
-			int j;
-			bdb_attr_info_free( bdb->bi_attrs[i] );
-			bdb->bi_nattrs--;
-			for (j=i; j<bdb->bi_nattrs; j++)
-				bdb->bi_attrs[j] = bdb->bi_attrs[j+1];
-			i--;
-		}
-	}
-}
diff --git a/servers/slapd/back-bdb/back-bdb.h b/servers/slapd/back-bdb/back-bdb.h
deleted file mode 100644
index 84897cd..0000000
--- a/servers/slapd/back-bdb/back-bdb.h
+++ /dev/null
@@ -1,377 +0,0 @@
-/* back-bdb.h - bdb back-end header file */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#ifndef _BACK_BDB_H_
-#define _BACK_BDB_H_
-
-#include <portable.h>
-#include "slap.h"
-#include <db.h>
-#include "alock.h"
-
-LDAP_BEGIN_DECL
-
-#define DB_VERSION_FULL ((DB_VERSION_MAJOR << 24) | (DB_VERSION_MINOR << 16) | DB_VERSION_PATCH)
-
-#define DN_BASE_PREFIX		SLAP_INDEX_EQUALITY_PREFIX
-#define DN_ONE_PREFIX	 	'%'
-#define DN_SUBTREE_PREFIX 	'@'
-
-#define DBTzero(t)			(memset((t), 0, sizeof(DBT)))
-#define DBT2bv(t,bv)		((bv)->bv_val = (t)->data, \
-								(bv)->bv_len = (t)->size)
-#define bv2DBT(bv,t)		((t)->data = (bv)->bv_val, \
-								(t)->size = (bv)->bv_len )
-
-#define BDB_TXN_RETRIES		16
-
-#define BDB_MAX_ADD_LOOP	30
-
-#define BDB_SUFFIX		".bdb"
-#define BDB_ID2ENTRY	0
-#define BDB_DN2ID		1
-#define BDB_NDB			2
-
-/* The bdb on-disk entry format is pretty space-inefficient. Average
- * sized user entries are 3-4K each. You need at least two entries to
- * fit into a single database page, more is better. 64K is BDB's
- * upper bound. Smaller pages are better for concurrency.
- */
-#ifndef BDB_ID2ENTRY_PAGESIZE
-#define	BDB_ID2ENTRY_PAGESIZE	16384
-#endif
-
-#define DEFAULT_CACHE_SIZE     1000
-
-/* The default search IDL stack cache depth */
-#define DEFAULT_SEARCH_STACK_DEPTH	16
-
-/* The minimum we can function with */
-#define MINIMUM_SEARCH_STACK_DEPTH	8
-
-typedef struct bdb_idl_cache_entry_s {
-	struct berval kstr;
-	ID      *idl;
-	DB      *db;
-	int		idl_flags;
-	struct bdb_idl_cache_entry_s* idl_lru_prev;
-	struct bdb_idl_cache_entry_s* idl_lru_next;
-} bdb_idl_cache_entry_t;
-
-/* BDB backend specific entry info */
-typedef struct bdb_entry_info {
-	struct bdb_entry_info *bei_parent;
-	ID bei_id;
-
-	/* we use the bei_id as a lockobj, but we need to make the size != 4
-	 * to avoid conflicting with BDB's internal locks. So add a byte here
-	 * that is always zero.
-	 */
-	short bei_lockpad;
-
-	short bei_state;
-#define	CACHE_ENTRY_DELETED	1
-#define	CACHE_ENTRY_NO_KIDS	2
-#define	CACHE_ENTRY_NOT_LINKED	4
-#define CACHE_ENTRY_NO_GRANDKIDS	8
-#define	CACHE_ENTRY_LOADING	0x10
-#define	CACHE_ENTRY_WALKING	0x20
-#define	CACHE_ENTRY_ONELEVEL	0x40
-#define	CACHE_ENTRY_REFERENCED	0x80
-#define	CACHE_ENTRY_NOT_CACHED	0x100
-	int bei_finders;
-
-	/*
-	 * remaining fields require backend cache lock to access
-	 */
-	struct berval bei_nrdn;
-#ifdef BDB_HIER
-	struct berval bei_rdn;
-	int	bei_modrdns;	/* track renames */
-	int	bei_ckids;	/* number of kids cached */
-	int	bei_dkids;	/* number of kids on-disk, plus 1 */
-#endif
-	Entry	*bei_e;
-	Avlnode	*bei_kids;
-#ifdef SLAP_ZONE_ALLOC
-	struct bdb_info *bei_bdb;
-	int bei_zseq;	
-#endif
-	ldap_pvt_thread_mutex_t	bei_kids_mutex;
-	
-	struct bdb_entry_info	*bei_lrunext;	/* for cache lru list */
-	struct bdb_entry_info	*bei_lruprev;
-} EntryInfo;
-#undef BEI
-#define BEI(e)	((EntryInfo *) ((e)->e_private))
-
-/* for the in-core cache of entries */
-typedef struct bdb_cache {
-	EntryInfo	*c_eifree;	/* free list */
-	Avlnode		*c_idtree;
-	EntryInfo	*c_lruhead;	/* lru - add accessed entries here */
-	EntryInfo	*c_lrutail;	/* lru - rem lru entries from here */
-	EntryInfo	c_dntree;
-	ID		c_maxsize;
-	ID		c_cursize;
-	ID		c_minfree;
-	ID		c_eimax;
-	ID		c_eiused;	/* EntryInfo's in use */
-	ID		c_leaves;	/* EntryInfo leaf nodes */
-	int		c_purging;
-	DB_TXN	*c_txn;	/* used by lru cleaner */
-	ldap_pvt_thread_rdwr_t c_rwlock;
-	ldap_pvt_thread_mutex_t c_lru_mutex;
-	ldap_pvt_thread_mutex_t c_count_mutex;
-	ldap_pvt_thread_mutex_t c_eifree_mutex;
-#ifdef SLAP_ZONE_ALLOC
-	void *c_zctx;
-#endif
-} Cache;
- 
-#define CACHE_READ_LOCK                0
-#define CACHE_WRITE_LOCK       1
- 
-#define BDB_INDICES		128
-
-struct bdb_db_info {
-	struct berval	bdi_name;
-	DB			*bdi_db;
-};
-
-struct bdb_db_pgsize {
-	struct bdb_db_pgsize *bdp_next;
-	struct berval	bdp_name;
-	int	bdp_size;
-};
-
-#ifdef LDAP_DEVEL
-#define BDB_MONITOR_IDX
-#endif /* LDAP_DEVEL */
-
-typedef struct bdb_monitor_t {
-	void		*bdm_cb;
-	struct berval	bdm_ndn;
-} bdb_monitor_t;
-
-/* From ldap_rq.h */
-struct re_s;
-
-struct bdb_info {
-	DB_ENV		*bi_dbenv;
-
-	/* DB_ENV parameters */
-	/* The DB_ENV can be tuned via DB_CONFIG */
-	char		*bi_dbenv_home;
-	u_int32_t	bi_dbenv_xflags; /* extra flags */
-	int			bi_dbenv_mode;
-
-	int			bi_ndatabases;
-	int		bi_db_opflags;	/* db-specific flags */
-	struct bdb_db_info **bi_databases;
-	ldap_pvt_thread_mutex_t	bi_database_mutex;
-	struct bdb_db_pgsize *bi_pagesizes;
-
-	slap_mask_t	bi_defaultmask;
-	Cache		bi_cache;
-	struct bdb_attrinfo		**bi_attrs;
-	int			bi_nattrs;
-	void		*bi_search_stack;
-	int		bi_search_stack_depth;
-	int		bi_linear_index;
-
-	int			bi_txn_cp;
-	u_int32_t	bi_txn_cp_min;
-	u_int32_t	bi_txn_cp_kbyte;
-	struct re_s		*bi_txn_cp_task;
-	struct re_s		*bi_index_task;
-
-	u_int32_t		bi_lock_detect;
-	long		bi_shm_key;
-
-	ID			bi_lastid;
-	ldap_pvt_thread_mutex_t	bi_lastid_mutex;
-	ID	bi_idl_cache_max_size;
-	ID		bi_idl_cache_size;
-	Avlnode		*bi_idl_tree;
-	bdb_idl_cache_entry_t	*bi_idl_lru_head;
-	bdb_idl_cache_entry_t	*bi_idl_lru_tail;
-	ldap_pvt_thread_rdwr_t bi_idl_tree_rwlock;
-	ldap_pvt_thread_mutex_t bi_idl_tree_lrulock;
-	alock_info_t	bi_alock_info;
-	char		*bi_db_config_path;
-	BerVarray	bi_db_config;
-	char		*bi_db_crypt_file;
-	struct berval	bi_db_crypt_key;
-	bdb_monitor_t	bi_monitor;
-
-#ifdef BDB_MONITOR_IDX
-	ldap_pvt_thread_mutex_t	bi_idx_mutex;
-	Avlnode		*bi_idx;
-#endif /* BDB_MONITOR_IDX */
-
-	int		bi_flags;
-#define	BDB_IS_OPEN		0x01
-#define	BDB_HAS_CONFIG	0x02
-#define	BDB_UPD_CONFIG	0x04
-#define	BDB_DEL_INDEX	0x08
-#define	BDB_RE_OPEN		0x10
-#define BDB_CHKSUM		0x20
-#ifdef BDB_HIER
-	int		bi_modrdns;		/* number of modrdns completed */
-	ldap_pvt_thread_mutex_t	bi_modrdns_mutex;
-#endif
-};
-
-#define bi_id2entry	bi_databases[BDB_ID2ENTRY]
-#define bi_dn2id	bi_databases[BDB_DN2ID]
-
-
-struct bdb_lock_info {
-	struct bdb_lock_info *bli_next;
-	DB_LOCK	bli_lock;
-	ID		bli_id;
-	int		bli_flag;
-};
-#define	BLI_DONTFREE	1
-
-struct bdb_op_info {
-	OpExtra boi_oe;
-	DB_TXN*		boi_txn;
-	struct bdb_lock_info *boi_locks;	/* used when no txn */
-	u_int32_t	boi_err;
-	char		boi_acl_cache;
-	char		boi_flag;
-};
-#define BOI_DONTFREE	1
-
-#define	DB_OPEN(db, file, name, type, flags, mode) \
-	((db)->open)(db, file, name, type, flags, mode)
-
-#if DB_VERSION_MAJOR < 4
-#define LOCK_DETECT(env,f,t,a)		lock_detect(env, f, t, a)
-#define LOCK_GET(env,i,f,o,m,l)		lock_get(env, i, f, o, m, l)
-#define LOCK_PUT(env,l)			lock_put(env, l)
-#define TXN_CHECKPOINT(env,k,m,f)	txn_checkpoint(env, k, m, f)
-#define TXN_BEGIN(env,p,t,f)		txn_begin((env), p, t, f)
-#define TXN_PREPARE(txn,gid)		txn_prepare((txn), (gid))
-#define TXN_COMMIT(txn,f)			txn_commit((txn), (f))
-#define	TXN_ABORT(txn)				txn_abort((txn))
-#define TXN_ID(txn)					txn_id(txn)
-#define XLOCK_ID(env, locker)		lock_id(env, locker)
-#define XLOCK_ID_FREE(env, locker)	lock_id_free(env, locker)
-#else
-#define LOCK_DETECT(env,f,t,a)		(env)->lock_detect(env, f, t, a)
-#define LOCK_GET(env,i,f,o,m,l)		(env)->lock_get(env, i, f, o, m, l)
-#define LOCK_PUT(env,l)			(env)->lock_put(env, l)
-#define TXN_CHECKPOINT(env,k,m,f)	(env)->txn_checkpoint(env, k, m, f)
-#define TXN_BEGIN(env,p,t,f)		(env)->txn_begin((env), p, t, f)
-#define TXN_PREPARE(txn,g)			(txn)->prepare((txn), (g))
-#define TXN_COMMIT(txn,f)			(txn)->commit((txn), (f))
-#define TXN_ABORT(txn)				(txn)->abort((txn))
-#define TXN_ID(txn)					(txn)->id(txn)
-#define XLOCK_ID(env, locker)		(env)->lock_id(env, locker)
-#define XLOCK_ID_FREE(env, locker)	(env)->lock_id_free(env, locker)
-
-/* BDB 4.1.17 adds txn arg to db->open */
-#if DB_VERSION_FULL >= 0x04010011
-#undef DB_OPEN
-#define	DB_OPEN(db, file, name, type, flags, mode) \
-	((db)->open)(db, NULL, file, name, type, flags, mode)
-#endif
-
-/* #undef BDB_LOG_DEBUG */
-
-#ifdef BDB_LOG_DEBUG
-
-/* env->log_printf appeared in 4.4 */
-#if DB_VERSION_FULL >= 0x04040000
-#define	BDB_LOG_PRINTF(env,txn,fmt,...)	(env)->log_printf((env),(txn),(fmt),__VA_ARGS__)
-#else
-extern int __db_logmsg(const DB_ENV *env, DB_TXN *txn, const char *op, u_int32_t flags,
-	const char *fmt,...);
-#define	BDB_LOG_PRINTF(env,txn,fmt,...)	__db_logmsg((env),(txn),"DIAGNOSTIC",0,(fmt),__VA_ARGS__)
-#endif
-
-/* !BDB_LOG_DEBUG */
-#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
-	(defined(__GNUC__) && __GNUC__ >= 3 && !defined(__STRICT_ANSI__))
-#define BDB_LOG_PRINTF(a,b,c,...)
-#else
-#define BDB_LOG_PRINTF (void)	/* will evaluate and discard the arguments */
-
-#endif /* BDB_LOG_DEBUG */
-
-#endif
-
-#ifndef DB_BUFFER_SMALL
-#define DB_BUFFER_SMALL			ENOMEM
-#endif
-
-#define BDB_CSN_COMMIT	0
-#define BDB_CSN_ABORT	1
-#define BDB_CSN_RETRY	2
-
-/* Copy an ID "src" to pointer "dst" in big-endian byte order */
-#define BDB_ID2DISK( src, dst )	\
-	do { int i0; ID tmp; unsigned char *_p;	\
-		tmp = (src); _p = (unsigned char *)(dst);	\
-		for ( i0=sizeof(ID)-1; i0>=0; i0-- ) {	\
-			_p[i0] = tmp & 0xff; tmp >>= 8;	\
-		} \
-	} while(0)
-
-/* Copy a pointer "src" to a pointer "dst" from big-endian to native order */
-#define BDB_DISK2ID( src, dst ) \
-	do { unsigned i0; ID tmp = 0; unsigned char *_p;	\
-		_p = (unsigned char *)(src);	\
-		for ( i0=0; i0<sizeof(ID); i0++ ) {	\
-			tmp <<= 8; tmp |= *_p++;	\
-		} *(dst) = tmp; \
-	} while (0)
-
-LDAP_END_DECL
-
-/* for the cache of attribute information (which are indexed, etc.) */
-typedef struct bdb_attrinfo {
-	AttributeDescription *ai_desc; /* attribute description cn;lang-en */
-	slap_mask_t ai_indexmask;	/* how the attr is indexed	*/
-	slap_mask_t ai_newmask;	/* new settings to replace old mask */
-#ifdef LDAP_COMP_MATCH
-	ComponentReference* ai_cr; /*component indexing*/
-#endif
-} AttrInfo;
-
-/* These flags must not clash with SLAP_INDEX flags or ops in slap.h! */
-#define	BDB_INDEX_DELETING	0x8000U	/* index is being modified */
-#define	BDB_INDEX_UPDATE_OP	0x03	/* performing an index update */
-
-/* For slapindex to record which attrs in an entry belong to which
- * index database 
- */
-typedef struct AttrList {
-	struct AttrList *next;
-	Attribute *attr;
-} AttrList;
-
-typedef struct IndexRec {
-	AttrInfo *ai;
-	AttrList *attrs;
-} IndexRec;
-
-#include "proto-bdb.h"
-
-#endif /* _BACK_BDB_H_ */
diff --git a/servers/slapd/back-bdb/bind.c b/servers/slapd/back-bdb/bind.c
deleted file mode 100644
index c09d629..0000000
--- a/servers/slapd/back-bdb/bind.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/* bind.c - bdb backend bind routine */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-
-#include "back-bdb.h"
-
-int
-bdb_bind( Operation *op, SlapReply *rs )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	Entry		*e;
-	Attribute	*a;
-	EntryInfo	*ei;
-
-	AttributeDescription *password = slap_schema.si_ad_userPassword;
-
-	DB_TXN		*rtxn;
-	DB_LOCK		lock;
-
-	Debug( LDAP_DEBUG_ARGS,
-		"==> " LDAP_XSTRING(bdb_bind) ": dn: %s\n",
-		op->o_req_dn.bv_val, 0, 0);
-
-	/* allow noauth binds */
-	switch ( be_rootdn_bind( op, NULL ) ) {
-	case LDAP_SUCCESS:
-		/* frontend will send result */
-		return rs->sr_err = LDAP_SUCCESS;
-
-	default:
-		/* give the database a chance */
-		/* NOTE: this behavior departs from that of other backends,
-		 * since the others, in case of password checking failure
-		 * do not give the database a chance.  If an entry with
-		 * rootdn's name does not exist in the database the result
-		 * will be the same.  See ITS#4962 for discussion. */
-		break;
-	}
-
-	rs->sr_err = bdb_reader_get(op, bdb->bi_dbenv, &rtxn);
-	switch(rs->sr_err) {
-	case 0:
-		break;
-	default:
-		rs->sr_text = "internal error";
-		send_ldap_result( op, rs );
-		return rs->sr_err;
-	}
-
-dn2entry_retry:
-	/* get entry with reader lock */
-	rs->sr_err = bdb_dn2entry( op, rtxn, &op->o_req_ndn, &ei, 1,
-		&lock );
-
-	switch(rs->sr_err) {
-	case DB_NOTFOUND:
-	case 0:
-		break;
-	case LDAP_BUSY:
-		send_ldap_error( op, rs, LDAP_BUSY, "ldap_server_busy" );
-		return LDAP_BUSY;
-	case DB_LOCK_DEADLOCK:
-	case DB_LOCK_NOTGRANTED:
-		goto dn2entry_retry;
-	default:
-		send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
-		return rs->sr_err;
-	}
-
-	e = ei->bei_e;
-	if ( rs->sr_err == DB_NOTFOUND ) {
-		if( e != NULL ) {
-			bdb_cache_return_entry_r( bdb, e, &lock );
-			e = NULL;
-		}
-
-		rs->sr_err = LDAP_INVALID_CREDENTIALS;
-		send_ldap_result( op, rs );
-
-		return rs->sr_err;
-	}
-
-	ber_dupbv( &op->oq_bind.rb_edn, &e->e_name );
-
-	/* check for deleted */
-	if ( is_entry_subentry( e ) ) {
-		/* entry is an subentry, don't allow bind */
-		Debug( LDAP_DEBUG_TRACE, "entry is subentry\n", 0,
-			0, 0 );
-		rs->sr_err = LDAP_INVALID_CREDENTIALS;
-		goto done;
-	}
-
-	if ( is_entry_alias( e ) ) {
-		/* entry is an alias, don't allow bind */
-		Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0, 0, 0 );
-		rs->sr_err = LDAP_INVALID_CREDENTIALS;
-		goto done;
-	}
-
-	if ( is_entry_referral( e ) ) {
-		Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
-			0, 0 );
-		rs->sr_err = LDAP_INVALID_CREDENTIALS;
-		goto done;
-	}
-
-	switch ( op->oq_bind.rb_method ) {
-	case LDAP_AUTH_SIMPLE:
-		a = attr_find( e->e_attrs, password );
-		if ( a == NULL ) {
-			rs->sr_err = LDAP_INVALID_CREDENTIALS;
-			goto done;
-		}
-
-		if ( slap_passwd_check( op, e, a, &op->oq_bind.rb_cred,
-					&rs->sr_text ) != 0 )
-		{
-			/* failure; stop front end from sending result */
-			rs->sr_err = LDAP_INVALID_CREDENTIALS;
-			goto done;
-		}
-			
-		rs->sr_err = 0;
-		break;
-
-	default:
-		assert( 0 ); /* should not be reachable */
-		rs->sr_err = LDAP_STRONG_AUTH_NOT_SUPPORTED;
-		rs->sr_text = "authentication method not supported";
-	}
-
-done:
-	/* free entry and reader lock */
-	if( e != NULL ) {
-		bdb_cache_return_entry_r( bdb, e, &lock );
-	}
-
-	if ( rs->sr_err ) {
-		send_ldap_result( op, rs );
-		if ( rs->sr_ref ) {
-			ber_bvarray_free( rs->sr_ref );
-			rs->sr_ref = NULL;
-		}
-	}
-	/* front end will send result on success (rs->sr_err==0) */
-	return rs->sr_err;
-}
diff --git a/servers/slapd/back-bdb/cache.c b/servers/slapd/back-bdb/cache.c
deleted file mode 100644
index 51161fe..0000000
--- a/servers/slapd/back-bdb/cache.c
+++ /dev/null
@@ -1,1692 +0,0 @@
-/* cache.c - routines to maintain an in-core cache of entries */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/errno.h>
-#include <ac/string.h>
-#include <ac/socket.h>
-
-#include "slap.h"
-
-#include "back-bdb.h"
-
-#include "ldap_rq.h"
-
-#ifdef BDB_HIER
-#define bdb_cache_lru_purge	hdb_cache_lru_purge
-#endif
-static void bdb_cache_lru_purge( struct bdb_info *bdb );
-
-static int	bdb_cache_delete_internal(Cache *cache, EntryInfo *e, int decr);
-#ifdef LDAP_DEBUG
-#define SLAPD_UNUSED
-#ifdef SLAPD_UNUSED
-static void	bdb_lru_print(Cache *cache);
-static void	bdb_idtree_print(Cache *cache);
-#endif
-#endif
-
-/* For concurrency experiments only! */
-#if 0
-#define	ldap_pvt_thread_rdwr_wlock(a)	0
-#define	ldap_pvt_thread_rdwr_wunlock(a)	0
-#define	ldap_pvt_thread_rdwr_rlock(a)	0
-#define	ldap_pvt_thread_rdwr_runlock(a)	0
-#endif
-
-#if 0
-#define ldap_pvt_thread_mutex_trylock(a) 0
-#endif
-
-static EntryInfo *
-bdb_cache_entryinfo_new( Cache *cache )
-{
-	EntryInfo *ei = NULL;
-
-	if ( cache->c_eifree ) {
-		ldap_pvt_thread_mutex_lock( &cache->c_eifree_mutex );
-		if ( cache->c_eifree ) {
-			ei = cache->c_eifree;
-			cache->c_eifree = ei->bei_lrunext;
-			ei->bei_finders = 0;
-			ei->bei_lrunext = NULL;
-		}
-		ldap_pvt_thread_mutex_unlock( &cache->c_eifree_mutex );
-	}
-	if ( !ei ) {
-		ei = ch_calloc(1, sizeof(EntryInfo));
-		ldap_pvt_thread_mutex_init( &ei->bei_kids_mutex );
-	}
-
-	ei->bei_state = CACHE_ENTRY_REFERENCED;
-
-	return ei;
-}
-
-static void
-bdb_cache_entryinfo_free( Cache *cache, EntryInfo *ei )
-{
-	free( ei->bei_nrdn.bv_val );
-	BER_BVZERO( &ei->bei_nrdn );
-#ifdef BDB_HIER
-	free( ei->bei_rdn.bv_val );
-	BER_BVZERO( &ei->bei_rdn );
-	ei->bei_modrdns = 0;
-	ei->bei_ckids = 0;
-	ei->bei_dkids = 0;
-#endif
-	ei->bei_parent = NULL;
-	ei->bei_kids = NULL;
-	ei->bei_lruprev = NULL;
-
-#if 0
-	ldap_pvt_thread_mutex_lock( &cache->c_eifree_mutex );
-	ei->bei_lrunext = cache->c_eifree;
-	cache->c_eifree = ei;
-	ldap_pvt_thread_mutex_unlock( &cache->c_eifree_mutex );
-#else
-	ldap_pvt_thread_mutex_destroy( &ei->bei_kids_mutex );
-	ch_free( ei );
-#endif
-}
-
-#define LRU_DEL( c, e ) do { \
-	if ( e == e->bei_lruprev ) { \
-		(c)->c_lruhead = (c)->c_lrutail = NULL; \
-	} else { \
-		if ( e == (c)->c_lruhead ) (c)->c_lruhead = e->bei_lruprev; \
-		if ( e == (c)->c_lrutail ) (c)->c_lrutail = e->bei_lruprev; \
-		e->bei_lrunext->bei_lruprev = e->bei_lruprev; \
-		e->bei_lruprev->bei_lrunext = e->bei_lrunext; \
-	} \
-	e->bei_lruprev = NULL; \
-} while ( 0 )
-
-/* Note - we now use a Second-Chance / Clock algorithm instead of
- * Least-Recently-Used. This tremendously improves concurrency
- * because we no longer need to manipulate the lists every time an
- * entry is touched. We only need to lock the lists when adding
- * or deleting an entry. It's now a circular doubly-linked list.
- * We always append to the tail, but the head traverses the circle
- * during a purge operation.
- */
-static void
-bdb_cache_lru_link( struct bdb_info *bdb, EntryInfo *ei )
-{
-
-	/* Already linked, ignore */
-	if ( ei->bei_lruprev )
-		return;
-
-	/* Insert into circular LRU list */
-	ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_lru_mutex );
-
-	ei->bei_lruprev = bdb->bi_cache.c_lrutail;
-	if ( bdb->bi_cache.c_lrutail ) {
-		ei->bei_lrunext = bdb->bi_cache.c_lrutail->bei_lrunext;
-		bdb->bi_cache.c_lrutail->bei_lrunext = ei;
-		if ( ei->bei_lrunext )
-			ei->bei_lrunext->bei_lruprev = ei;
-	} else {
-		ei->bei_lrunext = ei->bei_lruprev = ei;
-		bdb->bi_cache.c_lruhead = ei;
-	}
-	bdb->bi_cache.c_lrutail = ei;
-	ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_lru_mutex );
-}
-
-#ifdef NO_THREADS
-#define NO_DB_LOCK
-#endif
-
-/* #define NO_DB_LOCK 1 */
-/* Note: The BerkeleyDB locks are much slower than regular
- * mutexes or rdwr locks. But the BDB implementation has the
- * advantage of using a fixed size lock table, instead of
- * allocating a lock object per entry in the DB. That's a
- * key benefit for scaling. It also frees us from worrying
- * about undetectable deadlocks between BDB activity and our
- * own cache activity. It's still worth exploring faster
- * alternatives though.
- */
-
-/* Atomically release and reacquire a lock */
-int
-bdb_cache_entry_db_relock(
-	struct bdb_info *bdb,
-	DB_TXN *txn,
-	EntryInfo *ei,
-	int rw,
-	int tryOnly,
-	DB_LOCK *lock )
-{
-#ifdef NO_DB_LOCK
-	return 0;
-#else
-	int	rc;
-	DBT	lockobj;
-	DB_LOCKREQ list[2];
-
-	if ( !lock ) return 0;
-
-	DBTzero( &lockobj );
-	lockobj.data = &ei->bei_id;
-	lockobj.size = sizeof(ei->bei_id) + 1;
-
-	list[0].op = DB_LOCK_PUT;
-	list[0].lock = *lock;
-	list[1].op = DB_LOCK_GET;
-	list[1].lock = *lock;
-	list[1].mode = rw ? DB_LOCK_WRITE : DB_LOCK_READ;
-	list[1].obj = &lockobj;
-	rc = bdb->bi_dbenv->lock_vec(bdb->bi_dbenv, TXN_ID(txn), tryOnly ? DB_LOCK_NOWAIT : 0,
-		list, 2, NULL );
-
-	if (rc && !tryOnly) {
-		Debug( LDAP_DEBUG_TRACE,
-			"bdb_cache_entry_db_relock: entry %ld, rw %d, rc %d\n",
-			ei->bei_id, rw, rc );
-	} else {
-		*lock = list[1].lock;
-	}
-	return rc;
-#endif
-}
-
-static int
-bdb_cache_entry_db_lock( struct bdb_info *bdb, DB_TXN *txn, EntryInfo *ei,
-	int rw, int tryOnly, DB_LOCK *lock )
-{
-#ifdef NO_DB_LOCK
-	return 0;
-#else
-	int       rc;
-	DBT       lockobj;
-	int       db_rw;
-
-	if ( !lock ) return 0;
-
-	if (rw)
-		db_rw = DB_LOCK_WRITE;
-	else
-		db_rw = DB_LOCK_READ;
-
-	DBTzero( &lockobj );
-	lockobj.data = &ei->bei_id;
-	lockobj.size = sizeof(ei->bei_id) + 1;
-
-	rc = LOCK_GET(bdb->bi_dbenv, TXN_ID(txn), tryOnly ? DB_LOCK_NOWAIT : 0,
-					&lockobj, db_rw, lock);
-	if (rc && !tryOnly) {
-		Debug( LDAP_DEBUG_TRACE,
-			"bdb_cache_entry_db_lock: entry %ld, rw %d, rc %d\n",
-			ei->bei_id, rw, rc );
-	}
-	return rc;
-#endif /* NO_DB_LOCK */
-}
-
-int
-bdb_cache_entry_db_unlock ( struct bdb_info *bdb, DB_LOCK *lock )
-{
-#ifdef NO_DB_LOCK
-	return 0;
-#else
-	int rc;
-
-	if ( !lock || lock->mode == DB_LOCK_NG ) return 0;
-
-	rc = LOCK_PUT ( bdb->bi_dbenv, lock );
-	return rc;
-#endif
-}
-
-void
-bdb_cache_return_entry_rw( struct bdb_info *bdb, Entry *e,
-	int rw, DB_LOCK *lock )
-{
-	EntryInfo *ei;
-	int free = 0;
-
-	ei = e->e_private;
-	if ( ei && ( ei->bei_state & CACHE_ENTRY_NOT_CACHED )) {
-		bdb_cache_entryinfo_lock( ei );
-		if ( ei->bei_state & CACHE_ENTRY_NOT_CACHED ) {
-			/* Releasing the entry can only be done when
-			 * we know that nobody else is using it, i.e we
-			 * should have an entry_db writelock.  But the
-			 * flag is only set by the thread that loads the
-			 * entry, and only if no other threads has found
-			 * it while it was working.  All other threads
-			 * clear the flag, which mean that we should be
-			 * the only thread using the entry if the flag
-			 * is set here.
-			 */
-			ei->bei_e = NULL;
-			ei->bei_state ^= CACHE_ENTRY_NOT_CACHED;
-			free = 1;
-		}
-		bdb_cache_entryinfo_unlock( ei );
-	}
-	bdb_cache_entry_db_unlock( bdb, lock );
-	if ( free ) {
-		e->e_private = NULL;
-		bdb_entry_return( e );
-	}
-}
-
-static int
-bdb_cache_entryinfo_destroy( EntryInfo *e )
-{
-	ldap_pvt_thread_mutex_destroy( &e->bei_kids_mutex );
-	free( e->bei_nrdn.bv_val );
-#ifdef BDB_HIER
-	free( e->bei_rdn.bv_val );
-#endif
-	free( e );
-	return 0;
-}
-
-/* Do a length-ordered sort on normalized RDNs */
-static int
-bdb_rdn_cmp( const void *v_e1, const void *v_e2 )
-{
-	const EntryInfo *e1 = v_e1, *e2 = v_e2;
-	int rc = e1->bei_nrdn.bv_len - e2->bei_nrdn.bv_len;
-	if (rc == 0) {
-		rc = strncmp( e1->bei_nrdn.bv_val, e2->bei_nrdn.bv_val,
-			e1->bei_nrdn.bv_len );
-	}
-	return rc;
-}
-
-static int
-bdb_id_cmp( const void *v_e1, const void *v_e2 )
-{
-	const EntryInfo *e1 = v_e1, *e2 = v_e2;
-	return e1->bei_id - e2->bei_id;
-}
-
-static int
-bdb_id_dup_err( void *v1, void *v2 )
-{
-	EntryInfo *e2 = v2;
-	e2->bei_lrunext = v1;
-	return -1;
-}
-
-/* Create an entryinfo in the cache. Caller must release the locks later.
- */
-static int
-bdb_entryinfo_add_internal(
-	struct bdb_info *bdb,
-	EntryInfo *ei,
-	EntryInfo **res )
-{
-	EntryInfo *ei2 = NULL;
-
-	*res = NULL;
-
-	ei2 = bdb_cache_entryinfo_new( &bdb->bi_cache );
-
-	bdb_cache_entryinfo_lock( ei->bei_parent );
-	ldap_pvt_thread_rdwr_wlock( &bdb->bi_cache.c_rwlock );
-
-	ei2->bei_id = ei->bei_id;
-	ei2->bei_parent = ei->bei_parent;
-#ifdef BDB_HIER
-	ei2->bei_rdn = ei->bei_rdn;
-#endif
-#ifdef SLAP_ZONE_ALLOC
-	ei2->bei_bdb = bdb;
-#endif
-
-	/* Add to cache ID tree */
-	if (avl_insert( &bdb->bi_cache.c_idtree, ei2, bdb_id_cmp,
-		bdb_id_dup_err )) {
-		EntryInfo *eix = ei2->bei_lrunext;
-		bdb_cache_entryinfo_free( &bdb->bi_cache, ei2 );
-		ei2 = eix;
-#ifdef BDB_HIER
-		/* It got freed above because its value was
-		 * assigned to ei2.
-		 */
-		ei->bei_rdn.bv_val = NULL;
-#endif
-	} else {
-		int rc;
-
-		bdb->bi_cache.c_eiused++;
-		ber_dupbv( &ei2->bei_nrdn, &ei->bei_nrdn );
-
-		/* This is a new leaf node. But if parent had no kids, then it was
-		 * a leaf and we would be decrementing that. So, only increment if
-		 * the parent already has kids.
-		 */
-		if ( ei->bei_parent->bei_kids || !ei->bei_parent->bei_id )
-			bdb->bi_cache.c_leaves++;
-		rc = avl_insert( &ei->bei_parent->bei_kids, ei2, bdb_rdn_cmp,
-			avl_dup_error );
-#ifdef BDB_HIER
-		/* it's possible for hdb_cache_find_parent to beat us to it */
-		if ( !rc ) {
-			ei->bei_parent->bei_ckids++;
-		}
-#endif
-	}
-
-	*res = ei2;
-	return 0;
-}
-
-/* Find the EntryInfo for the requested DN. If the DN cannot be found, return
- * the info for its closest ancestor. *res should be NULL to process a
- * complete DN starting from the tree root. Otherwise *res must be the
- * immediate parent of the requested DN, and only the RDN will be searched.
- * The EntryInfo is locked upon return and must be unlocked by the caller.
- */
-int
-bdb_cache_find_ndn(
-	Operation	*op,
-	DB_TXN		*txn,
-	struct berval	*ndn,
-	EntryInfo	**res )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	EntryInfo	ei, *eip, *ei2;
-	int rc = 0;
-	char *ptr;
-
-	/* this function is always called with normalized DN */
-	if ( *res ) {
-		/* we're doing a onelevel search for an RDN */
-		ei.bei_nrdn.bv_val = ndn->bv_val;
-		ei.bei_nrdn.bv_len = dn_rdnlen( op->o_bd, ndn );
-		eip = *res;
-	} else {
-		/* we're searching a full DN from the root */
-		ptr = ndn->bv_val + ndn->bv_len - op->o_bd->be_nsuffix[0].bv_len;
-		ei.bei_nrdn.bv_val = ptr;
-		ei.bei_nrdn.bv_len = op->o_bd->be_nsuffix[0].bv_len;
-		/* Skip to next rdn if suffix is empty */
-		if ( ei.bei_nrdn.bv_len == 0 ) {
-			for (ptr = ei.bei_nrdn.bv_val - 2; ptr > ndn->bv_val
-				&& !DN_SEPARATOR(*ptr); ptr--) /* empty */;
-			if ( ptr >= ndn->bv_val ) {
-				if (DN_SEPARATOR(*ptr)) ptr++;
-				ei.bei_nrdn.bv_len = ei.bei_nrdn.bv_val - ptr;
-				ei.bei_nrdn.bv_val = ptr;
-			}
-		}
-		eip = &bdb->bi_cache.c_dntree;
-	}
-	
-	for ( bdb_cache_entryinfo_lock( eip ); eip; ) {
-		eip->bei_state |= CACHE_ENTRY_REFERENCED;
-		ei.bei_parent = eip;
-		ei2 = (EntryInfo *)avl_find( eip->bei_kids, &ei, bdb_rdn_cmp );
-		if ( !ei2 ) {
-			DBC *cursor;
-			int len = ei.bei_nrdn.bv_len;
-				
-			if ( BER_BVISEMPTY( ndn )) {
-				*res = eip;
-				return LDAP_SUCCESS;
-			}
-
-			ei.bei_nrdn.bv_len = ndn->bv_len -
-				(ei.bei_nrdn.bv_val - ndn->bv_val);
-			eip->bei_finders++;
-			bdb_cache_entryinfo_unlock( eip );
-
-			BDB_LOG_PRINTF( bdb->bi_dbenv, NULL, "slapd Reading %s",
-				ei.bei_nrdn.bv_val );
-
-			cursor = NULL;
-			rc = bdb_dn2id( op, &ei.bei_nrdn, &ei, txn, &cursor );
-			if (rc) {
-				bdb_cache_entryinfo_lock( eip );
-				eip->bei_finders--;
-				if ( cursor ) cursor->c_close( cursor );
-				*res = eip;
-				return rc;
-			}
-
-			BDB_LOG_PRINTF( bdb->bi_dbenv, NULL, "slapd Read got %s(%d)",
-				ei.bei_nrdn.bv_val, ei.bei_id );
-
-			/* DN exists but needs to be added to cache */
-			ei.bei_nrdn.bv_len = len;
-			rc = bdb_entryinfo_add_internal( bdb, &ei, &ei2 );
-			/* add_internal left eip and c_rwlock locked */
-			eip->bei_finders--;
-			ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
-			if ( cursor ) cursor->c_close( cursor );
-			if ( rc ) {
-				*res = eip;
-				return rc;
-			}
-		}
-		bdb_cache_entryinfo_lock( ei2 );
-		if ( ei2->bei_state & CACHE_ENTRY_DELETED ) {
-			/* In the midst of deleting? Give it a chance to
-			 * complete.
-			 */
-			bdb_cache_entryinfo_unlock( ei2 );
-			bdb_cache_entryinfo_unlock( eip );
-			ldap_pvt_thread_yield();
-			bdb_cache_entryinfo_lock( eip );
-			*res = eip;
-			return DB_NOTFOUND;
-		}
-		bdb_cache_entryinfo_unlock( eip );
-
-		eip = ei2;
-
-		/* Advance to next lower RDN */
-		for (ptr = ei.bei_nrdn.bv_val - 2; ptr > ndn->bv_val
-			&& !DN_SEPARATOR(*ptr); ptr--) /* empty */;
-		if ( ptr >= ndn->bv_val ) {
-			if (DN_SEPARATOR(*ptr)) ptr++;
-			ei.bei_nrdn.bv_len = ei.bei_nrdn.bv_val - ptr - 1;
-			ei.bei_nrdn.bv_val = ptr;
-		}
-		if ( ptr < ndn->bv_val ) {
-			*res = eip;
-			break;
-		}
-	}
-
-	return rc;
-}
-
-#ifdef BDB_HIER
-/* Walk up the tree from a child node, looking for an ID that's already
- * been linked into the cache.
- */
-int
-hdb_cache_find_parent(
-	Operation *op,
-	DB_TXN	*txn,
-	ID id,
-	EntryInfo **res )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	EntryInfo ei, eip, *ei2 = NULL, *ein = NULL, *eir = NULL;
-	int rc, add;
-
-	ei.bei_id = id;
-	ei.bei_kids = NULL;
-	ei.bei_ckids = 0;
-
-	for (;;) {
-		rc = hdb_dn2id_parent( op, txn, &ei, &eip.bei_id );
-		if ( rc ) break;
-
-		/* Save the previous node, if any */
-		ei2 = ein;
-
-		/* Create a new node for the current ID */
-		ein = bdb_cache_entryinfo_new( &bdb->bi_cache );
-		ein->bei_id = ei.bei_id;
-		ein->bei_kids = ei.bei_kids;
-		ein->bei_nrdn = ei.bei_nrdn;
-		ein->bei_rdn = ei.bei_rdn;
-		ein->bei_ckids = ei.bei_ckids;
-#ifdef SLAP_ZONE_ALLOC
-		ein->bei_bdb = bdb;
-#endif
-		ei.bei_ckids = 0;
-		add = 1;
-		
-		/* This node is not fully connected yet */
-		ein->bei_state |= CACHE_ENTRY_NOT_LINKED;
-
-		/* If this is the first time, save this node
-		 * to be returned later.
-		 */
-		if ( eir == NULL ) {
-			eir = ein;
-			ein->bei_finders++;
-		}
-
-again:
-		/* Insert this node into the ID tree */
-		ldap_pvt_thread_rdwr_wlock( &bdb->bi_cache.c_rwlock );
-		if ( avl_insert( &bdb->bi_cache.c_idtree, (caddr_t)ein,
-			bdb_id_cmp, bdb_id_dup_err ) ) {
-			EntryInfo *eix = ein->bei_lrunext;
-
-			if ( bdb_cache_entryinfo_trylock( eix )) {
-				ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
-				ldap_pvt_thread_yield();
-				goto again;
-			}
-			ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
-
-			/* Someone else created this node just before us.
-			 * Free our new copy and use the existing one.
-			 */
-			bdb_cache_entryinfo_free( &bdb->bi_cache, ein );
-
-			/* if it was the node we were looking for, just return it */
-			if ( eir == ein ) {
-				*res = eix;
-				rc = 0;
-				break;
-			}
-
-			ein = ei2;
-			ei2 = eix;
-			add = 0;
-
-			/* otherwise, link up what we have and return */
-			goto gotparent;
-		}
-
-		/* If there was a previous node, link it to this one */
-		if ( ei2 ) ei2->bei_parent = ein;
-
-		/* Look for this node's parent */
-par2:
-		if ( eip.bei_id ) {
-			ei2 = (EntryInfo *) avl_find( bdb->bi_cache.c_idtree,
-					(caddr_t) &eip, bdb_id_cmp );
-		} else {
-			ei2 = &bdb->bi_cache.c_dntree;
-		}
-		if ( ei2 && bdb_cache_entryinfo_trylock( ei2 )) {
-			ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
-			ldap_pvt_thread_yield();
-			ldap_pvt_thread_rdwr_wlock( &bdb->bi_cache.c_rwlock );
-			goto par2;
-		}
-		if ( add )
-			bdb->bi_cache.c_eiused++;
-		if ( ei2 && ( ei2->bei_kids || !ei2->bei_id ))
-			bdb->bi_cache.c_leaves++;
-		ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
-
-gotparent:
-		/* Got the parent, link in and we're done. */
-		if ( ei2 ) {
-			bdb_cache_entryinfo_lock( eir );
-			ein->bei_parent = ei2;
-
-			if ( avl_insert( &ei2->bei_kids, (caddr_t)ein, bdb_rdn_cmp,
-				avl_dup_error) == 0 )
-				ei2->bei_ckids++;
-
-			/* Reset all the state info */
-			for (ein = eir; ein != ei2; ein=ein->bei_parent)
-				ein->bei_state &= ~CACHE_ENTRY_NOT_LINKED;
-
-			bdb_cache_entryinfo_unlock( ei2 );
-			eir->bei_finders--;
-
-			*res = eir;
-			break;
-		}
-		ei.bei_kids = NULL;
-		ei.bei_id = eip.bei_id;
-		ei.bei_ckids = 1;
-		avl_insert( &ei.bei_kids, (caddr_t)ein, bdb_rdn_cmp,
-			avl_dup_error );
-	}
-	return rc;
-}
-
-/* Used by hdb_dn2idl when loading the EntryInfo for all the children
- * of a given node
- */
-int hdb_cache_load(
-	struct bdb_info *bdb,
-	EntryInfo *ei,
-	EntryInfo **res )
-{
-	EntryInfo *ei2;
-	int rc;
-
-	/* See if we already have this one */
-	bdb_cache_entryinfo_lock( ei->bei_parent );
-	ei2 = (EntryInfo *)avl_find( ei->bei_parent->bei_kids, ei, bdb_rdn_cmp );
-	bdb_cache_entryinfo_unlock( ei->bei_parent );
-
-	if ( !ei2 ) {
-		/* Not found, add it */
-		struct berval bv;
-
-		/* bei_rdn was not malloc'd before, do it now */
-		ber_dupbv( &bv, &ei->bei_rdn );
-		ei->bei_rdn = bv;
-
-		rc = bdb_entryinfo_add_internal( bdb, ei, res );
-		bdb_cache_entryinfo_unlock( ei->bei_parent );
-		ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
-	} else {
-		/* Found, return it */
-		*res = ei2;
-		return 0;
-	}
-	return rc;
-}
-#endif
-
-/* This is best-effort only. If all entries in the cache are
- * busy, they will all be kept. This is unlikely to happen
- * unless the cache is very much smaller than the working set.
- */
-static void
-bdb_cache_lru_purge( struct bdb_info *bdb )
-{
-	DB_LOCK		lock, *lockp;
-	EntryInfo *elru, *elnext = NULL;
-	int islocked;
-	ID eicount, ecount;
-	ID count, efree, eifree = 0;
-#ifdef LDAP_DEBUG
-	int iter;
-#endif
-
-	/* Wait for the mutex; we're the only one trying to purge. */
-	ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_lru_mutex );
-
-	if ( bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize ) {
-		efree = bdb->bi_cache.c_cursize - bdb->bi_cache.c_maxsize;
-		efree += bdb->bi_cache.c_minfree;
-	} else {
-		efree = 0;
-	}
-
-	/* maximum number of EntryInfo leaves to cache. In slapcat
-	 * we always free all leaf nodes.
-	 */
-
-	if ( slapMode & SLAP_TOOL_READONLY ) {
-		eifree = bdb->bi_cache.c_leaves;
-	} else if ( bdb->bi_cache.c_eimax &&
-		bdb->bi_cache.c_leaves > bdb->bi_cache.c_eimax ) {
-		eifree = bdb->bi_cache.c_minfree * 10;
-		if ( eifree >= bdb->bi_cache.c_leaves )
-			eifree /= 2;
-	}
-
-	if ( !efree && !eifree ) {
-		ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_lru_mutex );
-		bdb->bi_cache.c_purging = 0;
-		return;
-	}
-
-	if ( bdb->bi_cache.c_txn ) {
-		lockp = &lock;
-	} else {
-		lockp = NULL;
-	}
-
-	count = 0;
-	eicount = 0;
-	ecount = 0;
-#ifdef LDAP_DEBUG
-	iter = 0;
-#endif
-
-	/* Look for an unused entry to remove */
-	for ( elru = bdb->bi_cache.c_lruhead; elru; elru = elnext ) {
-		elnext = elru->bei_lrunext;
-
-		if ( bdb_cache_entryinfo_trylock( elru ))
-			goto bottom;
-
-		/* This flag implements the clock replacement behavior */
-		if ( elru->bei_state & ( CACHE_ENTRY_REFERENCED )) {
-			elru->bei_state &= ~CACHE_ENTRY_REFERENCED;
-			bdb_cache_entryinfo_unlock( elru );
-			goto bottom;
-		}
-
-		/* If this node is in the process of linking into the cache,
-		 * or this node is being deleted, skip it.
-		 */
-		if (( elru->bei_state & ( CACHE_ENTRY_NOT_LINKED |
-			CACHE_ENTRY_DELETED | CACHE_ENTRY_LOADING |
-			CACHE_ENTRY_ONELEVEL )) ||
-			elru->bei_finders > 0 ) {
-			bdb_cache_entryinfo_unlock( elru );
-			goto bottom;
-		}
-
-		if ( bdb_cache_entryinfo_trylock( elru->bei_parent )) {
-			bdb_cache_entryinfo_unlock( elru );
-			goto bottom;
-		}
-
-		/* entryinfo is locked */
-		islocked = 1;
-
-		/* If we can successfully writelock it, then
-		 * the object is idle.
-		 */
-		if ( bdb_cache_entry_db_lock( bdb,
-			bdb->bi_cache.c_txn, elru, 1, 1, lockp ) == 0 ) {
-
-			/* Free entry for this node if it's present */
-			if ( elru->bei_e ) {
-				ecount++;
-
-				/* the cache may have gone over the limit while we
-				 * weren't looking, so double check.
-				 */
-				if ( !efree && ecount > bdb->bi_cache.c_maxsize )
-					efree = bdb->bi_cache.c_minfree;
-
-				if ( count < efree ) {
-					elru->bei_e->e_private = NULL;
-#ifdef SLAP_ZONE_ALLOC
-					bdb_entry_return( bdb, elru->bei_e, elru->bei_zseq );
-#else
-					bdb_entry_return( elru->bei_e );
-#endif
-					elru->bei_e = NULL;
-					count++;
-				} else {
-					/* Keep this node cached, skip to next */
-					bdb_cache_entry_db_unlock( bdb, lockp );
-					goto next;
-				}
-			}
-			bdb_cache_entry_db_unlock( bdb, lockp );
-
-			/* 
-			 * If it is a leaf node, and we're over the limit, free it.
-			 */
-			if ( elru->bei_kids ) {
-				/* Drop from list, we ignore it... */
-				LRU_DEL( &bdb->bi_cache, elru );
-			} else if ( eicount < eifree ) {
-				/* Too many leaf nodes, free this one */
-				bdb_cache_delete_internal( &bdb->bi_cache, elru, 0 );
-				bdb_cache_delete_cleanup( &bdb->bi_cache, elru );
-				islocked = 0;
-				eicount++;
-			}	/* Leave on list until we need to free it */
-		}
-
-next:
-		if ( islocked ) {
-			bdb_cache_entryinfo_unlock( elru );
-			bdb_cache_entryinfo_unlock( elru->bei_parent );
-		}
-
-		if ( count >= efree && eicount >= eifree )
-			break;
-bottom:
-		if ( elnext == bdb->bi_cache.c_lruhead )
-			break;
-#ifdef LDAP_DEBUG
-		iter++;
-#endif
-	}
-
-	if ( count || ecount > bdb->bi_cache.c_cursize ) {
-		ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_count_mutex );
-		/* HACK: we seem to be losing track, fix up now */
-		if ( ecount > bdb->bi_cache.c_cursize )
-			bdb->bi_cache.c_cursize = ecount;
-		bdb->bi_cache.c_cursize -= count;
-		ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_count_mutex );
-	}
-	bdb->bi_cache.c_lruhead = elnext;
-	ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_lru_mutex );
-	bdb->bi_cache.c_purging = 0;
-}
-
-/*
- * cache_find_id - find an entry in the cache, given id.
- * The entry is locked for Read upon return. Call with flag ID_LOCKED if
- * the supplied *eip was already locked.
- */
-
-int
-bdb_cache_find_id(
-	Operation *op,
-	DB_TXN	*tid,
-	ID				id,
-	EntryInfo	**eip,
-	int		flag,
-	DB_LOCK		*lock )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	Entry	*ep = NULL;
-	int	rc = 0, load = 0;
-	EntryInfo ei = { 0 };
-
-	ei.bei_id = id;
-
-#ifdef SLAP_ZONE_ALLOC
-	slap_zh_rlock(bdb->bi_cache.c_zctx);
-#endif
-	/* If we weren't given any info, see if we have it already cached */
-	if ( !*eip ) {
-again:	ldap_pvt_thread_rdwr_rlock( &bdb->bi_cache.c_rwlock );
-		*eip = (EntryInfo *) avl_find( bdb->bi_cache.c_idtree,
-			(caddr_t) &ei, bdb_id_cmp );
-		if ( *eip ) {
-			/* If the lock attempt fails, the info is in use */
-			if ( bdb_cache_entryinfo_trylock( *eip )) {
-				int del = (*eip)->bei_state & CACHE_ENTRY_DELETED;
-				ldap_pvt_thread_rdwr_runlock( &bdb->bi_cache.c_rwlock );
-				/* If this node is being deleted, treat
-				 * as if the delete has already finished
-				 */
-				if ( del ) {
-					return DB_NOTFOUND;
-				}
-				/* otherwise, wait for the info to free up */
-				ldap_pvt_thread_yield();
-				goto again;
-			}
-			/* If this info isn't hooked up to its parent yet,
-			 * unlock and wait for it to be fully initialized
-			 */
-			if ( (*eip)->bei_state & CACHE_ENTRY_NOT_LINKED ) {
-				bdb_cache_entryinfo_unlock( *eip );
-				ldap_pvt_thread_rdwr_runlock( &bdb->bi_cache.c_rwlock );
-				ldap_pvt_thread_yield();
-				goto again;
-			}
-			flag |= ID_LOCKED;
-		}
-		ldap_pvt_thread_rdwr_runlock( &bdb->bi_cache.c_rwlock );
-	}
-
-	/* See if the ID exists in the database; add it to the cache if so */
-	if ( !*eip ) {
-#ifndef BDB_HIER
-		rc = bdb_id2entry( op->o_bd, tid, id, &ep );
-		if ( rc == 0 ) {
-			rc = bdb_cache_find_ndn( op, tid,
-				&ep->e_nname, eip );
-			if ( *eip ) flag |= ID_LOCKED;
-			if ( rc ) {
-				ep->e_private = NULL;
-#ifdef SLAP_ZONE_ALLOC
-				bdb_entry_return( bdb, ep, (*eip)->bei_zseq );
-#else
-				bdb_entry_return( ep );
-#endif
-				ep = NULL;
-			}
-		}
-#else
-		rc = hdb_cache_find_parent(op, tid, id, eip );
-		if ( rc == 0 ) flag |= ID_LOCKED;
-#endif
-	}
-
-	/* Ok, we found the info, do we have the entry? */
-	if ( rc == 0 ) {
-		if ( !( flag & ID_LOCKED )) {
-			bdb_cache_entryinfo_lock( *eip );
-			flag |= ID_LOCKED;
-		}
-
-		if ( (*eip)->bei_state & CACHE_ENTRY_DELETED ) {
-			rc = DB_NOTFOUND;
-		} else {
-			(*eip)->bei_finders++;
-			(*eip)->bei_state |= CACHE_ENTRY_REFERENCED;
-			if ( flag & ID_NOENTRY ) {
-				bdb_cache_entryinfo_unlock( *eip );
-				return 0;
-			}
-			/* Make sure only one thread tries to load the entry */
-load1:
-#ifdef SLAP_ZONE_ALLOC
-			if ((*eip)->bei_e && !slap_zn_validate(
-					bdb->bi_cache.c_zctx, (*eip)->bei_e, (*eip)->bei_zseq)) {
-				(*eip)->bei_e = NULL;
-				(*eip)->bei_zseq = 0;
-			}
-#endif
-			if ( !(*eip)->bei_e && !((*eip)->bei_state & CACHE_ENTRY_LOADING)) {
-				load = 1;
-				(*eip)->bei_state |= CACHE_ENTRY_LOADING;
-				flag |= ID_CHKPURGE;
-			}
-
-			if ( !load ) {
-				/* Clear the uncached state if we are not
-				 * loading it, i.e it is already cached or
-				 * another thread is currently loading it.
-				 */
-				if ( (*eip)->bei_state & CACHE_ENTRY_NOT_CACHED ) {
-					(*eip)->bei_state ^= CACHE_ENTRY_NOT_CACHED;
-					flag |= ID_CHKPURGE;
-				}
-			}
-
-			if ( flag & ID_LOCKED ) {
-				bdb_cache_entryinfo_unlock( *eip );
-				flag ^= ID_LOCKED;
-			}
-			rc = bdb_cache_entry_db_lock( bdb, tid, *eip, load, 0, lock );
-			if ( (*eip)->bei_state & CACHE_ENTRY_DELETED ) {
-				rc = DB_NOTFOUND;
-				bdb_cache_entry_db_unlock( bdb, lock );
-				bdb_cache_entryinfo_lock( *eip );
-				(*eip)->bei_finders--;
-				bdb_cache_entryinfo_unlock( *eip );
-			} else if ( rc == 0 ) {
-				if ( load ) {
-					if ( !ep) {
-						rc = bdb_id2entry( op->o_bd, tid, id, &ep );
-					}
-					if ( rc == 0 ) {
-						ep->e_private = *eip;
-#ifdef BDB_HIER
-						while ( (*eip)->bei_state & CACHE_ENTRY_NOT_LINKED )
-							ldap_pvt_thread_yield();
-						bdb_fix_dn( ep, 0 );
-#endif
-						bdb_cache_entryinfo_lock( *eip );
-
-						(*eip)->bei_e = ep;
-#ifdef SLAP_ZONE_ALLOC
-						(*eip)->bei_zseq = *((ber_len_t *)ep - 2);
-#endif
-						ep = NULL;
-						if ( flag & ID_NOCACHE ) {
-							/* Set the cached state only if no other thread
-							 * found the info while we were loading the entry.
-							 */
-							if ( (*eip)->bei_finders == 1 ) {
-								(*eip)->bei_state |= CACHE_ENTRY_NOT_CACHED;
-								flag ^= ID_CHKPURGE;
-							}
-						}
-						bdb_cache_entryinfo_unlock( *eip );
-						bdb_cache_lru_link( bdb, *eip );
-					}
-					if ( rc == 0 ) {
-						/* If we succeeded, downgrade back to a readlock. */
-						rc = bdb_cache_entry_db_relock( bdb, tid,
-							*eip, 0, 0, lock );
-					} else {
-						/* Otherwise, release the lock. */
-						bdb_cache_entry_db_unlock( bdb, lock );
-					}
-				} else if ( !(*eip)->bei_e ) {
-					/* Some other thread is trying to load the entry,
-					 * wait for it to finish.
-					 */
-					bdb_cache_entry_db_unlock( bdb, lock );
-					bdb_cache_entryinfo_lock( *eip );
-					flag |= ID_LOCKED;
-					goto load1;
-#ifdef BDB_HIER
-				} else {
-					/* Check for subtree renames
-					 */
-					rc = bdb_fix_dn( (*eip)->bei_e, 1 );
-					if ( rc ) {
-						bdb_cache_entry_db_relock( bdb,
-							tid, *eip, 1, 0, lock );
-						/* check again in case other modifier did it already */
-						if ( bdb_fix_dn( (*eip)->bei_e, 1 ) )
-							rc = bdb_fix_dn( (*eip)->bei_e, 2 );
-						bdb_cache_entry_db_relock( bdb,
-							tid, *eip, 0, 0, lock );
-					}
-#endif
-				}
-				bdb_cache_entryinfo_lock( *eip );
-				(*eip)->bei_finders--;
-				if ( load )
-					(*eip)->bei_state ^= CACHE_ENTRY_LOADING;
-				bdb_cache_entryinfo_unlock( *eip );
-			}
-		}
-	}
-	if ( flag & ID_LOCKED ) {
-		bdb_cache_entryinfo_unlock( *eip );
-	}
-	if ( ep ) {
-		ep->e_private = NULL;
-#ifdef SLAP_ZONE_ALLOC
-		bdb_entry_return( bdb, ep, (*eip)->bei_zseq );
-#else
-		bdb_entry_return( ep );
-#endif
-	}
-	if ( rc == 0 ) {
-		int purge = 0;
-
-		if (( flag & ID_CHKPURGE ) || bdb->bi_cache.c_eimax ) {
-			ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_count_mutex );
-			if ( flag & ID_CHKPURGE ) {
-				bdb->bi_cache.c_cursize++;
-				if ( !bdb->bi_cache.c_purging && bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize ) {
-					purge = 1;
-					bdb->bi_cache.c_purging = 1;
-				}
-			} else if ( !bdb->bi_cache.c_purging && bdb->bi_cache.c_eimax && bdb->bi_cache.c_leaves > bdb->bi_cache.c_eimax ) {
-				purge = 1;
-				bdb->bi_cache.c_purging = 1;
-			}
-			ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_count_mutex );
-		}
-		if ( purge )
-			bdb_cache_lru_purge( bdb );
-	}
-
-#ifdef SLAP_ZONE_ALLOC
-	if (rc == 0 && (*eip)->bei_e) {
-		slap_zn_rlock(bdb->bi_cache.c_zctx, (*eip)->bei_e);
-	}
-	slap_zh_runlock(bdb->bi_cache.c_zctx);
-#endif
-	return rc;
-}
-
-int
-bdb_cache_children(
-	Operation *op,
-	DB_TXN *txn,
-	Entry *e )
-{
-	int rc;
-
-	if ( BEI(e)->bei_kids ) {
-		return 0;
-	}
-	if ( BEI(e)->bei_state & CACHE_ENTRY_NO_KIDS ) {
-		return DB_NOTFOUND;
-	}
-	rc = bdb_dn2id_children( op, txn, e );
-	if ( rc == DB_NOTFOUND ) {
-		BEI(e)->bei_state |= CACHE_ENTRY_NO_KIDS | CACHE_ENTRY_NO_GRANDKIDS;
-	}
-	return rc;
-}
-
-/* Update the cache after a successful database Add. */
-int
-bdb_cache_add(
-	struct bdb_info *bdb,
-	EntryInfo *eip,
-	Entry *e,
-	struct berval *nrdn,
-	DB_TXN *txn,
-	DB_LOCK *lock )
-{
-	EntryInfo *new, ei;
-	int rc, purge = 0;
-#ifdef BDB_HIER
-	struct berval rdn = e->e_name;
-#endif
-
-	ei.bei_id = e->e_id;
-	ei.bei_parent = eip;
-	ei.bei_nrdn = *nrdn;
-	ei.bei_lockpad = 0;
-
-#if 0
-	/* Lock this entry so that bdb_add can run to completion.
-	 * It can only fail if BDB has run out of lock resources.
-	 */
-	rc = bdb_cache_entry_db_lock( bdb, txn, &ei, 0, 0, lock );
-	if ( rc ) {
-		bdb_cache_entryinfo_unlock( eip );
-		return rc;
-	}
-#endif
-
-#ifdef BDB_HIER
-	if ( nrdn->bv_len != e->e_nname.bv_len ) {
-		char *ptr = ber_bvchr( &rdn, ',' );
-		assert( ptr != NULL );
-		rdn.bv_len = ptr - rdn.bv_val;
-	}
-	ber_dupbv( &ei.bei_rdn, &rdn );
-	if ( eip->bei_dkids ) eip->bei_dkids++;
-#endif
-
-	if (eip->bei_parent) {
-		bdb_cache_entryinfo_lock( eip->bei_parent );
-		eip->bei_parent->bei_state &= ~CACHE_ENTRY_NO_GRANDKIDS;
-		bdb_cache_entryinfo_unlock( eip->bei_parent );
-	}
-
-	rc = bdb_entryinfo_add_internal( bdb, &ei, &new );
-	/* bdb_csn_commit can cause this when adding the database root entry */
-	if ( new->bei_e ) {
-		new->bei_e->e_private = NULL;
-#ifdef SLAP_ZONE_ALLOC
-		bdb_entry_return( bdb, new->bei_e, new->bei_zseq );
-#else
-		bdb_entry_return( new->bei_e );
-#endif
-	}
-	new->bei_e = e;
-	e->e_private = new;
-	new->bei_state |= CACHE_ENTRY_NO_KIDS | CACHE_ENTRY_NO_GRANDKIDS;
-	eip->bei_state &= ~CACHE_ENTRY_NO_KIDS;
-	bdb_cache_entryinfo_unlock( eip );
-
-	ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
-	ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_count_mutex );
-	++bdb->bi_cache.c_cursize;
-	if ( bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize &&
-		!bdb->bi_cache.c_purging ) {
-		purge = 1;
-		bdb->bi_cache.c_purging = 1;
-	}
-	ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_count_mutex );
-
-	new->bei_finders = 1;
-	bdb_cache_lru_link( bdb, new );
-
-	if ( purge )
-		bdb_cache_lru_purge( bdb );
-
-	return rc;
-}
-
-void bdb_cache_deref(
-	EntryInfo *ei
-	)
-{
-	bdb_cache_entryinfo_lock( ei );
-	ei->bei_finders--;
-	bdb_cache_entryinfo_unlock( ei );
-}
-
-int
-bdb_cache_modify(
-	struct bdb_info *bdb,
-	Entry *e,
-	Attribute *newAttrs,
-	DB_TXN *txn,
-	DB_LOCK *lock )
-{
-	EntryInfo *ei = BEI(e);
-	int rc;
-	/* Get write lock on data */
-	rc = bdb_cache_entry_db_relock( bdb, txn, ei, 1, 0, lock );
-
-	/* If we've done repeated mods on a cached entry, then e_attrs
-	 * is no longer contiguous with the entry, and must be freed.
-	 */
-	if ( ! rc ) {
-		if ( (void *)e->e_attrs != (void *)(e+1) ) {
-			attrs_free( e->e_attrs ); 
-		}
-		e->e_attrs = newAttrs;
-	}
-	return rc;
-}
-
-/*
- * Change the rdn in the entryinfo. Also move to a new parent if needed.
- */
-int
-bdb_cache_modrdn(
-	struct bdb_info *bdb,
-	Entry *e,
-	struct berval *nrdn,
-	Entry *new,
-	EntryInfo *ein,
-	DB_TXN *txn,
-	DB_LOCK *lock )
-{
-	EntryInfo *ei = BEI(e), *pei;
-	int rc;
-#ifdef BDB_HIER
-	struct berval rdn;
-#endif
-
-	/* Get write lock on data */
-	rc =  bdb_cache_entry_db_relock( bdb, txn, ei, 1, 0, lock );
-	if ( rc ) return rc;
-
-	/* If we've done repeated mods on a cached entry, then e_attrs
-	 * is no longer contiguous with the entry, and must be freed.
-	 */
-	if ( (void *)e->e_attrs != (void *)(e+1) ) {
-		attrs_free( e->e_attrs );
-	}
-	e->e_attrs = new->e_attrs;
-	if( e->e_nname.bv_val < e->e_bv.bv_val ||
-		e->e_nname.bv_val > e->e_bv.bv_val + e->e_bv.bv_len )
-	{
-		ch_free(e->e_name.bv_val);
-		ch_free(e->e_nname.bv_val);
-	}
-	e->e_name = new->e_name;
-	e->e_nname = new->e_nname;
-
-	/* Lock the parent's kids AVL tree */
-	pei = ei->bei_parent;
-	bdb_cache_entryinfo_lock( pei );
-	avl_delete( &pei->bei_kids, (caddr_t) ei, bdb_rdn_cmp );
-	free( ei->bei_nrdn.bv_val );
-	ber_dupbv( &ei->bei_nrdn, nrdn );
-
-#ifdef BDB_HIER
-	free( ei->bei_rdn.bv_val );
-
-	rdn = e->e_name;
-	if ( nrdn->bv_len != e->e_nname.bv_len ) {
-		char *ptr = ber_bvchr(&rdn, ',');
-		assert( ptr != NULL );
-		rdn.bv_len = ptr - rdn.bv_val;
-	}
-	ber_dupbv( &ei->bei_rdn, &rdn );
-
-	/* If new parent, decrement kid counts */
-	if ( ein ) {
-		pei->bei_ckids--;
-		if ( pei->bei_dkids ) {
-			pei->bei_dkids--;
-			if ( pei->bei_dkids < 2 )
-				pei->bei_state |= CACHE_ENTRY_NO_KIDS | CACHE_ENTRY_NO_GRANDKIDS;
-		}
-	}
-#endif
-
-	if (!ein) {
-		ein = ei->bei_parent;
-	} else {
-		ei->bei_parent = ein;
-		bdb_cache_entryinfo_unlock( pei );
-		bdb_cache_entryinfo_lock( ein );
-
-		/* new parent now has kids */
-		if ( ein->bei_state & CACHE_ENTRY_NO_KIDS )
-			ein->bei_state ^= CACHE_ENTRY_NO_KIDS;
-		/* grandparent has grandkids */
-		if ( ein->bei_parent )
-			ein->bei_parent->bei_state &= ~CACHE_ENTRY_NO_GRANDKIDS;
-#ifdef BDB_HIER
-		/* parent might now have grandkids */
-		if ( ein->bei_state & CACHE_ENTRY_NO_GRANDKIDS &&
-			!(ei->bei_state & CACHE_ENTRY_NO_KIDS))
-			ein->bei_state ^= CACHE_ENTRY_NO_GRANDKIDS;
-
-		ein->bei_ckids++;
-		if ( ein->bei_dkids ) ein->bei_dkids++;
-#endif
-	}
-
-#ifdef BDB_HIER
-	/* Record the generation number of this change */
-	ldap_pvt_thread_mutex_lock( &bdb->bi_modrdns_mutex );
-	bdb->bi_modrdns++;
-	ei->bei_modrdns = bdb->bi_modrdns;
-	ldap_pvt_thread_mutex_unlock( &bdb->bi_modrdns_mutex );
-#endif
-
-	avl_insert( &ein->bei_kids, ei, bdb_rdn_cmp, avl_dup_error );
-	bdb_cache_entryinfo_unlock( ein );
-	return rc;
-}
-/*
- * cache_delete - delete the entry e from the cache. 
- *
- * returns:	0	e was deleted ok
- *		1	e was not in the cache
- *		-1	something bad happened
- */
-int
-bdb_cache_delete(
-	struct bdb_info *bdb,
-    Entry		*e,
-    DB_TXN *txn,
-    DB_LOCK	*lock )
-{
-	EntryInfo *ei = BEI(e);
-	int	rc, busy = 0, counter = 0;
-
-	assert( e->e_private != NULL );
-
-	/* Lock the entry's info */
-	bdb_cache_entryinfo_lock( ei );
-
-	/* Set this early, warn off any queriers */
-	ei->bei_state |= CACHE_ENTRY_DELETED;
-
-	if (( ei->bei_state & ( CACHE_ENTRY_NOT_LINKED |
-		CACHE_ENTRY_LOADING | CACHE_ENTRY_ONELEVEL )) ||
-		ei->bei_finders > 0 )
-		busy = 1;
-
-	bdb_cache_entryinfo_unlock( ei );
-
-	while ( busy && counter < 1000) {
-		ldap_pvt_thread_yield();
-		busy = 0;
-		bdb_cache_entryinfo_lock( ei );
-		if (( ei->bei_state & ( CACHE_ENTRY_NOT_LINKED |
-			CACHE_ENTRY_LOADING | CACHE_ENTRY_ONELEVEL )) ||
-			ei->bei_finders > 0 )
-			busy = 1;
-		bdb_cache_entryinfo_unlock( ei );
-		counter ++;
-	}
-	if( busy ) {
-		bdb_cache_entryinfo_lock( ei );
-		ei->bei_state ^= CACHE_ENTRY_DELETED;
-		bdb_cache_entryinfo_unlock( ei );
-		return DB_LOCK_DEADLOCK;
-	}
-
-	/* Get write lock on the data */
-	rc = bdb_cache_entry_db_relock( bdb, txn, ei, 1, 0, lock );
-	if ( rc ) {
-		bdb_cache_entryinfo_lock( ei );
-		/* couldn't lock, undo and give up */
-		ei->bei_state ^= CACHE_ENTRY_DELETED;
-		bdb_cache_entryinfo_unlock( ei );
-		return rc;
-	}
-
-	Debug( LDAP_DEBUG_TRACE, "====> bdb_cache_delete( %ld )\n",
-		e->e_id, 0, 0 );
-
-	/* set lru mutex */
-	ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_lru_mutex );
-
-	bdb_cache_entryinfo_lock( ei->bei_parent );
-	bdb_cache_entryinfo_lock( ei );
-	rc = bdb_cache_delete_internal( &bdb->bi_cache, e->e_private, 1 );
-	bdb_cache_entryinfo_unlock( ei );
-
-	/* free lru mutex */
-	ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_lru_mutex );
-
-	return( rc );
-}
-
-void
-bdb_cache_delete_cleanup(
-	Cache *cache,
-	EntryInfo *ei )
-{
-	/* Enter with ei locked */
-
-	/* already freed? */
-	if ( !ei->bei_parent ) return;
-
-	if ( ei->bei_e ) {
-		ei->bei_e->e_private = NULL;
-#ifdef SLAP_ZONE_ALLOC
-		bdb_entry_return( ei->bei_bdb, ei->bei_e, ei->bei_zseq );
-#else
-		bdb_entry_return( ei->bei_e );
-#endif
-		ei->bei_e = NULL;
-	}
-
-	bdb_cache_entryinfo_unlock( ei );
-	bdb_cache_entryinfo_free( cache, ei );
-}
-
-static int
-bdb_cache_delete_internal(
-    Cache	*cache,
-    EntryInfo		*e,
-    int		decr )
-{
-	int rc = 0;	/* return code */
-	int decr_leaf = 0;
-
-	/* already freed? */
-	if ( !e->bei_parent ) {
-		assert(0);
-		return -1;
-	}
-
-#ifdef BDB_HIER
-	e->bei_parent->bei_ckids--;
-	if ( decr && e->bei_parent->bei_dkids ) e->bei_parent->bei_dkids--;
-#endif
-	/* dn tree */
-	if ( avl_delete( &e->bei_parent->bei_kids, (caddr_t) e, bdb_rdn_cmp )
-		== NULL )
-	{
-		rc = -1;
-		assert(0);
-	}
-	if ( e->bei_parent->bei_kids )
-		decr_leaf = 1;
-
-	ldap_pvt_thread_rdwr_wlock( &cache->c_rwlock );
-	/* id tree */
-	if ( avl_delete( &cache->c_idtree, (caddr_t) e, bdb_id_cmp )) {
-		cache->c_eiused--;
-		if ( decr_leaf )
-			cache->c_leaves--;
-	} else {
-		rc = -1;
-		assert(0);
-	}
-	ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
-	bdb_cache_entryinfo_unlock( e->bei_parent );
-
-	if ( rc == 0 ){
-		/* lru */
-		LRU_DEL( cache, e );
-
-		if ( e->bei_e ) {
-			ldap_pvt_thread_mutex_lock( &cache->c_count_mutex );
-			cache->c_cursize--;
-			ldap_pvt_thread_mutex_unlock( &cache->c_count_mutex );
-		}
-	}
-
-	return( rc );
-}
-
-static void
-bdb_entryinfo_release( void *data )
-{
-	EntryInfo *ei = (EntryInfo *)data;
-	if ( ei->bei_kids ) {
-		avl_free( ei->bei_kids, NULL );
-	}
-	if ( ei->bei_e ) {
-		ei->bei_e->e_private = NULL;
-#ifdef SLAP_ZONE_ALLOC
-		bdb_entry_return( ei->bei_bdb, ei->bei_e, ei->bei_zseq );
-#else
-		bdb_entry_return( ei->bei_e );
-#endif
-	}
-	bdb_cache_entryinfo_destroy( ei );
-}
-
-void
-bdb_cache_release_all( Cache *cache )
-{
-	/* set cache write lock */
-	ldap_pvt_thread_rdwr_wlock( &cache->c_rwlock );
-	/* set lru mutex */
-	ldap_pvt_thread_mutex_lock( &cache->c_lru_mutex );
-
-	Debug( LDAP_DEBUG_TRACE, "====> bdb_cache_release_all\n", 0, 0, 0 );
-
-	avl_free( cache->c_dntree.bei_kids, NULL );
-	avl_free( cache->c_idtree, bdb_entryinfo_release );
-	for (;cache->c_eifree;cache->c_eifree = cache->c_lruhead) {
-		cache->c_lruhead = cache->c_eifree->bei_lrunext;
-		bdb_cache_entryinfo_destroy(cache->c_eifree);
-	}
-	cache->c_cursize = 0;
-	cache->c_eiused = 0;
-	cache->c_leaves = 0;
-	cache->c_idtree = NULL;
-	cache->c_lruhead = NULL;
-	cache->c_lrutail = NULL;
-	cache->c_dntree.bei_kids = NULL;
-
-	/* free lru mutex */
-	ldap_pvt_thread_mutex_unlock( &cache->c_lru_mutex );
-	/* free cache write lock */
-	ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
-}
-
-#ifdef LDAP_DEBUG
-static void
-bdb_lru_count( Cache *cache )
-{
-	EntryInfo	*e;
-	int ei = 0, ent = 0, nc = 0;
-
-	for ( e = cache->c_lrutail; ; ) {
-		ei++;
-		if ( e->bei_e ) {
-			ent++;
-			if ( e->bei_state & CACHE_ENTRY_NOT_CACHED )
-				nc++;
-			fprintf( stderr, "ei %d entry %p dn %s\n", ei, (void *) e->bei_e, e->bei_e->e_name.bv_val );
-		}
-		e = e->bei_lrunext;
-		if ( e == cache->c_lrutail )
-			break;
-	}
-	fprintf( stderr, "counted %d entryInfos and %d entries, %d notcached\n",
-		ei, ent, nc );
-	ei = 0;
-	for ( e = cache->c_lrutail; ; ) {
-		ei++;
-		e = e->bei_lruprev;
-		if ( e == cache->c_lrutail )
-			break;
-	}
-	fprintf( stderr, "counted %d entryInfos (on lruprev)\n", ei );
-}
-
-#ifdef SLAPD_UNUSED
-static void
-bdb_lru_print( Cache *cache )
-{
-	EntryInfo	*e;
-
-	fprintf( stderr, "LRU circle head: %p\n", (void *) cache->c_lruhead );
-	fprintf( stderr, "LRU circle (tail forward):\n" );
-	for ( e = cache->c_lrutail; ; ) {
-		fprintf( stderr, "\t%p, %p id %ld rdn \"%s\"\n",
-			(void *) e, (void *) e->bei_e, e->bei_id, e->bei_nrdn.bv_val );
-		e = e->bei_lrunext;
-		if ( e == cache->c_lrutail )
-			break;
-	}
-	fprintf( stderr, "LRU circle (tail backward):\n" );
-	for ( e = cache->c_lrutail; ; ) {
-		fprintf( stderr, "\t%p, %p id %ld rdn \"%s\"\n",
-			(void *) e, (void *) e->bei_e, e->bei_id, e->bei_nrdn.bv_val );
-		e = e->bei_lruprev;
-		if ( e == cache->c_lrutail )
-			break;
-	}
-}
-
-static int
-bdb_entryinfo_print(void *data, void *arg)
-{
-	EntryInfo *e = data;
-	fprintf( stderr, "\t%p, %p id %ld rdn \"%s\"\n",
-		(void *) e, (void *) e->bei_e, e->bei_id, e->bei_nrdn.bv_val );
-	return 0;
-}
-
-static void
-bdb_idtree_print(Cache *cache)
-{
-	avl_apply( cache->c_idtree, bdb_entryinfo_print, NULL, -1, AVL_INORDER );
-}
-#endif
-#endif
-
-static void
-bdb_reader_free( void *key, void *data )
-{
-	/* DB_ENV *env = key; */
-	DB_TXN *txn = data;
-
-	if ( txn ) TXN_ABORT( txn );
-}
-
-/* free up any keys used by the main thread */
-void
-bdb_reader_flush( DB_ENV *env )
-{
-	void *data;
-	void *ctx = ldap_pvt_thread_pool_context();
-
-	if ( !ldap_pvt_thread_pool_getkey( ctx, env, &data, NULL ) ) {
-		ldap_pvt_thread_pool_setkey( ctx, env, NULL, 0, NULL, NULL );
-		bdb_reader_free( env, data );
-	}
-}
-
-int
-bdb_reader_get( Operation *op, DB_ENV *env, DB_TXN **txn )
-{
-	int i, rc;
-	void *data;
-	void *ctx;
-
-	if ( !env || !txn ) return -1;
-
-	/* If no op was provided, try to find the ctx anyway... */
-	if ( op ) {
-		ctx = op->o_threadctx;
-	} else {
-		ctx = ldap_pvt_thread_pool_context();
-	}
-
-	/* Shouldn't happen unless we're single-threaded */
-	if ( !ctx ) {
-		*txn = NULL;
-		return 0;
-	}
-
-	if ( ldap_pvt_thread_pool_getkey( ctx, env, &data, NULL ) ) {
-		for ( i=0, rc=1; rc != 0 && i<4; i++ ) {
-			rc = TXN_BEGIN( env, NULL, txn, DB_READ_COMMITTED );
-			if (rc) ldap_pvt_thread_yield();
-		}
-		if ( rc != 0) {
-			return rc;
-		}
-		data = *txn;
-		if ( ( rc = ldap_pvt_thread_pool_setkey( ctx, env,
-			data, bdb_reader_free, NULL, NULL ) ) ) {
-			TXN_ABORT( *txn );
-			Debug( LDAP_DEBUG_ANY, "bdb_reader_get: err %s(%d)\n",
-				db_strerror(rc), rc, 0 );
-
-			return rc;
-		}
-	} else {
-		*txn = data;
-	}
-	return 0;
-}
diff --git a/servers/slapd/back-bdb/compare.c b/servers/slapd/back-bdb/compare.c
deleted file mode 100644
index 4d7d45f..0000000
--- a/servers/slapd/back-bdb/compare.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/* compare.c - bdb backend compare routine */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "back-bdb.h"
-
-int
-bdb_compare( Operation *op, SlapReply *rs )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	Entry		*e = NULL;
-	EntryInfo	*ei;
-	int		manageDSAit = get_manageDSAit( op );
-
-	DB_TXN		*rtxn;
-	DB_LOCK		lock;
-
-	rs->sr_err = bdb_reader_get(op, bdb->bi_dbenv, &rtxn);
-	switch(rs->sr_err) {
-	case 0:
-		break;
-	default:
-		send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
-		return rs->sr_err;
-	}
-
-dn2entry_retry:
-	/* get entry */
-	rs->sr_err = bdb_dn2entry( op, rtxn, &op->o_req_ndn, &ei, 1,
-		&lock );
-
-	switch( rs->sr_err ) {
-	case DB_NOTFOUND:
-	case 0:
-		break;
-	case LDAP_BUSY:
-		rs->sr_text = "ldap server busy";
-		goto return_results;
-	case DB_LOCK_DEADLOCK:
-	case DB_LOCK_NOTGRANTED:
-		goto dn2entry_retry;
-	default:
-		rs->sr_err = LDAP_OTHER;
-		rs->sr_text = "internal error";
-		goto return_results;
-	}
-
-	e = ei->bei_e;
-	if ( rs->sr_err == DB_NOTFOUND ) {
-		if ( e != NULL ) {
-			/* return referral only if "disclose" is granted on the object */
-			if ( ! access_allowed( op, e, slap_schema.si_ad_entry,
-				NULL, ACL_DISCLOSE, NULL ) )
-			{
-				rs->sr_err = LDAP_NO_SUCH_OBJECT;
-
-			} else {
-				rs->sr_matched = ch_strdup( e->e_dn );
-				rs->sr_ref = is_entry_referral( e )
-					? get_entry_referrals( op, e )
-					: NULL;
-				rs->sr_err = LDAP_REFERRAL;
-			}
-
-			bdb_cache_return_entry_r( bdb, e, &lock );
-			e = NULL;
-
-		} else {
-			rs->sr_ref = referral_rewrite( default_referral,
-				NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
-			rs->sr_err = rs->sr_ref ? LDAP_REFERRAL : LDAP_NO_SUCH_OBJECT;
-		}
-
-		send_ldap_result( op, rs );
-
-		ber_bvarray_free( rs->sr_ref );
-		free( (char *)rs->sr_matched );
-		rs->sr_ref = NULL;
-		rs->sr_matched = NULL;
-
-		goto done;
-	}
-
-	if (!manageDSAit && is_entry_referral( e ) ) {
-		/* return referral only if "disclose" is granted on the object */
-		if ( !access_allowed( op, e, slap_schema.si_ad_entry,
-			NULL, ACL_DISCLOSE, NULL ) )
-		{
-			rs->sr_err = LDAP_NO_SUCH_OBJECT;
-		} else {
-			/* entry is a referral, don't allow compare */
-			rs->sr_ref = get_entry_referrals( op, e );
-			rs->sr_err = LDAP_REFERRAL;
-			rs->sr_matched = e->e_name.bv_val;
-		}
-
-		Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 );
-
-		send_ldap_result( op, rs );
-
-		ber_bvarray_free( rs->sr_ref );
-		rs->sr_ref = NULL;
-		rs->sr_matched = NULL;
-		goto done;
-	}
-
-	rs->sr_err = slap_compare_entry( op, e, op->orc_ava );
-
-return_results:
-	send_ldap_result( op, rs );
-
-	switch ( rs->sr_err ) {
-	case LDAP_COMPARE_FALSE:
-	case LDAP_COMPARE_TRUE:
-		rs->sr_err = LDAP_SUCCESS;
-		break;
-	}
-
-done:
-	/* free entry */
-	if ( e != NULL ) {
-		bdb_cache_return_entry_r( bdb, e, &lock );
-	}
-
-	return rs->sr_err;
-}
diff --git a/servers/slapd/back-bdb/config.c b/servers/slapd/back-bdb/config.c
deleted file mode 100644
index c3c8315..0000000
--- a/servers/slapd/back-bdb/config.c
+++ /dev/null
@@ -1,951 +0,0 @@
-/* config.c - bdb backend configuration file routine */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/ctype.h>
-#include <ac/string.h>
-#include <ac/errno.h>
-
-#include "back-bdb.h"
-
-#include "config.h"
-
-#include "lutil.h"
-#include "ldap_rq.h"
-
-#ifdef DB_DIRTY_READ
-#	define	SLAP_BDB_ALLOW_DIRTY_READ
-#endif
-
-#define bdb_cf_gen		BDB_SYMBOL(cf_gen)
-#define	bdb_cf_cleanup		BDB_SYMBOL(cf_cleanup)
-#define bdb_checkpoint		BDB_SYMBOL(checkpoint)
-#define bdb_online_index	BDB_SYMBOL(online_index)
-
-static ConfigDriver bdb_cf_gen;
-
-enum {
-	BDB_CHKPT = 1,
-	BDB_CONFIG,
-	BDB_CRYPTFILE,
-	BDB_CRYPTKEY,
-	BDB_DIRECTORY,
-	BDB_NOSYNC,
-	BDB_DIRTYR,
-	BDB_INDEX,
-	BDB_LOCKD,
-	BDB_SSTACK,
-	BDB_MODE,
-	BDB_PGSIZE,
-	BDB_CHECKSUM
-};
-
-static ConfigTable bdbcfg[] = {
-	{ "directory", "dir", 2, 2, 0, ARG_STRING|ARG_MAGIC|BDB_DIRECTORY,
-		bdb_cf_gen, "( OLcfgDbAt:0.1 NAME 'olcDbDirectory' "
-			"DESC 'Directory for database content' "
-			"EQUALITY caseIgnoreMatch "
-			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
-	{ "cachefree", "size", 2, 2, 0, ARG_ULONG|ARG_OFFSET,
-		(void *)offsetof(struct bdb_info, bi_cache.c_minfree),
-		"( OLcfgDbAt:1.11 NAME 'olcDbCacheFree' "
-			"DESC 'Number of extra entries to free when max is reached' "
-			"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
-	{ "cachesize", "size", 2, 2, 0, ARG_ULONG|ARG_OFFSET,
-		(void *)offsetof(struct bdb_info, bi_cache.c_maxsize),
-		"( OLcfgDbAt:1.1 NAME 'olcDbCacheSize' "
-			"DESC 'Entry cache size in entries' "
-			"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
-	{ "checkpoint", "kbyte> <min", 3, 3, 0, ARG_MAGIC|BDB_CHKPT,
-		bdb_cf_gen, "( OLcfgDbAt:1.2 NAME 'olcDbCheckpoint' "
-			"DESC 'Database checkpoint interval in kbytes and minutes' "
-			"SYNTAX OMsDirectoryString SINGLE-VALUE )",NULL, NULL },
-	{ "checksum", NULL, 1, 2, 0, ARG_ON_OFF|ARG_MAGIC|BDB_CHECKSUM,
-		bdb_cf_gen, "( OLcfgDbAt:1.16 NAME 'olcDbChecksum' "
-			"DESC 'Enable database checksum validation' "
-			"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
-	{ "cryptfile", "file", 2, 2, 0, ARG_STRING|ARG_MAGIC|BDB_CRYPTFILE,
-		bdb_cf_gen, "( OLcfgDbAt:1.13 NAME 'olcDbCryptFile' "
-			"DESC 'Pathname of file containing the DB encryption key' "
-			"SYNTAX OMsDirectoryString SINGLE-VALUE )",NULL, NULL },
-	{ "cryptkey", "key", 2, 2, 0, ARG_BERVAL|ARG_MAGIC|BDB_CRYPTKEY,
-		bdb_cf_gen, "( OLcfgDbAt:1.14 NAME 'olcDbCryptKey' "
-			"DESC 'DB encryption key' "
-			"SYNTAX OMsOctetString SINGLE-VALUE )",NULL, NULL },
-	{ "dbconfig", "DB_CONFIG setting", 1, 0, 0, ARG_MAGIC|BDB_CONFIG,
-		bdb_cf_gen, "( OLcfgDbAt:1.3 NAME 'olcDbConfig' "
-			"DESC 'BerkeleyDB DB_CONFIG configuration directives' "
-			"SYNTAX OMsIA5String X-ORDERED 'VALUES' )", NULL, NULL },
-	{ "dbnosync", NULL, 1, 2, 0, ARG_ON_OFF|ARG_MAGIC|BDB_NOSYNC,
-		bdb_cf_gen, "( OLcfgDbAt:1.4 NAME 'olcDbNoSync' "
-			"DESC 'Disable synchronous database writes' "
-			"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
-	{ "dbpagesize", "db> <size", 3, 3, 0, ARG_MAGIC|BDB_PGSIZE,
-		bdb_cf_gen, "( OLcfgDbAt:1.15 NAME 'olcDbPageSize' "
-			"DESC 'Page size of specified DB, in Kbytes' "
-			"EQUALITY caseExactMatch "
-			"SYNTAX OMsDirectoryString )", NULL, NULL },
-	{ "dirtyread", NULL, 1, 2, 0,
-#ifdef SLAP_BDB_ALLOW_DIRTY_READ
-		ARG_ON_OFF|ARG_MAGIC|BDB_DIRTYR, bdb_cf_gen,
-#else
-		ARG_IGNORED, NULL,
-#endif
-		"( OLcfgDbAt:1.5 NAME 'olcDbDirtyRead' "
-		"DESC 'Allow reads of uncommitted data' "
-		"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
-	{ "dncachesize", "size", 2, 2, 0, ARG_ULONG|ARG_OFFSET,
-		(void *)offsetof(struct bdb_info, bi_cache.c_eimax),
-		"( OLcfgDbAt:1.12 NAME 'olcDbDNcacheSize' "
-			"DESC 'DN cache size' "
-			"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
-	{ "idlcachesize", "size", 2, 2, 0, ARG_ULONG|ARG_OFFSET,
-		(void *)offsetof(struct bdb_info, bi_idl_cache_max_size),
-		"( OLcfgDbAt:1.6 NAME 'olcDbIDLcacheSize' "
-		"DESC 'IDL cache size in IDLs' "
-		"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
-	{ "index", "attr> <[pres,eq,approx,sub]", 2, 3, 0, ARG_MAGIC|BDB_INDEX,
-		bdb_cf_gen, "( OLcfgDbAt:0.2 NAME 'olcDbIndex' "
-		"DESC 'Attribute index parameters' "
-		"EQUALITY caseIgnoreMatch "
-		"SYNTAX OMsDirectoryString )", NULL, NULL },
-	{ "linearindex", NULL, 1, 2, 0, ARG_ON_OFF|ARG_OFFSET,
-		(void *)offsetof(struct bdb_info, bi_linear_index), 
-		"( OLcfgDbAt:1.7 NAME 'olcDbLinearIndex' "
-		"DESC 'Index attributes one at a time' "
-		"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
-	{ "lockdetect", "policy", 2, 2, 0, ARG_MAGIC|BDB_LOCKD,
-		bdb_cf_gen, "( OLcfgDbAt:1.8 NAME 'olcDbLockDetect' "
-		"DESC 'Deadlock detection algorithm' "
-		"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
-	{ "mode", "mode", 2, 2, 0, ARG_MAGIC|BDB_MODE,
-		bdb_cf_gen, "( OLcfgDbAt:0.3 NAME 'olcDbMode' "
-		"DESC 'Unix permissions of database files' "
-		"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
-	{ "searchstack", "depth", 2, 2, 0, ARG_INT|ARG_MAGIC|BDB_SSTACK,
-		bdb_cf_gen, "( OLcfgDbAt:1.9 NAME 'olcDbSearchStack' "
-		"DESC 'Depth of search stack in IDLs' "
-		"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
-	{ "shm_key", "key", 2, 2, 0, ARG_LONG|ARG_OFFSET,
-		(void *)offsetof(struct bdb_info, bi_shm_key), 
-		"( OLcfgDbAt:1.10 NAME 'olcDbShmKey' "
-		"DESC 'Key for shared memory region' "
-		"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
-	{ NULL, NULL, 0, 0, 0, ARG_IGNORED,
-		NULL, NULL, NULL, NULL }
-};
-
-static ConfigOCs bdbocs[] = {
-	{
-#ifdef BDB_HIER
-		"( OLcfgDbOc:1.2 "
-		"NAME 'olcHdbConfig' "
-		"DESC 'HDB backend configuration' "
-#else
-		"( OLcfgDbOc:1.1 "
-		"NAME 'olcBdbConfig' "
-		"DESC 'BDB backend configuration' "
-#endif
-		"SUP olcDatabaseConfig "
-		"MUST olcDbDirectory "
-		"MAY ( olcDbCacheSize $ olcDbCheckpoint $ olcDbChecksum $ "
-		"olcDbConfig $ olcDbCryptFile $ olcDbCryptKey $ "
-		"olcDbNoSync $ olcDbDirtyRead $ olcDbIDLcacheSize $ "
-		"olcDbIndex $ olcDbLinearIndex $ olcDbLockDetect $ "
-		"olcDbMode $ olcDbSearchStack $ olcDbShmKey $ "
-		"olcDbCacheFree $ olcDbDNcacheSize $ olcDbPageSize ) )",
-		 	Cft_Database, bdbcfg },
-	{ NULL, 0, NULL }
-};
-
-static slap_verbmasks bdb_lockd[] = {
-	{ BER_BVC("default"), DB_LOCK_DEFAULT },
-	{ BER_BVC("oldest"), DB_LOCK_OLDEST },
-	{ BER_BVC("random"), DB_LOCK_RANDOM },
-	{ BER_BVC("youngest"), DB_LOCK_YOUNGEST },
-	{ BER_BVC("fewest"), DB_LOCK_MINLOCKS },
-	{ BER_BVNULL, 0 }
-};
-
-/* perform periodic checkpoints */
-static void *
-bdb_checkpoint( void *ctx, void *arg )
-{
-	struct re_s *rtask = arg;
-	struct bdb_info *bdb = rtask->arg;
-	
-	TXN_CHECKPOINT( bdb->bi_dbenv, bdb->bi_txn_cp_kbyte,
-		bdb->bi_txn_cp_min, 0 );
-	ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
-	ldap_pvt_runqueue_stoptask( &slapd_rq, rtask );
-	ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
-	return NULL;
-}
-
-/* reindex entries on the fly */
-static void *
-bdb_online_index( void *ctx, void *arg )
-{
-	struct re_s *rtask = arg;
-	BackendDB *be = rtask->arg;
-	struct bdb_info *bdb = be->be_private;
-
-	Connection conn = {0};
-	OperationBuffer opbuf;
-	Operation *op;
-
-	DBC *curs;
-	DBT key, data;
-	DB_TXN *txn;
-	DB_LOCK lock;
-	ID id, nid;
-	EntryInfo *ei;
-	int rc, getnext = 1;
-	int i;
-
-	connection_fake_init( &conn, &opbuf, ctx );
-	op = &opbuf.ob_op;
-
-	op->o_bd = be;
-
-	DBTzero( &key );
-	DBTzero( &data );
-	
-	id = 1;
-	key.data = &nid;
-	key.size = key.ulen = sizeof(ID);
-	key.flags = DB_DBT_USERMEM;
-
-	data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
-	data.dlen = data.ulen = 0;
-
-	while ( 1 ) {
-		if ( slapd_shutdown )
-			break;
-
-		rc = TXN_BEGIN( bdb->bi_dbenv, NULL, &txn, bdb->bi_db_opflags );
-		if ( rc ) 
-			break;
-		Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_online_index) ": txn id: %x\n",
-			txn->id(txn), 0, 0 );
-		if ( getnext ) {
-			getnext = 0;
-			BDB_ID2DISK( id, &nid );
-			rc = bdb->bi_id2entry->bdi_db->cursor(
-				bdb->bi_id2entry->bdi_db, txn, &curs, bdb->bi_db_opflags );
-			if ( rc ) {
-				TXN_ABORT( txn );
-				break;
-			}
-			rc = curs->c_get( curs, &key, &data, DB_SET_RANGE );
-			curs->c_close( curs );
-			if ( rc ) {
-				TXN_ABORT( txn );
-				if ( rc == DB_NOTFOUND )
-					rc = 0;
-				if ( rc == DB_LOCK_DEADLOCK ) {
-					ldap_pvt_thread_yield();
-					continue;
-				}
-				break;
-			}
-			BDB_DISK2ID( &nid, &id );
-		}
-
-		ei = NULL;
-		rc = bdb_cache_find_id( op, txn, id, &ei, 0, &lock );
-		if ( rc ) {
-			TXN_ABORT( txn );
-			if ( rc == DB_LOCK_DEADLOCK ) {
-				ldap_pvt_thread_yield();
-				continue;
-			}
-			if ( rc == DB_NOTFOUND ) {
-				id++;
-				getnext = 1;
-				continue;
-			}
-			break;
-		}
-		if ( ei->bei_e ) {
-			rc = bdb_index_entry( op, txn, BDB_INDEX_UPDATE_OP, ei->bei_e );
-			if ( rc ) {
-				TXN_ABORT( txn );
-				if ( rc == DB_LOCK_DEADLOCK ) {
-					ldap_pvt_thread_yield();
-					continue;
-				}
-				break;
-			}
-			rc = TXN_COMMIT( txn, 0 );
-			txn = NULL;
-		}
-		id++;
-		getnext = 1;
-	}
-
-	for ( i = 0; i < bdb->bi_nattrs; i++ ) {
-		if ( bdb->bi_attrs[ i ]->ai_indexmask & BDB_INDEX_DELETING
-			|| bdb->bi_attrs[ i ]->ai_newmask == 0 )
-		{
-			continue;
-		}
-		bdb->bi_attrs[ i ]->ai_indexmask = bdb->bi_attrs[ i ]->ai_newmask;
-		bdb->bi_attrs[ i ]->ai_newmask = 0;
-	}
-
-	ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
-	ldap_pvt_runqueue_stoptask( &slapd_rq, rtask );
-	bdb->bi_index_task = NULL;
-	ldap_pvt_runqueue_remove( &slapd_rq, rtask );
-	ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
-
-	return NULL;
-}
-
-/* Cleanup loose ends after Modify completes */
-static int
-bdb_cf_cleanup( ConfigArgs *c )
-{
-	struct bdb_info *bdb = c->be->be_private;
-	int rc = 0;
-	BerVarray bva;
-
-	if ( bdb->bi_flags & BDB_DEL_INDEX ) {
-		bdb_attr_flush( bdb );
-		bdb->bi_flags ^= BDB_DEL_INDEX;
-	}
-
-	if ( bdb->bi_flags & BDB_RE_OPEN ) {
-		bdb->bi_flags ^= BDB_RE_OPEN;
-		bva = bdb->bi_db_config;
-		bdb->bi_db_config = NULL;
-		rc = c->be->bd_info->bi_db_close( c->be, &c->reply );
-		if ( rc == 0 ) {
-			if ( bdb->bi_flags & BDB_UPD_CONFIG ) {
-				if ( bva ) {
-					int i;
-					FILE *f = fopen( bdb->bi_db_config_path, "w" );
-					if ( f ) {
-						bdb->bi_db_config = bva;
-						bva = NULL;
-						for (i=0; bdb->bi_db_config[i].bv_val; i++)
-							fprintf( f, "%s\n", bdb->bi_db_config[i].bv_val );
-						fclose( f );
-					} else {
-						ber_bvarray_free( bva );
-					}
-				} else {
-					unlink( bdb->bi_db_config_path );
-				}
-				bdb->bi_flags ^= BDB_UPD_CONFIG;
-			}
-			rc = c->be->bd_info->bi_db_open( c->be, &c->reply );
-		}
-		/* If this fails, we need to restart */
-		if ( rc ) {
-			slapd_shutdown = 2;
-			snprintf( c->cr_msg, sizeof( c->cr_msg ),
-				"failed to reopen database, rc=%d", rc );
-			Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_cf_cleanup)
-				": %s\n", c->cr_msg, 0, 0 );
-			rc = LDAP_OTHER;
-		}
-	}
-	return rc;
-}
-
-static int
-bdb_cf_gen( ConfigArgs *c )
-{
-	struct bdb_info *bdb = c->be->be_private;
-	int rc;
-
-	if ( c->op == SLAP_CONFIG_EMIT ) {
-		rc = 0;
-		switch( c->type ) {
-		case BDB_MODE: {
-			char buf[64];
-			struct berval bv;
-			bv.bv_len = snprintf( buf, sizeof(buf), "0%o", bdb->bi_dbenv_mode );
-			if ( bv.bv_len > 0 && bv.bv_len < sizeof(buf) ) {
-				bv.bv_val = buf;
-				value_add_one( &c->rvalue_vals, &bv );
-			} else {
-				rc = 1;
-			}
-			} break;
-
-		case BDB_CHKPT:
-			if ( bdb->bi_txn_cp ) {
-				char buf[64];
-				struct berval bv;
-				bv.bv_len = snprintf( buf, sizeof(buf), "%ld %ld",
-					(long) bdb->bi_txn_cp_kbyte, (long) bdb->bi_txn_cp_min );
-				if ( bv.bv_len > 0 && bv.bv_len < sizeof(buf) ) {
-					bv.bv_val = buf;
-					value_add_one( &c->rvalue_vals, &bv );
-				} else {
-					rc = 1;
-				}
-			} else {
-				rc = 1;
-			}
-			break;
-
-		case BDB_CRYPTFILE:
-			if ( bdb->bi_db_crypt_file ) {
-				c->value_string = ch_strdup( bdb->bi_db_crypt_file );
-			} else {
-				rc = 1;
-			}
-			break;
-
-		/* If a crypt file has been set, its contents are copied here.
-		 * But we don't want the key to be incorporated here.
-		 */
-		case BDB_CRYPTKEY:
-			if ( !bdb->bi_db_crypt_file && !BER_BVISNULL( &bdb->bi_db_crypt_key )) {
-				value_add_one( &c->rvalue_vals, &bdb->bi_db_crypt_key );
-			} else {
-				rc = 1;
-			}
-			break;
-
-		case BDB_DIRECTORY:
-			if ( bdb->bi_dbenv_home ) {
-				c->value_string = ch_strdup( bdb->bi_dbenv_home );
-			} else {
-				rc = 1;
-			}
-			break;
-
-		case BDB_CONFIG:
-			if ( !( bdb->bi_flags & BDB_IS_OPEN )
-				&& !bdb->bi_db_config )
-			{
-				char	buf[SLAP_TEXT_BUFLEN];
-				FILE *f = fopen( bdb->bi_db_config_path, "r" );
-				struct berval bv;
-
-				if ( f ) {
-					bdb->bi_flags |= BDB_HAS_CONFIG;
-					while ( fgets( buf, sizeof(buf), f )) {
-						ber_str2bv( buf, 0, 1, &bv );
-						if ( bv.bv_len > 0 && bv.bv_val[bv.bv_len-1] == '\n' ) {
-							bv.bv_len--;
-							bv.bv_val[bv.bv_len] = '\0';
-						}
-						/* shouldn't need this, but ... */
-						if ( bv.bv_len > 0 && bv.bv_val[bv.bv_len-1] == '\r' ) {
-							bv.bv_len--;
-							bv.bv_val[bv.bv_len] = '\0';
-						}
-						ber_bvarray_add( &bdb->bi_db_config, &bv );
-					}
-					fclose( f );
-				}
-			}
-			if ( bdb->bi_db_config ) {
-				int i;
-				struct berval bv;
-
-				bv.bv_val = c->log;
-				for (i=0; !BER_BVISNULL(&bdb->bi_db_config[i]); i++) {
-					bv.bv_len = sprintf( bv.bv_val, "{%d}%s", i,
-						bdb->bi_db_config[i].bv_val );
-					value_add_one( &c->rvalue_vals, &bv );
-				}
-			}
-			if ( !c->rvalue_vals ) rc = 1;
-			break;
-
-		case BDB_NOSYNC:
-			if ( bdb->bi_dbenv_xflags & DB_TXN_NOSYNC )
-				c->value_int = 1;
-			break;
-			
-		case BDB_CHECKSUM:
-			if ( bdb->bi_flags & BDB_CHKSUM )
-				c->value_int = 1;
-			break;
-
-		case BDB_INDEX:
-			bdb_attr_index_unparse( bdb, &c->rvalue_vals );
-			if ( !c->rvalue_vals ) rc = 1;
-			break;
-
-		case BDB_LOCKD:
-			rc = 1;
-			if ( bdb->bi_lock_detect != DB_LOCK_DEFAULT ) {
-				int i;
-				for (i=0; !BER_BVISNULL(&bdb_lockd[i].word); i++) {
-					if ( bdb->bi_lock_detect == (u_int32_t)bdb_lockd[i].mask ) {
-						value_add_one( &c->rvalue_vals, &bdb_lockd[i].word );
-						rc = 0;
-						break;
-					}
-				}
-			}
-			break;
-
-		case BDB_SSTACK:
-			c->value_int = bdb->bi_search_stack_depth;
-			break;
-
-		case BDB_PGSIZE: {
-				struct bdb_db_pgsize *ps;
-				char buf[SLAP_TEXT_BUFLEN];
-				struct berval bv;
-				int rc = 1;
-
-				bv.bv_val = buf;
-				for ( ps = bdb->bi_pagesizes; ps; ps = ps->bdp_next ) {
-					bv.bv_len = sprintf( buf, "%s %d", ps->bdp_name.bv_val,
-						ps->bdp_size / 1024 );
-					value_add_one( &c->rvalue_vals, &bv );
-					rc = 0;
-
-				}
-				break;
-			}
-		}
-		return rc;
-	} else if ( c->op == LDAP_MOD_DELETE ) {
-		rc = 0;
-		switch( c->type ) {
-		case BDB_MODE:
-#if 0
-			/* FIXME: does it make any sense to change the mode,
-			 * if we don't exec a chmod()? */
-			bdb->bi_dbenv_mode = SLAPD_DEFAULT_DB_MODE;
-			break;
-#endif
-
-		/* single-valued no-ops */
-		case BDB_LOCKD:
-		case BDB_SSTACK:
-			break;
-
-		case BDB_CHKPT:
-			if ( bdb->bi_txn_cp_task ) {
-				struct re_s *re = bdb->bi_txn_cp_task;
-				bdb->bi_txn_cp_task = NULL;
-				ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
-				if ( ldap_pvt_runqueue_isrunning( &slapd_rq, re ) )
-					ldap_pvt_runqueue_stoptask( &slapd_rq, re );
-				ldap_pvt_runqueue_remove( &slapd_rq, re );
-				ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
-			}
-			bdb->bi_txn_cp = 0;
-			break;
-		case BDB_CONFIG:
-			if ( c->valx < 0 ) {
-				ber_bvarray_free( bdb->bi_db_config );
-				bdb->bi_db_config = NULL;
-			} else {
-				int i = c->valx;
-				ch_free( bdb->bi_db_config[i].bv_val );
-				for (; bdb->bi_db_config[i].bv_val; i++)
-					bdb->bi_db_config[i] = bdb->bi_db_config[i+1];
-			}
-			bdb->bi_flags |= BDB_UPD_CONFIG|BDB_RE_OPEN;
-			c->cleanup = bdb_cf_cleanup;
-			break;
-		/* Doesn't really make sense to change these on the fly;
-		 * the entire DB must be dumped and reloaded
-		 */
-		case BDB_CRYPTFILE:
-			if ( bdb->bi_db_crypt_file ) {
-				ch_free( bdb->bi_db_crypt_file );
-				bdb->bi_db_crypt_file = NULL;
-			}
-			/* FALLTHRU */
-		case BDB_CRYPTKEY:
-			if ( !BER_BVISNULL( &bdb->bi_db_crypt_key )) {
-				ch_free( bdb->bi_db_crypt_key.bv_val );
-				BER_BVZERO( &bdb->bi_db_crypt_key );
-			}
-			break;
-		case BDB_DIRECTORY:
-			bdb->bi_flags |= BDB_RE_OPEN;
-			bdb->bi_flags ^= BDB_HAS_CONFIG;
-			ch_free( bdb->bi_dbenv_home );
-			bdb->bi_dbenv_home = NULL;
-			ch_free( bdb->bi_db_config_path );
-			bdb->bi_db_config_path = NULL;
-			c->cleanup = bdb_cf_cleanup;
-			ldap_pvt_thread_pool_purgekey( bdb->bi_dbenv );
-			break;
-		case BDB_NOSYNC:
-			bdb->bi_dbenv->set_flags( bdb->bi_dbenv, DB_TXN_NOSYNC, 0 );
-			break;
-		case BDB_CHECKSUM:
-			bdb->bi_flags &= ~BDB_CHKSUM;
-			break;
-		case BDB_INDEX:
-			if ( c->valx == -1 ) {
-				int i;
-
-				/* delete all */
-				for ( i = 0; i < bdb->bi_nattrs; i++ ) {
-					bdb->bi_attrs[i]->ai_indexmask |= BDB_INDEX_DELETING;
-				}
-				bdb->bi_defaultmask = 0;
-				bdb->bi_flags |= BDB_DEL_INDEX;
-				c->cleanup = bdb_cf_cleanup;
-
-			} else {
-				struct berval bv, def = BER_BVC("default");
-				char *ptr;
-
-				for (ptr = c->line; !isspace( (unsigned char) *ptr ); ptr++);
-
-				bv.bv_val = c->line;
-				bv.bv_len = ptr - bv.bv_val;
-				if ( bvmatch( &bv, &def )) {
-					bdb->bi_defaultmask = 0;
-
-				} else {
-					int i;
-					char **attrs;
-					char sep;
-
-					sep = bv.bv_val[ bv.bv_len ];
-					bv.bv_val[ bv.bv_len ] = '\0';
-					attrs = ldap_str2charray( bv.bv_val, "," );
-
-					for ( i = 0; attrs[ i ]; i++ ) {
-						AttributeDescription *ad = NULL;
-						const char *text;
-						AttrInfo *ai;
-
-						slap_str2ad( attrs[ i ], &ad, &text );
-						/* if we got here... */
-						assert( ad != NULL );
-
-						ai = bdb_attr_mask( bdb, ad );
-						/* if we got here... */
-						assert( ai != NULL );
-
-						ai->ai_indexmask |= BDB_INDEX_DELETING;
-						bdb->bi_flags |= BDB_DEL_INDEX;
-						c->cleanup = bdb_cf_cleanup;
-					}
-
-					bv.bv_val[ bv.bv_len ] = sep;
-					ldap_charray_free( attrs );
-				}
-			}
-			break;
-		/* doesn't make sense on the fly; the DB file must be
-		 * recreated
-		 */
-		case BDB_PGSIZE: {
-				struct bdb_db_pgsize *ps, **prev;
-				int i;
-
-				for ( i = 0, prev = &bdb->bi_pagesizes, ps = *prev; ps;
-					prev = &ps->bdp_next, ps = ps->bdp_next, i++ ) {
-					if ( c->valx == -1 || i == c->valx ) {
-						*prev = ps->bdp_next;
-						ch_free( ps );
-						ps = *prev;
-						if ( i == c->valx ) break;
-					}
-				}
-			}
-			break;
-		}
-		return rc;
-	}
-
-	switch( c->type ) {
-	case BDB_MODE:
-		if ( ASCII_DIGIT( c->argv[1][0] ) ) {
-			long mode;
-			char *next;
-			errno = 0;
-			mode = strtol( c->argv[1], &next, 0 );
-			if ( errno != 0 || next == c->argv[1] || next[0] != '\0' ) {
-				fprintf( stderr, "%s: "
-					"unable to parse mode=\"%s\".\n",
-					c->log, c->argv[1] );
-				return 1;
-			}
-			bdb->bi_dbenv_mode = mode;
-
-		} else {
-			char *m = c->argv[1];
-			int who, what, mode = 0;
-
-			if ( strlen( m ) != STRLENOF("-rwxrwxrwx") ) {
-				return 1;
-			}
-
-			if ( m[0] != '-' ) {
-				return 1;
-			}
-
-			m++;
-			for ( who = 0; who < 3; who++ ) {
-				for ( what = 0; what < 3; what++, m++ ) {
-					if ( m[0] == '-' ) {
-						continue;
-					} else if ( m[0] != "rwx"[what] ) {
-						return 1;
-					}
-					mode += ((1 << (2 - what)) << 3*(2 - who));
-				}
-			}
-			bdb->bi_dbenv_mode = mode;
-		}
-		break;
-	case BDB_CHKPT: {
-		long	l;
-		bdb->bi_txn_cp = 1;
-		if ( lutil_atolx( &l, c->argv[1], 0 ) != 0 ) {
-			fprintf( stderr, "%s: "
-				"invalid kbyte \"%s\" in \"checkpoint\".\n",
-				c->log, c->argv[1] );
-			return 1;
-		}
-		bdb->bi_txn_cp_kbyte = l;
-		if ( lutil_atolx( &l, c->argv[2], 0 ) != 0 ) {
-			fprintf( stderr, "%s: "
-				"invalid minutes \"%s\" in \"checkpoint\".\n",
-				c->log, c->argv[2] );
-			return 1;
-		}
-		bdb->bi_txn_cp_min = l;
-		/* If we're in server mode and time-based checkpointing is enabled,
-		 * submit a task to perform periodic checkpoints.
-		 */
-		if ((slapMode & SLAP_SERVER_MODE) && bdb->bi_txn_cp_min ) {
-			struct re_s *re = bdb->bi_txn_cp_task;
-			if ( re ) {
-				re->interval.tv_sec = bdb->bi_txn_cp_min * 60;
-			} else {
-				if ( c->be->be_suffix == NULL || BER_BVISNULL( &c->be->be_suffix[0] ) ) {
-					fprintf( stderr, "%s: "
-						"\"checkpoint\" must occur after \"suffix\".\n",
-						c->log );
-					return 1;
-				}
-				ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
-				bdb->bi_txn_cp_task = ldap_pvt_runqueue_insert( &slapd_rq,
-					bdb->bi_txn_cp_min * 60, bdb_checkpoint, bdb,
-					LDAP_XSTRING(bdb_checkpoint), c->be->be_suffix[0].bv_val );
-				ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
-			}
-		}
-		} break;
-
-	case BDB_CONFIG: {
-		char *ptr = c->line;
-		struct berval bv;
-
-		if ( c->op == SLAP_CONFIG_ADD ) {
-			ptr += STRLENOF("dbconfig");
-			while (!isspace((unsigned char)*ptr)) ptr++;
-			while (isspace((unsigned char)*ptr)) ptr++;
-		}
-
-		if ( bdb->bi_flags & BDB_IS_OPEN ) {
-			bdb->bi_flags |= BDB_UPD_CONFIG|BDB_RE_OPEN;
-			c->cleanup = bdb_cf_cleanup;
-		} else {
-		/* If we're just starting up...
-		 */
-			FILE *f;
-			/* If a DB_CONFIG file exists, or we don't know the path
-			 * to the DB_CONFIG file, ignore these directives
-			 */
-			if (( bdb->bi_flags & BDB_HAS_CONFIG ) || !bdb->bi_db_config_path )
-				break;
-			f = fopen( bdb->bi_db_config_path, "a" );
-			if ( f ) {
-				/* FIXME: EBCDIC probably needs special handling */
-				fprintf( f, "%s\n", ptr );
-				fclose( f );
-			}
-		}
-		ber_str2bv( ptr, 0, 1, &bv );
-		ber_bvarray_add( &bdb->bi_db_config, &bv );
-		}
-		break;
-
-	case BDB_CRYPTFILE:
-		rc = lutil_get_filed_password( c->value_string, &bdb->bi_db_crypt_key );
-		if ( rc == 0 ) {
-			bdb->bi_db_crypt_file = c->value_string;
-		}
-		break;
-
-	/* Cannot set key if file was already set */
-	case BDB_CRYPTKEY:
-		if ( bdb->bi_db_crypt_file ) {
-			rc = 1;
-		} else {
-			bdb->bi_db_crypt_key = c->value_bv;
-		}
-		break;
-
-	case BDB_DIRECTORY: {
-		FILE *f;
-		char *ptr, *testpath;
-		int len;
-
-		len = strlen( c->value_string );
-		testpath = ch_malloc( len + STRLENOF(LDAP_DIRSEP) + STRLENOF("DUMMY") + 1 );
-		ptr = lutil_strcopy( testpath, c->value_string );
-		*ptr++ = LDAP_DIRSEP[0];
-		strcpy( ptr, "DUMMY" );
-		f = fopen( testpath, "w" );
-		if ( f ) {
-			fclose( f );
-			unlink( testpath );
-		}
-		ch_free( testpath );
-		if ( !f ) {
-			snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: invalid path: %s",
-				c->log, strerror( errno ));
-			Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg, 0, 0 );
-			return -1;
-		}
-
-		if ( bdb->bi_dbenv_home )
-			ch_free( bdb->bi_dbenv_home );
-		bdb->bi_dbenv_home = c->value_string;
-
-		/* See if a DB_CONFIG file already exists here */
-		if ( bdb->bi_db_config_path )
-			ch_free( bdb->bi_db_config_path );
-		bdb->bi_db_config_path = ch_malloc( len +
-			STRLENOF(LDAP_DIRSEP) + STRLENOF("DB_CONFIG") + 1 );
-		ptr = lutil_strcopy( bdb->bi_db_config_path, bdb->bi_dbenv_home );
-		*ptr++ = LDAP_DIRSEP[0];
-		strcpy( ptr, "DB_CONFIG" );
-
-		f = fopen( bdb->bi_db_config_path, "r" );
-		if ( f ) {
-			bdb->bi_flags |= BDB_HAS_CONFIG;
-			fclose(f);
-		}
-		}
-		break;
-
-	case BDB_NOSYNC:
-		if ( c->value_int )
-			bdb->bi_dbenv_xflags |= DB_TXN_NOSYNC;
-		else
-			bdb->bi_dbenv_xflags &= ~DB_TXN_NOSYNC;
-		if ( bdb->bi_flags & BDB_IS_OPEN ) {
-			bdb->bi_dbenv->set_flags( bdb->bi_dbenv, DB_TXN_NOSYNC,
-				c->value_int );
-		}
-		break;
-
-	case BDB_CHECKSUM:
-		if ( c->value_int )
-			bdb->bi_flags |= BDB_CHKSUM;
-		else
-			bdb->bi_flags &= ~BDB_CHKSUM;
-		break;
-
-	case BDB_INDEX:
-		rc = bdb_attr_index_config( bdb, c->fname, c->lineno,
-			c->argc - 1, &c->argv[1], &c->reply);
-
-		if( rc != LDAP_SUCCESS ) return 1;
-		if (( bdb->bi_flags & BDB_IS_OPEN ) && !bdb->bi_index_task ) {
-			/* Start the task as soon as we finish here. Set a long
-			 * interval (10 hours) so that it only gets scheduled once.
-			 */
-			if ( c->be->be_suffix == NULL || BER_BVISNULL( &c->be->be_suffix[0] ) ) {
-				fprintf( stderr, "%s: "
-					"\"index\" must occur after \"suffix\".\n",
-					c->log );
-				return 1;
-			}
-			ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
-			bdb->bi_index_task = ldap_pvt_runqueue_insert( &slapd_rq, 36000,
-				bdb_online_index, c->be,
-				LDAP_XSTRING(bdb_online_index), c->be->be_suffix[0].bv_val );
-			ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
-		}
-		break;
-
-	case BDB_LOCKD:
-		rc = verb_to_mask( c->argv[1], bdb_lockd );
-		if ( BER_BVISNULL(&bdb_lockd[rc].word) ) {
-			fprintf( stderr, "%s: "
-				"bad policy (%s) in \"lockDetect <policy>\" line\n",
-				c->log, c->argv[1] );
-			return 1;
-		}
-		bdb->bi_lock_detect = (u_int32_t)rc;
-		break;
-
-	case BDB_SSTACK:
-		if ( c->value_int < MINIMUM_SEARCH_STACK_DEPTH ) {
-			fprintf( stderr,
-		"%s: depth %d too small, using %d\n",
-			c->log, c->value_int, MINIMUM_SEARCH_STACK_DEPTH );
-			c->value_int = MINIMUM_SEARCH_STACK_DEPTH;
-		}
-		bdb->bi_search_stack_depth = c->value_int;
-		break;
-
-	case BDB_PGSIZE: {
-		struct bdb_db_pgsize *ps, **prev;
-		int i, s;
-		
-		s = atoi(c->argv[2]);
-		if ( s < 1 || s > 64 ) {
-			snprintf( c->cr_msg, sizeof( c->cr_msg ),
-				"%s: size must be > 0 and <= 64: %d",
-				c->log, s );
-			Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg, 0, 0 );
-			return -1;
-		}
-		i = strlen(c->argv[1]);
-		ps = ch_malloc( sizeof(struct bdb_db_pgsize) + i + 1 );
-		ps->bdp_next = NULL;
-		ps->bdp_name.bv_len = i;
-		ps->bdp_name.bv_val = (char *)(ps+1);
-		strcpy( ps->bdp_name.bv_val, c->argv[1] );
-		ps->bdp_size = s * 1024;
-		for ( prev = &bdb->bi_pagesizes; *prev; prev = &(*prev)->bdp_next )
-			;
-		*prev = ps;
-		}
-		break;
-	}
-	return 0;
-}
-
-int bdb_back_init_cf( BackendInfo *bi )
-{
-	int rc;
-	bi->bi_cf_ocs = bdbocs;
-
-	rc = config_register_schema( bdbcfg, bdbocs );
-	if ( rc ) return rc;
-	return 0;
-}
diff --git a/servers/slapd/back-bdb/dbcache.c b/servers/slapd/back-bdb/dbcache.c
deleted file mode 100644
index 9a35b71..0000000
--- a/servers/slapd/back-bdb/dbcache.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/* dbcache.c - manage cache of open databases */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/errno.h>
-#include <ac/socket.h>
-#include <ac/string.h>
-#include <ac/time.h>
-#include <sys/stat.h>
-
-#include "slap.h"
-#include "back-bdb.h"
-#include "lutil_hash.h"
-
-#ifdef BDB_INDEX_USE_HASH
-/* Pass-thru hash function. Since the indexer is already giving us hash
- * values as keys, we don't need BDB to re-hash them.
- */
-static u_int32_t
-bdb_db_hash(
-	DB *db,
-	const void *bytes,
-	u_int32_t length
-)
-{
-	u_int32_t ret = 0;
-	unsigned char *dst = (unsigned char *)&ret;
-	const unsigned char *src = (const unsigned char *)bytes;
-
-	if ( length > sizeof(u_int32_t) )
-		length = sizeof(u_int32_t);
-
-	while ( length ) {
-		*dst++ = *src++;
-		length--;
-	}
-	return ret;
-}
-#define	BDB_INDEXTYPE	DB_HASH
-#else
-#define	BDB_INDEXTYPE	DB_BTREE
-#endif
-
-/* If a configured size is found, return it, otherwise return 0 */
-int
-bdb_db_findsize(
-	struct bdb_info *bdb,
-	struct berval *name
-)
-{
-	struct bdb_db_pgsize *bp;
-	int rc;
-
-	for ( bp = bdb->bi_pagesizes; bp; bp=bp->bdp_next ) {
-		rc = strncmp( name->bv_val, bp->bdp_name.bv_val, name->bv_len );
-		if ( !rc ) {
-			if ( name->bv_len == bp->bdp_name.bv_len )
-				return bp->bdp_size;
-			if ( name->bv_len < bp->bdp_name.bv_len &&
-				bp->bdp_name.bv_val[name->bv_len] == '.' )
-				return bp->bdp_size;
-		}
-	}
-	return 0;
-}
-
-int
-bdb_db_cache(
-	Backend	*be,
-	struct berval *name,
-	DB **dbout )
-{
-	int i, flags;
-	int rc;
-	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
-	struct bdb_db_info *db;
-	char *file;
-
-	*dbout = NULL;
-
-	for( i=BDB_NDB; i < bdb->bi_ndatabases; i++ ) {
-		if( !ber_bvcmp( &bdb->bi_databases[i]->bdi_name, name) ) {
-			*dbout = bdb->bi_databases[i]->bdi_db;
-			return 0;
-		}
-	}
-
-	ldap_pvt_thread_mutex_lock( &bdb->bi_database_mutex );
-
-	/* check again! may have been added by another thread */
-	for( i=BDB_NDB; i < bdb->bi_ndatabases; i++ ) {
-		if( !ber_bvcmp( &bdb->bi_databases[i]->bdi_name, name) ) {
-			*dbout = bdb->bi_databases[i]->bdi_db;
-			ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
-			return 0;
-		}
-	}
-
-	if( i >= BDB_INDICES ) {
-		ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
-		return -1;
-	}
-
-	db = (struct bdb_db_info *) ch_calloc(1, sizeof(struct bdb_db_info));
-
-	ber_dupbv( &db->bdi_name, name );
-
-	rc = db_create( &db->bdi_db, bdb->bi_dbenv, 0 );
-	if( rc != 0 ) {
-		Debug( LDAP_DEBUG_ANY,
-			"bdb_db_cache: db_create(%s) failed: %s (%d)\n",
-			bdb->bi_dbenv_home, db_strerror(rc), rc );
-		ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
-		ch_free( db );
-		return rc;
-	}
-
-	if( !BER_BVISNULL( &bdb->bi_db_crypt_key )) {
-		rc = db->bdi_db->set_flags( db->bdi_db, DB_ENCRYPT );
-		if ( rc ) {
-			Debug( LDAP_DEBUG_ANY,
-				"bdb_db_cache: db set_flags(DB_ENCRYPT)(%s) failed: %s (%d)\n",
-				bdb->bi_dbenv_home, db_strerror(rc), rc );
-			ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
-			db->bdi_db->close( db->bdi_db, 0 );
-			ch_free( db );
-			return rc;
-		}
-	}
-
-	if( bdb->bi_flags & BDB_CHKSUM ) {
-		rc = db->bdi_db->set_flags( db->bdi_db, DB_CHKSUM );
-		if ( rc ) {
-			Debug( LDAP_DEBUG_ANY,
-				"bdb_db_cache: db set_flags(DB_CHKSUM)(%s) failed: %s (%d)\n",
-				bdb->bi_dbenv_home, db_strerror(rc), rc );
-			ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
-			db->bdi_db->close( db->bdi_db, 0 );
-			ch_free( db );
-			return rc;
-		}
-	}
-
-	/* If no explicit size set, use the FS default */
-	flags = bdb_db_findsize( bdb, name );
-	if ( flags )
-		rc = db->bdi_db->set_pagesize( db->bdi_db, flags );
-
-#ifdef BDB_INDEX_USE_HASH
-	rc = db->bdi_db->set_h_hash( db->bdi_db, bdb_db_hash );
-#endif
-	rc = db->bdi_db->set_flags( db->bdi_db, DB_DUP | DB_DUPSORT );
-
-	file = ch_malloc( db->bdi_name.bv_len + sizeof(BDB_SUFFIX) );
-	strcpy( file, db->bdi_name.bv_val );
-	strcpy( file+db->bdi_name.bv_len, BDB_SUFFIX );
-
-#ifdef HAVE_EBCDIC
-	__atoe( file );
-#endif
-	flags = DB_CREATE | DB_THREAD;
-#ifdef DB_AUTO_COMMIT
-	if ( !( slapMode & SLAP_TOOL_QUICK ))
-		flags |= DB_AUTO_COMMIT;
-#endif
-	/* Cannot Truncate when Transactions are in use */
-	if ( (slapMode & (SLAP_TOOL_QUICK|SLAP_TRUNCATE_MODE)) ==
-		(SLAP_TOOL_QUICK|SLAP_TRUNCATE_MODE))
-			flags |= DB_TRUNCATE;
-
-	rc = DB_OPEN( db->bdi_db,
-		file, NULL /* name */,
-		BDB_INDEXTYPE, bdb->bi_db_opflags | flags, bdb->bi_dbenv_mode );
-
-	ch_free( file );
-
-	if( rc != 0 ) {
-		Debug( LDAP_DEBUG_ANY,
-			"bdb_db_cache: db_open(%s) failed: %s (%d)\n",
-			name->bv_val, db_strerror(rc), rc );
-		ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
-		db->bdi_db->close( db->bdi_db, 0 );
-		ch_free( db );
-		return rc;
-	}
-
-	bdb->bi_databases[i] = db;
-	bdb->bi_ndatabases = i+1;
-
-	*dbout = db->bdi_db;
-
-	ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
-	return 0;
-}
diff --git a/servers/slapd/back-bdb/delete.c b/servers/slapd/back-bdb/delete.c
deleted file mode 100644
index f4f6e23..0000000
--- a/servers/slapd/back-bdb/delete.c
+++ /dev/null
@@ -1,605 +0,0 @@
-/* delete.c - bdb backend delete routine */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "lutil.h"
-#include "back-bdb.h"
-
-int
-bdb_delete( Operation *op, SlapReply *rs )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	Entry	*matched = NULL;
-	struct berval	pdn = {0, NULL};
-	Entry	*e = NULL;
-	Entry	*p = NULL;
-	EntryInfo	*ei = NULL, *eip = NULL;
-	int		manageDSAit = get_manageDSAit( op );
-	AttributeDescription *children = slap_schema.si_ad_children;
-	AttributeDescription *entry = slap_schema.si_ad_entry;
-	DB_TXN		*ltid = NULL, *lt2;
-	struct bdb_op_info opinfo = {{{ 0 }}};
-	ID	eid;
-
-	DB_LOCK		lock, plock;
-
-	int		num_retries = 0;
-
-	int     rc;
-
-	LDAPControl **preread_ctrl = NULL;
-	LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
-	int num_ctrls = 0;
-
-	int	parent_is_glue = 0;
-	int parent_is_leaf = 0;
-
-#ifdef LDAP_X_TXN
-	int settle = 0;
-#endif
-
-	Debug( LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(bdb_delete) ": %s\n",
-		op->o_req_dn.bv_val, 0, 0 );
-
-#ifdef LDAP_X_TXN
-	if( op->o_txnSpec ) {
-		/* acquire connection lock */
-		ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
-		if( op->o_conn->c_txn == CONN_TXN_INACTIVE ) {
-			rs->sr_text = "invalid transaction identifier";
-			rs->sr_err = LDAP_X_TXN_ID_INVALID;
-			goto txnReturn;
-		} else if( op->o_conn->c_txn == CONN_TXN_SETTLE ) {
-			settle=1;
-			goto txnReturn;
-		}
-
-		if( op->o_conn->c_txn_backend == NULL ) {
-			op->o_conn->c_txn_backend = op->o_bd;
-
-		} else if( op->o_conn->c_txn_backend != op->o_bd ) {
-			rs->sr_text = "transaction cannot span multiple database contexts";
-			rs->sr_err = LDAP_AFFECTS_MULTIPLE_DSAS;
-			goto txnReturn;
-		}
-
-		/* insert operation into transaction */
-
-		rs->sr_text = "transaction specified";
-		rs->sr_err = LDAP_X_TXN_SPECIFY_OKAY;
-
-txnReturn:
-		/* release connection lock */
-		ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
-
-		if( !settle ) {
-			send_ldap_result( op, rs );
-			return rs->sr_err;
-		}
-	}
-#endif
-
-	ctrls[num_ctrls] = 0;
-
-	/* allocate CSN */
-	if ( BER_BVISNULL( &op->o_csn ) ) {
-		struct berval csn;
-		char csnbuf[LDAP_PVT_CSNSTR_BUFSIZE];
-
-		csn.bv_val = csnbuf;
-		csn.bv_len = sizeof(csnbuf);
-		slap_get_csn( op, &csn, 1 );
-	}
-
-	if( 0 ) {
-retry:	/* transaction retry */
-		if( e != NULL ) {
-			bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
-			e = NULL;
-		}
-		if( p != NULL ) {
-			bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
-			p = NULL;
-		}
-		Debug( LDAP_DEBUG_TRACE,
-			"==> " LDAP_XSTRING(bdb_delete) ": retrying...\n",
-			0, 0, 0 );
-		rs->sr_err = TXN_ABORT( ltid );
-		ltid = NULL;
-		LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
-		opinfo.boi_oe.oe_key = NULL;
-		op->o_do_not_cache = opinfo.boi_acl_cache;
-		if( rs->sr_err != 0 ) {
-			rs->sr_err = LDAP_OTHER;
-			rs->sr_text = "internal error";
-			goto return_results;
-		}
-		if ( op->o_abandon ) {
-			rs->sr_err = SLAPD_ABANDON;
-			goto return_results;
-		}
-		parent_is_glue = 0;
-		parent_is_leaf = 0;
-		bdb_trans_backoff( ++num_retries );
-	}
-
-	/* begin transaction */
-	rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, NULL, &ltid, 
-		bdb->bi_db_opflags );
-	Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_delete) ": txn1 id: %x\n",
-		ltid->id(ltid), 0, 0 );
-	rs->sr_text = NULL;
-	if( rs->sr_err != 0 ) {
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_delete) ": txn_begin failed: "
-			"%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
-		rs->sr_err = LDAP_OTHER;
-		rs->sr_text = "internal error";
-		goto return_results;
-	}
-
-	opinfo.boi_oe.oe_key = bdb;
-	opinfo.boi_txn = ltid;
-	opinfo.boi_err = 0;
-	opinfo.boi_acl_cache = op->o_do_not_cache;
-	LDAP_SLIST_INSERT_HEAD( &op->o_extra, &opinfo.boi_oe, oe_next );
-
-	if ( !be_issuffix( op->o_bd, &op->o_req_ndn ) ) {
-		dnParent( &op->o_req_ndn, &pdn );
-	}
-
-	/* get entry */
-	rs->sr_err = bdb_dn2entry( op, ltid, &op->o_req_ndn, &ei, 1,
-		&lock );
-
-	switch( rs->sr_err ) {
-	case 0:
-	case DB_NOTFOUND:
-		break;
-	case DB_LOCK_DEADLOCK:
-	case DB_LOCK_NOTGRANTED:
-		goto retry;
-	case LDAP_BUSY:
-		rs->sr_text = "ldap server busy";
-		goto return_results;
-	default:
-		rs->sr_err = LDAP_OTHER;
-		rs->sr_text = "internal error";
-		goto return_results;
-	}
-
-	if ( rs->sr_err == 0 ) {
-		e = ei->bei_e;
-		eip = ei->bei_parent;
-	} else {
-		matched = ei->bei_e;
-	}
-
-	/* FIXME : dn2entry() should return non-glue entry */
-	if ( e == NULL || ( !manageDSAit && is_entry_glue( e ))) {
-		Debug( LDAP_DEBUG_ARGS,
-			"<=- " LDAP_XSTRING(bdb_delete) ": no such object %s\n",
-			op->o_req_dn.bv_val, 0, 0);
-
-		if ( matched != NULL ) {
-			rs->sr_matched = ch_strdup( matched->e_dn );
-			rs->sr_ref = is_entry_referral( matched )
-				? get_entry_referrals( op, matched )
-				: NULL;
-			bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, matched);
-			matched = NULL;
-
-		} else {
-			rs->sr_ref = referral_rewrite( default_referral, NULL,
-					&op->o_req_dn, LDAP_SCOPE_DEFAULT );
-		}
-
-		rs->sr_err = LDAP_REFERRAL;
-		rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
-		goto return_results;
-	}
-
-	rc = bdb_cache_find_id( op, ltid, eip->bei_id, &eip, 0, &plock );
-	switch( rc ) {
-	case DB_LOCK_DEADLOCK:
-	case DB_LOCK_NOTGRANTED:
-		goto retry;
-	case 0:
-	case DB_NOTFOUND:
-		break;
-	default:
-		rs->sr_err = LDAP_OTHER;
-		rs->sr_text = "internal error";
-		goto return_results;
-	}
-	if ( eip ) p = eip->bei_e;
-
-	if ( pdn.bv_len != 0 ) {
-		if( p == NULL || !bvmatch( &pdn, &p->e_nname )) {
-			Debug( LDAP_DEBUG_TRACE,
-				"<=- " LDAP_XSTRING(bdb_delete) ": parent "
-				"does not exist\n", 0, 0, 0 );
-			rs->sr_err = LDAP_OTHER;
-			rs->sr_text = "could not locate parent of entry";
-			goto return_results;
-		}
-
-		/* check parent for "children" acl */
-		rs->sr_err = access_allowed( op, p,
-			children, NULL, ACL_WDEL, NULL );
-
-		if ( !rs->sr_err  ) {
-			switch( opinfo.boi_err ) {
-			case DB_LOCK_DEADLOCK:
-			case DB_LOCK_NOTGRANTED:
-				goto retry;
-			}
-
-			Debug( LDAP_DEBUG_TRACE,
-				"<=- " LDAP_XSTRING(bdb_delete) ": no write "
-				"access to parent\n", 0, 0, 0 );
-			rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
-			rs->sr_text = "no write access to parent";
-			goto return_results;
-		}
-
-	} else {
-		/* no parent, must be root to delete */
-		if( ! be_isroot( op ) ) {
-			if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv )
-				|| be_shadow_update( op ) ) {
-				p = (Entry *)&slap_entry_root;
-
-				/* check parent for "children" acl */
-				rs->sr_err = access_allowed( op, p,
-					children, NULL, ACL_WDEL, NULL );
-
-				p = NULL;
-
-				if ( !rs->sr_err  ) {
-					switch( opinfo.boi_err ) {
-					case DB_LOCK_DEADLOCK:
-					case DB_LOCK_NOTGRANTED:
-						goto retry;
-					}
-
-					Debug( LDAP_DEBUG_TRACE,
-						"<=- " LDAP_XSTRING(bdb_delete)
-						": no access to parent\n",
-						0, 0, 0 );
-					rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
-					rs->sr_text = "no write access to parent";
-					goto return_results;
-				}
-
-			} else {
-				Debug( LDAP_DEBUG_TRACE,
-					"<=- " LDAP_XSTRING(bdb_delete)
-					": no parent and not root\n", 0, 0, 0 );
-				rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
-				goto return_results;
-			}
-		}
-	}
-
-	if ( get_assert( op ) &&
-		( test_filter( op, e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
-	{
-		rs->sr_err = LDAP_ASSERTION_FAILED;
-		goto return_results;
-	}
-
-	rs->sr_err = access_allowed( op, e,
-		entry, NULL, ACL_WDEL, NULL );
-
-	if ( !rs->sr_err  ) {
-		switch( opinfo.boi_err ) {
-		case DB_LOCK_DEADLOCK:
-		case DB_LOCK_NOTGRANTED:
-			goto retry;
-		}
-
-		Debug( LDAP_DEBUG_TRACE,
-			"<=- " LDAP_XSTRING(bdb_delete) ": no write access "
-			"to entry\n", 0, 0, 0 );
-		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
-		rs->sr_text = "no write access to entry";
-		goto return_results;
-	}
-
-	if ( !manageDSAit && is_entry_referral( e ) ) {
-		/* entry is a referral, don't allow delete */
-		rs->sr_ref = get_entry_referrals( op, e );
-
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_delete) ": entry is referral\n",
-			0, 0, 0 );
-
-		rs->sr_err = LDAP_REFERRAL;
-		rs->sr_matched = ch_strdup( e->e_name.bv_val );
-		rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
-		goto return_results;
-	}
-
-	/* pre-read */
-	if( op->o_preread ) {
-		if( preread_ctrl == NULL ) {
-			preread_ctrl = &ctrls[num_ctrls++];
-			ctrls[num_ctrls] = NULL;
-		}
-		if( slap_read_controls( op, rs, e,
-			&slap_pre_read_bv, preread_ctrl ) )
-		{
-			Debug( LDAP_DEBUG_TRACE,
-				"<=- " LDAP_XSTRING(bdb_delete) ": pre-read "
-				"failed!\n", 0, 0, 0 );
-			if ( op->o_preread & SLAP_CONTROL_CRITICAL ) {
-				/* FIXME: is it correct to abort
-				 * operation if control fails? */
-				goto return_results;
-			}
-		}
-	}
-
-	/* nested transaction */
-	rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, &lt2, 
-		bdb->bi_db_opflags );
-	rs->sr_text = NULL;
-	if( rs->sr_err != 0 ) {
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_delete) ": txn_begin(2) failed: "
-			"%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
-		rs->sr_err = LDAP_OTHER;
-		rs->sr_text = "internal error";
-		goto return_results;
-	}
-	Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_delete) ": txn2 id: %x\n",
-		lt2->id(lt2), 0, 0 );
-
-	BDB_LOG_PRINTF( bdb->bi_dbenv, lt2, "slapd Starting delete %s(%d)",
-		e->e_nname.bv_val, e->e_id );
-
-	/* Can't do it if we have kids */
-	rs->sr_err = bdb_cache_children( op, lt2, e );
-	if( rs->sr_err != DB_NOTFOUND ) {
-		switch( rs->sr_err ) {
-		case DB_LOCK_DEADLOCK:
-		case DB_LOCK_NOTGRANTED:
-			goto retry;
-		case 0:
-			Debug(LDAP_DEBUG_ARGS,
-				"<=- " LDAP_XSTRING(bdb_delete)
-				": non-leaf %s\n",
-				op->o_req_dn.bv_val, 0, 0);
-			rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
-			rs->sr_text = "subordinate objects must be deleted first";
-			break;
-		default:
-			Debug(LDAP_DEBUG_ARGS,
-				"<=- " LDAP_XSTRING(bdb_delete)
-				": has_children failed: %s (%d)\n",
-				db_strerror(rs->sr_err), rs->sr_err, 0 );
-			rs->sr_err = LDAP_OTHER;
-			rs->sr_text = "internal error";
-		}
-		goto return_results;
-	}
-
-	/* delete from dn2id */
-	rs->sr_err = bdb_dn2id_delete( op, lt2, eip, e );
-	if ( rs->sr_err != 0 ) {
-		Debug(LDAP_DEBUG_TRACE,
-			"<=- " LDAP_XSTRING(bdb_delete) ": dn2id failed: "
-			"%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
-		switch( rs->sr_err ) {
-		case DB_LOCK_DEADLOCK:
-		case DB_LOCK_NOTGRANTED:
-			goto retry;
-		}
-		rs->sr_text = "DN index delete failed";
-		rs->sr_err = LDAP_OTHER;
-		goto return_results;
-	}
-
-	/* delete indices for old attributes */
-	rs->sr_err = bdb_index_entry_del( op, lt2, e );
-	if ( rs->sr_err != LDAP_SUCCESS ) {
-		Debug(LDAP_DEBUG_TRACE,
-			"<=- " LDAP_XSTRING(bdb_delete) ": index failed: "
-			"%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
-		switch( rs->sr_err ) {
-		case DB_LOCK_DEADLOCK:
-		case DB_LOCK_NOTGRANTED:
-			goto retry;
-		}
-		rs->sr_text = "entry index delete failed";
-		rs->sr_err = LDAP_OTHER;
-		goto return_results;
-	}
-
-	/* fixup delete CSN */
-	if ( !SLAP_SHADOW( op->o_bd )) {
-		struct berval vals[2];
-
-		assert( !BER_BVISNULL( &op->o_csn ) );
-		vals[0] = op->o_csn;
-		BER_BVZERO( &vals[1] );
-		rs->sr_err = bdb_index_values( op, lt2, slap_schema.si_ad_entryCSN,
-			vals, 0, SLAP_INDEX_ADD_OP );
-	if ( rs->sr_err != LDAP_SUCCESS ) {
-			switch( rs->sr_err ) {
-			case DB_LOCK_DEADLOCK:
-			case DB_LOCK_NOTGRANTED:
-				goto retry;
-			}
-			rs->sr_text = "entryCSN index update failed";
-			rs->sr_err = LDAP_OTHER;
-			goto return_results;
-		}
-	}
-
-	/* delete from id2entry */
-	rs->sr_err = bdb_id2entry_delete( op->o_bd, lt2, e );
-	if ( rs->sr_err != 0 ) {
-		Debug( LDAP_DEBUG_TRACE,
-			"<=- " LDAP_XSTRING(bdb_delete) ": id2entry failed: "
-			"%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
-		switch( rs->sr_err ) {
-		case DB_LOCK_DEADLOCK:
-		case DB_LOCK_NOTGRANTED:
-			goto retry;
-		}
-		rs->sr_text = "entry delete failed";
-		rs->sr_err = LDAP_OTHER;
-		goto return_results;
-	}
-
-	if ( pdn.bv_len != 0 ) {
-		parent_is_glue = is_entry_glue(p);
-		rs->sr_err = bdb_cache_children( op, lt2, p );
-		if ( rs->sr_err != DB_NOTFOUND ) {
-			switch( rs->sr_err ) {
-			case DB_LOCK_DEADLOCK:
-			case DB_LOCK_NOTGRANTED:
-				goto retry;
-			case 0:
-				break;
-			default:
-				Debug(LDAP_DEBUG_ARGS,
-					"<=- " LDAP_XSTRING(bdb_delete)
-					": has_children failed: %s (%d)\n",
-					db_strerror(rs->sr_err), rs->sr_err, 0 );
-				rs->sr_err = LDAP_OTHER;
-				rs->sr_text = "internal error";
-				goto return_results;
-			}
-			parent_is_leaf = 1;
-		}
-		bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
-		p = NULL;
-	}
-
-	BDB_LOG_PRINTF( bdb->bi_dbenv, lt2, "slapd Commit1 delete %s(%d)",
-		e->e_nname.bv_val, e->e_id );
-
-	if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
-		rs->sr_err = LDAP_OTHER;
-		rs->sr_text = "txn_commit(2) failed";
-		goto return_results;
-	}
-
-	eid = e->e_id;
-
-#if 0	/* Do we want to reclaim deleted IDs? */
-	ldap_pvt_thread_mutex_lock( &bdb->bi_lastid_mutex );
-	if ( e->e_id == bdb->bi_lastid ) {
-		bdb_last_id( op->o_bd, ltid );
-	}
-	ldap_pvt_thread_mutex_unlock( &bdb->bi_lastid_mutex );
-#endif
-
-	if( op->o_noop ) {
-		if ( ( rs->sr_err = TXN_ABORT( ltid ) ) != 0 ) {
-			rs->sr_text = "txn_abort (no-op) failed";
-		} else {
-			rs->sr_err = LDAP_X_NO_OPERATION;
-			ltid = NULL;
-			goto return_results;
-		}
-	} else {
-
-		BDB_LOG_PRINTF( bdb->bi_dbenv, ltid, "slapd Cache delete %s(%d)",
-			e->e_nname.bv_val, e->e_id );
-
-		rc = bdb_cache_delete( bdb, e, ltid, &lock );
-		switch( rc ) {
-		case DB_LOCK_DEADLOCK:
-		case DB_LOCK_NOTGRANTED:
-			goto retry;
-		}
-
-		rs->sr_err = TXN_COMMIT( ltid, 0 );
-	}
-	ltid = NULL;
-	LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
-	opinfo.boi_oe.oe_key = NULL;
-
-	BDB_LOG_PRINTF( bdb->bi_dbenv, NULL, "slapd Committed delete %s(%d)",
-		e->e_nname.bv_val, e->e_id );
-
-	if( rs->sr_err != 0 ) {
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_delete) ": txn_%s failed: %s (%d)\n",
-			op->o_noop ? "abort (no-op)" : "commit",
-			db_strerror(rs->sr_err), rs->sr_err );
-		rs->sr_err = LDAP_OTHER;
-		rs->sr_text = "commit failed";
-
-		goto return_results;
-	}
-
-	Debug( LDAP_DEBUG_TRACE,
-		LDAP_XSTRING(bdb_delete) ": deleted%s id=%08lx dn=\"%s\"\n",
-		op->o_noop ? " (no-op)" : "",
-		eid, op->o_req_dn.bv_val );
-	rs->sr_err = LDAP_SUCCESS;
-	rs->sr_text = NULL;
-	if( num_ctrls ) rs->sr_ctrls = ctrls;
-
-return_results:
-	if ( rs->sr_err == LDAP_SUCCESS && parent_is_glue && parent_is_leaf ) {
-		op->o_delete_glue_parent = 1;
-	}
-
-	if ( p )
-		bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
-
-	/* free entry */
-	if( e != NULL ) {
-		if ( rs->sr_err == LDAP_SUCCESS ) {
-			/* Free the EntryInfo and the Entry */
-			bdb_cache_entryinfo_lock( BEI(e) );
-			bdb_cache_delete_cleanup( &bdb->bi_cache, BEI(e) );
-		} else {
-			bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
-		}
-	}
-
-	if( ltid != NULL ) {
-		TXN_ABORT( ltid );
-	}
-	if ( opinfo.boi_oe.oe_key ) {
-		LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
-	}
-
-	send_ldap_result( op, rs );
-	slap_graduate_commit_csn( op );
-
-	if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) {
-		slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
-		slap_sl_free( *preread_ctrl, op->o_tmpmemctx );
-	}
-
-	if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp_kbyte ) {
-		TXN_CHECKPOINT( bdb->bi_dbenv,
-			bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
-	}
-	return rs->sr_err;
-}
diff --git a/servers/slapd/back-bdb/dn2entry.c b/servers/slapd/back-bdb/dn2entry.c
deleted file mode 100644
index 41d1dc9..0000000
--- a/servers/slapd/back-bdb/dn2entry.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/* dn2entry.c - routines to deal with the dn2id / id2entry glue */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "back-bdb.h"
-
-/*
- * dn2entry - look up dn in the cache/indexes and return the corresponding
- * entry. If the requested DN is not found and matched is TRUE, return info
- * for the closest ancestor of the DN. Otherwise e is NULL.
- */
-
-int
-bdb_dn2entry(
-	Operation *op,
-	DB_TXN *tid,
-	struct berval *dn,
-	EntryInfo **e,
-	int matched,
-	DB_LOCK *lock )
-{
-	EntryInfo *ei = NULL;
-	int rc, rc2;
-
-	Debug(LDAP_DEBUG_TRACE, "bdb_dn2entry(\"%s\")\n",
-		dn->bv_val, 0, 0 );
-
-	*e = NULL;
-
-	rc = bdb_cache_find_ndn( op, tid, dn, &ei );
-	if ( rc ) {
-		if ( matched && rc == DB_NOTFOUND ) {
-			/* Set the return value, whether we have its entry
-			 * or not.
-			 */
-			*e = ei;
-			if ( ei && ei->bei_id ) {
-				rc2 = bdb_cache_find_id( op, tid, ei->bei_id,
-					&ei, ID_LOCKED, lock );
-				if ( rc2 ) rc = rc2;
-			} else if ( ei ) {
-				bdb_cache_entryinfo_unlock( ei );
-				memset( lock, 0, sizeof( *lock ));
-				lock->mode = DB_LOCK_NG;
-			}
-		} else if ( ei ) {
-			bdb_cache_entryinfo_unlock( ei );
-		}
-	} else {
-		rc = bdb_cache_find_id( op, tid, ei->bei_id, &ei, ID_LOCKED,
-			lock );
-		if ( rc == 0 ) {
-			*e = ei;
-		} else if ( matched && rc == DB_NOTFOUND ) {
-			/* always return EntryInfo */
-			if ( ei->bei_parent ) {
-				ei = ei->bei_parent;
-				rc2 = bdb_cache_find_id( op, tid, ei->bei_id, &ei, 0,
-					lock );
-				if ( rc2 ) rc = rc2;
-			}
-			*e = ei;
-		}
-	}
-
-	return rc;
-}
diff --git a/servers/slapd/back-bdb/dn2id.c b/servers/slapd/back-bdb/dn2id.c
deleted file mode 100644
index 7b54024..0000000
--- a/servers/slapd/back-bdb/dn2id.c
+++ /dev/null
@@ -1,1215 +0,0 @@
-/* dn2id.c - routines to deal with the dn2id index */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "back-bdb.h"
-#include "idl.h"
-#include "lutil.h"
-
-#ifndef BDB_HIER
-int
-bdb_dn2id_add(
-	Operation *op,
-	DB_TXN *txn,
-	EntryInfo *eip,
-	Entry		*e )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	DB *db = bdb->bi_dn2id->bdi_db;
-	int		rc;
-	DBT		key, data;
-	ID		nid;
-	char		*buf;
-	struct berval	ptr, pdn;
-
-	Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_add 0x%lx: \"%s\"\n",
-		e->e_id, e->e_ndn, 0 );
-	assert( e->e_id != NOID );
-
-	DBTzero( &key );
-	key.size = e->e_nname.bv_len + 2;
-	key.ulen = key.size;
-	key.flags = DB_DBT_USERMEM;
-	buf = op->o_tmpalloc( key.size, op->o_tmpmemctx );
-	key.data = buf;
-	buf[0] = DN_BASE_PREFIX;
-	ptr.bv_val = buf + 1;
-	ptr.bv_len = e->e_nname.bv_len;
-	AC_MEMCPY( ptr.bv_val, e->e_nname.bv_val, e->e_nname.bv_len );
-	ptr.bv_val[ptr.bv_len] = '\0';
-
-	DBTzero( &data );
-	data.data = &nid;
-	data.size = sizeof( nid );
-	BDB_ID2DISK( e->e_id, &nid );
-
-	/* store it -- don't override */
-	rc = db->put( db, txn, &key, &data, DB_NOOVERWRITE );
-	if( rc != 0 ) {
-		char buf[ SLAP_TEXT_BUFLEN ];
-		snprintf( buf, sizeof( buf ), "%s => bdb_dn2id_add dn=\"%s\" ID=0x%lx",
-			op->o_log_prefix, e->e_name.bv_val, e->e_id );
-		Debug( LDAP_DEBUG_ANY, "%s: put failed: %s %d\n",
-			buf, db_strerror(rc), rc );
-		goto done;
-	}
-
-#ifndef BDB_MULTIPLE_SUFFIXES
-	if( !be_issuffix( op->o_bd, &ptr ))
-#endif
-	{
-		buf[0] = DN_SUBTREE_PREFIX;
-		rc = db->put( db, txn, &key, &data, DB_NOOVERWRITE );
-		if( rc != 0 ) {
-			Debug( LDAP_DEBUG_ANY,
-			"=> bdb_dn2id_add 0x%lx: subtree (%s) put failed: %d\n",
-			e->e_id, ptr.bv_val, rc );
-			goto done;
-		}
-		
-#ifdef BDB_MULTIPLE_SUFFIXES
-	if( !be_issuffix( op->o_bd, &ptr ))
-#endif
-	{
-		dnParent( &ptr, &pdn );
-	
-		key.size = pdn.bv_len + 2;
-		key.ulen = key.size;
-		pdn.bv_val[-1] = DN_ONE_PREFIX;
-		key.data = pdn.bv_val-1;
-		ptr = pdn;
-
-		rc = bdb_idl_insert_key( op->o_bd, db, txn, &key, e->e_id );
-
-		if( rc != 0 ) {
-			Debug( LDAP_DEBUG_ANY,
-				"=> bdb_dn2id_add 0x%lx: parent (%s) insert failed: %d\n",
-					e->e_id, ptr.bv_val, rc );
-			goto done;
-		}
-	}
-
-#ifndef BDB_MULTIPLE_SUFFIXES
-	while( !be_issuffix( op->o_bd, &ptr ))
-#else
-	for (;;)
-#endif
-	{
-		ptr.bv_val[-1] = DN_SUBTREE_PREFIX;
-
-		rc = bdb_idl_insert_key( op->o_bd, db, txn, &key, e->e_id );
-
-		if( rc != 0 ) {
-			Debug( LDAP_DEBUG_ANY,
-				"=> bdb_dn2id_add 0x%lx: subtree (%s) insert failed: %d\n",
-					e->e_id, ptr.bv_val, rc );
-			break;
-		}
-#ifdef BDB_MULTIPLE_SUFFIXES
-		if( be_issuffix( op->o_bd, &ptr )) break;
-#endif
-		dnParent( &ptr, &pdn );
-
-		key.size = pdn.bv_len + 2;
-		key.ulen = key.size;
-		key.data = pdn.bv_val - 1;
-		ptr = pdn;
-	}
-	}
-
-done:
-	op->o_tmpfree( buf, op->o_tmpmemctx );
-	Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id_add 0x%lx: %d\n", e->e_id, rc, 0 );
-	return rc;
-}
-
-int
-bdb_dn2id_delete(
-	Operation *op,
-	DB_TXN *txn,
-	EntryInfo	*eip,
-	Entry		*e )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	DB *db = bdb->bi_dn2id->bdi_db;
-	char		*buf;
-	DBT		key;
-	struct berval	pdn, ptr;
-	int		rc;
-
-	Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_delete 0x%lx: \"%s\"\n",
-		e->e_id, e->e_ndn, 0 );
-
-	DBTzero( &key );
-	key.size = e->e_nname.bv_len + 2;
-	buf = op->o_tmpalloc( key.size, op->o_tmpmemctx );
-	key.data = buf;
-	key.flags = DB_DBT_USERMEM;
-	buf[0] = DN_BASE_PREFIX;
-	ptr.bv_val = buf+1;
-	ptr.bv_len = e->e_nname.bv_len;
-	AC_MEMCPY( ptr.bv_val, e->e_nname.bv_val, e->e_nname.bv_len );
-	ptr.bv_val[ptr.bv_len] = '\0';
-
-	/* delete it */
-	rc = db->del( db, txn, &key, 0 );
-	if( rc != 0 ) {
-		Debug( LDAP_DEBUG_ANY, "=> bdb_dn2id_delete 0x%lx: delete failed: %s %d\n",
-			e->e_id, db_strerror(rc), rc );
-		goto done;
-	}
-
-#ifndef BDB_MULTIPLE_SUFFIXES
-	if( !be_issuffix( op->o_bd, &ptr ))
-#endif
-	{
-		buf[0] = DN_SUBTREE_PREFIX;
-		rc = bdb_idl_delete_key( op->o_bd, db, txn, &key, e->e_id );
-		if( rc != 0 ) {
-			Debug( LDAP_DEBUG_ANY,
-			"=> bdb_dn2id_delete 0x%lx: subtree (%s) delete failed: %d\n",
-			e->e_id, ptr.bv_val, rc );
-			goto done;
-		}
-
-#ifdef BDB_MULTIPLE_SUFFIXES
-	if( !be_issuffix( op->o_bd, &ptr ))
-#endif
-	{
-		dnParent( &ptr, &pdn );
-
-		key.size = pdn.bv_len + 2;
-		key.ulen = key.size;
-		pdn.bv_val[-1] = DN_ONE_PREFIX;
-		key.data = pdn.bv_val - 1;
-		ptr = pdn;
-
-		rc = bdb_idl_delete_key( op->o_bd, db, txn, &key, e->e_id );
-
-		if( rc != 0 ) {
-			Debug( LDAP_DEBUG_ANY,
-				"=> bdb_dn2id_delete 0x%lx: parent (%s) delete failed: %d\n",
-				e->e_id, ptr.bv_val, rc );
-			goto done;
-		}
-	}
-
-#ifndef BDB_MULTIPLE_SUFFIXES
-	while( !be_issuffix( op->o_bd, &ptr ))
-#else
-	for (;;)
-#endif
-	{
-		ptr.bv_val[-1] = DN_SUBTREE_PREFIX;
-
-		rc = bdb_idl_delete_key( op->o_bd, db, txn, &key, e->e_id );
-		if( rc != 0 ) {
-			Debug( LDAP_DEBUG_ANY,
-				"=> bdb_dn2id_delete 0x%lx: subtree (%s) delete failed: %d\n",
-				e->e_id, ptr.bv_val, rc );
-			goto done;
-		}
-#ifdef BDB_MULTIPLE_SUFFIXES
-		if( be_issuffix( op->o_bd, &ptr )) break;
-#endif
-		dnParent( &ptr, &pdn );
-
-		key.size = pdn.bv_len + 2;
-		key.ulen = key.size;
-		key.data = pdn.bv_val - 1;
-		ptr = pdn;
-	}
-	}
-
-done:
-	op->o_tmpfree( buf, op->o_tmpmemctx );
-	Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id_delete 0x%lx: %d\n", e->e_id, rc, 0 );
-	return rc;
-}
-
-int
-bdb_dn2id(
-	Operation *op,
-	struct berval	*dn,
-	EntryInfo *ei,
-	DB_TXN *txn,
-	DBC **cursor )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	DB *db = bdb->bi_dn2id->bdi_db;
-	int		rc;
-	DBT		key, data;
-	ID		nid;
-
-	Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id(\"%s\")\n", dn->bv_val, 0, 0 );
-
-	DBTzero( &key );
-	key.size = dn->bv_len + 2;
-	key.data = op->o_tmpalloc( key.size, op->o_tmpmemctx );
-	((char *)key.data)[0] = DN_BASE_PREFIX;
-	AC_MEMCPY( &((char *)key.data)[1], dn->bv_val, key.size - 1 );
-
-	/* store the ID */
-	DBTzero( &data );
-	data.data = &nid;
-	data.ulen = sizeof(ID);
-	data.flags = DB_DBT_USERMEM;
-
-	rc = db->cursor( db, txn, cursor, bdb->bi_db_opflags );
-
-	/* fetch it */
-	if ( !rc )
-		rc = (*cursor)->c_get( *cursor, &key, &data, DB_SET );
-
-	if( rc != 0 ) {
-		Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id: get failed: %s (%d)\n",
-			db_strerror( rc ), rc, 0 );
-	} else {
-		BDB_DISK2ID( &nid, &ei->bei_id );
-		Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id: got id=0x%lx\n",
-			ei->bei_id, 0, 0 );
-	}
-	op->o_tmpfree( key.data, op->o_tmpmemctx );
-	return rc;
-}
-
-int
-bdb_dn2id_children(
-	Operation *op,
-	DB_TXN *txn,
-	Entry *e )
-{
-	DBT		key, data;
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	DB *db = bdb->bi_dn2id->bdi_db;
-	ID		id;
-	int		rc;
-
-	Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_children(\"%s\")\n",
-		e->e_nname.bv_val, 0, 0 );
-	DBTzero( &key );
-	key.size = e->e_nname.bv_len + 2;
-	key.data = op->o_tmpalloc( key.size, op->o_tmpmemctx );
-	((char *)key.data)[0] = DN_ONE_PREFIX;
-	AC_MEMCPY( &((char *)key.data)[1], e->e_nname.bv_val, key.size - 1 );
-
-	if ( bdb->bi_idl_cache_size ) {
-		rc = bdb_idl_cache_get( bdb, db, &key, NULL );
-		if ( rc != LDAP_NO_SUCH_OBJECT ) {
-			op->o_tmpfree( key.data, op->o_tmpmemctx );
-			return rc;
-		}
-	}
-	/* we actually could do a empty get... */
-	DBTzero( &data );
-	data.data = &id;
-	data.ulen = sizeof(id);
-	data.flags = DB_DBT_USERMEM;
-	data.doff = 0;
-	data.dlen = sizeof(id);
-
-	rc = db->get( db, txn, &key, &data, bdb->bi_db_opflags );
-	op->o_tmpfree( key.data, op->o_tmpmemctx );
-
-	Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id_children(\"%s\"): %s (%d)\n",
-		e->e_nname.bv_val,
-		rc == 0 ? "" : ( rc == DB_NOTFOUND ? "no " :
-			db_strerror(rc) ), rc );
-
-	return rc;
-}
-
-int
-bdb_dn2idl(
-	Operation *op,
-	DB_TXN *txn,
-	struct berval *ndn,
-	EntryInfo *ei,
-	ID *ids,
-	ID *stack )
-{
-	int		rc;
-	DBT		key;
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	DB *db = bdb->bi_dn2id->bdi_db;
-	int prefix = ( op->ors_scope == LDAP_SCOPE_ONELEVEL )
-		? DN_ONE_PREFIX : DN_SUBTREE_PREFIX;
-
-	Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2idl(\"%s\")\n",
-		ndn->bv_val, 0, 0 );
-
-#ifndef	BDB_MULTIPLE_SUFFIXES
-	if ( prefix == DN_SUBTREE_PREFIX
-		&& ( ei->bei_id == 0 ||
-		( ei->bei_parent->bei_id == 0 && op->o_bd->be_suffix[0].bv_len ))) {
-		BDB_IDL_ALL(bdb, ids);
-		return 0;
-	}
-#endif
-
-	DBTzero( &key );
-	key.size = ndn->bv_len + 2;
-	key.ulen = key.size;
-	key.flags = DB_DBT_USERMEM;
-	key.data = op->o_tmpalloc( key.size, op->o_tmpmemctx );
-	((char *)key.data)[0] = prefix;
-	AC_MEMCPY( &((char *)key.data)[1], ndn->bv_val, key.size - 1 );
-
-	BDB_IDL_ZERO( ids );
-	rc = bdb_idl_fetch_key( op->o_bd, db, txn, &key, ids, NULL, 0 );
-
-	if( rc != 0 ) {
-		Debug( LDAP_DEBUG_TRACE,
-			"<= bdb_dn2idl: get failed: %s (%d)\n",
-			db_strerror( rc ), rc, 0 );
-
-	} else {
-		Debug( LDAP_DEBUG_TRACE,
-			"<= bdb_dn2idl: id=%ld first=%ld last=%ld\n",
-			(long) ids[0],
-			(long) BDB_IDL_FIRST( ids ), (long) BDB_IDL_LAST( ids ) );
-	}
-
-	op->o_tmpfree( key.data, op->o_tmpmemctx );
-	return rc;
-}
-
-#else	/* BDB_HIER */
-/* Management routines for a hierarchically structured database.
- *
- * Instead of a ldbm-style dn2id database, we use a hierarchical one. Each
- * entry in this database is a struct diskNode, keyed by entryID and with
- * the data containing the RDN and entryID of the node's children. We use
- * a B-Tree with sorted duplicates to store all the children of a node under
- * the same key. Also, the first item under the key contains the entry's own
- * rdn and the ID of the node's parent, to allow bottom-up tree traversal as
- * well as top-down. To keep this info first in the list, the high bit of all
- * subsequent nrdnlen's is always set. This means we can only accomodate
- * RDNs up to length 32767, but that's fine since full DNs are already
- * restricted to 8192.
- *
- * The diskNode is a variable length structure. This definition is not
- * directly usable for in-memory manipulation.
- */
-typedef struct diskNode {
-	unsigned char nrdnlen[2];
-	char nrdn[1];
-	char rdn[1];                        /* variable placement */
-	unsigned char entryID[sizeof(ID)];  /* variable placement */
-} diskNode;
-
-/* Sort function for the sorted duplicate data items of a dn2id key.
- * Sorts based on normalized RDN, in length order.
- */
-int
-hdb_dup_compare(
-	DB *db, 
-	const DBT *usrkey,
-	const DBT *curkey
-)
-{
-	diskNode *un, *cn;
-	int rc;
-
-	un = (diskNode *)usrkey->data;
-	cn = (diskNode *)curkey->data;
-
-	/* data is not aligned, cannot compare directly */
-	rc = un->nrdnlen[0] - cn->nrdnlen[0];
-	if ( rc ) return rc;
-	rc = un->nrdnlen[1] - cn->nrdnlen[1];
-	if ( rc ) return rc;
-
-	return strcmp( un->nrdn, cn->nrdn );
-}
-
-/* This function constructs a full DN for a given entry.
- */
-int hdb_fix_dn(
-	Entry *e,
-	int checkit )
-{
-	EntryInfo *ei;
-	int rlen = 0, nrlen = 0;
-	char *ptr, *nptr;
-	int max = 0;
-
-	if ( !e->e_id )
-		return 0;
-
-	/* count length of all DN components */
-	for ( ei = BEI(e); ei && ei->bei_id; ei=ei->bei_parent ) {
-		rlen += ei->bei_rdn.bv_len + 1;
-		nrlen += ei->bei_nrdn.bv_len + 1;
-		if (ei->bei_modrdns > max) max = ei->bei_modrdns;
-	}
-
-	/* See if the entry DN was invalidated by a subtree rename */
-	if ( checkit ) {
-		if ( BEI(e)->bei_modrdns >= max ) {
-			return 0;
-		}
-		/* We found a mismatch, tell the caller to lock it */
-		if ( checkit == 1 ) {
-			return 1;
-		}
-		/* checkit == 2. do the fix. */
-		free( e->e_name.bv_val );
-		free( e->e_nname.bv_val );
-	}
-
-	e->e_name.bv_len = rlen - 1;
-	e->e_nname.bv_len = nrlen - 1;
-	e->e_name.bv_val = ch_malloc(rlen);
-	e->e_nname.bv_val = ch_malloc(nrlen);
-	ptr = e->e_name.bv_val;
-	nptr = e->e_nname.bv_val;
-	for ( ei = BEI(e); ei && ei->bei_id; ei=ei->bei_parent ) {
-		ptr = lutil_strcopy(ptr, ei->bei_rdn.bv_val);
-		nptr = lutil_strcopy(nptr, ei->bei_nrdn.bv_val);
-		if ( ei->bei_parent ) {
-			*ptr++ = ',';
-			*nptr++ = ',';
-		}
-	}
-	BEI(e)->bei_modrdns = max;
-	if ( ptr > e->e_name.bv_val ) ptr[-1] = '\0';
-	if ( nptr > e->e_nname.bv_val ) nptr[-1] = '\0';
-
-	return 0;
-}
-
-/* We add two elements to the DN2ID database - a data item under the parent's
- * entryID containing the child's RDN and entryID, and an item under the
- * child's entryID containing the parent's entryID.
- */
-int
-hdb_dn2id_add(
-	Operation	*op,
-	DB_TXN *txn,
-	EntryInfo	*eip,
-	Entry		*e )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	DB *db = bdb->bi_dn2id->bdi_db;
-	DBT		key, data;
-	ID		nid;
-	int		rc, rlen, nrlen;
-	diskNode *d;
-	char *ptr;
-
-	Debug( LDAP_DEBUG_TRACE, "=> hdb_dn2id_add 0x%lx: \"%s\"\n",
-		e->e_id, e->e_ndn, 0 );
-
-	nrlen = dn_rdnlen( op->o_bd, &e->e_nname );
-	if (nrlen) {
-		rlen = dn_rdnlen( op->o_bd, &e->e_name );
-	} else {
-		nrlen = e->e_nname.bv_len;
-		rlen = e->e_name.bv_len;
-	}
-
-	d = op->o_tmpalloc(sizeof(diskNode) + rlen + nrlen, op->o_tmpmemctx);
-	d->nrdnlen[1] = nrlen & 0xff;
-	d->nrdnlen[0] = (nrlen >> 8) | 0x80;
-	ptr = lutil_strncopy( d->nrdn, e->e_nname.bv_val, nrlen );
-	*ptr++ = '\0';
-	ptr = lutil_strncopy( ptr, e->e_name.bv_val, rlen );
-	*ptr++ = '\0';
-	BDB_ID2DISK( e->e_id, ptr );
-
-	DBTzero(&key);
-	DBTzero(&data);
-	key.size = sizeof(ID);
-	key.flags = DB_DBT_USERMEM;
-	BDB_ID2DISK( eip->bei_id, &nid );
-
-	key.data = &nid;
-
-	/* Need to make dummy root node once. Subsequent attempts
-	 * will fail harmlessly.
-	 */
-	if ( eip->bei_id == 0 ) {
-		diskNode dummy = {{0, 0}, "", "", ""};
-		data.data = &dummy;
-		data.size = sizeof(diskNode);
-		data.flags = DB_DBT_USERMEM;
-
-		db->put( db, txn, &key, &data, DB_NODUPDATA );
-	}
-
-	data.data = d;
-	data.size = sizeof(diskNode) + rlen + nrlen;
-	data.flags = DB_DBT_USERMEM;
-
-	rc = db->put( db, txn, &key, &data, DB_NODUPDATA );
-
-	if (rc == 0) {
-		BDB_ID2DISK( e->e_id, &nid );
-		BDB_ID2DISK( eip->bei_id, ptr );
-		d->nrdnlen[0] ^= 0x80;
-
-		rc = db->put( db, txn, &key, &data, DB_NODUPDATA );
-	}
-
-	/* Update all parents' IDL cache entries */
-	if ( rc == 0 && bdb->bi_idl_cache_size ) {
-		ID tmp[2];
-		char *ptr = ((char *)&tmp[1])-1;
-		key.data = ptr;
-		key.size = sizeof(ID)+1;
-		tmp[1] = eip->bei_id;
-		*ptr = DN_ONE_PREFIX;
-		bdb_idl_cache_add_id( bdb, db, &key, e->e_id );
-		if ( eip->bei_parent ) {
-			*ptr = DN_SUBTREE_PREFIX;
-			for (; eip && eip->bei_parent->bei_id; eip = eip->bei_parent) {
-				tmp[1] = eip->bei_id;
-				bdb_idl_cache_add_id( bdb, db, &key, e->e_id );
-			}
-			/* Handle DB with empty suffix */
-			if ( !op->o_bd->be_suffix[0].bv_len && eip ) {
-				tmp[1] = eip->bei_id;
-				bdb_idl_cache_add_id( bdb, db, &key, e->e_id );
-			}
-		}
-	}
-
-	op->o_tmpfree( d, op->o_tmpmemctx );
-	Debug( LDAP_DEBUG_TRACE, "<= hdb_dn2id_add 0x%lx: %d\n", e->e_id, rc, 0 );
-
-	return rc;
-}
-
-int
-hdb_dn2id_delete(
-	Operation	*op,
-	DB_TXN *txn,
-	EntryInfo	*eip,
-	Entry	*e )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	DB *db = bdb->bi_dn2id->bdi_db;
-	DBT		key, data;
-	DBC	*cursor;
-	diskNode *d;
-	int rc;
-	ID	nid;
-	unsigned char dlen[2];
-
-	Debug( LDAP_DEBUG_TRACE, "=> hdb_dn2id_delete 0x%lx: \"%s\"\n",
-		e->e_id, e->e_ndn, 0 );
-
-	DBTzero(&key);
-	key.size = sizeof(ID);
-	key.ulen = key.size;
-	key.flags = DB_DBT_USERMEM;
-	BDB_ID2DISK( eip->bei_id, &nid );
-
-	DBTzero(&data);
-	data.size = sizeof(diskNode) + BEI(e)->bei_nrdn.bv_len - sizeof(ID) - 1;
-	data.ulen = data.size;
-	data.dlen = data.size;
-	data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
-
-	key.data = &nid;
-
-	d = op->o_tmpalloc( data.size, op->o_tmpmemctx );
-	d->nrdnlen[1] = BEI(e)->bei_nrdn.bv_len & 0xff;
-	d->nrdnlen[0] = (BEI(e)->bei_nrdn.bv_len >> 8) | 0x80;
-	dlen[0] = d->nrdnlen[0];
-	dlen[1] = d->nrdnlen[1];
-	memcpy( d->nrdn, BEI(e)->bei_nrdn.bv_val, BEI(e)->bei_nrdn.bv_len+1 );
-	data.data = d;
-
-	rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
-	if ( rc ) goto func_leave;
-
-	/* Delete our ID from the parent's list */
-	rc = cursor->c_get( cursor, &key, &data, DB_GET_BOTH_RANGE );
-	if ( rc == 0 ) {
-		if ( dlen[1] == d->nrdnlen[1] && dlen[0] == d->nrdnlen[0] &&
-			!strcmp( d->nrdn, BEI(e)->bei_nrdn.bv_val ))
-			rc = cursor->c_del( cursor, 0 );
-		else
-			rc = DB_NOTFOUND;
-	}
-
-	/* Delete our ID from the tree. With sorted duplicates, this
-	 * will leave any child nodes still hanging around. This is OK
-	 * for modrdn, which will add our info back in later.
-	 */
-	if ( rc == 0 ) {
-		BDB_ID2DISK( e->e_id, &nid );
-		rc = cursor->c_get( cursor, &key, &data, DB_SET );
-		if ( rc == 0 )
-			rc = cursor->c_del( cursor, 0 );
-	}
-
-	cursor->c_close( cursor );
-func_leave:
-	op->o_tmpfree( d, op->o_tmpmemctx );
-
-	/* Delete IDL cache entries */
-	if ( rc == 0 && bdb->bi_idl_cache_size ) {
-		ID tmp[2];
-		char *ptr = ((char *)&tmp[1])-1;
-		key.data = ptr;
-		key.size = sizeof(ID)+1;
-		tmp[1] = eip->bei_id;
-		*ptr = DN_ONE_PREFIX;
-		bdb_idl_cache_del_id( bdb, db, &key, e->e_id );
-		if ( eip ->bei_parent ) {
-			*ptr = DN_SUBTREE_PREFIX;
-			for (; eip && eip->bei_parent->bei_id; eip = eip->bei_parent) {
-				tmp[1] = eip->bei_id;
-				bdb_idl_cache_del_id( bdb, db, &key, e->e_id );
-			}
-			/* Handle DB with empty suffix */
-			if ( !op->o_bd->be_suffix[0].bv_len && eip ) {
-				tmp[1] = eip->bei_id;
-				bdb_idl_cache_del_id( bdb, db, &key, e->e_id );
-			}
-		}
-	}
-	Debug( LDAP_DEBUG_TRACE, "<= hdb_dn2id_delete 0x%lx: %d\n", e->e_id, rc, 0 );
-	return rc;
-}
-
-
-int
-hdb_dn2id(
-	Operation	*op,
-	struct berval	*in,
-	EntryInfo	*ei,
-	DB_TXN *txn,
-	DBC **cursor )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	DB *db = bdb->bi_dn2id->bdi_db;
-	DBT		key, data;
-	int		rc = 0, nrlen;
-	diskNode *d;
-	char	*ptr;
-	unsigned char dlen[2];
-	ID idp, parentID;
-
-	Debug( LDAP_DEBUG_TRACE, "=> hdb_dn2id(\"%s\")\n", in->bv_val, 0, 0 );
-
-	nrlen = dn_rdnlen( op->o_bd, in );
-	if (!nrlen) nrlen = in->bv_len;
-
-	DBTzero(&key);
-	key.size = sizeof(ID);
-	key.data = &idp;
-	key.ulen = sizeof(ID);
-	key.flags = DB_DBT_USERMEM;
-	parentID = ( ei->bei_parent != NULL ) ? ei->bei_parent->bei_id : 0;
-	BDB_ID2DISK( parentID, &idp );
-
-	DBTzero(&data);
-	data.size = sizeof(diskNode) + nrlen - sizeof(ID) - 1;
-	data.ulen = data.size * 3;
-	data.dlen = data.ulen;
-	data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
-
-	rc = db->cursor( db, txn, cursor, bdb->bi_db_opflags );
-	if ( rc ) return rc;
-
-	d = op->o_tmpalloc( data.size * 3, op->o_tmpmemctx );
-	d->nrdnlen[1] = nrlen & 0xff;
-	d->nrdnlen[0] = (nrlen >> 8) | 0x80;
-	dlen[0] = d->nrdnlen[0];
-	dlen[1] = d->nrdnlen[1];
-	ptr = lutil_strncopy( d->nrdn, in->bv_val, nrlen );
-	*ptr = '\0';
-	data.data = d;
-
-	rc = (*cursor)->c_get( *cursor, &key, &data, DB_GET_BOTH_RANGE );
-	if ( rc == 0 && (dlen[1] != d->nrdnlen[1] || dlen[0] != d->nrdnlen[0] ||
-		strncmp( d->nrdn, in->bv_val, nrlen ))) {
-		rc = DB_NOTFOUND;
-	}
-	if ( rc == 0 ) {
-		ptr = (char *) data.data + data.size - sizeof(ID);
-		BDB_DISK2ID( ptr, &ei->bei_id );
-		ei->bei_rdn.bv_len = data.size - sizeof(diskNode) - nrlen;
-		ptr = d->nrdn + nrlen + 1;
-		ber_str2bv( ptr, ei->bei_rdn.bv_len, 1, &ei->bei_rdn );
-		if ( ei->bei_parent != NULL && !ei->bei_parent->bei_dkids ) {
-			db_recno_t dkids;
-			/* How many children does the parent have? */
-			/* FIXME: do we need to lock the parent
-			 * entryinfo? Seems safe...
-			 */
-			(*cursor)->c_count( *cursor, &dkids, 0 );
-			ei->bei_parent->bei_dkids = dkids;
-		}
-	}
-
-	op->o_tmpfree( d, op->o_tmpmemctx );
-	if( rc != 0 ) {
-		Debug( LDAP_DEBUG_TRACE, "<= hdb_dn2id: get failed: %s (%d)\n",
-			db_strerror( rc ), rc, 0 );
-	} else {
-		Debug( LDAP_DEBUG_TRACE, "<= hdb_dn2id: got id=0x%lx\n",
-			ei->bei_id, 0, 0 );
-	}
-
-	return rc;
-}
-
-int
-hdb_dn2id_parent(
-	Operation *op,
-	DB_TXN *txn,
-	EntryInfo *ei,
-	ID *idp )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	DB *db = bdb->bi_dn2id->bdi_db;
-	DBT		key, data;
-	DBC	*cursor;
-	int		rc = 0;
-	diskNode *d;
-	char	*ptr;
-	ID	nid;
-
-	DBTzero(&key);
-	key.size = sizeof(ID);
-	key.data = &nid;
-	key.ulen = sizeof(ID);
-	key.flags = DB_DBT_USERMEM;
-	BDB_ID2DISK( ei->bei_id, &nid );
-
-	DBTzero(&data);
-	data.flags = DB_DBT_USERMEM;
-
-	rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
-	if ( rc ) return rc;
-
-	data.ulen = sizeof(diskNode) + (SLAP_LDAPDN_MAXLEN * 2);
-	d = op->o_tmpalloc( data.ulen, op->o_tmpmemctx );
-	data.data = d;
-
-	rc = cursor->c_get( cursor, &key, &data, DB_SET );
-	if ( rc == 0 ) {
-		if (d->nrdnlen[0] & 0x80) {
-			rc = LDAP_OTHER;
-		} else {
-			db_recno_t dkids;
-			ptr = (char *) data.data + data.size - sizeof(ID);
-			BDB_DISK2ID( ptr, idp );
-			ei->bei_nrdn.bv_len = (d->nrdnlen[0] << 8) | d->nrdnlen[1];
-			ber_str2bv( d->nrdn, ei->bei_nrdn.bv_len, 1, &ei->bei_nrdn );
-			ei->bei_rdn.bv_len = data.size - sizeof(diskNode) -
-				ei->bei_nrdn.bv_len;
-			ptr = d->nrdn + ei->bei_nrdn.bv_len + 1;
-			ber_str2bv( ptr, ei->bei_rdn.bv_len, 1, &ei->bei_rdn );
-			/* How many children does this node have? */
-			cursor->c_count( cursor, &dkids, 0 );
-			ei->bei_dkids = dkids;
-		}
-	}
-	cursor->c_close( cursor );
-	op->o_tmpfree( d, op->o_tmpmemctx );
-	return rc;
-}
-
-int
-hdb_dn2id_children(
-	Operation *op,
-	DB_TXN *txn,
-	Entry *e )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	DB *db = bdb->bi_dn2id->bdi_db;
-	DBT		key, data;
-	DBC		*cursor;
-	int		rc;
-	ID		id;
-	diskNode d;
-
-	DBTzero(&key);
-	key.size = sizeof(ID);
-	key.data = &e->e_id;
-	key.flags = DB_DBT_USERMEM;
-	BDB_ID2DISK( e->e_id, &id );
-
-	/* IDL cache is in host byte order */
-	if ( bdb->bi_idl_cache_size ) {
-		rc = bdb_idl_cache_get( bdb, db, &key, NULL );
-		if ( rc != LDAP_NO_SUCH_OBJECT ) {
-			return rc;
-		}
-	}
-
-	key.data = &id;
-	DBTzero(&data);
-	data.data = &d;
-	data.ulen = sizeof(d);
-	data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
-	data.dlen = sizeof(d);
-
-	rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
-	if ( rc ) return rc;
-
-	rc = cursor->c_get( cursor, &key, &data, DB_SET );
-	if ( rc == 0 ) {
-		db_recno_t dkids;
-		rc = cursor->c_count( cursor, &dkids, 0 );
-		if ( rc == 0 ) {
-			BEI(e)->bei_dkids = dkids;
-			if ( dkids < 2 ) rc = DB_NOTFOUND;
-		}
-	}
-	cursor->c_close( cursor );
-	return rc;
-}
-
-/* bdb_dn2idl:
- * We can't just use bdb_idl_fetch_key because
- * 1 - our data items are longer than just an entry ID
- * 2 - our data items are sorted alphabetically by nrdn, not by ID.
- *
- * We descend the tree recursively, so we define this cookie
- * to hold our necessary state information. The bdb_dn2idl_internal
- * function uses this cookie when calling itself.
- */
-
-struct dn2id_cookie {
-	struct bdb_info *bdb;
-	Operation *op;
-	DB_TXN *txn;
-	EntryInfo *ei;
-	ID *ids;
-	ID *tmp;
-	ID *buf;
-	DB *db;
-	DBC *dbc;
-	DBT key;
-	DBT data;
-	ID dbuf;
-	ID id;
-	ID nid;
-	int rc;
-	int depth;
-	char need_sort;
-	char prefix;
-};
-
-static int
-apply_func(
-	void *data,
-	void *arg )
-{
-	EntryInfo *ei = data;
-	ID *idl = arg;
-
-	bdb_idl_append_one( idl, ei->bei_id );
-	return 0;
-}
-
-static int
-hdb_dn2idl_internal(
-	struct dn2id_cookie *cx
-)
-{
-	BDB_IDL_ZERO( cx->tmp );
-
-	if ( cx->bdb->bi_idl_cache_size ) {
-		char *ptr = ((char *)&cx->id)-1;
-
-		cx->key.data = ptr;
-		cx->key.size = sizeof(ID)+1;
-		if ( cx->prefix == DN_SUBTREE_PREFIX ) {
-			ID *ids = cx->depth ? cx->tmp : cx->ids;
-			*ptr = cx->prefix;
-			cx->rc = bdb_idl_cache_get(cx->bdb, cx->db, &cx->key, ids);
-			if ( cx->rc == LDAP_SUCCESS ) {
-				if ( cx->depth ) {
-					bdb_idl_delete( cx->tmp, cx->id );	/* ITS#6983, drop our own ID */
-					bdb_idl_append( cx->ids, cx->tmp );
-					cx->need_sort = 1;
-				}
-				return cx->rc;
-			}
-		}
-		*ptr = DN_ONE_PREFIX;
-		cx->rc = bdb_idl_cache_get(cx->bdb, cx->db, &cx->key, cx->tmp);
-		if ( cx->rc == LDAP_SUCCESS ) {
-			goto gotit;
-		}
-		if ( cx->rc == DB_NOTFOUND ) {
-			return cx->rc;
-		}
-	}
-
-	bdb_cache_entryinfo_lock( cx->ei );
-
-	/* If number of kids in the cache differs from on-disk, load
-	 * up all the kids from the database
-	 */
-	if ( cx->ei->bei_ckids+1 != cx->ei->bei_dkids ) {
-		EntryInfo ei;
-		db_recno_t dkids = cx->ei->bei_dkids;
-		ei.bei_parent = cx->ei;
-
-		/* Only one thread should load the cache */
-		while ( cx->ei->bei_state & CACHE_ENTRY_ONELEVEL ) {
-			bdb_cache_entryinfo_unlock( cx->ei );
-			ldap_pvt_thread_yield();
-			bdb_cache_entryinfo_lock( cx->ei );
-			if ( cx->ei->bei_ckids+1 == cx->ei->bei_dkids ) {
-				goto synced;
-			}
-		}
-
-		cx->ei->bei_state |= CACHE_ENTRY_ONELEVEL;
-
-		bdb_cache_entryinfo_unlock( cx->ei );
-
-		cx->rc = cx->db->cursor( cx->db, NULL, &cx->dbc,
-			cx->bdb->bi_db_opflags );
-		if ( cx->rc )
-			goto done_one;
-
-		cx->data.data = &cx->dbuf;
-		cx->data.ulen = sizeof(ID);
-		cx->data.dlen = sizeof(ID);
-		cx->data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
-
-		/* The first item holds the parent ID. Ignore it. */
-		cx->key.data = &cx->nid;
-		cx->key.size = sizeof(ID);
-		cx->rc = cx->dbc->c_get( cx->dbc, &cx->key, &cx->data, DB_SET );
-		if ( cx->rc ) {
-			cx->dbc->c_close( cx->dbc );
-			goto done_one;
-		}
-
-		/* If the on-disk count is zero we've never checked it.
-		 * Count it now.
-		 */
-		if ( !dkids ) {
-			cx->dbc->c_count( cx->dbc, &dkids, 0 );
-			cx->ei->bei_dkids = dkids;
-		}
-
-		cx->data.data = cx->buf;
-		cx->data.ulen = BDB_IDL_UM_SIZE * sizeof(ID);
-		cx->data.flags = DB_DBT_USERMEM;
-
-		if ( dkids > 1 ) {
-			/* Fetch the rest of the IDs in a loop... */
-			while ( (cx->rc = cx->dbc->c_get( cx->dbc, &cx->key, &cx->data,
-				DB_MULTIPLE | DB_NEXT_DUP )) == 0 ) {
-				u_int8_t *j;
-				size_t len;
-				void *ptr;
-				DB_MULTIPLE_INIT( ptr, &cx->data );
-				while (ptr) {
-					DB_MULTIPLE_NEXT( ptr, &cx->data, j, len );
-					if (j) {
-						EntryInfo *ei2;
-						diskNode *d = (diskNode *)j;
-						short nrlen;
-
-						BDB_DISK2ID( j + len - sizeof(ID), &ei.bei_id );
-						nrlen = ((d->nrdnlen[0] ^ 0x80) << 8) | d->nrdnlen[1];
-						ei.bei_nrdn.bv_len = nrlen;
-						/* nrdn/rdn are set in-place.
-						 * hdb_cache_load will copy them as needed
-						 */
-						ei.bei_nrdn.bv_val = d->nrdn;
-						ei.bei_rdn.bv_len = len - sizeof(diskNode)
-							- ei.bei_nrdn.bv_len;
-						ei.bei_rdn.bv_val = d->nrdn + ei.bei_nrdn.bv_len + 1;
-						bdb_idl_append_one( cx->tmp, ei.bei_id );
-						hdb_cache_load( cx->bdb, &ei, &ei2 );
-					}
-				}
-			}
-		}
-
-		cx->rc = cx->dbc->c_close( cx->dbc );
-done_one:
-		bdb_cache_entryinfo_lock( cx->ei );
-		cx->ei->bei_state &= ~CACHE_ENTRY_ONELEVEL;
-		bdb_cache_entryinfo_unlock( cx->ei );
-		if ( cx->rc )
-			return cx->rc;
-
-	} else {
-		/* The in-memory cache is in sync with the on-disk data.
-		 * do we have any kids?
-		 */
-synced:
-		cx->rc = 0;
-		if ( cx->ei->bei_ckids > 0 ) {
-			/* Walk the kids tree; order is irrelevant since bdb_idl_sort
-			 * will sort it later.
-			 */
-			avl_apply( cx->ei->bei_kids, apply_func,
-				cx->tmp, -1, AVL_POSTORDER );
-		}
-		bdb_cache_entryinfo_unlock( cx->ei );
-	}
-
-	if ( !BDB_IDL_IS_RANGE( cx->tmp ) && cx->tmp[0] > 3 )
-		bdb_idl_sort( cx->tmp, cx->buf );
-	if ( cx->bdb->bi_idl_cache_max_size && !BDB_IDL_IS_ZERO( cx->tmp )) {
-		char *ptr = ((char *)&cx->id)-1;
-		cx->key.data = ptr;
-		cx->key.size = sizeof(ID)+1;
-		*ptr = DN_ONE_PREFIX;
-		bdb_idl_cache_put( cx->bdb, cx->db, &cx->key, cx->tmp, cx->rc );
-	}
-
-gotit:
-	if ( !BDB_IDL_IS_ZERO( cx->tmp )) {
-		if ( cx->prefix == DN_SUBTREE_PREFIX ) {
-			bdb_idl_append( cx->ids, cx->tmp );
-			cx->need_sort = 1;
-			if ( !(cx->ei->bei_state & CACHE_ENTRY_NO_GRANDKIDS)) {
-				ID *save, idcurs;
-				EntryInfo *ei = cx->ei;
-				int nokids = 1;
-				save = cx->op->o_tmpalloc( BDB_IDL_SIZEOF( cx->tmp ),
-					cx->op->o_tmpmemctx );
-				BDB_IDL_CPY( save, cx->tmp );
-
-				idcurs = 0;
-				cx->depth++;
-				for ( cx->id = bdb_idl_first( save, &idcurs );
-					cx->id != NOID;
-					cx->id = bdb_idl_next( save, &idcurs )) {
-					EntryInfo *ei2;
-					cx->ei = NULL;
-					if ( bdb_cache_find_id( cx->op, cx->txn, cx->id, &cx->ei,
-						ID_NOENTRY, NULL ))
-						continue;
-					if ( cx->ei ) {
-						ei2 = cx->ei;
-						if ( !( ei2->bei_state & CACHE_ENTRY_NO_KIDS )) {
-							BDB_ID2DISK( cx->id, &cx->nid );
-							hdb_dn2idl_internal( cx );
-							if ( !BDB_IDL_IS_ZERO( cx->tmp ))
-								nokids = 0;
-						}
-						bdb_cache_entryinfo_lock( ei2 );
-						ei2->bei_finders--;
-						bdb_cache_entryinfo_unlock( ei2 );
-					}
-				}
-				cx->depth--;
-				cx->op->o_tmpfree( save, cx->op->o_tmpmemctx );
-				if ( nokids ) {
-					bdb_cache_entryinfo_lock( ei );
-					ei->bei_state |= CACHE_ENTRY_NO_GRANDKIDS;
-					bdb_cache_entryinfo_unlock( ei );
-				}
-			}
-			/* Make sure caller knows it had kids! */
-			cx->tmp[0]=1;
-
-			cx->rc = 0;
-		} else {
-			BDB_IDL_CPY( cx->ids, cx->tmp );
-		}
-	}
-	return cx->rc;
-}
-
-int
-hdb_dn2idl(
-	Operation	*op,
-	DB_TXN *txn,
-	struct berval *ndn,
-	EntryInfo	*ei,
-	ID *ids,
-	ID *stack )
-{
-	struct bdb_info *bdb = (struct bdb_info *)op->o_bd->be_private;
-	struct dn2id_cookie cx;
-
-	Debug( LDAP_DEBUG_TRACE, "=> hdb_dn2idl(\"%s\")\n",
-		ndn->bv_val, 0, 0 );
-
-#ifndef BDB_MULTIPLE_SUFFIXES
-	if ( op->ors_scope != LDAP_SCOPE_ONELEVEL && 
-		( ei->bei_id == 0 ||
-		( ei->bei_parent->bei_id == 0 && op->o_bd->be_suffix[0].bv_len )))
-	{
-		BDB_IDL_ALL( bdb, ids );
-		return 0;
-	}
-#endif
-
-	cx.id = ei->bei_id;
-	BDB_ID2DISK( cx.id, &cx.nid );
-	cx.ei = ei;
-	cx.bdb = bdb;
-	cx.db = cx.bdb->bi_dn2id->bdi_db;
-	cx.prefix = (op->ors_scope == LDAP_SCOPE_ONELEVEL) ?
-		DN_ONE_PREFIX : DN_SUBTREE_PREFIX;
-	cx.ids = ids;
-	cx.tmp = stack;
-	cx.buf = stack + BDB_IDL_UM_SIZE;
-	cx.op = op;
-	cx.txn = txn;
-	cx.need_sort = 0;
-	cx.depth = 0;
-
-	if ( cx.prefix == DN_SUBTREE_PREFIX ) {
-		ids[0] = 1;
-		ids[1] = cx.id;
-	} else {
-		BDB_IDL_ZERO( ids );
-	}
-	if ( cx.ei->bei_state & CACHE_ENTRY_NO_KIDS )
-		return LDAP_SUCCESS;
-
-	DBTzero(&cx.key);
-	cx.key.ulen = sizeof(ID);
-	cx.key.size = sizeof(ID);
-	cx.key.flags = DB_DBT_USERMEM;
-
-	DBTzero(&cx.data);
-
-	hdb_dn2idl_internal(&cx);
-	if ( cx.need_sort ) {
-		char *ptr = ((char *)&cx.id)-1;
-		if ( !BDB_IDL_IS_RANGE( cx.ids ) && cx.ids[0] > 3 ) 
-			bdb_idl_sort( cx.ids, cx.tmp );
-		cx.key.data = ptr;
-		cx.key.size = sizeof(ID)+1;
-		*ptr = cx.prefix;
-		cx.id = ei->bei_id;
-		if ( cx.bdb->bi_idl_cache_max_size )
-			bdb_idl_cache_put( cx.bdb, cx.db, &cx.key, cx.ids, cx.rc );
-	}
-
-	if ( cx.rc == DB_NOTFOUND )
-		cx.rc = LDAP_SUCCESS;
-
-	return cx.rc;
-}
-#endif	/* BDB_HIER */
diff --git a/servers/slapd/back-bdb/error.c b/servers/slapd/back-bdb/error.c
deleted file mode 100644
index cf823ec..0000000
--- a/servers/slapd/back-bdb/error.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/* error.c - BDB errcall routine */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "slap.h"
-#include "back-bdb.h"
-
-#if DB_VERSION_FULL < 0x04030000
-void bdb_errcall( const char *pfx, char * msg )
-#else
-void bdb_errcall( const DB_ENV *env, const char *pfx, const char * msg )
-#endif
-{
-#ifdef HAVE_EBCDIC
-	if ( msg[0] > 0x7f )
-		__etoa( msg );
-#endif
-	Debug( LDAP_DEBUG_ANY, "bdb(%s): %s\n", pfx, msg, 0 );
-}
-
-#if DB_VERSION_FULL >= 0x04030000
-void bdb_msgcall( const DB_ENV *env, const char *msg )
-{
-#ifdef HAVE_EBCDIC
-	if ( msg[0] > 0x7f )
-		__etoa( msg );
-#endif
-	Debug( LDAP_DEBUG_TRACE, "bdb: %s\n", msg, 0, 0 );
-}
-#endif
-
-#ifdef HAVE_EBCDIC
-
-#undef db_strerror
-
-/* Not re-entrant! */
-char *ebcdic_dberror( int rc )
-{
-	static char msg[1024];
-
-	strcpy( msg, db_strerror( rc ) );
-	__etoa( msg );
-	return msg;
-}
-#endif
diff --git a/servers/slapd/back-bdb/extended.c b/servers/slapd/back-bdb/extended.c
deleted file mode 100644
index 74d85df..0000000
--- a/servers/slapd/back-bdb/extended.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/* extended.c - bdb backend extended routines */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "back-bdb.h"
-#include "lber_pvt.h"
-
-static struct exop {
-	struct berval *oid;
-	BI_op_extended	*extended;
-} exop_table[] = {
-	{ NULL, NULL }
-};
-
-int
-bdb_extended( Operation *op, SlapReply *rs )
-/*	struct berval		*reqoid,
-	struct berval	*reqdata,
-	char		**rspoid,
-	struct berval	**rspdata,
-	LDAPControl *** rspctrls,
-	const char**	text,
-	BerVarray	*refs 
-) */
-{
-	int i;
-
-	for( i=0; exop_table[i].extended != NULL; i++ ) {
-		if( ber_bvcmp( exop_table[i].oid, &op->oq_extended.rs_reqoid ) == 0 ) {
-			return (exop_table[i].extended)( op, rs );
-		}
-	}
-
-	rs->sr_text = "not supported within naming context";
-	return rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
-}
-
diff --git a/servers/slapd/back-bdb/filterindex.c b/servers/slapd/back-bdb/filterindex.c
deleted file mode 100644
index c04c68c..0000000
--- a/servers/slapd/back-bdb/filterindex.c
+++ /dev/null
@@ -1,1183 +0,0 @@
-/* filterindex.c - generate the list of candidate entries from a filter */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "back-bdb.h"
-#include "idl.h"
-#ifdef LDAP_COMP_MATCH
-#include <component.h>
-#endif
-
-static int presence_candidates(
-	Operation *op,
-	DB_TXN *rtxn,
-	AttributeDescription *desc,
-	ID *ids );
-
-static int equality_candidates(
-	Operation *op,
-	DB_TXN *rtxn,
-	AttributeAssertion *ava,
-	ID *ids,
-	ID *tmp );
-static int inequality_candidates(
-	Operation *op,
-	DB_TXN *rtxn,
-	AttributeAssertion *ava,
-	ID *ids,
-	ID *tmp,
-	int gtorlt );
-static int approx_candidates(
-	Operation *op,
-	DB_TXN *rtxn,
-	AttributeAssertion *ava,
-	ID *ids,
-	ID *tmp );
-static int substring_candidates(
-	Operation *op,
-	DB_TXN *rtxn,
-	SubstringsAssertion *sub,
-	ID *ids,
-	ID *tmp );
-
-static int list_candidates(
-	Operation *op,
-	DB_TXN *rtxn,
-	Filter *flist,
-	int ftype,
-	ID *ids,
-	ID *tmp,
-	ID *stack );
-
-static int
-ext_candidates(
-        Operation *op,
-		DB_TXN *rtxn,
-        MatchingRuleAssertion *mra,
-        ID *ids,
-        ID *tmp,
-        ID *stack);
-
-#ifdef LDAP_COMP_MATCH
-static int
-comp_candidates (
-	Operation *op,
-	DB_TXN *rtxn,
-	MatchingRuleAssertion *mra,
-	ComponentFilter *f,
-	ID *ids,
-	ID *tmp,
-	ID *stack);
-
-static int
-ava_comp_candidates (
-		Operation *op,
-		DB_TXN *rtxn,
-		AttributeAssertion *ava,
-		AttributeAliasing *aa,
-		ID *ids,
-		ID *tmp,
-		ID *stack);
-#endif
-
-int
-bdb_filter_candidates(
-	Operation *op,
-	DB_TXN *rtxn,
-	Filter	*f,
-	ID *ids,
-	ID *tmp,
-	ID *stack )
-{
-	int rc = 0;
-#ifdef LDAP_COMP_MATCH
-	AttributeAliasing *aa;
-#endif
-	Debug( LDAP_DEBUG_FILTER, "=> bdb_filter_candidates\n", 0, 0, 0 );
-
-	if ( f->f_choice & SLAPD_FILTER_UNDEFINED ) {
-		BDB_IDL_ZERO( ids );
-		goto out;
-	}
-
-	switch ( f->f_choice ) {
-	case SLAPD_FILTER_COMPUTED:
-		switch( f->f_result ) {
-		case SLAPD_COMPARE_UNDEFINED:
-		/* This technically is not the same as FALSE, but it
-		 * certainly will produce no matches.
-		 */
-		/* FALL THRU */
-		case LDAP_COMPARE_FALSE:
-			BDB_IDL_ZERO( ids );
-			break;
-		case LDAP_COMPARE_TRUE: {
-			struct bdb_info *bdb = (struct bdb_info *)op->o_bd->be_private;
-			BDB_IDL_ALL( bdb, ids );
-			} break;
-		case LDAP_SUCCESS:
-			/* this is a pre-computed scope, leave it alone */
-			break;
-		}
-		break;
-	case LDAP_FILTER_PRESENT:
-		Debug( LDAP_DEBUG_FILTER, "\tPRESENT\n", 0, 0, 0 );
-		rc = presence_candidates( op, rtxn, f->f_desc, ids );
-		break;
-
-	case LDAP_FILTER_EQUALITY:
-		Debug( LDAP_DEBUG_FILTER, "\tEQUALITY\n", 0, 0, 0 );
-#ifdef LDAP_COMP_MATCH
-		if ( is_aliased_attribute && ( aa = is_aliased_attribute ( f->f_ava->aa_desc ) ) ) {
-			rc = ava_comp_candidates ( op, rtxn, f->f_ava, aa, ids, tmp, stack );
-		}
-		else
-#endif
-		{
-			rc = equality_candidates( op, rtxn, f->f_ava, ids, tmp );
-		}
-		break;
-
-	case LDAP_FILTER_APPROX:
-		Debug( LDAP_DEBUG_FILTER, "\tAPPROX\n", 0, 0, 0 );
-		rc = approx_candidates( op, rtxn, f->f_ava, ids, tmp );
-		break;
-
-	case LDAP_FILTER_SUBSTRINGS:
-		Debug( LDAP_DEBUG_FILTER, "\tSUBSTRINGS\n", 0, 0, 0 );
-		rc = substring_candidates( op, rtxn, f->f_sub, ids, tmp );
-		break;
-
-	case LDAP_FILTER_GE:
-		/* if no GE index, use pres */
-		Debug( LDAP_DEBUG_FILTER, "\tGE\n", 0, 0, 0 );
-		if( f->f_ava->aa_desc->ad_type->sat_ordering &&
-			( f->f_ava->aa_desc->ad_type->sat_ordering->smr_usage & SLAP_MR_ORDERED_INDEX ) )
-			rc = inequality_candidates( op, rtxn, f->f_ava, ids, tmp, LDAP_FILTER_GE );
-		else
-			rc = presence_candidates( op, rtxn, f->f_ava->aa_desc, ids );
-		break;
-
-	case LDAP_FILTER_LE:
-		/* if no LE index, use pres */
-		Debug( LDAP_DEBUG_FILTER, "\tLE\n", 0, 0, 0 );
-		if( f->f_ava->aa_desc->ad_type->sat_ordering &&
-			( f->f_ava->aa_desc->ad_type->sat_ordering->smr_usage & SLAP_MR_ORDERED_INDEX ) )
-			rc = inequality_candidates( op, rtxn, f->f_ava, ids, tmp, LDAP_FILTER_LE );
-		else
-			rc = presence_candidates( op, rtxn, f->f_ava->aa_desc, ids );
-		break;
-
-	case LDAP_FILTER_NOT:
-		/* no indexing to support NOT filters */
-		Debug( LDAP_DEBUG_FILTER, "\tNOT\n", 0, 0, 0 );
-		{ struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-		BDB_IDL_ALL( bdb, ids );
-		}
-		break;
-
-	case LDAP_FILTER_AND:
-		Debug( LDAP_DEBUG_FILTER, "\tAND\n", 0, 0, 0 );
-		rc = list_candidates( op, rtxn, 
-			f->f_and, LDAP_FILTER_AND, ids, tmp, stack );
-		break;
-
-	case LDAP_FILTER_OR:
-		Debug( LDAP_DEBUG_FILTER, "\tOR\n", 0, 0, 0 );
-		rc = list_candidates( op, rtxn,
-			f->f_or, LDAP_FILTER_OR, ids, tmp, stack );
-		break;
-	case LDAP_FILTER_EXT:
-                Debug( LDAP_DEBUG_FILTER, "\tEXT\n", 0, 0, 0 );
-                rc = ext_candidates( op, rtxn, f->f_mra, ids, tmp, stack );
-                break;
-	default:
-		Debug( LDAP_DEBUG_FILTER, "\tUNKNOWN %lu\n",
-			(unsigned long) f->f_choice, 0, 0 );
-		/* Must not return NULL, otherwise extended filters break */
-		{ struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-		BDB_IDL_ALL( bdb, ids );
-		}
-	}
-
-out:
-	Debug( LDAP_DEBUG_FILTER,
-		"<= bdb_filter_candidates: id=%ld first=%ld last=%ld\n",
-		(long) ids[0],
-		(long) BDB_IDL_FIRST( ids ),
-		(long) BDB_IDL_LAST( ids ) );
-
-	return rc;
-}
-
-#ifdef LDAP_COMP_MATCH
-static int
-comp_list_candidates(
-	Operation *op,
-	DB_TXN *rtxn,
-	MatchingRuleAssertion* mra,
-	ComponentFilter	*flist,
-	int	ftype,
-	ID *ids,
-	ID *tmp,
-	ID *save )
-{
-	int rc = 0;
-	ComponentFilter	*f;
-
-	Debug( LDAP_DEBUG_FILTER, "=> comp_list_candidates 0x%x\n", ftype, 0, 0 );
-	for ( f = flist; f != NULL; f = f->cf_next ) {
-		/* ignore precomputed scopes */
-		if ( f->cf_choice == SLAPD_FILTER_COMPUTED &&
-		     f->cf_result == LDAP_SUCCESS ) {
-			continue;
-		}
-		BDB_IDL_ZERO( save );
-		rc = comp_candidates( op, rtxn, mra, f, save, tmp, save+BDB_IDL_UM_SIZE );
-
-		if ( rc != 0 ) {
-			if ( ftype == LDAP_COMP_FILTER_AND ) {
-				rc = 0;
-				continue;
-			}
-			break;
-		}
-		
-		if ( ftype == LDAP_COMP_FILTER_AND ) {
-			if ( f == flist ) {
-				BDB_IDL_CPY( ids, save );
-			} else {
-				bdb_idl_intersection( ids, save );
-			}
-			if( BDB_IDL_IS_ZERO( ids ) )
-				break;
-		} else {
-			if ( f == flist ) {
-				BDB_IDL_CPY( ids, save );
-			} else {
-				bdb_idl_union( ids, save );
-			}
-		}
-	}
-
-	if( rc == LDAP_SUCCESS ) {
-		Debug( LDAP_DEBUG_FILTER,
-			"<= comp_list_candidates: id=%ld first=%ld last=%ld\n",
-			(long) ids[0],
-			(long) BDB_IDL_FIRST(ids),
-			(long) BDB_IDL_LAST(ids) );
-
-	} else {
-		Debug( LDAP_DEBUG_FILTER,
-			"<= comp_list_candidates: undefined rc=%d\n",
-			rc, 0, 0 );
-	}
-
-	return rc;
-}
-
-static int
-comp_equality_candidates (
-        Operation *op,
-	DB_TXN *rtxn,
-        MatchingRuleAssertion *mra,
-	ComponentAssertion *ca,
-        ID *ids,
-        ID *tmp,
-        ID *stack)
-{
-       struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-        DB      *db;
-        int i;
-        int rc;
-        slap_mask_t mask;
-        struct berval prefix = {0, NULL};
-        struct berval *keys = NULL;
-        MatchingRule *mr = mra->ma_rule;
-        Syntax *sat_syntax;
-	ComponentReference* cr_list, *cr;
-	AttrInfo *ai;
-
-        BDB_IDL_ALL( bdb, ids );
-
-	if ( !ca->ca_comp_ref )
-		return 0;
-
-	ai = bdb_attr_mask( op->o_bd->be_private, mra->ma_desc );
-	if( ai ) {
-		cr_list = ai->ai_cr;
-	}
-	else {
-		return 0;
-	}
-	/* find a component reference to be indexed */
-	sat_syntax = ca->ca_ma_rule->smr_syntax;
-	for ( cr = cr_list ; cr ; cr = cr->cr_next ) {
-		if ( cr->cr_string.bv_len == ca->ca_comp_ref->cr_string.bv_len &&
-			strncmp( cr->cr_string.bv_val, ca->ca_comp_ref->cr_string.bv_val,cr->cr_string.bv_len ) == 0 )
-			break;
-	}
-	
-	if ( !cr )
-		return 0;
-
-        rc = bdb_index_param( op->o_bd, mra->ma_desc, LDAP_FILTER_EQUALITY,
-                &db, &mask, &prefix );
-
-        if( rc != LDAP_SUCCESS ) {
-                return 0;
-        }
-
-        if( !mr ) {
-                return 0;
-        }
-
-        if( !mr->smr_filter ) {
-                return 0;
-        }
-
-	rc = (ca->ca_ma_rule->smr_filter)(
-                LDAP_FILTER_EQUALITY,
-                cr->cr_indexmask,
-                sat_syntax,
-                ca->ca_ma_rule,
-                &prefix,
-                &ca->ca_ma_value,
-                &keys, op->o_tmpmemctx );
-
-        if( rc != LDAP_SUCCESS ) {
-                return 0;
-        }
-
-        if( keys == NULL ) {
-                return 0;
-        }
-        for ( i= 0; keys[i].bv_val != NULL; i++ ) {
-                rc = bdb_key_read( op->o_bd, db, rtxn, &keys[i], tmp, NULL, 0 );
-
-                if( rc == DB_NOTFOUND ) {
-                        BDB_IDL_ZERO( ids );
-                        rc = 0;
-                        break;
-                } else if( rc != LDAP_SUCCESS ) {
-                        break;
-                }
-
-                if( BDB_IDL_IS_ZERO( tmp ) ) {
-                        BDB_IDL_ZERO( ids );
-                        break;
-                }
-
-                if ( i == 0 ) {
-                        BDB_IDL_CPY( ids, tmp );
-                } else {
-                        bdb_idl_intersection( ids, tmp );
-                }
-
-                if( BDB_IDL_IS_ZERO( ids ) )
-                        break;
-        }
-        ber_bvarray_free_x( keys, op->o_tmpmemctx );
-
-        Debug( LDAP_DEBUG_TRACE,
-                "<= comp_equality_candidates: id=%ld, first=%ld, last=%ld\n",
-                (long) ids[0],
-                (long) BDB_IDL_FIRST(ids),
-                (long) BDB_IDL_LAST(ids) );
-        return( rc );
-}
-
-static int
-ava_comp_candidates (
-	Operation *op,
-	DB_TXN *rtxn,
-	AttributeAssertion *ava,
-	AttributeAliasing *aa,
-	ID *ids,
-	ID *tmp,
-	ID *stack )
-{
-	MatchingRuleAssertion mra;
-	
-	mra.ma_rule = ava->aa_desc->ad_type->sat_equality;
-	if ( !mra.ma_rule ) {
-		struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-		BDB_IDL_ALL( bdb, ids );
-		return 0;
-	}
-	mra.ma_desc = aa->aa_aliased_ad;
-	mra.ma_rule = ava->aa_desc->ad_type->sat_equality;
-	
-	return comp_candidates ( op, rtxn, &mra, ava->aa_cf, ids, tmp, stack );
-}
-
-static int
-comp_candidates (
-	Operation *op,
-	DB_TXN *rtxn,
-	MatchingRuleAssertion *mra,
-	ComponentFilter *f,
-	ID *ids,
-	ID *tmp,
-	ID *stack)
-{
-	int	rc;
-
-	if ( !f ) return LDAP_PROTOCOL_ERROR;
-
-	Debug( LDAP_DEBUG_FILTER, "comp_candidates\n", 0, 0, 0 );
-	switch ( f->cf_choice ) {
-	case SLAPD_FILTER_COMPUTED:
-		rc = f->cf_result;
-		break;
-	case LDAP_COMP_FILTER_AND:
-		rc = comp_list_candidates( op, rtxn, mra, f->cf_and, LDAP_COMP_FILTER_AND, ids, tmp, stack );
-		break;
-	case LDAP_COMP_FILTER_OR:
-		rc = comp_list_candidates( op, rtxn, mra, f->cf_or, LDAP_COMP_FILTER_OR, ids, tmp, stack );
-		break;
-	case LDAP_COMP_FILTER_NOT:
-		/* No component indexing supported for NOT filter */
-		Debug( LDAP_DEBUG_FILTER, "\tComponent NOT\n", 0, 0, 0 );
-		{
-			struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-			BDB_IDL_ALL( bdb, ids );
-		}
-		rc = LDAP_PROTOCOL_ERROR;
-		break;
-	case LDAP_COMP_FILTER_ITEM:
-		rc = comp_equality_candidates( op, rtxn, mra, f->cf_ca, ids, tmp, stack );
-		break;
-	default:
-		{
-			struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-			BDB_IDL_ALL( bdb, ids );
-		}
-		rc = LDAP_PROTOCOL_ERROR;
-	}
-
-	return( rc );
-}
-#endif
-
-static int
-ext_candidates(
-        Operation *op,
-		DB_TXN *rtxn,
-        MatchingRuleAssertion *mra,
-        ID *ids,
-        ID *tmp,
-        ID *stack)
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-
-#ifdef LDAP_COMP_MATCH
-	/*
-	 * Currently Only Component Indexing for componentFilterMatch is supported
-	 * Indexing for an extensible filter is not supported yet
-	 */
-	if ( mra->ma_cf ) {
-		return comp_candidates ( op, rtxn, mra, mra->ma_cf, ids, tmp, stack);
-	}
-#endif
-	if ( mra->ma_desc == slap_schema.si_ad_entryDN ) {
-		int rc;
-		EntryInfo *ei;
-
-		BDB_IDL_ZERO( ids );
-		if ( mra->ma_rule == slap_schema.si_mr_distinguishedNameMatch ) {
-			ei = NULL;
-			rc = bdb_cache_find_ndn( op, rtxn, &mra->ma_value, &ei );
-			if ( rc == LDAP_SUCCESS )
-				bdb_idl_insert( ids, ei->bei_id );
-			if ( ei )
-				bdb_cache_entryinfo_unlock( ei );
-			return 0;
-		} else if ( mra->ma_rule && mra->ma_rule->smr_match ==
-			dnRelativeMatch && dnIsSuffix( &mra->ma_value,
-				op->o_bd->be_nsuffix )) {
-			int scope;
-			if ( mra->ma_rule == slap_schema.si_mr_dnSuperiorMatch ) {
-				struct berval pdn;
-				ei = NULL;
-				dnParent( &mra->ma_value, &pdn );
-				bdb_cache_find_ndn( op, rtxn, &pdn, &ei );
-				if ( ei ) {
-					bdb_cache_entryinfo_unlock( ei );
-					while ( ei && ei->bei_id ) {
-						bdb_idl_insert( ids, ei->bei_id );
-						ei = ei->bei_parent;
-					}
-				}
-				return 0;
-			}
-			if ( mra->ma_rule == slap_schema.si_mr_dnSubtreeMatch )
-				scope = LDAP_SCOPE_SUBTREE;
-			else if ( mra->ma_rule == slap_schema.si_mr_dnOneLevelMatch )
-				scope = LDAP_SCOPE_ONELEVEL;
-			else if ( mra->ma_rule == slap_schema.si_mr_dnSubordinateMatch )
-				scope = LDAP_SCOPE_SUBORDINATE;
-			else
-				scope = LDAP_SCOPE_BASE;
-			if ( scope > LDAP_SCOPE_BASE ) {
-				ei = NULL;
-				rc = bdb_cache_find_ndn( op, rtxn, &mra->ma_value, &ei );
-				if ( ei )
-					bdb_cache_entryinfo_unlock( ei );
-				if ( rc == LDAP_SUCCESS ) {
-					int sc = op->ors_scope;
-					op->ors_scope = scope;
-					rc = bdb_dn2idl( op, rtxn, &mra->ma_value, ei, ids,
-						stack );
-					op->ors_scope = sc;
-				}
-				return 0;
-			}
-		}
-	}
-
-	BDB_IDL_ALL( bdb, ids );
-	return 0;
-}
-
-static int
-list_candidates(
-	Operation *op,
-	DB_TXN *rtxn,
-	Filter	*flist,
-	int		ftype,
-	ID *ids,
-	ID *tmp,
-	ID *save )
-{
-	int rc = 0;
-	Filter	*f;
-
-	Debug( LDAP_DEBUG_FILTER, "=> bdb_list_candidates 0x%x\n", ftype, 0, 0 );
-	for ( f = flist; f != NULL; f = f->f_next ) {
-		/* ignore precomputed scopes */
-		if ( f->f_choice == SLAPD_FILTER_COMPUTED &&
-		     f->f_result == LDAP_SUCCESS ) {
-			continue;
-		}
-		BDB_IDL_ZERO( save );
-		rc = bdb_filter_candidates( op, rtxn, f, save, tmp,
-			save+BDB_IDL_UM_SIZE );
-
-		if ( rc != 0 ) {
-			if ( rc == DB_LOCK_DEADLOCK )
-				return rc;
-
-			if ( ftype == LDAP_FILTER_AND ) {
-				rc = 0;
-				continue;
-			}
-			break;
-		}
-
-		
-		if ( ftype == LDAP_FILTER_AND ) {
-			if ( f == flist ) {
-				BDB_IDL_CPY( ids, save );
-			} else {
-				bdb_idl_intersection( ids, save );
-			}
-			if( BDB_IDL_IS_ZERO( ids ) )
-				break;
-		} else {
-			if ( f == flist ) {
-				BDB_IDL_CPY( ids, save );
-			} else {
-				bdb_idl_union( ids, save );
-			}
-		}
-	}
-
-	if( rc == LDAP_SUCCESS ) {
-		Debug( LDAP_DEBUG_FILTER,
-			"<= bdb_list_candidates: id=%ld first=%ld last=%ld\n",
-			(long) ids[0],
-			(long) BDB_IDL_FIRST(ids),
-			(long) BDB_IDL_LAST(ids) );
-
-	} else {
-		Debug( LDAP_DEBUG_FILTER,
-			"<= bdb_list_candidates: undefined rc=%d\n",
-			rc, 0, 0 );
-	}
-
-	return rc;
-}
-
-static int
-presence_candidates(
-	Operation *op,
-	DB_TXN *rtxn,
-	AttributeDescription *desc,
-	ID *ids )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	DB *db;
-	int rc;
-	slap_mask_t mask;
-	struct berval prefix = {0, NULL};
-
-	Debug( LDAP_DEBUG_TRACE, "=> bdb_presence_candidates (%s)\n",
-			desc->ad_cname.bv_val, 0, 0 );
-
-	BDB_IDL_ALL( bdb, ids );
-
-	if( desc == slap_schema.si_ad_objectClass ) {
-		return 0;
-	}
-
-	rc = bdb_index_param( op->o_bd, desc, LDAP_FILTER_PRESENT,
-		&db, &mask, &prefix );
-
-	if( rc == LDAP_INAPPROPRIATE_MATCHING ) {
-		/* not indexed */
-		Debug( LDAP_DEBUG_TRACE,
-			"<= bdb_presence_candidates: (%s) not indexed\n",
-			desc->ad_cname.bv_val, 0, 0 );
-		return 0;
-	}
-
-	if( rc != LDAP_SUCCESS ) {
-		Debug( LDAP_DEBUG_TRACE,
-			"<= bdb_presence_candidates: (%s) index_param "
-			"returned=%d\n",
-			desc->ad_cname.bv_val, rc, 0 );
-		return 0;
-	}
-
-	if( prefix.bv_val == NULL ) {
-		Debug( LDAP_DEBUG_TRACE,
-			"<= bdb_presence_candidates: (%s) no prefix\n",
-			desc->ad_cname.bv_val, 0, 0 );
-		return -1;
-	}
-
-	rc = bdb_key_read( op->o_bd, db, rtxn, &prefix, ids, NULL, 0 );
-
-	if( rc == DB_NOTFOUND ) {
-		BDB_IDL_ZERO( ids );
-		rc = 0;
-	} else if( rc != LDAP_SUCCESS ) {
-		Debug( LDAP_DEBUG_TRACE,
-			"<= bdb_presense_candidates: (%s) "
-			"key read failed (%d)\n",
-			desc->ad_cname.bv_val, rc, 0 );
-		goto done;
-	}
-
-	Debug(LDAP_DEBUG_TRACE,
-		"<= bdb_presence_candidates: id=%ld first=%ld last=%ld\n",
-		(long) ids[0],
-		(long) BDB_IDL_FIRST(ids),
-		(long) BDB_IDL_LAST(ids) );
-
-done:
-	return rc;
-}
-
-static int
-equality_candidates(
-	Operation *op,
-	DB_TXN *rtxn,
-	AttributeAssertion *ava,
-	ID *ids,
-	ID *tmp )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	DB	*db;
-	int i;
-	int rc;
-	slap_mask_t mask;
-	struct berval prefix = {0, NULL};
-	struct berval *keys = NULL;
-	MatchingRule *mr;
-
-	Debug( LDAP_DEBUG_TRACE, "=> bdb_equality_candidates (%s)\n",
-			ava->aa_desc->ad_cname.bv_val, 0, 0 );
-
-	if ( ava->aa_desc == slap_schema.si_ad_entryDN ) {
-		EntryInfo *ei = NULL;
-		rc = bdb_cache_find_ndn( op, rtxn, &ava->aa_value, &ei );
-		if ( rc == LDAP_SUCCESS ) {
-			/* exactly one ID can match */
-			ids[0] = 1;
-			ids[1] = ei->bei_id;
-		}
-		if ( ei ) {
-			bdb_cache_entryinfo_unlock( ei );
-		}
-		if ( rc == DB_NOTFOUND ) {
-			BDB_IDL_ZERO( ids );
-			rc = 0;
-		}
-		return rc;
-	}
-
-	BDB_IDL_ALL( bdb, ids );
-
-	rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_EQUALITY,
-		&db, &mask, &prefix );
-
-	if ( rc == LDAP_INAPPROPRIATE_MATCHING ) {
-		Debug( LDAP_DEBUG_ANY,
-			"<= bdb_equality_candidates: (%s) not indexed\n", 
-			ava->aa_desc->ad_cname.bv_val, 0, 0 );
-		return 0;
-	}
-
-	if( rc != LDAP_SUCCESS ) {
-		Debug( LDAP_DEBUG_ANY,
-			"<= bdb_equality_candidates: (%s) "
-			"index_param failed (%d)\n",
-			ava->aa_desc->ad_cname.bv_val, rc, 0 );
-		return 0;
-	}
-
-	mr = ava->aa_desc->ad_type->sat_equality;
-	if( !mr ) {
-		return 0;
-	}
-
-	if( !mr->smr_filter ) {
-		return 0;
-	}
-
-	rc = (mr->smr_filter)(
-		LDAP_FILTER_EQUALITY,
-		mask,
-		ava->aa_desc->ad_type->sat_syntax,
-		mr,
-		&prefix,
-		&ava->aa_value,
-		&keys, op->o_tmpmemctx );
-
-	if( rc != LDAP_SUCCESS ) {
-		Debug( LDAP_DEBUG_TRACE,
-			"<= bdb_equality_candidates: (%s, %s) "
-			"MR filter failed (%d)\n",
-			prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
-		return 0;
-	}
-
-	if( keys == NULL ) {
-		Debug( LDAP_DEBUG_TRACE,
-			"<= bdb_equality_candidates: (%s) no keys\n",
-			ava->aa_desc->ad_cname.bv_val, 0, 0 );
-		return 0;
-	}
-
-	for ( i= 0; keys[i].bv_val != NULL; i++ ) {
-		rc = bdb_key_read( op->o_bd, db, rtxn, &keys[i], tmp, NULL, 0 );
-
-		if( rc == DB_NOTFOUND ) {
-			BDB_IDL_ZERO( ids );
-			rc = 0;
-			break;
-		} else if( rc != LDAP_SUCCESS ) {
-			Debug( LDAP_DEBUG_TRACE,
-				"<= bdb_equality_candidates: (%s) "
-				"key read failed (%d)\n",
-				ava->aa_desc->ad_cname.bv_val, rc, 0 );
-			break;
-		}
-
-		if( BDB_IDL_IS_ZERO( tmp ) ) {
-			Debug( LDAP_DEBUG_TRACE,
-				"<= bdb_equality_candidates: (%s) NULL\n", 
-				ava->aa_desc->ad_cname.bv_val, 0, 0 );
-			BDB_IDL_ZERO( ids );
-			break;
-		}
-
-		if ( i == 0 ) {
-			BDB_IDL_CPY( ids, tmp );
-		} else {
-			bdb_idl_intersection( ids, tmp );
-		}
-
-		if( BDB_IDL_IS_ZERO( ids ) )
-			break;
-	}
-
-	ber_bvarray_free_x( keys, op->o_tmpmemctx );
-
-	Debug( LDAP_DEBUG_TRACE,
-		"<= bdb_equality_candidates: id=%ld, first=%ld, last=%ld\n",
-		(long) ids[0],
-		(long) BDB_IDL_FIRST(ids),
-		(long) BDB_IDL_LAST(ids) );
-	return( rc );
-}
-
-
-static int
-approx_candidates(
-	Operation *op,
-	DB_TXN *rtxn,
-	AttributeAssertion *ava,
-	ID *ids,
-	ID *tmp )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	DB	*db;
-	int i;
-	int rc;
-	slap_mask_t mask;
-	struct berval prefix = {0, NULL};
-	struct berval *keys = NULL;
-	MatchingRule *mr;
-
-	Debug( LDAP_DEBUG_TRACE, "=> bdb_approx_candidates (%s)\n",
-			ava->aa_desc->ad_cname.bv_val, 0, 0 );
-
-	BDB_IDL_ALL( bdb, ids );
-
-	rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_APPROX,
-		&db, &mask, &prefix );
-
-	if ( rc == LDAP_INAPPROPRIATE_MATCHING ) {
-		Debug( LDAP_DEBUG_ANY,
-			"<= bdb_approx_candidates: (%s) not indexed\n",
-			ava->aa_desc->ad_cname.bv_val, 0, 0 );
-		return 0;
-	}
-
-	if( rc != LDAP_SUCCESS ) {
-		Debug( LDAP_DEBUG_ANY,
-			"<= bdb_approx_candidates: (%s) "
-			"index_param failed (%d)\n",
-			ava->aa_desc->ad_cname.bv_val, rc, 0 );
-		return 0;
-	}
-
-	mr = ava->aa_desc->ad_type->sat_approx;
-	if( !mr ) {
-		/* no approx matching rule, try equality matching rule */
-		mr = ava->aa_desc->ad_type->sat_equality;
-	}
-
-	if( !mr ) {
-		return 0;
-	}
-
-	if( !mr->smr_filter ) {
-		return 0;
-	}
-
-	rc = (mr->smr_filter)(
-		LDAP_FILTER_APPROX,
-		mask,
-		ava->aa_desc->ad_type->sat_syntax,
-		mr,
-		&prefix,
-		&ava->aa_value,
-		&keys, op->o_tmpmemctx );
-
-	if( rc != LDAP_SUCCESS ) {
-		Debug( LDAP_DEBUG_TRACE,
-			"<= bdb_approx_candidates: (%s, %s) "
-			"MR filter failed (%d)\n",
-			prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
-		return 0;
-	}
-
-	if( keys == NULL ) {
-		Debug( LDAP_DEBUG_TRACE,
-			"<= bdb_approx_candidates: (%s) no keys (%s)\n",
-			prefix.bv_val, ava->aa_desc->ad_cname.bv_val, 0 );
-		return 0;
-	}
-
-	for ( i= 0; keys[i].bv_val != NULL; i++ ) {
-		rc = bdb_key_read( op->o_bd, db, rtxn, &keys[i], tmp, NULL, 0 );
-
-		if( rc == DB_NOTFOUND ) {
-			BDB_IDL_ZERO( ids );
-			rc = 0;
-			break;
-		} else if( rc != LDAP_SUCCESS ) {
-			Debug( LDAP_DEBUG_TRACE,
-				"<= bdb_approx_candidates: (%s) "
-				"key read failed (%d)\n",
-				ava->aa_desc->ad_cname.bv_val, rc, 0 );
-			break;
-		}
-
-		if( BDB_IDL_IS_ZERO( tmp ) ) {
-			Debug( LDAP_DEBUG_TRACE,
-				"<= bdb_approx_candidates: (%s) NULL\n",
-				ava->aa_desc->ad_cname.bv_val, 0, 0 );
-			BDB_IDL_ZERO( ids );
-			break;
-		}
-
-		if ( i == 0 ) {
-			BDB_IDL_CPY( ids, tmp );
-		} else {
-			bdb_idl_intersection( ids, tmp );
-		}
-
-		if( BDB_IDL_IS_ZERO( ids ) )
-			break;
-	}
-
-	ber_bvarray_free_x( keys, op->o_tmpmemctx );
-
-	Debug( LDAP_DEBUG_TRACE, "<= bdb_approx_candidates %ld, first=%ld, last=%ld\n",
-		(long) ids[0],
-		(long) BDB_IDL_FIRST(ids),
-		(long) BDB_IDL_LAST(ids) );
-	return( rc );
-}
-
-static int
-substring_candidates(
-	Operation *op,
-	DB_TXN *rtxn,
-	SubstringsAssertion	*sub,
-	ID *ids,
-	ID *tmp )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	DB	*db;
-	int i;
-	int rc;
-	slap_mask_t mask;
-	struct berval prefix = {0, NULL};
-	struct berval *keys = NULL;
-	MatchingRule *mr;
-
-	Debug( LDAP_DEBUG_TRACE, "=> bdb_substring_candidates (%s)\n",
-			sub->sa_desc->ad_cname.bv_val, 0, 0 );
-
-	BDB_IDL_ALL( bdb, ids );
-
-	rc = bdb_index_param( op->o_bd, sub->sa_desc, LDAP_FILTER_SUBSTRINGS,
-		&db, &mask, &prefix );
-
-	if ( rc == LDAP_INAPPROPRIATE_MATCHING ) {
-		Debug( LDAP_DEBUG_ANY,
-			"<= bdb_substring_candidates: (%s) not indexed\n",
-			sub->sa_desc->ad_cname.bv_val, 0, 0 );
-		return 0;
-	}
-
-	if( rc != LDAP_SUCCESS ) {
-		Debug( LDAP_DEBUG_ANY,
-			"<= bdb_substring_candidates: (%s) "
-			"index_param failed (%d)\n",
-			sub->sa_desc->ad_cname.bv_val, rc, 0 );
-		return 0;
-	}
-
-	mr = sub->sa_desc->ad_type->sat_substr;
-
-	if( !mr ) {
-		return 0;
-	}
-
-	if( !mr->smr_filter ) {
-		return 0;
-	}
-
-	rc = (mr->smr_filter)(
-		LDAP_FILTER_SUBSTRINGS,
-		mask,
-		sub->sa_desc->ad_type->sat_syntax,
-		mr,
-		&prefix,
-		sub,
-		&keys, op->o_tmpmemctx );
-
-	if( rc != LDAP_SUCCESS ) {
-		Debug( LDAP_DEBUG_TRACE,
-			"<= bdb_substring_candidates: (%s) "
-			"MR filter failed (%d)\n",
-			sub->sa_desc->ad_cname.bv_val, rc, 0 );
-		return 0;
-	}
-
-	if( keys == NULL ) {
-		Debug( LDAP_DEBUG_TRACE,
-			"<= bdb_substring_candidates: (0x%04lx) no keys (%s)\n",
-			mask, sub->sa_desc->ad_cname.bv_val, 0 );
-		return 0;
-	}
-
-	for ( i= 0; keys[i].bv_val != NULL; i++ ) {
-		rc = bdb_key_read( op->o_bd, db, rtxn, &keys[i], tmp, NULL, 0 );
-
-		if( rc == DB_NOTFOUND ) {
-			BDB_IDL_ZERO( ids );
-			rc = 0;
-			break;
-		} else if( rc != LDAP_SUCCESS ) {
-			Debug( LDAP_DEBUG_TRACE,
-				"<= bdb_substring_candidates: (%s) "
-				"key read failed (%d)\n",
-				sub->sa_desc->ad_cname.bv_val, rc, 0 );
-			break;
-		}
-
-		if( BDB_IDL_IS_ZERO( tmp ) ) {
-			Debug( LDAP_DEBUG_TRACE,
-				"<= bdb_substring_candidates: (%s) NULL\n",
-				sub->sa_desc->ad_cname.bv_val, 0, 0 );
-			BDB_IDL_ZERO( ids );
-			break;
-		}
-
-		if ( i == 0 ) {
-			BDB_IDL_CPY( ids, tmp );
-		} else {
-			bdb_idl_intersection( ids, tmp );
-		}
-
-		if( BDB_IDL_IS_ZERO( ids ) )
-			break;
-	}
-
-	ber_bvarray_free_x( keys, op->o_tmpmemctx );
-
-	Debug( LDAP_DEBUG_TRACE, "<= bdb_substring_candidates: %ld, first=%ld, last=%ld\n",
-		(long) ids[0],
-		(long) BDB_IDL_FIRST(ids),
-		(long) BDB_IDL_LAST(ids) );
-	return( rc );
-}
-
-static int
-inequality_candidates(
-	Operation *op,
-	DB_TXN *rtxn,
-	AttributeAssertion *ava,
-	ID *ids,
-	ID *tmp,
-	int gtorlt )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	DB	*db;
-	int rc;
-	slap_mask_t mask;
-	struct berval prefix = {0, NULL};
-	struct berval *keys = NULL;
-	MatchingRule *mr;
-	DBC * cursor = NULL;
-
-	Debug( LDAP_DEBUG_TRACE, "=> bdb_inequality_candidates (%s)\n",
-			ava->aa_desc->ad_cname.bv_val, 0, 0 );
-
-	BDB_IDL_ALL( bdb, ids );
-
-	rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_EQUALITY,
-		&db, &mask, &prefix );
-
-	if ( rc == LDAP_INAPPROPRIATE_MATCHING ) {
-		Debug( LDAP_DEBUG_ANY,
-			"<= bdb_inequality_candidates: (%s) not indexed\n", 
-			ava->aa_desc->ad_cname.bv_val, 0, 0 );
-		return 0;
-	}
-
-	if( rc != LDAP_SUCCESS ) {
-		Debug( LDAP_DEBUG_ANY,
-			"<= bdb_inequality_candidates: (%s) "
-			"index_param failed (%d)\n",
-			ava->aa_desc->ad_cname.bv_val, rc, 0 );
-		return 0;
-	}
-
-	mr = ava->aa_desc->ad_type->sat_equality;
-	if( !mr ) {
-		return 0;
-	}
-
-	if( !mr->smr_filter ) {
-		return 0;
-	}
-
-	rc = (mr->smr_filter)(
-		LDAP_FILTER_EQUALITY,
-		mask,
-		ava->aa_desc->ad_type->sat_syntax,
-		mr,
-		&prefix,
-		&ava->aa_value,
-		&keys, op->o_tmpmemctx );
-
-	if( rc != LDAP_SUCCESS ) {
-		Debug( LDAP_DEBUG_TRACE,
-			"<= bdb_inequality_candidates: (%s, %s) "
-			"MR filter failed (%d)\n",
-			prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
-		return 0;
-	}
-
-	if( keys == NULL ) {
-		Debug( LDAP_DEBUG_TRACE,
-			"<= bdb_inequality_candidates: (%s) no keys\n",
-			ava->aa_desc->ad_cname.bv_val, 0, 0 );
-		return 0;
-	}
-
-	BDB_IDL_ZERO( ids );
-	while(1) {
-		rc = bdb_key_read( op->o_bd, db, rtxn, &keys[0], tmp, &cursor, gtorlt );
-
-		if( rc == DB_NOTFOUND ) {
-			rc = 0;
-			break;
-		} else if( rc != LDAP_SUCCESS ) {
-			Debug( LDAP_DEBUG_TRACE,
-			       "<= bdb_inequality_candidates: (%s) "
-			       "key read failed (%d)\n",
-			       ava->aa_desc->ad_cname.bv_val, rc, 0 );
-			break;
-		}
-
-		if( BDB_IDL_IS_ZERO( tmp ) ) {
-			Debug( LDAP_DEBUG_TRACE,
-			       "<= bdb_inequality_candidates: (%s) NULL\n", 
-			       ava->aa_desc->ad_cname.bv_val, 0, 0 );
-			break;
-		}
-
-		bdb_idl_union( ids, tmp );
-
-		if( op->ors_limit && op->ors_limit->lms_s_unchecked != -1 &&
-			BDB_IDL_N( ids ) >= (unsigned) op->ors_limit->lms_s_unchecked ) {
-			cursor->c_close( cursor );
-			break;
-		}
-	}
-	ber_bvarray_free_x( keys, op->o_tmpmemctx );
-
-	Debug( LDAP_DEBUG_TRACE,
-		"<= bdb_inequality_candidates: id=%ld, first=%ld, last=%ld\n",
-		(long) ids[0],
-		(long) BDB_IDL_FIRST(ids),
-		(long) BDB_IDL_LAST(ids) );
-	return( rc );
-}
diff --git a/servers/slapd/back-bdb/id2entry.c b/servers/slapd/back-bdb/id2entry.c
deleted file mode 100644
index cc00098..0000000
--- a/servers/slapd/back-bdb/id2entry.c
+++ /dev/null
@@ -1,446 +0,0 @@
-/* id2entry.c - routines to deal with the id2entry database */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-#include <ac/errno.h>
-
-#include "back-bdb.h"
-
-static int bdb_id2entry_put(
-	BackendDB *be,
-	DB_TXN *tid,
-	Entry *e,
-	int flag )
-{
-	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
-	DB *db = bdb->bi_id2entry->bdi_db;
-	DBT key, data;
-	struct berval bv;
-	int rc;
-	ID nid;
-#ifdef BDB_HIER
-	struct berval odn, ondn;
-
-	/* We only store rdns, and they go in the dn2id database. */
-
-	odn = e->e_name; ondn = e->e_nname;
-
-	e->e_name = slap_empty_bv;
-	e->e_nname = slap_empty_bv;
-#endif
-	DBTzero( &key );
-
-	/* Store ID in BigEndian format */
-	key.data = &nid;
-	key.size = sizeof(ID);
-	BDB_ID2DISK( e->e_id, &nid );
-
-	rc = entry_encode( e, &bv );
-#ifdef BDB_HIER
-	e->e_name = odn; e->e_nname = ondn;
-#endif
-	if( rc != LDAP_SUCCESS ) {
-		return -1;
-	}
-
-	DBTzero( &data );
-	bv2DBT( &bv, &data );
-
-	rc = db->put( db, tid, &key, &data, flag );
-
-	free( bv.bv_val );
-	return rc;
-}
-
-/*
- * This routine adds (or updates) an entry on disk.
- * The cache should be already be updated.
- */
-
-
-int bdb_id2entry_add(
-	BackendDB *be,
-	DB_TXN *tid,
-	Entry *e )
-{
-	return bdb_id2entry_put(be, tid, e, DB_NOOVERWRITE);
-}
-
-int bdb_id2entry_update(
-	BackendDB *be,
-	DB_TXN *tid,
-	Entry *e )
-{
-	return bdb_id2entry_put(be, tid, e, 0);
-}
-
-int bdb_id2entry(
-	BackendDB *be,
-	DB_TXN *tid,
-	ID id,
-	Entry **e )
-{
-	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
-	DB *db = bdb->bi_id2entry->bdi_db;
-	DBT key, data;
-	DBC *cursor;
-	EntryHeader eh;
-	char buf[16];
-	int rc = 0, off;
-	ID nid;
-
-	*e = NULL;
-
-	DBTzero( &key );
-	key.data = &nid;
-	key.size = sizeof(ID);
-	BDB_ID2DISK( id, &nid );
-
-	DBTzero( &data );
-	data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
-
-	/* fetch it */
-	rc = db->cursor( db, tid, &cursor, bdb->bi_db_opflags );
-	if ( rc ) return rc;
-
-	/* Get the nattrs / nvals counts first */
-	data.ulen = data.dlen = sizeof(buf);
-	data.data = buf;
-	rc = cursor->c_get( cursor, &key, &data, DB_SET );
-	if ( rc ) goto finish;
-
-
-	eh.bv.bv_val = buf;
-	eh.bv.bv_len = data.size;
-	rc = entry_header( &eh );
-	if ( rc ) goto finish;
-
-	if ( eh.nvals ) {
-		/* Get the size */
-		data.flags ^= DB_DBT_PARTIAL;
-		data.ulen = 0;
-		rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
-		if ( rc != DB_BUFFER_SMALL ) goto finish;
-
-		/* Allocate a block and retrieve the data */
-		off = eh.data - eh.bv.bv_val;
-		eh.bv.bv_len = eh.nvals * sizeof( struct berval ) + data.size;
-		eh.bv.bv_val = ch_malloc( eh.bv.bv_len );
-		eh.data = eh.bv.bv_val + eh.nvals * sizeof( struct berval );
-		data.data = eh.data;
-		data.ulen = data.size;
-
-		/* skip past already parsed nattr/nvals */
-		eh.data += off;
-
-		rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
-	}
-
-finish:
-	cursor->c_close( cursor );
-
-	if( rc != 0 ) {
-		return rc;
-	}
-
-	if ( eh.nvals ) {
-#ifdef SLAP_ZONE_ALLOC
-		rc = entry_decode(&eh, e, bdb->bi_cache.c_zctx);
-#else
-		rc = entry_decode(&eh, e);
-#endif
-	} else {
-		*e = entry_alloc();
-	}
-
-	if( rc == 0 ) {
-		(*e)->e_id = id;
-	} else {
-		/* only free on error. On success, the entry was
-		 * decoded in place.
-		 */
-#ifndef SLAP_ZONE_ALLOC
-		ch_free(eh.bv.bv_val);
-#endif
-	}
-#ifdef SLAP_ZONE_ALLOC
-	ch_free(eh.bv.bv_val);
-#endif
-
-	return rc;
-}
-
-int bdb_id2entry_delete(
-	BackendDB *be,
-	DB_TXN *tid,
-	Entry *e )
-{
-	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
-	DB *db = bdb->bi_id2entry->bdi_db;
-	DBT key;
-	int rc;
-	ID nid;
-
-	DBTzero( &key );
-	key.data = &nid;
-	key.size = sizeof(ID);
-	BDB_ID2DISK( e->e_id, &nid );
-
-	/* delete from database */
-	rc = db->del( db, tid, &key, 0 );
-
-	return rc;
-}
-
-int bdb_entry_return(
-	Entry *e
-)
-{
-	/* Our entries are allocated in two blocks; the data comes from
-	 * the db itself and the Entry structure and associated pointers
-	 * are allocated in entry_decode. The db data pointer is saved
-	 * in e_bv.
-	 */
-	if ( e->e_bv.bv_val ) {
-		/* See if the DNs were changed by modrdn */
-		if( e->e_nname.bv_val < e->e_bv.bv_val || e->e_nname.bv_val >
-			e->e_bv.bv_val + e->e_bv.bv_len ) {
-			ch_free(e->e_name.bv_val);
-			ch_free(e->e_nname.bv_val);
-		}
-		e->e_name.bv_val = NULL;
-		e->e_nname.bv_val = NULL;
-		/* In tool mode the e_bv buffer is realloc'd, leave it alone */
-		if( !(slapMode & SLAP_TOOL_MODE) ) {
-			free( e->e_bv.bv_val );
-		}
-		BER_BVZERO( &e->e_bv );
-	}
-	entry_free( e );
-	return 0;
-}
-
-int bdb_entry_release(
-	Operation *op,
-	Entry *e,
-	int rw )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	struct bdb_op_info *boi;
-	OpExtra *oex;
- 
-	/* slapMode : SLAP_SERVER_MODE, SLAP_TOOL_MODE,
-			SLAP_TRUNCATE_MODE, SLAP_UNDEFINED_MODE */
- 
-	if ( slapMode & SLAP_SERVER_MODE ) {
-		/* If not in our cache, just free it */
-		if ( !e->e_private ) {
-#ifdef SLAP_ZONE_ALLOC
-			return bdb_entry_return( bdb, e, -1 );
-#else
-			return bdb_entry_return( e );
-#endif
-		}
-		/* free entry and reader or writer lock */
-		LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
-			if ( oex->oe_key == bdb ) break;
-		}
-		boi = (struct bdb_op_info *)oex;
-
-		/* lock is freed with txn */
-		if ( !boi || boi->boi_txn ) {
-			bdb_unlocked_cache_return_entry_rw( bdb, e, rw );
-		} else {
-			struct bdb_lock_info *bli, *prev;
-			for ( prev=(struct bdb_lock_info *)&boi->boi_locks,
-				bli = boi->boi_locks; bli; prev=bli, bli=bli->bli_next ) {
-				if ( bli->bli_id == e->e_id ) {
-					bdb_cache_return_entry_rw( bdb, e, rw, &bli->bli_lock );
-					prev->bli_next = bli->bli_next;
-					/* Cleanup, or let caller know we unlocked */
-					if ( bli->bli_flag & BLI_DONTFREE )
-						bli->bli_flag = 0;
-					else
-						op->o_tmpfree( bli, op->o_tmpmemctx );
-					break;
-				}
-			}
-			if ( !boi->boi_locks ) {
-				LDAP_SLIST_REMOVE( &op->o_extra, &boi->boi_oe, OpExtra, oe_next );
-				if ( !(boi->boi_flag & BOI_DONTFREE))
-					op->o_tmpfree( boi, op->o_tmpmemctx );
-			}
-		}
-	} else {
-#ifdef SLAP_ZONE_ALLOC
-		int zseq = -1;
-		if (e->e_private != NULL) {
-			BEI(e)->bei_e = NULL;
-			zseq = BEI(e)->bei_zseq;
-		}
-#else
-		if (e->e_private != NULL)
-			BEI(e)->bei_e = NULL;
-#endif
-		e->e_private = NULL;
-#ifdef SLAP_ZONE_ALLOC
-		bdb_entry_return ( bdb, e, zseq );
-#else
-		bdb_entry_return ( e );
-#endif
-	}
- 
-	return 0;
-}
-
-/* return LDAP_SUCCESS IFF we can retrieve the specified entry.
- */
-int bdb_entry_get(
-	Operation *op,
-	struct berval *ndn,
-	ObjectClass *oc,
-	AttributeDescription *at,
-	int rw,
-	Entry **ent )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	struct bdb_op_info *boi = NULL;
-	DB_TXN *txn = NULL;
-	Entry *e = NULL;
-	EntryInfo *ei;
-	int	rc;
-	const char *at_name = at ? at->ad_cname.bv_val : "(null)";
-
-	DB_LOCK		lock;
-
-	Debug( LDAP_DEBUG_ARGS,
-		"=> bdb_entry_get: ndn: \"%s\"\n", ndn->bv_val, 0, 0 ); 
-	Debug( LDAP_DEBUG_ARGS,
-		"=> bdb_entry_get: oc: \"%s\", at: \"%s\"\n",
-		oc ? oc->soc_cname.bv_val : "(null)", at_name, 0);
-
-	if( op ) {
-		OpExtra *oex;
-		LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
-			if ( oex->oe_key == bdb ) break;
-		}
-		boi = (struct bdb_op_info *)oex;
-		if ( boi )
-			txn = boi->boi_txn;
-	}
-
-	if ( !txn ) {
-		rc = bdb_reader_get( op, bdb->bi_dbenv, &txn );
-		switch(rc) {
-		case 0:
-			break;
-		default:
-			return LDAP_OTHER;
-		}
-	}
-
-dn2entry_retry:
-	/* can we find entry */
-	rc = bdb_dn2entry( op, txn, ndn, &ei, 0, &lock );
-	switch( rc ) {
-	case DB_NOTFOUND:
-	case 0:
-		break;
-	case DB_LOCK_DEADLOCK:
-	case DB_LOCK_NOTGRANTED:
-		/* the txn must abort and retry */
-		if ( txn ) {
-			if ( boi ) boi->boi_err = rc;
-			return LDAP_BUSY;
-		}
-		ldap_pvt_thread_yield();
-		goto dn2entry_retry;
-	default:
-		if ( boi ) boi->boi_err = rc;
-		return (rc != LDAP_BUSY) ? LDAP_OTHER : LDAP_BUSY;
-	}
-	if (ei) e = ei->bei_e;
-	if (e == NULL) {
-		Debug( LDAP_DEBUG_ACL,
-			"=> bdb_entry_get: cannot find entry: \"%s\"\n",
-				ndn->bv_val, 0, 0 ); 
-		return LDAP_NO_SUCH_OBJECT; 
-	}
-	
-	Debug( LDAP_DEBUG_ACL,
-		"=> bdb_entry_get: found entry: \"%s\"\n",
-		ndn->bv_val, 0, 0 ); 
-
-	if ( oc && !is_entry_objectclass( e, oc, 0 )) {
-		Debug( LDAP_DEBUG_ACL,
-			"<= bdb_entry_get: failed to find objectClass %s\n",
-			oc->soc_cname.bv_val, 0, 0 ); 
-		rc = LDAP_NO_SUCH_ATTRIBUTE;
-		goto return_results;
-	}
-
-	/* NOTE: attr_find() or attrs_find()? */
-	if ( at && attr_find( e->e_attrs, at ) == NULL ) {
-		Debug( LDAP_DEBUG_ACL,
-			"<= bdb_entry_get: failed to find attribute %s\n",
-			at->ad_cname.bv_val, 0, 0 ); 
-		rc = LDAP_NO_SUCH_ATTRIBUTE;
-		goto return_results;
-	}
-
-return_results:
-	if( rc != LDAP_SUCCESS ) {
-		/* free entry */
-		bdb_cache_return_entry_rw(bdb, e, rw, &lock);
-
-	} else {
-		if ( slapMode & SLAP_SERVER_MODE ) {
-			*ent = e;
-			/* big drag. we need a place to store a read lock so we can
-			 * release it later?? If we're in a txn, nothing is needed
-			 * here because the locks will go away with the txn.
-			 */
-			if ( op ) {
-				if ( !boi ) {
-					boi = op->o_tmpcalloc(1,sizeof(struct bdb_op_info),op->o_tmpmemctx);
-					boi->boi_oe.oe_key = bdb;
-					LDAP_SLIST_INSERT_HEAD( &op->o_extra, &boi->boi_oe, oe_next );
-				}
-				if ( !boi->boi_txn ) {
-					struct bdb_lock_info *bli;
-					bli = op->o_tmpalloc( sizeof(struct bdb_lock_info),
-						op->o_tmpmemctx );
-					bli->bli_next = boi->boi_locks;
-					bli->bli_id = e->e_id;
-					bli->bli_flag = 0;
-					bli->bli_lock = lock;
-					boi->boi_locks = bli;
-				}
-			}
-		} else {
-			*ent = entry_dup( e );
-			bdb_cache_return_entry_rw(bdb, e, rw, &lock);
-		}
-	}
-
-	Debug( LDAP_DEBUG_TRACE,
-		"bdb_entry_get: rc=%d\n",
-		rc, 0, 0 ); 
-	return(rc);
-}
diff --git a/servers/slapd/back-bdb/idl.c b/servers/slapd/back-bdb/idl.c
deleted file mode 100644
index d0c13a6..0000000
--- a/servers/slapd/back-bdb/idl.c
+++ /dev/null
@@ -1,1570 +0,0 @@
-/* idl.c - ldap id list handling routines */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "back-bdb.h"
-#include "idl.h"
-
-#define IDL_MAX(x,y)	( (x) > (y) ? (x) : (y) )
-#define IDL_MIN(x,y)	( (x) < (y) ? (x) : (y) )
-#define IDL_CMP(x,y)	( (x) < (y) ? -1 : (x) > (y) )
-
-#define IDL_LRU_DELETE( bdb, e ) do { \
-	if ( (e) == (bdb)->bi_idl_lru_head ) { \
-		if ( (e)->idl_lru_next == (bdb)->bi_idl_lru_head ) { \
-			(bdb)->bi_idl_lru_head = NULL; \
-		} else { \
-			(bdb)->bi_idl_lru_head = (e)->idl_lru_next; \
-		} \
-	} \
-	if ( (e) == (bdb)->bi_idl_lru_tail ) { \
-		if ( (e)->idl_lru_prev == (bdb)->bi_idl_lru_tail ) { \
-			assert( (bdb)->bi_idl_lru_head == NULL ); \
-			(bdb)->bi_idl_lru_tail = NULL; \
-		} else { \
-			(bdb)->bi_idl_lru_tail = (e)->idl_lru_prev; \
-		} \
-	} \
-	(e)->idl_lru_next->idl_lru_prev = (e)->idl_lru_prev; \
-	(e)->idl_lru_prev->idl_lru_next = (e)->idl_lru_next; \
-} while ( 0 )
-
-static int
-bdb_idl_entry_cmp( const void *v_idl1, const void *v_idl2 )
-{
-	const bdb_idl_cache_entry_t *idl1 = v_idl1, *idl2 = v_idl2;
-	int rc;
-
-	if ((rc = SLAP_PTRCMP( idl1->db, idl2->db ))) return rc;
-	if ((rc = idl1->kstr.bv_len - idl2->kstr.bv_len )) return rc;
-	return ( memcmp ( idl1->kstr.bv_val, idl2->kstr.bv_val , idl1->kstr.bv_len ) );
-}
-
-#if IDL_DEBUG > 0
-static void idl_check( ID *ids )
-{
-	if( BDB_IDL_IS_RANGE( ids ) ) {
-		assert( BDB_IDL_RANGE_FIRST(ids) <= BDB_IDL_RANGE_LAST(ids) );
-	} else {
-		ID i;
-		for( i=1; i < ids[0]; i++ ) {
-			assert( ids[i+1] > ids[i] );
-		}
-	}
-}
-
-#if IDL_DEBUG > 1
-static void idl_dump( ID *ids )
-{
-	if( BDB_IDL_IS_RANGE( ids ) ) {
-		Debug( LDAP_DEBUG_ANY,
-			"IDL: range ( %ld - %ld )\n",
-			(long) BDB_IDL_RANGE_FIRST( ids ),
-			(long) BDB_IDL_RANGE_LAST( ids ) );
-
-	} else {
-		ID i;
-		Debug( LDAP_DEBUG_ANY, "IDL: size %ld", (long) ids[0], 0, 0 );
-
-		for( i=1; i<=ids[0]; i++ ) {
-			if( i % 16 == 1 ) {
-				Debug( LDAP_DEBUG_ANY, "\n", 0, 0, 0 );
-			}
-			Debug( LDAP_DEBUG_ANY, "  %02lx", (long) ids[i], 0, 0 );
-		}
-
-		Debug( LDAP_DEBUG_ANY, "\n", 0, 0, 0 );
-	}
-
-	idl_check( ids );
-}
-#endif /* IDL_DEBUG > 1 */
-#endif /* IDL_DEBUG > 0 */
-
-unsigned bdb_idl_search( ID *ids, ID id )
-{
-#define IDL_BINARY_SEARCH 1
-#ifdef IDL_BINARY_SEARCH
-	/*
-	 * binary search of id in ids
-	 * if found, returns position of id
-	 * if not found, returns first postion greater than id
-	 */
-	unsigned base = 0;
-	unsigned cursor = 1;
-	int val = 0;
-	unsigned n = ids[0];
-
-#if IDL_DEBUG > 0
-	idl_check( ids );
-#endif
-
-	while( 0 < n ) {
-		unsigned pivot = n >> 1;
-		cursor = base + pivot + 1;
-		val = IDL_CMP( id, ids[cursor] );
-
-		if( val < 0 ) {
-			n = pivot;
-
-		} else if ( val > 0 ) {
-			base = cursor;
-			n -= pivot + 1;
-
-		} else {
-			return cursor;
-		}
-	}
-	
-	if( val > 0 ) {
-		++cursor;
-	}
-	return cursor;
-
-#else
-	/* (reverse) linear search */
-	int i;
-
-#if IDL_DEBUG > 0
-	idl_check( ids );
-#endif
-
-	for( i=ids[0]; i; i-- ) {
-		if( id > ids[i] ) {
-			break;
-		}
-	}
-
-	return i+1;
-#endif
-}
-
-int bdb_idl_insert( ID *ids, ID id )
-{
-	unsigned x;
-
-#if IDL_DEBUG > 1
-	Debug( LDAP_DEBUG_ANY, "insert: %04lx at %d\n", (long) id, x, 0 );
-	idl_dump( ids );
-#elif IDL_DEBUG > 0
-	idl_check( ids );
-#endif
-
-	if (BDB_IDL_IS_RANGE( ids )) {
-		/* if already in range, treat as a dup */
-		if (id >= BDB_IDL_RANGE_FIRST(ids) && id <= BDB_IDL_RANGE_LAST(ids))
-			return -1;
-		if (id < BDB_IDL_RANGE_FIRST(ids))
-			ids[1] = id;
-		else if (id > BDB_IDL_RANGE_LAST(ids))
-			ids[2] = id;
-		return 0;
-	}
-
-	x = bdb_idl_search( ids, id );
-	assert( x > 0 );
-
-	if( x < 1 ) {
-		/* internal error */
-		return -2;
-	}
-
-	if ( x <= ids[0] && ids[x] == id ) {
-		/* duplicate */
-		return -1;
-	}
-
-	if ( ++ids[0] >= BDB_IDL_DB_MAX ) {
-		if( id < ids[1] ) {
-			ids[1] = id;
-			ids[2] = ids[ids[0]-1];
-		} else if ( ids[ids[0]-1] < id ) {
-			ids[2] = id;
-		} else {
-			ids[2] = ids[ids[0]-1];
-		}
-		ids[0] = NOID;
-	
-	} else {
-		/* insert id */
-		AC_MEMCPY( &ids[x+1], &ids[x], (ids[0]-x) * sizeof(ID) );
-		ids[x] = id;
-	}
-
-#if IDL_DEBUG > 1
-	idl_dump( ids );
-#elif IDL_DEBUG > 0
-	idl_check( ids );
-#endif
-
-	return 0;
-}
-
-int bdb_idl_delete( ID *ids, ID id )
-{
-	unsigned x;
-
-#if IDL_DEBUG > 1
-	Debug( LDAP_DEBUG_ANY, "delete: %04lx at %d\n", (long) id, x, 0 );
-	idl_dump( ids );
-#elif IDL_DEBUG > 0
-	idl_check( ids );
-#endif
-
-	if (BDB_IDL_IS_RANGE( ids )) {
-		/* If deleting a range boundary, adjust */
-		if ( ids[1] == id )
-			ids[1]++;
-		else if ( ids[2] == id )
-			ids[2]--;
-		/* deleting from inside a range is a no-op */
-
-		/* If the range has collapsed, re-adjust */
-		if ( ids[1] > ids[2] )
-			ids[0] = 0;
-		else if ( ids[1] == ids[2] )
-			ids[1] = 1;
-		return 0;
-	}
-
-	x = bdb_idl_search( ids, id );
-	assert( x > 0 );
-
-	if( x <= 0 ) {
-		/* internal error */
-		return -2;
-	}
-
-	if( x > ids[0] || ids[x] != id ) {
-		/* not found */
-		return -1;
-
-	} else if ( --ids[0] == 0 ) {
-		if( x != 1 ) {
-			return -3;
-		}
-
-	} else {
-		AC_MEMCPY( &ids[x], &ids[x+1], (1+ids[0]-x) * sizeof(ID) );
-	}
-
-#if IDL_DEBUG > 1
-	idl_dump( ids );
-#elif IDL_DEBUG > 0
-	idl_check( ids );
-#endif
-
-	return 0;
-}
-
-static char *
-bdb_show_key(
-	DBT		*key,
-	char		*buf )
-{
-	if ( key->size == 4 /* LUTIL_HASH_BYTES */ ) {
-		unsigned char *c = key->data;
-		sprintf( buf, "[%02x%02x%02x%02x]", c[0], c[1], c[2], c[3] );
-		return buf;
-	} else {
-		return key->data;
-	}
-}
-
-/* Find a db/key pair in the IDL cache. If ids is non-NULL,
- * copy the cached IDL into it, otherwise just return the status.
- */
-int
-bdb_idl_cache_get(
-	struct bdb_info	*bdb,
-	DB			*db,
-	DBT			*key,
-	ID			*ids )
-{
-	bdb_idl_cache_entry_t idl_tmp;
-	bdb_idl_cache_entry_t *matched_idl_entry;
-	int rc = LDAP_NO_SUCH_OBJECT;
-
-	DBT2bv( key, &idl_tmp.kstr );
-	idl_tmp.db = db;
-	ldap_pvt_thread_rdwr_rlock( &bdb->bi_idl_tree_rwlock );
-	matched_idl_entry = avl_find( bdb->bi_idl_tree, &idl_tmp,
-				      bdb_idl_entry_cmp );
-	if ( matched_idl_entry != NULL ) {
-		if ( matched_idl_entry->idl && ids )
-			BDB_IDL_CPY( ids, matched_idl_entry->idl );
-		matched_idl_entry->idl_flags |= CACHE_ENTRY_REFERENCED;
-		if ( matched_idl_entry->idl )
-			rc = LDAP_SUCCESS;
-		else
-			rc = DB_NOTFOUND;
-	}
-	ldap_pvt_thread_rdwr_runlock( &bdb->bi_idl_tree_rwlock );
-
-	return rc;
-}
-
-void
-bdb_idl_cache_put(
-	struct bdb_info	*bdb,
-	DB			*db,
-	DBT			*key,
-	ID			*ids,
-	int			rc )
-{
-	bdb_idl_cache_entry_t idl_tmp;
-	bdb_idl_cache_entry_t *ee, *eprev;
-
-	if ( rc == DB_NOTFOUND || BDB_IDL_IS_ZERO( ids ))
-		return;
-
-	DBT2bv( key, &idl_tmp.kstr );
-
-	ee = (bdb_idl_cache_entry_t *) ch_malloc(
-		sizeof( bdb_idl_cache_entry_t ) );
-	ee->db = db;
-	ee->idl = (ID*) ch_malloc( BDB_IDL_SIZEOF ( ids ) );
-	BDB_IDL_CPY( ee->idl, ids );
-
-	ee->idl_lru_prev = NULL;
-	ee->idl_lru_next = NULL;
-	ee->idl_flags = 0;
-	ber_dupbv( &ee->kstr, &idl_tmp.kstr );
-	ldap_pvt_thread_rdwr_wlock( &bdb->bi_idl_tree_rwlock );
-	if ( avl_insert( &bdb->bi_idl_tree, (caddr_t) ee,
-		bdb_idl_entry_cmp, avl_dup_error ))
-	{
-		ch_free( ee->kstr.bv_val );
-		ch_free( ee->idl );
-		ch_free( ee );
-		ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock );
-		return;
-	}
-	ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock );
-	/* LRU_ADD */
-	if ( bdb->bi_idl_lru_head ) {
-		assert( bdb->bi_idl_lru_tail != NULL );
-		assert( bdb->bi_idl_lru_head->idl_lru_prev != NULL );
-		assert( bdb->bi_idl_lru_head->idl_lru_next != NULL );
-
-		ee->idl_lru_next = bdb->bi_idl_lru_head;
-		ee->idl_lru_prev = bdb->bi_idl_lru_head->idl_lru_prev;
-		bdb->bi_idl_lru_head->idl_lru_prev->idl_lru_next = ee;
-		bdb->bi_idl_lru_head->idl_lru_prev = ee;
-	} else {
-		ee->idl_lru_next = ee->idl_lru_prev = ee;
-		bdb->bi_idl_lru_tail = ee;
-	}
-	bdb->bi_idl_lru_head = ee;
-
-	if ( bdb->bi_idl_cache_size >= bdb->bi_idl_cache_max_size ) {
-		int i;
-		eprev = bdb->bi_idl_lru_tail;
-		for ( i = 0; (ee = eprev) != NULL && i < 10; i++ ) {
-			eprev = ee->idl_lru_prev;
-			if ( eprev == ee ) {
-				eprev = NULL;
-			}
-			if ( ee->idl_flags & CACHE_ENTRY_REFERENCED ) {
-				ee->idl_flags ^= CACHE_ENTRY_REFERENCED;
-				continue;
-			}
-			if ( avl_delete( &bdb->bi_idl_tree, (caddr_t) ee,
-				    bdb_idl_entry_cmp ) == NULL ) {
-				Debug( LDAP_DEBUG_ANY, "=> bdb_idl_cache_put: "
-					"AVL delete failed\n",
-					0, 0, 0 );
-			}
-			IDL_LRU_DELETE( bdb, ee );
-			i++;
-			--bdb->bi_idl_cache_size;
-			ch_free( ee->kstr.bv_val );
-			ch_free( ee->idl );
-			ch_free( ee );
-		}
-		bdb->bi_idl_lru_tail = eprev;
-		assert( bdb->bi_idl_lru_tail != NULL
-			|| bdb->bi_idl_lru_head == NULL );
-	}
-	bdb->bi_idl_cache_size++;
-	ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
-	ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock );
-}
-
-void
-bdb_idl_cache_del(
-	struct bdb_info	*bdb,
-	DB			*db,
-	DBT			*key )
-{
-	bdb_idl_cache_entry_t *matched_idl_entry, idl_tmp;
-	DBT2bv( key, &idl_tmp.kstr );
-	idl_tmp.db = db;
-	ldap_pvt_thread_rdwr_wlock( &bdb->bi_idl_tree_rwlock );
-	matched_idl_entry = avl_find( bdb->bi_idl_tree, &idl_tmp,
-				      bdb_idl_entry_cmp );
-	if ( matched_idl_entry != NULL ) {
-		if ( avl_delete( &bdb->bi_idl_tree, (caddr_t) matched_idl_entry,
-				    bdb_idl_entry_cmp ) == NULL ) {
-			Debug( LDAP_DEBUG_ANY, "=> bdb_idl_cache_del: "
-				"AVL delete failed\n",
-				0, 0, 0 );
-		}
-		--bdb->bi_idl_cache_size;
-		ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock );
-		IDL_LRU_DELETE( bdb, matched_idl_entry );
-		ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
-		free( matched_idl_entry->kstr.bv_val );
-		if ( matched_idl_entry->idl )
-			free( matched_idl_entry->idl );
-		free( matched_idl_entry );
-	}
-	ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock );
-}
-
-void
-bdb_idl_cache_add_id(
-	struct bdb_info	*bdb,
-	DB			*db,
-	DBT			*key,
-	ID			id )
-{
-	bdb_idl_cache_entry_t *cache_entry, idl_tmp;
-	DBT2bv( key, &idl_tmp.kstr );
-	idl_tmp.db = db;
-	ldap_pvt_thread_rdwr_wlock( &bdb->bi_idl_tree_rwlock );
-	cache_entry = avl_find( bdb->bi_idl_tree, &idl_tmp,
-				      bdb_idl_entry_cmp );
-	if ( cache_entry != NULL ) {
-		if ( !BDB_IDL_IS_RANGE( cache_entry->idl ) &&
-			cache_entry->idl[0] < BDB_IDL_DB_MAX ) {
-			size_t s = BDB_IDL_SIZEOF( cache_entry->idl ) + sizeof(ID);
-			cache_entry->idl = ch_realloc( cache_entry->idl, s );
-		}
-		bdb_idl_insert( cache_entry->idl, id );
-	}
-	ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock );
-}
-
-void
-bdb_idl_cache_del_id(
-	struct bdb_info	*bdb,
-	DB			*db,
-	DBT			*key,
-	ID			id )
-{
-	bdb_idl_cache_entry_t *cache_entry, idl_tmp;
-	DBT2bv( key, &idl_tmp.kstr );
-	idl_tmp.db = db;
-	ldap_pvt_thread_rdwr_wlock( &bdb->bi_idl_tree_rwlock );
-	cache_entry = avl_find( bdb->bi_idl_tree, &idl_tmp,
-				      bdb_idl_entry_cmp );
-	if ( cache_entry != NULL ) {
-		bdb_idl_delete( cache_entry->idl, id );
-		if ( cache_entry->idl[0] == 0 ) {
-			if ( avl_delete( &bdb->bi_idl_tree, (caddr_t) cache_entry,
-						bdb_idl_entry_cmp ) == NULL ) {
-				Debug( LDAP_DEBUG_ANY, "=> bdb_idl_cache_del: "
-					"AVL delete failed\n",
-					0, 0, 0 );
-			}
-			--bdb->bi_idl_cache_size;
-			ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock );
-			IDL_LRU_DELETE( bdb, cache_entry );
-			ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
-			free( cache_entry->kstr.bv_val );
-			free( cache_entry->idl );
-			free( cache_entry );
-		}
-	}
-	ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock );
-}
-
-int
-bdb_idl_fetch_key(
-	BackendDB	*be,
-	DB			*db,
-	DB_TXN		*txn,
-	DBT			*key,
-	ID			*ids,
-	DBC                     **saved_cursor,
-	int                     get_flag )
-{
-	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
-	int rc;
-	DBT data, key2, *kptr;
-	DBC *cursor;
-	ID *i;
-	void *ptr;
-	size_t len;
-	int rc2;
-	int flags = bdb->bi_db_opflags | DB_MULTIPLE;
-	int opflag;
-
-	/* If using BerkeleyDB 4.0, the buf must be large enough to
-	 * grab the entire IDL in one get(), otherwise BDB will leak
-	 * resources on subsequent get's.  We can safely call get()
-	 * twice - once for the data, and once to get the DB_NOTFOUND
-	 * result meaning there's no more data. See ITS#2040 for details.
-	 * This bug is fixed in BDB 4.1 so a smaller buffer will work if
-	 * stack space is too limited.
-	 *
-	 * configure now requires Berkeley DB 4.1.
-	 */
-#if DB_VERSION_FULL < 0x04010000
-#	define BDB_ENOUGH 5
-#else
-	/* We sometimes test with tiny IDLs, and BDB always wants buffers
-	 * that are at least one page in size.
-	 */
-# if BDB_IDL_DB_SIZE < 4096
-#   define BDB_ENOUGH 2048
-# else
-#	define BDB_ENOUGH 1
-# endif
-#endif
-	ID buf[BDB_IDL_DB_SIZE*BDB_ENOUGH];
-
-	char keybuf[16];
-
-	Debug( LDAP_DEBUG_ARGS,
-		"bdb_idl_fetch_key: %s\n", 
-		bdb_show_key( key, keybuf ), 0, 0 );
-
-	assert( ids != NULL );
-
-	if ( saved_cursor && *saved_cursor ) {
-		opflag = DB_NEXT;
-	} else if ( get_flag == LDAP_FILTER_GE ) {
-		opflag = DB_SET_RANGE;
-	} else if ( get_flag == LDAP_FILTER_LE ) {
-		opflag = DB_FIRST;
-	} else {
-		opflag = DB_SET;
-	}
-
-	/* only non-range lookups can use the IDL cache */
-	if ( bdb->bi_idl_cache_size && opflag == DB_SET ) {
-		rc = bdb_idl_cache_get( bdb, db, key, ids );
-		if ( rc != LDAP_NO_SUCH_OBJECT ) return rc;
-	}
-
-	DBTzero( &data );
-
-	data.data = buf;
-	data.ulen = sizeof(buf);
-	data.flags = DB_DBT_USERMEM;
-
-	/* If we're not reusing an existing cursor, get a new one */
-	if( opflag != DB_NEXT ) {
-		rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
-		if( rc != 0 ) {
-			Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
-				"cursor failed: %s (%d)\n", db_strerror(rc), rc, 0 );
-			return rc;
-		}
-	} else {
-		cursor = *saved_cursor;
-	}
-	
-	/* If this is a LE lookup, save original key so we can determine
-	 * when to stop. If this is a GE lookup, save the key since it
-	 * will be overwritten.
-	 */
-	if ( get_flag == LDAP_FILTER_LE || get_flag == LDAP_FILTER_GE ) {
-		DBTzero( &key2 );
-		key2.flags = DB_DBT_USERMEM;
-		key2.ulen = sizeof(keybuf);
-		key2.data = keybuf;
-		key2.size = key->size;
-		AC_MEMCPY( keybuf, key->data, key->size );
-		kptr = &key2;
-	} else {
-		kptr = key;
-	}
-	len = key->size;
-	rc = cursor->c_get( cursor, kptr, &data, flags | opflag );
-
-	/* skip presence key on range inequality lookups */
-	while (rc == 0 && kptr->size != len) {
-		rc = cursor->c_get( cursor, kptr, &data, flags | DB_NEXT_NODUP );
-	}
-	/* If we're doing a LE compare and the new key is greater than
-	 * our search key, we're done
-	 */
-	if (rc == 0 && get_flag == LDAP_FILTER_LE && memcmp( kptr->data,
-		key->data, key->size ) > 0 ) {
-		rc = DB_NOTFOUND;
-	}
-	if (rc == 0) {
-		i = ids;
-		while (rc == 0) {
-			u_int8_t *j;
-
-			DB_MULTIPLE_INIT( ptr, &data );
-			while (ptr) {
-				DB_MULTIPLE_NEXT(ptr, &data, j, len);
-				if (j) {
-					++i;
-					BDB_DISK2ID( j, i );
-				}
-			}
-			rc = cursor->c_get( cursor, key, &data, flags | DB_NEXT_DUP );
-		}
-		if ( rc == DB_NOTFOUND ) rc = 0;
-		ids[0] = i - ids;
-		/* On disk, a range is denoted by 0 in the first element */
-		if (ids[1] == 0) {
-			if (ids[0] != BDB_IDL_RANGE_SIZE) {
-				Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
-					"range size mismatch: expected %d, got %ld\n",
-					BDB_IDL_RANGE_SIZE, ids[0], 0 );
-				cursor->c_close( cursor );
-				return -1;
-			}
-			BDB_IDL_RANGE( ids, ids[2], ids[3] );
-		}
-		data.size = BDB_IDL_SIZEOF(ids);
-	}
-
-	if ( saved_cursor && rc == 0 ) {
-		if ( !*saved_cursor )
-			*saved_cursor = cursor;
-		rc2 = 0;
-	}
-	else
-		rc2 = cursor->c_close( cursor );
-	if (rc2) {
-		Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
-			"close failed: %s (%d)\n", db_strerror(rc2), rc2, 0 );
-		return rc2;
-	}
-
-	if( rc == DB_NOTFOUND ) {
-		return rc;
-
-	} else if( rc != 0 ) {
-		Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
-			"get failed: %s (%d)\n",
-			db_strerror(rc), rc, 0 );
-		return rc;
-
-	} else if ( data.size == 0 || data.size % sizeof( ID ) ) {
-		/* size not multiple of ID size */
-		Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
-			"odd size: expected %ld multiple, got %ld\n",
-			(long) sizeof( ID ), (long) data.size, 0 );
-		return -1;
-
-	} else if ( data.size != BDB_IDL_SIZEOF(ids) ) {
-		/* size mismatch */
-		Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
-			"get size mismatch: expected %ld, got %ld\n",
-			(long) ((1 + ids[0]) * sizeof( ID )), (long) data.size, 0 );
-		return -1;
-	}
-
-	if ( bdb->bi_idl_cache_max_size ) {
-		bdb_idl_cache_put( bdb, db, key, ids, rc );
-	}
-
-	return rc;
-}
-
-
-int
-bdb_idl_insert_key(
-	BackendDB	*be,
-	DB			*db,
-	DB_TXN		*tid,
-	DBT			*key,
-	ID			id )
-{
-	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
-	int	rc;
-	DBT data;
-	DBC *cursor;
-	ID lo, hi, nlo, nhi, nid;
-	char *err;
-
-	{
-		char buf[16];
-		Debug( LDAP_DEBUG_ARGS,
-			"bdb_idl_insert_key: %lx %s\n", 
-			(long) id, bdb_show_key( key, buf ), 0 );
-	}
-
-	assert( id != NOID );
-
-	DBTzero( &data );
-	data.size = sizeof( ID );
-	data.ulen = data.size;
-	data.flags = DB_DBT_USERMEM;
-
-	BDB_ID2DISK( id, &nid );
-
-	rc = db->cursor( db, tid, &cursor, bdb->bi_db_opflags );
-	if ( rc != 0 ) {
-		Debug( LDAP_DEBUG_ANY, "=> bdb_idl_insert_key: "
-			"cursor failed: %s (%d)\n", db_strerror(rc), rc, 0 );
-		return rc;
-	}
-	data.data = &nlo;
-	/* Fetch the first data item for this key, to see if it
-	 * exists and if it's a range.
-	 */
-	rc = cursor->c_get( cursor, key, &data, DB_SET );
-	err = "c_get";
-	if ( rc == 0 ) {
-		if ( nlo != 0 ) {
-			/* not a range, count the number of items */
-			db_recno_t count;
-			rc = cursor->c_count( cursor, &count, 0 );
-			if ( rc != 0 ) {
-				err = "c_count";
-				goto fail;
-			}
-			if ( count >= BDB_IDL_DB_MAX ) {
-			/* No room, convert to a range */
-				DBT key2 = *key;
-				db_recno_t i;
-
-				key2.dlen = key2.ulen;
-				key2.flags |= DB_DBT_PARTIAL;
-
-				BDB_DISK2ID( &nlo, &lo );
-				data.data = &nhi;
-
-				rc = cursor->c_get( cursor, &key2, &data, DB_NEXT_NODUP );
-				if ( rc != 0 && rc != DB_NOTFOUND ) {
-					err = "c_get next_nodup";
-					goto fail;
-				}
-				if ( rc == DB_NOTFOUND ) {
-					rc = cursor->c_get( cursor, key, &data, DB_LAST );
-					if ( rc != 0 ) {
-						err = "c_get last";
-						goto fail;
-					}
-				} else {
-					rc = cursor->c_get( cursor, key, &data, DB_PREV );
-					if ( rc != 0 ) {
-						err = "c_get prev";
-						goto fail;
-					}
-				}
-				BDB_DISK2ID( &nhi, &hi );
-				/* Update hi/lo if needed, then delete all the items
-				 * between lo and hi
-				 */
-				if ( id < lo ) {
-					lo = id;
-					nlo = nid;
-				} else if ( id > hi ) {
-					hi = id;
-					nhi = nid;
-				}
-				data.data = &nid;
-				/* Don't fetch anything, just position cursor */
-				data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
-				data.dlen = data.ulen = 0;
-				rc = cursor->c_get( cursor, key, &data, DB_SET );
-				if ( rc != 0 ) {
-					err = "c_get 2";
-					goto fail;
-				}
-				rc = cursor->c_del( cursor, 0 );
-				if ( rc != 0 ) {
-					err = "c_del range1";
-					goto fail;
-				}
-				/* Delete all the records */
-				for ( i=1; i<count; i++ ) {
-					rc = cursor->c_get( cursor, &key2, &data, DB_NEXT_DUP );
-					if ( rc != 0 ) {
-						err = "c_get next_dup";
-						goto fail;
-					}
-					rc = cursor->c_del( cursor, 0 );
-					if ( rc != 0 ) {
-						err = "c_del range";
-						goto fail;
-					}
-				}
-				/* Store the range marker */
-				data.size = data.ulen = sizeof(ID);
-				data.flags = DB_DBT_USERMEM;
-				nid = 0;
-				rc = cursor->c_put( cursor, key, &data, DB_KEYFIRST );
-				if ( rc != 0 ) {
-					err = "c_put range";
-					goto fail;
-				}
-				nid = nlo;
-				rc = cursor->c_put( cursor, key, &data, DB_KEYLAST );
-				if ( rc != 0 ) {
-					err = "c_put lo";
-					goto fail;
-				}
-				nid = nhi;
-				rc = cursor->c_put( cursor, key, &data, DB_KEYLAST );
-				if ( rc != 0 ) {
-					err = "c_put hi";
-					goto fail;
-				}
-			} else {
-			/* There's room, just store it */
-				goto put1;
-			}
-		} else {
-			/* It's a range, see if we need to rewrite
-			 * the boundaries
-			 */
-			hi = id;
-			data.data = &nlo;
-			rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP );
-			if ( rc != 0 ) {
-				err = "c_get lo";
-				goto fail;
-			}
-			BDB_DISK2ID( &nlo, &lo );
-			if ( id > lo ) {
-				data.data = &nhi;
-				rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP );
-				if ( rc != 0 ) {
-					err = "c_get hi";
-					goto fail;
-				}
-				BDB_DISK2ID( &nhi, &hi );
-			}
-			if ( id < lo || id > hi ) {
-				/* Delete the current lo/hi */
-				rc = cursor->c_del( cursor, 0 );
-				if ( rc != 0 ) {
-					err = "c_del";
-					goto fail;
-				}
-				data.data = &nid;
-				rc = cursor->c_put( cursor, key, &data, DB_KEYFIRST );
-				if ( rc != 0 ) {
-					err = "c_put lo/hi";
-					goto fail;
-				}
-			}
-		}
-	} else if ( rc == DB_NOTFOUND ) {
-put1:		data.data = &nid;
-		rc = cursor->c_put( cursor, key, &data, DB_NODUPDATA );
-		/* Don't worry if it's already there */
-		if ( rc != 0 && rc != DB_KEYEXIST ) {
-			err = "c_put id";
-			goto fail;
-		}
-	} else {
-		/* initial c_get failed, nothing was done */
-fail:
-		Debug( LDAP_DEBUG_ANY, "=> bdb_idl_insert_key: "
-			"%s failed: %s (%d)\n", err, db_strerror(rc), rc );
-		cursor->c_close( cursor );
-		return rc;
-	}
-	/* If key was added (didn't already exist) and using IDL cache,
-	 * update key in IDL cache.
-	 */
-	if ( !rc && bdb->bi_idl_cache_max_size ) {
-		bdb_idl_cache_add_id( bdb, db, key, id );
-	}
-	rc = cursor->c_close( cursor );
-	if( rc != 0 ) {
-		Debug( LDAP_DEBUG_ANY, "=> bdb_idl_insert_key: "
-			"c_close failed: %s (%d)\n",
-			db_strerror(rc), rc, 0 );
-	}
-	return rc;
-}
-
-int
-bdb_idl_delete_key(
-	BackendDB	*be,
-	DB			*db,
-	DB_TXN		*tid,
-	DBT			*key,
-	ID			id )
-{
-	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
-	int	rc;
-	DBT data;
-	DBC *cursor;
-	ID lo, hi, tmp, nid, nlo, nhi;
-	char *err;
-
-	{
-		char buf[16];
-		Debug( LDAP_DEBUG_ARGS,
-			"bdb_idl_delete_key: %lx %s\n", 
-			(long) id, bdb_show_key( key, buf ), 0 );
-	}
-	assert( id != NOID );
-
-	if ( bdb->bi_idl_cache_size ) {
-		bdb_idl_cache_del( bdb, db, key );
-	}
-
-	BDB_ID2DISK( id, &nid );
-
-	DBTzero( &data );
-	data.data = &tmp;
-	data.size = sizeof( id );
-	data.ulen = data.size;
-	data.flags = DB_DBT_USERMEM;
-
-	rc = db->cursor( db, tid, &cursor, bdb->bi_db_opflags );
-	if ( rc != 0 ) {
-		Debug( LDAP_DEBUG_ANY, "=> bdb_idl_delete_key: "
-			"cursor failed: %s (%d)\n", db_strerror(rc), rc, 0 );
-		return rc;
-	}
-	/* Fetch the first data item for this key, to see if it
-	 * exists and if it's a range.
-	 */
-	rc = cursor->c_get( cursor, key, &data, DB_SET );
-	err = "c_get";
-	if ( rc == 0 ) {
-		if ( tmp != 0 ) {
-			/* Not a range, just delete it */
-			if (tmp != nid) {
-				/* position to correct item */
-				tmp = nid;
-				rc = cursor->c_get( cursor, key, &data, DB_GET_BOTH );
-				if ( rc != 0 ) {
-					err = "c_get id";
-					goto fail;
-				}
-			}
-			rc = cursor->c_del( cursor, 0 );
-			if ( rc != 0 ) {
-				err = "c_del id";
-				goto fail;
-			}
-		} else {
-			/* It's a range, see if we need to rewrite
-			 * the boundaries
-			 */
-			data.data = &nlo;
-			rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP );
-			if ( rc != 0 ) {
-				err = "c_get lo";
-				goto fail;
-			}
-			BDB_DISK2ID( &nlo, &lo );
-			data.data = &nhi;
-			rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP );
-			if ( rc != 0 ) {
-				err = "c_get hi";
-				goto fail;
-			}
-			BDB_DISK2ID( &nhi, &hi );
-			if ( id == lo || id == hi ) {
-				if ( id == lo ) {
-					id++;
-					lo = id;
-				} else if ( id == hi ) {
-					id--;
-					hi = id;
-				}
-				if ( lo >= hi ) {
-				/* The range has collapsed... */
-					rc = db->del( db, tid, key, 0 );
-					if ( rc != 0 ) {
-						err = "del";
-						goto fail;
-					}
-				} else {
-					if ( id == lo ) {
-						/* reposition on lo slot */
-						data.data = &nlo;
-						cursor->c_get( cursor, key, &data, DB_PREV );
-					}
-					rc = cursor->c_del( cursor, 0 );
-					if ( rc != 0 ) {
-						err = "c_del";
-						goto fail;
-					}
-				}
-				if ( lo <= hi ) {
-					BDB_ID2DISK( id, &nid );
-					data.data = &nid;
-					rc = cursor->c_put( cursor, key, &data, DB_KEYFIRST );
-					if ( rc != 0 ) {
-						err = "c_put lo/hi";
-						goto fail;
-					}
-				}
-			}
-		}
-	} else {
-		/* initial c_get failed, nothing was done */
-fail:
-		if ( rc != DB_NOTFOUND ) {
-		Debug( LDAP_DEBUG_ANY, "=> bdb_idl_delete_key: "
-			"%s failed: %s (%d)\n", err, db_strerror(rc), rc );
-		}
-		cursor->c_close( cursor );
-		return rc;
-	}
-	rc = cursor->c_close( cursor );
-	if( rc != 0 ) {
-		Debug( LDAP_DEBUG_ANY,
-			"=> bdb_idl_delete_key: c_close failed: %s (%d)\n",
-			db_strerror(rc), rc, 0 );
-	}
-
-	return rc;
-}
-
-
-/*
- * idl_intersection - return a = a intersection b
- */
-int
-bdb_idl_intersection(
-	ID *a,
-	ID *b )
-{
-	ID ida, idb;
-	ID idmax, idmin;
-	ID cursora = 0, cursorb = 0, cursorc;
-	int swap = 0;
-
-	if ( BDB_IDL_IS_ZERO( a ) || BDB_IDL_IS_ZERO( b ) ) {
-		a[0] = 0;
-		return 0;
-	}
-
-	idmin = IDL_MAX( BDB_IDL_FIRST(a), BDB_IDL_FIRST(b) );
-	idmax = IDL_MIN( BDB_IDL_LAST(a), BDB_IDL_LAST(b) );
-	if ( idmin > idmax ) {
-		a[0] = 0;
-		return 0;
-	} else if ( idmin == idmax ) {
-		a[0] = 1;
-		a[1] = idmin;
-		return 0;
-	}
-
-	if ( BDB_IDL_IS_RANGE( a ) ) {
-		if ( BDB_IDL_IS_RANGE(b) ) {
-		/* If both are ranges, just shrink the boundaries */
-			a[1] = idmin;
-			a[2] = idmax;
-			return 0;
-		} else {
-		/* Else swap so that b is the range, a is a list */
-			ID *tmp = a;
-			a = b;
-			b = tmp;
-			swap = 1;
-		}
-	}
-
-	/* If a range completely covers the list, the result is
-	 * just the list.
-	 */
-	if ( BDB_IDL_IS_RANGE( b )
-		&& BDB_IDL_RANGE_FIRST( b ) <= BDB_IDL_FIRST( a )
-		&& BDB_IDL_RANGE_LAST( b ) >= BDB_IDL_LLAST( a ) ) {
-		goto done;
-	}
-
-	/* Fine, do the intersection one element at a time.
-	 * First advance to idmin in both IDLs.
-	 */
-	cursora = cursorb = idmin;
-	ida = bdb_idl_first( a, &cursora );
-	idb = bdb_idl_first( b, &cursorb );
-	cursorc = 0;
-
-	while( ida <= idmax || idb <= idmax ) {
-		if( ida == idb ) {
-			a[++cursorc] = ida;
-			ida = bdb_idl_next( a, &cursora );
-			idb = bdb_idl_next( b, &cursorb );
-		} else if ( ida < idb ) {
-			ida = bdb_idl_next( a, &cursora );
-		} else {
-			idb = bdb_idl_next( b, &cursorb );
-		}
-	}
-	a[0] = cursorc;
-done:
-	if (swap)
-		BDB_IDL_CPY( b, a );
-
-	return 0;
-}
-
-
-/*
- * idl_union - return a = a union b
- */
-int
-bdb_idl_union(
-	ID	*a,
-	ID	*b )
-{
-	ID ida, idb;
-	ID cursora = 0, cursorb = 0, cursorc;
-
-	if ( BDB_IDL_IS_ZERO( b ) ) {
-		return 0;
-	}
-
-	if ( BDB_IDL_IS_ZERO( a ) ) {
-		BDB_IDL_CPY( a, b );
-		return 0;
-	}
-
-	if ( BDB_IDL_IS_RANGE( a ) || BDB_IDL_IS_RANGE(b) ) {
-over:		ida = IDL_MIN( BDB_IDL_FIRST(a), BDB_IDL_FIRST(b) );
-		idb = IDL_MAX( BDB_IDL_LAST(a), BDB_IDL_LAST(b) );
-		a[0] = NOID;
-		a[1] = ida;
-		a[2] = idb;
-		return 0;
-	}
-
-	ida = bdb_idl_first( a, &cursora );
-	idb = bdb_idl_first( b, &cursorb );
-
-	cursorc = b[0];
-
-	/* The distinct elements of a are cat'd to b */
-	while( ida != NOID || idb != NOID ) {
-		if ( ida < idb ) {
-			if( ++cursorc > BDB_IDL_UM_MAX ) {
-				goto over;
-			}
-			b[cursorc] = ida;
-			ida = bdb_idl_next( a, &cursora );
-
-		} else {
-			if ( ida == idb )
-				ida = bdb_idl_next( a, &cursora );
-			idb = bdb_idl_next( b, &cursorb );
-		}
-	}
-
-	/* b is copied back to a in sorted order */
-	a[0] = cursorc;
-	cursora = 1;
-	cursorb = 1;
-	cursorc = b[0]+1;
-	while (cursorb <= b[0] || cursorc <= a[0]) {
-		if (cursorc > a[0])
-			idb = NOID;
-		else
-			idb = b[cursorc];
-		if (cursorb <= b[0] && b[cursorb] < idb)
-			a[cursora++] = b[cursorb++];
-		else {
-			a[cursora++] = idb;
-			cursorc++;
-		}
-	}
-
-	return 0;
-}
-
-
-#if 0
-/*
- * bdb_idl_notin - return a intersection ~b (or a minus b)
- */
-int
-bdb_idl_notin(
-	ID	*a,
-	ID	*b,
-	ID *ids )
-{
-	ID ida, idb;
-	ID cursora = 0, cursorb = 0;
-
-	if( BDB_IDL_IS_ZERO( a ) ||
-		BDB_IDL_IS_ZERO( b ) ||
-		BDB_IDL_IS_RANGE( b ) )
-	{
-		BDB_IDL_CPY( ids, a );
-		return 0;
-	}
-
-	if( BDB_IDL_IS_RANGE( a ) ) {
-		BDB_IDL_CPY( ids, a );
-		return 0;
-	}
-
-	ida = bdb_idl_first( a, &cursora ),
-	idb = bdb_idl_first( b, &cursorb );
-
-	ids[0] = 0;
-
-	while( ida != NOID ) {
-		if ( idb == NOID ) {
-			/* we could shortcut this */
-			ids[++ids[0]] = ida;
-			ida = bdb_idl_next( a, &cursora );
-
-		} else if ( ida < idb ) {
-			ids[++ids[0]] = ida;
-			ida = bdb_idl_next( a, &cursora );
-
-		} else if ( ida > idb ) {
-			idb = bdb_idl_next( b, &cursorb );
-
-		} else {
-			ida = bdb_idl_next( a, &cursora );
-			idb = bdb_idl_next( b, &cursorb );
-		}
-	}
-
-	return 0;
-}
-#endif
-
-ID bdb_idl_first( ID *ids, ID *cursor )
-{
-	ID pos;
-
-	if ( ids[0] == 0 ) {
-		*cursor = NOID;
-		return NOID;
-	}
-
-	if ( BDB_IDL_IS_RANGE( ids ) ) {
-		if( *cursor < ids[1] ) {
-			*cursor = ids[1];
-		}
-		return *cursor;
-	}
-
-	if ( *cursor == 0 )
-		pos = 1;
-	else
-		pos = bdb_idl_search( ids, *cursor );
-
-	if( pos > ids[0] ) {
-		return NOID;
-	}
-
-	*cursor = pos;
-	return ids[pos];
-}
-
-ID bdb_idl_next( ID *ids, ID *cursor )
-{
-	if ( BDB_IDL_IS_RANGE( ids ) ) {
-		if( ids[2] < ++(*cursor) ) {
-			return NOID;
-		}
-		return *cursor;
-	}
-
-	if ( ++(*cursor) <= ids[0] ) {
-		return ids[*cursor];
-	}
-
-	return NOID;
-}
-
-#ifdef BDB_HIER
-
-/* Add one ID to an unsorted list. We ensure that the first element is the
- * minimum and the last element is the maximum, for fast range compaction.
- *   this means IDLs up to length 3 are always sorted...
- */
-int bdb_idl_append_one( ID *ids, ID id )
-{
-	if (BDB_IDL_IS_RANGE( ids )) {
-		/* if already in range, treat as a dup */
-		if (id >= BDB_IDL_RANGE_FIRST(ids) && id <= BDB_IDL_RANGE_LAST(ids))
-			return -1;
-		if (id < BDB_IDL_RANGE_FIRST(ids))
-			ids[1] = id;
-		else if (id > BDB_IDL_RANGE_LAST(ids))
-			ids[2] = id;
-		return 0;
-	}
-	if ( ids[0] ) {
-		ID tmp;
-
-		if (id < ids[1]) {
-			tmp = ids[1];
-			ids[1] = id;
-			id = tmp;
-		}
-		if ( ids[0] > 1 && id < ids[ids[0]] ) {
-			tmp = ids[ids[0]];
-			ids[ids[0]] = id;
-			id = tmp;
-		}
-	}
-	ids[0]++;
-	if ( ids[0] >= BDB_IDL_UM_MAX ) {
-		ids[0] = NOID;
-		ids[2] = id;
-	} else {
-		ids[ids[0]] = id;
-	}
-	return 0;
-}
-
-/* Append sorted list b to sorted list a. The result is unsorted but
- * a[1] is the min of the result and a[a[0]] is the max.
- */
-int bdb_idl_append( ID *a, ID *b )
-{
-	ID ida, idb, tmp, swap = 0;
-
-	if ( BDB_IDL_IS_ZERO( b ) ) {
-		return 0;
-	}
-
-	if ( BDB_IDL_IS_ZERO( a ) ) {
-		BDB_IDL_CPY( a, b );
-		return 0;
-	}
-
-	if ( b[0] == 1 ) {
-		return bdb_idl_append_one( a, BDB_IDL_FIRST( b ));
-	}
-
-	ida = BDB_IDL_LAST( a );
-	idb = BDB_IDL_LAST( b );
-	if ( BDB_IDL_IS_RANGE( a ) || BDB_IDL_IS_RANGE(b) ||
-		a[0] + b[0] >= BDB_IDL_UM_MAX ) {
-		a[2] = IDL_MAX( ida, idb );
-		a[1] = IDL_MIN( a[1], b[1] );
-		a[0] = NOID;
-		return 0;
-	}
-
-	if ( ida > idb ) {
-		swap = idb;
-		a[a[0]] = idb;
-		b[b[0]] = ida;
-	}
-
-	if ( b[1] < a[1] ) {
-		tmp = a[1];
-		a[1] = b[1];
-	} else {
-		tmp = b[1];
-	}
-	a[0]++;
-	a[a[0]] = tmp;
-
-	{
-		int i = b[0] - 1;
-		AC_MEMCPY(a+a[0]+1, b+2, i * sizeof(ID));
-		a[0] += i;
-	}
-	if ( swap ) {
-		b[b[0]] = swap;
-	}
-	return 0;
-}
-
-#if 1
-
-/* Quicksort + Insertion sort for small arrays */
-
-#define SMALL	8
-#define	SWAP(a,b)	itmp=(a);(a)=(b);(b)=itmp
-
-void
-bdb_idl_sort( ID *ids, ID *tmp )
-{
-	int *istack = (int *)tmp;
-	int i,j,k,l,ir,jstack;
-	ID a, itmp;
-
-	if ( BDB_IDL_IS_RANGE( ids ))
-		return;
-
-	ir = ids[0];
-	l = 1;
-	jstack = 0;
-	for(;;) {
-		if (ir - l < SMALL) {	/* Insertion sort */
-			for (j=l+1;j<=ir;j++) {
-				a = ids[j];
-				for (i=j-1;i>=1;i--) {
-					if (ids[i] <= a) break;
-					ids[i+1] = ids[i];
-				}
-				ids[i+1] = a;
-			}
-			if (jstack == 0) break;
-			ir = istack[jstack--];
-			l = istack[jstack--];
-		} else {
-			k = (l + ir) >> 1;	/* Choose median of left, center, right */
-			SWAP(ids[k], ids[l+1]);
-			if (ids[l] > ids[ir]) {
-				SWAP(ids[l], ids[ir]);
-			}
-			if (ids[l+1] > ids[ir]) {
-				SWAP(ids[l+1], ids[ir]);
-			}
-			if (ids[l] > ids[l+1]) {
-				SWAP(ids[l], ids[l+1]);
-			}
-			i = l+1;
-			j = ir;
-			a = ids[l+1];
-			for(;;) {
-				do i++; while(ids[i] < a);
-				do j--; while(ids[j] > a);
-				if (j < i) break;
-				SWAP(ids[i],ids[j]);
-			}
-			ids[l+1] = ids[j];
-			ids[j] = a;
-			jstack += 2;
-			if (ir-i+1 >= j-1) {
-				istack[jstack] = ir;
-				istack[jstack-1] = i;
-				ir = j-1;
-			} else {
-				istack[jstack] = j-1;
-				istack[jstack-1] = l;
-				l = i;
-			}
-		}
-	}
-}
-
-#else
-
-/* 8 bit Radix sort + insertion sort
- * 
- * based on code from http://www.cubic.org/docs/radix.htm
- * with improvements by ebackes@symas.com and hyc@symas.com
- *
- * This code is O(n) but has a relatively high constant factor. For lists
- * up to ~50 Quicksort is slightly faster; up to ~100 they are even.
- * Much faster than quicksort for lists longer than ~100. Insertion
- * sort is actually superior for lists <50.
- */
-
-#define BUCKETS	(1<<8)
-#define SMALL	50
-
-void
-bdb_idl_sort( ID *ids, ID *tmp )
-{
-	int count, soft_limit, phase = 0, size = ids[0];
-	ID *idls[2];
-	unsigned char *maxv = (unsigned char *)&ids[size];
-
- 	if ( BDB_IDL_IS_RANGE( ids ))
- 		return;
-
-	/* Use insertion sort for small lists */
-	if ( size <= SMALL ) {
-		int i,j;
-		ID a;
-
-		for (j=1;j<=size;j++) {
-			a = ids[j];
-			for (i=j-1;i>=1;i--) {
-				if (ids[i] <= a) break;
-				ids[i+1] = ids[i];
-			}
-			ids[i+1] = a;
-		}
-		return;
-	}
-
-	tmp[0] = size;
-	idls[0] = ids;
-	idls[1] = tmp;
-
-#if BYTE_ORDER == BIG_ENDIAN
-    for (soft_limit = 0; !maxv[soft_limit]; soft_limit++);
-#else
-    for (soft_limit = sizeof(ID)-1; !maxv[soft_limit]; soft_limit--);
-#endif
-
-	for (
-#if BYTE_ORDER == BIG_ENDIAN
-	count = sizeof(ID)-1; count >= soft_limit; --count
-#else
-	count = 0; count <= soft_limit; ++count
-#endif
-	) {
-		unsigned int num[BUCKETS], * np, n, sum;
-		int i;
-        ID *sp, *source, *dest;
-        unsigned char *bp, *source_start;
-
-		source = idls[phase]+1;
-		dest = idls[phase^1]+1;
-		source_start =  ((unsigned char *) source) + count;
-
-        np = num;
-        for ( i = BUCKETS; i > 0; --i ) *np++ = 0;
-
-		/* count occurences of every byte value */
-		bp = source_start;
-        for ( i = size; i > 0; --i, bp += sizeof(ID) )
-				num[*bp]++;
-
-		/* transform count into index by summing elements and storing
-		 * into same array
-		 */
-        sum = 0;
-        np = num;
-        for ( i = BUCKETS; i > 0; --i ) {
-                n = *np;
-                *np++ = sum;
-                sum += n;
-        }
-
-		/* fill dest with the right values in the right place */
-		bp = source_start;
-        sp = source;
-        for ( i = size; i > 0; --i, bp += sizeof(ID) ) {
-                np = num + *bp;
-                dest[*np] = *sp++;
-                ++(*np);
-        }
-		phase ^= 1;
-	}
-
-	/* copy back from temp if needed */
-	if ( phase ) {
-		ids++; tmp++;
-		for ( count = 0; count < size; ++count ) 
-			*ids++ = *tmp++;
-	}
-}
-#endif	/* Quick vs Radix */
-
-#endif	/* BDB_HIER */
diff --git a/servers/slapd/back-bdb/idl.h b/servers/slapd/back-bdb/idl.h
deleted file mode 100644
index 909a43b..0000000
--- a/servers/slapd/back-bdb/idl.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* idl.h - ldap bdb back-end ID list header file */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#ifndef _BDB_IDL_H_
-#define _BDB_IDL_H_
-
-/* IDL sizes - likely should be even bigger
- *   limiting factors: sizeof(ID), thread stack size
- */
-#define	BDB_IDL_LOGN	16	/* DB_SIZE is 2^16, UM_SIZE is 2^17 */
-#define BDB_IDL_DB_SIZE		(1<<BDB_IDL_LOGN)
-#define BDB_IDL_UM_SIZE		(1<<(BDB_IDL_LOGN+1))
-#define BDB_IDL_UM_SIZEOF	(BDB_IDL_UM_SIZE * sizeof(ID))
-
-#define BDB_IDL_DB_MAX		(BDB_IDL_DB_SIZE-1)
-
-#define BDB_IDL_UM_MAX		(BDB_IDL_UM_SIZE-1)
-
-#define BDB_IDL_IS_RANGE(ids)	((ids)[0] == NOID)
-#define BDB_IDL_RANGE_SIZE		(3)
-#define BDB_IDL_RANGE_SIZEOF	(BDB_IDL_RANGE_SIZE * sizeof(ID))
-#define BDB_IDL_SIZEOF(ids)		((BDB_IDL_IS_RANGE(ids) \
-	? BDB_IDL_RANGE_SIZE : ((ids)[0]+1)) * sizeof(ID))
-
-#define BDB_IDL_RANGE_FIRST(ids)	((ids)[1])
-#define BDB_IDL_RANGE_LAST(ids)		((ids)[2])
-
-#define BDB_IDL_RANGE( ids, f, l ) \
-	do { \
-		(ids)[0] = NOID; \
-		(ids)[1] = (f);  \
-		(ids)[2] = (l);  \
-	} while(0)
-
-#define BDB_IDL_ZERO(ids) \
-	do { \
-		(ids)[0] = 0; \
-		(ids)[1] = 0; \
-		(ids)[2] = 0; \
-	} while(0)
-
-#define BDB_IDL_IS_ZERO(ids) ( (ids)[0] == 0 )
-#define BDB_IDL_IS_ALL( range, ids ) ( (ids)[0] == NOID \
-	&& (ids)[1] <= (range)[1] && (range)[2] <= (ids)[2] )
-
-#define BDB_IDL_CPY( dst, src ) (AC_MEMCPY( dst, src, BDB_IDL_SIZEOF( src ) ))
-
-#define BDB_IDL_ID( bdb, ids, id ) BDB_IDL_RANGE( ids, id, ((bdb)->bi_lastid) )
-#define BDB_IDL_ALL( bdb, ids ) BDB_IDL_RANGE( ids, 1, ((bdb)->bi_lastid) )
-
-#define BDB_IDL_FIRST( ids )	( (ids)[1] )
-#define BDB_IDL_LLAST( ids )	( (ids)[(ids)[0]] )
-#define BDB_IDL_LAST( ids )		( BDB_IDL_IS_RANGE(ids) \
-	? (ids)[2] : (ids)[(ids)[0]] )
-
-#define BDB_IDL_N( ids )		( BDB_IDL_IS_RANGE(ids) \
-	? ((ids)[2]-(ids)[1])+1 : (ids)[0] )
-
-LDAP_BEGIN_DECL
-LDAP_END_DECL
-
-#endif
diff --git a/servers/slapd/back-bdb/index.c b/servers/slapd/back-bdb/index.c
deleted file mode 100644
index c095641..0000000
--- a/servers/slapd/back-bdb/index.c
+++ /dev/null
@@ -1,574 +0,0 @@
-/* index.c - routines for dealing with attribute indexes */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/string.h>
-#include <ac/socket.h>
-
-#include "slap.h"
-#include "back-bdb.h"
-#include "lutil_hash.h"
-
-static char presence_keyval[] = {0,0};
-static struct berval presence_key = BER_BVC(presence_keyval);
-
-AttrInfo *bdb_index_mask(
-	Backend *be,
-	AttributeDescription *desc,
-	struct berval *atname )
-{
-	AttributeType *at;
-	AttrInfo *ai = bdb_attr_mask( be->be_private, desc );
-
-	if( ai ) {
-		*atname = desc->ad_cname;
-		return ai;
-	}
-
-	/* If there is a tagging option, did we ever index the base
-	 * type? If so, check for mask, otherwise it's not there.
-	 */
-	if( slap_ad_is_tagged( desc ) && desc != desc->ad_type->sat_ad ) {
-		/* has tagging option */
-		ai = bdb_attr_mask( be->be_private, desc->ad_type->sat_ad );
-
-		if ( ai && !( ai->ai_indexmask & SLAP_INDEX_NOTAGS ) ) {
-			*atname = desc->ad_type->sat_cname;
-			return ai;
-		}
-	}
-
-	/* see if supertype defined mask for its subtypes */
-	for( at = desc->ad_type; at != NULL ; at = at->sat_sup ) {
-		/* If no AD, we've never indexed this type */
-		if ( !at->sat_ad ) continue;
-
-		ai = bdb_attr_mask( be->be_private, at->sat_ad );
-
-		if ( ai && !( ai->ai_indexmask & SLAP_INDEX_NOSUBTYPES ) ) {
-			*atname = at->sat_cname;
-			return ai;
-		}
-	}
-
-	return 0;
-}
-
-/* This function is only called when evaluating search filters.
- */
-int bdb_index_param(
-	Backend *be,
-	AttributeDescription *desc,
-	int ftype,
-	DB **dbp,
-	slap_mask_t *maskp,
-	struct berval *prefixp )
-{
-	AttrInfo *ai;
-	int rc;
-	slap_mask_t mask, type = 0;
-	DB *db;
-
-	ai = bdb_index_mask( be, desc, prefixp );
-
-	if ( !ai ) {
-#ifdef BDB_MONITOR_IDX
-		switch ( ftype ) {
-		case LDAP_FILTER_PRESENT:
-			type = SLAP_INDEX_PRESENT;
-			break;
-		case LDAP_FILTER_APPROX:
-			type = SLAP_INDEX_APPROX;
-			break;
-		case LDAP_FILTER_EQUALITY:
-			type = SLAP_INDEX_EQUALITY;
-			break;
-		case LDAP_FILTER_SUBSTRINGS:
-			type = SLAP_INDEX_SUBSTR;
-			break;
-		default:
-			return LDAP_INAPPROPRIATE_MATCHING;
-		}
-		bdb_monitor_idx_add( be->be_private, desc, type );
-#endif /* BDB_MONITOR_IDX */
-
-		return LDAP_INAPPROPRIATE_MATCHING;
-	}
-	mask = ai->ai_indexmask;
-
-	rc = bdb_db_cache( be, prefixp, &db );
-
-	if( rc != LDAP_SUCCESS ) {
-		return rc;
-	}
-
-	switch( ftype ) {
-	case LDAP_FILTER_PRESENT:
-		type = SLAP_INDEX_PRESENT;
-		if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
-			*prefixp = presence_key;
-			goto done;
-		}
-		break;
-
-	case LDAP_FILTER_APPROX:
-		type = SLAP_INDEX_APPROX;
-		if ( desc->ad_type->sat_approx ) {
-			if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
-				goto done;
-			}
-			break;
-		}
-
-		/* Use EQUALITY rule and index for approximate match */
-		/* fall thru */
-
-	case LDAP_FILTER_EQUALITY:
-		type = SLAP_INDEX_EQUALITY;
-		if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
-			goto done;
-		}
-		break;
-
-	case LDAP_FILTER_SUBSTRINGS:
-		type = SLAP_INDEX_SUBSTR;
-		if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
-			goto done;
-		}
-		break;
-
-	default:
-		return LDAP_OTHER;
-	}
-
-#ifdef BDB_MONITOR_IDX
-	bdb_monitor_idx_add( be->be_private, desc, type );
-#endif /* BDB_MONITOR_IDX */
-
-	return LDAP_INAPPROPRIATE_MATCHING;
-
-done:
-	*dbp = db;
-	*maskp = mask;
-	return LDAP_SUCCESS;
-}
-
-static int indexer(
-	Operation *op,
-	DB_TXN *txn,
-	AttributeDescription *ad,
-	struct berval *atname,
-	BerVarray vals,
-	ID id,
-	int opid,
-	slap_mask_t mask )
-{
-	int rc, i;
-	DB *db;
-	struct berval *keys;
-
-	assert( mask != 0 );
-
-	rc = bdb_db_cache( op->o_bd, atname, &db );
-	
-	if ( rc != LDAP_SUCCESS ) {
-		Debug( LDAP_DEBUG_ANY,
-			"bdb_index_read: Could not open DB %s\n",
-			atname->bv_val, 0, 0 );
-		return LDAP_OTHER;
-	}
-
-	if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
-		rc = bdb_key_change( op->o_bd, db, txn, &presence_key, id, opid );
-		if( rc ) {
-			goto done;
-		}
-	}
-
-	if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
-		rc = ad->ad_type->sat_equality->smr_indexer(
-			LDAP_FILTER_EQUALITY,
-			mask,
-			ad->ad_type->sat_syntax,
-			ad->ad_type->sat_equality,
-			atname, vals, &keys, op->o_tmpmemctx );
-
-		if( rc == LDAP_SUCCESS && keys != NULL ) {
-			for( i=0; keys[i].bv_val != NULL; i++ ) {
-				rc = bdb_key_change( op->o_bd, db, txn, &keys[i], id, opid );
-				if( rc ) {
-					ber_bvarray_free_x( keys, op->o_tmpmemctx );
-					goto done;
-				}
-			}
-			ber_bvarray_free_x( keys, op->o_tmpmemctx );
-		}
-		rc = LDAP_SUCCESS;
-	}
-
-	if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
-		rc = ad->ad_type->sat_approx->smr_indexer(
-			LDAP_FILTER_APPROX,
-			mask,
-			ad->ad_type->sat_syntax,
-			ad->ad_type->sat_approx,
-			atname, vals, &keys, op->o_tmpmemctx );
-
-		if( rc == LDAP_SUCCESS && keys != NULL ) {
-			for( i=0; keys[i].bv_val != NULL; i++ ) {
-				rc = bdb_key_change( op->o_bd, db, txn, &keys[i], id, opid );
-				if( rc ) {
-					ber_bvarray_free_x( keys, op->o_tmpmemctx );
-					goto done;
-				}
-			}
-			ber_bvarray_free_x( keys, op->o_tmpmemctx );
-		}
-
-		rc = LDAP_SUCCESS;
-	}
-
-	if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
-		rc = ad->ad_type->sat_substr->smr_indexer(
-			LDAP_FILTER_SUBSTRINGS,
-			mask,
-			ad->ad_type->sat_syntax,
-			ad->ad_type->sat_substr,
-			atname, vals, &keys, op->o_tmpmemctx );
-
-		if( rc == LDAP_SUCCESS && keys != NULL ) {
-			for( i=0; keys[i].bv_val != NULL; i++ ) {
-				rc = bdb_key_change( op->o_bd, db, txn, &keys[i], id, opid );
-				if( rc ) {
-					ber_bvarray_free_x( keys, op->o_tmpmemctx );
-					goto done;
-				}
-			}
-			ber_bvarray_free_x( keys, op->o_tmpmemctx );
-		}
-
-		rc = LDAP_SUCCESS;
-	}
-
-done:
-	switch( rc ) {
-	/* The callers all know how to deal with these results */
-	case 0:
-	case DB_LOCK_DEADLOCK:
-	case DB_LOCK_NOTGRANTED:
-		break;
-	/* Anything else is bad news */
-	default:
-		rc = LDAP_OTHER;
-	}
-	return rc;
-}
-
-static int index_at_values(
-	Operation *op,
-	DB_TXN *txn,
-	AttributeDescription *ad,
-	AttributeType *type,
-	struct berval *tags,
-	BerVarray vals,
-	ID id,
-	int opid )
-{
-	int rc;
-	slap_mask_t mask = 0;
-	int ixop = opid;
-	AttrInfo *ai = NULL;
-
-	if ( opid == BDB_INDEX_UPDATE_OP )
-		ixop = SLAP_INDEX_ADD_OP;
-
-	if( type->sat_sup ) {
-		/* recurse */
-		rc = index_at_values( op, txn, NULL,
-			type->sat_sup, tags,
-			vals, id, opid );
-
-		if( rc ) return rc;
-	}
-
-	/* If this type has no AD, we've never used it before */
-	if( type->sat_ad ) {
-		ai = bdb_attr_mask( op->o_bd->be_private, type->sat_ad );
-		if ( ai ) {
-#ifdef LDAP_COMP_MATCH
-			/* component indexing */
-			if ( ai->ai_cr ) {
-				ComponentReference *cr;
-				for( cr = ai->ai_cr ; cr ; cr = cr->cr_next ) {
-					rc = indexer( op, txn, cr->cr_ad, &type->sat_cname,
-						cr->cr_nvals, id, ixop,
-						cr->cr_indexmask );
-				}
-			}
-#endif
-			ad = type->sat_ad;
-			/* If we're updating the index, just set the new bits that aren't
-			 * already in the old mask.
-			 */
-			if ( opid == BDB_INDEX_UPDATE_OP )
-				mask = ai->ai_newmask & ~ai->ai_indexmask;
-			else
-			/* For regular updates, if there is a newmask use it. Otherwise
-			 * just use the old mask.
-			 */
-				mask = ai->ai_newmask ? ai->ai_newmask : ai->ai_indexmask;
-			if( mask ) {
-				rc = indexer( op, txn, ad, &type->sat_cname,
-					vals, id, ixop, mask );
-
-				if( rc ) return rc;
-			}
-		}
-	}
-
-	if( tags->bv_len ) {
-		AttributeDescription *desc;
-
-		desc = ad_find_tags( type, tags );
-		if( desc ) {
-			ai = bdb_attr_mask( op->o_bd->be_private, desc );
-
-			if( ai ) {
-				if ( opid == BDB_INDEX_UPDATE_OP )
-					mask = ai->ai_newmask & ~ai->ai_indexmask;
-				else
-					mask = ai->ai_newmask ? ai->ai_newmask : ai->ai_indexmask;
-				if ( mask ) {
-					rc = indexer( op, txn, desc, &desc->ad_cname,
-						vals, id, ixop, mask );
-
-					if( rc ) {
-						return rc;
-					}
-				}
-			}
-		}
-	}
-
-	return LDAP_SUCCESS;
-}
-
-int bdb_index_values(
-	Operation *op,
-	DB_TXN *txn,
-	AttributeDescription *desc,
-	BerVarray vals,
-	ID id,
-	int opid )
-{
-	int rc;
-
-	/* Never index ID 0 */
-	if ( id == 0 )
-		return 0;
-
-	rc = index_at_values( op, txn, desc,
-		desc->ad_type, &desc->ad_tags,
-		vals, id, opid );
-
-	return rc;
-}
-
-/* Get the list of which indices apply to this attr */
-int
-bdb_index_recset(
-	struct bdb_info *bdb,
-	Attribute *a,
-	AttributeType *type,
-	struct berval *tags,
-	IndexRec *ir )
-{
-	int rc, slot;
-	AttrList *al;
-
-	if( type->sat_sup ) {
-		/* recurse */
-		rc = bdb_index_recset( bdb, a, type->sat_sup, tags, ir );
-		if( rc ) return rc;
-	}
-	/* If this type has no AD, we've never used it before */
-	if( type->sat_ad ) {
-		slot = bdb_attr_slot( bdb, type->sat_ad, NULL );
-		if ( slot >= 0 ) {
-			ir[slot].ai = bdb->bi_attrs[slot];
-			al = ch_malloc( sizeof( AttrList ));
-			al->attr = a;
-			al->next = ir[slot].attrs;
-			ir[slot].attrs = al;
-		}
-	}
-	if( tags->bv_len ) {
-		AttributeDescription *desc;
-
-		desc = ad_find_tags( type, tags );
-		if( desc ) {
-			slot = bdb_attr_slot( bdb, desc, NULL );
-			if ( slot >= 0 ) {
-				ir[slot].ai = bdb->bi_attrs[slot];
-				al = ch_malloc( sizeof( AttrList ));
-				al->attr = a;
-				al->next = ir[slot].attrs;
-				ir[slot].attrs = al;
-			}
-		}
-	}
-	return LDAP_SUCCESS;
-}
-
-/* Apply the indices for the recset */
-int bdb_index_recrun(
-	Operation *op,
-	struct bdb_info *bdb,
-	IndexRec *ir0,
-	ID id,
-	int base )
-{
-	IndexRec *ir;
-	AttrList *al;
-	int i, rc = 0;
-
-	/* Never index ID 0 */
-	if ( id == 0 )
-		return 0;
-
-	for (i=base; i<bdb->bi_nattrs; i+=slap_tool_thread_max-1) {
-		ir = ir0 + i;
-		if ( !ir->ai ) continue;
-		while (( al = ir->attrs )) {
-			ir->attrs = al->next;
-			rc = indexer( op, NULL, ir->ai->ai_desc,
-				&ir->ai->ai_desc->ad_type->sat_cname,
-				al->attr->a_nvals, id, SLAP_INDEX_ADD_OP,
-				ir->ai->ai_indexmask );
-			free( al );
-			if ( rc ) break;
-		}
-	}
-	return rc;
-}
-
-int
-bdb_index_entry(
-	Operation *op,
-	DB_TXN *txn,
-	int opid,
-	Entry	*e )
-{
-	int rc;
-	Attribute *ap = e->e_attrs;
-#if 0 /* ifdef LDAP_COMP_MATCH */
-	ComponentReference *cr_list = NULL;
-	ComponentReference *cr = NULL, *dupped_cr = NULL;
-	void* decoded_comp;
-	ComponentSyntaxInfo* csi_attr;
-	Syntax* syn;
-	AttributeType* at;
-	int i, num_attr;
-	void* mem_op;
-	struct berval value = {0};
-#endif
-
-	/* Never index ID 0 */
-	if ( e->e_id == 0 )
-		return 0;
-
-	Debug( LDAP_DEBUG_TRACE, "=> index_entry_%s( %ld, \"%s\" )\n",
-		opid == SLAP_INDEX_DELETE_OP ? "del" : "add",
-		(long) e->e_id, e->e_dn );
-
-	/* add each attribute to the indexes */
-	for ( ; ap != NULL; ap = ap->a_next ) {
-#if 0 /* ifdef LDAP_COMP_MATCH */
-		AttrInfo *ai;
-		/* see if attribute has components to be indexed */
-		ai = bdb_attr_mask( op->o_bd->be_private, ap->a_desc->ad_type->sat_ad );
-		if ( !ai ) continue;
-		cr_list = ai->ai_cr;
-		if ( attr_converter && cr_list ) {
-			syn = ap->a_desc->ad_type->sat_syntax;
-			ap->a_comp_data = op->o_tmpalloc( sizeof( ComponentData ), op->o_tmpmemctx );
-                	/* Memory chunk(nibble) pre-allocation for decoders */
-                	mem_op = nibble_mem_allocator ( 1024*16, 1024*4 );
-			ap->a_comp_data->cd_mem_op = mem_op;
-			for( cr = cr_list ; cr ; cr = cr->cr_next ) {
-				/* count how many values in an attribute */
-				for( num_attr=0; ap->a_vals[num_attr].bv_val != NULL; num_attr++ );
-				num_attr++;
-				cr->cr_nvals = (BerVarray)op->o_tmpalloc( sizeof( struct berval )*num_attr, op->o_tmpmemctx );
-				for( i=0; ap->a_vals[i].bv_val != NULL; i++ ) {
-					/* decoding attribute value */
-					decoded_comp = attr_converter ( ap, syn, &ap->a_vals[i] );
-					if ( !decoded_comp )
-						return LDAP_DECODING_ERROR;
-					/* extracting the referenced component */
-					dupped_cr = dup_comp_ref( op, cr );
-					csi_attr = ((ComponentSyntaxInfo*)decoded_comp)->csi_comp_desc->cd_extract_i( mem_op, dupped_cr, decoded_comp );
-					if ( !csi_attr )
-						return LDAP_DECODING_ERROR;
-					cr->cr_asn_type_id = csi_attr->csi_comp_desc->cd_type_id;
-					cr->cr_ad = (AttributeDescription*)get_component_description ( cr->cr_asn_type_id );
-					if ( !cr->cr_ad )
-						return LDAP_INVALID_SYNTAX;
-					at = cr->cr_ad->ad_type;
-					/* encoding the value of component in GSER */
-					rc = component_encoder( mem_op, csi_attr, &value );
-					if ( rc != LDAP_SUCCESS )
-						return LDAP_ENCODING_ERROR;
-					/* Normalize the encoded component values */
-					if ( at->sat_equality && at->sat_equality->smr_normalize ) {
-						rc = at->sat_equality->smr_normalize (
-							SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
-							at->sat_syntax, at->sat_equality,
-							&value, &cr->cr_nvals[i], op->o_tmpmemctx );
-					} else {
-						cr->cr_nvals[i] = value;
-					}
-				}
-				/* The end of BerVarray */
-				cr->cr_nvals[num_attr-1].bv_val = NULL;
-				cr->cr_nvals[num_attr-1].bv_len = 0;
-			}
-			op->o_tmpfree( ap->a_comp_data, op->o_tmpmemctx );
-			nibble_mem_free ( mem_op );
-			ap->a_comp_data = NULL;
-		}
-#endif
-		rc = bdb_index_values( op, txn, ap->a_desc,
-			ap->a_nvals, e->e_id, opid );
-
-		if( rc != LDAP_SUCCESS ) {
-			Debug( LDAP_DEBUG_TRACE,
-				"<= index_entry_%s( %ld, \"%s\" ) failure\n",
-				opid == SLAP_INDEX_ADD_OP ? "add" : "del",
-				(long) e->e_id, e->e_dn );
-			return rc;
-		}
-	}
-
-	Debug( LDAP_DEBUG_TRACE, "<= index_entry_%s( %ld, \"%s\" ) success\n",
-		opid == SLAP_INDEX_DELETE_OP ? "del" : "add",
-		(long) e->e_id, e->e_dn );
-
-	return LDAP_SUCCESS;
-}
diff --git a/servers/slapd/back-bdb/init.c b/servers/slapd/back-bdb/init.c
deleted file mode 100644
index 6c42d54..0000000
--- a/servers/slapd/back-bdb/init.c
+++ /dev/null
@@ -1,874 +0,0 @@
-/* init.c - initialize bdb backend */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-#include <ac/stdlib.h>
-#include <ac/errno.h>
-#include <sys/stat.h>
-#include "back-bdb.h"
-#include <lutil.h>
-#include <ldap_rq.h>
-#include "alock.h"
-#include "config.h"
-
-static const struct bdbi_database {
-	char *file;
-	struct berval name;
-	int type;
-	int flags;
-} bdbi_databases[] = {
-	{ "id2entry" BDB_SUFFIX, BER_BVC("id2entry"), DB_BTREE, 0 },
-	{ "dn2id" BDB_SUFFIX, BER_BVC("dn2id"), DB_BTREE, 0 },
-	{ NULL, BER_BVNULL, 0, 0 }
-};
-
-typedef void * db_malloc(size_t);
-typedef void * db_realloc(void *, size_t);
-
-#define bdb_db_init	BDB_SYMBOL(db_init)
-#define bdb_db_open BDB_SYMBOL(db_open)
-#define bdb_db_close BDB_SYMBOL(db_close)
-
-static int
-bdb_db_init( BackendDB *be, ConfigReply *cr )
-{
-	struct bdb_info	*bdb;
-	int rc;
-
-	Debug( LDAP_DEBUG_TRACE,
-		LDAP_XSTRING(bdb_db_init) ": Initializing " BDB_UCTYPE " database\n",
-		0, 0, 0 );
-
-	/* allocate backend-database-specific stuff */
-	bdb = (struct bdb_info *) ch_calloc( 1, sizeof(struct bdb_info) );
-
-	/* DBEnv parameters */
-	bdb->bi_dbenv_home = ch_strdup( SLAPD_DEFAULT_DB_DIR );
-	bdb->bi_dbenv_xflags = DB_TIME_NOTGRANTED;
-	bdb->bi_dbenv_mode = SLAPD_DEFAULT_DB_MODE;
-
-	bdb->bi_cache.c_maxsize = DEFAULT_CACHE_SIZE;
-	bdb->bi_cache.c_minfree = 1;
-
-	bdb->bi_lock_detect = DB_LOCK_DEFAULT;
-	bdb->bi_search_stack_depth = DEFAULT_SEARCH_STACK_DEPTH;
-	bdb->bi_search_stack = NULL;
-
-	ldap_pvt_thread_mutex_init( &bdb->bi_database_mutex );
-	ldap_pvt_thread_mutex_init( &bdb->bi_lastid_mutex );
-#ifdef BDB_HIER
-	ldap_pvt_thread_mutex_init( &bdb->bi_modrdns_mutex );
-#endif
-	ldap_pvt_thread_mutex_init( &bdb->bi_cache.c_lru_mutex );
-	ldap_pvt_thread_mutex_init( &bdb->bi_cache.c_count_mutex );
-	ldap_pvt_thread_mutex_init( &bdb->bi_cache.c_eifree_mutex );
-	ldap_pvt_thread_mutex_init( &bdb->bi_cache.c_dntree.bei_kids_mutex );
-	ldap_pvt_thread_rdwr_init ( &bdb->bi_cache.c_rwlock );
-	ldap_pvt_thread_rdwr_init( &bdb->bi_idl_tree_rwlock );
-	ldap_pvt_thread_mutex_init( &bdb->bi_idl_tree_lrulock );
-
-	be->be_private = bdb;
-	be->be_cf_ocs = be->bd_info->bi_cf_ocs;
-
-#ifndef BDB_MULTIPLE_SUFFIXES
-	SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_ONE_SUFFIX;
-#endif
-
-	rc = bdb_monitor_db_init( be );
-
-	return rc;
-}
-
-static int
-bdb_db_close( BackendDB *be, ConfigReply *cr );
-
-static int
-bdb_db_open( BackendDB *be, ConfigReply *cr )
-{
-	int rc, i;
-	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
-	struct stat stat1, stat2;
-	u_int32_t flags;
-	char path[MAXPATHLEN];
-	char *dbhome;
-	Entry *e = NULL;
-	int do_recover = 0, do_alock_recover = 0;
-	int alockt, quick = 0;
-	int do_retry = 1;
-
-	if ( be->be_suffix == NULL ) {
-		Debug( LDAP_DEBUG_ANY,
-			LDAP_XSTRING(bdb_db_open) ": need suffix.\n",
-			1, 0, 0 );
-		return -1;
-	}
-
-	Debug( LDAP_DEBUG_ARGS,
-		LDAP_XSTRING(bdb_db_open) ": \"%s\"\n",
-		be->be_suffix[0].bv_val, 0, 0 );
-
-	/* Check existence of dbenv_home. Any error means trouble */
-	rc = stat( bdb->bi_dbenv_home, &stat1 );
-	if( rc != 0 ) {
-		Debug( LDAP_DEBUG_ANY,
-			LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
-			"cannot access database directory \"%s\" (%d).\n",
-			be->be_suffix[0].bv_val, bdb->bi_dbenv_home, errno );
-		return -1;
-	}
-
-	/* Perform database use arbitration/recovery logic */
-	alockt = (slapMode & SLAP_TOOL_READONLY) ? ALOCK_LOCKED : ALOCK_UNIQUE;
-	if ( slapMode & SLAP_TOOL_QUICK ) {
-		alockt |= ALOCK_NOSAVE;
-		quick = 1;
-	}
-
-	rc = alock_open( &bdb->bi_alock_info, 
-				"slapd", 
-				bdb->bi_dbenv_home, alockt );
-
-	/* alockt is TRUE if the existing environment was created in Quick mode */
-	alockt = (rc & ALOCK_NOSAVE) ? 1 : 0;
-	rc &= ~ALOCK_NOSAVE;
-
-	if( rc == ALOCK_RECOVER ) {
-		Debug( LDAP_DEBUG_ANY,
-			LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
-			"unclean shutdown detected; attempting recovery.\n", 
-			be->be_suffix[0].bv_val, 0, 0 );
-		do_alock_recover = 1;
-		do_recover = DB_RECOVER;
-	} else if( rc == ALOCK_BUSY ) {
-		Debug( LDAP_DEBUG_ANY,
-			LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
-			"database already in use.\n", 
-			be->be_suffix[0].bv_val, 0, 0 );
-		return -1;
-	} else if( rc != ALOCK_CLEAN ) {
-		Debug( LDAP_DEBUG_ANY,
-			LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
-			"alock package is unstable.\n", 
-			be->be_suffix[0].bv_val, 0, 0 );
-		return -1;
-	}
-	if ( rc == ALOCK_CLEAN )
-		be->be_flags |= SLAP_DBFLAG_CLEAN;
-
-	/*
-	 * The DB_CONFIG file may have changed. If so, recover the
-	 * database so that new settings are put into effect. Also
-	 * note the possible absence of DB_CONFIG in the log.
-	 */
-	if( stat( bdb->bi_db_config_path, &stat1 ) == 0 ) {
-		if ( !do_recover ) {
-			char *ptr = lutil_strcopy(path, bdb->bi_dbenv_home);
-			*ptr++ = LDAP_DIRSEP[0];
-			strcpy( ptr, "__db.001" );
-			if( stat( path, &stat2 ) == 0 ) {
-				if( stat2.st_mtime < stat1.st_mtime ) {
-					Debug( LDAP_DEBUG_ANY,
-						LDAP_XSTRING(bdb_db_open) ": DB_CONFIG for suffix \"%s\" has changed.\n",
-							be->be_suffix[0].bv_val, 0, 0 );
-					if ( quick ) {
-						Debug( LDAP_DEBUG_ANY,
-							"Cannot use Quick mode; perform manual recovery first.\n",
-							0, 0, 0 );
-						slapMode ^= SLAP_TOOL_QUICK;
-						rc = -1;
-						goto fail;
-					} else {
-						Debug( LDAP_DEBUG_ANY,
-							"Performing database recovery to activate new settings.\n",
-							0, 0, 0 );
-					}
-					do_recover = DB_RECOVER;
-				}
-			}
-		}
-	}
-	else {
-		Debug( LDAP_DEBUG_ANY,
-			LDAP_XSTRING(bdb_db_open) ": warning - no DB_CONFIG file found "
-			"in directory %s: (%d).\n"
-			"Expect poor performance for suffix \"%s\".\n",
-			bdb->bi_dbenv_home, errno, be->be_suffix[0].bv_val );
-	}
-
-	/* Always let slapcat run, regardless of environment state.
-	 * This can be used to cause a cache flush after an unclean
-	 * shutdown.
-	 */
-	if ( do_recover && ( slapMode & SLAP_TOOL_READONLY )) {
-		Debug( LDAP_DEBUG_ANY,
-			LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
-			"recovery skipped in read-only mode. "
-			"Run manual recovery if errors are encountered.\n",
-			be->be_suffix[0].bv_val, 0, 0 );
-		do_recover = 0;
-		do_alock_recover = 0;
-		quick = alockt;
-	}
-
-	/* An existing environment in Quick mode has nothing to recover. */
-	if ( alockt && do_recover ) {
-		Debug( LDAP_DEBUG_ANY,
-			LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
-			"cannot recover, database must be reinitialized.\n", 
-			be->be_suffix[0].bv_val, 0, 0 );
-		rc = -1;
-		goto fail;
-	}
-
-	rc = db_env_create( &bdb->bi_dbenv, 0 );
-	if( rc != 0 ) {
-		Debug( LDAP_DEBUG_ANY,
-			LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
-			"db_env_create failed: %s (%d).\n",
-			be->be_suffix[0].bv_val, db_strerror(rc), rc );
-		goto fail;
-	}
-
-#ifdef HAVE_EBCDIC
-	strcpy( path, bdb->bi_dbenv_home );
-	__atoe( path );
-	dbhome = path;
-#else
-	dbhome = bdb->bi_dbenv_home;
-#endif
-
-	/* If existing environment is clean but doesn't support
-	 * currently requested modes, remove it.
-	 */
-	if ( !do_recover && ( alockt ^ quick )) {
-shm_retry:
-		rc = bdb->bi_dbenv->remove( bdb->bi_dbenv, dbhome, DB_FORCE );
-		if ( rc ) {
-			Debug( LDAP_DEBUG_ANY,
-				LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
-				"dbenv remove failed: %s (%d).\n",
-				be->be_suffix[0].bv_val, db_strerror(rc), rc );
-			bdb->bi_dbenv = NULL;
-			goto fail;
-		}
-		rc = db_env_create( &bdb->bi_dbenv, 0 );
-		if( rc != 0 ) {
-			Debug( LDAP_DEBUG_ANY,
-				LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
-				"db_env_create failed: %s (%d).\n",
-				be->be_suffix[0].bv_val, db_strerror(rc), rc );
-			goto fail;
-		}
-	}
-
-	bdb->bi_dbenv->set_errpfx( bdb->bi_dbenv, be->be_suffix[0].bv_val );
-	bdb->bi_dbenv->set_errcall( bdb->bi_dbenv, bdb_errcall );
-
-	bdb->bi_dbenv->set_lk_detect( bdb->bi_dbenv, bdb->bi_lock_detect );
-
-	if ( !BER_BVISNULL( &bdb->bi_db_crypt_key )) {
-		rc = bdb->bi_dbenv->set_encrypt( bdb->bi_dbenv, bdb->bi_db_crypt_key.bv_val,
-			DB_ENCRYPT_AES );
-		if ( rc ) {
-			Debug( LDAP_DEBUG_ANY,
-				LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
-				"dbenv set_encrypt failed: %s (%d).\n",
-				be->be_suffix[0].bv_val, db_strerror(rc), rc );
-			goto fail;
-		}
-	}
-
-	/* One long-lived TXN per thread, two TXNs per write op */
-	bdb->bi_dbenv->set_tx_max( bdb->bi_dbenv, connection_pool_max * 3 );
-
-	if( bdb->bi_dbenv_xflags != 0 ) {
-		rc = bdb->bi_dbenv->set_flags( bdb->bi_dbenv,
-			bdb->bi_dbenv_xflags, 1);
-		if( rc != 0 ) {
-			Debug( LDAP_DEBUG_ANY,
-				LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
-				"dbenv_set_flags failed: %s (%d).\n",
-				be->be_suffix[0].bv_val, db_strerror(rc), rc );
-			goto fail;
-		}
-	}
-
-#define	BDB_TXN_FLAGS	(DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN)
-
-	Debug( LDAP_DEBUG_TRACE,
-		LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
-		"dbenv_open(%s).\n",
-		be->be_suffix[0].bv_val, bdb->bi_dbenv_home, 0);
-
-	flags = DB_INIT_MPOOL | DB_CREATE | DB_THREAD;
-
-	if ( !quick )
-		flags |= BDB_TXN_FLAGS;
-
-	/* If a key was set, use shared memory for the BDB environment */
-	if ( bdb->bi_shm_key ) {
-		bdb->bi_dbenv->set_shm_key( bdb->bi_dbenv, bdb->bi_shm_key );
-		flags |= DB_SYSTEM_MEM;
-	}
-	rc = (bdb->bi_dbenv->open)( bdb->bi_dbenv, dbhome,
-			flags | do_recover, bdb->bi_dbenv_mode );
-
-	if ( rc ) {
-		/* Regular open failed, probably a missing shm environment.
-		 * Start over, do a recovery.
-		 */
-		if ( !do_recover && bdb->bi_shm_key && do_retry ) {
-			bdb->bi_dbenv->close( bdb->bi_dbenv, 0 );
-			rc = db_env_create( &bdb->bi_dbenv, 0 );
-			if( rc == 0 ) {
-				Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open)
-					": database \"%s\": "
-					"shared memory env open failed, assuming stale env.\n",
-					be->be_suffix[0].bv_val, 0, 0 );
-				do_retry = 0;
-				goto shm_retry;
-			}
-		}
-		Debug( LDAP_DEBUG_ANY,
-			LDAP_XSTRING(bdb_db_open) ": database \"%s\" cannot be %s, err %d. "
-			"Restore from backup!\n",
-			be->be_suffix[0].bv_val, do_recover ? "recovered" : "opened", rc );
-		goto fail;
-	}
-
-	if ( do_alock_recover && alock_recover (&bdb->bi_alock_info) != 0 ) {
-		Debug( LDAP_DEBUG_ANY,
-			LDAP_XSTRING(bdb_db_open) ": database \"%s\": alock_recover failed\n",
-			be->be_suffix[0].bv_val, 0, 0 );
-		rc = -1;
-		goto fail;
-	}
-
-#ifdef SLAP_ZONE_ALLOC
-	if ( bdb->bi_cache.c_maxsize ) {
-		bdb->bi_cache.c_zctx = slap_zn_mem_create(
-			SLAP_ZONE_INITSIZE, SLAP_ZONE_MAXSIZE,
-			SLAP_ZONE_DELTA, SLAP_ZONE_SIZE);
-	}
-#endif
-
-	/* dncache defaults to 0 == unlimited
-	 * must be >= entrycache
-	 */
-	if ( bdb->bi_cache.c_eimax && bdb->bi_cache.c_eimax < bdb->bi_cache.c_maxsize ) {
-		bdb->bi_cache.c_eimax = bdb->bi_cache.c_maxsize;
-	}
-
-	if ( bdb->bi_idl_cache_max_size ) {
-		bdb->bi_idl_tree = NULL;
-		bdb->bi_idl_cache_size = 0;
-	}
-
-	flags = DB_THREAD | bdb->bi_db_opflags;
-
-#ifdef DB_AUTO_COMMIT
-	if ( !quick )
-		flags |= DB_AUTO_COMMIT;
-#endif
-
-	bdb->bi_databases = (struct bdb_db_info **) ch_malloc(
-		BDB_INDICES * sizeof(struct bdb_db_info *) );
-
-	/* open (and create) main database */
-	for( i = 0; bdbi_databases[i].name.bv_val; i++ ) {
-		struct bdb_db_info *db;
-
-		db = (struct bdb_db_info *) ch_calloc(1, sizeof(struct bdb_db_info));
-
-		rc = db_create( &db->bdi_db, bdb->bi_dbenv, 0 );
-		if( rc != 0 ) {
-			snprintf(cr->msg, sizeof(cr->msg),
-				"database \"%s\": db_create(%s) failed: %s (%d).",
-				be->be_suffix[0].bv_val, 
-				bdb->bi_dbenv_home, db_strerror(rc), rc );
-			Debug( LDAP_DEBUG_ANY,
-				LDAP_XSTRING(bdb_db_open) ": %s\n",
-				cr->msg, 0, 0 );
-			ch_free( db );
-			goto fail;
-		}
-
-		if( !BER_BVISNULL( &bdb->bi_db_crypt_key )) {
-			rc = db->bdi_db->set_flags( db->bdi_db, DB_ENCRYPT );
-			if ( rc ) {
-				snprintf(cr->msg, sizeof(cr->msg),
-					"database \"%s\": db set_flags(DB_ENCRYPT)(%s) failed: %s (%d).",
-					be->be_suffix[0].bv_val, 
-					bdb->bi_dbenv_home, db_strerror(rc), rc );
-				Debug( LDAP_DEBUG_ANY,
-					LDAP_XSTRING(bdb_db_open) ": %s\n",
-					cr->msg, 0, 0 );
-				db->bdi_db->close( db->bdi_db, 0 );
-				ch_free( db );
-				goto fail;
-			}
-		}
-
-		if( bdb->bi_flags & BDB_CHKSUM ) {
-			rc = db->bdi_db->set_flags( db->bdi_db, DB_CHKSUM );
-			if ( rc ) {
-				snprintf(cr->msg, sizeof(cr->msg),
-					"database \"%s\": db set_flags(DB_CHKSUM)(%s) failed: %s (%d).",
-					be->be_suffix[0].bv_val, 
-					bdb->bi_dbenv_home, db_strerror(rc), rc );
-				Debug( LDAP_DEBUG_ANY,
-					LDAP_XSTRING(bdb_db_open) ": %s\n",
-					cr->msg, 0, 0 );
-				db->bdi_db->close( db->bdi_db, 0 );
-				ch_free( db );
-				goto fail;
-			}
-		}
-
-		rc = bdb_db_findsize( bdb, (struct berval *)&bdbi_databases[i].name );
-
-		if( i == BDB_ID2ENTRY ) {
-			if ( !rc ) rc = BDB_ID2ENTRY_PAGESIZE;
-			rc = db->bdi_db->set_pagesize( db->bdi_db, rc );
-
-			if ( slapMode & SLAP_TOOL_MODE )
-				db->bdi_db->mpf->set_priority( db->bdi_db->mpf,
-					DB_PRIORITY_VERY_LOW );
-
-			if ( slapMode & SLAP_TOOL_READMAIN ) {
-				flags |= DB_RDONLY;
-			} else {
-				flags |= DB_CREATE;
-			}
-		} else {
-			/* Use FS default size if not configured */
-			if ( rc )
-				rc = db->bdi_db->set_pagesize( db->bdi_db, rc );
-
-			rc = db->bdi_db->set_flags( db->bdi_db, 
-				DB_DUP | DB_DUPSORT );
-#ifndef BDB_HIER
-			if ( slapMode & SLAP_TOOL_READONLY ) {
-				flags |= DB_RDONLY;
-			} else {
-				flags |= DB_CREATE;
-			}
-#else
-			rc = db->bdi_db->set_dup_compare( db->bdi_db,
-				bdb_dup_compare );
-			if ( slapMode & (SLAP_TOOL_READONLY|SLAP_TOOL_READMAIN) ) {
-				flags |= DB_RDONLY;
-			} else {
-				flags |= DB_CREATE;
-			}
-#endif
-		}
-
-#ifdef HAVE_EBCDIC
-		strcpy( path, bdbi_databases[i].file );
-		__atoe( path );
-		rc = DB_OPEN( db->bdi_db,
-			path,
-		/*	bdbi_databases[i].name, */ NULL,
-			bdbi_databases[i].type,
-			bdbi_databases[i].flags | flags,
-			bdb->bi_dbenv_mode );
-#else
-		rc = DB_OPEN( db->bdi_db,
-			bdbi_databases[i].file,
-		/*	bdbi_databases[i].name, */ NULL,
-			bdbi_databases[i].type,
-			bdbi_databases[i].flags | flags,
-			bdb->bi_dbenv_mode );
-#endif
-
-		if ( rc != 0 ) {
-			snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": "
-				"db_open(%s/%s) failed: %s (%d).", 
-				be->be_suffix[0].bv_val, 
-				bdb->bi_dbenv_home, bdbi_databases[i].file,
-				db_strerror(rc), rc );
-			Debug( LDAP_DEBUG_ANY,
-				LDAP_XSTRING(bdb_db_open) ": %s\n",
-				cr->msg, 0, 0 );
-			db->bdi_db->close( db->bdi_db, 0 );
-			ch_free( db );
-			goto fail;
-		}
-
-		flags &= ~(DB_CREATE | DB_RDONLY);
-		db->bdi_name = bdbi_databases[i].name;
-		bdb->bi_databases[i] = db;
-	}
-
-	bdb->bi_databases[i] = NULL;
-	bdb->bi_ndatabases = i;
-
-	/* get nextid */
-	rc = bdb_last_id( be, NULL );
-	if( rc != 0 ) {
-		snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": "
-			"last_id(%s) failed: %s (%d).",
-			be->be_suffix[0].bv_val, bdb->bi_dbenv_home,
-			db_strerror(rc), rc );
-		Debug( LDAP_DEBUG_ANY,
-			LDAP_XSTRING(bdb_db_open) ": %s\n",
-			cr->msg, 0, 0 );
-		goto fail;
-	}
-
-	if ( !quick ) {
-		int txflag = DB_READ_COMMITTED;
-		/* avoid deadlocks in server; tools should
-		 * wait since they have no deadlock retry mechanism.
-		 */
-		if ( slapMode & SLAP_SERVER_MODE )
-			txflag |= DB_TXN_NOWAIT;
-		TXN_BEGIN(bdb->bi_dbenv, NULL, &bdb->bi_cache.c_txn, txflag);
-	}
-
-	entry_prealloc( bdb->bi_cache.c_maxsize );
-	attr_prealloc( bdb->bi_cache.c_maxsize * 20 );
-
-	/* setup for empty-DN contexts */
-	if ( BER_BVISEMPTY( &be->be_nsuffix[0] )) {
-		rc = bdb_id2entry( be, NULL, 0, &e );
-	}
-	if ( !e ) {
-		struct berval gluebv = BER_BVC("glue");
-		Operation op = {0};
-		Opheader ohdr = {0};
-		e = entry_alloc();
-		e->e_id = 0;
-		ber_dupbv( &e->e_name, (struct berval *)&slap_empty_bv );
-		ber_dupbv( &e->e_nname, (struct berval *)&slap_empty_bv );
-		attr_merge_one( e, slap_schema.si_ad_objectClass,
-			&gluebv, NULL );
-		attr_merge_one( e, slap_schema.si_ad_structuralObjectClass,
-			&gluebv, NULL );
-		op.o_hdr = &ohdr;
-		op.o_bd = be;
-		op.ora_e = e;
-		op.o_dn = be->be_rootdn;
-		op.o_ndn = be->be_rootndn;
-		slap_add_opattrs( &op, NULL, NULL, 0, 0 );
-	}
-	e->e_ocflags = SLAP_OC_GLUE|SLAP_OC__END;
-	e->e_private = &bdb->bi_cache.c_dntree;
-	bdb->bi_cache.c_dntree.bei_e = e;
-
-	/* monitor setup */
-	rc = bdb_monitor_db_open( be );
-	if ( rc != 0 ) {
-		goto fail;
-	}
-
-	bdb->bi_flags |= BDB_IS_OPEN;
-
-	return 0;
-
-fail:
-	bdb_db_close( be, NULL );
-	return rc;
-}
-
-static int
-bdb_db_close( BackendDB *be, ConfigReply *cr )
-{
-	int rc;
-	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
-	struct bdb_db_info *db;
-	bdb_idl_cache_entry_t *entry, *next_entry;
-
-	/* monitor handling */
-	(void)bdb_monitor_db_close( be );
-
-	{
-		Entry *e = bdb->bi_cache.c_dntree.bei_e;
-		if ( e ) {
-			bdb->bi_cache.c_dntree.bei_e = NULL;
-			e->e_private = NULL;
-			bdb_entry_return( e );
-		}
-	}
-
-	bdb->bi_flags &= ~BDB_IS_OPEN;
-
-	ber_bvarray_free( bdb->bi_db_config );
-	bdb->bi_db_config = NULL;
-
-	if( bdb->bi_dbenv ) {
-		/* Free cache locker if we enabled locking.
-		 * TXNs must all be closed before DBs...
-		 */
-		if ( !( slapMode & SLAP_TOOL_QUICK ) && bdb->bi_cache.c_txn ) {
-			TXN_ABORT( bdb->bi_cache.c_txn );
-			bdb->bi_cache.c_txn = NULL;
-		}
-		bdb_reader_flush( bdb->bi_dbenv );
-	}
-
-	while( bdb->bi_databases && bdb->bi_ndatabases-- ) {
-		db = bdb->bi_databases[bdb->bi_ndatabases];
-		rc = db->bdi_db->close( db->bdi_db, 0 );
-		/* Lower numbered names are not strdup'd */
-		if( bdb->bi_ndatabases >= BDB_NDB )
-			free( db->bdi_name.bv_val );
-		free( db );
-	}
-	free( bdb->bi_databases );
-	bdb->bi_databases = NULL;
-
-	bdb_cache_release_all (&bdb->bi_cache);
-
-	if ( bdb->bi_idl_cache_size ) {
-		avl_free( bdb->bi_idl_tree, NULL );
-		bdb->bi_idl_tree = NULL;
-		entry = bdb->bi_idl_lru_head;
-		do {
-			next_entry = entry->idl_lru_next;
-			if ( entry->idl )
-				free( entry->idl );
-			free( entry->kstr.bv_val );
-			free( entry );
-			entry = next_entry;
-		} while ( entry != bdb->bi_idl_lru_head );
-		bdb->bi_idl_lru_head = bdb->bi_idl_lru_tail = NULL;
-	}
-
-	/* close db environment */
-	if( bdb->bi_dbenv ) {
-		/* force a checkpoint, but not if we were ReadOnly,
-		 * and not in Quick mode since there are no transactions there.
-		 */
-		if ( !( slapMode & ( SLAP_TOOL_QUICK|SLAP_TOOL_READONLY ))) {
-			rc = TXN_CHECKPOINT( bdb->bi_dbenv, 0, 0, DB_FORCE );
-			if( rc != 0 ) {
-				Debug( LDAP_DEBUG_ANY,
-					"bdb_db_close: database \"%s\": "
-					"txn_checkpoint failed: %s (%d).\n",
-					be->be_suffix[0].bv_val, db_strerror(rc), rc );
-			}
-		}
-
-		rc = bdb->bi_dbenv->close( bdb->bi_dbenv, 0 );
-		bdb->bi_dbenv = NULL;
-		if( rc != 0 ) {
-			Debug( LDAP_DEBUG_ANY,
-				"bdb_db_close: database \"%s\": "
-				"close failed: %s (%d)\n",
-				be->be_suffix[0].bv_val, db_strerror(rc), rc );
-			return rc;
-		}
-	}
-
-	rc = alock_close( &bdb->bi_alock_info, slapMode & SLAP_TOOL_QUICK );
-	if( rc != 0 ) {
-		Debug( LDAP_DEBUG_ANY,
-			"bdb_db_close: database \"%s\": alock_close failed\n",
-			be->be_suffix[0].bv_val, 0, 0 );
-		return -1;
-	}
-
-	return 0;
-}
-
-static int
-bdb_db_destroy( BackendDB *be, ConfigReply *cr )
-{
-	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
-
-	/* stop and remove checkpoint task */
-	if ( bdb->bi_txn_cp_task ) {
-		struct re_s *re = bdb->bi_txn_cp_task;
-		bdb->bi_txn_cp_task = NULL;
-		ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
-		if ( ldap_pvt_runqueue_isrunning( &slapd_rq, re ) )
-			ldap_pvt_runqueue_stoptask( &slapd_rq, re );
-		ldap_pvt_runqueue_remove( &slapd_rq, re );
-		ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
-	}
-
-	/* monitor handling */
-	(void)bdb_monitor_db_destroy( be );
-
-	if( bdb->bi_dbenv_home ) ch_free( bdb->bi_dbenv_home );
-	if( bdb->bi_db_config_path ) ch_free( bdb->bi_db_config_path );
-
-	bdb_attr_index_destroy( bdb );
-
-	ldap_pvt_thread_rdwr_destroy ( &bdb->bi_cache.c_rwlock );
-	ldap_pvt_thread_mutex_destroy( &bdb->bi_cache.c_lru_mutex );
-	ldap_pvt_thread_mutex_destroy( &bdb->bi_cache.c_count_mutex );
-	ldap_pvt_thread_mutex_destroy( &bdb->bi_cache.c_eifree_mutex );
-	ldap_pvt_thread_mutex_destroy( &bdb->bi_cache.c_dntree.bei_kids_mutex );
-#ifdef BDB_HIER
-	ldap_pvt_thread_mutex_destroy( &bdb->bi_modrdns_mutex );
-#endif
-	ldap_pvt_thread_mutex_destroy( &bdb->bi_lastid_mutex );
-	ldap_pvt_thread_mutex_destroy( &bdb->bi_database_mutex );
-	ldap_pvt_thread_rdwr_destroy( &bdb->bi_idl_tree_rwlock );
-	ldap_pvt_thread_mutex_destroy( &bdb->bi_idl_tree_lrulock );
-
-	ch_free( bdb );
-	be->be_private = NULL;
-
-	return 0;
-}
-
-int
-bdb_back_initialize(
-	BackendInfo	*bi )
-{
-	int rc;
-
-	static char *controls[] = {
-		LDAP_CONTROL_ASSERT,
-		LDAP_CONTROL_MANAGEDSAIT,
-		LDAP_CONTROL_NOOP,
-		LDAP_CONTROL_PAGEDRESULTS,
-		LDAP_CONTROL_PRE_READ,
-		LDAP_CONTROL_POST_READ,
-		LDAP_CONTROL_SUBENTRIES,
-		LDAP_CONTROL_X_PERMISSIVE_MODIFY,
-#ifdef LDAP_X_TXN
-		LDAP_CONTROL_X_TXN_SPEC,
-#endif
-		NULL
-	};
-
-	/* initialize the underlying database system */
-	Debug( LDAP_DEBUG_TRACE,
-		LDAP_XSTRING(bdb_back_initialize) ": initialize " 
-		BDB_UCTYPE " backend\n", 0, 0, 0 );
-
-	bi->bi_flags |=
-		SLAP_BFLAG_INCREMENT |
-		SLAP_BFLAG_SUBENTRIES |
-		SLAP_BFLAG_ALIASES |
-		SLAP_BFLAG_REFERRALS;
-
-	bi->bi_controls = controls;
-
-	{	/* version check */
-		int major, minor, patch, ver;
-		char *version = db_version( &major, &minor, &patch );
-#ifdef HAVE_EBCDIC
-		char v2[1024];
-
-		/* All our stdio does an ASCII to EBCDIC conversion on
-		 * the output. Strings from the BDB library are already
-		 * in EBCDIC; we have to go back and forth...
-		 */
-		strcpy( v2, version );
-		__etoa( v2 );
-		version = v2;
-#endif
-
-		ver = (major << 24) | (minor << 16) | patch;
-		if( ver != DB_VERSION_FULL ) {
-			/* fail if a versions don't match */
-			Debug( LDAP_DEBUG_ANY,
-				LDAP_XSTRING(bdb_back_initialize) ": "
-				"BDB library version mismatch:"
-				" expected " DB_VERSION_STRING ","
-				" got %s\n", version, 0, 0 );
-			return -1;
-		}
-
-		Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_back_initialize)
-			": %s\n", version, 0, 0 );
-	}
-
-	db_env_set_func_free( ber_memfree );
-	db_env_set_func_malloc( (db_malloc *)ber_memalloc );
-	db_env_set_func_realloc( (db_realloc *)ber_memrealloc );
-#if !defined(NO_THREAD) && DB_VERSION_FULL <= 0x04070000
-	/* This is a no-op on a NO_THREAD build. Leave the default
-	 * alone so that BDB will sleep on interprocess conflicts.
-	 * Don't bother on BDB 4.7...
-	 */
-	db_env_set_func_yield( ldap_pvt_thread_yield );
-#endif
-
-	bi->bi_open = 0;
-	bi->bi_close = 0;
-	bi->bi_config = 0;
-	bi->bi_destroy = 0;
-
-	bi->bi_db_init = bdb_db_init;
-	bi->bi_db_config = config_generic_wrapper;
-	bi->bi_db_open = bdb_db_open;
-	bi->bi_db_close = bdb_db_close;
-	bi->bi_db_destroy = bdb_db_destroy;
-
-	bi->bi_op_add = bdb_add;
-	bi->bi_op_bind = bdb_bind;
-	bi->bi_op_compare = bdb_compare;
-	bi->bi_op_delete = bdb_delete;
-	bi->bi_op_modify = bdb_modify;
-	bi->bi_op_modrdn = bdb_modrdn;
-	bi->bi_op_search = bdb_search;
-
-	bi->bi_op_unbind = 0;
-
-	bi->bi_extended = bdb_extended;
-
-	bi->bi_chk_referrals = bdb_referrals;
-	bi->bi_operational = bdb_operational;
-	bi->bi_has_subordinates = bdb_hasSubordinates;
-	bi->bi_entry_release_rw = bdb_entry_release;
-	bi->bi_entry_get_rw = bdb_entry_get;
-
-	/*
-	 * hooks for slap tools
-	 */
-	bi->bi_tool_entry_open = bdb_tool_entry_open;
-	bi->bi_tool_entry_close = bdb_tool_entry_close;
-	bi->bi_tool_entry_first = backend_tool_entry_first;
-	bi->bi_tool_entry_first_x = bdb_tool_entry_first_x;
-	bi->bi_tool_entry_next = bdb_tool_entry_next;
-	bi->bi_tool_entry_get = bdb_tool_entry_get;
-	bi->bi_tool_entry_put = bdb_tool_entry_put;
-	bi->bi_tool_entry_reindex = bdb_tool_entry_reindex;
-	bi->bi_tool_sync = 0;
-	bi->bi_tool_dn2id_get = bdb_tool_dn2id_get;
-	bi->bi_tool_entry_modify = bdb_tool_entry_modify;
-
-	bi->bi_connection_init = 0;
-	bi->bi_connection_destroy = 0;
-
-	rc = bdb_back_init_cf( bi );
-
-	return rc;
-}
-
-#if	(SLAPD_BDB == SLAPD_MOD_DYNAMIC && !defined(BDB_HIER)) || \
-	(SLAPD_HDB == SLAPD_MOD_DYNAMIC && defined(BDB_HIER))
-
-/* conditionally define the init_module() function */
-#ifdef BDB_HIER
-SLAP_BACKEND_INIT_MODULE( hdb )
-#else /* !BDB_HIER */
-SLAP_BACKEND_INIT_MODULE( bdb )
-#endif /* !BDB_HIER */
-
-#endif /* SLAPD_[BH]DB == SLAPD_MOD_DYNAMIC */
-
diff --git a/servers/slapd/back-bdb/key.c b/servers/slapd/back-bdb/key.c
deleted file mode 100644
index 417ad70..0000000
--- a/servers/slapd/back-bdb/key.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/* index.c - routines for dealing with attribute indexes */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/string.h>
-#include <ac/socket.h>
-
-#include "slap.h"
-#include "back-bdb.h"
-#include "idl.h"
-
-/* read a key */
-int
-bdb_key_read(
-	Backend	*be,
-	DB *db,
-	DB_TXN *txn,
-	struct berval *k,
-	ID *ids,
-	DBC **saved_cursor,
-	int get_flag
-)
-{
-	int rc;
-	DBT key;
-
-	Debug( LDAP_DEBUG_TRACE, "=> key_read\n", 0, 0, 0 );
-
-	DBTzero( &key );
-	bv2DBT(k,&key);
-	key.ulen = key.size;
-	key.flags = DB_DBT_USERMEM;
-
-	rc = bdb_idl_fetch_key( be, db, txn, &key, ids, saved_cursor, get_flag );
-
-	if( rc != LDAP_SUCCESS ) {
-		Debug( LDAP_DEBUG_TRACE, "<= bdb_index_read: failed (%d)\n",
-			rc, 0, 0 );
-	} else {
-		Debug( LDAP_DEBUG_TRACE, "<= bdb_index_read %ld candidates\n",
-			(long) BDB_IDL_N(ids), 0, 0 );
-	}
-
-	return rc;
-}
-
-/* Add or remove stuff from index files */
-int
-bdb_key_change(
-	Backend *be,
-	DB *db,
-	DB_TXN *txn,
-	struct berval *k,
-	ID id,
-	int op
-)
-{
-	int	rc;
-	DBT	key;
-
-	Debug( LDAP_DEBUG_TRACE, "=> key_change(%s,%lx)\n",
-		op == SLAP_INDEX_ADD_OP ? "ADD":"DELETE", (long) id, 0 );
-
-	DBTzero( &key );
-	bv2DBT(k,&key);
-	key.ulen = key.size;
-	key.flags = DB_DBT_USERMEM;
-
-	if (op == SLAP_INDEX_ADD_OP) {
-		/* Add values */
-
-#ifdef BDB_TOOL_IDL_CACHING
-		if ( slapMode & SLAP_TOOL_QUICK )
-			rc = bdb_tool_idl_add( be, db, txn, &key, id );
-		else
-#endif
-			rc = bdb_idl_insert_key( be, db, txn, &key, id );
-		if ( rc == DB_KEYEXIST ) rc = 0;
-	} else {
-		/* Delete values */
-		rc = bdb_idl_delete_key( be, db, txn, &key, id );
-		if ( rc == DB_NOTFOUND ) rc = 0;
-	}
-
-	Debug( LDAP_DEBUG_TRACE, "<= key_change %d\n", rc, 0, 0 );
-
-	return rc;
-}
diff --git a/servers/slapd/back-bdb/modify.c b/servers/slapd/back-bdb/modify.c
deleted file mode 100644
index fb7dbe3..0000000
--- a/servers/slapd/back-bdb/modify.c
+++ /dev/null
@@ -1,835 +0,0 @@
-/* modify.c - bdb backend modify routine */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-#include <ac/time.h>
-
-#include "back-bdb.h"
-
-static struct berval scbva[] = {
-	BER_BVC("glue"),
-	BER_BVNULL
-};
-
-static void
-bdb_modify_idxflags(
-	Operation *op,
-	AttributeDescription *desc,
-	int got_delete,
-	Attribute *newattrs,
-	Attribute *oldattrs )
-{
-	struct berval	ix_at;
-	AttrInfo	*ai;
-
-	/* check if modified attribute was indexed
-	 * but not in case of NOOP... */
-	ai = bdb_index_mask( op->o_bd, desc, &ix_at );
-	if ( ai ) {
-		if ( got_delete ) {
-			Attribute 	*ap;
-			struct berval	ix2;
-
-			ap = attr_find( oldattrs, desc );
-			if ( ap ) ap->a_flags |= SLAP_ATTR_IXDEL;
-
-			/* Find all other attrs that index to same slot */
-			for ( ap = newattrs; ap; ap = ap->a_next ) {
-				ai = bdb_index_mask( op->o_bd, ap->a_desc, &ix2 );
-				if ( ai && ix2.bv_val == ix_at.bv_val )
-					ap->a_flags |= SLAP_ATTR_IXADD;
-			}
-
-		} else {
-			Attribute 	*ap;
-
-			ap = attr_find( newattrs, desc );
-			if ( ap ) ap->a_flags |= SLAP_ATTR_IXADD;
-		}
-	}
-}
-
-int bdb_modify_internal(
-	Operation *op,
-	DB_TXN *tid,
-	Modifications *modlist,
-	Entry *e,
-	const char **text,
-	char *textbuf,
-	size_t textlen )
-{
-	int rc, err;
-	Modification	*mod;
-	Modifications	*ml;
-	Attribute	*save_attrs;
-	Attribute 	*ap;
-	int			glue_attr_delete = 0;
-	int			got_delete;
-
-	Debug( LDAP_DEBUG_TRACE, "bdb_modify_internal: 0x%08lx: %s\n",
-		e->e_id, e->e_dn, 0);
-
-	if ( !acl_check_modlist( op, e, modlist )) {
-		return LDAP_INSUFFICIENT_ACCESS;
-	}
-
-	/* save_attrs will be disposed of by bdb_cache_modify */
-	save_attrs = e->e_attrs;
-	e->e_attrs = attrs_dup( e->e_attrs );
-
-	for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
-		int match;
-		mod = &ml->sml_mod;
-		switch( mod->sm_op ) {
-		case LDAP_MOD_ADD:
-		case LDAP_MOD_REPLACE:
-			if ( mod->sm_desc == slap_schema.si_ad_structuralObjectClass ) {
-				value_match( &match, slap_schema.si_ad_structuralObjectClass,
-					slap_schema.si_ad_structuralObjectClass->
-						ad_type->sat_equality,
-					SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
-					&mod->sm_values[0], &scbva[0], text );
-				if ( !match ) glue_attr_delete = 1;
-			}
-		}
-		if ( glue_attr_delete )
-			break;
-	}
-
-	if ( glue_attr_delete ) {
-		Attribute	**app = &e->e_attrs;
-		while ( *app != NULL ) {
-			if ( !is_at_operational( (*app)->a_desc->ad_type )) {
-				Attribute *save = *app;
-				*app = (*app)->a_next;
-				attr_free( save );
-				continue;
-			}
-			app = &(*app)->a_next;
-		}
-	}
-
-	for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
-		mod = &ml->sml_mod;
-		got_delete = 0;
-
-		switch ( mod->sm_op ) {
-		case LDAP_MOD_ADD:
-			Debug(LDAP_DEBUG_ARGS,
-				"bdb_modify_internal: add %s\n",
-				mod->sm_desc->ad_cname.bv_val, 0, 0);
-			err = modify_add_values( e, mod, get_permissiveModify(op),
-				text, textbuf, textlen );
-			if( err != LDAP_SUCCESS ) {
-				Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
-					err, *text, 0);
-			}
-			break;
-
-		case LDAP_MOD_DELETE:
-			if ( glue_attr_delete ) {
-				err = LDAP_SUCCESS;
-				break;
-			}
-
-			Debug(LDAP_DEBUG_ARGS,
-				"bdb_modify_internal: delete %s\n",
-				mod->sm_desc->ad_cname.bv_val, 0, 0);
-			err = modify_delete_values( e, mod, get_permissiveModify(op),
-				text, textbuf, textlen );
-			if( err != LDAP_SUCCESS ) {
-				Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
-					err, *text, 0);
-			} else {
-				got_delete = 1;
-			}
-			break;
-
-		case LDAP_MOD_REPLACE:
-			Debug(LDAP_DEBUG_ARGS,
-				"bdb_modify_internal: replace %s\n",
-				mod->sm_desc->ad_cname.bv_val, 0, 0);
-			err = modify_replace_values( e, mod, get_permissiveModify(op),
-				text, textbuf, textlen );
-			if( err != LDAP_SUCCESS ) {
-				Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
-					err, *text, 0);
-			} else {
-				got_delete = 1;
-			}
-			break;
-
-		case LDAP_MOD_INCREMENT:
-			Debug(LDAP_DEBUG_ARGS,
-				"bdb_modify_internal: increment %s\n",
-				mod->sm_desc->ad_cname.bv_val, 0, 0);
-			err = modify_increment_values( e, mod, get_permissiveModify(op),
-				text, textbuf, textlen );
-			if( err != LDAP_SUCCESS ) {
-				Debug(LDAP_DEBUG_ARGS,
-					"bdb_modify_internal: %d %s\n",
-					err, *text, 0);
-			} else {
-				got_delete = 1;
-			}
-			break;
-
-		case SLAP_MOD_SOFTADD:
-			Debug(LDAP_DEBUG_ARGS,
-				"bdb_modify_internal: softadd %s\n",
-				mod->sm_desc->ad_cname.bv_val, 0, 0);
- 			/* Avoid problems in index_add_mods()
- 			 * We need to add index if necessary.
- 			 */
- 			mod->sm_op = LDAP_MOD_ADD;
-
-			err = modify_add_values( e, mod, get_permissiveModify(op),
-				text, textbuf, textlen );
-
- 			mod->sm_op = SLAP_MOD_SOFTADD;
-
- 			if ( err == LDAP_TYPE_OR_VALUE_EXISTS ) {
- 				err = LDAP_SUCCESS;
- 			}
-
-			if( err != LDAP_SUCCESS ) {
-				Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
-					err, *text, 0);
-			}
- 			break;
-
-		case SLAP_MOD_SOFTDEL:
-			Debug(LDAP_DEBUG_ARGS,
-				"bdb_modify_internal: softdel %s\n",
-				mod->sm_desc->ad_cname.bv_val, 0, 0);
- 			/* Avoid problems in index_delete_mods()
- 			 * We need to add index if necessary.
- 			 */
- 			mod->sm_op = LDAP_MOD_DELETE;
-
-			err = modify_delete_values( e, mod, get_permissiveModify(op),
-				text, textbuf, textlen );
-
- 			mod->sm_op = SLAP_MOD_SOFTDEL;
-
-			if ( err == LDAP_SUCCESS ) {
-				got_delete = 1;
-			} else if ( err == LDAP_NO_SUCH_ATTRIBUTE ) {
- 				err = LDAP_SUCCESS;
- 			}
-
-			if( err != LDAP_SUCCESS ) {
-				Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
-					err, *text, 0);
-			}
- 			break;
-
-		case SLAP_MOD_ADD_IF_NOT_PRESENT:
-			if ( attr_find( e->e_attrs, mod->sm_desc ) != NULL ) {
-				/* skip */
-				err = LDAP_SUCCESS;
-				break;
-			}
-
-			Debug(LDAP_DEBUG_ARGS,
-				"bdb_modify_internal: add_if_not_present %s\n",
-				mod->sm_desc->ad_cname.bv_val, 0, 0);
- 			/* Avoid problems in index_add_mods()
- 			 * We need to add index if necessary.
- 			 */
- 			mod->sm_op = LDAP_MOD_ADD;
-
-			err = modify_add_values( e, mod, get_permissiveModify(op),
-				text, textbuf, textlen );
-
- 			mod->sm_op = SLAP_MOD_ADD_IF_NOT_PRESENT;
-
-			if( err != LDAP_SUCCESS ) {
-				Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
-					err, *text, 0);
-			}
- 			break;
-
-		default:
-			Debug(LDAP_DEBUG_ANY, "bdb_modify_internal: invalid op %d\n",
-				mod->sm_op, 0, 0);
-			*text = "Invalid modify operation";
-			err = LDAP_OTHER;
-			Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
-				err, *text, 0);
-		}
-
-		if ( err != LDAP_SUCCESS ) {
-			attrs_free( e->e_attrs );
-			e->e_attrs = save_attrs;
-			/* unlock entry, delete from cache */
-			return err; 
-		}
-
-		/* If objectClass was modified, reset the flags */
-		if ( mod->sm_desc == slap_schema.si_ad_objectClass ) {
-			e->e_ocflags = 0;
-		}
-
-		if ( glue_attr_delete ) e->e_ocflags = 0;
-
-
-		/* check if modified attribute was indexed
-		 * but not in case of NOOP... */
-		if ( !op->o_noop ) {
-			bdb_modify_idxflags( op, mod->sm_desc, got_delete, e->e_attrs, save_attrs );
-		}
-	}
-
-	/* check that the entry still obeys the schema */
-	ap = NULL;
-	rc = entry_schema_check( op, e, save_attrs, get_relax(op), 0, &ap,
-		text, textbuf, textlen );
-	if ( rc != LDAP_SUCCESS || op->o_noop ) {
-		attrs_free( e->e_attrs );
-		/* clear the indexing flags */
-		for ( ap = save_attrs; ap != NULL; ap = ap->a_next ) {
-			ap->a_flags &= ~(SLAP_ATTR_IXADD|SLAP_ATTR_IXDEL);
-		}
-		e->e_attrs = save_attrs;
-
-		if ( rc != LDAP_SUCCESS ) {
-			Debug( LDAP_DEBUG_ANY,
-				"entry failed schema check: %s\n",
-				*text, 0, 0 );
-		}
-
-		/* if NOOP then silently revert to saved attrs */
-		return rc;
-	}
-
-	/* structuralObjectClass modified! */
-	if ( ap ) {
-		assert( ap->a_desc == slap_schema.si_ad_structuralObjectClass );
-		if ( !op->o_noop ) {
-			bdb_modify_idxflags( op, slap_schema.si_ad_structuralObjectClass,
-				1, e->e_attrs, save_attrs );
-		}
-	}
-
-	/* update the indices of the modified attributes */
-
-	/* start with deleting the old index entries */
-	for ( ap = save_attrs; ap != NULL; ap = ap->a_next ) {
-		if ( ap->a_flags & SLAP_ATTR_IXDEL ) {
-			struct berval *vals;
-			Attribute *a2;
-			ap->a_flags &= ~SLAP_ATTR_IXDEL;
-			a2 = attr_find( e->e_attrs, ap->a_desc );
-			if ( a2 ) {
-				/* need to detect which values were deleted */
-				int i, j;
-				/* let add know there were deletes */
-				if ( a2->a_flags & SLAP_ATTR_IXADD )
-					a2->a_flags |= SLAP_ATTR_IXDEL;
-				vals = op->o_tmpalloc( (ap->a_numvals + 1) *
-					sizeof(struct berval), op->o_tmpmemctx );
-				j = 0;
-				for ( i=0; i < ap->a_numvals; i++ ) {
-					rc = attr_valfind( a2, SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
-						&ap->a_nvals[i], NULL, op->o_tmpmemctx );
-					/* Save deleted values */
-					if ( rc == LDAP_NO_SUCH_ATTRIBUTE )
-						vals[j++] = ap->a_nvals[i];
-				}
-				BER_BVZERO(vals+j);
-			} else {
-				/* attribute was completely deleted */
-				vals = ap->a_nvals;
-			}
-			rc = 0;
-			if ( !BER_BVISNULL( vals )) {
-				rc = bdb_index_values( op, tid, ap->a_desc,
-					vals, e->e_id, SLAP_INDEX_DELETE_OP );
-				if ( rc != LDAP_SUCCESS ) {
-					Debug( LDAP_DEBUG_ANY,
-						"%s: attribute \"%s\" index delete failure\n",
-						op->o_log_prefix, ap->a_desc->ad_cname.bv_val, 0 );
-					attrs_free( e->e_attrs );
-					e->e_attrs = save_attrs;
-				}
-			}
-			if ( vals != ap->a_nvals )
-				op->o_tmpfree( vals, op->o_tmpmemctx );
-			if ( rc ) return rc;
-		}
-	}
-
-	/* add the new index entries */
-	for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) {
-		if (ap->a_flags & SLAP_ATTR_IXADD) {
-			ap->a_flags &= ~SLAP_ATTR_IXADD;
-			if ( ap->a_flags & SLAP_ATTR_IXDEL ) {
-				/* if any values were deleted, we must readd index
-				 * for all remaining values.
-				 */
-				ap->a_flags &= ~SLAP_ATTR_IXDEL;
-				rc = bdb_index_values( op, tid, ap->a_desc,
-					ap->a_nvals,
-					e->e_id, SLAP_INDEX_ADD_OP );
-			} else {
-				int found = 0;
-				/* if this was only an add, we only need to index
-				 * the added values.
-				 */
-				for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
-					struct berval *vals;
-					if ( ml->sml_desc != ap->a_desc || !ml->sml_numvals )
-						continue;
-					found = 1;
-					switch( ml->sml_op ) {
-					case LDAP_MOD_ADD:
-					case LDAP_MOD_REPLACE:
-					case LDAP_MOD_INCREMENT:
-					case SLAP_MOD_SOFTADD:
-					case SLAP_MOD_ADD_IF_NOT_PRESENT:
-						if ( ml->sml_op == LDAP_MOD_INCREMENT )
-							vals = ap->a_nvals;
-						else if ( ml->sml_nvalues )
-							vals = ml->sml_nvalues;
-						else
-							vals = ml->sml_values;
-						rc = bdb_index_values( op, tid, ap->a_desc,
-							vals, e->e_id, SLAP_INDEX_ADD_OP );
-						break;
-					}
-					if ( rc )
-						break;
-				}
-				/* This attr was affected by a modify of a subtype, so
-				 * there was no direct match in the modlist. Just readd
-				 * all of its values.
-				 */
-				if ( !found ) {
-					rc = bdb_index_values( op, tid, ap->a_desc,
-						ap->a_nvals,
-						e->e_id, SLAP_INDEX_ADD_OP );
-				}
-			}
-			if ( rc != LDAP_SUCCESS ) {
-				Debug( LDAP_DEBUG_ANY,
-				       "%s: attribute \"%s\" index add failure\n",
-					op->o_log_prefix, ap->a_desc->ad_cname.bv_val, 0 );
-				attrs_free( e->e_attrs );
-				e->e_attrs = save_attrs;
-				return rc;
-			}
-		}
-	}
-
-	return rc;
-}
-
-
-int
-bdb_modify( Operation *op, SlapReply *rs )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	Entry		*e = NULL;
-	EntryInfo	*ei = NULL;
-	int		manageDSAit = get_manageDSAit( op );
-	char textbuf[SLAP_TEXT_BUFLEN];
-	size_t textlen = sizeof textbuf;
-	DB_TXN	*ltid = NULL, *lt2;
-	struct bdb_op_info opinfo = {{{ 0 }}};
-	Entry		dummy = {0};
-
-	DB_LOCK		lock;
-
-	int		num_retries = 0;
-
-	LDAPControl **preread_ctrl = NULL;
-	LDAPControl **postread_ctrl = NULL;
-	LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
-	int num_ctrls = 0;
-
-	int rc;
-
-#ifdef LDAP_X_TXN
-	int settle = 0;
-#endif
-
-	Debug( LDAP_DEBUG_ARGS, LDAP_XSTRING(bdb_modify) ": %s\n",
-		op->o_req_dn.bv_val, 0, 0 );
-
-#ifdef LDAP_X_TXN
-	if( op->o_txnSpec ) {
-		/* acquire connection lock */
-		ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
-		if( op->o_conn->c_txn == CONN_TXN_INACTIVE ) {
-			rs->sr_text = "invalid transaction identifier";
-			rs->sr_err = LDAP_X_TXN_ID_INVALID;
-			goto txnReturn;
-		} else if( op->o_conn->c_txn == CONN_TXN_SETTLE ) {
-			settle=1;
-			goto txnReturn;
-		}
-
-		if( op->o_conn->c_txn_backend == NULL ) {
-			op->o_conn->c_txn_backend = op->o_bd;
-
-		} else if( op->o_conn->c_txn_backend != op->o_bd ) {
-			rs->sr_text = "transaction cannot span multiple database contexts";
-			rs->sr_err = LDAP_AFFECTS_MULTIPLE_DSAS;
-			goto txnReturn;
-		}
-
-		/* insert operation into transaction */
-
-		rs->sr_text = "transaction specified";
-		rs->sr_err = LDAP_X_TXN_SPECIFY_OKAY;
-
-txnReturn:
-		/* release connection lock */
-		ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
-
-		if( !settle ) {
-			send_ldap_result( op, rs );
-			return rs->sr_err;
-		}
-	}
-#endif
-
-	ctrls[num_ctrls] = NULL;
-
-	/* Don't touch the opattrs, if this is a contextCSN update
-	 * initiated from updatedn */
-	if ( !be_isupdate(op) || !op->orm_modlist || op->orm_modlist->sml_next ||
-		 op->orm_modlist->sml_desc != slap_schema.si_ad_contextCSN ) {
-
-		slap_mods_opattrs( op, &op->orm_modlist, 1 );
-	}
-
-	if( 0 ) {
-retry:	/* transaction retry */
-		if ( dummy.e_attrs ) {
-			attrs_free( dummy.e_attrs );
-			dummy.e_attrs = NULL;
-		}
-		if( e != NULL ) {
-			bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
-			e = NULL;
-		}
-		Debug(LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_modify) ": retrying...\n", 0, 0, 0);
-
-		rs->sr_err = TXN_ABORT( ltid );
-		ltid = NULL;
-		LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
-		opinfo.boi_oe.oe_key = NULL;
-		op->o_do_not_cache = opinfo.boi_acl_cache;
-		if( rs->sr_err != 0 ) {
-			rs->sr_err = LDAP_OTHER;
-			rs->sr_text = "internal error";
-			goto return_results;
-		}
-		if ( op->o_abandon ) {
-			rs->sr_err = SLAPD_ABANDON;
-			goto return_results;
-		}
-		bdb_trans_backoff( ++num_retries );
-	}
-
-	/* begin transaction */
-	rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, NULL, &ltid, 
-		bdb->bi_db_opflags );
-	rs->sr_text = NULL;
-	if( rs->sr_err != 0 ) {
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_modify) ": txn_begin failed: "
-			"%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
-		rs->sr_err = LDAP_OTHER;
-		rs->sr_text = "internal error";
-		goto return_results;
-	}
-	Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modify) ": txn1 id: %x\n",
-		ltid->id(ltid), 0, 0 );
-
-	opinfo.boi_oe.oe_key = bdb;
-	opinfo.boi_txn = ltid;
-	opinfo.boi_err = 0;
-	opinfo.boi_acl_cache = op->o_do_not_cache;
-	LDAP_SLIST_INSERT_HEAD( &op->o_extra, &opinfo.boi_oe, oe_next );
-
-	/* get entry or ancestor */
-	rs->sr_err = bdb_dn2entry( op, ltid, &op->o_req_ndn, &ei, 1,
-		&lock );
-
-	if ( rs->sr_err != 0 ) {
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_modify) ": dn2entry failed (%d)\n",
-			rs->sr_err, 0, 0 );
-		switch( rs->sr_err ) {
-		case DB_LOCK_DEADLOCK:
-		case DB_LOCK_NOTGRANTED:
-			goto retry;
-		case DB_NOTFOUND:
-			break;
-		case LDAP_BUSY:
-			rs->sr_text = "ldap server busy";
-			goto return_results;
-		default:
-			rs->sr_err = LDAP_OTHER;
-			rs->sr_text = "internal error";
-			goto return_results;
-		}
-	}
-
-	e = ei->bei_e;
-
-	/* acquire and lock entry */
-	/* FIXME: dn2entry() should return non-glue entry */
-	if (( rs->sr_err == DB_NOTFOUND ) ||
-		( !manageDSAit && e && is_entry_glue( e )))
-	{
-		if ( e != NULL ) {
-			rs->sr_matched = ch_strdup( e->e_dn );
-			rs->sr_ref = is_entry_referral( e )
-				? get_entry_referrals( op, e )
-				: NULL;
-			bdb_unlocked_cache_return_entry_r (&bdb->bi_cache, e);
-			e = NULL;
-
-		} else {
-			rs->sr_ref = referral_rewrite( default_referral, NULL,
-				&op->o_req_dn, LDAP_SCOPE_DEFAULT );
-		}
-
-		rs->sr_err = LDAP_REFERRAL;
-		send_ldap_result( op, rs );
-
-		if ( rs->sr_ref != default_referral ) {
-			ber_bvarray_free( rs->sr_ref );
-		}
-		free( (char *)rs->sr_matched );
-		rs->sr_ref = NULL;
-		rs->sr_matched = NULL;
-
-		goto done;
-	}
-
-	if ( !manageDSAit && is_entry_referral( e ) ) {
-		/* entry is a referral, don't allow modify */
-		rs->sr_ref = get_entry_referrals( op, e );
-
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_modify) ": entry is referral\n",
-			0, 0, 0 );
-
-		rs->sr_err = LDAP_REFERRAL;
-		rs->sr_matched = e->e_name.bv_val;
-		send_ldap_result( op, rs );
-
-		ber_bvarray_free( rs->sr_ref );
-		rs->sr_ref = NULL;
-		rs->sr_matched = NULL;
-		goto done;
-	}
-
-	if ( get_assert( op ) &&
-		( test_filter( op, e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
-	{
-		rs->sr_err = LDAP_ASSERTION_FAILED;
-		goto return_results;
-	}
-
-	if( op->o_preread ) {
-		if( preread_ctrl == NULL ) {
-			preread_ctrl = &ctrls[num_ctrls++];
-			ctrls[num_ctrls] = NULL;
-		}
-		if ( slap_read_controls( op, rs, e,
-			&slap_pre_read_bv, preread_ctrl ) )
-		{
-			Debug( LDAP_DEBUG_TRACE,
-				"<=- " LDAP_XSTRING(bdb_modify) ": pre-read "
-				"failed!\n", 0, 0, 0 );
-			if ( op->o_preread & SLAP_CONTROL_CRITICAL ) {
-				/* FIXME: is it correct to abort
-				 * operation if control fails? */
-				goto return_results;
-			}
-		}
-	}
-
-	/* nested transaction */
-	rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, &lt2, bdb->bi_db_opflags );
-	rs->sr_text = NULL;
-	if( rs->sr_err != 0 ) {
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_modify) ": txn_begin(2) failed: " "%s (%d)\n",
-			db_strerror(rs->sr_err), rs->sr_err, 0 );
-		rs->sr_err = LDAP_OTHER;
-		rs->sr_text = "internal error";
-		goto return_results;
-	}
-	Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modify) ": txn2 id: %x\n",
-		lt2->id(lt2), 0, 0 );
-	/* Modify the entry */
-	dummy = *e;
-	rs->sr_err = bdb_modify_internal( op, lt2, op->orm_modlist,
-		&dummy, &rs->sr_text, textbuf, textlen );
-
-	if( rs->sr_err != LDAP_SUCCESS ) {
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_modify) ": modify failed (%d)\n",
-			rs->sr_err, 0, 0 );
-		if ( (rs->sr_err == LDAP_INSUFFICIENT_ACCESS) && opinfo.boi_err ) {
-			rs->sr_err = opinfo.boi_err;
-		}
-		/* Only free attrs if they were dup'd.  */
-		if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL;
-		switch( rs->sr_err ) {
-		case DB_LOCK_DEADLOCK:
-		case DB_LOCK_NOTGRANTED:
-			goto retry;
-		}
-		goto return_results;
-	}
-
-	/* change the entry itself */
-	rs->sr_err = bdb_id2entry_update( op->o_bd, lt2, &dummy );
-	if ( rs->sr_err != 0 ) {
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_modify) ": id2entry update failed " "(%d)\n",
-			rs->sr_err, 0, 0 );
-		switch( rs->sr_err ) {
-		case DB_LOCK_DEADLOCK:
-		case DB_LOCK_NOTGRANTED:
-			goto retry;
-		}
-		rs->sr_text = "entry update failed";
-		goto return_results;
-	}
-
-	if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
-		rs->sr_err = LDAP_OTHER;
-		rs->sr_text = "txn_commit(2) failed";
-		goto return_results;
-	}
-
-	if( op->o_postread ) {
-		if( postread_ctrl == NULL ) {
-			postread_ctrl = &ctrls[num_ctrls++];
-			ctrls[num_ctrls] = NULL;
-		}
-		if( slap_read_controls( op, rs, &dummy,
-			&slap_post_read_bv, postread_ctrl ) )
-		{
-			Debug( LDAP_DEBUG_TRACE,
-				"<=- " LDAP_XSTRING(bdb_modify)
-				": post-read failed!\n", 0, 0, 0 );
-			if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
-				/* FIXME: is it correct to abort
-				 * operation if control fails? */
-				goto return_results;
-			}
-		}
-	}
-
-	if( op->o_noop ) {
-		if ( ( rs->sr_err = TXN_ABORT( ltid ) ) != 0 ) {
-			rs->sr_text = "txn_abort (no-op) failed";
-		} else {
-			rs->sr_err = LDAP_X_NO_OPERATION;
-			ltid = NULL;
-			/* Only free attrs if they were dup'd.  */
-			if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL;
-			goto return_results;
-		}
-	} else {
-		/* may have changed in bdb_modify_internal() */
-		e->e_ocflags = dummy.e_ocflags;
-		rc = bdb_cache_modify( bdb, e, dummy.e_attrs, ltid, &lock );
-		switch( rc ) {
-		case DB_LOCK_DEADLOCK:
-		case DB_LOCK_NOTGRANTED:
-			goto retry;
-		}
-		dummy.e_attrs = NULL;
-
-		rs->sr_err = TXN_COMMIT( ltid, 0 );
-	}
-	ltid = NULL;
-	LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
-	opinfo.boi_oe.oe_key = NULL;
-
-	if( rs->sr_err != 0 ) {
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_modify) ": txn_%s failed: %s (%d)\n",
-			op->o_noop ? "abort (no-op)" : "commit",
-			db_strerror(rs->sr_err), rs->sr_err );
-		rs->sr_err = LDAP_OTHER;
-		rs->sr_text = "commit failed";
-
-		goto return_results;
-	}
-
-	Debug( LDAP_DEBUG_TRACE,
-		LDAP_XSTRING(bdb_modify) ": updated%s id=%08lx dn=\"%s\"\n",
-		op->o_noop ? " (no-op)" : "",
-		dummy.e_id, op->o_req_dn.bv_val );
-
-	rs->sr_err = LDAP_SUCCESS;
-	rs->sr_text = NULL;
-	if( num_ctrls ) rs->sr_ctrls = ctrls;
-
-return_results:
-	if( dummy.e_attrs ) {
-		attrs_free( dummy.e_attrs );
-	}
-	send_ldap_result( op, rs );
-
-	if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp_kbyte ) {
-		TXN_CHECKPOINT( bdb->bi_dbenv,
-			bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
-	}
-
-done:
-	slap_graduate_commit_csn( op );
-
-	if( ltid != NULL ) {
-		TXN_ABORT( ltid );
-	}
-	if ( opinfo.boi_oe.oe_key ) {
-		LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
-	}
-
-	if( e != NULL ) {
-		bdb_unlocked_cache_return_entry_w (&bdb->bi_cache, e);
-	}
-
-	if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) {
-		slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
-		slap_sl_free( *preread_ctrl, op->o_tmpmemctx );
-	}
-	if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) {
-		slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
-		slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
-	}
-
-	rs->sr_text = NULL;
-
-	return rs->sr_err;
-}
diff --git a/servers/slapd/back-bdb/modrdn.c b/servers/slapd/back-bdb/modrdn.c
deleted file mode 100644
index f213b0f..0000000
--- a/servers/slapd/back-bdb/modrdn.c
+++ /dev/null
@@ -1,842 +0,0 @@
-/* modrdn.c - bdb backend modrdn routine */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "back-bdb.h"
-
-int
-bdb_modrdn( Operation	*op, SlapReply *rs )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	AttributeDescription *children = slap_schema.si_ad_children;
-	AttributeDescription *entry = slap_schema.si_ad_entry;
-	struct berval	p_dn, p_ndn;
-	struct berval	new_dn = {0, NULL}, new_ndn = {0, NULL};
-	Entry		*e = NULL;
-	Entry		*p = NULL;
-	EntryInfo	*ei = NULL, *eip = NULL, *nei = NULL, *neip = NULL;
-	/* LDAP v2 supporting correct attribute handling. */
-	char textbuf[SLAP_TEXT_BUFLEN];
-	size_t textlen = sizeof textbuf;
-	DB_TXN		*ltid = NULL, *lt2;
-	struct bdb_op_info opinfo = {{{ 0 }}};
-	Entry dummy = {0};
-
-	Entry		*np = NULL;			/* newSuperior Entry */
-	struct berval	*np_dn = NULL;			/* newSuperior dn */
-	struct berval	*np_ndn = NULL;			/* newSuperior ndn */
-	struct berval	*new_parent_dn = NULL;	/* np_dn, p_dn, or NULL */
-
-	int		manageDSAit = get_manageDSAit( op );
-
-	DB_LOCK		lock, plock, nplock;
-
-	int		num_retries = 0;
-
-	LDAPControl **preread_ctrl = NULL;
-	LDAPControl **postread_ctrl = NULL;
-	LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
-	int num_ctrls = 0;
-
-	int	rc;
-
-	int parent_is_glue = 0;
-	int parent_is_leaf = 0;
-
-#ifdef LDAP_X_TXN
-	int settle = 0;
-#endif
-
-	Debug( LDAP_DEBUG_TRACE, "==>" LDAP_XSTRING(bdb_modrdn) "(%s,%s,%s)\n",
-		op->o_req_dn.bv_val,op->oq_modrdn.rs_newrdn.bv_val,
-		op->oq_modrdn.rs_newSup ? op->oq_modrdn.rs_newSup->bv_val : "NULL" );
-
-#ifdef LDAP_X_TXN
-	if( op->o_txnSpec ) {
-		/* acquire connection lock */
-		ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
-		if( op->o_conn->c_txn == CONN_TXN_INACTIVE ) {
-			rs->sr_text = "invalid transaction identifier";
-			rs->sr_err = LDAP_X_TXN_ID_INVALID;
-			goto txnReturn;
-		} else if( op->o_conn->c_txn == CONN_TXN_SETTLE ) {
-			settle=1;
-			goto txnReturn;
-		}
-
-		if( op->o_conn->c_txn_backend == NULL ) {
-			op->o_conn->c_txn_backend = op->o_bd;
-
-		} else if( op->o_conn->c_txn_backend != op->o_bd ) {
-			rs->sr_text = "transaction cannot span multiple database contexts";
-			rs->sr_err = LDAP_AFFECTS_MULTIPLE_DSAS;
-			goto txnReturn;
-		}
-
-		/* insert operation into transaction */
-
-		rs->sr_text = "transaction specified";
-		rs->sr_err = LDAP_X_TXN_SPECIFY_OKAY;
-
-txnReturn:
-		/* release connection lock */
-		ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
-
-		if( !settle ) {
-			send_ldap_result( op, rs );
-			return rs->sr_err;
-		}
-	}
-#endif
-
-	ctrls[num_ctrls] = NULL;
-
-	slap_mods_opattrs( op, &op->orr_modlist, 1 );
-
-	if( 0 ) {
-retry:	/* transaction retry */
-		if ( dummy.e_attrs ) {
-			attrs_free( dummy.e_attrs );
-			dummy.e_attrs = NULL;
-		}
-		if (e != NULL) {
-			bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
-			e = NULL;
-		}
-		if (p != NULL) {
-			bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
-			p = NULL;
-		}
-		if (np != NULL) {
-			bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, np);
-			np = NULL;
-		}
-		Debug( LDAP_DEBUG_TRACE, "==>" LDAP_XSTRING(bdb_modrdn)
-				": retrying...\n", 0, 0, 0 );
-
-		rs->sr_err = TXN_ABORT( ltid );
-		ltid = NULL;
-		LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
-		opinfo.boi_oe.oe_key = NULL;
-		op->o_do_not_cache = opinfo.boi_acl_cache;
-		if( rs->sr_err != 0 ) {
-			rs->sr_err = LDAP_OTHER;
-			rs->sr_text = "internal error";
-			goto return_results;
-		}
-		if ( op->o_abandon ) {
-			rs->sr_err = SLAPD_ABANDON;
-			goto return_results;
-		}
-		parent_is_glue = 0;
-		parent_is_leaf = 0;
-		bdb_trans_backoff( ++num_retries );
-	}
-
-	/* begin transaction */
-	rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, NULL, &ltid, 
-		bdb->bi_db_opflags );
-	rs->sr_text = NULL;
-	if( rs->sr_err != 0 ) {
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_modrdn) ": txn_begin failed: "
-			"%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
-		rs->sr_err = LDAP_OTHER;
-		rs->sr_text = "internal error";
-		goto return_results;
-	}
-	Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn) ": txn1 id: %x\n",
-		ltid->id(ltid), 0, 0 );
-
-	opinfo.boi_oe.oe_key = bdb;
-	opinfo.boi_txn = ltid;
-	opinfo.boi_err = 0;
-	opinfo.boi_acl_cache = op->o_do_not_cache;
-	LDAP_SLIST_INSERT_HEAD( &op->o_extra, &opinfo.boi_oe, oe_next );
-
-	/* get entry */
-	rs->sr_err = bdb_dn2entry( op, ltid, &op->o_req_ndn, &ei, 1,
-		&lock );
-
-	switch( rs->sr_err ) {
-	case 0:
-	case DB_NOTFOUND:
-		break;
-	case DB_LOCK_DEADLOCK:
-	case DB_LOCK_NOTGRANTED:
-		goto retry;
-	case LDAP_BUSY:
-		rs->sr_text = "ldap server busy";
-		goto return_results;
-	default:
-		rs->sr_err = LDAP_OTHER;
-		rs->sr_text = "internal error";
-		goto return_results;
-	}
-
-	e = ei->bei_e;
-	/* FIXME: dn2entry() should return non-glue entry */
-	if (( rs->sr_err == DB_NOTFOUND ) ||
-		( !manageDSAit && e && is_entry_glue( e )))
-	{
-		if( e != NULL ) {
-			rs->sr_matched = ch_strdup( e->e_dn );
-			rs->sr_ref = is_entry_referral( e )
-				? get_entry_referrals( op, e )
-				: NULL;
-			bdb_unlocked_cache_return_entry_r( &bdb->bi_cache, e);
-			e = NULL;
-
-		} else {
-			rs->sr_ref = referral_rewrite( default_referral, NULL,
-					&op->o_req_dn, LDAP_SCOPE_DEFAULT );
-		}
-
-		rs->sr_err = LDAP_REFERRAL;
-		send_ldap_result( op, rs );
-
-		ber_bvarray_free( rs->sr_ref );
-		free( (char *)rs->sr_matched );
-		rs->sr_ref = NULL;
-		rs->sr_matched = NULL;
-
-		goto done;
-	}
-
-	if ( get_assert( op ) &&
-		( test_filter( op, e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
-	{
-		rs->sr_err = LDAP_ASSERTION_FAILED;
-		goto return_results;
-	}
-
-	/* check write on old entry */
-	rs->sr_err = access_allowed( op, e, entry, NULL, ACL_WRITE, NULL );
-	if ( ! rs->sr_err ) {
-		switch( opinfo.boi_err ) {
-		case DB_LOCK_DEADLOCK:
-		case DB_LOCK_NOTGRANTED:
-			goto retry;
-		}
-
-		Debug( LDAP_DEBUG_TRACE, "no access to entry\n", 0,
-			0, 0 );
-		rs->sr_text = "no write access to old entry";
-		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
-		goto return_results;
-	}
-
-#ifndef BDB_HIER
-	rs->sr_err = bdb_cache_children( op, ltid, e );
-	if ( rs->sr_err != DB_NOTFOUND ) {
-		switch( rs->sr_err ) {
-		case DB_LOCK_DEADLOCK:
-		case DB_LOCK_NOTGRANTED:
-			goto retry;
-		case 0:
-			Debug(LDAP_DEBUG_ARGS,
-				"<=- " LDAP_XSTRING(bdb_modrdn)
-				": non-leaf %s\n",
-				op->o_req_dn.bv_val, 0, 0);
-			rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
-			rs->sr_text = "subtree rename not supported";
-			break;
-		default:
-			Debug(LDAP_DEBUG_ARGS,
-				"<=- " LDAP_XSTRING(bdb_modrdn)
-				": has_children failed: %s (%d)\n",
-				db_strerror(rs->sr_err), rs->sr_err, 0 );
-			rs->sr_err = LDAP_OTHER;
-			rs->sr_text = "internal error";
-		}
-		goto return_results;
-	}
-	ei->bei_state |= CACHE_ENTRY_NO_KIDS;
-#endif
-
-	if (!manageDSAit && is_entry_referral( e ) ) {
-		/* parent is a referral, don't allow add */
-		rs->sr_ref = get_entry_referrals( op, e );
-
-		Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn)
-			": entry %s is referral\n", e->e_dn, 0, 0 );
-
-		rs->sr_err = LDAP_REFERRAL,
-		rs->sr_matched = e->e_name.bv_val;
-		send_ldap_result( op, rs );
-
-		ber_bvarray_free( rs->sr_ref );
-		rs->sr_ref = NULL;
-		rs->sr_matched = NULL;
-		goto done;
-	}
-
-	if ( be_issuffix( op->o_bd, &e->e_nname ) ) {
-#ifdef BDB_MULTIPLE_SUFFIXES
-		/* Allow renaming one suffix entry to another */
-		p_ndn = slap_empty_bv;
-#else
-		/* There can only be one suffix entry */
-		rs->sr_err = LDAP_NAMING_VIOLATION;
-		rs->sr_text = "cannot rename suffix entry";
-		goto return_results;
-#endif
-	} else {
-		dnParent( &e->e_nname, &p_ndn );
-	}
-	np_ndn = &p_ndn;
-	eip = ei->bei_parent;
-	if ( eip && eip->bei_id ) {
-		/* Make sure parent entry exist and we can write its 
-		 * children.
-		 */
-		rs->sr_err = bdb_cache_find_id( op, ltid,
-			eip->bei_id, &eip, 0, &plock );
-
-		switch( rs->sr_err ) {
-		case 0:
-		case DB_NOTFOUND:
-			break;
-		case DB_LOCK_DEADLOCK:
-		case DB_LOCK_NOTGRANTED:
-			goto retry;
-		case LDAP_BUSY:
-			rs->sr_text = "ldap server busy";
-			goto return_results;
-		default:
-			rs->sr_err = LDAP_OTHER;
-			rs->sr_text = "internal error";
-			goto return_results;
-		}
-
-		p = eip->bei_e;
-		if( p == NULL) {
-			Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn)
-				": parent does not exist\n", 0, 0, 0);
-			rs->sr_err = LDAP_OTHER;
-			rs->sr_text = "old entry's parent does not exist";
-			goto return_results;
-		}
-	} else {
-		p = (Entry *)&slap_entry_root;
-	}
-
-	/* check parent for "children" acl */
-	rs->sr_err = access_allowed( op, p,
-		children, NULL,
-		op->oq_modrdn.rs_newSup == NULL ?
-			ACL_WRITE : ACL_WDEL,
-		NULL );
-
-	if ( !p_ndn.bv_len )
-		p = NULL;
-
-	if ( ! rs->sr_err ) {
-		switch( opinfo.boi_err ) {
-		case DB_LOCK_DEADLOCK:
-		case DB_LOCK_NOTGRANTED:
-			goto retry;
-		}
-
-		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
-		Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
-			0, 0 );
-		rs->sr_text = "no write access to old parent's children";
-		goto return_results;
-	}
-
-	Debug( LDAP_DEBUG_TRACE,
-		LDAP_XSTRING(bdb_modrdn) ": wr to children "
-		"of entry %s OK\n", p_ndn.bv_val, 0, 0 );
-	
-	if ( p_ndn.bv_val == slap_empty_bv.bv_val ) {
-		p_dn = slap_empty_bv;
-	} else {
-		dnParent( &e->e_name, &p_dn );
-	}
-
-	Debug( LDAP_DEBUG_TRACE,
-		LDAP_XSTRING(bdb_modrdn) ": parent dn=%s\n",
-		p_dn.bv_val, 0, 0 );
-
-	new_parent_dn = &p_dn;	/* New Parent unless newSuperior given */
-
-	if ( op->oq_modrdn.rs_newSup != NULL ) {
-		Debug( LDAP_DEBUG_TRACE, 
-			LDAP_XSTRING(bdb_modrdn)
-			": new parent \"%s\" requested...\n",
-			op->oq_modrdn.rs_newSup->bv_val, 0, 0 );
-
-		/*  newSuperior == oldParent? */
-		if( dn_match( &p_ndn, op->oq_modrdn.rs_nnewSup ) ) {
-			Debug( LDAP_DEBUG_TRACE, "bdb_back_modrdn: "
-				"new parent \"%s\" same as the old parent \"%s\"\n",
-				op->oq_modrdn.rs_newSup->bv_val, p_dn.bv_val, 0 );
-			op->oq_modrdn.rs_newSup = NULL; /* ignore newSuperior */
-		}
-	}
-
-	/* There's a BDB_MULTIPLE_SUFFIXES case here that this code doesn't
-	 * support. E.g., two suffixes dc=foo,dc=com and dc=bar,dc=net.
-	 * We do not allow modDN
-	 *   dc=foo,dc=com
-	 *    newrdn dc=bar
-	 *    newsup dc=net
-	 * and we probably should. But since MULTIPLE_SUFFIXES is deprecated
-	 * I'm ignoring this problem for now.
-	 */
-	if ( op->oq_modrdn.rs_newSup != NULL ) {
-		if ( op->oq_modrdn.rs_newSup->bv_len ) {
-			np_dn = op->oq_modrdn.rs_newSup;
-			np_ndn = op->oq_modrdn.rs_nnewSup;
-
-			/* newSuperior == oldParent? - checked above */
-			/* newSuperior == entry being moved?, if so ==> ERROR */
-			if ( dnIsSuffix( np_ndn, &e->e_nname )) {
-				rs->sr_err = LDAP_NO_SUCH_OBJECT;
-				rs->sr_text = "new superior not found";
-				goto return_results;
-			}
-			/* Get Entry with dn=newSuperior. Does newSuperior exist? */
-
-			rs->sr_err = bdb_dn2entry( op, ltid, np_ndn,
-				&neip, 0, &nplock );
-
-			switch( rs->sr_err ) {
-			case 0: np = neip->bei_e;
-			case DB_NOTFOUND:
-				break;
-			case DB_LOCK_DEADLOCK:
-			case DB_LOCK_NOTGRANTED:
-				goto retry;
-			case LDAP_BUSY:
-				rs->sr_text = "ldap server busy";
-				goto return_results;
-			default:
-				rs->sr_err = LDAP_OTHER;
-				rs->sr_text = "internal error";
-				goto return_results;
-			}
-
-			if( np == NULL) {
-				Debug( LDAP_DEBUG_TRACE,
-					LDAP_XSTRING(bdb_modrdn)
-					": newSup(ndn=%s) not here!\n",
-					np_ndn->bv_val, 0, 0);
-				rs->sr_text = "new superior not found";
-				rs->sr_err = LDAP_NO_SUCH_OBJECT;
-				goto return_results;
-			}
-
-			Debug( LDAP_DEBUG_TRACE,
-				LDAP_XSTRING(bdb_modrdn)
-				": wr to new parent OK np=%p, id=%ld\n",
-				(void *) np, (long) np->e_id, 0 );
-
-			/* check newSuperior for "children" acl */
-			rs->sr_err = access_allowed( op, np, children,
-				NULL, ACL_WADD, NULL );
-
-			if( ! rs->sr_err ) {
-				switch( opinfo.boi_err ) {
-				case DB_LOCK_DEADLOCK:
-				case DB_LOCK_NOTGRANTED:
-					goto retry;
-				}
-
-				Debug( LDAP_DEBUG_TRACE,
-					LDAP_XSTRING(bdb_modrdn)
-					": no wr to newSup children\n",
-					0, 0, 0 );
-				rs->sr_text = "no write access to new superior's children";
-				rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
-				goto return_results;
-			}
-
-			if ( is_entry_alias( np ) ) {
-				/* parent is an alias, don't allow add */
-				Debug( LDAP_DEBUG_TRACE,
-					LDAP_XSTRING(bdb_modrdn)
-					": entry is alias\n",
-					0, 0, 0 );
-				rs->sr_text = "new superior is an alias";
-				rs->sr_err = LDAP_ALIAS_PROBLEM;
-				goto return_results;
-			}
-
-			if ( is_entry_referral( np ) ) {
-				/* parent is a referral, don't allow add */
-				Debug( LDAP_DEBUG_TRACE,
-					LDAP_XSTRING(bdb_modrdn)
-					": entry is referral\n",
-					0, 0, 0 );
-				rs->sr_text = "new superior is a referral";
-				rs->sr_err = LDAP_OTHER;
-				goto return_results;
-			}
-
-		} else {
-			np_dn = NULL;
-
-			/* no parent, modrdn entry directly under root */
-			if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv )
-				|| be_isupdate( op ) ) {
-				np = (Entry *)&slap_entry_root;
-
-				/* check parent for "children" acl */
-				rs->sr_err = access_allowed( op, np,
-					children, NULL, ACL_WADD, NULL );
-
-				np = NULL;
-
-				if ( ! rs->sr_err ) {
-					switch( opinfo.boi_err ) {
-					case DB_LOCK_DEADLOCK:
-					case DB_LOCK_NOTGRANTED:
-						goto retry;
-					}
-
-					rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
-					Debug( LDAP_DEBUG_TRACE, 
-						"no access to new superior\n", 
-						0, 0, 0 );
-					rs->sr_text =
-						"no write access to new superior's children";
-					goto return_results;
-				}
-			}
-		}
-
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_modrdn)
-			": wr to new parent's children OK\n",
-			0, 0, 0 );
-
-		new_parent_dn = np_dn;
-	}
-
-	/* Build target dn and make sure target entry doesn't exist already. */
-	if (!new_dn.bv_val) {
-		build_new_dn( &new_dn, new_parent_dn, &op->oq_modrdn.rs_newrdn, NULL ); 
-	}
-
-	if (!new_ndn.bv_val) {
-		struct berval bv = {0, NULL};
-		dnNormalize( 0, NULL, NULL, &new_dn, &bv, op->o_tmpmemctx );
-		ber_dupbv( &new_ndn, &bv );
-		/* FIXME: why not call dnNormalize() w/o ctx? */
-		op->o_tmpfree( bv.bv_val, op->o_tmpmemctx );
-	}
-
-	Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn) ": new ndn=%s\n",
-		new_ndn.bv_val, 0, 0 );
-
-	/* Shortcut the search */
-	nei = neip ? neip : eip;
-	rs->sr_err = bdb_cache_find_ndn ( op, ltid, &new_ndn, &nei );
-	if ( nei ) bdb_cache_entryinfo_unlock( nei );
-	switch( rs->sr_err ) {
-	case DB_LOCK_DEADLOCK:
-	case DB_LOCK_NOTGRANTED:
-		goto retry;
-	case DB_NOTFOUND:
-		break;
-	case 0:
-		/* Allow rename to same DN */
-		if ( nei == ei )
-			break;
-		rs->sr_err = LDAP_ALREADY_EXISTS;
-		goto return_results;
-	default:
-		rs->sr_err = LDAP_OTHER;
-		rs->sr_text = "internal error";
-		goto return_results;
-	}
-
-	assert( op->orr_modlist != NULL );
-
-	if( op->o_preread ) {
-		if( preread_ctrl == NULL ) {
-			preread_ctrl = &ctrls[num_ctrls++];
-			ctrls[num_ctrls] = NULL;
-		}
-		if( slap_read_controls( op, rs, e,
-			&slap_pre_read_bv, preread_ctrl ) )
-		{
-			Debug( LDAP_DEBUG_TRACE,        
-				"<=- " LDAP_XSTRING(bdb_modrdn)
-				": pre-read failed!\n", 0, 0, 0 );
-			if ( op->o_preread & SLAP_CONTROL_CRITICAL ) {
-				/* FIXME: is it correct to abort
-				 * operation if control fails? */
-				goto return_results;
-			}
-		}                   
-	}
-
-	/* nested transaction */
-	rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, &lt2, bdb->bi_db_opflags );
-	rs->sr_text = NULL;
-	if( rs->sr_err != 0 ) {
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_modrdn)
-			": txn_begin(2) failed: %s (%d)\n",
-			db_strerror(rs->sr_err), rs->sr_err, 0 );
-		rs->sr_err = LDAP_OTHER;
-		rs->sr_text = "internal error";
-		goto return_results;
-	}
-	Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn) ": txn2 id: %x\n",
-		lt2->id(lt2), 0, 0 );
-
-	/* delete old DN */
-	rs->sr_err = bdb_dn2id_delete( op, lt2, eip, e );
-	if ( rs->sr_err != 0 ) {
-		Debug(LDAP_DEBUG_TRACE,
-			"<=- " LDAP_XSTRING(bdb_modrdn)
-			": dn2id del failed: %s (%d)\n",
-			db_strerror(rs->sr_err), rs->sr_err, 0 );
-		switch( rs->sr_err ) {
-		case DB_LOCK_DEADLOCK:
-		case DB_LOCK_NOTGRANTED:
-			goto retry;
-		}
-		rs->sr_err = LDAP_OTHER;
-		rs->sr_text = "DN index delete fail";
-		goto return_results;
-	}
-
-	/* copy the entry, then override some fields */
-	dummy = *e;
-	dummy.e_name = new_dn;
-	dummy.e_nname = new_ndn;
-	dummy.e_attrs = NULL;
-
-	/* add new DN */
-	rs->sr_err = bdb_dn2id_add( op, lt2, neip ? neip : eip, &dummy );
-	if ( rs->sr_err != 0 ) {
-		Debug(LDAP_DEBUG_TRACE,
-			"<=- " LDAP_XSTRING(bdb_modrdn)
-			": dn2id add failed: %s (%d)\n",
-			db_strerror(rs->sr_err), rs->sr_err, 0 );
-		switch( rs->sr_err ) {
-		case DB_LOCK_DEADLOCK:
-		case DB_LOCK_NOTGRANTED:
-			goto retry;
-		}
-		rs->sr_err = LDAP_OTHER;
-		rs->sr_text = "DN index add failed";
-		goto return_results;
-	}
-
-	dummy.e_attrs = e->e_attrs;
-
-	/* modify entry */
-	rs->sr_err = bdb_modify_internal( op, lt2, op->orr_modlist, &dummy,
-		&rs->sr_text, textbuf, textlen );
-	if( rs->sr_err != LDAP_SUCCESS ) {
-		Debug(LDAP_DEBUG_TRACE,
-			"<=- " LDAP_XSTRING(bdb_modrdn)
-			": modify failed: %s (%d)\n",
-			db_strerror(rs->sr_err), rs->sr_err, 0 );
-		if ( ( rs->sr_err == LDAP_INSUFFICIENT_ACCESS ) && opinfo.boi_err ) {
-			rs->sr_err = opinfo.boi_err;
-		}
-		if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL;
-		switch( rs->sr_err ) {
-		case DB_LOCK_DEADLOCK:
-		case DB_LOCK_NOTGRANTED:
-			goto retry;
-		}
-		goto return_results;
-	}
-
-	/* id2entry index */
-	rs->sr_err = bdb_id2entry_update( op->o_bd, lt2, &dummy );
-	if ( rs->sr_err != 0 ) {
-		Debug(LDAP_DEBUG_TRACE,
-			"<=- " LDAP_XSTRING(bdb_modrdn)
-			": id2entry failed: %s (%d)\n",
-			db_strerror(rs->sr_err), rs->sr_err, 0 );
-		switch( rs->sr_err ) {
-		case DB_LOCK_DEADLOCK:
-		case DB_LOCK_NOTGRANTED:
-			goto retry;
-		}
-		rs->sr_err = LDAP_OTHER;
-		rs->sr_text = "entry update failed";
-		goto return_results;
-	}
-
-	if ( p_ndn.bv_len != 0 ) {
-		parent_is_glue = is_entry_glue(p);
-		rs->sr_err = bdb_cache_children( op, lt2, p );
-		if ( rs->sr_err != DB_NOTFOUND ) {
-			switch( rs->sr_err ) {
-			case DB_LOCK_DEADLOCK:
-			case DB_LOCK_NOTGRANTED:
-				goto retry;
-			case 0:
-				break;
-			default:
-				Debug(LDAP_DEBUG_ARGS,
-					"<=- " LDAP_XSTRING(bdb_modrdn)
-					": has_children failed: %s (%d)\n",
-					db_strerror(rs->sr_err), rs->sr_err, 0 );
-				rs->sr_err = LDAP_OTHER;
-				rs->sr_text = "internal error";
-				goto return_results;
-			}
-			parent_is_leaf = 1;
-		}
-		bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
-		p = NULL;
-	}
-
-	if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
-		rs->sr_err = LDAP_OTHER;
-		rs->sr_text = "txn_commit(2) failed";
-		goto return_results;
-	}
-
-	if( op->o_postread ) {
-		if( postread_ctrl == NULL ) {
-			postread_ctrl = &ctrls[num_ctrls++];
-			ctrls[num_ctrls] = NULL;
-		}
-		if( slap_read_controls( op, rs, &dummy,
-			&slap_post_read_bv, postread_ctrl ) )
-		{
-			Debug( LDAP_DEBUG_TRACE,        
-				"<=- " LDAP_XSTRING(bdb_modrdn)
-				": post-read failed!\n", 0, 0, 0 );
-			if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
-				/* FIXME: is it correct to abort
-				 * operation if control fails? */
-				goto return_results;
-			}
-		}                   
-	}
-
-	if( op->o_noop ) {
-		if(( rs->sr_err=TXN_ABORT( ltid )) != 0 ) {
-			rs->sr_text = "txn_abort (no-op) failed";
-		} else {
-			rs->sr_err = LDAP_X_NO_OPERATION;
-			ltid = NULL;
-			/* Only free attrs if they were dup'd.  */
-			if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL;
-			goto return_results;
-		}
-
-	} else {
-		rc = bdb_cache_modrdn( bdb, e, &op->orr_nnewrdn, &dummy, neip,
-			ltid, &lock );
-		switch( rc ) {
-		case DB_LOCK_DEADLOCK:
-		case DB_LOCK_NOTGRANTED:
-			goto retry;
-		}
-		dummy.e_attrs = NULL;
-		new_dn.bv_val = NULL;
-		new_ndn.bv_val = NULL;
-
-		if(( rs->sr_err=TXN_COMMIT( ltid, 0 )) != 0 ) {
-			rs->sr_text = "txn_commit failed";
-		} else {
-			rs->sr_err = LDAP_SUCCESS;
-		}
-	}
- 
-	ltid = NULL;
-	LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
-	opinfo.boi_oe.oe_key = NULL;
- 
-	if( rs->sr_err != LDAP_SUCCESS ) {
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_modrdn) ": %s : %s (%d)\n",
-			rs->sr_text, db_strerror(rs->sr_err), rs->sr_err );
-		rs->sr_err = LDAP_OTHER;
-
-		goto return_results;
-	}
-
-	Debug(LDAP_DEBUG_TRACE,
-		LDAP_XSTRING(bdb_modrdn)
-		": rdn modified%s id=%08lx dn=\"%s\"\n",
-		op->o_noop ? " (no-op)" : "",
-		dummy.e_id, op->o_req_dn.bv_val );
-	rs->sr_text = NULL;
-	if( num_ctrls ) rs->sr_ctrls = ctrls;
-
-return_results:
-	if ( dummy.e_attrs ) {
-		attrs_free( dummy.e_attrs );
-	}
-	send_ldap_result( op, rs );
-
-	if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp_kbyte ) {
-		TXN_CHECKPOINT( bdb->bi_dbenv,
-			bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
-	}
-	
-	if ( rs->sr_err == LDAP_SUCCESS && parent_is_glue && parent_is_leaf ) {
-		op->o_delete_glue_parent = 1;
-	}
-
-done:
-	slap_graduate_commit_csn( op );
-
-	if( new_dn.bv_val != NULL ) free( new_dn.bv_val );
-	if( new_ndn.bv_val != NULL ) free( new_ndn.bv_val );
-
-	/* LDAP v3 Support */
-	if( np != NULL ) {
-		/* free new parent and reader lock */
-		bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, np);
-	}
-
-	if( p != NULL ) {
-		/* free parent and reader lock */
-		bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
-	}
-
-	/* free entry */
-	if( e != NULL ) {
-		bdb_unlocked_cache_return_entry_w( &bdb->bi_cache, e);
-	}
-
-	if( ltid != NULL ) {
-		TXN_ABORT( ltid );
-	}
-	if ( opinfo.boi_oe.oe_key ) {
-		LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
-	}
-
-	if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) {
-		slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
-		slap_sl_free( *preread_ctrl, op->o_tmpmemctx );
-	}
-	if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) {
-		slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
-		slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
-	}
-	return rs->sr_err;
-}
diff --git a/servers/slapd/back-bdb/monitor.c b/servers/slapd/back-bdb/monitor.c
deleted file mode 100644
index 4afaf9d..0000000
--- a/servers/slapd/back-bdb/monitor.c
+++ /dev/null
@@ -1,724 +0,0 @@
-/* monitor.c - monitor bdb backend */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-#include <ac/stdlib.h>
-#include <ac/errno.h>
-#include <sys/stat.h>
-#include "lutil.h"
-#include "back-bdb.h"
-
-#include "../back-monitor/back-monitor.h"
-
-#include "config.h"
-
-static ObjectClass		*oc_olmBDBDatabase;
-
-static AttributeDescription	*ad_olmBDBEntryCache,
-	*ad_olmBDBDNCache, *ad_olmBDBIDLCache,
-	*ad_olmDbDirectory;
-
-#ifdef BDB_MONITOR_IDX
-static int
-bdb_monitor_idx_entry_add(
-	struct bdb_info	*bdb,
-	Entry		*e );
-
-static AttributeDescription	*ad_olmDbNotIndexed;
-#endif /* BDB_MONITOR_IDX */
-
-/*
- * NOTE: there's some confusion in monitor OID arc;
- * by now, let's consider:
- * 
- * Subsystems monitor attributes	1.3.6.1.4.1.4203.666.1.55.0
- * Databases monitor attributes		1.3.6.1.4.1.4203.666.1.55.0.1
- * BDB database monitor attributes	1.3.6.1.4.1.4203.666.1.55.0.1.1
- *
- * Subsystems monitor objectclasses	1.3.6.1.4.1.4203.666.3.16.0
- * Databases monitor objectclasses	1.3.6.1.4.1.4203.666.3.16.0.1
- * BDB database monitor objectclasses	1.3.6.1.4.1.4203.666.3.16.0.1.1
- */
-
-static struct {
-	char			*name;
-	char			*oid;
-}		s_oid[] = {
-	{ "olmBDBAttributes",			"olmDatabaseAttributes:1" },
-	{ "olmBDBObjectClasses",		"olmDatabaseObjectClasses:1" },
-
-	{ NULL }
-};
-
-static struct {
-	char			*desc;
-	AttributeDescription	**ad;
-}		s_at[] = {
-	{ "( olmBDBAttributes:1 "
-		"NAME ( 'olmBDBEntryCache' ) "
-		"DESC 'Number of items in Entry Cache' "
-		"SUP monitorCounter "
-		"NO-USER-MODIFICATION "
-		"USAGE dSAOperation )",
-		&ad_olmBDBEntryCache },
-
-	{ "( olmBDBAttributes:2 "
-		"NAME ( 'olmBDBDNCache' ) "
-		"DESC 'Number of items in DN Cache' "
-		"SUP monitorCounter "
-		"NO-USER-MODIFICATION "
-		"USAGE dSAOperation )",
-		&ad_olmBDBDNCache },
-
-	{ "( olmBDBAttributes:3 "
-		"NAME ( 'olmBDBIDLCache' ) "
-		"DESC 'Number of items in IDL Cache' "
-		"SUP monitorCounter "
-		"NO-USER-MODIFICATION "
-		"USAGE dSAOperation )",
-		&ad_olmBDBIDLCache },
-
-	{ "( olmDatabaseAttributes:1 "
-		"NAME ( 'olmDbDirectory' ) "
-		"DESC 'Path name of the directory "
-			"where the database environment resides' "
-		"SUP monitoredInfo "
-		"NO-USER-MODIFICATION "
-		"USAGE dSAOperation )",
-		&ad_olmDbDirectory },
-
-#ifdef BDB_MONITOR_IDX
-	{ "( olmDatabaseAttributes:2 "
-		"NAME ( 'olmDbNotIndexed' ) "
-		"DESC 'Missing indexes resulting from candidate selection' "
-		"SUP monitoredInfo "
-		"NO-USER-MODIFICATION "
-		"USAGE dSAOperation )",
-		&ad_olmDbNotIndexed },
-#endif /* BDB_MONITOR_IDX */
-
-	{ NULL }
-};
-
-static struct {
-	char		*desc;
-	ObjectClass	**oc;
-}		s_oc[] = {
-	/* augments an existing object, so it must be AUXILIARY
-	 * FIXME: derive from some ABSTRACT "monitoredEntity"? */
-	{ "( olmBDBObjectClasses:1 "
-		"NAME ( 'olmBDBDatabase' ) "
-		"SUP top AUXILIARY "
-		"MAY ( "
-			"olmBDBEntryCache "
-			"$ olmBDBDNCache "
-			"$ olmBDBIDLCache "
-			"$ olmDbDirectory "
-#ifdef BDB_MONITOR_IDX
-			"$ olmDbNotIndexed "
-#endif /* BDB_MONITOR_IDX */
-			") )",
-		&oc_olmBDBDatabase },
-
-	{ NULL }
-};
-
-static int
-bdb_monitor_update(
-	Operation	*op,
-	SlapReply	*rs,
-	Entry		*e,
-	void		*priv )
-{
-	struct bdb_info		*bdb = (struct bdb_info *) priv;
-	Attribute		*a;
-
-	char			buf[ BUFSIZ ];
-	struct berval		bv;
-
-	assert( ad_olmBDBEntryCache != NULL );
-
-	a = attr_find( e->e_attrs, ad_olmBDBEntryCache );
-	assert( a != NULL );
-	bv.bv_val = buf;
-	bv.bv_len = snprintf( buf, sizeof( buf ), "%lu", bdb->bi_cache.c_cursize );
-	ber_bvreplace( &a->a_vals[ 0 ], &bv );
-
-	a = attr_find( e->e_attrs, ad_olmBDBDNCache );
-	assert( a != NULL );
-	bv.bv_len = snprintf( buf, sizeof( buf ), "%lu", bdb->bi_cache.c_eiused );
-	ber_bvreplace( &a->a_vals[ 0 ], &bv );
-
-	a = attr_find( e->e_attrs, ad_olmBDBIDLCache );
-	assert( a != NULL );
-	bv.bv_len = snprintf( buf, sizeof( buf ), "%lu", bdb->bi_idl_cache_size );
-	ber_bvreplace( &a->a_vals[ 0 ], &bv );
-	
-#ifdef BDB_MONITOR_IDX
-	bdb_monitor_idx_entry_add( bdb, e );
-#endif /* BDB_MONITOR_IDX */
-
-	return SLAP_CB_CONTINUE;
-}
-
-#if 0	/* uncomment if required */
-static int
-bdb_monitor_modify(
-	Operation	*op,
-	SlapReply	*rs,
-	Entry		*e,
-	void		*priv )
-{
-	return SLAP_CB_CONTINUE;
-}
-#endif
-
-static int
-bdb_monitor_free(
-	Entry		*e,
-	void		**priv )
-{
-	struct berval	values[ 2 ];
-	Modification	mod = { 0 };
-
-	const char	*text;
-	char		textbuf[ SLAP_TEXT_BUFLEN ];
-
-	int		i, rc;
-
-	/* NOTE: if slap_shutdown != 0, priv might have already been freed */
-	*priv = NULL;
-
-	/* Remove objectClass */
-	mod.sm_op = LDAP_MOD_DELETE;
-	mod.sm_desc = slap_schema.si_ad_objectClass;
-	mod.sm_values = values;
-	mod.sm_numvals = 1;
-	values[ 0 ] = oc_olmBDBDatabase->soc_cname;
-	BER_BVZERO( &values[ 1 ] );
-
-	rc = modify_delete_values( e, &mod, 1, &text,
-		textbuf, sizeof( textbuf ) );
-	/* don't care too much about return code... */
-
-	/* remove attrs */
-	mod.sm_values = NULL;
-	mod.sm_numvals = 0;
-	for ( i = 0; s_at[ i ].desc != NULL; i++ ) {
-		mod.sm_desc = *s_at[ i ].ad;
-		rc = modify_delete_values( e, &mod, 1, &text,
-			textbuf, sizeof( textbuf ) );
-		/* don't care too much about return code... */
-	}
-	
-	return SLAP_CB_CONTINUE;
-}
-
-#define	bdb_monitor_initialize	BDB_SYMBOL(monitor_initialize)
-
-/*
- * call from within bdb_initialize()
- */
-static int
-bdb_monitor_initialize( void )
-{
-	int		i, code;
-	ConfigArgs c;
-	char	*argv[ 3 ];
-
-	static int	bdb_monitor_initialized = 0;
-
-	/* set to 0 when successfully initialized; otherwise, remember failure */
-	static int	bdb_monitor_initialized_failure = 1;
-
-	if ( bdb_monitor_initialized++ ) {
-		return bdb_monitor_initialized_failure;
-	}
-
-	if ( backend_info( "monitor" ) == NULL ) {
-		return -1;
-	}
-
-	/* register schema here */
-
-	argv[ 0 ] = "back-bdb/back-hdb monitor";
-	c.argv = argv;
-	c.argc = 3;
-	c.fname = argv[0];
-
-	for ( i = 0; s_oid[ i ].name; i++ ) {
-		c.lineno = i;
-		argv[ 1 ] = s_oid[ i ].name;
-		argv[ 2 ] = s_oid[ i ].oid;
-
-		if ( parse_oidm( &c, 0, NULL ) != 0 ) {
-			Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_monitor_initialize)
-				": unable to add "
-				"objectIdentifier \"%s=%s\"\n",
-				s_oid[ i ].name, s_oid[ i ].oid, 0 );
-			return 2;
-		}
-	}
-
-	for ( i = 0; s_at[ i ].desc != NULL; i++ ) {
-		code = register_at( s_at[ i ].desc, s_at[ i ].ad, 1 );
-		if ( code != LDAP_SUCCESS ) {
-			Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_monitor_initialize)
-				": register_at failed for attributeType (%s)\n",
-				s_at[ i ].desc, 0, 0 );
-			return 3;
-
-		} else {
-			(*s_at[ i ].ad)->ad_type->sat_flags |= SLAP_AT_HIDE;
-		}
-	}
-
-	for ( i = 0; s_oc[ i ].desc != NULL; i++ ) {
-		code = register_oc( s_oc[ i ].desc, s_oc[ i ].oc, 1 );
-		if ( code != LDAP_SUCCESS ) {
-			Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_monitor_initialize)
-				": register_oc failed for objectClass (%s)\n",
-				s_oc[ i ].desc, 0, 0 );
-			return 4;
-
-		} else {
-			(*s_oc[ i ].oc)->soc_flags |= SLAP_OC_HIDE;
-		}
-	}
-
-	return ( bdb_monitor_initialized_failure = LDAP_SUCCESS );
-}
-
-/*
- * call from within bdb_db_init()
- */
-int
-bdb_monitor_db_init( BackendDB *be )
-{
-	struct bdb_info		*bdb = (struct bdb_info *) be->be_private;
-
-	if ( bdb_monitor_initialize() == LDAP_SUCCESS ) {
-		/* monitoring in back-bdb is on by default */
-		SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_MONITORING;
-	}
-
-#ifdef BDB_MONITOR_IDX
-	bdb->bi_idx = NULL;
-	ldap_pvt_thread_mutex_init( &bdb->bi_idx_mutex );
-#endif /* BDB_MONITOR_IDX */
-
-	return 0;
-}
-
-/*
- * call from within bdb_db_open()
- */
-int
-bdb_monitor_db_open( BackendDB *be )
-{
-	struct bdb_info		*bdb = (struct bdb_info *) be->be_private;
-	Attribute		*a, *next;
-	monitor_callback_t	*cb = NULL;
-	int			rc = 0;
-	BackendInfo		*mi;
-	monitor_extra_t		*mbe;
-
-	if ( !SLAP_DBMONITORING( be ) ) {
-		return 0;
-	}
-
-	mi = backend_info( "monitor" );
-	if ( !mi || !mi->bi_extra ) {
-		SLAP_DBFLAGS( be ) ^= SLAP_DBFLAG_MONITORING;
-		return 0;
-	}
-	mbe = mi->bi_extra;
-
-	/* don't bother if monitor is not configured */
-	if ( !mbe->is_configured() ) {
-		static int warning = 0;
-
-		if ( warning++ == 0 ) {
-			Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_monitor_db_open)
-				": monitoring disabled; "
-				"configure monitor database to enable\n",
-				0, 0, 0 );
-		}
-
-		return 0;
-	}
-
-	/* alloc as many as required (plus 1 for objectClass) */
-	a = attrs_alloc( 1 + 4 );
-	if ( a == NULL ) {
-		rc = 1;
-		goto cleanup;
-	}
-
-	a->a_desc = slap_schema.si_ad_objectClass;
-	attr_valadd( a, &oc_olmBDBDatabase->soc_cname, NULL, 1 );
-	next = a->a_next;
-
-	{
-		struct berval	bv = BER_BVC( "0" );
-
-		next->a_desc = ad_olmBDBEntryCache;
-		attr_valadd( next, &bv, NULL, 1 );
-		next = next->a_next;
-
-		next->a_desc = ad_olmBDBDNCache;
-		attr_valadd( next, &bv, NULL, 1 );
-		next = next->a_next;
-
-		next->a_desc = ad_olmBDBIDLCache;
-		attr_valadd( next, &bv, NULL, 1 );
-		next = next->a_next;
-	}
-
-	{
-		struct berval	bv, nbv;
-		ber_len_t	pathlen = 0, len = 0;
-		char		path[ MAXPATHLEN ] = { '\0' };
-		char		*fname = bdb->bi_dbenv_home,
-				*ptr;
-
-		len = strlen( fname );
-		if ( fname[ 0 ] != '/' ) {
-			/* get full path name */
-			getcwd( path, sizeof( path ) );
-			pathlen = strlen( path );
-
-			if ( fname[ 0 ] == '.' && fname[ 1 ] == '/' ) {
-				fname += 2;
-				len -= 2;
-			}
-		}
-
-		bv.bv_len = pathlen + STRLENOF( "/" ) + len;
-		ptr = bv.bv_val = ch_malloc( bv.bv_len + STRLENOF( "/" ) + 1 );
-		if ( pathlen ) {
-			ptr = lutil_strncopy( ptr, path, pathlen );
-			ptr[ 0 ] = '/';
-			ptr++;
-		}
-		ptr = lutil_strncopy( ptr, fname, len );
-		if ( ptr[ -1 ] != '/' ) {
-			ptr[ 0 ] = '/';
-			ptr++;
-		}
-		ptr[ 0 ] = '\0';
-		
-		attr_normalize_one( ad_olmDbDirectory, &bv, &nbv, NULL );
-
-		next->a_desc = ad_olmDbDirectory;
-		next->a_vals = ch_calloc( sizeof( struct berval ), 2 );
-		next->a_vals[ 0 ] = bv;
-		next->a_numvals = 1;
-
-		if ( BER_BVISNULL( &nbv ) ) {
-			next->a_nvals = next->a_vals;
-
-		} else {
-			next->a_nvals = ch_calloc( sizeof( struct berval ), 2 );
-			next->a_nvals[ 0 ] = nbv;
-		}
-
-		next = next->a_next;
-	}
-
-	cb = ch_calloc( sizeof( monitor_callback_t ), 1 );
-	cb->mc_update = bdb_monitor_update;
-#if 0	/* uncomment if required */
-	cb->mc_modify = bdb_monitor_modify;
-#endif
-	cb->mc_free = bdb_monitor_free;
-	cb->mc_private = (void *)bdb;
-
-	/* make sure the database is registered; then add monitor attributes */
-	rc = mbe->register_database( be, &bdb->bi_monitor.bdm_ndn );
-	if ( rc == 0 ) {
-		rc = mbe->register_entry_attrs( &bdb->bi_monitor.bdm_ndn, a, cb,
-			NULL, 0, NULL );
-	}
-
-cleanup:;
-	if ( rc != 0 ) {
-		if ( cb != NULL ) {
-			ch_free( cb );
-			cb = NULL;
-		}
-
-		if ( a != NULL ) {
-			attrs_free( a );
-			a = NULL;
-		}
-	}
-
-	/* store for cleanup */
-	bdb->bi_monitor.bdm_cb = (void *)cb;
-
-	/* we don't need to keep track of the attributes, because
-	 * bdb_monitor_free() takes care of everything */
-	if ( a != NULL ) {
-		attrs_free( a );
-	}
-
-	return rc;
-}
-
-/*
- * call from within bdb_db_close()
- */
-int
-bdb_monitor_db_close( BackendDB *be )
-{
-	struct bdb_info		*bdb = (struct bdb_info *) be->be_private;
-
-	if ( !BER_BVISNULL( &bdb->bi_monitor.bdm_ndn ) ) {
-		BackendInfo		*mi = backend_info( "monitor" );
-		monitor_extra_t		*mbe;
-
-		if ( mi && &mi->bi_extra ) {
-			mbe = mi->bi_extra;
-			mbe->unregister_entry_callback( &bdb->bi_monitor.bdm_ndn,
-				(monitor_callback_t *)bdb->bi_monitor.bdm_cb,
-				NULL, 0, NULL );
-		}
-
-		memset( &bdb->bi_monitor, 0, sizeof( bdb->bi_monitor ) );
-	}
-
-	return 0;
-}
-
-/*
- * call from within bdb_db_destroy()
- */
-int
-bdb_monitor_db_destroy( BackendDB *be )
-{
-#ifdef BDB_MONITOR_IDX
-	struct bdb_info		*bdb = (struct bdb_info *) be->be_private;
-
-	/* TODO: free tree */
-	ldap_pvt_thread_mutex_destroy( &bdb->bi_idx_mutex );
-	avl_free( bdb->bi_idx, ch_free );
-#endif /* BDB_MONITOR_IDX */
-
-	return 0;
-}
-
-#ifdef BDB_MONITOR_IDX
-
-#define BDB_MONITOR_IDX_TYPES	(4)
-
-typedef struct monitor_idx_t monitor_idx_t;
-
-struct monitor_idx_t {
-	AttributeDescription	*idx_ad;
-	unsigned long		idx_count[BDB_MONITOR_IDX_TYPES];
-};
-
-static int
-bdb_monitor_bitmask2key( slap_mask_t bitmask )
-{
-	int	key;
-
-	for ( key = 0; key < 8 * (int)sizeof(slap_mask_t) && !( bitmask & 0x1U );
-			key++ )
-		bitmask >>= 1;
-
-	return key;
-}
-
-static struct berval idxbv[] = {
-	BER_BVC( "present=" ),
-	BER_BVC( "equality=" ),
-	BER_BVC( "approx=" ),
-	BER_BVC( "substr=" ),
-	BER_BVNULL
-};
-
-static ber_len_t
-bdb_monitor_idx2len( monitor_idx_t *idx )
-{
-	int		i;
-	ber_len_t	len = 0;
-
-	for ( i = 0; i < BDB_MONITOR_IDX_TYPES; i++ ) {
-		if ( idx->idx_count[ i ] != 0 ) {
-			len += idxbv[i].bv_len;
-		}
-	}
-
-	return len;
-}
-
-static int
-monitor_idx_cmp( const void *p1, const void *p2 )
-{
-	const monitor_idx_t	*idx1 = (const monitor_idx_t *)p1;
-	const monitor_idx_t	*idx2 = (const monitor_idx_t *)p2;
-
-	return SLAP_PTRCMP( idx1->idx_ad, idx2->idx_ad );
-}
-
-static int
-monitor_idx_dup( void *p1, void *p2 )
-{
-	monitor_idx_t	*idx1 = (monitor_idx_t *)p1;
-	monitor_idx_t	*idx2 = (monitor_idx_t *)p2;
-
-	return SLAP_PTRCMP( idx1->idx_ad, idx2->idx_ad ) == 0 ? -1 : 0;
-}
-
-int
-bdb_monitor_idx_add(
-	struct bdb_info		*bdb,
-	AttributeDescription	*desc,
-	slap_mask_t		type )
-{
-	monitor_idx_t		idx_dummy = { 0 },
-				*idx;
-	int			rc = 0, key;
-
-	idx_dummy.idx_ad = desc;
-	key = bdb_monitor_bitmask2key( type ) - 1;
-	if ( key >= BDB_MONITOR_IDX_TYPES ) {
-		/* invalid index type */
-		return -1;
-	}
-
-	ldap_pvt_thread_mutex_lock( &bdb->bi_idx_mutex );
-
-	idx = (monitor_idx_t *)avl_find( bdb->bi_idx,
-		(caddr_t)&idx_dummy, monitor_idx_cmp );
-	if ( idx == NULL ) {
-		idx = (monitor_idx_t *)ch_calloc( sizeof( monitor_idx_t ), 1 );
-		idx->idx_ad = desc;
-		idx->idx_count[ key ] = 1;
-
-		switch ( avl_insert( &bdb->bi_idx, (caddr_t)idx, 
-			monitor_idx_cmp, monitor_idx_dup ) )
-		{
-		case 0:
-			break;
-
-		default:
-			ch_free( idx );
-			rc = -1;
-		}
-
-	} else {
-		idx->idx_count[ key ]++;
-	}
-
-	ldap_pvt_thread_mutex_unlock( &bdb->bi_idx_mutex );
-
-	return rc;
-}
-
-static int
-bdb_monitor_idx_apply( void *v_idx, void *v_valp )
-{
-	monitor_idx_t	*idx = (monitor_idx_t *)v_idx;
-	BerVarray	*valp = (BerVarray *)v_valp;
-
-	struct berval	bv;
-	char		*ptr;
-	char		count_buf[ BDB_MONITOR_IDX_TYPES ][ SLAP_TEXT_BUFLEN ];
-	ber_len_t	count_len[ BDB_MONITOR_IDX_TYPES ],
-			idx_len;
-	int		i, num = 0;
-
-	idx_len = bdb_monitor_idx2len( idx );
-
-	bv.bv_len = 0;
-	for ( i = 0; i < BDB_MONITOR_IDX_TYPES; i++ ) {
-		if ( idx->idx_count[ i ] == 0 ) {
-			continue;
-		}
-
-		count_len[ i ] = snprintf( count_buf[ i ],
-			sizeof( count_buf[ i ] ), "%lu", idx->idx_count[ i ] );
-		bv.bv_len += count_len[ i ];
-		num++;
-	}
-
-	bv.bv_len += idx->idx_ad->ad_cname.bv_len
-		+ num
-		+ idx_len;
-	ptr = bv.bv_val = ch_malloc( bv.bv_len + 1 );
-	ptr = lutil_strcopy( ptr, idx->idx_ad->ad_cname.bv_val );
-	for ( i = 0; i < BDB_MONITOR_IDX_TYPES; i++ ) {
-		if ( idx->idx_count[ i ] == 0 ) {
-			continue;
-		}
-
-		ptr[ 0 ] = '#';
-		++ptr;
-		ptr = lutil_strcopy( ptr, idxbv[ i ].bv_val );
-		ptr = lutil_strcopy( ptr, count_buf[ i ] );
-	}
-
-	ber_bvarray_add( valp, &bv );
-
-	return 0;
-}
-
-static int
-bdb_monitor_idx_entry_add(
-	struct bdb_info	*bdb,
-	Entry		*e )
-{
-	BerVarray	vals = NULL;
-	Attribute	*a;
-
-	a = attr_find( e->e_attrs, ad_olmDbNotIndexed );
-
-	ldap_pvt_thread_mutex_lock( &bdb->bi_idx_mutex );
-
-	avl_apply( bdb->bi_idx, bdb_monitor_idx_apply,
-		&vals, -1, AVL_INORDER );
-
-	ldap_pvt_thread_mutex_unlock( &bdb->bi_idx_mutex );
-
-	if ( vals != NULL ) {
-		if ( a != NULL ) {
-			assert( a->a_nvals == a->a_vals );
-
-			ber_bvarray_free( a->a_vals );
-
-		} else {
-			Attribute	**ap;
-
-			for ( ap = &e->e_attrs; *ap != NULL; ap = &(*ap)->a_next )
-				;
-			*ap = attr_alloc( ad_olmDbNotIndexed );
-			a = *ap;
-		}
-		a->a_vals = vals;
-		a->a_nvals = a->a_vals;
-	}
-
-	return 0;
-}
-
-#endif /* BDB_MONITOR_IDX */
diff --git a/servers/slapd/back-bdb/nextid.c b/servers/slapd/back-bdb/nextid.c
deleted file mode 100644
index 480b80e..0000000
--- a/servers/slapd/back-bdb/nextid.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/* init.c - initialize bdb backend */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "back-bdb.h"
-
-int bdb_next_id( BackendDB *be, ID *out )
-{
-	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
-
-	ldap_pvt_thread_mutex_lock( &bdb->bi_lastid_mutex );
-	*out = ++bdb->bi_lastid;
-	ldap_pvt_thread_mutex_unlock( &bdb->bi_lastid_mutex );
-
-	return 0;
-}
-
-int bdb_last_id( BackendDB *be, DB_TXN *tid )
-{
-	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
-	int rc;
-	ID id = 0;
-	unsigned char idbuf[sizeof(ID)];
-	DBT key, data;
-	DBC *cursor;
-
-	DBTzero( &key );
-	key.flags = DB_DBT_USERMEM;
-	key.data = (char *) idbuf;
-	key.ulen = sizeof( idbuf );
-
-	DBTzero( &data );
-	data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
-
-	/* Get a read cursor */
-	rc = bdb->bi_id2entry->bdi_db->cursor( bdb->bi_id2entry->bdi_db,
-		tid, &cursor, 0 );
-
-	if (rc == 0) {
-		rc = cursor->c_get(cursor, &key, &data, DB_LAST);
-		cursor->c_close(cursor);
-	}
-
-	switch(rc) {
-	case DB_NOTFOUND:
-		rc = 0;
-		break;
-	case 0:
-		BDB_DISK2ID( idbuf, &id );
-		break;
-
-	default:
-		Debug( LDAP_DEBUG_ANY,
-			"=> bdb_last_id: get failed: %s (%d)\n",
-			db_strerror(rc), rc, 0 );
-		goto done;
-	}
-
-	bdb->bi_lastid = id;
-
-done:
-	return rc;
-}
diff --git a/servers/slapd/back-bdb/operational.c b/servers/slapd/back-bdb/operational.c
deleted file mode 100644
index 5f21abe..0000000
--- a/servers/slapd/back-bdb/operational.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/* operational.c - bdb backend operational attributes function */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/string.h>
-#include <ac/socket.h>
-
-#include "slap.h"
-#include "back-bdb.h"
-
-/*
- * sets *hasSubordinates to LDAP_COMPARE_TRUE/LDAP_COMPARE_FALSE
- * if the entry has children or not.
- */
-int
-bdb_hasSubordinates(
-	Operation	*op,
-	Entry		*e,
-	int		*hasSubordinates )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	struct bdb_op_info	*opinfo;
-	OpExtra *oex;
-	DB_TXN		*rtxn;
-	int		rc;
-	int		release = 0;
-	
-	assert( e != NULL );
-
-	/* NOTE: this should never happen, but it actually happens
-	 * when using back-relay; until we find a better way to
-	 * preserve entry's private information while rewriting it,
-	 * let's disable the hasSubordinate feature for back-relay.
-	 */
-	if ( BEI( e ) == NULL ) {
-		Entry *ee = NULL;
-		rc = be_entry_get_rw( op, &e->e_nname, NULL, NULL, 0, &ee );
-		if ( rc != LDAP_SUCCESS || ee == NULL ) {
-			rc = LDAP_OTHER;
-			goto done;
-		}
-		e = ee;
-		release = 1;
-		if ( BEI( ee ) == NULL ) {
-			rc = LDAP_OTHER;
-			goto done;
-		}
-	}
-
-	/* Check for a txn in a parent op, otherwise use reader txn */
-	LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
-		if ( oex->oe_key == bdb )
-			break;
-	}
-	opinfo = (struct bdb_op_info *) oex;
-	if ( opinfo && opinfo->boi_txn ) {
-		rtxn = opinfo->boi_txn;
-	} else {
-		rc = bdb_reader_get(op, bdb->bi_dbenv, &rtxn);
-		if ( rc ) {
-			rc = LDAP_OTHER;
-			goto done;
-		}
-	}
-
-retry:
-	/* FIXME: we can no longer assume the entry's e_private
-	 * field is correctly populated; so we need to reacquire
-	 * it with reader lock */
-	rc = bdb_cache_children( op, rtxn, e );
-
-	switch( rc ) {
-	case DB_LOCK_DEADLOCK:
-	case DB_LOCK_NOTGRANTED:
-		goto retry;
-
-	case 0:
-		*hasSubordinates = LDAP_COMPARE_TRUE;
-		break;
-
-	case DB_NOTFOUND:
-		*hasSubordinates = LDAP_COMPARE_FALSE;
-		rc = LDAP_SUCCESS;
-		break;
-
-	default:
-		Debug(LDAP_DEBUG_ARGS, 
-			"<=- " LDAP_XSTRING(bdb_hasSubordinates)
-			": has_children failed: %s (%d)\n", 
-			db_strerror(rc), rc, 0 );
-		rc = LDAP_OTHER;
-	}
-
-done:;
-	if ( release && e != NULL ) be_entry_release_r( op, e );
-	return rc;
-}
-
-/*
- * sets the supported operational attributes (if required)
- */
-int
-bdb_operational(
-	Operation	*op,
-	SlapReply	*rs )
-{
-	Attribute	**ap;
-
-	assert( rs->sr_entry != NULL );
-
-	for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next ) {
-		if ( (*ap)->a_desc == slap_schema.si_ad_hasSubordinates ) {
-			break;
-		}
-	}
-
-	if ( *ap == NULL &&
-		attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_hasSubordinates ) == NULL &&
-		( SLAP_OPATTRS( rs->sr_attr_flags ) ||
-			ad_inlist( slap_schema.si_ad_hasSubordinates, rs->sr_attrs ) ) )
-	{
-		int	hasSubordinates, rc;
-
-		rc = bdb_hasSubordinates( op, rs->sr_entry, &hasSubordinates );
-		if ( rc == LDAP_SUCCESS ) {
-			*ap = slap_operational_hasSubordinate( hasSubordinates == LDAP_COMPARE_TRUE );
-			assert( *ap != NULL );
-
-			ap = &(*ap)->a_next;
-		}
-	}
-
-	return LDAP_SUCCESS;
-}
-
diff --git a/servers/slapd/back-bdb/proto-bdb.h b/servers/slapd/back-bdb/proto-bdb.h
deleted file mode 100644
index 34b8ce0..0000000
--- a/servers/slapd/back-bdb/proto-bdb.h
+++ /dev/null
@@ -1,678 +0,0 @@
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#ifndef _PROTO_BDB_H
-#define _PROTO_BDB_H
-
-LDAP_BEGIN_DECL
-
-#ifdef BDB_HIER
-#define	BDB_SYMBOL(x)	LDAP_CONCAT(hdb_,x)
-#define BDB_UCTYPE	"HDB"
-#else
-#define BDB_SYMBOL(x)	LDAP_CONCAT(bdb_,x)
-#define BDB_UCTYPE	"BDB"
-#endif
-
-/*
- * attr.c
- */
-
-#define bdb_attr_mask				BDB_SYMBOL(attr_mask)
-#define bdb_attr_flush				BDB_SYMBOL(attr_flush)
-#define bdb_attr_slot				BDB_SYMBOL(attr_slot)
-#define bdb_attr_index_config		BDB_SYMBOL(attr_index_config)
-#define bdb_attr_index_destroy		BDB_SYMBOL(attr_index_destroy)
-#define bdb_attr_index_free			BDB_SYMBOL(attr_index_free)
-#define bdb_attr_index_unparse		BDB_SYMBOL(attr_index_unparse)
-#define bdb_attr_info_free			BDB_SYMBOL(attr_info_free)
-
-AttrInfo *bdb_attr_mask( struct bdb_info *bdb,
-	AttributeDescription *desc );
-
-void bdb_attr_flush( struct bdb_info *bdb );
-
-int bdb_attr_slot( struct bdb_info *bdb,
-	AttributeDescription *desc, int *insert );
-
-int bdb_attr_index_config LDAP_P(( struct bdb_info *bdb,
-	const char *fname, int lineno,
-	int argc, char **argv, struct config_reply_s *cr ));
-
-void bdb_attr_index_unparse LDAP_P(( struct bdb_info *bdb, BerVarray *bva ));
-void bdb_attr_index_destroy LDAP_P(( struct bdb_info *bdb ));
-void bdb_attr_index_free LDAP_P(( struct bdb_info *bdb,
-	AttributeDescription *ad ));
-
-void bdb_attr_info_free( AttrInfo *ai );
-
-/*
- * config.c
- */
-
-#define bdb_back_init_cf				BDB_SYMBOL(back_init_cf)
-
-int bdb_back_init_cf( BackendInfo *bi );
-
-/*
- * dbcache.c
- */
-#define bdb_db_cache				BDB_SYMBOL(db_cache)
-#define bdb_db_findsize				BDB_SYMBOL(db_findsize)
-
-int
-bdb_db_cache(
-    Backend	*be,
-    struct berval *name,
-	DB **db );
-
-int
-bdb_db_findsize(
-	struct bdb_info *bdb,
-	struct berval *name );
-
-/*
- * dn2entry.c
- */
-#define bdb_dn2entry				BDB_SYMBOL(dn2entry)
-
-int bdb_dn2entry LDAP_P(( Operation *op, DB_TXN *tid,
-	struct berval *dn, EntryInfo **e, int matched,
-	DB_LOCK *lock ));
-
-/*
- * dn2id.c
- */
-#define bdb_dn2id					BDB_SYMBOL(dn2id)
-#define bdb_dn2id_add				BDB_SYMBOL(dn2id_add)
-#define bdb_dn2id_delete			BDB_SYMBOL(dn2id_delete)
-#define bdb_dn2id_children			BDB_SYMBOL(dn2id_children)
-#define bdb_dn2idl					BDB_SYMBOL(dn2idl)
-
-int bdb_dn2id(
-	Operation *op,
-	struct berval *dn,
-	EntryInfo *ei,
-	DB_TXN *txn,
-	DBC **cursor );
-
-int bdb_dn2id_add(
-	Operation *op,
-	DB_TXN *tid,
-	EntryInfo *eip,
-	Entry *e );
-
-int bdb_dn2id_delete(
-	Operation *op,
-	DB_TXN *tid,
-	EntryInfo *eip,
-	Entry *e );
-
-int bdb_dn2id_children(
-	Operation *op,
-	DB_TXN *tid,
-	Entry *e );
-
-int bdb_dn2idl(
-	Operation *op,
-	DB_TXN *txn,
-	struct berval *ndn,
-	EntryInfo *ei,
-	ID *ids,
-	ID *stack );
-
-#ifdef BDB_HIER
-#define bdb_dn2id_parent			BDB_SYMBOL(dn2id_parent)
-#define bdb_dup_compare				BDB_SYMBOL(dup_compare)
-#define bdb_fix_dn					BDB_SYMBOL(fix_dn)
-
-int bdb_dn2id_parent(
-	Operation *op,
-	DB_TXN *txn,
-	EntryInfo *ei,
-	ID *idp );
-
-int bdb_dup_compare(
-	DB *db,
-	const DBT *usrkey,
-	const DBT *curkey );
-
-int bdb_fix_dn( Entry *e, int checkit );
-#endif
-
-
-/*
- * error.c
- */
-#define bdb_errcall					BDB_SYMBOL(errcall)
-
-#if DB_VERSION_FULL < 0x04030000
-void bdb_errcall( const char *pfx, char * msg );
-#else
-#define bdb_msgcall					BDB_SYMBOL(msgcall)
-void bdb_errcall( const DB_ENV *env, const char *pfx, const char * msg );
-void bdb_msgcall( const DB_ENV *env, const char * msg );
-#endif
-
-#ifdef HAVE_EBCDIC
-#define ebcdic_dberror				BDB_SYMBOL(ebcdic_dberror)
-
-char *ebcdic_dberror( int rc );
-#define db_strerror(x)	ebcdic_dberror(x)
-#endif
-
-/*
- * filterentry.c
- */
-#define bdb_filter_candidates		BDB_SYMBOL(filter_candidates)
-
-int bdb_filter_candidates(
-	Operation *op,
-	DB_TXN *txn,
-	Filter	*f,
-	ID *ids,
-	ID *tmp,
-	ID *stack );
-
-/*
- * id2entry.c
- */
-#define bdb_id2entry				BDB_SYMBOL(id2entry)
-#define bdb_id2entry_add			BDB_SYMBOL(id2entry_add)
-#define bdb_id2entry_update			BDB_SYMBOL(id2entry_update)
-#define bdb_id2entry_delete			BDB_SYMBOL(id2entry_delete)
-
-int bdb_id2entry_add(
-	BackendDB *be,
-	DB_TXN *tid,
-	Entry *e );
-
-int bdb_id2entry_update(
-	BackendDB *be,
-	DB_TXN *tid,
-	Entry *e );
-
-int bdb_id2entry_delete(
-	BackendDB *be,
-	DB_TXN *tid,
-	Entry *e);
-
-#ifdef SLAP_ZONE_ALLOC
-#else
-int bdb_id2entry(
-	BackendDB *be,
-	DB_TXN *tid,
-	ID id,
-	Entry **e);
-#endif
-
-#define bdb_entry_free				BDB_SYMBOL(entry_free)
-#define bdb_entry_return			BDB_SYMBOL(entry_return)
-#define bdb_entry_release			BDB_SYMBOL(entry_release)
-#define bdb_entry_get				BDB_SYMBOL(entry_get)
-
-void bdb_entry_free ( Entry *e );
-#ifdef SLAP_ZONE_ALLOC
-int bdb_entry_return( struct bdb_info *bdb, Entry *e, int seqno );
-#else
-int bdb_entry_return( Entry *e );
-#endif
-BI_entry_release_rw bdb_entry_release;
-BI_entry_get_rw bdb_entry_get;
-
-
-/*
- * idl.c
- */
-
-#define bdb_idl_cache_get			BDB_SYMBOL(idl_cache_get)
-#define bdb_idl_cache_put			BDB_SYMBOL(idl_cache_put)
-#define bdb_idl_cache_del			BDB_SYMBOL(idl_cache_del)
-#define bdb_idl_cache_add_id		BDB_SYMBOL(idl_cache_add_id)
-#define bdb_idl_cache_del_id		BDB_SYMBOL(idl_cache_del_id)
-
-int bdb_idl_cache_get(
-	struct bdb_info *bdb,
-	DB *db,
-	DBT *key,
-	ID *ids );
-
-void
-bdb_idl_cache_put(
-	struct bdb_info	*bdb,
-	DB		*db,
-	DBT		*key,
-	ID		*ids,
-	int		rc );
-
-void
-bdb_idl_cache_del(
-	struct bdb_info	*bdb,
-	DB		*db,
-	DBT		*key );
-
-void
-bdb_idl_cache_add_id(
-	struct bdb_info	*bdb,
-	DB		*db,
-	DBT		*key,
-	ID		id );
-
-void
-bdb_idl_cache_del_id(
-	struct bdb_info	*bdb,
-	DB		*db,
-	DBT		*key,
-	ID		id );
-
-#define bdb_idl_first				BDB_SYMBOL(idl_first)
-#define bdb_idl_next				BDB_SYMBOL(idl_next)
-#define bdb_idl_search				BDB_SYMBOL(idl_search)
-#define bdb_idl_insert				BDB_SYMBOL(idl_insert)
-#define bdb_idl_delete				BDB_SYMBOL(idl_delete)
-#define bdb_idl_intersection		BDB_SYMBOL(idl_intersection)
-#define bdb_idl_union				BDB_SYMBOL(idl_union)
-#define bdb_idl_sort				BDB_SYMBOL(idl_sort)
-#define bdb_idl_append				BDB_SYMBOL(idl_append)
-#define bdb_idl_append_one			BDB_SYMBOL(idl_append_one)
-
-#define bdb_idl_fetch_key			BDB_SYMBOL(idl_fetch_key)
-#define bdb_idl_insert_key			BDB_SYMBOL(idl_insert_key)
-#define bdb_idl_delete_key			BDB_SYMBOL(idl_delete_key)
-
-unsigned bdb_idl_search( ID *ids, ID id );
-
-int bdb_idl_fetch_key(
-	BackendDB	*be,
-	DB			*db,
-	DB_TXN		*txn,
-	DBT			*key,
-	ID			*ids,
-	DBC                     **saved_cursor,
-	int                     get_flag );
-
-int bdb_idl_insert( ID *ids, ID id );
-int bdb_idl_delete( ID *ids, ID id );
-
-int bdb_idl_insert_key(
-	BackendDB *be,
-	DB *db,
-	DB_TXN *txn,
-	DBT *key,
-	ID id );
-
-int bdb_idl_delete_key(
-	BackendDB *be,
-	DB *db,
-	DB_TXN *txn,
-	DBT *key,
-	ID id );
-
-int
-bdb_idl_intersection(
-	ID *a,
-	ID *b );
-
-int
-bdb_idl_union(
-	ID *a,
-	ID *b );
-
-ID bdb_idl_first( ID *ids, ID *cursor );
-ID bdb_idl_next( ID *ids, ID *cursor );
-
-void bdb_idl_sort( ID *ids, ID *tmp );
-int bdb_idl_append( ID *a, ID *b );
-int bdb_idl_append_one( ID *ids, ID id );
-
-
-/*
- * index.c
- */
-#define bdb_index_mask				BDB_SYMBOL(index_mask)
-#define bdb_index_param				BDB_SYMBOL(index_param)
-#define bdb_index_values			BDB_SYMBOL(index_values)
-#define bdb_index_entry				BDB_SYMBOL(index_entry)
-#define bdb_index_recset			BDB_SYMBOL(index_recset)
-#define bdb_index_recrun			BDB_SYMBOL(index_recrun)
-
-extern AttrInfo *
-bdb_index_mask LDAP_P((
-	Backend *be,
-	AttributeDescription *desc,
-	struct berval *name ));
-
-extern int
-bdb_index_param LDAP_P((
-	Backend *be,
-	AttributeDescription *desc,
-	int ftype,
-	DB **db,
-	slap_mask_t *mask,
-	struct berval *prefix ));
-
-extern int
-bdb_index_values LDAP_P((
-	Operation *op,
-	DB_TXN *txn,
-	AttributeDescription *desc,
-	BerVarray vals,
-	ID id,
-	int opid ));
-
-extern int
-bdb_index_recset LDAP_P((
-	struct bdb_info *bdb,
-	Attribute *a,
-	AttributeType *type,
-	struct berval *tags,
-	IndexRec *ir ));
-
-extern int
-bdb_index_recrun LDAP_P((
-	Operation *op,
-	struct bdb_info *bdb,
-	IndexRec *ir,
-	ID id,
-	int base ));
-
-int bdb_index_entry LDAP_P(( Operation *op, DB_TXN *t, int r, Entry *e ));
-
-#define bdb_index_entry_add(op,t,e) \
-	bdb_index_entry((op),(t),SLAP_INDEX_ADD_OP,(e))
-#define bdb_index_entry_del(op,t,e) \
-	bdb_index_entry((op),(t),SLAP_INDEX_DELETE_OP,(e))
-
-/*
- * key.c
- */
-#define bdb_key_read				BDB_SYMBOL(key_read)
-#define bdb_key_change				BDB_SYMBOL(key_change)
-
-extern int
-bdb_key_read(
-    Backend	*be,
-	DB *db,
-	DB_TXN *txn,
-    struct berval *k,
-	ID *ids,
-    DBC **saved_cursor,
-        int get_flags );
-
-extern int
-bdb_key_change(
-    Backend	 *be,
-    DB *db,
-	DB_TXN *txn,
-    struct berval *k,
-    ID id,
-    int	op );
-	
-/*
- * nextid.c
- */
-#define bdb_next_id					BDB_SYMBOL(next_id)
-#define bdb_last_id					BDB_SYMBOL(last_id)
-
-int bdb_next_id( BackendDB *be, ID *id );
-int bdb_last_id( BackendDB *be, DB_TXN *tid );
-
-/*
- * modify.c
- */
-#define bdb_modify_internal			BDB_SYMBOL(modify_internal)
-
-int bdb_modify_internal(
-	Operation *op,
-	DB_TXN *tid,
-	Modifications *modlist,
-	Entry *e,
-	const char **text,
-	char *textbuf,
-	size_t textlen );
-
-/*
- * monitor.c
- */
-
-#define bdb_monitor_db_init	BDB_SYMBOL(monitor_db_init)
-#define bdb_monitor_db_open	BDB_SYMBOL(monitor_db_open)
-#define bdb_monitor_db_close	BDB_SYMBOL(monitor_db_close)
-#define bdb_monitor_db_destroy	BDB_SYMBOL(monitor_db_destroy)
-
-int bdb_monitor_db_init( BackendDB *be );
-int bdb_monitor_db_open( BackendDB *be );
-int bdb_monitor_db_close( BackendDB *be );
-int bdb_monitor_db_destroy( BackendDB *be );
-
-#ifdef BDB_MONITOR_IDX
-#define bdb_monitor_idx_add	BDB_SYMBOL(monitor_idx_add)
-int
-bdb_monitor_idx_add(
-	struct bdb_info		*bdb,
-	AttributeDescription	*desc,
-	slap_mask_t		type );
-#endif /* BDB_MONITOR_IDX */
-
-/*
- * cache.c
- */
-#define bdb_cache_entry_db_unlock	BDB_SYMBOL(cache_entry_db_unlock)
-#define bdb_cache_return_entry_rw	BDB_SYMBOL(cache_return_entry_rw)
-
-#define	bdb_cache_entryinfo_lock(e) \
-	ldap_pvt_thread_mutex_lock( &(e)->bei_kids_mutex )
-#define	bdb_cache_entryinfo_unlock(e) \
-	ldap_pvt_thread_mutex_unlock( &(e)->bei_kids_mutex )
-#define	bdb_cache_entryinfo_trylock(e) \
-	ldap_pvt_thread_mutex_trylock( &(e)->bei_kids_mutex )
-
-/* What a mess. Hopefully the current cache scheme will stabilize
- * and we can trim out all of this stuff.
- */
-void bdb_cache_return_entry_rw( struct bdb_info *bdb, Entry *e,
-	int rw, DB_LOCK *lock );
-#define bdb_cache_return_entry_r(bdb, e, l) \
-	bdb_cache_return_entry_rw((bdb), (e), 0, (l))
-#define bdb_cache_return_entry_w(bdb, e, l) \
-	bdb_cache_return_entry_rw((bdb), (e), 1, (l))
-#if 0
-void bdb_unlocked_cache_return_entry_rw( struct bdb_info *bdb, Entry *e, int rw );
-#else
-#define	bdb_unlocked_cache_return_entry_rw( a, b, c )	((void)0)
-#endif
-#define bdb_unlocked_cache_return_entry_r( c, e ) \
-	bdb_unlocked_cache_return_entry_rw((c), (e), 0)
-#define bdb_unlocked_cache_return_entry_w( c, e ) \
-	bdb_unlocked_cache_return_entry_rw((c), (e), 1)
-
-#define bdb_cache_add				BDB_SYMBOL(cache_add)
-#define bdb_cache_children			BDB_SYMBOL(cache_children)
-#define bdb_cache_delete			BDB_SYMBOL(cache_delete)
-#define bdb_cache_delete_cleanup	BDB_SYMBOL(cache_delete_cleanup)
-#define bdb_cache_find_id			BDB_SYMBOL(cache_find_id)
-#define bdb_cache_find_ndn			BDB_SYMBOL(cache_find_ndn)
-#define bdb_cache_find_parent		BDB_SYMBOL(cache_find_parent)
-#define bdb_cache_modify			BDB_SYMBOL(cache_modify)
-#define bdb_cache_modrdn			BDB_SYMBOL(cache_modrdn)
-#define bdb_cache_release_all		BDB_SYMBOL(cache_release_all)
-#define bdb_cache_delete_entry		BDB_SYMBOL(cache_delete_entry)
-#define bdb_cache_deref				BDB_SYMBOL(cache_deref)
-
-int bdb_cache_children(
-	Operation *op,
-	DB_TXN *txn,
-	Entry *e
-);
-int bdb_cache_add(
-	struct bdb_info *bdb,
-	EntryInfo *pei,
-	Entry   *e,
-	struct berval *nrdn,
-	DB_TXN *txn,
-	DB_LOCK *lock
-);
-int bdb_cache_modrdn(
-	struct bdb_info *bdb,
-	Entry	*e,
-	struct berval *nrdn,
-	Entry	*new,
-	EntryInfo *ein,
-	DB_TXN *txn,
-	DB_LOCK *lock
-);
-int bdb_cache_modify(
-	struct bdb_info *bdb,
-	Entry *e,
-	Attribute *newAttrs,
-	DB_TXN *txn,
-	DB_LOCK *lock
-);
-int bdb_cache_find_ndn(
-	Operation *op,
-	DB_TXN *txn,
-	struct berval   *ndn,
-	EntryInfo	**res
-);
-
-#define	ID_LOCKED	1
-#define	ID_NOCACHE	2
-#define	ID_NOENTRY	4
-#define	ID_CHKPURGE	8
-int bdb_cache_find_id(
-	Operation *op,
-	DB_TXN	*tid,
-	ID		id,
-	EntryInfo **eip,
-	int	flag,
-	DB_LOCK		*lock
-);
-int
-bdb_cache_find_parent(
-	Operation *op,
-	DB_TXN *txn,
-	ID id,
-	EntryInfo **res
-);
-int bdb_cache_delete(
-	struct bdb_info *bdb,
-	Entry	*e,
-	DB_TXN *txn,
-	DB_LOCK	*lock
-);
-void bdb_cache_delete_cleanup(
-	Cache	*cache,
-	EntryInfo *ei
-);
-void bdb_cache_release_all( Cache *cache );
-void bdb_cache_deref( EntryInfo *ei );
-
-#ifdef BDB_HIER
-int hdb_cache_load(
-	struct bdb_info *bdb,
-	EntryInfo *ei,
-	EntryInfo **res
-);
-#endif
-
-#define bdb_cache_entry_db_relock		BDB_SYMBOL(cache_entry_db_relock)
-int bdb_cache_entry_db_relock(
-	struct bdb_info *bdb,
-	DB_TXN *txn,
-	EntryInfo *ei,
-	int rw,
-	int tryOnly,
-	DB_LOCK *lock );
-
-int bdb_cache_entry_db_unlock(
-	struct bdb_info *bdb,
-	DB_LOCK *lock );
-
-#define bdb_reader_get				BDB_SYMBOL(reader_get)
-#define bdb_reader_flush			BDB_SYMBOL(reader_flush)
-int bdb_reader_get( Operation *op, DB_ENV *env, DB_TXN **txn );
-void bdb_reader_flush( DB_ENV *env );
-
-/*
- * trans.c
- */
-#define bdb_trans_backoff			BDB_SYMBOL(trans_backoff)
-
-void
-bdb_trans_backoff( int num_retries );
-
-/*
- * former external.h
- */
-
-#define bdb_back_initialize		BDB_SYMBOL(back_initialize)
-#define bdb_db_config			BDB_SYMBOL(db_config)
-#define bdb_add				BDB_SYMBOL(add)
-#define bdb_bind			BDB_SYMBOL(bind)
-#define bdb_compare			BDB_SYMBOL(compare)
-#define bdb_delete			BDB_SYMBOL(delete)
-#define bdb_modify			BDB_SYMBOL(modify)
-#define bdb_modrdn			BDB_SYMBOL(modrdn)
-#define bdb_search			BDB_SYMBOL(search)
-#define bdb_extended			BDB_SYMBOL(extended)
-#define bdb_referrals			BDB_SYMBOL(referrals)
-#define bdb_operational			BDB_SYMBOL(operational)
-#define bdb_hasSubordinates		BDB_SYMBOL(hasSubordinates)
-#define bdb_tool_entry_open		BDB_SYMBOL(tool_entry_open)
-#define bdb_tool_entry_close		BDB_SYMBOL(tool_entry_close)
-#define bdb_tool_entry_first_x		BDB_SYMBOL(tool_entry_first_x)
-#define bdb_tool_entry_next		BDB_SYMBOL(tool_entry_next)
-#define bdb_tool_entry_get		BDB_SYMBOL(tool_entry_get)
-#define bdb_tool_entry_put		BDB_SYMBOL(tool_entry_put)
-#define bdb_tool_entry_reindex		BDB_SYMBOL(tool_entry_reindex)
-#define bdb_tool_dn2id_get		BDB_SYMBOL(tool_dn2id_get)
-#define bdb_tool_entry_modify		BDB_SYMBOL(tool_entry_modify)
-#define bdb_tool_idl_add		BDB_SYMBOL(tool_idl_add)
-
-extern BI_init				bdb_back_initialize;
-
-extern BI_db_config			bdb_db_config;
-
-extern BI_op_add			bdb_add;
-extern BI_op_bind			bdb_bind;
-extern BI_op_compare			bdb_compare;
-extern BI_op_delete			bdb_delete;
-extern BI_op_modify			bdb_modify;
-extern BI_op_modrdn			bdb_modrdn;
-extern BI_op_search			bdb_search;
-extern BI_op_extended			bdb_extended;
-
-extern BI_chk_referrals			bdb_referrals;
-
-extern BI_operational			bdb_operational;
-
-extern BI_has_subordinates 		bdb_hasSubordinates;
-
-/* tools.c */
-extern BI_tool_entry_open		bdb_tool_entry_open;
-extern BI_tool_entry_close		bdb_tool_entry_close;
-extern BI_tool_entry_first_x		bdb_tool_entry_first_x;
-extern BI_tool_entry_next		bdb_tool_entry_next;
-extern BI_tool_entry_get		bdb_tool_entry_get;
-extern BI_tool_entry_put		bdb_tool_entry_put;
-extern BI_tool_entry_reindex		bdb_tool_entry_reindex;
-extern BI_tool_dn2id_get		bdb_tool_dn2id_get;
-extern BI_tool_entry_modify		bdb_tool_entry_modify;
-
-int bdb_tool_idl_add( BackendDB *be, DB *db, DB_TXN *txn, DBT *key, ID id );
-
-LDAP_END_DECL
-
-#endif /* _PROTO_BDB_H */
diff --git a/servers/slapd/back-bdb/referral.c b/servers/slapd/back-bdb/referral.c
deleted file mode 100644
index d92ff5a..0000000
--- a/servers/slapd/back-bdb/referral.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/* referral.c - BDB backend referral handler */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "back-bdb.h"
-
-int
-bdb_referrals( Operation *op, SlapReply *rs )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	Entry *e = NULL;
-	EntryInfo *ei;
-	int rc = LDAP_SUCCESS;
-
-	DB_TXN		*rtxn;
-	DB_LOCK		lock;
-
-	if( op->o_tag == LDAP_REQ_SEARCH ) {
-		/* let search take care of itself */
-		return rc;
-	}
-
-	if( get_manageDSAit( op ) ) {
-		/* let op take care of DSA management */
-		return rc;
-	} 
-
-	rc = bdb_reader_get(op, bdb->bi_dbenv, &rtxn);
-	switch(rc) {
-	case 0:
-		break;
-	default:
-		return LDAP_OTHER;
-	}
-
-dn2entry_retry:
-	/* get entry */
-	rc = bdb_dn2entry( op, rtxn, &op->o_req_ndn, &ei, 1, &lock );
-
-	/* bdb_dn2entry() may legally leave ei == NULL
-	 * if rc != 0 and rc != DB_NOTFOUND
-	 */
-	if ( ei ) {
-		e = ei->bei_e;
-	}
-
-	switch(rc) {
-	case DB_NOTFOUND:
-	case 0:
-		break;
-	case LDAP_BUSY:
-		rs->sr_text = "ldap server busy";
-		return LDAP_BUSY;
-	case DB_LOCK_DEADLOCK:
-	case DB_LOCK_NOTGRANTED:
-		goto dn2entry_retry;
-	default:
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_referrals)
-			": dn2entry failed: %s (%d)\n",
-			db_strerror(rc), rc, 0 ); 
-		rs->sr_text = "internal error";
-		return LDAP_OTHER;
-	}
-
-	if ( rc == DB_NOTFOUND ) {
-		rc = LDAP_SUCCESS;
-		rs->sr_matched = NULL;
-		if ( e != NULL ) {
-			Debug( LDAP_DEBUG_TRACE,
-				LDAP_XSTRING(bdb_referrals)
-				": tag=%lu target=\"%s\" matched=\"%s\"\n",
-				(unsigned long)op->o_tag, op->o_req_dn.bv_val, e->e_name.bv_val );
-
-			if( is_entry_referral( e ) ) {
-				BerVarray ref = get_entry_referrals( op, e );
-				rc = LDAP_OTHER;
-				rs->sr_ref = referral_rewrite( ref, &e->e_name,
-					&op->o_req_dn, LDAP_SCOPE_DEFAULT );
-				ber_bvarray_free( ref );
-				if ( rs->sr_ref ) {
-					rs->sr_matched = ber_strdup_x(
-					e->e_name.bv_val, op->o_tmpmemctx );
-				}
-			}
-
-			bdb_cache_return_entry_r (bdb, e, &lock);
-			e = NULL;
-		}
-
-		if( rs->sr_ref != NULL ) {
-			/* send referrals */
-			rc = rs->sr_err = LDAP_REFERRAL;
-			send_ldap_result( op, rs );
-			ber_bvarray_free( rs->sr_ref );
-			rs->sr_ref = NULL;
-		} else if ( rc != LDAP_SUCCESS ) {
-			rs->sr_text = rs->sr_matched ? "bad referral object" : NULL;
-		}
-
-		if (rs->sr_matched) {
-			op->o_tmpfree( (char *)rs->sr_matched, op->o_tmpmemctx );
-			rs->sr_matched = NULL;
-		}
-		return rc;
-	}
-
-	if ( is_entry_referral( e ) ) {
-		/* entry is a referral */
-		BerVarray refs = get_entry_referrals( op, e );
-		rs->sr_ref = referral_rewrite(
-			refs, &e->e_name, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
-
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_referrals)
-			": tag=%lu target=\"%s\" matched=\"%s\"\n",
-			(unsigned long)op->o_tag, op->o_req_dn.bv_val, e->e_name.bv_val );
-
-		rs->sr_matched = e->e_name.bv_val;
-		if( rs->sr_ref != NULL ) {
-			rc = rs->sr_err = LDAP_REFERRAL;
-			send_ldap_result( op, rs );
-			ber_bvarray_free( rs->sr_ref );
-			rs->sr_ref = NULL;
-		} else {
-			rc = LDAP_OTHER;
-			rs->sr_text = "bad referral object";
-		}
-
-		rs->sr_matched = NULL;
-		ber_bvarray_free( refs );
-	}
-
-	bdb_cache_return_entry_r(bdb, e, &lock);
-	return rc;
-}
diff --git a/servers/slapd/back-bdb/search.c b/servers/slapd/back-bdb/search.c
deleted file mode 100644
index dd67f21..0000000
--- a/servers/slapd/back-bdb/search.c
+++ /dev/null
@@ -1,1388 +0,0 @@
-/* search.c - search operation */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "back-bdb.h"
-#include "idl.h"
-
-static int base_candidate(
-	BackendDB	*be,
-	Entry	*e,
-	ID		*ids );
-
-static int search_candidates(
-	Operation *op,
-	SlapReply *rs,
-	Entry *e,
-	DB_TXN *txn,
-	ID	*ids,
-	ID	*scopes );
-
-static int parse_paged_cookie( Operation *op, SlapReply *rs );
-
-static void send_paged_response( 
-	Operation *op,
-	SlapReply *rs,
-	ID  *lastid,
-	int tentries );
-
-/* Dereference aliases for a single alias entry. Return the final
- * dereferenced entry on success, NULL on any failure.
- */
-static Entry * deref_base (
-	Operation *op,
-	SlapReply *rs,
-	Entry *e,
-	Entry **matched,
-	DB_TXN *txn,
-	DB_LOCK *lock,
-	ID	*tmp,
-	ID	*visited )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	struct berval ndn;
-	EntryInfo *ei;
-	DB_LOCK lockr;
-
-	rs->sr_err = LDAP_ALIAS_DEREF_PROBLEM;
-	rs->sr_text = "maximum deref depth exceeded";
-
-	for (;;) {
-		/* Remember the last entry we looked at, so we can
-		 * report broken links
-		 */
-		*matched = e;
-
-		if (BDB_IDL_N(tmp) >= op->o_bd->be_max_deref_depth) {
-			e = NULL;
-			break;
-		}
-
-		/* If this is part of a subtree or onelevel search,
-		 * have we seen this ID before? If so, quit.
-		 */
-		if ( visited && bdb_idl_insert( visited, e->e_id ) ) {
-			e = NULL;
-			break;
-		}
-
-		/* If we've seen this ID during this deref iteration,
-		 * we've hit a loop.
-		 */
-		if ( bdb_idl_insert( tmp, e->e_id ) ) {
-			rs->sr_err = LDAP_ALIAS_PROBLEM;
-			rs->sr_text = "circular alias";
-			e = NULL;
-			break;
-		}
-
-		/* If there was a problem getting the aliasedObjectName,
-		 * get_alias_dn will have set the error status.
-		 */
-		if ( get_alias_dn(e, &ndn, &rs->sr_err, &rs->sr_text) ) {
-			e = NULL;
-			break;
-		}
-
-		rs->sr_err = bdb_dn2entry( op, txn, &ndn, &ei,
-			0, &lockr );
-		if ( rs->sr_err == DB_LOCK_DEADLOCK )
-			return NULL;
-
-		if ( ei ) {
-			e = ei->bei_e;
-		} else {
-			e = NULL;
-		}
-
-		if (!e) {
-			rs->sr_err = LDAP_ALIAS_PROBLEM;
-			rs->sr_text = "aliasedObject not found";
-			break;
-		}
-
-		/* Free the previous entry, continue to work with the
-		 * one we just retrieved.
-		 */
-		bdb_cache_return_entry_r( bdb, *matched, lock);
-		*lock = lockr;
-
-		/* We found a regular entry. Return this to the caller. The
-		 * entry is still locked for Read.
-		 */
-		if (!is_entry_alias(e)) {
-			rs->sr_err = LDAP_SUCCESS;
-			rs->sr_text = NULL;
-			break;
-		}
-	}
-	return e;
-}
-
-/* Look for and dereference all aliases within the search scope. Adds
- * the dereferenced entries to the "ids" list. Requires "stack" to be
- * able to hold 8 levels of DB_SIZE IDLs. Of course we're hardcoded to
- * require a minimum of 8 UM_SIZE IDLs so this is never a problem.
- */
-static int search_aliases(
-	Operation *op,
-	SlapReply *rs,
-	Entry *e,
-	DB_TXN *txn,
-	ID *ids,
-	ID *scopes,
-	ID *stack )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	ID *aliases, *curscop, *subscop, *visited, *newsubs, *oldsubs, *tmp;
-	ID cursora, ida, cursoro, ido, *subscop2;
-	Entry *matched, *a;
-	EntryInfo *ei;
-	struct berval bv_alias = BER_BVC( "alias" );
-	AttributeAssertion aa_alias = ATTRIBUTEASSERTION_INIT;
-	Filter	af;
-	DB_LOCK locka, lockr;
-	int first = 1;
-
-	aliases = stack;	/* IDL of all aliases in the database */
-	curscop = aliases + BDB_IDL_DB_SIZE;	/* Aliases in the current scope */
-	subscop = curscop + BDB_IDL_DB_SIZE;	/* The current scope */
-	visited = subscop + BDB_IDL_DB_SIZE;	/* IDs we've seen in this search */
-	newsubs = visited + BDB_IDL_DB_SIZE;	/* New subtrees we've added */
-	oldsubs = newsubs + BDB_IDL_DB_SIZE;	/* Subtrees added previously */
-	tmp = oldsubs + BDB_IDL_DB_SIZE;	/* Scratch space for deref_base() */
-
-	/* A copy of subscop, because subscop gets clobbered by
-	 * the bdb_idl_union/intersection routines
-	 */
-	subscop2 = tmp + BDB_IDL_DB_SIZE;
-
-	af.f_choice = LDAP_FILTER_EQUALITY;
-	af.f_ava = &aa_alias;
-	af.f_av_desc = slap_schema.si_ad_objectClass;
-	af.f_av_value = bv_alias;
-	af.f_next = NULL;
-
-	/* Find all aliases in database */
-	BDB_IDL_ZERO( aliases );
-	rs->sr_err = bdb_filter_candidates( op, txn, &af, aliases,
-		curscop, visited );
-	if (rs->sr_err != LDAP_SUCCESS || BDB_IDL_IS_ZERO( aliases )) {
-		return rs->sr_err;
-	}
-	oldsubs[0] = 1;
-	oldsubs[1] = e->e_id;
-
-	BDB_IDL_ZERO( ids );
-	BDB_IDL_ZERO( visited );
-	BDB_IDL_ZERO( newsubs );
-
-	cursoro = 0;
-	ido = bdb_idl_first( oldsubs, &cursoro );
-
-	for (;;) {
-		/* Set curscop to only the aliases in the current scope. Start with
-		 * all the aliases, obtain the IDL for the current scope, and then
-		 * get the intersection of these two IDLs. Add the current scope
-		 * to the cumulative list of candidates.
-		 */
-		BDB_IDL_CPY( curscop, aliases );
-		rs->sr_err = bdb_dn2idl( op, txn, &e->e_nname, BEI(e), subscop,
-			subscop2+BDB_IDL_DB_SIZE );
-
-		if (first) {
-			first = 0;
-		} else {
-			bdb_cache_return_entry_r (bdb, e, &locka);
-		}
-		if ( rs->sr_err == DB_LOCK_DEADLOCK )
-			return rs->sr_err;
-
-		BDB_IDL_CPY(subscop2, subscop);
-		rs->sr_err = bdb_idl_intersection(curscop, subscop);
-		bdb_idl_union( ids, subscop2 );
-
-		/* Dereference all of the aliases in the current scope. */
-		cursora = 0;
-		for (ida = bdb_idl_first(curscop, &cursora); ida != NOID;
-			ida = bdb_idl_next(curscop, &cursora))
-		{
-			ei = NULL;
-retry1:
-			rs->sr_err = bdb_cache_find_id(op, txn,
-				ida, &ei, 0, &lockr );
-			if (rs->sr_err != LDAP_SUCCESS) {
-				if ( rs->sr_err == DB_LOCK_DEADLOCK )
-					return rs->sr_err;
-				if ( rs->sr_err == DB_LOCK_NOTGRANTED )
-					goto retry1;
-				continue;
-			}
-			a = ei->bei_e;
-
-			/* This should only happen if the curscop IDL has maxed out and
-			 * turned into a range that spans IDs indiscriminately
-			 */
-			if (!is_entry_alias(a)) {
-				bdb_cache_return_entry_r (bdb, a, &lockr);
-				continue;
-			}
-
-			/* Actually dereference the alias */
-			BDB_IDL_ZERO(tmp);
-			a = deref_base( op, rs, a, &matched, txn, &lockr,
-				tmp, visited );
-			if (a) {
-				/* If the target was not already in our current candidates,
-				 * make note of it in the newsubs list. Also
-				 * set it in the scopes list so that bdb_search
-				 * can check it.
-				 */
-				if (bdb_idl_insert(ids, a->e_id) == 0) {
-					bdb_idl_insert(newsubs, a->e_id);
-					bdb_idl_insert(scopes, a->e_id);
-				}
-				bdb_cache_return_entry_r( bdb, a, &lockr);
-
-			} else if ( rs->sr_err == DB_LOCK_DEADLOCK ) {
-				return rs->sr_err;
-			} else if (matched) {
-				/* Alias could not be dereferenced, or it deref'd to
-				 * an ID we've already seen. Ignore it.
-				 */
-				bdb_cache_return_entry_r( bdb, matched, &lockr );
-				rs->sr_text = NULL;
-			}
-		}
-		/* If this is a OneLevel search, we're done; oldsubs only had one
-		 * ID in it. For a Subtree search, oldsubs may be a list of scope IDs.
-		 */
-		if ( op->ors_scope == LDAP_SCOPE_ONELEVEL ) break;
-nextido:
-		ido = bdb_idl_next( oldsubs, &cursoro );
-		
-		/* If we're done processing the old scopes, did we add any new
-		 * scopes in this iteration? If so, go back and do those now.
-		 */
-		if (ido == NOID) {
-			if (BDB_IDL_IS_ZERO(newsubs)) break;
-			BDB_IDL_CPY(oldsubs, newsubs);
-			BDB_IDL_ZERO(newsubs);
-			cursoro = 0;
-			ido = bdb_idl_first( oldsubs, &cursoro );
-		}
-
-		/* Find the entry corresponding to the next scope. If it can't
-		 * be found, ignore it and move on. This should never happen;
-		 * we should never see the ID of an entry that doesn't exist.
-		 * Set the name so that the scope's IDL can be retrieved.
-		 */
-		ei = NULL;
-sameido:
-		rs->sr_err = bdb_cache_find_id(op, txn, ido, &ei,
-			0, &locka );
-		if ( rs->sr_err != LDAP_SUCCESS ) {
-			if ( rs->sr_err == DB_LOCK_DEADLOCK )
-				return rs->sr_err;
-			if ( rs->sr_err == DB_LOCK_NOTGRANTED )
-				goto sameido;
-			goto nextido;
-		}
-		e = ei->bei_e;
-	}
-	return rs->sr_err;
-}
-
-/* Get the next ID from the DB. Used if the candidate list is
- * a range and simple iteration hits missing entryIDs
- */
-static int
-bdb_get_nextid(struct bdb_info *bdb, DB_TXN *ltid, ID *cursor)
-{
-	DBC *curs;
-	DBT key, data;
-	ID id, nid;
-	int rc;
-
-	id = *cursor + 1;
-	BDB_ID2DISK( id, &nid );
-	rc = bdb->bi_id2entry->bdi_db->cursor(
-		bdb->bi_id2entry->bdi_db, ltid, &curs, bdb->bi_db_opflags );
-	if ( rc )
-		return rc;
-	key.data = &nid;
-	key.size = key.ulen = sizeof(ID);
-	key.flags = DB_DBT_USERMEM;
-	data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
-	data.dlen = data.ulen = 0;
-	rc = curs->c_get( curs, &key, &data, DB_SET_RANGE );
-	curs->c_close( curs );
-	if ( rc )
-		return rc;
-	BDB_DISK2ID( &nid, cursor );
-	return 0;
-}
-
-int
-bdb_search( Operation *op, SlapReply *rs )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	ID		id, cursor;
-	ID		lastid = NOID;
-	ID		candidates[BDB_IDL_UM_SIZE];
-	ID		scopes[BDB_IDL_DB_SIZE];
-	Entry		*e = NULL, base, *e_root;
-	Entry		*matched = NULL;
-	EntryInfo	*ei;
-	AttributeName	*attrs;
-	struct berval	realbase = BER_BVNULL;
-	slap_mask_t	mask;
-	time_t		stoptime;
-	int		manageDSAit;
-	int		tentries = 0;
-	unsigned	nentries = 0;
-	int		idflag = 0;
-
-	DB_LOCK		lock;
-	struct	bdb_op_info	*opinfo = NULL;
-	DB_TXN			*ltid = NULL;
-	OpExtra *oex;
-
-	Debug( LDAP_DEBUG_TRACE, "=> " LDAP_XSTRING(bdb_search) "\n", 0, 0, 0);
-	attrs = op->oq_search.rs_attrs;
-
-	LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
-		if ( oex->oe_key == bdb )
-			break;
-	}
-	opinfo = (struct bdb_op_info *) oex;
-
-	manageDSAit = get_manageDSAit( op );
-
-	if ( opinfo && opinfo->boi_txn ) {
-		ltid = opinfo->boi_txn;
-	} else {
-		rs->sr_err = bdb_reader_get( op, bdb->bi_dbenv, &ltid );
-
-		switch(rs->sr_err) {
-		case 0:
-			break;
-		default:
-			send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
-			return rs->sr_err;
-		}
-	}
-
-	e_root = bdb->bi_cache.c_dntree.bei_e;
-	if ( op->o_req_ndn.bv_len == 0 ) {
-		/* DIT root special case */
-		ei = e_root->e_private;
-		rs->sr_err = LDAP_SUCCESS;
-	} else {
-		if ( op->ors_deref & LDAP_DEREF_FINDING ) {
-			BDB_IDL_ZERO(candidates);
-		}
-dn2entry_retry:
-		/* get entry with reader lock */
-		rs->sr_err = bdb_dn2entry( op, ltid, &op->o_req_ndn, &ei,
-			1, &lock );
-	}
-
-	switch(rs->sr_err) {
-	case DB_NOTFOUND:
-		matched = ei->bei_e;
-		break;
-	case 0:
-		e = ei->bei_e;
-		break;
-	case DB_LOCK_DEADLOCK:
-		if ( !opinfo ) {
-			ltid->flags &= ~TXN_DEADLOCK;
-			goto dn2entry_retry;
-		}
-		opinfo->boi_err = rs->sr_err;
-		/* FALLTHRU */
-	case LDAP_BUSY:
-		send_ldap_error( op, rs, LDAP_BUSY, "ldap server busy" );
-		return LDAP_BUSY;
-	case DB_LOCK_NOTGRANTED:
-		goto dn2entry_retry;
-	default:
-		send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
-		return rs->sr_err;
-	}
-
-	if ( op->ors_deref & LDAP_DEREF_FINDING ) {
-		if ( matched && is_entry_alias( matched )) {
-			struct berval stub;
-
-			stub.bv_val = op->o_req_ndn.bv_val;
-			stub.bv_len = op->o_req_ndn.bv_len - matched->e_nname.bv_len - 1;
-			e = deref_base( op, rs, matched, &matched, ltid, &lock,
-				candidates, NULL );
-			if ( e ) {
-				build_new_dn( &op->o_req_ndn, &e->e_nname, &stub,
-					op->o_tmpmemctx );
-				bdb_cache_return_entry_r (bdb, e, &lock);
-				matched = NULL;
-				goto dn2entry_retry;
-			}
-		} else if ( e && is_entry_alias( e )) {
-			e = deref_base( op, rs, e, &matched, ltid, &lock,
-				candidates, NULL );
-		}
-	}
-
-	if ( e == NULL ) {
-		struct berval matched_dn = BER_BVNULL;
-
-		if ( matched != NULL ) {
-			BerVarray erefs = NULL;
-
-			/* return referral only if "disclose"
-			 * is granted on the object */
-			if ( ! access_allowed( op, matched,
-						slap_schema.si_ad_entry,
-						NULL, ACL_DISCLOSE, NULL ) )
-			{
-				rs->sr_err = LDAP_NO_SUCH_OBJECT;
-
-			} else {
-				ber_dupbv( &matched_dn, &matched->e_name );
-
-				erefs = is_entry_referral( matched )
-					? get_entry_referrals( op, matched )
-					: NULL;
-				if ( rs->sr_err == DB_NOTFOUND )
-					rs->sr_err = LDAP_REFERRAL;
-				rs->sr_matched = matched_dn.bv_val;
-			}
-
-#ifdef SLAP_ZONE_ALLOC
-			slap_zn_runlock(bdb->bi_cache.c_zctx, matched);
-#endif
-			bdb_cache_return_entry_r (bdb, matched, &lock);
-			matched = NULL;
-
-			if ( erefs ) {
-				rs->sr_ref = referral_rewrite( erefs, &matched_dn,
-					&op->o_req_dn, op->oq_search.rs_scope );
-				ber_bvarray_free( erefs );
-			}
-
-		} else {
-#ifdef SLAP_ZONE_ALLOC
-			slap_zn_runlock(bdb->bi_cache.c_zctx, matched);
-#endif
-			rs->sr_ref = referral_rewrite( default_referral,
-				NULL, &op->o_req_dn, op->oq_search.rs_scope );
-			rs->sr_err = rs->sr_ref != NULL ? LDAP_REFERRAL : LDAP_NO_SUCH_OBJECT;
-		}
-
-		send_ldap_result( op, rs );
-
-		if ( rs->sr_ref ) {
-			ber_bvarray_free( rs->sr_ref );
-			rs->sr_ref = NULL;
-		}
-		if ( !BER_BVISNULL( &matched_dn ) ) {
-			ber_memfree( matched_dn.bv_val );
-			rs->sr_matched = NULL;
-		}
-		return rs->sr_err;
-	}
-
-	/* NOTE: __NEW__ "search" access is required
-	 * on searchBase object */
-	if ( ! access_allowed_mask( op, e, slap_schema.si_ad_entry,
-				NULL, ACL_SEARCH, NULL, &mask ) )
-	{
-		if ( !ACL_GRANT( mask, ACL_DISCLOSE ) ) {
-			rs->sr_err = LDAP_NO_SUCH_OBJECT;
-		} else {
-			rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
-		}
-
-#ifdef SLAP_ZONE_ALLOC
-		slap_zn_runlock(bdb->bi_cache.c_zctx, e);
-#endif
-		if ( e != e_root ) {
-			bdb_cache_return_entry_r(bdb, e, &lock);
-		}
-		send_ldap_result( op, rs );
-		return rs->sr_err;
-	}
-
-	if ( !manageDSAit && e != e_root && is_entry_referral( e ) ) {
-		/* entry is a referral, don't allow add */
-		struct berval matched_dn = BER_BVNULL;
-		BerVarray erefs = NULL;
-		
-		ber_dupbv( &matched_dn, &e->e_name );
-		erefs = get_entry_referrals( op, e );
-
-		rs->sr_err = LDAP_REFERRAL;
-
-#ifdef SLAP_ZONE_ALLOC
-		slap_zn_runlock(bdb->bi_cache.c_zctx, e);
-#endif
-		bdb_cache_return_entry_r( bdb, e, &lock );
-		e = NULL;
-
-		if ( erefs ) {
-			rs->sr_ref = referral_rewrite( erefs, &matched_dn,
-				&op->o_req_dn, op->oq_search.rs_scope );
-			ber_bvarray_free( erefs );
-
-			if ( !rs->sr_ref ) {
-				rs->sr_text = "bad_referral object";
-			}
-		}
-
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_search) ": entry is referral\n",
-			0, 0, 0 );
-
-		rs->sr_matched = matched_dn.bv_val;
-		send_ldap_result( op, rs );
-
-		ber_bvarray_free( rs->sr_ref );
-		rs->sr_ref = NULL;
-		ber_memfree( matched_dn.bv_val );
-		rs->sr_matched = NULL;
-		return 1;
-	}
-
-	if ( get_assert( op ) &&
-		( test_filter( op, e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
-	{
-		rs->sr_err = LDAP_ASSERTION_FAILED;
-#ifdef SLAP_ZONE_ALLOC
-		slap_zn_runlock(bdb->bi_cache.c_zctx, e);
-#endif
-		if ( e != e_root ) {
-			bdb_cache_return_entry_r(bdb, e, &lock);
-		}
-		send_ldap_result( op, rs );
-		return 1;
-	}
-
-	/* compute it anyway; root does not use it */
-	stoptime = op->o_time + op->ors_tlimit;
-
-	/* need normalized dn below */
-	ber_dupbv( &realbase, &e->e_nname );
-
-	/* Copy info to base, must free entry before accessing the database
-	 * in search_candidates, to avoid deadlocks.
-	 */
-	base.e_private = e->e_private;
-	base.e_nname = realbase;
-	base.e_id = e->e_id;
-
-#ifdef SLAP_ZONE_ALLOC
-	slap_zn_runlock(bdb->bi_cache.c_zctx, e);
-#endif
-	if ( e != e_root ) {
-		bdb_cache_return_entry_r(bdb, e, &lock);
-	}
-	e = NULL;
-
-	/* select candidates */
-	if ( op->oq_search.rs_scope == LDAP_SCOPE_BASE ) {
-		rs->sr_err = base_candidate( op->o_bd, &base, candidates );
-
-	} else {
-cand_retry:
-		BDB_IDL_ZERO( candidates );
-		BDB_IDL_ZERO( scopes );
-		rs->sr_err = search_candidates( op, rs, &base,
-			ltid, candidates, scopes );
-		if ( rs->sr_err == DB_LOCK_DEADLOCK ) {
-			if ( !opinfo ) {
-				ltid->flags &= ~TXN_DEADLOCK;
-				goto cand_retry;
-			}
-			opinfo->boi_err = rs->sr_err;
-			send_ldap_error( op, rs, LDAP_BUSY, "ldap server busy" );
-			return LDAP_BUSY;
-		}
-	}
-
-	/* start cursor at beginning of candidates.
-	 */
-	cursor = 0;
-
-	if ( candidates[0] == 0 ) {
-		Debug( LDAP_DEBUG_TRACE,
-			LDAP_XSTRING(bdb_search) ": no candidates\n",
-			0, 0, 0 );
-
-		goto nochange;
-	}
-
-	/* if not root and candidates exceed to-be-checked entries, abort */
-	if ( op->ors_limit	/* isroot == FALSE */ &&
-		op->ors_limit->lms_s_unchecked != -1 &&
-		BDB_IDL_N(candidates) > (unsigned) op->ors_limit->lms_s_unchecked )
-	{
-		rs->sr_err = LDAP_ADMINLIMIT_EXCEEDED;
-		send_ldap_result( op, rs );
-		rs->sr_err = LDAP_SUCCESS;
-		goto done;
-	}
-
-	if ( op->ors_limit == NULL	/* isroot == TRUE */ ||
-		!op->ors_limit->lms_s_pr_hide )
-	{
-		tentries = BDB_IDL_N(candidates);
-	}
-
-	if ( get_pagedresults( op ) > SLAP_CONTROL_IGNORED ) {
-		PagedResultsState *ps = op->o_pagedresults_state;
-		/* deferred cookie parsing */
-		rs->sr_err = parse_paged_cookie( op, rs );
-		if ( rs->sr_err != LDAP_SUCCESS ) {
-			send_ldap_result( op, rs );
-			goto done;
-		}
-
-		cursor = (ID) ps->ps_cookie;
-		if ( cursor && ps->ps_size == 0 ) {
-			rs->sr_err = LDAP_SUCCESS;
-			rs->sr_text = "search abandoned by pagedResult size=0";
-			send_ldap_result( op, rs );
-			goto done;
-		}
-		id = bdb_idl_first( candidates, &cursor );
-		if ( id == NOID ) {
-			Debug( LDAP_DEBUG_TRACE, 
-				LDAP_XSTRING(bdb_search)
-				": no paged results candidates\n",
-				0, 0, 0 );
-			send_paged_response( op, rs, &lastid, 0 );
-
-			rs->sr_err = LDAP_OTHER;
-			goto done;
-		}
-		nentries = ps->ps_count;
-		if ( id == (ID)ps->ps_cookie )
-			id = bdb_idl_next( candidates, &cursor );
-		goto loop_begin;
-	}
-
-	for ( id = bdb_idl_first( candidates, &cursor );
-		  id != NOID ; id = bdb_idl_next( candidates, &cursor ) )
-	{
-		int scopeok;
-
-loop_begin:
-
-		/* check for abandon */
-		if ( op->o_abandon ) {
-			rs->sr_err = SLAPD_ABANDON;
-			send_ldap_result( op, rs );
-			goto done;
-		}
-
-		/* mostly needed by internal searches,
-		 * e.g. related to syncrepl, for whom
-		 * abandon does not get set... */
-		if ( slapd_shutdown ) {
-			rs->sr_err = LDAP_UNAVAILABLE;
-			send_ldap_disconnect( op, rs );
-			goto done;
-		}
-
-		/* check time limit */
-		if ( op->ors_tlimit != SLAP_NO_LIMIT
-				&& slap_get_time() > stoptime )
-		{
-			rs->sr_err = LDAP_TIMELIMIT_EXCEEDED;
-			rs->sr_ref = rs->sr_v2ref;
-			send_ldap_result( op, rs );
-			rs->sr_err = LDAP_SUCCESS;
-			goto done;
-		}
-
-		/* If we inspect more entries than will
-		 * fit into the entry cache, stop caching
-		 * any subsequent entries
-		 */
-		nentries++;
-		if ( nentries > bdb->bi_cache.c_maxsize && !idflag ) {
-			idflag = ID_NOCACHE;
-		}
-
-fetch_entry_retry:
-		/* get the entry with reader lock */
-		ei = NULL;
-		rs->sr_err = bdb_cache_find_id( op, ltid,
-			id, &ei, idflag, &lock );
-
-		if (rs->sr_err == LDAP_BUSY) {
-			rs->sr_text = "ldap server busy";
-			send_ldap_result( op, rs );
-			goto done;
-
-		} else if ( rs->sr_err == DB_LOCK_DEADLOCK ) {
-			if ( !opinfo ) {
-				ltid->flags &= ~TXN_DEADLOCK;
-				goto fetch_entry_retry;
-			}
-txnfail:
-			opinfo->boi_err = rs->sr_err;
-			send_ldap_error( op, rs, LDAP_BUSY, "ldap server busy" );
-			goto done;
-
-		} else if ( rs->sr_err == DB_LOCK_NOTGRANTED )
-		{
-			goto fetch_entry_retry;
-		} else if ( rs->sr_err == LDAP_OTHER ) {
-			rs->sr_text = "internal error";
-			send_ldap_result( op, rs );
-			goto done;
-		}
-
-		if ( ei && rs->sr_err == LDAP_SUCCESS ) {
-			e = ei->bei_e;
-		} else {
-			e = NULL;
-		}
-
-		if ( e == NULL ) {
-			if( !BDB_IDL_IS_RANGE(candidates) ) {
-				/* only complain for non-range IDLs */
-				Debug( LDAP_DEBUG_TRACE,
-					LDAP_XSTRING(bdb_search)
-					": candidate %ld not found\n",
-					(long) id, 0, 0 );
-			} else {
-				/* get the next ID from the DB */
-id_retry:
-				rs->sr_err = bdb_get_nextid( bdb, ltid, &cursor );
-				if ( rs->sr_err == DB_NOTFOUND ) {
-					break;
-				} else if ( rs->sr_err == DB_LOCK_DEADLOCK ) {
-					if ( opinfo )
-						goto txnfail;
-					ltid->flags &= ~TXN_DEADLOCK;
-					goto id_retry;
-				} else if ( rs->sr_err == DB_LOCK_NOTGRANTED ) {
-					goto id_retry;
-				}
-				if ( rs->sr_err ) {
-					rs->sr_err = LDAP_OTHER;
-					rs->sr_text = "internal error in get_nextid";
-					send_ldap_result( op, rs );
-					goto done;
-				}
-				cursor--;
-			}
-
-			goto loop_continue;
-		}
-
-		if ( is_entry_subentry( e ) ) {
-			if( op->oq_search.rs_scope != LDAP_SCOPE_BASE ) {
-				if(!get_subentries_visibility( op )) {
-					/* only subentries are visible */
-					goto loop_continue;
-				}
-
-			} else if ( get_subentries( op ) &&
-				!get_subentries_visibility( op ))
-			{
-				/* only subentries are visible */
-				goto loop_continue;
-			}
-
-		} else if ( get_subentries_visibility( op )) {
-			/* only subentries are visible */
-			goto loop_continue;
-		}
-
-		/* Does this candidate actually satisfy the search scope?
-		 *
-		 * Note that we don't lock access to the bei_parent pointer.
-		 * Since only leaf nodes can be deleted, the parent of any
-		 * node will always be a valid node. Also since we have
-		 * a Read lock on the data, it cannot be renamed out of the
-		 * scope while we are looking at it, and unless we're using
-		 * BDB_HIER, its parents cannot be moved either.
-		 */
-		scopeok = 0;
-		switch( op->ors_scope ) {
-		case LDAP_SCOPE_BASE:
-			/* This is always true, yes? */
-			if ( id == base.e_id ) scopeok = 1;
-			break;
-
-		case LDAP_SCOPE_ONELEVEL:
-			if ( ei->bei_parent->bei_id == base.e_id ) scopeok = 1;
-			break;
-
-#ifdef LDAP_SCOPE_CHILDREN
-		case LDAP_SCOPE_CHILDREN:
-			if ( id == base.e_id ) break;
-			/* Fall-thru */
-#endif
-		case LDAP_SCOPE_SUBTREE: {
-			EntryInfo *tmp;
-			for ( tmp = BEI(e); tmp; tmp = tmp->bei_parent ) {
-				if ( tmp->bei_id == base.e_id ) {
-					scopeok = 1;
-					break;
-				}
-			}
-			} break;
-		}
-
-		/* aliases were already dereferenced in candidate list */
-		if ( op->ors_deref & LDAP_DEREF_SEARCHING ) {
-			/* but if the search base is an alias, and we didn't
-			 * deref it when finding, return it.
-			 */
-			if ( is_entry_alias(e) &&
-				((op->ors_deref & LDAP_DEREF_FINDING) ||
-					!bvmatch(&e->e_nname, &op->o_req_ndn)))
-			{
-				goto loop_continue;
-			}
-
-			/* scopes is only non-empty for onelevel or subtree */
-			if ( !scopeok && BDB_IDL_N(scopes) ) {
-				unsigned x;
-				if ( op->ors_scope == LDAP_SCOPE_ONELEVEL ) {
-					x = bdb_idl_search( scopes, e->e_id );
-					if ( scopes[x] == e->e_id ) scopeok = 1;
-				} else {
-					/* subtree, walk up the tree */
-					EntryInfo *tmp = BEI(e);
-					for (;tmp->bei_parent; tmp=tmp->bei_parent) {
-						x = bdb_idl_search( scopes, tmp->bei_id );
-						if ( scopes[x] == tmp->bei_id ) {
-							scopeok = 1;
-							break;
-						}
-					}
-				}
-			}
-		}
-
-		/* Not in scope, ignore it */
-		if ( !scopeok )
-		{
-			Debug( LDAP_DEBUG_TRACE,
-				LDAP_XSTRING(bdb_search)
-				": %ld scope not okay\n",
-				(long) id, 0, 0 );
-			goto loop_continue;
-		}
-
-		/*
-		 * if it's a referral, add it to the list of referrals. only do
-		 * this for non-base searches, and don't check the filter
-		 * explicitly here since it's only a candidate anyway.
-		 */
-		if ( !manageDSAit && op->oq_search.rs_scope != LDAP_SCOPE_BASE
-			&& is_entry_referral( e ) )
-		{
-			struct bdb_op_info bois;
-			struct bdb_lock_info blis;
-			BerVarray erefs = get_entry_referrals( op, e );
-			rs->sr_ref = referral_rewrite( erefs, &e->e_name, NULL,
-				op->oq_search.rs_scope == LDAP_SCOPE_ONELEVEL
-					? LDAP_SCOPE_BASE : LDAP_SCOPE_SUBTREE );
-
-			/* Must set lockinfo so that entry_release will work */
-			if (!opinfo) {
-				bois.boi_oe.oe_key = bdb;
-				bois.boi_txn = NULL;
-				bois.boi_err = 0;
-				bois.boi_acl_cache = op->o_do_not_cache;
-				bois.boi_flag = BOI_DONTFREE;
-				bois.boi_locks = &blis;
-				blis.bli_next = NULL;
-				LDAP_SLIST_INSERT_HEAD( &op->o_extra, &bois.boi_oe,
-					oe_next );
-			} else {
-				blis.bli_next = opinfo->boi_locks;
-				opinfo->boi_locks = &blis;
-			}
-			blis.bli_id = e->e_id;
-			blis.bli_lock = lock;
-			blis.bli_flag = BLI_DONTFREE;
-
-			rs->sr_entry = e;
-			rs->sr_flags = REP_ENTRY_MUSTRELEASE;
-
-			send_search_reference( op, rs );
-
-			if ( blis.bli_flag ) {
-#ifdef SLAP_ZONE_ALLOC
-				slap_zn_runlock(bdb->bi_cache.c_zctx, e);
-#endif
-				bdb_cache_return_entry_r(bdb, e, &lock);
-				if ( opinfo ) {
-					opinfo->boi_locks = blis.bli_next;
-				} else {
-					LDAP_SLIST_REMOVE( &op->o_extra, &bois.boi_oe,
-						OpExtra, oe_next );
-				}
-			}
-			rs->sr_entry = NULL;
-			e = NULL;
-
-			ber_bvarray_free( rs->sr_ref );
-			ber_bvarray_free( erefs );
-			rs->sr_ref = NULL;
-
-			goto loop_continue;
-		}
-
-		if ( !manageDSAit && is_entry_glue( e )) {
-			goto loop_continue;
-		}
-
-		/* if it matches the filter and scope, send it */
-		rs->sr_err = test_filter( op, e, op->oq_search.rs_filter );
-
-		if ( rs->sr_err == LDAP_COMPARE_TRUE ) {
-			/* check size limit */
-			if ( get_pagedresults(op) > SLAP_CONTROL_IGNORED ) {
-				if ( rs->sr_nentries >= ((PagedResultsState *)op->o_pagedresults_state)->ps_size ) {
-#ifdef SLAP_ZONE_ALLOC
-					slap_zn_runlock(bdb->bi_cache.c_zctx, e);
-#endif
-					bdb_cache_return_entry_r( bdb, e, &lock );
-					e = NULL;
-					send_paged_response( op, rs, &lastid, tentries );
-					goto done;
-				}
-				lastid = id;
-			}
-
-			if (e) {
-				struct bdb_op_info bois;
-				struct bdb_lock_info blis;
-
-				/* Must set lockinfo so that entry_release will work */
-				if (!opinfo) {
-					bois.boi_oe.oe_key = bdb;
-					bois.boi_txn = NULL;
-					bois.boi_err = 0;
-					bois.boi_acl_cache = op->o_do_not_cache;
-					bois.boi_flag = BOI_DONTFREE;
-					bois.boi_locks = &blis;
-					blis.bli_next = NULL;
-					LDAP_SLIST_INSERT_HEAD( &op->o_extra, &bois.boi_oe,
-						oe_next );
-				} else {
-					blis.bli_next = opinfo->boi_locks;
-					opinfo->boi_locks = &blis;
-				}
-				blis.bli_id = e->e_id;
-				blis.bli_lock = lock;
-				blis.bli_flag = BLI_DONTFREE;
-
-				/* safe default */
-				rs->sr_attrs = op->oq_search.rs_attrs;
-				rs->sr_operational_attrs = NULL;
-				rs->sr_ctrls = NULL;
-				rs->sr_entry = e;
-				RS_ASSERT( e->e_private != NULL );
-				rs->sr_flags = REP_ENTRY_MUSTRELEASE;
-				rs->sr_err = LDAP_SUCCESS;
-				rs->sr_err = send_search_entry( op, rs );
-				rs->sr_attrs = NULL;
-				rs->sr_entry = NULL;
-
-				/* send_search_entry will usually free it.
-				 * an overlay might leave its own copy here;
-				 * bli_flag will be 0 if lock was already released.
-				 */
-				if ( blis.bli_flag ) {
-#ifdef SLAP_ZONE_ALLOC
-					slap_zn_runlock(bdb->bi_cache.c_zctx, e);
-#endif
-					bdb_cache_return_entry_r(bdb, e, &lock);
-					if ( opinfo ) {
-						opinfo->boi_locks = blis.bli_next;
-					} else {
-						LDAP_SLIST_REMOVE( &op->o_extra, &bois.boi_oe,
-							OpExtra, oe_next );
-					}
-				}
-				e = NULL;
-
-				switch ( rs->sr_err ) {
-				case LDAP_SUCCESS:	/* entry sent ok */
-					break;
-				default:		/* entry not sent */
-					break;
-				case LDAP_BUSY:
-					send_ldap_result( op, rs );
-					goto done;
-				case LDAP_UNAVAILABLE:
-				case LDAP_SIZELIMIT_EXCEEDED:
-					if ( rs->sr_err == LDAP_SIZELIMIT_EXCEEDED ) {
-						rs->sr_ref = rs->sr_v2ref;
-						send_ldap_result( op, rs );
-						rs->sr_err = LDAP_SUCCESS;
-
-					} else {
-						rs->sr_err = LDAP_OTHER;
-					}
-					goto done;
-				}
-			}
-
-		} else {
-			Debug( LDAP_DEBUG_TRACE,
-				LDAP_XSTRING(bdb_search)
-				": %ld does not match filter\n",
-				(long) id, 0, 0 );
-		}
-
-loop_continue:
-		if( e != NULL ) {
-			/* free reader lock */
-#ifdef SLAP_ZONE_ALLOC
-			slap_zn_runlock(bdb->bi_cache.c_zctx, e);
-#endif
-			bdb_cache_return_entry_r( bdb, e , &lock );
-			RS_ASSERT( rs->sr_entry == NULL );
-			e = NULL;
-			rs->sr_entry = NULL;
-		}
-	}
-
-nochange:
-	rs->sr_ctrls = NULL;
-	rs->sr_ref = rs->sr_v2ref;
-	rs->sr_err = (rs->sr_v2ref == NULL) ? LDAP_SUCCESS : LDAP_REFERRAL;
-	rs->sr_rspoid = NULL;
-	if ( get_pagedresults(op) > SLAP_CONTROL_IGNORED ) {
-		send_paged_response( op, rs, NULL, 0 );
-	} else {
-		send_ldap_result( op, rs );
-	}
-
-	rs->sr_err = LDAP_SUCCESS;
-
-done:
-	if( rs->sr_v2ref ) {
-		ber_bvarray_free( rs->sr_v2ref );
-		rs->sr_v2ref = NULL;
-	}
-	if( realbase.bv_val ) ch_free( realbase.bv_val );
-
-	return rs->sr_err;
-}
-
-
-static int base_candidate(
-	BackendDB	*be,
-	Entry	*e,
-	ID		*ids )
-{
-	Debug(LDAP_DEBUG_ARGS, "base_candidates: base: \"%s\" (0x%08lx)\n",
-		e->e_nname.bv_val, (long) e->e_id, 0);
-
-	ids[0] = 1;
-	ids[1] = e->e_id;
-	return 0;
-}
-
-/* Look for "objectClass Present" in this filter.
- * Also count depth of filter tree while we're at it.
- */
-static int oc_filter(
-	Filter *f,
-	int cur,
-	int *max )
-{
-	int rc = 0;
-
-	assert( f != NULL );
-
-	if( cur > *max ) *max = cur;
-
-	switch( f->f_choice ) {
-	case LDAP_FILTER_PRESENT:
-		if (f->f_desc == slap_schema.si_ad_objectClass) {
-			rc = 1;
-		}
-		break;
-
-	case LDAP_FILTER_AND:
-	case LDAP_FILTER_OR:
-		cur++;
-		for ( f=f->f_and; f; f=f->f_next ) {
-			(void) oc_filter(f, cur, max);
-		}
-		break;
-
-	default:
-		break;
-	}
-	return rc;
-}
-
-static void search_stack_free( void *key, void *data )
-{
-	ber_memfree_x(data, NULL);
-}
-
-static void *search_stack( Operation *op )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	void *ret = NULL;
-
-	if ( op->o_threadctx ) {
-		ldap_pvt_thread_pool_getkey( op->o_threadctx, (void *)search_stack,
-			&ret, NULL );
-	} else {
-		ret = bdb->bi_search_stack;
-	}
-
-	if ( !ret ) {
-		ret = ch_malloc( bdb->bi_search_stack_depth * BDB_IDL_UM_SIZE
-			* sizeof( ID ) );
-		if ( op->o_threadctx ) {
-			ldap_pvt_thread_pool_setkey( op->o_threadctx, (void *)search_stack,
-				ret, search_stack_free, NULL, NULL );
-		} else {
-			bdb->bi_search_stack = ret;
-		}
-	}
-	return ret;
-}
-
-static int search_candidates(
-	Operation *op,
-	SlapReply *rs,
-	Entry *e,
-	DB_TXN *txn,
-	ID	*ids,
-	ID	*scopes )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-	int rc, depth = 1;
-	Filter		f, rf, xf, nf;
-	ID		*stack;
-	AttributeAssertion aa_ref = ATTRIBUTEASSERTION_INIT;
-	Filter	sf;
-	AttributeAssertion aa_subentry = ATTRIBUTEASSERTION_INIT;
-
-	/*
-	 * This routine takes as input a filter (user-filter)
-	 * and rewrites it as follows:
-	 *	(&(scope=DN)[(objectClass=subentry)]
-	 *		(|[(objectClass=referral)(objectClass=alias)](user-filter))
-	 */
-
-	Debug(LDAP_DEBUG_TRACE,
-		"search_candidates: base=\"%s\" (0x%08lx) scope=%d\n",
-		e->e_nname.bv_val, (long) e->e_id, op->oq_search.rs_scope );
-
-	xf.f_or = op->oq_search.rs_filter;
-	xf.f_choice = LDAP_FILTER_OR;
-	xf.f_next = NULL;
-
-	/* If the user's filter uses objectClass=*,
-	 * these clauses are redundant.
-	 */
-	if (!oc_filter(op->oq_search.rs_filter, 1, &depth)
-		&& !get_subentries_visibility(op)) {
-		if( !get_manageDSAit(op) && !get_domainScope(op) ) {
-			/* match referral objects */
-			struct berval bv_ref = BER_BVC( "referral" );
-			rf.f_choice = LDAP_FILTER_EQUALITY;
-			rf.f_ava = &aa_ref;
-			rf.f_av_desc = slap_schema.si_ad_objectClass;
-			rf.f_av_value = bv_ref;
-			rf.f_next = xf.f_or;
-			xf.f_or = &rf;
-			depth++;
-		}
-	}
-
-	f.f_next = NULL;
-	f.f_choice = LDAP_FILTER_AND;
-	f.f_and = &nf;
-	/* Dummy; we compute scope separately now */
-	nf.f_choice = SLAPD_FILTER_COMPUTED;
-	nf.f_result = LDAP_SUCCESS;
-	nf.f_next = ( xf.f_or == op->oq_search.rs_filter )
-		? op->oq_search.rs_filter : &xf ;
-	/* Filter depth increased again, adding dummy clause */
-	depth++;
-
-	if( get_subentries_visibility( op ) ) {
-		struct berval bv_subentry = BER_BVC( "subentry" );
-		sf.f_choice = LDAP_FILTER_EQUALITY;
-		sf.f_ava = &aa_subentry;
-		sf.f_av_desc = slap_schema.si_ad_objectClass;
-		sf.f_av_value = bv_subentry;
-		sf.f_next = nf.f_next;
-		nf.f_next = &sf;
-	}
-
-	/* Allocate IDL stack, plus 1 more for former tmp */
-	if ( depth+1 > bdb->bi_search_stack_depth ) {
-		stack = ch_malloc( (depth + 1) * BDB_IDL_UM_SIZE * sizeof( ID ) );
-	} else {
-		stack = search_stack( op );
-	}
-
-	if( op->ors_deref & LDAP_DEREF_SEARCHING ) {
-		rc = search_aliases( op, rs, e, txn, ids, scopes, stack );
-		if ( BDB_IDL_IS_ZERO( ids ) && rc == LDAP_SUCCESS )
-			rc = bdb_dn2idl( op, txn, &e->e_nname, BEI(e), ids, stack );
-	} else {
-		rc = bdb_dn2idl( op, txn, &e->e_nname, BEI(e), ids, stack );
-	}
-
-	if ( rc == LDAP_SUCCESS ) {
-		rc = bdb_filter_candidates( op, txn, &f, ids,
-			stack, stack+BDB_IDL_UM_SIZE );
-	}
-
-	if ( depth+1 > bdb->bi_search_stack_depth ) {
-		ch_free( stack );
-	}
-
-	if( rc ) {
-		Debug(LDAP_DEBUG_TRACE,
-			"bdb_search_candidates: failed (rc=%d)\n",
-			rc, NULL, NULL );
-
-	} else {
-		Debug(LDAP_DEBUG_TRACE,
-			"bdb_search_candidates: id=%ld first=%ld last=%ld\n",
-			(long) ids[0],
-			(long) BDB_IDL_FIRST(ids),
-			(long) BDB_IDL_LAST(ids) );
-	}
-
-	return rc;
-}
-
-static int
-parse_paged_cookie( Operation *op, SlapReply *rs )
-{
-	int		rc = LDAP_SUCCESS;
-	PagedResultsState *ps = op->o_pagedresults_state;
-
-	/* this function must be invoked only if the pagedResults
-	 * control has been detected, parsed and partially checked
-	 * by the frontend */
-	assert( get_pagedresults( op ) > SLAP_CONTROL_IGNORED );
-
-	/* cookie decoding/checks deferred to backend... */
-	if ( ps->ps_cookieval.bv_len ) {
-		PagedResultsCookie reqcookie;
-		if( ps->ps_cookieval.bv_len != sizeof( reqcookie ) ) {
-			/* bad cookie */
-			rs->sr_text = "paged results cookie is invalid";
-			rc = LDAP_PROTOCOL_ERROR;
-			goto done;
-		}
-
-		AC_MEMCPY( &reqcookie, ps->ps_cookieval.bv_val, sizeof( reqcookie ));
-
-		if ( reqcookie > ps->ps_cookie ) {
-			/* bad cookie */
-			rs->sr_text = "paged results cookie is invalid";
-			rc = LDAP_PROTOCOL_ERROR;
-			goto done;
-
-		} else if ( reqcookie < ps->ps_cookie ) {
-			rs->sr_text = "paged results cookie is invalid or old";
-			rc = LDAP_UNWILLING_TO_PERFORM;
-			goto done;
-		}
-
-	} else {
-		/* we're going to use ps_cookie */
-		op->o_conn->c_pagedresults_state.ps_cookie = 0;
-	}
-
-done:;
-
-	return rc;
-}
-
-static void
-send_paged_response( 
-	Operation	*op,
-	SlapReply	*rs,
-	ID		*lastid,
-	int		tentries )
-{
-	LDAPControl	*ctrls[2];
-	BerElementBuffer berbuf;
-	BerElement	*ber = (BerElement *)&berbuf;
-	PagedResultsCookie respcookie;
-	struct berval cookie;
-
-	Debug(LDAP_DEBUG_ARGS,
-		"send_paged_response: lastid=0x%08lx nentries=%d\n", 
-		lastid ? *lastid : 0, rs->sr_nentries, NULL );
-
-	ctrls[1] = NULL;
-
-	ber_init2( ber, NULL, LBER_USE_DER );
-
-	if ( lastid ) {
-		respcookie = ( PagedResultsCookie )(*lastid);
-		cookie.bv_len = sizeof( respcookie );
-		cookie.bv_val = (char *)&respcookie;
-
-	} else {
-		respcookie = ( PagedResultsCookie )0;
-		BER_BVSTR( &cookie, "" );
-	}
-
-	op->o_conn->c_pagedresults_state.ps_cookie = respcookie;
-	op->o_conn->c_pagedresults_state.ps_count =
-		((PagedResultsState *)op->o_pagedresults_state)->ps_count +
-		rs->sr_nentries;
-
-	/* return size of 0 -- no estimate */
-	ber_printf( ber, "{iO}", 0, &cookie ); 
-
-	ctrls[0] = op->o_tmpalloc( sizeof(LDAPControl), op->o_tmpmemctx );
-	if ( ber_flatten2( ber, &ctrls[0]->ldctl_value, 0 ) == -1 ) {
-		goto done;
-	}
-
-	ctrls[0]->ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
-	ctrls[0]->ldctl_iscritical = 0;
-
-	slap_add_ctrls( op, rs, ctrls );
-	rs->sr_err = LDAP_SUCCESS;
-	send_ldap_result( op, rs );
-
-done:
-	(void) ber_free_buf( ber );
-}
diff --git a/servers/slapd/back-bdb/tools.c b/servers/slapd/back-bdb/tools.c
deleted file mode 100644
index 1882ef2..0000000
--- a/servers/slapd/back-bdb/tools.c
+++ /dev/null
@@ -1,1327 +0,0 @@
-/* tools.c - tools for slap tools */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-#include <ac/errno.h>
-
-#define AVL_INTERNAL
-#include "back-bdb.h"
-#include "idl.h"
-
-static DBC *cursor = NULL;
-static DBT key, data;
-static EntryHeader eh;
-static ID nid, previd = NOID;
-static char ehbuf[16];
-
-typedef struct dn_id {
-	ID id;
-	struct berval dn;
-} dn_id;
-
-#define	HOLE_SIZE	4096
-static dn_id hbuf[HOLE_SIZE], *holes = hbuf;
-static unsigned nhmax = HOLE_SIZE;
-static unsigned nholes;
-
-static int index_nattrs;
-
-static struct berval	*tool_base;
-static int		tool_scope;
-static Filter		*tool_filter;
-static Entry		*tool_next_entry;
-
-#ifdef BDB_TOOL_IDL_CACHING
-#define bdb_tool_idl_cmp		BDB_SYMBOL(tool_idl_cmp)
-#define bdb_tool_idl_flush_one		BDB_SYMBOL(tool_idl_flush_one)
-#define bdb_tool_idl_flush		BDB_SYMBOL(tool_idl_flush)
-
-static int bdb_tool_idl_flush( BackendDB *be );
-
-#define	IDBLOCK	1024
-
-typedef struct bdb_tool_idl_cache_entry {
-	struct bdb_tool_idl_cache_entry *next;
-	ID ids[IDBLOCK];
-} bdb_tool_idl_cache_entry;
- 
-typedef struct bdb_tool_idl_cache {
-	struct berval kstr;
-	bdb_tool_idl_cache_entry *head, *tail;
-	ID first, last;
-	int count;
-} bdb_tool_idl_cache;
-
-static bdb_tool_idl_cache_entry *bdb_tool_idl_free_list;
-#endif	/* BDB_TOOL_IDL_CACHING */
-
-static ID bdb_tool_ix_id;
-static Operation *bdb_tool_ix_op;
-static int *bdb_tool_index_threads, bdb_tool_index_tcount;
-static void *bdb_tool_index_rec;
-static struct bdb_info *bdb_tool_info;
-static ldap_pvt_thread_mutex_t bdb_tool_index_mutex;
-static ldap_pvt_thread_cond_t bdb_tool_index_cond_main;
-static ldap_pvt_thread_cond_t bdb_tool_index_cond_work;
-
-#if DB_VERSION_FULL >= 0x04060000
-#define	USE_TRICKLE	1
-#else
-/* Seems to slow things down too much in BDB 4.5 */
-#undef USE_TRICKLE
-#endif
-
-#ifdef USE_TRICKLE
-static ldap_pvt_thread_mutex_t bdb_tool_trickle_mutex;
-static ldap_pvt_thread_cond_t bdb_tool_trickle_cond;
-static ldap_pvt_thread_cond_t bdb_tool_trickle_cond_end;
-
-static void * bdb_tool_trickle_task( void *ctx, void *ptr );
-static int bdb_tool_trickle_active;
-#endif
-
-static void * bdb_tool_index_task( void *ctx, void *ptr );
-
-static int
-bdb_tool_entry_get_int( BackendDB *be, ID id, Entry **ep );
-
-static int bdb_tool_threads;
-
-int bdb_tool_entry_open(
-	BackendDB *be, int mode )
-{
-	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
-
-	/* initialize key and data thangs */
-	DBTzero( &key );
-	DBTzero( &data );
-	key.flags = DB_DBT_USERMEM;
-	key.data = &nid;
-	key.size = key.ulen = sizeof( nid );
-	data.flags = DB_DBT_USERMEM;
-
-	if (cursor == NULL) {
-		int rc = bdb->bi_id2entry->bdi_db->cursor(
-			bdb->bi_id2entry->bdi_db, bdb->bi_cache.c_txn, &cursor,
-			bdb->bi_db_opflags );
-		if( rc != 0 ) {
-			return -1;
-		}
-	}
-
-	/* Set up for threaded slapindex */
-	if (( slapMode & (SLAP_TOOL_QUICK|SLAP_TOOL_READONLY)) == SLAP_TOOL_QUICK ) {
-		if ( !bdb_tool_info ) {
-#ifdef USE_TRICKLE
-			ldap_pvt_thread_mutex_init( &bdb_tool_trickle_mutex );
-			ldap_pvt_thread_cond_init( &bdb_tool_trickle_cond );
-			ldap_pvt_thread_cond_init( &bdb_tool_trickle_cond_end );
-			ldap_pvt_thread_pool_submit( &connection_pool, bdb_tool_trickle_task, bdb->bi_dbenv );
-#endif
-
-			ldap_pvt_thread_mutex_init( &bdb_tool_index_mutex );
-			ldap_pvt_thread_cond_init( &bdb_tool_index_cond_main );
-			ldap_pvt_thread_cond_init( &bdb_tool_index_cond_work );
-			if ( bdb->bi_nattrs ) {
-				int i;
-				bdb_tool_threads = slap_tool_thread_max - 1;
-				if ( bdb_tool_threads > 1 ) {
-					bdb_tool_index_threads = ch_malloc( bdb_tool_threads * sizeof( int ));
-					bdb_tool_index_rec = ch_malloc( bdb->bi_nattrs * sizeof( IndexRec ));
-					bdb_tool_index_tcount = bdb_tool_threads - 1;
-					for (i=1; i<bdb_tool_threads; i++) {
-						int *ptr = ch_malloc( sizeof( int ));
-						*ptr = i;
-						ldap_pvt_thread_pool_submit( &connection_pool,
-							bdb_tool_index_task, ptr );
-					}
-				}
-			}
-			bdb_tool_info = bdb;
-		}
-	}
-
-	return 0;
-}
-
-int bdb_tool_entry_close(
-	BackendDB *be )
-{
-	if ( bdb_tool_info ) {
-		slapd_shutdown = 1;
-#ifdef USE_TRICKLE
-		ldap_pvt_thread_mutex_lock( &bdb_tool_trickle_mutex );
-
-		/* trickle thread may not have started yet */
-		while ( !bdb_tool_trickle_active )
-			ldap_pvt_thread_cond_wait( &bdb_tool_trickle_cond_end,
-					&bdb_tool_trickle_mutex );
-
-		ldap_pvt_thread_cond_signal( &bdb_tool_trickle_cond );
-		while ( bdb_tool_trickle_active )
-			ldap_pvt_thread_cond_wait( &bdb_tool_trickle_cond_end,
-					&bdb_tool_trickle_mutex );
-		ldap_pvt_thread_mutex_unlock( &bdb_tool_trickle_mutex );
-#endif
-		if ( bdb_tool_threads > 1 ) {
-			ldap_pvt_thread_mutex_lock( &bdb_tool_index_mutex );
-
-			/* There might still be some threads starting */
-			while ( bdb_tool_index_tcount > 0 ) {
-				ldap_pvt_thread_cond_wait( &bdb_tool_index_cond_main,
-						&bdb_tool_index_mutex );
-			}
-
-			bdb_tool_index_tcount = bdb_tool_threads - 1;
-			ldap_pvt_thread_cond_broadcast( &bdb_tool_index_cond_work );
-
-			/* Make sure all threads are stopped */
-			while ( bdb_tool_index_tcount > 0 ) {
-				ldap_pvt_thread_cond_wait( &bdb_tool_index_cond_main,
-					&bdb_tool_index_mutex );
-			}
-			ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex );
-
-			ch_free( bdb_tool_index_threads );
-			ch_free( bdb_tool_index_rec );
-			bdb_tool_index_tcount = bdb_tool_threads - 1;
-		}
-		bdb_tool_info = NULL;
-		slapd_shutdown = 0;
-	}
-
-	if( eh.bv.bv_val ) {
-		ch_free( eh.bv.bv_val );
-		eh.bv.bv_val = NULL;
-	}
-
-	if( cursor ) {
-		cursor->c_close( cursor );
-		cursor = NULL;
-	}
-
-#ifdef BDB_TOOL_IDL_CACHING
-	bdb_tool_idl_flush( be );
-#endif
-
-	if( nholes ) {
-		unsigned i;
-		fprintf( stderr, "Error, entries missing!\n");
-		for (i=0; i<nholes; i++) {
-			fprintf(stderr, "  entry %ld: %s\n",
-				holes[i].id, holes[i].dn.bv_val);
-		}
-		return -1;
-	}
-			
-	return 0;
-}
-
-ID
-bdb_tool_entry_first_x(
-	BackendDB *be,
-	struct berval *base,
-	int scope,
-	Filter *f )
-{
-	tool_base = base;
-	tool_scope = scope;
-	tool_filter = f;
-	
-	return bdb_tool_entry_next( be );
-}
-
-ID bdb_tool_entry_next(
-	BackendDB *be )
-{
-	int rc;
-	ID id;
-	struct bdb_info *bdb;
-
-	assert( be != NULL );
-	assert( slapMode & SLAP_TOOL_MODE );
-
-	bdb = (struct bdb_info *) be->be_private;
-	assert( bdb != NULL );
-
-next:;
-	/* Get the header */
-	data.ulen = data.dlen = sizeof( ehbuf );
-	data.data = ehbuf;
-	data.flags |= DB_DBT_PARTIAL;
-	rc = cursor->c_get( cursor, &key, &data, DB_NEXT );
-
-	if( rc ) {
-		/* If we're doing linear indexing and there are more attrs to
-		 * index, and we're at the end of the database, start over.
-		 */
-		if ( index_nattrs && rc == DB_NOTFOUND ) {
-			/* optional - do a checkpoint here? */
-			bdb_attr_info_free( bdb->bi_attrs[0] );
-			bdb->bi_attrs[0] = bdb->bi_attrs[index_nattrs];
-			index_nattrs--;
-			rc = cursor->c_get( cursor, &key, &data, DB_FIRST );
-			if ( rc ) {
-				return NOID;
-			}
-		} else {
-			return NOID;
-		}
-	}
-
-	BDB_DISK2ID( key.data, &id );
-	previd = id;
-
-	if ( tool_filter || tool_base ) {
-		static Operation op = {0};
-		static Opheader ohdr = {0};
-
-		op.o_hdr = &ohdr;
-		op.o_bd = be;
-		op.o_tmpmemctx = NULL;
-		op.o_tmpmfuncs = &ch_mfuncs;
-
-		if ( tool_next_entry ) {
-			bdb_entry_release( &op, tool_next_entry, 0 );
-			tool_next_entry = NULL;
-		}
-
-		rc = bdb_tool_entry_get_int( be, id, &tool_next_entry );
-		if ( rc == LDAP_NO_SUCH_OBJECT ) {
-			goto next;
-		}
-
-		assert( tool_next_entry != NULL );
-
-#ifdef BDB_HIER
-		/* TODO: needed until BDB_HIER is handled accordingly
-		 * in bdb_tool_entry_get_int() */
-		if ( tool_base && !dnIsSuffixScope( &tool_next_entry->e_nname, tool_base, tool_scope ) )
-		{
-			bdb_entry_release( &op, tool_next_entry, 0 );
-			tool_next_entry = NULL;
-			goto next;
-		}
-#endif
-
-		if ( tool_filter && test_filter( NULL, tool_next_entry, tool_filter ) != LDAP_COMPARE_TRUE )
-		{
-			bdb_entry_release( &op, tool_next_entry, 0 );
-			tool_next_entry = NULL;
-			goto next;
-		}
-	}
-
-	return id;
-}
-
-ID bdb_tool_dn2id_get(
-	Backend *be,
-	struct berval *dn
-)
-{
-	Operation op = {0};
-	Opheader ohdr = {0};
-	EntryInfo *ei = NULL;
-	int rc;
-
-	if ( BER_BVISEMPTY(dn) )
-		return 0;
-
-	op.o_hdr = &ohdr;
-	op.o_bd = be;
-	op.o_tmpmemctx = NULL;
-	op.o_tmpmfuncs = &ch_mfuncs;
-
-	rc = bdb_cache_find_ndn( &op, 0, dn, &ei );
-	if ( ei ) bdb_cache_entryinfo_unlock( ei );
-	if ( rc == DB_NOTFOUND )
-		return NOID;
-	
-	return ei->bei_id;
-}
-
-static int
-bdb_tool_entry_get_int( BackendDB *be, ID id, Entry **ep )
-{
-	Entry *e = NULL;
-	char *dptr;
-	int rc, eoff;
-
-	assert( be != NULL );
-	assert( slapMode & SLAP_TOOL_MODE );
-
-	if ( ( tool_filter || tool_base ) && id == previd && tool_next_entry != NULL ) {
-		*ep = tool_next_entry;
-		tool_next_entry = NULL;
-		return LDAP_SUCCESS;
-	}
-
-	if ( id != previd ) {
-		data.ulen = data.dlen = sizeof( ehbuf );
-		data.data = ehbuf;
-		data.flags |= DB_DBT_PARTIAL;
-
-		BDB_ID2DISK( id, &nid );
-		rc = cursor->c_get( cursor, &key, &data, DB_SET );
-		if ( rc ) {
-			rc = LDAP_OTHER;
-			goto done;
-		}
-	}
-
-	/* Get the header */
-	dptr = eh.bv.bv_val;
-	eh.bv.bv_val = ehbuf;
-	eh.bv.bv_len = data.size;
-	rc = entry_header( &eh );
-	eoff = eh.data - eh.bv.bv_val;
-	eh.bv.bv_val = dptr;
-	if ( rc ) {
-		rc = LDAP_OTHER;
-		goto done;
-	}
-
-	/* Get the size */
-	data.flags &= ~DB_DBT_PARTIAL;
-	data.ulen = 0;
-	rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
-	if ( rc != DB_BUFFER_SMALL ) {
-		rc = LDAP_OTHER;
-		goto done;
-	}
-
-	/* Allocate a block and retrieve the data */
-	eh.bv.bv_len = eh.nvals * sizeof( struct berval ) + data.size;
-	eh.bv.bv_val = ch_realloc( eh.bv.bv_val, eh.bv.bv_len );
-	eh.data = eh.bv.bv_val + eh.nvals * sizeof( struct berval );
-	data.data = eh.data;
-	data.ulen = data.size;
-
-	/* Skip past already parsed nattr/nvals */
-	eh.data += eoff;
-
-	rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
-	if ( rc ) {
-		rc = LDAP_OTHER;
-		goto done;
-	}
-
-#ifndef BDB_HIER
-	/* TODO: handle BDB_HIER accordingly */
-	if ( tool_base != NULL ) {
-		struct berval ndn;
-		entry_decode_dn( &eh, NULL, &ndn );
-
-		if ( !dnIsSuffixScope( &ndn, tool_base, tool_scope ) ) {
-			return LDAP_NO_SUCH_OBJECT;
-		}
-	}
-#endif
-
-#ifdef SLAP_ZONE_ALLOC
-	/* FIXME: will add ctx later */
-	rc = entry_decode( &eh, &e, NULL );
-#else
-	rc = entry_decode( &eh, &e );
-#endif
-
-	if( rc == LDAP_SUCCESS ) {
-		e->e_id = id;
-#ifdef BDB_HIER
-		if ( slapMode & SLAP_TOOL_READONLY ) {
-			struct bdb_info *bdb = (struct bdb_info *) be->be_private;
-			EntryInfo *ei = NULL;
-			Operation op = {0};
-			Opheader ohdr = {0};
-
-			op.o_hdr = &ohdr;
-			op.o_bd = be;
-			op.o_tmpmemctx = NULL;
-			op.o_tmpmfuncs = &ch_mfuncs;
-
-			rc = bdb_cache_find_parent( &op, bdb->bi_cache.c_txn, id, &ei );
-			if ( rc == LDAP_SUCCESS ) {
-				bdb_cache_entryinfo_unlock( ei );
-				e->e_private = ei;
-				ei->bei_e = e;
-				bdb_fix_dn( e, 0 );
-				ei->bei_e = NULL;
-				e->e_private = NULL;
-			}
-		}
-#endif
-	}
-done:
-	if ( e != NULL ) {
-		*ep = e;
-	}
-
-	return rc;
-}
-
-Entry*
-bdb_tool_entry_get( BackendDB *be, ID id )
-{
-	Entry *e = NULL;
-
-	(void)bdb_tool_entry_get_int( be, id, &e );
-	return e;
-}
-
-static int bdb_tool_next_id(
-	Operation *op,
-	DB_TXN *tid,
-	Entry *e,
-	struct berval *text,
-	int hole )
-{
-	struct berval dn = e->e_name;
-	struct berval ndn = e->e_nname;
-	struct berval pdn, npdn;
-	EntryInfo *ei = NULL, eidummy;
-	int rc;
-
-	if (ndn.bv_len == 0) {
-		e->e_id = 0;
-		return 0;
-	}
-
-	rc = bdb_cache_find_ndn( op, tid, &ndn, &ei );
-	if ( ei ) bdb_cache_entryinfo_unlock( ei );
-	if ( rc == DB_NOTFOUND ) {
-		if ( !be_issuffix( op->o_bd, &ndn ) ) {
-			ID eid = e->e_id;
-			dnParent( &dn, &pdn );
-			dnParent( &ndn, &npdn );
-			e->e_name = pdn;
-			e->e_nname = npdn;
-			rc = bdb_tool_next_id( op, tid, e, text, 1 );
-			e->e_name = dn;
-			e->e_nname = ndn;
-			if ( rc ) {
-				return rc;
-			}
-			/* If parent didn't exist, it was created just now
-			 * and its ID is now in e->e_id. Make sure the current
-			 * entry gets added under the new parent ID.
-			 */
-			if ( eid != e->e_id ) {
-				eidummy.bei_id = e->e_id;
-				ei = &eidummy;
-			}
-		}
-		rc = bdb_next_id( op->o_bd, &e->e_id );
-		if ( rc ) {
-			snprintf( text->bv_val, text->bv_len,
-				"next_id failed: %s (%d)",
-				db_strerror(rc), rc );
-		Debug( LDAP_DEBUG_ANY,
-			"=> bdb_tool_next_id: %s\n", text->bv_val, 0, 0 );
-			return rc;
-		}
-		rc = bdb_dn2id_add( op, tid, ei, e );
-		if ( rc ) {
-			snprintf( text->bv_val, text->bv_len, 
-				"dn2id_add failed: %s (%d)",
-				db_strerror(rc), rc );
-		Debug( LDAP_DEBUG_ANY,
-			"=> bdb_tool_next_id: %s\n", text->bv_val, 0, 0 );
-		} else if ( hole ) {
-			if ( nholes == nhmax - 1 ) {
-				if ( holes == hbuf ) {
-					holes = ch_malloc( nhmax * sizeof(dn_id) * 2 );
-					AC_MEMCPY( holes, hbuf, sizeof(hbuf) );
-				} else {
-					holes = ch_realloc( holes, nhmax * sizeof(dn_id) * 2 );
-				}
-				nhmax *= 2;
-			}
-			ber_dupbv( &holes[nholes].dn, &ndn );
-			holes[nholes++].id = e->e_id;
-		}
-	} else if ( !hole ) {
-		unsigned i, j;
-
-		e->e_id = ei->bei_id;
-
-		for ( i=0; i<nholes; i++) {
-			if ( holes[i].id == e->e_id ) {
-				free(holes[i].dn.bv_val);
-				for (j=i;j<nholes;j++) holes[j] = holes[j+1];
-				holes[j].id = 0;
-				nholes--;
-				break;
-			} else if ( holes[i].id > e->e_id ) {
-				break;
-			}
-		}
-	}
-	return rc;
-}
-
-static int
-bdb_tool_index_add(
-	Operation *op,
-	DB_TXN *txn,
-	Entry *e )
-{
-	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-
-	if ( !bdb->bi_nattrs )
-		return 0;
-
-	if ( bdb_tool_threads > 1 ) {
-		IndexRec *ir;
-		int i, rc;
-		Attribute *a;
-		
-		ir = bdb_tool_index_rec;
-		memset(ir, 0, bdb->bi_nattrs * sizeof( IndexRec ));
-
-		for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
-			rc = bdb_index_recset( bdb, a, a->a_desc->ad_type, 
-				&a->a_desc->ad_tags, ir );
-			if ( rc )
-				return rc;
-		}
-		bdb_tool_ix_id = e->e_id;
-		bdb_tool_ix_op = op;
-		ldap_pvt_thread_mutex_lock( &bdb_tool_index_mutex );
-		/* Wait for all threads to be ready */
-		while ( bdb_tool_index_tcount > 0 ) {
-			ldap_pvt_thread_cond_wait( &bdb_tool_index_cond_main, 
-				&bdb_tool_index_mutex );
-		}
-		for ( i=1; i<bdb_tool_threads; i++ )
-			bdb_tool_index_threads[i] = LDAP_BUSY;
-		bdb_tool_index_tcount = bdb_tool_threads - 1;
-		ldap_pvt_thread_cond_broadcast( &bdb_tool_index_cond_work );
-		ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex );
-		rc = bdb_index_recrun( op, bdb, ir, e->e_id, 0 );
-		if ( rc )
-			return rc;
-		ldap_pvt_thread_mutex_lock( &bdb_tool_index_mutex );
-		for ( i=1; i<bdb_tool_threads; i++ ) {
-			if ( bdb_tool_index_threads[i] == LDAP_BUSY ) {
-				ldap_pvt_thread_cond_wait( &bdb_tool_index_cond_main, 
-					&bdb_tool_index_mutex );
-				i--;
-				continue;
-			}
-			if ( bdb_tool_index_threads[i] ) {
-				rc = bdb_tool_index_threads[i];
-				break;
-			}
-		}
-		ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex );
-		return rc;
-	} else {
-		return bdb_index_entry_add( op, txn, e );
-	}
-}
-
-ID bdb_tool_entry_put(
-	BackendDB *be,
-	Entry *e,
-	struct berval *text )
-{
-	int rc;
-	struct bdb_info *bdb;
-	DB_TXN *tid = NULL;
-	Operation op = {0};
-	Opheader ohdr = {0};
-
-	assert( be != NULL );
-	assert( slapMode & SLAP_TOOL_MODE );
-
-	assert( text != NULL );
-	assert( text->bv_val != NULL );
-	assert( text->bv_val[0] == '\0' );	/* overconservative? */
-
-	Debug( LDAP_DEBUG_TRACE, "=> " LDAP_XSTRING(bdb_tool_entry_put)
-		"( %ld, \"%s\" )\n", (long) e->e_id, e->e_dn, 0 );
-
-	bdb = (struct bdb_info *) be->be_private;
-
-	if (! (slapMode & SLAP_TOOL_QUICK)) {
-	rc = TXN_BEGIN( bdb->bi_dbenv, NULL, &tid, 
-		bdb->bi_db_opflags );
-	if( rc != 0 ) {
-		snprintf( text->bv_val, text->bv_len,
-			"txn_begin failed: %s (%d)",
-			db_strerror(rc), rc );
-		Debug( LDAP_DEBUG_ANY,
-			"=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
-			 text->bv_val, 0, 0 );
-		return NOID;
-	}
-	Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_tool_entry_put) ": txn id: %x\n",
-		tid->id(tid), 0, 0 );
-	}
-
-	op.o_hdr = &ohdr;
-	op.o_bd = be;
-	op.o_tmpmemctx = NULL;
-	op.o_tmpmfuncs = &ch_mfuncs;
-
-	/* add dn2id indices */
-	rc = bdb_tool_next_id( &op, tid, e, text, 0 );
-	if( rc != 0 ) {
-		goto done;
-	}
-
-#ifdef USE_TRICKLE
-	if (( slapMode & SLAP_TOOL_QUICK ) && (( e->e_id & 0xfff ) == 0xfff )) {
-		ldap_pvt_thread_cond_signal( &bdb_tool_trickle_cond );
-	}
-#endif
-
-	if ( !bdb->bi_linear_index )
-		rc = bdb_tool_index_add( &op, tid, e );
-	if( rc != 0 ) {
-		snprintf( text->bv_val, text->bv_len,
-				"index_entry_add failed: %s (%d)",
-				rc == LDAP_OTHER ? "Internal error" :
-				db_strerror(rc), rc );
-		Debug( LDAP_DEBUG_ANY,
-			"=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
-			text->bv_val, 0, 0 );
-		goto done;
-	}
-
-	/* id2entry index */
-	rc = bdb_id2entry_add( be, tid, e );
-	if( rc != 0 ) {
-		snprintf( text->bv_val, text->bv_len,
-				"id2entry_add failed: %s (%d)",
-				db_strerror(rc), rc );
-		Debug( LDAP_DEBUG_ANY,
-			"=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
-			text->bv_val, 0, 0 );
-		goto done;
-	}
-
-done:
-	if( rc == 0 ) {
-		if ( !( slapMode & SLAP_TOOL_QUICK )) {
-		rc = TXN_COMMIT( tid, 0 );
-		if( rc != 0 ) {
-			snprintf( text->bv_val, text->bv_len,
-					"txn_commit failed: %s (%d)",
-					db_strerror(rc), rc );
-			Debug( LDAP_DEBUG_ANY,
-				"=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
-				text->bv_val, 0, 0 );
-			e->e_id = NOID;
-		}
-		}
-
-	} else {
-		if ( !( slapMode & SLAP_TOOL_QUICK )) {
-		TXN_ABORT( tid );
-		snprintf( text->bv_val, text->bv_len,
-			"txn_aborted! %s (%d)",
-			rc == LDAP_OTHER ? "Internal error" :
-			db_strerror(rc), rc );
-		Debug( LDAP_DEBUG_ANY,
-			"=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
-			text->bv_val, 0, 0 );
-		}
-		e->e_id = NOID;
-	}
-
-	return e->e_id;
-}
-
-int bdb_tool_entry_reindex(
-	BackendDB *be,
-	ID id,
-	AttributeDescription **adv )
-{
-	struct bdb_info *bi = (struct bdb_info *) be->be_private;
-	int rc;
-	Entry *e;
-	DB_TXN *tid = NULL;
-	Operation op = {0};
-	Opheader ohdr = {0};
-
-	Debug( LDAP_DEBUG_ARGS,
-		"=> " LDAP_XSTRING(bdb_tool_entry_reindex) "( %ld )\n",
-		(long) id, 0, 0 );
-	assert( tool_base == NULL );
-	assert( tool_filter == NULL );
-
-	/* No indexes configured, nothing to do. Could return an
-	 * error here to shortcut things.
-	 */
-	if (!bi->bi_attrs) {
-		return 0;
-	}
-
-	/* Check for explicit list of attrs to index */
-	if ( adv ) {
-		int i, j, n;
-
-		if ( bi->bi_attrs[0]->ai_desc != adv[0] ) {
-			/* count */
-			for ( n = 0; adv[n]; n++ ) ;
-
-			/* insertion sort */
-			for ( i = 0; i < n; i++ ) {
-				AttributeDescription *ad = adv[i];
-				for ( j = i-1; j>=0; j--) {
-					if ( SLAP_PTRCMP( adv[j], ad ) <= 0 ) break;
-					adv[j+1] = adv[j];
-				}
-				adv[j+1] = ad;
-			}
-		}
-
-		for ( i = 0; adv[i]; i++ ) {
-			if ( bi->bi_attrs[i]->ai_desc != adv[i] ) {
-				for ( j = i+1; j < bi->bi_nattrs; j++ ) {
-					if ( bi->bi_attrs[j]->ai_desc == adv[i] ) {
-						AttrInfo *ai = bi->bi_attrs[i];
-						bi->bi_attrs[i] = bi->bi_attrs[j];
-						bi->bi_attrs[j] = ai;
-						break;
-					}
-				}
-				if ( j == bi->bi_nattrs ) {
-					Debug( LDAP_DEBUG_ANY,
-						LDAP_XSTRING(bdb_tool_entry_reindex)
-						": no index configured for %s\n",
-						adv[i]->ad_cname.bv_val, 0, 0 );
-					return -1;
-				}
-			}
-		}
-		bi->bi_nattrs = i;
-	}
-
-	/* Get the first attribute to index */
-	if (bi->bi_linear_index && !index_nattrs) {
-		index_nattrs = bi->bi_nattrs - 1;
-		bi->bi_nattrs = 1;
-	}
-
-	e = bdb_tool_entry_get( be, id );
-
-	if( e == NULL ) {
-		Debug( LDAP_DEBUG_ANY,
-			LDAP_XSTRING(bdb_tool_entry_reindex)
-			": could not locate id=%ld\n",
-			(long) id, 0, 0 );
-		return -1;
-	}
-
-	op.o_hdr = &ohdr;
-	op.o_bd = be;
-	op.o_tmpmemctx = NULL;
-	op.o_tmpmfuncs = &ch_mfuncs;
-
-	if (! (slapMode & SLAP_TOOL_QUICK)) {
-	rc = TXN_BEGIN( bi->bi_dbenv, NULL, &tid, bi->bi_db_opflags );
-	if( rc != 0 ) {
-		Debug( LDAP_DEBUG_ANY,
-			"=> " LDAP_XSTRING(bdb_tool_entry_reindex) ": "
-			"txn_begin failed: %s (%d)\n",
-			db_strerror(rc), rc, 0 );
-		goto done;
-	}
-	Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_tool_entry_reindex) ": txn id: %x\n",
-		tid->id(tid), 0, 0 );
-	}
- 	
-	/*
-	 * just (re)add them for now
-	 * assume that some other routine (not yet implemented)
-	 * will zap index databases
-	 *
-	 */
-
-	Debug( LDAP_DEBUG_TRACE,
-		"=> " LDAP_XSTRING(bdb_tool_entry_reindex) "( %ld, \"%s\" )\n",
-		(long) id, e->e_dn, 0 );
-
-	rc = bdb_tool_index_add( &op, tid, e );
-
-done:
-	if( rc == 0 ) {
-		if (! (slapMode & SLAP_TOOL_QUICK)) {
-		rc = TXN_COMMIT( tid, 0 );
-		if( rc != 0 ) {
-			Debug( LDAP_DEBUG_ANY,
-				"=> " LDAP_XSTRING(bdb_tool_entry_reindex)
-				": txn_commit failed: %s (%d)\n",
-				db_strerror(rc), rc, 0 );
-			e->e_id = NOID;
-		}
-		}
-
-	} else {
-		if (! (slapMode & SLAP_TOOL_QUICK)) {
-		TXN_ABORT( tid );
-		Debug( LDAP_DEBUG_ANY,
-			"=> " LDAP_XSTRING(bdb_tool_entry_reindex)
-			": txn_aborted! %s (%d)\n",
-			db_strerror(rc), rc, 0 );
-		}
-		e->e_id = NOID;
-	}
-	bdb_entry_release( &op, e, 0 );
-
-	return rc;
-}
-
-ID bdb_tool_entry_modify(
-	BackendDB *be,
-	Entry *e,
-	struct berval *text )
-{
-	int rc;
-	struct bdb_info *bdb;
-	DB_TXN *tid = NULL;
-	Operation op = {0};
-	Opheader ohdr = {0};
-
-	assert( be != NULL );
-	assert( slapMode & SLAP_TOOL_MODE );
-
-	assert( text != NULL );
-	assert( text->bv_val != NULL );
-	assert( text->bv_val[0] == '\0' );	/* overconservative? */
-
-	assert ( e->e_id != NOID );
-
-	Debug( LDAP_DEBUG_TRACE,
-		"=> " LDAP_XSTRING(bdb_tool_entry_modify) "( %ld, \"%s\" )\n",
-		(long) e->e_id, e->e_dn, 0 );
-
-	bdb = (struct bdb_info *) be->be_private;
-
-	if (! (slapMode & SLAP_TOOL_QUICK)) {
-		if( cursor ) {
-			cursor->c_close( cursor );
-			cursor = NULL;
-		}
-		rc = TXN_BEGIN( bdb->bi_dbenv, NULL, &tid, 
-			bdb->bi_db_opflags );
-		if( rc != 0 ) {
-			snprintf( text->bv_val, text->bv_len,
-				"txn_begin failed: %s (%d)",
-				db_strerror(rc), rc );
-			Debug( LDAP_DEBUG_ANY,
-				"=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
-				 text->bv_val, 0, 0 );
-			return NOID;
-		}
-		Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_tool_entry_modify) ": txn id: %x\n",
-			tid->id(tid), 0, 0 );
-	}
-
-	op.o_hdr = &ohdr;
-	op.o_bd = be;
-	op.o_tmpmemctx = NULL;
-	op.o_tmpmfuncs = &ch_mfuncs;
-
-	/* id2entry index */
-	rc = bdb_id2entry_update( be, tid, e );
-	if( rc != 0 ) {
-		snprintf( text->bv_val, text->bv_len,
-				"id2entry_add failed: %s (%d)",
-				db_strerror(rc), rc );
-		Debug( LDAP_DEBUG_ANY,
-			"=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
-			text->bv_val, 0, 0 );
-		goto done;
-	}
-
-done:
-	if( rc == 0 ) {
-		if (! (slapMode & SLAP_TOOL_QUICK)) {
-		rc = TXN_COMMIT( tid, 0 );
-		if( rc != 0 ) {
-			snprintf( text->bv_val, text->bv_len,
-					"txn_commit failed: %s (%d)",
-					db_strerror(rc), rc );
-			Debug( LDAP_DEBUG_ANY,
-				"=> " LDAP_XSTRING(bdb_tool_entry_modify) ": "
-				"%s\n", text->bv_val, 0, 0 );
-			e->e_id = NOID;
-		}
-		}
-
-	} else {
-		if (! (slapMode & SLAP_TOOL_QUICK)) {
-		TXN_ABORT( tid );
-		snprintf( text->bv_val, text->bv_len,
-			"txn_aborted! %s (%d)",
-			db_strerror(rc), rc );
-		Debug( LDAP_DEBUG_ANY,
-			"=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
-			text->bv_val, 0, 0 );
-		}
-		e->e_id = NOID;
-	}
-
-	return e->e_id;
-}
-
-#ifdef BDB_TOOL_IDL_CACHING
-static int
-bdb_tool_idl_cmp( const void *v1, const void *v2 )
-{
-	const bdb_tool_idl_cache *c1 = v1, *c2 = v2;
-	int rc;
-
-	if (( rc = c1->kstr.bv_len - c2->kstr.bv_len )) return rc;
-	return memcmp( c1->kstr.bv_val, c2->kstr.bv_val, c1->kstr.bv_len );
-}
-
-static int
-bdb_tool_idl_flush_one( void *v1, void *arg )
-{
-	bdb_tool_idl_cache *ic = v1;
-	DB *db = arg;
-	struct bdb_info *bdb = bdb_tool_info;
-	bdb_tool_idl_cache_entry *ice;
-	DBC *curs;
-	DBT key, data;
-	int i, rc;
-	ID id, nid;
-
-	/* Freshly allocated, ignore it */
-	if ( !ic->head && ic->count <= BDB_IDL_DB_SIZE ) {
-		return 0;
-	}
-
-	rc = db->cursor( db, NULL, &curs, 0 );
-	if ( rc )
-		return -1;
-
-	DBTzero( &key );
-	DBTzero( &data );
-
-	bv2DBT( &ic->kstr, &key );
-
-	data.size = data.ulen = sizeof( ID );
-	data.flags = DB_DBT_USERMEM;
-	data.data = &nid;
-
-	rc = curs->c_get( curs, &key, &data, DB_SET );
-	/* If key already exists and we're writing a range... */
-	if ( rc == 0 && ic->count > BDB_IDL_DB_SIZE ) {
-		/* If it's not currently a range, must delete old info */
-		if ( nid ) {
-			/* Skip lo */
-			while ( curs->c_get( curs, &key, &data, DB_NEXT_DUP ) == 0 )
-				curs->c_del( curs, 0 );
-
-			nid = 0;
-			/* Store range marker */
-			curs->c_put( curs, &key, &data, DB_KEYFIRST );
-		} else {
-			
-			/* Skip lo */
-			rc = curs->c_get( curs, &key, &data, DB_NEXT_DUP );
-
-			/* Get hi */
-			rc = curs->c_get( curs, &key, &data, DB_NEXT_DUP );
-
-			/* Delete hi */
-			curs->c_del( curs, 0 );
-		}
-		BDB_ID2DISK( ic->last, &nid );
-		curs->c_put( curs, &key, &data, DB_KEYLAST );
-		rc = 0;
-	} else if ( rc && rc != DB_NOTFOUND ) {
-		rc = -1;
-	} else if ( ic->count > BDB_IDL_DB_SIZE ) {
-		/* range, didn't exist before */
-		nid = 0;
-		rc = curs->c_put( curs, &key, &data, DB_KEYLAST );
-		if ( rc == 0 ) {
-			BDB_ID2DISK( ic->first, &nid );
-			rc = curs->c_put( curs, &key, &data, DB_KEYLAST );
-			if ( rc == 0 ) {
-				BDB_ID2DISK( ic->last, &nid );
-				rc = curs->c_put( curs, &key, &data, DB_KEYLAST );
-			}
-		}
-		if ( rc ) {
-			rc = -1;
-		}
-	} else {
-		int n;
-
-		/* Just a normal write */
-		rc = 0;
-		for ( ice = ic->head, n=0; ice; ice = ice->next, n++ ) {
-			int end;
-			if ( ice->next ) {
-				end = IDBLOCK;
-			} else {
-				end = ic->count & (IDBLOCK-1);
-				if ( !end )
-					end = IDBLOCK;
-			}
-			for ( i=0; i<end; i++ ) {
-				if ( !ice->ids[i] ) continue;
-				BDB_ID2DISK( ice->ids[i], &nid );
-				rc = curs->c_put( curs, &key, &data, DB_NODUPDATA );
-				if ( rc ) {
-					if ( rc == DB_KEYEXIST ) {
-						rc = 0;
-						continue;
-					}
-					rc = -1;
-					break;
-				}
-			}
-			if ( rc ) {
-				rc = -1;
-				break;
-			}
-		}
-		if ( ic->head ) {
-			ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock );
-			ic->tail->next = bdb_tool_idl_free_list;
-			bdb_tool_idl_free_list = ic->head;
-			bdb->bi_idl_cache_size -= n;
-			ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
-		}
-	}
-	if ( ic != db->app_private ) {
-		ch_free( ic );
-	} else {
-		ic->head = ic->tail = NULL;
-	}
-	curs->c_close( curs );
-	return rc;
-}
-
-static int
-bdb_tool_idl_flush_db( DB *db, bdb_tool_idl_cache *ic )
-{
-	Avlnode *root = db->app_private;
-	int rc;
-
-	db->app_private = ic;
-	rc = avl_apply( root, bdb_tool_idl_flush_one, db, -1, AVL_INORDER );
-	avl_free( root, NULL );
-	db->app_private = NULL;
-	if ( rc != -1 )
-		rc = 0;
-	return rc;
-}
-
-static int
-bdb_tool_idl_flush( BackendDB *be )
-{
-	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
-	DB *db;
-	Avlnode *root;
-	int i, rc = 0;
-
-	for ( i=BDB_NDB; i < bdb->bi_ndatabases; i++ ) {
-		db = bdb->bi_databases[i]->bdi_db;
-		if ( !db->app_private ) continue;
-		rc = bdb_tool_idl_flush_db( db, NULL );
-		if ( rc )
-			break;
-	}
-	if ( !rc ) {
-		bdb->bi_idl_cache_size = 0;
-	}
-	return rc;
-}
-
-int bdb_tool_idl_add(
-	BackendDB *be,
-	DB *db,
-	DB_TXN *txn,
-	DBT *key,
-	ID id )
-{
-	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
-	bdb_tool_idl_cache *ic, itmp;
-	bdb_tool_idl_cache_entry *ice;
-	int rc;
-
-	if ( !bdb->bi_idl_cache_max_size )
-		return bdb_idl_insert_key( be, db, txn, key, id );
-
-	DBT2bv( key, &itmp.kstr );
-
-	ic = avl_find( (Avlnode *)db->app_private, &itmp, bdb_tool_idl_cmp );
-
-	/* No entry yet, create one */
-	if ( !ic ) {
-		DBC *curs;
-		DBT data;
-		ID nid;
-		int rc;
-
-		ic = ch_malloc( sizeof( bdb_tool_idl_cache ) + itmp.kstr.bv_len );
-		ic->kstr.bv_len = itmp.kstr.bv_len;
-		ic->kstr.bv_val = (char *)(ic+1);
-		AC_MEMCPY( ic->kstr.bv_val, itmp.kstr.bv_val, ic->kstr.bv_len );
-		ic->head = ic->tail = NULL;
-		ic->last = 0;
-		ic->count = 0;
-		avl_insert( (Avlnode **)&db->app_private, ic, bdb_tool_idl_cmp,
-			avl_dup_error );
-
-		/* load existing key count here */
-		rc = db->cursor( db, NULL, &curs, 0 );
-		if ( rc ) return rc;
-
-		data.ulen = sizeof( ID );
-		data.flags = DB_DBT_USERMEM;
-		data.data = &nid;
-		rc = curs->c_get( curs, key, &data, DB_SET );
-		if ( rc == 0 ) {
-			if ( nid == 0 ) {
-				ic->count = BDB_IDL_DB_SIZE+1;
-			} else {
-				db_recno_t count;
-
-				curs->c_count( curs, &count, 0 );
-				ic->count = count;
-				BDB_DISK2ID( &nid, &ic->first );
-			}
-		}
-		curs->c_close( curs );
-	}
-	/* are we a range already? */
-	if ( ic->count > BDB_IDL_DB_SIZE ) {
-		ic->last = id;
-		return 0;
-	/* Are we at the limit, and converting to a range? */
-	} else if ( ic->count == BDB_IDL_DB_SIZE ) {
-		int n;
-		for ( ice = ic->head, n=0; ice; ice = ice->next, n++ )
-			/* counting */ ;
-		if ( n ) {
-			ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock );
-			ic->tail->next = bdb_tool_idl_free_list;
-			bdb_tool_idl_free_list = ic->head;
-			bdb->bi_idl_cache_size -= n;
-			ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
-		}
-		ic->head = ic->tail = NULL;
-		ic->last = id;
-		ic->count++;
-		return 0;
-	}
-	/* No free block, create that too */
-	if ( !ic->tail || ( ic->count & (IDBLOCK-1)) == 0) {
-		ice = NULL;
-		ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock );
-		if ( bdb->bi_idl_cache_size >= bdb->bi_idl_cache_max_size ) {
-			ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
-			rc = bdb_tool_idl_flush_db( db, ic );
-			if ( rc )
-				return rc;
-			avl_insert( (Avlnode **)&db->app_private, ic, bdb_tool_idl_cmp,
-				avl_dup_error );
-			ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock );
-		}
-		bdb->bi_idl_cache_size++;
-		if ( bdb_tool_idl_free_list ) {
-			ice = bdb_tool_idl_free_list;
-			bdb_tool_idl_free_list = ice->next;
-		}
-		ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
-		if ( !ice ) {
-			ice = ch_malloc( sizeof( bdb_tool_idl_cache_entry ));
-		}
-		memset( ice, 0, sizeof( *ice ));
-		if ( !ic->head ) {
-			ic->head = ice;
-		} else {
-			ic->tail->next = ice;
-		}
-		ic->tail = ice;
-		if ( !ic->count )
-			ic->first = id;
-	}
-	ice = ic->tail;
-	ice->ids[ ic->count & (IDBLOCK-1) ] = id;
-	ic->count++;
-
-	return 0;
-}
-#endif
-
-#ifdef USE_TRICKLE
-static void *
-bdb_tool_trickle_task( void *ctx, void *ptr )
-{
-	DB_ENV *env = ptr;
-	int wrote;
-
-	ldap_pvt_thread_mutex_lock( &bdb_tool_trickle_mutex );
-	bdb_tool_trickle_active = 1;
-	ldap_pvt_thread_cond_signal( &bdb_tool_trickle_cond_end );
-	while ( 1 ) {
-		ldap_pvt_thread_cond_wait( &bdb_tool_trickle_cond,
-			&bdb_tool_trickle_mutex );
-		if ( slapd_shutdown )
-			break;
-		env->memp_trickle( env, 30, &wrote );
-	}
-	bdb_tool_trickle_active = 0;
-	ldap_pvt_thread_cond_signal( &bdb_tool_trickle_cond_end );
-	ldap_pvt_thread_mutex_unlock( &bdb_tool_trickle_mutex );
-
-	return NULL;
-}
-#endif
-
-static void *
-bdb_tool_index_task( void *ctx, void *ptr )
-{
-	int base = *(int *)ptr;
-
-	free( ptr );
-	while ( 1 ) {
-		ldap_pvt_thread_mutex_lock( &bdb_tool_index_mutex );
-		bdb_tool_index_tcount--;
-		if ( !bdb_tool_index_tcount )
-			ldap_pvt_thread_cond_signal( &bdb_tool_index_cond_main );
-		ldap_pvt_thread_cond_wait( &bdb_tool_index_cond_work,
-			&bdb_tool_index_mutex );
-		if ( slapd_shutdown ) {
-			bdb_tool_index_tcount--;
-			if ( !bdb_tool_index_tcount )
-				ldap_pvt_thread_cond_signal( &bdb_tool_index_cond_main );
-			ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex );
-			break;
-		}
-		ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex );
-
-		bdb_tool_index_threads[base] = bdb_index_recrun( bdb_tool_ix_op,
-			bdb_tool_info, bdb_tool_index_rec, bdb_tool_ix_id, base );
-	}
-
-	return NULL;
-}
diff --git a/servers/slapd/back-bdb/trans.c b/servers/slapd/back-bdb/trans.c
deleted file mode 100644
index 1971d29..0000000
--- a/servers/slapd/back-bdb/trans.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/* trans.c - bdb backend transaction routines */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "back-bdb.h"
-#include "lber_pvt.h"
-#include "lutil.h"
-
-
-/* Congestion avoidance code
- * for Deadlock Rollback
- */
-
-void
-bdb_trans_backoff( int num_retries )
-{
-	int i;
-	int delay = 0;
-	int pow_retries = 1;
-	unsigned long key = 0;
-	unsigned long max_key = -1;
-	struct timeval timeout;
-
-	lutil_entropy( (unsigned char *) &key, sizeof( unsigned long ));
-
-	for ( i = 0; i < num_retries; i++ ) {
-		if ( i >= 5 ) break;
-		pow_retries *= 4;
-	}
-
-	delay = 16384 * (key * (double) pow_retries / (double) max_key);
-	delay = delay ? delay : 1;
-
-	Debug( LDAP_DEBUG_TRACE,  "delay = %d, num_retries = %d\n", delay, num_retries, 0 );
-
-	timeout.tv_sec = delay / 1000000;
-	timeout.tv_usec = delay % 1000000;
-	select( 0, NULL, NULL, NULL, &timeout );
-}
diff --git a/servers/slapd/back-hdb/Makefile.in b/servers/slapd/back-hdb/Makefile.in
deleted file mode 100644
index 150cee5..0000000
--- a/servers/slapd/back-hdb/Makefile.in
+++ /dev/null
@@ -1,70 +0,0 @@
-# Makefile for back-hdb
-# $OpenLDAP$
-## This work is part of OpenLDAP Software <http://www.openldap.org/>.
-##
-## Copyright 1998-2020 The OpenLDAP Foundation.
-## All rights reserved.
-##
-## Redistribution and use in source and binary forms, with or without
-## modification, are permitted only as authorized by the OpenLDAP
-## Public License.
-##
-## A copy of this license is available in the file LICENSE in the
-## top-level directory of the distribution or, alternatively, at
-## <http://www.OpenLDAP.org/license.html>.
-#
-## Copyright 2003 Howard Chu @ Symas Corp. See master COPYRIGHT file for terms.
-
-XXDIR = $(srcdir)/../back-bdb
-
-XXSRCS = init.c tools.c config.c \
-	add.c bind.c compare.c delete.c modify.c modrdn.c search.c \
-	extended.c referral.c operational.c \
-	attr.c index.c key.c dbcache.c filterindex.c trans.c \
-	dn2entry.c dn2id.c error.c id2entry.c idl.c nextid.c cache.c \
-	monitor.c
-SRCS = $(XXSRCS)
-OBJS = init.lo tools.lo config.lo \
-	add.lo bind.lo compare.lo delete.lo modify.lo modrdn.lo search.lo \
-	extended.lo referral.lo operational.lo \
-	attr.lo index.lo key.lo dbcache.lo filterindex.lo trans.lo \
-	dn2entry.lo dn2id.lo error.lo id2entry.lo idl.lo nextid.lo cache.lo \
-	monitor.lo
-
-LDAP_INCDIR= ../../../include       
-LDAP_LIBDIR= ../../../libraries
-
-BUILD_OPT = "--enable-hdb"
-BUILD_MOD = @BUILD_HDB@
-
-mod_DEFS = -DSLAPD_IMPORT
-MOD_DEFS = $(@BUILD_HDB@_DEFS)
-MOD_LIBS = $(BDB_LIBS)
-
-shared_LDAP_LIBS = $(LDAP_LIBLDAP_R_LA) $(LDAP_LIBLBER_LA)
-NT_LINK_LIBS = -L.. -lslapd $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
-UNIX_LINK_LIBS = $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
-
-.links : Makefile
-	@for i in $(XXSRCS); do \
-		$(RM) $$i; \
-		$(LN_S) $(XXDIR)/$$i . ; \
-	done
-	touch .links
-
-$(XXSRCS) : .links
-
-LIBBASE = back_hdb
-
-XINCPATH = -I.. -I$(srcdir)/.. -I$(srcdir) -I$(XXDIR)
-XDEFS = $(MODULES_CPPFLAGS)
-
-depend-local-lib: .links
-
-all-local-lib:	../.backend
-
-../.backend: lib$(LIBBASE).a
-	@touch $@
-
-veryclean-local: FORCE
-	$(RM) $(XXSRCS) .links
diff --git a/servers/slapd/back-hdb/back-bdb.h b/servers/slapd/back-hdb/back-bdb.h
deleted file mode 100644
index 9f92d8b..0000000
--- a/servers/slapd/back-hdb/back-bdb.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* back-bdb.h - hdb back-end header file */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2020 The OpenLDAP Foundation.
- * Portions Copyright 2003 Howard Chu @ Symas Corp.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by Howard Chu for inclusion
- * in OpenLDAP Software.
- */
-
-#ifndef _BACK_HDB_H_
-#define _BACK_HDB_H_
-
-#ifndef BDB_HIER
-#define	BDB_HIER	1
-#endif
-
-#include "../back-bdb/back-bdb.h"
-
-#endif /* _BACK_HDB_H_ */
diff --git a/servers/slapd/back-monitor/init.c b/servers/slapd/back-monitor/init.c
index b264115..ce9a34a 100644
--- a/servers/slapd/back-monitor/init.c
+++ b/servers/slapd/back-monitor/init.c
@@ -1991,8 +1991,8 @@ monitor_back_initialize(
 		{ "olmGenericAttributes",		"olmSubSystemAttributes:0" },
 		{ "olmDatabaseAttributes",		"olmSubSystemAttributes:1" },
 
-		/* for example, back-bdb specific attrs
-		 * are in "olmDatabaseAttributes:1"
+		/* for example, back-mdb specific attrs
+		 * are in "olmDatabaseAttributes:12"
 		 *
 		 * NOTE: developers, please record here OID assignments
 		 * for other modules */
@@ -2002,8 +2002,8 @@ monitor_back_initialize(
 		{ "olmGenericObjectClasses",		"olmSubSystemObjectClasses:0" },
 		{ "olmDatabaseObjectClasses",		"olmSubSystemObjectClasses:1" },
 
-		/* for example, back-bdb specific objectClasses
-		 * are in "olmDatabaseObjectClasses:1"
+		/* for example, back-mdb specific objectClasses
+		 * are in "olmDatabaseObjectClasses:12"
 		 *
 		 * NOTE: developers, please record here OID assignments
 		 * for other modules */
diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c
index 0c6a7f5..538eef1 100644
--- a/servers/slapd/bconfig.c
+++ b/servers/slapd/bconfig.c
@@ -238,7 +238,7 @@ static OidRec OidMacros[] = {
  * Backend/Database registry
  *
  * OLcfg{Bk|Db}{Oc|At}:0		-> common
- * OLcfg{Bk|Db}{Oc|At}:1		-> back-bdb(/back-hdb)
+ * OLcfg{Bk|Db}{Oc|At}:1		-> back-bdb(/back-hdb) (removed)
  * OLcfg{Bk|Db}{Oc|At}:2		-> back-ldif
  * OLcfg{Bk|Db}{Oc|At}:3		-> back-ldap/meta
  * OLcfg{Bk|Db}{Oc|At}:4		-> back-monitor
diff --git a/servers/slapd/dn.c b/servers/slapd/dn.c
index 06698b0..89b80e3 100644
--- a/servers/slapd/dn.c
+++ b/servers/slapd/dn.c
@@ -1131,8 +1131,7 @@ rdn_validate( struct berval *rdn )
 
 /* build_new_dn:
  *
- * Used by back-bdb back_modrdn to create the new dn of entries being
- * renamed.
+ * Used to create the new dn of entries being renamed.
  *
  * new_dn = parent (p_dn) + separator + rdn (newrdn) + null.
  */
diff --git a/servers/slapd/overlays/pcache.c b/servers/slapd/overlays/pcache.c
index f88ca09..0d7ff8c 100644
--- a/servers/slapd/overlays/pcache.c
+++ b/servers/slapd/overlays/pcache.c
@@ -5616,7 +5616,7 @@ cleanup:;
 	cm->monitor_cb = (void *)cb;
 
 	/* we don't need to keep track of the attributes, because
-	 * bdb_monitor_free() takes care of everything */
+	 * mdb_monitor_free() takes care of everything */
 	if ( a != NULL ) {
 		attrs_free( a );
 	}
@@ -5700,7 +5700,7 @@ pcache_initialize()
 	}
 #endif /* PCACHE_EXOP_QUERY_DELETE */
 
-	argv[ 0 ] = "back-bdb/back-hdb monitor";
+	argv[ 0 ] = "back-mdb monitor";
 	c.argv = argv;
 	c.argc = 3;
 	c.fname = argv[0];
diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h
index f003bb9..591f49d 100644
--- a/servers/slapd/slap.h
+++ b/servers/slapd/slap.h
@@ -1805,7 +1805,6 @@ struct BackendDB {
 
 /*
  * define to honor hasSubordinates operational attribute in search filters
- * (in previous use there was a flaw with back-bdb; now it is fixed).
  */
 #define		be_has_subordinates bd_info->bi_has_subordinates
 
diff --git a/servers/slapd/slapd.ldif b/servers/slapd/slapd.ldif
index 5aba54d..b2b38ea 100644
--- a/servers/slapd/slapd.ldif
+++ b/servers/slapd/slapd.ldif
@@ -30,8 +30,7 @@ olcPidFile: %LOCALSTATEDIR%/run/slapd.pid
 #objectClass: olcModuleList
 #cn: module
 #olcModulepath:	%MODULEDIR%
-#olcModuleload:	back_bdb.la
-#olcModuleload:	back_hdb.la
+#olcModuleload:	back_mdb.la
 #olcModuleload:	back_ldap.la
 #olcModuleload:	back_passwd.la
 #olcModuleload:	back_shell.la
diff --git a/tests/Makefile.in b/tests/Makefile.in
index d841846..ef98813 100644
--- a/tests/Makefile.in
+++ b/tests/Makefile.in
@@ -16,15 +16,11 @@
 RUN=./run
 SUBDIRS= progs
 
-BUILD_BDB=@BUILD_BDB@
-BUILD_HDB=@BUILD_HDB@
 BUILD_MDB=@BUILD_MDB@
 BUILD_SQL=@BUILD_SQL@
 
 # test primary backends (default)
 test tests:
-	@$(MAKE) bdb
-	@$(MAKE) hdb
 	@$(MAKE) mdb
 
 # test all backends
@@ -32,22 +28,6 @@ alltests: tests
 	@$(MAKE) sql
 	@$(MAKE) ldif
 
-bdb test-bdb:	bdb-$(BUILD_BDB)
-bdb-no:
-	@echo "run configure with --enable-bdb to run BDB tests"
-
-bdb-yes bdb-mod: FORCE
-	@echo "Initiating LDAP tests for BDB..."
-	@$(RUN) -b bdb all
-
-hdb test-hdb:	hdb-$(BUILD_HDB)
-hdb-no:
-	@echo "run configure with --enable-hdb to run HDB tests"
-
-hdb-yes hdb-mod: FORCE
-	@echo "Initiating LDAP tests for HDB..."
-	@$(RUN) -b hdb all
-
 mdb test-mdb:	mdb-$(BUILD_MDB)
 mdb-no:
 	@echo "run configure with --enable-mdb to run MDB tests"
@@ -70,26 +50,10 @@ ldif test-ldif: FORCE
 
 regressions:	FORCE
 	@echo "Testing (available) ITS regressions"
-	@$(MAKE) bdb-its
-	@$(MAKE) hdb-its
 	@$(MAKE) mdb-its
 
 its: regressions
 
-bdb-its: bdb-its-$(BUILD_BDB)
-bdb-its-no:
-	@echo "run configure with --enable-bdb to run BDB ITS regressions"
-
-bdb-its-yes bdb-its-mod: FORCE
-	@$(RUN) -b bdb its-all
-
-hdb-its: hdb-its-$(BUILD_HDB)
-hdb-its-no:
-	@echo "run configure with --enable-hdb to run HDB ITS regressions"
-
-hdb-its-yes hdb-its-mod: FORCE
-	@$(RUN) -b hdb its-all
-
 mdb-its: mdb-its-$(BUILD_MDB)
 mdb-its-no:
 	@echo "run configure with --enable-mdb to run MDB ITS regressions"
diff --git a/tests/README b/tests/README
index 1a25df8..a3b5d2f 100644
--- a/tests/README
+++ b/tests/README
@@ -2,8 +2,6 @@ This directory contains a series of test scripts which are used to
 verify basic functionality of the LDAP libraries and slapd.
 
 	To run all of the tests, type "make test".
-	To run BDB tests, type "make bdb".
-	To run HDB tests, type "make hdb".
 	To run MDB tests, type "make mdb".
 	To run SQL tests, define SLAPD_USE_SQL=<rdbms> and type
 		"make sql"; define SLAPD_USE_SQLWRITE=yes
diff --git a/tests/data/regressions/its4184/its4184 b/tests/data/regressions/its4184/its4184
index 08f9f1c..4170f05 100755
--- a/tests/data/regressions/its4184/its4184
+++ b/tests/data/regressions/its4184/its4184
@@ -16,10 +16,6 @@
 echo "running defines.sh"
 . $SRCDIR/scripts/defines.sh
 
-if test "$BACKEND" != "bdb" && test "$BACKEND" != "hdb" ; then
-	echo "Warning: this test is known to affect bdb and hdb, although it may impact other backends as well."
-fi
-
 mkdir -p $DBDIR1A $DBDIR2A
 
 ITS=4184
diff --git a/tests/data/regressions/its4448/its4448 b/tests/data/regressions/its4448/its4448
index 7f50999..9319374 100755
--- a/tests/data/regressions/its4448/its4448
+++ b/tests/data/regressions/its4448/its4448
@@ -47,22 +47,6 @@ ITS=4448
 ITSDIR=$DATADIR/regressions/its$ITS
 ITSCONF=$ITSDIR/slapd-meta.conf
 
-# NOTE: this could be added to all tests...
-if test "$BACKEND" = "bdb" || test "$BACKEND" = "hdb" ; then
-	if test "x$DB_CONFIG" != "x" ; then \
-		if test -f $DB_CONFIG ; then
-			echo "==> using DB_CONFIG \"$DB_CONFIG\""
-			cp $DB_CONFIG $DBDIR1
-			cp $DB_CONFIG $DBDIR2
-		else
-			echo "==> DB_CONFIG must point to a valid file (ignored)"
-		fi
-	else
-		echo "==> set \"DB_CONFIG\" to the DB_CONFIG file you want to use for the test."
-	fi
-	echo ""
-fi
-
 echo "Starting slapd on TCP/IP port $PORT1..."
 . $CONFFILTER $BACKEND $MONITORDB < $CONF > $CONF1
 $SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
diff --git a/tests/data/slapd-proxyauthz.conf b/tests/data/slapd-proxyauthz.conf
index 2ff6563..b28d60d 100644
--- a/tests/data/slapd-proxyauthz.conf
+++ b/tests/data/slapd-proxyauthz.conf
@@ -64,10 +64,6 @@ pcachetemplate   	(cn=) 0 86400 86400 86400 180
 
 pcachebind		(cn=) 0 3600 sub ou=people,dc=example,dc=com
 
-#bdb#cachesize 20
-#hdb#cachesize 20
-#bdb#dbnosync
-#hdb#dbnosync
 #mdb#dbnosync
 
 #~null~#directory	@TESTDIR@/db.2.a
diff --git a/tests/data/slapd-proxycache.conf b/tests/data/slapd-proxycache.conf
index b96d850..db3b60e 100644
--- a/tests/data/slapd-proxycache.conf
+++ b/tests/data/slapd-proxycache.conf
@@ -54,10 +54,6 @@ pcachetemplate   	(mail=) 0 @TTL@ @NTTL@ @STTL@
 pcachetemplate   	(&(objectclass=)(uid=)) 1 @TTL@ @NTTL@ @STTL@ @TTR@
 pcachebind		(&(objectclass=person)(uid=)) 1 @BTTR@ sub "ou=Alumni Association,ou=people,dc=example,dc=com"
 
-#bdb#cachesize 20
-#hdb#cachesize 20
-#bdb#dbnosync
-#hdb#dbnosync
 #mdb#dbnosync
 
 #~null~#directory	@TESTDIR@/db.2.a
diff --git a/tests/data/slapd-ref-slave.conf b/tests/data/slapd-ref-slave.conf
index 3d30ca7..5d8d83f 100644
--- a/tests/data/slapd-ref-slave.conf
+++ b/tests/data/slapd-ref-slave.conf
@@ -34,8 +34,6 @@ argsfile	@TESTDIR@/slapd.2.args
 referral	"@URI1@"
 
 database	@BACKEND@
-#bdb#cachesize	0
-#hdb#cachesize	0
 
 suffix		"o=University of Mich,c=US"
 rootdn		"cn=Manager,o=University of Mich,c=US"
diff --git a/tests/data/slapd.conf b/tests/data/slapd.conf
index 97c883b..309eb5a 100644
--- a/tests/data/slapd.conf
+++ b/tests/data/slapd.conf
@@ -44,8 +44,6 @@ rootpw		secret
 #~null~#directory	@TESTDIR@/db.1.a
 #indexdb#index		objectClass	eq
 #indexdb#index		cn,sn,uid	pres,eq,sub
-#bdb#checkpoint		1024 5
-#hdb#checkpoint		1024 5
 #mdb#maxsize	33554432
 #ndb#dbname db_1
 #ndb#include @DATADIR@/ndb.conf
diff --git a/tests/run.in b/tests/run.in
index 8830dd4..6705265 100644
--- a/tests/run.in
+++ b/tests/run.in
@@ -24,8 +24,6 @@ EGREP_CMD="@EGREP@"
 export SRCDIR TOPSRCDIR LN_S EGREP_CMD
 
 # backends known to ./run -b <backend> (used to deduce $BACKENDTYPE)
-AC_bdb=@BUILD_BDB@
-AC_hdb=@BUILD_HDB@
 AC_ldif=yes
 AC_mdb=@BUILD_MDB@
 AC_null=@BUILD_NULL@
@@ -69,7 +67,7 @@ if test "${AC_meta}" = "metamod" && test "${AC_LIBS_DYNAMIC}" = "static" ; then
 	AC_meta="metano"
 fi
 
-export AC_bdb AC_hdb AC_ldap AC_mdb AC_meta AC_monitor AC_null AC_relay AC_sql \
+export AC_ldap AC_mdb AC_meta AC_monitor AC_null AC_relay AC_sql \
 	AC_accesslog AC_constraint AC_dds AC_dynlist AC_memberof AC_pcache AC_ppolicy \
 	AC_refint AC_retcode AC_rwm AC_unique AC_syncprov AC_translucent \
 	AC_valsort \
@@ -153,7 +151,7 @@ while test $# -gt 0 ; do
 done
 
 if test -z "$BACKEND" ; then
-	for b in bdb hdb mdb ; do
+	for b in mdb ; do
 		if eval "test \"\$AC_$b\" != no" ; then
 			BACKEND=$b
 			break
@@ -174,7 +172,7 @@ fi
 # maindb: main storage backend.  Currently index,limits,mode,paged results.
 INDEXDB=noindexdb MAINDB=nomaindb
 case $BACKEND in
-	bdb|hdb|mdb) INDEXDB=indexdb MAINDB=maindb ;;
+	mdb) INDEXDB=indexdb MAINDB=maindb ;;
 	ndb) INDEXDB=indexdb ;;
 esac
 
diff --git a/tests/scripts/test023-refint b/tests/scripts/test023-refint
index 546b9c7..b51134d 100755
--- a/tests/scripts/test023-refint
+++ b/tests/scripts/test023-refint
@@ -189,9 +189,8 @@ if test $RC != 0 ; then
 	exit $RC
 fi
 
-if test $BACKEND != "bdb" ; then
-	$LDAPMODIFY -v -D "$REFINTDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
-		$TESTOUT 2>&1 << EDEL
+$LDAPMODIFY -v -D "$REFINTDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
+	$TESTOUT 2>&1 << EDEL
 version: 1
 dn: cn=group,o=refint
 changetype: add
@@ -205,65 +204,65 @@ member: uid=theman,ou=users,o=refint
 member: uid=richard,ou=users,o=refint
 EDEL
 
-	RC=$?
-	if test $RC != 0 ; then
-		echo "ldapmodify failed ($RC)!"
-		test $KILLSERVERS != no && kill -HUP $KILLPIDS
-		exit $RC
-	fi
+RC=$?
+if test $RC != 0 ; then
+	echo "ldapmodify failed ($RC)!"
+	test $KILLSERVERS != no && kill -HUP $KILLPIDS
+	exit $RC
+fi
 
-	sleep 1;
+sleep 1;
 
-	$LDAPSEARCH -S "" -b "o=refint" -h $LOCALHOST -p $PORT1 \
-		manager member secretary > $SEARCHOUT 2>&1
-	RC=$?
-	if test $RC != 0 ; then
-		echo "ldapsearch failed ($RC)!"
-		test $KILLSERVERS != no && kill -HUP $KILLPIDS
-		exit $RC
-	fi
+$LDAPSEARCH -S "" -b "o=refint" -h $LOCALHOST -p $PORT1 \
+	manager member secretary > $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+	echo "ldapsearch failed ($RC)!"
+	test $KILLSERVERS != no && kill -HUP $KILLPIDS
+	exit $RC
+fi
 
-	$EGREP_CMD "(manager|member|secretary):" $SEARCHOUT \
-		| sed "s/ou=users/ou=people/g" | \
-		sort > $TESTOUT 2>&1
+$EGREP_CMD "(manager|member|secretary):" $SEARCHOUT \
+	| sed "s/ou=users/ou=people/g" | \
+	sort > $TESTOUT 2>&1
 
-	echo "testing subtree rename"
-	$LDAPMODRDN -D "$REFINTDN" -r -h $LOCALHOST -p $PORT1 -w $PASSWD > \
-		/dev/null 2>&1 'ou=users,o=refint' 'ou=people'
-	RC=$?
-	if test $RC != 0 ; then
-		echo "ldapmodrdn failed ($RC)!"
-		test $KILLSERVERS != no && kill -HUP $KILLPIDS
-		exit $RC
-	fi
+echo "testing subtree rename"
+$LDAPMODRDN -D "$REFINTDN" -r -h $LOCALHOST -p $PORT1 -w $PASSWD > \
+	/dev/null 2>&1 'ou=users,o=refint' 'ou=people'
+RC=$?
+if test $RC != 0 ; then
+	echo "ldapmodrdn failed ($RC)!"
+	test $KILLSERVERS != no && kill -HUP $KILLPIDS
+	exit $RC
+fi
 
-	sleep 1;
+sleep 1;
 
-	echo "Using ldapsearch to check dependents new rdn..."
+echo "Using ldapsearch to check dependents new rdn..."
 
-	$LDAPSEARCH -S "" -b "o=refint" -h $LOCALHOST -p $PORT1 \
-		manager member secretary > $SEARCHOUT 2>&1
+$LDAPSEARCH -S "" -b "o=refint" -h $LOCALHOST -p $PORT1 \
+	manager member secretary > $SEARCHOUT 2>&1
 
-	RC=$?
-	if test $RC != 0 ; then
-		echo "ldapsearch failed ($RC)!"
-		test $KILLSERVERS != no && kill -HUP $KILLPIDS
-		exit $RC
-	fi
+RC=$?
+if test $RC != 0 ; then
+	echo "ldapsearch failed ($RC)!"
+	test $KILLSERVERS != no && kill -HUP $KILLPIDS
+	exit $RC
+fi
 
-	$EGREP_CMD "(manager|member|secretary):" $SEARCHOUT \
-		| sort > $SEARCHFLT 2>&1
+$EGREP_CMD "(manager|member|secretary):" $SEARCHOUT \
+	| sort > $SEARCHFLT 2>&1
 
-	echo "Comparing ldapsearch results against original..."
-	$CMP $TESTOUT $SEARCHFLT > $CMPOUT
+echo "Comparing ldapsearch results against original..."
+$CMP $TESTOUT $SEARCHFLT > $CMPOUT
 
-	if test $? != 0 ; then
-		echo "comparison failed - subtree rename operations did not complete correctly"
-		test $KILLSERVERS != no && kill -HUP $KILLPIDS
-		exit 1
-	fi
+if test $? != 0 ; then
+	echo "comparison failed - subtree rename operations did not complete correctly"
+	test $KILLSERVERS != no && kill -HUP $KILLPIDS
+	exit 1
 fi
 
+
 test $KILLSERVERS != no && kill -HUP $KILLPIDS
 
 echo ">>>>> Test succeeded"
diff --git a/tests/scripts/test025-limits b/tests/scripts/test025-limits
index 8d39c6b..551b969 100755
--- a/tests/scripts/test025-limits
+++ b/tests/scripts/test025-limits
@@ -750,7 +750,7 @@ case $RC in
 esac
 
 if test $MAINDB != maindb ; then
-		# only bdb|hdb|mdb currently supports pagedResults control
+		# only mdb currently supports pagedResults control
 		test $KILLSERVERS != no && kill -HUP $KILLPIDS
 
 		echo ">>>>> Test succeeded"
diff --git a/tests/scripts/test036-meta-concurrency b/tests/scripts/test036-meta-concurrency
index 2a4146c..3344f45 100755
--- a/tests/scripts/test036-meta-concurrency
+++ b/tests/scripts/test036-meta-concurrency
@@ -40,22 +40,6 @@ rm -rf $TESTDIR
 
 mkdir -p $TESTDIR $DBDIR1 $DBDIR2
 
-# NOTE: this could be added to all tests...
-if test "$BACKEND" = "bdb" || test "$BACKEND" = "hdb" ; then
-	if test "x$DB_CONFIG" != "x" ; then \
-		if test -f $DB_CONFIG ; then
-			echo "==> using DB_CONFIG \"$DB_CONFIG\""
-			cp $DB_CONFIG $DBDIR1
-			cp $DB_CONFIG $DBDIR2
-		else
-			echo "==> DB_CONFIG must point to a valid file (ignored)"
-		fi
-	else
-		echo "==> set \"DB_CONFIG\" to the DB_CONFIG file you want to use for the test."
-	fi
-	echo ""
-fi
-
 echo "Starting slapd on TCP/IP port $PORT1..."
 . $CONFFILTER $BACKEND $MONITORDB < $METACONF1 > $CONF1
 $SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
diff --git a/tests/scripts/test040-subtree-rename b/tests/scripts/test040-subtree-rename
index 671d626..f1057d6 100755
--- a/tests/scripts/test040-subtree-rename
+++ b/tests/scripts/test040-subtree-rename
@@ -16,11 +16,6 @@
 echo "running defines.sh"
 . $SRCDIR/scripts/defines.sh
 
-if test $BACKEND = bdb ; then
-	echo "subtree rename not supported by back-$BACKEND"
-	exit 0
-fi
-
 mkdir -p $TESTDIR $DBDIR1
 
 echo "Starting slapd on TCP/IP port $PORT1..."
diff --git a/tests/scripts/test043-delta-syncrepl b/tests/scripts/test043-delta-syncrepl
index 3c7c629..686bf1c 100755
--- a/tests/scripts/test043-delta-syncrepl
+++ b/tests/scripts/test043-delta-syncrepl
@@ -32,7 +32,7 @@ fi
 
 mkdir -p $TESTDIR $DBDIR1A $DBDIR1B $DBDIR2
 
-SPEC="mdb=a,bdb=a,hdb=a"
+SPEC="mdb=a"
 
 #
 # Test replication:
diff --git a/tests/scripts/test052-memberof b/tests/scripts/test052-memberof
index 4b2a5d9..a73a929 100755
--- a/tests/scripts/test052-memberof
+++ b/tests/scripts/test052-memberof
@@ -72,11 +72,10 @@ EOF
 	fi
 fi
 
-indexInclude="" mainInclude="" bdbInclude="# " nullExclude=""
+indexInclude="" mainInclude="" " nullExclude=""
 test $INDEXDB = indexdb	|| indexInclude="# "
 test $MAINDB  = maindb	|| mainInclude="# "
 case $BACKEND in
-bdb | hdb) bdbInclude="" ;;
 null) nullExclude="# " ;;
 esac
 
@@ -114,7 +113,6 @@ olcRootDN: cn=Manager,$BASEDN
 olcRootPW:: c2VjcmV0
 olcMonitoring: TRUE
 ${nullExclude}olcDbDirectory: $TESTDIR/db.1.a/
-${bdbInclude}olcDbCacheSize: 1000
 ${indexInclude}olcDbIndex: objectClass eq
 ${indexInclude}olcDbIndex: cn pres,eq,sub
 ${indexInclude}olcDbIndex: uid pres,eq,sub
diff --git a/tests/scripts/test056-monitor b/tests/scripts/test056-monitor
index 06713df..7a87eaa 100755
--- a/tests/scripts/test056-monitor
+++ b/tests/scripts/test056-monitor
@@ -85,8 +85,7 @@ echo "Using ldapsearch to read database monitor entries..."
 $LDAPSEARCH -S "" -b "$DATABASESMONITORDN" -h $LOCALHOST -p $PORT1 \
 	'objectclass=*' \
 	structuralObjectClass entryDN namingContexts readOnly \
-	monitorIsShadow monitorContext \
-	olmBDBEntryCache olmBDBDNCache olmBDBIDLCache \
+	monitorIsShadow monitorContext
 	> $SEARCHOUT 2>&1
 RC=$?
 
@@ -101,11 +100,8 @@ $LDIFFILTER -b monitor < $SEARCHOUT > $SEARCHFLT
 
 TMPMONITOROUT2=$MONITOROUT2
 case $BACKEND in
-bdb|hdb)
-	;;
 *)
 	TMPMONITOROUT2=$TESTDIR/monitor2.out
-	grep -v "olmBDB" $MONITOROUT2 > $TMPMONITOROUT2
 	;;
 esac
 
diff --git a/tests/scripts/test057-memberof-refint b/tests/scripts/test057-memberof-refint
index 5f02a77..ba480f8 100755
--- a/tests/scripts/test057-memberof-refint
+++ b/tests/scripts/test057-memberof-refint
@@ -27,11 +27,6 @@ if test $REFINT = refintno; then
 	exit 0
 fi 
 
-if test $BACKEND = bdb; then
-	echo "$BACKEND backend does not support subtree rename, test skipped"
-	exit 0
-fi
-
 mkdir -p $TESTDIR $DBDIR1 $TESTDIR/confdir
 
 $SLAPPASSWD -g -n >$CONFIGPWF
@@ -66,11 +61,10 @@ fi
 
 cat /dev/null > $TESTOUT
 
-indexInclude="" mainInclude="" bdbInclude="# " nullExclude=""
+indexInclude="" mainInclude="" nullExclude=""
 test $INDEXDB = indexdb	|| indexInclude="# "
 test $MAINDB  = maindb	|| mainInclude="# "
 case $BACKEND in
-bdb | hdb) bdbInclude="" ;;
 null) nullExclude="# " ;;
 esac
 
@@ -104,7 +98,6 @@ olcRootDN: cn=Manager,$BASEDN
 olcRootPW:: c2VjcmV0
 olcMonitoring: TRUE
 ${nullExclude}olcDbDirectory: $TESTDIR/db.1.a/
-${bdbInclude}olcDbCacheSize: 1000
 ${indexInclude}olcDbIndex: objectClass eq
 ${indexInclude}olcDbIndex: cn pres,eq,sub
 ${indexInclude}olcDbIndex: uid pres,eq,sub
diff --git a/tests/scripts/test061-syncreplication-initiation b/tests/scripts/test061-syncreplication-initiation
index 5d27e52..fda7a1b 100755
--- a/tests/scripts/test061-syncreplication-initiation
+++ b/tests/scripts/test061-syncreplication-initiation
@@ -63,7 +63,6 @@ KILLPIDS=
 $SLAPPASSWD -g -n >$CONFIGPWF
 
 case "$BACKEND" in
-	bdb|hdb)	olcDbCheckpoint="olcDbCheckpoint";;
 	*)		olcDbCheckpoint="# olcDbCheckpoint";;
 esac
 
-- 
2.19.1

