mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-03-19 14:30:57 +08: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
27
.gitignore
vendored
27
.gitignore
vendored
@ -152,33 +152,6 @@ libraries/librewrite/rewrite
|
||||
libraries/librewrite/version.c
|
||||
servers/slapd/.backend
|
||||
servers/slapd/all-cffiles
|
||||
servers/slapd/back-hdb/add.c
|
||||
servers/slapd/back-hdb/attr.c
|
||||
servers/slapd/back-hdb/bind.c
|
||||
servers/slapd/back-hdb/cache.c
|
||||
servers/slapd/back-hdb/compare.c
|
||||
servers/slapd/back-hdb/config.c
|
||||
servers/slapd/back-hdb/dbcache.c
|
||||
servers/slapd/back-hdb/delete.c
|
||||
servers/slapd/back-hdb/dn2entry.c
|
||||
servers/slapd/back-hdb/dn2id.c
|
||||
servers/slapd/back-hdb/error.c
|
||||
servers/slapd/back-hdb/extended.c
|
||||
servers/slapd/back-hdb/filterindex.c
|
||||
servers/slapd/back-hdb/id2entry.c
|
||||
servers/slapd/back-hdb/idl.c
|
||||
servers/slapd/back-hdb/index.c
|
||||
servers/slapd/back-hdb/init.c
|
||||
servers/slapd/back-hdb/key.c
|
||||
servers/slapd/back-hdb/modify.c
|
||||
servers/slapd/back-hdb/modrdn.c
|
||||
servers/slapd/back-hdb/monitor.c
|
||||
servers/slapd/back-hdb/nextid.c
|
||||
servers/slapd/back-hdb/operational.c
|
||||
servers/slapd/back-hdb/referral.c
|
||||
servers/slapd/back-hdb/search.c
|
||||
servers/slapd/back-hdb/tools.c
|
||||
servers/slapd/back-hdb/trans.c
|
||||
servers/slapd/backends.c
|
||||
servers/slapd/overlays/statover.c
|
||||
servers/slapd/slapacl
|
||||
|
3
INSTALL
3
INSTALL
@ -73,9 +73,6 @@ Making and Installing the OpenLDAP Distribution
|
||||
|
||||
6. Test the standalone system:
|
||||
|
||||
This step requires the standalone LDAP server, slapd(8), with HDB
|
||||
and/or BDB support.
|
||||
|
||||
% make test
|
||||
|
||||
If all goes well, the system has been built as configured. If
|
||||
|
@ -270,298 +270,6 @@ if test $ac_cv_header_unicode_utypes_h = yes ; then
|
||||
fi
|
||||
fi
|
||||
])
|
||||
dnl
|
||||
dnl ====================================================================
|
||||
dnl Berkeley DB macros
|
||||
dnl
|
||||
dnl --------------------------------------------------------------------
|
||||
dnl Try to link
|
||||
AC_DEFUN([OL_BERKELEY_DB_TRY],
|
||||
[if test $ol_cv_lib_db = no ; then
|
||||
AC_CACHE_CHECK([for Berkeley DB link (]ifelse($2,,default,$2)[)],[$1],
|
||||
[
|
||||
ol_DB_LIB=ifelse($2,,,$2)
|
||||
ol_LIBS=$LIBS
|
||||
LIBS="$ol_DB_LIB $LTHREAD_LIBS $LIBS"
|
||||
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#ifdef HAVE_DB_185_H
|
||||
# include <db_185.h>
|
||||
#else
|
||||
# include <db.h>
|
||||
#endif
|
||||
|
||||
#ifndef DB_VERSION_MAJOR
|
||||
# define DB_VERSION_MAJOR 1
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void*)0)
|
||||
#endif
|
||||
]], [[
|
||||
#if DB_VERSION_MAJOR > 2
|
||||
db_env_create( NULL, 0 );
|
||||
#elif DB_VERSION_MAJOR > 1
|
||||
db_appexit( NULL );
|
||||
#else
|
||||
(void) dbopen( NULL, 0, 0, 0, NULL);
|
||||
#endif
|
||||
]])],[$1=yes],[$1=no])
|
||||
|
||||
LIBS="$ol_LIBS"
|
||||
])
|
||||
|
||||
if test $$1 = yes ; then
|
||||
ol_cv_lib_db=ifelse($2,,yes,$2)
|
||||
fi
|
||||
fi
|
||||
])
|
||||
dnl
|
||||
dnl --------------------------------------------------------------------
|
||||
dnl Get major and minor version from <db.h>
|
||||
AC_DEFUN([OL_BDB_HEADER_VERSION],
|
||||
[AC_CACHE_CHECK([for Berkeley DB major version in db.h], [ol_cv_bdb_major],[
|
||||
AC_LANG_CONFTEST([AC_LANG_SOURCE([
|
||||
#include <db.h>
|
||||
#ifndef DB_VERSION_MAJOR
|
||||
# define DB_VERSION_MAJOR 1
|
||||
#endif
|
||||
__db_version DB_VERSION_MAJOR
|
||||
])])
|
||||
set X `eval "$ac_cpp -P conftest.$ac_ext" | $EGREP __db_version` none none
|
||||
ol_cv_bdb_major=${3}
|
||||
])
|
||||
case $ol_cv_bdb_major in [[1-9]]*) : ;; *)
|
||||
AC_MSG_ERROR([Unknown Berkeley DB major version in db.h]) ;;
|
||||
esac
|
||||
|
||||
dnl Determine minor version
|
||||
AC_CACHE_CHECK([for Berkeley DB minor version in db.h], [ol_cv_bdb_minor],[
|
||||
AC_LANG_CONFTEST([AC_LANG_SOURCE([
|
||||
#include <db.h>
|
||||
#ifndef DB_VERSION_MINOR
|
||||
# define DB_VERSION_MINOR 0
|
||||
#endif
|
||||
__db_version DB_VERSION_MINOR
|
||||
])])
|
||||
set X `eval "$ac_cpp -P conftest.$ac_ext" | $EGREP __db_version` none none
|
||||
ol_cv_bdb_minor=${3}
|
||||
])
|
||||
case $ol_cv_bdb_minor in [[0-9]]*) : ;; *)
|
||||
AC_MSG_ERROR([Unknown Berkeley DB minor version in db.h]) ;;
|
||||
esac
|
||||
])
|
||||
dnl
|
||||
dnl --------------------------------------------------------------------
|
||||
dnl Try to locate appropriate library
|
||||
AC_DEFUN([OL_BERKELEY_DB_LINK],
|
||||
[ol_cv_lib_db=no
|
||||
|
||||
if test $ol_cv_bdb_major = 5 ; then
|
||||
OL_BERKELEY_DB_TRY(ol_cv_db_db_5_dot_m,[-ldb-5.$ol_cv_bdb_minor])
|
||||
OL_BERKELEY_DB_TRY(ol_cv_db_db5m,[-ldb5$ol_cv_bdb_minor])
|
||||
OL_BERKELEY_DB_TRY(ol_cv_db_db_5m,[-ldb-5$ol_cv_bdb_minor])
|
||||
OL_BERKELEY_DB_TRY(ol_cv_db_db_5_m,[-ldb-5-$ol_cv_bdb_minor])
|
||||
OL_BERKELEY_DB_TRY(ol_cv_db_db_5,[-ldb-5])
|
||||
OL_BERKELEY_DB_TRY(ol_cv_db_db5,[-ldb5])
|
||||
elif test $ol_cv_bdb_major = 4 ; then
|
||||
OL_BERKELEY_DB_TRY(ol_cv_db_db_4_dot_m,[-ldb-4.$ol_cv_bdb_minor])
|
||||
OL_BERKELEY_DB_TRY(ol_cv_db_db4m,[-ldb4$ol_cv_bdb_minor])
|
||||
OL_BERKELEY_DB_TRY(ol_cv_db_db_4m,[-ldb-4$ol_cv_bdb_minor])
|
||||
OL_BERKELEY_DB_TRY(ol_cv_db_db_4_m,[-ldb-4-$ol_cv_bdb_minor])
|
||||
OL_BERKELEY_DB_TRY(ol_cv_db_db_4,[-ldb-4])
|
||||
OL_BERKELEY_DB_TRY(ol_cv_db_db4,[-ldb4])
|
||||
fi
|
||||
OL_BERKELEY_DB_TRY(ol_cv_db_db,[-ldb])
|
||||
OL_BERKELEY_DB_TRY(ol_cv_db_none)
|
||||
])
|
||||
dnl
|
||||
dnl --------------------------------------------------------------------
|
||||
dnl Check if Berkeley DB version
|
||||
AC_DEFUN([OL_BERKELEY_DB_VERSION],
|
||||
[AC_CACHE_CHECK([for Berkeley DB library and header version match], [ol_cv_berkeley_db_version], [
|
||||
ol_LIBS="$LIBS"
|
||||
LIBS="$LTHREAD_LIBS $LIBS"
|
||||
if test $ol_cv_lib_db != yes ; then
|
||||
LIBS="$ol_cv_lib_db $LIBS"
|
||||
fi
|
||||
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#ifdef HAVE_DB_185_H
|
||||
choke me;
|
||||
#else
|
||||
#include <db.h>
|
||||
#endif
|
||||
#ifndef DB_VERSION_MAJOR
|
||||
# define DB_VERSION_MAJOR 1
|
||||
#endif
|
||||
#ifndef NULL
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
main()
|
||||
{
|
||||
#if DB_VERSION_MAJOR > 1
|
||||
char *version;
|
||||
int major, minor, patch;
|
||||
|
||||
version = db_version( &major, &minor, &patch );
|
||||
|
||||
if( major != DB_VERSION_MAJOR ||
|
||||
minor != DB_VERSION_MINOR ||
|
||||
patch != DB_VERSION_PATCH )
|
||||
{
|
||||
printf("Berkeley DB version mismatch\n"
|
||||
"\theader: %s\n\tlibrary: %s\n",
|
||||
DB_VERSION_STRING, version);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}]])],[ol_cv_berkeley_db_version=yes],[ol_cv_berkeley_db_version=no],[ol_cv_berkeley_db_version=cross])
|
||||
|
||||
LIBS="$ol_LIBS"
|
||||
])
|
||||
|
||||
if test $ol_cv_berkeley_db_version = no ; then
|
||||
AC_MSG_ERROR([Berkeley DB version mismatch])
|
||||
fi
|
||||
])dnl
|
||||
dnl
|
||||
dnl --------------------------------------------------------------------
|
||||
dnl Check if Berkeley DB supports DB_THREAD
|
||||
AC_DEFUN([OL_BERKELEY_DB_THREAD],
|
||||
[AC_CACHE_CHECK([for Berkeley DB thread support], [ol_cv_berkeley_db_thread], [
|
||||
ol_LIBS="$LIBS"
|
||||
LIBS="$LTHREAD_LIBS $LIBS"
|
||||
if test $ol_cv_lib_db != yes ; then
|
||||
LIBS="$ol_cv_lib_db $LIBS"
|
||||
fi
|
||||
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#ifdef HAVE_DB_185_H
|
||||
choke me;
|
||||
#else
|
||||
#include <db.h>
|
||||
#endif
|
||||
#ifndef NULL
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
main()
|
||||
{
|
||||
int rc;
|
||||
u_int32_t flags = DB_CREATE |
|
||||
#ifdef DB_PRIVATE
|
||||
DB_PRIVATE |
|
||||
#endif
|
||||
DB_THREAD;
|
||||
|
||||
#if DB_VERSION_MAJOR > 2
|
||||
DB_ENV *env = NULL;
|
||||
|
||||
rc = db_env_create( &env, 0 );
|
||||
|
||||
flags |= DB_INIT_MPOOL;
|
||||
#ifdef DB_MPOOL_PRIVATE
|
||||
flags |= DB_MPOOL_PRIVATE;
|
||||
#endif
|
||||
|
||||
if( rc ) {
|
||||
printf("BerkeleyDB: %s\n", db_strerror(rc) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if (DB_VERSION_MAJOR > 3) || (DB_VERSION_MINOR >= 1)
|
||||
rc = (env->open)( env, NULL, flags, 0 );
|
||||
#else
|
||||
rc = (env->open)( env, NULL, NULL, flags, 0 );
|
||||
#endif
|
||||
|
||||
if ( rc == 0 ) {
|
||||
rc = env->close( env, 0 );
|
||||
}
|
||||
|
||||
if( rc ) {
|
||||
printf("BerkeleyDB: %s\n", db_strerror(rc) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
#else
|
||||
DB_ENV env;
|
||||
memset( &env, '\0', sizeof(env) );
|
||||
|
||||
rc = db_appinit( NULL, NULL, &env, flags );
|
||||
|
||||
if( rc == 0 ) {
|
||||
db_appexit( &env );
|
||||
}
|
||||
|
||||
unlink("__db_mpool.share");
|
||||
unlink("__db_lock.share");
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}]])],[ol_cv_berkeley_db_thread=yes],[ol_cv_berkeley_db_thread=no],[ol_cv_berkeley_db_thread=cross])
|
||||
|
||||
LIBS="$ol_LIBS"
|
||||
])
|
||||
|
||||
if test $ol_cv_berkeley_db_thread != no ; then
|
||||
AC_DEFINE(HAVE_BERKELEY_DB_THREAD, 1,
|
||||
[define if Berkeley DB has DB_THREAD support])
|
||||
fi
|
||||
])dnl
|
||||
dnl
|
||||
dnl --------------------------------------------------------------------
|
||||
dnl Find any DB
|
||||
AC_DEFUN([OL_BERKELEY_DB],
|
||||
[ol_cv_berkeley_db=no
|
||||
AC_CHECK_HEADERS(db.h)
|
||||
if test $ac_cv_header_db_h = yes; then
|
||||
OL_BDB_HEADER_VERSION
|
||||
OL_BDB_COMPAT
|
||||
|
||||
if test $ol_cv_bdb_compat != yes ; then
|
||||
AC_MSG_ERROR([BerkeleyDB version incompatible with BDB/HDB backends])
|
||||
fi
|
||||
|
||||
OL_BERKELEY_DB_LINK
|
||||
if test "$ol_cv_lib_db" != no ; then
|
||||
ol_cv_berkeley_db=yes
|
||||
OL_BERKELEY_DB_VERSION
|
||||
OL_BERKELEY_DB_THREAD
|
||||
fi
|
||||
fi
|
||||
])
|
||||
dnl --------------------------------------------------------------------
|
||||
dnl Check for version compatibility with back-bdb
|
||||
AC_DEFUN([OL_BDB_COMPAT],
|
||||
[AC_CACHE_CHECK([if Berkeley DB version supported by BDB/HDB backends], [ol_cv_bdb_compat],[
|
||||
AC_EGREP_CPP(__db_version_compat,[
|
||||
#include <db.h>
|
||||
|
||||
/* this check could be improved */
|
||||
#ifndef DB_VERSION_MAJOR
|
||||
# define DB_VERSION_MAJOR 1
|
||||
#endif
|
||||
#ifndef DB_VERSION_MINOR
|
||||
# define DB_VERSION_MINOR 0
|
||||
#endif
|
||||
#ifndef DB_VERSION_PATCH
|
||||
# define DB_VERSION_PATCH 0
|
||||
#endif
|
||||
|
||||
#define DB_VERSION_FULL ((DB_VERSION_MAJOR<<16)|(DB_VERSION_MINOR<<8)|DB_VERSION_PATCH)
|
||||
|
||||
/* require 4.4 or later, but less than 6.0.20 */
|
||||
#if DB_VERSION_FULL >= 0x040400 && DB_VERSION_FULL < 0x060014
|
||||
__db_version_compat
|
||||
#endif
|
||||
#if DB_VERSION_FULL >= 0x060014
|
||||
#error "BerkeleyDB 6.0.20+ license is incompatible with LDAP"
|
||||
#endif
|
||||
], [ol_cv_bdb_compat=yes], [ol_cv_bdb_compat=no])])
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl ====================================================================
|
||||
|
@ -163,7 +163,6 @@ CLIENT_LIBS = @CLIENT_LIBS@
|
||||
LUTIL_LIBS = @LUTIL_LIBS@
|
||||
LTHREAD_LIBS = @LTHREAD_LIBS@
|
||||
|
||||
BDB_LIBS = @BDB_LIBS@
|
||||
SLAPD_NDB_LIBS = @SLAPD_NDB_LIBS@
|
||||
WT_LIBS = @WT_LIBS@
|
||||
|
||||
|
74
configure.in
74
configure.in
@ -300,9 +300,7 @@ OL_ARG_ENABLE(wrappers,[ --enable-wrappers enable tcp wrapper support], no)
|
||||
|
||||
dnl ----------------------------------------------------------------
|
||||
dnl SLAPD Backend Options
|
||||
Backends="bdb \
|
||||
dnssrv \
|
||||
hdb \
|
||||
Backends="dnssrv \
|
||||
ldap \
|
||||
mdb \
|
||||
meta \
|
||||
@ -323,12 +321,8 @@ SLAPD Backend Options:])
|
||||
|
||||
OL_ARG_ENABLE(backends,[ --enable-backends enable all available backends],
|
||||
--, [no yes mod])dnl
|
||||
OL_ARG_ENABLE(bdb,[ --enable-bdb enable Berkeley DB backend],
|
||||
no, [no yes mod], ol_enable_backends)dnl
|
||||
OL_ARG_ENABLE(dnssrv,[ --enable-dnssrv enable dnssrv backend],
|
||||
no, [no yes mod], ol_enable_backends)dnl
|
||||
OL_ARG_ENABLE(hdb,[ --enable-hdb enable Hierarchical DB backend],
|
||||
no, [no yes mod], ol_enable_backends)dnl
|
||||
OL_ARG_ENABLE(ldap,[ --enable-ldap enable ldap backend],
|
||||
no, [no yes mod], ol_enable_backends)dnl
|
||||
OL_ARG_ENABLE(mdb,[ --enable-mdb enable mdb database backend],
|
||||
@ -498,9 +492,7 @@ if test $ol_enable_slapd = no ; then
|
||||
ol_enable_rewrite=no
|
||||
|
||||
elif test $ol_enable_modules != yes &&
|
||||
test $ol_enable_bdb = no &&
|
||||
test $ol_enable_dnssrv = no &&
|
||||
test $ol_enable_hdb = no &&
|
||||
test $ol_enable_ldap = no &&
|
||||
test $ol_enable_mdb = no &&
|
||||
test $ol_enable_meta = no &&
|
||||
@ -566,7 +558,6 @@ dnl ----------------------------------------------------------------
|
||||
|
||||
dnl Initialize vars
|
||||
LDAP_LIBS=
|
||||
BDB_LIBS=
|
||||
SLAPD_NDB_LIBS=
|
||||
SLAPD_NDB_INCS=
|
||||
LTHREAD_LIBS=
|
||||
@ -583,9 +574,7 @@ BUILD_THREAD=no
|
||||
BUILD_SLAPI=no
|
||||
SLAPD_SLAPI_DEPEND=
|
||||
|
||||
BUILD_BDB=no
|
||||
BUILD_DNSSRV=no
|
||||
BUILD_HDB=no
|
||||
BUILD_LDAP=no
|
||||
BUILD_MDB=no
|
||||
BUILD_META=no
|
||||
@ -1883,36 +1872,6 @@ else
|
||||
ol_cv_func_gethostbyaddr_r_nargs=0
|
||||
fi
|
||||
|
||||
dnl ----------------------------------------------------------------
|
||||
ol_link_bdb=no
|
||||
|
||||
if test $ol_enable_bdb/$ol_enable_hdb != no/no; then
|
||||
OL_BERKELEY_DB
|
||||
|
||||
if test $ol_cv_berkeley_db = no ; then
|
||||
AC_MSG_ERROR(BDB/HDB: BerkeleyDB not available)
|
||||
fi
|
||||
|
||||
AC_DEFINE(HAVE_BERKELEY_DB,1,
|
||||
[define this if Berkeley DB is available])
|
||||
|
||||
dnl $ol_cv_lib_db should be yes or -ldb
|
||||
dnl (it could be no, but that would be an error
|
||||
if test $ol_cv_lib_db != yes ; then
|
||||
BDB_LIBS="$BDB_LIBS $ol_cv_lib_db"
|
||||
fi
|
||||
|
||||
dnl link BDB library to slapd when there is a
|
||||
dnl static BDB based backend in use
|
||||
if test $ol_enable_bdb/$ol_enable_hdb != mod/mod ; then
|
||||
if test $ol_enable_bdb = yes -o $ol_enable_hdb = yes ; then
|
||||
SLAPD_LIBS="$SLAPD_LIBS \$(BDB_LIBS)"
|
||||
fi
|
||||
fi
|
||||
|
||||
ol_link_bdb=yes
|
||||
fi
|
||||
|
||||
dnl ----------------------------------------------------------------
|
||||
|
||||
if test $ol_enable_dynamic = yes && test $enable_shared = yes ; then
|
||||
@ -2667,19 +2626,6 @@ if test "$ol_enable_monitor" != no ; then
|
||||
AC_DEFINE_UNQUOTED(SLAPD_MONITOR,$MFLAG,[define to support cn=Monitor backend])
|
||||
fi
|
||||
|
||||
if test "$ol_enable_bdb" != no ; then
|
||||
BUILD_SLAPD=yes
|
||||
BUILD_BDB=$ol_enable_bdb
|
||||
if test "$ol_enable_bdb" = mod ; then
|
||||
SLAPD_DYNAMIC_BACKENDS="$SLAPD_DYNAMIC_BACKENDS back-bdb"
|
||||
MFLAG=SLAPD_MOD_DYNAMIC
|
||||
else
|
||||
SLAPD_STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS back-bdb"
|
||||
MFLAG=SLAPD_MOD_STATIC
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED(SLAPD_BDB,$MFLAG,[define to support BDB backend])
|
||||
fi
|
||||
|
||||
if test "$ol_enable_dnssrv" != no ; then
|
||||
BUILD_SLAPD=yes
|
||||
BUILD_DNSSRV=$ol_enable_dnssrv
|
||||
@ -2693,19 +2639,6 @@ if test "$ol_enable_dnssrv" != no ; then
|
||||
AC_DEFINE_UNQUOTED(SLAPD_DNSSRV,$MFLAG,[define to support DNS SRV backend])
|
||||
fi
|
||||
|
||||
if test "$ol_enable_hdb" != no ; then
|
||||
BUILD_SLAPD=yes
|
||||
BUILD_HDB=$ol_enable_hdb
|
||||
if test "$ol_enable_hdb" = mod ; then
|
||||
SLAPD_DYNAMIC_BACKENDS="$SLAPD_DYNAMIC_BACKENDS back-hdb"
|
||||
MFLAG=SLAPD_MOD_DYNAMIC
|
||||
else
|
||||
SLAPD_STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS back-hdb"
|
||||
MFLAG=SLAPD_MOD_STATIC
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED(SLAPD_HDB,$MFLAG,[define to support HDB backend])
|
||||
fi
|
||||
|
||||
if test "$ol_enable_ldap" != no ; then
|
||||
BUILD_SLAPD=yes
|
||||
BUILD_LDAP=$ol_enable_ldap
|
||||
@ -3172,9 +3105,7 @@ dnl slapi
|
||||
AC_SUBST(BUILD_SLAPI)
|
||||
AC_SUBST(SLAPD_SLAPI_DEPEND)
|
||||
dnl backends
|
||||
AC_SUBST(BUILD_BDB)
|
||||
AC_SUBST(BUILD_DNSSRV)
|
||||
AC_SUBST(BUILD_HDB)
|
||||
AC_SUBST(BUILD_LDAP)
|
||||
AC_SUBST(BUILD_MDB)
|
||||
AC_SUBST(BUILD_META)
|
||||
@ -3217,7 +3148,6 @@ dnl overlays
|
||||
AC_SUBST(LDAP_LIBS)
|
||||
AC_SUBST(CLIENT_LIBS)
|
||||
AC_SUBST(SLAPD_LIBS)
|
||||
AC_SUBST(BDB_LIBS)
|
||||
AC_SUBST(SLAPD_NDB_LIBS)
|
||||
AC_SUBST(SLAPD_NDB_INCS)
|
||||
AC_SUBST(LTHREAD_LIBS)
|
||||
@ -3286,9 +3216,7 @@ AC_CONFIG_FILES([Makefile:build/top.mk:Makefile.in:build/dir.mk]
|
||||
[libraries/librewrite/Makefile:build/top.mk:libraries/librewrite/Makefile.in:build/lib.mk:build/lib-static.mk]
|
||||
[servers/Makefile:build/top.mk:servers/Makefile.in:build/dir.mk]
|
||||
[servers/slapd/Makefile:build/top.mk:servers/slapd/Makefile.in:build/srv.mk]
|
||||
[servers/slapd/back-bdb/Makefile:build/top.mk:servers/slapd/back-bdb/Makefile.in:build/mod.mk]
|
||||
[servers/slapd/back-dnssrv/Makefile:build/top.mk:servers/slapd/back-dnssrv/Makefile.in:build/mod.mk]
|
||||
[servers/slapd/back-hdb/Makefile:build/top.mk:servers/slapd/back-hdb/Makefile.in:build/mod.mk]
|
||||
[servers/slapd/back-ldap/Makefile:build/top.mk:servers/slapd/back-ldap/Makefile.in:build/mod.mk]
|
||||
[servers/slapd/back-ldif/Makefile:build/top.mk:servers/slapd/back-ldif/Makefile.in:build/mod.mk]
|
||||
[servers/slapd/back-mdb/Makefile:build/top.mk:servers/slapd/back-mdb/Makefile.in:build/mod.mk]
|
||||
|
@ -27,7 +27,7 @@
|
||||
* Caveats:
|
||||
* - right now, the overlay assumes that all values of the objectClass
|
||||
* attribute will be returned in rs->sr_entry; this may not be true
|
||||
* in general, but it usually is for back-bdb/back-hdb. To generalize,
|
||||
* in general, but it usually is for back-mdb. To generalize,
|
||||
* the search request should be analyzed, and if allowedAttributes or
|
||||
* allowedAttributesEffective are requested, add objectClass to the
|
||||
* requested attributes
|
||||
|
@ -21,7 +21,7 @@ To use the overlay, add:
|
||||
moduleload <path to>nssov.so
|
||||
...
|
||||
|
||||
database hdb
|
||||
database mdb
|
||||
...
|
||||
overlay nssov
|
||||
|
||||
@ -65,7 +65,7 @@ See the nss-ldapd/README for the original attribute names used in this code.
|
||||
The overlay also supports dynamic configuration in cn=config. The layout
|
||||
of the config entry is
|
||||
|
||||
dn: olcOverlay={0}nssov,ocDatabase={1}hdb,cn=config
|
||||
dn: olcOverlay={0}nssov,ocDatabase={1}mdb,cn=config
|
||||
objectClass: olcOverlayConfig
|
||||
objectClass: olcNssOvConfig
|
||||
olcOverlay: {0}nssov
|
||||
|
@ -278,7 +278,7 @@ of the config entry is
|
||||
.LP
|
||||
.RS
|
||||
.nf
|
||||
dn: olcOverlay={0}nssov,ocDatabase={1}hdb,cn=config
|
||||
dn: olcOverlay={0}nssov,ocDatabase={1}mdb,cn=config
|
||||
objectClass: olcOverlayConfig
|
||||
objectClass: olcNssOvConfig
|
||||
olcOverlay: {0}nssov
|
||||
|
@ -147,11 +147,6 @@ search over 500 thousand entries per second. The search was on an unindexed
|
||||
attribute using a filter that would not match any entry, forcing slapd to examine
|
||||
every entry in the DB, testing the filter for a match.
|
||||
|
||||
Essentially the slapd entry cache in back-bdb/back-hdb is so efficient the search
|
||||
processing time is almost invisible; the runtime is limited only by the memory
|
||||
bandwidth of the machine. (The search data rate corresponds to about 3.5GB/sec;
|
||||
the memory bandwidth on the machine is only about 4GB/sec due to ECC and register latency.)
|
||||
|
||||
H3: New overlays
|
||||
|
||||
* slapo-constraint (Attribute value constraints)
|
||||
@ -199,21 +194,13 @@ H3: New build options
|
||||
* Support for building against GnuTLS
|
||||
|
||||
|
||||
H2: Obsolete Features Removed From 2.4
|
||||
H2: Obsolete Features Removed From 2.5
|
||||
|
||||
These features were strongly deprecated in 2.3 and removed in 2.4.
|
||||
These features were strongly deprecated in 2.4 and removed in 2.5.
|
||||
|
||||
H3: Slurpd
|
||||
H3: back-bdb and back-hdb
|
||||
|
||||
Please read the {{SECT:Replication}} section as to why this is no longer in
|
||||
OpenLDAP
|
||||
|
||||
H3: back-ldbm
|
||||
|
||||
back-ldbm was both slow and unreliable. Its byzantine indexing code was
|
||||
prone to spontaneous corruption, as were the underlying database libraries
|
||||
that were commonly used (e.g. GDBM or NDBM). back-bdb and back-hdb are
|
||||
superior in every aspect, with simplified indexing to avoid index corruption,
|
||||
fine-grained locking for greater concurrency, hierarchical caching for
|
||||
greater performance, streamlined on-disk format for greater efficiency
|
||||
and portability, and full transaction support for greater reliability.
|
||||
back-bdb and back-hdb were signficantly slower than back-mdb and
|
||||
required significant tuning of multiple parameters to maximize
|
||||
performance. back-mdb requires no tuning and provides all the
|
||||
functionality previously provided via back-bdb and back-hdb.
|
||||
|
@ -636,7 +636,7 @@ values of <n>.
|
||||
|
||||
H3: ldap_*: Internal (implementation specific) error (80) - additional info: entry index delete failed
|
||||
|
||||
This seems to be related with wrong ownership of the BDB's dir (/var/lib/ldap)
|
||||
This seems to be related with wrong ownership of the MDB's dir (/var/lib/ldap)
|
||||
and files. The files must be owned by the user that slapd runs as.
|
||||
|
||||
> chown -R ldap:ldap /var/lib/ldap
|
||||
@ -652,11 +652,3 @@ immediately and client gets an error :
|
||||
> SASL/GSSAPI authentication started ldap_sasl_interactive_bind_s: Can't contact LDAP server (-1)
|
||||
|
||||
Then check the slapd service, it stopped.
|
||||
|
||||
This may come from incompatible of using different versions of BerkeleyDB for
|
||||
installing of SASL and installing of OpenLDAP. The problem arises in case of
|
||||
using multiple version of BerkeleyDB. Solution: - Check which version of
|
||||
BerkeleyDB when install Cyrus SASL.
|
||||
|
||||
Reinstall OpenLDAP with the version of BerkeleyDB above.
|
||||
|
||||
|
@ -102,7 +102,6 @@ NOSYNC
|
||||
env
|
||||
pagedResultsControl
|
||||
dup
|
||||
hdb
|
||||
LDIFv
|
||||
syslog
|
||||
monitorTimestamp
|
||||
@ -886,7 +885,6 @@ proxyAttrSet
|
||||
proxyAttrset
|
||||
mary
|
||||
crlcheck
|
||||
olcBdbConfig
|
||||
kadmin
|
||||
mech
|
||||
slapcat
|
||||
@ -1189,7 +1187,6 @@ moddn
|
||||
calloc
|
||||
LDFLAGS
|
||||
attributeOrValueExists
|
||||
olcHdbConfig
|
||||
bsize
|
||||
auditObject
|
||||
dnssrv
|
||||
@ -1491,7 +1488,6 @@ ghenry
|
||||
odbcinst
|
||||
reqType
|
||||
slapover
|
||||
BerkeleyDB's
|
||||
attributename
|
||||
lwrap
|
||||
reqStart
|
||||
@ -1627,7 +1623,6 @@ DSAIT
|
||||
olcHidden
|
||||
mySNMP
|
||||
metainformation
|
||||
BerkeleyDB
|
||||
ldapuri
|
||||
auditAbandon
|
||||
RANDFILE
|
||||
@ -1661,7 +1656,6 @@ olcPasswordHash
|
||||
ldapc
|
||||
loopback
|
||||
ldapi
|
||||
BDB's
|
||||
GETREALM
|
||||
functionalities
|
||||
noplain
|
||||
@ -1669,7 +1663,6 @@ NOECHOPROMPT
|
||||
AES
|
||||
ldaps
|
||||
notoc
|
||||
bdb
|
||||
LDAPv
|
||||
IPsec
|
||||
olcServerID
|
||||
|
@ -14,38 +14,9 @@ name of the module for a backend is usually of the form:
|
||||
|
||||
> back_<backend name>.la
|
||||
|
||||
So for example, if you need to load the {{hdb}} backend, you would configure
|
||||
So for example, if you need to load the {{mdb}} backend, you would configure
|
||||
|
||||
> moduleload back_hdb.la
|
||||
|
||||
H2: Berkeley DB Backends
|
||||
|
||||
|
||||
H3: Overview
|
||||
|
||||
The {{hdb}} backend to {{slapd}}(8) is a backend for a
|
||||
normal {{slapd}} database. It uses the Oracle Berkeley DB ({{TERM:BDB}})
|
||||
package to store data. It makes extensive use of indexing and caching
|
||||
(see the {{SECT:Tuning}} section) to speed data access.
|
||||
|
||||
{{hdb}} is a variant of the original {{bdb}} backend which was first written for use with BDB.
|
||||
{{hdb}} uses a hierarchical database layout which supports subtree renames.
|
||||
It is otherwise identical to the {{bdb}}
|
||||
behavior, and all the same configuration options apply.
|
||||
|
||||
Note: An {{hdb}} database needs a large {{idlcachesize}} for good search performance,
|
||||
typically three times the {{cachesize}} (entry cache size) or larger.
|
||||
|
||||
Note: The {{hdb}} backend has superseded the {{bdb}} backend, and both will
|
||||
are deprecated in favor of the new {{mdb}} backend. See below.
|
||||
|
||||
H3: back-bdb/back-hdb Configuration
|
||||
|
||||
MORE LATER
|
||||
|
||||
H3: Further Information
|
||||
|
||||
{{slapd-bdb}}(5)
|
||||
> moduleload back_mdb.la
|
||||
|
||||
H2: LDAP
|
||||
|
||||
@ -199,16 +170,16 @@ H3: Overview
|
||||
The {{mdb}} backend to {{slapd}}(8) is the recommended primary backend for a
|
||||
normal {{slapd}} database. It uses OpenLDAP's own
|
||||
Lightning Memory-Mapped Database ({{TERM:LMDB}})
|
||||
library to store data and is intended to replace the Berkeley DB backends.
|
||||
library to store data and replaces the BerkeleyDB backends used in older
|
||||
OpenLDAP releases.
|
||||
|
||||
It supports indexing like the BDB backends, but it uses no caching and requires
|
||||
no tuning to deliver maximum search performance. Like {{hdb}}, it is also
|
||||
fully hierarchical and supports subtree renames in constant time.
|
||||
It supports indexing, it uses no caching, and requires no tuning to deliver
|
||||
maximum search performance. It is fully hierarchical and supports subtree
|
||||
renames in constant time.
|
||||
|
||||
H3: back-mdb Configuration
|
||||
|
||||
Unlike the BDB backends, the {{mdb}} backend can be instantiated with very few
|
||||
configuration lines:
|
||||
The {{mdb}} backend can be instantiated with very few configuration lines:
|
||||
|
||||
> include ./schema/core.schema
|
||||
>
|
||||
@ -490,7 +461,7 @@ distribute information between different sites/applications that use RDBMSes
|
||||
and/or LDAP. Or whatever else...
|
||||
|
||||
It is {{B:NOT}} designed as a general-purpose backend that uses RDBMS instead of
|
||||
BerkeleyDB (as the standard BDB backend does), though it can be used as such with
|
||||
LMDB (as the standard back-mdb backend does), though it can be used as such with
|
||||
several limitations. Please see {{SECT: LDAP vs RDBMS}} for discussion.
|
||||
|
||||
The idea is to use some meta-information to translate LDAP queries to SQL queries,
|
||||
|
@ -118,23 +118,6 @@ OpenLDAP's {{slapd}}(8) {{TERM:MDB}} primary database backend uses the {{TERM:LM
|
||||
software included with the OpenLDAP source. There is no need to download any
|
||||
additional software to have {{MDB}} support.
|
||||
|
||||
OpenLDAP's {{slapd}}(8) {{TERM:BDB}} and {{TERM:HDB}} deprecated database backends
|
||||
require {{ORG[expand]Oracle}}'s Berkeley DB.
|
||||
If not available at configure time, you will not be able to build
|
||||
{{slapd}}(8) with these deprecated database backends.
|
||||
|
||||
Your operating system may provide a supported version of
|
||||
Berkeley DB in the base system or as an optional
|
||||
software component. If not, you'll have to obtain and
|
||||
install it yourself. Berkeley DB is available from
|
||||
{{ORG[expand]Oracle}}'s Berkeley DB download page if required.
|
||||
|
||||
There are several versions available from {{ORG[expand]Oracle}}.
|
||||
Berkeley DB version 6.0.20 and later uses a software license that is
|
||||
incompatible with LDAP technology and should not be used with OpenLDAP.
|
||||
|
||||
Note: Please see {{SECT:Recommended OpenLDAP Software Dependency Versions}} for
|
||||
more information.
|
||||
|
||||
|
||||
H3: Threads
|
||||
|
@ -346,7 +346,7 @@ really have a "directory".
|
||||
|
||||
Existing commercial LDAP server implementations that use a relational database
|
||||
are either from the first kind or the third. I don't know of any implementation
|
||||
that uses a relational database to do inefficiently what BDB does efficiently.
|
||||
that uses a relational database to do inefficiently what LMDB does efficiently.
|
||||
For those who are interested in "third way" (exposing EXISTING data from RDBMS
|
||||
as LDAP tree, having some limitations compared to classic LDAP model, but making
|
||||
it possible to interoperate between LDAP and SQL applications):
|
||||
@ -403,15 +403,9 @@ tags.
|
||||
{{B:Choice of database backends}}: {{slapd}} comes with a variety
|
||||
of different database backends you can choose from. They include
|
||||
{{TERM:MDB}}, a hierarchical high-performance transactional database backend;
|
||||
{{TERM:BDB}}, a high-performance transactional database backend (deprecated);
|
||||
{{TERM:HDB}}, a hierarchical high-performance transactional
|
||||
backend (deprecated); {{SHELL}}, a backend interface to arbitrary shell scripts;
|
||||
{{SHELL}}, a backend interface to arbitrary shell scripts;
|
||||
and PASSWD, a simple backend interface to the {{passwd}}(5) file.
|
||||
The MDB backend utilizes {{TERM:LMDB}}, a high performance replacement
|
||||
for {{ORG[expand]Oracle}}'s Berkeley DB.
|
||||
The BDB and HDB backends utilize {{ORG[expand]Oracle}} Berkeley DB. These
|
||||
backends have been deprecated as LMDB provides significantly higher read
|
||||
and write throughput and data reliability.
|
||||
The MDB backend utilizes {{TERM:LMDB}}.
|
||||
|
||||
{{B:Multiple database instances}}: {{slapd}} can be configured to
|
||||
serve multiple databases at the same time. This means that a single
|
||||
|
@ -20,23 +20,7 @@ The LMDB database can be copied live using the mdb_copy command. If the databas
|
||||
is a sparse file via the use of the "writemap" environment flag, the resulting
|
||||
copy will be the actual size of the database rather than a sparse copy.
|
||||
|
||||
2. Backup the Berkeley database itself and periodically back up the transaction
|
||||
log files:
|
||||
|
||||
Berkeley DB produces transaction logs that can be used to reconstruct
|
||||
changes from a given point in time. For example, if an administrator were willing to only
|
||||
lose one hour's worth of changes, they could take down the server in
|
||||
the middle of the night, copy the Berkeley database files offsite, and bring
|
||||
the server back online. Then, on an hourly basis, they could force a
|
||||
database checkpoint, capture the log files that have been generated in the
|
||||
past hour, and copy them offsite. The accumulated log files, in combination
|
||||
with the previous database backup, could be used with db_recover to
|
||||
reconstruct the database up to the time the last collection of log files was
|
||||
copied offsite. This method affords good protection, with minimal space
|
||||
overhead.
|
||||
|
||||
|
||||
3. Periodically run slapcat and back up the LDIF file:
|
||||
2. Periodically run slapcat and back up the LDIF file:
|
||||
|
||||
Slapcat can be run while slapd is active. However, one runs the risk of an
|
||||
inconsistent database- not from the point of slapd, but from the point of
|
||||
@ -52,71 +36,11 @@ files can be rather large and the accumulation of the day's backups could
|
||||
add up to a substantial amount of space.
|
||||
|
||||
You can use {{slapcat}}(8) to generate an LDIF file for each of your {{slapd}}(8)
|
||||
back-mdb, back-bdb, or back-hdb databases.
|
||||
back-mdb databases.
|
||||
|
||||
> slapcat -f slapd.conf -b "dc=example,dc=com"
|
||||
|
||||
For back-mdb, back-bdb, and back-hdb, this command may be ran while slapd(8) is running.
|
||||
|
||||
H2: Berkeley DB Logs
|
||||
|
||||
Berkeley DB log files grow, and the administrator has to deal with it. The
|
||||
procedure is known as log file archival or log file rotation.
|
||||
|
||||
Note: The actual log file rotation is handled by the Berkeley DB engine.
|
||||
|
||||
Logs of current transactions need to be stored into files so that the database
|
||||
can be recovered in the event of an application crash. Administrators can change
|
||||
the size limit of a single log file (by default 10MB), and have old log files
|
||||
removed automatically, by setting up DB environment (see below). The reason
|
||||
Berkeley DB never deletes any log files by default is that the administrator
|
||||
may wish to backup the log files before removal to make database recovery
|
||||
possible even after a catastrophic failure, such as file system corruption.
|
||||
|
||||
Log file names are {{F:log.XXXXXXXXXX}} (X is a digit). By default the log files
|
||||
are located in the BDB backend directory. The {{F:db_archive}} tool knows what
|
||||
log files are used in current transactions, and what are not. Administrators can
|
||||
move unused log files to a backup media, and delete them. To have them removed
|
||||
automatically, place set_flags {{DB_LOG_AUTOREMOVE}} directive in {{F:DB_CONFIG}}.
|
||||
|
||||
Note: If the log files are removed automatically, recovery after a catastrophic
|
||||
failure is likely to be impossible.
|
||||
|
||||
The files with names {{F:__db.001}}, {{F:__db.002}}, etc are just shared memory
|
||||
regions (or whatever). These ARE NOT 'logs', they must be left alone. Don't be
|
||||
afraid of them, they do not grow like logs do.
|
||||
|
||||
To understand the {{F:db_archive}} interface, the reader should refer to
|
||||
chapter 9 of the Berkeley DB guide. In particular, the following chapters are
|
||||
recommended:
|
||||
|
||||
* Database and log file archival - {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/ref/transapp/archival.html}}
|
||||
* Log file removal - {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/ref/transapp/logfile.html}}
|
||||
* Recovery procedures - {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/ref/transapp/recovery.html}}
|
||||
* Hot failover - {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/ref/transapp/hotfail.html}}
|
||||
* Complete list of Berkeley DB flags - {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/api_c/env_set_flags.html}}
|
||||
|
||||
Advanced installations can use special environment settings to fine-tune some
|
||||
Berkeley DB options (change the log file limit, etc). This can be done by using
|
||||
the {{F:DB_CONFIG}} file. This magic file can be created in BDB backend directory
|
||||
set up by {{slapd.conf}}(5). More information on this file can be found in File
|
||||
naming chapter. Specific directives can be found in C Interface, look for
|
||||
{{DB_ENV->set_XXXX}} calls.
|
||||
|
||||
Note: options set in {{F:DB_CONFIG}} file override options set by OpenLDAP.
|
||||
Use them with extreme caution. Do not use them unless You know what You are doing.
|
||||
|
||||
The advantages of {{F:DB_CONFIG}} usage can be the following:
|
||||
|
||||
* to keep data files and log files on different mediums (i.e. disks) to improve
|
||||
performance and/or reliability;
|
||||
* to fine-tune some specific options (such as shared memory region sizes);
|
||||
* to set the log file limit (please read Log file limits before doing this).
|
||||
|
||||
To figure out the best-practice BDB backup scenario, the reader is highly
|
||||
recommended to read the whole Chapter 9: Berkeley DB Transactional Data Store Applications.
|
||||
This chapter is a set of small pages with examples in C language. Non-programming
|
||||
people can skip these examples without loss of knowledge.
|
||||
For back-mdb this command may be ran while slapd(8) is running.
|
||||
|
||||
|
||||
H2: Checkpointing
|
||||
@ -152,7 +76,7 @@ type are:
|
||||
+{{B: slapcat the current data out}}
|
||||
|
||||
.{{S: }}
|
||||
+{{B: Clear out the current data directory (/usr/local/var/openldap-data/) leaving DB_CONFIG in place}}
|
||||
+{{B: Clear out the current data directory (/usr/local/var/openldap-data/)}}
|
||||
|
||||
.{{S: }}
|
||||
+{{B: Perform the software upgrades}}
|
||||
|
@ -214,12 +214,10 @@ backends, as well as backends loaded by modules. For example:
|
||||
> monitoredInfo: config
|
||||
> monitoredInfo: ldif
|
||||
> monitoredInfo: monitor
|
||||
> monitoredInfo: bdb
|
||||
> monitoredInfo: hdb
|
||||
> monitoredInfo: mdb
|
||||
|
||||
This indicates the {{config}}, {{ldif}}, {{monitor}}, {{bdb}},
|
||||
and {{hdb}} backends are available.
|
||||
This indicates the {{config}}, {{ldif}}, {{monitor}},
|
||||
and {{mdb}} backends are available.
|
||||
|
||||
The {{EX:cn=Backends,cn=Monitor}} object is also a container
|
||||
for available backend objects. Each available backend object
|
||||
@ -243,33 +241,6 @@ contains information about a particular backend. For example:
|
||||
> seeAlso: cn=Database 2,cn=Databases,cn=Monitor
|
||||
>
|
||||
> dn: cn=Backend 3,cn=Backends,cn=Monitor
|
||||
> monitoredInfo: bdb
|
||||
> monitorRuntimeConfig: TRUE
|
||||
> supportedControl: 1.3.6.1.1.12
|
||||
> supportedControl: 2.16.840.1.113730.3.4.2
|
||||
> supportedControl: 1.3.6.1.4.1.4203.666.5.2
|
||||
> supportedControl: 1.2.840.113556.1.4.319
|
||||
> supportedControl: 1.3.6.1.1.13.1
|
||||
> supportedControl: 1.3.6.1.1.13.2
|
||||
> supportedControl: 1.3.6.1.4.1.4203.1.10.1
|
||||
> supportedControl: 1.2.840.113556.1.4.1413
|
||||
> supportedControl: 1.3.6.1.4.1.4203.666.11.7.2
|
||||
> seeAlso: cn=Database 1,cn=Databases,cn=Monitor
|
||||
>
|
||||
> dn: cn=Backend 4,cn=Backends,cn=Monitor
|
||||
> monitoredInfo: hdb
|
||||
> monitorRuntimeConfig: TRUE
|
||||
> supportedControl: 1.3.6.1.1.12
|
||||
> supportedControl: 2.16.840.1.113730.3.4.2
|
||||
> supportedControl: 1.3.6.1.4.1.4203.666.5.2
|
||||
> supportedControl: 1.2.840.113556.1.4.319
|
||||
> supportedControl: 1.3.6.1.1.13.1
|
||||
> supportedControl: 1.3.6.1.1.13.2
|
||||
> supportedControl: 1.3.6.1.4.1.4203.1.10.1
|
||||
> supportedControl: 1.2.840.113556.1.4.1413
|
||||
> supportedControl: 1.3.6.1.4.1.4203.666.11.7.2
|
||||
>
|
||||
> dn: cn=Backend 5,cn=Backends,cn=Monitor
|
||||
> monitoredInfo: mdb
|
||||
> monitorRuntimeConfig: TRUE
|
||||
> supportedControl: 1.3.6.1.1.12
|
||||
|
@ -86,7 +86,7 @@ H3: Access Logging Configuration
|
||||
|
||||
The following is a basic example that implements Access Logging:
|
||||
|
||||
> database bdb
|
||||
> database mdb
|
||||
> suffix dc=example,dc=com
|
||||
> ...
|
||||
> overlay accesslog
|
||||
@ -94,7 +94,7 @@ The following is a basic example that implements Access Logging:
|
||||
> logops writes reads
|
||||
> logold (objectclass=person)
|
||||
>
|
||||
> database bdb
|
||||
> database mdb
|
||||
> suffix cn=log
|
||||
> ...
|
||||
> index reqStart eq
|
||||
@ -103,7 +103,7 @@ The following is a basic example that implements Access Logging:
|
||||
|
||||
The following is an example used for {{SECT:delta-syncrepl replication}}:
|
||||
|
||||
> database hdb
|
||||
> database mdb
|
||||
> suffix cn=accesslog
|
||||
> directory /usr/local/var/openldap-accesslog
|
||||
> rootdn cn=accesslog
|
||||
@ -112,7 +112,7 @@ The following is an example used for {{SECT:delta-syncrepl replication}}:
|
||||
|
||||
Accesslog overlay definitions for the primary db
|
||||
|
||||
> database bdb
|
||||
> database mdb
|
||||
> suffix dc=example,dc=com
|
||||
> ...
|
||||
> overlay accesslog
|
||||
@ -619,7 +619,7 @@ specific database. For example, with the following minimal slapd.conf:
|
||||
>
|
||||
> authz-regexp "gidNumber=0\\\+uidNumber=0,cn=peercred,cn=external,cn=auth"
|
||||
> "cn=Manager,dc=example,dc=com"
|
||||
> database bdb
|
||||
> database mdb
|
||||
> suffix "dc=example,dc=com"
|
||||
> rootdn "cn=Manager,dc=example,dc=com"
|
||||
> rootpw secret
|
||||
@ -738,7 +738,7 @@ H4: Setting cache parameters
|
||||
This directive enables proxy caching and sets general cache
|
||||
parameters. The <DB> parameter specifies which underlying database
|
||||
is to be used to hold cached entries. It should be set to
|
||||
{{EX:bdb}} or {{EX:hdb}}. The <maxentries> parameter specifies the
|
||||
{{EX:mdb}}. The <maxentries> parameter specifies the
|
||||
total number of entries which may be held in the cache. The
|
||||
<nattrsets> parameter specifies the total number of attribute sets
|
||||
(as specified by the {{EX:pcacheAttrset}} directive) that may be
|
||||
@ -777,7 +777,7 @@ at server {{EX:ldap.example.com}}.
|
||||
> rootdn "dc=example,dc=com"
|
||||
> uri ldap://ldap.example.com/
|
||||
> overlay pcache
|
||||
> pcache hdb 100000 1 1000 100
|
||||
> pcache mdb 100000 1 1000 100
|
||||
> pcacheAttrset 0 mail postaladdress telephonenumber
|
||||
> pcacheTemplate (sn=) 0 3600
|
||||
> pcacheTemplate (&(sn=)(givenName=)) 0 3600
|
||||
@ -806,7 +806,7 @@ at server {{EX:ldap.example.com}}.
|
||||
> objectClass: olcOverlayConfig
|
||||
> objectClass: olcPcacheConfig
|
||||
> olcOverlay: {0}pcache
|
||||
> olcPcache: hdb 100000 1 1000 100
|
||||
> olcPcache: mdb 100000 1 1000 100
|
||||
> olcPcacheAttrset: 0 mail postalAddress telephoneNumber
|
||||
> olcPcacheTemplate: "(sn=)" 0 3600 0 0 0
|
||||
> olcPcacheTemplate: "(&(sn=)(givenName=))" 0 3600 0 0 0
|
||||
@ -889,7 +889,7 @@ the ppolicy module being added to the database that handles the naming
|
||||
context "dc=example,dc=com". In this example we are also specifying the DN of
|
||||
a policy object to use if none other is specified in a user's object.
|
||||
|
||||
> database bdb
|
||||
> database mdb
|
||||
> suffix "dc=example,dc=com"
|
||||
> [...additional database configuration directives go here...]
|
||||
>
|
||||
@ -978,7 +978,7 @@ H2: Referential Integrity
|
||||
|
||||
H3: Overview
|
||||
|
||||
This overlay can be used with a backend database such as slapd-bdb(5)
|
||||
This overlay can be used with a backend database such as slapd-mdb(5)
|
||||
to maintain the cohesiveness of a schema which utilizes reference
|
||||
attributes.
|
||||
|
||||
@ -1173,7 +1173,7 @@ H2: Translucent Proxy
|
||||
|
||||
H3: Overview
|
||||
|
||||
This overlay can be used with a backend database such as {{:slapd-bdb}}(5)
|
||||
This overlay can be used with a backend database such as {{:slapd-mdb}}(5)
|
||||
to create a "translucent proxy".
|
||||
|
||||
Entries retrieved from a remote LDAP server may have some or all attributes
|
||||
@ -1212,7 +1212,7 @@ First we configure the overlay in the normal manner:
|
||||
> pidfile ./slapd.pid
|
||||
> argsfile ./slapd.args
|
||||
>
|
||||
> database bdb
|
||||
> database mdb
|
||||
> suffix "dc=suretecsystems,dc=com"
|
||||
> rootdn "cn=trans,dc=suretecsystems,dc=com"
|
||||
> rootpw secret
|
||||
@ -1305,7 +1305,7 @@ H2: Attribute Uniqueness
|
||||
|
||||
H3: Overview
|
||||
|
||||
This overlay can be used with a backend database such as {{slapd-bdb(5)}}
|
||||
This overlay can be used with a backend database such as {{slapd-mdb(5)}}
|
||||
to enforce the uniqueness of some or all attributes within a subtree.
|
||||
|
||||
|
||||
@ -1390,7 +1390,7 @@ Here are a few examples:
|
||||
|
||||
> loglevel sync stats
|
||||
>
|
||||
> database hdb
|
||||
> database mdb
|
||||
> suffix "dc=suretecsystems,dc=com"
|
||||
> directory /usr/local/var/openldap-data
|
||||
>
|
||||
|
@ -225,8 +225,8 @@ in the replication context.
|
||||
|
||||
The syncrepl engine, which is a consumer-side replication engine,
|
||||
can work with any backends. The LDAP Sync provider can be configured
|
||||
as an overlay on any backend, but works best with the {{back-bdb}},
|
||||
{{back-hdb}}, or {{back-mdb}} backends.
|
||||
as an overlay on any backend, but works best with the {{back-mdb}}
|
||||
backend.
|
||||
|
||||
The LDAP Sync provider maintains a {{EX:contextCSN}} for each
|
||||
database as the current synchronization state indicator of the
|
||||
@ -423,9 +423,6 @@ writes have to go to just one of the mirror nodes at a time
|
||||
server (slapd in proxy mode) or device (hardware load balancer)
|
||||
is needed to manage which provider is currently active
|
||||
* Backups are managed slightly differently
|
||||
- If backing up the Berkeley database itself and periodically backing up the
|
||||
transaction log files, then the same member of the mirror pair needs to be
|
||||
used to collect logfiles until the next database backup is taken
|
||||
|
||||
For configuration, please see the {{SECT:MirrorMode}} section below
|
||||
|
||||
@ -674,8 +671,8 @@ replica servers:
|
||||
> # Set the module path location
|
||||
> modulepath /opt/symas/lib/openldap
|
||||
>
|
||||
> # Load the hdb backend
|
||||
> moduleload back_hdb.la
|
||||
> # Load the mdb backend
|
||||
> moduleload back_mdb.la
|
||||
>
|
||||
> # Load the accesslog overlay
|
||||
> moduleload accesslog.la
|
||||
@ -684,7 +681,7 @@ replica servers:
|
||||
> moduleload syncprov.la
|
||||
>
|
||||
> # Accesslog database definitions
|
||||
> database hdb
|
||||
> database mdb
|
||||
> suffix cn=accesslog
|
||||
> directory /db/accesslog
|
||||
> rootdn cn=accesslog
|
||||
@ -699,7 +696,7 @@ replica servers:
|
||||
> limits dn.exact="cn=replicator,dc=symas,dc=com" time.soft=unlimited time.hard=unlimited size.soft=unlimited size.hard=unlimited
|
||||
>
|
||||
> # Primary database definitions
|
||||
> database hdb
|
||||
> database mdb
|
||||
> suffix "dc=symas,dc=com"
|
||||
> rootdn "cn=manager,dc=symas,dc=com"
|
||||
>
|
||||
@ -730,7 +727,7 @@ For more information, always consult the relevant man pages ({{slapo-accesslog}}
|
||||
H4: Delta-syncrepl Consumer configuration
|
||||
|
||||
> # Replica database configuration
|
||||
> database hdb
|
||||
> database mdb
|
||||
> suffix "dc=symas,dc=com"
|
||||
> rootdn "cn=manager,dc=symas,dc=com"
|
||||
>
|
||||
@ -759,10 +756,7 @@ H4: Delta-syncrepl Consumer configuration
|
||||
|
||||
|
||||
The above configuration assumes that you have a replicator identity defined
|
||||
in your database that can be used to bind to the provider. In addition,
|
||||
all of the databases (primary, replica, and the accesslog
|
||||
storage database) should also have properly tuned {{DB_CONFIG}} files that meet
|
||||
your needs.
|
||||
in your database that can be used to bind to the provider.
|
||||
|
||||
Note: An accesslog database is unique to a given master. It should
|
||||
never be replicated.
|
||||
@ -978,7 +972,7 @@ The following example is for a self-contained push-based replication solution:
|
||||
> include /usr/local/etc/openldap/slapd.acl
|
||||
>
|
||||
> modulepath /usr/local/libexec/openldap
|
||||
> moduleload back_hdb.la
|
||||
> moduleload back_mdb.la
|
||||
> moduleload syncprov.la
|
||||
> moduleload back_monitor.la
|
||||
> moduleload back_ldap.la
|
||||
@ -988,7 +982,7 @@ The following example is for a self-contained push-based replication solution:
|
||||
>
|
||||
> loglevel sync stats
|
||||
>
|
||||
> database hdb
|
||||
> database mdb
|
||||
> suffix "dc=suretecsystems,dc=com"
|
||||
> directory /usr/local/var/openldap-data
|
||||
>
|
||||
@ -1064,7 +1058,7 @@ A replica configuration for this type of setup could be:
|
||||
> include /usr/local/etc/openldap/slapd.acl
|
||||
>
|
||||
> modulepath /usr/local/libexec/openldap
|
||||
> moduleload back_hdb.la
|
||||
> moduleload back_mdb.la
|
||||
> moduleload syncprov.la
|
||||
> moduleload back_monitor.la
|
||||
> moduleload back_ldap.la
|
||||
@ -1074,7 +1068,7 @@ A replica configuration for this type of setup could be:
|
||||
>
|
||||
> loglevel sync stats
|
||||
>
|
||||
> database hdb
|
||||
> database mdb
|
||||
> suffix "dc=suretecsystems,dc=com"
|
||||
> directory /usr/local/var/openldap-slave/data
|
||||
>
|
||||
|
@ -69,7 +69,7 @@ used to configure the software.
|
||||
the schema that is hard-coded in slapd).
|
||||
.. Child entries of {{EX:cn=schema,cn=config}} contain user schema as
|
||||
loaded from config files or added at runtime.
|
||||
* Backend-specific configuration
|
||||
* Backend-specific configuration
|
||||
* Database-specific configuration
|
||||
.. Overlays are defined in children of the Database entry.
|
||||
.. Databases and Overlays may also have other miscellaneous children.
|
||||
@ -207,7 +207,7 @@ Level Keyword Description
|
||||
!endblock
|
||||
|
||||
The desired log level can be input as a single integer that
|
||||
combines the (ORed) desired levels, both in decimal or in hexadecimal
|
||||
combines the (ORed) desired levels, both in decimal or in hexadecimal
|
||||
notation, as a list of integers (that are ORed internally), or as a list of the names that are shown between brackets, such that
|
||||
|
||||
> olcLogLevel 129
|
||||
@ -364,10 +364,8 @@ supported backend types listed in Table 5.2.
|
||||
!block table; align=Center; coltags="EX,N"; \
|
||||
title="Table 5.2: Database Backends"
|
||||
Types Description
|
||||
bdb Berkeley DB transactional backend (deprecated)
|
||||
config Slapd configuration backend
|
||||
dnssrv DNS SRV backend
|
||||
hdb Hierarchical variant of bdb backend (deprecated)
|
||||
ldap Lightweight Directory Access Protocol (Proxy) backend
|
||||
ldif Lightweight Data Interchange Format backend
|
||||
mdb Memory-Mapped DB backend
|
||||
@ -381,7 +379,7 @@ sql SQL Programmable backend
|
||||
|
||||
\Example:
|
||||
|
||||
> olcBackend: bdb
|
||||
> olcBackend: mdb
|
||||
|
||||
There are no other directives defined for this entry. Specific backend
|
||||
types may define additional attributes for their particular use but so
|
||||
@ -391,9 +389,9 @@ not appear in any actual configurations.
|
||||
|
||||
H4: Sample Entry
|
||||
|
||||
> dn: olcBackend=bdb,cn=config
|
||||
> dn: olcBackend=mdb,cn=config
|
||||
> objectClass: olcBackendConfig
|
||||
> olcBackend: bdb
|
||||
> olcBackend: mdb
|
||||
|
||||
|
||||
H3: Database-specific Directives
|
||||
@ -421,9 +419,9 @@ databases.
|
||||
|
||||
\Example:
|
||||
|
||||
> olcDatabase: bdb
|
||||
> olcDatabase: mdb
|
||||
|
||||
This marks the beginning of a new {{TERM:BDB}} database instance.
|
||||
This marks the beginning of a new {{TERM:MDB}} database instance.
|
||||
|
||||
|
||||
H4: olcAccess: to <what> [ by <who> [<accesslevel>] [<control>] ]+
|
||||
@ -642,7 +640,7 @@ schema conformance. The default is off.
|
||||
The {{EX:binddn}} parameter gives the DN to bind as for the
|
||||
syncrepl searches to the provider slapd. It should be a DN
|
||||
which has read access to the replication content in the
|
||||
master database.
|
||||
master database.
|
||||
|
||||
The {{EX:bindmethod}} is {{EX:simple}} or {{EX:sasl}},
|
||||
depending on whether simple password-based authentication or
|
||||
@ -683,8 +681,8 @@ conforms to the obsolete {{changelog}} format. If the {{EX:syncdata}}
|
||||
parameter is omitted or set to {{EX:"default"}} then the log
|
||||
parameters are ignored.
|
||||
|
||||
The {{syncrepl}} replication mechanism is supported by the {{bdb}},
|
||||
{{hdb}}, and {{mdb}} backends.
|
||||
The {{syncrepl}} replication mechanism is supported by the {{mdb}}
|
||||
backend.
|
||||
|
||||
See the {{SECT:LDAP Sync Replication}} chapter of this guide for
|
||||
more information on how to use this directive.
|
||||
@ -731,21 +729,20 @@ H4: Sample Entries
|
||||
>olcRootDN: cn=Manager,dc=example,dc=com
|
||||
|
||||
|
||||
H3: BDB and HDB Database Directives
|
||||
H3: MDB Database Directives
|
||||
|
||||
Directives in this category apply to both the {{TERM:BDB}}
|
||||
and the {{TERM:HDB}} database.
|
||||
Directives in this category apply to the {{TERM:MDB}}
|
||||
database backend.
|
||||
They are used in an olcDatabase entry in addition to the generic
|
||||
database directives defined above. For a complete reference
|
||||
of BDB/HDB configuration directives, see {{slapd-bdb}}(5). In
|
||||
addition to the {{EX:olcDatabaseConfig}} objectClass, BDB and HDB
|
||||
database entries must have the {{EX:olcBdbConfig}} and
|
||||
{{EX:olcHdbConfig}} objectClass, respectively.
|
||||
of MDB configuration directives, see {{slapd-mdb}}(5). In
|
||||
addition to the {{EX:olcDatabaseConfig}} objectClass, MDB
|
||||
database entries must have the {{EX:olcMdbConfig}} objectClass.
|
||||
|
||||
|
||||
H4: olcDbDirectory: <directory>
|
||||
|
||||
This directive specifies the directory where the BDB files
|
||||
This directive specifies the directory where the MDB files
|
||||
containing the database and associated indices live.
|
||||
|
||||
\Default:
|
||||
@ -753,98 +750,48 @@ containing the database and associated indices live.
|
||||
> olcDbDirectory: /usr/local/var/openldap-data
|
||||
|
||||
|
||||
H4: olcDbCachesize: <integer>
|
||||
|
||||
This directive specifies the size in entries of the in-memory
|
||||
cache maintained by the BDB backend database instance.
|
||||
|
||||
\Default:
|
||||
|
||||
> olcDbCachesize: 1000
|
||||
|
||||
|
||||
H4: olcDbCheckpoint: <kbyte> <min>
|
||||
|
||||
This directive specifies how often to checkpoint the BDB transaction log.
|
||||
A checkpoint operation flushes the database buffers to disk and writes a
|
||||
checkpoint record in the log.
|
||||
This directive specifies the frequency for flushing the database disk
|
||||
buffers. This directive is only needed if the {{olcDbNoSync}} option is
|
||||
{{EX:TRUE}}.
|
||||
The checkpoint will occur if either <kbyte> data has been written or
|
||||
<min> minutes have passed since the last checkpoint. Both arguments default
|
||||
to zero, in which case they are ignored. When the <min> argument is
|
||||
non-zero, an internal task will run every <min> minutes to perform the
|
||||
checkpoint. See the Berkeley DB reference guide for more details.
|
||||
checkpoint. Note: currently the _kbyte_ setting is unimplemented.
|
||||
|
||||
\Example:
|
||||
|
||||
> olcDbCheckpoint: 1024 10
|
||||
|
||||
|
||||
H4: olcDbConfig: <DB_CONFIG setting>
|
||||
H4: olcDbEnvFlags: {nosync,nometasync,writemap,mapasync,nordahead}
|
||||
|
||||
This attribute specifies a configuration directive to be placed in the
|
||||
{{EX:DB_CONFIG}} file of the database directory. At server startup time, if
|
||||
no such file exists yet, the {{EX:DB_CONFIG}} file will be created and the
|
||||
settings in this attribute will be written to it. If the file exists,
|
||||
its contents will be read and displayed in this attribute. The attribute
|
||||
is multi-valued, to accommodate multiple configuration directives. No default
|
||||
is provided, but it is essential to use proper settings here to get the
|
||||
best server performance.
|
||||
This option specifies flags for finer-grained control of the LMDB library's
|
||||
operation.
|
||||
|
||||
Any changes made to this attribute will be written to the {{EX:DB_CONFIG}}
|
||||
file and will cause the database environment to be reset so the changes
|
||||
can take immediate effect. If the environment cache is large and has not
|
||||
been recently checkpointed, this reset operation may take a long time. It
|
||||
may be advisable to manually perform a single checkpoint using the Berkeley DB
|
||||
{{db_checkpoint}} utility before using LDAP Modify to change this
|
||||
attribute.
|
||||
* {{F:nosync}}: This is exactly the same as the dbnosync directive.
|
||||
|
||||
\Example:
|
||||
* {{F:nometasync}}: Flush the data on a commit, but skip the sync of the meta
|
||||
page. This mode is slightly faster than doing a full sync, but can
|
||||
potentially lose the last committed transaction if the operating system
|
||||
crashes. If both nometasync and nosync are set, the nosync flag takes
|
||||
precedence.
|
||||
|
||||
> olcDbConfig: set_cachesize 0 10485760 0
|
||||
> olcDbConfig: set_lg_bsize 2097512
|
||||
> olcDbConfig: set_lg_dir /var/tmp/bdb-log
|
||||
> olcDbConfig: set_flags DB_LOG_AUTOREMOVE
|
||||
* {{F:writemap}}: Use a writable memory map instead of just read-only. This
|
||||
speeds up write operations but makes the database vulnerable to corruption in
|
||||
case any bugs in slapd cause stray writes into the mmap region.
|
||||
|
||||
In this example, the BDB cache is set to 10MB, the BDB transaction log
|
||||
buffer size is set to 2MB, and the transaction log files are to be stored
|
||||
in the /var/tmp/bdb-log directory. Also a flag is set to tell BDB to
|
||||
delete transaction log files as soon as their contents have been
|
||||
checkpointed and they are no longer needed. Without this setting the
|
||||
transaction log files will continue to accumulate until some other
|
||||
cleanup procedure removes them. See the Berkeley DB documentation for the
|
||||
{{EX:db_archive}} command for details. For a complete list of Berkeley DB
|
||||
flags please see - {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/api_c/env_set_flags.html}}
|
||||
* {{F:mapasync}}: When using a writable memory map and performing flushes on
|
||||
each commit, use an asynchronous flush instead of a synchronous flush (the
|
||||
default). This option has no effect if writemap has not been set. It also has
|
||||
no effect if nosync is set.
|
||||
|
||||
Ideally the BDB cache must be
|
||||
at least as large as the working set of the database, the log buffer size
|
||||
should be large enough to accommodate most transactions without overflowing,
|
||||
and the log directory must be on a separate physical disk from the main
|
||||
database files. And both the database directory and the log directory
|
||||
should be separate from disks used for regular system activities such as
|
||||
the root, boot, or swap filesystems. See the FAQ-o-Matic and the Berkeley DB
|
||||
documentation for more details.
|
||||
|
||||
|
||||
H4: olcDbNosync: { TRUE | FALSE }
|
||||
|
||||
This option causes on-disk database contents to not be immediately
|
||||
synchronized with in memory changes upon change. Setting this option
|
||||
to {{EX:TRUE}} may improve performance at the expense of data integrity. This
|
||||
directive has the same effect as using
|
||||
> olcDbConfig: set_flags DB_TXN_NOSYNC
|
||||
|
||||
|
||||
H4: olcDbIDLcacheSize: <integer>
|
||||
|
||||
Specify the size of the in-memory index cache, in index slots. The
|
||||
default is zero. A larger value will speed up frequent searches of
|
||||
indexed entries. The optimal size will depend on the data and search
|
||||
characteristics of the database, but using a number three times
|
||||
the entry cache size is a good starting point.
|
||||
|
||||
\Example:
|
||||
|
||||
> olcDbIDLcacheSize: 3000
|
||||
* {{F:nordahead}}: Turn off file readahead. Usually the OS performs readahead
|
||||
on every read request. This usually boosts read performance but can be
|
||||
harmful to random access read performance if the system's memory is full and
|
||||
the DB is larger than RAM. This option is not implemented on Windows.
|
||||
|
||||
|
||||
H4: olcDbIndex: {<attrlist> | default} [pres,eq,approx,sub,none]
|
||||
@ -874,7 +821,7 @@ matches do not use an index. However, some attributes do support
|
||||
indexing for inequality matches, based on the equality index.
|
||||
|
||||
A substring index can be more explicitly specified as {{EX:subinitial}},
|
||||
{{EX:subany}}, or {{EX:subfinal}}, corresponding to the three
|
||||
{{EX:subany}}, or {{EX:subfinal}}, corresponding to the three
|
||||
possible components
|
||||
of a substring match filter. A subinitial index only indexes
|
||||
substrings that appear at the beginning of an attribute value.
|
||||
@ -890,7 +837,7 @@ attribute that inherits from {{EX:name}} to be indexed.
|
||||
By default, no indices are maintained. It is generally advised
|
||||
that minimally an equality index upon objectClass be maintained.
|
||||
|
||||
> olcDbindex: objectClass eq
|
||||
> olcDbIndex: objectClass eq
|
||||
|
||||
Additional indices should be configured corresponding to the
|
||||
most common searches that are used on the database.
|
||||
@ -907,18 +854,24 @@ stopped before the index task completes, indexing will have to be
|
||||
manually completed using the slapindex tool.
|
||||
|
||||
|
||||
H4: olcDbLinearIndex: { TRUE | FALSE }
|
||||
H4: olcDbMaxReaders: <integer>
|
||||
|
||||
If this setting is {{EX:TRUE}} slapindex will index one attribute
|
||||
at a time. The default settings is {{EX:FALSE}} in which case all
|
||||
indexed attributes of an entry are processed at the same time. When
|
||||
enabled, each indexed attribute is processed individually, using
|
||||
multiple passes through the entire database. This option improves
|
||||
slapindex performance when the database size exceeds the BDB cache
|
||||
size. When the BDB cache is large enough, this option is not needed
|
||||
and will decrease performance. Also by default, slapadd performs
|
||||
full indexing and so a separate slapindex run is not needed. With
|
||||
this option, slapadd does no indexing and slapindex must be used.
|
||||
This directive specifies the maximum number of threads that may have
|
||||
concurrent read access to the database. Tools such as slapcat count as a
|
||||
single thread, in addition to threads in any active slapd processes. The
|
||||
default is 126.
|
||||
|
||||
|
||||
H4: olcDbMaxSize: <bytes>
|
||||
|
||||
This directive specifies the maximum size of the database in bytes. A memory
|
||||
map of this size is allocated at startup time and the database will not be
|
||||
allowed to grow beyond this size. The default is 10485760 bytes (10MB). This
|
||||
setting may be changed upward if the configured limit needs to be increased.
|
||||
|
||||
Note: It is important to set this to as large a value as possible, (relative
|
||||
to anticipated growth of the actual data over time) since growing the size
|
||||
later may not be practical when the system is under heavy load.
|
||||
|
||||
|
||||
H4: olcDbMode: { <octal> | <symbolic> }
|
||||
@ -932,6 +885,18 @@ created database index files should have. This can be in the form
|
||||
> olcDbMode: 0600
|
||||
|
||||
|
||||
H4: olcDbRtxnsize: <entries>
|
||||
|
||||
This directive specifies the maximum number of entries to process in a single
|
||||
read transaction when executing a large search. Long-lived read transactions
|
||||
prevent old database pages from being reused in write transactions, and so
|
||||
can cause significant growth of the database file when there is heavy write
|
||||
traffic. This setting causes the read transaction in large searches to be
|
||||
released and reacquired after the given number of entries has been read, to
|
||||
give writers the opportunity to reclaim old database pages. The default is
|
||||
10000.
|
||||
|
||||
|
||||
H4: olcDbSearchStack: <integer>
|
||||
|
||||
Specify the depth of the stack used for search filter evaluation.
|
||||
@ -955,33 +920,21 @@ to take effect.
|
||||
> olcDbSearchStack: 16
|
||||
|
||||
|
||||
H4: olcDbShmKey: <integer>
|
||||
H4: olcDbNosync: { TRUE | FALSE }
|
||||
|
||||
Specify a key for a shared memory BDB environment. By default the BDB
|
||||
environment uses memory mapped files. If a non-zero value is specified,
|
||||
it will be used as the key to identify a shared memory region that will
|
||||
house the environment.
|
||||
|
||||
\Example:
|
||||
|
||||
> olcDbShmKey: 42
|
||||
This directive causes on-disk database contents to not be immediately
|
||||
synchronized with in memory changes upon change. Setting this option
|
||||
to {{EX:TRUE}} may improve performance at the expense of data integrity.
|
||||
|
||||
|
||||
H4: Sample Entry
|
||||
|
||||
>dn: olcDatabase=hdb,cn=config
|
||||
>dn: olcDatabase=mdb,cn=config
|
||||
>objectClass: olcDatabaseConfig
|
||||
>objectClass: olcHdbConfig
|
||||
>olcDatabase: hdb
|
||||
>objectClass: olcMdbConfig
|
||||
>olcDatabase: mdb
|
||||
>olcSuffix: "dc=example,dc=com"
|
||||
>olcDbDirectory: /usr/local/var/openldap-data
|
||||
>olcDbCacheSize: 1000
|
||||
>olcDbCheckpoint: 1024 10
|
||||
>olcDbConfig: set_cachesize 0 10485760 0
|
||||
>olcDbConfig: set_lg_bsize 2097152
|
||||
>olcDbConfig: set_lg_dir /var/tmp/bdb-log
|
||||
>olcDbConfig: set_flags DB_LOG_AUTOREMOVE
|
||||
>olcDbIDLcacheSize: 3000
|
||||
>olcDbIndex: objectClass eq
|
||||
|
||||
|
||||
@ -989,7 +942,7 @@ H2: Configuration Example
|
||||
|
||||
The following is an example configuration, interspersed
|
||||
with explanatory text. It defines two databases to handle
|
||||
different parts of the {{TERM:X.500}} tree; both are {{TERM:BDB}}
|
||||
different parts of the {{TERM:X.500}} tree; both are {{TERM:MDB}}
|
||||
database instances. The line numbers shown are provided for
|
||||
reference only and are not included in the actual file. First, the
|
||||
global configuration section:
|
||||
@ -999,7 +952,7 @@ E: 2. dn: cn=config
|
||||
E: 3. objectClass: olcGlobal
|
||||
E: 4. cn: config
|
||||
E: 5. olcReferral: ldap://root.openldap.org
|
||||
E: 6.
|
||||
E: 6.
|
||||
|
||||
Line 1 is a comment. Lines 2-4 identify this as the global
|
||||
configuration entry.
|
||||
@ -1013,7 +966,7 @@ E: 7. # internal schema
|
||||
E: 8. dn: cn=schema,cn=config
|
||||
E: 9. objectClass: olcSchemaConfig
|
||||
E: 10. cn: schema
|
||||
E: 11.
|
||||
E: 11.
|
||||
|
||||
Line 7 is a comment. Lines 8-10 identify this as the root of
|
||||
the schema subtree. The actual schema definitions in this entry
|
||||
@ -1022,7 +975,7 @@ Line 11 is a blank line, indicating the end of this entry.
|
||||
|
||||
E: 12. # include the core schema
|
||||
E: 13. include: file:///usr/local/etc/openldap/schema/core.ldif
|
||||
E: 14.
|
||||
E: 14.
|
||||
|
||||
Line 12 is a comment. Line 13 is an LDIF include directive which
|
||||
accesses the {{core}} schema definitions in LDIF format. Line 14
|
||||
@ -1037,7 +990,7 @@ E: 16. dn: olcDatabase=frontend,cn=config
|
||||
E: 17. objectClass: olcDatabaseConfig
|
||||
E: 18. olcDatabase: frontend
|
||||
E: 19. olcAccess: to * by * read
|
||||
E: 20.
|
||||
E: 20.
|
||||
|
||||
Line 15 is a comment. Lines 16-18 identify this entry as the global
|
||||
database entry. Line 19 is a global access control. It applies to all
|
||||
@ -1066,16 +1019,16 @@ inaccessible.)
|
||||
|
||||
Line 28 is a blank line.
|
||||
|
||||
The next entry defines a BDB backend that will handle queries for things
|
||||
The next entry defines an MDB backend that will handle queries for things
|
||||
in the "dc=example,dc=com" portion of the tree. Indices are to be maintained
|
||||
for several attributes, and the {{EX:userPassword}} attribute is to be
|
||||
protected from unauthorized access.
|
||||
|
||||
E: 29. # BDB definition for example.com
|
||||
E: 30. dn: olcDatabase=bdb,cn=config
|
||||
E: 29. # MDB definition for example.com
|
||||
E: 30. dn: olcDatabase=mdb,cn=config
|
||||
E: 31. objectClass: olcDatabaseConfig
|
||||
E: 32. objectClass: olcBdbConfig
|
||||
E: 33. olcDatabase: bdb
|
||||
E: 32. objectClass: olcMdbConfig
|
||||
E: 33. olcDatabase: mdb
|
||||
E: 34. olcSuffix: dc=example,dc=com
|
||||
E: 35. olcDbDirectory: /usr/local/var/openldap-data
|
||||
E: 36. olcRootDN: cn=Manager,dc=example,dc=com
|
||||
@ -1092,9 +1045,9 @@ E: 46. olcAccess: to *
|
||||
E: 47. by self write
|
||||
E: 48. by dn.base="cn=Admin,dc=example,dc=com" write
|
||||
E: 49. by * read
|
||||
E: 50.
|
||||
E: 50.
|
||||
|
||||
Line 29 is a comment. Lines 30-33 identify this entry as a BDB database
|
||||
Line 29 is a comment. Lines 30-33 identify this entry as a MDB database
|
||||
configuration entry. Line 34 specifies the DN suffix
|
||||
for queries to pass to this database. Line 35 specifies the directory
|
||||
in which the database files will live.
|
||||
@ -1116,16 +1069,16 @@ entry, but may be read by all users (authenticated or not).
|
||||
Line 50 is a blank line, indicating the end of this entry.
|
||||
|
||||
The next entry defines another
|
||||
BDB database. This one handles queries involving the
|
||||
MDB database. This one handles queries involving the
|
||||
{{EX:dc=example,dc=net}} subtree but is managed by the same entity
|
||||
as the first database. Note that without line 60, the read access
|
||||
would be allowed due to the global access rule at line 19.
|
||||
|
||||
E: 51. # BDB definition for example.net
|
||||
E: 52. dn: olcDatabase=bdb,cn=config
|
||||
E: 51. # MDB definition for example.net
|
||||
E: 52. dn: olcDatabase=mdb,cn=config
|
||||
E: 53. objectClass: olcDatabaseConfig
|
||||
E: 54. objectClass: olcBdbConfig
|
||||
E: 55. olcDatabase: bdb
|
||||
E: 54. objectClass: olcMdbConfig
|
||||
E: 55. olcDatabase: mdb
|
||||
E: 56. olcSuffix: "dc=example,dc=net"
|
||||
E: 57. olcDbDirectory: /usr/local/var/openldap-data-net
|
||||
E: 58. olcRootDN: "cn=Manager,dc=example,dc=com"
|
||||
|
@ -90,7 +90,7 @@ H4: access to <what> [ by <who> [<accesslevel>] [<control>] ]+
|
||||
|
||||
This directive grants access (specified by <accesslevel>) to a set
|
||||
of entries and/or attributes (specified by <what>) by one or more
|
||||
requestors (specified by <who>). See the {{SECT:Access Control}} section of
|
||||
requestors (specified by <who>). See the {{SECT:Access Control}} section of
|
||||
this guide for basic usage.
|
||||
|
||||
!if 0
|
||||
@ -162,7 +162,7 @@ Level Keyword Description
|
||||
!endblock
|
||||
|
||||
The desired log level can be input as a single integer that
|
||||
combines the (ORed) desired levels, both in decimal or in hexadecimal
|
||||
combines the (ORed) desired levels, both in decimal or in hexadecimal
|
||||
notation, as a list of integers (that are ORed internally), or as a list of the names that are shown between brackets, such that
|
||||
|
||||
> loglevel 129
|
||||
@ -264,9 +264,7 @@ supported backend types listed in Table 6.2.
|
||||
!block table; align=Center; coltags="EX,N"; \
|
||||
title="Table 6.2: Database Backends"
|
||||
Types Description
|
||||
bdb Berkeley DB transactional backend (deprecated)
|
||||
dnssrv DNS SRV backend
|
||||
hdb Hierarchical variant of bdb backend (deprecated)
|
||||
ldap Lightweight Directory Access Protocol (Proxy) backend
|
||||
mdb Memory-Mapped DB backend
|
||||
meta Meta Directory backend
|
||||
@ -279,9 +277,9 @@ sql SQL Programmable backend
|
||||
|
||||
\Example:
|
||||
|
||||
> backend bdb
|
||||
> backend mdb
|
||||
|
||||
This marks the beginning of a new {{TERM:BDB}} backend
|
||||
This marks the beginning of a new {{TERM:MDB}} backend
|
||||
definition.
|
||||
|
||||
|
||||
@ -299,9 +297,9 @@ supported backend types listed in Table 6.2.
|
||||
|
||||
\Example:
|
||||
|
||||
> database bdb
|
||||
> database mdb
|
||||
|
||||
This marks the beginning of a new {{TERM:BDB}} database instance
|
||||
This marks the beginning of a new {{TERM:MDB}} database instance
|
||||
declaration.
|
||||
|
||||
|
||||
@ -507,7 +505,7 @@ defaults for these parameters come from {{ldap.conf}}(5).
|
||||
The {{EX:binddn}} parameter gives the DN to bind as for the
|
||||
syncrepl searches to the provider slapd. It should be a DN
|
||||
which has read access to the replication content in the
|
||||
master database.
|
||||
master database.
|
||||
|
||||
The {{EX:bindmethod}} is {{EX:simple}} or {{EX:sasl}},
|
||||
depending on whether simple password-based authentication or
|
||||
@ -564,8 +562,7 @@ conforms to the obsolete {{changelog}} format. If the {{EX:syncdata}}
|
||||
parameter is omitted or set to {{EX:"default"}} then the log
|
||||
parameters are ignored.
|
||||
|
||||
The {{syncrepl}} replication mechanism is supported by the {{bdb}},
|
||||
{{hdb}}, and {{mdb}} backends.
|
||||
The {{syncrepl}} replication mechanism is supported by the {{mdb}} backend.
|
||||
|
||||
See the {{SECT:LDAP Sync Replication}} chapter of this guide for
|
||||
more information on how to use this directive.
|
||||
@ -584,31 +581,207 @@ If specified multiple times, each {{TERM:URL}} is provided.
|
||||
> updateref ldap://master.example.net
|
||||
|
||||
|
||||
H3: BDB and HDB Database Directives
|
||||
H3: MDB Database Directives
|
||||
|
||||
Directives in this category only apply to both the {{TERM:BDB}}
|
||||
and the {{TERM:HDB}} database.
|
||||
That is, they must follow a "database bdb" or "database hdb" line
|
||||
and come before any
|
||||
subsequent "backend" or "database" line. For a complete reference
|
||||
of BDB/HDB configuration directives, see {{slapd-bdb}}(5).
|
||||
Directives in this category only apply to the {{TERM:MDB}}
|
||||
database backend.
|
||||
That is, they must follow a "database mdb" line
|
||||
and come before any subsequent "backend" or "database" lines.
|
||||
For a complete reference of MDB configuration directives, see {{slapd-mdb}}(5).
|
||||
|
||||
|
||||
H4: directory <directory>
|
||||
|
||||
This directive specifies the directory where the BDB files
|
||||
This directive specifies the directory where the MDB files
|
||||
containing the database and associated indices live.
|
||||
|
||||
\Default:
|
||||
|
||||
> directory /usr/local/var/openldap-data
|
||||
|
||||
H4: checkpoint <kbyte> <min>
|
||||
|
||||
This directive specifies the frequency for flushing the database disk
|
||||
buffers. This directive is only needed if the {{dbnosync}} option is
|
||||
{{EX:TRUE}}.
|
||||
The checkpoint will occur if either <kbyte> data has been written or
|
||||
<min> minutes have passed since the last checkpoint. Both arguments default
|
||||
to zero, in which case they are ignored. When the <min> argument is
|
||||
non-zero, an internal task will run every <min> minutes to perform the
|
||||
checkpoint. Note: currently the _kbyte_ setting is unimplemented.
|
||||
|
||||
\Example:
|
||||
|
||||
> checkpoint: 1024 10
|
||||
|
||||
H4: dbnosync: { TRUE | FALSE }
|
||||
|
||||
This directive causes on-disk database contents to not be immediately
|
||||
synchronized with in memory changes upon change. Setting this option
|
||||
to {{EX:TRUE}} may improve performance at the expense of data integrity.
|
||||
|
||||
|
||||
H4: envflags: {nosync,nometasync,writemap,mapasync,nordahead}
|
||||
|
||||
This option specifies flags for finer-grained control of the LMDB library's
|
||||
operation.
|
||||
|
||||
* {{F:nosync}}: This is exactly the same as the dbnosync directive.
|
||||
|
||||
* {{F:nometasync}}: Flush the data on a commit, but skip the sync of the meta
|
||||
page. This mode is slightly faster than doing a full sync, but can
|
||||
potentially lose the last committed transaction if the operating system
|
||||
crashes. If both nometasync and nosync are set, the nosync flag takes
|
||||
precedence.
|
||||
|
||||
* {{F:writemap}}: Use a writable memory map instead of just read-only. This
|
||||
speeds up write operations but makes the database vulnerable to corruption in
|
||||
case any bugs in slapd cause stray writes into the mmap region.
|
||||
|
||||
* {{F:mapasync}}: When using a writable memory map and performing flushes on
|
||||
each commit, use an asynchronous flush instead of a synchronous flush (the
|
||||
default). This option has no effect if writemap has not been set. It also has
|
||||
no effect if nosync is set.
|
||||
|
||||
* {{F:nordahead}}: Turn off file readahead. Usually the OS performs readahead
|
||||
on every read request. This usually boosts read performance but can be
|
||||
harmful to random access read performance if the system's memory is full and
|
||||
the DB is larger than RAM. This option is not implemented on Windows.
|
||||
|
||||
|
||||
H4: index: {<attrlist> | default} [pres,eq,approx,sub,none]
|
||||
|
||||
This directive specifies the indices to maintain for the given
|
||||
attribute. If only an {{EX:<attrlist>}} is given, the default
|
||||
indices are maintained. The index keywords correspond to the
|
||||
common types of matches that may be used in an LDAP search filter.
|
||||
|
||||
\Example:
|
||||
|
||||
> index: default pres,eq
|
||||
> index: uid
|
||||
> index: cn,sn pres,eq,sub
|
||||
> index: objectClass eq
|
||||
|
||||
The first line sets the default set of indices to maintain to
|
||||
present and equality. The second line causes the default (pres,eq)
|
||||
set of indices to be maintained for the {{EX:uid}} attribute type.
|
||||
The third line causes present, equality, and substring indices to
|
||||
be maintained for {{EX:cn}} and {{EX:sn}} attribute types. The
|
||||
fourth line causes an equality index for the {{EX:objectClass}}
|
||||
attribute type.
|
||||
|
||||
There is no index keyword for inequality matches. Generally these
|
||||
matches do not use an index. However, some attributes do support
|
||||
indexing for inequality matches, based on the equality index.
|
||||
|
||||
A substring index can be more explicitly specified as {{EX:subinitial}},
|
||||
{{EX:subany}}, or {{EX:subfinal}}, corresponding to the three
|
||||
possible components
|
||||
of a substring match filter. A subinitial index only indexes
|
||||
substrings that appear at the beginning of an attribute value.
|
||||
A subfinal index only indexes substrings that appear at the end
|
||||
of an attribute value, while subany indexes substrings that occur
|
||||
anywhere in a value.
|
||||
|
||||
Note that by default, setting an index for an attribute also
|
||||
affects every subtype of that attribute. E.g., setting an equality
|
||||
index on the {{EX:name}} attribute causes {{EX:cn}}, {{EX:sn}}, and every other
|
||||
attribute that inherits from {{EX:name}} to be indexed.
|
||||
|
||||
By default, no indices are maintained. It is generally advised
|
||||
that minimally an equality index upon objectClass be maintained.
|
||||
|
||||
> index: objectClass eq
|
||||
|
||||
Additional indices should be configured corresponding to the
|
||||
most common searches that are used on the database.
|
||||
Presence indexing should not be configured for an attribute
|
||||
unless the attribute occurs very rarely in the database, and
|
||||
presence searches on the attribute occur very frequently during
|
||||
normal use of the directory. Most applications don't use presence
|
||||
searches, so usually presence indexing is not very useful.
|
||||
|
||||
|
||||
H4: maxreaders: <integer>
|
||||
|
||||
This directive specifies the maximum number of threads that may have
|
||||
concurrent read access to the database. Tools such as slapcat count as a
|
||||
single thread, in addition to threads in any active slapd processes. The
|
||||
default is 126.
|
||||
|
||||
|
||||
H4: maxsize: <bytes>
|
||||
|
||||
This directive specifies the maximum size of the database in bytes. A memory
|
||||
map of this size is allocated at startup time and the database will not be
|
||||
allowed to grow beyond this size. The default is 10485760 bytes (10MB). This
|
||||
setting may be changed upward if the configured limit needs to be increased.
|
||||
|
||||
Note: It is important to set this to as large a value as possible, (relative
|
||||
to anticipated growth of the actual data over time) since growing the size
|
||||
later may not be practical when the system is under heavy load.
|
||||
|
||||
|
||||
H4: mode: { <octal> | <symbolic> }
|
||||
|
||||
This directive specifies the file protection mode that newly
|
||||
created database index files should have. This can be in the form
|
||||
{{EX:0600}} or {{EX:-rw-------}}
|
||||
|
||||
\Default:
|
||||
|
||||
> mode: 0600
|
||||
|
||||
|
||||
H4: rtxnsize: <entries>
|
||||
|
||||
This directive specifies the maximum number of entries to process in a single
|
||||
read transaction when executing a large search. Long-lived read transactions
|
||||
prevent old database pages from being reused in write transactions, and so
|
||||
can cause significant growth of the database file when there is heavy write
|
||||
traffic. This setting causes the read transaction in large searches to be
|
||||
released and reacquired after the given number of entries has been read, to
|
||||
give writers the opportunity to reclaim old database pages. The default is
|
||||
10000.
|
||||
|
||||
|
||||
H4: searchstack: <integer>
|
||||
|
||||
Specify the depth of the stack used for search filter evaluation.
|
||||
Search filters are evaluated on a stack to accommodate nested {{EX:AND}} /
|
||||
{{EX:OR}} clauses. An individual stack is allocated for each server thread.
|
||||
The depth of the stack determines how complex a filter can be evaluated
|
||||
without requiring any additional memory allocation. Filters that are
|
||||
nested deeper than the search stack depth will cause a separate stack to
|
||||
be allocated for that particular search operation. These separate allocations
|
||||
can have a major negative impact on server performance, but specifying
|
||||
too much stack will also consume a great deal of memory. Each search
|
||||
uses 512K bytes per level on a 32-bit machine, or 1024K bytes per level
|
||||
on a 64-bit machine. The default stack depth is 16, thus 8MB or 16MB
|
||||
per thread is used on 32 and 64 bit machines, respectively. Also the
|
||||
512KB size of a single stack slot is set by a compile-time constant which
|
||||
may be changed if needed; the code must be recompiled for the change
|
||||
to take effect.
|
||||
|
||||
\Default:
|
||||
|
||||
> searchstack: 16
|
||||
|
||||
|
||||
H4: Sample Entry
|
||||
|
||||
>database mdb
|
||||
>suffix: "dc=example,dc=com"
|
||||
>directory: /usr/local/var/openldap-data
|
||||
>index: objectClass eq
|
||||
|
||||
|
||||
H2: Configuration File Example
|
||||
|
||||
The following is an example configuration file, interspersed
|
||||
with explanatory text. It defines two databases to handle
|
||||
different parts of the {{TERM:X.500}} tree; both are {{TERM:BDB}}
|
||||
different parts of the {{TERM:X.500}} tree; both are {{TERM:MDB}}
|
||||
database instances. The line numbers shown are provided for
|
||||
reference only and are not included in the actual file. First, the
|
||||
global configuration section:
|
||||
@ -617,7 +790,7 @@ E: 1. # example config file - global configuration section
|
||||
E: 2. include /usr/local/etc/schema/core.schema
|
||||
E: 3. referral ldap://root.openldap.org
|
||||
E: 4. access to * by * read
|
||||
|
||||
|
||||
Line 1 is a comment. Line 2 includes another config file
|
||||
which contains {{core}} schema definitions.
|
||||
The {{EX:referral}} directive on line 3
|
||||
@ -629,7 +802,7 @@ Line 4 is a global access control. It applies to all
|
||||
entries (after any applicable database-specific access
|
||||
controls).
|
||||
|
||||
The next section of the configuration file defines a BDB
|
||||
The next section of the configuration file defines a MDB
|
||||
backend that will handle queries for things in the
|
||||
"dc=example,dc=com" portion of the tree. The
|
||||
database is to be replicated to two slave slapds, one on
|
||||
@ -637,8 +810,8 @@ truelies, the other on judgmentday. Indices are to be
|
||||
maintained for several attributes, and the {{EX:userPassword}}
|
||||
attribute is to be protected from unauthorized access.
|
||||
|
||||
E: 5. # BDB definition for the example.com
|
||||
E: 6. database bdb
|
||||
E: 5. # MDB definition for the example.com
|
||||
E: 6. database mdb
|
||||
E: 7. suffix "dc=example,dc=com"
|
||||
E: 8. directory /usr/local/var/openldap-data
|
||||
E: 9. rootdn "cn=Manager,dc=example,dc=com"
|
||||
@ -678,13 +851,13 @@ All other attributes are writable by the entry and the "admin"
|
||||
entry, but may be read by all users (authenticated or not).
|
||||
|
||||
The next section of the example configuration file defines another
|
||||
BDB database. This one handles queries involving the
|
||||
MDB database. This one handles queries involving the
|
||||
{{EX:dc=example,dc=net}} subtree but is managed by the same entity
|
||||
as the first database. Note that without line 39, the read access
|
||||
would be allowed due to the global access rule at line 4.
|
||||
|
||||
E: 33. # BDB definition for example.net
|
||||
E: 34. database bdb
|
||||
E: 33. # MDB definition for example.net
|
||||
E: 34. database mdb
|
||||
E: 35. suffix "dc=example,dc=net"
|
||||
E: 36. directory /usr/local/var/openldap-data-net
|
||||
E: 37. rootdn "cn=Manager,dc=example,dc=com"
|
||||
|
@ -27,10 +27,6 @@ H3: Memory
|
||||
|
||||
Scale your cache to use available memory and increase system memory if you can.
|
||||
|
||||
See {{SECT:Caching}} for BDB cache tuning hints.
|
||||
Note that LMDB uses no cache of its own and has no tuning options, so the Caching
|
||||
section can be ignored when using LMDB.
|
||||
|
||||
|
||||
H3: Disks
|
||||
|
||||
@ -39,15 +35,7 @@ types perform best with your workload. (On our own Linux testing, EXT2 and JFS
|
||||
tend to provide better write performance than everything else, including
|
||||
newer filesystems like EXT4, BTRFS, etc.)
|
||||
|
||||
Use fast subsystems. Put each database and logs on separate disks
|
||||
(for BDB this is configurable via {{DB_CONFIG}}):
|
||||
|
||||
> # Data Directory
|
||||
> set_data_dir /data/db
|
||||
>
|
||||
> # Transaction Log settings
|
||||
> set_lg_dir /logs
|
||||
|
||||
Use fast subsystems. Put each database on separate disks.
|
||||
|
||||
H3: Network Topology
|
||||
|
||||
@ -131,7 +119,7 @@ H3: What to watch out for
|
||||
|
||||
The most common message you'll see that you should pay attention to is:
|
||||
|
||||
> "<= bdb_equality_candidates: (foo) index_param failed (18)"
|
||||
> "<= mdb_equality_candidates: (foo) index_param failed (18)"
|
||||
|
||||
That means that some application tried to use an equality filter ({{foo=<somevalue>}})
|
||||
and attribute {{foo}} does not have an equality index. If you see a lot of these
|
||||
@ -163,165 +151,6 @@ For syslog-ng, add or modify the following line in {{syslog-ng.conf}}:
|
||||
where n is the number of lines which will be buffered before a write.
|
||||
|
||||
|
||||
H2: Caching
|
||||
|
||||
We all know what caching is, don't we?
|
||||
|
||||
In brief, "A cache is a block of memory for temporary storage of data likely
|
||||
to be used again" - {{URL:http://en.wikipedia.org/wiki/Cache}}
|
||||
|
||||
There are 3 types of caches, BerkeleyDB's own cache, {{slapd}}(8)
|
||||
entry cache and {{TERM:IDL}} (IDL) cache.
|
||||
|
||||
|
||||
H3: Berkeley DB Cache
|
||||
|
||||
There are two ways to tune for the BDB cachesize:
|
||||
|
||||
(a) BDB cache size necessary to load the database via slapadd in optimal time
|
||||
|
||||
(b) BDB cache size necessary to have a high performing running slapd once the data is loaded
|
||||
|
||||
For (a), the optimal cachesize is the size of the entire database. If you
|
||||
already have the database loaded, this is simply a
|
||||
|
||||
> du -c -h *.bdb
|
||||
|
||||
in the directory containing the OpenLDAP ({{/usr/local/var/openldap-data}}) data.
|
||||
|
||||
For (b), the optimal cachesize is just the size of the {{id2entry.bdb}} file,
|
||||
plus about 10% for growth.
|
||||
|
||||
The tuning of {{DB_CONFIG}} should be done for each BDB type database
|
||||
instantiated (back-bdb, back-hdb).
|
||||
|
||||
Note that while the {{TERM:BDB}} cache is just raw chunks of memory and
|
||||
configured as a memory size, the {{slapd}}(8) entry cache holds parsed entries,
|
||||
and the size of each entry is variable.
|
||||
|
||||
There is also an IDL cache which is used for Index Data Lookups.
|
||||
If you can fit all of your database into slapd's entry cache, and all of your
|
||||
index lookups fit in the IDL cache, that will provide the maximum throughput.
|
||||
|
||||
If not, but you can fit the entire database into the BDB cache, then you
|
||||
should do that and shrink the slapd entry cache as appropriate.
|
||||
|
||||
Failing that, you should balance the BDB cache against the entry cache.
|
||||
|
||||
It is worth noting that it is not absolutely necessary to configure a BerkeleyDB
|
||||
cache equal in size to your entire database. All that you need is a cache
|
||||
that's large enough for your "working set."
|
||||
|
||||
That means, large enough to hold all of the most frequently accessed data,
|
||||
plus a few less-frequently accessed items.
|
||||
|
||||
For more information, please see: {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/ref/am_conf/cachesize.html}}
|
||||
|
||||
H4: Calculating Cachesize
|
||||
|
||||
The back-bdb database lives in two main files, {{F:dn2id.bdb}} and {{F:id2entry.bdb}}.
|
||||
These are B-tree databases. We have never documented the back-bdb internal
|
||||
layout before, because it didn't seem like something anyone should have to worry
|
||||
about, nor was it necessarily cast in stone. But here's how it works today,
|
||||
in OpenLDAP 2.4.
|
||||
|
||||
A B-tree is a balanced tree; it stores data in its leaf nodes and bookkeeping
|
||||
data in its interior nodes (If you don't know what tree data structures look
|
||||
like in general, Google for some references, because that's getting far too
|
||||
elementary for the purposes of this discussion).
|
||||
|
||||
For decent performance, you need enough cache memory to contain all the nodes
|
||||
along the path from the root of the tree down to the particular data item
|
||||
you're accessing. That's enough cache for a single search. For the general case,
|
||||
you want enough cache to contain all the internal nodes in the database.
|
||||
|
||||
> db_stat -d
|
||||
|
||||
will tell you how many internal pages are present in a database. You should
|
||||
check this number for both dn2id and id2entry.
|
||||
|
||||
Also note that {{id2entry}} always uses 16KB per "page", while {{dn2id}} uses whatever
|
||||
the underlying filesystem uses, typically 4 or 8KB. To avoid thrashing,
|
||||
your cache must be at least as large as the number of internal pages in both
|
||||
the {{dn2id}} and {{id2entry}} databases, plus some extra space to accommodate
|
||||
the actual leaf data pages.
|
||||
|
||||
For example, in my OpenLDAP 2.4 test database, I have an input LDIF file that's
|
||||
about 360MB. With the back-hdb backend this creates a {{dn2id.bdb}} that's 68MB,
|
||||
and an {{id2entry}} that's 800MB. db_stat tells me that {{dn2id}} uses 4KB pages, has
|
||||
433 internal pages, and 6378 leaf pages. The id2entry uses 16KB pages, has 52
|
||||
internal pages, and 45912 leaf pages. In order to efficiently retrieve any
|
||||
single entry in this database, the cache should be at least
|
||||
|
||||
> (433+1) * 4KB + (52+1) * 16KB in size: 1736KB + 848KB =~ 2.5MB.
|
||||
|
||||
This doesn't take into account other library overhead, so this is even lower
|
||||
than the barest minimum. The default cache size, when nothing is configured,
|
||||
is only 256KB.
|
||||
|
||||
This 2.5MB number also doesn't take indexing into account. Each indexed
|
||||
attribute results in another database file. Earlier versions of OpenLDAP
|
||||
kept these index databases in Hash format, but from OpenLDAP 2.2 onward
|
||||
the index databases are in B-tree format so the same procedure can
|
||||
be used to calculate the necessary amount of cache for each index database.
|
||||
|
||||
For example, if your only index is for the objectClass attribute and db_stat
|
||||
reveals that {{objectClass.bdb}} has 339 internal pages and uses 4096 byte
|
||||
pages, the additional cache needed for just this attribute index is
|
||||
|
||||
> (339+1) * 4KB =~ 1.3MB.
|
||||
|
||||
With only this index enabled, I'd figure at least a 4MB cache for this backend.
|
||||
(Of course you're using a single cache shared among all of the database files,
|
||||
so the cache pages will most likely get used for something other than what you
|
||||
accounted for, but this gives you a fighting chance.)
|
||||
|
||||
With this 4MB cache I can slapcat this entire database on my 1.3GHz PIII in
|
||||
1 minute, 40 seconds. With the cache doubled to 8MB, it still takes the same 1:40s.
|
||||
Once you've got enough cache to fit the B-tree internal pages, increasing it
|
||||
further won't have any effect until the cache really is large enough to hold
|
||||
100% of the data pages. I don't have enough free RAM to hold all the 800MB
|
||||
id2entry data, so 4MB is good enough.
|
||||
|
||||
With back-bdb and back-hdb you can use "db_stat -m" to check how well the
|
||||
database cache is performing.
|
||||
|
||||
For more information on {{db_stat}}: {{URL:http://www.oracle.com/technology/documentation/berkeley-db/db/utility/db_stat.html}}
|
||||
|
||||
H3: {{slapd}}(8) Entry Cache (cachesize)
|
||||
|
||||
The {{slapd}}(8) entry cache operates on decoded entries. The rationale - entries
|
||||
in the entry cache can be used directly, giving the fastest response. If an entry
|
||||
isn't in the entry cache but can be extracted from the BDB page cache, that will
|
||||
avoid an I/O but it will still require parsing, so this will be slower.
|
||||
|
||||
If the entry is in neither cache then BDB will have to flush some of its current
|
||||
cached pages and bring in the needed pages, resulting in a couple of expensive
|
||||
I/Os as well as parsing.
|
||||
|
||||
The most optimal value is of course, the entire number of entries in the database.
|
||||
However, most directory servers don't consistently serve out their entire database, so setting this to a lesser number that more closely matches the believed working set of data is
|
||||
sufficient. This is the second most important parameter for the DB.
|
||||
|
||||
As far as balancing the entry cache vs the BDB cache - parsed entries in memory
|
||||
are generally about twice as large as they are on disk.
|
||||
|
||||
As we have already mentioned, not having a proper database cache size will
|
||||
cause performance issues. These issues are not an indication of corruption
|
||||
occurring in the database. It is merely the fact that the cache is thrashing
|
||||
itself that causes performance/response time to slowdown.
|
||||
|
||||
|
||||
H3: {{TERM:IDL}} Cache (idlcachesize)
|
||||
|
||||
Each IDL holds the search results from a given query, so the IDL cache will
|
||||
end up holding the most frequently requested search results. For back-bdb,
|
||||
it is generally recommended to match the "cachesize" setting. For back-hdb,
|
||||
it is generally recommended to be 3x"cachesize".
|
||||
|
||||
{NOTE: The idlcachesize setting directly affects search performance}
|
||||
|
||||
|
||||
H2: {{slapd}}(8) Threads
|
||||
|
||||
{{slapd}}(8) can process requests via a configurable number of threads, which
|
||||
|
@ -167,7 +167,6 @@ AuthcId|Authentication Identity
|
||||
AuthzDN|Authorization DN
|
||||
AuthzId|Authorization Identity
|
||||
BCP|Best Current Practice
|
||||
BDB|Berkeley DB (Backend)
|
||||
BER|Basic Encoding Rules
|
||||
BNF|Backus-Naur Form
|
||||
C|The C Programming Language
|
||||
@ -201,7 +200,6 @@ FYI|For Your Information
|
||||
GSER|Generic String Encoding Rules
|
||||
GSS-API|Generic Security Service Application Program Interface
|
||||
GSSAPI|SASL Kerberos V GSS-API Authentication Mechanism
|
||||
HDB|Hierarchical Database (Backend)
|
||||
I-D|Internet-Draft
|
||||
IA5|International Alphabet 5
|
||||
IDNA|Internationalized Domain Names in Applications
|
||||
|
@ -84,7 +84,7 @@ if you have not done so already.
|
||||
+ Test the standalone system:
|
||||
|
||||
.This step requires the standalone LDAP server, {{slapd}}(8),
|
||||
with {{HDB}} and/or {{BDB}} support.
|
||||
with {{MDB}} support.
|
||||
|
||||
E: % make test
|
||||
|
||||
|
@ -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.
|
||||
<databasetype>
|
||||
should be one of
|
||||
.BR bdb ,
|
||||
.BR config ,
|
||||
.BR dnssrv ,
|
||||
.BR hdb ,
|
||||
.BR ldap ,
|
||||
.BR ldif ,
|
||||
.BR mdb ,
|
||||
@ -2091,10 +2089,10 @@ olcDatabase: config
|
||||
olcRootPW: {SSHA}XKYnrjvGT3wZFQrDD5040US592LxsdLy
|
||||
olcAccess: to * by * none
|
||||
|
||||
dn: olcDatabase=bdb,cn=config
|
||||
dn: olcDatabase=mdb,cn=config
|
||||
objectClass: olcDatabaseConfig
|
||||
objectClass: olcBdbConfig
|
||||
olcDatabase: bdb
|
||||
objectClass: olcMdbConfig
|
||||
olcDatabase: mdb
|
||||
olcSuffix: "dc=our\-domain,dc=com"
|
||||
# The database directory MUST exist prior to
|
||||
# running slapd AND should only be accessible
|
||||
|
@ -14,11 +14,8 @@ It relies completely on the underlying operating system for memory
|
||||
management and does no caching of its own. It is the recommended
|
||||
primary database backend.
|
||||
.LP
|
||||
The \fBmdb\fP backend is similar to the \fBhdb\fP backend in that
|
||||
it uses a hierarchical database layout which
|
||||
supports subtree renames. It is both more space-efficient and more
|
||||
execution-efficient than the \fBbdb\fP backend, while being overall
|
||||
much simpler to manage.
|
||||
The \fBmdb\fP backend uses a hierarchical database layout which
|
||||
supports subtree renames.
|
||||
.SH CONFIGURATION
|
||||
These
|
||||
.B slapd.conf
|
||||
|
@ -19,7 +19,7 @@ sites/applications that use RDBMSes and/or LDAP.
|
||||
Or whatever else...
|
||||
.LP
|
||||
It is NOT designed as a general-purpose backend that uses RDBMS instead
|
||||
of BerkeleyDB (as the standard BDB backend does), though it can be
|
||||
of LMDB (as the standard MDB backend does), though it can be
|
||||
used as such with several limitations.
|
||||
You can take a look at
|
||||
.B http://www.openldap.org/faq/index.cgi?file=378
|
||||
|
@ -920,9 +920,8 @@ identity, control is passed straight to the subsequent rules.
|
||||
|
||||
.SH OPERATION REQUIREMENTS
|
||||
Operations require different privileges on different portions of entries.
|
||||
The following summary applies to primary MDB database backend and the
|
||||
deprecated BDB and HDB backends. Requirements for other backends may
|
||||
(and often do) differ.
|
||||
The following summary applies to primary MDB database backend. Requirements
|
||||
for other backends may (and often do) differ.
|
||||
|
||||
.LP
|
||||
The
|
||||
@ -1085,9 +1084,7 @@ Access control to search entries is checked by the frontend,
|
||||
so it is fully honored by all backends; for all other operations
|
||||
and for the discovery phase of the search operation,
|
||||
full ACL semantics is only supported by the primary backends, i.e.
|
||||
.BR back\-bdb (5),
|
||||
and
|
||||
.BR back\-hdb (5).
|
||||
.BR back\-mdb (5).
|
||||
|
||||
Some other backend, like
|
||||
.BR back\-sql (5),
|
||||
|
@ -19,14 +19,6 @@ corresponding
|
||||
.BR slapd\-<backend> (5)
|
||||
manual pages.
|
||||
.TP
|
||||
.B bdb
|
||||
This was the recommended primary backend through OpenLDAP 2.3, but it has
|
||||
since been superseded by the
|
||||
.BR mdb
|
||||
backend. It takes care to configure it properly.
|
||||
It uses the transactional database interface of the Oracle Berkeley
|
||||
DB (BDB) package to store data.
|
||||
.TP
|
||||
.B config
|
||||
This backend is used to manage the configuration of slapd at run-time.
|
||||
Unlike other backends, only a single instance of the
|
||||
@ -41,22 +33,6 @@ This backend is experimental.
|
||||
It serves up referrals based upon SRV resource records held in the
|
||||
Domain Name System.
|
||||
.TP
|
||||
.B hdb
|
||||
This was the recommended primary backend through OpenLDAP 2.4.40 but it has
|
||||
since been superseded by the
|
||||
.BR mdb
|
||||
backend. It takes care to configure it properly.
|
||||
.B hdb
|
||||
is a variant of the
|
||||
.B bdb
|
||||
backend that uses a hierarchical database
|
||||
layout.
|
||||
This layout stores entry DNs more efficiently than the
|
||||
.B bdb
|
||||
backend,
|
||||
using less space and requiring less work to create, delete, and rename
|
||||
entries. It is also one of the few backends to support subtree renames.
|
||||
.TP
|
||||
.B ldap
|
||||
This backend acts as a proxy to forward incoming requests to another
|
||||
LDAP server.
|
||||
@ -68,14 +44,9 @@ Its usage should be limited to very simple databases, where performance
|
||||
is not a requirement. This backend also supports subtree renames.
|
||||
.TP
|
||||
.B mdb
|
||||
This is the recommended primary backend, superseding
|
||||
.BR hdb .
|
||||
This is the recommended primary backend.
|
||||
This backend uses OpenLDAP's own MDB transactional database
|
||||
library. It is extremely compact and extremely efficient, delivering
|
||||
much higher performance than the Berkeley DB backends while using
|
||||
significantly less memory. Also, unlike Berkeley DB, MDB is crash proof,
|
||||
and requires no special tuning or maintenance.
|
||||
This backend also supports subtree renames.
|
||||
library. This backend also supports subtree renames.
|
||||
.TP
|
||||
.B meta
|
||||
This backend performs basic LDAP proxying with respect to a set of
|
||||
@ -138,10 +109,8 @@ ETCDIR/slapd.d
|
||||
default slapd configuration directory
|
||||
.SH SEE ALSO
|
||||
.BR ldap (3),
|
||||
.BR slapd\-bdb (5),
|
||||
.BR slapd\-config (5),
|
||||
.BR slapd\-dnssrv (5),
|
||||
.BR slapd\-hdb (5),
|
||||
.BR slapd\-ldap (5),
|
||||
.BR slapd\-ldif (5),
|
||||
.BR slapd\-mdb (5),
|
||||
|
@ -1276,10 +1276,8 @@ type of backend.
|
||||
.B backend <databasetype>
|
||||
Mark the beginning of a backend definition. <databasetype>
|
||||
should be one of
|
||||
.BR bdb ,
|
||||
.BR config ,
|
||||
.BR dnssrv ,
|
||||
.BR hdb ,
|
||||
.BR ldap ,
|
||||
.BR ldif ,
|
||||
.BR mdb ,
|
||||
@ -1306,10 +1304,8 @@ option are mandatory for each database.
|
||||
.B database <databasetype>
|
||||
Mark the beginning of a new database instance definition. <databasetype>
|
||||
should be one of
|
||||
.BR bdb ,
|
||||
.BR config ,
|
||||
.BR dnssrv ,
|
||||
.BR hdb ,
|
||||
.BR ldap ,
|
||||
.BR ldif ,
|
||||
.BR mdb ,
|
||||
@ -1619,8 +1615,7 @@ By default, mirrormode is off.
|
||||
This option enables database-specific monitoring in the entry related
|
||||
to the current database in the "cn=Databases,cn=Monitor" subtree
|
||||
of the monitor database, if the monitor database is enabled.
|
||||
Currently, only the BDB and the HDB databases provide database-specific
|
||||
monitoring.
|
||||
Currently, only the MDB database provides database-specific monitoring.
|
||||
The default depends on the backend type.
|
||||
.TP
|
||||
.B overlay <overlay-name>
|
||||
|
@ -91,7 +91,7 @@ password resets, etc.
|
||||
.B refint
|
||||
Referential Integrity.
|
||||
This overlay can be used with a backend database such as
|
||||
.BR slapd\-bdb (5)
|
||||
.BR slapd\-mdb (5)
|
||||
to maintain the cohesiveness of a schema which utilizes reference
|
||||
attributes.
|
||||
.TP
|
||||
@ -121,7 +121,7 @@ replication, including persistent search functionality.
|
||||
.B translucent
|
||||
Translucent Proxy.
|
||||
This overlay can be used with a backend database such as
|
||||
.BR slapd\-bdb (5)
|
||||
.BR slapd\-mdb (5)
|
||||
to create a "translucent proxy".
|
||||
Content of entries retrieved from a remote LDAP server can be partially
|
||||
overridden by the database.
|
||||
@ -129,7 +129,7 @@ overridden by the database.
|
||||
.B unique
|
||||
Attribute Uniqueness.
|
||||
This overlay can be used with a backend database such as
|
||||
.BR slapd\-bdb (5)
|
||||
.BR slapd\-mdb (5)
|
||||
to enforce the uniqueness of some or all attributes within a subtree.
|
||||
.TP
|
||||
.B valsort
|
||||
|
@ -8,7 +8,7 @@ slapo\-refint \- Referential Integrity overlay to slapd
|
||||
ETCDIR/slapd.conf
|
||||
.SH DESCRIPTION
|
||||
The Referential Integrity overlay can be used with a backend database such as
|
||||
.BR slapd\-bdb (5)
|
||||
.BR slapd\-mdb (5)
|
||||
to maintain the cohesiveness of a schema which utilizes reference attributes.
|
||||
.LP
|
||||
Integrity is maintained by updating database records which contain the named
|
||||
|
@ -8,7 +8,7 @@ slapo\-translucent \- Translucent Proxy overlay to slapd
|
||||
ETCDIR/slapd.conf
|
||||
.SH DESCRIPTION
|
||||
The Translucent Proxy overlay can be used with a backend database such as
|
||||
.BR slapd\-bdb (5)
|
||||
.BR slapd\-mdb (5)
|
||||
to create a "translucent proxy". Entries retrieved from a remote LDAP
|
||||
server may have some or all attributes overridden, or new attributes
|
||||
added, by entries in the local database before being presented to the
|
||||
|
@ -177,8 +177,6 @@ mode) when you do this to ensure consistency of the database. It is
|
||||
always safe to run
|
||||
.B slapcat
|
||||
with the
|
||||
.BR slapd\-bdb (5),
|
||||
.BR slapd\-hdb (5),
|
||||
.BR slapd\-mdb (5),
|
||||
and
|
||||
.BR slapd\-null (5)
|
||||
|
@ -168,8 +168,7 @@ mode) when you do this to ensure consistency of the database. It is
|
||||
always safe to run
|
||||
.B slapschema
|
||||
with the
|
||||
.BR slapd\-bdb (5),
|
||||
.BR slapd\-hdb (5),
|
||||
.BR slapd\-mdb (5),
|
||||
and
|
||||
.BR slapd\-null (5)
|
||||
backends.
|
||||
|
@ -96,12 +96,6 @@
|
||||
/* Define to 1 if you have the `bcopy' function. */
|
||||
#undef HAVE_BCOPY
|
||||
|
||||
/* define this if Berkeley DB is available */
|
||||
#undef HAVE_BERKELEY_DB
|
||||
|
||||
/* define if Berkeley DB has DB_THREAD support */
|
||||
#undef HAVE_BERKELEY_DB_THREAD
|
||||
|
||||
/* Define to 1 if you have the <bits/types.h> header file. */
|
||||
#undef HAVE_BITS_TYPES_H
|
||||
|
||||
@ -927,9 +921,6 @@
|
||||
/* define to support LDAP Async Metadirectory backend */
|
||||
#undef SLAPD_ASYNCMETA
|
||||
|
||||
/* define to support BDB backend */
|
||||
#undef SLAPD_BDB
|
||||
|
||||
/* define to support cleartext passwords */
|
||||
#undef SLAPD_CLEARTEXT
|
||||
|
||||
@ -939,9 +930,6 @@
|
||||
/* define to support DNS SRV backend */
|
||||
#undef SLAPD_DNSSRV
|
||||
|
||||
/* define to support HDB backend */
|
||||
#undef SLAPD_HDB
|
||||
|
||||
/* define to support LDAP backend */
|
||||
#undef SLAPD_LDAP
|
||||
|
||||
|
@ -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 \
|
||||
slapadd.c slapcat.c slapcommon.c slapdn.c slapindex.c \
|
||||
slappasswd.c slaptest.c slapauth.c slapacl.c component.c \
|
||||
aci.c alock.c txn.c slapschema.c slapmodify.c \
|
||||
aci.c txn.c slapschema.c slapmodify.c \
|
||||
$(@PLAT@_SRCS)
|
||||
|
||||
OBJS = main.o globals.o bconfig.o config.o daemon.o \
|
||||
@ -56,7 +56,7 @@ OBJS = main.o globals.o bconfig.o config.o daemon.o \
|
||||
backglue.o backover.o ctxcsn.o ldapsync.o frontend.o \
|
||||
slapadd.o slapcat.o slapcommon.o slapdn.o slapindex.o \
|
||||
slappasswd.o slaptest.o slapauth.o slapacl.o component.o \
|
||||
aci.o alock.o txn.o slapschema.o slapmodify.o \
|
||||
aci.o txn.o slapschema.o slapmodify.o \
|
||||
$(@PLAT@_OBJS)
|
||||
|
||||
LDAP_INCDIR= ../../include -I$(srcdir) -I$(srcdir)/slapi -I.
|
||||
@ -366,14 +366,8 @@ veryclean-local-srv: FORCE
|
||||
fi; \
|
||||
done
|
||||
|
||||
install-dbc-maybe: install-dbc-@BUILD_BDB@ install-dbc-@BUILD_HDB@
|
||||
|
||||
install-dbc-yes: install-db-config
|
||||
install-dbc-mod: install-db-config
|
||||
install-dbc-no:
|
||||
|
||||
install-local-srv: install-slapd install-tools \
|
||||
install-conf install-dbc-maybe install-schema install-tools
|
||||
install-conf install-schema install-tools
|
||||
|
||||
install-slapd: FORCE
|
||||
-$(MKDIR) $(DESTDIR)$(libexecdir)
|
||||
|
@ -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 */
|
||||
|
||||
/*
|
||||
* Left and Right "{num}" prefix to ordered RDNs ("olcDatabase={1}bdb").
|
||||
* Left and Right "{num}" prefix to ordered RDNs ("olcDatabase={1}mdb").
|
||||
* IX_DN* are for LDAP RDNs, IX_FS* for their .ldif filenames.
|
||||
*/
|
||||
#define IX_DNL '{'
|
||||
|
@ -1962,8 +1962,8 @@ monitor_back_initialize(
|
||||
{ "olmGenericAttributes", "olmSubSystemAttributes:0" },
|
||||
{ "olmDatabaseAttributes", "olmSubSystemAttributes:1" },
|
||||
|
||||
/* for example, back-bdb specific attrs
|
||||
* are in "olmDatabaseAttributes:1"
|
||||
/* for example, back-mdb specific attrs
|
||||
* are in "olmDatabaseAttributes:12"
|
||||
*
|
||||
* NOTE: developers, please record here OID assignments
|
||||
* for other modules */
|
||||
@ -1973,8 +1973,8 @@ monitor_back_initialize(
|
||||
{ "olmGenericObjectClasses", "olmSubSystemObjectClasses:0" },
|
||||
{ "olmDatabaseObjectClasses", "olmSubSystemObjectClasses:1" },
|
||||
|
||||
/* for example, back-bdb specific objectClasses
|
||||
* are in "olmDatabaseObjectClasses:1"
|
||||
/* for example, back-mdb specific objectClasses
|
||||
* are in "olmDatabaseObjectClasses:12"
|
||||
*
|
||||
* NOTE: developers, please record here OID assignments
|
||||
* for other modules */
|
||||
|
@ -247,7 +247,7 @@ static OidRec OidMacros[] = {
|
||||
* Backend/Database registry
|
||||
*
|
||||
* OLcfg{Bk|Db}{Oc|At}:0 -> common
|
||||
* OLcfg{Bk|Db}{Oc|At}:1 -> back-bdb(/back-hdb)
|
||||
* OLcfg{Bk|Db}{Oc|At}:1 -> back-bdb(/back-hdb) (removed)
|
||||
* OLcfg{Bk|Db}{Oc|At}:2 -> back-ldif
|
||||
* OLcfg{Bk|Db}{Oc|At}:3 -> back-ldap/meta
|
||||
* OLcfg{Bk|Db}{Oc|At}:4 -> back-monitor
|
||||
|
@ -1130,8 +1130,7 @@ rdn_validate( struct berval *rdn )
|
||||
|
||||
/* build_new_dn:
|
||||
*
|
||||
* Used by back-bdb back_modrdn to create the new dn of entries being
|
||||
* renamed.
|
||||
* Used to create the new dn of entries being renamed.
|
||||
*
|
||||
* new_dn = parent (p_dn) + separator + rdn (newrdn) + null.
|
||||
*/
|
||||
|
@ -5613,7 +5613,7 @@ cleanup:;
|
||||
cm->monitor_cb = (void *)cb;
|
||||
|
||||
/* we don't need to keep track of the attributes, because
|
||||
* bdb_monitor_free() takes care of everything */
|
||||
* mdb_monitor_free() takes care of everything */
|
||||
if ( a != NULL ) {
|
||||
attrs_free( a );
|
||||
}
|
||||
@ -5697,7 +5697,7 @@ pcache_initialize()
|
||||
}
|
||||
#endif /* PCACHE_EXOP_QUERY_DELETE */
|
||||
|
||||
argv[ 0 ] = "back-bdb/back-hdb monitor";
|
||||
argv[ 0 ] = "back-mdb monitor";
|
||||
c.argv = argv;
|
||||
c.argc = 3;
|
||||
c.fname = argv[0];
|
||||
|
@ -1818,7 +1818,6 @@ struct BackendDB {
|
||||
|
||||
/*
|
||||
* define to honor hasSubordinates operational attribute in search filters
|
||||
* (in previous use there was a flaw with back-bdb; now it is fixed).
|
||||
*/
|
||||
#define be_has_subordinates bd_info->bi_has_subordinates
|
||||
|
||||
|
@ -30,8 +30,7 @@ olcPidFile: %LOCALSTATEDIR%/run/slapd.pid
|
||||
#objectClass: olcModuleList
|
||||
#cn: module
|
||||
#olcModulepath: %MODULEDIR%
|
||||
#olcModuleload: back_bdb.la
|
||||
#olcModuleload: back_hdb.la
|
||||
#olcModuleload: back_mdb.la
|
||||
#olcModuleload: back_ldap.la
|
||||
#olcModuleload: back_passwd.la
|
||||
#olcModuleload: back_shell.la
|
||||
|
@ -16,15 +16,11 @@
|
||||
RUN=./run
|
||||
SUBDIRS= progs
|
||||
|
||||
BUILD_BDB=@BUILD_BDB@
|
||||
BUILD_HDB=@BUILD_HDB@
|
||||
BUILD_MDB=@BUILD_MDB@
|
||||
BUILD_SQL=@BUILD_SQL@
|
||||
|
||||
# test primary backends (default)
|
||||
test tests:
|
||||
@$(MAKE) bdb
|
||||
@$(MAKE) hdb
|
||||
@$(MAKE) mdb
|
||||
|
||||
# test all backends
|
||||
@ -32,22 +28,6 @@ alltests: tests
|
||||
@$(MAKE) sql
|
||||
@$(MAKE) ldif
|
||||
|
||||
bdb test-bdb: bdb-$(BUILD_BDB)
|
||||
bdb-no:
|
||||
@echo "run configure with --enable-bdb to run BDB tests"
|
||||
|
||||
bdb-yes bdb-mod: FORCE
|
||||
@echo "Initiating LDAP tests for BDB..."
|
||||
@$(RUN) -b bdb all
|
||||
|
||||
hdb test-hdb: hdb-$(BUILD_HDB)
|
||||
hdb-no:
|
||||
@echo "run configure with --enable-hdb to run HDB tests"
|
||||
|
||||
hdb-yes hdb-mod: FORCE
|
||||
@echo "Initiating LDAP tests for HDB..."
|
||||
@$(RUN) -b hdb all
|
||||
|
||||
mdb test-mdb: mdb-$(BUILD_MDB)
|
||||
mdb-no:
|
||||
@echo "run configure with --enable-mdb to run MDB tests"
|
||||
@ -70,26 +50,10 @@ ldif test-ldif: FORCE
|
||||
|
||||
regressions: FORCE
|
||||
@echo "Testing (available) ITS regressions"
|
||||
@$(MAKE) bdb-its
|
||||
@$(MAKE) hdb-its
|
||||
@$(MAKE) mdb-its
|
||||
|
||||
its: regressions
|
||||
|
||||
bdb-its: bdb-its-$(BUILD_BDB)
|
||||
bdb-its-no:
|
||||
@echo "run configure with --enable-bdb to run BDB ITS regressions"
|
||||
|
||||
bdb-its-yes bdb-its-mod: FORCE
|
||||
@$(RUN) -b bdb its-all
|
||||
|
||||
hdb-its: hdb-its-$(BUILD_HDB)
|
||||
hdb-its-no:
|
||||
@echo "run configure with --enable-hdb to run HDB ITS regressions"
|
||||
|
||||
hdb-its-yes hdb-its-mod: FORCE
|
||||
@$(RUN) -b hdb its-all
|
||||
|
||||
mdb-its: mdb-its-$(BUILD_MDB)
|
||||
mdb-its-no:
|
||||
@echo "run configure with --enable-mdb to run MDB ITS regressions"
|
||||
|
@ -2,8 +2,6 @@ This directory contains a series of test scripts which are used to
|
||||
verify basic functionality of the LDAP libraries and slapd.
|
||||
|
||||
To run all of the tests, type "make test".
|
||||
To run BDB tests, type "make bdb".
|
||||
To run HDB tests, type "make hdb".
|
||||
To run MDB tests, type "make mdb".
|
||||
To run SQL tests, define SLAPD_USE_SQL=<rdbms> and type
|
||||
"make sql"; define SLAPD_USE_SQLWRITE=yes
|
||||
|
@ -16,10 +16,6 @@
|
||||
echo "running defines.sh"
|
||||
. $SRCDIR/scripts/defines.sh
|
||||
|
||||
if test "$BACKEND" != "bdb" && test "$BACKEND" != "hdb" ; then
|
||||
echo "Warning: this test is known to affect bdb and hdb, although it may impact other backends as well."
|
||||
fi
|
||||
|
||||
mkdir -p $DBDIR1A $DBDIR2A
|
||||
|
||||
ITS=4184
|
||||
|
@ -47,22 +47,6 @@ ITS=4448
|
||||
ITSDIR=$DATADIR/regressions/its$ITS
|
||||
ITSCONF=$ITSDIR/slapd-meta.conf
|
||||
|
||||
# NOTE: this could be added to all tests...
|
||||
if test "$BACKEND" = "bdb" || test "$BACKEND" = "hdb" ; then
|
||||
if test "x$DB_CONFIG" != "x" ; then \
|
||||
if test -f $DB_CONFIG ; then
|
||||
echo "==> using DB_CONFIG \"$DB_CONFIG\""
|
||||
cp $DB_CONFIG $DBDIR1
|
||||
cp $DB_CONFIG $DBDIR2
|
||||
else
|
||||
echo "==> DB_CONFIG must point to a valid file (ignored)"
|
||||
fi
|
||||
else
|
||||
echo "==> set \"DB_CONFIG\" to the DB_CONFIG file you want to use for the test."
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
echo "Starting slapd on TCP/IP port $PORT1..."
|
||||
. $CONFFILTER $BACKEND $MONITORDB < $CONF > $CONF1
|
||||
$SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
|
||||
|
@ -64,10 +64,6 @@ pcachetemplate (cn=) 0 86400 86400 86400 180
|
||||
|
||||
pcachebind (cn=) 0 3600 sub ou=people,dc=example,dc=com
|
||||
|
||||
#bdb#cachesize 20
|
||||
#hdb#cachesize 20
|
||||
#bdb#dbnosync
|
||||
#hdb#dbnosync
|
||||
#mdb#dbnosync
|
||||
|
||||
#~null~#directory @TESTDIR@/db.2.a
|
||||
|
@ -54,10 +54,6 @@ pcachetemplate (mail=) 0 @TTL@ @NTTL@ @STTL@
|
||||
pcachetemplate (&(objectclass=)(uid=)) 1 @TTL@ @NTTL@ @STTL@ @TTR@
|
||||
pcachebind (&(objectclass=person)(uid=)) 1 @BTTR@ sub "ou=Alumni Association,ou=people,dc=example,dc=com"
|
||||
|
||||
#bdb#cachesize 20
|
||||
#hdb#cachesize 20
|
||||
#bdb#dbnosync
|
||||
#hdb#dbnosync
|
||||
#mdb#dbnosync
|
||||
|
||||
#~null~#directory @TESTDIR@/db.2.a
|
||||
|
@ -34,8 +34,6 @@ argsfile @TESTDIR@/slapd.2.args
|
||||
referral "@URI1@"
|
||||
|
||||
database @BACKEND@
|
||||
#bdb#cachesize 0
|
||||
#hdb#cachesize 0
|
||||
|
||||
suffix "o=University of Mich,c=US"
|
||||
rootdn "cn=Manager,o=University of Mich,c=US"
|
||||
|
@ -44,8 +44,6 @@ rootpw secret
|
||||
#~null~#directory @TESTDIR@/db.1.a
|
||||
#indexdb#index objectClass eq
|
||||
#indexdb#index cn,sn,uid pres,eq,sub
|
||||
#bdb#checkpoint 1024 5
|
||||
#hdb#checkpoint 1024 5
|
||||
#mdb#maxsize 33554432
|
||||
#ndb#dbname db_1
|
||||
#ndb#include @DATADIR@/ndb.conf
|
||||
|
@ -24,8 +24,6 @@ EGREP_CMD="@EGREP@"
|
||||
export SRCDIR TOPSRCDIR LN_S EGREP_CMD
|
||||
|
||||
# backends known to ./run -b <backend> (used to deduce $BACKENDTYPE)
|
||||
AC_bdb=@BUILD_BDB@
|
||||
AC_hdb=@BUILD_HDB@
|
||||
AC_ldif=yes
|
||||
AC_mdb=@BUILD_MDB@
|
||||
AC_null=@BUILD_NULL@
|
||||
@ -74,7 +72,7 @@ fi
|
||||
if test "${AC_asyncmeta}" = "metamod" && test "${AC_LIBS_DYNAMIC}" = "static" ; then
|
||||
AC_meta="asyncmetano"
|
||||
fi
|
||||
export AC_bdb AC_hdb AC_ldap AC_mdb AC_meta AC_asyncmeta AC_monitor AC_null AC_relay AC_sql \
|
||||
export AC_ldap AC_mdb AC_meta AC_asyncmeta AC_monitor AC_null AC_relay AC_sql \
|
||||
AC_accesslog AC_autoca AC_constraint AC_dds AC_dynlist AC_memberof AC_pcache AC_ppolicy \
|
||||
AC_refint AC_retcode AC_rwm AC_unique AC_syncprov AC_translucent \
|
||||
AC_valsort \
|
||||
@ -158,7 +156,7 @@ while test $# -gt 0 ; do
|
||||
done
|
||||
|
||||
if test -z "$BACKEND" ; then
|
||||
for b in bdb hdb mdb ; do
|
||||
for b in mdb ; do
|
||||
if eval "test \"\$AC_$b\" != no" ; then
|
||||
BACKEND=$b
|
||||
break
|
||||
@ -179,7 +177,7 @@ fi
|
||||
# maindb: main storage backend. Currently index,limits,mode,paged results.
|
||||
INDEXDB=noindexdb MAINDB=nomaindb
|
||||
case $BACKEND in
|
||||
bdb|hdb|mdb) INDEXDB=indexdb MAINDB=maindb ;;
|
||||
mdb) INDEXDB=indexdb MAINDB=maindb ;;
|
||||
ndb) INDEXDB=indexdb ;;
|
||||
esac
|
||||
|
||||
|
@ -189,9 +189,8 @@ if test $RC != 0 ; then
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
if test $BACKEND != "bdb" ; then
|
||||
$LDAPMODIFY -v -D "$REFINTDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
|
||||
$TESTOUT 2>&1 << EDEL
|
||||
$LDAPMODIFY -v -D "$REFINTDN" -h $LOCALHOST -p $PORT1 -w $PASSWD > \
|
||||
$TESTOUT 2>&1 << EDEL
|
||||
version: 1
|
||||
dn: cn=group,o=refint
|
||||
changetype: add
|
||||
@ -205,63 +204,62 @@ member: uid=theman,ou=users,o=refint
|
||||
member: uid=richard,ou=users,o=refint
|
||||
EDEL
|
||||
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "ldapmodify failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "ldapmodify failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
sleep 1;
|
||||
sleep 1;
|
||||
|
||||
$LDAPSEARCH -S "" -b "o=refint" -h $LOCALHOST -p $PORT1 \
|
||||
manager member secretary > $SEARCHOUT 2>&1
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "ldapsearch failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
$LDAPSEARCH -S "" -b "o=refint" -h $LOCALHOST -p $PORT1 \
|
||||
manager member secretary > $SEARCHOUT 2>&1
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "ldapsearch failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
$EGREP_CMD "(manager|member|secretary):" $SEARCHOUT \
|
||||
| sed "s/ou=users/ou=people/g" | \
|
||||
sort > $TESTOUT 2>&1
|
||||
$EGREP_CMD "(manager|member|secretary):" $SEARCHOUT \
|
||||
| sed "s/ou=users/ou=people/g" | \
|
||||
sort > $TESTOUT 2>&1
|
||||
|
||||
echo "testing subtree rename"
|
||||
$LDAPMODRDN -D "$REFINTDN" -r -h $LOCALHOST -p $PORT1 -w $PASSWD > \
|
||||
/dev/null 2>&1 'ou=users,o=refint' 'ou=people'
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "ldapmodrdn failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
echo "testing subtree rename"
|
||||
$LDAPMODRDN -D "$REFINTDN" -r -h $LOCALHOST -p $PORT1 -w $PASSWD > \
|
||||
/dev/null 2>&1 'ou=users,o=refint' 'ou=people'
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "ldapmodrdn failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
sleep 1;
|
||||
sleep 1;
|
||||
|
||||
echo "Using ldapsearch to check dependents new rdn..."
|
||||
echo "Using ldapsearch to check dependents new rdn..."
|
||||
|
||||
$LDAPSEARCH -S "" -b "o=refint" -h $LOCALHOST -p $PORT1 \
|
||||
manager member secretary > $SEARCHOUT 2>&1
|
||||
$LDAPSEARCH -S "" -b "o=refint" -h $LOCALHOST -p $PORT1 \
|
||||
manager member secretary > $SEARCHOUT 2>&1
|
||||
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "ldapsearch failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "ldapsearch failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
$EGREP_CMD "(manager|member|secretary):" $SEARCHOUT \
|
||||
| sort > $SEARCHFLT 2>&1
|
||||
$EGREP_CMD "(manager|member|secretary):" $SEARCHOUT \
|
||||
| sort > $SEARCHFLT 2>&1
|
||||
|
||||
echo "Comparing ldapsearch results against original..."
|
||||
$CMP $TESTOUT $SEARCHFLT > $CMPOUT
|
||||
echo "Comparing ldapsearch results against original..."
|
||||
$CMP $TESTOUT $SEARCHFLT > $CMPOUT
|
||||
|
||||
if test $? != 0 ; then
|
||||
echo "comparison failed - subtree rename operations did not complete correctly"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit 1
|
||||
fi
|
||||
if test $? != 0 ; then
|
||||
echo "comparison failed - subtree rename operations did not complete correctly"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit 1
|
||||
fi
|
||||
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
|
@ -750,7 +750,7 @@ case $RC in
|
||||
esac
|
||||
|
||||
if test $MAINDB != maindb ; then
|
||||
# only bdb|hdb|mdb currently supports pagedResults control
|
||||
# only mdb currently supports pagedResults control
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
|
||||
echo ">>>>> Test succeeded"
|
||||
|
@ -40,22 +40,6 @@ rm -rf $TESTDIR
|
||||
|
||||
mkdir -p $TESTDIR $DBDIR1 $DBDIR2
|
||||
|
||||
# NOTE: this could be added to all tests...
|
||||
if test "$BACKEND" = "bdb" || test "$BACKEND" = "hdb" ; then
|
||||
if test "x$DB_CONFIG" != "x" ; then \
|
||||
if test -f $DB_CONFIG ; then
|
||||
echo "==> using DB_CONFIG \"$DB_CONFIG\""
|
||||
cp $DB_CONFIG $DBDIR1
|
||||
cp $DB_CONFIG $DBDIR2
|
||||
else
|
||||
echo "==> DB_CONFIG must point to a valid file (ignored)"
|
||||
fi
|
||||
else
|
||||
echo "==> set \"DB_CONFIG\" to the DB_CONFIG file you want to use for the test."
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
echo "Starting slapd on TCP/IP port $PORT1..."
|
||||
. $CONFFILTER $BACKEND $MONITORDB < $METACONF1 > $CONF1
|
||||
$SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
|
||||
|
@ -16,11 +16,6 @@
|
||||
echo "running defines.sh"
|
||||
. $SRCDIR/scripts/defines.sh
|
||||
|
||||
if test $BACKEND = bdb ; then
|
||||
echo "subtree rename not supported by back-$BACKEND"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mkdir -p $TESTDIR $DBDIR1
|
||||
|
||||
echo "Starting slapd on TCP/IP port $PORT1..."
|
||||
|
@ -32,7 +32,7 @@ fi
|
||||
|
||||
mkdir -p $TESTDIR $DBDIR1A $DBDIR1B $DBDIR2
|
||||
|
||||
SPEC="mdb=a,bdb=a,hdb=a"
|
||||
SPEC="mdb=a"
|
||||
|
||||
#
|
||||
# Test replication:
|
||||
|
@ -72,11 +72,10 @@ EOF
|
||||
fi
|
||||
fi
|
||||
|
||||
indexInclude="" mainInclude="" bdbInclude="# " nullExclude=""
|
||||
indexInclude="" mainInclude="" " nullExclude=""
|
||||
test $INDEXDB = indexdb || indexInclude="# "
|
||||
test $MAINDB = maindb || mainInclude="# "
|
||||
case $BACKEND in
|
||||
bdb | hdb) bdbInclude="" ;;
|
||||
null) nullExclude="# " ;;
|
||||
esac
|
||||
|
||||
@ -114,7 +113,6 @@ olcRootDN: cn=Manager,$BASEDN
|
||||
olcRootPW:: c2VjcmV0
|
||||
olcMonitoring: TRUE
|
||||
${nullExclude}olcDbDirectory: $TESTDIR/db.1.a/
|
||||
${bdbInclude}olcDbCacheSize: 1000
|
||||
${indexInclude}olcDbIndex: objectClass eq
|
||||
${indexInclude}olcDbIndex: cn pres,eq,sub
|
||||
${indexInclude}olcDbIndex: uid pres,eq,sub
|
||||
|
@ -479,29 +479,6 @@ if test $RC != 0 ; then
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
case $BACKEND in bdb | hdb)
|
||||
db_stat=
|
||||
for path in `echo "$PATH" | sed -e 's/:/ /g'`; do
|
||||
if test -f "$path/db_stat" && \
|
||||
"$path/db_stat" -E -h $PRODDIR/db > /dev/null 2>&1
|
||||
then
|
||||
db_stat="$path/db_stat"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if test -z "$db_stat" ; then
|
||||
echo "Could not find a working db_stat in PATH!"
|
||||
lock_bug=1
|
||||
elif "$db_stat" -E -h $PRODDIR/db | egrep -q 'HELD .* len:'; then
|
||||
echo "WARNING: Glue lock bug hit, next modify could deadlock"
|
||||
lock_bug=2
|
||||
else
|
||||
echo "Glue lock bug not found :-)"
|
||||
lock_bug=0
|
||||
fi
|
||||
esac
|
||||
|
||||
echo "Using ldapmodify to modify glue suffix on provider..."
|
||||
$LDAPADD -D "$MANAGERDN" -H $URI1 -w $PASSWD <<EOF >> $TESTOUT 2>&1
|
||||
dn: dc=example,dc=com
|
||||
|
@ -85,8 +85,7 @@ echo "Using ldapsearch to read database monitor entries..."
|
||||
$LDAPSEARCH -S "" -b "$DATABASESMONITORDN" -h $LOCALHOST -p $PORT1 \
|
||||
'objectclass=*' \
|
||||
structuralObjectClass entryDN namingContexts readOnly \
|
||||
monitorIsShadow monitorContext \
|
||||
olmBDBEntryCache olmBDBDNCache olmBDBIDLCache \
|
||||
monitorIsShadow monitorContext
|
||||
> $SEARCHOUT 2>&1
|
||||
RC=$?
|
||||
|
||||
@ -101,11 +100,8 @@ $LDIFFILTER -b monitor < $SEARCHOUT > $SEARCHFLT
|
||||
|
||||
TMPMONITOROUT2=$MONITOROUT2
|
||||
case $BACKEND in
|
||||
bdb|hdb)
|
||||
;;
|
||||
*)
|
||||
TMPMONITOROUT2=$TESTDIR/monitor2.out
|
||||
grep -v "olmBDB" $MONITOROUT2 > $TMPMONITOROUT2
|
||||
;;
|
||||
esac
|
||||
|
||||
|
@ -27,11 +27,6 @@ if test $REFINT = refintno; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test $BACKEND = bdb; then
|
||||
echo "$BACKEND backend does not support subtree rename, test skipped"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mkdir -p $TESTDIR $DBDIR1 $TESTDIR/confdir
|
||||
|
||||
$SLAPPASSWD -g -n >$CONFIGPWF
|
||||
@ -66,11 +61,10 @@ fi
|
||||
|
||||
cat /dev/null > $TESTOUT
|
||||
|
||||
indexInclude="" mainInclude="" bdbInclude="# " nullExclude=""
|
||||
indexInclude="" mainInclude="" nullExclude=""
|
||||
test $INDEXDB = indexdb || indexInclude="# "
|
||||
test $MAINDB = maindb || mainInclude="# "
|
||||
case $BACKEND in
|
||||
bdb | hdb) bdbInclude="" ;;
|
||||
null) nullExclude="# " ;;
|
||||
esac
|
||||
|
||||
@ -104,7 +98,6 @@ olcRootDN: cn=Manager,$BASEDN
|
||||
olcRootPW:: c2VjcmV0
|
||||
olcMonitoring: TRUE
|
||||
${nullExclude}olcDbDirectory: $TESTDIR/db.1.a/
|
||||
${bdbInclude}olcDbCacheSize: 1000
|
||||
${indexInclude}olcDbIndex: objectClass eq
|
||||
${indexInclude}olcDbIndex: cn pres,eq,sub
|
||||
${indexInclude}olcDbIndex: uid pres,eq,sub
|
||||
|
@ -63,7 +63,6 @@ KILLPIDS=
|
||||
$SLAPPASSWD -g -n >$CONFIGPWF
|
||||
|
||||
case "$BACKEND" in
|
||||
bdb|hdb) olcDbCheckpoint="olcDbCheckpoint";;
|
||||
*) olcDbCheckpoint="# olcDbCheckpoint";;
|
||||
esac
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user