mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-20 22:59:34 -05:00
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:
parent
ebf0ef5cb1
commit
ec2cb12e68
101 changed files with 442 additions and 20199 deletions
27
.gitignore
vendored
27
.gitignore
vendored
|
|
@ -152,33 +152,6 @@ libraries/librewrite/rewrite
|
||||||
libraries/librewrite/version.c
|
libraries/librewrite/version.c
|
||||||
servers/slapd/.backend
|
servers/slapd/.backend
|
||||||
servers/slapd/all-cffiles
|
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/backends.c
|
||||||
servers/slapd/overlays/statover.c
|
servers/slapd/overlays/statover.c
|
||||||
servers/slapd/slapacl
|
servers/slapd/slapacl
|
||||||
|
|
|
||||||
3
INSTALL
3
INSTALL
|
|
@ -73,9 +73,6 @@ Making and Installing the OpenLDAP Distribution
|
||||||
|
|
||||||
6. Test the standalone system:
|
6. Test the standalone system:
|
||||||
|
|
||||||
This step requires the standalone LDAP server, slapd(8), with HDB
|
|
||||||
and/or BDB support.
|
|
||||||
|
|
||||||
% make test
|
% make test
|
||||||
|
|
||||||
If all goes well, the system has been built as configured. If
|
If all goes well, the system has been built as configured. If
|
||||||
|
|
|
||||||
|
|
@ -270,298 +270,6 @@ if test $ac_cv_header_unicode_utypes_h = yes ; then
|
||||||
fi
|
fi
|
||||||
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
|
||||||
dnl ====================================================================
|
dnl ====================================================================
|
||||||
|
|
|
||||||
|
|
@ -163,7 +163,6 @@ CLIENT_LIBS = @CLIENT_LIBS@
|
||||||
LUTIL_LIBS = @LUTIL_LIBS@
|
LUTIL_LIBS = @LUTIL_LIBS@
|
||||||
LTHREAD_LIBS = @LTHREAD_LIBS@
|
LTHREAD_LIBS = @LTHREAD_LIBS@
|
||||||
|
|
||||||
BDB_LIBS = @BDB_LIBS@
|
|
||||||
SLAPD_NDB_LIBS = @SLAPD_NDB_LIBS@
|
SLAPD_NDB_LIBS = @SLAPD_NDB_LIBS@
|
||||||
WT_LIBS = @WT_LIBS@
|
WT_LIBS = @WT_LIBS@
|
||||||
|
|
||||||
|
|
|
||||||
74
configure.in
74
configure.in
|
|
@ -300,9 +300,7 @@ OL_ARG_ENABLE(wrappers,[ --enable-wrappers enable tcp wrapper support], no)
|
||||||
|
|
||||||
dnl ----------------------------------------------------------------
|
dnl ----------------------------------------------------------------
|
||||||
dnl SLAPD Backend Options
|
dnl SLAPD Backend Options
|
||||||
Backends="bdb \
|
Backends="dnssrv \
|
||||||
dnssrv \
|
|
||||||
hdb \
|
|
||||||
ldap \
|
ldap \
|
||||||
mdb \
|
mdb \
|
||||||
meta \
|
meta \
|
||||||
|
|
@ -323,12 +321,8 @@ SLAPD Backend Options:])
|
||||||
|
|
||||||
OL_ARG_ENABLE(backends,[ --enable-backends enable all available backends],
|
OL_ARG_ENABLE(backends,[ --enable-backends enable all available backends],
|
||||||
--, [no yes mod])dnl
|
--, [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],
|
OL_ARG_ENABLE(dnssrv,[ --enable-dnssrv enable dnssrv backend],
|
||||||
no, [no yes mod], ol_enable_backends)dnl
|
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],
|
OL_ARG_ENABLE(ldap,[ --enable-ldap enable ldap backend],
|
||||||
no, [no yes mod], ol_enable_backends)dnl
|
no, [no yes mod], ol_enable_backends)dnl
|
||||||
OL_ARG_ENABLE(mdb,[ --enable-mdb enable mdb database backend],
|
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
|
ol_enable_rewrite=no
|
||||||
|
|
||||||
elif test $ol_enable_modules != yes &&
|
elif test $ol_enable_modules != yes &&
|
||||||
test $ol_enable_bdb = no &&
|
|
||||||
test $ol_enable_dnssrv = no &&
|
test $ol_enable_dnssrv = no &&
|
||||||
test $ol_enable_hdb = no &&
|
|
||||||
test $ol_enable_ldap = no &&
|
test $ol_enable_ldap = no &&
|
||||||
test $ol_enable_mdb = no &&
|
test $ol_enable_mdb = no &&
|
||||||
test $ol_enable_meta = no &&
|
test $ol_enable_meta = no &&
|
||||||
|
|
@ -566,7 +558,6 @@ dnl ----------------------------------------------------------------
|
||||||
|
|
||||||
dnl Initialize vars
|
dnl Initialize vars
|
||||||
LDAP_LIBS=
|
LDAP_LIBS=
|
||||||
BDB_LIBS=
|
|
||||||
SLAPD_NDB_LIBS=
|
SLAPD_NDB_LIBS=
|
||||||
SLAPD_NDB_INCS=
|
SLAPD_NDB_INCS=
|
||||||
LTHREAD_LIBS=
|
LTHREAD_LIBS=
|
||||||
|
|
@ -583,9 +574,7 @@ BUILD_THREAD=no
|
||||||
BUILD_SLAPI=no
|
BUILD_SLAPI=no
|
||||||
SLAPD_SLAPI_DEPEND=
|
SLAPD_SLAPI_DEPEND=
|
||||||
|
|
||||||
BUILD_BDB=no
|
|
||||||
BUILD_DNSSRV=no
|
BUILD_DNSSRV=no
|
||||||
BUILD_HDB=no
|
|
||||||
BUILD_LDAP=no
|
BUILD_LDAP=no
|
||||||
BUILD_MDB=no
|
BUILD_MDB=no
|
||||||
BUILD_META=no
|
BUILD_META=no
|
||||||
|
|
@ -1883,36 +1872,6 @@ else
|
||||||
ol_cv_func_gethostbyaddr_r_nargs=0
|
ol_cv_func_gethostbyaddr_r_nargs=0
|
||||||
fi
|
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 ----------------------------------------------------------------
|
dnl ----------------------------------------------------------------
|
||||||
|
|
||||||
if test $ol_enable_dynamic = yes && test $enable_shared = yes ; then
|
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])
|
AC_DEFINE_UNQUOTED(SLAPD_MONITOR,$MFLAG,[define to support cn=Monitor backend])
|
||||||
fi
|
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
|
if test "$ol_enable_dnssrv" != no ; then
|
||||||
BUILD_SLAPD=yes
|
BUILD_SLAPD=yes
|
||||||
BUILD_DNSSRV=$ol_enable_dnssrv
|
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])
|
AC_DEFINE_UNQUOTED(SLAPD_DNSSRV,$MFLAG,[define to support DNS SRV backend])
|
||||||
fi
|
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
|
if test "$ol_enable_ldap" != no ; then
|
||||||
BUILD_SLAPD=yes
|
BUILD_SLAPD=yes
|
||||||
BUILD_LDAP=$ol_enable_ldap
|
BUILD_LDAP=$ol_enable_ldap
|
||||||
|
|
@ -3172,9 +3105,7 @@ dnl slapi
|
||||||
AC_SUBST(BUILD_SLAPI)
|
AC_SUBST(BUILD_SLAPI)
|
||||||
AC_SUBST(SLAPD_SLAPI_DEPEND)
|
AC_SUBST(SLAPD_SLAPI_DEPEND)
|
||||||
dnl backends
|
dnl backends
|
||||||
AC_SUBST(BUILD_BDB)
|
|
||||||
AC_SUBST(BUILD_DNSSRV)
|
AC_SUBST(BUILD_DNSSRV)
|
||||||
AC_SUBST(BUILD_HDB)
|
|
||||||
AC_SUBST(BUILD_LDAP)
|
AC_SUBST(BUILD_LDAP)
|
||||||
AC_SUBST(BUILD_MDB)
|
AC_SUBST(BUILD_MDB)
|
||||||
AC_SUBST(BUILD_META)
|
AC_SUBST(BUILD_META)
|
||||||
|
|
@ -3217,7 +3148,6 @@ dnl overlays
|
||||||
AC_SUBST(LDAP_LIBS)
|
AC_SUBST(LDAP_LIBS)
|
||||||
AC_SUBST(CLIENT_LIBS)
|
AC_SUBST(CLIENT_LIBS)
|
||||||
AC_SUBST(SLAPD_LIBS)
|
AC_SUBST(SLAPD_LIBS)
|
||||||
AC_SUBST(BDB_LIBS)
|
|
||||||
AC_SUBST(SLAPD_NDB_LIBS)
|
AC_SUBST(SLAPD_NDB_LIBS)
|
||||||
AC_SUBST(SLAPD_NDB_INCS)
|
AC_SUBST(SLAPD_NDB_INCS)
|
||||||
AC_SUBST(LTHREAD_LIBS)
|
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]
|
[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/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/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-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-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-ldif/Makefile:build/top.mk:servers/slapd/back-ldif/Makefile.in:build/mod.mk]
|
||||||
[servers/slapd/back-mdb/Makefile:build/top.mk:servers/slapd/back-mdb/Makefile.in:build/mod.mk]
|
[servers/slapd/back-mdb/Makefile:build/top.mk:servers/slapd/back-mdb/Makefile.in:build/mod.mk]
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
* Caveats:
|
* Caveats:
|
||||||
* - right now, the overlay assumes that all values of the objectClass
|
* - right now, the overlay assumes that all values of the objectClass
|
||||||
* attribute will be returned in rs->sr_entry; this may not be true
|
* 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
|
* the search request should be analyzed, and if allowedAttributes or
|
||||||
* allowedAttributesEffective are requested, add objectClass to the
|
* allowedAttributesEffective are requested, add objectClass to the
|
||||||
* requested attributes
|
* requested attributes
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ To use the overlay, add:
|
||||||
moduleload <path to>nssov.so
|
moduleload <path to>nssov.so
|
||||||
...
|
...
|
||||||
|
|
||||||
database hdb
|
database mdb
|
||||||
...
|
...
|
||||||
overlay nssov
|
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
|
The overlay also supports dynamic configuration in cn=config. The layout
|
||||||
of the config entry is
|
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: olcOverlayConfig
|
||||||
objectClass: olcNssOvConfig
|
objectClass: olcNssOvConfig
|
||||||
olcOverlay: {0}nssov
|
olcOverlay: {0}nssov
|
||||||
|
|
|
||||||
|
|
@ -278,7 +278,7 @@ of the config entry is
|
||||||
.LP
|
.LP
|
||||||
.RS
|
.RS
|
||||||
.nf
|
.nf
|
||||||
dn: olcOverlay={0}nssov,ocDatabase={1}hdb,cn=config
|
dn: olcOverlay={0}nssov,ocDatabase={1}mdb,cn=config
|
||||||
objectClass: olcOverlayConfig
|
objectClass: olcOverlayConfig
|
||||||
objectClass: olcNssOvConfig
|
objectClass: olcNssOvConfig
|
||||||
olcOverlay: {0}nssov
|
olcOverlay: {0}nssov
|
||||||
|
|
|
||||||
|
|
@ -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
|
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.
|
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
|
H3: New overlays
|
||||||
|
|
||||||
* slapo-constraint (Attribute value constraints)
|
* slapo-constraint (Attribute value constraints)
|
||||||
|
|
@ -199,21 +194,13 @@ H3: New build options
|
||||||
* Support for building against GnuTLS
|
* 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
|
back-bdb and back-hdb were signficantly slower than back-mdb and
|
||||||
OpenLDAP
|
required significant tuning of multiple parameters to maximize
|
||||||
|
performance. back-mdb requires no tuning and provides all the
|
||||||
H3: back-ldbm
|
functionality previously provided via back-bdb and back-hdb.
|
||||||
|
|
||||||
back-ldbm was both slow and unreliable. Its byzantine indexing code was
|
|
||||||
prone to spontaneous corruption, as were the underlying database libraries
|
|
||||||
that were commonly used (e.g. GDBM or NDBM). back-bdb and back-hdb are
|
|
||||||
superior in every aspect, with simplified indexing to avoid index corruption,
|
|
||||||
fine-grained locking for greater concurrency, hierarchical caching for
|
|
||||||
greater performance, streamlined on-disk format for greater efficiency
|
|
||||||
and portability, and full transaction support for greater reliability.
|
|
||||||
|
|
|
||||||
|
|
@ -636,7 +636,7 @@ values of <n>.
|
||||||
|
|
||||||
H3: ldap_*: Internal (implementation specific) error (80) - additional info: entry index delete failed
|
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.
|
and files. The files must be owned by the user that slapd runs as.
|
||||||
|
|
||||||
> chown -R ldap:ldap /var/lib/ldap
|
> 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)
|
> SASL/GSSAPI authentication started ldap_sasl_interactive_bind_s: Can't contact LDAP server (-1)
|
||||||
|
|
||||||
Then check the slapd service, it stopped.
|
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.
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,6 @@ NOSYNC
|
||||||
env
|
env
|
||||||
pagedResultsControl
|
pagedResultsControl
|
||||||
dup
|
dup
|
||||||
hdb
|
|
||||||
LDIFv
|
LDIFv
|
||||||
syslog
|
syslog
|
||||||
monitorTimestamp
|
monitorTimestamp
|
||||||
|
|
@ -886,7 +885,6 @@ proxyAttrSet
|
||||||
proxyAttrset
|
proxyAttrset
|
||||||
mary
|
mary
|
||||||
crlcheck
|
crlcheck
|
||||||
olcBdbConfig
|
|
||||||
kadmin
|
kadmin
|
||||||
mech
|
mech
|
||||||
slapcat
|
slapcat
|
||||||
|
|
@ -1189,7 +1187,6 @@ moddn
|
||||||
calloc
|
calloc
|
||||||
LDFLAGS
|
LDFLAGS
|
||||||
attributeOrValueExists
|
attributeOrValueExists
|
||||||
olcHdbConfig
|
|
||||||
bsize
|
bsize
|
||||||
auditObject
|
auditObject
|
||||||
dnssrv
|
dnssrv
|
||||||
|
|
@ -1491,7 +1488,6 @@ ghenry
|
||||||
odbcinst
|
odbcinst
|
||||||
reqType
|
reqType
|
||||||
slapover
|
slapover
|
||||||
BerkeleyDB's
|
|
||||||
attributename
|
attributename
|
||||||
lwrap
|
lwrap
|
||||||
reqStart
|
reqStart
|
||||||
|
|
@ -1627,7 +1623,6 @@ DSAIT
|
||||||
olcHidden
|
olcHidden
|
||||||
mySNMP
|
mySNMP
|
||||||
metainformation
|
metainformation
|
||||||
BerkeleyDB
|
|
||||||
ldapuri
|
ldapuri
|
||||||
auditAbandon
|
auditAbandon
|
||||||
RANDFILE
|
RANDFILE
|
||||||
|
|
@ -1661,7 +1656,6 @@ olcPasswordHash
|
||||||
ldapc
|
ldapc
|
||||||
loopback
|
loopback
|
||||||
ldapi
|
ldapi
|
||||||
BDB's
|
|
||||||
GETREALM
|
GETREALM
|
||||||
functionalities
|
functionalities
|
||||||
noplain
|
noplain
|
||||||
|
|
@ -1669,7 +1663,6 @@ NOECHOPROMPT
|
||||||
AES
|
AES
|
||||||
ldaps
|
ldaps
|
||||||
notoc
|
notoc
|
||||||
bdb
|
|
||||||
LDAPv
|
LDAPv
|
||||||
IPsec
|
IPsec
|
||||||
olcServerID
|
olcServerID
|
||||||
|
|
|
||||||
|
|
@ -14,38 +14,9 @@ name of the module for a backend is usually of the form:
|
||||||
|
|
||||||
> back_<backend name>.la
|
> 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
|
> moduleload back_mdb.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)
|
|
||||||
|
|
||||||
H2: LDAP
|
H2: LDAP
|
||||||
|
|
||||||
|
|
@ -199,16 +170,16 @@ H3: Overview
|
||||||
The {{mdb}} backend to {{slapd}}(8) is the recommended primary backend for a
|
The {{mdb}} backend to {{slapd}}(8) is the recommended primary backend for a
|
||||||
normal {{slapd}} database. It uses OpenLDAP's own
|
normal {{slapd}} database. It uses OpenLDAP's own
|
||||||
Lightning Memory-Mapped Database ({{TERM:LMDB}})
|
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
|
It supports indexing, it uses no caching, and requires no tuning to deliver
|
||||||
no tuning to deliver maximum search performance. Like {{hdb}}, it is also
|
maximum search performance. It is fully hierarchical and supports subtree
|
||||||
fully hierarchical and supports subtree renames in constant time.
|
renames in constant time.
|
||||||
|
|
||||||
H3: back-mdb Configuration
|
H3: back-mdb Configuration
|
||||||
|
|
||||||
Unlike the BDB backends, the {{mdb}} backend can be instantiated with very few
|
The {{mdb}} backend can be instantiated with very few configuration lines:
|
||||||
configuration lines:
|
|
||||||
|
|
||||||
> include ./schema/core.schema
|
> include ./schema/core.schema
|
||||||
>
|
>
|
||||||
|
|
@ -490,7 +461,7 @@ distribute information between different sites/applications that use RDBMSes
|
||||||
and/or LDAP. Or whatever else...
|
and/or LDAP. Or whatever else...
|
||||||
|
|
||||||
It is {{B:NOT}} designed as a general-purpose backend that uses RDBMS instead of
|
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.
|
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,
|
The idea is to use some meta-information to translate LDAP queries to SQL queries,
|
||||||
|
|
|
||||||
|
|
@ -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
|
software included with the OpenLDAP source. There is no need to download any
|
||||||
additional software to have {{MDB}} support.
|
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
|
H3: Threads
|
||||||
|
|
|
||||||
|
|
@ -346,7 +346,7 @@ really have a "directory".
|
||||||
|
|
||||||
Existing commercial LDAP server implementations that use a relational database
|
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
|
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
|
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
|
as LDAP tree, having some limitations compared to classic LDAP model, but making
|
||||||
it possible to interoperate between LDAP and SQL applications):
|
it possible to interoperate between LDAP and SQL applications):
|
||||||
|
|
@ -403,15 +403,9 @@ tags.
|
||||||
{{B:Choice of database backends}}: {{slapd}} comes with a variety
|
{{B:Choice of database backends}}: {{slapd}} comes with a variety
|
||||||
of different database backends you can choose from. They include
|
of different database backends you can choose from. They include
|
||||||
{{TERM:MDB}}, a hierarchical high-performance transactional database backend;
|
{{TERM:MDB}}, a hierarchical high-performance transactional database backend;
|
||||||
{{TERM:BDB}}, a high-performance transactional database backend (deprecated);
|
{{SHELL}}, a backend interface to arbitrary shell scripts;
|
||||||
{{TERM:HDB}}, a hierarchical high-performance transactional
|
|
||||||
backend (deprecated); {{SHELL}}, a backend interface to arbitrary shell scripts;
|
|
||||||
and PASSWD, a simple backend interface to the {{passwd}}(5) file.
|
and PASSWD, a simple backend interface to the {{passwd}}(5) file.
|
||||||
The MDB backend utilizes {{TERM:LMDB}}, a high performance replacement
|
The MDB backend utilizes {{TERM:LMDB}}.
|
||||||
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.
|
|
||||||
|
|
||||||
{{B:Multiple database instances}}: {{slapd}} can be configured to
|
{{B:Multiple database instances}}: {{slapd}} can be configured to
|
||||||
serve multiple databases at the same time. This means that a single
|
serve multiple databases at the same time. This means that a single
|
||||||
|
|
|
||||||
|
|
@ -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
|
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.
|
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
|
2. Periodically run slapcat and back up the LDIF file:
|
||||||
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:
|
|
||||||
|
|
||||||
Slapcat can be run while slapd is active. However, one runs the risk of an
|
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
|
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.
|
add up to a substantial amount of space.
|
||||||
|
|
||||||
You can use {{slapcat}}(8) to generate an LDIF file for each of your {{slapd}}(8)
|
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"
|
> 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.
|
For back-mdb 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.
|
|
||||||
|
|
||||||
|
|
||||||
H2: Checkpointing
|
H2: Checkpointing
|
||||||
|
|
@ -152,7 +76,7 @@ type are:
|
||||||
+{{B: slapcat the current data out}}
|
+{{B: slapcat the current data out}}
|
||||||
|
|
||||||
.{{S: }}
|
.{{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: }}
|
.{{S: }}
|
||||||
+{{B: Perform the software upgrades}}
|
+{{B: Perform the software upgrades}}
|
||||||
|
|
|
||||||
|
|
@ -214,12 +214,10 @@ backends, as well as backends loaded by modules. For example:
|
||||||
> monitoredInfo: config
|
> monitoredInfo: config
|
||||||
> monitoredInfo: ldif
|
> monitoredInfo: ldif
|
||||||
> monitoredInfo: monitor
|
> monitoredInfo: monitor
|
||||||
> monitoredInfo: bdb
|
|
||||||
> monitoredInfo: hdb
|
|
||||||
> monitoredInfo: mdb
|
> monitoredInfo: mdb
|
||||||
|
|
||||||
This indicates the {{config}}, {{ldif}}, {{monitor}}, {{bdb}},
|
This indicates the {{config}}, {{ldif}}, {{monitor}},
|
||||||
and {{hdb}} backends are available.
|
and {{mdb}} backends are available.
|
||||||
|
|
||||||
The {{EX:cn=Backends,cn=Monitor}} object is also a container
|
The {{EX:cn=Backends,cn=Monitor}} object is also a container
|
||||||
for available backend objects. Each available backend object
|
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
|
> seeAlso: cn=Database 2,cn=Databases,cn=Monitor
|
||||||
>
|
>
|
||||||
> dn: cn=Backend 3,cn=Backends,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
|
> monitoredInfo: mdb
|
||||||
> monitorRuntimeConfig: TRUE
|
> monitorRuntimeConfig: TRUE
|
||||||
> supportedControl: 1.3.6.1.1.12
|
> supportedControl: 1.3.6.1.1.12
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ H3: Access Logging Configuration
|
||||||
|
|
||||||
The following is a basic example that implements Access Logging:
|
The following is a basic example that implements Access Logging:
|
||||||
|
|
||||||
> database bdb
|
> database mdb
|
||||||
> suffix dc=example,dc=com
|
> suffix dc=example,dc=com
|
||||||
> ...
|
> ...
|
||||||
> overlay accesslog
|
> overlay accesslog
|
||||||
|
|
@ -94,7 +94,7 @@ The following is a basic example that implements Access Logging:
|
||||||
> logops writes reads
|
> logops writes reads
|
||||||
> logold (objectclass=person)
|
> logold (objectclass=person)
|
||||||
>
|
>
|
||||||
> database bdb
|
> database mdb
|
||||||
> suffix cn=log
|
> suffix cn=log
|
||||||
> ...
|
> ...
|
||||||
> index reqStart eq
|
> 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}}:
|
The following is an example used for {{SECT:delta-syncrepl replication}}:
|
||||||
|
|
||||||
> database hdb
|
> database mdb
|
||||||
> suffix cn=accesslog
|
> suffix cn=accesslog
|
||||||
> directory /usr/local/var/openldap-accesslog
|
> directory /usr/local/var/openldap-accesslog
|
||||||
> rootdn cn=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
|
Accesslog overlay definitions for the primary db
|
||||||
|
|
||||||
> database bdb
|
> database mdb
|
||||||
> suffix dc=example,dc=com
|
> suffix dc=example,dc=com
|
||||||
> ...
|
> ...
|
||||||
> overlay accesslog
|
> 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"
|
> authz-regexp "gidNumber=0\\\+uidNumber=0,cn=peercred,cn=external,cn=auth"
|
||||||
> "cn=Manager,dc=example,dc=com"
|
> "cn=Manager,dc=example,dc=com"
|
||||||
> database bdb
|
> database mdb
|
||||||
> suffix "dc=example,dc=com"
|
> suffix "dc=example,dc=com"
|
||||||
> rootdn "cn=Manager,dc=example,dc=com"
|
> rootdn "cn=Manager,dc=example,dc=com"
|
||||||
> rootpw secret
|
> rootpw secret
|
||||||
|
|
@ -738,7 +738,7 @@ H4: Setting cache parameters
|
||||||
This directive enables proxy caching and sets general cache
|
This directive enables proxy caching and sets general cache
|
||||||
parameters. The <DB> parameter specifies which underlying database
|
parameters. The <DB> parameter specifies which underlying database
|
||||||
is to be used to hold cached entries. It should be set to
|
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
|
total number of entries which may be held in the cache. The
|
||||||
<nattrsets> parameter specifies the total number of attribute sets
|
<nattrsets> parameter specifies the total number of attribute sets
|
||||||
(as specified by the {{EX:pcacheAttrset}} directive) that may be
|
(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"
|
> rootdn "dc=example,dc=com"
|
||||||
> uri ldap://ldap.example.com/
|
> uri ldap://ldap.example.com/
|
||||||
> overlay pcache
|
> overlay pcache
|
||||||
> pcache hdb 100000 1 1000 100
|
> pcache mdb 100000 1 1000 100
|
||||||
> pcacheAttrset 0 mail postaladdress telephonenumber
|
> pcacheAttrset 0 mail postaladdress telephonenumber
|
||||||
> pcacheTemplate (sn=) 0 3600
|
> pcacheTemplate (sn=) 0 3600
|
||||||
> pcacheTemplate (&(sn=)(givenName=)) 0 3600
|
> pcacheTemplate (&(sn=)(givenName=)) 0 3600
|
||||||
|
|
@ -806,7 +806,7 @@ at server {{EX:ldap.example.com}}.
|
||||||
> objectClass: olcOverlayConfig
|
> objectClass: olcOverlayConfig
|
||||||
> objectClass: olcPcacheConfig
|
> objectClass: olcPcacheConfig
|
||||||
> olcOverlay: {0}pcache
|
> olcOverlay: {0}pcache
|
||||||
> olcPcache: hdb 100000 1 1000 100
|
> olcPcache: mdb 100000 1 1000 100
|
||||||
> olcPcacheAttrset: 0 mail postalAddress telephoneNumber
|
> olcPcacheAttrset: 0 mail postalAddress telephoneNumber
|
||||||
> olcPcacheTemplate: "(sn=)" 0 3600 0 0 0
|
> olcPcacheTemplate: "(sn=)" 0 3600 0 0 0
|
||||||
> olcPcacheTemplate: "(&(sn=)(givenName=))" 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
|
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.
|
a policy object to use if none other is specified in a user's object.
|
||||||
|
|
||||||
> database bdb
|
> database mdb
|
||||||
> suffix "dc=example,dc=com"
|
> suffix "dc=example,dc=com"
|
||||||
> [...additional database configuration directives go here...]
|
> [...additional database configuration directives go here...]
|
||||||
>
|
>
|
||||||
|
|
@ -978,7 +978,7 @@ H2: Referential Integrity
|
||||||
|
|
||||||
H3: Overview
|
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
|
to maintain the cohesiveness of a schema which utilizes reference
|
||||||
attributes.
|
attributes.
|
||||||
|
|
||||||
|
|
@ -1173,7 +1173,7 @@ H2: Translucent Proxy
|
||||||
|
|
||||||
H3: Overview
|
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".
|
to create a "translucent proxy".
|
||||||
|
|
||||||
Entries retrieved from a remote LDAP server may have some or all attributes
|
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
|
> pidfile ./slapd.pid
|
||||||
> argsfile ./slapd.args
|
> argsfile ./slapd.args
|
||||||
>
|
>
|
||||||
> database bdb
|
> database mdb
|
||||||
> suffix "dc=suretecsystems,dc=com"
|
> suffix "dc=suretecsystems,dc=com"
|
||||||
> rootdn "cn=trans,dc=suretecsystems,dc=com"
|
> rootdn "cn=trans,dc=suretecsystems,dc=com"
|
||||||
> rootpw secret
|
> rootpw secret
|
||||||
|
|
@ -1305,7 +1305,7 @@ H2: Attribute Uniqueness
|
||||||
|
|
||||||
H3: Overview
|
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.
|
to enforce the uniqueness of some or all attributes within a subtree.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1390,7 +1390,7 @@ Here are a few examples:
|
||||||
|
|
||||||
> loglevel sync stats
|
> loglevel sync stats
|
||||||
>
|
>
|
||||||
> database hdb
|
> database mdb
|
||||||
> suffix "dc=suretecsystems,dc=com"
|
> suffix "dc=suretecsystems,dc=com"
|
||||||
> directory /usr/local/var/openldap-data
|
> directory /usr/local/var/openldap-data
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -225,8 +225,8 @@ in the replication context.
|
||||||
|
|
||||||
The syncrepl engine, which is a consumer-side replication engine,
|
The syncrepl engine, which is a consumer-side replication engine,
|
||||||
can work with any backends. The LDAP Sync provider can be configured
|
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}},
|
as an overlay on any backend, but works best with the {{back-mdb}}
|
||||||
{{back-hdb}}, or {{back-mdb}} backends.
|
backend.
|
||||||
|
|
||||||
The LDAP Sync provider maintains a {{EX:contextCSN}} for each
|
The LDAP Sync provider maintains a {{EX:contextCSN}} for each
|
||||||
database as the current synchronization state indicator of the
|
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)
|
server (slapd in proxy mode) or device (hardware load balancer)
|
||||||
is needed to manage which provider is currently active
|
is needed to manage which provider is currently active
|
||||||
* Backups are managed slightly differently
|
* 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
|
For configuration, please see the {{SECT:MirrorMode}} section below
|
||||||
|
|
||||||
|
|
@ -674,8 +671,8 @@ replica servers:
|
||||||
> # Set the module path location
|
> # Set the module path location
|
||||||
> modulepath /opt/symas/lib/openldap
|
> modulepath /opt/symas/lib/openldap
|
||||||
>
|
>
|
||||||
> # Load the hdb backend
|
> # Load the mdb backend
|
||||||
> moduleload back_hdb.la
|
> moduleload back_mdb.la
|
||||||
>
|
>
|
||||||
> # Load the accesslog overlay
|
> # Load the accesslog overlay
|
||||||
> moduleload accesslog.la
|
> moduleload accesslog.la
|
||||||
|
|
@ -684,7 +681,7 @@ replica servers:
|
||||||
> moduleload syncprov.la
|
> moduleload syncprov.la
|
||||||
>
|
>
|
||||||
> # Accesslog database definitions
|
> # Accesslog database definitions
|
||||||
> database hdb
|
> database mdb
|
||||||
> suffix cn=accesslog
|
> suffix cn=accesslog
|
||||||
> directory /db/accesslog
|
> directory /db/accesslog
|
||||||
> rootdn cn=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
|
> limits dn.exact="cn=replicator,dc=symas,dc=com" time.soft=unlimited time.hard=unlimited size.soft=unlimited size.hard=unlimited
|
||||||
>
|
>
|
||||||
> # Primary database definitions
|
> # Primary database definitions
|
||||||
> database hdb
|
> database mdb
|
||||||
> suffix "dc=symas,dc=com"
|
> suffix "dc=symas,dc=com"
|
||||||
> rootdn "cn=manager,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
|
H4: Delta-syncrepl Consumer configuration
|
||||||
|
|
||||||
> # Replica database configuration
|
> # Replica database configuration
|
||||||
> database hdb
|
> database mdb
|
||||||
> suffix "dc=symas,dc=com"
|
> suffix "dc=symas,dc=com"
|
||||||
> rootdn "cn=manager,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
|
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,
|
in your database that can be used to bind to the provider.
|
||||||
all of the databases (primary, replica, and the accesslog
|
|
||||||
storage database) should also have properly tuned {{DB_CONFIG}} files that meet
|
|
||||||
your needs.
|
|
||||||
|
|
||||||
Note: An accesslog database is unique to a given master. It should
|
Note: An accesslog database is unique to a given master. It should
|
||||||
never be replicated.
|
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
|
> include /usr/local/etc/openldap/slapd.acl
|
||||||
>
|
>
|
||||||
> modulepath /usr/local/libexec/openldap
|
> modulepath /usr/local/libexec/openldap
|
||||||
> moduleload back_hdb.la
|
> moduleload back_mdb.la
|
||||||
> moduleload syncprov.la
|
> moduleload syncprov.la
|
||||||
> moduleload back_monitor.la
|
> moduleload back_monitor.la
|
||||||
> moduleload back_ldap.la
|
> moduleload back_ldap.la
|
||||||
|
|
@ -988,7 +982,7 @@ The following example is for a self-contained push-based replication solution:
|
||||||
>
|
>
|
||||||
> loglevel sync stats
|
> loglevel sync stats
|
||||||
>
|
>
|
||||||
> database hdb
|
> database mdb
|
||||||
> suffix "dc=suretecsystems,dc=com"
|
> suffix "dc=suretecsystems,dc=com"
|
||||||
> directory /usr/local/var/openldap-data
|
> 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
|
> include /usr/local/etc/openldap/slapd.acl
|
||||||
>
|
>
|
||||||
> modulepath /usr/local/libexec/openldap
|
> modulepath /usr/local/libexec/openldap
|
||||||
> moduleload back_hdb.la
|
> moduleload back_mdb.la
|
||||||
> moduleload syncprov.la
|
> moduleload syncprov.la
|
||||||
> moduleload back_monitor.la
|
> moduleload back_monitor.la
|
||||||
> moduleload back_ldap.la
|
> moduleload back_ldap.la
|
||||||
|
|
@ -1074,7 +1068,7 @@ A replica configuration for this type of setup could be:
|
||||||
>
|
>
|
||||||
> loglevel sync stats
|
> loglevel sync stats
|
||||||
>
|
>
|
||||||
> database hdb
|
> database mdb
|
||||||
> suffix "dc=suretecsystems,dc=com"
|
> suffix "dc=suretecsystems,dc=com"
|
||||||
> directory /usr/local/var/openldap-slave/data
|
> directory /usr/local/var/openldap-slave/data
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -364,10 +364,8 @@ supported backend types listed in Table 5.2.
|
||||||
!block table; align=Center; coltags="EX,N"; \
|
!block table; align=Center; coltags="EX,N"; \
|
||||||
title="Table 5.2: Database Backends"
|
title="Table 5.2: Database Backends"
|
||||||
Types Description
|
Types Description
|
||||||
bdb Berkeley DB transactional backend (deprecated)
|
|
||||||
config Slapd configuration backend
|
config Slapd configuration backend
|
||||||
dnssrv DNS SRV backend
|
dnssrv DNS SRV backend
|
||||||
hdb Hierarchical variant of bdb backend (deprecated)
|
|
||||||
ldap Lightweight Directory Access Protocol (Proxy) backend
|
ldap Lightweight Directory Access Protocol (Proxy) backend
|
||||||
ldif Lightweight Data Interchange Format backend
|
ldif Lightweight Data Interchange Format backend
|
||||||
mdb Memory-Mapped DB backend
|
mdb Memory-Mapped DB backend
|
||||||
|
|
@ -381,7 +379,7 @@ sql SQL Programmable backend
|
||||||
|
|
||||||
\Example:
|
\Example:
|
||||||
|
|
||||||
> olcBackend: bdb
|
> olcBackend: mdb
|
||||||
|
|
||||||
There are no other directives defined for this entry. Specific backend
|
There are no other directives defined for this entry. Specific backend
|
||||||
types may define additional attributes for their particular use but so
|
types may define additional attributes for their particular use but so
|
||||||
|
|
@ -391,9 +389,9 @@ not appear in any actual configurations.
|
||||||
|
|
||||||
H4: Sample Entry
|
H4: Sample Entry
|
||||||
|
|
||||||
> dn: olcBackend=bdb,cn=config
|
> dn: olcBackend=mdb,cn=config
|
||||||
> objectClass: olcBackendConfig
|
> objectClass: olcBackendConfig
|
||||||
> olcBackend: bdb
|
> olcBackend: mdb
|
||||||
|
|
||||||
|
|
||||||
H3: Database-specific Directives
|
H3: Database-specific Directives
|
||||||
|
|
@ -421,9 +419,9 @@ databases.
|
||||||
|
|
||||||
\Example:
|
\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>] ]+
|
H4: olcAccess: to <what> [ by <who> [<accesslevel>] [<control>] ]+
|
||||||
|
|
@ -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
|
parameter is omitted or set to {{EX:"default"}} then the log
|
||||||
parameters are ignored.
|
parameters are ignored.
|
||||||
|
|
||||||
The {{syncrepl}} replication mechanism is supported by the {{bdb}},
|
The {{syncrepl}} replication mechanism is supported by the {{mdb}}
|
||||||
{{hdb}}, and {{mdb}} backends.
|
backend.
|
||||||
|
|
||||||
See the {{SECT:LDAP Sync Replication}} chapter of this guide for
|
See the {{SECT:LDAP Sync Replication}} chapter of this guide for
|
||||||
more information on how to use this directive.
|
more information on how to use this directive.
|
||||||
|
|
@ -731,21 +729,20 @@ H4: Sample Entries
|
||||||
>olcRootDN: cn=Manager,dc=example,dc=com
|
>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}}
|
Directives in this category apply to the {{TERM:MDB}}
|
||||||
and the {{TERM:HDB}} database.
|
database backend.
|
||||||
They are used in an olcDatabase entry in addition to the generic
|
They are used in an olcDatabase entry in addition to the generic
|
||||||
database directives defined above. For a complete reference
|
database directives defined above. For a complete reference
|
||||||
of BDB/HDB configuration directives, see {{slapd-bdb}}(5). In
|
of MDB configuration directives, see {{slapd-mdb}}(5). In
|
||||||
addition to the {{EX:olcDatabaseConfig}} objectClass, BDB and HDB
|
addition to the {{EX:olcDatabaseConfig}} objectClass, MDB
|
||||||
database entries must have the {{EX:olcBdbConfig}} and
|
database entries must have the {{EX:olcMdbConfig}} objectClass.
|
||||||
{{EX:olcHdbConfig}} objectClass, respectively.
|
|
||||||
|
|
||||||
|
|
||||||
H4: olcDbDirectory: <directory>
|
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.
|
containing the database and associated indices live.
|
||||||
|
|
||||||
\Default:
|
\Default:
|
||||||
|
|
@ -753,98 +750,48 @@ containing the database and associated indices live.
|
||||||
> olcDbDirectory: /usr/local/var/openldap-data
|
> 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>
|
H4: olcDbCheckpoint: <kbyte> <min>
|
||||||
|
|
||||||
This directive specifies how often to checkpoint the BDB transaction log.
|
This directive specifies the frequency for flushing the database disk
|
||||||
A checkpoint operation flushes the database buffers to disk and writes a
|
buffers. This directive is only needed if the {{olcDbNoSync}} option is
|
||||||
checkpoint record in the log.
|
{{EX:TRUE}}.
|
||||||
The checkpoint will occur if either <kbyte> data has been written or
|
The checkpoint will occur if either <kbyte> data has been written or
|
||||||
<min> minutes have passed since the last checkpoint. Both arguments default
|
<min> minutes have passed since the last checkpoint. Both arguments default
|
||||||
to zero, in which case they are ignored. When the <min> argument is
|
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
|
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:
|
\Example:
|
||||||
|
|
||||||
> olcDbCheckpoint: 1024 10
|
> 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
|
This option specifies flags for finer-grained control of the LMDB library's
|
||||||
{{EX:DB_CONFIG}} file of the database directory. At server startup time, if
|
operation.
|
||||||
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.
|
|
||||||
|
|
||||||
Any changes made to this attribute will be written to the {{EX:DB_CONFIG}}
|
* {{F:nosync}}: This is exactly the same as the dbnosync directive.
|
||||||
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.
|
|
||||||
|
|
||||||
\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
|
* {{F:writemap}}: Use a writable memory map instead of just read-only. This
|
||||||
> olcDbConfig: set_lg_bsize 2097512
|
speeds up write operations but makes the database vulnerable to corruption in
|
||||||
> olcDbConfig: set_lg_dir /var/tmp/bdb-log
|
case any bugs in slapd cause stray writes into the mmap region.
|
||||||
> olcDbConfig: set_flags DB_LOG_AUTOREMOVE
|
|
||||||
|
|
||||||
In this example, the BDB cache is set to 10MB, the BDB transaction log
|
* {{F:mapasync}}: When using a writable memory map and performing flushes on
|
||||||
buffer size is set to 2MB, and the transaction log files are to be stored
|
each commit, use an asynchronous flush instead of a synchronous flush (the
|
||||||
in the /var/tmp/bdb-log directory. Also a flag is set to tell BDB to
|
default). This option has no effect if writemap has not been set. It also has
|
||||||
delete transaction log files as soon as their contents have been
|
no effect if nosync is set.
|
||||||
checkpointed and they are no longer needed. Without this setting the
|
|
||||||
transaction log files will continue to accumulate until some other
|
|
||||||
cleanup procedure removes them. See the Berkeley DB documentation for the
|
|
||||||
{{EX:db_archive}} command for details. For a complete list of Berkeley DB
|
|
||||||
flags please see - {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/api_c/env_set_flags.html}}
|
|
||||||
|
|
||||||
Ideally the BDB cache must be
|
* {{F:nordahead}}: Turn off file readahead. Usually the OS performs readahead
|
||||||
at least as large as the working set of the database, the log buffer size
|
on every read request. This usually boosts read performance but can be
|
||||||
should be large enough to accommodate most transactions without overflowing,
|
harmful to random access read performance if the system's memory is full and
|
||||||
and the log directory must be on a separate physical disk from the main
|
the DB is larger than RAM. This option is not implemented on Windows.
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
H4: olcDbIndex: {<attrlist> | default} [pres,eq,approx,sub,none]
|
H4: olcDbIndex: {<attrlist> | default} [pres,eq,approx,sub,none]
|
||||||
|
|
@ -890,7 +837,7 @@ attribute that inherits from {{EX:name}} to be indexed.
|
||||||
By default, no indices are maintained. It is generally advised
|
By default, no indices are maintained. It is generally advised
|
||||||
that minimally an equality index upon objectClass be maintained.
|
that minimally an equality index upon objectClass be maintained.
|
||||||
|
|
||||||
> olcDbindex: objectClass eq
|
> olcDbIndex: objectClass eq
|
||||||
|
|
||||||
Additional indices should be configured corresponding to the
|
Additional indices should be configured corresponding to the
|
||||||
most common searches that are used on the database.
|
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.
|
manually completed using the slapindex tool.
|
||||||
|
|
||||||
|
|
||||||
H4: olcDbLinearIndex: { TRUE | FALSE }
|
H4: olcDbMaxReaders: <integer>
|
||||||
|
|
||||||
If this setting is {{EX:TRUE}} slapindex will index one attribute
|
This directive specifies the maximum number of threads that may have
|
||||||
at a time. The default settings is {{EX:FALSE}} in which case all
|
concurrent read access to the database. Tools such as slapcat count as a
|
||||||
indexed attributes of an entry are processed at the same time. When
|
single thread, in addition to threads in any active slapd processes. The
|
||||||
enabled, each indexed attribute is processed individually, using
|
default is 126.
|
||||||
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
|
H4: olcDbMaxSize: <bytes>
|
||||||
and will decrease performance. Also by default, slapadd performs
|
|
||||||
full indexing and so a separate slapindex run is not needed. With
|
This directive specifies the maximum size of the database in bytes. A memory
|
||||||
this option, slapadd does no indexing and slapindex must be used.
|
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> }
|
H4: olcDbMode: { <octal> | <symbolic> }
|
||||||
|
|
@ -932,6 +885,18 @@ created database index files should have. This can be in the form
|
||||||
> olcDbMode: 0600
|
> 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>
|
H4: olcDbSearchStack: <integer>
|
||||||
|
|
||||||
Specify the depth of the stack used for search filter evaluation.
|
Specify the depth of the stack used for search filter evaluation.
|
||||||
|
|
@ -955,33 +920,21 @@ to take effect.
|
||||||
> olcDbSearchStack: 16
|
> olcDbSearchStack: 16
|
||||||
|
|
||||||
|
|
||||||
H4: olcDbShmKey: <integer>
|
H4: olcDbNosync: { TRUE | FALSE }
|
||||||
|
|
||||||
Specify a key for a shared memory BDB environment. By default the BDB
|
This directive causes on-disk database contents to not be immediately
|
||||||
environment uses memory mapped files. If a non-zero value is specified,
|
synchronized with in memory changes upon change. Setting this option
|
||||||
it will be used as the key to identify a shared memory region that will
|
to {{EX:TRUE}} may improve performance at the expense of data integrity.
|
||||||
house the environment.
|
|
||||||
|
|
||||||
\Example:
|
|
||||||
|
|
||||||
> olcDbShmKey: 42
|
|
||||||
|
|
||||||
|
|
||||||
H4: Sample Entry
|
H4: Sample Entry
|
||||||
|
|
||||||
>dn: olcDatabase=hdb,cn=config
|
>dn: olcDatabase=mdb,cn=config
|
||||||
>objectClass: olcDatabaseConfig
|
>objectClass: olcDatabaseConfig
|
||||||
>objectClass: olcHdbConfig
|
>objectClass: olcMdbConfig
|
||||||
>olcDatabase: hdb
|
>olcDatabase: mdb
|
||||||
>olcSuffix: "dc=example,dc=com"
|
>olcSuffix: "dc=example,dc=com"
|
||||||
>olcDbDirectory: /usr/local/var/openldap-data
|
>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
|
>olcDbIndex: objectClass eq
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -989,7 +942,7 @@ H2: Configuration Example
|
||||||
|
|
||||||
The following is an example configuration, interspersed
|
The following is an example configuration, interspersed
|
||||||
with explanatory text. It defines two databases to handle
|
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
|
database instances. The line numbers shown are provided for
|
||||||
reference only and are not included in the actual file. First, the
|
reference only and are not included in the actual file. First, the
|
||||||
global configuration section:
|
global configuration section:
|
||||||
|
|
@ -1066,16 +1019,16 @@ inaccessible.)
|
||||||
|
|
||||||
Line 28 is a blank line.
|
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
|
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
|
for several attributes, and the {{EX:userPassword}} attribute is to be
|
||||||
protected from unauthorized access.
|
protected from unauthorized access.
|
||||||
|
|
||||||
E: 29. # BDB definition for example.com
|
E: 29. # MDB definition for example.com
|
||||||
E: 30. dn: olcDatabase=bdb,cn=config
|
E: 30. dn: olcDatabase=mdb,cn=config
|
||||||
E: 31. objectClass: olcDatabaseConfig
|
E: 31. objectClass: olcDatabaseConfig
|
||||||
E: 32. objectClass: olcBdbConfig
|
E: 32. objectClass: olcMdbConfig
|
||||||
E: 33. olcDatabase: bdb
|
E: 33. olcDatabase: mdb
|
||||||
E: 34. olcSuffix: dc=example,dc=com
|
E: 34. olcSuffix: dc=example,dc=com
|
||||||
E: 35. olcDbDirectory: /usr/local/var/openldap-data
|
E: 35. olcDbDirectory: /usr/local/var/openldap-data
|
||||||
E: 36. olcRootDN: cn=Manager,dc=example,dc=com
|
E: 36. olcRootDN: cn=Manager,dc=example,dc=com
|
||||||
|
|
@ -1094,7 +1047,7 @@ E: 48. by dn.base="cn=Admin,dc=example,dc=com" write
|
||||||
E: 49. by * read
|
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
|
configuration entry. Line 34 specifies the DN suffix
|
||||||
for queries to pass to this database. Line 35 specifies the directory
|
for queries to pass to this database. Line 35 specifies the directory
|
||||||
in which the database files will live.
|
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.
|
Line 50 is a blank line, indicating the end of this entry.
|
||||||
|
|
||||||
The next entry defines another
|
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
|
{{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
|
as the first database. Note that without line 60, the read access
|
||||||
would be allowed due to the global access rule at line 19.
|
would be allowed due to the global access rule at line 19.
|
||||||
|
|
||||||
E: 51. # BDB definition for example.net
|
E: 51. # MDB definition for example.net
|
||||||
E: 52. dn: olcDatabase=bdb,cn=config
|
E: 52. dn: olcDatabase=mdb,cn=config
|
||||||
E: 53. objectClass: olcDatabaseConfig
|
E: 53. objectClass: olcDatabaseConfig
|
||||||
E: 54. objectClass: olcBdbConfig
|
E: 54. objectClass: olcMdbConfig
|
||||||
E: 55. olcDatabase: bdb
|
E: 55. olcDatabase: mdb
|
||||||
E: 56. olcSuffix: "dc=example,dc=net"
|
E: 56. olcSuffix: "dc=example,dc=net"
|
||||||
E: 57. olcDbDirectory: /usr/local/var/openldap-data-net
|
E: 57. olcDbDirectory: /usr/local/var/openldap-data-net
|
||||||
E: 58. olcRootDN: "cn=Manager,dc=example,dc=com"
|
E: 58. olcRootDN: "cn=Manager,dc=example,dc=com"
|
||||||
|
|
|
||||||
|
|
@ -264,9 +264,7 @@ supported backend types listed in Table 6.2.
|
||||||
!block table; align=Center; coltags="EX,N"; \
|
!block table; align=Center; coltags="EX,N"; \
|
||||||
title="Table 6.2: Database Backends"
|
title="Table 6.2: Database Backends"
|
||||||
Types Description
|
Types Description
|
||||||
bdb Berkeley DB transactional backend (deprecated)
|
|
||||||
dnssrv DNS SRV backend
|
dnssrv DNS SRV backend
|
||||||
hdb Hierarchical variant of bdb backend (deprecated)
|
|
||||||
ldap Lightweight Directory Access Protocol (Proxy) backend
|
ldap Lightweight Directory Access Protocol (Proxy) backend
|
||||||
mdb Memory-Mapped DB backend
|
mdb Memory-Mapped DB backend
|
||||||
meta Meta Directory backend
|
meta Meta Directory backend
|
||||||
|
|
@ -279,9 +277,9 @@ sql SQL Programmable backend
|
||||||
|
|
||||||
\Example:
|
\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.
|
definition.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -299,9 +297,9 @@ supported backend types listed in Table 6.2.
|
||||||
|
|
||||||
\Example:
|
\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.
|
declaration.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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
|
parameter is omitted or set to {{EX:"default"}} then the log
|
||||||
parameters are ignored.
|
parameters are ignored.
|
||||||
|
|
||||||
The {{syncrepl}} replication mechanism is supported by the {{bdb}},
|
The {{syncrepl}} replication mechanism is supported by the {{mdb}} backend.
|
||||||
{{hdb}}, and {{mdb}} backends.
|
|
||||||
|
|
||||||
See the {{SECT:LDAP Sync Replication}} chapter of this guide for
|
See the {{SECT:LDAP Sync Replication}} chapter of this guide for
|
||||||
more information on how to use this directive.
|
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
|
> 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}}
|
Directives in this category only apply to the {{TERM:MDB}}
|
||||||
and the {{TERM:HDB}} database.
|
database backend.
|
||||||
That is, they must follow a "database bdb" or "database hdb" line
|
That is, they must follow a "database mdb" line
|
||||||
and come before any
|
and come before any subsequent "backend" or "database" lines.
|
||||||
subsequent "backend" or "database" line. For a complete reference
|
For a complete reference of MDB configuration directives, see {{slapd-mdb}}(5).
|
||||||
of BDB/HDB configuration directives, see {{slapd-bdb}}(5).
|
|
||||||
|
|
||||||
|
|
||||||
H4: directory <directory>
|
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.
|
containing the database and associated indices live.
|
||||||
|
|
||||||
\Default:
|
\Default:
|
||||||
|
|
||||||
> directory /usr/local/var/openldap-data
|
> 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
|
H2: Configuration File Example
|
||||||
|
|
||||||
The following is an example configuration file, interspersed
|
The following is an example configuration file, interspersed
|
||||||
with explanatory text. It defines two databases to handle
|
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
|
database instances. The line numbers shown are provided for
|
||||||
reference only and are not included in the actual file. First, the
|
reference only and are not included in the actual file. First, the
|
||||||
global configuration section:
|
global configuration section:
|
||||||
|
|
@ -629,7 +802,7 @@ Line 4 is a global access control. It applies to all
|
||||||
entries (after any applicable database-specific access
|
entries (after any applicable database-specific access
|
||||||
controls).
|
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
|
backend that will handle queries for things in the
|
||||||
"dc=example,dc=com" portion of the tree. The
|
"dc=example,dc=com" portion of the tree. The
|
||||||
database is to be replicated to two slave slapds, one on
|
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}}
|
maintained for several attributes, and the {{EX:userPassword}}
|
||||||
attribute is to be protected from unauthorized access.
|
attribute is to be protected from unauthorized access.
|
||||||
|
|
||||||
E: 5. # BDB definition for the example.com
|
E: 5. # MDB definition for the example.com
|
||||||
E: 6. database bdb
|
E: 6. database mdb
|
||||||
E: 7. suffix "dc=example,dc=com"
|
E: 7. suffix "dc=example,dc=com"
|
||||||
E: 8. directory /usr/local/var/openldap-data
|
E: 8. directory /usr/local/var/openldap-data
|
||||||
E: 9. rootdn "cn=Manager,dc=example,dc=com"
|
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).
|
entry, but may be read by all users (authenticated or not).
|
||||||
|
|
||||||
The next section of the example configuration file defines another
|
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
|
{{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
|
as the first database. Note that without line 39, the read access
|
||||||
would be allowed due to the global access rule at line 4.
|
would be allowed due to the global access rule at line 4.
|
||||||
|
|
||||||
E: 33. # BDB definition for example.net
|
E: 33. # MDB definition for example.net
|
||||||
E: 34. database bdb
|
E: 34. database mdb
|
||||||
E: 35. suffix "dc=example,dc=net"
|
E: 35. suffix "dc=example,dc=net"
|
||||||
E: 36. directory /usr/local/var/openldap-data-net
|
E: 36. directory /usr/local/var/openldap-data-net
|
||||||
E: 37. rootdn "cn=Manager,dc=example,dc=com"
|
E: 37. rootdn "cn=Manager,dc=example,dc=com"
|
||||||
|
|
|
||||||
|
|
@ -27,10 +27,6 @@ H3: Memory
|
||||||
|
|
||||||
Scale your cache to use available memory and increase system memory if you can.
|
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
|
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
|
tend to provide better write performance than everything else, including
|
||||||
newer filesystems like EXT4, BTRFS, etc.)
|
newer filesystems like EXT4, BTRFS, etc.)
|
||||||
|
|
||||||
Use fast subsystems. Put each database and logs on separate disks
|
Use fast subsystems. Put each database 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
|
|
||||||
|
|
||||||
|
|
||||||
H3: Network Topology
|
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:
|
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>}})
|
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
|
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.
|
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
|
H2: {{slapd}}(8) Threads
|
||||||
|
|
||||||
{{slapd}}(8) can process requests via a configurable number of threads, which
|
{{slapd}}(8) can process requests via a configurable number of threads, which
|
||||||
|
|
|
||||||
|
|
@ -167,7 +167,6 @@ AuthcId|Authentication Identity
|
||||||
AuthzDN|Authorization DN
|
AuthzDN|Authorization DN
|
||||||
AuthzId|Authorization Identity
|
AuthzId|Authorization Identity
|
||||||
BCP|Best Current Practice
|
BCP|Best Current Practice
|
||||||
BDB|Berkeley DB (Backend)
|
|
||||||
BER|Basic Encoding Rules
|
BER|Basic Encoding Rules
|
||||||
BNF|Backus-Naur Form
|
BNF|Backus-Naur Form
|
||||||
C|The C Programming Language
|
C|The C Programming Language
|
||||||
|
|
@ -201,7 +200,6 @@ FYI|For Your Information
|
||||||
GSER|Generic String Encoding Rules
|
GSER|Generic String Encoding Rules
|
||||||
GSS-API|Generic Security Service Application Program Interface
|
GSS-API|Generic Security Service Application Program Interface
|
||||||
GSSAPI|SASL Kerberos V GSS-API Authentication Mechanism
|
GSSAPI|SASL Kerberos V GSS-API Authentication Mechanism
|
||||||
HDB|Hierarchical Database (Backend)
|
|
||||||
I-D|Internet-Draft
|
I-D|Internet-Draft
|
||||||
IA5|International Alphabet 5
|
IA5|International Alphabet 5
|
||||||
IDNA|Internationalized Domain Names in Applications
|
IDNA|Internationalized Domain Names in Applications
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ if you have not done so already.
|
||||||
+ Test the standalone system:
|
+ Test the standalone system:
|
||||||
|
|
||||||
.This step requires the standalone LDAP server, {{slapd}}(8),
|
.This step requires the standalone LDAP server, {{slapd}}(8),
|
||||||
with {{HDB}} and/or {{BDB}} support.
|
with {{MDB}} support.
|
||||||
|
|
||||||
E: % make test
|
E: % make test
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
slapd-hdb.5
|
|
||||||
|
|
@ -1149,10 +1149,8 @@ The entry must be named
|
||||||
and must have the olcBackendConfig objectClass.
|
and must have the olcBackendConfig objectClass.
|
||||||
<databasetype>
|
<databasetype>
|
||||||
should be one of
|
should be one of
|
||||||
.BR bdb ,
|
|
||||||
.BR config ,
|
.BR config ,
|
||||||
.BR dnssrv ,
|
.BR dnssrv ,
|
||||||
.BR hdb ,
|
|
||||||
.BR ldap ,
|
.BR ldap ,
|
||||||
.BR ldif ,
|
.BR ldif ,
|
||||||
.BR mdb ,
|
.BR mdb ,
|
||||||
|
|
@ -2091,10 +2089,10 @@ olcDatabase: config
|
||||||
olcRootPW: {SSHA}XKYnrjvGT3wZFQrDD5040US592LxsdLy
|
olcRootPW: {SSHA}XKYnrjvGT3wZFQrDD5040US592LxsdLy
|
||||||
olcAccess: to * by * none
|
olcAccess: to * by * none
|
||||||
|
|
||||||
dn: olcDatabase=bdb,cn=config
|
dn: olcDatabase=mdb,cn=config
|
||||||
objectClass: olcDatabaseConfig
|
objectClass: olcDatabaseConfig
|
||||||
objectClass: olcBdbConfig
|
objectClass: olcMdbConfig
|
||||||
olcDatabase: bdb
|
olcDatabase: mdb
|
||||||
olcSuffix: "dc=our\-domain,dc=com"
|
olcSuffix: "dc=our\-domain,dc=com"
|
||||||
# The database directory MUST exist prior to
|
# The database directory MUST exist prior to
|
||||||
# running slapd AND should only be accessible
|
# running slapd AND should only be accessible
|
||||||
|
|
|
||||||
|
|
@ -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
|
management and does no caching of its own. It is the recommended
|
||||||
primary database backend.
|
primary database backend.
|
||||||
.LP
|
.LP
|
||||||
The \fBmdb\fP backend is similar to the \fBhdb\fP backend in that
|
The \fBmdb\fP backend uses a hierarchical database layout which
|
||||||
it uses a hierarchical database layout which
|
supports subtree renames.
|
||||||
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.
|
|
||||||
.SH CONFIGURATION
|
.SH CONFIGURATION
|
||||||
These
|
These
|
||||||
.B slapd.conf
|
.B slapd.conf
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ sites/applications that use RDBMSes and/or LDAP.
|
||||||
Or whatever else...
|
Or whatever else...
|
||||||
.LP
|
.LP
|
||||||
It is NOT designed as a general-purpose backend that uses RDBMS instead
|
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.
|
used as such with several limitations.
|
||||||
You can take a look at
|
You can take a look at
|
||||||
.B http://www.openldap.org/faq/index.cgi?file=378
|
.B http://www.openldap.org/faq/index.cgi?file=378
|
||||||
|
|
|
||||||
|
|
@ -920,9 +920,8 @@ identity, control is passed straight to the subsequent rules.
|
||||||
|
|
||||||
.SH OPERATION REQUIREMENTS
|
.SH OPERATION REQUIREMENTS
|
||||||
Operations require different privileges on different portions of entries.
|
Operations require different privileges on different portions of entries.
|
||||||
The following summary applies to primary MDB database backend and the
|
The following summary applies to primary MDB database backend. Requirements
|
||||||
deprecated BDB and HDB backends. Requirements for other backends may
|
for other backends may (and often do) differ.
|
||||||
(and often do) differ.
|
|
||||||
|
|
||||||
.LP
|
.LP
|
||||||
The
|
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
|
so it is fully honored by all backends; for all other operations
|
||||||
and for the discovery phase of the search operation,
|
and for the discovery phase of the search operation,
|
||||||
full ACL semantics is only supported by the primary backends, i.e.
|
full ACL semantics is only supported by the primary backends, i.e.
|
||||||
.BR back\-bdb (5),
|
.BR back\-mdb (5).
|
||||||
and
|
|
||||||
.BR back\-hdb (5).
|
|
||||||
|
|
||||||
Some other backend, like
|
Some other backend, like
|
||||||
.BR back\-sql (5),
|
.BR back\-sql (5),
|
||||||
|
|
|
||||||
|
|
@ -19,14 +19,6 @@ corresponding
|
||||||
.BR slapd\-<backend> (5)
|
.BR slapd\-<backend> (5)
|
||||||
manual pages.
|
manual pages.
|
||||||
.TP
|
.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
|
.B config
|
||||||
This backend is used to manage the configuration of slapd at run-time.
|
This backend is used to manage the configuration of slapd at run-time.
|
||||||
Unlike other backends, only a single instance of the
|
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
|
It serves up referrals based upon SRV resource records held in the
|
||||||
Domain Name System.
|
Domain Name System.
|
||||||
.TP
|
.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
|
.B ldap
|
||||||
This backend acts as a proxy to forward incoming requests to another
|
This backend acts as a proxy to forward incoming requests to another
|
||||||
LDAP server.
|
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.
|
is not a requirement. This backend also supports subtree renames.
|
||||||
.TP
|
.TP
|
||||||
.B mdb
|
.B mdb
|
||||||
This is the recommended primary backend, superseding
|
This is the recommended primary backend.
|
||||||
.BR hdb .
|
|
||||||
This backend uses OpenLDAP's own MDB transactional database
|
This backend uses OpenLDAP's own MDB transactional database
|
||||||
library. It is extremely compact and extremely efficient, delivering
|
library. This backend also supports subtree renames.
|
||||||
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.
|
|
||||||
.TP
|
.TP
|
||||||
.B meta
|
.B meta
|
||||||
This backend performs basic LDAP proxying with respect to a set of
|
This backend performs basic LDAP proxying with respect to a set of
|
||||||
|
|
@ -138,10 +109,8 @@ ETCDIR/slapd.d
|
||||||
default slapd configuration directory
|
default slapd configuration directory
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.BR ldap (3),
|
.BR ldap (3),
|
||||||
.BR slapd\-bdb (5),
|
|
||||||
.BR slapd\-config (5),
|
.BR slapd\-config (5),
|
||||||
.BR slapd\-dnssrv (5),
|
.BR slapd\-dnssrv (5),
|
||||||
.BR slapd\-hdb (5),
|
|
||||||
.BR slapd\-ldap (5),
|
.BR slapd\-ldap (5),
|
||||||
.BR slapd\-ldif (5),
|
.BR slapd\-ldif (5),
|
||||||
.BR slapd\-mdb (5),
|
.BR slapd\-mdb (5),
|
||||||
|
|
|
||||||
|
|
@ -1276,10 +1276,8 @@ type of backend.
|
||||||
.B backend <databasetype>
|
.B backend <databasetype>
|
||||||
Mark the beginning of a backend definition. <databasetype>
|
Mark the beginning of a backend definition. <databasetype>
|
||||||
should be one of
|
should be one of
|
||||||
.BR bdb ,
|
|
||||||
.BR config ,
|
.BR config ,
|
||||||
.BR dnssrv ,
|
.BR dnssrv ,
|
||||||
.BR hdb ,
|
|
||||||
.BR ldap ,
|
.BR ldap ,
|
||||||
.BR ldif ,
|
.BR ldif ,
|
||||||
.BR mdb ,
|
.BR mdb ,
|
||||||
|
|
@ -1306,10 +1304,8 @@ option are mandatory for each database.
|
||||||
.B database <databasetype>
|
.B database <databasetype>
|
||||||
Mark the beginning of a new database instance definition. <databasetype>
|
Mark the beginning of a new database instance definition. <databasetype>
|
||||||
should be one of
|
should be one of
|
||||||
.BR bdb ,
|
|
||||||
.BR config ,
|
.BR config ,
|
||||||
.BR dnssrv ,
|
.BR dnssrv ,
|
||||||
.BR hdb ,
|
|
||||||
.BR ldap ,
|
.BR ldap ,
|
||||||
.BR ldif ,
|
.BR ldif ,
|
||||||
.BR mdb ,
|
.BR mdb ,
|
||||||
|
|
@ -1619,8 +1615,7 @@ By default, mirrormode is off.
|
||||||
This option enables database-specific monitoring in the entry related
|
This option enables database-specific monitoring in the entry related
|
||||||
to the current database in the "cn=Databases,cn=Monitor" subtree
|
to the current database in the "cn=Databases,cn=Monitor" subtree
|
||||||
of the monitor database, if the monitor database is enabled.
|
of the monitor database, if the monitor database is enabled.
|
||||||
Currently, only the BDB and the HDB databases provide database-specific
|
Currently, only the MDB database provides database-specific monitoring.
|
||||||
monitoring.
|
|
||||||
The default depends on the backend type.
|
The default depends on the backend type.
|
||||||
.TP
|
.TP
|
||||||
.B overlay <overlay-name>
|
.B overlay <overlay-name>
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ password resets, etc.
|
||||||
.B refint
|
.B refint
|
||||||
Referential Integrity.
|
Referential Integrity.
|
||||||
This overlay can be used with a backend database such as
|
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
|
to maintain the cohesiveness of a schema which utilizes reference
|
||||||
attributes.
|
attributes.
|
||||||
.TP
|
.TP
|
||||||
|
|
@ -121,7 +121,7 @@ replication, including persistent search functionality.
|
||||||
.B translucent
|
.B translucent
|
||||||
Translucent Proxy.
|
Translucent Proxy.
|
||||||
This overlay can be used with a backend database such as
|
This overlay can be used with a backend database such as
|
||||||
.BR slapd\-bdb (5)
|
.BR slapd\-mdb (5)
|
||||||
to create a "translucent proxy".
|
to create a "translucent proxy".
|
||||||
Content of entries retrieved from a remote LDAP server can be partially
|
Content of entries retrieved from a remote LDAP server can be partially
|
||||||
overridden by the database.
|
overridden by the database.
|
||||||
|
|
@ -129,7 +129,7 @@ overridden by the database.
|
||||||
.B unique
|
.B unique
|
||||||
Attribute Uniqueness.
|
Attribute Uniqueness.
|
||||||
This overlay can be used with a backend database such as
|
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.
|
to enforce the uniqueness of some or all attributes within a subtree.
|
||||||
.TP
|
.TP
|
||||||
.B valsort
|
.B valsort
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ slapo\-refint \- Referential Integrity overlay to slapd
|
||||||
ETCDIR/slapd.conf
|
ETCDIR/slapd.conf
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
The Referential Integrity overlay can be used with a backend database such as
|
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.
|
to maintain the cohesiveness of a schema which utilizes reference attributes.
|
||||||
.LP
|
.LP
|
||||||
Integrity is maintained by updating database records which contain the named
|
Integrity is maintained by updating database records which contain the named
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ slapo\-translucent \- Translucent Proxy overlay to slapd
|
||||||
ETCDIR/slapd.conf
|
ETCDIR/slapd.conf
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
The Translucent Proxy overlay can be used with a backend database such as
|
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
|
to create a "translucent proxy". Entries retrieved from a remote LDAP
|
||||||
server may have some or all attributes overridden, or new attributes
|
server may have some or all attributes overridden, or new attributes
|
||||||
added, by entries in the local database before being presented to the
|
added, by entries in the local database before being presented to the
|
||||||
|
|
|
||||||
|
|
@ -177,8 +177,6 @@ mode) when you do this to ensure consistency of the database. It is
|
||||||
always safe to run
|
always safe to run
|
||||||
.B slapcat
|
.B slapcat
|
||||||
with the
|
with the
|
||||||
.BR slapd\-bdb (5),
|
|
||||||
.BR slapd\-hdb (5),
|
|
||||||
.BR slapd\-mdb (5),
|
.BR slapd\-mdb (5),
|
||||||
and
|
and
|
||||||
.BR slapd\-null (5)
|
.BR slapd\-null (5)
|
||||||
|
|
|
||||||
|
|
@ -168,8 +168,7 @@ mode) when you do this to ensure consistency of the database. It is
|
||||||
always safe to run
|
always safe to run
|
||||||
.B slapschema
|
.B slapschema
|
||||||
with the
|
with the
|
||||||
.BR slapd\-bdb (5),
|
.BR slapd\-mdb (5),
|
||||||
.BR slapd\-hdb (5),
|
|
||||||
and
|
and
|
||||||
.BR slapd\-null (5)
|
.BR slapd\-null (5)
|
||||||
backends.
|
backends.
|
||||||
|
|
|
||||||
|
|
@ -96,12 +96,6 @@
|
||||||
/* Define to 1 if you have the `bcopy' function. */
|
/* Define to 1 if you have the `bcopy' function. */
|
||||||
#undef HAVE_BCOPY
|
#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. */
|
/* Define to 1 if you have the <bits/types.h> header file. */
|
||||||
#undef HAVE_BITS_TYPES_H
|
#undef HAVE_BITS_TYPES_H
|
||||||
|
|
||||||
|
|
@ -927,9 +921,6 @@
|
||||||
/* define to support LDAP Async Metadirectory backend */
|
/* define to support LDAP Async Metadirectory backend */
|
||||||
#undef SLAPD_ASYNCMETA
|
#undef SLAPD_ASYNCMETA
|
||||||
|
|
||||||
/* define to support BDB backend */
|
|
||||||
#undef SLAPD_BDB
|
|
||||||
|
|
||||||
/* define to support cleartext passwords */
|
/* define to support cleartext passwords */
|
||||||
#undef SLAPD_CLEARTEXT
|
#undef SLAPD_CLEARTEXT
|
||||||
|
|
||||||
|
|
@ -939,9 +930,6 @@
|
||||||
/* define to support DNS SRV backend */
|
/* define to support DNS SRV backend */
|
||||||
#undef SLAPD_DNSSRV
|
#undef SLAPD_DNSSRV
|
||||||
|
|
||||||
/* define to support HDB backend */
|
|
||||||
#undef SLAPD_HDB
|
|
||||||
|
|
||||||
/* define to support LDAP backend */
|
/* define to support LDAP backend */
|
||||||
#undef SLAPD_LDAP
|
#undef SLAPD_LDAP
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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).
|
|
||||||
|
|
@ -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 \
|
backglue.c backover.c ctxcsn.c ldapsync.c frontend.c \
|
||||||
slapadd.c slapcat.c slapcommon.c slapdn.c slapindex.c \
|
slapadd.c slapcat.c slapcommon.c slapdn.c slapindex.c \
|
||||||
slappasswd.c slaptest.c slapauth.c slapacl.c component.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)
|
$(@PLAT@_SRCS)
|
||||||
|
|
||||||
OBJS = main.o globals.o bconfig.o config.o daemon.o \
|
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 \
|
backglue.o backover.o ctxcsn.o ldapsync.o frontend.o \
|
||||||
slapadd.o slapcat.o slapcommon.o slapdn.o slapindex.o \
|
slapadd.o slapcat.o slapcommon.o slapdn.o slapindex.o \
|
||||||
slappasswd.o slaptest.o slapauth.o slapacl.o component.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)
|
$(@PLAT@_OBJS)
|
||||||
|
|
||||||
LDAP_INCDIR= ../../include -I$(srcdir) -I$(srcdir)/slapi -I.
|
LDAP_INCDIR= ../../include -I$(srcdir) -I$(srcdir)/slapi -I.
|
||||||
|
|
@ -366,14 +366,8 @@ veryclean-local-srv: FORCE
|
||||||
fi; \
|
fi; \
|
||||||
done
|
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-local-srv: install-slapd install-tools \
|
||||||
install-conf install-dbc-maybe install-schema install-tools
|
install-conf install-schema install-tools
|
||||||
|
|
||||||
install-slapd: FORCE
|
install-slapd: FORCE
|
||||||
-$(MKDIR) $(DESTDIR)$(libexecdir)
|
-$(MKDIR) $(DESTDIR)$(libexecdir)
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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 $@
|
|
||||||
|
|
||||||
|
|
@ -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, <id, tflags );
|
|
||||||
}
|
|
||||||
rs->sr_text = NULL;
|
|
||||||
if( rs->sr_err != 0 ) {
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_add) ": txn_begin failed: %s (%d)\n",
|
|
||||||
db_strerror(rs->sr_err), rs->sr_err );
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "internal error";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_add) ": txn1 id: %x\n",
|
|
||||||
ltid->id(ltid) );
|
|
||||||
|
|
||||||
opinfo.boi_oe.oe_key = bdb;
|
|
||||||
opinfo.boi_txn = ltid;
|
|
||||||
opinfo.boi_err = 0;
|
|
||||||
opinfo.boi_acl_cache = op->o_do_not_cache;
|
|
||||||
LDAP_SLIST_INSERT_HEAD( &op->o_extra, &opinfo.boi_oe, oe_next );
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the parent dn and see if the corresponding entry exists.
|
|
||||||
*/
|
|
||||||
if ( be_issuffix( op->o_bd, &op->ora_e->e_nname ) ) {
|
|
||||||
pdn = slap_empty_bv;
|
|
||||||
} else {
|
|
||||||
dnParent( &op->ora_e->e_nname, &pdn );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get entry or parent */
|
|
||||||
rs->sr_err = bdb_dn2entry( op, ltid, &op->ora_e->e_nname, &ei,
|
|
||||||
1, &lock );
|
|
||||||
switch( rs->sr_err ) {
|
|
||||||
case 0:
|
|
||||||
rs->sr_err = LDAP_ALREADY_EXISTS;
|
|
||||||
goto return_results;
|
|
||||||
case DB_NOTFOUND:
|
|
||||||
break;
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
case LDAP_BUSY:
|
|
||||||
rs->sr_text = "ldap server busy";
|
|
||||||
goto return_results;
|
|
||||||
default:
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "internal error";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = ei->bei_e;
|
|
||||||
if ( !p )
|
|
||||||
p = (Entry *)&slap_entry_root;
|
|
||||||
|
|
||||||
if ( !bvmatch( &pdn, &p->e_nname ) ) {
|
|
||||||
rs->sr_matched = ber_strdup_x( p->e_name.bv_val,
|
|
||||||
op->o_tmpmemctx );
|
|
||||||
rs->sr_ref = is_entry_referral( p )
|
|
||||||
? get_entry_referrals( op, p )
|
|
||||||
: NULL;
|
|
||||||
if ( p != (Entry *)&slap_entry_root )
|
|
||||||
bdb_unlocked_cache_return_entry_r( bdb, p );
|
|
||||||
p = NULL;
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_add) ": parent "
|
|
||||||
"does not exist\n" );
|
|
||||||
|
|
||||||
rs->sr_err = LDAP_REFERRAL;
|
|
||||||
rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
rs->sr_err = access_allowed( op, p,
|
|
||||||
children, NULL, ACL_WADD, NULL );
|
|
||||||
|
|
||||||
if ( ! rs->sr_err ) {
|
|
||||||
switch( opinfo.boi_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( p != (Entry *)&slap_entry_root )
|
|
||||||
bdb_unlocked_cache_return_entry_r( bdb, p );
|
|
||||||
p = NULL;
|
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_add) ": no write access to parent\n" );
|
|
||||||
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
|
||||||
rs->sr_text = "no write access to parent";
|
|
||||||
goto return_results;;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( p != (Entry *)&slap_entry_root ) {
|
|
||||||
if ( is_entry_subentry( p ) ) {
|
|
||||||
bdb_unlocked_cache_return_entry_r( bdb, p );
|
|
||||||
p = NULL;
|
|
||||||
/* parent is a subentry, don't allow add */
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_add) ": parent is subentry\n" );
|
|
||||||
rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION;
|
|
||||||
rs->sr_text = "parent is a subentry";
|
|
||||||
goto return_results;;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( is_entry_alias( p ) ) {
|
|
||||||
bdb_unlocked_cache_return_entry_r( bdb, p );
|
|
||||||
p = NULL;
|
|
||||||
/* parent is an alias, don't allow add */
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_add) ": parent is alias\n" );
|
|
||||||
rs->sr_err = LDAP_ALIAS_PROBLEM;
|
|
||||||
rs->sr_text = "parent is an alias";
|
|
||||||
goto return_results;;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( is_entry_referral( p ) ) {
|
|
||||||
/* parent is a referral, don't allow add */
|
|
||||||
rs->sr_matched = ber_strdup_x( p->e_name.bv_val,
|
|
||||||
op->o_tmpmemctx );
|
|
||||||
rs->sr_ref = get_entry_referrals( op, p );
|
|
||||||
bdb_unlocked_cache_return_entry_r( bdb, p );
|
|
||||||
p = NULL;
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_add) ": parent is referral\n" );
|
|
||||||
|
|
||||||
rs->sr_err = LDAP_REFERRAL;
|
|
||||||
rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( subentry ) {
|
|
||||||
/* FIXME: */
|
|
||||||
/* parent must be an administrative point of the required kind */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* free parent and reader lock */
|
|
||||||
if ( p != (Entry *)&slap_entry_root ) {
|
|
||||||
if ( p->e_nname.bv_len ) {
|
|
||||||
struct berval ppdn;
|
|
||||||
|
|
||||||
/* ITS#5326: use parent's DN if differs from provided one */
|
|
||||||
dnParent( &op->ora_e->e_name, &ppdn );
|
|
||||||
if ( !dn_match( &p->e_name, &ppdn ) ) {
|
|
||||||
struct berval rdn;
|
|
||||||
struct berval newdn;
|
|
||||||
|
|
||||||
dnRdn( &op->ora_e->e_name, &rdn );
|
|
||||||
|
|
||||||
build_new_dn( &newdn, &p->e_name, &rdn, NULL );
|
|
||||||
if ( op->ora_e->e_name.bv_val != op->o_req_dn.bv_val )
|
|
||||||
ber_memfree( op->ora_e->e_name.bv_val );
|
|
||||||
op->ora_e->e_name = newdn;
|
|
||||||
|
|
||||||
/* FIXME: should check whether
|
|
||||||
* dnNormalize(newdn) == e->e_nname ... */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bdb_unlocked_cache_return_entry_r( bdb, p );
|
|
||||||
}
|
|
||||||
p = NULL;
|
|
||||||
|
|
||||||
rs->sr_err = access_allowed( op, op->ora_e,
|
|
||||||
entry, NULL, ACL_WADD, NULL );
|
|
||||||
|
|
||||||
if ( ! rs->sr_err ) {
|
|
||||||
switch( opinfo.boi_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_add) ": no write access to entry\n" );
|
|
||||||
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
|
||||||
rs->sr_text = "no write access to entry";
|
|
||||||
goto return_results;;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check ACL for attribute write access
|
|
||||||
*/
|
|
||||||
if (!acl_check_modlist(op, oe, op->ora_modlist)) {
|
|
||||||
switch( opinfo.boi_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_add) ": no write access to attribute\n" );
|
|
||||||
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
|
||||||
rs->sr_text = "no write access to attribute";
|
|
||||||
goto return_results;;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( eid == NOID ) {
|
|
||||||
rs->sr_err = bdb_next_id( op->o_bd, &eid );
|
|
||||||
if( rs->sr_err != 0 ) {
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_add) ": next_id failed (%d)\n",
|
|
||||||
rs->sr_err );
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "internal error";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
op->ora_e->e_id = eid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* nested transaction */
|
|
||||||
rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, <2,
|
|
||||||
bdb->bi_db_opflags );
|
|
||||||
rs->sr_text = NULL;
|
|
||||||
if( rs->sr_err != 0 ) {
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_add) ": txn_begin(2) failed: "
|
|
||||||
"%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err );
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "internal error";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_add) ": txn2 id: %x\n",
|
|
||||||
lt2->id(lt2) );
|
|
||||||
|
|
||||||
/* dn2id index */
|
|
||||||
rs->sr_err = bdb_dn2id_add( op, lt2, ei, op->ora_e );
|
|
||||||
if ( rs->sr_err != 0 ) {
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_add) ": dn2id_add failed: %s (%d)\n",
|
|
||||||
db_strerror(rs->sr_err), rs->sr_err );
|
|
||||||
|
|
||||||
switch( rs->sr_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
case DB_KEYEXIST:
|
|
||||||
rs->sr_err = LDAP_ALREADY_EXISTS;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
}
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* attribute indexes */
|
|
||||||
rs->sr_err = bdb_index_entry_add( op, lt2, op->ora_e );
|
|
||||||
if ( rs->sr_err != LDAP_SUCCESS ) {
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_add) ": index_entry_add failed\n" );
|
|
||||||
switch( rs->sr_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
default:
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
}
|
|
||||||
rs->sr_text = "index generation failed";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* id2entry index */
|
|
||||||
rs->sr_err = bdb_id2entry_add( op->o_bd, lt2, op->ora_e );
|
|
||||||
if ( rs->sr_err != 0 ) {
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_add) ": id2entry_add failed\n" );
|
|
||||||
switch( rs->sr_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
default:
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
}
|
|
||||||
rs->sr_text = "entry store failed";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "txn_commit(2) failed";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* post-read */
|
|
||||||
if( op->o_postread ) {
|
|
||||||
if( postread_ctrl == NULL ) {
|
|
||||||
postread_ctrl = &ctrls[num_ctrls++];
|
|
||||||
ctrls[num_ctrls] = NULL;
|
|
||||||
}
|
|
||||||
if ( slap_read_controls( op, rs, op->ora_e,
|
|
||||||
&slap_post_read_bv, postread_ctrl ) )
|
|
||||||
{
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
"<=- " LDAP_XSTRING(bdb_add) ": post-read "
|
|
||||||
"failed!\n" );
|
|
||||||
if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
|
|
||||||
/* FIXME: is it correct to abort
|
|
||||||
* operation if control fails? */
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( op->o_noop ) {
|
|
||||||
if (( rs->sr_err=TXN_ABORT( ltid )) != 0 ) {
|
|
||||||
rs->sr_text = "txn_abort (no-op) failed";
|
|
||||||
} else {
|
|
||||||
rs->sr_err = LDAP_X_NO_OPERATION;
|
|
||||||
ltid = NULL;
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
struct berval nrdn;
|
|
||||||
|
|
||||||
/* pick the RDN if not suffix; otherwise pick the entire DN */
|
|
||||||
if (pdn.bv_len) {
|
|
||||||
nrdn.bv_val = op->ora_e->e_nname.bv_val;
|
|
||||||
nrdn.bv_len = pdn.bv_val - op->ora_e->e_nname.bv_val - 1;
|
|
||||||
} else {
|
|
||||||
nrdn = op->ora_e->e_nname;
|
|
||||||
}
|
|
||||||
|
|
||||||
bdb_cache_add( bdb, ei, op->ora_e, &nrdn, ltid, &lock );
|
|
||||||
|
|
||||||
if(( rs->sr_err=TXN_COMMIT( ltid, 0 )) != 0 ) {
|
|
||||||
rs->sr_text = "txn_commit failed";
|
|
||||||
} else {
|
|
||||||
rs->sr_err = LDAP_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ltid = NULL;
|
|
||||||
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
|
|
||||||
opinfo.boi_oe.oe_key = NULL;
|
|
||||||
|
|
||||||
if ( rs->sr_err != LDAP_SUCCESS ) {
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_add) ": %s : %s (%d)\n",
|
|
||||||
rs->sr_text, db_strerror(rs->sr_err), rs->sr_err );
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug(LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_add) ": added%s id=%08lx dn=\"%s\"\n",
|
|
||||||
op->o_noop ? " (no-op)" : "",
|
|
||||||
op->ora_e->e_id, op->ora_e->e_dn );
|
|
||||||
|
|
||||||
rs->sr_text = NULL;
|
|
||||||
if( num_ctrls ) rs->sr_ctrls = ctrls;
|
|
||||||
|
|
||||||
return_results:
|
|
||||||
success = rs->sr_err;
|
|
||||||
send_ldap_result( op, rs );
|
|
||||||
|
|
||||||
if( ltid != NULL ) {
|
|
||||||
TXN_ABORT( ltid );
|
|
||||||
}
|
|
||||||
if ( opinfo.boi_oe.oe_key ) {
|
|
||||||
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( success == LDAP_SUCCESS ) {
|
|
||||||
/* We own the entry now, and it can be purged at will
|
|
||||||
* Check to make sure it's the same entry we entered with.
|
|
||||||
* Possibly a callback may have mucked with it, although
|
|
||||||
* in general callbacks should treat the entry as read-only.
|
|
||||||
*/
|
|
||||||
bdb_cache_deref( oe->e_private );
|
|
||||||
if ( op->ora_e == oe )
|
|
||||||
op->ora_e = NULL;
|
|
||||||
|
|
||||||
if ( bdb->bi_txn_cp_kbyte ) {
|
|
||||||
TXN_CHECKPOINT( bdb->bi_dbenv,
|
|
||||||
bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
slap_graduate_commit_csn( op );
|
|
||||||
|
|
||||||
if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) {
|
|
||||||
slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
|
|
||||||
slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
|
|
||||||
}
|
|
||||||
return rs->sr_err;
|
|
||||||
}
|
|
||||||
|
|
@ -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--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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_ */
|
|
||||||
|
|
@ -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
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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, <id, tflags );
|
|
||||||
}
|
|
||||||
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_delete) ": txn1 id: %x\n",
|
|
||||||
ltid->id(ltid) );
|
|
||||||
rs->sr_text = NULL;
|
|
||||||
if( rs->sr_err != 0 ) {
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_delete) ": txn_begin failed: "
|
|
||||||
"%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err );
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "internal error";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
opinfo.boi_oe.oe_key = bdb;
|
|
||||||
opinfo.boi_txn = ltid;
|
|
||||||
opinfo.boi_err = 0;
|
|
||||||
opinfo.boi_acl_cache = op->o_do_not_cache;
|
|
||||||
LDAP_SLIST_INSERT_HEAD( &op->o_extra, &opinfo.boi_oe, oe_next );
|
|
||||||
|
|
||||||
if ( !be_issuffix( op->o_bd, &op->o_req_ndn ) ) {
|
|
||||||
dnParent( &op->o_req_ndn, &pdn );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get entry */
|
|
||||||
rs->sr_err = bdb_dn2entry( op, ltid, &op->o_req_ndn, &ei, 1,
|
|
||||||
&lock );
|
|
||||||
|
|
||||||
switch( rs->sr_err ) {
|
|
||||||
case 0:
|
|
||||||
case DB_NOTFOUND:
|
|
||||||
break;
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
case LDAP_BUSY:
|
|
||||||
rs->sr_text = "ldap server busy";
|
|
||||||
goto return_results;
|
|
||||||
default:
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "internal error";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( rs->sr_err == 0 ) {
|
|
||||||
e = ei->bei_e;
|
|
||||||
eip = ei->bei_parent;
|
|
||||||
} else {
|
|
||||||
matched = ei->bei_e;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME : dn2entry() should return non-glue entry */
|
|
||||||
if ( e == NULL || ( !manageDSAit && is_entry_glue( e ))) {
|
|
||||||
Debug( LDAP_DEBUG_ARGS,
|
|
||||||
"<=- " LDAP_XSTRING(bdb_delete) ": no such object %s\n",
|
|
||||||
op->o_req_dn.bv_val );
|
|
||||||
|
|
||||||
if ( matched != NULL ) {
|
|
||||||
rs->sr_matched = ch_strdup( matched->e_dn );
|
|
||||||
rs->sr_ref = is_entry_referral( matched )
|
|
||||||
? get_entry_referrals( op, matched )
|
|
||||||
: NULL;
|
|
||||||
bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, matched);
|
|
||||||
matched = NULL;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
rs->sr_ref = referral_rewrite( default_referral, NULL,
|
|
||||||
&op->o_req_dn, LDAP_SCOPE_DEFAULT );
|
|
||||||
}
|
|
||||||
|
|
||||||
rs->sr_err = LDAP_REFERRAL;
|
|
||||||
rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = bdb_cache_find_id( op, ltid, eip->bei_id, &eip, 0, &plock );
|
|
||||||
switch( rc ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
case 0:
|
|
||||||
case DB_NOTFOUND:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "internal error";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
if ( eip ) p = eip->bei_e;
|
|
||||||
|
|
||||||
if ( pdn.bv_len != 0 ) {
|
|
||||||
if( p == NULL || !bvmatch( &pdn, &p->e_nname )) {
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
"<=- " LDAP_XSTRING(bdb_delete) ": parent "
|
|
||||||
"does not exist\n" );
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "could not locate parent of entry";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check parent for "children" acl */
|
|
||||||
rs->sr_err = access_allowed( op, p,
|
|
||||||
children, NULL, ACL_WDEL, NULL );
|
|
||||||
|
|
||||||
if ( !rs->sr_err ) {
|
|
||||||
switch( opinfo.boi_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
"<=- " LDAP_XSTRING(bdb_delete) ": no write "
|
|
||||||
"access to parent\n" );
|
|
||||||
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
|
||||||
rs->sr_text = "no write access to parent";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* no parent, must be root to delete */
|
|
||||||
if( ! be_isroot( op ) ) {
|
|
||||||
if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv )
|
|
||||||
|| be_shadow_update( op ) ) {
|
|
||||||
p = (Entry *)&slap_entry_root;
|
|
||||||
|
|
||||||
/* check parent for "children" acl */
|
|
||||||
rs->sr_err = access_allowed( op, p,
|
|
||||||
children, NULL, ACL_WDEL, NULL );
|
|
||||||
|
|
||||||
p = NULL;
|
|
||||||
|
|
||||||
if ( !rs->sr_err ) {
|
|
||||||
switch( opinfo.boi_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
"<=- " LDAP_XSTRING(bdb_delete)
|
|
||||||
": no access to parent\n" );
|
|
||||||
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
|
||||||
rs->sr_text = "no write access to parent";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
"<=- " LDAP_XSTRING(bdb_delete)
|
|
||||||
": no parent and not root\n" );
|
|
||||||
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( get_assert( op ) &&
|
|
||||||
( test_filter( op, e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
|
|
||||||
{
|
|
||||||
rs->sr_err = LDAP_ASSERTION_FAILED;
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
rs->sr_err = access_allowed( op, e,
|
|
||||||
entry, NULL, ACL_WDEL, NULL );
|
|
||||||
|
|
||||||
if ( !rs->sr_err ) {
|
|
||||||
switch( opinfo.boi_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
"<=- " LDAP_XSTRING(bdb_delete) ": no write access "
|
|
||||||
"to entry\n" );
|
|
||||||
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
|
||||||
rs->sr_text = "no write access to entry";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !manageDSAit && is_entry_referral( e ) ) {
|
|
||||||
/* entry is a referral, don't allow delete */
|
|
||||||
rs->sr_ref = get_entry_referrals( op, e );
|
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_delete) ": entry is referral\n" );
|
|
||||||
|
|
||||||
rs->sr_err = LDAP_REFERRAL;
|
|
||||||
rs->sr_matched = ch_strdup( e->e_name.bv_val );
|
|
||||||
rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* pre-read */
|
|
||||||
if( op->o_preread ) {
|
|
||||||
if( preread_ctrl == NULL ) {
|
|
||||||
preread_ctrl = &ctrls[num_ctrls++];
|
|
||||||
ctrls[num_ctrls] = NULL;
|
|
||||||
}
|
|
||||||
if( slap_read_controls( op, rs, e,
|
|
||||||
&slap_pre_read_bv, preread_ctrl ) )
|
|
||||||
{
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
"<=- " LDAP_XSTRING(bdb_delete) ": pre-read "
|
|
||||||
"failed!\n" );
|
|
||||||
if ( op->o_preread & SLAP_CONTROL_CRITICAL ) {
|
|
||||||
/* FIXME: is it correct to abort
|
|
||||||
* operation if control fails? */
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* nested transaction */
|
|
||||||
rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, <2,
|
|
||||||
bdb->bi_db_opflags );
|
|
||||||
rs->sr_text = NULL;
|
|
||||||
if( rs->sr_err != 0 ) {
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_delete) ": txn_begin(2) failed: "
|
|
||||||
"%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err );
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "internal error";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_delete) ": txn2 id: %x\n",
|
|
||||||
lt2->id(lt2) );
|
|
||||||
|
|
||||||
BDB_LOG_PRINTF( bdb->bi_dbenv, lt2, "slapd Starting delete %s(%d)",
|
|
||||||
e->e_nname.bv_val, e->e_id );
|
|
||||||
|
|
||||||
/* Can't do it if we have kids */
|
|
||||||
rs->sr_err = bdb_cache_children( op, lt2, e );
|
|
||||||
if( rs->sr_err != DB_NOTFOUND ) {
|
|
||||||
switch( rs->sr_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
case 0:
|
|
||||||
Debug(LDAP_DEBUG_ARGS,
|
|
||||||
"<=- " LDAP_XSTRING(bdb_delete)
|
|
||||||
": non-leaf %s\n",
|
|
||||||
op->o_req_dn.bv_val );
|
|
||||||
rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
|
|
||||||
rs->sr_text = "subordinate objects must be deleted first";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Debug(LDAP_DEBUG_ARGS,
|
|
||||||
"<=- " LDAP_XSTRING(bdb_delete)
|
|
||||||
": has_children failed: %s (%d)\n",
|
|
||||||
db_strerror(rs->sr_err), rs->sr_err );
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "internal error";
|
|
||||||
}
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* delete from dn2id */
|
|
||||||
rs->sr_err = bdb_dn2id_delete( op, lt2, eip, e );
|
|
||||||
if ( rs->sr_err != 0 ) {
|
|
||||||
Debug(LDAP_DEBUG_TRACE,
|
|
||||||
"<=- " LDAP_XSTRING(bdb_delete) ": dn2id failed: "
|
|
||||||
"%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err );
|
|
||||||
switch( rs->sr_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
rs->sr_text = "DN index delete failed";
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* delete indices for old attributes */
|
|
||||||
rs->sr_err = bdb_index_entry_del( op, lt2, e );
|
|
||||||
if ( rs->sr_err != LDAP_SUCCESS ) {
|
|
||||||
Debug(LDAP_DEBUG_TRACE,
|
|
||||||
"<=- " LDAP_XSTRING(bdb_delete) ": index failed: "
|
|
||||||
"%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err );
|
|
||||||
switch( rs->sr_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
rs->sr_text = "entry index delete failed";
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* fixup delete CSN */
|
|
||||||
if ( !SLAP_SHADOW( op->o_bd )) {
|
|
||||||
struct berval vals[2];
|
|
||||||
|
|
||||||
assert( !BER_BVISNULL( &op->o_csn ) );
|
|
||||||
vals[0] = op->o_csn;
|
|
||||||
BER_BVZERO( &vals[1] );
|
|
||||||
rs->sr_err = bdb_index_values( op, lt2, slap_schema.si_ad_entryCSN,
|
|
||||||
vals, 0, SLAP_INDEX_ADD_OP );
|
|
||||||
if ( rs->sr_err != LDAP_SUCCESS ) {
|
|
||||||
switch( rs->sr_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
rs->sr_text = "entryCSN index update failed";
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* delete from id2entry */
|
|
||||||
rs->sr_err = bdb_id2entry_delete( op->o_bd, lt2, e );
|
|
||||||
if ( rs->sr_err != 0 ) {
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
"<=- " LDAP_XSTRING(bdb_delete) ": id2entry failed: "
|
|
||||||
"%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err );
|
|
||||||
switch( rs->sr_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
rs->sr_text = "entry delete failed";
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( pdn.bv_len != 0 ) {
|
|
||||||
parent_is_glue = is_entry_glue(p);
|
|
||||||
rs->sr_err = bdb_cache_children( op, lt2, p );
|
|
||||||
if ( rs->sr_err != DB_NOTFOUND ) {
|
|
||||||
switch( rs->sr_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Debug(LDAP_DEBUG_ARGS,
|
|
||||||
"<=- " LDAP_XSTRING(bdb_delete)
|
|
||||||
": has_children failed: %s (%d)\n",
|
|
||||||
db_strerror(rs->sr_err), rs->sr_err );
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "internal error";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
parent_is_leaf = 1;
|
|
||||||
}
|
|
||||||
bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
|
|
||||||
p = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
BDB_LOG_PRINTF( bdb->bi_dbenv, lt2, "slapd Commit1 delete %s(%d)",
|
|
||||||
e->e_nname.bv_val, e->e_id );
|
|
||||||
|
|
||||||
if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "txn_commit(2) failed";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
eid = e->e_id;
|
|
||||||
|
|
||||||
#if 0 /* Do we want to reclaim deleted IDs? */
|
|
||||||
ldap_pvt_thread_mutex_lock( &bdb->bi_lastid_mutex );
|
|
||||||
if ( e->e_id == bdb->bi_lastid ) {
|
|
||||||
bdb_last_id( op->o_bd, ltid );
|
|
||||||
}
|
|
||||||
ldap_pvt_thread_mutex_unlock( &bdb->bi_lastid_mutex );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if( op->o_noop ) {
|
|
||||||
if ( ( rs->sr_err = TXN_ABORT( ltid ) ) != 0 ) {
|
|
||||||
rs->sr_text = "txn_abort (no-op) failed";
|
|
||||||
} else {
|
|
||||||
rs->sr_err = LDAP_X_NO_OPERATION;
|
|
||||||
ltid = NULL;
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
BDB_LOG_PRINTF( bdb->bi_dbenv, ltid, "slapd Cache delete %s(%d)",
|
|
||||||
e->e_nname.bv_val, e->e_id );
|
|
||||||
|
|
||||||
rc = bdb_cache_delete( bdb, e, ltid, &lock );
|
|
||||||
switch( rc ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
rs->sr_err = TXN_COMMIT( ltid, 0 );
|
|
||||||
}
|
|
||||||
ltid = NULL;
|
|
||||||
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
|
|
||||||
opinfo.boi_oe.oe_key = NULL;
|
|
||||||
|
|
||||||
BDB_LOG_PRINTF( bdb->bi_dbenv, NULL, "slapd Committed delete %s(%d)",
|
|
||||||
e->e_nname.bv_val, e->e_id );
|
|
||||||
|
|
||||||
if( rs->sr_err != 0 ) {
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_delete) ": txn_%s failed: %s (%d)\n",
|
|
||||||
op->o_noop ? "abort (no-op)" : "commit",
|
|
||||||
db_strerror(rs->sr_err), rs->sr_err );
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "commit failed";
|
|
||||||
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_delete) ": deleted%s id=%08lx dn=\"%s\"\n",
|
|
||||||
op->o_noop ? " (no-op)" : "",
|
|
||||||
eid, op->o_req_dn.bv_val );
|
|
||||||
rs->sr_err = LDAP_SUCCESS;
|
|
||||||
rs->sr_text = NULL;
|
|
||||||
if( num_ctrls ) rs->sr_ctrls = ctrls;
|
|
||||||
|
|
||||||
return_results:
|
|
||||||
if ( rs->sr_err == LDAP_SUCCESS && parent_is_glue && parent_is_leaf ) {
|
|
||||||
op->o_delete_glue_parent = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( p )
|
|
||||||
bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
|
|
||||||
|
|
||||||
/* free entry */
|
|
||||||
if( e != NULL ) {
|
|
||||||
if ( rs->sr_err == LDAP_SUCCESS ) {
|
|
||||||
/* Free the EntryInfo and the Entry */
|
|
||||||
bdb_cache_entryinfo_lock( BEI(e) );
|
|
||||||
bdb_cache_delete_cleanup( &bdb->bi_cache, BEI(e) );
|
|
||||||
} else {
|
|
||||||
bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ltid != NULL ) {
|
|
||||||
TXN_ABORT( ltid );
|
|
||||||
}
|
|
||||||
if ( opinfo.boi_oe.oe_key ) {
|
|
||||||
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
|
|
||||||
}
|
|
||||||
|
|
||||||
send_ldap_result( op, rs );
|
|
||||||
slap_graduate_commit_csn( op );
|
|
||||||
|
|
||||||
if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) {
|
|
||||||
slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
|
|
||||||
slap_sl_free( *preread_ctrl, op->o_tmpmemctx );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp_kbyte ) {
|
|
||||||
TXN_CHECKPOINT( bdb->bi_dbenv,
|
|
||||||
bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
|
|
||||||
}
|
|
||||||
return rs->sr_err;
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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 */
|
|
||||||
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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, <id, tflags );
|
|
||||||
}
|
|
||||||
rs->sr_text = NULL;
|
|
||||||
if( rs->sr_err != 0 ) {
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_modify) ": txn_begin failed: "
|
|
||||||
"%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err );
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "internal error";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modify) ": txn1 id: %x\n",
|
|
||||||
ltid->id(ltid) );
|
|
||||||
|
|
||||||
opinfo.boi_oe.oe_key = bdb;
|
|
||||||
opinfo.boi_txn = ltid;
|
|
||||||
opinfo.boi_err = 0;
|
|
||||||
opinfo.boi_acl_cache = op->o_do_not_cache;
|
|
||||||
LDAP_SLIST_INSERT_HEAD( &op->o_extra, &opinfo.boi_oe, oe_next );
|
|
||||||
|
|
||||||
/* get entry or ancestor */
|
|
||||||
rs->sr_err = bdb_dn2entry( op, ltid, &op->o_req_ndn, &ei, 1,
|
|
||||||
&lock );
|
|
||||||
|
|
||||||
if ( rs->sr_err != 0 ) {
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_modify) ": dn2entry failed (%d)\n",
|
|
||||||
rs->sr_err );
|
|
||||||
switch( rs->sr_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
case DB_NOTFOUND:
|
|
||||||
break;
|
|
||||||
case LDAP_BUSY:
|
|
||||||
rs->sr_text = "ldap server busy";
|
|
||||||
goto return_results;
|
|
||||||
default:
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "internal error";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
e = ei->bei_e;
|
|
||||||
|
|
||||||
/* acquire and lock entry */
|
|
||||||
/* FIXME: dn2entry() should return non-glue entry */
|
|
||||||
if (( rs->sr_err == DB_NOTFOUND ) ||
|
|
||||||
( !manageDSAit && e && is_entry_glue( e )))
|
|
||||||
{
|
|
||||||
if ( e != NULL ) {
|
|
||||||
rs->sr_matched = ch_strdup( e->e_dn );
|
|
||||||
rs->sr_ref = is_entry_referral( e )
|
|
||||||
? get_entry_referrals( op, e )
|
|
||||||
: NULL;
|
|
||||||
bdb_unlocked_cache_return_entry_r (&bdb->bi_cache, e);
|
|
||||||
e = NULL;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
rs->sr_ref = referral_rewrite( default_referral, NULL,
|
|
||||||
&op->o_req_dn, LDAP_SCOPE_DEFAULT );
|
|
||||||
}
|
|
||||||
|
|
||||||
rs->sr_err = LDAP_REFERRAL;
|
|
||||||
send_ldap_result( op, rs );
|
|
||||||
|
|
||||||
if ( rs->sr_ref != default_referral ) {
|
|
||||||
ber_bvarray_free( rs->sr_ref );
|
|
||||||
}
|
|
||||||
free( (char *)rs->sr_matched );
|
|
||||||
rs->sr_ref = NULL;
|
|
||||||
rs->sr_matched = NULL;
|
|
||||||
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !manageDSAit && is_entry_referral( e ) ) {
|
|
||||||
/* entry is a referral, don't allow modify */
|
|
||||||
rs->sr_ref = get_entry_referrals( op, e );
|
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_modify) ": entry is referral\n" );
|
|
||||||
|
|
||||||
rs->sr_err = LDAP_REFERRAL;
|
|
||||||
rs->sr_matched = e->e_name.bv_val;
|
|
||||||
send_ldap_result( op, rs );
|
|
||||||
|
|
||||||
ber_bvarray_free( rs->sr_ref );
|
|
||||||
rs->sr_ref = NULL;
|
|
||||||
rs->sr_matched = NULL;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( get_assert( op ) &&
|
|
||||||
( test_filter( op, e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
|
|
||||||
{
|
|
||||||
rs->sr_err = LDAP_ASSERTION_FAILED;
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( op->o_preread ) {
|
|
||||||
if( preread_ctrl == NULL ) {
|
|
||||||
preread_ctrl = &ctrls[num_ctrls++];
|
|
||||||
ctrls[num_ctrls] = NULL;
|
|
||||||
}
|
|
||||||
if ( slap_read_controls( op, rs, e,
|
|
||||||
&slap_pre_read_bv, preread_ctrl ) )
|
|
||||||
{
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
"<=- " LDAP_XSTRING(bdb_modify) ": pre-read "
|
|
||||||
"failed!\n" );
|
|
||||||
if ( op->o_preread & SLAP_CONTROL_CRITICAL ) {
|
|
||||||
/* FIXME: is it correct to abort
|
|
||||||
* operation if control fails? */
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* nested transaction */
|
|
||||||
rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, <2, bdb->bi_db_opflags );
|
|
||||||
rs->sr_text = NULL;
|
|
||||||
if( rs->sr_err != 0 ) {
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_modify) ": txn_begin(2) failed: " "%s (%d)\n",
|
|
||||||
db_strerror(rs->sr_err), rs->sr_err );
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "internal error";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modify) ": txn2 id: %x\n",
|
|
||||||
lt2->id(lt2) );
|
|
||||||
/* Modify the entry */
|
|
||||||
dummy = *e;
|
|
||||||
rs->sr_err = bdb_modify_internal( op, lt2, op->orm_modlist,
|
|
||||||
&dummy, &rs->sr_text, textbuf, textlen );
|
|
||||||
|
|
||||||
if( rs->sr_err != LDAP_SUCCESS ) {
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_modify) ": modify failed (%d)\n",
|
|
||||||
rs->sr_err );
|
|
||||||
if ( (rs->sr_err == LDAP_INSUFFICIENT_ACCESS) && opinfo.boi_err ) {
|
|
||||||
rs->sr_err = opinfo.boi_err;
|
|
||||||
}
|
|
||||||
/* Only free attrs if they were dup'd. */
|
|
||||||
if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL;
|
|
||||||
switch( rs->sr_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* change the entry itself */
|
|
||||||
rs->sr_err = bdb_id2entry_update( op->o_bd, lt2, &dummy );
|
|
||||||
if ( rs->sr_err != 0 ) {
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_modify) ": id2entry update failed " "(%d)\n",
|
|
||||||
rs->sr_err );
|
|
||||||
switch( rs->sr_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
rs->sr_text = "entry update failed";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "txn_commit(2) failed";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( op->o_postread ) {
|
|
||||||
if( postread_ctrl == NULL ) {
|
|
||||||
postread_ctrl = &ctrls[num_ctrls++];
|
|
||||||
ctrls[num_ctrls] = NULL;
|
|
||||||
}
|
|
||||||
if( slap_read_controls( op, rs, &dummy,
|
|
||||||
&slap_post_read_bv, postread_ctrl ) )
|
|
||||||
{
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
"<=- " LDAP_XSTRING(bdb_modify)
|
|
||||||
": post-read failed!\n" );
|
|
||||||
if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
|
|
||||||
/* FIXME: is it correct to abort
|
|
||||||
* operation if control fails? */
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( op->o_noop ) {
|
|
||||||
if ( ( rs->sr_err = TXN_ABORT( ltid ) ) != 0 ) {
|
|
||||||
rs->sr_text = "txn_abort (no-op) failed";
|
|
||||||
} else {
|
|
||||||
rs->sr_err = LDAP_X_NO_OPERATION;
|
|
||||||
ltid = NULL;
|
|
||||||
/* Only free attrs if they were dup'd. */
|
|
||||||
if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL;
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* may have changed in bdb_modify_internal() */
|
|
||||||
e->e_ocflags = dummy.e_ocflags;
|
|
||||||
rc = bdb_cache_modify( bdb, e, dummy.e_attrs, ltid, &lock );
|
|
||||||
switch( rc ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
dummy.e_attrs = NULL;
|
|
||||||
|
|
||||||
rs->sr_err = TXN_COMMIT( ltid, 0 );
|
|
||||||
}
|
|
||||||
ltid = NULL;
|
|
||||||
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
|
|
||||||
opinfo.boi_oe.oe_key = NULL;
|
|
||||||
|
|
||||||
if( rs->sr_err != 0 ) {
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_modify) ": txn_%s failed: %s (%d)\n",
|
|
||||||
op->o_noop ? "abort (no-op)" : "commit",
|
|
||||||
db_strerror(rs->sr_err), rs->sr_err );
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "commit failed";
|
|
||||||
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_modify) ": updated%s id=%08lx dn=\"%s\"\n",
|
|
||||||
op->o_noop ? " (no-op)" : "",
|
|
||||||
dummy.e_id, op->o_req_dn.bv_val );
|
|
||||||
|
|
||||||
rs->sr_err = LDAP_SUCCESS;
|
|
||||||
rs->sr_text = NULL;
|
|
||||||
if( num_ctrls ) rs->sr_ctrls = ctrls;
|
|
||||||
|
|
||||||
return_results:
|
|
||||||
if( dummy.e_attrs ) {
|
|
||||||
attrs_free( dummy.e_attrs );
|
|
||||||
}
|
|
||||||
send_ldap_result( op, rs );
|
|
||||||
|
|
||||||
if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp_kbyte ) {
|
|
||||||
TXN_CHECKPOINT( bdb->bi_dbenv,
|
|
||||||
bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
|
||||||
slap_graduate_commit_csn( op );
|
|
||||||
|
|
||||||
if( ltid != NULL ) {
|
|
||||||
TXN_ABORT( ltid );
|
|
||||||
}
|
|
||||||
if ( opinfo.boi_oe.oe_key ) {
|
|
||||||
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( e != NULL ) {
|
|
||||||
bdb_unlocked_cache_return_entry_w (&bdb->bi_cache, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) {
|
|
||||||
slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
|
|
||||||
slap_sl_free( *preread_ctrl, op->o_tmpmemctx );
|
|
||||||
}
|
|
||||||
if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) {
|
|
||||||
slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
|
|
||||||
slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
|
|
||||||
}
|
|
||||||
|
|
||||||
rs->sr_text = NULL;
|
|
||||||
|
|
||||||
return rs->sr_err;
|
|
||||||
}
|
|
||||||
|
|
@ -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, <id, tflags );
|
|
||||||
}
|
|
||||||
rs->sr_text = NULL;
|
|
||||||
if( rs->sr_err != 0 ) {
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_modrdn) ": txn_begin failed: "
|
|
||||||
"%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err );
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "internal error";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn) ": txn1 id: %x\n",
|
|
||||||
ltid->id(ltid) );
|
|
||||||
|
|
||||||
opinfo.boi_oe.oe_key = bdb;
|
|
||||||
opinfo.boi_txn = ltid;
|
|
||||||
opinfo.boi_err = 0;
|
|
||||||
opinfo.boi_acl_cache = op->o_do_not_cache;
|
|
||||||
LDAP_SLIST_INSERT_HEAD( &op->o_extra, &opinfo.boi_oe, oe_next );
|
|
||||||
|
|
||||||
/* get entry */
|
|
||||||
rs->sr_err = bdb_dn2entry( op, ltid, &op->o_req_ndn, &ei, 1,
|
|
||||||
&lock );
|
|
||||||
|
|
||||||
switch( rs->sr_err ) {
|
|
||||||
case 0:
|
|
||||||
case DB_NOTFOUND:
|
|
||||||
break;
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
case LDAP_BUSY:
|
|
||||||
rs->sr_text = "ldap server busy";
|
|
||||||
goto return_results;
|
|
||||||
default:
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "internal error";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
e = ei->bei_e;
|
|
||||||
/* FIXME: dn2entry() should return non-glue entry */
|
|
||||||
if (( rs->sr_err == DB_NOTFOUND ) ||
|
|
||||||
( !manageDSAit && e && is_entry_glue( e )))
|
|
||||||
{
|
|
||||||
if( e != NULL ) {
|
|
||||||
rs->sr_matched = ch_strdup( e->e_dn );
|
|
||||||
rs->sr_ref = is_entry_referral( e )
|
|
||||||
? get_entry_referrals( op, e )
|
|
||||||
: NULL;
|
|
||||||
bdb_unlocked_cache_return_entry_r( &bdb->bi_cache, e);
|
|
||||||
e = NULL;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
rs->sr_ref = referral_rewrite( default_referral, NULL,
|
|
||||||
&op->o_req_dn, LDAP_SCOPE_DEFAULT );
|
|
||||||
}
|
|
||||||
|
|
||||||
rs->sr_err = LDAP_REFERRAL;
|
|
||||||
send_ldap_result( op, rs );
|
|
||||||
|
|
||||||
ber_bvarray_free( rs->sr_ref );
|
|
||||||
free( (char *)rs->sr_matched );
|
|
||||||
rs->sr_ref = NULL;
|
|
||||||
rs->sr_matched = NULL;
|
|
||||||
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( get_assert( op ) &&
|
|
||||||
( test_filter( op, e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
|
|
||||||
{
|
|
||||||
rs->sr_err = LDAP_ASSERTION_FAILED;
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check write on old entry */
|
|
||||||
rs->sr_err = access_allowed( op, e, entry, NULL, ACL_WRITE, NULL );
|
|
||||||
if ( ! rs->sr_err ) {
|
|
||||||
switch( opinfo.boi_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_TRACE, "no access to entry\n" );
|
|
||||||
rs->sr_text = "no write access to old entry";
|
|
||||||
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef BDB_HIER
|
|
||||||
rs->sr_err = bdb_cache_children( op, ltid, e );
|
|
||||||
if ( rs->sr_err != DB_NOTFOUND ) {
|
|
||||||
switch( rs->sr_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
case 0:
|
|
||||||
Debug(LDAP_DEBUG_ARGS,
|
|
||||||
"<=- " LDAP_XSTRING(bdb_modrdn)
|
|
||||||
": non-leaf %s\n",
|
|
||||||
op->o_req_dn.bv_val );
|
|
||||||
rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
|
|
||||||
rs->sr_text = "subtree rename not supported";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Debug(LDAP_DEBUG_ARGS,
|
|
||||||
"<=- " LDAP_XSTRING(bdb_modrdn)
|
|
||||||
": has_children failed: %s (%d)\n",
|
|
||||||
db_strerror(rs->sr_err), rs->sr_err );
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "internal error";
|
|
||||||
}
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
ei->bei_state |= CACHE_ENTRY_NO_KIDS;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!manageDSAit && is_entry_referral( e ) ) {
|
|
||||||
/* parent is a referral, don't allow add */
|
|
||||||
rs->sr_ref = get_entry_referrals( op, e );
|
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn)
|
|
||||||
": entry %s is referral\n", e->e_dn );
|
|
||||||
|
|
||||||
rs->sr_err = LDAP_REFERRAL,
|
|
||||||
rs->sr_matched = e->e_name.bv_val;
|
|
||||||
send_ldap_result( op, rs );
|
|
||||||
|
|
||||||
ber_bvarray_free( rs->sr_ref );
|
|
||||||
rs->sr_ref = NULL;
|
|
||||||
rs->sr_matched = NULL;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( be_issuffix( op->o_bd, &e->e_nname ) ) {
|
|
||||||
#ifdef BDB_MULTIPLE_SUFFIXES
|
|
||||||
/* Allow renaming one suffix entry to another */
|
|
||||||
p_ndn = slap_empty_bv;
|
|
||||||
#else
|
|
||||||
/* There can only be one suffix entry */
|
|
||||||
rs->sr_err = LDAP_NAMING_VIOLATION;
|
|
||||||
rs->sr_text = "cannot rename suffix entry";
|
|
||||||
goto return_results;
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
dnParent( &e->e_nname, &p_ndn );
|
|
||||||
}
|
|
||||||
np_ndn = &p_ndn;
|
|
||||||
eip = ei->bei_parent;
|
|
||||||
if ( eip && eip->bei_id ) {
|
|
||||||
/* Make sure parent entry exist and we can write its
|
|
||||||
* children.
|
|
||||||
*/
|
|
||||||
rs->sr_err = bdb_cache_find_id( op, ltid,
|
|
||||||
eip->bei_id, &eip, 0, &plock );
|
|
||||||
|
|
||||||
switch( rs->sr_err ) {
|
|
||||||
case 0:
|
|
||||||
case DB_NOTFOUND:
|
|
||||||
break;
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
case LDAP_BUSY:
|
|
||||||
rs->sr_text = "ldap server busy";
|
|
||||||
goto return_results;
|
|
||||||
default:
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "internal error";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = eip->bei_e;
|
|
||||||
if( p == NULL) {
|
|
||||||
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn)
|
|
||||||
": parent does not exist\n" );
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "old entry's parent does not exist";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
p = (Entry *)&slap_entry_root;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check parent for "children" acl */
|
|
||||||
rs->sr_err = access_allowed( op, p,
|
|
||||||
children, NULL,
|
|
||||||
op->oq_modrdn.rs_newSup == NULL ?
|
|
||||||
ACL_WRITE : ACL_WDEL,
|
|
||||||
NULL );
|
|
||||||
|
|
||||||
if ( !p_ndn.bv_len )
|
|
||||||
p = NULL;
|
|
||||||
|
|
||||||
if ( ! rs->sr_err ) {
|
|
||||||
switch( opinfo.boi_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
|
||||||
Debug( LDAP_DEBUG_TRACE, "no access to parent\n" );
|
|
||||||
rs->sr_text = "no write access to old parent's children";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_modrdn) ": wr to children "
|
|
||||||
"of entry %s OK\n", p_ndn.bv_val );
|
|
||||||
|
|
||||||
if ( p_ndn.bv_val == slap_empty_bv.bv_val ) {
|
|
||||||
p_dn = slap_empty_bv;
|
|
||||||
} else {
|
|
||||||
dnParent( &e->e_name, &p_dn );
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_modrdn) ": parent dn=%s\n",
|
|
||||||
p_dn.bv_val );
|
|
||||||
|
|
||||||
new_parent_dn = &p_dn; /* New Parent unless newSuperior given */
|
|
||||||
|
|
||||||
if ( op->oq_modrdn.rs_newSup != NULL ) {
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_modrdn)
|
|
||||||
": new parent \"%s\" requested...\n",
|
|
||||||
op->oq_modrdn.rs_newSup->bv_val );
|
|
||||||
|
|
||||||
/* newSuperior == oldParent? */
|
|
||||||
if( dn_match( &p_ndn, op->oq_modrdn.rs_nnewSup ) ) {
|
|
||||||
Debug( LDAP_DEBUG_TRACE, "bdb_back_modrdn: "
|
|
||||||
"new parent \"%s\" same as the old parent \"%s\"\n",
|
|
||||||
op->oq_modrdn.rs_newSup->bv_val, p_dn.bv_val );
|
|
||||||
op->oq_modrdn.rs_newSup = NULL; /* ignore newSuperior */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* There's a BDB_MULTIPLE_SUFFIXES case here that this code doesn't
|
|
||||||
* support. E.g., two suffixes dc=foo,dc=com and dc=bar,dc=net.
|
|
||||||
* We do not allow modDN
|
|
||||||
* dc=foo,dc=com
|
|
||||||
* newrdn dc=bar
|
|
||||||
* newsup dc=net
|
|
||||||
* and we probably should. But since MULTIPLE_SUFFIXES is deprecated
|
|
||||||
* I'm ignoring this problem for now.
|
|
||||||
*/
|
|
||||||
if ( op->oq_modrdn.rs_newSup != NULL ) {
|
|
||||||
if ( op->oq_modrdn.rs_newSup->bv_len ) {
|
|
||||||
np_dn = op->oq_modrdn.rs_newSup;
|
|
||||||
np_ndn = op->oq_modrdn.rs_nnewSup;
|
|
||||||
|
|
||||||
/* newSuperior == oldParent? - checked above */
|
|
||||||
/* newSuperior == entry being moved?, if so ==> ERROR */
|
|
||||||
if ( dnIsSuffix( np_ndn, &e->e_nname )) {
|
|
||||||
rs->sr_err = LDAP_NO_SUCH_OBJECT;
|
|
||||||
rs->sr_text = "new superior not found";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
/* Get Entry with dn=newSuperior. Does newSuperior exist? */
|
|
||||||
|
|
||||||
rs->sr_err = bdb_dn2entry( op, ltid, np_ndn,
|
|
||||||
&neip, 0, &nplock );
|
|
||||||
|
|
||||||
switch( rs->sr_err ) {
|
|
||||||
case 0: np = neip->bei_e;
|
|
||||||
case DB_NOTFOUND:
|
|
||||||
break;
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
case LDAP_BUSY:
|
|
||||||
rs->sr_text = "ldap server busy";
|
|
||||||
goto return_results;
|
|
||||||
default:
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "internal error";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( np == NULL) {
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_modrdn)
|
|
||||||
": newSup(ndn=%s) not here!\n",
|
|
||||||
np_ndn->bv_val );
|
|
||||||
rs->sr_text = "new superior not found";
|
|
||||||
rs->sr_err = LDAP_NO_SUCH_OBJECT;
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_modrdn)
|
|
||||||
": wr to new parent OK np=%p, id=%ld\n",
|
|
||||||
(void *) np, (long) np->e_id );
|
|
||||||
|
|
||||||
/* check newSuperior for "children" acl */
|
|
||||||
rs->sr_err = access_allowed( op, np, children,
|
|
||||||
NULL, ACL_WADD, NULL );
|
|
||||||
|
|
||||||
if( ! rs->sr_err ) {
|
|
||||||
switch( opinfo.boi_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_modrdn)
|
|
||||||
": no wr to newSup children\n" );
|
|
||||||
rs->sr_text = "no write access to new superior's children";
|
|
||||||
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( is_entry_alias( np ) ) {
|
|
||||||
/* parent is an alias, don't allow add */
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_modrdn)
|
|
||||||
": entry is alias\n" );
|
|
||||||
rs->sr_text = "new superior is an alias";
|
|
||||||
rs->sr_err = LDAP_ALIAS_PROBLEM;
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( is_entry_referral( np ) ) {
|
|
||||||
/* parent is a referral, don't allow add */
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_modrdn)
|
|
||||||
": entry is referral\n" );
|
|
||||||
rs->sr_text = "new superior is a referral";
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
np_dn = NULL;
|
|
||||||
|
|
||||||
/* no parent, modrdn entry directly under root */
|
|
||||||
if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv )
|
|
||||||
|| be_isupdate( op ) ) {
|
|
||||||
np = (Entry *)&slap_entry_root;
|
|
||||||
|
|
||||||
/* check parent for "children" acl */
|
|
||||||
rs->sr_err = access_allowed( op, np,
|
|
||||||
children, NULL, ACL_WADD, NULL );
|
|
||||||
|
|
||||||
np = NULL;
|
|
||||||
|
|
||||||
if ( ! rs->sr_err ) {
|
|
||||||
switch( opinfo.boi_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
"no access to new superior\n" );
|
|
||||||
rs->sr_text =
|
|
||||||
"no write access to new superior's children";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_modrdn)
|
|
||||||
": wr to new parent's children OK\n" );
|
|
||||||
|
|
||||||
new_parent_dn = np_dn;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Build target dn and make sure target entry doesn't exist already. */
|
|
||||||
if (!new_dn.bv_val) {
|
|
||||||
build_new_dn( &new_dn, new_parent_dn, &op->oq_modrdn.rs_newrdn, NULL );
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!new_ndn.bv_val) {
|
|
||||||
struct berval bv = {0, NULL};
|
|
||||||
dnNormalize( 0, NULL, NULL, &new_dn, &bv, op->o_tmpmemctx );
|
|
||||||
ber_dupbv( &new_ndn, &bv );
|
|
||||||
/* FIXME: why not call dnNormalize() w/o ctx? */
|
|
||||||
op->o_tmpfree( bv.bv_val, op->o_tmpmemctx );
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn) ": new ndn=%s\n",
|
|
||||||
new_ndn.bv_val );
|
|
||||||
|
|
||||||
/* Shortcut the search */
|
|
||||||
nei = neip ? neip : eip;
|
|
||||||
rs->sr_err = bdb_cache_find_ndn ( op, ltid, &new_ndn, &nei );
|
|
||||||
if ( nei ) bdb_cache_entryinfo_unlock( nei );
|
|
||||||
switch( rs->sr_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
case DB_NOTFOUND:
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
/* Allow rename to same DN */
|
|
||||||
if ( nei == ei )
|
|
||||||
break;
|
|
||||||
rs->sr_err = LDAP_ALREADY_EXISTS;
|
|
||||||
goto return_results;
|
|
||||||
default:
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "internal error";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( op->o_preread ) {
|
|
||||||
if( preread_ctrl == NULL ) {
|
|
||||||
preread_ctrl = &ctrls[num_ctrls++];
|
|
||||||
ctrls[num_ctrls] = NULL;
|
|
||||||
}
|
|
||||||
if( slap_read_controls( op, rs, e,
|
|
||||||
&slap_pre_read_bv, preread_ctrl ) )
|
|
||||||
{
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
"<=- " LDAP_XSTRING(bdb_modrdn)
|
|
||||||
": pre-read failed!\n" );
|
|
||||||
if ( op->o_preread & SLAP_CONTROL_CRITICAL ) {
|
|
||||||
/* FIXME: is it correct to abort
|
|
||||||
* operation if control fails? */
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* nested transaction */
|
|
||||||
rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, <2, bdb->bi_db_opflags );
|
|
||||||
rs->sr_text = NULL;
|
|
||||||
if( rs->sr_err != 0 ) {
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_modrdn)
|
|
||||||
": txn_begin(2) failed: %s (%d)\n",
|
|
||||||
db_strerror(rs->sr_err), rs->sr_err );
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "internal error";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn) ": txn2 id: %x\n",
|
|
||||||
lt2->id(lt2) );
|
|
||||||
|
|
||||||
/* delete old DN */
|
|
||||||
rs->sr_err = bdb_dn2id_delete( op, lt2, eip, e );
|
|
||||||
if ( rs->sr_err != 0 ) {
|
|
||||||
Debug(LDAP_DEBUG_TRACE,
|
|
||||||
"<=- " LDAP_XSTRING(bdb_modrdn)
|
|
||||||
": dn2id del failed: %s (%d)\n",
|
|
||||||
db_strerror(rs->sr_err), rs->sr_err );
|
|
||||||
switch( rs->sr_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "DN index delete fail";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* copy the entry, then override some fields */
|
|
||||||
dummy = *e;
|
|
||||||
dummy.e_name = new_dn;
|
|
||||||
dummy.e_nname = new_ndn;
|
|
||||||
dummy.e_attrs = NULL;
|
|
||||||
|
|
||||||
/* add new DN */
|
|
||||||
rs->sr_err = bdb_dn2id_add( op, lt2, neip ? neip : eip, &dummy );
|
|
||||||
if ( rs->sr_err != 0 ) {
|
|
||||||
Debug(LDAP_DEBUG_TRACE,
|
|
||||||
"<=- " LDAP_XSTRING(bdb_modrdn)
|
|
||||||
": dn2id add failed: %s (%d)\n",
|
|
||||||
db_strerror(rs->sr_err), rs->sr_err );
|
|
||||||
switch( rs->sr_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "DN index add failed";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
dummy.e_attrs = e->e_attrs;
|
|
||||||
|
|
||||||
if( op->orr_modlist != NULL ) {
|
|
||||||
/* modify entry */
|
|
||||||
rs->sr_err = bdb_modify_internal( op, lt2, op->orr_modlist, &dummy,
|
|
||||||
&rs->sr_text, textbuf, textlen );
|
|
||||||
if( rs->sr_err != LDAP_SUCCESS ) {
|
|
||||||
Debug(LDAP_DEBUG_TRACE,
|
|
||||||
"<=- " LDAP_XSTRING(bdb_modrdn)
|
|
||||||
": modify failed: %s (%d)\n",
|
|
||||||
db_strerror(rs->sr_err), rs->sr_err );
|
|
||||||
if ( ( rs->sr_err == LDAP_INSUFFICIENT_ACCESS ) && opinfo.boi_err ) {
|
|
||||||
rs->sr_err = opinfo.boi_err;
|
|
||||||
}
|
|
||||||
switch( rs->sr_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* id2entry index */
|
|
||||||
rs->sr_err = bdb_id2entry_update( op->o_bd, lt2, &dummy );
|
|
||||||
if ( rs->sr_err != 0 ) {
|
|
||||||
Debug(LDAP_DEBUG_TRACE,
|
|
||||||
"<=- " LDAP_XSTRING(bdb_modrdn)
|
|
||||||
": id2entry failed: %s (%d)\n",
|
|
||||||
db_strerror(rs->sr_err), rs->sr_err );
|
|
||||||
switch( rs->sr_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "entry update failed";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( p_ndn.bv_len != 0 ) {
|
|
||||||
parent_is_glue = is_entry_glue(p);
|
|
||||||
rs->sr_err = bdb_cache_children( op, lt2, p );
|
|
||||||
if ( rs->sr_err != DB_NOTFOUND ) {
|
|
||||||
switch( rs->sr_err ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Debug(LDAP_DEBUG_ARGS,
|
|
||||||
"<=- " LDAP_XSTRING(bdb_modrdn)
|
|
||||||
": has_children failed: %s (%d)\n",
|
|
||||||
db_strerror(rs->sr_err), rs->sr_err );
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "internal error";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
parent_is_leaf = 1;
|
|
||||||
}
|
|
||||||
bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
|
|
||||||
p = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
rs->sr_text = "txn_commit(2) failed";
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( op->o_postread ) {
|
|
||||||
if( postread_ctrl == NULL ) {
|
|
||||||
postread_ctrl = &ctrls[num_ctrls++];
|
|
||||||
ctrls[num_ctrls] = NULL;
|
|
||||||
}
|
|
||||||
if( slap_read_controls( op, rs, &dummy,
|
|
||||||
&slap_post_read_bv, postread_ctrl ) )
|
|
||||||
{
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
"<=- " LDAP_XSTRING(bdb_modrdn)
|
|
||||||
": post-read failed!\n" );
|
|
||||||
if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
|
|
||||||
/* FIXME: is it correct to abort
|
|
||||||
* operation if control fails? */
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( op->o_noop ) {
|
|
||||||
if(( rs->sr_err=TXN_ABORT( ltid )) != 0 ) {
|
|
||||||
rs->sr_text = "txn_abort (no-op) failed";
|
|
||||||
} else {
|
|
||||||
rs->sr_err = LDAP_X_NO_OPERATION;
|
|
||||||
ltid = NULL;
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
rc = bdb_cache_modrdn( bdb, e, &op->orr_nnewrdn, &dummy, neip,
|
|
||||||
ltid, &lock );
|
|
||||||
switch( rc ) {
|
|
||||||
case DB_LOCK_DEADLOCK:
|
|
||||||
case DB_LOCK_NOTGRANTED:
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
dummy.e_attrs = NULL;
|
|
||||||
new_dn.bv_val = NULL;
|
|
||||||
new_ndn.bv_val = NULL;
|
|
||||||
|
|
||||||
if(( rs->sr_err=TXN_COMMIT( ltid, 0 )) != 0 ) {
|
|
||||||
rs->sr_text = "txn_commit failed";
|
|
||||||
} else {
|
|
||||||
rs->sr_err = LDAP_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ltid = NULL;
|
|
||||||
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
|
|
||||||
opinfo.boi_oe.oe_key = NULL;
|
|
||||||
|
|
||||||
if( rs->sr_err != LDAP_SUCCESS ) {
|
|
||||||
Debug( LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_modrdn) ": %s : %s (%d)\n",
|
|
||||||
rs->sr_text, db_strerror(rs->sr_err), rs->sr_err );
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
|
|
||||||
goto return_results;
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug(LDAP_DEBUG_TRACE,
|
|
||||||
LDAP_XSTRING(bdb_modrdn)
|
|
||||||
": rdn modified%s id=%08lx dn=\"%s\"\n",
|
|
||||||
op->o_noop ? " (no-op)" : "",
|
|
||||||
dummy.e_id, op->o_req_dn.bv_val );
|
|
||||||
rs->sr_text = NULL;
|
|
||||||
if( num_ctrls ) rs->sr_ctrls = ctrls;
|
|
||||||
|
|
||||||
return_results:
|
|
||||||
if ( dummy.e_attrs != e->e_attrs ) {
|
|
||||||
attrs_free( dummy.e_attrs );
|
|
||||||
}
|
|
||||||
send_ldap_result( op, rs );
|
|
||||||
|
|
||||||
if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp_kbyte ) {
|
|
||||||
TXN_CHECKPOINT( bdb->bi_dbenv,
|
|
||||||
bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( rs->sr_err == LDAP_SUCCESS && parent_is_glue && parent_is_leaf ) {
|
|
||||||
op->o_delete_glue_parent = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
|
||||||
slap_graduate_commit_csn( op );
|
|
||||||
|
|
||||||
if( new_dn.bv_val != NULL ) free( new_dn.bv_val );
|
|
||||||
if( new_ndn.bv_val != NULL ) free( new_ndn.bv_val );
|
|
||||||
|
|
||||||
/* LDAP v3 Support */
|
|
||||||
if( np != NULL ) {
|
|
||||||
/* free new parent and reader lock */
|
|
||||||
bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, np);
|
|
||||||
}
|
|
||||||
|
|
||||||
if( p != NULL ) {
|
|
||||||
/* free parent and reader lock */
|
|
||||||
bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* free entry */
|
|
||||||
if( e != NULL ) {
|
|
||||||
bdb_unlocked_cache_return_entry_w( &bdb->bi_cache, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ltid != NULL ) {
|
|
||||||
TXN_ABORT( ltid );
|
|
||||||
}
|
|
||||||
if ( opinfo.boi_oe.oe_key ) {
|
|
||||||
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) {
|
|
||||||
slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
|
|
||||||
slap_sl_free( *preread_ctrl, op->o_tmpmemctx );
|
|
||||||
}
|
|
||||||
if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) {
|
|
||||||
slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
|
|
||||||
slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
|
|
||||||
}
|
|
||||||
return rs->sr_err;
|
|
||||||
}
|
|
||||||
|
|
@ -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 */
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -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 */
|
|
||||||
|
|
@ -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
|
|
@ -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 );
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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_ */
|
|
||||||
|
|
@ -113,7 +113,7 @@ static int write_data( int fd, const char *spew, int len, int *save_errno );
|
||||||
#endif /* !_WIN32 */
|
#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.
|
* IX_DN* are for LDAP RDNs, IX_FS* for their .ldif filenames.
|
||||||
*/
|
*/
|
||||||
#define IX_DNL '{'
|
#define IX_DNL '{'
|
||||||
|
|
|
||||||
|
|
@ -1962,8 +1962,8 @@ monitor_back_initialize(
|
||||||
{ "olmGenericAttributes", "olmSubSystemAttributes:0" },
|
{ "olmGenericAttributes", "olmSubSystemAttributes:0" },
|
||||||
{ "olmDatabaseAttributes", "olmSubSystemAttributes:1" },
|
{ "olmDatabaseAttributes", "olmSubSystemAttributes:1" },
|
||||||
|
|
||||||
/* for example, back-bdb specific attrs
|
/* for example, back-mdb specific attrs
|
||||||
* are in "olmDatabaseAttributes:1"
|
* are in "olmDatabaseAttributes:12"
|
||||||
*
|
*
|
||||||
* NOTE: developers, please record here OID assignments
|
* NOTE: developers, please record here OID assignments
|
||||||
* for other modules */
|
* for other modules */
|
||||||
|
|
@ -1973,8 +1973,8 @@ monitor_back_initialize(
|
||||||
{ "olmGenericObjectClasses", "olmSubSystemObjectClasses:0" },
|
{ "olmGenericObjectClasses", "olmSubSystemObjectClasses:0" },
|
||||||
{ "olmDatabaseObjectClasses", "olmSubSystemObjectClasses:1" },
|
{ "olmDatabaseObjectClasses", "olmSubSystemObjectClasses:1" },
|
||||||
|
|
||||||
/* for example, back-bdb specific objectClasses
|
/* for example, back-mdb specific objectClasses
|
||||||
* are in "olmDatabaseObjectClasses:1"
|
* are in "olmDatabaseObjectClasses:12"
|
||||||
*
|
*
|
||||||
* NOTE: developers, please record here OID assignments
|
* NOTE: developers, please record here OID assignments
|
||||||
* for other modules */
|
* for other modules */
|
||||||
|
|
|
||||||
|
|
@ -247,7 +247,7 @@ static OidRec OidMacros[] = {
|
||||||
* Backend/Database registry
|
* Backend/Database registry
|
||||||
*
|
*
|
||||||
* OLcfg{Bk|Db}{Oc|At}:0 -> common
|
* 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}:2 -> back-ldif
|
||||||
* OLcfg{Bk|Db}{Oc|At}:3 -> back-ldap/meta
|
* OLcfg{Bk|Db}{Oc|At}:3 -> back-ldap/meta
|
||||||
* OLcfg{Bk|Db}{Oc|At}:4 -> back-monitor
|
* OLcfg{Bk|Db}{Oc|At}:4 -> back-monitor
|
||||||
|
|
|
||||||
|
|
@ -1130,8 +1130,7 @@ rdn_validate( struct berval *rdn )
|
||||||
|
|
||||||
/* build_new_dn:
|
/* build_new_dn:
|
||||||
*
|
*
|
||||||
* Used by back-bdb back_modrdn to create the new dn of entries being
|
* Used to create the new dn of entries being renamed.
|
||||||
* renamed.
|
|
||||||
*
|
*
|
||||||
* new_dn = parent (p_dn) + separator + rdn (newrdn) + null.
|
* new_dn = parent (p_dn) + separator + rdn (newrdn) + null.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -5613,7 +5613,7 @@ cleanup:;
|
||||||
cm->monitor_cb = (void *)cb;
|
cm->monitor_cb = (void *)cb;
|
||||||
|
|
||||||
/* we don't need to keep track of the attributes, because
|
/* 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 ) {
|
if ( a != NULL ) {
|
||||||
attrs_free( a );
|
attrs_free( a );
|
||||||
}
|
}
|
||||||
|
|
@ -5697,7 +5697,7 @@ pcache_initialize()
|
||||||
}
|
}
|
||||||
#endif /* PCACHE_EXOP_QUERY_DELETE */
|
#endif /* PCACHE_EXOP_QUERY_DELETE */
|
||||||
|
|
||||||
argv[ 0 ] = "back-bdb/back-hdb monitor";
|
argv[ 0 ] = "back-mdb monitor";
|
||||||
c.argv = argv;
|
c.argv = argv;
|
||||||
c.argc = 3;
|
c.argc = 3;
|
||||||
c.fname = argv[0];
|
c.fname = argv[0];
|
||||||
|
|
|
||||||
|
|
@ -1818,7 +1818,6 @@ struct BackendDB {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* define to honor hasSubordinates operational attribute in search filters
|
* 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
|
#define be_has_subordinates bd_info->bi_has_subordinates
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,7 @@ olcPidFile: %LOCALSTATEDIR%/run/slapd.pid
|
||||||
#objectClass: olcModuleList
|
#objectClass: olcModuleList
|
||||||
#cn: module
|
#cn: module
|
||||||
#olcModulepath: %MODULEDIR%
|
#olcModulepath: %MODULEDIR%
|
||||||
#olcModuleload: back_bdb.la
|
#olcModuleload: back_mdb.la
|
||||||
#olcModuleload: back_hdb.la
|
|
||||||
#olcModuleload: back_ldap.la
|
#olcModuleload: back_ldap.la
|
||||||
#olcModuleload: back_passwd.la
|
#olcModuleload: back_passwd.la
|
||||||
#olcModuleload: back_shell.la
|
#olcModuleload: back_shell.la
|
||||||
|
|
|
||||||
|
|
@ -16,15 +16,11 @@
|
||||||
RUN=./run
|
RUN=./run
|
||||||
SUBDIRS= progs
|
SUBDIRS= progs
|
||||||
|
|
||||||
BUILD_BDB=@BUILD_BDB@
|
|
||||||
BUILD_HDB=@BUILD_HDB@
|
|
||||||
BUILD_MDB=@BUILD_MDB@
|
BUILD_MDB=@BUILD_MDB@
|
||||||
BUILD_SQL=@BUILD_SQL@
|
BUILD_SQL=@BUILD_SQL@
|
||||||
|
|
||||||
# test primary backends (default)
|
# test primary backends (default)
|
||||||
test tests:
|
test tests:
|
||||||
@$(MAKE) bdb
|
|
||||||
@$(MAKE) hdb
|
|
||||||
@$(MAKE) mdb
|
@$(MAKE) mdb
|
||||||
|
|
||||||
# test all backends
|
# test all backends
|
||||||
|
|
@ -32,22 +28,6 @@ alltests: tests
|
||||||
@$(MAKE) sql
|
@$(MAKE) sql
|
||||||
@$(MAKE) ldif
|
@$(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 test-mdb: mdb-$(BUILD_MDB)
|
||||||
mdb-no:
|
mdb-no:
|
||||||
@echo "run configure with --enable-mdb to run MDB tests"
|
@echo "run configure with --enable-mdb to run MDB tests"
|
||||||
|
|
@ -70,26 +50,10 @@ ldif test-ldif: FORCE
|
||||||
|
|
||||||
regressions: FORCE
|
regressions: FORCE
|
||||||
@echo "Testing (available) ITS regressions"
|
@echo "Testing (available) ITS regressions"
|
||||||
@$(MAKE) bdb-its
|
|
||||||
@$(MAKE) hdb-its
|
|
||||||
@$(MAKE) mdb-its
|
@$(MAKE) mdb-its
|
||||||
|
|
||||||
its: regressions
|
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: mdb-its-$(BUILD_MDB)
|
||||||
mdb-its-no:
|
mdb-its-no:
|
||||||
@echo "run configure with --enable-mdb to run MDB ITS regressions"
|
@echo "run configure with --enable-mdb to run MDB ITS regressions"
|
||||||
|
|
|
||||||
|
|
@ -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.
|
verify basic functionality of the LDAP libraries and slapd.
|
||||||
|
|
||||||
To run all of the tests, type "make test".
|
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 MDB tests, type "make mdb".
|
||||||
To run SQL tests, define SLAPD_USE_SQL=<rdbms> and type
|
To run SQL tests, define SLAPD_USE_SQL=<rdbms> and type
|
||||||
"make sql"; define SLAPD_USE_SQLWRITE=yes
|
"make sql"; define SLAPD_USE_SQLWRITE=yes
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,6 @@
|
||||||
echo "running defines.sh"
|
echo "running defines.sh"
|
||||||
. $SRCDIR/scripts/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
|
mkdir -p $DBDIR1A $DBDIR2A
|
||||||
|
|
||||||
ITS=4184
|
ITS=4184
|
||||||
|
|
|
||||||
|
|
@ -47,22 +47,6 @@ ITS=4448
|
||||||
ITSDIR=$DATADIR/regressions/its$ITS
|
ITSDIR=$DATADIR/regressions/its$ITS
|
||||||
ITSCONF=$ITSDIR/slapd-meta.conf
|
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..."
|
echo "Starting slapd on TCP/IP port $PORT1..."
|
||||||
. $CONFFILTER $BACKEND $MONITORDB < $CONF > $CONF1
|
. $CONFFILTER $BACKEND $MONITORDB < $CONF > $CONF1
|
||||||
$SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
|
$SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
|
||||||
|
|
|
||||||
|
|
@ -64,10 +64,6 @@ pcachetemplate (cn=) 0 86400 86400 86400 180
|
||||||
|
|
||||||
pcachebind (cn=) 0 3600 sub ou=people,dc=example,dc=com
|
pcachebind (cn=) 0 3600 sub ou=people,dc=example,dc=com
|
||||||
|
|
||||||
#bdb#cachesize 20
|
|
||||||
#hdb#cachesize 20
|
|
||||||
#bdb#dbnosync
|
|
||||||
#hdb#dbnosync
|
|
||||||
#mdb#dbnosync
|
#mdb#dbnosync
|
||||||
|
|
||||||
#~null~#directory @TESTDIR@/db.2.a
|
#~null~#directory @TESTDIR@/db.2.a
|
||||||
|
|
|
||||||
|
|
@ -54,10 +54,6 @@ pcachetemplate (mail=) 0 @TTL@ @NTTL@ @STTL@
|
||||||
pcachetemplate (&(objectclass=)(uid=)) 1 @TTL@ @NTTL@ @STTL@ @TTR@
|
pcachetemplate (&(objectclass=)(uid=)) 1 @TTL@ @NTTL@ @STTL@ @TTR@
|
||||||
pcachebind (&(objectclass=person)(uid=)) 1 @BTTR@ sub "ou=Alumni Association,ou=people,dc=example,dc=com"
|
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
|
#mdb#dbnosync
|
||||||
|
|
||||||
#~null~#directory @TESTDIR@/db.2.a
|
#~null~#directory @TESTDIR@/db.2.a
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,6 @@ argsfile @TESTDIR@/slapd.2.args
|
||||||
referral "@URI1@"
|
referral "@URI1@"
|
||||||
|
|
||||||
database @BACKEND@
|
database @BACKEND@
|
||||||
#bdb#cachesize 0
|
|
||||||
#hdb#cachesize 0
|
|
||||||
|
|
||||||
suffix "o=University of Mich,c=US"
|
suffix "o=University of Mich,c=US"
|
||||||
rootdn "cn=Manager,o=University of Mich,c=US"
|
rootdn "cn=Manager,o=University of Mich,c=US"
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,6 @@ rootpw secret
|
||||||
#~null~#directory @TESTDIR@/db.1.a
|
#~null~#directory @TESTDIR@/db.1.a
|
||||||
#indexdb#index objectClass eq
|
#indexdb#index objectClass eq
|
||||||
#indexdb#index cn,sn,uid pres,eq,sub
|
#indexdb#index cn,sn,uid pres,eq,sub
|
||||||
#bdb#checkpoint 1024 5
|
|
||||||
#hdb#checkpoint 1024 5
|
|
||||||
#mdb#maxsize 33554432
|
#mdb#maxsize 33554432
|
||||||
#ndb#dbname db_1
|
#ndb#dbname db_1
|
||||||
#ndb#include @DATADIR@/ndb.conf
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,6 @@ EGREP_CMD="@EGREP@"
|
||||||
export SRCDIR TOPSRCDIR LN_S EGREP_CMD
|
export SRCDIR TOPSRCDIR LN_S EGREP_CMD
|
||||||
|
|
||||||
# backends known to ./run -b <backend> (used to deduce $BACKENDTYPE)
|
# backends known to ./run -b <backend> (used to deduce $BACKENDTYPE)
|
||||||
AC_bdb=@BUILD_BDB@
|
|
||||||
AC_hdb=@BUILD_HDB@
|
|
||||||
AC_ldif=yes
|
AC_ldif=yes
|
||||||
AC_mdb=@BUILD_MDB@
|
AC_mdb=@BUILD_MDB@
|
||||||
AC_null=@BUILD_NULL@
|
AC_null=@BUILD_NULL@
|
||||||
|
|
@ -74,7 +72,7 @@ fi
|
||||||
if test "${AC_asyncmeta}" = "metamod" && test "${AC_LIBS_DYNAMIC}" = "static" ; then
|
if test "${AC_asyncmeta}" = "metamod" && test "${AC_LIBS_DYNAMIC}" = "static" ; then
|
||||||
AC_meta="asyncmetano"
|
AC_meta="asyncmetano"
|
||||||
fi
|
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_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_refint AC_retcode AC_rwm AC_unique AC_syncprov AC_translucent \
|
||||||
AC_valsort \
|
AC_valsort \
|
||||||
|
|
@ -158,7 +156,7 @@ while test $# -gt 0 ; do
|
||||||
done
|
done
|
||||||
|
|
||||||
if test -z "$BACKEND" ; then
|
if test -z "$BACKEND" ; then
|
||||||
for b in bdb hdb mdb ; do
|
for b in mdb ; do
|
||||||
if eval "test \"\$AC_$b\" != no" ; then
|
if eval "test \"\$AC_$b\" != no" ; then
|
||||||
BACKEND=$b
|
BACKEND=$b
|
||||||
break
|
break
|
||||||
|
|
@ -179,7 +177,7 @@ fi
|
||||||
# maindb: main storage backend. Currently index,limits,mode,paged results.
|
# maindb: main storage backend. Currently index,limits,mode,paged results.
|
||||||
INDEXDB=noindexdb MAINDB=nomaindb
|
INDEXDB=noindexdb MAINDB=nomaindb
|
||||||
case $BACKEND in
|
case $BACKEND in
|
||||||
bdb|hdb|mdb) INDEXDB=indexdb MAINDB=maindb ;;
|
mdb) INDEXDB=indexdb MAINDB=maindb ;;
|
||||||
ndb) INDEXDB=indexdb ;;
|
ndb) INDEXDB=indexdb ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -189,8 +189,7 @@ if test $RC != 0 ; then
|
||||||
exit $RC
|
exit $RC
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test $BACKEND != "bdb" ; then
|
$LDAPMODIFY -v -D "$REFINTDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
|
||||||
$LDAPMODIFY -v -D "$REFINTDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
|
|
||||||
$TESTOUT 2>&1 << EDEL
|
$TESTOUT 2>&1 << EDEL
|
||||||
version: 1
|
version: 1
|
||||||
dn: cn=group,o=refint
|
dn: cn=group,o=refint
|
||||||
|
|
@ -205,63 +204,62 @@ member: uid=theman,ou=users,o=refint
|
||||||
member: uid=richard,ou=users,o=refint
|
member: uid=richard,ou=users,o=refint
|
||||||
EDEL
|
EDEL
|
||||||
|
|
||||||
RC=$?
|
RC=$?
|
||||||
if test $RC != 0 ; then
|
if test $RC != 0 ; then
|
||||||
echo "ldapmodify failed ($RC)!"
|
echo "ldapmodify failed ($RC)!"
|
||||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||||
exit $RC
|
exit $RC
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sleep 1;
|
sleep 1;
|
||||||
|
|
||||||
$LDAPSEARCH -S "" -b "o=refint" -h $LOCALHOST -p $PORT1 \
|
$LDAPSEARCH -S "" -b "o=refint" -h $LOCALHOST -p $PORT1 \
|
||||||
manager member secretary > $SEARCHOUT 2>&1
|
manager member secretary > $SEARCHOUT 2>&1
|
||||||
RC=$?
|
RC=$?
|
||||||
if test $RC != 0 ; then
|
if test $RC != 0 ; then
|
||||||
echo "ldapsearch failed ($RC)!"
|
echo "ldapsearch failed ($RC)!"
|
||||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||||
exit $RC
|
exit $RC
|
||||||
fi
|
fi
|
||||||
|
|
||||||
$EGREP_CMD "(manager|member|secretary):" $SEARCHOUT \
|
$EGREP_CMD "(manager|member|secretary):" $SEARCHOUT \
|
||||||
| sed "s/ou=users/ou=people/g" | \
|
| sed "s/ou=users/ou=people/g" | \
|
||||||
sort > $TESTOUT 2>&1
|
sort > $TESTOUT 2>&1
|
||||||
|
|
||||||
echo "testing subtree rename"
|
echo "testing subtree rename"
|
||||||
$LDAPMODRDN -D "$REFINTDN" -r -h $LOCALHOST -p $PORT1 -w $PASSWD > \
|
$LDAPMODRDN -D "$REFINTDN" -r -h $LOCALHOST -p $PORT1 -w $PASSWD > \
|
||||||
/dev/null 2>&1 'ou=users,o=refint' 'ou=people'
|
/dev/null 2>&1 'ou=users,o=refint' 'ou=people'
|
||||||
RC=$?
|
RC=$?
|
||||||
if test $RC != 0 ; then
|
if test $RC != 0 ; then
|
||||||
echo "ldapmodrdn failed ($RC)!"
|
echo "ldapmodrdn failed ($RC)!"
|
||||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||||
exit $RC
|
exit $RC
|
||||||
fi
|
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 \
|
$LDAPSEARCH -S "" -b "o=refint" -h $LOCALHOST -p $PORT1 \
|
||||||
manager member secretary > $SEARCHOUT 2>&1
|
manager member secretary > $SEARCHOUT 2>&1
|
||||||
|
|
||||||
RC=$?
|
RC=$?
|
||||||
if test $RC != 0 ; then
|
if test $RC != 0 ; then
|
||||||
echo "ldapsearch failed ($RC)!"
|
echo "ldapsearch failed ($RC)!"
|
||||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||||
exit $RC
|
exit $RC
|
||||||
fi
|
fi
|
||||||
|
|
||||||
$EGREP_CMD "(manager|member|secretary):" $SEARCHOUT \
|
$EGREP_CMD "(manager|member|secretary):" $SEARCHOUT \
|
||||||
| sort > $SEARCHFLT 2>&1
|
| sort > $SEARCHFLT 2>&1
|
||||||
|
|
||||||
echo "Comparing ldapsearch results against original..."
|
echo "Comparing ldapsearch results against original..."
|
||||||
$CMP $TESTOUT $SEARCHFLT > $CMPOUT
|
$CMP $TESTOUT $SEARCHFLT > $CMPOUT
|
||||||
|
|
||||||
if test $? != 0 ; then
|
if test $? != 0 ; then
|
||||||
echo "comparison failed - subtree rename operations did not complete correctly"
|
echo "comparison failed - subtree rename operations did not complete correctly"
|
||||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||||
|
|
|
||||||
|
|
@ -750,7 +750,7 @@ case $RC in
|
||||||
esac
|
esac
|
||||||
|
|
||||||
if test $MAINDB != maindb ; then
|
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
|
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||||
|
|
||||||
echo ">>>>> Test succeeded"
|
echo ">>>>> Test succeeded"
|
||||||
|
|
|
||||||
|
|
@ -40,22 +40,6 @@ rm -rf $TESTDIR
|
||||||
|
|
||||||
mkdir -p $TESTDIR $DBDIR1 $DBDIR2
|
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..."
|
echo "Starting slapd on TCP/IP port $PORT1..."
|
||||||
. $CONFFILTER $BACKEND $MONITORDB < $METACONF1 > $CONF1
|
. $CONFFILTER $BACKEND $MONITORDB < $METACONF1 > $CONF1
|
||||||
$SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
|
$SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,6 @@
|
||||||
echo "running defines.sh"
|
echo "running defines.sh"
|
||||||
. $SRCDIR/scripts/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
|
mkdir -p $TESTDIR $DBDIR1
|
||||||
|
|
||||||
echo "Starting slapd on TCP/IP port $PORT1..."
|
echo "Starting slapd on TCP/IP port $PORT1..."
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ fi
|
||||||
|
|
||||||
mkdir -p $TESTDIR $DBDIR1A $DBDIR1B $DBDIR2
|
mkdir -p $TESTDIR $DBDIR1A $DBDIR1B $DBDIR2
|
||||||
|
|
||||||
SPEC="mdb=a,bdb=a,hdb=a"
|
SPEC="mdb=a"
|
||||||
|
|
||||||
#
|
#
|
||||||
# Test replication:
|
# Test replication:
|
||||||
|
|
|
||||||
|
|
@ -72,11 +72,10 @@ EOF
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
indexInclude="" mainInclude="" bdbInclude="# " nullExclude=""
|
indexInclude="" mainInclude="" " nullExclude=""
|
||||||
test $INDEXDB = indexdb || indexInclude="# "
|
test $INDEXDB = indexdb || indexInclude="# "
|
||||||
test $MAINDB = maindb || mainInclude="# "
|
test $MAINDB = maindb || mainInclude="# "
|
||||||
case $BACKEND in
|
case $BACKEND in
|
||||||
bdb | hdb) bdbInclude="" ;;
|
|
||||||
null) nullExclude="# " ;;
|
null) nullExclude="# " ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
|
@ -114,7 +113,6 @@ olcRootDN: cn=Manager,$BASEDN
|
||||||
olcRootPW:: c2VjcmV0
|
olcRootPW:: c2VjcmV0
|
||||||
olcMonitoring: TRUE
|
olcMonitoring: TRUE
|
||||||
${nullExclude}olcDbDirectory: $TESTDIR/db.1.a/
|
${nullExclude}olcDbDirectory: $TESTDIR/db.1.a/
|
||||||
${bdbInclude}olcDbCacheSize: 1000
|
|
||||||
${indexInclude}olcDbIndex: objectClass eq
|
${indexInclude}olcDbIndex: objectClass eq
|
||||||
${indexInclude}olcDbIndex: cn pres,eq,sub
|
${indexInclude}olcDbIndex: cn pres,eq,sub
|
||||||
${indexInclude}olcDbIndex: uid pres,eq,sub
|
${indexInclude}olcDbIndex: uid pres,eq,sub
|
||||||
|
|
|
||||||
|
|
@ -479,29 +479,6 @@ if test $RC != 0 ; then
|
||||||
exit $RC
|
exit $RC
|
||||||
fi
|
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..."
|
echo "Using ldapmodify to modify glue suffix on provider..."
|
||||||
$LDAPADD -D "$MANAGERDN" -H $URI1 -w $PASSWD <<EOF >> $TESTOUT 2>&1
|
$LDAPADD -D "$MANAGERDN" -H $URI1 -w $PASSWD <<EOF >> $TESTOUT 2>&1
|
||||||
dn: dc=example,dc=com
|
dn: dc=example,dc=com
|
||||||
|
|
|
||||||
|
|
@ -85,8 +85,7 @@ echo "Using ldapsearch to read database monitor entries..."
|
||||||
$LDAPSEARCH -S "" -b "$DATABASESMONITORDN" -h $LOCALHOST -p $PORT1 \
|
$LDAPSEARCH -S "" -b "$DATABASESMONITORDN" -h $LOCALHOST -p $PORT1 \
|
||||||
'objectclass=*' \
|
'objectclass=*' \
|
||||||
structuralObjectClass entryDN namingContexts readOnly \
|
structuralObjectClass entryDN namingContexts readOnly \
|
||||||
monitorIsShadow monitorContext \
|
monitorIsShadow monitorContext
|
||||||
olmBDBEntryCache olmBDBDNCache olmBDBIDLCache \
|
|
||||||
> $SEARCHOUT 2>&1
|
> $SEARCHOUT 2>&1
|
||||||
RC=$?
|
RC=$?
|
||||||
|
|
||||||
|
|
@ -101,11 +100,8 @@ $LDIFFILTER -b monitor < $SEARCHOUT > $SEARCHFLT
|
||||||
|
|
||||||
TMPMONITOROUT2=$MONITOROUT2
|
TMPMONITOROUT2=$MONITOROUT2
|
||||||
case $BACKEND in
|
case $BACKEND in
|
||||||
bdb|hdb)
|
|
||||||
;;
|
|
||||||
*)
|
*)
|
||||||
TMPMONITOROUT2=$TESTDIR/monitor2.out
|
TMPMONITOROUT2=$TESTDIR/monitor2.out
|
||||||
grep -v "olmBDB" $MONITOROUT2 > $TMPMONITOROUT2
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,11 +27,6 @@ if test $REFINT = refintno; then
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
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
|
mkdir -p $TESTDIR $DBDIR1 $TESTDIR/confdir
|
||||||
|
|
||||||
$SLAPPASSWD -g -n >$CONFIGPWF
|
$SLAPPASSWD -g -n >$CONFIGPWF
|
||||||
|
|
@ -66,11 +61,10 @@ fi
|
||||||
|
|
||||||
cat /dev/null > $TESTOUT
|
cat /dev/null > $TESTOUT
|
||||||
|
|
||||||
indexInclude="" mainInclude="" bdbInclude="# " nullExclude=""
|
indexInclude="" mainInclude="" nullExclude=""
|
||||||
test $INDEXDB = indexdb || indexInclude="# "
|
test $INDEXDB = indexdb || indexInclude="# "
|
||||||
test $MAINDB = maindb || mainInclude="# "
|
test $MAINDB = maindb || mainInclude="# "
|
||||||
case $BACKEND in
|
case $BACKEND in
|
||||||
bdb | hdb) bdbInclude="" ;;
|
|
||||||
null) nullExclude="# " ;;
|
null) nullExclude="# " ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
|
@ -104,7 +98,6 @@ olcRootDN: cn=Manager,$BASEDN
|
||||||
olcRootPW:: c2VjcmV0
|
olcRootPW:: c2VjcmV0
|
||||||
olcMonitoring: TRUE
|
olcMonitoring: TRUE
|
||||||
${nullExclude}olcDbDirectory: $TESTDIR/db.1.a/
|
${nullExclude}olcDbDirectory: $TESTDIR/db.1.a/
|
||||||
${bdbInclude}olcDbCacheSize: 1000
|
|
||||||
${indexInclude}olcDbIndex: objectClass eq
|
${indexInclude}olcDbIndex: objectClass eq
|
||||||
${indexInclude}olcDbIndex: cn pres,eq,sub
|
${indexInclude}olcDbIndex: cn pres,eq,sub
|
||||||
${indexInclude}olcDbIndex: uid pres,eq,sub
|
${indexInclude}olcDbIndex: uid pres,eq,sub
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,6 @@ KILLPIDS=
|
||||||
$SLAPPASSWD -g -n >$CONFIGPWF
|
$SLAPPASSWD -g -n >$CONFIGPWF
|
||||||
|
|
||||||
case "$BACKEND" in
|
case "$BACKEND" in
|
||||||
bdb|hdb) olcDbCheckpoint="olcDbCheckpoint";;
|
|
||||||
*) olcDbCheckpoint="# olcDbCheckpoint";;
|
*) olcDbCheckpoint="# olcDbCheckpoint";;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue