This commits deletes all references and code for back-bdb and back-hdb.
There is some follow up work still necessary to flush out the admin
guide for back-mdb.
libraries/librewrite/version.c
servers/slapd/.backend
servers/slapd/all-cffiles
-servers/slapd/back-hdb/add.c
-servers/slapd/back-hdb/attr.c
-servers/slapd/back-hdb/bind.c
-servers/slapd/back-hdb/cache.c
-servers/slapd/back-hdb/compare.c
-servers/slapd/back-hdb/config.c
-servers/slapd/back-hdb/dbcache.c
-servers/slapd/back-hdb/delete.c
-servers/slapd/back-hdb/dn2entry.c
-servers/slapd/back-hdb/dn2id.c
-servers/slapd/back-hdb/error.c
-servers/slapd/back-hdb/extended.c
-servers/slapd/back-hdb/filterindex.c
-servers/slapd/back-hdb/id2entry.c
-servers/slapd/back-hdb/idl.c
-servers/slapd/back-hdb/index.c
-servers/slapd/back-hdb/init.c
-servers/slapd/back-hdb/key.c
-servers/slapd/back-hdb/modify.c
-servers/slapd/back-hdb/modrdn.c
-servers/slapd/back-hdb/monitor.c
-servers/slapd/back-hdb/nextid.c
-servers/slapd/back-hdb/operational.c
-servers/slapd/back-hdb/referral.c
-servers/slapd/back-hdb/search.c
-servers/slapd/back-hdb/tools.c
-servers/slapd/back-hdb/trans.c
servers/slapd/backends.c
servers/slapd/overlays/statover.c
servers/slapd/slapacl
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
fi
fi
])
-dnl
-dnl ====================================================================
-dnl Berkeley DB macros
-dnl
-dnl --------------------------------------------------------------------
-dnl Try to link
-AC_DEFUN([OL_BERKELEY_DB_TRY],
-[if test $ol_cv_lib_db = no ; then
- AC_CACHE_CHECK([for Berkeley DB link (]ifelse($2,,default,$2)[)],[$1],
-[
- ol_DB_LIB=ifelse($2,,,$2)
- ol_LIBS=$LIBS
- LIBS="$ol_DB_LIB $LTHREAD_LIBS $LIBS"
-
- AC_LINK_IFELSE([AC_LANG_PROGRAM([[
-#ifdef HAVE_DB_185_H
-# include <db_185.h>
-#else
-# include <db.h>
-#endif
-
-#ifndef DB_VERSION_MAJOR
-# define DB_VERSION_MAJOR 1
-#endif
-
-#ifndef NULL
-#define NULL ((void*)0)
-#endif
-]], [[
-#if DB_VERSION_MAJOR > 2
- db_env_create( NULL, 0 );
-#elif DB_VERSION_MAJOR > 1
- db_appexit( NULL );
-#else
- (void) dbopen( NULL, 0, 0, 0, NULL);
-#endif
-]])],[$1=yes],[$1=no])
-
- LIBS="$ol_LIBS"
-])
-
- if test $$1 = yes ; then
- ol_cv_lib_db=ifelse($2,,yes,$2)
- fi
-fi
-])
-dnl
-dnl --------------------------------------------------------------------
-dnl Get major and minor version from <db.h>
-AC_DEFUN([OL_BDB_HEADER_VERSION],
-[AC_CACHE_CHECK([for Berkeley DB major version in db.h], [ol_cv_bdb_major],[
- AC_LANG_CONFTEST([AC_LANG_SOURCE([
-#include <db.h>
-#ifndef DB_VERSION_MAJOR
-# define DB_VERSION_MAJOR 1
-#endif
-__db_version DB_VERSION_MAJOR
-])])
- set X `eval "$ac_cpp -P conftest.$ac_ext" | $EGREP __db_version` none none
- ol_cv_bdb_major=${3}
-])
-case $ol_cv_bdb_major in [[1-9]]*) : ;; *)
- AC_MSG_ERROR([Unknown Berkeley DB major version in db.h]) ;;
-esac
-
-dnl Determine minor version
-AC_CACHE_CHECK([for Berkeley DB minor version in db.h], [ol_cv_bdb_minor],[
- AC_LANG_CONFTEST([AC_LANG_SOURCE([
-#include <db.h>
-#ifndef DB_VERSION_MINOR
-# define DB_VERSION_MINOR 0
-#endif
-__db_version DB_VERSION_MINOR
-])])
- set X `eval "$ac_cpp -P conftest.$ac_ext" | $EGREP __db_version` none none
- ol_cv_bdb_minor=${3}
-])
-case $ol_cv_bdb_minor in [[0-9]]*) : ;; *)
- AC_MSG_ERROR([Unknown Berkeley DB minor version in db.h]) ;;
-esac
-])
-dnl
-dnl --------------------------------------------------------------------
-dnl Try to locate appropriate library
-AC_DEFUN([OL_BERKELEY_DB_LINK],
-[ol_cv_lib_db=no
-
-if test $ol_cv_bdb_major = 5 ; then
- OL_BERKELEY_DB_TRY(ol_cv_db_db_5_dot_m,[-ldb-5.$ol_cv_bdb_minor])
- OL_BERKELEY_DB_TRY(ol_cv_db_db5m,[-ldb5$ol_cv_bdb_minor])
- OL_BERKELEY_DB_TRY(ol_cv_db_db_5m,[-ldb-5$ol_cv_bdb_minor])
- OL_BERKELEY_DB_TRY(ol_cv_db_db_5_m,[-ldb-5-$ol_cv_bdb_minor])
- OL_BERKELEY_DB_TRY(ol_cv_db_db_5,[-ldb-5])
- OL_BERKELEY_DB_TRY(ol_cv_db_db5,[-ldb5])
-elif test $ol_cv_bdb_major = 4 ; then
- OL_BERKELEY_DB_TRY(ol_cv_db_db_4_dot_m,[-ldb-4.$ol_cv_bdb_minor])
- OL_BERKELEY_DB_TRY(ol_cv_db_db4m,[-ldb4$ol_cv_bdb_minor])
- OL_BERKELEY_DB_TRY(ol_cv_db_db_4m,[-ldb-4$ol_cv_bdb_minor])
- OL_BERKELEY_DB_TRY(ol_cv_db_db_4_m,[-ldb-4-$ol_cv_bdb_minor])
- OL_BERKELEY_DB_TRY(ol_cv_db_db_4,[-ldb-4])
- OL_BERKELEY_DB_TRY(ol_cv_db_db4,[-ldb4])
-fi
-OL_BERKELEY_DB_TRY(ol_cv_db_db,[-ldb])
-OL_BERKELEY_DB_TRY(ol_cv_db_none)
-])
-dnl
-dnl --------------------------------------------------------------------
-dnl Check if Berkeley DB version
-AC_DEFUN([OL_BERKELEY_DB_VERSION],
-[AC_CACHE_CHECK([for Berkeley DB library and header version match], [ol_cv_berkeley_db_version], [
- ol_LIBS="$LIBS"
- LIBS="$LTHREAD_LIBS $LIBS"
- if test $ol_cv_lib_db != yes ; then
- LIBS="$ol_cv_lib_db $LIBS"
- fi
-
- AC_RUN_IFELSE([AC_LANG_SOURCE([[
-#ifdef HAVE_DB_185_H
- choke me;
-#else
-#include <db.h>
-#endif
-#ifndef DB_VERSION_MAJOR
-# define DB_VERSION_MAJOR 1
-#endif
-#ifndef NULL
-#define NULL ((void *)0)
-#endif
-main()
-{
-#if DB_VERSION_MAJOR > 1
- char *version;
- int major, minor, patch;
-
- version = db_version( &major, &minor, &patch );
-
- if( major != DB_VERSION_MAJOR ||
- minor != DB_VERSION_MINOR ||
- patch != DB_VERSION_PATCH )
- {
- printf("Berkeley DB version mismatch\n"
- "\theader: %s\n\tlibrary: %s\n",
- DB_VERSION_STRING, version);
- return 1;
- }
-#endif
-
- return 0;
-}]])],[ol_cv_berkeley_db_version=yes],[ol_cv_berkeley_db_version=no],[ol_cv_berkeley_db_version=cross])
-
- LIBS="$ol_LIBS"
-])
-
- if test $ol_cv_berkeley_db_version = no ; then
- AC_MSG_ERROR([Berkeley DB version mismatch])
- fi
-])dnl
-dnl
-dnl --------------------------------------------------------------------
-dnl Check if Berkeley DB supports DB_THREAD
-AC_DEFUN([OL_BERKELEY_DB_THREAD],
-[AC_CACHE_CHECK([for Berkeley DB thread support], [ol_cv_berkeley_db_thread], [
- ol_LIBS="$LIBS"
- LIBS="$LTHREAD_LIBS $LIBS"
- if test $ol_cv_lib_db != yes ; then
- LIBS="$ol_cv_lib_db $LIBS"
- fi
-
- AC_RUN_IFELSE([AC_LANG_SOURCE([[
-#ifdef HAVE_DB_185_H
- choke me;
-#else
-#include <db.h>
-#endif
-#ifndef NULL
-#define NULL ((void *)0)
-#endif
-main()
-{
- int rc;
- u_int32_t flags = DB_CREATE |
-#ifdef DB_PRIVATE
- DB_PRIVATE |
-#endif
- DB_THREAD;
-
-#if DB_VERSION_MAJOR > 2
- DB_ENV *env = NULL;
-
- rc = db_env_create( &env, 0 );
-
- flags |= DB_INIT_MPOOL;
-#ifdef DB_MPOOL_PRIVATE
- flags |= DB_MPOOL_PRIVATE;
-#endif
-
- if( rc ) {
- printf("BerkeleyDB: %s\n", db_strerror(rc) );
- return rc;
- }
-
-#if (DB_VERSION_MAJOR > 3) || (DB_VERSION_MINOR >= 1)
- rc = (env->open)( env, NULL, flags, 0 );
-#else
- rc = (env->open)( env, NULL, NULL, flags, 0 );
-#endif
-
- if ( rc == 0 ) {
- rc = env->close( env, 0 );
- }
-
- if( rc ) {
- printf("BerkeleyDB: %s\n", db_strerror(rc) );
- return rc;
- }
-
-#else
- DB_ENV env;
- memset( &env, '\0', sizeof(env) );
-
- rc = db_appinit( NULL, NULL, &env, flags );
-
- if( rc == 0 ) {
- db_appexit( &env );
- }
-
- unlink("__db_mpool.share");
- unlink("__db_lock.share");
-#endif
-
- return rc;
-}]])],[ol_cv_berkeley_db_thread=yes],[ol_cv_berkeley_db_thread=no],[ol_cv_berkeley_db_thread=cross])
-
- LIBS="$ol_LIBS"
-])
-
- if test $ol_cv_berkeley_db_thread != no ; then
- AC_DEFINE(HAVE_BERKELEY_DB_THREAD, 1,
- [define if Berkeley DB has DB_THREAD support])
- fi
-])dnl
-dnl
-dnl --------------------------------------------------------------------
-dnl Find any DB
-AC_DEFUN([OL_BERKELEY_DB],
-[ol_cv_berkeley_db=no
-AC_CHECK_HEADERS(db.h)
-if test $ac_cv_header_db_h = yes; then
- OL_BDB_HEADER_VERSION
- OL_BDB_COMPAT
-
- if test $ol_cv_bdb_compat != yes ; then
- AC_MSG_ERROR([BerkeleyDB version incompatible with BDB/HDB backends])
- fi
-
- OL_BERKELEY_DB_LINK
- if test "$ol_cv_lib_db" != no ; then
- ol_cv_berkeley_db=yes
- OL_BERKELEY_DB_VERSION
- OL_BERKELEY_DB_THREAD
- fi
-fi
-])
-dnl --------------------------------------------------------------------
-dnl Check for version compatibility with back-bdb
-AC_DEFUN([OL_BDB_COMPAT],
-[AC_CACHE_CHECK([if Berkeley DB version supported by BDB/HDB backends], [ol_cv_bdb_compat],[
- AC_EGREP_CPP(__db_version_compat,[
-#include <db.h>
-
- /* this check could be improved */
-#ifndef DB_VERSION_MAJOR
-# define DB_VERSION_MAJOR 1
-#endif
-#ifndef DB_VERSION_MINOR
-# define DB_VERSION_MINOR 0
-#endif
-#ifndef DB_VERSION_PATCH
-# define DB_VERSION_PATCH 0
-#endif
-
-#define DB_VERSION_FULL ((DB_VERSION_MAJOR<<16)|(DB_VERSION_MINOR<<8)|DB_VERSION_PATCH)
-
-/* require 4.4 or later, but less than 6.0.20 */
-#if DB_VERSION_FULL >= 0x040400 && DB_VERSION_FULL < 0x060014
- __db_version_compat
-#endif
-#if DB_VERSION_FULL >= 0x060014
-#error "BerkeleyDB 6.0.20+ license is incompatible with LDAP"
-#endif
- ], [ol_cv_bdb_compat=yes], [ol_cv_bdb_compat=no])])
-])
dnl
dnl ====================================================================
LUTIL_LIBS = @LUTIL_LIBS@
LTHREAD_LIBS = @LTHREAD_LIBS@
-BDB_LIBS = @BDB_LIBS@
SLAPD_NDB_LIBS = @SLAPD_NDB_LIBS@
WT_LIBS = @WT_LIBS@
dnl ----------------------------------------------------------------
dnl SLAPD Backend Options
-Backends="bdb \
- dnssrv \
- hdb \
+Backends="dnssrv \
ldap \
mdb \
meta \
OL_ARG_ENABLE(backends,[ --enable-backends enable all available backends],
--, [no yes mod])dnl
-OL_ARG_ENABLE(bdb,[ --enable-bdb enable Berkeley DB backend],
- no, [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],
- no, [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],
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 &&
dnl Initialize vars
LDAP_LIBS=
-BDB_LIBS=
SLAPD_NDB_LIBS=
SLAPD_NDB_INCS=
LTHREAD_LIBS=
BUILD_SLAPI=no
SLAPD_SLAPI_DEPEND=
-BUILD_BDB=no
BUILD_DNSSRV=no
-BUILD_HDB=no
BUILD_LDAP=no
BUILD_MDB=no
BUILD_META=no
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
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
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
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)
AC_SUBST(LDAP_LIBS)
AC_SUBST(CLIENT_LIBS)
AC_SUBST(SLAPD_LIBS)
-AC_SUBST(BDB_LIBS)
AC_SUBST(SLAPD_NDB_LIBS)
AC_SUBST(SLAPD_NDB_INCS)
AC_SUBST(LTHREAD_LIBS)
[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]
* 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
moduleload <path to>nssov.so
...
- database hdb
+ database mdb
...
overlay nssov
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
.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
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)
* 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.
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
> 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.
-
env
pagedResultsControl
dup
-hdb
LDIFv
syslog
monitorTimestamp
proxyAttrset
mary
crlcheck
-olcBdbConfig
kadmin
mech
slapcat
calloc
LDFLAGS
attributeOrValueExists
-olcHdbConfig
bsize
auditObject
dnssrv
odbcinst
reqType
slapover
-BerkeleyDB's
attributename
lwrap
reqStart
olcHidden
mySNMP
metainformation
-BerkeleyDB
ldapuri
auditAbandon
RANDFILE
ldapc
loopback
ldapi
-BDB's
GETREALM
functionalities
noplain
AES
ldaps
notoc
-bdb
LDAPv
IPsec
olcServerID
> back_<backend name>.la
-So for example, if you need to load the {{hdb}} backend, you would configure
+So for example, if you need to load the {{mdb}} backend, you would configure
-> moduleload back_hdb.la
-
-H2: Berkeley DB Backends
-
-
-H3: Overview
-
-The {{hdb}} backend to {{slapd}}(8) is a backend for a
-normal {{slapd}} database. It uses the Oracle Berkeley DB ({{TERM:BDB}})
-package to store data. It makes extensive use of indexing and caching
-(see the {{SECT:Tuning}} section) to speed data access.
-
-{{hdb}} is a variant of the original {{bdb}} backend which was first written for use with BDB.
-{{hdb}} uses a hierarchical database layout which supports subtree renames.
-It is otherwise identical to the {{bdb}}
-behavior, and all the same configuration options apply.
-
-Note: An {{hdb}} database needs a large {{idlcachesize}} for good search performance,
-typically three times the {{cachesize}} (entry cache size) or larger.
-
-Note: The {{hdb}} backend has superseded the {{bdb}} backend, and both will
-are 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
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 replaces 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
>
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,
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
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):
{{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
is a sparse file via the use of the "writemap" environment flag, the resulting
copy will be the actual size of the database rather than a sparse copy.
-2. 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.
-
-
-3. Periodically run slapcat and back up the LDIF file:
+2. 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
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-mdb, back-bdb, or back-hdb databases.
+back-mdb databases.
> slapcat -f slapd.conf -b "dc=example,dc=com"
-For back-mdb, back-bdb, and back-hdb, this command may be ran while slapd(8) is running.
-
-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
+{{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}}
> 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
> 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
-> 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
->
-> dn: cn=Backend 5,cn=Backends,cn=Monitor
> monitoredInfo: mdb
> monitorRuntimeConfig: TRUE
> supportedControl: 1.3.6.1.1.12
The following is a basic example that implements Access Logging:
-> database bdb
+> database mdb
> suffix dc=example,dc=com
> ...
> overlay accesslog
> logops writes reads
> logold (objectclass=person)
>
-> database bdb
+> database mdb
> suffix cn=log
> ...
> index reqStart eq
The following is an example used for {{SECT:delta-syncrepl replication}}:
-> database hdb
+> database mdb
> suffix cn=accesslog
> directory /usr/local/var/openldap-accesslog
> rootdn cn=accesslog
Accesslog overlay definitions for the primary db
-> database bdb
+> database mdb
> suffix dc=example,dc=com
> ...
> overlay accesslog
>
> authz-regexp "gidNumber=0\\\+uidNumber=0,cn=peercred,cn=external,cn=auth"
> "cn=Manager,dc=example,dc=com"
-> database bdb
+> database mdb
> suffix "dc=example,dc=com"
> rootdn "cn=Manager,dc=example,dc=com"
> rootpw secret
This directive enables proxy caching and sets general cache
parameters. The <DB> parameter specifies which underlying database
is to be used to hold cached entries. It should be set to
-{{EX:bdb}} or {{EX:hdb}}. The <maxentries> parameter specifies the
+{{EX:mdb}}. The <maxentries> parameter specifies the
total number of entries which may be held in the cache. The
<nattrsets> parameter specifies the total number of attribute sets
(as specified by the {{EX:pcacheAttrset}} directive) that may be
> rootdn "dc=example,dc=com"
> uri ldap://ldap.example.com/
> overlay pcache
-> pcache hdb 100000 1 1000 100
+> pcache mdb 100000 1 1000 100
> pcacheAttrset 0 mail postaladdress telephonenumber
> pcacheTemplate (sn=) 0 3600
> pcacheTemplate (&(sn=)(givenName=)) 0 3600
> objectClass: olcOverlayConfig
> objectClass: olcPcacheConfig
> olcOverlay: {0}pcache
-> olcPcache: hdb 100000 1 1000 100
+> olcPcache: mdb 100000 1 1000 100
> olcPcacheAttrset: 0 mail postalAddress telephoneNumber
> olcPcacheTemplate: "(sn=)" 0 3600 0 0 0
> olcPcacheTemplate: "(&(sn=)(givenName=))" 0 3600 0 0 0
context "dc=example,dc=com". In this example we are also specifying the DN of
a policy object to use if none other is specified in a user's object.
-> database bdb
+> database mdb
> suffix "dc=example,dc=com"
> [...additional database configuration directives go here...]
>
H3: Overview
-This overlay can be used with a backend database such as slapd-bdb(5)
+This overlay can be used with a backend database such as slapd-mdb(5)
to maintain the cohesiveness of a schema which utilizes reference
attributes.
H3: Overview
-This overlay can be used with a backend database such as {{:slapd-bdb}}(5)
+This overlay can be used with a backend database such as {{:slapd-mdb}}(5)
to create a "translucent proxy".
Entries retrieved from a remote LDAP server may have some or all attributes
> pidfile ./slapd.pid
> argsfile ./slapd.args
>
-> database bdb
+> database mdb
> suffix "dc=suretecsystems,dc=com"
> rootdn "cn=trans,dc=suretecsystems,dc=com"
> rootpw secret
H3: Overview
-This overlay can be used with a backend database such as {{slapd-bdb(5)}}
+This overlay can be used with a backend database such as {{slapd-mdb(5)}}
to enforce the uniqueness of some or all attributes within a subtree.
> loglevel sync stats
>
-> database hdb
+> database mdb
> suffix "dc=suretecsystems,dc=com"
> directory /usr/local/var/openldap-data
>
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}}
+backend.
The LDAP Sync provider maintains a {{EX:contextCSN}} for each
database as the current synchronization state indicator of the
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
> # Set the module path location
> modulepath /opt/symas/lib/openldap
>
-> # Load the hdb backend
-> moduleload back_hdb.la
+> # Load the mdb backend
+> moduleload back_mdb.la
>
> # Load the accesslog overlay
> moduleload accesslog.la
> moduleload syncprov.la
>
> # Accesslog database definitions
-> database hdb
+> database mdb
> suffix cn=accesslog
> directory /db/accesslog
> rootdn cn=accesslog
> limits dn.exact="cn=replicator,dc=symas,dc=com" time.soft=unlimited time.hard=unlimited size.soft=unlimited size.hard=unlimited
>
> # Primary database definitions
-> database hdb
+> database mdb
> suffix "dc=symas,dc=com"
> rootdn "cn=manager,dc=symas,dc=com"
>
H4: Delta-syncrepl Consumer configuration
> # Replica database configuration
-> database hdb
+> database mdb
> suffix "dc=symas,dc=com"
> rootdn "cn=manager,dc=symas,dc=com"
>
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.
> include /usr/local/etc/openldap/slapd.acl
>
> modulepath /usr/local/libexec/openldap
-> moduleload back_hdb.la
+> moduleload back_mdb.la
> moduleload syncprov.la
> moduleload back_monitor.la
> moduleload back_ldap.la
>
> loglevel sync stats
>
-> database hdb
+> database mdb
> suffix "dc=suretecsystems,dc=com"
> directory /usr/local/var/openldap-data
>
> include /usr/local/etc/openldap/slapd.acl
>
> modulepath /usr/local/libexec/openldap
-> moduleload back_hdb.la
+> moduleload back_mdb.la
> moduleload syncprov.la
> moduleload back_monitor.la
> moduleload back_ldap.la
>
> loglevel sync stats
>
-> database hdb
+> database mdb
> suffix "dc=suretecsystems,dc=com"
> directory /usr/local/var/openldap-slave/data
>
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.
!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
!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
\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
H4: Sample Entry
-> dn: olcBackend=bdb,cn=config
+> dn: olcBackend=mdb,cn=config
> objectClass: olcBackendConfig
-> olcBackend: bdb
+> olcBackend: mdb
H3: Database-specific Directives
\Example:
-> olcDatabase: bdb
+> olcDatabase: mdb
-This marks the beginning of a new {{TERM:BDB}} database instance.
+This marks the beginning of a new {{TERM:MDB}} database instance.
H4: olcAccess: to <what> [ by <who> [<accesslevel>] [<control>] ]+
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
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.
>olcRootDN: cn=Manager,dc=example,dc=com
-H3: BDB and HDB Database Directives
+H3: MDB Database Directives
-Directives in this category apply to both the {{TERM:BDB}}
-and the {{TERM:HDB}} database.
+Directives in this category apply to the {{TERM:MDB}}
+database backend.
They are used in an olcDatabase entry in addition to the generic
database directives defined above. For a complete reference
-of BDB/HDB configuration directives, see {{slapd-bdb}}(5). In
-addition to the {{EX:olcDatabaseConfig}} objectClass, BDB and HDB
-database entries must have the {{EX:olcBdbConfig}} and
-{{EX:olcHdbConfig}} objectClass, respectively.
+of MDB configuration directives, see {{slapd-mdb}}(5). In
+addition to the {{EX:olcDatabaseConfig}} objectClass, MDB
+database entries must have the {{EX:olcMdbConfig}} objectClass.
H4: olcDbDirectory: <directory>
-This directive specifies the directory where the BDB files
+This directive specifies the directory where the MDB files
containing the database and associated indices live.
\Default:
> olcDbDirectory: /usr/local/var/openldap-data
-H4: olcDbCachesize: <integer>
-
-This directive specifies the size in entries of the in-memory
-cache maintained by the BDB backend database instance.
-
-\Default:
-
-> olcDbCachesize: 1000
-
-
H4: olcDbCheckpoint: <kbyte> <min>
-This directive specifies how often to checkpoint the BDB transaction log.
-A checkpoint operation flushes the database buffers to disk and writes a
-checkpoint record in the log.
+This directive specifies the frequency for flushing the database disk
+buffers. This directive is only needed if the {{olcDbNoSync}} option is
+{{EX:TRUE}}.
The checkpoint will occur if either <kbyte> data has been written or
<min> minutes have passed since the last checkpoint. Both arguments default
to zero, in which case they are ignored. When the <min> argument is
non-zero, an internal task will run every <min> minutes to perform the
-checkpoint. See the Berkeley DB reference guide for more details.
+checkpoint. Note: currently the _kbyte_ setting is unimplemented.
\Example:
> olcDbCheckpoint: 1024 10
-H4: olcDbConfig: <DB_CONFIG setting>
+H4: olcDbEnvFlags: {nosync,nometasync,writemap,mapasync,nordahead}
-This attribute specifies a configuration directive to be placed in the
-{{EX:DB_CONFIG}} file of the database directory. At server startup time, if
-no such file exists yet, the {{EX:DB_CONFIG}} file will be created and the
-settings in this attribute will be written to it. If the file exists,
-its contents will be read and displayed in this attribute. The attribute
-is multi-valued, to accommodate multiple configuration directives. No default
-is provided, but it is essential to use proper settings here to get the
-best server performance.
+This option specifies flags for finer-grained control of the LMDB library's
+operation.
-Any changes made to this attribute will be written to the {{EX:DB_CONFIG}}
-file and will cause the database environment to be reset so the changes
-can take immediate effect. If the environment cache is large and has not
-been recently checkpointed, this reset operation may take a long time. It
-may be advisable to manually perform a single checkpoint using the Berkeley DB
-{{db_checkpoint}} utility before using LDAP Modify to change this
-attribute.
+* {{F:nosync}}: This is exactly the same as the dbnosync directive.
-\Example:
+* {{F:nometasync}}: Flush the data on a commit, but skip the sync of the meta
+page. This mode is slightly faster than doing a full sync, but can
+potentially lose the last committed transaction if the operating system
+crashes. If both nometasync and nosync are set, the nosync flag takes
+precedence.
-> olcDbConfig: set_cachesize 0 10485760 0
-> olcDbConfig: set_lg_bsize 2097512
-> olcDbConfig: set_lg_dir /var/tmp/bdb-log
-> olcDbConfig: set_flags DB_LOG_AUTOREMOVE
-
-In this example, the BDB cache is set to 10MB, the BDB transaction log
-buffer size is set to 2MB, and the transaction log files are to be stored
-in the /var/tmp/bdb-log directory. Also a flag is set to tell BDB to
-delete transaction log files as soon as their contents have been
-checkpointed and they are no longer needed. Without this setting the
-transaction log files will continue to accumulate until some other
-cleanup procedure removes them. See the Berkeley DB documentation for the
-{{EX:db_archive}} command for details. For a complete list of Berkeley DB
-flags please see - {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/api_c/env_set_flags.html}}
-
-Ideally the BDB cache must be
-at least as large as the working set of the database, the log buffer size
-should be large enough to accommodate most transactions without overflowing,
-and the log directory must be on a separate physical disk from the main
-database files. And both the database directory and the log directory
-should be separate from disks used for regular system activities such as
-the root, boot, or swap filesystems. See the FAQ-o-Matic and the Berkeley DB
-documentation for more details.
+* {{F:writemap}}: Use a writable memory map instead of just read-only. This
+speeds up write operations but makes the database vulnerable to corruption in
+case any bugs in slapd cause stray writes into the mmap region.
+* {{F:mapasync}}: When using a writable memory map and performing flushes on
+each commit, use an asynchronous flush instead of a synchronous flush (the
+default). This option has no effect if writemap has not been set. It also has
+no effect if nosync is set.
-H4: olcDbNosync: { TRUE | FALSE }
-
-This option causes on-disk database contents to not be immediately
-synchronized with in memory changes upon change. Setting this option
-to {{EX:TRUE}} may improve performance at the expense of data integrity. This
-directive has the same effect as using
-> olcDbConfig: set_flags DB_TXN_NOSYNC
-
-
-H4: olcDbIDLcacheSize: <integer>
-
-Specify the size of the in-memory index cache, in index slots. The
-default is zero. A larger value will speed up frequent searches of
-indexed entries. The optimal size will depend on the data and search
-characteristics of the database, but using a number three times
-the entry cache size is a good starting point.
-
-\Example:
-
-> olcDbIDLcacheSize: 3000
+* {{F:nordahead}}: Turn off file readahead. Usually the OS performs readahead
+on every read request. This usually boosts read performance but can be
+harmful to random access read performance if the system's memory is full and
+the DB is larger than RAM. This option is not implemented on Windows.
H4: olcDbIndex: {<attrlist> | default} [pres,eq,approx,sub,none]
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.
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.
manually completed using the slapindex tool.
-H4: olcDbLinearIndex: { TRUE | FALSE }
+H4: olcDbMaxReaders: <integer>
+
+This directive specifies the maximum number of threads that may have
+concurrent read access to the database. Tools such as slapcat count as a
+single thread, in addition to threads in any active slapd processes. The
+default is 126.
+
-If this setting is {{EX:TRUE}} slapindex will index one attribute
-at a time. The default settings is {{EX:FALSE}} in which case all
-indexed attributes of an entry are processed at the same time. When
-enabled, each indexed attribute is processed individually, using
-multiple passes through the entire database. This option improves
-slapindex performance when the database size exceeds the BDB cache
-size. When the BDB cache is large enough, this option is not needed
-and will decrease performance. Also by default, slapadd performs
-full indexing and so a separate slapindex run is not needed. With
-this option, slapadd does no indexing and slapindex must be used.
+H4: olcDbMaxSize: <bytes>
+
+This directive specifies the maximum size of the database in bytes. A memory
+map of this size is allocated at startup time and the database will not be
+allowed to grow beyond this size. The default is 10485760 bytes (10MB). This
+setting may be changed upward if the configured limit needs to be increased.
+
+Note: It is important to set this to as large a value as possible, (relative
+to anticipated growth of the actual data over time) since growing the size
+later may not be practical when the system is under heavy load.
H4: olcDbMode: { <octal> | <symbolic> }
> olcDbMode: 0600
+H4: olcDbRtxnsize: <entries>
+
+This directive specifies the maximum number of entries to process in a single
+read transaction when executing a large search. Long-lived read transactions
+prevent old database pages from being reused in write transactions, and so
+can cause significant growth of the database file when there is heavy write
+traffic. This setting causes the read transaction in large searches to be
+released and reacquired after the given number of entries has been read, to
+give writers the opportunity to reclaim old database pages. The default is
+10000.
+
+
H4: olcDbSearchStack: <integer>
Specify the depth of the stack used for search filter evaluation.
> olcDbSearchStack: 16
-H4: olcDbShmKey: <integer>
-
-Specify a key for a shared memory BDB environment. By default the BDB
-environment uses memory mapped files. If a non-zero value is specified,
-it will be used as the key to identify a shared memory region that will
-house the environment.
-
-\Example:
+H4: olcDbNosync: { TRUE | FALSE }
-> olcDbShmKey: 42
+This directive causes on-disk database contents to not be immediately
+synchronized with in memory changes upon change. Setting this option
+to {{EX:TRUE}} may improve performance at the expense of data integrity.
H4: Sample Entry
->dn: olcDatabase=hdb,cn=config
+>dn: olcDatabase=mdb,cn=config
>objectClass: olcDatabaseConfig
->objectClass: olcHdbConfig
->olcDatabase: hdb
+>objectClass: olcMdbConfig
+>olcDatabase: mdb
>olcSuffix: "dc=example,dc=com"
>olcDbDirectory: /usr/local/var/openldap-data
->olcDbCacheSize: 1000
->olcDbCheckpoint: 1024 10
->olcDbConfig: set_cachesize 0 10485760 0
->olcDbConfig: set_lg_bsize 2097152
->olcDbConfig: set_lg_dir /var/tmp/bdb-log
->olcDbConfig: set_flags DB_LOG_AUTOREMOVE
->olcDbIDLcacheSize: 3000
>olcDbIndex: objectClass eq
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:
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.
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
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
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
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
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
+Line 29 is a comment. Lines 30-33 identify this entry as a MDB database
configuration entry. Line 34 specifies the DN suffix
for queries to pass to this database. Line 35 specifies the directory
in which the database files will live.
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"
This directive grants access (specified by <accesslevel>) to a set
of entries and/or attributes (specified by <what>) by one or more
-requestors (specified by <who>). See the {{SECT:Access Control}} section of
+requestors (specified by <who>). See the {{SECT:Access Control}} section of
this guide for basic usage.
!if 0
!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
!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
\Example:
-> backend bdb
+> backend mdb
-This marks the beginning of a new {{TERM:BDB}} backend
+This marks the beginning of a new {{TERM:MDB}} backend
definition.
\Example:
-> database bdb
+> database mdb
-This marks the beginning of a new {{TERM:BDB}} database instance
+This marks the beginning of a new {{TERM:MDB}} database instance
declaration.
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
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.
> updateref ldap://master.example.net
-H3: BDB and HDB Database Directives
+H3: MDB Database Directives
-Directives in this category only apply to both the {{TERM:BDB}}
-and the {{TERM:HDB}} database.
-That is, they must follow a "database bdb" or "database hdb" line
-and come before any
-subsequent "backend" or "database" line. For a complete reference
-of BDB/HDB configuration directives, see {{slapd-bdb}}(5).
+Directives in this category only apply to the {{TERM:MDB}}
+database backend.
+That is, they must follow a "database mdb" line
+and come before any subsequent "backend" or "database" lines.
+For a complete reference of MDB configuration directives, see {{slapd-mdb}}(5).
H4: directory <directory>
-This directive specifies the directory where the BDB files
+This directive specifies the directory where the MDB files
containing the database and associated indices live.
\Default:
> directory /usr/local/var/openldap-data
+H4: checkpoint <kbyte> <min>
+
+This directive specifies the frequency for flushing the database disk
+buffers. This directive is only needed if the {{dbnosync}} option is
+{{EX:TRUE}}.
+The checkpoint will occur if either <kbyte> data has been written or
+<min> minutes have passed since the last checkpoint. Both arguments default
+to zero, in which case they are ignored. When the <min> argument is
+non-zero, an internal task will run every <min> minutes to perform the
+checkpoint. Note: currently the _kbyte_ setting is unimplemented.
+
+\Example:
+
+> checkpoint: 1024 10
+
+H4: dbnosync: { TRUE | FALSE }
+
+This directive causes on-disk database contents to not be immediately
+synchronized with in memory changes upon change. Setting this option
+to {{EX:TRUE}} may improve performance at the expense of data integrity.
+
+
+H4: envflags: {nosync,nometasync,writemap,mapasync,nordahead}
+
+This option specifies flags for finer-grained control of the LMDB library's
+operation.
+
+* {{F:nosync}}: This is exactly the same as the dbnosync directive.
+
+* {{F:nometasync}}: Flush the data on a commit, but skip the sync of the meta
+page. This mode is slightly faster than doing a full sync, but can
+potentially lose the last committed transaction if the operating system
+crashes. If both nometasync and nosync are set, the nosync flag takes
+precedence.
+
+* {{F:writemap}}: Use a writable memory map instead of just read-only. This
+speeds up write operations but makes the database vulnerable to corruption in
+case any bugs in slapd cause stray writes into the mmap region.
+
+* {{F:mapasync}}: When using a writable memory map and performing flushes on
+each commit, use an asynchronous flush instead of a synchronous flush (the
+default). This option has no effect if writemap has not been set. It also has
+no effect if nosync is set.
+
+* {{F:nordahead}}: Turn off file readahead. Usually the OS performs readahead
+on every read request. This usually boosts read performance but can be
+harmful to random access read performance if the system's memory is full and
+the DB is larger than RAM. This option is not implemented on Windows.
+
+
+H4: index: {<attrlist> | default} [pres,eq,approx,sub,none]
+
+This directive specifies the indices to maintain for the given
+attribute. If only an {{EX:<attrlist>}} is given, the default
+indices are maintained. The index keywords correspond to the
+common types of matches that may be used in an LDAP search filter.
+
+\Example:
+
+> index: default pres,eq
+> index: uid
+> index: cn,sn pres,eq,sub
+> index: objectClass eq
+
+The first line sets the default set of indices to maintain to
+present and equality. The second line causes the default (pres,eq)
+set of indices to be maintained for the {{EX:uid}} attribute type.
+The third line causes present, equality, and substring indices to
+be maintained for {{EX:cn}} and {{EX:sn}} attribute types. The
+fourth line causes an equality index for the {{EX:objectClass}}
+attribute type.
+
+There is no index keyword for inequality matches. Generally these
+matches do not use an index. However, some attributes do support
+indexing for inequality matches, based on the equality index.
+
+A substring index can be more explicitly specified as {{EX:subinitial}},
+{{EX:subany}}, or {{EX:subfinal}}, corresponding to the three
+possible components
+of a substring match filter. A subinitial index only indexes
+substrings that appear at the beginning of an attribute value.
+A subfinal index only indexes substrings that appear at the end
+of an attribute value, while subany indexes substrings that occur
+anywhere in a value.
+
+Note that by default, setting an index for an attribute also
+affects every subtype of that attribute. E.g., setting an equality
+index on the {{EX:name}} attribute causes {{EX:cn}}, {{EX:sn}}, and every other
+attribute that inherits from {{EX:name}} to be indexed.
+
+By default, no indices are maintained. It is generally advised
+that minimally an equality index upon objectClass be maintained.
+
+> index: objectClass eq
+
+Additional indices should be configured corresponding to the
+most common searches that are used on the database.
+Presence indexing should not be configured for an attribute
+unless the attribute occurs very rarely in the database, and
+presence searches on the attribute occur very frequently during
+normal use of the directory. Most applications don't use presence
+searches, so usually presence indexing is not very useful.
+
+
+H4: maxreaders: <integer>
+
+This directive specifies the maximum number of threads that may have
+concurrent read access to the database. Tools such as slapcat count as a
+single thread, in addition to threads in any active slapd processes. The
+default is 126.
+
+
+H4: maxsize: <bytes>
+
+This directive specifies the maximum size of the database in bytes. A memory
+map of this size is allocated at startup time and the database will not be
+allowed to grow beyond this size. The default is 10485760 bytes (10MB). This
+setting may be changed upward if the configured limit needs to be increased.
+
+Note: It is important to set this to as large a value as possible, (relative
+to anticipated growth of the actual data over time) since growing the size
+later may not be practical when the system is under heavy load.
+
+
+H4: mode: { <octal> | <symbolic> }
+
+This directive specifies the file protection mode that newly
+created database index files should have. This can be in the form
+{{EX:0600}} or {{EX:-rw-------}}
+
+\Default:
+
+> mode: 0600
+
+
+H4: rtxnsize: <entries>
+
+This directive specifies the maximum number of entries to process in a single
+read transaction when executing a large search. Long-lived read transactions
+prevent old database pages from being reused in write transactions, and so
+can cause significant growth of the database file when there is heavy write
+traffic. This setting causes the read transaction in large searches to be
+released and reacquired after the given number of entries has been read, to
+give writers the opportunity to reclaim old database pages. The default is
+10000.
+
+
+H4: searchstack: <integer>
+
+Specify the depth of the stack used for search filter evaluation.
+Search filters are evaluated on a stack to accommodate nested {{EX:AND}} /
+{{EX:OR}} clauses. An individual stack is allocated for each server thread.
+The depth of the stack determines how complex a filter can be evaluated
+without requiring any additional memory allocation. Filters that are
+nested deeper than the search stack depth will cause a separate stack to
+be allocated for that particular search operation. These separate allocations
+can have a major negative impact on server performance, but specifying
+too much stack will also consume a great deal of memory. Each search
+uses 512K bytes per level on a 32-bit machine, or 1024K bytes per level
+on a 64-bit machine. The default stack depth is 16, thus 8MB or 16MB
+per thread is used on 32 and 64 bit machines, respectively. Also the
+512KB size of a single stack slot is set by a compile-time constant which
+may be changed if needed; the code must be recompiled for the change
+to take effect.
+
+\Default:
+
+> searchstack: 16
+
+
+H4: Sample Entry
+
+>database mdb
+>suffix: "dc=example,dc=com"
+>directory: /usr/local/var/openldap-data
+>index: objectClass eq
+
H2: Configuration File Example
The following is an example configuration file, interspersed
with explanatory text. It defines two databases to handle
-different parts of the {{TERM:X.500}} tree; both are {{TERM:BDB}}
+different parts of the {{TERM:X.500}} tree; both are {{TERM:MDB}}
database instances. The line numbers shown are provided for
reference only and are not included in the actual file. First, the
global configuration section:
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
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
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"
entry, but may be read by all users (authenticated or not).
The next section of the example configuration file 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 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"
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
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
The most common message you'll see that you should pay attention to is:
-> "<= bdb_equality_candidates: (foo) index_param failed (18)"
+> "<= mdb_equality_candidates: (foo) index_param failed (18)"
That means that some application tried to use an equality filter ({{foo=<somevalue>}})
and attribute {{foo}} does not have an equality index. If you see a lot of these
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
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
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
+ 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
+++ /dev/null
-.TH SLAPD-BDB 5 "RELEASEDATE" "OpenLDAP LDVERSION"
-.\" Copyright 1998-2019 The OpenLDAP Foundation All Rights Reserved.
-.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
-.\" $OpenLDAP$
-.SH NAME
-slapd\-bdb, slapd\-hdb \- Berkeley DB backends to slapd
-.SH SYNOPSIS
-.B ETCDIR/slapd.conf
-.SH DESCRIPTION
-The \fBbdb\fP backend to
-.BR slapd (8)
-uses the Oracle Berkeley DB (BDB) package to store data.
-It makes extensive use of indexing and caching to speed data access.
-.LP
-Note that BDB is deprecated and support will be dropped in future
-OpenLDAP releases. Installations should use the \fBmdb\fP
-backend instead.
-.LP
-\fBhdb\fP is a variant of
-the \fBbdb\fP backend that uses a hierarchical database layout which
-supports subtree renames. It is both more space-efficient and more
-execution-efficient than the \fBbdb\fP backend. It is otherwise identical
-to the \fBbdb\fP behavior, and all the same configuration options apply.
-.LP
-It is noted that these options are intended to complement
-Berkeley DB configuration options set in the environment's
-.B DB_CONFIG
-file. See Berkeley DB documentation for details on
-.B DB_CONFIG
-configuration options.
-Where there is overlap, settings in
-.B DB_CONFIG
-take precedence.
-.SH CONFIGURATION
-These
-.B slapd.conf
-options apply to the \fBbdb\fP and \fBhdb\fP backend database.
-That is, they must follow a "database bdb" or "database hdb" line and
-come before any subsequent "backend" or "database" lines.
-Other database options are described in the
-.BR slapd.conf (5)
-manual page.
-.TP
-.BI cachesize \ <integer>
-Specify the size in entries of the in-memory entry cache maintained
-by the \fBbdb\fP or \fBhdb\fP backend database instance.
-The default is 1000 entries.
-.TP
-.BI cachefree \ <integer>
-Specify the number of entries to free from the entry cache when the
-cache reaches the \fBcachesize\fP limit.
-The default is 1 entry.
-.TP
-.BI checkpoint \ <kbyte>\ <min>
-Specify the frequency for checkpointing the database transaction log.
-A checkpoint operation flushes the database buffers to disk and writes
-a checkpoint record in the log.
-The checkpoint will occur if either \fI<kbyte>\fP data has been written or
-\fI<min>\fP minutes have passed since the last checkpoint.
-Both arguments default to zero, in which case they are ignored. When
-the \fI<min>\fP argument is non-zero, an internal task will run every
-\fI<min>\fP minutes to perform the checkpoint.
-See the Berkeley DB reference guide for more details.
-.TP
-.B checksum
-Enable checksum validation of DB pages whenever they are read from disk.
-This setting can only be configured before any database files are created.
-.TP
-.BI cryptfile \ <file>
-Specify the pathname of a file containing an encryption key to use for
-encrypting the database. Encryption is performed using Berkeley DB's
-implementation of AES. Note that encryption can only be configured before
-any database files are created, and changing the key can only be done
-after destroying the current database and recreating it. Encryption is
-not enabled by default, and some distributions of Berkeley DB do not
-support encryption.
-.TP
-.BI cryptkey \ <key>
-Specify an encryption key to use for encrypting the database. This option
-may be used when a separate
-.I cryptfile
-is not desired. Only one of
-.B cryptkey
-or
-.B cryptfile
-may be configured.
-.TP
-.BI dbconfig \ <Berkeley-DB-setting>
-Specify a configuration directive to be placed in the
-.B DB_CONFIG
-file of the database directory. The
-.B dbconfig
-directive is just a convenience
-to allow all necessary configuration to be set in the
-.B slapd.conf
-file.
-The options set using this directive will only be written to the
-.B DB_CONFIG
-file if no such file existed at server startup time, otherwise
-they are completely ignored. This allows one
-to set initial values without overwriting/destroying a
-.B DB_CONFIG
-file that was already customized through other means.
-This directive may be specified multiple times, as needed.
-For example:
-.RS
-.nf
- dbconfig set_cachesize 0 1048576 0
- dbconfig set_lg_bsize 2097152
-.fi
-.RE
-.TP
-.B dbnosync
-Specify that on-disk database contents should not be immediately
-synchronized with in memory changes.
-Enabling this option may improve performance at the expense of data
-security.
-See the Berkeley DB reference guide for more details.
-.TP
-\fBdbpagesize \fR \fI<dbfile> <size>\fR
-Specify the page size to use for a particular database file, in units
-of 1024 bytes. The default for the
-.B id2entry
-file is 16, the default for all other files depends on the size of the
-underlying filesystem's block size (typically 4 or 8).
-The maximum that BerkeleyDB supports is 64. This
-setting usually should not need to be changed, but if BerkeleyDB's
-"db_stat \-d" shows a large amount of overflow pages in use in a file,
-setting a larger size may increase performance at the expense of
-data integrity. This setting only takes effect when a database is
-being newly created. See the Berkeley DB reference guide for more details.
-.TP
-.BI directory \ <directory>
-Specify the directory where the BDB files containing this database and
-associated indexes live.
-A separate directory must be specified for each database.
-The default is
-.BR LOCALSTATEDIR/openldap\-data .
-.TP
-.B dirtyread
-Allow reads of modified but not yet committed data.
-Usually transactions are isolated to prevent other operations from
-accessing uncommitted data.
-This option may improve performance, but may also return inconsistent
-results if the data comes from a transaction that is later aborted.
-In this case, the modified data is discarded and a subsequent search
-will return a different result.
-.TP
-.BI dncachesize \ <integer>
-Specify the maximum number of DNs in the in-memory DN cache.
-Ideally this cache should be
-large enough to contain the DNs of every entry in the database. If
-set to a smaller value than the \fBcachesize\fP it will be silently
-increased to equal the \fBcachesize\fP. The default value is 0 which
-means unlimited, i.e. the DN cache will grow without bound.
-
-It should be noted that the \fBDN cache\fP is allowed to temporarily
-grow beyond the configured size. It does this if many entries are
-locked when it tries to do a purge, because that means they're
-legitimately in use. Also, the \fBDN cache\fP never purges entries
-that have cached children, so depending on the shape of the DIT, it
-could have lots of cached DNs over the defined limit.
-.TP
-.BI idlcachesize \ <integer>
-Specify the size of the in-memory index cache, in index slots. The
-default is zero. A larger value will speed up frequent searches of
-indexed entries. An \fBhdb\fP database needs a large \fBidlcachesize\fP
-for good search performance, typically three times the
-.B cachesize
-(entry cache size)
-or larger.
-.TP
-\fBindex \fR{\fI<attrlist>\fR|\fBdefault\fR} [\fBpres\fR,\fBeq\fR,\fBapprox\fR,\fBsub\fR,\fI<special>\fR]
-Specify the indexes to maintain for the given attribute (or
-list of attributes).
-Some attributes only support a subset of indexes.
-If only an \fI<attr>\fP is given, the indices specified for \fBdefault\fR
-are maintained.
-Note that setting a default does not imply that all attributes will be
-indexed. Also, for best performance, an
-.B eq
-index should always be configured for the
-.B objectClass
-attribute.
-
-A number of special index parameters may be specified.
-The index type
-.B sub
-can be decomposed into
-.BR subinitial ,
-.BR subany ,\ and
-.B subfinal
-indices.
-The special type
-.B nolang
-may be specified to disallow use of this index by language subtypes.
-The special type
-.B nosubtypes
-may be specified to disallow use of this index by named subtypes.
-Note: changing \fBindex\fP settings in
-.BR slapd.conf (5)
-requires rebuilding indices, see
-.BR slapindex (8);
-changing \fBindex\fP settings
-dynamically by LDAPModifying "cn=config" automatically causes rebuilding
-of the indices online in a background task.
-.TP
-.B linearindex
-Tell
-.B slapindex
-to index one attribute at a time. By default, all indexed
-attributes in an entry are processed at the same time. With this option,
-each indexed attribute is processed individually, using multiple passes
-through the entire database. This option improves
-.B slapindex
-performance
-when the database size exceeds the \fBdbcache\fP size. When the \fBdbcache\fP is
-large enough, this option is not needed and will decrease performance.
-Also by default,
-.B slapadd
-performs full indexing and so a separate
-.B slapindex
-run is not needed. With this option,
-.B slapadd
-does no indexing and
-.B slapindex
-must be used.
-.TP
-.BR lockdetect \ { oldest | youngest | fewest | random | default }
-Specify which transaction to abort when a deadlock is detected.
-The default is
-.BR random .
-.TP
-.BI mode \ <integer>
-Specify the file protection mode that newly created database
-index files should have.
-The default is 0600.
-.TP
-.BI searchstack \ <depth>
-Specify the depth of the stack used for search filter evaluation.
-Search filters are evaluated on a stack to accommodate nested AND / OR
-clauses. An individual stack is assigned to each server thread.
-The depth of the stack determines how complex a filter can be
-evaluated without requiring any additional memory allocation. Filters that
-are nested deeper than the search stack depth will cause a separate
-stack to be allocated for that particular search operation. These
-allocations can have a major negative impact on server performance,
-but specifying too much stack will also consume a great deal of memory.
-Each search stack uses 512K bytes per level. The default stack depth
-is 16, thus 8MB per thread is used.
-.TP
-.BI shm_key \ <integer>
-Specify a key for a shared memory BDB environment. By default the
-BDB environment uses memory mapped files. If a non-zero value is
-specified, it will be used as the key to identify a shared memory
-region that will house the environment.
-.SH ACCESS CONTROL
-The
-.B bdb
-and
-.B hdb
-backends honor access control semantics as indicated in
-.BR slapd.access (5).
-.SH FILES
-.TP
-.B ETCDIR/slapd.conf
-default
-.B slapd
-configuration file
-.TP
-.B DB_CONFIG
-Berkeley DB configuration file
-.SH SEE ALSO
-.BR slapd.conf (5),
-.BR slapd\-config (5),
-.BR slapd\-mdb (5),
-.BR slapd (8),
-.BR slapadd (8),
-.BR slapcat (8),
-.BR slapindex (8),
-Berkeley DB documentation.
-.SH ACKNOWLEDGEMENTS
-.so ../Project
-Originally begun by Kurt Zeilenga. Caching mechanisms originally designed
-by Jong-Hyuk Choi. Completion and subsequent work, as well as
-back-hdb, by Howard Chu.
+++ /dev/null
-slapd-hdb.5
and must have the olcBackendConfig objectClass.
<databasetype>
should be one of
-.BR bdb ,
.BR config ,
.BR dnssrv ,
-.BR hdb ,
.BR ldap ,
.BR ldif ,
.BR mdb ,
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
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
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 LMDB (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
.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
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),
.BR slapd\-<backend> (5)
manual pages.
.TP
-.B bdb
-This was the recommended primary backend through OpenLDAP 2.3, but it has
-since been superseded by the
-.BR mdb
-backend. It takes care to configure it properly.
-It uses the transactional database interface of the Oracle Berkeley
-DB (BDB) package to store data.
-.TP
.B config
This backend is used to manage the configuration of slapd at run-time.
Unlike other backends, only a single instance of the
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.
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
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),
.B backend <databasetype>
Mark the beginning of a backend definition. <databasetype>
should be one of
-.BR bdb ,
.BR config ,
.BR dnssrv ,
-.BR hdb ,
.BR ldap ,
.BR ldif ,
.BR mdb ,
.B database <databasetype>
Mark the beginning of a new database instance definition. <databasetype>
should be one of
-.BR bdb ,
.BR config ,
.BR dnssrv ,
-.BR hdb ,
.BR ldap ,
.BR ldif ,
.BR mdb ,
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 database provides database-specific monitoring.
The default depends on the backend type.
.TP
.B overlay <overlay-name>
.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
.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.
.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
ETCDIR/slapd.conf
.SH DESCRIPTION
The Referential Integrity 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.
.LP
Integrity is maintained by updating database records which contain the named
ETCDIR/slapd.conf
.SH DESCRIPTION
The Translucent Proxy overlay can be used with a backend database such as
-.BR slapd\-bdb (5)
+.BR slapd\-mdb (5)
to create a "translucent proxy". Entries retrieved from a remote LDAP
server may have some or all attributes overridden, or new attributes
added, by entries in the local database before being presented to the
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)
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.
/* Define to 1 if you have the `bcopy' function. */
#undef HAVE_BCOPY
-/* define this if Berkeley DB is available */
-#undef HAVE_BERKELEY_DB
-
-/* define if Berkeley DB has DB_THREAD support */
-#undef HAVE_BERKELEY_DB_THREAD
-
/* Define to 1 if you have the <bits/types.h> header file. */
#undef HAVE_BITS_TYPES_H
/* define to support LDAP Async Metadirectory backend */
#undef SLAPD_ASYNCMETA
-/* define to support BDB backend */
-#undef SLAPD_BDB
-
/* define to support cleartext passwords */
#undef SLAPD_CLEARTEXT
/* 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
+++ /dev/null
-# $OpenLDAP$
-# Example DB_CONFIG file for use with slapd(8) BDB/HDB databases.
-#
-# See the Oracle Berkeley DB documentation
-# <http://www.oracle.com/technology/documentation/berkeley-db/db/ref/env/db_config.html>
-# for detail description of DB_CONFIG syntax and semantics.
-#
-# Hints can also be found in the OpenLDAP Software FAQ
-# <http://www.openldap.org/faq/index.cgi?file=2>
-# in particular:
-# <http://www.openldap.org/faq/index.cgi?file=1075>
-
-# Note: most DB_CONFIG settings will take effect only upon rebuilding
-# the DB environment.
-
-# one 0.25 GB cache
-set_cachesize 0 268435456 1
-
-# Data Directory
-#set_data_dir db
-
-# Transaction Log settings
-set_lg_regionmax 262144
-set_lg_bsize 2097152
-#set_lg_dir logs
-
-# Note: special DB_CONFIG flags are no longer needed for "quick"
-# slapadd(8) or slapindex(8) access (see their -q option).
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 slapmodify.c \
+ aci.c txn.c slapschema.c slapmodify.c \
$(@PLAT@_SRCS)
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 slapmodify.o \
+ aci.o txn.o slapschema.o slapmodify.o \
$(@PLAT@_OBJS)
LDAP_INCDIR= ../../include -I$(srcdir) -I$(srcdir)/slapi -I.
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)
+++ /dev/null
-/* alock.c - access lock library */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2005-2019 The OpenLDAP Foundation.
- * Portions Copyright 2004-2005 Symas Corporation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was initially developed by Emily Backes at Symas
- * Corporation for inclusion in OpenLDAP Software.
- */
-
-#include "portable.h"
-
-#if SLAPD_BDB || SLAPD_HDB
-
-#include <lber.h>
-#include "alock.h"
-#include "lutil.h"
-
-#include <ac/stdlib.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-#include <ac/errno.h>
-#include <ac/assert.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#ifdef HAVE_SYS_FILE_H
-#include <sys/file.h>
-#endif
-#include <fcntl.h>
-
-#ifdef _WIN32
-#include <windows.h>
-#include <stdio.h>
-#include <io.h>
-#endif
-
-
-static int
-alock_grab_lock ( int fd, int slot )
-{
- int res;
-
-#if defined( HAVE_LOCKF )
- res = lseek (fd, (off_t) (ALOCK_SLOT_SIZE * slot), SEEK_SET);
- if (res == -1) return -1;
- res = lockf (fd, F_LOCK, (off_t) ALOCK_SLOT_SIZE);
-#elif defined( HAVE_FCNTL )
- struct flock lock_info;
- (void) memset ((void *) &lock_info, 0, sizeof (struct flock));
-
- lock_info.l_type = F_WRLCK;
- lock_info.l_whence = SEEK_SET;
- lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
- lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
-
- res = fcntl (fd, F_SETLKW, &lock_info);
-#elif defined( _WIN32 )
- OVERLAPPED ov;
- HANDLE hh = _get_osfhandle ( fd );
- ov.hEvent = 0;
- ov.Offset = ALOCK_SLOT_SIZE*slot;
- ov.OffsetHigh = 0;
- res = LockFileEx( hh, LOCKFILE_EXCLUSIVE_LOCK, 0,
- ALOCK_SLOT_SIZE, 0, &ov ) ? 0 : -1;
-#else
-# error alock needs lockf, fcntl, or LockFile[Ex]
-#endif
- if (res == -1) {
- assert (errno != EDEADLK);
- return -1;
- }
- return 0;
-}
-
-static int
-alock_release_lock ( int fd, int slot )
-{
- int res;
-
-#if defined( HAVE_LOCKF )
- res = lseek (fd, (off_t) (ALOCK_SLOT_SIZE * slot), SEEK_SET);
- if (res == -1) return -1;
- res = lockf (fd, F_ULOCK, (off_t) ALOCK_SLOT_SIZE);
- if (res == -1) return -1;
-#elif defined ( HAVE_FCNTL )
- struct flock lock_info;
- (void) memset ((void *) &lock_info, 0, sizeof (struct flock));
-
- lock_info.l_type = F_UNLCK;
- lock_info.l_whence = SEEK_SET;
- lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
- lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
-
- res = fcntl (fd, F_SETLKW, &lock_info);
- if (res == -1) return -1;
-#elif defined( _WIN32 )
- HANDLE hh = _get_osfhandle ( fd );
- if ( !UnlockFile ( hh, ALOCK_SLOT_SIZE*slot, 0,
- ALOCK_SLOT_SIZE, 0 ))
- return -1;
-#else
-# error alock needs lockf, fcntl, or LockFile[Ex]
-#endif
-
- return 0;
-}
-
-static int
-alock_share_lock ( int fd, int slot )
-{
- int res;
-
-#if defined( HAVE_LOCKF )
- res = 0; /* lockf has no shared locks */
-#elif defined ( HAVE_FCNTL )
- struct flock lock_info;
- (void) memset ((void *) &lock_info, 0, sizeof (struct flock));
-
- /* The shared lock replaces the existing lock */
- lock_info.l_type = F_RDLCK;
- lock_info.l_whence = SEEK_SET;
- lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
- lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
-
- res = fcntl (fd, F_SETLK, &lock_info);
- if (res == -1) return -1;
-#elif defined( _WIN32 )
- OVERLAPPED ov;
- HANDLE hh = _get_osfhandle ( fd );
-
- /* Windows locks are mandatory, not advisory.
- * We must downgrade the lock to allow future
- * callers to read the slot data.
- *
- * First acquire a shared lock. Unlock will
- * release the existing exclusive lock.
- */
- ov.hEvent = 0;
- ov.Offset = ALOCK_SLOT_SIZE*slot;
- ov.OffsetHigh = 0;
- LockFileEx (hh, 0, 0, ALOCK_SLOT_SIZE, 0, &ov);
- UnlockFile (hh, ALOCK_SLOT_SIZE*slot, 0, ALOCK_SLOT_SIZE, 0);
-#else
-# error alock needs lockf, fcntl, or LockFile[Ex]
-#endif
-
- return 0;
-}
-
-static int
-alock_test_lock ( int fd, int slot )
-{
- int res;
-
-#if defined( HAVE_LOCKF )
- res = lseek (fd, (off_t) (ALOCK_SLOT_SIZE * slot), SEEK_SET);
- if (res == -1) return -1;
-
- res = lockf (fd, F_TEST, (off_t) ALOCK_SLOT_SIZE);
- if (res == -1) {
- if (errno == EACCES || errno == EAGAIN) {
- return ALOCK_LOCKED;
- } else {
- return -1;
- }
- }
-#elif defined( HAVE_FCNTL )
- struct flock lock_info;
- (void) memset ((void *) &lock_info, 0, sizeof (struct flock));
-
- lock_info.l_type = F_WRLCK;
- lock_info.l_whence = SEEK_SET;
- lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
- lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
-
- res = fcntl (fd, F_GETLK, &lock_info);
- if (res == -1) return -1;
-
- if (lock_info.l_type != F_UNLCK) return ALOCK_LOCKED;
-#elif defined( _WIN32 )
- OVERLAPPED ov;
- HANDLE hh = _get_osfhandle ( fd );
- ov.hEvent = 0;
- ov.Offset = ALOCK_SLOT_SIZE*slot;
- ov.OffsetHigh = 0;
- if( !LockFileEx( hh,
- LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY, 0,
- ALOCK_SLOT_SIZE, 0, &ov )) {
- int err = GetLastError();
- if ( err == ERROR_LOCK_VIOLATION )
- return ALOCK_LOCKED;
- else
- return -1;
- }
-#else
-# error alock needs lockf, fcntl, or LockFile
-#endif
-
- return 0;
-}
-
-/* Read a 64bit LE value */
-static unsigned long int
-alock_read_iattr ( unsigned char * bufptr )
-{
- unsigned long int val = 0;
- int count;
-
- assert (bufptr != NULL);
-
- bufptr += sizeof (unsigned long int);
- for (count=0; count <= (int) sizeof (unsigned long int); ++count) {
- val <<= 8;
- val += (unsigned long int) *bufptr--;
- }
-
- return val;
-}
-
-/* Write a 64bit LE value */
-static void
-alock_write_iattr ( unsigned char * bufptr,
- unsigned long int val )
-{
- int count;
-
- assert (bufptr != NULL);
-
- for (count=0; count < 8; ++count) {
- *bufptr++ = (unsigned char) (val & 0xff);
- val >>= 8;
- }
-}
-
-static int
-alock_read_slot ( alock_info_t * info,
- alock_slot_t * slot_data )
-{
- unsigned char slotbuf [ALOCK_SLOT_SIZE];
- int res, size, size_total, err;
-
- assert (info != NULL);
- assert (slot_data != NULL);
- assert (info->al_slot > 0);
-
- res = lseek (info->al_fd,
- (off_t) (ALOCK_SLOT_SIZE * info->al_slot),
- SEEK_SET);
- if (res == -1) return -1;
-
- size_total = 0;
- while (size_total < ALOCK_SLOT_SIZE) {
- size = read (info->al_fd,
- slotbuf + size_total,
- ALOCK_SLOT_SIZE - size_total);
- if (size == 0) return -1;
- if (size < 0) {
- err = errno;
- if (err != EINTR && err != EAGAIN) return -1;
- } else {
- size_total += size;
- }
- }
-
- if (alock_read_iattr (slotbuf) != ALOCK_MAGIC) {
- return -1;
- }
- slot_data->al_lock = alock_read_iattr (slotbuf+8);
- slot_data->al_stamp = alock_read_iattr (slotbuf+16);
- slot_data->al_pid = alock_read_iattr (slotbuf+24);
-
- if (slot_data->al_appname) ber_memfree (slot_data->al_appname);
- slot_data->al_appname = ber_memcalloc (1, ALOCK_MAX_APPNAME);
- if (slot_data->al_appname == NULL) {
- return -1;
- }
- strncpy (slot_data->al_appname, (char *)slotbuf+32, ALOCK_MAX_APPNAME-1);
- (slot_data->al_appname) [ALOCK_MAX_APPNAME-1] = '\0';
-
- return 0;
-}
-
-static int
-alock_write_slot ( alock_info_t * info,
- alock_slot_t * slot_data )
-{
- unsigned char slotbuf [ALOCK_SLOT_SIZE];
- int res, size, size_total, err;
-
- assert (info != NULL);
- assert (slot_data != NULL);
- assert (info->al_slot > 0);
-
- (void) memset ((void *) slotbuf, 0, ALOCK_SLOT_SIZE);
-
- alock_write_iattr (slotbuf, ALOCK_MAGIC);
- assert (alock_read_iattr (slotbuf) == ALOCK_MAGIC);
- alock_write_iattr (slotbuf+8, slot_data->al_lock);
- alock_write_iattr (slotbuf+16, slot_data->al_stamp);
- alock_write_iattr (slotbuf+24, slot_data->al_pid);
-
- if (slot_data->al_appname)
- strncpy ((char *)slotbuf+32, slot_data->al_appname, ALOCK_MAX_APPNAME-1);
- slotbuf[ALOCK_SLOT_SIZE-1] = '\0';
-
- res = lseek (info->al_fd,
- (off_t) (ALOCK_SLOT_SIZE * info->al_slot),
- SEEK_SET);
- if (res == -1) return -1;
-
- size_total = 0;
- while (size_total < ALOCK_SLOT_SIZE) {
- size = write (info->al_fd,
- slotbuf + size_total,
- ALOCK_SLOT_SIZE - size_total);
- if (size == 0) return -1;
- if (size < 0) {
- err = errno;
- if (err != EINTR && err != EAGAIN) return -1;
- } else {
- size_total += size;
- }
- }
-
- return 0;
-}
-
-static int
-alock_query_slot ( alock_info_t * info )
-{
- int res, nosave;
- alock_slot_t slot_data;
-
- assert (info != NULL);
- assert (info->al_slot > 0);
-
- (void) memset ((void *) &slot_data, 0, sizeof (alock_slot_t));
- alock_read_slot (info, &slot_data);
-
- if (slot_data.al_appname != NULL) ber_memfree (slot_data.al_appname);
- slot_data.al_appname = NULL;
-
- nosave = slot_data.al_lock & ALOCK_NOSAVE;
-
- if ((slot_data.al_lock & ALOCK_SMASK) == ALOCK_UNLOCKED)
- return slot_data.al_lock;
-
- res = alock_test_lock (info->al_fd, info->al_slot);
- if (res < 0) return -1;
- if (res > 0) {
- if ((slot_data.al_lock & ALOCK_SMASK) == ALOCK_UNIQUE) {
- return slot_data.al_lock;
- } else {
- return ALOCK_LOCKED | nosave;
- }
- }
-
- return ALOCK_DIRTY | nosave;
-}
-
-int
-alock_open ( alock_info_t * info,
- const char * appname,
- const char * envdir,
- int locktype )
-{
- struct stat statbuf;
- alock_info_t scan_info;
- alock_slot_t slot_data;
- char * filename;
- int res, max_slot;
- int dirty_count, live_count, nosave;
- char *ptr;
-
- assert (info != NULL);
- assert (appname != NULL);
- assert (envdir != NULL);
- assert ((locktype & ALOCK_SMASK) >= 1 && (locktype & ALOCK_SMASK) <= 2);
-
- slot_data.al_lock = locktype;
- slot_data.al_stamp = time(NULL);
- slot_data.al_pid = getpid();
- slot_data.al_appname = ber_memcalloc (1, ALOCK_MAX_APPNAME);
- if (slot_data.al_appname == NULL) {
- return ALOCK_UNSTABLE;
- }
- strncpy (slot_data.al_appname, appname, ALOCK_MAX_APPNAME-1);
- slot_data.al_appname [ALOCK_MAX_APPNAME-1] = '\0';
-
- filename = ber_memcalloc (1, strlen (envdir) + strlen ("/alock") + 1);
- if (filename == NULL ) {
- ber_memfree (slot_data.al_appname);
- return ALOCK_UNSTABLE;
- }
- ptr = lutil_strcopy(filename, envdir);
- lutil_strcopy(ptr, "/alock");
-#ifdef _WIN32
- { HANDLE handle = CreateFile (filename, GENERIC_READ|GENERIC_WRITE,
- FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,
- FILE_ATTRIBUTE_NORMAL, NULL);
- info->al_fd = _open_osfhandle (handle, 0);
- }
-#else
- info->al_fd = open (filename, O_CREAT|O_RDWR, 0666);
-#endif
- ber_memfree (filename);
- if (info->al_fd < 0) {
- ber_memfree (slot_data.al_appname);
- return ALOCK_UNSTABLE;
- }
- info->al_slot = 0;
-
- res = alock_grab_lock (info->al_fd, 0);
- if (res == -1) {
- close (info->al_fd);
- ber_memfree (slot_data.al_appname);
- return ALOCK_UNSTABLE;
- }
-
- res = fstat (info->al_fd, &statbuf);
- if (res == -1) {
- close (info->al_fd);
- ber_memfree (slot_data.al_appname);
- return ALOCK_UNSTABLE;
- }
-
- max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE;
- dirty_count = 0;
- live_count = 0;
- nosave = 0;
- scan_info.al_fd = info->al_fd;
- for (scan_info.al_slot = 1;
- scan_info.al_slot < max_slot;
- ++ scan_info.al_slot) {
- if (scan_info.al_slot != info->al_slot) {
- res = alock_query_slot (&scan_info);
-
- if (res & ALOCK_NOSAVE) {
- nosave = ALOCK_NOSAVE;
- res ^= ALOCK_NOSAVE;
- }
- if (res == ALOCK_UNLOCKED
- && info->al_slot == 0) {
- info->al_slot = scan_info.al_slot;
-
- } else if (res == ALOCK_LOCKED) {
- ++live_count;
-
- } else if (res == ALOCK_UNIQUE
- && (( locktype & ALOCK_SMASK ) == ALOCK_UNIQUE
- || nosave )) {
- close (info->al_fd);
- ber_memfree (slot_data.al_appname);
- return ALOCK_BUSY;
-
- } else if (res == ALOCK_DIRTY) {
- ++dirty_count;
-
- } else if (res == -1) {
- close (info->al_fd);
- ber_memfree (slot_data.al_appname);
- return ALOCK_UNSTABLE;
-
- }
- }
- }
-
- if (dirty_count && live_count) {
- close (info->al_fd);
- ber_memfree (slot_data.al_appname);
- return ALOCK_UNSTABLE;
- }
-
- if (info->al_slot == 0) info->al_slot = max_slot + 1;
- res = alock_grab_lock (info->al_fd,
- info->al_slot);
- if (res == -1) {
- close (info->al_fd);
- ber_memfree (slot_data.al_appname);
- return ALOCK_UNSTABLE;
- }
- res = alock_write_slot (info, &slot_data);
- ber_memfree (slot_data.al_appname);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
- alock_share_lock (info->al_fd, info->al_slot);
-
- res = alock_release_lock (info->al_fd, 0);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
-
- if (dirty_count) return ALOCK_RECOVER | nosave;
- return ALOCK_CLEAN | nosave;
-}
-
-int
-alock_scan ( alock_info_t * info )
-{
- struct stat statbuf;
- alock_info_t scan_info;
- int res, max_slot;
- int dirty_count, live_count, nosave;
-
- assert (info != NULL);
-
- scan_info.al_fd = info->al_fd;
-
- res = alock_grab_lock (info->al_fd, 0);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
-
- res = fstat (info->al_fd, &statbuf);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
-
- max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE;
- dirty_count = 0;
- live_count = 0;
- nosave = 0;
- for (scan_info.al_slot = 1;
- scan_info.al_slot < max_slot;
- ++ scan_info.al_slot) {
- if (scan_info.al_slot != info->al_slot) {
- res = alock_query_slot (&scan_info);
-
- if (res & ALOCK_NOSAVE) {
- nosave = ALOCK_NOSAVE;
- res ^= ALOCK_NOSAVE;
- }
-
- if (res == ALOCK_LOCKED) {
- ++live_count;
-
- } else if (res == ALOCK_DIRTY) {
- ++dirty_count;
-
- } else if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
-
- }
- }
- }
-
- res = alock_release_lock (info->al_fd, 0);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
-
- if (dirty_count) {
- if (live_count) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- } else {
- return ALOCK_RECOVER | nosave;
- }
- }
-
- return ALOCK_CLEAN | nosave;
-}
-
-int
-alock_close ( alock_info_t * info, int nosave )
-{
- alock_slot_t slot_data;
- int res;
-
- if ( !info->al_slot )
- return ALOCK_CLEAN;
-
- (void) memset ((void *) &slot_data, 0, sizeof(alock_slot_t));
-
- res = alock_grab_lock (info->al_fd, 0);
- if (res == -1) {
-fail:
- /* Windows doesn't clean up locks immediately when a process exits.
- * Make sure we release our locks, to prevent stale locks from
- * hanging around.
- */
- alock_release_lock (info->al_fd, 0);
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
-
- /* mark our slot as clean */
- res = alock_read_slot (info, &slot_data);
- if (res == -1) {
- if (slot_data.al_appname != NULL)
- ber_memfree (slot_data.al_appname);
- goto fail;
- }
- slot_data.al_lock = ALOCK_UNLOCKED;
- if ( nosave )
- slot_data.al_lock |= ALOCK_NOSAVE;
- /* since we have slot 0 locked, we don't need our slot lock */
- res = alock_release_lock (info->al_fd, info->al_slot);
- if (res == -1) {
- goto fail;
- }
- res = alock_write_slot (info, &slot_data);
- if (res == -1) {
- if (slot_data.al_appname != NULL)
- ber_memfree (slot_data.al_appname);
- goto fail;
- }
- if (slot_data.al_appname != NULL) {
- ber_memfree (slot_data.al_appname);
- slot_data.al_appname = NULL;
- }
-
- res = alock_release_lock (info->al_fd, 0);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
-
- res = close (info->al_fd);
- if (res == -1) return ALOCK_UNSTABLE;
-
- return ALOCK_CLEAN;
-}
-
-int
-alock_recover ( alock_info_t * info )
-{
- struct stat statbuf;
- alock_slot_t slot_data;
- alock_info_t scan_info;
- int res, max_slot;
-
- assert (info != NULL);
-
- scan_info.al_fd = info->al_fd;
-
- (void) memset ((void *) &slot_data, 0, sizeof(alock_slot_t));
-
- res = alock_grab_lock (info->al_fd, 0);
- if (res == -1) {
- goto fail;
- }
-
- res = fstat (info->al_fd, &statbuf);
- if (res == -1) {
- goto fail;
- }
-
- max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE;
- for (scan_info.al_slot = 1;
- scan_info.al_slot < max_slot;
- ++ scan_info.al_slot) {
- if (scan_info.al_slot != info->al_slot) {
- res = alock_query_slot (&scan_info) & ~ALOCK_NOSAVE;
-
- if (res == ALOCK_LOCKED
- || res == ALOCK_UNIQUE) {
- /* recovery attempt on an active db? */
- goto fail;
-
- } else if (res == ALOCK_DIRTY) {
- /* mark it clean */
- res = alock_read_slot (&scan_info, &slot_data);
- if (res == -1) {
- goto fail;
- }
- slot_data.al_lock = ALOCK_UNLOCKED;
- res = alock_write_slot (&scan_info, &slot_data);
- if (res == -1) {
- if (slot_data.al_appname != NULL)
- ber_memfree (slot_data.al_appname);
- goto fail;
- }
- if (slot_data.al_appname != NULL) {
- ber_memfree (slot_data.al_appname);
- slot_data.al_appname = NULL;
- }
-
- } else if (res == -1) {
- goto fail;
-
- }
- }
- }
-
- res = alock_release_lock (info->al_fd, 0);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
-
- return ALOCK_CLEAN;
-
-fail:
- alock_release_lock (info->al_fd, 0);
- close (info->al_fd);
- return ALOCK_UNSTABLE;
-}
-
-#endif /* SLAPD_BDB || SLAPD_HDB */
+++ /dev/null
-/* alock.h - access lock header */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2005-2019 The OpenLDAP Foundation.
- * Portions Copyright 2004-2005 Symas Corporation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was initially developed by Emily Backes at Symas
- * Corporation for inclusion in OpenLDAP Software.
- */
-
-#ifndef _ALOCK_H_
-#define _ALOCK_H_
-
-#include "portable.h"
-#include <ac/time.h>
-#include <ac/unistd.h>
-
-/* environment states (all the slots together) */
-#define ALOCK_CLEAN (0)
-#define ALOCK_RECOVER (1)
-#define ALOCK_BUSY (2)
-#define ALOCK_UNSTABLE (3)
-
-/* lock user types and states */
-#define ALOCK_UNLOCKED (0)
-#define ALOCK_LOCKED (1)
-#define ALOCK_UNIQUE (2)
-#define ALOCK_DIRTY (3)
-
-#define ALOCK_SMASK 3
-
-/* lock/state where recovery is not available */
-#define ALOCK_NOSAVE 4
-
-/* constants */
-#define ALOCK_SLOT_SIZE (1024)
-#define ALOCK_SLOT_IATTRS (4)
-#define ALOCK_MAX_APPNAME (ALOCK_SLOT_SIZE - 8 * ALOCK_SLOT_IATTRS)
-#define ALOCK_MAGIC (0x12345678)
-
-LDAP_BEGIN_DECL
-
-typedef struct alock_info {
- int al_fd;
- int al_slot;
-} alock_info_t;
-
-typedef struct alock_slot {
- unsigned int al_lock;
- time_t al_stamp;
- pid_t al_pid;
- char * al_appname;
-} alock_slot_t;
-
-LDAP_SLAPD_F (int) alock_open LDAP_P(( alock_info_t * info, const char * appname,
- const char * envdir, int locktype ));
-LDAP_SLAPD_F (int) alock_scan LDAP_P(( alock_info_t * info ));
-LDAP_SLAPD_F (int) alock_close LDAP_P(( alock_info_t * info, int nosave ));
-LDAP_SLAPD_F (int) alock_recover LDAP_P(( alock_info_t * info ));
-
-LDAP_END_DECL
-
-#endif
+++ /dev/null
-# Makefile.in for back-bdb
-# $OpenLDAP$
-## This work is part of OpenLDAP Software <http://www.openldap.org/>.
-##
-## Copyright 1998-2019 The OpenLDAP Foundation.
-## All rights reserved.
-##
-## Redistribution and use in source and binary forms, with or without
-## modification, are permitted only as authorized by the OpenLDAP
-## Public License.
-##
-## A copy of this license is available in the file LICENSE in the
-## top-level directory of the distribution or, alternatively, at
-## <http://www.OpenLDAP.org/license.html>.
-
-SRCS = init.c tools.c config.c \
- add.c bind.c compare.c delete.c modify.c modrdn.c search.c \
- extended.c referral.c operational.c \
- attr.c index.c key.c dbcache.c filterindex.c \
- dn2entry.c dn2id.c error.c id2entry.c idl.c \
- nextid.c cache.c trans.c monitor.c
-
-OBJS = init.lo tools.lo config.lo \
- add.lo bind.lo compare.lo delete.lo modify.lo modrdn.lo search.lo \
- extended.lo referral.lo operational.lo \
- attr.lo index.lo key.lo dbcache.lo filterindex.lo \
- dn2entry.lo dn2id.lo error.lo id2entry.lo idl.lo \
- nextid.lo cache.lo trans.lo monitor.lo
-
-LDAP_INCDIR= ../../../include
-LDAP_LIBDIR= ../../../libraries
-
-BUILD_OPT = "--enable-bdb"
-BUILD_MOD = @BUILD_BDB@
-
-mod_DEFS = -DSLAPD_IMPORT
-MOD_DEFS = $(@BUILD_BDB@_DEFS)
-MOD_LIBS = $(BDB_LIBS)
-
-shared_LDAP_LIBS = $(LDAP_LIBLDAP_R_LA) $(LDAP_LIBLBER_LA)
-NT_LINK_LIBS = -L.. -lslapd $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
-UNIX_LINK_LIBS = $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
-
-LIBBASE = back_bdb
-
-XINCPATH = -I.. -I$(srcdir)/..
-XDEFS = $(MODULES_CPPFLAGS)
-
-all-local-lib: ../.backend
-
-../.backend: lib$(LIBBASE).a
- @touch $@
-
+++ /dev/null
-/* add.c - ldap BerkeleyDB back-end add routine */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "back-bdb.h"
-
-int
-bdb_add(Operation *op, SlapReply *rs )
-{
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
- struct berval pdn;
- Entry *p = NULL, *oe = op->ora_e;
- EntryInfo *ei;
- char textbuf[SLAP_TEXT_BUFLEN];
- size_t textlen = sizeof textbuf;
- AttributeDescription *children = slap_schema.si_ad_children;
- AttributeDescription *entry = slap_schema.si_ad_entry;
- DB_TXN *ltid = NULL, *lt2;
- ID eid = NOID;
- struct bdb_op_info opinfo = {{{ 0 }}};
- int subentry;
- DB_LOCK lock;
-
- int num_retries = 0;
- int success;
-
- LDAPControl **postread_ctrl = NULL;
- LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
- int num_ctrls = 0;
-
- Debug(LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(bdb_add) ": %s\n",
- op->ora_e->e_name.bv_val );
-
-#ifdef LDAP_X_TXN
- if( op->o_txnSpec && txn_preop( 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 );
- 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 );
- 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 */
- {
- int tflags = bdb->bi_db_opflags;
- if ( get_lazyCommit( op ))
- tflags |= DB_TXN_NOSYNC;
- rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, NULL, <id, tflags );
- }
- 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 );
- 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) );
-
- 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" );
-
- 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" );
- 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" );
- 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" );
- 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" );
-
- 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" );
- 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" );
- 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 );
- 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 );
- 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) );
-
- /* 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 );
-
- 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" );
- 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" );
- 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" );
- 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;
-}
+++ /dev/null
-/* attr.c - backend routines for dealing with attributes */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/socket.h>
-#include <ac/string.h>
-
-#include "slap.h"
-#include "back-bdb.h"
-#include "config.h"
-#include "lutil.h"
-
-/* Find the ad, return -1 if not found,
- * set point for insertion if ins is non-NULL
- */
-int
-bdb_attr_slot( struct bdb_info *bdb, AttributeDescription *ad, int *ins )
-{
- unsigned base = 0, cursor = 0;
- unsigned n = bdb->bi_nattrs;
- int val = 0;
-
- while ( 0 < n ) {
- unsigned pivot = n >> 1;
- cursor = base + pivot;
-
- val = SLAP_PTRCMP( ad, bdb->bi_attrs[cursor]->ai_desc );
- if ( val < 0 ) {
- n = pivot;
- } else if ( val > 0 ) {
- base = cursor + 1;
- n -= pivot + 1;
- } else {
- return cursor;
- }
- }
- if ( ins ) {
- if ( val > 0 )
- ++cursor;
- *ins = cursor;
- }
- return -1;
-}
-
-static int
-ainfo_insert( struct bdb_info *bdb, AttrInfo *a )
-{
- int x;
- int i = bdb_attr_slot( bdb, a->ai_desc, &x );
-
- /* Is it a dup? */
- if ( i >= 0 )
- return -1;
-
- bdb->bi_attrs = ch_realloc( bdb->bi_attrs, ( bdb->bi_nattrs+1 ) *
- sizeof( AttrInfo * ));
- if ( x < bdb->bi_nattrs )
- AC_MEMCPY( &bdb->bi_attrs[x+1], &bdb->bi_attrs[x],
- ( bdb->bi_nattrs - x ) * sizeof( AttrInfo *));
- bdb->bi_attrs[x] = a;
- bdb->bi_nattrs++;
- return 0;
-}
-
-AttrInfo *
-bdb_attr_mask(
- struct bdb_info *bdb,
- AttributeDescription *desc )
-{
- int i = bdb_attr_slot( bdb, desc, NULL );
- return i < 0 ? NULL : bdb->bi_attrs[i];
-}
-
-int
-bdb_attr_index_config(
- struct bdb_info *bdb,
- const char *fname,
- int lineno,
- int argc,
- char **argv,
- struct config_reply_s *c_reply)
-{
- int rc = 0;
- int i;
- slap_mask_t mask;
- char **attrs;
- char **indexes = NULL;
-
- attrs = ldap_str2charray( argv[0], "," );
-
- if( attrs == NULL ) {
- fprintf( stderr, "%s: line %d: "
- "no attributes specified: %s\n",
- fname, lineno, argv[0] );
- return LDAP_PARAM_ERROR;
- }
-
- if ( argc > 1 ) {
- indexes = ldap_str2charray( argv[1], "," );
-
- if( indexes == NULL ) {
- fprintf( stderr, "%s: line %d: "
- "no indexes specified: %s\n",
- fname, lineno, argv[1] );
- rc = LDAP_PARAM_ERROR;
- goto done;
- }
- }
-
- if( indexes == NULL ) {
- mask = bdb->bi_defaultmask;
-
- } else {
- mask = 0;
-
- for ( i = 0; indexes[i] != NULL; i++ ) {
- slap_mask_t index;
- rc = slap_str2index( indexes[i], &index );
-
- if( rc != LDAP_SUCCESS ) {
- if ( c_reply )
- {
- snprintf(c_reply->msg, sizeof(c_reply->msg),
- "index type \"%s\" undefined", indexes[i] );
-
- fprintf( stderr, "%s: line %d: %s\n",
- fname, lineno, c_reply->msg );
- }
- rc = LDAP_PARAM_ERROR;
- goto done;
- }
-
- mask |= index;
- }
- }
-
- if( !mask ) {
- if ( c_reply )
- {
- snprintf(c_reply->msg, sizeof(c_reply->msg),
- "no indexes selected" );
- fprintf( stderr, "%s: line %d: %s\n",
- fname, lineno, c_reply->msg );
- }
- rc = LDAP_PARAM_ERROR;
- goto done;
- }
-
- for ( i = 0; attrs[i] != NULL; i++ ) {
- AttrInfo *a;
- AttributeDescription *ad;
- const char *text;
-#ifdef LDAP_COMP_MATCH
- ComponentReference* cr = NULL;
- AttrInfo *a_cr = NULL;
-#endif
-
- if( strcasecmp( attrs[i], "default" ) == 0 ) {
- bdb->bi_defaultmask |= mask;
- continue;
- }
-
-#ifdef LDAP_COMP_MATCH
- if ( is_component_reference( attrs[i] ) ) {
- rc = extract_component_reference( attrs[i], &cr );
- if ( rc != LDAP_SUCCESS ) {
- if ( c_reply )
- {
- snprintf(c_reply->msg, sizeof(c_reply->msg),
- "index component reference\"%s\" undefined",
- attrs[i] );
- fprintf( stderr, "%s: line %d: %s\n",
- fname, lineno, c_reply->msg );
- }
- goto done;
- }
- cr->cr_indexmask = mask;
- /*
- * After extracting a component reference
- * only the name of a attribute will be remaining
- */
- } else {
- cr = NULL;
- }
-#endif
- ad = NULL;
- rc = slap_str2ad( attrs[i], &ad, &text );
-
- if( rc != LDAP_SUCCESS ) {
- if ( c_reply )
- {
- snprintf(c_reply->msg, sizeof(c_reply->msg),
- "index attribute \"%s\" undefined",
- attrs[i] );
-
- fprintf( stderr, "%s: line %d: %s\n",
- fname, lineno, c_reply->msg );
- }
-fail:
-#ifdef LDAP_COMP_MATCH
- ch_free( cr );
-#endif
- 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 fail;
- }
-
- 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 fail;
- }
-
- 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 fail;
- }
-
- 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 fail;
- }
-
- Debug( LDAP_DEBUG_CONFIG, "index %s 0x%04lx\n",
- ad->ad_cname.bv_val, mask );
-
- 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
- */
- ch_free( a );
- 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 fail;
- }
- 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;
- ch_free( a );
- goto fail;
- }
- }
- }
-#endif
- rc = ainfo_insert( bdb, a );
- if( rc ) {
- if ( bdb->bi_flags & BDB_IS_OPEN ) {
- AttrInfo *b = bdb_attr_mask( bdb, ad );
- /* If there is already an index defined for this attribute
- * it must be replaced. Otherwise we end up with multiple
- * olcIndex values for the same attribute */
- if ( b->ai_indexmask & BDB_INDEX_DELETING ) {
- /* If we were editing this attr, reset it */
- b->ai_indexmask &= ~BDB_INDEX_DELETING;
- /* If this is leftover from a previous add, commit it */
- if ( b->ai_newmask )
- b->ai_indexmask = b->ai_newmask;
- b->ai_newmask = a->ai_newmask;
- ch_free( a );
- rc = 0;
- continue;
- }
- }
- if (c_reply) {
- snprintf(c_reply->msg, sizeof(c_reply->msg),
- "duplicate index definition for attr \"%s\"",
- attrs[i] );
- fprintf( stderr, "%s: line %d: %s\n",
- fname, lineno, c_reply->msg );
- }
-
- rc = LDAP_PARAM_ERROR;
- goto done;
- }
- }
-
-done:
- ldap_charray_free( attrs );
- if ( indexes != NULL ) ldap_charray_free( indexes );
-
- return rc;
-}
-
-static int
-bdb_attr_index_unparser( void *v1, void *v2 )
-{
- AttrInfo *ai = v1;
- BerVarray *bva = v2;
- struct berval bv;
- char *ptr;
-
- slap_index2bvlen( ai->ai_indexmask, &bv );
- if ( bv.bv_len ) {
- bv.bv_len += ai->ai_desc->ad_cname.bv_len + 1;
- ptr = ch_malloc( bv.bv_len+1 );
- bv.bv_val = lutil_strcopy( ptr, ai->ai_desc->ad_cname.bv_val );
- *bv.bv_val++ = ' ';
- slap_index2bv( ai->ai_indexmask, &bv );
- bv.bv_val = ptr;
- ber_bvarray_add( bva, &bv );
- }
- return 0;
-}
-
-static AttributeDescription addef = { NULL, NULL, BER_BVC("default") };
-static AttrInfo aidef = { &addef };
-
-void
-bdb_attr_index_unparse( struct bdb_info *bdb, BerVarray *bva )
-{
- int i;
-
- if ( bdb->bi_defaultmask ) {
- aidef.ai_indexmask = bdb->bi_defaultmask;
- bdb_attr_index_unparser( &aidef, bva );
- }
- for ( i=0; i<bdb->bi_nattrs; i++ )
- bdb_attr_index_unparser( bdb->bi_attrs[i], bva );
-}
-
-void
-bdb_attr_info_free( AttrInfo *ai )
-{
-#ifdef LDAP_COMP_MATCH
- free( ai->ai_cr );
-#endif
- free( ai );
-}
-
-void
-bdb_attr_index_destroy( struct bdb_info *bdb )
-{
- int i;
-
- for ( i=0; i<bdb->bi_nattrs; i++ )
- bdb_attr_info_free( bdb->bi_attrs[i] );
-
- free( bdb->bi_attrs );
-}
-
-void bdb_attr_index_free( struct bdb_info *bdb, AttributeDescription *ad )
-{
- int i;
-
- i = bdb_attr_slot( bdb, ad, NULL );
- if ( i >= 0 ) {
- bdb_attr_info_free( bdb->bi_attrs[i] );
- bdb->bi_nattrs--;
- for (; i<bdb->bi_nattrs; i++)
- bdb->bi_attrs[i] = bdb->bi_attrs[i+1];
- }
-}
-
-void bdb_attr_flush( struct bdb_info *bdb )
-{
- int i;
-
- for ( i=0; i<bdb->bi_nattrs; i++ ) {
- if ( bdb->bi_attrs[i]->ai_indexmask & BDB_INDEX_DELETING ) {
- int j;
- bdb_attr_info_free( bdb->bi_attrs[i] );
- bdb->bi_nattrs--;
- for (j=i; j<bdb->bi_nattrs; j++)
- bdb->bi_attrs[j] = bdb->bi_attrs[j+1];
- i--;
- }
- }
-}
+++ /dev/null
-/* back-bdb.h - bdb back-end header file */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#ifndef _BACK_BDB_H_
-#define _BACK_BDB_H_
-
-#include <portable.h>
-#include "slap.h"
-#include <db.h>
-#include "alock.h"
-
-LDAP_BEGIN_DECL
-
-#define DB_VERSION_FULL ((DB_VERSION_MAJOR << 24) | (DB_VERSION_MINOR << 16) | DB_VERSION_PATCH)
-
-#define DN_BASE_PREFIX SLAP_INDEX_EQUALITY_PREFIX
-#define DN_ONE_PREFIX '%'
-#define DN_SUBTREE_PREFIX '@'
-
-#define DBTzero(t) (memset((t), 0, sizeof(DBT)))
-#define DBT2bv(t,bv) ((bv)->bv_val = (t)->data, \
- (bv)->bv_len = (t)->size)
-#define bv2DBT(bv,t) ((t)->data = (bv)->bv_val, \
- (t)->size = (bv)->bv_len )
-
-#define BDB_TXN_RETRIES 16
-
-#define BDB_MAX_ADD_LOOP 30
-
-#define BDB_SUFFIX ".bdb"
-#define BDB_ID2ENTRY 0
-#define BDB_DN2ID 1
-#define BDB_NDB 2
-
-/* The bdb on-disk entry format is pretty space-inefficient. Average
- * sized user entries are 3-4K each. You need at least two entries to
- * fit into a single database page, more is better. 64K is BDB's
- * upper bound. Smaller pages are better for concurrency.
- */
-#ifndef BDB_ID2ENTRY_PAGESIZE
-#define BDB_ID2ENTRY_PAGESIZE 16384
-#endif
-
-#define DEFAULT_CACHE_SIZE 1000
-
-/* The default search IDL stack cache depth */
-#define DEFAULT_SEARCH_STACK_DEPTH 16
-
-/* The minimum we can function with */
-#define MINIMUM_SEARCH_STACK_DEPTH 8
-
-typedef struct bdb_idl_cache_entry_s {
- struct berval kstr;
- ID *idl;
- DB *db;
- int idl_flags;
- struct bdb_idl_cache_entry_s* idl_lru_prev;
- struct bdb_idl_cache_entry_s* idl_lru_next;
-} bdb_idl_cache_entry_t;
-
-/* BDB backend specific entry info */
-typedef struct bdb_entry_info {
- struct bdb_entry_info *bei_parent;
- ID bei_id;
-
- /* we use the bei_id as a lockobj, but we need to make the size != 4
- * to avoid conflicting with BDB's internal locks. So add a byte here
- * that is always zero.
- */
- short bei_lockpad;
-
- short bei_state;
-#define CACHE_ENTRY_DELETED 1
-#define CACHE_ENTRY_NO_KIDS 2
-#define CACHE_ENTRY_NOT_LINKED 4
-#define CACHE_ENTRY_NO_GRANDKIDS 8
-#define CACHE_ENTRY_LOADING 0x10
-#define CACHE_ENTRY_WALKING 0x20
-#define CACHE_ENTRY_ONELEVEL 0x40
-#define CACHE_ENTRY_REFERENCED 0x80
-#define CACHE_ENTRY_NOT_CACHED 0x100
- int bei_finders;
-
- /*
- * remaining fields require backend cache lock to access
- */
- struct berval bei_nrdn;
-#ifdef BDB_HIER
- struct berval bei_rdn;
- int bei_modrdns; /* track renames */
- int bei_ckids; /* number of kids cached */
- int bei_dkids; /* number of kids on-disk, plus 1 */
-#endif
- Entry *bei_e;
- Avlnode *bei_kids;
-#ifdef SLAP_ZONE_ALLOC
- struct bdb_info *bei_bdb;
- int bei_zseq;
-#endif
- ldap_pvt_thread_mutex_t bei_kids_mutex;
-
- struct bdb_entry_info *bei_lrunext; /* for cache lru list */
- struct bdb_entry_info *bei_lruprev;
-} EntryInfo;
-#undef BEI
-#define BEI(e) ((EntryInfo *) ((e)->e_private))
-
-/* for the in-core cache of entries */
-typedef struct bdb_cache {
- EntryInfo *c_eifree; /* free list */
- Avlnode *c_idtree;
- EntryInfo *c_lruhead; /* lru - add accessed entries here */
- EntryInfo *c_lrutail; /* lru - rem lru entries from here */
- EntryInfo c_dntree;
- ID c_maxsize;
- ID c_cursize;
- ID c_minfree;
- ID c_eimax;
- ID c_eiused; /* EntryInfo's in use */
- ID c_leaves; /* EntryInfo leaf nodes */
- int c_purging;
- DB_TXN *c_txn; /* used by lru cleaner */
- ldap_pvt_thread_rdwr_t c_rwlock;
- ldap_pvt_thread_mutex_t c_lru_mutex;
- ldap_pvt_thread_mutex_t c_count_mutex;
- ldap_pvt_thread_mutex_t c_eifree_mutex;
-#ifdef SLAP_ZONE_ALLOC
- void *c_zctx;
-#endif
-} Cache;
-
-#define CACHE_READ_LOCK 0
-#define CACHE_WRITE_LOCK 1
-
-#define BDB_INDICES 128
-
-struct bdb_db_info {
- struct berval bdi_name;
- DB *bdi_db;
-};
-
-struct bdb_db_pgsize {
- struct bdb_db_pgsize *bdp_next;
- struct berval bdp_name;
- int bdp_size;
-};
-
-#ifdef LDAP_DEVEL
-#define BDB_MONITOR_IDX
-#endif
-
-typedef struct bdb_monitor_t {
- void *bdm_cb;
- struct berval bdm_ndn;
-} bdb_monitor_t;
-
-/* From ldap_rq.h */
-struct re_s;
-
-struct bdb_info {
- DB_ENV *bi_dbenv;
-
- /* DB_ENV parameters */
- /* The DB_ENV can be tuned via DB_CONFIG */
- char *bi_dbenv_home;
- u_int32_t bi_dbenv_xflags; /* extra flags */
- int bi_dbenv_mode;
-
- int bi_ndatabases;
- int bi_db_opflags; /* db-specific flags */
- struct bdb_db_info **bi_databases;
- ldap_pvt_thread_mutex_t bi_database_mutex;
- struct bdb_db_pgsize *bi_pagesizes;
-
- slap_mask_t bi_defaultmask;
- Cache bi_cache;
- struct bdb_attrinfo **bi_attrs;
- int bi_nattrs;
- void *bi_search_stack;
- int bi_search_stack_depth;
- int bi_linear_index;
-
- int bi_txn_cp;
- u_int32_t bi_txn_cp_min;
- u_int32_t bi_txn_cp_kbyte;
- struct re_s *bi_txn_cp_task;
- struct re_s *bi_index_task;
-
- u_int32_t bi_lock_detect;
- long bi_shm_key;
-
- ID bi_lastid;
- ldap_pvt_thread_mutex_t bi_lastid_mutex;
- ID bi_idl_cache_max_size;
- ID bi_idl_cache_size;
- Avlnode *bi_idl_tree;
- bdb_idl_cache_entry_t *bi_idl_lru_head;
- bdb_idl_cache_entry_t *bi_idl_lru_tail;
- ldap_pvt_thread_rdwr_t bi_idl_tree_rwlock;
- ldap_pvt_thread_mutex_t bi_idl_tree_lrulock;
- alock_info_t bi_alock_info;
- char *bi_db_config_path;
- BerVarray bi_db_config;
- char *bi_db_crypt_file;
- struct berval bi_db_crypt_key;
- bdb_monitor_t bi_monitor;
-
-#ifdef BDB_MONITOR_IDX
- ldap_pvt_thread_mutex_t bi_idx_mutex;
- Avlnode *bi_idx;
-#endif /* BDB_MONITOR_IDX */
-
- int bi_flags;
-#define BDB_IS_OPEN 0x01
-#define BDB_HAS_CONFIG 0x02
-#define BDB_UPD_CONFIG 0x04
-#define BDB_DEL_INDEX 0x08
-#define BDB_RE_OPEN 0x10
-#define BDB_CHKSUM 0x20
-#ifdef BDB_HIER
- int bi_modrdns; /* number of modrdns completed */
- ldap_pvt_thread_mutex_t bi_modrdns_mutex;
-#endif
-};
-
-#define bi_id2entry bi_databases[BDB_ID2ENTRY]
-#define bi_dn2id bi_databases[BDB_DN2ID]
-
-
-struct bdb_lock_info {
- struct bdb_lock_info *bli_next;
- DB_LOCK bli_lock;
- ID bli_id;
- int bli_flag;
-};
-#define BLI_DONTFREE 1
-
-struct bdb_op_info {
- OpExtra boi_oe;
- DB_TXN* boi_txn;
- struct bdb_lock_info *boi_locks; /* used when no txn */
- u_int32_t boi_err;
- char boi_acl_cache;
- char boi_flag;
-};
-#define BOI_DONTFREE 1
-
-#define DB_OPEN(db, file, name, type, flags, mode) \
- ((db)->open)(db, file, name, type, flags, mode)
-
-#if DB_VERSION_MAJOR < 4
-#define LOCK_DETECT(env,f,t,a) lock_detect(env, f, t, a)
-#define LOCK_GET(env,i,f,o,m,l) lock_get(env, i, f, o, m, l)
-#define LOCK_PUT(env,l) lock_put(env, l)
-#define TXN_CHECKPOINT(env,k,m,f) txn_checkpoint(env, k, m, f)
-#define TXN_BEGIN(env,p,t,f) txn_begin((env), p, t, f)
-#define TXN_PREPARE(txn,gid) txn_prepare((txn), (gid))
-#define TXN_COMMIT(txn,f) txn_commit((txn), (f))
-#define TXN_ABORT(txn) txn_abort((txn))
-#define TXN_ID(txn) txn_id(txn)
-#define XLOCK_ID(env, locker) lock_id(env, locker)
-#define XLOCK_ID_FREE(env, locker) lock_id_free(env, locker)
-#else
-#define LOCK_DETECT(env,f,t,a) (env)->lock_detect(env, f, t, a)
-#define LOCK_GET(env,i,f,o,m,l) (env)->lock_get(env, i, f, o, m, l)
-#define LOCK_PUT(env,l) (env)->lock_put(env, l)
-#define TXN_CHECKPOINT(env,k,m,f) (env)->txn_checkpoint(env, k, m, f)
-#define TXN_BEGIN(env,p,t,f) (env)->txn_begin((env), p, t, f)
-#define TXN_PREPARE(txn,g) (txn)->prepare((txn), (g))
-#define TXN_COMMIT(txn,f) (txn)->commit((txn), (f))
-#define TXN_ABORT(txn) (txn)->abort((txn))
-#define TXN_ID(txn) (txn)->id(txn)
-#define XLOCK_ID(env, locker) (env)->lock_id(env, locker)
-#define XLOCK_ID_FREE(env, locker) (env)->lock_id_free(env, locker)
-
-/* BDB 4.1.17 adds txn arg to db->open */
-#if DB_VERSION_FULL >= 0x04010011
-#undef DB_OPEN
-#define DB_OPEN(db, file, name, type, flags, mode) \
- ((db)->open)(db, NULL, file, name, type, flags, mode)
-#endif
-
-/* #undef BDB_LOG_DEBUG */
-
-#ifdef BDB_LOG_DEBUG
-
-/* env->log_printf appeared in 4.4 */
-#if DB_VERSION_FULL >= 0x04040000
-#define BDB_LOG_PRINTF(env,txn,fmt,...) (env)->log_printf((env),(txn),(fmt),__VA_ARGS__)
-#else
-extern int __db_logmsg(const DB_ENV *env, DB_TXN *txn, const char *op, u_int32_t flags,
- const char *fmt,...);
-#define BDB_LOG_PRINTF(env,txn,fmt,...) __db_logmsg((env),(txn),"DIAGNOSTIC",0,(fmt),__VA_ARGS__)
-#endif
-
-/* !BDB_LOG_DEBUG */
-#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
- (defined(__GNUC__) && __GNUC__ >= 3 && !defined(__STRICT_ANSI__))
-#define BDB_LOG_PRINTF(a,b,c,...)
-#else
-#define BDB_LOG_PRINTF (void) /* will evaluate and discard the arguments */
-
-#endif /* BDB_LOG_DEBUG */
-
-#endif
-
-#ifndef DB_BUFFER_SMALL
-#define DB_BUFFER_SMALL ENOMEM
-#endif
-
-#define BDB_CSN_COMMIT 0
-#define BDB_CSN_ABORT 1
-#define BDB_CSN_RETRY 2
-
-/* Copy an ID "src" to pointer "dst" in big-endian byte order */
-#define BDB_ID2DISK( src, dst ) \
- do { int i0; ID tmp; unsigned char *_p; \
- tmp = (src); _p = (unsigned char *)(dst); \
- for ( i0=sizeof(ID)-1; i0>=0; i0-- ) { \
- _p[i0] = tmp & 0xff; tmp >>= 8; \
- } \
- } while(0)
-
-/* Copy a pointer "src" to a pointer "dst" from big-endian to native order */
-#define BDB_DISK2ID( src, dst ) \
- do { unsigned i0; ID tmp = 0; unsigned char *_p; \
- _p = (unsigned char *)(src); \
- for ( i0=0; i0<sizeof(ID); i0++ ) { \
- tmp <<= 8; tmp |= *_p++; \
- } *(dst) = tmp; \
- } while (0)
-
-LDAP_END_DECL
-
-/* for the cache of attribute information (which are indexed, etc.) */
-typedef struct bdb_attrinfo {
- AttributeDescription *ai_desc; /* attribute description cn;lang-en */
- slap_mask_t ai_indexmask; /* how the attr is indexed */
- slap_mask_t ai_newmask; /* new settings to replace old mask */
-#ifdef LDAP_COMP_MATCH
- ComponentReference* ai_cr; /*component indexing*/
-#endif
-} AttrInfo;
-
-/* These flags must not clash with SLAP_INDEX flags or ops in slap.h! */
-#define BDB_INDEX_DELETING 0x8000U /* index is being modified */
-#define BDB_INDEX_UPDATE_OP 0x03 /* performing an index update */
-
-/* For slapindex to record which attrs in an entry belong to which
- * index database
- */
-typedef struct AttrList {
- struct AttrList *next;
- Attribute *attr;
-} AttrList;
-
-typedef struct IndexRec {
- AttrInfo *ai;
- AttrList *attrs;
-} IndexRec;
-
-#include "proto-bdb.h"
-
-#endif /* _BACK_BDB_H_ */
+++ /dev/null
-/* bind.c - bdb backend bind routine */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-
-#include "back-bdb.h"
-
-int
-bdb_bind( Operation *op, SlapReply *rs )
-{
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
- Entry *e;
- Attribute *a;
- EntryInfo *ei;
-
- AttributeDescription *password = slap_schema.si_ad_userPassword;
-
- DB_TXN *rtxn;
- DB_LOCK lock;
-
- Debug( LDAP_DEBUG_ARGS,
- "==> " LDAP_XSTRING(bdb_bind) ": dn: %s\n",
- op->o_req_dn.bv_val );
-
- /* 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" );
- 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" );
- rs->sr_err = LDAP_INVALID_CREDENTIALS;
- goto done;
- }
-
- if ( is_entry_referral( e ) ) {
- Debug( LDAP_DEBUG_TRACE, "entry is referral\n" );
- 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;
-}
+++ /dev/null
-/* cache.c - routines to maintain an in-core cache of entries */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/errno.h>
-#include <ac/string.h>
-#include <ac/socket.h>
-
-#include "slap.h"
-
-#include "back-bdb.h"
-
-#include "ldap_rq.h"
-
-#ifdef BDB_HIER
-#define bdb_cache_lru_purge hdb_cache_lru_purge
-#endif
-static void bdb_cache_lru_purge( struct bdb_info *bdb );
-
-static int bdb_cache_delete_internal(Cache *cache, EntryInfo *e, int decr);
-#ifdef LDAP_DEBUG
-#define SLAPD_UNUSED
-#ifdef SLAPD_UNUSED
-static void bdb_lru_print(Cache *cache);
-static void bdb_idtree_print(Cache *cache);
-#endif
-#endif
-
-/* For concurrency experiments only! */
-#if 0
-#define ldap_pvt_thread_rdwr_wlock(a) 0
-#define ldap_pvt_thread_rdwr_wunlock(a) 0
-#define ldap_pvt_thread_rdwr_rlock(a) 0
-#define ldap_pvt_thread_rdwr_runlock(a) 0
-#endif
-
-#if 0
-#define ldap_pvt_thread_mutex_trylock(a) 0
-#endif
-
-static EntryInfo *
-bdb_cache_entryinfo_new( Cache *cache )
-{
- EntryInfo *ei = NULL;
-
- if ( cache->c_eifree ) {
- ldap_pvt_thread_mutex_lock( &cache->c_eifree_mutex );
- if ( cache->c_eifree ) {
- ei = cache->c_eifree;
- cache->c_eifree = ei->bei_lrunext;
- ei->bei_finders = 0;
- ei->bei_lrunext = NULL;
- }
- ldap_pvt_thread_mutex_unlock( &cache->c_eifree_mutex );
- }
- if ( !ei ) {
- ei = ch_calloc(1, sizeof(EntryInfo));
- ldap_pvt_thread_mutex_init( &ei->bei_kids_mutex );
- }
-
- ei->bei_state = CACHE_ENTRY_REFERENCED;
-
- return ei;
-}
-
-static void
-bdb_cache_entryinfo_free( Cache *cache, EntryInfo *ei )
-{
- free( ei->bei_nrdn.bv_val );
- BER_BVZERO( &ei->bei_nrdn );
-#ifdef BDB_HIER
- free( ei->bei_rdn.bv_val );
- BER_BVZERO( &ei->bei_rdn );
- ei->bei_modrdns = 0;
- ei->bei_ckids = 0;
- ei->bei_dkids = 0;
-#endif
- ei->bei_parent = NULL;
- ei->bei_kids = NULL;
- ei->bei_lruprev = NULL;
-
-#if 0
- ldap_pvt_thread_mutex_lock( &cache->c_eifree_mutex );
- ei->bei_lrunext = cache->c_eifree;
- cache->c_eifree = ei;
- ldap_pvt_thread_mutex_unlock( &cache->c_eifree_mutex );
-#else
- ldap_pvt_thread_mutex_destroy( &ei->bei_kids_mutex );
- ch_free( ei );
-#endif
-}
-
-#define LRU_DEL( c, e ) do { \
- if ( e == e->bei_lruprev ) { \
- (c)->c_lruhead = (c)->c_lrutail = NULL; \
- } else { \
- if ( e == (c)->c_lruhead ) (c)->c_lruhead = e->bei_lruprev; \
- if ( e == (c)->c_lrutail ) (c)->c_lrutail = e->bei_lruprev; \
- e->bei_lrunext->bei_lruprev = e->bei_lruprev; \
- e->bei_lruprev->bei_lrunext = e->bei_lrunext; \
- } \
- e->bei_lruprev = NULL; \
-} while ( 0 )
-
-/* Note - we now use a Second-Chance / Clock algorithm instead of
- * Least-Recently-Used. This tremendously improves concurrency
- * because we no longer need to manipulate the lists every time an
- * entry is touched. We only need to lock the lists when adding
- * or deleting an entry. It's now a circular doubly-linked list.
- * We always append to the tail, but the head traverses the circle
- * during a purge operation.
- */
-static void
-bdb_cache_lru_link( struct bdb_info *bdb, EntryInfo *ei )
-{
-
- /* Already linked, ignore */
- if ( ei->bei_lruprev )
- return;
-
- /* Insert into circular LRU list */
- ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_lru_mutex );
-
- ei->bei_lruprev = bdb->bi_cache.c_lrutail;
- if ( bdb->bi_cache.c_lrutail ) {
- ei->bei_lrunext = bdb->bi_cache.c_lrutail->bei_lrunext;
- bdb->bi_cache.c_lrutail->bei_lrunext = ei;
- if ( ei->bei_lrunext )
- ei->bei_lrunext->bei_lruprev = ei;
- } else {
- ei->bei_lrunext = ei->bei_lruprev = ei;
- bdb->bi_cache.c_lruhead = ei;
- }
- bdb->bi_cache.c_lrutail = ei;
- ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_lru_mutex );
-}
-
-#ifdef NO_THREADS
-#define NO_DB_LOCK
-#endif
-
-/* #define NO_DB_LOCK 1 */
-/* Note: The BerkeleyDB locks are much slower than regular
- * mutexes or rdwr locks. But the BDB implementation has the
- * advantage of using a fixed size lock table, instead of
- * allocating a lock object per entry in the DB. That's a
- * key benefit for scaling. It also frees us from worrying
- * about undetectable deadlocks between BDB activity and our
- * own cache activity. It's still worth exploring faster
- * alternatives though.
- */
-
-/* Atomically release and reacquire a lock */
-int
-bdb_cache_entry_db_relock(
- struct bdb_info *bdb,
- DB_TXN *txn,
- EntryInfo *ei,
- int rw,
- int tryOnly,
- DB_LOCK *lock )
-{
-#ifdef NO_DB_LOCK
- return 0;
-#else
- int rc;
- DBT lockobj;
- DB_LOCKREQ list[2];
-
- if ( !lock ) return 0;
-
- DBTzero( &lockobj );
- lockobj.data = &ei->bei_id;
- lockobj.size = sizeof(ei->bei_id) + 1;
-
- list[0].op = DB_LOCK_PUT;
- list[0].lock = *lock;
- list[1].op = DB_LOCK_GET;
- list[1].lock = *lock;
- list[1].mode = rw ? DB_LOCK_WRITE : DB_LOCK_READ;
- list[1].obj = &lockobj;
- rc = bdb->bi_dbenv->lock_vec(bdb->bi_dbenv, TXN_ID(txn), tryOnly ? DB_LOCK_NOWAIT : 0,
- list, 2, NULL );
-
- if (rc && !tryOnly) {
- Debug( LDAP_DEBUG_TRACE,
- "bdb_cache_entry_db_relock: entry %ld, rw %d, rc %d\n",
- ei->bei_id, rw, rc );
- } else {
- *lock = list[1].lock;
- }
- return rc;
-#endif
-}
-
-static int
-bdb_cache_entry_db_lock( struct bdb_info *bdb, DB_TXN *txn, EntryInfo *ei,
- int rw, int tryOnly, DB_LOCK *lock )
-{
-#ifdef NO_DB_LOCK
- return 0;
-#else
- int rc;
- DBT lockobj;
- int db_rw;
-
- if ( !lock ) return 0;
-
- if (rw)
- db_rw = DB_LOCK_WRITE;
- else
- db_rw = DB_LOCK_READ;
-
- DBTzero( &lockobj );
- lockobj.data = &ei->bei_id;
- lockobj.size = sizeof(ei->bei_id) + 1;
-
- rc = LOCK_GET(bdb->bi_dbenv, TXN_ID(txn), tryOnly ? DB_LOCK_NOWAIT : 0,
- &lockobj, db_rw, lock);
- if (rc && !tryOnly) {
- Debug( LDAP_DEBUG_TRACE,
- "bdb_cache_entry_db_lock: entry %ld, rw %d, rc %d\n",
- ei->bei_id, rw, rc );
- }
- return rc;
-#endif /* NO_DB_LOCK */
-}
-
-int
-bdb_cache_entry_db_unlock ( struct bdb_info *bdb, DB_LOCK *lock )
-{
-#ifdef NO_DB_LOCK
- return 0;
-#else
- int rc;
-
- if ( !lock || lock->mode == DB_LOCK_NG ) return 0;
-
- rc = LOCK_PUT ( bdb->bi_dbenv, lock );
- return rc;
-#endif
-}
-
-void
-bdb_cache_return_entry_rw( struct bdb_info *bdb, Entry *e,
- int rw, DB_LOCK *lock )
-{
- EntryInfo *ei;
- int free = 0;
-
- ei = e->e_private;
- if ( ei && ( ei->bei_state & CACHE_ENTRY_NOT_CACHED )) {
- bdb_cache_entryinfo_lock( ei );
- if ( ei->bei_state & CACHE_ENTRY_NOT_CACHED ) {
- /* Releasing the entry can only be done when
- * we know that nobody else is using it, i.e we
- * should have an entry_db writelock. But the
- * flag is only set by the thread that loads the
- * entry, and only if no other threads has found
- * it while it was working. All other threads
- * clear the flag, which mean that we should be
- * the only thread using the entry if the flag
- * is set here.
- */
- ei->bei_e = NULL;
- ei->bei_state ^= CACHE_ENTRY_NOT_CACHED;
- free = 1;
- }
- bdb_cache_entryinfo_unlock( ei );
- }
- bdb_cache_entry_db_unlock( bdb, lock );
- if ( free ) {
- e->e_private = NULL;
- bdb_entry_return( e );
- }
-}
-
-static int
-bdb_cache_entryinfo_destroy( EntryInfo *e )
-{
- ldap_pvt_thread_mutex_destroy( &e->bei_kids_mutex );
- free( e->bei_nrdn.bv_val );
-#ifdef BDB_HIER
- free( e->bei_rdn.bv_val );
-#endif
- free( e );
- return 0;
-}
-
-/* Do a length-ordered sort on normalized RDNs */
-static int
-bdb_rdn_cmp( const void *v_e1, const void *v_e2 )
-{
- const EntryInfo *e1 = v_e1, *e2 = v_e2;
- int rc = e1->bei_nrdn.bv_len - e2->bei_nrdn.bv_len;
- if (rc == 0) {
- rc = strncmp( e1->bei_nrdn.bv_val, e2->bei_nrdn.bv_val,
- e1->bei_nrdn.bv_len );
- }
- return rc;
-}
-
-static int
-bdb_id_cmp( const void *v_e1, const void *v_e2 )
-{
- const EntryInfo *e1 = v_e1, *e2 = v_e2;
- return e1->bei_id - e2->bei_id;
-}
-
-static int
-bdb_id_dup_err( void *v1, void *v2 )
-{
- EntryInfo *e2 = v2;
- e2->bei_lrunext = v1;
- return -1;
-}
-
-/* Create an entryinfo in the cache. Caller must release the locks later.
- */
-static int
-bdb_entryinfo_add_internal(
- struct bdb_info *bdb,
- EntryInfo *ei,
- EntryInfo **res )
-{
- EntryInfo *ei2 = NULL;
-
- *res = NULL;
-
- ei2 = bdb_cache_entryinfo_new( &bdb->bi_cache );
-
- bdb_cache_entryinfo_lock( ei->bei_parent );
- ldap_pvt_thread_rdwr_wlock( &bdb->bi_cache.c_rwlock );
-
- ei2->bei_id = ei->bei_id;
- ei2->bei_parent = ei->bei_parent;
-#ifdef BDB_HIER
- ei2->bei_rdn = ei->bei_rdn;
-#endif
-#ifdef SLAP_ZONE_ALLOC
- ei2->bei_bdb = bdb;
-#endif
-
- /* Add to cache ID tree */
- if (avl_insert( &bdb->bi_cache.c_idtree, ei2, bdb_id_cmp,
- bdb_id_dup_err )) {
- EntryInfo *eix = ei2->bei_lrunext;
- bdb_cache_entryinfo_free( &bdb->bi_cache, ei2 );
- ei2 = eix;
-#ifdef BDB_HIER
- /* It got freed above because its value was
- * assigned to ei2.
- */
- ei->bei_rdn.bv_val = NULL;
-#endif
- } else {
- int rc;
-
- bdb->bi_cache.c_eiused++;
- ber_dupbv( &ei2->bei_nrdn, &ei->bei_nrdn );
-
- /* This is a new leaf node. But if parent had no kids, then it was
- * a leaf and we would be decrementing that. So, only increment if
- * the parent already has kids.
- */
- if ( ei->bei_parent->bei_kids || !ei->bei_parent->bei_id )
- bdb->bi_cache.c_leaves++;
- rc = avl_insert( &ei->bei_parent->bei_kids, ei2, bdb_rdn_cmp,
- avl_dup_error );
-#ifdef BDB_HIER
- /* it's possible for hdb_cache_find_parent to beat us to it */
- if ( !rc ) {
- ei->bei_parent->bei_ckids++;
- }
-#endif
- }
-
- *res = ei2;
- return 0;
-}
-
-/* Find the EntryInfo for the requested DN. If the DN cannot be found, return
- * the info for its closest ancestor. *res should be NULL to process a
- * complete DN starting from the tree root. Otherwise *res must be the
- * immediate parent of the requested DN, and only the RDN will be searched.
- * The EntryInfo is locked upon return and must be unlocked by the caller.
- */
-int
-bdb_cache_find_ndn(
- Operation *op,
- DB_TXN *txn,
- struct berval *ndn,
- EntryInfo **res )
-{
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
- EntryInfo ei, *eip, *ei2;
- int rc = 0;
- char *ptr;
-
- /* this function is always called with normalized DN */
- if ( *res ) {
- /* we're doing a onelevel search for an RDN */
- ei.bei_nrdn.bv_val = ndn->bv_val;
- ei.bei_nrdn.bv_len = dn_rdnlen( op->o_bd, ndn );
- eip = *res;
- } else {
- /* we're searching a full DN from the root */
- ptr = ndn->bv_val + ndn->bv_len - op->o_bd->be_nsuffix[0].bv_len;
- ei.bei_nrdn.bv_val = ptr;
- ei.bei_nrdn.bv_len = op->o_bd->be_nsuffix[0].bv_len;
- /* Skip to next rdn if suffix is empty */
- if ( ei.bei_nrdn.bv_len == 0 ) {
- for (ptr = ei.bei_nrdn.bv_val - 2; ptr > ndn->bv_val
- && !DN_SEPARATOR(*ptr); ptr--) /* empty */;
- if ( ptr >= ndn->bv_val ) {
- if (DN_SEPARATOR(*ptr)) ptr++;
- ei.bei_nrdn.bv_len = ei.bei_nrdn.bv_val - ptr;
- ei.bei_nrdn.bv_val = ptr;
- }
- }
- eip = &bdb->bi_cache.c_dntree;
- }
-
- for ( bdb_cache_entryinfo_lock( eip ); eip; ) {
- eip->bei_state |= CACHE_ENTRY_REFERENCED;
- ei.bei_parent = eip;
- ei2 = (EntryInfo *)avl_find( eip->bei_kids, &ei, bdb_rdn_cmp );
- if ( !ei2 ) {
- DBC *cursor;
- int len = ei.bei_nrdn.bv_len;
-
- if ( BER_BVISEMPTY( ndn )) {
- *res = eip;
- return LDAP_SUCCESS;
- }
-
- ei.bei_nrdn.bv_len = ndn->bv_len -
- (ei.bei_nrdn.bv_val - ndn->bv_val);
- eip->bei_finders++;
- bdb_cache_entryinfo_unlock( eip );
-
- BDB_LOG_PRINTF( bdb->bi_dbenv, NULL, "slapd Reading %s",
- ei.bei_nrdn.bv_val );
-
- cursor = NULL;
- rc = bdb_dn2id( op, &ei.bei_nrdn, &ei, txn, &cursor );
- if (rc) {
- bdb_cache_entryinfo_lock( eip );
- eip->bei_finders--;
- if ( cursor ) cursor->c_close( cursor );
- *res = eip;
- return rc;
- }
-
- BDB_LOG_PRINTF( bdb->bi_dbenv, NULL, "slapd Read got %s(%d)",
- ei.bei_nrdn.bv_val, ei.bei_id );
-
- /* DN exists but needs to be added to cache */
- ei.bei_nrdn.bv_len = len;
- rc = bdb_entryinfo_add_internal( bdb, &ei, &ei2 );
- /* add_internal left eip and c_rwlock locked */
- eip->bei_finders--;
- ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
- if ( cursor ) cursor->c_close( cursor );
- if ( rc ) {
- *res = eip;
- return rc;
- }
- }
- bdb_cache_entryinfo_lock( ei2 );
- if ( ei2->bei_state & CACHE_ENTRY_DELETED ) {
- /* In the midst of deleting? Give it a chance to
- * complete.
- */
- bdb_cache_entryinfo_unlock( ei2 );
- bdb_cache_entryinfo_unlock( eip );
- ldap_pvt_thread_yield();
- bdb_cache_entryinfo_lock( eip );
- *res = eip;
- return DB_NOTFOUND;
- }
- bdb_cache_entryinfo_unlock( eip );
-
- eip = ei2;
-
- /* Advance to next lower RDN */
- for (ptr = ei.bei_nrdn.bv_val - 2; ptr > ndn->bv_val
- && !DN_SEPARATOR(*ptr); ptr--) /* empty */;
- if ( ptr >= ndn->bv_val ) {
- if (DN_SEPARATOR(*ptr)) ptr++;
- ei.bei_nrdn.bv_len = ei.bei_nrdn.bv_val - ptr - 1;
- ei.bei_nrdn.bv_val = ptr;
- }
- if ( ptr < ndn->bv_val ) {
- *res = eip;
- break;
- }
- }
-
- return rc;
-}
-
-#ifdef BDB_HIER
-/* Walk up the tree from a child node, looking for an ID that's already
- * been linked into the cache.
- */
-int
-hdb_cache_find_parent(
- Operation *op,
- DB_TXN *txn,
- ID id,
- EntryInfo **res )
-{
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
- EntryInfo ei, eip, *ei2 = NULL, *ein = NULL, *eir = NULL;
- int rc, add;
-
- ei.bei_id = id;
- ei.bei_kids = NULL;
- ei.bei_ckids = 0;
-
- for (;;) {
- rc = hdb_dn2id_parent( op, txn, &ei, &eip.bei_id );
- if ( rc ) break;
-
- /* Save the previous node, if any */
- ei2 = ein;
-
- /* Create a new node for the current ID */
- ein = bdb_cache_entryinfo_new( &bdb->bi_cache );
- ein->bei_id = ei.bei_id;
- ein->bei_kids = ei.bei_kids;
- ein->bei_nrdn = ei.bei_nrdn;
- ein->bei_rdn = ei.bei_rdn;
- ein->bei_ckids = ei.bei_ckids;
-#ifdef SLAP_ZONE_ALLOC
- ein->bei_bdb = bdb;
-#endif
- ei.bei_ckids = 0;
- add = 1;
-
- /* This node is not fully connected yet */
- ein->bei_state |= CACHE_ENTRY_NOT_LINKED;
-
- /* If this is the first time, save this node
- * to be returned later.
- */
- if ( eir == NULL ) {
- eir = ein;
- ein->bei_finders++;
- }
-
-again:
- /* Insert this node into the ID tree */
- ldap_pvt_thread_rdwr_wlock( &bdb->bi_cache.c_rwlock );
- if ( avl_insert( &bdb->bi_cache.c_idtree, (caddr_t)ein,
- bdb_id_cmp, bdb_id_dup_err ) ) {
- EntryInfo *eix = ein->bei_lrunext;
-
- if ( bdb_cache_entryinfo_trylock( eix )) {
- ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
- ldap_pvt_thread_yield();
- goto again;
- }
- ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
-
- /* Someone else created this node just before us.
- * Free our new copy and use the existing one.
- */
- bdb_cache_entryinfo_free( &bdb->bi_cache, ein );
-
- /* if it was the node we were looking for, just return it */
- if ( eir == ein ) {
- *res = eix;
- rc = 0;
- break;
- }
-
- ein = ei2;
- ei2 = eix;
- add = 0;
-
- /* otherwise, link up what we have and return */
- goto gotparent;
- }
-
- /* If there was a previous node, link it to this one */
- if ( ei2 ) ei2->bei_parent = ein;
-
- /* Look for this node's parent */
-par2:
- if ( eip.bei_id ) {
- ei2 = (EntryInfo *) avl_find( bdb->bi_cache.c_idtree,
- (caddr_t) &eip, bdb_id_cmp );
- } else {
- ei2 = &bdb->bi_cache.c_dntree;
- }
- if ( ei2 && bdb_cache_entryinfo_trylock( ei2 )) {
- ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
- ldap_pvt_thread_yield();
- ldap_pvt_thread_rdwr_wlock( &bdb->bi_cache.c_rwlock );
- goto par2;
- }
- if ( add )
- bdb->bi_cache.c_eiused++;
- if ( ei2 && ( ei2->bei_kids || !ei2->bei_id ))
- bdb->bi_cache.c_leaves++;
- ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
-
-gotparent:
- /* Got the parent, link in and we're done. */
- if ( ei2 ) {
- bdb_cache_entryinfo_lock( eir );
- ein->bei_parent = ei2;
-
- if ( avl_insert( &ei2->bei_kids, (caddr_t)ein, bdb_rdn_cmp,
- avl_dup_error) == 0 )
- ei2->bei_ckids++;
-
- /* Reset all the state info */
- for (ein = eir; ein != ei2; ein=ein->bei_parent)
- ein->bei_state &= ~CACHE_ENTRY_NOT_LINKED;
-
- bdb_cache_entryinfo_unlock( ei2 );
- eir->bei_finders--;
-
- *res = eir;
- break;
- }
- ei.bei_kids = NULL;
- ei.bei_id = eip.bei_id;
- ei.bei_ckids = 1;
- avl_insert( &ei.bei_kids, (caddr_t)ein, bdb_rdn_cmp,
- avl_dup_error );
- }
- return rc;
-}
-
-/* Used by hdb_dn2idl when loading the EntryInfo for all the children
- * of a given node
- */
-int hdb_cache_load(
- struct bdb_info *bdb,
- EntryInfo *ei,
- EntryInfo **res )
-{
- EntryInfo *ei2;
- int rc;
-
- /* See if we already have this one */
- bdb_cache_entryinfo_lock( ei->bei_parent );
- ei2 = (EntryInfo *)avl_find( ei->bei_parent->bei_kids, ei, bdb_rdn_cmp );
- bdb_cache_entryinfo_unlock( ei->bei_parent );
-
- if ( !ei2 ) {
- /* Not found, add it */
- struct berval bv;
-
- /* bei_rdn was not malloc'd before, do it now */
- ber_dupbv( &bv, &ei->bei_rdn );
- ei->bei_rdn = bv;
-
- rc = bdb_entryinfo_add_internal( bdb, ei, res );
- bdb_cache_entryinfo_unlock( ei->bei_parent );
- ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
- } else {
- /* Found, return it */
- *res = ei2;
- return 0;
- }
- return rc;
-}
-#endif
-
-/* This is best-effort only. If all entries in the cache are
- * busy, they will all be kept. This is unlikely to happen
- * unless the cache is very much smaller than the working set.
- */
-static void
-bdb_cache_lru_purge( struct bdb_info *bdb )
-{
- DB_LOCK lock, *lockp;
- EntryInfo *elru, *elnext = NULL;
- int islocked;
- ID eicount, ecount;
- ID count, efree, eifree = 0;
-#ifdef LDAP_DEBUG
- int iter;
-#endif
-
- /* Wait for the mutex; we're the only one trying to purge. */
- ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_lru_mutex );
-
- if ( bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize ) {
- efree = bdb->bi_cache.c_cursize - bdb->bi_cache.c_maxsize;
- efree += bdb->bi_cache.c_minfree;
- } else {
- efree = 0;
- }
-
- /* maximum number of EntryInfo leaves to cache. In slapcat
- * we always free all leaf nodes.
- */
-
- if ( slapMode & SLAP_TOOL_READONLY ) {
- eifree = bdb->bi_cache.c_leaves;
- } else if ( bdb->bi_cache.c_eimax &&
- bdb->bi_cache.c_leaves > bdb->bi_cache.c_eimax ) {
- eifree = bdb->bi_cache.c_minfree * 10;
- if ( eifree >= bdb->bi_cache.c_leaves )
- eifree /= 2;
- }
-
- if ( !efree && !eifree ) {
- ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_lru_mutex );
- bdb->bi_cache.c_purging = 0;
- return;
- }
-
- if ( bdb->bi_cache.c_txn ) {
- lockp = &lock;
- } else {
- lockp = NULL;
- }
-
- count = 0;
- eicount = 0;
- ecount = 0;
-#ifdef LDAP_DEBUG
- iter = 0;
-#endif
-
- /* Look for an unused entry to remove */
- for ( elru = bdb->bi_cache.c_lruhead; elru; elru = elnext ) {
- elnext = elru->bei_lrunext;
-
- if ( bdb_cache_entryinfo_trylock( elru ))
- goto bottom;
-
- /* This flag implements the clock replacement behavior */
- if ( elru->bei_state & ( CACHE_ENTRY_REFERENCED )) {
- elru->bei_state &= ~CACHE_ENTRY_REFERENCED;
- bdb_cache_entryinfo_unlock( elru );
- goto bottom;
- }
-
- /* If this node is in the process of linking into the cache,
- * or this node is being deleted, skip it.
- */
- if (( elru->bei_state & ( CACHE_ENTRY_NOT_LINKED |
- CACHE_ENTRY_DELETED | CACHE_ENTRY_LOADING |
- CACHE_ENTRY_ONELEVEL )) ||
- elru->bei_finders > 0 ) {
- bdb_cache_entryinfo_unlock( elru );
- goto bottom;
- }
-
- if ( bdb_cache_entryinfo_trylock( elru->bei_parent )) {
- bdb_cache_entryinfo_unlock( elru );
- goto bottom;
- }
-
- /* entryinfo is locked */
- islocked = 1;
-
- /* If we can successfully writelock it, then
- * the object is idle.
- */
- if ( bdb_cache_entry_db_lock( bdb,
- bdb->bi_cache.c_txn, elru, 1, 1, lockp ) == 0 ) {
-
- /* Free entry for this node if it's present */
- if ( elru->bei_e ) {
- ecount++;
-
- /* the cache may have gone over the limit while we
- * weren't looking, so double check.
- */
- if ( !efree && ecount > bdb->bi_cache.c_maxsize )
- efree = bdb->bi_cache.c_minfree;
-
- if ( count < efree ) {
- elru->bei_e->e_private = NULL;
-#ifdef SLAP_ZONE_ALLOC
- bdb_entry_return( bdb, elru->bei_e, elru->bei_zseq );
-#else
- bdb_entry_return( elru->bei_e );
-#endif
- elru->bei_e = NULL;
- count++;
- } else {
- /* Keep this node cached, skip to next */
- bdb_cache_entry_db_unlock( bdb, lockp );
- goto next;
- }
- }
- bdb_cache_entry_db_unlock( bdb, lockp );
-
- /*
- * If it is a leaf node, and we're over the limit, free it.
- */
- if ( elru->bei_kids ) {
- /* Drop from list, we ignore it... */
- LRU_DEL( &bdb->bi_cache, elru );
- } else if ( eicount < eifree ) {
- /* Too many leaf nodes, free this one */
- bdb_cache_delete_internal( &bdb->bi_cache, elru, 0 );
- bdb_cache_delete_cleanup( &bdb->bi_cache, elru );
- islocked = 0;
- eicount++;
- } /* Leave on list until we need to free it */
- }
-
-next:
- if ( islocked ) {
- bdb_cache_entryinfo_unlock( elru );
- bdb_cache_entryinfo_unlock( elru->bei_parent );
- }
-
- if ( count >= efree && eicount >= eifree )
- break;
-bottom:
- if ( elnext == bdb->bi_cache.c_lruhead )
- break;
-#ifdef LDAP_DEBUG
- iter++;
-#endif
- }
-
- if ( count || ecount > bdb->bi_cache.c_cursize ) {
- ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_count_mutex );
- /* HACK: we seem to be losing track, fix up now */
- if ( ecount > bdb->bi_cache.c_cursize )
- bdb->bi_cache.c_cursize = ecount;
- bdb->bi_cache.c_cursize -= count;
- ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_count_mutex );
- }
- bdb->bi_cache.c_lruhead = elnext;
- ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_lru_mutex );
- bdb->bi_cache.c_purging = 0;
-}
-
-/*
- * cache_find_id - find an entry in the cache, given id.
- * The entry is locked for Read upon return. Call with flag ID_LOCKED if
- * the supplied *eip was already locked.
- */
-
-int
-bdb_cache_find_id(
- Operation *op,
- DB_TXN *tid,
- ID id,
- EntryInfo **eip,
- int flag,
- DB_LOCK *lock )
-{
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
- Entry *ep = NULL;
- int rc = 0, load = 0;
- EntryInfo ei = { 0 };
-
- ei.bei_id = id;
-
-#ifdef SLAP_ZONE_ALLOC
- slap_zh_rlock(bdb->bi_cache.c_zctx);
-#endif
- /* If we weren't given any info, see if we have it already cached */
- if ( !*eip ) {
-again: ldap_pvt_thread_rdwr_rlock( &bdb->bi_cache.c_rwlock );
- *eip = (EntryInfo *) avl_find( bdb->bi_cache.c_idtree,
- (caddr_t) &ei, bdb_id_cmp );
- if ( *eip ) {
- /* If the lock attempt fails, the info is in use */
- if ( bdb_cache_entryinfo_trylock( *eip )) {
- int del = (*eip)->bei_state & CACHE_ENTRY_DELETED;
- ldap_pvt_thread_rdwr_runlock( &bdb->bi_cache.c_rwlock );
- /* If this node is being deleted, treat
- * as if the delete has already finished
- */
- if ( del ) {
- return DB_NOTFOUND;
- }
- /* otherwise, wait for the info to free up */
- ldap_pvt_thread_yield();
- goto again;
- }
- /* If this info isn't hooked up to its parent yet,
- * unlock and wait for it to be fully initialized
- */
- if ( (*eip)->bei_state & CACHE_ENTRY_NOT_LINKED ) {
- bdb_cache_entryinfo_unlock( *eip );
- ldap_pvt_thread_rdwr_runlock( &bdb->bi_cache.c_rwlock );
- ldap_pvt_thread_yield();
- goto again;
- }
- flag |= ID_LOCKED;
- }
- ldap_pvt_thread_rdwr_runlock( &bdb->bi_cache.c_rwlock );
- }
-
- /* See if the ID exists in the database; add it to the cache if so */
- if ( !*eip ) {
-#ifndef BDB_HIER
- rc = bdb_id2entry( op->o_bd, tid, id, &ep );
- if ( rc == 0 ) {
- rc = bdb_cache_find_ndn( op, tid,
- &ep->e_nname, eip );
- if ( *eip ) flag |= ID_LOCKED;
- if ( rc ) {
- ep->e_private = NULL;
-#ifdef SLAP_ZONE_ALLOC
- bdb_entry_return( bdb, ep, (*eip)->bei_zseq );
-#else
- bdb_entry_return( ep );
-#endif
- ep = NULL;
- }
- }
-#else
- rc = hdb_cache_find_parent(op, tid, id, eip );
- if ( rc == 0 ) flag |= ID_LOCKED;
-#endif
- }
-
- /* Ok, we found the info, do we have the entry? */
- if ( rc == 0 ) {
- if ( !( flag & ID_LOCKED )) {
- bdb_cache_entryinfo_lock( *eip );
- flag |= ID_LOCKED;
- }
-
- if ( (*eip)->bei_state & CACHE_ENTRY_DELETED ) {
- rc = DB_NOTFOUND;
- } else {
- (*eip)->bei_finders++;
- (*eip)->bei_state |= CACHE_ENTRY_REFERENCED;
- if ( flag & ID_NOENTRY ) {
- bdb_cache_entryinfo_unlock( *eip );
- return 0;
- }
- /* Make sure only one thread tries to load the entry */
-load1:
-#ifdef SLAP_ZONE_ALLOC
- if ((*eip)->bei_e && !slap_zn_validate(
- bdb->bi_cache.c_zctx, (*eip)->bei_e, (*eip)->bei_zseq)) {
- (*eip)->bei_e = NULL;
- (*eip)->bei_zseq = 0;
- }
-#endif
- if ( !(*eip)->bei_e && !((*eip)->bei_state & CACHE_ENTRY_LOADING)) {
- load = 1;
- (*eip)->bei_state |= CACHE_ENTRY_LOADING;
- flag |= ID_CHKPURGE;
- }
-
- if ( !load ) {
- /* Clear the uncached state if we are not
- * loading it, i.e it is already cached or
- * another thread is currently loading it.
- */
- if ( (*eip)->bei_state & CACHE_ENTRY_NOT_CACHED ) {
- (*eip)->bei_state ^= CACHE_ENTRY_NOT_CACHED;
- flag |= ID_CHKPURGE;
- }
- }
-
- if ( flag & ID_LOCKED ) {
- bdb_cache_entryinfo_unlock( *eip );
- flag ^= ID_LOCKED;
- }
- rc = bdb_cache_entry_db_lock( bdb, tid, *eip, load, 0, lock );
- if ( (*eip)->bei_state & CACHE_ENTRY_DELETED ) {
- rc = DB_NOTFOUND;
- bdb_cache_entry_db_unlock( bdb, lock );
- bdb_cache_entryinfo_lock( *eip );
- (*eip)->bei_finders--;
- bdb_cache_entryinfo_unlock( *eip );
- } else if ( rc == 0 ) {
- if ( load ) {
- if ( !ep) {
- rc = bdb_id2entry( op->o_bd, tid, id, &ep );
- }
- if ( rc == 0 ) {
- ep->e_private = *eip;
-#ifdef BDB_HIER
- while ( (*eip)->bei_state & CACHE_ENTRY_NOT_LINKED )
- ldap_pvt_thread_yield();
- bdb_fix_dn( ep, 0 );
-#endif
- bdb_cache_entryinfo_lock( *eip );
-
- (*eip)->bei_e = ep;
-#ifdef SLAP_ZONE_ALLOC
- (*eip)->bei_zseq = *((ber_len_t *)ep - 2);
-#endif
- ep = NULL;
- if ( flag & ID_NOCACHE ) {
- /* Set the cached state only if no other thread
- * found the info while we were loading the entry.
- */
- if ( (*eip)->bei_finders == 1 ) {
- (*eip)->bei_state |= CACHE_ENTRY_NOT_CACHED;
- flag ^= ID_CHKPURGE;
- }
- }
- bdb_cache_entryinfo_unlock( *eip );
- bdb_cache_lru_link( bdb, *eip );
- }
- if ( rc == 0 ) {
- /* If we succeeded, downgrade back to a readlock. */
- rc = bdb_cache_entry_db_relock( bdb, tid,
- *eip, 0, 0, lock );
- } else {
- /* Otherwise, release the lock. */
- bdb_cache_entry_db_unlock( bdb, lock );
- }
- } else if ( !(*eip)->bei_e ) {
- /* Some other thread is trying to load the entry,
- * wait for it to finish.
- */
- bdb_cache_entry_db_unlock( bdb, lock );
- bdb_cache_entryinfo_lock( *eip );
- flag |= ID_LOCKED;
- goto load1;
-#ifdef BDB_HIER
- } else {
- /* Check for subtree renames
- */
- rc = bdb_fix_dn( (*eip)->bei_e, 1 );
- if ( rc ) {
- bdb_cache_entry_db_relock( bdb,
- tid, *eip, 1, 0, lock );
- /* check again in case other modifier did it already */
- if ( bdb_fix_dn( (*eip)->bei_e, 1 ) )
- rc = bdb_fix_dn( (*eip)->bei_e, 2 );
- bdb_cache_entry_db_relock( bdb,
- tid, *eip, 0, 0, lock );
- }
-#endif
- }
- bdb_cache_entryinfo_lock( *eip );
- (*eip)->bei_finders--;
- if ( load )
- (*eip)->bei_state ^= CACHE_ENTRY_LOADING;
- bdb_cache_entryinfo_unlock( *eip );
- }
- }
- }
- if ( flag & ID_LOCKED ) {
- bdb_cache_entryinfo_unlock( *eip );
- }
- if ( ep ) {
- ep->e_private = NULL;
-#ifdef SLAP_ZONE_ALLOC
- bdb_entry_return( bdb, ep, (*eip)->bei_zseq );
-#else
- bdb_entry_return( ep );
-#endif
- }
- if ( rc == 0 ) {
- int purge = 0;
-
- if (( flag & ID_CHKPURGE ) || bdb->bi_cache.c_eimax ) {
- ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_count_mutex );
- if ( flag & ID_CHKPURGE ) {
- bdb->bi_cache.c_cursize++;
- if ( !bdb->bi_cache.c_purging && bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize ) {
- purge = 1;
- bdb->bi_cache.c_purging = 1;
- }
- } else if ( !bdb->bi_cache.c_purging && bdb->bi_cache.c_eimax && bdb->bi_cache.c_leaves > bdb->bi_cache.c_eimax ) {
- purge = 1;
- bdb->bi_cache.c_purging = 1;
- }
- ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_count_mutex );
- }
- if ( purge )
- bdb_cache_lru_purge( bdb );
- }
-
-#ifdef SLAP_ZONE_ALLOC
- if (rc == 0 && (*eip)->bei_e) {
- slap_zn_rlock(bdb->bi_cache.c_zctx, (*eip)->bei_e);
- }
- slap_zh_runlock(bdb->bi_cache.c_zctx);
-#endif
- return rc;
-}
-
-int
-bdb_cache_children(
- Operation *op,
- DB_TXN *txn,
- Entry *e )
-{
- int rc;
-
- if ( BEI(e)->bei_kids ) {
- return 0;
- }
- if ( BEI(e)->bei_state & CACHE_ENTRY_NO_KIDS ) {
- return DB_NOTFOUND;
- }
- rc = bdb_dn2id_children( op, txn, e );
- if ( rc == DB_NOTFOUND ) {
- BEI(e)->bei_state |= CACHE_ENTRY_NO_KIDS | CACHE_ENTRY_NO_GRANDKIDS;
- }
- return rc;
-}
-
-/* Update the cache after a successful database Add. */
-int
-bdb_cache_add(
- struct bdb_info *bdb,
- EntryInfo *eip,
- Entry *e,
- struct berval *nrdn,
- DB_TXN *txn,
- DB_LOCK *lock )
-{
- EntryInfo *new, ei;
- int rc, purge = 0;
-#ifdef BDB_HIER
- struct berval rdn = e->e_name;
-#endif
-
- ei.bei_id = e->e_id;
- ei.bei_parent = eip;
- ei.bei_nrdn = *nrdn;
- ei.bei_lockpad = 0;
-
-#if 0
- /* Lock this entry so that bdb_add can run to completion.
- * It can only fail if BDB has run out of lock resources.
- */
- rc = bdb_cache_entry_db_lock( bdb, txn, &ei, 0, 0, lock );
- if ( rc ) {
- bdb_cache_entryinfo_unlock( eip );
- return rc;
- }
-#endif
-
-#ifdef BDB_HIER
- if ( nrdn->bv_len != e->e_nname.bv_len ) {
- char *ptr = ber_bvchr( &rdn, ',' );
- assert( ptr != NULL );
- rdn.bv_len = ptr - rdn.bv_val;
- }
- ber_dupbv( &ei.bei_rdn, &rdn );
- if ( eip->bei_dkids ) eip->bei_dkids++;
-#endif
-
- if (eip->bei_parent) {
- bdb_cache_entryinfo_lock( eip->bei_parent );
- eip->bei_parent->bei_state &= ~CACHE_ENTRY_NO_GRANDKIDS;
- bdb_cache_entryinfo_unlock( eip->bei_parent );
- }
-
- rc = bdb_entryinfo_add_internal( bdb, &ei, &new );
- /* bdb_csn_commit can cause this when adding the database root entry */
- if ( new->bei_e ) {
- new->bei_e->e_private = NULL;
-#ifdef SLAP_ZONE_ALLOC
- bdb_entry_return( bdb, new->bei_e, new->bei_zseq );
-#else
- bdb_entry_return( new->bei_e );
-#endif
- }
- new->bei_e = e;
- e->e_private = new;
- new->bei_state |= CACHE_ENTRY_NO_KIDS | CACHE_ENTRY_NO_GRANDKIDS;
- eip->bei_state &= ~CACHE_ENTRY_NO_KIDS;
- bdb_cache_entryinfo_unlock( eip );
-
- ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
- ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_count_mutex );
- ++bdb->bi_cache.c_cursize;
- if ( bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize &&
- !bdb->bi_cache.c_purging ) {
- purge = 1;
- bdb->bi_cache.c_purging = 1;
- }
- ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_count_mutex );
-
- new->bei_finders = 1;
- bdb_cache_lru_link( bdb, new );
-
- if ( purge )
- bdb_cache_lru_purge( bdb );
-
- return rc;
-}
-
-void bdb_cache_deref(
- EntryInfo *ei
- )
-{
- bdb_cache_entryinfo_lock( ei );
- ei->bei_finders--;
- bdb_cache_entryinfo_unlock( ei );
-}
-
-int
-bdb_cache_modify(
- struct bdb_info *bdb,
- Entry *e,
- Attribute *newAttrs,
- DB_TXN *txn,
- DB_LOCK *lock )
-{
- EntryInfo *ei = BEI(e);
- int rc;
- /* Get write lock on data */
- rc = bdb_cache_entry_db_relock( bdb, txn, ei, 1, 0, lock );
-
- /* If we've done repeated mods on a cached entry, then e_attrs
- * is no longer contiguous with the entry, and must be freed.
- */
- if ( ! rc ) {
- if ( (void *)e->e_attrs != (void *)(e+1) ) {
- attrs_free( e->e_attrs );
- }
- e->e_attrs = newAttrs;
- }
- return rc;
-}
-
-/*
- * Change the rdn in the entryinfo. Also move to a new parent if needed.
- */
-int
-bdb_cache_modrdn(
- struct bdb_info *bdb,
- Entry *e,
- struct berval *nrdn,
- Entry *new,
- EntryInfo *ein,
- DB_TXN *txn,
- DB_LOCK *lock )
-{
- EntryInfo *ei = BEI(e), *pei;
- int rc;
-#ifdef BDB_HIER
- struct berval rdn;
-#endif
-
- /* Get write lock on data */
- rc = bdb_cache_entry_db_relock( bdb, txn, ei, 1, 0, lock );
- if ( rc ) return rc;
-
- /* If we've done repeated mods on a cached entry, then e_attrs
- * is no longer contiguous with the entry, and must be freed.
- */
- if ( (void *)e->e_attrs != (void *)(e+1) && e->e_attrs != new->e_attrs ) {
- 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 );
-
- /* 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" );
-
- 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 );
-
- return rc;
- }
- } else {
- *txn = data;
- }
- return 0;
-}
+++ /dev/null
-/* compare.c - bdb backend compare routine */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "back-bdb.h"
-
-int
-bdb_compare( Operation *op, SlapReply *rs )
-{
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
- Entry *e = NULL;
- EntryInfo *ei;
- int manageDSAit = get_manageDSAit( op );
-
- DB_TXN *rtxn;
- DB_LOCK lock;
-
- rs->sr_err = bdb_reader_get(op, bdb->bi_dbenv, &rtxn);
- switch(rs->sr_err) {
- case 0:
- break;
- default:
- send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
- return rs->sr_err;
- }
-
-dn2entry_retry:
- /* get entry */
- rs->sr_err = bdb_dn2entry( op, rtxn, &op->o_req_ndn, &ei, 1,
- &lock );
-
- switch( rs->sr_err ) {
- case DB_NOTFOUND:
- case 0:
- break;
- case LDAP_BUSY:
- rs->sr_text = "ldap server busy";
- goto return_results;
- case DB_LOCK_DEADLOCK:
- case DB_LOCK_NOTGRANTED:
- goto dn2entry_retry;
- default:
- rs->sr_err = LDAP_OTHER;
- rs->sr_text = "internal error";
- goto return_results;
- }
-
- e = ei->bei_e;
- if ( rs->sr_err == DB_NOTFOUND ) {
- if ( e != NULL ) {
- /* return referral only if "disclose" is granted on the object */
- if ( ! access_allowed( op, e, slap_schema.si_ad_entry,
- NULL, ACL_DISCLOSE, NULL ) )
- {
- rs->sr_err = LDAP_NO_SUCH_OBJECT;
-
- } else {
- rs->sr_matched = ch_strdup( e->e_dn );
- rs->sr_ref = is_entry_referral( e )
- ? get_entry_referrals( op, e )
- : NULL;
- rs->sr_err = LDAP_REFERRAL;
- }
-
- bdb_cache_return_entry_r( bdb, e, &lock );
- e = NULL;
-
- } else {
- rs->sr_ref = referral_rewrite( default_referral,
- NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
- rs->sr_err = rs->sr_ref ? LDAP_REFERRAL : LDAP_NO_SUCH_OBJECT;
- }
-
- send_ldap_result( op, rs );
-
- ber_bvarray_free( rs->sr_ref );
- free( (char *)rs->sr_matched );
- rs->sr_ref = NULL;
- rs->sr_matched = NULL;
-
- goto done;
- }
-
- if (!manageDSAit && is_entry_referral( e ) ) {
- /* return referral only if "disclose" is granted on the object */
- if ( !access_allowed( op, e, slap_schema.si_ad_entry,
- NULL, ACL_DISCLOSE, NULL ) )
- {
- rs->sr_err = LDAP_NO_SUCH_OBJECT;
- } else {
- /* entry is a referral, don't allow compare */
- rs->sr_ref = get_entry_referrals( op, e );
- rs->sr_err = LDAP_REFERRAL;
- rs->sr_matched = e->e_name.bv_val;
- }
-
- Debug( LDAP_DEBUG_TRACE, "entry is referral\n" );
-
- 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;
-}
+++ /dev/null
-/* config.c - bdb backend configuration file routine */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/ctype.h>
-#include <ac/string.h>
-#include <ac/errno.h>
-
-#include "back-bdb.h"
-
-#include "config.h"
-
-#include "lutil.h"
-#include "ldap_rq.h"
-
-#ifdef DB_DIRTY_READ
-# define SLAP_BDB_ALLOW_DIRTY_READ
-#endif
-
-#define bdb_cf_gen BDB_SYMBOL(cf_gen)
-#define bdb_cf_cleanup BDB_SYMBOL(cf_cleanup)
-#define bdb_checkpoint BDB_SYMBOL(checkpoint)
-#define bdb_online_index BDB_SYMBOL(online_index)
-
-static ConfigDriver bdb_cf_gen;
-
-enum {
- BDB_CHKPT = 1,
- BDB_CONFIG,
- BDB_CRYPTFILE,
- BDB_CRYPTKEY,
- BDB_DIRECTORY,
- BDB_NOSYNC,
- BDB_DIRTYR,
- BDB_INDEX,
- BDB_LOCKD,
- BDB_SSTACK,
- BDB_MODE,
- BDB_PGSIZE,
- BDB_CHECKSUM
-};
-
-static ConfigTable bdbcfg[] = {
- { "directory", "dir", 2, 2, 0, ARG_STRING|ARG_MAGIC|BDB_DIRECTORY,
- bdb_cf_gen, "( OLcfgDbAt:0.1 NAME 'olcDbDirectory' "
- "DESC 'Directory for database content' "
- "EQUALITY caseIgnoreMatch "
- "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
- { "cachefree", "size", 2, 2, 0, ARG_ULONG|ARG_OFFSET,
- (void *)offsetof(struct bdb_info, bi_cache.c_minfree),
- "( OLcfgDbAt:1.11 NAME 'olcDbCacheFree' "
- "DESC 'Number of extra entries to free when max is reached' "
- "EQUALITY integerMatch "
- "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' "
- "EQUALITY integerMatch "
- "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
- { "checkpoint", "kbyte> <min", 3, 3, 0, ARG_MAGIC|BDB_CHKPT,
- bdb_cf_gen, "( OLcfgDbAt:1.2 NAME 'olcDbCheckpoint' "
- "DESC 'Database checkpoint interval in kbytes and minutes' "
- "EQUALITY caseIgnoreMatch "
- "SYNTAX OMsDirectoryString SINGLE-VALUE )",NULL, NULL },
- { "checksum", NULL, 1, 2, 0, ARG_ON_OFF|ARG_MAGIC|BDB_CHECKSUM,
- bdb_cf_gen, "( OLcfgDbAt:1.16 NAME 'olcDbChecksum' "
- "DESC 'Enable database checksum validation' "
- "EQUALITY booleanMatch "
- "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
- { "cryptfile", "file", 2, 2, 0, ARG_STRING|ARG_MAGIC|BDB_CRYPTFILE,
- bdb_cf_gen, "( OLcfgDbAt:1.13 NAME 'olcDbCryptFile' "
- "DESC 'Pathname of file containing the DB encryption key' "
- "EQUALITY caseExactMatch "
- "SYNTAX OMsDirectoryString SINGLE-VALUE )",NULL, NULL },
- { "cryptkey", "key", 2, 2, 0, ARG_BERVAL|ARG_MAGIC|BDB_CRYPTKEY,
- bdb_cf_gen, "( OLcfgDbAt:1.14 NAME 'olcDbCryptKey' "
- "DESC 'DB encryption key' "
- "EQUALITY octetStringMatch "
- "SYNTAX OMsOctetString SINGLE-VALUE )",NULL, NULL },
- { "dbconfig", "DB_CONFIG setting", 1, 0, 0, ARG_MAGIC|BDB_CONFIG,
- bdb_cf_gen, "( OLcfgDbAt:1.3 NAME 'olcDbConfig' "
- "DESC 'BerkeleyDB DB_CONFIG configuration directives' "
- "EQUALITY caseIgnoreIA5Match "
- "SYNTAX OMsIA5String X-ORDERED 'VALUES' )", NULL, NULL },
- { "dbnosync", NULL, 1, 2, 0, ARG_ON_OFF|ARG_MAGIC|BDB_NOSYNC,
- bdb_cf_gen, "( OLcfgDbAt:1.4 NAME 'olcDbNoSync' "
- "DESC 'Disable synchronous database writes' "
- "EQUALITY booleanMatch "
- "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
- { "dbpagesize", "db> <size", 3, 3, 0, ARG_MAGIC|BDB_PGSIZE,
- bdb_cf_gen, "( OLcfgDbAt:1.15 NAME 'olcDbPageSize' "
- "DESC 'Page size of specified DB, in Kbytes' "
- "EQUALITY caseExactMatch "
- "SYNTAX OMsDirectoryString )", NULL, NULL },
- { "dirtyread", NULL, 1, 2, 0,
-#ifdef SLAP_BDB_ALLOW_DIRTY_READ
- ARG_ON_OFF|ARG_MAGIC|BDB_DIRTYR, bdb_cf_gen,
-#else
- ARG_IGNORED, NULL,
-#endif
- "( OLcfgDbAt:1.5 NAME 'olcDbDirtyRead' "
- "DESC 'Allow reads of uncommitted data' "
- "EQUALITY booleanMatch "
- "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
- { "dncachesize", "size", 2, 2, 0, ARG_ULONG|ARG_OFFSET,
- (void *)offsetof(struct bdb_info, bi_cache.c_eimax),
- "( OLcfgDbAt:1.12 NAME 'olcDbDNcacheSize' "
- "DESC 'DN cache size' "
- "EQUALITY integerMatch "
- "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
- { "idlcachesize", "size", 2, 2, 0, ARG_ULONG|ARG_OFFSET,
- (void *)offsetof(struct bdb_info, bi_idl_cache_max_size),
- "( OLcfgDbAt:1.6 NAME 'olcDbIDLcacheSize' "
- "DESC 'IDL cache size in IDLs' "
- "EQUALITY integerMatch "
- "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
- { "index", "attr> <[pres,eq,approx,sub]", 2, 3, 0, ARG_MAGIC|BDB_INDEX,
- bdb_cf_gen, "( OLcfgDbAt:0.2 NAME 'olcDbIndex' "
- "DESC 'Attribute index parameters' "
- "EQUALITY caseIgnoreMatch "
- "SYNTAX OMsDirectoryString )", NULL, NULL },
- { "linearindex", NULL, 1, 2, 0, ARG_ON_OFF|ARG_OFFSET,
- (void *)offsetof(struct bdb_info, bi_linear_index),
- "( OLcfgDbAt:1.7 NAME 'olcDbLinearIndex' "
- "DESC 'Index attributes one at a time' "
- "EQUALITY booleanMatch "
- "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' "
- "EQUALITY caseIgnoreMatch "
- "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' "
- "EQUALITY caseIgnoreMatch "
- "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' "
- "EQUALITY integerMatch "
- "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' "
- "EQUALITY integerMatch "
- "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) );
- 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 );
- 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 );
- return -1;
- }
-
- if ( bdb->bi_dbenv_home )
- ch_free( bdb->bi_dbenv_home );
- bdb->bi_dbenv_home = c->value_string;
-
- /* See if a DB_CONFIG file already exists here */
- if ( bdb->bi_db_config_path )
- ch_free( bdb->bi_db_config_path );
- bdb->bi_db_config_path = ch_malloc( len +
- STRLENOF(LDAP_DIRSEP) + STRLENOF("DB_CONFIG") + 1 );
- ptr = lutil_strcopy( bdb->bi_db_config_path, bdb->bi_dbenv_home );
- *ptr++ = LDAP_DIRSEP[0];
- strcpy( ptr, "DB_CONFIG" );
-
- f = fopen( bdb->bi_db_config_path, "r" );
- if ( f ) {
- bdb->bi_flags |= BDB_HAS_CONFIG;
- fclose(f);
- }
- }
- break;
-
- case BDB_NOSYNC:
- if ( c->value_int )
- bdb->bi_dbenv_xflags |= DB_TXN_NOSYNC;
- else
- bdb->bi_dbenv_xflags &= ~DB_TXN_NOSYNC;
- if ( bdb->bi_flags & BDB_IS_OPEN ) {
- bdb->bi_dbenv->set_flags( bdb->bi_dbenv, DB_TXN_NOSYNC,
- c->value_int );
- }
- break;
-
- case BDB_CHECKSUM:
- if ( c->value_int )
- bdb->bi_flags |= BDB_CHKSUM;
- else
- bdb->bi_flags &= ~BDB_CHKSUM;
- break;
-
- case BDB_INDEX:
- rc = bdb_attr_index_config( bdb, c->fname, c->lineno,
- c->argc - 1, &c->argv[1], &c->reply);
-
- if( rc != LDAP_SUCCESS ) return 1;
- if (( bdb->bi_flags & BDB_IS_OPEN ) && !bdb->bi_index_task ) {
- /* Start the task as soon as we finish here. Set a long
- * interval (10 hours) so that it only gets scheduled once.
- */
- if ( c->be->be_suffix == NULL || BER_BVISNULL( &c->be->be_suffix[0] ) ) {
- fprintf( stderr, "%s: "
- "\"index\" must occur after \"suffix\".\n",
- c->log );
- return 1;
- }
- ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
- bdb->bi_index_task = ldap_pvt_runqueue_insert( &slapd_rq, 36000,
- bdb_online_index, c->be,
- LDAP_XSTRING(bdb_online_index), c->be->be_suffix[0].bv_val );
- ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
- }
- break;
-
- case BDB_LOCKD:
- rc = verb_to_mask( c->argv[1], bdb_lockd );
- if ( BER_BVISNULL(&bdb_lockd[rc].word) ) {
- fprintf( stderr, "%s: "
- "bad policy (%s) in \"lockDetect <policy>\" line\n",
- c->log, c->argv[1] );
- return 1;
- }
- bdb->bi_lock_detect = (u_int32_t)rc;
- break;
-
- case BDB_SSTACK:
- if ( c->value_int < MINIMUM_SEARCH_STACK_DEPTH ) {
- fprintf( stderr,
- "%s: depth %d too small, using %d\n",
- c->log, c->value_int, MINIMUM_SEARCH_STACK_DEPTH );
- c->value_int = MINIMUM_SEARCH_STACK_DEPTH;
- }
- bdb->bi_search_stack_depth = c->value_int;
- break;
-
- case BDB_PGSIZE: {
- struct bdb_db_pgsize *ps, **prev;
- int i, s;
-
- s = atoi(c->argv[2]);
- if ( s < 1 || s > 64 ) {
- snprintf( c->cr_msg, sizeof( c->cr_msg ),
- "%s: size must be > 0 and <= 64: %d",
- c->log, s );
- Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg );
- 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;
-}
+++ /dev/null
-/* dbcache.c - manage cache of open databases */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/errno.h>
-#include <ac/socket.h>
-#include <ac/string.h>
-#include <ac/time.h>
-#include <sys/stat.h>
-
-#include "slap.h"
-#include "back-bdb.h"
-#include "lutil_hash.h"
-
-#ifdef BDB_INDEX_USE_HASH
-/* Pass-thru hash function. Since the indexer is already giving us hash
- * values as keys, we don't need BDB to re-hash them.
- */
-static u_int32_t
-bdb_db_hash(
- DB *db,
- const void *bytes,
- u_int32_t length
-)
-{
- u_int32_t ret = 0;
- unsigned char *dst = (unsigned char *)&ret;
- const unsigned char *src = (const unsigned char *)bytes;
-
- if ( length > sizeof(u_int32_t) )
- length = sizeof(u_int32_t);
-
- while ( length ) {
- *dst++ = *src++;
- length--;
- }
- return ret;
-}
-#define BDB_INDEXTYPE DB_HASH
-#else
-#define BDB_INDEXTYPE DB_BTREE
-#endif
-
-/* If a configured size is found, return it, otherwise return 0 */
-int
-bdb_db_findsize(
- struct bdb_info *bdb,
- struct berval *name
-)
-{
- struct bdb_db_pgsize *bp;
- int rc;
-
- for ( bp = bdb->bi_pagesizes; bp; bp=bp->bdp_next ) {
- rc = strncmp( name->bv_val, bp->bdp_name.bv_val, name->bv_len );
- if ( !rc ) {
- if ( name->bv_len == bp->bdp_name.bv_len )
- return bp->bdp_size;
- if ( name->bv_len < bp->bdp_name.bv_len &&
- bp->bdp_name.bv_val[name->bv_len] == '.' )
- return bp->bdp_size;
- }
- }
- return 0;
-}
-
-int
-bdb_db_cache(
- Backend *be,
- struct berval *name,
- DB **dbout )
-{
- int i, flags;
- int rc;
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
- struct bdb_db_info *db;
- char *file;
-
- *dbout = NULL;
-
- for( i=BDB_NDB; i < bdb->bi_ndatabases; i++ ) {
- if( !ber_bvcmp( &bdb->bi_databases[i]->bdi_name, name) ) {
- *dbout = bdb->bi_databases[i]->bdi_db;
- return 0;
- }
- }
-
- ldap_pvt_thread_mutex_lock( &bdb->bi_database_mutex );
-
- /* check again! may have been added by another thread */
- for( i=BDB_NDB; i < bdb->bi_ndatabases; i++ ) {
- if( !ber_bvcmp( &bdb->bi_databases[i]->bdi_name, name) ) {
- *dbout = bdb->bi_databases[i]->bdi_db;
- ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
- return 0;
- }
- }
-
- if( i >= BDB_INDICES ) {
- ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
- return -1;
- }
-
- db = (struct bdb_db_info *) ch_calloc(1, sizeof(struct bdb_db_info));
-
- ber_dupbv( &db->bdi_name, name );
-
- rc = db_create( &db->bdi_db, bdb->bi_dbenv, 0 );
- if( rc != 0 ) {
- Debug( LDAP_DEBUG_ANY,
- "bdb_db_cache: db_create(%s) failed: %s (%d)\n",
- bdb->bi_dbenv_home, db_strerror(rc), rc );
- ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
- ch_free( db );
- return rc;
- }
-
- if( !BER_BVISNULL( &bdb->bi_db_crypt_key )) {
- rc = db->bdi_db->set_flags( db->bdi_db, DB_ENCRYPT );
- if ( rc ) {
- Debug( LDAP_DEBUG_ANY,
- "bdb_db_cache: db set_flags(DB_ENCRYPT)(%s) failed: %s (%d)\n",
- bdb->bi_dbenv_home, db_strerror(rc), rc );
- ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
- db->bdi_db->close( db->bdi_db, 0 );
- ch_free( db );
- return rc;
- }
- }
-
- if( bdb->bi_flags & BDB_CHKSUM ) {
- rc = db->bdi_db->set_flags( db->bdi_db, DB_CHKSUM );
- if ( rc ) {
- Debug( LDAP_DEBUG_ANY,
- "bdb_db_cache: db set_flags(DB_CHKSUM)(%s) failed: %s (%d)\n",
- bdb->bi_dbenv_home, db_strerror(rc), rc );
- ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
- db->bdi_db->close( db->bdi_db, 0 );
- ch_free( db );
- return rc;
- }
- }
-
- /* If no explicit size set, use the FS default */
- flags = bdb_db_findsize( bdb, name );
- if ( flags )
- rc = db->bdi_db->set_pagesize( db->bdi_db, flags );
-
-#ifdef BDB_INDEX_USE_HASH
- rc = db->bdi_db->set_h_hash( db->bdi_db, bdb_db_hash );
-#endif
- rc = db->bdi_db->set_flags( db->bdi_db, DB_DUP | DB_DUPSORT );
-
- file = ch_malloc( db->bdi_name.bv_len + sizeof(BDB_SUFFIX) );
- strcpy( file, db->bdi_name.bv_val );
- strcpy( file+db->bdi_name.bv_len, BDB_SUFFIX );
-
-#ifdef HAVE_EBCDIC
- __atoe( file );
-#endif
- flags = DB_CREATE | DB_THREAD;
-#ifdef DB_AUTO_COMMIT
- if ( !( slapMode & SLAP_TOOL_QUICK ))
- flags |= DB_AUTO_COMMIT;
-#endif
- /* Cannot Truncate when Transactions are in use */
- if ( (slapMode & (SLAP_TOOL_QUICK|SLAP_TRUNCATE_MODE)) ==
- (SLAP_TOOL_QUICK|SLAP_TRUNCATE_MODE))
- flags |= DB_TRUNCATE;
-
- rc = DB_OPEN( db->bdi_db,
- file, NULL /* name */,
- BDB_INDEXTYPE, bdb->bi_db_opflags | flags, bdb->bi_dbenv_mode );
-
- ch_free( file );
-
- if( rc != 0 ) {
- Debug( LDAP_DEBUG_ANY,
- "bdb_db_cache: db_open(%s) failed: %s (%d)\n",
- name->bv_val, db_strerror(rc), rc );
- ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
- db->bdi_db->close( db->bdi_db, 0 );
- ch_free( db );
- return rc;
- }
-
- bdb->bi_databases[i] = db;
- bdb->bi_ndatabases = i+1;
-
- *dbout = db->bdi_db;
-
- ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
- return 0;
-}
+++ /dev/null
-/* delete.c - bdb backend delete routine */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "lutil.h"
-#include "back-bdb.h"
-
-int
-bdb_delete( Operation *op, SlapReply *rs )
-{
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
- Entry *matched = NULL;
- struct berval pdn = {0, NULL};
- Entry *e = NULL;
- Entry *p = NULL;
- EntryInfo *ei = NULL, *eip = NULL;
- int manageDSAit = get_manageDSAit( op );
- AttributeDescription *children = slap_schema.si_ad_children;
- AttributeDescription *entry = slap_schema.si_ad_entry;
- DB_TXN *ltid = NULL, *lt2;
- struct bdb_op_info opinfo = {{{ 0 }}};
- ID eid;
-
- DB_LOCK lock, plock;
-
- int num_retries = 0;
-
- int rc;
-
- LDAPControl **preread_ctrl = NULL;
- LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
- int num_ctrls = 0;
-
- int parent_is_glue = 0;
- int parent_is_leaf = 0;
-
- Debug( LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(bdb_delete) ": %s\n",
- op->o_req_dn.bv_val );
-
-#ifdef LDAP_X_TXN
- if( op->o_txnSpec && txn_preop( 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" );
- 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 */
- {
- int tflags = bdb->bi_db_opflags;
- if ( get_lazyCommit( op ))
- tflags |= DB_TXN_NOSYNC;
- rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, NULL, <id, tflags );
- }
- Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_delete) ": txn1 id: %x\n",
- ltid->id(ltid) );
- 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 );
- 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 );
-
- 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" );
- 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" );
- 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" );
- 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" );
- 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" );
- 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" );
-
- 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" );
- 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 );
- 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) );
-
- 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 );
- 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 );
- 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 );
- 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 );
- 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 );
- 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 );
- 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;
-}
+++ /dev/null
-/* dn2entry.c - routines to deal with the dn2id / id2entry glue */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "back-bdb.h"
-
-/*
- * dn2entry - look up dn in the cache/indexes and return the corresponding
- * entry. If the requested DN is not found and matched is TRUE, return info
- * for the closest ancestor of the DN. Otherwise e is NULL.
- */
-
-int
-bdb_dn2entry(
- Operation *op,
- DB_TXN *tid,
- struct berval *dn,
- EntryInfo **e,
- int matched,
- DB_LOCK *lock )
-{
- EntryInfo *ei = NULL;
- int rc, rc2;
-
- Debug(LDAP_DEBUG_TRACE, "bdb_dn2entry(\"%s\")\n",
- dn->bv_val );
-
- *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;
-}
+++ /dev/null
-/* dn2id.c - routines to deal with the dn2id index */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "back-bdb.h"
-#include "idl.h"
-#include "lutil.h"
-
-#ifndef BDB_HIER
-int
-bdb_dn2id_add(
- Operation *op,
- DB_TXN *txn,
- EntryInfo *eip,
- Entry *e )
-{
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
- DB *db = bdb->bi_dn2id->bdi_db;
- int rc;
- DBT key, data;
- ID nid;
- char *buf;
- struct berval ptr, pdn;
-
- Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_add 0x%lx: \"%s\"\n",
- e->e_id, e->e_ndn );
- 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 ) {
- Debug(LDAP_DEBUG_ANY,
- "%s => bdb_dn2id_add dn=\"%s\" ID=0x%lx: put failed: %s %d\n",
- op->o_log_prefix, e->e_name.bv_val, 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 = 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 );
- 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 );
-
- 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 );
- 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 );
-
- 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 );
- } else {
- BDB_DISK2ID( &nid, &ei->bei_id );
- Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id: got id=0x%lx\n",
- ei->bei_id );
- }
- 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 );
- 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 );
-
-#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 );
-
- } 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 );
-
- 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 );
-
- 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 );
-
- 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 );
- 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 );
-
- 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 );
- } else {
- Debug( LDAP_DEBUG_TRACE, "<= hdb_dn2id: got id=0x%lx\n",
- ei->bei_id );
- }
-
- 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 );
-
-#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 */
+++ /dev/null
-/* error.c - BDB errcall routine */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "slap.h"
-#include "back-bdb.h"
-
-#if DB_VERSION_FULL < 0x04030000
-void bdb_errcall( const char *pfx, char * msg )
-#else
-void bdb_errcall( const DB_ENV *env, const char *pfx, const char * msg )
-#endif
-{
-#ifdef HAVE_EBCDIC
- if ( msg[0] > 0x7f )
- __etoa( msg );
-#endif
- Debug( LDAP_DEBUG_ANY, "bdb(%s): %s\n", pfx, msg );
-}
-
-#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 );
-}
-#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
+++ /dev/null
-/* extended.c - bdb backend extended routines */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "back-bdb.h"
-#include "lber_pvt.h"
-
-static struct exop {
- struct berval *oid;
- BI_op_extended *extended;
-} exop_table[] = {
- { NULL, NULL }
-};
-
-int
-bdb_extended( Operation *op, SlapReply *rs )
-/* struct berval *reqoid,
- struct berval *reqdata,
- char **rspoid,
- struct berval **rspdata,
- LDAPControl *** rspctrls,
- const char** text,
- BerVarray *refs
-) */
-{
- int i;
-
- for( i=0; exop_table[i].extended != NULL; i++ ) {
- if( ber_bvcmp( exop_table[i].oid, &op->oq_extended.rs_reqoid ) == 0 ) {
- return (exop_table[i].extended)( op, rs );
- }
- }
-
- rs->sr_text = "not supported within naming context";
- return rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
-}
-
+++ /dev/null
-/* filterindex.c - generate the list of candidate entries from a filter */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "back-bdb.h"
-#include "idl.h"
-#ifdef LDAP_COMP_MATCH
-#include <component.h>
-#endif
-
-static int presence_candidates(
- Operation *op,
- DB_TXN *rtxn,
- AttributeDescription *desc,
- ID *ids );
-
-static int equality_candidates(
- Operation *op,
- DB_TXN *rtxn,
- AttributeAssertion *ava,
- ID *ids,
- ID *tmp );
-static int inequality_candidates(
- Operation *op,
- DB_TXN *rtxn,
- AttributeAssertion *ava,
- ID *ids,
- ID *tmp,
- int gtorlt );
-static int approx_candidates(
- Operation *op,
- DB_TXN *rtxn,
- AttributeAssertion *ava,
- ID *ids,
- ID *tmp );
-static int substring_candidates(
- Operation *op,
- DB_TXN *rtxn,
- SubstringsAssertion *sub,
- ID *ids,
- ID *tmp );
-
-static int list_candidates(
- Operation *op,
- DB_TXN *rtxn,
- Filter *flist,
- int ftype,
- ID *ids,
- ID *tmp,
- ID *stack );
-
-static int
-ext_candidates(
- Operation *op,
- DB_TXN *rtxn,
- MatchingRuleAssertion *mra,
- ID *ids,
- ID *tmp,
- ID *stack);
-
-#ifdef LDAP_COMP_MATCH
-static int
-comp_candidates (
- Operation *op,
- DB_TXN *rtxn,
- MatchingRuleAssertion *mra,
- ComponentFilter *f,
- ID *ids,
- ID *tmp,
- ID *stack);
-
-static int
-ava_comp_candidates (
- Operation *op,
- DB_TXN *rtxn,
- AttributeAssertion *ava,
- AttributeAliasing *aa,
- ID *ids,
- ID *tmp,
- ID *stack);
-#endif
-
-int
-bdb_filter_candidates(
- Operation *op,
- DB_TXN *rtxn,
- Filter *f,
- ID *ids,
- ID *tmp,
- ID *stack )
-{
- int rc = 0;
-#ifdef LDAP_COMP_MATCH
- AttributeAliasing *aa;
-#endif
- Debug( LDAP_DEBUG_FILTER, "=> bdb_filter_candidates\n" );
-
- 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" );
- rc = presence_candidates( op, rtxn, f->f_desc, ids );
- break;
-
- case LDAP_FILTER_EQUALITY:
- Debug( LDAP_DEBUG_FILTER, "\tEQUALITY\n" );
-#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" );
- rc = approx_candidates( op, rtxn, f->f_ava, ids, tmp );
- break;
-
- case LDAP_FILTER_SUBSTRINGS:
- Debug( LDAP_DEBUG_FILTER, "\tSUBSTRINGS\n" );
- 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" );
- 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" );
- 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" );
- { 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" );
- 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" );
- 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" );
- 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 );
- /* 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 );
- 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 );
- }
-
- 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" );
- 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" );
- {
- 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 );
- 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 );
- }
-
- 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 );
-
- 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 );
- 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 );
- return 0;
- }
-
- if( prefix.bv_val == NULL ) {
- Debug( LDAP_DEBUG_TRACE,
- "<= bdb_presence_candidates: (%s) no prefix\n",
- desc->ad_cname.bv_val );
- 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 );
- 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 );
-
- 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 );
- 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 );
- 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 );
- 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 );
- break;
- }
-
- if( BDB_IDL_IS_ZERO( tmp ) ) {
- Debug( LDAP_DEBUG_TRACE,
- "<= bdb_equality_candidates: (%s) NULL\n",
- ava->aa_desc->ad_cname.bv_val );
- 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 );
-
- 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 );
- 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 );
- 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 );
- 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 );
- break;
- }
-
- if( BDB_IDL_IS_ZERO( tmp ) ) {
- Debug( LDAP_DEBUG_TRACE,
- "<= bdb_approx_candidates: (%s) NULL\n",
- ava->aa_desc->ad_cname.bv_val );
- 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 );
-
- 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 );
- 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 );
- 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 );
- 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 );
- 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 );
- break;
- }
-
- if( BDB_IDL_IS_ZERO( tmp ) ) {
- Debug( LDAP_DEBUG_TRACE,
- "<= bdb_substring_candidates: (%s) NULL\n",
- sub->sa_desc->ad_cname.bv_val );
- 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 );
-
- 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 );
- 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 );
- 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 );
- 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 );
- break;
- }
-
- if( BDB_IDL_IS_ZERO( tmp ) ) {
- Debug( LDAP_DEBUG_TRACE,
- "<= bdb_inequality_candidates: (%s) NULL\n",
- ava->aa_desc->ad_cname.bv_val );
- 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 );
-}
+++ /dev/null
-/* id2entry.c - routines to deal with the id2entry database */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-#include <ac/errno.h>
-
-#include "back-bdb.h"
-
-static int bdb_id2entry_put(
- BackendDB *be,
- DB_TXN *tid,
- Entry *e,
- int flag )
-{
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
- DB *db = bdb->bi_id2entry->bdi_db;
- DBT key, data;
- struct berval bv;
- int rc;
- ID nid;
-#ifdef BDB_HIER
- struct berval odn, ondn;
-
- /* We only store rdns, and they go in the dn2id database. */
-
- odn = e->e_name; ondn = e->e_nname;
-
- e->e_name = slap_empty_bv;
- e->e_nname = slap_empty_bv;
-#endif
- DBTzero( &key );
-
- /* Store ID in BigEndian format */
- key.data = &nid;
- key.size = sizeof(ID);
- BDB_ID2DISK( e->e_id, &nid );
-
- rc = entry_encode( e, &bv );
-#ifdef BDB_HIER
- e->e_name = odn; e->e_nname = ondn;
-#endif
- if( rc != LDAP_SUCCESS ) {
- return -1;
- }
-
- DBTzero( &data );
- bv2DBT( &bv, &data );
-
- rc = db->put( db, tid, &key, &data, flag );
-
- free( bv.bv_val );
- return rc;
-}
-
-/*
- * This routine adds (or updates) an entry on disk.
- * The cache should be already be updated.
- */
-
-
-int bdb_id2entry_add(
- BackendDB *be,
- DB_TXN *tid,
- Entry *e )
-{
- return bdb_id2entry_put(be, tid, e, DB_NOOVERWRITE);
-}
-
-int bdb_id2entry_update(
- BackendDB *be,
- DB_TXN *tid,
- Entry *e )
-{
- return bdb_id2entry_put(be, tid, e, 0);
-}
-
-int bdb_id2entry(
- BackendDB *be,
- DB_TXN *tid,
- ID id,
- Entry **e )
-{
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
- DB *db = bdb->bi_id2entry->bdi_db;
- DBT key, data;
- DBC *cursor;
- EntryHeader eh;
- char buf[16];
- int rc = 0, off;
- ID nid;
-
- *e = NULL;
-
- DBTzero( &key );
- key.data = &nid;
- key.size = sizeof(ID);
- BDB_ID2DISK( id, &nid );
-
- DBTzero( &data );
- data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
-
- /* fetch it */
- rc = db->cursor( db, tid, &cursor, bdb->bi_db_opflags );
- if ( rc ) return rc;
-
- /* Get the nattrs / nvals counts first */
- data.ulen = data.dlen = sizeof(buf);
- data.data = buf;
- rc = cursor->c_get( cursor, &key, &data, DB_SET );
- if ( rc ) goto finish;
-
-
- eh.bv.bv_val = buf;
- eh.bv.bv_len = data.size;
- rc = entry_header( &eh );
- if ( rc ) goto finish;
-
- if ( eh.nvals ) {
- /* Get the size */
- data.flags ^= DB_DBT_PARTIAL;
- data.ulen = 0;
- rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
- if ( rc != DB_BUFFER_SMALL ) goto finish;
-
- /* Allocate a block and retrieve the data */
- off = eh.data - eh.bv.bv_val;
- eh.bv.bv_len = eh.nvals * sizeof( struct berval ) + data.size;
- eh.bv.bv_val = ch_malloc( eh.bv.bv_len );
- eh.data = eh.bv.bv_val + eh.nvals * sizeof( struct berval );
- data.data = eh.data;
- data.ulen = data.size;
-
- /* skip past already parsed nattr/nvals */
- eh.data += off;
-
- rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
- }
-
-finish:
- cursor->c_close( cursor );
-
- if( rc != 0 ) {
- return rc;
- }
-
- if ( eh.nvals ) {
-#ifdef SLAP_ZONE_ALLOC
- rc = entry_decode(&eh, e, bdb->bi_cache.c_zctx);
-#else
- rc = entry_decode(&eh, e);
-#endif
- } else {
- *e = entry_alloc();
- }
-
- if( rc == 0 ) {
- (*e)->e_id = id;
- } else {
- /* only free on error. On success, the entry was
- * decoded in place.
- */
-#ifndef SLAP_ZONE_ALLOC
- ch_free(eh.bv.bv_val);
-#endif
- }
-#ifdef SLAP_ZONE_ALLOC
- ch_free(eh.bv.bv_val);
-#endif
-
- return rc;
-}
-
-int bdb_id2entry_delete(
- BackendDB *be,
- DB_TXN *tid,
- Entry *e )
-{
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
- DB *db = bdb->bi_id2entry->bdi_db;
- DBT key;
- int rc;
- ID nid;
-
- DBTzero( &key );
- key.data = &nid;
- key.size = sizeof(ID);
- BDB_ID2DISK( e->e_id, &nid );
-
- /* delete from database */
- rc = db->del( db, tid, &key, 0 );
-
- return rc;
-}
-
-int bdb_entry_return(
- Entry *e
-)
-{
- /* Our entries are allocated in two blocks; the data comes from
- * the db itself and the Entry structure and associated pointers
- * are allocated in entry_decode. The db data pointer is saved
- * in e_bv.
- */
- if ( e->e_bv.bv_val ) {
- /* See if the DNs were changed by modrdn */
- if( e->e_nname.bv_val < e->e_bv.bv_val || e->e_nname.bv_val >
- e->e_bv.bv_val + e->e_bv.bv_len ) {
- ch_free(e->e_name.bv_val);
- ch_free(e->e_nname.bv_val);
- }
- e->e_name.bv_val = NULL;
- e->e_nname.bv_val = NULL;
- /* In tool mode the e_bv buffer is realloc'd, leave it alone */
- if( !(slapMode & SLAP_TOOL_MODE) ) {
- free( e->e_bv.bv_val );
- }
- BER_BVZERO( &e->e_bv );
- }
- entry_free( e );
- return 0;
-}
-
-int bdb_entry_release(
- Operation *op,
- Entry *e,
- int rw )
-{
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
- struct bdb_op_info *boi;
- OpExtra *oex;
-
- /* slapMode : SLAP_SERVER_MODE, SLAP_TOOL_MODE,
- SLAP_TRUNCATE_MODE, SLAP_UNDEFINED_MODE */
-
- if ( slapMode & SLAP_SERVER_MODE ) {
- /* If not in our cache, just free it */
- if ( !e->e_private ) {
-#ifdef SLAP_ZONE_ALLOC
- return bdb_entry_return( bdb, e, -1 );
-#else
- return bdb_entry_return( e );
-#endif
- }
- /* free entry and reader or writer lock */
- LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
- if ( oex->oe_key == bdb ) break;
- }
- boi = (struct bdb_op_info *)oex;
-
- /* lock is freed with txn */
- if ( !boi || boi->boi_txn ) {
- bdb_unlocked_cache_return_entry_rw( bdb, e, rw );
- } else {
- struct bdb_lock_info *bli, *prev;
- for ( prev=(struct bdb_lock_info *)&boi->boi_locks,
- bli = boi->boi_locks; bli; prev=bli, bli=bli->bli_next ) {
- if ( bli->bli_id == e->e_id ) {
- bdb_cache_return_entry_rw( bdb, e, rw, &bli->bli_lock );
- prev->bli_next = bli->bli_next;
- /* Cleanup, or let caller know we unlocked */
- if ( bli->bli_flag & BLI_DONTFREE )
- bli->bli_flag = 0;
- else
- op->o_tmpfree( bli, op->o_tmpmemctx );
- break;
- }
- }
- if ( !boi->boi_locks ) {
- LDAP_SLIST_REMOVE( &op->o_extra, &boi->boi_oe, OpExtra, oe_next );
- if ( !(boi->boi_flag & BOI_DONTFREE))
- op->o_tmpfree( boi, op->o_tmpmemctx );
- }
- }
- } else {
-#ifdef SLAP_ZONE_ALLOC
- int zseq = -1;
- if (e->e_private != NULL) {
- BEI(e)->bei_e = NULL;
- zseq = BEI(e)->bei_zseq;
- }
-#else
- if (e->e_private != NULL)
- BEI(e)->bei_e = NULL;
-#endif
- e->e_private = NULL;
-#ifdef SLAP_ZONE_ALLOC
- bdb_entry_return ( bdb, e, zseq );
-#else
- bdb_entry_return ( e );
-#endif
- }
-
- return 0;
-}
-
-/* return LDAP_SUCCESS IFF we can retrieve the specified entry.
- */
-int bdb_entry_get(
- Operation *op,
- struct berval *ndn,
- ObjectClass *oc,
- AttributeDescription *at,
- int rw,
- Entry **ent )
-{
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
- struct bdb_op_info *boi = NULL;
- DB_TXN *txn = NULL;
- Entry *e = NULL;
- EntryInfo *ei;
- int rc;
- const char *at_name = at ? at->ad_cname.bv_val : "(null)";
-
- DB_LOCK lock;
-
- Debug( LDAP_DEBUG_ARGS,
- "=> bdb_entry_get: ndn: \"%s\"\n", ndn->bv_val );
- Debug( LDAP_DEBUG_ARGS,
- "=> bdb_entry_get: oc: \"%s\", at: \"%s\"\n",
- oc ? oc->soc_cname.bv_val : "(null)", at_name );
-
- 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 );
- return LDAP_NO_SUCH_OBJECT;
- }
-
- Debug( LDAP_DEBUG_ACL,
- "=> bdb_entry_get: found entry: \"%s\"\n",
- ndn->bv_val );
-
- 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 );
- 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 );
- 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 );
- return(rc);
-}
+++ /dev/null
-/* idl.c - ldap id list handling routines */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "back-bdb.h"
-#include "idl.h"
-
-#define IDL_MAX(x,y) ( (x) > (y) ? (x) : (y) )
-#define IDL_MIN(x,y) ( (x) < (y) ? (x) : (y) )
-#define IDL_CMP(x,y) ( (x) < (y) ? -1 : (x) > (y) )
-
-#define IDL_LRU_DELETE( bdb, e ) do { \
- if ( (e) == (bdb)->bi_idl_lru_head ) { \
- if ( (e)->idl_lru_next == (bdb)->bi_idl_lru_head ) { \
- (bdb)->bi_idl_lru_head = NULL; \
- } else { \
- (bdb)->bi_idl_lru_head = (e)->idl_lru_next; \
- } \
- } \
- if ( (e) == (bdb)->bi_idl_lru_tail ) { \
- if ( (e)->idl_lru_prev == (bdb)->bi_idl_lru_tail ) { \
- assert( (bdb)->bi_idl_lru_head == NULL ); \
- (bdb)->bi_idl_lru_tail = NULL; \
- } else { \
- (bdb)->bi_idl_lru_tail = (e)->idl_lru_prev; \
- } \
- } \
- (e)->idl_lru_next->idl_lru_prev = (e)->idl_lru_prev; \
- (e)->idl_lru_prev->idl_lru_next = (e)->idl_lru_next; \
-} while ( 0 )
-
-static int
-bdb_idl_entry_cmp( const void *v_idl1, const void *v_idl2 )
-{
- const bdb_idl_cache_entry_t *idl1 = v_idl1, *idl2 = v_idl2;
- int rc;
-
- if ((rc = SLAP_PTRCMP( idl1->db, idl2->db ))) return rc;
- if ((rc = idl1->kstr.bv_len - idl2->kstr.bv_len )) return rc;
- return ( memcmp ( idl1->kstr.bv_val, idl2->kstr.bv_val , idl1->kstr.bv_len ) );
-}
-
-#if IDL_DEBUG > 0
-static void idl_check( ID *ids )
-{
- if( BDB_IDL_IS_RANGE( ids ) ) {
- assert( BDB_IDL_RANGE_FIRST(ids) <= BDB_IDL_RANGE_LAST(ids) );
- } else {
- ID i;
- for( i=1; i < ids[0]; i++ ) {
- assert( ids[i+1] > ids[i] );
- }
- }
-}
-
-#if IDL_DEBUG > 1
-static void idl_dump( ID *ids )
-{
- if( BDB_IDL_IS_RANGE( ids ) ) {
- Debug( LDAP_DEBUG_ANY,
- "IDL: range ( %ld - %ld )\n",
- (long) BDB_IDL_RANGE_FIRST( ids ),
- (long) BDB_IDL_RANGE_LAST( ids ) );
-
- } else {
- ID i;
- Debug( LDAP_DEBUG_ANY, "IDL: size %ld", (long) ids[0] );
-
- for( i=1; i<=ids[0]; i++ ) {
- if( i % 16 == 1 ) {
- Debug( LDAP_DEBUG_ANY, "\n" );
- }
- Debug( LDAP_DEBUG_ANY, " %02lx", (long) ids[i] );
- }
-
- Debug( LDAP_DEBUG_ANY, "\n" );
- }
-
- 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 );
- 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 );
- 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" );
- }
- 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" );
- }
- --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" );
- }
- --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 ) );
-
- 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 );
- 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] );
- 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 );
- 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 );
- 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 );
- 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 );
- 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 ) );
- }
-
- 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 );
- return rc;
- }
- data.data = &nlo;
- /* Fetch the first data item for this key, to see if it
- * exists and if it's a range.
- */
- rc = cursor->c_get( cursor, key, &data, DB_SET );
- err = "c_get";
- if ( rc == 0 ) {
- if ( nlo != 0 ) {
- /* not a range, count the number of items */
- db_recno_t count;
- rc = cursor->c_count( cursor, &count, 0 );
- if ( rc != 0 ) {
- err = "c_count";
- goto fail;
- }
- if ( count >= BDB_IDL_DB_MAX ) {
- /* No room, convert to a range */
- DBT key2 = *key;
- db_recno_t i;
-
- key2.dlen = key2.ulen;
- key2.flags |= DB_DBT_PARTIAL;
-
- BDB_DISK2ID( &nlo, &lo );
- data.data = &nhi;
-
- rc = cursor->c_get( cursor, &key2, &data, DB_NEXT_NODUP );
- if ( rc != 0 && rc != DB_NOTFOUND ) {
- err = "c_get next_nodup";
- goto fail;
- }
- if ( rc == DB_NOTFOUND ) {
- rc = cursor->c_get( cursor, key, &data, DB_LAST );
- if ( rc != 0 ) {
- err = "c_get last";
- goto fail;
- }
- } else {
- rc = cursor->c_get( cursor, key, &data, DB_PREV );
- if ( rc != 0 ) {
- err = "c_get prev";
- goto fail;
- }
- }
- BDB_DISK2ID( &nhi, &hi );
- /* Update hi/lo if needed, then delete all the items
- * between lo and hi
- */
- if ( id < lo ) {
- lo = id;
- nlo = nid;
- } else if ( id > hi ) {
- hi = id;
- nhi = nid;
- }
- data.data = &nid;
- /* Don't fetch anything, just position cursor */
- data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
- data.dlen = data.ulen = 0;
- rc = cursor->c_get( cursor, key, &data, DB_SET );
- if ( rc != 0 ) {
- err = "c_get 2";
- goto fail;
- }
- rc = cursor->c_del( cursor, 0 );
- if ( rc != 0 ) {
- err = "c_del range1";
- goto fail;
- }
- /* Delete all the records */
- for ( i=1; i<count; i++ ) {
- rc = cursor->c_get( cursor, &key2, &data, DB_NEXT_DUP );
- if ( rc != 0 ) {
- err = "c_get next_dup";
- goto fail;
- }
- rc = cursor->c_del( cursor, 0 );
- if ( rc != 0 ) {
- err = "c_del range";
- goto fail;
- }
- }
- /* Store the range marker */
- data.size = data.ulen = sizeof(ID);
- data.flags = DB_DBT_USERMEM;
- nid = 0;
- rc = cursor->c_put( cursor, key, &data, DB_KEYFIRST );
- if ( rc != 0 ) {
- err = "c_put range";
- goto fail;
- }
- nid = nlo;
- rc = cursor->c_put( cursor, key, &data, DB_KEYLAST );
- if ( rc != 0 ) {
- err = "c_put lo";
- goto fail;
- }
- nid = nhi;
- rc = cursor->c_put( cursor, key, &data, DB_KEYLAST );
- if ( rc != 0 ) {
- err = "c_put hi";
- goto fail;
- }
- } else {
- /* There's room, just store it */
- goto put1;
- }
- } else {
- /* It's a range, see if we need to rewrite
- * the boundaries
- */
- hi = id;
- data.data = &nlo;
- rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP );
- if ( rc != 0 ) {
- err = "c_get lo";
- goto fail;
- }
- BDB_DISK2ID( &nlo, &lo );
- if ( id > lo ) {
- data.data = &nhi;
- rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP );
- if ( rc != 0 ) {
- err = "c_get hi";
- goto fail;
- }
- BDB_DISK2ID( &nhi, &hi );
- }
- if ( id < lo || id > hi ) {
- /* Delete the current lo/hi */
- rc = cursor->c_del( cursor, 0 );
- if ( rc != 0 ) {
- err = "c_del";
- goto fail;
- }
- data.data = &nid;
- rc = cursor->c_put( cursor, key, &data, DB_KEYFIRST );
- if ( rc != 0 ) {
- err = "c_put lo/hi";
- goto fail;
- }
- }
- }
- } else if ( rc == DB_NOTFOUND ) {
-put1: data.data = &nid;
- rc = cursor->c_put( cursor, key, &data, DB_NODUPDATA );
- /* Don't worry if it's already there */
- if ( rc != 0 && rc != DB_KEYEXIST ) {
- err = "c_put id";
- goto fail;
- }
- } else {
- /* initial c_get failed, nothing was done */
-fail:
- Debug( LDAP_DEBUG_ANY, "=> bdb_idl_insert_key: "
- "%s failed: %s (%d)\n", err, db_strerror(rc), rc );
- cursor->c_close( cursor );
- return rc;
- }
- /* If key was added (didn't already exist) and using IDL cache,
- * update key in IDL cache.
- */
- if ( !rc && bdb->bi_idl_cache_max_size ) {
- bdb_idl_cache_add_id( bdb, db, key, id );
- }
- rc = cursor->c_close( cursor );
- if( rc != 0 ) {
- Debug( LDAP_DEBUG_ANY, "=> bdb_idl_insert_key: "
- "c_close failed: %s (%d)\n",
- db_strerror(rc), rc );
- }
- 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 ) );
- }
- 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 );
- 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 );
- }
-
- 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-l) {
- 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 */
+++ /dev/null
-/* idl.h - ldap bdb back-end ID list header file */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#ifndef _BDB_IDL_H_
-#define _BDB_IDL_H_
-
-/* IDL sizes - likely should be even bigger
- * limiting factors: sizeof(ID), thread stack size
- */
-#define BDB_IDL_LOGN 16 /* DB_SIZE is 2^16, UM_SIZE is 2^17 */
-#define BDB_IDL_DB_SIZE (1<<BDB_IDL_LOGN)
-#define BDB_IDL_UM_SIZE (1<<(BDB_IDL_LOGN+1))
-#define BDB_IDL_UM_SIZEOF (BDB_IDL_UM_SIZE * sizeof(ID))
-
-#define BDB_IDL_DB_MAX (BDB_IDL_DB_SIZE-1)
-
-#define BDB_IDL_UM_MAX (BDB_IDL_UM_SIZE-1)
-
-#define BDB_IDL_IS_RANGE(ids) ((ids)[0] == NOID)
-#define BDB_IDL_RANGE_SIZE (3)
-#define BDB_IDL_RANGE_SIZEOF (BDB_IDL_RANGE_SIZE * sizeof(ID))
-#define BDB_IDL_SIZEOF(ids) ((BDB_IDL_IS_RANGE(ids) \
- ? BDB_IDL_RANGE_SIZE : ((ids)[0]+1)) * sizeof(ID))
-
-#define BDB_IDL_RANGE_FIRST(ids) ((ids)[1])
-#define BDB_IDL_RANGE_LAST(ids) ((ids)[2])
-
-#define BDB_IDL_RANGE( ids, f, l ) \
- do { \
- (ids)[0] = NOID; \
- (ids)[1] = (f); \
- (ids)[2] = (l); \
- } while(0)
-
-#define BDB_IDL_ZERO(ids) \
- do { \
- (ids)[0] = 0; \
- (ids)[1] = 0; \
- (ids)[2] = 0; \
- } while(0)
-
-#define BDB_IDL_IS_ZERO(ids) ( (ids)[0] == 0 )
-#define BDB_IDL_IS_ALL( range, ids ) ( (ids)[0] == NOID \
- && (ids)[1] <= (range)[1] && (range)[2] <= (ids)[2] )
-
-#define BDB_IDL_CPY( dst, src ) (AC_MEMCPY( dst, src, BDB_IDL_SIZEOF( src ) ))
-
-#define BDB_IDL_ID( bdb, ids, id ) BDB_IDL_RANGE( ids, id, ((bdb)->bi_lastid) )
-#define BDB_IDL_ALL( bdb, ids ) BDB_IDL_RANGE( ids, 1, ((bdb)->bi_lastid) )
-
-#define BDB_IDL_FIRST( ids ) ( (ids)[1] )
-#define BDB_IDL_LLAST( ids ) ( (ids)[(ids)[0]] )
-#define BDB_IDL_LAST( ids ) ( BDB_IDL_IS_RANGE(ids) \
- ? (ids)[2] : (ids)[(ids)[0]] )
-
-#define BDB_IDL_N( ids ) ( BDB_IDL_IS_RANGE(ids) \
- ? ((ids)[2]-(ids)[1])+1 : (ids)[0] )
-
-LDAP_BEGIN_DECL
-LDAP_END_DECL
-
-#endif
+++ /dev/null
-/* index.c - routines for dealing with attribute indexes */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/string.h>
-#include <ac/socket.h>
-
-#include "slap.h"
-#include "back-bdb.h"
-#include "lutil_hash.h"
-
-static char presence_keyval[] = {0,0};
-static struct berval presence_key = BER_BVC(presence_keyval);
-
-AttrInfo *bdb_index_mask(
- Backend *be,
- AttributeDescription *desc,
- struct berval *atname )
-{
- AttributeType *at;
- AttrInfo *ai = bdb_attr_mask( be->be_private, desc );
-
- if( ai ) {
- *atname = desc->ad_cname;
- return ai;
- }
-
- /* If there is a tagging option, did we ever index the base
- * type? If so, check for mask, otherwise it's not there.
- */
- if( slap_ad_is_tagged( desc ) && desc != desc->ad_type->sat_ad ) {
- /* has tagging option */
- ai = bdb_attr_mask( be->be_private, desc->ad_type->sat_ad );
-
- if ( ai && !( ai->ai_indexmask & SLAP_INDEX_NOTAGS ) ) {
- *atname = desc->ad_type->sat_cname;
- return ai;
- }
- }
-
- /* see if supertype defined mask for its subtypes */
- for( at = desc->ad_type; at != NULL ; at = at->sat_sup ) {
- /* If no AD, we've never indexed this type */
- if ( !at->sat_ad ) continue;
-
- ai = bdb_attr_mask( be->be_private, at->sat_ad );
-
- if ( ai && !( ai->ai_indexmask & SLAP_INDEX_NOSUBTYPES ) ) {
- *atname = at->sat_cname;
- return ai;
- }
- }
-
- return 0;
-}
-
-/* This function is only called when evaluating search filters.
- */
-int bdb_index_param(
- Backend *be,
- AttributeDescription *desc,
- int ftype,
- DB **dbp,
- slap_mask_t *maskp,
- struct berval *prefixp )
-{
- AttrInfo *ai;
- int rc;
- slap_mask_t mask, type = 0;
- DB *db;
-
- ai = bdb_index_mask( be, desc, prefixp );
-
- if ( !ai ) {
-#ifdef BDB_MONITOR_IDX
- switch ( ftype ) {
- case LDAP_FILTER_PRESENT:
- type = SLAP_INDEX_PRESENT;
- break;
- case LDAP_FILTER_APPROX:
- type = SLAP_INDEX_APPROX;
- break;
- case LDAP_FILTER_EQUALITY:
- type = SLAP_INDEX_EQUALITY;
- break;
- case LDAP_FILTER_SUBSTRINGS:
- type = SLAP_INDEX_SUBSTR;
- break;
- default:
- return LDAP_INAPPROPRIATE_MATCHING;
- }
- bdb_monitor_idx_add( be->be_private, desc, type );
-#endif /* BDB_MONITOR_IDX */
-
- return LDAP_INAPPROPRIATE_MATCHING;
- }
- mask = ai->ai_indexmask;
-
- rc = bdb_db_cache( be, prefixp, &db );
-
- if( rc != LDAP_SUCCESS ) {
- return rc;
- }
-
- switch( ftype ) {
- case LDAP_FILTER_PRESENT:
- type = SLAP_INDEX_PRESENT;
- if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
- *prefixp = presence_key;
- goto done;
- }
- break;
-
- case LDAP_FILTER_APPROX:
- type = SLAP_INDEX_APPROX;
- if ( desc->ad_type->sat_approx ) {
- if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
- goto done;
- }
- break;
- }
-
- /* Use EQUALITY rule and index for approximate match */
- /* fall thru */
-
- case LDAP_FILTER_EQUALITY:
- type = SLAP_INDEX_EQUALITY;
- if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
- goto done;
- }
- break;
-
- case LDAP_FILTER_SUBSTRINGS:
- type = SLAP_INDEX_SUBSTR;
- if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
- goto done;
- }
- break;
-
- default:
- return LDAP_OTHER;
- }
-
-#ifdef BDB_MONITOR_IDX
- bdb_monitor_idx_add( be->be_private, desc, type );
-#endif /* BDB_MONITOR_IDX */
-
- return LDAP_INAPPROPRIATE_MATCHING;
-
-done:
- *dbp = db;
- *maskp = mask;
- return LDAP_SUCCESS;
-}
-
-static int indexer(
- Operation *op,
- DB_TXN *txn,
- AttributeDescription *ad,
- struct berval *atname,
- BerVarray vals,
- ID id,
- int opid,
- slap_mask_t mask )
-{
- int rc, i;
- DB *db;
- struct berval *keys;
-
- assert( mask != 0 );
-
- rc = bdb_db_cache( op->o_bd, atname, &db );
-
- if ( rc != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_ANY,
- "bdb_index_read: Could not open DB %s\n",
- atname->bv_val );
- return LDAP_OTHER;
- }
-
- if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
- rc = bdb_key_change( op->o_bd, db, txn, &presence_key, id, opid );
- if( rc ) {
- goto done;
- }
- }
-
- if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
- rc = ad->ad_type->sat_equality->smr_indexer(
- LDAP_FILTER_EQUALITY,
- mask,
- ad->ad_type->sat_syntax,
- ad->ad_type->sat_equality,
- atname, vals, &keys, op->o_tmpmemctx );
-
- if( rc == LDAP_SUCCESS && keys != NULL ) {
- for( i=0; keys[i].bv_val != NULL; i++ ) {
- rc = bdb_key_change( op->o_bd, db, txn, &keys[i], id, opid );
- if( rc ) {
- ber_bvarray_free_x( keys, op->o_tmpmemctx );
- goto done;
- }
- }
- ber_bvarray_free_x( keys, op->o_tmpmemctx );
- }
- rc = LDAP_SUCCESS;
- }
-
- if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
- rc = ad->ad_type->sat_approx->smr_indexer(
- LDAP_FILTER_APPROX,
- mask,
- ad->ad_type->sat_syntax,
- ad->ad_type->sat_approx,
- atname, vals, &keys, op->o_tmpmemctx );
-
- if( rc == LDAP_SUCCESS && keys != NULL ) {
- for( i=0; keys[i].bv_val != NULL; i++ ) {
- rc = bdb_key_change( op->o_bd, db, txn, &keys[i], id, opid );
- if( rc ) {
- ber_bvarray_free_x( keys, op->o_tmpmemctx );
- goto done;
- }
- }
- ber_bvarray_free_x( keys, op->o_tmpmemctx );
- }
-
- rc = LDAP_SUCCESS;
- }
-
- if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
- rc = ad->ad_type->sat_substr->smr_indexer(
- LDAP_FILTER_SUBSTRINGS,
- mask,
- ad->ad_type->sat_syntax,
- ad->ad_type->sat_substr,
- atname, vals, &keys, op->o_tmpmemctx );
-
- if( rc == LDAP_SUCCESS && keys != NULL ) {
- for( i=0; keys[i].bv_val != NULL; i++ ) {
- rc = bdb_key_change( op->o_bd, db, txn, &keys[i], id, opid );
- if( rc ) {
- ber_bvarray_free_x( keys, op->o_tmpmemctx );
- goto done;
- }
- }
- ber_bvarray_free_x( keys, op->o_tmpmemctx );
- }
-
- rc = LDAP_SUCCESS;
- }
-
-done:
- switch( rc ) {
- /* The callers all know how to deal with these results */
- case 0:
- case DB_LOCK_DEADLOCK:
- case DB_LOCK_NOTGRANTED:
- break;
- /* Anything else is bad news */
- default:
- rc = LDAP_OTHER;
- }
- return rc;
-}
-
-static int index_at_values(
- Operation *op,
- DB_TXN *txn,
- AttributeDescription *ad,
- AttributeType *type,
- struct berval *tags,
- BerVarray vals,
- ID id,
- int opid )
-{
- int rc;
- slap_mask_t mask = 0;
- int ixop = opid;
- AttrInfo *ai = NULL;
-
- if ( opid == BDB_INDEX_UPDATE_OP )
- ixop = SLAP_INDEX_ADD_OP;
-
- if( type->sat_sup ) {
- /* recurse */
- rc = index_at_values( op, txn, NULL,
- type->sat_sup, tags,
- vals, id, opid );
-
- if( rc ) return rc;
- }
-
- /* If this type has no AD, we've never used it before */
- if( type->sat_ad ) {
- ai = bdb_attr_mask( op->o_bd->be_private, type->sat_ad );
- if ( ai ) {
-#ifdef LDAP_COMP_MATCH
- /* component indexing */
- if ( ai->ai_cr ) {
- ComponentReference *cr;
- for( cr = ai->ai_cr ; cr ; cr = cr->cr_next ) {
- rc = indexer( op, txn, cr->cr_ad, &type->sat_cname,
- cr->cr_nvals, id, ixop,
- cr->cr_indexmask );
- }
- }
-#endif
- ad = type->sat_ad;
- /* If we're updating the index, just set the new bits that aren't
- * already in the old mask.
- */
- if ( opid == BDB_INDEX_UPDATE_OP )
- mask = ai->ai_newmask & ~ai->ai_indexmask;
- else
- /* For regular updates, if there is a newmask use it. Otherwise
- * just use the old mask.
- */
- mask = ai->ai_newmask ? ai->ai_newmask : ai->ai_indexmask;
- if( mask ) {
- rc = indexer( op, txn, ad, &type->sat_cname,
- vals, id, ixop, mask );
-
- if( rc ) return rc;
- }
- }
- }
-
- if( tags->bv_len ) {
- AttributeDescription *desc;
-
- desc = ad_find_tags( type, tags );
- if( desc ) {
- ai = bdb_attr_mask( op->o_bd->be_private, desc );
-
- if( ai ) {
- if ( opid == BDB_INDEX_UPDATE_OP )
- mask = ai->ai_newmask & ~ai->ai_indexmask;
- else
- mask = ai->ai_newmask ? ai->ai_newmask : ai->ai_indexmask;
- if ( mask ) {
- rc = indexer( op, txn, desc, &desc->ad_cname,
- vals, id, ixop, mask );
-
- if( rc ) {
- return rc;
- }
- }
- }
- }
- }
-
- return LDAP_SUCCESS;
-}
-
-int bdb_index_values(
- Operation *op,
- DB_TXN *txn,
- AttributeDescription *desc,
- BerVarray vals,
- ID id,
- int opid )
-{
- int rc;
-
- /* Never index ID 0 */
- if ( id == 0 )
- return 0;
-
- rc = index_at_values( op, txn, desc,
- desc->ad_type, &desc->ad_tags,
- vals, id, opid );
-
- return rc;
-}
-
-/* Get the list of which indices apply to this attr */
-int
-bdb_index_recset(
- struct bdb_info *bdb,
- Attribute *a,
- AttributeType *type,
- struct berval *tags,
- IndexRec *ir )
-{
- int rc, slot;
- AttrList *al;
-
- if( type->sat_sup ) {
- /* recurse */
- rc = bdb_index_recset( bdb, a, type->sat_sup, tags, ir );
- if( rc ) return rc;
- }
- /* If this type has no AD, we've never used it before */
- if( type->sat_ad ) {
- slot = bdb_attr_slot( bdb, type->sat_ad, NULL );
- if ( slot >= 0 ) {
- ir[slot].ai = bdb->bi_attrs[slot];
- al = ch_malloc( sizeof( AttrList ));
- al->attr = a;
- al->next = ir[slot].attrs;
- ir[slot].attrs = al;
- }
- }
- if( tags->bv_len ) {
- AttributeDescription *desc;
-
- desc = ad_find_tags( type, tags );
- if( desc ) {
- slot = bdb_attr_slot( bdb, desc, NULL );
- if ( slot >= 0 ) {
- ir[slot].ai = bdb->bi_attrs[slot];
- al = ch_malloc( sizeof( AttrList ));
- al->attr = a;
- al->next = ir[slot].attrs;
- ir[slot].attrs = al;
- }
- }
- }
- return LDAP_SUCCESS;
-}
-
-/* Apply the indices for the recset */
-int bdb_index_recrun(
- Operation *op,
- struct bdb_info *bdb,
- IndexRec *ir0,
- ID id,
- int base )
-{
- IndexRec *ir;
- AttrList *al;
- int i, rc = 0;
-
- /* Never index ID 0 */
- if ( id == 0 )
- return 0;
-
- for (i=base; i<bdb->bi_nattrs; i+=slap_tool_thread_max-1) {
- ir = ir0 + i;
- if ( !ir->ai ) continue;
- while (( al = ir->attrs )) {
- ir->attrs = al->next;
- rc = indexer( op, NULL, ir->ai->ai_desc,
- &ir->ai->ai_desc->ad_type->sat_cname,
- al->attr->a_nvals, id, SLAP_INDEX_ADD_OP,
- ir->ai->ai_indexmask );
- free( al );
- if ( rc ) break;
- }
- }
- return rc;
-}
-
-int
-bdb_index_entry(
- Operation *op,
- DB_TXN *txn,
- int opid,
- Entry *e )
-{
- int rc;
- Attribute *ap = e->e_attrs;
-#if 0 /* ifdef LDAP_COMP_MATCH */
- ComponentReference *cr_list = NULL;
- ComponentReference *cr = NULL, *dupped_cr = NULL;
- void* decoded_comp;
- ComponentSyntaxInfo* csi_attr;
- Syntax* syn;
- AttributeType* at;
- int i, num_attr;
- void* mem_op;
- struct berval value = {0};
-#endif
-
- /* Never index ID 0 */
- if ( e->e_id == 0 )
- return 0;
-
- Debug( LDAP_DEBUG_TRACE, "=> index_entry_%s( %ld, \"%s\" )\n",
- opid == SLAP_INDEX_DELETE_OP ? "del" : "add",
- (long) e->e_id, e->e_dn );
-
- /* add each attribute to the indexes */
- for ( ; ap != NULL; ap = ap->a_next ) {
-#if 0 /* ifdef LDAP_COMP_MATCH */
- AttrInfo *ai;
- /* see if attribute has components to be indexed */
- ai = bdb_attr_mask( op->o_bd->be_private, ap->a_desc->ad_type->sat_ad );
- if ( !ai ) continue;
- cr_list = ai->ai_cr;
- if ( attr_converter && cr_list ) {
- syn = ap->a_desc->ad_type->sat_syntax;
- ap->a_comp_data = op->o_tmpalloc( sizeof( ComponentData ), op->o_tmpmemctx );
- /* Memory chunk(nibble) pre-allocation for decoders */
- mem_op = nibble_mem_allocator ( 1024*16, 1024*4 );
- ap->a_comp_data->cd_mem_op = mem_op;
- for( cr = cr_list ; cr ; cr = cr->cr_next ) {
- /* count how many values in an attribute */
- for( num_attr=0; ap->a_vals[num_attr].bv_val != NULL; num_attr++ );
- num_attr++;
- cr->cr_nvals = (BerVarray)op->o_tmpalloc( sizeof( struct berval )*num_attr, op->o_tmpmemctx );
- for( i=0; ap->a_vals[i].bv_val != NULL; i++ ) {
- /* decoding attribute value */
- decoded_comp = attr_converter ( ap, syn, &ap->a_vals[i] );
- if ( !decoded_comp )
- return LDAP_DECODING_ERROR;
- /* extracting the referenced component */
- dupped_cr = dup_comp_ref( op, cr );
- csi_attr = ((ComponentSyntaxInfo*)decoded_comp)->csi_comp_desc->cd_extract_i( mem_op, dupped_cr, decoded_comp );
- if ( !csi_attr )
- return LDAP_DECODING_ERROR;
- cr->cr_asn_type_id = csi_attr->csi_comp_desc->cd_type_id;
- cr->cr_ad = (AttributeDescription*)get_component_description ( cr->cr_asn_type_id );
- if ( !cr->cr_ad )
- return LDAP_INVALID_SYNTAX;
- at = cr->cr_ad->ad_type;
- /* encoding the value of component in GSER */
- rc = component_encoder( mem_op, csi_attr, &value );
- if ( rc != LDAP_SUCCESS )
- return LDAP_ENCODING_ERROR;
- /* Normalize the encoded component values */
- if ( at->sat_equality && at->sat_equality->smr_normalize ) {
- rc = at->sat_equality->smr_normalize (
- SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
- at->sat_syntax, at->sat_equality,
- &value, &cr->cr_nvals[i], op->o_tmpmemctx );
- } else {
- cr->cr_nvals[i] = value;
- }
- }
- /* The end of BerVarray */
- cr->cr_nvals[num_attr-1].bv_val = NULL;
- cr->cr_nvals[num_attr-1].bv_len = 0;
- }
- op->o_tmpfree( ap->a_comp_data, op->o_tmpmemctx );
- nibble_mem_free ( mem_op );
- ap->a_comp_data = NULL;
- }
-#endif
- rc = bdb_index_values( op, txn, ap->a_desc,
- ap->a_nvals, e->e_id, opid );
-
- if( rc != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_TRACE,
- "<= index_entry_%s( %ld, \"%s\" ) failure\n",
- opid == SLAP_INDEX_ADD_OP ? "add" : "del",
- (long) e->e_id, e->e_dn );
- return rc;
- }
- }
-
- Debug( LDAP_DEBUG_TRACE, "<= index_entry_%s( %ld, \"%s\" ) success\n",
- opid == SLAP_INDEX_DELETE_OP ? "del" : "add",
- (long) e->e_id, e->e_dn );
-
- return LDAP_SUCCESS;
-}
+++ /dev/null
-/* init.c - initialize bdb backend */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-#include <ac/stdlib.h>
-#include <ac/errno.h>
-#include <sys/stat.h>
-#include "back-bdb.h"
-#include <lutil.h>
-#include <ldap_rq.h>
-#include "alock.h"
-#include "config.h"
-
-static const struct bdbi_database {
- char *file;
- struct berval name;
- int type;
- int flags;
-} bdbi_databases[] = {
- { "id2entry" BDB_SUFFIX, BER_BVC("id2entry"), DB_BTREE, 0 },
- { "dn2id" BDB_SUFFIX, BER_BVC("dn2id"), DB_BTREE, 0 },
- { NULL, BER_BVNULL, 0, 0 }
-};
-
-typedef void * db_malloc(size_t);
-typedef void * db_realloc(void *, size_t);
-
-#define bdb_db_init BDB_SYMBOL(db_init)
-#define bdb_db_open BDB_SYMBOL(db_open)
-#define bdb_db_close BDB_SYMBOL(db_close)
-
-static int
-bdb_db_init( BackendDB *be, ConfigReply *cr )
-{
- struct bdb_info *bdb;
- int rc;
-
- Debug( LDAP_DEBUG_TRACE,
- LDAP_XSTRING(bdb_db_init) ": Initializing " BDB_UCTYPE " database\n" );
-
- /* 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" );
- return -1;
- }
-
- Debug( LDAP_DEBUG_ARGS,
- LDAP_XSTRING(bdb_db_open) ": \"%s\"\n",
- be->be_suffix[0].bv_val );
-
- /* 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 );
- 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 );
- 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 );
- 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 );
- if ( quick ) {
- Debug( LDAP_DEBUG_ANY,
- "Cannot use Quick mode; perform manual recovery first.\n" );
- slapMode ^= SLAP_TOOL_QUICK;
- rc = -1;
- goto fail;
- } else {
- Debug( LDAP_DEBUG_ANY,
- "Performing database recovery to activate new settings.\n" );
- }
- 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 );
- 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 );
- 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 );
-
- 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 );
- 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 );
- 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 );
- 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 );
- 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 );
- 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 );
- 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 );
- 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 );
- 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" );
-
- 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 );
- return -1;
- }
-
- Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_back_initialize)
- ": %s\n", version );
- }
-
- 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_tool_entry_delete = bdb_tool_entry_delete;
-
- 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 */
-
+++ /dev/null
-/* index.c - routines for dealing with attribute indexes */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/string.h>
-#include <ac/socket.h>
-
-#include "slap.h"
-#include "back-bdb.h"
-#include "idl.h"
-
-/* read a key */
-int
-bdb_key_read(
- Backend *be,
- DB *db,
- DB_TXN *txn,
- struct berval *k,
- ID *ids,
- DBC **saved_cursor,
- int get_flag
-)
-{
- int rc;
- DBT key;
-
- Debug( LDAP_DEBUG_TRACE, "=> key_read\n" );
-
- 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 );
- } else {
- Debug( LDAP_DEBUG_TRACE, "<= bdb_index_read %ld candidates\n",
- (long) BDB_IDL_N(ids) );
- }
-
- 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 );
-
- 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 );
-
- return rc;
-}
+++ /dev/null
-/* modify.c - bdb backend modify routine */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-#include <ac/time.h>
-
-#include "back-bdb.h"
-
-static struct berval scbva[] = {
- BER_BVC("glue"),
- BER_BVNULL
-};
-
-static void
-bdb_modify_idxflags(
- Operation *op,
- AttributeDescription *desc,
- int got_delete,
- Attribute *newattrs,
- Attribute *oldattrs )
-{
- struct berval ix_at;
- AttrInfo *ai;
-
- /* check if modified attribute was indexed
- * but not in case of NOOP... */
- ai = bdb_index_mask( op->o_bd, desc, &ix_at );
- if ( ai ) {
- if ( got_delete ) {
- Attribute *ap;
- struct berval ix2;
-
- ap = attr_find( oldattrs, desc );
- if ( ap ) ap->a_flags |= SLAP_ATTR_IXDEL;
-
- /* Find all other attrs that index to same slot */
- for ( ap = newattrs; ap; ap = ap->a_next ) {
- ai = bdb_index_mask( op->o_bd, ap->a_desc, &ix2 );
- if ( ai && ix2.bv_val == ix_at.bv_val )
- ap->a_flags |= SLAP_ATTR_IXADD;
- }
-
- } else {
- Attribute *ap;
-
- ap = attr_find( newattrs, desc );
- if ( ap ) ap->a_flags |= SLAP_ATTR_IXADD;
- }
- }
-}
-
-int bdb_modify_internal(
- Operation *op,
- DB_TXN *tid,
- Modifications *modlist,
- Entry *e,
- const char **text,
- char *textbuf,
- size_t textlen )
-{
- int rc, err;
- Modification *mod;
- Modifications *ml;
- Attribute *save_attrs;
- Attribute *ap;
- int glue_attr_delete = 0;
- int got_delete;
-
- Debug( LDAP_DEBUG_TRACE, "bdb_modify_internal: 0x%08lx: %s\n",
- e->e_id, e->e_dn );
-
- 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 );
- 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 );
- }
- 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 );
- 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 );
- } 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 );
- 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 );
- } 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 );
- 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 );
- } 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 );
- /* 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 );
- }
- break;
-
- case SLAP_MOD_SOFTDEL:
- Debug(LDAP_DEBUG_ARGS,
- "bdb_modify_internal: softdel %s\n",
- mod->sm_desc->ad_cname.bv_val );
- /* 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 );
- }
- 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 );
- /* 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 );
- }
- break;
-
- default:
- Debug(LDAP_DEBUG_ANY, "bdb_modify_internal: invalid op %d\n",
- mod->sm_op );
- *text = "Invalid modify operation";
- err = LDAP_OTHER;
- Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
- err, *text );
- }
-
- 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 );
- }
-
- /* 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 );
- 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 );
- 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;
-
- Debug( LDAP_DEBUG_ARGS, LDAP_XSTRING(bdb_modify) ": %s\n",
- op->o_req_dn.bv_val );
-
-#ifdef LDAP_X_TXN
- if( op->o_txnSpec && txn_preop( 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" );
-
- 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 */
- {
- int tflags = bdb->bi_db_opflags;
- if ( get_lazyCommit( op ))
- tflags |= DB_TXN_NOSYNC;
- rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, NULL, <id, tflags );
- }
- 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 );
- 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) );
-
- 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 );
- 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" );
-
- 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" );
- 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 );
- 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) );
- /* 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 );
- 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 );
- 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" );
- 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;
-}
+++ /dev/null
-/* modrdn.c - bdb backend modrdn routine */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "back-bdb.h"
-
-int
-bdb_modrdn( Operation *op, SlapReply *rs )
-{
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
- AttributeDescription *children = slap_schema.si_ad_children;
- AttributeDescription *entry = slap_schema.si_ad_entry;
- struct berval p_dn, p_ndn;
- struct berval new_dn = {0, NULL}, new_ndn = {0, NULL};
- Entry *e = NULL;
- Entry *p = NULL;
- EntryInfo *ei = NULL, *eip = NULL, *nei = NULL, *neip = NULL;
- /* LDAP v2 supporting correct attribute handling. */
- char textbuf[SLAP_TEXT_BUFLEN];
- size_t textlen = sizeof textbuf;
- DB_TXN *ltid = NULL, *lt2;
- struct bdb_op_info opinfo = {{{ 0 }}};
- Entry dummy = {0};
-
- Entry *np = NULL; /* newSuperior Entry */
- struct berval *np_dn = NULL; /* newSuperior dn */
- struct berval *np_ndn = NULL; /* newSuperior ndn */
- struct berval *new_parent_dn = NULL; /* np_dn, p_dn, or NULL */
-
- int manageDSAit = get_manageDSAit( op );
-
- DB_LOCK lock, plock, nplock;
-
- int num_retries = 0;
-
- LDAPControl **preread_ctrl = NULL;
- LDAPControl **postread_ctrl = NULL;
- LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
- int num_ctrls = 0;
-
- int rc;
-
- int parent_is_glue = 0;
- int parent_is_leaf = 0;
-
- 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 && txn_preop( 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 ) {
- if ( dummy.e_attrs != e->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" );
-
- 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 */
- {
- int tflags = bdb->bi_db_opflags;
- if ( get_lazyCommit( op ))
- tflags |= DB_TXN_NOSYNC;
- rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, NULL, <id, tflags );
- }
- 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 );
- 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) );
-
- 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" );
- 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 );
- 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 );
- 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 );
-
- 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" );
- 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" );
- 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 );
-
- 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 );
-
- 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 );
-
- /* 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 );
- 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 );
- 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 );
-
- /* 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" );
- 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" );
- 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" );
- 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" );
- 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" );
-
- 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 );
-
- /* 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;
- }
-
- 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" );
- 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 );
- 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) );
-
- /* 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 );
- 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 );
- 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;
-
- if( op->orr_modlist != NULL ) {
- /* 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 );
- if ( ( rs->sr_err == LDAP_INSUFFICIENT_ACCESS ) && opinfo.boi_err ) {
- rs->sr_err = opinfo.boi_err;
- }
- 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 );
- 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 );
- 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" );
- 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 {
- 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 != e->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;
-}
+++ /dev/null
-/* monitor.c - monitor bdb backend */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-#include <ac/stdlib.h>
-#include <ac/errno.h>
-#include <sys/stat.h>
-#include "lutil.h"
-#include "back-bdb.h"
-
-#include "../back-monitor/back-monitor.h"
-
-#include "config.h"
-
-static ObjectClass *oc_olmBDBDatabase;
-
-static AttributeDescription *ad_olmBDBEntryCache,
- *ad_olmBDBDNCache, *ad_olmBDBIDLCache,
- *ad_olmDbDirectory;
-
-#ifdef BDB_MONITOR_IDX
-static int
-bdb_monitor_idx_entry_add(
- struct bdb_info *bdb,
- Entry *e );
-
-static AttributeDescription *ad_olmDbNotIndexed;
-#endif /* BDB_MONITOR_IDX */
-
-/*
- * NOTE: there's some confusion in monitor OID arc;
- * by now, let's consider:
- *
- * Subsystems monitor attributes 1.3.6.1.4.1.4203.666.1.55.0
- * Databases monitor attributes 1.3.6.1.4.1.4203.666.1.55.0.1
- * BDB database monitor attributes 1.3.6.1.4.1.4203.666.1.55.0.1.1
- *
- * Subsystems monitor objectclasses 1.3.6.1.4.1.4203.666.3.16.0
- * Databases monitor objectclasses 1.3.6.1.4.1.4203.666.3.16.0.1
- * BDB database monitor objectclasses 1.3.6.1.4.1.4203.666.3.16.0.1.1
- */
-
-static struct {
- char *name;
- char *oid;
-} s_oid[] = {
- { "olmBDBAttributes", "olmDatabaseAttributes:1" },
- { "olmBDBObjectClasses", "olmDatabaseObjectClasses:1" },
-
- { NULL }
-};
-
-static struct {
- char *desc;
- AttributeDescription **ad;
-} s_at[] = {
- { "( olmBDBAttributes:1 "
- "NAME ( 'olmBDBEntryCache' ) "
- "DESC 'Number of items in Entry Cache' "
- "SUP monitorCounter "
- "NO-USER-MODIFICATION "
- "USAGE dSAOperation )",
- &ad_olmBDBEntryCache },
-
- { "( olmBDBAttributes:2 "
- "NAME ( 'olmBDBDNCache' ) "
- "DESC 'Number of items in DN Cache' "
- "SUP monitorCounter "
- "NO-USER-MODIFICATION "
- "USAGE dSAOperation )",
- &ad_olmBDBDNCache },
-
- { "( olmBDBAttributes:3 "
- "NAME ( 'olmBDBIDLCache' ) "
- "DESC 'Number of items in IDL Cache' "
- "SUP monitorCounter "
- "NO-USER-MODIFICATION "
- "USAGE dSAOperation )",
- &ad_olmBDBIDLCache },
-
- { "( olmDatabaseAttributes:1 "
- "NAME ( 'olmDbDirectory' ) "
- "DESC 'Path name of the directory "
- "where the database environment resides' "
- "SUP monitoredInfo "
- "NO-USER-MODIFICATION "
- "USAGE dSAOperation )",
- &ad_olmDbDirectory },
-
-#ifdef BDB_MONITOR_IDX
- { "( olmDatabaseAttributes:2 "
- "NAME ( 'olmDbNotIndexed' ) "
- "DESC 'Missing indexes resulting from candidate selection' "
- "SUP monitoredInfo "
- "NO-USER-MODIFICATION "
- "USAGE dSAOperation )",
- &ad_olmDbNotIndexed },
-#endif /* BDB_MONITOR_IDX */
-
- { NULL }
-};
-
-static struct {
- char *desc;
- ObjectClass **oc;
-} s_oc[] = {
- /* augments an existing object, so it must be AUXILIARY
- * FIXME: derive from some ABSTRACT "monitoredEntity"? */
- { "( olmBDBObjectClasses:1 "
- "NAME ( 'olmBDBDatabase' ) "
- "SUP top AUXILIARY "
- "MAY ( "
- "olmBDBEntryCache "
- "$ olmBDBDNCache "
- "$ olmBDBIDLCache "
- "$ olmDbDirectory "
-#ifdef BDB_MONITOR_IDX
- "$ olmDbNotIndexed "
-#endif /* BDB_MONITOR_IDX */
- ") )",
- &oc_olmBDBDatabase },
-
- { NULL }
-};
-
-static int
-bdb_monitor_update(
- Operation *op,
- SlapReply *rs,
- Entry *e,
- void *priv )
-{
- struct bdb_info *bdb = (struct bdb_info *) priv;
- Attribute *a;
-
- char buf[ BUFSIZ ];
- struct berval bv;
-
- assert( ad_olmBDBEntryCache != NULL );
-
- a = attr_find( e->e_attrs, ad_olmBDBEntryCache );
- assert( a != NULL );
- bv.bv_val = buf;
- bv.bv_len = snprintf( buf, sizeof( buf ), "%lu", bdb->bi_cache.c_cursize );
- ber_bvreplace( &a->a_vals[ 0 ], &bv );
-
- a = attr_find( e->e_attrs, ad_olmBDBDNCache );
- assert( a != NULL );
- bv.bv_len = snprintf( buf, sizeof( buf ), "%lu", bdb->bi_cache.c_eiused );
- ber_bvreplace( &a->a_vals[ 0 ], &bv );
-
- a = attr_find( e->e_attrs, ad_olmBDBIDLCache );
- assert( a != NULL );
- bv.bv_len = snprintf( buf, sizeof( buf ), "%lu", bdb->bi_idl_cache_size );
- ber_bvreplace( &a->a_vals[ 0 ], &bv );
-
-#ifdef BDB_MONITOR_IDX
- bdb_monitor_idx_entry_add( bdb, e );
-#endif /* BDB_MONITOR_IDX */
-
- return SLAP_CB_CONTINUE;
-}
-
-#if 0 /* uncomment if required */
-static int
-bdb_monitor_modify(
- Operation *op,
- SlapReply *rs,
- Entry *e,
- void *priv )
-{
- return SLAP_CB_CONTINUE;
-}
-#endif
-
-static int
-bdb_monitor_free(
- Entry *e,
- void **priv )
-{
- struct berval values[ 2 ];
- Modification mod = { 0 };
-
- const char *text;
- char textbuf[ SLAP_TEXT_BUFLEN ];
-
- int i, rc;
-
- /* NOTE: if slap_shutdown != 0, priv might have already been freed */
- *priv = NULL;
-
- /* Remove objectClass */
- mod.sm_op = LDAP_MOD_DELETE;
- mod.sm_desc = slap_schema.si_ad_objectClass;
- mod.sm_values = values;
- mod.sm_numvals = 1;
- values[ 0 ] = oc_olmBDBDatabase->soc_cname;
- BER_BVZERO( &values[ 1 ] );
-
- rc = modify_delete_values( e, &mod, 1, &text,
- textbuf, sizeof( textbuf ) );
- /* don't care too much about return code... */
-
- /* remove attrs */
- mod.sm_values = NULL;
- mod.sm_numvals = 0;
- for ( i = 0; s_at[ i ].desc != NULL; i++ ) {
- mod.sm_desc = *s_at[ i ].ad;
- rc = modify_delete_values( e, &mod, 1, &text,
- textbuf, sizeof( textbuf ) );
- /* don't care too much about return code... */
- }
-
- return SLAP_CB_CONTINUE;
-}
-
-#define bdb_monitor_initialize BDB_SYMBOL(monitor_initialize)
-
-/*
- * call from within bdb_initialize()
- */
-static int
-bdb_monitor_initialize( void )
-{
- int i, code;
- ConfigArgs c;
- char *argv[ 3 ];
-
- static int bdb_monitor_initialized = 0;
-
- /* set to 0 when successfully initialized; otherwise, remember failure */
- static int bdb_monitor_initialized_failure = 1;
-
- if ( bdb_monitor_initialized++ ) {
- return bdb_monitor_initialized_failure;
- }
-
- if ( backend_info( "monitor" ) == NULL ) {
- return -1;
- }
-
- /* register schema here */
-
- argv[ 0 ] = "back-bdb/back-hdb monitor";
- c.argv = argv;
- c.argc = 3;
- c.fname = argv[0];
-
- for ( i = 0; s_oid[ i ].name; i++ ) {
- c.lineno = i;
- argv[ 1 ] = s_oid[ i ].name;
- argv[ 2 ] = s_oid[ i ].oid;
-
- if ( parse_oidm( &c, 0, NULL ) != 0 ) {
- Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_monitor_initialize)
- ": unable to add "
- "objectIdentifier \"%s=%s\"\n",
- s_oid[ i ].name, s_oid[ i ].oid );
- 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 );
- 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 );
- 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" );
- }
-
- 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 */
+++ /dev/null
-/* init.c - initialize bdb backend */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "back-bdb.h"
-
-int bdb_next_id( BackendDB *be, ID *out )
-{
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
-
- ldap_pvt_thread_mutex_lock( &bdb->bi_lastid_mutex );
- *out = ++bdb->bi_lastid;
- ldap_pvt_thread_mutex_unlock( &bdb->bi_lastid_mutex );
-
- return 0;
-}
-
-int bdb_last_id( BackendDB *be, DB_TXN *tid )
-{
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
- int rc;
- ID id = 0;
- unsigned char idbuf[sizeof(ID)];
- DBT key, data;
- DBC *cursor;
-
- DBTzero( &key );
- key.flags = DB_DBT_USERMEM;
- key.data = (char *) idbuf;
- key.ulen = sizeof( idbuf );
-
- DBTzero( &data );
- data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
-
- /* Get a read cursor */
- rc = bdb->bi_id2entry->bdi_db->cursor( bdb->bi_id2entry->bdi_db,
- tid, &cursor, 0 );
-
- if (rc == 0) {
- rc = cursor->c_get(cursor, &key, &data, DB_LAST);
- cursor->c_close(cursor);
- }
-
- switch(rc) {
- case DB_NOTFOUND:
- rc = 0;
- break;
- case 0:
- BDB_DISK2ID( idbuf, &id );
- break;
-
- default:
- Debug( LDAP_DEBUG_ANY,
- "=> bdb_last_id: get failed: %s (%d)\n",
- db_strerror(rc), rc );
- goto done;
- }
-
- bdb->bi_lastid = id;
-
-done:
- return rc;
-}
+++ /dev/null
-/* operational.c - bdb backend operational attributes function */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/string.h>
-#include <ac/socket.h>
-
-#include "slap.h"
-#include "back-bdb.h"
-
-/*
- * sets *hasSubordinates to LDAP_COMPARE_TRUE/LDAP_COMPARE_FALSE
- * if the entry has children or not.
- */
-int
-bdb_hasSubordinates(
- Operation *op,
- Entry *e,
- int *hasSubordinates )
-{
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
- struct bdb_op_info *opinfo;
- OpExtra *oex;
- DB_TXN *rtxn;
- int rc;
- int release = 0;
-
- assert( e != NULL );
-
- /* NOTE: this should never happen, but it actually happens
- * when using back-relay; until we find a better way to
- * preserve entry's private information while rewriting it,
- * let's disable the hasSubordinate feature for back-relay.
- */
- if ( BEI( e ) == NULL ) {
- Entry *ee = NULL;
- rc = be_entry_get_rw( op, &e->e_nname, NULL, NULL, 0, &ee );
- if ( rc != LDAP_SUCCESS || ee == NULL ) {
- rc = LDAP_OTHER;
- goto done;
- }
- e = ee;
- release = 1;
- if ( BEI( ee ) == NULL ) {
- rc = LDAP_OTHER;
- goto done;
- }
- }
-
- /* Check for a txn in a parent op, otherwise use reader txn */
- LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
- if ( oex->oe_key == bdb )
- break;
- }
- opinfo = (struct bdb_op_info *) oex;
- if ( opinfo && opinfo->boi_txn ) {
- rtxn = opinfo->boi_txn;
- } else {
- rc = bdb_reader_get(op, bdb->bi_dbenv, &rtxn);
- if ( rc ) {
- rc = LDAP_OTHER;
- goto done;
- }
- }
-
-retry:
- /* FIXME: we can no longer assume the entry's e_private
- * field is correctly populated; so we need to reacquire
- * it with reader lock */
- rc = bdb_cache_children( op, rtxn, e );
-
- switch( rc ) {
- case DB_LOCK_DEADLOCK:
- case DB_LOCK_NOTGRANTED:
- goto retry;
-
- case 0:
- *hasSubordinates = LDAP_COMPARE_TRUE;
- break;
-
- case DB_NOTFOUND:
- *hasSubordinates = LDAP_COMPARE_FALSE;
- rc = LDAP_SUCCESS;
- break;
-
- default:
- Debug(LDAP_DEBUG_ARGS,
- "<=- " LDAP_XSTRING(bdb_hasSubordinates)
- ": has_children failed: %s (%d)\n",
- db_strerror(rc), rc );
- 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;
-}
-
+++ /dev/null
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#ifndef _PROTO_BDB_H
-#define _PROTO_BDB_H
-
-LDAP_BEGIN_DECL
-
-#ifdef BDB_HIER
-#define BDB_SYMBOL(x) LDAP_CONCAT(hdb_,x)
-#define BDB_UCTYPE "HDB"
-#else
-#define BDB_SYMBOL(x) LDAP_CONCAT(bdb_,x)
-#define BDB_UCTYPE "BDB"
-#endif
-
-/*
- * attr.c
- */
-
-#define bdb_attr_mask BDB_SYMBOL(attr_mask)
-#define bdb_attr_flush BDB_SYMBOL(attr_flush)
-#define bdb_attr_slot BDB_SYMBOL(attr_slot)
-#define bdb_attr_index_config BDB_SYMBOL(attr_index_config)
-#define bdb_attr_index_destroy BDB_SYMBOL(attr_index_destroy)
-#define bdb_attr_index_free BDB_SYMBOL(attr_index_free)
-#define bdb_attr_index_unparse BDB_SYMBOL(attr_index_unparse)
-#define bdb_attr_info_free BDB_SYMBOL(attr_info_free)
-
-AttrInfo *bdb_attr_mask( struct bdb_info *bdb,
- AttributeDescription *desc );
-
-void bdb_attr_flush( struct bdb_info *bdb );
-
-int bdb_attr_slot( struct bdb_info *bdb,
- AttributeDescription *desc, int *insert );
-
-int bdb_attr_index_config LDAP_P(( struct bdb_info *bdb,
- const char *fname, int lineno,
- int argc, char **argv, struct config_reply_s *cr ));
-
-void bdb_attr_index_unparse LDAP_P(( struct bdb_info *bdb, BerVarray *bva ));
-void bdb_attr_index_destroy LDAP_P(( struct bdb_info *bdb ));
-void bdb_attr_index_free LDAP_P(( struct bdb_info *bdb,
- AttributeDescription *ad ));
-
-void bdb_attr_info_free( AttrInfo *ai );
-
-/*
- * config.c
- */
-
-#define bdb_back_init_cf BDB_SYMBOL(back_init_cf)
-
-int bdb_back_init_cf( BackendInfo *bi );
-
-/*
- * dbcache.c
- */
-#define bdb_db_cache BDB_SYMBOL(db_cache)
-#define bdb_db_findsize BDB_SYMBOL(db_findsize)
-
-int
-bdb_db_cache(
- Backend *be,
- struct berval *name,
- DB **db );
-
-int
-bdb_db_findsize(
- struct bdb_info *bdb,
- struct berval *name );
-
-/*
- * dn2entry.c
- */
-#define bdb_dn2entry BDB_SYMBOL(dn2entry)
-
-int bdb_dn2entry LDAP_P(( Operation *op, DB_TXN *tid,
- struct berval *dn, EntryInfo **e, int matched,
- DB_LOCK *lock ));
-
-/*
- * dn2id.c
- */
-#define bdb_dn2id BDB_SYMBOL(dn2id)
-#define bdb_dn2id_add BDB_SYMBOL(dn2id_add)
-#define bdb_dn2id_delete BDB_SYMBOL(dn2id_delete)
-#define bdb_dn2id_children BDB_SYMBOL(dn2id_children)
-#define bdb_dn2idl BDB_SYMBOL(dn2idl)
-
-int bdb_dn2id(
- Operation *op,
- struct berval *dn,
- EntryInfo *ei,
- DB_TXN *txn,
- DBC **cursor );
-
-int bdb_dn2id_add(
- Operation *op,
- DB_TXN *tid,
- EntryInfo *eip,
- Entry *e );
-
-int bdb_dn2id_delete(
- Operation *op,
- DB_TXN *tid,
- EntryInfo *eip,
- Entry *e );
-
-int bdb_dn2id_children(
- Operation *op,
- DB_TXN *tid,
- Entry *e );
-
-int bdb_dn2idl(
- Operation *op,
- DB_TXN *txn,
- struct berval *ndn,
- EntryInfo *ei,
- ID *ids,
- ID *stack );
-
-#ifdef BDB_HIER
-#define bdb_dn2id_parent BDB_SYMBOL(dn2id_parent)
-#define bdb_dup_compare BDB_SYMBOL(dup_compare)
-#define bdb_fix_dn BDB_SYMBOL(fix_dn)
-
-int bdb_dn2id_parent(
- Operation *op,
- DB_TXN *txn,
- EntryInfo *ei,
- ID *idp );
-
-int bdb_dup_compare(
- DB *db,
- const DBT *usrkey,
- const DBT *curkey );
-
-int bdb_fix_dn( Entry *e, int checkit );
-#endif
-
-
-/*
- * error.c
- */
-#define bdb_errcall BDB_SYMBOL(errcall)
-
-#if DB_VERSION_FULL < 0x04030000
-void bdb_errcall( const char *pfx, char * msg );
-#else
-#define bdb_msgcall BDB_SYMBOL(msgcall)
-void bdb_errcall( const DB_ENV *env, const char *pfx, const char * msg );
-void bdb_msgcall( const DB_ENV *env, const char * msg );
-#endif
-
-#ifdef HAVE_EBCDIC
-#define ebcdic_dberror BDB_SYMBOL(ebcdic_dberror)
-
-char *ebcdic_dberror( int rc );
-#define db_strerror(x) ebcdic_dberror(x)
-#endif
-
-/*
- * filterentry.c
- */
-#define bdb_filter_candidates BDB_SYMBOL(filter_candidates)
-
-int bdb_filter_candidates(
- Operation *op,
- DB_TXN *txn,
- Filter *f,
- ID *ids,
- ID *tmp,
- ID *stack );
-
-/*
- * id2entry.c
- */
-#define bdb_id2entry BDB_SYMBOL(id2entry)
-#define bdb_id2entry_add BDB_SYMBOL(id2entry_add)
-#define bdb_id2entry_update BDB_SYMBOL(id2entry_update)
-#define bdb_id2entry_delete BDB_SYMBOL(id2entry_delete)
-
-int bdb_id2entry_add(
- BackendDB *be,
- DB_TXN *tid,
- Entry *e );
-
-int bdb_id2entry_update(
- BackendDB *be,
- DB_TXN *tid,
- Entry *e );
-
-int bdb_id2entry_delete(
- BackendDB *be,
- DB_TXN *tid,
- Entry *e);
-
-#ifdef SLAP_ZONE_ALLOC
-#else
-int bdb_id2entry(
- BackendDB *be,
- DB_TXN *tid,
- ID id,
- Entry **e);
-#endif
-
-#define bdb_entry_free BDB_SYMBOL(entry_free)
-#define bdb_entry_return BDB_SYMBOL(entry_return)
-#define bdb_entry_release BDB_SYMBOL(entry_release)
-#define bdb_entry_get BDB_SYMBOL(entry_get)
-
-void bdb_entry_free ( Entry *e );
-#ifdef SLAP_ZONE_ALLOC
-int bdb_entry_return( struct bdb_info *bdb, Entry *e, int seqno );
-#else
-int bdb_entry_return( Entry *e );
-#endif
-BI_entry_release_rw bdb_entry_release;
-BI_entry_get_rw bdb_entry_get;
-
-
-/*
- * idl.c
- */
-
-#define bdb_idl_cache_get BDB_SYMBOL(idl_cache_get)
-#define bdb_idl_cache_put BDB_SYMBOL(idl_cache_put)
-#define bdb_idl_cache_del BDB_SYMBOL(idl_cache_del)
-#define bdb_idl_cache_add_id BDB_SYMBOL(idl_cache_add_id)
-#define bdb_idl_cache_del_id BDB_SYMBOL(idl_cache_del_id)
-
-int bdb_idl_cache_get(
- struct bdb_info *bdb,
- DB *db,
- DBT *key,
- ID *ids );
-
-void
-bdb_idl_cache_put(
- struct bdb_info *bdb,
- DB *db,
- DBT *key,
- ID *ids,
- int rc );
-
-void
-bdb_idl_cache_del(
- struct bdb_info *bdb,
- DB *db,
- DBT *key );
-
-void
-bdb_idl_cache_add_id(
- struct bdb_info *bdb,
- DB *db,
- DBT *key,
- ID id );
-
-void
-bdb_idl_cache_del_id(
- struct bdb_info *bdb,
- DB *db,
- DBT *key,
- ID id );
-
-#define bdb_idl_first BDB_SYMBOL(idl_first)
-#define bdb_idl_next BDB_SYMBOL(idl_next)
-#define bdb_idl_search BDB_SYMBOL(idl_search)
-#define bdb_idl_insert BDB_SYMBOL(idl_insert)
-#define bdb_idl_delete BDB_SYMBOL(idl_delete)
-#define bdb_idl_intersection BDB_SYMBOL(idl_intersection)
-#define bdb_idl_union BDB_SYMBOL(idl_union)
-#define bdb_idl_sort BDB_SYMBOL(idl_sort)
-#define bdb_idl_append BDB_SYMBOL(idl_append)
-#define bdb_idl_append_one BDB_SYMBOL(idl_append_one)
-
-#define bdb_idl_fetch_key BDB_SYMBOL(idl_fetch_key)
-#define bdb_idl_insert_key BDB_SYMBOL(idl_insert_key)
-#define bdb_idl_delete_key BDB_SYMBOL(idl_delete_key)
-
-unsigned bdb_idl_search( ID *ids, ID id );
-
-int bdb_idl_fetch_key(
- BackendDB *be,
- DB *db,
- DB_TXN *txn,
- DBT *key,
- ID *ids,
- DBC **saved_cursor,
- int get_flag );
-
-int bdb_idl_insert( ID *ids, ID id );
-int bdb_idl_delete( ID *ids, ID id );
-
-int bdb_idl_insert_key(
- BackendDB *be,
- DB *db,
- DB_TXN *txn,
- DBT *key,
- ID id );
-
-int bdb_idl_delete_key(
- BackendDB *be,
- DB *db,
- DB_TXN *txn,
- DBT *key,
- ID id );
-
-int
-bdb_idl_intersection(
- ID *a,
- ID *b );
-
-int
-bdb_idl_union(
- ID *a,
- ID *b );
-
-ID bdb_idl_first( ID *ids, ID *cursor );
-ID bdb_idl_next( ID *ids, ID *cursor );
-
-void bdb_idl_sort( ID *ids, ID *tmp );
-int bdb_idl_append( ID *a, ID *b );
-int bdb_idl_append_one( ID *ids, ID id );
-
-
-/*
- * index.c
- */
-#define bdb_index_mask BDB_SYMBOL(index_mask)
-#define bdb_index_param BDB_SYMBOL(index_param)
-#define bdb_index_values BDB_SYMBOL(index_values)
-#define bdb_index_entry BDB_SYMBOL(index_entry)
-#define bdb_index_recset BDB_SYMBOL(index_recset)
-#define bdb_index_recrun BDB_SYMBOL(index_recrun)
-
-extern AttrInfo *
-bdb_index_mask LDAP_P((
- Backend *be,
- AttributeDescription *desc,
- struct berval *name ));
-
-extern int
-bdb_index_param LDAP_P((
- Backend *be,
- AttributeDescription *desc,
- int ftype,
- DB **db,
- slap_mask_t *mask,
- struct berval *prefix ));
-
-extern int
-bdb_index_values LDAP_P((
- Operation *op,
- DB_TXN *txn,
- AttributeDescription *desc,
- BerVarray vals,
- ID id,
- int opid ));
-
-extern int
-bdb_index_recset LDAP_P((
- struct bdb_info *bdb,
- Attribute *a,
- AttributeType *type,
- struct berval *tags,
- IndexRec *ir ));
-
-extern int
-bdb_index_recrun LDAP_P((
- Operation *op,
- struct bdb_info *bdb,
- IndexRec *ir,
- ID id,
- int base ));
-
-int bdb_index_entry LDAP_P(( Operation *op, DB_TXN *t, int r, Entry *e ));
-
-#define bdb_index_entry_add(op,t,e) \
- bdb_index_entry((op),(t),SLAP_INDEX_ADD_OP,(e))
-#define bdb_index_entry_del(op,t,e) \
- bdb_index_entry((op),(t),SLAP_INDEX_DELETE_OP,(e))
-
-/*
- * key.c
- */
-#define bdb_key_read BDB_SYMBOL(key_read)
-#define bdb_key_change BDB_SYMBOL(key_change)
-
-extern int
-bdb_key_read(
- Backend *be,
- DB *db,
- DB_TXN *txn,
- struct berval *k,
- ID *ids,
- DBC **saved_cursor,
- int get_flags );
-
-extern int
-bdb_key_change(
- Backend *be,
- DB *db,
- DB_TXN *txn,
- struct berval *k,
- ID id,
- int op );
-
-/*
- * nextid.c
- */
-#define bdb_next_id BDB_SYMBOL(next_id)
-#define bdb_last_id BDB_SYMBOL(last_id)
-
-int bdb_next_id( BackendDB *be, ID *id );
-int bdb_last_id( BackendDB *be, DB_TXN *tid );
-
-/*
- * modify.c
- */
-#define bdb_modify_internal BDB_SYMBOL(modify_internal)
-
-int bdb_modify_internal(
- Operation *op,
- DB_TXN *tid,
- Modifications *modlist,
- Entry *e,
- const char **text,
- char *textbuf,
- size_t textlen );
-
-/*
- * monitor.c
- */
-
-#define bdb_monitor_db_init BDB_SYMBOL(monitor_db_init)
-#define bdb_monitor_db_open BDB_SYMBOL(monitor_db_open)
-#define bdb_monitor_db_close BDB_SYMBOL(monitor_db_close)
-#define bdb_monitor_db_destroy BDB_SYMBOL(monitor_db_destroy)
-
-int bdb_monitor_db_init( BackendDB *be );
-int bdb_monitor_db_open( BackendDB *be );
-int bdb_monitor_db_close( BackendDB *be );
-int bdb_monitor_db_destroy( BackendDB *be );
-
-#ifdef BDB_MONITOR_IDX
-#define bdb_monitor_idx_add BDB_SYMBOL(monitor_idx_add)
-int
-bdb_monitor_idx_add(
- struct bdb_info *bdb,
- AttributeDescription *desc,
- slap_mask_t type );
-#endif /* BDB_MONITOR_IDX */
-
-/*
- * cache.c
- */
-#define bdb_cache_entry_db_unlock BDB_SYMBOL(cache_entry_db_unlock)
-#define bdb_cache_return_entry_rw BDB_SYMBOL(cache_return_entry_rw)
-
-#define bdb_cache_entryinfo_lock(e) \
- ldap_pvt_thread_mutex_lock( &(e)->bei_kids_mutex )
-#define bdb_cache_entryinfo_unlock(e) \
- ldap_pvt_thread_mutex_unlock( &(e)->bei_kids_mutex )
-#define bdb_cache_entryinfo_trylock(e) \
- ldap_pvt_thread_mutex_trylock( &(e)->bei_kids_mutex )
-
-/* What a mess. Hopefully the current cache scheme will stabilize
- * and we can trim out all of this stuff.
- */
-void bdb_cache_return_entry_rw( struct bdb_info *bdb, Entry *e,
- int rw, DB_LOCK *lock );
-#define bdb_cache_return_entry_r(bdb, e, l) \
- bdb_cache_return_entry_rw((bdb), (e), 0, (l))
-#define bdb_cache_return_entry_w(bdb, e, l) \
- bdb_cache_return_entry_rw((bdb), (e), 1, (l))
-#if 0
-void bdb_unlocked_cache_return_entry_rw( struct bdb_info *bdb, Entry *e, int rw );
-#else
-#define bdb_unlocked_cache_return_entry_rw( a, b, c ) ((void)0)
-#endif
-#define bdb_unlocked_cache_return_entry_r( c, e ) \
- bdb_unlocked_cache_return_entry_rw((c), (e), 0)
-#define bdb_unlocked_cache_return_entry_w( c, e ) \
- bdb_unlocked_cache_return_entry_rw((c), (e), 1)
-
-#define bdb_cache_add BDB_SYMBOL(cache_add)
-#define bdb_cache_children BDB_SYMBOL(cache_children)
-#define bdb_cache_delete BDB_SYMBOL(cache_delete)
-#define bdb_cache_delete_cleanup BDB_SYMBOL(cache_delete_cleanup)
-#define bdb_cache_find_id BDB_SYMBOL(cache_find_id)
-#define bdb_cache_find_ndn BDB_SYMBOL(cache_find_ndn)
-#define bdb_cache_find_parent BDB_SYMBOL(cache_find_parent)
-#define bdb_cache_modify BDB_SYMBOL(cache_modify)
-#define bdb_cache_modrdn BDB_SYMBOL(cache_modrdn)
-#define bdb_cache_release_all BDB_SYMBOL(cache_release_all)
-#define bdb_cache_delete_entry BDB_SYMBOL(cache_delete_entry)
-#define bdb_cache_deref BDB_SYMBOL(cache_deref)
-
-int bdb_cache_children(
- Operation *op,
- DB_TXN *txn,
- Entry *e
-);
-int bdb_cache_add(
- struct bdb_info *bdb,
- EntryInfo *pei,
- Entry *e,
- struct berval *nrdn,
- DB_TXN *txn,
- DB_LOCK *lock
-);
-int bdb_cache_modrdn(
- struct bdb_info *bdb,
- Entry *e,
- struct berval *nrdn,
- Entry *new,
- EntryInfo *ein,
- DB_TXN *txn,
- DB_LOCK *lock
-);
-int bdb_cache_modify(
- struct bdb_info *bdb,
- Entry *e,
- Attribute *newAttrs,
- DB_TXN *txn,
- DB_LOCK *lock
-);
-int bdb_cache_find_ndn(
- Operation *op,
- DB_TXN *txn,
- struct berval *ndn,
- EntryInfo **res
-);
-
-#define ID_LOCKED 1
-#define ID_NOCACHE 2
-#define ID_NOENTRY 4
-#define ID_CHKPURGE 8
-int bdb_cache_find_id(
- Operation *op,
- DB_TXN *tid,
- ID id,
- EntryInfo **eip,
- int flag,
- DB_LOCK *lock
-);
-int
-bdb_cache_find_parent(
- Operation *op,
- DB_TXN *txn,
- ID id,
- EntryInfo **res
-);
-int bdb_cache_delete(
- struct bdb_info *bdb,
- Entry *e,
- DB_TXN *txn,
- DB_LOCK *lock
-);
-void bdb_cache_delete_cleanup(
- Cache *cache,
- EntryInfo *ei
-);
-void bdb_cache_release_all( Cache *cache );
-void bdb_cache_deref( EntryInfo *ei );
-
-#ifdef BDB_HIER
-int hdb_cache_load(
- struct bdb_info *bdb,
- EntryInfo *ei,
- EntryInfo **res
-);
-#endif
-
-#define bdb_cache_entry_db_relock BDB_SYMBOL(cache_entry_db_relock)
-int bdb_cache_entry_db_relock(
- struct bdb_info *bdb,
- DB_TXN *txn,
- EntryInfo *ei,
- int rw,
- int tryOnly,
- DB_LOCK *lock );
-
-int bdb_cache_entry_db_unlock(
- struct bdb_info *bdb,
- DB_LOCK *lock );
-
-#define bdb_reader_get BDB_SYMBOL(reader_get)
-#define bdb_reader_flush BDB_SYMBOL(reader_flush)
-int bdb_reader_get( Operation *op, DB_ENV *env, DB_TXN **txn );
-void bdb_reader_flush( DB_ENV *env );
-
-/*
- * trans.c
- */
-#define bdb_trans_backoff BDB_SYMBOL(trans_backoff)
-
-void
-bdb_trans_backoff( int num_retries );
-
-/*
- * former external.h
- */
-
-#define bdb_back_initialize BDB_SYMBOL(back_initialize)
-#define bdb_db_config BDB_SYMBOL(db_config)
-#define bdb_add BDB_SYMBOL(add)
-#define bdb_bind BDB_SYMBOL(bind)
-#define bdb_compare BDB_SYMBOL(compare)
-#define bdb_delete BDB_SYMBOL(delete)
-#define bdb_modify BDB_SYMBOL(modify)
-#define bdb_modrdn BDB_SYMBOL(modrdn)
-#define bdb_search BDB_SYMBOL(search)
-#define bdb_extended BDB_SYMBOL(extended)
-#define bdb_referrals BDB_SYMBOL(referrals)
-#define bdb_operational BDB_SYMBOL(operational)
-#define bdb_hasSubordinates BDB_SYMBOL(hasSubordinates)
-#define bdb_tool_entry_open BDB_SYMBOL(tool_entry_open)
-#define bdb_tool_entry_close BDB_SYMBOL(tool_entry_close)
-#define bdb_tool_entry_first_x BDB_SYMBOL(tool_entry_first_x)
-#define bdb_tool_entry_next BDB_SYMBOL(tool_entry_next)
-#define bdb_tool_entry_get BDB_SYMBOL(tool_entry_get)
-#define bdb_tool_entry_put BDB_SYMBOL(tool_entry_put)
-#define bdb_tool_entry_reindex BDB_SYMBOL(tool_entry_reindex)
-#define bdb_tool_dn2id_get BDB_SYMBOL(tool_dn2id_get)
-#define bdb_tool_entry_modify BDB_SYMBOL(tool_entry_modify)
-#define bdb_tool_idl_add BDB_SYMBOL(tool_idl_add)
-#define bdb_tool_entry_delete BDB_SYMBOL(tool_entry_delete)
-
-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;
-extern BI_tool_entry_delete bdb_tool_entry_delete;
-
-int bdb_tool_idl_add( BackendDB *be, DB *db, DB_TXN *txn, DBT *key, ID id );
-
-LDAP_END_DECL
-
-#endif /* _PROTO_BDB_H */
+++ /dev/null
-/* referral.c - BDB backend referral handler */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "back-bdb.h"
-
-int
-bdb_referrals( Operation *op, SlapReply *rs )
-{
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
- Entry *e = NULL;
- EntryInfo *ei;
- int rc = LDAP_SUCCESS;
-
- DB_TXN *rtxn;
- DB_LOCK lock;
-
- if( op->o_tag == LDAP_REQ_SEARCH ) {
- /* let search take care of itself */
- return rc;
- }
-
- if( get_manageDSAit( op ) ) {
- /* let op take care of DSA management */
- return rc;
- }
-
- rc = bdb_reader_get(op, bdb->bi_dbenv, &rtxn);
- switch(rc) {
- case 0:
- break;
- default:
- return LDAP_OTHER;
- }
-
-dn2entry_retry:
- /* get entry */
- rc = bdb_dn2entry( op, rtxn, &op->o_req_ndn, &ei, 1, &lock );
-
- /* bdb_dn2entry() may legally leave ei == NULL
- * if rc != 0 and rc != DB_NOTFOUND
- */
- if ( ei ) {
- e = ei->bei_e;
- }
-
- switch(rc) {
- case DB_NOTFOUND:
- case 0:
- break;
- case LDAP_BUSY:
- rs->sr_text = "ldap server busy";
- return LDAP_BUSY;
- case DB_LOCK_DEADLOCK:
- case DB_LOCK_NOTGRANTED:
- goto dn2entry_retry;
- default:
- Debug( LDAP_DEBUG_TRACE,
- LDAP_XSTRING(bdb_referrals)
- ": dn2entry failed: %s (%d)\n",
- db_strerror(rc), rc );
- 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;
-}
+++ /dev/null
-/* search.c - search operation */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "back-bdb.h"
-#include "idl.h"
-
-static int base_candidate(
- BackendDB *be,
- Entry *e,
- ID *ids );
-
-static int search_candidates(
- Operation *op,
- SlapReply *rs,
- Entry *e,
- DB_TXN *txn,
- ID *ids,
- ID *scopes );
-
-static int parse_paged_cookie( Operation *op, SlapReply *rs );
-
-static void send_paged_response(
- Operation *op,
- SlapReply *rs,
- ID *lastid,
- int tentries );
-
-/* Dereference aliases for a single alias entry. Return the final
- * dereferenced entry on success, NULL on any failure.
- */
-static Entry * deref_base (
- Operation *op,
- SlapReply *rs,
- Entry *e,
- Entry **matched,
- DB_TXN *txn,
- DB_LOCK *lock,
- ID *tmp,
- ID *visited )
-{
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
- struct berval ndn;
- EntryInfo *ei;
- DB_LOCK lockr;
-
- rs->sr_err = LDAP_ALIAS_DEREF_PROBLEM;
- rs->sr_text = "maximum deref depth exceeded";
-
- for (;;) {
- /* Remember the last entry we looked at, so we can
- * report broken links
- */
- *matched = e;
-
- if (BDB_IDL_N(tmp) >= op->o_bd->be_max_deref_depth) {
- e = NULL;
- break;
- }
-
- /* If this is part of a subtree or onelevel search,
- * have we seen this ID before? If so, quit.
- */
- if ( visited && bdb_idl_insert( visited, e->e_id ) ) {
- e = NULL;
- break;
- }
-
- /* If we've seen this ID during this deref iteration,
- * we've hit a loop.
- */
- if ( bdb_idl_insert( tmp, e->e_id ) ) {
- rs->sr_err = LDAP_ALIAS_PROBLEM;
- rs->sr_text = "circular alias";
- e = NULL;
- break;
- }
-
- /* If there was a problem getting the aliasedObjectName,
- * get_alias_dn will have set the error status.
- */
- if ( get_alias_dn(e, &ndn, &rs->sr_err, &rs->sr_text) ) {
- e = NULL;
- break;
- }
-
- rs->sr_err = bdb_dn2entry( op, txn, &ndn, &ei,
- 0, &lockr );
- if ( rs->sr_err == DB_LOCK_DEADLOCK )
- return NULL;
-
- if ( ei ) {
- e = ei->bei_e;
- } else {
- e = NULL;
- }
-
- if (!e) {
- rs->sr_err = LDAP_ALIAS_PROBLEM;
- rs->sr_text = "aliasedObject not found";
- break;
- }
-
- /* Free the previous entry, continue to work with the
- * one we just retrieved.
- */
- bdb_cache_return_entry_r( bdb, *matched, lock);
- *lock = lockr;
-
- /* We found a regular entry. Return this to the caller. The
- * entry is still locked for Read.
- */
- if (!is_entry_alias(e)) {
- rs->sr_err = LDAP_SUCCESS;
- rs->sr_text = NULL;
- break;
- }
- }
- return e;
-}
-
-/* Look for and dereference all aliases within the search scope. Adds
- * the dereferenced entries to the "ids" list. Requires "stack" to be
- * able to hold 8 levels of DB_SIZE IDLs. Of course we're hardcoded to
- * require a minimum of 8 UM_SIZE IDLs so this is never a problem.
- */
-static int search_aliases(
- Operation *op,
- SlapReply *rs,
- Entry *e,
- DB_TXN *txn,
- ID *ids,
- ID *scopes,
- ID *stack )
-{
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
- ID *aliases, *curscop, *subscop, *visited, *newsubs, *oldsubs, *tmp;
- ID cursora, ida, cursoro, ido, *subscop2;
- Entry *matched, *a;
- EntryInfo *ei;
- struct berval bv_alias = BER_BVC( "alias" );
- AttributeAssertion aa_alias = ATTRIBUTEASSERTION_INIT;
- Filter af;
- DB_LOCK locka, lockr;
- int first = 1;
-
- aliases = stack; /* IDL of all aliases in the database */
- curscop = aliases + BDB_IDL_DB_SIZE; /* Aliases in the current scope */
- subscop = curscop + BDB_IDL_DB_SIZE; /* The current scope */
- visited = subscop + BDB_IDL_DB_SIZE; /* IDs we've seen in this search */
- newsubs = visited + BDB_IDL_DB_SIZE; /* New subtrees we've added */
- oldsubs = newsubs + BDB_IDL_DB_SIZE; /* Subtrees added previously */
- tmp = oldsubs + BDB_IDL_DB_SIZE; /* Scratch space for deref_base() */
-
- /* A copy of subscop, because subscop gets clobbered by
- * the bdb_idl_union/intersection routines
- */
- subscop2 = tmp + BDB_IDL_DB_SIZE;
-
- af.f_choice = LDAP_FILTER_EQUALITY;
- af.f_ava = &aa_alias;
- af.f_av_desc = slap_schema.si_ad_objectClass;
- af.f_av_value = bv_alias;
- af.f_next = NULL;
-
- /* Find all aliases in database */
- BDB_IDL_ZERO( aliases );
- rs->sr_err = bdb_filter_candidates( op, txn, &af, aliases,
- curscop, visited );
- if (rs->sr_err != LDAP_SUCCESS || BDB_IDL_IS_ZERO( aliases )) {
- return rs->sr_err;
- }
- oldsubs[0] = 1;
- oldsubs[1] = e->e_id;
-
- BDB_IDL_ZERO( ids );
- BDB_IDL_ZERO( visited );
- BDB_IDL_ZERO( newsubs );
-
- cursoro = 0;
- ido = bdb_idl_first( oldsubs, &cursoro );
-
- for (;;) {
- /* Set curscop to only the aliases in the current scope. Start with
- * all the aliases, obtain the IDL for the current scope, and then
- * get the intersection of these two IDLs. Add the current scope
- * to the cumulative list of candidates.
- */
- BDB_IDL_CPY( curscop, aliases );
- rs->sr_err = bdb_dn2idl( op, txn, &e->e_nname, BEI(e), subscop,
- subscop2+BDB_IDL_DB_SIZE );
-
- if (first) {
- first = 0;
- } else {
- bdb_cache_return_entry_r (bdb, e, &locka);
- }
- if ( rs->sr_err == DB_LOCK_DEADLOCK )
- return rs->sr_err;
-
- BDB_IDL_CPY(subscop2, subscop);
- rs->sr_err = bdb_idl_intersection(curscop, subscop);
- bdb_idl_union( ids, subscop2 );
-
- /* Dereference all of the aliases in the current scope. */
- cursora = 0;
- for (ida = bdb_idl_first(curscop, &cursora); ida != NOID;
- ida = bdb_idl_next(curscop, &cursora))
- {
- ei = NULL;
-retry1:
- rs->sr_err = bdb_cache_find_id(op, txn,
- ida, &ei, 0, &lockr );
- if (rs->sr_err != LDAP_SUCCESS) {
- if ( rs->sr_err == DB_LOCK_DEADLOCK )
- return rs->sr_err;
- if ( rs->sr_err == DB_LOCK_NOTGRANTED )
- goto retry1;
- continue;
- }
- a = ei->bei_e;
-
- /* This should only happen if the curscop IDL has maxed out and
- * turned into a range that spans IDs indiscriminately
- */
- if (!is_entry_alias(a)) {
- bdb_cache_return_entry_r (bdb, a, &lockr);
- continue;
- }
-
- /* Actually dereference the alias */
- BDB_IDL_ZERO(tmp);
- a = deref_base( op, rs, a, &matched, txn, &lockr,
- tmp, visited );
- if (a) {
- /* If the target was not already in our current candidates,
- * make note of it in the newsubs list. Also
- * set it in the scopes list so that bdb_search
- * can check it.
- */
- if (bdb_idl_insert(ids, a->e_id) == 0) {
- bdb_idl_insert(newsubs, a->e_id);
- bdb_idl_insert(scopes, a->e_id);
- }
- bdb_cache_return_entry_r( bdb, a, &lockr);
-
- } else if ( rs->sr_err == DB_LOCK_DEADLOCK ) {
- return rs->sr_err;
- } else if (matched) {
- /* Alias could not be dereferenced, or it deref'd to
- * an ID we've already seen. Ignore it.
- */
- bdb_cache_return_entry_r( bdb, matched, &lockr );
- rs->sr_text = NULL;
- }
- }
- /* If this is a OneLevel search, we're done; oldsubs only had one
- * ID in it. For a Subtree search, oldsubs may be a list of scope IDs.
- */
- if ( op->ors_scope == LDAP_SCOPE_ONELEVEL ) break;
-nextido:
- ido = bdb_idl_next( oldsubs, &cursoro );
-
- /* If we're done processing the old scopes, did we add any new
- * scopes in this iteration? If so, go back and do those now.
- */
- if (ido == NOID) {
- if (BDB_IDL_IS_ZERO(newsubs)) break;
- BDB_IDL_CPY(oldsubs, newsubs);
- BDB_IDL_ZERO(newsubs);
- cursoro = 0;
- ido = bdb_idl_first( oldsubs, &cursoro );
- }
-
- /* Find the entry corresponding to the next scope. If it can't
- * be found, ignore it and move on. This should never happen;
- * we should never see the ID of an entry that doesn't exist.
- * Set the name so that the scope's IDL can be retrieved.
- */
- ei = NULL;
-sameido:
- rs->sr_err = bdb_cache_find_id(op, txn, ido, &ei,
- 0, &locka );
- if ( rs->sr_err != LDAP_SUCCESS ) {
- if ( rs->sr_err == DB_LOCK_DEADLOCK )
- return rs->sr_err;
- if ( rs->sr_err == DB_LOCK_NOTGRANTED )
- goto sameido;
- goto nextido;
- }
- e = ei->bei_e;
- }
- return rs->sr_err;
-}
-
-/* Get the next ID from the DB. Used if the candidate list is
- * a range and simple iteration hits missing entryIDs
- */
-static int
-bdb_get_nextid(struct bdb_info *bdb, DB_TXN *ltid, ID *cursor)
-{
- DBC *curs;
- DBT key, data;
- ID id, nid;
- int rc;
-
- id = *cursor + 1;
- BDB_ID2DISK( id, &nid );
- rc = bdb->bi_id2entry->bdi_db->cursor(
- bdb->bi_id2entry->bdi_db, ltid, &curs, bdb->bi_db_opflags );
- if ( rc )
- return rc;
- key.data = &nid;
- key.size = key.ulen = sizeof(ID);
- key.flags = DB_DBT_USERMEM;
- data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
- data.dlen = data.ulen = 0;
- rc = curs->c_get( curs, &key, &data, DB_SET_RANGE );
- curs->c_close( curs );
- if ( rc )
- return rc;
- BDB_DISK2ID( &nid, cursor );
- return 0;
-}
-
-int
-bdb_search( Operation *op, SlapReply *rs )
-{
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
- ID id, cursor;
- ID lastid = NOID;
- ID candidates[BDB_IDL_UM_SIZE];
- ID scopes[BDB_IDL_DB_SIZE];
- Entry *e = NULL, base, *e_root;
- Entry *matched = NULL;
- EntryInfo *ei;
- AttributeName *attrs;
- struct berval realbase = BER_BVNULL;
- slap_mask_t mask;
- time_t stoptime;
- int manageDSAit;
- int tentries = 0;
- unsigned nentries = 0;
- int idflag = 0;
-
- DB_LOCK lock;
- struct bdb_op_info *opinfo = NULL;
- DB_TXN *ltid = NULL;
- OpExtra *oex;
-
- Debug( LDAP_DEBUG_TRACE, "=> " LDAP_XSTRING(bdb_search) "\n" );
- 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" );
-
- 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" );
-
- 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" );
- 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 );
- } 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 );
- 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 );
- }
-
-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 );
-
- 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 );
-
- } 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 );
-
- 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 );
-}
+++ /dev/null
-/* tools.c - tools for slap tools */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-#include <ac/errno.h>
-
-#define AVL_INTERNAL
-#include "back-bdb.h"
-#include "idl.h"
-
-static DBC *cursor = NULL;
-static DBT key, data;
-static EntryHeader eh;
-static ID nid, previd = NOID;
-static char ehbuf[16];
-
-typedef struct dn_id {
- ID id;
- struct berval dn;
-} dn_id;
-
-#define HOLE_SIZE 4096
-static dn_id hbuf[HOLE_SIZE], *holes = hbuf;
-static unsigned nhmax = HOLE_SIZE;
-static unsigned nholes;
-
-static int index_nattrs;
-
-static struct berval *tool_base;
-static int tool_scope;
-static Filter *tool_filter;
-static Entry *tool_next_entry;
-
-#ifdef BDB_TOOL_IDL_CACHING
-#define bdb_tool_idl_cmp BDB_SYMBOL(tool_idl_cmp)
-#define bdb_tool_idl_flush_one BDB_SYMBOL(tool_idl_flush_one)
-#define bdb_tool_idl_flush BDB_SYMBOL(tool_idl_flush)
-
-static int bdb_tool_idl_flush( BackendDB *be );
-
-#define IDBLOCK 1024
-
-typedef struct bdb_tool_idl_cache_entry {
- struct bdb_tool_idl_cache_entry *next;
- ID ids[IDBLOCK];
-} bdb_tool_idl_cache_entry;
-
-typedef struct bdb_tool_idl_cache {
- struct berval kstr;
- bdb_tool_idl_cache_entry *head, *tail;
- ID first, last;
- int count;
-} bdb_tool_idl_cache;
-
-static bdb_tool_idl_cache_entry *bdb_tool_idl_free_list;
-#endif /* BDB_TOOL_IDL_CACHING */
-
-static ID bdb_tool_ix_id;
-static Operation *bdb_tool_ix_op;
-static int *bdb_tool_index_threads, bdb_tool_index_tcount;
-static void *bdb_tool_index_rec;
-static struct bdb_info *bdb_tool_info;
-static ldap_pvt_thread_mutex_t bdb_tool_index_mutex;
-static ldap_pvt_thread_cond_t bdb_tool_index_cond_main;
-static ldap_pvt_thread_cond_t bdb_tool_index_cond_work;
-
-#if DB_VERSION_FULL >= 0x04060000
-#define USE_TRICKLE 1
-#else
-/* Seems to slow things down too much in BDB 4.5 */
-#undef USE_TRICKLE
-#endif
-
-#ifdef USE_TRICKLE
-static ldap_pvt_thread_mutex_t bdb_tool_trickle_mutex;
-static ldap_pvt_thread_cond_t bdb_tool_trickle_cond;
-static ldap_pvt_thread_cond_t bdb_tool_trickle_cond_end;
-
-static void * bdb_tool_trickle_task( void *ctx, void *ptr );
-static int bdb_tool_trickle_active;
-#endif
-
-static void * bdb_tool_index_task( void *ctx, void *ptr );
-
-static int
-bdb_tool_entry_get_int( BackendDB *be, ID id, Entry **ep );
-
-static int bdb_tool_threads;
-
-int bdb_tool_entry_open(
- BackendDB *be, int mode )
-{
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
-
- /* initialize key and data thangs */
- DBTzero( &key );
- DBTzero( &data );
- key.flags = DB_DBT_USERMEM;
- key.data = &nid;
- key.size = key.ulen = sizeof( nid );
- data.flags = DB_DBT_USERMEM;
-
- if (cursor == NULL) {
- int rc = bdb->bi_id2entry->bdi_db->cursor(
- bdb->bi_id2entry->bdi_db, bdb->bi_cache.c_txn, &cursor,
- bdb->bi_db_opflags );
- if( rc != 0 ) {
- return -1;
- }
- }
-
- /* Set up for threaded slapindex */
- if (( slapMode & (SLAP_TOOL_QUICK|SLAP_TOOL_READONLY)) == SLAP_TOOL_QUICK ) {
- if ( !bdb_tool_info ) {
-#ifdef USE_TRICKLE
- ldap_pvt_thread_mutex_init( &bdb_tool_trickle_mutex );
- ldap_pvt_thread_cond_init( &bdb_tool_trickle_cond );
- ldap_pvt_thread_cond_init( &bdb_tool_trickle_cond_end );
- ldap_pvt_thread_pool_submit( &connection_pool, bdb_tool_trickle_task, bdb->bi_dbenv );
-#endif
-
- ldap_pvt_thread_mutex_init( &bdb_tool_index_mutex );
- ldap_pvt_thread_cond_init( &bdb_tool_index_cond_main );
- ldap_pvt_thread_cond_init( &bdb_tool_index_cond_work );
- if ( bdb->bi_nattrs ) {
- int i;
- bdb_tool_threads = slap_tool_thread_max - 1;
- if ( bdb_tool_threads > 1 ) {
- bdb_tool_index_threads = ch_malloc( bdb_tool_threads * sizeof( int ));
- bdb_tool_index_rec = ch_malloc( bdb->bi_nattrs * sizeof( IndexRec ));
- bdb_tool_index_tcount = bdb_tool_threads - 1;
- for (i=1; i<bdb_tool_threads; i++) {
- int *ptr = ch_malloc( sizeof( int ));
- *ptr = i;
- ldap_pvt_thread_pool_submit( &connection_pool,
- bdb_tool_index_task, ptr );
- }
- }
- }
- bdb_tool_info = bdb;
- }
- }
-
- return 0;
-}
-
-int bdb_tool_entry_close(
- BackendDB *be )
-{
- if ( bdb_tool_info ) {
- slapd_shutdown = 1;
-#ifdef USE_TRICKLE
- ldap_pvt_thread_mutex_lock( &bdb_tool_trickle_mutex );
-
- /* trickle thread may not have started yet */
- while ( !bdb_tool_trickle_active )
- ldap_pvt_thread_cond_wait( &bdb_tool_trickle_cond_end,
- &bdb_tool_trickle_mutex );
-
- ldap_pvt_thread_cond_signal( &bdb_tool_trickle_cond );
- while ( bdb_tool_trickle_active )
- ldap_pvt_thread_cond_wait( &bdb_tool_trickle_cond_end,
- &bdb_tool_trickle_mutex );
- ldap_pvt_thread_mutex_unlock( &bdb_tool_trickle_mutex );
-#endif
- if ( bdb_tool_threads > 1 ) {
- ldap_pvt_thread_mutex_lock( &bdb_tool_index_mutex );
-
- /* There might still be some threads starting */
- while ( bdb_tool_index_tcount > 0 ) {
- ldap_pvt_thread_cond_wait( &bdb_tool_index_cond_main,
- &bdb_tool_index_mutex );
- }
-
- bdb_tool_index_tcount = bdb_tool_threads - 1;
- ldap_pvt_thread_cond_broadcast( &bdb_tool_index_cond_work );
-
- /* Make sure all threads are stopped */
- while ( bdb_tool_index_tcount > 0 ) {
- ldap_pvt_thread_cond_wait( &bdb_tool_index_cond_main,
- &bdb_tool_index_mutex );
- }
- ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex );
-
- ch_free( bdb_tool_index_threads );
- ch_free( bdb_tool_index_rec );
- bdb_tool_index_tcount = bdb_tool_threads - 1;
- }
- bdb_tool_info = NULL;
- slapd_shutdown = 0;
- }
-
- if( eh.bv.bv_val ) {
- ch_free( eh.bv.bv_val );
- eh.bv.bv_val = NULL;
- }
-
- if( cursor ) {
- cursor->c_close( cursor );
- cursor = NULL;
- }
-
-#ifdef BDB_TOOL_IDL_CACHING
- bdb_tool_idl_flush( be );
-#endif
-
- if( nholes ) {
- unsigned i;
- fprintf( stderr, "Error, entries missing!\n");
- for (i=0; i<nholes; i++) {
- fprintf(stderr, " entry %ld: %s\n",
- holes[i].id, holes[i].dn.bv_val);
- }
- return -1;
- }
-
- return 0;
-}
-
-ID
-bdb_tool_entry_first_x(
- BackendDB *be,
- struct berval *base,
- int scope,
- Filter *f )
-{
- tool_base = base;
- tool_scope = scope;
- tool_filter = f;
-
- return bdb_tool_entry_next( be );
-}
-
-ID bdb_tool_entry_next(
- BackendDB *be )
-{
- int rc;
- ID id;
- struct bdb_info *bdb;
-
- assert( be != NULL );
- assert( slapMode & SLAP_TOOL_MODE );
-
- bdb = (struct bdb_info *) be->be_private;
- assert( bdb != NULL );
-
-next:;
- /* Get the header */
- data.ulen = data.dlen = sizeof( ehbuf );
- data.data = ehbuf;
- data.flags |= DB_DBT_PARTIAL;
- rc = cursor->c_get( cursor, &key, &data, DB_NEXT );
-
- if( rc ) {
- /* If we're doing linear indexing and there are more attrs to
- * index, and we're at the end of the database, start over.
- */
- if ( index_nattrs && rc == DB_NOTFOUND ) {
- /* optional - do a checkpoint here? */
- bdb_attr_info_free( bdb->bi_attrs[0] );
- bdb->bi_attrs[0] = bdb->bi_attrs[index_nattrs];
- index_nattrs--;
- rc = cursor->c_get( cursor, &key, &data, DB_FIRST );
- if ( rc ) {
- return NOID;
- }
- } else {
- return NOID;
- }
- }
-
- BDB_DISK2ID( key.data, &id );
- previd = id;
-
- if ( tool_filter || tool_base ) {
- static Operation op = {0};
- static Opheader ohdr = {0};
-
- op.o_hdr = &ohdr;
- op.o_bd = be;
- op.o_tmpmemctx = NULL;
- op.o_tmpmfuncs = &ch_mfuncs;
-
- if ( tool_next_entry ) {
- bdb_entry_release( &op, tool_next_entry, 0 );
- tool_next_entry = NULL;
- }
-
- rc = bdb_tool_entry_get_int( be, id, &tool_next_entry );
- if ( rc == LDAP_NO_SUCH_OBJECT ) {
- goto next;
- }
-
- assert( tool_next_entry != NULL );
-
-#ifdef BDB_HIER
- /* TODO: needed until BDB_HIER is handled accordingly
- * in bdb_tool_entry_get_int() */
- if ( tool_base && !dnIsSuffixScope( &tool_next_entry->e_nname, tool_base, tool_scope ) )
- {
- bdb_entry_release( &op, tool_next_entry, 0 );
- tool_next_entry = NULL;
- goto next;
- }
-#endif
-
- if ( tool_filter && test_filter( NULL, tool_next_entry, tool_filter ) != LDAP_COMPARE_TRUE )
- {
- bdb_entry_release( &op, tool_next_entry, 0 );
- tool_next_entry = NULL;
- goto next;
- }
- }
-
- return id;
-}
-
-ID bdb_tool_dn2id_get(
- Backend *be,
- struct berval *dn
-)
-{
- Operation op = {0};
- Opheader ohdr = {0};
- EntryInfo *ei = NULL;
- int rc;
-
- if ( BER_BVISEMPTY(dn) )
- return 0;
-
- op.o_hdr = &ohdr;
- op.o_bd = be;
- op.o_tmpmemctx = NULL;
- op.o_tmpmfuncs = &ch_mfuncs;
-
- rc = bdb_cache_find_ndn( &op, 0, dn, &ei );
- if ( ei ) bdb_cache_entryinfo_unlock( ei );
- if ( rc == DB_NOTFOUND )
- return NOID;
-
- return ei->bei_id;
-}
-
-static int
-bdb_tool_entry_get_int( BackendDB *be, ID id, Entry **ep )
-{
- Entry *e = NULL;
- char *dptr;
- int rc, eoff;
-
- assert( be != NULL );
- assert( slapMode & SLAP_TOOL_MODE );
-
- if ( ( tool_filter || tool_base ) && id == previd && tool_next_entry != NULL ) {
- *ep = tool_next_entry;
- tool_next_entry = NULL;
- return LDAP_SUCCESS;
- }
-
- if ( id != previd ) {
- data.ulen = data.dlen = sizeof( ehbuf );
- data.data = ehbuf;
- data.flags |= DB_DBT_PARTIAL;
-
- BDB_ID2DISK( id, &nid );
- rc = cursor->c_get( cursor, &key, &data, DB_SET );
- if ( rc ) {
- rc = LDAP_OTHER;
- goto done;
- }
- }
-
- /* Get the header */
- dptr = eh.bv.bv_val;
- eh.bv.bv_val = ehbuf;
- eh.bv.bv_len = data.size;
- rc = entry_header( &eh );
- eoff = eh.data - eh.bv.bv_val;
- eh.bv.bv_val = dptr;
- if ( rc ) {
- rc = LDAP_OTHER;
- goto done;
- }
-
- /* Get the size */
- data.flags &= ~DB_DBT_PARTIAL;
- data.ulen = 0;
- rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
- if ( rc != DB_BUFFER_SMALL ) {
- rc = LDAP_OTHER;
- goto done;
- }
-
- /* Allocate a block and retrieve the data */
- eh.bv.bv_len = eh.nvals * sizeof( struct berval ) + data.size;
- eh.bv.bv_val = ch_realloc( eh.bv.bv_val, eh.bv.bv_len );
- eh.data = eh.bv.bv_val + eh.nvals * sizeof( struct berval );
- data.data = eh.data;
- data.ulen = data.size;
-
- /* Skip past already parsed nattr/nvals */
- eh.data += eoff;
-
- rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
- if ( rc ) {
- rc = LDAP_OTHER;
- goto done;
- }
-
-#ifndef BDB_HIER
- /* TODO: handle BDB_HIER accordingly */
- if ( tool_base != NULL ) {
- struct berval ndn;
- entry_decode_dn( &eh, NULL, &ndn );
-
- if ( !dnIsSuffixScope( &ndn, tool_base, tool_scope ) ) {
- return LDAP_NO_SUCH_OBJECT;
- }
- }
-#endif
-
-#ifdef SLAP_ZONE_ALLOC
- /* FIXME: will add ctx later */
- rc = entry_decode( &eh, &e, NULL );
-#else
- rc = entry_decode( &eh, &e );
-#endif
-
- if( rc == LDAP_SUCCESS ) {
- e->e_id = id;
-#ifdef BDB_HIER
- if ( slapMode & SLAP_TOOL_READONLY ) {
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
- EntryInfo *ei = NULL;
- Operation op = {0};
- Opheader ohdr = {0};
-
- op.o_hdr = &ohdr;
- op.o_bd = be;
- op.o_tmpmemctx = NULL;
- op.o_tmpmfuncs = &ch_mfuncs;
-
- rc = bdb_cache_find_parent( &op, bdb->bi_cache.c_txn, id, &ei );
- if ( rc == LDAP_SUCCESS ) {
- bdb_cache_entryinfo_unlock( ei );
- e->e_private = ei;
- ei->bei_e = e;
- bdb_fix_dn( e, 0 );
- ei->bei_e = NULL;
- e->e_private = NULL;
- }
- }
-#endif
- }
-done:
- if ( e != NULL ) {
- *ep = e;
- }
-
- return rc;
-}
-
-Entry*
-bdb_tool_entry_get( BackendDB *be, ID id )
-{
- Entry *e = NULL;
-
- (void)bdb_tool_entry_get_int( be, id, &e );
- return e;
-}
-
-static int bdb_tool_next_id(
- Operation *op,
- DB_TXN *tid,
- Entry *e,
- struct berval *text,
- int hole )
-{
- struct berval dn = e->e_name;
- struct berval ndn = e->e_nname;
- struct berval pdn, npdn;
- EntryInfo *ei = NULL, eidummy;
- int rc;
-
- if (ndn.bv_len == 0) {
- e->e_id = 0;
- return 0;
- }
-
- rc = bdb_cache_find_ndn( op, tid, &ndn, &ei );
- if ( ei ) bdb_cache_entryinfo_unlock( ei );
- if ( rc == DB_NOTFOUND ) {
- if ( !be_issuffix( op->o_bd, &ndn ) ) {
- ID eid = e->e_id;
- dnParent( &dn, &pdn );
- dnParent( &ndn, &npdn );
- e->e_name = pdn;
- e->e_nname = npdn;
- rc = bdb_tool_next_id( op, tid, e, text, 1 );
- e->e_name = dn;
- e->e_nname = ndn;
- if ( rc ) {
- return rc;
- }
- /* If parent didn't exist, it was created just now
- * and its ID is now in e->e_id. Make sure the current
- * entry gets added under the new parent ID.
- */
- if ( eid != e->e_id ) {
- eidummy.bei_id = e->e_id;
- ei = &eidummy;
- }
- }
- rc = bdb_next_id( op->o_bd, &e->e_id );
- if ( rc ) {
- snprintf( text->bv_val, text->bv_len,
- "next_id failed: %s (%d)",
- db_strerror(rc), rc );
- Debug( LDAP_DEBUG_ANY,
- "=> bdb_tool_next_id: %s\n", text->bv_val );
- 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 );
- } else if ( hole ) {
- if ( nholes == nhmax - 1 ) {
- if ( holes == hbuf ) {
- holes = ch_malloc( nhmax * sizeof(dn_id) * 2 );
- AC_MEMCPY( holes, hbuf, sizeof(hbuf) );
- } else {
- holes = ch_realloc( holes, nhmax * sizeof(dn_id) * 2 );
- }
- nhmax *= 2;
- }
- ber_dupbv( &holes[nholes].dn, &ndn );
- holes[nholes++].id = e->e_id;
- }
- } else if ( !hole ) {
- unsigned i, j;
-
- e->e_id = ei->bei_id;
-
- for ( i=0; i<nholes; i++) {
- if ( holes[i].id == e->e_id ) {
- free(holes[i].dn.bv_val);
- for (j=i;j<nholes;j++) holes[j] = holes[j+1];
- holes[j].id = 0;
- nholes--;
- break;
- } else if ( holes[i].id > e->e_id ) {
- break;
- }
- }
- }
- return rc;
-}
-
-static int
-bdb_tool_index_add(
- Operation *op,
- DB_TXN *txn,
- Entry *e )
-{
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-
- if ( !bdb->bi_nattrs )
- return 0;
-
- if ( bdb_tool_threads > 1 ) {
- IndexRec *ir;
- int i, rc;
- Attribute *a;
-
- ir = bdb_tool_index_rec;
- memset(ir, 0, bdb->bi_nattrs * sizeof( IndexRec ));
-
- for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
- rc = bdb_index_recset( bdb, a, a->a_desc->ad_type,
- &a->a_desc->ad_tags, ir );
- if ( rc )
- return rc;
- }
- bdb_tool_ix_id = e->e_id;
- bdb_tool_ix_op = op;
- ldap_pvt_thread_mutex_lock( &bdb_tool_index_mutex );
- /* Wait for all threads to be ready */
- while ( bdb_tool_index_tcount > 0 ) {
- ldap_pvt_thread_cond_wait( &bdb_tool_index_cond_main,
- &bdb_tool_index_mutex );
- }
- for ( i=1; i<bdb_tool_threads; i++ )
- bdb_tool_index_threads[i] = LDAP_BUSY;
- bdb_tool_index_tcount = bdb_tool_threads - 1;
- ldap_pvt_thread_cond_broadcast( &bdb_tool_index_cond_work );
- ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex );
- rc = bdb_index_recrun( op, bdb, ir, e->e_id, 0 );
- if ( rc )
- return rc;
- ldap_pvt_thread_mutex_lock( &bdb_tool_index_mutex );
- for ( i=1; i<bdb_tool_threads; i++ ) {
- if ( bdb_tool_index_threads[i] == LDAP_BUSY ) {
- ldap_pvt_thread_cond_wait( &bdb_tool_index_cond_main,
- &bdb_tool_index_mutex );
- i--;
- continue;
- }
- if ( bdb_tool_index_threads[i] ) {
- rc = bdb_tool_index_threads[i];
- break;
- }
- }
- ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex );
- return rc;
- } else {
- return bdb_index_entry_add( op, txn, e );
- }
-}
-
-ID bdb_tool_entry_put(
- BackendDB *be,
- Entry *e,
- struct berval *text )
-{
- int rc;
- struct bdb_info *bdb;
- DB_TXN *tid = NULL;
- Operation op = {0};
- Opheader ohdr = {0};
-
- assert( be != NULL );
- assert( slapMode & SLAP_TOOL_MODE );
-
- assert( text != NULL );
- assert( text->bv_val != NULL );
- assert( text->bv_val[0] == '\0' ); /* overconservative? */
-
- Debug( LDAP_DEBUG_TRACE, "=> " LDAP_XSTRING(bdb_tool_entry_put)
- "( %ld, \"%s\" )\n", (long) e->e_id, e->e_dn );
-
- 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 );
- return NOID;
- }
- Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_tool_entry_put) ": txn id: %x\n",
- tid->id(tid) );
- }
-
- 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 );
- 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 );
- 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 );
- 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 );
- }
- e->e_id = NOID;
- }
-
- 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 )
- 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 );
- 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 );
- 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 );
- 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 );
- goto done;
- }
- Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_tool_entry_reindex) ": txn id: %x\n",
- tid->id(tid) );
- }
-
- /*
- * 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 );
-
- 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 );
- 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 );
- }
- 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 );
-
- 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 );
- return NOID;
- }
- Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_tool_entry_modify) ": txn id: %x\n",
- tid->id(tid) );
- }
-
- 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 );
- 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 );
- 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 );
- }
- e->e_id = NOID;
- }
-
- 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 )
- e->e_id = NOID;
- }
-
- return e->e_id;
-}
-
-int bdb_tool_entry_delete(
- BackendDB *be,
- struct berval *ndn,
- struct berval *text )
-{
- int rc;
- struct bdb_info *bdb;
- DB_TXN *tid = NULL;
- Operation op = {0};
- Opheader ohdr = {0};
- EntryInfo *ei, *eip;
- Entry *e;
- DB_LOCK lock;
-
- assert( be != NULL );
- assert( slapMode & SLAP_TOOL_MODE );
-
- assert( text != NULL );
- assert( text->bv_val != NULL );
- assert( text->bv_val[0] == '\0' ); /* overconservative? */
-
- assert ( ndn != NULL );
- assert ( ndn->bv_val != NULL );
-
- Debug( LDAP_DEBUG_TRACE,
- "=> " LDAP_XSTRING(bdb_tool_entry_delete) "( %s )\n",
- ndn->bv_val );
-
- 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_delete) ": %s\n",
- text->bv_val );
- return LDAP_OTHER;
- }
- rc = bdb->bi_id2entry->bdi_db->cursor(
- bdb->bi_id2entry->bdi_db, bdb->bi_cache.c_txn, &cursor,
- bdb->bi_db_opflags );
- }
-
- op.o_hdr = &ohdr;
- op.o_bd = be;
- op.o_tmpmemctx = NULL;
- op.o_tmpmfuncs = &ch_mfuncs;
-
- /* do the deletion */
- rc = bdb_dn2entry( &op, tid, ndn, &ei, 1, &lock );
- if( rc != 0 ) {
- snprintf( text->bv_val, text->bv_len,
- "dn2entry failed: %s (%d)",
- db_strerror(rc), rc );
- Debug( LDAP_DEBUG_ANY,
- "=> " LDAP_XSTRING(bdb_tool_entry_delete) ": %s\n",
- text->bv_val );
- goto done;
- }
-
- e = ei->bei_e;
- eip = ei->bei_parent;
-
- rc = bdb_cache_children( &op, tid, e );
- if( rc != DB_NOTFOUND ) {
- switch( rc ) {
- case 0:
- snprintf( text->bv_val, text->bv_len,
- "delete failed:"
- " subordinate objects must be deleted first");
- break;
- default:
- snprintf( text->bv_val, text->bv_len,
- "has_children failed: %s (%d)",
- db_strerror(rc), rc );
- break;
- }
- rc = -1;
- Debug( LDAP_DEBUG_ANY,
- "=> " LDAP_XSTRING(mdb_tool_entry_delete) ": %s\n",
- text->bv_val );
- goto done;
- }
- rc = bdb_dn2id_delete( &op, tid, eip, e );
- if( rc != 0 ) {
- snprintf( text->bv_val, text->bv_len,
- "dn2entry failed: %s (%d)",
- db_strerror(rc), rc );
- Debug( LDAP_DEBUG_ANY,
- "=> " LDAP_XSTRING(bdb_tool_entry_delete) ": %s\n",
- text->bv_val );
- goto done;
- }
-
- rc = bdb_index_entry_del( &op, tid, e );
- if( rc != 0 ) {
- snprintf( text->bv_val, text->bv_len,
- "dn2entry failed: %s (%d)",
- db_strerror(rc), rc );
- Debug( LDAP_DEBUG_ANY,
- "=> " LDAP_XSTRING(bdb_tool_entry_delete) ": %s\n",
- text->bv_val );
- goto done;
- }
-
- rc = bdb_id2entry_delete( be, tid, e );
- if( rc != 0 ) {
- snprintf( text->bv_val, text->bv_len,
- "dn2entry failed: %s (%d)",
- db_strerror(rc), rc );
- Debug( LDAP_DEBUG_ANY,
- "=> " LDAP_XSTRING(bdb_tool_entry_delete) ": %s\n",
- text->bv_val );
- goto done;
- }
-
-done:
- /* Free the EntryInfo and the Entry */
- if( e != NULL ) {
- bdb_entry_release( &op, e, 0 );
- }
-
- 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_delete) ": "
- "%s\n", text->bv_val );
- }
- }
-
- } 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_delete) ": %s\n",
- text->bv_val );
- }
- }
-
- if ( cursor == NULL )
- {
- rc = bdb->bi_id2entry->bdi_db->cursor(
- bdb->bi_id2entry->bdi_db, bdb->bi_cache.c_txn, &cursor,
- bdb->bi_db_opflags );
- }
-
- return rc;
-}
-
-#ifdef BDB_TOOL_IDL_CACHING
-static int
-bdb_tool_idl_cmp( const void *v1, const void *v2 )
-{
- const bdb_tool_idl_cache *c1 = v1, *c2 = v2;
- int rc;
-
- if (( rc = c1->kstr.bv_len - c2->kstr.bv_len )) return rc;
- return memcmp( c1->kstr.bv_val, c2->kstr.bv_val, c1->kstr.bv_len );
-}
-
-static int
-bdb_tool_idl_flush_one( void *v1, void *arg )
-{
- bdb_tool_idl_cache *ic = v1;
- DB *db = arg;
- struct bdb_info *bdb = bdb_tool_info;
- bdb_tool_idl_cache_entry *ice;
- DBC *curs;
- DBT key, data;
- int i, rc;
- ID id, nid;
-
- /* Freshly allocated, ignore it */
- if ( !ic->head && ic->count <= BDB_IDL_DB_SIZE ) {
- return 0;
- }
-
- rc = db->cursor( db, NULL, &curs, 0 );
- if ( rc )
- return -1;
-
- DBTzero( &key );
- DBTzero( &data );
-
- bv2DBT( &ic->kstr, &key );
-
- data.size = data.ulen = sizeof( ID );
- data.flags = DB_DBT_USERMEM;
- data.data = &nid;
-
- rc = curs->c_get( curs, &key, &data, DB_SET );
- /* If key already exists and we're writing a range... */
- if ( rc == 0 && ic->count > BDB_IDL_DB_SIZE ) {
- /* If it's not currently a range, must delete old info */
- if ( nid ) {
- /* Skip lo */
- while ( curs->c_get( curs, &key, &data, DB_NEXT_DUP ) == 0 )
- curs->c_del( curs, 0 );
-
- nid = 0;
- /* Store range marker */
- curs->c_put( curs, &key, &data, DB_KEYFIRST );
- } else {
-
- /* Skip lo */
- rc = curs->c_get( curs, &key, &data, DB_NEXT_DUP );
-
- /* Get hi */
- rc = curs->c_get( curs, &key, &data, DB_NEXT_DUP );
-
- /* Delete hi */
- curs->c_del( curs, 0 );
- }
- BDB_ID2DISK( ic->last, &nid );
- curs->c_put( curs, &key, &data, DB_KEYLAST );
- rc = 0;
- } else if ( rc && rc != DB_NOTFOUND ) {
- rc = -1;
- } else if ( ic->count > BDB_IDL_DB_SIZE ) {
- /* range, didn't exist before */
- nid = 0;
- rc = curs->c_put( curs, &key, &data, DB_KEYLAST );
- if ( rc == 0 ) {
- BDB_ID2DISK( ic->first, &nid );
- rc = curs->c_put( curs, &key, &data, DB_KEYLAST );
- if ( rc == 0 ) {
- BDB_ID2DISK( ic->last, &nid );
- rc = curs->c_put( curs, &key, &data, DB_KEYLAST );
- }
- }
- if ( rc ) {
- rc = -1;
- }
- } else {
- int n;
-
- /* Just a normal write */
- rc = 0;
- for ( ice = ic->head, n=0; ice; ice = ice->next, n++ ) {
- int end;
- if ( ice->next ) {
- end = IDBLOCK;
- } else {
- end = ic->count & (IDBLOCK-1);
- if ( !end )
- end = IDBLOCK;
- }
- for ( i=0; i<end; i++ ) {
- if ( !ice->ids[i] ) continue;
- BDB_ID2DISK( ice->ids[i], &nid );
- rc = curs->c_put( curs, &key, &data, DB_NODUPDATA );
- if ( rc ) {
- if ( rc == DB_KEYEXIST ) {
- rc = 0;
- continue;
- }
- rc = -1;
- break;
- }
- }
- if ( rc ) {
- rc = -1;
- break;
- }
- }
- if ( ic->head ) {
- ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock );
- ic->tail->next = bdb_tool_idl_free_list;
- bdb_tool_idl_free_list = ic->head;
- bdb->bi_idl_cache_size -= n;
- ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
- }
- }
- if ( ic != db->app_private ) {
- ch_free( ic );
- } else {
- ic->head = ic->tail = NULL;
- }
- curs->c_close( curs );
- return rc;
-}
-
-static int
-bdb_tool_idl_flush_db( DB *db, bdb_tool_idl_cache *ic )
-{
- Avlnode *root = db->app_private;
- int rc;
-
- db->app_private = ic;
- rc = avl_apply( root, bdb_tool_idl_flush_one, db, -1, AVL_INORDER );
- avl_free( root, NULL );
- db->app_private = NULL;
- if ( rc != -1 )
- rc = 0;
- return rc;
-}
-
-static int
-bdb_tool_idl_flush( BackendDB *be )
-{
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
- DB *db;
- Avlnode *root;
- int i, rc = 0;
-
- for ( i=BDB_NDB; i < bdb->bi_ndatabases; i++ ) {
- db = bdb->bi_databases[i]->bdi_db;
- if ( !db->app_private ) continue;
- rc = bdb_tool_idl_flush_db( db, NULL );
- if ( rc )
- break;
- }
- if ( !rc ) {
- bdb->bi_idl_cache_size = 0;
- }
- return rc;
-}
-
-int bdb_tool_idl_add(
- BackendDB *be,
- DB *db,
- DB_TXN *txn,
- DBT *key,
- ID id )
-{
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
- bdb_tool_idl_cache *ic, itmp;
- bdb_tool_idl_cache_entry *ice;
- int rc;
-
- if ( !bdb->bi_idl_cache_max_size )
- return bdb_idl_insert_key( be, db, txn, key, id );
-
- DBT2bv( key, &itmp.kstr );
-
- ic = avl_find( (Avlnode *)db->app_private, &itmp, bdb_tool_idl_cmp );
-
- /* No entry yet, create one */
- if ( !ic ) {
- DBC *curs;
- DBT data;
- ID nid;
- int rc;
-
- ic = ch_malloc( sizeof( bdb_tool_idl_cache ) + itmp.kstr.bv_len );
- ic->kstr.bv_len = itmp.kstr.bv_len;
- ic->kstr.bv_val = (char *)(ic+1);
- AC_MEMCPY( ic->kstr.bv_val, itmp.kstr.bv_val, ic->kstr.bv_len );
- ic->head = ic->tail = NULL;
- ic->last = 0;
- ic->count = 0;
- avl_insert( (Avlnode **)&db->app_private, ic, bdb_tool_idl_cmp,
- avl_dup_error );
-
- /* load existing key count here */
- rc = db->cursor( db, NULL, &curs, 0 );
- if ( rc ) return rc;
-
- data.ulen = sizeof( ID );
- data.flags = DB_DBT_USERMEM;
- data.data = &nid;
- rc = curs->c_get( curs, key, &data, DB_SET );
- if ( rc == 0 ) {
- if ( nid == 0 ) {
- ic->count = BDB_IDL_DB_SIZE+1;
- } else {
- db_recno_t count;
-
- curs->c_count( curs, &count, 0 );
- ic->count = count;
- BDB_DISK2ID( &nid, &ic->first );
- }
- }
- curs->c_close( curs );
- }
- /* are we a range already? */
- if ( ic->count > BDB_IDL_DB_SIZE ) {
- ic->last = id;
- return 0;
- /* Are we at the limit, and converting to a range? */
- } else if ( ic->count == BDB_IDL_DB_SIZE ) {
- int n;
- for ( ice = ic->head, n=0; ice; ice = ice->next, n++ )
- /* counting */ ;
- if ( n ) {
- ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock );
- ic->tail->next = bdb_tool_idl_free_list;
- bdb_tool_idl_free_list = ic->head;
- bdb->bi_idl_cache_size -= n;
- ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
- }
- ic->head = ic->tail = NULL;
- ic->last = id;
- ic->count++;
- return 0;
- }
- /* No free block, create that too */
- if ( !ic->tail || ( ic->count & (IDBLOCK-1)) == 0) {
- ice = NULL;
- ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock );
- if ( bdb->bi_idl_cache_size >= bdb->bi_idl_cache_max_size ) {
- ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
- rc = bdb_tool_idl_flush_db( db, ic );
- if ( rc )
- return rc;
- avl_insert( (Avlnode **)&db->app_private, ic, bdb_tool_idl_cmp,
- avl_dup_error );
- ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock );
- }
- bdb->bi_idl_cache_size++;
- if ( bdb_tool_idl_free_list ) {
- ice = bdb_tool_idl_free_list;
- bdb_tool_idl_free_list = ice->next;
- }
- ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
- if ( !ice ) {
- ice = ch_malloc( sizeof( bdb_tool_idl_cache_entry ));
- }
- memset( ice, 0, sizeof( *ice ));
- if ( !ic->head ) {
- ic->head = ice;
- } else {
- ic->tail->next = ice;
- }
- ic->tail = ice;
- if ( !ic->count )
- ic->first = id;
- }
- ice = ic->tail;
- ice->ids[ ic->count & (IDBLOCK-1) ] = id;
- ic->count++;
-
- return 0;
-}
-#endif
-
-#ifdef USE_TRICKLE
-static void *
-bdb_tool_trickle_task( void *ctx, void *ptr )
-{
- DB_ENV *env = ptr;
- int wrote;
-
- ldap_pvt_thread_mutex_lock( &bdb_tool_trickle_mutex );
- bdb_tool_trickle_active = 1;
- ldap_pvt_thread_cond_signal( &bdb_tool_trickle_cond_end );
- while ( 1 ) {
- ldap_pvt_thread_cond_wait( &bdb_tool_trickle_cond,
- &bdb_tool_trickle_mutex );
- if ( slapd_shutdown )
- break;
- env->memp_trickle( env, 30, &wrote );
- }
- bdb_tool_trickle_active = 0;
- ldap_pvt_thread_cond_signal( &bdb_tool_trickle_cond_end );
- ldap_pvt_thread_mutex_unlock( &bdb_tool_trickle_mutex );
-
- return NULL;
-}
-#endif
-
-static void *
-bdb_tool_index_task( void *ctx, void *ptr )
-{
- int base = *(int *)ptr;
-
- free( ptr );
- while ( 1 ) {
- ldap_pvt_thread_mutex_lock( &bdb_tool_index_mutex );
- bdb_tool_index_tcount--;
- if ( !bdb_tool_index_tcount )
- ldap_pvt_thread_cond_signal( &bdb_tool_index_cond_main );
- ldap_pvt_thread_cond_wait( &bdb_tool_index_cond_work,
- &bdb_tool_index_mutex );
- if ( slapd_shutdown ) {
- bdb_tool_index_tcount--;
- if ( !bdb_tool_index_tcount )
- ldap_pvt_thread_cond_signal( &bdb_tool_index_cond_main );
- ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex );
- break;
- }
- ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex );
-
- bdb_tool_index_threads[base] = bdb_index_recrun( bdb_tool_ix_op,
- bdb_tool_info, bdb_tool_index_rec, bdb_tool_ix_id, base );
- }
-
- return NULL;
-}
+++ /dev/null
-/* trans.c - bdb backend transaction routines */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-
-#include "back-bdb.h"
-#include "lber_pvt.h"
-#include "lutil.h"
-
-
-/* Congestion avoidance code
- * for Deadlock Rollback
- */
-
-void
-bdb_trans_backoff( int num_retries )
-{
- int i;
- int delay = 0;
- int pow_retries = 1;
- unsigned long key = 0;
- unsigned long max_key = -1;
- struct timeval timeout;
-
- lutil_entropy( (unsigned char *) &key, sizeof( unsigned long ));
-
- for ( i = 0; i < num_retries; i++ ) {
- if ( i >= 5 ) break;
- pow_retries *= 4;
- }
-
- delay = 16384 * (key * (double) pow_retries / (double) max_key);
- delay = delay ? delay : 1;
-
- Debug( LDAP_DEBUG_TRACE, "delay = %d, num_retries = %d\n", delay, num_retries );
-
- timeout.tv_sec = delay / 1000000;
- timeout.tv_usec = delay % 1000000;
- select( 0, NULL, NULL, NULL, &timeout );
-}
+++ /dev/null
-# Makefile for back-hdb
-# $OpenLDAP$
-## This work is part of OpenLDAP Software <http://www.openldap.org/>.
-##
-## Copyright 1998-2019 The OpenLDAP Foundation.
-## All rights reserved.
-##
-## Redistribution and use in source and binary forms, with or without
-## modification, are permitted only as authorized by the OpenLDAP
-## Public License.
-##
-## A copy of this license is available in the file LICENSE in the
-## top-level directory of the distribution or, alternatively, at
-## <http://www.OpenLDAP.org/license.html>.
-#
-## Copyright 2003 Howard Chu @ Symas Corp. See master COPYRIGHT file for terms.
-
-XXDIR = $(srcdir)/../back-bdb
-
-XXSRCS = init.c tools.c config.c \
- add.c bind.c compare.c delete.c modify.c modrdn.c search.c \
- extended.c referral.c operational.c \
- attr.c index.c key.c dbcache.c filterindex.c trans.c \
- dn2entry.c dn2id.c error.c id2entry.c idl.c nextid.c cache.c \
- monitor.c
-SRCS = $(XXSRCS)
-OBJS = init.lo tools.lo config.lo \
- add.lo bind.lo compare.lo delete.lo modify.lo modrdn.lo search.lo \
- extended.lo referral.lo operational.lo \
- attr.lo index.lo key.lo dbcache.lo filterindex.lo trans.lo \
- dn2entry.lo dn2id.lo error.lo id2entry.lo idl.lo nextid.lo cache.lo \
- monitor.lo
-
-LDAP_INCDIR= ../../../include
-LDAP_LIBDIR= ../../../libraries
-
-BUILD_OPT = "--enable-hdb"
-BUILD_MOD = @BUILD_HDB@
-
-mod_DEFS = -DSLAPD_IMPORT
-MOD_DEFS = $(@BUILD_HDB@_DEFS)
-MOD_LIBS = $(BDB_LIBS)
-
-shared_LDAP_LIBS = $(LDAP_LIBLDAP_R_LA) $(LDAP_LIBLBER_LA)
-NT_LINK_LIBS = -L.. -lslapd $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
-UNIX_LINK_LIBS = $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
-
-.links : Makefile
- @for i in $(XXSRCS); do \
- $(RM) $$i; \
- $(LN_S) $(XXDIR)/$$i . ; \
- done
- touch .links
-
-$(XXSRCS) : .links
-
-LIBBASE = back_hdb
-
-XINCPATH = -I.. -I$(srcdir)/.. -I$(srcdir) -I$(XXDIR)
-XDEFS = $(MODULES_CPPFLAGS)
-
-depend-local-lib: .links
-
-all-local-lib: ../.backend
-
-../.backend: lib$(LIBBASE).a
- @touch $@
-
-veryclean-local: FORCE
- $(RM) $(XXSRCS) .links
+++ /dev/null
-/* back-bdb.h - hdb back-end header file */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2000-2019 The OpenLDAP Foundation.
- * Portions Copyright 2003 Howard Chu @ Symas Corp.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was originally developed by Howard Chu for inclusion
- * in OpenLDAP Software.
- */
-
-#ifndef _BACK_HDB_H_
-#define _BACK_HDB_H_
-
-#ifndef BDB_HIER
-#define BDB_HIER 1
-#endif
-
-#include "../back-bdb/back-bdb.h"
-
-#endif /* _BACK_HDB_H_ */
#endif /* !_WIN32 */
/*
- * Left and Right "{num}" prefix to ordered RDNs ("olcDatabase={1}bdb").
+ * Left and Right "{num}" prefix to ordered RDNs ("olcDatabase={1}mdb").
* IX_DN* are for LDAP RDNs, IX_FS* for their .ldif filenames.
*/
#define IX_DNL '{'
{ "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 */
{ "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 */
* 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
/* 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.
*/
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 );
}
}
#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];
/*
* 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
#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
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
@$(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"
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"
verify basic functionality of the LDAP libraries and slapd.
To run all of the tests, type "make test".
- To run BDB tests, type "make bdb".
- To run HDB tests, type "make hdb".
To run MDB tests, type "make mdb".
To run SQL tests, define SLAPD_USE_SQL=<rdbms> and type
"make sql"; define SLAPD_USE_SQLWRITE=yes
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
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 &
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
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
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"
#~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
export SRCDIR TOPSRCDIR LN_S EGREP_CMD
# backends known to ./run -b <backend> (used to deduce $BACKENDTYPE)
-AC_bdb=@BUILD_BDB@
-AC_hdb=@BUILD_HDB@
AC_ldif=yes
AC_mdb=@BUILD_MDB@
AC_null=@BUILD_NULL@
if test "${AC_asyncmeta}" = "metamod" && test "${AC_LIBS_DYNAMIC}" = "static" ; then
AC_meta="asyncmetano"
fi
-export AC_bdb AC_hdb AC_ldap AC_mdb AC_meta AC_asyncmeta AC_monitor AC_null AC_relay AC_sql \
+export AC_ldap AC_mdb AC_meta AC_asyncmeta AC_monitor AC_null AC_relay AC_sql \
AC_accesslog AC_autoca 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 \
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
# 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
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
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
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"
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 &
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..."
mkdir -p $TESTDIR $DBDIR1A $DBDIR1B $DBDIR2
-SPEC="mdb=a,bdb=a,hdb=a"
+SPEC="mdb=a"
#
# Test replication:
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
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
exit $RC
fi
-case $BACKEND in bdb | hdb)
-db_stat=
-for path in `echo "$PATH" | sed -e 's/:/ /g'`; do
- if test -f "$path/db_stat" && \
- "$path/db_stat" -E -h $PRODDIR/db > /dev/null 2>&1
- then
- db_stat="$path/db_stat"
- break
- fi
-done
-
-if test -z "$db_stat" ; then
- echo "Could not find a working db_stat in PATH!"
- lock_bug=1
-elif "$db_stat" -E -h $PRODDIR/db | egrep -q 'HELD .* len:'; then
- echo "WARNING: Glue lock bug hit, next modify could deadlock"
- lock_bug=2
-else
- echo "Glue lock bug not found :-)"
- lock_bug=0
-fi
-esac
-
echo "Using ldapmodify to modify glue suffix on provider..."
$LDAPADD -D "$MANAGERDN" -H $URI1 -w $PASSWD <<EOF >> $TESTOUT 2>&1
dn: dc=example,dc=com
$LDAPSEARCH -S "" -b "$DATABASESMONITORDN" -h $LOCALHOST -p $PORT1 \
'objectclass=*' \
structuralObjectClass entryDN namingContexts readOnly \
- monitorIsShadow monitorContext \
- olmBDBEntryCache olmBDBDNCache olmBDBIDLCache \
+ monitorIsShadow monitorContext
> $SEARCHOUT 2>&1
RC=$?
TMPMONITOROUT2=$MONITOROUT2
case $BACKEND in
-bdb|hdb)
- ;;
*)
TMPMONITOROUT2=$TESTDIR/monitor2.out
- grep -v "olmBDB" $MONITOROUT2 > $TMPMONITOROUT2
;;
esac
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
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
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
$SLAPPASSWD -g -n >$CONFIGPWF
case "$BACKEND" in
- bdb|hdb) olcDbCheckpoint="olcDbCheckpoint";;
*) olcDbCheckpoint="# olcDbCheckpoint";;
esac
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 &