22207 lines
591 KiB
Diff
22207 lines
591 KiB
Diff
From 8897fff4f352923b91e776bf9bc0bf8dbd636e85 Mon Sep 17 00:00:00 2001
|
|
From: zhangqiumiao <zhangqiumiao1@huawei.com>
|
|
Date: Fri, 25 Sep 2020 21:54:05 +0800
|
|
Subject: [PATCH] backport delete back-bdb/back-hdb
|
|
|
|
---
|
|
INSTALL | 3 -
|
|
build/openldap.m4 | 292 ---
|
|
build/top.mk | 1 -
|
|
configure.in | 74 +-
|
|
contrib/slapd-modules/allowed/allowed.c | 2 +-
|
|
contrib/slapd-modules/nssov/README | 4 +-
|
|
contrib/slapd-modules/nssov/slapo-nssov.5 | 2 +-
|
|
doc/guide/admin/appendix-changes.sdf | 27 +-
|
|
doc/guide/admin/appendix-common-errors.sdf | 10 +-
|
|
doc/guide/admin/aspell.en.pws | 7 -
|
|
doc/guide/admin/backends.sdf | 47 +-
|
|
doc/guide/admin/install.sdf | 17 -
|
|
doc/guide/admin/intro.sdf | 12 +-
|
|
doc/guide/admin/maintenance.sdf | 86 +-
|
|
doc/guide/admin/monitoringslapd.sdf | 25 +-
|
|
doc/guide/admin/overlays.sdf | 6 +-
|
|
doc/guide/admin/replication.sdf | 12 +-
|
|
doc/guide/admin/slapdconf2.sdf | 237 +--
|
|
doc/guide/admin/slapdconfig.sdf | 218 ++-
|
|
doc/guide/admin/tuning.sdf | 175 +-
|
|
doc/guide/preamble.sdf | 2 -
|
|
doc/guide/release/install.sdf | 2 +-
|
|
doc/man/man5/slapd-bdb.5 | 286 ---
|
|
doc/man/man5/slapd-bdb.5.links | 1 -
|
|
doc/man/man5/slapd-config.5 | 8 +-
|
|
doc/man/man5/slapd-mdb.5 | 7 +-
|
|
doc/man/man5/slapd-sql.5 | 2 +-
|
|
doc/man/man5/slapd.access.5 | 9 +-
|
|
doc/man/man5/slapd.backends.5 | 35 +-
|
|
doc/man/man5/slapd.conf.5 | 7 +-
|
|
doc/man/man5/slapd.overlays.5 | 6 +-
|
|
doc/man/man8/slapcat.8 | 2 -
|
|
doc/man/man8/slapschema.8 | 3 +-
|
|
include/portable.hin | 12 -
|
|
servers/slapd/DB_CONFIG | 28 -
|
|
servers/slapd/Makefile.in | 12 +-
|
|
servers/slapd/alock.c | 718 -------
|
|
servers/slapd/alock.h | 74 -
|
|
servers/slapd/back-bdb/Makefile.in | 53 -
|
|
servers/slapd/back-bdb/add.c | 547 ------
|
|
servers/slapd/back-bdb/attr.c | 441 -----
|
|
servers/slapd/back-bdb/back-bdb.h | 377 ----
|
|
servers/slapd/back-bdb/bind.c | 166 --
|
|
servers/slapd/back-bdb/cache.c | 1692 -----------------
|
|
servers/slapd/back-bdb/compare.c | 143 --
|
|
servers/slapd/back-bdb/config.c | 951 ---------
|
|
servers/slapd/back-bdb/dbcache.c | 210 --
|
|
servers/slapd/back-bdb/delete.c | 605 ------
|
|
servers/slapd/back-bdb/dn2entry.c | 84 -
|
|
servers/slapd/back-bdb/dn2id.c | 1215 ------------
|
|
servers/slapd/back-bdb/error.c | 62 -
|
|
servers/slapd/back-bdb/extended.c | 54 -
|
|
servers/slapd/back-bdb/filterindex.c | 1183 ------------
|
|
servers/slapd/back-bdb/id2entry.c | 446 -----
|
|
servers/slapd/back-bdb/idl.c | 1570 ---------------
|
|
servers/slapd/back-bdb/idl.h | 75 -
|
|
servers/slapd/back-bdb/index.c | 574 ------
|
|
servers/slapd/back-bdb/init.c | 874 ---------
|
|
servers/slapd/back-bdb/key.c | 104 -
|
|
servers/slapd/back-bdb/modify.c | 835 --------
|
|
servers/slapd/back-bdb/modrdn.c | 842 --------
|
|
servers/slapd/back-bdb/monitor.c | 724 -------
|
|
servers/slapd/back-bdb/nextid.c | 80 -
|
|
servers/slapd/back-bdb/operational.c | 151 --
|
|
servers/slapd/back-bdb/proto-bdb.h | 678 -------
|
|
servers/slapd/back-bdb/referral.c | 152 --
|
|
servers/slapd/back-bdb/search.c | 1388 --------------
|
|
servers/slapd/back-bdb/tools.c | 1327 -------------
|
|
servers/slapd/back-bdb/trans.c | 56 -
|
|
servers/slapd/back-hdb/Makefile.in | 70 -
|
|
servers/slapd/back-hdb/back-bdb.h | 31 -
|
|
servers/slapd/back-monitor/init.c | 8 +-
|
|
servers/slapd/bconfig.c | 2 +-
|
|
servers/slapd/dn.c | 3 +-
|
|
servers/slapd/overlays/pcache.c | 4 +-
|
|
servers/slapd/slap.h | 1 -
|
|
servers/slapd/slapd.ldif | 3 +-
|
|
tests/Makefile.in | 36 -
|
|
tests/README | 2 -
|
|
tests/data/regressions/its4184/its4184 | 4 -
|
|
tests/data/regressions/its4448/its4448 | 16 -
|
|
tests/data/slapd-proxyauthz.conf | 4 -
|
|
tests/data/slapd-proxycache.conf | 4 -
|
|
tests/data/slapd-ref-slave.conf | 2 -
|
|
tests/data/slapd.conf | 2 -
|
|
tests/run.in | 8 +-
|
|
tests/scripts/test023-refint | 97 +-
|
|
tests/scripts/test025-limits | 2 +-
|
|
tests/scripts/test036-meta-concurrency | 16 -
|
|
tests/scripts/test040-subtree-rename | 5 -
|
|
tests/scripts/test043-delta-syncrepl | 2 +-
|
|
tests/scripts/test052-memberof | 4 +-
|
|
tests/scripts/test056-monitor | 6 +-
|
|
tests/scripts/test057-memberof-refint | 9 +-
|
|
.../test061-syncreplication-initiation | 1 -
|
|
95 files changed, 418 insertions(+), 20054 deletions(-)
|
|
delete mode 100644 doc/man/man5/slapd-bdb.5
|
|
delete mode 100644 doc/man/man5/slapd-bdb.5.links
|
|
delete mode 100644 servers/slapd/DB_CONFIG
|
|
delete mode 100644 servers/slapd/alock.c
|
|
delete mode 100644 servers/slapd/alock.h
|
|
delete mode 100644 servers/slapd/back-bdb/Makefile.in
|
|
delete mode 100644 servers/slapd/back-bdb/add.c
|
|
delete mode 100644 servers/slapd/back-bdb/attr.c
|
|
delete mode 100644 servers/slapd/back-bdb/back-bdb.h
|
|
delete mode 100644 servers/slapd/back-bdb/bind.c
|
|
delete mode 100644 servers/slapd/back-bdb/cache.c
|
|
delete mode 100644 servers/slapd/back-bdb/compare.c
|
|
delete mode 100644 servers/slapd/back-bdb/config.c
|
|
delete mode 100644 servers/slapd/back-bdb/dbcache.c
|
|
delete mode 100644 servers/slapd/back-bdb/delete.c
|
|
delete mode 100644 servers/slapd/back-bdb/dn2entry.c
|
|
delete mode 100644 servers/slapd/back-bdb/dn2id.c
|
|
delete mode 100644 servers/slapd/back-bdb/error.c
|
|
delete mode 100644 servers/slapd/back-bdb/extended.c
|
|
delete mode 100644 servers/slapd/back-bdb/filterindex.c
|
|
delete mode 100644 servers/slapd/back-bdb/id2entry.c
|
|
delete mode 100644 servers/slapd/back-bdb/idl.c
|
|
delete mode 100644 servers/slapd/back-bdb/idl.h
|
|
delete mode 100644 servers/slapd/back-bdb/index.c
|
|
delete mode 100644 servers/slapd/back-bdb/init.c
|
|
delete mode 100644 servers/slapd/back-bdb/key.c
|
|
delete mode 100644 servers/slapd/back-bdb/modify.c
|
|
delete mode 100644 servers/slapd/back-bdb/modrdn.c
|
|
delete mode 100644 servers/slapd/back-bdb/monitor.c
|
|
delete mode 100644 servers/slapd/back-bdb/nextid.c
|
|
delete mode 100644 servers/slapd/back-bdb/operational.c
|
|
delete mode 100644 servers/slapd/back-bdb/proto-bdb.h
|
|
delete mode 100644 servers/slapd/back-bdb/referral.c
|
|
delete mode 100644 servers/slapd/back-bdb/search.c
|
|
delete mode 100644 servers/slapd/back-bdb/tools.c
|
|
delete mode 100644 servers/slapd/back-bdb/trans.c
|
|
delete mode 100644 servers/slapd/back-hdb/Makefile.in
|
|
delete mode 100644 servers/slapd/back-hdb/back-bdb.h
|
|
|
|
diff --git a/INSTALL b/INSTALL
|
|
index e8a4fb3..0805e1c 100644
|
|
--- a/INSTALL
|
|
+++ b/INSTALL
|
|
@@ -73,9 +73,6 @@ Making and Installing the OpenLDAP Distribution
|
|
|
|
6. Test the standalone system:
|
|
|
|
- This step requires the standalone LDAP server, slapd(8), with HDB
|
|
- and/or BDB support.
|
|
-
|
|
% make test
|
|
|
|
If all goes well, the system has been built as configured. If
|
|
diff --git a/build/openldap.m4 b/build/openldap.m4
|
|
index 80fda16..fd768aa 100644
|
|
--- a/build/openldap.m4
|
|
+++ b/build/openldap.m4
|
|
@@ -243,298 +243,6 @@ OL_RESOLVER_TRY(ol_cv_resolver_none)
|
|
OL_RESOLVER_TRY(ol_cv_resolver_resolv,[-lresolv])
|
|
OL_RESOLVER_TRY(ol_cv_resolver_bind,[-lbind])
|
|
])
|
|
-dnl
|
|
-dnl ====================================================================
|
|
-dnl Berkeley DB macros
|
|
-dnl
|
|
-dnl --------------------------------------------------------------------
|
|
-dnl Try to link
|
|
-AC_DEFUN([OL_BERKELEY_DB_TRY],
|
|
-[if test $ol_cv_lib_db = no ; then
|
|
- AC_CACHE_CHECK([for Berkeley DB link (]ifelse($2,,default,$2)[)],[$1],
|
|
-[
|
|
- ol_DB_LIB=ifelse($2,,,$2)
|
|
- ol_LIBS=$LIBS
|
|
- LIBS="$ol_DB_LIB $LTHREAD_LIBS $LIBS"
|
|
-
|
|
- AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
|
-#ifdef HAVE_DB_185_H
|
|
-# include <db_185.h>
|
|
-#else
|
|
-# include <db.h>
|
|
-#endif
|
|
-
|
|
-#ifndef DB_VERSION_MAJOR
|
|
-# define DB_VERSION_MAJOR 1
|
|
-#endif
|
|
-
|
|
-#ifndef NULL
|
|
-#define NULL ((void*)0)
|
|
-#endif
|
|
-]], [[
|
|
-#if DB_VERSION_MAJOR > 2
|
|
- db_env_create( NULL, 0 );
|
|
-#elif DB_VERSION_MAJOR > 1
|
|
- db_appexit( NULL );
|
|
-#else
|
|
- (void) dbopen( NULL, 0, 0, 0, NULL);
|
|
-#endif
|
|
-]])],[$1=yes],[$1=no])
|
|
-
|
|
- LIBS="$ol_LIBS"
|
|
-])
|
|
-
|
|
- if test $$1 = yes ; then
|
|
- ol_cv_lib_db=ifelse($2,,yes,$2)
|
|
- fi
|
|
-fi
|
|
-])
|
|
-dnl
|
|
-dnl --------------------------------------------------------------------
|
|
-dnl Get major and minor version from <db.h>
|
|
-AC_DEFUN([OL_BDB_HEADER_VERSION],
|
|
-[AC_CACHE_CHECK([for Berkeley DB major version in db.h], [ol_cv_bdb_major],[
|
|
- AC_LANG_CONFTEST([
|
|
-#include <db.h>
|
|
-#ifndef DB_VERSION_MAJOR
|
|
-# define DB_VERSION_MAJOR 1
|
|
-#endif
|
|
-__db_version DB_VERSION_MAJOR
|
|
-])
|
|
- set X `eval "$ac_cpp -P conftest.$ac_ext" | $EGREP __db_version` none none
|
|
- ol_cv_bdb_major=${3}
|
|
-])
|
|
-case $ol_cv_bdb_major in [[1-9]]*) : ;; *)
|
|
- AC_MSG_ERROR([Unknown Berkeley DB major version in db.h]) ;;
|
|
-esac
|
|
-
|
|
-dnl Determine minor version
|
|
-AC_CACHE_CHECK([for Berkeley DB minor version in db.h], [ol_cv_bdb_minor],[
|
|
- AC_LANG_CONFTEST([
|
|
-#include <db.h>
|
|
-#ifndef DB_VERSION_MINOR
|
|
-# define DB_VERSION_MINOR 0
|
|
-#endif
|
|
-__db_version DB_VERSION_MINOR
|
|
-])
|
|
- set X `eval "$ac_cpp -P conftest.$ac_ext" | $EGREP __db_version` none none
|
|
- ol_cv_bdb_minor=${3}
|
|
-])
|
|
-case $ol_cv_bdb_minor in [[0-9]]*) : ;; *)
|
|
- AC_MSG_ERROR([Unknown Berkeley DB minor version in db.h]) ;;
|
|
-esac
|
|
-])
|
|
-dnl
|
|
-dnl --------------------------------------------------------------------
|
|
-dnl Try to locate appropriate library
|
|
-AC_DEFUN([OL_BERKELEY_DB_LINK],
|
|
-[ol_cv_lib_db=no
|
|
-
|
|
-if test $ol_cv_bdb_major = 5 ; then
|
|
- OL_BERKELEY_DB_TRY(ol_cv_db_db_5_dot_m,[-ldb-5.$ol_cv_bdb_minor])
|
|
- OL_BERKELEY_DB_TRY(ol_cv_db_db5m,[-ldb5$ol_cv_bdb_minor])
|
|
- OL_BERKELEY_DB_TRY(ol_cv_db_db_5m,[-ldb-5$ol_cv_bdb_minor])
|
|
- OL_BERKELEY_DB_TRY(ol_cv_db_db_5_m,[-ldb-5-$ol_cv_bdb_minor])
|
|
- OL_BERKELEY_DB_TRY(ol_cv_db_db_5,[-ldb-5])
|
|
- OL_BERKELEY_DB_TRY(ol_cv_db_db5,[-ldb5])
|
|
-elif test $ol_cv_bdb_major = 4 ; then
|
|
- OL_BERKELEY_DB_TRY(ol_cv_db_db_4_dot_m,[-ldb-4.$ol_cv_bdb_minor])
|
|
- OL_BERKELEY_DB_TRY(ol_cv_db_db4m,[-ldb4$ol_cv_bdb_minor])
|
|
- OL_BERKELEY_DB_TRY(ol_cv_db_db_4m,[-ldb-4$ol_cv_bdb_minor])
|
|
- OL_BERKELEY_DB_TRY(ol_cv_db_db_4_m,[-ldb-4-$ol_cv_bdb_minor])
|
|
- OL_BERKELEY_DB_TRY(ol_cv_db_db_4,[-ldb-4])
|
|
- OL_BERKELEY_DB_TRY(ol_cv_db_db4,[-ldb4])
|
|
-fi
|
|
-OL_BERKELEY_DB_TRY(ol_cv_db_db,[-ldb])
|
|
-OL_BERKELEY_DB_TRY(ol_cv_db_none)
|
|
-])
|
|
-dnl
|
|
-dnl --------------------------------------------------------------------
|
|
-dnl Check if Berkeley DB version
|
|
-AC_DEFUN([OL_BERKELEY_DB_VERSION],
|
|
-[AC_CACHE_CHECK([for Berkeley DB library and header version match], [ol_cv_berkeley_db_version], [
|
|
- ol_LIBS="$LIBS"
|
|
- LIBS="$LTHREAD_LIBS $LIBS"
|
|
- if test $ol_cv_lib_db != yes ; then
|
|
- LIBS="$ol_cv_lib_db $LIBS"
|
|
- fi
|
|
-
|
|
- AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
|
-#ifdef HAVE_DB_185_H
|
|
- choke me;
|
|
-#else
|
|
-#include <db.h>
|
|
-#endif
|
|
-#ifndef DB_VERSION_MAJOR
|
|
-# define DB_VERSION_MAJOR 1
|
|
-#endif
|
|
-#ifndef NULL
|
|
-#define NULL ((void *)0)
|
|
-#endif
|
|
-main()
|
|
-{
|
|
-#if DB_VERSION_MAJOR > 1
|
|
- char *version;
|
|
- int major, minor, patch;
|
|
-
|
|
- version = db_version( &major, &minor, &patch );
|
|
-
|
|
- if( major != DB_VERSION_MAJOR ||
|
|
- minor != DB_VERSION_MINOR ||
|
|
- patch != DB_VERSION_PATCH )
|
|
- {
|
|
- printf("Berkeley DB version mismatch\n"
|
|
- "\theader: %s\n\tlibrary: %s\n",
|
|
- DB_VERSION_STRING, version);
|
|
- return 1;
|
|
- }
|
|
-#endif
|
|
-
|
|
- return 0;
|
|
-}]])],[ol_cv_berkeley_db_version=yes],[ol_cv_berkeley_db_version=no],[ol_cv_berkeley_db_version=cross])
|
|
-
|
|
- LIBS="$ol_LIBS"
|
|
-])
|
|
-
|
|
- if test $ol_cv_berkeley_db_version = no ; then
|
|
- AC_MSG_ERROR([Berkeley DB version mismatch])
|
|
- fi
|
|
-])dnl
|
|
-dnl
|
|
-dnl --------------------------------------------------------------------
|
|
-dnl Check if Berkeley DB supports DB_THREAD
|
|
-AC_DEFUN([OL_BERKELEY_DB_THREAD],
|
|
-[AC_CACHE_CHECK([for Berkeley DB thread support], [ol_cv_berkeley_db_thread], [
|
|
- ol_LIBS="$LIBS"
|
|
- LIBS="$LTHREAD_LIBS $LIBS"
|
|
- if test $ol_cv_lib_db != yes ; then
|
|
- LIBS="$ol_cv_lib_db $LIBS"
|
|
- fi
|
|
-
|
|
- AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
|
-#ifdef HAVE_DB_185_H
|
|
- choke me;
|
|
-#else
|
|
-#include <db.h>
|
|
-#endif
|
|
-#ifndef NULL
|
|
-#define NULL ((void *)0)
|
|
-#endif
|
|
-main()
|
|
-{
|
|
- int rc;
|
|
- u_int32_t flags = DB_CREATE |
|
|
-#ifdef DB_PRIVATE
|
|
- DB_PRIVATE |
|
|
-#endif
|
|
- DB_THREAD;
|
|
-
|
|
-#if DB_VERSION_MAJOR > 2
|
|
- DB_ENV *env = NULL;
|
|
-
|
|
- rc = db_env_create( &env, 0 );
|
|
-
|
|
- flags |= DB_INIT_MPOOL;
|
|
-#ifdef DB_MPOOL_PRIVATE
|
|
- flags |= DB_MPOOL_PRIVATE;
|
|
-#endif
|
|
-
|
|
- if( rc ) {
|
|
- printf("BerkeleyDB: %s\n", db_strerror(rc) );
|
|
- return rc;
|
|
- }
|
|
-
|
|
-#if (DB_VERSION_MAJOR > 3) || (DB_VERSION_MINOR >= 1)
|
|
- rc = (env->open)( env, NULL, flags, 0 );
|
|
-#else
|
|
- rc = (env->open)( env, NULL, NULL, flags, 0 );
|
|
-#endif
|
|
-
|
|
- if ( rc == 0 ) {
|
|
- rc = env->close( env, 0 );
|
|
- }
|
|
-
|
|
- if( rc ) {
|
|
- printf("BerkeleyDB: %s\n", db_strerror(rc) );
|
|
- return rc;
|
|
- }
|
|
-
|
|
-#else
|
|
- DB_ENV env;
|
|
- memset( &env, '\0', sizeof(env) );
|
|
-
|
|
- rc = db_appinit( NULL, NULL, &env, flags );
|
|
-
|
|
- if( rc == 0 ) {
|
|
- db_appexit( &env );
|
|
- }
|
|
-
|
|
- unlink("__db_mpool.share");
|
|
- unlink("__db_lock.share");
|
|
-#endif
|
|
-
|
|
- return rc;
|
|
-}]])],[ol_cv_berkeley_db_thread=yes],[ol_cv_berkeley_db_thread=no],[ol_cv_berkeley_db_thread=cross])
|
|
-
|
|
- LIBS="$ol_LIBS"
|
|
-])
|
|
-
|
|
- if test $ol_cv_berkeley_db_thread != no ; then
|
|
- AC_DEFINE(HAVE_BERKELEY_DB_THREAD, 1,
|
|
- [define if Berkeley DB has DB_THREAD support])
|
|
- fi
|
|
-])dnl
|
|
-dnl
|
|
-dnl --------------------------------------------------------------------
|
|
-dnl Find any DB
|
|
-AC_DEFUN([OL_BERKELEY_DB],
|
|
-[ol_cv_berkeley_db=no
|
|
-AC_CHECK_HEADERS(db.h)
|
|
-if test $ac_cv_header_db_h = yes; then
|
|
- OL_BDB_HEADER_VERSION
|
|
- OL_BDB_COMPAT
|
|
-
|
|
- if test $ol_cv_bdb_compat != yes ; then
|
|
- AC_MSG_ERROR([BerkeleyDB version incompatible with BDB/HDB backends])
|
|
- fi
|
|
-
|
|
- OL_BERKELEY_DB_LINK
|
|
- if test "$ol_cv_lib_db" != no ; then
|
|
- ol_cv_berkeley_db=yes
|
|
- OL_BERKELEY_DB_VERSION
|
|
- OL_BERKELEY_DB_THREAD
|
|
- fi
|
|
-fi
|
|
-])
|
|
-dnl --------------------------------------------------------------------
|
|
-dnl Check for version compatility with back-bdb
|
|
-AC_DEFUN([OL_BDB_COMPAT],
|
|
-[AC_CACHE_CHECK([if Berkeley DB version supported by BDB/HDB backends], [ol_cv_bdb_compat],[
|
|
- AC_EGREP_CPP(__db_version_compat,[
|
|
-#include <db.h>
|
|
-
|
|
- /* this check could be improved */
|
|
-#ifndef DB_VERSION_MAJOR
|
|
-# define DB_VERSION_MAJOR 1
|
|
-#endif
|
|
-#ifndef DB_VERSION_MINOR
|
|
-# define DB_VERSION_MINOR 0
|
|
-#endif
|
|
-#ifndef DB_VERSION_PATCH
|
|
-# define DB_VERSION_PATCH 0
|
|
-#endif
|
|
-
|
|
-#define DB_VERSION_FULL ((DB_VERSION_MAJOR<<16)|(DB_VERSION_MINOR<<8)|DB_VERSION_PATCH)
|
|
-
|
|
-/* require 4.4 or later, but less than 6.0.20 */
|
|
-#if DB_VERSION_FULL >= 0x040400 && DB_VERSION_FULL < 0x060014
|
|
- __db_version_compat
|
|
-#endif
|
|
-#if DB_VERSION_FULL >= 0x060014
|
|
-#error "BerkeleyDB 6.0.20+ license is incompatible with LDAP"
|
|
-#endif
|
|
- ], [ol_cv_bdb_compat=yes], [ol_cv_bdb_compat=no])])
|
|
-])
|
|
|
|
dnl
|
|
dnl ====================================================================
|
|
diff --git a/build/top.mk b/build/top.mk
|
|
index 6850121..a25c5fc 100644
|
|
--- a/build/top.mk
|
|
+++ b/build/top.mk
|
|
@@ -159,7 +159,6 @@ LDAP_LIBDIR= $(top_builddir)/libraries
|
|
LUTIL_LIBS = @LUTIL_LIBS@
|
|
LTHREAD_LIBS = @LTHREAD_LIBS@
|
|
|
|
-BDB_LIBS = @BDB_LIBS@
|
|
SLAPD_NDB_LIBS = @SLAPD_NDB_LIBS@
|
|
|
|
LDAP_LIBLBER_LA = $(LDAP_LIBDIR)/liblber/liblber.la
|
|
diff --git a/configure.in b/configure.in
|
|
index c70241a..065eae3 100644
|
|
--- a/configure.in
|
|
+++ b/configure.in
|
|
@@ -282,9 +282,7 @@ OL_ARG_ENABLE(wrappers,[ --enable-wrappers enable tcp wrapper support], no)
|
|
|
|
dnl ----------------------------------------------------------------
|
|
dnl SLAPD Backend Options
|
|
-Backends="bdb \
|
|
- dnssrv \
|
|
- hdb \
|
|
+Backends="dnssrv \
|
|
ldap \
|
|
mdb \
|
|
meta \
|
|
@@ -303,12 +301,8 @@ SLAPD Backend Options:])
|
|
|
|
OL_ARG_ENABLE(backends,[ --enable-backends enable all available backends],
|
|
--, [no yes mod])dnl
|
|
-OL_ARG_ENABLE(bdb,[ --enable-bdb enable Berkeley DB backend],
|
|
- yes, [no yes mod], ol_enable_backends)dnl
|
|
OL_ARG_ENABLE(dnssrv,[ --enable-dnssrv enable dnssrv backend],
|
|
no, [no yes mod], ol_enable_backends)dnl
|
|
-OL_ARG_ENABLE(hdb,[ --enable-hdb enable Hierarchical DB backend],
|
|
- yes, [no yes mod], ol_enable_backends)dnl
|
|
OL_ARG_ENABLE(ldap,[ --enable-ldap enable ldap backend],
|
|
no, [no yes mod], ol_enable_backends)dnl
|
|
OL_ARG_ENABLE(mdb,[ --enable-mdb enable mdb database backend],
|
|
@@ -471,9 +465,7 @@ if test $ol_enable_slapd = no ; then
|
|
ol_enable_rewrite=no
|
|
|
|
elif test $ol_enable_modules != yes &&
|
|
- test $ol_enable_bdb = no &&
|
|
test $ol_enable_dnssrv = no &&
|
|
- test $ol_enable_hdb = no &&
|
|
test $ol_enable_ldap = no &&
|
|
test $ol_enable_mdb = no &&
|
|
test $ol_enable_meta = no &&
|
|
@@ -518,7 +510,6 @@ AC_MSG_RESULT(done)
|
|
dnl ----------------------------------------------------------------
|
|
dnl Initialize vars
|
|
LDAP_LIBS=
|
|
-BDB_LIBS=
|
|
SLAPD_NDB_LIBS=
|
|
SLAPD_NDB_INCS=
|
|
LTHREAD_LIBS=
|
|
@@ -533,9 +524,7 @@ BUILD_THREAD=no
|
|
BUILD_SLAPI=no
|
|
SLAPD_SLAPI_DEPEND=
|
|
|
|
-BUILD_BDB=no
|
|
BUILD_DNSSRV=no
|
|
-BUILD_HDB=no
|
|
BUILD_LDAP=no
|
|
BUILD_MDB=no
|
|
BUILD_META=no
|
|
@@ -1867,36 +1856,6 @@ else
|
|
ol_cv_func_gethostbyaddr_r_nargs=0
|
|
fi
|
|
|
|
-dnl ----------------------------------------------------------------
|
|
-ol_link_bdb=no
|
|
-
|
|
-if test $ol_enable_bdb/$ol_enable_hdb != no/no; then
|
|
- OL_BERKELEY_DB
|
|
-
|
|
- if test $ol_cv_berkeley_db = no ; then
|
|
- AC_MSG_ERROR(BDB/HDB: BerkeleyDB not available)
|
|
- fi
|
|
-
|
|
- AC_DEFINE(HAVE_BERKELEY_DB,1,
|
|
- [define this if Berkeley DB is available])
|
|
-
|
|
- dnl $ol_cv_lib_db should be yes or -ldb
|
|
- dnl (it could be no, but that would be an error
|
|
- if test $ol_cv_lib_db != yes ; then
|
|
- BDB_LIBS="$BDB_LIBS $ol_cv_lib_db"
|
|
- fi
|
|
-
|
|
- dnl link BDB library to slapd when there is a
|
|
- dnl static BDB based backend in use
|
|
- if test $ol_enable_bdb/$ol_enable_hdb != mod/mod ; then
|
|
- if test $ol_enable_bdb = yes -o $ol_enable_hdb = yes ; then
|
|
- SLAPD_LIBS="$SLAPD_LIBS \$(BDB_LIBS)"
|
|
- fi
|
|
- fi
|
|
-
|
|
- ol_link_bdb=yes
|
|
-fi
|
|
-
|
|
dnl ----------------------------------------------------------------
|
|
|
|
if test $ol_enable_dynamic = yes && test $enable_shared = yes ; then
|
|
@@ -2610,19 +2569,6 @@ if test "$ol_enable_monitor" != no ; then
|
|
AC_DEFINE_UNQUOTED(SLAPD_MONITOR,$MFLAG,[define to support cn=Monitor backend])
|
|
fi
|
|
|
|
-if test "$ol_enable_bdb" != no ; then
|
|
- BUILD_SLAPD=yes
|
|
- BUILD_BDB=$ol_enable_bdb
|
|
- if test "$ol_enable_bdb" = mod ; then
|
|
- SLAPD_DYNAMIC_BACKENDS="$SLAPD_DYNAMIC_BACKENDS back-bdb"
|
|
- MFLAG=SLAPD_MOD_DYNAMIC
|
|
- else
|
|
- SLAPD_STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS back-bdb"
|
|
- MFLAG=SLAPD_MOD_STATIC
|
|
- fi
|
|
- AC_DEFINE_UNQUOTED(SLAPD_BDB,$MFLAG,[define to support BDB backend])
|
|
-fi
|
|
-
|
|
if test "$ol_enable_dnssrv" != no ; then
|
|
BUILD_SLAPD=yes
|
|
BUILD_DNSSRV=$ol_enable_dnssrv
|
|
@@ -2636,19 +2582,6 @@ if test "$ol_enable_dnssrv" != no ; then
|
|
AC_DEFINE_UNQUOTED(SLAPD_DNSSRV,$MFLAG,[define to support DNS SRV backend])
|
|
fi
|
|
|
|
-if test "$ol_enable_hdb" != no ; then
|
|
- BUILD_SLAPD=yes
|
|
- BUILD_HDB=$ol_enable_hdb
|
|
- if test "$ol_enable_hdb" = mod ; then
|
|
- SLAPD_DYNAMIC_BACKENDS="$SLAPD_DYNAMIC_BACKENDS back-hdb"
|
|
- MFLAG=SLAPD_MOD_DYNAMIC
|
|
- else
|
|
- SLAPD_STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS back-hdb"
|
|
- MFLAG=SLAPD_MOD_STATIC
|
|
- fi
|
|
- AC_DEFINE_UNQUOTED(SLAPD_HDB,$MFLAG,[define to support HDB backend])
|
|
-fi
|
|
-
|
|
if test "$ol_enable_ldap" != no ; then
|
|
BUILD_SLAPD=yes
|
|
BUILD_LDAP=$ol_enable_ldap
|
|
@@ -3076,9 +3009,7 @@ dnl slapi
|
|
AC_SUBST(BUILD_SLAPI)
|
|
AC_SUBST(SLAPD_SLAPI_DEPEND)
|
|
dnl backends
|
|
- AC_SUBST(BUILD_BDB)
|
|
AC_SUBST(BUILD_DNSSRV)
|
|
- AC_SUBST(BUILD_HDB)
|
|
AC_SUBST(BUILD_LDAP)
|
|
AC_SUBST(BUILD_MDB)
|
|
AC_SUBST(BUILD_META)
|
|
@@ -3117,7 +3048,6 @@ dnl overlays
|
|
|
|
AC_SUBST(LDAP_LIBS)
|
|
AC_SUBST(SLAPD_LIBS)
|
|
-AC_SUBST(BDB_LIBS)
|
|
AC_SUBST(SLAPD_NDB_LIBS)
|
|
AC_SUBST(SLAPD_NDB_INCS)
|
|
AC_SUBST(LTHREAD_LIBS)
|
|
@@ -3181,9 +3111,7 @@ AC_CONFIG_FILES([Makefile:build/top.mk:Makefile.in:build/dir.mk]
|
|
[libraries/librewrite/Makefile:build/top.mk:libraries/librewrite/Makefile.in:build/lib.mk:build/lib-static.mk]
|
|
[servers/Makefile:build/top.mk:servers/Makefile.in:build/dir.mk]
|
|
[servers/slapd/Makefile:build/top.mk:servers/slapd/Makefile.in:build/srv.mk]
|
|
-[servers/slapd/back-bdb/Makefile:build/top.mk:servers/slapd/back-bdb/Makefile.in:build/mod.mk]
|
|
[servers/slapd/back-dnssrv/Makefile:build/top.mk:servers/slapd/back-dnssrv/Makefile.in:build/mod.mk]
|
|
-[servers/slapd/back-hdb/Makefile:build/top.mk:servers/slapd/back-hdb/Makefile.in:build/mod.mk]
|
|
[servers/slapd/back-ldap/Makefile:build/top.mk:servers/slapd/back-ldap/Makefile.in:build/mod.mk]
|
|
[servers/slapd/back-ldif/Makefile:build/top.mk:servers/slapd/back-ldif/Makefile.in:build/mod.mk]
|
|
[servers/slapd/back-mdb/Makefile:build/top.mk:servers/slapd/back-mdb/Makefile.in:build/mod.mk]
|
|
diff --git a/contrib/slapd-modules/allowed/allowed.c b/contrib/slapd-modules/allowed/allowed.c
|
|
index 5f2810f..8ca0889 100644
|
|
--- a/contrib/slapd-modules/allowed/allowed.c
|
|
+++ b/contrib/slapd-modules/allowed/allowed.c
|
|
@@ -27,7 +27,7 @@
|
|
* Caveats:
|
|
* - right now, the overlay assumes that all values of the objectClass
|
|
* attribute will be returned in rs->sr_entry; this may not be true
|
|
- * in general, but it usually is for back-bdb/back-hdb. To generalize,
|
|
+ * in general, but it usually is for back-mdb. To generalize,
|
|
* the search request should be analyzed, and if allowedAttributes or
|
|
* allowedAttributesEffective are requested, add objectClass to the
|
|
* requested attributes
|
|
diff --git a/contrib/slapd-modules/nssov/README b/contrib/slapd-modules/nssov/README
|
|
index ced3872..f8538f9 100644
|
|
--- a/contrib/slapd-modules/nssov/README
|
|
+++ b/contrib/slapd-modules/nssov/README
|
|
@@ -21,7 +21,7 @@ To use the overlay, add:
|
|
moduleload <path to>nssov.so
|
|
...
|
|
|
|
- database hdb
|
|
+ database mdb
|
|
...
|
|
overlay nssov
|
|
|
|
@@ -65,7 +65,7 @@ See the nss-ldapd/README for the original attribute names used in this code.
|
|
The overlay also supports dynamic configuration in cn=config. The layout
|
|
of the config entry is
|
|
|
|
- dn: olcOverlay={0}nssov,ocDatabase={1}hdb,cn=config
|
|
+ dn: olcOverlay={0}nssov,ocDatabase={1}mdb,cn=config
|
|
objectClass: olcOverlayConfig
|
|
objectClass: olcNssOvConfig
|
|
olcOverlay: {0}nssov
|
|
diff --git a/contrib/slapd-modules/nssov/slapo-nssov.5 b/contrib/slapd-modules/nssov/slapo-nssov.5
|
|
index 816b661..83621bd 100644
|
|
--- a/contrib/slapd-modules/nssov/slapo-nssov.5
|
|
+++ b/contrib/slapd-modules/nssov/slapo-nssov.5
|
|
@@ -278,7 +278,7 @@ of the config entry is
|
|
.LP
|
|
.RS
|
|
.nf
|
|
- dn: olcOverlay={0}nssov,ocDatabase={1}hdb,cn=config
|
|
+ dn: olcOverlay={0}nssov,ocDatabase={1}mdb,cn=config
|
|
objectClass: olcOverlayConfig
|
|
objectClass: olcNssOvConfig
|
|
olcOverlay: {0}nssov
|
|
diff --git a/doc/guide/admin/appendix-changes.sdf b/doc/guide/admin/appendix-changes.sdf
|
|
index 5006672..7fe91d1 100644
|
|
--- a/doc/guide/admin/appendix-changes.sdf
|
|
+++ b/doc/guide/admin/appendix-changes.sdf
|
|
@@ -147,11 +147,6 @@ search over 500 thousand entries per second. The search was on an unindexed
|
|
attribute using a filter that would not match any entry, forcing slapd to examine
|
|
every entry in the DB, testing the filter for a match.
|
|
|
|
-Essentially the slapd entry cache in back-bdb/back-hdb is so efficient the search
|
|
-processing time is almost invisible; the runtime is limited only by the memory
|
|
-bandwidth of the machine. (The search data rate corresponds to about 3.5GB/sec;
|
|
-the memory bandwidth on the machine is only about 4GB/sec due to ECC and register latency.)
|
|
-
|
|
H3: New overlays
|
|
|
|
* slapo-constraint (Attribute value constraints)
|
|
@@ -199,21 +194,13 @@ H3: New build options
|
|
* Support for building against GnuTLS
|
|
|
|
|
|
-H2: Obsolete Features Removed From 2.4
|
|
-
|
|
-These features were strongly deprecated in 2.3 and removed in 2.4.
|
|
-
|
|
-H3: Slurpd
|
|
+H2: Obsolete Features Removed From 2.5
|
|
|
|
-Please read the {{SECT:Replication}} section as to why this is no longer in
|
|
-OpenLDAP
|
|
+These features were strongly deprecated in 2.4 and removed in 2.5.
|
|
|
|
-H3: back-ldbm
|
|
+H3: back-bdb and back-hdb
|
|
|
|
-back-ldbm was both slow and unreliable. Its byzantine indexing code was
|
|
-prone to spontaneous corruption, as were the underlying database libraries
|
|
-that were commonly used (e.g. GDBM or NDBM). back-bdb and back-hdb are
|
|
-superior in every aspect, with simplified indexing to avoid index corruption,
|
|
-fine-grained locking for greater concurrency, hierarchical caching for
|
|
-greater performance, streamlined on-disk format for greater efficiency
|
|
-and portability, and full transaction support for greater reliability.
|
|
+back-bdb and back-hdb were signficantly slower than back-mdb and
|
|
+required significant tuning of multiple parameters to maximize
|
|
+performance. back-mdb requires no tuning and provides all the
|
|
+functionality previously provided via back-bdb and back-hdb.
|
|
diff --git a/doc/guide/admin/appendix-common-errors.sdf b/doc/guide/admin/appendix-common-errors.sdf
|
|
index 23eef9b..5ead0e1 100644
|
|
--- a/doc/guide/admin/appendix-common-errors.sdf
|
|
+++ b/doc/guide/admin/appendix-common-errors.sdf
|
|
@@ -636,7 +636,7 @@ values of <n>.
|
|
|
|
H3: ldap_*: Internal (implementation specific) error (80) - additional info: entry index delete failed
|
|
|
|
-This seems to be related with wrong ownership of the BDB's dir (/var/lib/ldap)
|
|
+This seems to be related with wrong ownership of the MDB's dir (/var/lib/ldap)
|
|
and files. The files must be owned by the user that slapd runs as.
|
|
|
|
> chown -R ldap:ldap /var/lib/ldap
|
|
@@ -652,11 +652,3 @@ immediately and client gets an error :
|
|
> SASL/GSSAPI authentication started ldap_sasl_interactive_bind_s: Can't contact LDAP server (-1)
|
|
|
|
Then check the slapd service, it stopped.
|
|
-
|
|
-This may come from incompatible of using different versions of BerkeleyDB for
|
|
-installing of SASL and installing of OpenLDAP. The problem arises in case of
|
|
-using multiple version of BerkeleyDB. Solution: - Check which version of
|
|
-BerkeleyDB when install Cyrus SASL.
|
|
-
|
|
-Reinstall OpenLDAP with the version of BerkeleyDB above.
|
|
-
|
|
diff --git a/doc/guide/admin/aspell.en.pws b/doc/guide/admin/aspell.en.pws
|
|
index f486703..ae777e2 100644
|
|
--- a/doc/guide/admin/aspell.en.pws
|
|
+++ b/doc/guide/admin/aspell.en.pws
|
|
@@ -102,7 +102,6 @@ NOSYNC
|
|
env
|
|
pagedResultsControl
|
|
dup
|
|
-hdb
|
|
LDIFv
|
|
syslog
|
|
monitorTimestamp
|
|
@@ -887,7 +886,6 @@ proxyAttrSet
|
|
proxyAttrset
|
|
mary
|
|
crlcheck
|
|
-olcBdbConfig
|
|
kadmin
|
|
mech
|
|
slapcat
|
|
@@ -1190,7 +1188,6 @@ moddn
|
|
calloc
|
|
LDFLAGS
|
|
attributeOrValueExists
|
|
-olcHdbConfig
|
|
bsize
|
|
auditObject
|
|
dnssrv
|
|
@@ -1492,7 +1489,6 @@ ghenry
|
|
odbcinst
|
|
reqType
|
|
slapover
|
|
-BerkeleyDB's
|
|
attributename
|
|
lwrap
|
|
reqStart
|
|
@@ -1628,7 +1624,6 @@ DSAIT
|
|
olcHidden
|
|
mySNMP
|
|
metainformation
|
|
-BerkeleyDB
|
|
ldapuri
|
|
auditAbandon
|
|
RANDFILE
|
|
@@ -1662,7 +1657,6 @@ olcPasswordHash
|
|
ldapc
|
|
loopback
|
|
ldapi
|
|
-BDB's
|
|
GETREALM
|
|
functionalities
|
|
noplain
|
|
@@ -1670,7 +1664,6 @@ NOECHOPROMPT
|
|
AES
|
|
ldaps
|
|
notoc
|
|
-bdb
|
|
LDAPv
|
|
IPsec
|
|
olcServerID
|
|
diff --git a/doc/guide/admin/backends.sdf b/doc/guide/admin/backends.sdf
|
|
index 38e9ae2..6e005a6 100644
|
|
--- a/doc/guide/admin/backends.sdf
|
|
+++ b/doc/guide/admin/backends.sdf
|
|
@@ -14,38 +14,9 @@ name of the module for a backend is usually of the form:
|
|
|
|
> back_<backend name>.la
|
|
|
|
-So for example, if you need to load the {{hdb}} backend, you would configure
|
|
+So for example, if you need to load the {{mdb}} backend, you would configure
|
|
|
|
-> moduleload back_hdb.la
|
|
-
|
|
-H2: Berkeley DB Backends
|
|
-
|
|
-
|
|
-H3: Overview
|
|
-
|
|
-The {{hdb}} backend to {{slapd}}(8) is a backend for a
|
|
-normal {{slapd}} database. It uses the Oracle Berkeley DB ({{TERM:BDB}})
|
|
-package to store data. It makes extensive use of indexing and caching
|
|
-(see the {{SECT:Tuning}} section) to speed data access.
|
|
-
|
|
-{{hdb}} is a variant of the original {{bdb}} backend which was first written for use with BDB.
|
|
-{{hdb}} uses a hierarchical database layout which supports subtree renames.
|
|
-It is otherwise identical to the {{bdb}}
|
|
-behavior, and all the same configuration options apply.
|
|
-
|
|
-Note: An {{hdb}} database needs a large {{idlcachesize}} for good search performance,
|
|
-typically three times the {{cachesize}} (entry cache size) or larger.
|
|
-
|
|
-Note: The {{hdb}} backend has superseded the {{bdb}} backend, and both will
|
|
-soon be deprecated in favor of the new {{mdb}} backend. See below.
|
|
-
|
|
-H3: back-bdb/back-hdb Configuration
|
|
-
|
|
-MORE LATER
|
|
-
|
|
-H3: Further Information
|
|
-
|
|
-{{slapd-bdb}}(5)
|
|
+ moduleload back_mdb.la
|
|
|
|
H2: LDAP
|
|
|
|
@@ -199,16 +170,16 @@ H3: Overview
|
|
The {{mdb}} backend to {{slapd}}(8) is the recommended primary backend for a
|
|
normal {{slapd}} database. It uses OpenLDAP's own
|
|
Lightning Memory-Mapped Database ({{TERM:LMDB}})
|
|
-library to store data and is intended to replace the Berkeley DB backends.
|
|
+library to store data and replace the BerkeleyDB backends used in older
|
|
+OpenLDAP releases.
|
|
|
|
-It supports indexing like the BDB backends, but it uses no caching and requires
|
|
-no tuning to deliver maximum search performance. Like {{hdb}}, it is also
|
|
-fully hierarchical and supports subtree renames in constant time.
|
|
+It supports indexing, it uses no caching and requires no tuning to deliver
|
|
+maximum search performance. It is fully hierarchical and supports subtree
|
|
+renames in constant time.
|
|
|
|
H3: back-mdb Configuration
|
|
|
|
-Unlike the BDB backends, the {{mdb}} backend can be instantiated with very few
|
|
-configuration lines:
|
|
+The {{mdb}} backend can be instantiated with very few configuration lines:
|
|
|
|
> include ./schema/core.schema
|
|
>
|
|
@@ -490,7 +461,7 @@ distribute information between different sites/applications that use RDBMSes
|
|
and/or LDAP. Or whatever else...
|
|
|
|
It is {{B:NOT}} designed as a general-purpose backend that uses RDBMS instead of
|
|
-BerkeleyDB (as the standard BDB backend does), though it can be used as such with
|
|
+LMDB (as the standard back-mdb backend does), though it can be used as such with
|
|
several limitations. Please see {{SECT: LDAP vs RDBMS}} for discussion.
|
|
|
|
The idea is to use some meta-information to translate LDAP queries to SQL queries,
|
|
diff --git a/doc/guide/admin/install.sdf b/doc/guide/admin/install.sdf
|
|
index 9c47b24..4b4e85e 100644
|
|
--- a/doc/guide/admin/install.sdf
|
|
+++ b/doc/guide/admin/install.sdf
|
|
@@ -118,23 +118,6 @@ OpenLDAP's {{slapd}}(8) {{TERM:MDB}} primary database backend uses the {{TERM:LM
|
|
software included with the OpenLDAP source. There is no need to download any
|
|
additional software to have {{MDB}} support.
|
|
|
|
-OpenLDAP's {{slapd}}(8) {{TERM:BDB}} and {{TERM:HDB}} deprecated database backends
|
|
-require {{ORG[expand]Oracle}}'s Berkeley DB.
|
|
-If not available at configure time, you will not be able to build
|
|
-{{slapd}}(8) with these deprecated database backends.
|
|
-
|
|
-Your operating system may provide a supported version of
|
|
-Berkeley DB in the base system or as an optional
|
|
-software component. If not, you'll have to obtain and
|
|
-install it yourself. Berkeley DB is available from
|
|
-{{ORG[expand]Oracle}}'s Berkeley DB download page if required.
|
|
-
|
|
-There are several versions available from {{ORG[expand]Oracle}}.
|
|
-Berkeley DB version 6.0.20 and later uses a software license that is
|
|
-incompatible with LDAP technology and should not be used with OpenLDAP.
|
|
-
|
|
-Note: Please see {{SECT:Recommended OpenLDAP Software Dependency Versions}} for
|
|
-more information.
|
|
|
|
|
|
H3: Threads
|
|
diff --git a/doc/guide/admin/intro.sdf b/doc/guide/admin/intro.sdf
|
|
index c3dd92f..6aa2149 100644
|
|
--- a/doc/guide/admin/intro.sdf
|
|
+++ b/doc/guide/admin/intro.sdf
|
|
@@ -346,7 +346,7 @@ really have a "directory".
|
|
|
|
Existing commercial LDAP server implementations that use a relational database
|
|
are either from the first kind or the third. I don't know of any implementation
|
|
-that uses a relational database to do inefficiently what BDB does efficiently.
|
|
+that uses a relational database to do inefficiently what LMDB does efficiently.
|
|
For those who are interested in "third way" (exposing EXISTING data from RDBMS
|
|
as LDAP tree, having some limitations compared to classic LDAP model, but making
|
|
it possible to interoperate between LDAP and SQL applications):
|
|
@@ -403,15 +403,9 @@ tags.
|
|
{{B:Choice of database backends}}: {{slapd}} comes with a variety
|
|
of different database backends you can choose from. They include
|
|
{{TERM:MDB}}, a hierarchical high-performance transactional database backend;
|
|
-{{TERM:BDB}}, a high-performance transactional database backend (deprecated);
|
|
-{{TERM:HDB}}, a hierarchical high-performance transactional
|
|
-backend (deprecated); {{SHELL}}, a backend interface to arbitrary shell scripts;
|
|
+{{SHELL}}, a backend interface to arbitrary shell scripts;
|
|
and PASSWD, a simple backend interface to the {{passwd}}(5) file.
|
|
-The MDB backend utilizes {{TERM:LMDB}}, a high performance replacement
|
|
-for {{ORG[expand]Oracle}}'s Berkeley DB.
|
|
-The BDB and HDB backends utilize {{ORG[expand]Oracle}} Berkeley DB. These
|
|
-backends have been deprecated as LMDB provides significantly higher read
|
|
-and write throughput and data reliability.
|
|
+The MDB backend utilizes {{TERM:LMDB}}.
|
|
|
|
{{B:Multiple database instances}}: {{slapd}} can be configured to
|
|
serve multiple databases at the same time. This means that a single
|
|
diff --git a/doc/guide/admin/maintenance.sdf b/doc/guide/admin/maintenance.sdf
|
|
index deb14b9..3b7503f 100644
|
|
--- a/doc/guide/admin/maintenance.sdf
|
|
+++ b/doc/guide/admin/maintenance.sdf
|
|
@@ -14,23 +14,7 @@ Backup strategies largely depend on the amount of change in the database
|
|
and how much of that change an administrator might be willing to lose in a
|
|
catastrophic failure. There are two basic methods that can be used:
|
|
|
|
-1. Backup the Berkeley database itself and periodically back up the transaction
|
|
-log files:
|
|
-
|
|
-Berkeley DB produces transaction logs that can be used to reconstruct
|
|
-changes from a given point in time. For example, if an administrator were willing to only
|
|
-lose one hour's worth of changes, they could take down the server in
|
|
-the middle of the night, copy the Berkeley database files offsite, and bring
|
|
-the server back online. Then, on an hourly basis, they could force a
|
|
-database checkpoint, capture the log files that have been generated in the
|
|
-past hour, and copy them offsite. The accumulated log files, in combination
|
|
-with the previous database backup, could be used with db_recover to
|
|
-reconstruct the database up to the time the last collection of log files was
|
|
-copied offsite. This method affords good protection, with minimal space
|
|
-overhead.
|
|
-
|
|
-
|
|
-2. Periodically run slapcat and back up the LDIF file:
|
|
+1. Periodically run slapcat and back up the LDIF file:
|
|
|
|
Slapcat can be run while slapd is active. However, one runs the risk of an
|
|
inconsistent database- not from the point of slapd, but from the point of
|
|
@@ -46,73 +30,11 @@ files can be rather large and the accumulation of the day's backups could
|
|
add up to a substantial amount of space.
|
|
|
|
You can use {{slapcat}}(8) to generate an LDIF file for each of your {{slapd}}(8)
|
|
-back-bdb or back-hdb databases.
|
|
+back-mdb databases.
|
|
|
|
> slapcat -f slapd.conf -b "dc=example,dc=com"
|
|
|
|
-For back-bdb and back-hdb, this command may be ran while slapd(8) is running.
|
|
-
|
|
-MORE on actual Berkeley DB backups later covering db_recover etc.
|
|
-
|
|
-H2: Berkeley DB Logs
|
|
-
|
|
-Berkeley DB log files grow, and the administrator has to deal with it. The
|
|
-procedure is known as log file archival or log file rotation.
|
|
-
|
|
-Note: The actual log file rotation is handled by the Berkeley DB engine.
|
|
-
|
|
-Logs of current transactions need to be stored into files so that the database
|
|
-can be recovered in the event of an application crash. Administrators can change
|
|
-the size limit of a single log file (by default 10MB), and have old log files
|
|
-removed automatically, by setting up DB environment (see below). The reason
|
|
-Berkeley DB never deletes any log files by default is that the administrator
|
|
-may wish to backup the log files before removal to make database recovery
|
|
-possible even after a catastrophic failure, such as file system corruption.
|
|
-
|
|
-Log file names are {{F:log.XXXXXXXXXX}} (X is a digit). By default the log files
|
|
-are located in the BDB backend directory. The {{F:db_archive}} tool knows what
|
|
-log files are used in current transactions, and what are not. Administrators can
|
|
-move unused log files to a backup media, and delete them. To have them removed
|
|
-automatically, place set_flags {{DB_LOG_AUTOREMOVE}} directive in {{F:DB_CONFIG}}.
|
|
-
|
|
-Note: If the log files are removed automatically, recovery after a catastrophic
|
|
-failure is likely to be impossible.
|
|
-
|
|
-The files with names {{F:__db.001}}, {{F:__db.002}}, etc are just shared memory
|
|
-regions (or whatever). These ARE NOT 'logs', they must be left alone. Don't be
|
|
-afraid of them, they do not grow like logs do.
|
|
-
|
|
-To understand the {{F:db_archive}} interface, the reader should refer to
|
|
-chapter 9 of the Berkeley DB guide. In particular, the following chapters are
|
|
-recommended:
|
|
-
|
|
-* Database and log file archival - {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/ref/transapp/archival.html}}
|
|
-* Log file removal - {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/ref/transapp/logfile.html}}
|
|
-* Recovery procedures - {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/ref/transapp/recovery.html}}
|
|
-* Hot failover - {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/ref/transapp/hotfail.html}}
|
|
-* Complete list of Berkeley DB flags - {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/api_c/env_set_flags.html}}
|
|
-
|
|
-Advanced installations can use special environment settings to fine-tune some
|
|
-Berkeley DB options (change the log file limit, etc). This can be done by using
|
|
-the {{F:DB_CONFIG}} file. This magic file can be created in BDB backend directory
|
|
-set up by {{slapd.conf}}(5). More information on this file can be found in File
|
|
-naming chapter. Specific directives can be found in C Interface, look for
|
|
-{{DB_ENV->set_XXXX}} calls.
|
|
-
|
|
-Note: options set in {{F:DB_CONFIG}} file override options set by OpenLDAP.
|
|
-Use them with extreme caution. Do not use them unless You know what You are doing.
|
|
-
|
|
-The advantages of {{F:DB_CONFIG}} usage can be the following:
|
|
-
|
|
-* to keep data files and log files on different mediums (i.e. disks) to improve
|
|
- performance and/or reliability;
|
|
-* to fine-tune some specific options (such as shared memory region sizes);
|
|
-* to set the log file limit (please read Log file limits before doing this).
|
|
-
|
|
-To figure out the best-practice BDB backup scenario, the reader is highly
|
|
-recommended to read the whole Chapter 9: Berkeley DB Transactional Data Store Applications.
|
|
-This chapter is a set of small pages with examples in C language. Non-programming
|
|
-people can skip these examples without loss of knowledge.
|
|
+For back-mdb this command may be ran while slapd(8) is running.
|
|
|
|
|
|
H2: Checkpointing
|
|
@@ -148,7 +70,7 @@ type are:
|
|
+{{B: slapcat the current data out}}
|
|
|
|
.{{S: }}
|
|
-+{{B: Clear out the current data directory (/usr/local/var/openldap-data/) leaving DB_CONFIG in place}}
|
|
++{{B: Clear out the current data directory (/usr/local/var/openldap-data/)}}
|
|
|
|
.{{S: }}
|
|
+{{B: Perform the software upgrades}}
|
|
diff --git a/doc/guide/admin/monitoringslapd.sdf b/doc/guide/admin/monitoringslapd.sdf
|
|
index 2781e47..bca2ec5 100644
|
|
--- a/doc/guide/admin/monitoringslapd.sdf
|
|
+++ b/doc/guide/admin/monitoringslapd.sdf
|
|
@@ -214,11 +214,10 @@ backends, as well as backends loaded by modules. For example:
|
|
> monitoredInfo: config
|
|
> monitoredInfo: ldif
|
|
> monitoredInfo: monitor
|
|
-> monitoredInfo: bdb
|
|
-> monitoredInfo: hdb
|
|
+> monitoredInfo: mdb
|
|
|
|
-This indicates the {{config}}, {{ldif}}, {{monitor}}, {{bdb}},
|
|
-and {{hdb}} backends are available.
|
|
+This indicates the {{config}}, {{ldif}}, {{monitor}},
|
|
+and {{mdb}} backends are available.
|
|
|
|
The {{EX:cn=Backends,cn=Monitor}} object is also a container
|
|
for available backend objects. Each available backend object
|
|
@@ -242,21 +241,7 @@ contains information about a particular backend. For example:
|
|
> seeAlso: cn=Database 2,cn=Databases,cn=Monitor
|
|
>
|
|
> dn: cn=Backend 3,cn=Backends,cn=Monitor
|
|
-> monitoredInfo: bdb
|
|
-> monitorRuntimeConfig: TRUE
|
|
-> supportedControl: 1.3.6.1.1.12
|
|
-> supportedControl: 2.16.840.1.113730.3.4.2
|
|
-> supportedControl: 1.3.6.1.4.1.4203.666.5.2
|
|
-> supportedControl: 1.2.840.113556.1.4.319
|
|
-> supportedControl: 1.3.6.1.1.13.1
|
|
-> supportedControl: 1.3.6.1.1.13.2
|
|
-> supportedControl: 1.3.6.1.4.1.4203.1.10.1
|
|
-> supportedControl: 1.2.840.113556.1.4.1413
|
|
-> supportedControl: 1.3.6.1.4.1.4203.666.11.7.2
|
|
-> seeAlso: cn=Database 1,cn=Databases,cn=Monitor
|
|
->
|
|
-> dn: cn=Backend 4,cn=Backends,cn=Monitor
|
|
-> monitoredInfo: hdb
|
|
+> monitoredInfo: mdb
|
|
> monitorRuntimeConfig: TRUE
|
|
> supportedControl: 1.3.6.1.1.12
|
|
> supportedControl: 2.16.840.1.113730.3.4.2
|
|
@@ -271,7 +256,7 @@ contains information about a particular backend. For example:
|
|
For each of these objects, monitorInfo indicates which backend the
|
|
information in the object is about. For instance, the {{EX:cn=Backend
|
|
3,cn=Backends,cn=Monitor}} object contains (in the example) information
|
|
-about the {{bdb}} backend.
|
|
+about the {{mdb}} backend.
|
|
|
|
!block table
|
|
Attribute|Description
|
|
diff --git a/doc/guide/admin/overlays.sdf b/doc/guide/admin/overlays.sdf
|
|
index 2eb115b..712cd1b 100644
|
|
--- a/doc/guide/admin/overlays.sdf
|
|
+++ b/doc/guide/admin/overlays.sdf
|
|
@@ -743,9 +743,9 @@ H4: Setting cache parameters
|
|
This directive enables proxy caching and sets general cache
|
|
parameters. The <DB> parameter specifies which underlying database
|
|
is to be used to hold cached entries. It should be set to
|
|
-{{EX:mdb}}, {{EX:hdb}}, or {{EX:bdb}}. The <maxentries> parameter
|
|
-specifies the total number of entries which may be held in the cache.
|
|
-The <nattrsets> parameter specifies the total number of attribute sets
|
|
+{{EX:mdb}}. The <maxentries> parameter specifies the
|
|
+total number of entries which may be held in the cache. The
|
|
+<nattrsets> parameter specifies the total number of attribute sets
|
|
(as specified by the {{EX:pcacheAttrset}} directive) that may be
|
|
defined. The <entrylimit> parameter specifies the maximum number of
|
|
entries in a cacheable query. The <period> specifies the consistency
|
|
diff --git a/doc/guide/admin/replication.sdf b/doc/guide/admin/replication.sdf
|
|
index 87139b5..bbc91e4 100644
|
|
--- a/doc/guide/admin/replication.sdf
|
|
+++ b/doc/guide/admin/replication.sdf
|
|
@@ -225,8 +225,8 @@ in the replication context.
|
|
|
|
The syncrepl engine, which is a consumer-side replication engine,
|
|
can work with any backends. The LDAP Sync provider can be configured
|
|
-as an overlay on any backend, but works best with the {{back-bdb}},
|
|
-{{back-hdb}}, or {{back-mdb}} backends.
|
|
+as an overlay on any backend, but works best with the {{back-mdb}},
|
|
+backends.
|
|
|
|
The LDAP Sync provider maintains a {{EX:contextCSN}} for each
|
|
database as the current synchronization state indicator of the
|
|
@@ -423,9 +423,6 @@ writes have to go to just one of the mirror nodes at a time
|
|
server (slapd in proxy mode) or device (hardware load balancer)
|
|
is needed to manage which provider is currently active
|
|
* Backups are managed slightly differently
|
|
-- If backing up the Berkeley database itself and periodically backing up the
|
|
-transaction log files, then the same member of the mirror pair needs to be
|
|
-used to collect logfiles until the next database backup is taken
|
|
|
|
For configuration, please see the {{SECT:MirrorMode}} section below
|
|
|
|
@@ -762,10 +759,7 @@ H4: Delta-syncrepl Consumer configuration
|
|
|
|
|
|
The above configuration assumes that you have a replicator identity defined
|
|
-in your database that can be used to bind to the provider. In addition,
|
|
-all of the databases (primary, replica, and the accesslog
|
|
-storage database) should also have properly tuned {{DB_CONFIG}} files that meet
|
|
-your needs.
|
|
+in your database that can be used to bind to the provider.
|
|
|
|
Note: An accesslog database is unique to a given master. It should
|
|
never be replicated.
|
|
diff --git a/doc/guide/admin/slapdconf2.sdf b/doc/guide/admin/slapdconf2.sdf
|
|
index cb51d88..8a3e969 100644
|
|
--- a/doc/guide/admin/slapdconf2.sdf
|
|
+++ b/doc/guide/admin/slapdconf2.sdf
|
|
@@ -69,7 +69,7 @@ used to configure the software.
|
|
the schema that is hard-coded in slapd).
|
|
.. Child entries of {{EX:cn=schema,cn=config}} contain user schema as
|
|
loaded from config files or added at runtime.
|
|
-* Backend-specific configuration
|
|
+* Backend-specific configuration
|
|
* Database-specific configuration
|
|
.. Overlays are defined in children of the Database entry.
|
|
.. Databases and Overlays may also have other miscellaneous children.
|
|
@@ -207,7 +207,7 @@ Level Keyword Description
|
|
!endblock
|
|
|
|
The desired log level can be input as a single integer that
|
|
-combines the (ORed) desired levels, both in decimal or in hexadecimal
|
|
+combines the (ORed) desired levels, both in decimal or in hexadecimal
|
|
notation, as a list of integers (that are ORed internally), or as a list of the names that are shown between brackets, such that
|
|
|
|
> olcLogLevel 129
|
|
@@ -364,10 +364,8 @@ supported backend types listed in Table 5.2.
|
|
!block table; align=Center; coltags="EX,N"; \
|
|
title="Table 5.2: Database Backends"
|
|
Types Description
|
|
-bdb Berkeley DB transactional backend (deprecated)
|
|
config Slapd configuration backend
|
|
dnssrv DNS SRV backend
|
|
-hdb Hierarchical variant of bdb backend (deprecated)
|
|
ldap Lightweight Directory Access Protocol (Proxy) backend
|
|
ldif Lightweight Data Interchange Format backend
|
|
mdb Memory-Mapped DB backend
|
|
@@ -381,7 +379,7 @@ sql SQL Programmable backend
|
|
|
|
\Example:
|
|
|
|
-> olcBackend: bdb
|
|
+> olcBackend: mdb
|
|
|
|
There are no other directives defined for this entry. Specific backend
|
|
types may define additional attributes for their particular use but so
|
|
@@ -391,9 +389,9 @@ not appear in any actual configurations.
|
|
|
|
H4: Sample Entry
|
|
|
|
-> dn: olcBackend=bdb,cn=config
|
|
+> dn: olcBackend=mdb,cn=config
|
|
> objectClass: olcBackendConfig
|
|
-> olcBackend: bdb
|
|
+> olcBackend: mdb
|
|
|
|
|
|
H3: Database-specific Directives
|
|
@@ -421,9 +419,9 @@ databases.
|
|
|
|
\Example:
|
|
|
|
-> olcDatabase: bdb
|
|
+> olcDatabase: mdb
|
|
|
|
-This marks the beginning of a new {{TERM:BDB}} database instance.
|
|
+This marks the beginning of a new {{TERM:MDB}} database instance.
|
|
|
|
|
|
H4: olcAccess: to <what> [ by <who> [<accesslevel>] [<control>] ]+
|
|
@@ -642,7 +640,7 @@ schema conformance. The default is off.
|
|
The {{EX:binddn}} parameter gives the DN to bind as for the
|
|
syncrepl searches to the provider slapd. It should be a DN
|
|
which has read access to the replication content in the
|
|
-master database.
|
|
+master database.
|
|
|
|
The {{EX:bindmethod}} is {{EX:simple}} or {{EX:sasl}},
|
|
depending on whether simple password-based authentication or
|
|
@@ -683,8 +681,8 @@ conforms to the obsolete {{changelog}} format. If the {{EX:syncdata}}
|
|
parameter is omitted or set to {{EX:"default"}} then the log
|
|
parameters are ignored.
|
|
|
|
-The {{syncrepl}} replication mechanism is supported by the {{bdb}},
|
|
-{{hdb}}, and {{mdb}} backends.
|
|
+The {{syncrepl}} replication mechanism is supported by the {{mdb}}
|
|
+backend.
|
|
|
|
See the {{SECT:LDAP Sync Replication}} chapter of this guide for
|
|
more information on how to use this directive.
|
|
@@ -731,21 +729,20 @@ H4: Sample Entries
|
|
>olcRootDN: cn=Manager,dc=example,dc=com
|
|
|
|
|
|
-H3: BDB and HDB Database Directives
|
|
+H3: MDB Database Directives
|
|
|
|
-Directives in this category apply to both the {{TERM:BDB}}
|
|
-and the {{TERM:HDB}} database.
|
|
+Directives in this category apply to the {{TERM:MDB}}
|
|
+database backend.
|
|
They are used in an olcDatabase entry in addition to the generic
|
|
database directives defined above. For a complete reference
|
|
-of BDB/HDB configuration directives, see {{slapd-bdb}}(5). In
|
|
-addition to the {{EX:olcDatabaseConfig}} objectClass, BDB and HDB
|
|
-database entries must have the {{EX:olcBdbConfig}} and
|
|
-{{EX:olcHdbConfig}} objectClass, respectively.
|
|
+of MDB configuration directives, see {{slapd-mdb}}(5). In
|
|
+addition to the {{EX:olcDatabaseConfig}} objectClass, MDB
|
|
+database entries must have the {{EX:olcMdbConfig}} objectClass.
|
|
|
|
|
|
H4: olcDbDirectory: <directory>
|
|
|
|
-This directive specifies the directory where the BDB files
|
|
+This directive specifies the directory where the MDB files
|
|
containing the database and associated indices live.
|
|
|
|
\Default:
|
|
@@ -753,98 +750,48 @@ containing the database and associated indices live.
|
|
> olcDbDirectory: /usr/local/var/openldap-data
|
|
|
|
|
|
-H4: olcDbCachesize: <integer>
|
|
-
|
|
-This directive specifies the size in entries of the in-memory
|
|
-cache maintained by the BDB backend database instance.
|
|
-
|
|
-\Default:
|
|
-
|
|
-> olcDbCachesize: 1000
|
|
-
|
|
-
|
|
H4: olcDbCheckpoint: <kbyte> <min>
|
|
|
|
-This directive specifies how often to checkpoint the BDB transaction log.
|
|
-A checkpoint operation flushes the database buffers to disk and writes a
|
|
-checkpoint record in the log.
|
|
+This directive specifies the frequency for flushing the database disk
|
|
+buffers. This directive is only needed if the {{olcDbNoSync}} option is
|
|
+{{EX:TRUE}}.
|
|
The checkpoint will occur if either <kbyte> data has been written or
|
|
<min> minutes have passed since the last checkpoint. Both arguments default
|
|
to zero, in which case they are ignored. When the <min> argument is
|
|
non-zero, an internal task will run every <min> minutes to perform the
|
|
-checkpoint. See the Berkeley DB reference guide for more details.
|
|
+checkpoint. Note: currently the _kbyte_ setting is unimplemented.
|
|
|
|
\Example:
|
|
|
|
> olcDbCheckpoint: 1024 10
|
|
|
|
|
|
-H4: olcDbConfig: <DB_CONFIG setting>
|
|
+H4: olcDbEnvFlags: {nosync,nometasync,writemap,mapasync,nordahead}
|
|
|
|
-This attribute specifies a configuration directive to be placed in the
|
|
-{{EX:DB_CONFIG}} file of the database directory. At server startup time, if
|
|
-no such file exists yet, the {{EX:DB_CONFIG}} file will be created and the
|
|
-settings in this attribute will be written to it. If the file exists,
|
|
-its contents will be read and displayed in this attribute. The attribute
|
|
-is multi-valued, to accommodate multiple configuration directives. No default
|
|
-is provided, but it is essential to use proper settings here to get the
|
|
-best server performance.
|
|
+This option specifies flags for finer-grained control of the LMDB library's
|
|
+operation.
|
|
|
|
-Any changes made to this attribute will be written to the {{EX:DB_CONFIG}}
|
|
-file and will cause the database environment to be reset so the changes
|
|
-can take immediate effect. If the environment cache is large and has not
|
|
-been recently checkpointed, this reset operation may take a long time. It
|
|
-may be advisable to manually perform a single checkpoint using the Berkeley DB
|
|
-{{db_checkpoint}} utility before using LDAP Modify to change this
|
|
-attribute.
|
|
+* {{F:nosync}}: This is exactly the same as the dbnosync directive.
|
|
|
|
-\Example:
|
|
+* {{F:nometasync}}: Flush the data on a commit, but skip the sync of the meta
|
|
+page. This mode is slightly faster than doing a full sync, but can
|
|
+potentially lose the last committed transaction if the operating system
|
|
+crashes. If both nometasync and nosync are set, the nosync flag takes
|
|
+precedence.
|
|
|
|
-> olcDbConfig: set_cachesize 0 10485760 0
|
|
-> olcDbConfig: set_lg_bsize 2097512
|
|
-> olcDbConfig: set_lg_dir /var/tmp/bdb-log
|
|
-> olcDbConfig: set_flags DB_LOG_AUTOREMOVE
|
|
-
|
|
-In this example, the BDB cache is set to 10MB, the BDB transaction log
|
|
-buffer size is set to 2MB, and the transaction log files are to be stored
|
|
-in the /var/tmp/bdb-log directory. Also a flag is set to tell BDB to
|
|
-delete transaction log files as soon as their contents have been
|
|
-checkpointed and they are no longer needed. Without this setting the
|
|
-transaction log files will continue to accumulate until some other
|
|
-cleanup procedure removes them. See the Berkeley DB documentation for the
|
|
-{{EX:db_archive}} command for details. For a complete list of Berkeley DB
|
|
-flags please see - {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/api_c/env_set_flags.html}}
|
|
-
|
|
-Ideally the BDB cache must be
|
|
-at least as large as the working set of the database, the log buffer size
|
|
-should be large enough to accommodate most transactions without overflowing,
|
|
-and the log directory must be on a separate physical disk from the main
|
|
-database files. And both the database directory and the log directory
|
|
-should be separate from disks used for regular system activities such as
|
|
-the root, boot, or swap filesystems. See the FAQ-o-Matic and the Berkeley DB
|
|
-documentation for more details.
|
|
+* {{F:writemap}}: Use a writable memory map instead of just read-only. This
|
|
+speeds up write operations but makes the database vulnerable to corruption in
|
|
+case any bugs in slapd cause stray writes into the mmap region.
|
|
|
|
+* {{F:mapasync}}: When using a writable memory map and performing flushes on
|
|
+each commit, use an asynchronous flush instead of a synchronous flush (the
|
|
+default). This option has no effect if writemap has not been set. It also has
|
|
+no effect if nosync is set.
|
|
|
|
-H4: olcDbNosync: { TRUE | FALSE }
|
|
-
|
|
-This option causes on-disk database contents to not be immediately
|
|
-synchronized with in memory changes upon change. Setting this option
|
|
-to {{EX:TRUE}} may improve performance at the expense of data integrity. This
|
|
-directive has the same effect as using
|
|
-> olcDbConfig: set_flags DB_TXN_NOSYNC
|
|
-
|
|
-
|
|
-H4: olcDbIDLcacheSize: <integer>
|
|
-
|
|
-Specify the size of the in-memory index cache, in index slots. The
|
|
-default is zero. A larger value will speed up frequent searches of
|
|
-indexed entries. The optimal size will depend on the data and search
|
|
-characteristics of the database, but using a number three times
|
|
-the entry cache size is a good starting point.
|
|
-
|
|
-\Example:
|
|
-
|
|
-> olcDbIDLcacheSize: 3000
|
|
+* {{F:nordahead}}: Turn off file readahead. Usually the OS performs readahead
|
|
+on every read request. This usually boosts read performance but can be
|
|
+harmful to random access read performance if the system's memory is full and
|
|
+the DB is larger than RAM. This option is not implemented on Windows.
|
|
|
|
|
|
H4: olcDbIndex: {<attrlist> | default} [pres,eq,approx,sub,none]
|
|
@@ -874,7 +821,7 @@ matches do not use an index. However, some attributes do support
|
|
indexing for inequality matches, based on the equality index.
|
|
|
|
A substring index can be more explicitly specified as {{EX:subinitial}},
|
|
-{{EX:subany}}, or {{EX:subfinal}}, corresponding to the three
|
|
+{{EX:subany}}, or {{EX:subfinal}}, corresponding to the three
|
|
possible components
|
|
of a substring match filter. A subinitial index only indexes
|
|
substrings that appear at the beginning of an attribute value.
|
|
@@ -890,7 +837,7 @@ attribute that inherits from {{EX:name}} to be indexed.
|
|
By default, no indices are maintained. It is generally advised
|
|
that minimally an equality index upon objectClass be maintained.
|
|
|
|
-> olcDbindex: objectClass eq
|
|
+> olcDbIndex: objectClass eq
|
|
|
|
Additional indices should be configured corresponding to the
|
|
most common searches that are used on the database.
|
|
@@ -907,18 +854,24 @@ stopped before the index task completes, indexing will have to be
|
|
manually completed using the slapindex tool.
|
|
|
|
|
|
-H4: olcDbLinearIndex: { TRUE | FALSE }
|
|
+H4: olcDbMaxReaders: <integer>
|
|
+
|
|
+This directive specifies the maximum number of threads that may have
|
|
+concurrent read access to the database. Tools such as slapcat count as a
|
|
+single thread, in addition to threads in any active slapd processes. The
|
|
+default is 126.
|
|
+
|
|
|
|
-If this setting is {{EX:TRUE}} slapindex will index one attribute
|
|
-at a time. The default settings is {{EX:FALSE}} in which case all
|
|
-indexed attributes of an entry are processed at the same time. When
|
|
-enabled, each indexed attribute is processed individually, using
|
|
-multiple passes through the entire database. This option improves
|
|
-slapindex performance when the database size exceeds the BDB cache
|
|
-size. When the BDB cache is large enough, this option is not needed
|
|
-and will decrease performance. Also by default, slapadd performs
|
|
-full indexing and so a separate slapindex run is not needed. With
|
|
-this option, slapadd does no indexing and slapindex must be used.
|
|
+H4: olcDbMaxSize: <bytes>
|
|
+
|
|
+This directive specifies the maximum size of the database in bytes. A memory
|
|
+map of this size is allocated at startup time and the database will not be
|
|
+allowed to grow beyond this size. The default is 10485760 bytes (10MB). This
|
|
+setting may be changed upward if the configured limit needs to be increased.
|
|
+
|
|
+Note: It is important to set this to as large a value as possible, (relative
|
|
+to anticipated growth of the actual data over time) since growing the size
|
|
+later may not be practical when the system is under heavy load.
|
|
|
|
|
|
H4: olcDbMode: { <octal> | <symbolic> }
|
|
@@ -932,6 +885,18 @@ created database index files should have. This can be in the form
|
|
> olcDbMode: 0600
|
|
|
|
|
|
+H4: olcDbRtxnsize: <entries>
|
|
+
|
|
+This directive specifies the maximum number of entries to process in a single
|
|
+read transaction when executing a large search. Long-lived read transactions
|
|
+prevent old database pages from being reused in write transactions, and so
|
|
+can cause significant growth of the database file when there is heavy write
|
|
+traffic. This setting causes the read transaction in large searches to be
|
|
+released and reacquired after the given number of entries has been read, to
|
|
+give writers the opportunity to reclaim old database pages. The default is
|
|
+10000.
|
|
+
|
|
+
|
|
H4: olcDbSearchStack: <integer>
|
|
|
|
Specify the depth of the stack used for search filter evaluation.
|
|
@@ -955,33 +920,21 @@ to take effect.
|
|
> olcDbSearchStack: 16
|
|
|
|
|
|
-H4: olcDbShmKey: <integer>
|
|
-
|
|
-Specify a key for a shared memory BDB environment. By default the BDB
|
|
-environment uses memory mapped files. If a non-zero value is specified,
|
|
-it will be used as the key to identify a shared memory region that will
|
|
-house the environment.
|
|
-
|
|
-\Example:
|
|
+H4: olcDbNosync: { TRUE | FALSE }
|
|
|
|
-> olcDbShmKey: 42
|
|
+This directive causes on-disk database contents to not be immediately
|
|
+synchronized with in memory changes upon change. Setting this option
|
|
+to {{EX:TRUE}} may improve performance at the expense of data integrity.
|
|
|
|
|
|
H4: Sample Entry
|
|
|
|
->dn: olcDatabase=hdb,cn=config
|
|
+>dn: olcDatabase=mdb,cn=config
|
|
>objectClass: olcDatabaseConfig
|
|
->objectClass: olcHdbConfig
|
|
->olcDatabase: hdb
|
|
+>objectClass: olcMdbConfig
|
|
+>olcDatabase: mdb
|
|
>olcSuffix: dc=example,dc=com
|
|
>olcDbDirectory: /usr/local/var/openldap-data
|
|
->olcDbCacheSize: 1000
|
|
->olcDbCheckpoint: 1024 10
|
|
->olcDbConfig: set_cachesize 0 10485760 0
|
|
->olcDbConfig: set_lg_bsize 2097152
|
|
->olcDbConfig: set_lg_dir /var/tmp/bdb-log
|
|
->olcDbConfig: set_flags DB_LOG_AUTOREMOVE
|
|
->olcDbIDLcacheSize: 3000
|
|
>olcDbIndex: objectClass eq
|
|
|
|
|
|
@@ -989,7 +942,7 @@ H2: Configuration Example
|
|
|
|
The following is an example configuration, interspersed
|
|
with explanatory text. It defines two databases to handle
|
|
-different parts of the {{TERM:X.500}} tree; both are {{TERM:BDB}}
|
|
+different parts of the {{TERM:X.500}} tree; both are {{TERM:MDB}}
|
|
database instances. The line numbers shown are provided for
|
|
reference only and are not included in the actual file. First, the
|
|
global configuration section:
|
|
@@ -999,7 +952,7 @@ E: 2. dn: cn=config
|
|
E: 3. objectClass: olcGlobal
|
|
E: 4. cn: config
|
|
E: 5. olcReferral: ldap://root.openldap.org
|
|
-E: 6.
|
|
+E: 6.
|
|
|
|
Line 1 is a comment. Lines 2-4 identify this as the global
|
|
configuration entry.
|
|
@@ -1013,7 +966,7 @@ E: 7. # internal schema
|
|
E: 8. dn: cn=schema,cn=config
|
|
E: 9. objectClass: olcSchemaConfig
|
|
E: 10. cn: schema
|
|
-E: 11.
|
|
+E: 11.
|
|
|
|
Line 7 is a comment. Lines 8-10 identify this as the root of
|
|
the schema subtree. The actual schema definitions in this entry
|
|
@@ -1022,7 +975,7 @@ Line 11 is a blank line, indicating the end of this entry.
|
|
|
|
E: 12. # include the core schema
|
|
E: 13. include: file:///usr/local/etc/openldap/schema/core.ldif
|
|
-E: 14.
|
|
+E: 14.
|
|
|
|
Line 12 is a comment. Line 13 is an LDIF include directive which
|
|
accesses the {{core}} schema definitions in LDIF format. Line 14
|
|
@@ -1037,7 +990,7 @@ E: 16. dn: olcDatabase=frontend,cn=config
|
|
E: 17. objectClass: olcDatabaseConfig
|
|
E: 18. olcDatabase: frontend
|
|
E: 19. olcAccess: to * by * read
|
|
-E: 20.
|
|
+E: 20.
|
|
|
|
Line 15 is a comment. Lines 16-18 identify this entry as the global
|
|
database entry. Line 19 is a global access control. It applies to all
|
|
@@ -1066,16 +1019,16 @@ inaccessible.)
|
|
|
|
Line 28 is a blank line.
|
|
|
|
-The next entry defines a BDB backend that will handle queries for things
|
|
+The next entry defines an MDB backend that will handle queries for things
|
|
in the "dc=example,dc=com" portion of the tree. Indices are to be maintained
|
|
for several attributes, and the {{EX:userPassword}} attribute is to be
|
|
protected from unauthorized access.
|
|
|
|
-E: 29. # BDB definition for example.com
|
|
-E: 30. dn: olcDatabase=bdb,cn=config
|
|
+E: 29. # MDB definition for example.com
|
|
+E: 30. dn: olcDatabase=mdb,cn=config
|
|
E: 31. objectClass: olcDatabaseConfig
|
|
-E: 32. objectClass: olcBdbConfig
|
|
-E: 33. olcDatabase: bdb
|
|
+E: 32. objectClass: olcMdbConfig
|
|
+E: 33. olcDatabase: mdb
|
|
E: 34. olcSuffix: dc=example,dc=com
|
|
E: 35. olcDbDirectory: /usr/local/var/openldap-data
|
|
E: 36. olcRootDN: cn=Manager,dc=example,dc=com
|
|
@@ -1092,7 +1045,7 @@ E: 46. olcAccess: to *
|
|
E: 47. by self write
|
|
E: 48. by dn.base="cn=Admin,dc=example,dc=com" write
|
|
E: 49. by * read
|
|
-E: 50.
|
|
+E: 50.
|
|
|
|
Line 29 is a comment. Lines 30-33 identify this entry as a BDB database
|
|
configuration entry. Line 34 specifies the DN suffix
|
|
@@ -1116,16 +1069,16 @@ entry, but may be read by all users (authenticated or not).
|
|
Line 50 is a blank line, indicating the end of this entry.
|
|
|
|
The next entry defines another
|
|
-BDB database. This one handles queries involving the
|
|
+MDB database. This one handles queries involving the
|
|
{{EX:dc=example,dc=net}} subtree but is managed by the same entity
|
|
as the first database. Note that without line 60, the read access
|
|
would be allowed due to the global access rule at line 19.
|
|
|
|
-E: 51. # BDB definition for example.net
|
|
-E: 52. dn: olcDatabase=bdb,cn=config
|
|
+E: 51. # MDB definition for example.net
|
|
+E: 52. dn: olcDatabase=mdb,cn=config
|
|
E: 53. objectClass: olcDatabaseConfig
|
|
-E: 54. objectClass: olcBdbConfig
|
|
-E: 55. olcDatabase: bdb
|
|
+E: 54. objectClass: olcMdbConfig
|
|
+E: 55. olcDatabase: mdb
|
|
E: 56. olcSuffix: dc=example,dc=net
|
|
E: 57. olcDbDirectory: /usr/local/var/openldap-data-net
|
|
E: 58. olcRootDN: cn=Manager,dc=example,dc=com
|
|
diff --git a/doc/guide/admin/slapdconfig.sdf b/doc/guide/admin/slapdconfig.sdf
|
|
index d943eb9..8b1162c 100644
|
|
--- a/doc/guide/admin/slapdconfig.sdf
|
|
+++ b/doc/guide/admin/slapdconfig.sdf
|
|
@@ -90,7 +90,7 @@ H4: access to <what> [ by <who> [<accesslevel>] [<control>] ]+
|
|
|
|
This directive grants access (specified by <accesslevel>) to a set
|
|
of entries and/or attributes (specified by <what>) by one or more
|
|
-requestors (specified by <who>). See the {{SECT:Access Control}} section of
|
|
+requestors (specified by <who>). See the {{SECT:Access Control}} section of
|
|
this guide for basic usage.
|
|
|
|
!if 0
|
|
@@ -162,7 +162,7 @@ Level Keyword Description
|
|
!endblock
|
|
|
|
The desired log level can be input as a single integer that
|
|
-combines the (ORed) desired levels, both in decimal or in hexadecimal
|
|
+combines the (ORed) desired levels, both in decimal or in hexadecimal
|
|
notation, as a list of integers (that are ORed internally), or as a list of the names that are shown between brackets, such that
|
|
|
|
> loglevel 129
|
|
@@ -264,9 +264,7 @@ supported backend types listed in Table 6.2.
|
|
!block table; align=Center; coltags="EX,N"; \
|
|
title="Table 6.2: Database Backends"
|
|
Types Description
|
|
-bdb Berkeley DB transactional backend (deprecated)
|
|
dnssrv DNS SRV backend
|
|
-hdb Hierarchical variant of bdb backend (deprecated)
|
|
ldap Lightweight Directory Access Protocol (Proxy) backend
|
|
mdb Memory-Mapped DB backend
|
|
meta Meta Directory backend
|
|
@@ -507,7 +505,7 @@ defaults for these parameters come from {{ldap.conf}}(5).
|
|
The {{EX:binddn}} parameter gives the DN to bind as for the
|
|
syncrepl searches to the provider slapd. It should be a DN
|
|
which has read access to the replication content in the
|
|
-master database.
|
|
+master database.
|
|
|
|
The {{EX:bindmethod}} is {{EX:simple}} or {{EX:sasl}},
|
|
depending on whether simple password-based authentication or
|
|
@@ -564,8 +562,7 @@ conforms to the obsolete {{changelog}} format. If the {{EX:syncdata}}
|
|
parameter is omitted or set to {{EX:"default"}} then the log
|
|
parameters are ignored.
|
|
|
|
-The {{syncrepl}} replication mechanism is supported by the {{bdb}},
|
|
-{{hdb}}, and {{mdb}} backends.
|
|
+The {{syncrepl}} replication mechanism is supported by the {{mdb}} backends.
|
|
|
|
See the {{SECT:LDAP Sync Replication}} chapter of this guide for
|
|
more information on how to use this directive.
|
|
@@ -584,19 +581,18 @@ If specified multiple times, each {{TERM:URL}} is provided.
|
|
> updateref ldap://master.example.net
|
|
|
|
|
|
-H3: BDB and HDB Database Directives
|
|
+H3: MDB Database Directives
|
|
|
|
-Directives in this category only apply to both the {{TERM:BDB}}
|
|
-and the {{TERM:HDB}} database.
|
|
-That is, they must follow a "database bdb" or "database hdb" line
|
|
-and come before any
|
|
-subsequent "backend" or "database" line. For a complete reference
|
|
-of BDB/HDB configuration directives, see {{slapd-bdb}}(5).
|
|
+Directives in this category only apply to the {{TERM:MDB}}
|
|
+database backend.
|
|
+That is, they must follow a "database mdb" line
|
|
+and come before any subsequent "backend" or "database" lines.
|
|
+For a complete reference of MDB configuration directives, see {{slapd-mdb}}(5).
|
|
|
|
|
|
H4: directory <directory>
|
|
|
|
-This directive specifies the directory where the BDB files
|
|
+This directive specifies the directory where the MDB files
|
|
containing the database and associated indices live.
|
|
|
|
\Default:
|
|
@@ -604,11 +600,189 @@ containing the database and associated indices live.
|
|
> directory /usr/local/var/openldap-data
|
|
|
|
|
|
+H4: checkpoint <kbyte> <min>
|
|
+
|
|
+This directive specifies the frequency for flushing the database disk
|
|
+buffers. This directive is only needed if the {{dbnosync}} option is
|
|
+{{EX:TRUE}}.
|
|
+The checkpoint will occur if either <kbyte> data has been written or
|
|
+<min> minutes have passed since the last checkpoint. Both arguments default
|
|
+to zero, in which case they are ignored. When the <min> argument is
|
|
+non-zero, an internal task will run every <min> minutes to perform the
|
|
+checkpoint. Note: currently the _kbyte_ setting is unimplemented.
|
|
+
|
|
+\Example:
|
|
+
|
|
+> checkpoint: 1024 10
|
|
+
|
|
+H4: dbnosync: { TRUE | FALSE }
|
|
+
|
|
+This directive causes on-disk database contents to not be immediately
|
|
+synchronized with in memory changes upon change. Setting this option
|
|
+to {{EX:TRUE}} may improve performance at the expense of data integrity.
|
|
+
|
|
+
|
|
+H4: envflags: {nosync,nometasync,writemap,mapasync,nordahead}
|
|
+
|
|
+This option specifies flags for finer-grained control of the LMDB library's
|
|
+operation.
|
|
+
|
|
+* {{F:nosync}}: This is exactly the same as the dbnosync directive.
|
|
+
|
|
+* {{F:nometasync}}: Flush the data on a commit, but skip the sync of the meta
|
|
+page. This mode is slightly faster than doing a full sync, but can
|
|
+potentially lose the last committed transaction if the operating system
|
|
+crashes. If both nometasync and nosync are set, the nosync flag takes
|
|
+precedence.
|
|
+
|
|
+* {{F:writemap}}: Use a writable memory map instead of just read-only. This
|
|
+speeds up write operations but makes the database vulnerable to corruption in
|
|
+case any bugs in slapd cause stray writes into the mmap region.
|
|
+
|
|
+* {{F:mapasync}}: When using a writable memory map and performing flushes on
|
|
+each commit, use an asynchronous flush instead of a synchronous flush (the
|
|
+default). This option has no effect if writemap has not been set. It also has
|
|
+no effect if nosync is set.
|
|
+
|
|
+* {{F:nordahead}}: Turn off file readahead. Usually the OS performs readahead
|
|
+on every read request. This usually boosts read performance but can be
|
|
+harmful to random access read performance if the system's memory is full and
|
|
+the DB is larger than RAM. This option is not implemented on Windows.
|
|
+
|
|
+
|
|
+H4: index: {<attrlist> | default} [pres,eq,approx,sub,none]
|
|
+
|
|
+This directive specifies the indices to maintain for the given
|
|
+attribute. If only an {{EX:<attrlist>}} is given, the default
|
|
+indices are maintained. The index keywords correspond to the
|
|
+common types of matches that may be used in an LDAP search filter.
|
|
+
|
|
+\Example:
|
|
+
|
|
+> index: default pres,eq
|
|
+> index: uid
|
|
+> index: cn,sn pres,eq,sub
|
|
+> index: objectClass eq
|
|
+
|
|
+The first line sets the default set of indices to maintain to
|
|
+present and equality. The second line causes the default (pres,eq)
|
|
+set of indices to be maintained for the {{EX:uid}} attribute type.
|
|
+The third line causes present, equality, and substring indices to
|
|
+be maintained for {{EX:cn}} and {{EX:sn}} attribute types. The
|
|
+fourth line causes an equality index for the {{EX:objectClass}}
|
|
+attribute type.
|
|
+
|
|
+There is no index keyword for inequality matches. Generally these
|
|
+matches do not use an index. However, some attributes do support
|
|
+indexing for inequality matches, based on the equality index.
|
|
+
|
|
+A substring index can be more explicitly specified as {{EX:subinitial}},
|
|
+{{EX:subany}}, or {{EX:subfinal}}, corresponding to the three
|
|
+possible components
|
|
+of a substring match filter. A subinitial index only indexes
|
|
+substrings that appear at the beginning of an attribute value.
|
|
+A subfinal index only indexes substrings that appear at the end
|
|
+of an attribute value, while subany indexes substrings that occur
|
|
+anywhere in a value.
|
|
+
|
|
+Note that by default, setting an index for an attribute also
|
|
+affects every subtype of that attribute. E.g., setting an equality
|
|
+index on the {{EX:name}} attribute causes {{EX:cn}}, {{EX:sn}}, and every other
|
|
+attribute that inherits from {{EX:name}} to be indexed.
|
|
+
|
|
+By default, no indices are maintained. It is generally advised
|
|
+that minimally an equality index upon objectClass be maintained.
|
|
+
|
|
+> index: objectClass eq
|
|
+
|
|
+Additional indices should be configured corresponding to the
|
|
+most common searches that are used on the database.
|
|
+Presence indexing should not be configured for an attribute
|
|
+unless the attribute occurs very rarely in the database, and
|
|
+presence searches on the attribute occur very frequently during
|
|
+normal use of the directory. Most applications don't use presence
|
|
+searches, so usually presence indexing is not very useful.
|
|
+
|
|
+
|
|
+H4: maxreaders: <integer>
|
|
+
|
|
+This directive specifies the maximum number of threads that may have
|
|
+concurrent read access to the database. Tools such as slapcat count as a
|
|
+single thread, in addition to threads in any active slapd processes. The
|
|
+default is 126.
|
|
+
|
|
+
|
|
+H4: maxsize: <bytes>
|
|
+
|
|
+This directive specifies the maximum size of the database in bytes. A memory
|
|
+map of this size is allocated at startup time and the database will not be
|
|
+allowed to grow beyond this size. The default is 10485760 bytes (10MB). This
|
|
+setting may be changed upward if the configured limit needs to be increased.
|
|
+
|
|
+Note: It is important to set this to as large a value as possible, (relative
|
|
+to anticipated growth of the actual data over time) since growing the size
|
|
+later may not be practical when the system is under heavy load.
|
|
+
|
|
+
|
|
+H4: mode: { <octal> | <symbolic> }
|
|
+
|
|
+This directive specifies the file protection mode that newly
|
|
+created database index files should have. This can be in the form
|
|
+{{EX:0600}} or {{EX:-rw-------}}
|
|
+
|
|
+\Default:
|
|
+
|
|
+> mode: 0600
|
|
+
|
|
+
|
|
+H4: rtxnsize: <entries>
|
|
+
|
|
+This directive specifies the maximum number of entries to process in a single
|
|
+read transaction when executing a large search. Long-lived read transactions
|
|
+prevent old database pages from being reused in write transactions, and so
|
|
+can cause significant growth of the database file when there is heavy write
|
|
+traffic. This setting causes the read transaction in large searches to be
|
|
+released and reacquired after the given number of entries has been read, to
|
|
+give writers the opportunity to reclaim old database pages. The default is
|
|
+10000.
|
|
+
|
|
+
|
|
+H4: searchstack: <integer>
|
|
+
|
|
+Specify the depth of the stack used for search filter evaluation.
|
|
+Search filters are evaluated on a stack to accommodate nested {{EX:AND}} /
|
|
+{{EX:OR}} clauses. An individual stack is allocated for each server thread.
|
|
+The depth of the stack determines how complex a filter can be evaluated
|
|
+without requiring any additional memory allocation. Filters that are
|
|
+nested deeper than the search stack depth will cause a separate stack to
|
|
+be allocated for that particular search operation. These separate allocations
|
|
+can have a major negative impact on server performance, but specifying
|
|
+too much stack will also consume a great deal of memory. Each search
|
|
+uses 512K bytes per level on a 32-bit machine, or 1024K bytes per level
|
|
+on a 64-bit machine. The default stack depth is 16, thus 8MB or 16MB
|
|
+per thread is used on 32 and 64 bit machines, respectively. Also the
|
|
+512KB size of a single stack slot is set by a compile-time constant which
|
|
+may be changed if needed; the code must be recompiled for the change
|
|
+to take effect.
|
|
+
|
|
+\Default:
|
|
+
|
|
+> searchstack: 16
|
|
+
|
|
+
|
|
+H4: Sample Entry
|
|
+
|
|
+>database mdb
|
|
+>suffix: "dc=example,dc=com"
|
|
+>directory: /usr/local/var/openldap-data
|
|
+>index: objectClass eq
|
|
+
|
|
+
|
|
H2: Configuration File Example
|
|
|
|
The following is an example configuration file, interspersed
|
|
with explanatory text. It defines two databases to handle
|
|
-different parts of the {{TERM:X.500}} tree; both are {{TERM:BDB}}
|
|
+different parts of the {{TERM:X.500}} tree; both are {{TERM:MDB}}
|
|
database instances. The line numbers shown are provided for
|
|
reference only and are not included in the actual file. First, the
|
|
global configuration section:
|
|
@@ -617,7 +791,7 @@ E: 1. # example config file - global configuration section
|
|
E: 2. include /usr/local/etc/schema/core.schema
|
|
E: 3. referral ldap://root.openldap.org
|
|
E: 4. access to * by * read
|
|
-
|
|
+
|
|
Line 1 is a comment. Line 2 includes another config file
|
|
which contains {{core}} schema definitions.
|
|
The {{EX:referral}} directive on line 3
|
|
@@ -629,7 +803,7 @@ Line 4 is a global access control. It applies to all
|
|
entries (after any applicable database-specific access
|
|
controls).
|
|
|
|
-The next section of the configuration file defines a BDB
|
|
+The next section of the configuration file defines a MDB
|
|
backend that will handle queries for things in the
|
|
"dc=example,dc=com" portion of the tree. The
|
|
database is to be replicated to two slave slapds, one on
|
|
@@ -637,8 +811,8 @@ truelies, the other on judgmentday. Indices are to be
|
|
maintained for several attributes, and the {{EX:userPassword}}
|
|
attribute is to be protected from unauthorized access.
|
|
|
|
-E: 5. # BDB definition for the example.com
|
|
-E: 6. database bdb
|
|
+E: 5. # MDB definition for the example.com
|
|
+E: 6. database mdb
|
|
E: 7. suffix "dc=example,dc=com"
|
|
E: 8. directory /usr/local/var/openldap-data
|
|
E: 9. rootdn "cn=Manager,dc=example,dc=com"
|
|
@@ -683,8 +857,8 @@ BDB database. This one handles queries involving the
|
|
as the first database. Note that without line 39, the read access
|
|
would be allowed due to the global access rule at line 4.
|
|
|
|
-E: 33. # BDB definition for example.net
|
|
-E: 34. database bdb
|
|
+E: 33. # MDB definition for example.net
|
|
+E: 34. database mdb
|
|
E: 35. suffix "dc=example,dc=net"
|
|
E: 36. directory /usr/local/var/openldap-data-net
|
|
E: 37. rootdn "cn=Manager,dc=example,dc=com"
|
|
diff --git a/doc/guide/admin/tuning.sdf b/doc/guide/admin/tuning.sdf
|
|
index 7074561..795c5ce 100644
|
|
--- a/doc/guide/admin/tuning.sdf
|
|
+++ b/doc/guide/admin/tuning.sdf
|
|
@@ -27,10 +27,6 @@ H3: Memory
|
|
|
|
Scale your cache to use available memory and increase system memory if you can.
|
|
|
|
-See {{SECT:Caching}} for BDB cache tuning hints.
|
|
-Note that LMDB uses no cache of its own and has no tuning options, so the Caching
|
|
-section can be ignored when using LMDB.
|
|
-
|
|
|
|
H3: Disks
|
|
|
|
@@ -39,15 +35,7 @@ types perform best with your workload. (On our own Linux testing, EXT2 and JFS
|
|
tend to provide better write performance than everything else, including
|
|
newer filesystems like EXT4, BTRFS, etc.)
|
|
|
|
-Use fast subsystems. Put each database and logs on separate disks
|
|
-(for BDB this is configurable via {{DB_CONFIG}}):
|
|
-
|
|
-> # Data Directory
|
|
-> set_data_dir /data/db
|
|
->
|
|
-> # Transaction Log settings
|
|
-> set_lg_dir /logs
|
|
-
|
|
+Use fast subsystems. Put each database on separate disks
|
|
|
|
H3: Network Topology
|
|
|
|
@@ -131,7 +119,7 @@ H3: What to watch out for
|
|
|
|
The most common message you'll see that you should pay attention to is:
|
|
|
|
-> "<= bdb_equality_candidates: (foo) index_param failed (18)"
|
|
+> "<= mdb_equality_candidates: (foo) index_param failed (18)"
|
|
|
|
That means that some application tried to use an equality filter ({{foo=<somevalue>}})
|
|
and attribute {{foo}} does not have an equality index. If you see a lot of these
|
|
@@ -163,165 +151,6 @@ For syslog-ng, add or modify the following line in {{syslog-ng.conf}}:
|
|
where n is the number of lines which will be buffered before a write.
|
|
|
|
|
|
-H2: Caching
|
|
-
|
|
-We all know what caching is, don't we?
|
|
-
|
|
-In brief, "A cache is a block of memory for temporary storage of data likely
|
|
-to be used again" - {{URL:http://en.wikipedia.org/wiki/Cache}}
|
|
-
|
|
-There are 3 types of caches, BerkeleyDB's own cache, {{slapd}}(8)
|
|
-entry cache and {{TERM:IDL}} (IDL) cache.
|
|
-
|
|
-
|
|
-H3: Berkeley DB Cache
|
|
-
|
|
-There are two ways to tune for the BDB cachesize:
|
|
-
|
|
-(a) BDB cache size necessary to load the database via slapadd in optimal time
|
|
-
|
|
-(b) BDB cache size necessary to have a high performing running slapd once the data is loaded
|
|
-
|
|
-For (a), the optimal cachesize is the size of the entire database. If you
|
|
-already have the database loaded, this is simply a
|
|
-
|
|
-> du -c -h *.bdb
|
|
-
|
|
-in the directory containing the OpenLDAP ({{/usr/local/var/openldap-data}}) data.
|
|
-
|
|
-For (b), the optimal cachesize is just the size of the {{id2entry.bdb}} file,
|
|
-plus about 10% for growth.
|
|
-
|
|
-The tuning of {{DB_CONFIG}} should be done for each BDB type database
|
|
-instantiated (back-bdb, back-hdb).
|
|
-
|
|
-Note that while the {{TERM:BDB}} cache is just raw chunks of memory and
|
|
-configured as a memory size, the {{slapd}}(8) entry cache holds parsed entries,
|
|
-and the size of each entry is variable.
|
|
-
|
|
-There is also an IDL cache which is used for Index Data Lookups.
|
|
-If you can fit all of your database into slapd's entry cache, and all of your
|
|
-index lookups fit in the IDL cache, that will provide the maximum throughput.
|
|
-
|
|
-If not, but you can fit the entire database into the BDB cache, then you
|
|
-should do that and shrink the slapd entry cache as appropriate.
|
|
-
|
|
-Failing that, you should balance the BDB cache against the entry cache.
|
|
-
|
|
-It is worth noting that it is not absolutely necessary to configure a BerkeleyDB
|
|
-cache equal in size to your entire database. All that you need is a cache
|
|
-that's large enough for your "working set."
|
|
-
|
|
-That means, large enough to hold all of the most frequently accessed data,
|
|
-plus a few less-frequently accessed items.
|
|
-
|
|
-For more information, please see: {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/ref/am_conf/cachesize.html}}
|
|
-
|
|
-H4: Calculating Cachesize
|
|
-
|
|
-The back-bdb database lives in two main files, {{F:dn2id.bdb}} and {{F:id2entry.bdb}}.
|
|
-These are B-tree databases. We have never documented the back-bdb internal
|
|
-layout before, because it didn't seem like something anyone should have to worry
|
|
-about, nor was it necessarily cast in stone. But here's how it works today,
|
|
-in OpenLDAP 2.4.
|
|
-
|
|
-A B-tree is a balanced tree; it stores data in its leaf nodes and bookkeeping
|
|
-data in its interior nodes (If you don't know what tree data structures look
|
|
- like in general, Google for some references, because that's getting far too
|
|
-elementary for the purposes of this discussion).
|
|
-
|
|
-For decent performance, you need enough cache memory to contain all the nodes
|
|
-along the path from the root of the tree down to the particular data item
|
|
-you're accessing. That's enough cache for a single search. For the general case,
|
|
-you want enough cache to contain all the internal nodes in the database.
|
|
-
|
|
-> db_stat -d
|
|
-
|
|
-will tell you how many internal pages are present in a database. You should
|
|
-check this number for both dn2id and id2entry.
|
|
-
|
|
-Also note that {{id2entry}} always uses 16KB per "page", while {{dn2id}} uses whatever
|
|
-the underlying filesystem uses, typically 4 or 8KB. To avoid thrashing,
|
|
-your cache must be at least as large as the number of internal pages in both
|
|
-the {{dn2id}} and {{id2entry}} databases, plus some extra space to accommodate
|
|
-the actual leaf data pages.
|
|
-
|
|
-For example, in my OpenLDAP 2.4 test database, I have an input LDIF file that's
|
|
-about 360MB. With the back-hdb backend this creates a {{dn2id.bdb}} that's 68MB,
|
|
-and an {{id2entry}} that's 800MB. db_stat tells me that {{dn2id}} uses 4KB pages, has
|
|
-433 internal pages, and 6378 leaf pages. The id2entry uses 16KB pages, has 52
|
|
-internal pages, and 45912 leaf pages. In order to efficiently retrieve any
|
|
-single entry in this database, the cache should be at least
|
|
-
|
|
-> (433+1) * 4KB + (52+1) * 16KB in size: 1736KB + 848KB =~ 2.5MB.
|
|
-
|
|
-This doesn't take into account other library overhead, so this is even lower
|
|
-than the barest minimum. The default cache size, when nothing is configured,
|
|
-is only 256KB.
|
|
-
|
|
-This 2.5MB number also doesn't take indexing into account. Each indexed
|
|
-attribute results in another database file. Earlier versions of OpenLDAP
|
|
-kept these index databases in Hash format, but from OpenLDAP 2.2 onward
|
|
-the index databases are in B-tree format so the same procedure can
|
|
-be used to calculate the necessary amount of cache for each index database.
|
|
-
|
|
-For example, if your only index is for the objectClass attribute and db_stat
|
|
-reveals that {{objectClass.bdb}} has 339 internal pages and uses 4096 byte
|
|
-pages, the additional cache needed for just this attribute index is
|
|
-
|
|
-> (339+1) * 4KB =~ 1.3MB.
|
|
-
|
|
-With only this index enabled, I'd figure at least a 4MB cache for this backend.
|
|
-(Of course you're using a single cache shared among all of the database files,
|
|
-so the cache pages will most likely get used for something other than what you
|
|
-accounted for, but this gives you a fighting chance.)
|
|
-
|
|
-With this 4MB cache I can slapcat this entire database on my 1.3GHz PIII in
|
|
-1 minute, 40 seconds. With the cache doubled to 8MB, it still takes the same 1:40s.
|
|
-Once you've got enough cache to fit the B-tree internal pages, increasing it
|
|
-further won't have any effect until the cache really is large enough to hold
|
|
-100% of the data pages. I don't have enough free RAM to hold all the 800MB
|
|
-id2entry data, so 4MB is good enough.
|
|
-
|
|
-With back-bdb and back-hdb you can use "db_stat -m" to check how well the
|
|
-database cache is performing.
|
|
-
|
|
-For more information on {{db_stat}}: {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/utility/db_stat.html}}
|
|
-
|
|
-H3: {{slapd}}(8) Entry Cache (cachesize)
|
|
-
|
|
-The {{slapd}}(8) entry cache operates on decoded entries. The rationale - entries
|
|
-in the entry cache can be used directly, giving the fastest response. If an entry
|
|
-isn't in the entry cache but can be extracted from the BDB page cache, that will
|
|
-avoid an I/O but it will still require parsing, so this will be slower.
|
|
-
|
|
-If the entry is in neither cache then BDB will have to flush some of its current
|
|
-cached pages and bring in the needed pages, resulting in a couple of expensive
|
|
-I/Os as well as parsing.
|
|
-
|
|
-The most optimal value is of course, the entire number of entries in the database.
|
|
-However, most directory servers don't consistently serve out their entire database, so setting this to a lesser number that more closely matches the believed working set of data is
|
|
-sufficient. This is the second most important parameter for the DB.
|
|
-
|
|
-As far as balancing the entry cache vs the BDB cache - parsed entries in memory
|
|
-are generally about twice as large as they are on disk.
|
|
-
|
|
-As we have already mentioned, not having a proper database cache size will
|
|
-cause performance issues. These issues are not an indication of corruption
|
|
-occurring in the database. It is merely the fact that the cache is thrashing
|
|
-itself that causes performance/response time to slowdown.
|
|
-
|
|
-
|
|
-H3: {{TERM:IDL}} Cache (idlcachesize)
|
|
-
|
|
-Each IDL holds the search results from a given query, so the IDL cache will
|
|
-end up holding the most frequently requested search results. For back-bdb,
|
|
-it is generally recommended to match the "cachesize" setting. For back-hdb,
|
|
-it is generally recommended to be 3x"cachesize".
|
|
-
|
|
-{NOTE: The idlcachesize setting directly affects search performance}
|
|
-
|
|
-
|
|
H2: {{slapd}}(8) Threads
|
|
|
|
{{slapd}}(8) can process requests via a configurable number of threads, which
|
|
diff --git a/doc/guide/preamble.sdf b/doc/guide/preamble.sdf
|
|
index b4cc0dd..aa84f9b 100644
|
|
--- a/doc/guide/preamble.sdf
|
|
+++ b/doc/guide/preamble.sdf
|
|
@@ -167,7 +167,6 @@ AuthcId|Authentication Identity
|
|
AuthzDN|Authorization DN
|
|
AuthzId|Authorization Identity
|
|
BCP|Best Current Practice
|
|
-BDB|Berkeley DB (Backend)
|
|
BER|Basic Encoding Rules
|
|
BNF|Backus-Naur Form
|
|
C|The C Programming Language
|
|
@@ -201,7 +200,6 @@ FYI|For Your Information
|
|
GSER|Generic String Encoding Rules
|
|
GSS-API|Generic Security Service Application Program Interface
|
|
GSSAPI|SASL Kerberos V GSS-API Authentication Mechanism
|
|
-HDB|Hierarchical Database (Backend)
|
|
I-D|Internet-Draft
|
|
IA5|International Alphabet 5
|
|
IDNA|Internationalized Domain Names in Applications
|
|
diff --git a/doc/guide/release/install.sdf b/doc/guide/release/install.sdf
|
|
index 6770e6a..83c95ae 100644
|
|
--- a/doc/guide/release/install.sdf
|
|
+++ b/doc/guide/release/install.sdf
|
|
@@ -84,7 +84,7 @@ if you have not done so already.
|
|
+ Test the standalone system:
|
|
|
|
.This step requires the standalone LDAP server, {{slapd}}(8),
|
|
-with {{HDB}} and/or {{BDB}} support.
|
|
+with {{MDB}} support.
|
|
|
|
E: % make test
|
|
|
|
diff --git a/doc/man/man5/slapd-bdb.5 b/doc/man/man5/slapd-bdb.5
|
|
deleted file mode 100644
|
|
index 3c8ad9c..0000000
|
|
--- a/doc/man/man5/slapd-bdb.5
|
|
+++ /dev/null
|
|
@@ -1,286 +0,0 @@
|
|
-.TH SLAPD-BDB 5 "RELEASEDATE" "OpenLDAP LDVERSION"
|
|
-.\" Copyright 1998-2020 The OpenLDAP Foundation All Rights Reserved.
|
|
-.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
|
-.\" $OpenLDAP$
|
|
-.SH NAME
|
|
-slapd\-bdb, slapd\-hdb \- Berkeley DB backends to slapd
|
|
-.SH SYNOPSIS
|
|
-.B ETCDIR/slapd.conf
|
|
-.SH DESCRIPTION
|
|
-The \fBbdb\fP backend to
|
|
-.BR slapd (8)
|
|
-uses the Oracle Berkeley DB (BDB) package to store data.
|
|
-It makes extensive use of indexing and caching to speed data access.
|
|
-.LP
|
|
-Note that BDB is deprecated and support will be dropped in future
|
|
-OpenLDAP releases. Installations should use the \fBmdb\fP
|
|
-backend instead.
|
|
-.LP
|
|
-\fBhdb\fP is a variant of
|
|
-the \fBbdb\fP backend that uses a hierarchical database layout which
|
|
-supports subtree renames. It is both more space-efficient and more
|
|
-execution-efficient than the \fBbdb\fP backend. It is otherwise identical
|
|
-to the \fBbdb\fP behavior, and all the same configuration options apply.
|
|
-.LP
|
|
-It is noted that these options are intended to complement
|
|
-Berkeley DB configuration options set in the environment's
|
|
-.B DB_CONFIG
|
|
-file. See Berkeley DB documentation for details on
|
|
-.B DB_CONFIG
|
|
-configuration options.
|
|
-Where there is overlap, settings in
|
|
-.B DB_CONFIG
|
|
-take precedence.
|
|
-.SH CONFIGURATION
|
|
-These
|
|
-.B slapd.conf
|
|
-options apply to the \fBbdb\fP and \fBhdb\fP backend database.
|
|
-That is, they must follow a "database bdb" or "database hdb" line and
|
|
-come before any subsequent "backend" or "database" lines.
|
|
-Other database options are described in the
|
|
-.BR slapd.conf (5)
|
|
-manual page.
|
|
-.TP
|
|
-.BI cachesize \ <integer>
|
|
-Specify the size in entries of the in-memory entry cache maintained
|
|
-by the \fBbdb\fP or \fBhdb\fP backend database instance.
|
|
-The default is 1000 entries.
|
|
-.TP
|
|
-.BI cachefree \ <integer>
|
|
-Specify the number of entries to free from the entry cache when the
|
|
-cache reaches the \fBcachesize\fP limit.
|
|
-The default is 1 entry.
|
|
-.TP
|
|
-.BI checkpoint \ <kbyte>\ <min>
|
|
-Specify the frequency for checkpointing the database transaction log.
|
|
-A checkpoint operation flushes the database buffers to disk and writes
|
|
-a checkpoint record in the log.
|
|
-The checkpoint will occur if either \fI<kbyte>\fP data has been written or
|
|
-\fI<min>\fP minutes have passed since the last checkpoint.
|
|
-Both arguments default to zero, in which case they are ignored. When
|
|
-the \fI<min>\fP argument is non-zero, an internal task will run every
|
|
-\fI<min>\fP minutes to perform the checkpoint.
|
|
-See the Berkeley DB reference guide for more details.
|
|
-.TP
|
|
-.B checksum
|
|
-Enable checksum validation of DB pages whenever they are read from disk.
|
|
-This setting can only be configured before any database files are created.
|
|
-.TP
|
|
-.BI cryptfile \ <file>
|
|
-Specify the pathname of a file containing an encryption key to use for
|
|
-encrypting the database. Encryption is performed using Berkeley DB's
|
|
-implementation of AES. Note that encryption can only be configured before
|
|
-any database files are created, and changing the key can only be done
|
|
-after destroying the current database and recreating it. Encryption is
|
|
-not enabled by default, and some distributions of Berkeley DB do not
|
|
-support encryption.
|
|
-.TP
|
|
-.BI cryptkey \ <key>
|
|
-Specify an encryption key to use for encrypting the database. This option
|
|
-may be used when a separate
|
|
-.I cryptfile
|
|
-is not desired. Only one of
|
|
-.B cryptkey
|
|
-or
|
|
-.B cryptfile
|
|
-may be configured.
|
|
-.TP
|
|
-.BI dbconfig \ <Berkeley-DB-setting>
|
|
-Specify a configuration directive to be placed in the
|
|
-.B DB_CONFIG
|
|
-file of the database directory. The
|
|
-.B dbconfig
|
|
-directive is just a convenience
|
|
-to allow all necessary configuration to be set in the
|
|
-.B slapd.conf
|
|
-file.
|
|
-The options set using this directive will only be written to the
|
|
-.B DB_CONFIG
|
|
-file if no such file existed at server startup time, otherwise
|
|
-they are completely ignored. This allows one
|
|
-to set initial values without overwriting/destroying a
|
|
-.B DB_CONFIG
|
|
-file that was already customized through other means.
|
|
-This directive may be specified multiple times, as needed.
|
|
-For example:
|
|
-.RS
|
|
-.nf
|
|
- dbconfig set_cachesize 0 1048576 0
|
|
- dbconfig set_lg_bsize 2097152
|
|
-.fi
|
|
-.RE
|
|
-.TP
|
|
-.B dbnosync
|
|
-Specify that on-disk database contents should not be immediately
|
|
-synchronized with in memory changes.
|
|
-Enabling this option may improve performance at the expense of data
|
|
-security.
|
|
-See the Berkeley DB reference guide for more details.
|
|
-.TP
|
|
-\fBdbpagesize \fR \fI<dbfile> <size>\fR
|
|
-Specify the page size to use for a particular database file, in units
|
|
-of 1024 bytes. The default for the
|
|
-.B id2entry
|
|
-file is 16, the default for all other files depends on the size of the
|
|
-underlying filesystem's block size (typically 4 or 8).
|
|
-The maximum that BerkeleyDB supports is 64. This
|
|
-setting usually should not need to be changed, but if BerkeleyDB's
|
|
-"db_stat \-d" shows a large amount of overflow pages in use in a file,
|
|
-setting a larger size may increase performance at the expense of
|
|
-data integrity. This setting only takes effect when a database is
|
|
-being newly created. See the Berkeley DB reference guide for more details.
|
|
-.TP
|
|
-.BI directory \ <directory>
|
|
-Specify the directory where the BDB files containing this database and
|
|
-associated indexes live.
|
|
-A separate directory must be specified for each database.
|
|
-The default is
|
|
-.BR LOCALSTATEDIR/openldap\-data .
|
|
-.TP
|
|
-.B dirtyread
|
|
-Allow reads of modified but not yet committed data.
|
|
-Usually transactions are isolated to prevent other operations from
|
|
-accessing uncommitted data.
|
|
-This option may improve performance, but may also return inconsistent
|
|
-results if the data comes from a transaction that is later aborted.
|
|
-In this case, the modified data is discarded and a subsequent search
|
|
-will return a different result.
|
|
-.TP
|
|
-.BI dncachesize \ <integer>
|
|
-Specify the maximum number of DNs in the in-memory DN cache.
|
|
-Ideally this cache should be
|
|
-large enough to contain the DNs of every entry in the database. If
|
|
-set to a smaller value than the \fBcachesize\fP it will be silently
|
|
-increased to equal the \fBcachesize\fP. The default value is 0 which
|
|
-means unlimited, i.e. the DN cache will grow without bound.
|
|
-
|
|
-It should be noted that the \fBDN cache\fP is allowed to temporarily
|
|
-grow beyond the configured size. It does this if many entries are
|
|
-locked when it tries to do a purge, because that means they're
|
|
-legitimately in use. Also, the \fBDN cache\fP never purges entries
|
|
-that have cached children, so depending on the shape of the DIT, it
|
|
-could have lots of cached DNs over the defined limit.
|
|
-.TP
|
|
-.BI idlcachesize \ <integer>
|
|
-Specify the size of the in-memory index cache, in index slots. The
|
|
-default is zero. A larger value will speed up frequent searches of
|
|
-indexed entries. An \fBhdb\fP database needs a large \fBidlcachesize\fP
|
|
-for good search performance, typically three times the
|
|
-.B cachesize
|
|
-(entry cache size)
|
|
-or larger.
|
|
-.TP
|
|
-\fBindex \fR{\fI<attrlist>\fR|\fBdefault\fR} [\fBpres\fR,\fBeq\fR,\fBapprox\fR,\fBsub\fR,\fI<special>\fR]
|
|
-Specify the indexes to maintain for the given attribute (or
|
|
-list of attributes).
|
|
-Some attributes only support a subset of indexes.
|
|
-If only an \fI<attr>\fP is given, the indices specified for \fBdefault\fR
|
|
-are maintained.
|
|
-Note that setting a default does not imply that all attributes will be
|
|
-indexed. Also, for best performance, an
|
|
-.B eq
|
|
-index should always be configured for the
|
|
-.B objectClass
|
|
-attribute.
|
|
-
|
|
-A number of special index parameters may be specified.
|
|
-The index type
|
|
-.B sub
|
|
-can be decomposed into
|
|
-.BR subinitial ,
|
|
-.BR subany ,\ and
|
|
-.B subfinal
|
|
-indices.
|
|
-The special type
|
|
-.B nolang
|
|
-may be specified to disallow use of this index by language subtypes.
|
|
-The special type
|
|
-.B nosubtypes
|
|
-may be specified to disallow use of this index by named subtypes.
|
|
-Note: changing \fBindex\fP settings in
|
|
-.BR slapd.conf (5)
|
|
-requires rebuilding indices, see
|
|
-.BR slapindex (8);
|
|
-changing \fBindex\fP settings
|
|
-dynamically by LDAPModifying "cn=config" automatically causes rebuilding
|
|
-of the indices online in a background task.
|
|
-.TP
|
|
-.B linearindex
|
|
-Tell
|
|
-.B slapindex
|
|
-to index one attribute at a time. By default, all indexed
|
|
-attributes in an entry are processed at the same time. With this option,
|
|
-each indexed attribute is processed individually, using multiple passes
|
|
-through the entire database. This option improves
|
|
-.B slapindex
|
|
-performance
|
|
-when the database size exceeds the \fBdbcache\fP size. When the \fBdbcache\fP is
|
|
-large enough, this option is not needed and will decrease performance.
|
|
-Also by default,
|
|
-.B slapadd
|
|
-performs full indexing and so a separate
|
|
-.B slapindex
|
|
-run is not needed. With this option,
|
|
-.B slapadd
|
|
-does no indexing and
|
|
-.B slapindex
|
|
-must be used.
|
|
-.TP
|
|
-.BR lockdetect \ { oldest | youngest | fewest | random | default }
|
|
-Specify which transaction to abort when a deadlock is detected.
|
|
-The default is
|
|
-.BR random .
|
|
-.TP
|
|
-.BI mode \ <integer>
|
|
-Specify the file protection mode that newly created database
|
|
-index files should have.
|
|
-The default is 0600.
|
|
-.TP
|
|
-.BI searchstack \ <depth>
|
|
-Specify the depth of the stack used for search filter evaluation.
|
|
-Search filters are evaluated on a stack to accommodate nested AND / OR
|
|
-clauses. An individual stack is assigned to each server thread.
|
|
-The depth of the stack determines how complex a filter can be
|
|
-evaluated without requiring any additional memory allocation. Filters that
|
|
-are nested deeper than the search stack depth will cause a separate
|
|
-stack to be allocated for that particular search operation. These
|
|
-allocations can have a major negative impact on server performance,
|
|
-but specifying too much stack will also consume a great deal of memory.
|
|
-Each search stack uses 512K bytes per level. The default stack depth
|
|
-is 16, thus 8MB per thread is used.
|
|
-.TP
|
|
-.BI shm_key \ <integer>
|
|
-Specify a key for a shared memory BDB environment. By default the
|
|
-BDB environment uses memory mapped files. If a non-zero value is
|
|
-specified, it will be used as the key to identify a shared memory
|
|
-region that will house the environment.
|
|
-.SH ACCESS CONTROL
|
|
-The
|
|
-.B bdb
|
|
-and
|
|
-.B hdb
|
|
-backends honor access control semantics as indicated in
|
|
-.BR slapd.access (5).
|
|
-.SH FILES
|
|
-.TP
|
|
-.B ETCDIR/slapd.conf
|
|
-default
|
|
-.B slapd
|
|
-configuration file
|
|
-.TP
|
|
-.B DB_CONFIG
|
|
-Berkeley DB configuration file
|
|
-.SH SEE ALSO
|
|
-.BR slapd.conf (5),
|
|
-.BR slapd\-config (5),
|
|
-.BR slapd\-mdb (5),
|
|
-.BR slapd (8),
|
|
-.BR slapadd (8),
|
|
-.BR slapcat (8),
|
|
-.BR slapindex (8),
|
|
-Berkeley DB documentation.
|
|
-.SH ACKNOWLEDGEMENTS
|
|
-.so ../Project
|
|
-Originally begun by Kurt Zeilenga. Caching mechanisms originally designed
|
|
-by Jong-Hyuk Choi. Completion and subsequent work, as well as
|
|
-back-hdb, by Howard Chu.
|
|
diff --git a/doc/man/man5/slapd-bdb.5.links b/doc/man/man5/slapd-bdb.5.links
|
|
deleted file mode 100644
|
|
index 3bc8c40..0000000
|
|
--- a/doc/man/man5/slapd-bdb.5.links
|
|
+++ /dev/null
|
|
@@ -1 +0,0 @@
|
|
-slapd-hdb.5
|
|
diff --git a/doc/man/man5/slapd-config.5 b/doc/man/man5/slapd-config.5
|
|
index 5753292..3061dcf 100644
|
|
--- a/doc/man/man5/slapd-config.5
|
|
+++ b/doc/man/man5/slapd-config.5
|
|
@@ -1123,10 +1123,8 @@ The entry must be named
|
|
and must have the olcBackendConfig objectClass.
|
|
<databasetype>
|
|
should be one of
|
|
-.BR bdb ,
|
|
.BR config ,
|
|
.BR dnssrv ,
|
|
-.BR hdb ,
|
|
.BR ldap ,
|
|
.BR ldif ,
|
|
.BR mdb ,
|
|
@@ -2059,10 +2057,10 @@ olcDatabase: config
|
|
olcRootPW: {SSHA}XKYnrjvGT3wZFQrDD5040US592LxsdLy
|
|
olcAccess: to * by * none
|
|
|
|
-dn: olcDatabase=bdb,cn=config
|
|
+dn: olcDatabase=mdb,cn=config
|
|
objectClass: olcDatabaseConfig
|
|
-objectClass: olcBdbConfig
|
|
-olcDatabase: bdb
|
|
+objectClass: olcMdbConfig
|
|
+olcDatabase: mdb
|
|
olcSuffix: "dc=our\-domain,dc=com"
|
|
# The database directory MUST exist prior to
|
|
# running slapd AND should only be accessible
|
|
diff --git a/doc/man/man5/slapd-mdb.5 b/doc/man/man5/slapd-mdb.5
|
|
index 62146b0..8955bbb 100644
|
|
--- a/doc/man/man5/slapd-mdb.5
|
|
+++ b/doc/man/man5/slapd-mdb.5
|
|
@@ -14,11 +14,8 @@ It relies completely on the underlying operating system for memory
|
|
management and does no caching of its own. It is the recommended
|
|
primary database backend.
|
|
.LP
|
|
-The \fBmdb\fP backend is similar to the \fBhdb\fP backend in that
|
|
-it uses a hierarchical database layout which
|
|
-supports subtree renames. It is both more space-efficient and more
|
|
-execution-efficient than the \fBbdb\fP backend, while being overall
|
|
-much simpler to manage.
|
|
+The \fBmdb\fP backend uses a hierarchical database layout which
|
|
+supports subtree renames.
|
|
.SH CONFIGURATION
|
|
These
|
|
.B slapd.conf
|
|
diff --git a/doc/man/man5/slapd-sql.5 b/doc/man/man5/slapd-sql.5
|
|
index 8492553..ccfa3a4 100644
|
|
--- a/doc/man/man5/slapd-sql.5
|
|
+++ b/doc/man/man5/slapd-sql.5
|
|
@@ -19,7 +19,7 @@ sites/applications that use RDBMSes and/or LDAP.
|
|
Or whatever else...
|
|
.LP
|
|
It is NOT designed as a general-purpose backend that uses RDBMS instead
|
|
-of BerkeleyDB (as the standard BDB backend does), though it can be
|
|
+of MDB (as the standard MDB backend does), though it can be
|
|
used as such with several limitations.
|
|
You can take a look at
|
|
.B http://www.openldap.org/faq/index.cgi?file=378
|
|
diff --git a/doc/man/man5/slapd.access.5 b/doc/man/man5/slapd.access.5
|
|
index c62158b..ebad05a 100644
|
|
--- a/doc/man/man5/slapd.access.5
|
|
+++ b/doc/man/man5/slapd.access.5
|
|
@@ -920,9 +920,8 @@ identity, control is passed straight to the subsequent rules.
|
|
|
|
.SH OPERATION REQUIREMENTS
|
|
Operations require different privileges on different portions of entries.
|
|
-The following summary applies to primary MDB database backend and the
|
|
-deprecated BDB and HDB backends. Requirements for other backends may
|
|
-(and often do) differ.
|
|
+The following summary applies to primary MDB database backend. Requirements
|
|
+for other backends may (and often do) differ.
|
|
|
|
.LP
|
|
The
|
|
@@ -1085,9 +1084,7 @@ Access control to search entries is checked by the frontend,
|
|
so it is fully honored by all backends; for all other operations
|
|
and for the discovery phase of the search operation,
|
|
full ACL semantics is only supported by the primary backends, i.e.
|
|
-.BR back\-bdb (5),
|
|
-and
|
|
-.BR back\-hdb (5).
|
|
+.BR back\-mdb (5).
|
|
|
|
Some other backend, like
|
|
.BR back\-sql (5),
|
|
diff --git a/doc/man/man5/slapd.backends.5 b/doc/man/man5/slapd.backends.5
|
|
index b9f9190..25a70e6 100644
|
|
--- a/doc/man/man5/slapd.backends.5
|
|
+++ b/doc/man/man5/slapd.backends.5
|
|
@@ -19,14 +19,6 @@ corresponding
|
|
.BR slapd\-<backend> (5)
|
|
manual pages.
|
|
.TP
|
|
-.B bdb
|
|
-This was the recommended primary backend through OpenLDAP 2.3, but it has
|
|
-since been superseded by the
|
|
-.BR mdb
|
|
-backend. It takes care to configure it properly.
|
|
-It uses the transactional database interface of the Oracle Berkeley
|
|
-DB (BDB) package to store data.
|
|
-.TP
|
|
.B config
|
|
This backend is used to manage the configuration of slapd at run-time.
|
|
Unlike other backends, only a single instance of the
|
|
@@ -41,22 +33,6 @@ This backend is experimental.
|
|
It serves up referrals based upon SRV resource records held in the
|
|
Domain Name System.
|
|
.TP
|
|
-.B hdb
|
|
-This was the recommended primary backend through OpenLDAP 2.4.40 but it has
|
|
-since been superseded by the
|
|
-.BR mdb
|
|
-backend. It takes care to configure it properly.
|
|
-.B hdb
|
|
-is a variant of the
|
|
-.B bdb
|
|
-backend that uses a hierarchical database
|
|
-layout.
|
|
-This layout stores entry DNs more efficiently than the
|
|
-.B bdb
|
|
-backend,
|
|
-using less space and requiring less work to create, delete, and rename
|
|
-entries. It is also one of the few backends to support subtree renames.
|
|
-.TP
|
|
.B ldap
|
|
This backend acts as a proxy to forward incoming requests to another
|
|
LDAP server.
|
|
@@ -68,14 +44,9 @@ Its usage should be limited to very simple databases, where performance
|
|
is not a requirement. This backend also supports subtree renames.
|
|
.TP
|
|
.B mdb
|
|
-This is the recommended primary backend, superseding
|
|
-.BR hdb .
|
|
+This is the recommended primary backend.
|
|
This backend uses OpenLDAP's own MDB transactional database
|
|
-library. It is extremely compact and extremely efficient, delivering
|
|
-much higher performance than the Berkeley DB backends while using
|
|
-significantly less memory. Also, unlike Berkeley DB, MDB is crash proof,
|
|
-and requires no special tuning or maintenance.
|
|
-This backend also supports subtree renames.
|
|
+library. This backend also supports subtree renames.
|
|
.TP
|
|
.B meta
|
|
This backend performs basic LDAP proxying with respect to a set of
|
|
@@ -138,10 +109,8 @@ ETCDIR/slapd.d
|
|
default slapd configuration directory
|
|
.SH SEE ALSO
|
|
.BR ldap (3),
|
|
-.BR slapd\-bdb (5),
|
|
.BR slapd\-config (5),
|
|
.BR slapd\-dnssrv (5),
|
|
-.BR slapd\-hdb (5),
|
|
.BR slapd\-ldap (5),
|
|
.BR slapd\-ldif (5),
|
|
.BR slapd\-mdb (5),
|
|
diff --git a/doc/man/man5/slapd.conf.5 b/doc/man/man5/slapd.conf.5
|
|
index 78b2415..0fa62ce 100644
|
|
--- a/doc/man/man5/slapd.conf.5
|
|
+++ b/doc/man/man5/slapd.conf.5
|
|
@@ -1250,10 +1250,8 @@ type of backend.
|
|
.B backend <databasetype>
|
|
Mark the beginning of a backend definition. <databasetype>
|
|
should be one of
|
|
-.BR bdb ,
|
|
.BR config ,
|
|
.BR dnssrv ,
|
|
-.BR hdb ,
|
|
.BR ldap ,
|
|
.BR ldif ,
|
|
.BR mdb ,
|
|
@@ -1280,10 +1278,8 @@ option are mandatory for each database.
|
|
.B database <databasetype>
|
|
Mark the beginning of a new database instance definition. <databasetype>
|
|
should be one of
|
|
-.BR bdb ,
|
|
.BR config ,
|
|
.BR dnssrv ,
|
|
-.BR hdb ,
|
|
.BR ldap ,
|
|
.BR ldif ,
|
|
.BR mdb ,
|
|
@@ -1593,8 +1589,7 @@ By default, mirrormode is off.
|
|
This option enables database-specific monitoring in the entry related
|
|
to the current database in the "cn=Databases,cn=Monitor" subtree
|
|
of the monitor database, if the monitor database is enabled.
|
|
-Currently, only the BDB and the HDB databases provide database-specific
|
|
-monitoring.
|
|
+Currently, only the MDB databases provide database-specific monitoring.
|
|
The default depends on the backend type.
|
|
.TP
|
|
.B overlay <overlay-name>
|
|
diff --git a/doc/man/man5/slapd.overlays.5 b/doc/man/man5/slapd.overlays.5
|
|
index 2345d81..8ca9783 100644
|
|
--- a/doc/man/man5/slapd.overlays.5
|
|
+++ b/doc/man/man5/slapd.overlays.5
|
|
@@ -91,7 +91,7 @@ password resets, etc.
|
|
.B refint
|
|
Referential Integrity.
|
|
This overlay can be used with a backend database such as
|
|
-.BR slapd\-bdb (5)
|
|
+.BR slapd\-mdb (5)
|
|
to maintain the cohesiveness of a schema which utilizes reference
|
|
attributes.
|
|
.TP
|
|
@@ -121,7 +121,7 @@ replication, including persistent search functionality.
|
|
.B translucent
|
|
Translucent Proxy.
|
|
This overlay can be used with a backend database such as
|
|
-.BR slapd\-bdb (5)
|
|
+.BR slapd\-mdb (5)
|
|
to create a "translucent proxy".
|
|
Content of entries retrieved from a remote LDAP server can be partially
|
|
overridden by the database.
|
|
@@ -129,7 +129,7 @@ overridden by the database.
|
|
.B unique
|
|
Attribute Uniqueness.
|
|
This overlay can be used with a backend database such as
|
|
-.BR slapd\-bdb (5)
|
|
+.BR slapd\-mdb (5)
|
|
to enforce the uniqueness of some or all attributes within a subtree.
|
|
.TP
|
|
.B valsort
|
|
diff --git a/doc/man/man8/slapcat.8 b/doc/man/man8/slapcat.8
|
|
index bd22637..a80ad36 100644
|
|
--- a/doc/man/man8/slapcat.8
|
|
+++ b/doc/man/man8/slapcat.8
|
|
@@ -177,8 +177,6 @@ mode) when you do this to ensure consistency of the database. It is
|
|
always safe to run
|
|
.B slapcat
|
|
with the
|
|
-.BR slapd\-bdb (5),
|
|
-.BR slapd\-hdb (5),
|
|
.BR slapd\-mdb (5),
|
|
and
|
|
.BR slapd\-null (5)
|
|
diff --git a/doc/man/man8/slapschema.8 b/doc/man/man8/slapschema.8
|
|
index 704ab0c..f4ea0cd 100644
|
|
--- a/doc/man/man8/slapschema.8
|
|
+++ b/doc/man/man8/slapschema.8
|
|
@@ -168,8 +168,7 @@ mode) when you do this to ensure consistency of the database. It is
|
|
always safe to run
|
|
.B slapschema
|
|
with the
|
|
-.BR slapd\-bdb (5),
|
|
-.BR slapd\-hdb (5),
|
|
+.BR slapd\-mdb (5),
|
|
and
|
|
.BR slapd\-null (5)
|
|
backends.
|
|
diff --git a/include/portable.hin b/include/portable.hin
|
|
index 3169f03..1b1be1a 100644
|
|
--- a/include/portable.hin
|
|
+++ b/include/portable.hin
|
|
@@ -99,12 +99,6 @@
|
|
/* Define to 1 if you have the `bcopy' function. */
|
|
#undef HAVE_BCOPY
|
|
|
|
-/* define this if Berkeley DB is available */
|
|
-#undef HAVE_BERKELEY_DB
|
|
-
|
|
-/* define if Berkeley DB has DB_THREAD support */
|
|
-#undef HAVE_BERKELEY_DB_THREAD
|
|
-
|
|
/* Define to 1 if you have the <bits/types.h> header file. */
|
|
#undef HAVE_BITS_TYPES_H
|
|
|
|
@@ -924,9 +918,6 @@
|
|
/* define to support per-object ACIs */
|
|
#undef SLAPD_ACI_ENABLED
|
|
|
|
-/* define to support BDB backend */
|
|
-#undef SLAPD_BDB
|
|
-
|
|
/* define to support cleartext passwords */
|
|
#undef SLAPD_CLEARTEXT
|
|
|
|
@@ -936,9 +927,6 @@
|
|
/* define to support DNS SRV backend */
|
|
#undef SLAPD_DNSSRV
|
|
|
|
-/* define to support HDB backend */
|
|
-#undef SLAPD_HDB
|
|
-
|
|
/* define to support LDAP backend */
|
|
#undef SLAPD_LDAP
|
|
|
|
diff --git a/servers/slapd/DB_CONFIG b/servers/slapd/DB_CONFIG
|
|
deleted file mode 100644
|
|
index d0f2c68..0000000
|
|
--- a/servers/slapd/DB_CONFIG
|
|
+++ /dev/null
|
|
@@ -1,28 +0,0 @@
|
|
-# $OpenLDAP$
|
|
-# Example DB_CONFIG file for use with slapd(8) BDB/HDB databases.
|
|
-#
|
|
-# See the Oracle Berkeley DB documentation
|
|
-# <http://www.oracle.com/technology/documentation/berkeley-db/db/ref/env/db_config.html>
|
|
-# for detail description of DB_CONFIG syntax and semantics.
|
|
-#
|
|
-# Hints can also be found in the OpenLDAP Software FAQ
|
|
-# <http://www.openldap.org/faq/index.cgi?file=2>
|
|
-# in particular:
|
|
-# <http://www.openldap.org/faq/index.cgi?file=1075>
|
|
-
|
|
-# Note: most DB_CONFIG settings will take effect only upon rebuilding
|
|
-# the DB environment.
|
|
-
|
|
-# one 0.25 GB cache
|
|
-set_cachesize 0 268435456 1
|
|
-
|
|
-# Data Directory
|
|
-#set_data_dir db
|
|
-
|
|
-# Transaction Log settings
|
|
-set_lg_regionmax 262144
|
|
-set_lg_bsize 2097152
|
|
-#set_lg_dir logs
|
|
-
|
|
-# Note: special DB_CONFIG flags are no longer needed for "quick"
|
|
-# slapadd(8) or slapindex(8) access (see their -q option).
|
|
diff --git a/servers/slapd/Makefile.in b/servers/slapd/Makefile.in
|
|
index b20564d..9a9f589 100644
|
|
--- a/servers/slapd/Makefile.in
|
|
+++ b/servers/slapd/Makefile.in
|
|
@@ -38,7 +38,7 @@ SRCS = main.c globals.c bconfig.c config.c daemon.c \
|
|
backglue.c backover.c ctxcsn.c ldapsync.c frontend.c \
|
|
slapadd.c slapcat.c slapcommon.c slapdn.c slapindex.c \
|
|
slappasswd.c slaptest.c slapauth.c slapacl.c component.c \
|
|
- aci.c alock.c txn.c slapschema.c \
|
|
+ aci.c txn.c slapschema.c \
|
|
$(@PLAT@_SRCS)
|
|
|
|
OBJS = main.o globals.o bconfig.o config.o daemon.o \
|
|
@@ -56,7 +56,7 @@ OBJS = main.o globals.o bconfig.o config.o daemon.o \
|
|
backglue.o backover.o ctxcsn.o ldapsync.o frontend.o \
|
|
slapadd.o slapcat.o slapcommon.o slapdn.o slapindex.o \
|
|
slappasswd.o slaptest.o slapauth.o slapacl.o component.o \
|
|
- aci.o alock.o txn.o slapschema.o \
|
|
+ aci.o txn.o slapschema.o \
|
|
$(@PLAT@_OBJS)
|
|
|
|
LDAP_INCDIR= ../../include -I$(srcdir) -I$(srcdir)/slapi -I.
|
|
@@ -366,14 +366,8 @@ veryclean-local-srv: FORCE
|
|
fi; \
|
|
done
|
|
|
|
-install-dbc-maybe: install-dbc-@BUILD_BDB@ install-dbc-@BUILD_HDB@
|
|
-
|
|
-install-dbc-yes: install-db-config
|
|
-install-dbc-mod: install-db-config
|
|
-install-dbc-no:
|
|
-
|
|
install-local-srv: install-slapd install-tools \
|
|
- install-conf install-dbc-maybe install-schema install-tools
|
|
+ install-conf install-schema install-tools
|
|
|
|
install-slapd: FORCE
|
|
-$(MKDIR) $(DESTDIR)$(libexecdir)
|
|
diff --git a/servers/slapd/alock.c b/servers/slapd/alock.c
|
|
deleted file mode 100644
|
|
index 4e85fad..0000000
|
|
--- a/servers/slapd/alock.c
|
|
+++ /dev/null
|
|
@@ -1,718 +0,0 @@
|
|
-/* alock.c - access lock library */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2005-2020 The OpenLDAP Foundation.
|
|
- * Portions Copyright 2004-2005 Symas Corporation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-/* ACKNOWLEDGEMENTS:
|
|
- * This work was initially developed by Emily Backes at Symas
|
|
- * Corporation for inclusion in OpenLDAP Software.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-
|
|
-#if SLAPD_BDB || SLAPD_HDB
|
|
-
|
|
-#include <lber.h>
|
|
-#include "alock.h"
|
|
-#include "lutil.h"
|
|
-
|
|
-#include <ac/stdlib.h>
|
|
-#include <ac/string.h>
|
|
-#include <ac/unistd.h>
|
|
-#include <ac/errno.h>
|
|
-#include <ac/assert.h>
|
|
-#include <sys/types.h>
|
|
-#include <sys/stat.h>
|
|
-#ifdef HAVE_SYS_FILE_H
|
|
-#include <sys/file.h>
|
|
-#endif
|
|
-#include <fcntl.h>
|
|
-
|
|
-#ifdef _WIN32
|
|
-#include <windows.h>
|
|
-#include <stdio.h>
|
|
-#include <io.h>
|
|
-#endif
|
|
-
|
|
-
|
|
-static int
|
|
-alock_grab_lock ( int fd, int slot )
|
|
-{
|
|
- int res;
|
|
-
|
|
-#if defined( HAVE_LOCKF )
|
|
- res = lseek (fd, (off_t) (ALOCK_SLOT_SIZE * slot), SEEK_SET);
|
|
- if (res == -1) return -1;
|
|
- res = lockf (fd, F_LOCK, (off_t) ALOCK_SLOT_SIZE);
|
|
-#elif defined( HAVE_FCNTL )
|
|
- struct flock lock_info;
|
|
- (void) memset ((void *) &lock_info, 0, sizeof (struct flock));
|
|
-
|
|
- lock_info.l_type = F_WRLCK;
|
|
- lock_info.l_whence = SEEK_SET;
|
|
- lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
|
|
- lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
|
|
-
|
|
- res = fcntl (fd, F_SETLKW, &lock_info);
|
|
-#elif defined( _WIN32 )
|
|
- OVERLAPPED ov;
|
|
- HANDLE hh = _get_osfhandle ( fd );
|
|
- ov.hEvent = 0;
|
|
- ov.Offset = ALOCK_SLOT_SIZE*slot;
|
|
- ov.OffsetHigh = 0;
|
|
- res = LockFileEx( hh, LOCKFILE_EXCLUSIVE_LOCK, 0,
|
|
- ALOCK_SLOT_SIZE, 0, &ov ) ? 0 : -1;
|
|
-#else
|
|
-# error alock needs lockf, fcntl, or LockFile[Ex]
|
|
-#endif
|
|
- if (res == -1) {
|
|
- assert (errno != EDEADLK);
|
|
- return -1;
|
|
- }
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int
|
|
-alock_release_lock ( int fd, int slot )
|
|
-{
|
|
- int res;
|
|
-
|
|
-#if defined( HAVE_LOCKF )
|
|
- res = lseek (fd, (off_t) (ALOCK_SLOT_SIZE * slot), SEEK_SET);
|
|
- if (res == -1) return -1;
|
|
- res = lockf (fd, F_ULOCK, (off_t) ALOCK_SLOT_SIZE);
|
|
- if (res == -1) return -1;
|
|
-#elif defined ( HAVE_FCNTL )
|
|
- struct flock lock_info;
|
|
- (void) memset ((void *) &lock_info, 0, sizeof (struct flock));
|
|
-
|
|
- lock_info.l_type = F_UNLCK;
|
|
- lock_info.l_whence = SEEK_SET;
|
|
- lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
|
|
- lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
|
|
-
|
|
- res = fcntl (fd, F_SETLKW, &lock_info);
|
|
- if (res == -1) return -1;
|
|
-#elif defined( _WIN32 )
|
|
- HANDLE hh = _get_osfhandle ( fd );
|
|
- if ( !UnlockFile ( hh, ALOCK_SLOT_SIZE*slot, 0,
|
|
- ALOCK_SLOT_SIZE, 0 ))
|
|
- return -1;
|
|
-#else
|
|
-# error alock needs lockf, fcntl, or LockFile[Ex]
|
|
-#endif
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int
|
|
-alock_share_lock ( int fd, int slot )
|
|
-{
|
|
- int res;
|
|
-
|
|
-#if defined( HAVE_LOCKF )
|
|
- res = 0; /* lockf has no shared locks */
|
|
-#elif defined ( HAVE_FCNTL )
|
|
- struct flock lock_info;
|
|
- (void) memset ((void *) &lock_info, 0, sizeof (struct flock));
|
|
-
|
|
- /* The shared lock replaces the existing lock */
|
|
- lock_info.l_type = F_RDLCK;
|
|
- lock_info.l_whence = SEEK_SET;
|
|
- lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
|
|
- lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
|
|
-
|
|
- res = fcntl (fd, F_SETLK, &lock_info);
|
|
- if (res == -1) return -1;
|
|
-#elif defined( _WIN32 )
|
|
- OVERLAPPED ov;
|
|
- HANDLE hh = _get_osfhandle ( fd );
|
|
-
|
|
- /* Windows locks are mandatory, not advisory.
|
|
- * We must downgrade the lock to allow future
|
|
- * callers to read the slot data.
|
|
- *
|
|
- * First acquire a shared lock. Unlock will
|
|
- * release the existing exclusive lock.
|
|
- */
|
|
- ov.hEvent = 0;
|
|
- ov.Offset = ALOCK_SLOT_SIZE*slot;
|
|
- ov.OffsetHigh = 0;
|
|
- LockFileEx (hh, 0, 0, ALOCK_SLOT_SIZE, 0, &ov);
|
|
- UnlockFile (hh, ALOCK_SLOT_SIZE*slot, 0, ALOCK_SLOT_SIZE, 0);
|
|
-#else
|
|
-# error alock needs lockf, fcntl, or LockFile[Ex]
|
|
-#endif
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int
|
|
-alock_test_lock ( int fd, int slot )
|
|
-{
|
|
- int res;
|
|
-
|
|
-#if defined( HAVE_LOCKF )
|
|
- res = lseek (fd, (off_t) (ALOCK_SLOT_SIZE * slot), SEEK_SET);
|
|
- if (res == -1) return -1;
|
|
-
|
|
- res = lockf (fd, F_TEST, (off_t) ALOCK_SLOT_SIZE);
|
|
- if (res == -1) {
|
|
- if (errno == EACCES || errno == EAGAIN) {
|
|
- return ALOCK_LOCKED;
|
|
- } else {
|
|
- return -1;
|
|
- }
|
|
- }
|
|
-#elif defined( HAVE_FCNTL )
|
|
- struct flock lock_info;
|
|
- (void) memset ((void *) &lock_info, 0, sizeof (struct flock));
|
|
-
|
|
- lock_info.l_type = F_WRLCK;
|
|
- lock_info.l_whence = SEEK_SET;
|
|
- lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
|
|
- lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
|
|
-
|
|
- res = fcntl (fd, F_GETLK, &lock_info);
|
|
- if (res == -1) return -1;
|
|
-
|
|
- if (lock_info.l_type != F_UNLCK) return ALOCK_LOCKED;
|
|
-#elif defined( _WIN32 )
|
|
- OVERLAPPED ov;
|
|
- HANDLE hh = _get_osfhandle ( fd );
|
|
- ov.hEvent = 0;
|
|
- ov.Offset = ALOCK_SLOT_SIZE*slot;
|
|
- ov.OffsetHigh = 0;
|
|
- if( !LockFileEx( hh,
|
|
- LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY, 0,
|
|
- ALOCK_SLOT_SIZE, 0, &ov )) {
|
|
- int err = GetLastError();
|
|
- if ( err == ERROR_LOCK_VIOLATION )
|
|
- return ALOCK_LOCKED;
|
|
- else
|
|
- return -1;
|
|
- }
|
|
-#else
|
|
-# error alock needs lockf, fcntl, or LockFile
|
|
-#endif
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/* Read a 64bit LE value */
|
|
-static unsigned long int
|
|
-alock_read_iattr ( unsigned char * bufptr )
|
|
-{
|
|
- unsigned long int val = 0;
|
|
- int count;
|
|
-
|
|
- assert (bufptr != NULL);
|
|
-
|
|
- bufptr += sizeof (unsigned long int);
|
|
- for (count=0; count <= (int) sizeof (unsigned long int); ++count) {
|
|
- val <<= 8;
|
|
- val += (unsigned long int) *bufptr--;
|
|
- }
|
|
-
|
|
- return val;
|
|
-}
|
|
-
|
|
-/* Write a 64bit LE value */
|
|
-static void
|
|
-alock_write_iattr ( unsigned char * bufptr,
|
|
- unsigned long int val )
|
|
-{
|
|
- int count;
|
|
-
|
|
- assert (bufptr != NULL);
|
|
-
|
|
- for (count=0; count < 8; ++count) {
|
|
- *bufptr++ = (unsigned char) (val & 0xff);
|
|
- val >>= 8;
|
|
- }
|
|
-}
|
|
-
|
|
-static int
|
|
-alock_read_slot ( alock_info_t * info,
|
|
- alock_slot_t * slot_data )
|
|
-{
|
|
- unsigned char slotbuf [ALOCK_SLOT_SIZE];
|
|
- int res, size, size_total, err;
|
|
-
|
|
- assert (info != NULL);
|
|
- assert (slot_data != NULL);
|
|
- assert (info->al_slot > 0);
|
|
-
|
|
- res = lseek (info->al_fd,
|
|
- (off_t) (ALOCK_SLOT_SIZE * info->al_slot),
|
|
- SEEK_SET);
|
|
- if (res == -1) return -1;
|
|
-
|
|
- size_total = 0;
|
|
- while (size_total < ALOCK_SLOT_SIZE) {
|
|
- size = read (info->al_fd,
|
|
- slotbuf + size_total,
|
|
- ALOCK_SLOT_SIZE - size_total);
|
|
- if (size == 0) return -1;
|
|
- if (size < 0) {
|
|
- err = errno;
|
|
- if (err != EINTR && err != EAGAIN) return -1;
|
|
- } else {
|
|
- size_total += size;
|
|
- }
|
|
- }
|
|
-
|
|
- if (alock_read_iattr (slotbuf) != ALOCK_MAGIC) {
|
|
- return -1;
|
|
- }
|
|
- slot_data->al_lock = alock_read_iattr (slotbuf+8);
|
|
- slot_data->al_stamp = alock_read_iattr (slotbuf+16);
|
|
- slot_data->al_pid = alock_read_iattr (slotbuf+24);
|
|
-
|
|
- if (slot_data->al_appname) ber_memfree (slot_data->al_appname);
|
|
- slot_data->al_appname = ber_memcalloc (1, ALOCK_MAX_APPNAME);
|
|
- if (slot_data->al_appname == NULL) {
|
|
- return -1;
|
|
- }
|
|
- strncpy (slot_data->al_appname, (char *)slotbuf+32, ALOCK_MAX_APPNAME-1);
|
|
- (slot_data->al_appname) [ALOCK_MAX_APPNAME-1] = '\0';
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int
|
|
-alock_write_slot ( alock_info_t * info,
|
|
- alock_slot_t * slot_data )
|
|
-{
|
|
- unsigned char slotbuf [ALOCK_SLOT_SIZE];
|
|
- int res, size, size_total, err;
|
|
-
|
|
- assert (info != NULL);
|
|
- assert (slot_data != NULL);
|
|
- assert (info->al_slot > 0);
|
|
-
|
|
- (void) memset ((void *) slotbuf, 0, ALOCK_SLOT_SIZE);
|
|
-
|
|
- alock_write_iattr (slotbuf, ALOCK_MAGIC);
|
|
- assert (alock_read_iattr (slotbuf) == ALOCK_MAGIC);
|
|
- alock_write_iattr (slotbuf+8, slot_data->al_lock);
|
|
- alock_write_iattr (slotbuf+16, slot_data->al_stamp);
|
|
- alock_write_iattr (slotbuf+24, slot_data->al_pid);
|
|
-
|
|
- if (slot_data->al_appname)
|
|
- strncpy ((char *)slotbuf+32, slot_data->al_appname, ALOCK_MAX_APPNAME-1);
|
|
- slotbuf[ALOCK_SLOT_SIZE-1] = '\0';
|
|
-
|
|
- res = lseek (info->al_fd,
|
|
- (off_t) (ALOCK_SLOT_SIZE * info->al_slot),
|
|
- SEEK_SET);
|
|
- if (res == -1) return -1;
|
|
-
|
|
- size_total = 0;
|
|
- while (size_total < ALOCK_SLOT_SIZE) {
|
|
- size = write (info->al_fd,
|
|
- slotbuf + size_total,
|
|
- ALOCK_SLOT_SIZE - size_total);
|
|
- if (size == 0) return -1;
|
|
- if (size < 0) {
|
|
- err = errno;
|
|
- if (err != EINTR && err != EAGAIN) return -1;
|
|
- } else {
|
|
- size_total += size;
|
|
- }
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int
|
|
-alock_query_slot ( alock_info_t * info )
|
|
-{
|
|
- int res, nosave;
|
|
- alock_slot_t slot_data;
|
|
-
|
|
- assert (info != NULL);
|
|
- assert (info->al_slot > 0);
|
|
-
|
|
- (void) memset ((void *) &slot_data, 0, sizeof (alock_slot_t));
|
|
- alock_read_slot (info, &slot_data);
|
|
-
|
|
- if (slot_data.al_appname != NULL) ber_memfree (slot_data.al_appname);
|
|
- slot_data.al_appname = NULL;
|
|
-
|
|
- nosave = slot_data.al_lock & ALOCK_NOSAVE;
|
|
-
|
|
- if ((slot_data.al_lock & ALOCK_SMASK) == ALOCK_UNLOCKED)
|
|
- return slot_data.al_lock;
|
|
-
|
|
- res = alock_test_lock (info->al_fd, info->al_slot);
|
|
- if (res < 0) return -1;
|
|
- if (res > 0) {
|
|
- if ((slot_data.al_lock & ALOCK_SMASK) == ALOCK_UNIQUE) {
|
|
- return slot_data.al_lock;
|
|
- } else {
|
|
- return ALOCK_LOCKED | nosave;
|
|
- }
|
|
- }
|
|
-
|
|
- return ALOCK_DIRTY | nosave;
|
|
-}
|
|
-
|
|
-int
|
|
-alock_open ( alock_info_t * info,
|
|
- const char * appname,
|
|
- const char * envdir,
|
|
- int locktype )
|
|
-{
|
|
- struct stat statbuf;
|
|
- alock_info_t scan_info;
|
|
- alock_slot_t slot_data;
|
|
- char * filename;
|
|
- int res, max_slot;
|
|
- int dirty_count, live_count, nosave;
|
|
- char *ptr;
|
|
-
|
|
- assert (info != NULL);
|
|
- assert (appname != NULL);
|
|
- assert (envdir != NULL);
|
|
- assert ((locktype & ALOCK_SMASK) >= 1 && (locktype & ALOCK_SMASK) <= 2);
|
|
-
|
|
- slot_data.al_lock = locktype;
|
|
- slot_data.al_stamp = time(NULL);
|
|
- slot_data.al_pid = getpid();
|
|
- slot_data.al_appname = ber_memcalloc (1, ALOCK_MAX_APPNAME);
|
|
- if (slot_data.al_appname == NULL) {
|
|
- return ALOCK_UNSTABLE;
|
|
- }
|
|
- strncpy (slot_data.al_appname, appname, ALOCK_MAX_APPNAME-1);
|
|
- slot_data.al_appname [ALOCK_MAX_APPNAME-1] = '\0';
|
|
-
|
|
- filename = ber_memcalloc (1, strlen (envdir) + strlen ("/alock") + 1);
|
|
- if (filename == NULL ) {
|
|
- ber_memfree (slot_data.al_appname);
|
|
- return ALOCK_UNSTABLE;
|
|
- }
|
|
- ptr = lutil_strcopy(filename, envdir);
|
|
- lutil_strcopy(ptr, "/alock");
|
|
-#ifdef _WIN32
|
|
- { HANDLE handle = CreateFile (filename, GENERIC_READ|GENERIC_WRITE,
|
|
- FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,
|
|
- FILE_ATTRIBUTE_NORMAL, NULL);
|
|
- info->al_fd = _open_osfhandle (handle, 0);
|
|
- }
|
|
-#else
|
|
- info->al_fd = open (filename, O_CREAT|O_RDWR, 0666);
|
|
-#endif
|
|
- ber_memfree (filename);
|
|
- if (info->al_fd < 0) {
|
|
- ber_memfree (slot_data.al_appname);
|
|
- return ALOCK_UNSTABLE;
|
|
- }
|
|
- info->al_slot = 0;
|
|
-
|
|
- res = alock_grab_lock (info->al_fd, 0);
|
|
- if (res == -1) {
|
|
- close (info->al_fd);
|
|
- ber_memfree (slot_data.al_appname);
|
|
- return ALOCK_UNSTABLE;
|
|
- }
|
|
-
|
|
- res = fstat (info->al_fd, &statbuf);
|
|
- if (res == -1) {
|
|
- close (info->al_fd);
|
|
- ber_memfree (slot_data.al_appname);
|
|
- return ALOCK_UNSTABLE;
|
|
- }
|
|
-
|
|
- max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE;
|
|
- dirty_count = 0;
|
|
- live_count = 0;
|
|
- nosave = 0;
|
|
- scan_info.al_fd = info->al_fd;
|
|
- for (scan_info.al_slot = 1;
|
|
- scan_info.al_slot < max_slot;
|
|
- ++ scan_info.al_slot) {
|
|
- if (scan_info.al_slot != info->al_slot) {
|
|
- res = alock_query_slot (&scan_info);
|
|
-
|
|
- if (res & ALOCK_NOSAVE) {
|
|
- nosave = ALOCK_NOSAVE;
|
|
- res ^= ALOCK_NOSAVE;
|
|
- }
|
|
- if (res == ALOCK_UNLOCKED
|
|
- && info->al_slot == 0) {
|
|
- info->al_slot = scan_info.al_slot;
|
|
-
|
|
- } else if (res == ALOCK_LOCKED) {
|
|
- ++live_count;
|
|
-
|
|
- } else if (res == ALOCK_UNIQUE
|
|
- && (( locktype & ALOCK_SMASK ) == ALOCK_UNIQUE
|
|
- || nosave )) {
|
|
- close (info->al_fd);
|
|
- ber_memfree (slot_data.al_appname);
|
|
- return ALOCK_BUSY;
|
|
-
|
|
- } else if (res == ALOCK_DIRTY) {
|
|
- ++dirty_count;
|
|
-
|
|
- } else if (res == -1) {
|
|
- close (info->al_fd);
|
|
- ber_memfree (slot_data.al_appname);
|
|
- return ALOCK_UNSTABLE;
|
|
-
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- if (dirty_count && live_count) {
|
|
- close (info->al_fd);
|
|
- ber_memfree (slot_data.al_appname);
|
|
- return ALOCK_UNSTABLE;
|
|
- }
|
|
-
|
|
- if (info->al_slot == 0) info->al_slot = max_slot + 1;
|
|
- res = alock_grab_lock (info->al_fd,
|
|
- info->al_slot);
|
|
- if (res == -1) {
|
|
- close (info->al_fd);
|
|
- ber_memfree (slot_data.al_appname);
|
|
- return ALOCK_UNSTABLE;
|
|
- }
|
|
- res = alock_write_slot (info, &slot_data);
|
|
- ber_memfree (slot_data.al_appname);
|
|
- if (res == -1) {
|
|
- close (info->al_fd);
|
|
- return ALOCK_UNSTABLE;
|
|
- }
|
|
- alock_share_lock (info->al_fd, info->al_slot);
|
|
-
|
|
- res = alock_release_lock (info->al_fd, 0);
|
|
- if (res == -1) {
|
|
- close (info->al_fd);
|
|
- return ALOCK_UNSTABLE;
|
|
- }
|
|
-
|
|
- if (dirty_count) return ALOCK_RECOVER | nosave;
|
|
- return ALOCK_CLEAN | nosave;
|
|
-}
|
|
-
|
|
-int
|
|
-alock_scan ( alock_info_t * info )
|
|
-{
|
|
- struct stat statbuf;
|
|
- alock_info_t scan_info;
|
|
- int res, max_slot;
|
|
- int dirty_count, live_count, nosave;
|
|
-
|
|
- assert (info != NULL);
|
|
-
|
|
- scan_info.al_fd = info->al_fd;
|
|
-
|
|
- res = alock_grab_lock (info->al_fd, 0);
|
|
- if (res == -1) {
|
|
- close (info->al_fd);
|
|
- return ALOCK_UNSTABLE;
|
|
- }
|
|
-
|
|
- res = fstat (info->al_fd, &statbuf);
|
|
- if (res == -1) {
|
|
- close (info->al_fd);
|
|
- return ALOCK_UNSTABLE;
|
|
- }
|
|
-
|
|
- max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE;
|
|
- dirty_count = 0;
|
|
- live_count = 0;
|
|
- nosave = 0;
|
|
- for (scan_info.al_slot = 1;
|
|
- scan_info.al_slot < max_slot;
|
|
- ++ scan_info.al_slot) {
|
|
- if (scan_info.al_slot != info->al_slot) {
|
|
- res = alock_query_slot (&scan_info);
|
|
-
|
|
- if (res & ALOCK_NOSAVE) {
|
|
- nosave = ALOCK_NOSAVE;
|
|
- res ^= ALOCK_NOSAVE;
|
|
- }
|
|
-
|
|
- if (res == ALOCK_LOCKED) {
|
|
- ++live_count;
|
|
-
|
|
- } else if (res == ALOCK_DIRTY) {
|
|
- ++dirty_count;
|
|
-
|
|
- } else if (res == -1) {
|
|
- close (info->al_fd);
|
|
- return ALOCK_UNSTABLE;
|
|
-
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- res = alock_release_lock (info->al_fd, 0);
|
|
- if (res == -1) {
|
|
- close (info->al_fd);
|
|
- return ALOCK_UNSTABLE;
|
|
- }
|
|
-
|
|
- if (dirty_count) {
|
|
- if (live_count) {
|
|
- close (info->al_fd);
|
|
- return ALOCK_UNSTABLE;
|
|
- } else {
|
|
- return ALOCK_RECOVER | nosave;
|
|
- }
|
|
- }
|
|
-
|
|
- return ALOCK_CLEAN | nosave;
|
|
-}
|
|
-
|
|
-int
|
|
-alock_close ( alock_info_t * info, int nosave )
|
|
-{
|
|
- alock_slot_t slot_data;
|
|
- int res;
|
|
-
|
|
- if ( !info->al_slot )
|
|
- return ALOCK_CLEAN;
|
|
-
|
|
- (void) memset ((void *) &slot_data, 0, sizeof(alock_slot_t));
|
|
-
|
|
- res = alock_grab_lock (info->al_fd, 0);
|
|
- if (res == -1) {
|
|
-fail:
|
|
- /* Windows doesn't clean up locks immediately when a process exits.
|
|
- * Make sure we release our locks, to prevent stale locks from
|
|
- * hanging around.
|
|
- */
|
|
- alock_release_lock (info->al_fd, 0);
|
|
- close (info->al_fd);
|
|
- return ALOCK_UNSTABLE;
|
|
- }
|
|
-
|
|
- /* mark our slot as clean */
|
|
- res = alock_read_slot (info, &slot_data);
|
|
- if (res == -1) {
|
|
- if (slot_data.al_appname != NULL)
|
|
- ber_memfree (slot_data.al_appname);
|
|
- goto fail;
|
|
- }
|
|
- slot_data.al_lock = ALOCK_UNLOCKED;
|
|
- if ( nosave )
|
|
- slot_data.al_lock |= ALOCK_NOSAVE;
|
|
- /* since we have slot 0 locked, we don't need our slot lock */
|
|
- res = alock_release_lock (info->al_fd, info->al_slot);
|
|
- if (res == -1) {
|
|
- goto fail;
|
|
- }
|
|
- res = alock_write_slot (info, &slot_data);
|
|
- if (res == -1) {
|
|
- if (slot_data.al_appname != NULL)
|
|
- ber_memfree (slot_data.al_appname);
|
|
- goto fail;
|
|
- }
|
|
- if (slot_data.al_appname != NULL) {
|
|
- ber_memfree (slot_data.al_appname);
|
|
- slot_data.al_appname = NULL;
|
|
- }
|
|
-
|
|
- res = alock_release_lock (info->al_fd, 0);
|
|
- if (res == -1) {
|
|
- close (info->al_fd);
|
|
- return ALOCK_UNSTABLE;
|
|
- }
|
|
-
|
|
- res = close (info->al_fd);
|
|
- if (res == -1) return ALOCK_UNSTABLE;
|
|
-
|
|
- return ALOCK_CLEAN;
|
|
-}
|
|
-
|
|
-int
|
|
-alock_recover ( alock_info_t * info )
|
|
-{
|
|
- struct stat statbuf;
|
|
- alock_slot_t slot_data;
|
|
- alock_info_t scan_info;
|
|
- int res, max_slot;
|
|
-
|
|
- assert (info != NULL);
|
|
-
|
|
- scan_info.al_fd = info->al_fd;
|
|
-
|
|
- (void) memset ((void *) &slot_data, 0, sizeof(alock_slot_t));
|
|
-
|
|
- res = alock_grab_lock (info->al_fd, 0);
|
|
- if (res == -1) {
|
|
- goto fail;
|
|
- }
|
|
-
|
|
- res = fstat (info->al_fd, &statbuf);
|
|
- if (res == -1) {
|
|
- goto fail;
|
|
- }
|
|
-
|
|
- max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE;
|
|
- for (scan_info.al_slot = 1;
|
|
- scan_info.al_slot < max_slot;
|
|
- ++ scan_info.al_slot) {
|
|
- if (scan_info.al_slot != info->al_slot) {
|
|
- res = alock_query_slot (&scan_info) & ~ALOCK_NOSAVE;
|
|
-
|
|
- if (res == ALOCK_LOCKED
|
|
- || res == ALOCK_UNIQUE) {
|
|
- /* recovery attempt on an active db? */
|
|
- goto fail;
|
|
-
|
|
- } else if (res == ALOCK_DIRTY) {
|
|
- /* mark it clean */
|
|
- res = alock_read_slot (&scan_info, &slot_data);
|
|
- if (res == -1) {
|
|
- goto fail;
|
|
- }
|
|
- slot_data.al_lock = ALOCK_UNLOCKED;
|
|
- res = alock_write_slot (&scan_info, &slot_data);
|
|
- if (res == -1) {
|
|
- if (slot_data.al_appname != NULL)
|
|
- ber_memfree (slot_data.al_appname);
|
|
- goto fail;
|
|
- }
|
|
- if (slot_data.al_appname != NULL) {
|
|
- ber_memfree (slot_data.al_appname);
|
|
- slot_data.al_appname = NULL;
|
|
- }
|
|
-
|
|
- } else if (res == -1) {
|
|
- goto fail;
|
|
-
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- res = alock_release_lock (info->al_fd, 0);
|
|
- if (res == -1) {
|
|
- close (info->al_fd);
|
|
- return ALOCK_UNSTABLE;
|
|
- }
|
|
-
|
|
- return ALOCK_CLEAN;
|
|
-
|
|
-fail:
|
|
- alock_release_lock (info->al_fd, 0);
|
|
- close (info->al_fd);
|
|
- return ALOCK_UNSTABLE;
|
|
-}
|
|
-
|
|
-#endif /* SLAPD_BDB || SLAPD_HDB */
|
|
diff --git a/servers/slapd/alock.h b/servers/slapd/alock.h
|
|
deleted file mode 100644
|
|
index 56f03d8..0000000
|
|
--- a/servers/slapd/alock.h
|
|
+++ /dev/null
|
|
@@ -1,74 +0,0 @@
|
|
-/* alock.h - access lock header */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2005-2020 The OpenLDAP Foundation.
|
|
- * Portions Copyright 2004-2005 Symas Corporation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-/* ACKNOWLEDGEMENTS:
|
|
- * This work was initially developed by Emily Backes at Symas
|
|
- * Corporation for inclusion in OpenLDAP Software.
|
|
- */
|
|
-
|
|
-#ifndef _ALOCK_H_
|
|
-#define _ALOCK_H_
|
|
-
|
|
-#include "portable.h"
|
|
-#include <ac/time.h>
|
|
-#include <ac/unistd.h>
|
|
-
|
|
-/* environment states (all the slots together) */
|
|
-#define ALOCK_CLEAN (0)
|
|
-#define ALOCK_RECOVER (1)
|
|
-#define ALOCK_BUSY (2)
|
|
-#define ALOCK_UNSTABLE (3)
|
|
-
|
|
-/* lock user types and states */
|
|
-#define ALOCK_UNLOCKED (0)
|
|
-#define ALOCK_LOCKED (1)
|
|
-#define ALOCK_UNIQUE (2)
|
|
-#define ALOCK_DIRTY (3)
|
|
-
|
|
-#define ALOCK_SMASK 3
|
|
-
|
|
-/* lock/state where recovery is not available */
|
|
-#define ALOCK_NOSAVE 4
|
|
-
|
|
-/* constants */
|
|
-#define ALOCK_SLOT_SIZE (1024)
|
|
-#define ALOCK_SLOT_IATTRS (4)
|
|
-#define ALOCK_MAX_APPNAME (ALOCK_SLOT_SIZE - 8 * ALOCK_SLOT_IATTRS)
|
|
-#define ALOCK_MAGIC (0x12345678)
|
|
-
|
|
-LDAP_BEGIN_DECL
|
|
-
|
|
-typedef struct alock_info {
|
|
- int al_fd;
|
|
- int al_slot;
|
|
-} alock_info_t;
|
|
-
|
|
-typedef struct alock_slot {
|
|
- unsigned int al_lock;
|
|
- time_t al_stamp;
|
|
- pid_t al_pid;
|
|
- char * al_appname;
|
|
-} alock_slot_t;
|
|
-
|
|
-LDAP_SLAPD_F (int) alock_open LDAP_P(( alock_info_t * info, const char * appname,
|
|
- const char * envdir, int locktype ));
|
|
-LDAP_SLAPD_F (int) alock_scan LDAP_P(( alock_info_t * info ));
|
|
-LDAP_SLAPD_F (int) alock_close LDAP_P(( alock_info_t * info, int nosave ));
|
|
-LDAP_SLAPD_F (int) alock_recover LDAP_P(( alock_info_t * info ));
|
|
-
|
|
-LDAP_END_DECL
|
|
-
|
|
-#endif
|
|
diff --git a/servers/slapd/back-bdb/Makefile.in b/servers/slapd/back-bdb/Makefile.in
|
|
deleted file mode 100644
|
|
index 8529202..0000000
|
|
--- a/servers/slapd/back-bdb/Makefile.in
|
|
+++ /dev/null
|
|
@@ -1,53 +0,0 @@
|
|
-# Makefile.in for back-bdb
|
|
-# $OpenLDAP$
|
|
-## This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
-##
|
|
-## Copyright 1998-2020 The OpenLDAP Foundation.
|
|
-## All rights reserved.
|
|
-##
|
|
-## Redistribution and use in source and binary forms, with or without
|
|
-## modification, are permitted only as authorized by the OpenLDAP
|
|
-## Public License.
|
|
-##
|
|
-## A copy of this license is available in the file LICENSE in the
|
|
-## top-level directory of the distribution or, alternatively, at
|
|
-## <http://www.OpenLDAP.org/license.html>.
|
|
-
|
|
-SRCS = init.c tools.c config.c \
|
|
- add.c bind.c compare.c delete.c modify.c modrdn.c search.c \
|
|
- extended.c referral.c operational.c \
|
|
- attr.c index.c key.c dbcache.c filterindex.c \
|
|
- dn2entry.c dn2id.c error.c id2entry.c idl.c \
|
|
- nextid.c cache.c trans.c monitor.c
|
|
-
|
|
-OBJS = init.lo tools.lo config.lo \
|
|
- add.lo bind.lo compare.lo delete.lo modify.lo modrdn.lo search.lo \
|
|
- extended.lo referral.lo operational.lo \
|
|
- attr.lo index.lo key.lo dbcache.lo filterindex.lo \
|
|
- dn2entry.lo dn2id.lo error.lo id2entry.lo idl.lo \
|
|
- nextid.lo cache.lo trans.lo monitor.lo
|
|
-
|
|
-LDAP_INCDIR= ../../../include
|
|
-LDAP_LIBDIR= ../../../libraries
|
|
-
|
|
-BUILD_OPT = "--enable-bdb"
|
|
-BUILD_MOD = @BUILD_BDB@
|
|
-
|
|
-mod_DEFS = -DSLAPD_IMPORT
|
|
-MOD_DEFS = $(@BUILD_BDB@_DEFS)
|
|
-MOD_LIBS = $(BDB_LIBS)
|
|
-
|
|
-shared_LDAP_LIBS = $(LDAP_LIBLDAP_R_LA) $(LDAP_LIBLBER_LA)
|
|
-NT_LINK_LIBS = -L.. -lslapd $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
|
|
-UNIX_LINK_LIBS = $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
|
|
-
|
|
-LIBBASE = back_bdb
|
|
-
|
|
-XINCPATH = -I.. -I$(srcdir)/..
|
|
-XDEFS = $(MODULES_CPPFLAGS)
|
|
-
|
|
-all-local-lib: ../.backend
|
|
-
|
|
-../.backend: lib$(LIBBASE).a
|
|
- @touch $@
|
|
-
|
|
diff --git a/servers/slapd/back-bdb/add.c b/servers/slapd/back-bdb/add.c
|
|
deleted file mode 100644
|
|
index d842b55..0000000
|
|
--- a/servers/slapd/back-bdb/add.c
|
|
+++ /dev/null
|
|
@@ -1,547 +0,0 @@
|
|
-/* add.c - ldap BerkeleyDB back-end add routine */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-
|
|
-#include <stdio.h>
|
|
-#include <ac/string.h>
|
|
-
|
|
-#include "back-bdb.h"
|
|
-
|
|
-int
|
|
-bdb_add(Operation *op, SlapReply *rs )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- struct berval pdn;
|
|
- Entry *p = NULL, *oe = op->ora_e;
|
|
- EntryInfo *ei;
|
|
- char textbuf[SLAP_TEXT_BUFLEN];
|
|
- size_t textlen = sizeof textbuf;
|
|
- AttributeDescription *children = slap_schema.si_ad_children;
|
|
- AttributeDescription *entry = slap_schema.si_ad_entry;
|
|
- DB_TXN *ltid = NULL, *lt2;
|
|
- ID eid = NOID;
|
|
- struct bdb_op_info opinfo = {{{ 0 }}};
|
|
- int subentry;
|
|
- DB_LOCK lock;
|
|
-
|
|
- int num_retries = 0;
|
|
- int success;
|
|
-
|
|
- LDAPControl **postread_ctrl = NULL;
|
|
- LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
|
|
- int num_ctrls = 0;
|
|
-
|
|
-#ifdef LDAP_X_TXN
|
|
- int settle = 0;
|
|
-#endif
|
|
-
|
|
- Debug(LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(bdb_add) ": %s\n",
|
|
- op->ora_e->e_name.bv_val, 0, 0);
|
|
-
|
|
-#ifdef LDAP_X_TXN
|
|
- if( op->o_txnSpec ) {
|
|
- /* acquire connection lock */
|
|
- ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
|
|
- if( op->o_conn->c_txn == CONN_TXN_INACTIVE ) {
|
|
- rs->sr_text = "invalid transaction identifier";
|
|
- rs->sr_err = LDAP_X_TXN_ID_INVALID;
|
|
- goto txnReturn;
|
|
- } else if( op->o_conn->c_txn == CONN_TXN_SETTLE ) {
|
|
- settle=1;
|
|
- goto txnReturn;
|
|
- }
|
|
-
|
|
- if( op->o_conn->c_txn_backend == NULL ) {
|
|
- op->o_conn->c_txn_backend = op->o_bd;
|
|
-
|
|
- } else if( op->o_conn->c_txn_backend != op->o_bd ) {
|
|
- rs->sr_text = "transaction cannot span multiple database contexts";
|
|
- rs->sr_err = LDAP_AFFECTS_MULTIPLE_DSAS;
|
|
- goto txnReturn;
|
|
- }
|
|
-
|
|
- /* insert operation into transaction */
|
|
-
|
|
- rs->sr_text = "transaction specified";
|
|
- rs->sr_err = LDAP_X_TXN_SPECIFY_OKAY;
|
|
-
|
|
-txnReturn:
|
|
- /* release connection lock */
|
|
- ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
|
|
-
|
|
- if( !settle ) {
|
|
- send_ldap_result( op, rs );
|
|
- return rs->sr_err;
|
|
- }
|
|
- }
|
|
-#endif
|
|
-
|
|
- ctrls[num_ctrls] = 0;
|
|
-
|
|
- /* check entry's schema */
|
|
- rs->sr_err = entry_schema_check( op, op->ora_e, NULL,
|
|
- get_relax(op), 1, NULL, &rs->sr_text, textbuf, textlen );
|
|
- if ( rs->sr_err != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_add) ": entry failed schema check: "
|
|
- "%s (%d)\n", rs->sr_text, rs->sr_err, 0 );
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- /* add opattrs to shadow as well, only missing attrs will actually
|
|
- * be added; helps compatibility with older OL versions */
|
|
- rs->sr_err = slap_add_opattrs( op, &rs->sr_text, textbuf, textlen, 1 );
|
|
- if ( rs->sr_err != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_add) ": entry failed op attrs add: "
|
|
- "%s (%d)\n", rs->sr_text, rs->sr_err, 0 );
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- if ( get_assert( op ) &&
|
|
- ( test_filter( op, op->ora_e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
|
|
- {
|
|
- rs->sr_err = LDAP_ASSERTION_FAILED;
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- subentry = is_entry_subentry( op->ora_e );
|
|
-
|
|
- if( 0 ) {
|
|
-retry: /* transaction retry */
|
|
- if( p ) {
|
|
- /* free parent and reader lock */
|
|
- if ( p != (Entry *)&slap_entry_root ) {
|
|
- bdb_unlocked_cache_return_entry_r( bdb, p );
|
|
- }
|
|
- p = NULL;
|
|
- }
|
|
- rs->sr_err = TXN_ABORT( ltid );
|
|
- ltid = NULL;
|
|
- LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
|
|
- opinfo.boi_oe.oe_key = NULL;
|
|
- op->o_do_not_cache = opinfo.boi_acl_cache;
|
|
- if( rs->sr_err != 0 ) {
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "internal error";
|
|
- goto return_results;
|
|
- }
|
|
- if ( op->o_abandon ) {
|
|
- rs->sr_err = SLAPD_ABANDON;
|
|
- goto return_results;
|
|
- }
|
|
- bdb_trans_backoff( ++num_retries );
|
|
- }
|
|
-
|
|
- /* begin transaction */
|
|
- rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, NULL, <id,
|
|
- bdb->bi_db_opflags );
|
|
- rs->sr_text = NULL;
|
|
- if( rs->sr_err != 0 ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_add) ": txn_begin failed: %s (%d)\n",
|
|
- db_strerror(rs->sr_err), rs->sr_err, 0 );
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "internal error";
|
|
- goto return_results;
|
|
- }
|
|
- Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_add) ": txn1 id: %x\n",
|
|
- ltid->id(ltid), 0, 0 );
|
|
-
|
|
- opinfo.boi_oe.oe_key = bdb;
|
|
- opinfo.boi_txn = ltid;
|
|
- opinfo.boi_err = 0;
|
|
- opinfo.boi_acl_cache = op->o_do_not_cache;
|
|
- LDAP_SLIST_INSERT_HEAD( &op->o_extra, &opinfo.boi_oe, oe_next );
|
|
-
|
|
- /*
|
|
- * Get the parent dn and see if the corresponding entry exists.
|
|
- */
|
|
- if ( be_issuffix( op->o_bd, &op->ora_e->e_nname ) ) {
|
|
- pdn = slap_empty_bv;
|
|
- } else {
|
|
- dnParent( &op->ora_e->e_nname, &pdn );
|
|
- }
|
|
-
|
|
- /* get entry or parent */
|
|
- rs->sr_err = bdb_dn2entry( op, ltid, &op->ora_e->e_nname, &ei,
|
|
- 1, &lock );
|
|
- switch( rs->sr_err ) {
|
|
- case 0:
|
|
- rs->sr_err = LDAP_ALREADY_EXISTS;
|
|
- goto return_results;
|
|
- case DB_NOTFOUND:
|
|
- break;
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- case LDAP_BUSY:
|
|
- rs->sr_text = "ldap server busy";
|
|
- goto return_results;
|
|
- default:
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "internal error";
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- p = ei->bei_e;
|
|
- if ( !p )
|
|
- p = (Entry *)&slap_entry_root;
|
|
-
|
|
- if ( !bvmatch( &pdn, &p->e_nname ) ) {
|
|
- rs->sr_matched = ber_strdup_x( p->e_name.bv_val,
|
|
- op->o_tmpmemctx );
|
|
- rs->sr_ref = is_entry_referral( p )
|
|
- ? get_entry_referrals( op, p )
|
|
- : NULL;
|
|
- if ( p != (Entry *)&slap_entry_root )
|
|
- bdb_unlocked_cache_return_entry_r( bdb, p );
|
|
- p = NULL;
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_add) ": parent "
|
|
- "does not exist\n", 0, 0, 0 );
|
|
-
|
|
- rs->sr_err = LDAP_REFERRAL;
|
|
- rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- rs->sr_err = access_allowed( op, p,
|
|
- children, NULL, ACL_WADD, NULL );
|
|
-
|
|
- if ( ! rs->sr_err ) {
|
|
- switch( opinfo.boi_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- }
|
|
-
|
|
- if ( p != (Entry *)&slap_entry_root )
|
|
- bdb_unlocked_cache_return_entry_r( bdb, p );
|
|
- p = NULL;
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_add) ": no write access to parent\n",
|
|
- 0, 0, 0 );
|
|
- rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
|
- rs->sr_text = "no write access to parent";
|
|
- goto return_results;;
|
|
- }
|
|
-
|
|
- if ( p != (Entry *)&slap_entry_root ) {
|
|
- if ( is_entry_subentry( p ) ) {
|
|
- bdb_unlocked_cache_return_entry_r( bdb, p );
|
|
- p = NULL;
|
|
- /* parent is a subentry, don't allow add */
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_add) ": parent is subentry\n",
|
|
- 0, 0, 0 );
|
|
- rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION;
|
|
- rs->sr_text = "parent is a subentry";
|
|
- goto return_results;;
|
|
- }
|
|
-
|
|
- if ( is_entry_alias( p ) ) {
|
|
- bdb_unlocked_cache_return_entry_r( bdb, p );
|
|
- p = NULL;
|
|
- /* parent is an alias, don't allow add */
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_add) ": parent is alias\n",
|
|
- 0, 0, 0 );
|
|
- rs->sr_err = LDAP_ALIAS_PROBLEM;
|
|
- rs->sr_text = "parent is an alias";
|
|
- goto return_results;;
|
|
- }
|
|
-
|
|
- if ( is_entry_referral( p ) ) {
|
|
- /* parent is a referral, don't allow add */
|
|
- rs->sr_matched = ber_strdup_x( p->e_name.bv_val,
|
|
- op->o_tmpmemctx );
|
|
- rs->sr_ref = get_entry_referrals( op, p );
|
|
- bdb_unlocked_cache_return_entry_r( bdb, p );
|
|
- p = NULL;
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_add) ": parent is referral\n",
|
|
- 0, 0, 0 );
|
|
-
|
|
- rs->sr_err = LDAP_REFERRAL;
|
|
- rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- }
|
|
-
|
|
- if ( subentry ) {
|
|
- /* FIXME: */
|
|
- /* parent must be an administrative point of the required kind */
|
|
- }
|
|
-
|
|
- /* free parent and reader lock */
|
|
- if ( p != (Entry *)&slap_entry_root ) {
|
|
- if ( p->e_nname.bv_len ) {
|
|
- struct berval ppdn;
|
|
-
|
|
- /* ITS#5326: use parent's DN if differs from provided one */
|
|
- dnParent( &op->ora_e->e_name, &ppdn );
|
|
- if ( !dn_match( &p->e_name, &ppdn ) ) {
|
|
- struct berval rdn;
|
|
- struct berval newdn;
|
|
-
|
|
- dnRdn( &op->ora_e->e_name, &rdn );
|
|
-
|
|
- build_new_dn( &newdn, &p->e_name, &rdn, NULL );
|
|
- if ( op->ora_e->e_name.bv_val != op->o_req_dn.bv_val )
|
|
- ber_memfree( op->ora_e->e_name.bv_val );
|
|
- op->ora_e->e_name = newdn;
|
|
-
|
|
- /* FIXME: should check whether
|
|
- * dnNormalize(newdn) == e->e_nname ... */
|
|
- }
|
|
- }
|
|
-
|
|
- bdb_unlocked_cache_return_entry_r( bdb, p );
|
|
- }
|
|
- p = NULL;
|
|
-
|
|
- rs->sr_err = access_allowed( op, op->ora_e,
|
|
- entry, NULL, ACL_WADD, NULL );
|
|
-
|
|
- if ( ! rs->sr_err ) {
|
|
- switch( opinfo.boi_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- }
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_add) ": no write access to entry\n",
|
|
- 0, 0, 0 );
|
|
- rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
|
- rs->sr_text = "no write access to entry";
|
|
- goto return_results;;
|
|
- }
|
|
-
|
|
- /*
|
|
- * Check ACL for attribute write access
|
|
- */
|
|
- if (!acl_check_modlist(op, oe, op->ora_modlist)) {
|
|
- switch( opinfo.boi_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- }
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_add) ": no write access to attribute\n",
|
|
- 0, 0, 0 );
|
|
- rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
|
- rs->sr_text = "no write access to attribute";
|
|
- goto return_results;;
|
|
- }
|
|
-
|
|
- if ( eid == NOID ) {
|
|
- rs->sr_err = bdb_next_id( op->o_bd, &eid );
|
|
- if( rs->sr_err != 0 ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_add) ": next_id failed (%d)\n",
|
|
- rs->sr_err, 0, 0 );
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "internal error";
|
|
- goto return_results;
|
|
- }
|
|
- op->ora_e->e_id = eid;
|
|
- }
|
|
-
|
|
- /* nested transaction */
|
|
- rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, <2,
|
|
- bdb->bi_db_opflags );
|
|
- rs->sr_text = NULL;
|
|
- if( rs->sr_err != 0 ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_add) ": txn_begin(2) failed: "
|
|
- "%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "internal error";
|
|
- goto return_results;
|
|
- }
|
|
- Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_add) ": txn2 id: %x\n",
|
|
- lt2->id(lt2), 0, 0 );
|
|
-
|
|
- /* dn2id index */
|
|
- rs->sr_err = bdb_dn2id_add( op, lt2, ei, op->ora_e );
|
|
- if ( rs->sr_err != 0 ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_add) ": dn2id_add failed: %s (%d)\n",
|
|
- db_strerror(rs->sr_err), rs->sr_err, 0 );
|
|
-
|
|
- switch( rs->sr_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- case DB_KEYEXIST:
|
|
- rs->sr_err = LDAP_ALREADY_EXISTS;
|
|
- break;
|
|
- default:
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- }
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- /* attribute indexes */
|
|
- rs->sr_err = bdb_index_entry_add( op, lt2, op->ora_e );
|
|
- if ( rs->sr_err != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_add) ": index_entry_add failed\n",
|
|
- 0, 0, 0 );
|
|
- switch( rs->sr_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- default:
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- }
|
|
- rs->sr_text = "index generation failed";
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- /* id2entry index */
|
|
- rs->sr_err = bdb_id2entry_add( op->o_bd, lt2, op->ora_e );
|
|
- if ( rs->sr_err != 0 ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_add) ": id2entry_add failed\n",
|
|
- 0, 0, 0 );
|
|
- switch( rs->sr_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- default:
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- }
|
|
- rs->sr_text = "entry store failed";
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "txn_commit(2) failed";
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- /* post-read */
|
|
- if( op->o_postread ) {
|
|
- if( postread_ctrl == NULL ) {
|
|
- postread_ctrl = &ctrls[num_ctrls++];
|
|
- ctrls[num_ctrls] = NULL;
|
|
- }
|
|
- if ( slap_read_controls( op, rs, op->ora_e,
|
|
- &slap_post_read_bv, postread_ctrl ) )
|
|
- {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<=- " LDAP_XSTRING(bdb_add) ": post-read "
|
|
- "failed!\n", 0, 0, 0 );
|
|
- if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
|
|
- /* FIXME: is it correct to abort
|
|
- * operation if control fails? */
|
|
- goto return_results;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- if ( op->o_noop ) {
|
|
- if (( rs->sr_err=TXN_ABORT( ltid )) != 0 ) {
|
|
- rs->sr_text = "txn_abort (no-op) failed";
|
|
- } else {
|
|
- rs->sr_err = LDAP_X_NO_OPERATION;
|
|
- ltid = NULL;
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- } else {
|
|
- struct berval nrdn;
|
|
-
|
|
- /* pick the RDN if not suffix; otherwise pick the entire DN */
|
|
- if (pdn.bv_len) {
|
|
- nrdn.bv_val = op->ora_e->e_nname.bv_val;
|
|
- nrdn.bv_len = pdn.bv_val - op->ora_e->e_nname.bv_val - 1;
|
|
- } else {
|
|
- nrdn = op->ora_e->e_nname;
|
|
- }
|
|
-
|
|
- bdb_cache_add( bdb, ei, op->ora_e, &nrdn, ltid, &lock );
|
|
-
|
|
- if(( rs->sr_err=TXN_COMMIT( ltid, 0 )) != 0 ) {
|
|
- rs->sr_text = "txn_commit failed";
|
|
- } else {
|
|
- rs->sr_err = LDAP_SUCCESS;
|
|
- }
|
|
- }
|
|
-
|
|
- ltid = NULL;
|
|
- LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
|
|
- opinfo.boi_oe.oe_key = NULL;
|
|
-
|
|
- if ( rs->sr_err != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_add) ": %s : %s (%d)\n",
|
|
- rs->sr_text, db_strerror(rs->sr_err), rs->sr_err );
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- Debug(LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_add) ": added%s id=%08lx dn=\"%s\"\n",
|
|
- op->o_noop ? " (no-op)" : "",
|
|
- op->ora_e->e_id, op->ora_e->e_dn );
|
|
-
|
|
- rs->sr_text = NULL;
|
|
- if( num_ctrls ) rs->sr_ctrls = ctrls;
|
|
-
|
|
-return_results:
|
|
- success = rs->sr_err;
|
|
- send_ldap_result( op, rs );
|
|
-
|
|
- if( ltid != NULL ) {
|
|
- TXN_ABORT( ltid );
|
|
- }
|
|
- if ( opinfo.boi_oe.oe_key ) {
|
|
- LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
|
|
- }
|
|
-
|
|
- if( success == LDAP_SUCCESS ) {
|
|
- /* We own the entry now, and it can be purged at will
|
|
- * Check to make sure it's the same entry we entered with.
|
|
- * Possibly a callback may have mucked with it, although
|
|
- * in general callbacks should treat the entry as read-only.
|
|
- */
|
|
- bdb_cache_deref( oe->e_private );
|
|
- if ( op->ora_e == oe )
|
|
- op->ora_e = NULL;
|
|
-
|
|
- if ( bdb->bi_txn_cp_kbyte ) {
|
|
- TXN_CHECKPOINT( bdb->bi_dbenv,
|
|
- bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
|
|
- }
|
|
- }
|
|
-
|
|
- slap_graduate_commit_csn( op );
|
|
-
|
|
- if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) {
|
|
- slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
|
|
- slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
|
|
- }
|
|
- return rs->sr_err;
|
|
-}
|
|
diff --git a/servers/slapd/back-bdb/attr.c b/servers/slapd/back-bdb/attr.c
|
|
deleted file mode 100644
|
|
index 5d9990d..0000000
|
|
--- a/servers/slapd/back-bdb/attr.c
|
|
+++ /dev/null
|
|
@@ -1,441 +0,0 @@
|
|
-/* attr.c - backend routines for dealing with attributes */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-
|
|
-#include <stdio.h>
|
|
-
|
|
-#include <ac/socket.h>
|
|
-#include <ac/string.h>
|
|
-
|
|
-#include "slap.h"
|
|
-#include "back-bdb.h"
|
|
-#include "config.h"
|
|
-#include "lutil.h"
|
|
-
|
|
-/* Find the ad, return -1 if not found,
|
|
- * set point for insertion if ins is non-NULL
|
|
- */
|
|
-int
|
|
-bdb_attr_slot( struct bdb_info *bdb, AttributeDescription *ad, int *ins )
|
|
-{
|
|
- unsigned base = 0, cursor = 0;
|
|
- unsigned n = bdb->bi_nattrs;
|
|
- int val = 0;
|
|
-
|
|
- while ( 0 < n ) {
|
|
- unsigned pivot = n >> 1;
|
|
- cursor = base + pivot;
|
|
-
|
|
- val = SLAP_PTRCMP( ad, bdb->bi_attrs[cursor]->ai_desc );
|
|
- if ( val < 0 ) {
|
|
- n = pivot;
|
|
- } else if ( val > 0 ) {
|
|
- base = cursor + 1;
|
|
- n -= pivot + 1;
|
|
- } else {
|
|
- return cursor;
|
|
- }
|
|
- }
|
|
- if ( ins ) {
|
|
- if ( val > 0 )
|
|
- ++cursor;
|
|
- *ins = cursor;
|
|
- }
|
|
- return -1;
|
|
-}
|
|
-
|
|
-static int
|
|
-ainfo_insert( struct bdb_info *bdb, AttrInfo *a )
|
|
-{
|
|
- int x;
|
|
- int i = bdb_attr_slot( bdb, a->ai_desc, &x );
|
|
-
|
|
- /* Is it a dup? */
|
|
- if ( i >= 0 )
|
|
- return -1;
|
|
-
|
|
- bdb->bi_attrs = ch_realloc( bdb->bi_attrs, ( bdb->bi_nattrs+1 ) *
|
|
- sizeof( AttrInfo * ));
|
|
- if ( x < bdb->bi_nattrs )
|
|
- AC_MEMCPY( &bdb->bi_attrs[x+1], &bdb->bi_attrs[x],
|
|
- ( bdb->bi_nattrs - x ) * sizeof( AttrInfo *));
|
|
- bdb->bi_attrs[x] = a;
|
|
- bdb->bi_nattrs++;
|
|
- return 0;
|
|
-}
|
|
-
|
|
-AttrInfo *
|
|
-bdb_attr_mask(
|
|
- struct bdb_info *bdb,
|
|
- AttributeDescription *desc )
|
|
-{
|
|
- int i = bdb_attr_slot( bdb, desc, NULL );
|
|
- return i < 0 ? NULL : bdb->bi_attrs[i];
|
|
-}
|
|
-
|
|
-int
|
|
-bdb_attr_index_config(
|
|
- struct bdb_info *bdb,
|
|
- const char *fname,
|
|
- int lineno,
|
|
- int argc,
|
|
- char **argv,
|
|
- struct config_reply_s *c_reply)
|
|
-{
|
|
- int rc = 0;
|
|
- int i;
|
|
- slap_mask_t mask;
|
|
- char **attrs;
|
|
- char **indexes = NULL;
|
|
-
|
|
- attrs = ldap_str2charray( argv[0], "," );
|
|
-
|
|
- if( attrs == NULL ) {
|
|
- fprintf( stderr, "%s: line %d: "
|
|
- "no attributes specified: %s\n",
|
|
- fname, lineno, argv[0] );
|
|
- return LDAP_PARAM_ERROR;
|
|
- }
|
|
-
|
|
- if ( argc > 1 ) {
|
|
- indexes = ldap_str2charray( argv[1], "," );
|
|
-
|
|
- if( indexes == NULL ) {
|
|
- fprintf( stderr, "%s: line %d: "
|
|
- "no indexes specified: %s\n",
|
|
- fname, lineno, argv[1] );
|
|
- rc = LDAP_PARAM_ERROR;
|
|
- goto done;
|
|
- }
|
|
- }
|
|
-
|
|
- if( indexes == NULL ) {
|
|
- mask = bdb->bi_defaultmask;
|
|
-
|
|
- } else {
|
|
- mask = 0;
|
|
-
|
|
- for ( i = 0; indexes[i] != NULL; i++ ) {
|
|
- slap_mask_t index;
|
|
- rc = slap_str2index( indexes[i], &index );
|
|
-
|
|
- if( rc != LDAP_SUCCESS ) {
|
|
- if ( c_reply )
|
|
- {
|
|
- snprintf(c_reply->msg, sizeof(c_reply->msg),
|
|
- "index type \"%s\" undefined", indexes[i] );
|
|
-
|
|
- fprintf( stderr, "%s: line %d: %s\n",
|
|
- fname, lineno, c_reply->msg );
|
|
- }
|
|
- rc = LDAP_PARAM_ERROR;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- mask |= index;
|
|
- }
|
|
- }
|
|
-
|
|
- if( !mask ) {
|
|
- if ( c_reply )
|
|
- {
|
|
- snprintf(c_reply->msg, sizeof(c_reply->msg),
|
|
- "no indexes selected" );
|
|
- fprintf( stderr, "%s: line %d: %s\n",
|
|
- fname, lineno, c_reply->msg );
|
|
- }
|
|
- rc = LDAP_PARAM_ERROR;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- for ( i = 0; attrs[i] != NULL; i++ ) {
|
|
- AttrInfo *a;
|
|
- AttributeDescription *ad;
|
|
- const char *text;
|
|
-#ifdef LDAP_COMP_MATCH
|
|
- ComponentReference* cr = NULL;
|
|
- AttrInfo *a_cr = NULL;
|
|
-#endif
|
|
-
|
|
- if( strcasecmp( attrs[i], "default" ) == 0 ) {
|
|
- bdb->bi_defaultmask |= mask;
|
|
- continue;
|
|
- }
|
|
-
|
|
-#ifdef LDAP_COMP_MATCH
|
|
- if ( is_component_reference( attrs[i] ) ) {
|
|
- rc = extract_component_reference( attrs[i], &cr );
|
|
- if ( rc != LDAP_SUCCESS ) {
|
|
- if ( c_reply )
|
|
- {
|
|
- snprintf(c_reply->msg, sizeof(c_reply->msg),
|
|
- "index component reference\"%s\" undefined",
|
|
- attrs[i] );
|
|
- fprintf( stderr, "%s: line %d: %s\n",
|
|
- fname, lineno, c_reply->msg );
|
|
- }
|
|
- goto done;
|
|
- }
|
|
- cr->cr_indexmask = mask;
|
|
- /*
|
|
- * After extracting a component reference
|
|
- * only the name of a attribute will be remaining
|
|
- */
|
|
- } else {
|
|
- cr = NULL;
|
|
- }
|
|
-#endif
|
|
- ad = NULL;
|
|
- rc = slap_str2ad( attrs[i], &ad, &text );
|
|
-
|
|
- if( rc != LDAP_SUCCESS ) {
|
|
- if ( c_reply )
|
|
- {
|
|
- snprintf(c_reply->msg, sizeof(c_reply->msg),
|
|
- "index attribute \"%s\" undefined",
|
|
- attrs[i] );
|
|
-
|
|
- fprintf( stderr, "%s: line %d: %s\n",
|
|
- fname, lineno, c_reply->msg );
|
|
- }
|
|
- goto done;
|
|
- }
|
|
-
|
|
- if( ad == slap_schema.si_ad_entryDN || slap_ad_is_binary( ad ) ) {
|
|
- if (c_reply) {
|
|
- snprintf(c_reply->msg, sizeof(c_reply->msg),
|
|
- "index of attribute \"%s\" disallowed", attrs[i] );
|
|
- fprintf( stderr, "%s: line %d: %s\n",
|
|
- fname, lineno, c_reply->msg );
|
|
- }
|
|
- rc = LDAP_UNWILLING_TO_PERFORM;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) && !(
|
|
- ad->ad_type->sat_approx
|
|
- && ad->ad_type->sat_approx->smr_indexer
|
|
- && ad->ad_type->sat_approx->smr_filter ) )
|
|
- {
|
|
- if (c_reply) {
|
|
- snprintf(c_reply->msg, sizeof(c_reply->msg),
|
|
- "approx index of attribute \"%s\" disallowed", attrs[i] );
|
|
- fprintf( stderr, "%s: line %d: %s\n",
|
|
- fname, lineno, c_reply->msg );
|
|
- }
|
|
- rc = LDAP_INAPPROPRIATE_MATCHING;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) && !(
|
|
- ad->ad_type->sat_equality
|
|
- && ad->ad_type->sat_equality->smr_indexer
|
|
- && ad->ad_type->sat_equality->smr_filter ) )
|
|
- {
|
|
- if (c_reply) {
|
|
- snprintf(c_reply->msg, sizeof(c_reply->msg),
|
|
- "equality index of attribute \"%s\" disallowed", attrs[i] );
|
|
- fprintf( stderr, "%s: line %d: %s\n",
|
|
- fname, lineno, c_reply->msg );
|
|
- }
|
|
- rc = LDAP_INAPPROPRIATE_MATCHING;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) && !(
|
|
- ad->ad_type->sat_substr
|
|
- && ad->ad_type->sat_substr->smr_indexer
|
|
- && ad->ad_type->sat_substr->smr_filter ) )
|
|
- {
|
|
- if (c_reply) {
|
|
- snprintf(c_reply->msg, sizeof(c_reply->msg),
|
|
- "substr index of attribute \"%s\" disallowed", attrs[i] );
|
|
- fprintf( stderr, "%s: line %d: %s\n",
|
|
- fname, lineno, c_reply->msg );
|
|
- }
|
|
- rc = LDAP_INAPPROPRIATE_MATCHING;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- Debug( LDAP_DEBUG_CONFIG, "index %s 0x%04lx\n",
|
|
- ad->ad_cname.bv_val, mask, 0 );
|
|
-
|
|
- a = (AttrInfo *) ch_malloc( sizeof(AttrInfo) );
|
|
-
|
|
-#ifdef LDAP_COMP_MATCH
|
|
- a->ai_cr = NULL;
|
|
-#endif
|
|
- a->ai_desc = ad;
|
|
-
|
|
- if ( bdb->bi_flags & BDB_IS_OPEN ) {
|
|
- a->ai_indexmask = 0;
|
|
- a->ai_newmask = mask;
|
|
- } else {
|
|
- a->ai_indexmask = mask;
|
|
- a->ai_newmask = 0;
|
|
- }
|
|
-
|
|
-#ifdef LDAP_COMP_MATCH
|
|
- if ( cr ) {
|
|
- a_cr = bdb_attr_mask( bdb, ad );
|
|
- if ( a_cr ) {
|
|
- /*
|
|
- * AttrInfo is already in AVL
|
|
- * just add the extracted component reference
|
|
- * in the AttrInfo
|
|
- */
|
|
- rc = insert_component_reference( cr, &a_cr->ai_cr );
|
|
- if ( rc != LDAP_SUCCESS) {
|
|
- fprintf( stderr, " error during inserting component reference in %s ", attrs[i]);
|
|
- rc = LDAP_PARAM_ERROR;
|
|
- goto done;
|
|
- }
|
|
- continue;
|
|
- } else {
|
|
- rc = insert_component_reference( cr, &a->ai_cr );
|
|
- if ( rc != LDAP_SUCCESS) {
|
|
- fprintf( stderr, " error during inserting component reference in %s ", attrs[i]);
|
|
- rc = LDAP_PARAM_ERROR;
|
|
- goto done;
|
|
- }
|
|
- }
|
|
- }
|
|
-#endif
|
|
- rc = ainfo_insert( bdb, a );
|
|
- if( rc ) {
|
|
- if ( bdb->bi_flags & BDB_IS_OPEN ) {
|
|
- AttrInfo *b = bdb_attr_mask( bdb, ad );
|
|
- /* If there is already an index defined for this attribute
|
|
- * it must be replaced. Otherwise we end up with multiple
|
|
- * olcIndex values for the same attribute */
|
|
- if ( b->ai_indexmask & BDB_INDEX_DELETING ) {
|
|
- /* If we were editing this attr, reset it */
|
|
- b->ai_indexmask &= ~BDB_INDEX_DELETING;
|
|
- /* If this is leftover from a previous add, commit it */
|
|
- if ( b->ai_newmask )
|
|
- b->ai_indexmask = b->ai_newmask;
|
|
- b->ai_newmask = a->ai_newmask;
|
|
- ch_free( a );
|
|
- rc = 0;
|
|
- continue;
|
|
- }
|
|
- }
|
|
- if (c_reply) {
|
|
- snprintf(c_reply->msg, sizeof(c_reply->msg),
|
|
- "duplicate index definition for attr \"%s\"",
|
|
- attrs[i] );
|
|
- fprintf( stderr, "%s: line %d: %s\n",
|
|
- fname, lineno, c_reply->msg );
|
|
- }
|
|
-
|
|
- rc = LDAP_PARAM_ERROR;
|
|
- goto done;
|
|
- }
|
|
- }
|
|
-
|
|
-done:
|
|
- ldap_charray_free( attrs );
|
|
- if ( indexes != NULL ) ldap_charray_free( indexes );
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static int
|
|
-bdb_attr_index_unparser( void *v1, void *v2 )
|
|
-{
|
|
- AttrInfo *ai = v1;
|
|
- BerVarray *bva = v2;
|
|
- struct berval bv;
|
|
- char *ptr;
|
|
-
|
|
- slap_index2bvlen( ai->ai_indexmask, &bv );
|
|
- if ( bv.bv_len ) {
|
|
- bv.bv_len += ai->ai_desc->ad_cname.bv_len + 1;
|
|
- ptr = ch_malloc( bv.bv_len+1 );
|
|
- bv.bv_val = lutil_strcopy( ptr, ai->ai_desc->ad_cname.bv_val );
|
|
- *bv.bv_val++ = ' ';
|
|
- slap_index2bv( ai->ai_indexmask, &bv );
|
|
- bv.bv_val = ptr;
|
|
- ber_bvarray_add( bva, &bv );
|
|
- }
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static AttributeDescription addef = { NULL, NULL, BER_BVC("default") };
|
|
-static AttrInfo aidef = { &addef };
|
|
-
|
|
-void
|
|
-bdb_attr_index_unparse( struct bdb_info *bdb, BerVarray *bva )
|
|
-{
|
|
- int i;
|
|
-
|
|
- if ( bdb->bi_defaultmask ) {
|
|
- aidef.ai_indexmask = bdb->bi_defaultmask;
|
|
- bdb_attr_index_unparser( &aidef, bva );
|
|
- }
|
|
- for ( i=0; i<bdb->bi_nattrs; i++ )
|
|
- bdb_attr_index_unparser( bdb->bi_attrs[i], bva );
|
|
-}
|
|
-
|
|
-void
|
|
-bdb_attr_info_free( AttrInfo *ai )
|
|
-{
|
|
-#ifdef LDAP_COMP_MATCH
|
|
- free( ai->ai_cr );
|
|
-#endif
|
|
- free( ai );
|
|
-}
|
|
-
|
|
-void
|
|
-bdb_attr_index_destroy( struct bdb_info *bdb )
|
|
-{
|
|
- int i;
|
|
-
|
|
- for ( i=0; i<bdb->bi_nattrs; i++ )
|
|
- bdb_attr_info_free( bdb->bi_attrs[i] );
|
|
-
|
|
- free( bdb->bi_attrs );
|
|
-}
|
|
-
|
|
-void bdb_attr_index_free( struct bdb_info *bdb, AttributeDescription *ad )
|
|
-{
|
|
- int i;
|
|
-
|
|
- i = bdb_attr_slot( bdb, ad, NULL );
|
|
- if ( i >= 0 ) {
|
|
- bdb_attr_info_free( bdb->bi_attrs[i] );
|
|
- bdb->bi_nattrs--;
|
|
- for (; i<bdb->bi_nattrs; i++)
|
|
- bdb->bi_attrs[i] = bdb->bi_attrs[i+1];
|
|
- }
|
|
-}
|
|
-
|
|
-void bdb_attr_flush( struct bdb_info *bdb )
|
|
-{
|
|
- int i;
|
|
-
|
|
- for ( i=0; i<bdb->bi_nattrs; i++ ) {
|
|
- if ( bdb->bi_attrs[i]->ai_indexmask & BDB_INDEX_DELETING ) {
|
|
- int j;
|
|
- bdb_attr_info_free( bdb->bi_attrs[i] );
|
|
- bdb->bi_nattrs--;
|
|
- for (j=i; j<bdb->bi_nattrs; j++)
|
|
- bdb->bi_attrs[j] = bdb->bi_attrs[j+1];
|
|
- i--;
|
|
- }
|
|
- }
|
|
-}
|
|
diff --git a/servers/slapd/back-bdb/back-bdb.h b/servers/slapd/back-bdb/back-bdb.h
|
|
deleted file mode 100644
|
|
index 84897cd..0000000
|
|
--- a/servers/slapd/back-bdb/back-bdb.h
|
|
+++ /dev/null
|
|
@@ -1,377 +0,0 @@
|
|
-/* back-bdb.h - bdb back-end header file */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#ifndef _BACK_BDB_H_
|
|
-#define _BACK_BDB_H_
|
|
-
|
|
-#include <portable.h>
|
|
-#include "slap.h"
|
|
-#include <db.h>
|
|
-#include "alock.h"
|
|
-
|
|
-LDAP_BEGIN_DECL
|
|
-
|
|
-#define DB_VERSION_FULL ((DB_VERSION_MAJOR << 24) | (DB_VERSION_MINOR << 16) | DB_VERSION_PATCH)
|
|
-
|
|
-#define DN_BASE_PREFIX SLAP_INDEX_EQUALITY_PREFIX
|
|
-#define DN_ONE_PREFIX '%'
|
|
-#define DN_SUBTREE_PREFIX '@'
|
|
-
|
|
-#define DBTzero(t) (memset((t), 0, sizeof(DBT)))
|
|
-#define DBT2bv(t,bv) ((bv)->bv_val = (t)->data, \
|
|
- (bv)->bv_len = (t)->size)
|
|
-#define bv2DBT(bv,t) ((t)->data = (bv)->bv_val, \
|
|
- (t)->size = (bv)->bv_len )
|
|
-
|
|
-#define BDB_TXN_RETRIES 16
|
|
-
|
|
-#define BDB_MAX_ADD_LOOP 30
|
|
-
|
|
-#define BDB_SUFFIX ".bdb"
|
|
-#define BDB_ID2ENTRY 0
|
|
-#define BDB_DN2ID 1
|
|
-#define BDB_NDB 2
|
|
-
|
|
-/* The bdb on-disk entry format is pretty space-inefficient. Average
|
|
- * sized user entries are 3-4K each. You need at least two entries to
|
|
- * fit into a single database page, more is better. 64K is BDB's
|
|
- * upper bound. Smaller pages are better for concurrency.
|
|
- */
|
|
-#ifndef BDB_ID2ENTRY_PAGESIZE
|
|
-#define BDB_ID2ENTRY_PAGESIZE 16384
|
|
-#endif
|
|
-
|
|
-#define DEFAULT_CACHE_SIZE 1000
|
|
-
|
|
-/* The default search IDL stack cache depth */
|
|
-#define DEFAULT_SEARCH_STACK_DEPTH 16
|
|
-
|
|
-/* The minimum we can function with */
|
|
-#define MINIMUM_SEARCH_STACK_DEPTH 8
|
|
-
|
|
-typedef struct bdb_idl_cache_entry_s {
|
|
- struct berval kstr;
|
|
- ID *idl;
|
|
- DB *db;
|
|
- int idl_flags;
|
|
- struct bdb_idl_cache_entry_s* idl_lru_prev;
|
|
- struct bdb_idl_cache_entry_s* idl_lru_next;
|
|
-} bdb_idl_cache_entry_t;
|
|
-
|
|
-/* BDB backend specific entry info */
|
|
-typedef struct bdb_entry_info {
|
|
- struct bdb_entry_info *bei_parent;
|
|
- ID bei_id;
|
|
-
|
|
- /* we use the bei_id as a lockobj, but we need to make the size != 4
|
|
- * to avoid conflicting with BDB's internal locks. So add a byte here
|
|
- * that is always zero.
|
|
- */
|
|
- short bei_lockpad;
|
|
-
|
|
- short bei_state;
|
|
-#define CACHE_ENTRY_DELETED 1
|
|
-#define CACHE_ENTRY_NO_KIDS 2
|
|
-#define CACHE_ENTRY_NOT_LINKED 4
|
|
-#define CACHE_ENTRY_NO_GRANDKIDS 8
|
|
-#define CACHE_ENTRY_LOADING 0x10
|
|
-#define CACHE_ENTRY_WALKING 0x20
|
|
-#define CACHE_ENTRY_ONELEVEL 0x40
|
|
-#define CACHE_ENTRY_REFERENCED 0x80
|
|
-#define CACHE_ENTRY_NOT_CACHED 0x100
|
|
- int bei_finders;
|
|
-
|
|
- /*
|
|
- * remaining fields require backend cache lock to access
|
|
- */
|
|
- struct berval bei_nrdn;
|
|
-#ifdef BDB_HIER
|
|
- struct berval bei_rdn;
|
|
- int bei_modrdns; /* track renames */
|
|
- int bei_ckids; /* number of kids cached */
|
|
- int bei_dkids; /* number of kids on-disk, plus 1 */
|
|
-#endif
|
|
- Entry *bei_e;
|
|
- Avlnode *bei_kids;
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- struct bdb_info *bei_bdb;
|
|
- int bei_zseq;
|
|
-#endif
|
|
- ldap_pvt_thread_mutex_t bei_kids_mutex;
|
|
-
|
|
- struct bdb_entry_info *bei_lrunext; /* for cache lru list */
|
|
- struct bdb_entry_info *bei_lruprev;
|
|
-} EntryInfo;
|
|
-#undef BEI
|
|
-#define BEI(e) ((EntryInfo *) ((e)->e_private))
|
|
-
|
|
-/* for the in-core cache of entries */
|
|
-typedef struct bdb_cache {
|
|
- EntryInfo *c_eifree; /* free list */
|
|
- Avlnode *c_idtree;
|
|
- EntryInfo *c_lruhead; /* lru - add accessed entries here */
|
|
- EntryInfo *c_lrutail; /* lru - rem lru entries from here */
|
|
- EntryInfo c_dntree;
|
|
- ID c_maxsize;
|
|
- ID c_cursize;
|
|
- ID c_minfree;
|
|
- ID c_eimax;
|
|
- ID c_eiused; /* EntryInfo's in use */
|
|
- ID c_leaves; /* EntryInfo leaf nodes */
|
|
- int c_purging;
|
|
- DB_TXN *c_txn; /* used by lru cleaner */
|
|
- ldap_pvt_thread_rdwr_t c_rwlock;
|
|
- ldap_pvt_thread_mutex_t c_lru_mutex;
|
|
- ldap_pvt_thread_mutex_t c_count_mutex;
|
|
- ldap_pvt_thread_mutex_t c_eifree_mutex;
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- void *c_zctx;
|
|
-#endif
|
|
-} Cache;
|
|
-
|
|
-#define CACHE_READ_LOCK 0
|
|
-#define CACHE_WRITE_LOCK 1
|
|
-
|
|
-#define BDB_INDICES 128
|
|
-
|
|
-struct bdb_db_info {
|
|
- struct berval bdi_name;
|
|
- DB *bdi_db;
|
|
-};
|
|
-
|
|
-struct bdb_db_pgsize {
|
|
- struct bdb_db_pgsize *bdp_next;
|
|
- struct berval bdp_name;
|
|
- int bdp_size;
|
|
-};
|
|
-
|
|
-#ifdef LDAP_DEVEL
|
|
-#define BDB_MONITOR_IDX
|
|
-#endif /* LDAP_DEVEL */
|
|
-
|
|
-typedef struct bdb_monitor_t {
|
|
- void *bdm_cb;
|
|
- struct berval bdm_ndn;
|
|
-} bdb_monitor_t;
|
|
-
|
|
-/* From ldap_rq.h */
|
|
-struct re_s;
|
|
-
|
|
-struct bdb_info {
|
|
- DB_ENV *bi_dbenv;
|
|
-
|
|
- /* DB_ENV parameters */
|
|
- /* The DB_ENV can be tuned via DB_CONFIG */
|
|
- char *bi_dbenv_home;
|
|
- u_int32_t bi_dbenv_xflags; /* extra flags */
|
|
- int bi_dbenv_mode;
|
|
-
|
|
- int bi_ndatabases;
|
|
- int bi_db_opflags; /* db-specific flags */
|
|
- struct bdb_db_info **bi_databases;
|
|
- ldap_pvt_thread_mutex_t bi_database_mutex;
|
|
- struct bdb_db_pgsize *bi_pagesizes;
|
|
-
|
|
- slap_mask_t bi_defaultmask;
|
|
- Cache bi_cache;
|
|
- struct bdb_attrinfo **bi_attrs;
|
|
- int bi_nattrs;
|
|
- void *bi_search_stack;
|
|
- int bi_search_stack_depth;
|
|
- int bi_linear_index;
|
|
-
|
|
- int bi_txn_cp;
|
|
- u_int32_t bi_txn_cp_min;
|
|
- u_int32_t bi_txn_cp_kbyte;
|
|
- struct re_s *bi_txn_cp_task;
|
|
- struct re_s *bi_index_task;
|
|
-
|
|
- u_int32_t bi_lock_detect;
|
|
- long bi_shm_key;
|
|
-
|
|
- ID bi_lastid;
|
|
- ldap_pvt_thread_mutex_t bi_lastid_mutex;
|
|
- ID bi_idl_cache_max_size;
|
|
- ID bi_idl_cache_size;
|
|
- Avlnode *bi_idl_tree;
|
|
- bdb_idl_cache_entry_t *bi_idl_lru_head;
|
|
- bdb_idl_cache_entry_t *bi_idl_lru_tail;
|
|
- ldap_pvt_thread_rdwr_t bi_idl_tree_rwlock;
|
|
- ldap_pvt_thread_mutex_t bi_idl_tree_lrulock;
|
|
- alock_info_t bi_alock_info;
|
|
- char *bi_db_config_path;
|
|
- BerVarray bi_db_config;
|
|
- char *bi_db_crypt_file;
|
|
- struct berval bi_db_crypt_key;
|
|
- bdb_monitor_t bi_monitor;
|
|
-
|
|
-#ifdef BDB_MONITOR_IDX
|
|
- ldap_pvt_thread_mutex_t bi_idx_mutex;
|
|
- Avlnode *bi_idx;
|
|
-#endif /* BDB_MONITOR_IDX */
|
|
-
|
|
- int bi_flags;
|
|
-#define BDB_IS_OPEN 0x01
|
|
-#define BDB_HAS_CONFIG 0x02
|
|
-#define BDB_UPD_CONFIG 0x04
|
|
-#define BDB_DEL_INDEX 0x08
|
|
-#define BDB_RE_OPEN 0x10
|
|
-#define BDB_CHKSUM 0x20
|
|
-#ifdef BDB_HIER
|
|
- int bi_modrdns; /* number of modrdns completed */
|
|
- ldap_pvt_thread_mutex_t bi_modrdns_mutex;
|
|
-#endif
|
|
-};
|
|
-
|
|
-#define bi_id2entry bi_databases[BDB_ID2ENTRY]
|
|
-#define bi_dn2id bi_databases[BDB_DN2ID]
|
|
-
|
|
-
|
|
-struct bdb_lock_info {
|
|
- struct bdb_lock_info *bli_next;
|
|
- DB_LOCK bli_lock;
|
|
- ID bli_id;
|
|
- int bli_flag;
|
|
-};
|
|
-#define BLI_DONTFREE 1
|
|
-
|
|
-struct bdb_op_info {
|
|
- OpExtra boi_oe;
|
|
- DB_TXN* boi_txn;
|
|
- struct bdb_lock_info *boi_locks; /* used when no txn */
|
|
- u_int32_t boi_err;
|
|
- char boi_acl_cache;
|
|
- char boi_flag;
|
|
-};
|
|
-#define BOI_DONTFREE 1
|
|
-
|
|
-#define DB_OPEN(db, file, name, type, flags, mode) \
|
|
- ((db)->open)(db, file, name, type, flags, mode)
|
|
-
|
|
-#if DB_VERSION_MAJOR < 4
|
|
-#define LOCK_DETECT(env,f,t,a) lock_detect(env, f, t, a)
|
|
-#define LOCK_GET(env,i,f,o,m,l) lock_get(env, i, f, o, m, l)
|
|
-#define LOCK_PUT(env,l) lock_put(env, l)
|
|
-#define TXN_CHECKPOINT(env,k,m,f) txn_checkpoint(env, k, m, f)
|
|
-#define TXN_BEGIN(env,p,t,f) txn_begin((env), p, t, f)
|
|
-#define TXN_PREPARE(txn,gid) txn_prepare((txn), (gid))
|
|
-#define TXN_COMMIT(txn,f) txn_commit((txn), (f))
|
|
-#define TXN_ABORT(txn) txn_abort((txn))
|
|
-#define TXN_ID(txn) txn_id(txn)
|
|
-#define XLOCK_ID(env, locker) lock_id(env, locker)
|
|
-#define XLOCK_ID_FREE(env, locker) lock_id_free(env, locker)
|
|
-#else
|
|
-#define LOCK_DETECT(env,f,t,a) (env)->lock_detect(env, f, t, a)
|
|
-#define LOCK_GET(env,i,f,o,m,l) (env)->lock_get(env, i, f, o, m, l)
|
|
-#define LOCK_PUT(env,l) (env)->lock_put(env, l)
|
|
-#define TXN_CHECKPOINT(env,k,m,f) (env)->txn_checkpoint(env, k, m, f)
|
|
-#define TXN_BEGIN(env,p,t,f) (env)->txn_begin((env), p, t, f)
|
|
-#define TXN_PREPARE(txn,g) (txn)->prepare((txn), (g))
|
|
-#define TXN_COMMIT(txn,f) (txn)->commit((txn), (f))
|
|
-#define TXN_ABORT(txn) (txn)->abort((txn))
|
|
-#define TXN_ID(txn) (txn)->id(txn)
|
|
-#define XLOCK_ID(env, locker) (env)->lock_id(env, locker)
|
|
-#define XLOCK_ID_FREE(env, locker) (env)->lock_id_free(env, locker)
|
|
-
|
|
-/* BDB 4.1.17 adds txn arg to db->open */
|
|
-#if DB_VERSION_FULL >= 0x04010011
|
|
-#undef DB_OPEN
|
|
-#define DB_OPEN(db, file, name, type, flags, mode) \
|
|
- ((db)->open)(db, NULL, file, name, type, flags, mode)
|
|
-#endif
|
|
-
|
|
-/* #undef BDB_LOG_DEBUG */
|
|
-
|
|
-#ifdef BDB_LOG_DEBUG
|
|
-
|
|
-/* env->log_printf appeared in 4.4 */
|
|
-#if DB_VERSION_FULL >= 0x04040000
|
|
-#define BDB_LOG_PRINTF(env,txn,fmt,...) (env)->log_printf((env),(txn),(fmt),__VA_ARGS__)
|
|
-#else
|
|
-extern int __db_logmsg(const DB_ENV *env, DB_TXN *txn, const char *op, u_int32_t flags,
|
|
- const char *fmt,...);
|
|
-#define BDB_LOG_PRINTF(env,txn,fmt,...) __db_logmsg((env),(txn),"DIAGNOSTIC",0,(fmt),__VA_ARGS__)
|
|
-#endif
|
|
-
|
|
-/* !BDB_LOG_DEBUG */
|
|
-#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
|
|
- (defined(__GNUC__) && __GNUC__ >= 3 && !defined(__STRICT_ANSI__))
|
|
-#define BDB_LOG_PRINTF(a,b,c,...)
|
|
-#else
|
|
-#define BDB_LOG_PRINTF (void) /* will evaluate and discard the arguments */
|
|
-
|
|
-#endif /* BDB_LOG_DEBUG */
|
|
-
|
|
-#endif
|
|
-
|
|
-#ifndef DB_BUFFER_SMALL
|
|
-#define DB_BUFFER_SMALL ENOMEM
|
|
-#endif
|
|
-
|
|
-#define BDB_CSN_COMMIT 0
|
|
-#define BDB_CSN_ABORT 1
|
|
-#define BDB_CSN_RETRY 2
|
|
-
|
|
-/* Copy an ID "src" to pointer "dst" in big-endian byte order */
|
|
-#define BDB_ID2DISK( src, dst ) \
|
|
- do { int i0; ID tmp; unsigned char *_p; \
|
|
- tmp = (src); _p = (unsigned char *)(dst); \
|
|
- for ( i0=sizeof(ID)-1; i0>=0; i0-- ) { \
|
|
- _p[i0] = tmp & 0xff; tmp >>= 8; \
|
|
- } \
|
|
- } while(0)
|
|
-
|
|
-/* Copy a pointer "src" to a pointer "dst" from big-endian to native order */
|
|
-#define BDB_DISK2ID( src, dst ) \
|
|
- do { unsigned i0; ID tmp = 0; unsigned char *_p; \
|
|
- _p = (unsigned char *)(src); \
|
|
- for ( i0=0; i0<sizeof(ID); i0++ ) { \
|
|
- tmp <<= 8; tmp |= *_p++; \
|
|
- } *(dst) = tmp; \
|
|
- } while (0)
|
|
-
|
|
-LDAP_END_DECL
|
|
-
|
|
-/* for the cache of attribute information (which are indexed, etc.) */
|
|
-typedef struct bdb_attrinfo {
|
|
- AttributeDescription *ai_desc; /* attribute description cn;lang-en */
|
|
- slap_mask_t ai_indexmask; /* how the attr is indexed */
|
|
- slap_mask_t ai_newmask; /* new settings to replace old mask */
|
|
-#ifdef LDAP_COMP_MATCH
|
|
- ComponentReference* ai_cr; /*component indexing*/
|
|
-#endif
|
|
-} AttrInfo;
|
|
-
|
|
-/* These flags must not clash with SLAP_INDEX flags or ops in slap.h! */
|
|
-#define BDB_INDEX_DELETING 0x8000U /* index is being modified */
|
|
-#define BDB_INDEX_UPDATE_OP 0x03 /* performing an index update */
|
|
-
|
|
-/* For slapindex to record which attrs in an entry belong to which
|
|
- * index database
|
|
- */
|
|
-typedef struct AttrList {
|
|
- struct AttrList *next;
|
|
- Attribute *attr;
|
|
-} AttrList;
|
|
-
|
|
-typedef struct IndexRec {
|
|
- AttrInfo *ai;
|
|
- AttrList *attrs;
|
|
-} IndexRec;
|
|
-
|
|
-#include "proto-bdb.h"
|
|
-
|
|
-#endif /* _BACK_BDB_H_ */
|
|
diff --git a/servers/slapd/back-bdb/bind.c b/servers/slapd/back-bdb/bind.c
|
|
deleted file mode 100644
|
|
index c09d629..0000000
|
|
--- a/servers/slapd/back-bdb/bind.c
|
|
+++ /dev/null
|
|
@@ -1,166 +0,0 @@
|
|
-/* bind.c - bdb backend bind routine */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-
|
|
-#include <stdio.h>
|
|
-#include <ac/string.h>
|
|
-#include <ac/unistd.h>
|
|
-
|
|
-#include "back-bdb.h"
|
|
-
|
|
-int
|
|
-bdb_bind( Operation *op, SlapReply *rs )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- Entry *e;
|
|
- Attribute *a;
|
|
- EntryInfo *ei;
|
|
-
|
|
- AttributeDescription *password = slap_schema.si_ad_userPassword;
|
|
-
|
|
- DB_TXN *rtxn;
|
|
- DB_LOCK lock;
|
|
-
|
|
- Debug( LDAP_DEBUG_ARGS,
|
|
- "==> " LDAP_XSTRING(bdb_bind) ": dn: %s\n",
|
|
- op->o_req_dn.bv_val, 0, 0);
|
|
-
|
|
- /* allow noauth binds */
|
|
- switch ( be_rootdn_bind( op, NULL ) ) {
|
|
- case LDAP_SUCCESS:
|
|
- /* frontend will send result */
|
|
- return rs->sr_err = LDAP_SUCCESS;
|
|
-
|
|
- default:
|
|
- /* give the database a chance */
|
|
- /* NOTE: this behavior departs from that of other backends,
|
|
- * since the others, in case of password checking failure
|
|
- * do not give the database a chance. If an entry with
|
|
- * rootdn's name does not exist in the database the result
|
|
- * will be the same. See ITS#4962 for discussion. */
|
|
- break;
|
|
- }
|
|
-
|
|
- rs->sr_err = bdb_reader_get(op, bdb->bi_dbenv, &rtxn);
|
|
- switch(rs->sr_err) {
|
|
- case 0:
|
|
- break;
|
|
- default:
|
|
- rs->sr_text = "internal error";
|
|
- send_ldap_result( op, rs );
|
|
- return rs->sr_err;
|
|
- }
|
|
-
|
|
-dn2entry_retry:
|
|
- /* get entry with reader lock */
|
|
- rs->sr_err = bdb_dn2entry( op, rtxn, &op->o_req_ndn, &ei, 1,
|
|
- &lock );
|
|
-
|
|
- switch(rs->sr_err) {
|
|
- case DB_NOTFOUND:
|
|
- case 0:
|
|
- break;
|
|
- case LDAP_BUSY:
|
|
- send_ldap_error( op, rs, LDAP_BUSY, "ldap_server_busy" );
|
|
- return LDAP_BUSY;
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto dn2entry_retry;
|
|
- default:
|
|
- send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
|
|
- return rs->sr_err;
|
|
- }
|
|
-
|
|
- e = ei->bei_e;
|
|
- if ( rs->sr_err == DB_NOTFOUND ) {
|
|
- if( e != NULL ) {
|
|
- bdb_cache_return_entry_r( bdb, e, &lock );
|
|
- e = NULL;
|
|
- }
|
|
-
|
|
- rs->sr_err = LDAP_INVALID_CREDENTIALS;
|
|
- send_ldap_result( op, rs );
|
|
-
|
|
- return rs->sr_err;
|
|
- }
|
|
-
|
|
- ber_dupbv( &op->oq_bind.rb_edn, &e->e_name );
|
|
-
|
|
- /* check for deleted */
|
|
- if ( is_entry_subentry( e ) ) {
|
|
- /* entry is an subentry, don't allow bind */
|
|
- Debug( LDAP_DEBUG_TRACE, "entry is subentry\n", 0,
|
|
- 0, 0 );
|
|
- rs->sr_err = LDAP_INVALID_CREDENTIALS;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- if ( is_entry_alias( e ) ) {
|
|
- /* entry is an alias, don't allow bind */
|
|
- Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0, 0, 0 );
|
|
- rs->sr_err = LDAP_INVALID_CREDENTIALS;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- if ( is_entry_referral( e ) ) {
|
|
- Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
|
|
- 0, 0 );
|
|
- rs->sr_err = LDAP_INVALID_CREDENTIALS;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- switch ( op->oq_bind.rb_method ) {
|
|
- case LDAP_AUTH_SIMPLE:
|
|
- a = attr_find( e->e_attrs, password );
|
|
- if ( a == NULL ) {
|
|
- rs->sr_err = LDAP_INVALID_CREDENTIALS;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- if ( slap_passwd_check( op, e, a, &op->oq_bind.rb_cred,
|
|
- &rs->sr_text ) != 0 )
|
|
- {
|
|
- /* failure; stop front end from sending result */
|
|
- rs->sr_err = LDAP_INVALID_CREDENTIALS;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- rs->sr_err = 0;
|
|
- break;
|
|
-
|
|
- default:
|
|
- assert( 0 ); /* should not be reachable */
|
|
- rs->sr_err = LDAP_STRONG_AUTH_NOT_SUPPORTED;
|
|
- rs->sr_text = "authentication method not supported";
|
|
- }
|
|
-
|
|
-done:
|
|
- /* free entry and reader lock */
|
|
- if( e != NULL ) {
|
|
- bdb_cache_return_entry_r( bdb, e, &lock );
|
|
- }
|
|
-
|
|
- if ( rs->sr_err ) {
|
|
- send_ldap_result( op, rs );
|
|
- if ( rs->sr_ref ) {
|
|
- ber_bvarray_free( rs->sr_ref );
|
|
- rs->sr_ref = NULL;
|
|
- }
|
|
- }
|
|
- /* front end will send result on success (rs->sr_err==0) */
|
|
- return rs->sr_err;
|
|
-}
|
|
diff --git a/servers/slapd/back-bdb/cache.c b/servers/slapd/back-bdb/cache.c
|
|
deleted file mode 100644
|
|
index 51161fe..0000000
|
|
--- a/servers/slapd/back-bdb/cache.c
|
|
+++ /dev/null
|
|
@@ -1,1692 +0,0 @@
|
|
-/* cache.c - routines to maintain an in-core cache of entries */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-
|
|
-#include <stdio.h>
|
|
-
|
|
-#include <ac/errno.h>
|
|
-#include <ac/string.h>
|
|
-#include <ac/socket.h>
|
|
-
|
|
-#include "slap.h"
|
|
-
|
|
-#include "back-bdb.h"
|
|
-
|
|
-#include "ldap_rq.h"
|
|
-
|
|
-#ifdef BDB_HIER
|
|
-#define bdb_cache_lru_purge hdb_cache_lru_purge
|
|
-#endif
|
|
-static void bdb_cache_lru_purge( struct bdb_info *bdb );
|
|
-
|
|
-static int bdb_cache_delete_internal(Cache *cache, EntryInfo *e, int decr);
|
|
-#ifdef LDAP_DEBUG
|
|
-#define SLAPD_UNUSED
|
|
-#ifdef SLAPD_UNUSED
|
|
-static void bdb_lru_print(Cache *cache);
|
|
-static void bdb_idtree_print(Cache *cache);
|
|
-#endif
|
|
-#endif
|
|
-
|
|
-/* For concurrency experiments only! */
|
|
-#if 0
|
|
-#define ldap_pvt_thread_rdwr_wlock(a) 0
|
|
-#define ldap_pvt_thread_rdwr_wunlock(a) 0
|
|
-#define ldap_pvt_thread_rdwr_rlock(a) 0
|
|
-#define ldap_pvt_thread_rdwr_runlock(a) 0
|
|
-#endif
|
|
-
|
|
-#if 0
|
|
-#define ldap_pvt_thread_mutex_trylock(a) 0
|
|
-#endif
|
|
-
|
|
-static EntryInfo *
|
|
-bdb_cache_entryinfo_new( Cache *cache )
|
|
-{
|
|
- EntryInfo *ei = NULL;
|
|
-
|
|
- if ( cache->c_eifree ) {
|
|
- ldap_pvt_thread_mutex_lock( &cache->c_eifree_mutex );
|
|
- if ( cache->c_eifree ) {
|
|
- ei = cache->c_eifree;
|
|
- cache->c_eifree = ei->bei_lrunext;
|
|
- ei->bei_finders = 0;
|
|
- ei->bei_lrunext = NULL;
|
|
- }
|
|
- ldap_pvt_thread_mutex_unlock( &cache->c_eifree_mutex );
|
|
- }
|
|
- if ( !ei ) {
|
|
- ei = ch_calloc(1, sizeof(EntryInfo));
|
|
- ldap_pvt_thread_mutex_init( &ei->bei_kids_mutex );
|
|
- }
|
|
-
|
|
- ei->bei_state = CACHE_ENTRY_REFERENCED;
|
|
-
|
|
- return ei;
|
|
-}
|
|
-
|
|
-static void
|
|
-bdb_cache_entryinfo_free( Cache *cache, EntryInfo *ei )
|
|
-{
|
|
- free( ei->bei_nrdn.bv_val );
|
|
- BER_BVZERO( &ei->bei_nrdn );
|
|
-#ifdef BDB_HIER
|
|
- free( ei->bei_rdn.bv_val );
|
|
- BER_BVZERO( &ei->bei_rdn );
|
|
- ei->bei_modrdns = 0;
|
|
- ei->bei_ckids = 0;
|
|
- ei->bei_dkids = 0;
|
|
-#endif
|
|
- ei->bei_parent = NULL;
|
|
- ei->bei_kids = NULL;
|
|
- ei->bei_lruprev = NULL;
|
|
-
|
|
-#if 0
|
|
- ldap_pvt_thread_mutex_lock( &cache->c_eifree_mutex );
|
|
- ei->bei_lrunext = cache->c_eifree;
|
|
- cache->c_eifree = ei;
|
|
- ldap_pvt_thread_mutex_unlock( &cache->c_eifree_mutex );
|
|
-#else
|
|
- ldap_pvt_thread_mutex_destroy( &ei->bei_kids_mutex );
|
|
- ch_free( ei );
|
|
-#endif
|
|
-}
|
|
-
|
|
-#define LRU_DEL( c, e ) do { \
|
|
- if ( e == e->bei_lruprev ) { \
|
|
- (c)->c_lruhead = (c)->c_lrutail = NULL; \
|
|
- } else { \
|
|
- if ( e == (c)->c_lruhead ) (c)->c_lruhead = e->bei_lruprev; \
|
|
- if ( e == (c)->c_lrutail ) (c)->c_lrutail = e->bei_lruprev; \
|
|
- e->bei_lrunext->bei_lruprev = e->bei_lruprev; \
|
|
- e->bei_lruprev->bei_lrunext = e->bei_lrunext; \
|
|
- } \
|
|
- e->bei_lruprev = NULL; \
|
|
-} while ( 0 )
|
|
-
|
|
-/* Note - we now use a Second-Chance / Clock algorithm instead of
|
|
- * Least-Recently-Used. This tremendously improves concurrency
|
|
- * because we no longer need to manipulate the lists every time an
|
|
- * entry is touched. We only need to lock the lists when adding
|
|
- * or deleting an entry. It's now a circular doubly-linked list.
|
|
- * We always append to the tail, but the head traverses the circle
|
|
- * during a purge operation.
|
|
- */
|
|
-static void
|
|
-bdb_cache_lru_link( struct bdb_info *bdb, EntryInfo *ei )
|
|
-{
|
|
-
|
|
- /* Already linked, ignore */
|
|
- if ( ei->bei_lruprev )
|
|
- return;
|
|
-
|
|
- /* Insert into circular LRU list */
|
|
- ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_lru_mutex );
|
|
-
|
|
- ei->bei_lruprev = bdb->bi_cache.c_lrutail;
|
|
- if ( bdb->bi_cache.c_lrutail ) {
|
|
- ei->bei_lrunext = bdb->bi_cache.c_lrutail->bei_lrunext;
|
|
- bdb->bi_cache.c_lrutail->bei_lrunext = ei;
|
|
- if ( ei->bei_lrunext )
|
|
- ei->bei_lrunext->bei_lruprev = ei;
|
|
- } else {
|
|
- ei->bei_lrunext = ei->bei_lruprev = ei;
|
|
- bdb->bi_cache.c_lruhead = ei;
|
|
- }
|
|
- bdb->bi_cache.c_lrutail = ei;
|
|
- ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_lru_mutex );
|
|
-}
|
|
-
|
|
-#ifdef NO_THREADS
|
|
-#define NO_DB_LOCK
|
|
-#endif
|
|
-
|
|
-/* #define NO_DB_LOCK 1 */
|
|
-/* Note: The BerkeleyDB locks are much slower than regular
|
|
- * mutexes or rdwr locks. But the BDB implementation has the
|
|
- * advantage of using a fixed size lock table, instead of
|
|
- * allocating a lock object per entry in the DB. That's a
|
|
- * key benefit for scaling. It also frees us from worrying
|
|
- * about undetectable deadlocks between BDB activity and our
|
|
- * own cache activity. It's still worth exploring faster
|
|
- * alternatives though.
|
|
- */
|
|
-
|
|
-/* Atomically release and reacquire a lock */
|
|
-int
|
|
-bdb_cache_entry_db_relock(
|
|
- struct bdb_info *bdb,
|
|
- DB_TXN *txn,
|
|
- EntryInfo *ei,
|
|
- int rw,
|
|
- int tryOnly,
|
|
- DB_LOCK *lock )
|
|
-{
|
|
-#ifdef NO_DB_LOCK
|
|
- return 0;
|
|
-#else
|
|
- int rc;
|
|
- DBT lockobj;
|
|
- DB_LOCKREQ list[2];
|
|
-
|
|
- if ( !lock ) return 0;
|
|
-
|
|
- DBTzero( &lockobj );
|
|
- lockobj.data = &ei->bei_id;
|
|
- lockobj.size = sizeof(ei->bei_id) + 1;
|
|
-
|
|
- list[0].op = DB_LOCK_PUT;
|
|
- list[0].lock = *lock;
|
|
- list[1].op = DB_LOCK_GET;
|
|
- list[1].lock = *lock;
|
|
- list[1].mode = rw ? DB_LOCK_WRITE : DB_LOCK_READ;
|
|
- list[1].obj = &lockobj;
|
|
- rc = bdb->bi_dbenv->lock_vec(bdb->bi_dbenv, TXN_ID(txn), tryOnly ? DB_LOCK_NOWAIT : 0,
|
|
- list, 2, NULL );
|
|
-
|
|
- if (rc && !tryOnly) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "bdb_cache_entry_db_relock: entry %ld, rw %d, rc %d\n",
|
|
- ei->bei_id, rw, rc );
|
|
- } else {
|
|
- *lock = list[1].lock;
|
|
- }
|
|
- return rc;
|
|
-#endif
|
|
-}
|
|
-
|
|
-static int
|
|
-bdb_cache_entry_db_lock( struct bdb_info *bdb, DB_TXN *txn, EntryInfo *ei,
|
|
- int rw, int tryOnly, DB_LOCK *lock )
|
|
-{
|
|
-#ifdef NO_DB_LOCK
|
|
- return 0;
|
|
-#else
|
|
- int rc;
|
|
- DBT lockobj;
|
|
- int db_rw;
|
|
-
|
|
- if ( !lock ) return 0;
|
|
-
|
|
- if (rw)
|
|
- db_rw = DB_LOCK_WRITE;
|
|
- else
|
|
- db_rw = DB_LOCK_READ;
|
|
-
|
|
- DBTzero( &lockobj );
|
|
- lockobj.data = &ei->bei_id;
|
|
- lockobj.size = sizeof(ei->bei_id) + 1;
|
|
-
|
|
- rc = LOCK_GET(bdb->bi_dbenv, TXN_ID(txn), tryOnly ? DB_LOCK_NOWAIT : 0,
|
|
- &lockobj, db_rw, lock);
|
|
- if (rc && !tryOnly) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "bdb_cache_entry_db_lock: entry %ld, rw %d, rc %d\n",
|
|
- ei->bei_id, rw, rc );
|
|
- }
|
|
- return rc;
|
|
-#endif /* NO_DB_LOCK */
|
|
-}
|
|
-
|
|
-int
|
|
-bdb_cache_entry_db_unlock ( struct bdb_info *bdb, DB_LOCK *lock )
|
|
-{
|
|
-#ifdef NO_DB_LOCK
|
|
- return 0;
|
|
-#else
|
|
- int rc;
|
|
-
|
|
- if ( !lock || lock->mode == DB_LOCK_NG ) return 0;
|
|
-
|
|
- rc = LOCK_PUT ( bdb->bi_dbenv, lock );
|
|
- return rc;
|
|
-#endif
|
|
-}
|
|
-
|
|
-void
|
|
-bdb_cache_return_entry_rw( struct bdb_info *bdb, Entry *e,
|
|
- int rw, DB_LOCK *lock )
|
|
-{
|
|
- EntryInfo *ei;
|
|
- int free = 0;
|
|
-
|
|
- ei = e->e_private;
|
|
- if ( ei && ( ei->bei_state & CACHE_ENTRY_NOT_CACHED )) {
|
|
- bdb_cache_entryinfo_lock( ei );
|
|
- if ( ei->bei_state & CACHE_ENTRY_NOT_CACHED ) {
|
|
- /* Releasing the entry can only be done when
|
|
- * we know that nobody else is using it, i.e we
|
|
- * should have an entry_db writelock. But the
|
|
- * flag is only set by the thread that loads the
|
|
- * entry, and only if no other threads has found
|
|
- * it while it was working. All other threads
|
|
- * clear the flag, which mean that we should be
|
|
- * the only thread using the entry if the flag
|
|
- * is set here.
|
|
- */
|
|
- ei->bei_e = NULL;
|
|
- ei->bei_state ^= CACHE_ENTRY_NOT_CACHED;
|
|
- free = 1;
|
|
- }
|
|
- bdb_cache_entryinfo_unlock( ei );
|
|
- }
|
|
- bdb_cache_entry_db_unlock( bdb, lock );
|
|
- if ( free ) {
|
|
- e->e_private = NULL;
|
|
- bdb_entry_return( e );
|
|
- }
|
|
-}
|
|
-
|
|
-static int
|
|
-bdb_cache_entryinfo_destroy( EntryInfo *e )
|
|
-{
|
|
- ldap_pvt_thread_mutex_destroy( &e->bei_kids_mutex );
|
|
- free( e->bei_nrdn.bv_val );
|
|
-#ifdef BDB_HIER
|
|
- free( e->bei_rdn.bv_val );
|
|
-#endif
|
|
- free( e );
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/* Do a length-ordered sort on normalized RDNs */
|
|
-static int
|
|
-bdb_rdn_cmp( const void *v_e1, const void *v_e2 )
|
|
-{
|
|
- const EntryInfo *e1 = v_e1, *e2 = v_e2;
|
|
- int rc = e1->bei_nrdn.bv_len - e2->bei_nrdn.bv_len;
|
|
- if (rc == 0) {
|
|
- rc = strncmp( e1->bei_nrdn.bv_val, e2->bei_nrdn.bv_val,
|
|
- e1->bei_nrdn.bv_len );
|
|
- }
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static int
|
|
-bdb_id_cmp( const void *v_e1, const void *v_e2 )
|
|
-{
|
|
- const EntryInfo *e1 = v_e1, *e2 = v_e2;
|
|
- return e1->bei_id - e2->bei_id;
|
|
-}
|
|
-
|
|
-static int
|
|
-bdb_id_dup_err( void *v1, void *v2 )
|
|
-{
|
|
- EntryInfo *e2 = v2;
|
|
- e2->bei_lrunext = v1;
|
|
- return -1;
|
|
-}
|
|
-
|
|
-/* Create an entryinfo in the cache. Caller must release the locks later.
|
|
- */
|
|
-static int
|
|
-bdb_entryinfo_add_internal(
|
|
- struct bdb_info *bdb,
|
|
- EntryInfo *ei,
|
|
- EntryInfo **res )
|
|
-{
|
|
- EntryInfo *ei2 = NULL;
|
|
-
|
|
- *res = NULL;
|
|
-
|
|
- ei2 = bdb_cache_entryinfo_new( &bdb->bi_cache );
|
|
-
|
|
- bdb_cache_entryinfo_lock( ei->bei_parent );
|
|
- ldap_pvt_thread_rdwr_wlock( &bdb->bi_cache.c_rwlock );
|
|
-
|
|
- ei2->bei_id = ei->bei_id;
|
|
- ei2->bei_parent = ei->bei_parent;
|
|
-#ifdef BDB_HIER
|
|
- ei2->bei_rdn = ei->bei_rdn;
|
|
-#endif
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- ei2->bei_bdb = bdb;
|
|
-#endif
|
|
-
|
|
- /* Add to cache ID tree */
|
|
- if (avl_insert( &bdb->bi_cache.c_idtree, ei2, bdb_id_cmp,
|
|
- bdb_id_dup_err )) {
|
|
- EntryInfo *eix = ei2->bei_lrunext;
|
|
- bdb_cache_entryinfo_free( &bdb->bi_cache, ei2 );
|
|
- ei2 = eix;
|
|
-#ifdef BDB_HIER
|
|
- /* It got freed above because its value was
|
|
- * assigned to ei2.
|
|
- */
|
|
- ei->bei_rdn.bv_val = NULL;
|
|
-#endif
|
|
- } else {
|
|
- int rc;
|
|
-
|
|
- bdb->bi_cache.c_eiused++;
|
|
- ber_dupbv( &ei2->bei_nrdn, &ei->bei_nrdn );
|
|
-
|
|
- /* This is a new leaf node. But if parent had no kids, then it was
|
|
- * a leaf and we would be decrementing that. So, only increment if
|
|
- * the parent already has kids.
|
|
- */
|
|
- if ( ei->bei_parent->bei_kids || !ei->bei_parent->bei_id )
|
|
- bdb->bi_cache.c_leaves++;
|
|
- rc = avl_insert( &ei->bei_parent->bei_kids, ei2, bdb_rdn_cmp,
|
|
- avl_dup_error );
|
|
-#ifdef BDB_HIER
|
|
- /* it's possible for hdb_cache_find_parent to beat us to it */
|
|
- if ( !rc ) {
|
|
- ei->bei_parent->bei_ckids++;
|
|
- }
|
|
-#endif
|
|
- }
|
|
-
|
|
- *res = ei2;
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/* Find the EntryInfo for the requested DN. If the DN cannot be found, return
|
|
- * the info for its closest ancestor. *res should be NULL to process a
|
|
- * complete DN starting from the tree root. Otherwise *res must be the
|
|
- * immediate parent of the requested DN, and only the RDN will be searched.
|
|
- * The EntryInfo is locked upon return and must be unlocked by the caller.
|
|
- */
|
|
-int
|
|
-bdb_cache_find_ndn(
|
|
- Operation *op,
|
|
- DB_TXN *txn,
|
|
- struct berval *ndn,
|
|
- EntryInfo **res )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- EntryInfo ei, *eip, *ei2;
|
|
- int rc = 0;
|
|
- char *ptr;
|
|
-
|
|
- /* this function is always called with normalized DN */
|
|
- if ( *res ) {
|
|
- /* we're doing a onelevel search for an RDN */
|
|
- ei.bei_nrdn.bv_val = ndn->bv_val;
|
|
- ei.bei_nrdn.bv_len = dn_rdnlen( op->o_bd, ndn );
|
|
- eip = *res;
|
|
- } else {
|
|
- /* we're searching a full DN from the root */
|
|
- ptr = ndn->bv_val + ndn->bv_len - op->o_bd->be_nsuffix[0].bv_len;
|
|
- ei.bei_nrdn.bv_val = ptr;
|
|
- ei.bei_nrdn.bv_len = op->o_bd->be_nsuffix[0].bv_len;
|
|
- /* Skip to next rdn if suffix is empty */
|
|
- if ( ei.bei_nrdn.bv_len == 0 ) {
|
|
- for (ptr = ei.bei_nrdn.bv_val - 2; ptr > ndn->bv_val
|
|
- && !DN_SEPARATOR(*ptr); ptr--) /* empty */;
|
|
- if ( ptr >= ndn->bv_val ) {
|
|
- if (DN_SEPARATOR(*ptr)) ptr++;
|
|
- ei.bei_nrdn.bv_len = ei.bei_nrdn.bv_val - ptr;
|
|
- ei.bei_nrdn.bv_val = ptr;
|
|
- }
|
|
- }
|
|
- eip = &bdb->bi_cache.c_dntree;
|
|
- }
|
|
-
|
|
- for ( bdb_cache_entryinfo_lock( eip ); eip; ) {
|
|
- eip->bei_state |= CACHE_ENTRY_REFERENCED;
|
|
- ei.bei_parent = eip;
|
|
- ei2 = (EntryInfo *)avl_find( eip->bei_kids, &ei, bdb_rdn_cmp );
|
|
- if ( !ei2 ) {
|
|
- DBC *cursor;
|
|
- int len = ei.bei_nrdn.bv_len;
|
|
-
|
|
- if ( BER_BVISEMPTY( ndn )) {
|
|
- *res = eip;
|
|
- return LDAP_SUCCESS;
|
|
- }
|
|
-
|
|
- ei.bei_nrdn.bv_len = ndn->bv_len -
|
|
- (ei.bei_nrdn.bv_val - ndn->bv_val);
|
|
- eip->bei_finders++;
|
|
- bdb_cache_entryinfo_unlock( eip );
|
|
-
|
|
- BDB_LOG_PRINTF( bdb->bi_dbenv, NULL, "slapd Reading %s",
|
|
- ei.bei_nrdn.bv_val );
|
|
-
|
|
- cursor = NULL;
|
|
- rc = bdb_dn2id( op, &ei.bei_nrdn, &ei, txn, &cursor );
|
|
- if (rc) {
|
|
- bdb_cache_entryinfo_lock( eip );
|
|
- eip->bei_finders--;
|
|
- if ( cursor ) cursor->c_close( cursor );
|
|
- *res = eip;
|
|
- return rc;
|
|
- }
|
|
-
|
|
- BDB_LOG_PRINTF( bdb->bi_dbenv, NULL, "slapd Read got %s(%d)",
|
|
- ei.bei_nrdn.bv_val, ei.bei_id );
|
|
-
|
|
- /* DN exists but needs to be added to cache */
|
|
- ei.bei_nrdn.bv_len = len;
|
|
- rc = bdb_entryinfo_add_internal( bdb, &ei, &ei2 );
|
|
- /* add_internal left eip and c_rwlock locked */
|
|
- eip->bei_finders--;
|
|
- ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
|
|
- if ( cursor ) cursor->c_close( cursor );
|
|
- if ( rc ) {
|
|
- *res = eip;
|
|
- return rc;
|
|
- }
|
|
- }
|
|
- bdb_cache_entryinfo_lock( ei2 );
|
|
- if ( ei2->bei_state & CACHE_ENTRY_DELETED ) {
|
|
- /* In the midst of deleting? Give it a chance to
|
|
- * complete.
|
|
- */
|
|
- bdb_cache_entryinfo_unlock( ei2 );
|
|
- bdb_cache_entryinfo_unlock( eip );
|
|
- ldap_pvt_thread_yield();
|
|
- bdb_cache_entryinfo_lock( eip );
|
|
- *res = eip;
|
|
- return DB_NOTFOUND;
|
|
- }
|
|
- bdb_cache_entryinfo_unlock( eip );
|
|
-
|
|
- eip = ei2;
|
|
-
|
|
- /* Advance to next lower RDN */
|
|
- for (ptr = ei.bei_nrdn.bv_val - 2; ptr > ndn->bv_val
|
|
- && !DN_SEPARATOR(*ptr); ptr--) /* empty */;
|
|
- if ( ptr >= ndn->bv_val ) {
|
|
- if (DN_SEPARATOR(*ptr)) ptr++;
|
|
- ei.bei_nrdn.bv_len = ei.bei_nrdn.bv_val - ptr - 1;
|
|
- ei.bei_nrdn.bv_val = ptr;
|
|
- }
|
|
- if ( ptr < ndn->bv_val ) {
|
|
- *res = eip;
|
|
- break;
|
|
- }
|
|
- }
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-#ifdef BDB_HIER
|
|
-/* Walk up the tree from a child node, looking for an ID that's already
|
|
- * been linked into the cache.
|
|
- */
|
|
-int
|
|
-hdb_cache_find_parent(
|
|
- Operation *op,
|
|
- DB_TXN *txn,
|
|
- ID id,
|
|
- EntryInfo **res )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- EntryInfo ei, eip, *ei2 = NULL, *ein = NULL, *eir = NULL;
|
|
- int rc, add;
|
|
-
|
|
- ei.bei_id = id;
|
|
- ei.bei_kids = NULL;
|
|
- ei.bei_ckids = 0;
|
|
-
|
|
- for (;;) {
|
|
- rc = hdb_dn2id_parent( op, txn, &ei, &eip.bei_id );
|
|
- if ( rc ) break;
|
|
-
|
|
- /* Save the previous node, if any */
|
|
- ei2 = ein;
|
|
-
|
|
- /* Create a new node for the current ID */
|
|
- ein = bdb_cache_entryinfo_new( &bdb->bi_cache );
|
|
- ein->bei_id = ei.bei_id;
|
|
- ein->bei_kids = ei.bei_kids;
|
|
- ein->bei_nrdn = ei.bei_nrdn;
|
|
- ein->bei_rdn = ei.bei_rdn;
|
|
- ein->bei_ckids = ei.bei_ckids;
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- ein->bei_bdb = bdb;
|
|
-#endif
|
|
- ei.bei_ckids = 0;
|
|
- add = 1;
|
|
-
|
|
- /* This node is not fully connected yet */
|
|
- ein->bei_state |= CACHE_ENTRY_NOT_LINKED;
|
|
-
|
|
- /* If this is the first time, save this node
|
|
- * to be returned later.
|
|
- */
|
|
- if ( eir == NULL ) {
|
|
- eir = ein;
|
|
- ein->bei_finders++;
|
|
- }
|
|
-
|
|
-again:
|
|
- /* Insert this node into the ID tree */
|
|
- ldap_pvt_thread_rdwr_wlock( &bdb->bi_cache.c_rwlock );
|
|
- if ( avl_insert( &bdb->bi_cache.c_idtree, (caddr_t)ein,
|
|
- bdb_id_cmp, bdb_id_dup_err ) ) {
|
|
- EntryInfo *eix = ein->bei_lrunext;
|
|
-
|
|
- if ( bdb_cache_entryinfo_trylock( eix )) {
|
|
- ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
|
|
- ldap_pvt_thread_yield();
|
|
- goto again;
|
|
- }
|
|
- ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
|
|
-
|
|
- /* Someone else created this node just before us.
|
|
- * Free our new copy and use the existing one.
|
|
- */
|
|
- bdb_cache_entryinfo_free( &bdb->bi_cache, ein );
|
|
-
|
|
- /* if it was the node we were looking for, just return it */
|
|
- if ( eir == ein ) {
|
|
- *res = eix;
|
|
- rc = 0;
|
|
- break;
|
|
- }
|
|
-
|
|
- ein = ei2;
|
|
- ei2 = eix;
|
|
- add = 0;
|
|
-
|
|
- /* otherwise, link up what we have and return */
|
|
- goto gotparent;
|
|
- }
|
|
-
|
|
- /* If there was a previous node, link it to this one */
|
|
- if ( ei2 ) ei2->bei_parent = ein;
|
|
-
|
|
- /* Look for this node's parent */
|
|
-par2:
|
|
- if ( eip.bei_id ) {
|
|
- ei2 = (EntryInfo *) avl_find( bdb->bi_cache.c_idtree,
|
|
- (caddr_t) &eip, bdb_id_cmp );
|
|
- } else {
|
|
- ei2 = &bdb->bi_cache.c_dntree;
|
|
- }
|
|
- if ( ei2 && bdb_cache_entryinfo_trylock( ei2 )) {
|
|
- ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
|
|
- ldap_pvt_thread_yield();
|
|
- ldap_pvt_thread_rdwr_wlock( &bdb->bi_cache.c_rwlock );
|
|
- goto par2;
|
|
- }
|
|
- if ( add )
|
|
- bdb->bi_cache.c_eiused++;
|
|
- if ( ei2 && ( ei2->bei_kids || !ei2->bei_id ))
|
|
- bdb->bi_cache.c_leaves++;
|
|
- ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
|
|
-
|
|
-gotparent:
|
|
- /* Got the parent, link in and we're done. */
|
|
- if ( ei2 ) {
|
|
- bdb_cache_entryinfo_lock( eir );
|
|
- ein->bei_parent = ei2;
|
|
-
|
|
- if ( avl_insert( &ei2->bei_kids, (caddr_t)ein, bdb_rdn_cmp,
|
|
- avl_dup_error) == 0 )
|
|
- ei2->bei_ckids++;
|
|
-
|
|
- /* Reset all the state info */
|
|
- for (ein = eir; ein != ei2; ein=ein->bei_parent)
|
|
- ein->bei_state &= ~CACHE_ENTRY_NOT_LINKED;
|
|
-
|
|
- bdb_cache_entryinfo_unlock( ei2 );
|
|
- eir->bei_finders--;
|
|
-
|
|
- *res = eir;
|
|
- break;
|
|
- }
|
|
- ei.bei_kids = NULL;
|
|
- ei.bei_id = eip.bei_id;
|
|
- ei.bei_ckids = 1;
|
|
- avl_insert( &ei.bei_kids, (caddr_t)ein, bdb_rdn_cmp,
|
|
- avl_dup_error );
|
|
- }
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/* Used by hdb_dn2idl when loading the EntryInfo for all the children
|
|
- * of a given node
|
|
- */
|
|
-int hdb_cache_load(
|
|
- struct bdb_info *bdb,
|
|
- EntryInfo *ei,
|
|
- EntryInfo **res )
|
|
-{
|
|
- EntryInfo *ei2;
|
|
- int rc;
|
|
-
|
|
- /* See if we already have this one */
|
|
- bdb_cache_entryinfo_lock( ei->bei_parent );
|
|
- ei2 = (EntryInfo *)avl_find( ei->bei_parent->bei_kids, ei, bdb_rdn_cmp );
|
|
- bdb_cache_entryinfo_unlock( ei->bei_parent );
|
|
-
|
|
- if ( !ei2 ) {
|
|
- /* Not found, add it */
|
|
- struct berval bv;
|
|
-
|
|
- /* bei_rdn was not malloc'd before, do it now */
|
|
- ber_dupbv( &bv, &ei->bei_rdn );
|
|
- ei->bei_rdn = bv;
|
|
-
|
|
- rc = bdb_entryinfo_add_internal( bdb, ei, res );
|
|
- bdb_cache_entryinfo_unlock( ei->bei_parent );
|
|
- ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
|
|
- } else {
|
|
- /* Found, return it */
|
|
- *res = ei2;
|
|
- return 0;
|
|
- }
|
|
- return rc;
|
|
-}
|
|
-#endif
|
|
-
|
|
-/* This is best-effort only. If all entries in the cache are
|
|
- * busy, they will all be kept. This is unlikely to happen
|
|
- * unless the cache is very much smaller than the working set.
|
|
- */
|
|
-static void
|
|
-bdb_cache_lru_purge( struct bdb_info *bdb )
|
|
-{
|
|
- DB_LOCK lock, *lockp;
|
|
- EntryInfo *elru, *elnext = NULL;
|
|
- int islocked;
|
|
- ID eicount, ecount;
|
|
- ID count, efree, eifree = 0;
|
|
-#ifdef LDAP_DEBUG
|
|
- int iter;
|
|
-#endif
|
|
-
|
|
- /* Wait for the mutex; we're the only one trying to purge. */
|
|
- ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_lru_mutex );
|
|
-
|
|
- if ( bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize ) {
|
|
- efree = bdb->bi_cache.c_cursize - bdb->bi_cache.c_maxsize;
|
|
- efree += bdb->bi_cache.c_minfree;
|
|
- } else {
|
|
- efree = 0;
|
|
- }
|
|
-
|
|
- /* maximum number of EntryInfo leaves to cache. In slapcat
|
|
- * we always free all leaf nodes.
|
|
- */
|
|
-
|
|
- if ( slapMode & SLAP_TOOL_READONLY ) {
|
|
- eifree = bdb->bi_cache.c_leaves;
|
|
- } else if ( bdb->bi_cache.c_eimax &&
|
|
- bdb->bi_cache.c_leaves > bdb->bi_cache.c_eimax ) {
|
|
- eifree = bdb->bi_cache.c_minfree * 10;
|
|
- if ( eifree >= bdb->bi_cache.c_leaves )
|
|
- eifree /= 2;
|
|
- }
|
|
-
|
|
- if ( !efree && !eifree ) {
|
|
- ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_lru_mutex );
|
|
- bdb->bi_cache.c_purging = 0;
|
|
- return;
|
|
- }
|
|
-
|
|
- if ( bdb->bi_cache.c_txn ) {
|
|
- lockp = &lock;
|
|
- } else {
|
|
- lockp = NULL;
|
|
- }
|
|
-
|
|
- count = 0;
|
|
- eicount = 0;
|
|
- ecount = 0;
|
|
-#ifdef LDAP_DEBUG
|
|
- iter = 0;
|
|
-#endif
|
|
-
|
|
- /* Look for an unused entry to remove */
|
|
- for ( elru = bdb->bi_cache.c_lruhead; elru; elru = elnext ) {
|
|
- elnext = elru->bei_lrunext;
|
|
-
|
|
- if ( bdb_cache_entryinfo_trylock( elru ))
|
|
- goto bottom;
|
|
-
|
|
- /* This flag implements the clock replacement behavior */
|
|
- if ( elru->bei_state & ( CACHE_ENTRY_REFERENCED )) {
|
|
- elru->bei_state &= ~CACHE_ENTRY_REFERENCED;
|
|
- bdb_cache_entryinfo_unlock( elru );
|
|
- goto bottom;
|
|
- }
|
|
-
|
|
- /* If this node is in the process of linking into the cache,
|
|
- * or this node is being deleted, skip it.
|
|
- */
|
|
- if (( elru->bei_state & ( CACHE_ENTRY_NOT_LINKED |
|
|
- CACHE_ENTRY_DELETED | CACHE_ENTRY_LOADING |
|
|
- CACHE_ENTRY_ONELEVEL )) ||
|
|
- elru->bei_finders > 0 ) {
|
|
- bdb_cache_entryinfo_unlock( elru );
|
|
- goto bottom;
|
|
- }
|
|
-
|
|
- if ( bdb_cache_entryinfo_trylock( elru->bei_parent )) {
|
|
- bdb_cache_entryinfo_unlock( elru );
|
|
- goto bottom;
|
|
- }
|
|
-
|
|
- /* entryinfo is locked */
|
|
- islocked = 1;
|
|
-
|
|
- /* If we can successfully writelock it, then
|
|
- * the object is idle.
|
|
- */
|
|
- if ( bdb_cache_entry_db_lock( bdb,
|
|
- bdb->bi_cache.c_txn, elru, 1, 1, lockp ) == 0 ) {
|
|
-
|
|
- /* Free entry for this node if it's present */
|
|
- if ( elru->bei_e ) {
|
|
- ecount++;
|
|
-
|
|
- /* the cache may have gone over the limit while we
|
|
- * weren't looking, so double check.
|
|
- */
|
|
- if ( !efree && ecount > bdb->bi_cache.c_maxsize )
|
|
- efree = bdb->bi_cache.c_minfree;
|
|
-
|
|
- if ( count < efree ) {
|
|
- elru->bei_e->e_private = NULL;
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- bdb_entry_return( bdb, elru->bei_e, elru->bei_zseq );
|
|
-#else
|
|
- bdb_entry_return( elru->bei_e );
|
|
-#endif
|
|
- elru->bei_e = NULL;
|
|
- count++;
|
|
- } else {
|
|
- /* Keep this node cached, skip to next */
|
|
- bdb_cache_entry_db_unlock( bdb, lockp );
|
|
- goto next;
|
|
- }
|
|
- }
|
|
- bdb_cache_entry_db_unlock( bdb, lockp );
|
|
-
|
|
- /*
|
|
- * If it is a leaf node, and we're over the limit, free it.
|
|
- */
|
|
- if ( elru->bei_kids ) {
|
|
- /* Drop from list, we ignore it... */
|
|
- LRU_DEL( &bdb->bi_cache, elru );
|
|
- } else if ( eicount < eifree ) {
|
|
- /* Too many leaf nodes, free this one */
|
|
- bdb_cache_delete_internal( &bdb->bi_cache, elru, 0 );
|
|
- bdb_cache_delete_cleanup( &bdb->bi_cache, elru );
|
|
- islocked = 0;
|
|
- eicount++;
|
|
- } /* Leave on list until we need to free it */
|
|
- }
|
|
-
|
|
-next:
|
|
- if ( islocked ) {
|
|
- bdb_cache_entryinfo_unlock( elru );
|
|
- bdb_cache_entryinfo_unlock( elru->bei_parent );
|
|
- }
|
|
-
|
|
- if ( count >= efree && eicount >= eifree )
|
|
- break;
|
|
-bottom:
|
|
- if ( elnext == bdb->bi_cache.c_lruhead )
|
|
- break;
|
|
-#ifdef LDAP_DEBUG
|
|
- iter++;
|
|
-#endif
|
|
- }
|
|
-
|
|
- if ( count || ecount > bdb->bi_cache.c_cursize ) {
|
|
- ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_count_mutex );
|
|
- /* HACK: we seem to be losing track, fix up now */
|
|
- if ( ecount > bdb->bi_cache.c_cursize )
|
|
- bdb->bi_cache.c_cursize = ecount;
|
|
- bdb->bi_cache.c_cursize -= count;
|
|
- ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_count_mutex );
|
|
- }
|
|
- bdb->bi_cache.c_lruhead = elnext;
|
|
- ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_lru_mutex );
|
|
- bdb->bi_cache.c_purging = 0;
|
|
-}
|
|
-
|
|
-/*
|
|
- * cache_find_id - find an entry in the cache, given id.
|
|
- * The entry is locked for Read upon return. Call with flag ID_LOCKED if
|
|
- * the supplied *eip was already locked.
|
|
- */
|
|
-
|
|
-int
|
|
-bdb_cache_find_id(
|
|
- Operation *op,
|
|
- DB_TXN *tid,
|
|
- ID id,
|
|
- EntryInfo **eip,
|
|
- int flag,
|
|
- DB_LOCK *lock )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- Entry *ep = NULL;
|
|
- int rc = 0, load = 0;
|
|
- EntryInfo ei = { 0 };
|
|
-
|
|
- ei.bei_id = id;
|
|
-
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- slap_zh_rlock(bdb->bi_cache.c_zctx);
|
|
-#endif
|
|
- /* If we weren't given any info, see if we have it already cached */
|
|
- if ( !*eip ) {
|
|
-again: ldap_pvt_thread_rdwr_rlock( &bdb->bi_cache.c_rwlock );
|
|
- *eip = (EntryInfo *) avl_find( bdb->bi_cache.c_idtree,
|
|
- (caddr_t) &ei, bdb_id_cmp );
|
|
- if ( *eip ) {
|
|
- /* If the lock attempt fails, the info is in use */
|
|
- if ( bdb_cache_entryinfo_trylock( *eip )) {
|
|
- int del = (*eip)->bei_state & CACHE_ENTRY_DELETED;
|
|
- ldap_pvt_thread_rdwr_runlock( &bdb->bi_cache.c_rwlock );
|
|
- /* If this node is being deleted, treat
|
|
- * as if the delete has already finished
|
|
- */
|
|
- if ( del ) {
|
|
- return DB_NOTFOUND;
|
|
- }
|
|
- /* otherwise, wait for the info to free up */
|
|
- ldap_pvt_thread_yield();
|
|
- goto again;
|
|
- }
|
|
- /* If this info isn't hooked up to its parent yet,
|
|
- * unlock and wait for it to be fully initialized
|
|
- */
|
|
- if ( (*eip)->bei_state & CACHE_ENTRY_NOT_LINKED ) {
|
|
- bdb_cache_entryinfo_unlock( *eip );
|
|
- ldap_pvt_thread_rdwr_runlock( &bdb->bi_cache.c_rwlock );
|
|
- ldap_pvt_thread_yield();
|
|
- goto again;
|
|
- }
|
|
- flag |= ID_LOCKED;
|
|
- }
|
|
- ldap_pvt_thread_rdwr_runlock( &bdb->bi_cache.c_rwlock );
|
|
- }
|
|
-
|
|
- /* See if the ID exists in the database; add it to the cache if so */
|
|
- if ( !*eip ) {
|
|
-#ifndef BDB_HIER
|
|
- rc = bdb_id2entry( op->o_bd, tid, id, &ep );
|
|
- if ( rc == 0 ) {
|
|
- rc = bdb_cache_find_ndn( op, tid,
|
|
- &ep->e_nname, eip );
|
|
- if ( *eip ) flag |= ID_LOCKED;
|
|
- if ( rc ) {
|
|
- ep->e_private = NULL;
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- bdb_entry_return( bdb, ep, (*eip)->bei_zseq );
|
|
-#else
|
|
- bdb_entry_return( ep );
|
|
-#endif
|
|
- ep = NULL;
|
|
- }
|
|
- }
|
|
-#else
|
|
- rc = hdb_cache_find_parent(op, tid, id, eip );
|
|
- if ( rc == 0 ) flag |= ID_LOCKED;
|
|
-#endif
|
|
- }
|
|
-
|
|
- /* Ok, we found the info, do we have the entry? */
|
|
- if ( rc == 0 ) {
|
|
- if ( !( flag & ID_LOCKED )) {
|
|
- bdb_cache_entryinfo_lock( *eip );
|
|
- flag |= ID_LOCKED;
|
|
- }
|
|
-
|
|
- if ( (*eip)->bei_state & CACHE_ENTRY_DELETED ) {
|
|
- rc = DB_NOTFOUND;
|
|
- } else {
|
|
- (*eip)->bei_finders++;
|
|
- (*eip)->bei_state |= CACHE_ENTRY_REFERENCED;
|
|
- if ( flag & ID_NOENTRY ) {
|
|
- bdb_cache_entryinfo_unlock( *eip );
|
|
- return 0;
|
|
- }
|
|
- /* Make sure only one thread tries to load the entry */
|
|
-load1:
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- if ((*eip)->bei_e && !slap_zn_validate(
|
|
- bdb->bi_cache.c_zctx, (*eip)->bei_e, (*eip)->bei_zseq)) {
|
|
- (*eip)->bei_e = NULL;
|
|
- (*eip)->bei_zseq = 0;
|
|
- }
|
|
-#endif
|
|
- if ( !(*eip)->bei_e && !((*eip)->bei_state & CACHE_ENTRY_LOADING)) {
|
|
- load = 1;
|
|
- (*eip)->bei_state |= CACHE_ENTRY_LOADING;
|
|
- flag |= ID_CHKPURGE;
|
|
- }
|
|
-
|
|
- if ( !load ) {
|
|
- /* Clear the uncached state if we are not
|
|
- * loading it, i.e it is already cached or
|
|
- * another thread is currently loading it.
|
|
- */
|
|
- if ( (*eip)->bei_state & CACHE_ENTRY_NOT_CACHED ) {
|
|
- (*eip)->bei_state ^= CACHE_ENTRY_NOT_CACHED;
|
|
- flag |= ID_CHKPURGE;
|
|
- }
|
|
- }
|
|
-
|
|
- if ( flag & ID_LOCKED ) {
|
|
- bdb_cache_entryinfo_unlock( *eip );
|
|
- flag ^= ID_LOCKED;
|
|
- }
|
|
- rc = bdb_cache_entry_db_lock( bdb, tid, *eip, load, 0, lock );
|
|
- if ( (*eip)->bei_state & CACHE_ENTRY_DELETED ) {
|
|
- rc = DB_NOTFOUND;
|
|
- bdb_cache_entry_db_unlock( bdb, lock );
|
|
- bdb_cache_entryinfo_lock( *eip );
|
|
- (*eip)->bei_finders--;
|
|
- bdb_cache_entryinfo_unlock( *eip );
|
|
- } else if ( rc == 0 ) {
|
|
- if ( load ) {
|
|
- if ( !ep) {
|
|
- rc = bdb_id2entry( op->o_bd, tid, id, &ep );
|
|
- }
|
|
- if ( rc == 0 ) {
|
|
- ep->e_private = *eip;
|
|
-#ifdef BDB_HIER
|
|
- while ( (*eip)->bei_state & CACHE_ENTRY_NOT_LINKED )
|
|
- ldap_pvt_thread_yield();
|
|
- bdb_fix_dn( ep, 0 );
|
|
-#endif
|
|
- bdb_cache_entryinfo_lock( *eip );
|
|
-
|
|
- (*eip)->bei_e = ep;
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- (*eip)->bei_zseq = *((ber_len_t *)ep - 2);
|
|
-#endif
|
|
- ep = NULL;
|
|
- if ( flag & ID_NOCACHE ) {
|
|
- /* Set the cached state only if no other thread
|
|
- * found the info while we were loading the entry.
|
|
- */
|
|
- if ( (*eip)->bei_finders == 1 ) {
|
|
- (*eip)->bei_state |= CACHE_ENTRY_NOT_CACHED;
|
|
- flag ^= ID_CHKPURGE;
|
|
- }
|
|
- }
|
|
- bdb_cache_entryinfo_unlock( *eip );
|
|
- bdb_cache_lru_link( bdb, *eip );
|
|
- }
|
|
- if ( rc == 0 ) {
|
|
- /* If we succeeded, downgrade back to a readlock. */
|
|
- rc = bdb_cache_entry_db_relock( bdb, tid,
|
|
- *eip, 0, 0, lock );
|
|
- } else {
|
|
- /* Otherwise, release the lock. */
|
|
- bdb_cache_entry_db_unlock( bdb, lock );
|
|
- }
|
|
- } else if ( !(*eip)->bei_e ) {
|
|
- /* Some other thread is trying to load the entry,
|
|
- * wait for it to finish.
|
|
- */
|
|
- bdb_cache_entry_db_unlock( bdb, lock );
|
|
- bdb_cache_entryinfo_lock( *eip );
|
|
- flag |= ID_LOCKED;
|
|
- goto load1;
|
|
-#ifdef BDB_HIER
|
|
- } else {
|
|
- /* Check for subtree renames
|
|
- */
|
|
- rc = bdb_fix_dn( (*eip)->bei_e, 1 );
|
|
- if ( rc ) {
|
|
- bdb_cache_entry_db_relock( bdb,
|
|
- tid, *eip, 1, 0, lock );
|
|
- /* check again in case other modifier did it already */
|
|
- if ( bdb_fix_dn( (*eip)->bei_e, 1 ) )
|
|
- rc = bdb_fix_dn( (*eip)->bei_e, 2 );
|
|
- bdb_cache_entry_db_relock( bdb,
|
|
- tid, *eip, 0, 0, lock );
|
|
- }
|
|
-#endif
|
|
- }
|
|
- bdb_cache_entryinfo_lock( *eip );
|
|
- (*eip)->bei_finders--;
|
|
- if ( load )
|
|
- (*eip)->bei_state ^= CACHE_ENTRY_LOADING;
|
|
- bdb_cache_entryinfo_unlock( *eip );
|
|
- }
|
|
- }
|
|
- }
|
|
- if ( flag & ID_LOCKED ) {
|
|
- bdb_cache_entryinfo_unlock( *eip );
|
|
- }
|
|
- if ( ep ) {
|
|
- ep->e_private = NULL;
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- bdb_entry_return( bdb, ep, (*eip)->bei_zseq );
|
|
-#else
|
|
- bdb_entry_return( ep );
|
|
-#endif
|
|
- }
|
|
- if ( rc == 0 ) {
|
|
- int purge = 0;
|
|
-
|
|
- if (( flag & ID_CHKPURGE ) || bdb->bi_cache.c_eimax ) {
|
|
- ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_count_mutex );
|
|
- if ( flag & ID_CHKPURGE ) {
|
|
- bdb->bi_cache.c_cursize++;
|
|
- if ( !bdb->bi_cache.c_purging && bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize ) {
|
|
- purge = 1;
|
|
- bdb->bi_cache.c_purging = 1;
|
|
- }
|
|
- } else if ( !bdb->bi_cache.c_purging && bdb->bi_cache.c_eimax && bdb->bi_cache.c_leaves > bdb->bi_cache.c_eimax ) {
|
|
- purge = 1;
|
|
- bdb->bi_cache.c_purging = 1;
|
|
- }
|
|
- ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_count_mutex );
|
|
- }
|
|
- if ( purge )
|
|
- bdb_cache_lru_purge( bdb );
|
|
- }
|
|
-
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- if (rc == 0 && (*eip)->bei_e) {
|
|
- slap_zn_rlock(bdb->bi_cache.c_zctx, (*eip)->bei_e);
|
|
- }
|
|
- slap_zh_runlock(bdb->bi_cache.c_zctx);
|
|
-#endif
|
|
- return rc;
|
|
-}
|
|
-
|
|
-int
|
|
-bdb_cache_children(
|
|
- Operation *op,
|
|
- DB_TXN *txn,
|
|
- Entry *e )
|
|
-{
|
|
- int rc;
|
|
-
|
|
- if ( BEI(e)->bei_kids ) {
|
|
- return 0;
|
|
- }
|
|
- if ( BEI(e)->bei_state & CACHE_ENTRY_NO_KIDS ) {
|
|
- return DB_NOTFOUND;
|
|
- }
|
|
- rc = bdb_dn2id_children( op, txn, e );
|
|
- if ( rc == DB_NOTFOUND ) {
|
|
- BEI(e)->bei_state |= CACHE_ENTRY_NO_KIDS | CACHE_ENTRY_NO_GRANDKIDS;
|
|
- }
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/* Update the cache after a successful database Add. */
|
|
-int
|
|
-bdb_cache_add(
|
|
- struct bdb_info *bdb,
|
|
- EntryInfo *eip,
|
|
- Entry *e,
|
|
- struct berval *nrdn,
|
|
- DB_TXN *txn,
|
|
- DB_LOCK *lock )
|
|
-{
|
|
- EntryInfo *new, ei;
|
|
- int rc, purge = 0;
|
|
-#ifdef BDB_HIER
|
|
- struct berval rdn = e->e_name;
|
|
-#endif
|
|
-
|
|
- ei.bei_id = e->e_id;
|
|
- ei.bei_parent = eip;
|
|
- ei.bei_nrdn = *nrdn;
|
|
- ei.bei_lockpad = 0;
|
|
-
|
|
-#if 0
|
|
- /* Lock this entry so that bdb_add can run to completion.
|
|
- * It can only fail if BDB has run out of lock resources.
|
|
- */
|
|
- rc = bdb_cache_entry_db_lock( bdb, txn, &ei, 0, 0, lock );
|
|
- if ( rc ) {
|
|
- bdb_cache_entryinfo_unlock( eip );
|
|
- return rc;
|
|
- }
|
|
-#endif
|
|
-
|
|
-#ifdef BDB_HIER
|
|
- if ( nrdn->bv_len != e->e_nname.bv_len ) {
|
|
- char *ptr = ber_bvchr( &rdn, ',' );
|
|
- assert( ptr != NULL );
|
|
- rdn.bv_len = ptr - rdn.bv_val;
|
|
- }
|
|
- ber_dupbv( &ei.bei_rdn, &rdn );
|
|
- if ( eip->bei_dkids ) eip->bei_dkids++;
|
|
-#endif
|
|
-
|
|
- if (eip->bei_parent) {
|
|
- bdb_cache_entryinfo_lock( eip->bei_parent );
|
|
- eip->bei_parent->bei_state &= ~CACHE_ENTRY_NO_GRANDKIDS;
|
|
- bdb_cache_entryinfo_unlock( eip->bei_parent );
|
|
- }
|
|
-
|
|
- rc = bdb_entryinfo_add_internal( bdb, &ei, &new );
|
|
- /* bdb_csn_commit can cause this when adding the database root entry */
|
|
- if ( new->bei_e ) {
|
|
- new->bei_e->e_private = NULL;
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- bdb_entry_return( bdb, new->bei_e, new->bei_zseq );
|
|
-#else
|
|
- bdb_entry_return( new->bei_e );
|
|
-#endif
|
|
- }
|
|
- new->bei_e = e;
|
|
- e->e_private = new;
|
|
- new->bei_state |= CACHE_ENTRY_NO_KIDS | CACHE_ENTRY_NO_GRANDKIDS;
|
|
- eip->bei_state &= ~CACHE_ENTRY_NO_KIDS;
|
|
- bdb_cache_entryinfo_unlock( eip );
|
|
-
|
|
- ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
|
|
- ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_count_mutex );
|
|
- ++bdb->bi_cache.c_cursize;
|
|
- if ( bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize &&
|
|
- !bdb->bi_cache.c_purging ) {
|
|
- purge = 1;
|
|
- bdb->bi_cache.c_purging = 1;
|
|
- }
|
|
- ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_count_mutex );
|
|
-
|
|
- new->bei_finders = 1;
|
|
- bdb_cache_lru_link( bdb, new );
|
|
-
|
|
- if ( purge )
|
|
- bdb_cache_lru_purge( bdb );
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-void bdb_cache_deref(
|
|
- EntryInfo *ei
|
|
- )
|
|
-{
|
|
- bdb_cache_entryinfo_lock( ei );
|
|
- ei->bei_finders--;
|
|
- bdb_cache_entryinfo_unlock( ei );
|
|
-}
|
|
-
|
|
-int
|
|
-bdb_cache_modify(
|
|
- struct bdb_info *bdb,
|
|
- Entry *e,
|
|
- Attribute *newAttrs,
|
|
- DB_TXN *txn,
|
|
- DB_LOCK *lock )
|
|
-{
|
|
- EntryInfo *ei = BEI(e);
|
|
- int rc;
|
|
- /* Get write lock on data */
|
|
- rc = bdb_cache_entry_db_relock( bdb, txn, ei, 1, 0, lock );
|
|
-
|
|
- /* If we've done repeated mods on a cached entry, then e_attrs
|
|
- * is no longer contiguous with the entry, and must be freed.
|
|
- */
|
|
- if ( ! rc ) {
|
|
- if ( (void *)e->e_attrs != (void *)(e+1) ) {
|
|
- attrs_free( e->e_attrs );
|
|
- }
|
|
- e->e_attrs = newAttrs;
|
|
- }
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Change the rdn in the entryinfo. Also move to a new parent if needed.
|
|
- */
|
|
-int
|
|
-bdb_cache_modrdn(
|
|
- struct bdb_info *bdb,
|
|
- Entry *e,
|
|
- struct berval *nrdn,
|
|
- Entry *new,
|
|
- EntryInfo *ein,
|
|
- DB_TXN *txn,
|
|
- DB_LOCK *lock )
|
|
-{
|
|
- EntryInfo *ei = BEI(e), *pei;
|
|
- int rc;
|
|
-#ifdef BDB_HIER
|
|
- struct berval rdn;
|
|
-#endif
|
|
-
|
|
- /* Get write lock on data */
|
|
- rc = bdb_cache_entry_db_relock( bdb, txn, ei, 1, 0, lock );
|
|
- if ( rc ) return rc;
|
|
-
|
|
- /* If we've done repeated mods on a cached entry, then e_attrs
|
|
- * is no longer contiguous with the entry, and must be freed.
|
|
- */
|
|
- if ( (void *)e->e_attrs != (void *)(e+1) ) {
|
|
- attrs_free( e->e_attrs );
|
|
- }
|
|
- e->e_attrs = new->e_attrs;
|
|
- if( e->e_nname.bv_val < e->e_bv.bv_val ||
|
|
- e->e_nname.bv_val > e->e_bv.bv_val + e->e_bv.bv_len )
|
|
- {
|
|
- ch_free(e->e_name.bv_val);
|
|
- ch_free(e->e_nname.bv_val);
|
|
- }
|
|
- e->e_name = new->e_name;
|
|
- e->e_nname = new->e_nname;
|
|
-
|
|
- /* Lock the parent's kids AVL tree */
|
|
- pei = ei->bei_parent;
|
|
- bdb_cache_entryinfo_lock( pei );
|
|
- avl_delete( &pei->bei_kids, (caddr_t) ei, bdb_rdn_cmp );
|
|
- free( ei->bei_nrdn.bv_val );
|
|
- ber_dupbv( &ei->bei_nrdn, nrdn );
|
|
-
|
|
-#ifdef BDB_HIER
|
|
- free( ei->bei_rdn.bv_val );
|
|
-
|
|
- rdn = e->e_name;
|
|
- if ( nrdn->bv_len != e->e_nname.bv_len ) {
|
|
- char *ptr = ber_bvchr(&rdn, ',');
|
|
- assert( ptr != NULL );
|
|
- rdn.bv_len = ptr - rdn.bv_val;
|
|
- }
|
|
- ber_dupbv( &ei->bei_rdn, &rdn );
|
|
-
|
|
- /* If new parent, decrement kid counts */
|
|
- if ( ein ) {
|
|
- pei->bei_ckids--;
|
|
- if ( pei->bei_dkids ) {
|
|
- pei->bei_dkids--;
|
|
- if ( pei->bei_dkids < 2 )
|
|
- pei->bei_state |= CACHE_ENTRY_NO_KIDS | CACHE_ENTRY_NO_GRANDKIDS;
|
|
- }
|
|
- }
|
|
-#endif
|
|
-
|
|
- if (!ein) {
|
|
- ein = ei->bei_parent;
|
|
- } else {
|
|
- ei->bei_parent = ein;
|
|
- bdb_cache_entryinfo_unlock( pei );
|
|
- bdb_cache_entryinfo_lock( ein );
|
|
-
|
|
- /* new parent now has kids */
|
|
- if ( ein->bei_state & CACHE_ENTRY_NO_KIDS )
|
|
- ein->bei_state ^= CACHE_ENTRY_NO_KIDS;
|
|
- /* grandparent has grandkids */
|
|
- if ( ein->bei_parent )
|
|
- ein->bei_parent->bei_state &= ~CACHE_ENTRY_NO_GRANDKIDS;
|
|
-#ifdef BDB_HIER
|
|
- /* parent might now have grandkids */
|
|
- if ( ein->bei_state & CACHE_ENTRY_NO_GRANDKIDS &&
|
|
- !(ei->bei_state & CACHE_ENTRY_NO_KIDS))
|
|
- ein->bei_state ^= CACHE_ENTRY_NO_GRANDKIDS;
|
|
-
|
|
- ein->bei_ckids++;
|
|
- if ( ein->bei_dkids ) ein->bei_dkids++;
|
|
-#endif
|
|
- }
|
|
-
|
|
-#ifdef BDB_HIER
|
|
- /* Record the generation number of this change */
|
|
- ldap_pvt_thread_mutex_lock( &bdb->bi_modrdns_mutex );
|
|
- bdb->bi_modrdns++;
|
|
- ei->bei_modrdns = bdb->bi_modrdns;
|
|
- ldap_pvt_thread_mutex_unlock( &bdb->bi_modrdns_mutex );
|
|
-#endif
|
|
-
|
|
- avl_insert( &ein->bei_kids, ei, bdb_rdn_cmp, avl_dup_error );
|
|
- bdb_cache_entryinfo_unlock( ein );
|
|
- return rc;
|
|
-}
|
|
-/*
|
|
- * cache_delete - delete the entry e from the cache.
|
|
- *
|
|
- * returns: 0 e was deleted ok
|
|
- * 1 e was not in the cache
|
|
- * -1 something bad happened
|
|
- */
|
|
-int
|
|
-bdb_cache_delete(
|
|
- struct bdb_info *bdb,
|
|
- Entry *e,
|
|
- DB_TXN *txn,
|
|
- DB_LOCK *lock )
|
|
-{
|
|
- EntryInfo *ei = BEI(e);
|
|
- int rc, busy = 0, counter = 0;
|
|
-
|
|
- assert( e->e_private != NULL );
|
|
-
|
|
- /* Lock the entry's info */
|
|
- bdb_cache_entryinfo_lock( ei );
|
|
-
|
|
- /* Set this early, warn off any queriers */
|
|
- ei->bei_state |= CACHE_ENTRY_DELETED;
|
|
-
|
|
- if (( ei->bei_state & ( CACHE_ENTRY_NOT_LINKED |
|
|
- CACHE_ENTRY_LOADING | CACHE_ENTRY_ONELEVEL )) ||
|
|
- ei->bei_finders > 0 )
|
|
- busy = 1;
|
|
-
|
|
- bdb_cache_entryinfo_unlock( ei );
|
|
-
|
|
- while ( busy && counter < 1000) {
|
|
- ldap_pvt_thread_yield();
|
|
- busy = 0;
|
|
- bdb_cache_entryinfo_lock( ei );
|
|
- if (( ei->bei_state & ( CACHE_ENTRY_NOT_LINKED |
|
|
- CACHE_ENTRY_LOADING | CACHE_ENTRY_ONELEVEL )) ||
|
|
- ei->bei_finders > 0 )
|
|
- busy = 1;
|
|
- bdb_cache_entryinfo_unlock( ei );
|
|
- counter ++;
|
|
- }
|
|
- if( busy ) {
|
|
- bdb_cache_entryinfo_lock( ei );
|
|
- ei->bei_state ^= CACHE_ENTRY_DELETED;
|
|
- bdb_cache_entryinfo_unlock( ei );
|
|
- return DB_LOCK_DEADLOCK;
|
|
- }
|
|
-
|
|
- /* Get write lock on the data */
|
|
- rc = bdb_cache_entry_db_relock( bdb, txn, ei, 1, 0, lock );
|
|
- if ( rc ) {
|
|
- bdb_cache_entryinfo_lock( ei );
|
|
- /* couldn't lock, undo and give up */
|
|
- ei->bei_state ^= CACHE_ENTRY_DELETED;
|
|
- bdb_cache_entryinfo_unlock( ei );
|
|
- return rc;
|
|
- }
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "====> bdb_cache_delete( %ld )\n",
|
|
- e->e_id, 0, 0 );
|
|
-
|
|
- /* set lru mutex */
|
|
- ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_lru_mutex );
|
|
-
|
|
- bdb_cache_entryinfo_lock( ei->bei_parent );
|
|
- bdb_cache_entryinfo_lock( ei );
|
|
- rc = bdb_cache_delete_internal( &bdb->bi_cache, e->e_private, 1 );
|
|
- bdb_cache_entryinfo_unlock( ei );
|
|
-
|
|
- /* free lru mutex */
|
|
- ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_lru_mutex );
|
|
-
|
|
- return( rc );
|
|
-}
|
|
-
|
|
-void
|
|
-bdb_cache_delete_cleanup(
|
|
- Cache *cache,
|
|
- EntryInfo *ei )
|
|
-{
|
|
- /* Enter with ei locked */
|
|
-
|
|
- /* already freed? */
|
|
- if ( !ei->bei_parent ) return;
|
|
-
|
|
- if ( ei->bei_e ) {
|
|
- ei->bei_e->e_private = NULL;
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- bdb_entry_return( ei->bei_bdb, ei->bei_e, ei->bei_zseq );
|
|
-#else
|
|
- bdb_entry_return( ei->bei_e );
|
|
-#endif
|
|
- ei->bei_e = NULL;
|
|
- }
|
|
-
|
|
- bdb_cache_entryinfo_unlock( ei );
|
|
- bdb_cache_entryinfo_free( cache, ei );
|
|
-}
|
|
-
|
|
-static int
|
|
-bdb_cache_delete_internal(
|
|
- Cache *cache,
|
|
- EntryInfo *e,
|
|
- int decr )
|
|
-{
|
|
- int rc = 0; /* return code */
|
|
- int decr_leaf = 0;
|
|
-
|
|
- /* already freed? */
|
|
- if ( !e->bei_parent ) {
|
|
- assert(0);
|
|
- return -1;
|
|
- }
|
|
-
|
|
-#ifdef BDB_HIER
|
|
- e->bei_parent->bei_ckids--;
|
|
- if ( decr && e->bei_parent->bei_dkids ) e->bei_parent->bei_dkids--;
|
|
-#endif
|
|
- /* dn tree */
|
|
- if ( avl_delete( &e->bei_parent->bei_kids, (caddr_t) e, bdb_rdn_cmp )
|
|
- == NULL )
|
|
- {
|
|
- rc = -1;
|
|
- assert(0);
|
|
- }
|
|
- if ( e->bei_parent->bei_kids )
|
|
- decr_leaf = 1;
|
|
-
|
|
- ldap_pvt_thread_rdwr_wlock( &cache->c_rwlock );
|
|
- /* id tree */
|
|
- if ( avl_delete( &cache->c_idtree, (caddr_t) e, bdb_id_cmp )) {
|
|
- cache->c_eiused--;
|
|
- if ( decr_leaf )
|
|
- cache->c_leaves--;
|
|
- } else {
|
|
- rc = -1;
|
|
- assert(0);
|
|
- }
|
|
- ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
|
|
- bdb_cache_entryinfo_unlock( e->bei_parent );
|
|
-
|
|
- if ( rc == 0 ){
|
|
- /* lru */
|
|
- LRU_DEL( cache, e );
|
|
-
|
|
- if ( e->bei_e ) {
|
|
- ldap_pvt_thread_mutex_lock( &cache->c_count_mutex );
|
|
- cache->c_cursize--;
|
|
- ldap_pvt_thread_mutex_unlock( &cache->c_count_mutex );
|
|
- }
|
|
- }
|
|
-
|
|
- return( rc );
|
|
-}
|
|
-
|
|
-static void
|
|
-bdb_entryinfo_release( void *data )
|
|
-{
|
|
- EntryInfo *ei = (EntryInfo *)data;
|
|
- if ( ei->bei_kids ) {
|
|
- avl_free( ei->bei_kids, NULL );
|
|
- }
|
|
- if ( ei->bei_e ) {
|
|
- ei->bei_e->e_private = NULL;
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- bdb_entry_return( ei->bei_bdb, ei->bei_e, ei->bei_zseq );
|
|
-#else
|
|
- bdb_entry_return( ei->bei_e );
|
|
-#endif
|
|
- }
|
|
- bdb_cache_entryinfo_destroy( ei );
|
|
-}
|
|
-
|
|
-void
|
|
-bdb_cache_release_all( Cache *cache )
|
|
-{
|
|
- /* set cache write lock */
|
|
- ldap_pvt_thread_rdwr_wlock( &cache->c_rwlock );
|
|
- /* set lru mutex */
|
|
- ldap_pvt_thread_mutex_lock( &cache->c_lru_mutex );
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "====> bdb_cache_release_all\n", 0, 0, 0 );
|
|
-
|
|
- avl_free( cache->c_dntree.bei_kids, NULL );
|
|
- avl_free( cache->c_idtree, bdb_entryinfo_release );
|
|
- for (;cache->c_eifree;cache->c_eifree = cache->c_lruhead) {
|
|
- cache->c_lruhead = cache->c_eifree->bei_lrunext;
|
|
- bdb_cache_entryinfo_destroy(cache->c_eifree);
|
|
- }
|
|
- cache->c_cursize = 0;
|
|
- cache->c_eiused = 0;
|
|
- cache->c_leaves = 0;
|
|
- cache->c_idtree = NULL;
|
|
- cache->c_lruhead = NULL;
|
|
- cache->c_lrutail = NULL;
|
|
- cache->c_dntree.bei_kids = NULL;
|
|
-
|
|
- /* free lru mutex */
|
|
- ldap_pvt_thread_mutex_unlock( &cache->c_lru_mutex );
|
|
- /* free cache write lock */
|
|
- ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
|
|
-}
|
|
-
|
|
-#ifdef LDAP_DEBUG
|
|
-static void
|
|
-bdb_lru_count( Cache *cache )
|
|
-{
|
|
- EntryInfo *e;
|
|
- int ei = 0, ent = 0, nc = 0;
|
|
-
|
|
- for ( e = cache->c_lrutail; ; ) {
|
|
- ei++;
|
|
- if ( e->bei_e ) {
|
|
- ent++;
|
|
- if ( e->bei_state & CACHE_ENTRY_NOT_CACHED )
|
|
- nc++;
|
|
- fprintf( stderr, "ei %d entry %p dn %s\n", ei, (void *) e->bei_e, e->bei_e->e_name.bv_val );
|
|
- }
|
|
- e = e->bei_lrunext;
|
|
- if ( e == cache->c_lrutail )
|
|
- break;
|
|
- }
|
|
- fprintf( stderr, "counted %d entryInfos and %d entries, %d notcached\n",
|
|
- ei, ent, nc );
|
|
- ei = 0;
|
|
- for ( e = cache->c_lrutail; ; ) {
|
|
- ei++;
|
|
- e = e->bei_lruprev;
|
|
- if ( e == cache->c_lrutail )
|
|
- break;
|
|
- }
|
|
- fprintf( stderr, "counted %d entryInfos (on lruprev)\n", ei );
|
|
-}
|
|
-
|
|
-#ifdef SLAPD_UNUSED
|
|
-static void
|
|
-bdb_lru_print( Cache *cache )
|
|
-{
|
|
- EntryInfo *e;
|
|
-
|
|
- fprintf( stderr, "LRU circle head: %p\n", (void *) cache->c_lruhead );
|
|
- fprintf( stderr, "LRU circle (tail forward):\n" );
|
|
- for ( e = cache->c_lrutail; ; ) {
|
|
- fprintf( stderr, "\t%p, %p id %ld rdn \"%s\"\n",
|
|
- (void *) e, (void *) e->bei_e, e->bei_id, e->bei_nrdn.bv_val );
|
|
- e = e->bei_lrunext;
|
|
- if ( e == cache->c_lrutail )
|
|
- break;
|
|
- }
|
|
- fprintf( stderr, "LRU circle (tail backward):\n" );
|
|
- for ( e = cache->c_lrutail; ; ) {
|
|
- fprintf( stderr, "\t%p, %p id %ld rdn \"%s\"\n",
|
|
- (void *) e, (void *) e->bei_e, e->bei_id, e->bei_nrdn.bv_val );
|
|
- e = e->bei_lruprev;
|
|
- if ( e == cache->c_lrutail )
|
|
- break;
|
|
- }
|
|
-}
|
|
-
|
|
-static int
|
|
-bdb_entryinfo_print(void *data, void *arg)
|
|
-{
|
|
- EntryInfo *e = data;
|
|
- fprintf( stderr, "\t%p, %p id %ld rdn \"%s\"\n",
|
|
- (void *) e, (void *) e->bei_e, e->bei_id, e->bei_nrdn.bv_val );
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static void
|
|
-bdb_idtree_print(Cache *cache)
|
|
-{
|
|
- avl_apply( cache->c_idtree, bdb_entryinfo_print, NULL, -1, AVL_INORDER );
|
|
-}
|
|
-#endif
|
|
-#endif
|
|
-
|
|
-static void
|
|
-bdb_reader_free( void *key, void *data )
|
|
-{
|
|
- /* DB_ENV *env = key; */
|
|
- DB_TXN *txn = data;
|
|
-
|
|
- if ( txn ) TXN_ABORT( txn );
|
|
-}
|
|
-
|
|
-/* free up any keys used by the main thread */
|
|
-void
|
|
-bdb_reader_flush( DB_ENV *env )
|
|
-{
|
|
- void *data;
|
|
- void *ctx = ldap_pvt_thread_pool_context();
|
|
-
|
|
- if ( !ldap_pvt_thread_pool_getkey( ctx, env, &data, NULL ) ) {
|
|
- ldap_pvt_thread_pool_setkey( ctx, env, NULL, 0, NULL, NULL );
|
|
- bdb_reader_free( env, data );
|
|
- }
|
|
-}
|
|
-
|
|
-int
|
|
-bdb_reader_get( Operation *op, DB_ENV *env, DB_TXN **txn )
|
|
-{
|
|
- int i, rc;
|
|
- void *data;
|
|
- void *ctx;
|
|
-
|
|
- if ( !env || !txn ) return -1;
|
|
-
|
|
- /* If no op was provided, try to find the ctx anyway... */
|
|
- if ( op ) {
|
|
- ctx = op->o_threadctx;
|
|
- } else {
|
|
- ctx = ldap_pvt_thread_pool_context();
|
|
- }
|
|
-
|
|
- /* Shouldn't happen unless we're single-threaded */
|
|
- if ( !ctx ) {
|
|
- *txn = NULL;
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if ( ldap_pvt_thread_pool_getkey( ctx, env, &data, NULL ) ) {
|
|
- for ( i=0, rc=1; rc != 0 && i<4; i++ ) {
|
|
- rc = TXN_BEGIN( env, NULL, txn, DB_READ_COMMITTED );
|
|
- if (rc) ldap_pvt_thread_yield();
|
|
- }
|
|
- if ( rc != 0) {
|
|
- return rc;
|
|
- }
|
|
- data = *txn;
|
|
- if ( ( rc = ldap_pvt_thread_pool_setkey( ctx, env,
|
|
- data, bdb_reader_free, NULL, NULL ) ) ) {
|
|
- TXN_ABORT( *txn );
|
|
- Debug( LDAP_DEBUG_ANY, "bdb_reader_get: err %s(%d)\n",
|
|
- db_strerror(rc), rc, 0 );
|
|
-
|
|
- return rc;
|
|
- }
|
|
- } else {
|
|
- *txn = data;
|
|
- }
|
|
- return 0;
|
|
-}
|
|
diff --git a/servers/slapd/back-bdb/compare.c b/servers/slapd/back-bdb/compare.c
|
|
deleted file mode 100644
|
|
index 4d7d45f..0000000
|
|
--- a/servers/slapd/back-bdb/compare.c
|
|
+++ /dev/null
|
|
@@ -1,143 +0,0 @@
|
|
-/* compare.c - bdb backend compare routine */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-
|
|
-#include <stdio.h>
|
|
-#include <ac/string.h>
|
|
-
|
|
-#include "back-bdb.h"
|
|
-
|
|
-int
|
|
-bdb_compare( Operation *op, SlapReply *rs )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- Entry *e = NULL;
|
|
- EntryInfo *ei;
|
|
- int manageDSAit = get_manageDSAit( op );
|
|
-
|
|
- DB_TXN *rtxn;
|
|
- DB_LOCK lock;
|
|
-
|
|
- rs->sr_err = bdb_reader_get(op, bdb->bi_dbenv, &rtxn);
|
|
- switch(rs->sr_err) {
|
|
- case 0:
|
|
- break;
|
|
- default:
|
|
- send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
|
|
- return rs->sr_err;
|
|
- }
|
|
-
|
|
-dn2entry_retry:
|
|
- /* get entry */
|
|
- rs->sr_err = bdb_dn2entry( op, rtxn, &op->o_req_ndn, &ei, 1,
|
|
- &lock );
|
|
-
|
|
- switch( rs->sr_err ) {
|
|
- case DB_NOTFOUND:
|
|
- case 0:
|
|
- break;
|
|
- case LDAP_BUSY:
|
|
- rs->sr_text = "ldap server busy";
|
|
- goto return_results;
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto dn2entry_retry;
|
|
- default:
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "internal error";
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- e = ei->bei_e;
|
|
- if ( rs->sr_err == DB_NOTFOUND ) {
|
|
- if ( e != NULL ) {
|
|
- /* return referral only if "disclose" is granted on the object */
|
|
- if ( ! access_allowed( op, e, slap_schema.si_ad_entry,
|
|
- NULL, ACL_DISCLOSE, NULL ) )
|
|
- {
|
|
- rs->sr_err = LDAP_NO_SUCH_OBJECT;
|
|
-
|
|
- } else {
|
|
- rs->sr_matched = ch_strdup( e->e_dn );
|
|
- rs->sr_ref = is_entry_referral( e )
|
|
- ? get_entry_referrals( op, e )
|
|
- : NULL;
|
|
- rs->sr_err = LDAP_REFERRAL;
|
|
- }
|
|
-
|
|
- bdb_cache_return_entry_r( bdb, e, &lock );
|
|
- e = NULL;
|
|
-
|
|
- } else {
|
|
- rs->sr_ref = referral_rewrite( default_referral,
|
|
- NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
|
|
- rs->sr_err = rs->sr_ref ? LDAP_REFERRAL : LDAP_NO_SUCH_OBJECT;
|
|
- }
|
|
-
|
|
- send_ldap_result( op, rs );
|
|
-
|
|
- ber_bvarray_free( rs->sr_ref );
|
|
- free( (char *)rs->sr_matched );
|
|
- rs->sr_ref = NULL;
|
|
- rs->sr_matched = NULL;
|
|
-
|
|
- goto done;
|
|
- }
|
|
-
|
|
- if (!manageDSAit && is_entry_referral( e ) ) {
|
|
- /* return referral only if "disclose" is granted on the object */
|
|
- if ( !access_allowed( op, e, slap_schema.si_ad_entry,
|
|
- NULL, ACL_DISCLOSE, NULL ) )
|
|
- {
|
|
- rs->sr_err = LDAP_NO_SUCH_OBJECT;
|
|
- } else {
|
|
- /* entry is a referral, don't allow compare */
|
|
- rs->sr_ref = get_entry_referrals( op, e );
|
|
- rs->sr_err = LDAP_REFERRAL;
|
|
- rs->sr_matched = e->e_name.bv_val;
|
|
- }
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 );
|
|
-
|
|
- send_ldap_result( op, rs );
|
|
-
|
|
- ber_bvarray_free( rs->sr_ref );
|
|
- rs->sr_ref = NULL;
|
|
- rs->sr_matched = NULL;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- rs->sr_err = slap_compare_entry( op, e, op->orc_ava );
|
|
-
|
|
-return_results:
|
|
- send_ldap_result( op, rs );
|
|
-
|
|
- switch ( rs->sr_err ) {
|
|
- case LDAP_COMPARE_FALSE:
|
|
- case LDAP_COMPARE_TRUE:
|
|
- rs->sr_err = LDAP_SUCCESS;
|
|
- break;
|
|
- }
|
|
-
|
|
-done:
|
|
- /* free entry */
|
|
- if ( e != NULL ) {
|
|
- bdb_cache_return_entry_r( bdb, e, &lock );
|
|
- }
|
|
-
|
|
- return rs->sr_err;
|
|
-}
|
|
diff --git a/servers/slapd/back-bdb/config.c b/servers/slapd/back-bdb/config.c
|
|
deleted file mode 100644
|
|
index c3c8315..0000000
|
|
--- a/servers/slapd/back-bdb/config.c
|
|
+++ /dev/null
|
|
@@ -1,951 +0,0 @@
|
|
-/* config.c - bdb backend configuration file routine */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-
|
|
-#include <stdio.h>
|
|
-#include <ac/ctype.h>
|
|
-#include <ac/string.h>
|
|
-#include <ac/errno.h>
|
|
-
|
|
-#include "back-bdb.h"
|
|
-
|
|
-#include "config.h"
|
|
-
|
|
-#include "lutil.h"
|
|
-#include "ldap_rq.h"
|
|
-
|
|
-#ifdef DB_DIRTY_READ
|
|
-# define SLAP_BDB_ALLOW_DIRTY_READ
|
|
-#endif
|
|
-
|
|
-#define bdb_cf_gen BDB_SYMBOL(cf_gen)
|
|
-#define bdb_cf_cleanup BDB_SYMBOL(cf_cleanup)
|
|
-#define bdb_checkpoint BDB_SYMBOL(checkpoint)
|
|
-#define bdb_online_index BDB_SYMBOL(online_index)
|
|
-
|
|
-static ConfigDriver bdb_cf_gen;
|
|
-
|
|
-enum {
|
|
- BDB_CHKPT = 1,
|
|
- BDB_CONFIG,
|
|
- BDB_CRYPTFILE,
|
|
- BDB_CRYPTKEY,
|
|
- BDB_DIRECTORY,
|
|
- BDB_NOSYNC,
|
|
- BDB_DIRTYR,
|
|
- BDB_INDEX,
|
|
- BDB_LOCKD,
|
|
- BDB_SSTACK,
|
|
- BDB_MODE,
|
|
- BDB_PGSIZE,
|
|
- BDB_CHECKSUM
|
|
-};
|
|
-
|
|
-static ConfigTable bdbcfg[] = {
|
|
- { "directory", "dir", 2, 2, 0, ARG_STRING|ARG_MAGIC|BDB_DIRECTORY,
|
|
- bdb_cf_gen, "( OLcfgDbAt:0.1 NAME 'olcDbDirectory' "
|
|
- "DESC 'Directory for database content' "
|
|
- "EQUALITY caseIgnoreMatch "
|
|
- "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
|
|
- { "cachefree", "size", 2, 2, 0, ARG_ULONG|ARG_OFFSET,
|
|
- (void *)offsetof(struct bdb_info, bi_cache.c_minfree),
|
|
- "( OLcfgDbAt:1.11 NAME 'olcDbCacheFree' "
|
|
- "DESC 'Number of extra entries to free when max is reached' "
|
|
- "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
|
|
- { "cachesize", "size", 2, 2, 0, ARG_ULONG|ARG_OFFSET,
|
|
- (void *)offsetof(struct bdb_info, bi_cache.c_maxsize),
|
|
- "( OLcfgDbAt:1.1 NAME 'olcDbCacheSize' "
|
|
- "DESC 'Entry cache size in entries' "
|
|
- "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
|
|
- { "checkpoint", "kbyte> <min", 3, 3, 0, ARG_MAGIC|BDB_CHKPT,
|
|
- bdb_cf_gen, "( OLcfgDbAt:1.2 NAME 'olcDbCheckpoint' "
|
|
- "DESC 'Database checkpoint interval in kbytes and minutes' "
|
|
- "SYNTAX OMsDirectoryString SINGLE-VALUE )",NULL, NULL },
|
|
- { "checksum", NULL, 1, 2, 0, ARG_ON_OFF|ARG_MAGIC|BDB_CHECKSUM,
|
|
- bdb_cf_gen, "( OLcfgDbAt:1.16 NAME 'olcDbChecksum' "
|
|
- "DESC 'Enable database checksum validation' "
|
|
- "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
|
|
- { "cryptfile", "file", 2, 2, 0, ARG_STRING|ARG_MAGIC|BDB_CRYPTFILE,
|
|
- bdb_cf_gen, "( OLcfgDbAt:1.13 NAME 'olcDbCryptFile' "
|
|
- "DESC 'Pathname of file containing the DB encryption key' "
|
|
- "SYNTAX OMsDirectoryString SINGLE-VALUE )",NULL, NULL },
|
|
- { "cryptkey", "key", 2, 2, 0, ARG_BERVAL|ARG_MAGIC|BDB_CRYPTKEY,
|
|
- bdb_cf_gen, "( OLcfgDbAt:1.14 NAME 'olcDbCryptKey' "
|
|
- "DESC 'DB encryption key' "
|
|
- "SYNTAX OMsOctetString SINGLE-VALUE )",NULL, NULL },
|
|
- { "dbconfig", "DB_CONFIG setting", 1, 0, 0, ARG_MAGIC|BDB_CONFIG,
|
|
- bdb_cf_gen, "( OLcfgDbAt:1.3 NAME 'olcDbConfig' "
|
|
- "DESC 'BerkeleyDB DB_CONFIG configuration directives' "
|
|
- "SYNTAX OMsIA5String X-ORDERED 'VALUES' )", NULL, NULL },
|
|
- { "dbnosync", NULL, 1, 2, 0, ARG_ON_OFF|ARG_MAGIC|BDB_NOSYNC,
|
|
- bdb_cf_gen, "( OLcfgDbAt:1.4 NAME 'olcDbNoSync' "
|
|
- "DESC 'Disable synchronous database writes' "
|
|
- "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
|
|
- { "dbpagesize", "db> <size", 3, 3, 0, ARG_MAGIC|BDB_PGSIZE,
|
|
- bdb_cf_gen, "( OLcfgDbAt:1.15 NAME 'olcDbPageSize' "
|
|
- "DESC 'Page size of specified DB, in Kbytes' "
|
|
- "EQUALITY caseExactMatch "
|
|
- "SYNTAX OMsDirectoryString )", NULL, NULL },
|
|
- { "dirtyread", NULL, 1, 2, 0,
|
|
-#ifdef SLAP_BDB_ALLOW_DIRTY_READ
|
|
- ARG_ON_OFF|ARG_MAGIC|BDB_DIRTYR, bdb_cf_gen,
|
|
-#else
|
|
- ARG_IGNORED, NULL,
|
|
-#endif
|
|
- "( OLcfgDbAt:1.5 NAME 'olcDbDirtyRead' "
|
|
- "DESC 'Allow reads of uncommitted data' "
|
|
- "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
|
|
- { "dncachesize", "size", 2, 2, 0, ARG_ULONG|ARG_OFFSET,
|
|
- (void *)offsetof(struct bdb_info, bi_cache.c_eimax),
|
|
- "( OLcfgDbAt:1.12 NAME 'olcDbDNcacheSize' "
|
|
- "DESC 'DN cache size' "
|
|
- "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
|
|
- { "idlcachesize", "size", 2, 2, 0, ARG_ULONG|ARG_OFFSET,
|
|
- (void *)offsetof(struct bdb_info, bi_idl_cache_max_size),
|
|
- "( OLcfgDbAt:1.6 NAME 'olcDbIDLcacheSize' "
|
|
- "DESC 'IDL cache size in IDLs' "
|
|
- "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
|
|
- { "index", "attr> <[pres,eq,approx,sub]", 2, 3, 0, ARG_MAGIC|BDB_INDEX,
|
|
- bdb_cf_gen, "( OLcfgDbAt:0.2 NAME 'olcDbIndex' "
|
|
- "DESC 'Attribute index parameters' "
|
|
- "EQUALITY caseIgnoreMatch "
|
|
- "SYNTAX OMsDirectoryString )", NULL, NULL },
|
|
- { "linearindex", NULL, 1, 2, 0, ARG_ON_OFF|ARG_OFFSET,
|
|
- (void *)offsetof(struct bdb_info, bi_linear_index),
|
|
- "( OLcfgDbAt:1.7 NAME 'olcDbLinearIndex' "
|
|
- "DESC 'Index attributes one at a time' "
|
|
- "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
|
|
- { "lockdetect", "policy", 2, 2, 0, ARG_MAGIC|BDB_LOCKD,
|
|
- bdb_cf_gen, "( OLcfgDbAt:1.8 NAME 'olcDbLockDetect' "
|
|
- "DESC 'Deadlock detection algorithm' "
|
|
- "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
|
|
- { "mode", "mode", 2, 2, 0, ARG_MAGIC|BDB_MODE,
|
|
- bdb_cf_gen, "( OLcfgDbAt:0.3 NAME 'olcDbMode' "
|
|
- "DESC 'Unix permissions of database files' "
|
|
- "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
|
|
- { "searchstack", "depth", 2, 2, 0, ARG_INT|ARG_MAGIC|BDB_SSTACK,
|
|
- bdb_cf_gen, "( OLcfgDbAt:1.9 NAME 'olcDbSearchStack' "
|
|
- "DESC 'Depth of search stack in IDLs' "
|
|
- "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
|
|
- { "shm_key", "key", 2, 2, 0, ARG_LONG|ARG_OFFSET,
|
|
- (void *)offsetof(struct bdb_info, bi_shm_key),
|
|
- "( OLcfgDbAt:1.10 NAME 'olcDbShmKey' "
|
|
- "DESC 'Key for shared memory region' "
|
|
- "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
|
|
- { NULL, NULL, 0, 0, 0, ARG_IGNORED,
|
|
- NULL, NULL, NULL, NULL }
|
|
-};
|
|
-
|
|
-static ConfigOCs bdbocs[] = {
|
|
- {
|
|
-#ifdef BDB_HIER
|
|
- "( OLcfgDbOc:1.2 "
|
|
- "NAME 'olcHdbConfig' "
|
|
- "DESC 'HDB backend configuration' "
|
|
-#else
|
|
- "( OLcfgDbOc:1.1 "
|
|
- "NAME 'olcBdbConfig' "
|
|
- "DESC 'BDB backend configuration' "
|
|
-#endif
|
|
- "SUP olcDatabaseConfig "
|
|
- "MUST olcDbDirectory "
|
|
- "MAY ( olcDbCacheSize $ olcDbCheckpoint $ olcDbChecksum $ "
|
|
- "olcDbConfig $ olcDbCryptFile $ olcDbCryptKey $ "
|
|
- "olcDbNoSync $ olcDbDirtyRead $ olcDbIDLcacheSize $ "
|
|
- "olcDbIndex $ olcDbLinearIndex $ olcDbLockDetect $ "
|
|
- "olcDbMode $ olcDbSearchStack $ olcDbShmKey $ "
|
|
- "olcDbCacheFree $ olcDbDNcacheSize $ olcDbPageSize ) )",
|
|
- Cft_Database, bdbcfg },
|
|
- { NULL, 0, NULL }
|
|
-};
|
|
-
|
|
-static slap_verbmasks bdb_lockd[] = {
|
|
- { BER_BVC("default"), DB_LOCK_DEFAULT },
|
|
- { BER_BVC("oldest"), DB_LOCK_OLDEST },
|
|
- { BER_BVC("random"), DB_LOCK_RANDOM },
|
|
- { BER_BVC("youngest"), DB_LOCK_YOUNGEST },
|
|
- { BER_BVC("fewest"), DB_LOCK_MINLOCKS },
|
|
- { BER_BVNULL, 0 }
|
|
-};
|
|
-
|
|
-/* perform periodic checkpoints */
|
|
-static void *
|
|
-bdb_checkpoint( void *ctx, void *arg )
|
|
-{
|
|
- struct re_s *rtask = arg;
|
|
- struct bdb_info *bdb = rtask->arg;
|
|
-
|
|
- TXN_CHECKPOINT( bdb->bi_dbenv, bdb->bi_txn_cp_kbyte,
|
|
- bdb->bi_txn_cp_min, 0 );
|
|
- ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
|
|
- ldap_pvt_runqueue_stoptask( &slapd_rq, rtask );
|
|
- ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
|
|
- return NULL;
|
|
-}
|
|
-
|
|
-/* reindex entries on the fly */
|
|
-static void *
|
|
-bdb_online_index( void *ctx, void *arg )
|
|
-{
|
|
- struct re_s *rtask = arg;
|
|
- BackendDB *be = rtask->arg;
|
|
- struct bdb_info *bdb = be->be_private;
|
|
-
|
|
- Connection conn = {0};
|
|
- OperationBuffer opbuf;
|
|
- Operation *op;
|
|
-
|
|
- DBC *curs;
|
|
- DBT key, data;
|
|
- DB_TXN *txn;
|
|
- DB_LOCK lock;
|
|
- ID id, nid;
|
|
- EntryInfo *ei;
|
|
- int rc, getnext = 1;
|
|
- int i;
|
|
-
|
|
- connection_fake_init( &conn, &opbuf, ctx );
|
|
- op = &opbuf.ob_op;
|
|
-
|
|
- op->o_bd = be;
|
|
-
|
|
- DBTzero( &key );
|
|
- DBTzero( &data );
|
|
-
|
|
- id = 1;
|
|
- key.data = &nid;
|
|
- key.size = key.ulen = sizeof(ID);
|
|
- key.flags = DB_DBT_USERMEM;
|
|
-
|
|
- data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
|
|
- data.dlen = data.ulen = 0;
|
|
-
|
|
- while ( 1 ) {
|
|
- if ( slapd_shutdown )
|
|
- break;
|
|
-
|
|
- rc = TXN_BEGIN( bdb->bi_dbenv, NULL, &txn, bdb->bi_db_opflags );
|
|
- if ( rc )
|
|
- break;
|
|
- Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_online_index) ": txn id: %x\n",
|
|
- txn->id(txn), 0, 0 );
|
|
- if ( getnext ) {
|
|
- getnext = 0;
|
|
- BDB_ID2DISK( id, &nid );
|
|
- rc = bdb->bi_id2entry->bdi_db->cursor(
|
|
- bdb->bi_id2entry->bdi_db, txn, &curs, bdb->bi_db_opflags );
|
|
- if ( rc ) {
|
|
- TXN_ABORT( txn );
|
|
- break;
|
|
- }
|
|
- rc = curs->c_get( curs, &key, &data, DB_SET_RANGE );
|
|
- curs->c_close( curs );
|
|
- if ( rc ) {
|
|
- TXN_ABORT( txn );
|
|
- if ( rc == DB_NOTFOUND )
|
|
- rc = 0;
|
|
- if ( rc == DB_LOCK_DEADLOCK ) {
|
|
- ldap_pvt_thread_yield();
|
|
- continue;
|
|
- }
|
|
- break;
|
|
- }
|
|
- BDB_DISK2ID( &nid, &id );
|
|
- }
|
|
-
|
|
- ei = NULL;
|
|
- rc = bdb_cache_find_id( op, txn, id, &ei, 0, &lock );
|
|
- if ( rc ) {
|
|
- TXN_ABORT( txn );
|
|
- if ( rc == DB_LOCK_DEADLOCK ) {
|
|
- ldap_pvt_thread_yield();
|
|
- continue;
|
|
- }
|
|
- if ( rc == DB_NOTFOUND ) {
|
|
- id++;
|
|
- getnext = 1;
|
|
- continue;
|
|
- }
|
|
- break;
|
|
- }
|
|
- if ( ei->bei_e ) {
|
|
- rc = bdb_index_entry( op, txn, BDB_INDEX_UPDATE_OP, ei->bei_e );
|
|
- if ( rc ) {
|
|
- TXN_ABORT( txn );
|
|
- if ( rc == DB_LOCK_DEADLOCK ) {
|
|
- ldap_pvt_thread_yield();
|
|
- continue;
|
|
- }
|
|
- break;
|
|
- }
|
|
- rc = TXN_COMMIT( txn, 0 );
|
|
- txn = NULL;
|
|
- }
|
|
- id++;
|
|
- getnext = 1;
|
|
- }
|
|
-
|
|
- for ( i = 0; i < bdb->bi_nattrs; i++ ) {
|
|
- if ( bdb->bi_attrs[ i ]->ai_indexmask & BDB_INDEX_DELETING
|
|
- || bdb->bi_attrs[ i ]->ai_newmask == 0 )
|
|
- {
|
|
- continue;
|
|
- }
|
|
- bdb->bi_attrs[ i ]->ai_indexmask = bdb->bi_attrs[ i ]->ai_newmask;
|
|
- bdb->bi_attrs[ i ]->ai_newmask = 0;
|
|
- }
|
|
-
|
|
- ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
|
|
- ldap_pvt_runqueue_stoptask( &slapd_rq, rtask );
|
|
- bdb->bi_index_task = NULL;
|
|
- ldap_pvt_runqueue_remove( &slapd_rq, rtask );
|
|
- ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
|
|
-
|
|
- return NULL;
|
|
-}
|
|
-
|
|
-/* Cleanup loose ends after Modify completes */
|
|
-static int
|
|
-bdb_cf_cleanup( ConfigArgs *c )
|
|
-{
|
|
- struct bdb_info *bdb = c->be->be_private;
|
|
- int rc = 0;
|
|
- BerVarray bva;
|
|
-
|
|
- if ( bdb->bi_flags & BDB_DEL_INDEX ) {
|
|
- bdb_attr_flush( bdb );
|
|
- bdb->bi_flags ^= BDB_DEL_INDEX;
|
|
- }
|
|
-
|
|
- if ( bdb->bi_flags & BDB_RE_OPEN ) {
|
|
- bdb->bi_flags ^= BDB_RE_OPEN;
|
|
- bva = bdb->bi_db_config;
|
|
- bdb->bi_db_config = NULL;
|
|
- rc = c->be->bd_info->bi_db_close( c->be, &c->reply );
|
|
- if ( rc == 0 ) {
|
|
- if ( bdb->bi_flags & BDB_UPD_CONFIG ) {
|
|
- if ( bva ) {
|
|
- int i;
|
|
- FILE *f = fopen( bdb->bi_db_config_path, "w" );
|
|
- if ( f ) {
|
|
- bdb->bi_db_config = bva;
|
|
- bva = NULL;
|
|
- for (i=0; bdb->bi_db_config[i].bv_val; i++)
|
|
- fprintf( f, "%s\n", bdb->bi_db_config[i].bv_val );
|
|
- fclose( f );
|
|
- } else {
|
|
- ber_bvarray_free( bva );
|
|
- }
|
|
- } else {
|
|
- unlink( bdb->bi_db_config_path );
|
|
- }
|
|
- bdb->bi_flags ^= BDB_UPD_CONFIG;
|
|
- }
|
|
- rc = c->be->bd_info->bi_db_open( c->be, &c->reply );
|
|
- }
|
|
- /* If this fails, we need to restart */
|
|
- if ( rc ) {
|
|
- slapd_shutdown = 2;
|
|
- snprintf( c->cr_msg, sizeof( c->cr_msg ),
|
|
- "failed to reopen database, rc=%d", rc );
|
|
- Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_cf_cleanup)
|
|
- ": %s\n", c->cr_msg, 0, 0 );
|
|
- rc = LDAP_OTHER;
|
|
- }
|
|
- }
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static int
|
|
-bdb_cf_gen( ConfigArgs *c )
|
|
-{
|
|
- struct bdb_info *bdb = c->be->be_private;
|
|
- int rc;
|
|
-
|
|
- if ( c->op == SLAP_CONFIG_EMIT ) {
|
|
- rc = 0;
|
|
- switch( c->type ) {
|
|
- case BDB_MODE: {
|
|
- char buf[64];
|
|
- struct berval bv;
|
|
- bv.bv_len = snprintf( buf, sizeof(buf), "0%o", bdb->bi_dbenv_mode );
|
|
- if ( bv.bv_len > 0 && bv.bv_len < sizeof(buf) ) {
|
|
- bv.bv_val = buf;
|
|
- value_add_one( &c->rvalue_vals, &bv );
|
|
- } else {
|
|
- rc = 1;
|
|
- }
|
|
- } break;
|
|
-
|
|
- case BDB_CHKPT:
|
|
- if ( bdb->bi_txn_cp ) {
|
|
- char buf[64];
|
|
- struct berval bv;
|
|
- bv.bv_len = snprintf( buf, sizeof(buf), "%ld %ld",
|
|
- (long) bdb->bi_txn_cp_kbyte, (long) bdb->bi_txn_cp_min );
|
|
- if ( bv.bv_len > 0 && bv.bv_len < sizeof(buf) ) {
|
|
- bv.bv_val = buf;
|
|
- value_add_one( &c->rvalue_vals, &bv );
|
|
- } else {
|
|
- rc = 1;
|
|
- }
|
|
- } else {
|
|
- rc = 1;
|
|
- }
|
|
- break;
|
|
-
|
|
- case BDB_CRYPTFILE:
|
|
- if ( bdb->bi_db_crypt_file ) {
|
|
- c->value_string = ch_strdup( bdb->bi_db_crypt_file );
|
|
- } else {
|
|
- rc = 1;
|
|
- }
|
|
- break;
|
|
-
|
|
- /* If a crypt file has been set, its contents are copied here.
|
|
- * But we don't want the key to be incorporated here.
|
|
- */
|
|
- case BDB_CRYPTKEY:
|
|
- if ( !bdb->bi_db_crypt_file && !BER_BVISNULL( &bdb->bi_db_crypt_key )) {
|
|
- value_add_one( &c->rvalue_vals, &bdb->bi_db_crypt_key );
|
|
- } else {
|
|
- rc = 1;
|
|
- }
|
|
- break;
|
|
-
|
|
- case BDB_DIRECTORY:
|
|
- if ( bdb->bi_dbenv_home ) {
|
|
- c->value_string = ch_strdup( bdb->bi_dbenv_home );
|
|
- } else {
|
|
- rc = 1;
|
|
- }
|
|
- break;
|
|
-
|
|
- case BDB_CONFIG:
|
|
- if ( !( bdb->bi_flags & BDB_IS_OPEN )
|
|
- && !bdb->bi_db_config )
|
|
- {
|
|
- char buf[SLAP_TEXT_BUFLEN];
|
|
- FILE *f = fopen( bdb->bi_db_config_path, "r" );
|
|
- struct berval bv;
|
|
-
|
|
- if ( f ) {
|
|
- bdb->bi_flags |= BDB_HAS_CONFIG;
|
|
- while ( fgets( buf, sizeof(buf), f )) {
|
|
- ber_str2bv( buf, 0, 1, &bv );
|
|
- if ( bv.bv_len > 0 && bv.bv_val[bv.bv_len-1] == '\n' ) {
|
|
- bv.bv_len--;
|
|
- bv.bv_val[bv.bv_len] = '\0';
|
|
- }
|
|
- /* shouldn't need this, but ... */
|
|
- if ( bv.bv_len > 0 && bv.bv_val[bv.bv_len-1] == '\r' ) {
|
|
- bv.bv_len--;
|
|
- bv.bv_val[bv.bv_len] = '\0';
|
|
- }
|
|
- ber_bvarray_add( &bdb->bi_db_config, &bv );
|
|
- }
|
|
- fclose( f );
|
|
- }
|
|
- }
|
|
- if ( bdb->bi_db_config ) {
|
|
- int i;
|
|
- struct berval bv;
|
|
-
|
|
- bv.bv_val = c->log;
|
|
- for (i=0; !BER_BVISNULL(&bdb->bi_db_config[i]); i++) {
|
|
- bv.bv_len = sprintf( bv.bv_val, "{%d}%s", i,
|
|
- bdb->bi_db_config[i].bv_val );
|
|
- value_add_one( &c->rvalue_vals, &bv );
|
|
- }
|
|
- }
|
|
- if ( !c->rvalue_vals ) rc = 1;
|
|
- break;
|
|
-
|
|
- case BDB_NOSYNC:
|
|
- if ( bdb->bi_dbenv_xflags & DB_TXN_NOSYNC )
|
|
- c->value_int = 1;
|
|
- break;
|
|
-
|
|
- case BDB_CHECKSUM:
|
|
- if ( bdb->bi_flags & BDB_CHKSUM )
|
|
- c->value_int = 1;
|
|
- break;
|
|
-
|
|
- case BDB_INDEX:
|
|
- bdb_attr_index_unparse( bdb, &c->rvalue_vals );
|
|
- if ( !c->rvalue_vals ) rc = 1;
|
|
- break;
|
|
-
|
|
- case BDB_LOCKD:
|
|
- rc = 1;
|
|
- if ( bdb->bi_lock_detect != DB_LOCK_DEFAULT ) {
|
|
- int i;
|
|
- for (i=0; !BER_BVISNULL(&bdb_lockd[i].word); i++) {
|
|
- if ( bdb->bi_lock_detect == (u_int32_t)bdb_lockd[i].mask ) {
|
|
- value_add_one( &c->rvalue_vals, &bdb_lockd[i].word );
|
|
- rc = 0;
|
|
- break;
|
|
- }
|
|
- }
|
|
- }
|
|
- break;
|
|
-
|
|
- case BDB_SSTACK:
|
|
- c->value_int = bdb->bi_search_stack_depth;
|
|
- break;
|
|
-
|
|
- case BDB_PGSIZE: {
|
|
- struct bdb_db_pgsize *ps;
|
|
- char buf[SLAP_TEXT_BUFLEN];
|
|
- struct berval bv;
|
|
- int rc = 1;
|
|
-
|
|
- bv.bv_val = buf;
|
|
- for ( ps = bdb->bi_pagesizes; ps; ps = ps->bdp_next ) {
|
|
- bv.bv_len = sprintf( buf, "%s %d", ps->bdp_name.bv_val,
|
|
- ps->bdp_size / 1024 );
|
|
- value_add_one( &c->rvalue_vals, &bv );
|
|
- rc = 0;
|
|
-
|
|
- }
|
|
- break;
|
|
- }
|
|
- }
|
|
- return rc;
|
|
- } else if ( c->op == LDAP_MOD_DELETE ) {
|
|
- rc = 0;
|
|
- switch( c->type ) {
|
|
- case BDB_MODE:
|
|
-#if 0
|
|
- /* FIXME: does it make any sense to change the mode,
|
|
- * if we don't exec a chmod()? */
|
|
- bdb->bi_dbenv_mode = SLAPD_DEFAULT_DB_MODE;
|
|
- break;
|
|
-#endif
|
|
-
|
|
- /* single-valued no-ops */
|
|
- case BDB_LOCKD:
|
|
- case BDB_SSTACK:
|
|
- break;
|
|
-
|
|
- case BDB_CHKPT:
|
|
- if ( bdb->bi_txn_cp_task ) {
|
|
- struct re_s *re = bdb->bi_txn_cp_task;
|
|
- bdb->bi_txn_cp_task = NULL;
|
|
- ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
|
|
- if ( ldap_pvt_runqueue_isrunning( &slapd_rq, re ) )
|
|
- ldap_pvt_runqueue_stoptask( &slapd_rq, re );
|
|
- ldap_pvt_runqueue_remove( &slapd_rq, re );
|
|
- ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
|
|
- }
|
|
- bdb->bi_txn_cp = 0;
|
|
- break;
|
|
- case BDB_CONFIG:
|
|
- if ( c->valx < 0 ) {
|
|
- ber_bvarray_free( bdb->bi_db_config );
|
|
- bdb->bi_db_config = NULL;
|
|
- } else {
|
|
- int i = c->valx;
|
|
- ch_free( bdb->bi_db_config[i].bv_val );
|
|
- for (; bdb->bi_db_config[i].bv_val; i++)
|
|
- bdb->bi_db_config[i] = bdb->bi_db_config[i+1];
|
|
- }
|
|
- bdb->bi_flags |= BDB_UPD_CONFIG|BDB_RE_OPEN;
|
|
- c->cleanup = bdb_cf_cleanup;
|
|
- break;
|
|
- /* Doesn't really make sense to change these on the fly;
|
|
- * the entire DB must be dumped and reloaded
|
|
- */
|
|
- case BDB_CRYPTFILE:
|
|
- if ( bdb->bi_db_crypt_file ) {
|
|
- ch_free( bdb->bi_db_crypt_file );
|
|
- bdb->bi_db_crypt_file = NULL;
|
|
- }
|
|
- /* FALLTHRU */
|
|
- case BDB_CRYPTKEY:
|
|
- if ( !BER_BVISNULL( &bdb->bi_db_crypt_key )) {
|
|
- ch_free( bdb->bi_db_crypt_key.bv_val );
|
|
- BER_BVZERO( &bdb->bi_db_crypt_key );
|
|
- }
|
|
- break;
|
|
- case BDB_DIRECTORY:
|
|
- bdb->bi_flags |= BDB_RE_OPEN;
|
|
- bdb->bi_flags ^= BDB_HAS_CONFIG;
|
|
- ch_free( bdb->bi_dbenv_home );
|
|
- bdb->bi_dbenv_home = NULL;
|
|
- ch_free( bdb->bi_db_config_path );
|
|
- bdb->bi_db_config_path = NULL;
|
|
- c->cleanup = bdb_cf_cleanup;
|
|
- ldap_pvt_thread_pool_purgekey( bdb->bi_dbenv );
|
|
- break;
|
|
- case BDB_NOSYNC:
|
|
- bdb->bi_dbenv->set_flags( bdb->bi_dbenv, DB_TXN_NOSYNC, 0 );
|
|
- break;
|
|
- case BDB_CHECKSUM:
|
|
- bdb->bi_flags &= ~BDB_CHKSUM;
|
|
- break;
|
|
- case BDB_INDEX:
|
|
- if ( c->valx == -1 ) {
|
|
- int i;
|
|
-
|
|
- /* delete all */
|
|
- for ( i = 0; i < bdb->bi_nattrs; i++ ) {
|
|
- bdb->bi_attrs[i]->ai_indexmask |= BDB_INDEX_DELETING;
|
|
- }
|
|
- bdb->bi_defaultmask = 0;
|
|
- bdb->bi_flags |= BDB_DEL_INDEX;
|
|
- c->cleanup = bdb_cf_cleanup;
|
|
-
|
|
- } else {
|
|
- struct berval bv, def = BER_BVC("default");
|
|
- char *ptr;
|
|
-
|
|
- for (ptr = c->line; !isspace( (unsigned char) *ptr ); ptr++);
|
|
-
|
|
- bv.bv_val = c->line;
|
|
- bv.bv_len = ptr - bv.bv_val;
|
|
- if ( bvmatch( &bv, &def )) {
|
|
- bdb->bi_defaultmask = 0;
|
|
-
|
|
- } else {
|
|
- int i;
|
|
- char **attrs;
|
|
- char sep;
|
|
-
|
|
- sep = bv.bv_val[ bv.bv_len ];
|
|
- bv.bv_val[ bv.bv_len ] = '\0';
|
|
- attrs = ldap_str2charray( bv.bv_val, "," );
|
|
-
|
|
- for ( i = 0; attrs[ i ]; i++ ) {
|
|
- AttributeDescription *ad = NULL;
|
|
- const char *text;
|
|
- AttrInfo *ai;
|
|
-
|
|
- slap_str2ad( attrs[ i ], &ad, &text );
|
|
- /* if we got here... */
|
|
- assert( ad != NULL );
|
|
-
|
|
- ai = bdb_attr_mask( bdb, ad );
|
|
- /* if we got here... */
|
|
- assert( ai != NULL );
|
|
-
|
|
- ai->ai_indexmask |= BDB_INDEX_DELETING;
|
|
- bdb->bi_flags |= BDB_DEL_INDEX;
|
|
- c->cleanup = bdb_cf_cleanup;
|
|
- }
|
|
-
|
|
- bv.bv_val[ bv.bv_len ] = sep;
|
|
- ldap_charray_free( attrs );
|
|
- }
|
|
- }
|
|
- break;
|
|
- /* doesn't make sense on the fly; the DB file must be
|
|
- * recreated
|
|
- */
|
|
- case BDB_PGSIZE: {
|
|
- struct bdb_db_pgsize *ps, **prev;
|
|
- int i;
|
|
-
|
|
- for ( i = 0, prev = &bdb->bi_pagesizes, ps = *prev; ps;
|
|
- prev = &ps->bdp_next, ps = ps->bdp_next, i++ ) {
|
|
- if ( c->valx == -1 || i == c->valx ) {
|
|
- *prev = ps->bdp_next;
|
|
- ch_free( ps );
|
|
- ps = *prev;
|
|
- if ( i == c->valx ) break;
|
|
- }
|
|
- }
|
|
- }
|
|
- break;
|
|
- }
|
|
- return rc;
|
|
- }
|
|
-
|
|
- switch( c->type ) {
|
|
- case BDB_MODE:
|
|
- if ( ASCII_DIGIT( c->argv[1][0] ) ) {
|
|
- long mode;
|
|
- char *next;
|
|
- errno = 0;
|
|
- mode = strtol( c->argv[1], &next, 0 );
|
|
- if ( errno != 0 || next == c->argv[1] || next[0] != '\0' ) {
|
|
- fprintf( stderr, "%s: "
|
|
- "unable to parse mode=\"%s\".\n",
|
|
- c->log, c->argv[1] );
|
|
- return 1;
|
|
- }
|
|
- bdb->bi_dbenv_mode = mode;
|
|
-
|
|
- } else {
|
|
- char *m = c->argv[1];
|
|
- int who, what, mode = 0;
|
|
-
|
|
- if ( strlen( m ) != STRLENOF("-rwxrwxrwx") ) {
|
|
- return 1;
|
|
- }
|
|
-
|
|
- if ( m[0] != '-' ) {
|
|
- return 1;
|
|
- }
|
|
-
|
|
- m++;
|
|
- for ( who = 0; who < 3; who++ ) {
|
|
- for ( what = 0; what < 3; what++, m++ ) {
|
|
- if ( m[0] == '-' ) {
|
|
- continue;
|
|
- } else if ( m[0] != "rwx"[what] ) {
|
|
- return 1;
|
|
- }
|
|
- mode += ((1 << (2 - what)) << 3*(2 - who));
|
|
- }
|
|
- }
|
|
- bdb->bi_dbenv_mode = mode;
|
|
- }
|
|
- break;
|
|
- case BDB_CHKPT: {
|
|
- long l;
|
|
- bdb->bi_txn_cp = 1;
|
|
- if ( lutil_atolx( &l, c->argv[1], 0 ) != 0 ) {
|
|
- fprintf( stderr, "%s: "
|
|
- "invalid kbyte \"%s\" in \"checkpoint\".\n",
|
|
- c->log, c->argv[1] );
|
|
- return 1;
|
|
- }
|
|
- bdb->bi_txn_cp_kbyte = l;
|
|
- if ( lutil_atolx( &l, c->argv[2], 0 ) != 0 ) {
|
|
- fprintf( stderr, "%s: "
|
|
- "invalid minutes \"%s\" in \"checkpoint\".\n",
|
|
- c->log, c->argv[2] );
|
|
- return 1;
|
|
- }
|
|
- bdb->bi_txn_cp_min = l;
|
|
- /* If we're in server mode and time-based checkpointing is enabled,
|
|
- * submit a task to perform periodic checkpoints.
|
|
- */
|
|
- if ((slapMode & SLAP_SERVER_MODE) && bdb->bi_txn_cp_min ) {
|
|
- struct re_s *re = bdb->bi_txn_cp_task;
|
|
- if ( re ) {
|
|
- re->interval.tv_sec = bdb->bi_txn_cp_min * 60;
|
|
- } else {
|
|
- if ( c->be->be_suffix == NULL || BER_BVISNULL( &c->be->be_suffix[0] ) ) {
|
|
- fprintf( stderr, "%s: "
|
|
- "\"checkpoint\" must occur after \"suffix\".\n",
|
|
- c->log );
|
|
- return 1;
|
|
- }
|
|
- ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
|
|
- bdb->bi_txn_cp_task = ldap_pvt_runqueue_insert( &slapd_rq,
|
|
- bdb->bi_txn_cp_min * 60, bdb_checkpoint, bdb,
|
|
- LDAP_XSTRING(bdb_checkpoint), c->be->be_suffix[0].bv_val );
|
|
- ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
|
|
- }
|
|
- }
|
|
- } break;
|
|
-
|
|
- case BDB_CONFIG: {
|
|
- char *ptr = c->line;
|
|
- struct berval bv;
|
|
-
|
|
- if ( c->op == SLAP_CONFIG_ADD ) {
|
|
- ptr += STRLENOF("dbconfig");
|
|
- while (!isspace((unsigned char)*ptr)) ptr++;
|
|
- while (isspace((unsigned char)*ptr)) ptr++;
|
|
- }
|
|
-
|
|
- if ( bdb->bi_flags & BDB_IS_OPEN ) {
|
|
- bdb->bi_flags |= BDB_UPD_CONFIG|BDB_RE_OPEN;
|
|
- c->cleanup = bdb_cf_cleanup;
|
|
- } else {
|
|
- /* If we're just starting up...
|
|
- */
|
|
- FILE *f;
|
|
- /* If a DB_CONFIG file exists, or we don't know the path
|
|
- * to the DB_CONFIG file, ignore these directives
|
|
- */
|
|
- if (( bdb->bi_flags & BDB_HAS_CONFIG ) || !bdb->bi_db_config_path )
|
|
- break;
|
|
- f = fopen( bdb->bi_db_config_path, "a" );
|
|
- if ( f ) {
|
|
- /* FIXME: EBCDIC probably needs special handling */
|
|
- fprintf( f, "%s\n", ptr );
|
|
- fclose( f );
|
|
- }
|
|
- }
|
|
- ber_str2bv( ptr, 0, 1, &bv );
|
|
- ber_bvarray_add( &bdb->bi_db_config, &bv );
|
|
- }
|
|
- break;
|
|
-
|
|
- case BDB_CRYPTFILE:
|
|
- rc = lutil_get_filed_password( c->value_string, &bdb->bi_db_crypt_key );
|
|
- if ( rc == 0 ) {
|
|
- bdb->bi_db_crypt_file = c->value_string;
|
|
- }
|
|
- break;
|
|
-
|
|
- /* Cannot set key if file was already set */
|
|
- case BDB_CRYPTKEY:
|
|
- if ( bdb->bi_db_crypt_file ) {
|
|
- rc = 1;
|
|
- } else {
|
|
- bdb->bi_db_crypt_key = c->value_bv;
|
|
- }
|
|
- break;
|
|
-
|
|
- case BDB_DIRECTORY: {
|
|
- FILE *f;
|
|
- char *ptr, *testpath;
|
|
- int len;
|
|
-
|
|
- len = strlen( c->value_string );
|
|
- testpath = ch_malloc( len + STRLENOF(LDAP_DIRSEP) + STRLENOF("DUMMY") + 1 );
|
|
- ptr = lutil_strcopy( testpath, c->value_string );
|
|
- *ptr++ = LDAP_DIRSEP[0];
|
|
- strcpy( ptr, "DUMMY" );
|
|
- f = fopen( testpath, "w" );
|
|
- if ( f ) {
|
|
- fclose( f );
|
|
- unlink( testpath );
|
|
- }
|
|
- ch_free( testpath );
|
|
- if ( !f ) {
|
|
- snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: invalid path: %s",
|
|
- c->log, strerror( errno ));
|
|
- Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg, 0, 0 );
|
|
- return -1;
|
|
- }
|
|
-
|
|
- if ( bdb->bi_dbenv_home )
|
|
- ch_free( bdb->bi_dbenv_home );
|
|
- bdb->bi_dbenv_home = c->value_string;
|
|
-
|
|
- /* See if a DB_CONFIG file already exists here */
|
|
- if ( bdb->bi_db_config_path )
|
|
- ch_free( bdb->bi_db_config_path );
|
|
- bdb->bi_db_config_path = ch_malloc( len +
|
|
- STRLENOF(LDAP_DIRSEP) + STRLENOF("DB_CONFIG") + 1 );
|
|
- ptr = lutil_strcopy( bdb->bi_db_config_path, bdb->bi_dbenv_home );
|
|
- *ptr++ = LDAP_DIRSEP[0];
|
|
- strcpy( ptr, "DB_CONFIG" );
|
|
-
|
|
- f = fopen( bdb->bi_db_config_path, "r" );
|
|
- if ( f ) {
|
|
- bdb->bi_flags |= BDB_HAS_CONFIG;
|
|
- fclose(f);
|
|
- }
|
|
- }
|
|
- break;
|
|
-
|
|
- case BDB_NOSYNC:
|
|
- if ( c->value_int )
|
|
- bdb->bi_dbenv_xflags |= DB_TXN_NOSYNC;
|
|
- else
|
|
- bdb->bi_dbenv_xflags &= ~DB_TXN_NOSYNC;
|
|
- if ( bdb->bi_flags & BDB_IS_OPEN ) {
|
|
- bdb->bi_dbenv->set_flags( bdb->bi_dbenv, DB_TXN_NOSYNC,
|
|
- c->value_int );
|
|
- }
|
|
- break;
|
|
-
|
|
- case BDB_CHECKSUM:
|
|
- if ( c->value_int )
|
|
- bdb->bi_flags |= BDB_CHKSUM;
|
|
- else
|
|
- bdb->bi_flags &= ~BDB_CHKSUM;
|
|
- break;
|
|
-
|
|
- case BDB_INDEX:
|
|
- rc = bdb_attr_index_config( bdb, c->fname, c->lineno,
|
|
- c->argc - 1, &c->argv[1], &c->reply);
|
|
-
|
|
- if( rc != LDAP_SUCCESS ) return 1;
|
|
- if (( bdb->bi_flags & BDB_IS_OPEN ) && !bdb->bi_index_task ) {
|
|
- /* Start the task as soon as we finish here. Set a long
|
|
- * interval (10 hours) so that it only gets scheduled once.
|
|
- */
|
|
- if ( c->be->be_suffix == NULL || BER_BVISNULL( &c->be->be_suffix[0] ) ) {
|
|
- fprintf( stderr, "%s: "
|
|
- "\"index\" must occur after \"suffix\".\n",
|
|
- c->log );
|
|
- return 1;
|
|
- }
|
|
- ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
|
|
- bdb->bi_index_task = ldap_pvt_runqueue_insert( &slapd_rq, 36000,
|
|
- bdb_online_index, c->be,
|
|
- LDAP_XSTRING(bdb_online_index), c->be->be_suffix[0].bv_val );
|
|
- ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
|
|
- }
|
|
- break;
|
|
-
|
|
- case BDB_LOCKD:
|
|
- rc = verb_to_mask( c->argv[1], bdb_lockd );
|
|
- if ( BER_BVISNULL(&bdb_lockd[rc].word) ) {
|
|
- fprintf( stderr, "%s: "
|
|
- "bad policy (%s) in \"lockDetect <policy>\" line\n",
|
|
- c->log, c->argv[1] );
|
|
- return 1;
|
|
- }
|
|
- bdb->bi_lock_detect = (u_int32_t)rc;
|
|
- break;
|
|
-
|
|
- case BDB_SSTACK:
|
|
- if ( c->value_int < MINIMUM_SEARCH_STACK_DEPTH ) {
|
|
- fprintf( stderr,
|
|
- "%s: depth %d too small, using %d\n",
|
|
- c->log, c->value_int, MINIMUM_SEARCH_STACK_DEPTH );
|
|
- c->value_int = MINIMUM_SEARCH_STACK_DEPTH;
|
|
- }
|
|
- bdb->bi_search_stack_depth = c->value_int;
|
|
- break;
|
|
-
|
|
- case BDB_PGSIZE: {
|
|
- struct bdb_db_pgsize *ps, **prev;
|
|
- int i, s;
|
|
-
|
|
- s = atoi(c->argv[2]);
|
|
- if ( s < 1 || s > 64 ) {
|
|
- snprintf( c->cr_msg, sizeof( c->cr_msg ),
|
|
- "%s: size must be > 0 and <= 64: %d",
|
|
- c->log, s );
|
|
- Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg, 0, 0 );
|
|
- return -1;
|
|
- }
|
|
- i = strlen(c->argv[1]);
|
|
- ps = ch_malloc( sizeof(struct bdb_db_pgsize) + i + 1 );
|
|
- ps->bdp_next = NULL;
|
|
- ps->bdp_name.bv_len = i;
|
|
- ps->bdp_name.bv_val = (char *)(ps+1);
|
|
- strcpy( ps->bdp_name.bv_val, c->argv[1] );
|
|
- ps->bdp_size = s * 1024;
|
|
- for ( prev = &bdb->bi_pagesizes; *prev; prev = &(*prev)->bdp_next )
|
|
- ;
|
|
- *prev = ps;
|
|
- }
|
|
- break;
|
|
- }
|
|
- return 0;
|
|
-}
|
|
-
|
|
-int bdb_back_init_cf( BackendInfo *bi )
|
|
-{
|
|
- int rc;
|
|
- bi->bi_cf_ocs = bdbocs;
|
|
-
|
|
- rc = config_register_schema( bdbcfg, bdbocs );
|
|
- if ( rc ) return rc;
|
|
- return 0;
|
|
-}
|
|
diff --git a/servers/slapd/back-bdb/dbcache.c b/servers/slapd/back-bdb/dbcache.c
|
|
deleted file mode 100644
|
|
index 9a35b71..0000000
|
|
--- a/servers/slapd/back-bdb/dbcache.c
|
|
+++ /dev/null
|
|
@@ -1,210 +0,0 @@
|
|
-/* dbcache.c - manage cache of open databases */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-
|
|
-#include <stdio.h>
|
|
-
|
|
-#include <ac/errno.h>
|
|
-#include <ac/socket.h>
|
|
-#include <ac/string.h>
|
|
-#include <ac/time.h>
|
|
-#include <sys/stat.h>
|
|
-
|
|
-#include "slap.h"
|
|
-#include "back-bdb.h"
|
|
-#include "lutil_hash.h"
|
|
-
|
|
-#ifdef BDB_INDEX_USE_HASH
|
|
-/* Pass-thru hash function. Since the indexer is already giving us hash
|
|
- * values as keys, we don't need BDB to re-hash them.
|
|
- */
|
|
-static u_int32_t
|
|
-bdb_db_hash(
|
|
- DB *db,
|
|
- const void *bytes,
|
|
- u_int32_t length
|
|
-)
|
|
-{
|
|
- u_int32_t ret = 0;
|
|
- unsigned char *dst = (unsigned char *)&ret;
|
|
- const unsigned char *src = (const unsigned char *)bytes;
|
|
-
|
|
- if ( length > sizeof(u_int32_t) )
|
|
- length = sizeof(u_int32_t);
|
|
-
|
|
- while ( length ) {
|
|
- *dst++ = *src++;
|
|
- length--;
|
|
- }
|
|
- return ret;
|
|
-}
|
|
-#define BDB_INDEXTYPE DB_HASH
|
|
-#else
|
|
-#define BDB_INDEXTYPE DB_BTREE
|
|
-#endif
|
|
-
|
|
-/* If a configured size is found, return it, otherwise return 0 */
|
|
-int
|
|
-bdb_db_findsize(
|
|
- struct bdb_info *bdb,
|
|
- struct berval *name
|
|
-)
|
|
-{
|
|
- struct bdb_db_pgsize *bp;
|
|
- int rc;
|
|
-
|
|
- for ( bp = bdb->bi_pagesizes; bp; bp=bp->bdp_next ) {
|
|
- rc = strncmp( name->bv_val, bp->bdp_name.bv_val, name->bv_len );
|
|
- if ( !rc ) {
|
|
- if ( name->bv_len == bp->bdp_name.bv_len )
|
|
- return bp->bdp_size;
|
|
- if ( name->bv_len < bp->bdp_name.bv_len &&
|
|
- bp->bdp_name.bv_val[name->bv_len] == '.' )
|
|
- return bp->bdp_size;
|
|
- }
|
|
- }
|
|
- return 0;
|
|
-}
|
|
-
|
|
-int
|
|
-bdb_db_cache(
|
|
- Backend *be,
|
|
- struct berval *name,
|
|
- DB **dbout )
|
|
-{
|
|
- int i, flags;
|
|
- int rc;
|
|
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
|
- struct bdb_db_info *db;
|
|
- char *file;
|
|
-
|
|
- *dbout = NULL;
|
|
-
|
|
- for( i=BDB_NDB; i < bdb->bi_ndatabases; i++ ) {
|
|
- if( !ber_bvcmp( &bdb->bi_databases[i]->bdi_name, name) ) {
|
|
- *dbout = bdb->bi_databases[i]->bdi_db;
|
|
- return 0;
|
|
- }
|
|
- }
|
|
-
|
|
- ldap_pvt_thread_mutex_lock( &bdb->bi_database_mutex );
|
|
-
|
|
- /* check again! may have been added by another thread */
|
|
- for( i=BDB_NDB; i < bdb->bi_ndatabases; i++ ) {
|
|
- if( !ber_bvcmp( &bdb->bi_databases[i]->bdi_name, name) ) {
|
|
- *dbout = bdb->bi_databases[i]->bdi_db;
|
|
- ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
|
|
- return 0;
|
|
- }
|
|
- }
|
|
-
|
|
- if( i >= BDB_INDICES ) {
|
|
- ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
|
|
- return -1;
|
|
- }
|
|
-
|
|
- db = (struct bdb_db_info *) ch_calloc(1, sizeof(struct bdb_db_info));
|
|
-
|
|
- ber_dupbv( &db->bdi_name, name );
|
|
-
|
|
- rc = db_create( &db->bdi_db, bdb->bi_dbenv, 0 );
|
|
- if( rc != 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "bdb_db_cache: db_create(%s) failed: %s (%d)\n",
|
|
- bdb->bi_dbenv_home, db_strerror(rc), rc );
|
|
- ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
|
|
- ch_free( db );
|
|
- return rc;
|
|
- }
|
|
-
|
|
- if( !BER_BVISNULL( &bdb->bi_db_crypt_key )) {
|
|
- rc = db->bdi_db->set_flags( db->bdi_db, DB_ENCRYPT );
|
|
- if ( rc ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "bdb_db_cache: db set_flags(DB_ENCRYPT)(%s) failed: %s (%d)\n",
|
|
- bdb->bi_dbenv_home, db_strerror(rc), rc );
|
|
- ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
|
|
- db->bdi_db->close( db->bdi_db, 0 );
|
|
- ch_free( db );
|
|
- return rc;
|
|
- }
|
|
- }
|
|
-
|
|
- if( bdb->bi_flags & BDB_CHKSUM ) {
|
|
- rc = db->bdi_db->set_flags( db->bdi_db, DB_CHKSUM );
|
|
- if ( rc ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "bdb_db_cache: db set_flags(DB_CHKSUM)(%s) failed: %s (%d)\n",
|
|
- bdb->bi_dbenv_home, db_strerror(rc), rc );
|
|
- ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
|
|
- db->bdi_db->close( db->bdi_db, 0 );
|
|
- ch_free( db );
|
|
- return rc;
|
|
- }
|
|
- }
|
|
-
|
|
- /* If no explicit size set, use the FS default */
|
|
- flags = bdb_db_findsize( bdb, name );
|
|
- if ( flags )
|
|
- rc = db->bdi_db->set_pagesize( db->bdi_db, flags );
|
|
-
|
|
-#ifdef BDB_INDEX_USE_HASH
|
|
- rc = db->bdi_db->set_h_hash( db->bdi_db, bdb_db_hash );
|
|
-#endif
|
|
- rc = db->bdi_db->set_flags( db->bdi_db, DB_DUP | DB_DUPSORT );
|
|
-
|
|
- file = ch_malloc( db->bdi_name.bv_len + sizeof(BDB_SUFFIX) );
|
|
- strcpy( file, db->bdi_name.bv_val );
|
|
- strcpy( file+db->bdi_name.bv_len, BDB_SUFFIX );
|
|
-
|
|
-#ifdef HAVE_EBCDIC
|
|
- __atoe( file );
|
|
-#endif
|
|
- flags = DB_CREATE | DB_THREAD;
|
|
-#ifdef DB_AUTO_COMMIT
|
|
- if ( !( slapMode & SLAP_TOOL_QUICK ))
|
|
- flags |= DB_AUTO_COMMIT;
|
|
-#endif
|
|
- /* Cannot Truncate when Transactions are in use */
|
|
- if ( (slapMode & (SLAP_TOOL_QUICK|SLAP_TRUNCATE_MODE)) ==
|
|
- (SLAP_TOOL_QUICK|SLAP_TRUNCATE_MODE))
|
|
- flags |= DB_TRUNCATE;
|
|
-
|
|
- rc = DB_OPEN( db->bdi_db,
|
|
- file, NULL /* name */,
|
|
- BDB_INDEXTYPE, bdb->bi_db_opflags | flags, bdb->bi_dbenv_mode );
|
|
-
|
|
- ch_free( file );
|
|
-
|
|
- if( rc != 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "bdb_db_cache: db_open(%s) failed: %s (%d)\n",
|
|
- name->bv_val, db_strerror(rc), rc );
|
|
- ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
|
|
- db->bdi_db->close( db->bdi_db, 0 );
|
|
- ch_free( db );
|
|
- return rc;
|
|
- }
|
|
-
|
|
- bdb->bi_databases[i] = db;
|
|
- bdb->bi_ndatabases = i+1;
|
|
-
|
|
- *dbout = db->bdi_db;
|
|
-
|
|
- ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
|
|
- return 0;
|
|
-}
|
|
diff --git a/servers/slapd/back-bdb/delete.c b/servers/slapd/back-bdb/delete.c
|
|
deleted file mode 100644
|
|
index f4f6e23..0000000
|
|
--- a/servers/slapd/back-bdb/delete.c
|
|
+++ /dev/null
|
|
@@ -1,605 +0,0 @@
|
|
-/* delete.c - bdb backend delete routine */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-
|
|
-#include <stdio.h>
|
|
-#include <ac/string.h>
|
|
-
|
|
-#include "lutil.h"
|
|
-#include "back-bdb.h"
|
|
-
|
|
-int
|
|
-bdb_delete( Operation *op, SlapReply *rs )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- Entry *matched = NULL;
|
|
- struct berval pdn = {0, NULL};
|
|
- Entry *e = NULL;
|
|
- Entry *p = NULL;
|
|
- EntryInfo *ei = NULL, *eip = NULL;
|
|
- int manageDSAit = get_manageDSAit( op );
|
|
- AttributeDescription *children = slap_schema.si_ad_children;
|
|
- AttributeDescription *entry = slap_schema.si_ad_entry;
|
|
- DB_TXN *ltid = NULL, *lt2;
|
|
- struct bdb_op_info opinfo = {{{ 0 }}};
|
|
- ID eid;
|
|
-
|
|
- DB_LOCK lock, plock;
|
|
-
|
|
- int num_retries = 0;
|
|
-
|
|
- int rc;
|
|
-
|
|
- LDAPControl **preread_ctrl = NULL;
|
|
- LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
|
|
- int num_ctrls = 0;
|
|
-
|
|
- int parent_is_glue = 0;
|
|
- int parent_is_leaf = 0;
|
|
-
|
|
-#ifdef LDAP_X_TXN
|
|
- int settle = 0;
|
|
-#endif
|
|
-
|
|
- Debug( LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(bdb_delete) ": %s\n",
|
|
- op->o_req_dn.bv_val, 0, 0 );
|
|
-
|
|
-#ifdef LDAP_X_TXN
|
|
- if( op->o_txnSpec ) {
|
|
- /* acquire connection lock */
|
|
- ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
|
|
- if( op->o_conn->c_txn == CONN_TXN_INACTIVE ) {
|
|
- rs->sr_text = "invalid transaction identifier";
|
|
- rs->sr_err = LDAP_X_TXN_ID_INVALID;
|
|
- goto txnReturn;
|
|
- } else if( op->o_conn->c_txn == CONN_TXN_SETTLE ) {
|
|
- settle=1;
|
|
- goto txnReturn;
|
|
- }
|
|
-
|
|
- if( op->o_conn->c_txn_backend == NULL ) {
|
|
- op->o_conn->c_txn_backend = op->o_bd;
|
|
-
|
|
- } else if( op->o_conn->c_txn_backend != op->o_bd ) {
|
|
- rs->sr_text = "transaction cannot span multiple database contexts";
|
|
- rs->sr_err = LDAP_AFFECTS_MULTIPLE_DSAS;
|
|
- goto txnReturn;
|
|
- }
|
|
-
|
|
- /* insert operation into transaction */
|
|
-
|
|
- rs->sr_text = "transaction specified";
|
|
- rs->sr_err = LDAP_X_TXN_SPECIFY_OKAY;
|
|
-
|
|
-txnReturn:
|
|
- /* release connection lock */
|
|
- ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
|
|
-
|
|
- if( !settle ) {
|
|
- send_ldap_result( op, rs );
|
|
- return rs->sr_err;
|
|
- }
|
|
- }
|
|
-#endif
|
|
-
|
|
- ctrls[num_ctrls] = 0;
|
|
-
|
|
- /* allocate CSN */
|
|
- if ( BER_BVISNULL( &op->o_csn ) ) {
|
|
- struct berval csn;
|
|
- char csnbuf[LDAP_PVT_CSNSTR_BUFSIZE];
|
|
-
|
|
- csn.bv_val = csnbuf;
|
|
- csn.bv_len = sizeof(csnbuf);
|
|
- slap_get_csn( op, &csn, 1 );
|
|
- }
|
|
-
|
|
- if( 0 ) {
|
|
-retry: /* transaction retry */
|
|
- if( e != NULL ) {
|
|
- bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
|
|
- e = NULL;
|
|
- }
|
|
- if( p != NULL ) {
|
|
- bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
|
|
- p = NULL;
|
|
- }
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "==> " LDAP_XSTRING(bdb_delete) ": retrying...\n",
|
|
- 0, 0, 0 );
|
|
- rs->sr_err = TXN_ABORT( ltid );
|
|
- ltid = NULL;
|
|
- LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
|
|
- opinfo.boi_oe.oe_key = NULL;
|
|
- op->o_do_not_cache = opinfo.boi_acl_cache;
|
|
- if( rs->sr_err != 0 ) {
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "internal error";
|
|
- goto return_results;
|
|
- }
|
|
- if ( op->o_abandon ) {
|
|
- rs->sr_err = SLAPD_ABANDON;
|
|
- goto return_results;
|
|
- }
|
|
- parent_is_glue = 0;
|
|
- parent_is_leaf = 0;
|
|
- bdb_trans_backoff( ++num_retries );
|
|
- }
|
|
-
|
|
- /* begin transaction */
|
|
- rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, NULL, <id,
|
|
- bdb->bi_db_opflags );
|
|
- Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_delete) ": txn1 id: %x\n",
|
|
- ltid->id(ltid), 0, 0 );
|
|
- rs->sr_text = NULL;
|
|
- if( rs->sr_err != 0 ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_delete) ": txn_begin failed: "
|
|
- "%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "internal error";
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- opinfo.boi_oe.oe_key = bdb;
|
|
- opinfo.boi_txn = ltid;
|
|
- opinfo.boi_err = 0;
|
|
- opinfo.boi_acl_cache = op->o_do_not_cache;
|
|
- LDAP_SLIST_INSERT_HEAD( &op->o_extra, &opinfo.boi_oe, oe_next );
|
|
-
|
|
- if ( !be_issuffix( op->o_bd, &op->o_req_ndn ) ) {
|
|
- dnParent( &op->o_req_ndn, &pdn );
|
|
- }
|
|
-
|
|
- /* get entry */
|
|
- rs->sr_err = bdb_dn2entry( op, ltid, &op->o_req_ndn, &ei, 1,
|
|
- &lock );
|
|
-
|
|
- switch( rs->sr_err ) {
|
|
- case 0:
|
|
- case DB_NOTFOUND:
|
|
- break;
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- case LDAP_BUSY:
|
|
- rs->sr_text = "ldap server busy";
|
|
- goto return_results;
|
|
- default:
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "internal error";
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- if ( rs->sr_err == 0 ) {
|
|
- e = ei->bei_e;
|
|
- eip = ei->bei_parent;
|
|
- } else {
|
|
- matched = ei->bei_e;
|
|
- }
|
|
-
|
|
- /* FIXME : dn2entry() should return non-glue entry */
|
|
- if ( e == NULL || ( !manageDSAit && is_entry_glue( e ))) {
|
|
- Debug( LDAP_DEBUG_ARGS,
|
|
- "<=- " LDAP_XSTRING(bdb_delete) ": no such object %s\n",
|
|
- op->o_req_dn.bv_val, 0, 0);
|
|
-
|
|
- if ( matched != NULL ) {
|
|
- rs->sr_matched = ch_strdup( matched->e_dn );
|
|
- rs->sr_ref = is_entry_referral( matched )
|
|
- ? get_entry_referrals( op, matched )
|
|
- : NULL;
|
|
- bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, matched);
|
|
- matched = NULL;
|
|
-
|
|
- } else {
|
|
- rs->sr_ref = referral_rewrite( default_referral, NULL,
|
|
- &op->o_req_dn, LDAP_SCOPE_DEFAULT );
|
|
- }
|
|
-
|
|
- rs->sr_err = LDAP_REFERRAL;
|
|
- rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- rc = bdb_cache_find_id( op, ltid, eip->bei_id, &eip, 0, &plock );
|
|
- switch( rc ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- case 0:
|
|
- case DB_NOTFOUND:
|
|
- break;
|
|
- default:
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "internal error";
|
|
- goto return_results;
|
|
- }
|
|
- if ( eip ) p = eip->bei_e;
|
|
-
|
|
- if ( pdn.bv_len != 0 ) {
|
|
- if( p == NULL || !bvmatch( &pdn, &p->e_nname )) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<=- " LDAP_XSTRING(bdb_delete) ": parent "
|
|
- "does not exist\n", 0, 0, 0 );
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "could not locate parent of entry";
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- /* check parent for "children" acl */
|
|
- rs->sr_err = access_allowed( op, p,
|
|
- children, NULL, ACL_WDEL, NULL );
|
|
-
|
|
- if ( !rs->sr_err ) {
|
|
- switch( opinfo.boi_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- }
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<=- " LDAP_XSTRING(bdb_delete) ": no write "
|
|
- "access to parent\n", 0, 0, 0 );
|
|
- rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
|
- rs->sr_text = "no write access to parent";
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- } else {
|
|
- /* no parent, must be root to delete */
|
|
- if( ! be_isroot( op ) ) {
|
|
- if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv )
|
|
- || be_shadow_update( op ) ) {
|
|
- p = (Entry *)&slap_entry_root;
|
|
-
|
|
- /* check parent for "children" acl */
|
|
- rs->sr_err = access_allowed( op, p,
|
|
- children, NULL, ACL_WDEL, NULL );
|
|
-
|
|
- p = NULL;
|
|
-
|
|
- if ( !rs->sr_err ) {
|
|
- switch( opinfo.boi_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- }
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<=- " LDAP_XSTRING(bdb_delete)
|
|
- ": no access to parent\n",
|
|
- 0, 0, 0 );
|
|
- rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
|
- rs->sr_text = "no write access to parent";
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- } else {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<=- " LDAP_XSTRING(bdb_delete)
|
|
- ": no parent and not root\n", 0, 0, 0 );
|
|
- rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
|
- goto return_results;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- if ( get_assert( op ) &&
|
|
- ( test_filter( op, e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
|
|
- {
|
|
- rs->sr_err = LDAP_ASSERTION_FAILED;
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- rs->sr_err = access_allowed( op, e,
|
|
- entry, NULL, ACL_WDEL, NULL );
|
|
-
|
|
- if ( !rs->sr_err ) {
|
|
- switch( opinfo.boi_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- }
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<=- " LDAP_XSTRING(bdb_delete) ": no write access "
|
|
- "to entry\n", 0, 0, 0 );
|
|
- rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
|
- rs->sr_text = "no write access to entry";
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- if ( !manageDSAit && is_entry_referral( e ) ) {
|
|
- /* entry is a referral, don't allow delete */
|
|
- rs->sr_ref = get_entry_referrals( op, e );
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_delete) ": entry is referral\n",
|
|
- 0, 0, 0 );
|
|
-
|
|
- rs->sr_err = LDAP_REFERRAL;
|
|
- rs->sr_matched = ch_strdup( e->e_name.bv_val );
|
|
- rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- /* pre-read */
|
|
- if( op->o_preread ) {
|
|
- if( preread_ctrl == NULL ) {
|
|
- preread_ctrl = &ctrls[num_ctrls++];
|
|
- ctrls[num_ctrls] = NULL;
|
|
- }
|
|
- if( slap_read_controls( op, rs, e,
|
|
- &slap_pre_read_bv, preread_ctrl ) )
|
|
- {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<=- " LDAP_XSTRING(bdb_delete) ": pre-read "
|
|
- "failed!\n", 0, 0, 0 );
|
|
- if ( op->o_preread & SLAP_CONTROL_CRITICAL ) {
|
|
- /* FIXME: is it correct to abort
|
|
- * operation if control fails? */
|
|
- goto return_results;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- /* nested transaction */
|
|
- rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, <2,
|
|
- bdb->bi_db_opflags );
|
|
- rs->sr_text = NULL;
|
|
- if( rs->sr_err != 0 ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_delete) ": txn_begin(2) failed: "
|
|
- "%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "internal error";
|
|
- goto return_results;
|
|
- }
|
|
- Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_delete) ": txn2 id: %x\n",
|
|
- lt2->id(lt2), 0, 0 );
|
|
-
|
|
- BDB_LOG_PRINTF( bdb->bi_dbenv, lt2, "slapd Starting delete %s(%d)",
|
|
- e->e_nname.bv_val, e->e_id );
|
|
-
|
|
- /* Can't do it if we have kids */
|
|
- rs->sr_err = bdb_cache_children( op, lt2, e );
|
|
- if( rs->sr_err != DB_NOTFOUND ) {
|
|
- switch( rs->sr_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- case 0:
|
|
- Debug(LDAP_DEBUG_ARGS,
|
|
- "<=- " LDAP_XSTRING(bdb_delete)
|
|
- ": non-leaf %s\n",
|
|
- op->o_req_dn.bv_val, 0, 0);
|
|
- rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
|
|
- rs->sr_text = "subordinate objects must be deleted first";
|
|
- break;
|
|
- default:
|
|
- Debug(LDAP_DEBUG_ARGS,
|
|
- "<=- " LDAP_XSTRING(bdb_delete)
|
|
- ": has_children failed: %s (%d)\n",
|
|
- db_strerror(rs->sr_err), rs->sr_err, 0 );
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "internal error";
|
|
- }
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- /* delete from dn2id */
|
|
- rs->sr_err = bdb_dn2id_delete( op, lt2, eip, e );
|
|
- if ( rs->sr_err != 0 ) {
|
|
- Debug(LDAP_DEBUG_TRACE,
|
|
- "<=- " LDAP_XSTRING(bdb_delete) ": dn2id failed: "
|
|
- "%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
|
|
- switch( rs->sr_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- }
|
|
- rs->sr_text = "DN index delete failed";
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- /* delete indices for old attributes */
|
|
- rs->sr_err = bdb_index_entry_del( op, lt2, e );
|
|
- if ( rs->sr_err != LDAP_SUCCESS ) {
|
|
- Debug(LDAP_DEBUG_TRACE,
|
|
- "<=- " LDAP_XSTRING(bdb_delete) ": index failed: "
|
|
- "%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
|
|
- switch( rs->sr_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- }
|
|
- rs->sr_text = "entry index delete failed";
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- /* fixup delete CSN */
|
|
- if ( !SLAP_SHADOW( op->o_bd )) {
|
|
- struct berval vals[2];
|
|
-
|
|
- assert( !BER_BVISNULL( &op->o_csn ) );
|
|
- vals[0] = op->o_csn;
|
|
- BER_BVZERO( &vals[1] );
|
|
- rs->sr_err = bdb_index_values( op, lt2, slap_schema.si_ad_entryCSN,
|
|
- vals, 0, SLAP_INDEX_ADD_OP );
|
|
- if ( rs->sr_err != LDAP_SUCCESS ) {
|
|
- switch( rs->sr_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- }
|
|
- rs->sr_text = "entryCSN index update failed";
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- goto return_results;
|
|
- }
|
|
- }
|
|
-
|
|
- /* delete from id2entry */
|
|
- rs->sr_err = bdb_id2entry_delete( op->o_bd, lt2, e );
|
|
- if ( rs->sr_err != 0 ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<=- " LDAP_XSTRING(bdb_delete) ": id2entry failed: "
|
|
- "%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
|
|
- switch( rs->sr_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- }
|
|
- rs->sr_text = "entry delete failed";
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- if ( pdn.bv_len != 0 ) {
|
|
- parent_is_glue = is_entry_glue(p);
|
|
- rs->sr_err = bdb_cache_children( op, lt2, p );
|
|
- if ( rs->sr_err != DB_NOTFOUND ) {
|
|
- switch( rs->sr_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- case 0:
|
|
- break;
|
|
- default:
|
|
- Debug(LDAP_DEBUG_ARGS,
|
|
- "<=- " LDAP_XSTRING(bdb_delete)
|
|
- ": has_children failed: %s (%d)\n",
|
|
- db_strerror(rs->sr_err), rs->sr_err, 0 );
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "internal error";
|
|
- goto return_results;
|
|
- }
|
|
- parent_is_leaf = 1;
|
|
- }
|
|
- bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
|
|
- p = NULL;
|
|
- }
|
|
-
|
|
- BDB_LOG_PRINTF( bdb->bi_dbenv, lt2, "slapd Commit1 delete %s(%d)",
|
|
- e->e_nname.bv_val, e->e_id );
|
|
-
|
|
- if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "txn_commit(2) failed";
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- eid = e->e_id;
|
|
-
|
|
-#if 0 /* Do we want to reclaim deleted IDs? */
|
|
- ldap_pvt_thread_mutex_lock( &bdb->bi_lastid_mutex );
|
|
- if ( e->e_id == bdb->bi_lastid ) {
|
|
- bdb_last_id( op->o_bd, ltid );
|
|
- }
|
|
- ldap_pvt_thread_mutex_unlock( &bdb->bi_lastid_mutex );
|
|
-#endif
|
|
-
|
|
- if( op->o_noop ) {
|
|
- if ( ( rs->sr_err = TXN_ABORT( ltid ) ) != 0 ) {
|
|
- rs->sr_text = "txn_abort (no-op) failed";
|
|
- } else {
|
|
- rs->sr_err = LDAP_X_NO_OPERATION;
|
|
- ltid = NULL;
|
|
- goto return_results;
|
|
- }
|
|
- } else {
|
|
-
|
|
- BDB_LOG_PRINTF( bdb->bi_dbenv, ltid, "slapd Cache delete %s(%d)",
|
|
- e->e_nname.bv_val, e->e_id );
|
|
-
|
|
- rc = bdb_cache_delete( bdb, e, ltid, &lock );
|
|
- switch( rc ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- }
|
|
-
|
|
- rs->sr_err = TXN_COMMIT( ltid, 0 );
|
|
- }
|
|
- ltid = NULL;
|
|
- LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
|
|
- opinfo.boi_oe.oe_key = NULL;
|
|
-
|
|
- BDB_LOG_PRINTF( bdb->bi_dbenv, NULL, "slapd Committed delete %s(%d)",
|
|
- e->e_nname.bv_val, e->e_id );
|
|
-
|
|
- if( rs->sr_err != 0 ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_delete) ": txn_%s failed: %s (%d)\n",
|
|
- op->o_noop ? "abort (no-op)" : "commit",
|
|
- db_strerror(rs->sr_err), rs->sr_err );
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "commit failed";
|
|
-
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_delete) ": deleted%s id=%08lx dn=\"%s\"\n",
|
|
- op->o_noop ? " (no-op)" : "",
|
|
- eid, op->o_req_dn.bv_val );
|
|
- rs->sr_err = LDAP_SUCCESS;
|
|
- rs->sr_text = NULL;
|
|
- if( num_ctrls ) rs->sr_ctrls = ctrls;
|
|
-
|
|
-return_results:
|
|
- if ( rs->sr_err == LDAP_SUCCESS && parent_is_glue && parent_is_leaf ) {
|
|
- op->o_delete_glue_parent = 1;
|
|
- }
|
|
-
|
|
- if ( p )
|
|
- bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
|
|
-
|
|
- /* free entry */
|
|
- if( e != NULL ) {
|
|
- if ( rs->sr_err == LDAP_SUCCESS ) {
|
|
- /* Free the EntryInfo and the Entry */
|
|
- bdb_cache_entryinfo_lock( BEI(e) );
|
|
- bdb_cache_delete_cleanup( &bdb->bi_cache, BEI(e) );
|
|
- } else {
|
|
- bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
|
|
- }
|
|
- }
|
|
-
|
|
- if( ltid != NULL ) {
|
|
- TXN_ABORT( ltid );
|
|
- }
|
|
- if ( opinfo.boi_oe.oe_key ) {
|
|
- LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
|
|
- }
|
|
-
|
|
- send_ldap_result( op, rs );
|
|
- slap_graduate_commit_csn( op );
|
|
-
|
|
- if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) {
|
|
- slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
|
|
- slap_sl_free( *preread_ctrl, op->o_tmpmemctx );
|
|
- }
|
|
-
|
|
- if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp_kbyte ) {
|
|
- TXN_CHECKPOINT( bdb->bi_dbenv,
|
|
- bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
|
|
- }
|
|
- return rs->sr_err;
|
|
-}
|
|
diff --git a/servers/slapd/back-bdb/dn2entry.c b/servers/slapd/back-bdb/dn2entry.c
|
|
deleted file mode 100644
|
|
index 41d1dc9..0000000
|
|
--- a/servers/slapd/back-bdb/dn2entry.c
|
|
+++ /dev/null
|
|
@@ -1,84 +0,0 @@
|
|
-/* dn2entry.c - routines to deal with the dn2id / id2entry glue */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-
|
|
-#include <stdio.h>
|
|
-#include <ac/string.h>
|
|
-
|
|
-#include "back-bdb.h"
|
|
-
|
|
-/*
|
|
- * dn2entry - look up dn in the cache/indexes and return the corresponding
|
|
- * entry. If the requested DN is not found and matched is TRUE, return info
|
|
- * for the closest ancestor of the DN. Otherwise e is NULL.
|
|
- */
|
|
-
|
|
-int
|
|
-bdb_dn2entry(
|
|
- Operation *op,
|
|
- DB_TXN *tid,
|
|
- struct berval *dn,
|
|
- EntryInfo **e,
|
|
- int matched,
|
|
- DB_LOCK *lock )
|
|
-{
|
|
- EntryInfo *ei = NULL;
|
|
- int rc, rc2;
|
|
-
|
|
- Debug(LDAP_DEBUG_TRACE, "bdb_dn2entry(\"%s\")\n",
|
|
- dn->bv_val, 0, 0 );
|
|
-
|
|
- *e = NULL;
|
|
-
|
|
- rc = bdb_cache_find_ndn( op, tid, dn, &ei );
|
|
- if ( rc ) {
|
|
- if ( matched && rc == DB_NOTFOUND ) {
|
|
- /* Set the return value, whether we have its entry
|
|
- * or not.
|
|
- */
|
|
- *e = ei;
|
|
- if ( ei && ei->bei_id ) {
|
|
- rc2 = bdb_cache_find_id( op, tid, ei->bei_id,
|
|
- &ei, ID_LOCKED, lock );
|
|
- if ( rc2 ) rc = rc2;
|
|
- } else if ( ei ) {
|
|
- bdb_cache_entryinfo_unlock( ei );
|
|
- memset( lock, 0, sizeof( *lock ));
|
|
- lock->mode = DB_LOCK_NG;
|
|
- }
|
|
- } else if ( ei ) {
|
|
- bdb_cache_entryinfo_unlock( ei );
|
|
- }
|
|
- } else {
|
|
- rc = bdb_cache_find_id( op, tid, ei->bei_id, &ei, ID_LOCKED,
|
|
- lock );
|
|
- if ( rc == 0 ) {
|
|
- *e = ei;
|
|
- } else if ( matched && rc == DB_NOTFOUND ) {
|
|
- /* always return EntryInfo */
|
|
- if ( ei->bei_parent ) {
|
|
- ei = ei->bei_parent;
|
|
- rc2 = bdb_cache_find_id( op, tid, ei->bei_id, &ei, 0,
|
|
- lock );
|
|
- if ( rc2 ) rc = rc2;
|
|
- }
|
|
- *e = ei;
|
|
- }
|
|
- }
|
|
-
|
|
- return rc;
|
|
-}
|
|
diff --git a/servers/slapd/back-bdb/dn2id.c b/servers/slapd/back-bdb/dn2id.c
|
|
deleted file mode 100644
|
|
index 7b54024..0000000
|
|
--- a/servers/slapd/back-bdb/dn2id.c
|
|
+++ /dev/null
|
|
@@ -1,1215 +0,0 @@
|
|
-/* dn2id.c - routines to deal with the dn2id index */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-
|
|
-#include <stdio.h>
|
|
-#include <ac/string.h>
|
|
-
|
|
-#include "back-bdb.h"
|
|
-#include "idl.h"
|
|
-#include "lutil.h"
|
|
-
|
|
-#ifndef BDB_HIER
|
|
-int
|
|
-bdb_dn2id_add(
|
|
- Operation *op,
|
|
- DB_TXN *txn,
|
|
- EntryInfo *eip,
|
|
- Entry *e )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- DB *db = bdb->bi_dn2id->bdi_db;
|
|
- int rc;
|
|
- DBT key, data;
|
|
- ID nid;
|
|
- char *buf;
|
|
- struct berval ptr, pdn;
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_add 0x%lx: \"%s\"\n",
|
|
- e->e_id, e->e_ndn, 0 );
|
|
- assert( e->e_id != NOID );
|
|
-
|
|
- DBTzero( &key );
|
|
- key.size = e->e_nname.bv_len + 2;
|
|
- key.ulen = key.size;
|
|
- key.flags = DB_DBT_USERMEM;
|
|
- buf = op->o_tmpalloc( key.size, op->o_tmpmemctx );
|
|
- key.data = buf;
|
|
- buf[0] = DN_BASE_PREFIX;
|
|
- ptr.bv_val = buf + 1;
|
|
- ptr.bv_len = e->e_nname.bv_len;
|
|
- AC_MEMCPY( ptr.bv_val, e->e_nname.bv_val, e->e_nname.bv_len );
|
|
- ptr.bv_val[ptr.bv_len] = '\0';
|
|
-
|
|
- DBTzero( &data );
|
|
- data.data = &nid;
|
|
- data.size = sizeof( nid );
|
|
- BDB_ID2DISK( e->e_id, &nid );
|
|
-
|
|
- /* store it -- don't override */
|
|
- rc = db->put( db, txn, &key, &data, DB_NOOVERWRITE );
|
|
- if( rc != 0 ) {
|
|
- char buf[ SLAP_TEXT_BUFLEN ];
|
|
- snprintf( buf, sizeof( buf ), "%s => bdb_dn2id_add dn=\"%s\" ID=0x%lx",
|
|
- op->o_log_prefix, e->e_name.bv_val, e->e_id );
|
|
- Debug( LDAP_DEBUG_ANY, "%s: put failed: %s %d\n",
|
|
- buf, db_strerror(rc), rc );
|
|
- goto done;
|
|
- }
|
|
-
|
|
-#ifndef BDB_MULTIPLE_SUFFIXES
|
|
- if( !be_issuffix( op->o_bd, &ptr ))
|
|
-#endif
|
|
- {
|
|
- buf[0] = DN_SUBTREE_PREFIX;
|
|
- rc = db->put( db, txn, &key, &data, DB_NOOVERWRITE );
|
|
- if( rc != 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "=> bdb_dn2id_add 0x%lx: subtree (%s) put failed: %d\n",
|
|
- e->e_id, ptr.bv_val, rc );
|
|
- goto done;
|
|
- }
|
|
-
|
|
-#ifdef BDB_MULTIPLE_SUFFIXES
|
|
- if( !be_issuffix( op->o_bd, &ptr ))
|
|
-#endif
|
|
- {
|
|
- dnParent( &ptr, &pdn );
|
|
-
|
|
- key.size = pdn.bv_len + 2;
|
|
- key.ulen = key.size;
|
|
- pdn.bv_val[-1] = DN_ONE_PREFIX;
|
|
- key.data = pdn.bv_val-1;
|
|
- ptr = pdn;
|
|
-
|
|
- rc = bdb_idl_insert_key( op->o_bd, db, txn, &key, e->e_id );
|
|
-
|
|
- if( rc != 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "=> bdb_dn2id_add 0x%lx: parent (%s) insert failed: %d\n",
|
|
- e->e_id, ptr.bv_val, rc );
|
|
- goto done;
|
|
- }
|
|
- }
|
|
-
|
|
-#ifndef BDB_MULTIPLE_SUFFIXES
|
|
- while( !be_issuffix( op->o_bd, &ptr ))
|
|
-#else
|
|
- for (;;)
|
|
-#endif
|
|
- {
|
|
- ptr.bv_val[-1] = DN_SUBTREE_PREFIX;
|
|
-
|
|
- rc = bdb_idl_insert_key( op->o_bd, db, txn, &key, e->e_id );
|
|
-
|
|
- if( rc != 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "=> bdb_dn2id_add 0x%lx: subtree (%s) insert failed: %d\n",
|
|
- e->e_id, ptr.bv_val, rc );
|
|
- break;
|
|
- }
|
|
-#ifdef BDB_MULTIPLE_SUFFIXES
|
|
- if( be_issuffix( op->o_bd, &ptr )) break;
|
|
-#endif
|
|
- dnParent( &ptr, &pdn );
|
|
-
|
|
- key.size = pdn.bv_len + 2;
|
|
- key.ulen = key.size;
|
|
- key.data = pdn.bv_val - 1;
|
|
- ptr = pdn;
|
|
- }
|
|
- }
|
|
-
|
|
-done:
|
|
- op->o_tmpfree( buf, op->o_tmpmemctx );
|
|
- Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id_add 0x%lx: %d\n", e->e_id, rc, 0 );
|
|
- return rc;
|
|
-}
|
|
-
|
|
-int
|
|
-bdb_dn2id_delete(
|
|
- Operation *op,
|
|
- DB_TXN *txn,
|
|
- EntryInfo *eip,
|
|
- Entry *e )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- DB *db = bdb->bi_dn2id->bdi_db;
|
|
- char *buf;
|
|
- DBT key;
|
|
- struct berval pdn, ptr;
|
|
- int rc;
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_delete 0x%lx: \"%s\"\n",
|
|
- e->e_id, e->e_ndn, 0 );
|
|
-
|
|
- DBTzero( &key );
|
|
- key.size = e->e_nname.bv_len + 2;
|
|
- buf = op->o_tmpalloc( key.size, op->o_tmpmemctx );
|
|
- key.data = buf;
|
|
- key.flags = DB_DBT_USERMEM;
|
|
- buf[0] = DN_BASE_PREFIX;
|
|
- ptr.bv_val = buf+1;
|
|
- ptr.bv_len = e->e_nname.bv_len;
|
|
- AC_MEMCPY( ptr.bv_val, e->e_nname.bv_val, e->e_nname.bv_len );
|
|
- ptr.bv_val[ptr.bv_len] = '\0';
|
|
-
|
|
- /* delete it */
|
|
- rc = db->del( db, txn, &key, 0 );
|
|
- if( rc != 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY, "=> bdb_dn2id_delete 0x%lx: delete failed: %s %d\n",
|
|
- e->e_id, db_strerror(rc), rc );
|
|
- goto done;
|
|
- }
|
|
-
|
|
-#ifndef BDB_MULTIPLE_SUFFIXES
|
|
- if( !be_issuffix( op->o_bd, &ptr ))
|
|
-#endif
|
|
- {
|
|
- buf[0] = DN_SUBTREE_PREFIX;
|
|
- rc = bdb_idl_delete_key( op->o_bd, db, txn, &key, e->e_id );
|
|
- if( rc != 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "=> bdb_dn2id_delete 0x%lx: subtree (%s) delete failed: %d\n",
|
|
- e->e_id, ptr.bv_val, rc );
|
|
- goto done;
|
|
- }
|
|
-
|
|
-#ifdef BDB_MULTIPLE_SUFFIXES
|
|
- if( !be_issuffix( op->o_bd, &ptr ))
|
|
-#endif
|
|
- {
|
|
- dnParent( &ptr, &pdn );
|
|
-
|
|
- key.size = pdn.bv_len + 2;
|
|
- key.ulen = key.size;
|
|
- pdn.bv_val[-1] = DN_ONE_PREFIX;
|
|
- key.data = pdn.bv_val - 1;
|
|
- ptr = pdn;
|
|
-
|
|
- rc = bdb_idl_delete_key( op->o_bd, db, txn, &key, e->e_id );
|
|
-
|
|
- if( rc != 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "=> bdb_dn2id_delete 0x%lx: parent (%s) delete failed: %d\n",
|
|
- e->e_id, ptr.bv_val, rc );
|
|
- goto done;
|
|
- }
|
|
- }
|
|
-
|
|
-#ifndef BDB_MULTIPLE_SUFFIXES
|
|
- while( !be_issuffix( op->o_bd, &ptr ))
|
|
-#else
|
|
- for (;;)
|
|
-#endif
|
|
- {
|
|
- ptr.bv_val[-1] = DN_SUBTREE_PREFIX;
|
|
-
|
|
- rc = bdb_idl_delete_key( op->o_bd, db, txn, &key, e->e_id );
|
|
- if( rc != 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "=> bdb_dn2id_delete 0x%lx: subtree (%s) delete failed: %d\n",
|
|
- e->e_id, ptr.bv_val, rc );
|
|
- goto done;
|
|
- }
|
|
-#ifdef BDB_MULTIPLE_SUFFIXES
|
|
- if( be_issuffix( op->o_bd, &ptr )) break;
|
|
-#endif
|
|
- dnParent( &ptr, &pdn );
|
|
-
|
|
- key.size = pdn.bv_len + 2;
|
|
- key.ulen = key.size;
|
|
- key.data = pdn.bv_val - 1;
|
|
- ptr = pdn;
|
|
- }
|
|
- }
|
|
-
|
|
-done:
|
|
- op->o_tmpfree( buf, op->o_tmpmemctx );
|
|
- Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id_delete 0x%lx: %d\n", e->e_id, rc, 0 );
|
|
- return rc;
|
|
-}
|
|
-
|
|
-int
|
|
-bdb_dn2id(
|
|
- Operation *op,
|
|
- struct berval *dn,
|
|
- EntryInfo *ei,
|
|
- DB_TXN *txn,
|
|
- DBC **cursor )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- DB *db = bdb->bi_dn2id->bdi_db;
|
|
- int rc;
|
|
- DBT key, data;
|
|
- ID nid;
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id(\"%s\")\n", dn->bv_val, 0, 0 );
|
|
-
|
|
- DBTzero( &key );
|
|
- key.size = dn->bv_len + 2;
|
|
- key.data = op->o_tmpalloc( key.size, op->o_tmpmemctx );
|
|
- ((char *)key.data)[0] = DN_BASE_PREFIX;
|
|
- AC_MEMCPY( &((char *)key.data)[1], dn->bv_val, key.size - 1 );
|
|
-
|
|
- /* store the ID */
|
|
- DBTzero( &data );
|
|
- data.data = &nid;
|
|
- data.ulen = sizeof(ID);
|
|
- data.flags = DB_DBT_USERMEM;
|
|
-
|
|
- rc = db->cursor( db, txn, cursor, bdb->bi_db_opflags );
|
|
-
|
|
- /* fetch it */
|
|
- if ( !rc )
|
|
- rc = (*cursor)->c_get( *cursor, &key, &data, DB_SET );
|
|
-
|
|
- if( rc != 0 ) {
|
|
- Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id: get failed: %s (%d)\n",
|
|
- db_strerror( rc ), rc, 0 );
|
|
- } else {
|
|
- BDB_DISK2ID( &nid, &ei->bei_id );
|
|
- Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id: got id=0x%lx\n",
|
|
- ei->bei_id, 0, 0 );
|
|
- }
|
|
- op->o_tmpfree( key.data, op->o_tmpmemctx );
|
|
- return rc;
|
|
-}
|
|
-
|
|
-int
|
|
-bdb_dn2id_children(
|
|
- Operation *op,
|
|
- DB_TXN *txn,
|
|
- Entry *e )
|
|
-{
|
|
- DBT key, data;
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- DB *db = bdb->bi_dn2id->bdi_db;
|
|
- ID id;
|
|
- int rc;
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_children(\"%s\")\n",
|
|
- e->e_nname.bv_val, 0, 0 );
|
|
- DBTzero( &key );
|
|
- key.size = e->e_nname.bv_len + 2;
|
|
- key.data = op->o_tmpalloc( key.size, op->o_tmpmemctx );
|
|
- ((char *)key.data)[0] = DN_ONE_PREFIX;
|
|
- AC_MEMCPY( &((char *)key.data)[1], e->e_nname.bv_val, key.size - 1 );
|
|
-
|
|
- if ( bdb->bi_idl_cache_size ) {
|
|
- rc = bdb_idl_cache_get( bdb, db, &key, NULL );
|
|
- if ( rc != LDAP_NO_SUCH_OBJECT ) {
|
|
- op->o_tmpfree( key.data, op->o_tmpmemctx );
|
|
- return rc;
|
|
- }
|
|
- }
|
|
- /* we actually could do a empty get... */
|
|
- DBTzero( &data );
|
|
- data.data = &id;
|
|
- data.ulen = sizeof(id);
|
|
- data.flags = DB_DBT_USERMEM;
|
|
- data.doff = 0;
|
|
- data.dlen = sizeof(id);
|
|
-
|
|
- rc = db->get( db, txn, &key, &data, bdb->bi_db_opflags );
|
|
- op->o_tmpfree( key.data, op->o_tmpmemctx );
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id_children(\"%s\"): %s (%d)\n",
|
|
- e->e_nname.bv_val,
|
|
- rc == 0 ? "" : ( rc == DB_NOTFOUND ? "no " :
|
|
- db_strerror(rc) ), rc );
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-int
|
|
-bdb_dn2idl(
|
|
- Operation *op,
|
|
- DB_TXN *txn,
|
|
- struct berval *ndn,
|
|
- EntryInfo *ei,
|
|
- ID *ids,
|
|
- ID *stack )
|
|
-{
|
|
- int rc;
|
|
- DBT key;
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- DB *db = bdb->bi_dn2id->bdi_db;
|
|
- int prefix = ( op->ors_scope == LDAP_SCOPE_ONELEVEL )
|
|
- ? DN_ONE_PREFIX : DN_SUBTREE_PREFIX;
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2idl(\"%s\")\n",
|
|
- ndn->bv_val, 0, 0 );
|
|
-
|
|
-#ifndef BDB_MULTIPLE_SUFFIXES
|
|
- if ( prefix == DN_SUBTREE_PREFIX
|
|
- && ( ei->bei_id == 0 ||
|
|
- ( ei->bei_parent->bei_id == 0 && op->o_bd->be_suffix[0].bv_len ))) {
|
|
- BDB_IDL_ALL(bdb, ids);
|
|
- return 0;
|
|
- }
|
|
-#endif
|
|
-
|
|
- DBTzero( &key );
|
|
- key.size = ndn->bv_len + 2;
|
|
- key.ulen = key.size;
|
|
- key.flags = DB_DBT_USERMEM;
|
|
- key.data = op->o_tmpalloc( key.size, op->o_tmpmemctx );
|
|
- ((char *)key.data)[0] = prefix;
|
|
- AC_MEMCPY( &((char *)key.data)[1], ndn->bv_val, key.size - 1 );
|
|
-
|
|
- BDB_IDL_ZERO( ids );
|
|
- rc = bdb_idl_fetch_key( op->o_bd, db, txn, &key, ids, NULL, 0 );
|
|
-
|
|
- if( rc != 0 ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<= bdb_dn2idl: get failed: %s (%d)\n",
|
|
- db_strerror( rc ), rc, 0 );
|
|
-
|
|
- } else {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<= bdb_dn2idl: id=%ld first=%ld last=%ld\n",
|
|
- (long) ids[0],
|
|
- (long) BDB_IDL_FIRST( ids ), (long) BDB_IDL_LAST( ids ) );
|
|
- }
|
|
-
|
|
- op->o_tmpfree( key.data, op->o_tmpmemctx );
|
|
- return rc;
|
|
-}
|
|
-
|
|
-#else /* BDB_HIER */
|
|
-/* Management routines for a hierarchically structured database.
|
|
- *
|
|
- * Instead of a ldbm-style dn2id database, we use a hierarchical one. Each
|
|
- * entry in this database is a struct diskNode, keyed by entryID and with
|
|
- * the data containing the RDN and entryID of the node's children. We use
|
|
- * a B-Tree with sorted duplicates to store all the children of a node under
|
|
- * the same key. Also, the first item under the key contains the entry's own
|
|
- * rdn and the ID of the node's parent, to allow bottom-up tree traversal as
|
|
- * well as top-down. To keep this info first in the list, the high bit of all
|
|
- * subsequent nrdnlen's is always set. This means we can only accomodate
|
|
- * RDNs up to length 32767, but that's fine since full DNs are already
|
|
- * restricted to 8192.
|
|
- *
|
|
- * The diskNode is a variable length structure. This definition is not
|
|
- * directly usable for in-memory manipulation.
|
|
- */
|
|
-typedef struct diskNode {
|
|
- unsigned char nrdnlen[2];
|
|
- char nrdn[1];
|
|
- char rdn[1]; /* variable placement */
|
|
- unsigned char entryID[sizeof(ID)]; /* variable placement */
|
|
-} diskNode;
|
|
-
|
|
-/* Sort function for the sorted duplicate data items of a dn2id key.
|
|
- * Sorts based on normalized RDN, in length order.
|
|
- */
|
|
-int
|
|
-hdb_dup_compare(
|
|
- DB *db,
|
|
- const DBT *usrkey,
|
|
- const DBT *curkey
|
|
-)
|
|
-{
|
|
- diskNode *un, *cn;
|
|
- int rc;
|
|
-
|
|
- un = (diskNode *)usrkey->data;
|
|
- cn = (diskNode *)curkey->data;
|
|
-
|
|
- /* data is not aligned, cannot compare directly */
|
|
- rc = un->nrdnlen[0] - cn->nrdnlen[0];
|
|
- if ( rc ) return rc;
|
|
- rc = un->nrdnlen[1] - cn->nrdnlen[1];
|
|
- if ( rc ) return rc;
|
|
-
|
|
- return strcmp( un->nrdn, cn->nrdn );
|
|
-}
|
|
-
|
|
-/* This function constructs a full DN for a given entry.
|
|
- */
|
|
-int hdb_fix_dn(
|
|
- Entry *e,
|
|
- int checkit )
|
|
-{
|
|
- EntryInfo *ei;
|
|
- int rlen = 0, nrlen = 0;
|
|
- char *ptr, *nptr;
|
|
- int max = 0;
|
|
-
|
|
- if ( !e->e_id )
|
|
- return 0;
|
|
-
|
|
- /* count length of all DN components */
|
|
- for ( ei = BEI(e); ei && ei->bei_id; ei=ei->bei_parent ) {
|
|
- rlen += ei->bei_rdn.bv_len + 1;
|
|
- nrlen += ei->bei_nrdn.bv_len + 1;
|
|
- if (ei->bei_modrdns > max) max = ei->bei_modrdns;
|
|
- }
|
|
-
|
|
- /* See if the entry DN was invalidated by a subtree rename */
|
|
- if ( checkit ) {
|
|
- if ( BEI(e)->bei_modrdns >= max ) {
|
|
- return 0;
|
|
- }
|
|
- /* We found a mismatch, tell the caller to lock it */
|
|
- if ( checkit == 1 ) {
|
|
- return 1;
|
|
- }
|
|
- /* checkit == 2. do the fix. */
|
|
- free( e->e_name.bv_val );
|
|
- free( e->e_nname.bv_val );
|
|
- }
|
|
-
|
|
- e->e_name.bv_len = rlen - 1;
|
|
- e->e_nname.bv_len = nrlen - 1;
|
|
- e->e_name.bv_val = ch_malloc(rlen);
|
|
- e->e_nname.bv_val = ch_malloc(nrlen);
|
|
- ptr = e->e_name.bv_val;
|
|
- nptr = e->e_nname.bv_val;
|
|
- for ( ei = BEI(e); ei && ei->bei_id; ei=ei->bei_parent ) {
|
|
- ptr = lutil_strcopy(ptr, ei->bei_rdn.bv_val);
|
|
- nptr = lutil_strcopy(nptr, ei->bei_nrdn.bv_val);
|
|
- if ( ei->bei_parent ) {
|
|
- *ptr++ = ',';
|
|
- *nptr++ = ',';
|
|
- }
|
|
- }
|
|
- BEI(e)->bei_modrdns = max;
|
|
- if ( ptr > e->e_name.bv_val ) ptr[-1] = '\0';
|
|
- if ( nptr > e->e_nname.bv_val ) nptr[-1] = '\0';
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/* We add two elements to the DN2ID database - a data item under the parent's
|
|
- * entryID containing the child's RDN and entryID, and an item under the
|
|
- * child's entryID containing the parent's entryID.
|
|
- */
|
|
-int
|
|
-hdb_dn2id_add(
|
|
- Operation *op,
|
|
- DB_TXN *txn,
|
|
- EntryInfo *eip,
|
|
- Entry *e )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- DB *db = bdb->bi_dn2id->bdi_db;
|
|
- DBT key, data;
|
|
- ID nid;
|
|
- int rc, rlen, nrlen;
|
|
- diskNode *d;
|
|
- char *ptr;
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "=> hdb_dn2id_add 0x%lx: \"%s\"\n",
|
|
- e->e_id, e->e_ndn, 0 );
|
|
-
|
|
- nrlen = dn_rdnlen( op->o_bd, &e->e_nname );
|
|
- if (nrlen) {
|
|
- rlen = dn_rdnlen( op->o_bd, &e->e_name );
|
|
- } else {
|
|
- nrlen = e->e_nname.bv_len;
|
|
- rlen = e->e_name.bv_len;
|
|
- }
|
|
-
|
|
- d = op->o_tmpalloc(sizeof(diskNode) + rlen + nrlen, op->o_tmpmemctx);
|
|
- d->nrdnlen[1] = nrlen & 0xff;
|
|
- d->nrdnlen[0] = (nrlen >> 8) | 0x80;
|
|
- ptr = lutil_strncopy( d->nrdn, e->e_nname.bv_val, nrlen );
|
|
- *ptr++ = '\0';
|
|
- ptr = lutil_strncopy( ptr, e->e_name.bv_val, rlen );
|
|
- *ptr++ = '\0';
|
|
- BDB_ID2DISK( e->e_id, ptr );
|
|
-
|
|
- DBTzero(&key);
|
|
- DBTzero(&data);
|
|
- key.size = sizeof(ID);
|
|
- key.flags = DB_DBT_USERMEM;
|
|
- BDB_ID2DISK( eip->bei_id, &nid );
|
|
-
|
|
- key.data = &nid;
|
|
-
|
|
- /* Need to make dummy root node once. Subsequent attempts
|
|
- * will fail harmlessly.
|
|
- */
|
|
- if ( eip->bei_id == 0 ) {
|
|
- diskNode dummy = {{0, 0}, "", "", ""};
|
|
- data.data = &dummy;
|
|
- data.size = sizeof(diskNode);
|
|
- data.flags = DB_DBT_USERMEM;
|
|
-
|
|
- db->put( db, txn, &key, &data, DB_NODUPDATA );
|
|
- }
|
|
-
|
|
- data.data = d;
|
|
- data.size = sizeof(diskNode) + rlen + nrlen;
|
|
- data.flags = DB_DBT_USERMEM;
|
|
-
|
|
- rc = db->put( db, txn, &key, &data, DB_NODUPDATA );
|
|
-
|
|
- if (rc == 0) {
|
|
- BDB_ID2DISK( e->e_id, &nid );
|
|
- BDB_ID2DISK( eip->bei_id, ptr );
|
|
- d->nrdnlen[0] ^= 0x80;
|
|
-
|
|
- rc = db->put( db, txn, &key, &data, DB_NODUPDATA );
|
|
- }
|
|
-
|
|
- /* Update all parents' IDL cache entries */
|
|
- if ( rc == 0 && bdb->bi_idl_cache_size ) {
|
|
- ID tmp[2];
|
|
- char *ptr = ((char *)&tmp[1])-1;
|
|
- key.data = ptr;
|
|
- key.size = sizeof(ID)+1;
|
|
- tmp[1] = eip->bei_id;
|
|
- *ptr = DN_ONE_PREFIX;
|
|
- bdb_idl_cache_add_id( bdb, db, &key, e->e_id );
|
|
- if ( eip->bei_parent ) {
|
|
- *ptr = DN_SUBTREE_PREFIX;
|
|
- for (; eip && eip->bei_parent->bei_id; eip = eip->bei_parent) {
|
|
- tmp[1] = eip->bei_id;
|
|
- bdb_idl_cache_add_id( bdb, db, &key, e->e_id );
|
|
- }
|
|
- /* Handle DB with empty suffix */
|
|
- if ( !op->o_bd->be_suffix[0].bv_len && eip ) {
|
|
- tmp[1] = eip->bei_id;
|
|
- bdb_idl_cache_add_id( bdb, db, &key, e->e_id );
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- op->o_tmpfree( d, op->o_tmpmemctx );
|
|
- Debug( LDAP_DEBUG_TRACE, "<= hdb_dn2id_add 0x%lx: %d\n", e->e_id, rc, 0 );
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-int
|
|
-hdb_dn2id_delete(
|
|
- Operation *op,
|
|
- DB_TXN *txn,
|
|
- EntryInfo *eip,
|
|
- Entry *e )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- DB *db = bdb->bi_dn2id->bdi_db;
|
|
- DBT key, data;
|
|
- DBC *cursor;
|
|
- diskNode *d;
|
|
- int rc;
|
|
- ID nid;
|
|
- unsigned char dlen[2];
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "=> hdb_dn2id_delete 0x%lx: \"%s\"\n",
|
|
- e->e_id, e->e_ndn, 0 );
|
|
-
|
|
- DBTzero(&key);
|
|
- key.size = sizeof(ID);
|
|
- key.ulen = key.size;
|
|
- key.flags = DB_DBT_USERMEM;
|
|
- BDB_ID2DISK( eip->bei_id, &nid );
|
|
-
|
|
- DBTzero(&data);
|
|
- data.size = sizeof(diskNode) + BEI(e)->bei_nrdn.bv_len - sizeof(ID) - 1;
|
|
- data.ulen = data.size;
|
|
- data.dlen = data.size;
|
|
- data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
|
|
-
|
|
- key.data = &nid;
|
|
-
|
|
- d = op->o_tmpalloc( data.size, op->o_tmpmemctx );
|
|
- d->nrdnlen[1] = BEI(e)->bei_nrdn.bv_len & 0xff;
|
|
- d->nrdnlen[0] = (BEI(e)->bei_nrdn.bv_len >> 8) | 0x80;
|
|
- dlen[0] = d->nrdnlen[0];
|
|
- dlen[1] = d->nrdnlen[1];
|
|
- memcpy( d->nrdn, BEI(e)->bei_nrdn.bv_val, BEI(e)->bei_nrdn.bv_len+1 );
|
|
- data.data = d;
|
|
-
|
|
- rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
|
|
- if ( rc ) goto func_leave;
|
|
-
|
|
- /* Delete our ID from the parent's list */
|
|
- rc = cursor->c_get( cursor, &key, &data, DB_GET_BOTH_RANGE );
|
|
- if ( rc == 0 ) {
|
|
- if ( dlen[1] == d->nrdnlen[1] && dlen[0] == d->nrdnlen[0] &&
|
|
- !strcmp( d->nrdn, BEI(e)->bei_nrdn.bv_val ))
|
|
- rc = cursor->c_del( cursor, 0 );
|
|
- else
|
|
- rc = DB_NOTFOUND;
|
|
- }
|
|
-
|
|
- /* Delete our ID from the tree. With sorted duplicates, this
|
|
- * will leave any child nodes still hanging around. This is OK
|
|
- * for modrdn, which will add our info back in later.
|
|
- */
|
|
- if ( rc == 0 ) {
|
|
- BDB_ID2DISK( e->e_id, &nid );
|
|
- rc = cursor->c_get( cursor, &key, &data, DB_SET );
|
|
- if ( rc == 0 )
|
|
- rc = cursor->c_del( cursor, 0 );
|
|
- }
|
|
-
|
|
- cursor->c_close( cursor );
|
|
-func_leave:
|
|
- op->o_tmpfree( d, op->o_tmpmemctx );
|
|
-
|
|
- /* Delete IDL cache entries */
|
|
- if ( rc == 0 && bdb->bi_idl_cache_size ) {
|
|
- ID tmp[2];
|
|
- char *ptr = ((char *)&tmp[1])-1;
|
|
- key.data = ptr;
|
|
- key.size = sizeof(ID)+1;
|
|
- tmp[1] = eip->bei_id;
|
|
- *ptr = DN_ONE_PREFIX;
|
|
- bdb_idl_cache_del_id( bdb, db, &key, e->e_id );
|
|
- if ( eip ->bei_parent ) {
|
|
- *ptr = DN_SUBTREE_PREFIX;
|
|
- for (; eip && eip->bei_parent->bei_id; eip = eip->bei_parent) {
|
|
- tmp[1] = eip->bei_id;
|
|
- bdb_idl_cache_del_id( bdb, db, &key, e->e_id );
|
|
- }
|
|
- /* Handle DB with empty suffix */
|
|
- if ( !op->o_bd->be_suffix[0].bv_len && eip ) {
|
|
- tmp[1] = eip->bei_id;
|
|
- bdb_idl_cache_del_id( bdb, db, &key, e->e_id );
|
|
- }
|
|
- }
|
|
- }
|
|
- Debug( LDAP_DEBUG_TRACE, "<= hdb_dn2id_delete 0x%lx: %d\n", e->e_id, rc, 0 );
|
|
- return rc;
|
|
-}
|
|
-
|
|
-
|
|
-int
|
|
-hdb_dn2id(
|
|
- Operation *op,
|
|
- struct berval *in,
|
|
- EntryInfo *ei,
|
|
- DB_TXN *txn,
|
|
- DBC **cursor )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- DB *db = bdb->bi_dn2id->bdi_db;
|
|
- DBT key, data;
|
|
- int rc = 0, nrlen;
|
|
- diskNode *d;
|
|
- char *ptr;
|
|
- unsigned char dlen[2];
|
|
- ID idp, parentID;
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "=> hdb_dn2id(\"%s\")\n", in->bv_val, 0, 0 );
|
|
-
|
|
- nrlen = dn_rdnlen( op->o_bd, in );
|
|
- if (!nrlen) nrlen = in->bv_len;
|
|
-
|
|
- DBTzero(&key);
|
|
- key.size = sizeof(ID);
|
|
- key.data = &idp;
|
|
- key.ulen = sizeof(ID);
|
|
- key.flags = DB_DBT_USERMEM;
|
|
- parentID = ( ei->bei_parent != NULL ) ? ei->bei_parent->bei_id : 0;
|
|
- BDB_ID2DISK( parentID, &idp );
|
|
-
|
|
- DBTzero(&data);
|
|
- data.size = sizeof(diskNode) + nrlen - sizeof(ID) - 1;
|
|
- data.ulen = data.size * 3;
|
|
- data.dlen = data.ulen;
|
|
- data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
|
|
-
|
|
- rc = db->cursor( db, txn, cursor, bdb->bi_db_opflags );
|
|
- if ( rc ) return rc;
|
|
-
|
|
- d = op->o_tmpalloc( data.size * 3, op->o_tmpmemctx );
|
|
- d->nrdnlen[1] = nrlen & 0xff;
|
|
- d->nrdnlen[0] = (nrlen >> 8) | 0x80;
|
|
- dlen[0] = d->nrdnlen[0];
|
|
- dlen[1] = d->nrdnlen[1];
|
|
- ptr = lutil_strncopy( d->nrdn, in->bv_val, nrlen );
|
|
- *ptr = '\0';
|
|
- data.data = d;
|
|
-
|
|
- rc = (*cursor)->c_get( *cursor, &key, &data, DB_GET_BOTH_RANGE );
|
|
- if ( rc == 0 && (dlen[1] != d->nrdnlen[1] || dlen[0] != d->nrdnlen[0] ||
|
|
- strncmp( d->nrdn, in->bv_val, nrlen ))) {
|
|
- rc = DB_NOTFOUND;
|
|
- }
|
|
- if ( rc == 0 ) {
|
|
- ptr = (char *) data.data + data.size - sizeof(ID);
|
|
- BDB_DISK2ID( ptr, &ei->bei_id );
|
|
- ei->bei_rdn.bv_len = data.size - sizeof(diskNode) - nrlen;
|
|
- ptr = d->nrdn + nrlen + 1;
|
|
- ber_str2bv( ptr, ei->bei_rdn.bv_len, 1, &ei->bei_rdn );
|
|
- if ( ei->bei_parent != NULL && !ei->bei_parent->bei_dkids ) {
|
|
- db_recno_t dkids;
|
|
- /* How many children does the parent have? */
|
|
- /* FIXME: do we need to lock the parent
|
|
- * entryinfo? Seems safe...
|
|
- */
|
|
- (*cursor)->c_count( *cursor, &dkids, 0 );
|
|
- ei->bei_parent->bei_dkids = dkids;
|
|
- }
|
|
- }
|
|
-
|
|
- op->o_tmpfree( d, op->o_tmpmemctx );
|
|
- if( rc != 0 ) {
|
|
- Debug( LDAP_DEBUG_TRACE, "<= hdb_dn2id: get failed: %s (%d)\n",
|
|
- db_strerror( rc ), rc, 0 );
|
|
- } else {
|
|
- Debug( LDAP_DEBUG_TRACE, "<= hdb_dn2id: got id=0x%lx\n",
|
|
- ei->bei_id, 0, 0 );
|
|
- }
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-int
|
|
-hdb_dn2id_parent(
|
|
- Operation *op,
|
|
- DB_TXN *txn,
|
|
- EntryInfo *ei,
|
|
- ID *idp )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- DB *db = bdb->bi_dn2id->bdi_db;
|
|
- DBT key, data;
|
|
- DBC *cursor;
|
|
- int rc = 0;
|
|
- diskNode *d;
|
|
- char *ptr;
|
|
- ID nid;
|
|
-
|
|
- DBTzero(&key);
|
|
- key.size = sizeof(ID);
|
|
- key.data = &nid;
|
|
- key.ulen = sizeof(ID);
|
|
- key.flags = DB_DBT_USERMEM;
|
|
- BDB_ID2DISK( ei->bei_id, &nid );
|
|
-
|
|
- DBTzero(&data);
|
|
- data.flags = DB_DBT_USERMEM;
|
|
-
|
|
- rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
|
|
- if ( rc ) return rc;
|
|
-
|
|
- data.ulen = sizeof(diskNode) + (SLAP_LDAPDN_MAXLEN * 2);
|
|
- d = op->o_tmpalloc( data.ulen, op->o_tmpmemctx );
|
|
- data.data = d;
|
|
-
|
|
- rc = cursor->c_get( cursor, &key, &data, DB_SET );
|
|
- if ( rc == 0 ) {
|
|
- if (d->nrdnlen[0] & 0x80) {
|
|
- rc = LDAP_OTHER;
|
|
- } else {
|
|
- db_recno_t dkids;
|
|
- ptr = (char *) data.data + data.size - sizeof(ID);
|
|
- BDB_DISK2ID( ptr, idp );
|
|
- ei->bei_nrdn.bv_len = (d->nrdnlen[0] << 8) | d->nrdnlen[1];
|
|
- ber_str2bv( d->nrdn, ei->bei_nrdn.bv_len, 1, &ei->bei_nrdn );
|
|
- ei->bei_rdn.bv_len = data.size - sizeof(diskNode) -
|
|
- ei->bei_nrdn.bv_len;
|
|
- ptr = d->nrdn + ei->bei_nrdn.bv_len + 1;
|
|
- ber_str2bv( ptr, ei->bei_rdn.bv_len, 1, &ei->bei_rdn );
|
|
- /* How many children does this node have? */
|
|
- cursor->c_count( cursor, &dkids, 0 );
|
|
- ei->bei_dkids = dkids;
|
|
- }
|
|
- }
|
|
- cursor->c_close( cursor );
|
|
- op->o_tmpfree( d, op->o_tmpmemctx );
|
|
- return rc;
|
|
-}
|
|
-
|
|
-int
|
|
-hdb_dn2id_children(
|
|
- Operation *op,
|
|
- DB_TXN *txn,
|
|
- Entry *e )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- DB *db = bdb->bi_dn2id->bdi_db;
|
|
- DBT key, data;
|
|
- DBC *cursor;
|
|
- int rc;
|
|
- ID id;
|
|
- diskNode d;
|
|
-
|
|
- DBTzero(&key);
|
|
- key.size = sizeof(ID);
|
|
- key.data = &e->e_id;
|
|
- key.flags = DB_DBT_USERMEM;
|
|
- BDB_ID2DISK( e->e_id, &id );
|
|
-
|
|
- /* IDL cache is in host byte order */
|
|
- if ( bdb->bi_idl_cache_size ) {
|
|
- rc = bdb_idl_cache_get( bdb, db, &key, NULL );
|
|
- if ( rc != LDAP_NO_SUCH_OBJECT ) {
|
|
- return rc;
|
|
- }
|
|
- }
|
|
-
|
|
- key.data = &id;
|
|
- DBTzero(&data);
|
|
- data.data = &d;
|
|
- data.ulen = sizeof(d);
|
|
- data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
|
|
- data.dlen = sizeof(d);
|
|
-
|
|
- rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
|
|
- if ( rc ) return rc;
|
|
-
|
|
- rc = cursor->c_get( cursor, &key, &data, DB_SET );
|
|
- if ( rc == 0 ) {
|
|
- db_recno_t dkids;
|
|
- rc = cursor->c_count( cursor, &dkids, 0 );
|
|
- if ( rc == 0 ) {
|
|
- BEI(e)->bei_dkids = dkids;
|
|
- if ( dkids < 2 ) rc = DB_NOTFOUND;
|
|
- }
|
|
- }
|
|
- cursor->c_close( cursor );
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/* bdb_dn2idl:
|
|
- * We can't just use bdb_idl_fetch_key because
|
|
- * 1 - our data items are longer than just an entry ID
|
|
- * 2 - our data items are sorted alphabetically by nrdn, not by ID.
|
|
- *
|
|
- * We descend the tree recursively, so we define this cookie
|
|
- * to hold our necessary state information. The bdb_dn2idl_internal
|
|
- * function uses this cookie when calling itself.
|
|
- */
|
|
-
|
|
-struct dn2id_cookie {
|
|
- struct bdb_info *bdb;
|
|
- Operation *op;
|
|
- DB_TXN *txn;
|
|
- EntryInfo *ei;
|
|
- ID *ids;
|
|
- ID *tmp;
|
|
- ID *buf;
|
|
- DB *db;
|
|
- DBC *dbc;
|
|
- DBT key;
|
|
- DBT data;
|
|
- ID dbuf;
|
|
- ID id;
|
|
- ID nid;
|
|
- int rc;
|
|
- int depth;
|
|
- char need_sort;
|
|
- char prefix;
|
|
-};
|
|
-
|
|
-static int
|
|
-apply_func(
|
|
- void *data,
|
|
- void *arg )
|
|
-{
|
|
- EntryInfo *ei = data;
|
|
- ID *idl = arg;
|
|
-
|
|
- bdb_idl_append_one( idl, ei->bei_id );
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int
|
|
-hdb_dn2idl_internal(
|
|
- struct dn2id_cookie *cx
|
|
-)
|
|
-{
|
|
- BDB_IDL_ZERO( cx->tmp );
|
|
-
|
|
- if ( cx->bdb->bi_idl_cache_size ) {
|
|
- char *ptr = ((char *)&cx->id)-1;
|
|
-
|
|
- cx->key.data = ptr;
|
|
- cx->key.size = sizeof(ID)+1;
|
|
- if ( cx->prefix == DN_SUBTREE_PREFIX ) {
|
|
- ID *ids = cx->depth ? cx->tmp : cx->ids;
|
|
- *ptr = cx->prefix;
|
|
- cx->rc = bdb_idl_cache_get(cx->bdb, cx->db, &cx->key, ids);
|
|
- if ( cx->rc == LDAP_SUCCESS ) {
|
|
- if ( cx->depth ) {
|
|
- bdb_idl_delete( cx->tmp, cx->id ); /* ITS#6983, drop our own ID */
|
|
- bdb_idl_append( cx->ids, cx->tmp );
|
|
- cx->need_sort = 1;
|
|
- }
|
|
- return cx->rc;
|
|
- }
|
|
- }
|
|
- *ptr = DN_ONE_PREFIX;
|
|
- cx->rc = bdb_idl_cache_get(cx->bdb, cx->db, &cx->key, cx->tmp);
|
|
- if ( cx->rc == LDAP_SUCCESS ) {
|
|
- goto gotit;
|
|
- }
|
|
- if ( cx->rc == DB_NOTFOUND ) {
|
|
- return cx->rc;
|
|
- }
|
|
- }
|
|
-
|
|
- bdb_cache_entryinfo_lock( cx->ei );
|
|
-
|
|
- /* If number of kids in the cache differs from on-disk, load
|
|
- * up all the kids from the database
|
|
- */
|
|
- if ( cx->ei->bei_ckids+1 != cx->ei->bei_dkids ) {
|
|
- EntryInfo ei;
|
|
- db_recno_t dkids = cx->ei->bei_dkids;
|
|
- ei.bei_parent = cx->ei;
|
|
-
|
|
- /* Only one thread should load the cache */
|
|
- while ( cx->ei->bei_state & CACHE_ENTRY_ONELEVEL ) {
|
|
- bdb_cache_entryinfo_unlock( cx->ei );
|
|
- ldap_pvt_thread_yield();
|
|
- bdb_cache_entryinfo_lock( cx->ei );
|
|
- if ( cx->ei->bei_ckids+1 == cx->ei->bei_dkids ) {
|
|
- goto synced;
|
|
- }
|
|
- }
|
|
-
|
|
- cx->ei->bei_state |= CACHE_ENTRY_ONELEVEL;
|
|
-
|
|
- bdb_cache_entryinfo_unlock( cx->ei );
|
|
-
|
|
- cx->rc = cx->db->cursor( cx->db, NULL, &cx->dbc,
|
|
- cx->bdb->bi_db_opflags );
|
|
- if ( cx->rc )
|
|
- goto done_one;
|
|
-
|
|
- cx->data.data = &cx->dbuf;
|
|
- cx->data.ulen = sizeof(ID);
|
|
- cx->data.dlen = sizeof(ID);
|
|
- cx->data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
|
|
-
|
|
- /* The first item holds the parent ID. Ignore it. */
|
|
- cx->key.data = &cx->nid;
|
|
- cx->key.size = sizeof(ID);
|
|
- cx->rc = cx->dbc->c_get( cx->dbc, &cx->key, &cx->data, DB_SET );
|
|
- if ( cx->rc ) {
|
|
- cx->dbc->c_close( cx->dbc );
|
|
- goto done_one;
|
|
- }
|
|
-
|
|
- /* If the on-disk count is zero we've never checked it.
|
|
- * Count it now.
|
|
- */
|
|
- if ( !dkids ) {
|
|
- cx->dbc->c_count( cx->dbc, &dkids, 0 );
|
|
- cx->ei->bei_dkids = dkids;
|
|
- }
|
|
-
|
|
- cx->data.data = cx->buf;
|
|
- cx->data.ulen = BDB_IDL_UM_SIZE * sizeof(ID);
|
|
- cx->data.flags = DB_DBT_USERMEM;
|
|
-
|
|
- if ( dkids > 1 ) {
|
|
- /* Fetch the rest of the IDs in a loop... */
|
|
- while ( (cx->rc = cx->dbc->c_get( cx->dbc, &cx->key, &cx->data,
|
|
- DB_MULTIPLE | DB_NEXT_DUP )) == 0 ) {
|
|
- u_int8_t *j;
|
|
- size_t len;
|
|
- void *ptr;
|
|
- DB_MULTIPLE_INIT( ptr, &cx->data );
|
|
- while (ptr) {
|
|
- DB_MULTIPLE_NEXT( ptr, &cx->data, j, len );
|
|
- if (j) {
|
|
- EntryInfo *ei2;
|
|
- diskNode *d = (diskNode *)j;
|
|
- short nrlen;
|
|
-
|
|
- BDB_DISK2ID( j + len - sizeof(ID), &ei.bei_id );
|
|
- nrlen = ((d->nrdnlen[0] ^ 0x80) << 8) | d->nrdnlen[1];
|
|
- ei.bei_nrdn.bv_len = nrlen;
|
|
- /* nrdn/rdn are set in-place.
|
|
- * hdb_cache_load will copy them as needed
|
|
- */
|
|
- ei.bei_nrdn.bv_val = d->nrdn;
|
|
- ei.bei_rdn.bv_len = len - sizeof(diskNode)
|
|
- - ei.bei_nrdn.bv_len;
|
|
- ei.bei_rdn.bv_val = d->nrdn + ei.bei_nrdn.bv_len + 1;
|
|
- bdb_idl_append_one( cx->tmp, ei.bei_id );
|
|
- hdb_cache_load( cx->bdb, &ei, &ei2 );
|
|
- }
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- cx->rc = cx->dbc->c_close( cx->dbc );
|
|
-done_one:
|
|
- bdb_cache_entryinfo_lock( cx->ei );
|
|
- cx->ei->bei_state &= ~CACHE_ENTRY_ONELEVEL;
|
|
- bdb_cache_entryinfo_unlock( cx->ei );
|
|
- if ( cx->rc )
|
|
- return cx->rc;
|
|
-
|
|
- } else {
|
|
- /* The in-memory cache is in sync with the on-disk data.
|
|
- * do we have any kids?
|
|
- */
|
|
-synced:
|
|
- cx->rc = 0;
|
|
- if ( cx->ei->bei_ckids > 0 ) {
|
|
- /* Walk the kids tree; order is irrelevant since bdb_idl_sort
|
|
- * will sort it later.
|
|
- */
|
|
- avl_apply( cx->ei->bei_kids, apply_func,
|
|
- cx->tmp, -1, AVL_POSTORDER );
|
|
- }
|
|
- bdb_cache_entryinfo_unlock( cx->ei );
|
|
- }
|
|
-
|
|
- if ( !BDB_IDL_IS_RANGE( cx->tmp ) && cx->tmp[0] > 3 )
|
|
- bdb_idl_sort( cx->tmp, cx->buf );
|
|
- if ( cx->bdb->bi_idl_cache_max_size && !BDB_IDL_IS_ZERO( cx->tmp )) {
|
|
- char *ptr = ((char *)&cx->id)-1;
|
|
- cx->key.data = ptr;
|
|
- cx->key.size = sizeof(ID)+1;
|
|
- *ptr = DN_ONE_PREFIX;
|
|
- bdb_idl_cache_put( cx->bdb, cx->db, &cx->key, cx->tmp, cx->rc );
|
|
- }
|
|
-
|
|
-gotit:
|
|
- if ( !BDB_IDL_IS_ZERO( cx->tmp )) {
|
|
- if ( cx->prefix == DN_SUBTREE_PREFIX ) {
|
|
- bdb_idl_append( cx->ids, cx->tmp );
|
|
- cx->need_sort = 1;
|
|
- if ( !(cx->ei->bei_state & CACHE_ENTRY_NO_GRANDKIDS)) {
|
|
- ID *save, idcurs;
|
|
- EntryInfo *ei = cx->ei;
|
|
- int nokids = 1;
|
|
- save = cx->op->o_tmpalloc( BDB_IDL_SIZEOF( cx->tmp ),
|
|
- cx->op->o_tmpmemctx );
|
|
- BDB_IDL_CPY( save, cx->tmp );
|
|
-
|
|
- idcurs = 0;
|
|
- cx->depth++;
|
|
- for ( cx->id = bdb_idl_first( save, &idcurs );
|
|
- cx->id != NOID;
|
|
- cx->id = bdb_idl_next( save, &idcurs )) {
|
|
- EntryInfo *ei2;
|
|
- cx->ei = NULL;
|
|
- if ( bdb_cache_find_id( cx->op, cx->txn, cx->id, &cx->ei,
|
|
- ID_NOENTRY, NULL ))
|
|
- continue;
|
|
- if ( cx->ei ) {
|
|
- ei2 = cx->ei;
|
|
- if ( !( ei2->bei_state & CACHE_ENTRY_NO_KIDS )) {
|
|
- BDB_ID2DISK( cx->id, &cx->nid );
|
|
- hdb_dn2idl_internal( cx );
|
|
- if ( !BDB_IDL_IS_ZERO( cx->tmp ))
|
|
- nokids = 0;
|
|
- }
|
|
- bdb_cache_entryinfo_lock( ei2 );
|
|
- ei2->bei_finders--;
|
|
- bdb_cache_entryinfo_unlock( ei2 );
|
|
- }
|
|
- }
|
|
- cx->depth--;
|
|
- cx->op->o_tmpfree( save, cx->op->o_tmpmemctx );
|
|
- if ( nokids ) {
|
|
- bdb_cache_entryinfo_lock( ei );
|
|
- ei->bei_state |= CACHE_ENTRY_NO_GRANDKIDS;
|
|
- bdb_cache_entryinfo_unlock( ei );
|
|
- }
|
|
- }
|
|
- /* Make sure caller knows it had kids! */
|
|
- cx->tmp[0]=1;
|
|
-
|
|
- cx->rc = 0;
|
|
- } else {
|
|
- BDB_IDL_CPY( cx->ids, cx->tmp );
|
|
- }
|
|
- }
|
|
- return cx->rc;
|
|
-}
|
|
-
|
|
-int
|
|
-hdb_dn2idl(
|
|
- Operation *op,
|
|
- DB_TXN *txn,
|
|
- struct berval *ndn,
|
|
- EntryInfo *ei,
|
|
- ID *ids,
|
|
- ID *stack )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *)op->o_bd->be_private;
|
|
- struct dn2id_cookie cx;
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "=> hdb_dn2idl(\"%s\")\n",
|
|
- ndn->bv_val, 0, 0 );
|
|
-
|
|
-#ifndef BDB_MULTIPLE_SUFFIXES
|
|
- if ( op->ors_scope != LDAP_SCOPE_ONELEVEL &&
|
|
- ( ei->bei_id == 0 ||
|
|
- ( ei->bei_parent->bei_id == 0 && op->o_bd->be_suffix[0].bv_len )))
|
|
- {
|
|
- BDB_IDL_ALL( bdb, ids );
|
|
- return 0;
|
|
- }
|
|
-#endif
|
|
-
|
|
- cx.id = ei->bei_id;
|
|
- BDB_ID2DISK( cx.id, &cx.nid );
|
|
- cx.ei = ei;
|
|
- cx.bdb = bdb;
|
|
- cx.db = cx.bdb->bi_dn2id->bdi_db;
|
|
- cx.prefix = (op->ors_scope == LDAP_SCOPE_ONELEVEL) ?
|
|
- DN_ONE_PREFIX : DN_SUBTREE_PREFIX;
|
|
- cx.ids = ids;
|
|
- cx.tmp = stack;
|
|
- cx.buf = stack + BDB_IDL_UM_SIZE;
|
|
- cx.op = op;
|
|
- cx.txn = txn;
|
|
- cx.need_sort = 0;
|
|
- cx.depth = 0;
|
|
-
|
|
- if ( cx.prefix == DN_SUBTREE_PREFIX ) {
|
|
- ids[0] = 1;
|
|
- ids[1] = cx.id;
|
|
- } else {
|
|
- BDB_IDL_ZERO( ids );
|
|
- }
|
|
- if ( cx.ei->bei_state & CACHE_ENTRY_NO_KIDS )
|
|
- return LDAP_SUCCESS;
|
|
-
|
|
- DBTzero(&cx.key);
|
|
- cx.key.ulen = sizeof(ID);
|
|
- cx.key.size = sizeof(ID);
|
|
- cx.key.flags = DB_DBT_USERMEM;
|
|
-
|
|
- DBTzero(&cx.data);
|
|
-
|
|
- hdb_dn2idl_internal(&cx);
|
|
- if ( cx.need_sort ) {
|
|
- char *ptr = ((char *)&cx.id)-1;
|
|
- if ( !BDB_IDL_IS_RANGE( cx.ids ) && cx.ids[0] > 3 )
|
|
- bdb_idl_sort( cx.ids, cx.tmp );
|
|
- cx.key.data = ptr;
|
|
- cx.key.size = sizeof(ID)+1;
|
|
- *ptr = cx.prefix;
|
|
- cx.id = ei->bei_id;
|
|
- if ( cx.bdb->bi_idl_cache_max_size )
|
|
- bdb_idl_cache_put( cx.bdb, cx.db, &cx.key, cx.ids, cx.rc );
|
|
- }
|
|
-
|
|
- if ( cx.rc == DB_NOTFOUND )
|
|
- cx.rc = LDAP_SUCCESS;
|
|
-
|
|
- return cx.rc;
|
|
-}
|
|
-#endif /* BDB_HIER */
|
|
diff --git a/servers/slapd/back-bdb/error.c b/servers/slapd/back-bdb/error.c
|
|
deleted file mode 100644
|
|
index cf823ec..0000000
|
|
--- a/servers/slapd/back-bdb/error.c
|
|
+++ /dev/null
|
|
@@ -1,62 +0,0 @@
|
|
-/* error.c - BDB errcall routine */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-
|
|
-#include <stdio.h>
|
|
-#include <ac/string.h>
|
|
-
|
|
-#include "slap.h"
|
|
-#include "back-bdb.h"
|
|
-
|
|
-#if DB_VERSION_FULL < 0x04030000
|
|
-void bdb_errcall( const char *pfx, char * msg )
|
|
-#else
|
|
-void bdb_errcall( const DB_ENV *env, const char *pfx, const char * msg )
|
|
-#endif
|
|
-{
|
|
-#ifdef HAVE_EBCDIC
|
|
- if ( msg[0] > 0x7f )
|
|
- __etoa( msg );
|
|
-#endif
|
|
- Debug( LDAP_DEBUG_ANY, "bdb(%s): %s\n", pfx, msg, 0 );
|
|
-}
|
|
-
|
|
-#if DB_VERSION_FULL >= 0x04030000
|
|
-void bdb_msgcall( const DB_ENV *env, const char *msg )
|
|
-{
|
|
-#ifdef HAVE_EBCDIC
|
|
- if ( msg[0] > 0x7f )
|
|
- __etoa( msg );
|
|
-#endif
|
|
- Debug( LDAP_DEBUG_TRACE, "bdb: %s\n", msg, 0, 0 );
|
|
-}
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_EBCDIC
|
|
-
|
|
-#undef db_strerror
|
|
-
|
|
-/* Not re-entrant! */
|
|
-char *ebcdic_dberror( int rc )
|
|
-{
|
|
- static char msg[1024];
|
|
-
|
|
- strcpy( msg, db_strerror( rc ) );
|
|
- __etoa( msg );
|
|
- return msg;
|
|
-}
|
|
-#endif
|
|
diff --git a/servers/slapd/back-bdb/extended.c b/servers/slapd/back-bdb/extended.c
|
|
deleted file mode 100644
|
|
index 74d85df..0000000
|
|
--- a/servers/slapd/back-bdb/extended.c
|
|
+++ /dev/null
|
|
@@ -1,54 +0,0 @@
|
|
-/* extended.c - bdb backend extended routines */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-
|
|
-#include <stdio.h>
|
|
-#include <ac/string.h>
|
|
-
|
|
-#include "back-bdb.h"
|
|
-#include "lber_pvt.h"
|
|
-
|
|
-static struct exop {
|
|
- struct berval *oid;
|
|
- BI_op_extended *extended;
|
|
-} exop_table[] = {
|
|
- { NULL, NULL }
|
|
-};
|
|
-
|
|
-int
|
|
-bdb_extended( Operation *op, SlapReply *rs )
|
|
-/* struct berval *reqoid,
|
|
- struct berval *reqdata,
|
|
- char **rspoid,
|
|
- struct berval **rspdata,
|
|
- LDAPControl *** rspctrls,
|
|
- const char** text,
|
|
- BerVarray *refs
|
|
-) */
|
|
-{
|
|
- int i;
|
|
-
|
|
- for( i=0; exop_table[i].extended != NULL; i++ ) {
|
|
- if( ber_bvcmp( exop_table[i].oid, &op->oq_extended.rs_reqoid ) == 0 ) {
|
|
- return (exop_table[i].extended)( op, rs );
|
|
- }
|
|
- }
|
|
-
|
|
- rs->sr_text = "not supported within naming context";
|
|
- return rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
|
|
-}
|
|
-
|
|
diff --git a/servers/slapd/back-bdb/filterindex.c b/servers/slapd/back-bdb/filterindex.c
|
|
deleted file mode 100644
|
|
index c04c68c..0000000
|
|
--- a/servers/slapd/back-bdb/filterindex.c
|
|
+++ /dev/null
|
|
@@ -1,1183 +0,0 @@
|
|
-/* filterindex.c - generate the list of candidate entries from a filter */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-
|
|
-#include <stdio.h>
|
|
-#include <ac/string.h>
|
|
-
|
|
-#include "back-bdb.h"
|
|
-#include "idl.h"
|
|
-#ifdef LDAP_COMP_MATCH
|
|
-#include <component.h>
|
|
-#endif
|
|
-
|
|
-static int presence_candidates(
|
|
- Operation *op,
|
|
- DB_TXN *rtxn,
|
|
- AttributeDescription *desc,
|
|
- ID *ids );
|
|
-
|
|
-static int equality_candidates(
|
|
- Operation *op,
|
|
- DB_TXN *rtxn,
|
|
- AttributeAssertion *ava,
|
|
- ID *ids,
|
|
- ID *tmp );
|
|
-static int inequality_candidates(
|
|
- Operation *op,
|
|
- DB_TXN *rtxn,
|
|
- AttributeAssertion *ava,
|
|
- ID *ids,
|
|
- ID *tmp,
|
|
- int gtorlt );
|
|
-static int approx_candidates(
|
|
- Operation *op,
|
|
- DB_TXN *rtxn,
|
|
- AttributeAssertion *ava,
|
|
- ID *ids,
|
|
- ID *tmp );
|
|
-static int substring_candidates(
|
|
- Operation *op,
|
|
- DB_TXN *rtxn,
|
|
- SubstringsAssertion *sub,
|
|
- ID *ids,
|
|
- ID *tmp );
|
|
-
|
|
-static int list_candidates(
|
|
- Operation *op,
|
|
- DB_TXN *rtxn,
|
|
- Filter *flist,
|
|
- int ftype,
|
|
- ID *ids,
|
|
- ID *tmp,
|
|
- ID *stack );
|
|
-
|
|
-static int
|
|
-ext_candidates(
|
|
- Operation *op,
|
|
- DB_TXN *rtxn,
|
|
- MatchingRuleAssertion *mra,
|
|
- ID *ids,
|
|
- ID *tmp,
|
|
- ID *stack);
|
|
-
|
|
-#ifdef LDAP_COMP_MATCH
|
|
-static int
|
|
-comp_candidates (
|
|
- Operation *op,
|
|
- DB_TXN *rtxn,
|
|
- MatchingRuleAssertion *mra,
|
|
- ComponentFilter *f,
|
|
- ID *ids,
|
|
- ID *tmp,
|
|
- ID *stack);
|
|
-
|
|
-static int
|
|
-ava_comp_candidates (
|
|
- Operation *op,
|
|
- DB_TXN *rtxn,
|
|
- AttributeAssertion *ava,
|
|
- AttributeAliasing *aa,
|
|
- ID *ids,
|
|
- ID *tmp,
|
|
- ID *stack);
|
|
-#endif
|
|
-
|
|
-int
|
|
-bdb_filter_candidates(
|
|
- Operation *op,
|
|
- DB_TXN *rtxn,
|
|
- Filter *f,
|
|
- ID *ids,
|
|
- ID *tmp,
|
|
- ID *stack )
|
|
-{
|
|
- int rc = 0;
|
|
-#ifdef LDAP_COMP_MATCH
|
|
- AttributeAliasing *aa;
|
|
-#endif
|
|
- Debug( LDAP_DEBUG_FILTER, "=> bdb_filter_candidates\n", 0, 0, 0 );
|
|
-
|
|
- if ( f->f_choice & SLAPD_FILTER_UNDEFINED ) {
|
|
- BDB_IDL_ZERO( ids );
|
|
- goto out;
|
|
- }
|
|
-
|
|
- switch ( f->f_choice ) {
|
|
- case SLAPD_FILTER_COMPUTED:
|
|
- switch( f->f_result ) {
|
|
- case SLAPD_COMPARE_UNDEFINED:
|
|
- /* This technically is not the same as FALSE, but it
|
|
- * certainly will produce no matches.
|
|
- */
|
|
- /* FALL THRU */
|
|
- case LDAP_COMPARE_FALSE:
|
|
- BDB_IDL_ZERO( ids );
|
|
- break;
|
|
- case LDAP_COMPARE_TRUE: {
|
|
- struct bdb_info *bdb = (struct bdb_info *)op->o_bd->be_private;
|
|
- BDB_IDL_ALL( bdb, ids );
|
|
- } break;
|
|
- case LDAP_SUCCESS:
|
|
- /* this is a pre-computed scope, leave it alone */
|
|
- break;
|
|
- }
|
|
- break;
|
|
- case LDAP_FILTER_PRESENT:
|
|
- Debug( LDAP_DEBUG_FILTER, "\tPRESENT\n", 0, 0, 0 );
|
|
- rc = presence_candidates( op, rtxn, f->f_desc, ids );
|
|
- break;
|
|
-
|
|
- case LDAP_FILTER_EQUALITY:
|
|
- Debug( LDAP_DEBUG_FILTER, "\tEQUALITY\n", 0, 0, 0 );
|
|
-#ifdef LDAP_COMP_MATCH
|
|
- if ( is_aliased_attribute && ( aa = is_aliased_attribute ( f->f_ava->aa_desc ) ) ) {
|
|
- rc = ava_comp_candidates ( op, rtxn, f->f_ava, aa, ids, tmp, stack );
|
|
- }
|
|
- else
|
|
-#endif
|
|
- {
|
|
- rc = equality_candidates( op, rtxn, f->f_ava, ids, tmp );
|
|
- }
|
|
- break;
|
|
-
|
|
- case LDAP_FILTER_APPROX:
|
|
- Debug( LDAP_DEBUG_FILTER, "\tAPPROX\n", 0, 0, 0 );
|
|
- rc = approx_candidates( op, rtxn, f->f_ava, ids, tmp );
|
|
- break;
|
|
-
|
|
- case LDAP_FILTER_SUBSTRINGS:
|
|
- Debug( LDAP_DEBUG_FILTER, "\tSUBSTRINGS\n", 0, 0, 0 );
|
|
- rc = substring_candidates( op, rtxn, f->f_sub, ids, tmp );
|
|
- break;
|
|
-
|
|
- case LDAP_FILTER_GE:
|
|
- /* if no GE index, use pres */
|
|
- Debug( LDAP_DEBUG_FILTER, "\tGE\n", 0, 0, 0 );
|
|
- if( f->f_ava->aa_desc->ad_type->sat_ordering &&
|
|
- ( f->f_ava->aa_desc->ad_type->sat_ordering->smr_usage & SLAP_MR_ORDERED_INDEX ) )
|
|
- rc = inequality_candidates( op, rtxn, f->f_ava, ids, tmp, LDAP_FILTER_GE );
|
|
- else
|
|
- rc = presence_candidates( op, rtxn, f->f_ava->aa_desc, ids );
|
|
- break;
|
|
-
|
|
- case LDAP_FILTER_LE:
|
|
- /* if no LE index, use pres */
|
|
- Debug( LDAP_DEBUG_FILTER, "\tLE\n", 0, 0, 0 );
|
|
- if( f->f_ava->aa_desc->ad_type->sat_ordering &&
|
|
- ( f->f_ava->aa_desc->ad_type->sat_ordering->smr_usage & SLAP_MR_ORDERED_INDEX ) )
|
|
- rc = inequality_candidates( op, rtxn, f->f_ava, ids, tmp, LDAP_FILTER_LE );
|
|
- else
|
|
- rc = presence_candidates( op, rtxn, f->f_ava->aa_desc, ids );
|
|
- break;
|
|
-
|
|
- case LDAP_FILTER_NOT:
|
|
- /* no indexing to support NOT filters */
|
|
- Debug( LDAP_DEBUG_FILTER, "\tNOT\n", 0, 0, 0 );
|
|
- { struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- BDB_IDL_ALL( bdb, ids );
|
|
- }
|
|
- break;
|
|
-
|
|
- case LDAP_FILTER_AND:
|
|
- Debug( LDAP_DEBUG_FILTER, "\tAND\n", 0, 0, 0 );
|
|
- rc = list_candidates( op, rtxn,
|
|
- f->f_and, LDAP_FILTER_AND, ids, tmp, stack );
|
|
- break;
|
|
-
|
|
- case LDAP_FILTER_OR:
|
|
- Debug( LDAP_DEBUG_FILTER, "\tOR\n", 0, 0, 0 );
|
|
- rc = list_candidates( op, rtxn,
|
|
- f->f_or, LDAP_FILTER_OR, ids, tmp, stack );
|
|
- break;
|
|
- case LDAP_FILTER_EXT:
|
|
- Debug( LDAP_DEBUG_FILTER, "\tEXT\n", 0, 0, 0 );
|
|
- rc = ext_candidates( op, rtxn, f->f_mra, ids, tmp, stack );
|
|
- break;
|
|
- default:
|
|
- Debug( LDAP_DEBUG_FILTER, "\tUNKNOWN %lu\n",
|
|
- (unsigned long) f->f_choice, 0, 0 );
|
|
- /* Must not return NULL, otherwise extended filters break */
|
|
- { struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- BDB_IDL_ALL( bdb, ids );
|
|
- }
|
|
- }
|
|
-
|
|
-out:
|
|
- Debug( LDAP_DEBUG_FILTER,
|
|
- "<= bdb_filter_candidates: id=%ld first=%ld last=%ld\n",
|
|
- (long) ids[0],
|
|
- (long) BDB_IDL_FIRST( ids ),
|
|
- (long) BDB_IDL_LAST( ids ) );
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-#ifdef LDAP_COMP_MATCH
|
|
-static int
|
|
-comp_list_candidates(
|
|
- Operation *op,
|
|
- DB_TXN *rtxn,
|
|
- MatchingRuleAssertion* mra,
|
|
- ComponentFilter *flist,
|
|
- int ftype,
|
|
- ID *ids,
|
|
- ID *tmp,
|
|
- ID *save )
|
|
-{
|
|
- int rc = 0;
|
|
- ComponentFilter *f;
|
|
-
|
|
- Debug( LDAP_DEBUG_FILTER, "=> comp_list_candidates 0x%x\n", ftype, 0, 0 );
|
|
- for ( f = flist; f != NULL; f = f->cf_next ) {
|
|
- /* ignore precomputed scopes */
|
|
- if ( f->cf_choice == SLAPD_FILTER_COMPUTED &&
|
|
- f->cf_result == LDAP_SUCCESS ) {
|
|
- continue;
|
|
- }
|
|
- BDB_IDL_ZERO( save );
|
|
- rc = comp_candidates( op, rtxn, mra, f, save, tmp, save+BDB_IDL_UM_SIZE );
|
|
-
|
|
- if ( rc != 0 ) {
|
|
- if ( ftype == LDAP_COMP_FILTER_AND ) {
|
|
- rc = 0;
|
|
- continue;
|
|
- }
|
|
- break;
|
|
- }
|
|
-
|
|
- if ( ftype == LDAP_COMP_FILTER_AND ) {
|
|
- if ( f == flist ) {
|
|
- BDB_IDL_CPY( ids, save );
|
|
- } else {
|
|
- bdb_idl_intersection( ids, save );
|
|
- }
|
|
- if( BDB_IDL_IS_ZERO( ids ) )
|
|
- break;
|
|
- } else {
|
|
- if ( f == flist ) {
|
|
- BDB_IDL_CPY( ids, save );
|
|
- } else {
|
|
- bdb_idl_union( ids, save );
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- if( rc == LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_FILTER,
|
|
- "<= comp_list_candidates: id=%ld first=%ld last=%ld\n",
|
|
- (long) ids[0],
|
|
- (long) BDB_IDL_FIRST(ids),
|
|
- (long) BDB_IDL_LAST(ids) );
|
|
-
|
|
- } else {
|
|
- Debug( LDAP_DEBUG_FILTER,
|
|
- "<= comp_list_candidates: undefined rc=%d\n",
|
|
- rc, 0, 0 );
|
|
- }
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static int
|
|
-comp_equality_candidates (
|
|
- Operation *op,
|
|
- DB_TXN *rtxn,
|
|
- MatchingRuleAssertion *mra,
|
|
- ComponentAssertion *ca,
|
|
- ID *ids,
|
|
- ID *tmp,
|
|
- ID *stack)
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- DB *db;
|
|
- int i;
|
|
- int rc;
|
|
- slap_mask_t mask;
|
|
- struct berval prefix = {0, NULL};
|
|
- struct berval *keys = NULL;
|
|
- MatchingRule *mr = mra->ma_rule;
|
|
- Syntax *sat_syntax;
|
|
- ComponentReference* cr_list, *cr;
|
|
- AttrInfo *ai;
|
|
-
|
|
- BDB_IDL_ALL( bdb, ids );
|
|
-
|
|
- if ( !ca->ca_comp_ref )
|
|
- return 0;
|
|
-
|
|
- ai = bdb_attr_mask( op->o_bd->be_private, mra->ma_desc );
|
|
- if( ai ) {
|
|
- cr_list = ai->ai_cr;
|
|
- }
|
|
- else {
|
|
- return 0;
|
|
- }
|
|
- /* find a component reference to be indexed */
|
|
- sat_syntax = ca->ca_ma_rule->smr_syntax;
|
|
- for ( cr = cr_list ; cr ; cr = cr->cr_next ) {
|
|
- if ( cr->cr_string.bv_len == ca->ca_comp_ref->cr_string.bv_len &&
|
|
- strncmp( cr->cr_string.bv_val, ca->ca_comp_ref->cr_string.bv_val,cr->cr_string.bv_len ) == 0 )
|
|
- break;
|
|
- }
|
|
-
|
|
- if ( !cr )
|
|
- return 0;
|
|
-
|
|
- rc = bdb_index_param( op->o_bd, mra->ma_desc, LDAP_FILTER_EQUALITY,
|
|
- &db, &mask, &prefix );
|
|
-
|
|
- if( rc != LDAP_SUCCESS ) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if( !mr ) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if( !mr->smr_filter ) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- rc = (ca->ca_ma_rule->smr_filter)(
|
|
- LDAP_FILTER_EQUALITY,
|
|
- cr->cr_indexmask,
|
|
- sat_syntax,
|
|
- ca->ca_ma_rule,
|
|
- &prefix,
|
|
- &ca->ca_ma_value,
|
|
- &keys, op->o_tmpmemctx );
|
|
-
|
|
- if( rc != LDAP_SUCCESS ) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if( keys == NULL ) {
|
|
- return 0;
|
|
- }
|
|
- for ( i= 0; keys[i].bv_val != NULL; i++ ) {
|
|
- rc = bdb_key_read( op->o_bd, db, rtxn, &keys[i], tmp, NULL, 0 );
|
|
-
|
|
- if( rc == DB_NOTFOUND ) {
|
|
- BDB_IDL_ZERO( ids );
|
|
- rc = 0;
|
|
- break;
|
|
- } else if( rc != LDAP_SUCCESS ) {
|
|
- break;
|
|
- }
|
|
-
|
|
- if( BDB_IDL_IS_ZERO( tmp ) ) {
|
|
- BDB_IDL_ZERO( ids );
|
|
- break;
|
|
- }
|
|
-
|
|
- if ( i == 0 ) {
|
|
- BDB_IDL_CPY( ids, tmp );
|
|
- } else {
|
|
- bdb_idl_intersection( ids, tmp );
|
|
- }
|
|
-
|
|
- if( BDB_IDL_IS_ZERO( ids ) )
|
|
- break;
|
|
- }
|
|
- ber_bvarray_free_x( keys, op->o_tmpmemctx );
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<= comp_equality_candidates: id=%ld, first=%ld, last=%ld\n",
|
|
- (long) ids[0],
|
|
- (long) BDB_IDL_FIRST(ids),
|
|
- (long) BDB_IDL_LAST(ids) );
|
|
- return( rc );
|
|
-}
|
|
-
|
|
-static int
|
|
-ava_comp_candidates (
|
|
- Operation *op,
|
|
- DB_TXN *rtxn,
|
|
- AttributeAssertion *ava,
|
|
- AttributeAliasing *aa,
|
|
- ID *ids,
|
|
- ID *tmp,
|
|
- ID *stack )
|
|
-{
|
|
- MatchingRuleAssertion mra;
|
|
-
|
|
- mra.ma_rule = ava->aa_desc->ad_type->sat_equality;
|
|
- if ( !mra.ma_rule ) {
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- BDB_IDL_ALL( bdb, ids );
|
|
- return 0;
|
|
- }
|
|
- mra.ma_desc = aa->aa_aliased_ad;
|
|
- mra.ma_rule = ava->aa_desc->ad_type->sat_equality;
|
|
-
|
|
- return comp_candidates ( op, rtxn, &mra, ava->aa_cf, ids, tmp, stack );
|
|
-}
|
|
-
|
|
-static int
|
|
-comp_candidates (
|
|
- Operation *op,
|
|
- DB_TXN *rtxn,
|
|
- MatchingRuleAssertion *mra,
|
|
- ComponentFilter *f,
|
|
- ID *ids,
|
|
- ID *tmp,
|
|
- ID *stack)
|
|
-{
|
|
- int rc;
|
|
-
|
|
- if ( !f ) return LDAP_PROTOCOL_ERROR;
|
|
-
|
|
- Debug( LDAP_DEBUG_FILTER, "comp_candidates\n", 0, 0, 0 );
|
|
- switch ( f->cf_choice ) {
|
|
- case SLAPD_FILTER_COMPUTED:
|
|
- rc = f->cf_result;
|
|
- break;
|
|
- case LDAP_COMP_FILTER_AND:
|
|
- rc = comp_list_candidates( op, rtxn, mra, f->cf_and, LDAP_COMP_FILTER_AND, ids, tmp, stack );
|
|
- break;
|
|
- case LDAP_COMP_FILTER_OR:
|
|
- rc = comp_list_candidates( op, rtxn, mra, f->cf_or, LDAP_COMP_FILTER_OR, ids, tmp, stack );
|
|
- break;
|
|
- case LDAP_COMP_FILTER_NOT:
|
|
- /* No component indexing supported for NOT filter */
|
|
- Debug( LDAP_DEBUG_FILTER, "\tComponent NOT\n", 0, 0, 0 );
|
|
- {
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- BDB_IDL_ALL( bdb, ids );
|
|
- }
|
|
- rc = LDAP_PROTOCOL_ERROR;
|
|
- break;
|
|
- case LDAP_COMP_FILTER_ITEM:
|
|
- rc = comp_equality_candidates( op, rtxn, mra, f->cf_ca, ids, tmp, stack );
|
|
- break;
|
|
- default:
|
|
- {
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- BDB_IDL_ALL( bdb, ids );
|
|
- }
|
|
- rc = LDAP_PROTOCOL_ERROR;
|
|
- }
|
|
-
|
|
- return( rc );
|
|
-}
|
|
-#endif
|
|
-
|
|
-static int
|
|
-ext_candidates(
|
|
- Operation *op,
|
|
- DB_TXN *rtxn,
|
|
- MatchingRuleAssertion *mra,
|
|
- ID *ids,
|
|
- ID *tmp,
|
|
- ID *stack)
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
-
|
|
-#ifdef LDAP_COMP_MATCH
|
|
- /*
|
|
- * Currently Only Component Indexing for componentFilterMatch is supported
|
|
- * Indexing for an extensible filter is not supported yet
|
|
- */
|
|
- if ( mra->ma_cf ) {
|
|
- return comp_candidates ( op, rtxn, mra, mra->ma_cf, ids, tmp, stack);
|
|
- }
|
|
-#endif
|
|
- if ( mra->ma_desc == slap_schema.si_ad_entryDN ) {
|
|
- int rc;
|
|
- EntryInfo *ei;
|
|
-
|
|
- BDB_IDL_ZERO( ids );
|
|
- if ( mra->ma_rule == slap_schema.si_mr_distinguishedNameMatch ) {
|
|
- ei = NULL;
|
|
- rc = bdb_cache_find_ndn( op, rtxn, &mra->ma_value, &ei );
|
|
- if ( rc == LDAP_SUCCESS )
|
|
- bdb_idl_insert( ids, ei->bei_id );
|
|
- if ( ei )
|
|
- bdb_cache_entryinfo_unlock( ei );
|
|
- return 0;
|
|
- } else if ( mra->ma_rule && mra->ma_rule->smr_match ==
|
|
- dnRelativeMatch && dnIsSuffix( &mra->ma_value,
|
|
- op->o_bd->be_nsuffix )) {
|
|
- int scope;
|
|
- if ( mra->ma_rule == slap_schema.si_mr_dnSuperiorMatch ) {
|
|
- struct berval pdn;
|
|
- ei = NULL;
|
|
- dnParent( &mra->ma_value, &pdn );
|
|
- bdb_cache_find_ndn( op, rtxn, &pdn, &ei );
|
|
- if ( ei ) {
|
|
- bdb_cache_entryinfo_unlock( ei );
|
|
- while ( ei && ei->bei_id ) {
|
|
- bdb_idl_insert( ids, ei->bei_id );
|
|
- ei = ei->bei_parent;
|
|
- }
|
|
- }
|
|
- return 0;
|
|
- }
|
|
- if ( mra->ma_rule == slap_schema.si_mr_dnSubtreeMatch )
|
|
- scope = LDAP_SCOPE_SUBTREE;
|
|
- else if ( mra->ma_rule == slap_schema.si_mr_dnOneLevelMatch )
|
|
- scope = LDAP_SCOPE_ONELEVEL;
|
|
- else if ( mra->ma_rule == slap_schema.si_mr_dnSubordinateMatch )
|
|
- scope = LDAP_SCOPE_SUBORDINATE;
|
|
- else
|
|
- scope = LDAP_SCOPE_BASE;
|
|
- if ( scope > LDAP_SCOPE_BASE ) {
|
|
- ei = NULL;
|
|
- rc = bdb_cache_find_ndn( op, rtxn, &mra->ma_value, &ei );
|
|
- if ( ei )
|
|
- bdb_cache_entryinfo_unlock( ei );
|
|
- if ( rc == LDAP_SUCCESS ) {
|
|
- int sc = op->ors_scope;
|
|
- op->ors_scope = scope;
|
|
- rc = bdb_dn2idl( op, rtxn, &mra->ma_value, ei, ids,
|
|
- stack );
|
|
- op->ors_scope = sc;
|
|
- }
|
|
- return 0;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- BDB_IDL_ALL( bdb, ids );
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int
|
|
-list_candidates(
|
|
- Operation *op,
|
|
- DB_TXN *rtxn,
|
|
- Filter *flist,
|
|
- int ftype,
|
|
- ID *ids,
|
|
- ID *tmp,
|
|
- ID *save )
|
|
-{
|
|
- int rc = 0;
|
|
- Filter *f;
|
|
-
|
|
- Debug( LDAP_DEBUG_FILTER, "=> bdb_list_candidates 0x%x\n", ftype, 0, 0 );
|
|
- for ( f = flist; f != NULL; f = f->f_next ) {
|
|
- /* ignore precomputed scopes */
|
|
- if ( f->f_choice == SLAPD_FILTER_COMPUTED &&
|
|
- f->f_result == LDAP_SUCCESS ) {
|
|
- continue;
|
|
- }
|
|
- BDB_IDL_ZERO( save );
|
|
- rc = bdb_filter_candidates( op, rtxn, f, save, tmp,
|
|
- save+BDB_IDL_UM_SIZE );
|
|
-
|
|
- if ( rc != 0 ) {
|
|
- if ( rc == DB_LOCK_DEADLOCK )
|
|
- return rc;
|
|
-
|
|
- if ( ftype == LDAP_FILTER_AND ) {
|
|
- rc = 0;
|
|
- continue;
|
|
- }
|
|
- break;
|
|
- }
|
|
-
|
|
-
|
|
- if ( ftype == LDAP_FILTER_AND ) {
|
|
- if ( f == flist ) {
|
|
- BDB_IDL_CPY( ids, save );
|
|
- } else {
|
|
- bdb_idl_intersection( ids, save );
|
|
- }
|
|
- if( BDB_IDL_IS_ZERO( ids ) )
|
|
- break;
|
|
- } else {
|
|
- if ( f == flist ) {
|
|
- BDB_IDL_CPY( ids, save );
|
|
- } else {
|
|
- bdb_idl_union( ids, save );
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- if( rc == LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_FILTER,
|
|
- "<= bdb_list_candidates: id=%ld first=%ld last=%ld\n",
|
|
- (long) ids[0],
|
|
- (long) BDB_IDL_FIRST(ids),
|
|
- (long) BDB_IDL_LAST(ids) );
|
|
-
|
|
- } else {
|
|
- Debug( LDAP_DEBUG_FILTER,
|
|
- "<= bdb_list_candidates: undefined rc=%d\n",
|
|
- rc, 0, 0 );
|
|
- }
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static int
|
|
-presence_candidates(
|
|
- Operation *op,
|
|
- DB_TXN *rtxn,
|
|
- AttributeDescription *desc,
|
|
- ID *ids )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- DB *db;
|
|
- int rc;
|
|
- slap_mask_t mask;
|
|
- struct berval prefix = {0, NULL};
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "=> bdb_presence_candidates (%s)\n",
|
|
- desc->ad_cname.bv_val, 0, 0 );
|
|
-
|
|
- BDB_IDL_ALL( bdb, ids );
|
|
-
|
|
- if( desc == slap_schema.si_ad_objectClass ) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- rc = bdb_index_param( op->o_bd, desc, LDAP_FILTER_PRESENT,
|
|
- &db, &mask, &prefix );
|
|
-
|
|
- if( rc == LDAP_INAPPROPRIATE_MATCHING ) {
|
|
- /* not indexed */
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<= bdb_presence_candidates: (%s) not indexed\n",
|
|
- desc->ad_cname.bv_val, 0, 0 );
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if( rc != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<= bdb_presence_candidates: (%s) index_param "
|
|
- "returned=%d\n",
|
|
- desc->ad_cname.bv_val, rc, 0 );
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if( prefix.bv_val == NULL ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<= bdb_presence_candidates: (%s) no prefix\n",
|
|
- desc->ad_cname.bv_val, 0, 0 );
|
|
- return -1;
|
|
- }
|
|
-
|
|
- rc = bdb_key_read( op->o_bd, db, rtxn, &prefix, ids, NULL, 0 );
|
|
-
|
|
- if( rc == DB_NOTFOUND ) {
|
|
- BDB_IDL_ZERO( ids );
|
|
- rc = 0;
|
|
- } else if( rc != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<= bdb_presense_candidates: (%s) "
|
|
- "key read failed (%d)\n",
|
|
- desc->ad_cname.bv_val, rc, 0 );
|
|
- goto done;
|
|
- }
|
|
-
|
|
- Debug(LDAP_DEBUG_TRACE,
|
|
- "<= bdb_presence_candidates: id=%ld first=%ld last=%ld\n",
|
|
- (long) ids[0],
|
|
- (long) BDB_IDL_FIRST(ids),
|
|
- (long) BDB_IDL_LAST(ids) );
|
|
-
|
|
-done:
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static int
|
|
-equality_candidates(
|
|
- Operation *op,
|
|
- DB_TXN *rtxn,
|
|
- AttributeAssertion *ava,
|
|
- ID *ids,
|
|
- ID *tmp )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- DB *db;
|
|
- int i;
|
|
- int rc;
|
|
- slap_mask_t mask;
|
|
- struct berval prefix = {0, NULL};
|
|
- struct berval *keys = NULL;
|
|
- MatchingRule *mr;
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "=> bdb_equality_candidates (%s)\n",
|
|
- ava->aa_desc->ad_cname.bv_val, 0, 0 );
|
|
-
|
|
- if ( ava->aa_desc == slap_schema.si_ad_entryDN ) {
|
|
- EntryInfo *ei = NULL;
|
|
- rc = bdb_cache_find_ndn( op, rtxn, &ava->aa_value, &ei );
|
|
- if ( rc == LDAP_SUCCESS ) {
|
|
- /* exactly one ID can match */
|
|
- ids[0] = 1;
|
|
- ids[1] = ei->bei_id;
|
|
- }
|
|
- if ( ei ) {
|
|
- bdb_cache_entryinfo_unlock( ei );
|
|
- }
|
|
- if ( rc == DB_NOTFOUND ) {
|
|
- BDB_IDL_ZERO( ids );
|
|
- rc = 0;
|
|
- }
|
|
- return rc;
|
|
- }
|
|
-
|
|
- BDB_IDL_ALL( bdb, ids );
|
|
-
|
|
- rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_EQUALITY,
|
|
- &db, &mask, &prefix );
|
|
-
|
|
- if ( rc == LDAP_INAPPROPRIATE_MATCHING ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "<= bdb_equality_candidates: (%s) not indexed\n",
|
|
- ava->aa_desc->ad_cname.bv_val, 0, 0 );
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if( rc != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "<= bdb_equality_candidates: (%s) "
|
|
- "index_param failed (%d)\n",
|
|
- ava->aa_desc->ad_cname.bv_val, rc, 0 );
|
|
- return 0;
|
|
- }
|
|
-
|
|
- mr = ava->aa_desc->ad_type->sat_equality;
|
|
- if( !mr ) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if( !mr->smr_filter ) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- rc = (mr->smr_filter)(
|
|
- LDAP_FILTER_EQUALITY,
|
|
- mask,
|
|
- ava->aa_desc->ad_type->sat_syntax,
|
|
- mr,
|
|
- &prefix,
|
|
- &ava->aa_value,
|
|
- &keys, op->o_tmpmemctx );
|
|
-
|
|
- if( rc != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<= bdb_equality_candidates: (%s, %s) "
|
|
- "MR filter failed (%d)\n",
|
|
- prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if( keys == NULL ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<= bdb_equality_candidates: (%s) no keys\n",
|
|
- ava->aa_desc->ad_cname.bv_val, 0, 0 );
|
|
- return 0;
|
|
- }
|
|
-
|
|
- for ( i= 0; keys[i].bv_val != NULL; i++ ) {
|
|
- rc = bdb_key_read( op->o_bd, db, rtxn, &keys[i], tmp, NULL, 0 );
|
|
-
|
|
- if( rc == DB_NOTFOUND ) {
|
|
- BDB_IDL_ZERO( ids );
|
|
- rc = 0;
|
|
- break;
|
|
- } else if( rc != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<= bdb_equality_candidates: (%s) "
|
|
- "key read failed (%d)\n",
|
|
- ava->aa_desc->ad_cname.bv_val, rc, 0 );
|
|
- break;
|
|
- }
|
|
-
|
|
- if( BDB_IDL_IS_ZERO( tmp ) ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<= bdb_equality_candidates: (%s) NULL\n",
|
|
- ava->aa_desc->ad_cname.bv_val, 0, 0 );
|
|
- BDB_IDL_ZERO( ids );
|
|
- break;
|
|
- }
|
|
-
|
|
- if ( i == 0 ) {
|
|
- BDB_IDL_CPY( ids, tmp );
|
|
- } else {
|
|
- bdb_idl_intersection( ids, tmp );
|
|
- }
|
|
-
|
|
- if( BDB_IDL_IS_ZERO( ids ) )
|
|
- break;
|
|
- }
|
|
-
|
|
- ber_bvarray_free_x( keys, op->o_tmpmemctx );
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<= bdb_equality_candidates: id=%ld, first=%ld, last=%ld\n",
|
|
- (long) ids[0],
|
|
- (long) BDB_IDL_FIRST(ids),
|
|
- (long) BDB_IDL_LAST(ids) );
|
|
- return( rc );
|
|
-}
|
|
-
|
|
-
|
|
-static int
|
|
-approx_candidates(
|
|
- Operation *op,
|
|
- DB_TXN *rtxn,
|
|
- AttributeAssertion *ava,
|
|
- ID *ids,
|
|
- ID *tmp )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- DB *db;
|
|
- int i;
|
|
- int rc;
|
|
- slap_mask_t mask;
|
|
- struct berval prefix = {0, NULL};
|
|
- struct berval *keys = NULL;
|
|
- MatchingRule *mr;
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "=> bdb_approx_candidates (%s)\n",
|
|
- ava->aa_desc->ad_cname.bv_val, 0, 0 );
|
|
-
|
|
- BDB_IDL_ALL( bdb, ids );
|
|
-
|
|
- rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_APPROX,
|
|
- &db, &mask, &prefix );
|
|
-
|
|
- if ( rc == LDAP_INAPPROPRIATE_MATCHING ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "<= bdb_approx_candidates: (%s) not indexed\n",
|
|
- ava->aa_desc->ad_cname.bv_val, 0, 0 );
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if( rc != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "<= bdb_approx_candidates: (%s) "
|
|
- "index_param failed (%d)\n",
|
|
- ava->aa_desc->ad_cname.bv_val, rc, 0 );
|
|
- return 0;
|
|
- }
|
|
-
|
|
- mr = ava->aa_desc->ad_type->sat_approx;
|
|
- if( !mr ) {
|
|
- /* no approx matching rule, try equality matching rule */
|
|
- mr = ava->aa_desc->ad_type->sat_equality;
|
|
- }
|
|
-
|
|
- if( !mr ) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if( !mr->smr_filter ) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- rc = (mr->smr_filter)(
|
|
- LDAP_FILTER_APPROX,
|
|
- mask,
|
|
- ava->aa_desc->ad_type->sat_syntax,
|
|
- mr,
|
|
- &prefix,
|
|
- &ava->aa_value,
|
|
- &keys, op->o_tmpmemctx );
|
|
-
|
|
- if( rc != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<= bdb_approx_candidates: (%s, %s) "
|
|
- "MR filter failed (%d)\n",
|
|
- prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if( keys == NULL ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<= bdb_approx_candidates: (%s) no keys (%s)\n",
|
|
- prefix.bv_val, ava->aa_desc->ad_cname.bv_val, 0 );
|
|
- return 0;
|
|
- }
|
|
-
|
|
- for ( i= 0; keys[i].bv_val != NULL; i++ ) {
|
|
- rc = bdb_key_read( op->o_bd, db, rtxn, &keys[i], tmp, NULL, 0 );
|
|
-
|
|
- if( rc == DB_NOTFOUND ) {
|
|
- BDB_IDL_ZERO( ids );
|
|
- rc = 0;
|
|
- break;
|
|
- } else if( rc != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<= bdb_approx_candidates: (%s) "
|
|
- "key read failed (%d)\n",
|
|
- ava->aa_desc->ad_cname.bv_val, rc, 0 );
|
|
- break;
|
|
- }
|
|
-
|
|
- if( BDB_IDL_IS_ZERO( tmp ) ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<= bdb_approx_candidates: (%s) NULL\n",
|
|
- ava->aa_desc->ad_cname.bv_val, 0, 0 );
|
|
- BDB_IDL_ZERO( ids );
|
|
- break;
|
|
- }
|
|
-
|
|
- if ( i == 0 ) {
|
|
- BDB_IDL_CPY( ids, tmp );
|
|
- } else {
|
|
- bdb_idl_intersection( ids, tmp );
|
|
- }
|
|
-
|
|
- if( BDB_IDL_IS_ZERO( ids ) )
|
|
- break;
|
|
- }
|
|
-
|
|
- ber_bvarray_free_x( keys, op->o_tmpmemctx );
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "<= bdb_approx_candidates %ld, first=%ld, last=%ld\n",
|
|
- (long) ids[0],
|
|
- (long) BDB_IDL_FIRST(ids),
|
|
- (long) BDB_IDL_LAST(ids) );
|
|
- return( rc );
|
|
-}
|
|
-
|
|
-static int
|
|
-substring_candidates(
|
|
- Operation *op,
|
|
- DB_TXN *rtxn,
|
|
- SubstringsAssertion *sub,
|
|
- ID *ids,
|
|
- ID *tmp )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- DB *db;
|
|
- int i;
|
|
- int rc;
|
|
- slap_mask_t mask;
|
|
- struct berval prefix = {0, NULL};
|
|
- struct berval *keys = NULL;
|
|
- MatchingRule *mr;
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "=> bdb_substring_candidates (%s)\n",
|
|
- sub->sa_desc->ad_cname.bv_val, 0, 0 );
|
|
-
|
|
- BDB_IDL_ALL( bdb, ids );
|
|
-
|
|
- rc = bdb_index_param( op->o_bd, sub->sa_desc, LDAP_FILTER_SUBSTRINGS,
|
|
- &db, &mask, &prefix );
|
|
-
|
|
- if ( rc == LDAP_INAPPROPRIATE_MATCHING ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "<= bdb_substring_candidates: (%s) not indexed\n",
|
|
- sub->sa_desc->ad_cname.bv_val, 0, 0 );
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if( rc != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "<= bdb_substring_candidates: (%s) "
|
|
- "index_param failed (%d)\n",
|
|
- sub->sa_desc->ad_cname.bv_val, rc, 0 );
|
|
- return 0;
|
|
- }
|
|
-
|
|
- mr = sub->sa_desc->ad_type->sat_substr;
|
|
-
|
|
- if( !mr ) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if( !mr->smr_filter ) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- rc = (mr->smr_filter)(
|
|
- LDAP_FILTER_SUBSTRINGS,
|
|
- mask,
|
|
- sub->sa_desc->ad_type->sat_syntax,
|
|
- mr,
|
|
- &prefix,
|
|
- sub,
|
|
- &keys, op->o_tmpmemctx );
|
|
-
|
|
- if( rc != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<= bdb_substring_candidates: (%s) "
|
|
- "MR filter failed (%d)\n",
|
|
- sub->sa_desc->ad_cname.bv_val, rc, 0 );
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if( keys == NULL ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<= bdb_substring_candidates: (0x%04lx) no keys (%s)\n",
|
|
- mask, sub->sa_desc->ad_cname.bv_val, 0 );
|
|
- return 0;
|
|
- }
|
|
-
|
|
- for ( i= 0; keys[i].bv_val != NULL; i++ ) {
|
|
- rc = bdb_key_read( op->o_bd, db, rtxn, &keys[i], tmp, NULL, 0 );
|
|
-
|
|
- if( rc == DB_NOTFOUND ) {
|
|
- BDB_IDL_ZERO( ids );
|
|
- rc = 0;
|
|
- break;
|
|
- } else if( rc != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<= bdb_substring_candidates: (%s) "
|
|
- "key read failed (%d)\n",
|
|
- sub->sa_desc->ad_cname.bv_val, rc, 0 );
|
|
- break;
|
|
- }
|
|
-
|
|
- if( BDB_IDL_IS_ZERO( tmp ) ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<= bdb_substring_candidates: (%s) NULL\n",
|
|
- sub->sa_desc->ad_cname.bv_val, 0, 0 );
|
|
- BDB_IDL_ZERO( ids );
|
|
- break;
|
|
- }
|
|
-
|
|
- if ( i == 0 ) {
|
|
- BDB_IDL_CPY( ids, tmp );
|
|
- } else {
|
|
- bdb_idl_intersection( ids, tmp );
|
|
- }
|
|
-
|
|
- if( BDB_IDL_IS_ZERO( ids ) )
|
|
- break;
|
|
- }
|
|
-
|
|
- ber_bvarray_free_x( keys, op->o_tmpmemctx );
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "<= bdb_substring_candidates: %ld, first=%ld, last=%ld\n",
|
|
- (long) ids[0],
|
|
- (long) BDB_IDL_FIRST(ids),
|
|
- (long) BDB_IDL_LAST(ids) );
|
|
- return( rc );
|
|
-}
|
|
-
|
|
-static int
|
|
-inequality_candidates(
|
|
- Operation *op,
|
|
- DB_TXN *rtxn,
|
|
- AttributeAssertion *ava,
|
|
- ID *ids,
|
|
- ID *tmp,
|
|
- int gtorlt )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- DB *db;
|
|
- int rc;
|
|
- slap_mask_t mask;
|
|
- struct berval prefix = {0, NULL};
|
|
- struct berval *keys = NULL;
|
|
- MatchingRule *mr;
|
|
- DBC * cursor = NULL;
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "=> bdb_inequality_candidates (%s)\n",
|
|
- ava->aa_desc->ad_cname.bv_val, 0, 0 );
|
|
-
|
|
- BDB_IDL_ALL( bdb, ids );
|
|
-
|
|
- rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_EQUALITY,
|
|
- &db, &mask, &prefix );
|
|
-
|
|
- if ( rc == LDAP_INAPPROPRIATE_MATCHING ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "<= bdb_inequality_candidates: (%s) not indexed\n",
|
|
- ava->aa_desc->ad_cname.bv_val, 0, 0 );
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if( rc != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "<= bdb_inequality_candidates: (%s) "
|
|
- "index_param failed (%d)\n",
|
|
- ava->aa_desc->ad_cname.bv_val, rc, 0 );
|
|
- return 0;
|
|
- }
|
|
-
|
|
- mr = ava->aa_desc->ad_type->sat_equality;
|
|
- if( !mr ) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if( !mr->smr_filter ) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- rc = (mr->smr_filter)(
|
|
- LDAP_FILTER_EQUALITY,
|
|
- mask,
|
|
- ava->aa_desc->ad_type->sat_syntax,
|
|
- mr,
|
|
- &prefix,
|
|
- &ava->aa_value,
|
|
- &keys, op->o_tmpmemctx );
|
|
-
|
|
- if( rc != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<= bdb_inequality_candidates: (%s, %s) "
|
|
- "MR filter failed (%d)\n",
|
|
- prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if( keys == NULL ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<= bdb_inequality_candidates: (%s) no keys\n",
|
|
- ava->aa_desc->ad_cname.bv_val, 0, 0 );
|
|
- return 0;
|
|
- }
|
|
-
|
|
- BDB_IDL_ZERO( ids );
|
|
- while(1) {
|
|
- rc = bdb_key_read( op->o_bd, db, rtxn, &keys[0], tmp, &cursor, gtorlt );
|
|
-
|
|
- if( rc == DB_NOTFOUND ) {
|
|
- rc = 0;
|
|
- break;
|
|
- } else if( rc != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<= bdb_inequality_candidates: (%s) "
|
|
- "key read failed (%d)\n",
|
|
- ava->aa_desc->ad_cname.bv_val, rc, 0 );
|
|
- break;
|
|
- }
|
|
-
|
|
- if( BDB_IDL_IS_ZERO( tmp ) ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<= bdb_inequality_candidates: (%s) NULL\n",
|
|
- ava->aa_desc->ad_cname.bv_val, 0, 0 );
|
|
- break;
|
|
- }
|
|
-
|
|
- bdb_idl_union( ids, tmp );
|
|
-
|
|
- if( op->ors_limit && op->ors_limit->lms_s_unchecked != -1 &&
|
|
- BDB_IDL_N( ids ) >= (unsigned) op->ors_limit->lms_s_unchecked ) {
|
|
- cursor->c_close( cursor );
|
|
- break;
|
|
- }
|
|
- }
|
|
- ber_bvarray_free_x( keys, op->o_tmpmemctx );
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<= bdb_inequality_candidates: id=%ld, first=%ld, last=%ld\n",
|
|
- (long) ids[0],
|
|
- (long) BDB_IDL_FIRST(ids),
|
|
- (long) BDB_IDL_LAST(ids) );
|
|
- return( rc );
|
|
-}
|
|
diff --git a/servers/slapd/back-bdb/id2entry.c b/servers/slapd/back-bdb/id2entry.c
|
|
deleted file mode 100644
|
|
index cc00098..0000000
|
|
--- a/servers/slapd/back-bdb/id2entry.c
|
|
+++ /dev/null
|
|
@@ -1,446 +0,0 @@
|
|
-/* id2entry.c - routines to deal with the id2entry database */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-
|
|
-#include <stdio.h>
|
|
-#include <ac/string.h>
|
|
-#include <ac/errno.h>
|
|
-
|
|
-#include "back-bdb.h"
|
|
-
|
|
-static int bdb_id2entry_put(
|
|
- BackendDB *be,
|
|
- DB_TXN *tid,
|
|
- Entry *e,
|
|
- int flag )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
|
- DB *db = bdb->bi_id2entry->bdi_db;
|
|
- DBT key, data;
|
|
- struct berval bv;
|
|
- int rc;
|
|
- ID nid;
|
|
-#ifdef BDB_HIER
|
|
- struct berval odn, ondn;
|
|
-
|
|
- /* We only store rdns, and they go in the dn2id database. */
|
|
-
|
|
- odn = e->e_name; ondn = e->e_nname;
|
|
-
|
|
- e->e_name = slap_empty_bv;
|
|
- e->e_nname = slap_empty_bv;
|
|
-#endif
|
|
- DBTzero( &key );
|
|
-
|
|
- /* Store ID in BigEndian format */
|
|
- key.data = &nid;
|
|
- key.size = sizeof(ID);
|
|
- BDB_ID2DISK( e->e_id, &nid );
|
|
-
|
|
- rc = entry_encode( e, &bv );
|
|
-#ifdef BDB_HIER
|
|
- e->e_name = odn; e->e_nname = ondn;
|
|
-#endif
|
|
- if( rc != LDAP_SUCCESS ) {
|
|
- return -1;
|
|
- }
|
|
-
|
|
- DBTzero( &data );
|
|
- bv2DBT( &bv, &data );
|
|
-
|
|
- rc = db->put( db, tid, &key, &data, flag );
|
|
-
|
|
- free( bv.bv_val );
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/*
|
|
- * This routine adds (or updates) an entry on disk.
|
|
- * The cache should be already be updated.
|
|
- */
|
|
-
|
|
-
|
|
-int bdb_id2entry_add(
|
|
- BackendDB *be,
|
|
- DB_TXN *tid,
|
|
- Entry *e )
|
|
-{
|
|
- return bdb_id2entry_put(be, tid, e, DB_NOOVERWRITE);
|
|
-}
|
|
-
|
|
-int bdb_id2entry_update(
|
|
- BackendDB *be,
|
|
- DB_TXN *tid,
|
|
- Entry *e )
|
|
-{
|
|
- return bdb_id2entry_put(be, tid, e, 0);
|
|
-}
|
|
-
|
|
-int bdb_id2entry(
|
|
- BackendDB *be,
|
|
- DB_TXN *tid,
|
|
- ID id,
|
|
- Entry **e )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
|
- DB *db = bdb->bi_id2entry->bdi_db;
|
|
- DBT key, data;
|
|
- DBC *cursor;
|
|
- EntryHeader eh;
|
|
- char buf[16];
|
|
- int rc = 0, off;
|
|
- ID nid;
|
|
-
|
|
- *e = NULL;
|
|
-
|
|
- DBTzero( &key );
|
|
- key.data = &nid;
|
|
- key.size = sizeof(ID);
|
|
- BDB_ID2DISK( id, &nid );
|
|
-
|
|
- DBTzero( &data );
|
|
- data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
|
|
-
|
|
- /* fetch it */
|
|
- rc = db->cursor( db, tid, &cursor, bdb->bi_db_opflags );
|
|
- if ( rc ) return rc;
|
|
-
|
|
- /* Get the nattrs / nvals counts first */
|
|
- data.ulen = data.dlen = sizeof(buf);
|
|
- data.data = buf;
|
|
- rc = cursor->c_get( cursor, &key, &data, DB_SET );
|
|
- if ( rc ) goto finish;
|
|
-
|
|
-
|
|
- eh.bv.bv_val = buf;
|
|
- eh.bv.bv_len = data.size;
|
|
- rc = entry_header( &eh );
|
|
- if ( rc ) goto finish;
|
|
-
|
|
- if ( eh.nvals ) {
|
|
- /* Get the size */
|
|
- data.flags ^= DB_DBT_PARTIAL;
|
|
- data.ulen = 0;
|
|
- rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
|
|
- if ( rc != DB_BUFFER_SMALL ) goto finish;
|
|
-
|
|
- /* Allocate a block and retrieve the data */
|
|
- off = eh.data - eh.bv.bv_val;
|
|
- eh.bv.bv_len = eh.nvals * sizeof( struct berval ) + data.size;
|
|
- eh.bv.bv_val = ch_malloc( eh.bv.bv_len );
|
|
- eh.data = eh.bv.bv_val + eh.nvals * sizeof( struct berval );
|
|
- data.data = eh.data;
|
|
- data.ulen = data.size;
|
|
-
|
|
- /* skip past already parsed nattr/nvals */
|
|
- eh.data += off;
|
|
-
|
|
- rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
|
|
- }
|
|
-
|
|
-finish:
|
|
- cursor->c_close( cursor );
|
|
-
|
|
- if( rc != 0 ) {
|
|
- return rc;
|
|
- }
|
|
-
|
|
- if ( eh.nvals ) {
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- rc = entry_decode(&eh, e, bdb->bi_cache.c_zctx);
|
|
-#else
|
|
- rc = entry_decode(&eh, e);
|
|
-#endif
|
|
- } else {
|
|
- *e = entry_alloc();
|
|
- }
|
|
-
|
|
- if( rc == 0 ) {
|
|
- (*e)->e_id = id;
|
|
- } else {
|
|
- /* only free on error. On success, the entry was
|
|
- * decoded in place.
|
|
- */
|
|
-#ifndef SLAP_ZONE_ALLOC
|
|
- ch_free(eh.bv.bv_val);
|
|
-#endif
|
|
- }
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- ch_free(eh.bv.bv_val);
|
|
-#endif
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-int bdb_id2entry_delete(
|
|
- BackendDB *be,
|
|
- DB_TXN *tid,
|
|
- Entry *e )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
|
- DB *db = bdb->bi_id2entry->bdi_db;
|
|
- DBT key;
|
|
- int rc;
|
|
- ID nid;
|
|
-
|
|
- DBTzero( &key );
|
|
- key.data = &nid;
|
|
- key.size = sizeof(ID);
|
|
- BDB_ID2DISK( e->e_id, &nid );
|
|
-
|
|
- /* delete from database */
|
|
- rc = db->del( db, tid, &key, 0 );
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-int bdb_entry_return(
|
|
- Entry *e
|
|
-)
|
|
-{
|
|
- /* Our entries are allocated in two blocks; the data comes from
|
|
- * the db itself and the Entry structure and associated pointers
|
|
- * are allocated in entry_decode. The db data pointer is saved
|
|
- * in e_bv.
|
|
- */
|
|
- if ( e->e_bv.bv_val ) {
|
|
- /* See if the DNs were changed by modrdn */
|
|
- if( e->e_nname.bv_val < e->e_bv.bv_val || e->e_nname.bv_val >
|
|
- e->e_bv.bv_val + e->e_bv.bv_len ) {
|
|
- ch_free(e->e_name.bv_val);
|
|
- ch_free(e->e_nname.bv_val);
|
|
- }
|
|
- e->e_name.bv_val = NULL;
|
|
- e->e_nname.bv_val = NULL;
|
|
- /* In tool mode the e_bv buffer is realloc'd, leave it alone */
|
|
- if( !(slapMode & SLAP_TOOL_MODE) ) {
|
|
- free( e->e_bv.bv_val );
|
|
- }
|
|
- BER_BVZERO( &e->e_bv );
|
|
- }
|
|
- entry_free( e );
|
|
- return 0;
|
|
-}
|
|
-
|
|
-int bdb_entry_release(
|
|
- Operation *op,
|
|
- Entry *e,
|
|
- int rw )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- struct bdb_op_info *boi;
|
|
- OpExtra *oex;
|
|
-
|
|
- /* slapMode : SLAP_SERVER_MODE, SLAP_TOOL_MODE,
|
|
- SLAP_TRUNCATE_MODE, SLAP_UNDEFINED_MODE */
|
|
-
|
|
- if ( slapMode & SLAP_SERVER_MODE ) {
|
|
- /* If not in our cache, just free it */
|
|
- if ( !e->e_private ) {
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- return bdb_entry_return( bdb, e, -1 );
|
|
-#else
|
|
- return bdb_entry_return( e );
|
|
-#endif
|
|
- }
|
|
- /* free entry and reader or writer lock */
|
|
- LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
|
|
- if ( oex->oe_key == bdb ) break;
|
|
- }
|
|
- boi = (struct bdb_op_info *)oex;
|
|
-
|
|
- /* lock is freed with txn */
|
|
- if ( !boi || boi->boi_txn ) {
|
|
- bdb_unlocked_cache_return_entry_rw( bdb, e, rw );
|
|
- } else {
|
|
- struct bdb_lock_info *bli, *prev;
|
|
- for ( prev=(struct bdb_lock_info *)&boi->boi_locks,
|
|
- bli = boi->boi_locks; bli; prev=bli, bli=bli->bli_next ) {
|
|
- if ( bli->bli_id == e->e_id ) {
|
|
- bdb_cache_return_entry_rw( bdb, e, rw, &bli->bli_lock );
|
|
- prev->bli_next = bli->bli_next;
|
|
- /* Cleanup, or let caller know we unlocked */
|
|
- if ( bli->bli_flag & BLI_DONTFREE )
|
|
- bli->bli_flag = 0;
|
|
- else
|
|
- op->o_tmpfree( bli, op->o_tmpmemctx );
|
|
- break;
|
|
- }
|
|
- }
|
|
- if ( !boi->boi_locks ) {
|
|
- LDAP_SLIST_REMOVE( &op->o_extra, &boi->boi_oe, OpExtra, oe_next );
|
|
- if ( !(boi->boi_flag & BOI_DONTFREE))
|
|
- op->o_tmpfree( boi, op->o_tmpmemctx );
|
|
- }
|
|
- }
|
|
- } else {
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- int zseq = -1;
|
|
- if (e->e_private != NULL) {
|
|
- BEI(e)->bei_e = NULL;
|
|
- zseq = BEI(e)->bei_zseq;
|
|
- }
|
|
-#else
|
|
- if (e->e_private != NULL)
|
|
- BEI(e)->bei_e = NULL;
|
|
-#endif
|
|
- e->e_private = NULL;
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- bdb_entry_return ( bdb, e, zseq );
|
|
-#else
|
|
- bdb_entry_return ( e );
|
|
-#endif
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/* return LDAP_SUCCESS IFF we can retrieve the specified entry.
|
|
- */
|
|
-int bdb_entry_get(
|
|
- Operation *op,
|
|
- struct berval *ndn,
|
|
- ObjectClass *oc,
|
|
- AttributeDescription *at,
|
|
- int rw,
|
|
- Entry **ent )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- struct bdb_op_info *boi = NULL;
|
|
- DB_TXN *txn = NULL;
|
|
- Entry *e = NULL;
|
|
- EntryInfo *ei;
|
|
- int rc;
|
|
- const char *at_name = at ? at->ad_cname.bv_val : "(null)";
|
|
-
|
|
- DB_LOCK lock;
|
|
-
|
|
- Debug( LDAP_DEBUG_ARGS,
|
|
- "=> bdb_entry_get: ndn: \"%s\"\n", ndn->bv_val, 0, 0 );
|
|
- Debug( LDAP_DEBUG_ARGS,
|
|
- "=> bdb_entry_get: oc: \"%s\", at: \"%s\"\n",
|
|
- oc ? oc->soc_cname.bv_val : "(null)", at_name, 0);
|
|
-
|
|
- if( op ) {
|
|
- OpExtra *oex;
|
|
- LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
|
|
- if ( oex->oe_key == bdb ) break;
|
|
- }
|
|
- boi = (struct bdb_op_info *)oex;
|
|
- if ( boi )
|
|
- txn = boi->boi_txn;
|
|
- }
|
|
-
|
|
- if ( !txn ) {
|
|
- rc = bdb_reader_get( op, bdb->bi_dbenv, &txn );
|
|
- switch(rc) {
|
|
- case 0:
|
|
- break;
|
|
- default:
|
|
- return LDAP_OTHER;
|
|
- }
|
|
- }
|
|
-
|
|
-dn2entry_retry:
|
|
- /* can we find entry */
|
|
- rc = bdb_dn2entry( op, txn, ndn, &ei, 0, &lock );
|
|
- switch( rc ) {
|
|
- case DB_NOTFOUND:
|
|
- case 0:
|
|
- break;
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- /* the txn must abort and retry */
|
|
- if ( txn ) {
|
|
- if ( boi ) boi->boi_err = rc;
|
|
- return LDAP_BUSY;
|
|
- }
|
|
- ldap_pvt_thread_yield();
|
|
- goto dn2entry_retry;
|
|
- default:
|
|
- if ( boi ) boi->boi_err = rc;
|
|
- return (rc != LDAP_BUSY) ? LDAP_OTHER : LDAP_BUSY;
|
|
- }
|
|
- if (ei) e = ei->bei_e;
|
|
- if (e == NULL) {
|
|
- Debug( LDAP_DEBUG_ACL,
|
|
- "=> bdb_entry_get: cannot find entry: \"%s\"\n",
|
|
- ndn->bv_val, 0, 0 );
|
|
- return LDAP_NO_SUCH_OBJECT;
|
|
- }
|
|
-
|
|
- Debug( LDAP_DEBUG_ACL,
|
|
- "=> bdb_entry_get: found entry: \"%s\"\n",
|
|
- ndn->bv_val, 0, 0 );
|
|
-
|
|
- if ( oc && !is_entry_objectclass( e, oc, 0 )) {
|
|
- Debug( LDAP_DEBUG_ACL,
|
|
- "<= bdb_entry_get: failed to find objectClass %s\n",
|
|
- oc->soc_cname.bv_val, 0, 0 );
|
|
- rc = LDAP_NO_SUCH_ATTRIBUTE;
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- /* NOTE: attr_find() or attrs_find()? */
|
|
- if ( at && attr_find( e->e_attrs, at ) == NULL ) {
|
|
- Debug( LDAP_DEBUG_ACL,
|
|
- "<= bdb_entry_get: failed to find attribute %s\n",
|
|
- at->ad_cname.bv_val, 0, 0 );
|
|
- rc = LDAP_NO_SUCH_ATTRIBUTE;
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
-return_results:
|
|
- if( rc != LDAP_SUCCESS ) {
|
|
- /* free entry */
|
|
- bdb_cache_return_entry_rw(bdb, e, rw, &lock);
|
|
-
|
|
- } else {
|
|
- if ( slapMode & SLAP_SERVER_MODE ) {
|
|
- *ent = e;
|
|
- /* big drag. we need a place to store a read lock so we can
|
|
- * release it later?? If we're in a txn, nothing is needed
|
|
- * here because the locks will go away with the txn.
|
|
- */
|
|
- if ( op ) {
|
|
- if ( !boi ) {
|
|
- boi = op->o_tmpcalloc(1,sizeof(struct bdb_op_info),op->o_tmpmemctx);
|
|
- boi->boi_oe.oe_key = bdb;
|
|
- LDAP_SLIST_INSERT_HEAD( &op->o_extra, &boi->boi_oe, oe_next );
|
|
- }
|
|
- if ( !boi->boi_txn ) {
|
|
- struct bdb_lock_info *bli;
|
|
- bli = op->o_tmpalloc( sizeof(struct bdb_lock_info),
|
|
- op->o_tmpmemctx );
|
|
- bli->bli_next = boi->boi_locks;
|
|
- bli->bli_id = e->e_id;
|
|
- bli->bli_flag = 0;
|
|
- bli->bli_lock = lock;
|
|
- boi->boi_locks = bli;
|
|
- }
|
|
- }
|
|
- } else {
|
|
- *ent = entry_dup( e );
|
|
- bdb_cache_return_entry_rw(bdb, e, rw, &lock);
|
|
- }
|
|
- }
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "bdb_entry_get: rc=%d\n",
|
|
- rc, 0, 0 );
|
|
- return(rc);
|
|
-}
|
|
diff --git a/servers/slapd/back-bdb/idl.c b/servers/slapd/back-bdb/idl.c
|
|
deleted file mode 100644
|
|
index d0c13a6..0000000
|
|
--- a/servers/slapd/back-bdb/idl.c
|
|
+++ /dev/null
|
|
@@ -1,1570 +0,0 @@
|
|
-/* idl.c - ldap id list handling routines */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-
|
|
-#include <stdio.h>
|
|
-#include <ac/string.h>
|
|
-
|
|
-#include "back-bdb.h"
|
|
-#include "idl.h"
|
|
-
|
|
-#define IDL_MAX(x,y) ( (x) > (y) ? (x) : (y) )
|
|
-#define IDL_MIN(x,y) ( (x) < (y) ? (x) : (y) )
|
|
-#define IDL_CMP(x,y) ( (x) < (y) ? -1 : (x) > (y) )
|
|
-
|
|
-#define IDL_LRU_DELETE( bdb, e ) do { \
|
|
- if ( (e) == (bdb)->bi_idl_lru_head ) { \
|
|
- if ( (e)->idl_lru_next == (bdb)->bi_idl_lru_head ) { \
|
|
- (bdb)->bi_idl_lru_head = NULL; \
|
|
- } else { \
|
|
- (bdb)->bi_idl_lru_head = (e)->idl_lru_next; \
|
|
- } \
|
|
- } \
|
|
- if ( (e) == (bdb)->bi_idl_lru_tail ) { \
|
|
- if ( (e)->idl_lru_prev == (bdb)->bi_idl_lru_tail ) { \
|
|
- assert( (bdb)->bi_idl_lru_head == NULL ); \
|
|
- (bdb)->bi_idl_lru_tail = NULL; \
|
|
- } else { \
|
|
- (bdb)->bi_idl_lru_tail = (e)->idl_lru_prev; \
|
|
- } \
|
|
- } \
|
|
- (e)->idl_lru_next->idl_lru_prev = (e)->idl_lru_prev; \
|
|
- (e)->idl_lru_prev->idl_lru_next = (e)->idl_lru_next; \
|
|
-} while ( 0 )
|
|
-
|
|
-static int
|
|
-bdb_idl_entry_cmp( const void *v_idl1, const void *v_idl2 )
|
|
-{
|
|
- const bdb_idl_cache_entry_t *idl1 = v_idl1, *idl2 = v_idl2;
|
|
- int rc;
|
|
-
|
|
- if ((rc = SLAP_PTRCMP( idl1->db, idl2->db ))) return rc;
|
|
- if ((rc = idl1->kstr.bv_len - idl2->kstr.bv_len )) return rc;
|
|
- return ( memcmp ( idl1->kstr.bv_val, idl2->kstr.bv_val , idl1->kstr.bv_len ) );
|
|
-}
|
|
-
|
|
-#if IDL_DEBUG > 0
|
|
-static void idl_check( ID *ids )
|
|
-{
|
|
- if( BDB_IDL_IS_RANGE( ids ) ) {
|
|
- assert( BDB_IDL_RANGE_FIRST(ids) <= BDB_IDL_RANGE_LAST(ids) );
|
|
- } else {
|
|
- ID i;
|
|
- for( i=1; i < ids[0]; i++ ) {
|
|
- assert( ids[i+1] > ids[i] );
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
-#if IDL_DEBUG > 1
|
|
-static void idl_dump( ID *ids )
|
|
-{
|
|
- if( BDB_IDL_IS_RANGE( ids ) ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "IDL: range ( %ld - %ld )\n",
|
|
- (long) BDB_IDL_RANGE_FIRST( ids ),
|
|
- (long) BDB_IDL_RANGE_LAST( ids ) );
|
|
-
|
|
- } else {
|
|
- ID i;
|
|
- Debug( LDAP_DEBUG_ANY, "IDL: size %ld", (long) ids[0], 0, 0 );
|
|
-
|
|
- for( i=1; i<=ids[0]; i++ ) {
|
|
- if( i % 16 == 1 ) {
|
|
- Debug( LDAP_DEBUG_ANY, "\n", 0, 0, 0 );
|
|
- }
|
|
- Debug( LDAP_DEBUG_ANY, " %02lx", (long) ids[i], 0, 0 );
|
|
- }
|
|
-
|
|
- Debug( LDAP_DEBUG_ANY, "\n", 0, 0, 0 );
|
|
- }
|
|
-
|
|
- idl_check( ids );
|
|
-}
|
|
-#endif /* IDL_DEBUG > 1 */
|
|
-#endif /* IDL_DEBUG > 0 */
|
|
-
|
|
-unsigned bdb_idl_search( ID *ids, ID id )
|
|
-{
|
|
-#define IDL_BINARY_SEARCH 1
|
|
-#ifdef IDL_BINARY_SEARCH
|
|
- /*
|
|
- * binary search of id in ids
|
|
- * if found, returns position of id
|
|
- * if not found, returns first postion greater than id
|
|
- */
|
|
- unsigned base = 0;
|
|
- unsigned cursor = 1;
|
|
- int val = 0;
|
|
- unsigned n = ids[0];
|
|
-
|
|
-#if IDL_DEBUG > 0
|
|
- idl_check( ids );
|
|
-#endif
|
|
-
|
|
- while( 0 < n ) {
|
|
- unsigned pivot = n >> 1;
|
|
- cursor = base + pivot + 1;
|
|
- val = IDL_CMP( id, ids[cursor] );
|
|
-
|
|
- if( val < 0 ) {
|
|
- n = pivot;
|
|
-
|
|
- } else if ( val > 0 ) {
|
|
- base = cursor;
|
|
- n -= pivot + 1;
|
|
-
|
|
- } else {
|
|
- return cursor;
|
|
- }
|
|
- }
|
|
-
|
|
- if( val > 0 ) {
|
|
- ++cursor;
|
|
- }
|
|
- return cursor;
|
|
-
|
|
-#else
|
|
- /* (reverse) linear search */
|
|
- int i;
|
|
-
|
|
-#if IDL_DEBUG > 0
|
|
- idl_check( ids );
|
|
-#endif
|
|
-
|
|
- for( i=ids[0]; i; i-- ) {
|
|
- if( id > ids[i] ) {
|
|
- break;
|
|
- }
|
|
- }
|
|
-
|
|
- return i+1;
|
|
-#endif
|
|
-}
|
|
-
|
|
-int bdb_idl_insert( ID *ids, ID id )
|
|
-{
|
|
- unsigned x;
|
|
-
|
|
-#if IDL_DEBUG > 1
|
|
- Debug( LDAP_DEBUG_ANY, "insert: %04lx at %d\n", (long) id, x, 0 );
|
|
- idl_dump( ids );
|
|
-#elif IDL_DEBUG > 0
|
|
- idl_check( ids );
|
|
-#endif
|
|
-
|
|
- if (BDB_IDL_IS_RANGE( ids )) {
|
|
- /* if already in range, treat as a dup */
|
|
- if (id >= BDB_IDL_RANGE_FIRST(ids) && id <= BDB_IDL_RANGE_LAST(ids))
|
|
- return -1;
|
|
- if (id < BDB_IDL_RANGE_FIRST(ids))
|
|
- ids[1] = id;
|
|
- else if (id > BDB_IDL_RANGE_LAST(ids))
|
|
- ids[2] = id;
|
|
- return 0;
|
|
- }
|
|
-
|
|
- x = bdb_idl_search( ids, id );
|
|
- assert( x > 0 );
|
|
-
|
|
- if( x < 1 ) {
|
|
- /* internal error */
|
|
- return -2;
|
|
- }
|
|
-
|
|
- if ( x <= ids[0] && ids[x] == id ) {
|
|
- /* duplicate */
|
|
- return -1;
|
|
- }
|
|
-
|
|
- if ( ++ids[0] >= BDB_IDL_DB_MAX ) {
|
|
- if( id < ids[1] ) {
|
|
- ids[1] = id;
|
|
- ids[2] = ids[ids[0]-1];
|
|
- } else if ( ids[ids[0]-1] < id ) {
|
|
- ids[2] = id;
|
|
- } else {
|
|
- ids[2] = ids[ids[0]-1];
|
|
- }
|
|
- ids[0] = NOID;
|
|
-
|
|
- } else {
|
|
- /* insert id */
|
|
- AC_MEMCPY( &ids[x+1], &ids[x], (ids[0]-x) * sizeof(ID) );
|
|
- ids[x] = id;
|
|
- }
|
|
-
|
|
-#if IDL_DEBUG > 1
|
|
- idl_dump( ids );
|
|
-#elif IDL_DEBUG > 0
|
|
- idl_check( ids );
|
|
-#endif
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-int bdb_idl_delete( ID *ids, ID id )
|
|
-{
|
|
- unsigned x;
|
|
-
|
|
-#if IDL_DEBUG > 1
|
|
- Debug( LDAP_DEBUG_ANY, "delete: %04lx at %d\n", (long) id, x, 0 );
|
|
- idl_dump( ids );
|
|
-#elif IDL_DEBUG > 0
|
|
- idl_check( ids );
|
|
-#endif
|
|
-
|
|
- if (BDB_IDL_IS_RANGE( ids )) {
|
|
- /* If deleting a range boundary, adjust */
|
|
- if ( ids[1] == id )
|
|
- ids[1]++;
|
|
- else if ( ids[2] == id )
|
|
- ids[2]--;
|
|
- /* deleting from inside a range is a no-op */
|
|
-
|
|
- /* If the range has collapsed, re-adjust */
|
|
- if ( ids[1] > ids[2] )
|
|
- ids[0] = 0;
|
|
- else if ( ids[1] == ids[2] )
|
|
- ids[1] = 1;
|
|
- return 0;
|
|
- }
|
|
-
|
|
- x = bdb_idl_search( ids, id );
|
|
- assert( x > 0 );
|
|
-
|
|
- if( x <= 0 ) {
|
|
- /* internal error */
|
|
- return -2;
|
|
- }
|
|
-
|
|
- if( x > ids[0] || ids[x] != id ) {
|
|
- /* not found */
|
|
- return -1;
|
|
-
|
|
- } else if ( --ids[0] == 0 ) {
|
|
- if( x != 1 ) {
|
|
- return -3;
|
|
- }
|
|
-
|
|
- } else {
|
|
- AC_MEMCPY( &ids[x], &ids[x+1], (1+ids[0]-x) * sizeof(ID) );
|
|
- }
|
|
-
|
|
-#if IDL_DEBUG > 1
|
|
- idl_dump( ids );
|
|
-#elif IDL_DEBUG > 0
|
|
- idl_check( ids );
|
|
-#endif
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static char *
|
|
-bdb_show_key(
|
|
- DBT *key,
|
|
- char *buf )
|
|
-{
|
|
- if ( key->size == 4 /* LUTIL_HASH_BYTES */ ) {
|
|
- unsigned char *c = key->data;
|
|
- sprintf( buf, "[%02x%02x%02x%02x]", c[0], c[1], c[2], c[3] );
|
|
- return buf;
|
|
- } else {
|
|
- return key->data;
|
|
- }
|
|
-}
|
|
-
|
|
-/* Find a db/key pair in the IDL cache. If ids is non-NULL,
|
|
- * copy the cached IDL into it, otherwise just return the status.
|
|
- */
|
|
-int
|
|
-bdb_idl_cache_get(
|
|
- struct bdb_info *bdb,
|
|
- DB *db,
|
|
- DBT *key,
|
|
- ID *ids )
|
|
-{
|
|
- bdb_idl_cache_entry_t idl_tmp;
|
|
- bdb_idl_cache_entry_t *matched_idl_entry;
|
|
- int rc = LDAP_NO_SUCH_OBJECT;
|
|
-
|
|
- DBT2bv( key, &idl_tmp.kstr );
|
|
- idl_tmp.db = db;
|
|
- ldap_pvt_thread_rdwr_rlock( &bdb->bi_idl_tree_rwlock );
|
|
- matched_idl_entry = avl_find( bdb->bi_idl_tree, &idl_tmp,
|
|
- bdb_idl_entry_cmp );
|
|
- if ( matched_idl_entry != NULL ) {
|
|
- if ( matched_idl_entry->idl && ids )
|
|
- BDB_IDL_CPY( ids, matched_idl_entry->idl );
|
|
- matched_idl_entry->idl_flags |= CACHE_ENTRY_REFERENCED;
|
|
- if ( matched_idl_entry->idl )
|
|
- rc = LDAP_SUCCESS;
|
|
- else
|
|
- rc = DB_NOTFOUND;
|
|
- }
|
|
- ldap_pvt_thread_rdwr_runlock( &bdb->bi_idl_tree_rwlock );
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-void
|
|
-bdb_idl_cache_put(
|
|
- struct bdb_info *bdb,
|
|
- DB *db,
|
|
- DBT *key,
|
|
- ID *ids,
|
|
- int rc )
|
|
-{
|
|
- bdb_idl_cache_entry_t idl_tmp;
|
|
- bdb_idl_cache_entry_t *ee, *eprev;
|
|
-
|
|
- if ( rc == DB_NOTFOUND || BDB_IDL_IS_ZERO( ids ))
|
|
- return;
|
|
-
|
|
- DBT2bv( key, &idl_tmp.kstr );
|
|
-
|
|
- ee = (bdb_idl_cache_entry_t *) ch_malloc(
|
|
- sizeof( bdb_idl_cache_entry_t ) );
|
|
- ee->db = db;
|
|
- ee->idl = (ID*) ch_malloc( BDB_IDL_SIZEOF ( ids ) );
|
|
- BDB_IDL_CPY( ee->idl, ids );
|
|
-
|
|
- ee->idl_lru_prev = NULL;
|
|
- ee->idl_lru_next = NULL;
|
|
- ee->idl_flags = 0;
|
|
- ber_dupbv( &ee->kstr, &idl_tmp.kstr );
|
|
- ldap_pvt_thread_rdwr_wlock( &bdb->bi_idl_tree_rwlock );
|
|
- if ( avl_insert( &bdb->bi_idl_tree, (caddr_t) ee,
|
|
- bdb_idl_entry_cmp, avl_dup_error ))
|
|
- {
|
|
- ch_free( ee->kstr.bv_val );
|
|
- ch_free( ee->idl );
|
|
- ch_free( ee );
|
|
- ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock );
|
|
- return;
|
|
- }
|
|
- ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock );
|
|
- /* LRU_ADD */
|
|
- if ( bdb->bi_idl_lru_head ) {
|
|
- assert( bdb->bi_idl_lru_tail != NULL );
|
|
- assert( bdb->bi_idl_lru_head->idl_lru_prev != NULL );
|
|
- assert( bdb->bi_idl_lru_head->idl_lru_next != NULL );
|
|
-
|
|
- ee->idl_lru_next = bdb->bi_idl_lru_head;
|
|
- ee->idl_lru_prev = bdb->bi_idl_lru_head->idl_lru_prev;
|
|
- bdb->bi_idl_lru_head->idl_lru_prev->idl_lru_next = ee;
|
|
- bdb->bi_idl_lru_head->idl_lru_prev = ee;
|
|
- } else {
|
|
- ee->idl_lru_next = ee->idl_lru_prev = ee;
|
|
- bdb->bi_idl_lru_tail = ee;
|
|
- }
|
|
- bdb->bi_idl_lru_head = ee;
|
|
-
|
|
- if ( bdb->bi_idl_cache_size >= bdb->bi_idl_cache_max_size ) {
|
|
- int i;
|
|
- eprev = bdb->bi_idl_lru_tail;
|
|
- for ( i = 0; (ee = eprev) != NULL && i < 10; i++ ) {
|
|
- eprev = ee->idl_lru_prev;
|
|
- if ( eprev == ee ) {
|
|
- eprev = NULL;
|
|
- }
|
|
- if ( ee->idl_flags & CACHE_ENTRY_REFERENCED ) {
|
|
- ee->idl_flags ^= CACHE_ENTRY_REFERENCED;
|
|
- continue;
|
|
- }
|
|
- if ( avl_delete( &bdb->bi_idl_tree, (caddr_t) ee,
|
|
- bdb_idl_entry_cmp ) == NULL ) {
|
|
- Debug( LDAP_DEBUG_ANY, "=> bdb_idl_cache_put: "
|
|
- "AVL delete failed\n",
|
|
- 0, 0, 0 );
|
|
- }
|
|
- IDL_LRU_DELETE( bdb, ee );
|
|
- i++;
|
|
- --bdb->bi_idl_cache_size;
|
|
- ch_free( ee->kstr.bv_val );
|
|
- ch_free( ee->idl );
|
|
- ch_free( ee );
|
|
- }
|
|
- bdb->bi_idl_lru_tail = eprev;
|
|
- assert( bdb->bi_idl_lru_tail != NULL
|
|
- || bdb->bi_idl_lru_head == NULL );
|
|
- }
|
|
- bdb->bi_idl_cache_size++;
|
|
- ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
|
|
- ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock );
|
|
-}
|
|
-
|
|
-void
|
|
-bdb_idl_cache_del(
|
|
- struct bdb_info *bdb,
|
|
- DB *db,
|
|
- DBT *key )
|
|
-{
|
|
- bdb_idl_cache_entry_t *matched_idl_entry, idl_tmp;
|
|
- DBT2bv( key, &idl_tmp.kstr );
|
|
- idl_tmp.db = db;
|
|
- ldap_pvt_thread_rdwr_wlock( &bdb->bi_idl_tree_rwlock );
|
|
- matched_idl_entry = avl_find( bdb->bi_idl_tree, &idl_tmp,
|
|
- bdb_idl_entry_cmp );
|
|
- if ( matched_idl_entry != NULL ) {
|
|
- if ( avl_delete( &bdb->bi_idl_tree, (caddr_t) matched_idl_entry,
|
|
- bdb_idl_entry_cmp ) == NULL ) {
|
|
- Debug( LDAP_DEBUG_ANY, "=> bdb_idl_cache_del: "
|
|
- "AVL delete failed\n",
|
|
- 0, 0, 0 );
|
|
- }
|
|
- --bdb->bi_idl_cache_size;
|
|
- ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock );
|
|
- IDL_LRU_DELETE( bdb, matched_idl_entry );
|
|
- ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
|
|
- free( matched_idl_entry->kstr.bv_val );
|
|
- if ( matched_idl_entry->idl )
|
|
- free( matched_idl_entry->idl );
|
|
- free( matched_idl_entry );
|
|
- }
|
|
- ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock );
|
|
-}
|
|
-
|
|
-void
|
|
-bdb_idl_cache_add_id(
|
|
- struct bdb_info *bdb,
|
|
- DB *db,
|
|
- DBT *key,
|
|
- ID id )
|
|
-{
|
|
- bdb_idl_cache_entry_t *cache_entry, idl_tmp;
|
|
- DBT2bv( key, &idl_tmp.kstr );
|
|
- idl_tmp.db = db;
|
|
- ldap_pvt_thread_rdwr_wlock( &bdb->bi_idl_tree_rwlock );
|
|
- cache_entry = avl_find( bdb->bi_idl_tree, &idl_tmp,
|
|
- bdb_idl_entry_cmp );
|
|
- if ( cache_entry != NULL ) {
|
|
- if ( !BDB_IDL_IS_RANGE( cache_entry->idl ) &&
|
|
- cache_entry->idl[0] < BDB_IDL_DB_MAX ) {
|
|
- size_t s = BDB_IDL_SIZEOF( cache_entry->idl ) + sizeof(ID);
|
|
- cache_entry->idl = ch_realloc( cache_entry->idl, s );
|
|
- }
|
|
- bdb_idl_insert( cache_entry->idl, id );
|
|
- }
|
|
- ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock );
|
|
-}
|
|
-
|
|
-void
|
|
-bdb_idl_cache_del_id(
|
|
- struct bdb_info *bdb,
|
|
- DB *db,
|
|
- DBT *key,
|
|
- ID id )
|
|
-{
|
|
- bdb_idl_cache_entry_t *cache_entry, idl_tmp;
|
|
- DBT2bv( key, &idl_tmp.kstr );
|
|
- idl_tmp.db = db;
|
|
- ldap_pvt_thread_rdwr_wlock( &bdb->bi_idl_tree_rwlock );
|
|
- cache_entry = avl_find( bdb->bi_idl_tree, &idl_tmp,
|
|
- bdb_idl_entry_cmp );
|
|
- if ( cache_entry != NULL ) {
|
|
- bdb_idl_delete( cache_entry->idl, id );
|
|
- if ( cache_entry->idl[0] == 0 ) {
|
|
- if ( avl_delete( &bdb->bi_idl_tree, (caddr_t) cache_entry,
|
|
- bdb_idl_entry_cmp ) == NULL ) {
|
|
- Debug( LDAP_DEBUG_ANY, "=> bdb_idl_cache_del: "
|
|
- "AVL delete failed\n",
|
|
- 0, 0, 0 );
|
|
- }
|
|
- --bdb->bi_idl_cache_size;
|
|
- ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock );
|
|
- IDL_LRU_DELETE( bdb, cache_entry );
|
|
- ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
|
|
- free( cache_entry->kstr.bv_val );
|
|
- free( cache_entry->idl );
|
|
- free( cache_entry );
|
|
- }
|
|
- }
|
|
- ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock );
|
|
-}
|
|
-
|
|
-int
|
|
-bdb_idl_fetch_key(
|
|
- BackendDB *be,
|
|
- DB *db,
|
|
- DB_TXN *txn,
|
|
- DBT *key,
|
|
- ID *ids,
|
|
- DBC **saved_cursor,
|
|
- int get_flag )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
|
- int rc;
|
|
- DBT data, key2, *kptr;
|
|
- DBC *cursor;
|
|
- ID *i;
|
|
- void *ptr;
|
|
- size_t len;
|
|
- int rc2;
|
|
- int flags = bdb->bi_db_opflags | DB_MULTIPLE;
|
|
- int opflag;
|
|
-
|
|
- /* If using BerkeleyDB 4.0, the buf must be large enough to
|
|
- * grab the entire IDL in one get(), otherwise BDB will leak
|
|
- * resources on subsequent get's. We can safely call get()
|
|
- * twice - once for the data, and once to get the DB_NOTFOUND
|
|
- * result meaning there's no more data. See ITS#2040 for details.
|
|
- * This bug is fixed in BDB 4.1 so a smaller buffer will work if
|
|
- * stack space is too limited.
|
|
- *
|
|
- * configure now requires Berkeley DB 4.1.
|
|
- */
|
|
-#if DB_VERSION_FULL < 0x04010000
|
|
-# define BDB_ENOUGH 5
|
|
-#else
|
|
- /* We sometimes test with tiny IDLs, and BDB always wants buffers
|
|
- * that are at least one page in size.
|
|
- */
|
|
-# if BDB_IDL_DB_SIZE < 4096
|
|
-# define BDB_ENOUGH 2048
|
|
-# else
|
|
-# define BDB_ENOUGH 1
|
|
-# endif
|
|
-#endif
|
|
- ID buf[BDB_IDL_DB_SIZE*BDB_ENOUGH];
|
|
-
|
|
- char keybuf[16];
|
|
-
|
|
- Debug( LDAP_DEBUG_ARGS,
|
|
- "bdb_idl_fetch_key: %s\n",
|
|
- bdb_show_key( key, keybuf ), 0, 0 );
|
|
-
|
|
- assert( ids != NULL );
|
|
-
|
|
- if ( saved_cursor && *saved_cursor ) {
|
|
- opflag = DB_NEXT;
|
|
- } else if ( get_flag == LDAP_FILTER_GE ) {
|
|
- opflag = DB_SET_RANGE;
|
|
- } else if ( get_flag == LDAP_FILTER_LE ) {
|
|
- opflag = DB_FIRST;
|
|
- } else {
|
|
- opflag = DB_SET;
|
|
- }
|
|
-
|
|
- /* only non-range lookups can use the IDL cache */
|
|
- if ( bdb->bi_idl_cache_size && opflag == DB_SET ) {
|
|
- rc = bdb_idl_cache_get( bdb, db, key, ids );
|
|
- if ( rc != LDAP_NO_SUCH_OBJECT ) return rc;
|
|
- }
|
|
-
|
|
- DBTzero( &data );
|
|
-
|
|
- data.data = buf;
|
|
- data.ulen = sizeof(buf);
|
|
- data.flags = DB_DBT_USERMEM;
|
|
-
|
|
- /* If we're not reusing an existing cursor, get a new one */
|
|
- if( opflag != DB_NEXT ) {
|
|
- rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
|
|
- if( rc != 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
|
|
- "cursor failed: %s (%d)\n", db_strerror(rc), rc, 0 );
|
|
- return rc;
|
|
- }
|
|
- } else {
|
|
- cursor = *saved_cursor;
|
|
- }
|
|
-
|
|
- /* If this is a LE lookup, save original key so we can determine
|
|
- * when to stop. If this is a GE lookup, save the key since it
|
|
- * will be overwritten.
|
|
- */
|
|
- if ( get_flag == LDAP_FILTER_LE || get_flag == LDAP_FILTER_GE ) {
|
|
- DBTzero( &key2 );
|
|
- key2.flags = DB_DBT_USERMEM;
|
|
- key2.ulen = sizeof(keybuf);
|
|
- key2.data = keybuf;
|
|
- key2.size = key->size;
|
|
- AC_MEMCPY( keybuf, key->data, key->size );
|
|
- kptr = &key2;
|
|
- } else {
|
|
- kptr = key;
|
|
- }
|
|
- len = key->size;
|
|
- rc = cursor->c_get( cursor, kptr, &data, flags | opflag );
|
|
-
|
|
- /* skip presence key on range inequality lookups */
|
|
- while (rc == 0 && kptr->size != len) {
|
|
- rc = cursor->c_get( cursor, kptr, &data, flags | DB_NEXT_NODUP );
|
|
- }
|
|
- /* If we're doing a LE compare and the new key is greater than
|
|
- * our search key, we're done
|
|
- */
|
|
- if (rc == 0 && get_flag == LDAP_FILTER_LE && memcmp( kptr->data,
|
|
- key->data, key->size ) > 0 ) {
|
|
- rc = DB_NOTFOUND;
|
|
- }
|
|
- if (rc == 0) {
|
|
- i = ids;
|
|
- while (rc == 0) {
|
|
- u_int8_t *j;
|
|
-
|
|
- DB_MULTIPLE_INIT( ptr, &data );
|
|
- while (ptr) {
|
|
- DB_MULTIPLE_NEXT(ptr, &data, j, len);
|
|
- if (j) {
|
|
- ++i;
|
|
- BDB_DISK2ID( j, i );
|
|
- }
|
|
- }
|
|
- rc = cursor->c_get( cursor, key, &data, flags | DB_NEXT_DUP );
|
|
- }
|
|
- if ( rc == DB_NOTFOUND ) rc = 0;
|
|
- ids[0] = i - ids;
|
|
- /* On disk, a range is denoted by 0 in the first element */
|
|
- if (ids[1] == 0) {
|
|
- if (ids[0] != BDB_IDL_RANGE_SIZE) {
|
|
- Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
|
|
- "range size mismatch: expected %d, got %ld\n",
|
|
- BDB_IDL_RANGE_SIZE, ids[0], 0 );
|
|
- cursor->c_close( cursor );
|
|
- return -1;
|
|
- }
|
|
- BDB_IDL_RANGE( ids, ids[2], ids[3] );
|
|
- }
|
|
- data.size = BDB_IDL_SIZEOF(ids);
|
|
- }
|
|
-
|
|
- if ( saved_cursor && rc == 0 ) {
|
|
- if ( !*saved_cursor )
|
|
- *saved_cursor = cursor;
|
|
- rc2 = 0;
|
|
- }
|
|
- else
|
|
- rc2 = cursor->c_close( cursor );
|
|
- if (rc2) {
|
|
- Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
|
|
- "close failed: %s (%d)\n", db_strerror(rc2), rc2, 0 );
|
|
- return rc2;
|
|
- }
|
|
-
|
|
- if( rc == DB_NOTFOUND ) {
|
|
- return rc;
|
|
-
|
|
- } else if( rc != 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
|
|
- "get failed: %s (%d)\n",
|
|
- db_strerror(rc), rc, 0 );
|
|
- return rc;
|
|
-
|
|
- } else if ( data.size == 0 || data.size % sizeof( ID ) ) {
|
|
- /* size not multiple of ID size */
|
|
- Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
|
|
- "odd size: expected %ld multiple, got %ld\n",
|
|
- (long) sizeof( ID ), (long) data.size, 0 );
|
|
- return -1;
|
|
-
|
|
- } else if ( data.size != BDB_IDL_SIZEOF(ids) ) {
|
|
- /* size mismatch */
|
|
- Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
|
|
- "get size mismatch: expected %ld, got %ld\n",
|
|
- (long) ((1 + ids[0]) * sizeof( ID )), (long) data.size, 0 );
|
|
- return -1;
|
|
- }
|
|
-
|
|
- if ( bdb->bi_idl_cache_max_size ) {
|
|
- bdb_idl_cache_put( bdb, db, key, ids, rc );
|
|
- }
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-
|
|
-int
|
|
-bdb_idl_insert_key(
|
|
- BackendDB *be,
|
|
- DB *db,
|
|
- DB_TXN *tid,
|
|
- DBT *key,
|
|
- ID id )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
|
- int rc;
|
|
- DBT data;
|
|
- DBC *cursor;
|
|
- ID lo, hi, nlo, nhi, nid;
|
|
- char *err;
|
|
-
|
|
- {
|
|
- char buf[16];
|
|
- Debug( LDAP_DEBUG_ARGS,
|
|
- "bdb_idl_insert_key: %lx %s\n",
|
|
- (long) id, bdb_show_key( key, buf ), 0 );
|
|
- }
|
|
-
|
|
- assert( id != NOID );
|
|
-
|
|
- DBTzero( &data );
|
|
- data.size = sizeof( ID );
|
|
- data.ulen = data.size;
|
|
- data.flags = DB_DBT_USERMEM;
|
|
-
|
|
- BDB_ID2DISK( id, &nid );
|
|
-
|
|
- rc = db->cursor( db, tid, &cursor, bdb->bi_db_opflags );
|
|
- if ( rc != 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY, "=> bdb_idl_insert_key: "
|
|
- "cursor failed: %s (%d)\n", db_strerror(rc), rc, 0 );
|
|
- return rc;
|
|
- }
|
|
- data.data = &nlo;
|
|
- /* Fetch the first data item for this key, to see if it
|
|
- * exists and if it's a range.
|
|
- */
|
|
- rc = cursor->c_get( cursor, key, &data, DB_SET );
|
|
- err = "c_get";
|
|
- if ( rc == 0 ) {
|
|
- if ( nlo != 0 ) {
|
|
- /* not a range, count the number of items */
|
|
- db_recno_t count;
|
|
- rc = cursor->c_count( cursor, &count, 0 );
|
|
- if ( rc != 0 ) {
|
|
- err = "c_count";
|
|
- goto fail;
|
|
- }
|
|
- if ( count >= BDB_IDL_DB_MAX ) {
|
|
- /* No room, convert to a range */
|
|
- DBT key2 = *key;
|
|
- db_recno_t i;
|
|
-
|
|
- key2.dlen = key2.ulen;
|
|
- key2.flags |= DB_DBT_PARTIAL;
|
|
-
|
|
- BDB_DISK2ID( &nlo, &lo );
|
|
- data.data = &nhi;
|
|
-
|
|
- rc = cursor->c_get( cursor, &key2, &data, DB_NEXT_NODUP );
|
|
- if ( rc != 0 && rc != DB_NOTFOUND ) {
|
|
- err = "c_get next_nodup";
|
|
- goto fail;
|
|
- }
|
|
- if ( rc == DB_NOTFOUND ) {
|
|
- rc = cursor->c_get( cursor, key, &data, DB_LAST );
|
|
- if ( rc != 0 ) {
|
|
- err = "c_get last";
|
|
- goto fail;
|
|
- }
|
|
- } else {
|
|
- rc = cursor->c_get( cursor, key, &data, DB_PREV );
|
|
- if ( rc != 0 ) {
|
|
- err = "c_get prev";
|
|
- goto fail;
|
|
- }
|
|
- }
|
|
- BDB_DISK2ID( &nhi, &hi );
|
|
- /* Update hi/lo if needed, then delete all the items
|
|
- * between lo and hi
|
|
- */
|
|
- if ( id < lo ) {
|
|
- lo = id;
|
|
- nlo = nid;
|
|
- } else if ( id > hi ) {
|
|
- hi = id;
|
|
- nhi = nid;
|
|
- }
|
|
- data.data = &nid;
|
|
- /* Don't fetch anything, just position cursor */
|
|
- data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
|
|
- data.dlen = data.ulen = 0;
|
|
- rc = cursor->c_get( cursor, key, &data, DB_SET );
|
|
- if ( rc != 0 ) {
|
|
- err = "c_get 2";
|
|
- goto fail;
|
|
- }
|
|
- rc = cursor->c_del( cursor, 0 );
|
|
- if ( rc != 0 ) {
|
|
- err = "c_del range1";
|
|
- goto fail;
|
|
- }
|
|
- /* Delete all the records */
|
|
- for ( i=1; i<count; i++ ) {
|
|
- rc = cursor->c_get( cursor, &key2, &data, DB_NEXT_DUP );
|
|
- if ( rc != 0 ) {
|
|
- err = "c_get next_dup";
|
|
- goto fail;
|
|
- }
|
|
- rc = cursor->c_del( cursor, 0 );
|
|
- if ( rc != 0 ) {
|
|
- err = "c_del range";
|
|
- goto fail;
|
|
- }
|
|
- }
|
|
- /* Store the range marker */
|
|
- data.size = data.ulen = sizeof(ID);
|
|
- data.flags = DB_DBT_USERMEM;
|
|
- nid = 0;
|
|
- rc = cursor->c_put( cursor, key, &data, DB_KEYFIRST );
|
|
- if ( rc != 0 ) {
|
|
- err = "c_put range";
|
|
- goto fail;
|
|
- }
|
|
- nid = nlo;
|
|
- rc = cursor->c_put( cursor, key, &data, DB_KEYLAST );
|
|
- if ( rc != 0 ) {
|
|
- err = "c_put lo";
|
|
- goto fail;
|
|
- }
|
|
- nid = nhi;
|
|
- rc = cursor->c_put( cursor, key, &data, DB_KEYLAST );
|
|
- if ( rc != 0 ) {
|
|
- err = "c_put hi";
|
|
- goto fail;
|
|
- }
|
|
- } else {
|
|
- /* There's room, just store it */
|
|
- goto put1;
|
|
- }
|
|
- } else {
|
|
- /* It's a range, see if we need to rewrite
|
|
- * the boundaries
|
|
- */
|
|
- hi = id;
|
|
- data.data = &nlo;
|
|
- rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP );
|
|
- if ( rc != 0 ) {
|
|
- err = "c_get lo";
|
|
- goto fail;
|
|
- }
|
|
- BDB_DISK2ID( &nlo, &lo );
|
|
- if ( id > lo ) {
|
|
- data.data = &nhi;
|
|
- rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP );
|
|
- if ( rc != 0 ) {
|
|
- err = "c_get hi";
|
|
- goto fail;
|
|
- }
|
|
- BDB_DISK2ID( &nhi, &hi );
|
|
- }
|
|
- if ( id < lo || id > hi ) {
|
|
- /* Delete the current lo/hi */
|
|
- rc = cursor->c_del( cursor, 0 );
|
|
- if ( rc != 0 ) {
|
|
- err = "c_del";
|
|
- goto fail;
|
|
- }
|
|
- data.data = &nid;
|
|
- rc = cursor->c_put( cursor, key, &data, DB_KEYFIRST );
|
|
- if ( rc != 0 ) {
|
|
- err = "c_put lo/hi";
|
|
- goto fail;
|
|
- }
|
|
- }
|
|
- }
|
|
- } else if ( rc == DB_NOTFOUND ) {
|
|
-put1: data.data = &nid;
|
|
- rc = cursor->c_put( cursor, key, &data, DB_NODUPDATA );
|
|
- /* Don't worry if it's already there */
|
|
- if ( rc != 0 && rc != DB_KEYEXIST ) {
|
|
- err = "c_put id";
|
|
- goto fail;
|
|
- }
|
|
- } else {
|
|
- /* initial c_get failed, nothing was done */
|
|
-fail:
|
|
- Debug( LDAP_DEBUG_ANY, "=> bdb_idl_insert_key: "
|
|
- "%s failed: %s (%d)\n", err, db_strerror(rc), rc );
|
|
- cursor->c_close( cursor );
|
|
- return rc;
|
|
- }
|
|
- /* If key was added (didn't already exist) and using IDL cache,
|
|
- * update key in IDL cache.
|
|
- */
|
|
- if ( !rc && bdb->bi_idl_cache_max_size ) {
|
|
- bdb_idl_cache_add_id( bdb, db, key, id );
|
|
- }
|
|
- rc = cursor->c_close( cursor );
|
|
- if( rc != 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY, "=> bdb_idl_insert_key: "
|
|
- "c_close failed: %s (%d)\n",
|
|
- db_strerror(rc), rc, 0 );
|
|
- }
|
|
- return rc;
|
|
-}
|
|
-
|
|
-int
|
|
-bdb_idl_delete_key(
|
|
- BackendDB *be,
|
|
- DB *db,
|
|
- DB_TXN *tid,
|
|
- DBT *key,
|
|
- ID id )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
|
- int rc;
|
|
- DBT data;
|
|
- DBC *cursor;
|
|
- ID lo, hi, tmp, nid, nlo, nhi;
|
|
- char *err;
|
|
-
|
|
- {
|
|
- char buf[16];
|
|
- Debug( LDAP_DEBUG_ARGS,
|
|
- "bdb_idl_delete_key: %lx %s\n",
|
|
- (long) id, bdb_show_key( key, buf ), 0 );
|
|
- }
|
|
- assert( id != NOID );
|
|
-
|
|
- if ( bdb->bi_idl_cache_size ) {
|
|
- bdb_idl_cache_del( bdb, db, key );
|
|
- }
|
|
-
|
|
- BDB_ID2DISK( id, &nid );
|
|
-
|
|
- DBTzero( &data );
|
|
- data.data = &tmp;
|
|
- data.size = sizeof( id );
|
|
- data.ulen = data.size;
|
|
- data.flags = DB_DBT_USERMEM;
|
|
-
|
|
- rc = db->cursor( db, tid, &cursor, bdb->bi_db_opflags );
|
|
- if ( rc != 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY, "=> bdb_idl_delete_key: "
|
|
- "cursor failed: %s (%d)\n", db_strerror(rc), rc, 0 );
|
|
- return rc;
|
|
- }
|
|
- /* Fetch the first data item for this key, to see if it
|
|
- * exists and if it's a range.
|
|
- */
|
|
- rc = cursor->c_get( cursor, key, &data, DB_SET );
|
|
- err = "c_get";
|
|
- if ( rc == 0 ) {
|
|
- if ( tmp != 0 ) {
|
|
- /* Not a range, just delete it */
|
|
- if (tmp != nid) {
|
|
- /* position to correct item */
|
|
- tmp = nid;
|
|
- rc = cursor->c_get( cursor, key, &data, DB_GET_BOTH );
|
|
- if ( rc != 0 ) {
|
|
- err = "c_get id";
|
|
- goto fail;
|
|
- }
|
|
- }
|
|
- rc = cursor->c_del( cursor, 0 );
|
|
- if ( rc != 0 ) {
|
|
- err = "c_del id";
|
|
- goto fail;
|
|
- }
|
|
- } else {
|
|
- /* It's a range, see if we need to rewrite
|
|
- * the boundaries
|
|
- */
|
|
- data.data = &nlo;
|
|
- rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP );
|
|
- if ( rc != 0 ) {
|
|
- err = "c_get lo";
|
|
- goto fail;
|
|
- }
|
|
- BDB_DISK2ID( &nlo, &lo );
|
|
- data.data = &nhi;
|
|
- rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP );
|
|
- if ( rc != 0 ) {
|
|
- err = "c_get hi";
|
|
- goto fail;
|
|
- }
|
|
- BDB_DISK2ID( &nhi, &hi );
|
|
- if ( id == lo || id == hi ) {
|
|
- if ( id == lo ) {
|
|
- id++;
|
|
- lo = id;
|
|
- } else if ( id == hi ) {
|
|
- id--;
|
|
- hi = id;
|
|
- }
|
|
- if ( lo >= hi ) {
|
|
- /* The range has collapsed... */
|
|
- rc = db->del( db, tid, key, 0 );
|
|
- if ( rc != 0 ) {
|
|
- err = "del";
|
|
- goto fail;
|
|
- }
|
|
- } else {
|
|
- if ( id == lo ) {
|
|
- /* reposition on lo slot */
|
|
- data.data = &nlo;
|
|
- cursor->c_get( cursor, key, &data, DB_PREV );
|
|
- }
|
|
- rc = cursor->c_del( cursor, 0 );
|
|
- if ( rc != 0 ) {
|
|
- err = "c_del";
|
|
- goto fail;
|
|
- }
|
|
- }
|
|
- if ( lo <= hi ) {
|
|
- BDB_ID2DISK( id, &nid );
|
|
- data.data = &nid;
|
|
- rc = cursor->c_put( cursor, key, &data, DB_KEYFIRST );
|
|
- if ( rc != 0 ) {
|
|
- err = "c_put lo/hi";
|
|
- goto fail;
|
|
- }
|
|
- }
|
|
- }
|
|
- }
|
|
- } else {
|
|
- /* initial c_get failed, nothing was done */
|
|
-fail:
|
|
- if ( rc != DB_NOTFOUND ) {
|
|
- Debug( LDAP_DEBUG_ANY, "=> bdb_idl_delete_key: "
|
|
- "%s failed: %s (%d)\n", err, db_strerror(rc), rc );
|
|
- }
|
|
- cursor->c_close( cursor );
|
|
- return rc;
|
|
- }
|
|
- rc = cursor->c_close( cursor );
|
|
- if( rc != 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "=> bdb_idl_delete_key: c_close failed: %s (%d)\n",
|
|
- db_strerror(rc), rc, 0 );
|
|
- }
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-
|
|
-/*
|
|
- * idl_intersection - return a = a intersection b
|
|
- */
|
|
-int
|
|
-bdb_idl_intersection(
|
|
- ID *a,
|
|
- ID *b )
|
|
-{
|
|
- ID ida, idb;
|
|
- ID idmax, idmin;
|
|
- ID cursora = 0, cursorb = 0, cursorc;
|
|
- int swap = 0;
|
|
-
|
|
- if ( BDB_IDL_IS_ZERO( a ) || BDB_IDL_IS_ZERO( b ) ) {
|
|
- a[0] = 0;
|
|
- return 0;
|
|
- }
|
|
-
|
|
- idmin = IDL_MAX( BDB_IDL_FIRST(a), BDB_IDL_FIRST(b) );
|
|
- idmax = IDL_MIN( BDB_IDL_LAST(a), BDB_IDL_LAST(b) );
|
|
- if ( idmin > idmax ) {
|
|
- a[0] = 0;
|
|
- return 0;
|
|
- } else if ( idmin == idmax ) {
|
|
- a[0] = 1;
|
|
- a[1] = idmin;
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if ( BDB_IDL_IS_RANGE( a ) ) {
|
|
- if ( BDB_IDL_IS_RANGE(b) ) {
|
|
- /* If both are ranges, just shrink the boundaries */
|
|
- a[1] = idmin;
|
|
- a[2] = idmax;
|
|
- return 0;
|
|
- } else {
|
|
- /* Else swap so that b is the range, a is a list */
|
|
- ID *tmp = a;
|
|
- a = b;
|
|
- b = tmp;
|
|
- swap = 1;
|
|
- }
|
|
- }
|
|
-
|
|
- /* If a range completely covers the list, the result is
|
|
- * just the list.
|
|
- */
|
|
- if ( BDB_IDL_IS_RANGE( b )
|
|
- && BDB_IDL_RANGE_FIRST( b ) <= BDB_IDL_FIRST( a )
|
|
- && BDB_IDL_RANGE_LAST( b ) >= BDB_IDL_LLAST( a ) ) {
|
|
- goto done;
|
|
- }
|
|
-
|
|
- /* Fine, do the intersection one element at a time.
|
|
- * First advance to idmin in both IDLs.
|
|
- */
|
|
- cursora = cursorb = idmin;
|
|
- ida = bdb_idl_first( a, &cursora );
|
|
- idb = bdb_idl_first( b, &cursorb );
|
|
- cursorc = 0;
|
|
-
|
|
- while( ida <= idmax || idb <= idmax ) {
|
|
- if( ida == idb ) {
|
|
- a[++cursorc] = ida;
|
|
- ida = bdb_idl_next( a, &cursora );
|
|
- idb = bdb_idl_next( b, &cursorb );
|
|
- } else if ( ida < idb ) {
|
|
- ida = bdb_idl_next( a, &cursora );
|
|
- } else {
|
|
- idb = bdb_idl_next( b, &cursorb );
|
|
- }
|
|
- }
|
|
- a[0] = cursorc;
|
|
-done:
|
|
- if (swap)
|
|
- BDB_IDL_CPY( b, a );
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-
|
|
-/*
|
|
- * idl_union - return a = a union b
|
|
- */
|
|
-int
|
|
-bdb_idl_union(
|
|
- ID *a,
|
|
- ID *b )
|
|
-{
|
|
- ID ida, idb;
|
|
- ID cursora = 0, cursorb = 0, cursorc;
|
|
-
|
|
- if ( BDB_IDL_IS_ZERO( b ) ) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if ( BDB_IDL_IS_ZERO( a ) ) {
|
|
- BDB_IDL_CPY( a, b );
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if ( BDB_IDL_IS_RANGE( a ) || BDB_IDL_IS_RANGE(b) ) {
|
|
-over: ida = IDL_MIN( BDB_IDL_FIRST(a), BDB_IDL_FIRST(b) );
|
|
- idb = IDL_MAX( BDB_IDL_LAST(a), BDB_IDL_LAST(b) );
|
|
- a[0] = NOID;
|
|
- a[1] = ida;
|
|
- a[2] = idb;
|
|
- return 0;
|
|
- }
|
|
-
|
|
- ida = bdb_idl_first( a, &cursora );
|
|
- idb = bdb_idl_first( b, &cursorb );
|
|
-
|
|
- cursorc = b[0];
|
|
-
|
|
- /* The distinct elements of a are cat'd to b */
|
|
- while( ida != NOID || idb != NOID ) {
|
|
- if ( ida < idb ) {
|
|
- if( ++cursorc > BDB_IDL_UM_MAX ) {
|
|
- goto over;
|
|
- }
|
|
- b[cursorc] = ida;
|
|
- ida = bdb_idl_next( a, &cursora );
|
|
-
|
|
- } else {
|
|
- if ( ida == idb )
|
|
- ida = bdb_idl_next( a, &cursora );
|
|
- idb = bdb_idl_next( b, &cursorb );
|
|
- }
|
|
- }
|
|
-
|
|
- /* b is copied back to a in sorted order */
|
|
- a[0] = cursorc;
|
|
- cursora = 1;
|
|
- cursorb = 1;
|
|
- cursorc = b[0]+1;
|
|
- while (cursorb <= b[0] || cursorc <= a[0]) {
|
|
- if (cursorc > a[0])
|
|
- idb = NOID;
|
|
- else
|
|
- idb = b[cursorc];
|
|
- if (cursorb <= b[0] && b[cursorb] < idb)
|
|
- a[cursora++] = b[cursorb++];
|
|
- else {
|
|
- a[cursora++] = idb;
|
|
- cursorc++;
|
|
- }
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-
|
|
-#if 0
|
|
-/*
|
|
- * bdb_idl_notin - return a intersection ~b (or a minus b)
|
|
- */
|
|
-int
|
|
-bdb_idl_notin(
|
|
- ID *a,
|
|
- ID *b,
|
|
- ID *ids )
|
|
-{
|
|
- ID ida, idb;
|
|
- ID cursora = 0, cursorb = 0;
|
|
-
|
|
- if( BDB_IDL_IS_ZERO( a ) ||
|
|
- BDB_IDL_IS_ZERO( b ) ||
|
|
- BDB_IDL_IS_RANGE( b ) )
|
|
- {
|
|
- BDB_IDL_CPY( ids, a );
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if( BDB_IDL_IS_RANGE( a ) ) {
|
|
- BDB_IDL_CPY( ids, a );
|
|
- return 0;
|
|
- }
|
|
-
|
|
- ida = bdb_idl_first( a, &cursora ),
|
|
- idb = bdb_idl_first( b, &cursorb );
|
|
-
|
|
- ids[0] = 0;
|
|
-
|
|
- while( ida != NOID ) {
|
|
- if ( idb == NOID ) {
|
|
- /* we could shortcut this */
|
|
- ids[++ids[0]] = ida;
|
|
- ida = bdb_idl_next( a, &cursora );
|
|
-
|
|
- } else if ( ida < idb ) {
|
|
- ids[++ids[0]] = ida;
|
|
- ida = bdb_idl_next( a, &cursora );
|
|
-
|
|
- } else if ( ida > idb ) {
|
|
- idb = bdb_idl_next( b, &cursorb );
|
|
-
|
|
- } else {
|
|
- ida = bdb_idl_next( a, &cursora );
|
|
- idb = bdb_idl_next( b, &cursorb );
|
|
- }
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-#endif
|
|
-
|
|
-ID bdb_idl_first( ID *ids, ID *cursor )
|
|
-{
|
|
- ID pos;
|
|
-
|
|
- if ( ids[0] == 0 ) {
|
|
- *cursor = NOID;
|
|
- return NOID;
|
|
- }
|
|
-
|
|
- if ( BDB_IDL_IS_RANGE( ids ) ) {
|
|
- if( *cursor < ids[1] ) {
|
|
- *cursor = ids[1];
|
|
- }
|
|
- return *cursor;
|
|
- }
|
|
-
|
|
- if ( *cursor == 0 )
|
|
- pos = 1;
|
|
- else
|
|
- pos = bdb_idl_search( ids, *cursor );
|
|
-
|
|
- if( pos > ids[0] ) {
|
|
- return NOID;
|
|
- }
|
|
-
|
|
- *cursor = pos;
|
|
- return ids[pos];
|
|
-}
|
|
-
|
|
-ID bdb_idl_next( ID *ids, ID *cursor )
|
|
-{
|
|
- if ( BDB_IDL_IS_RANGE( ids ) ) {
|
|
- if( ids[2] < ++(*cursor) ) {
|
|
- return NOID;
|
|
- }
|
|
- return *cursor;
|
|
- }
|
|
-
|
|
- if ( ++(*cursor) <= ids[0] ) {
|
|
- return ids[*cursor];
|
|
- }
|
|
-
|
|
- return NOID;
|
|
-}
|
|
-
|
|
-#ifdef BDB_HIER
|
|
-
|
|
-/* Add one ID to an unsorted list. We ensure that the first element is the
|
|
- * minimum and the last element is the maximum, for fast range compaction.
|
|
- * this means IDLs up to length 3 are always sorted...
|
|
- */
|
|
-int bdb_idl_append_one( ID *ids, ID id )
|
|
-{
|
|
- if (BDB_IDL_IS_RANGE( ids )) {
|
|
- /* if already in range, treat as a dup */
|
|
- if (id >= BDB_IDL_RANGE_FIRST(ids) && id <= BDB_IDL_RANGE_LAST(ids))
|
|
- return -1;
|
|
- if (id < BDB_IDL_RANGE_FIRST(ids))
|
|
- ids[1] = id;
|
|
- else if (id > BDB_IDL_RANGE_LAST(ids))
|
|
- ids[2] = id;
|
|
- return 0;
|
|
- }
|
|
- if ( ids[0] ) {
|
|
- ID tmp;
|
|
-
|
|
- if (id < ids[1]) {
|
|
- tmp = ids[1];
|
|
- ids[1] = id;
|
|
- id = tmp;
|
|
- }
|
|
- if ( ids[0] > 1 && id < ids[ids[0]] ) {
|
|
- tmp = ids[ids[0]];
|
|
- ids[ids[0]] = id;
|
|
- id = tmp;
|
|
- }
|
|
- }
|
|
- ids[0]++;
|
|
- if ( ids[0] >= BDB_IDL_UM_MAX ) {
|
|
- ids[0] = NOID;
|
|
- ids[2] = id;
|
|
- } else {
|
|
- ids[ids[0]] = id;
|
|
- }
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/* Append sorted list b to sorted list a. The result is unsorted but
|
|
- * a[1] is the min of the result and a[a[0]] is the max.
|
|
- */
|
|
-int bdb_idl_append( ID *a, ID *b )
|
|
-{
|
|
- ID ida, idb, tmp, swap = 0;
|
|
-
|
|
- if ( BDB_IDL_IS_ZERO( b ) ) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if ( BDB_IDL_IS_ZERO( a ) ) {
|
|
- BDB_IDL_CPY( a, b );
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if ( b[0] == 1 ) {
|
|
- return bdb_idl_append_one( a, BDB_IDL_FIRST( b ));
|
|
- }
|
|
-
|
|
- ida = BDB_IDL_LAST( a );
|
|
- idb = BDB_IDL_LAST( b );
|
|
- if ( BDB_IDL_IS_RANGE( a ) || BDB_IDL_IS_RANGE(b) ||
|
|
- a[0] + b[0] >= BDB_IDL_UM_MAX ) {
|
|
- a[2] = IDL_MAX( ida, idb );
|
|
- a[1] = IDL_MIN( a[1], b[1] );
|
|
- a[0] = NOID;
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if ( ida > idb ) {
|
|
- swap = idb;
|
|
- a[a[0]] = idb;
|
|
- b[b[0]] = ida;
|
|
- }
|
|
-
|
|
- if ( b[1] < a[1] ) {
|
|
- tmp = a[1];
|
|
- a[1] = b[1];
|
|
- } else {
|
|
- tmp = b[1];
|
|
- }
|
|
- a[0]++;
|
|
- a[a[0]] = tmp;
|
|
-
|
|
- {
|
|
- int i = b[0] - 1;
|
|
- AC_MEMCPY(a+a[0]+1, b+2, i * sizeof(ID));
|
|
- a[0] += i;
|
|
- }
|
|
- if ( swap ) {
|
|
- b[b[0]] = swap;
|
|
- }
|
|
- return 0;
|
|
-}
|
|
-
|
|
-#if 1
|
|
-
|
|
-/* Quicksort + Insertion sort for small arrays */
|
|
-
|
|
-#define SMALL 8
|
|
-#define SWAP(a,b) itmp=(a);(a)=(b);(b)=itmp
|
|
-
|
|
-void
|
|
-bdb_idl_sort( ID *ids, ID *tmp )
|
|
-{
|
|
- int *istack = (int *)tmp;
|
|
- int i,j,k,l,ir,jstack;
|
|
- ID a, itmp;
|
|
-
|
|
- if ( BDB_IDL_IS_RANGE( ids ))
|
|
- return;
|
|
-
|
|
- ir = ids[0];
|
|
- l = 1;
|
|
- jstack = 0;
|
|
- for(;;) {
|
|
- if (ir - l < SMALL) { /* Insertion sort */
|
|
- for (j=l+1;j<=ir;j++) {
|
|
- a = ids[j];
|
|
- for (i=j-1;i>=1;i--) {
|
|
- if (ids[i] <= a) break;
|
|
- ids[i+1] = ids[i];
|
|
- }
|
|
- ids[i+1] = a;
|
|
- }
|
|
- if (jstack == 0) break;
|
|
- ir = istack[jstack--];
|
|
- l = istack[jstack--];
|
|
- } else {
|
|
- k = (l + ir) >> 1; /* Choose median of left, center, right */
|
|
- SWAP(ids[k], ids[l+1]);
|
|
- if (ids[l] > ids[ir]) {
|
|
- SWAP(ids[l], ids[ir]);
|
|
- }
|
|
- if (ids[l+1] > ids[ir]) {
|
|
- SWAP(ids[l+1], ids[ir]);
|
|
- }
|
|
- if (ids[l] > ids[l+1]) {
|
|
- SWAP(ids[l], ids[l+1]);
|
|
- }
|
|
- i = l+1;
|
|
- j = ir;
|
|
- a = ids[l+1];
|
|
- for(;;) {
|
|
- do i++; while(ids[i] < a);
|
|
- do j--; while(ids[j] > a);
|
|
- if (j < i) break;
|
|
- SWAP(ids[i],ids[j]);
|
|
- }
|
|
- ids[l+1] = ids[j];
|
|
- ids[j] = a;
|
|
- jstack += 2;
|
|
- if (ir-i+1 >= j-1) {
|
|
- istack[jstack] = ir;
|
|
- istack[jstack-1] = i;
|
|
- ir = j-1;
|
|
- } else {
|
|
- istack[jstack] = j-1;
|
|
- istack[jstack-1] = l;
|
|
- l = i;
|
|
- }
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
-#else
|
|
-
|
|
-/* 8 bit Radix sort + insertion sort
|
|
- *
|
|
- * based on code from http://www.cubic.org/docs/radix.htm
|
|
- * with improvements by ebackes@symas.com and hyc@symas.com
|
|
- *
|
|
- * This code is O(n) but has a relatively high constant factor. For lists
|
|
- * up to ~50 Quicksort is slightly faster; up to ~100 they are even.
|
|
- * Much faster than quicksort for lists longer than ~100. Insertion
|
|
- * sort is actually superior for lists <50.
|
|
- */
|
|
-
|
|
-#define BUCKETS (1<<8)
|
|
-#define SMALL 50
|
|
-
|
|
-void
|
|
-bdb_idl_sort( ID *ids, ID *tmp )
|
|
-{
|
|
- int count, soft_limit, phase = 0, size = ids[0];
|
|
- ID *idls[2];
|
|
- unsigned char *maxv = (unsigned char *)&ids[size];
|
|
-
|
|
- if ( BDB_IDL_IS_RANGE( ids ))
|
|
- return;
|
|
-
|
|
- /* Use insertion sort for small lists */
|
|
- if ( size <= SMALL ) {
|
|
- int i,j;
|
|
- ID a;
|
|
-
|
|
- for (j=1;j<=size;j++) {
|
|
- a = ids[j];
|
|
- for (i=j-1;i>=1;i--) {
|
|
- if (ids[i] <= a) break;
|
|
- ids[i+1] = ids[i];
|
|
- }
|
|
- ids[i+1] = a;
|
|
- }
|
|
- return;
|
|
- }
|
|
-
|
|
- tmp[0] = size;
|
|
- idls[0] = ids;
|
|
- idls[1] = tmp;
|
|
-
|
|
-#if BYTE_ORDER == BIG_ENDIAN
|
|
- for (soft_limit = 0; !maxv[soft_limit]; soft_limit++);
|
|
-#else
|
|
- for (soft_limit = sizeof(ID)-1; !maxv[soft_limit]; soft_limit--);
|
|
-#endif
|
|
-
|
|
- for (
|
|
-#if BYTE_ORDER == BIG_ENDIAN
|
|
- count = sizeof(ID)-1; count >= soft_limit; --count
|
|
-#else
|
|
- count = 0; count <= soft_limit; ++count
|
|
-#endif
|
|
- ) {
|
|
- unsigned int num[BUCKETS], * np, n, sum;
|
|
- int i;
|
|
- ID *sp, *source, *dest;
|
|
- unsigned char *bp, *source_start;
|
|
-
|
|
- source = idls[phase]+1;
|
|
- dest = idls[phase^1]+1;
|
|
- source_start = ((unsigned char *) source) + count;
|
|
-
|
|
- np = num;
|
|
- for ( i = BUCKETS; i > 0; --i ) *np++ = 0;
|
|
-
|
|
- /* count occurences of every byte value */
|
|
- bp = source_start;
|
|
- for ( i = size; i > 0; --i, bp += sizeof(ID) )
|
|
- num[*bp]++;
|
|
-
|
|
- /* transform count into index by summing elements and storing
|
|
- * into same array
|
|
- */
|
|
- sum = 0;
|
|
- np = num;
|
|
- for ( i = BUCKETS; i > 0; --i ) {
|
|
- n = *np;
|
|
- *np++ = sum;
|
|
- sum += n;
|
|
- }
|
|
-
|
|
- /* fill dest with the right values in the right place */
|
|
- bp = source_start;
|
|
- sp = source;
|
|
- for ( i = size; i > 0; --i, bp += sizeof(ID) ) {
|
|
- np = num + *bp;
|
|
- dest[*np] = *sp++;
|
|
- ++(*np);
|
|
- }
|
|
- phase ^= 1;
|
|
- }
|
|
-
|
|
- /* copy back from temp if needed */
|
|
- if ( phase ) {
|
|
- ids++; tmp++;
|
|
- for ( count = 0; count < size; ++count )
|
|
- *ids++ = *tmp++;
|
|
- }
|
|
-}
|
|
-#endif /* Quick vs Radix */
|
|
-
|
|
-#endif /* BDB_HIER */
|
|
diff --git a/servers/slapd/back-bdb/idl.h b/servers/slapd/back-bdb/idl.h
|
|
deleted file mode 100644
|
|
index 909a43b..0000000
|
|
--- a/servers/slapd/back-bdb/idl.h
|
|
+++ /dev/null
|
|
@@ -1,75 +0,0 @@
|
|
-/* idl.h - ldap bdb back-end ID list header file */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#ifndef _BDB_IDL_H_
|
|
-#define _BDB_IDL_H_
|
|
-
|
|
-/* IDL sizes - likely should be even bigger
|
|
- * limiting factors: sizeof(ID), thread stack size
|
|
- */
|
|
-#define BDB_IDL_LOGN 16 /* DB_SIZE is 2^16, UM_SIZE is 2^17 */
|
|
-#define BDB_IDL_DB_SIZE (1<<BDB_IDL_LOGN)
|
|
-#define BDB_IDL_UM_SIZE (1<<(BDB_IDL_LOGN+1))
|
|
-#define BDB_IDL_UM_SIZEOF (BDB_IDL_UM_SIZE * sizeof(ID))
|
|
-
|
|
-#define BDB_IDL_DB_MAX (BDB_IDL_DB_SIZE-1)
|
|
-
|
|
-#define BDB_IDL_UM_MAX (BDB_IDL_UM_SIZE-1)
|
|
-
|
|
-#define BDB_IDL_IS_RANGE(ids) ((ids)[0] == NOID)
|
|
-#define BDB_IDL_RANGE_SIZE (3)
|
|
-#define BDB_IDL_RANGE_SIZEOF (BDB_IDL_RANGE_SIZE * sizeof(ID))
|
|
-#define BDB_IDL_SIZEOF(ids) ((BDB_IDL_IS_RANGE(ids) \
|
|
- ? BDB_IDL_RANGE_SIZE : ((ids)[0]+1)) * sizeof(ID))
|
|
-
|
|
-#define BDB_IDL_RANGE_FIRST(ids) ((ids)[1])
|
|
-#define BDB_IDL_RANGE_LAST(ids) ((ids)[2])
|
|
-
|
|
-#define BDB_IDL_RANGE( ids, f, l ) \
|
|
- do { \
|
|
- (ids)[0] = NOID; \
|
|
- (ids)[1] = (f); \
|
|
- (ids)[2] = (l); \
|
|
- } while(0)
|
|
-
|
|
-#define BDB_IDL_ZERO(ids) \
|
|
- do { \
|
|
- (ids)[0] = 0; \
|
|
- (ids)[1] = 0; \
|
|
- (ids)[2] = 0; \
|
|
- } while(0)
|
|
-
|
|
-#define BDB_IDL_IS_ZERO(ids) ( (ids)[0] == 0 )
|
|
-#define BDB_IDL_IS_ALL( range, ids ) ( (ids)[0] == NOID \
|
|
- && (ids)[1] <= (range)[1] && (range)[2] <= (ids)[2] )
|
|
-
|
|
-#define BDB_IDL_CPY( dst, src ) (AC_MEMCPY( dst, src, BDB_IDL_SIZEOF( src ) ))
|
|
-
|
|
-#define BDB_IDL_ID( bdb, ids, id ) BDB_IDL_RANGE( ids, id, ((bdb)->bi_lastid) )
|
|
-#define BDB_IDL_ALL( bdb, ids ) BDB_IDL_RANGE( ids, 1, ((bdb)->bi_lastid) )
|
|
-
|
|
-#define BDB_IDL_FIRST( ids ) ( (ids)[1] )
|
|
-#define BDB_IDL_LLAST( ids ) ( (ids)[(ids)[0]] )
|
|
-#define BDB_IDL_LAST( ids ) ( BDB_IDL_IS_RANGE(ids) \
|
|
- ? (ids)[2] : (ids)[(ids)[0]] )
|
|
-
|
|
-#define BDB_IDL_N( ids ) ( BDB_IDL_IS_RANGE(ids) \
|
|
- ? ((ids)[2]-(ids)[1])+1 : (ids)[0] )
|
|
-
|
|
-LDAP_BEGIN_DECL
|
|
-LDAP_END_DECL
|
|
-
|
|
-#endif
|
|
diff --git a/servers/slapd/back-bdb/index.c b/servers/slapd/back-bdb/index.c
|
|
deleted file mode 100644
|
|
index c095641..0000000
|
|
--- a/servers/slapd/back-bdb/index.c
|
|
+++ /dev/null
|
|
@@ -1,574 +0,0 @@
|
|
-/* index.c - routines for dealing with attribute indexes */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-
|
|
-#include <stdio.h>
|
|
-
|
|
-#include <ac/string.h>
|
|
-#include <ac/socket.h>
|
|
-
|
|
-#include "slap.h"
|
|
-#include "back-bdb.h"
|
|
-#include "lutil_hash.h"
|
|
-
|
|
-static char presence_keyval[] = {0,0};
|
|
-static struct berval presence_key = BER_BVC(presence_keyval);
|
|
-
|
|
-AttrInfo *bdb_index_mask(
|
|
- Backend *be,
|
|
- AttributeDescription *desc,
|
|
- struct berval *atname )
|
|
-{
|
|
- AttributeType *at;
|
|
- AttrInfo *ai = bdb_attr_mask( be->be_private, desc );
|
|
-
|
|
- if( ai ) {
|
|
- *atname = desc->ad_cname;
|
|
- return ai;
|
|
- }
|
|
-
|
|
- /* If there is a tagging option, did we ever index the base
|
|
- * type? If so, check for mask, otherwise it's not there.
|
|
- */
|
|
- if( slap_ad_is_tagged( desc ) && desc != desc->ad_type->sat_ad ) {
|
|
- /* has tagging option */
|
|
- ai = bdb_attr_mask( be->be_private, desc->ad_type->sat_ad );
|
|
-
|
|
- if ( ai && !( ai->ai_indexmask & SLAP_INDEX_NOTAGS ) ) {
|
|
- *atname = desc->ad_type->sat_cname;
|
|
- return ai;
|
|
- }
|
|
- }
|
|
-
|
|
- /* see if supertype defined mask for its subtypes */
|
|
- for( at = desc->ad_type; at != NULL ; at = at->sat_sup ) {
|
|
- /* If no AD, we've never indexed this type */
|
|
- if ( !at->sat_ad ) continue;
|
|
-
|
|
- ai = bdb_attr_mask( be->be_private, at->sat_ad );
|
|
-
|
|
- if ( ai && !( ai->ai_indexmask & SLAP_INDEX_NOSUBTYPES ) ) {
|
|
- *atname = at->sat_cname;
|
|
- return ai;
|
|
- }
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/* This function is only called when evaluating search filters.
|
|
- */
|
|
-int bdb_index_param(
|
|
- Backend *be,
|
|
- AttributeDescription *desc,
|
|
- int ftype,
|
|
- DB **dbp,
|
|
- slap_mask_t *maskp,
|
|
- struct berval *prefixp )
|
|
-{
|
|
- AttrInfo *ai;
|
|
- int rc;
|
|
- slap_mask_t mask, type = 0;
|
|
- DB *db;
|
|
-
|
|
- ai = bdb_index_mask( be, desc, prefixp );
|
|
-
|
|
- if ( !ai ) {
|
|
-#ifdef BDB_MONITOR_IDX
|
|
- switch ( ftype ) {
|
|
- case LDAP_FILTER_PRESENT:
|
|
- type = SLAP_INDEX_PRESENT;
|
|
- break;
|
|
- case LDAP_FILTER_APPROX:
|
|
- type = SLAP_INDEX_APPROX;
|
|
- break;
|
|
- case LDAP_FILTER_EQUALITY:
|
|
- type = SLAP_INDEX_EQUALITY;
|
|
- break;
|
|
- case LDAP_FILTER_SUBSTRINGS:
|
|
- type = SLAP_INDEX_SUBSTR;
|
|
- break;
|
|
- default:
|
|
- return LDAP_INAPPROPRIATE_MATCHING;
|
|
- }
|
|
- bdb_monitor_idx_add( be->be_private, desc, type );
|
|
-#endif /* BDB_MONITOR_IDX */
|
|
-
|
|
- return LDAP_INAPPROPRIATE_MATCHING;
|
|
- }
|
|
- mask = ai->ai_indexmask;
|
|
-
|
|
- rc = bdb_db_cache( be, prefixp, &db );
|
|
-
|
|
- if( rc != LDAP_SUCCESS ) {
|
|
- return rc;
|
|
- }
|
|
-
|
|
- switch( ftype ) {
|
|
- case LDAP_FILTER_PRESENT:
|
|
- type = SLAP_INDEX_PRESENT;
|
|
- if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
|
|
- *prefixp = presence_key;
|
|
- goto done;
|
|
- }
|
|
- break;
|
|
-
|
|
- case LDAP_FILTER_APPROX:
|
|
- type = SLAP_INDEX_APPROX;
|
|
- if ( desc->ad_type->sat_approx ) {
|
|
- if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
|
|
- goto done;
|
|
- }
|
|
- break;
|
|
- }
|
|
-
|
|
- /* Use EQUALITY rule and index for approximate match */
|
|
- /* fall thru */
|
|
-
|
|
- case LDAP_FILTER_EQUALITY:
|
|
- type = SLAP_INDEX_EQUALITY;
|
|
- if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
|
|
- goto done;
|
|
- }
|
|
- break;
|
|
-
|
|
- case LDAP_FILTER_SUBSTRINGS:
|
|
- type = SLAP_INDEX_SUBSTR;
|
|
- if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
|
|
- goto done;
|
|
- }
|
|
- break;
|
|
-
|
|
- default:
|
|
- return LDAP_OTHER;
|
|
- }
|
|
-
|
|
-#ifdef BDB_MONITOR_IDX
|
|
- bdb_monitor_idx_add( be->be_private, desc, type );
|
|
-#endif /* BDB_MONITOR_IDX */
|
|
-
|
|
- return LDAP_INAPPROPRIATE_MATCHING;
|
|
-
|
|
-done:
|
|
- *dbp = db;
|
|
- *maskp = mask;
|
|
- return LDAP_SUCCESS;
|
|
-}
|
|
-
|
|
-static int indexer(
|
|
- Operation *op,
|
|
- DB_TXN *txn,
|
|
- AttributeDescription *ad,
|
|
- struct berval *atname,
|
|
- BerVarray vals,
|
|
- ID id,
|
|
- int opid,
|
|
- slap_mask_t mask )
|
|
-{
|
|
- int rc, i;
|
|
- DB *db;
|
|
- struct berval *keys;
|
|
-
|
|
- assert( mask != 0 );
|
|
-
|
|
- rc = bdb_db_cache( op->o_bd, atname, &db );
|
|
-
|
|
- if ( rc != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "bdb_index_read: Could not open DB %s\n",
|
|
- atname->bv_val, 0, 0 );
|
|
- return LDAP_OTHER;
|
|
- }
|
|
-
|
|
- if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
|
|
- rc = bdb_key_change( op->o_bd, db, txn, &presence_key, id, opid );
|
|
- if( rc ) {
|
|
- goto done;
|
|
- }
|
|
- }
|
|
-
|
|
- if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
|
|
- rc = ad->ad_type->sat_equality->smr_indexer(
|
|
- LDAP_FILTER_EQUALITY,
|
|
- mask,
|
|
- ad->ad_type->sat_syntax,
|
|
- ad->ad_type->sat_equality,
|
|
- atname, vals, &keys, op->o_tmpmemctx );
|
|
-
|
|
- if( rc == LDAP_SUCCESS && keys != NULL ) {
|
|
- for( i=0; keys[i].bv_val != NULL; i++ ) {
|
|
- rc = bdb_key_change( op->o_bd, db, txn, &keys[i], id, opid );
|
|
- if( rc ) {
|
|
- ber_bvarray_free_x( keys, op->o_tmpmemctx );
|
|
- goto done;
|
|
- }
|
|
- }
|
|
- ber_bvarray_free_x( keys, op->o_tmpmemctx );
|
|
- }
|
|
- rc = LDAP_SUCCESS;
|
|
- }
|
|
-
|
|
- if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
|
|
- rc = ad->ad_type->sat_approx->smr_indexer(
|
|
- LDAP_FILTER_APPROX,
|
|
- mask,
|
|
- ad->ad_type->sat_syntax,
|
|
- ad->ad_type->sat_approx,
|
|
- atname, vals, &keys, op->o_tmpmemctx );
|
|
-
|
|
- if( rc == LDAP_SUCCESS && keys != NULL ) {
|
|
- for( i=0; keys[i].bv_val != NULL; i++ ) {
|
|
- rc = bdb_key_change( op->o_bd, db, txn, &keys[i], id, opid );
|
|
- if( rc ) {
|
|
- ber_bvarray_free_x( keys, op->o_tmpmemctx );
|
|
- goto done;
|
|
- }
|
|
- }
|
|
- ber_bvarray_free_x( keys, op->o_tmpmemctx );
|
|
- }
|
|
-
|
|
- rc = LDAP_SUCCESS;
|
|
- }
|
|
-
|
|
- if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
|
|
- rc = ad->ad_type->sat_substr->smr_indexer(
|
|
- LDAP_FILTER_SUBSTRINGS,
|
|
- mask,
|
|
- ad->ad_type->sat_syntax,
|
|
- ad->ad_type->sat_substr,
|
|
- atname, vals, &keys, op->o_tmpmemctx );
|
|
-
|
|
- if( rc == LDAP_SUCCESS && keys != NULL ) {
|
|
- for( i=0; keys[i].bv_val != NULL; i++ ) {
|
|
- rc = bdb_key_change( op->o_bd, db, txn, &keys[i], id, opid );
|
|
- if( rc ) {
|
|
- ber_bvarray_free_x( keys, op->o_tmpmemctx );
|
|
- goto done;
|
|
- }
|
|
- }
|
|
- ber_bvarray_free_x( keys, op->o_tmpmemctx );
|
|
- }
|
|
-
|
|
- rc = LDAP_SUCCESS;
|
|
- }
|
|
-
|
|
-done:
|
|
- switch( rc ) {
|
|
- /* The callers all know how to deal with these results */
|
|
- case 0:
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- break;
|
|
- /* Anything else is bad news */
|
|
- default:
|
|
- rc = LDAP_OTHER;
|
|
- }
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static int index_at_values(
|
|
- Operation *op,
|
|
- DB_TXN *txn,
|
|
- AttributeDescription *ad,
|
|
- AttributeType *type,
|
|
- struct berval *tags,
|
|
- BerVarray vals,
|
|
- ID id,
|
|
- int opid )
|
|
-{
|
|
- int rc;
|
|
- slap_mask_t mask = 0;
|
|
- int ixop = opid;
|
|
- AttrInfo *ai = NULL;
|
|
-
|
|
- if ( opid == BDB_INDEX_UPDATE_OP )
|
|
- ixop = SLAP_INDEX_ADD_OP;
|
|
-
|
|
- if( type->sat_sup ) {
|
|
- /* recurse */
|
|
- rc = index_at_values( op, txn, NULL,
|
|
- type->sat_sup, tags,
|
|
- vals, id, opid );
|
|
-
|
|
- if( rc ) return rc;
|
|
- }
|
|
-
|
|
- /* If this type has no AD, we've never used it before */
|
|
- if( type->sat_ad ) {
|
|
- ai = bdb_attr_mask( op->o_bd->be_private, type->sat_ad );
|
|
- if ( ai ) {
|
|
-#ifdef LDAP_COMP_MATCH
|
|
- /* component indexing */
|
|
- if ( ai->ai_cr ) {
|
|
- ComponentReference *cr;
|
|
- for( cr = ai->ai_cr ; cr ; cr = cr->cr_next ) {
|
|
- rc = indexer( op, txn, cr->cr_ad, &type->sat_cname,
|
|
- cr->cr_nvals, id, ixop,
|
|
- cr->cr_indexmask );
|
|
- }
|
|
- }
|
|
-#endif
|
|
- ad = type->sat_ad;
|
|
- /* If we're updating the index, just set the new bits that aren't
|
|
- * already in the old mask.
|
|
- */
|
|
- if ( opid == BDB_INDEX_UPDATE_OP )
|
|
- mask = ai->ai_newmask & ~ai->ai_indexmask;
|
|
- else
|
|
- /* For regular updates, if there is a newmask use it. Otherwise
|
|
- * just use the old mask.
|
|
- */
|
|
- mask = ai->ai_newmask ? ai->ai_newmask : ai->ai_indexmask;
|
|
- if( mask ) {
|
|
- rc = indexer( op, txn, ad, &type->sat_cname,
|
|
- vals, id, ixop, mask );
|
|
-
|
|
- if( rc ) return rc;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- if( tags->bv_len ) {
|
|
- AttributeDescription *desc;
|
|
-
|
|
- desc = ad_find_tags( type, tags );
|
|
- if( desc ) {
|
|
- ai = bdb_attr_mask( op->o_bd->be_private, desc );
|
|
-
|
|
- if( ai ) {
|
|
- if ( opid == BDB_INDEX_UPDATE_OP )
|
|
- mask = ai->ai_newmask & ~ai->ai_indexmask;
|
|
- else
|
|
- mask = ai->ai_newmask ? ai->ai_newmask : ai->ai_indexmask;
|
|
- if ( mask ) {
|
|
- rc = indexer( op, txn, desc, &desc->ad_cname,
|
|
- vals, id, ixop, mask );
|
|
-
|
|
- if( rc ) {
|
|
- return rc;
|
|
- }
|
|
- }
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- return LDAP_SUCCESS;
|
|
-}
|
|
-
|
|
-int bdb_index_values(
|
|
- Operation *op,
|
|
- DB_TXN *txn,
|
|
- AttributeDescription *desc,
|
|
- BerVarray vals,
|
|
- ID id,
|
|
- int opid )
|
|
-{
|
|
- int rc;
|
|
-
|
|
- /* Never index ID 0 */
|
|
- if ( id == 0 )
|
|
- return 0;
|
|
-
|
|
- rc = index_at_values( op, txn, desc,
|
|
- desc->ad_type, &desc->ad_tags,
|
|
- vals, id, opid );
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/* Get the list of which indices apply to this attr */
|
|
-int
|
|
-bdb_index_recset(
|
|
- struct bdb_info *bdb,
|
|
- Attribute *a,
|
|
- AttributeType *type,
|
|
- struct berval *tags,
|
|
- IndexRec *ir )
|
|
-{
|
|
- int rc, slot;
|
|
- AttrList *al;
|
|
-
|
|
- if( type->sat_sup ) {
|
|
- /* recurse */
|
|
- rc = bdb_index_recset( bdb, a, type->sat_sup, tags, ir );
|
|
- if( rc ) return rc;
|
|
- }
|
|
- /* If this type has no AD, we've never used it before */
|
|
- if( type->sat_ad ) {
|
|
- slot = bdb_attr_slot( bdb, type->sat_ad, NULL );
|
|
- if ( slot >= 0 ) {
|
|
- ir[slot].ai = bdb->bi_attrs[slot];
|
|
- al = ch_malloc( sizeof( AttrList ));
|
|
- al->attr = a;
|
|
- al->next = ir[slot].attrs;
|
|
- ir[slot].attrs = al;
|
|
- }
|
|
- }
|
|
- if( tags->bv_len ) {
|
|
- AttributeDescription *desc;
|
|
-
|
|
- desc = ad_find_tags( type, tags );
|
|
- if( desc ) {
|
|
- slot = bdb_attr_slot( bdb, desc, NULL );
|
|
- if ( slot >= 0 ) {
|
|
- ir[slot].ai = bdb->bi_attrs[slot];
|
|
- al = ch_malloc( sizeof( AttrList ));
|
|
- al->attr = a;
|
|
- al->next = ir[slot].attrs;
|
|
- ir[slot].attrs = al;
|
|
- }
|
|
- }
|
|
- }
|
|
- return LDAP_SUCCESS;
|
|
-}
|
|
-
|
|
-/* Apply the indices for the recset */
|
|
-int bdb_index_recrun(
|
|
- Operation *op,
|
|
- struct bdb_info *bdb,
|
|
- IndexRec *ir0,
|
|
- ID id,
|
|
- int base )
|
|
-{
|
|
- IndexRec *ir;
|
|
- AttrList *al;
|
|
- int i, rc = 0;
|
|
-
|
|
- /* Never index ID 0 */
|
|
- if ( id == 0 )
|
|
- return 0;
|
|
-
|
|
- for (i=base; i<bdb->bi_nattrs; i+=slap_tool_thread_max-1) {
|
|
- ir = ir0 + i;
|
|
- if ( !ir->ai ) continue;
|
|
- while (( al = ir->attrs )) {
|
|
- ir->attrs = al->next;
|
|
- rc = indexer( op, NULL, ir->ai->ai_desc,
|
|
- &ir->ai->ai_desc->ad_type->sat_cname,
|
|
- al->attr->a_nvals, id, SLAP_INDEX_ADD_OP,
|
|
- ir->ai->ai_indexmask );
|
|
- free( al );
|
|
- if ( rc ) break;
|
|
- }
|
|
- }
|
|
- return rc;
|
|
-}
|
|
-
|
|
-int
|
|
-bdb_index_entry(
|
|
- Operation *op,
|
|
- DB_TXN *txn,
|
|
- int opid,
|
|
- Entry *e )
|
|
-{
|
|
- int rc;
|
|
- Attribute *ap = e->e_attrs;
|
|
-#if 0 /* ifdef LDAP_COMP_MATCH */
|
|
- ComponentReference *cr_list = NULL;
|
|
- ComponentReference *cr = NULL, *dupped_cr = NULL;
|
|
- void* decoded_comp;
|
|
- ComponentSyntaxInfo* csi_attr;
|
|
- Syntax* syn;
|
|
- AttributeType* at;
|
|
- int i, num_attr;
|
|
- void* mem_op;
|
|
- struct berval value = {0};
|
|
-#endif
|
|
-
|
|
- /* Never index ID 0 */
|
|
- if ( e->e_id == 0 )
|
|
- return 0;
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "=> index_entry_%s( %ld, \"%s\" )\n",
|
|
- opid == SLAP_INDEX_DELETE_OP ? "del" : "add",
|
|
- (long) e->e_id, e->e_dn );
|
|
-
|
|
- /* add each attribute to the indexes */
|
|
- for ( ; ap != NULL; ap = ap->a_next ) {
|
|
-#if 0 /* ifdef LDAP_COMP_MATCH */
|
|
- AttrInfo *ai;
|
|
- /* see if attribute has components to be indexed */
|
|
- ai = bdb_attr_mask( op->o_bd->be_private, ap->a_desc->ad_type->sat_ad );
|
|
- if ( !ai ) continue;
|
|
- cr_list = ai->ai_cr;
|
|
- if ( attr_converter && cr_list ) {
|
|
- syn = ap->a_desc->ad_type->sat_syntax;
|
|
- ap->a_comp_data = op->o_tmpalloc( sizeof( ComponentData ), op->o_tmpmemctx );
|
|
- /* Memory chunk(nibble) pre-allocation for decoders */
|
|
- mem_op = nibble_mem_allocator ( 1024*16, 1024*4 );
|
|
- ap->a_comp_data->cd_mem_op = mem_op;
|
|
- for( cr = cr_list ; cr ; cr = cr->cr_next ) {
|
|
- /* count how many values in an attribute */
|
|
- for( num_attr=0; ap->a_vals[num_attr].bv_val != NULL; num_attr++ );
|
|
- num_attr++;
|
|
- cr->cr_nvals = (BerVarray)op->o_tmpalloc( sizeof( struct berval )*num_attr, op->o_tmpmemctx );
|
|
- for( i=0; ap->a_vals[i].bv_val != NULL; i++ ) {
|
|
- /* decoding attribute value */
|
|
- decoded_comp = attr_converter ( ap, syn, &ap->a_vals[i] );
|
|
- if ( !decoded_comp )
|
|
- return LDAP_DECODING_ERROR;
|
|
- /* extracting the referenced component */
|
|
- dupped_cr = dup_comp_ref( op, cr );
|
|
- csi_attr = ((ComponentSyntaxInfo*)decoded_comp)->csi_comp_desc->cd_extract_i( mem_op, dupped_cr, decoded_comp );
|
|
- if ( !csi_attr )
|
|
- return LDAP_DECODING_ERROR;
|
|
- cr->cr_asn_type_id = csi_attr->csi_comp_desc->cd_type_id;
|
|
- cr->cr_ad = (AttributeDescription*)get_component_description ( cr->cr_asn_type_id );
|
|
- if ( !cr->cr_ad )
|
|
- return LDAP_INVALID_SYNTAX;
|
|
- at = cr->cr_ad->ad_type;
|
|
- /* encoding the value of component in GSER */
|
|
- rc = component_encoder( mem_op, csi_attr, &value );
|
|
- if ( rc != LDAP_SUCCESS )
|
|
- return LDAP_ENCODING_ERROR;
|
|
- /* Normalize the encoded component values */
|
|
- if ( at->sat_equality && at->sat_equality->smr_normalize ) {
|
|
- rc = at->sat_equality->smr_normalize (
|
|
- SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
|
|
- at->sat_syntax, at->sat_equality,
|
|
- &value, &cr->cr_nvals[i], op->o_tmpmemctx );
|
|
- } else {
|
|
- cr->cr_nvals[i] = value;
|
|
- }
|
|
- }
|
|
- /* The end of BerVarray */
|
|
- cr->cr_nvals[num_attr-1].bv_val = NULL;
|
|
- cr->cr_nvals[num_attr-1].bv_len = 0;
|
|
- }
|
|
- op->o_tmpfree( ap->a_comp_data, op->o_tmpmemctx );
|
|
- nibble_mem_free ( mem_op );
|
|
- ap->a_comp_data = NULL;
|
|
- }
|
|
-#endif
|
|
- rc = bdb_index_values( op, txn, ap->a_desc,
|
|
- ap->a_nvals, e->e_id, opid );
|
|
-
|
|
- if( rc != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<= index_entry_%s( %ld, \"%s\" ) failure\n",
|
|
- opid == SLAP_INDEX_ADD_OP ? "add" : "del",
|
|
- (long) e->e_id, e->e_dn );
|
|
- return rc;
|
|
- }
|
|
- }
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "<= index_entry_%s( %ld, \"%s\" ) success\n",
|
|
- opid == SLAP_INDEX_DELETE_OP ? "del" : "add",
|
|
- (long) e->e_id, e->e_dn );
|
|
-
|
|
- return LDAP_SUCCESS;
|
|
-}
|
|
diff --git a/servers/slapd/back-bdb/init.c b/servers/slapd/back-bdb/init.c
|
|
deleted file mode 100644
|
|
index 6c42d54..0000000
|
|
--- a/servers/slapd/back-bdb/init.c
|
|
+++ /dev/null
|
|
@@ -1,874 +0,0 @@
|
|
-/* init.c - initialize bdb backend */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-
|
|
-#include <stdio.h>
|
|
-#include <ac/string.h>
|
|
-#include <ac/unistd.h>
|
|
-#include <ac/stdlib.h>
|
|
-#include <ac/errno.h>
|
|
-#include <sys/stat.h>
|
|
-#include "back-bdb.h"
|
|
-#include <lutil.h>
|
|
-#include <ldap_rq.h>
|
|
-#include "alock.h"
|
|
-#include "config.h"
|
|
-
|
|
-static const struct bdbi_database {
|
|
- char *file;
|
|
- struct berval name;
|
|
- int type;
|
|
- int flags;
|
|
-} bdbi_databases[] = {
|
|
- { "id2entry" BDB_SUFFIX, BER_BVC("id2entry"), DB_BTREE, 0 },
|
|
- { "dn2id" BDB_SUFFIX, BER_BVC("dn2id"), DB_BTREE, 0 },
|
|
- { NULL, BER_BVNULL, 0, 0 }
|
|
-};
|
|
-
|
|
-typedef void * db_malloc(size_t);
|
|
-typedef void * db_realloc(void *, size_t);
|
|
-
|
|
-#define bdb_db_init BDB_SYMBOL(db_init)
|
|
-#define bdb_db_open BDB_SYMBOL(db_open)
|
|
-#define bdb_db_close BDB_SYMBOL(db_close)
|
|
-
|
|
-static int
|
|
-bdb_db_init( BackendDB *be, ConfigReply *cr )
|
|
-{
|
|
- struct bdb_info *bdb;
|
|
- int rc;
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_db_init) ": Initializing " BDB_UCTYPE " database\n",
|
|
- 0, 0, 0 );
|
|
-
|
|
- /* allocate backend-database-specific stuff */
|
|
- bdb = (struct bdb_info *) ch_calloc( 1, sizeof(struct bdb_info) );
|
|
-
|
|
- /* DBEnv parameters */
|
|
- bdb->bi_dbenv_home = ch_strdup( SLAPD_DEFAULT_DB_DIR );
|
|
- bdb->bi_dbenv_xflags = DB_TIME_NOTGRANTED;
|
|
- bdb->bi_dbenv_mode = SLAPD_DEFAULT_DB_MODE;
|
|
-
|
|
- bdb->bi_cache.c_maxsize = DEFAULT_CACHE_SIZE;
|
|
- bdb->bi_cache.c_minfree = 1;
|
|
-
|
|
- bdb->bi_lock_detect = DB_LOCK_DEFAULT;
|
|
- bdb->bi_search_stack_depth = DEFAULT_SEARCH_STACK_DEPTH;
|
|
- bdb->bi_search_stack = NULL;
|
|
-
|
|
- ldap_pvt_thread_mutex_init( &bdb->bi_database_mutex );
|
|
- ldap_pvt_thread_mutex_init( &bdb->bi_lastid_mutex );
|
|
-#ifdef BDB_HIER
|
|
- ldap_pvt_thread_mutex_init( &bdb->bi_modrdns_mutex );
|
|
-#endif
|
|
- ldap_pvt_thread_mutex_init( &bdb->bi_cache.c_lru_mutex );
|
|
- ldap_pvt_thread_mutex_init( &bdb->bi_cache.c_count_mutex );
|
|
- ldap_pvt_thread_mutex_init( &bdb->bi_cache.c_eifree_mutex );
|
|
- ldap_pvt_thread_mutex_init( &bdb->bi_cache.c_dntree.bei_kids_mutex );
|
|
- ldap_pvt_thread_rdwr_init ( &bdb->bi_cache.c_rwlock );
|
|
- ldap_pvt_thread_rdwr_init( &bdb->bi_idl_tree_rwlock );
|
|
- ldap_pvt_thread_mutex_init( &bdb->bi_idl_tree_lrulock );
|
|
-
|
|
- be->be_private = bdb;
|
|
- be->be_cf_ocs = be->bd_info->bi_cf_ocs;
|
|
-
|
|
-#ifndef BDB_MULTIPLE_SUFFIXES
|
|
- SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_ONE_SUFFIX;
|
|
-#endif
|
|
-
|
|
- rc = bdb_monitor_db_init( be );
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static int
|
|
-bdb_db_close( BackendDB *be, ConfigReply *cr );
|
|
-
|
|
-static int
|
|
-bdb_db_open( BackendDB *be, ConfigReply *cr )
|
|
-{
|
|
- int rc, i;
|
|
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
|
- struct stat stat1, stat2;
|
|
- u_int32_t flags;
|
|
- char path[MAXPATHLEN];
|
|
- char *dbhome;
|
|
- Entry *e = NULL;
|
|
- int do_recover = 0, do_alock_recover = 0;
|
|
- int alockt, quick = 0;
|
|
- int do_retry = 1;
|
|
-
|
|
- if ( be->be_suffix == NULL ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- LDAP_XSTRING(bdb_db_open) ": need suffix.\n",
|
|
- 1, 0, 0 );
|
|
- return -1;
|
|
- }
|
|
-
|
|
- Debug( LDAP_DEBUG_ARGS,
|
|
- LDAP_XSTRING(bdb_db_open) ": \"%s\"\n",
|
|
- be->be_suffix[0].bv_val, 0, 0 );
|
|
-
|
|
- /* Check existence of dbenv_home. Any error means trouble */
|
|
- rc = stat( bdb->bi_dbenv_home, &stat1 );
|
|
- if( rc != 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
|
|
- "cannot access database directory \"%s\" (%d).\n",
|
|
- be->be_suffix[0].bv_val, bdb->bi_dbenv_home, errno );
|
|
- return -1;
|
|
- }
|
|
-
|
|
- /* Perform database use arbitration/recovery logic */
|
|
- alockt = (slapMode & SLAP_TOOL_READONLY) ? ALOCK_LOCKED : ALOCK_UNIQUE;
|
|
- if ( slapMode & SLAP_TOOL_QUICK ) {
|
|
- alockt |= ALOCK_NOSAVE;
|
|
- quick = 1;
|
|
- }
|
|
-
|
|
- rc = alock_open( &bdb->bi_alock_info,
|
|
- "slapd",
|
|
- bdb->bi_dbenv_home, alockt );
|
|
-
|
|
- /* alockt is TRUE if the existing environment was created in Quick mode */
|
|
- alockt = (rc & ALOCK_NOSAVE) ? 1 : 0;
|
|
- rc &= ~ALOCK_NOSAVE;
|
|
-
|
|
- if( rc == ALOCK_RECOVER ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
|
|
- "unclean shutdown detected; attempting recovery.\n",
|
|
- be->be_suffix[0].bv_val, 0, 0 );
|
|
- do_alock_recover = 1;
|
|
- do_recover = DB_RECOVER;
|
|
- } else if( rc == ALOCK_BUSY ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
|
|
- "database already in use.\n",
|
|
- be->be_suffix[0].bv_val, 0, 0 );
|
|
- return -1;
|
|
- } else if( rc != ALOCK_CLEAN ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
|
|
- "alock package is unstable.\n",
|
|
- be->be_suffix[0].bv_val, 0, 0 );
|
|
- return -1;
|
|
- }
|
|
- if ( rc == ALOCK_CLEAN )
|
|
- be->be_flags |= SLAP_DBFLAG_CLEAN;
|
|
-
|
|
- /*
|
|
- * The DB_CONFIG file may have changed. If so, recover the
|
|
- * database so that new settings are put into effect. Also
|
|
- * note the possible absence of DB_CONFIG in the log.
|
|
- */
|
|
- if( stat( bdb->bi_db_config_path, &stat1 ) == 0 ) {
|
|
- if ( !do_recover ) {
|
|
- char *ptr = lutil_strcopy(path, bdb->bi_dbenv_home);
|
|
- *ptr++ = LDAP_DIRSEP[0];
|
|
- strcpy( ptr, "__db.001" );
|
|
- if( stat( path, &stat2 ) == 0 ) {
|
|
- if( stat2.st_mtime < stat1.st_mtime ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- LDAP_XSTRING(bdb_db_open) ": DB_CONFIG for suffix \"%s\" has changed.\n",
|
|
- be->be_suffix[0].bv_val, 0, 0 );
|
|
- if ( quick ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "Cannot use Quick mode; perform manual recovery first.\n",
|
|
- 0, 0, 0 );
|
|
- slapMode ^= SLAP_TOOL_QUICK;
|
|
- rc = -1;
|
|
- goto fail;
|
|
- } else {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "Performing database recovery to activate new settings.\n",
|
|
- 0, 0, 0 );
|
|
- }
|
|
- do_recover = DB_RECOVER;
|
|
- }
|
|
- }
|
|
- }
|
|
- }
|
|
- else {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- LDAP_XSTRING(bdb_db_open) ": warning - no DB_CONFIG file found "
|
|
- "in directory %s: (%d).\n"
|
|
- "Expect poor performance for suffix \"%s\".\n",
|
|
- bdb->bi_dbenv_home, errno, be->be_suffix[0].bv_val );
|
|
- }
|
|
-
|
|
- /* Always let slapcat run, regardless of environment state.
|
|
- * This can be used to cause a cache flush after an unclean
|
|
- * shutdown.
|
|
- */
|
|
- if ( do_recover && ( slapMode & SLAP_TOOL_READONLY )) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
|
|
- "recovery skipped in read-only mode. "
|
|
- "Run manual recovery if errors are encountered.\n",
|
|
- be->be_suffix[0].bv_val, 0, 0 );
|
|
- do_recover = 0;
|
|
- do_alock_recover = 0;
|
|
- quick = alockt;
|
|
- }
|
|
-
|
|
- /* An existing environment in Quick mode has nothing to recover. */
|
|
- if ( alockt && do_recover ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
|
|
- "cannot recover, database must be reinitialized.\n",
|
|
- be->be_suffix[0].bv_val, 0, 0 );
|
|
- rc = -1;
|
|
- goto fail;
|
|
- }
|
|
-
|
|
- rc = db_env_create( &bdb->bi_dbenv, 0 );
|
|
- if( rc != 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
|
|
- "db_env_create failed: %s (%d).\n",
|
|
- be->be_suffix[0].bv_val, db_strerror(rc), rc );
|
|
- goto fail;
|
|
- }
|
|
-
|
|
-#ifdef HAVE_EBCDIC
|
|
- strcpy( path, bdb->bi_dbenv_home );
|
|
- __atoe( path );
|
|
- dbhome = path;
|
|
-#else
|
|
- dbhome = bdb->bi_dbenv_home;
|
|
-#endif
|
|
-
|
|
- /* If existing environment is clean but doesn't support
|
|
- * currently requested modes, remove it.
|
|
- */
|
|
- if ( !do_recover && ( alockt ^ quick )) {
|
|
-shm_retry:
|
|
- rc = bdb->bi_dbenv->remove( bdb->bi_dbenv, dbhome, DB_FORCE );
|
|
- if ( rc ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
|
|
- "dbenv remove failed: %s (%d).\n",
|
|
- be->be_suffix[0].bv_val, db_strerror(rc), rc );
|
|
- bdb->bi_dbenv = NULL;
|
|
- goto fail;
|
|
- }
|
|
- rc = db_env_create( &bdb->bi_dbenv, 0 );
|
|
- if( rc != 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
|
|
- "db_env_create failed: %s (%d).\n",
|
|
- be->be_suffix[0].bv_val, db_strerror(rc), rc );
|
|
- goto fail;
|
|
- }
|
|
- }
|
|
-
|
|
- bdb->bi_dbenv->set_errpfx( bdb->bi_dbenv, be->be_suffix[0].bv_val );
|
|
- bdb->bi_dbenv->set_errcall( bdb->bi_dbenv, bdb_errcall );
|
|
-
|
|
- bdb->bi_dbenv->set_lk_detect( bdb->bi_dbenv, bdb->bi_lock_detect );
|
|
-
|
|
- if ( !BER_BVISNULL( &bdb->bi_db_crypt_key )) {
|
|
- rc = bdb->bi_dbenv->set_encrypt( bdb->bi_dbenv, bdb->bi_db_crypt_key.bv_val,
|
|
- DB_ENCRYPT_AES );
|
|
- if ( rc ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
|
|
- "dbenv set_encrypt failed: %s (%d).\n",
|
|
- be->be_suffix[0].bv_val, db_strerror(rc), rc );
|
|
- goto fail;
|
|
- }
|
|
- }
|
|
-
|
|
- /* One long-lived TXN per thread, two TXNs per write op */
|
|
- bdb->bi_dbenv->set_tx_max( bdb->bi_dbenv, connection_pool_max * 3 );
|
|
-
|
|
- if( bdb->bi_dbenv_xflags != 0 ) {
|
|
- rc = bdb->bi_dbenv->set_flags( bdb->bi_dbenv,
|
|
- bdb->bi_dbenv_xflags, 1);
|
|
- if( rc != 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
|
|
- "dbenv_set_flags failed: %s (%d).\n",
|
|
- be->be_suffix[0].bv_val, db_strerror(rc), rc );
|
|
- goto fail;
|
|
- }
|
|
- }
|
|
-
|
|
-#define BDB_TXN_FLAGS (DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN)
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
|
|
- "dbenv_open(%s).\n",
|
|
- be->be_suffix[0].bv_val, bdb->bi_dbenv_home, 0);
|
|
-
|
|
- flags = DB_INIT_MPOOL | DB_CREATE | DB_THREAD;
|
|
-
|
|
- if ( !quick )
|
|
- flags |= BDB_TXN_FLAGS;
|
|
-
|
|
- /* If a key was set, use shared memory for the BDB environment */
|
|
- if ( bdb->bi_shm_key ) {
|
|
- bdb->bi_dbenv->set_shm_key( bdb->bi_dbenv, bdb->bi_shm_key );
|
|
- flags |= DB_SYSTEM_MEM;
|
|
- }
|
|
- rc = (bdb->bi_dbenv->open)( bdb->bi_dbenv, dbhome,
|
|
- flags | do_recover, bdb->bi_dbenv_mode );
|
|
-
|
|
- if ( rc ) {
|
|
- /* Regular open failed, probably a missing shm environment.
|
|
- * Start over, do a recovery.
|
|
- */
|
|
- if ( !do_recover && bdb->bi_shm_key && do_retry ) {
|
|
- bdb->bi_dbenv->close( bdb->bi_dbenv, 0 );
|
|
- rc = db_env_create( &bdb->bi_dbenv, 0 );
|
|
- if( rc == 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open)
|
|
- ": database \"%s\": "
|
|
- "shared memory env open failed, assuming stale env.\n",
|
|
- be->be_suffix[0].bv_val, 0, 0 );
|
|
- do_retry = 0;
|
|
- goto shm_retry;
|
|
- }
|
|
- }
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- LDAP_XSTRING(bdb_db_open) ": database \"%s\" cannot be %s, err %d. "
|
|
- "Restore from backup!\n",
|
|
- be->be_suffix[0].bv_val, do_recover ? "recovered" : "opened", rc );
|
|
- goto fail;
|
|
- }
|
|
-
|
|
- if ( do_alock_recover && alock_recover (&bdb->bi_alock_info) != 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- LDAP_XSTRING(bdb_db_open) ": database \"%s\": alock_recover failed\n",
|
|
- be->be_suffix[0].bv_val, 0, 0 );
|
|
- rc = -1;
|
|
- goto fail;
|
|
- }
|
|
-
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- if ( bdb->bi_cache.c_maxsize ) {
|
|
- bdb->bi_cache.c_zctx = slap_zn_mem_create(
|
|
- SLAP_ZONE_INITSIZE, SLAP_ZONE_MAXSIZE,
|
|
- SLAP_ZONE_DELTA, SLAP_ZONE_SIZE);
|
|
- }
|
|
-#endif
|
|
-
|
|
- /* dncache defaults to 0 == unlimited
|
|
- * must be >= entrycache
|
|
- */
|
|
- if ( bdb->bi_cache.c_eimax && bdb->bi_cache.c_eimax < bdb->bi_cache.c_maxsize ) {
|
|
- bdb->bi_cache.c_eimax = bdb->bi_cache.c_maxsize;
|
|
- }
|
|
-
|
|
- if ( bdb->bi_idl_cache_max_size ) {
|
|
- bdb->bi_idl_tree = NULL;
|
|
- bdb->bi_idl_cache_size = 0;
|
|
- }
|
|
-
|
|
- flags = DB_THREAD | bdb->bi_db_opflags;
|
|
-
|
|
-#ifdef DB_AUTO_COMMIT
|
|
- if ( !quick )
|
|
- flags |= DB_AUTO_COMMIT;
|
|
-#endif
|
|
-
|
|
- bdb->bi_databases = (struct bdb_db_info **) ch_malloc(
|
|
- BDB_INDICES * sizeof(struct bdb_db_info *) );
|
|
-
|
|
- /* open (and create) main database */
|
|
- for( i = 0; bdbi_databases[i].name.bv_val; i++ ) {
|
|
- struct bdb_db_info *db;
|
|
-
|
|
- db = (struct bdb_db_info *) ch_calloc(1, sizeof(struct bdb_db_info));
|
|
-
|
|
- rc = db_create( &db->bdi_db, bdb->bi_dbenv, 0 );
|
|
- if( rc != 0 ) {
|
|
- snprintf(cr->msg, sizeof(cr->msg),
|
|
- "database \"%s\": db_create(%s) failed: %s (%d).",
|
|
- be->be_suffix[0].bv_val,
|
|
- bdb->bi_dbenv_home, db_strerror(rc), rc );
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- LDAP_XSTRING(bdb_db_open) ": %s\n",
|
|
- cr->msg, 0, 0 );
|
|
- ch_free( db );
|
|
- goto fail;
|
|
- }
|
|
-
|
|
- if( !BER_BVISNULL( &bdb->bi_db_crypt_key )) {
|
|
- rc = db->bdi_db->set_flags( db->bdi_db, DB_ENCRYPT );
|
|
- if ( rc ) {
|
|
- snprintf(cr->msg, sizeof(cr->msg),
|
|
- "database \"%s\": db set_flags(DB_ENCRYPT)(%s) failed: %s (%d).",
|
|
- be->be_suffix[0].bv_val,
|
|
- bdb->bi_dbenv_home, db_strerror(rc), rc );
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- LDAP_XSTRING(bdb_db_open) ": %s\n",
|
|
- cr->msg, 0, 0 );
|
|
- db->bdi_db->close( db->bdi_db, 0 );
|
|
- ch_free( db );
|
|
- goto fail;
|
|
- }
|
|
- }
|
|
-
|
|
- if( bdb->bi_flags & BDB_CHKSUM ) {
|
|
- rc = db->bdi_db->set_flags( db->bdi_db, DB_CHKSUM );
|
|
- if ( rc ) {
|
|
- snprintf(cr->msg, sizeof(cr->msg),
|
|
- "database \"%s\": db set_flags(DB_CHKSUM)(%s) failed: %s (%d).",
|
|
- be->be_suffix[0].bv_val,
|
|
- bdb->bi_dbenv_home, db_strerror(rc), rc );
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- LDAP_XSTRING(bdb_db_open) ": %s\n",
|
|
- cr->msg, 0, 0 );
|
|
- db->bdi_db->close( db->bdi_db, 0 );
|
|
- ch_free( db );
|
|
- goto fail;
|
|
- }
|
|
- }
|
|
-
|
|
- rc = bdb_db_findsize( bdb, (struct berval *)&bdbi_databases[i].name );
|
|
-
|
|
- if( i == BDB_ID2ENTRY ) {
|
|
- if ( !rc ) rc = BDB_ID2ENTRY_PAGESIZE;
|
|
- rc = db->bdi_db->set_pagesize( db->bdi_db, rc );
|
|
-
|
|
- if ( slapMode & SLAP_TOOL_MODE )
|
|
- db->bdi_db->mpf->set_priority( db->bdi_db->mpf,
|
|
- DB_PRIORITY_VERY_LOW );
|
|
-
|
|
- if ( slapMode & SLAP_TOOL_READMAIN ) {
|
|
- flags |= DB_RDONLY;
|
|
- } else {
|
|
- flags |= DB_CREATE;
|
|
- }
|
|
- } else {
|
|
- /* Use FS default size if not configured */
|
|
- if ( rc )
|
|
- rc = db->bdi_db->set_pagesize( db->bdi_db, rc );
|
|
-
|
|
- rc = db->bdi_db->set_flags( db->bdi_db,
|
|
- DB_DUP | DB_DUPSORT );
|
|
-#ifndef BDB_HIER
|
|
- if ( slapMode & SLAP_TOOL_READONLY ) {
|
|
- flags |= DB_RDONLY;
|
|
- } else {
|
|
- flags |= DB_CREATE;
|
|
- }
|
|
-#else
|
|
- rc = db->bdi_db->set_dup_compare( db->bdi_db,
|
|
- bdb_dup_compare );
|
|
- if ( slapMode & (SLAP_TOOL_READONLY|SLAP_TOOL_READMAIN) ) {
|
|
- flags |= DB_RDONLY;
|
|
- } else {
|
|
- flags |= DB_CREATE;
|
|
- }
|
|
-#endif
|
|
- }
|
|
-
|
|
-#ifdef HAVE_EBCDIC
|
|
- strcpy( path, bdbi_databases[i].file );
|
|
- __atoe( path );
|
|
- rc = DB_OPEN( db->bdi_db,
|
|
- path,
|
|
- /* bdbi_databases[i].name, */ NULL,
|
|
- bdbi_databases[i].type,
|
|
- bdbi_databases[i].flags | flags,
|
|
- bdb->bi_dbenv_mode );
|
|
-#else
|
|
- rc = DB_OPEN( db->bdi_db,
|
|
- bdbi_databases[i].file,
|
|
- /* bdbi_databases[i].name, */ NULL,
|
|
- bdbi_databases[i].type,
|
|
- bdbi_databases[i].flags | flags,
|
|
- bdb->bi_dbenv_mode );
|
|
-#endif
|
|
-
|
|
- if ( rc != 0 ) {
|
|
- snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": "
|
|
- "db_open(%s/%s) failed: %s (%d).",
|
|
- be->be_suffix[0].bv_val,
|
|
- bdb->bi_dbenv_home, bdbi_databases[i].file,
|
|
- db_strerror(rc), rc );
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- LDAP_XSTRING(bdb_db_open) ": %s\n",
|
|
- cr->msg, 0, 0 );
|
|
- db->bdi_db->close( db->bdi_db, 0 );
|
|
- ch_free( db );
|
|
- goto fail;
|
|
- }
|
|
-
|
|
- flags &= ~(DB_CREATE | DB_RDONLY);
|
|
- db->bdi_name = bdbi_databases[i].name;
|
|
- bdb->bi_databases[i] = db;
|
|
- }
|
|
-
|
|
- bdb->bi_databases[i] = NULL;
|
|
- bdb->bi_ndatabases = i;
|
|
-
|
|
- /* get nextid */
|
|
- rc = bdb_last_id( be, NULL );
|
|
- if( rc != 0 ) {
|
|
- snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": "
|
|
- "last_id(%s) failed: %s (%d).",
|
|
- be->be_suffix[0].bv_val, bdb->bi_dbenv_home,
|
|
- db_strerror(rc), rc );
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- LDAP_XSTRING(bdb_db_open) ": %s\n",
|
|
- cr->msg, 0, 0 );
|
|
- goto fail;
|
|
- }
|
|
-
|
|
- if ( !quick ) {
|
|
- int txflag = DB_READ_COMMITTED;
|
|
- /* avoid deadlocks in server; tools should
|
|
- * wait since they have no deadlock retry mechanism.
|
|
- */
|
|
- if ( slapMode & SLAP_SERVER_MODE )
|
|
- txflag |= DB_TXN_NOWAIT;
|
|
- TXN_BEGIN(bdb->bi_dbenv, NULL, &bdb->bi_cache.c_txn, txflag);
|
|
- }
|
|
-
|
|
- entry_prealloc( bdb->bi_cache.c_maxsize );
|
|
- attr_prealloc( bdb->bi_cache.c_maxsize * 20 );
|
|
-
|
|
- /* setup for empty-DN contexts */
|
|
- if ( BER_BVISEMPTY( &be->be_nsuffix[0] )) {
|
|
- rc = bdb_id2entry( be, NULL, 0, &e );
|
|
- }
|
|
- if ( !e ) {
|
|
- struct berval gluebv = BER_BVC("glue");
|
|
- Operation op = {0};
|
|
- Opheader ohdr = {0};
|
|
- e = entry_alloc();
|
|
- e->e_id = 0;
|
|
- ber_dupbv( &e->e_name, (struct berval *)&slap_empty_bv );
|
|
- ber_dupbv( &e->e_nname, (struct berval *)&slap_empty_bv );
|
|
- attr_merge_one( e, slap_schema.si_ad_objectClass,
|
|
- &gluebv, NULL );
|
|
- attr_merge_one( e, slap_schema.si_ad_structuralObjectClass,
|
|
- &gluebv, NULL );
|
|
- op.o_hdr = &ohdr;
|
|
- op.o_bd = be;
|
|
- op.ora_e = e;
|
|
- op.o_dn = be->be_rootdn;
|
|
- op.o_ndn = be->be_rootndn;
|
|
- slap_add_opattrs( &op, NULL, NULL, 0, 0 );
|
|
- }
|
|
- e->e_ocflags = SLAP_OC_GLUE|SLAP_OC__END;
|
|
- e->e_private = &bdb->bi_cache.c_dntree;
|
|
- bdb->bi_cache.c_dntree.bei_e = e;
|
|
-
|
|
- /* monitor setup */
|
|
- rc = bdb_monitor_db_open( be );
|
|
- if ( rc != 0 ) {
|
|
- goto fail;
|
|
- }
|
|
-
|
|
- bdb->bi_flags |= BDB_IS_OPEN;
|
|
-
|
|
- return 0;
|
|
-
|
|
-fail:
|
|
- bdb_db_close( be, NULL );
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static int
|
|
-bdb_db_close( BackendDB *be, ConfigReply *cr )
|
|
-{
|
|
- int rc;
|
|
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
|
- struct bdb_db_info *db;
|
|
- bdb_idl_cache_entry_t *entry, *next_entry;
|
|
-
|
|
- /* monitor handling */
|
|
- (void)bdb_monitor_db_close( be );
|
|
-
|
|
- {
|
|
- Entry *e = bdb->bi_cache.c_dntree.bei_e;
|
|
- if ( e ) {
|
|
- bdb->bi_cache.c_dntree.bei_e = NULL;
|
|
- e->e_private = NULL;
|
|
- bdb_entry_return( e );
|
|
- }
|
|
- }
|
|
-
|
|
- bdb->bi_flags &= ~BDB_IS_OPEN;
|
|
-
|
|
- ber_bvarray_free( bdb->bi_db_config );
|
|
- bdb->bi_db_config = NULL;
|
|
-
|
|
- if( bdb->bi_dbenv ) {
|
|
- /* Free cache locker if we enabled locking.
|
|
- * TXNs must all be closed before DBs...
|
|
- */
|
|
- if ( !( slapMode & SLAP_TOOL_QUICK ) && bdb->bi_cache.c_txn ) {
|
|
- TXN_ABORT( bdb->bi_cache.c_txn );
|
|
- bdb->bi_cache.c_txn = NULL;
|
|
- }
|
|
- bdb_reader_flush( bdb->bi_dbenv );
|
|
- }
|
|
-
|
|
- while( bdb->bi_databases && bdb->bi_ndatabases-- ) {
|
|
- db = bdb->bi_databases[bdb->bi_ndatabases];
|
|
- rc = db->bdi_db->close( db->bdi_db, 0 );
|
|
- /* Lower numbered names are not strdup'd */
|
|
- if( bdb->bi_ndatabases >= BDB_NDB )
|
|
- free( db->bdi_name.bv_val );
|
|
- free( db );
|
|
- }
|
|
- free( bdb->bi_databases );
|
|
- bdb->bi_databases = NULL;
|
|
-
|
|
- bdb_cache_release_all (&bdb->bi_cache);
|
|
-
|
|
- if ( bdb->bi_idl_cache_size ) {
|
|
- avl_free( bdb->bi_idl_tree, NULL );
|
|
- bdb->bi_idl_tree = NULL;
|
|
- entry = bdb->bi_idl_lru_head;
|
|
- do {
|
|
- next_entry = entry->idl_lru_next;
|
|
- if ( entry->idl )
|
|
- free( entry->idl );
|
|
- free( entry->kstr.bv_val );
|
|
- free( entry );
|
|
- entry = next_entry;
|
|
- } while ( entry != bdb->bi_idl_lru_head );
|
|
- bdb->bi_idl_lru_head = bdb->bi_idl_lru_tail = NULL;
|
|
- }
|
|
-
|
|
- /* close db environment */
|
|
- if( bdb->bi_dbenv ) {
|
|
- /* force a checkpoint, but not if we were ReadOnly,
|
|
- * and not in Quick mode since there are no transactions there.
|
|
- */
|
|
- if ( !( slapMode & ( SLAP_TOOL_QUICK|SLAP_TOOL_READONLY ))) {
|
|
- rc = TXN_CHECKPOINT( bdb->bi_dbenv, 0, 0, DB_FORCE );
|
|
- if( rc != 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "bdb_db_close: database \"%s\": "
|
|
- "txn_checkpoint failed: %s (%d).\n",
|
|
- be->be_suffix[0].bv_val, db_strerror(rc), rc );
|
|
- }
|
|
- }
|
|
-
|
|
- rc = bdb->bi_dbenv->close( bdb->bi_dbenv, 0 );
|
|
- bdb->bi_dbenv = NULL;
|
|
- if( rc != 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "bdb_db_close: database \"%s\": "
|
|
- "close failed: %s (%d)\n",
|
|
- be->be_suffix[0].bv_val, db_strerror(rc), rc );
|
|
- return rc;
|
|
- }
|
|
- }
|
|
-
|
|
- rc = alock_close( &bdb->bi_alock_info, slapMode & SLAP_TOOL_QUICK );
|
|
- if( rc != 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "bdb_db_close: database \"%s\": alock_close failed\n",
|
|
- be->be_suffix[0].bv_val, 0, 0 );
|
|
- return -1;
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int
|
|
-bdb_db_destroy( BackendDB *be, ConfigReply *cr )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
|
-
|
|
- /* stop and remove checkpoint task */
|
|
- if ( bdb->bi_txn_cp_task ) {
|
|
- struct re_s *re = bdb->bi_txn_cp_task;
|
|
- bdb->bi_txn_cp_task = NULL;
|
|
- ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
|
|
- if ( ldap_pvt_runqueue_isrunning( &slapd_rq, re ) )
|
|
- ldap_pvt_runqueue_stoptask( &slapd_rq, re );
|
|
- ldap_pvt_runqueue_remove( &slapd_rq, re );
|
|
- ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
|
|
- }
|
|
-
|
|
- /* monitor handling */
|
|
- (void)bdb_monitor_db_destroy( be );
|
|
-
|
|
- if( bdb->bi_dbenv_home ) ch_free( bdb->bi_dbenv_home );
|
|
- if( bdb->bi_db_config_path ) ch_free( bdb->bi_db_config_path );
|
|
-
|
|
- bdb_attr_index_destroy( bdb );
|
|
-
|
|
- ldap_pvt_thread_rdwr_destroy ( &bdb->bi_cache.c_rwlock );
|
|
- ldap_pvt_thread_mutex_destroy( &bdb->bi_cache.c_lru_mutex );
|
|
- ldap_pvt_thread_mutex_destroy( &bdb->bi_cache.c_count_mutex );
|
|
- ldap_pvt_thread_mutex_destroy( &bdb->bi_cache.c_eifree_mutex );
|
|
- ldap_pvt_thread_mutex_destroy( &bdb->bi_cache.c_dntree.bei_kids_mutex );
|
|
-#ifdef BDB_HIER
|
|
- ldap_pvt_thread_mutex_destroy( &bdb->bi_modrdns_mutex );
|
|
-#endif
|
|
- ldap_pvt_thread_mutex_destroy( &bdb->bi_lastid_mutex );
|
|
- ldap_pvt_thread_mutex_destroy( &bdb->bi_database_mutex );
|
|
- ldap_pvt_thread_rdwr_destroy( &bdb->bi_idl_tree_rwlock );
|
|
- ldap_pvt_thread_mutex_destroy( &bdb->bi_idl_tree_lrulock );
|
|
-
|
|
- ch_free( bdb );
|
|
- be->be_private = NULL;
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-int
|
|
-bdb_back_initialize(
|
|
- BackendInfo *bi )
|
|
-{
|
|
- int rc;
|
|
-
|
|
- static char *controls[] = {
|
|
- LDAP_CONTROL_ASSERT,
|
|
- LDAP_CONTROL_MANAGEDSAIT,
|
|
- LDAP_CONTROL_NOOP,
|
|
- LDAP_CONTROL_PAGEDRESULTS,
|
|
- LDAP_CONTROL_PRE_READ,
|
|
- LDAP_CONTROL_POST_READ,
|
|
- LDAP_CONTROL_SUBENTRIES,
|
|
- LDAP_CONTROL_X_PERMISSIVE_MODIFY,
|
|
-#ifdef LDAP_X_TXN
|
|
- LDAP_CONTROL_X_TXN_SPEC,
|
|
-#endif
|
|
- NULL
|
|
- };
|
|
-
|
|
- /* initialize the underlying database system */
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_back_initialize) ": initialize "
|
|
- BDB_UCTYPE " backend\n", 0, 0, 0 );
|
|
-
|
|
- bi->bi_flags |=
|
|
- SLAP_BFLAG_INCREMENT |
|
|
- SLAP_BFLAG_SUBENTRIES |
|
|
- SLAP_BFLAG_ALIASES |
|
|
- SLAP_BFLAG_REFERRALS;
|
|
-
|
|
- bi->bi_controls = controls;
|
|
-
|
|
- { /* version check */
|
|
- int major, minor, patch, ver;
|
|
- char *version = db_version( &major, &minor, &patch );
|
|
-#ifdef HAVE_EBCDIC
|
|
- char v2[1024];
|
|
-
|
|
- /* All our stdio does an ASCII to EBCDIC conversion on
|
|
- * the output. Strings from the BDB library are already
|
|
- * in EBCDIC; we have to go back and forth...
|
|
- */
|
|
- strcpy( v2, version );
|
|
- __etoa( v2 );
|
|
- version = v2;
|
|
-#endif
|
|
-
|
|
- ver = (major << 24) | (minor << 16) | patch;
|
|
- if( ver != DB_VERSION_FULL ) {
|
|
- /* fail if a versions don't match */
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- LDAP_XSTRING(bdb_back_initialize) ": "
|
|
- "BDB library version mismatch:"
|
|
- " expected " DB_VERSION_STRING ","
|
|
- " got %s\n", version, 0, 0 );
|
|
- return -1;
|
|
- }
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_back_initialize)
|
|
- ": %s\n", version, 0, 0 );
|
|
- }
|
|
-
|
|
- db_env_set_func_free( ber_memfree );
|
|
- db_env_set_func_malloc( (db_malloc *)ber_memalloc );
|
|
- db_env_set_func_realloc( (db_realloc *)ber_memrealloc );
|
|
-#if !defined(NO_THREAD) && DB_VERSION_FULL <= 0x04070000
|
|
- /* This is a no-op on a NO_THREAD build. Leave the default
|
|
- * alone so that BDB will sleep on interprocess conflicts.
|
|
- * Don't bother on BDB 4.7...
|
|
- */
|
|
- db_env_set_func_yield( ldap_pvt_thread_yield );
|
|
-#endif
|
|
-
|
|
- bi->bi_open = 0;
|
|
- bi->bi_close = 0;
|
|
- bi->bi_config = 0;
|
|
- bi->bi_destroy = 0;
|
|
-
|
|
- bi->bi_db_init = bdb_db_init;
|
|
- bi->bi_db_config = config_generic_wrapper;
|
|
- bi->bi_db_open = bdb_db_open;
|
|
- bi->bi_db_close = bdb_db_close;
|
|
- bi->bi_db_destroy = bdb_db_destroy;
|
|
-
|
|
- bi->bi_op_add = bdb_add;
|
|
- bi->bi_op_bind = bdb_bind;
|
|
- bi->bi_op_compare = bdb_compare;
|
|
- bi->bi_op_delete = bdb_delete;
|
|
- bi->bi_op_modify = bdb_modify;
|
|
- bi->bi_op_modrdn = bdb_modrdn;
|
|
- bi->bi_op_search = bdb_search;
|
|
-
|
|
- bi->bi_op_unbind = 0;
|
|
-
|
|
- bi->bi_extended = bdb_extended;
|
|
-
|
|
- bi->bi_chk_referrals = bdb_referrals;
|
|
- bi->bi_operational = bdb_operational;
|
|
- bi->bi_has_subordinates = bdb_hasSubordinates;
|
|
- bi->bi_entry_release_rw = bdb_entry_release;
|
|
- bi->bi_entry_get_rw = bdb_entry_get;
|
|
-
|
|
- /*
|
|
- * hooks for slap tools
|
|
- */
|
|
- bi->bi_tool_entry_open = bdb_tool_entry_open;
|
|
- bi->bi_tool_entry_close = bdb_tool_entry_close;
|
|
- bi->bi_tool_entry_first = backend_tool_entry_first;
|
|
- bi->bi_tool_entry_first_x = bdb_tool_entry_first_x;
|
|
- bi->bi_tool_entry_next = bdb_tool_entry_next;
|
|
- bi->bi_tool_entry_get = bdb_tool_entry_get;
|
|
- bi->bi_tool_entry_put = bdb_tool_entry_put;
|
|
- bi->bi_tool_entry_reindex = bdb_tool_entry_reindex;
|
|
- bi->bi_tool_sync = 0;
|
|
- bi->bi_tool_dn2id_get = bdb_tool_dn2id_get;
|
|
- bi->bi_tool_entry_modify = bdb_tool_entry_modify;
|
|
-
|
|
- bi->bi_connection_init = 0;
|
|
- bi->bi_connection_destroy = 0;
|
|
-
|
|
- rc = bdb_back_init_cf( bi );
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-#if (SLAPD_BDB == SLAPD_MOD_DYNAMIC && !defined(BDB_HIER)) || \
|
|
- (SLAPD_HDB == SLAPD_MOD_DYNAMIC && defined(BDB_HIER))
|
|
-
|
|
-/* conditionally define the init_module() function */
|
|
-#ifdef BDB_HIER
|
|
-SLAP_BACKEND_INIT_MODULE( hdb )
|
|
-#else /* !BDB_HIER */
|
|
-SLAP_BACKEND_INIT_MODULE( bdb )
|
|
-#endif /* !BDB_HIER */
|
|
-
|
|
-#endif /* SLAPD_[BH]DB == SLAPD_MOD_DYNAMIC */
|
|
-
|
|
diff --git a/servers/slapd/back-bdb/key.c b/servers/slapd/back-bdb/key.c
|
|
deleted file mode 100644
|
|
index 417ad70..0000000
|
|
--- a/servers/slapd/back-bdb/key.c
|
|
+++ /dev/null
|
|
@@ -1,104 +0,0 @@
|
|
-/* index.c - routines for dealing with attribute indexes */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-
|
|
-#include <stdio.h>
|
|
-
|
|
-#include <ac/string.h>
|
|
-#include <ac/socket.h>
|
|
-
|
|
-#include "slap.h"
|
|
-#include "back-bdb.h"
|
|
-#include "idl.h"
|
|
-
|
|
-/* read a key */
|
|
-int
|
|
-bdb_key_read(
|
|
- Backend *be,
|
|
- DB *db,
|
|
- DB_TXN *txn,
|
|
- struct berval *k,
|
|
- ID *ids,
|
|
- DBC **saved_cursor,
|
|
- int get_flag
|
|
-)
|
|
-{
|
|
- int rc;
|
|
- DBT key;
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "=> key_read\n", 0, 0, 0 );
|
|
-
|
|
- DBTzero( &key );
|
|
- bv2DBT(k,&key);
|
|
- key.ulen = key.size;
|
|
- key.flags = DB_DBT_USERMEM;
|
|
-
|
|
- rc = bdb_idl_fetch_key( be, db, txn, &key, ids, saved_cursor, get_flag );
|
|
-
|
|
- if( rc != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_TRACE, "<= bdb_index_read: failed (%d)\n",
|
|
- rc, 0, 0 );
|
|
- } else {
|
|
- Debug( LDAP_DEBUG_TRACE, "<= bdb_index_read %ld candidates\n",
|
|
- (long) BDB_IDL_N(ids), 0, 0 );
|
|
- }
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/* Add or remove stuff from index files */
|
|
-int
|
|
-bdb_key_change(
|
|
- Backend *be,
|
|
- DB *db,
|
|
- DB_TXN *txn,
|
|
- struct berval *k,
|
|
- ID id,
|
|
- int op
|
|
-)
|
|
-{
|
|
- int rc;
|
|
- DBT key;
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "=> key_change(%s,%lx)\n",
|
|
- op == SLAP_INDEX_ADD_OP ? "ADD":"DELETE", (long) id, 0 );
|
|
-
|
|
- DBTzero( &key );
|
|
- bv2DBT(k,&key);
|
|
- key.ulen = key.size;
|
|
- key.flags = DB_DBT_USERMEM;
|
|
-
|
|
- if (op == SLAP_INDEX_ADD_OP) {
|
|
- /* Add values */
|
|
-
|
|
-#ifdef BDB_TOOL_IDL_CACHING
|
|
- if ( slapMode & SLAP_TOOL_QUICK )
|
|
- rc = bdb_tool_idl_add( be, db, txn, &key, id );
|
|
- else
|
|
-#endif
|
|
- rc = bdb_idl_insert_key( be, db, txn, &key, id );
|
|
- if ( rc == DB_KEYEXIST ) rc = 0;
|
|
- } else {
|
|
- /* Delete values */
|
|
- rc = bdb_idl_delete_key( be, db, txn, &key, id );
|
|
- if ( rc == DB_NOTFOUND ) rc = 0;
|
|
- }
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "<= key_change %d\n", rc, 0, 0 );
|
|
-
|
|
- return rc;
|
|
-}
|
|
diff --git a/servers/slapd/back-bdb/modify.c b/servers/slapd/back-bdb/modify.c
|
|
deleted file mode 100644
|
|
index fb7dbe3..0000000
|
|
--- a/servers/slapd/back-bdb/modify.c
|
|
+++ /dev/null
|
|
@@ -1,835 +0,0 @@
|
|
-/* modify.c - bdb backend modify routine */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-
|
|
-#include <stdio.h>
|
|
-#include <ac/string.h>
|
|
-#include <ac/time.h>
|
|
-
|
|
-#include "back-bdb.h"
|
|
-
|
|
-static struct berval scbva[] = {
|
|
- BER_BVC("glue"),
|
|
- BER_BVNULL
|
|
-};
|
|
-
|
|
-static void
|
|
-bdb_modify_idxflags(
|
|
- Operation *op,
|
|
- AttributeDescription *desc,
|
|
- int got_delete,
|
|
- Attribute *newattrs,
|
|
- Attribute *oldattrs )
|
|
-{
|
|
- struct berval ix_at;
|
|
- AttrInfo *ai;
|
|
-
|
|
- /* check if modified attribute was indexed
|
|
- * but not in case of NOOP... */
|
|
- ai = bdb_index_mask( op->o_bd, desc, &ix_at );
|
|
- if ( ai ) {
|
|
- if ( got_delete ) {
|
|
- Attribute *ap;
|
|
- struct berval ix2;
|
|
-
|
|
- ap = attr_find( oldattrs, desc );
|
|
- if ( ap ) ap->a_flags |= SLAP_ATTR_IXDEL;
|
|
-
|
|
- /* Find all other attrs that index to same slot */
|
|
- for ( ap = newattrs; ap; ap = ap->a_next ) {
|
|
- ai = bdb_index_mask( op->o_bd, ap->a_desc, &ix2 );
|
|
- if ( ai && ix2.bv_val == ix_at.bv_val )
|
|
- ap->a_flags |= SLAP_ATTR_IXADD;
|
|
- }
|
|
-
|
|
- } else {
|
|
- Attribute *ap;
|
|
-
|
|
- ap = attr_find( newattrs, desc );
|
|
- if ( ap ) ap->a_flags |= SLAP_ATTR_IXADD;
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
-int bdb_modify_internal(
|
|
- Operation *op,
|
|
- DB_TXN *tid,
|
|
- Modifications *modlist,
|
|
- Entry *e,
|
|
- const char **text,
|
|
- char *textbuf,
|
|
- size_t textlen )
|
|
-{
|
|
- int rc, err;
|
|
- Modification *mod;
|
|
- Modifications *ml;
|
|
- Attribute *save_attrs;
|
|
- Attribute *ap;
|
|
- int glue_attr_delete = 0;
|
|
- int got_delete;
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "bdb_modify_internal: 0x%08lx: %s\n",
|
|
- e->e_id, e->e_dn, 0);
|
|
-
|
|
- if ( !acl_check_modlist( op, e, modlist )) {
|
|
- return LDAP_INSUFFICIENT_ACCESS;
|
|
- }
|
|
-
|
|
- /* save_attrs will be disposed of by bdb_cache_modify */
|
|
- save_attrs = e->e_attrs;
|
|
- e->e_attrs = attrs_dup( e->e_attrs );
|
|
-
|
|
- for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
|
|
- int match;
|
|
- mod = &ml->sml_mod;
|
|
- switch( mod->sm_op ) {
|
|
- case LDAP_MOD_ADD:
|
|
- case LDAP_MOD_REPLACE:
|
|
- if ( mod->sm_desc == slap_schema.si_ad_structuralObjectClass ) {
|
|
- value_match( &match, slap_schema.si_ad_structuralObjectClass,
|
|
- slap_schema.si_ad_structuralObjectClass->
|
|
- ad_type->sat_equality,
|
|
- SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
|
|
- &mod->sm_values[0], &scbva[0], text );
|
|
- if ( !match ) glue_attr_delete = 1;
|
|
- }
|
|
- }
|
|
- if ( glue_attr_delete )
|
|
- break;
|
|
- }
|
|
-
|
|
- if ( glue_attr_delete ) {
|
|
- Attribute **app = &e->e_attrs;
|
|
- while ( *app != NULL ) {
|
|
- if ( !is_at_operational( (*app)->a_desc->ad_type )) {
|
|
- Attribute *save = *app;
|
|
- *app = (*app)->a_next;
|
|
- attr_free( save );
|
|
- continue;
|
|
- }
|
|
- app = &(*app)->a_next;
|
|
- }
|
|
- }
|
|
-
|
|
- for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
|
|
- mod = &ml->sml_mod;
|
|
- got_delete = 0;
|
|
-
|
|
- switch ( mod->sm_op ) {
|
|
- case LDAP_MOD_ADD:
|
|
- Debug(LDAP_DEBUG_ARGS,
|
|
- "bdb_modify_internal: add %s\n",
|
|
- mod->sm_desc->ad_cname.bv_val, 0, 0);
|
|
- err = modify_add_values( e, mod, get_permissiveModify(op),
|
|
- text, textbuf, textlen );
|
|
- if( err != LDAP_SUCCESS ) {
|
|
- Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
|
|
- err, *text, 0);
|
|
- }
|
|
- break;
|
|
-
|
|
- case LDAP_MOD_DELETE:
|
|
- if ( glue_attr_delete ) {
|
|
- err = LDAP_SUCCESS;
|
|
- break;
|
|
- }
|
|
-
|
|
- Debug(LDAP_DEBUG_ARGS,
|
|
- "bdb_modify_internal: delete %s\n",
|
|
- mod->sm_desc->ad_cname.bv_val, 0, 0);
|
|
- err = modify_delete_values( e, mod, get_permissiveModify(op),
|
|
- text, textbuf, textlen );
|
|
- if( err != LDAP_SUCCESS ) {
|
|
- Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
|
|
- err, *text, 0);
|
|
- } else {
|
|
- got_delete = 1;
|
|
- }
|
|
- break;
|
|
-
|
|
- case LDAP_MOD_REPLACE:
|
|
- Debug(LDAP_DEBUG_ARGS,
|
|
- "bdb_modify_internal: replace %s\n",
|
|
- mod->sm_desc->ad_cname.bv_val, 0, 0);
|
|
- err = modify_replace_values( e, mod, get_permissiveModify(op),
|
|
- text, textbuf, textlen );
|
|
- if( err != LDAP_SUCCESS ) {
|
|
- Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
|
|
- err, *text, 0);
|
|
- } else {
|
|
- got_delete = 1;
|
|
- }
|
|
- break;
|
|
-
|
|
- case LDAP_MOD_INCREMENT:
|
|
- Debug(LDAP_DEBUG_ARGS,
|
|
- "bdb_modify_internal: increment %s\n",
|
|
- mod->sm_desc->ad_cname.bv_val, 0, 0);
|
|
- err = modify_increment_values( e, mod, get_permissiveModify(op),
|
|
- text, textbuf, textlen );
|
|
- if( err != LDAP_SUCCESS ) {
|
|
- Debug(LDAP_DEBUG_ARGS,
|
|
- "bdb_modify_internal: %d %s\n",
|
|
- err, *text, 0);
|
|
- } else {
|
|
- got_delete = 1;
|
|
- }
|
|
- break;
|
|
-
|
|
- case SLAP_MOD_SOFTADD:
|
|
- Debug(LDAP_DEBUG_ARGS,
|
|
- "bdb_modify_internal: softadd %s\n",
|
|
- mod->sm_desc->ad_cname.bv_val, 0, 0);
|
|
- /* Avoid problems in index_add_mods()
|
|
- * We need to add index if necessary.
|
|
- */
|
|
- mod->sm_op = LDAP_MOD_ADD;
|
|
-
|
|
- err = modify_add_values( e, mod, get_permissiveModify(op),
|
|
- text, textbuf, textlen );
|
|
-
|
|
- mod->sm_op = SLAP_MOD_SOFTADD;
|
|
-
|
|
- if ( err == LDAP_TYPE_OR_VALUE_EXISTS ) {
|
|
- err = LDAP_SUCCESS;
|
|
- }
|
|
-
|
|
- if( err != LDAP_SUCCESS ) {
|
|
- Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
|
|
- err, *text, 0);
|
|
- }
|
|
- break;
|
|
-
|
|
- case SLAP_MOD_SOFTDEL:
|
|
- Debug(LDAP_DEBUG_ARGS,
|
|
- "bdb_modify_internal: softdel %s\n",
|
|
- mod->sm_desc->ad_cname.bv_val, 0, 0);
|
|
- /* Avoid problems in index_delete_mods()
|
|
- * We need to add index if necessary.
|
|
- */
|
|
- mod->sm_op = LDAP_MOD_DELETE;
|
|
-
|
|
- err = modify_delete_values( e, mod, get_permissiveModify(op),
|
|
- text, textbuf, textlen );
|
|
-
|
|
- mod->sm_op = SLAP_MOD_SOFTDEL;
|
|
-
|
|
- if ( err == LDAP_SUCCESS ) {
|
|
- got_delete = 1;
|
|
- } else if ( err == LDAP_NO_SUCH_ATTRIBUTE ) {
|
|
- err = LDAP_SUCCESS;
|
|
- }
|
|
-
|
|
- if( err != LDAP_SUCCESS ) {
|
|
- Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
|
|
- err, *text, 0);
|
|
- }
|
|
- break;
|
|
-
|
|
- case SLAP_MOD_ADD_IF_NOT_PRESENT:
|
|
- if ( attr_find( e->e_attrs, mod->sm_desc ) != NULL ) {
|
|
- /* skip */
|
|
- err = LDAP_SUCCESS;
|
|
- break;
|
|
- }
|
|
-
|
|
- Debug(LDAP_DEBUG_ARGS,
|
|
- "bdb_modify_internal: add_if_not_present %s\n",
|
|
- mod->sm_desc->ad_cname.bv_val, 0, 0);
|
|
- /* Avoid problems in index_add_mods()
|
|
- * We need to add index if necessary.
|
|
- */
|
|
- mod->sm_op = LDAP_MOD_ADD;
|
|
-
|
|
- err = modify_add_values( e, mod, get_permissiveModify(op),
|
|
- text, textbuf, textlen );
|
|
-
|
|
- mod->sm_op = SLAP_MOD_ADD_IF_NOT_PRESENT;
|
|
-
|
|
- if( err != LDAP_SUCCESS ) {
|
|
- Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
|
|
- err, *text, 0);
|
|
- }
|
|
- break;
|
|
-
|
|
- default:
|
|
- Debug(LDAP_DEBUG_ANY, "bdb_modify_internal: invalid op %d\n",
|
|
- mod->sm_op, 0, 0);
|
|
- *text = "Invalid modify operation";
|
|
- err = LDAP_OTHER;
|
|
- Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
|
|
- err, *text, 0);
|
|
- }
|
|
-
|
|
- if ( err != LDAP_SUCCESS ) {
|
|
- attrs_free( e->e_attrs );
|
|
- e->e_attrs = save_attrs;
|
|
- /* unlock entry, delete from cache */
|
|
- return err;
|
|
- }
|
|
-
|
|
- /* If objectClass was modified, reset the flags */
|
|
- if ( mod->sm_desc == slap_schema.si_ad_objectClass ) {
|
|
- e->e_ocflags = 0;
|
|
- }
|
|
-
|
|
- if ( glue_attr_delete ) e->e_ocflags = 0;
|
|
-
|
|
-
|
|
- /* check if modified attribute was indexed
|
|
- * but not in case of NOOP... */
|
|
- if ( !op->o_noop ) {
|
|
- bdb_modify_idxflags( op, mod->sm_desc, got_delete, e->e_attrs, save_attrs );
|
|
- }
|
|
- }
|
|
-
|
|
- /* check that the entry still obeys the schema */
|
|
- ap = NULL;
|
|
- rc = entry_schema_check( op, e, save_attrs, get_relax(op), 0, &ap,
|
|
- text, textbuf, textlen );
|
|
- if ( rc != LDAP_SUCCESS || op->o_noop ) {
|
|
- attrs_free( e->e_attrs );
|
|
- /* clear the indexing flags */
|
|
- for ( ap = save_attrs; ap != NULL; ap = ap->a_next ) {
|
|
- ap->a_flags &= ~(SLAP_ATTR_IXADD|SLAP_ATTR_IXDEL);
|
|
- }
|
|
- e->e_attrs = save_attrs;
|
|
-
|
|
- if ( rc != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "entry failed schema check: %s\n",
|
|
- *text, 0, 0 );
|
|
- }
|
|
-
|
|
- /* if NOOP then silently revert to saved attrs */
|
|
- return rc;
|
|
- }
|
|
-
|
|
- /* structuralObjectClass modified! */
|
|
- if ( ap ) {
|
|
- assert( ap->a_desc == slap_schema.si_ad_structuralObjectClass );
|
|
- if ( !op->o_noop ) {
|
|
- bdb_modify_idxflags( op, slap_schema.si_ad_structuralObjectClass,
|
|
- 1, e->e_attrs, save_attrs );
|
|
- }
|
|
- }
|
|
-
|
|
- /* update the indices of the modified attributes */
|
|
-
|
|
- /* start with deleting the old index entries */
|
|
- for ( ap = save_attrs; ap != NULL; ap = ap->a_next ) {
|
|
- if ( ap->a_flags & SLAP_ATTR_IXDEL ) {
|
|
- struct berval *vals;
|
|
- Attribute *a2;
|
|
- ap->a_flags &= ~SLAP_ATTR_IXDEL;
|
|
- a2 = attr_find( e->e_attrs, ap->a_desc );
|
|
- if ( a2 ) {
|
|
- /* need to detect which values were deleted */
|
|
- int i, j;
|
|
- /* let add know there were deletes */
|
|
- if ( a2->a_flags & SLAP_ATTR_IXADD )
|
|
- a2->a_flags |= SLAP_ATTR_IXDEL;
|
|
- vals = op->o_tmpalloc( (ap->a_numvals + 1) *
|
|
- sizeof(struct berval), op->o_tmpmemctx );
|
|
- j = 0;
|
|
- for ( i=0; i < ap->a_numvals; i++ ) {
|
|
- rc = attr_valfind( a2, SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
|
|
- &ap->a_nvals[i], NULL, op->o_tmpmemctx );
|
|
- /* Save deleted values */
|
|
- if ( rc == LDAP_NO_SUCH_ATTRIBUTE )
|
|
- vals[j++] = ap->a_nvals[i];
|
|
- }
|
|
- BER_BVZERO(vals+j);
|
|
- } else {
|
|
- /* attribute was completely deleted */
|
|
- vals = ap->a_nvals;
|
|
- }
|
|
- rc = 0;
|
|
- if ( !BER_BVISNULL( vals )) {
|
|
- rc = bdb_index_values( op, tid, ap->a_desc,
|
|
- vals, e->e_id, SLAP_INDEX_DELETE_OP );
|
|
- if ( rc != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "%s: attribute \"%s\" index delete failure\n",
|
|
- op->o_log_prefix, ap->a_desc->ad_cname.bv_val, 0 );
|
|
- attrs_free( e->e_attrs );
|
|
- e->e_attrs = save_attrs;
|
|
- }
|
|
- }
|
|
- if ( vals != ap->a_nvals )
|
|
- op->o_tmpfree( vals, op->o_tmpmemctx );
|
|
- if ( rc ) return rc;
|
|
- }
|
|
- }
|
|
-
|
|
- /* add the new index entries */
|
|
- for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) {
|
|
- if (ap->a_flags & SLAP_ATTR_IXADD) {
|
|
- ap->a_flags &= ~SLAP_ATTR_IXADD;
|
|
- if ( ap->a_flags & SLAP_ATTR_IXDEL ) {
|
|
- /* if any values were deleted, we must readd index
|
|
- * for all remaining values.
|
|
- */
|
|
- ap->a_flags &= ~SLAP_ATTR_IXDEL;
|
|
- rc = bdb_index_values( op, tid, ap->a_desc,
|
|
- ap->a_nvals,
|
|
- e->e_id, SLAP_INDEX_ADD_OP );
|
|
- } else {
|
|
- int found = 0;
|
|
- /* if this was only an add, we only need to index
|
|
- * the added values.
|
|
- */
|
|
- for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
|
|
- struct berval *vals;
|
|
- if ( ml->sml_desc != ap->a_desc || !ml->sml_numvals )
|
|
- continue;
|
|
- found = 1;
|
|
- switch( ml->sml_op ) {
|
|
- case LDAP_MOD_ADD:
|
|
- case LDAP_MOD_REPLACE:
|
|
- case LDAP_MOD_INCREMENT:
|
|
- case SLAP_MOD_SOFTADD:
|
|
- case SLAP_MOD_ADD_IF_NOT_PRESENT:
|
|
- if ( ml->sml_op == LDAP_MOD_INCREMENT )
|
|
- vals = ap->a_nvals;
|
|
- else if ( ml->sml_nvalues )
|
|
- vals = ml->sml_nvalues;
|
|
- else
|
|
- vals = ml->sml_values;
|
|
- rc = bdb_index_values( op, tid, ap->a_desc,
|
|
- vals, e->e_id, SLAP_INDEX_ADD_OP );
|
|
- break;
|
|
- }
|
|
- if ( rc )
|
|
- break;
|
|
- }
|
|
- /* This attr was affected by a modify of a subtype, so
|
|
- * there was no direct match in the modlist. Just readd
|
|
- * all of its values.
|
|
- */
|
|
- if ( !found ) {
|
|
- rc = bdb_index_values( op, tid, ap->a_desc,
|
|
- ap->a_nvals,
|
|
- e->e_id, SLAP_INDEX_ADD_OP );
|
|
- }
|
|
- }
|
|
- if ( rc != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "%s: attribute \"%s\" index add failure\n",
|
|
- op->o_log_prefix, ap->a_desc->ad_cname.bv_val, 0 );
|
|
- attrs_free( e->e_attrs );
|
|
- e->e_attrs = save_attrs;
|
|
- return rc;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-
|
|
-int
|
|
-bdb_modify( Operation *op, SlapReply *rs )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- Entry *e = NULL;
|
|
- EntryInfo *ei = NULL;
|
|
- int manageDSAit = get_manageDSAit( op );
|
|
- char textbuf[SLAP_TEXT_BUFLEN];
|
|
- size_t textlen = sizeof textbuf;
|
|
- DB_TXN *ltid = NULL, *lt2;
|
|
- struct bdb_op_info opinfo = {{{ 0 }}};
|
|
- Entry dummy = {0};
|
|
-
|
|
- DB_LOCK lock;
|
|
-
|
|
- int num_retries = 0;
|
|
-
|
|
- LDAPControl **preread_ctrl = NULL;
|
|
- LDAPControl **postread_ctrl = NULL;
|
|
- LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
|
|
- int num_ctrls = 0;
|
|
-
|
|
- int rc;
|
|
-
|
|
-#ifdef LDAP_X_TXN
|
|
- int settle = 0;
|
|
-#endif
|
|
-
|
|
- Debug( LDAP_DEBUG_ARGS, LDAP_XSTRING(bdb_modify) ": %s\n",
|
|
- op->o_req_dn.bv_val, 0, 0 );
|
|
-
|
|
-#ifdef LDAP_X_TXN
|
|
- if( op->o_txnSpec ) {
|
|
- /* acquire connection lock */
|
|
- ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
|
|
- if( op->o_conn->c_txn == CONN_TXN_INACTIVE ) {
|
|
- rs->sr_text = "invalid transaction identifier";
|
|
- rs->sr_err = LDAP_X_TXN_ID_INVALID;
|
|
- goto txnReturn;
|
|
- } else if( op->o_conn->c_txn == CONN_TXN_SETTLE ) {
|
|
- settle=1;
|
|
- goto txnReturn;
|
|
- }
|
|
-
|
|
- if( op->o_conn->c_txn_backend == NULL ) {
|
|
- op->o_conn->c_txn_backend = op->o_bd;
|
|
-
|
|
- } else if( op->o_conn->c_txn_backend != op->o_bd ) {
|
|
- rs->sr_text = "transaction cannot span multiple database contexts";
|
|
- rs->sr_err = LDAP_AFFECTS_MULTIPLE_DSAS;
|
|
- goto txnReturn;
|
|
- }
|
|
-
|
|
- /* insert operation into transaction */
|
|
-
|
|
- rs->sr_text = "transaction specified";
|
|
- rs->sr_err = LDAP_X_TXN_SPECIFY_OKAY;
|
|
-
|
|
-txnReturn:
|
|
- /* release connection lock */
|
|
- ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
|
|
-
|
|
- if( !settle ) {
|
|
- send_ldap_result( op, rs );
|
|
- return rs->sr_err;
|
|
- }
|
|
- }
|
|
-#endif
|
|
-
|
|
- ctrls[num_ctrls] = NULL;
|
|
-
|
|
- /* Don't touch the opattrs, if this is a contextCSN update
|
|
- * initiated from updatedn */
|
|
- if ( !be_isupdate(op) || !op->orm_modlist || op->orm_modlist->sml_next ||
|
|
- op->orm_modlist->sml_desc != slap_schema.si_ad_contextCSN ) {
|
|
-
|
|
- slap_mods_opattrs( op, &op->orm_modlist, 1 );
|
|
- }
|
|
-
|
|
- if( 0 ) {
|
|
-retry: /* transaction retry */
|
|
- if ( dummy.e_attrs ) {
|
|
- attrs_free( dummy.e_attrs );
|
|
- dummy.e_attrs = NULL;
|
|
- }
|
|
- if( e != NULL ) {
|
|
- bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
|
|
- e = NULL;
|
|
- }
|
|
- Debug(LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_modify) ": retrying...\n", 0, 0, 0);
|
|
-
|
|
- rs->sr_err = TXN_ABORT( ltid );
|
|
- ltid = NULL;
|
|
- LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
|
|
- opinfo.boi_oe.oe_key = NULL;
|
|
- op->o_do_not_cache = opinfo.boi_acl_cache;
|
|
- if( rs->sr_err != 0 ) {
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "internal error";
|
|
- goto return_results;
|
|
- }
|
|
- if ( op->o_abandon ) {
|
|
- rs->sr_err = SLAPD_ABANDON;
|
|
- goto return_results;
|
|
- }
|
|
- bdb_trans_backoff( ++num_retries );
|
|
- }
|
|
-
|
|
- /* begin transaction */
|
|
- rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, NULL, <id,
|
|
- bdb->bi_db_opflags );
|
|
- rs->sr_text = NULL;
|
|
- if( rs->sr_err != 0 ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_modify) ": txn_begin failed: "
|
|
- "%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "internal error";
|
|
- goto return_results;
|
|
- }
|
|
- Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modify) ": txn1 id: %x\n",
|
|
- ltid->id(ltid), 0, 0 );
|
|
-
|
|
- opinfo.boi_oe.oe_key = bdb;
|
|
- opinfo.boi_txn = ltid;
|
|
- opinfo.boi_err = 0;
|
|
- opinfo.boi_acl_cache = op->o_do_not_cache;
|
|
- LDAP_SLIST_INSERT_HEAD( &op->o_extra, &opinfo.boi_oe, oe_next );
|
|
-
|
|
- /* get entry or ancestor */
|
|
- rs->sr_err = bdb_dn2entry( op, ltid, &op->o_req_ndn, &ei, 1,
|
|
- &lock );
|
|
-
|
|
- if ( rs->sr_err != 0 ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_modify) ": dn2entry failed (%d)\n",
|
|
- rs->sr_err, 0, 0 );
|
|
- switch( rs->sr_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- case DB_NOTFOUND:
|
|
- break;
|
|
- case LDAP_BUSY:
|
|
- rs->sr_text = "ldap server busy";
|
|
- goto return_results;
|
|
- default:
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "internal error";
|
|
- goto return_results;
|
|
- }
|
|
- }
|
|
-
|
|
- e = ei->bei_e;
|
|
-
|
|
- /* acquire and lock entry */
|
|
- /* FIXME: dn2entry() should return non-glue entry */
|
|
- if (( rs->sr_err == DB_NOTFOUND ) ||
|
|
- ( !manageDSAit && e && is_entry_glue( e )))
|
|
- {
|
|
- if ( e != NULL ) {
|
|
- rs->sr_matched = ch_strdup( e->e_dn );
|
|
- rs->sr_ref = is_entry_referral( e )
|
|
- ? get_entry_referrals( op, e )
|
|
- : NULL;
|
|
- bdb_unlocked_cache_return_entry_r (&bdb->bi_cache, e);
|
|
- e = NULL;
|
|
-
|
|
- } else {
|
|
- rs->sr_ref = referral_rewrite( default_referral, NULL,
|
|
- &op->o_req_dn, LDAP_SCOPE_DEFAULT );
|
|
- }
|
|
-
|
|
- rs->sr_err = LDAP_REFERRAL;
|
|
- send_ldap_result( op, rs );
|
|
-
|
|
- if ( rs->sr_ref != default_referral ) {
|
|
- ber_bvarray_free( rs->sr_ref );
|
|
- }
|
|
- free( (char *)rs->sr_matched );
|
|
- rs->sr_ref = NULL;
|
|
- rs->sr_matched = NULL;
|
|
-
|
|
- goto done;
|
|
- }
|
|
-
|
|
- if ( !manageDSAit && is_entry_referral( e ) ) {
|
|
- /* entry is a referral, don't allow modify */
|
|
- rs->sr_ref = get_entry_referrals( op, e );
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_modify) ": entry is referral\n",
|
|
- 0, 0, 0 );
|
|
-
|
|
- rs->sr_err = LDAP_REFERRAL;
|
|
- rs->sr_matched = e->e_name.bv_val;
|
|
- send_ldap_result( op, rs );
|
|
-
|
|
- ber_bvarray_free( rs->sr_ref );
|
|
- rs->sr_ref = NULL;
|
|
- rs->sr_matched = NULL;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- if ( get_assert( op ) &&
|
|
- ( test_filter( op, e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
|
|
- {
|
|
- rs->sr_err = LDAP_ASSERTION_FAILED;
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- if( op->o_preread ) {
|
|
- if( preread_ctrl == NULL ) {
|
|
- preread_ctrl = &ctrls[num_ctrls++];
|
|
- ctrls[num_ctrls] = NULL;
|
|
- }
|
|
- if ( slap_read_controls( op, rs, e,
|
|
- &slap_pre_read_bv, preread_ctrl ) )
|
|
- {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<=- " LDAP_XSTRING(bdb_modify) ": pre-read "
|
|
- "failed!\n", 0, 0, 0 );
|
|
- if ( op->o_preread & SLAP_CONTROL_CRITICAL ) {
|
|
- /* FIXME: is it correct to abort
|
|
- * operation if control fails? */
|
|
- goto return_results;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- /* nested transaction */
|
|
- rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, <2, bdb->bi_db_opflags );
|
|
- rs->sr_text = NULL;
|
|
- if( rs->sr_err != 0 ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_modify) ": txn_begin(2) failed: " "%s (%d)\n",
|
|
- db_strerror(rs->sr_err), rs->sr_err, 0 );
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "internal error";
|
|
- goto return_results;
|
|
- }
|
|
- Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modify) ": txn2 id: %x\n",
|
|
- lt2->id(lt2), 0, 0 );
|
|
- /* Modify the entry */
|
|
- dummy = *e;
|
|
- rs->sr_err = bdb_modify_internal( op, lt2, op->orm_modlist,
|
|
- &dummy, &rs->sr_text, textbuf, textlen );
|
|
-
|
|
- if( rs->sr_err != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_modify) ": modify failed (%d)\n",
|
|
- rs->sr_err, 0, 0 );
|
|
- if ( (rs->sr_err == LDAP_INSUFFICIENT_ACCESS) && opinfo.boi_err ) {
|
|
- rs->sr_err = opinfo.boi_err;
|
|
- }
|
|
- /* Only free attrs if they were dup'd. */
|
|
- if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL;
|
|
- switch( rs->sr_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- }
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- /* change the entry itself */
|
|
- rs->sr_err = bdb_id2entry_update( op->o_bd, lt2, &dummy );
|
|
- if ( rs->sr_err != 0 ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_modify) ": id2entry update failed " "(%d)\n",
|
|
- rs->sr_err, 0, 0 );
|
|
- switch( rs->sr_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- }
|
|
- rs->sr_text = "entry update failed";
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "txn_commit(2) failed";
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- if( op->o_postread ) {
|
|
- if( postread_ctrl == NULL ) {
|
|
- postread_ctrl = &ctrls[num_ctrls++];
|
|
- ctrls[num_ctrls] = NULL;
|
|
- }
|
|
- if( slap_read_controls( op, rs, &dummy,
|
|
- &slap_post_read_bv, postread_ctrl ) )
|
|
- {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<=- " LDAP_XSTRING(bdb_modify)
|
|
- ": post-read failed!\n", 0, 0, 0 );
|
|
- if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
|
|
- /* FIXME: is it correct to abort
|
|
- * operation if control fails? */
|
|
- goto return_results;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- if( op->o_noop ) {
|
|
- if ( ( rs->sr_err = TXN_ABORT( ltid ) ) != 0 ) {
|
|
- rs->sr_text = "txn_abort (no-op) failed";
|
|
- } else {
|
|
- rs->sr_err = LDAP_X_NO_OPERATION;
|
|
- ltid = NULL;
|
|
- /* Only free attrs if they were dup'd. */
|
|
- if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL;
|
|
- goto return_results;
|
|
- }
|
|
- } else {
|
|
- /* may have changed in bdb_modify_internal() */
|
|
- e->e_ocflags = dummy.e_ocflags;
|
|
- rc = bdb_cache_modify( bdb, e, dummy.e_attrs, ltid, &lock );
|
|
- switch( rc ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- }
|
|
- dummy.e_attrs = NULL;
|
|
-
|
|
- rs->sr_err = TXN_COMMIT( ltid, 0 );
|
|
- }
|
|
- ltid = NULL;
|
|
- LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
|
|
- opinfo.boi_oe.oe_key = NULL;
|
|
-
|
|
- if( rs->sr_err != 0 ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_modify) ": txn_%s failed: %s (%d)\n",
|
|
- op->o_noop ? "abort (no-op)" : "commit",
|
|
- db_strerror(rs->sr_err), rs->sr_err );
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "commit failed";
|
|
-
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_modify) ": updated%s id=%08lx dn=\"%s\"\n",
|
|
- op->o_noop ? " (no-op)" : "",
|
|
- dummy.e_id, op->o_req_dn.bv_val );
|
|
-
|
|
- rs->sr_err = LDAP_SUCCESS;
|
|
- rs->sr_text = NULL;
|
|
- if( num_ctrls ) rs->sr_ctrls = ctrls;
|
|
-
|
|
-return_results:
|
|
- if( dummy.e_attrs ) {
|
|
- attrs_free( dummy.e_attrs );
|
|
- }
|
|
- send_ldap_result( op, rs );
|
|
-
|
|
- if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp_kbyte ) {
|
|
- TXN_CHECKPOINT( bdb->bi_dbenv,
|
|
- bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
|
|
- }
|
|
-
|
|
-done:
|
|
- slap_graduate_commit_csn( op );
|
|
-
|
|
- if( ltid != NULL ) {
|
|
- TXN_ABORT( ltid );
|
|
- }
|
|
- if ( opinfo.boi_oe.oe_key ) {
|
|
- LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
|
|
- }
|
|
-
|
|
- if( e != NULL ) {
|
|
- bdb_unlocked_cache_return_entry_w (&bdb->bi_cache, e);
|
|
- }
|
|
-
|
|
- if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) {
|
|
- slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
|
|
- slap_sl_free( *preread_ctrl, op->o_tmpmemctx );
|
|
- }
|
|
- if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) {
|
|
- slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
|
|
- slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
|
|
- }
|
|
-
|
|
- rs->sr_text = NULL;
|
|
-
|
|
- return rs->sr_err;
|
|
-}
|
|
diff --git a/servers/slapd/back-bdb/modrdn.c b/servers/slapd/back-bdb/modrdn.c
|
|
deleted file mode 100644
|
|
index f213b0f..0000000
|
|
--- a/servers/slapd/back-bdb/modrdn.c
|
|
+++ /dev/null
|
|
@@ -1,842 +0,0 @@
|
|
-/* modrdn.c - bdb backend modrdn routine */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-
|
|
-#include <stdio.h>
|
|
-#include <ac/string.h>
|
|
-
|
|
-#include "back-bdb.h"
|
|
-
|
|
-int
|
|
-bdb_modrdn( Operation *op, SlapReply *rs )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- AttributeDescription *children = slap_schema.si_ad_children;
|
|
- AttributeDescription *entry = slap_schema.si_ad_entry;
|
|
- struct berval p_dn, p_ndn;
|
|
- struct berval new_dn = {0, NULL}, new_ndn = {0, NULL};
|
|
- Entry *e = NULL;
|
|
- Entry *p = NULL;
|
|
- EntryInfo *ei = NULL, *eip = NULL, *nei = NULL, *neip = NULL;
|
|
- /* LDAP v2 supporting correct attribute handling. */
|
|
- char textbuf[SLAP_TEXT_BUFLEN];
|
|
- size_t textlen = sizeof textbuf;
|
|
- DB_TXN *ltid = NULL, *lt2;
|
|
- struct bdb_op_info opinfo = {{{ 0 }}};
|
|
- Entry dummy = {0};
|
|
-
|
|
- Entry *np = NULL; /* newSuperior Entry */
|
|
- struct berval *np_dn = NULL; /* newSuperior dn */
|
|
- struct berval *np_ndn = NULL; /* newSuperior ndn */
|
|
- struct berval *new_parent_dn = NULL; /* np_dn, p_dn, or NULL */
|
|
-
|
|
- int manageDSAit = get_manageDSAit( op );
|
|
-
|
|
- DB_LOCK lock, plock, nplock;
|
|
-
|
|
- int num_retries = 0;
|
|
-
|
|
- LDAPControl **preread_ctrl = NULL;
|
|
- LDAPControl **postread_ctrl = NULL;
|
|
- LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
|
|
- int num_ctrls = 0;
|
|
-
|
|
- int rc;
|
|
-
|
|
- int parent_is_glue = 0;
|
|
- int parent_is_leaf = 0;
|
|
-
|
|
-#ifdef LDAP_X_TXN
|
|
- int settle = 0;
|
|
-#endif
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "==>" LDAP_XSTRING(bdb_modrdn) "(%s,%s,%s)\n",
|
|
- op->o_req_dn.bv_val,op->oq_modrdn.rs_newrdn.bv_val,
|
|
- op->oq_modrdn.rs_newSup ? op->oq_modrdn.rs_newSup->bv_val : "NULL" );
|
|
-
|
|
-#ifdef LDAP_X_TXN
|
|
- if( op->o_txnSpec ) {
|
|
- /* acquire connection lock */
|
|
- ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
|
|
- if( op->o_conn->c_txn == CONN_TXN_INACTIVE ) {
|
|
- rs->sr_text = "invalid transaction identifier";
|
|
- rs->sr_err = LDAP_X_TXN_ID_INVALID;
|
|
- goto txnReturn;
|
|
- } else if( op->o_conn->c_txn == CONN_TXN_SETTLE ) {
|
|
- settle=1;
|
|
- goto txnReturn;
|
|
- }
|
|
-
|
|
- if( op->o_conn->c_txn_backend == NULL ) {
|
|
- op->o_conn->c_txn_backend = op->o_bd;
|
|
-
|
|
- } else if( op->o_conn->c_txn_backend != op->o_bd ) {
|
|
- rs->sr_text = "transaction cannot span multiple database contexts";
|
|
- rs->sr_err = LDAP_AFFECTS_MULTIPLE_DSAS;
|
|
- goto txnReturn;
|
|
- }
|
|
-
|
|
- /* insert operation into transaction */
|
|
-
|
|
- rs->sr_text = "transaction specified";
|
|
- rs->sr_err = LDAP_X_TXN_SPECIFY_OKAY;
|
|
-
|
|
-txnReturn:
|
|
- /* release connection lock */
|
|
- ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
|
|
-
|
|
- if( !settle ) {
|
|
- send_ldap_result( op, rs );
|
|
- return rs->sr_err;
|
|
- }
|
|
- }
|
|
-#endif
|
|
-
|
|
- ctrls[num_ctrls] = NULL;
|
|
-
|
|
- slap_mods_opattrs( op, &op->orr_modlist, 1 );
|
|
-
|
|
- if( 0 ) {
|
|
-retry: /* transaction retry */
|
|
- if ( dummy.e_attrs ) {
|
|
- attrs_free( dummy.e_attrs );
|
|
- dummy.e_attrs = NULL;
|
|
- }
|
|
- if (e != NULL) {
|
|
- bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
|
|
- e = NULL;
|
|
- }
|
|
- if (p != NULL) {
|
|
- bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
|
|
- p = NULL;
|
|
- }
|
|
- if (np != NULL) {
|
|
- bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, np);
|
|
- np = NULL;
|
|
- }
|
|
- Debug( LDAP_DEBUG_TRACE, "==>" LDAP_XSTRING(bdb_modrdn)
|
|
- ": retrying...\n", 0, 0, 0 );
|
|
-
|
|
- rs->sr_err = TXN_ABORT( ltid );
|
|
- ltid = NULL;
|
|
- LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
|
|
- opinfo.boi_oe.oe_key = NULL;
|
|
- op->o_do_not_cache = opinfo.boi_acl_cache;
|
|
- if( rs->sr_err != 0 ) {
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "internal error";
|
|
- goto return_results;
|
|
- }
|
|
- if ( op->o_abandon ) {
|
|
- rs->sr_err = SLAPD_ABANDON;
|
|
- goto return_results;
|
|
- }
|
|
- parent_is_glue = 0;
|
|
- parent_is_leaf = 0;
|
|
- bdb_trans_backoff( ++num_retries );
|
|
- }
|
|
-
|
|
- /* begin transaction */
|
|
- rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, NULL, <id,
|
|
- bdb->bi_db_opflags );
|
|
- rs->sr_text = NULL;
|
|
- if( rs->sr_err != 0 ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_modrdn) ": txn_begin failed: "
|
|
- "%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "internal error";
|
|
- goto return_results;
|
|
- }
|
|
- Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn) ": txn1 id: %x\n",
|
|
- ltid->id(ltid), 0, 0 );
|
|
-
|
|
- opinfo.boi_oe.oe_key = bdb;
|
|
- opinfo.boi_txn = ltid;
|
|
- opinfo.boi_err = 0;
|
|
- opinfo.boi_acl_cache = op->o_do_not_cache;
|
|
- LDAP_SLIST_INSERT_HEAD( &op->o_extra, &opinfo.boi_oe, oe_next );
|
|
-
|
|
- /* get entry */
|
|
- rs->sr_err = bdb_dn2entry( op, ltid, &op->o_req_ndn, &ei, 1,
|
|
- &lock );
|
|
-
|
|
- switch( rs->sr_err ) {
|
|
- case 0:
|
|
- case DB_NOTFOUND:
|
|
- break;
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- case LDAP_BUSY:
|
|
- rs->sr_text = "ldap server busy";
|
|
- goto return_results;
|
|
- default:
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "internal error";
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- e = ei->bei_e;
|
|
- /* FIXME: dn2entry() should return non-glue entry */
|
|
- if (( rs->sr_err == DB_NOTFOUND ) ||
|
|
- ( !manageDSAit && e && is_entry_glue( e )))
|
|
- {
|
|
- if( e != NULL ) {
|
|
- rs->sr_matched = ch_strdup( e->e_dn );
|
|
- rs->sr_ref = is_entry_referral( e )
|
|
- ? get_entry_referrals( op, e )
|
|
- : NULL;
|
|
- bdb_unlocked_cache_return_entry_r( &bdb->bi_cache, e);
|
|
- e = NULL;
|
|
-
|
|
- } else {
|
|
- rs->sr_ref = referral_rewrite( default_referral, NULL,
|
|
- &op->o_req_dn, LDAP_SCOPE_DEFAULT );
|
|
- }
|
|
-
|
|
- rs->sr_err = LDAP_REFERRAL;
|
|
- send_ldap_result( op, rs );
|
|
-
|
|
- ber_bvarray_free( rs->sr_ref );
|
|
- free( (char *)rs->sr_matched );
|
|
- rs->sr_ref = NULL;
|
|
- rs->sr_matched = NULL;
|
|
-
|
|
- goto done;
|
|
- }
|
|
-
|
|
- if ( get_assert( op ) &&
|
|
- ( test_filter( op, e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
|
|
- {
|
|
- rs->sr_err = LDAP_ASSERTION_FAILED;
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- /* check write on old entry */
|
|
- rs->sr_err = access_allowed( op, e, entry, NULL, ACL_WRITE, NULL );
|
|
- if ( ! rs->sr_err ) {
|
|
- switch( opinfo.boi_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- }
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "no access to entry\n", 0,
|
|
- 0, 0 );
|
|
- rs->sr_text = "no write access to old entry";
|
|
- rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
-#ifndef BDB_HIER
|
|
- rs->sr_err = bdb_cache_children( op, ltid, e );
|
|
- if ( rs->sr_err != DB_NOTFOUND ) {
|
|
- switch( rs->sr_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- case 0:
|
|
- Debug(LDAP_DEBUG_ARGS,
|
|
- "<=- " LDAP_XSTRING(bdb_modrdn)
|
|
- ": non-leaf %s\n",
|
|
- op->o_req_dn.bv_val, 0, 0);
|
|
- rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
|
|
- rs->sr_text = "subtree rename not supported";
|
|
- break;
|
|
- default:
|
|
- Debug(LDAP_DEBUG_ARGS,
|
|
- "<=- " LDAP_XSTRING(bdb_modrdn)
|
|
- ": has_children failed: %s (%d)\n",
|
|
- db_strerror(rs->sr_err), rs->sr_err, 0 );
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "internal error";
|
|
- }
|
|
- goto return_results;
|
|
- }
|
|
- ei->bei_state |= CACHE_ENTRY_NO_KIDS;
|
|
-#endif
|
|
-
|
|
- if (!manageDSAit && is_entry_referral( e ) ) {
|
|
- /* parent is a referral, don't allow add */
|
|
- rs->sr_ref = get_entry_referrals( op, e );
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn)
|
|
- ": entry %s is referral\n", e->e_dn, 0, 0 );
|
|
-
|
|
- rs->sr_err = LDAP_REFERRAL,
|
|
- rs->sr_matched = e->e_name.bv_val;
|
|
- send_ldap_result( op, rs );
|
|
-
|
|
- ber_bvarray_free( rs->sr_ref );
|
|
- rs->sr_ref = NULL;
|
|
- rs->sr_matched = NULL;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- if ( be_issuffix( op->o_bd, &e->e_nname ) ) {
|
|
-#ifdef BDB_MULTIPLE_SUFFIXES
|
|
- /* Allow renaming one suffix entry to another */
|
|
- p_ndn = slap_empty_bv;
|
|
-#else
|
|
- /* There can only be one suffix entry */
|
|
- rs->sr_err = LDAP_NAMING_VIOLATION;
|
|
- rs->sr_text = "cannot rename suffix entry";
|
|
- goto return_results;
|
|
-#endif
|
|
- } else {
|
|
- dnParent( &e->e_nname, &p_ndn );
|
|
- }
|
|
- np_ndn = &p_ndn;
|
|
- eip = ei->bei_parent;
|
|
- if ( eip && eip->bei_id ) {
|
|
- /* Make sure parent entry exist and we can write its
|
|
- * children.
|
|
- */
|
|
- rs->sr_err = bdb_cache_find_id( op, ltid,
|
|
- eip->bei_id, &eip, 0, &plock );
|
|
-
|
|
- switch( rs->sr_err ) {
|
|
- case 0:
|
|
- case DB_NOTFOUND:
|
|
- break;
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- case LDAP_BUSY:
|
|
- rs->sr_text = "ldap server busy";
|
|
- goto return_results;
|
|
- default:
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "internal error";
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- p = eip->bei_e;
|
|
- if( p == NULL) {
|
|
- Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn)
|
|
- ": parent does not exist\n", 0, 0, 0);
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "old entry's parent does not exist";
|
|
- goto return_results;
|
|
- }
|
|
- } else {
|
|
- p = (Entry *)&slap_entry_root;
|
|
- }
|
|
-
|
|
- /* check parent for "children" acl */
|
|
- rs->sr_err = access_allowed( op, p,
|
|
- children, NULL,
|
|
- op->oq_modrdn.rs_newSup == NULL ?
|
|
- ACL_WRITE : ACL_WDEL,
|
|
- NULL );
|
|
-
|
|
- if ( !p_ndn.bv_len )
|
|
- p = NULL;
|
|
-
|
|
- if ( ! rs->sr_err ) {
|
|
- switch( opinfo.boi_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- }
|
|
-
|
|
- rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
|
- Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
|
|
- 0, 0 );
|
|
- rs->sr_text = "no write access to old parent's children";
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_modrdn) ": wr to children "
|
|
- "of entry %s OK\n", p_ndn.bv_val, 0, 0 );
|
|
-
|
|
- if ( p_ndn.bv_val == slap_empty_bv.bv_val ) {
|
|
- p_dn = slap_empty_bv;
|
|
- } else {
|
|
- dnParent( &e->e_name, &p_dn );
|
|
- }
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_modrdn) ": parent dn=%s\n",
|
|
- p_dn.bv_val, 0, 0 );
|
|
-
|
|
- new_parent_dn = &p_dn; /* New Parent unless newSuperior given */
|
|
-
|
|
- if ( op->oq_modrdn.rs_newSup != NULL ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_modrdn)
|
|
- ": new parent \"%s\" requested...\n",
|
|
- op->oq_modrdn.rs_newSup->bv_val, 0, 0 );
|
|
-
|
|
- /* newSuperior == oldParent? */
|
|
- if( dn_match( &p_ndn, op->oq_modrdn.rs_nnewSup ) ) {
|
|
- Debug( LDAP_DEBUG_TRACE, "bdb_back_modrdn: "
|
|
- "new parent \"%s\" same as the old parent \"%s\"\n",
|
|
- op->oq_modrdn.rs_newSup->bv_val, p_dn.bv_val, 0 );
|
|
- op->oq_modrdn.rs_newSup = NULL; /* ignore newSuperior */
|
|
- }
|
|
- }
|
|
-
|
|
- /* There's a BDB_MULTIPLE_SUFFIXES case here that this code doesn't
|
|
- * support. E.g., two suffixes dc=foo,dc=com and dc=bar,dc=net.
|
|
- * We do not allow modDN
|
|
- * dc=foo,dc=com
|
|
- * newrdn dc=bar
|
|
- * newsup dc=net
|
|
- * and we probably should. But since MULTIPLE_SUFFIXES is deprecated
|
|
- * I'm ignoring this problem for now.
|
|
- */
|
|
- if ( op->oq_modrdn.rs_newSup != NULL ) {
|
|
- if ( op->oq_modrdn.rs_newSup->bv_len ) {
|
|
- np_dn = op->oq_modrdn.rs_newSup;
|
|
- np_ndn = op->oq_modrdn.rs_nnewSup;
|
|
-
|
|
- /* newSuperior == oldParent? - checked above */
|
|
- /* newSuperior == entry being moved?, if so ==> ERROR */
|
|
- if ( dnIsSuffix( np_ndn, &e->e_nname )) {
|
|
- rs->sr_err = LDAP_NO_SUCH_OBJECT;
|
|
- rs->sr_text = "new superior not found";
|
|
- goto return_results;
|
|
- }
|
|
- /* Get Entry with dn=newSuperior. Does newSuperior exist? */
|
|
-
|
|
- rs->sr_err = bdb_dn2entry( op, ltid, np_ndn,
|
|
- &neip, 0, &nplock );
|
|
-
|
|
- switch( rs->sr_err ) {
|
|
- case 0: np = neip->bei_e;
|
|
- case DB_NOTFOUND:
|
|
- break;
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- case LDAP_BUSY:
|
|
- rs->sr_text = "ldap server busy";
|
|
- goto return_results;
|
|
- default:
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "internal error";
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- if( np == NULL) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_modrdn)
|
|
- ": newSup(ndn=%s) not here!\n",
|
|
- np_ndn->bv_val, 0, 0);
|
|
- rs->sr_text = "new superior not found";
|
|
- rs->sr_err = LDAP_NO_SUCH_OBJECT;
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_modrdn)
|
|
- ": wr to new parent OK np=%p, id=%ld\n",
|
|
- (void *) np, (long) np->e_id, 0 );
|
|
-
|
|
- /* check newSuperior for "children" acl */
|
|
- rs->sr_err = access_allowed( op, np, children,
|
|
- NULL, ACL_WADD, NULL );
|
|
-
|
|
- if( ! rs->sr_err ) {
|
|
- switch( opinfo.boi_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- }
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_modrdn)
|
|
- ": no wr to newSup children\n",
|
|
- 0, 0, 0 );
|
|
- rs->sr_text = "no write access to new superior's children";
|
|
- rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- if ( is_entry_alias( np ) ) {
|
|
- /* parent is an alias, don't allow add */
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_modrdn)
|
|
- ": entry is alias\n",
|
|
- 0, 0, 0 );
|
|
- rs->sr_text = "new superior is an alias";
|
|
- rs->sr_err = LDAP_ALIAS_PROBLEM;
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- if ( is_entry_referral( np ) ) {
|
|
- /* parent is a referral, don't allow add */
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_modrdn)
|
|
- ": entry is referral\n",
|
|
- 0, 0, 0 );
|
|
- rs->sr_text = "new superior is a referral";
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- } else {
|
|
- np_dn = NULL;
|
|
-
|
|
- /* no parent, modrdn entry directly under root */
|
|
- if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv )
|
|
- || be_isupdate( op ) ) {
|
|
- np = (Entry *)&slap_entry_root;
|
|
-
|
|
- /* check parent for "children" acl */
|
|
- rs->sr_err = access_allowed( op, np,
|
|
- children, NULL, ACL_WADD, NULL );
|
|
-
|
|
- np = NULL;
|
|
-
|
|
- if ( ! rs->sr_err ) {
|
|
- switch( opinfo.boi_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- }
|
|
-
|
|
- rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "no access to new superior\n",
|
|
- 0, 0, 0 );
|
|
- rs->sr_text =
|
|
- "no write access to new superior's children";
|
|
- goto return_results;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_modrdn)
|
|
- ": wr to new parent's children OK\n",
|
|
- 0, 0, 0 );
|
|
-
|
|
- new_parent_dn = np_dn;
|
|
- }
|
|
-
|
|
- /* Build target dn and make sure target entry doesn't exist already. */
|
|
- if (!new_dn.bv_val) {
|
|
- build_new_dn( &new_dn, new_parent_dn, &op->oq_modrdn.rs_newrdn, NULL );
|
|
- }
|
|
-
|
|
- if (!new_ndn.bv_val) {
|
|
- struct berval bv = {0, NULL};
|
|
- dnNormalize( 0, NULL, NULL, &new_dn, &bv, op->o_tmpmemctx );
|
|
- ber_dupbv( &new_ndn, &bv );
|
|
- /* FIXME: why not call dnNormalize() w/o ctx? */
|
|
- op->o_tmpfree( bv.bv_val, op->o_tmpmemctx );
|
|
- }
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn) ": new ndn=%s\n",
|
|
- new_ndn.bv_val, 0, 0 );
|
|
-
|
|
- /* Shortcut the search */
|
|
- nei = neip ? neip : eip;
|
|
- rs->sr_err = bdb_cache_find_ndn ( op, ltid, &new_ndn, &nei );
|
|
- if ( nei ) bdb_cache_entryinfo_unlock( nei );
|
|
- switch( rs->sr_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- case DB_NOTFOUND:
|
|
- break;
|
|
- case 0:
|
|
- /* Allow rename to same DN */
|
|
- if ( nei == ei )
|
|
- break;
|
|
- rs->sr_err = LDAP_ALREADY_EXISTS;
|
|
- goto return_results;
|
|
- default:
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "internal error";
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- assert( op->orr_modlist != NULL );
|
|
-
|
|
- if( op->o_preread ) {
|
|
- if( preread_ctrl == NULL ) {
|
|
- preread_ctrl = &ctrls[num_ctrls++];
|
|
- ctrls[num_ctrls] = NULL;
|
|
- }
|
|
- if( slap_read_controls( op, rs, e,
|
|
- &slap_pre_read_bv, preread_ctrl ) )
|
|
- {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<=- " LDAP_XSTRING(bdb_modrdn)
|
|
- ": pre-read failed!\n", 0, 0, 0 );
|
|
- if ( op->o_preread & SLAP_CONTROL_CRITICAL ) {
|
|
- /* FIXME: is it correct to abort
|
|
- * operation if control fails? */
|
|
- goto return_results;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- /* nested transaction */
|
|
- rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, <2, bdb->bi_db_opflags );
|
|
- rs->sr_text = NULL;
|
|
- if( rs->sr_err != 0 ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_modrdn)
|
|
- ": txn_begin(2) failed: %s (%d)\n",
|
|
- db_strerror(rs->sr_err), rs->sr_err, 0 );
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "internal error";
|
|
- goto return_results;
|
|
- }
|
|
- Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn) ": txn2 id: %x\n",
|
|
- lt2->id(lt2), 0, 0 );
|
|
-
|
|
- /* delete old DN */
|
|
- rs->sr_err = bdb_dn2id_delete( op, lt2, eip, e );
|
|
- if ( rs->sr_err != 0 ) {
|
|
- Debug(LDAP_DEBUG_TRACE,
|
|
- "<=- " LDAP_XSTRING(bdb_modrdn)
|
|
- ": dn2id del failed: %s (%d)\n",
|
|
- db_strerror(rs->sr_err), rs->sr_err, 0 );
|
|
- switch( rs->sr_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- }
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "DN index delete fail";
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- /* copy the entry, then override some fields */
|
|
- dummy = *e;
|
|
- dummy.e_name = new_dn;
|
|
- dummy.e_nname = new_ndn;
|
|
- dummy.e_attrs = NULL;
|
|
-
|
|
- /* add new DN */
|
|
- rs->sr_err = bdb_dn2id_add( op, lt2, neip ? neip : eip, &dummy );
|
|
- if ( rs->sr_err != 0 ) {
|
|
- Debug(LDAP_DEBUG_TRACE,
|
|
- "<=- " LDAP_XSTRING(bdb_modrdn)
|
|
- ": dn2id add failed: %s (%d)\n",
|
|
- db_strerror(rs->sr_err), rs->sr_err, 0 );
|
|
- switch( rs->sr_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- }
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "DN index add failed";
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- dummy.e_attrs = e->e_attrs;
|
|
-
|
|
- /* modify entry */
|
|
- rs->sr_err = bdb_modify_internal( op, lt2, op->orr_modlist, &dummy,
|
|
- &rs->sr_text, textbuf, textlen );
|
|
- if( rs->sr_err != LDAP_SUCCESS ) {
|
|
- Debug(LDAP_DEBUG_TRACE,
|
|
- "<=- " LDAP_XSTRING(bdb_modrdn)
|
|
- ": modify failed: %s (%d)\n",
|
|
- db_strerror(rs->sr_err), rs->sr_err, 0 );
|
|
- if ( ( rs->sr_err == LDAP_INSUFFICIENT_ACCESS ) && opinfo.boi_err ) {
|
|
- rs->sr_err = opinfo.boi_err;
|
|
- }
|
|
- if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL;
|
|
- switch( rs->sr_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- }
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- /* id2entry index */
|
|
- rs->sr_err = bdb_id2entry_update( op->o_bd, lt2, &dummy );
|
|
- if ( rs->sr_err != 0 ) {
|
|
- Debug(LDAP_DEBUG_TRACE,
|
|
- "<=- " LDAP_XSTRING(bdb_modrdn)
|
|
- ": id2entry failed: %s (%d)\n",
|
|
- db_strerror(rs->sr_err), rs->sr_err, 0 );
|
|
- switch( rs->sr_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- }
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "entry update failed";
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- if ( p_ndn.bv_len != 0 ) {
|
|
- parent_is_glue = is_entry_glue(p);
|
|
- rs->sr_err = bdb_cache_children( op, lt2, p );
|
|
- if ( rs->sr_err != DB_NOTFOUND ) {
|
|
- switch( rs->sr_err ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- case 0:
|
|
- break;
|
|
- default:
|
|
- Debug(LDAP_DEBUG_ARGS,
|
|
- "<=- " LDAP_XSTRING(bdb_modrdn)
|
|
- ": has_children failed: %s (%d)\n",
|
|
- db_strerror(rs->sr_err), rs->sr_err, 0 );
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "internal error";
|
|
- goto return_results;
|
|
- }
|
|
- parent_is_leaf = 1;
|
|
- }
|
|
- bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
|
|
- p = NULL;
|
|
- }
|
|
-
|
|
- if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "txn_commit(2) failed";
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- if( op->o_postread ) {
|
|
- if( postread_ctrl == NULL ) {
|
|
- postread_ctrl = &ctrls[num_ctrls++];
|
|
- ctrls[num_ctrls] = NULL;
|
|
- }
|
|
- if( slap_read_controls( op, rs, &dummy,
|
|
- &slap_post_read_bv, postread_ctrl ) )
|
|
- {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "<=- " LDAP_XSTRING(bdb_modrdn)
|
|
- ": post-read failed!\n", 0, 0, 0 );
|
|
- if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
|
|
- /* FIXME: is it correct to abort
|
|
- * operation if control fails? */
|
|
- goto return_results;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- if( op->o_noop ) {
|
|
- if(( rs->sr_err=TXN_ABORT( ltid )) != 0 ) {
|
|
- rs->sr_text = "txn_abort (no-op) failed";
|
|
- } else {
|
|
- rs->sr_err = LDAP_X_NO_OPERATION;
|
|
- ltid = NULL;
|
|
- /* Only free attrs if they were dup'd. */
|
|
- if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL;
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- } else {
|
|
- rc = bdb_cache_modrdn( bdb, e, &op->orr_nnewrdn, &dummy, neip,
|
|
- ltid, &lock );
|
|
- switch( rc ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
- }
|
|
- dummy.e_attrs = NULL;
|
|
- new_dn.bv_val = NULL;
|
|
- new_ndn.bv_val = NULL;
|
|
-
|
|
- if(( rs->sr_err=TXN_COMMIT( ltid, 0 )) != 0 ) {
|
|
- rs->sr_text = "txn_commit failed";
|
|
- } else {
|
|
- rs->sr_err = LDAP_SUCCESS;
|
|
- }
|
|
- }
|
|
-
|
|
- ltid = NULL;
|
|
- LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
|
|
- opinfo.boi_oe.oe_key = NULL;
|
|
-
|
|
- if( rs->sr_err != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_modrdn) ": %s : %s (%d)\n",
|
|
- rs->sr_text, db_strerror(rs->sr_err), rs->sr_err );
|
|
- rs->sr_err = LDAP_OTHER;
|
|
-
|
|
- goto return_results;
|
|
- }
|
|
-
|
|
- Debug(LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_modrdn)
|
|
- ": rdn modified%s id=%08lx dn=\"%s\"\n",
|
|
- op->o_noop ? " (no-op)" : "",
|
|
- dummy.e_id, op->o_req_dn.bv_val );
|
|
- rs->sr_text = NULL;
|
|
- if( num_ctrls ) rs->sr_ctrls = ctrls;
|
|
-
|
|
-return_results:
|
|
- if ( dummy.e_attrs ) {
|
|
- attrs_free( dummy.e_attrs );
|
|
- }
|
|
- send_ldap_result( op, rs );
|
|
-
|
|
- if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp_kbyte ) {
|
|
- TXN_CHECKPOINT( bdb->bi_dbenv,
|
|
- bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
|
|
- }
|
|
-
|
|
- if ( rs->sr_err == LDAP_SUCCESS && parent_is_glue && parent_is_leaf ) {
|
|
- op->o_delete_glue_parent = 1;
|
|
- }
|
|
-
|
|
-done:
|
|
- slap_graduate_commit_csn( op );
|
|
-
|
|
- if( new_dn.bv_val != NULL ) free( new_dn.bv_val );
|
|
- if( new_ndn.bv_val != NULL ) free( new_ndn.bv_val );
|
|
-
|
|
- /* LDAP v3 Support */
|
|
- if( np != NULL ) {
|
|
- /* free new parent and reader lock */
|
|
- bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, np);
|
|
- }
|
|
-
|
|
- if( p != NULL ) {
|
|
- /* free parent and reader lock */
|
|
- bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
|
|
- }
|
|
-
|
|
- /* free entry */
|
|
- if( e != NULL ) {
|
|
- bdb_unlocked_cache_return_entry_w( &bdb->bi_cache, e);
|
|
- }
|
|
-
|
|
- if( ltid != NULL ) {
|
|
- TXN_ABORT( ltid );
|
|
- }
|
|
- if ( opinfo.boi_oe.oe_key ) {
|
|
- LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
|
|
- }
|
|
-
|
|
- if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) {
|
|
- slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
|
|
- slap_sl_free( *preread_ctrl, op->o_tmpmemctx );
|
|
- }
|
|
- if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) {
|
|
- slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
|
|
- slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
|
|
- }
|
|
- return rs->sr_err;
|
|
-}
|
|
diff --git a/servers/slapd/back-bdb/monitor.c b/servers/slapd/back-bdb/monitor.c
|
|
deleted file mode 100644
|
|
index 4afaf9d..0000000
|
|
--- a/servers/slapd/back-bdb/monitor.c
|
|
+++ /dev/null
|
|
@@ -1,724 +0,0 @@
|
|
-/* monitor.c - monitor bdb backend */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-
|
|
-#include <stdio.h>
|
|
-#include <ac/string.h>
|
|
-#include <ac/unistd.h>
|
|
-#include <ac/stdlib.h>
|
|
-#include <ac/errno.h>
|
|
-#include <sys/stat.h>
|
|
-#include "lutil.h"
|
|
-#include "back-bdb.h"
|
|
-
|
|
-#include "../back-monitor/back-monitor.h"
|
|
-
|
|
-#include "config.h"
|
|
-
|
|
-static ObjectClass *oc_olmBDBDatabase;
|
|
-
|
|
-static AttributeDescription *ad_olmBDBEntryCache,
|
|
- *ad_olmBDBDNCache, *ad_olmBDBIDLCache,
|
|
- *ad_olmDbDirectory;
|
|
-
|
|
-#ifdef BDB_MONITOR_IDX
|
|
-static int
|
|
-bdb_monitor_idx_entry_add(
|
|
- struct bdb_info *bdb,
|
|
- Entry *e );
|
|
-
|
|
-static AttributeDescription *ad_olmDbNotIndexed;
|
|
-#endif /* BDB_MONITOR_IDX */
|
|
-
|
|
-/*
|
|
- * NOTE: there's some confusion in monitor OID arc;
|
|
- * by now, let's consider:
|
|
- *
|
|
- * Subsystems monitor attributes 1.3.6.1.4.1.4203.666.1.55.0
|
|
- * Databases monitor attributes 1.3.6.1.4.1.4203.666.1.55.0.1
|
|
- * BDB database monitor attributes 1.3.6.1.4.1.4203.666.1.55.0.1.1
|
|
- *
|
|
- * Subsystems monitor objectclasses 1.3.6.1.4.1.4203.666.3.16.0
|
|
- * Databases monitor objectclasses 1.3.6.1.4.1.4203.666.3.16.0.1
|
|
- * BDB database monitor objectclasses 1.3.6.1.4.1.4203.666.3.16.0.1.1
|
|
- */
|
|
-
|
|
-static struct {
|
|
- char *name;
|
|
- char *oid;
|
|
-} s_oid[] = {
|
|
- { "olmBDBAttributes", "olmDatabaseAttributes:1" },
|
|
- { "olmBDBObjectClasses", "olmDatabaseObjectClasses:1" },
|
|
-
|
|
- { NULL }
|
|
-};
|
|
-
|
|
-static struct {
|
|
- char *desc;
|
|
- AttributeDescription **ad;
|
|
-} s_at[] = {
|
|
- { "( olmBDBAttributes:1 "
|
|
- "NAME ( 'olmBDBEntryCache' ) "
|
|
- "DESC 'Number of items in Entry Cache' "
|
|
- "SUP monitorCounter "
|
|
- "NO-USER-MODIFICATION "
|
|
- "USAGE dSAOperation )",
|
|
- &ad_olmBDBEntryCache },
|
|
-
|
|
- { "( olmBDBAttributes:2 "
|
|
- "NAME ( 'olmBDBDNCache' ) "
|
|
- "DESC 'Number of items in DN Cache' "
|
|
- "SUP monitorCounter "
|
|
- "NO-USER-MODIFICATION "
|
|
- "USAGE dSAOperation )",
|
|
- &ad_olmBDBDNCache },
|
|
-
|
|
- { "( olmBDBAttributes:3 "
|
|
- "NAME ( 'olmBDBIDLCache' ) "
|
|
- "DESC 'Number of items in IDL Cache' "
|
|
- "SUP monitorCounter "
|
|
- "NO-USER-MODIFICATION "
|
|
- "USAGE dSAOperation )",
|
|
- &ad_olmBDBIDLCache },
|
|
-
|
|
- { "( olmDatabaseAttributes:1 "
|
|
- "NAME ( 'olmDbDirectory' ) "
|
|
- "DESC 'Path name of the directory "
|
|
- "where the database environment resides' "
|
|
- "SUP monitoredInfo "
|
|
- "NO-USER-MODIFICATION "
|
|
- "USAGE dSAOperation )",
|
|
- &ad_olmDbDirectory },
|
|
-
|
|
-#ifdef BDB_MONITOR_IDX
|
|
- { "( olmDatabaseAttributes:2 "
|
|
- "NAME ( 'olmDbNotIndexed' ) "
|
|
- "DESC 'Missing indexes resulting from candidate selection' "
|
|
- "SUP monitoredInfo "
|
|
- "NO-USER-MODIFICATION "
|
|
- "USAGE dSAOperation )",
|
|
- &ad_olmDbNotIndexed },
|
|
-#endif /* BDB_MONITOR_IDX */
|
|
-
|
|
- { NULL }
|
|
-};
|
|
-
|
|
-static struct {
|
|
- char *desc;
|
|
- ObjectClass **oc;
|
|
-} s_oc[] = {
|
|
- /* augments an existing object, so it must be AUXILIARY
|
|
- * FIXME: derive from some ABSTRACT "monitoredEntity"? */
|
|
- { "( olmBDBObjectClasses:1 "
|
|
- "NAME ( 'olmBDBDatabase' ) "
|
|
- "SUP top AUXILIARY "
|
|
- "MAY ( "
|
|
- "olmBDBEntryCache "
|
|
- "$ olmBDBDNCache "
|
|
- "$ olmBDBIDLCache "
|
|
- "$ olmDbDirectory "
|
|
-#ifdef BDB_MONITOR_IDX
|
|
- "$ olmDbNotIndexed "
|
|
-#endif /* BDB_MONITOR_IDX */
|
|
- ") )",
|
|
- &oc_olmBDBDatabase },
|
|
-
|
|
- { NULL }
|
|
-};
|
|
-
|
|
-static int
|
|
-bdb_monitor_update(
|
|
- Operation *op,
|
|
- SlapReply *rs,
|
|
- Entry *e,
|
|
- void *priv )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) priv;
|
|
- Attribute *a;
|
|
-
|
|
- char buf[ BUFSIZ ];
|
|
- struct berval bv;
|
|
-
|
|
- assert( ad_olmBDBEntryCache != NULL );
|
|
-
|
|
- a = attr_find( e->e_attrs, ad_olmBDBEntryCache );
|
|
- assert( a != NULL );
|
|
- bv.bv_val = buf;
|
|
- bv.bv_len = snprintf( buf, sizeof( buf ), "%lu", bdb->bi_cache.c_cursize );
|
|
- ber_bvreplace( &a->a_vals[ 0 ], &bv );
|
|
-
|
|
- a = attr_find( e->e_attrs, ad_olmBDBDNCache );
|
|
- assert( a != NULL );
|
|
- bv.bv_len = snprintf( buf, sizeof( buf ), "%lu", bdb->bi_cache.c_eiused );
|
|
- ber_bvreplace( &a->a_vals[ 0 ], &bv );
|
|
-
|
|
- a = attr_find( e->e_attrs, ad_olmBDBIDLCache );
|
|
- assert( a != NULL );
|
|
- bv.bv_len = snprintf( buf, sizeof( buf ), "%lu", bdb->bi_idl_cache_size );
|
|
- ber_bvreplace( &a->a_vals[ 0 ], &bv );
|
|
-
|
|
-#ifdef BDB_MONITOR_IDX
|
|
- bdb_monitor_idx_entry_add( bdb, e );
|
|
-#endif /* BDB_MONITOR_IDX */
|
|
-
|
|
- return SLAP_CB_CONTINUE;
|
|
-}
|
|
-
|
|
-#if 0 /* uncomment if required */
|
|
-static int
|
|
-bdb_monitor_modify(
|
|
- Operation *op,
|
|
- SlapReply *rs,
|
|
- Entry *e,
|
|
- void *priv )
|
|
-{
|
|
- return SLAP_CB_CONTINUE;
|
|
-}
|
|
-#endif
|
|
-
|
|
-static int
|
|
-bdb_monitor_free(
|
|
- Entry *e,
|
|
- void **priv )
|
|
-{
|
|
- struct berval values[ 2 ];
|
|
- Modification mod = { 0 };
|
|
-
|
|
- const char *text;
|
|
- char textbuf[ SLAP_TEXT_BUFLEN ];
|
|
-
|
|
- int i, rc;
|
|
-
|
|
- /* NOTE: if slap_shutdown != 0, priv might have already been freed */
|
|
- *priv = NULL;
|
|
-
|
|
- /* Remove objectClass */
|
|
- mod.sm_op = LDAP_MOD_DELETE;
|
|
- mod.sm_desc = slap_schema.si_ad_objectClass;
|
|
- mod.sm_values = values;
|
|
- mod.sm_numvals = 1;
|
|
- values[ 0 ] = oc_olmBDBDatabase->soc_cname;
|
|
- BER_BVZERO( &values[ 1 ] );
|
|
-
|
|
- rc = modify_delete_values( e, &mod, 1, &text,
|
|
- textbuf, sizeof( textbuf ) );
|
|
- /* don't care too much about return code... */
|
|
-
|
|
- /* remove attrs */
|
|
- mod.sm_values = NULL;
|
|
- mod.sm_numvals = 0;
|
|
- for ( i = 0; s_at[ i ].desc != NULL; i++ ) {
|
|
- mod.sm_desc = *s_at[ i ].ad;
|
|
- rc = modify_delete_values( e, &mod, 1, &text,
|
|
- textbuf, sizeof( textbuf ) );
|
|
- /* don't care too much about return code... */
|
|
- }
|
|
-
|
|
- return SLAP_CB_CONTINUE;
|
|
-}
|
|
-
|
|
-#define bdb_monitor_initialize BDB_SYMBOL(monitor_initialize)
|
|
-
|
|
-/*
|
|
- * call from within bdb_initialize()
|
|
- */
|
|
-static int
|
|
-bdb_monitor_initialize( void )
|
|
-{
|
|
- int i, code;
|
|
- ConfigArgs c;
|
|
- char *argv[ 3 ];
|
|
-
|
|
- static int bdb_monitor_initialized = 0;
|
|
-
|
|
- /* set to 0 when successfully initialized; otherwise, remember failure */
|
|
- static int bdb_monitor_initialized_failure = 1;
|
|
-
|
|
- if ( bdb_monitor_initialized++ ) {
|
|
- return bdb_monitor_initialized_failure;
|
|
- }
|
|
-
|
|
- if ( backend_info( "monitor" ) == NULL ) {
|
|
- return -1;
|
|
- }
|
|
-
|
|
- /* register schema here */
|
|
-
|
|
- argv[ 0 ] = "back-bdb/back-hdb monitor";
|
|
- c.argv = argv;
|
|
- c.argc = 3;
|
|
- c.fname = argv[0];
|
|
-
|
|
- for ( i = 0; s_oid[ i ].name; i++ ) {
|
|
- c.lineno = i;
|
|
- argv[ 1 ] = s_oid[ i ].name;
|
|
- argv[ 2 ] = s_oid[ i ].oid;
|
|
-
|
|
- if ( parse_oidm( &c, 0, NULL ) != 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_monitor_initialize)
|
|
- ": unable to add "
|
|
- "objectIdentifier \"%s=%s\"\n",
|
|
- s_oid[ i ].name, s_oid[ i ].oid, 0 );
|
|
- return 2;
|
|
- }
|
|
- }
|
|
-
|
|
- for ( i = 0; s_at[ i ].desc != NULL; i++ ) {
|
|
- code = register_at( s_at[ i ].desc, s_at[ i ].ad, 1 );
|
|
- if ( code != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_monitor_initialize)
|
|
- ": register_at failed for attributeType (%s)\n",
|
|
- s_at[ i ].desc, 0, 0 );
|
|
- return 3;
|
|
-
|
|
- } else {
|
|
- (*s_at[ i ].ad)->ad_type->sat_flags |= SLAP_AT_HIDE;
|
|
- }
|
|
- }
|
|
-
|
|
- for ( i = 0; s_oc[ i ].desc != NULL; i++ ) {
|
|
- code = register_oc( s_oc[ i ].desc, s_oc[ i ].oc, 1 );
|
|
- if ( code != LDAP_SUCCESS ) {
|
|
- Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_monitor_initialize)
|
|
- ": register_oc failed for objectClass (%s)\n",
|
|
- s_oc[ i ].desc, 0, 0 );
|
|
- return 4;
|
|
-
|
|
- } else {
|
|
- (*s_oc[ i ].oc)->soc_flags |= SLAP_OC_HIDE;
|
|
- }
|
|
- }
|
|
-
|
|
- return ( bdb_monitor_initialized_failure = LDAP_SUCCESS );
|
|
-}
|
|
-
|
|
-/*
|
|
- * call from within bdb_db_init()
|
|
- */
|
|
-int
|
|
-bdb_monitor_db_init( BackendDB *be )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
|
-
|
|
- if ( bdb_monitor_initialize() == LDAP_SUCCESS ) {
|
|
- /* monitoring in back-bdb is on by default */
|
|
- SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_MONITORING;
|
|
- }
|
|
-
|
|
-#ifdef BDB_MONITOR_IDX
|
|
- bdb->bi_idx = NULL;
|
|
- ldap_pvt_thread_mutex_init( &bdb->bi_idx_mutex );
|
|
-#endif /* BDB_MONITOR_IDX */
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/*
|
|
- * call from within bdb_db_open()
|
|
- */
|
|
-int
|
|
-bdb_monitor_db_open( BackendDB *be )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
|
- Attribute *a, *next;
|
|
- monitor_callback_t *cb = NULL;
|
|
- int rc = 0;
|
|
- BackendInfo *mi;
|
|
- monitor_extra_t *mbe;
|
|
-
|
|
- if ( !SLAP_DBMONITORING( be ) ) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- mi = backend_info( "monitor" );
|
|
- if ( !mi || !mi->bi_extra ) {
|
|
- SLAP_DBFLAGS( be ) ^= SLAP_DBFLAG_MONITORING;
|
|
- return 0;
|
|
- }
|
|
- mbe = mi->bi_extra;
|
|
-
|
|
- /* don't bother if monitor is not configured */
|
|
- if ( !mbe->is_configured() ) {
|
|
- static int warning = 0;
|
|
-
|
|
- if ( warning++ == 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_monitor_db_open)
|
|
- ": monitoring disabled; "
|
|
- "configure monitor database to enable\n",
|
|
- 0, 0, 0 );
|
|
- }
|
|
-
|
|
- return 0;
|
|
- }
|
|
-
|
|
- /* alloc as many as required (plus 1 for objectClass) */
|
|
- a = attrs_alloc( 1 + 4 );
|
|
- if ( a == NULL ) {
|
|
- rc = 1;
|
|
- goto cleanup;
|
|
- }
|
|
-
|
|
- a->a_desc = slap_schema.si_ad_objectClass;
|
|
- attr_valadd( a, &oc_olmBDBDatabase->soc_cname, NULL, 1 );
|
|
- next = a->a_next;
|
|
-
|
|
- {
|
|
- struct berval bv = BER_BVC( "0" );
|
|
-
|
|
- next->a_desc = ad_olmBDBEntryCache;
|
|
- attr_valadd( next, &bv, NULL, 1 );
|
|
- next = next->a_next;
|
|
-
|
|
- next->a_desc = ad_olmBDBDNCache;
|
|
- attr_valadd( next, &bv, NULL, 1 );
|
|
- next = next->a_next;
|
|
-
|
|
- next->a_desc = ad_olmBDBIDLCache;
|
|
- attr_valadd( next, &bv, NULL, 1 );
|
|
- next = next->a_next;
|
|
- }
|
|
-
|
|
- {
|
|
- struct berval bv, nbv;
|
|
- ber_len_t pathlen = 0, len = 0;
|
|
- char path[ MAXPATHLEN ] = { '\0' };
|
|
- char *fname = bdb->bi_dbenv_home,
|
|
- *ptr;
|
|
-
|
|
- len = strlen( fname );
|
|
- if ( fname[ 0 ] != '/' ) {
|
|
- /* get full path name */
|
|
- getcwd( path, sizeof( path ) );
|
|
- pathlen = strlen( path );
|
|
-
|
|
- if ( fname[ 0 ] == '.' && fname[ 1 ] == '/' ) {
|
|
- fname += 2;
|
|
- len -= 2;
|
|
- }
|
|
- }
|
|
-
|
|
- bv.bv_len = pathlen + STRLENOF( "/" ) + len;
|
|
- ptr = bv.bv_val = ch_malloc( bv.bv_len + STRLENOF( "/" ) + 1 );
|
|
- if ( pathlen ) {
|
|
- ptr = lutil_strncopy( ptr, path, pathlen );
|
|
- ptr[ 0 ] = '/';
|
|
- ptr++;
|
|
- }
|
|
- ptr = lutil_strncopy( ptr, fname, len );
|
|
- if ( ptr[ -1 ] != '/' ) {
|
|
- ptr[ 0 ] = '/';
|
|
- ptr++;
|
|
- }
|
|
- ptr[ 0 ] = '\0';
|
|
-
|
|
- attr_normalize_one( ad_olmDbDirectory, &bv, &nbv, NULL );
|
|
-
|
|
- next->a_desc = ad_olmDbDirectory;
|
|
- next->a_vals = ch_calloc( sizeof( struct berval ), 2 );
|
|
- next->a_vals[ 0 ] = bv;
|
|
- next->a_numvals = 1;
|
|
-
|
|
- if ( BER_BVISNULL( &nbv ) ) {
|
|
- next->a_nvals = next->a_vals;
|
|
-
|
|
- } else {
|
|
- next->a_nvals = ch_calloc( sizeof( struct berval ), 2 );
|
|
- next->a_nvals[ 0 ] = nbv;
|
|
- }
|
|
-
|
|
- next = next->a_next;
|
|
- }
|
|
-
|
|
- cb = ch_calloc( sizeof( monitor_callback_t ), 1 );
|
|
- cb->mc_update = bdb_monitor_update;
|
|
-#if 0 /* uncomment if required */
|
|
- cb->mc_modify = bdb_monitor_modify;
|
|
-#endif
|
|
- cb->mc_free = bdb_monitor_free;
|
|
- cb->mc_private = (void *)bdb;
|
|
-
|
|
- /* make sure the database is registered; then add monitor attributes */
|
|
- rc = mbe->register_database( be, &bdb->bi_monitor.bdm_ndn );
|
|
- if ( rc == 0 ) {
|
|
- rc = mbe->register_entry_attrs( &bdb->bi_monitor.bdm_ndn, a, cb,
|
|
- NULL, 0, NULL );
|
|
- }
|
|
-
|
|
-cleanup:;
|
|
- if ( rc != 0 ) {
|
|
- if ( cb != NULL ) {
|
|
- ch_free( cb );
|
|
- cb = NULL;
|
|
- }
|
|
-
|
|
- if ( a != NULL ) {
|
|
- attrs_free( a );
|
|
- a = NULL;
|
|
- }
|
|
- }
|
|
-
|
|
- /* store for cleanup */
|
|
- bdb->bi_monitor.bdm_cb = (void *)cb;
|
|
-
|
|
- /* we don't need to keep track of the attributes, because
|
|
- * bdb_monitor_free() takes care of everything */
|
|
- if ( a != NULL ) {
|
|
- attrs_free( a );
|
|
- }
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/*
|
|
- * call from within bdb_db_close()
|
|
- */
|
|
-int
|
|
-bdb_monitor_db_close( BackendDB *be )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
|
-
|
|
- if ( !BER_BVISNULL( &bdb->bi_monitor.bdm_ndn ) ) {
|
|
- BackendInfo *mi = backend_info( "monitor" );
|
|
- monitor_extra_t *mbe;
|
|
-
|
|
- if ( mi && &mi->bi_extra ) {
|
|
- mbe = mi->bi_extra;
|
|
- mbe->unregister_entry_callback( &bdb->bi_monitor.bdm_ndn,
|
|
- (monitor_callback_t *)bdb->bi_monitor.bdm_cb,
|
|
- NULL, 0, NULL );
|
|
- }
|
|
-
|
|
- memset( &bdb->bi_monitor, 0, sizeof( bdb->bi_monitor ) );
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/*
|
|
- * call from within bdb_db_destroy()
|
|
- */
|
|
-int
|
|
-bdb_monitor_db_destroy( BackendDB *be )
|
|
-{
|
|
-#ifdef BDB_MONITOR_IDX
|
|
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
|
-
|
|
- /* TODO: free tree */
|
|
- ldap_pvt_thread_mutex_destroy( &bdb->bi_idx_mutex );
|
|
- avl_free( bdb->bi_idx, ch_free );
|
|
-#endif /* BDB_MONITOR_IDX */
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-#ifdef BDB_MONITOR_IDX
|
|
-
|
|
-#define BDB_MONITOR_IDX_TYPES (4)
|
|
-
|
|
-typedef struct monitor_idx_t monitor_idx_t;
|
|
-
|
|
-struct monitor_idx_t {
|
|
- AttributeDescription *idx_ad;
|
|
- unsigned long idx_count[BDB_MONITOR_IDX_TYPES];
|
|
-};
|
|
-
|
|
-static int
|
|
-bdb_monitor_bitmask2key( slap_mask_t bitmask )
|
|
-{
|
|
- int key;
|
|
-
|
|
- for ( key = 0; key < 8 * (int)sizeof(slap_mask_t) && !( bitmask & 0x1U );
|
|
- key++ )
|
|
- bitmask >>= 1;
|
|
-
|
|
- return key;
|
|
-}
|
|
-
|
|
-static struct berval idxbv[] = {
|
|
- BER_BVC( "present=" ),
|
|
- BER_BVC( "equality=" ),
|
|
- BER_BVC( "approx=" ),
|
|
- BER_BVC( "substr=" ),
|
|
- BER_BVNULL
|
|
-};
|
|
-
|
|
-static ber_len_t
|
|
-bdb_monitor_idx2len( monitor_idx_t *idx )
|
|
-{
|
|
- int i;
|
|
- ber_len_t len = 0;
|
|
-
|
|
- for ( i = 0; i < BDB_MONITOR_IDX_TYPES; i++ ) {
|
|
- if ( idx->idx_count[ i ] != 0 ) {
|
|
- len += idxbv[i].bv_len;
|
|
- }
|
|
- }
|
|
-
|
|
- return len;
|
|
-}
|
|
-
|
|
-static int
|
|
-monitor_idx_cmp( const void *p1, const void *p2 )
|
|
-{
|
|
- const monitor_idx_t *idx1 = (const monitor_idx_t *)p1;
|
|
- const monitor_idx_t *idx2 = (const monitor_idx_t *)p2;
|
|
-
|
|
- return SLAP_PTRCMP( idx1->idx_ad, idx2->idx_ad );
|
|
-}
|
|
-
|
|
-static int
|
|
-monitor_idx_dup( void *p1, void *p2 )
|
|
-{
|
|
- monitor_idx_t *idx1 = (monitor_idx_t *)p1;
|
|
- monitor_idx_t *idx2 = (monitor_idx_t *)p2;
|
|
-
|
|
- return SLAP_PTRCMP( idx1->idx_ad, idx2->idx_ad ) == 0 ? -1 : 0;
|
|
-}
|
|
-
|
|
-int
|
|
-bdb_monitor_idx_add(
|
|
- struct bdb_info *bdb,
|
|
- AttributeDescription *desc,
|
|
- slap_mask_t type )
|
|
-{
|
|
- monitor_idx_t idx_dummy = { 0 },
|
|
- *idx;
|
|
- int rc = 0, key;
|
|
-
|
|
- idx_dummy.idx_ad = desc;
|
|
- key = bdb_monitor_bitmask2key( type ) - 1;
|
|
- if ( key >= BDB_MONITOR_IDX_TYPES ) {
|
|
- /* invalid index type */
|
|
- return -1;
|
|
- }
|
|
-
|
|
- ldap_pvt_thread_mutex_lock( &bdb->bi_idx_mutex );
|
|
-
|
|
- idx = (monitor_idx_t *)avl_find( bdb->bi_idx,
|
|
- (caddr_t)&idx_dummy, monitor_idx_cmp );
|
|
- if ( idx == NULL ) {
|
|
- idx = (monitor_idx_t *)ch_calloc( sizeof( monitor_idx_t ), 1 );
|
|
- idx->idx_ad = desc;
|
|
- idx->idx_count[ key ] = 1;
|
|
-
|
|
- switch ( avl_insert( &bdb->bi_idx, (caddr_t)idx,
|
|
- monitor_idx_cmp, monitor_idx_dup ) )
|
|
- {
|
|
- case 0:
|
|
- break;
|
|
-
|
|
- default:
|
|
- ch_free( idx );
|
|
- rc = -1;
|
|
- }
|
|
-
|
|
- } else {
|
|
- idx->idx_count[ key ]++;
|
|
- }
|
|
-
|
|
- ldap_pvt_thread_mutex_unlock( &bdb->bi_idx_mutex );
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static int
|
|
-bdb_monitor_idx_apply( void *v_idx, void *v_valp )
|
|
-{
|
|
- monitor_idx_t *idx = (monitor_idx_t *)v_idx;
|
|
- BerVarray *valp = (BerVarray *)v_valp;
|
|
-
|
|
- struct berval bv;
|
|
- char *ptr;
|
|
- char count_buf[ BDB_MONITOR_IDX_TYPES ][ SLAP_TEXT_BUFLEN ];
|
|
- ber_len_t count_len[ BDB_MONITOR_IDX_TYPES ],
|
|
- idx_len;
|
|
- int i, num = 0;
|
|
-
|
|
- idx_len = bdb_monitor_idx2len( idx );
|
|
-
|
|
- bv.bv_len = 0;
|
|
- for ( i = 0; i < BDB_MONITOR_IDX_TYPES; i++ ) {
|
|
- if ( idx->idx_count[ i ] == 0 ) {
|
|
- continue;
|
|
- }
|
|
-
|
|
- count_len[ i ] = snprintf( count_buf[ i ],
|
|
- sizeof( count_buf[ i ] ), "%lu", idx->idx_count[ i ] );
|
|
- bv.bv_len += count_len[ i ];
|
|
- num++;
|
|
- }
|
|
-
|
|
- bv.bv_len += idx->idx_ad->ad_cname.bv_len
|
|
- + num
|
|
- + idx_len;
|
|
- ptr = bv.bv_val = ch_malloc( bv.bv_len + 1 );
|
|
- ptr = lutil_strcopy( ptr, idx->idx_ad->ad_cname.bv_val );
|
|
- for ( i = 0; i < BDB_MONITOR_IDX_TYPES; i++ ) {
|
|
- if ( idx->idx_count[ i ] == 0 ) {
|
|
- continue;
|
|
- }
|
|
-
|
|
- ptr[ 0 ] = '#';
|
|
- ++ptr;
|
|
- ptr = lutil_strcopy( ptr, idxbv[ i ].bv_val );
|
|
- ptr = lutil_strcopy( ptr, count_buf[ i ] );
|
|
- }
|
|
-
|
|
- ber_bvarray_add( valp, &bv );
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int
|
|
-bdb_monitor_idx_entry_add(
|
|
- struct bdb_info *bdb,
|
|
- Entry *e )
|
|
-{
|
|
- BerVarray vals = NULL;
|
|
- Attribute *a;
|
|
-
|
|
- a = attr_find( e->e_attrs, ad_olmDbNotIndexed );
|
|
-
|
|
- ldap_pvt_thread_mutex_lock( &bdb->bi_idx_mutex );
|
|
-
|
|
- avl_apply( bdb->bi_idx, bdb_monitor_idx_apply,
|
|
- &vals, -1, AVL_INORDER );
|
|
-
|
|
- ldap_pvt_thread_mutex_unlock( &bdb->bi_idx_mutex );
|
|
-
|
|
- if ( vals != NULL ) {
|
|
- if ( a != NULL ) {
|
|
- assert( a->a_nvals == a->a_vals );
|
|
-
|
|
- ber_bvarray_free( a->a_vals );
|
|
-
|
|
- } else {
|
|
- Attribute **ap;
|
|
-
|
|
- for ( ap = &e->e_attrs; *ap != NULL; ap = &(*ap)->a_next )
|
|
- ;
|
|
- *ap = attr_alloc( ad_olmDbNotIndexed );
|
|
- a = *ap;
|
|
- }
|
|
- a->a_vals = vals;
|
|
- a->a_nvals = a->a_vals;
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-#endif /* BDB_MONITOR_IDX */
|
|
diff --git a/servers/slapd/back-bdb/nextid.c b/servers/slapd/back-bdb/nextid.c
|
|
deleted file mode 100644
|
|
index 480b80e..0000000
|
|
--- a/servers/slapd/back-bdb/nextid.c
|
|
+++ /dev/null
|
|
@@ -1,80 +0,0 @@
|
|
-/* init.c - initialize bdb backend */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-
|
|
-#include <stdio.h>
|
|
-#include <ac/string.h>
|
|
-
|
|
-#include "back-bdb.h"
|
|
-
|
|
-int bdb_next_id( BackendDB *be, ID *out )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
|
-
|
|
- ldap_pvt_thread_mutex_lock( &bdb->bi_lastid_mutex );
|
|
- *out = ++bdb->bi_lastid;
|
|
- ldap_pvt_thread_mutex_unlock( &bdb->bi_lastid_mutex );
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-int bdb_last_id( BackendDB *be, DB_TXN *tid )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
|
- int rc;
|
|
- ID id = 0;
|
|
- unsigned char idbuf[sizeof(ID)];
|
|
- DBT key, data;
|
|
- DBC *cursor;
|
|
-
|
|
- DBTzero( &key );
|
|
- key.flags = DB_DBT_USERMEM;
|
|
- key.data = (char *) idbuf;
|
|
- key.ulen = sizeof( idbuf );
|
|
-
|
|
- DBTzero( &data );
|
|
- data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
|
|
-
|
|
- /* Get a read cursor */
|
|
- rc = bdb->bi_id2entry->bdi_db->cursor( bdb->bi_id2entry->bdi_db,
|
|
- tid, &cursor, 0 );
|
|
-
|
|
- if (rc == 0) {
|
|
- rc = cursor->c_get(cursor, &key, &data, DB_LAST);
|
|
- cursor->c_close(cursor);
|
|
- }
|
|
-
|
|
- switch(rc) {
|
|
- case DB_NOTFOUND:
|
|
- rc = 0;
|
|
- break;
|
|
- case 0:
|
|
- BDB_DISK2ID( idbuf, &id );
|
|
- break;
|
|
-
|
|
- default:
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "=> bdb_last_id: get failed: %s (%d)\n",
|
|
- db_strerror(rc), rc, 0 );
|
|
- goto done;
|
|
- }
|
|
-
|
|
- bdb->bi_lastid = id;
|
|
-
|
|
-done:
|
|
- return rc;
|
|
-}
|
|
diff --git a/servers/slapd/back-bdb/operational.c b/servers/slapd/back-bdb/operational.c
|
|
deleted file mode 100644
|
|
index 5f21abe..0000000
|
|
--- a/servers/slapd/back-bdb/operational.c
|
|
+++ /dev/null
|
|
@@ -1,151 +0,0 @@
|
|
-/* operational.c - bdb backend operational attributes function */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-
|
|
-#include <stdio.h>
|
|
-
|
|
-#include <ac/string.h>
|
|
-#include <ac/socket.h>
|
|
-
|
|
-#include "slap.h"
|
|
-#include "back-bdb.h"
|
|
-
|
|
-/*
|
|
- * sets *hasSubordinates to LDAP_COMPARE_TRUE/LDAP_COMPARE_FALSE
|
|
- * if the entry has children or not.
|
|
- */
|
|
-int
|
|
-bdb_hasSubordinates(
|
|
- Operation *op,
|
|
- Entry *e,
|
|
- int *hasSubordinates )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- struct bdb_op_info *opinfo;
|
|
- OpExtra *oex;
|
|
- DB_TXN *rtxn;
|
|
- int rc;
|
|
- int release = 0;
|
|
-
|
|
- assert( e != NULL );
|
|
-
|
|
- /* NOTE: this should never happen, but it actually happens
|
|
- * when using back-relay; until we find a better way to
|
|
- * preserve entry's private information while rewriting it,
|
|
- * let's disable the hasSubordinate feature for back-relay.
|
|
- */
|
|
- if ( BEI( e ) == NULL ) {
|
|
- Entry *ee = NULL;
|
|
- rc = be_entry_get_rw( op, &e->e_nname, NULL, NULL, 0, &ee );
|
|
- if ( rc != LDAP_SUCCESS || ee == NULL ) {
|
|
- rc = LDAP_OTHER;
|
|
- goto done;
|
|
- }
|
|
- e = ee;
|
|
- release = 1;
|
|
- if ( BEI( ee ) == NULL ) {
|
|
- rc = LDAP_OTHER;
|
|
- goto done;
|
|
- }
|
|
- }
|
|
-
|
|
- /* Check for a txn in a parent op, otherwise use reader txn */
|
|
- LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
|
|
- if ( oex->oe_key == bdb )
|
|
- break;
|
|
- }
|
|
- opinfo = (struct bdb_op_info *) oex;
|
|
- if ( opinfo && opinfo->boi_txn ) {
|
|
- rtxn = opinfo->boi_txn;
|
|
- } else {
|
|
- rc = bdb_reader_get(op, bdb->bi_dbenv, &rtxn);
|
|
- if ( rc ) {
|
|
- rc = LDAP_OTHER;
|
|
- goto done;
|
|
- }
|
|
- }
|
|
-
|
|
-retry:
|
|
- /* FIXME: we can no longer assume the entry's e_private
|
|
- * field is correctly populated; so we need to reacquire
|
|
- * it with reader lock */
|
|
- rc = bdb_cache_children( op, rtxn, e );
|
|
-
|
|
- switch( rc ) {
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto retry;
|
|
-
|
|
- case 0:
|
|
- *hasSubordinates = LDAP_COMPARE_TRUE;
|
|
- break;
|
|
-
|
|
- case DB_NOTFOUND:
|
|
- *hasSubordinates = LDAP_COMPARE_FALSE;
|
|
- rc = LDAP_SUCCESS;
|
|
- break;
|
|
-
|
|
- default:
|
|
- Debug(LDAP_DEBUG_ARGS,
|
|
- "<=- " LDAP_XSTRING(bdb_hasSubordinates)
|
|
- ": has_children failed: %s (%d)\n",
|
|
- db_strerror(rc), rc, 0 );
|
|
- rc = LDAP_OTHER;
|
|
- }
|
|
-
|
|
-done:;
|
|
- if ( release && e != NULL ) be_entry_release_r( op, e );
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/*
|
|
- * sets the supported operational attributes (if required)
|
|
- */
|
|
-int
|
|
-bdb_operational(
|
|
- Operation *op,
|
|
- SlapReply *rs )
|
|
-{
|
|
- Attribute **ap;
|
|
-
|
|
- assert( rs->sr_entry != NULL );
|
|
-
|
|
- for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next ) {
|
|
- if ( (*ap)->a_desc == slap_schema.si_ad_hasSubordinates ) {
|
|
- break;
|
|
- }
|
|
- }
|
|
-
|
|
- if ( *ap == NULL &&
|
|
- attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_hasSubordinates ) == NULL &&
|
|
- ( SLAP_OPATTRS( rs->sr_attr_flags ) ||
|
|
- ad_inlist( slap_schema.si_ad_hasSubordinates, rs->sr_attrs ) ) )
|
|
- {
|
|
- int hasSubordinates, rc;
|
|
-
|
|
- rc = bdb_hasSubordinates( op, rs->sr_entry, &hasSubordinates );
|
|
- if ( rc == LDAP_SUCCESS ) {
|
|
- *ap = slap_operational_hasSubordinate( hasSubordinates == LDAP_COMPARE_TRUE );
|
|
- assert( *ap != NULL );
|
|
-
|
|
- ap = &(*ap)->a_next;
|
|
- }
|
|
- }
|
|
-
|
|
- return LDAP_SUCCESS;
|
|
-}
|
|
-
|
|
diff --git a/servers/slapd/back-bdb/proto-bdb.h b/servers/slapd/back-bdb/proto-bdb.h
|
|
deleted file mode 100644
|
|
index 34b8ce0..0000000
|
|
--- a/servers/slapd/back-bdb/proto-bdb.h
|
|
+++ /dev/null
|
|
@@ -1,678 +0,0 @@
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#ifndef _PROTO_BDB_H
|
|
-#define _PROTO_BDB_H
|
|
-
|
|
-LDAP_BEGIN_DECL
|
|
-
|
|
-#ifdef BDB_HIER
|
|
-#define BDB_SYMBOL(x) LDAP_CONCAT(hdb_,x)
|
|
-#define BDB_UCTYPE "HDB"
|
|
-#else
|
|
-#define BDB_SYMBOL(x) LDAP_CONCAT(bdb_,x)
|
|
-#define BDB_UCTYPE "BDB"
|
|
-#endif
|
|
-
|
|
-/*
|
|
- * attr.c
|
|
- */
|
|
-
|
|
-#define bdb_attr_mask BDB_SYMBOL(attr_mask)
|
|
-#define bdb_attr_flush BDB_SYMBOL(attr_flush)
|
|
-#define bdb_attr_slot BDB_SYMBOL(attr_slot)
|
|
-#define bdb_attr_index_config BDB_SYMBOL(attr_index_config)
|
|
-#define bdb_attr_index_destroy BDB_SYMBOL(attr_index_destroy)
|
|
-#define bdb_attr_index_free BDB_SYMBOL(attr_index_free)
|
|
-#define bdb_attr_index_unparse BDB_SYMBOL(attr_index_unparse)
|
|
-#define bdb_attr_info_free BDB_SYMBOL(attr_info_free)
|
|
-
|
|
-AttrInfo *bdb_attr_mask( struct bdb_info *bdb,
|
|
- AttributeDescription *desc );
|
|
-
|
|
-void bdb_attr_flush( struct bdb_info *bdb );
|
|
-
|
|
-int bdb_attr_slot( struct bdb_info *bdb,
|
|
- AttributeDescription *desc, int *insert );
|
|
-
|
|
-int bdb_attr_index_config LDAP_P(( struct bdb_info *bdb,
|
|
- const char *fname, int lineno,
|
|
- int argc, char **argv, struct config_reply_s *cr ));
|
|
-
|
|
-void bdb_attr_index_unparse LDAP_P(( struct bdb_info *bdb, BerVarray *bva ));
|
|
-void bdb_attr_index_destroy LDAP_P(( struct bdb_info *bdb ));
|
|
-void bdb_attr_index_free LDAP_P(( struct bdb_info *bdb,
|
|
- AttributeDescription *ad ));
|
|
-
|
|
-void bdb_attr_info_free( AttrInfo *ai );
|
|
-
|
|
-/*
|
|
- * config.c
|
|
- */
|
|
-
|
|
-#define bdb_back_init_cf BDB_SYMBOL(back_init_cf)
|
|
-
|
|
-int bdb_back_init_cf( BackendInfo *bi );
|
|
-
|
|
-/*
|
|
- * dbcache.c
|
|
- */
|
|
-#define bdb_db_cache BDB_SYMBOL(db_cache)
|
|
-#define bdb_db_findsize BDB_SYMBOL(db_findsize)
|
|
-
|
|
-int
|
|
-bdb_db_cache(
|
|
- Backend *be,
|
|
- struct berval *name,
|
|
- DB **db );
|
|
-
|
|
-int
|
|
-bdb_db_findsize(
|
|
- struct bdb_info *bdb,
|
|
- struct berval *name );
|
|
-
|
|
-/*
|
|
- * dn2entry.c
|
|
- */
|
|
-#define bdb_dn2entry BDB_SYMBOL(dn2entry)
|
|
-
|
|
-int bdb_dn2entry LDAP_P(( Operation *op, DB_TXN *tid,
|
|
- struct berval *dn, EntryInfo **e, int matched,
|
|
- DB_LOCK *lock ));
|
|
-
|
|
-/*
|
|
- * dn2id.c
|
|
- */
|
|
-#define bdb_dn2id BDB_SYMBOL(dn2id)
|
|
-#define bdb_dn2id_add BDB_SYMBOL(dn2id_add)
|
|
-#define bdb_dn2id_delete BDB_SYMBOL(dn2id_delete)
|
|
-#define bdb_dn2id_children BDB_SYMBOL(dn2id_children)
|
|
-#define bdb_dn2idl BDB_SYMBOL(dn2idl)
|
|
-
|
|
-int bdb_dn2id(
|
|
- Operation *op,
|
|
- struct berval *dn,
|
|
- EntryInfo *ei,
|
|
- DB_TXN *txn,
|
|
- DBC **cursor );
|
|
-
|
|
-int bdb_dn2id_add(
|
|
- Operation *op,
|
|
- DB_TXN *tid,
|
|
- EntryInfo *eip,
|
|
- Entry *e );
|
|
-
|
|
-int bdb_dn2id_delete(
|
|
- Operation *op,
|
|
- DB_TXN *tid,
|
|
- EntryInfo *eip,
|
|
- Entry *e );
|
|
-
|
|
-int bdb_dn2id_children(
|
|
- Operation *op,
|
|
- DB_TXN *tid,
|
|
- Entry *e );
|
|
-
|
|
-int bdb_dn2idl(
|
|
- Operation *op,
|
|
- DB_TXN *txn,
|
|
- struct berval *ndn,
|
|
- EntryInfo *ei,
|
|
- ID *ids,
|
|
- ID *stack );
|
|
-
|
|
-#ifdef BDB_HIER
|
|
-#define bdb_dn2id_parent BDB_SYMBOL(dn2id_parent)
|
|
-#define bdb_dup_compare BDB_SYMBOL(dup_compare)
|
|
-#define bdb_fix_dn BDB_SYMBOL(fix_dn)
|
|
-
|
|
-int bdb_dn2id_parent(
|
|
- Operation *op,
|
|
- DB_TXN *txn,
|
|
- EntryInfo *ei,
|
|
- ID *idp );
|
|
-
|
|
-int bdb_dup_compare(
|
|
- DB *db,
|
|
- const DBT *usrkey,
|
|
- const DBT *curkey );
|
|
-
|
|
-int bdb_fix_dn( Entry *e, int checkit );
|
|
-#endif
|
|
-
|
|
-
|
|
-/*
|
|
- * error.c
|
|
- */
|
|
-#define bdb_errcall BDB_SYMBOL(errcall)
|
|
-
|
|
-#if DB_VERSION_FULL < 0x04030000
|
|
-void bdb_errcall( const char *pfx, char * msg );
|
|
-#else
|
|
-#define bdb_msgcall BDB_SYMBOL(msgcall)
|
|
-void bdb_errcall( const DB_ENV *env, const char *pfx, const char * msg );
|
|
-void bdb_msgcall( const DB_ENV *env, const char * msg );
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_EBCDIC
|
|
-#define ebcdic_dberror BDB_SYMBOL(ebcdic_dberror)
|
|
-
|
|
-char *ebcdic_dberror( int rc );
|
|
-#define db_strerror(x) ebcdic_dberror(x)
|
|
-#endif
|
|
-
|
|
-/*
|
|
- * filterentry.c
|
|
- */
|
|
-#define bdb_filter_candidates BDB_SYMBOL(filter_candidates)
|
|
-
|
|
-int bdb_filter_candidates(
|
|
- Operation *op,
|
|
- DB_TXN *txn,
|
|
- Filter *f,
|
|
- ID *ids,
|
|
- ID *tmp,
|
|
- ID *stack );
|
|
-
|
|
-/*
|
|
- * id2entry.c
|
|
- */
|
|
-#define bdb_id2entry BDB_SYMBOL(id2entry)
|
|
-#define bdb_id2entry_add BDB_SYMBOL(id2entry_add)
|
|
-#define bdb_id2entry_update BDB_SYMBOL(id2entry_update)
|
|
-#define bdb_id2entry_delete BDB_SYMBOL(id2entry_delete)
|
|
-
|
|
-int bdb_id2entry_add(
|
|
- BackendDB *be,
|
|
- DB_TXN *tid,
|
|
- Entry *e );
|
|
-
|
|
-int bdb_id2entry_update(
|
|
- BackendDB *be,
|
|
- DB_TXN *tid,
|
|
- Entry *e );
|
|
-
|
|
-int bdb_id2entry_delete(
|
|
- BackendDB *be,
|
|
- DB_TXN *tid,
|
|
- Entry *e);
|
|
-
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
-#else
|
|
-int bdb_id2entry(
|
|
- BackendDB *be,
|
|
- DB_TXN *tid,
|
|
- ID id,
|
|
- Entry **e);
|
|
-#endif
|
|
-
|
|
-#define bdb_entry_free BDB_SYMBOL(entry_free)
|
|
-#define bdb_entry_return BDB_SYMBOL(entry_return)
|
|
-#define bdb_entry_release BDB_SYMBOL(entry_release)
|
|
-#define bdb_entry_get BDB_SYMBOL(entry_get)
|
|
-
|
|
-void bdb_entry_free ( Entry *e );
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
-int bdb_entry_return( struct bdb_info *bdb, Entry *e, int seqno );
|
|
-#else
|
|
-int bdb_entry_return( Entry *e );
|
|
-#endif
|
|
-BI_entry_release_rw bdb_entry_release;
|
|
-BI_entry_get_rw bdb_entry_get;
|
|
-
|
|
-
|
|
-/*
|
|
- * idl.c
|
|
- */
|
|
-
|
|
-#define bdb_idl_cache_get BDB_SYMBOL(idl_cache_get)
|
|
-#define bdb_idl_cache_put BDB_SYMBOL(idl_cache_put)
|
|
-#define bdb_idl_cache_del BDB_SYMBOL(idl_cache_del)
|
|
-#define bdb_idl_cache_add_id BDB_SYMBOL(idl_cache_add_id)
|
|
-#define bdb_idl_cache_del_id BDB_SYMBOL(idl_cache_del_id)
|
|
-
|
|
-int bdb_idl_cache_get(
|
|
- struct bdb_info *bdb,
|
|
- DB *db,
|
|
- DBT *key,
|
|
- ID *ids );
|
|
-
|
|
-void
|
|
-bdb_idl_cache_put(
|
|
- struct bdb_info *bdb,
|
|
- DB *db,
|
|
- DBT *key,
|
|
- ID *ids,
|
|
- int rc );
|
|
-
|
|
-void
|
|
-bdb_idl_cache_del(
|
|
- struct bdb_info *bdb,
|
|
- DB *db,
|
|
- DBT *key );
|
|
-
|
|
-void
|
|
-bdb_idl_cache_add_id(
|
|
- struct bdb_info *bdb,
|
|
- DB *db,
|
|
- DBT *key,
|
|
- ID id );
|
|
-
|
|
-void
|
|
-bdb_idl_cache_del_id(
|
|
- struct bdb_info *bdb,
|
|
- DB *db,
|
|
- DBT *key,
|
|
- ID id );
|
|
-
|
|
-#define bdb_idl_first BDB_SYMBOL(idl_first)
|
|
-#define bdb_idl_next BDB_SYMBOL(idl_next)
|
|
-#define bdb_idl_search BDB_SYMBOL(idl_search)
|
|
-#define bdb_idl_insert BDB_SYMBOL(idl_insert)
|
|
-#define bdb_idl_delete BDB_SYMBOL(idl_delete)
|
|
-#define bdb_idl_intersection BDB_SYMBOL(idl_intersection)
|
|
-#define bdb_idl_union BDB_SYMBOL(idl_union)
|
|
-#define bdb_idl_sort BDB_SYMBOL(idl_sort)
|
|
-#define bdb_idl_append BDB_SYMBOL(idl_append)
|
|
-#define bdb_idl_append_one BDB_SYMBOL(idl_append_one)
|
|
-
|
|
-#define bdb_idl_fetch_key BDB_SYMBOL(idl_fetch_key)
|
|
-#define bdb_idl_insert_key BDB_SYMBOL(idl_insert_key)
|
|
-#define bdb_idl_delete_key BDB_SYMBOL(idl_delete_key)
|
|
-
|
|
-unsigned bdb_idl_search( ID *ids, ID id );
|
|
-
|
|
-int bdb_idl_fetch_key(
|
|
- BackendDB *be,
|
|
- DB *db,
|
|
- DB_TXN *txn,
|
|
- DBT *key,
|
|
- ID *ids,
|
|
- DBC **saved_cursor,
|
|
- int get_flag );
|
|
-
|
|
-int bdb_idl_insert( ID *ids, ID id );
|
|
-int bdb_idl_delete( ID *ids, ID id );
|
|
-
|
|
-int bdb_idl_insert_key(
|
|
- BackendDB *be,
|
|
- DB *db,
|
|
- DB_TXN *txn,
|
|
- DBT *key,
|
|
- ID id );
|
|
-
|
|
-int bdb_idl_delete_key(
|
|
- BackendDB *be,
|
|
- DB *db,
|
|
- DB_TXN *txn,
|
|
- DBT *key,
|
|
- ID id );
|
|
-
|
|
-int
|
|
-bdb_idl_intersection(
|
|
- ID *a,
|
|
- ID *b );
|
|
-
|
|
-int
|
|
-bdb_idl_union(
|
|
- ID *a,
|
|
- ID *b );
|
|
-
|
|
-ID bdb_idl_first( ID *ids, ID *cursor );
|
|
-ID bdb_idl_next( ID *ids, ID *cursor );
|
|
-
|
|
-void bdb_idl_sort( ID *ids, ID *tmp );
|
|
-int bdb_idl_append( ID *a, ID *b );
|
|
-int bdb_idl_append_one( ID *ids, ID id );
|
|
-
|
|
-
|
|
-/*
|
|
- * index.c
|
|
- */
|
|
-#define bdb_index_mask BDB_SYMBOL(index_mask)
|
|
-#define bdb_index_param BDB_SYMBOL(index_param)
|
|
-#define bdb_index_values BDB_SYMBOL(index_values)
|
|
-#define bdb_index_entry BDB_SYMBOL(index_entry)
|
|
-#define bdb_index_recset BDB_SYMBOL(index_recset)
|
|
-#define bdb_index_recrun BDB_SYMBOL(index_recrun)
|
|
-
|
|
-extern AttrInfo *
|
|
-bdb_index_mask LDAP_P((
|
|
- Backend *be,
|
|
- AttributeDescription *desc,
|
|
- struct berval *name ));
|
|
-
|
|
-extern int
|
|
-bdb_index_param LDAP_P((
|
|
- Backend *be,
|
|
- AttributeDescription *desc,
|
|
- int ftype,
|
|
- DB **db,
|
|
- slap_mask_t *mask,
|
|
- struct berval *prefix ));
|
|
-
|
|
-extern int
|
|
-bdb_index_values LDAP_P((
|
|
- Operation *op,
|
|
- DB_TXN *txn,
|
|
- AttributeDescription *desc,
|
|
- BerVarray vals,
|
|
- ID id,
|
|
- int opid ));
|
|
-
|
|
-extern int
|
|
-bdb_index_recset LDAP_P((
|
|
- struct bdb_info *bdb,
|
|
- Attribute *a,
|
|
- AttributeType *type,
|
|
- struct berval *tags,
|
|
- IndexRec *ir ));
|
|
-
|
|
-extern int
|
|
-bdb_index_recrun LDAP_P((
|
|
- Operation *op,
|
|
- struct bdb_info *bdb,
|
|
- IndexRec *ir,
|
|
- ID id,
|
|
- int base ));
|
|
-
|
|
-int bdb_index_entry LDAP_P(( Operation *op, DB_TXN *t, int r, Entry *e ));
|
|
-
|
|
-#define bdb_index_entry_add(op,t,e) \
|
|
- bdb_index_entry((op),(t),SLAP_INDEX_ADD_OP,(e))
|
|
-#define bdb_index_entry_del(op,t,e) \
|
|
- bdb_index_entry((op),(t),SLAP_INDEX_DELETE_OP,(e))
|
|
-
|
|
-/*
|
|
- * key.c
|
|
- */
|
|
-#define bdb_key_read BDB_SYMBOL(key_read)
|
|
-#define bdb_key_change BDB_SYMBOL(key_change)
|
|
-
|
|
-extern int
|
|
-bdb_key_read(
|
|
- Backend *be,
|
|
- DB *db,
|
|
- DB_TXN *txn,
|
|
- struct berval *k,
|
|
- ID *ids,
|
|
- DBC **saved_cursor,
|
|
- int get_flags );
|
|
-
|
|
-extern int
|
|
-bdb_key_change(
|
|
- Backend *be,
|
|
- DB *db,
|
|
- DB_TXN *txn,
|
|
- struct berval *k,
|
|
- ID id,
|
|
- int op );
|
|
-
|
|
-/*
|
|
- * nextid.c
|
|
- */
|
|
-#define bdb_next_id BDB_SYMBOL(next_id)
|
|
-#define bdb_last_id BDB_SYMBOL(last_id)
|
|
-
|
|
-int bdb_next_id( BackendDB *be, ID *id );
|
|
-int bdb_last_id( BackendDB *be, DB_TXN *tid );
|
|
-
|
|
-/*
|
|
- * modify.c
|
|
- */
|
|
-#define bdb_modify_internal BDB_SYMBOL(modify_internal)
|
|
-
|
|
-int bdb_modify_internal(
|
|
- Operation *op,
|
|
- DB_TXN *tid,
|
|
- Modifications *modlist,
|
|
- Entry *e,
|
|
- const char **text,
|
|
- char *textbuf,
|
|
- size_t textlen );
|
|
-
|
|
-/*
|
|
- * monitor.c
|
|
- */
|
|
-
|
|
-#define bdb_monitor_db_init BDB_SYMBOL(monitor_db_init)
|
|
-#define bdb_monitor_db_open BDB_SYMBOL(monitor_db_open)
|
|
-#define bdb_monitor_db_close BDB_SYMBOL(monitor_db_close)
|
|
-#define bdb_monitor_db_destroy BDB_SYMBOL(monitor_db_destroy)
|
|
-
|
|
-int bdb_monitor_db_init( BackendDB *be );
|
|
-int bdb_monitor_db_open( BackendDB *be );
|
|
-int bdb_monitor_db_close( BackendDB *be );
|
|
-int bdb_monitor_db_destroy( BackendDB *be );
|
|
-
|
|
-#ifdef BDB_MONITOR_IDX
|
|
-#define bdb_monitor_idx_add BDB_SYMBOL(monitor_idx_add)
|
|
-int
|
|
-bdb_monitor_idx_add(
|
|
- struct bdb_info *bdb,
|
|
- AttributeDescription *desc,
|
|
- slap_mask_t type );
|
|
-#endif /* BDB_MONITOR_IDX */
|
|
-
|
|
-/*
|
|
- * cache.c
|
|
- */
|
|
-#define bdb_cache_entry_db_unlock BDB_SYMBOL(cache_entry_db_unlock)
|
|
-#define bdb_cache_return_entry_rw BDB_SYMBOL(cache_return_entry_rw)
|
|
-
|
|
-#define bdb_cache_entryinfo_lock(e) \
|
|
- ldap_pvt_thread_mutex_lock( &(e)->bei_kids_mutex )
|
|
-#define bdb_cache_entryinfo_unlock(e) \
|
|
- ldap_pvt_thread_mutex_unlock( &(e)->bei_kids_mutex )
|
|
-#define bdb_cache_entryinfo_trylock(e) \
|
|
- ldap_pvt_thread_mutex_trylock( &(e)->bei_kids_mutex )
|
|
-
|
|
-/* What a mess. Hopefully the current cache scheme will stabilize
|
|
- * and we can trim out all of this stuff.
|
|
- */
|
|
-void bdb_cache_return_entry_rw( struct bdb_info *bdb, Entry *e,
|
|
- int rw, DB_LOCK *lock );
|
|
-#define bdb_cache_return_entry_r(bdb, e, l) \
|
|
- bdb_cache_return_entry_rw((bdb), (e), 0, (l))
|
|
-#define bdb_cache_return_entry_w(bdb, e, l) \
|
|
- bdb_cache_return_entry_rw((bdb), (e), 1, (l))
|
|
-#if 0
|
|
-void bdb_unlocked_cache_return_entry_rw( struct bdb_info *bdb, Entry *e, int rw );
|
|
-#else
|
|
-#define bdb_unlocked_cache_return_entry_rw( a, b, c ) ((void)0)
|
|
-#endif
|
|
-#define bdb_unlocked_cache_return_entry_r( c, e ) \
|
|
- bdb_unlocked_cache_return_entry_rw((c), (e), 0)
|
|
-#define bdb_unlocked_cache_return_entry_w( c, e ) \
|
|
- bdb_unlocked_cache_return_entry_rw((c), (e), 1)
|
|
-
|
|
-#define bdb_cache_add BDB_SYMBOL(cache_add)
|
|
-#define bdb_cache_children BDB_SYMBOL(cache_children)
|
|
-#define bdb_cache_delete BDB_SYMBOL(cache_delete)
|
|
-#define bdb_cache_delete_cleanup BDB_SYMBOL(cache_delete_cleanup)
|
|
-#define bdb_cache_find_id BDB_SYMBOL(cache_find_id)
|
|
-#define bdb_cache_find_ndn BDB_SYMBOL(cache_find_ndn)
|
|
-#define bdb_cache_find_parent BDB_SYMBOL(cache_find_parent)
|
|
-#define bdb_cache_modify BDB_SYMBOL(cache_modify)
|
|
-#define bdb_cache_modrdn BDB_SYMBOL(cache_modrdn)
|
|
-#define bdb_cache_release_all BDB_SYMBOL(cache_release_all)
|
|
-#define bdb_cache_delete_entry BDB_SYMBOL(cache_delete_entry)
|
|
-#define bdb_cache_deref BDB_SYMBOL(cache_deref)
|
|
-
|
|
-int bdb_cache_children(
|
|
- Operation *op,
|
|
- DB_TXN *txn,
|
|
- Entry *e
|
|
-);
|
|
-int bdb_cache_add(
|
|
- struct bdb_info *bdb,
|
|
- EntryInfo *pei,
|
|
- Entry *e,
|
|
- struct berval *nrdn,
|
|
- DB_TXN *txn,
|
|
- DB_LOCK *lock
|
|
-);
|
|
-int bdb_cache_modrdn(
|
|
- struct bdb_info *bdb,
|
|
- Entry *e,
|
|
- struct berval *nrdn,
|
|
- Entry *new,
|
|
- EntryInfo *ein,
|
|
- DB_TXN *txn,
|
|
- DB_LOCK *lock
|
|
-);
|
|
-int bdb_cache_modify(
|
|
- struct bdb_info *bdb,
|
|
- Entry *e,
|
|
- Attribute *newAttrs,
|
|
- DB_TXN *txn,
|
|
- DB_LOCK *lock
|
|
-);
|
|
-int bdb_cache_find_ndn(
|
|
- Operation *op,
|
|
- DB_TXN *txn,
|
|
- struct berval *ndn,
|
|
- EntryInfo **res
|
|
-);
|
|
-
|
|
-#define ID_LOCKED 1
|
|
-#define ID_NOCACHE 2
|
|
-#define ID_NOENTRY 4
|
|
-#define ID_CHKPURGE 8
|
|
-int bdb_cache_find_id(
|
|
- Operation *op,
|
|
- DB_TXN *tid,
|
|
- ID id,
|
|
- EntryInfo **eip,
|
|
- int flag,
|
|
- DB_LOCK *lock
|
|
-);
|
|
-int
|
|
-bdb_cache_find_parent(
|
|
- Operation *op,
|
|
- DB_TXN *txn,
|
|
- ID id,
|
|
- EntryInfo **res
|
|
-);
|
|
-int bdb_cache_delete(
|
|
- struct bdb_info *bdb,
|
|
- Entry *e,
|
|
- DB_TXN *txn,
|
|
- DB_LOCK *lock
|
|
-);
|
|
-void bdb_cache_delete_cleanup(
|
|
- Cache *cache,
|
|
- EntryInfo *ei
|
|
-);
|
|
-void bdb_cache_release_all( Cache *cache );
|
|
-void bdb_cache_deref( EntryInfo *ei );
|
|
-
|
|
-#ifdef BDB_HIER
|
|
-int hdb_cache_load(
|
|
- struct bdb_info *bdb,
|
|
- EntryInfo *ei,
|
|
- EntryInfo **res
|
|
-);
|
|
-#endif
|
|
-
|
|
-#define bdb_cache_entry_db_relock BDB_SYMBOL(cache_entry_db_relock)
|
|
-int bdb_cache_entry_db_relock(
|
|
- struct bdb_info *bdb,
|
|
- DB_TXN *txn,
|
|
- EntryInfo *ei,
|
|
- int rw,
|
|
- int tryOnly,
|
|
- DB_LOCK *lock );
|
|
-
|
|
-int bdb_cache_entry_db_unlock(
|
|
- struct bdb_info *bdb,
|
|
- DB_LOCK *lock );
|
|
-
|
|
-#define bdb_reader_get BDB_SYMBOL(reader_get)
|
|
-#define bdb_reader_flush BDB_SYMBOL(reader_flush)
|
|
-int bdb_reader_get( Operation *op, DB_ENV *env, DB_TXN **txn );
|
|
-void bdb_reader_flush( DB_ENV *env );
|
|
-
|
|
-/*
|
|
- * trans.c
|
|
- */
|
|
-#define bdb_trans_backoff BDB_SYMBOL(trans_backoff)
|
|
-
|
|
-void
|
|
-bdb_trans_backoff( int num_retries );
|
|
-
|
|
-/*
|
|
- * former external.h
|
|
- */
|
|
-
|
|
-#define bdb_back_initialize BDB_SYMBOL(back_initialize)
|
|
-#define bdb_db_config BDB_SYMBOL(db_config)
|
|
-#define bdb_add BDB_SYMBOL(add)
|
|
-#define bdb_bind BDB_SYMBOL(bind)
|
|
-#define bdb_compare BDB_SYMBOL(compare)
|
|
-#define bdb_delete BDB_SYMBOL(delete)
|
|
-#define bdb_modify BDB_SYMBOL(modify)
|
|
-#define bdb_modrdn BDB_SYMBOL(modrdn)
|
|
-#define bdb_search BDB_SYMBOL(search)
|
|
-#define bdb_extended BDB_SYMBOL(extended)
|
|
-#define bdb_referrals BDB_SYMBOL(referrals)
|
|
-#define bdb_operational BDB_SYMBOL(operational)
|
|
-#define bdb_hasSubordinates BDB_SYMBOL(hasSubordinates)
|
|
-#define bdb_tool_entry_open BDB_SYMBOL(tool_entry_open)
|
|
-#define bdb_tool_entry_close BDB_SYMBOL(tool_entry_close)
|
|
-#define bdb_tool_entry_first_x BDB_SYMBOL(tool_entry_first_x)
|
|
-#define bdb_tool_entry_next BDB_SYMBOL(tool_entry_next)
|
|
-#define bdb_tool_entry_get BDB_SYMBOL(tool_entry_get)
|
|
-#define bdb_tool_entry_put BDB_SYMBOL(tool_entry_put)
|
|
-#define bdb_tool_entry_reindex BDB_SYMBOL(tool_entry_reindex)
|
|
-#define bdb_tool_dn2id_get BDB_SYMBOL(tool_dn2id_get)
|
|
-#define bdb_tool_entry_modify BDB_SYMBOL(tool_entry_modify)
|
|
-#define bdb_tool_idl_add BDB_SYMBOL(tool_idl_add)
|
|
-
|
|
-extern BI_init bdb_back_initialize;
|
|
-
|
|
-extern BI_db_config bdb_db_config;
|
|
-
|
|
-extern BI_op_add bdb_add;
|
|
-extern BI_op_bind bdb_bind;
|
|
-extern BI_op_compare bdb_compare;
|
|
-extern BI_op_delete bdb_delete;
|
|
-extern BI_op_modify bdb_modify;
|
|
-extern BI_op_modrdn bdb_modrdn;
|
|
-extern BI_op_search bdb_search;
|
|
-extern BI_op_extended bdb_extended;
|
|
-
|
|
-extern BI_chk_referrals bdb_referrals;
|
|
-
|
|
-extern BI_operational bdb_operational;
|
|
-
|
|
-extern BI_has_subordinates bdb_hasSubordinates;
|
|
-
|
|
-/* tools.c */
|
|
-extern BI_tool_entry_open bdb_tool_entry_open;
|
|
-extern BI_tool_entry_close bdb_tool_entry_close;
|
|
-extern BI_tool_entry_first_x bdb_tool_entry_first_x;
|
|
-extern BI_tool_entry_next bdb_tool_entry_next;
|
|
-extern BI_tool_entry_get bdb_tool_entry_get;
|
|
-extern BI_tool_entry_put bdb_tool_entry_put;
|
|
-extern BI_tool_entry_reindex bdb_tool_entry_reindex;
|
|
-extern BI_tool_dn2id_get bdb_tool_dn2id_get;
|
|
-extern BI_tool_entry_modify bdb_tool_entry_modify;
|
|
-
|
|
-int bdb_tool_idl_add( BackendDB *be, DB *db, DB_TXN *txn, DBT *key, ID id );
|
|
-
|
|
-LDAP_END_DECL
|
|
-
|
|
-#endif /* _PROTO_BDB_H */
|
|
diff --git a/servers/slapd/back-bdb/referral.c b/servers/slapd/back-bdb/referral.c
|
|
deleted file mode 100644
|
|
index d92ff5a..0000000
|
|
--- a/servers/slapd/back-bdb/referral.c
|
|
+++ /dev/null
|
|
@@ -1,152 +0,0 @@
|
|
-/* referral.c - BDB backend referral handler */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-#include <stdio.h>
|
|
-#include <ac/string.h>
|
|
-
|
|
-#include "back-bdb.h"
|
|
-
|
|
-int
|
|
-bdb_referrals( Operation *op, SlapReply *rs )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- Entry *e = NULL;
|
|
- EntryInfo *ei;
|
|
- int rc = LDAP_SUCCESS;
|
|
-
|
|
- DB_TXN *rtxn;
|
|
- DB_LOCK lock;
|
|
-
|
|
- if( op->o_tag == LDAP_REQ_SEARCH ) {
|
|
- /* let search take care of itself */
|
|
- return rc;
|
|
- }
|
|
-
|
|
- if( get_manageDSAit( op ) ) {
|
|
- /* let op take care of DSA management */
|
|
- return rc;
|
|
- }
|
|
-
|
|
- rc = bdb_reader_get(op, bdb->bi_dbenv, &rtxn);
|
|
- switch(rc) {
|
|
- case 0:
|
|
- break;
|
|
- default:
|
|
- return LDAP_OTHER;
|
|
- }
|
|
-
|
|
-dn2entry_retry:
|
|
- /* get entry */
|
|
- rc = bdb_dn2entry( op, rtxn, &op->o_req_ndn, &ei, 1, &lock );
|
|
-
|
|
- /* bdb_dn2entry() may legally leave ei == NULL
|
|
- * if rc != 0 and rc != DB_NOTFOUND
|
|
- */
|
|
- if ( ei ) {
|
|
- e = ei->bei_e;
|
|
- }
|
|
-
|
|
- switch(rc) {
|
|
- case DB_NOTFOUND:
|
|
- case 0:
|
|
- break;
|
|
- case LDAP_BUSY:
|
|
- rs->sr_text = "ldap server busy";
|
|
- return LDAP_BUSY;
|
|
- case DB_LOCK_DEADLOCK:
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto dn2entry_retry;
|
|
- default:
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_referrals)
|
|
- ": dn2entry failed: %s (%d)\n",
|
|
- db_strerror(rc), rc, 0 );
|
|
- rs->sr_text = "internal error";
|
|
- return LDAP_OTHER;
|
|
- }
|
|
-
|
|
- if ( rc == DB_NOTFOUND ) {
|
|
- rc = LDAP_SUCCESS;
|
|
- rs->sr_matched = NULL;
|
|
- if ( e != NULL ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_referrals)
|
|
- ": tag=%lu target=\"%s\" matched=\"%s\"\n",
|
|
- (unsigned long)op->o_tag, op->o_req_dn.bv_val, e->e_name.bv_val );
|
|
-
|
|
- if( is_entry_referral( e ) ) {
|
|
- BerVarray ref = get_entry_referrals( op, e );
|
|
- rc = LDAP_OTHER;
|
|
- rs->sr_ref = referral_rewrite( ref, &e->e_name,
|
|
- &op->o_req_dn, LDAP_SCOPE_DEFAULT );
|
|
- ber_bvarray_free( ref );
|
|
- if ( rs->sr_ref ) {
|
|
- rs->sr_matched = ber_strdup_x(
|
|
- e->e_name.bv_val, op->o_tmpmemctx );
|
|
- }
|
|
- }
|
|
-
|
|
- bdb_cache_return_entry_r (bdb, e, &lock);
|
|
- e = NULL;
|
|
- }
|
|
-
|
|
- if( rs->sr_ref != NULL ) {
|
|
- /* send referrals */
|
|
- rc = rs->sr_err = LDAP_REFERRAL;
|
|
- send_ldap_result( op, rs );
|
|
- ber_bvarray_free( rs->sr_ref );
|
|
- rs->sr_ref = NULL;
|
|
- } else if ( rc != LDAP_SUCCESS ) {
|
|
- rs->sr_text = rs->sr_matched ? "bad referral object" : NULL;
|
|
- }
|
|
-
|
|
- if (rs->sr_matched) {
|
|
- op->o_tmpfree( (char *)rs->sr_matched, op->o_tmpmemctx );
|
|
- rs->sr_matched = NULL;
|
|
- }
|
|
- return rc;
|
|
- }
|
|
-
|
|
- if ( is_entry_referral( e ) ) {
|
|
- /* entry is a referral */
|
|
- BerVarray refs = get_entry_referrals( op, e );
|
|
- rs->sr_ref = referral_rewrite(
|
|
- refs, &e->e_name, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_referrals)
|
|
- ": tag=%lu target=\"%s\" matched=\"%s\"\n",
|
|
- (unsigned long)op->o_tag, op->o_req_dn.bv_val, e->e_name.bv_val );
|
|
-
|
|
- rs->sr_matched = e->e_name.bv_val;
|
|
- if( rs->sr_ref != NULL ) {
|
|
- rc = rs->sr_err = LDAP_REFERRAL;
|
|
- send_ldap_result( op, rs );
|
|
- ber_bvarray_free( rs->sr_ref );
|
|
- rs->sr_ref = NULL;
|
|
- } else {
|
|
- rc = LDAP_OTHER;
|
|
- rs->sr_text = "bad referral object";
|
|
- }
|
|
-
|
|
- rs->sr_matched = NULL;
|
|
- ber_bvarray_free( refs );
|
|
- }
|
|
-
|
|
- bdb_cache_return_entry_r(bdb, e, &lock);
|
|
- return rc;
|
|
-}
|
|
diff --git a/servers/slapd/back-bdb/search.c b/servers/slapd/back-bdb/search.c
|
|
deleted file mode 100644
|
|
index dd67f21..0000000
|
|
--- a/servers/slapd/back-bdb/search.c
|
|
+++ /dev/null
|
|
@@ -1,1388 +0,0 @@
|
|
-/* search.c - search operation */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-
|
|
-#include <stdio.h>
|
|
-#include <ac/string.h>
|
|
-
|
|
-#include "back-bdb.h"
|
|
-#include "idl.h"
|
|
-
|
|
-static int base_candidate(
|
|
- BackendDB *be,
|
|
- Entry *e,
|
|
- ID *ids );
|
|
-
|
|
-static int search_candidates(
|
|
- Operation *op,
|
|
- SlapReply *rs,
|
|
- Entry *e,
|
|
- DB_TXN *txn,
|
|
- ID *ids,
|
|
- ID *scopes );
|
|
-
|
|
-static int parse_paged_cookie( Operation *op, SlapReply *rs );
|
|
-
|
|
-static void send_paged_response(
|
|
- Operation *op,
|
|
- SlapReply *rs,
|
|
- ID *lastid,
|
|
- int tentries );
|
|
-
|
|
-/* Dereference aliases for a single alias entry. Return the final
|
|
- * dereferenced entry on success, NULL on any failure.
|
|
- */
|
|
-static Entry * deref_base (
|
|
- Operation *op,
|
|
- SlapReply *rs,
|
|
- Entry *e,
|
|
- Entry **matched,
|
|
- DB_TXN *txn,
|
|
- DB_LOCK *lock,
|
|
- ID *tmp,
|
|
- ID *visited )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- struct berval ndn;
|
|
- EntryInfo *ei;
|
|
- DB_LOCK lockr;
|
|
-
|
|
- rs->sr_err = LDAP_ALIAS_DEREF_PROBLEM;
|
|
- rs->sr_text = "maximum deref depth exceeded";
|
|
-
|
|
- for (;;) {
|
|
- /* Remember the last entry we looked at, so we can
|
|
- * report broken links
|
|
- */
|
|
- *matched = e;
|
|
-
|
|
- if (BDB_IDL_N(tmp) >= op->o_bd->be_max_deref_depth) {
|
|
- e = NULL;
|
|
- break;
|
|
- }
|
|
-
|
|
- /* If this is part of a subtree or onelevel search,
|
|
- * have we seen this ID before? If so, quit.
|
|
- */
|
|
- if ( visited && bdb_idl_insert( visited, e->e_id ) ) {
|
|
- e = NULL;
|
|
- break;
|
|
- }
|
|
-
|
|
- /* If we've seen this ID during this deref iteration,
|
|
- * we've hit a loop.
|
|
- */
|
|
- if ( bdb_idl_insert( tmp, e->e_id ) ) {
|
|
- rs->sr_err = LDAP_ALIAS_PROBLEM;
|
|
- rs->sr_text = "circular alias";
|
|
- e = NULL;
|
|
- break;
|
|
- }
|
|
-
|
|
- /* If there was a problem getting the aliasedObjectName,
|
|
- * get_alias_dn will have set the error status.
|
|
- */
|
|
- if ( get_alias_dn(e, &ndn, &rs->sr_err, &rs->sr_text) ) {
|
|
- e = NULL;
|
|
- break;
|
|
- }
|
|
-
|
|
- rs->sr_err = bdb_dn2entry( op, txn, &ndn, &ei,
|
|
- 0, &lockr );
|
|
- if ( rs->sr_err == DB_LOCK_DEADLOCK )
|
|
- return NULL;
|
|
-
|
|
- if ( ei ) {
|
|
- e = ei->bei_e;
|
|
- } else {
|
|
- e = NULL;
|
|
- }
|
|
-
|
|
- if (!e) {
|
|
- rs->sr_err = LDAP_ALIAS_PROBLEM;
|
|
- rs->sr_text = "aliasedObject not found";
|
|
- break;
|
|
- }
|
|
-
|
|
- /* Free the previous entry, continue to work with the
|
|
- * one we just retrieved.
|
|
- */
|
|
- bdb_cache_return_entry_r( bdb, *matched, lock);
|
|
- *lock = lockr;
|
|
-
|
|
- /* We found a regular entry. Return this to the caller. The
|
|
- * entry is still locked for Read.
|
|
- */
|
|
- if (!is_entry_alias(e)) {
|
|
- rs->sr_err = LDAP_SUCCESS;
|
|
- rs->sr_text = NULL;
|
|
- break;
|
|
- }
|
|
- }
|
|
- return e;
|
|
-}
|
|
-
|
|
-/* Look for and dereference all aliases within the search scope. Adds
|
|
- * the dereferenced entries to the "ids" list. Requires "stack" to be
|
|
- * able to hold 8 levels of DB_SIZE IDLs. Of course we're hardcoded to
|
|
- * require a minimum of 8 UM_SIZE IDLs so this is never a problem.
|
|
- */
|
|
-static int search_aliases(
|
|
- Operation *op,
|
|
- SlapReply *rs,
|
|
- Entry *e,
|
|
- DB_TXN *txn,
|
|
- ID *ids,
|
|
- ID *scopes,
|
|
- ID *stack )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- ID *aliases, *curscop, *subscop, *visited, *newsubs, *oldsubs, *tmp;
|
|
- ID cursora, ida, cursoro, ido, *subscop2;
|
|
- Entry *matched, *a;
|
|
- EntryInfo *ei;
|
|
- struct berval bv_alias = BER_BVC( "alias" );
|
|
- AttributeAssertion aa_alias = ATTRIBUTEASSERTION_INIT;
|
|
- Filter af;
|
|
- DB_LOCK locka, lockr;
|
|
- int first = 1;
|
|
-
|
|
- aliases = stack; /* IDL of all aliases in the database */
|
|
- curscop = aliases + BDB_IDL_DB_SIZE; /* Aliases in the current scope */
|
|
- subscop = curscop + BDB_IDL_DB_SIZE; /* The current scope */
|
|
- visited = subscop + BDB_IDL_DB_SIZE; /* IDs we've seen in this search */
|
|
- newsubs = visited + BDB_IDL_DB_SIZE; /* New subtrees we've added */
|
|
- oldsubs = newsubs + BDB_IDL_DB_SIZE; /* Subtrees added previously */
|
|
- tmp = oldsubs + BDB_IDL_DB_SIZE; /* Scratch space for deref_base() */
|
|
-
|
|
- /* A copy of subscop, because subscop gets clobbered by
|
|
- * the bdb_idl_union/intersection routines
|
|
- */
|
|
- subscop2 = tmp + BDB_IDL_DB_SIZE;
|
|
-
|
|
- af.f_choice = LDAP_FILTER_EQUALITY;
|
|
- af.f_ava = &aa_alias;
|
|
- af.f_av_desc = slap_schema.si_ad_objectClass;
|
|
- af.f_av_value = bv_alias;
|
|
- af.f_next = NULL;
|
|
-
|
|
- /* Find all aliases in database */
|
|
- BDB_IDL_ZERO( aliases );
|
|
- rs->sr_err = bdb_filter_candidates( op, txn, &af, aliases,
|
|
- curscop, visited );
|
|
- if (rs->sr_err != LDAP_SUCCESS || BDB_IDL_IS_ZERO( aliases )) {
|
|
- return rs->sr_err;
|
|
- }
|
|
- oldsubs[0] = 1;
|
|
- oldsubs[1] = e->e_id;
|
|
-
|
|
- BDB_IDL_ZERO( ids );
|
|
- BDB_IDL_ZERO( visited );
|
|
- BDB_IDL_ZERO( newsubs );
|
|
-
|
|
- cursoro = 0;
|
|
- ido = bdb_idl_first( oldsubs, &cursoro );
|
|
-
|
|
- for (;;) {
|
|
- /* Set curscop to only the aliases in the current scope. Start with
|
|
- * all the aliases, obtain the IDL for the current scope, and then
|
|
- * get the intersection of these two IDLs. Add the current scope
|
|
- * to the cumulative list of candidates.
|
|
- */
|
|
- BDB_IDL_CPY( curscop, aliases );
|
|
- rs->sr_err = bdb_dn2idl( op, txn, &e->e_nname, BEI(e), subscop,
|
|
- subscop2+BDB_IDL_DB_SIZE );
|
|
-
|
|
- if (first) {
|
|
- first = 0;
|
|
- } else {
|
|
- bdb_cache_return_entry_r (bdb, e, &locka);
|
|
- }
|
|
- if ( rs->sr_err == DB_LOCK_DEADLOCK )
|
|
- return rs->sr_err;
|
|
-
|
|
- BDB_IDL_CPY(subscop2, subscop);
|
|
- rs->sr_err = bdb_idl_intersection(curscop, subscop);
|
|
- bdb_idl_union( ids, subscop2 );
|
|
-
|
|
- /* Dereference all of the aliases in the current scope. */
|
|
- cursora = 0;
|
|
- for (ida = bdb_idl_first(curscop, &cursora); ida != NOID;
|
|
- ida = bdb_idl_next(curscop, &cursora))
|
|
- {
|
|
- ei = NULL;
|
|
-retry1:
|
|
- rs->sr_err = bdb_cache_find_id(op, txn,
|
|
- ida, &ei, 0, &lockr );
|
|
- if (rs->sr_err != LDAP_SUCCESS) {
|
|
- if ( rs->sr_err == DB_LOCK_DEADLOCK )
|
|
- return rs->sr_err;
|
|
- if ( rs->sr_err == DB_LOCK_NOTGRANTED )
|
|
- goto retry1;
|
|
- continue;
|
|
- }
|
|
- a = ei->bei_e;
|
|
-
|
|
- /* This should only happen if the curscop IDL has maxed out and
|
|
- * turned into a range that spans IDs indiscriminately
|
|
- */
|
|
- if (!is_entry_alias(a)) {
|
|
- bdb_cache_return_entry_r (bdb, a, &lockr);
|
|
- continue;
|
|
- }
|
|
-
|
|
- /* Actually dereference the alias */
|
|
- BDB_IDL_ZERO(tmp);
|
|
- a = deref_base( op, rs, a, &matched, txn, &lockr,
|
|
- tmp, visited );
|
|
- if (a) {
|
|
- /* If the target was not already in our current candidates,
|
|
- * make note of it in the newsubs list. Also
|
|
- * set it in the scopes list so that bdb_search
|
|
- * can check it.
|
|
- */
|
|
- if (bdb_idl_insert(ids, a->e_id) == 0) {
|
|
- bdb_idl_insert(newsubs, a->e_id);
|
|
- bdb_idl_insert(scopes, a->e_id);
|
|
- }
|
|
- bdb_cache_return_entry_r( bdb, a, &lockr);
|
|
-
|
|
- } else if ( rs->sr_err == DB_LOCK_DEADLOCK ) {
|
|
- return rs->sr_err;
|
|
- } else if (matched) {
|
|
- /* Alias could not be dereferenced, or it deref'd to
|
|
- * an ID we've already seen. Ignore it.
|
|
- */
|
|
- bdb_cache_return_entry_r( bdb, matched, &lockr );
|
|
- rs->sr_text = NULL;
|
|
- }
|
|
- }
|
|
- /* If this is a OneLevel search, we're done; oldsubs only had one
|
|
- * ID in it. For a Subtree search, oldsubs may be a list of scope IDs.
|
|
- */
|
|
- if ( op->ors_scope == LDAP_SCOPE_ONELEVEL ) break;
|
|
-nextido:
|
|
- ido = bdb_idl_next( oldsubs, &cursoro );
|
|
-
|
|
- /* If we're done processing the old scopes, did we add any new
|
|
- * scopes in this iteration? If so, go back and do those now.
|
|
- */
|
|
- if (ido == NOID) {
|
|
- if (BDB_IDL_IS_ZERO(newsubs)) break;
|
|
- BDB_IDL_CPY(oldsubs, newsubs);
|
|
- BDB_IDL_ZERO(newsubs);
|
|
- cursoro = 0;
|
|
- ido = bdb_idl_first( oldsubs, &cursoro );
|
|
- }
|
|
-
|
|
- /* Find the entry corresponding to the next scope. If it can't
|
|
- * be found, ignore it and move on. This should never happen;
|
|
- * we should never see the ID of an entry that doesn't exist.
|
|
- * Set the name so that the scope's IDL can be retrieved.
|
|
- */
|
|
- ei = NULL;
|
|
-sameido:
|
|
- rs->sr_err = bdb_cache_find_id(op, txn, ido, &ei,
|
|
- 0, &locka );
|
|
- if ( rs->sr_err != LDAP_SUCCESS ) {
|
|
- if ( rs->sr_err == DB_LOCK_DEADLOCK )
|
|
- return rs->sr_err;
|
|
- if ( rs->sr_err == DB_LOCK_NOTGRANTED )
|
|
- goto sameido;
|
|
- goto nextido;
|
|
- }
|
|
- e = ei->bei_e;
|
|
- }
|
|
- return rs->sr_err;
|
|
-}
|
|
-
|
|
-/* Get the next ID from the DB. Used if the candidate list is
|
|
- * a range and simple iteration hits missing entryIDs
|
|
- */
|
|
-static int
|
|
-bdb_get_nextid(struct bdb_info *bdb, DB_TXN *ltid, ID *cursor)
|
|
-{
|
|
- DBC *curs;
|
|
- DBT key, data;
|
|
- ID id, nid;
|
|
- int rc;
|
|
-
|
|
- id = *cursor + 1;
|
|
- BDB_ID2DISK( id, &nid );
|
|
- rc = bdb->bi_id2entry->bdi_db->cursor(
|
|
- bdb->bi_id2entry->bdi_db, ltid, &curs, bdb->bi_db_opflags );
|
|
- if ( rc )
|
|
- return rc;
|
|
- key.data = &nid;
|
|
- key.size = key.ulen = sizeof(ID);
|
|
- key.flags = DB_DBT_USERMEM;
|
|
- data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
|
|
- data.dlen = data.ulen = 0;
|
|
- rc = curs->c_get( curs, &key, &data, DB_SET_RANGE );
|
|
- curs->c_close( curs );
|
|
- if ( rc )
|
|
- return rc;
|
|
- BDB_DISK2ID( &nid, cursor );
|
|
- return 0;
|
|
-}
|
|
-
|
|
-int
|
|
-bdb_search( Operation *op, SlapReply *rs )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- ID id, cursor;
|
|
- ID lastid = NOID;
|
|
- ID candidates[BDB_IDL_UM_SIZE];
|
|
- ID scopes[BDB_IDL_DB_SIZE];
|
|
- Entry *e = NULL, base, *e_root;
|
|
- Entry *matched = NULL;
|
|
- EntryInfo *ei;
|
|
- AttributeName *attrs;
|
|
- struct berval realbase = BER_BVNULL;
|
|
- slap_mask_t mask;
|
|
- time_t stoptime;
|
|
- int manageDSAit;
|
|
- int tentries = 0;
|
|
- unsigned nentries = 0;
|
|
- int idflag = 0;
|
|
-
|
|
- DB_LOCK lock;
|
|
- struct bdb_op_info *opinfo = NULL;
|
|
- DB_TXN *ltid = NULL;
|
|
- OpExtra *oex;
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "=> " LDAP_XSTRING(bdb_search) "\n", 0, 0, 0);
|
|
- attrs = op->oq_search.rs_attrs;
|
|
-
|
|
- LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
|
|
- if ( oex->oe_key == bdb )
|
|
- break;
|
|
- }
|
|
- opinfo = (struct bdb_op_info *) oex;
|
|
-
|
|
- manageDSAit = get_manageDSAit( op );
|
|
-
|
|
- if ( opinfo && opinfo->boi_txn ) {
|
|
- ltid = opinfo->boi_txn;
|
|
- } else {
|
|
- rs->sr_err = bdb_reader_get( op, bdb->bi_dbenv, <id );
|
|
-
|
|
- switch(rs->sr_err) {
|
|
- case 0:
|
|
- break;
|
|
- default:
|
|
- send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
|
|
- return rs->sr_err;
|
|
- }
|
|
- }
|
|
-
|
|
- e_root = bdb->bi_cache.c_dntree.bei_e;
|
|
- if ( op->o_req_ndn.bv_len == 0 ) {
|
|
- /* DIT root special case */
|
|
- ei = e_root->e_private;
|
|
- rs->sr_err = LDAP_SUCCESS;
|
|
- } else {
|
|
- if ( op->ors_deref & LDAP_DEREF_FINDING ) {
|
|
- BDB_IDL_ZERO(candidates);
|
|
- }
|
|
-dn2entry_retry:
|
|
- /* get entry with reader lock */
|
|
- rs->sr_err = bdb_dn2entry( op, ltid, &op->o_req_ndn, &ei,
|
|
- 1, &lock );
|
|
- }
|
|
-
|
|
- switch(rs->sr_err) {
|
|
- case DB_NOTFOUND:
|
|
- matched = ei->bei_e;
|
|
- break;
|
|
- case 0:
|
|
- e = ei->bei_e;
|
|
- break;
|
|
- case DB_LOCK_DEADLOCK:
|
|
- if ( !opinfo ) {
|
|
- ltid->flags &= ~TXN_DEADLOCK;
|
|
- goto dn2entry_retry;
|
|
- }
|
|
- opinfo->boi_err = rs->sr_err;
|
|
- /* FALLTHRU */
|
|
- case LDAP_BUSY:
|
|
- send_ldap_error( op, rs, LDAP_BUSY, "ldap server busy" );
|
|
- return LDAP_BUSY;
|
|
- case DB_LOCK_NOTGRANTED:
|
|
- goto dn2entry_retry;
|
|
- default:
|
|
- send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
|
|
- return rs->sr_err;
|
|
- }
|
|
-
|
|
- if ( op->ors_deref & LDAP_DEREF_FINDING ) {
|
|
- if ( matched && is_entry_alias( matched )) {
|
|
- struct berval stub;
|
|
-
|
|
- stub.bv_val = op->o_req_ndn.bv_val;
|
|
- stub.bv_len = op->o_req_ndn.bv_len - matched->e_nname.bv_len - 1;
|
|
- e = deref_base( op, rs, matched, &matched, ltid, &lock,
|
|
- candidates, NULL );
|
|
- if ( e ) {
|
|
- build_new_dn( &op->o_req_ndn, &e->e_nname, &stub,
|
|
- op->o_tmpmemctx );
|
|
- bdb_cache_return_entry_r (bdb, e, &lock);
|
|
- matched = NULL;
|
|
- goto dn2entry_retry;
|
|
- }
|
|
- } else if ( e && is_entry_alias( e )) {
|
|
- e = deref_base( op, rs, e, &matched, ltid, &lock,
|
|
- candidates, NULL );
|
|
- }
|
|
- }
|
|
-
|
|
- if ( e == NULL ) {
|
|
- struct berval matched_dn = BER_BVNULL;
|
|
-
|
|
- if ( matched != NULL ) {
|
|
- BerVarray erefs = NULL;
|
|
-
|
|
- /* return referral only if "disclose"
|
|
- * is granted on the object */
|
|
- if ( ! access_allowed( op, matched,
|
|
- slap_schema.si_ad_entry,
|
|
- NULL, ACL_DISCLOSE, NULL ) )
|
|
- {
|
|
- rs->sr_err = LDAP_NO_SUCH_OBJECT;
|
|
-
|
|
- } else {
|
|
- ber_dupbv( &matched_dn, &matched->e_name );
|
|
-
|
|
- erefs = is_entry_referral( matched )
|
|
- ? get_entry_referrals( op, matched )
|
|
- : NULL;
|
|
- if ( rs->sr_err == DB_NOTFOUND )
|
|
- rs->sr_err = LDAP_REFERRAL;
|
|
- rs->sr_matched = matched_dn.bv_val;
|
|
- }
|
|
-
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- slap_zn_runlock(bdb->bi_cache.c_zctx, matched);
|
|
-#endif
|
|
- bdb_cache_return_entry_r (bdb, matched, &lock);
|
|
- matched = NULL;
|
|
-
|
|
- if ( erefs ) {
|
|
- rs->sr_ref = referral_rewrite( erefs, &matched_dn,
|
|
- &op->o_req_dn, op->oq_search.rs_scope );
|
|
- ber_bvarray_free( erefs );
|
|
- }
|
|
-
|
|
- } else {
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- slap_zn_runlock(bdb->bi_cache.c_zctx, matched);
|
|
-#endif
|
|
- rs->sr_ref = referral_rewrite( default_referral,
|
|
- NULL, &op->o_req_dn, op->oq_search.rs_scope );
|
|
- rs->sr_err = rs->sr_ref != NULL ? LDAP_REFERRAL : LDAP_NO_SUCH_OBJECT;
|
|
- }
|
|
-
|
|
- send_ldap_result( op, rs );
|
|
-
|
|
- if ( rs->sr_ref ) {
|
|
- ber_bvarray_free( rs->sr_ref );
|
|
- rs->sr_ref = NULL;
|
|
- }
|
|
- if ( !BER_BVISNULL( &matched_dn ) ) {
|
|
- ber_memfree( matched_dn.bv_val );
|
|
- rs->sr_matched = NULL;
|
|
- }
|
|
- return rs->sr_err;
|
|
- }
|
|
-
|
|
- /* NOTE: __NEW__ "search" access is required
|
|
- * on searchBase object */
|
|
- if ( ! access_allowed_mask( op, e, slap_schema.si_ad_entry,
|
|
- NULL, ACL_SEARCH, NULL, &mask ) )
|
|
- {
|
|
- if ( !ACL_GRANT( mask, ACL_DISCLOSE ) ) {
|
|
- rs->sr_err = LDAP_NO_SUCH_OBJECT;
|
|
- } else {
|
|
- rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
|
- }
|
|
-
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- slap_zn_runlock(bdb->bi_cache.c_zctx, e);
|
|
-#endif
|
|
- if ( e != e_root ) {
|
|
- bdb_cache_return_entry_r(bdb, e, &lock);
|
|
- }
|
|
- send_ldap_result( op, rs );
|
|
- return rs->sr_err;
|
|
- }
|
|
-
|
|
- if ( !manageDSAit && e != e_root && is_entry_referral( e ) ) {
|
|
- /* entry is a referral, don't allow add */
|
|
- struct berval matched_dn = BER_BVNULL;
|
|
- BerVarray erefs = NULL;
|
|
-
|
|
- ber_dupbv( &matched_dn, &e->e_name );
|
|
- erefs = get_entry_referrals( op, e );
|
|
-
|
|
- rs->sr_err = LDAP_REFERRAL;
|
|
-
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- slap_zn_runlock(bdb->bi_cache.c_zctx, e);
|
|
-#endif
|
|
- bdb_cache_return_entry_r( bdb, e, &lock );
|
|
- e = NULL;
|
|
-
|
|
- if ( erefs ) {
|
|
- rs->sr_ref = referral_rewrite( erefs, &matched_dn,
|
|
- &op->o_req_dn, op->oq_search.rs_scope );
|
|
- ber_bvarray_free( erefs );
|
|
-
|
|
- if ( !rs->sr_ref ) {
|
|
- rs->sr_text = "bad_referral object";
|
|
- }
|
|
- }
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_search) ": entry is referral\n",
|
|
- 0, 0, 0 );
|
|
-
|
|
- rs->sr_matched = matched_dn.bv_val;
|
|
- send_ldap_result( op, rs );
|
|
-
|
|
- ber_bvarray_free( rs->sr_ref );
|
|
- rs->sr_ref = NULL;
|
|
- ber_memfree( matched_dn.bv_val );
|
|
- rs->sr_matched = NULL;
|
|
- return 1;
|
|
- }
|
|
-
|
|
- if ( get_assert( op ) &&
|
|
- ( test_filter( op, e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
|
|
- {
|
|
- rs->sr_err = LDAP_ASSERTION_FAILED;
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- slap_zn_runlock(bdb->bi_cache.c_zctx, e);
|
|
-#endif
|
|
- if ( e != e_root ) {
|
|
- bdb_cache_return_entry_r(bdb, e, &lock);
|
|
- }
|
|
- send_ldap_result( op, rs );
|
|
- return 1;
|
|
- }
|
|
-
|
|
- /* compute it anyway; root does not use it */
|
|
- stoptime = op->o_time + op->ors_tlimit;
|
|
-
|
|
- /* need normalized dn below */
|
|
- ber_dupbv( &realbase, &e->e_nname );
|
|
-
|
|
- /* Copy info to base, must free entry before accessing the database
|
|
- * in search_candidates, to avoid deadlocks.
|
|
- */
|
|
- base.e_private = e->e_private;
|
|
- base.e_nname = realbase;
|
|
- base.e_id = e->e_id;
|
|
-
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- slap_zn_runlock(bdb->bi_cache.c_zctx, e);
|
|
-#endif
|
|
- if ( e != e_root ) {
|
|
- bdb_cache_return_entry_r(bdb, e, &lock);
|
|
- }
|
|
- e = NULL;
|
|
-
|
|
- /* select candidates */
|
|
- if ( op->oq_search.rs_scope == LDAP_SCOPE_BASE ) {
|
|
- rs->sr_err = base_candidate( op->o_bd, &base, candidates );
|
|
-
|
|
- } else {
|
|
-cand_retry:
|
|
- BDB_IDL_ZERO( candidates );
|
|
- BDB_IDL_ZERO( scopes );
|
|
- rs->sr_err = search_candidates( op, rs, &base,
|
|
- ltid, candidates, scopes );
|
|
- if ( rs->sr_err == DB_LOCK_DEADLOCK ) {
|
|
- if ( !opinfo ) {
|
|
- ltid->flags &= ~TXN_DEADLOCK;
|
|
- goto cand_retry;
|
|
- }
|
|
- opinfo->boi_err = rs->sr_err;
|
|
- send_ldap_error( op, rs, LDAP_BUSY, "ldap server busy" );
|
|
- return LDAP_BUSY;
|
|
- }
|
|
- }
|
|
-
|
|
- /* start cursor at beginning of candidates.
|
|
- */
|
|
- cursor = 0;
|
|
-
|
|
- if ( candidates[0] == 0 ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_search) ": no candidates\n",
|
|
- 0, 0, 0 );
|
|
-
|
|
- goto nochange;
|
|
- }
|
|
-
|
|
- /* if not root and candidates exceed to-be-checked entries, abort */
|
|
- if ( op->ors_limit /* isroot == FALSE */ &&
|
|
- op->ors_limit->lms_s_unchecked != -1 &&
|
|
- BDB_IDL_N(candidates) > (unsigned) op->ors_limit->lms_s_unchecked )
|
|
- {
|
|
- rs->sr_err = LDAP_ADMINLIMIT_EXCEEDED;
|
|
- send_ldap_result( op, rs );
|
|
- rs->sr_err = LDAP_SUCCESS;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- if ( op->ors_limit == NULL /* isroot == TRUE */ ||
|
|
- !op->ors_limit->lms_s_pr_hide )
|
|
- {
|
|
- tentries = BDB_IDL_N(candidates);
|
|
- }
|
|
-
|
|
- if ( get_pagedresults( op ) > SLAP_CONTROL_IGNORED ) {
|
|
- PagedResultsState *ps = op->o_pagedresults_state;
|
|
- /* deferred cookie parsing */
|
|
- rs->sr_err = parse_paged_cookie( op, rs );
|
|
- if ( rs->sr_err != LDAP_SUCCESS ) {
|
|
- send_ldap_result( op, rs );
|
|
- goto done;
|
|
- }
|
|
-
|
|
- cursor = (ID) ps->ps_cookie;
|
|
- if ( cursor && ps->ps_size == 0 ) {
|
|
- rs->sr_err = LDAP_SUCCESS;
|
|
- rs->sr_text = "search abandoned by pagedResult size=0";
|
|
- send_ldap_result( op, rs );
|
|
- goto done;
|
|
- }
|
|
- id = bdb_idl_first( candidates, &cursor );
|
|
- if ( id == NOID ) {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_search)
|
|
- ": no paged results candidates\n",
|
|
- 0, 0, 0 );
|
|
- send_paged_response( op, rs, &lastid, 0 );
|
|
-
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- goto done;
|
|
- }
|
|
- nentries = ps->ps_count;
|
|
- if ( id == (ID)ps->ps_cookie )
|
|
- id = bdb_idl_next( candidates, &cursor );
|
|
- goto loop_begin;
|
|
- }
|
|
-
|
|
- for ( id = bdb_idl_first( candidates, &cursor );
|
|
- id != NOID ; id = bdb_idl_next( candidates, &cursor ) )
|
|
- {
|
|
- int scopeok;
|
|
-
|
|
-loop_begin:
|
|
-
|
|
- /* check for abandon */
|
|
- if ( op->o_abandon ) {
|
|
- rs->sr_err = SLAPD_ABANDON;
|
|
- send_ldap_result( op, rs );
|
|
- goto done;
|
|
- }
|
|
-
|
|
- /* mostly needed by internal searches,
|
|
- * e.g. related to syncrepl, for whom
|
|
- * abandon does not get set... */
|
|
- if ( slapd_shutdown ) {
|
|
- rs->sr_err = LDAP_UNAVAILABLE;
|
|
- send_ldap_disconnect( op, rs );
|
|
- goto done;
|
|
- }
|
|
-
|
|
- /* check time limit */
|
|
- if ( op->ors_tlimit != SLAP_NO_LIMIT
|
|
- && slap_get_time() > stoptime )
|
|
- {
|
|
- rs->sr_err = LDAP_TIMELIMIT_EXCEEDED;
|
|
- rs->sr_ref = rs->sr_v2ref;
|
|
- send_ldap_result( op, rs );
|
|
- rs->sr_err = LDAP_SUCCESS;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- /* If we inspect more entries than will
|
|
- * fit into the entry cache, stop caching
|
|
- * any subsequent entries
|
|
- */
|
|
- nentries++;
|
|
- if ( nentries > bdb->bi_cache.c_maxsize && !idflag ) {
|
|
- idflag = ID_NOCACHE;
|
|
- }
|
|
-
|
|
-fetch_entry_retry:
|
|
- /* get the entry with reader lock */
|
|
- ei = NULL;
|
|
- rs->sr_err = bdb_cache_find_id( op, ltid,
|
|
- id, &ei, idflag, &lock );
|
|
-
|
|
- if (rs->sr_err == LDAP_BUSY) {
|
|
- rs->sr_text = "ldap server busy";
|
|
- send_ldap_result( op, rs );
|
|
- goto done;
|
|
-
|
|
- } else if ( rs->sr_err == DB_LOCK_DEADLOCK ) {
|
|
- if ( !opinfo ) {
|
|
- ltid->flags &= ~TXN_DEADLOCK;
|
|
- goto fetch_entry_retry;
|
|
- }
|
|
-txnfail:
|
|
- opinfo->boi_err = rs->sr_err;
|
|
- send_ldap_error( op, rs, LDAP_BUSY, "ldap server busy" );
|
|
- goto done;
|
|
-
|
|
- } else if ( rs->sr_err == DB_LOCK_NOTGRANTED )
|
|
- {
|
|
- goto fetch_entry_retry;
|
|
- } else if ( rs->sr_err == LDAP_OTHER ) {
|
|
- rs->sr_text = "internal error";
|
|
- send_ldap_result( op, rs );
|
|
- goto done;
|
|
- }
|
|
-
|
|
- if ( ei && rs->sr_err == LDAP_SUCCESS ) {
|
|
- e = ei->bei_e;
|
|
- } else {
|
|
- e = NULL;
|
|
- }
|
|
-
|
|
- if ( e == NULL ) {
|
|
- if( !BDB_IDL_IS_RANGE(candidates) ) {
|
|
- /* only complain for non-range IDLs */
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_search)
|
|
- ": candidate %ld not found\n",
|
|
- (long) id, 0, 0 );
|
|
- } else {
|
|
- /* get the next ID from the DB */
|
|
-id_retry:
|
|
- rs->sr_err = bdb_get_nextid( bdb, ltid, &cursor );
|
|
- if ( rs->sr_err == DB_NOTFOUND ) {
|
|
- break;
|
|
- } else if ( rs->sr_err == DB_LOCK_DEADLOCK ) {
|
|
- if ( opinfo )
|
|
- goto txnfail;
|
|
- ltid->flags &= ~TXN_DEADLOCK;
|
|
- goto id_retry;
|
|
- } else if ( rs->sr_err == DB_LOCK_NOTGRANTED ) {
|
|
- goto id_retry;
|
|
- }
|
|
- if ( rs->sr_err ) {
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- rs->sr_text = "internal error in get_nextid";
|
|
- send_ldap_result( op, rs );
|
|
- goto done;
|
|
- }
|
|
- cursor--;
|
|
- }
|
|
-
|
|
- goto loop_continue;
|
|
- }
|
|
-
|
|
- if ( is_entry_subentry( e ) ) {
|
|
- if( op->oq_search.rs_scope != LDAP_SCOPE_BASE ) {
|
|
- if(!get_subentries_visibility( op )) {
|
|
- /* only subentries are visible */
|
|
- goto loop_continue;
|
|
- }
|
|
-
|
|
- } else if ( get_subentries( op ) &&
|
|
- !get_subentries_visibility( op ))
|
|
- {
|
|
- /* only subentries are visible */
|
|
- goto loop_continue;
|
|
- }
|
|
-
|
|
- } else if ( get_subentries_visibility( op )) {
|
|
- /* only subentries are visible */
|
|
- goto loop_continue;
|
|
- }
|
|
-
|
|
- /* Does this candidate actually satisfy the search scope?
|
|
- *
|
|
- * Note that we don't lock access to the bei_parent pointer.
|
|
- * Since only leaf nodes can be deleted, the parent of any
|
|
- * node will always be a valid node. Also since we have
|
|
- * a Read lock on the data, it cannot be renamed out of the
|
|
- * scope while we are looking at it, and unless we're using
|
|
- * BDB_HIER, its parents cannot be moved either.
|
|
- */
|
|
- scopeok = 0;
|
|
- switch( op->ors_scope ) {
|
|
- case LDAP_SCOPE_BASE:
|
|
- /* This is always true, yes? */
|
|
- if ( id == base.e_id ) scopeok = 1;
|
|
- break;
|
|
-
|
|
- case LDAP_SCOPE_ONELEVEL:
|
|
- if ( ei->bei_parent->bei_id == base.e_id ) scopeok = 1;
|
|
- break;
|
|
-
|
|
-#ifdef LDAP_SCOPE_CHILDREN
|
|
- case LDAP_SCOPE_CHILDREN:
|
|
- if ( id == base.e_id ) break;
|
|
- /* Fall-thru */
|
|
-#endif
|
|
- case LDAP_SCOPE_SUBTREE: {
|
|
- EntryInfo *tmp;
|
|
- for ( tmp = BEI(e); tmp; tmp = tmp->bei_parent ) {
|
|
- if ( tmp->bei_id == base.e_id ) {
|
|
- scopeok = 1;
|
|
- break;
|
|
- }
|
|
- }
|
|
- } break;
|
|
- }
|
|
-
|
|
- /* aliases were already dereferenced in candidate list */
|
|
- if ( op->ors_deref & LDAP_DEREF_SEARCHING ) {
|
|
- /* but if the search base is an alias, and we didn't
|
|
- * deref it when finding, return it.
|
|
- */
|
|
- if ( is_entry_alias(e) &&
|
|
- ((op->ors_deref & LDAP_DEREF_FINDING) ||
|
|
- !bvmatch(&e->e_nname, &op->o_req_ndn)))
|
|
- {
|
|
- goto loop_continue;
|
|
- }
|
|
-
|
|
- /* scopes is only non-empty for onelevel or subtree */
|
|
- if ( !scopeok && BDB_IDL_N(scopes) ) {
|
|
- unsigned x;
|
|
- if ( op->ors_scope == LDAP_SCOPE_ONELEVEL ) {
|
|
- x = bdb_idl_search( scopes, e->e_id );
|
|
- if ( scopes[x] == e->e_id ) scopeok = 1;
|
|
- } else {
|
|
- /* subtree, walk up the tree */
|
|
- EntryInfo *tmp = BEI(e);
|
|
- for (;tmp->bei_parent; tmp=tmp->bei_parent) {
|
|
- x = bdb_idl_search( scopes, tmp->bei_id );
|
|
- if ( scopes[x] == tmp->bei_id ) {
|
|
- scopeok = 1;
|
|
- break;
|
|
- }
|
|
- }
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- /* Not in scope, ignore it */
|
|
- if ( !scopeok )
|
|
- {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_search)
|
|
- ": %ld scope not okay\n",
|
|
- (long) id, 0, 0 );
|
|
- goto loop_continue;
|
|
- }
|
|
-
|
|
- /*
|
|
- * if it's a referral, add it to the list of referrals. only do
|
|
- * this for non-base searches, and don't check the filter
|
|
- * explicitly here since it's only a candidate anyway.
|
|
- */
|
|
- if ( !manageDSAit && op->oq_search.rs_scope != LDAP_SCOPE_BASE
|
|
- && is_entry_referral( e ) )
|
|
- {
|
|
- struct bdb_op_info bois;
|
|
- struct bdb_lock_info blis;
|
|
- BerVarray erefs = get_entry_referrals( op, e );
|
|
- rs->sr_ref = referral_rewrite( erefs, &e->e_name, NULL,
|
|
- op->oq_search.rs_scope == LDAP_SCOPE_ONELEVEL
|
|
- ? LDAP_SCOPE_BASE : LDAP_SCOPE_SUBTREE );
|
|
-
|
|
- /* Must set lockinfo so that entry_release will work */
|
|
- if (!opinfo) {
|
|
- bois.boi_oe.oe_key = bdb;
|
|
- bois.boi_txn = NULL;
|
|
- bois.boi_err = 0;
|
|
- bois.boi_acl_cache = op->o_do_not_cache;
|
|
- bois.boi_flag = BOI_DONTFREE;
|
|
- bois.boi_locks = &blis;
|
|
- blis.bli_next = NULL;
|
|
- LDAP_SLIST_INSERT_HEAD( &op->o_extra, &bois.boi_oe,
|
|
- oe_next );
|
|
- } else {
|
|
- blis.bli_next = opinfo->boi_locks;
|
|
- opinfo->boi_locks = &blis;
|
|
- }
|
|
- blis.bli_id = e->e_id;
|
|
- blis.bli_lock = lock;
|
|
- blis.bli_flag = BLI_DONTFREE;
|
|
-
|
|
- rs->sr_entry = e;
|
|
- rs->sr_flags = REP_ENTRY_MUSTRELEASE;
|
|
-
|
|
- send_search_reference( op, rs );
|
|
-
|
|
- if ( blis.bli_flag ) {
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- slap_zn_runlock(bdb->bi_cache.c_zctx, e);
|
|
-#endif
|
|
- bdb_cache_return_entry_r(bdb, e, &lock);
|
|
- if ( opinfo ) {
|
|
- opinfo->boi_locks = blis.bli_next;
|
|
- } else {
|
|
- LDAP_SLIST_REMOVE( &op->o_extra, &bois.boi_oe,
|
|
- OpExtra, oe_next );
|
|
- }
|
|
- }
|
|
- rs->sr_entry = NULL;
|
|
- e = NULL;
|
|
-
|
|
- ber_bvarray_free( rs->sr_ref );
|
|
- ber_bvarray_free( erefs );
|
|
- rs->sr_ref = NULL;
|
|
-
|
|
- goto loop_continue;
|
|
- }
|
|
-
|
|
- if ( !manageDSAit && is_entry_glue( e )) {
|
|
- goto loop_continue;
|
|
- }
|
|
-
|
|
- /* if it matches the filter and scope, send it */
|
|
- rs->sr_err = test_filter( op, e, op->oq_search.rs_filter );
|
|
-
|
|
- if ( rs->sr_err == LDAP_COMPARE_TRUE ) {
|
|
- /* check size limit */
|
|
- if ( get_pagedresults(op) > SLAP_CONTROL_IGNORED ) {
|
|
- if ( rs->sr_nentries >= ((PagedResultsState *)op->o_pagedresults_state)->ps_size ) {
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- slap_zn_runlock(bdb->bi_cache.c_zctx, e);
|
|
-#endif
|
|
- bdb_cache_return_entry_r( bdb, e, &lock );
|
|
- e = NULL;
|
|
- send_paged_response( op, rs, &lastid, tentries );
|
|
- goto done;
|
|
- }
|
|
- lastid = id;
|
|
- }
|
|
-
|
|
- if (e) {
|
|
- struct bdb_op_info bois;
|
|
- struct bdb_lock_info blis;
|
|
-
|
|
- /* Must set lockinfo so that entry_release will work */
|
|
- if (!opinfo) {
|
|
- bois.boi_oe.oe_key = bdb;
|
|
- bois.boi_txn = NULL;
|
|
- bois.boi_err = 0;
|
|
- bois.boi_acl_cache = op->o_do_not_cache;
|
|
- bois.boi_flag = BOI_DONTFREE;
|
|
- bois.boi_locks = &blis;
|
|
- blis.bli_next = NULL;
|
|
- LDAP_SLIST_INSERT_HEAD( &op->o_extra, &bois.boi_oe,
|
|
- oe_next );
|
|
- } else {
|
|
- blis.bli_next = opinfo->boi_locks;
|
|
- opinfo->boi_locks = &blis;
|
|
- }
|
|
- blis.bli_id = e->e_id;
|
|
- blis.bli_lock = lock;
|
|
- blis.bli_flag = BLI_DONTFREE;
|
|
-
|
|
- /* safe default */
|
|
- rs->sr_attrs = op->oq_search.rs_attrs;
|
|
- rs->sr_operational_attrs = NULL;
|
|
- rs->sr_ctrls = NULL;
|
|
- rs->sr_entry = e;
|
|
- RS_ASSERT( e->e_private != NULL );
|
|
- rs->sr_flags = REP_ENTRY_MUSTRELEASE;
|
|
- rs->sr_err = LDAP_SUCCESS;
|
|
- rs->sr_err = send_search_entry( op, rs );
|
|
- rs->sr_attrs = NULL;
|
|
- rs->sr_entry = NULL;
|
|
-
|
|
- /* send_search_entry will usually free it.
|
|
- * an overlay might leave its own copy here;
|
|
- * bli_flag will be 0 if lock was already released.
|
|
- */
|
|
- if ( blis.bli_flag ) {
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- slap_zn_runlock(bdb->bi_cache.c_zctx, e);
|
|
-#endif
|
|
- bdb_cache_return_entry_r(bdb, e, &lock);
|
|
- if ( opinfo ) {
|
|
- opinfo->boi_locks = blis.bli_next;
|
|
- } else {
|
|
- LDAP_SLIST_REMOVE( &op->o_extra, &bois.boi_oe,
|
|
- OpExtra, oe_next );
|
|
- }
|
|
- }
|
|
- e = NULL;
|
|
-
|
|
- switch ( rs->sr_err ) {
|
|
- case LDAP_SUCCESS: /* entry sent ok */
|
|
- break;
|
|
- default: /* entry not sent */
|
|
- break;
|
|
- case LDAP_BUSY:
|
|
- send_ldap_result( op, rs );
|
|
- goto done;
|
|
- case LDAP_UNAVAILABLE:
|
|
- case LDAP_SIZELIMIT_EXCEEDED:
|
|
- if ( rs->sr_err == LDAP_SIZELIMIT_EXCEEDED ) {
|
|
- rs->sr_ref = rs->sr_v2ref;
|
|
- send_ldap_result( op, rs );
|
|
- rs->sr_err = LDAP_SUCCESS;
|
|
-
|
|
- } else {
|
|
- rs->sr_err = LDAP_OTHER;
|
|
- }
|
|
- goto done;
|
|
- }
|
|
- }
|
|
-
|
|
- } else {
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- LDAP_XSTRING(bdb_search)
|
|
- ": %ld does not match filter\n",
|
|
- (long) id, 0, 0 );
|
|
- }
|
|
-
|
|
-loop_continue:
|
|
- if( e != NULL ) {
|
|
- /* free reader lock */
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- slap_zn_runlock(bdb->bi_cache.c_zctx, e);
|
|
-#endif
|
|
- bdb_cache_return_entry_r( bdb, e , &lock );
|
|
- RS_ASSERT( rs->sr_entry == NULL );
|
|
- e = NULL;
|
|
- rs->sr_entry = NULL;
|
|
- }
|
|
- }
|
|
-
|
|
-nochange:
|
|
- rs->sr_ctrls = NULL;
|
|
- rs->sr_ref = rs->sr_v2ref;
|
|
- rs->sr_err = (rs->sr_v2ref == NULL) ? LDAP_SUCCESS : LDAP_REFERRAL;
|
|
- rs->sr_rspoid = NULL;
|
|
- if ( get_pagedresults(op) > SLAP_CONTROL_IGNORED ) {
|
|
- send_paged_response( op, rs, NULL, 0 );
|
|
- } else {
|
|
- send_ldap_result( op, rs );
|
|
- }
|
|
-
|
|
- rs->sr_err = LDAP_SUCCESS;
|
|
-
|
|
-done:
|
|
- if( rs->sr_v2ref ) {
|
|
- ber_bvarray_free( rs->sr_v2ref );
|
|
- rs->sr_v2ref = NULL;
|
|
- }
|
|
- if( realbase.bv_val ) ch_free( realbase.bv_val );
|
|
-
|
|
- return rs->sr_err;
|
|
-}
|
|
-
|
|
-
|
|
-static int base_candidate(
|
|
- BackendDB *be,
|
|
- Entry *e,
|
|
- ID *ids )
|
|
-{
|
|
- Debug(LDAP_DEBUG_ARGS, "base_candidates: base: \"%s\" (0x%08lx)\n",
|
|
- e->e_nname.bv_val, (long) e->e_id, 0);
|
|
-
|
|
- ids[0] = 1;
|
|
- ids[1] = e->e_id;
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/* Look for "objectClass Present" in this filter.
|
|
- * Also count depth of filter tree while we're at it.
|
|
- */
|
|
-static int oc_filter(
|
|
- Filter *f,
|
|
- int cur,
|
|
- int *max )
|
|
-{
|
|
- int rc = 0;
|
|
-
|
|
- assert( f != NULL );
|
|
-
|
|
- if( cur > *max ) *max = cur;
|
|
-
|
|
- switch( f->f_choice ) {
|
|
- case LDAP_FILTER_PRESENT:
|
|
- if (f->f_desc == slap_schema.si_ad_objectClass) {
|
|
- rc = 1;
|
|
- }
|
|
- break;
|
|
-
|
|
- case LDAP_FILTER_AND:
|
|
- case LDAP_FILTER_OR:
|
|
- cur++;
|
|
- for ( f=f->f_and; f; f=f->f_next ) {
|
|
- (void) oc_filter(f, cur, max);
|
|
- }
|
|
- break;
|
|
-
|
|
- default:
|
|
- break;
|
|
- }
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static void search_stack_free( void *key, void *data )
|
|
-{
|
|
- ber_memfree_x(data, NULL);
|
|
-}
|
|
-
|
|
-static void *search_stack( Operation *op )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- void *ret = NULL;
|
|
-
|
|
- if ( op->o_threadctx ) {
|
|
- ldap_pvt_thread_pool_getkey( op->o_threadctx, (void *)search_stack,
|
|
- &ret, NULL );
|
|
- } else {
|
|
- ret = bdb->bi_search_stack;
|
|
- }
|
|
-
|
|
- if ( !ret ) {
|
|
- ret = ch_malloc( bdb->bi_search_stack_depth * BDB_IDL_UM_SIZE
|
|
- * sizeof( ID ) );
|
|
- if ( op->o_threadctx ) {
|
|
- ldap_pvt_thread_pool_setkey( op->o_threadctx, (void *)search_stack,
|
|
- ret, search_stack_free, NULL, NULL );
|
|
- } else {
|
|
- bdb->bi_search_stack = ret;
|
|
- }
|
|
- }
|
|
- return ret;
|
|
-}
|
|
-
|
|
-static int search_candidates(
|
|
- Operation *op,
|
|
- SlapReply *rs,
|
|
- Entry *e,
|
|
- DB_TXN *txn,
|
|
- ID *ids,
|
|
- ID *scopes )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
- int rc, depth = 1;
|
|
- Filter f, rf, xf, nf;
|
|
- ID *stack;
|
|
- AttributeAssertion aa_ref = ATTRIBUTEASSERTION_INIT;
|
|
- Filter sf;
|
|
- AttributeAssertion aa_subentry = ATTRIBUTEASSERTION_INIT;
|
|
-
|
|
- /*
|
|
- * This routine takes as input a filter (user-filter)
|
|
- * and rewrites it as follows:
|
|
- * (&(scope=DN)[(objectClass=subentry)]
|
|
- * (|[(objectClass=referral)(objectClass=alias)](user-filter))
|
|
- */
|
|
-
|
|
- Debug(LDAP_DEBUG_TRACE,
|
|
- "search_candidates: base=\"%s\" (0x%08lx) scope=%d\n",
|
|
- e->e_nname.bv_val, (long) e->e_id, op->oq_search.rs_scope );
|
|
-
|
|
- xf.f_or = op->oq_search.rs_filter;
|
|
- xf.f_choice = LDAP_FILTER_OR;
|
|
- xf.f_next = NULL;
|
|
-
|
|
- /* If the user's filter uses objectClass=*,
|
|
- * these clauses are redundant.
|
|
- */
|
|
- if (!oc_filter(op->oq_search.rs_filter, 1, &depth)
|
|
- && !get_subentries_visibility(op)) {
|
|
- if( !get_manageDSAit(op) && !get_domainScope(op) ) {
|
|
- /* match referral objects */
|
|
- struct berval bv_ref = BER_BVC( "referral" );
|
|
- rf.f_choice = LDAP_FILTER_EQUALITY;
|
|
- rf.f_ava = &aa_ref;
|
|
- rf.f_av_desc = slap_schema.si_ad_objectClass;
|
|
- rf.f_av_value = bv_ref;
|
|
- rf.f_next = xf.f_or;
|
|
- xf.f_or = &rf;
|
|
- depth++;
|
|
- }
|
|
- }
|
|
-
|
|
- f.f_next = NULL;
|
|
- f.f_choice = LDAP_FILTER_AND;
|
|
- f.f_and = &nf;
|
|
- /* Dummy; we compute scope separately now */
|
|
- nf.f_choice = SLAPD_FILTER_COMPUTED;
|
|
- nf.f_result = LDAP_SUCCESS;
|
|
- nf.f_next = ( xf.f_or == op->oq_search.rs_filter )
|
|
- ? op->oq_search.rs_filter : &xf ;
|
|
- /* Filter depth increased again, adding dummy clause */
|
|
- depth++;
|
|
-
|
|
- if( get_subentries_visibility( op ) ) {
|
|
- struct berval bv_subentry = BER_BVC( "subentry" );
|
|
- sf.f_choice = LDAP_FILTER_EQUALITY;
|
|
- sf.f_ava = &aa_subentry;
|
|
- sf.f_av_desc = slap_schema.si_ad_objectClass;
|
|
- sf.f_av_value = bv_subentry;
|
|
- sf.f_next = nf.f_next;
|
|
- nf.f_next = &sf;
|
|
- }
|
|
-
|
|
- /* Allocate IDL stack, plus 1 more for former tmp */
|
|
- if ( depth+1 > bdb->bi_search_stack_depth ) {
|
|
- stack = ch_malloc( (depth + 1) * BDB_IDL_UM_SIZE * sizeof( ID ) );
|
|
- } else {
|
|
- stack = search_stack( op );
|
|
- }
|
|
-
|
|
- if( op->ors_deref & LDAP_DEREF_SEARCHING ) {
|
|
- rc = search_aliases( op, rs, e, txn, ids, scopes, stack );
|
|
- if ( BDB_IDL_IS_ZERO( ids ) && rc == LDAP_SUCCESS )
|
|
- rc = bdb_dn2idl( op, txn, &e->e_nname, BEI(e), ids, stack );
|
|
- } else {
|
|
- rc = bdb_dn2idl( op, txn, &e->e_nname, BEI(e), ids, stack );
|
|
- }
|
|
-
|
|
- if ( rc == LDAP_SUCCESS ) {
|
|
- rc = bdb_filter_candidates( op, txn, &f, ids,
|
|
- stack, stack+BDB_IDL_UM_SIZE );
|
|
- }
|
|
-
|
|
- if ( depth+1 > bdb->bi_search_stack_depth ) {
|
|
- ch_free( stack );
|
|
- }
|
|
-
|
|
- if( rc ) {
|
|
- Debug(LDAP_DEBUG_TRACE,
|
|
- "bdb_search_candidates: failed (rc=%d)\n",
|
|
- rc, NULL, NULL );
|
|
-
|
|
- } else {
|
|
- Debug(LDAP_DEBUG_TRACE,
|
|
- "bdb_search_candidates: id=%ld first=%ld last=%ld\n",
|
|
- (long) ids[0],
|
|
- (long) BDB_IDL_FIRST(ids),
|
|
- (long) BDB_IDL_LAST(ids) );
|
|
- }
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static int
|
|
-parse_paged_cookie( Operation *op, SlapReply *rs )
|
|
-{
|
|
- int rc = LDAP_SUCCESS;
|
|
- PagedResultsState *ps = op->o_pagedresults_state;
|
|
-
|
|
- /* this function must be invoked only if the pagedResults
|
|
- * control has been detected, parsed and partially checked
|
|
- * by the frontend */
|
|
- assert( get_pagedresults( op ) > SLAP_CONTROL_IGNORED );
|
|
-
|
|
- /* cookie decoding/checks deferred to backend... */
|
|
- if ( ps->ps_cookieval.bv_len ) {
|
|
- PagedResultsCookie reqcookie;
|
|
- if( ps->ps_cookieval.bv_len != sizeof( reqcookie ) ) {
|
|
- /* bad cookie */
|
|
- rs->sr_text = "paged results cookie is invalid";
|
|
- rc = LDAP_PROTOCOL_ERROR;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- AC_MEMCPY( &reqcookie, ps->ps_cookieval.bv_val, sizeof( reqcookie ));
|
|
-
|
|
- if ( reqcookie > ps->ps_cookie ) {
|
|
- /* bad cookie */
|
|
- rs->sr_text = "paged results cookie is invalid";
|
|
- rc = LDAP_PROTOCOL_ERROR;
|
|
- goto done;
|
|
-
|
|
- } else if ( reqcookie < ps->ps_cookie ) {
|
|
- rs->sr_text = "paged results cookie is invalid or old";
|
|
- rc = LDAP_UNWILLING_TO_PERFORM;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- } else {
|
|
- /* we're going to use ps_cookie */
|
|
- op->o_conn->c_pagedresults_state.ps_cookie = 0;
|
|
- }
|
|
-
|
|
-done:;
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static void
|
|
-send_paged_response(
|
|
- Operation *op,
|
|
- SlapReply *rs,
|
|
- ID *lastid,
|
|
- int tentries )
|
|
-{
|
|
- LDAPControl *ctrls[2];
|
|
- BerElementBuffer berbuf;
|
|
- BerElement *ber = (BerElement *)&berbuf;
|
|
- PagedResultsCookie respcookie;
|
|
- struct berval cookie;
|
|
-
|
|
- Debug(LDAP_DEBUG_ARGS,
|
|
- "send_paged_response: lastid=0x%08lx nentries=%d\n",
|
|
- lastid ? *lastid : 0, rs->sr_nentries, NULL );
|
|
-
|
|
- ctrls[1] = NULL;
|
|
-
|
|
- ber_init2( ber, NULL, LBER_USE_DER );
|
|
-
|
|
- if ( lastid ) {
|
|
- respcookie = ( PagedResultsCookie )(*lastid);
|
|
- cookie.bv_len = sizeof( respcookie );
|
|
- cookie.bv_val = (char *)&respcookie;
|
|
-
|
|
- } else {
|
|
- respcookie = ( PagedResultsCookie )0;
|
|
- BER_BVSTR( &cookie, "" );
|
|
- }
|
|
-
|
|
- op->o_conn->c_pagedresults_state.ps_cookie = respcookie;
|
|
- op->o_conn->c_pagedresults_state.ps_count =
|
|
- ((PagedResultsState *)op->o_pagedresults_state)->ps_count +
|
|
- rs->sr_nentries;
|
|
-
|
|
- /* return size of 0 -- no estimate */
|
|
- ber_printf( ber, "{iO}", 0, &cookie );
|
|
-
|
|
- ctrls[0] = op->o_tmpalloc( sizeof(LDAPControl), op->o_tmpmemctx );
|
|
- if ( ber_flatten2( ber, &ctrls[0]->ldctl_value, 0 ) == -1 ) {
|
|
- goto done;
|
|
- }
|
|
-
|
|
- ctrls[0]->ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
|
|
- ctrls[0]->ldctl_iscritical = 0;
|
|
-
|
|
- slap_add_ctrls( op, rs, ctrls );
|
|
- rs->sr_err = LDAP_SUCCESS;
|
|
- send_ldap_result( op, rs );
|
|
-
|
|
-done:
|
|
- (void) ber_free_buf( ber );
|
|
-}
|
|
diff --git a/servers/slapd/back-bdb/tools.c b/servers/slapd/back-bdb/tools.c
|
|
deleted file mode 100644
|
|
index 1882ef2..0000000
|
|
--- a/servers/slapd/back-bdb/tools.c
|
|
+++ /dev/null
|
|
@@ -1,1327 +0,0 @@
|
|
-/* tools.c - tools for slap tools */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-
|
|
-#include <stdio.h>
|
|
-#include <ac/string.h>
|
|
-#include <ac/errno.h>
|
|
-
|
|
-#define AVL_INTERNAL
|
|
-#include "back-bdb.h"
|
|
-#include "idl.h"
|
|
-
|
|
-static DBC *cursor = NULL;
|
|
-static DBT key, data;
|
|
-static EntryHeader eh;
|
|
-static ID nid, previd = NOID;
|
|
-static char ehbuf[16];
|
|
-
|
|
-typedef struct dn_id {
|
|
- ID id;
|
|
- struct berval dn;
|
|
-} dn_id;
|
|
-
|
|
-#define HOLE_SIZE 4096
|
|
-static dn_id hbuf[HOLE_SIZE], *holes = hbuf;
|
|
-static unsigned nhmax = HOLE_SIZE;
|
|
-static unsigned nholes;
|
|
-
|
|
-static int index_nattrs;
|
|
-
|
|
-static struct berval *tool_base;
|
|
-static int tool_scope;
|
|
-static Filter *tool_filter;
|
|
-static Entry *tool_next_entry;
|
|
-
|
|
-#ifdef BDB_TOOL_IDL_CACHING
|
|
-#define bdb_tool_idl_cmp BDB_SYMBOL(tool_idl_cmp)
|
|
-#define bdb_tool_idl_flush_one BDB_SYMBOL(tool_idl_flush_one)
|
|
-#define bdb_tool_idl_flush BDB_SYMBOL(tool_idl_flush)
|
|
-
|
|
-static int bdb_tool_idl_flush( BackendDB *be );
|
|
-
|
|
-#define IDBLOCK 1024
|
|
-
|
|
-typedef struct bdb_tool_idl_cache_entry {
|
|
- struct bdb_tool_idl_cache_entry *next;
|
|
- ID ids[IDBLOCK];
|
|
-} bdb_tool_idl_cache_entry;
|
|
-
|
|
-typedef struct bdb_tool_idl_cache {
|
|
- struct berval kstr;
|
|
- bdb_tool_idl_cache_entry *head, *tail;
|
|
- ID first, last;
|
|
- int count;
|
|
-} bdb_tool_idl_cache;
|
|
-
|
|
-static bdb_tool_idl_cache_entry *bdb_tool_idl_free_list;
|
|
-#endif /* BDB_TOOL_IDL_CACHING */
|
|
-
|
|
-static ID bdb_tool_ix_id;
|
|
-static Operation *bdb_tool_ix_op;
|
|
-static int *bdb_tool_index_threads, bdb_tool_index_tcount;
|
|
-static void *bdb_tool_index_rec;
|
|
-static struct bdb_info *bdb_tool_info;
|
|
-static ldap_pvt_thread_mutex_t bdb_tool_index_mutex;
|
|
-static ldap_pvt_thread_cond_t bdb_tool_index_cond_main;
|
|
-static ldap_pvt_thread_cond_t bdb_tool_index_cond_work;
|
|
-
|
|
-#if DB_VERSION_FULL >= 0x04060000
|
|
-#define USE_TRICKLE 1
|
|
-#else
|
|
-/* Seems to slow things down too much in BDB 4.5 */
|
|
-#undef USE_TRICKLE
|
|
-#endif
|
|
-
|
|
-#ifdef USE_TRICKLE
|
|
-static ldap_pvt_thread_mutex_t bdb_tool_trickle_mutex;
|
|
-static ldap_pvt_thread_cond_t bdb_tool_trickle_cond;
|
|
-static ldap_pvt_thread_cond_t bdb_tool_trickle_cond_end;
|
|
-
|
|
-static void * bdb_tool_trickle_task( void *ctx, void *ptr );
|
|
-static int bdb_tool_trickle_active;
|
|
-#endif
|
|
-
|
|
-static void * bdb_tool_index_task( void *ctx, void *ptr );
|
|
-
|
|
-static int
|
|
-bdb_tool_entry_get_int( BackendDB *be, ID id, Entry **ep );
|
|
-
|
|
-static int bdb_tool_threads;
|
|
-
|
|
-int bdb_tool_entry_open(
|
|
- BackendDB *be, int mode )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
|
-
|
|
- /* initialize key and data thangs */
|
|
- DBTzero( &key );
|
|
- DBTzero( &data );
|
|
- key.flags = DB_DBT_USERMEM;
|
|
- key.data = &nid;
|
|
- key.size = key.ulen = sizeof( nid );
|
|
- data.flags = DB_DBT_USERMEM;
|
|
-
|
|
- if (cursor == NULL) {
|
|
- int rc = bdb->bi_id2entry->bdi_db->cursor(
|
|
- bdb->bi_id2entry->bdi_db, bdb->bi_cache.c_txn, &cursor,
|
|
- bdb->bi_db_opflags );
|
|
- if( rc != 0 ) {
|
|
- return -1;
|
|
- }
|
|
- }
|
|
-
|
|
- /* Set up for threaded slapindex */
|
|
- if (( slapMode & (SLAP_TOOL_QUICK|SLAP_TOOL_READONLY)) == SLAP_TOOL_QUICK ) {
|
|
- if ( !bdb_tool_info ) {
|
|
-#ifdef USE_TRICKLE
|
|
- ldap_pvt_thread_mutex_init( &bdb_tool_trickle_mutex );
|
|
- ldap_pvt_thread_cond_init( &bdb_tool_trickle_cond );
|
|
- ldap_pvt_thread_cond_init( &bdb_tool_trickle_cond_end );
|
|
- ldap_pvt_thread_pool_submit( &connection_pool, bdb_tool_trickle_task, bdb->bi_dbenv );
|
|
-#endif
|
|
-
|
|
- ldap_pvt_thread_mutex_init( &bdb_tool_index_mutex );
|
|
- ldap_pvt_thread_cond_init( &bdb_tool_index_cond_main );
|
|
- ldap_pvt_thread_cond_init( &bdb_tool_index_cond_work );
|
|
- if ( bdb->bi_nattrs ) {
|
|
- int i;
|
|
- bdb_tool_threads = slap_tool_thread_max - 1;
|
|
- if ( bdb_tool_threads > 1 ) {
|
|
- bdb_tool_index_threads = ch_malloc( bdb_tool_threads * sizeof( int ));
|
|
- bdb_tool_index_rec = ch_malloc( bdb->bi_nattrs * sizeof( IndexRec ));
|
|
- bdb_tool_index_tcount = bdb_tool_threads - 1;
|
|
- for (i=1; i<bdb_tool_threads; i++) {
|
|
- int *ptr = ch_malloc( sizeof( int ));
|
|
- *ptr = i;
|
|
- ldap_pvt_thread_pool_submit( &connection_pool,
|
|
- bdb_tool_index_task, ptr );
|
|
- }
|
|
- }
|
|
- }
|
|
- bdb_tool_info = bdb;
|
|
- }
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-int bdb_tool_entry_close(
|
|
- BackendDB *be )
|
|
-{
|
|
- if ( bdb_tool_info ) {
|
|
- slapd_shutdown = 1;
|
|
-#ifdef USE_TRICKLE
|
|
- ldap_pvt_thread_mutex_lock( &bdb_tool_trickle_mutex );
|
|
-
|
|
- /* trickle thread may not have started yet */
|
|
- while ( !bdb_tool_trickle_active )
|
|
- ldap_pvt_thread_cond_wait( &bdb_tool_trickle_cond_end,
|
|
- &bdb_tool_trickle_mutex );
|
|
-
|
|
- ldap_pvt_thread_cond_signal( &bdb_tool_trickle_cond );
|
|
- while ( bdb_tool_trickle_active )
|
|
- ldap_pvt_thread_cond_wait( &bdb_tool_trickle_cond_end,
|
|
- &bdb_tool_trickle_mutex );
|
|
- ldap_pvt_thread_mutex_unlock( &bdb_tool_trickle_mutex );
|
|
-#endif
|
|
- if ( bdb_tool_threads > 1 ) {
|
|
- ldap_pvt_thread_mutex_lock( &bdb_tool_index_mutex );
|
|
-
|
|
- /* There might still be some threads starting */
|
|
- while ( bdb_tool_index_tcount > 0 ) {
|
|
- ldap_pvt_thread_cond_wait( &bdb_tool_index_cond_main,
|
|
- &bdb_tool_index_mutex );
|
|
- }
|
|
-
|
|
- bdb_tool_index_tcount = bdb_tool_threads - 1;
|
|
- ldap_pvt_thread_cond_broadcast( &bdb_tool_index_cond_work );
|
|
-
|
|
- /* Make sure all threads are stopped */
|
|
- while ( bdb_tool_index_tcount > 0 ) {
|
|
- ldap_pvt_thread_cond_wait( &bdb_tool_index_cond_main,
|
|
- &bdb_tool_index_mutex );
|
|
- }
|
|
- ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex );
|
|
-
|
|
- ch_free( bdb_tool_index_threads );
|
|
- ch_free( bdb_tool_index_rec );
|
|
- bdb_tool_index_tcount = bdb_tool_threads - 1;
|
|
- }
|
|
- bdb_tool_info = NULL;
|
|
- slapd_shutdown = 0;
|
|
- }
|
|
-
|
|
- if( eh.bv.bv_val ) {
|
|
- ch_free( eh.bv.bv_val );
|
|
- eh.bv.bv_val = NULL;
|
|
- }
|
|
-
|
|
- if( cursor ) {
|
|
- cursor->c_close( cursor );
|
|
- cursor = NULL;
|
|
- }
|
|
-
|
|
-#ifdef BDB_TOOL_IDL_CACHING
|
|
- bdb_tool_idl_flush( be );
|
|
-#endif
|
|
-
|
|
- if( nholes ) {
|
|
- unsigned i;
|
|
- fprintf( stderr, "Error, entries missing!\n");
|
|
- for (i=0; i<nholes; i++) {
|
|
- fprintf(stderr, " entry %ld: %s\n",
|
|
- holes[i].id, holes[i].dn.bv_val);
|
|
- }
|
|
- return -1;
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-ID
|
|
-bdb_tool_entry_first_x(
|
|
- BackendDB *be,
|
|
- struct berval *base,
|
|
- int scope,
|
|
- Filter *f )
|
|
-{
|
|
- tool_base = base;
|
|
- tool_scope = scope;
|
|
- tool_filter = f;
|
|
-
|
|
- return bdb_tool_entry_next( be );
|
|
-}
|
|
-
|
|
-ID bdb_tool_entry_next(
|
|
- BackendDB *be )
|
|
-{
|
|
- int rc;
|
|
- ID id;
|
|
- struct bdb_info *bdb;
|
|
-
|
|
- assert( be != NULL );
|
|
- assert( slapMode & SLAP_TOOL_MODE );
|
|
-
|
|
- bdb = (struct bdb_info *) be->be_private;
|
|
- assert( bdb != NULL );
|
|
-
|
|
-next:;
|
|
- /* Get the header */
|
|
- data.ulen = data.dlen = sizeof( ehbuf );
|
|
- data.data = ehbuf;
|
|
- data.flags |= DB_DBT_PARTIAL;
|
|
- rc = cursor->c_get( cursor, &key, &data, DB_NEXT );
|
|
-
|
|
- if( rc ) {
|
|
- /* If we're doing linear indexing and there are more attrs to
|
|
- * index, and we're at the end of the database, start over.
|
|
- */
|
|
- if ( index_nattrs && rc == DB_NOTFOUND ) {
|
|
- /* optional - do a checkpoint here? */
|
|
- bdb_attr_info_free( bdb->bi_attrs[0] );
|
|
- bdb->bi_attrs[0] = bdb->bi_attrs[index_nattrs];
|
|
- index_nattrs--;
|
|
- rc = cursor->c_get( cursor, &key, &data, DB_FIRST );
|
|
- if ( rc ) {
|
|
- return NOID;
|
|
- }
|
|
- } else {
|
|
- return NOID;
|
|
- }
|
|
- }
|
|
-
|
|
- BDB_DISK2ID( key.data, &id );
|
|
- previd = id;
|
|
-
|
|
- if ( tool_filter || tool_base ) {
|
|
- static Operation op = {0};
|
|
- static Opheader ohdr = {0};
|
|
-
|
|
- op.o_hdr = &ohdr;
|
|
- op.o_bd = be;
|
|
- op.o_tmpmemctx = NULL;
|
|
- op.o_tmpmfuncs = &ch_mfuncs;
|
|
-
|
|
- if ( tool_next_entry ) {
|
|
- bdb_entry_release( &op, tool_next_entry, 0 );
|
|
- tool_next_entry = NULL;
|
|
- }
|
|
-
|
|
- rc = bdb_tool_entry_get_int( be, id, &tool_next_entry );
|
|
- if ( rc == LDAP_NO_SUCH_OBJECT ) {
|
|
- goto next;
|
|
- }
|
|
-
|
|
- assert( tool_next_entry != NULL );
|
|
-
|
|
-#ifdef BDB_HIER
|
|
- /* TODO: needed until BDB_HIER is handled accordingly
|
|
- * in bdb_tool_entry_get_int() */
|
|
- if ( tool_base && !dnIsSuffixScope( &tool_next_entry->e_nname, tool_base, tool_scope ) )
|
|
- {
|
|
- bdb_entry_release( &op, tool_next_entry, 0 );
|
|
- tool_next_entry = NULL;
|
|
- goto next;
|
|
- }
|
|
-#endif
|
|
-
|
|
- if ( tool_filter && test_filter( NULL, tool_next_entry, tool_filter ) != LDAP_COMPARE_TRUE )
|
|
- {
|
|
- bdb_entry_release( &op, tool_next_entry, 0 );
|
|
- tool_next_entry = NULL;
|
|
- goto next;
|
|
- }
|
|
- }
|
|
-
|
|
- return id;
|
|
-}
|
|
-
|
|
-ID bdb_tool_dn2id_get(
|
|
- Backend *be,
|
|
- struct berval *dn
|
|
-)
|
|
-{
|
|
- Operation op = {0};
|
|
- Opheader ohdr = {0};
|
|
- EntryInfo *ei = NULL;
|
|
- int rc;
|
|
-
|
|
- if ( BER_BVISEMPTY(dn) )
|
|
- return 0;
|
|
-
|
|
- op.o_hdr = &ohdr;
|
|
- op.o_bd = be;
|
|
- op.o_tmpmemctx = NULL;
|
|
- op.o_tmpmfuncs = &ch_mfuncs;
|
|
-
|
|
- rc = bdb_cache_find_ndn( &op, 0, dn, &ei );
|
|
- if ( ei ) bdb_cache_entryinfo_unlock( ei );
|
|
- if ( rc == DB_NOTFOUND )
|
|
- return NOID;
|
|
-
|
|
- return ei->bei_id;
|
|
-}
|
|
-
|
|
-static int
|
|
-bdb_tool_entry_get_int( BackendDB *be, ID id, Entry **ep )
|
|
-{
|
|
- Entry *e = NULL;
|
|
- char *dptr;
|
|
- int rc, eoff;
|
|
-
|
|
- assert( be != NULL );
|
|
- assert( slapMode & SLAP_TOOL_MODE );
|
|
-
|
|
- if ( ( tool_filter || tool_base ) && id == previd && tool_next_entry != NULL ) {
|
|
- *ep = tool_next_entry;
|
|
- tool_next_entry = NULL;
|
|
- return LDAP_SUCCESS;
|
|
- }
|
|
-
|
|
- if ( id != previd ) {
|
|
- data.ulen = data.dlen = sizeof( ehbuf );
|
|
- data.data = ehbuf;
|
|
- data.flags |= DB_DBT_PARTIAL;
|
|
-
|
|
- BDB_ID2DISK( id, &nid );
|
|
- rc = cursor->c_get( cursor, &key, &data, DB_SET );
|
|
- if ( rc ) {
|
|
- rc = LDAP_OTHER;
|
|
- goto done;
|
|
- }
|
|
- }
|
|
-
|
|
- /* Get the header */
|
|
- dptr = eh.bv.bv_val;
|
|
- eh.bv.bv_val = ehbuf;
|
|
- eh.bv.bv_len = data.size;
|
|
- rc = entry_header( &eh );
|
|
- eoff = eh.data - eh.bv.bv_val;
|
|
- eh.bv.bv_val = dptr;
|
|
- if ( rc ) {
|
|
- rc = LDAP_OTHER;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- /* Get the size */
|
|
- data.flags &= ~DB_DBT_PARTIAL;
|
|
- data.ulen = 0;
|
|
- rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
|
|
- if ( rc != DB_BUFFER_SMALL ) {
|
|
- rc = LDAP_OTHER;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- /* Allocate a block and retrieve the data */
|
|
- eh.bv.bv_len = eh.nvals * sizeof( struct berval ) + data.size;
|
|
- eh.bv.bv_val = ch_realloc( eh.bv.bv_val, eh.bv.bv_len );
|
|
- eh.data = eh.bv.bv_val + eh.nvals * sizeof( struct berval );
|
|
- data.data = eh.data;
|
|
- data.ulen = data.size;
|
|
-
|
|
- /* Skip past already parsed nattr/nvals */
|
|
- eh.data += eoff;
|
|
-
|
|
- rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
|
|
- if ( rc ) {
|
|
- rc = LDAP_OTHER;
|
|
- goto done;
|
|
- }
|
|
-
|
|
-#ifndef BDB_HIER
|
|
- /* TODO: handle BDB_HIER accordingly */
|
|
- if ( tool_base != NULL ) {
|
|
- struct berval ndn;
|
|
- entry_decode_dn( &eh, NULL, &ndn );
|
|
-
|
|
- if ( !dnIsSuffixScope( &ndn, tool_base, tool_scope ) ) {
|
|
- return LDAP_NO_SUCH_OBJECT;
|
|
- }
|
|
- }
|
|
-#endif
|
|
-
|
|
-#ifdef SLAP_ZONE_ALLOC
|
|
- /* FIXME: will add ctx later */
|
|
- rc = entry_decode( &eh, &e, NULL );
|
|
-#else
|
|
- rc = entry_decode( &eh, &e );
|
|
-#endif
|
|
-
|
|
- if( rc == LDAP_SUCCESS ) {
|
|
- e->e_id = id;
|
|
-#ifdef BDB_HIER
|
|
- if ( slapMode & SLAP_TOOL_READONLY ) {
|
|
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
|
- EntryInfo *ei = NULL;
|
|
- Operation op = {0};
|
|
- Opheader ohdr = {0};
|
|
-
|
|
- op.o_hdr = &ohdr;
|
|
- op.o_bd = be;
|
|
- op.o_tmpmemctx = NULL;
|
|
- op.o_tmpmfuncs = &ch_mfuncs;
|
|
-
|
|
- rc = bdb_cache_find_parent( &op, bdb->bi_cache.c_txn, id, &ei );
|
|
- if ( rc == LDAP_SUCCESS ) {
|
|
- bdb_cache_entryinfo_unlock( ei );
|
|
- e->e_private = ei;
|
|
- ei->bei_e = e;
|
|
- bdb_fix_dn( e, 0 );
|
|
- ei->bei_e = NULL;
|
|
- e->e_private = NULL;
|
|
- }
|
|
- }
|
|
-#endif
|
|
- }
|
|
-done:
|
|
- if ( e != NULL ) {
|
|
- *ep = e;
|
|
- }
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-Entry*
|
|
-bdb_tool_entry_get( BackendDB *be, ID id )
|
|
-{
|
|
- Entry *e = NULL;
|
|
-
|
|
- (void)bdb_tool_entry_get_int( be, id, &e );
|
|
- return e;
|
|
-}
|
|
-
|
|
-static int bdb_tool_next_id(
|
|
- Operation *op,
|
|
- DB_TXN *tid,
|
|
- Entry *e,
|
|
- struct berval *text,
|
|
- int hole )
|
|
-{
|
|
- struct berval dn = e->e_name;
|
|
- struct berval ndn = e->e_nname;
|
|
- struct berval pdn, npdn;
|
|
- EntryInfo *ei = NULL, eidummy;
|
|
- int rc;
|
|
-
|
|
- if (ndn.bv_len == 0) {
|
|
- e->e_id = 0;
|
|
- return 0;
|
|
- }
|
|
-
|
|
- rc = bdb_cache_find_ndn( op, tid, &ndn, &ei );
|
|
- if ( ei ) bdb_cache_entryinfo_unlock( ei );
|
|
- if ( rc == DB_NOTFOUND ) {
|
|
- if ( !be_issuffix( op->o_bd, &ndn ) ) {
|
|
- ID eid = e->e_id;
|
|
- dnParent( &dn, &pdn );
|
|
- dnParent( &ndn, &npdn );
|
|
- e->e_name = pdn;
|
|
- e->e_nname = npdn;
|
|
- rc = bdb_tool_next_id( op, tid, e, text, 1 );
|
|
- e->e_name = dn;
|
|
- e->e_nname = ndn;
|
|
- if ( rc ) {
|
|
- return rc;
|
|
- }
|
|
- /* If parent didn't exist, it was created just now
|
|
- * and its ID is now in e->e_id. Make sure the current
|
|
- * entry gets added under the new parent ID.
|
|
- */
|
|
- if ( eid != e->e_id ) {
|
|
- eidummy.bei_id = e->e_id;
|
|
- ei = &eidummy;
|
|
- }
|
|
- }
|
|
- rc = bdb_next_id( op->o_bd, &e->e_id );
|
|
- if ( rc ) {
|
|
- snprintf( text->bv_val, text->bv_len,
|
|
- "next_id failed: %s (%d)",
|
|
- db_strerror(rc), rc );
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "=> bdb_tool_next_id: %s\n", text->bv_val, 0, 0 );
|
|
- return rc;
|
|
- }
|
|
- rc = bdb_dn2id_add( op, tid, ei, e );
|
|
- if ( rc ) {
|
|
- snprintf( text->bv_val, text->bv_len,
|
|
- "dn2id_add failed: %s (%d)",
|
|
- db_strerror(rc), rc );
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "=> bdb_tool_next_id: %s\n", text->bv_val, 0, 0 );
|
|
- } else if ( hole ) {
|
|
- if ( nholes == nhmax - 1 ) {
|
|
- if ( holes == hbuf ) {
|
|
- holes = ch_malloc( nhmax * sizeof(dn_id) * 2 );
|
|
- AC_MEMCPY( holes, hbuf, sizeof(hbuf) );
|
|
- } else {
|
|
- holes = ch_realloc( holes, nhmax * sizeof(dn_id) * 2 );
|
|
- }
|
|
- nhmax *= 2;
|
|
- }
|
|
- ber_dupbv( &holes[nholes].dn, &ndn );
|
|
- holes[nholes++].id = e->e_id;
|
|
- }
|
|
- } else if ( !hole ) {
|
|
- unsigned i, j;
|
|
-
|
|
- e->e_id = ei->bei_id;
|
|
-
|
|
- for ( i=0; i<nholes; i++) {
|
|
- if ( holes[i].id == e->e_id ) {
|
|
- free(holes[i].dn.bv_val);
|
|
- for (j=i;j<nholes;j++) holes[j] = holes[j+1];
|
|
- holes[j].id = 0;
|
|
- nholes--;
|
|
- break;
|
|
- } else if ( holes[i].id > e->e_id ) {
|
|
- break;
|
|
- }
|
|
- }
|
|
- }
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static int
|
|
-bdb_tool_index_add(
|
|
- Operation *op,
|
|
- DB_TXN *txn,
|
|
- Entry *e )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
|
-
|
|
- if ( !bdb->bi_nattrs )
|
|
- return 0;
|
|
-
|
|
- if ( bdb_tool_threads > 1 ) {
|
|
- IndexRec *ir;
|
|
- int i, rc;
|
|
- Attribute *a;
|
|
-
|
|
- ir = bdb_tool_index_rec;
|
|
- memset(ir, 0, bdb->bi_nattrs * sizeof( IndexRec ));
|
|
-
|
|
- for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
|
|
- rc = bdb_index_recset( bdb, a, a->a_desc->ad_type,
|
|
- &a->a_desc->ad_tags, ir );
|
|
- if ( rc )
|
|
- return rc;
|
|
- }
|
|
- bdb_tool_ix_id = e->e_id;
|
|
- bdb_tool_ix_op = op;
|
|
- ldap_pvt_thread_mutex_lock( &bdb_tool_index_mutex );
|
|
- /* Wait for all threads to be ready */
|
|
- while ( bdb_tool_index_tcount > 0 ) {
|
|
- ldap_pvt_thread_cond_wait( &bdb_tool_index_cond_main,
|
|
- &bdb_tool_index_mutex );
|
|
- }
|
|
- for ( i=1; i<bdb_tool_threads; i++ )
|
|
- bdb_tool_index_threads[i] = LDAP_BUSY;
|
|
- bdb_tool_index_tcount = bdb_tool_threads - 1;
|
|
- ldap_pvt_thread_cond_broadcast( &bdb_tool_index_cond_work );
|
|
- ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex );
|
|
- rc = bdb_index_recrun( op, bdb, ir, e->e_id, 0 );
|
|
- if ( rc )
|
|
- return rc;
|
|
- ldap_pvt_thread_mutex_lock( &bdb_tool_index_mutex );
|
|
- for ( i=1; i<bdb_tool_threads; i++ ) {
|
|
- if ( bdb_tool_index_threads[i] == LDAP_BUSY ) {
|
|
- ldap_pvt_thread_cond_wait( &bdb_tool_index_cond_main,
|
|
- &bdb_tool_index_mutex );
|
|
- i--;
|
|
- continue;
|
|
- }
|
|
- if ( bdb_tool_index_threads[i] ) {
|
|
- rc = bdb_tool_index_threads[i];
|
|
- break;
|
|
- }
|
|
- }
|
|
- ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex );
|
|
- return rc;
|
|
- } else {
|
|
- return bdb_index_entry_add( op, txn, e );
|
|
- }
|
|
-}
|
|
-
|
|
-ID bdb_tool_entry_put(
|
|
- BackendDB *be,
|
|
- Entry *e,
|
|
- struct berval *text )
|
|
-{
|
|
- int rc;
|
|
- struct bdb_info *bdb;
|
|
- DB_TXN *tid = NULL;
|
|
- Operation op = {0};
|
|
- Opheader ohdr = {0};
|
|
-
|
|
- assert( be != NULL );
|
|
- assert( slapMode & SLAP_TOOL_MODE );
|
|
-
|
|
- assert( text != NULL );
|
|
- assert( text->bv_val != NULL );
|
|
- assert( text->bv_val[0] == '\0' ); /* overconservative? */
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "=> " LDAP_XSTRING(bdb_tool_entry_put)
|
|
- "( %ld, \"%s\" )\n", (long) e->e_id, e->e_dn, 0 );
|
|
-
|
|
- bdb = (struct bdb_info *) be->be_private;
|
|
-
|
|
- if (! (slapMode & SLAP_TOOL_QUICK)) {
|
|
- rc = TXN_BEGIN( bdb->bi_dbenv, NULL, &tid,
|
|
- bdb->bi_db_opflags );
|
|
- if( rc != 0 ) {
|
|
- snprintf( text->bv_val, text->bv_len,
|
|
- "txn_begin failed: %s (%d)",
|
|
- db_strerror(rc), rc );
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
|
|
- text->bv_val, 0, 0 );
|
|
- return NOID;
|
|
- }
|
|
- Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_tool_entry_put) ": txn id: %x\n",
|
|
- tid->id(tid), 0, 0 );
|
|
- }
|
|
-
|
|
- op.o_hdr = &ohdr;
|
|
- op.o_bd = be;
|
|
- op.o_tmpmemctx = NULL;
|
|
- op.o_tmpmfuncs = &ch_mfuncs;
|
|
-
|
|
- /* add dn2id indices */
|
|
- rc = bdb_tool_next_id( &op, tid, e, text, 0 );
|
|
- if( rc != 0 ) {
|
|
- goto done;
|
|
- }
|
|
-
|
|
-#ifdef USE_TRICKLE
|
|
- if (( slapMode & SLAP_TOOL_QUICK ) && (( e->e_id & 0xfff ) == 0xfff )) {
|
|
- ldap_pvt_thread_cond_signal( &bdb_tool_trickle_cond );
|
|
- }
|
|
-#endif
|
|
-
|
|
- if ( !bdb->bi_linear_index )
|
|
- rc = bdb_tool_index_add( &op, tid, e );
|
|
- if( rc != 0 ) {
|
|
- snprintf( text->bv_val, text->bv_len,
|
|
- "index_entry_add failed: %s (%d)",
|
|
- rc == LDAP_OTHER ? "Internal error" :
|
|
- db_strerror(rc), rc );
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
|
|
- text->bv_val, 0, 0 );
|
|
- goto done;
|
|
- }
|
|
-
|
|
- /* id2entry index */
|
|
- rc = bdb_id2entry_add( be, tid, e );
|
|
- if( rc != 0 ) {
|
|
- snprintf( text->bv_val, text->bv_len,
|
|
- "id2entry_add failed: %s (%d)",
|
|
- db_strerror(rc), rc );
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
|
|
- text->bv_val, 0, 0 );
|
|
- goto done;
|
|
- }
|
|
-
|
|
-done:
|
|
- if( rc == 0 ) {
|
|
- if ( !( slapMode & SLAP_TOOL_QUICK )) {
|
|
- rc = TXN_COMMIT( tid, 0 );
|
|
- if( rc != 0 ) {
|
|
- snprintf( text->bv_val, text->bv_len,
|
|
- "txn_commit failed: %s (%d)",
|
|
- db_strerror(rc), rc );
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
|
|
- text->bv_val, 0, 0 );
|
|
- e->e_id = NOID;
|
|
- }
|
|
- }
|
|
-
|
|
- } else {
|
|
- if ( !( slapMode & SLAP_TOOL_QUICK )) {
|
|
- TXN_ABORT( tid );
|
|
- snprintf( text->bv_val, text->bv_len,
|
|
- "txn_aborted! %s (%d)",
|
|
- rc == LDAP_OTHER ? "Internal error" :
|
|
- db_strerror(rc), rc );
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
|
|
- text->bv_val, 0, 0 );
|
|
- }
|
|
- e->e_id = NOID;
|
|
- }
|
|
-
|
|
- return e->e_id;
|
|
-}
|
|
-
|
|
-int bdb_tool_entry_reindex(
|
|
- BackendDB *be,
|
|
- ID id,
|
|
- AttributeDescription **adv )
|
|
-{
|
|
- struct bdb_info *bi = (struct bdb_info *) be->be_private;
|
|
- int rc;
|
|
- Entry *e;
|
|
- DB_TXN *tid = NULL;
|
|
- Operation op = {0};
|
|
- Opheader ohdr = {0};
|
|
-
|
|
- Debug( LDAP_DEBUG_ARGS,
|
|
- "=> " LDAP_XSTRING(bdb_tool_entry_reindex) "( %ld )\n",
|
|
- (long) id, 0, 0 );
|
|
- assert( tool_base == NULL );
|
|
- assert( tool_filter == NULL );
|
|
-
|
|
- /* No indexes configured, nothing to do. Could return an
|
|
- * error here to shortcut things.
|
|
- */
|
|
- if (!bi->bi_attrs) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- /* Check for explicit list of attrs to index */
|
|
- if ( adv ) {
|
|
- int i, j, n;
|
|
-
|
|
- if ( bi->bi_attrs[0]->ai_desc != adv[0] ) {
|
|
- /* count */
|
|
- for ( n = 0; adv[n]; n++ ) ;
|
|
-
|
|
- /* insertion sort */
|
|
- for ( i = 0; i < n; i++ ) {
|
|
- AttributeDescription *ad = adv[i];
|
|
- for ( j = i-1; j>=0; j--) {
|
|
- if ( SLAP_PTRCMP( adv[j], ad ) <= 0 ) break;
|
|
- adv[j+1] = adv[j];
|
|
- }
|
|
- adv[j+1] = ad;
|
|
- }
|
|
- }
|
|
-
|
|
- for ( i = 0; adv[i]; i++ ) {
|
|
- if ( bi->bi_attrs[i]->ai_desc != adv[i] ) {
|
|
- for ( j = i+1; j < bi->bi_nattrs; j++ ) {
|
|
- if ( bi->bi_attrs[j]->ai_desc == adv[i] ) {
|
|
- AttrInfo *ai = bi->bi_attrs[i];
|
|
- bi->bi_attrs[i] = bi->bi_attrs[j];
|
|
- bi->bi_attrs[j] = ai;
|
|
- break;
|
|
- }
|
|
- }
|
|
- if ( j == bi->bi_nattrs ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- LDAP_XSTRING(bdb_tool_entry_reindex)
|
|
- ": no index configured for %s\n",
|
|
- adv[i]->ad_cname.bv_val, 0, 0 );
|
|
- return -1;
|
|
- }
|
|
- }
|
|
- }
|
|
- bi->bi_nattrs = i;
|
|
- }
|
|
-
|
|
- /* Get the first attribute to index */
|
|
- if (bi->bi_linear_index && !index_nattrs) {
|
|
- index_nattrs = bi->bi_nattrs - 1;
|
|
- bi->bi_nattrs = 1;
|
|
- }
|
|
-
|
|
- e = bdb_tool_entry_get( be, id );
|
|
-
|
|
- if( e == NULL ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- LDAP_XSTRING(bdb_tool_entry_reindex)
|
|
- ": could not locate id=%ld\n",
|
|
- (long) id, 0, 0 );
|
|
- return -1;
|
|
- }
|
|
-
|
|
- op.o_hdr = &ohdr;
|
|
- op.o_bd = be;
|
|
- op.o_tmpmemctx = NULL;
|
|
- op.o_tmpmfuncs = &ch_mfuncs;
|
|
-
|
|
- if (! (slapMode & SLAP_TOOL_QUICK)) {
|
|
- rc = TXN_BEGIN( bi->bi_dbenv, NULL, &tid, bi->bi_db_opflags );
|
|
- if( rc != 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "=> " LDAP_XSTRING(bdb_tool_entry_reindex) ": "
|
|
- "txn_begin failed: %s (%d)\n",
|
|
- db_strerror(rc), rc, 0 );
|
|
- goto done;
|
|
- }
|
|
- Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_tool_entry_reindex) ": txn id: %x\n",
|
|
- tid->id(tid), 0, 0 );
|
|
- }
|
|
-
|
|
- /*
|
|
- * just (re)add them for now
|
|
- * assume that some other routine (not yet implemented)
|
|
- * will zap index databases
|
|
- *
|
|
- */
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "=> " LDAP_XSTRING(bdb_tool_entry_reindex) "( %ld, \"%s\" )\n",
|
|
- (long) id, e->e_dn, 0 );
|
|
-
|
|
- rc = bdb_tool_index_add( &op, tid, e );
|
|
-
|
|
-done:
|
|
- if( rc == 0 ) {
|
|
- if (! (slapMode & SLAP_TOOL_QUICK)) {
|
|
- rc = TXN_COMMIT( tid, 0 );
|
|
- if( rc != 0 ) {
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "=> " LDAP_XSTRING(bdb_tool_entry_reindex)
|
|
- ": txn_commit failed: %s (%d)\n",
|
|
- db_strerror(rc), rc, 0 );
|
|
- e->e_id = NOID;
|
|
- }
|
|
- }
|
|
-
|
|
- } else {
|
|
- if (! (slapMode & SLAP_TOOL_QUICK)) {
|
|
- TXN_ABORT( tid );
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "=> " LDAP_XSTRING(bdb_tool_entry_reindex)
|
|
- ": txn_aborted! %s (%d)\n",
|
|
- db_strerror(rc), rc, 0 );
|
|
- }
|
|
- e->e_id = NOID;
|
|
- }
|
|
- bdb_entry_release( &op, e, 0 );
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-ID bdb_tool_entry_modify(
|
|
- BackendDB *be,
|
|
- Entry *e,
|
|
- struct berval *text )
|
|
-{
|
|
- int rc;
|
|
- struct bdb_info *bdb;
|
|
- DB_TXN *tid = NULL;
|
|
- Operation op = {0};
|
|
- Opheader ohdr = {0};
|
|
-
|
|
- assert( be != NULL );
|
|
- assert( slapMode & SLAP_TOOL_MODE );
|
|
-
|
|
- assert( text != NULL );
|
|
- assert( text->bv_val != NULL );
|
|
- assert( text->bv_val[0] == '\0' ); /* overconservative? */
|
|
-
|
|
- assert ( e->e_id != NOID );
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE,
|
|
- "=> " LDAP_XSTRING(bdb_tool_entry_modify) "( %ld, \"%s\" )\n",
|
|
- (long) e->e_id, e->e_dn, 0 );
|
|
-
|
|
- bdb = (struct bdb_info *) be->be_private;
|
|
-
|
|
- if (! (slapMode & SLAP_TOOL_QUICK)) {
|
|
- if( cursor ) {
|
|
- cursor->c_close( cursor );
|
|
- cursor = NULL;
|
|
- }
|
|
- rc = TXN_BEGIN( bdb->bi_dbenv, NULL, &tid,
|
|
- bdb->bi_db_opflags );
|
|
- if( rc != 0 ) {
|
|
- snprintf( text->bv_val, text->bv_len,
|
|
- "txn_begin failed: %s (%d)",
|
|
- db_strerror(rc), rc );
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
|
|
- text->bv_val, 0, 0 );
|
|
- return NOID;
|
|
- }
|
|
- Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_tool_entry_modify) ": txn id: %x\n",
|
|
- tid->id(tid), 0, 0 );
|
|
- }
|
|
-
|
|
- op.o_hdr = &ohdr;
|
|
- op.o_bd = be;
|
|
- op.o_tmpmemctx = NULL;
|
|
- op.o_tmpmfuncs = &ch_mfuncs;
|
|
-
|
|
- /* id2entry index */
|
|
- rc = bdb_id2entry_update( be, tid, e );
|
|
- if( rc != 0 ) {
|
|
- snprintf( text->bv_val, text->bv_len,
|
|
- "id2entry_add failed: %s (%d)",
|
|
- db_strerror(rc), rc );
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
|
|
- text->bv_val, 0, 0 );
|
|
- goto done;
|
|
- }
|
|
-
|
|
-done:
|
|
- if( rc == 0 ) {
|
|
- if (! (slapMode & SLAP_TOOL_QUICK)) {
|
|
- rc = TXN_COMMIT( tid, 0 );
|
|
- if( rc != 0 ) {
|
|
- snprintf( text->bv_val, text->bv_len,
|
|
- "txn_commit failed: %s (%d)",
|
|
- db_strerror(rc), rc );
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": "
|
|
- "%s\n", text->bv_val, 0, 0 );
|
|
- e->e_id = NOID;
|
|
- }
|
|
- }
|
|
-
|
|
- } else {
|
|
- if (! (slapMode & SLAP_TOOL_QUICK)) {
|
|
- TXN_ABORT( tid );
|
|
- snprintf( text->bv_val, text->bv_len,
|
|
- "txn_aborted! %s (%d)",
|
|
- db_strerror(rc), rc );
|
|
- Debug( LDAP_DEBUG_ANY,
|
|
- "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
|
|
- text->bv_val, 0, 0 );
|
|
- }
|
|
- e->e_id = NOID;
|
|
- }
|
|
-
|
|
- return e->e_id;
|
|
-}
|
|
-
|
|
-#ifdef BDB_TOOL_IDL_CACHING
|
|
-static int
|
|
-bdb_tool_idl_cmp( const void *v1, const void *v2 )
|
|
-{
|
|
- const bdb_tool_idl_cache *c1 = v1, *c2 = v2;
|
|
- int rc;
|
|
-
|
|
- if (( rc = c1->kstr.bv_len - c2->kstr.bv_len )) return rc;
|
|
- return memcmp( c1->kstr.bv_val, c2->kstr.bv_val, c1->kstr.bv_len );
|
|
-}
|
|
-
|
|
-static int
|
|
-bdb_tool_idl_flush_one( void *v1, void *arg )
|
|
-{
|
|
- bdb_tool_idl_cache *ic = v1;
|
|
- DB *db = arg;
|
|
- struct bdb_info *bdb = bdb_tool_info;
|
|
- bdb_tool_idl_cache_entry *ice;
|
|
- DBC *curs;
|
|
- DBT key, data;
|
|
- int i, rc;
|
|
- ID id, nid;
|
|
-
|
|
- /* Freshly allocated, ignore it */
|
|
- if ( !ic->head && ic->count <= BDB_IDL_DB_SIZE ) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- rc = db->cursor( db, NULL, &curs, 0 );
|
|
- if ( rc )
|
|
- return -1;
|
|
-
|
|
- DBTzero( &key );
|
|
- DBTzero( &data );
|
|
-
|
|
- bv2DBT( &ic->kstr, &key );
|
|
-
|
|
- data.size = data.ulen = sizeof( ID );
|
|
- data.flags = DB_DBT_USERMEM;
|
|
- data.data = &nid;
|
|
-
|
|
- rc = curs->c_get( curs, &key, &data, DB_SET );
|
|
- /* If key already exists and we're writing a range... */
|
|
- if ( rc == 0 && ic->count > BDB_IDL_DB_SIZE ) {
|
|
- /* If it's not currently a range, must delete old info */
|
|
- if ( nid ) {
|
|
- /* Skip lo */
|
|
- while ( curs->c_get( curs, &key, &data, DB_NEXT_DUP ) == 0 )
|
|
- curs->c_del( curs, 0 );
|
|
-
|
|
- nid = 0;
|
|
- /* Store range marker */
|
|
- curs->c_put( curs, &key, &data, DB_KEYFIRST );
|
|
- } else {
|
|
-
|
|
- /* Skip lo */
|
|
- rc = curs->c_get( curs, &key, &data, DB_NEXT_DUP );
|
|
-
|
|
- /* Get hi */
|
|
- rc = curs->c_get( curs, &key, &data, DB_NEXT_DUP );
|
|
-
|
|
- /* Delete hi */
|
|
- curs->c_del( curs, 0 );
|
|
- }
|
|
- BDB_ID2DISK( ic->last, &nid );
|
|
- curs->c_put( curs, &key, &data, DB_KEYLAST );
|
|
- rc = 0;
|
|
- } else if ( rc && rc != DB_NOTFOUND ) {
|
|
- rc = -1;
|
|
- } else if ( ic->count > BDB_IDL_DB_SIZE ) {
|
|
- /* range, didn't exist before */
|
|
- nid = 0;
|
|
- rc = curs->c_put( curs, &key, &data, DB_KEYLAST );
|
|
- if ( rc == 0 ) {
|
|
- BDB_ID2DISK( ic->first, &nid );
|
|
- rc = curs->c_put( curs, &key, &data, DB_KEYLAST );
|
|
- if ( rc == 0 ) {
|
|
- BDB_ID2DISK( ic->last, &nid );
|
|
- rc = curs->c_put( curs, &key, &data, DB_KEYLAST );
|
|
- }
|
|
- }
|
|
- if ( rc ) {
|
|
- rc = -1;
|
|
- }
|
|
- } else {
|
|
- int n;
|
|
-
|
|
- /* Just a normal write */
|
|
- rc = 0;
|
|
- for ( ice = ic->head, n=0; ice; ice = ice->next, n++ ) {
|
|
- int end;
|
|
- if ( ice->next ) {
|
|
- end = IDBLOCK;
|
|
- } else {
|
|
- end = ic->count & (IDBLOCK-1);
|
|
- if ( !end )
|
|
- end = IDBLOCK;
|
|
- }
|
|
- for ( i=0; i<end; i++ ) {
|
|
- if ( !ice->ids[i] ) continue;
|
|
- BDB_ID2DISK( ice->ids[i], &nid );
|
|
- rc = curs->c_put( curs, &key, &data, DB_NODUPDATA );
|
|
- if ( rc ) {
|
|
- if ( rc == DB_KEYEXIST ) {
|
|
- rc = 0;
|
|
- continue;
|
|
- }
|
|
- rc = -1;
|
|
- break;
|
|
- }
|
|
- }
|
|
- if ( rc ) {
|
|
- rc = -1;
|
|
- break;
|
|
- }
|
|
- }
|
|
- if ( ic->head ) {
|
|
- ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock );
|
|
- ic->tail->next = bdb_tool_idl_free_list;
|
|
- bdb_tool_idl_free_list = ic->head;
|
|
- bdb->bi_idl_cache_size -= n;
|
|
- ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
|
|
- }
|
|
- }
|
|
- if ( ic != db->app_private ) {
|
|
- ch_free( ic );
|
|
- } else {
|
|
- ic->head = ic->tail = NULL;
|
|
- }
|
|
- curs->c_close( curs );
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static int
|
|
-bdb_tool_idl_flush_db( DB *db, bdb_tool_idl_cache *ic )
|
|
-{
|
|
- Avlnode *root = db->app_private;
|
|
- int rc;
|
|
-
|
|
- db->app_private = ic;
|
|
- rc = avl_apply( root, bdb_tool_idl_flush_one, db, -1, AVL_INORDER );
|
|
- avl_free( root, NULL );
|
|
- db->app_private = NULL;
|
|
- if ( rc != -1 )
|
|
- rc = 0;
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static int
|
|
-bdb_tool_idl_flush( BackendDB *be )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
|
- DB *db;
|
|
- Avlnode *root;
|
|
- int i, rc = 0;
|
|
-
|
|
- for ( i=BDB_NDB; i < bdb->bi_ndatabases; i++ ) {
|
|
- db = bdb->bi_databases[i]->bdi_db;
|
|
- if ( !db->app_private ) continue;
|
|
- rc = bdb_tool_idl_flush_db( db, NULL );
|
|
- if ( rc )
|
|
- break;
|
|
- }
|
|
- if ( !rc ) {
|
|
- bdb->bi_idl_cache_size = 0;
|
|
- }
|
|
- return rc;
|
|
-}
|
|
-
|
|
-int bdb_tool_idl_add(
|
|
- BackendDB *be,
|
|
- DB *db,
|
|
- DB_TXN *txn,
|
|
- DBT *key,
|
|
- ID id )
|
|
-{
|
|
- struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
|
- bdb_tool_idl_cache *ic, itmp;
|
|
- bdb_tool_idl_cache_entry *ice;
|
|
- int rc;
|
|
-
|
|
- if ( !bdb->bi_idl_cache_max_size )
|
|
- return bdb_idl_insert_key( be, db, txn, key, id );
|
|
-
|
|
- DBT2bv( key, &itmp.kstr );
|
|
-
|
|
- ic = avl_find( (Avlnode *)db->app_private, &itmp, bdb_tool_idl_cmp );
|
|
-
|
|
- /* No entry yet, create one */
|
|
- if ( !ic ) {
|
|
- DBC *curs;
|
|
- DBT data;
|
|
- ID nid;
|
|
- int rc;
|
|
-
|
|
- ic = ch_malloc( sizeof( bdb_tool_idl_cache ) + itmp.kstr.bv_len );
|
|
- ic->kstr.bv_len = itmp.kstr.bv_len;
|
|
- ic->kstr.bv_val = (char *)(ic+1);
|
|
- AC_MEMCPY( ic->kstr.bv_val, itmp.kstr.bv_val, ic->kstr.bv_len );
|
|
- ic->head = ic->tail = NULL;
|
|
- ic->last = 0;
|
|
- ic->count = 0;
|
|
- avl_insert( (Avlnode **)&db->app_private, ic, bdb_tool_idl_cmp,
|
|
- avl_dup_error );
|
|
-
|
|
- /* load existing key count here */
|
|
- rc = db->cursor( db, NULL, &curs, 0 );
|
|
- if ( rc ) return rc;
|
|
-
|
|
- data.ulen = sizeof( ID );
|
|
- data.flags = DB_DBT_USERMEM;
|
|
- data.data = &nid;
|
|
- rc = curs->c_get( curs, key, &data, DB_SET );
|
|
- if ( rc == 0 ) {
|
|
- if ( nid == 0 ) {
|
|
- ic->count = BDB_IDL_DB_SIZE+1;
|
|
- } else {
|
|
- db_recno_t count;
|
|
-
|
|
- curs->c_count( curs, &count, 0 );
|
|
- ic->count = count;
|
|
- BDB_DISK2ID( &nid, &ic->first );
|
|
- }
|
|
- }
|
|
- curs->c_close( curs );
|
|
- }
|
|
- /* are we a range already? */
|
|
- if ( ic->count > BDB_IDL_DB_SIZE ) {
|
|
- ic->last = id;
|
|
- return 0;
|
|
- /* Are we at the limit, and converting to a range? */
|
|
- } else if ( ic->count == BDB_IDL_DB_SIZE ) {
|
|
- int n;
|
|
- for ( ice = ic->head, n=0; ice; ice = ice->next, n++ )
|
|
- /* counting */ ;
|
|
- if ( n ) {
|
|
- ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock );
|
|
- ic->tail->next = bdb_tool_idl_free_list;
|
|
- bdb_tool_idl_free_list = ic->head;
|
|
- bdb->bi_idl_cache_size -= n;
|
|
- ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
|
|
- }
|
|
- ic->head = ic->tail = NULL;
|
|
- ic->last = id;
|
|
- ic->count++;
|
|
- return 0;
|
|
- }
|
|
- /* No free block, create that too */
|
|
- if ( !ic->tail || ( ic->count & (IDBLOCK-1)) == 0) {
|
|
- ice = NULL;
|
|
- ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock );
|
|
- if ( bdb->bi_idl_cache_size >= bdb->bi_idl_cache_max_size ) {
|
|
- ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
|
|
- rc = bdb_tool_idl_flush_db( db, ic );
|
|
- if ( rc )
|
|
- return rc;
|
|
- avl_insert( (Avlnode **)&db->app_private, ic, bdb_tool_idl_cmp,
|
|
- avl_dup_error );
|
|
- ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock );
|
|
- }
|
|
- bdb->bi_idl_cache_size++;
|
|
- if ( bdb_tool_idl_free_list ) {
|
|
- ice = bdb_tool_idl_free_list;
|
|
- bdb_tool_idl_free_list = ice->next;
|
|
- }
|
|
- ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
|
|
- if ( !ice ) {
|
|
- ice = ch_malloc( sizeof( bdb_tool_idl_cache_entry ));
|
|
- }
|
|
- memset( ice, 0, sizeof( *ice ));
|
|
- if ( !ic->head ) {
|
|
- ic->head = ice;
|
|
- } else {
|
|
- ic->tail->next = ice;
|
|
- }
|
|
- ic->tail = ice;
|
|
- if ( !ic->count )
|
|
- ic->first = id;
|
|
- }
|
|
- ice = ic->tail;
|
|
- ice->ids[ ic->count & (IDBLOCK-1) ] = id;
|
|
- ic->count++;
|
|
-
|
|
- return 0;
|
|
-}
|
|
-#endif
|
|
-
|
|
-#ifdef USE_TRICKLE
|
|
-static void *
|
|
-bdb_tool_trickle_task( void *ctx, void *ptr )
|
|
-{
|
|
- DB_ENV *env = ptr;
|
|
- int wrote;
|
|
-
|
|
- ldap_pvt_thread_mutex_lock( &bdb_tool_trickle_mutex );
|
|
- bdb_tool_trickle_active = 1;
|
|
- ldap_pvt_thread_cond_signal( &bdb_tool_trickle_cond_end );
|
|
- while ( 1 ) {
|
|
- ldap_pvt_thread_cond_wait( &bdb_tool_trickle_cond,
|
|
- &bdb_tool_trickle_mutex );
|
|
- if ( slapd_shutdown )
|
|
- break;
|
|
- env->memp_trickle( env, 30, &wrote );
|
|
- }
|
|
- bdb_tool_trickle_active = 0;
|
|
- ldap_pvt_thread_cond_signal( &bdb_tool_trickle_cond_end );
|
|
- ldap_pvt_thread_mutex_unlock( &bdb_tool_trickle_mutex );
|
|
-
|
|
- return NULL;
|
|
-}
|
|
-#endif
|
|
-
|
|
-static void *
|
|
-bdb_tool_index_task( void *ctx, void *ptr )
|
|
-{
|
|
- int base = *(int *)ptr;
|
|
-
|
|
- free( ptr );
|
|
- while ( 1 ) {
|
|
- ldap_pvt_thread_mutex_lock( &bdb_tool_index_mutex );
|
|
- bdb_tool_index_tcount--;
|
|
- if ( !bdb_tool_index_tcount )
|
|
- ldap_pvt_thread_cond_signal( &bdb_tool_index_cond_main );
|
|
- ldap_pvt_thread_cond_wait( &bdb_tool_index_cond_work,
|
|
- &bdb_tool_index_mutex );
|
|
- if ( slapd_shutdown ) {
|
|
- bdb_tool_index_tcount--;
|
|
- if ( !bdb_tool_index_tcount )
|
|
- ldap_pvt_thread_cond_signal( &bdb_tool_index_cond_main );
|
|
- ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex );
|
|
- break;
|
|
- }
|
|
- ldap_pvt_thread_mutex_unlock( &bdb_tool_index_mutex );
|
|
-
|
|
- bdb_tool_index_threads[base] = bdb_index_recrun( bdb_tool_ix_op,
|
|
- bdb_tool_info, bdb_tool_index_rec, bdb_tool_ix_id, base );
|
|
- }
|
|
-
|
|
- return NULL;
|
|
-}
|
|
diff --git a/servers/slapd/back-bdb/trans.c b/servers/slapd/back-bdb/trans.c
|
|
deleted file mode 100644
|
|
index 1971d29..0000000
|
|
--- a/servers/slapd/back-bdb/trans.c
|
|
+++ /dev/null
|
|
@@ -1,56 +0,0 @@
|
|
-/* trans.c - bdb backend transaction routines */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-
|
|
-#include "portable.h"
|
|
-
|
|
-#include <stdio.h>
|
|
-#include <ac/string.h>
|
|
-
|
|
-#include "back-bdb.h"
|
|
-#include "lber_pvt.h"
|
|
-#include "lutil.h"
|
|
-
|
|
-
|
|
-/* Congestion avoidance code
|
|
- * for Deadlock Rollback
|
|
- */
|
|
-
|
|
-void
|
|
-bdb_trans_backoff( int num_retries )
|
|
-{
|
|
- int i;
|
|
- int delay = 0;
|
|
- int pow_retries = 1;
|
|
- unsigned long key = 0;
|
|
- unsigned long max_key = -1;
|
|
- struct timeval timeout;
|
|
-
|
|
- lutil_entropy( (unsigned char *) &key, sizeof( unsigned long ));
|
|
-
|
|
- for ( i = 0; i < num_retries; i++ ) {
|
|
- if ( i >= 5 ) break;
|
|
- pow_retries *= 4;
|
|
- }
|
|
-
|
|
- delay = 16384 * (key * (double) pow_retries / (double) max_key);
|
|
- delay = delay ? delay : 1;
|
|
-
|
|
- Debug( LDAP_DEBUG_TRACE, "delay = %d, num_retries = %d\n", delay, num_retries, 0 );
|
|
-
|
|
- timeout.tv_sec = delay / 1000000;
|
|
- timeout.tv_usec = delay % 1000000;
|
|
- select( 0, NULL, NULL, NULL, &timeout );
|
|
-}
|
|
diff --git a/servers/slapd/back-hdb/Makefile.in b/servers/slapd/back-hdb/Makefile.in
|
|
deleted file mode 100644
|
|
index 150cee5..0000000
|
|
--- a/servers/slapd/back-hdb/Makefile.in
|
|
+++ /dev/null
|
|
@@ -1,70 +0,0 @@
|
|
-# Makefile for back-hdb
|
|
-# $OpenLDAP$
|
|
-## This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
-##
|
|
-## Copyright 1998-2020 The OpenLDAP Foundation.
|
|
-## All rights reserved.
|
|
-##
|
|
-## Redistribution and use in source and binary forms, with or without
|
|
-## modification, are permitted only as authorized by the OpenLDAP
|
|
-## Public License.
|
|
-##
|
|
-## A copy of this license is available in the file LICENSE in the
|
|
-## top-level directory of the distribution or, alternatively, at
|
|
-## <http://www.OpenLDAP.org/license.html>.
|
|
-#
|
|
-## Copyright 2003 Howard Chu @ Symas Corp. See master COPYRIGHT file for terms.
|
|
-
|
|
-XXDIR = $(srcdir)/../back-bdb
|
|
-
|
|
-XXSRCS = init.c tools.c config.c \
|
|
- add.c bind.c compare.c delete.c modify.c modrdn.c search.c \
|
|
- extended.c referral.c operational.c \
|
|
- attr.c index.c key.c dbcache.c filterindex.c trans.c \
|
|
- dn2entry.c dn2id.c error.c id2entry.c idl.c nextid.c cache.c \
|
|
- monitor.c
|
|
-SRCS = $(XXSRCS)
|
|
-OBJS = init.lo tools.lo config.lo \
|
|
- add.lo bind.lo compare.lo delete.lo modify.lo modrdn.lo search.lo \
|
|
- extended.lo referral.lo operational.lo \
|
|
- attr.lo index.lo key.lo dbcache.lo filterindex.lo trans.lo \
|
|
- dn2entry.lo dn2id.lo error.lo id2entry.lo idl.lo nextid.lo cache.lo \
|
|
- monitor.lo
|
|
-
|
|
-LDAP_INCDIR= ../../../include
|
|
-LDAP_LIBDIR= ../../../libraries
|
|
-
|
|
-BUILD_OPT = "--enable-hdb"
|
|
-BUILD_MOD = @BUILD_HDB@
|
|
-
|
|
-mod_DEFS = -DSLAPD_IMPORT
|
|
-MOD_DEFS = $(@BUILD_HDB@_DEFS)
|
|
-MOD_LIBS = $(BDB_LIBS)
|
|
-
|
|
-shared_LDAP_LIBS = $(LDAP_LIBLDAP_R_LA) $(LDAP_LIBLBER_LA)
|
|
-NT_LINK_LIBS = -L.. -lslapd $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
|
|
-UNIX_LINK_LIBS = $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
|
|
-
|
|
-.links : Makefile
|
|
- @for i in $(XXSRCS); do \
|
|
- $(RM) $$i; \
|
|
- $(LN_S) $(XXDIR)/$$i . ; \
|
|
- done
|
|
- touch .links
|
|
-
|
|
-$(XXSRCS) : .links
|
|
-
|
|
-LIBBASE = back_hdb
|
|
-
|
|
-XINCPATH = -I.. -I$(srcdir)/.. -I$(srcdir) -I$(XXDIR)
|
|
-XDEFS = $(MODULES_CPPFLAGS)
|
|
-
|
|
-depend-local-lib: .links
|
|
-
|
|
-all-local-lib: ../.backend
|
|
-
|
|
-../.backend: lib$(LIBBASE).a
|
|
- @touch $@
|
|
-
|
|
-veryclean-local: FORCE
|
|
- $(RM) $(XXSRCS) .links
|
|
diff --git a/servers/slapd/back-hdb/back-bdb.h b/servers/slapd/back-hdb/back-bdb.h
|
|
deleted file mode 100644
|
|
index 9f92d8b..0000000
|
|
--- a/servers/slapd/back-hdb/back-bdb.h
|
|
+++ /dev/null
|
|
@@ -1,31 +0,0 @@
|
|
-/* back-bdb.h - hdb back-end header file */
|
|
-/* $OpenLDAP$ */
|
|
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
- *
|
|
- * Copyright 2000-2020 The OpenLDAP Foundation.
|
|
- * Portions Copyright 2003 Howard Chu @ Symas Corp.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted only as authorized by the OpenLDAP
|
|
- * Public License.
|
|
- *
|
|
- * A copy of this license is available in the file LICENSE in the
|
|
- * top-level directory of the distribution or, alternatively, at
|
|
- * <http://www.OpenLDAP.org/license.html>.
|
|
- */
|
|
-/* ACKNOWLEDGEMENTS:
|
|
- * This work was originally developed by Howard Chu for inclusion
|
|
- * in OpenLDAP Software.
|
|
- */
|
|
-
|
|
-#ifndef _BACK_HDB_H_
|
|
-#define _BACK_HDB_H_
|
|
-
|
|
-#ifndef BDB_HIER
|
|
-#define BDB_HIER 1
|
|
-#endif
|
|
-
|
|
-#include "../back-bdb/back-bdb.h"
|
|
-
|
|
-#endif /* _BACK_HDB_H_ */
|
|
diff --git a/servers/slapd/back-monitor/init.c b/servers/slapd/back-monitor/init.c
|
|
index b264115..ce9a34a 100644
|
|
--- a/servers/slapd/back-monitor/init.c
|
|
+++ b/servers/slapd/back-monitor/init.c
|
|
@@ -1991,8 +1991,8 @@ monitor_back_initialize(
|
|
{ "olmGenericAttributes", "olmSubSystemAttributes:0" },
|
|
{ "olmDatabaseAttributes", "olmSubSystemAttributes:1" },
|
|
|
|
- /* for example, back-bdb specific attrs
|
|
- * are in "olmDatabaseAttributes:1"
|
|
+ /* for example, back-mdb specific attrs
|
|
+ * are in "olmDatabaseAttributes:12"
|
|
*
|
|
* NOTE: developers, please record here OID assignments
|
|
* for other modules */
|
|
@@ -2002,8 +2002,8 @@ monitor_back_initialize(
|
|
{ "olmGenericObjectClasses", "olmSubSystemObjectClasses:0" },
|
|
{ "olmDatabaseObjectClasses", "olmSubSystemObjectClasses:1" },
|
|
|
|
- /* for example, back-bdb specific objectClasses
|
|
- * are in "olmDatabaseObjectClasses:1"
|
|
+ /* for example, back-mdb specific objectClasses
|
|
+ * are in "olmDatabaseObjectClasses:12"
|
|
*
|
|
* NOTE: developers, please record here OID assignments
|
|
* for other modules */
|
|
diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c
|
|
index 0c6a7f5..538eef1 100644
|
|
--- a/servers/slapd/bconfig.c
|
|
+++ b/servers/slapd/bconfig.c
|
|
@@ -238,7 +238,7 @@ static OidRec OidMacros[] = {
|
|
* Backend/Database registry
|
|
*
|
|
* OLcfg{Bk|Db}{Oc|At}:0 -> common
|
|
- * OLcfg{Bk|Db}{Oc|At}:1 -> back-bdb(/back-hdb)
|
|
+ * OLcfg{Bk|Db}{Oc|At}:1 -> back-bdb(/back-hdb) (removed)
|
|
* OLcfg{Bk|Db}{Oc|At}:2 -> back-ldif
|
|
* OLcfg{Bk|Db}{Oc|At}:3 -> back-ldap/meta
|
|
* OLcfg{Bk|Db}{Oc|At}:4 -> back-monitor
|
|
diff --git a/servers/slapd/dn.c b/servers/slapd/dn.c
|
|
index 06698b0..89b80e3 100644
|
|
--- a/servers/slapd/dn.c
|
|
+++ b/servers/slapd/dn.c
|
|
@@ -1131,8 +1131,7 @@ rdn_validate( struct berval *rdn )
|
|
|
|
/* build_new_dn:
|
|
*
|
|
- * Used by back-bdb back_modrdn to create the new dn of entries being
|
|
- * renamed.
|
|
+ * Used to create the new dn of entries being renamed.
|
|
*
|
|
* new_dn = parent (p_dn) + separator + rdn (newrdn) + null.
|
|
*/
|
|
diff --git a/servers/slapd/overlays/pcache.c b/servers/slapd/overlays/pcache.c
|
|
index f88ca09..0d7ff8c 100644
|
|
--- a/servers/slapd/overlays/pcache.c
|
|
+++ b/servers/slapd/overlays/pcache.c
|
|
@@ -5616,7 +5616,7 @@ cleanup:;
|
|
cm->monitor_cb = (void *)cb;
|
|
|
|
/* we don't need to keep track of the attributes, because
|
|
- * bdb_monitor_free() takes care of everything */
|
|
+ * mdb_monitor_free() takes care of everything */
|
|
if ( a != NULL ) {
|
|
attrs_free( a );
|
|
}
|
|
@@ -5700,7 +5700,7 @@ pcache_initialize()
|
|
}
|
|
#endif /* PCACHE_EXOP_QUERY_DELETE */
|
|
|
|
- argv[ 0 ] = "back-bdb/back-hdb monitor";
|
|
+ argv[ 0 ] = "back-mdb monitor";
|
|
c.argv = argv;
|
|
c.argc = 3;
|
|
c.fname = argv[0];
|
|
diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h
|
|
index f003bb9..591f49d 100644
|
|
--- a/servers/slapd/slap.h
|
|
+++ b/servers/slapd/slap.h
|
|
@@ -1805,7 +1805,6 @@ struct BackendDB {
|
|
|
|
/*
|
|
* define to honor hasSubordinates operational attribute in search filters
|
|
- * (in previous use there was a flaw with back-bdb; now it is fixed).
|
|
*/
|
|
#define be_has_subordinates bd_info->bi_has_subordinates
|
|
|
|
diff --git a/servers/slapd/slapd.ldif b/servers/slapd/slapd.ldif
|
|
index 5aba54d..b2b38ea 100644
|
|
--- a/servers/slapd/slapd.ldif
|
|
+++ b/servers/slapd/slapd.ldif
|
|
@@ -30,8 +30,7 @@ olcPidFile: %LOCALSTATEDIR%/run/slapd.pid
|
|
#objectClass: olcModuleList
|
|
#cn: module
|
|
#olcModulepath: %MODULEDIR%
|
|
-#olcModuleload: back_bdb.la
|
|
-#olcModuleload: back_hdb.la
|
|
+#olcModuleload: back_mdb.la
|
|
#olcModuleload: back_ldap.la
|
|
#olcModuleload: back_passwd.la
|
|
#olcModuleload: back_shell.la
|
|
diff --git a/tests/Makefile.in b/tests/Makefile.in
|
|
index d841846..ef98813 100644
|
|
--- a/tests/Makefile.in
|
|
+++ b/tests/Makefile.in
|
|
@@ -16,15 +16,11 @@
|
|
RUN=./run
|
|
SUBDIRS= progs
|
|
|
|
-BUILD_BDB=@BUILD_BDB@
|
|
-BUILD_HDB=@BUILD_HDB@
|
|
BUILD_MDB=@BUILD_MDB@
|
|
BUILD_SQL=@BUILD_SQL@
|
|
|
|
# test primary backends (default)
|
|
test tests:
|
|
- @$(MAKE) bdb
|
|
- @$(MAKE) hdb
|
|
@$(MAKE) mdb
|
|
|
|
# test all backends
|
|
@@ -32,22 +28,6 @@ alltests: tests
|
|
@$(MAKE) sql
|
|
@$(MAKE) ldif
|
|
|
|
-bdb test-bdb: bdb-$(BUILD_BDB)
|
|
-bdb-no:
|
|
- @echo "run configure with --enable-bdb to run BDB tests"
|
|
-
|
|
-bdb-yes bdb-mod: FORCE
|
|
- @echo "Initiating LDAP tests for BDB..."
|
|
- @$(RUN) -b bdb all
|
|
-
|
|
-hdb test-hdb: hdb-$(BUILD_HDB)
|
|
-hdb-no:
|
|
- @echo "run configure with --enable-hdb to run HDB tests"
|
|
-
|
|
-hdb-yes hdb-mod: FORCE
|
|
- @echo "Initiating LDAP tests for HDB..."
|
|
- @$(RUN) -b hdb all
|
|
-
|
|
mdb test-mdb: mdb-$(BUILD_MDB)
|
|
mdb-no:
|
|
@echo "run configure with --enable-mdb to run MDB tests"
|
|
@@ -70,26 +50,10 @@ ldif test-ldif: FORCE
|
|
|
|
regressions: FORCE
|
|
@echo "Testing (available) ITS regressions"
|
|
- @$(MAKE) bdb-its
|
|
- @$(MAKE) hdb-its
|
|
@$(MAKE) mdb-its
|
|
|
|
its: regressions
|
|
|
|
-bdb-its: bdb-its-$(BUILD_BDB)
|
|
-bdb-its-no:
|
|
- @echo "run configure with --enable-bdb to run BDB ITS regressions"
|
|
-
|
|
-bdb-its-yes bdb-its-mod: FORCE
|
|
- @$(RUN) -b bdb its-all
|
|
-
|
|
-hdb-its: hdb-its-$(BUILD_HDB)
|
|
-hdb-its-no:
|
|
- @echo "run configure with --enable-hdb to run HDB ITS regressions"
|
|
-
|
|
-hdb-its-yes hdb-its-mod: FORCE
|
|
- @$(RUN) -b hdb its-all
|
|
-
|
|
mdb-its: mdb-its-$(BUILD_MDB)
|
|
mdb-its-no:
|
|
@echo "run configure with --enable-mdb to run MDB ITS regressions"
|
|
diff --git a/tests/README b/tests/README
|
|
index 1a25df8..a3b5d2f 100644
|
|
--- a/tests/README
|
|
+++ b/tests/README
|
|
@@ -2,8 +2,6 @@ This directory contains a series of test scripts which are used to
|
|
verify basic functionality of the LDAP libraries and slapd.
|
|
|
|
To run all of the tests, type "make test".
|
|
- To run BDB tests, type "make bdb".
|
|
- To run HDB tests, type "make hdb".
|
|
To run MDB tests, type "make mdb".
|
|
To run SQL tests, define SLAPD_USE_SQL=<rdbms> and type
|
|
"make sql"; define SLAPD_USE_SQLWRITE=yes
|
|
diff --git a/tests/data/regressions/its4184/its4184 b/tests/data/regressions/its4184/its4184
|
|
index 08f9f1c..4170f05 100755
|
|
--- a/tests/data/regressions/its4184/its4184
|
|
+++ b/tests/data/regressions/its4184/its4184
|
|
@@ -16,10 +16,6 @@
|
|
echo "running defines.sh"
|
|
. $SRCDIR/scripts/defines.sh
|
|
|
|
-if test "$BACKEND" != "bdb" && test "$BACKEND" != "hdb" ; then
|
|
- echo "Warning: this test is known to affect bdb and hdb, although it may impact other backends as well."
|
|
-fi
|
|
-
|
|
mkdir -p $DBDIR1A $DBDIR2A
|
|
|
|
ITS=4184
|
|
diff --git a/tests/data/regressions/its4448/its4448 b/tests/data/regressions/its4448/its4448
|
|
index 7f50999..9319374 100755
|
|
--- a/tests/data/regressions/its4448/its4448
|
|
+++ b/tests/data/regressions/its4448/its4448
|
|
@@ -47,22 +47,6 @@ ITS=4448
|
|
ITSDIR=$DATADIR/regressions/its$ITS
|
|
ITSCONF=$ITSDIR/slapd-meta.conf
|
|
|
|
-# NOTE: this could be added to all tests...
|
|
-if test "$BACKEND" = "bdb" || test "$BACKEND" = "hdb" ; then
|
|
- if test "x$DB_CONFIG" != "x" ; then \
|
|
- if test -f $DB_CONFIG ; then
|
|
- echo "==> using DB_CONFIG \"$DB_CONFIG\""
|
|
- cp $DB_CONFIG $DBDIR1
|
|
- cp $DB_CONFIG $DBDIR2
|
|
- else
|
|
- echo "==> DB_CONFIG must point to a valid file (ignored)"
|
|
- fi
|
|
- else
|
|
- echo "==> set \"DB_CONFIG\" to the DB_CONFIG file you want to use for the test."
|
|
- fi
|
|
- echo ""
|
|
-fi
|
|
-
|
|
echo "Starting slapd on TCP/IP port $PORT1..."
|
|
. $CONFFILTER $BACKEND $MONITORDB < $CONF > $CONF1
|
|
$SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
|
|
diff --git a/tests/data/slapd-proxyauthz.conf b/tests/data/slapd-proxyauthz.conf
|
|
index 2ff6563..b28d60d 100644
|
|
--- a/tests/data/slapd-proxyauthz.conf
|
|
+++ b/tests/data/slapd-proxyauthz.conf
|
|
@@ -64,10 +64,6 @@ pcachetemplate (cn=) 0 86400 86400 86400 180
|
|
|
|
pcachebind (cn=) 0 3600 sub ou=people,dc=example,dc=com
|
|
|
|
-#bdb#cachesize 20
|
|
-#hdb#cachesize 20
|
|
-#bdb#dbnosync
|
|
-#hdb#dbnosync
|
|
#mdb#dbnosync
|
|
|
|
#~null~#directory @TESTDIR@/db.2.a
|
|
diff --git a/tests/data/slapd-proxycache.conf b/tests/data/slapd-proxycache.conf
|
|
index b96d850..db3b60e 100644
|
|
--- a/tests/data/slapd-proxycache.conf
|
|
+++ b/tests/data/slapd-proxycache.conf
|
|
@@ -54,10 +54,6 @@ pcachetemplate (mail=) 0 @TTL@ @NTTL@ @STTL@
|
|
pcachetemplate (&(objectclass=)(uid=)) 1 @TTL@ @NTTL@ @STTL@ @TTR@
|
|
pcachebind (&(objectclass=person)(uid=)) 1 @BTTR@ sub "ou=Alumni Association,ou=people,dc=example,dc=com"
|
|
|
|
-#bdb#cachesize 20
|
|
-#hdb#cachesize 20
|
|
-#bdb#dbnosync
|
|
-#hdb#dbnosync
|
|
#mdb#dbnosync
|
|
|
|
#~null~#directory @TESTDIR@/db.2.a
|
|
diff --git a/tests/data/slapd-ref-slave.conf b/tests/data/slapd-ref-slave.conf
|
|
index 3d30ca7..5d8d83f 100644
|
|
--- a/tests/data/slapd-ref-slave.conf
|
|
+++ b/tests/data/slapd-ref-slave.conf
|
|
@@ -34,8 +34,6 @@ argsfile @TESTDIR@/slapd.2.args
|
|
referral "@URI1@"
|
|
|
|
database @BACKEND@
|
|
-#bdb#cachesize 0
|
|
-#hdb#cachesize 0
|
|
|
|
suffix "o=University of Mich,c=US"
|
|
rootdn "cn=Manager,o=University of Mich,c=US"
|
|
diff --git a/tests/data/slapd.conf b/tests/data/slapd.conf
|
|
index 97c883b..309eb5a 100644
|
|
--- a/tests/data/slapd.conf
|
|
+++ b/tests/data/slapd.conf
|
|
@@ -44,8 +44,6 @@ rootpw secret
|
|
#~null~#directory @TESTDIR@/db.1.a
|
|
#indexdb#index objectClass eq
|
|
#indexdb#index cn,sn,uid pres,eq,sub
|
|
-#bdb#checkpoint 1024 5
|
|
-#hdb#checkpoint 1024 5
|
|
#mdb#maxsize 33554432
|
|
#ndb#dbname db_1
|
|
#ndb#include @DATADIR@/ndb.conf
|
|
diff --git a/tests/run.in b/tests/run.in
|
|
index 8830dd4..6705265 100644
|
|
--- a/tests/run.in
|
|
+++ b/tests/run.in
|
|
@@ -24,8 +24,6 @@ EGREP_CMD="@EGREP@"
|
|
export SRCDIR TOPSRCDIR LN_S EGREP_CMD
|
|
|
|
# backends known to ./run -b <backend> (used to deduce $BACKENDTYPE)
|
|
-AC_bdb=@BUILD_BDB@
|
|
-AC_hdb=@BUILD_HDB@
|
|
AC_ldif=yes
|
|
AC_mdb=@BUILD_MDB@
|
|
AC_null=@BUILD_NULL@
|
|
@@ -69,7 +67,7 @@ if test "${AC_meta}" = "metamod" && test "${AC_LIBS_DYNAMIC}" = "static" ; then
|
|
AC_meta="metano"
|
|
fi
|
|
|
|
-export AC_bdb AC_hdb AC_ldap AC_mdb AC_meta AC_monitor AC_null AC_relay AC_sql \
|
|
+export AC_ldap AC_mdb AC_meta AC_monitor AC_null AC_relay AC_sql \
|
|
AC_accesslog AC_constraint AC_dds AC_dynlist AC_memberof AC_pcache AC_ppolicy \
|
|
AC_refint AC_retcode AC_rwm AC_unique AC_syncprov AC_translucent \
|
|
AC_valsort \
|
|
@@ -153,7 +151,7 @@ while test $# -gt 0 ; do
|
|
done
|
|
|
|
if test -z "$BACKEND" ; then
|
|
- for b in bdb hdb mdb ; do
|
|
+ for b in mdb ; do
|
|
if eval "test \"\$AC_$b\" != no" ; then
|
|
BACKEND=$b
|
|
break
|
|
@@ -174,7 +172,7 @@ fi
|
|
# maindb: main storage backend. Currently index,limits,mode,paged results.
|
|
INDEXDB=noindexdb MAINDB=nomaindb
|
|
case $BACKEND in
|
|
- bdb|hdb|mdb) INDEXDB=indexdb MAINDB=maindb ;;
|
|
+ mdb) INDEXDB=indexdb MAINDB=maindb ;;
|
|
ndb) INDEXDB=indexdb ;;
|
|
esac
|
|
|
|
diff --git a/tests/scripts/test023-refint b/tests/scripts/test023-refint
|
|
index 546b9c7..b51134d 100755
|
|
--- a/tests/scripts/test023-refint
|
|
+++ b/tests/scripts/test023-refint
|
|
@@ -189,9 +189,8 @@ if test $RC != 0 ; then
|
|
exit $RC
|
|
fi
|
|
|
|
-if test $BACKEND != "bdb" ; then
|
|
- $LDAPMODIFY -v -D "$REFINTDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
|
|
- $TESTOUT 2>&1 << EDEL
|
|
+$LDAPMODIFY -v -D "$REFINTDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
|
|
+ $TESTOUT 2>&1 << EDEL
|
|
version: 1
|
|
dn: cn=group,o=refint
|
|
changetype: add
|
|
@@ -205,65 +204,65 @@ member: uid=theman,ou=users,o=refint
|
|
member: uid=richard,ou=users,o=refint
|
|
EDEL
|
|
|
|
- RC=$?
|
|
- if test $RC != 0 ; then
|
|
- echo "ldapmodify failed ($RC)!"
|
|
- test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
|
- exit $RC
|
|
- fi
|
|
+RC=$?
|
|
+if test $RC != 0 ; then
|
|
+ echo "ldapmodify failed ($RC)!"
|
|
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
|
+ exit $RC
|
|
+fi
|
|
|
|
- sleep 1;
|
|
+sleep 1;
|
|
|
|
- $LDAPSEARCH -S "" -b "o=refint" -h $LOCALHOST -p $PORT1 \
|
|
- manager member secretary > $SEARCHOUT 2>&1
|
|
- RC=$?
|
|
- if test $RC != 0 ; then
|
|
- echo "ldapsearch failed ($RC)!"
|
|
- test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
|
- exit $RC
|
|
- fi
|
|
+$LDAPSEARCH -S "" -b "o=refint" -h $LOCALHOST -p $PORT1 \
|
|
+ manager member secretary > $SEARCHOUT 2>&1
|
|
+RC=$?
|
|
+if test $RC != 0 ; then
|
|
+ echo "ldapsearch failed ($RC)!"
|
|
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
|
+ exit $RC
|
|
+fi
|
|
|
|
- $EGREP_CMD "(manager|member|secretary):" $SEARCHOUT \
|
|
- | sed "s/ou=users/ou=people/g" | \
|
|
- sort > $TESTOUT 2>&1
|
|
+$EGREP_CMD "(manager|member|secretary):" $SEARCHOUT \
|
|
+ | sed "s/ou=users/ou=people/g" | \
|
|
+ sort > $TESTOUT 2>&1
|
|
|
|
- echo "testing subtree rename"
|
|
- $LDAPMODRDN -D "$REFINTDN" -r -h $LOCALHOST -p $PORT1 -w $PASSWD > \
|
|
- /dev/null 2>&1 'ou=users,o=refint' 'ou=people'
|
|
- RC=$?
|
|
- if test $RC != 0 ; then
|
|
- echo "ldapmodrdn failed ($RC)!"
|
|
- test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
|
- exit $RC
|
|
- fi
|
|
+echo "testing subtree rename"
|
|
+$LDAPMODRDN -D "$REFINTDN" -r -h $LOCALHOST -p $PORT1 -w $PASSWD > \
|
|
+ /dev/null 2>&1 'ou=users,o=refint' 'ou=people'
|
|
+RC=$?
|
|
+if test $RC != 0 ; then
|
|
+ echo "ldapmodrdn failed ($RC)!"
|
|
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
|
+ exit $RC
|
|
+fi
|
|
|
|
- sleep 1;
|
|
+sleep 1;
|
|
|
|
- echo "Using ldapsearch to check dependents new rdn..."
|
|
+echo "Using ldapsearch to check dependents new rdn..."
|
|
|
|
- $LDAPSEARCH -S "" -b "o=refint" -h $LOCALHOST -p $PORT1 \
|
|
- manager member secretary > $SEARCHOUT 2>&1
|
|
+$LDAPSEARCH -S "" -b "o=refint" -h $LOCALHOST -p $PORT1 \
|
|
+ manager member secretary > $SEARCHOUT 2>&1
|
|
|
|
- RC=$?
|
|
- if test $RC != 0 ; then
|
|
- echo "ldapsearch failed ($RC)!"
|
|
- test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
|
- exit $RC
|
|
- fi
|
|
+RC=$?
|
|
+if test $RC != 0 ; then
|
|
+ echo "ldapsearch failed ($RC)!"
|
|
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
|
+ exit $RC
|
|
+fi
|
|
|
|
- $EGREP_CMD "(manager|member|secretary):" $SEARCHOUT \
|
|
- | sort > $SEARCHFLT 2>&1
|
|
+$EGREP_CMD "(manager|member|secretary):" $SEARCHOUT \
|
|
+ | sort > $SEARCHFLT 2>&1
|
|
|
|
- echo "Comparing ldapsearch results against original..."
|
|
- $CMP $TESTOUT $SEARCHFLT > $CMPOUT
|
|
+echo "Comparing ldapsearch results against original..."
|
|
+$CMP $TESTOUT $SEARCHFLT > $CMPOUT
|
|
|
|
- if test $? != 0 ; then
|
|
- echo "comparison failed - subtree rename operations did not complete correctly"
|
|
- test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
|
- exit 1
|
|
- fi
|
|
+if test $? != 0 ; then
|
|
+ echo "comparison failed - subtree rename operations did not complete correctly"
|
|
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
|
+ exit 1
|
|
fi
|
|
|
|
+
|
|
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
|
|
|
echo ">>>>> Test succeeded"
|
|
diff --git a/tests/scripts/test025-limits b/tests/scripts/test025-limits
|
|
index 8d39c6b..551b969 100755
|
|
--- a/tests/scripts/test025-limits
|
|
+++ b/tests/scripts/test025-limits
|
|
@@ -750,7 +750,7 @@ case $RC in
|
|
esac
|
|
|
|
if test $MAINDB != maindb ; then
|
|
- # only bdb|hdb|mdb currently supports pagedResults control
|
|
+ # only mdb currently supports pagedResults control
|
|
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
|
|
|
echo ">>>>> Test succeeded"
|
|
diff --git a/tests/scripts/test036-meta-concurrency b/tests/scripts/test036-meta-concurrency
|
|
index 2a4146c..3344f45 100755
|
|
--- a/tests/scripts/test036-meta-concurrency
|
|
+++ b/tests/scripts/test036-meta-concurrency
|
|
@@ -40,22 +40,6 @@ rm -rf $TESTDIR
|
|
|
|
mkdir -p $TESTDIR $DBDIR1 $DBDIR2
|
|
|
|
-# NOTE: this could be added to all tests...
|
|
-if test "$BACKEND" = "bdb" || test "$BACKEND" = "hdb" ; then
|
|
- if test "x$DB_CONFIG" != "x" ; then \
|
|
- if test -f $DB_CONFIG ; then
|
|
- echo "==> using DB_CONFIG \"$DB_CONFIG\""
|
|
- cp $DB_CONFIG $DBDIR1
|
|
- cp $DB_CONFIG $DBDIR2
|
|
- else
|
|
- echo "==> DB_CONFIG must point to a valid file (ignored)"
|
|
- fi
|
|
- else
|
|
- echo "==> set \"DB_CONFIG\" to the DB_CONFIG file you want to use for the test."
|
|
- fi
|
|
- echo ""
|
|
-fi
|
|
-
|
|
echo "Starting slapd on TCP/IP port $PORT1..."
|
|
. $CONFFILTER $BACKEND $MONITORDB < $METACONF1 > $CONF1
|
|
$SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
|
|
diff --git a/tests/scripts/test040-subtree-rename b/tests/scripts/test040-subtree-rename
|
|
index 671d626..f1057d6 100755
|
|
--- a/tests/scripts/test040-subtree-rename
|
|
+++ b/tests/scripts/test040-subtree-rename
|
|
@@ -16,11 +16,6 @@
|
|
echo "running defines.sh"
|
|
. $SRCDIR/scripts/defines.sh
|
|
|
|
-if test $BACKEND = bdb ; then
|
|
- echo "subtree rename not supported by back-$BACKEND"
|
|
- exit 0
|
|
-fi
|
|
-
|
|
mkdir -p $TESTDIR $DBDIR1
|
|
|
|
echo "Starting slapd on TCP/IP port $PORT1..."
|
|
diff --git a/tests/scripts/test043-delta-syncrepl b/tests/scripts/test043-delta-syncrepl
|
|
index 3c7c629..686bf1c 100755
|
|
--- a/tests/scripts/test043-delta-syncrepl
|
|
+++ b/tests/scripts/test043-delta-syncrepl
|
|
@@ -32,7 +32,7 @@ fi
|
|
|
|
mkdir -p $TESTDIR $DBDIR1A $DBDIR1B $DBDIR2
|
|
|
|
-SPEC="mdb=a,bdb=a,hdb=a"
|
|
+SPEC="mdb=a"
|
|
|
|
#
|
|
# Test replication:
|
|
diff --git a/tests/scripts/test052-memberof b/tests/scripts/test052-memberof
|
|
index 4b2a5d9..a73a929 100755
|
|
--- a/tests/scripts/test052-memberof
|
|
+++ b/tests/scripts/test052-memberof
|
|
@@ -72,11 +72,10 @@ EOF
|
|
fi
|
|
fi
|
|
|
|
-indexInclude="" mainInclude="" bdbInclude="# " nullExclude=""
|
|
+indexInclude="" mainInclude="" " nullExclude=""
|
|
test $INDEXDB = indexdb || indexInclude="# "
|
|
test $MAINDB = maindb || mainInclude="# "
|
|
case $BACKEND in
|
|
-bdb | hdb) bdbInclude="" ;;
|
|
null) nullExclude="# " ;;
|
|
esac
|
|
|
|
@@ -114,7 +113,6 @@ olcRootDN: cn=Manager,$BASEDN
|
|
olcRootPW:: c2VjcmV0
|
|
olcMonitoring: TRUE
|
|
${nullExclude}olcDbDirectory: $TESTDIR/db.1.a/
|
|
-${bdbInclude}olcDbCacheSize: 1000
|
|
${indexInclude}olcDbIndex: objectClass eq
|
|
${indexInclude}olcDbIndex: cn pres,eq,sub
|
|
${indexInclude}olcDbIndex: uid pres,eq,sub
|
|
diff --git a/tests/scripts/test056-monitor b/tests/scripts/test056-monitor
|
|
index 06713df..7a87eaa 100755
|
|
--- a/tests/scripts/test056-monitor
|
|
+++ b/tests/scripts/test056-monitor
|
|
@@ -85,8 +85,7 @@ echo "Using ldapsearch to read database monitor entries..."
|
|
$LDAPSEARCH -S "" -b "$DATABASESMONITORDN" -h $LOCALHOST -p $PORT1 \
|
|
'objectclass=*' \
|
|
structuralObjectClass entryDN namingContexts readOnly \
|
|
- monitorIsShadow monitorContext \
|
|
- olmBDBEntryCache olmBDBDNCache olmBDBIDLCache \
|
|
+ monitorIsShadow monitorContext
|
|
> $SEARCHOUT 2>&1
|
|
RC=$?
|
|
|
|
@@ -101,11 +100,8 @@ $LDIFFILTER -b monitor < $SEARCHOUT > $SEARCHFLT
|
|
|
|
TMPMONITOROUT2=$MONITOROUT2
|
|
case $BACKEND in
|
|
-bdb|hdb)
|
|
- ;;
|
|
*)
|
|
TMPMONITOROUT2=$TESTDIR/monitor2.out
|
|
- grep -v "olmBDB" $MONITOROUT2 > $TMPMONITOROUT2
|
|
;;
|
|
esac
|
|
|
|
diff --git a/tests/scripts/test057-memberof-refint b/tests/scripts/test057-memberof-refint
|
|
index 5f02a77..ba480f8 100755
|
|
--- a/tests/scripts/test057-memberof-refint
|
|
+++ b/tests/scripts/test057-memberof-refint
|
|
@@ -27,11 +27,6 @@ if test $REFINT = refintno; then
|
|
exit 0
|
|
fi
|
|
|
|
-if test $BACKEND = bdb; then
|
|
- echo "$BACKEND backend does not support subtree rename, test skipped"
|
|
- exit 0
|
|
-fi
|
|
-
|
|
mkdir -p $TESTDIR $DBDIR1 $TESTDIR/confdir
|
|
|
|
$SLAPPASSWD -g -n >$CONFIGPWF
|
|
@@ -66,11 +61,10 @@ fi
|
|
|
|
cat /dev/null > $TESTOUT
|
|
|
|
-indexInclude="" mainInclude="" bdbInclude="# " nullExclude=""
|
|
+indexInclude="" mainInclude="" nullExclude=""
|
|
test $INDEXDB = indexdb || indexInclude="# "
|
|
test $MAINDB = maindb || mainInclude="# "
|
|
case $BACKEND in
|
|
-bdb | hdb) bdbInclude="" ;;
|
|
null) nullExclude="# " ;;
|
|
esac
|
|
|
|
@@ -104,7 +98,6 @@ olcRootDN: cn=Manager,$BASEDN
|
|
olcRootPW:: c2VjcmV0
|
|
olcMonitoring: TRUE
|
|
${nullExclude}olcDbDirectory: $TESTDIR/db.1.a/
|
|
-${bdbInclude}olcDbCacheSize: 1000
|
|
${indexInclude}olcDbIndex: objectClass eq
|
|
${indexInclude}olcDbIndex: cn pres,eq,sub
|
|
${indexInclude}olcDbIndex: uid pres,eq,sub
|
|
diff --git a/tests/scripts/test061-syncreplication-initiation b/tests/scripts/test061-syncreplication-initiation
|
|
index 5d27e52..fda7a1b 100755
|
|
--- a/tests/scripts/test061-syncreplication-initiation
|
|
+++ b/tests/scripts/test061-syncreplication-initiation
|
|
@@ -63,7 +63,6 @@ KILLPIDS=
|
|
$SLAPPASSWD -g -n >$CONFIGPWF
|
|
|
|
case "$BACKEND" in
|
|
- bdb|hdb) olcDbCheckpoint="olcDbCheckpoint";;
|
|
*) olcDbCheckpoint="# olcDbCheckpoint";;
|
|
esac
|
|
|
|
--
|
|
2.19.1
|
|
|