- autoreconf
- mkdir obj
- cd obj
- - ../configure --enable-backends=mod --enable-overlays=mod --enable-modules --enable-dynamic --disable-ndb --enable-balancer=mod --enable-argon2 --with-systemd
+ - ../configure --enable-backends=mod --enable-overlays=mod --enable-modules --enable-dynamic --enable-balancer=mod --enable-argon2 --with-systemd
- make depend
- make
- export DEBUGINFOD_URLS="${DEBUGINFOD_URLS-https://debuginfod.debian.net}"
- autoreconf
- mkdir obj
- cd obj
- - ../configure --enable-backends=mod --enable-overlays=mod --disable-autoca --enable-modules --enable-dynamic --disable-ndb --enable-balancer=yes --enable-argon2 --with-systemd
+ - ../configure --enable-backends=mod --enable-overlays=mod --disable-autoca --enable-modules --enable-dynamic --enable-balancer=yes --enable-argon2 --with-systemd
- make depend
- make
- export DEBUGINFOD_URLS="${DEBUGINFOD_URLS-https://debuginfod.debian.net}"
mdb \
meta \
asyncmeta \
- ndb \
null \
passwd \
perl \
no, [no yes mod], ol_enable_backends)dnl
OL_ARG_ENABLE(asyncmeta, [AS_HELP_STRING([--enable-asyncmeta], [enable asynchronous metadirectory backend])],
no, [no yes mod], ol_enable_backends)dnl
-OL_ARG_ENABLE(ndb, [AS_HELP_STRING([--enable-ndb], [enable MySQL NDB Cluster backend])],
- no, [no yes mod], ol_enable_backends)dnl
OL_ARG_ENABLE(null, [AS_HELP_STRING([--enable-null], [enable null backend])],
no, [no yes mod], ol_enable_backends)dnl
OL_ARG_ENABLE(passwd, [AS_HELP_STRING([--enable-passwd], [enable passwd backend])],
fi
fi
-dnl ----------------------------------------------------------------
-dnl MySQL NDBapi
-dnl Note: uses C++, but we don't want to add C++ test overhead to
-dnl the rest of the libtool machinery.
-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"
-
- save_CPPFLAGS="$CPPFLAGS"
- CPPFLAGS="$SLAPD_NDB_INCS"
- AC_MSG_CHECKING(for NdbApi.hpp)
- AC_PREPROC_IFELSE(
- [AC_LANG_SOURCE([[#include <NdbApi.hpp>]])],
- AC_MSG_RESULT(yes),
- AC_MSG_ERROR([could not locate NdbApi headers])
- )
- CPPFLAGS="$save_CPPFLAGS"
-
- SQL_LIB=`mysql_config --libs_r`
- SLAPD_NDB_LIBS="$SQL_LIB -lndbclient -lstdc++"
-
- save_LDFLAGS="$LDFLAGS"
- save_LIBS="$LIBS"
- LDFLAGS="$SQL_LIB"
- AC_CHECK_LIB(ndbclient,ndb_init,[: ok],[
- AC_MSG_ERROR([could not locate ndbclient library])
- ],[-lstdc++])
- LIBS="$save_LIBS"
- LDFLAGS="$save_LDFLAGS"
-
- if test "$ol_enable_ndb" = yes ; then
- SLAPD_LIBS="$SLAPD_LIBS \$(SLAPD_NDB_LIBS)"
- fi
-fi
-
dnl ----------------------------------------------------------------
dnl WiredTiger
ol_link_wt=no
AC_DEFINE_UNQUOTED(SLAPD_ASYNCMETA,$MFLAG,[define to support LDAP Async Metadirectory backend])
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
BUILD_SLAPD=yes
BUILD_NULL=$ol_enable_null
[servers/slapd/back-meta/Makefile:build/top.mk:servers/slapd/back-meta/Makefile.in:build/mod.mk]
[servers/slapd/back-asyncmeta/Makefile:build/top.mk:servers/slapd/back-asyncmeta/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-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]
INDEXDB=noindexdb MAINDB=nomaindb
case $BACKEND in
mdb) INDEXDB=indexdb MAINDB=maindb ;;
- ndb) INDEXDB=indexdb ;;
esac
export BACKEND BACKENDTYPE INDEXDB MAINDB \
/bin/rm -rf ${TESTDIR}/db.*
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}
if test $USERDATA = yes ; then
else
/bin/rm -rf $TESTDIR
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
BCMD=`basename $CMD`
if [ -x "$CMD" ]; then
INDEXDB=noindexdb MAINDB=nomaindb
case $BACKEND in
mdb) INDEXDB=indexdb MAINDB=maindb ;;
- ndb) INDEXDB=indexdb ;;
esac
export BACKEND BACKENDTYPE INDEXDB MAINDB \
/bin/rm -rf ${TESTDIR}/db.*
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}
if test $USERDATA = yes ; then
else
/bin/rm -rf $TESTDIR
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
BCMD=`basename $CMD`
if [ -x "$CMD" ]; then
mdb Memory-Mapped DB backend
meta Metadirectory backend
monitor Monitor backend
-ndb MySQL NDB backend
null Null backend
passwd Provides read-only access to {{passwd}}(5)
perl Perl Programmable backend
mdb Memory-Mapped DB backend
meta Metadirectory backend
monitor Monitor backend
-ndb MySQL NDB backend
null Null backend
passwd Provides read-only access to {{passwd}}(5)
perl Perl Programmable backend
.BR mdb ,
.BR meta ,
.BR monitor ,
-.BR ndb ,
.BR null ,
.BR passwd ,
.BR perl ,
+++ /dev/null
-.TH SLAPD-NDB 5 "RELEASEDATE" "OpenLDAP LDVERSION"
-.\" Copyright 2008-2021 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\-config (5),
-.BR slapd (8),
-.BR slapadd (8),
-.BR slapcat (8),
-.BR slapindex (8),
-.BR slapmodify (8),
-MySQL Cluster documentation.
-.SH AUTHOR
-Howard Chu, with assistance from Johan Andersson et al @ MySQL.
.B monitor
backend may be defined.
.TP
-.B ndb
-This backend is experimental, incomplete, and deprecated.
-It uses the transactional database interface of the MySQL Cluster Engine
-(NDB) to store data. Note that Oracle, which now owns MySQL, has withdrawn
-support for NDB and this backend is unlikely to be developed any further.
-.TP
.B null
Operations in this backend succeed but do nothing.
.TP
.BR slapd\-mdb (5),
.BR slapd\-meta (5),
.BR slapd\-monitor (5),
-.BR slapd\-ndb (5),
.BR slapd\-null (5),
.BR slapd\-passwd (5),
.BR slapd\-perl (5),
.BR mdb ,
.BR meta ,
.BR monitor ,
-.BR ndb ,
.BR null ,
.BR passwd ,
.BR perl ,
.BR mdb ,
.BR meta ,
.BR monitor ,
-.BR ndb ,
.BR null ,
.BR passwd ,
.BR perl ,
+++ /dev/null
-# Makefile.in for back-ndb
-# $OpenLDAP$
-## This work is part of OpenLDAP Software <http://www.openldap.org/>.
-##
-## Copyright 2008-2021 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_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 $@
-
+++ /dev/null
-LDAP features not currently supported:
-
-tagged attributes
-aliases
-substring indexing
-subtree rename
+++ /dev/null
-/* add.cpp - ldap NDB back-end add routine */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2008-2021 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;
- NA.txn = NULL;
-
- /* check entry's schema */
- rs->sr_err = entry_schema_check( op, op->oq_add.rs_e, NULL,
- get_relax(op), 1, NULL, &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;;
- }
-
- /*
- * Check ACL for attribute write access
- */
- if (!acl_check_modlist(op, op->ora_e, op->ora_modlist)) {
- Debug( LDAP_DEBUG_TRACE,
- LDAP_XSTRING(bdb_add) ": no write access to attribute\n",
- 0, 0, 0 );
- rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
- rs->sr_text = "no write access to attribute";
- goto return_results;;
- }
-
-
- /* 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;
-}
+++ /dev/null
-# 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 }
-
+++ /dev/null
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2008-2021 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
+++ /dev/null
-/* bind.cpp - ndb backend bind routine */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2008-2021 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 LDAP_SUCCESS:
- /* frontend will send result */
- return rs->sr_err = LDAP_SUCCESS;
-
- default:
- /* give the database a chance */
- break;
- }
-
- /* 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;
-}
+++ /dev/null
-/* compare.cpp - ndb backend compare routine */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2008-2021 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;
-}
+++ /dev/null
-/* config.cpp - ndb backend configuration file routine */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2008-2021 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 "slap-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 );
-}
+++ /dev/null
-/* delete.cpp - ndb backend delete routine */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2008-2021 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_PVT_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;
-}
+++ /dev/null
-/* init.cpp - initialize ndb backend */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2008-2021 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 "slap-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, 30 );
- 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,
- LDAP_CONTROL_TXN_SPEC,
- 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 */
-extern "C" { int init_module( int argc, char *argv[] ); }
-
-SLAP_BACKEND_INIT_MODULE( ndb )
-
-#endif /* SLAPD_NDB == SLAPD_MOD_DYNAMIC */
-
+++ /dev/null
-/* modify.cpp - ndb backend modify routine */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2008-2021 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;
-
- case SLAP_MOD_SOFTDEL:
- Debug(LDAP_DEBUG_ARGS,
- "ndb_modify_internal: softdel %s\n",
- mod->sm_desc->ad_cname.bv_val, 0, 0);
- mod->sm_op = LDAP_MOD_DELETE;
-
- rc = modify_delete_values( NA->e, mod, get_permissiveModify(op),
- text, textbuf, textlen );
-
- mod->sm_op = SLAP_MOD_SOFTDEL;
-
- if ( rc == LDAP_NO_SUCH_ATTRIBUTE) {
- rc = LDAP_SUCCESS;
- }
-
- if( rc != LDAP_SUCCESS ) {
- Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: %d %s\n",
- rc, *text, 0);
- }
- break;
-
- case SLAP_MOD_ADD_IF_NOT_PRESENT:
- Debug(LDAP_DEBUG_ARGS,
- "ndb_modify_internal: add_if_not_present %s\n",
- mod->sm_desc->ad_cname.bv_val, 0, 0);
- if ( attr_find( NA->e->e_attrs, mod->sm_desc ) ) {
- rc = LDAP_SUCCESS;
- break;
- }
-
- mod->sm_op = LDAP_MOD_ADD;
-
- rc = modify_add_values( NA->e, mod, get_permissiveModify(op),
- text, textbuf, textlen );
-
- mod->sm_op = SLAP_MOD_ADD_IF_NOT_PRESENT;
-
- 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, NULL,
- 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;
- }
-
- if ( got_oc ) {
- rc = ndb_entry_put_info( op->o_bd, NA, 1 );
- if ( rc ) {
- 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, this was already done above */
- if ( indexed && !got_oc) {
- 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;
-}
+++ /dev/null
-/* modrdn.cpp - ndb backend modrdn routine */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2008-2021 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;
- 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 );
- }
-
- /* Make sure target entry doesn't exist already. */
- Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn) ": new ndn=%s\n",
- op->orr_nnewDN.bv_val, 0, 0 );
-
- /* Allow rename to same DN */
- if ( !bvmatch ( &op->orr_nnewDN, &e.e_nname )) {
- rdn2.nr_num = 0;
- e2.e_name = op->orr_newDN;
- e2.e_nname = op->orr_nnewDN;
- 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( 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;
-}
+++ /dev/null
-/* ndbio.cpp - get/set/del data for NDB */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2008-2021 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"
-
-/* For reference only */
-typedef struct MedVar {
- Int16 len; /* length is always little-endian */
- char buf[1024];
-} MedVar;
-
-extern "C" {
- static int ndb_name_cmp( const void *v1, const void *v2 );
- static int ndb_oc_dup_err( void *v1, void *v2 );
-};
-
-static int
-ndb_name_cmp( const void *v1, const void *v2 )
-{
- NdbOcInfo *oc1 = (NdbOcInfo *)v1, *oc2 = (NdbOcInfo *)v2;
- return ber_bvstrcasecmp( &oc1->no_name, &oc2->no_name );
-}
-
-static int
-ndb_oc_dup_err( void *v1, void *v2 )
-{
- NdbOcInfo *oc = (NdbOcInfo *)v2;
-
- oc->no_oc = (ObjectClass *)v1;
- return -1;
-}
-
-/* Find an existing NdbAttrInfo */
-extern "C" NdbAttrInfo *
-ndb_ai_find( struct ndb_info *ni, AttributeType *at )
-{
- NdbAttrInfo atmp;
- atmp.na_name = at->sat_cname;
-
- return (NdbAttrInfo *)avl_find( ni->ni_ai_tree, &atmp, ndb_name_cmp );
-}
-
-/* Find or create an NdbAttrInfo */
-extern "C" NdbAttrInfo *
-ndb_ai_get( struct ndb_info *ni, struct berval *aname )
-{
- NdbAttrInfo atmp, *ai;
- atmp.na_name = *aname;
-
- ai = (NdbAttrInfo *)avl_find( ni->ni_ai_tree, &atmp, ndb_name_cmp );
- if ( !ai ) {
- const char *text;
- AttributeDescription *ad = NULL;
-
- if ( slap_bv2ad( aname, &ad, &text ))
- return NULL;
-
- ai = (NdbAttrInfo *)ch_malloc( sizeof( NdbAttrInfo ));
- ai->na_desc = ad;
- ai->na_attr = ai->na_desc->ad_type;
- ai->na_name = ai->na_attr->sat_cname;
- ai->na_oi = NULL;
- ai->na_flag = 0;
- ai->na_ixcol = 0;
- ai->na_len = ai->na_attr->sat_atype.at_syntax_len;
- /* Reasonable default */
- if ( !ai->na_len ) {
- if ( ai->na_attr->sat_syntax == slap_schema.si_syn_distinguishedName )
- ai->na_len = 1024;
- else
- ai->na_len = 128;
- }
- /* Arbitrary limit */
- if ( ai->na_len > 1024 )
- ai->na_len = 1024;
- avl_insert( &ni->ni_ai_tree, ai, ndb_name_cmp, avl_dup_error );
- }
- return ai;
-}
-
-static int
-ndb_ai_check( struct ndb_info *ni, NdbOcInfo *oci, AttributeType **attrs, char **ptr, int *col,
- int create )
-{
- NdbAttrInfo *ai;
- int i;
-
- for ( i=0; attrs[i]; i++ ) {
- if ( attrs[i] == slap_schema.si_ad_objectClass->ad_type )
- continue;
- /* skip attrs that are in a superior */
- if ( oci->no_oc && oci->no_oc->soc_sups ) {
- int j, k, found=0;
- ObjectClass *oc;
- for ( j=0; oci->no_oc->soc_sups[j]; j++ ) {
- oc = oci->no_oc->soc_sups[j];
- if ( oc->soc_kind == LDAP_SCHEMA_ABSTRACT )
- continue;
- if ( oc->soc_required ) {
- for ( k=0; oc->soc_required[k]; k++ ) {
- if ( attrs[i] == oc->soc_required[k] ) {
- found = 1;
- break;
- }
- }
- if ( found ) break;
- }
- if ( oc->soc_allowed ) {
- for ( k=0; oc->soc_allowed[k]; k++ ) {
- if ( attrs[i] == oc->soc_allowed[k] ) {
- found = 1;
- break;
- }
- }
- if ( found ) break;
- }
- }
- if ( found )
- continue;
- }
-
- ai = ndb_ai_get( ni, &attrs[i]->sat_cname );
- if ( !ai ) {
- /* can never happen */
- return LDAP_OTHER;
- }
-
- /* An attrset may have already been connected */
- if (( oci->no_flag & NDB_INFO_ATSET ) && ai->na_oi == oci )
- continue;
-
- /* An indexed attr is defined before its OC is */
- if ( !ai->na_oi ) {
- ai->na_oi = oci;
- ai->na_column = (*col)++;
- }
-
- oci->no_attrs[oci->no_nattrs++] = ai;
-
- /* An attrset attr may already be defined */
- if ( ai->na_oi != oci ) {
- int j;
- for ( j=0; j<oci->no_nsets; j++ )
- if ( oci->no_sets[j] == ai->na_oi ) break;
- if ( j >= oci->no_nsets ) {
- /* FIXME: data loss if more sets are in use */
- if ( oci->no_nsets < NDB_MAX_OCSETS ) {
- oci->no_sets[oci->no_nsets++] = ai->na_oi;
- }
- }
- continue;
- }
-
- if ( create ) {
- if ( ai->na_flag & NDB_INFO_ATBLOB ) {
- *ptr += sprintf( *ptr, ", `%s` BLOB", ai->na_attr->sat_cname.bv_val );
- } else {
- *ptr += sprintf( *ptr, ", `%s` VARCHAR(%d)", ai->na_attr->sat_cname.bv_val,
- ai->na_len );
- }
- }
- }
- return 0;
-}
-
-static int
-ndb_oc_create( struct ndb_info *ni, NdbOcInfo *oci, int create )
-{
- char buf[4096], *ptr;
- int i, rc = 0, col;
-
- if ( create ) {
- ptr = buf + sprintf( buf,
- "CREATE TABLE `%s` (eid bigint unsigned NOT NULL, vid int unsigned NOT NULL",
- oci->no_table.bv_val );
- }
-
- col = 0;
- if ( oci->no_oc->soc_required ) {
- for ( i=0; oci->no_oc->soc_required[i]; i++ );
- col += i;
- }
- if ( oci->no_oc->soc_allowed ) {
- for ( i=0; oci->no_oc->soc_allowed[i]; i++ );
- col += i;
- }
- /* assume all are present */
- oci->no_attrs = (struct ndb_attrinfo **)ch_malloc( col * sizeof(struct ndb_attrinfo *));
-
- col = 2;
- ldap_pvt_thread_rdwr_wlock( &ni->ni_ai_rwlock );
- if ( oci->no_oc->soc_required ) {
- rc = ndb_ai_check( ni, oci, oci->no_oc->soc_required, &ptr, &col, create );
- }
- if ( !rc && oci->no_oc->soc_allowed ) {
- rc = ndb_ai_check( ni, oci, oci->no_oc->soc_allowed, &ptr, &col, create );
- }
- ldap_pvt_thread_rdwr_wunlock( &ni->ni_ai_rwlock );
-
- /* shrink down to just the needed size */
- oci->no_attrs = (struct ndb_attrinfo **)ch_realloc( oci->no_attrs,
- oci->no_nattrs * sizeof(struct ndb_attrinfo *));
-
- if ( create ) {
- ptr = lutil_strcopy( ptr, ", PRIMARY KEY(eid, vid) ) ENGINE=ndb PARTITION BY KEY(eid)" );
- rc = mysql_real_query( &ni->ni_sql, buf, ptr - buf );
- if ( rc ) {
- Debug( LDAP_DEBUG_ANY,
- "ndb_oc_create: CREATE TABLE %s failed, %s (%d)\n",
- oci->no_table.bv_val, mysql_error(&ni->ni_sql), mysql_errno(&ni->ni_sql) );
- }
- }
- return rc;
-}
-
-/* Read table definitions from the DB and populate ObjectClassInfo */
-extern "C" int
-ndb_oc_read( struct ndb_info *ni, const NdbDictionary::Dictionary *myDict )
-{
- const NdbDictionary::Table *myTable;
- const NdbDictionary::Column *myCol;
- NdbOcInfo *oci, octmp;
- NdbAttrInfo *ai;
- ObjectClass *oc;
- NdbDictionary::Dictionary::List myList;
- struct berval bv;
- int i, j, rc, col;
-
- rc = myDict->listObjects( myList, NdbDictionary::Object::UserTable );
- /* Populate our objectClass structures */
- for ( i=0; i<myList.count; i++ ) {
- /* Ignore other DBs */
- if ( strcmp( myList.elements[i].database, ni->ni_dbname ))
- continue;
- /* Ignore internal tables */
- if ( !strncmp( myList.elements[i].name, "OL_", 3 ))
- continue;
- ber_str2bv( myList.elements[i].name, 0, 0, &octmp.no_name );
- oci = (NdbOcInfo *)avl_find( ni->ni_oc_tree, &octmp, ndb_name_cmp );
- if ( oci )
- continue;
-
- oc = oc_bvfind( &octmp.no_name );
- if ( !oc ) {
- /* undefined - shouldn't happen */
- continue;
- }
- myTable = myDict->getTable( myList.elements[i].name );
- oci = (NdbOcInfo *)ch_malloc( sizeof( NdbOcInfo )+oc->soc_cname.bv_len+1 );
- oci->no_table.bv_val = (char *)(oci+1);
- strcpy( oci->no_table.bv_val, oc->soc_cname.bv_val );
- oci->no_table.bv_len = oc->soc_cname.bv_len;
- oci->no_name = oci->no_table;
- oci->no_oc = oc;
- oci->no_flag = 0;
- oci->no_nsets = 0;
- oci->no_nattrs = 0;
- col = 0;
- /* Make space for all attrs, even tho sups will be dropped */
- if ( oci->no_oc->soc_required ) {
- for ( j=0; oci->no_oc->soc_required[j]; j++ );
- col = j;
- }
- if ( oci->no_oc->soc_allowed ) {
- for ( j=0; oci->no_oc->soc_allowed[j]; j++ );
- col += j;
- }
- oci->no_attrs = (struct ndb_attrinfo **)ch_malloc( col * sizeof(struct ndb_attrinfo *));
- avl_insert( &ni->ni_oc_tree, oci, ndb_name_cmp, avl_dup_error );
-
- col = myTable->getNoOfColumns();
- /* Skip 0 and 1, eid and vid */
- for ( j = 2; j<col; j++ ) {
- myCol = myTable->getColumn( j );
- ber_str2bv( myCol->getName(), 0, 0, &bv );
- ai = ndb_ai_get( ni, &bv );
- /* shouldn't happen */
- if ( !ai )
- continue;
- ai->na_oi = oci;
- ai->na_column = j;
- ai->na_len = myCol->getLength();
- if ( myCol->getType() == NdbDictionary::Column::Blob )
- ai->na_flag |= NDB_INFO_ATBLOB;
- }
- }
- /* Link to any attrsets */
- for ( i=0; i<myList.count; i++ ) {
- /* Ignore other DBs */
- if ( strcmp( myList.elements[i].database, ni->ni_dbname ))
- continue;
- /* Ignore internal tables */
- if ( !strncmp( myList.elements[i].name, "OL_", 3 ))
- continue;
- ber_str2bv( myList.elements[i].name, 0, 0, &octmp.no_name );
- oci = (NdbOcInfo *)avl_find( ni->ni_oc_tree, &octmp, ndb_name_cmp );
- /* shouldn't happen */
- if ( !oci )
- continue;
- col = 2;
- if ( oci->no_oc->soc_required ) {
- rc = ndb_ai_check( ni, oci, oci->no_oc->soc_required, NULL, &col, 0 );
- }
- if ( oci->no_oc->soc_allowed ) {
- rc = ndb_ai_check( ni, oci, oci->no_oc->soc_allowed, NULL, &col, 0 );
- }
- /* shrink down to just the needed size */
- oci->no_attrs = (struct ndb_attrinfo **)ch_realloc( oci->no_attrs,
- oci->no_nattrs * sizeof(struct ndb_attrinfo *));
- }
- return 0;
-}
-
-static int
-ndb_oc_list( struct ndb_info *ni, const NdbDictionary::Dictionary *myDict,
- struct berval *oname, int implied, NdbOcs *out )
-{
- const NdbDictionary::Table *myTable;
- NdbOcInfo *oci, octmp;
- ObjectClass *oc;
- int i, rc;
-
- /* shortcut top */
- if ( ber_bvstrcasecmp( oname, &slap_schema.si_oc_top->soc_cname )) {
- octmp.no_name = *oname;
- oci = (NdbOcInfo *)avl_find( ni->ni_oc_tree, &octmp, ndb_name_cmp );
- if ( oci ) {
- oc = oci->no_oc;
- } else {
- oc = oc_bvfind( oname );
- if ( !oc ) {
- /* undefined - shouldn't happen */
- return LDAP_INVALID_SYNTAX;
- }
- }
- if ( oc->soc_sups ) {
- int i;
-
- for ( i=0; oc->soc_sups[i]; i++ ) {
- rc = ndb_oc_list( ni, myDict, &oc->soc_sups[i]->soc_cname, 1, out );
- if ( rc ) return rc;
- }
- }
- } else {
- oc = slap_schema.si_oc_top;
- }
- /* Only insert once */
- for ( i=0; i<out->no_ntext; i++ )
- if ( out->no_text[i].bv_val == oc->soc_cname.bv_val )
- break;
- if ( i == out->no_ntext ) {
- for ( i=0; i<out->no_nitext; i++ )
- if ( out->no_itext[i].bv_val == oc->soc_cname.bv_val )
- break;
- if ( i == out->no_nitext ) {
- if ( implied )
- out->no_itext[out->no_nitext++] = oc->soc_cname;
- else
- out->no_text[out->no_ntext++] = oc->soc_cname;
- }
- }
-
- /* ignore top, etc... */
- if ( oc->soc_kind == LDAP_SCHEMA_ABSTRACT )
- return 0;
-
- if ( !oci ) {
- ldap_pvt_thread_rdwr_runlock( &ni->ni_oc_rwlock );
- oci = (NdbOcInfo *)ch_malloc( sizeof( NdbOcInfo )+oc->soc_cname.bv_len+1 );
- oci->no_table.bv_val = (char *)(oci+1);
- strcpy( oci->no_table.bv_val, oc->soc_cname.bv_val );
- oci->no_table.bv_len = oc->soc_cname.bv_len;
- oci->no_name = oci->no_table;
- oci->no_oc = oc;
- oci->no_flag = 0;
- oci->no_nsets = 0;
- oci->no_nattrs = 0;
- ldap_pvt_thread_rdwr_wlock( &ni->ni_oc_rwlock );
- if ( avl_insert( &ni->ni_oc_tree, oci, ndb_name_cmp, ndb_oc_dup_err )) {
- octmp.no_oc = oci->no_oc;
- ch_free( oci );
- oci = (NdbOcInfo *)octmp.no_oc;
- }
- /* see if the oc table already exists in the DB */
- myTable = myDict->getTable( oci->no_table.bv_val );
- rc = ndb_oc_create( ni, oci, myTable == NULL );
- ldap_pvt_thread_rdwr_wunlock( &ni->ni_oc_rwlock );
- ldap_pvt_thread_rdwr_rlock( &ni->ni_oc_rwlock );
- if ( rc ) return rc;
- }
- /* Only insert once */
- for ( i=0; i<out->no_ninfo; i++ )
- if ( out->no_info[i] == oci )
- break;
- if ( i == out->no_ninfo )
- out->no_info[out->no_ninfo++] = oci;
- return 0;
-}
-
-extern "C" int
-ndb_aset_get( struct ndb_info *ni, struct berval *sname, struct berval *attrs, NdbOcInfo **ret )
-{
- NdbOcInfo *oci, octmp;
- int i, rc;
-
- octmp.no_name = *sname;
- oci = (NdbOcInfo *)avl_find( ni->ni_oc_tree, &octmp, ndb_name_cmp );
- if ( oci )
- return LDAP_ALREADY_EXISTS;
-
- for ( i=0; !BER_BVISNULL( &attrs[i] ); i++ ) {
- if ( !at_bvfind( &attrs[i] ))
- return LDAP_NO_SUCH_ATTRIBUTE;
- }
- i++;
-
- oci = (NdbOcInfo *)ch_calloc( 1, sizeof( NdbOcInfo ) + sizeof( ObjectClass ) +
- i*sizeof(AttributeType *) + sname->bv_len+1 );
- oci->no_oc = (ObjectClass *)(oci+1);
- oci->no_oc->soc_required = (AttributeType **)(oci->no_oc+1);
- oci->no_table.bv_val = (char *)(oci->no_oc->soc_required+i);
-
- for ( i=0; !BER_BVISNULL( &attrs[i] ); i++ )
- oci->no_oc->soc_required[i] = at_bvfind( &attrs[i] );
-
- strcpy( oci->no_table.bv_val, sname->bv_val );
- oci->no_table.bv_len = sname->bv_len;
- oci->no_name = oci->no_table;
- oci->no_oc->soc_cname = oci->no_name;
- oci->no_flag = NDB_INFO_ATSET;
-
- if ( !ber_bvcmp( sname, &slap_schema.si_oc_extensibleObject->soc_cname ))
- oci->no_oc->soc_kind = slap_schema.si_oc_extensibleObject->soc_kind;
-
- rc = ndb_oc_create( ni, oci, 0 );
- if ( !rc )
- rc = avl_insert( &ni->ni_oc_tree, oci, ndb_name_cmp, avl_dup_error );
- if ( rc ) {
- ch_free( oci );
- } else {
- *ret = oci;
- }
- return rc;
-}
-
-extern "C" int
-ndb_aset_create( struct ndb_info *ni, NdbOcInfo *oci )
-{
- char buf[4096], *ptr;
- NdbAttrInfo *ai;
- int i;
-
- ptr = buf + sprintf( buf,
- "CREATE TABLE IF NOT EXISTS `%s` (eid bigint unsigned NOT NULL, vid int unsigned NOT NULL",
- oci->no_table.bv_val );
-
- for ( i=0; i<oci->no_nattrs; i++ ) {
- if ( oci->no_attrs[i]->na_oi != oci )
- continue;
- ai = oci->no_attrs[i];
- ptr += sprintf( ptr, ", `%s` VARCHAR(%d)", ai->na_attr->sat_cname.bv_val,
- ai->na_len );
- if ( ai->na_flag & NDB_INFO_INDEX ) {
- ptr += sprintf( ptr, ", INDEX (`%s`)", ai->na_attr->sat_cname.bv_val );
- }
- }
- ptr = lutil_strcopy( ptr, ", PRIMARY KEY(eid, vid) ) ENGINE=ndb PARTITION BY KEY(eid)" );
- i = mysql_real_query( &ni->ni_sql, buf, ptr - buf );
- if ( i ) {
- Debug( LDAP_DEBUG_ANY,
- "ndb_aset_create: CREATE TABLE %s failed, %s (%d)\n",
- oci->no_table.bv_val, mysql_error(&ni->ni_sql), mysql_errno(&ni->ni_sql) );
- }
- return i;
-}
-
-static int
-ndb_oc_check( BackendDB *be, Ndb *ndb,
- struct berval *ocsin, NdbOcs *out )
-{
- struct ndb_info *ni = (struct ndb_info *) be->be_private;
- const NdbDictionary::Dictionary *myDict = ndb->getDictionary();
-
- int i, rc = 0;
-
- out->no_ninfo = 0;
- out->no_ntext = 0;
- out->no_nitext = 0;
-
- /* Find all objectclasses and their superiors. List
- * the superiors first.
- */
-
- ldap_pvt_thread_rdwr_rlock( &ni->ni_oc_rwlock );
- for ( i=0; !BER_BVISNULL( &ocsin[i] ); i++ ) {
- rc = ndb_oc_list( ni, myDict, &ocsin[i], 0, out );
- if ( rc ) break;
- }
- ldap_pvt_thread_rdwr_runlock( &ni->ni_oc_rwlock );
- return rc;
-}
-
-#define V_INS 1
-#define V_DEL 2
-#define V_REP 3
-
-static int ndb_flush_blobs;
-
-/* set all the unique attrs of this objectclass into the table
- */
-extern "C" int
-ndb_oc_attrs(
- NdbTransaction *txn,
- const NdbDictionary::Table *myTable,
- Entry *e,
- NdbOcInfo *no,
- NdbAttrInfo **attrs,
- int nattrs,
- Attribute *old
-)
-{
- char buf[65538], *ptr;
- Attribute **an, **ao, *a;
- NdbOperation *myop;
- int i, j, max = 0;
- int changed, rc;
- Uint64 eid = e->e_id;
-
- if ( !nattrs )
- return 0;
-
- an = (Attribute **)ch_malloc( 2 * nattrs * sizeof(Attribute *));
- ao = an + nattrs;
-
- /* Turn lists of attrs into arrays for easier access */
- for ( i=0; i<nattrs; i++ ) {
- if ( attrs[i]->na_oi != no ) {
- an[i] = NULL;
- ao[i] = NULL;
- continue;
- }
- for ( a=e->e_attrs; a; a=a->a_next ) {
- if ( a->a_desc == slap_schema.si_ad_objectClass )
- continue;
- if ( a->a_desc->ad_type == attrs[i]->na_attr ) {
- /* Don't process same attr twice */
- if ( a->a_flags & SLAP_ATTR_IXADD )
- a = NULL;
- else
- a->a_flags |= SLAP_ATTR_IXADD;
- break;
- }
- }
- an[i] = a;
- if ( a && a->a_numvals > max )
- max = a->a_numvals;
- for ( a=old; a; a=a->a_next ) {
- if ( a->a_desc == slap_schema.si_ad_objectClass )
- continue;
- if ( a->a_desc->ad_type == attrs[i]->na_attr )
- break;
- }
- ao[i] = a;
- if ( a && a->a_numvals > max )
- max = a->a_numvals;
- }
-
- for ( i=0; i<max; i++ ) {
- myop = NULL;
- for ( j=0; j<nattrs; j++ ) {
- if ( !an[j] && !ao[j] )
- continue;
- changed = 0;
- if ( an[j] && an[j]->a_numvals > i ) {
- /* both old and new are present, compare for changes */
- if ( ao[j] && ao[j]->a_numvals > i ) {
- if ( ber_bvcmp( &ao[j]->a_nvals[i], &an[j]->a_nvals[i] ))
- changed = V_REP;
- } else {
- changed = V_INS;
- }
- } else {
- if ( ao[j] && ao[j]->a_numvals > i )
- changed = V_DEL;
- }
- if ( changed ) {
- if ( !myop ) {
- rc = LDAP_OTHER;
- myop = txn->getNdbOperation( myTable );
- if ( !myop ) {
- goto done;
- }
- if ( old ) {
- if ( myop->writeTuple()) {
- goto done;
- }
- } else {
- if ( myop->insertTuple()) {
- goto done;
- }
- }
- if ( myop->equal( EID_COLUMN, eid )) {
- goto done;
- }
- if ( myop->equal( VID_COLUMN, i )) {
- goto done;
- }
- }
- if ( attrs[j]->na_flag & NDB_INFO_ATBLOB ) {
- NdbBlob *myBlob = myop->getBlobHandle( attrs[j]->na_column );
- rc = LDAP_OTHER;
- if ( !myBlob ) {
- Debug( LDAP_DEBUG_TRACE, "ndb_oc_attrs: getBlobHandle failed %s (%d)\n",
- myop->getNdbError().message, myop->getNdbError().code, 0 );
- goto done;
- }
- if ( slapMode & SLAP_TOOL_MODE )
- ndb_flush_blobs = 1;
- if ( changed & V_INS ) {
- if ( myBlob->setValue( an[j]->a_vals[i].bv_val, an[j]->a_vals[i].bv_len )) {
- Debug( LDAP_DEBUG_TRACE, "ndb_oc_attrs: blob->setValue failed %s (%d)\n",
- myBlob->getNdbError().message, myBlob->getNdbError().code, 0 );
- goto done;
- }
- } else {
- if ( myBlob->setValue( NULL, 0 )) {
- Debug( LDAP_DEBUG_TRACE, "ndb_oc_attrs: blob->setValue failed %s (%d)\n",
- myBlob->getNdbError().message, myBlob->getNdbError().code, 0 );
- goto done;
- }
- }
- } else {
- if ( changed & V_INS ) {
- if ( an[j]->a_vals[i].bv_len > attrs[j]->na_len ) {
- Debug( LDAP_DEBUG_ANY, "ndb_oc_attrs: attribute %s too long for column\n",
- attrs[j]->na_name.bv_val, 0, 0 );
- rc = LDAP_CONSTRAINT_VIOLATION;
- goto done;
- }
- ptr = buf;
- *ptr++ = an[j]->a_vals[i].bv_len & 0xff;
- if ( attrs[j]->na_len > 255 ) {
- /* MedVar */
- *ptr++ = an[j]->a_vals[i].bv_len >> 8;
- }
- memcpy( ptr, an[j]->a_vals[i].bv_val, an[j]->a_vals[i].bv_len );
- ptr = buf;
- } else {
- ptr = NULL;
- }
- if ( myop->setValue( attrs[j]->na_column, ptr )) {
- rc = LDAP_OTHER;
- goto done;
- }
- }
- }
- }
- }
- rc = LDAP_SUCCESS;
-done:
- ch_free( an );
- if ( rc ) {
- Debug( LDAP_DEBUG_TRACE, "ndb_oc_attrs: failed %s (%d)\n",
- myop->getNdbError().message, myop->getNdbError().code, 0 );
- }
- return rc;
-}
-
-static int
-ndb_oc_put(
- const NdbDictionary::Dictionary *myDict,
- NdbTransaction *txn, NdbOcInfo *no, Entry *e )
-{
- const NdbDictionary::Table *myTable;
- int i, rc;
-
- for ( i=0; i<no->no_nsets; i++ ) {
- rc = ndb_oc_put( myDict, txn, no->no_sets[i], e );
- if ( rc )
- return rc;
- }
-
- myTable = myDict->getTable( no->no_table.bv_val );
- if ( !myTable )
- return LDAP_OTHER;
-
- return ndb_oc_attrs( txn, myTable, e, no, no->no_attrs, no->no_nattrs, NULL );
-}
-
-/* This is now only used for Adds. Modifies call ndb_oc_attrs directly. */
-extern "C" int
-ndb_entry_put_data(
- BackendDB *be,
- NdbArgs *NA
-)
-{
- struct ndb_info *ni = (struct ndb_info *) be->be_private;
- Attribute *aoc;
- const NdbDictionary::Dictionary *myDict = NA->ndb->getDictionary();
- NdbOcs myOcs;
- int i, rc;
-
- /* Get the entry's objectClass attribute */
- aoc = attr_find( NA->e->e_attrs, slap_schema.si_ad_objectClass );
- if ( !aoc )
- return LDAP_OTHER;
-
- ndb_oc_check( be, NA->ndb, aoc->a_nvals, &myOcs );
- myOcs.no_info[myOcs.no_ninfo++] = ni->ni_opattrs;
-
- /* Walk thru objectclasses, find all the attributes belonging to a class */
- for ( i=0; i<myOcs.no_ninfo; i++ ) {
- rc = ndb_oc_put( myDict, NA->txn, myOcs.no_info[i], NA->e );
- if ( rc ) return rc;
- }
-
- /* slapadd tries to batch multiple entries per txn, but entry data is
- * transient and blob data is required to remain valid for the whole txn.
- * So we need to flush blobs before their source data disappears.
- */
- if (( slapMode & SLAP_TOOL_MODE ) && ndb_flush_blobs )
- NA->txn->execute( NdbTransaction::NoCommit );
-
- return 0;
-}
-
-static void
-ndb_oc_get( Operation *op, NdbOcInfo *no, int *j, int *nocs, NdbOcInfo ***oclist )
-{
- int i;
- NdbOcInfo **ol2;
-
- for ( i=0; i<no->no_nsets; i++ ) {
- ndb_oc_get( op, no->no_sets[i], j, nocs, oclist );
- }
-
- /* Don't insert twice */
- ol2 = *oclist;
- for ( i=0; i<*j; i++ )
- if ( ol2[i] == no )
- return;
-
- if ( *j >= *nocs ) {
- *nocs *= 2;
- ol2 = (NdbOcInfo **)op->o_tmprealloc( *oclist, *nocs * sizeof(NdbOcInfo *), op->o_tmpmemctx );
- *oclist = ol2;
- }
- ol2 = *oclist;
- ol2[(*j)++] = no;
-}
-
-/* Retrieve attribute data for given entry. The entry's DN and eid should
- * already be populated.
- */
-extern "C" int
-ndb_entry_get_data(
- Operation *op,
- NdbArgs *NA,
- int update
-)
-{
- struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private;
- const NdbDictionary::Dictionary *myDict = NA->ndb->getDictionary();
- const NdbDictionary::Table *myTable;
- NdbIndexScanOperation **myop = NULL;
- Uint64 eid;
-
- Attribute *a;
- NdbOcs myOcs;
- NdbOcInfo *oci, **oclist = NULL;
- char abuf[65536], *ptr, **attrs = NULL;
- struct berval bv[2];
- int *ocx = NULL;
-
- /* FIXME: abuf should be dynamically allocated */
-
- int i, j, k, nocs, nattrs, rc = LDAP_OTHER;
-
- eid = NA->e->e_id;
-
- ndb_oc_check( op->o_bd, NA->ndb, NA->ocs, &myOcs );
- myOcs.no_info[myOcs.no_ninfo++] = ni->ni_opattrs;
- nocs = myOcs.no_ninfo;
-
- oclist = (NdbOcInfo **)op->o_tmpcalloc( 1, nocs * sizeof(NdbOcInfo *), op->o_tmpmemctx );
-
- for ( i=0, j=0; i<myOcs.no_ninfo; i++ ) {
- ndb_oc_get( op, myOcs.no_info[i], &j, &nocs, &oclist );
- }
-
- nocs = j;
- nattrs = 0;
- for ( i=0; i<nocs; i++ )
- nattrs += oclist[i]->no_nattrs;
-
- ocx = (int *)op->o_tmpalloc( nocs * sizeof(int), op->o_tmpmemctx );
-
- attrs = (char **)op->o_tmpalloc( nattrs * sizeof(char *), op->o_tmpmemctx );
-
- myop = (NdbIndexScanOperation **)op->o_tmpalloc( nattrs * sizeof(NdbIndexScanOperation *), op->o_tmpmemctx );
-
- k = 0;
- ptr = abuf;
- for ( i=0; i<nocs; i++ ) {
- oci = oclist[i];
-
- myop[i] = NA->txn->getNdbIndexScanOperation( "PRIMARY", oci->no_table.bv_val );
- if ( !myop[i] )
- goto leave;
- if ( myop[i]->readTuples( update ? NdbOperation::LM_Exclusive : NdbOperation::LM_CommittedRead ))
- goto leave;
- if ( myop[i]->setBound( 0U, NdbIndexScanOperation::BoundEQ, &eid ))
- goto leave;
-
- for ( j=0; j<oci->no_nattrs; j++ ) {
- if ( oci->no_attrs[j]->na_oi != oci )
- continue;
- if ( oci->no_attrs[j]->na_flag & NDB_INFO_ATBLOB ) {
- NdbBlob *bi = myop[i]->getBlobHandle( oci->no_attrs[j]->na_column );
- attrs[k++] = (char *)bi;
- } else {
- attrs[k] = ptr;
- *ptr++ = 0;
- if ( oci->no_attrs[j]->na_len > 255 )
- *ptr++ = 0;
- ptr += oci->no_attrs[j]->na_len + 1;
- myop[i]->getValue( oci->no_attrs[j]->na_column, attrs[k++] );
- }
- }
- ocx[i] = k;
- }
- /* Must use IgnoreError, because an entry with multiple objectClasses may not
- * actually have attributes defined in each class / table.
- */
- if ( NA->txn->execute( NdbTransaction::NoCommit, NdbOperation::AO_IgnoreError, 1) < 0 )
- goto leave;
-
- /* count results */
- for ( i=0; i<nocs; i++ ) {
- if (( j = myop[i]->nextResult(true) )) {
- if ( j < 0 ) {
- Debug( LDAP_DEBUG_TRACE,
- "ndb_entry_get_data: first nextResult(%d) failed: %s (%d)\n",
- i, myop[i]->getNdbError().message, myop[i]->getNdbError().code );
- }
- myop[i] = NULL;
- }
- }
-
- nattrs = 0;
- k = 0;
- for ( i=0; i<nocs; i++ ) {
- oci = oclist[i];
- for ( j=0; j<oci->no_nattrs; j++ ) {
- unsigned char *buf;
- int len;
- if ( oci->no_attrs[j]->na_oi != oci )
- continue;
- if ( !myop[i] ) {
- attrs[k] = NULL;
- } else if ( oci->no_attrs[j]->na_flag & NDB_INFO_ATBLOB ) {
- void *vi = attrs[k];
- NdbBlob *bi = (NdbBlob *)vi;
- int isNull;
- bi->getNull( isNull );
- if ( !isNull ) {
- nattrs++;
- } else {
- attrs[k] = NULL;
- }
- } else {
- buf = (unsigned char *)attrs[k];
- len = buf[0];
- if ( oci->no_attrs[j]->na_len > 255 ) {
- /* MedVar */
- len |= (buf[1] << 8);
- }
- if ( len ) {
- nattrs++;
- } else {
- attrs[k] = NULL;
- }
- }
- k++;
- }
- }
-
- a = attrs_alloc( nattrs+1 );
- NA->e->e_attrs = a;
-
- a->a_desc = slap_schema.si_ad_objectClass;
- a->a_vals = NULL;
- ber_bvarray_dup_x( &a->a_vals, NA->ocs, NULL );
- a->a_nvals = a->a_vals;
- a->a_numvals = myOcs.no_ntext;
-
- BER_BVZERO( &bv[1] );
-
- do {
- a = NA->e->e_attrs->a_next;
- k = 0;
- for ( i=0; i<nocs; k=ocx[i], i++ ) {
- oci = oclist[i];
- for ( j=0; j<oci->no_nattrs; j++ ) {
- unsigned char *buf;
- struct berval nbv;
- if ( oci->no_attrs[j]->na_oi != oci )
- continue;
- buf = (unsigned char *)attrs[k++];
- if ( !buf )
- continue;
- if ( !myop[i] ) {
- a=a->a_next;
- continue;
- }
- if ( oci->no_attrs[j]->na_flag & NDB_INFO_ATBLOB ) {
- void *vi = (void *)buf;
- NdbBlob *bi = (NdbBlob *)vi;
- Uint64 len;
- Uint32 len2;
- int isNull;
- bi->getNull( isNull );
- if ( isNull ) {
- a = a->a_next;
- continue;
- }
- bi->getLength( len );
- bv[0].bv_len = len;
- bv[0].bv_val = (char *)ch_malloc( len+1 );
- len2 = len;
- if ( bi->readData( bv[0].bv_val, len2 )) {
- Debug( LDAP_DEBUG_TRACE,
- "ndb_entry_get_data: blob readData failed: %s (%d), len %d\n",
- bi->getNdbError().message, bi->getNdbError().code, len2 );
- }
- bv[0].bv_val[len] = '\0';
- ber_bvarray_add_x( &a->a_vals, bv, NULL );
- } else {
- bv[0].bv_len = buf[0];
- if ( oci->no_attrs[j]->na_len > 255 ) {
- /* MedVar */
- bv[0].bv_len |= (buf[1] << 8);
- bv[0].bv_val = (char *)buf+2;
- buf[1] = 0;
- } else {
- bv[0].bv_val = (char *)buf+1;
- }
- buf[0] = 0;
- if ( bv[0].bv_len == 0 ) {
- a = a->a_next;
- continue;
- }
- bv[0].bv_val[bv[0].bv_len] = '\0';
- value_add_one( &a->a_vals, bv );
- }
- a->a_desc = oci->no_attrs[j]->na_desc;
- attr_normalize_one( a->a_desc, bv, &nbv, NULL );
- a->a_numvals++;
- if ( !BER_BVISNULL( &nbv )) {
- ber_bvarray_add_x( &a->a_nvals, &nbv, NULL );
- } else if ( !a->a_nvals ) {
- a->a_nvals = a->a_vals;
- }
- a = a->a_next;
- }
- }
- k = 0;
- for ( i=0; i<nocs; i++ ) {
- if ( !myop[i] )
- continue;
- if ((j = myop[i]->nextResult(true))) {
- if ( j < 0 ) {
- Debug( LDAP_DEBUG_TRACE,
- "ndb_entry_get_data: last nextResult(%d) failed: %s (%d)\n",
- i, myop[i]->getNdbError().message, myop[i]->getNdbError().code );
- }
- myop[i] = NULL;
- } else {
- k = 1;
- }
- }
- } while ( k );
-
- rc = 0;
-leave:
- if ( myop ) {
- op->o_tmpfree( myop, op->o_tmpmemctx );
- }
- if ( attrs ) {
- op->o_tmpfree( attrs, op->o_tmpmemctx );
- }
- if ( ocx ) {
- op->o_tmpfree( ocx, op->o_tmpmemctx );
- }
- if ( oclist ) {
- op->o_tmpfree( oclist, op->o_tmpmemctx );
- }
-
- return rc;
-}
-
-static int
-ndb_oc_del(
- NdbTransaction *txn, Uint64 eid, NdbOcInfo *no )
-{
- NdbIndexScanOperation *myop;
- int i, rc;
-
- for ( i=0; i<no->no_nsets; i++ ) {
- rc = ndb_oc_del( txn, eid, no->no_sets[i] );
- if ( rc ) return rc;
- }
-
- myop = txn->getNdbIndexScanOperation( "PRIMARY", no->no_table.bv_val );
- if ( !myop )
- return LDAP_OTHER;
- if ( myop->readTuples( NdbOperation::LM_Exclusive ))
- return LDAP_OTHER;
- if ( myop->setBound( 0U, NdbIndexScanOperation::BoundEQ, &eid ))
- return LDAP_OTHER;
-
- txn->execute(NoCommit);
- while ( myop->nextResult(true) == 0) {
- do {
- myop->deleteCurrentTuple();
- } while (myop->nextResult(false) == 0);
- txn->execute(NoCommit);
- }
-
- return 0;
-}
-
-extern "C" int
-ndb_entry_del_data(
- BackendDB *be,
- NdbArgs *NA
-)
-{
- struct ndb_info *ni = (struct ndb_info *) be->be_private;
- Uint64 eid = NA->e->e_id;
- int i;
- NdbOcs myOcs;
-
- ndb_oc_check( be, NA->ndb, NA->ocs, &myOcs );
- myOcs.no_info[myOcs.no_ninfo++] = ni->ni_opattrs;
-
- for ( i=0; i<myOcs.no_ninfo; i++ ) {
- if ( ndb_oc_del( NA->txn, eid, myOcs.no_info[i] ))
- return LDAP_OTHER;
- }
-
- return 0;
-}
-
-extern "C" int
-ndb_dn2rdns(
- struct berval *dn,
- NdbRdns *rdns
-)
-{
- char *beg, *end;
- int i, len;
-
- /* Walk thru RDNs */
- end = dn->bv_val + dn->bv_len;
- for ( i=0; i<NDB_MAX_RDNS; i++ ) {
- for ( beg = end-1; beg > dn->bv_val; beg-- ) {
- if (*beg == ',') {
- beg++;
- break;
- }
- }
- if ( beg >= dn->bv_val ) {
- len = end - beg;
- /* RDN is too long */
- if ( len > NDB_RDN_LEN )
- return LDAP_CONSTRAINT_VIOLATION;
- memcpy( rdns->nr_buf[i]+1, beg, len );
- } else {
- break;
- }
- rdns->nr_buf[i][0] = len;
- end = beg - 1;
- }
- /* Too many RDNs in DN */
- if ( i == NDB_MAX_RDNS && beg > dn->bv_val ) {
- return LDAP_CONSTRAINT_VIOLATION;
- }
- rdns->nr_num = i;
- return 0;
-}
-
-static int
-ndb_rdns2keys(
- NdbOperation *myop,
- NdbRdns *rdns
-)
-{
- int i;
- char dummy[2] = {0,0};
-
- /* Walk thru RDNs */
- for ( i=0; i<rdns->nr_num; i++ ) {
- if ( myop->equal( i+RDN_COLUMN, rdns->nr_buf[i] ))
- return LDAP_OTHER;
- }
- for ( ; i<NDB_MAX_RDNS; i++ ) {
- if ( myop->equal( i+RDN_COLUMN, dummy ))
- return LDAP_OTHER;
- }
- return 0;
-}
-
-/* Store the DN2ID_TABLE fields */
-extern "C" int
-ndb_entry_put_info(
- BackendDB *be,
- NdbArgs *NA,
- int update
-)
-{
- struct ndb_info *ni = (struct ndb_info *) be->be_private;
- const NdbDictionary::Dictionary *myDict = NA->ndb->getDictionary();
- const NdbDictionary::Table *myTable = myDict->getTable( DN2ID_TABLE );
- NdbOperation *myop;
- NdbAttrInfo *ai;
- Attribute *aoc, *a;
-
- /* Get the entry's objectClass attribute; it's ok to be
- * absent on a fresh insert
- */
- aoc = attr_find( NA->e->e_attrs, slap_schema.si_ad_objectClass );
- if ( update && !aoc )
- return LDAP_OBJECT_CLASS_VIOLATION;
-
- myop = NA->txn->getNdbOperation( myTable );
- if ( !myop )
- return LDAP_OTHER;
- if ( update ) {
- if ( myop->updateTuple())
- return LDAP_OTHER;
- } else {
- if ( myop->insertTuple())
- return LDAP_OTHER;
- }
-
- if ( ndb_rdns2keys( myop, NA->rdns ))
- return LDAP_OTHER;
-
- /* Set entry ID */
- {
- Uint64 eid = NA->e->e_id;
- if ( myop->setValue( EID_COLUMN, eid ))
- return LDAP_OTHER;
- }
-
- /* Set list of objectClasses */
- /* List is <sp> <class> <sp> <class> <sp> ... so that
- * searches for " class " will yield accurate results
- */
- if ( aoc ) {
- char *ptr, buf[sizeof(MedVar)];
- NdbOcs myOcs;
- int i;
-
- ndb_oc_check( be, NA->ndb, aoc->a_nvals, &myOcs );
- ptr = buf+2;
- *ptr++ = ' ';
- for ( i=0; i<myOcs.no_ntext; i++ ) {
- /* data loss... */
- if ( ptr + myOcs.no_text[i].bv_len + 1 >= &buf[sizeof(buf)] )
- break;
- ptr = lutil_strcopy( ptr, myOcs.no_text[i].bv_val );
- *ptr++ = ' ';
- }
-
- /* implicit classes */
- if ( myOcs.no_nitext ) {
- *ptr++ = '@';
- *ptr++ = ' ';
- for ( i=0; i<myOcs.no_nitext; i++ ) {
- /* data loss... */
- if ( ptr + myOcs.no_itext[i].bv_len + 1 >= &buf[sizeof(buf)] )
- break;
- ptr = lutil_strcopy( ptr, myOcs.no_itext[i].bv_val );
- *ptr++ = ' ';
- }
- }
-
- i = ptr - buf - 2;
- buf[0] = i & 0xff;
- buf[1] = i >> 8;
- if ( myop->setValue( OCS_COLUMN, buf ))
- return LDAP_OTHER;
- }
-
- /* Set any indexed attrs */
- for ( a = NA->e->e_attrs; a; a=a->a_next ) {
- ai = ndb_ai_find( ni, a->a_desc->ad_type );
- if ( ai && ( ai->na_flag & NDB_INFO_INDEX )) {
- char *ptr, buf[sizeof(MedVar)];
- int len;
-
- ptr = buf+1;
- len = a->a_vals[0].bv_len;
- /* FIXME: data loss */
- if ( len > ai->na_len )
- len = ai->na_len;
- buf[0] = len & 0xff;
- if ( ai->na_len > 255 ) {
- *ptr++ = len >> 8;
- }
- memcpy( ptr, a->a_vals[0].bv_val, len );
- if ( myop->setValue( ai->na_ixcol, buf ))
- return LDAP_OTHER;
- }
- }
-
- return 0;
-}
-
-extern "C" struct berval *
-ndb_str2bvarray(
- char *str,
- int len,
- char delim,
- void *ctx
-)
-{
- struct berval *list, tmp;
- char *beg;
- int i, num;
-
- while ( *str == delim ) {
- str++;
- len--;
- }
-
- while ( str[len-1] == delim ) {
- str[--len] = '\0';
- }
-
- for ( i = 1, beg = str;; i++ ) {
- beg = strchr( beg, delim );
- if ( !beg )
- break;
- if ( beg >= str + len )
- break;
- beg++;
- }
-
- num = i;
- list = (struct berval *)slap_sl_malloc( (num+1)*sizeof(struct berval), ctx);
-
- for ( i = 0, beg = str; i<num; i++ ) {
- tmp.bv_val = beg;
- beg = strchr( beg, delim );
- if ( beg >= str + len )
- beg = NULL;
- if ( beg ) {
- tmp.bv_len = beg - tmp.bv_val;
- } else {
- tmp.bv_len = len - (tmp.bv_val - str);
- }
- ber_dupbv_x( &list[i], &tmp, ctx );
- beg++;
- }
-
- BER_BVZERO( &list[i] );
- return list;
-}
-
-extern "C" struct berval *
-ndb_ref2oclist(
- const char *ref,
- void *ctx
-)
-{
- char *implied;
-
- /* MedVar */
- int len = ref[0] | (ref[1] << 8);
-
- /* don't return the implied classes */
- implied = (char *)memchr( ref+2, '@', len );
- if ( implied ) {
- len = implied - ref - 2;
- *implied = '\0';
- }
-
- return ndb_str2bvarray( (char *)ref+2, len, ' ', ctx );
-}
-
-/* Retrieve the DN2ID_TABLE fields. Can call with NULL ocs if just verifying
- * the existence of a DN.
- */
-extern "C" int
-ndb_entry_get_info(
- Operation *op,
- NdbArgs *NA,
- int update,
- struct berval *matched
-)
-{
- struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private;
- const NdbDictionary::Dictionary *myDict = NA->ndb->getDictionary();
- const NdbDictionary::Table *myTable = myDict->getTable( DN2ID_TABLE );
- NdbOperation *myop[NDB_MAX_RDNS];
- NdbRecAttr *eid[NDB_MAX_RDNS], *oc[NDB_MAX_RDNS];
- char idbuf[NDB_MAX_RDNS][2*sizeof(ID)];
- char ocbuf[NDB_MAX_RDNS][NDB_OC_BUFLEN];
-
- if ( matched ) {
- BER_BVZERO( matched );
- }
- if ( !myTable ) {
- return LDAP_OTHER;
- }
-
- myop[0] = NA->txn->getNdbOperation( myTable );
- if ( !myop[0] ) {
- return LDAP_OTHER;
- }
-
- if ( myop[0]->readTuple( update ? NdbOperation::LM_Exclusive : NdbOperation::LM_CommittedRead )) {
- return LDAP_OTHER;
- }
-
- if ( !NA->rdns->nr_num && ndb_dn2rdns( &NA->e->e_name, NA->rdns )) {
- return LDAP_NO_SUCH_OBJECT;
- }
-
- if ( ndb_rdns2keys( myop[0], NA->rdns )) {
- return LDAP_OTHER;
- }
-
- eid[0] = myop[0]->getValue( EID_COLUMN, idbuf[0] );
- if ( !eid[0] ) {
- return LDAP_OTHER;
- }
-
- ocbuf[0][0] = 0;
- ocbuf[0][1] = 0;
- if ( !NA->ocs ) {
- oc[0] = myop[0]->getValue( OCS_COLUMN, ocbuf[0] );
- if ( !oc[0] ) {
- return LDAP_OTHER;
- }
- }
-
- if ( NA->txn->execute(NdbTransaction::NoCommit, NdbOperation::AO_IgnoreError, 1) < 0 ) {
- return LDAP_OTHER;
- }
-
- switch( myop[0]->getNdbError().code ) {
- case 0:
- if ( !eid[0]->isNULL() && ( NA->e->e_id = eid[0]->u_64_value() )) {
- /* If we didn't care about OCs, or we got them */
- if ( NA->ocs || ocbuf[0][0] || ocbuf[0][1] ) {
- /* If wanted, return them */
- if ( !NA->ocs )
- NA->ocs = ndb_ref2oclist( ocbuf[0], op->o_tmpmemctx );
- break;
- }
- }
- /* FALLTHRU */
- case NDB_NO_SUCH_OBJECT: /* no such tuple: look for closest parent */
- if ( matched ) {
- int i, j, k;
- char dummy[2] = {0,0};
-
- /* get to last RDN, then back up 1 */
- k = NA->rdns->nr_num - 1;
-
- for ( i=0; i<k; i++ ) {
- myop[i] = NA->txn->getNdbOperation( myTable );
- if ( !myop[i] )
- return LDAP_OTHER;
- if ( myop[i]->readTuple( NdbOperation::LM_CommittedRead ))
- return LDAP_OTHER;
- for ( j=0; j<=i; j++ ) {
- if ( myop[i]->equal( j+RDN_COLUMN, NA->rdns->nr_buf[j] ))
- return LDAP_OTHER;
- }
- for ( ;j<NDB_MAX_RDNS; j++ ) {
- if ( myop[i]->equal( j+RDN_COLUMN, dummy ))
- return LDAP_OTHER;
- }
- eid[i] = myop[i]->getValue( EID_COLUMN, idbuf[i] );
- if ( !eid[i] ) {
- return LDAP_OTHER;
- }
- ocbuf[i][0] = 0;
- ocbuf[i][1] = 0;
- if ( !NA->ocs ) {
- oc[i] = myop[0]->getValue( OCS_COLUMN, ocbuf[i] );
- if ( !oc[i] ) {
- return LDAP_OTHER;
- }
- }
- }
- if ( NA->txn->execute(NdbTransaction::NoCommit, NdbOperation::AO_IgnoreError, 1) < 0 ) {
- return LDAP_OTHER;
- }
- for ( --i; i>=0; i-- ) {
- if ( myop[i]->getNdbError().code == 0 ) {
- for ( j=0; j<=i; j++ )
- matched->bv_len += NA->rdns->nr_buf[j][0];
- NA->erdns = NA->rdns->nr_num;
- NA->rdns->nr_num = j;
- matched->bv_len += i;
- matched->bv_val = NA->e->e_name.bv_val +
- NA->e->e_name.bv_len - matched->bv_len;
- if ( !eid[i]->isNULL() )
- NA->e->e_id = eid[i]->u_64_value();
- if ( !NA->ocs )
- NA->ocs = ndb_ref2oclist( ocbuf[i], op->o_tmpmemctx );
- break;
- }
- }
- }
- return LDAP_NO_SUCH_OBJECT;
- default:
- return LDAP_OTHER;
- }
-
- return 0;
-}
-
-extern "C" int
-ndb_entry_del_info(
- BackendDB *be,
- NdbArgs *NA
-)
-{
- struct ndb_info *ni = (struct ndb_info *) be->be_private;
- const NdbDictionary::Dictionary *myDict = NA->ndb->getDictionary();
- const NdbDictionary::Table *myTable = myDict->getTable( DN2ID_TABLE );
- NdbOperation *myop;
-
- myop = NA->txn->getNdbOperation( myTable );
- if ( !myop )
- return LDAP_OTHER;
- if ( myop->deleteTuple())
- return LDAP_OTHER;
-
- if ( ndb_rdns2keys( myop, NA->rdns ))
- return LDAP_OTHER;
-
- return 0;
-}
-
-extern "C" int
-ndb_next_id(
- BackendDB *be,
- Ndb *ndb,
- ID *id
-)
-{
- struct ndb_info *ni = (struct ndb_info *) be->be_private;
- const NdbDictionary::Dictionary *myDict = ndb->getDictionary();
- const NdbDictionary::Table *myTable = myDict->getTable( NEXTID_TABLE );
- Uint64 nid = 0;
- int rc;
-
- if ( !myTable ) {
- Debug( LDAP_DEBUG_ANY, "ndb_next_id: " NEXTID_TABLE " table is missing\n",
- 0, 0, 0 );
- return LDAP_OTHER;
- }
-
- rc = ndb->getAutoIncrementValue( myTable, nid, 1000 );
- if ( !rc )
- *id = nid;
- return rc;
-}
-
-extern "C" { static void ndb_thread_hfree( void *key, void *data ); };
-static void
-ndb_thread_hfree( void *key, void *data )
-{
- Ndb *ndb = (Ndb *)data;
- delete ndb;
-}
-
-extern "C" int
-ndb_thread_handle(
- Operation *op,
- Ndb **ndb )
-{
- struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private;
- void *data;
-
- if ( ldap_pvt_thread_pool_getkey( op->o_threadctx, ni, &data, NULL )) {
- Ndb *myNdb;
- int rc;
- ldap_pvt_thread_mutex_lock( &ni->ni_conn_mutex );
- myNdb = new Ndb( ni->ni_cluster[ni->ni_nextconn++], ni->ni_dbname );
- if ( ni->ni_nextconn >= ni->ni_nconns )
- ni->ni_nextconn = 0;
- ldap_pvt_thread_mutex_unlock( &ni->ni_conn_mutex );
- if ( !myNdb ) {
- return LDAP_OTHER;
- }
- rc = myNdb->init(1024);
- if ( rc ) {
- delete myNdb;
- Debug( LDAP_DEBUG_ANY, "ndb_thread_handle: err %d\n",
- rc, 0, 0 );
- return rc;
- }
- data = (void *)myNdb;
- if (( rc = ldap_pvt_thread_pool_setkey( op->o_threadctx, ni,
- data, ndb_thread_hfree, NULL, NULL ))) {
- delete myNdb;
- Debug( LDAP_DEBUG_ANY, "ndb_thread_handle: err %d\n",
- rc, 0, 0 );
- return rc;
- }
- }
- *ndb = (Ndb *)data;
- return 0;
-}
-
-extern "C" int
-ndb_entry_get(
- Operation *op,
- struct berval *ndn,
- ObjectClass *oc,
- AttributeDescription *ad,
- int rw,
- Entry **ent )
-{
- struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private;
- NdbArgs NA;
- Entry e = {0};
- int rc;
-
- /* Get our NDB handle */
- rc = ndb_thread_handle( op, &NA.ndb );
-
- NA.txn = NA.ndb->startTransaction();
- if( !NA.txn ) {
- Debug( LDAP_DEBUG_TRACE,
- LDAP_XSTRING(ndb_entry_get) ": startTransaction failed: %s (%d)\n",
- NA.ndb->getNdbError().message, NA.ndb->getNdbError().code, 0 );
- return 1;
- }
-
- e.e_name = *ndn;
- NA.e = &e;
- /* get entry */
- {
- NdbRdns rdns;
- rdns.nr_num = 0;
- NA.ocs = NULL;
- NA.rdns = &rdns;
- rc = ndb_entry_get_info( op, &NA, rw, NULL );
- }
- if ( rc == 0 ) {
- e.e_name = *ndn;
- e.e_nname = *ndn;
- rc = ndb_entry_get_data( op, &NA, 0 );
- ber_bvarray_free( NA.ocs );
- if ( rc == 0 ) {
- if ( oc && !is_entry_objectclass_or_sub( &e, oc )) {
- attrs_free( e.e_attrs );
- rc = 1;
- }
- }
- }
- if ( rc == 0 ) {
- *ent = entry_alloc();
- **ent = e;
- ber_dupbv( &(*ent)->e_name, ndn );
- ber_dupbv( &(*ent)->e_nname, ndn );
- } else {
- rc = 1;
- }
- NA.txn->close();
- return rc;
-}
-
-/* Congestion avoidance code
- * for Deadlock Rollback
- */
-
-extern "C" void
-ndb_trans_backoff( int num_retries )
-{
- int i;
- int delay = 0;
- int pow_retries = 1;
- unsigned long key = 0;
- unsigned long max_key = -1;
- struct timeval timeout;
-
- lutil_entropy( (unsigned char *) &key, sizeof( unsigned long ));
-
- for ( i = 0; i < num_retries; i++ ) {
- if ( i >= 5 ) break;
- pow_retries *= 4;
- }
-
- delay = 16384 * (key * (double) pow_retries / (double) max_key);
- delay = delay ? delay : 1;
-
- Debug( LDAP_DEBUG_TRACE, "delay = %d, num_retries = %d\n", delay, num_retries, 0 );
-
- timeout.tv_sec = delay / 1000000;
- timeout.tv_usec = delay % 1000000;
- select( 0, NULL, NULL, NULL, &timeout );
-}
-
-extern "C" void
-ndb_check_referral( Operation *op, SlapReply *rs, NdbArgs *NA )
-{
- struct berval dn, ndn;
- int i, dif;
- dif = NA->erdns - NA->rdns->nr_num;
-
- /* Set full DN of matched into entry */
- for ( i=0; i<dif; i++ ) {
- dnParent( &NA->e->e_name, &dn );
- dnParent( &NA->e->e_nname, &ndn );
- NA->e->e_name = dn;
- NA->e->e_nname = ndn;
- }
-
- /* return referral only if "disclose" is granted on the object */
- if ( access_allowed( op, NA->e, slap_schema.si_ad_entry,
- NULL, ACL_DISCLOSE, NULL )) {
- Attribute a;
- for ( i=0; !BER_BVISNULL( &NA->ocs[i] ); i++ );
- a.a_numvals = i;
- a.a_desc = slap_schema.si_ad_objectClass;
- a.a_vals = NA->ocs;
- a.a_nvals = NA->ocs;
- a.a_next = NULL;
- NA->e->e_attrs = &a;
- if ( is_entry_referral( NA->e )) {
- NA->e->e_attrs = NULL;
- ndb_entry_get_data( op, NA, 0 );
- rs->sr_ref = get_entry_referrals( op, NA->e );
- if ( rs->sr_ref ) {
- rs->sr_err = LDAP_REFERRAL;
- rs->sr_flags |= REP_REF_MUSTBEFREED;
- }
- attrs_free( NA->e->e_attrs );
- }
- NA->e->e_attrs = NULL;
- }
-}
+++ /dev/null
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2008-2021 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 */
+++ /dev/null
-/* search.cpp - tools for slap tools */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2008-2021 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 );
- {
-#if 1 /* NDBapi was broken here but seems to work now */
- Ndb::Key_part_ptr keys[2];
- char xbuf[512];
- 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;
- rs->sr_attrs = 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 );
- if ( !scan ) {
- rs->sr_err = LDAP_OTHER;
- goto leave;
- }
- 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 ) {
- if ( (*ap)->a_desc == slap_schema.si_ad_hasSubordinates ) {
- break;
- }
- }
-
- if ( *ap == NULL &&
- attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_hasSubordinates ) == NULL &&
- ( SLAP_OPATTRS( rs->sr_attr_flags ) ||
- ad_inlist( slap_schema.si_ad_hasSubordinates, rs->sr_attrs ) ) )
- {
- int hasSubordinates, rc;
-
- rc = 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;
-}
-
+++ /dev/null
-/* tools.cpp - tools for slap tools */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2008-2021 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;
-
- if ( slapMode & SLAP_TOOL_DRYRUN )
- return 0;
-
- myNdb = new Ndb( ni->ni_cluster[0], ni->ni_dbname );
- return myNdb->init(1024);
-}
-
-extern "C"
-int ndb_tool_entry_close(
- BackendDB *be )
-{
- if ( slapMode & SLAP_TOOL_DRYRUN )
- return 0;
-
- 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? */
-
- if ( slapMode & SLAP_TOOL_DRYRUN )
- return 0;
-
- 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;
-}
-
* OLcfg{Bk|Db}{Oc|At}:3 -> back-ldap/meta
* OLcfg{Bk|Db}{Oc|At}:4 -> back-monitor
* OLcfg{Bk|Db}{Oc|At}:5 -> back-relay
- * OLcfg{Bk|Db}{Oc|At}:6 -> back-sql(/back-ndb)
+ * OLcfg{Bk|Db}{Oc|At}:6 -> back-sql
* OLcfg{Bk|Db}{Oc|At}:7 -> back-sock
* OLcfg{Bk|Db}{Oc|At}:8 -> back-null
* OLcfg{Bk|Db}{Oc|At}:9 -> back-passwd
+++ /dev/null
-# back-ndb boilerplate config -- for testing
-# $OpenLDAP$
-## This work is part of OpenLDAP Software <http://www.openldap.org/>.
-##
-## Copyright 1998-2021 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
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
database @BACKEND@
suffix "dc=example,dc=com"
#~null~#directory @TESTDIR@/db.1.b
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_2
-#ndb#include @DATADIR@/ndb.conf
database monitor
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
access to dn.subtree="dc=example,dc=com"
by dynacl/aci write
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
add_content_acl on
#access to attrs=objectclass dn.subtree="dc=example,dc=com"
access to attrs=objectclass
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
database monitor
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
database monitor
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
database monitor
#~null~#directory @TESTDIR@/db.2.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_2
-#ndb#include @DATADIR@/ndb.conf
#
# uses the chain overlay as database specific;
rootpw secret
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
database monitor
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
database monitor
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
#indexdb#index entryExpireTimestamp eq
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
add_content_acl on
overlay dds
#~null~#directory @TESTDIR@/db.2.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_3
-#ndb#include @DATADIR@/ndb.conf
# Don't change syncrepl spec yet
syncrepl rid=1
#~null~#directory @TESTDIR@/db.1.b
#indexdb#index objectClass eq
#indexdb#index entryUUID,entryCSN eq
-#ndb#dbname db_2
-#ndb#include @DATADIR@/ndb.conf
overlay syncprov
syncprov-reloadhint true
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
#indexdb#index entryUUID,entryCSN eq
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
access to *
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
overlay deref
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
#indexdb#index entryUUID,entryCSN eq
-#ndb#dbname db_2
-#ndb#include @DATADIR@/ndb.conf
# Don't change syncrepl spec yet
syncrepl rid=1
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
database monitor
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
#indexdb#index entryUUID,entryCSN eq
-#ndb#dbname db_2
-#ndb#include @DATADIR@/ndb.conf
# Don't change syncrepl spec yet
syncrepl rid=1
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
#indexdb#index entryUUID,entryCSN eq
-#ndb#dbname db_4
-#ndb#include @DATADIR@/ndb.conf
# Don't change syncrepl spec yet
syncrepl rid=1
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
# we'll reconfigure the attrset dynamically
overlay dynlist
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
access to attrs=userPassword
by dn.exact="cn=Manager,c=US" write
#~null~#directory @TESTDIR@/db.2.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_2
-#ndb#include @DATADIR@/ndb.conf
access to attrs=userPassword
by self =wx
#indexdb#index uid pres,eq,sub
#indexdb#index cn,sn pres,eq,sub,subany
#indexdb#index entryUUID,entryCSN pres
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
overlay syncprov
#indexdb#index uid pres,eq,sub
#indexdb#index cn,sn pres,eq,sub,subany
#indexdb#index entryUUID,entryCSN pres
-#ndb#dbname db_2
-#ndb#include @DATADIR@/ndb.conf
syncrepl rid=1
provider=@URI2@
#indexdb#index objectclass eq
#indexdb#index uid pres,eq,sub
#indexdb#index cn,sn pres,eq,sub,subany
-#ndb#dbname db_3
-#ndb#include @DATADIR@/ndb.conf
#overlay syncprov
#indexdb#index uid pres,eq,sub
#indexdb#index cn,sn pres,eq,sub,subany
#indexdb#index entryUUID,entryCSN pres
-#ndb#dbname db_4
-#ndb#include @DATADIR@/ndb.conf
syncrepl rid=2
#indexdb#index uid pres,eq,sub
#indexdb#index cn,sn pres,eq,sub,subany
#indexdb#index entryUUID,entryCSN pres
-#ndb#dbname db_5
-#ndb#include @DATADIR@/ndb.conf
overlay syncprov
#indexdb#index objectclass eq
#indexdb#index uid pres,eq,sub
#indexdb#index cn,sn pres,eq,sub,subany
-#ndb#dbname db_6
-#ndb#include @DATADIR@/ndb.conf
#overlay syncprov
#indexdb#index objectclass eq
#indexdb#index uid pres,eq,sub
#indexdb#index cn,sn pres,eq,sub,subany
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
database @BACKEND@
suffix "ou=Groups,dc=example,dc=com"
#indexdb#index objectclass eq
#indexdb#index uid pres,eq,sub
#indexdb#index cn,sn pres,eq,sub,subany
-#ndb#dbname db_2
-#ndb#include @DATADIR@/ndb.conf
database @BACKEND@
suffix "dc=example,dc=com"
#indexdb#index objectclass eq
#indexdb#index uid pres,eq,sub
#indexdb#index cn,sn pres,eq,sub,subany
-#ndb#dbname db_3
-#ndb#include @DATADIR@/ndb.conf
database monitor
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
#mdb#maxsize 33554432
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
overlay homedir
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
#indexdb#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"
attrs=authzTo
#~null~#directory @TESTDIR@/db.2.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_2
-#ndb#include @DATADIR@/ndb.conf
database ldap
suffix "o=Example,c=US"
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
database monitor
#~null~#directory @TESTDIR@/db.3.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_6
-#ndb#include @DATADIR@/ndb.conf
database monitor
#~null~#directory @TESTDIR@/db.2.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_5
-#ndb#include @DATADIR@/ndb.conf
database monitor
# Need quality indices on "uid" to check "unchecked" limits...
#indexdb#index objectClass eq
#indexdb#index uid eq
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
# Need extra limits for pagedResults on backends that support it...
#maindb#limits dn.exact="cn=Unlimited User,ou=Paged Results Users,dc=example,dc=com" size=4 size.pr=unlimited
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
#indexdb#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
access to dn="cn=Barbara Jensen,ou=Information Technology DivisioN,ou=People,dc=example,dc=com"
#~null~#directory @TESTDIR@/db.2.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_2
-#ndb#include @DATADIR@/ndb.conf
access to *
by dn="cn=Manager,o=Local" write
rootpw secret
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
lastbind on
rootpw secret
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
database monitor
#~null~#directory @TESTDIR@/db.2.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid,mail pres,eq,sub
-#ndb#dbname db_2
-#ndb#include @DATADIR@/ndb.conf
database monitor
#~null~#directory @TESTDIR@/db.2.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid,mail pres,eq,sub
-#ndb#dbname db_2
-#ndb#include @DATADIR@/ndb.conf
database monitor
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
#
# normal installations should protect root dse,
#~null~#directory @TESTDIR@/db.2.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_2
-#ndb#include @DATADIR@/ndb.conf
database monitor
rootpw secret
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
database monitor
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
overlay refint
refint_attributes manager secretary member
#null#bind on
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
database @RELAY@
suffix "o=Example,c=US"
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
#indexdb#index entryUUID pres,eq
-#ndb#dbname db_2
-#ndb#include @DATADIR@/ndb.conf
# Need to strip hasSubordinates from internal searches otherwise
# syncrepl will try to delete it, since syncprov is not sending
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
overlay retcode
retcode-parent "ou=RetCodes,dc=example,dc=com"
suffix "o=OpenLDAP Project,l=Internet"
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
-#ndb#dbname db_1_a
-#ndb#include @DATADIR@/ndb.conf
database monitor
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
#indexdb#index entryUUID,entryCSN eq
-#ndb#dbname db_4
-#ndb#include @DATADIR@/ndb.conf
# Don't change syncrepl spec yet
syncrepl rid=1
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
#indexdb#index entryUUID,entryCSN eq
-#ndb#dbname db_5
-#ndb#include @DATADIR@/ndb.conf
# Don't change syncrepl spec yet
syncrepl rid=1
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
#indexdb#index entryUUID,entryCSN eq
-#ndb#dbname db_6
-#ndb#include @DATADIR@/ndb.conf
# Don't change syncrepl spec yet
syncrepl rid=1
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
#indexdb#index entryUUID,entryCSN eq
-#ndb#dbname db_2
-#ndb#include @DATADIR@/ndb.conf
# Don't change syncrepl spec yet
syncrepl rid=1
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
#indexdb#index entryUUID,entryCSN eq
-#ndb#dbname db_3
-#ndb#include @DATADIR@/ndb.conf
# Don't change syncrepl spec yet
syncrepl rid=1
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
#indexdb#index entryUUID,entryCSN eq
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
overlay syncprov
syncprov-sessionlog 100
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
#indexdb#index entryUUID,entryCSN eq
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
overlay syncprov
#syncprov-sessionlog 100
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
#indexdb#index mail eq
-#ndb#dbname db_1_a
-#ndb#include @DATADIR@/ndb.conf
database monitor
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
#indexdb#index mail eq
-#ndb#dbname db_1_a
-#ndb#include @DATADIR@/ndb.conf
database monitor
#~null~#directory @TESTDIR@/db.2.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_2
-#ndb#include @DATADIR@/ndb.conf
overlay translucent
translucent_no_glue
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
access to attrs=userPassword by * auth
access to * by users write
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
access to attrs=userPassword
by anonymous auth
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
overlay valsort
valsort-attr sn ou=users,o=valsort alpha-ascend
#~null~#directory @TESTDIR@/db.1.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
database monitor
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
#mdb#maxsize 33554432
-#ndb#dbname db_1
-#ndb#include @DATADIR@/ndb.conf
database monitor
#~null~#directory @TESTDIR@/db.2.a
#indexdb#index objectClass eq
#indexdb#index cn,sn,uid pres,eq,sub
-#ndb#dbname db_2
-#ndb#include @DATADIR@/ndb.conf
database monitor
INDEXDB=noindexdb MAINDB=nomaindb
case $BACKEND in
mdb) INDEXDB=indexdb MAINDB=maindb ;;
- ndb) INDEXDB=indexdb ;;
wt) INDEXDB=indexdb ;;
esac
/bin/rm -rf ${TESTDIR}/db.*
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}
if test $USERDATA = yes ; then
else
/bin/rm -rf $TESTDIR
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
BCMD=`basename $CMD`
if [ -x "$CMD" ]; then
else
/bin/rm -rf $TESTDIR
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
BCMD=`basename $CMD`
if [ -x "$CMD" ]; then