mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-25 00:59:45 -05:00
Introduction of a new Berkeley DB version 2 (!) specific backend.
BEWARE: the backend will be compiled.
the backend will NOT be invoked, yet.
the backend CANNOT be invoked, yet, because it is NOT yet
integrated into the new initialization/startup environment
of the slapd server.
This commit is contained in:
parent
8107ec91f0
commit
d92b9d3c9e
36 changed files with 7511 additions and 1 deletions
38
servers/slapd/back-bdb2/Makefile.in
Normal file
38
servers/slapd/back-bdb2/Makefile.in
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
XSRCS = version.c
|
||||
SRCS = idl.c add.c search.c cache.c dbcache.c dn2id.c id2entry.c \
|
||||
index.c id2children.c nextid.c abandon.c compare.c group.c \
|
||||
modify.c modrdn.c delete.c init.c config.c bind.c attr.c \
|
||||
filterindex.c unbind.c kerberos.c close.c alias.c startup.c \
|
||||
timing.c porter.c txn.c
|
||||
OBJS = idl.o add.o search.o cache.o dbcache.o dn2id.o id2entry.o \
|
||||
index.o id2children.o nextid.o abandon.o compare.o group.o \
|
||||
modify.o modrdn.o delete.o init.o config.o bind.o attr.o \
|
||||
filterindex.o unbind.o kerberos.o close.o alias.o startup.o \
|
||||
timing.o porter.o txn.o
|
||||
|
||||
LDAP_INCDIR= ../../../include
|
||||
LDAP_LIBDIR= ../../../libraries
|
||||
|
||||
BUILD_OPT = "--enable-bdb2"
|
||||
BUILD_SRV = @BUILD_BDB2@
|
||||
|
||||
XINCPATH = -I.. -I$(srcdir)/..
|
||||
|
||||
PROGRAMS = libback-bdb2.a
|
||||
|
||||
all-local-srv: FORCE
|
||||
$(MAKE) $(MFLAGS) libback-bdb2.a
|
||||
|
||||
libback-bdb2.a: version.o
|
||||
$(AR) ruv $@ $(OBJS) version.o
|
||||
@$(RANLIB) $@
|
||||
@touch ../.backend
|
||||
|
||||
version.c: $(OBJS) $(LDAP_LIBDEPEND)
|
||||
$(RM) $@
|
||||
(u=$${USER-root} v=`$(CAT) $(VERSIONFILE)` d=`$(PWD)` \
|
||||
h=`$(HOSTNAME)` t=`$(DATE)`; \
|
||||
$(SED) -e "s|%WHEN%|$${t}|" \
|
||||
-e "s|%WHOANDWHERE%|$${u}@$${h}:$${d}|" \
|
||||
-e "s|%VERSION%|$${v}|" \
|
||||
< $(srcdir)/Version.c > $@)
|
||||
13
servers/slapd/back-bdb2/Version.c
Normal file
13
servers/slapd/back-bdb2/Version.c
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* Copyright (c) 1995 Regents of the University of Michigan.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that this notice is preserved and that due credit is given
|
||||
* to the University of Michigan at Ann Arbor. The name of the University
|
||||
* may not be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission. This software
|
||||
* is provided ``as is'' without express or implied warranty.
|
||||
*/
|
||||
|
||||
static char Versionstr[] = " bdb2 backend %VERSION% (%WHEN%)\n\t%WHOANDWHERE%\n";
|
||||
55
servers/slapd/back-bdb2/abandon.c
Normal file
55
servers/slapd/back-bdb2/abandon.c
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/* abandon.c - ldbm backend abandon routine */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-bdb2.h"
|
||||
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
bdb2i_back_abandon_internal(
|
||||
Backend *be,
|
||||
Connection *c,
|
||||
Operation *o,
|
||||
int msgid )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
bdb2_back_abandon(
|
||||
Backend *be,
|
||||
Connection *c,
|
||||
Operation *o,
|
||||
int msgid )
|
||||
{
|
||||
struct timeval time1, time2;
|
||||
char *elapsed_time;
|
||||
int ret;
|
||||
|
||||
gettimeofday( &time1, NULL );
|
||||
|
||||
ret = bdb2i_back_abandon_internal( be, c, o, msgid );
|
||||
|
||||
if ( bdb2i_do_timing ) {
|
||||
|
||||
gettimeofday( &time2, NULL);
|
||||
elapsed_time = bdb2i_elapsed( time1, time2 );
|
||||
Debug( LDAP_DEBUG_ANY, "ABND elapsed=%s\n",
|
||||
elapsed_time, 0, 0 );
|
||||
free( elapsed_time );
|
||||
|
||||
}
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
|
||||
289
servers/slapd/back-bdb2/add.c
Normal file
289
servers/slapd/back-bdb2/add.c
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
/* add.c - ldap bdb2 back-end add routine */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-bdb2.h"
|
||||
#include "proto-back-bdb2.h"
|
||||
|
||||
static int
|
||||
bdb2i_back_add_internal(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
Entry *e
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
char *pdn;
|
||||
Entry *p = NULL;
|
||||
int rootlock = 0;
|
||||
int rc = -1;
|
||||
|
||||
Debug(LDAP_DEBUG_ARGS, "==> bdb2i_back_add: %s\n", e->e_dn, 0, 0);
|
||||
|
||||
/* nobody else can add until we lock our parent */
|
||||
ldap_pvt_thread_mutex_lock(&li->li_add_mutex);
|
||||
|
||||
if ( ( bdb2i_dn2id( be, e->e_ndn ) ) != NOID ) {
|
||||
ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
|
||||
entry_free( e );
|
||||
send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, "", "" );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if ( global_schemacheck && oc_schema_check( e ) != 0 ) {
|
||||
ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "entry failed schema check\n",
|
||||
0, 0, 0 );
|
||||
|
||||
entry_free( e );
|
||||
send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, "",
|
||||
"" );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the parent dn and see if the corresponding entry exists.
|
||||
* If the parent does not exist, only allow the "root" user to
|
||||
* add the entry.
|
||||
*/
|
||||
|
||||
if ( (pdn = dn_parent( be, e->e_ndn )) != NULL ) {
|
||||
char *matched = NULL;
|
||||
|
||||
/* get parent with writer lock */
|
||||
if ( (p = bdb2i_dn2entry_w( be, pdn, &matched )) == NULL ) {
|
||||
ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
|
||||
Debug( LDAP_DEBUG_TRACE, "parent does not exist\n", 0,
|
||||
0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
|
||||
matched, "" );
|
||||
|
||||
if ( matched != NULL ) {
|
||||
free( matched );
|
||||
}
|
||||
|
||||
entry_free( e );
|
||||
free( pdn );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* don't need the add lock anymore */
|
||||
ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
|
||||
|
||||
free(pdn);
|
||||
|
||||
if ( matched != NULL ) {
|
||||
free( matched );
|
||||
}
|
||||
|
||||
if ( ! access_allowed( be, conn, op, p,
|
||||
"children", NULL, ACL_WRITE ) )
|
||||
{
|
||||
Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
|
||||
0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
|
||||
"", "" );
|
||||
|
||||
/* free parent and writer lock */
|
||||
bdb2i_cache_return_entry_w( &li->li_cache, p );
|
||||
|
||||
entry_free( e );
|
||||
return -1;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* no parent, must be adding entry to root */
|
||||
if ( ! be_isroot( be, op->o_ndn ) ) {
|
||||
ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
|
||||
Debug( LDAP_DEBUG_TRACE, "no parent & not root\n", 0,
|
||||
0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
|
||||
"", "" );
|
||||
|
||||
entry_free( e );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* no parent, acquire the root write lock
|
||||
* and release the add lock.
|
||||
*/
|
||||
ldap_pvt_thread_mutex_lock(&li->li_root_mutex);
|
||||
rootlock = 1;
|
||||
ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
|
||||
}
|
||||
|
||||
/* acquire required reader/writer lock */
|
||||
if (entry_rdwr_lock(e, 1)) {
|
||||
if( p != NULL) {
|
||||
/* free parent and writer lock */
|
||||
bdb2i_cache_return_entry_w( &li->li_cache, p );
|
||||
}
|
||||
|
||||
if ( rootlock ) {
|
||||
/* release root lock */
|
||||
ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_ANY, "add: could not lock entry\n",
|
||||
0, 0, 0 );
|
||||
|
||||
entry_free(e);
|
||||
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
e->e_id = bdb2i_next_id( be );
|
||||
|
||||
/*
|
||||
* Try to add the entry to the cache, assign it a new dnid
|
||||
* This should only fail if the entry already exists.
|
||||
*/
|
||||
|
||||
if ( bdb2i_cache_add_entry_lock( &li->li_cache, e, ENTRY_STATE_CREATING )
|
||||
!= 0 ) {
|
||||
if( p != NULL) {
|
||||
/* free parent and writer lock */
|
||||
bdb2i_cache_return_entry_w( &li->li_cache, p );
|
||||
}
|
||||
if ( rootlock ) {
|
||||
/* release root lock */
|
||||
ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_ANY, "cache_add_entry_lock failed\n", 0, 0,
|
||||
0 );
|
||||
bdb2i_next_id_return( be, e->e_id );
|
||||
|
||||
entry_rdwr_unlock(e, 1);
|
||||
entry_free( e );
|
||||
|
||||
send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, "", "" );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/*
|
||||
* add it to the id2children index for the parent
|
||||
*/
|
||||
|
||||
if ( bdb2i_id2children_add( be, p, e ) != 0 ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "bdb2i_id2children_add failed\n", 0,
|
||||
0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
|
||||
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the entry to the attribute indexes, then add it to
|
||||
* the id2children index, dn2id index, and the id2entry index.
|
||||
*/
|
||||
|
||||
/* attribute indexes */
|
||||
if ( bdb2i_index_add_entry( be, e ) != 0 ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "bdb2i_index_add_entry failed\n", 0,
|
||||
0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
|
||||
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
/* dn2id index */
|
||||
if ( bdb2i_dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "bdb2i_dn2id_add failed\n", 0,
|
||||
0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
|
||||
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
/* id2entry index */
|
||||
if ( bdb2i_id2entry_add( be, e ) != 0 ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "bdb2i_id2entry_add failed\n", 0,
|
||||
0, 0 );
|
||||
(void) bdb2i_dn2id_delete( be, e->e_ndn );
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
|
||||
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
|
||||
rc = 0;
|
||||
|
||||
return_results:;
|
||||
if (p != NULL) {
|
||||
/* free parent and writer lock */
|
||||
bdb2i_cache_return_entry_w( &li->li_cache, p );
|
||||
|
||||
}
|
||||
|
||||
if ( rootlock ) {
|
||||
/* release root lock */
|
||||
ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
|
||||
}
|
||||
|
||||
bdb2i_cache_set_state( &li->li_cache, e, 0 );
|
||||
|
||||
/* free entry and writer lock */
|
||||
bdb2i_cache_return_entry_w( &li->li_cache, e );
|
||||
|
||||
return( rc );
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
bdb2_back_add(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
Entry *e
|
||||
)
|
||||
{
|
||||
DB_LOCK lock;
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
|
||||
struct timeval time1, time2;
|
||||
char *elapsed_time;
|
||||
int ret;
|
||||
|
||||
gettimeofday( &time1, NULL );
|
||||
|
||||
if ( bdb2i_enter_backend_w( &li->li_db_env, &lock ) != 0 ) {
|
||||
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
|
||||
return( -1 );
|
||||
|
||||
}
|
||||
|
||||
/* check, if a new default attribute index will be created,
|
||||
in which case we have to open the index file BEFORE TP */
|
||||
if ( bdb2i_with_dbenv )
|
||||
bdb2i_check_default_attr_index_add( li, e );
|
||||
|
||||
ret = bdb2i_back_add_internal( be, conn, op, e );
|
||||
|
||||
(void) bdb2i_leave_backend( &li->li_db_env, lock );
|
||||
|
||||
if ( bdb2i_do_timing ) {
|
||||
|
||||
gettimeofday( &time2, NULL);
|
||||
elapsed_time = bdb2i_elapsed( time1, time2 );
|
||||
Debug( LDAP_DEBUG_ANY, "conn=%d op=%d ADD elapsed=%s\n",
|
||||
conn->c_connid, op->o_opid, elapsed_time );
|
||||
free( elapsed_time );
|
||||
|
||||
}
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
|
||||
320
servers/slapd/back-bdb2/alias.c
Normal file
320
servers/slapd/back-bdb2/alias.c
Normal file
|
|
@ -0,0 +1,320 @@
|
|||
/*
|
||||
* Copyright (c) 1998 Will Ballantyne, ITSD, Government of BC
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that this notice is preserved and that due credit is given
|
||||
* to ITSD, Government of BC. The name of ITSD
|
||||
* may not be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission. This software
|
||||
* is provided ``as is'' without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ac/socket.h> /* Get struct sockaddr for slap.h */
|
||||
#include "slap.h"
|
||||
#include "back-bdb2.h"
|
||||
#include "proto-back-bdb2.h"
|
||||
|
||||
/*
|
||||
* given an alias object, dereference it to its end point.
|
||||
* Entry returned has reader lock or is NULL. Starting entry is not released.
|
||||
*/
|
||||
Entry *bdb2i_derefAlias_r ( Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
Entry *e)
|
||||
{
|
||||
/* to free cache entries */
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
Attribute *a;
|
||||
int depth;
|
||||
char **pastAliases;
|
||||
char *matched;
|
||||
Entry *origDN = e;
|
||||
|
||||
if (!e) return NULL; /* be sure we have a starting entry */
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= checking for alias for dn %s\n", e->e_dn, 0, 0 );
|
||||
|
||||
/*
|
||||
* try to deref fully, up to a maximum depth. If the max depth exceeded
|
||||
* then send an error
|
||||
*/
|
||||
for ( depth = 0;
|
||||
( ( a = attr_find( e->e_attrs, "aliasedobjectname" ) ) != NULL) &&
|
||||
( depth < be->be_maxDerefDepth );
|
||||
++depth)
|
||||
{
|
||||
|
||||
/*
|
||||
* make sure there is a defined aliasedobjectname.
|
||||
* can only have one value so just use first value (0) in the attr list.
|
||||
*/
|
||||
if (a->a_vals[0] && a->a_vals[0]->bv_val) {
|
||||
char *newDN, *oldDN;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= %s is an alias for %s\n",
|
||||
e->e_dn, a->a_vals[0]->bv_val, 0 );
|
||||
newDN = ch_strdup (a->a_vals[0]->bv_val);
|
||||
oldDN = ch_strdup (e->e_ndn);
|
||||
|
||||
/*
|
||||
* release past lock if not original
|
||||
*/
|
||||
if ( (depth > 0) && e ) {
|
||||
bdb2i_cache_return_entry_r(&li->li_cache, e);
|
||||
}
|
||||
|
||||
/* make sure new and old DN are not same to avoid loops */
|
||||
dn_normalize_case (newDN);
|
||||
if ( strcmp (newDN, oldDN) == 0 ) {
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= %s alias is same as current %s\n",
|
||||
oldDN, newDN, 0 );
|
||||
send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, "",
|
||||
"Circular alias" );
|
||||
free (newDN);
|
||||
free (oldDN);
|
||||
break;
|
||||
}
|
||||
|
||||
/* make sure new and original are not same to avoid deadlocks */
|
||||
if ( strcmp (newDN, origDN->e_ndn) == 0 ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= %s alias is same as original %s\n",
|
||||
oldDN, origDN->e_ndn, 0 );
|
||||
send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, "",
|
||||
"Circular alias" );
|
||||
free (newDN);
|
||||
free (oldDN);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* ok, so what happens if there is an alias in the DN of a dereferenced
|
||||
* alias object?
|
||||
*/
|
||||
if ( (e = bdb2i_dn2entry_r( be, newDN, &matched )) == NULL ) {
|
||||
|
||||
/* could not deref return error */
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= %s is a dangling alias to %s\n",
|
||||
oldDN, newDN, 0 );
|
||||
send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, "",
|
||||
"Dangling Alias" );
|
||||
|
||||
if(matched != NULL) free(matched);
|
||||
free (newDN);
|
||||
free (oldDN);
|
||||
break;
|
||||
}
|
||||
|
||||
free (newDN);
|
||||
free (oldDN);
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* there was an aliasedobjectname defined but no data.
|
||||
* this can't happen, right?
|
||||
*/
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= %s has no data in aliasedobjectname attribute\n",
|
||||
(e && e->e_dn) ? e->e_dn : "(null)", 0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, "",
|
||||
"Alias missing aliasedobjectname" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* warn if we pulled out due to exceeding the maximum deref depth
|
||||
*/
|
||||
if ( depth >= be->be_maxDerefDepth ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= deref(\"%s\") exceeded maximum deref depth (%d) at \"%s\"\n",
|
||||
origDN->e_dn ? origDN->e_dn : "(null)",
|
||||
be->be_maxDerefDepth,
|
||||
(e && e->e_ndn) ? e->e_ndn : "(null)");
|
||||
send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, "",
|
||||
"Maximum alias dereference depth exceeded" );
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
/*
|
||||
* given a DN fully deref it and return the real DN or original DN if it fails
|
||||
* This involves finding the last matched part then reconstructing forward
|
||||
* e.g.
|
||||
* ou=MyOU,o=MyAliasedOrg,c=MyCountry where o=MyAliasedOrg is an alias for o=MyOrg
|
||||
* loop starts with newDN = ou=MyOU,o=MyAliasedOrg,c=MyCountry
|
||||
* dn2entry_r on newDN gives null entry and o=MyAliasedOrg,c=MyCountry matched
|
||||
* dn2entry_r on matched gives o=MyAliasedOrg,c=MyCountry entry
|
||||
* remainder is ou=MyOU
|
||||
* dereferencing o=MyAliasedOrg,c=MyCountry yields entry o=MyOrg,c=MyCountry
|
||||
* release lock on o=MyAliasedOrg,c=MyCountry entry
|
||||
* reconstructed dn is ou=MyOU,o=MyOrg,c=MyCountry
|
||||
* release lock on o=MyOrg,c=MyCountry entry
|
||||
*/
|
||||
char *bdb2i_derefDN ( Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
char *dn
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
char *matched = 0;
|
||||
char *newDN = NULL;
|
||||
int depth, i;
|
||||
Entry *eMatched;
|
||||
Entry *eDeref;
|
||||
Entry *eNew;
|
||||
|
||||
if (!dn) return NULL;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= dereferencing dn: \"%s\"\n",
|
||||
dn, 0, 0 );
|
||||
|
||||
newDN = ch_strdup ( dn );
|
||||
|
||||
/* while we don't have a matched dn, deref the DN */
|
||||
for ( depth = 0;
|
||||
( (eMatched = bdb2i_dn2entry_r( be, newDN, &matched )) == NULL) &&
|
||||
(depth < be->be_maxDerefDepth);
|
||||
++depth ) {
|
||||
|
||||
if ((matched != NULL) && *matched) {
|
||||
char *submatch;
|
||||
|
||||
/*
|
||||
* make sure there actually is an entry for the matched part
|
||||
*/
|
||||
if ( (eMatched = bdb2i_dn2entry_r( be, matched, &submatch )) != NULL) {
|
||||
char *remainder; /* part before the aliased part */
|
||||
int rlen = strlen(newDN) - strlen(matched);
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= matched %s\n", matched, 0, 0 );
|
||||
|
||||
remainder = ch_malloc (rlen + 1);
|
||||
strncpy ( remainder, newDN, rlen );
|
||||
remainder[rlen] = '\0';
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= remainder %s\n", remainder, 0, 0 );
|
||||
|
||||
if ((eNew = bdb2i_derefAlias_r( be, conn, op, eMatched )) == NULL) {
|
||||
free (matched);
|
||||
matched = NULL;
|
||||
free (newDN);
|
||||
newDN = NULL;
|
||||
free (remainder);
|
||||
remainder = NULL;
|
||||
|
||||
bdb2i_cache_return_entry_r(&li->li_cache, eMatched);
|
||||
eMatched = NULL;
|
||||
break; /* no associated entry, dont deref */
|
||||
}
|
||||
else {
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= l&g we have %s vs %s \n", matched, eNew->e_dn, 0 );
|
||||
|
||||
i = strcasecmp (matched, eNew->e_dn);
|
||||
/* free reader lock */
|
||||
bdb2i_cache_return_entry_r(&li->li_cache, eNew);
|
||||
|
||||
free (matched);
|
||||
matched = NULL;
|
||||
|
||||
if (! i) {
|
||||
/* newDN same as old so not an alias, no need to go further */
|
||||
free (newDN);
|
||||
newDN = NULL;
|
||||
free (remainder);
|
||||
|
||||
bdb2i_cache_return_entry_r(&li->li_cache, eMatched);
|
||||
eMatched = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* we have dereferenced the aliased part so put
|
||||
* the new dn together
|
||||
*/
|
||||
free (newDN);
|
||||
newDN = ch_malloc (strlen(eMatched->e_dn) + rlen + 1);
|
||||
strcpy (newDN, remainder);
|
||||
strcat (newDN, eMatched->e_dn);
|
||||
Debug( LDAP_DEBUG_TRACE, "<= expanded to %s\n", newDN, 0, 0 );
|
||||
|
||||
free (remainder);
|
||||
}
|
||||
/* free reader lock */
|
||||
bdb2i_cache_return_entry_r(&li->li_cache, eMatched);
|
||||
}
|
||||
else {
|
||||
if(submatch != NULL) free(submatch);
|
||||
break; /* there was no entry for the matched part */
|
||||
}
|
||||
}
|
||||
else {
|
||||
break; /* there was no matched part */
|
||||
}
|
||||
}
|
||||
|
||||
/* release lock if a match terminated the loop, there should be no
|
||||
* outstanding locks at this point
|
||||
*/
|
||||
if(eMatched != NULL) {
|
||||
/* free reader lock */
|
||||
bdb2i_cache_return_entry_r(&li->li_cache, eMatched);
|
||||
}
|
||||
|
||||
/*
|
||||
* the final part of the DN might be an alias so try to dereference it.
|
||||
* e.g. if we had started with dn = o=MyAliasedOrg,c=MyCountry the dn would match
|
||||
* and the above loop complete but we would still be left with an aliased DN.
|
||||
*/
|
||||
if ( (eNew = bdb2i_dn2entry_r( be, newDN, &matched )) != NULL) {
|
||||
if ((eDeref = bdb2i_derefAlias_r( be, conn, op, eNew )) != NULL) {
|
||||
free (newDN);
|
||||
newDN = ch_strdup (eDeref->e_dn);
|
||||
/* free reader lock */
|
||||
bdb2i_cache_return_entry_r(&li->li_cache, eDeref);
|
||||
}
|
||||
/* free reader lock */
|
||||
bdb2i_cache_return_entry_r(&li->li_cache, eNew);
|
||||
}
|
||||
if (matched != NULL) free(matched);
|
||||
|
||||
/*
|
||||
* warn if we exceeded the max depth as the resulting DN may not be dereferenced
|
||||
*/
|
||||
if (depth >= be->be_maxDerefDepth) {
|
||||
if (newDN) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= max deref depth exceeded in derefDN for \"%s\", result \"%s\"\n",
|
||||
dn, newDN, 0 );
|
||||
free (newDN);
|
||||
newDN = NULL;
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= max deref depth exceeded in derefDN for \"%s\", result NULL\n",
|
||||
dn, 0, 0 );
|
||||
}
|
||||
send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, "",
|
||||
"Maximum alias dereference depth exceeded for base" );
|
||||
}
|
||||
|
||||
if (newDN == NULL) {
|
||||
newDN = ch_strdup ( dn );
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= returning deref DN of \"%s\"\n", newDN, 0, 0 );
|
||||
|
||||
return newDN;
|
||||
}
|
||||
171
servers/slapd/back-bdb2/attr.c
Normal file
171
servers/slapd/back-bdb2/attr.c
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
/* attr.c - backend routines for dealing with attributes */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-bdb2.h"
|
||||
|
||||
static int
|
||||
ainfo_type_cmp(
|
||||
char *type,
|
||||
struct attrinfo *a
|
||||
)
|
||||
{
|
||||
return( strcasecmp( type, a->ai_type ) );
|
||||
}
|
||||
|
||||
static int
|
||||
ainfo_cmp(
|
||||
struct attrinfo *a,
|
||||
struct attrinfo *b
|
||||
)
|
||||
{
|
||||
return( strcasecmp( a->ai_type, b->ai_type ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when a duplicate "index" line is encountered.
|
||||
*
|
||||
* returns 1 => original from init code, indexmask updated
|
||||
* 2 => original not from init code, warn the user
|
||||
*/
|
||||
|
||||
static int
|
||||
ainfo_dup(
|
||||
struct attrinfo *a,
|
||||
struct attrinfo *b
|
||||
)
|
||||
{
|
||||
/*
|
||||
* if the duplicate definition is because we initialized the attr,
|
||||
* just add what came from the config file. otherwise, complain.
|
||||
*/
|
||||
if ( a->ai_indexmask & INDEX_FROMINIT ) {
|
||||
a->ai_indexmask |= b->ai_indexmask;
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
return( 2 );
|
||||
}
|
||||
|
||||
void
|
||||
bdb2i_attr_masks(
|
||||
struct ldbminfo *li,
|
||||
char *type,
|
||||
int *indexmask,
|
||||
int *syntaxmask
|
||||
)
|
||||
{
|
||||
struct attrinfo *a;
|
||||
|
||||
*indexmask = 0;
|
||||
*syntaxmask = 0;
|
||||
if ( (a = (struct attrinfo *) avl_find( li->li_attrs, type,
|
||||
ainfo_type_cmp )) == NULL ) {
|
||||
if ( (a = (struct attrinfo *) avl_find( li->li_attrs, "default",
|
||||
ainfo_type_cmp )) == NULL ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
*indexmask = a->ai_indexmask;
|
||||
if ( strcasecmp( a->ai_type, "default" ) == 0 ) {
|
||||
*syntaxmask = attr_syntax( type );
|
||||
} else {
|
||||
*syntaxmask = a->ai_syntaxmask;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* BDB2 changed */
|
||||
void
|
||||
bdb2i_attr_index_config(
|
||||
struct ldbminfo *li,
|
||||
char *fname,
|
||||
int lineno,
|
||||
int argc,
|
||||
char **argv,
|
||||
int init
|
||||
)
|
||||
{
|
||||
int i, j;
|
||||
char **attrs, **indexes;
|
||||
struct attrinfo *a;
|
||||
|
||||
attrs = str2charray( argv[0], "," );
|
||||
if ( argc > 1 ) {
|
||||
indexes = str2charray( argv[1], "," );
|
||||
}
|
||||
for ( i = 0; attrs[i] != NULL; i++ ) {
|
||||
a = (struct attrinfo *) ch_malloc( sizeof(struct attrinfo) );
|
||||
a->ai_type = ch_strdup( attrs[i] );
|
||||
a->ai_syntaxmask = attr_syntax( a->ai_type );
|
||||
if ( argc == 1 ) {
|
||||
a->ai_indexmask = (INDEX_PRESENCE | INDEX_EQUALITY |
|
||||
INDEX_APPROX | INDEX_SUB);
|
||||
} else {
|
||||
a->ai_indexmask = 0;
|
||||
for ( j = 0; indexes[j] != NULL; j++ ) {
|
||||
if ( strncasecmp( indexes[j], "pres", 4 )
|
||||
== 0 ) {
|
||||
a->ai_indexmask |= INDEX_PRESENCE;
|
||||
} else if ( strncasecmp( indexes[j], "eq", 2 )
|
||||
== 0 ) {
|
||||
a->ai_indexmask |= INDEX_EQUALITY;
|
||||
} else if ( strncasecmp( indexes[j], "approx",
|
||||
6 ) == 0 ) {
|
||||
a->ai_indexmask |= INDEX_APPROX;
|
||||
} else if ( strncasecmp( indexes[j], "sub", 3 )
|
||||
== 0 ) {
|
||||
a->ai_indexmask |= INDEX_SUB;
|
||||
} else if ( strncasecmp( indexes[j], "none", 4 )
|
||||
== 0 ) {
|
||||
if ( a->ai_indexmask != 0 ) {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: index type \"none\" cannot be combined with other types\n",
|
||||
fname, lineno );
|
||||
}
|
||||
a->ai_indexmask = 0;
|
||||
} else {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: unknown index type \"%s\" (ignored)\n",
|
||||
fname, lineno, indexes[j] );
|
||||
fprintf( stderr,
|
||||
"valid index types are \"pres\", \"eq\", \"approx\", or \"sub\"\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( init ) {
|
||||
a->ai_indexmask |= INDEX_FROMINIT;
|
||||
} else {
|
||||
if ( a->ai_indexmask )
|
||||
bdb2i_txn_attr_config( li, a->ai_type, 0 );
|
||||
}
|
||||
|
||||
switch (avl_insert( &li->li_attrs, (caddr_t) a, ainfo_cmp, ainfo_dup )) {
|
||||
case 1: /* duplicate - updating init version */
|
||||
free( a->ai_type );
|
||||
free( (char *) a );
|
||||
break;
|
||||
|
||||
case 2: /* user duplicate - ignore and warn */
|
||||
fprintf( stderr,
|
||||
"%s: line %d: duplicate index definition for attr \"%s\" (ignored)\n",
|
||||
fname, lineno, a->ai_type );
|
||||
free( a->ai_type );
|
||||
free( (char *) a );
|
||||
break;
|
||||
|
||||
default:; /* inserted ok */
|
||||
/* FALL */
|
||||
}
|
||||
}
|
||||
charray_free( attrs );
|
||||
if ( argc > 1 )
|
||||
charray_free( indexes );
|
||||
}
|
||||
185
servers/slapd/back-bdb2/back-bdb2.h
Normal file
185
servers/slapd/back-bdb2/back-bdb2.h
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
/* back-bdb2.h - ldap bdb2 back-end header file */
|
||||
|
||||
#ifndef _BACK_BDB2_H_
|
||||
#define _BACK_BDB2_H_
|
||||
|
||||
#include "ldbm.h"
|
||||
#include "db.h"
|
||||
|
||||
LDAP_BEGIN_DECL
|
||||
|
||||
#define DEFAULT_CACHE_SIZE 1000
|
||||
|
||||
/* since DEFAULT_DB_PAGE_SIZE is 1K, we have 128K,
|
||||
which is suggested by Sleepycat */
|
||||
#define DEFAULT_DBCACHE_SIZE (128 * DEFAULT_DB_PAGE_SIZE)
|
||||
|
||||
#define DEFAULT_DB_DIRECTORY "/usr/tmp"
|
||||
#define DEFAULT_MODE 0600
|
||||
|
||||
#define SUBLEN 3
|
||||
|
||||
/*
|
||||
* there is a single index for each attribute. these prefixes insure
|
||||
* that there is no collision among keys.
|
||||
*/
|
||||
#define EQ_PREFIX '=' /* prefix for equality keys */
|
||||
#define APPROX_PREFIX '~' /* prefix for approx keys */
|
||||
#define SUB_PREFIX '*' /* prefix for substring keys */
|
||||
#define CONT_PREFIX '\\' /* prefix for continuation keys */
|
||||
|
||||
#define UNKNOWN_PREFIX '?' /* prefix for unknown keys */
|
||||
|
||||
#define DEFAULT_BLOCKSIZE 8192
|
||||
|
||||
/*
|
||||
* This structure represents an id block on disk and an id list
|
||||
* in core.
|
||||
*
|
||||
* The fields have the following meanings:
|
||||
*
|
||||
* b_nmax maximum number of ids in this block. if this is == ALLIDSBLOCK,
|
||||
* then this block represents all ids.
|
||||
* b_nids current number of ids in use in this block. if this
|
||||
* is == INDBLOCK, then this block is an indirect block
|
||||
* containing a list of other blocks containing actual ids.
|
||||
* the list is terminated by an id of NOID.
|
||||
* b_ids a list of the actual ids themselves
|
||||
*/
|
||||
|
||||
typedef ID ID_BLOCK;
|
||||
|
||||
#define ID_BLOCK_NMAX_OFFSET 0
|
||||
#define ID_BLOCK_NIDS_OFFSET 1
|
||||
#define ID_BLOCK_IDS_OFFSET 2
|
||||
|
||||
/* all ID_BLOCK macros operate on a pointer to a ID_BLOCK */
|
||||
|
||||
#define ID_BLOCK_NMAX(b) ((b)[ID_BLOCK_NMAX_OFFSET])
|
||||
#define ID_BLOCK_NIDS(b) ((b)[ID_BLOCK_NIDS_OFFSET])
|
||||
#define ID_BLOCK_ID(b, n) ((b)[ID_BLOCK_IDS_OFFSET+(n)])
|
||||
|
||||
#define ID_BLOCK_NOID(b, n) (ID_BLOCK_ID((b),(n)) == NOID)
|
||||
|
||||
#define ID_BLOCK_ALLIDS_VALUE 0
|
||||
#define ID_BLOCK_ALLIDS(b) (ID_BLOCK_NMAX(b) == ID_BLOCK_ALLIDS_VALUE)
|
||||
|
||||
#define ID_BLOCK_INDIRECT_VALUE 0
|
||||
#define ID_BLOCK_INDIRECT(b) (ID_BLOCK_NIDS(b) == ID_BLOCK_INDIRECT_VALUE)
|
||||
|
||||
/* for the in-core cache of entries */
|
||||
struct cache {
|
||||
int c_maxsize;
|
||||
int c_cursize;
|
||||
Avlnode *c_dntree;
|
||||
Avlnode *c_idtree;
|
||||
Entry *c_lruhead; /* lru - add accessed entries here */
|
||||
Entry *c_lrutail; /* lru - rem lru entries from here */
|
||||
ldap_pvt_thread_mutex_t c_mutex;
|
||||
};
|
||||
|
||||
/* for the cache of open index files (re-used for txn) */
|
||||
struct dbcache {
|
||||
int dbc_refcnt;
|
||||
int dbc_maxids;
|
||||
int dbc_maxindirect;
|
||||
time_t dbc_lastref;
|
||||
long dbc_blksize;
|
||||
char *dbc_name;
|
||||
LDBM dbc_db;
|
||||
|
||||
struct dbcache *next;
|
||||
};
|
||||
|
||||
typedef struct dbcache BDB2_TXN_FILES;
|
||||
|
||||
|
||||
/* for the cache of attribute information (which are indexed, etc.) */
|
||||
struct attrinfo {
|
||||
char *ai_type; /* type name (cn, sn, ...) */
|
||||
int ai_indexmask; /* how the attr is indexed */
|
||||
#define INDEX_PRESENCE 0x01
|
||||
#define INDEX_EQUALITY 0x02
|
||||
#define INDEX_APPROX 0x04
|
||||
#define INDEX_SUB 0x08
|
||||
#define INDEX_UNKNOWN 0x10
|
||||
#define INDEX_FROMINIT 0x20
|
||||
int ai_syntaxmask; /* what kind of syntax */
|
||||
/* ...from slap.h...
|
||||
#define SYNTAX_CIS 0x01
|
||||
#define SYNTAX_CES 0x02
|
||||
#define SYNTAX_BIN 0x04
|
||||
... etc. ...
|
||||
*/
|
||||
};
|
||||
|
||||
#define MAXDBCACHE 10
|
||||
|
||||
/* this could be made an option */
|
||||
#ifndef SLAPD_NEXTID_CHUNK
|
||||
#define SLAPD_NEXTID_CHUNK 32
|
||||
#endif
|
||||
|
||||
|
||||
/* TP stuff */
|
||||
|
||||
typedef struct _bdb2_txn_head {
|
||||
|
||||
/* counter and timer to control checkpoints */
|
||||
size_t txn_cnt;
|
||||
time_t txn_chkp;
|
||||
|
||||
/* a list of all DB files in use */
|
||||
BDB2_TXN_FILES *dbFiles;
|
||||
|
||||
/* for performance reasons we have pointers to fixed descriptors */
|
||||
BDB2_TXN_FILES *dbFileHandle[4];
|
||||
#define BDB2_DB_DN_FILE 0
|
||||
#define BDB2_DB_DN2ID_FILE 1
|
||||
#define BDB2_DB_ID2ENTRY_FILE 2
|
||||
#define BDB2_DB_ID2CHILDREN_FILE 3
|
||||
#define BDB2_DB_OC_IDX_FILE 4
|
||||
|
||||
/* is the default attribute index set to non-none */
|
||||
int withDefIDX;
|
||||
#define BDB2_WITH_DEF_IDX 1
|
||||
|
||||
} BDB2_TXN_HEAD;
|
||||
|
||||
|
||||
/* end of TP stuff */
|
||||
|
||||
struct ldbminfo {
|
||||
ID li_nextid;
|
||||
#if SLAPD_NEXTID_CHUNK > 1
|
||||
ID li_nextid_wrote;
|
||||
#endif
|
||||
char *li_nextid_file;
|
||||
ldap_pvt_thread_mutex_t li_root_mutex;
|
||||
ldap_pvt_thread_mutex_t li_add_mutex;
|
||||
ldap_pvt_thread_mutex_t li_nextid_mutex;
|
||||
int li_mode;
|
||||
char *li_directory;
|
||||
struct cache li_cache;
|
||||
Avlnode *li_attrs;
|
||||
int li_dbcachesize;
|
||||
int li_dbcachewsync;
|
||||
struct dbcache li_dbcache[MAXDBCACHE];
|
||||
ldap_pvt_thread_mutex_t li_dbcache_mutex;
|
||||
ldap_pvt_thread_cond_t li_dbcache_cv;
|
||||
|
||||
/* Berkeley DB2 Environment */
|
||||
DB_ENV li_db_env;
|
||||
char *li_dbhome;
|
||||
BDB2_TXN_HEAD li_txn_head;
|
||||
|
||||
};
|
||||
|
||||
|
||||
extern int bdb2i_with_dbenv;
|
||||
|
||||
#include "proto-back-bdb2.h"
|
||||
|
||||
LDAP_END_DECL
|
||||
|
||||
#endif /* _back_bdb2_h_ */
|
||||
262
servers/slapd/back-bdb2/bind.c
Normal file
262
servers/slapd/back-bdb2/bind.c
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
/* bind.c - bdb2 backend bind and unbind routines */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/krb.h>
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
#include <ac/unistd.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-bdb2.h"
|
||||
#include "proto-back-bdb2.h"
|
||||
|
||||
#include <lutil.h>
|
||||
|
||||
#ifdef HAVE_KERBEROS
|
||||
extern int bdb2i_krbv4_ldap_auth();
|
||||
#endif
|
||||
|
||||
static int
|
||||
crypted_value_find(
|
||||
struct berval **vals,
|
||||
struct berval *v,
|
||||
int syntax,
|
||||
int normalize,
|
||||
struct berval *cred
|
||||
)
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; vals[i] != NULL; i++ ) {
|
||||
if ( syntax != SYNTAX_BIN ) {
|
||||
int result;
|
||||
|
||||
#ifdef SLAPD_CRYPT
|
||||
ldap_pvt_thread_mutex_lock( &crypt_mutex );
|
||||
#endif
|
||||
|
||||
result = lutil_passwd(
|
||||
(char*) cred->bv_val,
|
||||
(char*) vals[i]->bv_val);
|
||||
|
||||
#ifdef SLAPD_CRYPT
|
||||
ldap_pvt_thread_mutex_unlock( &crypt_mutex );
|
||||
#endif
|
||||
|
||||
return result;
|
||||
|
||||
} else {
|
||||
if ( value_cmp( vals[i], v, syntax, normalize ) == 0 ) {
|
||||
return( 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
static int
|
||||
bdb2i_back_bind_internal(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
char *dn,
|
||||
int method,
|
||||
struct berval *cred,
|
||||
char** edn
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
Entry *e;
|
||||
Attribute *a;
|
||||
int rc;
|
||||
char *matched;
|
||||
#ifdef HAVE_KERBEROS
|
||||
char krbname[MAX_K_NAME_SZ + 1];
|
||||
AUTH_DAT ad;
|
||||
#endif
|
||||
|
||||
Debug(LDAP_DEBUG_ARGS, "==> bdb2_back_bind: dn: %s\n", dn, 0, 0);
|
||||
|
||||
*edn = NULL;
|
||||
|
||||
/* get entry with reader lock */
|
||||
if ( (e = bdb2i_dn2entry_r( be, dn, &matched )) == NULL ) {
|
||||
/* allow noauth binds */
|
||||
if ( method == LDAP_AUTH_SIMPLE && cred->bv_len == 0 ) {
|
||||
/*
|
||||
* bind successful, but return 1 so we don't
|
||||
* authorize based on noauth credentials
|
||||
*/
|
||||
send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
|
||||
rc = 1;
|
||||
} else if ( be_isroot_pw( be, dn, cred ) ) {
|
||||
/* front end will send result */
|
||||
*edn = ch_strdup( be_root_dn( be ) );
|
||||
rc = 0;
|
||||
} else {
|
||||
send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, NULL );
|
||||
rc = 1;
|
||||
}
|
||||
if ( matched != NULL ) {
|
||||
free( matched );
|
||||
}
|
||||
return( rc );
|
||||
}
|
||||
|
||||
*edn = ch_strdup( e->e_dn );
|
||||
|
||||
/* check for deleted */
|
||||
|
||||
switch ( method ) {
|
||||
case LDAP_AUTH_SIMPLE:
|
||||
if ( cred->bv_len == 0 ) {
|
||||
send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
|
||||
|
||||
/* stop front end from sending result */
|
||||
rc = 1;
|
||||
goto return_results;
|
||||
} else if ( be_isroot_pw( be, dn, cred ) ) {
|
||||
/* front end will send result */
|
||||
*edn = ch_strdup( be_root_dn( be ) );
|
||||
rc = 0;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if ( (a = attr_find( e->e_attrs, "userpassword" )) == NULL ) {
|
||||
if ( be_isroot_pw( be, dn, cred ) ) {
|
||||
/* front end will send result */
|
||||
*edn = ch_strdup( be_root_dn( be ) );
|
||||
rc = 0;
|
||||
goto return_results;
|
||||
}
|
||||
send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
|
||||
NULL, NULL );
|
||||
rc = 1;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if ( crypted_value_find( a->a_vals, cred, a->a_syntax, 0, cred ) != 0 )
|
||||
{
|
||||
if ( be_isroot_pw( be, dn, cred ) ) {
|
||||
/* front end will send result */
|
||||
*edn = ch_strdup( be_root_dn( be ) );
|
||||
rc = 0;
|
||||
goto return_results;
|
||||
}
|
||||
send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
|
||||
NULL, NULL );
|
||||
rc = 1;
|
||||
goto return_results;
|
||||
}
|
||||
rc = 0;
|
||||
break;
|
||||
|
||||
#ifdef HAVE_KERBEROS
|
||||
case LDAP_AUTH_KRBV41:
|
||||
if ( bdb2i_krbv4_ldap_auth( be, cred, &ad ) != LDAP_SUCCESS ) {
|
||||
send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
|
||||
NULL, NULL );
|
||||
rc = 0;
|
||||
goto return_results;
|
||||
}
|
||||
sprintf( krbname, "%s%s%s@%s", ad.pname, *ad.pinst ? "."
|
||||
: "", ad.pinst, ad.prealm );
|
||||
if ( (a = attr_find( e->e_attrs, "krbname" )) == NULL ) {
|
||||
/*
|
||||
* no krbName values present: check against DN
|
||||
*/
|
||||
if ( strcasecmp( dn, krbname ) == 0 ) {
|
||||
rc = 0; /* XXX wild ass guess */
|
||||
break;
|
||||
}
|
||||
send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
|
||||
NULL, NULL );
|
||||
rc = 1;
|
||||
goto return_results;
|
||||
} else { /* look for krbName match */
|
||||
struct berval krbval;
|
||||
|
||||
krbval.bv_val = krbname;
|
||||
krbval.bv_len = strlen( krbname );
|
||||
|
||||
if ( value_find( a->a_vals, &krbval, a->a_syntax, 3 ) != 0 ) {
|
||||
send_ldap_result( conn, op,
|
||||
LDAP_INVALID_CREDENTIALS, NULL, NULL );
|
||||
rc = 1;
|
||||
goto return_results;
|
||||
}
|
||||
}
|
||||
rc = 0;
|
||||
break;
|
||||
|
||||
case LDAP_AUTH_KRBV42:
|
||||
send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
|
||||
/* stop front end from sending result */
|
||||
rc = 1;
|
||||
goto return_results;
|
||||
#endif
|
||||
|
||||
default:
|
||||
send_ldap_result( conn, op, LDAP_STRONG_AUTH_NOT_SUPPORTED,
|
||||
NULL, "auth method not supported" );
|
||||
rc = 1;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
return_results:;
|
||||
/* free entry and reader lock */
|
||||
bdb2i_cache_return_entry_r( &li->li_cache, e );
|
||||
|
||||
/* front end with send result on success (rc==0) */
|
||||
return( rc );
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
bdb2_back_bind(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
char *dn,
|
||||
int method,
|
||||
struct berval *cred,
|
||||
char** edn
|
||||
)
|
||||
{
|
||||
DB_LOCK lock;
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
|
||||
struct timeval time1, time2;
|
||||
char *elapsed_time;
|
||||
int ret;
|
||||
|
||||
gettimeofday( &time1, NULL );
|
||||
|
||||
if ( bdb2i_enter_backend_r( &li->li_db_env, &lock ) != 0 ) {
|
||||
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
|
||||
return( 1 );
|
||||
|
||||
}
|
||||
|
||||
ret = bdb2i_back_bind_internal( be, conn, op, dn, method, cred, edn );
|
||||
|
||||
(void) bdb2i_leave_backend( &li->li_db_env, lock );
|
||||
|
||||
if ( bdb2i_do_timing ) {
|
||||
|
||||
gettimeofday( &time2, NULL);
|
||||
elapsed_time = bdb2i_elapsed( time1, time2 );
|
||||
Debug( LDAP_DEBUG_ANY, "conn=%d op=%d BIND elapsed=%s\n",
|
||||
conn->c_connid, op->o_opid, elapsed_time );
|
||||
free( elapsed_time );
|
||||
|
||||
}
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
|
||||
462
servers/slapd/back-bdb2/cache.c
Normal file
462
servers/slapd/back-bdb2/cache.c
Normal file
|
|
@ -0,0 +1,462 @@
|
|||
/* cache.c - routines to maintain an in-core cache of entries */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/errno.h>
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
|
||||
#include "back-bdb2.h"
|
||||
|
||||
static int cache_delete_entry_internal(struct cache *cache, Entry *e);
|
||||
#ifdef LDAP_DEBUG
|
||||
static void lru_print(struct cache *cache);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* the cache has three entry points (ways to find things):
|
||||
*
|
||||
* by entry e.g., if you already have an entry from the cache
|
||||
* and want to delete it. (really by entry ptr)
|
||||
* by dn e.g., when looking for the base object of a search
|
||||
* by id e.g., for search candidates
|
||||
*
|
||||
* these correspond to three different avl trees that are maintained.
|
||||
*/
|
||||
|
||||
static int
|
||||
cache_entry_cmp( Entry *e1, Entry *e2 )
|
||||
{
|
||||
return( e1 < e2 ? -1 : (e1 > e2 ? 1 : 0) );
|
||||
}
|
||||
|
||||
static int
|
||||
cache_entrydn_cmp( Entry *e1, Entry *e2 )
|
||||
{
|
||||
/* compare their normalized UPPERCASED dn's */
|
||||
return( strcmp( e1->e_ndn, e2->e_ndn ) );
|
||||
}
|
||||
|
||||
static int
|
||||
cache_entryid_cmp( Entry *e1, Entry *e2 )
|
||||
{
|
||||
return( e1->e_id < e2->e_id ? -1 : (e1->e_id > e2->e_id ? 1 : 0) );
|
||||
}
|
||||
|
||||
void
|
||||
bdb2i_cache_set_state( struct cache *cache, Entry *e, int state )
|
||||
{
|
||||
/* set cache mutex */
|
||||
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
|
||||
|
||||
e->e_state = state;
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
}
|
||||
|
||||
#ifdef not_used
|
||||
static void
|
||||
cache_return_entry( struct cache *cache, Entry *e )
|
||||
{
|
||||
/* set cache mutex */
|
||||
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
|
||||
|
||||
if ( --e->e_refcnt == 0 && e->e_state == ENTRY_STATE_DELETED ) {
|
||||
entry_free( e );
|
||||
}
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
cache_return_entry_rw( struct cache *cache, Entry *e, int rw )
|
||||
{
|
||||
Debug( LDAP_DEBUG_TRACE, "====> cache_return_entry_%s\n",
|
||||
rw ? "w" : "r", 0, 0);
|
||||
|
||||
/* set cache mutex */
|
||||
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
|
||||
|
||||
entry_rdwr_unlock(e, rw);;
|
||||
|
||||
if ( --e->e_refcnt == 0 && e->e_state == ENTRY_STATE_DELETED ) {
|
||||
entry_free( e );
|
||||
}
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
}
|
||||
|
||||
void
|
||||
bdb2i_cache_return_entry_r( struct cache *cache, Entry *e )
|
||||
{
|
||||
cache_return_entry_rw(cache, e, 0);
|
||||
}
|
||||
|
||||
void
|
||||
bdb2i_cache_return_entry_w( struct cache *cache, Entry *e )
|
||||
{
|
||||
cache_return_entry_rw(cache, e, 1);
|
||||
}
|
||||
|
||||
|
||||
#define LRU_DELETE( cache, e ) { \
|
||||
if ( e->e_lruprev != NULL ) { \
|
||||
e->e_lruprev->e_lrunext = e->e_lrunext; \
|
||||
} else { \
|
||||
cache->c_lruhead = e->e_lrunext; \
|
||||
} \
|
||||
if ( e->e_lrunext != NULL ) { \
|
||||
e->e_lrunext->e_lruprev = e->e_lruprev; \
|
||||
} else { \
|
||||
cache->c_lrutail = e->e_lruprev; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define LRU_ADD( cache, e ) { \
|
||||
e->e_lrunext = cache->c_lruhead; \
|
||||
if ( e->e_lrunext != NULL ) { \
|
||||
e->e_lrunext->e_lruprev = e; \
|
||||
} \
|
||||
cache->c_lruhead = e; \
|
||||
e->e_lruprev = NULL; \
|
||||
if ( cache->c_lrutail == NULL ) { \
|
||||
cache->c_lrutail = e; \
|
||||
} \
|
||||
}
|
||||
|
||||
/*
|
||||
* cache_create_entry_lock - create an entry in the cache, and lock it.
|
||||
* returns: 0 entry has been created and locked
|
||||
* 1 entry already existed
|
||||
* -1 something bad happened
|
||||
*/
|
||||
int
|
||||
bdb2i_cache_add_entry_lock(
|
||||
struct cache *cache,
|
||||
Entry *e,
|
||||
int state
|
||||
)
|
||||
{
|
||||
int i, rc;
|
||||
Entry *ee;
|
||||
|
||||
/* set cache mutex */
|
||||
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
|
||||
|
||||
if ( avl_insert( &cache->c_dntree, (caddr_t) e,
|
||||
cache_entrydn_cmp, avl_dup_error ) != 0 )
|
||||
{
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"====> cache_add_entry lock: entry %20s id %lu already in dn cache\n",
|
||||
e->e_dn, e->e_id, 0 );
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* id tree */
|
||||
if ( avl_insert( &cache->c_idtree, (caddr_t) e,
|
||||
cache_entryid_cmp, avl_dup_error ) != 0 )
|
||||
{
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"====> entry %20s id %lu already in id cache\n",
|
||||
e->e_dn, e->e_id, 0 );
|
||||
|
||||
/* delete from dn tree inserted above */
|
||||
if ( avl_delete( &cache->c_dntree, (caddr_t) e,
|
||||
cache_entrydn_cmp ) == NULL )
|
||||
{
|
||||
Debug( LDAP_DEBUG_ANY, "====> can't delete from dn cache\n",
|
||||
0, 0, 0 );
|
||||
}
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
e->e_state = state;
|
||||
e->e_refcnt = 1;
|
||||
|
||||
/* lru */
|
||||
LRU_ADD( cache, e );
|
||||
if ( ++cache->c_cursize > cache->c_maxsize ) {
|
||||
/*
|
||||
* find the lru entry not currently in use and delete it.
|
||||
* in case a lot of entries are in use, only look at the
|
||||
* first 10 on the tail of the list.
|
||||
*/
|
||||
i = 0;
|
||||
while ( cache->c_lrutail != NULL && cache->c_lrutail->e_refcnt
|
||||
!= 0 && i < 10 ) {
|
||||
/* move this in-use entry to the front of the q */
|
||||
ee = cache->c_lrutail;
|
||||
LRU_DELETE( cache, ee );
|
||||
LRU_ADD( cache, ee );
|
||||
i++;
|
||||
}
|
||||
|
||||
/*
|
||||
* found at least one to delete - try to get back under
|
||||
* the max cache size.
|
||||
*/
|
||||
while ( cache->c_lrutail != NULL && cache->c_lrutail->e_refcnt
|
||||
== 0 && cache->c_cursize > cache->c_maxsize ) {
|
||||
e = cache->c_lrutail;
|
||||
|
||||
/* XXX check for writer lock - should also check no readers pending */
|
||||
#ifdef LDAP_DEBUG
|
||||
assert(!ldap_pvt_thread_rdwr_active(&e->e_rdwr));
|
||||
#endif
|
||||
|
||||
/* delete from cache and lru q */
|
||||
rc = cache_delete_entry_internal( cache, e );
|
||||
|
||||
entry_free( e );
|
||||
}
|
||||
}
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* cache_find_entry_dn2id - find an entry in the cache, given dn
|
||||
*/
|
||||
|
||||
ID
|
||||
bdb2i_cache_find_entry_dn2id(
|
||||
Backend *be,
|
||||
struct cache *cache,
|
||||
char *dn
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
Entry e, *ep;
|
||||
ID id;
|
||||
|
||||
/* set cache mutex */
|
||||
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
|
||||
|
||||
e.e_dn = dn;
|
||||
e.e_ndn = dn_normalize_case( ch_strdup( dn ) );
|
||||
|
||||
if ( (ep = (Entry *) avl_find( cache->c_dntree, (caddr_t) &e,
|
||||
cache_entrydn_cmp )) != NULL )
|
||||
{
|
||||
/*
|
||||
* ep now points to an unlocked entry
|
||||
* we do not need to lock the entry if we only
|
||||
* check the state, refcnt, LRU, and id.
|
||||
*/
|
||||
free(e.e_ndn);
|
||||
|
||||
Debug(LDAP_DEBUG_TRACE, "====> cache_find_entry_dn2id: found dn: %s\n",
|
||||
dn, 0, 0);
|
||||
|
||||
/*
|
||||
* entry is deleted or not fully created yet
|
||||
*/
|
||||
if ( ep->e_state == ENTRY_STATE_DELETED ||
|
||||
ep->e_state == ENTRY_STATE_CREATING )
|
||||
{
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
return( NOID );
|
||||
}
|
||||
|
||||
/* lru */
|
||||
LRU_DELETE( cache, ep );
|
||||
LRU_ADD( cache, ep );
|
||||
|
||||
/* save id */
|
||||
id = ep->e_id;
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
return( id );
|
||||
}
|
||||
|
||||
free(e.e_ndn);
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
return( NOID );
|
||||
}
|
||||
|
||||
/*
|
||||
* cache_find_entry_id - find an entry in the cache, given id
|
||||
*/
|
||||
|
||||
Entry *
|
||||
bdb2i_cache_find_entry_id(
|
||||
struct cache *cache,
|
||||
ID id,
|
||||
int rw
|
||||
)
|
||||
{
|
||||
Entry e;
|
||||
Entry *ep;
|
||||
|
||||
e.e_id = id;
|
||||
|
||||
try_again:
|
||||
/* set cache mutex */
|
||||
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
|
||||
|
||||
if ( (ep = (Entry *) avl_find( cache->c_idtree, (caddr_t) &e,
|
||||
cache_entryid_cmp )) != NULL )
|
||||
{
|
||||
Debug(LDAP_DEBUG_TRACE,
|
||||
"====> cache_find_entry_dn2id: found id: %ld rw: %d\n",
|
||||
id, rw, 0);
|
||||
|
||||
/*
|
||||
* entry is deleted or not fully created yet
|
||||
*/
|
||||
if ( ep->e_state == ENTRY_STATE_DELETED ||
|
||||
ep->e_state == ENTRY_STATE_CREATING )
|
||||
{
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
/* acquire reader lock */
|
||||
if ( entry_rdwr_trylock(ep, rw) == LDAP_PVT_THREAD_EBUSY ) {
|
||||
/* could not acquire entry lock...
|
||||
* owner cannot free as we have the cache locked.
|
||||
* so, unlock the cache, yield, and try again.
|
||||
*/
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
ldap_pvt_thread_yield();
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
/* lru */
|
||||
LRU_DELETE( cache, ep );
|
||||
LRU_ADD( cache, ep );
|
||||
|
||||
ep->e_refcnt++;
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
return( ep );
|
||||
}
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
/*
|
||||
* cache_delete_entry - delete the entry e from the cache. the caller
|
||||
* should have obtained e (increasing its ref count) via a call to one
|
||||
* of the cache_find_* routines. the caller should *not* call the
|
||||
* cache_return_entry() routine prior to calling cache_delete_entry().
|
||||
* it performs this function.
|
||||
*
|
||||
* returns: 0 e was deleted ok
|
||||
* 1 e was not in the cache
|
||||
* -1 something bad happened
|
||||
*/
|
||||
int
|
||||
bdb2i_cache_delete_entry(
|
||||
struct cache *cache,
|
||||
Entry *e
|
||||
)
|
||||
{
|
||||
int rc;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "====> cache_delete_entry:\n", 0, 0, 0 );
|
||||
|
||||
/* XXX check for writer lock - should also check no readers pending */
|
||||
#ifdef LDAP_DEBUG
|
||||
assert(ldap_pvt_thread_rdwr_writers(&e->e_rdwr));
|
||||
#endif
|
||||
|
||||
/* set cache mutex */
|
||||
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
|
||||
|
||||
rc = cache_delete_entry_internal( cache, e );
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
return( rc );
|
||||
}
|
||||
|
||||
static int
|
||||
cache_delete_entry_internal(
|
||||
struct cache *cache,
|
||||
Entry *e
|
||||
)
|
||||
{
|
||||
int rc = 0; /* return code */
|
||||
|
||||
/* dn tree */
|
||||
if ( avl_delete( &cache->c_dntree, (caddr_t) e, cache_entrydn_cmp )
|
||||
== NULL )
|
||||
{
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
/* id tree */
|
||||
if ( avl_delete( &cache->c_idtree, (caddr_t) e, cache_entryid_cmp )
|
||||
== NULL )
|
||||
{
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* lru */
|
||||
LRU_DELETE( cache, e );
|
||||
cache->c_cursize--;
|
||||
|
||||
/*
|
||||
* flag entry to be freed later by a call to cache_return_entry()
|
||||
*/
|
||||
e->e_state = ENTRY_STATE_DELETED;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#ifdef LDAP_DEBUG
|
||||
|
||||
static void
|
||||
lru_print( struct cache *cache )
|
||||
{
|
||||
Entry *e;
|
||||
|
||||
fprintf( stderr, "LRU queue (head to tail):\n" );
|
||||
for ( e = cache->c_lruhead; e != NULL; e = e->e_lrunext ) {
|
||||
fprintf( stderr, "\tdn %20s id %lu refcnt %d\n", e->e_dn,
|
||||
e->e_id, e->e_refcnt );
|
||||
}
|
||||
fprintf( stderr, "LRU queue (tail to head):\n" );
|
||||
for ( e = cache->c_lrutail; e != NULL; e = e->e_lruprev ) {
|
||||
fprintf( stderr, "\tdn %20s id %lu refcnt %d\n", e->e_dn,
|
||||
e->e_id, e->e_refcnt );
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
52
servers/slapd/back-bdb2/close.c
Normal file
52
servers/slapd/back-bdb2/close.c
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/* close.c - close bdb2 backend */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-bdb2.h"
|
||||
|
||||
static int
|
||||
bdb2i_back_db_close_internal( Backend *be )
|
||||
{
|
||||
Debug( LDAP_DEBUG_TRACE, "bdb2 backend saving nextid\n", 0, 0, 0 );
|
||||
if ( bdb2i_next_id_save( be ) < 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY, "bdb2 backend nextid save failed!\n", 0, 0, 0 );
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "bdb2 backend syncing\n", 0, 0, 0 );
|
||||
bdb2i_cache_flush_all( be );
|
||||
Debug( LDAP_DEBUG_TRACE, "bdb2 backend done syncing\n", 0, 0, 0 );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
bdb2_back_db_close( Backend *be )
|
||||
{
|
||||
struct timeval time1, time2;
|
||||
char *elapsed_time;
|
||||
int ret;
|
||||
|
||||
gettimeofday( &time1, NULL );
|
||||
|
||||
ret = bdb2i_back_db_close_internal( be );
|
||||
|
||||
if ( bdb2i_do_timing ) {
|
||||
|
||||
gettimeofday( &time2, NULL);
|
||||
elapsed_time = bdb2i_elapsed( time1, time2 );
|
||||
Debug( LDAP_DEBUG_ANY, "CLOSE elapsed=%s\n",
|
||||
elapsed_time, 0, 0 );
|
||||
free( elapsed_time );
|
||||
|
||||
}
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
|
||||
107
servers/slapd/back-bdb2/compare.c
Normal file
107
servers/slapd/back-bdb2/compare.c
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/* compare.c - bdb2 backend compare routine */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-bdb2.h"
|
||||
#include "proto-back-bdb2.h"
|
||||
|
||||
static int
|
||||
bdb2i_back_compare_internal(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
char *dn,
|
||||
Ava *ava
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
char *matched;
|
||||
Entry *e;
|
||||
Attribute *a;
|
||||
int rc;
|
||||
|
||||
/* get entry with reader lock */
|
||||
if ( (e = bdb2i_dn2entry_r( be, dn, &matched )) == NULL ) {
|
||||
send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, "" );
|
||||
|
||||
if(matched == NULL) free(matched);
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* check for deleted */
|
||||
if ( ! access_allowed( be, conn, op, e,
|
||||
ava->ava_type, &ava->ava_value, ACL_COMPARE ) )
|
||||
{
|
||||
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
|
||||
rc = 1;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if ( (a = attr_find( e->e_attrs, ava->ava_type )) == NULL ) {
|
||||
send_ldap_result( conn, op, LDAP_NO_SUCH_ATTRIBUTE, "", "" );
|
||||
rc = 1;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if ( value_find( a->a_vals, &ava->ava_value, a->a_syntax, 1 ) == 0 )
|
||||
send_ldap_result( conn, op, LDAP_COMPARE_TRUE, "", "" );
|
||||
else
|
||||
send_ldap_result( conn, op, LDAP_COMPARE_FALSE, "", "" );
|
||||
|
||||
rc = 0;
|
||||
|
||||
return_results:;
|
||||
bdb2i_cache_return_entry_r( &li->li_cache, e );
|
||||
return( rc );
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
bdb2_back_compare(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
char *dn,
|
||||
Ava *ava
|
||||
)
|
||||
{
|
||||
DB_LOCK lock;
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
|
||||
struct timeval time1, time2;
|
||||
char *elapsed_time;
|
||||
int ret;
|
||||
|
||||
gettimeofday( &time1, NULL );
|
||||
|
||||
if ( bdb2i_enter_backend_r( &li->li_db_env, &lock ) != 0 ) {
|
||||
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
|
||||
return( 1 );
|
||||
|
||||
}
|
||||
|
||||
ret = bdb2i_back_compare_internal( be, conn, op, dn, ava );
|
||||
|
||||
(void) bdb2i_leave_backend( &li->li_db_env, lock );
|
||||
|
||||
if ( bdb2i_do_timing ) {
|
||||
|
||||
gettimeofday( &time2, NULL);
|
||||
elapsed_time = bdb2i_elapsed( time1, time2 );
|
||||
Debug( LDAP_DEBUG_ANY, "conn=%d op=%d CMP elapsed=%s\n",
|
||||
conn->c_connid, op->o_opid, elapsed_time );
|
||||
free( elapsed_time );
|
||||
|
||||
}
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
|
||||
138
servers/slapd/back-bdb2/config.c
Normal file
138
servers/slapd/back-bdb2/config.c
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
/* config.c - bdb2 backend configuration file routine */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-bdb2.h"
|
||||
|
||||
static int
|
||||
bdb2i_back_db_config_internal(
|
||||
Backend *be,
|
||||
char *fname,
|
||||
int lineno,
|
||||
int argc,
|
||||
char **argv
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
|
||||
if ( li == NULL ) {
|
||||
fprintf( stderr, "%s: line %d: ldbm backend info is null!\n",
|
||||
fname, lineno );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* directory where database files live */
|
||||
if ( strcasecmp( argv[0], "directory" ) == 0 ) {
|
||||
if ( argc < 2 ) {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: missing dir in \"directory <dir>\" line\n",
|
||||
fname, lineno );
|
||||
return( 1 );
|
||||
}
|
||||
li->li_directory = ch_strdup( argv[1] );
|
||||
|
||||
li->li_nextid_file =
|
||||
ch_malloc( strlen(li->li_directory) + sizeof("/NEXTID") );
|
||||
|
||||
strcpy(li->li_nextid_file, li->li_directory);
|
||||
strcat(li->li_nextid_file, "/NEXTID");
|
||||
|
||||
/* mode with which to create new database files */
|
||||
} else if ( strcasecmp( argv[0], "mode" ) == 0 ) {
|
||||
if ( argc < 2 ) {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: missing mode in \"mode <mode>\" line\n",
|
||||
fname, lineno );
|
||||
return( 1 );
|
||||
}
|
||||
li->li_mode = strtol( argv[1], NULL, 0 );
|
||||
|
||||
/* attribute to index */
|
||||
} else if ( strcasecmp( argv[0], "index" ) == 0 ) {
|
||||
if ( argc < 2 ) {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: missing attr in \"index <attr> [pres,eq,approx,sub]\" line\n",
|
||||
fname, lineno );
|
||||
return( 1 );
|
||||
} else if ( argc > 3 ) {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: extra junk after \"index <attr> [pres,eq,approx,sub]\" line (ignored)\n",
|
||||
fname, lineno );
|
||||
}
|
||||
bdb2i_attr_index_config( li, fname, lineno, argc - 1, &argv[1], 0 );
|
||||
|
||||
/* size of the cache in entries */
|
||||
} else if ( strcasecmp( argv[0], "cachesize" ) == 0 ) {
|
||||
if ( argc < 2 ) {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: missing size in \"cachesize <size>\" line\n",
|
||||
fname, lineno );
|
||||
return( 1 );
|
||||
}
|
||||
li->li_cache.c_maxsize = atoi( argv[1] );
|
||||
|
||||
/* size of each dbcache in bytes */
|
||||
} else if ( strcasecmp( argv[0], "dbcachesize" ) == 0 ) {
|
||||
if ( argc < 2 ) {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: missing size in \"dbcachesize <size>\" line\n",
|
||||
fname, lineno );
|
||||
return( 1 );
|
||||
}
|
||||
li->li_dbcachesize = atoi( argv[1] );
|
||||
/* we should at least have the suggested 128k */
|
||||
if ( li->li_dbcachesize < DEFAULT_DBCACHE_SIZE )
|
||||
li->li_dbcachesize = DEFAULT_DBCACHE_SIZE;
|
||||
|
||||
/* no write sync */
|
||||
} else if ( strcasecmp( argv[0], "dbcachenowsync" ) == 0 ) {
|
||||
li->li_dbcachewsync = 0;
|
||||
|
||||
/* anything else */
|
||||
} else {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: unknown directive \"%s\" in ldbm database definition (ignored)\n",
|
||||
fname, lineno, argv[0] );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
bdb2_back_db_config(
|
||||
Backend *be,
|
||||
char *fname,
|
||||
int lineno,
|
||||
int argc,
|
||||
char **argv
|
||||
)
|
||||
{
|
||||
struct timeval time1, time2;
|
||||
char *elapsed_time;
|
||||
int ret;
|
||||
|
||||
gettimeofday( &time1, NULL );
|
||||
|
||||
ret = bdb2i_back_db_config_internal( be, fname, lineno, argc, argv );
|
||||
|
||||
if ( bdb2i_do_timing ) {
|
||||
|
||||
gettimeofday( &time2, NULL);
|
||||
elapsed_time = bdb2i_elapsed( time1, time2 );
|
||||
Debug( LDAP_DEBUG_ANY, "CONFIG elapsed=%s\n",
|
||||
elapsed_time, 0, 0 );
|
||||
free( elapsed_time );
|
||||
|
||||
}
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
|
||||
252
servers/slapd/back-bdb2/dbcache.c
Normal file
252
servers/slapd/back-bdb2/dbcache.c
Normal file
|
|
@ -0,0 +1,252 @@
|
|||
/* ldbmcache.c - maintain a cache of open bdb2 files */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/errno.h>
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
#include <ac/time.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#include "ldapconfig.h"
|
||||
#include "slap.h"
|
||||
#include "back-bdb2.h"
|
||||
|
||||
#define ldbm_open_env( buf, flags, mode, dbcachesize, env ) \
|
||||
ldbm_open( (buf), (flags), (mode), (dbcachesize) )
|
||||
|
||||
struct dbcache *
|
||||
bdb2i_cache_open(
|
||||
Backend *be,
|
||||
char *name,
|
||||
char *suffix,
|
||||
int flags
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
int i, lru;
|
||||
time_t oldtime, curtime;
|
||||
char buf[MAXPATHLEN];
|
||||
LDBM db;
|
||||
struct stat st;
|
||||
int dbcachesize;
|
||||
|
||||
/* sprintf( buf, "%s%s%s%s", li->li_directory, DEFAULT_DIRSEP, name, suffix ); */
|
||||
sprintf( buf, "%s%s", name, suffix );
|
||||
|
||||
/* if in slapd, all files are open, so return handle from file cache */
|
||||
if ( bdb2i_with_dbenv )
|
||||
return( bdb2i_get_db_file_cache( li, buf ));
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> bdb2i_cache_open( \"%s\", %d, %o )\n", buf,
|
||||
flags, li->li_mode );
|
||||
|
||||
lru = 0;
|
||||
ldap_pvt_thread_mutex_lock( ¤ttime_mutex );
|
||||
curtime = currenttime;
|
||||
ldap_pvt_thread_mutex_unlock( ¤ttime_mutex );
|
||||
oldtime = curtime;
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex );
|
||||
for ( i = 0; i < MAXDBCACHE && li->li_dbcache[i].dbc_name != NULL;
|
||||
i++ ) {
|
||||
/* already open - return it */
|
||||
if ( strcmp( li->li_dbcache[i].dbc_name, buf ) == 0 ) {
|
||||
li->li_dbcache[i].dbc_refcnt++;
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= bdb2i_cache_open (cache %d)\n", i, 0, 0 );
|
||||
ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
|
||||
return( &li->li_dbcache[i] );
|
||||
}
|
||||
|
||||
/* keep track of lru db */
|
||||
if ( li->li_dbcache[i].dbc_lastref < oldtime &&
|
||||
li->li_dbcache[i].dbc_refcnt == 0 ) {
|
||||
lru = i;
|
||||
oldtime = li->li_dbcache[i].dbc_lastref;
|
||||
}
|
||||
}
|
||||
|
||||
/* no empty slots, not already open - close lru and use that slot */
|
||||
if ( i == MAXDBCACHE ) {
|
||||
i = lru;
|
||||
if ( li->li_dbcache[i].dbc_refcnt != 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"bdb2i_cache_open no unused db to close - waiting\n",
|
||||
0, 0, 0 );
|
||||
lru = -1;
|
||||
while ( lru == -1 ) {
|
||||
ldap_pvt_thread_cond_wait( &li->li_dbcache_cv,
|
||||
&li->li_dbcache_mutex );
|
||||
for ( i = 0; i < MAXDBCACHE; i++ ) {
|
||||
if ( li->li_dbcache[i].dbc_refcnt
|
||||
== 0 ) {
|
||||
lru = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
i = lru;
|
||||
}
|
||||
ldbm_close( li->li_dbcache[i].dbc_db );
|
||||
free( li->li_dbcache[i].dbc_name );
|
||||
li->li_dbcache[i].dbc_name = NULL;
|
||||
}
|
||||
|
||||
dbcachesize = li->li_dbcachesize;
|
||||
|
||||
if ( bdb2i_with_dbenv ) dbcachesize = 0;
|
||||
if ( (li->li_dbcache[i].dbc_db = ldbm_open_env( buf, flags, li->li_mode,
|
||||
dbcachesize, &li->li_db_env )) == NULL ) {
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= bdb2i_cache_open NULL \"%s\" errno %d reason \"%s\")\n",
|
||||
buf, errno, errno > -1 && errno < sys_nerr ?
|
||||
sys_errlist[errno] : "unknown" );
|
||||
ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
|
||||
return( NULL );
|
||||
}
|
||||
li->li_dbcache[i].dbc_name = ch_strdup( buf );
|
||||
li->li_dbcache[i].dbc_refcnt = 1;
|
||||
li->li_dbcache[i].dbc_lastref = curtime;
|
||||
if ( stat( buf, &st ) == 0 ) {
|
||||
li->li_dbcache[i].dbc_blksize = st.st_blksize;
|
||||
} else {
|
||||
li->li_dbcache[i].dbc_blksize = DEFAULT_BLOCKSIZE;
|
||||
}
|
||||
li->li_dbcache[i].dbc_maxids = (li->li_dbcache[i].dbc_blksize /
|
||||
sizeof(ID)) - ID_BLOCK_IDS_OFFSET;
|
||||
li->li_dbcache[i].dbc_maxindirect = (SLAPD_LDBM_MIN_MAXIDS /
|
||||
li->li_dbcache[i].dbc_maxids) + 1;
|
||||
|
||||
Debug( LDAP_DEBUG_ARGS,
|
||||
"bdb2i_cache_open (blksize %ld) (maxids %d) (maxindirect %d)\n",
|
||||
li->li_dbcache[i].dbc_blksize, li->li_dbcache[i].dbc_maxids,
|
||||
li->li_dbcache[i].dbc_maxindirect );
|
||||
Debug( LDAP_DEBUG_TRACE, "<= bdb2i_cache_open (opened %d)\n", i, 0, 0 );
|
||||
ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
|
||||
return( &li->li_dbcache[i] );
|
||||
}
|
||||
|
||||
void
|
||||
bdb2i_cache_close( Backend *be, struct dbcache *db )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
|
||||
/* if in slapd, all files stay open and we have only
|
||||
readers or one writer */
|
||||
if ( bdb2i_with_dbenv ) return;
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex );
|
||||
if ( --db->dbc_refcnt == 0 ) {
|
||||
ldap_pvt_thread_cond_signal( &li->li_dbcache_cv );
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
|
||||
}
|
||||
|
||||
void
|
||||
bdb2i_cache_really_close( Backend *be, struct dbcache *db )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
|
||||
/* if in slapd, all files stay open and we have only
|
||||
readers or one writer */
|
||||
if ( bdb2i_with_dbenv ) return;
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex );
|
||||
if ( --db->dbc_refcnt == 0 ) {
|
||||
ldap_pvt_thread_cond_signal( &li->li_dbcache_cv );
|
||||
ldbm_close( db->dbc_db );
|
||||
free( db->dbc_name );
|
||||
db->dbc_name = NULL;
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
|
||||
}
|
||||
|
||||
void
|
||||
bdb2i_cache_flush_all( Backend *be )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
int i;
|
||||
|
||||
/* if in slapd, syncing is done by TP */
|
||||
if ( bdb2i_with_dbenv ) return;
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex );
|
||||
for ( i = 0; i < MAXDBCACHE; i++ ) {
|
||||
if ( li->li_dbcache[i].dbc_name != NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "ldbm flushing db (%s)\n",
|
||||
li->li_dbcache[i].dbc_name, 0, 0 );
|
||||
ldbm_sync( li->li_dbcache[i].dbc_db );
|
||||
}
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
|
||||
}
|
||||
|
||||
Datum
|
||||
bdb2i_cache_fetch(
|
||||
struct dbcache *db,
|
||||
Datum key
|
||||
)
|
||||
{
|
||||
Datum data;
|
||||
|
||||
ldbm_datum_init( data );
|
||||
|
||||
data = ldbm_fetch( db->dbc_db, key );
|
||||
|
||||
return( data );
|
||||
}
|
||||
|
||||
int
|
||||
bdb2i_cache_store(
|
||||
struct dbcache *db,
|
||||
Datum key,
|
||||
Datum data,
|
||||
int flags
|
||||
)
|
||||
{
|
||||
int rc;
|
||||
|
||||
#ifdef LDBM_DEBUG
|
||||
Statslog( LDAP_DEBUG_STATS,
|
||||
"=> bdb2i_cache_store(): key.dptr=%s, key.dsize=%d\n",
|
||||
key.dptr, key.dsize, 0, 0, 0 );
|
||||
|
||||
Statslog( LDAP_DEBUG_STATS,
|
||||
"=> bdb2i_cache_store(): key.dptr=0x%08x, data.dptr=0x%0 8x\n",
|
||||
key.dptr, data.dptr, 0, 0, 0 );
|
||||
|
||||
Statslog( LDAP_DEBUG_STATS,
|
||||
"=> bdb2i_cache_store(): data.dptr=%s, data.dsize=%d\n",
|
||||
data.dptr, data.dsize, 0, 0, 0 );
|
||||
|
||||
Statslog( LDAP_DEBUG_STATS,
|
||||
"=> bdb2i_cache_store(): flags=0x%08x\n",
|
||||
flags, 0, 0, 0, 0 );
|
||||
#endif /* LDBM_DEBUG */
|
||||
|
||||
rc = ldbm_store( db->dbc_db, key, data, flags );
|
||||
|
||||
return( rc );
|
||||
}
|
||||
|
||||
int
|
||||
bdb2i_cache_delete(
|
||||
struct dbcache *db,
|
||||
Datum key
|
||||
)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = ldbm_delete( db->dbc_db, key );
|
||||
|
||||
return( rc );
|
||||
}
|
||||
194
servers/slapd/back-bdb2/delete.c
Normal file
194
servers/slapd/back-bdb2/delete.c
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
/* delete.c - bdb2 backend delete routine */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-bdb2.h"
|
||||
#include "proto-back-bdb2.h"
|
||||
|
||||
static int
|
||||
bdb2i_back_delete_internal(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
char *dn
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
char *matched = NULL;
|
||||
char *pdn = NULL;
|
||||
Entry *e, *p = NULL;
|
||||
int rootlock = 0;
|
||||
int rc = -1;
|
||||
|
||||
Debug(LDAP_DEBUG_ARGS, "==> bdb2i_back_delete: %s\n", dn, 0, 0);
|
||||
|
||||
/* get entry with writer lock */
|
||||
if ( (e = bdb2i_dn2entry_w( be, dn, &matched )) == NULL ) {
|
||||
Debug(LDAP_DEBUG_ARGS, "<=- bdb2i_back_delete: no such object %s\n",
|
||||
dn, 0, 0);
|
||||
send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, "" );
|
||||
if ( matched != NULL ) {
|
||||
free( matched );
|
||||
}
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* check for deleted */
|
||||
|
||||
if ( bdb2i_has_children( be, e ) ) {
|
||||
Debug(LDAP_DEBUG_ARGS, "<=- bdb2i_back_delete: non leaf %s\n",
|
||||
dn, 0, 0);
|
||||
send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF, "",
|
||||
"" );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
#ifdef SLAPD_CHILD_MODIFICATION_WITH_ENTRY_ACL
|
||||
if ( ! access_allowed( be, conn, op, e,
|
||||
"entry", NULL, ACL_WRITE ) )
|
||||
{
|
||||
Debug(LDAP_DEBUG_ARGS,
|
||||
"<=- bdb2i_back_delete: insufficient access %s\n",
|
||||
dn, 0, 0);
|
||||
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
|
||||
goto return_results;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* delete from parent's id2children entry */
|
||||
if( (pdn = dn_parent( be, dn )) != NULL ) {
|
||||
if( (p = bdb2i_dn2entry_w( be, pdn, &matched )) == NULL) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<=- bdb2i_back_delete: parent does not exist\n", 0, 0, 0);
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
|
||||
"", "");
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
#ifndef SLAPD_CHILD_MODIFICATION_WITH_ENTRY_ACL
|
||||
/* check parent for "children" acl */
|
||||
if ( ! access_allowed( be, conn, op, p,
|
||||
"children", NULL, ACL_WRITE ) )
|
||||
{
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<=- bdb2i_back_delete: no access to parent\n", 0, 0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
|
||||
"", "" );
|
||||
goto return_results;
|
||||
}
|
||||
#endif
|
||||
|
||||
} else {
|
||||
/* no parent, must be root to delete */
|
||||
if( ! be_isroot( be, op->o_ndn ) ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<=- bdb2i_back_delete: no parent & not root\n", 0, 0, 0);
|
||||
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
|
||||
"", "");
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_lock(&li->li_root_mutex);
|
||||
rootlock = 1;
|
||||
}
|
||||
|
||||
if ( bdb2i_id2children_remove( be, p, e ) != 0 ) {
|
||||
Debug(LDAP_DEBUG_ARGS,
|
||||
"<=- bdb2i_back_delete: operations error %s\n",
|
||||
dn, 0, 0);
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "","" );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
/* delete from dn2id mapping */
|
||||
if ( bdb2i_dn2id_delete( be, e->e_dn ) != 0 ) {
|
||||
Debug(LDAP_DEBUG_ARGS,
|
||||
"<=- bdb2i_back_delete: operations error %s\n",
|
||||
dn, 0, 0);
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
/* delete from disk and cache */
|
||||
if ( bdb2i_id2entry_delete( be, e ) != 0 ) {
|
||||
Debug(LDAP_DEBUG_ARGS,
|
||||
"<=- bdb2i_back_delete: operations error %s\n",
|
||||
dn, 0, 0);
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
|
||||
rc = 0;
|
||||
|
||||
return_results:;
|
||||
if ( pdn != NULL ) free(pdn);
|
||||
|
||||
if( p != NULL ) {
|
||||
/* free parent and writer lock */
|
||||
bdb2i_cache_return_entry_w( &li->li_cache, p );
|
||||
|
||||
}
|
||||
|
||||
if ( rootlock ) {
|
||||
/* release root lock */
|
||||
ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
|
||||
}
|
||||
|
||||
/* free entry and writer lock */
|
||||
bdb2i_cache_return_entry_w( &li->li_cache, e );
|
||||
|
||||
if ( matched != NULL ) free(matched);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
bdb2_back_delete(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
char *dn
|
||||
)
|
||||
{
|
||||
DB_LOCK lock;
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
|
||||
struct timeval time1, time2;
|
||||
char *elapsed_time;
|
||||
int ret;
|
||||
|
||||
gettimeofday( &time1, NULL );
|
||||
|
||||
if ( bdb2i_enter_backend_w( &li->li_db_env, &lock ) != 0 ) {
|
||||
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
|
||||
return( -1 );
|
||||
|
||||
}
|
||||
|
||||
ret = bdb2i_back_delete_internal( be, conn, op, dn );
|
||||
|
||||
(void) bdb2i_leave_backend( &li->li_db_env, lock );
|
||||
|
||||
if ( bdb2i_do_timing ) {
|
||||
|
||||
gettimeofday( &time2, NULL);
|
||||
elapsed_time = bdb2i_elapsed( time1, time2 );
|
||||
Debug( LDAP_DEBUG_ANY, "conn=%d op=%d DEL elapsed=%s\n",
|
||||
conn->c_connid, op->o_opid, elapsed_time );
|
||||
free( elapsed_time );
|
||||
|
||||
}
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
|
||||
232
servers/slapd/back-bdb2/dn2id.c
Normal file
232
servers/slapd/back-bdb2/dn2id.c
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
/* dn2id.c - routines to deal with the dn2id index */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-bdb2.h"
|
||||
#include "proto-back-bdb2.h"
|
||||
|
||||
int
|
||||
bdb2i_dn2id_add(
|
||||
Backend *be,
|
||||
char *dn,
|
||||
ID id
|
||||
)
|
||||
{
|
||||
int rc, flags;
|
||||
struct dbcache *db;
|
||||
Datum key, data;
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
|
||||
ldbm_datum_init( key );
|
||||
ldbm_datum_init( data );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> bdb2i_dn2id_add( \"%s\", %ld )\n", dn, id, 0 );
|
||||
|
||||
if ( (db = bdb2i_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_WRCREAT ))
|
||||
== NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY, "Could not open/create dn2id%s\n",
|
||||
LDBM_SUFFIX, 0, 0 );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
dn = ch_strdup( dn );
|
||||
dn_normalize_case( dn );
|
||||
|
||||
key.dptr = dn;
|
||||
key.dsize = strlen( dn ) + 1;
|
||||
data.dptr = (char *) &id;
|
||||
data.dsize = sizeof(ID);
|
||||
|
||||
flags = LDBM_INSERT;
|
||||
if ( li->li_dbcachewsync ) flags |= LDBM_SYNC;
|
||||
|
||||
rc = bdb2i_cache_store( db, key, data, flags );
|
||||
|
||||
free( dn );
|
||||
bdb2i_cache_close( be, db );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= bdb2i_dn2id_add %d\n", rc, 0, 0 );
|
||||
return( rc );
|
||||
}
|
||||
|
||||
ID
|
||||
bdb2i_dn2id(
|
||||
Backend *be,
|
||||
char *dn
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
struct dbcache *db;
|
||||
ID id;
|
||||
Datum key, data;
|
||||
|
||||
ldbm_datum_init( key );
|
||||
ldbm_datum_init( data );
|
||||
|
||||
dn = ch_strdup( dn );
|
||||
Debug( LDAP_DEBUG_TRACE, "=> bdb2i_dn2id( \"%s\" )\n", dn, 0, 0 );
|
||||
dn_normalize_case( dn );
|
||||
|
||||
/* first check the cache */
|
||||
if ( (id = bdb2i_cache_find_entry_dn2id( be, &li->li_cache, dn )) != NOID ) {
|
||||
free( dn );
|
||||
Debug( LDAP_DEBUG_TRACE, "<= bdb2i_dn2id %lu (in cache)\n", id,
|
||||
0, 0 );
|
||||
return( id );
|
||||
}
|
||||
|
||||
if ( (db = bdb2i_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_WRCREAT ))
|
||||
== NULL ) {
|
||||
free( dn );
|
||||
Debug( LDAP_DEBUG_ANY, "<= bdb2i_dn2id could not open dn2id%s\n",
|
||||
LDBM_SUFFIX, 0, 0 );
|
||||
return( NOID );
|
||||
}
|
||||
|
||||
key.dptr = dn;
|
||||
key.dsize = strlen( dn ) + 1;
|
||||
|
||||
data = bdb2i_cache_fetch( db, key );
|
||||
|
||||
bdb2i_cache_close( be, db );
|
||||
free( dn );
|
||||
|
||||
if ( data.dptr == NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "<= bdb2i_dn2id NOID\n", 0, 0, 0 );
|
||||
return( NOID );
|
||||
}
|
||||
|
||||
(void) memcpy( (char *) &id, data.dptr, sizeof(ID) );
|
||||
|
||||
ldbm_datum_free( db->dbc_db, data );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= bdb2i_dn2id %lu\n", id, 0, 0 );
|
||||
return( id );
|
||||
}
|
||||
|
||||
int
|
||||
bdb2i_dn2id_delete(
|
||||
Backend *be,
|
||||
char *dn
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
struct dbcache *db;
|
||||
Datum key;
|
||||
int rc;
|
||||
|
||||
ldbm_datum_init( key );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> bdb2i_dn2id_delete( \"%s\" )\n", dn, 0, 0 );
|
||||
|
||||
if ( (db = bdb2i_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_WRCREAT ))
|
||||
== NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"<= bdb2i_dn2id_delete could not open dn2id%s\n", LDBM_SUFFIX,
|
||||
0, 0 );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
dn = ch_strdup( dn );
|
||||
dn_normalize_case( dn );
|
||||
key.dptr = dn;
|
||||
key.dsize = strlen( dn ) + 1;
|
||||
|
||||
rc = bdb2i_cache_delete( db, key );
|
||||
|
||||
free( dn );
|
||||
|
||||
bdb2i_cache_close( be, db );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= bdb2i_dn2id_delete %d\n", rc, 0, 0 );
|
||||
return( rc );
|
||||
}
|
||||
|
||||
/*
|
||||
* dn2entry - look up dn in the cache/indexes and return the corresponding
|
||||
* entry.
|
||||
*/
|
||||
|
||||
static Entry *
|
||||
dn2entry(
|
||||
Backend *be,
|
||||
char *dn,
|
||||
char **matched,
|
||||
int rw
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
ID id;
|
||||
Entry *e = NULL;
|
||||
char *pdn;
|
||||
|
||||
Debug(LDAP_DEBUG_TRACE, "dn2entry_%s: dn: \"%s\"\n",
|
||||
rw ? "w" : "r", dn, 0);
|
||||
|
||||
*matched = NULL;
|
||||
|
||||
if ( (id = bdb2i_dn2id( be, dn )) != NOID &&
|
||||
(e = bdb2i_id2entry( be, id, rw )) != NULL )
|
||||
{
|
||||
return( e );
|
||||
}
|
||||
|
||||
if ( id != NOID ) {
|
||||
Debug(LDAP_DEBUG_ANY,
|
||||
"dn2entry_%s: no entry for valid id (%lu), dn \"%s\"\n",
|
||||
rw ? "w" : "r", id, dn);
|
||||
/* must have been deleted from underneath us */
|
||||
/* treat as if NOID was found */
|
||||
}
|
||||
|
||||
/* stop when we get to the suffix */
|
||||
if ( be_issuffix( be, dn ) ) {
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
/* entry does not exist - see how much of the dn does exist */
|
||||
if ( (pdn = dn_parent( be, dn )) != NULL ) {
|
||||
/* get entry with reader lock */
|
||||
if ( (e = bdb2i_dn2entry_r( be, pdn, matched )) != NULL ) {
|
||||
if(*matched != NULL) {
|
||||
free(*matched);
|
||||
}
|
||||
*matched = pdn;
|
||||
/* free entry with reader lock */
|
||||
bdb2i_cache_return_entry_r( &li->li_cache, e );
|
||||
} else {
|
||||
free( pdn );
|
||||
}
|
||||
}
|
||||
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
Entry *
|
||||
bdb2i_dn2entry_r(
|
||||
Backend *be,
|
||||
char *dn,
|
||||
char **matched
|
||||
)
|
||||
{
|
||||
return( dn2entry( be, dn, matched, 0 ) );
|
||||
}
|
||||
|
||||
Entry *
|
||||
bdb2i_dn2entry_w(
|
||||
Backend *be,
|
||||
char *dn,
|
||||
char **matched
|
||||
)
|
||||
{
|
||||
return( dn2entry( be, dn, matched, 1 ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
59
servers/slapd/back-bdb2/external.h
Normal file
59
servers/slapd/back-bdb2/external.h
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
#ifndef _BDB2_EXTERNAL_H
|
||||
#define _BDB2_EXTERNAL_H
|
||||
|
||||
LDAP_BEGIN_DECL
|
||||
|
||||
extern int bdb2_back_initialize LDAP_P(( BackendInfo *bi ));
|
||||
extern int bdb2_back_open LDAP_P(( BackendInfo *bi ));
|
||||
extern int bdb2_back_close LDAP_P(( BackendInfo *bi ));
|
||||
extern int bdb2_back_destroy LDAP_P(( BackendInfo *bi ));
|
||||
|
||||
extern int bdb2_back_db_init LDAP_P(( BackendDB *bd ));
|
||||
extern int bdb2_back_db_open LDAP_P(( BackendDB *bd ));
|
||||
extern int bdb2_back_db_close LDAP_P(( BackendDB *bd ));
|
||||
extern int bdb2_back_db_destroy LDAP_P(( BackendDB *bd ));
|
||||
|
||||
extern int bdb2_back_db_config LDAP_P(( BackendDB *bd,
|
||||
char *fname, int lineno, int argc, char **argv ));
|
||||
|
||||
extern int bdb2_back_bind LDAP_P(( BackendDB *bd,
|
||||
Connection *conn, Operation *op,
|
||||
char *dn, int method, struct berval *cred, char** edn ));
|
||||
|
||||
extern int bdb2_back_unbind LDAP_P(( BackendDB *bd,
|
||||
Connection *conn, Operation *op ));
|
||||
|
||||
extern int bdb2_back_search LDAP_P(( BackendDB *bd,
|
||||
Connection *conn, Operation *op,
|
||||
char *base, int scope, int deref, int sizelimit, int timelimit,
|
||||
Filter *filter, char *filterstr, char **attrs, int attrsonly ));
|
||||
|
||||
extern int bdb2_back_compare LDAP_P((BackendDB *bd,
|
||||
Connection *conn, Operation *op,
|
||||
char *dn, Ava *ava ));
|
||||
|
||||
extern int bdb2_back_modify LDAP_P(( BackendDB *bd,
|
||||
Connection *conn, Operation *op,
|
||||
char *dn, LDAPModList *ml ));
|
||||
|
||||
extern int bdb2_back_modrdn LDAP_P(( BackendDB *bd,
|
||||
Connection *conn, Operation *op,
|
||||
char *dn, char*newrdn, int deleteoldrdn ));
|
||||
|
||||
extern int bdb2_back_add LDAP_P(( BackendDB *bd,
|
||||
Connection *conn, Operation *op, Entry *e ));
|
||||
|
||||
extern int bdb2_back_delete LDAP_P(( BackendDB *bd,
|
||||
Connection *conn, Operation *op, char *dn ));
|
||||
|
||||
extern int bdb2_back_abandon LDAP_P(( BackendDB *bd,
|
||||
Connection *conn, Operation *op, int msgid ));
|
||||
|
||||
extern int bdb2_back_group LDAP_P(( BackendDB *bd,
|
||||
Entry *target, char* gr_ndn, char* op_ndn,
|
||||
char* objectclassValue, char* groupattrName));
|
||||
|
||||
LDAP_END_DECL
|
||||
|
||||
#endif /* _BDB2_EXTERNAL_H */
|
||||
|
||||
353
servers/slapd/back-bdb2/filterindex.c
Normal file
353
servers/slapd/back-bdb2/filterindex.c
Normal file
|
|
@ -0,0 +1,353 @@
|
|||
/* filterindex.c - generate the list of candidate entries from a filter */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-bdb2.h"
|
||||
|
||||
static ID_BLOCK *ava_candidates( Backend *be, Ava *ava, int type );
|
||||
static ID_BLOCK *presence_candidates( Backend *be, char *type );
|
||||
static ID_BLOCK *approx_candidates( Backend *be, Ava *ava );
|
||||
static ID_BLOCK *list_candidates( Backend *be, Filter *flist, int ftype );
|
||||
static ID_BLOCK *substring_candidates( Backend *be, Filter *f );
|
||||
static ID_BLOCK *substring_comp_candidates( Backend *be, char *type, char *val, int prepost );
|
||||
|
||||
/*
|
||||
* test_filter - test a filter against a single entry.
|
||||
* returns 0 filter matched
|
||||
* -1 filter did not match
|
||||
* >0 an ldap error code
|
||||
*/
|
||||
|
||||
ID_BLOCK *
|
||||
bdb2i_filter_candidates(
|
||||
Backend *be,
|
||||
Filter *f
|
||||
)
|
||||
{
|
||||
ID_BLOCK *result, *tmp1, *tmp2;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> bdb2i_filter_candidates\n", 0, 0, 0 );
|
||||
|
||||
result = NULL;
|
||||
switch ( f->f_choice ) {
|
||||
case LDAP_FILTER_EQUALITY:
|
||||
Debug( LDAP_DEBUG_FILTER, "\tEQUALITY\n", 0, 0, 0 );
|
||||
result = ava_candidates( be, &f->f_ava, LDAP_FILTER_EQUALITY );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_SUBSTRINGS:
|
||||
Debug( LDAP_DEBUG_FILTER, "\tSUBSTRINGS\n", 0, 0, 0 );
|
||||
result = substring_candidates( be, f );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_GE:
|
||||
Debug( LDAP_DEBUG_FILTER, "\tGE\n", 0, 0, 0 );
|
||||
result = ava_candidates( be, &f->f_ava, LDAP_FILTER_GE );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_LE:
|
||||
Debug( LDAP_DEBUG_FILTER, "\tLE\n", 0, 0, 0 );
|
||||
result = ava_candidates( be, &f->f_ava, LDAP_FILTER_LE );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_PRESENT:
|
||||
Debug( LDAP_DEBUG_FILTER, "\tPRESENT\n", 0, 0, 0 );
|
||||
result = presence_candidates( be, f->f_type );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_APPROX:
|
||||
Debug( LDAP_DEBUG_FILTER, "\tAPPROX\n", 0, 0, 0 );
|
||||
result = approx_candidates( be, &f->f_ava );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_AND:
|
||||
Debug( LDAP_DEBUG_FILTER, "\tAND\n", 0, 0, 0 );
|
||||
result = list_candidates( be, f->f_and, LDAP_FILTER_AND );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_OR:
|
||||
Debug( LDAP_DEBUG_FILTER, "\tOR\n", 0, 0, 0 );
|
||||
result = list_candidates( be, f->f_or, LDAP_FILTER_OR );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_NOT:
|
||||
Debug( LDAP_DEBUG_FILTER, "\tNOT\n", 0, 0, 0 );
|
||||
tmp1 = bdb2i_idl_allids( be );
|
||||
tmp2 = bdb2i_filter_candidates( be, f->f_not );
|
||||
result = bdb2i_idl_notin( be, tmp1, tmp2 );
|
||||
bdb2i_idl_free( tmp2 );
|
||||
bdb2i_idl_free( tmp1 );
|
||||
break;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= bdb2i_filter_candidates %lu\n",
|
||||
result ? ID_BLOCK_NIDS(result) : 0, 0, 0 );
|
||||
return( result );
|
||||
}
|
||||
|
||||
static ID_BLOCK *
|
||||
ava_candidates(
|
||||
Backend *be,
|
||||
Ava *ava,
|
||||
int type
|
||||
)
|
||||
{
|
||||
ID_BLOCK *idl;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> ava_candidates 0x%x\n", type, 0, 0 );
|
||||
|
||||
switch ( type ) {
|
||||
case LDAP_FILTER_EQUALITY:
|
||||
idl = bdb2i_index_read( be, ava->ava_type, INDEX_EQUALITY,
|
||||
ava->ava_value.bv_val );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_GE:
|
||||
idl = bdb2i_idl_allids( be );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_LE:
|
||||
idl = bdb2i_idl_allids( be );
|
||||
break;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= ava_candidates %lu\n",
|
||||
idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
|
||||
return( idl );
|
||||
}
|
||||
|
||||
static ID_BLOCK *
|
||||
presence_candidates(
|
||||
Backend *be,
|
||||
char *type
|
||||
)
|
||||
{
|
||||
ID_BLOCK *idl;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> presence_candidates\n", 0, 0, 0 );
|
||||
|
||||
idl = bdb2i_index_read( be, type, 0, "*" );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= presence_candidates %lu\n",
|
||||
idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
|
||||
return( idl );
|
||||
}
|
||||
|
||||
static ID_BLOCK *
|
||||
approx_candidates(
|
||||
Backend *be,
|
||||
Ava *ava
|
||||
)
|
||||
{
|
||||
char *w, *c;
|
||||
ID_BLOCK *idl, *tmp;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> approx_candidates\n", 0, 0, 0 );
|
||||
|
||||
idl = NULL;
|
||||
for ( w = first_word( ava->ava_value.bv_val ); w != NULL;
|
||||
w = next_word( w ) ) {
|
||||
c = phonetic( w );
|
||||
if ( (tmp = bdb2i_index_read( be, ava->ava_type, INDEX_APPROX, c ))
|
||||
== NULL ) {
|
||||
free( c );
|
||||
bdb2i_idl_free( idl );
|
||||
Debug( LDAP_DEBUG_TRACE, "<= approx_candidates NULL\n",
|
||||
0, 0, 0 );
|
||||
return( NULL );
|
||||
}
|
||||
free( c );
|
||||
|
||||
if ( idl == NULL ) {
|
||||
idl = tmp;
|
||||
} else {
|
||||
idl = bdb2i_idl_intersection( be, idl, tmp );
|
||||
}
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= approx_candidates %lu\n",
|
||||
idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
|
||||
return( idl );
|
||||
}
|
||||
|
||||
static ID_BLOCK *
|
||||
list_candidates(
|
||||
Backend *be,
|
||||
Filter *flist,
|
||||
int ftype
|
||||
)
|
||||
{
|
||||
ID_BLOCK *idl, *tmp, *tmp2;
|
||||
Filter *f;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> list_candidates 0x%x\n", ftype, 0, 0 );
|
||||
|
||||
idl = NULL;
|
||||
for ( f = flist; f != NULL; f = f->f_next ) {
|
||||
if ( (tmp = bdb2i_filter_candidates( be, f )) == NULL &&
|
||||
ftype == LDAP_FILTER_AND ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= list_candidates NULL\n", 0, 0, 0 );
|
||||
bdb2i_idl_free( idl );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
tmp2 = idl;
|
||||
if ( idl == NULL ) {
|
||||
idl = tmp;
|
||||
} else if ( ftype == LDAP_FILTER_AND ) {
|
||||
idl = bdb2i_idl_intersection( be, idl, tmp );
|
||||
bdb2i_idl_free( tmp );
|
||||
bdb2i_idl_free( tmp2 );
|
||||
} else {
|
||||
idl = bdb2i_idl_union( be, idl, tmp );
|
||||
bdb2i_idl_free( tmp );
|
||||
bdb2i_idl_free( tmp2 );
|
||||
}
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= list_candidates %lu\n",
|
||||
idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
|
||||
return( idl );
|
||||
}
|
||||
|
||||
static ID_BLOCK *
|
||||
substring_candidates(
|
||||
Backend *be,
|
||||
Filter *f
|
||||
)
|
||||
{
|
||||
int i;
|
||||
ID_BLOCK *idl, *tmp, *tmp2;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> substring_candidates\n", 0, 0, 0 );
|
||||
|
||||
idl = NULL;
|
||||
|
||||
/* initial */
|
||||
if ( f->f_sub_initial != NULL ) {
|
||||
if ( (int) strlen( f->f_sub_initial ) < SUBLEN - 1 ) {
|
||||
idl = bdb2i_idl_allids( be );
|
||||
} else if ( (idl = substring_comp_candidates( be, f->f_sub_type,
|
||||
f->f_sub_initial, '^' )) == NULL ) {
|
||||
return( NULL );
|
||||
}
|
||||
}
|
||||
|
||||
/* final */
|
||||
if ( f->f_sub_final != NULL ) {
|
||||
if ( (int) strlen( f->f_sub_final ) < SUBLEN - 1 ) {
|
||||
tmp = bdb2i_idl_allids( be );
|
||||
} else if ( (tmp = substring_comp_candidates( be, f->f_sub_type,
|
||||
f->f_sub_final, '$' )) == NULL ) {
|
||||
bdb2i_idl_free( idl );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
if ( idl == NULL ) {
|
||||
idl = tmp;
|
||||
} else {
|
||||
tmp2 = idl;
|
||||
idl = bdb2i_idl_intersection( be, idl, tmp );
|
||||
bdb2i_idl_free( tmp );
|
||||
bdb2i_idl_free( tmp2 );
|
||||
}
|
||||
}
|
||||
|
||||
for ( i = 0; f->f_sub_any != NULL && f->f_sub_any[i] != NULL; i++ ) {
|
||||
if ( (int) strlen( f->f_sub_any[i] ) < SUBLEN ) {
|
||||
tmp = bdb2i_idl_allids( be );
|
||||
} else if ( (tmp = substring_comp_candidates( be, f->f_sub_type,
|
||||
f->f_sub_any[i], 0 )) == NULL ) {
|
||||
bdb2i_idl_free( idl );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
if ( idl == NULL ) {
|
||||
idl = tmp;
|
||||
} else {
|
||||
tmp2 = idl;
|
||||
idl = bdb2i_idl_intersection( be, idl, tmp );
|
||||
bdb2i_idl_free( tmp );
|
||||
bdb2i_idl_free( tmp2 );
|
||||
}
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= substring_candidates %lu\n",
|
||||
idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
|
||||
return( idl );
|
||||
}
|
||||
|
||||
static ID_BLOCK *
|
||||
substring_comp_candidates(
|
||||
Backend *be,
|
||||
char *type,
|
||||
char *val,
|
||||
int prepost
|
||||
)
|
||||
{
|
||||
int i, len;
|
||||
ID_BLOCK *idl, *tmp, *tmp2;
|
||||
char *p;
|
||||
char buf[SUBLEN + 1];
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> substring_comp_candidates\n", 0, 0, 0 );
|
||||
|
||||
len = strlen( val );
|
||||
idl = NULL;
|
||||
|
||||
/* prepend ^ for initial substring */
|
||||
if ( prepost == '^' ) {
|
||||
buf[0] = '^';
|
||||
for ( i = 0; i < SUBLEN - 1; i++ ) {
|
||||
buf[i + 1] = val[i];
|
||||
}
|
||||
buf[SUBLEN] = '\0';
|
||||
|
||||
if ( (idl = bdb2i_index_read( be, type, INDEX_SUB, buf )) == NULL ) {
|
||||
return( NULL );
|
||||
}
|
||||
} else if ( prepost == '$' ) {
|
||||
p = val + len - SUBLEN + 1;
|
||||
for ( i = 0; i < SUBLEN - 1; i++ ) {
|
||||
buf[i] = p[i];
|
||||
}
|
||||
buf[SUBLEN - 1] = '$';
|
||||
buf[SUBLEN] = '\0';
|
||||
|
||||
if ( (idl = bdb2i_index_read( be, type, INDEX_SUB, buf )) == NULL ) {
|
||||
return( NULL );
|
||||
}
|
||||
}
|
||||
|
||||
for ( p = val; p < (val + len - SUBLEN + 1); p++ ) {
|
||||
for ( i = 0; i < SUBLEN; i++ ) {
|
||||
buf[i] = p[i];
|
||||
}
|
||||
buf[SUBLEN] = '\0';
|
||||
|
||||
if ( (tmp = bdb2i_index_read( be, type, INDEX_SUB, buf )) == NULL ) {
|
||||
bdb2i_idl_free( idl );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
if ( idl == NULL ) {
|
||||
idl = tmp;
|
||||
} else {
|
||||
tmp2 = idl;
|
||||
idl = bdb2i_idl_intersection( be, idl, tmp );
|
||||
bdb2i_idl_free( tmp );
|
||||
bdb2i_idl_free( tmp2 );
|
||||
}
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= substring_comp_candidates %lu\n",
|
||||
idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
|
||||
return( idl );
|
||||
}
|
||||
171
servers/slapd/back-bdb2/group.c
Normal file
171
servers/slapd/back-bdb2/group.c
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
/* group.c - bdb2 backend acl group routine */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-bdb2.h"
|
||||
#include "proto-back-bdb2.h"
|
||||
|
||||
|
||||
#ifdef SLAPD_ACLGROUPS
|
||||
/* return 0 IFF op_dn is a value in member attribute
|
||||
* of entry with gr_dn AND that entry has an objectClass
|
||||
* value of groupOfNames
|
||||
*/
|
||||
static int
|
||||
bdb2i_back_group_internal(
|
||||
Backend *be,
|
||||
Entry *target,
|
||||
char *gr_ndn,
|
||||
char *op_ndn,
|
||||
char *objectclassValue,
|
||||
char *groupattrName
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
Entry *e;
|
||||
char *matched;
|
||||
Attribute *objectClass;
|
||||
Attribute *member;
|
||||
int rc;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"=> bdb2i_back_group: gr dn: \"%s\"\n",
|
||||
gr_ndn, 0, 0 );
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"=> bdb2i_back_group: op dn: \"%s\"\n",
|
||||
op_ndn, 0, 0 );
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"=> bdb2i_back_group: objectClass: \"%s\" attrName: \"%s\"\n",
|
||||
objectclassValue, groupattrName, 0 );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"=> bdb2i_back_group: tr dn: \"%s\"\n",
|
||||
target->e_ndn, 0, 0 );
|
||||
|
||||
if (strcmp(target->e_ndn, gr_ndn) == 0) {
|
||||
/* we already have a LOCKED copy of the entry */
|
||||
e = target;
|
||||
Debug( LDAP_DEBUG_ARGS,
|
||||
"=> bdb2i_back_group: target is group: \"%s\"\n",
|
||||
gr_ndn, 0, 0 );
|
||||
} else {
|
||||
/* can we find group entry with reader lock */
|
||||
if ((e = bdb2i_dn2entry_r(be, gr_ndn, &matched )) == NULL) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"=> bdb2i_back_group: cannot find group: \"%s\" matched: \"%s\"\n",
|
||||
gr_ndn, (matched ? matched : ""), 0 );
|
||||
if (matched != NULL)
|
||||
free(matched);
|
||||
return( 1 );
|
||||
}
|
||||
Debug( LDAP_DEBUG_ARGS,
|
||||
"=> bdb2i_back_group: found group: \"%s\"\n",
|
||||
gr_ndn, 0, 0 );
|
||||
}
|
||||
|
||||
|
||||
/* check for deleted */
|
||||
|
||||
/* find it's objectClass and member attribute values
|
||||
* make sure this is a group entry
|
||||
* finally test if we can find op_dn in the member attribute value list *
|
||||
*/
|
||||
|
||||
rc = 1;
|
||||
if ((objectClass = attr_find(e->e_attrs, "objectclass")) == NULL) {
|
||||
Debug( LDAP_DEBUG_TRACE, "<= bdb2i_back_group: failed to find objectClass\n", 0, 0, 0 );
|
||||
}
|
||||
else if ((member = attr_find(e->e_attrs, groupattrName)) == NULL) {
|
||||
Debug( LDAP_DEBUG_TRACE, "<= bdb2i_back_group: failed to find %s\n", groupattrName, 0, 0 );
|
||||
}
|
||||
else {
|
||||
struct berval bvObjectClass;
|
||||
struct berval bvMembers;
|
||||
|
||||
Debug( LDAP_DEBUG_ARGS, "<= bdb2i_back_group: found objectClass and %s\n", groupattrName, 0, 0 );
|
||||
|
||||
bvObjectClass.bv_val = objectclassValue;
|
||||
bvObjectClass.bv_len = strlen( bvObjectClass.bv_val );
|
||||
|
||||
bvMembers.bv_val = op_ndn;
|
||||
bvMembers.bv_len = strlen( op_ndn );
|
||||
|
||||
if (value_find(objectClass->a_vals, &bvObjectClass, SYNTAX_CIS, 1) != 0) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= bdb2i_back_group: failed to find %s in objectClass\n",
|
||||
objectclassValue, 0, 0 );
|
||||
}
|
||||
else if (value_find(member->a_vals, &bvMembers, SYNTAX_CIS, 1) != 0) {
|
||||
Debug( LDAP_DEBUG_ACL,
|
||||
"<= bdb2i_back_group: \"%s\" not in \"%s\": %s\n",
|
||||
op_ndn, gr_ndn, groupattrName );
|
||||
}
|
||||
else {
|
||||
Debug( LDAP_DEBUG_ACL,
|
||||
"<= bdb2i_back_group: \"%s\" is in \"%s\": %s\n",
|
||||
op_ndn, gr_ndn, groupattrName );
|
||||
rc = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( target != e ) {
|
||||
/* free entry and reader lock */
|
||||
bdb2i_cache_return_entry_r( &li->li_cache, e );
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_ARGS, "bdb2i_back_group: rc: %d\n", rc, 0, 0 );
|
||||
return(rc);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
bdb2_back_group(
|
||||
Backend *be,
|
||||
Entry *target,
|
||||
char *gr_ndn,
|
||||
char *op_ndn,
|
||||
char *objectclassValue,
|
||||
char *groupattrName
|
||||
)
|
||||
{
|
||||
DB_LOCK lock;
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
|
||||
struct timeval time1, time2;
|
||||
char *elapsed_time;
|
||||
int ret;
|
||||
|
||||
gettimeofday( &time1, NULL );
|
||||
|
||||
if ( bdb2i_enter_backend_r( &li->li_db_env, &lock ) != 0 ) {
|
||||
|
||||
return( 1 );
|
||||
|
||||
}
|
||||
|
||||
ret = bdb2i_back_group_internal( be, target, gr_ndn, op_ndn,
|
||||
objectclassValue, groupattrName );
|
||||
|
||||
(void) bdb2i_leave_backend( &li->li_db_env, lock );
|
||||
|
||||
if ( bdb2i_do_timing ) {
|
||||
|
||||
gettimeofday( &time2, NULL);
|
||||
elapsed_time = bdb2i_elapsed( time1, time2 );
|
||||
Debug( LDAP_DEBUG_ANY, "GRP elapsed=%s\n",
|
||||
elapsed_time, 0, 0 );
|
||||
free( elapsed_time );
|
||||
|
||||
}
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
#endif /* SLAPD_ACLGROUPS */
|
||||
|
||||
139
servers/slapd/back-bdb2/id2children.c
Normal file
139
servers/slapd/back-bdb2/id2children.c
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
/* id2children.c - routines to deal with the id2children index */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ac/string.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-bdb2.h"
|
||||
|
||||
int
|
||||
bdb2i_id2children_add(
|
||||
Backend *be,
|
||||
Entry *p,
|
||||
Entry *e
|
||||
)
|
||||
{
|
||||
struct dbcache *db;
|
||||
Datum key;
|
||||
int len, rc;
|
||||
ID_BLOCK *idl;
|
||||
char buf[20];
|
||||
|
||||
ldbm_datum_init( key );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> bdb2i_id2children_add( %lu, %lu )\n",
|
||||
p ? p->e_id : 0, e->e_id, 0 );
|
||||
|
||||
if ( (db = bdb2i_cache_open( be, "id2children", LDBM_SUFFIX,
|
||||
LDBM_WRCREAT )) == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"<= bdb2i_id2children_add -1 could not open \"id2children%s\"\n",
|
||||
LDBM_SUFFIX, 0, 0 );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
sprintf( buf, "%c%ld", EQ_PREFIX, p ? p->e_id : 0 );
|
||||
key.dptr = buf;
|
||||
key.dsize = strlen( buf ) + 1;
|
||||
|
||||
if ( bdb2i_idl_insert_key( be, db, key, e->e_id ) != 0 ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "<= bdb2i_id2children_add -1 (idl_insert)\n",
|
||||
0, 0, 0 );
|
||||
bdb2i_cache_close( be, db );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
bdb2i_cache_close( be, db );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= bdb2i_id2children_add 0\n", 0, 0, 0 );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
bdb2i_id2children_remove(
|
||||
Backend *be,
|
||||
Entry *p,
|
||||
Entry *e
|
||||
)
|
||||
{
|
||||
struct dbcache *db;
|
||||
Datum key;
|
||||
int len, rc;
|
||||
ID_BLOCK *idl;
|
||||
char buf[20];
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> bdb2i_id2children_remove( %lu, %lu )\n",
|
||||
p ? p->e_id : 0, e->e_id, 0 );
|
||||
|
||||
if ( (db = bdb2i_cache_open( be, "id2children", LDBM_SUFFIX,
|
||||
LDBM_WRCREAT )) == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"<= bdb2i_id2children_remove -1 could not open \"id2children%s\"\n",
|
||||
LDBM_SUFFIX, 0, 0 );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
ldbm_datum_init( key );
|
||||
sprintf( buf, "%c%ld", EQ_PREFIX, p ? p->e_id : 0 );
|
||||
key.dptr = buf;
|
||||
key.dsize = strlen( buf ) + 1;
|
||||
|
||||
if ( bdb2i_idl_delete_key( be, db, key, e->e_id ) != 0 ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "<= bdb2i_id2children_remove -1 (idl_delete)\n",
|
||||
0, 0, 0 );
|
||||
bdb2i_cache_close( be, db );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
bdb2i_cache_close( be, db );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= bdb2i_id2children_remove 0\n", 0, 0, 0 );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int
|
||||
bdb2i_has_children(
|
||||
Backend *be,
|
||||
Entry *p
|
||||
)
|
||||
{
|
||||
struct dbcache *db;
|
||||
Datum key;
|
||||
int rc = 0;
|
||||
ID_BLOCK *idl;
|
||||
char buf[20];
|
||||
|
||||
ldbm_datum_init( key );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> bdb2i_has_children( %lu )\n", p->e_id , 0, 0 );
|
||||
|
||||
if ( (db = bdb2i_cache_open( be, "id2children", LDBM_SUFFIX,
|
||||
LDBM_WRCREAT )) == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"<= bdb2i_has_children -1 could not open \"id2children%s\"\n",
|
||||
LDBM_SUFFIX, 0, 0 );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
sprintf( buf, "%c%ld", EQ_PREFIX, p->e_id );
|
||||
key.dptr = buf;
|
||||
key.dsize = strlen( buf ) + 1;
|
||||
|
||||
idl = bdb2i_idl_fetch( be, db, key );
|
||||
|
||||
bdb2i_cache_close( be, db );
|
||||
|
||||
if( idl != NULL ) {
|
||||
bdb2i_idl_free( idl );
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= bdb2i_has_children( %lu ): %s\n",
|
||||
p->e_id, rc ? "yes" : "no", 0 );
|
||||
return( rc );
|
||||
}
|
||||
174
servers/slapd/back-bdb2/id2entry.c
Normal file
174
servers/slapd/back-bdb2/id2entry.c
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
/* id2entry.c - routines to deal with the id2entry index */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-bdb2.h"
|
||||
|
||||
int
|
||||
bdb2i_id2entry_add( Backend *be, Entry *e )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
struct dbcache *db;
|
||||
Datum key, data;
|
||||
int len, rc, flags;
|
||||
|
||||
ldbm_datum_init( key );
|
||||
ldbm_datum_init( data );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> bdb2i_id2entry_add( %lu, \"%s\" )\n", e->e_id,
|
||||
e->e_dn, 0 );
|
||||
|
||||
if ( (db = bdb2i_cache_open( be, "id2entry", LDBM_SUFFIX, LDBM_WRCREAT ))
|
||||
== NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY, "Could not open/create id2entry%s\n",
|
||||
LDBM_SUFFIX, 0, 0 );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
key.dptr = (char *) &e->e_id;
|
||||
key.dsize = sizeof(ID);
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &entry2str_mutex );
|
||||
data.dptr = entry2str( e, &len, 1 );
|
||||
data.dsize = len + 1;
|
||||
|
||||
/* store it */
|
||||
flags = LDBM_REPLACE;
|
||||
if ( li->li_dbcachewsync ) flags |= LDBM_SYNC;
|
||||
rc = bdb2i_cache_store( db, key, data, flags );
|
||||
|
||||
ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
|
||||
|
||||
bdb2i_cache_close( be, db );
|
||||
(void) bdb2i_cache_add_entry_lock( &li->li_cache, e, 0 );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= bdb2i_id2entry_add %d\n", rc, 0, 0 );
|
||||
|
||||
/* XXX should entries be born locked, i.e. apply writer lock here? */
|
||||
return( rc );
|
||||
}
|
||||
|
||||
int
|
||||
bdb2i_id2entry_delete( Backend *be, Entry *e )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
struct dbcache *db;
|
||||
Datum key;
|
||||
int rc;
|
||||
|
||||
Debug(LDAP_DEBUG_TRACE, "=> bdb2i_id2entry_delete( %lu, \"%s\" )\n", e->e_id,
|
||||
e->e_dn, 0 );
|
||||
|
||||
#ifdef LDAP_DEBUG
|
||||
/* check for writer lock */
|
||||
assert(ldap_pvt_thread_rdwr_writers(&e->e_rdwr));
|
||||
#endif
|
||||
|
||||
ldbm_datum_init( key );
|
||||
|
||||
if ( (db = bdb2i_cache_open( be, "id2entry", LDBM_SUFFIX, LDBM_WRCREAT ))
|
||||
== NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY, "Could not open/create id2entry%s\n",
|
||||
LDBM_SUFFIX, 0, 0 );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if ( bdb2i_cache_delete_entry( &li->li_cache, e ) != 0 ) {
|
||||
Debug(LDAP_DEBUG_ANY, "could not delete %lu (%s) from cache\n",
|
||||
e->e_id, e->e_dn, 0 );
|
||||
}
|
||||
|
||||
key.dptr = (char *) &e->e_id;
|
||||
key.dsize = sizeof(ID);
|
||||
|
||||
rc = bdb2i_cache_delete( db, key );
|
||||
|
||||
bdb2i_cache_close( be, db );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= bdb2i_id2entry_delete %d\n", rc, 0, 0 );
|
||||
return( rc );
|
||||
}
|
||||
|
||||
/* XXX returns entry with reader/writer lock */
|
||||
Entry *
|
||||
bdb2i_id2entry( Backend *be, ID id, int rw )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
struct dbcache *db;
|
||||
Datum key, data;
|
||||
Entry *e;
|
||||
|
||||
ldbm_datum_init( key );
|
||||
ldbm_datum_init( data );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> bdb2i_id2entry_%s( %ld )\n",
|
||||
rw ? "w" : "r", id, 0 );
|
||||
|
||||
if ( (e = bdb2i_cache_find_entry_id( &li->li_cache, id, rw )) != NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "<= bdb2i_id2entry_%s 0x%lx (cache)\n",
|
||||
rw ? "w" : "r", (unsigned long)e, 0 );
|
||||
return( e );
|
||||
}
|
||||
|
||||
if ( (db = bdb2i_cache_open( be, "id2entry", LDBM_SUFFIX, LDBM_WRCREAT ))
|
||||
== NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY, "Could not open id2entry%s\n",
|
||||
LDBM_SUFFIX, 0, 0 );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
key.dptr = (char *) &id;
|
||||
key.dsize = sizeof(ID);
|
||||
|
||||
data = bdb2i_cache_fetch( db, key );
|
||||
|
||||
if ( data.dptr == NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "<= bdb2i_id2entry_%s( %ld ) not found\n",
|
||||
rw ? "w" : "r", id, 0 );
|
||||
bdb2i_cache_close( be, db );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
e = str2entry( data.dptr );
|
||||
|
||||
ldbm_datum_free( db->dbc_db, data );
|
||||
bdb2i_cache_close( be, db );
|
||||
|
||||
if ( e == NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "<= bdb2i_id2entry_%s( %ld ) (failed)\n",
|
||||
rw ? "w" : "r", id, 0 );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
/* acquire required reader/writer lock */
|
||||
if (entry_rdwr_lock(e, rw)) {
|
||||
/* XXX set DELETE flag?? */
|
||||
entry_free(e);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
e->e_id = id;
|
||||
(void) bdb2i_cache_add_entry_lock( &li->li_cache, e, 0 );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= bdb2i_id2entry_%s( %ld ) (disk)\n",
|
||||
rw ? "w" : "r", id, 0 );
|
||||
return( e );
|
||||
}
|
||||
|
||||
Entry *
|
||||
bdb2i_id2entry_r( Backend *be, ID id )
|
||||
{
|
||||
return( bdb2i_id2entry( be, id, 0 ) );
|
||||
}
|
||||
|
||||
Entry *
|
||||
bdb2i_id2entry_w( Backend *be, ID id )
|
||||
{
|
||||
return( bdb2i_id2entry( be, id, 1 ) );
|
||||
}
|
||||
|
||||
1032
servers/slapd/back-bdb2/idl.c
Normal file
1032
servers/slapd/back-bdb2/idl.c
Normal file
File diff suppressed because it is too large
Load diff
362
servers/slapd/back-bdb2/index.c
Normal file
362
servers/slapd/back-bdb2/index.c
Normal file
|
|
@ -0,0 +1,362 @@
|
|||
/* index.c - routines for dealing with attribute indexes */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-bdb2.h"
|
||||
|
||||
static int add_value(Backend *be, struct dbcache *db, char *type, int indextype, char *val, ID id);
|
||||
static int index2prefix(int indextype);
|
||||
|
||||
int
|
||||
bdb2i_index_add_entry(
|
||||
Backend *be,
|
||||
Entry *e
|
||||
)
|
||||
{
|
||||
Attribute *ap;
|
||||
char *dnval;
|
||||
struct berval bv;
|
||||
struct berval *bvals[2];
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> index_add( %ld, \"%s\" )\n", e->e_id,
|
||||
e->e_dn, 0 );
|
||||
|
||||
/*
|
||||
* dn index entry - make it look like an attribute so it works
|
||||
* with bdb2i_index_add_values() call
|
||||
*/
|
||||
|
||||
bv.bv_val = ch_strdup( e->e_dn );
|
||||
bv.bv_len = strlen( bv.bv_val );
|
||||
(void) dn_normalize_case( bv.bv_val );
|
||||
bvals[0] = &bv;
|
||||
bvals[1] = NULL;
|
||||
|
||||
/* add the dn to the indexes */
|
||||
bdb2i_index_add_values( be, "dn", bvals, e->e_id );
|
||||
|
||||
free( bv.bv_val );
|
||||
|
||||
/* add each attribute to the indexes */
|
||||
for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) {
|
||||
bdb2i_index_add_values( be, ap->a_type, ap->a_vals, e->e_id );
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= index_add( %ld, \"%s\" ) 0\n", e->e_id,
|
||||
e->e_dn, 0 );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int
|
||||
bdb2i_index_add_mods(
|
||||
Backend *be,
|
||||
LDAPModList *ml,
|
||||
ID id
|
||||
)
|
||||
{
|
||||
int rc;
|
||||
|
||||
for ( ; ml != NULL; ml = ml->ml_next ) {
|
||||
LDAPMod *mod = &ml->ml_mod;
|
||||
|
||||
switch ( mod->mod_op & ~LDAP_MOD_BVALUES ) {
|
||||
case LDAP_MOD_ADD:
|
||||
case LDAP_MOD_REPLACE:
|
||||
rc = bdb2i_index_add_values( be, mod->mod_type,
|
||||
mod->mod_bvalues, id );
|
||||
break;
|
||||
|
||||
case LDAP_MOD_DELETE:
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( rc != 0 ) {
|
||||
return( rc );
|
||||
}
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
ID_BLOCK *
|
||||
bdb2i_index_read(
|
||||
Backend *be,
|
||||
char *type,
|
||||
int indextype,
|
||||
char *val
|
||||
)
|
||||
{
|
||||
struct dbcache *db;
|
||||
Datum key;
|
||||
ID_BLOCK *idl;
|
||||
int indexmask, syntax;
|
||||
char prefix;
|
||||
char *realval, *tmpval;
|
||||
char buf[BUFSIZ];
|
||||
|
||||
ldbm_datum_init( key );
|
||||
|
||||
prefix = index2prefix( indextype );
|
||||
Debug( LDAP_DEBUG_TRACE, "=> bdb2i_index_read( \"%s\" \"%c\" \"%s\" )\n",
|
||||
type, prefix, val );
|
||||
|
||||
bdb2i_attr_masks( be->be_private, type, &indexmask, &syntax );
|
||||
if ( ! (indextype & indexmask) ) {
|
||||
idl = bdb2i_idl_allids( be );
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= bdb2i_index_read %lu candidates (allids - not indexed)\n",
|
||||
idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
|
||||
return( idl );
|
||||
}
|
||||
|
||||
attr_normalize( type );
|
||||
if ( (db = bdb2i_cache_open( be, type, LDBM_SUFFIX, LDBM_WRCREAT ))
|
||||
== NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"<= bdb2i_index_read NULL (could not open %s%s)\n", type,
|
||||
LDBM_SUFFIX, 0 );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
realval = val;
|
||||
tmpval = NULL;
|
||||
if ( prefix != UNKNOWN_PREFIX ) {
|
||||
unsigned int len = strlen( val );
|
||||
|
||||
if ( (len + 2) < sizeof(buf) ) {
|
||||
realval = buf;
|
||||
} else {
|
||||
/* value + prefix + null */
|
||||
tmpval = (char *) ch_malloc( len + 2 );
|
||||
realval = tmpval;
|
||||
}
|
||||
realval[0] = prefix;
|
||||
strcpy( &realval[1], val );
|
||||
}
|
||||
|
||||
key.dptr = realval;
|
||||
key.dsize = strlen( realval ) + 1;
|
||||
|
||||
idl = bdb2i_idl_fetch( be, db, key );
|
||||
if ( tmpval != NULL ) {
|
||||
free( tmpval );
|
||||
}
|
||||
|
||||
bdb2i_cache_close( be, db );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= bdb2i_index_read %lu candidates\n",
|
||||
idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
|
||||
return( idl );
|
||||
}
|
||||
|
||||
static int
|
||||
add_value(
|
||||
Backend *be,
|
||||
struct dbcache *db,
|
||||
char *type,
|
||||
int indextype,
|
||||
char *val,
|
||||
ID id
|
||||
)
|
||||
{
|
||||
int rc;
|
||||
Datum key;
|
||||
ID_BLOCK *idl;
|
||||
char prefix;
|
||||
char *realval, *tmpval, *s;
|
||||
char buf[BUFSIZ];
|
||||
|
||||
ldbm_datum_init( key );
|
||||
|
||||
prefix = index2prefix( indextype );
|
||||
Debug( LDAP_DEBUG_TRACE, "=> add_value( \"%c%s\" )\n", prefix, val, 0 );
|
||||
|
||||
realval = val;
|
||||
tmpval = NULL;
|
||||
idl = NULL;
|
||||
if ( prefix != UNKNOWN_PREFIX ) {
|
||||
unsigned int len = strlen( val );
|
||||
|
||||
if ( (len + 2) < sizeof(buf) ) {
|
||||
realval = buf;
|
||||
} else {
|
||||
/* value + prefix + null */
|
||||
tmpval = (char *) ch_malloc( len + 2 );
|
||||
realval = tmpval;
|
||||
}
|
||||
realval[0] = prefix;
|
||||
strcpy( &realval[1], val );
|
||||
}
|
||||
|
||||
key.dptr = realval;
|
||||
key.dsize = strlen( realval ) + 1;
|
||||
|
||||
rc = bdb2i_idl_insert_key( be, db, key, id );
|
||||
|
||||
if ( tmpval != NULL ) {
|
||||
free( tmpval );
|
||||
}
|
||||
bdb2i_idl_free( idl );
|
||||
|
||||
ldap_pvt_thread_yield();
|
||||
|
||||
/* Debug( LDAP_DEBUG_TRACE, "<= add_value %d\n", rc, 0, 0 ); */
|
||||
return( rc );
|
||||
}
|
||||
|
||||
int
|
||||
bdb2i_index_add_values(
|
||||
Backend *be,
|
||||
char *type,
|
||||
struct berval **vals,
|
||||
ID id
|
||||
)
|
||||
{
|
||||
char *val, *p, *code, *w;
|
||||
unsigned i, j, len;
|
||||
int indexmask, syntax;
|
||||
char buf[SUBLEN + 1];
|
||||
char vbuf[BUFSIZ];
|
||||
char *bigbuf;
|
||||
struct dbcache *db;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> bdb2i_index_add_values( \"%s\", %ld )\n", type,
|
||||
id, 0 );
|
||||
|
||||
bdb2i_attr_masks( be->be_private, type, &indexmask, &syntax );
|
||||
if ( indexmask == 0 ) {
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
if ( (db = bdb2i_cache_open( be, type, LDBM_SUFFIX, LDBM_WRCREAT ))
|
||||
== NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"<= bdb2i_index_add_values -1 (could not open/create %s%s)\n",
|
||||
type, LDBM_SUFFIX, 0 );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
for ( i = 0; vals[i] != NULL; i++ ) {
|
||||
/*
|
||||
* presence index entry
|
||||
*/
|
||||
if ( indexmask & INDEX_PRESENCE ) {
|
||||
add_value( be, db, type, INDEX_PRESENCE, "*", id );
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "*** bdb2i_index_add_values syntax 0x%x syntax bin 0x%x\n",
|
||||
syntax, SYNTAX_BIN, 0 );
|
||||
if ( syntax & SYNTAX_BIN ) {
|
||||
bdb2i_cache_close( be, db );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
bigbuf = NULL;
|
||||
len = vals[i]->bv_len;
|
||||
|
||||
/* value + null */
|
||||
if ( len + 2 > sizeof(vbuf) ) {
|
||||
bigbuf = (char *) ch_malloc( len + 1 );
|
||||
val = bigbuf;
|
||||
} else {
|
||||
val = vbuf;
|
||||
}
|
||||
(void) memcpy( val, vals[i]->bv_val, len );
|
||||
val[len] = '\0';
|
||||
|
||||
value_normalize( val, syntax );
|
||||
|
||||
/*
|
||||
* equality index entry
|
||||
*/
|
||||
if ( indexmask & INDEX_EQUALITY ) {
|
||||
add_value( be, db, type, INDEX_EQUALITY, val, id );
|
||||
}
|
||||
|
||||
/*
|
||||
* approximate index entry
|
||||
*/
|
||||
if ( indexmask & INDEX_APPROX ) {
|
||||
for ( w = first_word( val ); w != NULL;
|
||||
w = next_word( w ) ) {
|
||||
if ( (code = phonetic( w )) != NULL ) {
|
||||
add_value( be, db, type, INDEX_APPROX,
|
||||
code, id );
|
||||
free( code );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* substrings index entry
|
||||
*/
|
||||
if ( indexmask & INDEX_SUB ) {
|
||||
/* leading and trailing */
|
||||
if ( len > SUBLEN - 2 ) {
|
||||
buf[0] = '^';
|
||||
for ( j = 0; j < SUBLEN - 1; j++ ) {
|
||||
buf[j + 1] = val[j];
|
||||
}
|
||||
buf[SUBLEN] = '\0';
|
||||
|
||||
add_value( be, db, type, INDEX_SUB, buf, id );
|
||||
|
||||
p = val + len - SUBLEN + 1;
|
||||
for ( j = 0; j < SUBLEN - 1; j++ ) {
|
||||
buf[j] = p[j];
|
||||
}
|
||||
buf[SUBLEN - 1] = '$';
|
||||
buf[SUBLEN] = '\0';
|
||||
|
||||
add_value( be, db, type, INDEX_SUB, buf, id );
|
||||
}
|
||||
|
||||
/* any */
|
||||
for ( p = val; p < (val + len - SUBLEN + 1); p++ ) {
|
||||
for ( j = 0; j < SUBLEN; j++ ) {
|
||||
buf[j] = p[j];
|
||||
}
|
||||
buf[SUBLEN] = '\0';
|
||||
|
||||
add_value( be, db, type, INDEX_SUB, buf, id );
|
||||
}
|
||||
}
|
||||
|
||||
if ( bigbuf != NULL ) {
|
||||
free( bigbuf );
|
||||
}
|
||||
}
|
||||
bdb2i_cache_close( be, db );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
index2prefix( int indextype )
|
||||
{
|
||||
int prefix;
|
||||
|
||||
switch ( indextype ) {
|
||||
case INDEX_EQUALITY:
|
||||
prefix = EQ_PREFIX;
|
||||
break;
|
||||
case INDEX_APPROX:
|
||||
prefix = APPROX_PREFIX;
|
||||
break;
|
||||
case INDEX_SUB:
|
||||
prefix = SUB_PREFIX;
|
||||
break;
|
||||
default:
|
||||
prefix = UNKNOWN_PREFIX;
|
||||
break;
|
||||
}
|
||||
|
||||
return( prefix );
|
||||
}
|
||||
196
servers/slapd/back-bdb2/init.c
Normal file
196
servers/slapd/back-bdb2/init.c
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
/* init.c - initialize bdb2 backend */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-bdb2.h"
|
||||
|
||||
|
||||
int
|
||||
bdb2_back_initialize(
|
||||
BackendInfo *bi
|
||||
)
|
||||
{
|
||||
bi->bi_open = bdb2_back_open;
|
||||
bi->bi_config = NULL;
|
||||
bi->bi_close = bdb2_back_close;
|
||||
bi->bi_destroy = bdb2_back_destroy;
|
||||
|
||||
bi->bi_db_init = bdb2_back_db_init;
|
||||
bi->bi_db_config = bdb2_back_db_config;
|
||||
bi->bi_db_open = bdb2_back_db_open;
|
||||
bi->bi_db_close = bdb2_back_db_close;
|
||||
bi->bi_db_destroy = bdb2_back_db_destroy;
|
||||
|
||||
bi->bi_op_bind = bdb2_back_bind;
|
||||
bi->bi_op_unbind = bdb2_back_unbind;
|
||||
bi->bi_op_search = bdb2_back_search;
|
||||
bi->bi_op_compare = bdb2_back_compare;
|
||||
bi->bi_op_modify = bdb2_back_modify;
|
||||
bi->bi_op_modrdn = bdb2_back_modrdn;
|
||||
bi->bi_op_add = bdb2_back_add;
|
||||
bi->bi_op_delete = bdb2_back_delete;
|
||||
bi->bi_op_abandon = bdb2_back_abandon;
|
||||
|
||||
bi->bi_acl_group = bdb2_back_group;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
bdb2_back_destroy(
|
||||
BackendInfo *bi
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
bdb2_back_open(
|
||||
BackendInfo *bi
|
||||
)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* initialize the underlying database system */
|
||||
rc = bdb2_initialize();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
bdb2_back_close(
|
||||
BackendInfo *bi
|
||||
)
|
||||
{
|
||||
/* close the underlying database system */
|
||||
bdb2_shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* BDB2 changed */
|
||||
static int
|
||||
bdb2i_back_db_init_internal(
|
||||
Backend *be
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li;
|
||||
char *argv[ 4 ];
|
||||
int i;
|
||||
|
||||
/* allocate backend-specific stuff */
|
||||
li = (struct ldbminfo *) ch_calloc( 1, sizeof(struct ldbminfo) );
|
||||
|
||||
/* arrange to read nextid later (on first request for it) */
|
||||
li->li_nextid = NOID;
|
||||
#if SLAPD_NEXTID_CHUNCK > 1
|
||||
li->li_nextid_wrote = NOID
|
||||
#endif
|
||||
|
||||
/* default cache size */
|
||||
li->li_cache.c_maxsize = DEFAULT_CACHE_SIZE;
|
||||
|
||||
/* default database cache size */
|
||||
li->li_dbcachesize = DEFAULT_DBCACHE_SIZE;
|
||||
|
||||
/* default cache mode is sync on write */
|
||||
li->li_dbcachewsync = 1;
|
||||
|
||||
/* default file creation mode */
|
||||
li->li_mode = DEFAULT_MODE;
|
||||
|
||||
/* default database directory */
|
||||
li->li_directory = DEFAULT_DB_DIRECTORY;
|
||||
|
||||
/* always index dn, id2children, objectclass (used in some searches) */
|
||||
argv[ 0 ] = "dn";
|
||||
argv[ 1 ] = "dn";
|
||||
argv[ 2 ] = NULL;
|
||||
attr_syntax_config( "ldbm dn initialization", 0, 2, argv );
|
||||
argv[ 0 ] = "dn";
|
||||
argv[ 1 ] = "sub";
|
||||
argv[ 2 ] = "eq";
|
||||
argv[ 3 ] = NULL;
|
||||
bdb2i_attr_index_config( li, "ldbm dn initialization", 0, 3, argv, 1 );
|
||||
argv[ 0 ] = "id2children";
|
||||
argv[ 1 ] = "eq";
|
||||
argv[ 2 ] = NULL;
|
||||
bdb2i_attr_index_config( li, "ldbm id2children initialization", 0, 2, argv,
|
||||
1 );
|
||||
argv[ 0 ] = "objectclass";
|
||||
argv[ 1 ] = ch_strdup( "pres,eq" );
|
||||
argv[ 2 ] = NULL;
|
||||
bdb2i_attr_index_config( li, "ldbm objectclass initialization", 0, 2, argv,
|
||||
1 );
|
||||
free( argv[ 1 ] );
|
||||
|
||||
/* initialize various mutex locks & condition variables */
|
||||
ldap_pvt_thread_mutex_init( &li->li_root_mutex );
|
||||
ldap_pvt_thread_mutex_init( &li->li_add_mutex );
|
||||
ldap_pvt_thread_mutex_init( &li->li_cache.c_mutex );
|
||||
ldap_pvt_thread_mutex_init( &li->li_nextid_mutex );
|
||||
ldap_pvt_thread_mutex_init( &li->li_dbcache_mutex );
|
||||
ldap_pvt_thread_cond_init( &li->li_dbcache_cv );
|
||||
|
||||
/* initialize the TP file head */
|
||||
bdb2i_txn_head_init( &li->li_txn_head );
|
||||
|
||||
be->be_private = li;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
bdb2_back_db_init(
|
||||
Backend *be
|
||||
)
|
||||
{
|
||||
struct timeval time1, time2;
|
||||
char *elapsed_time;
|
||||
int ret;
|
||||
|
||||
gettimeofday( &time1, NULL );
|
||||
|
||||
ret = bdb2i_back_db_init_internal( be );
|
||||
|
||||
if ( bdb2i_do_timing ) {
|
||||
|
||||
gettimeofday( &time2, NULL);
|
||||
elapsed_time = bdb2i_elapsed( time1, time2 );
|
||||
Debug( LDAP_DEBUG_ANY, "INIT elapsed=%s\n",
|
||||
elapsed_time, 0, 0 );
|
||||
free( elapsed_time );
|
||||
|
||||
}
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
bdb2_back_db_open(
|
||||
BackendDB *be
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
bdb2_back_db_destroy(
|
||||
BackendDB *be
|
||||
)
|
||||
{
|
||||
/* should free/destroy every in be_private */
|
||||
free( be->be_private );
|
||||
be->be_private = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
48
servers/slapd/back-bdb2/kerberos.c
Normal file
48
servers/slapd/back-bdb2/kerberos.c
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/* kerberos.c - bdb2 backend kerberos bind routines */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#ifdef HAVE_KERBEROS
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/krb.h>
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-bdb2.h"
|
||||
|
||||
#define LDAP_KRB_PRINCIPAL "ldapserver"
|
||||
|
||||
extern char *ldap_srvtab;
|
||||
extern Attribute *attr_find();
|
||||
|
||||
bdb2i_krbv4_ldap_auth(
|
||||
Backend *be,
|
||||
struct berval *cred,
|
||||
AUTH_DAT *ad
|
||||
)
|
||||
{
|
||||
KTEXT_ST k;
|
||||
KTEXT ktxt = &k;
|
||||
char instance[INST_SZ];
|
||||
int err;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> kerberosv4_ldap_auth\n", 0, 0, 0 );
|
||||
|
||||
SAFEMEMCPY( ktxt->dat, cred->bv_val, cred->bv_len );
|
||||
ktxt->length = cred->bv_len;
|
||||
|
||||
strcpy( instance, "*" );
|
||||
if ( (err = krb_rd_req( ktxt, LDAP_KRB_PRINCIPAL, instance, 0L, ad,
|
||||
ldap_srvtab )) != KSUCCESS ) {
|
||||
Debug( LDAP_DEBUG_ANY, "krb_rd_req failed (%s)\n",
|
||||
krb_err_txt[err], 0, 0 );
|
||||
return( LDAP_INVALID_CREDENTIALS );
|
||||
}
|
||||
|
||||
return( LDAP_SUCCESS );
|
||||
}
|
||||
|
||||
#endif /* kerberos */
|
||||
264
servers/slapd/back-bdb2/modify.c
Normal file
264
servers/slapd/back-bdb2/modify.c
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
/* modify.c - bdb2 backend modify routine */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-bdb2.h"
|
||||
#include "proto-back-bdb2.h"
|
||||
|
||||
static int add_values(Entry *e, LDAPMod *mod, char *dn);
|
||||
static int delete_values(Entry *e, LDAPMod *mod, char *dn);
|
||||
static int replace_values(Entry *e, LDAPMod *mod, char *dn);
|
||||
|
||||
static int
|
||||
bdb2i_back_modify_internal(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
char *dn,
|
||||
LDAPModList *modlist
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
char *matched;
|
||||
LDAPModList *ml;
|
||||
Entry *e;
|
||||
int i, err;
|
||||
|
||||
Debug(LDAP_DEBUG_ARGS, "bdb2i_back_modify:\n", 0, 0, 0);
|
||||
|
||||
if ( (e = bdb2i_dn2entry_w( be, dn, &matched )) == NULL ) {
|
||||
send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched,
|
||||
NULL );
|
||||
if ( matched != NULL ) {
|
||||
free( matched );
|
||||
}
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if ( (err = acl_check_modlist( be, conn, op, e, modlist )) != LDAP_SUCCESS ) {
|
||||
send_ldap_result( conn, op, err, NULL, NULL );
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
for ( ml = modlist; ml != NULL; ml = ml->ml_next ) {
|
||||
LDAPMod *mod = &ml->ml_mod;
|
||||
|
||||
switch ( mod->mod_op & ~LDAP_MOD_BVALUES ) {
|
||||
case LDAP_MOD_ADD:
|
||||
err = add_values( e, mod, op->o_ndn );
|
||||
break;
|
||||
|
||||
case LDAP_MOD_DELETE:
|
||||
err = delete_values( e, mod, op->o_ndn );
|
||||
break;
|
||||
|
||||
case LDAP_MOD_REPLACE:
|
||||
err = replace_values( e, mod, op->o_ndn );
|
||||
break;
|
||||
}
|
||||
|
||||
if ( err != LDAP_SUCCESS ) {
|
||||
/* unlock entry, delete from cache */
|
||||
send_ldap_result( conn, op, err, NULL, NULL );
|
||||
goto error_return;
|
||||
}
|
||||
}
|
||||
|
||||
/* check that the entry still obeys the schema */
|
||||
if ( global_schemacheck && oc_schema_check( e ) != 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY, "entry failed schema check\n", 0, 0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, NULL, NULL );
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
/* check for abandon */
|
||||
ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
|
||||
if ( op->o_abandon ) {
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
|
||||
goto error_return;
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
|
||||
|
||||
/* modify indexes */
|
||||
if ( bdb2i_index_add_mods( be, modlist, e->e_id ) != 0 ) {
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
/* check for abandon */
|
||||
ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
|
||||
if ( op->o_abandon ) {
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
|
||||
goto error_return;
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
|
||||
|
||||
/* change the entry itself */
|
||||
if ( bdb2i_id2entry_add( be, e ) != 0 ) {
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
|
||||
bdb2i_cache_return_entry_w( &li->li_cache, e );
|
||||
return( 0 );
|
||||
|
||||
error_return:;
|
||||
bdb2i_cache_return_entry_w( &li->li_cache, e );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
bdb2_back_modify(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
char *dn,
|
||||
LDAPModList *modlist
|
||||
)
|
||||
{
|
||||
DB_LOCK lock;
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
|
||||
struct timeval time1, time2;
|
||||
char *elapsed_time;
|
||||
int ret;
|
||||
|
||||
gettimeofday( &time1, NULL );
|
||||
|
||||
if ( bdb2i_enter_backend_w( &li->li_db_env, &lock ) != 0 ) {
|
||||
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
|
||||
return( -1 );
|
||||
|
||||
}
|
||||
|
||||
/* check, if a new default attribute index will be created,
|
||||
in which case we have to open the index file BEFORE TP */
|
||||
if ( bdb2i_with_dbenv )
|
||||
bdb2i_check_default_attr_index_mod( li, modlist );
|
||||
|
||||
ret = bdb2i_back_modify_internal( be, conn, op, dn, modlist );
|
||||
|
||||
(void) bdb2i_leave_backend( &li->li_db_env, lock );
|
||||
|
||||
if ( bdb2i_do_timing ) {
|
||||
|
||||
gettimeofday( &time2, NULL);
|
||||
elapsed_time = bdb2i_elapsed( time1, time2 );
|
||||
Debug( LDAP_DEBUG_ANY, "conn=%d op=%d MOD elapsed=%s\n",
|
||||
conn->c_connid, op->o_opid, elapsed_time );
|
||||
free( elapsed_time );
|
||||
|
||||
}
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
add_values(
|
||||
Entry *e,
|
||||
LDAPMod *mod,
|
||||
char *dn
|
||||
)
|
||||
{
|
||||
int i;
|
||||
Attribute *a;
|
||||
|
||||
/* check if the values we're adding already exist */
|
||||
if ( (a = attr_find( e->e_attrs, mod->mod_type )) != NULL ) {
|
||||
for ( i = 0; mod->mod_bvalues[i] != NULL; i++ ) {
|
||||
if ( value_find( a->a_vals, mod->mod_bvalues[i],
|
||||
a->a_syntax, 3 ) == 0 ) {
|
||||
return( LDAP_TYPE_OR_VALUE_EXISTS );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* no - add them */
|
||||
if( attr_merge( e, mod->mod_type, mod->mod_bvalues ) != 0 ) {
|
||||
return( LDAP_CONSTRAINT_VIOLATION );
|
||||
}
|
||||
|
||||
return( LDAP_SUCCESS );
|
||||
}
|
||||
|
||||
static int
|
||||
delete_values(
|
||||
Entry *e,
|
||||
LDAPMod *mod,
|
||||
char *dn
|
||||
)
|
||||
{
|
||||
int i, j, k, found;
|
||||
Attribute *a;
|
||||
|
||||
/* delete the entire attribute */
|
||||
if ( mod->mod_bvalues == NULL ) {
|
||||
Debug( LDAP_DEBUG_ARGS, "removing entire attribute %s\n",
|
||||
mod->mod_type, 0, 0 );
|
||||
return( attr_delete( &e->e_attrs, mod->mod_type ) ?
|
||||
LDAP_NO_SUCH_ATTRIBUTE : LDAP_SUCCESS );
|
||||
}
|
||||
|
||||
/* delete specific values - find the attribute first */
|
||||
if ( (a = attr_find( e->e_attrs, mod->mod_type )) == NULL ) {
|
||||
Debug( LDAP_DEBUG_ARGS, "could not find attribute %s\n",
|
||||
mod->mod_type, 0, 0 );
|
||||
return( LDAP_NO_SUCH_ATTRIBUTE );
|
||||
}
|
||||
|
||||
/* find each value to delete */
|
||||
for ( i = 0; mod->mod_bvalues[i] != NULL; i++ ) {
|
||||
found = 0;
|
||||
for ( j = 0; a->a_vals[j] != NULL; j++ ) {
|
||||
if ( value_cmp( mod->mod_bvalues[i], a->a_vals[j],
|
||||
a->a_syntax, 3 ) != 0 ) {
|
||||
continue;
|
||||
}
|
||||
found = 1;
|
||||
|
||||
/* found a matching value - delete it */
|
||||
ber_bvfree( a->a_vals[j] );
|
||||
for ( k = j + 1; a->a_vals[k] != NULL; k++ ) {
|
||||
a->a_vals[k - 1] = a->a_vals[k];
|
||||
}
|
||||
a->a_vals[k - 1] = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* looked through them all w/o finding it */
|
||||
if ( ! found ) {
|
||||
Debug( LDAP_DEBUG_ARGS,
|
||||
"could not find value for attr %s\n",
|
||||
mod->mod_type, 0, 0 );
|
||||
return( LDAP_NO_SUCH_ATTRIBUTE );
|
||||
}
|
||||
}
|
||||
|
||||
return( LDAP_SUCCESS );
|
||||
}
|
||||
|
||||
static int
|
||||
replace_values(
|
||||
Entry *e,
|
||||
LDAPMod *mod,
|
||||
char *dn
|
||||
)
|
||||
{
|
||||
(void) attr_delete( &e->e_attrs, mod->mod_type );
|
||||
|
||||
if ( attr_merge( e, mod->mod_type, mod->mod_bvalues ) != 0 ) {
|
||||
return( LDAP_CONSTRAINT_VIOLATION );
|
||||
}
|
||||
|
||||
return( LDAP_SUCCESS );
|
||||
}
|
||||
237
servers/slapd/back-bdb2/modrdn.c
Normal file
237
servers/slapd/back-bdb2/modrdn.c
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
/* modrdn.c - bdb2 backend modrdn routine */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-bdb2.h"
|
||||
#include "proto-back-bdb2.h"
|
||||
|
||||
static int
|
||||
bdb2i_back_modrdn_internal(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
char *dn,
|
||||
char *newrdn,
|
||||
int deleteoldrdn
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
char *matched = NULL;
|
||||
char *p_dn = NULL, *p_ndn = NULL;
|
||||
char *new_dn = NULL, *new_ndn = NULL;
|
||||
char sep[2];
|
||||
Entry *e, *p = NULL;
|
||||
int rootlock = 0;
|
||||
int rc = -1;
|
||||
|
||||
/* get entry with writer lock */
|
||||
if ( (e = bdb2i_dn2entry_w( be, dn, &matched )) == NULL ) {
|
||||
send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, "" );
|
||||
if ( matched != NULL ) {
|
||||
free( matched );
|
||||
}
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
#ifdef SLAPD_CHILD_MODIFICATION_WITH_ENTRY_ACL
|
||||
/* check parent for "children" acl */
|
||||
if ( ! access_allowed( be, conn, op, e,
|
||||
"entry", NULL, ACL_WRITE ) )
|
||||
{
|
||||
Debug( LDAP_DEBUG_TRACE, "no access to entry\n", 0,
|
||||
0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
|
||||
"", "" );
|
||||
goto return_results;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( (p_ndn = dn_parent( be, e->e_ndn )) != NULL ) {
|
||||
/* parent + rdn + separator(s) + null */
|
||||
if( (p = bdb2i_dn2entry_w( be, p_ndn, &matched )) == NULL) {
|
||||
Debug( LDAP_DEBUG_TRACE, "parent does not exist\n",
|
||||
0, 0, 0);
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
|
||||
"", "");
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
#ifndef SLAPD_CHILD_MODIFICATION_WITH_ENTRY_ACL
|
||||
/* check parent for "children" acl */
|
||||
if ( ! access_allowed( be, conn, op, p,
|
||||
"children", NULL, ACL_WRITE ) )
|
||||
{
|
||||
Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
|
||||
0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
|
||||
"", "" );
|
||||
goto return_results;
|
||||
}
|
||||
#endif
|
||||
|
||||
p_dn = dn_parent( be, e->e_dn );
|
||||
new_dn = (char *) ch_malloc( strlen( p_dn ) + strlen( newrdn )
|
||||
+ 3 );
|
||||
if ( dn_type( e->e_dn ) == DN_X500 ) {
|
||||
strcpy( new_dn, newrdn );
|
||||
strcat( new_dn, ", " );
|
||||
strcat( new_dn, p_dn );
|
||||
} else {
|
||||
char *s;
|
||||
strcpy( new_dn, newrdn );
|
||||
s = strchr( newrdn, '\0' );
|
||||
s--;
|
||||
if ( *s != '.' && *s != '@' ) {
|
||||
if ( (s = strpbrk( dn, ".@" )) != NULL ) {
|
||||
sep[0] = *s;
|
||||
sep[1] = '\0';
|
||||
strcat( new_dn, sep );
|
||||
}
|
||||
}
|
||||
strcat( new_dn, p_dn );
|
||||
}
|
||||
|
||||
} else {
|
||||
/* no parent, modrdn entry directly under root */
|
||||
if( ! be_isroot( be, op->o_ndn ) ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "no parent & not root\n",
|
||||
0, 0, 0);
|
||||
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
|
||||
"", "");
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_lock(&li->li_root_mutex);
|
||||
rootlock = 1;
|
||||
|
||||
new_dn = ch_strdup( newrdn );
|
||||
}
|
||||
|
||||
new_ndn = dn_normalize_case( ch_strdup( new_dn ) );
|
||||
|
||||
if ( (bdb2i_dn2id ( be, new_ndn ) ) != NOID ) {
|
||||
send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, NULL, NULL );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
/* check for abandon */
|
||||
ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
|
||||
if ( op->o_abandon ) {
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
|
||||
goto return_results;
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
|
||||
|
||||
/* add new one */
|
||||
if ( bdb2i_dn2id_add( be, new_ndn, e->e_id ) != 0 ) {
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
/* delete old one */
|
||||
if ( bdb2i_dn2id_delete( be, e->e_ndn ) != 0 ) {
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
(void) bdb2i_cache_delete_entry( &li->li_cache, e );
|
||||
free( e->e_dn );
|
||||
free( e->e_ndn );
|
||||
e->e_dn = new_dn;
|
||||
e->e_ndn = new_ndn;
|
||||
|
||||
/* XXX
|
||||
* At some point here we need to update the attribute values in
|
||||
* the entry itself that were effected by this RDN change
|
||||
* (respecting the value of the deleteoldrdn parameter).
|
||||
*
|
||||
* Since the code to do this has not yet been written, treat this
|
||||
* omission as a (documented) bug.
|
||||
*/
|
||||
|
||||
/* id2entry index */
|
||||
if ( bdb2i_id2entry_add( be, e ) != 0 ) {
|
||||
entry_free( e );
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
|
||||
rc = 0;
|
||||
|
||||
return_results:
|
||||
if( new_dn != NULL ) free( new_dn );
|
||||
if( new_ndn != NULL ) free( new_ndn );
|
||||
if( p_dn != NULL ) free( p_dn );
|
||||
if( p_ndn != NULL ) free( p_ndn );
|
||||
|
||||
if( matched != NULL ) free( matched );
|
||||
|
||||
if( p != NULL ) {
|
||||
/* free parent and writer lock */
|
||||
bdb2i_cache_return_entry_w( &li->li_cache, p );
|
||||
|
||||
}
|
||||
|
||||
if ( rootlock ) {
|
||||
/* release root writer lock */
|
||||
ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
|
||||
}
|
||||
|
||||
/* free entry and writer lock */
|
||||
bdb2i_cache_return_entry_w( &li->li_cache, e );
|
||||
return( rc );
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
bdb2_back_modrdn(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
char *dn,
|
||||
char *newrdn,
|
||||
int deleteoldrdn
|
||||
)
|
||||
{
|
||||
DB_LOCK lock;
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
|
||||
struct timeval time1, time2;
|
||||
char *elapsed_time;
|
||||
int ret;
|
||||
|
||||
gettimeofday( &time1, NULL );
|
||||
|
||||
if ( bdb2i_enter_backend_w( &li->li_db_env, &lock ) != 0 ) {
|
||||
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
|
||||
return( -1 );
|
||||
|
||||
}
|
||||
|
||||
ret = bdb2i_back_modrdn_internal( be, conn, op, dn,
|
||||
newrdn, deleteoldrdn );
|
||||
|
||||
(void) bdb2i_leave_backend( &li->li_db_env, lock );
|
||||
|
||||
if ( bdb2i_do_timing ) {
|
||||
|
||||
gettimeofday( &time2, NULL);
|
||||
elapsed_time = bdb2i_elapsed( time1, time2 );
|
||||
Debug( LDAP_DEBUG_ANY, "conn=%d op=%d MODRDN elapsed=%s\n",
|
||||
conn->c_connid, op->o_opid, elapsed_time );
|
||||
free( elapsed_time );
|
||||
|
||||
}
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
|
||||
184
servers/slapd/back-bdb2/nextid.c
Normal file
184
servers/slapd/back-bdb2/nextid.c
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
/* id.c - keep track of the next id to be given out */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
|
||||
#ifdef HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-bdb2.h"
|
||||
|
||||
static ID
|
||||
next_id_read( Backend *be )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
ID id;
|
||||
char buf[20];
|
||||
char* file = li->li_nextid_file;
|
||||
FILE* fp;
|
||||
|
||||
if ( (fp = fopen( file, "r" )) == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"next_id_read: could not open \"%s\"\n",
|
||||
file, 0, 0 );
|
||||
return NOID;
|
||||
}
|
||||
|
||||
if ( fgets( buf, sizeof(buf), fp ) == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"next_id_read: could not fgets nextid from \"%s\"\n",
|
||||
file, 0, 0 );
|
||||
fclose( fp );
|
||||
return NOID;
|
||||
}
|
||||
|
||||
id = atol( buf );
|
||||
fclose( fp );
|
||||
|
||||
if(id < 1) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"next_id_read %lu: atol(%s) return non-positive integer\n",
|
||||
id, buf, 0 );
|
||||
return NOID;
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
static int
|
||||
next_id_write( Backend *be, ID id )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
char buf[20];
|
||||
char* file = li->li_nextid_file;
|
||||
FILE* fp;
|
||||
int rc;
|
||||
|
||||
if ( (fp = fopen( file, "w" )) == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY, "next_id_write(%lu): could not open \"%s\"\n",
|
||||
id, file, 0 );
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
|
||||
if ( fprintf( fp, "%ld\n", id ) == EOF ) {
|
||||
Debug( LDAP_DEBUG_ANY, "next_id_write(%lu): cannot fprintf\n",
|
||||
id, 0, 0 );
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
if( fclose( fp ) != 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY, "next_id_write %lu: cannot fclose\n",
|
||||
id, 0, 0 );
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
bdb2i_next_id_save( Backend *be )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
ID id = next_id_get( be );
|
||||
int rc = next_id_write( be, id );
|
||||
|
||||
if (rc == 0) {
|
||||
li->li_nextid_wrote = id;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
ID
|
||||
bdb2i_next_id( Backend *be )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
ID id;
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &li->li_nextid_mutex );
|
||||
|
||||
/* first time in here since startup - try to read the nexid */
|
||||
if ( li->li_nextid == NOID ) {
|
||||
li->li_nextid = next_id_read( be );
|
||||
|
||||
if ( li->li_nextid == NOID ) {
|
||||
li->li_nextid = 1;
|
||||
}
|
||||
|
||||
#if SLAPD_NEXTID_CHUNK > 1
|
||||
li->li_nextid_wrote = li->li_nextid;
|
||||
#endif
|
||||
}
|
||||
|
||||
id = li->li_nextid++;
|
||||
|
||||
#if SLAPD_NEXTID_CHUNK > 1
|
||||
if ( li->li_nextid > li->li_nextid_wrote ) {
|
||||
li->li_nextid_wrote += SLAPD_NEXTID_CHUNK;
|
||||
(void) next_id_write( be, li->li_nextid_wrote );
|
||||
}
|
||||
#else
|
||||
(void) next_id_write( be, li->li_nextid );
|
||||
#endif
|
||||
|
||||
ldap_pvt_thread_mutex_unlock( &li->li_nextid_mutex );
|
||||
return( id );
|
||||
}
|
||||
|
||||
void
|
||||
bdb2i_next_id_return( Backend *be, ID id )
|
||||
{
|
||||
#ifdef SLAPD_NEXTID_RETURN
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &li->li_nextid_mutex );
|
||||
|
||||
if ( id != li->li_nextid - 1 ) {
|
||||
ldap_pvt_thread_mutex_unlock( &li->li_nextid_mutex );
|
||||
return;
|
||||
}
|
||||
|
||||
li->li_nextid--;
|
||||
|
||||
#if !( SLAPD_NEXTID_CHUCK > 1 )
|
||||
(void) next_id_write( be, li->li_nextid );
|
||||
#endif
|
||||
|
||||
ldap_pvt_thread_mutex_unlock( &li->li_nextid_mutex );
|
||||
#endif
|
||||
}
|
||||
|
||||
ID
|
||||
bdb2i_next_id_get( Backend *be )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
ID id;
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &li->li_nextid_mutex );
|
||||
|
||||
/* first time in here since startup - try to read the nexid */
|
||||
if ( li->li_nextid == NOID ) {
|
||||
li->li_nextid = next_id_read( be );
|
||||
|
||||
if ( li->li_nextid == NOID ) {
|
||||
li->li_nextid = 1;
|
||||
}
|
||||
|
||||
#if SLAPD_NEXTID_CHUNK > 1
|
||||
li->li_nextid_wrote = li->li_nextid;
|
||||
#endif
|
||||
}
|
||||
|
||||
id = li->li_nextid;
|
||||
|
||||
ldap_pvt_thread_mutex_unlock( &li->li_nextid_mutex );
|
||||
|
||||
return( id );
|
||||
}
|
||||
127
servers/slapd/back-bdb2/porter.c
Normal file
127
servers/slapd/back-bdb2/porter.c
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
/* porter.c - port functions of the bdb2 backend */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-bdb2.h"
|
||||
|
||||
#define PORTER_OBJ "bdb2_backend"
|
||||
|
||||
int bdb2i_with_dbenv = 0;
|
||||
|
||||
|
||||
static int
|
||||
bdb2i_enter_backend( DB_ENV *dbEnv, DB_LOCK *lock, int writer )
|
||||
{
|
||||
u_int32_t locker;
|
||||
db_lockmode_t lock_type;
|
||||
DBT lock_dbt;
|
||||
int ret;
|
||||
|
||||
if ( !bdb2i_with_dbenv ) return( 0 );
|
||||
|
||||
if ( ( ret = lock_id( dbEnv->lk_info, &locker )) != 0 ) {
|
||||
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"bdb2i_enter_backend(): unable to get locker id -- %s\n",
|
||||
strerror( ret ), 0, 0 );
|
||||
return( ret );
|
||||
|
||||
}
|
||||
|
||||
lock_type = writer ? DB_LOCK_WRITE : DB_LOCK_READ;
|
||||
lock_dbt.data = PORTER_OBJ;
|
||||
lock_dbt.size = strlen( PORTER_OBJ );
|
||||
|
||||
switch ( ( ret = lock_get( dbEnv->lk_info, locker, 0, &lock_dbt,
|
||||
lock_type, lock ))) {
|
||||
|
||||
case 0:
|
||||
Debug( LDAP_DEBUG_ANY, "bdb2i_enter_backend() -- %s lock granted\n",
|
||||
writer ? "write" : "read", 0, 0 );
|
||||
break;
|
||||
|
||||
case DB_LOCK_NOTGRANTED:
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"bdb2i_enter_backend() -- %s lock NOT granted\n",
|
||||
writer ? "write" : "read", 0, 0 );
|
||||
break;
|
||||
|
||||
case DB_LOCK_DEADLOCK:
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"bdb2i_enter_backend() -- %s lock returned DEADLOCK\n",
|
||||
writer ? "write" : "read", 0, 0 );
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"bdb2i_enter_backend() -- %s lock returned ERROR: %s\n",
|
||||
writer ? "write" : "read", strerror( errno ), 0 );
|
||||
ret = errno;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
bdb2i_enter_backend_r( DB_ENV *dbEnv, DB_LOCK *lock )
|
||||
{
|
||||
return( bdb2i_enter_backend( dbEnv, lock, 0 ));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
bdb2i_enter_backend_w( DB_ENV *dbEnv, DB_LOCK *lock )
|
||||
{
|
||||
return( bdb2i_enter_backend( dbEnv, lock, 1 ));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
bdb2i_leave_backend( DB_ENV *dbEnv, DB_LOCK lock )
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ( !bdb2i_with_dbenv ) return( 0 );
|
||||
|
||||
switch( ( ret = lock_put( dbEnv->lk_info, lock ))) {
|
||||
|
||||
case 0:
|
||||
Debug( LDAP_DEBUG_ANY, "bdb2i_leave_backend() -- lock released\n",
|
||||
0, 0, 0 );
|
||||
break;
|
||||
|
||||
case DB_LOCK_NOTHELD:
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"bdb2i_leave_backend() -- lock NOT held\n",
|
||||
0, 0, 0 );
|
||||
break;
|
||||
|
||||
case DB_LOCK_DEADLOCK:
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"bdb2i_leave_backend() -- lock returned DEADLOCK\n",
|
||||
0, 0, 0 );
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"bdb2i_leave_backend() -- lock returned ERROR: %s\n",
|
||||
strerror( errno ), 0, 0 );
|
||||
ret = errno;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return( ret );
|
||||
|
||||
}
|
||||
|
||||
|
||||
177
servers/slapd/back-bdb2/proto-back-bdb2.h
Normal file
177
servers/slapd/back-bdb2/proto-back-bdb2.h
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
#ifndef _PROTO_BACK_BDB2
|
||||
#define _PROTO_BACK_BDB2
|
||||
|
||||
#include <ldap_cdefs.h>
|
||||
|
||||
#include "external.h"
|
||||
|
||||
LDAP_BEGIN_DECL
|
||||
|
||||
/*
|
||||
* alias.c
|
||||
*/
|
||||
Entry *bdb2i_derefAlias_r LDAP_P((
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
Entry *e ));
|
||||
char *bdb2i_derefDN LDAP_P((
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
char *dn ));
|
||||
|
||||
/*
|
||||
* attr.c
|
||||
*/
|
||||
|
||||
void bdb2i_attr_masks LDAP_P(( struct ldbminfo *li, char *type, int *indexmask,
|
||||
int *syntaxmask ));
|
||||
void bdb2i_attr_index_config LDAP_P(( struct ldbminfo *li, char *fname,
|
||||
int lineno, int argc, char **argv, int init ));
|
||||
|
||||
/*
|
||||
* cache.c
|
||||
*/
|
||||
|
||||
void bdb2i_cache_set_state LDAP_P(( struct cache *cache, Entry *e, int state ));
|
||||
void bdb2i_cache_return_entry_r LDAP_P(( struct cache *cache, Entry *e ));
|
||||
void bdb2i_cache_return_entry_w LDAP_P(( struct cache *cache, Entry *e ));
|
||||
int bdb2i_cache_add_entry_lock LDAP_P(( struct cache *cache, Entry *e,
|
||||
int state ));
|
||||
ID bdb2i_cache_find_entry_dn2id LDAP_P(( Backend *be, struct cache *cache,
|
||||
char *dn ));
|
||||
Entry * bdb2i_cache_find_entry_id LDAP_P(( struct cache *cache, ID id, int rw ));
|
||||
int bdb2i_cache_delete_entry LDAP_P(( struct cache *cache, Entry *e ));
|
||||
|
||||
/*
|
||||
* dbcache.c
|
||||
*/
|
||||
|
||||
struct dbcache * bdb2i_cache_open LDAP_P(( Backend *be, char *name, char *suffix,
|
||||
int flags ));
|
||||
void bdb2i_cache_close LDAP_P(( Backend *be, struct dbcache *db ));
|
||||
void bdb2i_cache_really_close LDAP_P(( Backend *be, struct dbcache *db ));
|
||||
void bdb2i_cache_flush_all LDAP_P(( Backend *be ));
|
||||
Datum bdb2i_cache_fetch LDAP_P(( struct dbcache *db, Datum key ));
|
||||
int bdb2i_cache_store LDAP_P(( struct dbcache *db, Datum key, Datum data, int flags ));
|
||||
int bdb2i_cache_delete LDAP_P(( struct dbcache *db, Datum key ));
|
||||
|
||||
/*
|
||||
* dn2id.c
|
||||
*/
|
||||
|
||||
int bdb2i_dn2id_add LDAP_P(( Backend *be, char *dn, ID id ));
|
||||
ID bdb2i_dn2id LDAP_P(( Backend *be, char *dn ));
|
||||
int bdb2i_dn2id_delete LDAP_P(( Backend *be, char *dn ));
|
||||
Entry * bdb2i_dn2entry_r LDAP_P(( Backend *be, char *dn, char **matched ));
|
||||
Entry * bdb2i_dn2entry_w LDAP_P(( Backend *be, char *dn, char **matched ));
|
||||
|
||||
/*
|
||||
* filterindex.c
|
||||
*/
|
||||
|
||||
ID_BLOCK * bdb2i_filter_candidates LDAP_P(( Backend *be, Filter *f ));
|
||||
|
||||
/*
|
||||
* id2children.c
|
||||
*/
|
||||
|
||||
int bdb2i_id2children_add LDAP_P(( Backend *be, Entry *p, Entry *e ));
|
||||
int bdb2i_id2children_remove LDAP_P(( Backend *be, Entry *p, Entry *e ));
|
||||
int bdb2i_has_children LDAP_P(( Backend *be, Entry *p ));
|
||||
|
||||
/*
|
||||
* id2entry.c
|
||||
*/
|
||||
|
||||
int bdb2i_id2entry_add LDAP_P(( Backend *be, Entry *e ));
|
||||
int bdb2i_id2entry_delete LDAP_P(( Backend *be, Entry *e ));
|
||||
Entry * bdb2i_id2entry LDAP_P(( Backend *be, ID id, int rw ));
|
||||
Entry * bdb2i_id2entry_r LDAP_P(( Backend *be, ID id ));
|
||||
Entry * bdb2i_id2entry_w LDAP_P(( Backend *be, ID id ));
|
||||
|
||||
/*
|
||||
* idl.c
|
||||
*/
|
||||
|
||||
ID_BLOCK * bdb2i_idl_alloc LDAP_P(( int nids ));
|
||||
ID_BLOCK * bdb2i_idl_allids LDAP_P(( Backend *be ));
|
||||
void bdb2i_idl_free LDAP_P(( ID_BLOCK *idl ));
|
||||
ID_BLOCK * bdb2i_idl_fetch LDAP_P(( Backend *be, struct dbcache *db, Datum key ));
|
||||
int bdb2i_idl_insert_key LDAP_P(( Backend *be, struct dbcache *db, Datum key, ID id ));
|
||||
int bdb2i_idl_insert LDAP_P(( ID_BLOCK **idl, ID id, int maxids ));
|
||||
int bdb2i_idl_delete_key LDAP_P(( Backend *be, struct dbcache *db, Datum key, ID id ));
|
||||
ID_BLOCK * bdb2i_idl_intersection LDAP_P(( Backend *be, ID_BLOCK *a, ID_BLOCK *b ));
|
||||
ID_BLOCK * bdb2i_idl_union LDAP_P(( Backend *be, ID_BLOCK *a, ID_BLOCK *b ));
|
||||
ID_BLOCK * bdb2i_idl_notin LDAP_P(( Backend *be, ID_BLOCK *a, ID_BLOCK *b ));
|
||||
ID bdb2i_idl_firstid LDAP_P(( ID_BLOCK *idl ));
|
||||
ID bdb2i_idl_nextid LDAP_P(( ID_BLOCK *idl, ID id ));
|
||||
|
||||
/*
|
||||
* index.c
|
||||
*/
|
||||
|
||||
int bdb2i_index_add_entry LDAP_P(( Backend *be, Entry *e ));
|
||||
int bdb2i_index_add_mods LDAP_P(( Backend *be, LDAPModList *ml, ID id ));
|
||||
ID_BLOCK * bdb2i_index_read LDAP_P(( Backend *be, char *type, int indextype, char *val ));
|
||||
int bdb2i_index_add_values LDAP_P(( Backend *be, char *type, struct berval **vals, ID id ));
|
||||
|
||||
/*
|
||||
* kerberos.c
|
||||
*/
|
||||
|
||||
#ifdef HAVE_KERBEROS
|
||||
/* bdb2i_krbv4_ldap_auth LDAP_P(( Backend *be, struct berval *cred, AUTH_DAT *ad )); */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* nextid.c
|
||||
*/
|
||||
|
||||
ID bdb2i_next_id LDAP_P(( Backend *be ));
|
||||
void bdb2i_next_id_return LDAP_P(( Backend *be, ID id ));
|
||||
ID bdb2i_next_id_get LDAP_P(( Backend *be ));
|
||||
int bdb2i_next_id_save LDAP_P(( Backend *be ));
|
||||
|
||||
/*
|
||||
* timing.c
|
||||
*/
|
||||
|
||||
char *bdb2i_elapsed LDAP_P(( struct timeval firsttime,
|
||||
struct timeval secondtime ));
|
||||
|
||||
/*
|
||||
* porter.c
|
||||
*/
|
||||
|
||||
int bdb2i_enter_backend_r LDAP_P(( DB_ENV *dbEnv, DB_LOCK *lock ));
|
||||
int bdb2i_enter_backend_w LDAP_P(( DB_ENV *dbEnv, DB_LOCK *lock ));
|
||||
int bdb2i_leave_backend LDAP_P(( DB_ENV *dbEnv, DB_LOCK lock ));
|
||||
|
||||
/*
|
||||
* txn.c
|
||||
*/
|
||||
|
||||
void bdb2i_txn_head_init LDAP_P(( BDB2_TXN_HEAD *head ));
|
||||
void bdb2i_txn_attr_config LDAP_P((
|
||||
struct ldbminfo *li,
|
||||
char *attr,
|
||||
int open ));
|
||||
void bdb2i_txn_open_files LDAP_P(( struct ldbminfo *li ));
|
||||
void bdb2i_txn_close_files LDAP_P(( BDB2_TXN_HEAD *head ));
|
||||
BDB2_TXN_FILES *bdb2i_get_db_file_cache LDAP_P((
|
||||
struct ldbminfo *li,
|
||||
char *name ));
|
||||
void bdb2i_check_additional_attr_index LDAP_P(( struct ldbminfo *li ));
|
||||
void bdb2i_check_default_attr_index_add LDAP_P((
|
||||
struct ldbminfo *li,
|
||||
Entry *e ));
|
||||
void bdb2i_check_default_attr_index_mod LDAP_P((
|
||||
struct ldbminfo *li,
|
||||
LDAPModList *modlist ));
|
||||
|
||||
|
||||
|
||||
LDAP_END_DECL
|
||||
#endif
|
||||
559
servers/slapd/back-bdb2/search.c
Normal file
559
servers/slapd/back-bdb2/search.c
Normal file
|
|
@ -0,0 +1,559 @@
|
|||
/* search.c - bdb2 backend search function */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-bdb2.h"
|
||||
#include "proto-back-bdb2.h"
|
||||
|
||||
static ID_BLOCK *base_candidates(Backend *be, Connection *conn, Operation *op, char *base, Filter *filter, char **attrs, int attrsonly, char **matched, int *err);
|
||||
static ID_BLOCK *onelevel_candidates(Backend *be, Connection *conn, Operation *op, char *base, Filter *filter, char **attrs, int attrsonly, char **matched, int *err);
|
||||
static ID_BLOCK *subtree_candidates(Backend *be, Connection *conn, Operation *op, char *base, Filter *filter, char **attrs, int attrsonly, char **matched, Entry *e, int *err, int lookupbase);
|
||||
|
||||
#define GRABSIZE BUFSIZ
|
||||
|
||||
#define MAKE_SPACE( n ) { \
|
||||
if ( rcur + n > rbuf + rmaxsize ) { \
|
||||
int offset = rcur - rbuf; \
|
||||
rbuf = ch_realloc( rbuf, rmaxsize + GRABSIZE ); \
|
||||
rmaxsize += GRABSIZE; \
|
||||
rcur = rbuf + offset; \
|
||||
} \
|
||||
}
|
||||
|
||||
static int
|
||||
bdb2i_back_search_internal(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
char *base,
|
||||
int scope,
|
||||
int deref,
|
||||
int slimit,
|
||||
int tlimit,
|
||||
Filter *filter,
|
||||
char *filterstr,
|
||||
char **attrs,
|
||||
int attrsonly
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
int err;
|
||||
time_t stoptime;
|
||||
ID_BLOCK *candidates;
|
||||
ID id;
|
||||
Entry *e;
|
||||
Attribute *ref;
|
||||
char *matched = NULL;
|
||||
int rmaxsize, nrefs;
|
||||
char *rbuf, *rcur, *r;
|
||||
int nentries = 0;
|
||||
char *realBase;
|
||||
|
||||
Debug(LDAP_DEBUG_ARGS, "=> bdb2i_back_search\n", 0, 0, 0);
|
||||
|
||||
if ( tlimit == 0 && be_isroot( be, op->o_ndn ) ) {
|
||||
tlimit = -1; /* allow root to set no limit */
|
||||
} else {
|
||||
tlimit = (tlimit > be->be_timelimit || tlimit < 1) ?
|
||||
be->be_timelimit : tlimit;
|
||||
stoptime = op->o_time + tlimit;
|
||||
}
|
||||
if ( slimit == 0 && be_isroot( be, op->o_ndn ) ) {
|
||||
slimit = -1; /* allow root to set no limit */
|
||||
} else {
|
||||
slimit = (slimit > be->be_sizelimit || slimit < 1) ?
|
||||
be->be_sizelimit : slimit;
|
||||
}
|
||||
|
||||
/*
|
||||
* check and apply aliasing where the dereferencing applies to
|
||||
* the subordinates of the base
|
||||
*/
|
||||
|
||||
switch ( deref ) {
|
||||
case LDAP_DEREF_FINDING:
|
||||
case LDAP_DEREF_ALWAYS:
|
||||
realBase = bdb2i_derefDN ( be, conn, op, base );
|
||||
break;
|
||||
default:
|
||||
realBase = ch_strdup(base);
|
||||
}
|
||||
|
||||
(void) dn_normalize_case( realBase );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "using base \"%s\"\n",
|
||||
realBase, 0, 0 );
|
||||
|
||||
switch ( scope ) {
|
||||
case LDAP_SCOPE_BASE:
|
||||
candidates = base_candidates( be, conn, op, realBase, filter,
|
||||
attrs, attrsonly, &matched, &err );
|
||||
break;
|
||||
|
||||
case LDAP_SCOPE_ONELEVEL:
|
||||
candidates = onelevel_candidates( be, conn, op, realBase, filter,
|
||||
attrs, attrsonly, &matched, &err );
|
||||
break;
|
||||
|
||||
case LDAP_SCOPE_SUBTREE:
|
||||
candidates = subtree_candidates( be, conn, op, realBase, filter,
|
||||
attrs, attrsonly, &matched, NULL, &err, 1 );
|
||||
break;
|
||||
|
||||
default:
|
||||
send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, "",
|
||||
"Bad scope" );
|
||||
if( realBase != NULL) {
|
||||
free( realBase );
|
||||
}
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* null candidates means we could not find the base object */
|
||||
if ( candidates == NULL ) {
|
||||
send_ldap_result( conn, op, err, matched, "" );
|
||||
if ( matched != NULL ) {
|
||||
free( matched );
|
||||
}
|
||||
if( realBase != NULL) {
|
||||
free( realBase );
|
||||
}
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if ( matched != NULL ) {
|
||||
free( matched );
|
||||
}
|
||||
|
||||
rmaxsize = 0;
|
||||
nrefs = 0;
|
||||
rbuf = rcur = NULL;
|
||||
MAKE_SPACE( sizeof("Referral:") + 1 );
|
||||
strcpy( rbuf, "Referral:" );
|
||||
rcur = strchr( rbuf, '\0' );
|
||||
for ( id = bdb2i_idl_firstid( candidates ); id != NOID;
|
||||
id = bdb2i_idl_nextid( candidates, id ) ) {
|
||||
/* check for abandon */
|
||||
ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
|
||||
if ( op->o_abandon ) {
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
|
||||
bdb2i_idl_free( candidates );
|
||||
free( rbuf );
|
||||
if( realBase != NULL) {
|
||||
free( realBase );
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
|
||||
|
||||
/* check time limit */
|
||||
ldap_pvt_thread_mutex_lock( ¤ttime_mutex );
|
||||
time( ¤ttime );
|
||||
if ( tlimit != -1 && currenttime > stoptime ) {
|
||||
ldap_pvt_thread_mutex_unlock( ¤ttime_mutex );
|
||||
send_ldap_search_result( conn, op,
|
||||
LDAP_TIMELIMIT_EXCEEDED, NULL, nrefs > 0 ? rbuf :
|
||||
NULL, nentries );
|
||||
bdb2i_idl_free( candidates );
|
||||
free( rbuf );
|
||||
if( realBase != NULL) {
|
||||
free( realBase );
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( ¤ttime_mutex );
|
||||
|
||||
/* get the entry with reader lock */
|
||||
if ( (e = bdb2i_id2entry_r( be, id )) == NULL ) {
|
||||
Debug( LDAP_DEBUG_ARGS, "candidate %lu not found\n",
|
||||
id, 0, 0 );
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* if it's a referral, add it to the list of referrals. only do
|
||||
* this for subtree searches, and don't check the filter explicitly
|
||||
* here since it's only a candidate anyway.
|
||||
*/
|
||||
if ( scope == LDAP_SCOPE_SUBTREE &&
|
||||
e->e_ndn != NULL &&
|
||||
strncmp( e->e_ndn, "REF=", 4 ) == 0 &&
|
||||
(ref = attr_find( e->e_attrs, "ref" )) != NULL )
|
||||
{
|
||||
int i, len;
|
||||
|
||||
if ( ref->a_vals == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY, "null ref in (%s)\n",
|
||||
e->e_dn, 0, 0 );
|
||||
} else {
|
||||
for ( i = 0; ref->a_vals[i] != NULL; i++ ) {
|
||||
/* referral + newline + null */
|
||||
MAKE_SPACE( ref->a_vals[i]->bv_len + 2 );
|
||||
*rcur++ = '\n';
|
||||
strncpy( rcur, ref->a_vals[i]->bv_val,
|
||||
ref->a_vals[i]->bv_len );
|
||||
rcur = rcur + ref->a_vals[i]->bv_len;
|
||||
*rcur = '\0';
|
||||
nrefs++;
|
||||
}
|
||||
}
|
||||
|
||||
/* otherwise it's an entry - see if it matches the filter */
|
||||
} else {
|
||||
/* if it matches the filter and scope, send it */
|
||||
if ( test_filter( be, conn, op, e, filter ) == 0 ) {
|
||||
int scopeok;
|
||||
char *dn;
|
||||
|
||||
/* check scope */
|
||||
scopeok = 1;
|
||||
if ( scope == LDAP_SCOPE_ONELEVEL ) {
|
||||
if ( (dn = dn_parent( be, e->e_dn )) != NULL ) {
|
||||
(void) dn_normalize_case( dn );
|
||||
scopeok = (dn == realBase)
|
||||
? 1
|
||||
: (strcmp( dn, realBase ) ? 0 : 1 );
|
||||
free( dn );
|
||||
} else {
|
||||
scopeok = (realBase == NULL || *realBase == '\0');
|
||||
}
|
||||
} else if ( scope == LDAP_SCOPE_SUBTREE ) {
|
||||
dn = ch_strdup( e->e_ndn );
|
||||
scopeok = dn_issuffix( dn, realBase );
|
||||
free( dn );
|
||||
}
|
||||
|
||||
if ( scopeok ) {
|
||||
/* check size limit */
|
||||
if ( --slimit == -1 ) {
|
||||
bdb2i_cache_return_entry_r( &li->li_cache, e );
|
||||
send_ldap_search_result( conn, op,
|
||||
LDAP_SIZELIMIT_EXCEEDED, NULL,
|
||||
nrefs > 0 ? rbuf : NULL, nentries );
|
||||
bdb2i_idl_free( candidates );
|
||||
free( rbuf );
|
||||
|
||||
if( realBase != NULL) {
|
||||
free( realBase );
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* check and apply aliasing where the dereferencing applies to
|
||||
* the subordinates of the base
|
||||
*/
|
||||
switch ( deref ) {
|
||||
case LDAP_DEREF_SEARCHING:
|
||||
case LDAP_DEREF_ALWAYS:
|
||||
{
|
||||
Entry *newe = bdb2i_derefAlias_r( be, conn, op, e );
|
||||
if ( newe == NULL ) { /* problem with the alias */
|
||||
bdb2i_cache_return_entry_r( &li->li_cache, e );
|
||||
e = NULL;
|
||||
}
|
||||
else if ( newe != e ) { /* reassign e */
|
||||
bdb2i_cache_return_entry_r( &li->li_cache, e );
|
||||
e = newe;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (e) {
|
||||
switch ( send_search_entry( be, conn, op, e,
|
||||
attrs, attrsonly ) ) {
|
||||
case 0: /* entry sent ok */
|
||||
nentries++;
|
||||
break;
|
||||
case 1: /* entry not sent */
|
||||
break;
|
||||
case -1: /* connection closed */
|
||||
bdb2i_cache_return_entry_r( &li->li_cache, e );
|
||||
bdb2i_idl_free( candidates );
|
||||
free( rbuf );
|
||||
|
||||
if( realBase != NULL) {
|
||||
free( realBase );
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( e != NULL ) {
|
||||
/* free reader lock */
|
||||
bdb2i_cache_return_entry_r( &li->li_cache, e );
|
||||
}
|
||||
|
||||
ldap_pvt_thread_yield();
|
||||
}
|
||||
bdb2i_idl_free( candidates );
|
||||
if ( nrefs > 0 ) {
|
||||
send_ldap_search_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
|
||||
rbuf, nentries );
|
||||
} else {
|
||||
send_ldap_search_result( conn, op, LDAP_SUCCESS, NULL, NULL,
|
||||
nentries );
|
||||
}
|
||||
free( rbuf );
|
||||
|
||||
if( realBase != NULL) {
|
||||
free( realBase );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
bdb2_back_search(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
char *base,
|
||||
int scope,
|
||||
int deref,
|
||||
int slimit,
|
||||
int tlimit,
|
||||
Filter *filter,
|
||||
char *filterstr,
|
||||
char **attrs,
|
||||
int attrsonly
|
||||
)
|
||||
{
|
||||
DB_LOCK lock;
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
|
||||
struct timeval time1, time2;
|
||||
char *elapsed_time;
|
||||
int ret;
|
||||
|
||||
gettimeofday( &time1, NULL );
|
||||
|
||||
if ( bdb2i_enter_backend_r( &li->li_db_env, &lock ) != 0 ) {
|
||||
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
|
||||
return( -1 );
|
||||
|
||||
}
|
||||
|
||||
ret = bdb2i_back_search_internal( be, conn, op, base, scope, deref,
|
||||
slimit, tlimit, filter, filterstr, attrs, attrsonly );
|
||||
|
||||
(void) bdb2i_leave_backend( &li->li_db_env, lock );
|
||||
|
||||
if ( bdb2i_do_timing ) {
|
||||
|
||||
gettimeofday( &time2, NULL);
|
||||
elapsed_time = bdb2i_elapsed( time1, time2 );
|
||||
Debug( LDAP_DEBUG_ANY, "conn=%d op=%d SRCH elapsed=%s\n",
|
||||
conn->c_connid, op->o_opid, elapsed_time );
|
||||
free( elapsed_time );
|
||||
|
||||
}
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
|
||||
static ID_BLOCK *
|
||||
base_candidates(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
char *base,
|
||||
Filter *filter,
|
||||
char **attrs,
|
||||
int attrsonly,
|
||||
char **matched,
|
||||
int *err
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
int rc;
|
||||
ID id;
|
||||
ID_BLOCK *idl;
|
||||
Entry *e;
|
||||
|
||||
Debug(LDAP_DEBUG_TRACE, "base_candidates: base: \"%s\"\n", base, 0, 0);
|
||||
|
||||
*err = LDAP_SUCCESS;
|
||||
|
||||
/* get entry with reader lock */
|
||||
if ( (e = bdb2i_dn2entry_r( be, base, matched )) == NULL ) {
|
||||
*err = LDAP_NO_SUCH_OBJECT;
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
/* check for deleted */
|
||||
|
||||
idl = bdb2i_idl_alloc( 1 );
|
||||
bdb2i_idl_insert( &idl, e->e_id, 1 );
|
||||
|
||||
|
||||
/* free reader lock */
|
||||
bdb2i_cache_return_entry_r( &li->li_cache, e );
|
||||
|
||||
return( idl );
|
||||
}
|
||||
|
||||
static ID_BLOCK *
|
||||
onelevel_candidates(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
char *base,
|
||||
Filter *filter,
|
||||
char **attrs,
|
||||
int attrsonly,
|
||||
char **matched,
|
||||
int *err
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
Entry *e = NULL;
|
||||
Filter *f;
|
||||
char buf[20];
|
||||
ID_BLOCK *candidates;
|
||||
|
||||
Debug(LDAP_DEBUG_TRACE, "onelevel_candidates: base: \"%s\"\n", base, 0, 0);
|
||||
|
||||
*err = LDAP_SUCCESS;
|
||||
|
||||
/* get the base object with reader lock */
|
||||
if ( base != NULL && *base != '\0' &&
|
||||
(e = bdb2i_dn2entry_r( be, base, matched )) == NULL )
|
||||
{
|
||||
*err = LDAP_NO_SUCH_OBJECT;
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
/*
|
||||
* modify the filter to be something like this:
|
||||
*
|
||||
* parent=baseobject & originalfilter
|
||||
*/
|
||||
|
||||
f = (Filter *) ch_malloc( sizeof(Filter) );
|
||||
f->f_next = NULL;
|
||||
f->f_choice = LDAP_FILTER_AND;
|
||||
f->f_and = (Filter *) ch_malloc( sizeof(Filter) );
|
||||
f->f_and->f_choice = LDAP_FILTER_EQUALITY;
|
||||
f->f_and->f_ava.ava_type = ch_strdup( "id2children" );
|
||||
sprintf( buf, "%ld", e != NULL ? e->e_id : 0 );
|
||||
f->f_and->f_ava.ava_value.bv_val = ch_strdup( buf );
|
||||
f->f_and->f_ava.ava_value.bv_len = strlen( buf );
|
||||
f->f_and->f_next = filter;
|
||||
|
||||
/* from here, it's just like subtree_candidates */
|
||||
candidates = subtree_candidates( be, conn, op, base, f, attrs,
|
||||
attrsonly, matched, e, err, 0 );
|
||||
|
||||
/* free up just the filter stuff we allocated above */
|
||||
f->f_and->f_next = NULL;
|
||||
filter_free( f );
|
||||
|
||||
/* free entry and reader lock */
|
||||
if( e != NULL ) {
|
||||
bdb2i_cache_return_entry_r( &li->li_cache, e );
|
||||
}
|
||||
return( candidates );
|
||||
}
|
||||
|
||||
static ID_BLOCK *
|
||||
subtree_candidates(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
char *base,
|
||||
Filter *filter,
|
||||
char **attrs,
|
||||
int attrsonly,
|
||||
char **matched,
|
||||
Entry *e,
|
||||
int *err,
|
||||
int lookupbase
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
Filter *f, **filterarg_ptr;
|
||||
ID_BLOCK *candidates;
|
||||
|
||||
Debug(LDAP_DEBUG_TRACE, "subtree_candidates: base: \"%s\" %s\n",
|
||||
base ? base : "NULL", lookupbase ? "lookupbase" : "", 0);
|
||||
|
||||
/*
|
||||
* get the base object - unless we already have it (from one-level).
|
||||
* also, unless this is a one-level search or a subtree search
|
||||
* starting at the very top of our subtree, we need to modify the
|
||||
* filter to be something like this:
|
||||
*
|
||||
* dn=*baseobjectdn & (originalfilter | ref=*)
|
||||
*
|
||||
* the "objectclass=referral" part is used to select referrals to return
|
||||
*/
|
||||
|
||||
*err = LDAP_SUCCESS;
|
||||
f = NULL;
|
||||
if ( lookupbase ) {
|
||||
e = NULL;
|
||||
|
||||
if ( base != NULL && *base != '\0' &&
|
||||
(e = bdb2i_dn2entry_r( be, base, matched )) == NULL )
|
||||
{
|
||||
*err = LDAP_NO_SUCH_OBJECT;
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
if (e) {
|
||||
bdb2i_cache_return_entry_r( &li->li_cache, e );
|
||||
}
|
||||
|
||||
f = (Filter *) ch_malloc( sizeof(Filter) );
|
||||
f->f_next = NULL;
|
||||
f->f_choice = LDAP_FILTER_OR;
|
||||
f->f_or = (Filter *) ch_malloc( sizeof(Filter) );
|
||||
f->f_or->f_choice = LDAP_FILTER_EQUALITY;
|
||||
f->f_or->f_avtype = ch_strdup( "objectclass" );
|
||||
/* Patch to use normalized uppercase */
|
||||
f->f_or->f_avvalue.bv_val = ch_strdup( "REFERRAL" );
|
||||
f->f_or->f_avvalue.bv_len = strlen( "REFERRAL" );
|
||||
filterarg_ptr = &f->f_or->f_next;
|
||||
*filterarg_ptr = filter;
|
||||
filter = f;
|
||||
|
||||
if ( ! be_issuffix( be, base ) ) {
|
||||
f = (Filter *) ch_malloc( sizeof(Filter) );
|
||||
f->f_next = NULL;
|
||||
f->f_choice = LDAP_FILTER_AND;
|
||||
f->f_and = (Filter *) ch_malloc( sizeof(Filter) );
|
||||
f->f_and->f_choice = LDAP_FILTER_SUBSTRINGS;
|
||||
f->f_and->f_sub_type = ch_strdup( "dn" );
|
||||
f->f_and->f_sub_initial = NULL;
|
||||
f->f_and->f_sub_any = NULL;
|
||||
f->f_and->f_sub_final = ch_strdup( base );
|
||||
value_normalize( f->f_and->f_sub_final, SYNTAX_CIS );
|
||||
f->f_and->f_next = filter;
|
||||
filter = f;
|
||||
}
|
||||
}
|
||||
|
||||
candidates = bdb2i_filter_candidates( be, filter );
|
||||
|
||||
/* free up just the parts we allocated above */
|
||||
if ( f != NULL ) {
|
||||
*filterarg_ptr = NULL;
|
||||
filter_free( f );
|
||||
}
|
||||
|
||||
return( candidates );
|
||||
}
|
||||
217
servers/slapd/back-bdb2/startup.c
Normal file
217
servers/slapd/back-bdb2/startup.c
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
/* startup.c - startup bdb2 backend */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "ldapconfig.h"
|
||||
#include "slap.h"
|
||||
#include "back-bdb2.h"
|
||||
|
||||
#include "db.h"
|
||||
|
||||
static void remove_old_locks( char *home );
|
||||
|
||||
|
||||
static void
|
||||
bdb2i_db_errcall( char *prefix, char *message )
|
||||
{
|
||||
Debug( LDAP_DEBUG_ANY, "dbd2_db_errcall(): %s %s", prefix, message, 0 );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bdb2i_back_startup_internal(
|
||||
Backend *be
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
DB_ENV *dbEnv = &li->li_db_env;
|
||||
int envFlags = DB_CREATE | DB_THREAD | DB_INIT_LOCK | DB_INIT_MPOOL;
|
||||
int err = 0;
|
||||
char *home;
|
||||
char datadir[MAXPATHLEN];
|
||||
char *config[2] = { datadir, NULL };
|
||||
|
||||
/* if the data directory is not an absolute path, have it relative
|
||||
to the current working directory (which should not be configured !) */
|
||||
if ( *li->li_directory != *DEFAULT_DIRSEP ) {
|
||||
char cwd[MAXPATHLEN];
|
||||
|
||||
(void) getcwd( cwd, MAXPATHLEN );
|
||||
sprintf( cwd, "%s%s%s", cwd, DEFAULT_DIRSEP, li->li_directory );
|
||||
free( li->li_directory );
|
||||
li->li_directory = strdup( cwd );
|
||||
|
||||
}
|
||||
|
||||
/* set the DB home directory to the configured one, or the data dir */
|
||||
if ( li->li_dbhome ) {
|
||||
|
||||
if ( *li->li_dbhome != *DEFAULT_DIRSEP ) {
|
||||
char cwd[MAXPATHLEN];
|
||||
|
||||
(void) getcwd( cwd, MAXPATHLEN );
|
||||
sprintf( cwd, "%s%s%s", cwd, DEFAULT_DIRSEP, li->li_dbhome );
|
||||
free( li->li_dbhome );
|
||||
li->li_dbhome = strdup( cwd );
|
||||
|
||||
}
|
||||
home = li->li_dbhome;
|
||||
|
||||
} else {
|
||||
|
||||
home = li->li_directory;
|
||||
|
||||
}
|
||||
|
||||
/* set the DATA_DIR */
|
||||
sprintf( datadir, "DB_DATA_DIR %s", li->li_directory );
|
||||
|
||||
/* general initialization of the environment */
|
||||
memset( dbEnv, 0, sizeof( DB_ENV ));
|
||||
dbEnv->db_errcall = bdb2i_db_errcall;
|
||||
dbEnv->db_errpfx = "==>";
|
||||
|
||||
/* initialize the lock subsystem */
|
||||
dbEnv->lk_max = 0;
|
||||
|
||||
/* remove old locking tables */
|
||||
remove_old_locks( home );
|
||||
|
||||
/* initialize the mpool subsystem */
|
||||
dbEnv->mp_size = (size_t) li->li_dbcachesize;
|
||||
|
||||
/* now do the db_appinit */
|
||||
if ( ( err = db_appinit( home, config, dbEnv, envFlags )) ) {
|
||||
char error[BUFSIZ];
|
||||
|
||||
if ( err < 0 ) sprintf( error, "%ld\n", (long) err );
|
||||
else sprintf( error, "%s\n", strerror( err ));
|
||||
|
||||
fprintf( stderr,
|
||||
"bdb2i_back_startup(): FATAL error in db_appinit() : %s\n",
|
||||
error );
|
||||
exit( 1 );
|
||||
|
||||
}
|
||||
|
||||
bdb2i_with_dbenv = 1;
|
||||
|
||||
/* if there are more index files, add them to the DB file list */
|
||||
bdb2i_check_additional_attr_index( li );
|
||||
|
||||
/* now open all DB files */
|
||||
bdb2i_txn_open_files( li );
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
bdb2i_back_shutdown_internal(
|
||||
Backend *be
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
DB_ENV *dbEnv = &li->li_db_env;
|
||||
int err;
|
||||
|
||||
/* close all DB files */
|
||||
bdb2i_txn_close_files( &li->li_txn_head );
|
||||
|
||||
/* remove old locking tables */
|
||||
dbEnv->db_errpfx = "bdb2i_back_shutdown(): lock_unlink:";
|
||||
if ( ( err = lock_unlink( NULL, 1, dbEnv )) != 0 )
|
||||
Debug( LDAP_DEBUG_ANY, "bdb2i_back_shutdown(): lock_unlink: %s\n",
|
||||
strerror( err ), 0, 0);
|
||||
|
||||
/* remove old memory pool */
|
||||
dbEnv->db_errpfx = "bdb2i_back_shutdown(): memp_unlink:";
|
||||
if ( ( err = memp_unlink( NULL, 1, dbEnv )) != 0 )
|
||||
Debug( LDAP_DEBUG_ANY, "bdb2i_back_shutdown(): memp_unlink: %s\n",
|
||||
strerror( err ), 0, 0);
|
||||
|
||||
(void) db_appexit( &li->li_db_env );
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bdb2_back_startup(
|
||||
Backend *be
|
||||
)
|
||||
{
|
||||
struct timeval time1, time2;
|
||||
char *elapsed_time;
|
||||
|
||||
gettimeofday( &time1, NULL );
|
||||
|
||||
bdb2i_back_startup_internal( be );
|
||||
|
||||
if ( bdb2i_do_timing ) {
|
||||
|
||||
gettimeofday( &time2, NULL);
|
||||
elapsed_time = bdb2i_elapsed( time1, time2 );
|
||||
Debug( LDAP_DEBUG_ANY, "START elapsed=%s\n",
|
||||
elapsed_time, 0, 0 );
|
||||
free( elapsed_time );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bdb2_back_shutdown(
|
||||
Backend *be
|
||||
)
|
||||
{
|
||||
struct timeval time1, time2;
|
||||
char *elapsed_time;
|
||||
|
||||
gettimeofday( &time1, NULL );
|
||||
|
||||
bdb2i_back_shutdown_internal( be );
|
||||
|
||||
if ( bdb2i_do_timing ) {
|
||||
|
||||
gettimeofday( &time2, NULL);
|
||||
elapsed_time = bdb2i_elapsed( time1, time2 );
|
||||
Debug( LDAP_DEBUG_ANY, "SHUTDOWN elapsed=%s\n",
|
||||
elapsed_time, 0, 0 );
|
||||
free( elapsed_time );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
remove_old_locks( char *home )
|
||||
{
|
||||
DB_ENV dbEnv;
|
||||
int err;
|
||||
|
||||
memset( &dbEnv, 0, sizeof( DB_ENV ));
|
||||
dbEnv.db_errcall = stderr;
|
||||
dbEnv.db_errpfx = "remove_old_locks(): db_appinit:";
|
||||
dbEnv.lk_max = 0;
|
||||
|
||||
if ( ( err = db_appinit( home, NULL, &dbEnv, 0 )) != 0 )
|
||||
Debug( LDAP_DEBUG_ANY, "remove_old_locks(): db_appinit: %s\n",
|
||||
strerror( err ), 0, 0);
|
||||
|
||||
dbEnv.db_errpfx = "remove_old_locks(): lock_unlink:";
|
||||
if ( ( err = lock_unlink( NULL, 1, &dbEnv )) != 0 )
|
||||
Debug( LDAP_DEBUG_ANY, "remove_old_locks(): lock_unlink: %s\n",
|
||||
strerror( err ), 0, 0);
|
||||
|
||||
dbEnv.db_errpfx = "remove_old_locks(): db_appexit:";
|
||||
if ( ( err = db_appexit( &dbEnv )) != 0 )
|
||||
Debug( LDAP_DEBUG_ANY, "remove_old_locks(): db_appexit: %s\n",
|
||||
strerror( err ), 0, 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
35
servers/slapd/back-bdb2/timing.c
Normal file
35
servers/slapd/back-bdb2/timing.c
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/* timing.c - timing bdb2 backend */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-bdb2.h"
|
||||
|
||||
|
||||
int bdb2i_do_timing = 0;
|
||||
|
||||
|
||||
char *
|
||||
bdb2i_elapsed( struct timeval firsttime, struct timeval secondtime )
|
||||
{
|
||||
long int elapsedmicrosec, elapsedsec;
|
||||
char elapsed_string[BUFSIZ];
|
||||
|
||||
elapsedsec = secondtime.tv_sec - firsttime.tv_sec;
|
||||
elapsedmicrosec = secondtime.tv_usec - firsttime.tv_usec;
|
||||
if(elapsedmicrosec < 0) {
|
||||
elapsedmicrosec += 1000000;
|
||||
elapsedsec -= 1;
|
||||
}
|
||||
|
||||
sprintf( elapsed_string, "%ld.%.6ld", elapsedsec, elapsedmicrosec );
|
||||
return( strdup( elapsed_string ));
|
||||
}
|
||||
|
||||
|
||||
321
servers/slapd/back-bdb2/txn.c
Normal file
321
servers/slapd/back-bdb2/txn.c
Normal file
|
|
@ -0,0 +1,321 @@
|
|||
/* txn.c - TP support functions of the bdb2 backend */
|
||||
|
||||
#include "txn.h"
|
||||
|
||||
|
||||
void
|
||||
bdb2i_txn_head_init( BDB2_TXN_HEAD *head )
|
||||
{
|
||||
int dbFile;
|
||||
BDB2_TXN_FILES **fileNodeH;
|
||||
|
||||
/* for each fixed DB file allocate a file descriptor node and
|
||||
initialize the file's name */
|
||||
fileNodeH = &head->dbFiles;
|
||||
for ( dbFile = BDB2_DB_DN_FILE; dbFile <= BDB2_DB_OC_IDX_FILE; dbFile++ ) {
|
||||
|
||||
char fileName[MAXPATHLEN];
|
||||
|
||||
*fileNodeH = head->dbFileHandle[dbFile] =
|
||||
(BDB2_TXN_FILES *) ch_calloc( 1, sizeof( BDB2_TXN_FILES ));
|
||||
if ( *fileNodeH == NULL ) {
|
||||
|
||||
Debug( LDAP_DEBUG_ANY, "bdb2i_txn_head_init(): out of memory!\n",
|
||||
0, 0, 0 );
|
||||
exit( 1 );
|
||||
|
||||
}
|
||||
|
||||
sprintf( fileName, "%s%s", bdb2i_fixed_filenames[dbFile], LDBM_SUFFIX );
|
||||
(*fileNodeH)->dbc_name = strdup( fileName );
|
||||
|
||||
fileNodeH = &(*fileNodeH)->next;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
bdb2i_init_db_file_cache( struct ldbminfo *li, BDB2_TXN_FILES *fileinfo )
|
||||
{
|
||||
time_t curtime;
|
||||
struct stat st;
|
||||
char buf[MAXPATHLEN];
|
||||
|
||||
pthread_mutex_lock( ¤ttime_mutex );
|
||||
curtime = currenttime;
|
||||
pthread_mutex_unlock( ¤ttime_mutex );
|
||||
|
||||
fileinfo->dbc_refcnt = 1;
|
||||
fileinfo->dbc_lastref = curtime;
|
||||
|
||||
sprintf( buf, "%s%s%s", li->li_directory, DEFAULT_DIRSEP,
|
||||
fileinfo->dbc_name );
|
||||
if ( stat( buf, &st ) == 0 ) {
|
||||
fileinfo->dbc_blksize = st.st_blksize;
|
||||
} else {
|
||||
fileinfo->dbc_blksize = DEFAULT_BLOCKSIZE;
|
||||
}
|
||||
|
||||
fileinfo->dbc_maxids = ( fileinfo->dbc_blksize / sizeof( ID )) - 2;
|
||||
fileinfo->dbc_maxindirect = ( SLAPD_LDBM_MIN_MAXIDS /
|
||||
fileinfo->dbc_maxids ) + 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bdb2i_txn_attr_config(
|
||||
struct ldbminfo *li,
|
||||
char *attr,
|
||||
int open )
|
||||
{
|
||||
BDB2_TXN_HEAD *head = &li->li_txn_head;
|
||||
|
||||
/* the "attribute" 'default' is special */
|
||||
if ( strcasecmp( attr, "default" )) {
|
||||
|
||||
/* create a new index file node, if the index is not known already */
|
||||
BDB2_TXN_FILES **fileNodeH;
|
||||
char fileName[MAXPATHLEN];
|
||||
|
||||
sprintf( fileName, "%s%s", attr, LDBM_SUFFIX );
|
||||
|
||||
/* search for the end of the list or a node describing
|
||||
the current attribute */
|
||||
for ( fileNodeH = &head->dbFiles;
|
||||
( *fileNodeH && strcasecmp( (*fileNodeH)->dbc_name, fileName ));
|
||||
fileNodeH = &(*fileNodeH)->next ) {
|
||||
|
||||
}
|
||||
|
||||
/* unless we have that attribute already... */
|
||||
if ( *fileNodeH == NULL ) {
|
||||
BDB2_TXN_FILES *p;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"bdb2i_txn_attr_config(): adding node for \"%s\"\n",
|
||||
fileName, 0, 0 );
|
||||
|
||||
/* if we're out of memory, we have to see, how to exit... */
|
||||
if ( ( *fileNodeH = p = (BDB2_TXN_FILES *)
|
||||
ch_calloc( 1, sizeof( BDB2_TXN_FILES )) ) == NULL ) {
|
||||
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"bdb2i_txn_attr_config(): out of memory -- FATAL.\n",
|
||||
0, 0, 0 );
|
||||
|
||||
/* during configuration (no files are opened)
|
||||
we can just exit, otherwise we kill ourself and
|
||||
hope to shutdown cleanly... */
|
||||
if ( open ) {
|
||||
pthread_kill( pthread_self(), LDAP_SIGUSR1 );
|
||||
} else {
|
||||
exit( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
p->dbc_name = strdup( fileName );
|
||||
|
||||
/* if requested for, we have to open the DB file */
|
||||
/* BUT NOT "objectclass", 'cause that's a default index ! */
|
||||
if ( open && strcasecmp( fileName, "objectclass" )) {
|
||||
|
||||
/* since we have an mpool, we should not define a cache size */
|
||||
p->dbc_db = ldbm_open_env( p->dbc_name, LDBM_WRCREAT,
|
||||
li->li_mode, 0, &li->li_db_env );
|
||||
|
||||
/* if the files could not be opened, something is wrong;
|
||||
complain */
|
||||
if ( p->dbc_db == NULL ) {
|
||||
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"bdb2i_txn_open_files(): couldn't open file \"%s\" -- FATAL.\n",
|
||||
p->dbc_name, 0, 0 );
|
||||
pthread_kill( pthread_self(), LDAP_SIGUSR1 );
|
||||
|
||||
}
|
||||
|
||||
bdb2i_init_db_file_cache( li, p );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"bdb2i_txn_attr_config(): NEW INDEX FILE \"%s\"\n",
|
||||
p->dbc_name, 0, 0 );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} else { /* it is "attribute" 'default' */
|
||||
|
||||
head->withDefIDX = BDB2_WITH_DEF_IDX;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bdb2i_txn_open_files( struct ldbminfo *li )
|
||||
{
|
||||
BDB2_TXN_HEAD *head = &li->li_txn_head;
|
||||
BDB2_TXN_FILES *dbFile;
|
||||
|
||||
for ( dbFile = head->dbFiles; dbFile; dbFile = dbFile->next ) {
|
||||
|
||||
/* since we have an mpool, we should not define a cache size */
|
||||
dbFile->dbc_db = ldbm_open_env( dbFile->dbc_name, LDBM_WRCREAT,
|
||||
li->li_mode, 0, &li->li_db_env );
|
||||
|
||||
/* if the files could not be opened, something is wrong; complain */
|
||||
if ( dbFile->dbc_db == NULL ) {
|
||||
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"bdb2i_txn_open_files(): couldn't open file \"%s\" -- FATAL.\n",
|
||||
dbFile->dbc_name, 0, 0 );
|
||||
exit( 1 );
|
||||
|
||||
}
|
||||
|
||||
/* initialize the file info */
|
||||
bdb2i_init_db_file_cache( li, dbFile );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "bdb2i_txn_open_files(): OPEN INDEX \"%s\"\n",
|
||||
dbFile->dbc_name, 0, 0 );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bdb2i_txn_close_files( BDB2_TXN_HEAD *head)
|
||||
{
|
||||
BDB2_TXN_FILES *dbFile;
|
||||
|
||||
for ( dbFile = head->dbFiles; dbFile; dbFile = dbFile->next ) {
|
||||
|
||||
ldbm_close( dbFile->dbc_db );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BDB2_TXN_FILES *
|
||||
bdb2i_get_db_file_cache( struct ldbminfo *li, char *name )
|
||||
{
|
||||
BDB2_TXN_HEAD *head = &li->li_txn_head;
|
||||
BDB2_TXN_FILES *dbFile;
|
||||
int dbFileNum;
|
||||
|
||||
for ( dbFile = head->dbFiles; dbFile; dbFile = dbFile->next ) {
|
||||
|
||||
if ( !strcasecmp( dbFile->dbc_name, name )) return( dbFile );
|
||||
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"bdb2i_get_db_file_cache(): UPS, could't find \"%s\" \n", name, 0, 0 );
|
||||
|
||||
/* ups, we couldn't find the file */
|
||||
return( NULL );
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* check for new attribute indexes, that might have been created
|
||||
during former runs of slapd */
|
||||
/* this is called during startup of the slapd server */
|
||||
void
|
||||
bdb2i_check_additional_attr_index( struct ldbminfo *li )
|
||||
{
|
||||
DIR *datadir;
|
||||
struct dirent *file;
|
||||
|
||||
if ( ( datadir = opendir( li->li_directory ) ) == NULL ) {
|
||||
/* if ( ( datadir = opendir( "/tmp" ) ) == NULL ) { */
|
||||
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"bdb2i_check_additional_attr_index(): ERROR while opening datadir: %s\n",
|
||||
strerror( errno ), 0, 0 );
|
||||
exit( 1 );
|
||||
|
||||
}
|
||||
|
||||
for ( file = readdir( datadir ); file; file = readdir( datadir )) {
|
||||
char filename[MAXPATHLEN];
|
||||
int namelen;
|
||||
|
||||
strcpy( filename, file->d_name );
|
||||
namelen = strlen( filename );
|
||||
|
||||
if ( namelen > strlen( LDBM_SUFFIX )) {
|
||||
|
||||
if ( !strcasecmp( filename + namelen - strlen( LDBM_SUFFIX ),
|
||||
LDBM_SUFFIX )) {
|
||||
|
||||
*(filename + namelen - strlen( LDBM_SUFFIX )) = '\0';
|
||||
bdb2i_txn_attr_config( li, filename, 0 );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "INDEX FILE: %s\n", filename, 0, 0 );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
closedir( datadir );
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* check for the addition of new attribute indexes during add */
|
||||
/* this is called after startup of the slapd server */
|
||||
/* DON'T WORRY ABOUT ACCESS RIGHTS, THAT MIGHT PREVENT US
|
||||
FROM ADDING ATTRIBUTES LATER ON */
|
||||
void
|
||||
bdb2i_check_default_attr_index_add( struct ldbminfo *li, Entry *e )
|
||||
{
|
||||
BDB2_TXN_HEAD *head = &li->li_txn_head;
|
||||
|
||||
if ( head->withDefIDX == BDB2_WITH_DEF_IDX ) {
|
||||
Attribute *ap;
|
||||
|
||||
for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) {
|
||||
if ( strcasecmp( ap->a_type, "objectclass" ))
|
||||
bdb2i_txn_attr_config( li, ap->a_type, 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* check for the addition of new attribute indexes during modify */
|
||||
/* this is called after startup of the slapd server */
|
||||
/* DON'T WORRY ABOUT ACCESS RIGHTS, THAT MIGHT PREVENT US
|
||||
FROM ADDING ATTRIBUTES LATER ON */
|
||||
void
|
||||
bdb2i_check_default_attr_index_mod( struct ldbminfo *li, LDAPModList *modlist )
|
||||
{
|
||||
BDB2_TXN_HEAD *head = &li->li_txn_head;
|
||||
|
||||
if ( head->withDefIDX == BDB2_WITH_DEF_IDX ) {
|
||||
LDAPModList *ml;
|
||||
char *default_attrs[] = { "modifytimestamp", "modifiersname", NULL };
|
||||
int attr;
|
||||
|
||||
for ( ml = modlist; ml != NULL; ml = ml->ml_next ) {
|
||||
LDAPMod *mod = &ml->ml_mod;
|
||||
|
||||
if (( mod->mod_op & ~LDAP_MOD_BVALUES ) == LDAP_MOD_ADD )
|
||||
if ( strcasecmp( mod->mod_type, "objectclass" ))
|
||||
bdb2i_txn_attr_config( li, mod->mod_type, 1 );
|
||||
}
|
||||
|
||||
/* these attributes are default when modifying */
|
||||
for ( attr = 0; default_attrs[attr]; attr++ ) {
|
||||
bdb2i_txn_attr_config( li, default_attrs[attr], 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
38
servers/slapd/back-bdb2/txn.h
Normal file
38
servers/slapd/back-bdb2/txn.h
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/* txn.h - Header for TP support functions of the bdb2 backend */
|
||||
|
||||
#ifndef _BDB2_TXN_H_
|
||||
#define _BDB2_TXN_H_
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
#include <ac/signal.h>
|
||||
|
||||
#include "ldapconfig.h"
|
||||
#include "slap.h"
|
||||
#include "back-bdb2.h"
|
||||
|
||||
|
||||
|
||||
#define BDB2_TXN_CHKP_MAX_CNT 20 /* checkpoint every
|
||||
20 transactions */
|
||||
#define BDB2_TXN_CHKP_MAX_TIME 600 /* checkpoint after
|
||||
600 seconds */
|
||||
|
||||
|
||||
char *bdb2i_fixed_filenames[] = {
|
||||
|
||||
"dn", "dn2id", "id2entry", "id2children", "objectclass"
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* _BDB2_TXN_H_ */
|
||||
|
||||
48
servers/slapd/back-bdb2/unbind.c
Normal file
48
servers/slapd/back-bdb2/unbind.c
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/* unbind.c - handle an ldap unbind operation */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-bdb2.h"
|
||||
|
||||
static int
|
||||
bdb2i_back_unbind_internal(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op
|
||||
)
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
bdb2_back_unbind(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op
|
||||
)
|
||||
{
|
||||
struct timeval time1, time2;
|
||||
char *elapsed_time;
|
||||
int ret;
|
||||
|
||||
gettimeofday( &time1, NULL );
|
||||
|
||||
ret = bdb2i_back_unbind_internal( be, conn, op );
|
||||
|
||||
if ( bdb2i_do_timing ) {
|
||||
|
||||
gettimeofday( &time2, NULL);
|
||||
elapsed_time = bdb2i_elapsed( time1, time2 );
|
||||
Debug( LDAP_DEBUG_ANY, "conn=%d op=%d UNBIND elapsed=%s\n",
|
||||
conn->c_connid, op->o_opid, elapsed_time );
|
||||
free( elapsed_time );
|
||||
|
||||
}
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
|
@ -315,7 +315,6 @@ char *derefDN ( Backend *be,
|
|||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= returning deref DN of \"%s\"\n", newDN, 0, 0 );
|
||||
if (matched != NULL) free(matched);
|
||||
|
||||
return newDN;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue