mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-21 15:19:34 -05:00
Add back-ndb
This commit is contained in:
parent
c32cbed9ae
commit
f6edefa25d
74 changed files with 6822 additions and 8 deletions
|
|
@ -159,6 +159,7 @@ LUTIL_LIBS = @LUTIL_LIBS@
|
||||||
LTHREAD_LIBS = @LTHREAD_LIBS@
|
LTHREAD_LIBS = @LTHREAD_LIBS@
|
||||||
|
|
||||||
BDB_LIBS = @BDB_LIBS@
|
BDB_LIBS = @BDB_LIBS@
|
||||||
|
SLAPD_NDB_LIBS = @SLAPD_NDB_LIBS@
|
||||||
|
|
||||||
LDAP_LIBLBER_LA = $(LDAP_LIBDIR)/liblber/liblber.la
|
LDAP_LIBLBER_LA = $(LDAP_LIBDIR)/liblber/liblber.la
|
||||||
LDAP_LIBLDAP_LA = $(LDAP_LIBDIR)/libldap/libldap.la
|
LDAP_LIBLDAP_LA = $(LDAP_LIBDIR)/libldap/libldap.la
|
||||||
|
|
|
||||||
43
configure.in
43
configure.in
|
|
@ -286,6 +286,7 @@ Backends="bdb \
|
||||||
ldap \
|
ldap \
|
||||||
meta \
|
meta \
|
||||||
monitor \
|
monitor \
|
||||||
|
ndb \
|
||||||
null \
|
null \
|
||||||
passwd \
|
passwd \
|
||||||
perl \
|
perl \
|
||||||
|
|
@ -311,6 +312,8 @@ OL_ARG_ENABLE(meta,[ --enable-meta enable metadirectory backend],
|
||||||
no, [no yes mod], ol_enable_backends)dnl
|
no, [no yes mod], ol_enable_backends)dnl
|
||||||
OL_ARG_ENABLE(monitor,[ --enable-monitor enable monitor backend],
|
OL_ARG_ENABLE(monitor,[ --enable-monitor enable monitor backend],
|
||||||
yes, [no yes mod], ol_enable_backends)dnl
|
yes, [no yes mod], ol_enable_backends)dnl
|
||||||
|
OL_ARG_ENABLE(ndb,[ --enable-ndb enable MySQL NDB Cluster backend],
|
||||||
|
no, [no yes mod], ol_enable_backends)dnl
|
||||||
OL_ARG_ENABLE(null,[ --enable-null enable null backend],
|
OL_ARG_ENABLE(null,[ --enable-null enable null backend],
|
||||||
no, [no yes mod], ol_enable_backends)dnl
|
no, [no yes mod], ol_enable_backends)dnl
|
||||||
OL_ARG_ENABLE(passwd,[ --enable-passwd enable passwd backend],
|
OL_ARG_ENABLE(passwd,[ --enable-passwd enable passwd backend],
|
||||||
|
|
@ -460,6 +463,7 @@ elif test $ol_enable_modules != yes &&
|
||||||
test $ol_enable_ldap = no &&
|
test $ol_enable_ldap = no &&
|
||||||
test $ol_enable_meta = no &&
|
test $ol_enable_meta = no &&
|
||||||
test $ol_enable_monitor = no &&
|
test $ol_enable_monitor = no &&
|
||||||
|
test $ol_enable_ndb = no &&
|
||||||
test $ol_enable_null = no &&
|
test $ol_enable_null = no &&
|
||||||
test $ol_enable_passwd = no &&
|
test $ol_enable_passwd = no &&
|
||||||
test $ol_enable_perl = no &&
|
test $ol_enable_perl = no &&
|
||||||
|
|
@ -500,6 +504,8 @@ dnl ----------------------------------------------------------------
|
||||||
dnl Initialize vars
|
dnl Initialize vars
|
||||||
LDAP_LIBS=
|
LDAP_LIBS=
|
||||||
BDB_LIBS=
|
BDB_LIBS=
|
||||||
|
SLAPD_NDB_LIBS=
|
||||||
|
SLAPD_NDB_INCS=
|
||||||
LTHREAD_LIBS=
|
LTHREAD_LIBS=
|
||||||
LUTIL_LIBS=
|
LUTIL_LIBS=
|
||||||
|
|
||||||
|
|
@ -1973,6 +1979,26 @@ if test $ol_enable_sql != no ; then
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
dnl ----------------------------------------------------------------
|
||||||
|
dnl MySQL NDBapi
|
||||||
|
ol_link_ndb=no
|
||||||
|
if test $ol_enable_ndb != no ; then
|
||||||
|
AC_CHECK_PROG(MYSQL,mysql_config,yes)
|
||||||
|
if test "$MYSQL" != yes ; then
|
||||||
|
AC_MSG_ERROR([could not locate mysql_config])
|
||||||
|
fi
|
||||||
|
|
||||||
|
SQL_INC=`mysql_config --include`
|
||||||
|
SLAPD_NDB_INCS="$SQL_INC $SQL_INC/storage/ndb $SQL_INC/storage/ndb/ndbapi"
|
||||||
|
|
||||||
|
SQL_LIB=`mysql_config --libs_r`
|
||||||
|
SLAPD_NDB_LIBS="$SQL_LIB -lndbclient -lmysys -lmystrings -lstdc++"
|
||||||
|
|
||||||
|
if test "$ol_enable_ndb" = yes ; then
|
||||||
|
SLAPD_LIBS="$SLAPD_LIBS \$(SLAPD_NDB_LIBS)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
dnl ----------------------------------------------------------------
|
dnl ----------------------------------------------------------------
|
||||||
dnl International Components for Unicode
|
dnl International Components for Unicode
|
||||||
OL_ICU
|
OL_ICU
|
||||||
|
|
@ -2579,6 +2605,19 @@ if test "$ol_enable_meta" != no ; then
|
||||||
AC_DEFINE_UNQUOTED(SLAPD_META,$MFLAG,[define to support LDAP Metadirectory backend])
|
AC_DEFINE_UNQUOTED(SLAPD_META,$MFLAG,[define to support LDAP Metadirectory backend])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "$ol_enable_ndb" != no ; then
|
||||||
|
BUILD_SLAPD=yes
|
||||||
|
BUILD_NDB=$ol_enable_ndb
|
||||||
|
if test "$ol_enable_ndb" = mod ; then
|
||||||
|
SLAPD_DYNAMIC_BACKENDS="$SLAPD_DYNAMIC_BACKENDS back-ndb"
|
||||||
|
MFLAG=SLAPD_MOD_DYNAMIC
|
||||||
|
else
|
||||||
|
SLAPD_STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS back-ndb"
|
||||||
|
MFLAG=SLAPD_MOD_STATIC
|
||||||
|
fi
|
||||||
|
AC_DEFINE_UNQUOTED(SLAPD_NDB,$MFLAG,[define to support NDB backend])
|
||||||
|
fi
|
||||||
|
|
||||||
if test "$ol_enable_null" != no ; then
|
if test "$ol_enable_null" != no ; then
|
||||||
BUILD_SLAPD=yes
|
BUILD_SLAPD=yes
|
||||||
BUILD_NULL=$ol_enable_null
|
BUILD_NULL=$ol_enable_null
|
||||||
|
|
@ -2923,6 +2962,7 @@ dnl backends
|
||||||
AC_SUBST(BUILD_LDAP)
|
AC_SUBST(BUILD_LDAP)
|
||||||
AC_SUBST(BUILD_META)
|
AC_SUBST(BUILD_META)
|
||||||
AC_SUBST(BUILD_MONITOR)
|
AC_SUBST(BUILD_MONITOR)
|
||||||
|
AC_SUBST(BUILD_NDB)
|
||||||
AC_SUBST(BUILD_NULL)
|
AC_SUBST(BUILD_NULL)
|
||||||
AC_SUBST(BUILD_PASSWD)
|
AC_SUBST(BUILD_PASSWD)
|
||||||
AC_SUBST(BUILD_RELAY)
|
AC_SUBST(BUILD_RELAY)
|
||||||
|
|
@ -2954,6 +2994,8 @@ dnl overlays
|
||||||
AC_SUBST(LDAP_LIBS)
|
AC_SUBST(LDAP_LIBS)
|
||||||
AC_SUBST(SLAPD_LIBS)
|
AC_SUBST(SLAPD_LIBS)
|
||||||
AC_SUBST(BDB_LIBS)
|
AC_SUBST(BDB_LIBS)
|
||||||
|
AC_SUBST(SLAPD_NDB_LIBS)
|
||||||
|
AC_SUBST(SLAPD_NDB_INCS)
|
||||||
AC_SUBST(LTHREAD_LIBS)
|
AC_SUBST(LTHREAD_LIBS)
|
||||||
AC_SUBST(LUTIL_LIBS)
|
AC_SUBST(LUTIL_LIBS)
|
||||||
AC_SUBST(WRAP_LIBS)
|
AC_SUBST(WRAP_LIBS)
|
||||||
|
|
@ -3024,6 +3066,7 @@ AC_CONFIG_FILES([Makefile:build/top.mk:Makefile.in:build/dir.mk]
|
||||||
[servers/slapd/back-ldif/Makefile:build/top.mk:servers/slapd/back-ldif/Makefile.in:build/mod.mk]
|
[servers/slapd/back-ldif/Makefile:build/top.mk:servers/slapd/back-ldif/Makefile.in:build/mod.mk]
|
||||||
[servers/slapd/back-meta/Makefile:build/top.mk:servers/slapd/back-meta/Makefile.in:build/mod.mk]
|
[servers/slapd/back-meta/Makefile:build/top.mk:servers/slapd/back-meta/Makefile.in:build/mod.mk]
|
||||||
[servers/slapd/back-monitor/Makefile:build/top.mk:servers/slapd/back-monitor/Makefile.in:build/mod.mk]
|
[servers/slapd/back-monitor/Makefile:build/top.mk:servers/slapd/back-monitor/Makefile.in:build/mod.mk]
|
||||||
|
[servers/slapd/back-ndb/Makefile:build/top.mk:servers/slapd/back-ndb/Makefile.in:build/mod.mk]
|
||||||
[servers/slapd/back-null/Makefile:build/top.mk:servers/slapd/back-null/Makefile.in:build/mod.mk]
|
[servers/slapd/back-null/Makefile:build/top.mk:servers/slapd/back-null/Makefile.in:build/mod.mk]
|
||||||
[servers/slapd/back-passwd/Makefile:build/top.mk:servers/slapd/back-passwd/Makefile.in:build/mod.mk]
|
[servers/slapd/back-passwd/Makefile:build/top.mk:servers/slapd/back-passwd/Makefile.in:build/mod.mk]
|
||||||
[servers/slapd/back-perl/Makefile:build/top.mk:servers/slapd/back-perl/Makefile.in:build/mod.mk]
|
[servers/slapd/back-perl/Makefile:build/top.mk:servers/slapd/back-perl/Makefile.in:build/mod.mk]
|
||||||
|
|
|
||||||
125
doc/man/man5/slapd-ndb.5
Normal file
125
doc/man/man5/slapd-ndb.5
Normal file
|
|
@ -0,0 +1,125 @@
|
||||||
|
.TH SLAPD-NDB 5 "RELEASEDATE" "OpenLDAP LDVERSION"
|
||||||
|
.\" Copyright 2008 The OpenLDAP Foundation All Rights Reserved.
|
||||||
|
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||||
|
.\" $OpenLDAP$
|
||||||
|
.SH NAME
|
||||||
|
slapd-ndb \- MySQL NDB backend to slapd
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B ETCDIR/slapd.conf
|
||||||
|
.SH DESCRIPTION
|
||||||
|
The \fBndb\fP backend to
|
||||||
|
.BR slapd (8)
|
||||||
|
uses the MySQL Cluster package to store data, through its NDB API.
|
||||||
|
It provides fault tolerance with extreme scalability, along with
|
||||||
|
a degree of SQL compatibility.
|
||||||
|
.LP
|
||||||
|
This backend is designed to store LDAP information using tables that
|
||||||
|
are also visible from SQL. It uses a higher level SQL API for creating
|
||||||
|
these tables, while using the low level NDB API for storing and
|
||||||
|
retrieving the data within these tables. The NDB Cluster engine
|
||||||
|
allows data to be partitioned across multiple data nodes, and this
|
||||||
|
backend allows multiple slapd instances to operate against a given
|
||||||
|
database concurrently.
|
||||||
|
.LP
|
||||||
|
The general approach is to use distinct tables for each LDAP object class.
|
||||||
|
Entries comprised of multiple object classes will have their data
|
||||||
|
spread across multiple tables. The data tables use a 64 bit entryID
|
||||||
|
as their primary key. The DIT hierarchy is maintained in a separate
|
||||||
|
table, which maps DNs to entryIDs.
|
||||||
|
.LP
|
||||||
|
This backend is experimental. While intended to be a general-purpose
|
||||||
|
backend, it is currently missing a number of common LDAP features.
|
||||||
|
See the \fBTODO\fP file in the source directory for details.
|
||||||
|
.SH CONFIGURATION
|
||||||
|
These
|
||||||
|
.B slapd.conf
|
||||||
|
options apply to the \fBndb\fP backend database.
|
||||||
|
That is, they must follow a "database ndb" line and
|
||||||
|
come before any subsequent "backend" or "database" lines.
|
||||||
|
Other database options are described in the
|
||||||
|
.BR slapd.conf (5)
|
||||||
|
manual page.
|
||||||
|
|
||||||
|
.SH DATA SOURCE CONFIGURATION
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B dbhost <hostname>
|
||||||
|
The name or IP address of the host running the MySQL server. The default
|
||||||
|
is "localhost". On Unix systems, the connection to a local server is made
|
||||||
|
using a Unix Domain socket, whose path is specified using the
|
||||||
|
.B dbsocket
|
||||||
|
directive.
|
||||||
|
.TP
|
||||||
|
.B dbuser <username>
|
||||||
|
The MySQL login ID to use when connecting to the MySQL server. The chosen
|
||||||
|
user must have sufficient privileges to manipulate the SQL tables in the
|
||||||
|
target database.
|
||||||
|
.TP
|
||||||
|
.B dbpasswd <password>
|
||||||
|
The password for the \fBdbuser\fP.
|
||||||
|
.TP
|
||||||
|
.B dbname <database name>
|
||||||
|
The name of the MySQL database to use.
|
||||||
|
.TP
|
||||||
|
.B dbport <port>
|
||||||
|
The port number to use for the TCP connection to the MySQL server.
|
||||||
|
.TP
|
||||||
|
.B dbsocket <path>
|
||||||
|
The socket to be used for connecting to a local MySQL server.
|
||||||
|
.TP
|
||||||
|
.B dbflag <integer>
|
||||||
|
Client flags for the MySQL session. See the MySQL documentation for details.
|
||||||
|
.TP
|
||||||
|
.B dbconnect <connectstring>
|
||||||
|
The name or IP address of the host running the cluster manager. The default
|
||||||
|
is "localhost".
|
||||||
|
.TP
|
||||||
|
.B dbconnections <integer>
|
||||||
|
The number of cluster connections to establish. Using up to 4 may improve
|
||||||
|
performance under heavier load. The default is 1.
|
||||||
|
|
||||||
|
.SH SCHEMA CONFIGURATION
|
||||||
|
.TP
|
||||||
|
.B attrlen <attribute> <length>
|
||||||
|
Specify the column length to use for a particular attribute. LDAP attributes are
|
||||||
|
stored in individual columns of the SQL tables. The maximum column lengths for
|
||||||
|
each column must be specified when creating these tables. If a length constraint
|
||||||
|
was specified in the attribute's LDAP schema definition, that value will be used
|
||||||
|
by default. If the schema didn't specify a constraint, the default is 128 bytes.
|
||||||
|
Currently the maximum is 1024.
|
||||||
|
.TP
|
||||||
|
.B index <attr[,attr...]>
|
||||||
|
Specify a list of attributes for which indexing should be maintained.
|
||||||
|
Currently there is no support for substring indexing; a single index structure
|
||||||
|
provides presence, equality, and inequality indexing for the specified attributes.
|
||||||
|
.TP
|
||||||
|
.B attrset <set> <attrs>
|
||||||
|
Specify a list of attributes to be treated as an attribute set. This directive
|
||||||
|
creates a table named \fIset\fP which will contain all of the listed attributes.
|
||||||
|
Ordinarily an attribute resides in a table named by an object class that uses
|
||||||
|
the attribute. However, attributes are only allowed to appear in a single table.
|
||||||
|
For attributes that are derived from an inherited object class definition,
|
||||||
|
the attribute will only be stored in the superior class's table.
|
||||||
|
Attribute sets should be defined for any attributes that are used in multiple
|
||||||
|
unrelated object classes, i.e., classes that are not connected by a simple
|
||||||
|
inheritance chain.
|
||||||
|
.SH ACCESS CONTROL
|
||||||
|
The
|
||||||
|
.B ndb
|
||||||
|
backend honors most access control semantics as indicated in
|
||||||
|
.BR slapd.access (5).
|
||||||
|
.SH FILES
|
||||||
|
.TP
|
||||||
|
.B ETCDIR/slapd.conf
|
||||||
|
default
|
||||||
|
.B slapd
|
||||||
|
configuration file
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR slapd.conf (5),
|
||||||
|
.BR slapd (8),
|
||||||
|
.BR slapadd (8),
|
||||||
|
.BR slapcat (8),
|
||||||
|
.BR slapindex (8),
|
||||||
|
MySQL Cluster documentation.
|
||||||
|
.SH AUTHOR
|
||||||
|
Howard Chu, with assistance from Johan Andersson et al @ MySQL.
|
||||||
|
|
@ -71,6 +71,11 @@ daemon. Only a single instance of the
|
||||||
.B monitor
|
.B monitor
|
||||||
backend may be defined.
|
backend may be defined.
|
||||||
.TP
|
.TP
|
||||||
|
.B ndb
|
||||||
|
This backend is experimental.
|
||||||
|
It uses the transactional database interface of the MySQL Cluster Engine
|
||||||
|
(NDB) to store data.
|
||||||
|
.TP
|
||||||
.B null
|
.B null
|
||||||
Operations in this backend succeed but do nothing.
|
Operations in this backend succeed but do nothing.
|
||||||
.TP
|
.TP
|
||||||
|
|
|
||||||
|
|
@ -945,6 +945,9 @@
|
||||||
/* define to support cn=Monitor backend */
|
/* define to support cn=Monitor backend */
|
||||||
#undef SLAPD_MONITOR
|
#undef SLAPD_MONITOR
|
||||||
|
|
||||||
|
/* define to support NDB backend */
|
||||||
|
#undef SLAPD_NDB
|
||||||
|
|
||||||
/* define to support NULL backend */
|
/* define to support NULL backend */
|
||||||
#undef SLAPD_NULL
|
#undef SLAPD_NULL
|
||||||
|
|
||||||
|
|
|
||||||
59
servers/slapd/back-ndb/Makefile.in
Normal file
59
servers/slapd/back-ndb/Makefile.in
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
# Makefile.in for back-ndb
|
||||||
|
# $OpenLDAP$
|
||||||
|
## This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||||
|
##
|
||||||
|
## Copyright 2008 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>.
|
||||||
|
##
|
||||||
|
## ACKNOWLEDGEMENTS:
|
||||||
|
## This work was initially developed by Howard Chu for inclusion
|
||||||
|
## in OpenLDAP Software. This work was sponsored by MySQL.
|
||||||
|
|
||||||
|
SRCS = init.cpp tools.cpp config.cpp ndbio.cpp \
|
||||||
|
add.cpp bind.cpp compare.cpp delete.cpp modify.cpp modrdn.cpp search.cpp
|
||||||
|
|
||||||
|
OBJS = init.lo tools.lo config.lo ndbio.lo \
|
||||||
|
add.lo bind.lo compare.lo delete.lo modify.lo modrdn.lo search.lo
|
||||||
|
|
||||||
|
LDAP_INCDIR= ../../../include
|
||||||
|
LDAP_LIBDIR= ../../../libraries
|
||||||
|
|
||||||
|
BUILD_OPT = "--enable-ndb"
|
||||||
|
BUILD_MOD = @BUILD_NDB@
|
||||||
|
|
||||||
|
mod_DEFS = -DSLAPD_IMPORT
|
||||||
|
MOD_DEFS = $(@BUILD_NDB@_DEFS)
|
||||||
|
MOD_LIBS = $(SLAPD_NDB_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_ndb
|
||||||
|
|
||||||
|
XINCPATH = -I.. -I$(srcdir)/.. @SLAPD_NDB_INCS@
|
||||||
|
XDEFS = $(MODULES_CPPFLAGS)
|
||||||
|
|
||||||
|
AC_CXX = g++
|
||||||
|
CXX = $(AC_CXX)
|
||||||
|
LTCXX_MOD = $(LIBTOOL) $(LTONLY_MOD) --mode=compile \
|
||||||
|
$(CXX) $(LT_CFLAGS) $(LT_CPPFLAGS) $(MOD_DEFS) -c
|
||||||
|
|
||||||
|
all-local-lib: ../.backend
|
||||||
|
|
||||||
|
.SUFFIXES: .c .o .lo .cpp
|
||||||
|
|
||||||
|
.cpp.lo:
|
||||||
|
$(LTCXX_MOD) $<
|
||||||
|
|
||||||
|
../.backend: lib$(LIBBASE).a
|
||||||
|
@touch $@
|
||||||
|
|
||||||
6
servers/slapd/back-ndb/TODO
Normal file
6
servers/slapd/back-ndb/TODO
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
LDAP features not currently supported:
|
||||||
|
|
||||||
|
tagged attributes
|
||||||
|
aliases
|
||||||
|
substring indexing
|
||||||
|
subtree rename
|
||||||
333
servers/slapd/back-ndb/add.cpp
Normal file
333
servers/slapd/back-ndb/add.cpp
Normal file
|
|
@ -0,0 +1,333 @@
|
||||||
|
/* add.cpp - ldap NDB back-end add routine */
|
||||||
|
/* $OpenLDAP$ */
|
||||||
|
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||||
|
*
|
||||||
|
* Copyright 2008 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>.
|
||||||
|
*/
|
||||||
|
/* ACKNOWLEDGEMENTS:
|
||||||
|
* This work was initially developed by Howard Chu for inclusion
|
||||||
|
* in OpenLDAP Software. This work was sponsored by MySQL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "portable.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ac/string.h>
|
||||||
|
|
||||||
|
#include "back-ndb.h"
|
||||||
|
|
||||||
|
extern "C" int
|
||||||
|
ndb_back_add(Operation *op, SlapReply *rs )
|
||||||
|
{
|
||||||
|
struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private;
|
||||||
|
Entry p = {0};
|
||||||
|
Attribute poc;
|
||||||
|
char textbuf[SLAP_TEXT_BUFLEN];
|
||||||
|
size_t textlen = sizeof textbuf;
|
||||||
|
AttributeDescription *children = slap_schema.si_ad_children;
|
||||||
|
AttributeDescription *entry = slap_schema.si_ad_entry;
|
||||||
|
NdbArgs NA;
|
||||||
|
NdbRdns rdns;
|
||||||
|
struct berval matched;
|
||||||
|
struct berval pdn, pndn;
|
||||||
|
|
||||||
|
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(ndb_back_add) ": %s\n",
|
||||||
|
op->oq_add.rs_e->e_name.bv_val, 0, 0);
|
||||||
|
|
||||||
|
ctrls[num_ctrls] = 0;
|
||||||
|
|
||||||
|
/* check entry's schema */
|
||||||
|
rs->sr_err = entry_schema_check( op, op->oq_add.rs_e, NULL,
|
||||||
|
get_relax(op), 1, &rs->sr_text, textbuf, textlen );
|
||||||
|
if ( rs->sr_err != LDAP_SUCCESS ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_add) ": entry failed schema check: "
|
||||||
|
"%s (%d)\n", rs->sr_text, rs->sr_err, 0 );
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add opattrs to shadow as well, only missing attrs will actually
|
||||||
|
* be added; helps compatibility with older OL versions */
|
||||||
|
rs->sr_err = slap_add_opattrs( op, &rs->sr_text, textbuf, textlen, 1 );
|
||||||
|
if ( rs->sr_err != LDAP_SUCCESS ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_add) ": entry failed op attrs add: "
|
||||||
|
"%s (%d)\n", rs->sr_text, rs->sr_err, 0 );
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get our NDB handle */
|
||||||
|
rs->sr_err = ndb_thread_handle( op, &NA.ndb );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the parent dn and see if the corresponding entry exists.
|
||||||
|
*/
|
||||||
|
if ( be_issuffix( op->o_bd, &op->oq_add.rs_e->e_nname ) ) {
|
||||||
|
pdn = slap_empty_bv;
|
||||||
|
pndn = slap_empty_bv;
|
||||||
|
} else {
|
||||||
|
dnParent( &op->ora_e->e_name, &pdn );
|
||||||
|
dnParent( &op->ora_e->e_nname, &pndn );
|
||||||
|
}
|
||||||
|
p.e_name = op->ora_e->e_name;
|
||||||
|
p.e_nname = op->ora_e->e_nname;
|
||||||
|
|
||||||
|
op->ora_e->e_id = NOID;
|
||||||
|
rdns.nr_num = 0;
|
||||||
|
NA.rdns = &rdns;
|
||||||
|
|
||||||
|
if( 0 ) {
|
||||||
|
retry: /* transaction retry */
|
||||||
|
NA.txn->close();
|
||||||
|
NA.txn = NULL;
|
||||||
|
if ( op->o_abandon ) {
|
||||||
|
rs->sr_err = SLAPD_ABANDON;
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
ndb_trans_backoff( ++num_retries );
|
||||||
|
}
|
||||||
|
|
||||||
|
NA.txn = NA.ndb->startTransaction();
|
||||||
|
rs->sr_text = NULL;
|
||||||
|
if( !NA.txn ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_add) ": startTransaction failed: %s (%d)\n",
|
||||||
|
NA.ndb->getNdbError().message, NA.ndb->getNdbError().code, 0 );
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
rs->sr_text = "internal error";
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get entry or parent */
|
||||||
|
NA.e = &p;
|
||||||
|
NA.ocs = NULL;
|
||||||
|
rs->sr_err = ndb_entry_get_info( op, &NA, 0, &matched );
|
||||||
|
switch( rs->sr_err ) {
|
||||||
|
case 0:
|
||||||
|
rs->sr_err = LDAP_ALREADY_EXISTS;
|
||||||
|
goto return_results;
|
||||||
|
case LDAP_NO_SUCH_OBJECT:
|
||||||
|
break;
|
||||||
|
#if 0
|
||||||
|
case DB_LOCK_DEADLOCK:
|
||||||
|
case DB_LOCK_NOTGRANTED:
|
||||||
|
goto retry;
|
||||||
|
#endif
|
||||||
|
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 ( NA.ocs ) {
|
||||||
|
int i;
|
||||||
|
for ( i=0; !BER_BVISNULL( &NA.ocs[i] ); i++ );
|
||||||
|
poc.a_numvals = i;
|
||||||
|
poc.a_desc = slap_schema.si_ad_objectClass;
|
||||||
|
poc.a_vals = NA.ocs;
|
||||||
|
poc.a_nvals = poc.a_vals;
|
||||||
|
poc.a_next = NULL;
|
||||||
|
p.e_attrs = &poc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ber_bvstrcasecmp( &pndn, &matched ) ) {
|
||||||
|
rs->sr_matched = matched.bv_val;
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_add) ": parent "
|
||||||
|
"does not exist\n", 0, 0, 0 );
|
||||||
|
|
||||||
|
rs->sr_text = "parent does not exist";
|
||||||
|
rs->sr_err = LDAP_NO_SUCH_OBJECT;
|
||||||
|
if ( p.e_attrs && is_entry_referral( &p )) {
|
||||||
|
is_ref: p.e_attrs = NULL;
|
||||||
|
ndb_entry_get_data( op, &NA, 0 );
|
||||||
|
rs->sr_ref = get_entry_referrals( op, &p );
|
||||||
|
rs->sr_err = LDAP_REFERRAL;
|
||||||
|
rs->sr_flags = REP_REF_MUSTBEFREED;
|
||||||
|
attrs_free( p.e_attrs );
|
||||||
|
p.e_attrs = NULL;
|
||||||
|
}
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.e_name = pdn;
|
||||||
|
p.e_nname = pndn;
|
||||||
|
rs->sr_err = access_allowed( op, &p,
|
||||||
|
children, NULL, ACL_WADD, NULL );
|
||||||
|
|
||||||
|
if ( ! rs->sr_err ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_add) ": no write access to parent\n",
|
||||||
|
0, 0, 0 );
|
||||||
|
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
||||||
|
rs->sr_text = "no write access to parent";
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( NA.ocs ) {
|
||||||
|
if ( is_entry_subentry( &p )) {
|
||||||
|
/* parent is a subentry, don't allow add */
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_add) ": parent is subentry\n",
|
||||||
|
0, 0, 0 );
|
||||||
|
rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION;
|
||||||
|
rs->sr_text = "parent is a subentry";
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( is_entry_alias( &p ) ) {
|
||||||
|
/* parent is an alias, don't allow add */
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_add) ": parent is alias\n",
|
||||||
|
0, 0, 0 );
|
||||||
|
rs->sr_err = LDAP_ALIAS_PROBLEM;
|
||||||
|
rs->sr_text = "parent is an alias";
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( is_entry_referral( &p ) ) {
|
||||||
|
/* parent is a referral, don't allow add */
|
||||||
|
rs->sr_matched = p.e_name.bv_val;
|
||||||
|
goto is_ref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rs->sr_err = access_allowed( op, op->ora_e,
|
||||||
|
entry, NULL, ACL_WADD, NULL );
|
||||||
|
|
||||||
|
if ( ! rs->sr_err ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_add) ": no write access to entry\n",
|
||||||
|
0, 0, 0 );
|
||||||
|
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
||||||
|
rs->sr_text = "no write access to entry";
|
||||||
|
goto return_results;;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* acquire entry ID */
|
||||||
|
if ( op->ora_e->e_id == NOID ) {
|
||||||
|
rs->sr_err = ndb_next_id( op->o_bd, NA.ndb, &op->ora_e->e_id );
|
||||||
|
if( rs->sr_err != 0 ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_add) ": next_id failed (%d)\n",
|
||||||
|
rs->sr_err, 0, 0 );
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
rs->sr_text = "internal error";
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( matched.bv_val )
|
||||||
|
rdns.nr_num++;
|
||||||
|
NA.e = op->ora_e;
|
||||||
|
/* dn2id index */
|
||||||
|
rs->sr_err = ndb_entry_put_info( op->o_bd, &NA, 0 );
|
||||||
|
if ( rs->sr_err ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_add) ": ndb_entry_put_info failed (%d)\n",
|
||||||
|
rs->sr_err, 0, 0 );
|
||||||
|
rs->sr_text = "internal error";
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* id2entry index */
|
||||||
|
rs->sr_err = ndb_entry_put_data( op->o_bd, &NA );
|
||||||
|
if ( rs->sr_err ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_add) ": ndb_entry_put_data failed (%d) %s(%d)\n",
|
||||||
|
rs->sr_err, NA.txn->getNdbError().message, NA.txn->getNdbError().code );
|
||||||
|
rs->sr_text = "internal error";
|
||||||
|
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->oq_add.rs_e,
|
||||||
|
&slap_post_read_bv, postread_ctrl ) )
|
||||||
|
{
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
"<=- " LDAP_XSTRING(ndb_back_add) ": post-read "
|
||||||
|
"failed!\n", 0, 0, 0 );
|
||||||
|
if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
|
||||||
|
/* FIXME: is it correct to abort
|
||||||
|
* operation if control fails? */
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( op->o_noop ) {
|
||||||
|
if (( rs->sr_err=NA.txn->execute( NdbTransaction::Rollback,
|
||||||
|
NdbOperation::AbortOnError, 1 )) != 0 ) {
|
||||||
|
rs->sr_text = "txn (no-op) failed";
|
||||||
|
} else {
|
||||||
|
rs->sr_err = LDAP_X_NO_OPERATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if(( rs->sr_err=NA.txn->execute( NdbTransaction::Commit,
|
||||||
|
NdbOperation::AbortOnError, 1 )) != 0 ) {
|
||||||
|
rs->sr_text = "txn_commit failed";
|
||||||
|
} else {
|
||||||
|
rs->sr_err = LDAP_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( rs->sr_err != LDAP_SUCCESS && rs->sr_err != LDAP_X_NO_OPERATION ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_add) ": %s : %s (%d)\n",
|
||||||
|
rs->sr_text, NA.txn->getNdbError().message, NA.txn->getNdbError().code );
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
NA.txn->close();
|
||||||
|
NA.txn = NULL;
|
||||||
|
|
||||||
|
Debug(LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_add) ": added%s id=%08lx dn=\"%s\"\n",
|
||||||
|
op->o_noop ? " (no-op)" : "",
|
||||||
|
op->oq_add.rs_e->e_id, op->oq_add.rs_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 );
|
||||||
|
slap_graduate_commit_csn( op );
|
||||||
|
|
||||||
|
if( NA.txn != NULL ) {
|
||||||
|
NA.txn->execute( Rollback );
|
||||||
|
NA.txn->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
36
servers/slapd/back-ndb/attrsets.conf
Normal file
36
servers/slapd/back-ndb/attrsets.conf
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
# Definition of useful attribute sets
|
||||||
|
# from X.521 section 5
|
||||||
|
#
|
||||||
|
# TelecommunicationAttributeSet ATTRIBUTE ::= {
|
||||||
|
# facsimileTelephoneNumber |
|
||||||
|
# internationalISDNNumber |
|
||||||
|
# telephoneNumber |
|
||||||
|
# teletexTerminalIdentifier |
|
||||||
|
# telexNumber |
|
||||||
|
# preferredDeliveryMethod |
|
||||||
|
# destinationIndicator |
|
||||||
|
# registeredAddress |
|
||||||
|
# x121Address }
|
||||||
|
#
|
||||||
|
# PostalAttributeSet ATTRIBUTE ::= {
|
||||||
|
# physicalDeliveryOfficeName |
|
||||||
|
# postalAddress |
|
||||||
|
# postalCode |
|
||||||
|
# postOfficeBox |
|
||||||
|
# streetAddress }
|
||||||
|
#
|
||||||
|
# LocaleAttributeSet ATTRIBUTE ::= {
|
||||||
|
# localityName |
|
||||||
|
# stateOrProvinceName |
|
||||||
|
# streetAddress }
|
||||||
|
#
|
||||||
|
# OrganizationalAttributeSet ATTRIBUTE ::= {
|
||||||
|
# description |
|
||||||
|
# LocaleAttributeSet |
|
||||||
|
# PostalAttributeSet |
|
||||||
|
# TelecommunicationAttributeSet |
|
||||||
|
# businessCategory |
|
||||||
|
# seeAlso |
|
||||||
|
# searchGuide |
|
||||||
|
# userPassword }
|
||||||
|
|
||||||
168
servers/slapd/back-ndb/back-ndb.h
Normal file
168
servers/slapd/back-ndb/back-ndb.h
Normal file
|
|
@ -0,0 +1,168 @@
|
||||||
|
/* $OpenLDAP$ */
|
||||||
|
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||||
|
*
|
||||||
|
* Copyright 2008 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>.
|
||||||
|
*/
|
||||||
|
/* ACKNOWLEDGEMENTS:
|
||||||
|
* This work was initially developed by Howard Chu for inclusion
|
||||||
|
* in OpenLDAP Software. This work was sponsored by MySQL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SLAPD_NDB_H
|
||||||
|
#define SLAPD_NDB_H
|
||||||
|
|
||||||
|
#include "slap.h"
|
||||||
|
|
||||||
|
#include <mysql.h>
|
||||||
|
#include <NdbApi.hpp>
|
||||||
|
|
||||||
|
LDAP_BEGIN_DECL
|
||||||
|
|
||||||
|
/* The general design is to use one relational table per objectclass. This is
|
||||||
|
* complicated by objectclass inheritance and auxiliary classes though.
|
||||||
|
*
|
||||||
|
* Attributes must only occur in a single table. For objectclasses that inherit
|
||||||
|
* from other classes, attributes defined in the superior class are only stored
|
||||||
|
* in the superior class' table. When multiple unrelated classes define the same
|
||||||
|
* attributes, an attributeSet should be defined instead, containing all of the
|
||||||
|
* common attributes.
|
||||||
|
*
|
||||||
|
* The no_set table lists which other attributeSets apply to the current
|
||||||
|
* objectClass. The no_attrs table lists all of the non-inherited attributes of
|
||||||
|
* the class, including those residing in an attributeSet.
|
||||||
|
*
|
||||||
|
* Usually the table is named identically to the objectClass, but it can also
|
||||||
|
* be explicitly named something else if needed.
|
||||||
|
*/
|
||||||
|
#define NDB_MAX_OCSETS 8
|
||||||
|
|
||||||
|
struct ndb_attrinfo;
|
||||||
|
|
||||||
|
typedef struct ndb_ocinfo {
|
||||||
|
struct berval no_name; /* objectclass cname */
|
||||||
|
struct berval no_table;
|
||||||
|
ObjectClass *no_oc;
|
||||||
|
struct ndb_ocinfo *no_sets[NDB_MAX_OCSETS];
|
||||||
|
struct ndb_attrinfo **no_attrs;
|
||||||
|
int no_flag;
|
||||||
|
int no_nsets;
|
||||||
|
int no_nattrs;
|
||||||
|
} NdbOcInfo;
|
||||||
|
|
||||||
|
#define NDB_INFO_ATLEN 0x01
|
||||||
|
#define NDB_INFO_ATSET 0x02
|
||||||
|
#define NDB_INFO_INDEX 0x04
|
||||||
|
#define NDB_INFO_ATBLOB 0x08
|
||||||
|
|
||||||
|
typedef struct ndb_attrinfo {
|
||||||
|
struct berval na_name; /* attribute cname */
|
||||||
|
AttributeDescription *na_desc;
|
||||||
|
AttributeType *na_attr;
|
||||||
|
NdbOcInfo *na_oi;
|
||||||
|
int na_flag;
|
||||||
|
int na_len;
|
||||||
|
int na_column;
|
||||||
|
int na_ixcol;
|
||||||
|
} NdbAttrInfo;
|
||||||
|
|
||||||
|
typedef struct ListNode {
|
||||||
|
struct ListNode *ln_next;
|
||||||
|
void *ln_data;
|
||||||
|
} ListNode;
|
||||||
|
|
||||||
|
#define NDB_IS_OPEN(ni) (ni->ni_cluster != NULL)
|
||||||
|
|
||||||
|
struct ndb_info {
|
||||||
|
/* NDB connection */
|
||||||
|
char *ni_connectstr;
|
||||||
|
char *ni_dbname;
|
||||||
|
Ndb_cluster_connection **ni_cluster;
|
||||||
|
|
||||||
|
/* MySQL connection parameters */
|
||||||
|
MYSQL ni_sql;
|
||||||
|
char *ni_hostname;
|
||||||
|
char *ni_username;
|
||||||
|
char *ni_password;
|
||||||
|
char *ni_socket;
|
||||||
|
unsigned long ni_clflag;
|
||||||
|
unsigned int ni_port;
|
||||||
|
|
||||||
|
/* Search filter processing */
|
||||||
|
int ni_search_stack_depth;
|
||||||
|
void *ni_search_stack;
|
||||||
|
|
||||||
|
#define DEFAULT_SEARCH_STACK_DEPTH 16
|
||||||
|
#define MINIMUM_SEARCH_STACK_DEPTH 8
|
||||||
|
|
||||||
|
/* Schema config */
|
||||||
|
NdbOcInfo *ni_opattrs;
|
||||||
|
ListNode *ni_attridxs;
|
||||||
|
ListNode *ni_attrlens;
|
||||||
|
ListNode *ni_attrsets;
|
||||||
|
ListNode *ni_attrblobs;
|
||||||
|
ldap_pvt_thread_rdwr_t ni_ai_rwlock;
|
||||||
|
Avlnode *ni_ai_tree;
|
||||||
|
ldap_pvt_thread_rdwr_t ni_oc_rwlock;
|
||||||
|
Avlnode *ni_oc_tree;
|
||||||
|
int ni_nconns; /* number of connections to open */
|
||||||
|
int ni_nextconn; /* next conn to use */
|
||||||
|
ldap_pvt_thread_mutex_t ni_conn_mutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NDB_MAX_RDNS 16
|
||||||
|
#define NDB_RDN_LEN 128
|
||||||
|
#define NDB_MAX_OCS 64
|
||||||
|
|
||||||
|
#define DN2ID_TABLE "OL_dn2id"
|
||||||
|
#define EID_COLUMN 0U
|
||||||
|
#define VID_COLUMN 1U
|
||||||
|
#define OCS_COLUMN 1U
|
||||||
|
#define RDN_COLUMN 2U
|
||||||
|
#define IDX_COLUMN (2U+NDB_MAX_RDNS)
|
||||||
|
|
||||||
|
#define NEXTID_TABLE "OL_nextid"
|
||||||
|
|
||||||
|
#define NDB_OC_BUFLEN 1026 /* 1024 data plus 2 len bytes */
|
||||||
|
|
||||||
|
#define INDEX_NAME "OL_index"
|
||||||
|
|
||||||
|
typedef struct NdbRdns {
|
||||||
|
short nr_num;
|
||||||
|
char nr_buf[NDB_MAX_RDNS][NDB_RDN_LEN+1];
|
||||||
|
} NdbRdns;
|
||||||
|
|
||||||
|
typedef struct NdbOcs {
|
||||||
|
int no_ninfo;
|
||||||
|
int no_ntext;
|
||||||
|
int no_nitext; /* number of implicit classes */
|
||||||
|
NdbOcInfo *no_info[NDB_MAX_OCS];
|
||||||
|
struct berval no_text[NDB_MAX_OCS];
|
||||||
|
struct berval no_itext[NDB_MAX_OCS]; /* implicit classes */
|
||||||
|
} NdbOcs;
|
||||||
|
|
||||||
|
typedef struct NdbArgs {
|
||||||
|
Ndb *ndb;
|
||||||
|
NdbTransaction *txn;
|
||||||
|
Entry *e;
|
||||||
|
NdbRdns *rdns;
|
||||||
|
struct berval *ocs;
|
||||||
|
int erdns;
|
||||||
|
} NdbArgs;
|
||||||
|
|
||||||
|
#define NDB_NO_SUCH_OBJECT 626
|
||||||
|
#define NDB_ALREADY_EXISTS 630
|
||||||
|
|
||||||
|
LDAP_END_DECL
|
||||||
|
|
||||||
|
#include "proto-ndb.h"
|
||||||
|
|
||||||
|
#endif
|
||||||
163
servers/slapd/back-ndb/bind.cpp
Normal file
163
servers/slapd/back-ndb/bind.cpp
Normal file
|
|
@ -0,0 +1,163 @@
|
||||||
|
/* bind.cpp - ndb backend bind routine */
|
||||||
|
/* $OpenLDAP$ */
|
||||||
|
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||||
|
*
|
||||||
|
* Copyright 2008 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>.
|
||||||
|
*/
|
||||||
|
/* ACKNOWLEDGEMENTS:
|
||||||
|
* This work was initially developed by Howard Chu for inclusion
|
||||||
|
* in OpenLDAP Software. This work was sponsored by MySQL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "portable.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ac/string.h>
|
||||||
|
#include <ac/unistd.h>
|
||||||
|
|
||||||
|
#include "back-ndb.h"
|
||||||
|
|
||||||
|
extern "C" int
|
||||||
|
ndb_back_bind( Operation *op, SlapReply *rs )
|
||||||
|
{
|
||||||
|
struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private;
|
||||||
|
Entry e = {0};
|
||||||
|
Attribute *a;
|
||||||
|
|
||||||
|
AttributeDescription *password = slap_schema.si_ad_userPassword;
|
||||||
|
|
||||||
|
NdbArgs NA;
|
||||||
|
|
||||||
|
Debug( LDAP_DEBUG_ARGS,
|
||||||
|
"==> " LDAP_XSTRING(ndb_back_bind) ": dn: %s\n",
|
||||||
|
op->o_req_dn.bv_val, 0, 0);
|
||||||
|
|
||||||
|
/* allow noauth binds */
|
||||||
|
switch ( be_rootdn_bind( op, NULL ) ) {
|
||||||
|
case SLAP_CB_CONTINUE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return rs->sr_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get our NDB handle */
|
||||||
|
rs->sr_err = ndb_thread_handle( op, &NA.ndb );
|
||||||
|
|
||||||
|
e.e_name = op->o_req_dn;
|
||||||
|
e.e_nname = op->o_req_ndn;
|
||||||
|
NA.e = &e;
|
||||||
|
|
||||||
|
dn2entry_retry:
|
||||||
|
NA.txn = NA.ndb->startTransaction();
|
||||||
|
rs->sr_text = NULL;
|
||||||
|
if( !NA.txn ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_bind) ": startTransaction failed: %s (%d)\n",
|
||||||
|
NA.ndb->getNdbError().message, NA.ndb->getNdbError().code, 0 );
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
rs->sr_text = "internal error";
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get entry */
|
||||||
|
{
|
||||||
|
NdbRdns rdns;
|
||||||
|
rdns.nr_num = 0;
|
||||||
|
NA.rdns = &rdns;
|
||||||
|
NA.ocs = NULL;
|
||||||
|
rs->sr_err = ndb_entry_get_info( op, &NA, 0, NULL );
|
||||||
|
}
|
||||||
|
switch(rs->sr_err) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case LDAP_NO_SUCH_OBJECT:
|
||||||
|
rs->sr_err = LDAP_INVALID_CREDENTIALS;
|
||||||
|
goto done;
|
||||||
|
case LDAP_BUSY:
|
||||||
|
rs->sr_text = "ldap_server_busy";
|
||||||
|
goto done;
|
||||||
|
#if 0
|
||||||
|
case DB_LOCK_DEADLOCK:
|
||||||
|
case DB_LOCK_NOTGRANTED:
|
||||||
|
goto dn2entry_retry;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
rs->sr_text = "internal error";
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
rs->sr_err = ndb_entry_get_data( op, &NA, 0 );
|
||||||
|
ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx );
|
||||||
|
ber_dupbv( &op->oq_bind.rb_edn, &e.e_name );
|
||||||
|
|
||||||
|
/* check for deleted */
|
||||||
|
if ( is_entry_subentry( &e ) ) {
|
||||||
|
/* entry is an subentry, don't allow bind */
|
||||||
|
Debug( LDAP_DEBUG_TRACE, "entry is subentry\n", 0,
|
||||||
|
0, 0 );
|
||||||
|
rs->sr_err = LDAP_INVALID_CREDENTIALS;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( is_entry_alias( &e ) ) {
|
||||||
|
/* entry is an alias, don't allow bind */
|
||||||
|
Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0, 0, 0 );
|
||||||
|
rs->sr_err = LDAP_INVALID_CREDENTIALS;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( is_entry_referral( &e ) ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
|
||||||
|
0, 0 );
|
||||||
|
rs->sr_err = LDAP_INVALID_CREDENTIALS;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ( op->oq_bind.rb_method ) {
|
||||||
|
case LDAP_AUTH_SIMPLE:
|
||||||
|
a = attr_find( e.e_attrs, password );
|
||||||
|
if ( a == NULL ) {
|
||||||
|
rs->sr_err = LDAP_INVALID_CREDENTIALS;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( slap_passwd_check( op, &e, a, &op->oq_bind.rb_cred,
|
||||||
|
&rs->sr_text ) != 0 )
|
||||||
|
{
|
||||||
|
/* failure; stop front end from sending result */
|
||||||
|
rs->sr_err = LDAP_INVALID_CREDENTIALS;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
rs->sr_err = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert( 0 ); /* should not be reachable */
|
||||||
|
rs->sr_err = LDAP_STRONG_AUTH_NOT_SUPPORTED;
|
||||||
|
rs->sr_text = "authentication method not supported";
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
NA.txn->close();
|
||||||
|
if ( e.e_attrs ) {
|
||||||
|
attrs_free( e.e_attrs );
|
||||||
|
e.e_attrs = NULL;
|
||||||
|
}
|
||||||
|
if ( rs->sr_err ) {
|
||||||
|
send_ldap_result( op, rs );
|
||||||
|
}
|
||||||
|
/* front end will send result on success (rs->sr_err==0) */
|
||||||
|
return rs->sr_err;
|
||||||
|
}
|
||||||
169
servers/slapd/back-ndb/compare.cpp
Normal file
169
servers/slapd/back-ndb/compare.cpp
Normal file
|
|
@ -0,0 +1,169 @@
|
||||||
|
/* compare.cpp - ndb backend compare routine */
|
||||||
|
/* $OpenLDAP$ */
|
||||||
|
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||||
|
*
|
||||||
|
* Copyright 2008 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>.
|
||||||
|
*/
|
||||||
|
/* ACKNOWLEDGEMENTS:
|
||||||
|
* This work was initially developed by Howard Chu for inclusion
|
||||||
|
* in OpenLDAP Software. This work was sponsored by MySQL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "portable.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ac/string.h>
|
||||||
|
|
||||||
|
#include "back-ndb.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
ndb_back_compare( Operation *op, SlapReply *rs )
|
||||||
|
{
|
||||||
|
struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private;
|
||||||
|
Entry e = {0};
|
||||||
|
Attribute *a;
|
||||||
|
int manageDSAit = get_manageDSAit( op );
|
||||||
|
|
||||||
|
NdbArgs NA;
|
||||||
|
NdbRdns rdns;
|
||||||
|
struct berval matched;
|
||||||
|
|
||||||
|
/* Get our NDB handle */
|
||||||
|
rs->sr_err = ndb_thread_handle( op, &NA.ndb );
|
||||||
|
|
||||||
|
rdns.nr_num = 0;
|
||||||
|
NA.rdns = &rdns;
|
||||||
|
e.e_name = op->o_req_dn;
|
||||||
|
e.e_nname = op->o_req_ndn;
|
||||||
|
NA.e = &e;
|
||||||
|
|
||||||
|
dn2entry_retry:
|
||||||
|
NA.txn = NA.ndb->startTransaction();
|
||||||
|
rs->sr_text = NULL;
|
||||||
|
if( !NA.txn ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_compare) ": startTransaction failed: %s (%d)\n",
|
||||||
|
NA.ndb->getNdbError().message, NA.ndb->getNdbError().code, 0 );
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
rs->sr_text = "internal error";
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
NA.ocs = NULL;
|
||||||
|
/* get entry */
|
||||||
|
rs->sr_err = ndb_entry_get_info( op, &NA, 0, &matched );
|
||||||
|
switch( rs->sr_err ) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case LDAP_NO_SUCH_OBJECT:
|
||||||
|
rs->sr_matched = matched.bv_val;
|
||||||
|
if ( NA.ocs )
|
||||||
|
ndb_check_referral( op, rs, &NA );
|
||||||
|
goto return_results;
|
||||||
|
case LDAP_BUSY:
|
||||||
|
rs->sr_text = "ldap server busy";
|
||||||
|
goto return_results;
|
||||||
|
#if 0
|
||||||
|
case DB_LOCK_DEADLOCK:
|
||||||
|
case DB_LOCK_NOTGRANTED:
|
||||||
|
goto dn2entry_retry;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
rs->sr_text = "internal error";
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
rs->sr_err = ndb_entry_get_data( op, &NA, 0 );
|
||||||
|
ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx );
|
||||||
|
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;
|
||||||
|
rs->sr_flags |= REP_REF_MUSTBEFREED;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 );
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( get_assert( op ) &&
|
||||||
|
( test_filter( op, &e, (Filter *)get_assertion( op )) != LDAP_COMPARE_TRUE ))
|
||||||
|
{
|
||||||
|
if ( !access_allowed( op, &e, slap_schema.si_ad_entry,
|
||||||
|
NULL, ACL_DISCLOSE, NULL ) )
|
||||||
|
{
|
||||||
|
rs->sr_err = LDAP_NO_SUCH_OBJECT;
|
||||||
|
} else {
|
||||||
|
rs->sr_err = LDAP_ASSERTION_FAILED;
|
||||||
|
}
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !access_allowed( op, &e, op->oq_compare.rs_ava->aa_desc,
|
||||||
|
&op->oq_compare.rs_ava->aa_value, ACL_COMPARE, NULL ) )
|
||||||
|
{
|
||||||
|
/* return error 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_err = LDAP_INSUFFICIENT_ACCESS;
|
||||||
|
}
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
rs->sr_err = LDAP_NO_SUCH_ATTRIBUTE;
|
||||||
|
|
||||||
|
for ( a = attrs_find( e.e_attrs, op->oq_compare.rs_ava->aa_desc );
|
||||||
|
a != NULL;
|
||||||
|
a = attrs_find( a->a_next, op->oq_compare.rs_ava->aa_desc ) )
|
||||||
|
{
|
||||||
|
rs->sr_err = LDAP_COMPARE_FALSE;
|
||||||
|
|
||||||
|
if ( attr_valfind( a,
|
||||||
|
SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
|
||||||
|
SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
|
||||||
|
&op->oq_compare.rs_ava->aa_value, NULL,
|
||||||
|
op->o_tmpmemctx ) == 0 )
|
||||||
|
{
|
||||||
|
rs->sr_err = LDAP_COMPARE_TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return_results:
|
||||||
|
NA.txn->close();
|
||||||
|
if ( e.e_attrs ) {
|
||||||
|
attrs_free( e.e_attrs );
|
||||||
|
e.e_attrs = NULL;
|
||||||
|
}
|
||||||
|
send_ldap_result( op, rs );
|
||||||
|
|
||||||
|
switch ( rs->sr_err ) {
|
||||||
|
case LDAP_COMPARE_FALSE:
|
||||||
|
case LDAP_COMPARE_TRUE:
|
||||||
|
rs->sr_err = LDAP_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rs->sr_err;
|
||||||
|
}
|
||||||
333
servers/slapd/back-ndb/config.cpp
Normal file
333
servers/slapd/back-ndb/config.cpp
Normal file
|
|
@ -0,0 +1,333 @@
|
||||||
|
/* config.cpp - ndb backend configuration file routine */
|
||||||
|
/* $OpenLDAP$ */
|
||||||
|
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||||
|
*
|
||||||
|
* Copyright 2008 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>.
|
||||||
|
*/
|
||||||
|
/* ACKNOWLEDGEMENTS:
|
||||||
|
* This work was initially developed by Howard Chu for inclusion
|
||||||
|
* in OpenLDAP Software. This work was sponsored by MySQL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "portable.h"
|
||||||
|
#include "lutil.h"
|
||||||
|
|
||||||
|
#include "back-ndb.h"
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
static ConfigDriver ndb_cf_gen;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
NDB_ATLEN = 1,
|
||||||
|
NDB_ATSET,
|
||||||
|
NDB_INDEX,
|
||||||
|
NDB_ATBLOB
|
||||||
|
};
|
||||||
|
|
||||||
|
static ConfigTable ndbcfg[] = {
|
||||||
|
{ "dbhost", "hostname", 2, 2, 0, ARG_STRING|ARG_OFFSET,
|
||||||
|
(void *)offsetof(struct ndb_info, ni_hostname),
|
||||||
|
"( OLcfgDbAt:6.1 NAME 'olcDbHost' "
|
||||||
|
"DESC 'Hostname of SQL server' "
|
||||||
|
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
|
||||||
|
{ "dbname", "name", 2, 2, 0, ARG_STRING|ARG_OFFSET,
|
||||||
|
(void *)offsetof(struct ndb_info, ni_dbname),
|
||||||
|
"( OLcfgDbAt:6.2 NAME 'olcDbName' "
|
||||||
|
"DESC 'Name of SQL database' "
|
||||||
|
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
|
||||||
|
{ "dbuser", "username", 2, 2, 0, ARG_STRING|ARG_OFFSET,
|
||||||
|
(void *)offsetof(struct ndb_info, ni_username),
|
||||||
|
"( OLcfgDbAt:6.3 NAME 'olcDbUser' "
|
||||||
|
"DESC 'Username for SQL session' "
|
||||||
|
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
|
||||||
|
{ "dbpass", "password", 2, 2, 0, ARG_STRING|ARG_OFFSET,
|
||||||
|
(void *)offsetof(struct ndb_info, ni_password),
|
||||||
|
"( OLcfgDbAt:6.4 NAME 'olcDbPass' "
|
||||||
|
"DESC 'Password for SQL session' "
|
||||||
|
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
|
||||||
|
{ "dbport", "port", 2, 2, 0, ARG_UINT|ARG_OFFSET,
|
||||||
|
(void *)offsetof(struct ndb_info, ni_port),
|
||||||
|
"( OLcfgDbAt:6.5 NAME 'olcDbPort' "
|
||||||
|
"DESC 'Port number of SQL server' "
|
||||||
|
"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
|
||||||
|
{ "dbsocket", "path", 2, 2, 0, ARG_STRING|ARG_OFFSET,
|
||||||
|
(void *)offsetof(struct ndb_info, ni_socket),
|
||||||
|
"( OLcfgDbAt:6.6 NAME 'olcDbSocket' "
|
||||||
|
"DESC 'Local socket path of SQL server' "
|
||||||
|
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
|
||||||
|
{ "dbflag", "flag", 2, 2, 0, ARG_LONG|ARG_OFFSET,
|
||||||
|
(void *)offsetof(struct ndb_info, ni_clflag),
|
||||||
|
"( OLcfgDbAt:6.7 NAME 'olcDbFlag' "
|
||||||
|
"DESC 'Flags for SQL session' "
|
||||||
|
"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
|
||||||
|
{ "dbconnect", "hostname", 2, 2, 0, ARG_STRING|ARG_OFFSET,
|
||||||
|
(void *)offsetof(struct ndb_info, ni_connectstr),
|
||||||
|
"( OLcfgDbAt:6.8 NAME 'olcDbConnect' "
|
||||||
|
"DESC 'Hostname of NDB server' "
|
||||||
|
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
|
||||||
|
{ "dbconnections", "number", 2, 2, 0, ARG_INT|ARG_OFFSET,
|
||||||
|
(void *)offsetof(struct ndb_info, ni_nconns),
|
||||||
|
"( OLcfgDbAt:6.9 NAME 'olcDbConnections' "
|
||||||
|
"DESC 'Number of cluster connections to open' "
|
||||||
|
"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
|
||||||
|
{ "attrlen", "attr> <len", 3, 3, 0, ARG_MAGIC|NDB_ATLEN,
|
||||||
|
(void *)ndb_cf_gen,
|
||||||
|
"( OLcfgDbAt:6.10 NAME 'olcNdbAttrLen' "
|
||||||
|
"DESC 'Column length of a specific attribute' "
|
||||||
|
"EQUALITY caseIgnoreMatch "
|
||||||
|
"SYNTAX OMsDirectoryString )", NULL, NULL },
|
||||||
|
{ "attrset", "set> <attrs", 3, 3, 0, ARG_MAGIC|NDB_ATSET,
|
||||||
|
(void *)ndb_cf_gen,
|
||||||
|
"( OLcfgDbAt:6.11 NAME 'olcNdbAttrSet' "
|
||||||
|
"DESC 'Set of common attributes' "
|
||||||
|
"EQUALITY caseIgnoreMatch "
|
||||||
|
"SYNTAX OMsDirectoryString )", NULL, NULL },
|
||||||
|
{ "index", "attr", 2, 2, 0, ARG_MAGIC|NDB_INDEX,
|
||||||
|
(void *)ndb_cf_gen, "( OLcfgDbAt:0.2 NAME 'olcDbIndex' "
|
||||||
|
"DESC 'Attribute to index' "
|
||||||
|
"EQUALITY caseIgnoreMatch "
|
||||||
|
"SYNTAX OMsDirectoryString )", NULL, NULL },
|
||||||
|
{ "attrblob", "attr", 2, 2, 0, ARG_MAGIC|NDB_ATBLOB,
|
||||||
|
(void *)ndb_cf_gen, "( OLcfgDbAt:6.12 NAME 'olcNdbAttrBlob' "
|
||||||
|
"DESC 'Attribute to treat as a BLOB' "
|
||||||
|
"EQUALITY caseIgnoreMatch "
|
||||||
|
"SYNTAX OMsDirectoryString )", NULL, NULL },
|
||||||
|
{ "directory", "dir", 2, 2, 0, ARG_IGNORED,
|
||||||
|
NULL, "( OLcfgDbAt:0.1 NAME 'olcDbDirectory' "
|
||||||
|
"DESC 'Dummy keyword' "
|
||||||
|
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
|
||||||
|
{ NULL, NULL, 0, 0, 0, ARG_IGNORED,
|
||||||
|
NULL, NULL, NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static ConfigOCs ndbocs[] = {
|
||||||
|
{
|
||||||
|
"( OLcfgDbOc:6.2 "
|
||||||
|
"NAME 'olcNdbConfig' "
|
||||||
|
"DESC 'NDB backend configuration' "
|
||||||
|
"SUP olcDatabaseConfig "
|
||||||
|
"MUST ( olcDbHost $ olcDbName $ olcDbConnect ) "
|
||||||
|
"MAY ( olcDbUser $ olcDbPass $ olcDbPort $ olcDbSocket $ "
|
||||||
|
"olcDbFlag $ olcDbConnections $ olcNdbAttrLen $ "
|
||||||
|
"olcDbIndex $ olcNdbAttrSet $ olcNdbAttrBlob ) )",
|
||||||
|
Cft_Database, ndbcfg },
|
||||||
|
{ NULL, Cft_Abstract, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
ndb_cf_gen( ConfigArgs *c )
|
||||||
|
{
|
||||||
|
struct ndb_info *ni = (struct ndb_info *)c->be->be_private;
|
||||||
|
int i, rc;
|
||||||
|
NdbAttrInfo *ai;
|
||||||
|
NdbOcInfo *oci;
|
||||||
|
ListNode *ln, **l2;
|
||||||
|
struct berval bv, *bva;
|
||||||
|
|
||||||
|
if ( c->op == SLAP_CONFIG_EMIT ) {
|
||||||
|
char buf[BUFSIZ];
|
||||||
|
rc = 0;
|
||||||
|
bv.bv_val = buf;
|
||||||
|
switch( c->type ) {
|
||||||
|
case NDB_ATLEN:
|
||||||
|
if ( ni->ni_attrlens ) {
|
||||||
|
for ( ln = ni->ni_attrlens; ln; ln=ln->ln_next ) {
|
||||||
|
ai = (NdbAttrInfo *)ln->ln_data;
|
||||||
|
bv.bv_len = snprintf( buf, sizeof(buf),
|
||||||
|
"%s %d", ai->na_name.bv_val,
|
||||||
|
ai->na_len );
|
||||||
|
value_add_one( &c->rvalue_vals, &bv );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rc = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NDB_ATSET:
|
||||||
|
if ( ni->ni_attrsets ) {
|
||||||
|
char *ptr, *end = buf+sizeof(buf);
|
||||||
|
for ( ln = ni->ni_attrsets; ln; ln=ln->ln_next ) {
|
||||||
|
oci = (NdbOcInfo *)ln->ln_data;
|
||||||
|
ptr = lutil_strcopy( buf, oci->no_name.bv_val );
|
||||||
|
*ptr++ = ' ';
|
||||||
|
for ( i=0; i<oci->no_nattrs; i++ ) {
|
||||||
|
if ( end - ptr < oci->no_attrs[i]->na_name.bv_len+1 )
|
||||||
|
break;
|
||||||
|
if ( i )
|
||||||
|
*ptr++ = ',';
|
||||||
|
ptr = lutil_strcopy(ptr,
|
||||||
|
oci->no_attrs[i]->na_name.bv_val );
|
||||||
|
}
|
||||||
|
bv.bv_len = ptr - buf;
|
||||||
|
value_add_one( &c->rvalue_vals, &bv );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rc = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NDB_INDEX:
|
||||||
|
if ( ni->ni_attridxs ) {
|
||||||
|
for ( ln = ni->ni_attridxs; ln; ln=ln->ln_next ) {
|
||||||
|
ai = (NdbAttrInfo *)ln->ln_data;
|
||||||
|
value_add_one( &c->rvalue_vals, &ai->na_name );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rc = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NDB_ATBLOB:
|
||||||
|
if ( ni->ni_attrblobs ) {
|
||||||
|
for ( ln = ni->ni_attrblobs; ln; ln=ln->ln_next ) {
|
||||||
|
ai = (NdbAttrInfo *)ln->ln_data;
|
||||||
|
value_add_one( &c->rvalue_vals, &ai->na_name );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rc = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
} else if ( c->op == LDAP_MOD_DELETE ) { /* FIXME */
|
||||||
|
rc = 0;
|
||||||
|
switch( c->type ) {
|
||||||
|
case NDB_INDEX:
|
||||||
|
if ( c->valx == -1 ) {
|
||||||
|
|
||||||
|
/* delete all */
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch( c->type ) {
|
||||||
|
case NDB_ATLEN:
|
||||||
|
ber_str2bv( c->argv[1], 0, 0, &bv );
|
||||||
|
ai = ndb_ai_get( ni, &bv );
|
||||||
|
if ( !ai ) {
|
||||||
|
snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: invalid attr %s",
|
||||||
|
c->log, c->argv[1] );
|
||||||
|
Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg, 0, 0 );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for ( ln = ni->ni_attrlens; ln; ln = ln->ln_next ) {
|
||||||
|
if ( ln->ln_data == (void *)ai ) {
|
||||||
|
snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: attr len already set for %s",
|
||||||
|
c->log, c->argv[1] );
|
||||||
|
Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg, 0, 0 );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ai->na_len = atoi( c->argv[2] );
|
||||||
|
ai->na_flag |= NDB_INFO_ATLEN;
|
||||||
|
ln = (ListNode *)ch_malloc( sizeof(ListNode));
|
||||||
|
ln->ln_data = ai;
|
||||||
|
ln->ln_next = NULL;
|
||||||
|
for ( l2 = &ni->ni_attrlens; *l2; l2 = &(*l2)->ln_next );
|
||||||
|
*l2 = ln;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NDB_INDEX:
|
||||||
|
ber_str2bv( c->argv[1], 0, 0, &bv );
|
||||||
|
ai = ndb_ai_get( ni, &bv );
|
||||||
|
if ( !ai ) {
|
||||||
|
snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: invalid attr %s",
|
||||||
|
c->log, c->argv[1] );
|
||||||
|
Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg, 0, 0 );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for ( ln = ni->ni_attridxs; ln; ln = ln->ln_next ) {
|
||||||
|
if ( ln->ln_data == (void *)ai ) {
|
||||||
|
snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: attr index already set for %s",
|
||||||
|
c->log, c->argv[1] );
|
||||||
|
Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg, 0, 0 );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ai->na_flag |= NDB_INFO_INDEX;
|
||||||
|
ln = (ListNode *)ch_malloc( sizeof(ListNode));
|
||||||
|
ln->ln_data = ai;
|
||||||
|
ln->ln_next = NULL;
|
||||||
|
for ( l2 = &ni->ni_attridxs; *l2; l2 = &(*l2)->ln_next );
|
||||||
|
*l2 = ln;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NDB_ATSET:
|
||||||
|
ber_str2bv( c->argv[1], 0, 0, &bv );
|
||||||
|
bva = ndb_str2bvarray( c->argv[2], strlen( c->argv[2] ), ',', NULL );
|
||||||
|
rc = ndb_aset_get( ni, &bv, bva, &oci );
|
||||||
|
ber_bvarray_free( bva );
|
||||||
|
if ( rc ) {
|
||||||
|
if ( rc == LDAP_ALREADY_EXISTS ) {
|
||||||
|
snprintf( c->cr_msg, sizeof( c->cr_msg ),
|
||||||
|
"%s: attrset %s already defined",
|
||||||
|
c->log, c->argv[1] );
|
||||||
|
} else {
|
||||||
|
snprintf( c->cr_msg, sizeof( c->cr_msg ),
|
||||||
|
"%s: invalid attrset %s (%d)",
|
||||||
|
c->log, c->argv[1], rc );
|
||||||
|
}
|
||||||
|
Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg, 0, 0 );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ln = (ListNode *)ch_malloc( sizeof(ListNode));
|
||||||
|
ln->ln_data = oci;
|
||||||
|
ln->ln_next = NULL;
|
||||||
|
for ( l2 = &ni->ni_attrsets; *l2; l2 = &(*l2)->ln_next );
|
||||||
|
*l2 = ln;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NDB_ATBLOB:
|
||||||
|
ber_str2bv( c->argv[1], 0, 0, &bv );
|
||||||
|
ai = ndb_ai_get( ni, &bv );
|
||||||
|
if ( !ai ) {
|
||||||
|
snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: invalid attr %s",
|
||||||
|
c->log, c->argv[1] );
|
||||||
|
Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg, 0, 0 );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for ( ln = ni->ni_attrblobs; ln; ln = ln->ln_next ) {
|
||||||
|
if ( ln->ln_data == (void *)ai ) {
|
||||||
|
snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: attr blob already set for %s",
|
||||||
|
c->log, c->argv[1] );
|
||||||
|
Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg, 0, 0 );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ai->na_flag |= NDB_INFO_ATBLOB;
|
||||||
|
ln = (ListNode *)ch_malloc( sizeof(ListNode));
|
||||||
|
ln->ln_data = ai;
|
||||||
|
ln->ln_next = NULL;
|
||||||
|
for ( l2 = &ni->ni_attrblobs; *l2; l2 = &(*l2)->ln_next );
|
||||||
|
*l2 = ln;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
int ndb_back_init_cf( BackendInfo *bi )
|
||||||
|
{
|
||||||
|
bi->bi_cf_ocs = ndbocs;
|
||||||
|
|
||||||
|
return config_register_schema( ndbcfg, ndbocs );
|
||||||
|
}
|
||||||
322
servers/slapd/back-ndb/delete.cpp
Normal file
322
servers/slapd/back-ndb/delete.cpp
Normal file
|
|
@ -0,0 +1,322 @@
|
||||||
|
/* delete.cpp - ndb backend delete routine */
|
||||||
|
/* $OpenLDAP$ */
|
||||||
|
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||||
|
*
|
||||||
|
* Copyright 2008 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>.
|
||||||
|
*/
|
||||||
|
/* ACKNOWLEDGEMENTS:
|
||||||
|
* This work was initially developed by Howard Chu for inclusion
|
||||||
|
* in OpenLDAP Software. This work was sponsored by MySQL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "portable.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ac/string.h>
|
||||||
|
|
||||||
|
#include "lutil.h"
|
||||||
|
#include "back-ndb.h"
|
||||||
|
|
||||||
|
static struct berval glue_bv = BER_BVC("glue");
|
||||||
|
|
||||||
|
int
|
||||||
|
ndb_back_delete( Operation *op, SlapReply *rs )
|
||||||
|
{
|
||||||
|
struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private;
|
||||||
|
Entry e = {0};
|
||||||
|
Entry p = {0};
|
||||||
|
int manageDSAit = get_manageDSAit( op );
|
||||||
|
AttributeDescription *children = slap_schema.si_ad_children;
|
||||||
|
AttributeDescription *entry = slap_schema.si_ad_entry;
|
||||||
|
|
||||||
|
NdbArgs NA;
|
||||||
|
NdbRdns rdns;
|
||||||
|
struct berval matched;
|
||||||
|
|
||||||
|
int num_retries = 0;
|
||||||
|
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
LDAPControl **preread_ctrl = NULL;
|
||||||
|
LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
|
||||||
|
int num_ctrls = 0;
|
||||||
|
|
||||||
|
Debug( LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(ndb_back_delete) ": %s\n",
|
||||||
|
op->o_req_dn.bv_val, 0, 0 );
|
||||||
|
|
||||||
|
ctrls[num_ctrls] = 0;
|
||||||
|
|
||||||
|
/* allocate CSN */
|
||||||
|
if ( BER_BVISNULL( &op->o_csn ) ) {
|
||||||
|
struct berval csn;
|
||||||
|
char csnbuf[LDAP_LUTIL_CSNSTR_BUFSIZE];
|
||||||
|
|
||||||
|
csn.bv_val = csnbuf;
|
||||||
|
csn.bv_len = sizeof(csnbuf);
|
||||||
|
slap_get_csn( op, &csn, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !be_issuffix( op->o_bd, &op->o_req_ndn ) ) {
|
||||||
|
dnParent( &op->o_req_dn, &p.e_name );
|
||||||
|
dnParent( &op->o_req_ndn, &p.e_nname );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get our NDB handle */
|
||||||
|
rs->sr_err = ndb_thread_handle( op, &NA.ndb );
|
||||||
|
rdns.nr_num = 0;
|
||||||
|
NA.rdns = &rdns;
|
||||||
|
NA.ocs = NULL;
|
||||||
|
NA.e = &e;
|
||||||
|
e.e_name = op->o_req_dn;
|
||||||
|
e.e_nname = op->o_req_ndn;
|
||||||
|
|
||||||
|
if( 0 ) {
|
||||||
|
retry: /* transaction retry */
|
||||||
|
NA.txn->close();
|
||||||
|
NA.txn = NULL;
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
"==> " LDAP_XSTRING(ndb_back_delete) ": retrying...\n",
|
||||||
|
0, 0, 0 );
|
||||||
|
if ( op->o_abandon ) {
|
||||||
|
rs->sr_err = SLAPD_ABANDON;
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
if ( NA.ocs ) {
|
||||||
|
ber_bvarray_free( NA.ocs );
|
||||||
|
NA.ocs = NULL;
|
||||||
|
}
|
||||||
|
ndb_trans_backoff( ++num_retries );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* begin transaction */
|
||||||
|
NA.txn = NA.ndb->startTransaction();
|
||||||
|
rs->sr_text = NULL;
|
||||||
|
if( !NA.txn ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_delete) ": startTransaction failed: %s (%d)\n",
|
||||||
|
NA.ndb->getNdbError().message, NA.ndb->getNdbError().code, 0 );
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
rs->sr_text = "internal error";
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get entry */
|
||||||
|
rs->sr_err = ndb_entry_get_info( op, &NA, 1, &matched );
|
||||||
|
switch( rs->sr_err ) {
|
||||||
|
case 0:
|
||||||
|
case LDAP_NO_SUCH_OBJECT:
|
||||||
|
break;
|
||||||
|
#if 0
|
||||||
|
case DB_LOCK_DEADLOCK:
|
||||||
|
case DB_LOCK_NOTGRANTED:
|
||||||
|
goto retry;
|
||||||
|
#endif
|
||||||
|
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 == LDAP_NO_SUCH_OBJECT ||
|
||||||
|
( !manageDSAit && bvmatch( NA.ocs, &glue_bv ))) {
|
||||||
|
Debug( LDAP_DEBUG_ARGS,
|
||||||
|
"<=- " LDAP_XSTRING(ndb_back_delete) ": no such object %s\n",
|
||||||
|
op->o_req_dn.bv_val, 0, 0);
|
||||||
|
|
||||||
|
if ( rs->sr_err == LDAP_NO_SUCH_OBJECT ) {
|
||||||
|
rs->sr_matched = matched.bv_val;
|
||||||
|
if ( NA.ocs )
|
||||||
|
ndb_check_referral( op, rs, &NA );
|
||||||
|
} else {
|
||||||
|
rs->sr_matched = p.e_name.bv_val;
|
||||||
|
rs->sr_err = LDAP_NO_SUCH_OBJECT;
|
||||||
|
}
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check parent for "children" acl */
|
||||||
|
rs->sr_err = access_allowed( op, &p,
|
||||||
|
children, NULL, ACL_WDEL, NULL );
|
||||||
|
|
||||||
|
if ( !rs->sr_err ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
"<=- " LDAP_XSTRING(ndb_back_delete) ": no write "
|
||||||
|
"access to parent\n", 0, 0, 0 );
|
||||||
|
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
||||||
|
rs->sr_text = "no write access to parent";
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
rs->sr_err = ndb_entry_get_data( op, &NA, 1 );
|
||||||
|
|
||||||
|
rs->sr_err = access_allowed( op, &e,
|
||||||
|
entry, NULL, ACL_WDEL, NULL );
|
||||||
|
|
||||||
|
if ( !rs->sr_err ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
"<=- " LDAP_XSTRING(ndb_back_delete) ": no write access "
|
||||||
|
"to entry\n", 0, 0, 0 );
|
||||||
|
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
||||||
|
rs->sr_text = "no write access to entry";
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !manageDSAit && is_entry_referral( &e ) ) {
|
||||||
|
/* entry is a referral, don't allow delete */
|
||||||
|
rs->sr_ref = get_entry_referrals( op, &e );
|
||||||
|
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_delete) ": entry is referral\n",
|
||||||
|
0, 0, 0 );
|
||||||
|
|
||||||
|
rs->sr_err = LDAP_REFERRAL;
|
||||||
|
rs->sr_matched = e.e_name.bv_val;
|
||||||
|
rs->sr_flags = REP_REF_MUSTBEFREED;
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( get_assert( op ) &&
|
||||||
|
( test_filter( op, &e, (Filter *)get_assertion( op )) != LDAP_COMPARE_TRUE ))
|
||||||
|
{
|
||||||
|
rs->sr_err = LDAP_ASSERTION_FAILED;
|
||||||
|
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(ndb_back_delete) ": pre-read "
|
||||||
|
"failed!\n", 0, 0, 0 );
|
||||||
|
if ( op->o_preread & SLAP_CONTROL_CRITICAL ) {
|
||||||
|
/* FIXME: is it correct to abort
|
||||||
|
* operation if control fails? */
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Can't do it if we have kids */
|
||||||
|
rs->sr_err = ndb_has_children( &NA, &rc );
|
||||||
|
if ( rs->sr_err ) {
|
||||||
|
Debug(LDAP_DEBUG_ARGS,
|
||||||
|
"<=- " LDAP_XSTRING(ndb_back_delete)
|
||||||
|
": has_children failed: %s (%d)\n",
|
||||||
|
NA.txn->getNdbError().message, NA.txn->getNdbError().code, 0 );
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
rs->sr_text = "internal error";
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
if ( rc == LDAP_COMPARE_TRUE ) {
|
||||||
|
Debug(LDAP_DEBUG_ARGS,
|
||||||
|
"<=- " LDAP_XSTRING(ndb_back_delete)
|
||||||
|
": non-leaf %s\n",
|
||||||
|
op->o_req_dn.bv_val, 0, 0);
|
||||||
|
rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
|
||||||
|
rs->sr_text = "subordinate objects must be deleted first";
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* delete info */
|
||||||
|
rs->sr_err = ndb_entry_del_info( op->o_bd, &NA );
|
||||||
|
if ( rs->sr_err != 0 ) {
|
||||||
|
Debug(LDAP_DEBUG_TRACE,
|
||||||
|
"<=- " LDAP_XSTRING(ndb_back_delete) ": del_info failed: %s (%d)\n",
|
||||||
|
NA.txn->getNdbError().message, NA.txn->getNdbError().code, 0 );
|
||||||
|
rs->sr_text = "DN index delete failed";
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* delete data */
|
||||||
|
rs->sr_err = ndb_entry_del_data( op->o_bd, &NA );
|
||||||
|
if ( rs->sr_err != 0 ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
"<=- " LDAP_XSTRING(ndb_back_delete) ": del_data failed: %s (%d)\n",
|
||||||
|
NA.txn->getNdbError().message, NA.txn->getNdbError().code, 0 );
|
||||||
|
rs->sr_text = "entry delete failed";
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( op->o_noop ) {
|
||||||
|
if (( rs->sr_err=NA.txn->execute( NdbTransaction::Rollback,
|
||||||
|
NdbOperation::AbortOnError, 1 )) != 0 ) {
|
||||||
|
rs->sr_text = "txn (no-op) failed";
|
||||||
|
} else {
|
||||||
|
rs->sr_err = LDAP_X_NO_OPERATION;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (( rs->sr_err=NA.txn->execute( NdbTransaction::Commit,
|
||||||
|
NdbOperation::AbortOnError, 1 )) != 0 ) {
|
||||||
|
rs->sr_text = "txn_commit failed";
|
||||||
|
} else {
|
||||||
|
rs->sr_err = LDAP_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( rs->sr_err != LDAP_SUCCESS && rs->sr_err != LDAP_X_NO_OPERATION ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_delete) ": txn_%s failed: %s (%d)\n",
|
||||||
|
op->o_noop ? "abort (no-op)" : "commit",
|
||||||
|
NA.txn->getNdbError().message, NA.txn->getNdbError().code );
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
rs->sr_text = "commit failed";
|
||||||
|
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
NA.txn->close();
|
||||||
|
NA.txn = NULL;
|
||||||
|
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_delete) ": deleted%s id=%08lx dn=\"%s\"\n",
|
||||||
|
op->o_noop ? " (no-op)" : "",
|
||||||
|
e.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 ( NA.ocs ) {
|
||||||
|
ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx );
|
||||||
|
NA.ocs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* free entry */
|
||||||
|
if( e.e_attrs != NULL ) {
|
||||||
|
attrs_free( e.e_attrs );
|
||||||
|
e.e_attrs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( NA.txn != NULL ) {
|
||||||
|
NA.txn->execute( Rollback );
|
||||||
|
NA.txn->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
return rs->sr_err;
|
||||||
|
}
|
||||||
449
servers/slapd/back-ndb/init.cpp
Normal file
449
servers/slapd/back-ndb/init.cpp
Normal file
|
|
@ -0,0 +1,449 @@
|
||||||
|
/* init.cpp - initialize ndb backend */
|
||||||
|
/* $OpenLDAP$ */
|
||||||
|
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||||
|
*
|
||||||
|
* Copyright 2008 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>.
|
||||||
|
*/
|
||||||
|
/* ACKNOWLEDGEMENTS:
|
||||||
|
* This work was initially developed by Howard Chu for inclusion
|
||||||
|
* in OpenLDAP Software. This work was sponsored by MySQL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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-ndb.h"
|
||||||
|
#include <lutil.h>
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
static BI_db_init ndb_db_init;
|
||||||
|
static BI_db_close ndb_db_close;
|
||||||
|
static BI_db_open ndb_db_open;
|
||||||
|
static BI_db_destroy ndb_db_destroy;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct berval ndb_optable = BER_BVC("OL_opattrs");
|
||||||
|
|
||||||
|
static struct berval ndb_opattrs[] = {
|
||||||
|
BER_BVC("structuralObjectClass"),
|
||||||
|
BER_BVC("entryUUID"),
|
||||||
|
BER_BVC("creatorsName"),
|
||||||
|
BER_BVC("createTimestamp"),
|
||||||
|
BER_BVC("entryCSN"),
|
||||||
|
BER_BVC("modifiersName"),
|
||||||
|
BER_BVC("modifyTimestamp"),
|
||||||
|
BER_BVNULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static int ndb_oplens[] = {
|
||||||
|
0, /* structuralOC, default */
|
||||||
|
36, /* entryUUID */
|
||||||
|
0, /* creatorsName, default */
|
||||||
|
26, /* createTimestamp */
|
||||||
|
40, /* entryCSN */
|
||||||
|
0, /* modifiersName, default */
|
||||||
|
26, /* modifyTimestamp */
|
||||||
|
-1
|
||||||
|
};
|
||||||
|
|
||||||
|
static Uint32 ndb_lastrow[1];
|
||||||
|
NdbInterpretedCode *ndb_lastrow_code;
|
||||||
|
|
||||||
|
static int
|
||||||
|
ndb_db_init( BackendDB *be, ConfigReply *cr )
|
||||||
|
{
|
||||||
|
struct ndb_info *ni;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_db_init) ": Initializing ndb database\n",
|
||||||
|
0, 0, 0 );
|
||||||
|
|
||||||
|
/* allocate backend-database-specific stuff */
|
||||||
|
ni = (struct ndb_info *) ch_calloc( 1, sizeof(struct ndb_info) );
|
||||||
|
|
||||||
|
be->be_private = ni;
|
||||||
|
be->be_cf_ocs = be->bd_info->bi_cf_ocs;
|
||||||
|
|
||||||
|
ni->ni_search_stack_depth = DEFAULT_SEARCH_STACK_DEPTH;
|
||||||
|
|
||||||
|
ldap_pvt_thread_rdwr_init( &ni->ni_ai_rwlock );
|
||||||
|
ldap_pvt_thread_rdwr_init( &ni->ni_oc_rwlock );
|
||||||
|
ldap_pvt_thread_mutex_init( &ni->ni_conn_mutex );
|
||||||
|
|
||||||
|
#ifdef DO_MONITORING
|
||||||
|
rc = ndb_monitor_db_init( be );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ndb_db_close( BackendDB *be, ConfigReply *cr );
|
||||||
|
|
||||||
|
static int
|
||||||
|
ndb_db_open( BackendDB *be, ConfigReply *cr )
|
||||||
|
{
|
||||||
|
struct ndb_info *ni = (struct ndb_info *) be->be_private;
|
||||||
|
char sqlbuf[BUFSIZ], *ptr;
|
||||||
|
int rc, i;
|
||||||
|
|
||||||
|
if ( be->be_suffix == NULL ) {
|
||||||
|
snprintf( cr->msg, sizeof( cr->msg ),
|
||||||
|
"ndb_db_open: need suffix" );
|
||||||
|
Debug( LDAP_DEBUG_ANY, "%s\n",
|
||||||
|
cr->msg, 0, 0 );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug( LDAP_DEBUG_ARGS,
|
||||||
|
LDAP_XSTRING(ndb_db_open) ": \"%s\"\n",
|
||||||
|
be->be_suffix[0].bv_val, 0, 0 );
|
||||||
|
|
||||||
|
if ( ni->ni_nconns < 1 )
|
||||||
|
ni->ni_nconns = 1;
|
||||||
|
|
||||||
|
ni->ni_cluster = (Ndb_cluster_connection **)ch_calloc( ni->ni_nconns, sizeof( Ndb_cluster_connection *));
|
||||||
|
for ( i=0; i<ni->ni_nconns; i++ ) {
|
||||||
|
ni->ni_cluster[i] = new Ndb_cluster_connection( ni->ni_connectstr );
|
||||||
|
rc = ni->ni_cluster[i]->connect( 20, 5, 1 );
|
||||||
|
if ( rc ) {
|
||||||
|
snprintf( cr->msg, sizeof( cr->msg ),
|
||||||
|
"ndb_db_open: ni_cluster[%d]->connect failed (%d)",
|
||||||
|
i, rc );
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for ( i=0; i<ni->ni_nconns; i++ ) {
|
||||||
|
rc = ni->ni_cluster[i]->wait_until_ready( 30, 0 );
|
||||||
|
if ( rc ) {
|
||||||
|
snprintf( cr->msg, sizeof( cr->msg ),
|
||||||
|
"ndb_db_open: ni_cluster[%d]->wait failed (%d)",
|
||||||
|
i, rc );
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mysql_init( &ni->ni_sql );
|
||||||
|
if ( !mysql_real_connect( &ni->ni_sql, ni->ni_hostname, ni->ni_username, ni->ni_password,
|
||||||
|
"", ni->ni_port, ni->ni_socket, ni->ni_clflag )) {
|
||||||
|
snprintf( cr->msg, sizeof( cr->msg ),
|
||||||
|
"ndb_db_open: mysql_real_connect failed, %s (%d)",
|
||||||
|
mysql_error(&ni->ni_sql), mysql_errno(&ni->ni_sql) );
|
||||||
|
rc = -1;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf( sqlbuf, "CREATE DATABASE IF NOT EXISTS %s", ni->ni_dbname );
|
||||||
|
rc = mysql_query( &ni->ni_sql, sqlbuf );
|
||||||
|
if ( rc ) {
|
||||||
|
snprintf( cr->msg, sizeof( cr->msg ),
|
||||||
|
"ndb_db_open: CREATE DATABASE %s failed, %s (%d)",
|
||||||
|
ni->ni_dbname, mysql_error(&ni->ni_sql), mysql_errno(&ni->ni_sql) );
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf( sqlbuf, "USE %s", ni->ni_dbname );
|
||||||
|
rc = mysql_query( &ni->ni_sql, sqlbuf );
|
||||||
|
if ( rc ) {
|
||||||
|
snprintf( cr->msg, sizeof( cr->msg ),
|
||||||
|
"ndb_db_open: USE DATABASE %s failed, %s (%d)",
|
||||||
|
ni->ni_dbname, mysql_error(&ni->ni_sql), mysql_errno(&ni->ni_sql) );
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = sqlbuf;
|
||||||
|
ptr += sprintf( ptr, "CREATE TABLE IF NOT EXISTS " DN2ID_TABLE " ("
|
||||||
|
"eid bigint unsigned NOT NULL, "
|
||||||
|
"object_classes VARCHAR(1024) NOT NULL, "
|
||||||
|
"a0 VARCHAR(128) NOT NULL DEFAULT '', "
|
||||||
|
"a1 VARCHAR(128) NOT NULL DEFAULT '', "
|
||||||
|
"a2 VARCHAR(128) NOT NULL DEFAULT '', "
|
||||||
|
"a3 VARCHAR(128) NOT NULL DEFAULT '', "
|
||||||
|
"a4 VARCHAR(128) NOT NULL DEFAULT '', "
|
||||||
|
"a5 VARCHAR(128) NOT NULL DEFAULT '', "
|
||||||
|
"a6 VARCHAR(128) NOT NULL DEFAULT '', "
|
||||||
|
"a7 VARCHAR(128) NOT NULL DEFAULT '', "
|
||||||
|
"a8 VARCHAR(128) NOT NULL DEFAULT '', "
|
||||||
|
"a9 VARCHAR(128) NOT NULL DEFAULT '', "
|
||||||
|
"a10 VARCHAR(128) NOT NULL DEFAULT '', "
|
||||||
|
"a11 VARCHAR(128) NOT NULL DEFAULT '', "
|
||||||
|
"a12 VARCHAR(128) NOT NULL DEFAULT '', "
|
||||||
|
"a13 VARCHAR(128) NOT NULL DEFAULT '', "
|
||||||
|
"a14 VARCHAR(128) NOT NULL DEFAULT '', "
|
||||||
|
"a15 VARCHAR(128) NOT NULL DEFAULT '', "
|
||||||
|
"PRIMARY KEY (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15), "
|
||||||
|
"UNIQUE KEY eid (eid) USING HASH" );
|
||||||
|
/* Create index columns */
|
||||||
|
if ( ni->ni_attridxs ) {
|
||||||
|
ListNode *ln;
|
||||||
|
int newcol = 0;
|
||||||
|
|
||||||
|
*ptr++ = ',';
|
||||||
|
*ptr++ = ' ';
|
||||||
|
for ( ln = ni->ni_attridxs; ln; ln=ln->ln_next ) {
|
||||||
|
NdbAttrInfo *ai = (NdbAttrInfo *)ln->ln_data;
|
||||||
|
ptr += sprintf( ptr, "`%s` VARCHAR(%d), ",
|
||||||
|
ai->na_name.bv_val, ai->na_len );
|
||||||
|
}
|
||||||
|
ptr = lutil_strcopy(ptr, "KEY " INDEX_NAME " (" );
|
||||||
|
|
||||||
|
for ( ln = ni->ni_attridxs; ln; ln=ln->ln_next ) {
|
||||||
|
NdbAttrInfo *ai = (NdbAttrInfo *)ln->ln_data;
|
||||||
|
if ( newcol ) *ptr++ = ',';
|
||||||
|
*ptr++ = '`';
|
||||||
|
ptr = lutil_strcopy( ptr, ai->na_name.bv_val );
|
||||||
|
*ptr++ = '`';
|
||||||
|
ai->na_ixcol = newcol + 18;
|
||||||
|
newcol++;
|
||||||
|
}
|
||||||
|
*ptr++ = ')';
|
||||||
|
}
|
||||||
|
strcpy( ptr, ") ENGINE=ndb" );
|
||||||
|
rc = mysql_query( &ni->ni_sql, sqlbuf );
|
||||||
|
if ( rc ) {
|
||||||
|
snprintf( cr->msg, sizeof( cr->msg ),
|
||||||
|
"ndb_db_open: CREATE TABLE " DN2ID_TABLE " failed, %s (%d)",
|
||||||
|
mysql_error(&ni->ni_sql), mysql_errno(&ni->ni_sql) );
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = mysql_query( &ni->ni_sql, "CREATE TABLE IF NOT EXISTS " NEXTID_TABLE " ("
|
||||||
|
"a bigint unsigned AUTO_INCREMENT PRIMARY KEY ) ENGINE=ndb" );
|
||||||
|
if ( rc ) {
|
||||||
|
snprintf( cr->msg, sizeof( cr->msg ),
|
||||||
|
"ndb_db_open: CREATE TABLE " NEXTID_TABLE " failed, %s (%d)",
|
||||||
|
mysql_error(&ni->ni_sql), mysql_errno(&ni->ni_sql) );
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
NdbOcInfo *oci;
|
||||||
|
|
||||||
|
rc = ndb_aset_get( ni, &ndb_optable, ndb_opattrs, &oci );
|
||||||
|
if ( rc ) {
|
||||||
|
snprintf( cr->msg, sizeof( cr->msg ),
|
||||||
|
"ndb_db_open: ndb_aset_get( %s ) failed (%d)",
|
||||||
|
ndb_optable.bv_val, rc );
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
for ( i=0; ndb_oplens[i] >= 0; i++ ) {
|
||||||
|
if ( ndb_oplens[i] )
|
||||||
|
oci->no_attrs[i]->na_len = ndb_oplens[i];
|
||||||
|
}
|
||||||
|
rc = ndb_aset_create( ni, oci );
|
||||||
|
if ( rc ) {
|
||||||
|
snprintf( cr->msg, sizeof( cr->msg ),
|
||||||
|
"ndb_db_open: ndb_aset_create( %s ) failed (%d)",
|
||||||
|
ndb_optable.bv_val, rc );
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
ni->ni_opattrs = oci;
|
||||||
|
}
|
||||||
|
/* Create attribute sets */
|
||||||
|
{
|
||||||
|
ListNode *ln;
|
||||||
|
|
||||||
|
for ( ln = ni->ni_attrsets; ln; ln=ln->ln_next ) {
|
||||||
|
NdbOcInfo *oci = (NdbOcInfo *)ln->ln_data;
|
||||||
|
rc = ndb_aset_create( ni, oci );
|
||||||
|
if ( rc ) {
|
||||||
|
snprintf( cr->msg, sizeof( cr->msg ),
|
||||||
|
"ndb_db_open: ndb_aset_create( %s ) failed (%d)",
|
||||||
|
oci->no_name.bv_val, rc );
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Initialize any currently used objectClasses */
|
||||||
|
{
|
||||||
|
Ndb *ndb;
|
||||||
|
const NdbDictionary::Dictionary *myDict;
|
||||||
|
|
||||||
|
ndb = new Ndb( ni->ni_cluster[0], ni->ni_dbname );
|
||||||
|
ndb->init(1024);
|
||||||
|
|
||||||
|
myDict = ndb->getDictionary();
|
||||||
|
ndb_oc_read( ni, myDict );
|
||||||
|
delete ndb;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DO_MONITORING
|
||||||
|
/* monitor setup */
|
||||||
|
rc = ndb_monitor_db_open( be );
|
||||||
|
if ( rc != 0 ) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
Debug( LDAP_DEBUG_ANY, "%s\n",
|
||||||
|
cr->msg, 0, 0 );
|
||||||
|
ndb_db_close( be, NULL );
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ndb_db_close( BackendDB *be, ConfigReply *cr )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct ndb_info *ni = (struct ndb_info *) be->be_private;
|
||||||
|
|
||||||
|
mysql_close( &ni->ni_sql );
|
||||||
|
if ( ni->ni_cluster ) {
|
||||||
|
for ( i=0; i<ni->ni_nconns; i++ ) {
|
||||||
|
if ( ni->ni_cluster[i] ) {
|
||||||
|
delete ni->ni_cluster[i];
|
||||||
|
ni->ni_cluster[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ch_free( ni->ni_cluster );
|
||||||
|
ni->ni_cluster = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DO_MONITORING
|
||||||
|
/* monitor handling */
|
||||||
|
(void)ndb_monitor_db_close( be );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ndb_db_destroy( BackendDB *be, ConfigReply *cr )
|
||||||
|
{
|
||||||
|
struct ndb_info *ni = (struct ndb_info *) be->be_private;
|
||||||
|
|
||||||
|
#ifdef DO_MONITORING
|
||||||
|
/* monitor handling */
|
||||||
|
(void)ndb_monitor_db_destroy( be );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ldap_pvt_thread_mutex_destroy( &ni->ni_conn_mutex );
|
||||||
|
ldap_pvt_thread_rdwr_destroy( &ni->ni_ai_rwlock );
|
||||||
|
ldap_pvt_thread_rdwr_destroy( &ni->ni_oc_rwlock );
|
||||||
|
|
||||||
|
ch_free( ni );
|
||||||
|
be->be_private = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int
|
||||||
|
ndb_back_initialize(
|
||||||
|
BackendInfo *bi )
|
||||||
|
{
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
/* initialize the underlying database system */
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_initialize) ": initialize ndb backend\n", 0, 0, 0 );
|
||||||
|
|
||||||
|
ndb_init();
|
||||||
|
|
||||||
|
ndb_lastrow_code = new NdbInterpretedCode( NULL, ndb_lastrow, 1 );
|
||||||
|
ndb_lastrow_code->interpret_exit_last_row();
|
||||||
|
ndb_lastrow_code->finalise();
|
||||||
|
|
||||||
|
bi->bi_flags |=
|
||||||
|
SLAP_BFLAG_INCREMENT |
|
||||||
|
SLAP_BFLAG_SUBENTRIES |
|
||||||
|
SLAP_BFLAG_ALIASES |
|
||||||
|
SLAP_BFLAG_REFERRALS;
|
||||||
|
|
||||||
|
bi->bi_controls = controls;
|
||||||
|
|
||||||
|
bi->bi_open = 0;
|
||||||
|
bi->bi_close = 0;
|
||||||
|
bi->bi_config = 0;
|
||||||
|
bi->bi_destroy = 0;
|
||||||
|
|
||||||
|
bi->bi_db_init = ndb_db_init;
|
||||||
|
bi->bi_db_config = config_generic_wrapper;
|
||||||
|
bi->bi_db_open = ndb_db_open;
|
||||||
|
bi->bi_db_close = ndb_db_close;
|
||||||
|
bi->bi_db_destroy = ndb_db_destroy;
|
||||||
|
|
||||||
|
bi->bi_op_add = ndb_back_add;
|
||||||
|
bi->bi_op_bind = ndb_back_bind;
|
||||||
|
bi->bi_op_compare = ndb_back_compare;
|
||||||
|
bi->bi_op_delete = ndb_back_delete;
|
||||||
|
bi->bi_op_modify = ndb_back_modify;
|
||||||
|
bi->bi_op_modrdn = ndb_back_modrdn;
|
||||||
|
bi->bi_op_search = ndb_back_search;
|
||||||
|
|
||||||
|
bi->bi_op_unbind = 0;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
bi->bi_extended = ndb_extended;
|
||||||
|
|
||||||
|
bi->bi_chk_referrals = ndb_referrals;
|
||||||
|
#endif
|
||||||
|
bi->bi_operational = ndb_operational;
|
||||||
|
bi->bi_has_subordinates = ndb_has_subordinates;
|
||||||
|
bi->bi_entry_release_rw = 0;
|
||||||
|
bi->bi_entry_get_rw = ndb_entry_get;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* hooks for slap tools
|
||||||
|
*/
|
||||||
|
bi->bi_tool_entry_open = ndb_tool_entry_open;
|
||||||
|
bi->bi_tool_entry_close = ndb_tool_entry_close;
|
||||||
|
bi->bi_tool_entry_first = ndb_tool_entry_first;
|
||||||
|
bi->bi_tool_entry_next = ndb_tool_entry_next;
|
||||||
|
bi->bi_tool_entry_get = ndb_tool_entry_get;
|
||||||
|
bi->bi_tool_entry_put = ndb_tool_entry_put;
|
||||||
|
#if 0
|
||||||
|
bi->bi_tool_entry_reindex = ndb_tool_entry_reindex;
|
||||||
|
bi->bi_tool_sync = 0;
|
||||||
|
bi->bi_tool_dn2id_get = ndb_tool_dn2id_get;
|
||||||
|
bi->bi_tool_entry_modify = ndb_tool_entry_modify;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bi->bi_connection_init = 0;
|
||||||
|
bi->bi_connection_destroy = 0;
|
||||||
|
|
||||||
|
rc = ndb_back_init_cf( bi );
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SLAPD_NDB == SLAPD_MOD_DYNAMIC
|
||||||
|
|
||||||
|
/* conditionally define the init_module() function */
|
||||||
|
SLAP_BACKEND_INIT_MODULE( ndb )
|
||||||
|
|
||||||
|
#endif /* SLAPD_NDB == SLAPD_MOD_DYNAMIC */
|
||||||
|
|
||||||
652
servers/slapd/back-ndb/modify.cpp
Normal file
652
servers/slapd/back-ndb/modify.cpp
Normal file
|
|
@ -0,0 +1,652 @@
|
||||||
|
/* modify.cpp - ndb backend modify routine */
|
||||||
|
/* $OpenLDAP$ */
|
||||||
|
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||||
|
*
|
||||||
|
* Copyright 2008 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>.
|
||||||
|
*/
|
||||||
|
/* ACKNOWLEDGEMENTS:
|
||||||
|
* This work was initially developed by Howard Chu for inclusion
|
||||||
|
* in OpenLDAP Software. This work was sponsored by MySQL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "portable.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ac/string.h>
|
||||||
|
#include <ac/time.h>
|
||||||
|
|
||||||
|
#include "back-ndb.h"
|
||||||
|
|
||||||
|
/* This is a copy from slapd/mods.c, but with compaction tweaked
|
||||||
|
* to swap values from the tail into deleted slots, to reduce the
|
||||||
|
* overall update traffic.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
ndb_modify_delete(
|
||||||
|
Entry *e,
|
||||||
|
Modification *mod,
|
||||||
|
int permissive,
|
||||||
|
const char **text,
|
||||||
|
char *textbuf, size_t textlen,
|
||||||
|
int *idx )
|
||||||
|
{
|
||||||
|
Attribute *a;
|
||||||
|
MatchingRule *mr = mod->sm_desc->ad_type->sat_equality;
|
||||||
|
struct berval *cvals;
|
||||||
|
int *id2 = NULL;
|
||||||
|
int i, j, rc = 0, num;
|
||||||
|
unsigned flags;
|
||||||
|
char dummy = '\0';
|
||||||
|
|
||||||
|
/* For ordered vals, we have no choice but to preserve order */
|
||||||
|
if ( mod->sm_desc->ad_type->sat_flags & SLAP_AT_ORDERED_VAL )
|
||||||
|
return modify_delete_vindex( e, mod, permissive, text,
|
||||||
|
textbuf, textlen, idx );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If permissive is set, then the non-existence of an
|
||||||
|
* attribute is not treated as an error.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* delete the entire attribute */
|
||||||
|
if ( mod->sm_values == NULL ) {
|
||||||
|
rc = attr_delete( &e->e_attrs, mod->sm_desc );
|
||||||
|
|
||||||
|
if( permissive ) {
|
||||||
|
rc = LDAP_SUCCESS;
|
||||||
|
} else if( rc != LDAP_SUCCESS ) {
|
||||||
|
*text = textbuf;
|
||||||
|
snprintf( textbuf, textlen,
|
||||||
|
"modify/delete: %s: no such attribute",
|
||||||
|
mod->sm_desc->ad_cname.bv_val );
|
||||||
|
rc = LDAP_NO_SUCH_ATTRIBUTE;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: Catch old code that doesn't set sm_numvals.
|
||||||
|
*/
|
||||||
|
if ( !BER_BVISNULL( &mod->sm_values[mod->sm_numvals] )) {
|
||||||
|
for ( i = 0; !BER_BVISNULL( &mod->sm_values[i] ); i++ );
|
||||||
|
assert( mod->sm_numvals == i );
|
||||||
|
}
|
||||||
|
if ( !idx ) {
|
||||||
|
id2 = (int *)ch_malloc( mod->sm_numvals * sizeof( int ));
|
||||||
|
idx = id2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( mr == NULL || !mr->smr_match ) {
|
||||||
|
/* disallow specific attributes from being deleted if
|
||||||
|
no equality rule */
|
||||||
|
*text = textbuf;
|
||||||
|
snprintf( textbuf, textlen,
|
||||||
|
"modify/delete: %s: no equality matching rule",
|
||||||
|
mod->sm_desc->ad_cname.bv_val );
|
||||||
|
rc = LDAP_INAPPROPRIATE_MATCHING;
|
||||||
|
goto return_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* delete specific values - find the attribute first */
|
||||||
|
if ( (a = attr_find( e->e_attrs, mod->sm_desc )) == NULL ) {
|
||||||
|
if( permissive ) {
|
||||||
|
rc = LDAP_SUCCESS;
|
||||||
|
goto return_result;
|
||||||
|
}
|
||||||
|
*text = textbuf;
|
||||||
|
snprintf( textbuf, textlen,
|
||||||
|
"modify/delete: %s: no such attribute",
|
||||||
|
mod->sm_desc->ad_cname.bv_val );
|
||||||
|
rc = LDAP_NO_SUCH_ATTRIBUTE;
|
||||||
|
goto return_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( mod->sm_nvalues ) {
|
||||||
|
flags = SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX
|
||||||
|
| SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH
|
||||||
|
| SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH;
|
||||||
|
cvals = mod->sm_nvalues;
|
||||||
|
} else {
|
||||||
|
flags = SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX;
|
||||||
|
cvals = mod->sm_values;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Locate values to delete */
|
||||||
|
for ( i = 0; !BER_BVISNULL( &mod->sm_values[i] ); i++ ) {
|
||||||
|
unsigned sort;
|
||||||
|
rc = attr_valfind( a, flags, &cvals[i], &sort, NULL );
|
||||||
|
if ( rc == LDAP_SUCCESS ) {
|
||||||
|
idx[i] = sort;
|
||||||
|
} else if ( rc == LDAP_NO_SUCH_ATTRIBUTE ) {
|
||||||
|
if ( permissive ) {
|
||||||
|
idx[i] = -1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*text = textbuf;
|
||||||
|
snprintf( textbuf, textlen,
|
||||||
|
"modify/delete: %s: no such value",
|
||||||
|
mod->sm_desc->ad_cname.bv_val );
|
||||||
|
goto return_result;
|
||||||
|
} else {
|
||||||
|
*text = textbuf;
|
||||||
|
snprintf( textbuf, textlen,
|
||||||
|
"modify/delete: %s: matching rule failed",
|
||||||
|
mod->sm_desc->ad_cname.bv_val );
|
||||||
|
goto return_result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
num = a->a_numvals;
|
||||||
|
|
||||||
|
/* Delete the values */
|
||||||
|
for ( i = 0; i < mod->sm_numvals; i++ ) {
|
||||||
|
/* Skip permissive values that weren't found */
|
||||||
|
if ( idx[i] < 0 )
|
||||||
|
continue;
|
||||||
|
/* Skip duplicate delete specs */
|
||||||
|
if ( a->a_vals[idx[i]].bv_val == &dummy )
|
||||||
|
continue;
|
||||||
|
/* delete value and mark it as gone */
|
||||||
|
free( a->a_vals[idx[i]].bv_val );
|
||||||
|
a->a_vals[idx[i]].bv_val = &dummy;
|
||||||
|
if( a->a_nvals != a->a_vals ) {
|
||||||
|
free( a->a_nvals[idx[i]].bv_val );
|
||||||
|
a->a_nvals[idx[i]].bv_val = &dummy;
|
||||||
|
}
|
||||||
|
a->a_numvals--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* compact array */
|
||||||
|
for ( i=0; i<num; i++ ) {
|
||||||
|
if ( a->a_vals[i].bv_val != &dummy )
|
||||||
|
continue;
|
||||||
|
for ( --num; num > i && a->a_vals[num].bv_val == &dummy; num-- )
|
||||||
|
;
|
||||||
|
a->a_vals[i] = a->a_vals[num];
|
||||||
|
if ( a->a_nvals != a->a_vals )
|
||||||
|
a->a_nvals[i] = a->a_nvals[num];
|
||||||
|
}
|
||||||
|
|
||||||
|
BER_BVZERO( &a->a_vals[num] );
|
||||||
|
if (a->a_nvals != a->a_vals) {
|
||||||
|
BER_BVZERO( &a->a_nvals[num] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if no values remain, delete the entire attribute */
|
||||||
|
if ( !a->a_numvals ) {
|
||||||
|
if ( attr_delete( &e->e_attrs, mod->sm_desc ) ) {
|
||||||
|
/* Can never happen */
|
||||||
|
*text = textbuf;
|
||||||
|
snprintf( textbuf, textlen,
|
||||||
|
"modify/delete: %s: no such attribute",
|
||||||
|
mod->sm_desc->ad_cname.bv_val );
|
||||||
|
rc = LDAP_NO_SUCH_ATTRIBUTE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return_result:
|
||||||
|
if ( id2 )
|
||||||
|
ch_free( id2 );
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ndb_modify_internal(
|
||||||
|
Operation *op,
|
||||||
|
NdbArgs *NA,
|
||||||
|
const char **text,
|
||||||
|
char *textbuf,
|
||||||
|
size_t textlen )
|
||||||
|
{
|
||||||
|
struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private;
|
||||||
|
Modification *mod;
|
||||||
|
Modifications *ml;
|
||||||
|
Modifications *modlist = op->orm_modlist;
|
||||||
|
NdbAttrInfo **modai, *atmp;
|
||||||
|
const NdbDictionary::Dictionary *myDict;
|
||||||
|
const NdbDictionary::Table *myTable;
|
||||||
|
int got_oc = 0, nmods = 0, nai = 0, i, j;
|
||||||
|
int rc, indexed = 0;
|
||||||
|
Attribute *old = NULL;
|
||||||
|
|
||||||
|
Debug( LDAP_DEBUG_TRACE, "ndb_modify_internal: 0x%08lx: %s\n",
|
||||||
|
NA->e->e_id, NA->e->e_dn, 0);
|
||||||
|
|
||||||
|
if ( !acl_check_modlist( op, NA->e, modlist )) {
|
||||||
|
return LDAP_INSUFFICIENT_ACCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
old = attrs_dup( NA->e->e_attrs );
|
||||||
|
|
||||||
|
for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
|
||||||
|
mod = &ml->sml_mod;
|
||||||
|
nmods++;
|
||||||
|
|
||||||
|
switch ( mod->sm_op ) {
|
||||||
|
case LDAP_MOD_ADD:
|
||||||
|
Debug(LDAP_DEBUG_ARGS,
|
||||||
|
"ndb_modify_internal: add %s\n",
|
||||||
|
mod->sm_desc->ad_cname.bv_val, 0, 0);
|
||||||
|
rc = modify_add_values( NA->e, mod, get_permissiveModify(op),
|
||||||
|
text, textbuf, textlen );
|
||||||
|
if( rc != LDAP_SUCCESS ) {
|
||||||
|
Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: %d %s\n",
|
||||||
|
rc, *text, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LDAP_MOD_DELETE:
|
||||||
|
Debug(LDAP_DEBUG_ARGS,
|
||||||
|
"ndb_modify_internal: delete %s\n",
|
||||||
|
mod->sm_desc->ad_cname.bv_val, 0, 0);
|
||||||
|
rc = ndb_modify_delete( NA->e, mod, get_permissiveModify(op),
|
||||||
|
text, textbuf, textlen, NULL );
|
||||||
|
assert( rc != LDAP_TYPE_OR_VALUE_EXISTS );
|
||||||
|
if( rc != LDAP_SUCCESS ) {
|
||||||
|
Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: %d %s\n",
|
||||||
|
rc, *text, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LDAP_MOD_REPLACE:
|
||||||
|
Debug(LDAP_DEBUG_ARGS,
|
||||||
|
"ndb_modify_internal: replace %s\n",
|
||||||
|
mod->sm_desc->ad_cname.bv_val, 0, 0);
|
||||||
|
rc = modify_replace_values( NA->e, mod, get_permissiveModify(op),
|
||||||
|
text, textbuf, textlen );
|
||||||
|
if( rc != LDAP_SUCCESS ) {
|
||||||
|
Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: %d %s\n",
|
||||||
|
rc, *text, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LDAP_MOD_INCREMENT:
|
||||||
|
Debug(LDAP_DEBUG_ARGS,
|
||||||
|
"ndb_modify_internal: increment %s\n",
|
||||||
|
mod->sm_desc->ad_cname.bv_val, 0, 0);
|
||||||
|
rc = modify_increment_values( NA->e, mod, get_permissiveModify(op),
|
||||||
|
text, textbuf, textlen );
|
||||||
|
if( rc != LDAP_SUCCESS ) {
|
||||||
|
Debug(LDAP_DEBUG_ARGS,
|
||||||
|
"ndb_modify_internal: %d %s\n",
|
||||||
|
rc, *text, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SLAP_MOD_SOFTADD:
|
||||||
|
Debug(LDAP_DEBUG_ARGS,
|
||||||
|
"ndb_modify_internal: softadd %s\n",
|
||||||
|
mod->sm_desc->ad_cname.bv_val, 0, 0);
|
||||||
|
mod->sm_op = LDAP_MOD_ADD;
|
||||||
|
|
||||||
|
rc = modify_add_values( NA->e, mod, get_permissiveModify(op),
|
||||||
|
text, textbuf, textlen );
|
||||||
|
|
||||||
|
mod->sm_op = SLAP_MOD_SOFTADD;
|
||||||
|
|
||||||
|
if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) {
|
||||||
|
rc = LDAP_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( rc != LDAP_SUCCESS ) {
|
||||||
|
Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: %d %s\n",
|
||||||
|
rc, *text, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Debug(LDAP_DEBUG_ANY, "ndb_modify_internal: invalid op %d\n",
|
||||||
|
mod->sm_op, 0, 0);
|
||||||
|
*text = "Invalid modify operation";
|
||||||
|
rc = LDAP_OTHER;
|
||||||
|
Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: %d %s\n",
|
||||||
|
rc, *text, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( rc != LDAP_SUCCESS ) {
|
||||||
|
attrs_free( old );
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If objectClass was modified, reset the flags */
|
||||||
|
if ( mod->sm_desc == slap_schema.si_ad_objectClass ) {
|
||||||
|
NA->e->e_ocflags = 0;
|
||||||
|
got_oc = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check that the entry still obeys the schema */
|
||||||
|
rc = entry_schema_check( op, NA->e, NULL, get_relax(op), 0,
|
||||||
|
text, textbuf, textlen );
|
||||||
|
if ( rc != LDAP_SUCCESS || op->o_noop ) {
|
||||||
|
if ( rc != LDAP_SUCCESS ) {
|
||||||
|
Debug( LDAP_DEBUG_ANY,
|
||||||
|
"entry failed schema check: %s\n",
|
||||||
|
*text, 0, 0 );
|
||||||
|
}
|
||||||
|
attrs_free( old );
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* apply modifications to DB */
|
||||||
|
modai = (NdbAttrInfo **)op->o_tmpalloc( nmods * sizeof(NdbAttrInfo*), op->o_tmpmemctx );
|
||||||
|
|
||||||
|
/* Get the unique list of modified attributes */
|
||||||
|
ldap_pvt_thread_rdwr_rlock( &ni->ni_ai_rwlock );
|
||||||
|
for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
|
||||||
|
/* Already took care of objectclass */
|
||||||
|
if ( ml->sml_desc == slap_schema.si_ad_objectClass )
|
||||||
|
continue;
|
||||||
|
for ( i=0; i<nai; i++ ) {
|
||||||
|
if ( ml->sml_desc->ad_type == modai[i]->na_attr )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* This attr was already updated */
|
||||||
|
if ( i < nai )
|
||||||
|
continue;
|
||||||
|
modai[nai] = ndb_ai_find( ni, ml->sml_desc->ad_type );
|
||||||
|
if ( modai[nai]->na_flag & NDB_INFO_INDEX )
|
||||||
|
indexed++;
|
||||||
|
nai++;
|
||||||
|
}
|
||||||
|
ldap_pvt_thread_rdwr_runlock( &ni->ni_ai_rwlock );
|
||||||
|
|
||||||
|
if ( got_oc || indexed ) {
|
||||||
|
rc = ndb_entry_put_info( op->o_bd, NA, 1 );
|
||||||
|
if ( rc ) {
|
||||||
|
attrs_free( old );
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
myDict = NA->ndb->getDictionary();
|
||||||
|
|
||||||
|
/* sort modai so that OcInfo's are contiguous */
|
||||||
|
{
|
||||||
|
int j, k;
|
||||||
|
for ( i=0; i<nai; i++ ) {
|
||||||
|
for ( j=i+1; j<nai; j++ ) {
|
||||||
|
if ( modai[i]->na_oi == modai[j]->na_oi )
|
||||||
|
continue;
|
||||||
|
for ( k=j+1; k<nai; k++ ) {
|
||||||
|
if ( modai[i]->na_oi == modai[k]->na_oi ) {
|
||||||
|
atmp = modai[j];
|
||||||
|
modai[j] = modai[k];
|
||||||
|
modai[k] = atmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* there are no more na_oi's that match modai[i] */
|
||||||
|
if ( k == nai ) {
|
||||||
|
i = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* One call per table... */
|
||||||
|
for ( i=0; i<nai; i += j ) {
|
||||||
|
atmp = modai[i];
|
||||||
|
for ( j=i+1; j<nai; j++ )
|
||||||
|
if ( atmp->na_oi != modai[j]->na_oi )
|
||||||
|
break;
|
||||||
|
j -= i;
|
||||||
|
myTable = myDict->getTable( atmp->na_oi->no_table.bv_val );
|
||||||
|
if ( !myTable )
|
||||||
|
continue;
|
||||||
|
rc = ndb_oc_attrs( NA->txn, myTable, NA->e, atmp->na_oi, &modai[i], j, old );
|
||||||
|
if ( rc ) break;
|
||||||
|
}
|
||||||
|
attrs_free( old );
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
ndb_back_modify( Operation *op, SlapReply *rs )
|
||||||
|
{
|
||||||
|
struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private;
|
||||||
|
Entry e = {0};
|
||||||
|
int manageDSAit = get_manageDSAit( op );
|
||||||
|
char textbuf[SLAP_TEXT_BUFLEN];
|
||||||
|
size_t textlen = sizeof textbuf;
|
||||||
|
|
||||||
|
int num_retries = 0;
|
||||||
|
|
||||||
|
NdbArgs NA;
|
||||||
|
NdbRdns rdns;
|
||||||
|
struct berval matched;
|
||||||
|
|
||||||
|
LDAPControl **preread_ctrl = NULL;
|
||||||
|
LDAPControl **postread_ctrl = NULL;
|
||||||
|
LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
|
||||||
|
int num_ctrls = 0;
|
||||||
|
|
||||||
|
Debug( LDAP_DEBUG_ARGS, LDAP_XSTRING(ndb_back_modify) ": %s\n",
|
||||||
|
op->o_req_dn.bv_val, 0, 0 );
|
||||||
|
|
||||||
|
ctrls[num_ctrls] = NULL;
|
||||||
|
|
||||||
|
slap_mods_opattrs( op, &op->orm_modlist, 1 );
|
||||||
|
|
||||||
|
e.e_name = op->o_req_dn;
|
||||||
|
e.e_nname = op->o_req_ndn;
|
||||||
|
|
||||||
|
/* Get our NDB handle */
|
||||||
|
rs->sr_err = ndb_thread_handle( op, &NA.ndb );
|
||||||
|
rdns.nr_num = 0;
|
||||||
|
NA.rdns = &rdns;
|
||||||
|
NA.e = &e;
|
||||||
|
|
||||||
|
if( 0 ) {
|
||||||
|
retry: /* transaction retry */
|
||||||
|
NA.txn->close();
|
||||||
|
NA.txn = NULL;
|
||||||
|
if( e.e_attrs ) {
|
||||||
|
attrs_free( e.e_attrs );
|
||||||
|
e.e_attrs = NULL;
|
||||||
|
}
|
||||||
|
Debug(LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_modify) ": retrying...\n", 0, 0, 0);
|
||||||
|
if ( op->o_abandon ) {
|
||||||
|
rs->sr_err = SLAPD_ABANDON;
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
if ( NA.ocs ) {
|
||||||
|
ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx );
|
||||||
|
}
|
||||||
|
ndb_trans_backoff( ++num_retries );
|
||||||
|
}
|
||||||
|
NA.ocs = NULL;
|
||||||
|
|
||||||
|
/* begin transaction */
|
||||||
|
NA.txn = NA.ndb->startTransaction();
|
||||||
|
rs->sr_text = NULL;
|
||||||
|
if( !NA.txn ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_modify) ": startTransaction failed: %s (%d)\n",
|
||||||
|
NA.ndb->getNdbError().message, NA.ndb->getNdbError().code, 0 );
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
rs->sr_text = "internal error";
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get entry or ancestor */
|
||||||
|
rs->sr_err = ndb_entry_get_info( op, &NA, 0, &matched );
|
||||||
|
switch( rs->sr_err ) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case LDAP_NO_SUCH_OBJECT:
|
||||||
|
Debug( LDAP_DEBUG_ARGS,
|
||||||
|
"<=- ndb_back_modify: no such object %s\n",
|
||||||
|
op->o_req_dn.bv_val, 0, 0 );
|
||||||
|
rs->sr_matched = matched.bv_val;
|
||||||
|
if (NA.ocs )
|
||||||
|
ndb_check_referral( op, rs, &NA );
|
||||||
|
goto return_results;
|
||||||
|
#if 0
|
||||||
|
case DB_LOCK_DEADLOCK:
|
||||||
|
case DB_LOCK_NOTGRANTED:
|
||||||
|
goto retry;
|
||||||
|
#endif
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* acquire and lock entry */
|
||||||
|
rs->sr_err = ndb_entry_get_data( op, &NA, 1 );
|
||||||
|
|
||||||
|
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(ndb_back_modify) ": entry is referral\n",
|
||||||
|
0, 0, 0 );
|
||||||
|
|
||||||
|
rs->sr_err = LDAP_REFERRAL;
|
||||||
|
rs->sr_matched = e.e_name.bv_val;
|
||||||
|
rs->sr_flags = REP_REF_MUSTBEFREED;
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( get_assert( op ) &&
|
||||||
|
( test_filter( op, &e, (Filter*)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(ndb_back_modify) ": pre-read "
|
||||||
|
"failed!\n", 0, 0, 0 );
|
||||||
|
if ( op->o_preread & SLAP_CONTROL_CRITICAL ) {
|
||||||
|
/* FIXME: is it correct to abort
|
||||||
|
* operation if control fails? */
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Modify the entry */
|
||||||
|
rs->sr_err = ndb_modify_internal( op, &NA, &rs->sr_text, textbuf, textlen );
|
||||||
|
|
||||||
|
if( rs->sr_err != LDAP_SUCCESS ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_modify) ": modify failed (%d)\n",
|
||||||
|
rs->sr_err, 0, 0 );
|
||||||
|
#if 0
|
||||||
|
switch( rs->sr_err ) {
|
||||||
|
case DB_LOCK_DEADLOCK:
|
||||||
|
case DB_LOCK_NOTGRANTED:
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
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, &e,
|
||||||
|
&slap_post_read_bv, postread_ctrl ) )
|
||||||
|
{
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
"<=- " LDAP_XSTRING(ndb_back_modify)
|
||||||
|
": post-read failed!\n", 0, 0, 0 );
|
||||||
|
if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
|
||||||
|
/* FIXME: is it correct to abort
|
||||||
|
* operation if control fails? */
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( op->o_noop ) {
|
||||||
|
if (( rs->sr_err=NA.txn->execute( NdbTransaction::Rollback,
|
||||||
|
NdbOperation::AbortOnError, 1 )) != 0 ) {
|
||||||
|
rs->sr_text = "txn_abort (no-op) failed";
|
||||||
|
} else {
|
||||||
|
rs->sr_err = LDAP_X_NO_OPERATION;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (( rs->sr_err=NA.txn->execute( NdbTransaction::Commit,
|
||||||
|
NdbOperation::AbortOnError, 1 )) != 0 ) {
|
||||||
|
rs->sr_text = "txn_commit failed";
|
||||||
|
} else {
|
||||||
|
rs->sr_err = LDAP_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( rs->sr_err != LDAP_SUCCESS && rs->sr_err != LDAP_X_NO_OPERATION ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_modify) ": txn_%s failed: %s (%d)\n",
|
||||||
|
op->o_noop ? "abort (no-op)" : "commit",
|
||||||
|
NA.txn->getNdbError().message, NA.txn->getNdbError().code );
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
NA.txn->close();
|
||||||
|
NA.txn = NULL;
|
||||||
|
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_modify) ": updated%s id=%08lx dn=\"%s\"\n",
|
||||||
|
op->o_noop ? " (no-op)" : "",
|
||||||
|
e.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 ( NA.ocs ) {
|
||||||
|
ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx );
|
||||||
|
NA.ocs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( e.e_attrs != NULL ) {
|
||||||
|
attrs_free( e.e_attrs );
|
||||||
|
e.e_attrs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( NA.txn != NULL ) {
|
||||||
|
NA.txn->execute( Rollback );
|
||||||
|
NA.txn->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
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( 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;
|
||||||
|
}
|
||||||
558
servers/slapd/back-ndb/modrdn.cpp
Normal file
558
servers/slapd/back-ndb/modrdn.cpp
Normal file
|
|
@ -0,0 +1,558 @@
|
||||||
|
/* modrdn.cpp - ndb backend modrdn routine */
|
||||||
|
/* $OpenLDAP$ */
|
||||||
|
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||||
|
*
|
||||||
|
* Copyright 2008 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>.
|
||||||
|
*/
|
||||||
|
/* ACKNOWLEDGEMENTS:
|
||||||
|
* This work was initially developed by Howard Chu for inclusion
|
||||||
|
* in OpenLDAP Software. This work was sponsored by MySQL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "portable.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ac/string.h>
|
||||||
|
|
||||||
|
#include "back-ndb.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
ndb_back_modrdn( Operation *op, SlapReply *rs )
|
||||||
|
{
|
||||||
|
struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private;
|
||||||
|
AttributeDescription *children = slap_schema.si_ad_children;
|
||||||
|
AttributeDescription *entry = slap_schema.si_ad_entry;
|
||||||
|
struct berval new_dn = BER_BVNULL, new_ndn = BER_BVNULL;
|
||||||
|
Entry e = {0};
|
||||||
|
Entry e2 = {0};
|
||||||
|
char textbuf[SLAP_TEXT_BUFLEN];
|
||||||
|
size_t textlen = sizeof textbuf;
|
||||||
|
|
||||||
|
struct berval *np_dn = NULL; /* newSuperior dn */
|
||||||
|
struct berval *np_ndn = NULL; /* newSuperior ndn */
|
||||||
|
|
||||||
|
int manageDSAit = get_manageDSAit( op );
|
||||||
|
int num_retries = 0;
|
||||||
|
|
||||||
|
NdbArgs NA, NA2;
|
||||||
|
NdbRdns rdns, rdn2;
|
||||||
|
struct berval matched;
|
||||||
|
|
||||||
|
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(ndb_back_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" );
|
||||||
|
|
||||||
|
ctrls[num_ctrls] = NULL;
|
||||||
|
|
||||||
|
slap_mods_opattrs( op, &op->orr_modlist, 1 );
|
||||||
|
|
||||||
|
e.e_name = op->o_req_dn;
|
||||||
|
e.e_nname = op->o_req_ndn;
|
||||||
|
|
||||||
|
/* Get our NDB handle */
|
||||||
|
rs->sr_err = ndb_thread_handle( op, &NA.ndb );
|
||||||
|
rdns.nr_num = 0;
|
||||||
|
NA.rdns = &rdns;
|
||||||
|
NA.e = &e;
|
||||||
|
NA2.ndb = NA.ndb;
|
||||||
|
NA2.e = &e2;
|
||||||
|
NA2.rdns = &rdn2;
|
||||||
|
|
||||||
|
if( 0 ) {
|
||||||
|
retry: /* transaction retry */
|
||||||
|
NA.txn->close();
|
||||||
|
NA.txn = NULL;
|
||||||
|
if ( e.e_attrs ) {
|
||||||
|
attrs_free( e.e_attrs );
|
||||||
|
e.e_attrs = NULL;
|
||||||
|
}
|
||||||
|
Debug( LDAP_DEBUG_TRACE, "==>" LDAP_XSTRING(ndb_back_modrdn)
|
||||||
|
": retrying...\n", 0, 0, 0 );
|
||||||
|
if ( op->o_abandon ) {
|
||||||
|
rs->sr_err = SLAPD_ABANDON;
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
if ( NA2.ocs ) {
|
||||||
|
ber_bvarray_free_x( NA2.ocs, op->o_tmpmemctx );
|
||||||
|
}
|
||||||
|
if ( NA.ocs ) {
|
||||||
|
ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx );
|
||||||
|
}
|
||||||
|
ndb_trans_backoff( ++num_retries );
|
||||||
|
}
|
||||||
|
NA.ocs = NULL;
|
||||||
|
NA2.ocs = NULL;
|
||||||
|
|
||||||
|
/* begin transaction */
|
||||||
|
NA.txn = NA.ndb->startTransaction();
|
||||||
|
rs->sr_text = NULL;
|
||||||
|
if( !NA.txn ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_modrdn) ": startTransaction failed: %s (%d)\n",
|
||||||
|
NA.ndb->getNdbError().message, NA.ndb->getNdbError().code, 0 );
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
rs->sr_text = "internal error";
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
NA2.txn = NA.txn;
|
||||||
|
|
||||||
|
/* get entry */
|
||||||
|
rs->sr_err = ndb_entry_get_info( op, &NA, 1, &matched );
|
||||||
|
switch( rs->sr_err ) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case LDAP_NO_SUCH_OBJECT:
|
||||||
|
Debug( LDAP_DEBUG_ARGS,
|
||||||
|
"<=- ndb_back_modrdn: no such object %s\n",
|
||||||
|
op->o_req_dn.bv_val, 0, 0 );
|
||||||
|
rs->sr_matched = matched.bv_val;
|
||||||
|
if ( NA.ocs )
|
||||||
|
ndb_check_referral( op, rs, &NA );
|
||||||
|
goto return_results;
|
||||||
|
#if 0
|
||||||
|
case DB_LOCK_DEADLOCK:
|
||||||
|
case DB_LOCK_NOTGRANTED:
|
||||||
|
goto retry;
|
||||||
|
#endif
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* acquire and lock entry */
|
||||||
|
rs->sr_err = ndb_entry_get_data( op, &NA, 1 );
|
||||||
|
if ( rs->sr_err )
|
||||||
|
goto return_results;
|
||||||
|
|
||||||
|
if ( !manageDSAit && is_entry_glue( &e )) {
|
||||||
|
rs->sr_err = LDAP_NO_SUCH_OBJECT;
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( get_assert( op ) &&
|
||||||
|
( test_filter( op, &e, (Filter *)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 ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE, "no access to entry\n", 0,
|
||||||
|
0, 0 );
|
||||||
|
rs->sr_text = "no write access to old entry";
|
||||||
|
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Can't do it if we have kids */
|
||||||
|
rs->sr_err = ndb_has_children( &NA, &rc );
|
||||||
|
if ( rs->sr_err ) {
|
||||||
|
Debug(LDAP_DEBUG_ARGS,
|
||||||
|
"<=- " LDAP_XSTRING(ndb_back_modrdn)
|
||||||
|
": has_children failed: %s (%d)\n",
|
||||||
|
NA.txn->getNdbError().message, NA.txn->getNdbError().code, 0 );
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
rs->sr_text = "internal error";
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
if ( rc == LDAP_COMPARE_TRUE ) {
|
||||||
|
Debug(LDAP_DEBUG_ARGS,
|
||||||
|
"<=- " LDAP_XSTRING(ndb_back_modrdn)
|
||||||
|
": non-leaf %s\n",
|
||||||
|
op->o_req_dn.bv_val, 0, 0);
|
||||||
|
rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
|
||||||
|
rs->sr_text = "subtree rename not supported";
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!manageDSAit && is_entry_referral( &e ) ) {
|
||||||
|
/* entry is a referral, don't allow modrdn */
|
||||||
|
rs->sr_ref = get_entry_referrals( op, &e );
|
||||||
|
|
||||||
|
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn)
|
||||||
|
": entry %s is referral\n", e.e_dn, 0, 0 );
|
||||||
|
|
||||||
|
rs->sr_err = LDAP_REFERRAL,
|
||||||
|
rs->sr_matched = op->o_req_dn.bv_val;
|
||||||
|
rs->sr_flags = REP_REF_MUSTBEFREED;
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( be_issuffix( op->o_bd, &e.e_nname ) ) {
|
||||||
|
/* There can only be one suffix entry */
|
||||||
|
rs->sr_err = LDAP_NAMING_VIOLATION;
|
||||||
|
rs->sr_text = "cannot rename suffix entry";
|
||||||
|
goto return_results;
|
||||||
|
} else {
|
||||||
|
dnParent( &e.e_nname, &e2.e_nname );
|
||||||
|
dnParent( &e.e_name, &e2.e_name );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check parent for "children" acl */
|
||||||
|
rs->sr_err = access_allowed( op, &e2,
|
||||||
|
children, NULL,
|
||||||
|
op->oq_modrdn.rs_newSup == NULL ?
|
||||||
|
ACL_WRITE : ACL_WDEL,
|
||||||
|
NULL );
|
||||||
|
|
||||||
|
if ( ! rs->sr_err ) {
|
||||||
|
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
||||||
|
Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
|
||||||
|
0, 0 );
|
||||||
|
rs->sr_text = "no write access to old parent's children";
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_modrdn) ": wr to children "
|
||||||
|
"of entry %s OK\n", e2.e_name.bv_val, 0, 0 );
|
||||||
|
|
||||||
|
if ( op->oq_modrdn.rs_newSup != NULL ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_modrdn)
|
||||||
|
": new parent \"%s\" requested...\n",
|
||||||
|
op->oq_modrdn.rs_newSup->bv_val, 0, 0 );
|
||||||
|
|
||||||
|
/* newSuperior == oldParent? */
|
||||||
|
if( dn_match( &e2.e_nname, 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, e2.e_name.bv_val, 0 );
|
||||||
|
op->oq_modrdn.rs_newSup = NULL; /* ignore newSuperior */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( op->oq_modrdn.rs_newSup != NULL ) {
|
||||||
|
if ( op->oq_modrdn.rs_newSup->bv_len ) {
|
||||||
|
rdn2.nr_num = 0;
|
||||||
|
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? */
|
||||||
|
|
||||||
|
e2.e_name = *np_dn;
|
||||||
|
e2.e_nname = *np_ndn;
|
||||||
|
rs->sr_err = ndb_entry_get_info( op, &NA2, 1, NULL );
|
||||||
|
switch( rs->sr_err ) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case LDAP_NO_SUCH_OBJECT:
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_modrdn)
|
||||||
|
": newSup(ndn=%s) not here!\n",
|
||||||
|
np_ndn->bv_val, 0, 0);
|
||||||
|
rs->sr_text = "new superior not found";
|
||||||
|
goto return_results;
|
||||||
|
#if 0
|
||||||
|
case DB_LOCK_DEADLOCK:
|
||||||
|
case DB_LOCK_NOTGRANTED:
|
||||||
|
goto retry;
|
||||||
|
#endif
|
||||||
|
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 ( NA2.ocs ) {
|
||||||
|
Attribute a;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for ( i=0; !BER_BVISNULL( &NA2.ocs[i] ); i++);
|
||||||
|
a.a_numvals = i;
|
||||||
|
a.a_desc = slap_schema.si_ad_objectClass;
|
||||||
|
a.a_vals = NA2.ocs;
|
||||||
|
a.a_nvals = NA2.ocs;
|
||||||
|
a.a_next = NULL;
|
||||||
|
e2.e_attrs = &a;
|
||||||
|
|
||||||
|
if ( is_entry_alias( &e2 )) {
|
||||||
|
/* parent is an alias, don't allow move */
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_modrdn)
|
||||||
|
": entry is alias\n",
|
||||||
|
0, 0, 0 );
|
||||||
|
rs->sr_text = "new superior is an alias";
|
||||||
|
rs->sr_err = LDAP_ALIAS_PROBLEM;
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( is_entry_referral( &e2 ) ) {
|
||||||
|
/* parent is a referral, don't allow move */
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_modrdn)
|
||||||
|
": entry is referral\n",
|
||||||
|
0, 0, 0 );
|
||||||
|
rs->sr_text = "new superior is a referral";
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check newSuperior for "children" acl */
|
||||||
|
rs->sr_err = access_allowed( op, &e2, children,
|
||||||
|
NULL, ACL_WADD, NULL );
|
||||||
|
if( ! rs->sr_err ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_modrdn)
|
||||||
|
": no wr to newSup children\n",
|
||||||
|
0, 0, 0 );
|
||||||
|
rs->sr_text = "no write access to new superior's children";
|
||||||
|
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_modrdn)
|
||||||
|
": wr to new parent OK id=%ld\n",
|
||||||
|
(long) e2.e_id, 0, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build target dn and make sure target entry doesn't exist already. */
|
||||||
|
if (!new_dn.bv_val) {
|
||||||
|
build_new_dn( &new_dn, &e2.e_name, &op->oq_modrdn.rs_newrdn, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!new_ndn.bv_val) {
|
||||||
|
build_new_dn( &new_ndn, &e2.e_nname, &op->oq_modrdn.rs_nnewrdn, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn) ": new ndn=%s\n",
|
||||||
|
new_ndn.bv_val, 0, 0 );
|
||||||
|
|
||||||
|
/* Allow rename to same DN */
|
||||||
|
if ( !bvmatch ( &new_ndn, &e.e_nname )) {
|
||||||
|
rdn2.nr_num = 0;
|
||||||
|
e2.e_name = new_dn;
|
||||||
|
e2.e_nname = new_ndn;
|
||||||
|
NA2.ocs = &matched;
|
||||||
|
rs->sr_err = ndb_entry_get_info( op, &NA2, 1, NULL );
|
||||||
|
NA2.ocs = NULL;
|
||||||
|
switch( rs->sr_err ) {
|
||||||
|
#if 0
|
||||||
|
case DB_LOCK_DEADLOCK:
|
||||||
|
case DB_LOCK_NOTGRANTED:
|
||||||
|
goto retry;
|
||||||
|
#endif
|
||||||
|
case LDAP_NO_SUCH_OBJECT:
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
rs->sr_err = LDAP_ALREADY_EXISTS;
|
||||||
|
goto return_results;
|
||||||
|
default:
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
rs->sr_text = "internal error";
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert( op->orr_modlist != NULL );
|
||||||
|
|
||||||
|
if( op->o_preread ) {
|
||||||
|
if( preread_ctrl == NULL ) {
|
||||||
|
preread_ctrl = &ctrls[num_ctrls++];
|
||||||
|
ctrls[num_ctrls] = NULL;
|
||||||
|
}
|
||||||
|
if( slap_read_controls( op, rs, &e,
|
||||||
|
&slap_pre_read_bv, preread_ctrl ) )
|
||||||
|
{
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
"<=- " LDAP_XSTRING(ndb_back_modrdn)
|
||||||
|
": pre-read failed!\n", 0, 0, 0 );
|
||||||
|
if ( op->o_preread & SLAP_CONTROL_CRITICAL ) {
|
||||||
|
/* FIXME: is it correct to abort
|
||||||
|
* operation if control fails? */
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* delete old DN */
|
||||||
|
rs->sr_err = ndb_entry_del_info( op->o_bd, &NA );
|
||||||
|
if ( rs->sr_err != 0 ) {
|
||||||
|
Debug(LDAP_DEBUG_TRACE,
|
||||||
|
"<=- " LDAP_XSTRING(ndb_back_modrdn)
|
||||||
|
": dn2id del failed: %s (%d)\n",
|
||||||
|
NA.txn->getNdbError().message, NA.txn->getNdbError().code, 0 );
|
||||||
|
#if 0
|
||||||
|
switch( rs->sr_err ) {
|
||||||
|
case DB_LOCK_DEADLOCK:
|
||||||
|
case DB_LOCK_NOTGRANTED:
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
rs->sr_text = "DN index delete fail";
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy entry fields */
|
||||||
|
e2.e_attrs = e.e_attrs;
|
||||||
|
e2.e_id = e.e_id;
|
||||||
|
|
||||||
|
/* add new DN */
|
||||||
|
rs->sr_err = ndb_entry_put_info( op->o_bd, &NA2, 0 );
|
||||||
|
if ( rs->sr_err != 0 ) {
|
||||||
|
Debug(LDAP_DEBUG_TRACE,
|
||||||
|
"<=- " LDAP_XSTRING(ndb_back_modrdn)
|
||||||
|
": dn2id add failed: %s (%d)\n",
|
||||||
|
NA.txn->getNdbError().message, NA.txn->getNdbError().code, 0 );
|
||||||
|
#if 0
|
||||||
|
switch( rs->sr_err ) {
|
||||||
|
case DB_LOCK_DEADLOCK:
|
||||||
|
case DB_LOCK_NOTGRANTED:
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
rs->sr_text = "DN index add failed";
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* modify entry */
|
||||||
|
rs->sr_err = ndb_modify_internal( op, &NA2,
|
||||||
|
&rs->sr_text, textbuf, textlen );
|
||||||
|
if( rs->sr_err != LDAP_SUCCESS ) {
|
||||||
|
Debug(LDAP_DEBUG_TRACE,
|
||||||
|
"<=- " LDAP_XSTRING(ndb_back_modrdn)
|
||||||
|
": modify failed: %s (%d)\n",
|
||||||
|
NA.txn->getNdbError().message, NA.txn->getNdbError().code, 0 );
|
||||||
|
#if 0
|
||||||
|
switch( rs->sr_err ) {
|
||||||
|
case DB_LOCK_DEADLOCK:
|
||||||
|
case DB_LOCK_NOTGRANTED:
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.e_attrs = e2.e_attrs;
|
||||||
|
|
||||||
|
if( op->o_postread ) {
|
||||||
|
if( postread_ctrl == NULL ) {
|
||||||
|
postread_ctrl = &ctrls[num_ctrls++];
|
||||||
|
ctrls[num_ctrls] = NULL;
|
||||||
|
}
|
||||||
|
if( slap_read_controls( op, rs, &e2,
|
||||||
|
&slap_post_read_bv, postread_ctrl ) )
|
||||||
|
{
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
"<=- " LDAP_XSTRING(ndb_back_modrdn)
|
||||||
|
": post-read failed!\n", 0, 0, 0 );
|
||||||
|
if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
|
||||||
|
/* FIXME: is it correct to abort
|
||||||
|
* operation if control fails? */
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( op->o_noop ) {
|
||||||
|
if (( rs->sr_err=NA.txn->execute( NdbTransaction::Rollback,
|
||||||
|
NdbOperation::AbortOnError, 1 )) != 0 ) {
|
||||||
|
rs->sr_text = "txn_abort (no-op) failed";
|
||||||
|
} else {
|
||||||
|
rs->sr_err = LDAP_X_NO_OPERATION;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (( rs->sr_err=NA.txn->execute( NdbTransaction::Commit,
|
||||||
|
NdbOperation::AbortOnError, 1 )) != 0 ) {
|
||||||
|
rs->sr_text = "txn_commit failed";
|
||||||
|
} else {
|
||||||
|
rs->sr_err = LDAP_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( rs->sr_err != LDAP_SUCCESS && rs->sr_err != LDAP_X_NO_OPERATION ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_modrdn) ": txn_%s failed: %s (%d)\n",
|
||||||
|
op->o_noop ? "abort (no-op)" : "commit",
|
||||||
|
NA.txn->getNdbError().message, NA.txn->getNdbError().code );
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
goto return_results;
|
||||||
|
}
|
||||||
|
NA.txn->close();
|
||||||
|
NA.txn = NULL;
|
||||||
|
|
||||||
|
Debug(LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_modrdn)
|
||||||
|
": rdn modified%s id=%08lx dn=\"%s\"\n",
|
||||||
|
op->o_noop ? " (no-op)" : "",
|
||||||
|
e.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 ( NA2.ocs ) {
|
||||||
|
ber_bvarray_free_x( NA2.ocs, op->o_tmpmemctx );
|
||||||
|
NA2.ocs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( NA.ocs ) {
|
||||||
|
ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx );
|
||||||
|
NA.ocs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( e.e_attrs ) {
|
||||||
|
attrs_free( e.e_attrs );
|
||||||
|
e.e_attrs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( NA.txn != NULL ) {
|
||||||
|
NA.txn->execute( Rollback );
|
||||||
|
NA.txn->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
send_ldap_result( op, rs );
|
||||||
|
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 );
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
1677
servers/slapd/back-ndb/ndbio.cpp
Normal file
1677
servers/slapd/back-ndb/ndbio.cpp
Normal file
File diff suppressed because it is too large
Load diff
166
servers/slapd/back-ndb/proto-ndb.h
Normal file
166
servers/slapd/back-ndb/proto-ndb.h
Normal file
|
|
@ -0,0 +1,166 @@
|
||||||
|
/* $OpenLDAP$ */
|
||||||
|
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||||
|
*
|
||||||
|
* Copyright 2008 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>.
|
||||||
|
*/
|
||||||
|
/* ACKNOWLEDGEMENTS:
|
||||||
|
* This work was initially developed by Howard Chu for inclusion
|
||||||
|
* in OpenLDAP Software. This work was sponsored by MySQL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PROTO_NDB_H
|
||||||
|
#define _PROTO_NDB_H
|
||||||
|
|
||||||
|
LDAP_BEGIN_DECL
|
||||||
|
|
||||||
|
extern BI_init ndb_back_initialize;
|
||||||
|
|
||||||
|
extern BI_open ndb_back_open;
|
||||||
|
extern BI_close ndb_back_close;
|
||||||
|
extern BI_destroy ndb_back_destroy;
|
||||||
|
|
||||||
|
extern BI_db_init ndb_back_db_init;
|
||||||
|
extern BI_db_destroy ndb_back_db_destroy;
|
||||||
|
|
||||||
|
extern BI_op_bind ndb_back_bind;
|
||||||
|
extern BI_op_unbind ndb_back_unbind;
|
||||||
|
extern BI_op_search ndb_back_search;
|
||||||
|
extern BI_op_compare ndb_back_compare;
|
||||||
|
extern BI_op_modify ndb_back_modify;
|
||||||
|
extern BI_op_modrdn ndb_back_modrdn;
|
||||||
|
extern BI_op_add ndb_back_add;
|
||||||
|
extern BI_op_delete ndb_back_delete;
|
||||||
|
|
||||||
|
extern BI_operational ndb_operational;
|
||||||
|
extern BI_has_subordinates ndb_has_subordinates;
|
||||||
|
extern BI_entry_get_rw ndb_entry_get;
|
||||||
|
|
||||||
|
extern BI_tool_entry_open ndb_tool_entry_open;
|
||||||
|
extern BI_tool_entry_close ndb_tool_entry_close;
|
||||||
|
extern BI_tool_entry_first ndb_tool_entry_first;
|
||||||
|
extern BI_tool_entry_next ndb_tool_entry_next;
|
||||||
|
extern BI_tool_entry_get ndb_tool_entry_get;
|
||||||
|
extern BI_tool_entry_put ndb_tool_entry_put;
|
||||||
|
extern BI_tool_dn2id_get ndb_tool_dn2id_get;
|
||||||
|
|
||||||
|
extern int ndb_modify_internal(
|
||||||
|
Operation *op,
|
||||||
|
NdbArgs *NA,
|
||||||
|
const char **text,
|
||||||
|
char *textbuf,
|
||||||
|
size_t textlen );
|
||||||
|
|
||||||
|
extern int
|
||||||
|
ndb_entry_get_data(
|
||||||
|
Operation *op,
|
||||||
|
NdbArgs *args,
|
||||||
|
int update );
|
||||||
|
|
||||||
|
extern int
|
||||||
|
ndb_entry_put_data(
|
||||||
|
BackendDB *be,
|
||||||
|
NdbArgs *args );
|
||||||
|
|
||||||
|
extern int
|
||||||
|
ndb_entry_del_data(
|
||||||
|
BackendDB *be,
|
||||||
|
NdbArgs *args );
|
||||||
|
|
||||||
|
extern int
|
||||||
|
ndb_entry_put_info(
|
||||||
|
BackendDB *be,
|
||||||
|
NdbArgs *args,
|
||||||
|
int update );
|
||||||
|
|
||||||
|
extern int
|
||||||
|
ndb_entry_get_info(
|
||||||
|
Operation *op,
|
||||||
|
NdbArgs *args,
|
||||||
|
int update,
|
||||||
|
struct berval *matched );
|
||||||
|
|
||||||
|
extern "C" int
|
||||||
|
ndb_entry_del_info(
|
||||||
|
BackendDB *be,
|
||||||
|
NdbArgs *args );
|
||||||
|
|
||||||
|
extern int
|
||||||
|
ndb_dn2rdns(
|
||||||
|
struct berval *dn,
|
||||||
|
NdbRdns *buf );
|
||||||
|
|
||||||
|
extern NdbAttrInfo *
|
||||||
|
ndb_ai_find( struct ndb_info *ni, AttributeType *at );
|
||||||
|
|
||||||
|
extern NdbAttrInfo *
|
||||||
|
ndb_ai_get( struct ndb_info *ni, struct berval *at );
|
||||||
|
|
||||||
|
extern int
|
||||||
|
ndb_aset_get( struct ndb_info *ni, struct berval *sname, struct berval *attrs, NdbOcInfo **ret );
|
||||||
|
|
||||||
|
extern int
|
||||||
|
ndb_aset_create( struct ndb_info *ni, NdbOcInfo *oci );
|
||||||
|
|
||||||
|
extern int
|
||||||
|
ndb_oc_read( struct ndb_info *ni, const NdbDictionary::Dictionary *dict );
|
||||||
|
|
||||||
|
extern int
|
||||||
|
ndb_oc_attrs(
|
||||||
|
NdbTransaction *txn,
|
||||||
|
const NdbDictionary::Table *myTable,
|
||||||
|
Entry *e,
|
||||||
|
NdbOcInfo *no,
|
||||||
|
NdbAttrInfo **attrs,
|
||||||
|
int nattrs,
|
||||||
|
Attribute *old );
|
||||||
|
|
||||||
|
extern int
|
||||||
|
ndb_has_children(
|
||||||
|
NdbArgs *NA,
|
||||||
|
int *hasChildren );
|
||||||
|
|
||||||
|
extern struct berval *
|
||||||
|
ndb_str2bvarray(
|
||||||
|
char *str,
|
||||||
|
int len,
|
||||||
|
char delim,
|
||||||
|
void *ctx );
|
||||||
|
|
||||||
|
extern struct berval *
|
||||||
|
ndb_ref2oclist(
|
||||||
|
const char *ref,
|
||||||
|
void *ctx );
|
||||||
|
|
||||||
|
extern int
|
||||||
|
ndb_next_id(
|
||||||
|
BackendDB *be,
|
||||||
|
Ndb *ndb,
|
||||||
|
ID *id );
|
||||||
|
|
||||||
|
extern int
|
||||||
|
ndb_thread_handle(
|
||||||
|
Operation *op,
|
||||||
|
Ndb **ndb );
|
||||||
|
|
||||||
|
extern int
|
||||||
|
ndb_back_init_cf(
|
||||||
|
BackendInfo *bi );
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
ndb_trans_backoff( int num_retries );
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
ndb_check_referral( Operation *op, SlapReply *rs, NdbArgs *NA );
|
||||||
|
|
||||||
|
LDAP_END_DECL
|
||||||
|
|
||||||
|
#endif /* _PROTO_NDB_H */
|
||||||
844
servers/slapd/back-ndb/search.cpp
Normal file
844
servers/slapd/back-ndb/search.cpp
Normal file
|
|
@ -0,0 +1,844 @@
|
||||||
|
/* search.cpp - tools for slap tools */
|
||||||
|
/* $OpenLDAP$ */
|
||||||
|
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||||
|
*
|
||||||
|
* Copyright 2008 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>.
|
||||||
|
*/
|
||||||
|
/* ACKNOWLEDGEMENTS:
|
||||||
|
* This work was initially developed by Howard Chu for inclusion
|
||||||
|
* in OpenLDAP Software. This work was sponsored by MySQL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "portable.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ac/string.h>
|
||||||
|
#include <ac/errno.h>
|
||||||
|
|
||||||
|
#include "lutil.h"
|
||||||
|
|
||||||
|
#include "back-ndb.h"
|
||||||
|
|
||||||
|
static int
|
||||||
|
ndb_dn2bound(
|
||||||
|
NdbIndexScanOperation *myop,
|
||||||
|
NdbRdns *rdns
|
||||||
|
)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
/* Walk thru RDNs */
|
||||||
|
for ( i=0; i<rdns->nr_num; i++ ) {
|
||||||
|
/* Note: RDN_COLUMN offset not needed here */
|
||||||
|
if ( myop->setBound( i, NdbIndexScanOperation::BoundEQ, rdns->nr_buf[i] ))
|
||||||
|
return LDAP_OTHER;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that all filter terms reside in the same table.
|
||||||
|
*
|
||||||
|
* If any of the filter terms are indexed, then only an IndexScan of the OL_index
|
||||||
|
* will be performed. If none are indexed, but all the terms reside in a single
|
||||||
|
* table, a Scan can be performed with the LDAP filter transformed into a ScanFilter.
|
||||||
|
*
|
||||||
|
* Otherwise, a full scan of the DB must be done with all filtering done by slapd.
|
||||||
|
*/
|
||||||
|
static int ndb_filter_check( struct ndb_info *ni, Filter *f,
|
||||||
|
NdbOcInfo **oci, int *indexed, int *ocfilter )
|
||||||
|
{
|
||||||
|
AttributeDescription *ad = NULL;
|
||||||
|
ber_tag_t choice = f->f_choice;
|
||||||
|
int rc = 0, undef = 0;
|
||||||
|
|
||||||
|
if ( choice & SLAPD_FILTER_UNDEFINED ) {
|
||||||
|
choice &= SLAPD_FILTER_MASK;
|
||||||
|
undef = 1;
|
||||||
|
}
|
||||||
|
switch( choice ) {
|
||||||
|
case LDAP_FILTER_AND:
|
||||||
|
case LDAP_FILTER_OR:
|
||||||
|
case LDAP_FILTER_NOT:
|
||||||
|
for ( f = f->f_list; f; f=f->f_next ) {
|
||||||
|
rc = ndb_filter_check( ni, f, oci, indexed, ocfilter );
|
||||||
|
if ( rc ) return rc;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LDAP_FILTER_PRESENT:
|
||||||
|
ad = f->f_desc;
|
||||||
|
break;
|
||||||
|
case LDAP_FILTER_EQUALITY:
|
||||||
|
case LDAP_FILTER_SUBSTRINGS:
|
||||||
|
case LDAP_FILTER_GE:
|
||||||
|
case LDAP_FILTER_LE:
|
||||||
|
case LDAP_FILTER_APPROX:
|
||||||
|
ad = f->f_av_desc;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ( ad && !undef ) {
|
||||||
|
NdbAttrInfo *ai;
|
||||||
|
/* ObjectClass filtering is in dn2id table */
|
||||||
|
if ( ad == slap_schema.si_ad_objectClass ) {
|
||||||
|
if ( choice == LDAP_FILTER_EQUALITY )
|
||||||
|
(*ocfilter)++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ai = ndb_ai_find( ni, ad->ad_type );
|
||||||
|
if ( ai ) {
|
||||||
|
if ( ai->na_flag & NDB_INFO_INDEX )
|
||||||
|
(*indexed)++;
|
||||||
|
if ( *oci ) {
|
||||||
|
if ( ai->na_oi != *oci )
|
||||||
|
rc = -1;
|
||||||
|
} else {
|
||||||
|
*oci = ai->na_oi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ndb_filter_set( Operation *op, struct ndb_info *ni, Filter *f, int indexed,
|
||||||
|
NdbIndexScanOperation *scan, NdbScanFilter *sf, int *bounds )
|
||||||
|
{
|
||||||
|
AttributeDescription *ad = NULL;
|
||||||
|
ber_tag_t choice = f->f_choice;
|
||||||
|
int undef = 0;
|
||||||
|
|
||||||
|
if ( choice & SLAPD_FILTER_UNDEFINED ) {
|
||||||
|
choice &= SLAPD_FILTER_MASK;
|
||||||
|
undef = 1;
|
||||||
|
}
|
||||||
|
switch( choice ) {
|
||||||
|
case LDAP_FILTER_NOT:
|
||||||
|
/* no indexing for these */
|
||||||
|
break;
|
||||||
|
case LDAP_FILTER_OR:
|
||||||
|
/* FIXME: these bounds aren't right. */
|
||||||
|
if ( indexed ) {
|
||||||
|
scan->end_of_bound( (*bounds)++ );
|
||||||
|
}
|
||||||
|
case LDAP_FILTER_AND:
|
||||||
|
if ( sf ) {
|
||||||
|
sf->begin( choice == LDAP_FILTER_OR ? NdbScanFilter::OR : NdbScanFilter::AND );
|
||||||
|
}
|
||||||
|
for ( f = f->f_list; f; f=f->f_next ) {
|
||||||
|
if ( ndb_filter_set( op, ni, f, indexed, scan, sf, bounds ))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ( sf ) {
|
||||||
|
sf->end();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LDAP_FILTER_PRESENT:
|
||||||
|
ad = f->f_desc;
|
||||||
|
break;
|
||||||
|
case LDAP_FILTER_EQUALITY:
|
||||||
|
case LDAP_FILTER_SUBSTRINGS:
|
||||||
|
case LDAP_FILTER_GE:
|
||||||
|
case LDAP_FILTER_LE:
|
||||||
|
case LDAP_FILTER_APPROX:
|
||||||
|
ad = f->f_av_desc;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ( ad && !undef ) {
|
||||||
|
NdbAttrInfo *ai;
|
||||||
|
/* ObjectClass filtering is in dn2id table */
|
||||||
|
if ( ad == slap_schema.si_ad_objectClass ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ai = ndb_ai_find( ni, ad->ad_type );
|
||||||
|
if ( ai ) {
|
||||||
|
int rc;
|
||||||
|
if ( ai->na_flag & NDB_INFO_INDEX ) {
|
||||||
|
char *buf, *ptr;
|
||||||
|
NdbIndexScanOperation::BoundType bt;
|
||||||
|
|
||||||
|
switch(choice) {
|
||||||
|
case LDAP_FILTER_PRESENT:
|
||||||
|
rc = scan->setBound( ai->na_ixcol - IDX_COLUMN,
|
||||||
|
NdbIndexScanOperation::BoundGT, NULL );
|
||||||
|
break;
|
||||||
|
case LDAP_FILTER_EQUALITY:
|
||||||
|
case LDAP_FILTER_APPROX:
|
||||||
|
bt = NdbIndexScanOperation::BoundEQ;
|
||||||
|
goto setit;
|
||||||
|
case LDAP_FILTER_GE:
|
||||||
|
bt = NdbIndexScanOperation::BoundGE;
|
||||||
|
goto setit;
|
||||||
|
case LDAP_FILTER_LE:
|
||||||
|
bt = NdbIndexScanOperation::BoundLE;
|
||||||
|
setit:
|
||||||
|
rc = f->f_av_value.bv_len+1;
|
||||||
|
if ( ai->na_len > 255 )
|
||||||
|
rc++;
|
||||||
|
buf = (char *)op->o_tmpalloc( rc, op->o_tmpmemctx );
|
||||||
|
rc = f->f_av_value.bv_len;
|
||||||
|
buf[0] = rc & 0xff;
|
||||||
|
ptr = buf+1;
|
||||||
|
if ( ai->na_len > 255 ) {
|
||||||
|
buf[1] = (rc >> 8);
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
memcpy( ptr, f->f_av_value.bv_val, f->f_av_value.bv_len );
|
||||||
|
rc = scan->setBound( ai->na_ixcol - IDX_COLUMN, bt, buf );
|
||||||
|
op->o_tmpfree( buf, op->o_tmpmemctx );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if ( sf ) {
|
||||||
|
char *buf, *ptr;
|
||||||
|
NdbScanFilter::BinaryCondition bc;
|
||||||
|
|
||||||
|
switch(choice) {
|
||||||
|
case LDAP_FILTER_PRESENT:
|
||||||
|
rc = sf->isnotnull( ai->na_column );
|
||||||
|
break;
|
||||||
|
case LDAP_FILTER_EQUALITY:
|
||||||
|
case LDAP_FILTER_APPROX:
|
||||||
|
bc = NdbScanFilter::COND_EQ;
|
||||||
|
goto setf;
|
||||||
|
case LDAP_FILTER_GE:
|
||||||
|
bc = NdbScanFilter::COND_GE;
|
||||||
|
goto setf;
|
||||||
|
case LDAP_FILTER_LE:
|
||||||
|
bc = NdbScanFilter::COND_LE;
|
||||||
|
setf:
|
||||||
|
rc = sf->cmp( bc, ai->na_column, f->f_av_value.bv_val, f->f_av_value.bv_len );
|
||||||
|
break;
|
||||||
|
case LDAP_FILTER_SUBSTRINGS:
|
||||||
|
rc = 0;
|
||||||
|
if ( f->f_sub_initial.bv_val )
|
||||||
|
rc += f->f_sub_initial.bv_len + 1;
|
||||||
|
if ( f->f_sub_any ) {
|
||||||
|
int i;
|
||||||
|
if ( !rc ) rc++;
|
||||||
|
for (i=0; f->f_sub_any[i].bv_val; i++)
|
||||||
|
rc += f->f_sub_any[i].bv_len + 1;
|
||||||
|
}
|
||||||
|
if ( f->f_sub_final.bv_val ) {
|
||||||
|
if ( !rc ) rc++;
|
||||||
|
rc += f->f_sub_final.bv_len;
|
||||||
|
}
|
||||||
|
buf = (char *)op->o_tmpalloc( rc+1, op->o_tmpmemctx );
|
||||||
|
ptr = buf;
|
||||||
|
if ( f->f_sub_initial.bv_val ) {
|
||||||
|
memcpy( ptr, f->f_sub_initial.bv_val, f->f_sub_initial.bv_len );
|
||||||
|
ptr += f->f_sub_initial.bv_len;
|
||||||
|
*ptr++ = '%';
|
||||||
|
}
|
||||||
|
if ( f->f_sub_any ) {
|
||||||
|
int i;
|
||||||
|
if ( ptr == buf )
|
||||||
|
*ptr++ = '%';
|
||||||
|
for (i=0; f->f_sub_any[i].bv_val; i++) {
|
||||||
|
memcpy( ptr, f->f_sub_any[i].bv_val, f->f_sub_any[i].bv_len );
|
||||||
|
ptr += f->f_sub_any[i].bv_len;
|
||||||
|
*ptr++ = '%';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( f->f_sub_final.bv_val ) {
|
||||||
|
if ( ptr == buf )
|
||||||
|
*ptr++ = '%';
|
||||||
|
memcpy( ptr, f->f_sub_final.bv_val, f->f_sub_final.bv_len );
|
||||||
|
ptr += f->f_sub_final.bv_len;
|
||||||
|
}
|
||||||
|
*ptr = '\0';
|
||||||
|
rc = sf->cmp( NdbScanFilter::COND_LIKE, ai->na_column, buf, ptr - buf );
|
||||||
|
op->o_tmpfree( buf, op->o_tmpmemctx );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ndb_oc_search( Operation *op, SlapReply *rs, Ndb *ndb, NdbTransaction *txn,
|
||||||
|
NdbRdns *rbase, NdbOcInfo *oci, int indexed )
|
||||||
|
{
|
||||||
|
struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private;
|
||||||
|
const NdbDictionary::Dictionary *myDict = ndb->getDictionary();
|
||||||
|
const NdbDictionary::Table *myTable;
|
||||||
|
const NdbDictionary::Index *myIndex;
|
||||||
|
NdbIndexScanOperation *scan;
|
||||||
|
NdbIndexOperation *ixop;
|
||||||
|
NdbScanFilter *sf = NULL;
|
||||||
|
struct berval *ocs;
|
||||||
|
NdbRecAttr *scanID, *scanOC, *scanDN[NDB_MAX_RDNS];
|
||||||
|
char dnBuf[2048], *ptr;
|
||||||
|
NdbRdns rdns;
|
||||||
|
NdbArgs NA;
|
||||||
|
char idbuf[2*sizeof(ID)];
|
||||||
|
char ocbuf[NDB_OC_BUFLEN];
|
||||||
|
int i, rc, bounds;
|
||||||
|
Entry e = {0};
|
||||||
|
Uint64 eid;
|
||||||
|
time_t stoptime;
|
||||||
|
int manageDSAit;
|
||||||
|
|
||||||
|
stoptime = op->o_time + op->ors_tlimit;
|
||||||
|
manageDSAit = get_manageDSAit( op );
|
||||||
|
|
||||||
|
myTable = myDict->getTable( oci->no_table.bv_val );
|
||||||
|
if ( indexed ) {
|
||||||
|
scan = txn->getNdbIndexScanOperation( INDEX_NAME, DN2ID_TABLE );
|
||||||
|
if ( !scan )
|
||||||
|
return LDAP_OTHER;
|
||||||
|
scan->readTuples( NdbOperation::LM_CommittedRead );
|
||||||
|
} else {
|
||||||
|
myIndex = myDict->getIndex( "eid$unique", DN2ID_TABLE );
|
||||||
|
if ( !myIndex ) {
|
||||||
|
Debug( LDAP_DEBUG_ANY, DN2ID_TABLE " eid index is missing!\n", 0, 0, 0 );
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
scan = (NdbIndexScanOperation *)txn->getNdbScanOperation( myTable );
|
||||||
|
if ( !scan )
|
||||||
|
return LDAP_OTHER;
|
||||||
|
scan->readTuples( NdbOperation::LM_CommittedRead );
|
||||||
|
#if 1
|
||||||
|
sf = new NdbScanFilter(scan);
|
||||||
|
if ( !sf )
|
||||||
|
return LDAP_OTHER;
|
||||||
|
switch ( op->ors_filter->f_choice ) {
|
||||||
|
case LDAP_FILTER_AND:
|
||||||
|
case LDAP_FILTER_OR:
|
||||||
|
case LDAP_FILTER_NOT:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if ( sf->begin() < 0 ) {
|
||||||
|
rc = LDAP_OTHER;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bounds = 0;
|
||||||
|
rc = ndb_filter_set( op, ni, op->ors_filter, indexed, scan, sf, &bounds );
|
||||||
|
if ( rc )
|
||||||
|
goto leave;
|
||||||
|
if ( sf ) sf->end();
|
||||||
|
|
||||||
|
scanID = scan->getValue( EID_COLUMN, idbuf );
|
||||||
|
if ( indexed ) {
|
||||||
|
scanOC = scan->getValue( OCS_COLUMN, ocbuf );
|
||||||
|
for ( i=0; i<NDB_MAX_RDNS; i++ ) {
|
||||||
|
rdns.nr_buf[i][0] = '\0';
|
||||||
|
scanDN[i] = scan->getValue( RDN_COLUMN+i, rdns.nr_buf[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( txn->execute( NdbTransaction::NoCommit, NdbOperation::AbortOnError, 1 )) {
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.e_name.bv_val = dnBuf;
|
||||||
|
NA.e = &e;
|
||||||
|
NA.ndb = ndb;
|
||||||
|
while ( scan->nextResult( true, true ) == 0 ) {
|
||||||
|
NdbTransaction *tx2;
|
||||||
|
if ( op->o_abandon ) {
|
||||||
|
rs->sr_err = SLAPD_ABANDON;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ( slapd_shutdown ) {
|
||||||
|
rs->sr_err = LDAP_UNAVAILABLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ( op->ors_tlimit != SLAP_NO_LIMIT &&
|
||||||
|
slap_get_time() > stoptime ) {
|
||||||
|
rs->sr_err = LDAP_TIMELIMIT_EXCEEDED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
eid = scanID->u_64_value();
|
||||||
|
e.e_id = eid;
|
||||||
|
if ( !indexed ) {
|
||||||
|
tx2 = ndb->startTransaction( myTable );
|
||||||
|
if ( !tx2 ) {
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
ixop = tx2->getNdbIndexOperation( myIndex );
|
||||||
|
if ( !ixop ) {
|
||||||
|
tx2->close();
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
ixop->readTuple( NdbOperation::LM_CommittedRead );
|
||||||
|
ixop->equal( EID_COLUMN, eid );
|
||||||
|
|
||||||
|
scanOC = ixop->getValue( OCS_COLUMN, ocbuf );
|
||||||
|
for ( i=0; i<NDB_MAX_RDNS; i++ ) {
|
||||||
|
rdns.nr_buf[i][0] = '\0';
|
||||||
|
scanDN[i] = ixop->getValue( RDN_COLUMN+i, rdns.nr_buf[i] );
|
||||||
|
}
|
||||||
|
rc = tx2->execute( NdbTransaction::Commit, NdbOperation::AbortOnError, 1 );
|
||||||
|
tx2->close();
|
||||||
|
if ( rc ) {
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ocs = ndb_ref2oclist( ocbuf, op->o_tmpmemctx );
|
||||||
|
for ( i=0; i<NDB_MAX_RDNS; i++ ) {
|
||||||
|
if ( scanDN[i]->isNULL() || !rdns.nr_buf[i][0] )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rdns.nr_num = i;
|
||||||
|
|
||||||
|
/* entry must be subordinate to the base */
|
||||||
|
if ( i < rbase->nr_num ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = dnBuf;
|
||||||
|
for ( --i; i>=0; i-- ) {
|
||||||
|
char *buf;
|
||||||
|
int len;
|
||||||
|
buf = rdns.nr_buf[i];
|
||||||
|
len = *buf++;
|
||||||
|
ptr = lutil_strncopy( ptr, buf, len );
|
||||||
|
if ( i ) *ptr++ = ',';
|
||||||
|
}
|
||||||
|
*ptr = '\0';
|
||||||
|
e.e_name.bv_len = ptr - dnBuf;
|
||||||
|
|
||||||
|
/* More scope checks */
|
||||||
|
/* If indexed, these can be moved into the ScanFilter */
|
||||||
|
switch( op->ors_scope ) {
|
||||||
|
case LDAP_SCOPE_ONELEVEL:
|
||||||
|
if ( rdns.nr_num != rbase->nr_num+1 )
|
||||||
|
continue;
|
||||||
|
case LDAP_SCOPE_SUBORDINATE:
|
||||||
|
if ( rdns.nr_num == rbase->nr_num )
|
||||||
|
continue;
|
||||||
|
case LDAP_SCOPE_SUBTREE:
|
||||||
|
default:
|
||||||
|
if ( e.e_name.bv_len <= op->o_req_dn.bv_len ) {
|
||||||
|
if ( op->ors_scope != LDAP_SCOPE_SUBTREE ||
|
||||||
|
strcasecmp( op->o_req_dn.bv_val, e.e_name.bv_val ))
|
||||||
|
continue;
|
||||||
|
} else if ( strcasecmp( op->o_req_dn.bv_val, e.e_name.bv_val +
|
||||||
|
e.e_name.bv_len - op->o_req_dn.bv_len ))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
dnNormalize( 0, NULL, NULL, &e.e_name, &e.e_nname, op->o_tmpmemctx );
|
||||||
|
{
|
||||||
|
#ifdef notdef /* NDBapi is broken here */
|
||||||
|
Ndb::Key_part_ptr keys[2];
|
||||||
|
char xbuf[32];
|
||||||
|
keys[0].ptr = &eid;
|
||||||
|
keys[0].len = sizeof(eid);
|
||||||
|
keys[1].ptr = NULL;
|
||||||
|
keys[1].len = 0;
|
||||||
|
tx2 = ndb->startTransaction( myTable, keys, xbuf, sizeof(xbuf));
|
||||||
|
#else
|
||||||
|
tx2 = ndb->startTransaction( myTable );
|
||||||
|
#endif
|
||||||
|
if ( !tx2 ) {
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
NA.txn = tx2;
|
||||||
|
NA.ocs = ocs;
|
||||||
|
rc = ndb_entry_get_data( op, &NA, 0 );
|
||||||
|
tx2->close();
|
||||||
|
}
|
||||||
|
ber_bvarray_free_x( ocs, op->o_tmpmemctx );
|
||||||
|
if ( !manageDSAit && is_entry_referral( &e )) {
|
||||||
|
BerVarray erefs = get_entry_referrals( op, &e );
|
||||||
|
rs->sr_ref = referral_rewrite( erefs, &e.e_name, NULL,
|
||||||
|
op->ors_scope == LDAP_SCOPE_ONELEVEL ?
|
||||||
|
LDAP_SCOPE_BASE : LDAP_SCOPE_SUBTREE );
|
||||||
|
rc = send_search_reference( op, rs );
|
||||||
|
ber_bvarray_free( rs->sr_ref );
|
||||||
|
ber_bvarray_free( erefs );
|
||||||
|
rs->sr_ref = NULL;
|
||||||
|
} else if ( manageDSAit || !is_entry_glue( &e )) {
|
||||||
|
rc = test_filter( op, &e, op->ors_filter );
|
||||||
|
if ( rc == LDAP_COMPARE_TRUE ) {
|
||||||
|
rs->sr_entry = &e;
|
||||||
|
rs->sr_attrs = op->ors_attrs;
|
||||||
|
rs->sr_flags = 0;
|
||||||
|
rc = send_search_entry( op, rs );
|
||||||
|
rs->sr_entry = NULL;
|
||||||
|
} else {
|
||||||
|
rc = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
attrs_free( e.e_attrs );
|
||||||
|
e.e_attrs = NULL;
|
||||||
|
op->o_tmpfree( e.e_nname.bv_val, op->o_tmpmemctx );
|
||||||
|
if ( rc ) break;
|
||||||
|
}
|
||||||
|
leave:
|
||||||
|
if ( sf ) delete sf;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
int ndb_back_search( Operation *op, SlapReply *rs )
|
||||||
|
{
|
||||||
|
struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private;
|
||||||
|
NdbTransaction *txn;
|
||||||
|
NdbIndexScanOperation *scan;
|
||||||
|
NdbScanFilter *sf = NULL;
|
||||||
|
Entry e = {0};
|
||||||
|
int rc, i, ocfilter, indexed;
|
||||||
|
struct berval matched;
|
||||||
|
NdbRecAttr *scanID, *scanOC, *scanDN[NDB_MAX_RDNS];
|
||||||
|
char dnBuf[2048], *ptr;
|
||||||
|
char idbuf[2*sizeof(ID)];
|
||||||
|
char ocbuf[NDB_OC_BUFLEN];
|
||||||
|
NdbRdns rdns;
|
||||||
|
NdbOcInfo *oci;
|
||||||
|
NdbArgs NA;
|
||||||
|
slap_mask_t mask;
|
||||||
|
time_t stoptime;
|
||||||
|
int manageDSAit;
|
||||||
|
|
||||||
|
rc = ndb_thread_handle( op, &NA.ndb );
|
||||||
|
rdns.nr_num = 0;
|
||||||
|
|
||||||
|
manageDSAit = get_manageDSAit( op );
|
||||||
|
|
||||||
|
txn = NA.ndb->startTransaction();
|
||||||
|
if ( !txn ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
LDAP_XSTRING(ndb_back_search) ": startTransaction failed: %s (%d)\n",
|
||||||
|
NA.ndb->getNdbError().message, NA.ndb->getNdbError().code, 0 );
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
rs->sr_text = "internal error";
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
NA.txn = txn;
|
||||||
|
e.e_name = op->o_req_dn;
|
||||||
|
e.e_nname = op->o_req_ndn;
|
||||||
|
NA.e = &e;
|
||||||
|
NA.rdns = &rdns;
|
||||||
|
NA.ocs = NULL;
|
||||||
|
|
||||||
|
rs->sr_err = ndb_entry_get_info( op, &NA, 0, &matched );
|
||||||
|
if ( rs->sr_err ) {
|
||||||
|
if ( rs->sr_err == LDAP_NO_SUCH_OBJECT ) {
|
||||||
|
rs->sr_matched = matched.bv_val;
|
||||||
|
if ( NA.ocs )
|
||||||
|
ndb_check_referral( op, rs, &NA );
|
||||||
|
}
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !access_allowed_mask( op, &e, slap_schema.si_ad_entry,
|
||||||
|
NULL, ACL_SEARCH, NULL, &mask )) {
|
||||||
|
if ( !ACL_GRANT( mask, ACL_DISCLOSE ))
|
||||||
|
rs->sr_err = LDAP_NO_SUCH_OBJECT;
|
||||||
|
else
|
||||||
|
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
||||||
|
ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx );
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
rs->sr_err = ndb_entry_get_data( op, &NA, 0 );
|
||||||
|
ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx );
|
||||||
|
if ( rs->sr_err )
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
if ( !manageDSAit && is_entry_referral( &e )) {
|
||||||
|
rs->sr_ref = get_entry_referrals( op, &e );
|
||||||
|
rs->sr_err = LDAP_REFERRAL;
|
||||||
|
if ( rs->sr_ref )
|
||||||
|
rs->sr_flags |= REP_REF_MUSTBEFREED;
|
||||||
|
rs->sr_matched = e.e_name.bv_val;
|
||||||
|
attrs_free( e.e_attrs );
|
||||||
|
e.e_attrs = NULL;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !manageDSAit && is_entry_glue( &e )) {
|
||||||
|
rs->sr_err = LDAP_NO_SUCH_OBJECT;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( get_assert( op ) && test_filter( op, &e, (Filter *)get_assertion( op )) !=
|
||||||
|
LDAP_COMPARE_TRUE ) {
|
||||||
|
rs->sr_err = LDAP_ASSERTION_FAILED;
|
||||||
|
attrs_free( e.e_attrs );
|
||||||
|
e.e_attrs = NULL;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* admin ignores tlimits */
|
||||||
|
stoptime = op->o_time + op->ors_tlimit;
|
||||||
|
|
||||||
|
if ( op->ors_scope == LDAP_SCOPE_BASE ) {
|
||||||
|
rc = test_filter( op, &e, op->ors_filter );
|
||||||
|
if ( rc == LDAP_COMPARE_TRUE ) {
|
||||||
|
rs->sr_entry = &e;
|
||||||
|
rs->sr_attrs = op->ors_attrs;
|
||||||
|
rs->sr_flags = 0;
|
||||||
|
send_search_entry( op, rs );
|
||||||
|
rs->sr_entry = NULL;
|
||||||
|
}
|
||||||
|
attrs_free( e.e_attrs );
|
||||||
|
e.e_attrs = NULL;
|
||||||
|
rs->sr_err = LDAP_SUCCESS;
|
||||||
|
goto leave;
|
||||||
|
} else {
|
||||||
|
attrs_free( e.e_attrs );
|
||||||
|
e.e_attrs = NULL;
|
||||||
|
if ( rdns.nr_num == NDB_MAX_RDNS ) {
|
||||||
|
if ( op->ors_scope == LDAP_SCOPE_ONELEVEL ||
|
||||||
|
op->ors_scope == LDAP_SCOPE_CHILDREN )
|
||||||
|
rs->sr_err = LDAP_SUCCESS;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See if we can handle the filter. Filtering on objectClass is only done
|
||||||
|
* in the DN2ID table scan. If all other filter terms reside in one table,
|
||||||
|
* then we scan the OC table instead of the DN2ID table.
|
||||||
|
*/
|
||||||
|
oci = NULL;
|
||||||
|
indexed = 0;
|
||||||
|
ocfilter = 0;
|
||||||
|
rc = ndb_filter_check( ni, op->ors_filter, &oci, &indexed, &ocfilter );
|
||||||
|
if ( rc ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE, "ndb_back_search: "
|
||||||
|
"filter attributes from multiple tables, indexing ignored\n",
|
||||||
|
0, 0, 0 );
|
||||||
|
} else if ( oci ) {
|
||||||
|
rc = ndb_oc_search( op, rs, NA.ndb, txn, &rdns, oci, indexed );
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
scan = txn->getNdbIndexScanOperation( "PRIMARY", DN2ID_TABLE );
|
||||||
|
scan->readTuples( NdbOperation::LM_CommittedRead );
|
||||||
|
rc = ndb_dn2bound( scan, &rdns );
|
||||||
|
|
||||||
|
/* TODO: if ( ocfilter ) set up scanfilter for objectclass matches
|
||||||
|
* column COND_LIKE "% <class> %"
|
||||||
|
*/
|
||||||
|
|
||||||
|
switch( op->ors_scope ) {
|
||||||
|
case LDAP_SCOPE_ONELEVEL:
|
||||||
|
sf = new NdbScanFilter(scan);
|
||||||
|
if ( sf->begin() < 0 ||
|
||||||
|
sf->cmp(NdbScanFilter::COND_NOT_LIKE, rc+3, "_%",
|
||||||
|
STRLENOF("_%")) < 0 ||
|
||||||
|
sf->end() < 0 ) {
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
/* FALLTHRU */
|
||||||
|
case LDAP_SCOPE_CHILDREN:
|
||||||
|
/* Note: RDN_COLUMN offset not needed here */
|
||||||
|
scan->setBound( rc, NdbIndexScanOperation::BoundLT, "\0" );
|
||||||
|
/* FALLTHRU */
|
||||||
|
case LDAP_SCOPE_SUBTREE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
scanID = scan->getValue( EID_COLUMN, idbuf );
|
||||||
|
scanOC = scan->getValue( OCS_COLUMN, ocbuf );
|
||||||
|
for ( i=0; i<NDB_MAX_RDNS; i++ ) {
|
||||||
|
rdns.nr_buf[i][0] = '\0';
|
||||||
|
scanDN[i] = scan->getValue( RDN_COLUMN+i, rdns.nr_buf[i] );
|
||||||
|
}
|
||||||
|
if ( txn->execute( NdbTransaction::NoCommit, NdbOperation::AbortOnError, 1 )) {
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.e_name.bv_val = dnBuf;
|
||||||
|
while ( scan->nextResult( true, true ) == 0 ) {
|
||||||
|
if ( op->o_abandon ) {
|
||||||
|
rs->sr_err = SLAPD_ABANDON;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ( slapd_shutdown ) {
|
||||||
|
rs->sr_err = LDAP_UNAVAILABLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ( op->ors_tlimit != SLAP_NO_LIMIT &&
|
||||||
|
slap_get_time() > stoptime ) {
|
||||||
|
rs->sr_err = LDAP_TIMELIMIT_EXCEEDED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
e.e_id = scanID->u_64_value();
|
||||||
|
NA.ocs = ndb_ref2oclist( ocbuf, op->o_tmpmemctx );
|
||||||
|
for ( i=0; i<NDB_MAX_RDNS; i++ ) {
|
||||||
|
if ( scanDN[i]->isNULL() || !rdns.nr_buf[i][0] )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ptr = dnBuf;
|
||||||
|
rdns.nr_num = i;
|
||||||
|
for ( --i; i>=0; i-- ) {
|
||||||
|
char *buf;
|
||||||
|
int len;
|
||||||
|
buf = rdns.nr_buf[i];
|
||||||
|
len = *buf++;
|
||||||
|
ptr = lutil_strncopy( ptr, buf, len );
|
||||||
|
if ( i ) *ptr++ = ',';
|
||||||
|
}
|
||||||
|
*ptr = '\0';
|
||||||
|
e.e_name.bv_len = ptr - dnBuf;
|
||||||
|
dnNormalize( 0, NULL, NULL, &e.e_name, &e.e_nname, op->o_tmpmemctx );
|
||||||
|
NA.txn = NA.ndb->startTransaction();
|
||||||
|
rc = ndb_entry_get_data( op, &NA, 0 );
|
||||||
|
NA.txn->close();
|
||||||
|
ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx );
|
||||||
|
if ( !manageDSAit && is_entry_referral( &e )) {
|
||||||
|
BerVarray erefs = get_entry_referrals( op, &e );
|
||||||
|
rs->sr_ref = referral_rewrite( erefs, &e.e_name, NULL,
|
||||||
|
op->ors_scope == LDAP_SCOPE_ONELEVEL ?
|
||||||
|
LDAP_SCOPE_BASE : LDAP_SCOPE_SUBTREE );
|
||||||
|
rc = send_search_reference( op, rs );
|
||||||
|
ber_bvarray_free( rs->sr_ref );
|
||||||
|
ber_bvarray_free( erefs );
|
||||||
|
rs->sr_ref = NULL;
|
||||||
|
} else if ( manageDSAit || !is_entry_glue( &e )) {
|
||||||
|
rc = test_filter( op, &e, op->ors_filter );
|
||||||
|
if ( rc == LDAP_COMPARE_TRUE ) {
|
||||||
|
rs->sr_entry = &e;
|
||||||
|
rs->sr_attrs = op->ors_attrs;
|
||||||
|
rs->sr_flags = 0;
|
||||||
|
rc = send_search_entry( op, rs );
|
||||||
|
rs->sr_entry = NULL;
|
||||||
|
} else {
|
||||||
|
rc = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
attrs_free( e.e_attrs );
|
||||||
|
e.e_attrs = NULL;
|
||||||
|
op->o_tmpfree( e.e_nname.bv_val, op->o_tmpmemctx );
|
||||||
|
if ( rc ) break;
|
||||||
|
}
|
||||||
|
leave:
|
||||||
|
if ( sf )
|
||||||
|
delete sf;
|
||||||
|
if ( txn )
|
||||||
|
txn->close();
|
||||||
|
send_ldap_result( op, rs );
|
||||||
|
return rs->sr_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern NdbInterpretedCode *ndb_lastrow_code; /* init.cpp */
|
||||||
|
|
||||||
|
extern "C" int
|
||||||
|
ndb_has_children(
|
||||||
|
NdbArgs *NA,
|
||||||
|
int *hasChildren
|
||||||
|
)
|
||||||
|
{
|
||||||
|
NdbIndexScanOperation *scan;
|
||||||
|
char idbuf[2*sizeof(ID)];
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if ( NA->rdns->nr_num >= NDB_MAX_RDNS ) {
|
||||||
|
*hasChildren = LDAP_COMPARE_FALSE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
scan = NA->txn->getNdbIndexScanOperation( "PRIMARY", DN2ID_TABLE );
|
||||||
|
if ( !scan )
|
||||||
|
return LDAP_OTHER;
|
||||||
|
scan->readTuples( NdbOperation::LM_Read, 0U, 0U, 1U );
|
||||||
|
rc = ndb_dn2bound( scan, NA->rdns );
|
||||||
|
if ( rc < NDB_MAX_RDNS ) {
|
||||||
|
scan->setBound( rc, NdbIndexScanOperation::BoundLT, "\0" );
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
scan->interpret_exit_last_row();
|
||||||
|
#else
|
||||||
|
scan->setInterpretedCode(ndb_lastrow_code);
|
||||||
|
#endif
|
||||||
|
scan->getValue( EID_COLUMN, idbuf );
|
||||||
|
if ( NA->txn->execute( NdbTransaction::NoCommit, NdbOperation::AO_IgnoreError, 1 )) {
|
||||||
|
return LDAP_OTHER;
|
||||||
|
}
|
||||||
|
if (rc < NDB_MAX_RDNS && scan->nextResult( true, true ) == 0 )
|
||||||
|
*hasChildren = LDAP_COMPARE_TRUE;
|
||||||
|
else
|
||||||
|
*hasChildren = LDAP_COMPARE_FALSE;
|
||||||
|
scan->close();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int
|
||||||
|
ndb_has_subordinates(
|
||||||
|
Operation *op,
|
||||||
|
Entry *e,
|
||||||
|
int *hasSubordinates )
|
||||||
|
{
|
||||||
|
NdbArgs NA;
|
||||||
|
NdbRdns rdns;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
NA.rdns = &rdns;
|
||||||
|
rc = ndb_dn2rdns( &e->e_nname, &rdns );
|
||||||
|
|
||||||
|
if ( rc == 0 ) {
|
||||||
|
rc = ndb_thread_handle( op, &NA.ndb );
|
||||||
|
NA.txn = NA.ndb->startTransaction();
|
||||||
|
if ( NA.txn ) {
|
||||||
|
rc = ndb_has_children( &NA, hasSubordinates );
|
||||||
|
NA.txn->close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sets the supported operational attributes (if required)
|
||||||
|
*/
|
||||||
|
extern "C" int
|
||||||
|
ndb_operational(
|
||||||
|
Operation *op,
|
||||||
|
SlapReply *rs )
|
||||||
|
{
|
||||||
|
Attribute **ap;
|
||||||
|
|
||||||
|
assert( rs->sr_entry != NULL );
|
||||||
|
|
||||||
|
for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next )
|
||||||
|
/* just count */ ;
|
||||||
|
|
||||||
|
if ( SLAP_OPATTRS( rs->sr_attr_flags ) ||
|
||||||
|
ad_inlist( slap_schema.si_ad_hasSubordinates, rs->sr_attrs ) )
|
||||||
|
{
|
||||||
|
int hasSubordinates, rc;
|
||||||
|
|
||||||
|
rc = ndb_has_subordinates( 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;
|
||||||
|
}
|
||||||
|
|
||||||
544
servers/slapd/back-ndb/tools.cpp
Normal file
544
servers/slapd/back-ndb/tools.cpp
Normal file
|
|
@ -0,0 +1,544 @@
|
||||||
|
/* tools.cpp - tools for slap tools */
|
||||||
|
/* $OpenLDAP$ */
|
||||||
|
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||||
|
*
|
||||||
|
* Copyright 2008 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>.
|
||||||
|
*/
|
||||||
|
/* ACKNOWLEDGEMENTS:
|
||||||
|
* This work was initially developed by Howard Chu for inclusion
|
||||||
|
* in OpenLDAP Software. This work was sponsored by MySQL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "portable.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ac/string.h>
|
||||||
|
#include <ac/errno.h>
|
||||||
|
|
||||||
|
#include "lutil.h"
|
||||||
|
|
||||||
|
#include "back-ndb.h"
|
||||||
|
|
||||||
|
typedef struct dn_id {
|
||||||
|
ID id;
|
||||||
|
struct berval dn;
|
||||||
|
} dn_id;
|
||||||
|
|
||||||
|
#define HOLE_SIZE 4096
|
||||||
|
static dn_id hbuf[HOLE_SIZE], *holes = hbuf;
|
||||||
|
static unsigned nhmax = HOLE_SIZE;
|
||||||
|
static unsigned nholes;
|
||||||
|
static Avlnode *myParents;
|
||||||
|
|
||||||
|
static Ndb *myNdb;
|
||||||
|
static NdbTransaction *myScanTxn;
|
||||||
|
static NdbIndexScanOperation *myScanOp;
|
||||||
|
|
||||||
|
static NdbRecAttr *myScanID, *myScanOC;
|
||||||
|
static NdbRecAttr *myScanDN[NDB_MAX_RDNS];
|
||||||
|
static char myDNbuf[2048];
|
||||||
|
static char myIdbuf[2*sizeof(ID)];
|
||||||
|
static char myOcbuf[NDB_OC_BUFLEN];
|
||||||
|
static NdbRdns myRdns;
|
||||||
|
|
||||||
|
static NdbTransaction *myPutTxn;
|
||||||
|
static int myPutCnt;
|
||||||
|
|
||||||
|
static struct berval *myOcList;
|
||||||
|
static struct berval myDn;
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
int ndb_tool_entry_open(
|
||||||
|
BackendDB *be, int mode )
|
||||||
|
{
|
||||||
|
struct ndb_info *ni = (struct ndb_info *) be->be_private;
|
||||||
|
|
||||||
|
myNdb = new Ndb( ni->ni_cluster[0], ni->ni_dbname );
|
||||||
|
return myNdb->init(1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
int ndb_tool_entry_close(
|
||||||
|
BackendDB *be )
|
||||||
|
{
|
||||||
|
if ( myPutTxn ) {
|
||||||
|
int rc = myPutTxn->execute(NdbTransaction::Commit);
|
||||||
|
if( rc != 0 ) {
|
||||||
|
char text[1024];
|
||||||
|
snprintf( text, sizeof(text),
|
||||||
|
"txn_commit failed: %s (%d)",
|
||||||
|
myPutTxn->getNdbError().message, myPutTxn->getNdbError().code );
|
||||||
|
Debug( LDAP_DEBUG_ANY,
|
||||||
|
"=> " LDAP_XSTRING(ndb_tool_entry_put) ": %s\n",
|
||||||
|
text, 0, 0 );
|
||||||
|
}
|
||||||
|
myPutTxn->close();
|
||||||
|
myPutTxn = NULL;
|
||||||
|
}
|
||||||
|
myPutCnt = 0;
|
||||||
|
|
||||||
|
if( nholes ) {
|
||||||
|
unsigned i;
|
||||||
|
fprintf( stderr, "Error, entries missing!\n");
|
||||||
|
for (i=0; i<nholes; i++) {
|
||||||
|
fprintf(stderr, " entry %ld: %s\n",
|
||||||
|
holes[i].id, holes[i].dn.bv_val);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
ID ndb_tool_entry_next(
|
||||||
|
BackendDB *be )
|
||||||
|
{
|
||||||
|
struct ndb_info *ni = (struct ndb_info *) be->be_private;
|
||||||
|
char *ptr;
|
||||||
|
ID id;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
assert( be != NULL );
|
||||||
|
assert( slapMode & SLAP_TOOL_MODE );
|
||||||
|
|
||||||
|
if ( myScanOp->nextResult() ) {
|
||||||
|
myScanOp->close();
|
||||||
|
myScanOp = NULL;
|
||||||
|
myScanTxn->close();
|
||||||
|
myScanTxn = NULL;
|
||||||
|
return NOID;
|
||||||
|
}
|
||||||
|
id = myScanID->u_64_value();
|
||||||
|
|
||||||
|
if ( myOcList ) {
|
||||||
|
ber_bvarray_free( myOcList );
|
||||||
|
}
|
||||||
|
myOcList = ndb_ref2oclist( myOcbuf, NULL );
|
||||||
|
for ( i=0; i<NDB_MAX_RDNS; i++ ) {
|
||||||
|
if ( myScanDN[i]->isNULL() || !myRdns.nr_buf[i][0] )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
myRdns.nr_num = i;
|
||||||
|
ptr = myDNbuf;
|
||||||
|
for ( --i; i>=0; i-- ) {
|
||||||
|
char *buf;
|
||||||
|
int len;
|
||||||
|
buf = myRdns.nr_buf[i];
|
||||||
|
len = *buf++;
|
||||||
|
ptr = lutil_strncopy( ptr, buf, len );
|
||||||
|
if ( i )
|
||||||
|
*ptr++ = ',';
|
||||||
|
}
|
||||||
|
*ptr = '\0';
|
||||||
|
myDn.bv_val = myDNbuf;
|
||||||
|
myDn.bv_len = ptr - myDNbuf;
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
ID ndb_tool_entry_first(
|
||||||
|
BackendDB *be )
|
||||||
|
{
|
||||||
|
struct ndb_info *ni = (struct ndb_info *) be->be_private;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
myScanTxn = myNdb->startTransaction();
|
||||||
|
if ( !myScanTxn )
|
||||||
|
return NOID;
|
||||||
|
|
||||||
|
myScanOp = myScanTxn->getNdbIndexScanOperation( "PRIMARY", DN2ID_TABLE );
|
||||||
|
if ( !myScanOp )
|
||||||
|
return NOID;
|
||||||
|
|
||||||
|
if ( myScanOp->readTuples( NdbOperation::LM_CommittedRead, NdbScanOperation::SF_KeyInfo ))
|
||||||
|
return NOID;
|
||||||
|
|
||||||
|
myScanID = myScanOp->getValue( EID_COLUMN, myIdbuf );
|
||||||
|
myScanOC = myScanOp->getValue( OCS_COLUMN, myOcbuf );
|
||||||
|
for ( i=0; i<NDB_MAX_RDNS; i++ ) {
|
||||||
|
myScanDN[i] = myScanOp->getValue( i+RDN_COLUMN, myRdns.nr_buf[i] );
|
||||||
|
}
|
||||||
|
if ( myScanTxn->execute( NdbTransaction::NoCommit, NdbOperation::AbortOnError, 1 ))
|
||||||
|
return NOID;
|
||||||
|
|
||||||
|
return ndb_tool_entry_next( be );
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
ID ndb_tool_dn2id_get(
|
||||||
|
Backend *be,
|
||||||
|
struct berval *dn
|
||||||
|
)
|
||||||
|
{
|
||||||
|
struct ndb_info *ni = (struct ndb_info *) be->be_private;
|
||||||
|
NdbArgs NA;
|
||||||
|
NdbRdns rdns;
|
||||||
|
Entry e;
|
||||||
|
char text[1024];
|
||||||
|
Operation op = {0};
|
||||||
|
Opheader ohdr = {0};
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if ( BER_BVISEMPTY(dn) )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
NA.ndb = myNdb;
|
||||||
|
NA.txn = myNdb->startTransaction();
|
||||||
|
if ( !NA.txn ) {
|
||||||
|
snprintf( text, sizeof(text),
|
||||||
|
"startTransaction failed: %s (%d)",
|
||||||
|
myNdb->getNdbError().message, myNdb->getNdbError().code );
|
||||||
|
Debug( LDAP_DEBUG_ANY,
|
||||||
|
"=> " LDAP_XSTRING(ndb_tool_dn2id_get) ": %s\n",
|
||||||
|
text, 0, 0 );
|
||||||
|
return NOID;
|
||||||
|
}
|
||||||
|
if ( myOcList ) {
|
||||||
|
ber_bvarray_free( myOcList );
|
||||||
|
myOcList = NULL;
|
||||||
|
}
|
||||||
|
op.o_hdr = &ohdr;
|
||||||
|
op.o_bd = be;
|
||||||
|
op.o_tmpmemctx = NULL;
|
||||||
|
op.o_tmpmfuncs = &ch_mfuncs;
|
||||||
|
|
||||||
|
NA.e = &e;
|
||||||
|
e.e_name = *dn;
|
||||||
|
NA.rdns = &rdns;
|
||||||
|
NA.ocs = NULL;
|
||||||
|
rc = ndb_entry_get_info( &op, &NA, 0, NULL );
|
||||||
|
myOcList = NA.ocs;
|
||||||
|
NA.txn->close();
|
||||||
|
if ( rc )
|
||||||
|
return NOID;
|
||||||
|
|
||||||
|
myDn = *dn;
|
||||||
|
|
||||||
|
return e.e_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
Entry* ndb_tool_entry_get( BackendDB *be, ID id )
|
||||||
|
{
|
||||||
|
NdbArgs NA;
|
||||||
|
int rc;
|
||||||
|
char text[1024];
|
||||||
|
Operation op = {0};
|
||||||
|
Opheader ohdr = {0};
|
||||||
|
|
||||||
|
assert( be != NULL );
|
||||||
|
assert( slapMode & SLAP_TOOL_MODE );
|
||||||
|
|
||||||
|
NA.txn = myNdb->startTransaction();
|
||||||
|
if ( !NA.txn ) {
|
||||||
|
snprintf( text, sizeof(text),
|
||||||
|
"start_transaction failed: %s (%d)",
|
||||||
|
myNdb->getNdbError().message, myNdb->getNdbError().code );
|
||||||
|
Debug( LDAP_DEBUG_ANY,
|
||||||
|
"=> " LDAP_XSTRING(ndb_tool_entry_get) ": %s\n",
|
||||||
|
text, 0, 0 );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
NA.e = entry_alloc();
|
||||||
|
NA.e->e_id = id;
|
||||||
|
ber_dupbv( &NA.e->e_name, &myDn );
|
||||||
|
dnNormalize( 0, NULL, NULL, &NA.e->e_name, &NA.e->e_nname, NULL );
|
||||||
|
|
||||||
|
op.o_hdr = &ohdr;
|
||||||
|
op.o_bd = be;
|
||||||
|
op.o_tmpmemctx = NULL;
|
||||||
|
op.o_tmpmfuncs = &ch_mfuncs;
|
||||||
|
|
||||||
|
NA.ndb = myNdb;
|
||||||
|
NA.ocs = myOcList;
|
||||||
|
rc = ndb_entry_get_data( &op, &NA, 0 );
|
||||||
|
|
||||||
|
if ( rc ) {
|
||||||
|
entry_free( NA.e );
|
||||||
|
NA.e = NULL;
|
||||||
|
}
|
||||||
|
NA.txn->close();
|
||||||
|
|
||||||
|
return NA.e;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct berval glueval[] = {
|
||||||
|
BER_BVC("glue"),
|
||||||
|
BER_BVNULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static int ndb_dnid_cmp( const void *v1, const void *v2 )
|
||||||
|
{
|
||||||
|
struct dn_id *dn1 = (struct dn_id *)v1,
|
||||||
|
*dn2 = (struct dn_id *)v2;
|
||||||
|
return ber_bvcmp( &dn1->dn, &dn2->dn );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ndb_tool_next_id(
|
||||||
|
Operation *op,
|
||||||
|
NdbArgs *NA,
|
||||||
|
struct berval *text,
|
||||||
|
int hole )
|
||||||
|
{
|
||||||
|
struct berval ndn = NA->e->e_nname;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (ndn.bv_len == 0) {
|
||||||
|
NA->e->e_id = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ndb_entry_get_info( op, NA, 0, NULL );
|
||||||
|
if ( rc ) {
|
||||||
|
Attribute *a, tmp = {0};
|
||||||
|
if ( !be_issuffix( op->o_bd, &ndn ) ) {
|
||||||
|
struct dn_id *dptr;
|
||||||
|
struct berval npdn;
|
||||||
|
dnParent( &ndn, &npdn );
|
||||||
|
NA->e->e_nname = npdn;
|
||||||
|
NA->rdns->nr_num--;
|
||||||
|
rc = ndb_tool_next_id( op, NA, text, 1 );
|
||||||
|
NA->e->e_nname = ndn;
|
||||||
|
NA->rdns->nr_num++;
|
||||||
|
if ( rc ) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
/* If parent didn't exist, it was created just now
|
||||||
|
* and its ID is now in e->e_id.
|
||||||
|
*/
|
||||||
|
dptr = (struct dn_id *)ch_malloc( sizeof( struct dn_id ) + npdn.bv_len + 1);
|
||||||
|
dptr->id = NA->e->e_id;
|
||||||
|
dptr->dn.bv_val = (char *)(dptr+1);
|
||||||
|
strcpy(dptr->dn.bv_val, npdn.bv_val );
|
||||||
|
dptr->dn.bv_len = npdn.bv_len;
|
||||||
|
if ( avl_insert( &myParents, dptr, ndb_dnid_cmp, avl_dup_error )) {
|
||||||
|
ch_free( dptr );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rc = ndb_next_id( op->o_bd, myNdb, &NA->e->e_id );
|
||||||
|
if ( rc ) {
|
||||||
|
snprintf( text->bv_val, text->bv_len,
|
||||||
|
"next_id failed: %s (%d)",
|
||||||
|
myNdb->getNdbError().message, myNdb->getNdbError().code );
|
||||||
|
Debug( LDAP_DEBUG_ANY,
|
||||||
|
"=> ndb_tool_next_id: %s\n", text->bv_val, 0, 0 );
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
if ( hole ) {
|
||||||
|
a = NA->e->e_attrs;
|
||||||
|
NA->e->e_attrs = &tmp;
|
||||||
|
tmp.a_desc = slap_schema.si_ad_objectClass;
|
||||||
|
tmp.a_vals = glueval;
|
||||||
|
tmp.a_nvals = tmp.a_vals;
|
||||||
|
tmp.a_numvals = 1;
|
||||||
|
}
|
||||||
|
rc = ndb_entry_put_info( op->o_bd, NA, 0 );
|
||||||
|
if ( hole ) {
|
||||||
|
NA->e->e_attrs = a;
|
||||||
|
}
|
||||||
|
if ( rc ) {
|
||||||
|
snprintf( text->bv_val, text->bv_len,
|
||||||
|
"ndb_entry_put_info failed: %s (%d)",
|
||||||
|
myNdb->getNdbError().message, myNdb->getNdbError().code );
|
||||||
|
Debug( LDAP_DEBUG_ANY,
|
||||||
|
"=> ndb_tool_next_id: %s\n", text->bv_val, 0, 0 );
|
||||||
|
} else if ( hole ) {
|
||||||
|
if ( nholes == nhmax - 1 ) {
|
||||||
|
if ( holes == hbuf ) {
|
||||||
|
holes = (dn_id *)ch_malloc( nhmax * sizeof(dn_id) * 2 );
|
||||||
|
AC_MEMCPY( holes, hbuf, sizeof(hbuf) );
|
||||||
|
} else {
|
||||||
|
holes = (dn_id *)ch_realloc( holes, nhmax * sizeof(dn_id) * 2 );
|
||||||
|
}
|
||||||
|
nhmax *= 2;
|
||||||
|
}
|
||||||
|
ber_dupbv( &holes[nholes].dn, &ndn );
|
||||||
|
holes[nholes++].id = NA->e->e_id;
|
||||||
|
}
|
||||||
|
} else if ( !hole ) {
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
for ( i=0; i<nholes; i++) {
|
||||||
|
if ( holes[i].id == NA->e->e_id ) {
|
||||||
|
int j;
|
||||||
|
free(holes[i].dn.bv_val);
|
||||||
|
for (j=i;j<nholes;j++) holes[j] = holes[j+1];
|
||||||
|
holes[j].id = 0;
|
||||||
|
nholes--;
|
||||||
|
rc = ndb_entry_put_info( op->o_bd, NA, 1 );
|
||||||
|
break;
|
||||||
|
} else if ( holes[i].id > NA->e->e_id ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
ID ndb_tool_entry_put(
|
||||||
|
BackendDB *be,
|
||||||
|
Entry *e,
|
||||||
|
struct berval *text )
|
||||||
|
{
|
||||||
|
struct ndb_info *ni = (struct ndb_info *) be->be_private;
|
||||||
|
struct dn_id dtmp, *dptr;
|
||||||
|
NdbArgs NA;
|
||||||
|
NdbRdns rdns;
|
||||||
|
int rc, slow = 0;
|
||||||
|
Operation op = {0};
|
||||||
|
Opheader ohdr = {0};
|
||||||
|
|
||||||
|
assert( be != NULL );
|
||||||
|
assert( slapMode & SLAP_TOOL_MODE );
|
||||||
|
|
||||||
|
assert( text != NULL );
|
||||||
|
assert( text->bv_val != NULL );
|
||||||
|
assert( text->bv_val[0] == '\0' ); /* overconservative? */
|
||||||
|
|
||||||
|
Debug( LDAP_DEBUG_TRACE, "=> " LDAP_XSTRING(ndb_tool_entry_put)
|
||||||
|
"( %ld, \"%s\" )\n", (long) e->e_id, e->e_dn, 0 );
|
||||||
|
|
||||||
|
if ( !be_issuffix( be, &e->e_nname )) {
|
||||||
|
dnParent( &e->e_nname, &dtmp.dn );
|
||||||
|
dptr = (struct dn_id *)avl_find( myParents, &dtmp, ndb_dnid_cmp );
|
||||||
|
if ( !dptr )
|
||||||
|
slow = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rdns.nr_num = 0;
|
||||||
|
|
||||||
|
op.o_hdr = &ohdr;
|
||||||
|
op.o_bd = be;
|
||||||
|
op.o_tmpmemctx = NULL;
|
||||||
|
op.o_tmpmfuncs = &ch_mfuncs;
|
||||||
|
|
||||||
|
if ( !slow ) {
|
||||||
|
rc = ndb_next_id( be, myNdb, &e->e_id );
|
||||||
|
if ( rc ) {
|
||||||
|
snprintf( text->bv_val, text->bv_len,
|
||||||
|
"next_id failed: %s (%d)",
|
||||||
|
myNdb->getNdbError().message, myNdb->getNdbError().code );
|
||||||
|
Debug( LDAP_DEBUG_ANY,
|
||||||
|
"=> ndb_tool_next_id: %s\n", text->bv_val, 0, 0 );
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !myPutTxn )
|
||||||
|
myPutTxn = myNdb->startTransaction();
|
||||||
|
if ( !myPutTxn ) {
|
||||||
|
snprintf( text->bv_val, text->bv_len,
|
||||||
|
"start_transaction failed: %s (%d)",
|
||||||
|
myNdb->getNdbError().message, myNdb->getNdbError().code );
|
||||||
|
Debug( LDAP_DEBUG_ANY,
|
||||||
|
"=> " LDAP_XSTRING(ndb_tool_entry_put) ": %s\n",
|
||||||
|
text->bv_val, 0, 0 );
|
||||||
|
return NOID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add dn2id indices */
|
||||||
|
ndb_dn2rdns( &e->e_name, &rdns );
|
||||||
|
NA.rdns = &rdns;
|
||||||
|
NA.e = e;
|
||||||
|
NA.ndb = myNdb;
|
||||||
|
NA.txn = myPutTxn;
|
||||||
|
if ( slow ) {
|
||||||
|
rc = ndb_tool_next_id( &op, &NA, text, 0 );
|
||||||
|
if( rc != 0 ) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rc = ndb_entry_put_info( be, &NA, 0 );
|
||||||
|
if ( rc != 0 ) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* id2entry index */
|
||||||
|
rc = ndb_entry_put_data( be, &NA );
|
||||||
|
if( rc != 0 ) {
|
||||||
|
snprintf( text->bv_val, text->bv_len,
|
||||||
|
"ndb_entry_put_data failed: %s (%d)",
|
||||||
|
myNdb->getNdbError().message, myNdb->getNdbError().code );
|
||||||
|
Debug( LDAP_DEBUG_ANY,
|
||||||
|
"=> " LDAP_XSTRING(ndb_tool_entry_put) ": %s\n",
|
||||||
|
text->bv_val, 0, 0 );
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
if( rc == 0 ) {
|
||||||
|
myPutCnt++;
|
||||||
|
if ( !( myPutCnt & 0x0f )) {
|
||||||
|
rc = myPutTxn->execute(NdbTransaction::Commit);
|
||||||
|
if( rc != 0 ) {
|
||||||
|
snprintf( text->bv_val, text->bv_len,
|
||||||
|
"txn_commit failed: %s (%d)",
|
||||||
|
myPutTxn->getNdbError().message, myPutTxn->getNdbError().code );
|
||||||
|
Debug( LDAP_DEBUG_ANY,
|
||||||
|
"=> " LDAP_XSTRING(ndb_tool_entry_put) ": %s\n",
|
||||||
|
text->bv_val, 0, 0 );
|
||||||
|
e->e_id = NOID;
|
||||||
|
}
|
||||||
|
myPutTxn->close();
|
||||||
|
myPutTxn = NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
snprintf( text->bv_val, text->bv_len,
|
||||||
|
"txn_aborted! %s (%d)",
|
||||||
|
myPutTxn->getNdbError().message, myPutTxn->getNdbError().code );
|
||||||
|
Debug( LDAP_DEBUG_ANY,
|
||||||
|
"=> " LDAP_XSTRING(ndb_tool_entry_put) ": %s\n",
|
||||||
|
text->bv_val, 0, 0 );
|
||||||
|
e->e_id = NOID;
|
||||||
|
myPutTxn->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return e->e_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
int ndb_tool_entry_reindex(
|
||||||
|
BackendDB *be,
|
||||||
|
ID id,
|
||||||
|
AttributeDescription **adv )
|
||||||
|
{
|
||||||
|
struct ndb_info *ni = (struct ndb_info *) be->be_private;
|
||||||
|
|
||||||
|
Debug( LDAP_DEBUG_ARGS,
|
||||||
|
"=> " LDAP_XSTRING(ndb_tool_entry_reindex) "( %ld )\n",
|
||||||
|
(long) id, 0, 0 );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
ID ndb_tool_entry_modify(
|
||||||
|
BackendDB *be,
|
||||||
|
Entry *e,
|
||||||
|
struct berval *text )
|
||||||
|
{
|
||||||
|
struct ndb_info *ni = (struct ndb_info *) be->be_private;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
Debug( LDAP_DEBUG_TRACE,
|
||||||
|
"=> " LDAP_XSTRING(ndb_tool_entry_modify) "( %ld, \"%s\" )\n",
|
||||||
|
(long) e->e_id, e->e_dn, 0 );
|
||||||
|
|
||||||
|
done:
|
||||||
|
return e->e_id;
|
||||||
|
}
|
||||||
|
|
||||||
23
tests/data/ndb.conf
Normal file
23
tests/data/ndb.conf
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
# back-ndb boilerplate config -- for testing
|
||||||
|
# $OpenLDAP$
|
||||||
|
## This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||||
|
##
|
||||||
|
## Copyright 1998-2008 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>.
|
||||||
|
|
||||||
|
dbuser root
|
||||||
|
dbhost localhost
|
||||||
|
dbconnect 127.0.0.1
|
||||||
|
dbsocket /tmp/mysql.sock
|
||||||
|
attrset extensibleObject uidNumber,gidNumber
|
||||||
|
attrblob description
|
||||||
|
index cn
|
||||||
|
#index sn
|
||||||
|
|
@ -38,6 +38,8 @@ subordinate
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
database @BACKEND@
|
database @BACKEND@
|
||||||
suffix "dc=example,dc=com"
|
suffix "dc=example,dc=com"
|
||||||
|
|
@ -48,5 +50,7 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_2
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
#monitor#database monitor
|
#monitor#database monitor
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,8 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
access to dn.subtree="dc=example,dc=com"
|
access to dn.subtree="dc=example,dc=com"
|
||||||
by dynacl/aci write
|
by dynacl/aci write
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,8 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
#access to attrs=objectclass dn.subtree="dc=example,dc=com"
|
#access to attrs=objectclass dn.subtree="dc=example,dc=com"
|
||||||
access to attrs=objectclass
|
access to attrs=objectclass
|
||||||
|
|
|
||||||
|
|
@ -40,5 +40,7 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
#monitor#database monitor
|
#monitor#database monitor
|
||||||
|
|
|
||||||
|
|
@ -58,5 +58,7 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
#monitor#database monitor
|
#monitor#database monitor
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,8 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_2
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
#
|
#
|
||||||
# uses the chain overlay as database specific;
|
# uses the chain overlay as database specific;
|
||||||
|
|
|
||||||
|
|
@ -43,5 +43,7 @@ rootdn "cn=Manager,dc=example,dc=com"
|
||||||
rootpw secret
|
rootpw secret
|
||||||
#bdb#index objectClass eq
|
#bdb#index objectClass eq
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
#monitor#database monitor
|
#monitor#database monitor
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
#monitor#database monitor
|
#monitor#database monitor
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,8 @@ rootpw secret
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index entryExpireTimestamp eq
|
#hdb#index entryExpireTimestamp eq
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
overlay dds
|
overlay dds
|
||||||
dds-max-ttl 1d
|
dds-max-ttl 1d
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,8 @@ rootdn "cn=Manager,dc=example,dc=com"
|
||||||
#bdb#index entryUUID,entryCSN eq
|
#bdb#index entryUUID,entryCSN eq
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index entryUUID,entryCSN eq
|
#hdb#index entryUUID,entryCSN eq
|
||||||
|
#ndb#dbname db_2
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
overlay syncprov
|
overlay syncprov
|
||||||
syncprov-reloadhint true
|
syncprov-reloadhint true
|
||||||
|
|
@ -60,6 +62,8 @@ rootpw secret
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index entryUUID,entryCSN eq
|
#hdb#index entryUUID,entryCSN eq
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
|
|
||||||
access to *
|
access to *
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,8 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_3
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
# Don't change syncrepl spec yet
|
# Don't change syncrepl spec yet
|
||||||
syncrepl rid=1
|
syncrepl rid=1
|
||||||
|
|
|
||||||
|
|
@ -42,5 +42,7 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
#monitor#database monitor
|
#monitor#database monitor
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,8 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
# we'll reconfigure the attrset dynamically
|
# we'll reconfigure the attrset dynamically
|
||||||
overlay dynlist
|
overlay dynlist
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,8 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
access to attrs=userPassword
|
access to attrs=userPassword
|
||||||
by dn.exact="cn=Manager,c=US" write
|
by dn.exact="cn=Manager,c=US" write
|
||||||
|
|
@ -70,6 +72,8 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_2
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
access to attrs=userPassword
|
access to attrs=userPassword
|
||||||
by self =wx
|
by self =wx
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,8 @@ rootdn "cn=Manager 1,dc=example,dc=com"
|
||||||
#hdb#index uid pres,eq,sub
|
#hdb#index uid pres,eq,sub
|
||||||
#hdb#index cn,sn pres,eq,sub,subany
|
#hdb#index cn,sn pres,eq,sub,subany
|
||||||
#hdb#index entryUUID,entryCSN pres
|
#hdb#index entryUUID,entryCSN pres
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
overlay syncprov
|
overlay syncprov
|
||||||
|
|
||||||
|
|
@ -60,6 +62,8 @@ rootdn "cn=Manager 1,dc=example,dc=com"
|
||||||
#hdb#index uid pres,eq,sub
|
#hdb#index uid pres,eq,sub
|
||||||
#hdb#index cn,sn pres,eq,sub,subany
|
#hdb#index cn,sn pres,eq,sub,subany
|
||||||
#hdb#index entryUUID,entryCSN pres
|
#hdb#index entryUUID,entryCSN pres
|
||||||
|
#ndb#dbname db_2
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
syncrepl rid=1
|
syncrepl rid=1
|
||||||
provider=@URI2@
|
provider=@URI2@
|
||||||
|
|
@ -88,6 +92,8 @@ rootpw secret
|
||||||
#hdb#index objectclass eq
|
#hdb#index objectclass eq
|
||||||
#hdb#index uid pres,eq,sub
|
#hdb#index uid pres,eq,sub
|
||||||
#hdb#index cn,sn pres,eq,sub,subany
|
#hdb#index cn,sn pres,eq,sub,subany
|
||||||
|
#ndb#dbname db_3
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
#overlay syncprov
|
#overlay syncprov
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,8 @@ rootdn "cn=Manager 2,dc=example,dc=com"
|
||||||
#hdb#index uid pres,eq,sub
|
#hdb#index uid pres,eq,sub
|
||||||
#hdb#index cn,sn pres,eq,sub,subany
|
#hdb#index cn,sn pres,eq,sub,subany
|
||||||
#hdb#index entryUUID,entryCSN pres
|
#hdb#index entryUUID,entryCSN pres
|
||||||
|
#ndb#dbname db_4
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
|
|
||||||
syncrepl rid=2
|
syncrepl rid=2
|
||||||
|
|
@ -74,6 +76,8 @@ rootdn "cn=Manager 2,dc=example,dc=com"
|
||||||
#hdb#index uid pres,eq,sub
|
#hdb#index uid pres,eq,sub
|
||||||
#hdb#index cn,sn pres,eq,sub,subany
|
#hdb#index cn,sn pres,eq,sub,subany
|
||||||
#hdb#index entryUUID,entryCSN pres
|
#hdb#index entryUUID,entryCSN pres
|
||||||
|
#ndb#dbname db_5
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
|
|
||||||
overlay syncprov
|
overlay syncprov
|
||||||
|
|
@ -90,6 +94,8 @@ rootpw secret
|
||||||
#hdb#index objectclass eq
|
#hdb#index objectclass eq
|
||||||
#hdb#index uid pres,eq,sub
|
#hdb#index uid pres,eq,sub
|
||||||
#hdb#index cn,sn pres,eq,sub,subany
|
#hdb#index cn,sn pres,eq,sub,subany
|
||||||
|
#ndb#dbname db_6
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
|
|
||||||
#overlay syncprov
|
#overlay syncprov
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,8 @@ rootdn "cn=Manager, dc=example,dc=com"
|
||||||
#hdb#index objectclass eq
|
#hdb#index objectclass eq
|
||||||
#hdb#index uid pres,eq,sub
|
#hdb#index uid pres,eq,sub
|
||||||
#hdb#index cn,sn pres,eq,sub,subany
|
#hdb#index cn,sn pres,eq,sub,subany
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
database @BACKEND@
|
database @BACKEND@
|
||||||
suffix "ou=Groups,dc=example,dc=com"
|
suffix "ou=Groups,dc=example,dc=com"
|
||||||
|
|
@ -53,6 +55,8 @@ rootdn "cn=Manager, dc=example,dc=com"
|
||||||
#hdb#index objectclass eq
|
#hdb#index objectclass eq
|
||||||
#hdb#index uid pres,eq,sub
|
#hdb#index uid pres,eq,sub
|
||||||
#hdb#index cn,sn pres,eq,sub,subany
|
#hdb#index cn,sn pres,eq,sub,subany
|
||||||
|
#ndb#dbname db_2
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
database @BACKEND@
|
database @BACKEND@
|
||||||
suffix "dc=example,dc=com"
|
suffix "dc=example,dc=com"
|
||||||
|
|
@ -65,5 +69,7 @@ rootpw secret
|
||||||
#hdb#index objectclass eq
|
#hdb#index objectclass eq
|
||||||
#hdb#index uid pres,eq,sub
|
#hdb#index uid pres,eq,sub
|
||||||
#hdb#index cn,sn pres,eq,sub,subany
|
#hdb#index cn,sn pres,eq,sub,subany
|
||||||
|
#ndb#dbname db_3
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
#monitor#database monitor
|
#monitor#database monitor
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,8 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
access to dn.exact="cn=Proxy,ou=Admin,dc=example,dc=com"
|
access to dn.exact="cn=Proxy,ou=Admin,dc=example,dc=com"
|
||||||
attrs=authzTo
|
attrs=authzTo
|
||||||
|
|
@ -82,6 +84,8 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_2
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
database ldap
|
database ldap
|
||||||
suffix "o=Example,c=US"
|
suffix "o=Example,c=US"
|
||||||
|
|
|
||||||
|
|
@ -75,5 +75,7 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
#monitor#database monitor
|
#monitor#database monitor
|
||||||
|
|
|
||||||
|
|
@ -57,5 +57,7 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_6
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
#monitor#database monitor
|
#monitor#database monitor
|
||||||
|
|
|
||||||
|
|
@ -58,5 +58,7 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_5
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
#monitor#database monitor
|
#monitor#database monitor
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,8 @@ rootpw secret
|
||||||
#bdb#index uid eq
|
#bdb#index uid eq
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index uid eq
|
#hdb#index uid eq
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
# Need extra limits for pagedResults on backends that support it...
|
# Need extra limits for pagedResults on backends that support it...
|
||||||
#bdb#limits dn.exact="cn=Unlimited User,ou=Paged Results Users,dc=example,dc=com" size=4 size.pr=unlimited
|
#bdb#limits dn.exact="cn=Unlimited User,ou=Paged Results Users,dc=example,dc=com" size=4 size.pr=unlimited
|
||||||
|
|
|
||||||
|
|
@ -40,5 +40,7 @@ rootdn "cn=Manager,dc=example,dc=com"
|
||||||
rootpw secret
|
rootpw secret
|
||||||
#bdb#index objectClass eq
|
#bdb#index objectClass eq
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
#monitor#database monitor
|
#monitor#database monitor
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,8 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
# ITS#5154: force mixed success/failure of binds using same connection
|
# ITS#5154: force mixed success/failure of binds using same connection
|
||||||
access to dn="cn=Barbara Jensen,ou=Information Technology DivisioN,ou=People,dc=example,dc=com"
|
access to dn="cn=Barbara Jensen,ou=Information Technology DivisioN,ou=People,dc=example,dc=com"
|
||||||
|
|
|
||||||
|
|
@ -48,5 +48,7 @@ rootdn "cn=Manager,ou=Meta,dc=example,dc=com"
|
||||||
rootpw secret
|
rootpw secret
|
||||||
#bdb#index objectClass eq
|
#bdb#index objectClass eq
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
|
#ndb#dbname db_2
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
#monitor#database monitor
|
#monitor#database monitor
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,8 @@ rootdn "cn=Manager,dc=example,dc=com"
|
||||||
rootpw secret
|
rootpw secret
|
||||||
#bdb#index objectClass eq
|
#bdb#index objectClass eq
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
overlay ppolicy
|
overlay ppolicy
|
||||||
ppolicy_default "cn=Standard Policy,ou=Policies,dc=example,dc=com"
|
ppolicy_default "cn=Standard Policy,ou=Policies,dc=example,dc=com"
|
||||||
|
|
|
||||||
|
|
@ -60,5 +60,7 @@ directory @TESTDIR@/db.2.a
|
||||||
#bdb#index cn,sn,uid,mail pres,eq,sub
|
#bdb#index cn,sn,uid,mail pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid,mail pres,eq,sub
|
#hdb#index cn,sn,uid,mail pres,eq,sub
|
||||||
|
#ndb#dbname db_2
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
#monitor#database monitor
|
#monitor#database monitor
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,8 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
#
|
#
|
||||||
# normal installations should protect root dse,
|
# normal installations should protect root dse,
|
||||||
|
|
|
||||||
|
|
@ -45,5 +45,7 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_2
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
#monitor#database monitor
|
#monitor#database monitor
|
||||||
|
|
|
||||||
|
|
@ -37,5 +37,7 @@ rootdn "cn=Manager,c=us"
|
||||||
rootpw secret
|
rootpw secret
|
||||||
#bdb#index objectClass eq
|
#bdb#index objectClass eq
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
#monitor#database monitor
|
#monitor#database monitor
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,8 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
overlay refint
|
overlay refint
|
||||||
refint_attributes manager secretary member
|
refint_attributes manager secretary member
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,8 @@ rootdn "cn=Manager,dc=example,dc=com"
|
||||||
rootpw secret
|
rootpw secret
|
||||||
#bdb#index objectClass eq
|
#bdb#index objectClass eq
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
database @RELAY@
|
database @RELAY@
|
||||||
suffix "o=Example,c=US"
|
suffix "o=Example,c=US"
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,8 @@ updateref @URI1@
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index entryUUID pres,eq
|
#hdb#index entryUUID pres,eq
|
||||||
|
#ndb#dbname db_2
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
# Need to strip hasSubordinates from internal searches otherwise
|
# Need to strip hasSubordinates from internal searches otherwise
|
||||||
# syncrepl will try to delete it, since syncprov is not sending
|
# syncrepl will try to delete it, since syncprov is not sending
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,8 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
overlay retcode
|
overlay retcode
|
||||||
retcode-parent "ou=RetCodes,dc=example,dc=com"
|
retcode-parent "ou=RetCodes,dc=example,dc=com"
|
||||||
|
|
|
||||||
|
|
@ -49,11 +49,7 @@ suffix "o=OpenLDAP Project,l=Internet"
|
||||||
directory @TESTDIR@/db.1.a
|
directory @TESTDIR@/db.1.a
|
||||||
#bdb#index objectClass eq
|
#bdb#index objectClass eq
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
|
#ndb#dbname db_1_a
|
||||||
#database @BACKEND@
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
#suffix "dc=example,dc=com"
|
|
||||||
#directory @TESTDIR@/db.1.b
|
|
||||||
##bdb#index objectClass eq
|
|
||||||
##hdb#index objectClass eq
|
|
||||||
|
|
||||||
#monitor#database monitor
|
#monitor#database monitor
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,8 @@ rootpw secret
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index entryUUID,entryCSN eq
|
#hdb#index entryUUID,entryCSN eq
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
overlay syncprov
|
overlay syncprov
|
||||||
#syncprov-sessionlog 100
|
#syncprov-sessionlog 100
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,8 @@ rootpw secret
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index entryUUID,entryCSN eq
|
#hdb#index entryUUID,entryCSN eq
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
overlay syncprov
|
overlay syncprov
|
||||||
syncprov-sessionlog 100
|
syncprov-sessionlog 100
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,8 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_4
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
# Don't change syncrepl spec yet
|
# Don't change syncrepl spec yet
|
||||||
syncrepl rid=1
|
syncrepl rid=1
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@ rootpw secret
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index entryUUID,entryCSN eq
|
#hdb#index entryUUID,entryCSN eq
|
||||||
|
#ndb#dbname db_5
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
# Don't change syncrepl spec yet
|
# Don't change syncrepl spec yet
|
||||||
syncrepl rid=1
|
syncrepl rid=1
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,8 @@ rootpw secret
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index entryUUID,entryCSN eq
|
#hdb#index entryUUID,entryCSN eq
|
||||||
|
#ndb#dbname db_6
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
# Don't change syncrepl spec yet
|
# Don't change syncrepl spec yet
|
||||||
syncrepl rid=1
|
syncrepl rid=1
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,8 @@ rootpw secret
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index entryUUID,entryCSN eq
|
#hdb#index entryUUID,entryCSN eq
|
||||||
|
#ndb#dbname db_2
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
# Don't change syncrepl spec yet
|
# Don't change syncrepl spec yet
|
||||||
syncrepl rid=1
|
syncrepl rid=1
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,8 @@ rootpw secret
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index entryUUID,entryCSN eq
|
#hdb#index entryUUID,entryCSN eq
|
||||||
|
#ndb#dbname db_3
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
# Don't change syncrepl spec yet
|
# Don't change syncrepl spec yet
|
||||||
syncrepl rid=1
|
syncrepl rid=1
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,8 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_2
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
overlay translucent
|
overlay translucent
|
||||||
translucent_no_glue
|
translucent_no_glue
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@
|
||||||
## top-level directory of the distribution or, alternatively, at
|
## top-level directory of the distribution or, alternatively, at
|
||||||
## <http://www.OpenLDAP.org/license.html>.
|
## <http://www.OpenLDAP.org/license.html>.
|
||||||
|
|
||||||
ucdata-path ./ucdata
|
|
||||||
include @SCHEMADIR@/core.schema
|
include @SCHEMADIR@/core.schema
|
||||||
include @SCHEMADIR@/cosine.schema
|
include @SCHEMADIR@/cosine.schema
|
||||||
include @SCHEMADIR@/inetorgperson.schema
|
include @SCHEMADIR@/inetorgperson.schema
|
||||||
|
|
@ -44,3 +43,5 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,8 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
overlay unique
|
overlay unique
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,8 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
overlay valsort
|
overlay valsort
|
||||||
valsort-attr sn ou=users,o=valsort alpha-ascend
|
valsort-attr sn ou=users,o=valsort alpha-ascend
|
||||||
|
|
|
||||||
|
|
@ -60,5 +60,7 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
#monitor#database monitor
|
#monitor#database monitor
|
||||||
|
|
|
||||||
|
|
@ -47,5 +47,7 @@ rootpw secret
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#checkpoint 1 1
|
#hdb#checkpoint 1 1
|
||||||
|
#ndb#dbname db_1
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
#monitor#database monitor
|
#monitor#database monitor
|
||||||
|
|
|
||||||
|
|
@ -40,5 +40,7 @@ rootpw secret
|
||||||
#bdb#index cn,sn,uid pres,eq,sub
|
#bdb#index cn,sn,uid pres,eq,sub
|
||||||
#hdb#index objectClass eq
|
#hdb#index objectClass eq
|
||||||
#hdb#index cn,sn,uid pres,eq,sub
|
#hdb#index cn,sn,uid pres,eq,sub
|
||||||
|
#ndb#dbname db_2
|
||||||
|
#ndb#include @DATADIR@/ndb.conf
|
||||||
|
|
||||||
#monitor#database monitor
|
#monitor#database monitor
|
||||||
|
|
|
||||||
10
tests/run.in
10
tests/run.in
|
|
@ -177,6 +177,16 @@ if test -d ${TESTDIR} ; then
|
||||||
/bin/rm -rf ${TESTDIR}/db.*
|
/bin/rm -rf ${TESTDIR}/db.*
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
if test $BACKEND = ndb ; then
|
||||||
|
mysql --user root <<EOF
|
||||||
|
drop database if exists db_1;
|
||||||
|
drop database if exists db_2;
|
||||||
|
drop database if exists db_3;
|
||||||
|
drop database if exists db_4;
|
||||||
|
drop database if exists db_5;
|
||||||
|
drop database if exists db_6;
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
mkdir -p ${TESTDIR}
|
mkdir -p ${TESTDIR}
|
||||||
|
|
||||||
if test $USERDATA = yes ; then
|
if test $USERDATA = yes ; then
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,10 @@
|
||||||
## top-level directory of the distribution or, alternatively, at
|
## top-level directory of the distribution or, alternatively, at
|
||||||
## <http://www.OpenLDAP.org/license.html>.
|
## <http://www.OpenLDAP.org/license.html>.
|
||||||
#
|
#
|
||||||
# Strip comments
|
# Strip comments, sort attributes. Requires GNU awk
|
||||||
#
|
#
|
||||||
|
if [ "$BACKEND" != ndb ]; then
|
||||||
grep -v '^#'
|
grep -v '^#'
|
||||||
|
else
|
||||||
|
grep -v '^#'| awk 'BEGIN{FS="\n";RS=""} {j=0; for (i=1; i<=NF; i++){ if ($i ~ /^ /){ x[j] = x[j] "\n" $i; } else { j++; x[j] = $i } } print x[1]; delete x[1]; j=asort(x); for (i=1; i<=j; i++){ print x[i]; } delete x; print "" }'
|
||||||
|
fi
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,16 @@ for CMD in $SRCDIR/scripts/test*; do
|
||||||
else
|
else
|
||||||
/bin/rm -rf $TESTDIR
|
/bin/rm -rf $TESTDIR
|
||||||
fi
|
fi
|
||||||
|
if test $BACKEND = ndb ; then
|
||||||
|
mysql --user root <<EOF
|
||||||
|
drop database if exists db_1;
|
||||||
|
drop database if exists db_2;
|
||||||
|
drop database if exists db_3;
|
||||||
|
drop database if exists db_4;
|
||||||
|
drop database if exists db_5;
|
||||||
|
drop database if exists db_6;
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
echo ">>>>> Starting ${TB}`basename $CMD`${TN} ..."
|
echo ">>>>> Starting ${TB}`basename $CMD`${TN} ..."
|
||||||
$CMD
|
$CMD
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue