ITS#9010 - Delete back-bdb/back-hdb

This commits deletes all references and code for back-bdb and back-hdb.
There is some follow up work still necessary to flush out the admin
guide for back-mdb.
This commit is contained in:
Quanah Gibson-Mount 2019-05-03 22:52:59 +00:00
parent ebf0ef5cb1
commit ec2cb12e68
101 changed files with 442 additions and 20199 deletions

27
.gitignore vendored
View File

@ -152,33 +152,6 @@ libraries/librewrite/rewrite
libraries/librewrite/version.c
servers/slapd/.backend
servers/slapd/all-cffiles
servers/slapd/back-hdb/add.c
servers/slapd/back-hdb/attr.c
servers/slapd/back-hdb/bind.c
servers/slapd/back-hdb/cache.c
servers/slapd/back-hdb/compare.c
servers/slapd/back-hdb/config.c
servers/slapd/back-hdb/dbcache.c
servers/slapd/back-hdb/delete.c
servers/slapd/back-hdb/dn2entry.c
servers/slapd/back-hdb/dn2id.c
servers/slapd/back-hdb/error.c
servers/slapd/back-hdb/extended.c
servers/slapd/back-hdb/filterindex.c
servers/slapd/back-hdb/id2entry.c
servers/slapd/back-hdb/idl.c
servers/slapd/back-hdb/index.c
servers/slapd/back-hdb/init.c
servers/slapd/back-hdb/key.c
servers/slapd/back-hdb/modify.c
servers/slapd/back-hdb/modrdn.c
servers/slapd/back-hdb/monitor.c
servers/slapd/back-hdb/nextid.c
servers/slapd/back-hdb/operational.c
servers/slapd/back-hdb/referral.c
servers/slapd/back-hdb/search.c
servers/slapd/back-hdb/tools.c
servers/slapd/back-hdb/trans.c
servers/slapd/backends.c
servers/slapd/overlays/statover.c
servers/slapd/slapacl

View File

@ -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

View File

@ -270,298 +270,6 @@ if test $ac_cv_header_unicode_utypes_h = yes ; then
fi
fi
])
dnl
dnl ====================================================================
dnl Berkeley DB macros
dnl
dnl --------------------------------------------------------------------
dnl Try to link
AC_DEFUN([OL_BERKELEY_DB_TRY],
[if test $ol_cv_lib_db = no ; then
AC_CACHE_CHECK([for Berkeley DB link (]ifelse($2,,default,$2)[)],[$1],
[
ol_DB_LIB=ifelse($2,,,$2)
ol_LIBS=$LIBS
LIBS="$ol_DB_LIB $LTHREAD_LIBS $LIBS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#ifdef HAVE_DB_185_H
# include <db_185.h>
#else
# include <db.h>
#endif
#ifndef DB_VERSION_MAJOR
# define DB_VERSION_MAJOR 1
#endif
#ifndef NULL
#define NULL ((void*)0)
#endif
]], [[
#if DB_VERSION_MAJOR > 2
db_env_create( NULL, 0 );
#elif DB_VERSION_MAJOR > 1
db_appexit( NULL );
#else
(void) dbopen( NULL, 0, 0, 0, NULL);
#endif
]])],[$1=yes],[$1=no])
LIBS="$ol_LIBS"
])
if test $$1 = yes ; then
ol_cv_lib_db=ifelse($2,,yes,$2)
fi
fi
])
dnl
dnl --------------------------------------------------------------------
dnl Get major and minor version from <db.h>
AC_DEFUN([OL_BDB_HEADER_VERSION],
[AC_CACHE_CHECK([for Berkeley DB major version in db.h], [ol_cv_bdb_major],[
AC_LANG_CONFTEST([AC_LANG_SOURCE([
#include <db.h>
#ifndef DB_VERSION_MAJOR
# define DB_VERSION_MAJOR 1
#endif
__db_version DB_VERSION_MAJOR
])])
set X `eval "$ac_cpp -P conftest.$ac_ext" | $EGREP __db_version` none none
ol_cv_bdb_major=${3}
])
case $ol_cv_bdb_major in [[1-9]]*) : ;; *)
AC_MSG_ERROR([Unknown Berkeley DB major version in db.h]) ;;
esac
dnl Determine minor version
AC_CACHE_CHECK([for Berkeley DB minor version in db.h], [ol_cv_bdb_minor],[
AC_LANG_CONFTEST([AC_LANG_SOURCE([
#include <db.h>
#ifndef DB_VERSION_MINOR
# define DB_VERSION_MINOR 0
#endif
__db_version DB_VERSION_MINOR
])])
set X `eval "$ac_cpp -P conftest.$ac_ext" | $EGREP __db_version` none none
ol_cv_bdb_minor=${3}
])
case $ol_cv_bdb_minor in [[0-9]]*) : ;; *)
AC_MSG_ERROR([Unknown Berkeley DB minor version in db.h]) ;;
esac
])
dnl
dnl --------------------------------------------------------------------
dnl Try to locate appropriate library
AC_DEFUN([OL_BERKELEY_DB_LINK],
[ol_cv_lib_db=no
if test $ol_cv_bdb_major = 5 ; then
OL_BERKELEY_DB_TRY(ol_cv_db_db_5_dot_m,[-ldb-5.$ol_cv_bdb_minor])
OL_BERKELEY_DB_TRY(ol_cv_db_db5m,[-ldb5$ol_cv_bdb_minor])
OL_BERKELEY_DB_TRY(ol_cv_db_db_5m,[-ldb-5$ol_cv_bdb_minor])
OL_BERKELEY_DB_TRY(ol_cv_db_db_5_m,[-ldb-5-$ol_cv_bdb_minor])
OL_BERKELEY_DB_TRY(ol_cv_db_db_5,[-ldb-5])
OL_BERKELEY_DB_TRY(ol_cv_db_db5,[-ldb5])
elif test $ol_cv_bdb_major = 4 ; then
OL_BERKELEY_DB_TRY(ol_cv_db_db_4_dot_m,[-ldb-4.$ol_cv_bdb_minor])
OL_BERKELEY_DB_TRY(ol_cv_db_db4m,[-ldb4$ol_cv_bdb_minor])
OL_BERKELEY_DB_TRY(ol_cv_db_db_4m,[-ldb-4$ol_cv_bdb_minor])
OL_BERKELEY_DB_TRY(ol_cv_db_db_4_m,[-ldb-4-$ol_cv_bdb_minor])
OL_BERKELEY_DB_TRY(ol_cv_db_db_4,[-ldb-4])
OL_BERKELEY_DB_TRY(ol_cv_db_db4,[-ldb4])
fi
OL_BERKELEY_DB_TRY(ol_cv_db_db,[-ldb])
OL_BERKELEY_DB_TRY(ol_cv_db_none)
])
dnl
dnl --------------------------------------------------------------------
dnl Check if Berkeley DB version
AC_DEFUN([OL_BERKELEY_DB_VERSION],
[AC_CACHE_CHECK([for Berkeley DB library and header version match], [ol_cv_berkeley_db_version], [
ol_LIBS="$LIBS"
LIBS="$LTHREAD_LIBS $LIBS"
if test $ol_cv_lib_db != yes ; then
LIBS="$ol_cv_lib_db $LIBS"
fi
AC_RUN_IFELSE([AC_LANG_SOURCE([[
#ifdef HAVE_DB_185_H
choke me;
#else
#include <db.h>
#endif
#ifndef DB_VERSION_MAJOR
# define DB_VERSION_MAJOR 1
#endif
#ifndef NULL
#define NULL ((void *)0)
#endif
main()
{
#if DB_VERSION_MAJOR > 1
char *version;
int major, minor, patch;
version = db_version( &major, &minor, &patch );
if( major != DB_VERSION_MAJOR ||
minor != DB_VERSION_MINOR ||
patch != DB_VERSION_PATCH )
{
printf("Berkeley DB version mismatch\n"
"\theader: %s\n\tlibrary: %s\n",
DB_VERSION_STRING, version);
return 1;
}
#endif
return 0;
}]])],[ol_cv_berkeley_db_version=yes],[ol_cv_berkeley_db_version=no],[ol_cv_berkeley_db_version=cross])
LIBS="$ol_LIBS"
])
if test $ol_cv_berkeley_db_version = no ; then
AC_MSG_ERROR([Berkeley DB version mismatch])
fi
])dnl
dnl
dnl --------------------------------------------------------------------
dnl Check if Berkeley DB supports DB_THREAD
AC_DEFUN([OL_BERKELEY_DB_THREAD],
[AC_CACHE_CHECK([for Berkeley DB thread support], [ol_cv_berkeley_db_thread], [
ol_LIBS="$LIBS"
LIBS="$LTHREAD_LIBS $LIBS"
if test $ol_cv_lib_db != yes ; then
LIBS="$ol_cv_lib_db $LIBS"
fi
AC_RUN_IFELSE([AC_LANG_SOURCE([[
#ifdef HAVE_DB_185_H
choke me;
#else
#include <db.h>
#endif
#ifndef NULL
#define NULL ((void *)0)
#endif
main()
{
int rc;
u_int32_t flags = DB_CREATE |
#ifdef DB_PRIVATE
DB_PRIVATE |
#endif
DB_THREAD;
#if DB_VERSION_MAJOR > 2
DB_ENV *env = NULL;
rc = db_env_create( &env, 0 );
flags |= DB_INIT_MPOOL;
#ifdef DB_MPOOL_PRIVATE
flags |= DB_MPOOL_PRIVATE;
#endif
if( rc ) {
printf("BerkeleyDB: %s\n", db_strerror(rc) );
return rc;
}
#if (DB_VERSION_MAJOR > 3) || (DB_VERSION_MINOR >= 1)
rc = (env->open)( env, NULL, flags, 0 );
#else
rc = (env->open)( env, NULL, NULL, flags, 0 );
#endif
if ( rc == 0 ) {
rc = env->close( env, 0 );
}
if( rc ) {
printf("BerkeleyDB: %s\n", db_strerror(rc) );
return rc;
}
#else
DB_ENV env;
memset( &env, '\0', sizeof(env) );
rc = db_appinit( NULL, NULL, &env, flags );
if( rc == 0 ) {
db_appexit( &env );
}
unlink("__db_mpool.share");
unlink("__db_lock.share");
#endif
return rc;
}]])],[ol_cv_berkeley_db_thread=yes],[ol_cv_berkeley_db_thread=no],[ol_cv_berkeley_db_thread=cross])
LIBS="$ol_LIBS"
])
if test $ol_cv_berkeley_db_thread != no ; then
AC_DEFINE(HAVE_BERKELEY_DB_THREAD, 1,
[define if Berkeley DB has DB_THREAD support])
fi
])dnl
dnl
dnl --------------------------------------------------------------------
dnl Find any DB
AC_DEFUN([OL_BERKELEY_DB],
[ol_cv_berkeley_db=no
AC_CHECK_HEADERS(db.h)
if test $ac_cv_header_db_h = yes; then
OL_BDB_HEADER_VERSION
OL_BDB_COMPAT
if test $ol_cv_bdb_compat != yes ; then
AC_MSG_ERROR([BerkeleyDB version incompatible with BDB/HDB backends])
fi
OL_BERKELEY_DB_LINK
if test "$ol_cv_lib_db" != no ; then
ol_cv_berkeley_db=yes
OL_BERKELEY_DB_VERSION
OL_BERKELEY_DB_THREAD
fi
fi
])
dnl --------------------------------------------------------------------
dnl Check for version compatibility with back-bdb
AC_DEFUN([OL_BDB_COMPAT],
[AC_CACHE_CHECK([if Berkeley DB version supported by BDB/HDB backends], [ol_cv_bdb_compat],[
AC_EGREP_CPP(__db_version_compat,[
#include <db.h>
/* this check could be improved */
#ifndef DB_VERSION_MAJOR
# define DB_VERSION_MAJOR 1
#endif
#ifndef DB_VERSION_MINOR
# define DB_VERSION_MINOR 0
#endif
#ifndef DB_VERSION_PATCH
# define DB_VERSION_PATCH 0
#endif
#define DB_VERSION_FULL ((DB_VERSION_MAJOR<<16)|(DB_VERSION_MINOR<<8)|DB_VERSION_PATCH)
/* require 4.4 or later, but less than 6.0.20 */
#if DB_VERSION_FULL >= 0x040400 && DB_VERSION_FULL < 0x060014
__db_version_compat
#endif
#if DB_VERSION_FULL >= 0x060014
#error "BerkeleyDB 6.0.20+ license is incompatible with LDAP"
#endif
], [ol_cv_bdb_compat=yes], [ol_cv_bdb_compat=no])])
])
dnl
dnl ====================================================================

View File

@ -163,7 +163,6 @@ CLIENT_LIBS = @CLIENT_LIBS@
LUTIL_LIBS = @LUTIL_LIBS@
LTHREAD_LIBS = @LTHREAD_LIBS@
BDB_LIBS = @BDB_LIBS@
SLAPD_NDB_LIBS = @SLAPD_NDB_LIBS@
WT_LIBS = @WT_LIBS@

View File

@ -300,9 +300,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 \
@ -323,12 +321,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],
no, [no yes mod], ol_enable_backends)dnl
OL_ARG_ENABLE(dnssrv,[ --enable-dnssrv enable dnssrv backend],
no, [no yes mod], ol_enable_backends)dnl
OL_ARG_ENABLE(hdb,[ --enable-hdb enable Hierarchical DB backend],
no, [no yes mod], ol_enable_backends)dnl
OL_ARG_ENABLE(ldap,[ --enable-ldap enable ldap backend],
no, [no yes mod], ol_enable_backends)dnl
OL_ARG_ENABLE(mdb,[ --enable-mdb enable mdb database backend],
@ -498,9 +492,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 &&
@ -566,7 +558,6 @@ dnl ----------------------------------------------------------------
dnl Initialize vars
LDAP_LIBS=
BDB_LIBS=
SLAPD_NDB_LIBS=
SLAPD_NDB_INCS=
LTHREAD_LIBS=
@ -583,9 +574,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
@ -1883,36 +1872,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
@ -2667,19 +2626,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
@ -2693,19 +2639,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
@ -3172,9 +3105,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)
@ -3217,7 +3148,6 @@ dnl overlays
AC_SUBST(LDAP_LIBS)
AC_SUBST(CLIENT_LIBS)
AC_SUBST(SLAPD_LIBS)
AC_SUBST(BDB_LIBS)
AC_SUBST(SLAPD_NDB_LIBS)
AC_SUBST(SLAPD_NDB_INCS)
AC_SUBST(LTHREAD_LIBS)
@ -3286,9 +3216,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]

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
H2: Obsolete Features Removed From 2.5
These features were strongly deprecated in 2.3 and removed in 2.4.
These features were strongly deprecated in 2.4 and removed in 2.5.
H3: Slurpd
H3: back-bdb and back-hdb
Please read the {{SECT:Replication}} section as to why this is no longer in
OpenLDAP
H3: back-ldbm
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.

View File

@ -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.

View File

@ -102,7 +102,6 @@ NOSYNC
env
pagedResultsControl
dup
hdb
LDIFv
syslog
monitorTimestamp
@ -886,7 +885,6 @@ proxyAttrSet
proxyAttrset
mary
crlcheck
olcBdbConfig
kadmin
mech
slapcat
@ -1189,7 +1187,6 @@ moddn
calloc
LDFLAGS
attributeOrValueExists
olcHdbConfig
bsize
auditObject
dnssrv
@ -1491,7 +1488,6 @@ ghenry
odbcinst
reqType
slapover
BerkeleyDB's
attributename
lwrap
reqStart
@ -1627,7 +1623,6 @@ DSAIT
olcHidden
mySNMP
metainformation
BerkeleyDB
ldapuri
auditAbandon
RANDFILE
@ -1661,7 +1656,6 @@ olcPasswordHash
ldapc
loopback
ldapi
BDB's
GETREALM
functionalities
noplain
@ -1669,7 +1663,6 @@ NOECHOPROMPT
AES
ldaps
notoc
bdb
LDAPv
IPsec
olcServerID

View File

@ -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
are deprecated in favor of the new {{mdb}} backend. See below.
H3: back-bdb/back-hdb Configuration
MORE LATER
H3: Further Information
{{slapd-bdb}}(5)
> moduleload back_mdb.la
H2: LDAP
@ -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 replaces the BerkeleyDB backends used in older
OpenLDAP releases.
It supports indexing like the BDB backends, but it uses no caching and requires
no tuning to deliver maximum search performance. Like {{hdb}}, it is also
fully hierarchical and supports subtree renames in constant time.
It supports indexing, it uses no caching, and requires no tuning to deliver
maximum search performance. It is fully hierarchical and supports subtree
renames in constant time.
H3: back-mdb Configuration
Unlike the BDB backends, the {{mdb}} backend can be instantiated with very few
configuration lines:
The {{mdb}} backend can be instantiated with very few configuration lines:
> include ./schema/core.schema
>
@ -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,

View File

@ -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

View File

@ -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

View File

@ -20,23 +20,7 @@ The LMDB database can be copied live using the mdb_copy command. If the databas
is a sparse file via the use of the "writemap" environment flag, the resulting
copy will be the actual size of the database rather than a sparse copy.
2. Backup the Berkeley database itself and periodically back up the transaction
log files:
Berkeley DB produces transaction logs that can be used to reconstruct
changes from a given point in time. For example, if an administrator were willing to only
lose one hour's worth of changes, they could take down the server in
the middle of the night, copy the Berkeley database files offsite, and bring
the server back online. Then, on an hourly basis, they could force a
database checkpoint, capture the log files that have been generated in the
past hour, and copy them offsite. The accumulated log files, in combination
with the previous database backup, could be used with db_recover to
reconstruct the database up to the time the last collection of log files was
copied offsite. This method affords good protection, with minimal space
overhead.
3. Periodically run slapcat and back up the LDIF file:
2. Periodically run slapcat and back up the LDIF file:
Slapcat can be run while slapd is active. However, one runs the risk of an
inconsistent database- not from the point of slapd, but from the point of
@ -52,71 +36,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-mdb, back-bdb, or back-hdb databases.
back-mdb databases.
> slapcat -f slapd.conf -b "dc=example,dc=com"
For back-mdb, back-bdb, and back-hdb, this command may be ran while slapd(8) is running.
H2: Berkeley DB Logs
Berkeley DB log files grow, and the administrator has to deal with it. The
procedure is known as log file archival or log file rotation.
Note: The actual log file rotation is handled by the Berkeley DB engine.
Logs of current transactions need to be stored into files so that the database
can be recovered in the event of an application crash. Administrators can change
the size limit of a single log file (by default 10MB), and have old log files
removed automatically, by setting up DB environment (see below). The reason
Berkeley DB never deletes any log files by default is that the administrator
may wish to backup the log files before removal to make database recovery
possible even after a catastrophic failure, such as file system corruption.
Log file names are {{F:log.XXXXXXXXXX}} (X is a digit). By default the log files
are located in the BDB backend directory. The {{F:db_archive}} tool knows what
log files are used in current transactions, and what are not. Administrators can
move unused log files to a backup media, and delete them. To have them removed
automatically, place set_flags {{DB_LOG_AUTOREMOVE}} directive in {{F:DB_CONFIG}}.
Note: If the log files are removed automatically, recovery after a catastrophic
failure is likely to be impossible.
The files with names {{F:__db.001}}, {{F:__db.002}}, etc are just shared memory
regions (or whatever). These ARE NOT 'logs', they must be left alone. Don't be
afraid of them, they do not grow like logs do.
To understand the {{F:db_archive}} interface, the reader should refer to
chapter 9 of the Berkeley DB guide. In particular, the following chapters are
recommended:
* Database and log file archival - {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/ref/transapp/archival.html}}
* Log file removal - {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/ref/transapp/logfile.html}}
* Recovery procedures - {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/ref/transapp/recovery.html}}
* Hot failover - {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/ref/transapp/hotfail.html}}
* Complete list of Berkeley DB flags - {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/api_c/env_set_flags.html}}
Advanced installations can use special environment settings to fine-tune some
Berkeley DB options (change the log file limit, etc). This can be done by using
the {{F:DB_CONFIG}} file. This magic file can be created in BDB backend directory
set up by {{slapd.conf}}(5). More information on this file can be found in File
naming chapter. Specific directives can be found in C Interface, look for
{{DB_ENV->set_XXXX}} calls.
Note: options set in {{F:DB_CONFIG}} file override options set by OpenLDAP.
Use them with extreme caution. Do not use them unless You know what You are doing.
The advantages of {{F:DB_CONFIG}} usage can be the following:
* to keep data files and log files on different mediums (i.e. disks) to improve
performance and/or reliability;
* to fine-tune some specific options (such as shared memory region sizes);
* to set the log file limit (please read Log file limits before doing this).
To figure out the best-practice BDB backup scenario, the reader is highly
recommended to read the whole Chapter 9: Berkeley DB Transactional Data Store Applications.
This chapter is a set of small pages with examples in C language. Non-programming
people can skip these examples without loss of knowledge.
For back-mdb this command may be ran while slapd(8) is running.
H2: Checkpointing
@ -152,7 +76,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}}

View File

@ -214,12 +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
@ -243,33 +241,6 @@ 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
> monitorRuntimeConfig: TRUE
> supportedControl: 1.3.6.1.1.12
> supportedControl: 2.16.840.1.113730.3.4.2
> supportedControl: 1.3.6.1.4.1.4203.666.5.2
> supportedControl: 1.2.840.113556.1.4.319
> supportedControl: 1.3.6.1.1.13.1
> supportedControl: 1.3.6.1.1.13.2
> supportedControl: 1.3.6.1.4.1.4203.1.10.1
> supportedControl: 1.2.840.113556.1.4.1413
> supportedControl: 1.3.6.1.4.1.4203.666.11.7.2
>
> dn: cn=Backend 5,cn=Backends,cn=Monitor
> monitoredInfo: mdb
> monitorRuntimeConfig: TRUE
> supportedControl: 1.3.6.1.1.12

View File

@ -86,7 +86,7 @@ H3: Access Logging Configuration
The following is a basic example that implements Access Logging:
> database bdb
> database mdb
> suffix dc=example,dc=com
> ...
> overlay accesslog
@ -94,7 +94,7 @@ The following is a basic example that implements Access Logging:
> logops writes reads
> logold (objectclass=person)
>
> database bdb
> database mdb
> suffix cn=log
> ...
> index reqStart eq
@ -103,7 +103,7 @@ The following is a basic example that implements Access Logging:
The following is an example used for {{SECT:delta-syncrepl replication}}:
> database hdb
> database mdb
> suffix cn=accesslog
> directory /usr/local/var/openldap-accesslog
> rootdn cn=accesslog
@ -112,7 +112,7 @@ The following is an example used for {{SECT:delta-syncrepl replication}}:
Accesslog overlay definitions for the primary db
> database bdb
> database mdb
> suffix dc=example,dc=com
> ...
> overlay accesslog
@ -619,7 +619,7 @@ specific database. For example, with the following minimal slapd.conf:
>
> authz-regexp "gidNumber=0\\\+uidNumber=0,cn=peercred,cn=external,cn=auth"
> "cn=Manager,dc=example,dc=com"
> database bdb
> database mdb
> suffix "dc=example,dc=com"
> rootdn "cn=Manager,dc=example,dc=com"
> rootpw secret
@ -738,7 +738,7 @@ 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:bdb}} or {{EX:hdb}}. The <maxentries> parameter specifies the
{{EX:mdb}}. The <maxentries> parameter specifies the
total number of entries which may be held in the cache. The
<nattrsets> parameter specifies the total number of attribute sets
(as specified by the {{EX:pcacheAttrset}} directive) that may be
@ -777,7 +777,7 @@ at server {{EX:ldap.example.com}}.
> rootdn "dc=example,dc=com"
> uri ldap://ldap.example.com/
> overlay pcache
> pcache hdb 100000 1 1000 100
> pcache mdb 100000 1 1000 100
> pcacheAttrset 0 mail postaladdress telephonenumber
> pcacheTemplate (sn=) 0 3600
> pcacheTemplate (&(sn=)(givenName=)) 0 3600
@ -806,7 +806,7 @@ at server {{EX:ldap.example.com}}.
> objectClass: olcOverlayConfig
> objectClass: olcPcacheConfig
> olcOverlay: {0}pcache
> olcPcache: hdb 100000 1 1000 100
> olcPcache: mdb 100000 1 1000 100
> olcPcacheAttrset: 0 mail postalAddress telephoneNumber
> olcPcacheTemplate: "(sn=)" 0 3600 0 0 0
> olcPcacheTemplate: "(&(sn=)(givenName=))" 0 3600 0 0 0
@ -889,7 +889,7 @@ the ppolicy module being added to the database that handles the naming
context "dc=example,dc=com". In this example we are also specifying the DN of
a policy object to use if none other is specified in a user's object.
> database bdb
> database mdb
> suffix "dc=example,dc=com"
> [...additional database configuration directives go here...]
>
@ -978,7 +978,7 @@ H2: Referential Integrity
H3: Overview
This overlay can be used with a backend database such as slapd-bdb(5)
This overlay can be used with a backend database such as slapd-mdb(5)
to maintain the cohesiveness of a schema which utilizes reference
attributes.
@ -1173,7 +1173,7 @@ H2: Translucent Proxy
H3: Overview
This overlay can be used with a backend database such as {{:slapd-bdb}}(5)
This overlay can be used with a backend database such as {{:slapd-mdb}}(5)
to create a "translucent proxy".
Entries retrieved from a remote LDAP server may have some or all attributes
@ -1212,7 +1212,7 @@ First we configure the overlay in the normal manner:
> pidfile ./slapd.pid
> argsfile ./slapd.args
>
> database bdb
> database mdb
> suffix "dc=suretecsystems,dc=com"
> rootdn "cn=trans,dc=suretecsystems,dc=com"
> rootpw secret
@ -1305,7 +1305,7 @@ H2: Attribute Uniqueness
H3: Overview
This overlay can be used with a backend database such as {{slapd-bdb(5)}}
This overlay can be used with a backend database such as {{slapd-mdb(5)}}
to enforce the uniqueness of some or all attributes within a subtree.
@ -1390,7 +1390,7 @@ Here are a few examples:
> loglevel sync stats
>
> database hdb
> database mdb
> suffix "dc=suretecsystems,dc=com"
> directory /usr/local/var/openldap-data
>

View File

@ -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}}
backend.
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
@ -674,8 +671,8 @@ replica servers:
> # Set the module path location
> modulepath /opt/symas/lib/openldap
>
> # Load the hdb backend
> moduleload back_hdb.la
> # Load the mdb backend
> moduleload back_mdb.la
>
> # Load the accesslog overlay
> moduleload accesslog.la
@ -684,7 +681,7 @@ replica servers:
> moduleload syncprov.la
>
> # Accesslog database definitions
> database hdb
> database mdb
> suffix cn=accesslog
> directory /db/accesslog
> rootdn cn=accesslog
@ -699,7 +696,7 @@ replica servers:
> limits dn.exact="cn=replicator,dc=symas,dc=com" time.soft=unlimited time.hard=unlimited size.soft=unlimited size.hard=unlimited
>
> # Primary database definitions
> database hdb
> database mdb
> suffix "dc=symas,dc=com"
> rootdn "cn=manager,dc=symas,dc=com"
>
@ -730,7 +727,7 @@ For more information, always consult the relevant man pages ({{slapo-accesslog}}
H4: Delta-syncrepl Consumer configuration
> # Replica database configuration
> database hdb
> database mdb
> suffix "dc=symas,dc=com"
> rootdn "cn=manager,dc=symas,dc=com"
>
@ -759,10 +756,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.
@ -978,7 +972,7 @@ The following example is for a self-contained push-based replication solution:
> include /usr/local/etc/openldap/slapd.acl
>
> modulepath /usr/local/libexec/openldap
> moduleload back_hdb.la
> moduleload back_mdb.la
> moduleload syncprov.la
> moduleload back_monitor.la
> moduleload back_ldap.la
@ -988,7 +982,7 @@ The following example is for a self-contained push-based replication solution:
>
> loglevel sync stats
>
> database hdb
> database mdb
> suffix "dc=suretecsystems,dc=com"
> directory /usr/local/var/openldap-data
>
@ -1064,7 +1058,7 @@ A replica configuration for this type of setup could be:
> include /usr/local/etc/openldap/slapd.acl
>
> modulepath /usr/local/libexec/openldap
> moduleload back_hdb.la
> moduleload back_mdb.la
> moduleload syncprov.la
> moduleload back_monitor.la
> moduleload back_ldap.la
@ -1074,7 +1068,7 @@ A replica configuration for this type of setup could be:
>
> loglevel sync stats
>
> database hdb
> database mdb
> suffix "dc=suretecsystems,dc=com"
> directory /usr/local/var/openldap-slave/data
>

View File

@ -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
* {{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.
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}}
* {{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.
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.
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>
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.
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: 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>
H4: olcDbNosync: { TRUE | FALSE }
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:
> 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,9 +1045,9 @@ 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
Line 29 is a comment. Lines 30-33 identify this entry as a MDB database
configuration entry. Line 34 specifies the DN suffix
for queries to pass to this database. Line 35 specifies the directory
in which the database files will live.
@ -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"

View File

@ -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
@ -279,9 +277,9 @@ sql SQL Programmable backend
\Example:
> backend bdb
> backend mdb
This marks the beginning of a new {{TERM:BDB}} backend
This marks the beginning of a new {{TERM:MDB}} backend
definition.
@ -299,9 +297,9 @@ supported backend types listed in Table 6.2.
\Example:
> database bdb
> database mdb
This marks the beginning of a new {{TERM:BDB}} database instance
This marks the beginning of a new {{TERM:MDB}} database instance
declaration.
@ -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}} backend.
See the {{SECT:LDAP Sync Replication}} chapter of this guide for
more information on how to use this directive.
@ -584,31 +581,207 @@ 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:
> 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 +790,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 +802,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 +810,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"
@ -678,13 +851,13 @@ All other attributes are writable by the entry and the "admin"
entry, but may be read by all users (authenticated or not).
The next section of the example configuration file defines another
BDB database. This one handles queries involving the
MDB database. This one handles queries involving the
{{EX:dc=example,dc=net}} subtree but is managed by the same entity
as the first database. Note that without line 39, the read access
would be allowed due to the global access rule at line 4.
E: 33. # BDB definition for example.net
E: 34. database bdb
E: 33. # MDB definition for example.net
E: 34. database mdb
E: 35. suffix "dc=example,dc=net"
E: 36. directory /usr/local/var/openldap-data-net
E: 37. rootdn "cn=Manager,dc=example,dc=com"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,286 +0,0 @@
.TH SLAPD-BDB 5 "RELEASEDATE" "OpenLDAP LDVERSION"
.\" Copyright 1998-2019 The OpenLDAP Foundation All Rights Reserved.
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.\" $OpenLDAP$
.SH NAME
slapd\-bdb, slapd\-hdb \- Berkeley DB backends to slapd
.SH SYNOPSIS
.B ETCDIR/slapd.conf
.SH DESCRIPTION
The \fBbdb\fP backend to
.BR slapd (8)
uses the Oracle Berkeley DB (BDB) package to store data.
It makes extensive use of indexing and caching to speed data access.
.LP
Note that BDB is deprecated and support will be dropped in future
OpenLDAP releases. Installations should use the \fBmdb\fP
backend instead.
.LP
\fBhdb\fP is a variant of
the \fBbdb\fP backend that uses a hierarchical database layout which
supports subtree renames. It is both more space-efficient and more
execution-efficient than the \fBbdb\fP backend. It is otherwise identical
to the \fBbdb\fP behavior, and all the same configuration options apply.
.LP
It is noted that these options are intended to complement
Berkeley DB configuration options set in the environment's
.B DB_CONFIG
file. See Berkeley DB documentation for details on
.B DB_CONFIG
configuration options.
Where there is overlap, settings in
.B DB_CONFIG
take precedence.
.SH CONFIGURATION
These
.B slapd.conf
options apply to the \fBbdb\fP and \fBhdb\fP backend database.
That is, they must follow a "database bdb" or "database hdb" line and
come before any subsequent "backend" or "database" lines.
Other database options are described in the
.BR slapd.conf (5)
manual page.
.TP
.BI cachesize \ <integer>
Specify the size in entries of the in-memory entry cache maintained
by the \fBbdb\fP or \fBhdb\fP backend database instance.
The default is 1000 entries.
.TP
.BI cachefree \ <integer>
Specify the number of entries to free from the entry cache when the
cache reaches the \fBcachesize\fP limit.
The default is 1 entry.
.TP
.BI checkpoint \ <kbyte>\ <min>
Specify the frequency for checkpointing the database transaction log.
A checkpoint operation flushes the database buffers to disk and writes
a checkpoint record in the log.
The checkpoint will occur if either \fI<kbyte>\fP data has been written or
\fI<min>\fP minutes have passed since the last checkpoint.
Both arguments default to zero, in which case they are ignored. When
the \fI<min>\fP argument is non-zero, an internal task will run every
\fI<min>\fP minutes to perform the checkpoint.
See the Berkeley DB reference guide for more details.
.TP
.B checksum
Enable checksum validation of DB pages whenever they are read from disk.
This setting can only be configured before any database files are created.
.TP
.BI cryptfile \ <file>
Specify the pathname of a file containing an encryption key to use for
encrypting the database. Encryption is performed using Berkeley DB's
implementation of AES. Note that encryption can only be configured before
any database files are created, and changing the key can only be done
after destroying the current database and recreating it. Encryption is
not enabled by default, and some distributions of Berkeley DB do not
support encryption.
.TP
.BI cryptkey \ <key>
Specify an encryption key to use for encrypting the database. This option
may be used when a separate
.I cryptfile
is not desired. Only one of
.B cryptkey
or
.B cryptfile
may be configured.
.TP
.BI dbconfig \ <Berkeley-DB-setting>
Specify a configuration directive to be placed in the
.B DB_CONFIG
file of the database directory. The
.B dbconfig
directive is just a convenience
to allow all necessary configuration to be set in the
.B slapd.conf
file.
The options set using this directive will only be written to the
.B DB_CONFIG
file if no such file existed at server startup time, otherwise
they are completely ignored. This allows one
to set initial values without overwriting/destroying a
.B DB_CONFIG
file that was already customized through other means.
This directive may be specified multiple times, as needed.
For example:
.RS
.nf
dbconfig set_cachesize 0 1048576 0
dbconfig set_lg_bsize 2097152
.fi
.RE
.TP
.B dbnosync
Specify that on-disk database contents should not be immediately
synchronized with in memory changes.
Enabling this option may improve performance at the expense of data
security.
See the Berkeley DB reference guide for more details.
.TP
\fBdbpagesize \fR \fI<dbfile> <size>\fR
Specify the page size to use for a particular database file, in units
of 1024 bytes. The default for the
.B id2entry
file is 16, the default for all other files depends on the size of the
underlying filesystem's block size (typically 4 or 8).
The maximum that BerkeleyDB supports is 64. This
setting usually should not need to be changed, but if BerkeleyDB's
"db_stat \-d" shows a large amount of overflow pages in use in a file,
setting a larger size may increase performance at the expense of
data integrity. This setting only takes effect when a database is
being newly created. See the Berkeley DB reference guide for more details.
.TP
.BI directory \ <directory>
Specify the directory where the BDB files containing this database and
associated indexes live.
A separate directory must be specified for each database.
The default is
.BR LOCALSTATEDIR/openldap\-data .
.TP
.B dirtyread
Allow reads of modified but not yet committed data.
Usually transactions are isolated to prevent other operations from
accessing uncommitted data.
This option may improve performance, but may also return inconsistent
results if the data comes from a transaction that is later aborted.
In this case, the modified data is discarded and a subsequent search
will return a different result.
.TP
.BI dncachesize \ <integer>
Specify the maximum number of DNs in the in-memory DN cache.
Ideally this cache should be
large enough to contain the DNs of every entry in the database. If
set to a smaller value than the \fBcachesize\fP it will be silently
increased to equal the \fBcachesize\fP. The default value is 0 which
means unlimited, i.e. the DN cache will grow without bound.
It should be noted that the \fBDN cache\fP is allowed to temporarily
grow beyond the configured size. It does this if many entries are
locked when it tries to do a purge, because that means they're
legitimately in use. Also, the \fBDN cache\fP never purges entries
that have cached children, so depending on the shape of the DIT, it
could have lots of cached DNs over the defined limit.
.TP
.BI idlcachesize \ <integer>
Specify the size of the in-memory index cache, in index slots. The
default is zero. A larger value will speed up frequent searches of
indexed entries. An \fBhdb\fP database needs a large \fBidlcachesize\fP
for good search performance, typically three times the
.B cachesize
(entry cache size)
or larger.
.TP
\fBindex \fR{\fI<attrlist>\fR|\fBdefault\fR} [\fBpres\fR,\fBeq\fR,\fBapprox\fR,\fBsub\fR,\fI<special>\fR]
Specify the indexes to maintain for the given attribute (or
list of attributes).
Some attributes only support a subset of indexes.
If only an \fI<attr>\fP is given, the indices specified for \fBdefault\fR
are maintained.
Note that setting a default does not imply that all attributes will be
indexed. Also, for best performance, an
.B eq
index should always be configured for the
.B objectClass
attribute.
A number of special index parameters may be specified.
The index type
.B sub
can be decomposed into
.BR subinitial ,
.BR subany ,\ and
.B subfinal
indices.
The special type
.B nolang
may be specified to disallow use of this index by language subtypes.
The special type
.B nosubtypes
may be specified to disallow use of this index by named subtypes.
Note: changing \fBindex\fP settings in
.BR slapd.conf (5)
requires rebuilding indices, see
.BR slapindex (8);
changing \fBindex\fP settings
dynamically by LDAPModifying "cn=config" automatically causes rebuilding
of the indices online in a background task.
.TP
.B linearindex
Tell
.B slapindex
to index one attribute at a time. By default, all indexed
attributes in an entry are processed at the same time. With this option,
each indexed attribute is processed individually, using multiple passes
through the entire database. This option improves
.B slapindex
performance
when the database size exceeds the \fBdbcache\fP size. When the \fBdbcache\fP is
large enough, this option is not needed and will decrease performance.
Also by default,
.B slapadd
performs full indexing and so a separate
.B slapindex
run is not needed. With this option,
.B slapadd
does no indexing and
.B slapindex
must be used.
.TP
.BR lockdetect \ { oldest | youngest | fewest | random | default }
Specify which transaction to abort when a deadlock is detected.
The default is
.BR random .
.TP
.BI mode \ <integer>
Specify the file protection mode that newly created database
index files should have.
The default is 0600.
.TP
.BI searchstack \ <depth>
Specify the depth of the stack used for search filter evaluation.
Search filters are evaluated on a stack to accommodate nested AND / OR
clauses. An individual stack is assigned to each server thread.
The depth of the stack determines how complex a filter can be
evaluated without requiring any additional memory allocation. Filters that
are nested deeper than the search stack depth will cause a separate
stack to be allocated for that particular search operation. These
allocations can have a major negative impact on server performance,
but specifying too much stack will also consume a great deal of memory.
Each search stack uses 512K bytes per level. The default stack depth
is 16, thus 8MB per thread is used.
.TP
.BI shm_key \ <integer>
Specify a key for a shared memory BDB environment. By default the
BDB environment uses memory mapped files. If a non-zero value is
specified, it will be used as the key to identify a shared memory
region that will house the environment.
.SH ACCESS CONTROL
The
.B bdb
and
.B hdb
backends honor access control semantics as indicated in
.BR slapd.access (5).
.SH FILES
.TP
.B ETCDIR/slapd.conf
default
.B slapd
configuration file
.TP
.B DB_CONFIG
Berkeley DB configuration file
.SH SEE ALSO
.BR slapd.conf (5),
.BR slapd\-config (5),
.BR slapd\-mdb (5),
.BR slapd (8),
.BR slapadd (8),
.BR slapcat (8),
.BR slapindex (8),
Berkeley DB documentation.
.SH ACKNOWLEDGEMENTS
.so ../Project
Originally begun by Kurt Zeilenga. Caching mechanisms originally designed
by Jong-Hyuk Choi. Completion and subsequent work, as well as
back-hdb, by Howard Chu.

View File

@ -1 +0,0 @@
slapd-hdb.5

View File

@ -1149,10 +1149,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 ,
@ -2091,10 +2089,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

View File

@ -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

View File

@ -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 LMDB (as the standard MDB backend does), though it can be
used as such with several limitations.
You can take a look at
.B http://www.openldap.org/faq/index.cgi?file=378

View File

@ -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),

View File

@ -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),

View File

@ -1276,10 +1276,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 ,
@ -1306,10 +1304,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 ,
@ -1619,8 +1615,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 database provides database-specific monitoring.
The default depends on the backend type.
.TP
.B overlay <overlay-name>

View File

@ -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

View File

@ -8,7 +8,7 @@ slapo\-refint \- Referential Integrity overlay to slapd
ETCDIR/slapd.conf
.SH DESCRIPTION
The Referential Integrity overlay can be used with a backend database such as
.BR slapd\-bdb (5)
.BR slapd\-mdb (5)
to maintain the cohesiveness of a schema which utilizes reference attributes.
.LP
Integrity is maintained by updating database records which contain the named

View File

@ -8,7 +8,7 @@ slapo\-translucent \- Translucent Proxy overlay to slapd
ETCDIR/slapd.conf
.SH DESCRIPTION
The Translucent Proxy overlay can be used with a backend database such as
.BR slapd\-bdb (5)
.BR slapd\-mdb (5)
to create a "translucent proxy". Entries retrieved from a remote LDAP
server may have some or all attributes overridden, or new attributes
added, by entries in the local database before being presented to the

View File

@ -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)

View File

@ -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.

View File

@ -96,12 +96,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
@ -927,9 +921,6 @@
/* define to support LDAP Async Metadirectory backend */
#undef SLAPD_ASYNCMETA
/* define to support BDB backend */
#undef SLAPD_BDB
/* define to support cleartext passwords */
#undef SLAPD_CLEARTEXT
@ -939,9 +930,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

View File

@ -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).

View File

@ -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 slapmodify.c \
aci.c txn.c slapschema.c slapmodify.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 slapmodify.o \
aci.o txn.o slapschema.o slapmodify.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)

View File

@ -1,718 +0,0 @@
/* alock.c - access lock library */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2005-2019 The OpenLDAP Foundation.
* Portions Copyright 2004-2005 Symas Corporation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* ACKNOWLEDGEMENTS:
* This work was initially developed by Emily Backes at Symas
* Corporation for inclusion in OpenLDAP Software.
*/
#include "portable.h"
#if SLAPD_BDB || SLAPD_HDB
#include <lber.h>
#include "alock.h"
#include "lutil.h"
#include <ac/stdlib.h>
#include <ac/string.h>
#include <ac/unistd.h>
#include <ac/errno.h>
#include <ac/assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#include <fcntl.h>
#ifdef _WIN32
#include <windows.h>
#include <stdio.h>
#include <io.h>
#endif
static int
alock_grab_lock ( int fd, int slot )
{
int res;
#if defined( HAVE_LOCKF )
res = lseek (fd, (off_t) (ALOCK_SLOT_SIZE * slot), SEEK_SET);
if (res == -1) return -1;
res = lockf (fd, F_LOCK, (off_t) ALOCK_SLOT_SIZE);
#elif defined( HAVE_FCNTL )
struct flock lock_info;
(void) memset ((void *) &lock_info, 0, sizeof (struct flock));
lock_info.l_type = F_WRLCK;
lock_info.l_whence = SEEK_SET;
lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
res = fcntl (fd, F_SETLKW, &lock_info);
#elif defined( _WIN32 )
OVERLAPPED ov;
HANDLE hh = _get_osfhandle ( fd );
ov.hEvent = 0;
ov.Offset = ALOCK_SLOT_SIZE*slot;
ov.OffsetHigh = 0;
res = LockFileEx( hh, LOCKFILE_EXCLUSIVE_LOCK, 0,
ALOCK_SLOT_SIZE, 0, &ov ) ? 0 : -1;
#else
# error alock needs lockf, fcntl, or LockFile[Ex]
#endif
if (res == -1) {
assert (errno != EDEADLK);
return -1;
}
return 0;
}
static int
alock_release_lock ( int fd, int slot )
{
int res;
#if defined( HAVE_LOCKF )
res = lseek (fd, (off_t) (ALOCK_SLOT_SIZE * slot), SEEK_SET);
if (res == -1) return -1;
res = lockf (fd, F_ULOCK, (off_t) ALOCK_SLOT_SIZE);
if (res == -1) return -1;
#elif defined ( HAVE_FCNTL )
struct flock lock_info;
(void) memset ((void *) &lock_info, 0, sizeof (struct flock));
lock_info.l_type = F_UNLCK;
lock_info.l_whence = SEEK_SET;
lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
res = fcntl (fd, F_SETLKW, &lock_info);
if (res == -1) return -1;
#elif defined( _WIN32 )
HANDLE hh = _get_osfhandle ( fd );
if ( !UnlockFile ( hh, ALOCK_SLOT_SIZE*slot, 0,
ALOCK_SLOT_SIZE, 0 ))
return -1;
#else
# error alock needs lockf, fcntl, or LockFile[Ex]
#endif
return 0;
}
static int
alock_share_lock ( int fd, int slot )
{
int res;
#if defined( HAVE_LOCKF )
res = 0; /* lockf has no shared locks */
#elif defined ( HAVE_FCNTL )
struct flock lock_info;
(void) memset ((void *) &lock_info, 0, sizeof (struct flock));
/* The shared lock replaces the existing lock */
lock_info.l_type = F_RDLCK;
lock_info.l_whence = SEEK_SET;
lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
res = fcntl (fd, F_SETLK, &lock_info);
if (res == -1) return -1;
#elif defined( _WIN32 )
OVERLAPPED ov;
HANDLE hh = _get_osfhandle ( fd );
/* Windows locks are mandatory, not advisory.
* We must downgrade the lock to allow future
* callers to read the slot data.
*
* First acquire a shared lock. Unlock will
* release the existing exclusive lock.
*/
ov.hEvent = 0;
ov.Offset = ALOCK_SLOT_SIZE*slot;
ov.OffsetHigh = 0;
LockFileEx (hh, 0, 0, ALOCK_SLOT_SIZE, 0, &ov);
UnlockFile (hh, ALOCK_SLOT_SIZE*slot, 0, ALOCK_SLOT_SIZE, 0);
#else
# error alock needs lockf, fcntl, or LockFile[Ex]
#endif
return 0;
}
static int
alock_test_lock ( int fd, int slot )
{
int res;
#if defined( HAVE_LOCKF )
res = lseek (fd, (off_t) (ALOCK_SLOT_SIZE * slot), SEEK_SET);
if (res == -1) return -1;
res = lockf (fd, F_TEST, (off_t) ALOCK_SLOT_SIZE);
if (res == -1) {
if (errno == EACCES || errno == EAGAIN) {
return ALOCK_LOCKED;
} else {
return -1;
}
}
#elif defined( HAVE_FCNTL )
struct flock lock_info;
(void) memset ((void *) &lock_info, 0, sizeof (struct flock));
lock_info.l_type = F_WRLCK;
lock_info.l_whence = SEEK_SET;
lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
res = fcntl (fd, F_GETLK, &lock_info);
if (res == -1) return -1;
if (lock_info.l_type != F_UNLCK) return ALOCK_LOCKED;
#elif defined( _WIN32 )
OVERLAPPED ov;
HANDLE hh = _get_osfhandle ( fd );
ov.hEvent = 0;
ov.Offset = ALOCK_SLOT_SIZE*slot;
ov.OffsetHigh = 0;
if( !LockFileEx( hh,
LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY, 0,
ALOCK_SLOT_SIZE, 0, &ov )) {
int err = GetLastError();
if ( err == ERROR_LOCK_VIOLATION )
return ALOCK_LOCKED;
else
return -1;
}
#else
# error alock needs lockf, fcntl, or LockFile
#endif
return 0;
}
/* Read a 64bit LE value */
static unsigned long int
alock_read_iattr ( unsigned char * bufptr )
{
unsigned long int val = 0;
int count;
assert (bufptr != NULL);
bufptr += sizeof (unsigned long int);
for (count=0; count <= (int) sizeof (unsigned long int); ++count) {
val <<= 8;
val += (unsigned long int) *bufptr--;
}
return val;
}
/* Write a 64bit LE value */
static void
alock_write_iattr ( unsigned char * bufptr,
unsigned long int val )
{
int count;
assert (bufptr != NULL);
for (count=0; count < 8; ++count) {
*bufptr++ = (unsigned char) (val & 0xff);
val >>= 8;
}
}
static int
alock_read_slot ( alock_info_t * info,
alock_slot_t * slot_data )
{
unsigned char slotbuf [ALOCK_SLOT_SIZE];
int res, size, size_total, err;
assert (info != NULL);
assert (slot_data != NULL);
assert (info->al_slot > 0);
res = lseek (info->al_fd,
(off_t) (ALOCK_SLOT_SIZE * info->al_slot),
SEEK_SET);
if (res == -1) return -1;
size_total = 0;
while (size_total < ALOCK_SLOT_SIZE) {
size = read (info->al_fd,
slotbuf + size_total,
ALOCK_SLOT_SIZE - size_total);
if (size == 0) return -1;
if (size < 0) {
err = errno;
if (err != EINTR && err != EAGAIN) return -1;
} else {
size_total += size;
}
}
if (alock_read_iattr (slotbuf) != ALOCK_MAGIC) {
return -1;
}
slot_data->al_lock = alock_read_iattr (slotbuf+8);
slot_data->al_stamp = alock_read_iattr (slotbuf+16);
slot_data->al_pid = alock_read_iattr (slotbuf+24);
if (slot_data->al_appname) ber_memfree (slot_data->al_appname);
slot_data->al_appname = ber_memcalloc (1, ALOCK_MAX_APPNAME);
if (slot_data->al_appname == NULL) {
return -1;
}
strncpy (slot_data->al_appname, (char *)slotbuf+32, ALOCK_MAX_APPNAME-1);
(slot_data->al_appname) [ALOCK_MAX_APPNAME-1] = '\0';
return 0;
}
static int
alock_write_slot ( alock_info_t * info,
alock_slot_t * slot_data )
{
unsigned char slotbuf [ALOCK_SLOT_SIZE];
int res, size, size_total, err;
assert (info != NULL);
assert (slot_data != NULL);
assert (info->al_slot > 0);
(void) memset ((void *) slotbuf, 0, ALOCK_SLOT_SIZE);
alock_write_iattr (slotbuf, ALOCK_MAGIC);
assert (alock_read_iattr (slotbuf) == ALOCK_MAGIC);
alock_write_iattr (slotbuf+8, slot_data->al_lock);
alock_write_iattr (slotbuf+16, slot_data->al_stamp);
alock_write_iattr (slotbuf+24, slot_data->al_pid);
if (slot_data->al_appname)
strncpy ((char *)slotbuf+32, slot_data->al_appname, ALOCK_MAX_APPNAME-1);
slotbuf[ALOCK_SLOT_SIZE-1] = '\0';
res = lseek (info->al_fd,
(off_t) (ALOCK_SLOT_SIZE * info->al_slot),
SEEK_SET);
if (res == -1) return -1;
size_total = 0;
while (size_total < ALOCK_SLOT_SIZE) {
size = write (info->al_fd,
slotbuf + size_total,
ALOCK_SLOT_SIZE - size_total);
if (size == 0) return -1;
if (size < 0) {
err = errno;
if (err != EINTR && err != EAGAIN) return -1;
} else {
size_total += size;
}
}
return 0;
}
static int
alock_query_slot ( alock_info_t * info )
{
int res, nosave;
alock_slot_t slot_data;
assert (info != NULL);
assert (info->al_slot > 0);
(void) memset ((void *) &slot_data, 0, sizeof (alock_slot_t));
alock_read_slot (info, &slot_data);
if (slot_data.al_appname != NULL) ber_memfree (slot_data.al_appname);
slot_data.al_appname = NULL;
nosave = slot_data.al_lock & ALOCK_NOSAVE;
if ((slot_data.al_lock & ALOCK_SMASK) == ALOCK_UNLOCKED)
return slot_data.al_lock;
res = alock_test_lock (info->al_fd, info->al_slot);
if (res < 0) return -1;
if (res > 0) {
if ((slot_data.al_lock & ALOCK_SMASK) == ALOCK_UNIQUE) {
return slot_data.al_lock;
} else {
return ALOCK_LOCKED | nosave;
}
}
return ALOCK_DIRTY | nosave;
}
int
alock_open ( alock_info_t * info,
const char * appname,
const char * envdir,
int locktype )
{
struct stat statbuf;
alock_info_t scan_info;
alock_slot_t slot_data;
char * filename;
int res, max_slot;
int dirty_count, live_count, nosave;
char *ptr;
assert (info != NULL);
assert (appname != NULL);
assert (envdir != NULL);
assert ((locktype & ALOCK_SMASK) >= 1 && (locktype & ALOCK_SMASK) <= 2);
slot_data.al_lock = locktype;
slot_data.al_stamp = time(NULL);
slot_data.al_pid = getpid();
slot_data.al_appname = ber_memcalloc (1, ALOCK_MAX_APPNAME);
if (slot_data.al_appname == NULL) {
return ALOCK_UNSTABLE;
}
strncpy (slot_data.al_appname, appname, ALOCK_MAX_APPNAME-1);
slot_data.al_appname [ALOCK_MAX_APPNAME-1] = '\0';
filename = ber_memcalloc (1, strlen (envdir) + strlen ("/alock") + 1);
if (filename == NULL ) {
ber_memfree (slot_data.al_appname);
return ALOCK_UNSTABLE;
}
ptr = lutil_strcopy(filename, envdir);
lutil_strcopy(ptr, "/alock");
#ifdef _WIN32
{ HANDLE handle = CreateFile (filename, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
info->al_fd = _open_osfhandle (handle, 0);
}
#else
info->al_fd = open (filename, O_CREAT|O_RDWR, 0666);
#endif
ber_memfree (filename);
if (info->al_fd < 0) {
ber_memfree (slot_data.al_appname);
return ALOCK_UNSTABLE;
}
info->al_slot = 0;
res = alock_grab_lock (info->al_fd, 0);
if (res == -1) {
close (info->al_fd);
ber_memfree (slot_data.al_appname);
return ALOCK_UNSTABLE;
}
res = fstat (info->al_fd, &statbuf);
if (res == -1) {
close (info->al_fd);
ber_memfree (slot_data.al_appname);
return ALOCK_UNSTABLE;
}
max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE;
dirty_count = 0;
live_count = 0;
nosave = 0;
scan_info.al_fd = info->al_fd;
for (scan_info.al_slot = 1;
scan_info.al_slot < max_slot;
++ scan_info.al_slot) {
if (scan_info.al_slot != info->al_slot) {
res = alock_query_slot (&scan_info);
if (res & ALOCK_NOSAVE) {
nosave = ALOCK_NOSAVE;
res ^= ALOCK_NOSAVE;
}
if (res == ALOCK_UNLOCKED
&& info->al_slot == 0) {
info->al_slot = scan_info.al_slot;
} else if (res == ALOCK_LOCKED) {
++live_count;
} else if (res == ALOCK_UNIQUE
&& (( locktype & ALOCK_SMASK ) == ALOCK_UNIQUE
|| nosave )) {
close (info->al_fd);
ber_memfree (slot_data.al_appname);
return ALOCK_BUSY;
} else if (res == ALOCK_DIRTY) {
++dirty_count;
} else if (res == -1) {
close (info->al_fd);
ber_memfree (slot_data.al_appname);
return ALOCK_UNSTABLE;
}
}
}
if (dirty_count && live_count) {
close (info->al_fd);
ber_memfree (slot_data.al_appname);
return ALOCK_UNSTABLE;
}
if (info->al_slot == 0) info->al_slot = max_slot + 1;
res = alock_grab_lock (info->al_fd,
info->al_slot);
if (res == -1) {
close (info->al_fd);
ber_memfree (slot_data.al_appname);
return ALOCK_UNSTABLE;
}
res = alock_write_slot (info, &slot_data);
ber_memfree (slot_data.al_appname);
if (res == -1) {
close (info->al_fd);
return ALOCK_UNSTABLE;
}
alock_share_lock (info->al_fd, info->al_slot);
res = alock_release_lock (info->al_fd, 0);
if (res == -1) {
close (info->al_fd);
return ALOCK_UNSTABLE;
}
if (dirty_count) return ALOCK_RECOVER | nosave;
return ALOCK_CLEAN | nosave;
}
int
alock_scan ( alock_info_t * info )
{
struct stat statbuf;
alock_info_t scan_info;
int res, max_slot;
int dirty_count, live_count, nosave;
assert (info != NULL);
scan_info.al_fd = info->al_fd;
res = alock_grab_lock (info->al_fd, 0);
if (res == -1) {
close (info->al_fd);
return ALOCK_UNSTABLE;
}
res = fstat (info->al_fd, &statbuf);
if (res == -1) {
close (info->al_fd);
return ALOCK_UNSTABLE;
}
max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE;
dirty_count = 0;
live_count = 0;
nosave = 0;
for (scan_info.al_slot = 1;
scan_info.al_slot < max_slot;
++ scan_info.al_slot) {
if (scan_info.al_slot != info->al_slot) {
res = alock_query_slot (&scan_info);
if (res & ALOCK_NOSAVE) {
nosave = ALOCK_NOSAVE;
res ^= ALOCK_NOSAVE;
}
if (res == ALOCK_LOCKED) {
++live_count;
} else if (res == ALOCK_DIRTY) {
++dirty_count;
} else if (res == -1) {
close (info->al_fd);
return ALOCK_UNSTABLE;
}
}
}
res = alock_release_lock (info->al_fd, 0);
if (res == -1) {
close (info->al_fd);
return ALOCK_UNSTABLE;
}
if (dirty_count) {
if (live_count) {
close (info->al_fd);
return ALOCK_UNSTABLE;
} else {
return ALOCK_RECOVER | nosave;
}
}
return ALOCK_CLEAN | nosave;
}
int
alock_close ( alock_info_t * info, int nosave )
{
alock_slot_t slot_data;
int res;
if ( !info->al_slot )
return ALOCK_CLEAN;
(void) memset ((void *) &slot_data, 0, sizeof(alock_slot_t));
res = alock_grab_lock (info->al_fd, 0);
if (res == -1) {
fail:
/* Windows doesn't clean up locks immediately when a process exits.
* Make sure we release our locks, to prevent stale locks from
* hanging around.
*/
alock_release_lock (info->al_fd, 0);
close (info->al_fd);
return ALOCK_UNSTABLE;
}
/* mark our slot as clean */
res = alock_read_slot (info, &slot_data);
if (res == -1) {
if (slot_data.al_appname != NULL)
ber_memfree (slot_data.al_appname);
goto fail;
}
slot_data.al_lock = ALOCK_UNLOCKED;
if ( nosave )
slot_data.al_lock |= ALOCK_NOSAVE;
/* since we have slot 0 locked, we don't need our slot lock */
res = alock_release_lock (info->al_fd, info->al_slot);
if (res == -1) {
goto fail;
}
res = alock_write_slot (info, &slot_data);
if (res == -1) {
if (slot_data.al_appname != NULL)
ber_memfree (slot_data.al_appname);
goto fail;
}
if (slot_data.al_appname != NULL) {
ber_memfree (slot_data.al_appname);
slot_data.al_appname = NULL;
}
res = alock_release_lock (info->al_fd, 0);
if (res == -1) {
close (info->al_fd);
return ALOCK_UNSTABLE;
}
res = close (info->al_fd);
if (res == -1) return ALOCK_UNSTABLE;
return ALOCK_CLEAN;
}
int
alock_recover ( alock_info_t * info )
{
struct stat statbuf;
alock_slot_t slot_data;
alock_info_t scan_info;
int res, max_slot;
assert (info != NULL);
scan_info.al_fd = info->al_fd;
(void) memset ((void *) &slot_data, 0, sizeof(alock_slot_t));
res = alock_grab_lock (info->al_fd, 0);
if (res == -1) {
goto fail;
}
res = fstat (info->al_fd, &statbuf);
if (res == -1) {
goto fail;
}
max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE;
for (scan_info.al_slot = 1;
scan_info.al_slot < max_slot;
++ scan_info.al_slot) {
if (scan_info.al_slot != info->al_slot) {
res = alock_query_slot (&scan_info) & ~ALOCK_NOSAVE;
if (res == ALOCK_LOCKED
|| res == ALOCK_UNIQUE) {
/* recovery attempt on an active db? */
goto fail;
} else if (res == ALOCK_DIRTY) {
/* mark it clean */
res = alock_read_slot (&scan_info, &slot_data);
if (res == -1) {
goto fail;
}
slot_data.al_lock = ALOCK_UNLOCKED;
res = alock_write_slot (&scan_info, &slot_data);
if (res == -1) {
if (slot_data.al_appname != NULL)
ber_memfree (slot_data.al_appname);
goto fail;
}
if (slot_data.al_appname != NULL) {
ber_memfree (slot_data.al_appname);
slot_data.al_appname = NULL;
}
} else if (res == -1) {
goto fail;
}
}
}
res = alock_release_lock (info->al_fd, 0);
if (res == -1) {
close (info->al_fd);
return ALOCK_UNSTABLE;
}
return ALOCK_CLEAN;
fail:
alock_release_lock (info->al_fd, 0);
close (info->al_fd);
return ALOCK_UNSTABLE;
}
#endif /* SLAPD_BDB || SLAPD_HDB */

View File

@ -1,74 +0,0 @@
/* alock.h - access lock header */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2005-2019 The OpenLDAP Foundation.
* Portions Copyright 2004-2005 Symas Corporation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* ACKNOWLEDGEMENTS:
* This work was initially developed by Emily Backes at Symas
* Corporation for inclusion in OpenLDAP Software.
*/
#ifndef _ALOCK_H_
#define _ALOCK_H_
#include "portable.h"
#include <ac/time.h>
#include <ac/unistd.h>
/* environment states (all the slots together) */
#define ALOCK_CLEAN (0)
#define ALOCK_RECOVER (1)
#define ALOCK_BUSY (2)
#define ALOCK_UNSTABLE (3)
/* lock user types and states */
#define ALOCK_UNLOCKED (0)
#define ALOCK_LOCKED (1)
#define ALOCK_UNIQUE (2)
#define ALOCK_DIRTY (3)
#define ALOCK_SMASK 3
/* lock/state where recovery is not available */
#define ALOCK_NOSAVE 4
/* constants */
#define ALOCK_SLOT_SIZE (1024)
#define ALOCK_SLOT_IATTRS (4)
#define ALOCK_MAX_APPNAME (ALOCK_SLOT_SIZE - 8 * ALOCK_SLOT_IATTRS)
#define ALOCK_MAGIC (0x12345678)
LDAP_BEGIN_DECL
typedef struct alock_info {
int al_fd;
int al_slot;
} alock_info_t;
typedef struct alock_slot {
unsigned int al_lock;
time_t al_stamp;
pid_t al_pid;
char * al_appname;
} alock_slot_t;
LDAP_SLAPD_F (int) alock_open LDAP_P(( alock_info_t * info, const char * appname,
const char * envdir, int locktype ));
LDAP_SLAPD_F (int) alock_scan LDAP_P(( alock_info_t * info ));
LDAP_SLAPD_F (int) alock_close LDAP_P(( alock_info_t * info, int nosave ));
LDAP_SLAPD_F (int) alock_recover LDAP_P(( alock_info_t * info ));
LDAP_END_DECL
#endif

View File

@ -1,53 +0,0 @@
# Makefile.in for back-bdb
# $OpenLDAP$
## This work is part of OpenLDAP Software <http://www.openldap.org/>.
##
## Copyright 1998-2019 The OpenLDAP Foundation.
## All rights reserved.
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted only as authorized by the OpenLDAP
## Public License.
##
## A copy of this license is available in the file LICENSE in the
## top-level directory of the distribution or, alternatively, at
## <http://www.OpenLDAP.org/license.html>.
SRCS = init.c tools.c config.c \
add.c bind.c compare.c delete.c modify.c modrdn.c search.c \
extended.c referral.c operational.c \
attr.c index.c key.c dbcache.c filterindex.c \
dn2entry.c dn2id.c error.c id2entry.c idl.c \
nextid.c cache.c trans.c monitor.c
OBJS = init.lo tools.lo config.lo \
add.lo bind.lo compare.lo delete.lo modify.lo modrdn.lo search.lo \
extended.lo referral.lo operational.lo \
attr.lo index.lo key.lo dbcache.lo filterindex.lo \
dn2entry.lo dn2id.lo error.lo id2entry.lo idl.lo \
nextid.lo cache.lo trans.lo monitor.lo
LDAP_INCDIR= ../../../include
LDAP_LIBDIR= ../../../libraries
BUILD_OPT = "--enable-bdb"
BUILD_MOD = @BUILD_BDB@
mod_DEFS = -DSLAPD_IMPORT
MOD_DEFS = $(@BUILD_BDB@_DEFS)
MOD_LIBS = $(BDB_LIBS)
shared_LDAP_LIBS = $(LDAP_LIBLDAP_R_LA) $(LDAP_LIBLBER_LA)
NT_LINK_LIBS = -L.. -lslapd $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
UNIX_LINK_LIBS = $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
LIBBASE = back_bdb
XINCPATH = -I.. -I$(srcdir)/..
XDEFS = $(MODULES_CPPFLAGS)
all-local-lib: ../.backend
../.backend: lib$(LIBBASE).a
@touch $@

View File

@ -1,506 +0,0 @@
/* add.c - ldap BerkeleyDB back-end add routine */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2000-2019 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include "back-bdb.h"
int
bdb_add(Operation *op, SlapReply *rs )
{
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
struct berval pdn;
Entry *p = NULL, *oe = op->ora_e;
EntryInfo *ei;
char textbuf[SLAP_TEXT_BUFLEN];
size_t textlen = sizeof textbuf;
AttributeDescription *children = slap_schema.si_ad_children;
AttributeDescription *entry = slap_schema.si_ad_entry;
DB_TXN *ltid = NULL, *lt2;
ID eid = NOID;
struct bdb_op_info opinfo = {{{ 0 }}};
int subentry;
DB_LOCK lock;
int num_retries = 0;
int success;
LDAPControl **postread_ctrl = NULL;
LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
int num_ctrls = 0;
Debug(LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(bdb_add) ": %s\n",
op->ora_e->e_name.bv_val );
#ifdef LDAP_X_TXN
if( op->o_txnSpec && txn_preop( op, rs ))
return rs->sr_err;
#endif
ctrls[num_ctrls] = 0;
/* check entry's schema */
rs->sr_err = entry_schema_check( op, op->ora_e, NULL,
get_relax(op), 1, NULL, &rs->sr_text, textbuf, textlen );
if ( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_add) ": entry failed schema check: "
"%s (%d)\n", rs->sr_text, rs->sr_err );
goto return_results;
}
/* add opattrs to shadow as well, only missing attrs will actually
* be added; helps compatibility with older OL versions */
rs->sr_err = slap_add_opattrs( op, &rs->sr_text, textbuf, textlen, 1 );
if ( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_add) ": entry failed op attrs add: "
"%s (%d)\n", rs->sr_text, rs->sr_err );
goto return_results;
}
if ( get_assert( op ) &&
( test_filter( op, op->ora_e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
{
rs->sr_err = LDAP_ASSERTION_FAILED;
goto return_results;
}
subentry = is_entry_subentry( op->ora_e );
if( 0 ) {
retry: /* transaction retry */
if( p ) {
/* free parent and reader lock */
if ( p != (Entry *)&slap_entry_root ) {
bdb_unlocked_cache_return_entry_r( bdb, p );
}
p = NULL;
}
rs->sr_err = TXN_ABORT( ltid );
ltid = NULL;
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
opinfo.boi_oe.oe_key = NULL;
op->o_do_not_cache = opinfo.boi_acl_cache;
if( rs->sr_err != 0 ) {
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
if ( op->o_abandon ) {
rs->sr_err = SLAPD_ABANDON;
goto return_results;
}
bdb_trans_backoff( ++num_retries );
}
/* begin transaction */
{
int tflags = bdb->bi_db_opflags;
if ( get_lazyCommit( op ))
tflags |= DB_TXN_NOSYNC;
rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, NULL, &ltid, tflags );
}
rs->sr_text = NULL;
if( rs->sr_err != 0 ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_add) ": txn_begin failed: %s (%d)\n",
db_strerror(rs->sr_err), rs->sr_err );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_add) ": txn1 id: %x\n",
ltid->id(ltid) );
opinfo.boi_oe.oe_key = bdb;
opinfo.boi_txn = ltid;
opinfo.boi_err = 0;
opinfo.boi_acl_cache = op->o_do_not_cache;
LDAP_SLIST_INSERT_HEAD( &op->o_extra, &opinfo.boi_oe, oe_next );
/*
* Get the parent dn and see if the corresponding entry exists.
*/
if ( be_issuffix( op->o_bd, &op->ora_e->e_nname ) ) {
pdn = slap_empty_bv;
} else {
dnParent( &op->ora_e->e_nname, &pdn );
}
/* get entry or parent */
rs->sr_err = bdb_dn2entry( op, ltid, &op->ora_e->e_nname, &ei,
1, &lock );
switch( rs->sr_err ) {
case 0:
rs->sr_err = LDAP_ALREADY_EXISTS;
goto return_results;
case DB_NOTFOUND:
break;
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
case LDAP_BUSY:
rs->sr_text = "ldap server busy";
goto return_results;
default:
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
p = ei->bei_e;
if ( !p )
p = (Entry *)&slap_entry_root;
if ( !bvmatch( &pdn, &p->e_nname ) ) {
rs->sr_matched = ber_strdup_x( p->e_name.bv_val,
op->o_tmpmemctx );
rs->sr_ref = is_entry_referral( p )
? get_entry_referrals( op, p )
: NULL;
if ( p != (Entry *)&slap_entry_root )
bdb_unlocked_cache_return_entry_r( bdb, p );
p = NULL;
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_add) ": parent "
"does not exist\n" );
rs->sr_err = LDAP_REFERRAL;
rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
goto return_results;
}
rs->sr_err = access_allowed( op, p,
children, NULL, ACL_WADD, NULL );
if ( ! rs->sr_err ) {
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
if ( p != (Entry *)&slap_entry_root )
bdb_unlocked_cache_return_entry_r( bdb, p );
p = NULL;
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_add) ": no write access to parent\n" );
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
rs->sr_text = "no write access to parent";
goto return_results;;
}
if ( p != (Entry *)&slap_entry_root ) {
if ( is_entry_subentry( p ) ) {
bdb_unlocked_cache_return_entry_r( bdb, p );
p = NULL;
/* parent is a subentry, don't allow add */
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_add) ": parent is subentry\n" );
rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION;
rs->sr_text = "parent is a subentry";
goto return_results;;
}
if ( is_entry_alias( p ) ) {
bdb_unlocked_cache_return_entry_r( bdb, p );
p = NULL;
/* parent is an alias, don't allow add */
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_add) ": parent is alias\n" );
rs->sr_err = LDAP_ALIAS_PROBLEM;
rs->sr_text = "parent is an alias";
goto return_results;;
}
if ( is_entry_referral( p ) ) {
/* parent is a referral, don't allow add */
rs->sr_matched = ber_strdup_x( p->e_name.bv_val,
op->o_tmpmemctx );
rs->sr_ref = get_entry_referrals( op, p );
bdb_unlocked_cache_return_entry_r( bdb, p );
p = NULL;
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_add) ": parent is referral\n" );
rs->sr_err = LDAP_REFERRAL;
rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
goto return_results;
}
}
if ( subentry ) {
/* FIXME: */
/* parent must be an administrative point of the required kind */
}
/* free parent and reader lock */
if ( p != (Entry *)&slap_entry_root ) {
if ( p->e_nname.bv_len ) {
struct berval ppdn;
/* ITS#5326: use parent's DN if differs from provided one */
dnParent( &op->ora_e->e_name, &ppdn );
if ( !dn_match( &p->e_name, &ppdn ) ) {
struct berval rdn;
struct berval newdn;
dnRdn( &op->ora_e->e_name, &rdn );
build_new_dn( &newdn, &p->e_name, &rdn, NULL );
if ( op->ora_e->e_name.bv_val != op->o_req_dn.bv_val )
ber_memfree( op->ora_e->e_name.bv_val );
op->ora_e->e_name = newdn;
/* FIXME: should check whether
* dnNormalize(newdn) == e->e_nname ... */
}
}
bdb_unlocked_cache_return_entry_r( bdb, p );
}
p = NULL;
rs->sr_err = access_allowed( op, op->ora_e,
entry, NULL, ACL_WADD, NULL );
if ( ! rs->sr_err ) {
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_add) ": no write access to entry\n" );
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
rs->sr_text = "no write access to entry";
goto return_results;;
}
/*
* Check ACL for attribute write access
*/
if (!acl_check_modlist(op, oe, op->ora_modlist)) {
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_add) ": no write access to attribute\n" );
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
rs->sr_text = "no write access to attribute";
goto return_results;;
}
if ( eid == NOID ) {
rs->sr_err = bdb_next_id( op->o_bd, &eid );
if( rs->sr_err != 0 ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_add) ": next_id failed (%d)\n",
rs->sr_err );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
op->ora_e->e_id = eid;
}
/* nested transaction */
rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, &lt2,
bdb->bi_db_opflags );
rs->sr_text = NULL;
if( rs->sr_err != 0 ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_add) ": txn_begin(2) failed: "
"%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_add) ": txn2 id: %x\n",
lt2->id(lt2) );
/* dn2id index */
rs->sr_err = bdb_dn2id_add( op, lt2, ei, op->ora_e );
if ( rs->sr_err != 0 ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_add) ": dn2id_add failed: %s (%d)\n",
db_strerror(rs->sr_err), rs->sr_err );
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
case DB_KEYEXIST:
rs->sr_err = LDAP_ALREADY_EXISTS;
break;
default:
rs->sr_err = LDAP_OTHER;
}
goto return_results;
}
/* attribute indexes */
rs->sr_err = bdb_index_entry_add( op, lt2, op->ora_e );
if ( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_add) ": index_entry_add failed\n" );
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
default:
rs->sr_err = LDAP_OTHER;
}
rs->sr_text = "index generation failed";
goto return_results;
}
/* id2entry index */
rs->sr_err = bdb_id2entry_add( op->o_bd, lt2, op->ora_e );
if ( rs->sr_err != 0 ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_add) ": id2entry_add failed\n" );
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
default:
rs->sr_err = LDAP_OTHER;
}
rs->sr_text = "entry store failed";
goto return_results;
}
if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
rs->sr_err = LDAP_OTHER;
rs->sr_text = "txn_commit(2) failed";
goto return_results;
}
/* post-read */
if( op->o_postread ) {
if( postread_ctrl == NULL ) {
postread_ctrl = &ctrls[num_ctrls++];
ctrls[num_ctrls] = NULL;
}
if ( slap_read_controls( op, rs, op->ora_e,
&slap_post_read_bv, postread_ctrl ) )
{
Debug( LDAP_DEBUG_TRACE,
"<=- " LDAP_XSTRING(bdb_add) ": post-read "
"failed!\n" );
if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
/* FIXME: is it correct to abort
* operation if control fails? */
goto return_results;
}
}
}
if ( op->o_noop ) {
if (( rs->sr_err=TXN_ABORT( ltid )) != 0 ) {
rs->sr_text = "txn_abort (no-op) failed";
} else {
rs->sr_err = LDAP_X_NO_OPERATION;
ltid = NULL;
goto return_results;
}
} else {
struct berval nrdn;
/* pick the RDN if not suffix; otherwise pick the entire DN */
if (pdn.bv_len) {
nrdn.bv_val = op->ora_e->e_nname.bv_val;
nrdn.bv_len = pdn.bv_val - op->ora_e->e_nname.bv_val - 1;
} else {
nrdn = op->ora_e->e_nname;
}
bdb_cache_add( bdb, ei, op->ora_e, &nrdn, ltid, &lock );
if(( rs->sr_err=TXN_COMMIT( ltid, 0 )) != 0 ) {
rs->sr_text = "txn_commit failed";
} else {
rs->sr_err = LDAP_SUCCESS;
}
}
ltid = NULL;
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
opinfo.boi_oe.oe_key = NULL;
if ( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_add) ": %s : %s (%d)\n",
rs->sr_text, db_strerror(rs->sr_err), rs->sr_err );
rs->sr_err = LDAP_OTHER;
goto return_results;
}
Debug(LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_add) ": added%s id=%08lx dn=\"%s\"\n",
op->o_noop ? " (no-op)" : "",
op->ora_e->e_id, op->ora_e->e_dn );
rs->sr_text = NULL;
if( num_ctrls ) rs->sr_ctrls = ctrls;
return_results:
success = rs->sr_err;
send_ldap_result( op, rs );
if( ltid != NULL ) {
TXN_ABORT( ltid );
}
if ( opinfo.boi_oe.oe_key ) {
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
}
if( success == LDAP_SUCCESS ) {
/* We own the entry now, and it can be purged at will
* Check to make sure it's the same entry we entered with.
* Possibly a callback may have mucked with it, although
* in general callbacks should treat the entry as read-only.
*/
bdb_cache_deref( oe->e_private );
if ( op->ora_e == oe )
op->ora_e = NULL;
if ( bdb->bi_txn_cp_kbyte ) {
TXN_CHECKPOINT( bdb->bi_dbenv,
bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
}
}
slap_graduate_commit_csn( op );
if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) {
slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
}
return rs->sr_err;
}

View File

@ -1,447 +0,0 @@
/* attr.c - backend routines for dealing with attributes */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2000-2019 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/socket.h>
#include <ac/string.h>
#include "slap.h"
#include "back-bdb.h"
#include "config.h"
#include "lutil.h"
/* Find the ad, return -1 if not found,
* set point for insertion if ins is non-NULL
*/
int
bdb_attr_slot( struct bdb_info *bdb, AttributeDescription *ad, int *ins )
{
unsigned base = 0, cursor = 0;
unsigned n = bdb->bi_nattrs;
int val = 0;
while ( 0 < n ) {
unsigned pivot = n >> 1;
cursor = base + pivot;
val = SLAP_PTRCMP( ad, bdb->bi_attrs[cursor]->ai_desc );
if ( val < 0 ) {
n = pivot;
} else if ( val > 0 ) {
base = cursor + 1;
n -= pivot + 1;
} else {
return cursor;
}
}
if ( ins ) {
if ( val > 0 )
++cursor;
*ins = cursor;
}
return -1;
}
static int
ainfo_insert( struct bdb_info *bdb, AttrInfo *a )
{
int x;
int i = bdb_attr_slot( bdb, a->ai_desc, &x );
/* Is it a dup? */
if ( i >= 0 )
return -1;
bdb->bi_attrs = ch_realloc( bdb->bi_attrs, ( bdb->bi_nattrs+1 ) *
sizeof( AttrInfo * ));
if ( x < bdb->bi_nattrs )
AC_MEMCPY( &bdb->bi_attrs[x+1], &bdb->bi_attrs[x],
( bdb->bi_nattrs - x ) * sizeof( AttrInfo *));
bdb->bi_attrs[x] = a;
bdb->bi_nattrs++;
return 0;
}
AttrInfo *
bdb_attr_mask(
struct bdb_info *bdb,
AttributeDescription *desc )
{
int i = bdb_attr_slot( bdb, desc, NULL );
return i < 0 ? NULL : bdb->bi_attrs[i];
}
int
bdb_attr_index_config(
struct bdb_info *bdb,
const char *fname,
int lineno,
int argc,
char **argv,
struct config_reply_s *c_reply)
{
int rc = 0;
int i;
slap_mask_t mask;
char **attrs;
char **indexes = NULL;
attrs = ldap_str2charray( argv[0], "," );
if( attrs == NULL ) {
fprintf( stderr, "%s: line %d: "
"no attributes specified: %s\n",
fname, lineno, argv[0] );
return LDAP_PARAM_ERROR;
}
if ( argc > 1 ) {
indexes = ldap_str2charray( argv[1], "," );
if( indexes == NULL ) {
fprintf( stderr, "%s: line %d: "
"no indexes specified: %s\n",
fname, lineno, argv[1] );
rc = LDAP_PARAM_ERROR;
goto done;
}
}
if( indexes == NULL ) {
mask = bdb->bi_defaultmask;
} else {
mask = 0;
for ( i = 0; indexes[i] != NULL; i++ ) {
slap_mask_t index;
rc = slap_str2index( indexes[i], &index );
if( rc != LDAP_SUCCESS ) {
if ( c_reply )
{
snprintf(c_reply->msg, sizeof(c_reply->msg),
"index type \"%s\" undefined", indexes[i] );
fprintf( stderr, "%s: line %d: %s\n",
fname, lineno, c_reply->msg );
}
rc = LDAP_PARAM_ERROR;
goto done;
}
mask |= index;
}
}
if( !mask ) {
if ( c_reply )
{
snprintf(c_reply->msg, sizeof(c_reply->msg),
"no indexes selected" );
fprintf( stderr, "%s: line %d: %s\n",
fname, lineno, c_reply->msg );
}
rc = LDAP_PARAM_ERROR;
goto done;
}
for ( i = 0; attrs[i] != NULL; i++ ) {
AttrInfo *a;
AttributeDescription *ad;
const char *text;
#ifdef LDAP_COMP_MATCH
ComponentReference* cr = NULL;
AttrInfo *a_cr = NULL;
#endif
if( strcasecmp( attrs[i], "default" ) == 0 ) {
bdb->bi_defaultmask |= mask;
continue;
}
#ifdef LDAP_COMP_MATCH
if ( is_component_reference( attrs[i] ) ) {
rc = extract_component_reference( attrs[i], &cr );
if ( rc != LDAP_SUCCESS ) {
if ( c_reply )
{
snprintf(c_reply->msg, sizeof(c_reply->msg),
"index component reference\"%s\" undefined",
attrs[i] );
fprintf( stderr, "%s: line %d: %s\n",
fname, lineno, c_reply->msg );
}
goto done;
}
cr->cr_indexmask = mask;
/*
* After extracting a component reference
* only the name of a attribute will be remaining
*/
} else {
cr = NULL;
}
#endif
ad = NULL;
rc = slap_str2ad( attrs[i], &ad, &text );
if( rc != LDAP_SUCCESS ) {
if ( c_reply )
{
snprintf(c_reply->msg, sizeof(c_reply->msg),
"index attribute \"%s\" undefined",
attrs[i] );
fprintf( stderr, "%s: line %d: %s\n",
fname, lineno, c_reply->msg );
}
fail:
#ifdef LDAP_COMP_MATCH
ch_free( cr );
#endif
goto done;
}
if( ad == slap_schema.si_ad_entryDN || slap_ad_is_binary( ad ) ) {
if (c_reply) {
snprintf(c_reply->msg, sizeof(c_reply->msg),
"index of attribute \"%s\" disallowed", attrs[i] );
fprintf( stderr, "%s: line %d: %s\n",
fname, lineno, c_reply->msg );
}
rc = LDAP_UNWILLING_TO_PERFORM;
goto fail;
}
if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) && !(
ad->ad_type->sat_approx
&& ad->ad_type->sat_approx->smr_indexer
&& ad->ad_type->sat_approx->smr_filter ) )
{
if (c_reply) {
snprintf(c_reply->msg, sizeof(c_reply->msg),
"approx index of attribute \"%s\" disallowed", attrs[i] );
fprintf( stderr, "%s: line %d: %s\n",
fname, lineno, c_reply->msg );
}
rc = LDAP_INAPPROPRIATE_MATCHING;
goto fail;
}
if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) && !(
ad->ad_type->sat_equality
&& ad->ad_type->sat_equality->smr_indexer
&& ad->ad_type->sat_equality->smr_filter ) )
{
if (c_reply) {
snprintf(c_reply->msg, sizeof(c_reply->msg),
"equality index of attribute \"%s\" disallowed", attrs[i] );
fprintf( stderr, "%s: line %d: %s\n",
fname, lineno, c_reply->msg );
}
rc = LDAP_INAPPROPRIATE_MATCHING;
goto fail;
}
if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) && !(
ad->ad_type->sat_substr
&& ad->ad_type->sat_substr->smr_indexer
&& ad->ad_type->sat_substr->smr_filter ) )
{
if (c_reply) {
snprintf(c_reply->msg, sizeof(c_reply->msg),
"substr index of attribute \"%s\" disallowed", attrs[i] );
fprintf( stderr, "%s: line %d: %s\n",
fname, lineno, c_reply->msg );
}
rc = LDAP_INAPPROPRIATE_MATCHING;
goto fail;
}
Debug( LDAP_DEBUG_CONFIG, "index %s 0x%04lx\n",
ad->ad_cname.bv_val, mask );
a = (AttrInfo *) ch_malloc( sizeof(AttrInfo) );
#ifdef LDAP_COMP_MATCH
a->ai_cr = NULL;
#endif
a->ai_desc = ad;
if ( bdb->bi_flags & BDB_IS_OPEN ) {
a->ai_indexmask = 0;
a->ai_newmask = mask;
} else {
a->ai_indexmask = mask;
a->ai_newmask = 0;
}
#ifdef LDAP_COMP_MATCH
if ( cr ) {
a_cr = bdb_attr_mask( bdb, ad );
if ( a_cr ) {
/*
* AttrInfo is already in AVL
* just add the extracted component reference
* in the AttrInfo
*/
ch_free( a );
rc = insert_component_reference( cr, &a_cr->ai_cr );
if ( rc != LDAP_SUCCESS) {
fprintf( stderr, " error during inserting component reference in %s ", attrs[i]);
rc = LDAP_PARAM_ERROR;
goto fail;
}
continue;
} else {
rc = insert_component_reference( cr, &a->ai_cr );
if ( rc != LDAP_SUCCESS) {
fprintf( stderr, " error during inserting component reference in %s ", attrs[i]);
rc = LDAP_PARAM_ERROR;
ch_free( a );
goto fail;
}
}
}
#endif
rc = ainfo_insert( bdb, a );
if( rc ) {
if ( bdb->bi_flags & BDB_IS_OPEN ) {
AttrInfo *b = bdb_attr_mask( bdb, ad );
/* If there is already an index defined for this attribute
* it must be replaced. Otherwise we end up with multiple
* olcIndex values for the same attribute */
if ( b->ai_indexmask & BDB_INDEX_DELETING ) {
/* If we were editing this attr, reset it */
b->ai_indexmask &= ~BDB_INDEX_DELETING;
/* If this is leftover from a previous add, commit it */
if ( b->ai_newmask )
b->ai_indexmask = b->ai_newmask;
b->ai_newmask = a->ai_newmask;
ch_free( a );
rc = 0;
continue;
}
}
if (c_reply) {
snprintf(c_reply->msg, sizeof(c_reply->msg),
"duplicate index definition for attr \"%s\"",
attrs[i] );
fprintf( stderr, "%s: line %d: %s\n",
fname, lineno, c_reply->msg );
}
rc = LDAP_PARAM_ERROR;
goto done;
}
}
done:
ldap_charray_free( attrs );
if ( indexes != NULL ) ldap_charray_free( indexes );
return rc;
}
static int
bdb_attr_index_unparser( void *v1, void *v2 )
{
AttrInfo *ai = v1;
BerVarray *bva = v2;
struct berval bv;
char *ptr;
slap_index2bvlen( ai->ai_indexmask, &bv );
if ( bv.bv_len ) {
bv.bv_len += ai->ai_desc->ad_cname.bv_len + 1;
ptr = ch_malloc( bv.bv_len+1 );
bv.bv_val = lutil_strcopy( ptr, ai->ai_desc->ad_cname.bv_val );
*bv.bv_val++ = ' ';
slap_index2bv( ai->ai_indexmask, &bv );
bv.bv_val = ptr;
ber_bvarray_add( bva, &bv );
}
return 0;
}
static AttributeDescription addef = { NULL, NULL, BER_BVC("default") };
static AttrInfo aidef = { &addef };
void
bdb_attr_index_unparse( struct bdb_info *bdb, BerVarray *bva )
{
int i;
if ( bdb->bi_defaultmask ) {
aidef.ai_indexmask = bdb->bi_defaultmask;
bdb_attr_index_unparser( &aidef, bva );
}
for ( i=0; i<bdb->bi_nattrs; i++ )
bdb_attr_index_unparser( bdb->bi_attrs[i], bva );
}
void
bdb_attr_info_free( AttrInfo *ai )
{
#ifdef LDAP_COMP_MATCH
free( ai->ai_cr );
#endif
free( ai );
}
void
bdb_attr_index_destroy( struct bdb_info *bdb )
{
int i;
for ( i=0; i<bdb->bi_nattrs; i++ )
bdb_attr_info_free( bdb->bi_attrs[i] );
free( bdb->bi_attrs );
}
void bdb_attr_index_free( struct bdb_info *bdb, AttributeDescription *ad )
{
int i;
i = bdb_attr_slot( bdb, ad, NULL );
if ( i >= 0 ) {
bdb_attr_info_free( bdb->bi_attrs[i] );
bdb->bi_nattrs--;
for (; i<bdb->bi_nattrs; i++)
bdb->bi_attrs[i] = bdb->bi_attrs[i+1];
}
}
void bdb_attr_flush( struct bdb_info *bdb )
{
int i;
for ( i=0; i<bdb->bi_nattrs; i++ ) {
if ( bdb->bi_attrs[i]->ai_indexmask & BDB_INDEX_DELETING ) {
int j;
bdb_attr_info_free( bdb->bi_attrs[i] );
bdb->bi_nattrs--;
for (j=i; j<bdb->bi_nattrs; j++)
bdb->bi_attrs[j] = bdb->bi_attrs[j+1];
i--;
}
}
}

View File

@ -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-2019 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
#ifndef _BACK_BDB_H_
#define _BACK_BDB_H_
#include <portable.h>
#include "slap.h"
#include <db.h>
#include "alock.h"
LDAP_BEGIN_DECL
#define DB_VERSION_FULL ((DB_VERSION_MAJOR << 24) | (DB_VERSION_MINOR << 16) | DB_VERSION_PATCH)
#define DN_BASE_PREFIX SLAP_INDEX_EQUALITY_PREFIX
#define DN_ONE_PREFIX '%'
#define DN_SUBTREE_PREFIX '@'
#define DBTzero(t) (memset((t), 0, sizeof(DBT)))
#define DBT2bv(t,bv) ((bv)->bv_val = (t)->data, \
(bv)->bv_len = (t)->size)
#define bv2DBT(bv,t) ((t)->data = (bv)->bv_val, \
(t)->size = (bv)->bv_len )
#define BDB_TXN_RETRIES 16
#define BDB_MAX_ADD_LOOP 30
#define BDB_SUFFIX ".bdb"
#define BDB_ID2ENTRY 0
#define BDB_DN2ID 1
#define BDB_NDB 2
/* The bdb on-disk entry format is pretty space-inefficient. Average
* sized user entries are 3-4K each. You need at least two entries to
* fit into a single database page, more is better. 64K is BDB's
* upper bound. Smaller pages are better for concurrency.
*/
#ifndef BDB_ID2ENTRY_PAGESIZE
#define BDB_ID2ENTRY_PAGESIZE 16384
#endif
#define DEFAULT_CACHE_SIZE 1000
/* The default search IDL stack cache depth */
#define DEFAULT_SEARCH_STACK_DEPTH 16
/* The minimum we can function with */
#define MINIMUM_SEARCH_STACK_DEPTH 8
typedef struct bdb_idl_cache_entry_s {
struct berval kstr;
ID *idl;
DB *db;
int idl_flags;
struct bdb_idl_cache_entry_s* idl_lru_prev;
struct bdb_idl_cache_entry_s* idl_lru_next;
} bdb_idl_cache_entry_t;
/* BDB backend specific entry info */
typedef struct bdb_entry_info {
struct bdb_entry_info *bei_parent;
ID bei_id;
/* we use the bei_id as a lockobj, but we need to make the size != 4
* to avoid conflicting with BDB's internal locks. So add a byte here
* that is always zero.
*/
short bei_lockpad;
short bei_state;
#define CACHE_ENTRY_DELETED 1
#define CACHE_ENTRY_NO_KIDS 2
#define CACHE_ENTRY_NOT_LINKED 4
#define CACHE_ENTRY_NO_GRANDKIDS 8
#define CACHE_ENTRY_LOADING 0x10
#define CACHE_ENTRY_WALKING 0x20
#define CACHE_ENTRY_ONELEVEL 0x40
#define CACHE_ENTRY_REFERENCED 0x80
#define CACHE_ENTRY_NOT_CACHED 0x100
int bei_finders;
/*
* remaining fields require backend cache lock to access
*/
struct berval bei_nrdn;
#ifdef BDB_HIER
struct berval bei_rdn;
int bei_modrdns; /* track renames */
int bei_ckids; /* number of kids cached */
int bei_dkids; /* number of kids on-disk, plus 1 */
#endif
Entry *bei_e;
Avlnode *bei_kids;
#ifdef SLAP_ZONE_ALLOC
struct bdb_info *bei_bdb;
int bei_zseq;
#endif
ldap_pvt_thread_mutex_t bei_kids_mutex;
struct bdb_entry_info *bei_lrunext; /* for cache lru list */
struct bdb_entry_info *bei_lruprev;
} EntryInfo;
#undef BEI
#define BEI(e) ((EntryInfo *) ((e)->e_private))
/* for the in-core cache of entries */
typedef struct bdb_cache {
EntryInfo *c_eifree; /* free list */
Avlnode *c_idtree;
EntryInfo *c_lruhead; /* lru - add accessed entries here */
EntryInfo *c_lrutail; /* lru - rem lru entries from here */
EntryInfo c_dntree;
ID c_maxsize;
ID c_cursize;
ID c_minfree;
ID c_eimax;
ID c_eiused; /* EntryInfo's in use */
ID c_leaves; /* EntryInfo leaf nodes */
int c_purging;
DB_TXN *c_txn; /* used by lru cleaner */
ldap_pvt_thread_rdwr_t c_rwlock;
ldap_pvt_thread_mutex_t c_lru_mutex;
ldap_pvt_thread_mutex_t c_count_mutex;
ldap_pvt_thread_mutex_t c_eifree_mutex;
#ifdef SLAP_ZONE_ALLOC
void *c_zctx;
#endif
} Cache;
#define CACHE_READ_LOCK 0
#define CACHE_WRITE_LOCK 1
#define BDB_INDICES 128
struct bdb_db_info {
struct berval bdi_name;
DB *bdi_db;
};
struct bdb_db_pgsize {
struct bdb_db_pgsize *bdp_next;
struct berval bdp_name;
int bdp_size;
};
#ifdef LDAP_DEVEL
#define BDB_MONITOR_IDX
#endif
typedef struct bdb_monitor_t {
void *bdm_cb;
struct berval bdm_ndn;
} bdb_monitor_t;
/* From ldap_rq.h */
struct re_s;
struct bdb_info {
DB_ENV *bi_dbenv;
/* DB_ENV parameters */
/* The DB_ENV can be tuned via DB_CONFIG */
char *bi_dbenv_home;
u_int32_t bi_dbenv_xflags; /* extra flags */
int bi_dbenv_mode;
int bi_ndatabases;
int bi_db_opflags; /* db-specific flags */
struct bdb_db_info **bi_databases;
ldap_pvt_thread_mutex_t bi_database_mutex;
struct bdb_db_pgsize *bi_pagesizes;
slap_mask_t bi_defaultmask;
Cache bi_cache;
struct bdb_attrinfo **bi_attrs;
int bi_nattrs;
void *bi_search_stack;
int bi_search_stack_depth;
int bi_linear_index;
int bi_txn_cp;
u_int32_t bi_txn_cp_min;
u_int32_t bi_txn_cp_kbyte;
struct re_s *bi_txn_cp_task;
struct re_s *bi_index_task;
u_int32_t bi_lock_detect;
long bi_shm_key;
ID bi_lastid;
ldap_pvt_thread_mutex_t bi_lastid_mutex;
ID bi_idl_cache_max_size;
ID bi_idl_cache_size;
Avlnode *bi_idl_tree;
bdb_idl_cache_entry_t *bi_idl_lru_head;
bdb_idl_cache_entry_t *bi_idl_lru_tail;
ldap_pvt_thread_rdwr_t bi_idl_tree_rwlock;
ldap_pvt_thread_mutex_t bi_idl_tree_lrulock;
alock_info_t bi_alock_info;
char *bi_db_config_path;
BerVarray bi_db_config;
char *bi_db_crypt_file;
struct berval bi_db_crypt_key;
bdb_monitor_t bi_monitor;
#ifdef BDB_MONITOR_IDX
ldap_pvt_thread_mutex_t bi_idx_mutex;
Avlnode *bi_idx;
#endif /* BDB_MONITOR_IDX */
int bi_flags;
#define BDB_IS_OPEN 0x01
#define BDB_HAS_CONFIG 0x02
#define BDB_UPD_CONFIG 0x04
#define BDB_DEL_INDEX 0x08
#define BDB_RE_OPEN 0x10
#define BDB_CHKSUM 0x20
#ifdef BDB_HIER
int bi_modrdns; /* number of modrdns completed */
ldap_pvt_thread_mutex_t bi_modrdns_mutex;
#endif
};
#define bi_id2entry bi_databases[BDB_ID2ENTRY]
#define bi_dn2id bi_databases[BDB_DN2ID]
struct bdb_lock_info {
struct bdb_lock_info *bli_next;
DB_LOCK bli_lock;
ID bli_id;
int bli_flag;
};
#define BLI_DONTFREE 1
struct bdb_op_info {
OpExtra boi_oe;
DB_TXN* boi_txn;
struct bdb_lock_info *boi_locks; /* used when no txn */
u_int32_t boi_err;
char boi_acl_cache;
char boi_flag;
};
#define BOI_DONTFREE 1
#define DB_OPEN(db, file, name, type, flags, mode) \
((db)->open)(db, file, name, type, flags, mode)
#if DB_VERSION_MAJOR < 4
#define LOCK_DETECT(env,f,t,a) lock_detect(env, f, t, a)
#define LOCK_GET(env,i,f,o,m,l) lock_get(env, i, f, o, m, l)
#define LOCK_PUT(env,l) lock_put(env, l)
#define TXN_CHECKPOINT(env,k,m,f) txn_checkpoint(env, k, m, f)
#define TXN_BEGIN(env,p,t,f) txn_begin((env), p, t, f)
#define TXN_PREPARE(txn,gid) txn_prepare((txn), (gid))
#define TXN_COMMIT(txn,f) txn_commit((txn), (f))
#define TXN_ABORT(txn) txn_abort((txn))
#define TXN_ID(txn) txn_id(txn)
#define XLOCK_ID(env, locker) lock_id(env, locker)
#define XLOCK_ID_FREE(env, locker) lock_id_free(env, locker)
#else
#define LOCK_DETECT(env,f,t,a) (env)->lock_detect(env, f, t, a)
#define LOCK_GET(env,i,f,o,m,l) (env)->lock_get(env, i, f, o, m, l)
#define LOCK_PUT(env,l) (env)->lock_put(env, l)
#define TXN_CHECKPOINT(env,k,m,f) (env)->txn_checkpoint(env, k, m, f)
#define TXN_BEGIN(env,p,t,f) (env)->txn_begin((env), p, t, f)
#define TXN_PREPARE(txn,g) (txn)->prepare((txn), (g))
#define TXN_COMMIT(txn,f) (txn)->commit((txn), (f))
#define TXN_ABORT(txn) (txn)->abort((txn))
#define TXN_ID(txn) (txn)->id(txn)
#define XLOCK_ID(env, locker) (env)->lock_id(env, locker)
#define XLOCK_ID_FREE(env, locker) (env)->lock_id_free(env, locker)
/* BDB 4.1.17 adds txn arg to db->open */
#if DB_VERSION_FULL >= 0x04010011
#undef DB_OPEN
#define DB_OPEN(db, file, name, type, flags, mode) \
((db)->open)(db, NULL, file, name, type, flags, mode)
#endif
/* #undef BDB_LOG_DEBUG */
#ifdef BDB_LOG_DEBUG
/* env->log_printf appeared in 4.4 */
#if DB_VERSION_FULL >= 0x04040000
#define BDB_LOG_PRINTF(env,txn,fmt,...) (env)->log_printf((env),(txn),(fmt),__VA_ARGS__)
#else
extern int __db_logmsg(const DB_ENV *env, DB_TXN *txn, const char *op, u_int32_t flags,
const char *fmt,...);
#define BDB_LOG_PRINTF(env,txn,fmt,...) __db_logmsg((env),(txn),"DIAGNOSTIC",0,(fmt),__VA_ARGS__)
#endif
/* !BDB_LOG_DEBUG */
#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
(defined(__GNUC__) && __GNUC__ >= 3 && !defined(__STRICT_ANSI__))
#define BDB_LOG_PRINTF(a,b,c,...)
#else
#define BDB_LOG_PRINTF (void) /* will evaluate and discard the arguments */
#endif /* BDB_LOG_DEBUG */
#endif
#ifndef DB_BUFFER_SMALL
#define DB_BUFFER_SMALL ENOMEM
#endif
#define BDB_CSN_COMMIT 0
#define BDB_CSN_ABORT 1
#define BDB_CSN_RETRY 2
/* Copy an ID "src" to pointer "dst" in big-endian byte order */
#define BDB_ID2DISK( src, dst ) \
do { int i0; ID tmp; unsigned char *_p; \
tmp = (src); _p = (unsigned char *)(dst); \
for ( i0=sizeof(ID)-1; i0>=0; i0-- ) { \
_p[i0] = tmp & 0xff; tmp >>= 8; \
} \
} while(0)
/* Copy a pointer "src" to a pointer "dst" from big-endian to native order */
#define BDB_DISK2ID( src, dst ) \
do { unsigned i0; ID tmp = 0; unsigned char *_p; \
_p = (unsigned char *)(src); \
for ( i0=0; i0<sizeof(ID); i0++ ) { \
tmp <<= 8; tmp |= *_p++; \
} *(dst) = tmp; \
} while (0)
LDAP_END_DECL
/* for the cache of attribute information (which are indexed, etc.) */
typedef struct bdb_attrinfo {
AttributeDescription *ai_desc; /* attribute description cn;lang-en */
slap_mask_t ai_indexmask; /* how the attr is indexed */
slap_mask_t ai_newmask; /* new settings to replace old mask */
#ifdef LDAP_COMP_MATCH
ComponentReference* ai_cr; /*component indexing*/
#endif
} AttrInfo;
/* These flags must not clash with SLAP_INDEX flags or ops in slap.h! */
#define BDB_INDEX_DELETING 0x8000U /* index is being modified */
#define BDB_INDEX_UPDATE_OP 0x03 /* performing an index update */
/* For slapindex to record which attrs in an entry belong to which
* index database
*/
typedef struct AttrList {
struct AttrList *next;
Attribute *attr;
} AttrList;
typedef struct IndexRec {
AttrInfo *ai;
AttrList *attrs;
} IndexRec;
#include "proto-bdb.h"
#endif /* _BACK_BDB_H_ */

View File

@ -1,164 +0,0 @@
/* bind.c - bdb backend bind routine */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2000-2019 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include <ac/unistd.h>
#include "back-bdb.h"
int
bdb_bind( Operation *op, SlapReply *rs )
{
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
Entry *e;
Attribute *a;
EntryInfo *ei;
AttributeDescription *password = slap_schema.si_ad_userPassword;
DB_TXN *rtxn;
DB_LOCK lock;
Debug( LDAP_DEBUG_ARGS,
"==> " LDAP_XSTRING(bdb_bind) ": dn: %s\n",
op->o_req_dn.bv_val );
/* allow noauth binds */
switch ( be_rootdn_bind( op, NULL ) ) {
case LDAP_SUCCESS:
/* frontend will send result */
return rs->sr_err = LDAP_SUCCESS;
default:
/* give the database a chance */
/* NOTE: this behavior departs from that of other backends,
* since the others, in case of password checking failure
* do not give the database a chance. If an entry with
* rootdn's name does not exist in the database the result
* will be the same. See ITS#4962 for discussion. */
break;
}
rs->sr_err = bdb_reader_get(op, bdb->bi_dbenv, &rtxn);
switch(rs->sr_err) {
case 0:
break;
default:
rs->sr_text = "internal error";
send_ldap_result( op, rs );
return rs->sr_err;
}
dn2entry_retry:
/* get entry with reader lock */
rs->sr_err = bdb_dn2entry( op, rtxn, &op->o_req_ndn, &ei, 1,
&lock );
switch(rs->sr_err) {
case DB_NOTFOUND:
case 0:
break;
case LDAP_BUSY:
send_ldap_error( op, rs, LDAP_BUSY, "ldap_server_busy" );
return LDAP_BUSY;
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto dn2entry_retry;
default:
send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
return rs->sr_err;
}
e = ei->bei_e;
if ( rs->sr_err == DB_NOTFOUND ) {
if( e != NULL ) {
bdb_cache_return_entry_r( bdb, e, &lock );
e = NULL;
}
rs->sr_err = LDAP_INVALID_CREDENTIALS;
send_ldap_result( op, rs );
return rs->sr_err;
}
ber_dupbv( &op->oq_bind.rb_edn, &e->e_name );
/* check for deleted */
if ( is_entry_subentry( e ) ) {
/* entry is an subentry, don't allow bind */
Debug( LDAP_DEBUG_TRACE, "entry is subentry\n" );
rs->sr_err = LDAP_INVALID_CREDENTIALS;
goto done;
}
if ( is_entry_alias( e ) ) {
/* entry is an alias, don't allow bind */
Debug( LDAP_DEBUG_TRACE, "entry is alias\n" );
rs->sr_err = LDAP_INVALID_CREDENTIALS;
goto done;
}
if ( is_entry_referral( e ) ) {
Debug( LDAP_DEBUG_TRACE, "entry is referral\n" );
rs->sr_err = LDAP_INVALID_CREDENTIALS;
goto done;
}
switch ( op->oq_bind.rb_method ) {
case LDAP_AUTH_SIMPLE:
a = attr_find( e->e_attrs, password );
if ( a == NULL ) {
rs->sr_err = LDAP_INVALID_CREDENTIALS;
goto done;
}
if ( slap_passwd_check( op, e, a, &op->oq_bind.rb_cred,
&rs->sr_text ) != 0 )
{
/* failure; stop front end from sending result */
rs->sr_err = LDAP_INVALID_CREDENTIALS;
goto done;
}
rs->sr_err = 0;
break;
default:
assert( 0 ); /* should not be reachable */
rs->sr_err = LDAP_STRONG_AUTH_NOT_SUPPORTED;
rs->sr_text = "authentication method not supported";
}
done:
/* free entry and reader lock */
if( e != NULL ) {
bdb_cache_return_entry_r( bdb, e, &lock );
}
if ( rs->sr_err ) {
send_ldap_result( op, rs );
if ( rs->sr_ref ) {
ber_bvarray_free( rs->sr_ref );
rs->sr_ref = NULL;
}
}
/* front end will send result on success (rs->sr_err==0) */
return rs->sr_err;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,143 +0,0 @@
/* compare.c - bdb backend compare routine */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2000-2019 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include "back-bdb.h"
int
bdb_compare( Operation *op, SlapReply *rs )
{
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
Entry *e = NULL;
EntryInfo *ei;
int manageDSAit = get_manageDSAit( op );
DB_TXN *rtxn;
DB_LOCK lock;
rs->sr_err = bdb_reader_get(op, bdb->bi_dbenv, &rtxn);
switch(rs->sr_err) {
case 0:
break;
default:
send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
return rs->sr_err;
}
dn2entry_retry:
/* get entry */
rs->sr_err = bdb_dn2entry( op, rtxn, &op->o_req_ndn, &ei, 1,
&lock );
switch( rs->sr_err ) {
case DB_NOTFOUND:
case 0:
break;
case LDAP_BUSY:
rs->sr_text = "ldap server busy";
goto return_results;
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto dn2entry_retry;
default:
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
e = ei->bei_e;
if ( rs->sr_err == DB_NOTFOUND ) {
if ( e != NULL ) {
/* return referral only if "disclose" is granted on the object */
if ( ! access_allowed( op, e, slap_schema.si_ad_entry,
NULL, ACL_DISCLOSE, NULL ) )
{
rs->sr_err = LDAP_NO_SUCH_OBJECT;
} else {
rs->sr_matched = ch_strdup( e->e_dn );
rs->sr_ref = is_entry_referral( e )
? get_entry_referrals( op, e )
: NULL;
rs->sr_err = LDAP_REFERRAL;
}
bdb_cache_return_entry_r( bdb, e, &lock );
e = NULL;
} else {
rs->sr_ref = referral_rewrite( default_referral,
NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
rs->sr_err = rs->sr_ref ? LDAP_REFERRAL : LDAP_NO_SUCH_OBJECT;
}
send_ldap_result( op, rs );
ber_bvarray_free( rs->sr_ref );
free( (char *)rs->sr_matched );
rs->sr_ref = NULL;
rs->sr_matched = NULL;
goto done;
}
if (!manageDSAit && is_entry_referral( e ) ) {
/* return referral only if "disclose" is granted on the object */
if ( !access_allowed( op, e, slap_schema.si_ad_entry,
NULL, ACL_DISCLOSE, NULL ) )
{
rs->sr_err = LDAP_NO_SUCH_OBJECT;
} else {
/* entry is a referral, don't allow compare */
rs->sr_ref = get_entry_referrals( op, e );
rs->sr_err = LDAP_REFERRAL;
rs->sr_matched = e->e_name.bv_val;
}
Debug( LDAP_DEBUG_TRACE, "entry is referral\n" );
send_ldap_result( op, rs );
ber_bvarray_free( rs->sr_ref );
rs->sr_ref = NULL;
rs->sr_matched = NULL;
goto done;
}
rs->sr_err = slap_compare_entry( op, e, op->orc_ava );
return_results:
send_ldap_result( op, rs );
switch ( rs->sr_err ) {
case LDAP_COMPARE_FALSE:
case LDAP_COMPARE_TRUE:
rs->sr_err = LDAP_SUCCESS;
break;
}
done:
/* free entry */
if ( e != NULL ) {
bdb_cache_return_entry_r( bdb, e, &lock );
}
return rs->sr_err;
}

View File

@ -1,967 +0,0 @@
/* config.c - bdb backend configuration file routine */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2000-2019 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/ctype.h>
#include <ac/string.h>
#include <ac/errno.h>
#include "back-bdb.h"
#include "config.h"
#include "lutil.h"
#include "ldap_rq.h"
#ifdef DB_DIRTY_READ
# define SLAP_BDB_ALLOW_DIRTY_READ
#endif
#define bdb_cf_gen BDB_SYMBOL(cf_gen)
#define bdb_cf_cleanup BDB_SYMBOL(cf_cleanup)
#define bdb_checkpoint BDB_SYMBOL(checkpoint)
#define bdb_online_index BDB_SYMBOL(online_index)
static ConfigDriver bdb_cf_gen;
enum {
BDB_CHKPT = 1,
BDB_CONFIG,
BDB_CRYPTFILE,
BDB_CRYPTKEY,
BDB_DIRECTORY,
BDB_NOSYNC,
BDB_DIRTYR,
BDB_INDEX,
BDB_LOCKD,
BDB_SSTACK,
BDB_MODE,
BDB_PGSIZE,
BDB_CHECKSUM
};
static ConfigTable bdbcfg[] = {
{ "directory", "dir", 2, 2, 0, ARG_STRING|ARG_MAGIC|BDB_DIRECTORY,
bdb_cf_gen, "( OLcfgDbAt:0.1 NAME 'olcDbDirectory' "
"DESC 'Directory for database content' "
"EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "cachefree", "size", 2, 2, 0, ARG_ULONG|ARG_OFFSET,
(void *)offsetof(struct bdb_info, bi_cache.c_minfree),
"( OLcfgDbAt:1.11 NAME 'olcDbCacheFree' "
"DESC 'Number of extra entries to free when max is reached' "
"EQUALITY integerMatch "
"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
{ "cachesize", "size", 2, 2, 0, ARG_ULONG|ARG_OFFSET,
(void *)offsetof(struct bdb_info, bi_cache.c_maxsize),
"( OLcfgDbAt:1.1 NAME 'olcDbCacheSize' "
"DESC 'Entry cache size in entries' "
"EQUALITY integerMatch "
"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
{ "checkpoint", "kbyte> <min", 3, 3, 0, ARG_MAGIC|BDB_CHKPT,
bdb_cf_gen, "( OLcfgDbAt:1.2 NAME 'olcDbCheckpoint' "
"DESC 'Database checkpoint interval in kbytes and minutes' "
"EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )",NULL, NULL },
{ "checksum", NULL, 1, 2, 0, ARG_ON_OFF|ARG_MAGIC|BDB_CHECKSUM,
bdb_cf_gen, "( OLcfgDbAt:1.16 NAME 'olcDbChecksum' "
"DESC 'Enable database checksum validation' "
"EQUALITY booleanMatch "
"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
{ "cryptfile", "file", 2, 2, 0, ARG_STRING|ARG_MAGIC|BDB_CRYPTFILE,
bdb_cf_gen, "( OLcfgDbAt:1.13 NAME 'olcDbCryptFile' "
"DESC 'Pathname of file containing the DB encryption key' "
"EQUALITY caseExactMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )",NULL, NULL },
{ "cryptkey", "key", 2, 2, 0, ARG_BERVAL|ARG_MAGIC|BDB_CRYPTKEY,
bdb_cf_gen, "( OLcfgDbAt:1.14 NAME 'olcDbCryptKey' "
"DESC 'DB encryption key' "
"EQUALITY octetStringMatch "
"SYNTAX OMsOctetString SINGLE-VALUE )",NULL, NULL },
{ "dbconfig", "DB_CONFIG setting", 1, 0, 0, ARG_MAGIC|BDB_CONFIG,
bdb_cf_gen, "( OLcfgDbAt:1.3 NAME 'olcDbConfig' "
"DESC 'BerkeleyDB DB_CONFIG configuration directives' "
"EQUALITY caseIgnoreIA5Match "
"SYNTAX OMsIA5String X-ORDERED 'VALUES' )", NULL, NULL },
{ "dbnosync", NULL, 1, 2, 0, ARG_ON_OFF|ARG_MAGIC|BDB_NOSYNC,
bdb_cf_gen, "( OLcfgDbAt:1.4 NAME 'olcDbNoSync' "
"DESC 'Disable synchronous database writes' "
"EQUALITY booleanMatch "
"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
{ "dbpagesize", "db> <size", 3, 3, 0, ARG_MAGIC|BDB_PGSIZE,
bdb_cf_gen, "( OLcfgDbAt:1.15 NAME 'olcDbPageSize' "
"DESC 'Page size of specified DB, in Kbytes' "
"EQUALITY caseExactMatch "
"SYNTAX OMsDirectoryString )", NULL, NULL },
{ "dirtyread", NULL, 1, 2, 0,
#ifdef SLAP_BDB_ALLOW_DIRTY_READ
ARG_ON_OFF|ARG_MAGIC|BDB_DIRTYR, bdb_cf_gen,
#else
ARG_IGNORED, NULL,
#endif
"( OLcfgDbAt:1.5 NAME 'olcDbDirtyRead' "
"DESC 'Allow reads of uncommitted data' "
"EQUALITY booleanMatch "
"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
{ "dncachesize", "size", 2, 2, 0, ARG_ULONG|ARG_OFFSET,
(void *)offsetof(struct bdb_info, bi_cache.c_eimax),
"( OLcfgDbAt:1.12 NAME 'olcDbDNcacheSize' "
"DESC 'DN cache size' "
"EQUALITY integerMatch "
"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
{ "idlcachesize", "size", 2, 2, 0, ARG_ULONG|ARG_OFFSET,
(void *)offsetof(struct bdb_info, bi_idl_cache_max_size),
"( OLcfgDbAt:1.6 NAME 'olcDbIDLcacheSize' "
"DESC 'IDL cache size in IDLs' "
"EQUALITY integerMatch "
"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
{ "index", "attr> <[pres,eq,approx,sub]", 2, 3, 0, ARG_MAGIC|BDB_INDEX,
bdb_cf_gen, "( OLcfgDbAt:0.2 NAME 'olcDbIndex' "
"DESC 'Attribute index parameters' "
"EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString )", NULL, NULL },
{ "linearindex", NULL, 1, 2, 0, ARG_ON_OFF|ARG_OFFSET,
(void *)offsetof(struct bdb_info, bi_linear_index),
"( OLcfgDbAt:1.7 NAME 'olcDbLinearIndex' "
"DESC 'Index attributes one at a time' "
"EQUALITY booleanMatch "
"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
{ "lockdetect", "policy", 2, 2, 0, ARG_MAGIC|BDB_LOCKD,
bdb_cf_gen, "( OLcfgDbAt:1.8 NAME 'olcDbLockDetect' "
"DESC 'Deadlock detection algorithm' "
"EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "mode", "mode", 2, 2, 0, ARG_MAGIC|BDB_MODE,
bdb_cf_gen, "( OLcfgDbAt:0.3 NAME 'olcDbMode' "
"DESC 'Unix permissions of database files' "
"EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "searchstack", "depth", 2, 2, 0, ARG_INT|ARG_MAGIC|BDB_SSTACK,
bdb_cf_gen, "( OLcfgDbAt:1.9 NAME 'olcDbSearchStack' "
"DESC 'Depth of search stack in IDLs' "
"EQUALITY integerMatch "
"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
{ "shm_key", "key", 2, 2, 0, ARG_LONG|ARG_OFFSET,
(void *)offsetof(struct bdb_info, bi_shm_key),
"( OLcfgDbAt:1.10 NAME 'olcDbShmKey' "
"DESC 'Key for shared memory region' "
"EQUALITY integerMatch "
"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
{ NULL, NULL, 0, 0, 0, ARG_IGNORED,
NULL, NULL, NULL, NULL }
};
static ConfigOCs bdbocs[] = {
{
#ifdef BDB_HIER
"( OLcfgDbOc:1.2 "
"NAME 'olcHdbConfig' "
"DESC 'HDB backend configuration' "
#else
"( OLcfgDbOc:1.1 "
"NAME 'olcBdbConfig' "
"DESC 'BDB backend configuration' "
#endif
"SUP olcDatabaseConfig "
"MUST olcDbDirectory "
"MAY ( olcDbCacheSize $ olcDbCheckpoint $ olcDbChecksum $ "
"olcDbConfig $ olcDbCryptFile $ olcDbCryptKey $ "
"olcDbNoSync $ olcDbDirtyRead $ olcDbIDLcacheSize $ "
"olcDbIndex $ olcDbLinearIndex $ olcDbLockDetect $ "
"olcDbMode $ olcDbSearchStack $ olcDbShmKey $ "
"olcDbCacheFree $ olcDbDNcacheSize $ olcDbPageSize ) )",
Cft_Database, bdbcfg },
{ NULL, 0, NULL }
};
static slap_verbmasks bdb_lockd[] = {
{ BER_BVC("default"), DB_LOCK_DEFAULT },
{ BER_BVC("oldest"), DB_LOCK_OLDEST },
{ BER_BVC("random"), DB_LOCK_RANDOM },
{ BER_BVC("youngest"), DB_LOCK_YOUNGEST },
{ BER_BVC("fewest"), DB_LOCK_MINLOCKS },
{ BER_BVNULL, 0 }
};
/* perform periodic checkpoints */
static void *
bdb_checkpoint( void *ctx, void *arg )
{
struct re_s *rtask = arg;
struct bdb_info *bdb = rtask->arg;
TXN_CHECKPOINT( bdb->bi_dbenv, bdb->bi_txn_cp_kbyte,
bdb->bi_txn_cp_min, 0 );
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
ldap_pvt_runqueue_stoptask( &slapd_rq, rtask );
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
return NULL;
}
/* reindex entries on the fly */
static void *
bdb_online_index( void *ctx, void *arg )
{
struct re_s *rtask = arg;
BackendDB *be = rtask->arg;
struct bdb_info *bdb = be->be_private;
Connection conn = {0};
OperationBuffer opbuf;
Operation *op;
DBC *curs;
DBT key, data;
DB_TXN *txn;
DB_LOCK lock;
ID id, nid;
EntryInfo *ei;
int rc, getnext = 1;
int i;
connection_fake_init( &conn, &opbuf, ctx );
op = &opbuf.ob_op;
op->o_bd = be;
DBTzero( &key );
DBTzero( &data );
id = 1;
key.data = &nid;
key.size = key.ulen = sizeof(ID);
key.flags = DB_DBT_USERMEM;
data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
data.dlen = data.ulen = 0;
while ( 1 ) {
if ( slapd_shutdown )
break;
rc = TXN_BEGIN( bdb->bi_dbenv, NULL, &txn, bdb->bi_db_opflags );
if ( rc )
break;
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_online_index) ": txn id: %x\n",
txn->id(txn) );
if ( getnext ) {
getnext = 0;
BDB_ID2DISK( id, &nid );
rc = bdb->bi_id2entry->bdi_db->cursor(
bdb->bi_id2entry->bdi_db, txn, &curs, bdb->bi_db_opflags );
if ( rc ) {
TXN_ABORT( txn );
break;
}
rc = curs->c_get( curs, &key, &data, DB_SET_RANGE );
curs->c_close( curs );
if ( rc ) {
TXN_ABORT( txn );
if ( rc == DB_NOTFOUND )
rc = 0;
if ( rc == DB_LOCK_DEADLOCK ) {
ldap_pvt_thread_yield();
continue;
}
break;
}
BDB_DISK2ID( &nid, &id );
}
ei = NULL;
rc = bdb_cache_find_id( op, txn, id, &ei, 0, &lock );
if ( rc ) {
TXN_ABORT( txn );
if ( rc == DB_LOCK_DEADLOCK ) {
ldap_pvt_thread_yield();
continue;
}
if ( rc == DB_NOTFOUND ) {
id++;
getnext = 1;
continue;
}
break;
}
if ( ei->bei_e ) {
rc = bdb_index_entry( op, txn, BDB_INDEX_UPDATE_OP, ei->bei_e );
if ( rc ) {
TXN_ABORT( txn );
if ( rc == DB_LOCK_DEADLOCK ) {
ldap_pvt_thread_yield();
continue;
}
break;
}
rc = TXN_COMMIT( txn, 0 );
txn = NULL;
}
id++;
getnext = 1;
}
for ( i = 0; i < bdb->bi_nattrs; i++ ) {
if ( bdb->bi_attrs[ i ]->ai_indexmask & BDB_INDEX_DELETING
|| bdb->bi_attrs[ i ]->ai_newmask == 0 )
{
continue;
}
bdb->bi_attrs[ i ]->ai_indexmask = bdb->bi_attrs[ i ]->ai_newmask;
bdb->bi_attrs[ i ]->ai_newmask = 0;
}
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
ldap_pvt_runqueue_stoptask( &slapd_rq, rtask );
bdb->bi_index_task = NULL;
ldap_pvt_runqueue_remove( &slapd_rq, rtask );
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
return NULL;
}
/* Cleanup loose ends after Modify completes */
static int
bdb_cf_cleanup( ConfigArgs *c )
{
struct bdb_info *bdb = c->be->be_private;
int rc = 0;
BerVarray bva;
if ( bdb->bi_flags & BDB_DEL_INDEX ) {
bdb_attr_flush( bdb );
bdb->bi_flags ^= BDB_DEL_INDEX;
}
if ( bdb->bi_flags & BDB_RE_OPEN ) {
bdb->bi_flags ^= BDB_RE_OPEN;
bva = bdb->bi_db_config;
bdb->bi_db_config = NULL;
rc = c->be->bd_info->bi_db_close( c->be, &c->reply );
if ( rc == 0 ) {
if ( bdb->bi_flags & BDB_UPD_CONFIG ) {
if ( bva ) {
int i;
FILE *f = fopen( bdb->bi_db_config_path, "w" );
if ( f ) {
bdb->bi_db_config = bva;
bva = NULL;
for (i=0; bdb->bi_db_config[i].bv_val; i++)
fprintf( f, "%s\n", bdb->bi_db_config[i].bv_val );
fclose( f );
} else {
ber_bvarray_free( bva );
}
} else {
unlink( bdb->bi_db_config_path );
}
bdb->bi_flags ^= BDB_UPD_CONFIG;
}
rc = c->be->bd_info->bi_db_open( c->be, &c->reply );
}
/* If this fails, we need to restart */
if ( rc ) {
slapd_shutdown = 2;
snprintf( c->cr_msg, sizeof( c->cr_msg ),
"failed to reopen database, rc=%d", rc );
Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_cf_cleanup)
": %s\n", c->cr_msg );
rc = LDAP_OTHER;
}
}
return rc;
}
static int
bdb_cf_gen( ConfigArgs *c )
{
struct bdb_info *bdb = c->be->be_private;
int rc;
if ( c->op == SLAP_CONFIG_EMIT ) {
rc = 0;
switch( c->type ) {
case BDB_MODE: {
char buf[64];
struct berval bv;
bv.bv_len = snprintf( buf, sizeof(buf), "0%o", bdb->bi_dbenv_mode );
if ( bv.bv_len > 0 && bv.bv_len < sizeof(buf) ) {
bv.bv_val = buf;
value_add_one( &c->rvalue_vals, &bv );
} else {
rc = 1;
}
} break;
case BDB_CHKPT:
if ( bdb->bi_txn_cp ) {
char buf[64];
struct berval bv;
bv.bv_len = snprintf( buf, sizeof(buf), "%ld %ld",
(long) bdb->bi_txn_cp_kbyte, (long) bdb->bi_txn_cp_min );
if ( bv.bv_len > 0 && bv.bv_len < sizeof(buf) ) {
bv.bv_val = buf;
value_add_one( &c->rvalue_vals, &bv );
} else {
rc = 1;
}
} else {
rc = 1;
}
break;
case BDB_CRYPTFILE:
if ( bdb->bi_db_crypt_file ) {
c->value_string = ch_strdup( bdb->bi_db_crypt_file );
} else {
rc = 1;
}
break;
/* If a crypt file has been set, its contents are copied here.
* But we don't want the key to be incorporated here.
*/
case BDB_CRYPTKEY:
if ( !bdb->bi_db_crypt_file && !BER_BVISNULL( &bdb->bi_db_crypt_key )) {
value_add_one( &c->rvalue_vals, &bdb->bi_db_crypt_key );
} else {
rc = 1;
}
break;
case BDB_DIRECTORY:
if ( bdb->bi_dbenv_home ) {
c->value_string = ch_strdup( bdb->bi_dbenv_home );
} else {
rc = 1;
}
break;
case BDB_CONFIG:
if ( !( bdb->bi_flags & BDB_IS_OPEN )
&& !bdb->bi_db_config )
{
char buf[SLAP_TEXT_BUFLEN];
FILE *f = fopen( bdb->bi_db_config_path, "r" );
struct berval bv;
if ( f ) {
bdb->bi_flags |= BDB_HAS_CONFIG;
while ( fgets( buf, sizeof(buf), f )) {
ber_str2bv( buf, 0, 1, &bv );
if ( bv.bv_len > 0 && bv.bv_val[bv.bv_len-1] == '\n' ) {
bv.bv_len--;
bv.bv_val[bv.bv_len] = '\0';
}
/* shouldn't need this, but ... */
if ( bv.bv_len > 0 && bv.bv_val[bv.bv_len-1] == '\r' ) {
bv.bv_len--;
bv.bv_val[bv.bv_len] = '\0';
}
ber_bvarray_add( &bdb->bi_db_config, &bv );
}
fclose( f );
}
}
if ( bdb->bi_db_config ) {
int i;
struct berval bv;
bv.bv_val = c->log;
for (i=0; !BER_BVISNULL(&bdb->bi_db_config[i]); i++) {
bv.bv_len = sprintf( bv.bv_val, "{%d}%s", i,
bdb->bi_db_config[i].bv_val );
value_add_one( &c->rvalue_vals, &bv );
}
}
if ( !c->rvalue_vals ) rc = 1;
break;
case BDB_NOSYNC:
if ( bdb->bi_dbenv_xflags & DB_TXN_NOSYNC )
c->value_int = 1;
break;
case BDB_CHECKSUM:
if ( bdb->bi_flags & BDB_CHKSUM )
c->value_int = 1;
break;
case BDB_INDEX:
bdb_attr_index_unparse( bdb, &c->rvalue_vals );
if ( !c->rvalue_vals ) rc = 1;
break;
case BDB_LOCKD:
rc = 1;
if ( bdb->bi_lock_detect != DB_LOCK_DEFAULT ) {
int i;
for (i=0; !BER_BVISNULL(&bdb_lockd[i].word); i++) {
if ( bdb->bi_lock_detect == (u_int32_t)bdb_lockd[i].mask ) {
value_add_one( &c->rvalue_vals, &bdb_lockd[i].word );
rc = 0;
break;
}
}
}
break;
case BDB_SSTACK:
c->value_int = bdb->bi_search_stack_depth;
break;
case BDB_PGSIZE: {
struct bdb_db_pgsize *ps;
char buf[SLAP_TEXT_BUFLEN];
struct berval bv;
int rc = 1;
bv.bv_val = buf;
for ( ps = bdb->bi_pagesizes; ps; ps = ps->bdp_next ) {
bv.bv_len = sprintf( buf, "%s %d", ps->bdp_name.bv_val,
ps->bdp_size / 1024 );
value_add_one( &c->rvalue_vals, &bv );
rc = 0;
}
break;
}
}
return rc;
} else if ( c->op == LDAP_MOD_DELETE ) {
rc = 0;
switch( c->type ) {
case BDB_MODE:
#if 0
/* FIXME: does it make any sense to change the mode,
* if we don't exec a chmod()? */
bdb->bi_dbenv_mode = SLAPD_DEFAULT_DB_MODE;
break;
#endif
/* single-valued no-ops */
case BDB_LOCKD:
case BDB_SSTACK:
break;
case BDB_CHKPT:
if ( bdb->bi_txn_cp_task ) {
struct re_s *re = bdb->bi_txn_cp_task;
bdb->bi_txn_cp_task = NULL;
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
if ( ldap_pvt_runqueue_isrunning( &slapd_rq, re ) )
ldap_pvt_runqueue_stoptask( &slapd_rq, re );
ldap_pvt_runqueue_remove( &slapd_rq, re );
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
}
bdb->bi_txn_cp = 0;
break;
case BDB_CONFIG:
if ( c->valx < 0 ) {
ber_bvarray_free( bdb->bi_db_config );
bdb->bi_db_config = NULL;
} else {
int i = c->valx;
ch_free( bdb->bi_db_config[i].bv_val );
for (; bdb->bi_db_config[i].bv_val; i++)
bdb->bi_db_config[i] = bdb->bi_db_config[i+1];
}
bdb->bi_flags |= BDB_UPD_CONFIG|BDB_RE_OPEN;
c->cleanup = bdb_cf_cleanup;
break;
/* Doesn't really make sense to change these on the fly;
* the entire DB must be dumped and reloaded
*/
case BDB_CRYPTFILE:
if ( bdb->bi_db_crypt_file ) {
ch_free( bdb->bi_db_crypt_file );
bdb->bi_db_crypt_file = NULL;
}
/* FALLTHRU */
case BDB_CRYPTKEY:
if ( !BER_BVISNULL( &bdb->bi_db_crypt_key )) {
ch_free( bdb->bi_db_crypt_key.bv_val );
BER_BVZERO( &bdb->bi_db_crypt_key );
}
break;
case BDB_DIRECTORY:
bdb->bi_flags |= BDB_RE_OPEN;
bdb->bi_flags ^= BDB_HAS_CONFIG;
ch_free( bdb->bi_dbenv_home );
bdb->bi_dbenv_home = NULL;
ch_free( bdb->bi_db_config_path );
bdb->bi_db_config_path = NULL;
c->cleanup = bdb_cf_cleanup;
ldap_pvt_thread_pool_purgekey( bdb->bi_dbenv );
break;
case BDB_NOSYNC:
bdb->bi_dbenv->set_flags( bdb->bi_dbenv, DB_TXN_NOSYNC, 0 );
break;
case BDB_CHECKSUM:
bdb->bi_flags &= ~BDB_CHKSUM;
break;
case BDB_INDEX:
if ( c->valx == -1 ) {
int i;
/* delete all */
for ( i = 0; i < bdb->bi_nattrs; i++ ) {
bdb->bi_attrs[i]->ai_indexmask |= BDB_INDEX_DELETING;
}
bdb->bi_defaultmask = 0;
bdb->bi_flags |= BDB_DEL_INDEX;
c->cleanup = bdb_cf_cleanup;
} else {
struct berval bv, def = BER_BVC("default");
char *ptr;
for (ptr = c->line; !isspace( (unsigned char) *ptr ); ptr++);
bv.bv_val = c->line;
bv.bv_len = ptr - bv.bv_val;
if ( bvmatch( &bv, &def )) {
bdb->bi_defaultmask = 0;
} else {
int i;
char **attrs;
char sep;
sep = bv.bv_val[ bv.bv_len ];
bv.bv_val[ bv.bv_len ] = '\0';
attrs = ldap_str2charray( bv.bv_val, "," );
for ( i = 0; attrs[ i ]; i++ ) {
AttributeDescription *ad = NULL;
const char *text;
AttrInfo *ai;
slap_str2ad( attrs[ i ], &ad, &text );
/* if we got here... */
assert( ad != NULL );
ai = bdb_attr_mask( bdb, ad );
/* if we got here... */
assert( ai != NULL );
ai->ai_indexmask |= BDB_INDEX_DELETING;
bdb->bi_flags |= BDB_DEL_INDEX;
c->cleanup = bdb_cf_cleanup;
}
bv.bv_val[ bv.bv_len ] = sep;
ldap_charray_free( attrs );
}
}
break;
/* doesn't make sense on the fly; the DB file must be
* recreated
*/
case BDB_PGSIZE: {
struct bdb_db_pgsize *ps, **prev;
int i;
for ( i = 0, prev = &bdb->bi_pagesizes, ps = *prev; ps;
prev = &ps->bdp_next, ps = ps->bdp_next, i++ ) {
if ( c->valx == -1 || i == c->valx ) {
*prev = ps->bdp_next;
ch_free( ps );
ps = *prev;
if ( i == c->valx ) break;
}
}
}
break;
}
return rc;
}
switch( c->type ) {
case BDB_MODE:
if ( ASCII_DIGIT( c->argv[1][0] ) ) {
long mode;
char *next;
errno = 0;
mode = strtol( c->argv[1], &next, 0 );
if ( errno != 0 || next == c->argv[1] || next[0] != '\0' ) {
fprintf( stderr, "%s: "
"unable to parse mode=\"%s\".\n",
c->log, c->argv[1] );
return 1;
}
bdb->bi_dbenv_mode = mode;
} else {
char *m = c->argv[1];
int who, what, mode = 0;
if ( strlen( m ) != STRLENOF("-rwxrwxrwx") ) {
return 1;
}
if ( m[0] != '-' ) {
return 1;
}
m++;
for ( who = 0; who < 3; who++ ) {
for ( what = 0; what < 3; what++, m++ ) {
if ( m[0] == '-' ) {
continue;
} else if ( m[0] != "rwx"[what] ) {
return 1;
}
mode += ((1 << (2 - what)) << 3*(2 - who));
}
}
bdb->bi_dbenv_mode = mode;
}
break;
case BDB_CHKPT: {
long l;
bdb->bi_txn_cp = 1;
if ( lutil_atolx( &l, c->argv[1], 0 ) != 0 ) {
fprintf( stderr, "%s: "
"invalid kbyte \"%s\" in \"checkpoint\".\n",
c->log, c->argv[1] );
return 1;
}
bdb->bi_txn_cp_kbyte = l;
if ( lutil_atolx( &l, c->argv[2], 0 ) != 0 ) {
fprintf( stderr, "%s: "
"invalid minutes \"%s\" in \"checkpoint\".\n",
c->log, c->argv[2] );
return 1;
}
bdb->bi_txn_cp_min = l;
/* If we're in server mode and time-based checkpointing is enabled,
* submit a task to perform periodic checkpoints.
*/
if ((slapMode & SLAP_SERVER_MODE) && bdb->bi_txn_cp_min ) {
struct re_s *re = bdb->bi_txn_cp_task;
if ( re ) {
re->interval.tv_sec = bdb->bi_txn_cp_min * 60;
} else {
if ( c->be->be_suffix == NULL || BER_BVISNULL( &c->be->be_suffix[0] ) ) {
fprintf( stderr, "%s: "
"\"checkpoint\" must occur after \"suffix\".\n",
c->log );
return 1;
}
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
bdb->bi_txn_cp_task = ldap_pvt_runqueue_insert( &slapd_rq,
bdb->bi_txn_cp_min * 60, bdb_checkpoint, bdb,
LDAP_XSTRING(bdb_checkpoint), c->be->be_suffix[0].bv_val );
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
}
}
} break;
case BDB_CONFIG: {
char *ptr = c->line;
struct berval bv;
if ( c->op == SLAP_CONFIG_ADD ) {
ptr += STRLENOF("dbconfig");
while (!isspace((unsigned char)*ptr)) ptr++;
while (isspace((unsigned char)*ptr)) ptr++;
}
if ( bdb->bi_flags & BDB_IS_OPEN ) {
bdb->bi_flags |= BDB_UPD_CONFIG|BDB_RE_OPEN;
c->cleanup = bdb_cf_cleanup;
} else {
/* If we're just starting up...
*/
FILE *f;
/* If a DB_CONFIG file exists, or we don't know the path
* to the DB_CONFIG file, ignore these directives
*/
if (( bdb->bi_flags & BDB_HAS_CONFIG ) || !bdb->bi_db_config_path )
break;
f = fopen( bdb->bi_db_config_path, "a" );
if ( f ) {
/* FIXME: EBCDIC probably needs special handling */
fprintf( f, "%s\n", ptr );
fclose( f );
}
}
ber_str2bv( ptr, 0, 1, &bv );
ber_bvarray_add( &bdb->bi_db_config, &bv );
}
break;
case BDB_CRYPTFILE:
rc = lutil_get_filed_password( c->value_string, &bdb->bi_db_crypt_key );
if ( rc == 0 ) {
bdb->bi_db_crypt_file = c->value_string;
}
break;
/* Cannot set key if file was already set */
case BDB_CRYPTKEY:
if ( bdb->bi_db_crypt_file ) {
rc = 1;
} else {
bdb->bi_db_crypt_key = c->value_bv;
}
break;
case BDB_DIRECTORY: {
FILE *f;
char *ptr, *testpath;
int len;
len = strlen( c->value_string );
testpath = ch_malloc( len + STRLENOF(LDAP_DIRSEP) + STRLENOF("DUMMY") + 1 );
ptr = lutil_strcopy( testpath, c->value_string );
*ptr++ = LDAP_DIRSEP[0];
strcpy( ptr, "DUMMY" );
f = fopen( testpath, "w" );
if ( f ) {
fclose( f );
unlink( testpath );
}
ch_free( testpath );
if ( !f ) {
snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: invalid path: %s",
c->log, strerror( errno ));
Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg );
return -1;
}
if ( bdb->bi_dbenv_home )
ch_free( bdb->bi_dbenv_home );
bdb->bi_dbenv_home = c->value_string;
/* See if a DB_CONFIG file already exists here */
if ( bdb->bi_db_config_path )
ch_free( bdb->bi_db_config_path );
bdb->bi_db_config_path = ch_malloc( len +
STRLENOF(LDAP_DIRSEP) + STRLENOF("DB_CONFIG") + 1 );
ptr = lutil_strcopy( bdb->bi_db_config_path, bdb->bi_dbenv_home );
*ptr++ = LDAP_DIRSEP[0];
strcpy( ptr, "DB_CONFIG" );
f = fopen( bdb->bi_db_config_path, "r" );
if ( f ) {
bdb->bi_flags |= BDB_HAS_CONFIG;
fclose(f);
}
}
break;
case BDB_NOSYNC:
if ( c->value_int )
bdb->bi_dbenv_xflags |= DB_TXN_NOSYNC;
else
bdb->bi_dbenv_xflags &= ~DB_TXN_NOSYNC;
if ( bdb->bi_flags & BDB_IS_OPEN ) {
bdb->bi_dbenv->set_flags( bdb->bi_dbenv, DB_TXN_NOSYNC,
c->value_int );
}
break;
case BDB_CHECKSUM:
if ( c->value_int )
bdb->bi_flags |= BDB_CHKSUM;
else
bdb->bi_flags &= ~BDB_CHKSUM;
break;
case BDB_INDEX:
rc = bdb_attr_index_config( bdb, c->fname, c->lineno,
c->argc - 1, &c->argv[1], &c->reply);
if( rc != LDAP_SUCCESS ) return 1;
if (( bdb->bi_flags & BDB_IS_OPEN ) && !bdb->bi_index_task ) {
/* Start the task as soon as we finish here. Set a long
* interval (10 hours) so that it only gets scheduled once.
*/
if ( c->be->be_suffix == NULL || BER_BVISNULL( &c->be->be_suffix[0] ) ) {
fprintf( stderr, "%s: "
"\"index\" must occur after \"suffix\".\n",
c->log );
return 1;
}
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
bdb->bi_index_task = ldap_pvt_runqueue_insert( &slapd_rq, 36000,
bdb_online_index, c->be,
LDAP_XSTRING(bdb_online_index), c->be->be_suffix[0].bv_val );
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
}
break;
case BDB_LOCKD:
rc = verb_to_mask( c->argv[1], bdb_lockd );
if ( BER_BVISNULL(&bdb_lockd[rc].word) ) {
fprintf( stderr, "%s: "
"bad policy (%s) in \"lockDetect <policy>\" line\n",
c->log, c->argv[1] );
return 1;
}
bdb->bi_lock_detect = (u_int32_t)rc;
break;
case BDB_SSTACK:
if ( c->value_int < MINIMUM_SEARCH_STACK_DEPTH ) {
fprintf( stderr,
"%s: depth %d too small, using %d\n",
c->log, c->value_int, MINIMUM_SEARCH_STACK_DEPTH );
c->value_int = MINIMUM_SEARCH_STACK_DEPTH;
}
bdb->bi_search_stack_depth = c->value_int;
break;
case BDB_PGSIZE: {
struct bdb_db_pgsize *ps, **prev;
int i, s;
s = atoi(c->argv[2]);
if ( s < 1 || s > 64 ) {
snprintf( c->cr_msg, sizeof( c->cr_msg ),
"%s: size must be > 0 and <= 64: %d",
c->log, s );
Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg );
return -1;
}
i = strlen(c->argv[1]);
ps = ch_malloc( sizeof(struct bdb_db_pgsize) + i + 1 );
ps->bdp_next = NULL;
ps->bdp_name.bv_len = i;
ps->bdp_name.bv_val = (char *)(ps+1);
strcpy( ps->bdp_name.bv_val, c->argv[1] );
ps->bdp_size = s * 1024;
for ( prev = &bdb->bi_pagesizes; *prev; prev = &(*prev)->bdp_next )
;
*prev = ps;
}
break;
}
return 0;
}
int bdb_back_init_cf( BackendInfo *bi )
{
int rc;
bi->bi_cf_ocs = bdbocs;
rc = config_register_schema( bdbcfg, bdbocs );
if ( rc ) return rc;
return 0;
}

View File

@ -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-2019 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/errno.h>
#include <ac/socket.h>
#include <ac/string.h>
#include <ac/time.h>
#include <sys/stat.h>
#include "slap.h"
#include "back-bdb.h"
#include "lutil_hash.h"
#ifdef BDB_INDEX_USE_HASH
/* Pass-thru hash function. Since the indexer is already giving us hash
* values as keys, we don't need BDB to re-hash them.
*/
static u_int32_t
bdb_db_hash(
DB *db,
const void *bytes,
u_int32_t length
)
{
u_int32_t ret = 0;
unsigned char *dst = (unsigned char *)&ret;
const unsigned char *src = (const unsigned char *)bytes;
if ( length > sizeof(u_int32_t) )
length = sizeof(u_int32_t);
while ( length ) {
*dst++ = *src++;
length--;
}
return ret;
}
#define BDB_INDEXTYPE DB_HASH
#else
#define BDB_INDEXTYPE DB_BTREE
#endif
/* If a configured size is found, return it, otherwise return 0 */
int
bdb_db_findsize(
struct bdb_info *bdb,
struct berval *name
)
{
struct bdb_db_pgsize *bp;
int rc;
for ( bp = bdb->bi_pagesizes; bp; bp=bp->bdp_next ) {
rc = strncmp( name->bv_val, bp->bdp_name.bv_val, name->bv_len );
if ( !rc ) {
if ( name->bv_len == bp->bdp_name.bv_len )
return bp->bdp_size;
if ( name->bv_len < bp->bdp_name.bv_len &&
bp->bdp_name.bv_val[name->bv_len] == '.' )
return bp->bdp_size;
}
}
return 0;
}
int
bdb_db_cache(
Backend *be,
struct berval *name,
DB **dbout )
{
int i, flags;
int rc;
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
struct bdb_db_info *db;
char *file;
*dbout = NULL;
for( i=BDB_NDB; i < bdb->bi_ndatabases; i++ ) {
if( !ber_bvcmp( &bdb->bi_databases[i]->bdi_name, name) ) {
*dbout = bdb->bi_databases[i]->bdi_db;
return 0;
}
}
ldap_pvt_thread_mutex_lock( &bdb->bi_database_mutex );
/* check again! may have been added by another thread */
for( i=BDB_NDB; i < bdb->bi_ndatabases; i++ ) {
if( !ber_bvcmp( &bdb->bi_databases[i]->bdi_name, name) ) {
*dbout = bdb->bi_databases[i]->bdi_db;
ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
return 0;
}
}
if( i >= BDB_INDICES ) {
ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
return -1;
}
db = (struct bdb_db_info *) ch_calloc(1, sizeof(struct bdb_db_info));
ber_dupbv( &db->bdi_name, name );
rc = db_create( &db->bdi_db, bdb->bi_dbenv, 0 );
if( rc != 0 ) {
Debug( LDAP_DEBUG_ANY,
"bdb_db_cache: db_create(%s) failed: %s (%d)\n",
bdb->bi_dbenv_home, db_strerror(rc), rc );
ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
ch_free( db );
return rc;
}
if( !BER_BVISNULL( &bdb->bi_db_crypt_key )) {
rc = db->bdi_db->set_flags( db->bdi_db, DB_ENCRYPT );
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
"bdb_db_cache: db set_flags(DB_ENCRYPT)(%s) failed: %s (%d)\n",
bdb->bi_dbenv_home, db_strerror(rc), rc );
ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
db->bdi_db->close( db->bdi_db, 0 );
ch_free( db );
return rc;
}
}
if( bdb->bi_flags & BDB_CHKSUM ) {
rc = db->bdi_db->set_flags( db->bdi_db, DB_CHKSUM );
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
"bdb_db_cache: db set_flags(DB_CHKSUM)(%s) failed: %s (%d)\n",
bdb->bi_dbenv_home, db_strerror(rc), rc );
ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
db->bdi_db->close( db->bdi_db, 0 );
ch_free( db );
return rc;
}
}
/* If no explicit size set, use the FS default */
flags = bdb_db_findsize( bdb, name );
if ( flags )
rc = db->bdi_db->set_pagesize( db->bdi_db, flags );
#ifdef BDB_INDEX_USE_HASH
rc = db->bdi_db->set_h_hash( db->bdi_db, bdb_db_hash );
#endif
rc = db->bdi_db->set_flags( db->bdi_db, DB_DUP | DB_DUPSORT );
file = ch_malloc( db->bdi_name.bv_len + sizeof(BDB_SUFFIX) );
strcpy( file, db->bdi_name.bv_val );
strcpy( file+db->bdi_name.bv_len, BDB_SUFFIX );
#ifdef HAVE_EBCDIC
__atoe( file );
#endif
flags = DB_CREATE | DB_THREAD;
#ifdef DB_AUTO_COMMIT
if ( !( slapMode & SLAP_TOOL_QUICK ))
flags |= DB_AUTO_COMMIT;
#endif
/* Cannot Truncate when Transactions are in use */
if ( (slapMode & (SLAP_TOOL_QUICK|SLAP_TRUNCATE_MODE)) ==
(SLAP_TOOL_QUICK|SLAP_TRUNCATE_MODE))
flags |= DB_TRUNCATE;
rc = DB_OPEN( db->bdi_db,
file, NULL /* name */,
BDB_INDEXTYPE, bdb->bi_db_opflags | flags, bdb->bi_dbenv_mode );
ch_free( file );
if( rc != 0 ) {
Debug( LDAP_DEBUG_ANY,
"bdb_db_cache: db_open(%s) failed: %s (%d)\n",
name->bv_val, db_strerror(rc), rc );
ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
db->bdi_db->close( db->bdi_db, 0 );
ch_free( db );
return rc;
}
bdb->bi_databases[i] = db;
bdb->bi_ndatabases = i+1;
*dbout = db->bdi_db;
ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
return 0;
}

View File

@ -1,569 +0,0 @@
/* delete.c - bdb backend delete routine */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2000-2019 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include "lutil.h"
#include "back-bdb.h"
int
bdb_delete( Operation *op, SlapReply *rs )
{
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
Entry *matched = NULL;
struct berval pdn = {0, NULL};
Entry *e = NULL;
Entry *p = NULL;
EntryInfo *ei = NULL, *eip = NULL;
int manageDSAit = get_manageDSAit( op );
AttributeDescription *children = slap_schema.si_ad_children;
AttributeDescription *entry = slap_schema.si_ad_entry;
DB_TXN *ltid = NULL, *lt2;
struct bdb_op_info opinfo = {{{ 0 }}};
ID eid;
DB_LOCK lock, plock;
int num_retries = 0;
int rc;
LDAPControl **preread_ctrl = NULL;
LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
int num_ctrls = 0;
int parent_is_glue = 0;
int parent_is_leaf = 0;
Debug( LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(bdb_delete) ": %s\n",
op->o_req_dn.bv_val );
#ifdef LDAP_X_TXN
if( op->o_txnSpec && txn_preop( op, rs ))
return rs->sr_err;
#endif
ctrls[num_ctrls] = 0;
/* allocate CSN */
if ( BER_BVISNULL( &op->o_csn ) ) {
struct berval csn;
char csnbuf[LDAP_PVT_CSNSTR_BUFSIZE];
csn.bv_val = csnbuf;
csn.bv_len = sizeof(csnbuf);
slap_get_csn( op, &csn, 1 );
}
if( 0 ) {
retry: /* transaction retry */
if( e != NULL ) {
bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
e = NULL;
}
if( p != NULL ) {
bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
p = NULL;
}
Debug( LDAP_DEBUG_TRACE,
"==> " LDAP_XSTRING(bdb_delete) ": retrying...\n" );
rs->sr_err = TXN_ABORT( ltid );
ltid = NULL;
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
opinfo.boi_oe.oe_key = NULL;
op->o_do_not_cache = opinfo.boi_acl_cache;
if( rs->sr_err != 0 ) {
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
if ( op->o_abandon ) {
rs->sr_err = SLAPD_ABANDON;
goto return_results;
}
parent_is_glue = 0;
parent_is_leaf = 0;
bdb_trans_backoff( ++num_retries );
}
/* begin transaction */
{
int tflags = bdb->bi_db_opflags;
if ( get_lazyCommit( op ))
tflags |= DB_TXN_NOSYNC;
rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, NULL, &ltid, tflags );
}
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_delete) ": txn1 id: %x\n",
ltid->id(ltid) );
rs->sr_text = NULL;
if( rs->sr_err != 0 ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_delete) ": txn_begin failed: "
"%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
opinfo.boi_oe.oe_key = bdb;
opinfo.boi_txn = ltid;
opinfo.boi_err = 0;
opinfo.boi_acl_cache = op->o_do_not_cache;
LDAP_SLIST_INSERT_HEAD( &op->o_extra, &opinfo.boi_oe, oe_next );
if ( !be_issuffix( op->o_bd, &op->o_req_ndn ) ) {
dnParent( &op->o_req_ndn, &pdn );
}
/* get entry */
rs->sr_err = bdb_dn2entry( op, ltid, &op->o_req_ndn, &ei, 1,
&lock );
switch( rs->sr_err ) {
case 0:
case DB_NOTFOUND:
break;
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
case LDAP_BUSY:
rs->sr_text = "ldap server busy";
goto return_results;
default:
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
if ( rs->sr_err == 0 ) {
e = ei->bei_e;
eip = ei->bei_parent;
} else {
matched = ei->bei_e;
}
/* FIXME : dn2entry() should return non-glue entry */
if ( e == NULL || ( !manageDSAit && is_entry_glue( e ))) {
Debug( LDAP_DEBUG_ARGS,
"<=- " LDAP_XSTRING(bdb_delete) ": no such object %s\n",
op->o_req_dn.bv_val );
if ( matched != NULL ) {
rs->sr_matched = ch_strdup( matched->e_dn );
rs->sr_ref = is_entry_referral( matched )
? get_entry_referrals( op, matched )
: NULL;
bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, matched);
matched = NULL;
} else {
rs->sr_ref = referral_rewrite( default_referral, NULL,
&op->o_req_dn, LDAP_SCOPE_DEFAULT );
}
rs->sr_err = LDAP_REFERRAL;
rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
goto return_results;
}
rc = bdb_cache_find_id( op, ltid, eip->bei_id, &eip, 0, &plock );
switch( rc ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
case 0:
case DB_NOTFOUND:
break;
default:
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
if ( eip ) p = eip->bei_e;
if ( pdn.bv_len != 0 ) {
if( p == NULL || !bvmatch( &pdn, &p->e_nname )) {
Debug( LDAP_DEBUG_TRACE,
"<=- " LDAP_XSTRING(bdb_delete) ": parent "
"does not exist\n" );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "could not locate parent of entry";
goto return_results;
}
/* check parent for "children" acl */
rs->sr_err = access_allowed( op, p,
children, NULL, ACL_WDEL, NULL );
if ( !rs->sr_err ) {
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
Debug( LDAP_DEBUG_TRACE,
"<=- " LDAP_XSTRING(bdb_delete) ": no write "
"access to parent\n" );
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
rs->sr_text = "no write access to parent";
goto return_results;
}
} else {
/* no parent, must be root to delete */
if( ! be_isroot( op ) ) {
if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv )
|| be_shadow_update( op ) ) {
p = (Entry *)&slap_entry_root;
/* check parent for "children" acl */
rs->sr_err = access_allowed( op, p,
children, NULL, ACL_WDEL, NULL );
p = NULL;
if ( !rs->sr_err ) {
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
Debug( LDAP_DEBUG_TRACE,
"<=- " LDAP_XSTRING(bdb_delete)
": no access to parent\n" );
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
rs->sr_text = "no write access to parent";
goto return_results;
}
} else {
Debug( LDAP_DEBUG_TRACE,
"<=- " LDAP_XSTRING(bdb_delete)
": no parent and not root\n" );
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
goto return_results;
}
}
}
if ( get_assert( op ) &&
( test_filter( op, e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
{
rs->sr_err = LDAP_ASSERTION_FAILED;
goto return_results;
}
rs->sr_err = access_allowed( op, e,
entry, NULL, ACL_WDEL, NULL );
if ( !rs->sr_err ) {
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
Debug( LDAP_DEBUG_TRACE,
"<=- " LDAP_XSTRING(bdb_delete) ": no write access "
"to entry\n" );
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
rs->sr_text = "no write access to entry";
goto return_results;
}
if ( !manageDSAit && is_entry_referral( e ) ) {
/* entry is a referral, don't allow delete */
rs->sr_ref = get_entry_referrals( op, e );
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_delete) ": entry is referral\n" );
rs->sr_err = LDAP_REFERRAL;
rs->sr_matched = ch_strdup( e->e_name.bv_val );
rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
goto return_results;
}
/* pre-read */
if( op->o_preread ) {
if( preread_ctrl == NULL ) {
preread_ctrl = &ctrls[num_ctrls++];
ctrls[num_ctrls] = NULL;
}
if( slap_read_controls( op, rs, e,
&slap_pre_read_bv, preread_ctrl ) )
{
Debug( LDAP_DEBUG_TRACE,
"<=- " LDAP_XSTRING(bdb_delete) ": pre-read "
"failed!\n" );
if ( op->o_preread & SLAP_CONTROL_CRITICAL ) {
/* FIXME: is it correct to abort
* operation if control fails? */
goto return_results;
}
}
}
/* nested transaction */
rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, &lt2,
bdb->bi_db_opflags );
rs->sr_text = NULL;
if( rs->sr_err != 0 ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_delete) ": txn_begin(2) failed: "
"%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_delete) ": txn2 id: %x\n",
lt2->id(lt2) );
BDB_LOG_PRINTF( bdb->bi_dbenv, lt2, "slapd Starting delete %s(%d)",
e->e_nname.bv_val, e->e_id );
/* Can't do it if we have kids */
rs->sr_err = bdb_cache_children( op, lt2, e );
if( rs->sr_err != DB_NOTFOUND ) {
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
case 0:
Debug(LDAP_DEBUG_ARGS,
"<=- " LDAP_XSTRING(bdb_delete)
": non-leaf %s\n",
op->o_req_dn.bv_val );
rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
rs->sr_text = "subordinate objects must be deleted first";
break;
default:
Debug(LDAP_DEBUG_ARGS,
"<=- " LDAP_XSTRING(bdb_delete)
": has_children failed: %s (%d)\n",
db_strerror(rs->sr_err), rs->sr_err );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
}
goto return_results;
}
/* delete from dn2id */
rs->sr_err = bdb_dn2id_delete( op, lt2, eip, e );
if ( rs->sr_err != 0 ) {
Debug(LDAP_DEBUG_TRACE,
"<=- " LDAP_XSTRING(bdb_delete) ": dn2id failed: "
"%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err );
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
rs->sr_text = "DN index delete failed";
rs->sr_err = LDAP_OTHER;
goto return_results;
}
/* delete indices for old attributes */
rs->sr_err = bdb_index_entry_del( op, lt2, e );
if ( rs->sr_err != LDAP_SUCCESS ) {
Debug(LDAP_DEBUG_TRACE,
"<=- " LDAP_XSTRING(bdb_delete) ": index failed: "
"%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err );
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
rs->sr_text = "entry index delete failed";
rs->sr_err = LDAP_OTHER;
goto return_results;
}
/* fixup delete CSN */
if ( !SLAP_SHADOW( op->o_bd )) {
struct berval vals[2];
assert( !BER_BVISNULL( &op->o_csn ) );
vals[0] = op->o_csn;
BER_BVZERO( &vals[1] );
rs->sr_err = bdb_index_values( op, lt2, slap_schema.si_ad_entryCSN,
vals, 0, SLAP_INDEX_ADD_OP );
if ( rs->sr_err != LDAP_SUCCESS ) {
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
rs->sr_text = "entryCSN index update failed";
rs->sr_err = LDAP_OTHER;
goto return_results;
}
}
/* delete from id2entry */
rs->sr_err = bdb_id2entry_delete( op->o_bd, lt2, e );
if ( rs->sr_err != 0 ) {
Debug( LDAP_DEBUG_TRACE,
"<=- " LDAP_XSTRING(bdb_delete) ": id2entry failed: "
"%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err );
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
rs->sr_text = "entry delete failed";
rs->sr_err = LDAP_OTHER;
goto return_results;
}
if ( pdn.bv_len != 0 ) {
parent_is_glue = is_entry_glue(p);
rs->sr_err = bdb_cache_children( op, lt2, p );
if ( rs->sr_err != DB_NOTFOUND ) {
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
case 0:
break;
default:
Debug(LDAP_DEBUG_ARGS,
"<=- " LDAP_XSTRING(bdb_delete)
": has_children failed: %s (%d)\n",
db_strerror(rs->sr_err), rs->sr_err );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
parent_is_leaf = 1;
}
bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
p = NULL;
}
BDB_LOG_PRINTF( bdb->bi_dbenv, lt2, "slapd Commit1 delete %s(%d)",
e->e_nname.bv_val, e->e_id );
if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
rs->sr_err = LDAP_OTHER;
rs->sr_text = "txn_commit(2) failed";
goto return_results;
}
eid = e->e_id;
#if 0 /* Do we want to reclaim deleted IDs? */
ldap_pvt_thread_mutex_lock( &bdb->bi_lastid_mutex );
if ( e->e_id == bdb->bi_lastid ) {
bdb_last_id( op->o_bd, ltid );
}
ldap_pvt_thread_mutex_unlock( &bdb->bi_lastid_mutex );
#endif
if( op->o_noop ) {
if ( ( rs->sr_err = TXN_ABORT( ltid ) ) != 0 ) {
rs->sr_text = "txn_abort (no-op) failed";
} else {
rs->sr_err = LDAP_X_NO_OPERATION;
ltid = NULL;
goto return_results;
}
} else {
BDB_LOG_PRINTF( bdb->bi_dbenv, ltid, "slapd Cache delete %s(%d)",
e->e_nname.bv_val, e->e_id );
rc = bdb_cache_delete( bdb, e, ltid, &lock );
switch( rc ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
rs->sr_err = TXN_COMMIT( ltid, 0 );
}
ltid = NULL;
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
opinfo.boi_oe.oe_key = NULL;
BDB_LOG_PRINTF( bdb->bi_dbenv, NULL, "slapd Committed delete %s(%d)",
e->e_nname.bv_val, e->e_id );
if( rs->sr_err != 0 ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_delete) ": txn_%s failed: %s (%d)\n",
op->o_noop ? "abort (no-op)" : "commit",
db_strerror(rs->sr_err), rs->sr_err );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "commit failed";
goto return_results;
}
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_delete) ": deleted%s id=%08lx dn=\"%s\"\n",
op->o_noop ? " (no-op)" : "",
eid, op->o_req_dn.bv_val );
rs->sr_err = LDAP_SUCCESS;
rs->sr_text = NULL;
if( num_ctrls ) rs->sr_ctrls = ctrls;
return_results:
if ( rs->sr_err == LDAP_SUCCESS && parent_is_glue && parent_is_leaf ) {
op->o_delete_glue_parent = 1;
}
if ( p )
bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
/* free entry */
if( e != NULL ) {
if ( rs->sr_err == LDAP_SUCCESS ) {
/* Free the EntryInfo and the Entry */
bdb_cache_entryinfo_lock( BEI(e) );
bdb_cache_delete_cleanup( &bdb->bi_cache, BEI(e) );
} else {
bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
}
}
if( ltid != NULL ) {
TXN_ABORT( ltid );
}
if ( opinfo.boi_oe.oe_key ) {
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
}
send_ldap_result( op, rs );
slap_graduate_commit_csn( op );
if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) {
slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
slap_sl_free( *preread_ctrl, op->o_tmpmemctx );
}
if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp_kbyte ) {
TXN_CHECKPOINT( bdb->bi_dbenv,
bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
}
return rs->sr_err;
}

View File

@ -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-2019 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include "back-bdb.h"
/*
* dn2entry - look up dn in the cache/indexes and return the corresponding
* entry. If the requested DN is not found and matched is TRUE, return info
* for the closest ancestor of the DN. Otherwise e is NULL.
*/
int
bdb_dn2entry(
Operation *op,
DB_TXN *tid,
struct berval *dn,
EntryInfo **e,
int matched,
DB_LOCK *lock )
{
EntryInfo *ei = NULL;
int rc, rc2;
Debug(LDAP_DEBUG_TRACE, "bdb_dn2entry(\"%s\")\n",
dn->bv_val );
*e = NULL;
rc = bdb_cache_find_ndn( op, tid, dn, &ei );
if ( rc ) {
if ( matched && rc == DB_NOTFOUND ) {
/* Set the return value, whether we have its entry
* or not.
*/
*e = ei;
if ( ei && ei->bei_id ) {
rc2 = bdb_cache_find_id( op, tid, ei->bei_id,
&ei, ID_LOCKED, lock );
if ( rc2 ) rc = rc2;
} else if ( ei ) {
bdb_cache_entryinfo_unlock( ei );
memset( lock, 0, sizeof( *lock ));
lock->mode = DB_LOCK_NG;
}
} else if ( ei ) {
bdb_cache_entryinfo_unlock( ei );
}
} else {
rc = bdb_cache_find_id( op, tid, ei->bei_id, &ei, ID_LOCKED,
lock );
if ( rc == 0 ) {
*e = ei;
} else if ( matched && rc == DB_NOTFOUND ) {
/* always return EntryInfo */
if ( ei->bei_parent ) {
ei = ei->bei_parent;
rc2 = bdb_cache_find_id( op, tid, ei->bei_id, &ei, 0,
lock );
if ( rc2 ) rc = rc2;
}
*e = ei;
}
}
return rc;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,62 +0,0 @@
/* error.c - BDB errcall routine */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2000-2019 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include "slap.h"
#include "back-bdb.h"
#if DB_VERSION_FULL < 0x04030000
void bdb_errcall( const char *pfx, char * msg )
#else
void bdb_errcall( const DB_ENV *env, const char *pfx, const char * msg )
#endif
{
#ifdef HAVE_EBCDIC
if ( msg[0] > 0x7f )
__etoa( msg );
#endif
Debug( LDAP_DEBUG_ANY, "bdb(%s): %s\n", pfx, msg );
}
#if DB_VERSION_FULL >= 0x04030000
void bdb_msgcall( const DB_ENV *env, const char *msg )
{
#ifdef HAVE_EBCDIC
if ( msg[0] > 0x7f )
__etoa( msg );
#endif
Debug( LDAP_DEBUG_TRACE, "bdb: %s\n", msg );
}
#endif
#ifdef HAVE_EBCDIC
#undef db_strerror
/* Not re-entrant! */
char *ebcdic_dberror( int rc )
{
static char msg[1024];
strcpy( msg, db_strerror( rc ) );
__etoa( msg );
return msg;
}
#endif

View File

@ -1,54 +0,0 @@
/* extended.c - bdb backend extended routines */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2000-2019 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include "back-bdb.h"
#include "lber_pvt.h"
static struct exop {
struct berval *oid;
BI_op_extended *extended;
} exop_table[] = {
{ NULL, NULL }
};
int
bdb_extended( Operation *op, SlapReply *rs )
/* struct berval *reqoid,
struct berval *reqdata,
char **rspoid,
struct berval **rspdata,
LDAPControl *** rspctrls,
const char** text,
BerVarray *refs
) */
{
int i;
for( i=0; exop_table[i].extended != NULL; i++ ) {
if( ber_bvcmp( exop_table[i].oid, &op->oq_extended.rs_reqoid ) == 0 ) {
return (exop_table[i].extended)( op, rs );
}
}
rs->sr_text = "not supported within naming context";
return rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
}

File diff suppressed because it is too large Load Diff

View File

@ -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-2019 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include <ac/errno.h>
#include "back-bdb.h"
static int bdb_id2entry_put(
BackendDB *be,
DB_TXN *tid,
Entry *e,
int flag )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
DB *db = bdb->bi_id2entry->bdi_db;
DBT key, data;
struct berval bv;
int rc;
ID nid;
#ifdef BDB_HIER
struct berval odn, ondn;
/* We only store rdns, and they go in the dn2id database. */
odn = e->e_name; ondn = e->e_nname;
e->e_name = slap_empty_bv;
e->e_nname = slap_empty_bv;
#endif
DBTzero( &key );
/* Store ID in BigEndian format */
key.data = &nid;
key.size = sizeof(ID);
BDB_ID2DISK( e->e_id, &nid );
rc = entry_encode( e, &bv );
#ifdef BDB_HIER
e->e_name = odn; e->e_nname = ondn;
#endif
if( rc != LDAP_SUCCESS ) {
return -1;
}
DBTzero( &data );
bv2DBT( &bv, &data );
rc = db->put( db, tid, &key, &data, flag );
free( bv.bv_val );
return rc;
}
/*
* This routine adds (or updates) an entry on disk.
* The cache should be already be updated.
*/
int bdb_id2entry_add(
BackendDB *be,
DB_TXN *tid,
Entry *e )
{
return bdb_id2entry_put(be, tid, e, DB_NOOVERWRITE);
}
int bdb_id2entry_update(
BackendDB *be,
DB_TXN *tid,
Entry *e )
{
return bdb_id2entry_put(be, tid, e, 0);
}
int bdb_id2entry(
BackendDB *be,
DB_TXN *tid,
ID id,
Entry **e )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
DB *db = bdb->bi_id2entry->bdi_db;
DBT key, data;
DBC *cursor;
EntryHeader eh;
char buf[16];
int rc = 0, off;
ID nid;
*e = NULL;
DBTzero( &key );
key.data = &nid;
key.size = sizeof(ID);
BDB_ID2DISK( id, &nid );
DBTzero( &data );
data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
/* fetch it */
rc = db->cursor( db, tid, &cursor, bdb->bi_db_opflags );
if ( rc ) return rc;
/* Get the nattrs / nvals counts first */
data.ulen = data.dlen = sizeof(buf);
data.data = buf;
rc = cursor->c_get( cursor, &key, &data, DB_SET );
if ( rc ) goto finish;
eh.bv.bv_val = buf;
eh.bv.bv_len = data.size;
rc = entry_header( &eh );
if ( rc ) goto finish;
if ( eh.nvals ) {
/* Get the size */
data.flags ^= DB_DBT_PARTIAL;
data.ulen = 0;
rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
if ( rc != DB_BUFFER_SMALL ) goto finish;
/* Allocate a block and retrieve the data */
off = eh.data - eh.bv.bv_val;
eh.bv.bv_len = eh.nvals * sizeof( struct berval ) + data.size;
eh.bv.bv_val = ch_malloc( eh.bv.bv_len );
eh.data = eh.bv.bv_val + eh.nvals * sizeof( struct berval );
data.data = eh.data;
data.ulen = data.size;
/* skip past already parsed nattr/nvals */
eh.data += off;
rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
}
finish:
cursor->c_close( cursor );
if( rc != 0 ) {
return rc;
}
if ( eh.nvals ) {
#ifdef SLAP_ZONE_ALLOC
rc = entry_decode(&eh, e, bdb->bi_cache.c_zctx);
#else
rc = entry_decode(&eh, e);
#endif
} else {
*e = entry_alloc();
}
if( rc == 0 ) {
(*e)->e_id = id;
} else {
/* only free on error. On success, the entry was
* decoded in place.
*/
#ifndef SLAP_ZONE_ALLOC
ch_free(eh.bv.bv_val);
#endif
}
#ifdef SLAP_ZONE_ALLOC
ch_free(eh.bv.bv_val);
#endif
return rc;
}
int bdb_id2entry_delete(
BackendDB *be,
DB_TXN *tid,
Entry *e )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
DB *db = bdb->bi_id2entry->bdi_db;
DBT key;
int rc;
ID nid;
DBTzero( &key );
key.data = &nid;
key.size = sizeof(ID);
BDB_ID2DISK( e->e_id, &nid );
/* delete from database */
rc = db->del( db, tid, &key, 0 );
return rc;
}
int bdb_entry_return(
Entry *e
)
{
/* Our entries are allocated in two blocks; the data comes from
* the db itself and the Entry structure and associated pointers
* are allocated in entry_decode. The db data pointer is saved
* in e_bv.
*/
if ( e->e_bv.bv_val ) {
/* See if the DNs were changed by modrdn */
if( e->e_nname.bv_val < e->e_bv.bv_val || e->e_nname.bv_val >
e->e_bv.bv_val + e->e_bv.bv_len ) {
ch_free(e->e_name.bv_val);
ch_free(e->e_nname.bv_val);
}
e->e_name.bv_val = NULL;
e->e_nname.bv_val = NULL;
/* In tool mode the e_bv buffer is realloc'd, leave it alone */
if( !(slapMode & SLAP_TOOL_MODE) ) {
free( e->e_bv.bv_val );
}
BER_BVZERO( &e->e_bv );
}
entry_free( e );
return 0;
}
int bdb_entry_release(
Operation *op,
Entry *e,
int rw )
{
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
struct bdb_op_info *boi;
OpExtra *oex;
/* slapMode : SLAP_SERVER_MODE, SLAP_TOOL_MODE,
SLAP_TRUNCATE_MODE, SLAP_UNDEFINED_MODE */
if ( slapMode & SLAP_SERVER_MODE ) {
/* If not in our cache, just free it */
if ( !e->e_private ) {
#ifdef SLAP_ZONE_ALLOC
return bdb_entry_return( bdb, e, -1 );
#else
return bdb_entry_return( e );
#endif
}
/* free entry and reader or writer lock */
LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
if ( oex->oe_key == bdb ) break;
}
boi = (struct bdb_op_info *)oex;
/* lock is freed with txn */
if ( !boi || boi->boi_txn ) {
bdb_unlocked_cache_return_entry_rw( bdb, e, rw );
} else {
struct bdb_lock_info *bli, *prev;
for ( prev=(struct bdb_lock_info *)&boi->boi_locks,
bli = boi->boi_locks; bli; prev=bli, bli=bli->bli_next ) {
if ( bli->bli_id == e->e_id ) {
bdb_cache_return_entry_rw( bdb, e, rw, &bli->bli_lock );
prev->bli_next = bli->bli_next;
/* Cleanup, or let caller know we unlocked */
if ( bli->bli_flag & BLI_DONTFREE )
bli->bli_flag = 0;
else
op->o_tmpfree( bli, op->o_tmpmemctx );
break;
}
}
if ( !boi->boi_locks ) {
LDAP_SLIST_REMOVE( &op->o_extra, &boi->boi_oe, OpExtra, oe_next );
if ( !(boi->boi_flag & BOI_DONTFREE))
op->o_tmpfree( boi, op->o_tmpmemctx );
}
}
} else {
#ifdef SLAP_ZONE_ALLOC
int zseq = -1;
if (e->e_private != NULL) {
BEI(e)->bei_e = NULL;
zseq = BEI(e)->bei_zseq;
}
#else
if (e->e_private != NULL)
BEI(e)->bei_e = NULL;
#endif
e->e_private = NULL;
#ifdef SLAP_ZONE_ALLOC
bdb_entry_return ( bdb, e, zseq );
#else
bdb_entry_return ( e );
#endif
}
return 0;
}
/* return LDAP_SUCCESS IFF we can retrieve the specified entry.
*/
int bdb_entry_get(
Operation *op,
struct berval *ndn,
ObjectClass *oc,
AttributeDescription *at,
int rw,
Entry **ent )
{
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
struct bdb_op_info *boi = NULL;
DB_TXN *txn = NULL;
Entry *e = NULL;
EntryInfo *ei;
int rc;
const char *at_name = at ? at->ad_cname.bv_val : "(null)";
DB_LOCK lock;
Debug( LDAP_DEBUG_ARGS,
"=> bdb_entry_get: ndn: \"%s\"\n", ndn->bv_val );
Debug( LDAP_DEBUG_ARGS,
"=> bdb_entry_get: oc: \"%s\", at: \"%s\"\n",
oc ? oc->soc_cname.bv_val : "(null)", at_name );
if( op ) {
OpExtra *oex;
LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
if ( oex->oe_key == bdb ) break;
}
boi = (struct bdb_op_info *)oex;
if ( boi )
txn = boi->boi_txn;
}
if ( !txn ) {
rc = bdb_reader_get( op, bdb->bi_dbenv, &txn );
switch(rc) {
case 0:
break;
default:
return LDAP_OTHER;
}
}
dn2entry_retry:
/* can we find entry */
rc = bdb_dn2entry( op, txn, ndn, &ei, 0, &lock );
switch( rc ) {
case DB_NOTFOUND:
case 0:
break;
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
/* the txn must abort and retry */
if ( txn ) {
if ( boi ) boi->boi_err = rc;
return LDAP_BUSY;
}
ldap_pvt_thread_yield();
goto dn2entry_retry;
default:
if ( boi ) boi->boi_err = rc;
return (rc != LDAP_BUSY) ? LDAP_OTHER : LDAP_BUSY;
}
if (ei) e = ei->bei_e;
if (e == NULL) {
Debug( LDAP_DEBUG_ACL,
"=> bdb_entry_get: cannot find entry: \"%s\"\n",
ndn->bv_val );
return LDAP_NO_SUCH_OBJECT;
}
Debug( LDAP_DEBUG_ACL,
"=> bdb_entry_get: found entry: \"%s\"\n",
ndn->bv_val );
if ( oc && !is_entry_objectclass( e, oc, 0 )) {
Debug( LDAP_DEBUG_ACL,
"<= bdb_entry_get: failed to find objectClass %s\n",
oc->soc_cname.bv_val );
rc = LDAP_NO_SUCH_ATTRIBUTE;
goto return_results;
}
/* NOTE: attr_find() or attrs_find()? */
if ( at && attr_find( e->e_attrs, at ) == NULL ) {
Debug( LDAP_DEBUG_ACL,
"<= bdb_entry_get: failed to find attribute %s\n",
at->ad_cname.bv_val );
rc = LDAP_NO_SUCH_ATTRIBUTE;
goto return_results;
}
return_results:
if( rc != LDAP_SUCCESS ) {
/* free entry */
bdb_cache_return_entry_rw(bdb, e, rw, &lock);
} else {
if ( slapMode & SLAP_SERVER_MODE ) {
*ent = e;
/* big drag. we need a place to store a read lock so we can
* release it later?? If we're in a txn, nothing is needed
* here because the locks will go away with the txn.
*/
if ( op ) {
if ( !boi ) {
boi = op->o_tmpcalloc(1,sizeof(struct bdb_op_info),op->o_tmpmemctx);
boi->boi_oe.oe_key = bdb;
LDAP_SLIST_INSERT_HEAD( &op->o_extra, &boi->boi_oe, oe_next );
}
if ( !boi->boi_txn ) {
struct bdb_lock_info *bli;
bli = op->o_tmpalloc( sizeof(struct bdb_lock_info),
op->o_tmpmemctx );
bli->bli_next = boi->boi_locks;
bli->bli_id = e->e_id;
bli->bli_flag = 0;
bli->bli_lock = lock;
boi->boi_locks = bli;
}
}
} else {
*ent = entry_dup( e );
bdb_cache_return_entry_rw(bdb, e, rw, &lock);
}
}
Debug( LDAP_DEBUG_TRACE,
"bdb_entry_get: rc=%d\n",
rc );
return(rc);
}

File diff suppressed because it is too large Load Diff

View File

@ -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-2019 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
#ifndef _BDB_IDL_H_
#define _BDB_IDL_H_
/* IDL sizes - likely should be even bigger
* limiting factors: sizeof(ID), thread stack size
*/
#define BDB_IDL_LOGN 16 /* DB_SIZE is 2^16, UM_SIZE is 2^17 */
#define BDB_IDL_DB_SIZE (1<<BDB_IDL_LOGN)
#define BDB_IDL_UM_SIZE (1<<(BDB_IDL_LOGN+1))
#define BDB_IDL_UM_SIZEOF (BDB_IDL_UM_SIZE * sizeof(ID))
#define BDB_IDL_DB_MAX (BDB_IDL_DB_SIZE-1)
#define BDB_IDL_UM_MAX (BDB_IDL_UM_SIZE-1)
#define BDB_IDL_IS_RANGE(ids) ((ids)[0] == NOID)
#define BDB_IDL_RANGE_SIZE (3)
#define BDB_IDL_RANGE_SIZEOF (BDB_IDL_RANGE_SIZE * sizeof(ID))
#define BDB_IDL_SIZEOF(ids) ((BDB_IDL_IS_RANGE(ids) \
? BDB_IDL_RANGE_SIZE : ((ids)[0]+1)) * sizeof(ID))
#define BDB_IDL_RANGE_FIRST(ids) ((ids)[1])
#define BDB_IDL_RANGE_LAST(ids) ((ids)[2])
#define BDB_IDL_RANGE( ids, f, l ) \
do { \
(ids)[0] = NOID; \
(ids)[1] = (f); \
(ids)[2] = (l); \
} while(0)
#define BDB_IDL_ZERO(ids) \
do { \
(ids)[0] = 0; \
(ids)[1] = 0; \
(ids)[2] = 0; \
} while(0)
#define BDB_IDL_IS_ZERO(ids) ( (ids)[0] == 0 )
#define BDB_IDL_IS_ALL( range, ids ) ( (ids)[0] == NOID \
&& (ids)[1] <= (range)[1] && (range)[2] <= (ids)[2] )
#define BDB_IDL_CPY( dst, src ) (AC_MEMCPY( dst, src, BDB_IDL_SIZEOF( src ) ))
#define BDB_IDL_ID( bdb, ids, id ) BDB_IDL_RANGE( ids, id, ((bdb)->bi_lastid) )
#define BDB_IDL_ALL( bdb, ids ) BDB_IDL_RANGE( ids, 1, ((bdb)->bi_lastid) )
#define BDB_IDL_FIRST( ids ) ( (ids)[1] )
#define BDB_IDL_LLAST( ids ) ( (ids)[(ids)[0]] )
#define BDB_IDL_LAST( ids ) ( BDB_IDL_IS_RANGE(ids) \
? (ids)[2] : (ids)[(ids)[0]] )
#define BDB_IDL_N( ids ) ( BDB_IDL_IS_RANGE(ids) \
? ((ids)[2]-(ids)[1])+1 : (ids)[0] )
LDAP_BEGIN_DECL
LDAP_END_DECL
#endif

View File

@ -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-2019 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include <ac/socket.h>
#include "slap.h"
#include "back-bdb.h"
#include "lutil_hash.h"
static char presence_keyval[] = {0,0};
static struct berval presence_key = BER_BVC(presence_keyval);
AttrInfo *bdb_index_mask(
Backend *be,
AttributeDescription *desc,
struct berval *atname )
{
AttributeType *at;
AttrInfo *ai = bdb_attr_mask( be->be_private, desc );
if( ai ) {
*atname = desc->ad_cname;
return ai;
}
/* If there is a tagging option, did we ever index the base
* type? If so, check for mask, otherwise it's not there.
*/
if( slap_ad_is_tagged( desc ) && desc != desc->ad_type->sat_ad ) {
/* has tagging option */
ai = bdb_attr_mask( be->be_private, desc->ad_type->sat_ad );
if ( ai && !( ai->ai_indexmask & SLAP_INDEX_NOTAGS ) ) {
*atname = desc->ad_type->sat_cname;
return ai;
}
}
/* see if supertype defined mask for its subtypes */
for( at = desc->ad_type; at != NULL ; at = at->sat_sup ) {
/* If no AD, we've never indexed this type */
if ( !at->sat_ad ) continue;
ai = bdb_attr_mask( be->be_private, at->sat_ad );
if ( ai && !( ai->ai_indexmask & SLAP_INDEX_NOSUBTYPES ) ) {
*atname = at->sat_cname;
return ai;
}
}
return 0;
}
/* This function is only called when evaluating search filters.
*/
int bdb_index_param(
Backend *be,
AttributeDescription *desc,
int ftype,
DB **dbp,
slap_mask_t *maskp,
struct berval *prefixp )
{
AttrInfo *ai;
int rc;
slap_mask_t mask, type = 0;
DB *db;
ai = bdb_index_mask( be, desc, prefixp );
if ( !ai ) {
#ifdef BDB_MONITOR_IDX
switch ( ftype ) {
case LDAP_FILTER_PRESENT:
type = SLAP_INDEX_PRESENT;
break;
case LDAP_FILTER_APPROX:
type = SLAP_INDEX_APPROX;
break;
case LDAP_FILTER_EQUALITY:
type = SLAP_INDEX_EQUALITY;
break;
case LDAP_FILTER_SUBSTRINGS:
type = SLAP_INDEX_SUBSTR;
break;
default:
return LDAP_INAPPROPRIATE_MATCHING;
}
bdb_monitor_idx_add( be->be_private, desc, type );
#endif /* BDB_MONITOR_IDX */
return LDAP_INAPPROPRIATE_MATCHING;
}
mask = ai->ai_indexmask;
rc = bdb_db_cache( be, prefixp, &db );
if( rc != LDAP_SUCCESS ) {
return rc;
}
switch( ftype ) {
case LDAP_FILTER_PRESENT:
type = SLAP_INDEX_PRESENT;
if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
*prefixp = presence_key;
goto done;
}
break;
case LDAP_FILTER_APPROX:
type = SLAP_INDEX_APPROX;
if ( desc->ad_type->sat_approx ) {
if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
goto done;
}
break;
}
/* Use EQUALITY rule and index for approximate match */
/* fall thru */
case LDAP_FILTER_EQUALITY:
type = SLAP_INDEX_EQUALITY;
if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
goto done;
}
break;
case LDAP_FILTER_SUBSTRINGS:
type = SLAP_INDEX_SUBSTR;
if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
goto done;
}
break;
default:
return LDAP_OTHER;
}
#ifdef BDB_MONITOR_IDX
bdb_monitor_idx_add( be->be_private, desc, type );
#endif /* BDB_MONITOR_IDX */
return LDAP_INAPPROPRIATE_MATCHING;
done:
*dbp = db;
*maskp = mask;
return LDAP_SUCCESS;
}
static int indexer(
Operation *op,
DB_TXN *txn,
AttributeDescription *ad,
struct berval *atname,
BerVarray vals,
ID id,
int opid,
slap_mask_t mask )
{
int rc, i;
DB *db;
struct berval *keys;
assert( mask != 0 );
rc = bdb_db_cache( op->o_bd, atname, &db );
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY,
"bdb_index_read: Could not open DB %s\n",
atname->bv_val );
return LDAP_OTHER;
}
if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
rc = bdb_key_change( op->o_bd, db, txn, &presence_key, id, opid );
if( rc ) {
goto done;
}
}
if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
rc = ad->ad_type->sat_equality->smr_indexer(
LDAP_FILTER_EQUALITY,
mask,
ad->ad_type->sat_syntax,
ad->ad_type->sat_equality,
atname, vals, &keys, op->o_tmpmemctx );
if( rc == LDAP_SUCCESS && keys != NULL ) {
for( i=0; keys[i].bv_val != NULL; i++ ) {
rc = bdb_key_change( op->o_bd, db, txn, &keys[i], id, opid );
if( rc ) {
ber_bvarray_free_x( keys, op->o_tmpmemctx );
goto done;
}
}
ber_bvarray_free_x( keys, op->o_tmpmemctx );
}
rc = LDAP_SUCCESS;
}
if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
rc = ad->ad_type->sat_approx->smr_indexer(
LDAP_FILTER_APPROX,
mask,
ad->ad_type->sat_syntax,
ad->ad_type->sat_approx,
atname, vals, &keys, op->o_tmpmemctx );
if( rc == LDAP_SUCCESS && keys != NULL ) {
for( i=0; keys[i].bv_val != NULL; i++ ) {
rc = bdb_key_change( op->o_bd, db, txn, &keys[i], id, opid );
if( rc ) {
ber_bvarray_free_x( keys, op->o_tmpmemctx );
goto done;
}
}
ber_bvarray_free_x( keys, op->o_tmpmemctx );
}
rc = LDAP_SUCCESS;
}
if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
rc = ad->ad_type->sat_substr->smr_indexer(
LDAP_FILTER_SUBSTRINGS,
mask,
ad->ad_type->sat_syntax,
ad->ad_type->sat_substr,
atname, vals, &keys, op->o_tmpmemctx );
if( rc == LDAP_SUCCESS && keys != NULL ) {
for( i=0; keys[i].bv_val != NULL; i++ ) {
rc = bdb_key_change( op->o_bd, db, txn, &keys[i], id, opid );
if( rc ) {
ber_bvarray_free_x( keys, op->o_tmpmemctx );
goto done;
}
}
ber_bvarray_free_x( keys, op->o_tmpmemctx );
}
rc = LDAP_SUCCESS;
}
done:
switch( rc ) {
/* The callers all know how to deal with these results */
case 0:
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
break;
/* Anything else is bad news */
default:
rc = LDAP_OTHER;
}
return rc;
}
static int index_at_values(
Operation *op,
DB_TXN *txn,
AttributeDescription *ad,
AttributeType *type,
struct berval *tags,
BerVarray vals,
ID id,
int opid )
{
int rc;
slap_mask_t mask = 0;
int ixop = opid;
AttrInfo *ai = NULL;
if ( opid == BDB_INDEX_UPDATE_OP )
ixop = SLAP_INDEX_ADD_OP;
if( type->sat_sup ) {
/* recurse */
rc = index_at_values( op, txn, NULL,
type->sat_sup, tags,
vals, id, opid );
if( rc ) return rc;
}
/* If this type has no AD, we've never used it before */
if( type->sat_ad ) {
ai = bdb_attr_mask( op->o_bd->be_private, type->sat_ad );
if ( ai ) {
#ifdef LDAP_COMP_MATCH
/* component indexing */
if ( ai->ai_cr ) {
ComponentReference *cr;
for( cr = ai->ai_cr ; cr ; cr = cr->cr_next ) {
rc = indexer( op, txn, cr->cr_ad, &type->sat_cname,
cr->cr_nvals, id, ixop,
cr->cr_indexmask );
}
}
#endif
ad = type->sat_ad;
/* If we're updating the index, just set the new bits that aren't
* already in the old mask.
*/
if ( opid == BDB_INDEX_UPDATE_OP )
mask = ai->ai_newmask & ~ai->ai_indexmask;
else
/* For regular updates, if there is a newmask use it. Otherwise
* just use the old mask.
*/
mask = ai->ai_newmask ? ai->ai_newmask : ai->ai_indexmask;
if( mask ) {
rc = indexer( op, txn, ad, &type->sat_cname,
vals, id, ixop, mask );
if( rc ) return rc;
}
}
}
if( tags->bv_len ) {
AttributeDescription *desc;
desc = ad_find_tags( type, tags );
if( desc ) {
ai = bdb_attr_mask( op->o_bd->be_private, desc );
if( ai ) {
if ( opid == BDB_INDEX_UPDATE_OP )
mask = ai->ai_newmask & ~ai->ai_indexmask;
else
mask = ai->ai_newmask ? ai->ai_newmask : ai->ai_indexmask;
if ( mask ) {
rc = indexer( op, txn, desc, &desc->ad_cname,
vals, id, ixop, mask );
if( rc ) {
return rc;
}
}
}
}
}
return LDAP_SUCCESS;
}
int bdb_index_values(
Operation *op,
DB_TXN *txn,
AttributeDescription *desc,
BerVarray vals,
ID id,
int opid )
{
int rc;
/* Never index ID 0 */
if ( id == 0 )
return 0;
rc = index_at_values( op, txn, desc,
desc->ad_type, &desc->ad_tags,
vals, id, opid );
return rc;
}
/* Get the list of which indices apply to this attr */
int
bdb_index_recset(
struct bdb_info *bdb,
Attribute *a,
AttributeType *type,
struct berval *tags,
IndexRec *ir )
{
int rc, slot;
AttrList *al;
if( type->sat_sup ) {
/* recurse */
rc = bdb_index_recset( bdb, a, type->sat_sup, tags, ir );
if( rc ) return rc;
}
/* If this type has no AD, we've never used it before */
if( type->sat_ad ) {
slot = bdb_attr_slot( bdb, type->sat_ad, NULL );
if ( slot >= 0 ) {
ir[slot].ai = bdb->bi_attrs[slot];
al = ch_malloc( sizeof( AttrList ));
al->attr = a;
al->next = ir[slot].attrs;
ir[slot].attrs = al;
}
}
if( tags->bv_len ) {
AttributeDescription *desc;
desc = ad_find_tags( type, tags );
if( desc ) {
slot = bdb_attr_slot( bdb, desc, NULL );
if ( slot >= 0 ) {
ir[slot].ai = bdb->bi_attrs[slot];
al = ch_malloc( sizeof( AttrList ));
al->attr = a;
al->next = ir[slot].attrs;
ir[slot].attrs = al;
}
}
}
return LDAP_SUCCESS;
}
/* Apply the indices for the recset */
int bdb_index_recrun(
Operation *op,
struct bdb_info *bdb,
IndexRec *ir0,
ID id,
int base )
{
IndexRec *ir;
AttrList *al;
int i, rc = 0;
/* Never index ID 0 */
if ( id == 0 )
return 0;
for (i=base; i<bdb->bi_nattrs; i+=slap_tool_thread_max-1) {
ir = ir0 + i;
if ( !ir->ai ) continue;
while (( al = ir->attrs )) {
ir->attrs = al->next;
rc = indexer( op, NULL, ir->ai->ai_desc,
&ir->ai->ai_desc->ad_type->sat_cname,
al->attr->a_nvals, id, SLAP_INDEX_ADD_OP,
ir->ai->ai_indexmask );
free( al );
if ( rc ) break;
}
}
return rc;
}
int
bdb_index_entry(
Operation *op,
DB_TXN *txn,
int opid,
Entry *e )
{
int rc;
Attribute *ap = e->e_attrs;
#if 0 /* ifdef LDAP_COMP_MATCH */
ComponentReference *cr_list = NULL;
ComponentReference *cr = NULL, *dupped_cr = NULL;
void* decoded_comp;
ComponentSyntaxInfo* csi_attr;
Syntax* syn;
AttributeType* at;
int i, num_attr;
void* mem_op;
struct berval value = {0};
#endif
/* Never index ID 0 */
if ( e->e_id == 0 )
return 0;
Debug( LDAP_DEBUG_TRACE, "=> index_entry_%s( %ld, \"%s\" )\n",
opid == SLAP_INDEX_DELETE_OP ? "del" : "add",
(long) e->e_id, e->e_dn );
/* add each attribute to the indexes */
for ( ; ap != NULL; ap = ap->a_next ) {
#if 0 /* ifdef LDAP_COMP_MATCH */
AttrInfo *ai;
/* see if attribute has components to be indexed */
ai = bdb_attr_mask( op->o_bd->be_private, ap->a_desc->ad_type->sat_ad );
if ( !ai ) continue;
cr_list = ai->ai_cr;
if ( attr_converter && cr_list ) {
syn = ap->a_desc->ad_type->sat_syntax;
ap->a_comp_data = op->o_tmpalloc( sizeof( ComponentData ), op->o_tmpmemctx );
/* Memory chunk(nibble) pre-allocation for decoders */
mem_op = nibble_mem_allocator ( 1024*16, 1024*4 );
ap->a_comp_data->cd_mem_op = mem_op;
for( cr = cr_list ; cr ; cr = cr->cr_next ) {
/* count how many values in an attribute */
for( num_attr=0; ap->a_vals[num_attr].bv_val != NULL; num_attr++ );
num_attr++;
cr->cr_nvals = (BerVarray)op->o_tmpalloc( sizeof( struct berval )*num_attr, op->o_tmpmemctx );
for( i=0; ap->a_vals[i].bv_val != NULL; i++ ) {
/* decoding attribute value */
decoded_comp = attr_converter ( ap, syn, &ap->a_vals[i] );
if ( !decoded_comp )
return LDAP_DECODING_ERROR;
/* extracting the referenced component */
dupped_cr = dup_comp_ref( op, cr );
csi_attr = ((ComponentSyntaxInfo*)decoded_comp)->csi_comp_desc->cd_extract_i( mem_op, dupped_cr, decoded_comp );
if ( !csi_attr )
return LDAP_DECODING_ERROR;
cr->cr_asn_type_id = csi_attr->csi_comp_desc->cd_type_id;
cr->cr_ad = (AttributeDescription*)get_component_description ( cr->cr_asn_type_id );
if ( !cr->cr_ad )
return LDAP_INVALID_SYNTAX;
at = cr->cr_ad->ad_type;
/* encoding the value of component in GSER */
rc = component_encoder( mem_op, csi_attr, &value );
if ( rc != LDAP_SUCCESS )
return LDAP_ENCODING_ERROR;
/* Normalize the encoded component values */
if ( at->sat_equality && at->sat_equality->smr_normalize ) {
rc = at->sat_equality->smr_normalize (
SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
at->sat_syntax, at->sat_equality,
&value, &cr->cr_nvals[i], op->o_tmpmemctx );
} else {
cr->cr_nvals[i] = value;
}
}
/* The end of BerVarray */
cr->cr_nvals[num_attr-1].bv_val = NULL;
cr->cr_nvals[num_attr-1].bv_len = 0;
}
op->o_tmpfree( ap->a_comp_data, op->o_tmpmemctx );
nibble_mem_free ( mem_op );
ap->a_comp_data = NULL;
}
#endif
rc = bdb_index_values( op, txn, ap->a_desc,
ap->a_nvals, e->e_id, opid );
if( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
"<= index_entry_%s( %ld, \"%s\" ) failure\n",
opid == SLAP_INDEX_ADD_OP ? "add" : "del",
(long) e->e_id, e->e_dn );
return rc;
}
}
Debug( LDAP_DEBUG_TRACE, "<= index_entry_%s( %ld, \"%s\" ) success\n",
opid == SLAP_INDEX_DELETE_OP ? "del" : "add",
(long) e->e_id, e->e_dn );
return LDAP_SUCCESS;
}

View File

@ -1,871 +0,0 @@
/* init.c - initialize bdb backend */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2000-2019 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include <ac/unistd.h>
#include <ac/stdlib.h>
#include <ac/errno.h>
#include <sys/stat.h>
#include "back-bdb.h"
#include <lutil.h>
#include <ldap_rq.h>
#include "alock.h"
#include "config.h"
static const struct bdbi_database {
char *file;
struct berval name;
int type;
int flags;
} bdbi_databases[] = {
{ "id2entry" BDB_SUFFIX, BER_BVC("id2entry"), DB_BTREE, 0 },
{ "dn2id" BDB_SUFFIX, BER_BVC("dn2id"), DB_BTREE, 0 },
{ NULL, BER_BVNULL, 0, 0 }
};
typedef void * db_malloc(size_t);
typedef void * db_realloc(void *, size_t);
#define bdb_db_init BDB_SYMBOL(db_init)
#define bdb_db_open BDB_SYMBOL(db_open)
#define bdb_db_close BDB_SYMBOL(db_close)
static int
bdb_db_init( BackendDB *be, ConfigReply *cr )
{
struct bdb_info *bdb;
int rc;
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_db_init) ": Initializing " BDB_UCTYPE " database\n" );
/* allocate backend-database-specific stuff */
bdb = (struct bdb_info *) ch_calloc( 1, sizeof(struct bdb_info) );
/* DBEnv parameters */
bdb->bi_dbenv_home = ch_strdup( SLAPD_DEFAULT_DB_DIR );
bdb->bi_dbenv_xflags = DB_TIME_NOTGRANTED;
bdb->bi_dbenv_mode = SLAPD_DEFAULT_DB_MODE;
bdb->bi_cache.c_maxsize = DEFAULT_CACHE_SIZE;
bdb->bi_cache.c_minfree = 1;
bdb->bi_lock_detect = DB_LOCK_DEFAULT;
bdb->bi_search_stack_depth = DEFAULT_SEARCH_STACK_DEPTH;
bdb->bi_search_stack = NULL;
ldap_pvt_thread_mutex_init( &bdb->bi_database_mutex );
ldap_pvt_thread_mutex_init( &bdb->bi_lastid_mutex );
#ifdef BDB_HIER
ldap_pvt_thread_mutex_init( &bdb->bi_modrdns_mutex );
#endif
ldap_pvt_thread_mutex_init( &bdb->bi_cache.c_lru_mutex );
ldap_pvt_thread_mutex_init( &bdb->bi_cache.c_count_mutex );
ldap_pvt_thread_mutex_init( &bdb->bi_cache.c_eifree_mutex );
ldap_pvt_thread_mutex_init( &bdb->bi_cache.c_dntree.bei_kids_mutex );
ldap_pvt_thread_rdwr_init ( &bdb->bi_cache.c_rwlock );
ldap_pvt_thread_rdwr_init( &bdb->bi_idl_tree_rwlock );
ldap_pvt_thread_mutex_init( &bdb->bi_idl_tree_lrulock );
be->be_private = bdb;
be->be_cf_ocs = be->bd_info->bi_cf_ocs;
#ifndef BDB_MULTIPLE_SUFFIXES
SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_ONE_SUFFIX;
#endif
rc = bdb_monitor_db_init( be );
return rc;
}
static int
bdb_db_close( BackendDB *be, ConfigReply *cr );
static int
bdb_db_open( BackendDB *be, ConfigReply *cr )
{
int rc, i;
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
struct stat stat1, stat2;
u_int32_t flags;
char path[MAXPATHLEN];
char *dbhome;
Entry *e = NULL;
int do_recover = 0, do_alock_recover = 0;
int alockt, quick = 0;
int do_retry = 1;
if ( be->be_suffix == NULL ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(bdb_db_open) ": need suffix.\n" );
return -1;
}
Debug( LDAP_DEBUG_ARGS,
LDAP_XSTRING(bdb_db_open) ": \"%s\"\n",
be->be_suffix[0].bv_val );
/* Check existence of dbenv_home. Any error means trouble */
rc = stat( bdb->bi_dbenv_home, &stat1 );
if( rc != 0 ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
"cannot access database directory \"%s\" (%d).\n",
be->be_suffix[0].bv_val, bdb->bi_dbenv_home, errno );
return -1;
}
/* Perform database use arbitration/recovery logic */
alockt = (slapMode & SLAP_TOOL_READONLY) ? ALOCK_LOCKED : ALOCK_UNIQUE;
if ( slapMode & SLAP_TOOL_QUICK ) {
alockt |= ALOCK_NOSAVE;
quick = 1;
}
rc = alock_open( &bdb->bi_alock_info,
"slapd",
bdb->bi_dbenv_home, alockt );
/* alockt is TRUE if the existing environment was created in Quick mode */
alockt = (rc & ALOCK_NOSAVE) ? 1 : 0;
rc &= ~ALOCK_NOSAVE;
if( rc == ALOCK_RECOVER ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
"unclean shutdown detected; attempting recovery.\n",
be->be_suffix[0].bv_val );
do_alock_recover = 1;
do_recover = DB_RECOVER;
} else if( rc == ALOCK_BUSY ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
"database already in use.\n",
be->be_suffix[0].bv_val );
return -1;
} else if( rc != ALOCK_CLEAN ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
"alock package is unstable.\n",
be->be_suffix[0].bv_val );
return -1;
}
if ( rc == ALOCK_CLEAN )
be->be_flags |= SLAP_DBFLAG_CLEAN;
/*
* The DB_CONFIG file may have changed. If so, recover the
* database so that new settings are put into effect. Also
* note the possible absence of DB_CONFIG in the log.
*/
if( stat( bdb->bi_db_config_path, &stat1 ) == 0 ) {
if ( !do_recover ) {
char *ptr = lutil_strcopy(path, bdb->bi_dbenv_home);
*ptr++ = LDAP_DIRSEP[0];
strcpy( ptr, "__db.001" );
if( stat( path, &stat2 ) == 0 ) {
if( stat2.st_mtime < stat1.st_mtime ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(bdb_db_open) ": DB_CONFIG for suffix \"%s\" has changed.\n",
be->be_suffix[0].bv_val );
if ( quick ) {
Debug( LDAP_DEBUG_ANY,
"Cannot use Quick mode; perform manual recovery first.\n" );
slapMode ^= SLAP_TOOL_QUICK;
rc = -1;
goto fail;
} else {
Debug( LDAP_DEBUG_ANY,
"Performing database recovery to activate new settings.\n" );
}
do_recover = DB_RECOVER;
}
}
}
}
else {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(bdb_db_open) ": warning - no DB_CONFIG file found "
"in directory %s: (%d).\n"
"Expect poor performance for suffix \"%s\".\n",
bdb->bi_dbenv_home, errno, be->be_suffix[0].bv_val );
}
/* Always let slapcat run, regardless of environment state.
* This can be used to cause a cache flush after an unclean
* shutdown.
*/
if ( do_recover && ( slapMode & SLAP_TOOL_READONLY )) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
"recovery skipped in read-only mode. "
"Run manual recovery if errors are encountered.\n",
be->be_suffix[0].bv_val );
do_recover = 0;
do_alock_recover = 0;
quick = alockt;
}
/* An existing environment in Quick mode has nothing to recover. */
if ( alockt && do_recover ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
"cannot recover, database must be reinitialized.\n",
be->be_suffix[0].bv_val );
rc = -1;
goto fail;
}
rc = db_env_create( &bdb->bi_dbenv, 0 );
if( rc != 0 ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
"db_env_create failed: %s (%d).\n",
be->be_suffix[0].bv_val, db_strerror(rc), rc );
goto fail;
}
#ifdef HAVE_EBCDIC
strcpy( path, bdb->bi_dbenv_home );
__atoe( path );
dbhome = path;
#else
dbhome = bdb->bi_dbenv_home;
#endif
/* If existing environment is clean but doesn't support
* currently requested modes, remove it.
*/
if ( !do_recover && ( alockt ^ quick )) {
shm_retry:
rc = bdb->bi_dbenv->remove( bdb->bi_dbenv, dbhome, DB_FORCE );
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
"dbenv remove failed: %s (%d).\n",
be->be_suffix[0].bv_val, db_strerror(rc), rc );
bdb->bi_dbenv = NULL;
goto fail;
}
rc = db_env_create( &bdb->bi_dbenv, 0 );
if( rc != 0 ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
"db_env_create failed: %s (%d).\n",
be->be_suffix[0].bv_val, db_strerror(rc), rc );
goto fail;
}
}
bdb->bi_dbenv->set_errpfx( bdb->bi_dbenv, be->be_suffix[0].bv_val );
bdb->bi_dbenv->set_errcall( bdb->bi_dbenv, bdb_errcall );
bdb->bi_dbenv->set_lk_detect( bdb->bi_dbenv, bdb->bi_lock_detect );
if ( !BER_BVISNULL( &bdb->bi_db_crypt_key )) {
rc = bdb->bi_dbenv->set_encrypt( bdb->bi_dbenv, bdb->bi_db_crypt_key.bv_val,
DB_ENCRYPT_AES );
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
"dbenv set_encrypt failed: %s (%d).\n",
be->be_suffix[0].bv_val, db_strerror(rc), rc );
goto fail;
}
}
/* One long-lived TXN per thread, two TXNs per write op */
bdb->bi_dbenv->set_tx_max( bdb->bi_dbenv, connection_pool_max * 3 );
if( bdb->bi_dbenv_xflags != 0 ) {
rc = bdb->bi_dbenv->set_flags( bdb->bi_dbenv,
bdb->bi_dbenv_xflags, 1);
if( rc != 0 ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
"dbenv_set_flags failed: %s (%d).\n",
be->be_suffix[0].bv_val, db_strerror(rc), rc );
goto fail;
}
}
#define BDB_TXN_FLAGS (DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN)
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
"dbenv_open(%s).\n",
be->be_suffix[0].bv_val, bdb->bi_dbenv_home );
flags = DB_INIT_MPOOL | DB_CREATE | DB_THREAD;
if ( !quick )
flags |= BDB_TXN_FLAGS;
/* If a key was set, use shared memory for the BDB environment */
if ( bdb->bi_shm_key ) {
bdb->bi_dbenv->set_shm_key( bdb->bi_dbenv, bdb->bi_shm_key );
flags |= DB_SYSTEM_MEM;
}
rc = (bdb->bi_dbenv->open)( bdb->bi_dbenv, dbhome,
flags | do_recover, bdb->bi_dbenv_mode );
if ( rc ) {
/* Regular open failed, probably a missing shm environment.
* Start over, do a recovery.
*/
if ( !do_recover && bdb->bi_shm_key && do_retry ) {
bdb->bi_dbenv->close( bdb->bi_dbenv, 0 );
rc = db_env_create( &bdb->bi_dbenv, 0 );
if( rc == 0 ) {
Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open)
": database \"%s\": "
"shared memory env open failed, assuming stale env.\n",
be->be_suffix[0].bv_val );
do_retry = 0;
goto shm_retry;
}
}
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(bdb_db_open) ": database \"%s\" cannot be %s, err %d. "
"Restore from backup!\n",
be->be_suffix[0].bv_val, do_recover ? "recovered" : "opened", rc );
goto fail;
}
if ( do_alock_recover && alock_recover (&bdb->bi_alock_info) != 0 ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(bdb_db_open) ": database \"%s\": alock_recover failed\n",
be->be_suffix[0].bv_val );
rc = -1;
goto fail;
}
#ifdef SLAP_ZONE_ALLOC
if ( bdb->bi_cache.c_maxsize ) {
bdb->bi_cache.c_zctx = slap_zn_mem_create(
SLAP_ZONE_INITSIZE, SLAP_ZONE_MAXSIZE,
SLAP_ZONE_DELTA, SLAP_ZONE_SIZE);
}
#endif
/* dncache defaults to 0 == unlimited
* must be >= entrycache
*/
if ( bdb->bi_cache.c_eimax && bdb->bi_cache.c_eimax < bdb->bi_cache.c_maxsize ) {
bdb->bi_cache.c_eimax = bdb->bi_cache.c_maxsize;
}
if ( bdb->bi_idl_cache_max_size ) {
bdb->bi_idl_tree = NULL;
bdb->bi_idl_cache_size = 0;
}
flags = DB_THREAD | bdb->bi_db_opflags;
#ifdef DB_AUTO_COMMIT
if ( !quick )
flags |= DB_AUTO_COMMIT;
#endif
bdb->bi_databases = (struct bdb_db_info **) ch_malloc(
BDB_INDICES * sizeof(struct bdb_db_info *) );
/* open (and create) main database */
for( i = 0; bdbi_databases[i].name.bv_val; i++ ) {
struct bdb_db_info *db;
db = (struct bdb_db_info *) ch_calloc(1, sizeof(struct bdb_db_info));
rc = db_create( &db->bdi_db, bdb->bi_dbenv, 0 );
if( rc != 0 ) {
snprintf(cr->msg, sizeof(cr->msg),
"database \"%s\": db_create(%s) failed: %s (%d).",
be->be_suffix[0].bv_val,
bdb->bi_dbenv_home, db_strerror(rc), rc );
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(bdb_db_open) ": %s\n",
cr->msg );
ch_free( db );
goto fail;
}
if( !BER_BVISNULL( &bdb->bi_db_crypt_key )) {
rc = db->bdi_db->set_flags( db->bdi_db, DB_ENCRYPT );
if ( rc ) {
snprintf(cr->msg, sizeof(cr->msg),
"database \"%s\": db set_flags(DB_ENCRYPT)(%s) failed: %s (%d).",
be->be_suffix[0].bv_val,
bdb->bi_dbenv_home, db_strerror(rc), rc );
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(bdb_db_open) ": %s\n",
cr->msg );
db->bdi_db->close( db->bdi_db, 0 );
ch_free( db );
goto fail;
}
}
if( bdb->bi_flags & BDB_CHKSUM ) {
rc = db->bdi_db->set_flags( db->bdi_db, DB_CHKSUM );
if ( rc ) {
snprintf(cr->msg, sizeof(cr->msg),
"database \"%s\": db set_flags(DB_CHKSUM)(%s) failed: %s (%d).",
be->be_suffix[0].bv_val,
bdb->bi_dbenv_home, db_strerror(rc), rc );
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(bdb_db_open) ": %s\n",
cr->msg );
db->bdi_db->close( db->bdi_db, 0 );
ch_free( db );
goto fail;
}
}
rc = bdb_db_findsize( bdb, (struct berval *)&bdbi_databases[i].name );
if( i == BDB_ID2ENTRY ) {
if ( !rc ) rc = BDB_ID2ENTRY_PAGESIZE;
rc = db->bdi_db->set_pagesize( db->bdi_db, rc );
if ( slapMode & SLAP_TOOL_MODE )
db->bdi_db->mpf->set_priority( db->bdi_db->mpf,
DB_PRIORITY_VERY_LOW );
if ( slapMode & SLAP_TOOL_READMAIN ) {
flags |= DB_RDONLY;
} else {
flags |= DB_CREATE;
}
} else {
/* Use FS default size if not configured */
if ( rc )
rc = db->bdi_db->set_pagesize( db->bdi_db, rc );
rc = db->bdi_db->set_flags( db->bdi_db,
DB_DUP | DB_DUPSORT );
#ifndef BDB_HIER
if ( slapMode & SLAP_TOOL_READONLY ) {
flags |= DB_RDONLY;
} else {
flags |= DB_CREATE;
}
#else
rc = db->bdi_db->set_dup_compare( db->bdi_db,
bdb_dup_compare );
if ( slapMode & (SLAP_TOOL_READONLY|SLAP_TOOL_READMAIN) ) {
flags |= DB_RDONLY;
} else {
flags |= DB_CREATE;
}
#endif
}
#ifdef HAVE_EBCDIC
strcpy( path, bdbi_databases[i].file );
__atoe( path );
rc = DB_OPEN( db->bdi_db,
path,
/* bdbi_databases[i].name, */ NULL,
bdbi_databases[i].type,
bdbi_databases[i].flags | flags,
bdb->bi_dbenv_mode );
#else
rc = DB_OPEN( db->bdi_db,
bdbi_databases[i].file,
/* bdbi_databases[i].name, */ NULL,
bdbi_databases[i].type,
bdbi_databases[i].flags | flags,
bdb->bi_dbenv_mode );
#endif
if ( rc != 0 ) {
snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": "
"db_open(%s/%s) failed: %s (%d).",
be->be_suffix[0].bv_val,
bdb->bi_dbenv_home, bdbi_databases[i].file,
db_strerror(rc), rc );
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(bdb_db_open) ": %s\n",
cr->msg );
db->bdi_db->close( db->bdi_db, 0 );
ch_free( db );
goto fail;
}
flags &= ~(DB_CREATE | DB_RDONLY);
db->bdi_name = bdbi_databases[i].name;
bdb->bi_databases[i] = db;
}
bdb->bi_databases[i] = NULL;
bdb->bi_ndatabases = i;
/* get nextid */
rc = bdb_last_id( be, NULL );
if( rc != 0 ) {
snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": "
"last_id(%s) failed: %s (%d).",
be->be_suffix[0].bv_val, bdb->bi_dbenv_home,
db_strerror(rc), rc );
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(bdb_db_open) ": %s\n",
cr->msg );
goto fail;
}
if ( !quick ) {
int txflag = DB_READ_COMMITTED;
/* avoid deadlocks in server; tools should
* wait since they have no deadlock retry mechanism.
*/
if ( slapMode & SLAP_SERVER_MODE )
txflag |= DB_TXN_NOWAIT;
TXN_BEGIN(bdb->bi_dbenv, NULL, &bdb->bi_cache.c_txn, txflag);
}
entry_prealloc( bdb->bi_cache.c_maxsize );
attr_prealloc( bdb->bi_cache.c_maxsize * 20 );
/* setup for empty-DN contexts */
if ( BER_BVISEMPTY( &be->be_nsuffix[0] )) {
rc = bdb_id2entry( be, NULL, 0, &e );
}
if ( !e ) {
struct berval gluebv = BER_BVC("glue");
Operation op = {0};
Opheader ohdr = {0};
e = entry_alloc();
e->e_id = 0;
ber_dupbv( &e->e_name, (struct berval *)&slap_empty_bv );
ber_dupbv( &e->e_nname, (struct berval *)&slap_empty_bv );
attr_merge_one( e, slap_schema.si_ad_objectClass,
&gluebv, NULL );
attr_merge_one( e, slap_schema.si_ad_structuralObjectClass,
&gluebv, NULL );
op.o_hdr = &ohdr;
op.o_bd = be;
op.ora_e = e;
op.o_dn = be->be_rootdn;
op.o_ndn = be->be_rootndn;
slap_add_opattrs( &op, NULL, NULL, 0, 0 );
}
e->e_ocflags = SLAP_OC_GLUE|SLAP_OC__END;
e->e_private = &bdb->bi_cache.c_dntree;
bdb->bi_cache.c_dntree.bei_e = e;
/* monitor setup */
rc = bdb_monitor_db_open( be );
if ( rc != 0 ) {
goto fail;
}
bdb->bi_flags |= BDB_IS_OPEN;
return 0;
fail:
bdb_db_close( be, NULL );
return rc;
}
static int
bdb_db_close( BackendDB *be, ConfigReply *cr )
{
int rc;
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
struct bdb_db_info *db;
bdb_idl_cache_entry_t *entry, *next_entry;
/* monitor handling */
(void)bdb_monitor_db_close( be );
{
Entry *e = bdb->bi_cache.c_dntree.bei_e;
if ( e ) {
bdb->bi_cache.c_dntree.bei_e = NULL;
e->e_private = NULL;
bdb_entry_return( e );
}
}
bdb->bi_flags &= ~BDB_IS_OPEN;
ber_bvarray_free( bdb->bi_db_config );
bdb->bi_db_config = NULL;
if( bdb->bi_dbenv ) {
/* Free cache locker if we enabled locking.
* TXNs must all be closed before DBs...
*/
if ( !( slapMode & SLAP_TOOL_QUICK ) && bdb->bi_cache.c_txn ) {
TXN_ABORT( bdb->bi_cache.c_txn );
bdb->bi_cache.c_txn = NULL;
}
bdb_reader_flush( bdb->bi_dbenv );
}
while( bdb->bi_databases && bdb->bi_ndatabases-- ) {
db = bdb->bi_databases[bdb->bi_ndatabases];
rc = db->bdi_db->close( db->bdi_db, 0 );
/* Lower numbered names are not strdup'd */
if( bdb->bi_ndatabases >= BDB_NDB )
free( db->bdi_name.bv_val );
free( db );
}
free( bdb->bi_databases );
bdb->bi_databases = NULL;
bdb_cache_release_all (&bdb->bi_cache);
if ( bdb->bi_idl_cache_size ) {
avl_free( bdb->bi_idl_tree, NULL );
bdb->bi_idl_tree = NULL;
entry = bdb->bi_idl_lru_head;
do {
next_entry = entry->idl_lru_next;
if ( entry->idl )
free( entry->idl );
free( entry->kstr.bv_val );
free( entry );
entry = next_entry;
} while ( entry != bdb->bi_idl_lru_head );
bdb->bi_idl_lru_head = bdb->bi_idl_lru_tail = NULL;
}
/* close db environment */
if( bdb->bi_dbenv ) {
/* force a checkpoint, but not if we were ReadOnly,
* and not in Quick mode since there are no transactions there.
*/
if ( !( slapMode & ( SLAP_TOOL_QUICK|SLAP_TOOL_READONLY ))) {
rc = TXN_CHECKPOINT( bdb->bi_dbenv, 0, 0, DB_FORCE );
if( rc != 0 ) {
Debug( LDAP_DEBUG_ANY,
"bdb_db_close: database \"%s\": "
"txn_checkpoint failed: %s (%d).\n",
be->be_suffix[0].bv_val, db_strerror(rc), rc );
}
}
rc = bdb->bi_dbenv->close( bdb->bi_dbenv, 0 );
bdb->bi_dbenv = NULL;
if( rc != 0 ) {
Debug( LDAP_DEBUG_ANY,
"bdb_db_close: database \"%s\": "
"close failed: %s (%d)\n",
be->be_suffix[0].bv_val, db_strerror(rc), rc );
return rc;
}
}
rc = alock_close( &bdb->bi_alock_info, slapMode & SLAP_TOOL_QUICK );
if( rc != 0 ) {
Debug( LDAP_DEBUG_ANY,
"bdb_db_close: database \"%s\": alock_close failed\n",
be->be_suffix[0].bv_val );
return -1;
}
return 0;
}
static int
bdb_db_destroy( BackendDB *be, ConfigReply *cr )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
/* stop and remove checkpoint task */
if ( bdb->bi_txn_cp_task ) {
struct re_s *re = bdb->bi_txn_cp_task;
bdb->bi_txn_cp_task = NULL;
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
if ( ldap_pvt_runqueue_isrunning( &slapd_rq, re ) )
ldap_pvt_runqueue_stoptask( &slapd_rq, re );
ldap_pvt_runqueue_remove( &slapd_rq, re );
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
}
/* monitor handling */
(void)bdb_monitor_db_destroy( be );
if( bdb->bi_dbenv_home ) ch_free( bdb->bi_dbenv_home );
if( bdb->bi_db_config_path ) ch_free( bdb->bi_db_config_path );
bdb_attr_index_destroy( bdb );
ldap_pvt_thread_rdwr_destroy ( &bdb->bi_cache.c_rwlock );
ldap_pvt_thread_mutex_destroy( &bdb->bi_cache.c_lru_mutex );
ldap_pvt_thread_mutex_destroy( &bdb->bi_cache.c_count_mutex );
ldap_pvt_thread_mutex_destroy( &bdb->bi_cache.c_eifree_mutex );
ldap_pvt_thread_mutex_destroy( &bdb->bi_cache.c_dntree.bei_kids_mutex );
#ifdef BDB_HIER
ldap_pvt_thread_mutex_destroy( &bdb->bi_modrdns_mutex );
#endif
ldap_pvt_thread_mutex_destroy( &bdb->bi_lastid_mutex );
ldap_pvt_thread_mutex_destroy( &bdb->bi_database_mutex );
ldap_pvt_thread_rdwr_destroy( &bdb->bi_idl_tree_rwlock );
ldap_pvt_thread_mutex_destroy( &bdb->bi_idl_tree_lrulock );
ch_free( bdb );
be->be_private = NULL;
return 0;
}
int
bdb_back_initialize(
BackendInfo *bi )
{
int rc;
static char *controls[] = {
LDAP_CONTROL_ASSERT,
LDAP_CONTROL_MANAGEDSAIT,
LDAP_CONTROL_NOOP,
LDAP_CONTROL_PAGEDRESULTS,
LDAP_CONTROL_PRE_READ,
LDAP_CONTROL_POST_READ,
LDAP_CONTROL_SUBENTRIES,
LDAP_CONTROL_X_PERMISSIVE_MODIFY,
#ifdef LDAP_X_TXN
LDAP_CONTROL_X_TXN_SPEC,
#endif
NULL
};
/* initialize the underlying database system */
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_back_initialize) ": initialize "
BDB_UCTYPE " backend\n" );
bi->bi_flags |=
SLAP_BFLAG_INCREMENT |
SLAP_BFLAG_SUBENTRIES |
SLAP_BFLAG_ALIASES |
SLAP_BFLAG_REFERRALS;
bi->bi_controls = controls;
{ /* version check */
int major, minor, patch, ver;
char *version = db_version( &major, &minor, &patch );
#ifdef HAVE_EBCDIC
char v2[1024];
/* All our stdio does an ASCII to EBCDIC conversion on
* the output. Strings from the BDB library are already
* in EBCDIC; we have to go back and forth...
*/
strcpy( v2, version );
__etoa( v2 );
version = v2;
#endif
ver = (major << 24) | (minor << 16) | patch;
if( ver != DB_VERSION_FULL ) {
/* fail if a versions don't match */
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(bdb_back_initialize) ": "
"BDB library version mismatch:"
" expected " DB_VERSION_STRING ","
" got %s\n", version );
return -1;
}
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_back_initialize)
": %s\n", version );
}
db_env_set_func_free( ber_memfree );
db_env_set_func_malloc( (db_malloc *)ber_memalloc );
db_env_set_func_realloc( (db_realloc *)ber_memrealloc );
#if !defined(NO_THREAD) && DB_VERSION_FULL <= 0x04070000
/* This is a no-op on a NO_THREAD build. Leave the default
* alone so that BDB will sleep on interprocess conflicts.
* Don't bother on BDB 4.7...
*/
db_env_set_func_yield( ldap_pvt_thread_yield );
#endif
bi->bi_open = 0;
bi->bi_close = 0;
bi->bi_config = 0;
bi->bi_destroy = 0;
bi->bi_db_init = bdb_db_init;
bi->bi_db_config = config_generic_wrapper;
bi->bi_db_open = bdb_db_open;
bi->bi_db_close = bdb_db_close;
bi->bi_db_destroy = bdb_db_destroy;
bi->bi_op_add = bdb_add;
bi->bi_op_bind = bdb_bind;
bi->bi_op_compare = bdb_compare;
bi->bi_op_delete = bdb_delete;
bi->bi_op_modify = bdb_modify;
bi->bi_op_modrdn = bdb_modrdn;
bi->bi_op_search = bdb_search;
bi->bi_op_unbind = 0;
bi->bi_extended = bdb_extended;
bi->bi_chk_referrals = bdb_referrals;
bi->bi_operational = bdb_operational;
bi->bi_has_subordinates = bdb_hasSubordinates;
bi->bi_entry_release_rw = bdb_entry_release;
bi->bi_entry_get_rw = bdb_entry_get;
/*
* hooks for slap tools
*/
bi->bi_tool_entry_open = bdb_tool_entry_open;
bi->bi_tool_entry_close = bdb_tool_entry_close;
bi->bi_tool_entry_first = backend_tool_entry_first;
bi->bi_tool_entry_first_x = bdb_tool_entry_first_x;
bi->bi_tool_entry_next = bdb_tool_entry_next;
bi->bi_tool_entry_get = bdb_tool_entry_get;
bi->bi_tool_entry_put = bdb_tool_entry_put;
bi->bi_tool_entry_reindex = bdb_tool_entry_reindex;
bi->bi_tool_sync = 0;
bi->bi_tool_dn2id_get = bdb_tool_dn2id_get;
bi->bi_tool_entry_modify = bdb_tool_entry_modify;
bi->bi_tool_entry_delete = bdb_tool_entry_delete;
bi->bi_connection_init = 0;
bi->bi_connection_destroy = 0;
rc = bdb_back_init_cf( bi );
return rc;
}
#if (SLAPD_BDB == SLAPD_MOD_DYNAMIC && !defined(BDB_HIER)) || \
(SLAPD_HDB == SLAPD_MOD_DYNAMIC && defined(BDB_HIER))
/* conditionally define the init_module() function */
#ifdef BDB_HIER
SLAP_BACKEND_INIT_MODULE( hdb )
#else /* !BDB_HIER */
SLAP_BACKEND_INIT_MODULE( bdb )
#endif /* !BDB_HIER */
#endif /* SLAPD_[BH]DB == SLAPD_MOD_DYNAMIC */

View File

@ -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-2019 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include <ac/socket.h>
#include "slap.h"
#include "back-bdb.h"
#include "idl.h"
/* read a key */
int
bdb_key_read(
Backend *be,
DB *db,
DB_TXN *txn,
struct berval *k,
ID *ids,
DBC **saved_cursor,
int get_flag
)
{
int rc;
DBT key;
Debug( LDAP_DEBUG_TRACE, "=> key_read\n" );
DBTzero( &key );
bv2DBT(k,&key);
key.ulen = key.size;
key.flags = DB_DBT_USERMEM;
rc = bdb_idl_fetch_key( be, db, txn, &key, ids, saved_cursor, get_flag );
if( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "<= bdb_index_read: failed (%d)\n",
rc );
} else {
Debug( LDAP_DEBUG_TRACE, "<= bdb_index_read %ld candidates\n",
(long) BDB_IDL_N(ids) );
}
return rc;
}
/* Add or remove stuff from index files */
int
bdb_key_change(
Backend *be,
DB *db,
DB_TXN *txn,
struct berval *k,
ID id,
int op
)
{
int rc;
DBT key;
Debug( LDAP_DEBUG_TRACE, "=> key_change(%s,%lx)\n",
op == SLAP_INDEX_ADD_OP ? "ADD":"DELETE", (long) id );
DBTzero( &key );
bv2DBT(k,&key);
key.ulen = key.size;
key.flags = DB_DBT_USERMEM;
if (op == SLAP_INDEX_ADD_OP) {
/* Add values */
#ifdef BDB_TOOL_IDL_CACHING
if ( slapMode & SLAP_TOOL_QUICK )
rc = bdb_tool_idl_add( be, db, txn, &key, id );
else
#endif
rc = bdb_idl_insert_key( be, db, txn, &key, id );
if ( rc == DB_KEYEXIST ) rc = 0;
} else {
/* Delete values */
rc = bdb_idl_delete_key( be, db, txn, &key, id );
if ( rc == DB_NOTFOUND ) rc = 0;
}
Debug( LDAP_DEBUG_TRACE, "<= key_change %d\n", rc );
return rc;
}

View File

@ -1,801 +0,0 @@
/* modify.c - bdb backend modify routine */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2000-2019 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include <ac/time.h>
#include "back-bdb.h"
static struct berval scbva[] = {
BER_BVC("glue"),
BER_BVNULL
};
static void
bdb_modify_idxflags(
Operation *op,
AttributeDescription *desc,
int got_delete,
Attribute *newattrs,
Attribute *oldattrs )
{
struct berval ix_at;
AttrInfo *ai;
/* check if modified attribute was indexed
* but not in case of NOOP... */
ai = bdb_index_mask( op->o_bd, desc, &ix_at );
if ( ai ) {
if ( got_delete ) {
Attribute *ap;
struct berval ix2;
ap = attr_find( oldattrs, desc );
if ( ap ) ap->a_flags |= SLAP_ATTR_IXDEL;
/* Find all other attrs that index to same slot */
for ( ap = newattrs; ap; ap = ap->a_next ) {
ai = bdb_index_mask( op->o_bd, ap->a_desc, &ix2 );
if ( ai && ix2.bv_val == ix_at.bv_val )
ap->a_flags |= SLAP_ATTR_IXADD;
}
} else {
Attribute *ap;
ap = attr_find( newattrs, desc );
if ( ap ) ap->a_flags |= SLAP_ATTR_IXADD;
}
}
}
int bdb_modify_internal(
Operation *op,
DB_TXN *tid,
Modifications *modlist,
Entry *e,
const char **text,
char *textbuf,
size_t textlen )
{
int rc, err;
Modification *mod;
Modifications *ml;
Attribute *save_attrs;
Attribute *ap;
int glue_attr_delete = 0;
int got_delete;
Debug( LDAP_DEBUG_TRACE, "bdb_modify_internal: 0x%08lx: %s\n",
e->e_id, e->e_dn );
if ( !acl_check_modlist( op, e, modlist )) {
return LDAP_INSUFFICIENT_ACCESS;
}
/* save_attrs will be disposed of by bdb_cache_modify */
save_attrs = e->e_attrs;
e->e_attrs = attrs_dup( e->e_attrs );
for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
int match;
mod = &ml->sml_mod;
switch( mod->sm_op ) {
case LDAP_MOD_ADD:
case LDAP_MOD_REPLACE:
if ( mod->sm_desc == slap_schema.si_ad_structuralObjectClass ) {
value_match( &match, slap_schema.si_ad_structuralObjectClass,
slap_schema.si_ad_structuralObjectClass->
ad_type->sat_equality,
SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
&mod->sm_values[0], &scbva[0], text );
if ( !match ) glue_attr_delete = 1;
}
}
if ( glue_attr_delete )
break;
}
if ( glue_attr_delete ) {
Attribute **app = &e->e_attrs;
while ( *app != NULL ) {
if ( !is_at_operational( (*app)->a_desc->ad_type )) {
Attribute *save = *app;
*app = (*app)->a_next;
attr_free( save );
continue;
}
app = &(*app)->a_next;
}
}
for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
mod = &ml->sml_mod;
got_delete = 0;
switch ( mod->sm_op ) {
case LDAP_MOD_ADD:
Debug(LDAP_DEBUG_ARGS,
"bdb_modify_internal: add %s\n",
mod->sm_desc->ad_cname.bv_val );
err = modify_add_values( e, mod, get_permissiveModify(op),
text, textbuf, textlen );
if( err != LDAP_SUCCESS ) {
Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
err, *text );
}
break;
case LDAP_MOD_DELETE:
if ( glue_attr_delete ) {
err = LDAP_SUCCESS;
break;
}
Debug(LDAP_DEBUG_ARGS,
"bdb_modify_internal: delete %s\n",
mod->sm_desc->ad_cname.bv_val );
err = modify_delete_values( e, mod, get_permissiveModify(op),
text, textbuf, textlen );
if( err != LDAP_SUCCESS ) {
Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
err, *text );
} else {
got_delete = 1;
}
break;
case LDAP_MOD_REPLACE:
Debug(LDAP_DEBUG_ARGS,
"bdb_modify_internal: replace %s\n",
mod->sm_desc->ad_cname.bv_val );
err = modify_replace_values( e, mod, get_permissiveModify(op),
text, textbuf, textlen );
if( err != LDAP_SUCCESS ) {
Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
err, *text );
} else {
got_delete = 1;
}
break;
case LDAP_MOD_INCREMENT:
Debug(LDAP_DEBUG_ARGS,
"bdb_modify_internal: increment %s\n",
mod->sm_desc->ad_cname.bv_val );
err = modify_increment_values( e, mod, get_permissiveModify(op),
text, textbuf, textlen );
if( err != LDAP_SUCCESS ) {
Debug(LDAP_DEBUG_ARGS,
"bdb_modify_internal: %d %s\n",
err, *text );
} else {
got_delete = 1;
}
break;
case SLAP_MOD_SOFTADD:
Debug(LDAP_DEBUG_ARGS,
"bdb_modify_internal: softadd %s\n",
mod->sm_desc->ad_cname.bv_val );
/* Avoid problems in index_add_mods()
* We need to add index if necessary.
*/
mod->sm_op = LDAP_MOD_ADD;
err = modify_add_values( e, mod, get_permissiveModify(op),
text, textbuf, textlen );
mod->sm_op = SLAP_MOD_SOFTADD;
if ( err == LDAP_TYPE_OR_VALUE_EXISTS ) {
err = LDAP_SUCCESS;
}
if( err != LDAP_SUCCESS ) {
Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
err, *text );
}
break;
case SLAP_MOD_SOFTDEL:
Debug(LDAP_DEBUG_ARGS,
"bdb_modify_internal: softdel %s\n",
mod->sm_desc->ad_cname.bv_val );
/* Avoid problems in index_delete_mods()
* We need to add index if necessary.
*/
mod->sm_op = LDAP_MOD_DELETE;
err = modify_delete_values( e, mod, get_permissiveModify(op),
text, textbuf, textlen );
mod->sm_op = SLAP_MOD_SOFTDEL;
if ( err == LDAP_SUCCESS ) {
got_delete = 1;
} else if ( err == LDAP_NO_SUCH_ATTRIBUTE ) {
err = LDAP_SUCCESS;
}
if( err != LDAP_SUCCESS ) {
Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
err, *text );
}
break;
case SLAP_MOD_ADD_IF_NOT_PRESENT:
if ( attr_find( e->e_attrs, mod->sm_desc ) != NULL ) {
/* skip */
err = LDAP_SUCCESS;
break;
}
Debug(LDAP_DEBUG_ARGS,
"bdb_modify_internal: add_if_not_present %s\n",
mod->sm_desc->ad_cname.bv_val );
/* Avoid problems in index_add_mods()
* We need to add index if necessary.
*/
mod->sm_op = LDAP_MOD_ADD;
err = modify_add_values( e, mod, get_permissiveModify(op),
text, textbuf, textlen );
mod->sm_op = SLAP_MOD_ADD_IF_NOT_PRESENT;
if( err != LDAP_SUCCESS ) {
Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
err, *text );
}
break;
default:
Debug(LDAP_DEBUG_ANY, "bdb_modify_internal: invalid op %d\n",
mod->sm_op );
*text = "Invalid modify operation";
err = LDAP_OTHER;
Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
err, *text );
}
if ( err != LDAP_SUCCESS ) {
attrs_free( e->e_attrs );
e->e_attrs = save_attrs;
/* unlock entry, delete from cache */
return err;
}
/* If objectClass was modified, reset the flags */
if ( mod->sm_desc == slap_schema.si_ad_objectClass ) {
e->e_ocflags = 0;
}
if ( glue_attr_delete ) e->e_ocflags = 0;
/* check if modified attribute was indexed
* but not in case of NOOP... */
if ( !op->o_noop ) {
bdb_modify_idxflags( op, mod->sm_desc, got_delete, e->e_attrs, save_attrs );
}
}
/* check that the entry still obeys the schema */
ap = NULL;
rc = entry_schema_check( op, e, save_attrs, get_relax(op), 0, &ap,
text, textbuf, textlen );
if ( rc != LDAP_SUCCESS || op->o_noop ) {
attrs_free( e->e_attrs );
/* clear the indexing flags */
for ( ap = save_attrs; ap != NULL; ap = ap->a_next ) {
ap->a_flags &= ~(SLAP_ATTR_IXADD|SLAP_ATTR_IXDEL);
}
e->e_attrs = save_attrs;
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY,
"entry failed schema check: %s\n",
*text );
}
/* if NOOP then silently revert to saved attrs */
return rc;
}
/* structuralObjectClass modified! */
if ( ap ) {
assert( ap->a_desc == slap_schema.si_ad_structuralObjectClass );
if ( !op->o_noop ) {
bdb_modify_idxflags( op, slap_schema.si_ad_structuralObjectClass,
1, e->e_attrs, save_attrs );
}
}
/* update the indices of the modified attributes */
/* start with deleting the old index entries */
for ( ap = save_attrs; ap != NULL; ap = ap->a_next ) {
if ( ap->a_flags & SLAP_ATTR_IXDEL ) {
struct berval *vals;
Attribute *a2;
ap->a_flags &= ~SLAP_ATTR_IXDEL;
a2 = attr_find( e->e_attrs, ap->a_desc );
if ( a2 ) {
/* need to detect which values were deleted */
int i, j;
/* let add know there were deletes */
if ( a2->a_flags & SLAP_ATTR_IXADD )
a2->a_flags |= SLAP_ATTR_IXDEL;
vals = op->o_tmpalloc( (ap->a_numvals + 1) *
sizeof(struct berval), op->o_tmpmemctx );
j = 0;
for ( i=0; i < ap->a_numvals; i++ ) {
rc = attr_valfind( a2, SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
&ap->a_nvals[i], NULL, op->o_tmpmemctx );
/* Save deleted values */
if ( rc == LDAP_NO_SUCH_ATTRIBUTE )
vals[j++] = ap->a_nvals[i];
}
BER_BVZERO(vals+j);
} else {
/* attribute was completely deleted */
vals = ap->a_nvals;
}
rc = 0;
if ( !BER_BVISNULL( vals )) {
rc = bdb_index_values( op, tid, ap->a_desc,
vals, e->e_id, SLAP_INDEX_DELETE_OP );
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY,
"%s: attribute \"%s\" index delete failure\n",
op->o_log_prefix, ap->a_desc->ad_cname.bv_val );
attrs_free( e->e_attrs );
e->e_attrs = save_attrs;
}
}
if ( vals != ap->a_nvals )
op->o_tmpfree( vals, op->o_tmpmemctx );
if ( rc ) return rc;
}
}
/* add the new index entries */
for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) {
if (ap->a_flags & SLAP_ATTR_IXADD) {
ap->a_flags &= ~SLAP_ATTR_IXADD;
if ( ap->a_flags & SLAP_ATTR_IXDEL ) {
/* if any values were deleted, we must readd index
* for all remaining values.
*/
ap->a_flags &= ~SLAP_ATTR_IXDEL;
rc = bdb_index_values( op, tid, ap->a_desc,
ap->a_nvals,
e->e_id, SLAP_INDEX_ADD_OP );
} else {
int found = 0;
/* if this was only an add, we only need to index
* the added values.
*/
for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
struct berval *vals;
if ( ml->sml_desc != ap->a_desc || !ml->sml_numvals )
continue;
found = 1;
switch( ml->sml_op ) {
case LDAP_MOD_ADD:
case LDAP_MOD_REPLACE:
case LDAP_MOD_INCREMENT:
case SLAP_MOD_SOFTADD:
case SLAP_MOD_ADD_IF_NOT_PRESENT:
if ( ml->sml_op == LDAP_MOD_INCREMENT )
vals = ap->a_nvals;
else if ( ml->sml_nvalues )
vals = ml->sml_nvalues;
else
vals = ml->sml_values;
rc = bdb_index_values( op, tid, ap->a_desc,
vals, e->e_id, SLAP_INDEX_ADD_OP );
break;
}
if ( rc )
break;
}
/* This attr was affected by a modify of a subtype, so
* there was no direct match in the modlist. Just readd
* all of its values.
*/
if ( !found ) {
rc = bdb_index_values( op, tid, ap->a_desc,
ap->a_nvals,
e->e_id, SLAP_INDEX_ADD_OP );
}
}
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY,
"%s: attribute \"%s\" index add failure\n",
op->o_log_prefix, ap->a_desc->ad_cname.bv_val );
attrs_free( e->e_attrs );
e->e_attrs = save_attrs;
return rc;
}
}
}
return rc;
}
int
bdb_modify( Operation *op, SlapReply *rs )
{
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
Entry *e = NULL;
EntryInfo *ei = NULL;
int manageDSAit = get_manageDSAit( op );
char textbuf[SLAP_TEXT_BUFLEN];
size_t textlen = sizeof textbuf;
DB_TXN *ltid = NULL, *lt2;
struct bdb_op_info opinfo = {{{ 0 }}};
Entry dummy = {0};
DB_LOCK lock;
int num_retries = 0;
LDAPControl **preread_ctrl = NULL;
LDAPControl **postread_ctrl = NULL;
LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
int num_ctrls = 0;
int rc;
Debug( LDAP_DEBUG_ARGS, LDAP_XSTRING(bdb_modify) ": %s\n",
op->o_req_dn.bv_val );
#ifdef LDAP_X_TXN
if( op->o_txnSpec && txn_preop( op, rs ))
return rs->sr_err;
#endif
ctrls[num_ctrls] = NULL;
/* Don't touch the opattrs, if this is a contextCSN update
* initiated from updatedn */
if ( !be_isupdate(op) || !op->orm_modlist || op->orm_modlist->sml_next ||
op->orm_modlist->sml_desc != slap_schema.si_ad_contextCSN ) {
slap_mods_opattrs( op, &op->orm_modlist, 1 );
}
if( 0 ) {
retry: /* transaction retry */
if ( dummy.e_attrs ) {
attrs_free( dummy.e_attrs );
dummy.e_attrs = NULL;
}
if( e != NULL ) {
bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
e = NULL;
}
Debug(LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_modify) ": retrying...\n" );
rs->sr_err = TXN_ABORT( ltid );
ltid = NULL;
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
opinfo.boi_oe.oe_key = NULL;
op->o_do_not_cache = opinfo.boi_acl_cache;
if( rs->sr_err != 0 ) {
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
if ( op->o_abandon ) {
rs->sr_err = SLAPD_ABANDON;
goto return_results;
}
bdb_trans_backoff( ++num_retries );
}
/* begin transaction */
{
int tflags = bdb->bi_db_opflags;
if ( get_lazyCommit( op ))
tflags |= DB_TXN_NOSYNC;
rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, NULL, &ltid, tflags );
}
rs->sr_text = NULL;
if( rs->sr_err != 0 ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_modify) ": txn_begin failed: "
"%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modify) ": txn1 id: %x\n",
ltid->id(ltid) );
opinfo.boi_oe.oe_key = bdb;
opinfo.boi_txn = ltid;
opinfo.boi_err = 0;
opinfo.boi_acl_cache = op->o_do_not_cache;
LDAP_SLIST_INSERT_HEAD( &op->o_extra, &opinfo.boi_oe, oe_next );
/* get entry or ancestor */
rs->sr_err = bdb_dn2entry( op, ltid, &op->o_req_ndn, &ei, 1,
&lock );
if ( rs->sr_err != 0 ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_modify) ": dn2entry failed (%d)\n",
rs->sr_err );
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
case DB_NOTFOUND:
break;
case LDAP_BUSY:
rs->sr_text = "ldap server busy";
goto return_results;
default:
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
}
e = ei->bei_e;
/* acquire and lock entry */
/* FIXME: dn2entry() should return non-glue entry */
if (( rs->sr_err == DB_NOTFOUND ) ||
( !manageDSAit && e && is_entry_glue( e )))
{
if ( e != NULL ) {
rs->sr_matched = ch_strdup( e->e_dn );
rs->sr_ref = is_entry_referral( e )
? get_entry_referrals( op, e )
: NULL;
bdb_unlocked_cache_return_entry_r (&bdb->bi_cache, e);
e = NULL;
} else {
rs->sr_ref = referral_rewrite( default_referral, NULL,
&op->o_req_dn, LDAP_SCOPE_DEFAULT );
}
rs->sr_err = LDAP_REFERRAL;
send_ldap_result( op, rs );
if ( rs->sr_ref != default_referral ) {
ber_bvarray_free( rs->sr_ref );
}
free( (char *)rs->sr_matched );
rs->sr_ref = NULL;
rs->sr_matched = NULL;
goto done;
}
if ( !manageDSAit && is_entry_referral( e ) ) {
/* entry is a referral, don't allow modify */
rs->sr_ref = get_entry_referrals( op, e );
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_modify) ": entry is referral\n" );
rs->sr_err = LDAP_REFERRAL;
rs->sr_matched = e->e_name.bv_val;
send_ldap_result( op, rs );
ber_bvarray_free( rs->sr_ref );
rs->sr_ref = NULL;
rs->sr_matched = NULL;
goto done;
}
if ( get_assert( op ) &&
( test_filter( op, e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
{
rs->sr_err = LDAP_ASSERTION_FAILED;
goto return_results;
}
if( op->o_preread ) {
if( preread_ctrl == NULL ) {
preread_ctrl = &ctrls[num_ctrls++];
ctrls[num_ctrls] = NULL;
}
if ( slap_read_controls( op, rs, e,
&slap_pre_read_bv, preread_ctrl ) )
{
Debug( LDAP_DEBUG_TRACE,
"<=- " LDAP_XSTRING(bdb_modify) ": pre-read "
"failed!\n" );
if ( op->o_preread & SLAP_CONTROL_CRITICAL ) {
/* FIXME: is it correct to abort
* operation if control fails? */
goto return_results;
}
}
}
/* nested transaction */
rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, &lt2, bdb->bi_db_opflags );
rs->sr_text = NULL;
if( rs->sr_err != 0 ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_modify) ": txn_begin(2) failed: " "%s (%d)\n",
db_strerror(rs->sr_err), rs->sr_err );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modify) ": txn2 id: %x\n",
lt2->id(lt2) );
/* Modify the entry */
dummy = *e;
rs->sr_err = bdb_modify_internal( op, lt2, op->orm_modlist,
&dummy, &rs->sr_text, textbuf, textlen );
if( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_modify) ": modify failed (%d)\n",
rs->sr_err );
if ( (rs->sr_err == LDAP_INSUFFICIENT_ACCESS) && opinfo.boi_err ) {
rs->sr_err = opinfo.boi_err;
}
/* Only free attrs if they were dup'd. */
if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL;
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
goto return_results;
}
/* change the entry itself */
rs->sr_err = bdb_id2entry_update( op->o_bd, lt2, &dummy );
if ( rs->sr_err != 0 ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_modify) ": id2entry update failed " "(%d)\n",
rs->sr_err );
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
rs->sr_text = "entry update failed";
goto return_results;
}
if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
rs->sr_err = LDAP_OTHER;
rs->sr_text = "txn_commit(2) failed";
goto return_results;
}
if( op->o_postread ) {
if( postread_ctrl == NULL ) {
postread_ctrl = &ctrls[num_ctrls++];
ctrls[num_ctrls] = NULL;
}
if( slap_read_controls( op, rs, &dummy,
&slap_post_read_bv, postread_ctrl ) )
{
Debug( LDAP_DEBUG_TRACE,
"<=- " LDAP_XSTRING(bdb_modify)
": post-read failed!\n" );
if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
/* FIXME: is it correct to abort
* operation if control fails? */
goto return_results;
}
}
}
if( op->o_noop ) {
if ( ( rs->sr_err = TXN_ABORT( ltid ) ) != 0 ) {
rs->sr_text = "txn_abort (no-op) failed";
} else {
rs->sr_err = LDAP_X_NO_OPERATION;
ltid = NULL;
/* Only free attrs if they were dup'd. */
if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL;
goto return_results;
}
} else {
/* may have changed in bdb_modify_internal() */
e->e_ocflags = dummy.e_ocflags;
rc = bdb_cache_modify( bdb, e, dummy.e_attrs, ltid, &lock );
switch( rc ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
dummy.e_attrs = NULL;
rs->sr_err = TXN_COMMIT( ltid, 0 );
}
ltid = NULL;
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
opinfo.boi_oe.oe_key = NULL;
if( rs->sr_err != 0 ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_modify) ": txn_%s failed: %s (%d)\n",
op->o_noop ? "abort (no-op)" : "commit",
db_strerror(rs->sr_err), rs->sr_err );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "commit failed";
goto return_results;
}
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_modify) ": updated%s id=%08lx dn=\"%s\"\n",
op->o_noop ? " (no-op)" : "",
dummy.e_id, op->o_req_dn.bv_val );
rs->sr_err = LDAP_SUCCESS;
rs->sr_text = NULL;
if( num_ctrls ) rs->sr_ctrls = ctrls;
return_results:
if( dummy.e_attrs ) {
attrs_free( dummy.e_attrs );
}
send_ldap_result( op, rs );
if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp_kbyte ) {
TXN_CHECKPOINT( bdb->bi_dbenv,
bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
}
done:
slap_graduate_commit_csn( op );
if( ltid != NULL ) {
TXN_ABORT( ltid );
}
if ( opinfo.boi_oe.oe_key ) {
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
}
if( e != NULL ) {
bdb_unlocked_cache_return_entry_w (&bdb->bi_cache, e);
}
if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) {
slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
slap_sl_free( *preread_ctrl, op->o_tmpmemctx );
}
if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) {
slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
}
rs->sr_text = NULL;
return rs->sr_err;
}

View File

@ -1,800 +0,0 @@
/* modrdn.c - bdb backend modrdn routine */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2000-2019 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include "back-bdb.h"
int
bdb_modrdn( Operation *op, SlapReply *rs )
{
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
AttributeDescription *children = slap_schema.si_ad_children;
AttributeDescription *entry = slap_schema.si_ad_entry;
struct berval p_dn, p_ndn;
struct berval new_dn = {0, NULL}, new_ndn = {0, NULL};
Entry *e = NULL;
Entry *p = NULL;
EntryInfo *ei = NULL, *eip = NULL, *nei = NULL, *neip = NULL;
/* LDAP v2 supporting correct attribute handling. */
char textbuf[SLAP_TEXT_BUFLEN];
size_t textlen = sizeof textbuf;
DB_TXN *ltid = NULL, *lt2;
struct bdb_op_info opinfo = {{{ 0 }}};
Entry dummy = {0};
Entry *np = NULL; /* newSuperior Entry */
struct berval *np_dn = NULL; /* newSuperior dn */
struct berval *np_ndn = NULL; /* newSuperior ndn */
struct berval *new_parent_dn = NULL; /* np_dn, p_dn, or NULL */
int manageDSAit = get_manageDSAit( op );
DB_LOCK lock, plock, nplock;
int num_retries = 0;
LDAPControl **preread_ctrl = NULL;
LDAPControl **postread_ctrl = NULL;
LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
int num_ctrls = 0;
int rc;
int parent_is_glue = 0;
int parent_is_leaf = 0;
Debug( LDAP_DEBUG_TRACE, "==>" LDAP_XSTRING(bdb_modrdn) "(%s,%s,%s)\n",
op->o_req_dn.bv_val,op->oq_modrdn.rs_newrdn.bv_val,
op->oq_modrdn.rs_newSup ? op->oq_modrdn.rs_newSup->bv_val : "NULL" );
#ifdef LDAP_X_TXN
if( op->o_txnSpec && txn_preop( op, rs ))
return rs->sr_err;
#endif
ctrls[num_ctrls] = NULL;
slap_mods_opattrs( op, &op->orr_modlist, 1 );
if( 0 ) {
retry: /* transaction retry */
if ( dummy.e_attrs ) {
if ( dummy.e_attrs != e->e_attrs )
attrs_free( dummy.e_attrs );
dummy.e_attrs = NULL;
}
if (e != NULL) {
bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
e = NULL;
}
if (p != NULL) {
bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
p = NULL;
}
if (np != NULL) {
bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, np);
np = NULL;
}
Debug( LDAP_DEBUG_TRACE, "==>" LDAP_XSTRING(bdb_modrdn)
": retrying...\n" );
rs->sr_err = TXN_ABORT( ltid );
ltid = NULL;
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
opinfo.boi_oe.oe_key = NULL;
op->o_do_not_cache = opinfo.boi_acl_cache;
if( rs->sr_err != 0 ) {
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
if ( op->o_abandon ) {
rs->sr_err = SLAPD_ABANDON;
goto return_results;
}
parent_is_glue = 0;
parent_is_leaf = 0;
bdb_trans_backoff( ++num_retries );
}
/* begin transaction */
{
int tflags = bdb->bi_db_opflags;
if ( get_lazyCommit( op ))
tflags |= DB_TXN_NOSYNC;
rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, NULL, &ltid, tflags );
}
rs->sr_text = NULL;
if( rs->sr_err != 0 ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_modrdn) ": txn_begin failed: "
"%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn) ": txn1 id: %x\n",
ltid->id(ltid) );
opinfo.boi_oe.oe_key = bdb;
opinfo.boi_txn = ltid;
opinfo.boi_err = 0;
opinfo.boi_acl_cache = op->o_do_not_cache;
LDAP_SLIST_INSERT_HEAD( &op->o_extra, &opinfo.boi_oe, oe_next );
/* get entry */
rs->sr_err = bdb_dn2entry( op, ltid, &op->o_req_ndn, &ei, 1,
&lock );
switch( rs->sr_err ) {
case 0:
case DB_NOTFOUND:
break;
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
case LDAP_BUSY:
rs->sr_text = "ldap server busy";
goto return_results;
default:
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
e = ei->bei_e;
/* FIXME: dn2entry() should return non-glue entry */
if (( rs->sr_err == DB_NOTFOUND ) ||
( !manageDSAit && e && is_entry_glue( e )))
{
if( e != NULL ) {
rs->sr_matched = ch_strdup( e->e_dn );
rs->sr_ref = is_entry_referral( e )
? get_entry_referrals( op, e )
: NULL;
bdb_unlocked_cache_return_entry_r( &bdb->bi_cache, e);
e = NULL;
} else {
rs->sr_ref = referral_rewrite( default_referral, NULL,
&op->o_req_dn, LDAP_SCOPE_DEFAULT );
}
rs->sr_err = LDAP_REFERRAL;
send_ldap_result( op, rs );
ber_bvarray_free( rs->sr_ref );
free( (char *)rs->sr_matched );
rs->sr_ref = NULL;
rs->sr_matched = NULL;
goto done;
}
if ( get_assert( op ) &&
( test_filter( op, e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
{
rs->sr_err = LDAP_ASSERTION_FAILED;
goto return_results;
}
/* check write on old entry */
rs->sr_err = access_allowed( op, e, entry, NULL, ACL_WRITE, NULL );
if ( ! rs->sr_err ) {
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
Debug( LDAP_DEBUG_TRACE, "no access to entry\n" );
rs->sr_text = "no write access to old entry";
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
goto return_results;
}
#ifndef BDB_HIER
rs->sr_err = bdb_cache_children( op, ltid, e );
if ( rs->sr_err != DB_NOTFOUND ) {
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
case 0:
Debug(LDAP_DEBUG_ARGS,
"<=- " LDAP_XSTRING(bdb_modrdn)
": non-leaf %s\n",
op->o_req_dn.bv_val );
rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
rs->sr_text = "subtree rename not supported";
break;
default:
Debug(LDAP_DEBUG_ARGS,
"<=- " LDAP_XSTRING(bdb_modrdn)
": has_children failed: %s (%d)\n",
db_strerror(rs->sr_err), rs->sr_err );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
}
goto return_results;
}
ei->bei_state |= CACHE_ENTRY_NO_KIDS;
#endif
if (!manageDSAit && is_entry_referral( e ) ) {
/* parent is a referral, don't allow add */
rs->sr_ref = get_entry_referrals( op, e );
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn)
": entry %s is referral\n", e->e_dn );
rs->sr_err = LDAP_REFERRAL,
rs->sr_matched = e->e_name.bv_val;
send_ldap_result( op, rs );
ber_bvarray_free( rs->sr_ref );
rs->sr_ref = NULL;
rs->sr_matched = NULL;
goto done;
}
if ( be_issuffix( op->o_bd, &e->e_nname ) ) {
#ifdef BDB_MULTIPLE_SUFFIXES
/* Allow renaming one suffix entry to another */
p_ndn = slap_empty_bv;
#else
/* There can only be one suffix entry */
rs->sr_err = LDAP_NAMING_VIOLATION;
rs->sr_text = "cannot rename suffix entry";
goto return_results;
#endif
} else {
dnParent( &e->e_nname, &p_ndn );
}
np_ndn = &p_ndn;
eip = ei->bei_parent;
if ( eip && eip->bei_id ) {
/* Make sure parent entry exist and we can write its
* children.
*/
rs->sr_err = bdb_cache_find_id( op, ltid,
eip->bei_id, &eip, 0, &plock );
switch( rs->sr_err ) {
case 0:
case DB_NOTFOUND:
break;
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
case LDAP_BUSY:
rs->sr_text = "ldap server busy";
goto return_results;
default:
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
p = eip->bei_e;
if( p == NULL) {
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn)
": parent does not exist\n" );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "old entry's parent does not exist";
goto return_results;
}
} else {
p = (Entry *)&slap_entry_root;
}
/* check parent for "children" acl */
rs->sr_err = access_allowed( op, p,
children, NULL,
op->oq_modrdn.rs_newSup == NULL ?
ACL_WRITE : ACL_WDEL,
NULL );
if ( !p_ndn.bv_len )
p = NULL;
if ( ! rs->sr_err ) {
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
Debug( LDAP_DEBUG_TRACE, "no access to parent\n" );
rs->sr_text = "no write access to old parent's children";
goto return_results;
}
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_modrdn) ": wr to children "
"of entry %s OK\n", p_ndn.bv_val );
if ( p_ndn.bv_val == slap_empty_bv.bv_val ) {
p_dn = slap_empty_bv;
} else {
dnParent( &e->e_name, &p_dn );
}
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_modrdn) ": parent dn=%s\n",
p_dn.bv_val );
new_parent_dn = &p_dn; /* New Parent unless newSuperior given */
if ( op->oq_modrdn.rs_newSup != NULL ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_modrdn)
": new parent \"%s\" requested...\n",
op->oq_modrdn.rs_newSup->bv_val );
/* newSuperior == oldParent? */
if( dn_match( &p_ndn, op->oq_modrdn.rs_nnewSup ) ) {
Debug( LDAP_DEBUG_TRACE, "bdb_back_modrdn: "
"new parent \"%s\" same as the old parent \"%s\"\n",
op->oq_modrdn.rs_newSup->bv_val, p_dn.bv_val );
op->oq_modrdn.rs_newSup = NULL; /* ignore newSuperior */
}
}
/* There's a BDB_MULTIPLE_SUFFIXES case here that this code doesn't
* support. E.g., two suffixes dc=foo,dc=com and dc=bar,dc=net.
* We do not allow modDN
* dc=foo,dc=com
* newrdn dc=bar
* newsup dc=net
* and we probably should. But since MULTIPLE_SUFFIXES is deprecated
* I'm ignoring this problem for now.
*/
if ( op->oq_modrdn.rs_newSup != NULL ) {
if ( op->oq_modrdn.rs_newSup->bv_len ) {
np_dn = op->oq_modrdn.rs_newSup;
np_ndn = op->oq_modrdn.rs_nnewSup;
/* newSuperior == oldParent? - checked above */
/* newSuperior == entry being moved?, if so ==> ERROR */
if ( dnIsSuffix( np_ndn, &e->e_nname )) {
rs->sr_err = LDAP_NO_SUCH_OBJECT;
rs->sr_text = "new superior not found";
goto return_results;
}
/* Get Entry with dn=newSuperior. Does newSuperior exist? */
rs->sr_err = bdb_dn2entry( op, ltid, np_ndn,
&neip, 0, &nplock );
switch( rs->sr_err ) {
case 0: np = neip->bei_e;
case DB_NOTFOUND:
break;
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
case LDAP_BUSY:
rs->sr_text = "ldap server busy";
goto return_results;
default:
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
if( np == NULL) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_modrdn)
": newSup(ndn=%s) not here!\n",
np_ndn->bv_val );
rs->sr_text = "new superior not found";
rs->sr_err = LDAP_NO_SUCH_OBJECT;
goto return_results;
}
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_modrdn)
": wr to new parent OK np=%p, id=%ld\n",
(void *) np, (long) np->e_id );
/* check newSuperior for "children" acl */
rs->sr_err = access_allowed( op, np, children,
NULL, ACL_WADD, NULL );
if( ! rs->sr_err ) {
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_modrdn)
": no wr to newSup children\n" );
rs->sr_text = "no write access to new superior's children";
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
goto return_results;
}
if ( is_entry_alias( np ) ) {
/* parent is an alias, don't allow add */
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_modrdn)
": entry is alias\n" );
rs->sr_text = "new superior is an alias";
rs->sr_err = LDAP_ALIAS_PROBLEM;
goto return_results;
}
if ( is_entry_referral( np ) ) {
/* parent is a referral, don't allow add */
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_modrdn)
": entry is referral\n" );
rs->sr_text = "new superior is a referral";
rs->sr_err = LDAP_OTHER;
goto return_results;
}
} else {
np_dn = NULL;
/* no parent, modrdn entry directly under root */
if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv )
|| be_isupdate( op ) ) {
np = (Entry *)&slap_entry_root;
/* check parent for "children" acl */
rs->sr_err = access_allowed( op, np,
children, NULL, ACL_WADD, NULL );
np = NULL;
if ( ! rs->sr_err ) {
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
Debug( LDAP_DEBUG_TRACE,
"no access to new superior\n" );
rs->sr_text =
"no write access to new superior's children";
goto return_results;
}
}
}
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_modrdn)
": wr to new parent's children OK\n" );
new_parent_dn = np_dn;
}
/* Build target dn and make sure target entry doesn't exist already. */
if (!new_dn.bv_val) {
build_new_dn( &new_dn, new_parent_dn, &op->oq_modrdn.rs_newrdn, NULL );
}
if (!new_ndn.bv_val) {
struct berval bv = {0, NULL};
dnNormalize( 0, NULL, NULL, &new_dn, &bv, op->o_tmpmemctx );
ber_dupbv( &new_ndn, &bv );
/* FIXME: why not call dnNormalize() w/o ctx? */
op->o_tmpfree( bv.bv_val, op->o_tmpmemctx );
}
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn) ": new ndn=%s\n",
new_ndn.bv_val );
/* Shortcut the search */
nei = neip ? neip : eip;
rs->sr_err = bdb_cache_find_ndn ( op, ltid, &new_ndn, &nei );
if ( nei ) bdb_cache_entryinfo_unlock( nei );
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
case DB_NOTFOUND:
break;
case 0:
/* Allow rename to same DN */
if ( nei == ei )
break;
rs->sr_err = LDAP_ALREADY_EXISTS;
goto return_results;
default:
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
if( op->o_preread ) {
if( preread_ctrl == NULL ) {
preread_ctrl = &ctrls[num_ctrls++];
ctrls[num_ctrls] = NULL;
}
if( slap_read_controls( op, rs, e,
&slap_pre_read_bv, preread_ctrl ) )
{
Debug( LDAP_DEBUG_TRACE,
"<=- " LDAP_XSTRING(bdb_modrdn)
": pre-read failed!\n" );
if ( op->o_preread & SLAP_CONTROL_CRITICAL ) {
/* FIXME: is it correct to abort
* operation if control fails? */
goto return_results;
}
}
}
/* nested transaction */
rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, &lt2, bdb->bi_db_opflags );
rs->sr_text = NULL;
if( rs->sr_err != 0 ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_modrdn)
": txn_begin(2) failed: %s (%d)\n",
db_strerror(rs->sr_err), rs->sr_err );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn) ": txn2 id: %x\n",
lt2->id(lt2) );
/* delete old DN */
rs->sr_err = bdb_dn2id_delete( op, lt2, eip, e );
if ( rs->sr_err != 0 ) {
Debug(LDAP_DEBUG_TRACE,
"<=- " LDAP_XSTRING(bdb_modrdn)
": dn2id del failed: %s (%d)\n",
db_strerror(rs->sr_err), rs->sr_err );
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
rs->sr_err = LDAP_OTHER;
rs->sr_text = "DN index delete fail";
goto return_results;
}
/* copy the entry, then override some fields */
dummy = *e;
dummy.e_name = new_dn;
dummy.e_nname = new_ndn;
dummy.e_attrs = NULL;
/* add new DN */
rs->sr_err = bdb_dn2id_add( op, lt2, neip ? neip : eip, &dummy );
if ( rs->sr_err != 0 ) {
Debug(LDAP_DEBUG_TRACE,
"<=- " LDAP_XSTRING(bdb_modrdn)
": dn2id add failed: %s (%d)\n",
db_strerror(rs->sr_err), rs->sr_err );
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
rs->sr_err = LDAP_OTHER;
rs->sr_text = "DN index add failed";
goto return_results;
}
dummy.e_attrs = e->e_attrs;
if( op->orr_modlist != NULL ) {
/* modify entry */
rs->sr_err = bdb_modify_internal( op, lt2, op->orr_modlist, &dummy,
&rs->sr_text, textbuf, textlen );
if( rs->sr_err != LDAP_SUCCESS ) {
Debug(LDAP_DEBUG_TRACE,
"<=- " LDAP_XSTRING(bdb_modrdn)
": modify failed: %s (%d)\n",
db_strerror(rs->sr_err), rs->sr_err );
if ( ( rs->sr_err == LDAP_INSUFFICIENT_ACCESS ) && opinfo.boi_err ) {
rs->sr_err = opinfo.boi_err;
}
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
goto return_results;
}
}
/* id2entry index */
rs->sr_err = bdb_id2entry_update( op->o_bd, lt2, &dummy );
if ( rs->sr_err != 0 ) {
Debug(LDAP_DEBUG_TRACE,
"<=- " LDAP_XSTRING(bdb_modrdn)
": id2entry failed: %s (%d)\n",
db_strerror(rs->sr_err), rs->sr_err );
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
rs->sr_err = LDAP_OTHER;
rs->sr_text = "entry update failed";
goto return_results;
}
if ( p_ndn.bv_len != 0 ) {
parent_is_glue = is_entry_glue(p);
rs->sr_err = bdb_cache_children( op, lt2, p );
if ( rs->sr_err != DB_NOTFOUND ) {
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
case 0:
break;
default:
Debug(LDAP_DEBUG_ARGS,
"<=- " LDAP_XSTRING(bdb_modrdn)
": has_children failed: %s (%d)\n",
db_strerror(rs->sr_err), rs->sr_err );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
parent_is_leaf = 1;
}
bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
p = NULL;
}
if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
rs->sr_err = LDAP_OTHER;
rs->sr_text = "txn_commit(2) failed";
goto return_results;
}
if( op->o_postread ) {
if( postread_ctrl == NULL ) {
postread_ctrl = &ctrls[num_ctrls++];
ctrls[num_ctrls] = NULL;
}
if( slap_read_controls( op, rs, &dummy,
&slap_post_read_bv, postread_ctrl ) )
{
Debug( LDAP_DEBUG_TRACE,
"<=- " LDAP_XSTRING(bdb_modrdn)
": post-read failed!\n" );
if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
/* FIXME: is it correct to abort
* operation if control fails? */
goto return_results;
}
}
}
if( op->o_noop ) {
if(( rs->sr_err=TXN_ABORT( ltid )) != 0 ) {
rs->sr_text = "txn_abort (no-op) failed";
} else {
rs->sr_err = LDAP_X_NO_OPERATION;
ltid = NULL;
goto return_results;
}
} else {
rc = bdb_cache_modrdn( bdb, e, &op->orr_nnewrdn, &dummy, neip,
ltid, &lock );
switch( rc ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
}
dummy.e_attrs = NULL;
new_dn.bv_val = NULL;
new_ndn.bv_val = NULL;
if(( rs->sr_err=TXN_COMMIT( ltid, 0 )) != 0 ) {
rs->sr_text = "txn_commit failed";
} else {
rs->sr_err = LDAP_SUCCESS;
}
}
ltid = NULL;
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
opinfo.boi_oe.oe_key = NULL;
if( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_modrdn) ": %s : %s (%d)\n",
rs->sr_text, db_strerror(rs->sr_err), rs->sr_err );
rs->sr_err = LDAP_OTHER;
goto return_results;
}
Debug(LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_modrdn)
": rdn modified%s id=%08lx dn=\"%s\"\n",
op->o_noop ? " (no-op)" : "",
dummy.e_id, op->o_req_dn.bv_val );
rs->sr_text = NULL;
if( num_ctrls ) rs->sr_ctrls = ctrls;
return_results:
if ( dummy.e_attrs != e->e_attrs ) {
attrs_free( dummy.e_attrs );
}
send_ldap_result( op, rs );
if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp_kbyte ) {
TXN_CHECKPOINT( bdb->bi_dbenv,
bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
}
if ( rs->sr_err == LDAP_SUCCESS && parent_is_glue && parent_is_leaf ) {
op->o_delete_glue_parent = 1;
}
done:
slap_graduate_commit_csn( op );
if( new_dn.bv_val != NULL ) free( new_dn.bv_val );
if( new_ndn.bv_val != NULL ) free( new_ndn.bv_val );
/* LDAP v3 Support */
if( np != NULL ) {
/* free new parent and reader lock */
bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, np);
}
if( p != NULL ) {
/* free parent and reader lock */
bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
}
/* free entry */
if( e != NULL ) {
bdb_unlocked_cache_return_entry_w( &bdb->bi_cache, e);
}
if( ltid != NULL ) {
TXN_ABORT( ltid );
}
if ( opinfo.boi_oe.oe_key ) {
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
}
if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) {
slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
slap_sl_free( *preread_ctrl, op->o_tmpmemctx );
}
if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) {
slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
}
return rs->sr_err;
}

View File

@ -1,723 +0,0 @@
/* monitor.c - monitor bdb backend */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2000-2019 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include <ac/unistd.h>
#include <ac/stdlib.h>
#include <ac/errno.h>
#include <sys/stat.h>
#include "lutil.h"
#include "back-bdb.h"
#include "../back-monitor/back-monitor.h"
#include "config.h"
static ObjectClass *oc_olmBDBDatabase;
static AttributeDescription *ad_olmBDBEntryCache,
*ad_olmBDBDNCache, *ad_olmBDBIDLCache,
*ad_olmDbDirectory;
#ifdef BDB_MONITOR_IDX
static int
bdb_monitor_idx_entry_add(
struct bdb_info *bdb,
Entry *e );
static AttributeDescription *ad_olmDbNotIndexed;
#endif /* BDB_MONITOR_IDX */
/*
* NOTE: there's some confusion in monitor OID arc;
* by now, let's consider:
*
* Subsystems monitor attributes 1.3.6.1.4.1.4203.666.1.55.0
* Databases monitor attributes 1.3.6.1.4.1.4203.666.1.55.0.1
* BDB database monitor attributes 1.3.6.1.4.1.4203.666.1.55.0.1.1
*
* Subsystems monitor objectclasses 1.3.6.1.4.1.4203.666.3.16.0
* Databases monitor objectclasses 1.3.6.1.4.1.4203.666.3.16.0.1
* BDB database monitor objectclasses 1.3.6.1.4.1.4203.666.3.16.0.1.1
*/
static struct {
char *name;
char *oid;
} s_oid[] = {
{ "olmBDBAttributes", "olmDatabaseAttributes:1" },
{ "olmBDBObjectClasses", "olmDatabaseObjectClasses:1" },
{ NULL }
};
static struct {
char *desc;
AttributeDescription **ad;
} s_at[] = {
{ "( olmBDBAttributes:1 "
"NAME ( 'olmBDBEntryCache' ) "
"DESC 'Number of items in Entry Cache' "
"SUP monitorCounter "
"NO-USER-MODIFICATION "
"USAGE dSAOperation )",
&ad_olmBDBEntryCache },
{ "( olmBDBAttributes:2 "
"NAME ( 'olmBDBDNCache' ) "
"DESC 'Number of items in DN Cache' "
"SUP monitorCounter "
"NO-USER-MODIFICATION "
"USAGE dSAOperation )",
&ad_olmBDBDNCache },
{ "( olmBDBAttributes:3 "
"NAME ( 'olmBDBIDLCache' ) "
"DESC 'Number of items in IDL Cache' "
"SUP monitorCounter "
"NO-USER-MODIFICATION "
"USAGE dSAOperation )",
&ad_olmBDBIDLCache },
{ "( olmDatabaseAttributes:1 "
"NAME ( 'olmDbDirectory' ) "
"DESC 'Path name of the directory "
"where the database environment resides' "
"SUP monitoredInfo "
"NO-USER-MODIFICATION "
"USAGE dSAOperation )",
&ad_olmDbDirectory },
#ifdef BDB_MONITOR_IDX
{ "( olmDatabaseAttributes:2 "
"NAME ( 'olmDbNotIndexed' ) "
"DESC 'Missing indexes resulting from candidate selection' "
"SUP monitoredInfo "
"NO-USER-MODIFICATION "
"USAGE dSAOperation )",
&ad_olmDbNotIndexed },
#endif /* BDB_MONITOR_IDX */
{ NULL }
};
static struct {
char *desc;
ObjectClass **oc;
} s_oc[] = {
/* augments an existing object, so it must be AUXILIARY
* FIXME: derive from some ABSTRACT "monitoredEntity"? */
{ "( olmBDBObjectClasses:1 "
"NAME ( 'olmBDBDatabase' ) "
"SUP top AUXILIARY "
"MAY ( "
"olmBDBEntryCache "
"$ olmBDBDNCache "
"$ olmBDBIDLCache "
"$ olmDbDirectory "
#ifdef BDB_MONITOR_IDX
"$ olmDbNotIndexed "
#endif /* BDB_MONITOR_IDX */
") )",
&oc_olmBDBDatabase },
{ NULL }
};
static int
bdb_monitor_update(
Operation *op,
SlapReply *rs,
Entry *e,
void *priv )
{
struct bdb_info *bdb = (struct bdb_info *) priv;
Attribute *a;
char buf[ BUFSIZ ];
struct berval bv;
assert( ad_olmBDBEntryCache != NULL );
a = attr_find( e->e_attrs, ad_olmBDBEntryCache );
assert( a != NULL );
bv.bv_val = buf;
bv.bv_len = snprintf( buf, sizeof( buf ), "%lu", bdb->bi_cache.c_cursize );
ber_bvreplace( &a->a_vals[ 0 ], &bv );
a = attr_find( e->e_attrs, ad_olmBDBDNCache );
assert( a != NULL );
bv.bv_len = snprintf( buf, sizeof( buf ), "%lu", bdb->bi_cache.c_eiused );
ber_bvreplace( &a->a_vals[ 0 ], &bv );
a = attr_find( e->e_attrs, ad_olmBDBIDLCache );
assert( a != NULL );
bv.bv_len = snprintf( buf, sizeof( buf ), "%lu", bdb->bi_idl_cache_size );
ber_bvreplace( &a->a_vals[ 0 ], &bv );
#ifdef BDB_MONITOR_IDX
bdb_monitor_idx_entry_add( bdb, e );
#endif /* BDB_MONITOR_IDX */
return SLAP_CB_CONTINUE;
}
#if 0 /* uncomment if required */
static int
bdb_monitor_modify(
Operation *op,
SlapReply *rs,
Entry *e,
void *priv )
{
return SLAP_CB_CONTINUE;
}
#endif
static int
bdb_monitor_free(
Entry *e,
void **priv )
{
struct berval values[ 2 ];
Modification mod = { 0 };
const char *text;
char textbuf[ SLAP_TEXT_BUFLEN ];
int i, rc;
/* NOTE: if slap_shutdown != 0, priv might have already been freed */
*priv = NULL;
/* Remove objectClass */
mod.sm_op = LDAP_MOD_DELETE;
mod.sm_desc = slap_schema.si_ad_objectClass;
mod.sm_values = values;
mod.sm_numvals = 1;
values[ 0 ] = oc_olmBDBDatabase->soc_cname;
BER_BVZERO( &values[ 1 ] );
rc = modify_delete_values( e, &mod, 1, &text,
textbuf, sizeof( textbuf ) );
/* don't care too much about return code... */
/* remove attrs */
mod.sm_values = NULL;
mod.sm_numvals = 0;
for ( i = 0; s_at[ i ].desc != NULL; i++ ) {
mod.sm_desc = *s_at[ i ].ad;
rc = modify_delete_values( e, &mod, 1, &text,
textbuf, sizeof( textbuf ) );
/* don't care too much about return code... */
}
return SLAP_CB_CONTINUE;
}
#define bdb_monitor_initialize BDB_SYMBOL(monitor_initialize)
/*
* call from within bdb_initialize()
*/
static int
bdb_monitor_initialize( void )
{
int i, code;
ConfigArgs c;
char *argv[ 3 ];
static int bdb_monitor_initialized = 0;
/* set to 0 when successfully initialized; otherwise, remember failure */
static int bdb_monitor_initialized_failure = 1;
if ( bdb_monitor_initialized++ ) {
return bdb_monitor_initialized_failure;
}
if ( backend_info( "monitor" ) == NULL ) {
return -1;
}
/* register schema here */
argv[ 0 ] = "back-bdb/back-hdb monitor";
c.argv = argv;
c.argc = 3;
c.fname = argv[0];
for ( i = 0; s_oid[ i ].name; i++ ) {
c.lineno = i;
argv[ 1 ] = s_oid[ i ].name;
argv[ 2 ] = s_oid[ i ].oid;
if ( parse_oidm( &c, 0, NULL ) != 0 ) {
Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_monitor_initialize)
": unable to add "
"objectIdentifier \"%s=%s\"\n",
s_oid[ i ].name, s_oid[ i ].oid );
return 2;
}
}
for ( i = 0; s_at[ i ].desc != NULL; i++ ) {
code = register_at( s_at[ i ].desc, s_at[ i ].ad, 1 );
if ( code != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_monitor_initialize)
": register_at failed for attributeType (%s)\n",
s_at[ i ].desc );
return 3;
} else {
(*s_at[ i ].ad)->ad_type->sat_flags |= SLAP_AT_HIDE;
}
}
for ( i = 0; s_oc[ i ].desc != NULL; i++ ) {
code = register_oc( s_oc[ i ].desc, s_oc[ i ].oc, 1 );
if ( code != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_monitor_initialize)
": register_oc failed for objectClass (%s)\n",
s_oc[ i ].desc );
return 4;
} else {
(*s_oc[ i ].oc)->soc_flags |= SLAP_OC_HIDE;
}
}
return ( bdb_monitor_initialized_failure = LDAP_SUCCESS );
}
/*
* call from within bdb_db_init()
*/
int
bdb_monitor_db_init( BackendDB *be )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
if ( bdb_monitor_initialize() == LDAP_SUCCESS ) {
/* monitoring in back-bdb is on by default */
SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_MONITORING;
}
#ifdef BDB_MONITOR_IDX
bdb->bi_idx = NULL;
ldap_pvt_thread_mutex_init( &bdb->bi_idx_mutex );
#endif /* BDB_MONITOR_IDX */
return 0;
}
/*
* call from within bdb_db_open()
*/
int
bdb_monitor_db_open( BackendDB *be )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
Attribute *a, *next;
monitor_callback_t *cb = NULL;
int rc = 0;
BackendInfo *mi;
monitor_extra_t *mbe;
if ( !SLAP_DBMONITORING( be ) ) {
return 0;
}
mi = backend_info( "monitor" );
if ( !mi || !mi->bi_extra ) {
SLAP_DBFLAGS( be ) ^= SLAP_DBFLAG_MONITORING;
return 0;
}
mbe = mi->bi_extra;
/* don't bother if monitor is not configured */
if ( !mbe->is_configured() ) {
static int warning = 0;
if ( warning++ == 0 ) {
Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_monitor_db_open)
": monitoring disabled; "
"configure monitor database to enable\n" );
}
return 0;
}
/* alloc as many as required (plus 1 for objectClass) */
a = attrs_alloc( 1 + 4 );
if ( a == NULL ) {
rc = 1;
goto cleanup;
}
a->a_desc = slap_schema.si_ad_objectClass;
attr_valadd( a, &oc_olmBDBDatabase->soc_cname, NULL, 1 );
next = a->a_next;
{
struct berval bv = BER_BVC( "0" );
next->a_desc = ad_olmBDBEntryCache;
attr_valadd( next, &bv, NULL, 1 );
next = next->a_next;
next->a_desc = ad_olmBDBDNCache;
attr_valadd( next, &bv, NULL, 1 );
next = next->a_next;
next->a_desc = ad_olmBDBIDLCache;
attr_valadd( next, &bv, NULL, 1 );
next = next->a_next;
}
{
struct berval bv, nbv;
ber_len_t pathlen = 0, len = 0;
char path[ MAXPATHLEN ] = { '\0' };
char *fname = bdb->bi_dbenv_home,
*ptr;
len = strlen( fname );
if ( fname[ 0 ] != '/' ) {
/* get full path name */
getcwd( path, sizeof( path ) );
pathlen = strlen( path );
if ( fname[ 0 ] == '.' && fname[ 1 ] == '/' ) {
fname += 2;
len -= 2;
}
}
bv.bv_len = pathlen + STRLENOF( "/" ) + len;
ptr = bv.bv_val = ch_malloc( bv.bv_len + STRLENOF( "/" ) + 1 );
if ( pathlen ) {
ptr = lutil_strncopy( ptr, path, pathlen );
ptr[ 0 ] = '/';
ptr++;
}
ptr = lutil_strncopy( ptr, fname, len );
if ( ptr[ -1 ] != '/' ) {
ptr[ 0 ] = '/';
ptr++;
}
ptr[ 0 ] = '\0';
attr_normalize_one( ad_olmDbDirectory, &bv, &nbv, NULL );
next->a_desc = ad_olmDbDirectory;
next->a_vals = ch_calloc( sizeof( struct berval ), 2 );
next->a_vals[ 0 ] = bv;
next->a_numvals = 1;
if ( BER_BVISNULL( &nbv ) ) {
next->a_nvals = next->a_vals;
} else {
next->a_nvals = ch_calloc( sizeof( struct berval ), 2 );
next->a_nvals[ 0 ] = nbv;
}
next = next->a_next;
}
cb = ch_calloc( sizeof( monitor_callback_t ), 1 );
cb->mc_update = bdb_monitor_update;
#if 0 /* uncomment if required */
cb->mc_modify = bdb_monitor_modify;
#endif
cb->mc_free = bdb_monitor_free;
cb->mc_private = (void *)bdb;
/* make sure the database is registered; then add monitor attributes */
rc = mbe->register_database( be, &bdb->bi_monitor.bdm_ndn );
if ( rc == 0 ) {
rc = mbe->register_entry_attrs( &bdb->bi_monitor.bdm_ndn, a, cb,
NULL, 0, NULL );
}
cleanup:;
if ( rc != 0 ) {
if ( cb != NULL ) {
ch_free( cb );
cb = NULL;
}
if ( a != NULL ) {
attrs_free( a );
a = NULL;
}
}
/* store for cleanup */
bdb->bi_monitor.bdm_cb = (void *)cb;
/* we don't need to keep track of the attributes, because
* bdb_monitor_free() takes care of everything */
if ( a != NULL ) {
attrs_free( a );
}
return rc;
}
/*
* call from within bdb_db_close()
*/
int
bdb_monitor_db_close( BackendDB *be )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
if ( !BER_BVISNULL( &bdb->bi_monitor.bdm_ndn ) ) {
BackendInfo *mi = backend_info( "monitor" );
monitor_extra_t *mbe;
if ( mi && mi->bi_extra ) {
mbe = mi->bi_extra;
mbe->unregister_entry_callback( &bdb->bi_monitor.bdm_ndn,
(monitor_callback_t *)bdb->bi_monitor.bdm_cb,
NULL, 0, NULL );
}
memset( &bdb->bi_monitor, 0, sizeof( bdb->bi_monitor ) );
}
return 0;
}
/*
* call from within bdb_db_destroy()
*/
int
bdb_monitor_db_destroy( BackendDB *be )
{
#ifdef BDB_MONITOR_IDX
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
/* TODO: free tree */
ldap_pvt_thread_mutex_destroy( &bdb->bi_idx_mutex );
avl_free( bdb->bi_idx, ch_free );
#endif /* BDB_MONITOR_IDX */
return 0;
}
#ifdef BDB_MONITOR_IDX
#define BDB_MONITOR_IDX_TYPES (4)
typedef struct monitor_idx_t monitor_idx_t;
struct monitor_idx_t {
AttributeDescription *idx_ad;
unsigned long idx_count[BDB_MONITOR_IDX_TYPES];
};
static int
bdb_monitor_bitmask2key( slap_mask_t bitmask )
{
int key;
for ( key = 0; key < 8 * (int)sizeof(slap_mask_t) && !( bitmask & 0x1U );
key++ )
bitmask >>= 1;
return key;
}
static struct berval idxbv[] = {
BER_BVC( "present=" ),
BER_BVC( "equality=" ),
BER_BVC( "approx=" ),
BER_BVC( "substr=" ),
BER_BVNULL
};
static ber_len_t
bdb_monitor_idx2len( monitor_idx_t *idx )
{
int i;
ber_len_t len = 0;
for ( i = 0; i < BDB_MONITOR_IDX_TYPES; i++ ) {
if ( idx->idx_count[ i ] != 0 ) {
len += idxbv[i].bv_len;
}
}
return len;
}
static int
monitor_idx_cmp( const void *p1, const void *p2 )
{
const monitor_idx_t *idx1 = (const monitor_idx_t *)p1;
const monitor_idx_t *idx2 = (const monitor_idx_t *)p2;
return SLAP_PTRCMP( idx1->idx_ad, idx2->idx_ad );
}
static int
monitor_idx_dup( void *p1, void *p2 )
{
monitor_idx_t *idx1 = (monitor_idx_t *)p1;
monitor_idx_t *idx2 = (monitor_idx_t *)p2;
return SLAP_PTRCMP( idx1->idx_ad, idx2->idx_ad ) == 0 ? -1 : 0;
}
int
bdb_monitor_idx_add(
struct bdb_info *bdb,
AttributeDescription *desc,
slap_mask_t type )
{
monitor_idx_t idx_dummy = { 0 },
*idx;
int rc = 0, key;
idx_dummy.idx_ad = desc;
key = bdb_monitor_bitmask2key( type ) - 1;
if ( key >= BDB_MONITOR_IDX_TYPES ) {
/* invalid index type */
return -1;
}
ldap_pvt_thread_mutex_lock( &bdb->bi_idx_mutex );
idx = (monitor_idx_t *)avl_find( bdb->bi_idx,
(caddr_t)&idx_dummy, monitor_idx_cmp );
if ( idx == NULL ) {
idx = (monitor_idx_t *)ch_calloc( sizeof( monitor_idx_t ), 1 );
idx->idx_ad = desc;
idx->idx_count[ key ] = 1;
switch ( avl_insert( &bdb->bi_idx, (caddr_t)idx,
monitor_idx_cmp, monitor_idx_dup ) )
{
case 0:
break;
default:
ch_free( idx );
rc = -1;
}
} else {
idx->idx_count[ key ]++;
}
ldap_pvt_thread_mutex_unlock( &bdb->bi_idx_mutex );
return rc;
}
static int
bdb_monitor_idx_apply( void *v_idx, void *v_valp )
{
monitor_idx_t *idx = (monitor_idx_t *)v_idx;
BerVarray *valp = (BerVarray *)v_valp;
struct berval bv;
char *ptr;
char count_buf[ BDB_MONITOR_IDX_TYPES ][ SLAP_TEXT_BUFLEN ];
ber_len_t count_len[ BDB_MONITOR_IDX_TYPES ],
idx_len;
int i, num = 0;
idx_len = bdb_monitor_idx2len( idx );
bv.bv_len = 0;
for ( i = 0; i < BDB_MONITOR_IDX_TYPES; i++ ) {
if ( idx->idx_count[ i ] == 0 ) {
continue;
}
count_len[ i ] = snprintf( count_buf[ i ],
sizeof( count_buf[ i ] ), "%lu", idx->idx_count[ i ] );
bv.bv_len += count_len[ i ];
num++;
}
bv.bv_len += idx->idx_ad->ad_cname.bv_len
+ num
+ idx_len;
ptr = bv.bv_val = ch_malloc( bv.bv_len + 1 );
ptr = lutil_strcopy( ptr, idx->idx_ad->ad_cname.bv_val );
for ( i = 0; i < BDB_MONITOR_IDX_TYPES; i++ ) {
if ( idx->idx_count[ i ] == 0 ) {
continue;
}
ptr[ 0 ] = '#';
++ptr;
ptr = lutil_strcopy( ptr, idxbv[ i ].bv_val );
ptr = lutil_strcopy( ptr, count_buf[ i ] );
}
ber_bvarray_add( valp, &bv );
return 0;
}
static int
bdb_monitor_idx_entry_add(
struct bdb_info *bdb,
Entry *e )
{
BerVarray vals = NULL;
Attribute *a;
a = attr_find( e->e_attrs, ad_olmDbNotIndexed );
ldap_pvt_thread_mutex_lock( &bdb->bi_idx_mutex );
avl_apply( bdb->bi_idx, bdb_monitor_idx_apply,
&vals, -1, AVL_INORDER );
ldap_pvt_thread_mutex_unlock( &bdb->bi_idx_mutex );
if ( vals != NULL ) {
if ( a != NULL ) {
assert( a->a_nvals == a->a_vals );
ber_bvarray_free( a->a_vals );
} else {
Attribute **ap;
for ( ap = &e->e_attrs; *ap != NULL; ap = &(*ap)->a_next )
;
*ap = attr_alloc( ad_olmDbNotIndexed );
a = *ap;
}
a->a_vals = vals;
a->a_nvals = a->a_vals;
}
return 0;
}
#endif /* BDB_MONITOR_IDX */

View File

@ -1,80 +0,0 @@
/* init.c - initialize bdb backend */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2000-2019 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include "back-bdb.h"
int bdb_next_id( BackendDB *be, ID *out )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
ldap_pvt_thread_mutex_lock( &bdb->bi_lastid_mutex );
*out = ++bdb->bi_lastid;
ldap_pvt_thread_mutex_unlock( &bdb->bi_lastid_mutex );
return 0;
}
int bdb_last_id( BackendDB *be, DB_TXN *tid )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
int rc;
ID id = 0;
unsigned char idbuf[sizeof(ID)];
DBT key, data;
DBC *cursor;
DBTzero( &key );
key.flags = DB_DBT_USERMEM;
key.data = (char *) idbuf;
key.ulen = sizeof( idbuf );
DBTzero( &data );
data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
/* Get a read cursor */
rc = bdb->bi_id2entry->bdi_db->cursor( bdb->bi_id2entry->bdi_db,
tid, &cursor, 0 );
if (rc == 0) {
rc = cursor->c_get(cursor, &key, &data, DB_LAST);
cursor->c_close(cursor);
}
switch(rc) {
case DB_NOTFOUND:
rc = 0;
break;
case 0:
BDB_DISK2ID( idbuf, &id );
break;
default:
Debug( LDAP_DEBUG_ANY,
"=> bdb_last_id: get failed: %s (%d)\n",
db_strerror(rc), rc );
goto done;
}
bdb->bi_lastid = id;
done:
return rc;
}

View File

@ -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-2019 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include <ac/socket.h>
#include "slap.h"
#include "back-bdb.h"
/*
* sets *hasSubordinates to LDAP_COMPARE_TRUE/LDAP_COMPARE_FALSE
* if the entry has children or not.
*/
int
bdb_hasSubordinates(
Operation *op,
Entry *e,
int *hasSubordinates )
{
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
struct bdb_op_info *opinfo;
OpExtra *oex;
DB_TXN *rtxn;
int rc;
int release = 0;
assert( e != NULL );
/* NOTE: this should never happen, but it actually happens
* when using back-relay; until we find a better way to
* preserve entry's private information while rewriting it,
* let's disable the hasSubordinate feature for back-relay.
*/
if ( BEI( e ) == NULL ) {
Entry *ee = NULL;
rc = be_entry_get_rw( op, &e->e_nname, NULL, NULL, 0, &ee );
if ( rc != LDAP_SUCCESS || ee == NULL ) {
rc = LDAP_OTHER;
goto done;
}
e = ee;
release = 1;
if ( BEI( ee ) == NULL ) {
rc = LDAP_OTHER;
goto done;
}
}
/* Check for a txn in a parent op, otherwise use reader txn */
LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
if ( oex->oe_key == bdb )
break;
}
opinfo = (struct bdb_op_info *) oex;
if ( opinfo && opinfo->boi_txn ) {
rtxn = opinfo->boi_txn;
} else {
rc = bdb_reader_get(op, bdb->bi_dbenv, &rtxn);
if ( rc ) {
rc = LDAP_OTHER;
goto done;
}
}
retry:
/* FIXME: we can no longer assume the entry's e_private
* field is correctly populated; so we need to reacquire
* it with reader lock */
rc = bdb_cache_children( op, rtxn, e );
switch( rc ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
case 0:
*hasSubordinates = LDAP_COMPARE_TRUE;
break;
case DB_NOTFOUND:
*hasSubordinates = LDAP_COMPARE_FALSE;
rc = LDAP_SUCCESS;
break;
default:
Debug(LDAP_DEBUG_ARGS,
"<=- " LDAP_XSTRING(bdb_hasSubordinates)
": has_children failed: %s (%d)\n",
db_strerror(rc), rc );
rc = LDAP_OTHER;
}
done:;
if ( release && e != NULL ) be_entry_release_r( op, e );
return rc;
}
/*
* sets the supported operational attributes (if required)
*/
int
bdb_operational(
Operation *op,
SlapReply *rs )
{
Attribute **ap;
assert( rs->sr_entry != NULL );
for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next ) {
if ( (*ap)->a_desc == slap_schema.si_ad_hasSubordinates ) {
break;
}
}
if ( *ap == NULL &&
attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_hasSubordinates ) == NULL &&
( SLAP_OPATTRS( rs->sr_attr_flags ) ||
ad_inlist( slap_schema.si_ad_hasSubordinates, rs->sr_attrs ) ) )
{
int hasSubordinates, rc;
rc = bdb_hasSubordinates( op, rs->sr_entry, &hasSubordinates );
if ( rc == LDAP_SUCCESS ) {
*ap = slap_operational_hasSubordinate( hasSubordinates == LDAP_COMPARE_TRUE );
assert( *ap != NULL );
ap = &(*ap)->a_next;
}
}
return LDAP_SUCCESS;
}

View File

@ -1,680 +0,0 @@
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2000-2019 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
#ifndef _PROTO_BDB_H
#define _PROTO_BDB_H
LDAP_BEGIN_DECL
#ifdef BDB_HIER
#define BDB_SYMBOL(x) LDAP_CONCAT(hdb_,x)
#define BDB_UCTYPE "HDB"
#else
#define BDB_SYMBOL(x) LDAP_CONCAT(bdb_,x)
#define BDB_UCTYPE "BDB"
#endif
/*
* attr.c
*/
#define bdb_attr_mask BDB_SYMBOL(attr_mask)
#define bdb_attr_flush BDB_SYMBOL(attr_flush)
#define bdb_attr_slot BDB_SYMBOL(attr_slot)
#define bdb_attr_index_config BDB_SYMBOL(attr_index_config)
#define bdb_attr_index_destroy BDB_SYMBOL(attr_index_destroy)
#define bdb_attr_index_free BDB_SYMBOL(attr_index_free)
#define bdb_attr_index_unparse BDB_SYMBOL(attr_index_unparse)
#define bdb_attr_info_free BDB_SYMBOL(attr_info_free)
AttrInfo *bdb_attr_mask( struct bdb_info *bdb,
AttributeDescription *desc );
void bdb_attr_flush( struct bdb_info *bdb );
int bdb_attr_slot( struct bdb_info *bdb,
AttributeDescription *desc, int *insert );
int bdb_attr_index_config LDAP_P(( struct bdb_info *bdb,
const char *fname, int lineno,
int argc, char **argv, struct config_reply_s *cr ));
void bdb_attr_index_unparse LDAP_P(( struct bdb_info *bdb, BerVarray *bva ));
void bdb_attr_index_destroy LDAP_P(( struct bdb_info *bdb ));
void bdb_attr_index_free LDAP_P(( struct bdb_info *bdb,
AttributeDescription *ad ));
void bdb_attr_info_free( AttrInfo *ai );
/*
* config.c
*/
#define bdb_back_init_cf BDB_SYMBOL(back_init_cf)
int bdb_back_init_cf( BackendInfo *bi );
/*
* dbcache.c
*/
#define bdb_db_cache BDB_SYMBOL(db_cache)
#define bdb_db_findsize BDB_SYMBOL(db_findsize)
int
bdb_db_cache(
Backend *be,
struct berval *name,
DB **db );
int
bdb_db_findsize(
struct bdb_info *bdb,
struct berval *name );
/*
* dn2entry.c
*/
#define bdb_dn2entry BDB_SYMBOL(dn2entry)
int bdb_dn2entry LDAP_P(( Operation *op, DB_TXN *tid,
struct berval *dn, EntryInfo **e, int matched,
DB_LOCK *lock ));
/*
* dn2id.c
*/
#define bdb_dn2id BDB_SYMBOL(dn2id)
#define bdb_dn2id_add BDB_SYMBOL(dn2id_add)
#define bdb_dn2id_delete BDB_SYMBOL(dn2id_delete)
#define bdb_dn2id_children BDB_SYMBOL(dn2id_children)
#define bdb_dn2idl BDB_SYMBOL(dn2idl)
int bdb_dn2id(
Operation *op,
struct berval *dn,
EntryInfo *ei,
DB_TXN *txn,
DBC **cursor );
int bdb_dn2id_add(
Operation *op,
DB_TXN *tid,
EntryInfo *eip,
Entry *e );
int bdb_dn2id_delete(
Operation *op,
DB_TXN *tid,
EntryInfo *eip,
Entry *e );
int bdb_dn2id_children(
Operation *op,
DB_TXN *tid,
Entry *e );
int bdb_dn2idl(
Operation *op,
DB_TXN *txn,
struct berval *ndn,
EntryInfo *ei,
ID *ids,
ID *stack );
#ifdef BDB_HIER
#define bdb_dn2id_parent BDB_SYMBOL(dn2id_parent)
#define bdb_dup_compare BDB_SYMBOL(dup_compare)
#define bdb_fix_dn BDB_SYMBOL(fix_dn)
int bdb_dn2id_parent(
Operation *op,
DB_TXN *txn,
EntryInfo *ei,
ID *idp );
int bdb_dup_compare(
DB *db,
const DBT *usrkey,
const DBT *curkey );
int bdb_fix_dn( Entry *e, int checkit );
#endif
/*
* error.c
*/
#define bdb_errcall BDB_SYMBOL(errcall)
#if DB_VERSION_FULL < 0x04030000
void bdb_errcall( const char *pfx, char * msg );
#else
#define bdb_msgcall BDB_SYMBOL(msgcall)
void bdb_errcall( const DB_ENV *env, const char *pfx, const char * msg );
void bdb_msgcall( const DB_ENV *env, const char * msg );
#endif
#ifdef HAVE_EBCDIC
#define ebcdic_dberror BDB_SYMBOL(ebcdic_dberror)
char *ebcdic_dberror( int rc );
#define db_strerror(x) ebcdic_dberror(x)
#endif
/*
* filterentry.c
*/
#define bdb_filter_candidates BDB_SYMBOL(filter_candidates)
int bdb_filter_candidates(
Operation *op,
DB_TXN *txn,
Filter *f,
ID *ids,
ID *tmp,
ID *stack );
/*
* id2entry.c
*/
#define bdb_id2entry BDB_SYMBOL(id2entry)
#define bdb_id2entry_add BDB_SYMBOL(id2entry_add)
#define bdb_id2entry_update BDB_SYMBOL(id2entry_update)
#define bdb_id2entry_delete BDB_SYMBOL(id2entry_delete)
int bdb_id2entry_add(
BackendDB *be,
DB_TXN *tid,
Entry *e );
int bdb_id2entry_update(
BackendDB *be,
DB_TXN *tid,
Entry *e );
int bdb_id2entry_delete(
BackendDB *be,
DB_TXN *tid,
Entry *e);
#ifdef SLAP_ZONE_ALLOC
#else
int bdb_id2entry(
BackendDB *be,
DB_TXN *tid,
ID id,
Entry **e);
#endif
#define bdb_entry_free BDB_SYMBOL(entry_free)
#define bdb_entry_return BDB_SYMBOL(entry_return)
#define bdb_entry_release BDB_SYMBOL(entry_release)
#define bdb_entry_get BDB_SYMBOL(entry_get)
void bdb_entry_free ( Entry *e );
#ifdef SLAP_ZONE_ALLOC
int bdb_entry_return( struct bdb_info *bdb, Entry *e, int seqno );
#else
int bdb_entry_return( Entry *e );
#endif
BI_entry_release_rw bdb_entry_release;
BI_entry_get_rw bdb_entry_get;
/*
* idl.c
*/
#define bdb_idl_cache_get BDB_SYMBOL(idl_cache_get)
#define bdb_idl_cache_put BDB_SYMBOL(idl_cache_put)
#define bdb_idl_cache_del BDB_SYMBOL(idl_cache_del)
#define bdb_idl_cache_add_id BDB_SYMBOL(idl_cache_add_id)
#define bdb_idl_cache_del_id BDB_SYMBOL(idl_cache_del_id)
int bdb_idl_cache_get(
struct bdb_info *bdb,
DB *db,
DBT *key,
ID *ids );
void
bdb_idl_cache_put(
struct bdb_info *bdb,
DB *db,
DBT *key,
ID *ids,
int rc );
void
bdb_idl_cache_del(
struct bdb_info *bdb,
DB *db,
DBT *key );
void
bdb_idl_cache_add_id(
struct bdb_info *bdb,
DB *db,
DBT *key,
ID id );
void
bdb_idl_cache_del_id(
struct bdb_info *bdb,
DB *db,
DBT *key,
ID id );
#define bdb_idl_first BDB_SYMBOL(idl_first)
#define bdb_idl_next BDB_SYMBOL(idl_next)
#define bdb_idl_search BDB_SYMBOL(idl_search)
#define bdb_idl_insert BDB_SYMBOL(idl_insert)
#define bdb_idl_delete BDB_SYMBOL(idl_delete)
#define bdb_idl_intersection BDB_SYMBOL(idl_intersection)
#define bdb_idl_union BDB_SYMBOL(idl_union)
#define bdb_idl_sort BDB_SYMBOL(idl_sort)
#define bdb_idl_append BDB_SYMBOL(idl_append)
#define bdb_idl_append_one BDB_SYMBOL(idl_append_one)
#define bdb_idl_fetch_key BDB_SYMBOL(idl_fetch_key)
#define bdb_idl_insert_key BDB_SYMBOL(idl_insert_key)
#define bdb_idl_delete_key BDB_SYMBOL(idl_delete_key)
unsigned bdb_idl_search( ID *ids, ID id );
int bdb_idl_fetch_key(
BackendDB *be,
DB *db,
DB_TXN *txn,
DBT *key,
ID *ids,
DBC **saved_cursor,
int get_flag );
int bdb_idl_insert( ID *ids, ID id );
int bdb_idl_delete( ID *ids, ID id );
int bdb_idl_insert_key(
BackendDB *be,
DB *db,
DB_TXN *txn,
DBT *key,
ID id );
int bdb_idl_delete_key(
BackendDB *be,
DB *db,
DB_TXN *txn,
DBT *key,
ID id );
int
bdb_idl_intersection(
ID *a,
ID *b );
int
bdb_idl_union(
ID *a,
ID *b );
ID bdb_idl_first( ID *ids, ID *cursor );
ID bdb_idl_next( ID *ids, ID *cursor );
void bdb_idl_sort( ID *ids, ID *tmp );
int bdb_idl_append( ID *a, ID *b );
int bdb_idl_append_one( ID *ids, ID id );
/*
* index.c
*/
#define bdb_index_mask BDB_SYMBOL(index_mask)
#define bdb_index_param BDB_SYMBOL(index_param)
#define bdb_index_values BDB_SYMBOL(index_values)
#define bdb_index_entry BDB_SYMBOL(index_entry)
#define bdb_index_recset BDB_SYMBOL(index_recset)
#define bdb_index_recrun BDB_SYMBOL(index_recrun)
extern AttrInfo *
bdb_index_mask LDAP_P((
Backend *be,
AttributeDescription *desc,
struct berval *name ));
extern int
bdb_index_param LDAP_P((
Backend *be,
AttributeDescription *desc,
int ftype,
DB **db,
slap_mask_t *mask,
struct berval *prefix ));
extern int
bdb_index_values LDAP_P((
Operation *op,
DB_TXN *txn,
AttributeDescription *desc,
BerVarray vals,
ID id,
int opid ));
extern int
bdb_index_recset LDAP_P((
struct bdb_info *bdb,
Attribute *a,
AttributeType *type,
struct berval *tags,
IndexRec *ir ));
extern int
bdb_index_recrun LDAP_P((
Operation *op,
struct bdb_info *bdb,
IndexRec *ir,
ID id,
int base ));
int bdb_index_entry LDAP_P(( Operation *op, DB_TXN *t, int r, Entry *e ));
#define bdb_index_entry_add(op,t,e) \
bdb_index_entry((op),(t),SLAP_INDEX_ADD_OP,(e))
#define bdb_index_entry_del(op,t,e) \
bdb_index_entry((op),(t),SLAP_INDEX_DELETE_OP,(e))
/*
* key.c
*/
#define bdb_key_read BDB_SYMBOL(key_read)
#define bdb_key_change BDB_SYMBOL(key_change)
extern int
bdb_key_read(
Backend *be,
DB *db,
DB_TXN *txn,
struct berval *k,
ID *ids,
DBC **saved_cursor,
int get_flags );
extern int
bdb_key_change(
Backend *be,
DB *db,
DB_TXN *txn,
struct berval *k,
ID id,
int op );
/*
* nextid.c
*/
#define bdb_next_id BDB_SYMBOL(next_id)
#define bdb_last_id BDB_SYMBOL(last_id)
int bdb_next_id( BackendDB *be, ID *id );
int bdb_last_id( BackendDB *be, DB_TXN *tid );
/*
* modify.c
*/
#define bdb_modify_internal BDB_SYMBOL(modify_internal)
int bdb_modify_internal(
Operation *op,
DB_TXN *tid,
Modifications *modlist,
Entry *e,
const char **text,
char *textbuf,
size_t textlen );
/*
* monitor.c
*/
#define bdb_monitor_db_init BDB_SYMBOL(monitor_db_init)
#define bdb_monitor_db_open BDB_SYMBOL(monitor_db_open)
#define bdb_monitor_db_close BDB_SYMBOL(monitor_db_close)
#define bdb_monitor_db_destroy BDB_SYMBOL(monitor_db_destroy)
int bdb_monitor_db_init( BackendDB *be );
int bdb_monitor_db_open( BackendDB *be );
int bdb_monitor_db_close( BackendDB *be );
int bdb_monitor_db_destroy( BackendDB *be );
#ifdef BDB_MONITOR_IDX
#define bdb_monitor_idx_add BDB_SYMBOL(monitor_idx_add)
int
bdb_monitor_idx_add(
struct bdb_info *bdb,
AttributeDescription *desc,
slap_mask_t type );
#endif /* BDB_MONITOR_IDX */
/*
* cache.c
*/
#define bdb_cache_entry_db_unlock BDB_SYMBOL(cache_entry_db_unlock)
#define bdb_cache_return_entry_rw BDB_SYMBOL(cache_return_entry_rw)
#define bdb_cache_entryinfo_lock(e) \
ldap_pvt_thread_mutex_lock( &(e)->bei_kids_mutex )
#define bdb_cache_entryinfo_unlock(e) \
ldap_pvt_thread_mutex_unlock( &(e)->bei_kids_mutex )
#define bdb_cache_entryinfo_trylock(e) \
ldap_pvt_thread_mutex_trylock( &(e)->bei_kids_mutex )
/* What a mess. Hopefully the current cache scheme will stabilize
* and we can trim out all of this stuff.
*/
void bdb_cache_return_entry_rw( struct bdb_info *bdb, Entry *e,
int rw, DB_LOCK *lock );
#define bdb_cache_return_entry_r(bdb, e, l) \
bdb_cache_return_entry_rw((bdb), (e), 0, (l))
#define bdb_cache_return_entry_w(bdb, e, l) \
bdb_cache_return_entry_rw((bdb), (e), 1, (l))
#if 0
void bdb_unlocked_cache_return_entry_rw( struct bdb_info *bdb, Entry *e, int rw );
#else
#define bdb_unlocked_cache_return_entry_rw( a, b, c ) ((void)0)
#endif
#define bdb_unlocked_cache_return_entry_r( c, e ) \
bdb_unlocked_cache_return_entry_rw((c), (e), 0)
#define bdb_unlocked_cache_return_entry_w( c, e ) \
bdb_unlocked_cache_return_entry_rw((c), (e), 1)
#define bdb_cache_add BDB_SYMBOL(cache_add)
#define bdb_cache_children BDB_SYMBOL(cache_children)
#define bdb_cache_delete BDB_SYMBOL(cache_delete)
#define bdb_cache_delete_cleanup BDB_SYMBOL(cache_delete_cleanup)
#define bdb_cache_find_id BDB_SYMBOL(cache_find_id)
#define bdb_cache_find_ndn BDB_SYMBOL(cache_find_ndn)
#define bdb_cache_find_parent BDB_SYMBOL(cache_find_parent)
#define bdb_cache_modify BDB_SYMBOL(cache_modify)
#define bdb_cache_modrdn BDB_SYMBOL(cache_modrdn)
#define bdb_cache_release_all BDB_SYMBOL(cache_release_all)
#define bdb_cache_delete_entry BDB_SYMBOL(cache_delete_entry)
#define bdb_cache_deref BDB_SYMBOL(cache_deref)
int bdb_cache_children(
Operation *op,
DB_TXN *txn,
Entry *e
);
int bdb_cache_add(
struct bdb_info *bdb,
EntryInfo *pei,
Entry *e,
struct berval *nrdn,
DB_TXN *txn,
DB_LOCK *lock
);
int bdb_cache_modrdn(
struct bdb_info *bdb,
Entry *e,
struct berval *nrdn,
Entry *new,
EntryInfo *ein,
DB_TXN *txn,
DB_LOCK *lock
);
int bdb_cache_modify(
struct bdb_info *bdb,
Entry *e,
Attribute *newAttrs,
DB_TXN *txn,
DB_LOCK *lock
);
int bdb_cache_find_ndn(
Operation *op,
DB_TXN *txn,
struct berval *ndn,
EntryInfo **res
);
#define ID_LOCKED 1
#define ID_NOCACHE 2
#define ID_NOENTRY 4
#define ID_CHKPURGE 8
int bdb_cache_find_id(
Operation *op,
DB_TXN *tid,
ID id,
EntryInfo **eip,
int flag,
DB_LOCK *lock
);
int
bdb_cache_find_parent(
Operation *op,
DB_TXN *txn,
ID id,
EntryInfo **res
);
int bdb_cache_delete(
struct bdb_info *bdb,
Entry *e,
DB_TXN *txn,
DB_LOCK *lock
);
void bdb_cache_delete_cleanup(
Cache *cache,
EntryInfo *ei
);
void bdb_cache_release_all( Cache *cache );
void bdb_cache_deref( EntryInfo *ei );
#ifdef BDB_HIER
int hdb_cache_load(
struct bdb_info *bdb,
EntryInfo *ei,
EntryInfo **res
);
#endif
#define bdb_cache_entry_db_relock BDB_SYMBOL(cache_entry_db_relock)
int bdb_cache_entry_db_relock(
struct bdb_info *bdb,
DB_TXN *txn,
EntryInfo *ei,
int rw,
int tryOnly,
DB_LOCK *lock );
int bdb_cache_entry_db_unlock(
struct bdb_info *bdb,
DB_LOCK *lock );
#define bdb_reader_get BDB_SYMBOL(reader_get)
#define bdb_reader_flush BDB_SYMBOL(reader_flush)
int bdb_reader_get( Operation *op, DB_ENV *env, DB_TXN **txn );
void bdb_reader_flush( DB_ENV *env );
/*
* trans.c
*/
#define bdb_trans_backoff BDB_SYMBOL(trans_backoff)
void
bdb_trans_backoff( int num_retries );
/*
* former external.h
*/
#define bdb_back_initialize BDB_SYMBOL(back_initialize)
#define bdb_db_config BDB_SYMBOL(db_config)
#define bdb_add BDB_SYMBOL(add)
#define bdb_bind BDB_SYMBOL(bind)
#define bdb_compare BDB_SYMBOL(compare)
#define bdb_delete BDB_SYMBOL(delete)
#define bdb_modify BDB_SYMBOL(modify)
#define bdb_modrdn BDB_SYMBOL(modrdn)
#define bdb_search BDB_SYMBOL(search)
#define bdb_extended BDB_SYMBOL(extended)
#define bdb_referrals BDB_SYMBOL(referrals)
#define bdb_operational BDB_SYMBOL(operational)
#define bdb_hasSubordinates BDB_SYMBOL(hasSubordinates)
#define bdb_tool_entry_open BDB_SYMBOL(tool_entry_open)
#define bdb_tool_entry_close BDB_SYMBOL(tool_entry_close)
#define bdb_tool_entry_first_x BDB_SYMBOL(tool_entry_first_x)
#define bdb_tool_entry_next BDB_SYMBOL(tool_entry_next)
#define bdb_tool_entry_get BDB_SYMBOL(tool_entry_get)
#define bdb_tool_entry_put BDB_SYMBOL(tool_entry_put)
#define bdb_tool_entry_reindex BDB_SYMBOL(tool_entry_reindex)
#define bdb_tool_dn2id_get BDB_SYMBOL(tool_dn2id_get)
#define bdb_tool_entry_modify BDB_SYMBOL(tool_entry_modify)
#define bdb_tool_idl_add BDB_SYMBOL(tool_idl_add)
#define bdb_tool_entry_delete BDB_SYMBOL(tool_entry_delete)
extern BI_init bdb_back_initialize;
extern BI_db_config bdb_db_config;
extern BI_op_add bdb_add;
extern BI_op_bind bdb_bind;
extern BI_op_compare bdb_compare;
extern BI_op_delete bdb_delete;
extern BI_op_modify bdb_modify;
extern BI_op_modrdn bdb_modrdn;
extern BI_op_search bdb_search;
extern BI_op_extended bdb_extended;
extern BI_chk_referrals bdb_referrals;
extern BI_operational bdb_operational;
extern BI_has_subordinates bdb_hasSubordinates;
/* tools.c */
extern BI_tool_entry_open bdb_tool_entry_open;
extern BI_tool_entry_close bdb_tool_entry_close;
extern BI_tool_entry_first_x bdb_tool_entry_first_x;
extern BI_tool_entry_next bdb_tool_entry_next;
extern BI_tool_entry_get bdb_tool_entry_get;
extern BI_tool_entry_put bdb_tool_entry_put;
extern BI_tool_entry_reindex bdb_tool_entry_reindex;
extern BI_tool_dn2id_get bdb_tool_dn2id_get;
extern BI_tool_entry_modify bdb_tool_entry_modify;
extern BI_tool_entry_delete bdb_tool_entry_delete;
int bdb_tool_idl_add( BackendDB *be, DB *db, DB_TXN *txn, DBT *key, ID id );
LDAP_END_DECL
#endif /* _PROTO_BDB_H */

View File

@ -1,152 +0,0 @@
/* referral.c - BDB backend referral handler */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2000-2019 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include "back-bdb.h"
int
bdb_referrals( Operation *op, SlapReply *rs )
{
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
Entry *e = NULL;
EntryInfo *ei;
int rc = LDAP_SUCCESS;
DB_TXN *rtxn;
DB_LOCK lock;
if( op->o_tag == LDAP_REQ_SEARCH ) {
/* let search take care of itself */
return rc;
}
if( get_manageDSAit( op ) ) {
/* let op take care of DSA management */
return rc;
}
rc = bdb_reader_get(op, bdb->bi_dbenv, &rtxn);
switch(rc) {
case 0:
break;
default:
return LDAP_OTHER;
}
dn2entry_retry:
/* get entry */
rc = bdb_dn2entry( op, rtxn, &op->o_req_ndn, &ei, 1, &lock );
/* bdb_dn2entry() may legally leave ei == NULL
* if rc != 0 and rc != DB_NOTFOUND
*/
if ( ei ) {
e = ei->bei_e;
}
switch(rc) {
case DB_NOTFOUND:
case 0:
break;
case LDAP_BUSY:
rs->sr_text = "ldap server busy";
return LDAP_BUSY;
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto dn2entry_retry;
default:
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_referrals)
": dn2entry failed: %s (%d)\n",
db_strerror(rc), rc );
rs->sr_text = "internal error";
return LDAP_OTHER;
}
if ( rc == DB_NOTFOUND ) {
rc = LDAP_SUCCESS;
rs->sr_matched = NULL;
if ( e != NULL ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_referrals)
": tag=%lu target=\"%s\" matched=\"%s\"\n",
(unsigned long)op->o_tag, op->o_req_dn.bv_val, e->e_name.bv_val );
if( is_entry_referral( e ) ) {
BerVarray ref = get_entry_referrals( op, e );
rc = LDAP_OTHER;
rs->sr_ref = referral_rewrite( ref, &e->e_name,
&op->o_req_dn, LDAP_SCOPE_DEFAULT );
ber_bvarray_free( ref );
if ( rs->sr_ref ) {
rs->sr_matched = ber_strdup_x(
e->e_name.bv_val, op->o_tmpmemctx );
}
}
bdb_cache_return_entry_r (bdb, e, &lock);
e = NULL;
}
if( rs->sr_ref != NULL ) {
/* send referrals */
rc = rs->sr_err = LDAP_REFERRAL;
send_ldap_result( op, rs );
ber_bvarray_free( rs->sr_ref );
rs->sr_ref = NULL;
} else if ( rc != LDAP_SUCCESS ) {
rs->sr_text = rs->sr_matched ? "bad referral object" : NULL;
}
if (rs->sr_matched) {
op->o_tmpfree( (char *)rs->sr_matched, op->o_tmpmemctx );
rs->sr_matched = NULL;
}
return rc;
}
if ( is_entry_referral( e ) ) {
/* entry is a referral */
BerVarray refs = get_entry_referrals( op, e );
rs->sr_ref = referral_rewrite(
refs, &e->e_name, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_referrals)
": tag=%lu target=\"%s\" matched=\"%s\"\n",
(unsigned long)op->o_tag, op->o_req_dn.bv_val, e->e_name.bv_val );
rs->sr_matched = e->e_name.bv_val;
if( rs->sr_ref != NULL ) {
rc = rs->sr_err = LDAP_REFERRAL;
send_ldap_result( op, rs );
ber_bvarray_free( rs->sr_ref );
rs->sr_ref = NULL;
} else {
rc = LDAP_OTHER;
rs->sr_text = "bad referral object";
}
rs->sr_matched = NULL;
ber_bvarray_free( refs );
}
bdb_cache_return_entry_r(bdb, e, &lock);
return rc;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,56 +0,0 @@
/* trans.c - bdb backend transaction routines */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2000-2019 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include "back-bdb.h"
#include "lber_pvt.h"
#include "lutil.h"
/* Congestion avoidance code
* for Deadlock Rollback
*/
void
bdb_trans_backoff( int num_retries )
{
int i;
int delay = 0;
int pow_retries = 1;
unsigned long key = 0;
unsigned long max_key = -1;
struct timeval timeout;
lutil_entropy( (unsigned char *) &key, sizeof( unsigned long ));
for ( i = 0; i < num_retries; i++ ) {
if ( i >= 5 ) break;
pow_retries *= 4;
}
delay = 16384 * (key * (double) pow_retries / (double) max_key);
delay = delay ? delay : 1;
Debug( LDAP_DEBUG_TRACE, "delay = %d, num_retries = %d\n", delay, num_retries );
timeout.tv_sec = delay / 1000000;
timeout.tv_usec = delay % 1000000;
select( 0, NULL, NULL, NULL, &timeout );
}

View File

@ -1,70 +0,0 @@
# Makefile for back-hdb
# $OpenLDAP$
## This work is part of OpenLDAP Software <http://www.openldap.org/>.
##
## Copyright 1998-2019 The OpenLDAP Foundation.
## All rights reserved.
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted only as authorized by the OpenLDAP
## Public License.
##
## A copy of this license is available in the file LICENSE in the
## top-level directory of the distribution or, alternatively, at
## <http://www.OpenLDAP.org/license.html>.
#
## Copyright 2003 Howard Chu @ Symas Corp. See master COPYRIGHT file for terms.
XXDIR = $(srcdir)/../back-bdb
XXSRCS = init.c tools.c config.c \
add.c bind.c compare.c delete.c modify.c modrdn.c search.c \
extended.c referral.c operational.c \
attr.c index.c key.c dbcache.c filterindex.c trans.c \
dn2entry.c dn2id.c error.c id2entry.c idl.c nextid.c cache.c \
monitor.c
SRCS = $(XXSRCS)
OBJS = init.lo tools.lo config.lo \
add.lo bind.lo compare.lo delete.lo modify.lo modrdn.lo search.lo \
extended.lo referral.lo operational.lo \
attr.lo index.lo key.lo dbcache.lo filterindex.lo trans.lo \
dn2entry.lo dn2id.lo error.lo id2entry.lo idl.lo nextid.lo cache.lo \
monitor.lo
LDAP_INCDIR= ../../../include
LDAP_LIBDIR= ../../../libraries
BUILD_OPT = "--enable-hdb"
BUILD_MOD = @BUILD_HDB@
mod_DEFS = -DSLAPD_IMPORT
MOD_DEFS = $(@BUILD_HDB@_DEFS)
MOD_LIBS = $(BDB_LIBS)
shared_LDAP_LIBS = $(LDAP_LIBLDAP_R_LA) $(LDAP_LIBLBER_LA)
NT_LINK_LIBS = -L.. -lslapd $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
UNIX_LINK_LIBS = $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
.links : Makefile
@for i in $(XXSRCS); do \
$(RM) $$i; \
$(LN_S) $(XXDIR)/$$i . ; \
done
touch .links
$(XXSRCS) : .links
LIBBASE = back_hdb
XINCPATH = -I.. -I$(srcdir)/.. -I$(srcdir) -I$(XXDIR)
XDEFS = $(MODULES_CPPFLAGS)
depend-local-lib: .links
all-local-lib: ../.backend
../.backend: lib$(LIBBASE).a
@touch $@
veryclean-local: FORCE
$(RM) $(XXSRCS) .links

View File

@ -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-2019 The OpenLDAP Foundation.
* Portions Copyright 2003 Howard Chu @ Symas Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* ACKNOWLEDGEMENTS:
* This work was originally developed by Howard Chu for inclusion
* in OpenLDAP Software.
*/
#ifndef _BACK_HDB_H_
#define _BACK_HDB_H_
#ifndef BDB_HIER
#define BDB_HIER 1
#endif
#include "../back-bdb/back-bdb.h"
#endif /* _BACK_HDB_H_ */

View File

@ -113,7 +113,7 @@ static int write_data( int fd, const char *spew, int len, int *save_errno );
#endif /* !_WIN32 */
/*
* Left and Right "{num}" prefix to ordered RDNs ("olcDatabase={1}bdb").
* Left and Right "{num}" prefix to ordered RDNs ("olcDatabase={1}mdb").
* IX_DN* are for LDAP RDNs, IX_FS* for their .ldif filenames.
*/
#define IX_DNL '{'

View File

@ -1962,8 +1962,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 */
@ -1973,8 +1973,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 */

View File

@ -247,7 +247,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

View File

@ -1130,8 +1130,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.
*/

View File

@ -5613,7 +5613,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 );
}
@ -5697,7 +5697,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];

View File

@ -1818,7 +1818,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

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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 &

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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@
@ -74,7 +72,7 @@ fi
if test "${AC_asyncmeta}" = "metamod" && test "${AC_LIBS_DYNAMIC}" = "static" ; then
AC_meta="asyncmetano"
fi
export AC_bdb AC_hdb AC_ldap AC_mdb AC_meta AC_asyncmeta AC_monitor AC_null AC_relay AC_sql \
export AC_ldap AC_mdb AC_meta AC_asyncmeta AC_monitor AC_null AC_relay AC_sql \
AC_accesslog AC_autoca AC_constraint AC_dds AC_dynlist AC_memberof AC_pcache AC_ppolicy \
AC_refint AC_retcode AC_rwm AC_unique AC_syncprov AC_translucent \
AC_valsort \
@ -158,7 +156,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
@ -179,7 +177,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

View File

@ -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,63 +204,62 @@ 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

View File

@ -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"

View File

@ -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 &

View File

@ -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..."

View File

@ -32,7 +32,7 @@ fi
mkdir -p $TESTDIR $DBDIR1A $DBDIR1B $DBDIR2
SPEC="mdb=a,bdb=a,hdb=a"
SPEC="mdb=a"
#
# Test replication:

View File

@ -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

View File

@ -479,29 +479,6 @@ if test $RC != 0 ; then
exit $RC
fi
case $BACKEND in bdb | hdb)
db_stat=
for path in `echo "$PATH" | sed -e 's/:/ /g'`; do
if test -f "$path/db_stat" && \
"$path/db_stat" -E -h $PRODDIR/db > /dev/null 2>&1
then
db_stat="$path/db_stat"
break
fi
done
if test -z "$db_stat" ; then
echo "Could not find a working db_stat in PATH!"
lock_bug=1
elif "$db_stat" -E -h $PRODDIR/db | egrep -q 'HELD .* len:'; then
echo "WARNING: Glue lock bug hit, next modify could deadlock"
lock_bug=2
else
echo "Glue lock bug not found :-)"
lock_bug=0
fi
esac
echo "Using ldapmodify to modify glue suffix on provider..."
$LDAPADD -D "$MANAGERDN" -H $URI1 -w $PASSWD <<EOF >> $TESTOUT 2>&1
dn: dc=example,dc=com

View File

@ -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

View File

@ -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

View File

@ -63,7 +63,6 @@ KILLPIDS=
$SLAPPASSWD -g -n >$CONFIGPWF
case "$BACKEND" in
bdb|hdb) olcDbCheckpoint="olcDbCheckpoint";;
*) olcDbCheckpoint="# olcDbCheckpoint";;
esac

Some files were not shown because too many files have changed in this diff Show More