From a3c567152ce0cc64ff0cd4a70c62c3afef92ccb4 Mon Sep 17 00:00:00 2001 From: orange-snn Date: Thu, 25 Feb 2021 10:56:38 +0800 Subject: [PATCH] delete libdb-devel in buildrequires and requires --- backport-Fix-test-suite.patch | 71 + backport-ITS-9010-More-BDB-HDB-cleanup.patch | 406 + backport-ITS-9010-regenerate-configure.patch | 1783 ++ backport-delete-back-bdb-back-hdb.patch | 22206 +++++++++++++++++ openldap.spec | 23 +- 5 files changed, 24482 insertions(+), 7 deletions(-) create mode 100644 backport-Fix-test-suite.patch create mode 100644 backport-ITS-9010-More-BDB-HDB-cleanup.patch create mode 100644 backport-ITS-9010-regenerate-configure.patch create mode 100644 backport-delete-back-bdb-back-hdb.patch diff --git a/backport-Fix-test-suite.patch b/backport-Fix-test-suite.patch new file mode 100644 index 0000000..cc8f72e --- /dev/null +++ b/backport-Fix-test-suite.patch @@ -0,0 +1,71 @@ +From 70f87370f99e78ac3874501bfe5124dbb86185a8 Mon Sep 17 00:00:00 2001 +From: zhangqiumiao +Date: Fri, 25 Sep 2020 21:56:43 +0800 +Subject: [PATCH] backport Fix test suite + +--- + tests/data/monitor2.out | 3 --- + tests/scripts/test052-memberof | 2 +- + tests/scripts/test056-monitor | 11 ++--------- + 3 files changed, 3 insertions(+), 13 deletions(-) + +diff --git a/tests/data/monitor2.out b/tests/data/monitor2.out +index 26e9ce9..20209d1 100644 +--- a/tests/data/monitor2.out ++++ b/tests/data/monitor2.out +@@ -10,9 +10,6 @@ structuralObjectClass: monitoredObject + monitorIsShadow: FALSE + namingContexts: o=OpenLDAP Project,l=Internet + readOnly: FALSE +-olmBDBEntryCache: 0 +-olmBDBDNCache: 0 +-olmBDBIDLCache: 0 + entryDN: cn=Database 1,cn=Databases,cn=Monitor + + dn: cn=Database 2,cn=Databases,cn=Monitor +diff --git a/tests/scripts/test052-memberof b/tests/scripts/test052-memberof +index a73a929..1dba946 100755 +--- a/tests/scripts/test052-memberof ++++ b/tests/scripts/test052-memberof +@@ -72,7 +72,7 @@ EOF + fi + fi + +-indexInclude="" mainInclude="" " nullExclude="" ++indexInclude="" mainInclude="" nullExclude="" + test $INDEXDB = indexdb || indexInclude="# " + test $MAINDB = maindb || mainInclude="# " + case $BACKEND in +diff --git a/tests/scripts/test056-monitor b/tests/scripts/test056-monitor +index 7a87eaa..0e1ba20 100755 +--- a/tests/scripts/test056-monitor ++++ b/tests/scripts/test056-monitor +@@ -85,7 +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 ++ monitorIsShadow monitorContext \ + > $SEARCHOUT 2>&1 + RC=$? + +@@ -98,15 +98,8 @@ fi + echo "Filtering ldapsearch results..." + $LDIFFILTER -b monitor < $SEARCHOUT > $SEARCHFLT + +-TMPMONITOROUT2=$MONITOROUT2 +-case $BACKEND in +-*) +- TMPMONITOROUT2=$TESTDIR/monitor2.out +- ;; +-esac +- + echo "Comparing filter output..." +-$CMP $SEARCHFLT $TMPMONITOROUT2 > $CMPOUT ++$CMP $SEARCHFLT $MONITOROUT2 > $CMPOUT + + if test $? != 0 ; then + echo "comparison failed - database monitor output is not correct" +-- +2.19.1 + diff --git a/backport-ITS-9010-More-BDB-HDB-cleanup.patch b/backport-ITS-9010-More-BDB-HDB-cleanup.patch new file mode 100644 index 0000000..9739b8c --- /dev/null +++ b/backport-ITS-9010-More-BDB-HDB-cleanup.patch @@ -0,0 +1,406 @@ +From ac37a67536d37ae059ed120f00b540429be6b4e0 Mon Sep 17 00:00:00 2001 +From: zhangqiumiao +Date: Sun, 27 Sep 2020 15:01:05 +0800 +Subject: [PATCH] backport ITS#9010 More BDB/HDB cleanup + +--- + doc/guide/admin/aspell.en.pws | 7 - + tests/data/regressions/its4337/config.out | 129 ------------------ + tests/data/regressions/its4337/its4337 | 157 ---------------------- + tests/data/regressions/its4337/slapd.conf | 36 ----- + 4 files changed, 329 deletions(-) + delete mode 100644 tests/data/regressions/its4337/config.out + delete mode 100755 tests/data/regressions/its4337/its4337 + delete mode 100644 tests/data/regressions/its4337/slapd.conf + +diff --git a/doc/guide/admin/aspell.en.pws b/doc/guide/admin/aspell.en.pws +index ae777e2..ec24572 100644 +--- a/doc/guide/admin/aspell.en.pws ++++ b/doc/guide/admin/aspell.en.pws +@@ -220,8 +220,6 @@ AVAs + associatedDomain + organizationalRole + initgroups +-olcDbCachesize +-olcDbCacheSize + ETCDIR + colaligns + olcReadOnly +@@ -426,10 +424,8 @@ txt + UTR + XER + roomNumber +-olcDbIDLcacheSize + namespace + LDAPControl +-dbconfig + olcAttributeOptions + dsaparam + searchResult +@@ -965,7 +961,6 @@ unwillingToPerform + PhotoURI + MyCompany + mkdep +-idlcachesize + irresponsive + PasswordModify + readOnly +@@ -1183,7 +1178,6 @@ monitorRuntimeConfig + olcAuditlogFile + namingContexts + referralAttrDN +-idlecachesize + moddn + calloc + LDFLAGS +@@ -1375,7 +1369,6 @@ spasswd + sprintf + monitorCounterObject + Instanstantiation +-olcDbConfig + olcLastMod + vals + param +diff --git a/tests/data/regressions/its4337/config.out b/tests/data/regressions/its4337/config.out +deleted file mode 100644 +index bdcbbe5..0000000 +--- a/tests/data/regressions/its4337/config.out ++++ /dev/null +@@ -1,129 +0,0 @@ +-# Searching databases __before__ append... +-dn: olcDatabase={-1}frontend,cn=config +-objectClass: olcDatabaseConfig +-objectClass: olcFrontendConfig +-olcDatabase: {-1}frontend +-olcAddContentAcl: FALSE +-olcLastMod: TRUE +-olcMaxDerefDepth: 0 +-olcReadOnly: FALSE +-olcSchemaDN: cn=Subschema +-olcSyncUseSubentry: FALSE +-olcMonitoring: FALSE +- +-dn: olcDatabase={0}config,cn=config +-objectClass: olcDatabaseConfig +-olcDatabase: {0}config +-olcAccess: {0}to * by * none +-olcAddContentAcl: TRUE +-olcLastMod: TRUE +-olcMaxDerefDepth: 15 +-olcReadOnly: FALSE +-olcRootDN: cn=config +-olcRootPW: config +-olcSyncUseSubentry: FALSE +-olcMonitoring: FALSE +- +-dn: olcDatabase={1}monitor,cn=config +-objectClass: olcDatabaseConfig +-olcDatabase: {1}monitor +-olcAddContentAcl: FALSE +-olcLastMod: TRUE +-olcMaxDerefDepth: 15 +-olcReadOnly: FALSE +-olcSyncUseSubentry: FALSE +-olcMonitoring: FALSE +- +-# Searching databases __after__ append... +-dn: olcDatabase={-1}frontend,cn=config +-objectClass: olcDatabaseConfig +-objectClass: olcFrontendConfig +-olcDatabase: {-1}frontend +-olcAddContentAcl: FALSE +-olcLastMod: TRUE +-olcMaxDerefDepth: 0 +-olcReadOnly: FALSE +-olcSchemaDN: cn=Subschema +-olcSyncUseSubentry: FALSE +-olcMonitoring: FALSE +- +-dn: olcDatabase={0}config,cn=config +-objectClass: olcDatabaseConfig +-olcDatabase: {0}config +-olcAccess: {0}to * by * none +-olcAddContentAcl: TRUE +-olcLastMod: TRUE +-olcMaxDerefDepth: 15 +-olcReadOnly: FALSE +-olcRootDN: cn=config +-olcRootPW: config +-olcSyncUseSubentry: FALSE +-olcMonitoring: FALSE +- +-dn: olcDatabase={1}monitor,cn=config +-objectClass: olcDatabaseConfig +-olcDatabase: {1}monitor +-olcAddContentAcl: FALSE +-olcLastMod: TRUE +-olcMaxDerefDepth: 15 +-olcReadOnly: FALSE +-olcSyncUseSubentry: FALSE +-olcMonitoring: FALSE +- +-dn: olcDatabase={2}bdb,cn=config +-objectClass: olcDatabaseConfig +-objectClass: olcBdbConfig +-olcDatabase: {2}bdb +-olcDbDirectory: ./testrun/db.1.a +-olcSuffix: dc=com +- +-# Searching databases __after__ insert... +-dn: olcDatabase={-1}frontend,cn=config +-objectClass: olcDatabaseConfig +-objectClass: olcFrontendConfig +-olcDatabase: {-1}frontend +-olcAddContentAcl: FALSE +-olcLastMod: TRUE +-olcMaxDerefDepth: 0 +-olcReadOnly: FALSE +-olcSchemaDN: cn=Subschema +-olcSyncUseSubentry: FALSE +-olcMonitoring: FALSE +- +-dn: olcDatabase={0}config,cn=config +-objectClass: olcDatabaseConfig +-olcDatabase: {0}config +-olcAccess: {0}to * by * none +-olcAddContentAcl: TRUE +-olcLastMod: TRUE +-olcMaxDerefDepth: 15 +-olcReadOnly: FALSE +-olcRootDN: cn=config +-olcRootPW: config +-olcSyncUseSubentry: FALSE +-olcMonitoring: FALSE +- +-dn: olcDatabase={1}bdb,cn=config +-objectClass: olcDatabaseConfig +-objectClass: olcBdbConfig +-olcDatabase: {1}bdb +-olcDbDirectory: ./testrun/db.2.a +-olcSuffix: dc=org +- +-dn: olcDatabase={2}monitor,cn=config +-objectClass: olcDatabaseConfig +-olcDatabase: {2}monitor +-olcAddContentAcl: FALSE +-olcLastMod: TRUE +-olcMaxDerefDepth: 15 +-olcReadOnly: FALSE +-olcSyncUseSubentry: FALSE +-olcMonitoring: FALSE +- +-dn: olcDatabase={3}bdb,cn=config +-objectClass: olcDatabaseConfig +-objectClass: olcBdbConfig +-olcDatabase: {3}bdb +-olcDbDirectory: ./testrun/db.1.a +-olcSuffix: dc=com +- +diff --git a/tests/data/regressions/its4337/its4337 b/tests/data/regressions/its4337/its4337 +deleted file mode 100755 +index 66bc716..0000000 +--- a/tests/data/regressions/its4337/its4337 ++++ /dev/null +@@ -1,157 +0,0 @@ +-#! /bin/sh +-# $OpenLDAP$ +-## This work is part of OpenLDAP Software . +-## +-## 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 +-## . +- +-echo "running defines.sh" +-. $SRCDIR/scripts/defines.sh +- +-if test $BACKEND != "bdb" ; then +- echo "BDB backend not available, test skipped" +- exit 0 +-fi +- +-mkdir -p $TESTDIR $DBDIR1 $DBDIR2 $DBDIR3 $TESTDIR/slapd.d +- +-ITS=4337 +-ITSDIR=$DATADIR/regressions/its$ITS +- +-echo "Starting slapd on TCP/IP port $PORT1..." +-. $CONFFILTER $BACKEND $MONITORDB < $ITSDIR/slapd.conf > $CONF1 +-#$SLAPD -f $CONF1 -F $TESTDIR/slapd.d -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 & +-$SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 & +-PID=$! +-if test $WAIT != 0 ; then +- echo PID $PID +- read foo +-fi +-KILLPIDS="$PID" +- +-sleep 1 +- +-echo "Using ldapsearch to check that slapd is running..." +-for i in 0 1 2 3 4 5; do +- $LDAPSEARCH -s base -b "$MONITOR" -h $LOCALHOST -p $PORT1 \ +- 'objectclass=*' > /dev/null 2>&1 +- RC=$? +- if test $RC = 0 ; then +- break +- fi +- echo "Waiting 5 seconds for slapd to start..." +- sleep 5 +-done +- +-if test $RC != 0 ; then +- echo "ldapsearch failed ($RC)!" +- test $KILLSERVERS != no && kill -HUP $KILLPIDS +- exit $RC +-fi +- +-cat /dev/null > $TESTOUT +-cat /dev/null > $SEARCHOUT +- +-echo "Searching databases..." +-echo "# Searching databases __before__ append..." >> $SEARCHOUT +-$LDAPSEARCH -h $LOCALHOST -p $PORT1 \ +- -D "cn=config" -w "config" -b "cn=config" \ +- '(objectClass=olcDatabaseConfig)' >> $SEARCHOUT 2>> $TESTOUT +-RC=$? +-if test $RC != 0 ; then +- echo "ldapsearch failed ($RC)!" +- test $KILLSERVERS != no && kill -HUP $KILLPIDS +- exit $RC +-fi +- +-echo "Appending a database..." +-$LDAPADD -v -D "cn=config" -w "config" -h $LOCALHOST -p $PORT1 \ +- >> $TESTOUT 2>&1 << EOMODS +-dn: olcDatabase=bdb,cn=config +-objectClass: olcDatabaseConfig +-objectClass: olcBdbConfig +-olcDatabase: bdb +-olcSuffix: dc=com +-olcDbDirectory: ./testrun/db.1.a +-EOMODS +-RC=$? +-if test $RC != 0 ; then +- echo "ldapadd failed ($RC)!" +- test $KILLSERVERS != no && kill -HUP $KILLPIDS +- exit $RC +-fi +- +-echo "Searching databases..." +-echo "# Searching databases __after__ append..." >> $SEARCHOUT +-$LDAPSEARCH -h $LOCALHOST -p $PORT1 \ +- -D "cn=config" -w "config" -b "cn=config" \ +- '(objectClass=olcDatabaseConfig)' >> $SEARCHOUT 2>> $TESTOUT +-RC=$? +-if test $RC != 0 ; then +- echo "ldapsearch failed ($RC)!" +- test $KILLSERVERS != no && kill -HUP $KILLPIDS +- exit $RC +-fi +- +-echo "Inserting a database..." +-$LDAPADD -v -D "cn=config" -w "config" -h $LOCALHOST -p $PORT1 \ +- >> $TESTOUT 2>&1 << EOMODS +-dn: olcDatabase={1}bdb,cn=config +-objectClass: olcDatabaseConfig +-objectClass: olcBdbConfig +-olcDatabase: {1}bdb +-olcSuffix: dc=org +-olcDbDirectory: ./testrun/db.2.a +-EOMODS +-RC=$? +-if test $RC != 0 ; then +- echo "ldapadd failed ($RC)!" +- test $KILLSERVERS != no && kill -HUP $KILLPIDS +- if test $RC = 53 ; then +- echo "TODO" +- exit 0 +- fi +- exit $RC +-fi +- +-echo "Searching databases..." +-echo "# Searching databases __after__ insert..." >> $SEARCHOUT +-$LDAPSEARCH -h $LOCALHOST -p $PORT1 \ +- -D "cn=config" -w "config" -b "cn=config" \ +- '(objectClass=olcDatabaseConfig)' >> $SEARCHOUT 2>> $TESTOUT +-RC=$? +-if test $RC != 0 ; then +- echo "ldapsearch failed ($RC)!" +- test $KILLSERVERS != no && kill -HUP $KILLPIDS +- exit $RC +-fi +- +-test $KILLSERVERS != no && kill -HUP $KILLPIDS +- +-LDIF=$ITSDIR/config.out +- +-echo "Filtering ldapsearch results..." +-$LDIFFILTER < $SEARCHOUT > $SEARCHFLT +-echo "Filtering original ldif..." +-$LDIFFILTER < $LDIF > $LDIFFLT +-echo "Comparing filter output..." +-$CMP $SEARCHFLT $LDIFFLT > $CMPOUT +- +-if test $? != 0 ; then +- echo "Comparison failed" +- exit 1 +-fi +- +-echo ">>>>> Test succeeded" +- +-test $KILLSERVERS != no && wait +- +-exit 0 +diff --git a/tests/data/regressions/its4337/slapd.conf b/tests/data/regressions/its4337/slapd.conf +deleted file mode 100644 +index ee3108a..0000000 +--- a/tests/data/regressions/its4337/slapd.conf ++++ /dev/null +@@ -1,36 +0,0 @@ +-# stand-alone slapd config -- for testing (with indexing) +-# $OpenLDAP$ +-## This work is part of OpenLDAP Software . +-## +-## 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 +-## . +- +-include @SCHEMADIR@/core.schema +-include @SCHEMADIR@/cosine.schema +-include @SCHEMADIR@/inetorgperson.schema +-include @SCHEMADIR@/openldap.schema +-include @SCHEMADIR@/nis.schema +-include @DATADIR@/test.schema +- +-# +-pidfile @TESTDIR@/slapd.2.pid +-argsfile @TESTDIR@/slapd.2.args +- +-#mod#modulepath ../servers/slapd/back-@BACKEND@/:../servers/slapd/overlays +-#mod#moduleload back_@BACKEND@.la +- +-#monitormod#modulepath ../servers/slapd/back-monitor/ +-#monitormod#moduleload back_monitor.la +- +-database config +-rootpw config +- +-#monitor#database monitor +-- +2.19.1 + diff --git a/backport-ITS-9010-regenerate-configure.patch b/backport-ITS-9010-regenerate-configure.patch new file mode 100644 index 0000000..1ec1ee1 --- /dev/null +++ b/backport-ITS-9010-regenerate-configure.patch @@ -0,0 +1,1783 @@ +From 14c7c8f3579a8c0a802aaac72841efed3d01445f Mon Sep 17 00:00:00 2001 +From: zhangqiumiao +Date: Sun, 27 Sep 2020 14:25:21 +0800 +Subject: [PATCH] backport ITS#9010 regenerate configure + +--- + configure | 1565 +++++------------------------------------------------ + 1 file changed, 148 insertions(+), 1417 deletions(-) + +diff --git a/configure b/configure +index 5f05f1c..5c5097a 100755 +--- a/configure ++++ b/configure +@@ -667,7 +667,6 @@ LUTIL_LIBS + LTHREAD_LIBS + SLAPD_NDB_INCS + SLAPD_NDB_LIBS +-BDB_LIBS + SLAPD_LIBS + LDAP_LIBS + BUILD_VALSORT +@@ -704,9 +703,7 @@ BUILD_MONITOR + BUILD_META + BUILD_MDB + BUILD_LDAP +-BUILD_HDB + BUILD_DNSSRV +-BUILD_BDB + SLAPD_SLAPI_DEPEND + BUILD_SLAPI + BUILD_SLAPD +@@ -764,6 +761,7 @@ DLLTOOL + AS + AR + CC ++moduledir + ldap_subdir + top_builddir + OPENLDAP_RELEASE_DATE +@@ -852,6 +850,7 @@ ac_user_opts=' + enable_option_checking + enable_silent_rules + with_subdir ++with_moduledir + enable_debug + enable_dynamic + enable_syslog +@@ -881,9 +880,7 @@ enable_slp + enable_wrappers + enable_xxslapbackends + enable_backends +-enable_bdb + enable_dnssrv +-enable_hdb + enable_ldap + enable_mdb + enable_meta +@@ -1583,9 +1580,7 @@ SLAPD (Standalone LDAP Daemon) Options: + + SLAPD Backend Options: + --enable-backends enable all available backends no|yes|mod +- --enable-bdb enable Berkeley DB backend no|yes|mod [yes] + --enable-dnssrv enable dnssrv backend no|yes|mod [no] +- --enable-hdb enable Hierarchical DB backend no|yes|mod [yes] + --enable-ldap enable ldap backend no|yes|mod [no] + --enable-mdb enable mdb database backend no|yes|mod [yes] + --enable-meta enable metadirectory backend no|yes|mod [no] +@@ -1637,6 +1632,7 @@ Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-subdir=DIR change default subdirectory used for installs ++ --with-moduledir=DIR change default module subdirectory used for installs + --with-cyrus-sasl with Cyrus SASL support [auto] + --with-fetch with fetch(3) URL support [auto] + --with-threads with threads [auto] +@@ -3570,6 +3566,24 @@ esac + fi + + ++ ++moduledir="openldap" ++ ++ ++# Check whether --with-moduledir was given. ++if test "${with_moduledir+set}" = set; then : ++ withval=$with_moduledir; case "$withval" in ++ no) moduledir="" ++ ;; ++ yes) ++ ;; ++ *) ++ moduledir="$withval" ++ ;; ++esac ++ ++fi ++ + # OpenLDAP --enable-debug + + # Check whether --enable-debug was given. +@@ -4126,9 +4140,7 @@ fi + + # end --enable-wrappers + +-Backends="bdb \ +- dnssrv \ +- hdb \ ++Backends="dnssrv \ + ldap \ + mdb \ + meta \ +@@ -4167,27 +4179,6 @@ if test "${enable_backends+set}" = set; then : + fi + + # end --enable-backends +-# OpenLDAP --enable-bdb +- +- # Check whether --enable-bdb was given. +-if test "${enable_bdb+set}" = set; then : +- enableval=$enable_bdb; +- ol_arg=invalid +- for ol_val in no yes mod ; do +- if test "$enableval" = "$ol_val" ; then +- ol_arg="$ol_val" +- fi +- done +- if test "$ol_arg" = "invalid" ; then +- as_fn_error $? "bad value $enableval for --enable-bdb" "$LINENO" 5 +- fi +- ol_enable_bdb="$ol_arg" +- +-else +- ol_enable_bdb=${ol_enable_backends:-yes} +-fi +- +-# end --enable-bdb + # OpenLDAP --enable-dnssrv + + # Check whether --enable-dnssrv was given. +@@ -4209,27 +4200,6 @@ else + fi + + # end --enable-dnssrv +-# OpenLDAP --enable-hdb +- +- # Check whether --enable-hdb was given. +-if test "${enable_hdb+set}" = set; then : +- enableval=$enable_hdb; +- ol_arg=invalid +- for ol_val in no yes mod ; do +- if test "$enableval" = "$ol_val" ; then +- ol_arg="$ol_val" +- fi +- done +- if test "$ol_arg" = "invalid" ; then +- as_fn_error $? "bad value $enableval for --enable-hdb" "$LINENO" 5 +- fi +- ol_enable_hdb="$ol_arg" +- +-else +- ol_enable_hdb=${ol_enable_backends:-yes} +-fi +- +-# end --enable-hdb + # OpenLDAP --enable-ldap + + # Check whether --enable-ldap was given. +@@ -5108,9 +5078,7 @@ $as_echo "$as_me: WARNING: slapd disabled, ignoring --enable-$i argument" >&2;} + 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 && +@@ -5150,11 +5118,22 @@ if test $ol_enable_spasswd = yes ; then + ol_with_cyrus_sasl=yes + fi + ++ + { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 + $as_echo "done" >&6; } + ++case $moduledir in ++ /*|\\*) ++ ;; ++ *) ++ moduledir=$libexecdir/$moduledir ++ ;; ++esac ++ ++ ++ ++ + LDAP_LIBS= +-BDB_LIBS= + SLAPD_NDB_LIBS= + SLAPD_NDB_INCS= + LTHREAD_LIBS= +@@ -5169,9 +5148,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 +@@ -22937,1388 +22914,178 @@ else + ol_cv_func_gethostbyaddr_r_nargs=0 + fi + +-ol_link_bdb=no + +-if test $ol_enable_bdb/$ol_enable_hdb != no/no; then +- ol_cv_berkeley_db=no +-for ac_header in db.h +-do : +- ac_fn_c_check_header_mongrel "$LINENO" "db.h" "ac_cv_header_db_h" "$ac_includes_default" +-if test "x$ac_cv_header_db_h" = xyes; then : +- cat >>confdefs.h <<_ACEOF +-#define HAVE_DB_H 1 +-_ACEOF +- +-fi +- +-done +- +-if test $ac_cv_header_db_h = yes; then +- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Berkeley DB major version in db.h" >&5 +-$as_echo_n "checking for Berkeley DB major version in db.h... " >&6; } +-if ${ol_cv_bdb_major+:} false; then : +- $as_echo_n "(cached) " >&6 ++if test $ol_enable_dynamic = yes && test $enable_shared = yes ; then ++ BUILD_LIBS_DYNAMIC=shared ++ $as_echo "#define LDAP_LIBS_DYNAMIC 1" >>confdefs.h ++ LTSTATIC="" + else +- +- cat confdefs.h - <<_ACEOF >conftest.$ac_ext +-/* end confdefs.h. */ +- +-#include +-#ifndef DB_VERSION_MAJOR +-# define DB_VERSION_MAJOR 1 +-#endif +-__db_version DB_VERSION_MAJOR +- +-_ACEOF +- set X `eval "$ac_cpp -P conftest.$ac_ext" | $EGREP __db_version` none none +- ol_cv_bdb_major=${3} +- ++ BUILD_LIBS_DYNAMIC=static ++ LTSTATIC="-static" + fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ol_cv_bdb_major" >&5 +-$as_echo "$ol_cv_bdb_major" >&6; } +-case $ol_cv_bdb_major in [1-9]*) : ;; *) +- as_fn_error $? "Unknown Berkeley DB major version in db.h" "$LINENO" 5 ;; +-esac +- +-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Berkeley DB minor version in db.h" >&5 +-$as_echo_n "checking for Berkeley DB minor version in db.h... " >&6; } +-if ${ol_cv_bdb_minor+:} false; then : +- $as_echo_n "(cached) " >&6 +-else +- +- cat confdefs.h - <<_ACEOF >conftest.$ac_ext +-/* end confdefs.h. */ +- +-#include +-#ifndef DB_VERSION_MINOR +-# define DB_VERSION_MINOR 0 +-#endif +-__db_version DB_VERSION_MINOR + ++if test $ol_enable_wrappers != no ; then ++ for ac_header in tcpd.h ++do : ++ ac_fn_c_check_header_mongrel "$LINENO" "tcpd.h" "ac_cv_header_tcpd_h" "$ac_includes_default" ++if test "x$ac_cv_header_tcpd_h" = x""yes; then : ++ cat >>confdefs.h <<_ACEOF ++#define HAVE_TCPD_H 1 + _ACEOF +- set X `eval "$ac_cpp -P conftest.$ac_ext" | $EGREP __db_version` none none +- ol_cv_bdb_minor=${3} +- +-fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ol_cv_bdb_minor" >&5 +-$as_echo "$ol_cv_bdb_minor" >&6; } +-case $ol_cv_bdb_minor in [0-9]*) : ;; *) +- as_fn_error $? "Unknown Berkeley DB minor version in db.h" "$LINENO" 5 ;; +-esac + +- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if Berkeley DB version supported by BDB/HDB backends" >&5 +-$as_echo_n "checking if Berkeley DB version supported by BDB/HDB backends... " >&6; } +-if ${ol_cv_bdb_compat+:} false; then : +- $as_echo_n "(cached) " >&6 +-else +- +- cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for TCP wrappers library" >&5 ++$as_echo_n "checking for TCP wrappers library... " >&6; } ++ save_LIBS="$LIBS" ++ LIBS="$LIBS -lwrap" ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext + /* end confdefs.h. */ + +-#include ++#include ++int allow_severity = 0; ++int deny_severity = 0; + +- /* 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 ++struct request_info *req; + +-#define DB_VERSION_FULL ((DB_VERSION_MAJOR<<16)|(DB_VERSION_MINOR<<8)|DB_VERSION_PATCH) ++int ++main () ++{ + +-/* 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 ++hosts_access(req) + ++ ; ++ return 0; ++} + _ACEOF +-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | +- $EGREP "__db_version_compat" >/dev/null 2>&1; then : +- ol_cv_bdb_compat=yes +-else +- ol_cv_bdb_compat=no +-fi +-rm -f conftest* +- +-fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ol_cv_bdb_compat" >&5 +-$as_echo "$ol_cv_bdb_compat" >&6; } +- +- +- if test $ol_cv_bdb_compat != yes ; then +- as_fn_error $? "BerkeleyDB version incompatible with BDB/HDB backends" "$LINENO" 5 +- fi +- +- ol_cv_lib_db=no +- +-if test $ol_cv_bdb_major = 5 ; then +- if test $ol_cv_lib_db = no ; then +- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Berkeley DB link (-ldb-5.$ol_cv_bdb_minor)" >&5 +-$as_echo_n "checking for Berkeley DB link (-ldb-5.$ol_cv_bdb_minor)... " >&6; } +-if ${ol_cv_db_db_5_dot_m+:} false; then : +- $as_echo_n "(cached) " >&6 ++if ac_fn_c_try_link "$LINENO"; then : ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: -lwrap" >&5 ++$as_echo "-lwrap" >&6; } ++ have_wrappers=yes ++ LIBS="$save_LIBS" + else +- +- ol_DB_LIB=-ldb-5.$ol_cv_bdb_minor +- ol_LIBS=$LIBS +- LIBS="$ol_DB_LIB $LTHREAD_LIBS $LIBS" +- +- cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++ LIBS="$LIBS -lnsl" ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext + /* end confdefs.h. */ + +-#ifdef HAVE_DB_185_H +-# include +-#else +-# include +-#endif +- +-#ifndef DB_VERSION_MAJOR +-# define DB_VERSION_MAJOR 1 +-#endif ++#include ++int allow_severity = 0; ++int deny_severity = 0; + +-#ifndef NULL +-#define NULL ((void*)0) +-#endif ++struct request_info *req; + + int + main () + { + +-#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 ++hosts_access(req) + + ; + return 0; + } + _ACEOF + if ac_fn_c_try_link "$LINENO"; then : +- ol_cv_db_db_5_dot_m=yes ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: -lwrap -lnsl" >&5 ++$as_echo "-lwrap -lnsl" >&6; } ++ have_wrappers=yes ++ LIBS="$save_LIBS -lnsl" + else +- ol_cv_db_db_5_dot_m=no ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++ have_wrappers=no ++ LIBS=$save_LIBS + fi + rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +- +- LIBS="$ol_LIBS" +- + fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ol_cv_db_db_5_dot_m" >&5 +-$as_echo "$ol_cv_db_db_5_dot_m" >&6; } +- +- if test $ol_cv_db_db_5_dot_m = yes ; then +- ol_cv_lib_db=-ldb-5.$ol_cv_bdb_minor +- fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++else ++ have_wrappers=no + fi + +- if test $ol_cv_lib_db = no ; then +- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Berkeley DB link (-ldb5$ol_cv_bdb_minor)" >&5 +-$as_echo_n "checking for Berkeley DB link (-ldb5$ol_cv_bdb_minor)... " >&6; } +-if ${ol_cv_db_db5m+:} false; then : +- $as_echo_n "(cached) " >&6 +-else ++done + +- ol_DB_LIB=-ldb5$ol_cv_bdb_minor +- ol_LIBS=$LIBS +- LIBS="$ol_DB_LIB $LTHREAD_LIBS $LIBS" + +- cat confdefs.h - <<_ACEOF >conftest.$ac_ext +-/* end confdefs.h. */ ++ if test $have_wrappers = yes ; then + +-#ifdef HAVE_DB_185_H +-# include +-#else +-# include +-#endif ++$as_echo "#define HAVE_TCPD 1" >>confdefs.h + +-#ifndef DB_VERSION_MAJOR +-# define DB_VERSION_MAJOR 1 +-#endif ++ WRAP_LIBS="-lwrap" ++ elif test $ol_enable_wrappers = yes ; then ++ as_fn_error "could not find TCP wrappers, select appropriate options or disable" "$LINENO" 5 ++ else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find TCP wrappers, support disabled" >&5 ++$as_echo "$as_me: WARNING: could not find TCP wrappers, support disabled" >&2;} ++ WRAP_LIBS="" ++ fi ++fi + +-#ifndef NULL +-#define NULL ((void*)0) +-#endif ++if test $ol_enable_syslog != no ; then ++ ac_fn_c_check_func "$LINENO" "openlog" "ac_cv_func_openlog" ++if test "x$ac_cv_func_openlog" = x""yes; then : + +-int +-main () +-{ ++fi + +-#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 ++ if test $ac_cv_func_openlog = no && test $ol_enable_syslog = yes; then ++ { as_fn_set_status select appropriate options or disable ++as_fn_error "could not find syslog" "$LINENO" 5; } ++ fi ++ ol_enable_syslog=$ac_cv_func_openlog ++fi + +- ; +- return 0; +-} ++ol_link_sql=no ++if test $ol_enable_sql != no ; then ++ for ac_header in sql.h sqlext.h ++do : ++ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ++ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" ++eval as_val=\$$as_ac_Header ++ if test "x$as_val" = x""yes; then : ++ cat >>confdefs.h <<_ACEOF ++#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 + _ACEOF +-if ac_fn_c_try_link "$LINENO"; then : +- ol_cv_db_db5m=yes ++ + else +- ol_cv_db_db5m=no +-fi +-rm -f core conftest.err conftest.$ac_objext \ +- conftest$ac_exeext conftest.$ac_ext + +- LIBS="$ol_LIBS" ++ as_fn_error "could not locate SQL headers" "$LINENO" 5 + + fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ol_cv_db_db5m" >&5 +-$as_echo "$ol_cv_db_db5m" >&6; } + +- if test $ol_cv_db_db5m = yes ; then +- ol_cv_lib_db=-ldb5$ol_cv_bdb_minor ++done ++ ++ ++ sql_LIBS="$LIBS" ++ LIBS="$LTHREAD_LIBS $LIBS" ++ ++ if test $ol_with_odbc = auto ; then ++ ol_with_odbc="iodbc unixodbc odbc32" + fi +-fi + +- if test $ol_cv_lib_db = no ; then +- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Berkeley DB link (-ldb-5$ol_cv_bdb_minor)" >&5 +-$as_echo_n "checking for Berkeley DB link (-ldb-5$ol_cv_bdb_minor)... " >&6; } +-if ${ol_cv_db_db_5m+:} false; then : ++ for odbc in $ol_with_odbc ; do ++ if test $ol_link_sql = no ; then ++ case $odbc in ++ iodbc) ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SQLDriverConnect in -liodbc" >&5 ++$as_echo_n "checking for SQLDriverConnect in -liodbc... " >&6; } ++if test "${ac_cv_lib_iodbc_SQLDriverConnect+set}" = set; then : + $as_echo_n "(cached) " >&6 + else +- +- ol_DB_LIB=-ldb-5$ol_cv_bdb_minor +- ol_LIBS=$LIBS +- LIBS="$ol_DB_LIB $LTHREAD_LIBS $LIBS" +- +- cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++ ac_check_lib_save_LIBS=$LIBS ++LIBS="-liodbc $LIBS" ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext + /* end confdefs.h. */ + +-#ifdef HAVE_DB_185_H +-# include +-#else +-# include +-#endif +- +-#ifndef DB_VERSION_MAJOR +-# define DB_VERSION_MAJOR 1 +-#endif +- +-#ifndef NULL +-#define NULL ((void*)0) ++/* Override any GCC internal prototype to avoid an error. ++ Use char because int might match the return type of a GCC ++ builtin and then its argument prototype would still apply. */ ++#ifdef __cplusplus ++extern "C" + #endif +- ++char SQLDriverConnect (); + int + main () + { +- +-#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 +- +- ; +- return 0; +-} +-_ACEOF +-if ac_fn_c_try_link "$LINENO"; then : +- ol_cv_db_db_5m=yes +-else +- ol_cv_db_db_5m=no +-fi +-rm -f core conftest.err conftest.$ac_objext \ +- conftest$ac_exeext conftest.$ac_ext +- +- LIBS="$ol_LIBS" +- +-fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ol_cv_db_db_5m" >&5 +-$as_echo "$ol_cv_db_db_5m" >&6; } +- +- if test $ol_cv_db_db_5m = yes ; then +- ol_cv_lib_db=-ldb-5$ol_cv_bdb_minor +- fi +-fi +- +- if test $ol_cv_lib_db = no ; then +- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Berkeley DB link (-ldb-5-$ol_cv_bdb_minor)" >&5 +-$as_echo_n "checking for Berkeley DB link (-ldb-5-$ol_cv_bdb_minor)... " >&6; } +-if ${ol_cv_db_db_5_m+:} false; then : +- $as_echo_n "(cached) " >&6 +-else +- +- ol_DB_LIB=-ldb-5-$ol_cv_bdb_minor +- ol_LIBS=$LIBS +- LIBS="$ol_DB_LIB $LTHREAD_LIBS $LIBS" +- +- cat confdefs.h - <<_ACEOF >conftest.$ac_ext +-/* end confdefs.h. */ +- +-#ifdef HAVE_DB_185_H +-# include +-#else +-# include +-#endif +- +-#ifndef DB_VERSION_MAJOR +-# define DB_VERSION_MAJOR 1 +-#endif +- +-#ifndef NULL +-#define NULL ((void*)0) +-#endif +- +-int +-main () +-{ +- +-#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 +- +- ; +- return 0; +-} +-_ACEOF +-if ac_fn_c_try_link "$LINENO"; then : +- ol_cv_db_db_5_m=yes +-else +- ol_cv_db_db_5_m=no +-fi +-rm -f core conftest.err conftest.$ac_objext \ +- conftest$ac_exeext conftest.$ac_ext +- +- LIBS="$ol_LIBS" +- +-fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ol_cv_db_db_5_m" >&5 +-$as_echo "$ol_cv_db_db_5_m" >&6; } +- +- if test $ol_cv_db_db_5_m = yes ; then +- ol_cv_lib_db=-ldb-5-$ol_cv_bdb_minor +- fi +-fi +- +- if test $ol_cv_lib_db = no ; then +- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Berkeley DB link (-ldb-5)" >&5 +-$as_echo_n "checking for Berkeley DB link (-ldb-5)... " >&6; } +-if ${ol_cv_db_db_5+:} false; then : +- $as_echo_n "(cached) " >&6 +-else +- +- ol_DB_LIB=-ldb-5 +- ol_LIBS=$LIBS +- LIBS="$ol_DB_LIB $LTHREAD_LIBS $LIBS" +- +- cat confdefs.h - <<_ACEOF >conftest.$ac_ext +-/* end confdefs.h. */ +- +-#ifdef HAVE_DB_185_H +-# include +-#else +-# include +-#endif +- +-#ifndef DB_VERSION_MAJOR +-# define DB_VERSION_MAJOR 1 +-#endif +- +-#ifndef NULL +-#define NULL ((void*)0) +-#endif +- +-int +-main () +-{ +- +-#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 +- +- ; +- return 0; +-} +-_ACEOF +-if ac_fn_c_try_link "$LINENO"; then : +- ol_cv_db_db_5=yes +-else +- ol_cv_db_db_5=no +-fi +-rm -f core conftest.err conftest.$ac_objext \ +- conftest$ac_exeext conftest.$ac_ext +- +- LIBS="$ol_LIBS" +- +-fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ol_cv_db_db_5" >&5 +-$as_echo "$ol_cv_db_db_5" >&6; } +- +- if test $ol_cv_db_db_5 = yes ; then +- ol_cv_lib_db=-ldb-5 +- fi +-fi +- +- if test $ol_cv_lib_db = no ; then +- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Berkeley DB link (-ldb5)" >&5 +-$as_echo_n "checking for Berkeley DB link (-ldb5)... " >&6; } +-if ${ol_cv_db_db5+:} false; then : +- $as_echo_n "(cached) " >&6 +-else +- +- ol_DB_LIB=-ldb5 +- ol_LIBS=$LIBS +- LIBS="$ol_DB_LIB $LTHREAD_LIBS $LIBS" +- +- cat confdefs.h - <<_ACEOF >conftest.$ac_ext +-/* end confdefs.h. */ +- +-#ifdef HAVE_DB_185_H +-# include +-#else +-# include +-#endif +- +-#ifndef DB_VERSION_MAJOR +-# define DB_VERSION_MAJOR 1 +-#endif +- +-#ifndef NULL +-#define NULL ((void*)0) +-#endif +- +-int +-main () +-{ +- +-#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 +- +- ; +- return 0; +-} +-_ACEOF +-if ac_fn_c_try_link "$LINENO"; then : +- ol_cv_db_db5=yes +-else +- ol_cv_db_db5=no +-fi +-rm -f core conftest.err conftest.$ac_objext \ +- conftest$ac_exeext conftest.$ac_ext +- +- LIBS="$ol_LIBS" +- +-fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ol_cv_db_db5" >&5 +-$as_echo "$ol_cv_db_db5" >&6; } +- +- if test $ol_cv_db_db5 = yes ; then +- ol_cv_lib_db=-ldb5 +- fi +-fi +- +-elif test $ol_cv_bdb_major = 4 ; then +- if test $ol_cv_lib_db = no ; then +- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Berkeley DB link (-ldb-4.$ol_cv_bdb_minor)" >&5 +-$as_echo_n "checking for Berkeley DB link (-ldb-4.$ol_cv_bdb_minor)... " >&6; } +-if ${ol_cv_db_db_4_dot_m+:} false; then : +- $as_echo_n "(cached) " >&6 +-else +- +- ol_DB_LIB=-ldb-4.$ol_cv_bdb_minor +- ol_LIBS=$LIBS +- LIBS="$ol_DB_LIB $LTHREAD_LIBS $LIBS" +- +- cat confdefs.h - <<_ACEOF >conftest.$ac_ext +-/* end confdefs.h. */ +- +-#ifdef HAVE_DB_185_H +-# include +-#else +-# include +-#endif +- +-#ifndef DB_VERSION_MAJOR +-# define DB_VERSION_MAJOR 1 +-#endif +- +-#ifndef NULL +-#define NULL ((void*)0) +-#endif +- +-int +-main () +-{ +- +-#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 +- +- ; +- return 0; +-} +-_ACEOF +-if ac_fn_c_try_link "$LINENO"; then : +- ol_cv_db_db_4_dot_m=yes +-else +- ol_cv_db_db_4_dot_m=no +-fi +-rm -f core conftest.err conftest.$ac_objext \ +- conftest$ac_exeext conftest.$ac_ext +- +- LIBS="$ol_LIBS" +- +-fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ol_cv_db_db_4_dot_m" >&5 +-$as_echo "$ol_cv_db_db_4_dot_m" >&6; } +- +- if test $ol_cv_db_db_4_dot_m = yes ; then +- ol_cv_lib_db=-ldb-4.$ol_cv_bdb_minor +- fi +-fi +- +- if test $ol_cv_lib_db = no ; then +- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Berkeley DB link (-ldb4$ol_cv_bdb_minor)" >&5 +-$as_echo_n "checking for Berkeley DB link (-ldb4$ol_cv_bdb_minor)... " >&6; } +-if ${ol_cv_db_db4m+:} false; then : +- $as_echo_n "(cached) " >&6 +-else +- +- ol_DB_LIB=-ldb4$ol_cv_bdb_minor +- ol_LIBS=$LIBS +- LIBS="$ol_DB_LIB $LTHREAD_LIBS $LIBS" +- +- cat confdefs.h - <<_ACEOF >conftest.$ac_ext +-/* end confdefs.h. */ +- +-#ifdef HAVE_DB_185_H +-# include +-#else +-# include +-#endif +- +-#ifndef DB_VERSION_MAJOR +-# define DB_VERSION_MAJOR 1 +-#endif +- +-#ifndef NULL +-#define NULL ((void*)0) +-#endif +- +-int +-main () +-{ +- +-#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 +- +- ; +- return 0; +-} +-_ACEOF +-if ac_fn_c_try_link "$LINENO"; then : +- ol_cv_db_db4m=yes +-else +- ol_cv_db_db4m=no +-fi +-rm -f core conftest.err conftest.$ac_objext \ +- conftest$ac_exeext conftest.$ac_ext +- +- LIBS="$ol_LIBS" +- +-fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ol_cv_db_db4m" >&5 +-$as_echo "$ol_cv_db_db4m" >&6; } +- +- if test $ol_cv_db_db4m = yes ; then +- ol_cv_lib_db=-ldb4$ol_cv_bdb_minor +- fi +-fi +- +- if test $ol_cv_lib_db = no ; then +- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Berkeley DB link (-ldb-4$ol_cv_bdb_minor)" >&5 +-$as_echo_n "checking for Berkeley DB link (-ldb-4$ol_cv_bdb_minor)... " >&6; } +-if ${ol_cv_db_db_4m+:} false; then : +- $as_echo_n "(cached) " >&6 +-else +- +- ol_DB_LIB=-ldb-4$ol_cv_bdb_minor +- ol_LIBS=$LIBS +- LIBS="$ol_DB_LIB $LTHREAD_LIBS $LIBS" +- +- cat confdefs.h - <<_ACEOF >conftest.$ac_ext +-/* end confdefs.h. */ +- +-#ifdef HAVE_DB_185_H +-# include +-#else +-# include +-#endif +- +-#ifndef DB_VERSION_MAJOR +-# define DB_VERSION_MAJOR 1 +-#endif +- +-#ifndef NULL +-#define NULL ((void*)0) +-#endif +- +-int +-main () +-{ +- +-#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 +- +- ; +- return 0; +-} +-_ACEOF +-if ac_fn_c_try_link "$LINENO"; then : +- ol_cv_db_db_4m=yes +-else +- ol_cv_db_db_4m=no +-fi +-rm -f core conftest.err conftest.$ac_objext \ +- conftest$ac_exeext conftest.$ac_ext +- +- LIBS="$ol_LIBS" +- +-fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ol_cv_db_db_4m" >&5 +-$as_echo "$ol_cv_db_db_4m" >&6; } +- +- if test $ol_cv_db_db_4m = yes ; then +- ol_cv_lib_db=-ldb-4$ol_cv_bdb_minor +- fi +-fi +- +- if test $ol_cv_lib_db = no ; then +- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Berkeley DB link (-ldb-4-$ol_cv_bdb_minor)" >&5 +-$as_echo_n "checking for Berkeley DB link (-ldb-4-$ol_cv_bdb_minor)... " >&6; } +-if ${ol_cv_db_db_4_m+:} false; then : +- $as_echo_n "(cached) " >&6 +-else +- +- ol_DB_LIB=-ldb-4-$ol_cv_bdb_minor +- ol_LIBS=$LIBS +- LIBS="$ol_DB_LIB $LTHREAD_LIBS $LIBS" +- +- cat confdefs.h - <<_ACEOF >conftest.$ac_ext +-/* end confdefs.h. */ +- +-#ifdef HAVE_DB_185_H +-# include +-#else +-# include +-#endif +- +-#ifndef DB_VERSION_MAJOR +-# define DB_VERSION_MAJOR 1 +-#endif +- +-#ifndef NULL +-#define NULL ((void*)0) +-#endif +- +-int +-main () +-{ +- +-#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 +- +- ; +- return 0; +-} +-_ACEOF +-if ac_fn_c_try_link "$LINENO"; then : +- ol_cv_db_db_4_m=yes +-else +- ol_cv_db_db_4_m=no +-fi +-rm -f core conftest.err conftest.$ac_objext \ +- conftest$ac_exeext conftest.$ac_ext +- +- LIBS="$ol_LIBS" +- +-fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ol_cv_db_db_4_m" >&5 +-$as_echo "$ol_cv_db_db_4_m" >&6; } +- +- if test $ol_cv_db_db_4_m = yes ; then +- ol_cv_lib_db=-ldb-4-$ol_cv_bdb_minor +- fi +-fi +- +- if test $ol_cv_lib_db = no ; then +- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Berkeley DB link (-ldb-4)" >&5 +-$as_echo_n "checking for Berkeley DB link (-ldb-4)... " >&6; } +-if ${ol_cv_db_db_4+:} false; then : +- $as_echo_n "(cached) " >&6 +-else +- +- ol_DB_LIB=-ldb-4 +- ol_LIBS=$LIBS +- LIBS="$ol_DB_LIB $LTHREAD_LIBS $LIBS" +- +- cat confdefs.h - <<_ACEOF >conftest.$ac_ext +-/* end confdefs.h. */ +- +-#ifdef HAVE_DB_185_H +-# include +-#else +-# include +-#endif +- +-#ifndef DB_VERSION_MAJOR +-# define DB_VERSION_MAJOR 1 +-#endif +- +-#ifndef NULL +-#define NULL ((void*)0) +-#endif +- +-int +-main () +-{ +- +-#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 +- +- ; +- return 0; +-} +-_ACEOF +-if ac_fn_c_try_link "$LINENO"; then : +- ol_cv_db_db_4=yes +-else +- ol_cv_db_db_4=no +-fi +-rm -f core conftest.err conftest.$ac_objext \ +- conftest$ac_exeext conftest.$ac_ext +- +- LIBS="$ol_LIBS" +- +-fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ol_cv_db_db_4" >&5 +-$as_echo "$ol_cv_db_db_4" >&6; } +- +- if test $ol_cv_db_db_4 = yes ; then +- ol_cv_lib_db=-ldb-4 +- fi +-fi +- +- if test $ol_cv_lib_db = no ; then +- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Berkeley DB link (-ldb4)" >&5 +-$as_echo_n "checking for Berkeley DB link (-ldb4)... " >&6; } +-if ${ol_cv_db_db4+:} false; then : +- $as_echo_n "(cached) " >&6 +-else +- +- ol_DB_LIB=-ldb4 +- ol_LIBS=$LIBS +- LIBS="$ol_DB_LIB $LTHREAD_LIBS $LIBS" +- +- cat confdefs.h - <<_ACEOF >conftest.$ac_ext +-/* end confdefs.h. */ +- +-#ifdef HAVE_DB_185_H +-# include +-#else +-# include +-#endif +- +-#ifndef DB_VERSION_MAJOR +-# define DB_VERSION_MAJOR 1 +-#endif +- +-#ifndef NULL +-#define NULL ((void*)0) +-#endif +- +-int +-main () +-{ +- +-#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 +- +- ; +- return 0; +-} +-_ACEOF +-if ac_fn_c_try_link "$LINENO"; then : +- ol_cv_db_db4=yes +-else +- ol_cv_db_db4=no +-fi +-rm -f core conftest.err conftest.$ac_objext \ +- conftest$ac_exeext conftest.$ac_ext +- +- LIBS="$ol_LIBS" +- +-fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ol_cv_db_db4" >&5 +-$as_echo "$ol_cv_db_db4" >&6; } +- +- if test $ol_cv_db_db4 = yes ; then +- ol_cv_lib_db=-ldb4 +- fi +-fi +- +-fi +-if test $ol_cv_lib_db = no ; then +- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Berkeley DB link (-ldb)" >&5 +-$as_echo_n "checking for Berkeley DB link (-ldb)... " >&6; } +-if ${ol_cv_db_db+:} false; then : +- $as_echo_n "(cached) " >&6 +-else +- +- ol_DB_LIB=-ldb +- ol_LIBS=$LIBS +- LIBS="$ol_DB_LIB $LTHREAD_LIBS $LIBS" +- +- cat confdefs.h - <<_ACEOF >conftest.$ac_ext +-/* end confdefs.h. */ +- +-#ifdef HAVE_DB_185_H +-# include +-#else +-# include +-#endif +- +-#ifndef DB_VERSION_MAJOR +-# define DB_VERSION_MAJOR 1 +-#endif +- +-#ifndef NULL +-#define NULL ((void*)0) +-#endif +- +-int +-main () +-{ +- +-#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 +- +- ; +- return 0; +-} +-_ACEOF +-if ac_fn_c_try_link "$LINENO"; then : +- ol_cv_db_db=yes +-else +- ol_cv_db_db=no +-fi +-rm -f core conftest.err conftest.$ac_objext \ +- conftest$ac_exeext conftest.$ac_ext +- +- LIBS="$ol_LIBS" +- +-fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ol_cv_db_db" >&5 +-$as_echo "$ol_cv_db_db" >&6; } +- +- if test $ol_cv_db_db = yes ; then +- ol_cv_lib_db=-ldb +- fi +-fi +- +-if test $ol_cv_lib_db = no ; then +- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Berkeley DB link (default)" >&5 +-$as_echo_n "checking for Berkeley DB link (default)... " >&6; } +-if ${ol_cv_db_none+:} false; then : +- $as_echo_n "(cached) " >&6 +-else +- +- ol_DB_LIB= +- ol_LIBS=$LIBS +- LIBS="$ol_DB_LIB $LTHREAD_LIBS $LIBS" +- +- cat confdefs.h - <<_ACEOF >conftest.$ac_ext +-/* end confdefs.h. */ +- +-#ifdef HAVE_DB_185_H +-# include +-#else +-# include +-#endif +- +-#ifndef DB_VERSION_MAJOR +-# define DB_VERSION_MAJOR 1 +-#endif +- +-#ifndef NULL +-#define NULL ((void*)0) +-#endif +- +-int +-main () +-{ +- +-#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 +- +- ; +- return 0; +-} +-_ACEOF +-if ac_fn_c_try_link "$LINENO"; then : +- ol_cv_db_none=yes +-else +- ol_cv_db_none=no +-fi +-rm -f core conftest.err conftest.$ac_objext \ +- conftest$ac_exeext conftest.$ac_ext +- +- LIBS="$ol_LIBS" +- +-fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ol_cv_db_none" >&5 +-$as_echo "$ol_cv_db_none" >&6; } +- +- if test $ol_cv_db_none = yes ; then +- ol_cv_lib_db=yes +- fi +-fi +- +- +- if test "$ol_cv_lib_db" != no ; then +- ol_cv_berkeley_db=yes +- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Berkeley DB library and header version match" >&5 +-$as_echo_n "checking for Berkeley DB library and header version match... " >&6; } +-if ${ol_cv_berkeley_db_version+:} false; then : +- $as_echo_n "(cached) " >&6 +-else +- +- ol_LIBS="$LIBS" +- LIBS="$LTHREAD_LIBS $LIBS" +- if test $ol_cv_lib_db != yes ; then +- LIBS="$ol_cv_lib_db $LIBS" +- fi +- +- if test "$cross_compiling" = yes; then : +- ol_cv_berkeley_db_version=cross +-else +- cat confdefs.h - <<_ACEOF >conftest.$ac_ext +-/* end confdefs.h. */ +- +-#ifdef HAVE_DB_185_H +- choke me; +-#else +-#include +-#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; +-} +-_ACEOF +-if ac_fn_c_try_run "$LINENO"; then : +- ol_cv_berkeley_db_version=yes +-else +- ol_cv_berkeley_db_version=no +-fi +-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ +- conftest.$ac_objext conftest.beam conftest.$ac_ext +-fi +- +- +- LIBS="$ol_LIBS" +- +-fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ol_cv_berkeley_db_version" >&5 +-$as_echo "$ol_cv_berkeley_db_version" >&6; } +- +- if test $ol_cv_berkeley_db_version = no ; then +- as_fn_error $? "Berkeley DB version mismatch" "$LINENO" 5 +- fi +- +- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Berkeley DB thread support" >&5 +-$as_echo_n "checking for Berkeley DB thread support... " >&6; } +-if ${ol_cv_berkeley_db_thread+:} false; then : +- $as_echo_n "(cached) " >&6 +-else +- +- ol_LIBS="$LIBS" +- LIBS="$LTHREAD_LIBS $LIBS" +- if test $ol_cv_lib_db != yes ; then +- LIBS="$ol_cv_lib_db $LIBS" +- fi +- +- if test "$cross_compiling" = yes; then : +- ol_cv_berkeley_db_thread=cross +-else +- cat confdefs.h - <<_ACEOF >conftest.$ac_ext +-/* end confdefs.h. */ +- +-#ifdef HAVE_DB_185_H +- choke me; +-#else +-#include +-#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; +-} +-_ACEOF +-if ac_fn_c_try_run "$LINENO"; then : +- ol_cv_berkeley_db_thread=yes +-else +- ol_cv_berkeley_db_thread=no +-fi +-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ +- conftest.$ac_objext conftest.beam conftest.$ac_ext +-fi +- +- +- LIBS="$ol_LIBS" +- +-fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ol_cv_berkeley_db_thread" >&5 +-$as_echo "$ol_cv_berkeley_db_thread" >&6; } +- +- if test $ol_cv_berkeley_db_thread != no ; then +- +-$as_echo "#define HAVE_BERKELEY_DB_THREAD 1" >>confdefs.h +- +- fi +- +- fi +-fi +- +- +- if test $ol_cv_berkeley_db = no ; then +- as_fn_error $? "BDB/HDB: BerkeleyDB not available" "$LINENO" 5 +- fi +- +- +-$as_echo "#define HAVE_BERKELEY_DB 1" >>confdefs.h +- +- +- if test $ol_cv_lib_db != yes ; then +- BDB_LIBS="$BDB_LIBS $ol_cv_lib_db" +- fi +- +- 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 +- +- +-if test $ol_enable_dynamic = yes && test $enable_shared = yes ; then +- BUILD_LIBS_DYNAMIC=shared +- +-$as_echo "#define LDAP_LIBS_DYNAMIC 1" >>confdefs.h +- +- LTSTATIC="" +-else +- BUILD_LIBS_DYNAMIC=static +- LTSTATIC="-static" +-fi +- +-if test $ol_enable_wrappers != no ; then +- for ac_header in tcpd.h +-do : +- ac_fn_c_check_header_mongrel "$LINENO" "tcpd.h" "ac_cv_header_tcpd_h" "$ac_includes_default" +-if test "x$ac_cv_header_tcpd_h" = xyes; then : +- cat >>confdefs.h <<_ACEOF +-#define HAVE_TCPD_H 1 +-_ACEOF +- +- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for TCP wrappers library" >&5 +-$as_echo_n "checking for TCP wrappers library... " >&6; } +- save_LIBS="$LIBS" +- LIBS="$LIBS -lwrap" +- cat confdefs.h - <<_ACEOF >conftest.$ac_ext +-/* end confdefs.h. */ +- +-#include +-int allow_severity = 0; +-int deny_severity = 0; +- +-struct request_info *req; +- +-int +-main () +-{ +- +-hosts_access(req) +- +- ; +- return 0; +-} +-_ACEOF +-if ac_fn_c_try_link "$LINENO"; then : +- { $as_echo "$as_me:${as_lineno-$LINENO}: result: -lwrap" >&5 +-$as_echo "-lwrap" >&6; } +- have_wrappers=yes +- LIBS="$save_LIBS" +-else +- +- LIBS="$LIBS -lnsl" +- cat confdefs.h - <<_ACEOF >conftest.$ac_ext +-/* end confdefs.h. */ +- +-#include +-int allow_severity = 0; +-int deny_severity = 0; +- +-struct request_info *req; +- +-int +-main () +-{ +- +-hosts_access(req) +- +- ; +- return 0; +-} +-_ACEOF +-if ac_fn_c_try_link "$LINENO"; then : +- { $as_echo "$as_me:${as_lineno-$LINENO}: result: -lwrap -lnsl" >&5 +-$as_echo "-lwrap -lnsl" >&6; } +- have_wrappers=yes +- LIBS="$save_LIBS -lnsl" +-else +- +- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +-$as_echo "no" >&6; } +- have_wrappers=no +- LIBS=$save_LIBS +-fi +-rm -f core conftest.err conftest.$ac_objext \ +- conftest$ac_exeext conftest.$ac_ext +-fi +-rm -f core conftest.err conftest.$ac_objext \ +- conftest$ac_exeext conftest.$ac_ext +-else +- have_wrappers=no +-fi +- +-done +- +- +- if test $have_wrappers = yes ; then +- +-$as_echo "#define HAVE_TCPD 1" >>confdefs.h +- +- WRAP_LIBS="-lwrap" +- elif test $ol_enable_wrappers = yes ; then +- as_fn_error $? "could not find TCP wrappers, select apppropriate options or disable" "$LINENO" 5 +- else +- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find TCP wrappers, support disabled" >&5 +-$as_echo "$as_me: WARNING: could not find TCP wrappers, support disabled" >&2;} +- WRAP_LIBS="" +- fi +-fi +- +-if test $ol_enable_syslog != no ; then +- ac_fn_c_check_func "$LINENO" "openlog" "ac_cv_func_openlog" +-if test "x$ac_cv_func_openlog" = xyes; then : +- +-fi +- +- if test $ac_cv_func_openlog = no && test $ol_enable_syslog = yes; then +- as_fn_error select appropriate options or disable "could not find syslog" "$LINENO" 5 +- fi +- ol_enable_syslog=$ac_cv_func_openlog +-fi +- +-ol_link_sql=no +-if test $ol_enable_sql != no ; then +- for ac_header in sql.h sqlext.h +-do : +- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +-ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : +- cat >>confdefs.h <<_ACEOF +-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +-_ACEOF +- +-else +- +- as_fn_error $? "could not locate SQL headers" "$LINENO" 5 +- +-fi +- +-done +- +- +- sql_LIBS="$LIBS" +- LIBS="$LTHREAD_LIBS $LIBS" +- +- if test $ol_with_odbc = auto ; then +- ol_with_odbc="iodbc unixodbc odbc32" +- fi +- +- for odbc in $ol_with_odbc ; do +- if test $ol_link_sql = no ; then +- case $odbc in +- iodbc) +- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SQLDriverConnect in -liodbc" >&5 +-$as_echo_n "checking for SQLDriverConnect in -liodbc... " >&6; } +-if ${ac_cv_lib_iodbc_SQLDriverConnect+:} false; then : +- $as_echo_n "(cached) " >&6 +-else +- ac_check_lib_save_LIBS=$LIBS +-LIBS="-liodbc $LIBS" +-cat confdefs.h - <<_ACEOF >conftest.$ac_ext +-/* end confdefs.h. */ +- +-/* Override any GCC internal prototype to avoid an error. +- Use char because int might match the return type of a GCC +- builtin and then its argument prototype would still apply. */ +-#ifdef __cplusplus +-extern "C" +-#endif +-char SQLDriverConnect (); +-int +-main () +-{ +-return SQLDriverConnect (); ++return SQLDriverConnect (); + ; + return 0; + } +@@ -26763,23 +25530,6 @@ _ACEOF + + 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 +- +-cat >>confdefs.h <<_ACEOF +-#define SLAPD_BDB $MFLAG +-_ACEOF +- +-fi +- + if test "$ol_enable_dnssrv" != no ; then + BUILD_SLAPD=yes + BUILD_DNSSRV=$ol_enable_dnssrv +@@ -26797,23 +25547,6 @@ _ACEOF + + 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 +- +-cat >>confdefs.h <<_ACEOF +-#define SLAPD_HDB $MFLAG +-_ACEOF +- +-fi +- + if test "$ol_enable_ldap" != no ; then + BUILD_SLAPD=yes + BUILD_LDAP=$ol_enable_ldap +@@ -27447,7 +26180,7 @@ fi + + + +-ac_config_files="$ac_config_files Makefile:build/top.mk:Makefile.in:build/dir.mk doc/Makefile:build/top.mk:doc/Makefile.in:build/dir.mk doc/man/Makefile:build/top.mk:doc/man/Makefile.in:build/dir.mk doc/man/man1/Makefile:build/top.mk:doc/man/man1/Makefile.in:build/man.mk doc/man/man3/Makefile:build/top.mk:doc/man/man3/Makefile.in:build/man.mk doc/man/man5/Makefile:build/top.mk:doc/man/man5/Makefile.in:build/man.mk doc/man/man8/Makefile:build/top.mk:doc/man/man8/Makefile.in:build/man.mk clients/Makefile:build/top.mk:clients/Makefile.in:build/dir.mk clients/tools/Makefile:build/top.mk:clients/tools/Makefile.in:build/rules.mk include/Makefile:build/top.mk:include/Makefile.in libraries/Makefile:build/top.mk:libraries/Makefile.in:build/dir.mk libraries/liblber/Makefile:build/top.mk:libraries/liblber/Makefile.in:build/lib.mk:build/lib-shared.mk libraries/libldap/Makefile:build/top.mk:libraries/libldap/Makefile.in:build/lib.mk:build/lib-shared.mk libraries/libldap_r/Makefile:build/top.mk:libraries/libldap_r/Makefile.in:build/lib.mk:build/lib-shared.mk libraries/liblunicode/Makefile:build/top.mk:libraries/liblunicode/Makefile.in:build/lib.mk:build/lib-static.mk libraries/liblutil/Makefile:build/top.mk:libraries/liblutil/Makefile.in:build/lib.mk:build/lib-static.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 servers/slapd/back-meta/Makefile:build/top.mk:servers/slapd/back-meta/Makefile.in:build/mod.mk servers/slapd/back-monitor/Makefile:build/top.mk:servers/slapd/back-monitor/Makefile.in:build/mod.mk servers/slapd/back-ndb/Makefile:build/top.mk:servers/slapd/back-ndb/Makefile.in:build/mod.mk servers/slapd/back-null/Makefile:build/top.mk:servers/slapd/back-null/Makefile.in:build/mod.mk servers/slapd/back-passwd/Makefile:build/top.mk:servers/slapd/back-passwd/Makefile.in:build/mod.mk servers/slapd/back-perl/Makefile:build/top.mk:servers/slapd/back-perl/Makefile.in:build/mod.mk servers/slapd/back-relay/Makefile:build/top.mk:servers/slapd/back-relay/Makefile.in:build/mod.mk servers/slapd/back-shell/Makefile:build/top.mk:servers/slapd/back-shell/Makefile.in:build/mod.mk servers/slapd/back-sock/Makefile:build/top.mk:servers/slapd/back-sock/Makefile.in:build/mod.mk servers/slapd/back-sql/Makefile:build/top.mk:servers/slapd/back-sql/Makefile.in:build/mod.mk servers/slapd/shell-backends/Makefile:build/top.mk:servers/slapd/shell-backends/Makefile.in:build/srv.mk servers/slapd/slapi/Makefile:build/top.mk:servers/slapd/slapi/Makefile.in:build/lib.mk:build/lib-shared.mk servers/slapd/overlays/Makefile:build/top.mk:servers/slapd/overlays/Makefile.in:build/lib.mk tests/Makefile:build/top.mk:tests/Makefile.in:build/dir.mk tests/run tests/progs/Makefile:build/top.mk:tests/progs/Makefile.in:build/rules.mk" ++ac_config_files="$ac_config_files Makefile:build/top.mk:Makefile.in:build/dir.mk doc/Makefile:build/top.mk:doc/Makefile.in:build/dir.mk doc/man/Makefile:build/top.mk:doc/man/Makefile.in:build/dir.mk doc/man/man1/Makefile:build/top.mk:doc/man/man1/Makefile.in:build/man.mk doc/man/man3/Makefile:build/top.mk:doc/man/man3/Makefile.in:build/man.mk doc/man/man5/Makefile:build/top.mk:doc/man/man5/Makefile.in:build/man.mk doc/man/man8/Makefile:build/top.mk:doc/man/man8/Makefile.in:build/man.mk clients/Makefile:build/top.mk:clients/Makefile.in:build/dir.mk clients/tools/Makefile:build/top.mk:clients/tools/Makefile.in:build/rules.mk include/Makefile:build/top.mk:include/Makefile.in libraries/Makefile:build/top.mk:libraries/Makefile.in:build/dir.mk libraries/liblber/Makefile:build/top.mk:libraries/liblber/Makefile.in:build/lib.mk:build/lib-shared.mk libraries/libldap/Makefile:build/top.mk:libraries/libldap/Makefile.in:build/lib.mk:build/lib-shared.mk libraries/libldap_r/Makefile:build/top.mk:libraries/libldap_r/Makefile.in:build/lib.mk:build/lib-shared.mk libraries/liblunicode/Makefile:build/top.mk:libraries/liblunicode/Makefile.in:build/lib.mk:build/lib-static.mk libraries/liblutil/Makefile:build/top.mk:libraries/liblutil/Makefile.in:build/lib.mk:build/lib-static.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-dnssrv/Makefile:build/top.mk:servers/slapd/back-dnssrv/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 servers/slapd/back-meta/Makefile:build/top.mk:servers/slapd/back-meta/Makefile.in:build/mod.mk servers/slapd/back-monitor/Makefile:build/top.mk:servers/slapd/back-monitor/Makefile.in:build/mod.mk servers/slapd/back-ndb/Makefile:build/top.mk:servers/slapd/back-ndb/Makefile.in:build/mod.mk servers/slapd/back-null/Makefile:build/top.mk:servers/slapd/back-null/Makefile.in:build/mod.mk servers/slapd/back-passwd/Makefile:build/top.mk:servers/slapd/back-passwd/Makefile.in:build/mod.mk servers/slapd/back-perl/Makefile:build/top.mk:servers/slapd/back-perl/Makefile.in:build/mod.mk servers/slapd/back-relay/Makefile:build/top.mk:servers/slapd/back-relay/Makefile.in:build/mod.mk servers/slapd/back-shell/Makefile:build/top.mk:servers/slapd/back-shell/Makefile.in:build/mod.mk servers/slapd/back-sock/Makefile:build/top.mk:servers/slapd/back-sock/Makefile.in:build/mod.mk servers/slapd/back-sql/Makefile:build/top.mk:servers/slapd/back-sql/Makefile.in:build/mod.mk servers/slapd/shell-backends/Makefile:build/top.mk:servers/slapd/shell-backends/Makefile.in:build/srv.mk servers/slapd/slapi/Makefile:build/top.mk:servers/slapd/slapi/Makefile.in:build/lib.mk:build/lib-shared.mk servers/slapd/overlays/Makefile:build/top.mk:servers/slapd/overlays/Makefile.in:build/lib.mk tests/Makefile:build/top.mk:tests/Makefile.in:build/dir.mk tests/run tests/progs/Makefile:build/top.mk:tests/progs/Makefile.in:build/rules.mk" + + + ac_config_commands="$ac_config_commands default" +@@ -28411,9 +27144,7 @@ do + "libraries/librewrite/Makefile") CONFIG_FILES="$CONFIG_FILES libraries/librewrite/Makefile:build/top.mk:libraries/librewrite/Makefile.in:build/lib.mk:build/lib-static.mk" ;; + "servers/Makefile") CONFIG_FILES="$CONFIG_FILES servers/Makefile:build/top.mk:servers/Makefile.in:build/dir.mk" ;; + "servers/slapd/Makefile") CONFIG_FILES="$CONFIG_FILES servers/slapd/Makefile:build/top.mk:servers/slapd/Makefile.in:build/srv.mk" ;; +- "servers/slapd/back-bdb/Makefile") CONFIG_FILES="$CONFIG_FILES servers/slapd/back-bdb/Makefile:build/top.mk:servers/slapd/back-bdb/Makefile.in:build/mod.mk" ;; + "servers/slapd/back-dnssrv/Makefile") CONFIG_FILES="$CONFIG_FILES servers/slapd/back-dnssrv/Makefile:build/top.mk:servers/slapd/back-dnssrv/Makefile.in:build/mod.mk" ;; +- "servers/slapd/back-hdb/Makefile") CONFIG_FILES="$CONFIG_FILES servers/slapd/back-hdb/Makefile:build/top.mk:servers/slapd/back-hdb/Makefile.in:build/mod.mk" ;; + "servers/slapd/back-ldap/Makefile") CONFIG_FILES="$CONFIG_FILES servers/slapd/back-ldap/Makefile:build/top.mk:servers/slapd/back-ldap/Makefile.in:build/mod.mk" ;; + "servers/slapd/back-ldif/Makefile") CONFIG_FILES="$CONFIG_FILES servers/slapd/back-ldif/Makefile:build/top.mk:servers/slapd/back-ldif/Makefile.in:build/mod.mk" ;; + "servers/slapd/back-mdb/Makefile") CONFIG_FILES="$CONFIG_FILES servers/slapd/back-mdb/Makefile:build/top.mk:servers/slapd/back-mdb/Makefile.in:build/mod.mk" ;; +-- +2.19.1 + diff --git a/backport-delete-back-bdb-back-hdb.patch b/backport-delete-back-bdb-back-hdb.patch new file mode 100644 index 0000000..6eb148b --- /dev/null +++ b/backport-delete-back-bdb-back-hdb.patch @@ -0,0 +1,22206 @@ +From 8897fff4f352923b91e776bf9bc0bf8dbd636e85 Mon Sep 17 00:00:00 2001 +From: zhangqiumiao +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 +-#else +-# include +-#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 +-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 +-#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 +-#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 +-#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 +-#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 +- +- /* 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 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 . + + 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_.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 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 parameter +-specifies the total number of entries which may be held in the cache. +-The parameter specifies the total number of attribute sets ++{{EX:mdb}}. The parameter specifies the ++total number of entries which may be held in the cache. The ++ parameter specifies the total number of attribute sets + (as specified by the {{EX:pcacheAttrset}} directive) that may be + defined. The parameter specifies the maximum number of + entries in a cacheable query. The 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 [ by [] [] ]+ +@@ -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: + +-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: +- +-This directive specifies the size in entries of the in-memory +-cache maintained by the BDB backend database instance. +- +-\Default: +- +-> olcDbCachesize: 1000 +- +- + H4: olcDbCheckpoint: + +-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 data has been written or + minutes have passed since the last checkpoint. Both arguments default + to zero, in which case they are ignored. When the argument is + non-zero, an internal task will run every 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: ++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: +- +-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: { | 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: ++ ++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: ++ ++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: { | } +@@ -932,6 +885,18 @@ created database index files should have. This can be in the form + > olcDbMode: 0600 + + ++H4: olcDbRtxnsize: ++ ++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: + + Specify the depth of the stack used for search filter evaluation. +@@ -955,33 +920,21 @@ to take effect. + > olcDbSearchStack: 16 + + +-H4: olcDbShmKey: +- +-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 [ by [] [] ]+ + + This directive grants access (specified by ) to a set + of entries and/or attributes (specified by ) by one or more +-requestors (specified by ). See the {{SECT:Access Control}} section of ++requestors (specified by ). 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 + +-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 ++ ++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 data has been written or ++ minutes have passed since the last checkpoint. Both arguments default ++to zero, in which case they are ignored. When the argument is ++non-zero, an internal task will run every 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: { | default} [pres,eq,approx,sub,none] ++ ++This directive specifies the indices to maintain for the given ++attribute. If only an {{EX:}} 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: ++ ++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: ++ ++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: { | } ++ ++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: ++ ++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: ++ ++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=}}) + 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 \ +-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 \ +-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 \ \ +-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\fP data has been written or +-\fI\fP minutes have passed since the last checkpoint. +-Both arguments default to zero, in which case they are ignored. When +-the \fI\fP argument is non-zero, an internal task will run every +-\fI\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 \ +-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 \ +-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 \ +-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 \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 \ +-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 \ +-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 \ +-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\fR|\fBdefault\fR} [\fBpres\fR,\fBeq\fR,\fBapprox\fR,\fBsub\fR,\fI\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\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 \ +-Specify the file protection mode that newly created database +-index files should have. +-The default is 0600. +-.TP +-.BI searchstack \ +-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 \ +-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. + + 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\- (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 + Mark the beginning of a backend definition. + 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 + Mark the beginning of a new database instance definition. + 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 +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 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 +-# +-# for detail description of DB_CONFIG syntax and semantics. +-# +-# Hints can also be found in the OpenLDAP Software FAQ +-# +-# in particular: +-# +- +-# 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 . +- * +- * 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 +- * . +- */ +-/* 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 +-#include "alock.h" +-#include "lutil.h" +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#ifdef HAVE_SYS_FILE_H +-#include +-#endif +-#include +- +-#ifdef _WIN32 +-#include +-#include +-#include +-#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 . +- * +- * 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 +- * . +- */ +-/* 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 +-#include +- +-/* 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 . +-## +-## 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 +-## . +- +-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 . +- * +- * 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 +- * . +- */ +- +-#include "portable.h" +- +-#include +-#include +- +-#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, <id, +- 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, <2, +- 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 . +- * +- * 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 +- * . +- */ +- +-#include "portable.h" +- +-#include +- +-#include +-#include +- +-#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; ibi_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; ibi_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 (; ibi_nattrs; i++) +- bdb->bi_attrs[i] = bdb->bi_attrs[i+1]; +- } +-} +- +-void bdb_attr_flush( struct bdb_info *bdb ) +-{ +- int i; +- +- for ( i=0; ibi_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; jbi_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 . +- * +- * 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 +- * . +- */ +- +-#ifndef _BACK_BDB_H_ +-#define _BACK_BDB_H_ +- +-#include +-#include "slap.h" +-#include +-#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. +- * +- * 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 +- * . +- */ +- +-#include "portable.h" +- +-#include +-#include +-#include +- +-#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 . +- * +- * 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 +- * . +- */ +- +-#include "portable.h" +- +-#include +- +-#include +-#include +-#include +- +-#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 . +- * +- * 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 +- * . +- */ +- +-#include "portable.h" +- +-#include +-#include +- +-#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 . +- * +- * 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 +- * . +- */ +- +-#include "portable.h" +- +-#include +-#include +-#include +-#include +- +-#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> <[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 \" 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 . +- * +- * 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 +- * . +- */ +- +-#include "portable.h" +- +-#include +- +-#include +-#include +-#include +-#include +-#include +- +-#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 . +- * +- * 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 +- * . +- */ +- +-#include "portable.h" +- +-#include +-#include +- +-#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, <id, +- 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, <2, +- 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 . +- * +- * 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 +- * . +- */ +- +-#include "portable.h" +- +-#include +-#include +- +-#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 . +- * +- * 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 +- * . +- */ +- +-#include "portable.h" +- +-#include +-#include +- +-#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 . +- * +- * 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 +- * . +- */ +- +-#include "portable.h" +- +-#include +-#include +- +-#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 . +- * +- * 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 +- * . +- */ +- +-#include "portable.h" +- +-#include +-#include +- +-#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 . +- * +- * 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 +- * . +- */ +- +-#include "portable.h" +- +-#include +-#include +- +-#include "back-bdb.h" +-#include "idl.h" +-#ifdef LDAP_COMP_MATCH +-#include +-#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 . +- * +- * 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 +- * . +- */ +- +-#include "portable.h" +- +-#include +-#include +-#include +- +-#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 . +- * +- * 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 +- * . +- */ +- +-#include "portable.h" +- +-#include +-#include +- +-#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; ic_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 . +- * +- * 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 +- * . +- */ +- +-#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<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 . +- * +- * 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 +- * . +- */ +- +-#include "portable.h" +- +-#include +- +-#include +-#include +- +-#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; ibi_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 . +- * +- * 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 +- * . +- */ +- +-#include "portable.h" +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include "back-bdb.h" +-#include +-#include +-#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 . +- * +- * 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 +- * . +- */ +- +-#include "portable.h" +- +-#include +- +-#include +-#include +- +-#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 . +- * +- * 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 +- * . +- */ +- +-#include "portable.h" +- +-#include +-#include +-#include +- +-#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, <id, +- 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, <2, 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 . +- * +- * 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 +- * . +- */ +- +-#include "portable.h" +- +-#include +-#include +- +-#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, <id, +- 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, <2, 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 . +- * +- * 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 +- * . +- */ +- +-#include "portable.h" +- +-#include +-#include +-#include +-#include +-#include +-#include +-#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 . +- * +- * 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 +- * . +- */ +- +-#include "portable.h" +- +-#include +-#include +- +-#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 . +- * +- * 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 +- * . +- */ +- +-#include "portable.h" +- +-#include +- +-#include +-#include +- +-#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 . +- * +- * 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 +- * . +- */ +- +-#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 . +- * +- * 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 +- * . +- */ +- +-#include "portable.h" +-#include +-#include +- +-#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 . +- * +- * 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 +- * . +- */ +- +-#include "portable.h" +- +-#include +-#include +- +-#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, <id ); +- +- 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 . +- * +- * 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 +- * . +- */ +- +-#include "portable.h" +- +-#include +-#include +-#include +- +-#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 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; ibe_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; ie_id ) { +- free(holes[i].dn.bv_val); +- for (j=i;j 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; ie_id, 0 ); +- if ( rc ) +- return rc; +- ldap_pvt_thread_mutex_lock( &bdb_tool_index_mutex ); +- for ( i=1; ibv_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; iids[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 . +- * +- * 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 +- * . +- */ +- +-#include "portable.h" +- +-#include +-#include +- +-#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 . +-## +-## 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 +-## . +-# +-## 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 . +- * +- * 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 +- * . +- */ +-/* 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= 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 (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 + diff --git a/openldap.spec b/openldap.spec index 965a3df..de7324c 100644 --- a/openldap.spec +++ b/openldap.spec @@ -2,7 +2,7 @@ Name: openldap Version: 2.4.50 -Release: 5 +Release: 6 Summary: LDAP support libraries License: OpenLDAP URL: https://www.openldap.org/ @@ -57,6 +57,11 @@ Patch36: CVE-2020-36227.patch Patch37: CVE-2020-36228.patch Patch38: CVE-2020-36230.patch Patch39: CVE-2020-36229.patch +Patch40: backport-delete-back-bdb-back-hdb.patch +Patch41: backport-Fix-test-suite.patch +Patch42: backport-ITS-9010-regenerate-configure.patch +Patch43: backport-ITS-9010-More-BDB-HDB-cleanup.patch + BuildRequires: cyrus-sasl-devel openssl-devel krb5-devel unixODBC-devel BuildRequires: glibc-devel libtool libtool-ltdl-devel groff perl-interpreter perl-devel perl-generators perl-ExtUtils-Embed @@ -85,11 +90,11 @@ customized LDAP clients. %package servers Summary: LDAP server License: OpenLDAP -Requires: openldap = %{version}-%{release} libdb-utils +Requires: openldap = %{version}-%{release} Requires(pre): shadow-utils %{?systemd_requires} BuildRequires: systemd -BuildRequires: libdb-devel cracklib-devel +BuildRequires: cracklib-devel Provides: ldif2ldbm %description servers @@ -161,6 +166,10 @@ AUTOMAKE=%{_bindir}/true autoreconf -fi %patch37 -p1 %patch38 -p1 %patch39 -p1 +%patch40 -p1 +%patch41 -p1 +%patch42 -p1 +%patch43 -p1 ln -s ../../../contrib/slapd-modules/smbk5pwd/smbk5pwd.c servers/slapd/overlays mv contrib/slapd-modules/smbk5pwd/README contrib/slapd-modules/smbk5pwd/README.smbk5pwd @@ -193,7 +202,7 @@ pushd openldap-%{version} --enable-cleartext --enable-crypt --enable-lmpasswd \ --enable-spasswd --enable-modules --enable-rewrite \ --enable-rlookups --enable-slapi --disable-slp \ - --enable-backends=mod --enable-bdb=yes --enable-hdb=yes \ + --enable-backends=mod \ --enable-mdb=yes --enable-monitor=yes --disable-ndb \ --disable-sql --enable-overlays=mod --disable-static \ --with-cyrus-sasl --without-fetch --with-threads \ @@ -288,13 +297,10 @@ install -m 0755 -d %{buildroot}%{_datadir}/openldap-servers install -m 0644 %SOURCE3 %{buildroot}%{_datadir}/openldap-servers/slapd.ldif install -m 0700 -d %{buildroot}%{_sysconfdir}/openldap/slapd.d mv %{buildroot}%{_sysconfdir}/openldap/schema/README README.schema -mv %{buildroot}%{_sysconfdir}/openldap/DB_CONFIG.example %{buildroot}%{_datadir}/openldap-servers/DB_CONFIG.example -chmod 0644 %{buildroot}%{_datadir}/openldap-servers/DB_CONFIG.example rm -f %{buildroot}%{_libdir}/*.la rm -f %{buildroot}%{_localstatedir}/openldap-data/DB_CONFIG.example -rmdir %{buildroot}%{_localstatedir}/openldap-data %ldconfig_scriptlets @@ -443,6 +449,9 @@ popd %doc ltb-project-openldap-ppolicy-check-password-1.1/README.check_pwd %changelog +* Thu Feb 25 2021 orange-snn - 2.4.50-6 +- remove libdb-devel in buildrequires and requires. + * Thu Feb 18 2021 liulong - 2.4.50-5 - Type:cves - ID:NA -- Gitee