mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-20 22:59:34 -05:00
ITS#8734 Fixes for many back-asyncmeta issues
Includes all the changes necessary to fix back-asyncmeta issues discovered during on-site testing since the start of 2016. These include: Issues with stability - crashes and assetion failures Incorrect behavior during unstable network conditions, such as inability to reset connections or process responses, or "hanging" to wait for a response that would never be received. Memory leaks and memory management fixes - major redesign of the way back-asyncmeta works with memory contexts. Rewrite was replaced with suffix-massage in configuration, and the network-timeout value was changed to milliseconds. Incorrect behavior when SASL is used to bind to a target. Many problems caused by race conditions Fixes for compiler warnings, and tests. Cleanup of unused code.
This commit is contained in:
parent
06d289f985
commit
bb7e14d201
26 changed files with 3691 additions and 4760 deletions
|
|
@ -376,16 +376,18 @@ Sets the network timeout value after which
|
|||
.BR poll (2)/ select (2)
|
||||
following a
|
||||
.BR connect (2)
|
||||
returns in case of no activity.
|
||||
The value is in seconds, and it can be specified as for
|
||||
returns in case of no activity while sending an operation to the remote target.
|
||||
The value is in milliseconds, and it can be specified as for
|
||||
.BR idle\-timeout .
|
||||
If set before any target specification, it affects all targets, unless
|
||||
overridden by any per-target directive.
|
||||
|
||||
.TP
|
||||
.B nretries {forever|never|<nretries>}
|
||||
This directive defines how many times a bind should be retried
|
||||
in case of temporary failure in contacting a target. If defined
|
||||
This directive defines how many times forwarding an operation should be retried
|
||||
in case of temporary failure in contacting a target. The number of retries
|
||||
is per operation, so if a bind to the target is necessary first, the remaining
|
||||
number is decremented. If defined
|
||||
before any target specification, it applies to all targets (by default,
|
||||
.BR 3
|
||||
times);
|
||||
|
|
@ -409,11 +411,13 @@ by a target. See
|
|||
for details.
|
||||
|
||||
.TP
|
||||
.B suffixmassage "<virtual naming context>" "<real naming context>"
|
||||
All the directives starting with "rewrite" refer to the rewrite engine
|
||||
that has been added to slapd. See
|
||||
.B slapd\-meta(5)
|
||||
for details.
|
||||
.B suffixmassage "<local suffix>" "<remote suffix>"
|
||||
.B slapd\-asyncmeta
|
||||
does not support the rewrite engine used by
|
||||
the LDAP and META backends.
|
||||
.B suffixmassage
|
||||
can be used to perform DN suffix rewriting, the same way as the obsoleted suffixmassage directive
|
||||
previously used by the LDAP backend.
|
||||
|
||||
.TP
|
||||
.B t\-f\-support {NO|yes|discover}
|
||||
|
|
|
|||
|
|
@ -19,12 +19,12 @@
|
|||
## based on back-meta module for inclusion in OpenLDAP Software.
|
||||
## This work was sponsored by Ericsson
|
||||
|
||||
SRCS = init.c config.c search.c message_queue.c bind.c unbind.c add.c compare.c \
|
||||
delete.c modify.c modrdn.c suffixmassage.c map.c \
|
||||
conn.c candidates.c dncache.c meta_result.c abandon.c
|
||||
OBJS = init.lo config.lo search.lo message_queue.lo bind.lo unbind.lo add.lo compare.lo \
|
||||
delete.lo modify.lo modrdn.lo suffixmassage.lo map.lo \
|
||||
conn.lo candidates.lo dncache.lo meta_result.lo abandon.lo
|
||||
SRCS = init.c config.c search.c message_queue.c bind.c add.c compare.c \
|
||||
delete.c modify.c modrdn.c map.c \
|
||||
conn.c candidates.c dncache.c meta_result.c
|
||||
OBJS = init.lo config.lo search.lo message_queue.lo bind.lo add.lo compare.lo \
|
||||
delete.lo modify.lo modrdn.lo map.lo \
|
||||
conn.lo candidates.lo dncache.lo meta_result.lo
|
||||
|
||||
LDAP_INCDIR= ../../../include
|
||||
LDAP_LIBDIR= ../../../libraries
|
||||
|
|
|
|||
|
|
@ -1,52 +0,0 @@
|
|||
/* abandon.c - abandon request handler for back-asyncmeta */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 2016-2019 The OpenLDAP Foundation.
|
||||
* Portions Copyright 2016 Symas Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted only as authorized by the OpenLDAP
|
||||
* Public License.
|
||||
*
|
||||
* A copy of this license is available in the file LICENSE in the
|
||||
* top-level directory of the distribution or, alternatively, at
|
||||
* <http://www.OpenLDAP.org/license.html>.
|
||||
*/
|
||||
|
||||
/* ACKNOWLEDGEMENTS:
|
||||
* This work was developed by Symas Corporation
|
||||
* based on back-meta module for inclusion in OpenLDAP Software.
|
||||
* This work was sponsored by Ericsson. */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "../back-ldap/back-ldap.h"
|
||||
#include "back-asyncmeta.h"
|
||||
#include "ldap_rq.h"
|
||||
|
||||
/* function is unused */
|
||||
int
|
||||
asyncmeta_back_abandon( Operation *op, SlapReply *rs )
|
||||
{
|
||||
Operation *t_op;
|
||||
|
||||
/* Find the ops being abandoned */
|
||||
ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
|
||||
|
||||
LDAP_STAILQ_FOREACH( t_op, &op->o_conn->c_ops, o_next ) {
|
||||
if ( t_op->o_msgid == op->orn_msgid ) {
|
||||
t_op->o_abandon = 1;
|
||||
}
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
|
||||
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
|
@ -27,23 +27,33 @@
|
|||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "../../../libraries/liblber/lber-int.h"
|
||||
#include "../../../libraries/libldap/ldap-int.h"
|
||||
#include "../back-ldap/back-ldap.h"
|
||||
#include "back-asyncmeta.h"
|
||||
#include "ldap_rq.h"
|
||||
#include "../../../libraries/liblber/lber-int.h"
|
||||
#include "../../../libraries/libldap/ldap-int.h"
|
||||
|
||||
void
|
||||
asyncmeta_sender_error(Operation *op,
|
||||
SlapReply *rs,
|
||||
slap_callback *cb)
|
||||
|
||||
int
|
||||
asyncmeta_error_cleanup(Operation *op,
|
||||
SlapReply *rs,
|
||||
bm_context_t *bc,
|
||||
a_metaconn_t *mc,
|
||||
int candidate)
|
||||
{
|
||||
if (cb != NULL) {
|
||||
op->o_callback = cb;
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
mc->mc_conns[candidate].msc_active--;
|
||||
if (asyncmeta_bc_in_queue(mc,bc) == NULL || bc->bc_active > 1) {
|
||||
bc->bc_active--;
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
asyncmeta_drop_bc(mc, bc);
|
||||
slap_sl_mem_setctx(op->o_threadctx, op->o_tmpmemctx);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
send_ldap_result(op, rs);
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
meta_search_candidate_t
|
||||
|
|
@ -51,195 +61,174 @@ asyncmeta_back_add_start(Operation *op,
|
|||
SlapReply *rs,
|
||||
a_metaconn_t *mc,
|
||||
bm_context_t *bc,
|
||||
int candidate)
|
||||
int candidate,
|
||||
int do_lock)
|
||||
{
|
||||
int isupdate;
|
||||
Attribute *a;
|
||||
int i;
|
||||
LDAPMod **attrs;
|
||||
struct berval mapped;
|
||||
a_dncookie dc;
|
||||
a_metainfo_t *mi = mc->mc_info;
|
||||
a_metatarget_t *mt = mi->mi_targets[ candidate ];
|
||||
struct berval mdn;
|
||||
struct berval mdn = {0, NULL};
|
||||
meta_search_candidate_t retcode = META_SEARCH_CANDIDATE;
|
||||
BerElement *ber = NULL;
|
||||
a_metasingleconn_t *msc = &mc->mc_conns[ candidate ];
|
||||
SlapReply *candidates = bc->candidates;
|
||||
ber_int_t msgid;
|
||||
LDAPControl **ctrls = NULL;
|
||||
int rc, nretries = 1;
|
||||
|
||||
int rc;
|
||||
|
||||
dc.op = op;
|
||||
dc.target = mt;
|
||||
dc.conn = op->o_conn;
|
||||
dc.rs = rs;
|
||||
dc.ctx = "addDN";
|
||||
|
||||
mdn.bv_len = 0;
|
||||
|
||||
switch (asyncmeta_dn_massage( &dc, &bc->op->o_req_dn, &mdn ) )
|
||||
{
|
||||
case LDAP_SUCCESS:
|
||||
break;
|
||||
case LDAP_UNWILLING_TO_PERFORM:
|
||||
rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
|
||||
rs->sr_text = "Operation not allowed";
|
||||
retcode = META_SEARCH_ERR;
|
||||
goto doreturn;
|
||||
default:
|
||||
rs->sr_err = LDAP_NO_SUCH_OBJECT;
|
||||
retcode = META_SEARCH_NOT_CANDIDATE;
|
||||
goto doreturn;
|
||||
}
|
||||
dc.memctx = op->o_tmpmemctx;
|
||||
dc.to_from = MASSAGE_REQ;
|
||||
asyncmeta_dn_massage( &dc, &op->o_req_dn, &mdn );
|
||||
|
||||
/* Count number of attributes in entry ( +1 ) */
|
||||
for ( i = 1, a = op->ora_e->e_attrs; a; i++, a = a->a_next );
|
||||
|
||||
/* Create array of LDAPMods for ldap_add() */
|
||||
attrs = ch_malloc( sizeof( LDAPMod * )*i );
|
||||
attrs = op->o_tmpalloc(sizeof( LDAPMod * )*i, op->o_tmpmemctx);
|
||||
|
||||
dc.ctx = "addAttrDN";
|
||||
isupdate = be_shadow_update( op );
|
||||
for ( i = 0, a = op->ora_e->e_attrs; a; a = a->a_next ) {
|
||||
int j, is_oc = 0;
|
||||
int j;
|
||||
|
||||
if ( !isupdate && !get_relax( op ) && a->a_desc->ad_type->sat_no_user_mod )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( a->a_desc == slap_schema.si_ad_objectClass
|
||||
|| a->a_desc == slap_schema.si_ad_structuralObjectClass )
|
||||
{
|
||||
is_oc = 1;
|
||||
mapped = a->a_desc->ad_cname;
|
||||
|
||||
} else {
|
||||
asyncmeta_map( &mt->mt_rwmap.rwm_at,
|
||||
&a->a_desc->ad_cname, &mapped, BACKLDAP_MAP );
|
||||
if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
attrs[ i ] = ch_malloc( sizeof( LDAPMod ) );
|
||||
attrs[ i ] = op->o_tmpalloc( sizeof( LDAPMod ), op->o_tmpmemctx );
|
||||
if ( attrs[ i ] == NULL ) {
|
||||
continue;
|
||||
}
|
||||
attrs[ i ]->mod_op = LDAP_MOD_BVALUES;
|
||||
attrs[ i ]->mod_type = mapped.bv_val;
|
||||
|
||||
if ( is_oc ) {
|
||||
for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); j++ );
|
||||
|
||||
attrs[ i ]->mod_bvalues =
|
||||
(struct berval **)ch_malloc( ( j + 1 ) *
|
||||
sizeof( struct berval * ) );
|
||||
for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); ) {
|
||||
struct ldapmapping *mapping;
|
||||
|
||||
asyncmeta_mapping( &mt->mt_rwmap.rwm_oc,
|
||||
&a->a_vals[ j ], &mapping, BACKLDAP_MAP );
|
||||
|
||||
if ( mapping == NULL ) {
|
||||
if ( mt->mt_rwmap.rwm_oc.drop_missing ) {
|
||||
continue;
|
||||
}
|
||||
attrs[ i ]->mod_bvalues[ j ] = &a->a_vals[ j ];
|
||||
|
||||
} else {
|
||||
attrs[ i ]->mod_bvalues[ j ] = &mapping->dst;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
attrs[ i ]->mod_bvalues[ j ] = NULL;
|
||||
|
||||
} else {
|
||||
/*
|
||||
* FIXME: dn-valued attrs should be rewritten
|
||||
* to allow their use in ACLs at the back-ldap
|
||||
* level.
|
||||
*/
|
||||
if ( a->a_desc->ad_type->sat_syntax ==
|
||||
slap_schema.si_syn_distinguishedName )
|
||||
{
|
||||
(void)asyncmeta_dnattr_rewrite( &dc, a->a_vals );
|
||||
if ( a->a_vals == NULL ) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); j++ )
|
||||
;
|
||||
|
||||
attrs[ i ]->mod_bvalues = ch_malloc( ( j + 1 ) * sizeof( struct berval * ) );
|
||||
for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); j++ ) {
|
||||
attrs[ i ]->mod_bvalues[ j ] = &a->a_vals[ j ];
|
||||
}
|
||||
attrs[ i ]->mod_bvalues[ j ] = NULL;
|
||||
attrs[ i ]->mod_type = a->a_desc->ad_cname.bv_val;
|
||||
j = a->a_numvals;
|
||||
attrs[ i ]->mod_bvalues = op->o_tmpalloc( ( j + 1 ) * sizeof( struct berval * ), op->o_tmpmemctx );
|
||||
for (j=0; j<a->a_numvals; j++) {
|
||||
attrs[ i ]->mod_bvalues[ j ] = op->o_tmpalloc( sizeof( struct berval ), op->o_tmpmemctx );
|
||||
if ( a->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
|
||||
asyncmeta_dn_massage( &dc, &a->a_vals[ j ], attrs[ i ]->mod_bvalues[ j ] );
|
||||
else
|
||||
*attrs[ i ]->mod_bvalues[ j ] = a->a_vals[ j ];
|
||||
}
|
||||
|
||||
attrs[ i ]->mod_bvalues[ j ] = NULL;
|
||||
i++;
|
||||
}
|
||||
attrs[ i ] = NULL;
|
||||
|
||||
retry:;
|
||||
asyncmeta_set_msc_time(msc);
|
||||
|
||||
ctrls = op->o_ctrls;
|
||||
if ( asyncmeta_controls_add( op, rs, mc, candidate, &ctrls ) != LDAP_SUCCESS )
|
||||
if ( asyncmeta_controls_add( op, rs, mc, candidate, bc->is_root, &ctrls ) != LDAP_SUCCESS )
|
||||
{
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
retcode = META_SEARCH_ERR;
|
||||
goto done;
|
||||
}
|
||||
/* someone might have reset the connection */
|
||||
if (!( LDAP_BACK_CONN_ISBOUND( msc )
|
||||
|| LDAP_BACK_CONN_ISANON( msc )) || msc->msc_ld == NULL ) {
|
||||
Debug( asyncmeta_debug, "msc %p not initialized at %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
goto error_unavailable;
|
||||
}
|
||||
|
||||
ber = ldap_build_add_req( msc->msc_ld, mdn.bv_val, attrs, ctrls, NULL, &msgid);
|
||||
if (!ber) {
|
||||
Debug( asyncmeta_debug, "%s asyncmeta_back_add_start: Operation encoding failed with errno %d\n",
|
||||
op->o_log_prefix, msc->msc_ld->ld_errno );
|
||||
rs->sr_err = LDAP_OPERATIONS_ERROR;
|
||||
rs->sr_text = "Failed to encode proxied request";
|
||||
retcode = META_SEARCH_ERR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (ber) {
|
||||
candidates[ candidate ].sr_msgid = msgid;
|
||||
rc = ldap_send_initial_request( msc->msc_ld, LDAP_REQ_ADD,
|
||||
mdn.bv_val, ber, msgid );
|
||||
if (rc == msgid)
|
||||
rc = LDAP_SUCCESS;
|
||||
else
|
||||
rc = LDAP_SERVER_DOWN;
|
||||
struct timeval tv = {0, mt->mt_network_timeout*1000};
|
||||
ber_socket_t s;
|
||||
if (!( LDAP_BACK_CONN_ISBOUND( msc )
|
||||
|| LDAP_BACK_CONN_ISANON( msc )) || msc->msc_ld == NULL ) {
|
||||
Debug( asyncmeta_debug, "msc %p not initialized at %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
goto error_unavailable;
|
||||
}
|
||||
ldap_get_option( msc->msc_ld, LDAP_OPT_DESC, &s );
|
||||
if (s < 0) {
|
||||
Debug( asyncmeta_debug, "msc %p not initialized at %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
goto error_unavailable;
|
||||
}
|
||||
|
||||
rc = ldap_int_poll( msc->msc_ld, s, &tv, 1);
|
||||
if (rc < 0) {
|
||||
Debug( asyncmeta_debug, "msc %p not writable within network timeout %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
if ((msc->msc_result_time + META_BACK_RESULT_INTERVAL) < slap_get_time()) {
|
||||
rc = LDAP_SERVER_DOWN;
|
||||
} else {
|
||||
goto error_unavailable;
|
||||
}
|
||||
} else {
|
||||
candidates[ candidate ].sr_msgid = msgid;
|
||||
rc = ldap_send_initial_request( msc->msc_ld, LDAP_REQ_ADD,
|
||||
mdn.bv_val, ber, msgid );
|
||||
if (rc == msgid)
|
||||
rc = LDAP_SUCCESS;
|
||||
else
|
||||
rc = LDAP_SERVER_DOWN;
|
||||
ber = NULL;
|
||||
}
|
||||
|
||||
switch ( rc ) {
|
||||
case LDAP_SUCCESS:
|
||||
retcode = META_SEARCH_CANDIDATE;
|
||||
asyncmeta_set_msc_time(msc);
|
||||
break;
|
||||
goto done;
|
||||
|
||||
case LDAP_SERVER_DOWN:
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_clear_one_msc(NULL, mc, candidate);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
if ( nretries && asyncmeta_retry( op, rs, &mc, candidate, LDAP_BACK_DONTSEND ) ) {
|
||||
nretries = 0;
|
||||
/* if the identity changed, there might be need to re-authz */
|
||||
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
||||
goto retry;
|
||||
/* do not lock if called from asyncmeta_handle_bind_result. Also do not reset the connection */
|
||||
if (do_lock > 0) {
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_reset_msc(NULL, mc, candidate, 0, __FUNCTION__);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
}
|
||||
|
||||
/* fall though*/
|
||||
default:
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
retcode = META_SEARCH_ERR;
|
||||
Debug( asyncmeta_debug, "msc %p ldap_send_initial_request failed. %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
goto error_unavailable;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
error_unavailable:
|
||||
if (ber)
|
||||
ber_free(ber, 1);
|
||||
switch (bc->nretries[candidate]) {
|
||||
case -1: /* nretries = forever */
|
||||
ldap_pvt_thread_yield();
|
||||
retcode = META_SEARCH_NEED_BIND;
|
||||
break;
|
||||
case 0: /* no retries left */
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
rs->sr_err = LDAP_UNAVAILABLE;
|
||||
rs->sr_text = "Unable to send add request to target";
|
||||
retcode = META_SEARCH_ERR;
|
||||
break;
|
||||
default: /* more retries left - try to rebind and go again */
|
||||
retcode = META_SEARCH_NEED_BIND;
|
||||
bc->nretries[candidate]--;
|
||||
ldap_pvt_thread_yield();
|
||||
break;
|
||||
}
|
||||
|
||||
done:
|
||||
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
||||
|
||||
for ( --i; i >= 0; --i ) {
|
||||
free( attrs[ i ]->mod_bvalues );
|
||||
free( attrs[ i ] );
|
||||
}
|
||||
free( attrs );
|
||||
if ( mdn.bv_val != op->ora_e->e_dn ) {
|
||||
free( mdn.bv_val );
|
||||
BER_BVZERO( &mdn );
|
||||
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
|
||||
op->o_tmpfree( mdn.bv_val, op->o_tmpmemctx );
|
||||
}
|
||||
|
||||
doreturn:;
|
||||
Debug( LDAP_DEBUG_TRACE, "%s <<< asyncmeta_back_add_start[%p]=%d\n", op->o_log_prefix, msc, candidates[candidate].sr_msgid );
|
||||
return retcode;
|
||||
}
|
||||
|
|
@ -252,26 +241,31 @@ asyncmeta_back_add( Operation *op, SlapReply *rs )
|
|||
a_metatarget_t *mt;
|
||||
a_metaconn_t *mc;
|
||||
int rc, candidate = -1;
|
||||
OperationBuffer opbuf;
|
||||
void *thrctx = op->o_threadctx;
|
||||
bm_context_t *bc;
|
||||
SlapReply *candidates;
|
||||
slap_callback *cb = op->o_callback;
|
||||
time_t current_time = slap_get_time();
|
||||
int max_pending_ops = (mi->mi_max_pending_ops == 0) ? META_BACK_CFG_MAX_PENDING_OPS : mi->mi_max_pending_ops;
|
||||
|
||||
Debug(LDAP_DEBUG_ARGS, "==> asyncmeta_back_add: %s\n",
|
||||
Debug(LDAP_DEBUG_TRACE, "==> asyncmeta_back_add: %s\n",
|
||||
op->o_req_dn.bv_val );
|
||||
|
||||
asyncmeta_new_bm_context(op, rs, &bc, mi->mi_ntargets );
|
||||
if (current_time > op->o_time) {
|
||||
Debug(asyncmeta_debug, "==> asyncmeta_back_add[%s]: o_time:[%ld], current time: [%ld]\n",
|
||||
op->o_log_prefix, op->o_time, current_time );
|
||||
}
|
||||
|
||||
asyncmeta_new_bm_context(op, rs, &bc, mi->mi_ntargets, mi );
|
||||
if (bc == NULL) {
|
||||
rs->sr_err = LDAP_OTHER;
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
send_ldap_result(op, rs);
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
candidates = bc->candidates;
|
||||
mc = asyncmeta_getconn( op, rs, candidates, &candidate, LDAP_BACK_DONTSEND, 0);
|
||||
if ( !mc || rs->sr_err != LDAP_SUCCESS) {
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
send_ldap_result(op, rs);
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
|
|
@ -280,16 +274,39 @@ asyncmeta_back_add( Operation *op, SlapReply *rs )
|
|||
bc->retrying = LDAP_BACK_RETRYING;
|
||||
bc->sendok = ( LDAP_BACK_SENDRESULT | bc->retrying );
|
||||
bc->stoptime = op->o_time + bc->timeout;
|
||||
bc->bc_active = 1;
|
||||
|
||||
if (mc->pending_ops >= max_pending_ops) {
|
||||
rs->sr_err = LDAP_BUSY;
|
||||
rs->sr_text = "Maximum pending ops limit exceeded";
|
||||
send_ldap_result(op, rs);
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
rc = asyncmeta_add_message_queue(mc, bc);
|
||||
mc->mc_conns[candidate].msc_active++;
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
|
||||
if (rc != LDAP_SUCCESS) {
|
||||
rs->sr_err = LDAP_BUSY;
|
||||
rs->sr_text = "Maximum pending ops limit exceeded";
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
send_ldap_result(op, rs);
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
mc->mc_conns[candidate].msc_active--;
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
retry:
|
||||
current_time = slap_get_time();
|
||||
if (bc->timeout && bc->stoptime < current_time) {
|
||||
int timeout_err;
|
||||
timeout_err = op->o_protocol >= LDAP_VERSION3 ?
|
||||
LDAP_ADMINLIMIT_EXCEEDED : LDAP_OTHER;
|
||||
rs->sr_err = timeout_err;
|
||||
rs->sr_text = "Operation timed out before it was sent to target";
|
||||
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
|
@ -298,72 +315,49 @@ asyncmeta_back_add( Operation *op, SlapReply *rs )
|
|||
{
|
||||
case META_SEARCH_CANDIDATE:
|
||||
/* target is already bound, just send the request */
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_add: "
|
||||
"cnd=\"%ld\"\n", op->o_log_prefix, candidate );
|
||||
Debug(LDAP_DEBUG_TRACE , "%s asyncmeta_back_add: "
|
||||
"cnd=\"%d\"\n", op->o_log_prefix, candidate );
|
||||
|
||||
rc = asyncmeta_back_add_start( op, rs, mc, bc, candidate);
|
||||
rc = asyncmeta_back_add_start( op, rs, mc, bc, candidate, 1);
|
||||
if (rc == META_SEARCH_ERR) {
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_drop_bc(mc, bc);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||
goto finish;
|
||||
|
||||
} else if (rc == META_SEARCH_NEED_BIND) {
|
||||
goto retry;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case META_SEARCH_NOT_CANDIDATE:
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_add: NOT_CANDIDATE "
|
||||
"cnd=\"%ld\"\n", op->o_log_prefix, candidate );
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_drop_bc(mc, bc);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
"cnd=\"%d\"\n", op->o_log_prefix, candidate );
|
||||
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||
goto finish;
|
||||
|
||||
case META_SEARCH_NEED_BIND:
|
||||
case META_SEARCH_CONNECTING:
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_add: NEED_BIND "
|
||||
"cnd=\"%ld\" %p\n", op->o_log_prefix, candidate , &mc->mc_conns[candidate]);
|
||||
rc = asyncmeta_dobind_init(op, rs, bc, mc, candidate);
|
||||
if (rc == META_SEARCH_ERR) {
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_drop_bc(mc, bc);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
goto finish;
|
||||
}
|
||||
break;
|
||||
case META_SEARCH_BINDING:
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_add: BINDING "
|
||||
"cnd=\"%ld\" %p\n", op->o_log_prefix, candidate , &mc->mc_conns[candidate]);
|
||||
/* Todo add the context to the message queue but do not send the request
|
||||
the receiver must send this when we are done binding */
|
||||
/* question - how would do receiver know to which targets??? */
|
||||
break;
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_add: BINDING "
|
||||
"cnd=\"%d\" %p\n", op->o_log_prefix, candidate , &mc->mc_conns[candidate]);
|
||||
/* add the context to the message queue but do not send the request
|
||||
the receiver must send this when we are done binding */
|
||||
break;
|
||||
|
||||
case META_SEARCH_ERR:
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_add: ERR "
|
||||
"cnd=\"%ldd\"\n", op->o_log_prefix, candidate );
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
candidates[ candidate ].sr_type = REP_RESULT;
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_drop_bc(mc, bc);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
goto finish;
|
||||
default:
|
||||
assert( 0 );
|
||||
break;
|
||||
}
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_add: ERR "
|
||||
"cnd=\"%d\"\n", op->o_log_prefix, candidate );
|
||||
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||
goto finish;
|
||||
default:
|
||||
assert( 0 );
|
||||
break;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
mc->mc_conns[candidate].msc_active--;
|
||||
asyncmeta_start_one_listener(mc, candidates, bc, candidate);
|
||||
bc->bc_active--;
|
||||
asyncmeta_memctx_toggle(thrctx);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
rs->sr_err = SLAPD_ASYNCOP;
|
||||
finish:
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,18 +27,12 @@
|
|||
#ifndef SLAPD_ASYNCMETA_H
|
||||
#define SLAPD_ASYNCMETA_H
|
||||
|
||||
#ifndef ENABLE_REWRITE
|
||||
#error "--enable-rewrite is required!"
|
||||
#endif
|
||||
|
||||
#ifdef LDAP_DEVEL
|
||||
#define SLAPD_META_CLIENT_PR 1
|
||||
#endif /* LDAP_DEVEL */
|
||||
|
||||
#include "proto-asyncmeta.h"
|
||||
|
||||
/* String rewrite library */
|
||||
#include "rewrite.h"
|
||||
#include "ldap_rq.h"
|
||||
|
||||
LDAP_BEGIN_DECL
|
||||
|
|
@ -50,108 +44,6 @@ LDAP_BEGIN_DECL
|
|||
#define META_BACK_PRINT_CONNTREE 0
|
||||
#endif /* !META_BACK_PRINT_CONNTREE */
|
||||
|
||||
/* from back-ldap.h before rwm removal */
|
||||
struct ldapmap {
|
||||
int drop_missing;
|
||||
|
||||
Avlnode *map;
|
||||
Avlnode *remap;
|
||||
};
|
||||
|
||||
struct ldapmapping {
|
||||
struct berval src;
|
||||
struct berval dst;
|
||||
};
|
||||
|
||||
struct ldaprwmap {
|
||||
/*
|
||||
* DN rewriting
|
||||
*/
|
||||
struct rewrite_info *rwm_rw;
|
||||
BerVarray rwm_bva_rewrite;
|
||||
|
||||
/*
|
||||
* Attribute/objectClass mapping
|
||||
*/
|
||||
struct ldapmap rwm_oc;
|
||||
struct ldapmap rwm_at;
|
||||
BerVarray rwm_bva_map;
|
||||
};
|
||||
|
||||
/* Whatever context asyncmeta_dn_massage needs... */
|
||||
typedef struct a_dncookie {
|
||||
struct a_metatarget_t *target;
|
||||
|
||||
Connection *conn;
|
||||
char *ctx;
|
||||
SlapReply *rs;
|
||||
} a_dncookie;
|
||||
|
||||
int asyncmeta_dn_massage(a_dncookie *dc, struct berval *dn,
|
||||
struct berval *res);
|
||||
|
||||
extern int asyncmeta_conn_dup( void *c1, void *c2 );
|
||||
extern void asyncmeta_conn_free( void *c );
|
||||
|
||||
/* attributeType/objectClass mapping */
|
||||
int asyncmeta_mapping_cmp (const void *, const void *);
|
||||
int asyncmeta_mapping_dup (void *, void *);
|
||||
|
||||
void asyncmeta_map_init ( struct ldapmap *lm, struct ldapmapping ** );
|
||||
int asyncmeta_mapping ( struct ldapmap *map, struct berval *s,
|
||||
struct ldapmapping **m, int remap );
|
||||
void asyncmeta_map ( struct ldapmap *map, struct berval *s, struct berval *m,
|
||||
int remap );
|
||||
#define BACKLDAP_MAP 0
|
||||
#define BACKLDAP_REMAP 1
|
||||
char *
|
||||
asyncmeta_map_filter(
|
||||
struct ldapmap *at_map,
|
||||
struct ldapmap *oc_map,
|
||||
struct berval *f,
|
||||
int remap );
|
||||
|
||||
int
|
||||
asyncmeta_map_attrs(
|
||||
Operation *op,
|
||||
struct ldapmap *at_map,
|
||||
AttributeName *a,
|
||||
int remap,
|
||||
char ***mapped_attrs );
|
||||
|
||||
extern int
|
||||
asyncmeta_filter_map_rewrite(
|
||||
a_dncookie *dc,
|
||||
Filter *f,
|
||||
struct berval *fstr,
|
||||
int remap,
|
||||
void *memctx );
|
||||
|
||||
/* suffix massaging by means of librewrite */
|
||||
extern int
|
||||
asyncmeta_suffix_massage_config( struct rewrite_info *info,
|
||||
struct berval *pvnc,
|
||||
struct berval *nvnc,
|
||||
struct berval *prnc,
|
||||
struct berval *nrnc );
|
||||
|
||||
extern int
|
||||
asyncmeta_back_referral_result_rewrite(
|
||||
a_dncookie *dc,
|
||||
BerVarray a_vals,
|
||||
void *memctx );
|
||||
extern int
|
||||
asyncmeta_dnattr_rewrite(
|
||||
a_dncookie *dc,
|
||||
BerVarray a_vals );
|
||||
extern int
|
||||
asyncmeta_dnattr_result_rewrite(
|
||||
a_dncookie *dc,
|
||||
BerVarray a_vals );
|
||||
|
||||
|
||||
/* (end of) from back-ldap.h before rwm removal */
|
||||
|
||||
/*
|
||||
* A a_metasingleconn_t can be in the following, mutually exclusive states:
|
||||
*
|
||||
|
|
@ -171,6 +63,7 @@ asyncmeta_dnattr_result_rewrite(
|
|||
|
||||
#define META_BACK_FCONN_INITED (0x00100000U)
|
||||
#define META_BACK_FCONN_CREATING (0x00200000U)
|
||||
#define META_BACK_FCONN_INVALID (0x00400000U)
|
||||
|
||||
#define META_BACK_CONN_INITED(lc) LDAP_BACK_CONN_ISSET((lc), META_BACK_FCONN_INITED)
|
||||
#define META_BACK_CONN_INITED_SET(lc) LDAP_BACK_CONN_SET((lc), META_BACK_FCONN_INITED)
|
||||
|
|
@ -180,6 +73,9 @@ asyncmeta_dnattr_result_rewrite(
|
|||
#define META_BACK_CONN_CREATING_SET(lc) LDAP_BACK_CONN_SET((lc), META_BACK_FCONN_CREATING)
|
||||
#define META_BACK_CONN_CREATING_CLEAR(lc) LDAP_BACK_CONN_CLEAR((lc), META_BACK_FCONN_CREATING)
|
||||
#define META_BACK_CONN_CREATING_CPY(lc, mlc) LDAP_BACK_CONN_CPY((lc), META_BACK_FCONN_CREATING, (mlc))
|
||||
#define META_BACK_CONN_INVALID(lc) LDAP_BACK_CONN_ISSET((lc), META_BACK_FCONN_INVALID)
|
||||
#define META_BACK_CONN_INVALID_SET(lc) LDAP_BACK_CONN_SET((lc), META_BACK_FCONN_INVALID)
|
||||
#define META_BACK_CONN_INVALID_CLEAR(lc) LDAP_BACK_CONN_CLEAR((lc), META_BACK_FCONN_INVALID)
|
||||
|
||||
struct a_metainfo_t;
|
||||
struct a_metaconn_t;
|
||||
|
|
@ -190,20 +86,25 @@ struct a_metatarget_t;
|
|||
#define META_RETRYING ((ber_tag_t)0x4)
|
||||
|
||||
typedef struct bm_context_t {
|
||||
LDAP_SLIST_ENTRY(bm_context_t) bc_next;
|
||||
LDAP_STAILQ_ENTRY(bm_context_t) bc_next;
|
||||
struct a_metaconn_t *bc_mc;
|
||||
time_t timeout;
|
||||
time_t stoptime;
|
||||
ldap_back_send_t sendok;
|
||||
ldap_back_send_t retrying;
|
||||
int candidate_match;
|
||||
int sent;
|
||||
int bc_active;
|
||||
volatile int bc_active;
|
||||
int searchtime; /* stoptime is a search timelimit */
|
||||
int is_ok;
|
||||
int is_root;
|
||||
volatile sig_atomic_t bc_invalid;
|
||||
SlapReply rs;
|
||||
Operation *op;
|
||||
Operation copy_op;
|
||||
LDAPControl **ctrls;
|
||||
int *msgids;
|
||||
int *nretries; /* number of times to retry a failed send on an msc */
|
||||
struct berval c_peer_name; /* peer name of original op->o_conn*/
|
||||
SlapReply *candidates;
|
||||
} bm_context_t;
|
||||
|
||||
|
|
@ -226,14 +127,16 @@ typedef struct a_metasingleconn_t {
|
|||
LDAP *msc_ld;
|
||||
LDAP *msc_ldr;
|
||||
time_t msc_time;
|
||||
time_t msc_binding_time;
|
||||
time_t msc_result_time;
|
||||
struct berval msc_bound_ndn;
|
||||
struct berval msc_cred;
|
||||
unsigned msc_mscflags;
|
||||
|
||||
/* NOTE: lc_lcflags is redefined to msc_mscflags to reuse the macros
|
||||
* defined for back-ldap */
|
||||
#define lc_lcflags msc_mscflags
|
||||
int msc_pending_ops;
|
||||
int msc_timeout_ops;
|
||||
volatile int msc_active;
|
||||
/* Connection for the select */
|
||||
Connection *conn;
|
||||
} a_metasingleconn_t;
|
||||
|
|
@ -267,7 +170,7 @@ typedef struct a_metaconn_t {
|
|||
int pending_ops;
|
||||
ldap_pvt_thread_mutex_t mc_om_mutex;
|
||||
/* queue for pending operations */
|
||||
LDAP_SLIST_HEAD(BCList, bm_context_t) mc_om_list;
|
||||
LDAP_STAILQ_HEAD(BCList, bm_context_t) mc_om_list;
|
||||
/* supersedes the connection stuff */
|
||||
a_metasingleconn_t *mc_conns;
|
||||
} a_metaconn_t;
|
||||
|
|
@ -309,7 +212,7 @@ typedef struct a_metacommon_t {
|
|||
#define META_RETRY_UNDEFINED (-2)
|
||||
#define META_RETRY_FOREVER (-1)
|
||||
#define META_RETRY_NEVER (0)
|
||||
#define META_RETRY_DEFAULT (10)
|
||||
#define META_RETRY_DEFAULT (2)
|
||||
|
||||
unsigned mc_flags;
|
||||
#define META_BACK_CMN_ISSET(mc,f) ( ( (mc)->mc_flags & (f) ) == (f) )
|
||||
|
|
@ -359,6 +262,9 @@ typedef struct a_metatarget_t {
|
|||
struct berval mt_psuffix; /* pretty suffix */
|
||||
struct berval mt_nsuffix; /* normalized suffix */
|
||||
|
||||
struct berval mt_lsuffixm; /* local suffix for massage */
|
||||
struct berval mt_rsuffixm; /* remote suffix for massage */
|
||||
|
||||
struct berval mt_binddn;
|
||||
struct berval mt_bindpw;
|
||||
|
||||
|
|
@ -379,8 +285,6 @@ typedef struct a_metatarget_t {
|
|||
#define mt_idassert_flags mt_idassert.si_flags
|
||||
#define mt_idassert_authz mt_idassert.si_authz
|
||||
|
||||
struct ldaprwmap mt_rwmap;
|
||||
|
||||
sig_atomic_t mt_isquarantined;
|
||||
ldap_pvt_thread_mutex_t mt_quarantine_mutex;
|
||||
|
||||
|
|
@ -520,6 +424,7 @@ typedef struct a_metainfo_t {
|
|||
int mi_next_conn;
|
||||
a_metaconn_t *mi_conns;
|
||||
|
||||
struct berval mi_suffix;
|
||||
} a_metainfo_t;
|
||||
|
||||
typedef enum meta_op_type {
|
||||
|
|
@ -528,6 +433,33 @@ typedef enum meta_op_type {
|
|||
META_OP_REQUIRE_ALL
|
||||
} meta_op_type;
|
||||
|
||||
/* Whatever context asyncmeta_dn_massage needs... */
|
||||
typedef struct a_dncookie {
|
||||
Operation *op;
|
||||
struct a_metatarget_t *target;
|
||||
void *memctx;
|
||||
int to_from;
|
||||
} a_dncookie;
|
||||
|
||||
|
||||
#define MASSAGE_REQ 0
|
||||
#define MASSAGE_REP 1
|
||||
|
||||
extern void
|
||||
asyncmeta_dn_massage(a_dncookie *dc, struct berval *dn,
|
||||
struct berval *res);
|
||||
|
||||
extern void
|
||||
asyncmeta_filter_map_rewrite(
|
||||
a_dncookie *dc,
|
||||
Filter *f,
|
||||
struct berval *fstr );
|
||||
|
||||
extern void
|
||||
asyncmeta_back_referral_result_rewrite(
|
||||
a_dncookie *dc,
|
||||
BerVarray a_vals );
|
||||
|
||||
extern a_metaconn_t *
|
||||
asyncmeta_getconn(
|
||||
Operation *op,
|
||||
|
|
@ -537,17 +469,6 @@ asyncmeta_getconn(
|
|||
ldap_back_send_t sendok,
|
||||
int alloc_new);
|
||||
|
||||
extern int
|
||||
asyncmeta_retry(
|
||||
Operation *op,
|
||||
SlapReply *rs,
|
||||
a_metaconn_t **mcp,
|
||||
int candidate,
|
||||
ldap_back_send_t sendok );
|
||||
|
||||
extern void
|
||||
asyncmeta_conn_free(
|
||||
void *v_mc );
|
||||
|
||||
extern int
|
||||
asyncmeta_init_one_conn(
|
||||
|
|
@ -566,24 +487,6 @@ asyncmeta_quarantine(
|
|||
SlapReply *rs,
|
||||
int candidate );
|
||||
|
||||
extern int
|
||||
asyncmeta_dobind(
|
||||
Operation *op,
|
||||
SlapReply *rs,
|
||||
a_metaconn_t *mc,
|
||||
ldap_back_send_t sendok,
|
||||
SlapReply *candidates);
|
||||
|
||||
extern int
|
||||
asyncmeta_single_dobind(
|
||||
Operation *op,
|
||||
SlapReply *rs,
|
||||
a_metaconn_t **mcp,
|
||||
int candidate,
|
||||
ldap_back_send_t sendok,
|
||||
int retries,
|
||||
int dolock );
|
||||
|
||||
extern int
|
||||
asyncmeta_proxy_authz_cred(
|
||||
a_metaconn_t *mc,
|
||||
|
|
@ -595,31 +498,13 @@ asyncmeta_proxy_authz_cred(
|
|||
struct berval *bindcred,
|
||||
int *method );
|
||||
|
||||
extern int
|
||||
asyncmeta_cancel(
|
||||
a_metaconn_t *mc,
|
||||
Operation *op,
|
||||
SlapReply *rs,
|
||||
ber_int_t msgid,
|
||||
int candidate,
|
||||
ldap_back_send_t sendok );
|
||||
|
||||
extern int
|
||||
asyncmeta_op_result(
|
||||
a_metaconn_t *mc,
|
||||
Operation *op,
|
||||
SlapReply *rs,
|
||||
int candidate,
|
||||
ber_int_t msgid,
|
||||
time_t timeout,
|
||||
ldap_back_send_t sendok );
|
||||
|
||||
extern int
|
||||
asyncmeta_controls_add(
|
||||
Operation *op,
|
||||
SlapReply *rs,
|
||||
a_metaconn_t *mc,
|
||||
int candidate,
|
||||
int isroot,
|
||||
LDAPControl ***pctrls );
|
||||
|
||||
extern int
|
||||
|
|
@ -682,9 +567,6 @@ asyncmeta_dncache_delete_entry(
|
|||
extern void
|
||||
asyncmeta_dncache_free( void *entry );
|
||||
|
||||
extern void
|
||||
asyncmeta_back_map_free( struct ldapmap *lm );
|
||||
|
||||
extern int
|
||||
asyncmeta_subtree_destroy( a_metasubtree_t *ms );
|
||||
|
||||
|
|
@ -724,12 +606,12 @@ void asyncmeta_clear_bm_context(bm_context_t *bc);
|
|||
|
||||
int asyncmeta_add_message_queue(a_metaconn_t *mc, bm_context_t *bc);
|
||||
void asyncmeta_drop_bc(a_metaconn_t *mc, bm_context_t *bc);
|
||||
void asyncmeta_drop_bc_from_fconn(bm_context_t *bc);
|
||||
|
||||
bm_context_t *
|
||||
asyncmeta_find_message(ber_int_t msgid, a_metaconn_t *mc, int candidate);
|
||||
|
||||
bm_context_t *
|
||||
asyncmeta_find_message_by_opmsguid(ber_int_t msgid, a_metaconn_t *mc, int remove);
|
||||
void asyncmeta_memctx_toggle(void *thrctx);
|
||||
|
||||
void* asyncmeta_op_handle_result(void *ctx, void *arg);
|
||||
int asyncmeta_back_cleanup( Operation *op, SlapReply *rs, bm_context_t *bm );
|
||||
|
|
@ -738,16 +620,19 @@ int
|
|||
asyncmeta_clear_one_msc(
|
||||
Operation *op,
|
||||
a_metaconn_t *msc,
|
||||
int candidate );
|
||||
int candidate,
|
||||
int unbind,
|
||||
const char * caller);
|
||||
|
||||
a_metaconn_t *
|
||||
asyncmeta_get_next_mc( a_metainfo_t *mi );
|
||||
|
||||
void* asyncmeta_timeout_loop(void *ctx, void *arg);
|
||||
|
||||
int
|
||||
asyncmeta_start_timeout_loop(a_metatarget_t *mt, a_metainfo_t *mi);
|
||||
|
||||
void asyncmeta_set_msc_time(a_metasingleconn_t *msc);
|
||||
void asyncmeta_clear_message_queue(a_metasingleconn_t *msc);
|
||||
|
||||
int asyncmeta_back_cancel(
|
||||
a_metaconn_t *mc,
|
||||
|
|
@ -755,25 +640,15 @@ int asyncmeta_back_cancel(
|
|||
ber_int_t msgid,
|
||||
int candidate );
|
||||
|
||||
int
|
||||
asyncmeta_back_cancel_msc(
|
||||
Operation *op,
|
||||
SlapReply *rs,
|
||||
ber_int_t msgid,
|
||||
a_metasingleconn_t *msc,
|
||||
int candidate,
|
||||
ldap_back_send_t sendok );
|
||||
|
||||
int
|
||||
asyncmeta_back_abandon_candidate(
|
||||
a_metaconn_t *mc,
|
||||
Operation *op,
|
||||
ber_int_t msgid,
|
||||
int candidate );
|
||||
void
|
||||
asyncmeta_send_result(bm_context_t* bc, int error, char *text);
|
||||
|
||||
int asyncmeta_new_bm_context(Operation *op, SlapReply *rs, bm_context_t **new_bc, int ntargets);
|
||||
int asyncmeta_new_bm_context(Operation *op,
|
||||
SlapReply *rs,
|
||||
bm_context_t **new_bc,
|
||||
int ntargets,
|
||||
a_metainfo_t *mi);
|
||||
|
||||
int asyncmeta_start_listeners(a_metaconn_t *mc, SlapReply *candidates, bm_context_t *bc);
|
||||
int asyncmeta_start_one_listener(a_metaconn_t *mc, SlapReply *candidates, bm_context_t *bc, int candidate);
|
||||
|
||||
|
|
@ -785,7 +660,8 @@ asyncmeta_back_search_start(
|
|||
bm_context_t *bc,
|
||||
int candidate,
|
||||
struct berval *prcookie,
|
||||
ber_int_t prsize );
|
||||
ber_int_t prsize,
|
||||
int do_lock);
|
||||
|
||||
meta_search_candidate_t
|
||||
asyncmeta_dobind_init(
|
||||
|
|
@ -808,40 +684,97 @@ asyncmeta_back_add_start(Operation *op,
|
|||
SlapReply *rs,
|
||||
a_metaconn_t *mc,
|
||||
bm_context_t *bc,
|
||||
int candidate);
|
||||
int candidate,
|
||||
int do_lock);
|
||||
meta_search_candidate_t
|
||||
asyncmeta_back_modify_start(Operation *op,
|
||||
SlapReply *rs,
|
||||
a_metaconn_t *mc,
|
||||
bm_context_t *bc,
|
||||
int candidate);
|
||||
SlapReply *rs,
|
||||
a_metaconn_t *mc,
|
||||
bm_context_t *bc,
|
||||
int candidate,
|
||||
int do_lock);
|
||||
|
||||
meta_search_candidate_t
|
||||
asyncmeta_back_modrdn_start(Operation *op,
|
||||
SlapReply *rs,
|
||||
a_metaconn_t *mc,
|
||||
bm_context_t *bc,
|
||||
int candidate);
|
||||
SlapReply *rs,
|
||||
a_metaconn_t *mc,
|
||||
bm_context_t *bc,
|
||||
int candidate,
|
||||
int do_lock);
|
||||
meta_search_candidate_t
|
||||
asyncmeta_back_delete_start(Operation *op,
|
||||
SlapReply *rs,
|
||||
a_metaconn_t *mc,
|
||||
bm_context_t *bc,
|
||||
int candidate);
|
||||
SlapReply *rs,
|
||||
a_metaconn_t *mc,
|
||||
bm_context_t *bc,
|
||||
int candidate,
|
||||
int do_lock);
|
||||
|
||||
meta_search_candidate_t
|
||||
asyncmeta_back_compare_start(Operation *op,
|
||||
SlapReply *rs,
|
||||
a_metaconn_t *mc,
|
||||
bm_context_t *bc,
|
||||
int candidate);
|
||||
SlapReply *rs,
|
||||
a_metaconn_t *mc,
|
||||
bm_context_t *bc,
|
||||
int candidate,
|
||||
int do_lock);
|
||||
|
||||
bm_context_t *
|
||||
asyncmeta_bc_in_queue(a_metaconn_t *mc,
|
||||
bm_context_t *bc);
|
||||
|
||||
int
|
||||
asyncmeta_error_cleanup(Operation *op,
|
||||
SlapReply *rs,
|
||||
bm_context_t *bc,
|
||||
a_metaconn_t *mc,
|
||||
int candidate);
|
||||
|
||||
int
|
||||
asyncmeta_reset_msc(Operation *op,
|
||||
a_metaconn_t *mc,
|
||||
int candidate,
|
||||
int unbind,
|
||||
const char *caller);
|
||||
|
||||
|
||||
void
|
||||
asyncmeta_sender_error(Operation *op,
|
||||
SlapReply *rs,
|
||||
slap_callback *cb);
|
||||
asyncmeta_back_conn_free(
|
||||
void *v_mc );
|
||||
|
||||
void asyncmeta_log_msc(a_metasingleconn_t *msc);
|
||||
void asyncmeta_log_conns(a_metainfo_t *mi);
|
||||
|
||||
void asyncmeta_get_timestamp(char *buf);
|
||||
|
||||
int
|
||||
asyncmeta_dncache_update_entry(a_metadncache_t *cache,
|
||||
struct berval *ndn,
|
||||
int target );
|
||||
|
||||
void
|
||||
asyncmeta_dnattr_result_rewrite(a_dncookie *dc,
|
||||
BerVarray a_vals);
|
||||
|
||||
void
|
||||
asyncmeta_referral_result_rewrite(a_dncookie *dc,
|
||||
BerVarray a_vals);
|
||||
|
||||
meta_search_candidate_t
|
||||
asyncmeta_send_all_pending_ops(a_metaconn_t *mc,
|
||||
int candidate,
|
||||
void *ctx,
|
||||
int dolock);
|
||||
meta_search_candidate_t
|
||||
asyncmeta_return_bind_errors(a_metaconn_t *mc,
|
||||
int candidate,
|
||||
SlapReply *bind_result,
|
||||
void *ctx,
|
||||
int dolock);
|
||||
|
||||
/* The the maximum time in seconds after a result has been received on a connection,
|
||||
* after which it can be reset if a sender error occurs. Should this be configurable? */
|
||||
#define META_BACK_RESULT_INTERVAL (2)
|
||||
|
||||
extern int asyncmeta_debug;
|
||||
|
||||
LDAP_END_DECL
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -206,8 +206,6 @@ asyncmeta_select_unique_candidate(
|
|||
if ( candidate == META_TARGET_NONE ) {
|
||||
candidate = i;
|
||||
|
||||
} else {
|
||||
return META_TARGET_MULTIPLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -239,50 +237,3 @@ asyncmeta_clear_unused_candidates(
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
asyncmeta_clear_one_msc(
|
||||
Operation *op,
|
||||
a_metaconn_t *mc,
|
||||
int candidate )
|
||||
{
|
||||
a_metasingleconn_t *msc;
|
||||
if (mc == NULL) {
|
||||
return 0;
|
||||
}
|
||||
msc = &mc->mc_conns[candidate];
|
||||
if (msc->conn) {
|
||||
connection_client_stop( msc->conn );
|
||||
msc->conn = NULL;
|
||||
}
|
||||
if ( msc->msc_ld != NULL ) {
|
||||
|
||||
#ifdef DEBUG_205
|
||||
Debug(LDAP_DEBUG_ANY,
|
||||
"### %s asyncmeta_clear_one_msc ldap_unbind_ext[%d] ld=%p\n",
|
||||
op ? op->o_log_prefix : "", candidate,
|
||||
(void *)msc->msc_ld );
|
||||
#endif /* DEBUG_205 */
|
||||
|
||||
ldap_unbind_ext( msc->msc_ld, NULL, NULL );
|
||||
msc->msc_ld = NULL;
|
||||
ldap_ld_free( msc->msc_ldr, 0, NULL, NULL );
|
||||
msc->msc_ldr = NULL;
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &msc->msc_bound_ndn ) ) {
|
||||
ber_memfree_x( msc->msc_bound_ndn.bv_val, NULL );
|
||||
BER_BVZERO( &msc->msc_bound_ndn );
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &msc->msc_cred ) ) {
|
||||
memset( msc->msc_cred.bv_val, 0, msc->msc_cred.bv_len );
|
||||
ber_memfree_x( msc->msc_cred.bv_val, NULL );
|
||||
BER_BVZERO( &msc->msc_cred );
|
||||
}
|
||||
msc->msc_time = 0;
|
||||
msc->msc_mscflags = 0;
|
||||
msc->msc_timeout_ops = 0;
|
||||
msc->msc_pending_ops = 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,27 +26,27 @@
|
|||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "../back-ldap/back-ldap.h"
|
||||
#include "back-asyncmeta.h"
|
||||
#include "../../../libraries/liblber/lber-int.h"
|
||||
#include "../../../libraries/libldap/ldap-int.h"
|
||||
#include "../back-ldap/back-ldap.h"
|
||||
#include "back-asyncmeta.h"
|
||||
|
||||
meta_search_candidate_t
|
||||
asyncmeta_back_compare_start(Operation *op,
|
||||
SlapReply *rs,
|
||||
a_metaconn_t *mc,
|
||||
bm_context_t *bc,
|
||||
int candidate)
|
||||
SlapReply *rs,
|
||||
a_metaconn_t *mc,
|
||||
bm_context_t *bc,
|
||||
int candidate,
|
||||
int do_lock)
|
||||
{
|
||||
a_dncookie dc;
|
||||
a_metainfo_t *mi = mc->mc_info;
|
||||
a_metatarget_t *mt = mi->mi_targets[ candidate ];
|
||||
struct berval c_attr = op->orc_ava->aa_desc->ad_cname;
|
||||
struct berval mdn = BER_BVNULL;
|
||||
struct berval mapped_attr = op->orc_ava->aa_desc->ad_cname;
|
||||
struct berval mapped_value = op->orc_ava->aa_value;
|
||||
int rc = 0, nretries = 1;
|
||||
int rc = 0;
|
||||
LDAPControl **ctrls = NULL;
|
||||
meta_search_candidate_t retcode = META_SEARCH_CANDIDATE;
|
||||
BerElement *ber = NULL;
|
||||
|
|
@ -54,117 +54,125 @@ asyncmeta_back_compare_start(Operation *op,
|
|||
SlapReply *candidates = bc->candidates;
|
||||
ber_int_t msgid;
|
||||
|
||||
dc.op = op;
|
||||
dc.target = mt;
|
||||
dc.conn = op->o_conn;
|
||||
dc.rs = rs;
|
||||
dc.ctx = "compareDN";
|
||||
dc.memctx = op->o_tmpmemctx;
|
||||
dc.to_from = MASSAGE_REQ;
|
||||
|
||||
switch ( asyncmeta_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
|
||||
case LDAP_UNWILLING_TO_PERFORM:
|
||||
rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
|
||||
retcode = META_SEARCH_ERR;
|
||||
goto doreturn;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
asyncmeta_dn_massage( &dc, &op->o_req_dn, &mdn );
|
||||
|
||||
/*
|
||||
* if attr is objectClass, try to remap the value
|
||||
*/
|
||||
if ( op->orc_ava->aa_desc == slap_schema.si_ad_objectClass ) {
|
||||
asyncmeta_map( &mt->mt_rwmap.rwm_oc,
|
||||
&op->orc_ava->aa_value,
|
||||
&mapped_value, BACKLDAP_MAP );
|
||||
if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
|
||||
asyncmeta_dn_massage( &dc, &op->orc_ava->aa_value, &mapped_value );
|
||||
|
||||
if ( BER_BVISNULL( &mapped_value ) || BER_BVISEMPTY( &mapped_value ) ) {
|
||||
rs->sr_err = LDAP_OTHER;
|
||||
retcode = META_SEARCH_ERR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* else try to remap the attribute
|
||||
*/
|
||||
} else {
|
||||
asyncmeta_map( &mt->mt_rwmap.rwm_at,
|
||||
&op->orc_ava->aa_desc->ad_cname,
|
||||
&mapped_attr, BACKLDAP_MAP );
|
||||
if ( BER_BVISNULL( &mapped_attr ) || BER_BVISEMPTY( &mapped_attr ) ) {
|
||||
rs->sr_err = LDAP_OTHER;
|
||||
retcode = META_SEARCH_ERR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
|
||||
{
|
||||
dc.ctx = "compareAttrDN";
|
||||
|
||||
switch ( asyncmeta_dn_massage( &dc, &op->orc_ava->aa_value, &mapped_value ) )
|
||||
{
|
||||
case LDAP_UNWILLING_TO_PERFORM:
|
||||
rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
|
||||
retcode = META_SEARCH_ERR;
|
||||
goto done;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
retry:;
|
||||
asyncmeta_set_msc_time(msc);
|
||||
ctrls = op->o_ctrls;
|
||||
if ( asyncmeta_controls_add( op, rs, mc, candidate, &ctrls ) != LDAP_SUCCESS )
|
||||
if ( asyncmeta_controls_add( op, rs, mc, candidate, bc->is_root,&ctrls ) != LDAP_SUCCESS )
|
||||
{
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
retcode = META_SEARCH_ERR;
|
||||
goto done;
|
||||
}
|
||||
/* someone might have reset the connection */
|
||||
if (!( LDAP_BACK_CONN_ISBOUND( msc )
|
||||
|| LDAP_BACK_CONN_ISANON( msc )) || msc->msc_ld == NULL ) {
|
||||
Debug( asyncmeta_debug, "msc %p not initialized at %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
goto error_unavailable;
|
||||
}
|
||||
|
||||
ber = ldap_build_compare_req( msc->msc_ld, mdn.bv_val, mapped_attr.bv_val, &mapped_value,
|
||||
ber = ldap_build_compare_req( msc->msc_ld, mdn.bv_val, c_attr.bv_val, &mapped_value,
|
||||
ctrls, NULL, &msgid);
|
||||
|
||||
if (!ber) {
|
||||
Debug( asyncmeta_debug, "%s asyncmeta_back_compare_start: Operation encoding failed with errno %d\n",
|
||||
op->o_log_prefix, msc->msc_ld->ld_errno );
|
||||
rs->sr_err = LDAP_OPERATIONS_ERROR;
|
||||
rs->sr_text = "Failed to encode proxied request";
|
||||
retcode = META_SEARCH_ERR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (ber) {
|
||||
candidates[ candidate ].sr_msgid = msgid;
|
||||
rc = ldap_send_initial_request( msc->msc_ld, LDAP_REQ_COMPARE,
|
||||
mdn.bv_val, ber, msgid );
|
||||
if (rc == msgid)
|
||||
rc = LDAP_SUCCESS;
|
||||
else
|
||||
rc = LDAP_SERVER_DOWN;
|
||||
struct timeval tv = {0, mt->mt_network_timeout*1000};
|
||||
ber_socket_t s;
|
||||
if (!( LDAP_BACK_CONN_ISBOUND( msc )
|
||||
|| LDAP_BACK_CONN_ISANON( msc )) || msc->msc_ld == NULL ) {
|
||||
Debug( asyncmeta_debug, "msc %p not initialized at %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
goto error_unavailable;
|
||||
}
|
||||
|
||||
ldap_get_option( msc->msc_ld, LDAP_OPT_DESC, &s );
|
||||
if (s < 0) {
|
||||
Debug( asyncmeta_debug, "msc %p not initialized at %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
goto error_unavailable;
|
||||
}
|
||||
rc = ldap_int_poll( msc->msc_ld, s, &tv, 1);
|
||||
if (rc < 0) {
|
||||
Debug( asyncmeta_debug, "msc %p not writable within network timeout %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
if ((msc->msc_result_time + META_BACK_RESULT_INTERVAL) < slap_get_time()) {
|
||||
rc = LDAP_SERVER_DOWN;
|
||||
} else {
|
||||
goto error_unavailable;
|
||||
}
|
||||
} else {
|
||||
candidates[ candidate ].sr_msgid = msgid;
|
||||
rc = ldap_send_initial_request( msc->msc_ld, LDAP_REQ_COMPARE,
|
||||
mdn.bv_val, ber, msgid );
|
||||
if (rc == msgid)
|
||||
rc = LDAP_SUCCESS;
|
||||
else
|
||||
rc = LDAP_SERVER_DOWN;
|
||||
ber = NULL;
|
||||
}
|
||||
|
||||
switch ( rc ) {
|
||||
case LDAP_SUCCESS:
|
||||
retcode = META_SEARCH_CANDIDATE;
|
||||
asyncmeta_set_msc_time(msc);
|
||||
break;
|
||||
goto done;
|
||||
|
||||
case LDAP_SERVER_DOWN:
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_clear_one_msc(NULL, mc, candidate);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
if ( nretries && asyncmeta_retry( op, rs, &mc, candidate, LDAP_BACK_DONTSEND ) ) {
|
||||
nretries = 0;
|
||||
/* if the identity changed, there might be need to re-authz */
|
||||
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
||||
goto retry;
|
||||
/* do not lock if called from asyncmeta_handle_bind_result. Also do not reset the connection */
|
||||
if (do_lock > 0) {
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_reset_msc(NULL, mc, candidate, 0, __FUNCTION__);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
}
|
||||
|
||||
/* fall though*/
|
||||
default:
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
retcode = META_SEARCH_ERR;
|
||||
Debug( asyncmeta_debug, "msc %p ldap_send_initial_request failed. %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
goto error_unavailable;
|
||||
}
|
||||
}
|
||||
|
||||
error_unavailable:
|
||||
if (ber)
|
||||
ber_free(ber, 1);
|
||||
switch (bc->nretries[candidate]) {
|
||||
case -1: /* nretries = forever */
|
||||
retcode = META_SEARCH_NEED_BIND;
|
||||
break;
|
||||
case 0: /* no retries left */
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
rs->sr_err = LDAP_UNAVAILABLE;
|
||||
rs->sr_text = "Unable to send compare request to target";
|
||||
retcode = META_SEARCH_ERR;
|
||||
break;
|
||||
default: /* more retries left - try to rebind and go again */
|
||||
retcode = META_SEARCH_NEED_BIND;
|
||||
bc->nretries[candidate]--;
|
||||
break;
|
||||
}
|
||||
done:
|
||||
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
||||
|
||||
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
|
||||
free( mdn.bv_val );
|
||||
}
|
||||
|
||||
if ( op->orc_ava->aa_value.bv_val != mapped_value.bv_val ) {
|
||||
free( mapped_value.bv_val );
|
||||
op->o_tmpfree( mapped_value.bv_val, op->o_tmpmemctx );
|
||||
}
|
||||
|
||||
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
|
||||
op->o_tmpfree( mdn.bv_val, op->o_tmpmemctx );
|
||||
}
|
||||
|
||||
doreturn:;
|
||||
Debug( LDAP_DEBUG_TRACE, "%s <<< asyncmeta_back_compare_start[%p]=%d\n", op->o_log_prefix, msc, candidates[candidate].sr_msgid );
|
||||
return retcode;
|
||||
}
|
||||
|
|
@ -176,26 +184,30 @@ asyncmeta_back_compare( Operation *op, SlapReply *rs )
|
|||
a_metatarget_t *mt;
|
||||
a_metaconn_t *mc;
|
||||
int rc, candidate = -1;
|
||||
OperationBuffer opbuf;
|
||||
void *thrctx = op->o_threadctx;
|
||||
bm_context_t *bc;
|
||||
SlapReply *candidates;
|
||||
slap_callback *cb = op->o_callback;
|
||||
time_t current_time = slap_get_time();
|
||||
int max_pending_ops = (mi->mi_max_pending_ops == 0) ? META_BACK_CFG_MAX_PENDING_OPS : mi->mi_max_pending_ops;
|
||||
|
||||
Debug(LDAP_DEBUG_ARGS, "==> asyncmeta_back_compare: %s\n",
|
||||
op->o_req_dn.bv_val );
|
||||
|
||||
asyncmeta_new_bm_context(op, rs, &bc, mi->mi_ntargets );
|
||||
if (current_time > op->o_time) {
|
||||
Debug( asyncmeta_debug, "==> asyncmeta_back_compare[%s]: o_time:[%ld], current time: [%ld]\n",
|
||||
op->o_log_prefix, op->o_time, current_time );
|
||||
}
|
||||
asyncmeta_new_bm_context(op, rs, &bc, mi->mi_ntargets, mi );
|
||||
if (bc == NULL) {
|
||||
rs->sr_err = LDAP_OTHER;
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
send_ldap_result(op, rs);
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
candidates = bc->candidates;
|
||||
mc = asyncmeta_getconn( op, rs, candidates, &candidate, LDAP_BACK_DONTSEND, 0);
|
||||
if ( !mc || rs->sr_err != LDAP_SUCCESS) {
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
send_ldap_result(op, rs);
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
|
|
@ -204,16 +216,38 @@ asyncmeta_back_compare( Operation *op, SlapReply *rs )
|
|||
bc->retrying = LDAP_BACK_RETRYING;
|
||||
bc->sendok = ( LDAP_BACK_SENDRESULT | bc->retrying );
|
||||
bc->stoptime = op->o_time + bc->timeout;
|
||||
bc->bc_active = 1;
|
||||
|
||||
if (mc->pending_ops >= max_pending_ops) {
|
||||
rs->sr_err = LDAP_BUSY;
|
||||
rs->sr_text = "Maximum pending ops limit exceeded";
|
||||
send_ldap_result(op, rs);
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
rc = asyncmeta_add_message_queue(mc, bc);
|
||||
mc->mc_conns[candidate].msc_active++;
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
|
||||
if (rc != LDAP_SUCCESS) {
|
||||
rs->sr_err = LDAP_BUSY;
|
||||
rs->sr_text = "Maximum pending ops limit exceeded";
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
send_ldap_result(op, rs);
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
mc->mc_conns[candidate].msc_active--;
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
retry:
|
||||
if (bc->timeout && bc->stoptime < slap_get_time()) {
|
||||
int timeout_err;
|
||||
timeout_err = op->o_protocol >= LDAP_VERSION3 ?
|
||||
LDAP_ADMINLIMIT_EXCEEDED : LDAP_OTHER;
|
||||
rs->sr_err = timeout_err;
|
||||
rs->sr_text = "Operation timed out before it was sent to target";
|
||||
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
|
@ -223,47 +257,27 @@ asyncmeta_back_compare( Operation *op, SlapReply *rs )
|
|||
case META_SEARCH_CANDIDATE:
|
||||
/* target is already bound, just send the request */
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_compare: "
|
||||
"cnd=\"%ld\"\n", op->o_log_prefix, candidate );
|
||||
"cnd=\"%d\"\n", op->o_log_prefix, candidate );
|
||||
|
||||
rc = asyncmeta_back_compare_start( op, rs, mc, bc, candidate);
|
||||
rc = asyncmeta_back_compare_start( op, rs, mc, bc, candidate, 1);
|
||||
if (rc == META_SEARCH_ERR) {
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_drop_bc(mc, bc);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||
goto finish;
|
||||
|
||||
} else if (rc == META_SEARCH_NEED_BIND) {
|
||||
goto retry;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case META_SEARCH_NOT_CANDIDATE:
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_compare: NOT_CANDIDATE "
|
||||
"cnd=\"%ld\"\n", op->o_log_prefix, candidate );
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_drop_bc(mc, bc);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
"cnd=\"%d\"\n", op->o_log_prefix, candidate );
|
||||
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||
goto finish;
|
||||
|
||||
case META_SEARCH_NEED_BIND:
|
||||
case META_SEARCH_CONNECTING:
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_compare: NEED_BIND "
|
||||
"cnd=\"%ld\" %p\n", op->o_log_prefix, candidate , &mc->mc_conns[candidate]);
|
||||
rc = asyncmeta_dobind_init(op, rs, bc, mc, candidate);
|
||||
if (rc == META_SEARCH_ERR) {
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_drop_bc(mc, bc);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
goto finish;
|
||||
}
|
||||
break;
|
||||
case META_SEARCH_BINDING:
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_compare: BINDING "
|
||||
"cnd=\"%ld\" %p\n", op->o_log_prefix, candidate , &mc->mc_conns[candidate]);
|
||||
"cnd=\"%d\" %p\n", op->o_log_prefix, candidate , &mc->mc_conns[candidate]);
|
||||
/* Todo add the context to the message queue but do not send the request
|
||||
the receiver must send this when we are done binding */
|
||||
/* question - how would do receiver know to which targets??? */
|
||||
|
|
@ -271,23 +285,21 @@ asyncmeta_back_compare( Operation *op, SlapReply *rs )
|
|||
|
||||
case META_SEARCH_ERR:
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_compare: ERR "
|
||||
"cnd=\"%ldd\"\n", op->o_log_prefix, candidate );
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
candidates[ candidate ].sr_type = REP_RESULT;
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_drop_bc(mc, bc);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
"cnd=\"%d\"\n", op->o_log_prefix, candidate );
|
||||
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||
goto finish;
|
||||
default:
|
||||
assert( 0 );
|
||||
break;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
mc->mc_conns[candidate].msc_active--;
|
||||
asyncmeta_start_one_listener(mc, candidates, bc, candidate);
|
||||
bc->bc_active--;
|
||||
asyncmeta_memctx_toggle(thrctx);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
rs->sr_err = SLAPD_ASYNCOP;
|
||||
finish:
|
||||
return rs->sr_err;
|
||||
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -27,57 +27,11 @@
|
|||
#include <ac/errno.h>
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
|
||||
|
||||
#define AVL_INTERNAL
|
||||
#include "slap.h"
|
||||
#include "../../../libraries/libldap/ldap-int.h"
|
||||
#include "../back-ldap/back-ldap.h"
|
||||
#include "back-asyncmeta.h"
|
||||
|
||||
|
||||
/*
|
||||
* Debug stuff (got it from libavl)
|
||||
*/
|
||||
#if META_BACK_PRINT_CONNTREE > 0
|
||||
|
||||
static void
|
||||
asyncmeta_back_ravl_print( Avlnode *root, int depth )
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( root == 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
asyncmeta_back_ravl_print( root->avl_right, depth + 1 );
|
||||
|
||||
for ( i = 0; i < depth; i++ ) {
|
||||
fprintf( stderr, "-" );
|
||||
}
|
||||
fputc( ' ', stderr );
|
||||
|
||||
asyncmeta_back_print( (a_metaconn_t *)root->avl_data,
|
||||
avl_bf2str( root->avl_bf ) );
|
||||
|
||||
asyncmeta_back_ravl_print( root->avl_left, depth + 1 );
|
||||
}
|
||||
|
||||
/* NOTE: duplicate from back-ldap/bind.c */
|
||||
static char* priv2str[] = {
|
||||
"privileged",
|
||||
"privileged/TLS",
|
||||
"anonymous",
|
||||
"anonymous/TLS",
|
||||
"bind",
|
||||
"bind/TLS",
|
||||
NULL
|
||||
};
|
||||
|
||||
#endif /* META_BACK_PRINT_CONNTREE */
|
||||
/*
|
||||
* End of debug stuff
|
||||
*/
|
||||
|
||||
/*
|
||||
* asyncmeta_conn_alloc
|
||||
*
|
||||
|
|
@ -127,8 +81,6 @@ asyncmeta_init_one_conn(
|
|||
a_dncookie dc;
|
||||
int isauthz = ( candidate == mc->mc_authz_target );
|
||||
int do_return = 0;
|
||||
int nretries = 2;
|
||||
|
||||
#ifdef HAVE_TLS
|
||||
int is_ldaps = 0;
|
||||
int do_start_tls = 0;
|
||||
|
|
@ -164,15 +116,16 @@ asyncmeta_init_one_conn(
|
|||
|
||||
if ( dont_retry ) {
|
||||
rs->sr_err = LDAP_UNAVAILABLE;
|
||||
rs->sr_text = "Target is quarantined";
|
||||
Debug( LDAP_DEBUG_ANY, "%s asyncmeta_init_one_conn: Target is quarantined\n",
|
||||
op->o_log_prefix );
|
||||
if ( op->o_conn && ( sendok & LDAP_BACK_SENDERR ) ) {
|
||||
rs->sr_text = "Target is quarantined";
|
||||
send_ldap_result( op, rs );
|
||||
}
|
||||
return rs->sr_err;
|
||||
}
|
||||
}
|
||||
msc = &mc->mc_conns[candidate];
|
||||
retry_lock:;
|
||||
/*
|
||||
* Already init'ed
|
||||
*/
|
||||
|
|
@ -186,13 +139,7 @@ retry_lock:;
|
|||
} else if ( META_BACK_CONN_CREATING( msc )
|
||||
|| LDAP_BACK_CONN_BINDING( msc ) )
|
||||
{
|
||||
/* sounds more appropriate */
|
||||
if (nretries >= 0) {
|
||||
nretries--;
|
||||
ldap_pvt_thread_yield();
|
||||
goto retry_lock;
|
||||
}
|
||||
rs->sr_err = LDAP_UNAVAILABLE;
|
||||
rs->sr_err = LDAP_SUCCESS;
|
||||
do_return = 1;
|
||||
|
||||
} else if ( META_BACK_CONN_INITED( msc ) ) {
|
||||
|
|
@ -231,6 +178,8 @@ retry_lock:;
|
|||
#endif /* HAVE_TLS */
|
||||
ldap_pvt_thread_mutex_unlock( &mt->mt_uri_mutex );
|
||||
if ( rs->sr_err != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_ANY, "%s asyncmeta_init_one_conn: ldap_initialize failed err=%d\n",
|
||||
op->o_log_prefix, rs->sr_err );
|
||||
goto error_return;
|
||||
}
|
||||
msc->msc_ldr = ldap_dup(msc->msc_ld);
|
||||
|
|
@ -327,8 +276,8 @@ retry:;
|
|||
|
||||
default:
|
||||
/* only touch when activity actually took place... */
|
||||
if ( mi->mi_idle_timeout != 0 && msc->msc_time < op->o_time ) {
|
||||
msc->msc_time = op->o_time;
|
||||
if ( mi->mi_idle_timeout != 0 ) {
|
||||
asyncmeta_set_msc_time(msc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -348,6 +297,7 @@ retry:;
|
|||
res = NULL;
|
||||
|
||||
if ( rs->sr_err == LDAP_SUCCESS ) {
|
||||
|
||||
rs->sr_err = err;
|
||||
}
|
||||
rs->sr_err = slap_map_api2result( rs );
|
||||
|
|
@ -385,7 +335,10 @@ retry:;
|
|||
*/
|
||||
rs->sr_err = ldap_start_tls_s( msc->msc_ld, NULL, NULL );
|
||||
#endif /* ! SLAP_STARTTLS_ASYNCHRONOUS */
|
||||
|
||||
if (rs->sr_err != LDAP_SUCCESS) {
|
||||
Debug( LDAP_DEBUG_ANY, "%s asyncmeta_init_one_conn: ldap_start_tls_s failed err=%d\n",
|
||||
op->o_log_prefix, rs->sr_err );
|
||||
}
|
||||
/* if StartTLS is requested, only attempt it if the URL
|
||||
* is not "ldaps://"; this may occur not only in case
|
||||
* of misconfiguration, but also when used in the chain
|
||||
|
|
@ -407,18 +360,16 @@ retry:;
|
|||
}
|
||||
}
|
||||
#endif /* HAVE_TLS */
|
||||
|
||||
/*
|
||||
* Set the network timeout if set
|
||||
*/
|
||||
if ( mt->mt_network_timeout != 0 ) {
|
||||
struct timeval network_timeout;
|
||||
|
||||
network_timeout.tv_usec = 0;
|
||||
network_timeout.tv_sec = mt->mt_network_timeout;
|
||||
struct timeval network_timeout;
|
||||
network_timeout.tv_sec = 0;
|
||||
network_timeout.tv_usec = mt->mt_network_timeout*1000;
|
||||
|
||||
ldap_set_option( msc->msc_ld, LDAP_OPT_NETWORK_TIMEOUT,
|
||||
(void *)&network_timeout );
|
||||
(void *)&network_timeout );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -452,38 +403,22 @@ retry:;
|
|||
BER_BVZERO( &msc->msc_bound_ndn );
|
||||
}
|
||||
if ( !BER_BVISEMPTY( &op->o_ndn )
|
||||
&& SLAP_IS_AUTHZ_BACKEND( op )
|
||||
&& isauthz )
|
||||
{
|
||||
dc.op = op;
|
||||
dc.target = mt;
|
||||
dc.conn = op->o_conn;
|
||||
dc.rs = rs;
|
||||
dc.ctx = "bindDN";
|
||||
dc.memctx = NULL;
|
||||
dc.to_from = MASSAGE_REQ;
|
||||
|
||||
/*
|
||||
* Rewrite the bind dn if needed
|
||||
*/
|
||||
if ( asyncmeta_dn_massage( &dc, &op->o_conn->c_dn,
|
||||
&msc->msc_bound_ndn ) )
|
||||
{
|
||||
|
||||
#ifdef DEBUG_205
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"### %s asyncmeta_init_one_conn(rewrite) "
|
||||
"ldap_unbind_ext[%d] ld=%p\n",
|
||||
op->o_log_prefix, candidate,
|
||||
(void *)msc->msc_ld );
|
||||
#endif /* DEBUG_205 */
|
||||
goto error_return;
|
||||
}
|
||||
asyncmeta_dn_massage( &dc, &op->o_conn->c_dn, &msc->msc_bound_ndn );
|
||||
|
||||
/* copy the DN if needed */
|
||||
if ( msc->msc_bound_ndn.bv_val == op->o_conn->c_dn.bv_val ) {
|
||||
ber_dupbv( &msc->msc_bound_ndn, &op->o_conn->c_dn );
|
||||
}
|
||||
|
||||
assert( !BER_BVISNULL( &msc->msc_bound_ndn ) );
|
||||
|
||||
} else {
|
||||
ber_dupbv( &msc->msc_bound_ndn, (struct berval *)&slap_empty_bv );
|
||||
}
|
||||
|
|
@ -496,10 +431,6 @@ error_return:;
|
|||
META_BACK_CONN_CREATING_CLEAR( msc );
|
||||
}
|
||||
if ( rs->sr_err == LDAP_SUCCESS && msc != NULL) {
|
||||
/*
|
||||
* Sets a cookie for the rewrite session
|
||||
*/
|
||||
( void )rewrite_session_init( mt->mt_rwmap.rwm_rw, op->o_conn );
|
||||
META_BACK_CONN_INITED_SET( msc );
|
||||
}
|
||||
|
||||
|
|
@ -512,125 +443,6 @@ error_return:;
|
|||
return rs->sr_err;
|
||||
}
|
||||
|
||||
/*
|
||||
* asyncmeta_retry
|
||||
*
|
||||
* Retries one connection
|
||||
*/
|
||||
int
|
||||
asyncmeta_retry(
|
||||
Operation *op,
|
||||
SlapReply *rs,
|
||||
a_metaconn_t **mcp,
|
||||
int candidate,
|
||||
ldap_back_send_t sendok )
|
||||
{
|
||||
a_metaconn_t *mc = *mcp;
|
||||
a_metainfo_t *mi = mc->mc_info;
|
||||
a_metatarget_t *mt = mi->mi_targets[ candidate ];
|
||||
a_metasingleconn_t *msc = &mc->mc_conns[ candidate ];
|
||||
int rc = LDAP_UNAVAILABLE,
|
||||
binding,
|
||||
quarantine = 1;
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex );
|
||||
struct berval save_cred;
|
||||
|
||||
if ( LogTest( LDAP_DEBUG_ANY ) ) {
|
||||
/* this lock is required; however,
|
||||
* it's invoked only when logging is on */
|
||||
ldap_pvt_thread_mutex_lock( &mt->mt_uri_mutex );
|
||||
Debug(LDAP_DEBUG_ANY,
|
||||
"%s asyncmeta_retry[%d]: retrying URI=\"%s\" DN=\"%s\".\n",
|
||||
op->o_log_prefix, candidate, mt->mt_uri,
|
||||
BER_BVISNULL(&msc->msc_bound_ndn) ? "" : msc->msc_bound_ndn.bv_val );
|
||||
ldap_pvt_thread_mutex_unlock( &mt->mt_uri_mutex );
|
||||
}
|
||||
|
||||
( void )rewrite_session_delete( mt->mt_rwmap.rwm_rw, op->o_conn );
|
||||
/* mc here must be the regular mc, reset and ready for init */
|
||||
rc = asyncmeta_init_one_conn( op, rs, mc, candidate,
|
||||
LDAP_BACK_CONN_ISPRIV( mc ), sendok, 0 );
|
||||
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
if ( sendok & LDAP_BACK_SENDERR ) {
|
||||
/* init_one_conn has set the result */
|
||||
send_ldap_result( op, rs );
|
||||
}
|
||||
}
|
||||
|
||||
if ( rc == LDAP_SUCCESS ) {
|
||||
quarantine = 0;
|
||||
LDAP_BACK_CONN_BINDING_SET( msc ); binding = 1;
|
||||
/* todo this must be dobind_init */
|
||||
rc = asyncmeta_back_single_dobind( op, rs, mcp, candidate,
|
||||
sendok, mt->mt_nretries, 0 );
|
||||
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s asyncmeta_retry[%d]: "
|
||||
"asyncmeta_single_dobind=%d\n",
|
||||
op->o_log_prefix, candidate, rc );
|
||||
if ( rc == LDAP_SUCCESS ) {
|
||||
if ( !BER_BVISNULL( &msc->msc_bound_ndn ) &&
|
||||
!BER_BVISEMPTY( &msc->msc_bound_ndn ) )
|
||||
{
|
||||
LDAP_BACK_CONN_ISBOUND_SET( msc );
|
||||
|
||||
} else {
|
||||
LDAP_BACK_CONN_ISANON_SET( msc );
|
||||
}
|
||||
|
||||
/* when bound, dispose of the "binding" flag */
|
||||
if ( binding ) {
|
||||
LDAP_BACK_CONN_BINDING_CLEAR( msc );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
if (mc->mc_active < 1) {
|
||||
asyncmeta_clear_one_msc(NULL, mc, candidate);
|
||||
}
|
||||
if ( sendok & LDAP_BACK_SENDERR ) {
|
||||
rs->sr_err = rc;
|
||||
rs->sr_text = "Unable to retry";
|
||||
send_ldap_result( op, rs );
|
||||
}
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex );
|
||||
if ( quarantine && META_BACK_TGT_QUARANTINE( mt ) ) {
|
||||
asyncmeta_quarantine( op, mi, rs, candidate );
|
||||
}
|
||||
|
||||
return rc == LDAP_SUCCESS ? 1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* callback for unique candidate selection
|
||||
*/
|
||||
static int
|
||||
asyncmeta_conn_cb( Operation *op, SlapReply *rs )
|
||||
{
|
||||
assert( op->o_tag == LDAP_REQ_SEARCH );
|
||||
|
||||
switch ( rs->sr_type ) {
|
||||
case REP_SEARCH:
|
||||
((long *)op->o_callback->sc_private)[0] = (long)op->o_private;
|
||||
break;
|
||||
|
||||
case REP_SEARCHREF:
|
||||
case REP_RESULT:
|
||||
break;
|
||||
|
||||
default:
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
asyncmeta_get_candidate(
|
||||
|
|
@ -654,59 +466,6 @@ asyncmeta_get_candidate(
|
|||
rs->sr_err = LDAP_NO_SUCH_OBJECT;
|
||||
rs->sr_text = "No suitable candidate target found";
|
||||
|
||||
} else if ( candidate == META_TARGET_MULTIPLE ) {
|
||||
Operation op2 = *op;
|
||||
SlapReply rs2 = { REP_RESULT };
|
||||
slap_callback cb2 = { 0 };
|
||||
int rc;
|
||||
|
||||
/* try to get a unique match for the request ndn
|
||||
* among the multiple candidates available */
|
||||
op2.o_tag = LDAP_REQ_SEARCH;
|
||||
op2.o_req_dn = *ndn;
|
||||
op2.o_req_ndn = *ndn;
|
||||
op2.ors_scope = LDAP_SCOPE_BASE;
|
||||
op2.ors_deref = LDAP_DEREF_NEVER;
|
||||
op2.ors_attrs = slap_anlist_no_attrs;
|
||||
op2.ors_attrsonly = 0;
|
||||
op2.ors_limit = NULL;
|
||||
op2.ors_slimit = 1;
|
||||
op2.ors_tlimit = SLAP_NO_LIMIT;
|
||||
|
||||
op2.ors_filter = (Filter *)slap_filter_objectClass_pres;
|
||||
op2.ors_filterstr = *slap_filterstr_objectClass_pres;
|
||||
|
||||
op2.o_callback = &cb2;
|
||||
cb2.sc_response = asyncmeta_conn_cb;
|
||||
cb2.sc_private = (void *)&candidate;
|
||||
|
||||
rc = op->o_bd->be_search( &op2, &rs2 );
|
||||
|
||||
switch ( rs2.sr_err ) {
|
||||
case LDAP_SUCCESS:
|
||||
default:
|
||||
rs->sr_err = rs2.sr_err;
|
||||
break;
|
||||
|
||||
case LDAP_SIZELIMIT_EXCEEDED:
|
||||
/* if multiple candidates can serve the operation,
|
||||
* and a default target is defined, and it is
|
||||
* a candidate, try using it (FIXME: YMMV) */
|
||||
if ( mi->mi_defaulttarget != META_DEFAULT_TARGET_NONE
|
||||
&& asyncmeta_is_candidate( mi->mi_targets[ mi->mi_defaulttarget ],
|
||||
ndn, op->o_tag == LDAP_REQ_SEARCH ? op->ors_scope : LDAP_SCOPE_BASE ) )
|
||||
{
|
||||
candidate = mi->mi_defaulttarget;
|
||||
rs->sr_err = LDAP_SUCCESS;
|
||||
rs->sr_text = NULL;
|
||||
|
||||
} else {
|
||||
rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
|
||||
rs->sr_text = "Unable to select unique candidate target";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
rs->sr_err = LDAP_SUCCESS;
|
||||
}
|
||||
|
|
@ -714,19 +473,6 @@ asyncmeta_get_candidate(
|
|||
return candidate;
|
||||
}
|
||||
|
||||
static void *asyncmeta_candidates_dummy;
|
||||
|
||||
static void
|
||||
asyncmeta_candidates_keyfree(
|
||||
void *key,
|
||||
void *data )
|
||||
{
|
||||
a_metacandidates_t *mc = (a_metacandidates_t *)data;
|
||||
|
||||
ber_memfree_x( mc->mc_candidates, NULL );
|
||||
ber_memfree_x( data, NULL );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* asyncmeta_getconn
|
||||
|
|
@ -910,7 +656,7 @@ asyncmeta_getconn(
|
|||
|
||||
if ( sendok & LDAP_BACK_SENDERR ) {
|
||||
if ( rs->sr_err == LDAP_NO_SUCH_OBJECT ) {
|
||||
rs->sr_matched = op->o_bd->be_suffix[ 0 ].bv_val;
|
||||
rs->sr_matched = mi->mi_suffix.bv_val;
|
||||
}
|
||||
send_ldap_result( op, rs );
|
||||
rs->sr_matched = NULL;
|
||||
|
|
@ -933,9 +679,6 @@ asyncmeta_getconn(
|
|||
}
|
||||
|
||||
if ( op_type == META_OP_REQUIRE_SINGLE ) {
|
||||
a_metatarget_t *mt = NULL;
|
||||
a_metasingleconn_t *msc = NULL;
|
||||
|
||||
int j;
|
||||
|
||||
for ( j = 0; j < mi->mi_ntargets; j++ ) {
|
||||
|
|
@ -956,7 +699,7 @@ asyncmeta_getconn(
|
|||
if ( i < 0 || rs->sr_err != LDAP_SUCCESS ) {
|
||||
if ( sendok & LDAP_BACK_SENDERR ) {
|
||||
if ( rs->sr_err == LDAP_NO_SUCH_OBJECT ) {
|
||||
rs->sr_matched = op->o_bd->be_suffix[ 0 ].bv_val;
|
||||
rs->sr_matched = mi->mi_suffix.bv_val;
|
||||
}
|
||||
send_ldap_result( op, rs );
|
||||
rs->sr_matched = NULL;
|
||||
|
|
@ -998,9 +741,6 @@ asyncmeta_getconn(
|
|||
*/
|
||||
( void )asyncmeta_clear_unused_candidates( op, i , mc, candidates);
|
||||
|
||||
mt = mi->mi_targets[ i ];
|
||||
msc = &mc->mc_conns[ i ];
|
||||
|
||||
/*
|
||||
* The target is activated; if needed, it is
|
||||
* also init'd. In case of error, asyncmeta_init_one_conn
|
||||
|
|
@ -1118,7 +858,7 @@ asyncmeta_getconn(
|
|||
|
||||
if ( sendok & LDAP_BACK_SENDERR ) {
|
||||
if ( rs->sr_err == LDAP_NO_SUCH_OBJECT ) {
|
||||
rs->sr_matched = op->o_bd->be_suffix[ 0 ].bv_val;
|
||||
rs->sr_matched = mi->mi_suffix.bv_val;
|
||||
}
|
||||
send_ldap_result( op, rs );
|
||||
rs->sr_matched = NULL;
|
||||
|
|
@ -1133,7 +873,6 @@ asyncmeta_getconn(
|
|||
}
|
||||
|
||||
done:;
|
||||
/* clear out meta_back_init_one_conn non-fatal errors */
|
||||
rs->sr_err = LDAP_SUCCESS;
|
||||
rs->sr_text = NULL;
|
||||
|
||||
|
|
@ -1266,6 +1005,7 @@ a_metaconn_t *
|
|||
asyncmeta_get_next_mc( a_metainfo_t *mi )
|
||||
{
|
||||
a_metaconn_t *mc = NULL;
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &mi->mi_mc_mutex );
|
||||
if (mi->mi_next_conn >= mi->mi_num_conns-1) {
|
||||
mi->mi_next_conn = 0;
|
||||
|
|
@ -1294,14 +1034,13 @@ int asyncmeta_start_one_listener(a_metaconn_t *mc,
|
|||
{
|
||||
a_metasingleconn_t *msc;
|
||||
ber_socket_t s;
|
||||
int i;
|
||||
|
||||
msc = &mc->mc_conns[candidate];
|
||||
if (msc->msc_ld == NULL || !META_IS_CANDIDATE( &candidates[ candidate ] )) {
|
||||
if ( slapd_shutdown || !META_BACK_CONN_INITED( msc ) || msc->msc_ld == NULL
|
||||
|| !META_IS_CANDIDATE( &candidates[ candidate ] )) {
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
bc->msgids[candidate] = candidates[candidate].sr_msgid;
|
||||
msc->msc_pending_ops++;
|
||||
if ( msc->conn == NULL) {
|
||||
ldap_get_option( msc->msc_ld, LDAP_OPT_DESC, &s );
|
||||
if (s < 0) {
|
||||
|
|
@ -1313,3 +1052,130 @@ int asyncmeta_start_one_listener(a_metaconn_t *mc,
|
|||
connection_client_enable( msc->conn );
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
asyncmeta_clear_one_msc(
|
||||
Operation *op,
|
||||
a_metaconn_t *mc,
|
||||
int candidate,
|
||||
int unbind,
|
||||
const char *caller)
|
||||
{
|
||||
a_metasingleconn_t *msc;
|
||||
if (mc == NULL) {
|
||||
return 0;
|
||||
}
|
||||
msc = &mc->mc_conns[candidate];
|
||||
if ( LogTest( asyncmeta_debug ) ) {
|
||||
char time_buf[ SLAP_TEXT_BUFLEN ];
|
||||
asyncmeta_get_timestamp(time_buf);
|
||||
Debug( asyncmeta_debug, "[%s] Resetting msc: %p, msc_ld: %p, "
|
||||
"msc_bound_ndn: %s, msc->conn: %p, %s \n",
|
||||
time_buf, msc, msc->msc_ld, msc->msc_bound_ndn.bv_val,
|
||||
msc->conn, caller ? caller : "" );
|
||||
}
|
||||
msc->msc_mscflags = 0;
|
||||
if (msc->conn) {
|
||||
connection_client_stop( msc->conn );
|
||||
msc->conn = NULL;
|
||||
}
|
||||
|
||||
if ( msc->msc_ld != NULL ) {
|
||||
|
||||
#ifdef DEBUG_205
|
||||
Debug( LDAP_DEBUG_ANY, "### %s asyncmeta_clear_one_msc ldap_unbind_ext[%d] ld=%p\n",
|
||||
op ? op->o_log_prefix : "", candidate, (void *)msc->msc_ld );
|
||||
#endif /* DEBUG_205 */
|
||||
|
||||
ldap_unbind_ext( msc->msc_ld, NULL, NULL );
|
||||
msc->msc_ld = NULL;
|
||||
ldap_ld_free( msc->msc_ldr, 0, NULL, NULL );
|
||||
msc->msc_ldr = NULL;
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &msc->msc_bound_ndn ) ) {
|
||||
ber_memfree_x( msc->msc_bound_ndn.bv_val, NULL );
|
||||
BER_BVZERO( &msc->msc_bound_ndn );
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &msc->msc_cred ) ) {
|
||||
memset( msc->msc_cred.bv_val, 0, msc->msc_cred.bv_len );
|
||||
ber_memfree_x( msc->msc_cred.bv_val, NULL );
|
||||
BER_BVZERO( &msc->msc_cred );
|
||||
}
|
||||
msc->msc_time = 0;
|
||||
msc->msc_binding_time = 0;
|
||||
msc->msc_result_time = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void asyncmeta_get_timestamp(char *buf)
|
||||
{
|
||||
struct timespec tp;
|
||||
struct tm *ttm;
|
||||
clock_gettime(CLOCK_REALTIME, &tp);
|
||||
ttm = gmtime(&tp.tv_sec);
|
||||
sprintf(buf, "%d:%d:%d.%ld", ttm->tm_hour, ttm->tm_min, ttm->tm_sec, tp.tv_nsec/1000);
|
||||
}
|
||||
|
||||
int
|
||||
asyncmeta_reset_msc(
|
||||
Operation *op,
|
||||
a_metaconn_t *mc,
|
||||
int candidate,
|
||||
int unbind,
|
||||
const char *caller)
|
||||
{
|
||||
a_metasingleconn_t *msc = &mc->mc_conns[candidate];
|
||||
if ( LogTest( asyncmeta_debug ) ) {
|
||||
char time_buf[ SLAP_TEXT_BUFLEN ];
|
||||
asyncmeta_get_timestamp(time_buf);
|
||||
Debug(asyncmeta_debug, "[%x] Will attempt to reset [%s] msc: %p, "
|
||||
"msc->msc_binding_time: %x, msc->msc_flags:%x %s\n",
|
||||
(unsigned int)slap_get_time(), time_buf, msc,
|
||||
(unsigned int)msc->msc_binding_time, msc->msc_mscflags, caller );
|
||||
}
|
||||
if (msc->msc_active <= 1 && mc->mc_active < 1) {
|
||||
bm_context_t *om;
|
||||
asyncmeta_clear_one_msc(NULL, mc, candidate, 0, caller);
|
||||
/* set whatever's in the queue to invalid, so the timeout loop cleans it up,
|
||||
* but do not invalidate the current op*/
|
||||
LDAP_STAILQ_FOREACH( om, &mc->mc_om_list, bc_next ) {
|
||||
if (om->candidates[candidate].sr_msgid >= 0 && (om->op != op)) {
|
||||
om->bc_invalid = 1;
|
||||
}
|
||||
}
|
||||
return LDAP_SUCCESS;
|
||||
} else {
|
||||
META_BACK_CONN_INVALID_SET(msc);
|
||||
Debug( asyncmeta_debug, "[%x] Failed to reset msc %p, msc_active=%d, mc_active=%d, %s\n",
|
||||
(unsigned int)slap_get_time(), msc, msc->msc_active, mc->mc_active, caller );
|
||||
}
|
||||
return LDAP_OTHER;
|
||||
}
|
||||
|
||||
|
||||
void asyncmeta_log_msc(a_metasingleconn_t *msc)
|
||||
{
|
||||
ber_socket_t s = 0;
|
||||
if (msc->msc_ld) {
|
||||
ldap_get_option( msc->msc_ld, LDAP_OPT_DESC, &s );
|
||||
}
|
||||
Debug( asyncmeta_debug, "msc: %p, msc_ld: %p, msc_ld socket: %d, "
|
||||
"msc_bound_ndn: %s, msc->conn: %p\n", msc, msc->msc_ld,
|
||||
(int)s, msc->msc_bound_ndn.bv_val, msc->conn );
|
||||
}
|
||||
|
||||
void asyncmeta_log_conns(a_metainfo_t *mi)
|
||||
{
|
||||
a_metaconn_t *mc;
|
||||
int i, j;
|
||||
for (i = 0; i < mi->mi_num_conns; i++) {
|
||||
mc = &mi->mi_conns[i];
|
||||
Debug(asyncmeta_debug, "mc: %p, mc->pending_ops: %d\n", mc, mc->pending_ops);
|
||||
for (j = 0; j < mi->mi_ntargets; j++ ) {
|
||||
asyncmeta_log_msc(&mc->mc_conns[j]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,28 +23,27 @@
|
|||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "../back-ldap/back-ldap.h"
|
||||
#include "back-asyncmeta.h"
|
||||
#include "../../../libraries/liblber/lber-int.h"
|
||||
#include "../../../libraries/libldap/ldap-int.h"
|
||||
#include "../back-ldap/back-ldap.h"
|
||||
#include "back-asyncmeta.h"
|
||||
|
||||
meta_search_candidate_t
|
||||
asyncmeta_back_delete_start(Operation *op,
|
||||
SlapReply *rs,
|
||||
a_metaconn_t *mc,
|
||||
bm_context_t *bc,
|
||||
int candidate)
|
||||
int candidate,
|
||||
int do_lock)
|
||||
{
|
||||
a_metainfo_t *mi = mc->mc_info;
|
||||
a_metatarget_t *mt = mi->mi_targets[ candidate ];
|
||||
struct berval mdn = BER_BVNULL;
|
||||
a_dncookie dc;
|
||||
int rc = 0, nretries = 1;
|
||||
int rc = 0;
|
||||
LDAPControl **ctrls = NULL;
|
||||
meta_search_candidate_t retcode = META_SEARCH_CANDIDATE;
|
||||
BerElement *ber = NULL;
|
||||
|
|
@ -52,67 +51,119 @@ asyncmeta_back_delete_start(Operation *op,
|
|||
SlapReply *candidates = bc->candidates;
|
||||
ber_int_t msgid;
|
||||
|
||||
dc.op = op;
|
||||
dc.target = mt;
|
||||
dc.conn = op->o_conn;
|
||||
dc.rs = rs;
|
||||
dc.ctx = "deleteDN";
|
||||
dc.memctx = op->o_tmpmemctx;
|
||||
dc.to_from = MASSAGE_REQ;
|
||||
|
||||
if ( asyncmeta_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
|
||||
rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
|
||||
retcode = META_SEARCH_ERR;
|
||||
goto doreturn;
|
||||
}
|
||||
asyncmeta_dn_massage( &dc, &op->o_req_dn, &mdn );
|
||||
|
||||
retry:;
|
||||
asyncmeta_set_msc_time(msc);
|
||||
ctrls = op->o_ctrls;
|
||||
if ( asyncmeta_controls_add( op, rs, mc, candidate, &ctrls ) != LDAP_SUCCESS )
|
||||
if ( asyncmeta_controls_add( op, rs, mc, candidate, bc->is_root, &ctrls ) != LDAP_SUCCESS )
|
||||
{
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
retcode = META_SEARCH_ERR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* someone might have reset the connection */
|
||||
if (!( LDAP_BACK_CONN_ISBOUND( msc )
|
||||
|| LDAP_BACK_CONN_ISANON( msc )) || msc->msc_ld == NULL ) {
|
||||
Debug( asyncmeta_debug, "msc %p not initialized at %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
goto error_unavailable;
|
||||
}
|
||||
ber = ldap_build_delete_req( msc->msc_ld, mdn.bv_val, ctrls, NULL, &msgid);
|
||||
|
||||
if (!ber) {
|
||||
Debug( asyncmeta_debug, "%s asyncmeta_back_delete_start: Operation encoding failed with errno %d\n",
|
||||
op->o_log_prefix, msc->msc_ld->ld_errno );
|
||||
rs->sr_err = LDAP_OPERATIONS_ERROR;
|
||||
rs->sr_text = "Failed to encode proxied request";
|
||||
retcode = META_SEARCH_ERR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (ber) {
|
||||
candidates[ candidate ].sr_msgid = msgid;
|
||||
rc = ldap_send_initial_request( msc->msc_ld, LDAP_REQ_DELETE,
|
||||
mdn.bv_val, ber, msgid );
|
||||
if (rc == msgid)
|
||||
rc = LDAP_SUCCESS;
|
||||
else
|
||||
rc = LDAP_SERVER_DOWN;
|
||||
struct timeval tv = {0, mt->mt_network_timeout*1000};
|
||||
ber_socket_t s;
|
||||
if (!( LDAP_BACK_CONN_ISBOUND( msc )
|
||||
|| LDAP_BACK_CONN_ISANON( msc )) || msc->msc_ld == NULL ) {
|
||||
Debug( asyncmeta_debug, "msc %p not initialized at %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
goto error_unavailable;
|
||||
}
|
||||
|
||||
ldap_get_option( msc->msc_ld, LDAP_OPT_DESC, &s );
|
||||
if (s < 0) {
|
||||
Debug( asyncmeta_debug, "msc %p not initialized at %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
goto error_unavailable;
|
||||
}
|
||||
|
||||
rc = ldap_int_poll( msc->msc_ld, s, &tv, 1);
|
||||
if (rc < 0) {
|
||||
Debug( asyncmeta_debug, "msc %p not writable within network timeout %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
if ((msc->msc_result_time + META_BACK_RESULT_INTERVAL) < slap_get_time()) {
|
||||
rc = LDAP_SERVER_DOWN;
|
||||
} else {
|
||||
goto error_unavailable;
|
||||
}
|
||||
} else {
|
||||
candidates[ candidate ].sr_msgid = msgid;
|
||||
rc = ldap_send_initial_request( msc->msc_ld, LDAP_REQ_DELETE,
|
||||
mdn.bv_val, ber, msgid );
|
||||
if (rc == msgid)
|
||||
rc = LDAP_SUCCESS;
|
||||
else
|
||||
rc = LDAP_SERVER_DOWN;
|
||||
ber = NULL;
|
||||
}
|
||||
|
||||
switch ( rc ) {
|
||||
case LDAP_SUCCESS:
|
||||
retcode = META_SEARCH_CANDIDATE;
|
||||
asyncmeta_set_msc_time(msc);
|
||||
break;
|
||||
goto done;
|
||||
|
||||
case LDAP_SERVER_DOWN:
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_clear_one_msc(NULL, mc, candidate);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
if ( nretries && asyncmeta_retry( op, rs, &mc, candidate, LDAP_BACK_DONTSEND ) ) {
|
||||
nretries = 0;
|
||||
/* if the identity changed, there might be need to re-authz */
|
||||
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
||||
goto retry;
|
||||
/* do not lock if called from asyncmeta_handle_bind_result. Also do not reset the connection */
|
||||
if (do_lock > 0) {
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_reset_msc(NULL, mc, candidate, 0, __FUNCTION__);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
}
|
||||
|
||||
/* fall though*/
|
||||
default:
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
retcode = META_SEARCH_ERR;
|
||||
Debug( asyncmeta_debug, "msc %p ldap_send_initial_request failed. %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
goto error_unavailable;
|
||||
}
|
||||
}
|
||||
|
||||
error_unavailable:
|
||||
if (ber)
|
||||
ber_free(ber, 1);
|
||||
switch (bc->nretries[candidate]) {
|
||||
case -1: /* nretries = forever */
|
||||
retcode = META_SEARCH_NEED_BIND;
|
||||
ldap_pvt_thread_yield();
|
||||
break;
|
||||
case 0: /* no retries left */
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
rs->sr_err = LDAP_UNAVAILABLE;
|
||||
rs->sr_text = "Unable to send delete request to target";
|
||||
retcode = META_SEARCH_ERR;
|
||||
break;
|
||||
default: /* more retries left - try to rebind and go again */
|
||||
retcode = META_SEARCH_NEED_BIND;
|
||||
bc->nretries[candidate]--;
|
||||
ldap_pvt_thread_yield();
|
||||
break;
|
||||
}
|
||||
done:
|
||||
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
||||
|
||||
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
|
||||
free( mdn.bv_val );
|
||||
BER_BVZERO( &mdn );
|
||||
op->o_tmpfree( mdn.bv_val, op->o_tmpmemctx );
|
||||
}
|
||||
|
||||
doreturn:;
|
||||
Debug( LDAP_DEBUG_TRACE, "%s <<< asyncmeta_back_delete_start[%p]=%d\n", op->o_log_prefix, msc, candidates[candidate].sr_msgid );
|
||||
return retcode;
|
||||
}
|
||||
|
|
@ -124,26 +175,32 @@ asyncmeta_back_delete( Operation *op, SlapReply *rs )
|
|||
a_metatarget_t *mt;
|
||||
a_metaconn_t *mc;
|
||||
int rc, candidate = -1;
|
||||
OperationBuffer opbuf;
|
||||
void *thrctx = op->o_threadctx;
|
||||
bm_context_t *bc;
|
||||
SlapReply *candidates;
|
||||
slap_callback *cb = op->o_callback;
|
||||
time_t current_time = slap_get_time();
|
||||
|
||||
Debug(LDAP_DEBUG_ARGS, "==> asyncmeta_back_delete: %s\n",
|
||||
int max_pending_ops = (mi->mi_max_pending_ops == 0) ? META_BACK_CFG_MAX_PENDING_OPS : mi->mi_max_pending_ops;
|
||||
|
||||
Debug(LDAP_DEBUG_TRACE, "==> asyncmeta_back_delete: %s\n",
|
||||
op->o_req_dn.bv_val );
|
||||
|
||||
asyncmeta_new_bm_context(op, rs, &bc, mi->mi_ntargets );
|
||||
if (current_time > op->o_time) {
|
||||
Debug(asyncmeta_debug, "==> asyncmeta_back_delete[%s]: o_time:[%ld], current time: [%ld]\n",
|
||||
op->o_log_prefix, op->o_time, current_time );
|
||||
}
|
||||
|
||||
asyncmeta_new_bm_context(op, rs, &bc, mi->mi_ntargets, mi );
|
||||
if (bc == NULL) {
|
||||
rs->sr_err = LDAP_OTHER;
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
send_ldap_result(op, rs);
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
candidates = bc->candidates;
|
||||
mc = asyncmeta_getconn( op, rs, candidates, &candidate, LDAP_BACK_DONTSEND, 0);
|
||||
if ( !mc || rs->sr_err != LDAP_SUCCESS) {
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
send_ldap_result(op, rs);
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
|
|
@ -152,16 +209,38 @@ asyncmeta_back_delete( Operation *op, SlapReply *rs )
|
|||
bc->retrying = LDAP_BACK_RETRYING;
|
||||
bc->sendok = ( LDAP_BACK_SENDRESULT | bc->retrying );
|
||||
bc->stoptime = op->o_time + bc->timeout;
|
||||
bc->bc_active = 1;
|
||||
|
||||
if (mc->pending_ops >= max_pending_ops) {
|
||||
rs->sr_err = LDAP_BUSY;
|
||||
rs->sr_text = "Maximum pending ops limit exceeded";
|
||||
send_ldap_result(op, rs);
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
rc = asyncmeta_add_message_queue(mc, bc);
|
||||
mc->mc_conns[candidate].msc_active++;
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
|
||||
if (rc != LDAP_SUCCESS) {
|
||||
rs->sr_err = LDAP_BUSY;
|
||||
rs->sr_text = "Maximum pending ops limit exceeded";
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
send_ldap_result(op, rs);
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
mc->mc_conns[candidate].msc_active--;
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
retry:
|
||||
if (bc->timeout && bc->stoptime < slap_get_time()) {
|
||||
int timeout_err;
|
||||
timeout_err = op->o_protocol >= LDAP_VERSION3 ?
|
||||
LDAP_ADMINLIMIT_EXCEEDED : LDAP_OTHER;
|
||||
rs->sr_err = timeout_err;
|
||||
rs->sr_text = "Operation timed out before it was sent to target";
|
||||
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
|
@ -171,47 +250,27 @@ asyncmeta_back_delete( Operation *op, SlapReply *rs )
|
|||
case META_SEARCH_CANDIDATE:
|
||||
/* target is already bound, just send the request */
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_delete: "
|
||||
"cnd=\"%ld\"\n", op->o_log_prefix, candidate );
|
||||
"cnd=\"%d\"\n", op->o_log_prefix, candidate );
|
||||
|
||||
rc = asyncmeta_back_delete_start( op, rs, mc, bc, candidate);
|
||||
rc = asyncmeta_back_delete_start( op, rs, mc, bc, candidate, 1);
|
||||
if (rc == META_SEARCH_ERR) {
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_drop_bc(mc, bc);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||
goto finish;
|
||||
|
||||
} else if (rc == META_SEARCH_NEED_BIND) {
|
||||
goto retry;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case META_SEARCH_NOT_CANDIDATE:
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_delete: NOT_CANDIDATE "
|
||||
"cnd=\"%ld\"\n", op->o_log_prefix, candidate );
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_drop_bc(mc, bc);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
"cnd=\"%d\"\n", op->o_log_prefix, candidate );
|
||||
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||
goto finish;
|
||||
|
||||
case META_SEARCH_NEED_BIND:
|
||||
case META_SEARCH_CONNECTING:
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_delete: NEED_BIND "
|
||||
"cnd=\"%ld\" %p\n", op->o_log_prefix, candidate , &mc->mc_conns[candidate]);
|
||||
rc = asyncmeta_dobind_init(op, rs, bc, mc, candidate);
|
||||
if (rc == META_SEARCH_ERR) {
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_drop_bc(mc, bc);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
goto finish;
|
||||
}
|
||||
break;
|
||||
case META_SEARCH_BINDING:
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_delete: BINDING "
|
||||
"cnd=\"%ld\" %p\n", op->o_log_prefix, candidate , &mc->mc_conns[candidate]);
|
||||
"cnd=\"%d\" %p\n", op->o_log_prefix, candidate , &mc->mc_conns[candidate]);
|
||||
/* Todo add the context to the message queue but do not send the request
|
||||
the receiver must send this when we are done binding */
|
||||
/* question - how would do receiver know to which targets??? */
|
||||
|
|
@ -219,22 +278,21 @@ asyncmeta_back_delete( Operation *op, SlapReply *rs )
|
|||
|
||||
case META_SEARCH_ERR:
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_delete: ERR "
|
||||
"cnd=\"%ldd\"\n", op->o_log_prefix, candidate );
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
candidates[ candidate ].sr_type = REP_RESULT;
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_drop_bc(mc, bc);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
"cnd=\"%d\"\n", op->o_log_prefix, candidate );
|
||||
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||
goto finish;
|
||||
default:
|
||||
assert( 0 );
|
||||
break;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
mc->mc_conns[candidate].msc_active--;
|
||||
asyncmeta_start_one_listener(mc, candidates, bc, candidate);
|
||||
bc->bc_active--;
|
||||
asyncmeta_memctx_toggle(thrctx);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
rs->sr_err = SLAPD_ASYNCOP;
|
||||
finish:
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@
|
|||
#include "../back-ldap/back-ldap.h"
|
||||
#include "back-asyncmeta.h"
|
||||
|
||||
int asyncmeta_debug;
|
||||
|
||||
int
|
||||
asyncmeta_back_open(
|
||||
BackendInfo *bi )
|
||||
|
|
@ -46,6 +48,14 @@ int
|
|||
asyncmeta_back_initialize(
|
||||
BackendInfo *bi )
|
||||
{
|
||||
int rc;
|
||||
struct berval debugbv = BER_BVC("asyncmeta");
|
||||
|
||||
rc = slap_loglevel_get( &debugbv, &asyncmeta_debug );
|
||||
if ( rc ) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
bi->bi_flags =
|
||||
#if 0
|
||||
/* this is not (yet) set essentially because back-meta does not
|
||||
|
|
@ -89,7 +99,7 @@ asyncmeta_back_initialize(
|
|||
bi->bi_chk_referrals = 0;
|
||||
|
||||
bi->bi_connection_init = 0;
|
||||
bi->bi_connection_destroy = asyncmeta_back_conn_destroy;
|
||||
bi->bi_connection_destroy = 0 /* asyncmeta_back_conn_destroy */;
|
||||
|
||||
return asyncmeta_back_init_cf( bi );
|
||||
}
|
||||
|
|
@ -164,9 +174,7 @@ asyncmeta_target_finish(
|
|||
)
|
||||
{
|
||||
slap_bindconf sb = { BER_BVNULL };
|
||||
struct berval mapped;
|
||||
int rc;
|
||||
int msc_num, i;
|
||||
|
||||
ber_str2bv( mt->mt_uri, 0, 0, &sb.sb_uri );
|
||||
sb.sb_version = mt->mt_version;
|
||||
|
|
@ -216,21 +224,6 @@ asyncmeta_target_finish(
|
|||
mi->mi_flags &= ~META_BACK_F_PROXYAUTHZ_NOANON;
|
||||
}
|
||||
|
||||
BER_BVZERO( &mapped );
|
||||
asyncmeta_map( &mt->mt_rwmap.rwm_at,
|
||||
&slap_schema.si_ad_entryDN->ad_cname, &mapped,
|
||||
BACKLDAP_REMAP );
|
||||
if ( BER_BVISNULL( &mapped ) || mapped.bv_val[0] == '\0' ) {
|
||||
mt->mt_rep_flags |= REP_NO_ENTRYDN;
|
||||
}
|
||||
|
||||
BER_BVZERO( &mapped );
|
||||
asyncmeta_map( &mt->mt_rwmap.rwm_at,
|
||||
&slap_schema.si_ad_subschemaSubentry->ad_cname, &mapped,
|
||||
BACKLDAP_REMAP );
|
||||
if ( BER_BVISNULL( &mapped ) || mapped.bv_val[0] == '\0' ) {
|
||||
mt->mt_rep_flags |= REP_NO_SUBSCHEMA;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -240,10 +233,8 @@ asyncmeta_back_db_open(
|
|||
ConfigReply *cr )
|
||||
{
|
||||
a_metainfo_t *mi = (a_metainfo_t *)be->be_private;
|
||||
|
||||
char msg[SLAP_TEXT_BUFLEN];
|
||||
|
||||
int i, rc;
|
||||
int i;
|
||||
|
||||
if ( mi->mi_ntargets == 0 ) {
|
||||
/* Dynamically added, nothing to check here until
|
||||
|
|
@ -272,11 +263,12 @@ asyncmeta_back_db_open(
|
|||
mc->mc_authz_target = META_BOUND_NONE;
|
||||
mc->mc_conns = ch_calloc( mi->mi_ntargets, sizeof( a_metasingleconn_t ));
|
||||
mc->mc_info = mi;
|
||||
LDAP_STAILQ_INIT( &mc->mc_om_list );
|
||||
}
|
||||
|
||||
mi->mi_suffix = be->be_suffix[0];
|
||||
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
|
||||
mi->mi_task = ldap_pvt_runqueue_insert( &slapd_rq, 0,
|
||||
asyncmeta_timeout_loop, mi, "asyncmeta_timeout_loop", be->be_suffix[0].bv_val );
|
||||
asyncmeta_timeout_loop, mi, "asyncmeta_timeout_loop", mi->mi_suffix.bv_val );
|
||||
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -298,36 +290,6 @@ asyncmeta_back_conn_free(
|
|||
free( mc );
|
||||
}
|
||||
|
||||
static void
|
||||
mapping_free(
|
||||
void *v_mapping )
|
||||
{
|
||||
struct ldapmapping *mapping = v_mapping;
|
||||
ch_free( mapping->src.bv_val );
|
||||
ch_free( mapping->dst.bv_val );
|
||||
ch_free( mapping );
|
||||
}
|
||||
|
||||
static void
|
||||
mapping_dst_free(
|
||||
void *v_mapping )
|
||||
{
|
||||
struct ldapmapping *mapping = v_mapping;
|
||||
|
||||
if ( BER_BVISEMPTY( &mapping->dst ) ) {
|
||||
mapping_free( &mapping[ -1 ] );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
asyncmeta_back_map_free( struct ldapmap *lm )
|
||||
{
|
||||
avl_free( lm->remap, mapping_dst_free );
|
||||
avl_free( lm->map, mapping_free );
|
||||
lm->remap = NULL;
|
||||
lm->map = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
asyncmeta_back_stop_miconns( a_metainfo_t *mi )
|
||||
{
|
||||
|
|
@ -344,7 +306,7 @@ asyncmeta_back_clear_miconns( a_metainfo_t *mi )
|
|||
mc = &mi->mi_conns[i];
|
||||
/* todo clear the message queue */
|
||||
for (j = 0; j < mi->mi_ntargets; j ++) {
|
||||
asyncmeta_clear_one_msc(NULL, mc, j);
|
||||
asyncmeta_clear_one_msc(NULL, mc, j, 1, __FUNCTION__);
|
||||
}
|
||||
free(mc->mc_conns);
|
||||
ldap_pvt_thread_mutex_destroy( &mc->mc_om_mutex );
|
||||
|
|
@ -401,14 +363,12 @@ asyncmeta_target_free(
|
|||
if ( mt->mt_idassert_authz != NULL ) {
|
||||
ber_bvarray_free( mt->mt_idassert_authz );
|
||||
}
|
||||
if ( mt->mt_rwmap.rwm_rw ) {
|
||||
rewrite_info_delete( &mt->mt_rwmap.rwm_rw );
|
||||
if ( mt->mt_rwmap.rwm_bva_rewrite )
|
||||
ber_bvarray_free( mt->mt_rwmap.rwm_bva_rewrite );
|
||||
if ( !BER_BVISNULL( &mt->mt_lsuffixm )) {
|
||||
ch_free( mt->mt_lsuffixm.bv_val );
|
||||
}
|
||||
if ( !BER_BVISNULL( &mt->mt_rsuffixm )) {
|
||||
ch_free( mt->mt_rsuffixm.bv_val );
|
||||
}
|
||||
asyncmeta_back_map_free( &mt->mt_rwmap.rwm_oc );
|
||||
asyncmeta_back_map_free( &mt->mt_rwmap.rwm_at );
|
||||
ber_bvarray_free( mt->mt_rwmap.rwm_bva_map );
|
||||
free( mt );
|
||||
}
|
||||
|
||||
|
|
@ -420,8 +380,6 @@ asyncmeta_back_db_close(
|
|||
a_metainfo_t *mi;
|
||||
|
||||
if ( be->be_private ) {
|
||||
int i;
|
||||
|
||||
mi = ( a_metainfo_t * )be->be_private;
|
||||
if ( mi->mi_task != NULL ) {
|
||||
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
|
||||
|
|
@ -435,6 +393,7 @@ asyncmeta_back_db_close(
|
|||
asyncmeta_back_stop_miconns( mi );
|
||||
ldap_pvt_thread_mutex_unlock( &mi->mi_mc_mutex );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -486,13 +445,14 @@ asyncmeta_back_db_destroy(
|
|||
if ( META_BACK_QUARANTINE( mi ) ) {
|
||||
mi->mi_ldap_extra->retry_info_destroy( &mi->mi_quarantine );
|
||||
}
|
||||
}
|
||||
ldap_pvt_thread_mutex_lock( &mi->mi_mc_mutex );
|
||||
asyncmeta_back_clear_miconns(mi);
|
||||
ldap_pvt_thread_mutex_unlock( &mi->mi_mc_mutex );
|
||||
ldap_pvt_thread_mutex_destroy( &mi->mi_mc_mutex );
|
||||
|
||||
free( be->be_private );
|
||||
ldap_pvt_thread_mutex_lock( &mi->mi_mc_mutex );
|
||||
asyncmeta_back_clear_miconns(mi);
|
||||
ldap_pvt_thread_mutex_unlock( &mi->mi_mc_mutex );
|
||||
ldap_pvt_thread_mutex_destroy( &mi->mi_mc_mutex );
|
||||
|
||||
free( be->be_private );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -63,641 +63,10 @@
|
|||
#include "../back-ldap/back-ldap.h"
|
||||
#include "back-asyncmeta.h"
|
||||
|
||||
int
|
||||
asyncmeta_mapping_cmp ( const void *c1, const void *c2 )
|
||||
{
|
||||
struct ldapmapping *map1 = (struct ldapmapping *)c1;
|
||||
struct ldapmapping *map2 = (struct ldapmapping *)c2;
|
||||
int rc = map1->src.bv_len - map2->src.bv_len;
|
||||
if (rc) return rc;
|
||||
return ( strcasecmp( map1->src.bv_val, map2->src.bv_val ) );
|
||||
}
|
||||
|
||||
int
|
||||
asyncmeta_mapping_dup ( void *c1, void *c2 )
|
||||
{
|
||||
struct ldapmapping *map1 = (struct ldapmapping *)c1;
|
||||
struct ldapmapping *map2 = (struct ldapmapping *)c2;
|
||||
|
||||
return ( ( strcasecmp( map1->src.bv_val, map2->src.bv_val ) == 0 ) ? -1 : 0 );
|
||||
}
|
||||
|
||||
void
|
||||
asyncmeta_map_init ( struct ldapmap *lm, struct ldapmapping **m )
|
||||
{
|
||||
struct ldapmapping *mapping;
|
||||
|
||||
assert( m != NULL );
|
||||
|
||||
*m = NULL;
|
||||
|
||||
mapping = (struct ldapmapping *)ch_calloc( 2,
|
||||
sizeof( struct ldapmapping ) );
|
||||
if ( mapping == NULL ) {
|
||||
return;
|
||||
}
|
||||
|
||||
ber_str2bv( "objectclass", STRLENOF("objectclass"), 1, &mapping[0].src);
|
||||
ber_dupbv( &mapping[0].dst, &mapping[0].src );
|
||||
mapping[1].src = mapping[0].src;
|
||||
mapping[1].dst = mapping[0].dst;
|
||||
|
||||
avl_insert( &lm->map, (caddr_t)&mapping[0],
|
||||
asyncmeta_mapping_cmp, asyncmeta_mapping_dup );
|
||||
avl_insert( &lm->remap, (caddr_t)&mapping[1],
|
||||
asyncmeta_mapping_cmp, asyncmeta_mapping_dup );
|
||||
*m = mapping;
|
||||
}
|
||||
|
||||
int
|
||||
asyncmeta_mapping ( struct ldapmap *map, struct berval *s, struct ldapmapping **m,
|
||||
int remap )
|
||||
{
|
||||
Avlnode *tree;
|
||||
struct ldapmapping fmapping;
|
||||
|
||||
assert( m != NULL );
|
||||
|
||||
/* let special attrnames slip through (ITS#5760) */
|
||||
if ( bvmatch( s, slap_bv_no_attrs )
|
||||
|| bvmatch( s, slap_bv_all_user_attrs )
|
||||
|| bvmatch( s, slap_bv_all_operational_attrs ) )
|
||||
{
|
||||
*m = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( remap == BACKLDAP_REMAP ) {
|
||||
tree = map->remap;
|
||||
|
||||
} else {
|
||||
tree = map->map;
|
||||
}
|
||||
|
||||
fmapping.src = *s;
|
||||
*m = (struct ldapmapping *)avl_find( tree, (caddr_t)&fmapping, asyncmeta_mapping_cmp );
|
||||
if ( *m == NULL ) {
|
||||
return map->drop_missing;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
asyncmeta_map ( struct ldapmap *map, struct berval *s, struct berval *bv,
|
||||
int remap )
|
||||
{
|
||||
struct ldapmapping *mapping;
|
||||
int drop_missing;
|
||||
|
||||
/* map->map may be NULL when mapping is configured,
|
||||
* but map->remap can't */
|
||||
if ( map->remap == NULL ) {
|
||||
*bv = *s;
|
||||
return;
|
||||
}
|
||||
|
||||
BER_BVZERO( bv );
|
||||
drop_missing = asyncmeta_mapping( map, s, &mapping, remap );
|
||||
if ( mapping != NULL ) {
|
||||
if ( !BER_BVISNULL( &mapping->dst ) ) {
|
||||
*bv = mapping->dst;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !drop_missing ) {
|
||||
*bv = *s;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
asyncmeta_map_attrs(
|
||||
Operation *op,
|
||||
struct ldapmap *at_map,
|
||||
AttributeName *an,
|
||||
int remap,
|
||||
char ***mapped_attrs )
|
||||
{
|
||||
int i, x, j;
|
||||
char **na;
|
||||
struct berval mapped;
|
||||
|
||||
if ( an == NULL && op->o_bd->be_extra_anlist == NULL ) {
|
||||
*mapped_attrs = NULL;
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
if ( an != NULL ) {
|
||||
for ( ; !BER_BVISNULL( &an[i].an_name ); i++ )
|
||||
/* */ ;
|
||||
}
|
||||
|
||||
x = 0;
|
||||
if ( op->o_bd->be_extra_anlist != NULL ) {
|
||||
for ( ; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++ )
|
||||
/* */ ;
|
||||
}
|
||||
|
||||
assert( i > 0 || x > 0 );
|
||||
|
||||
na = (char **)ber_memcalloc_x( i + x + 1, sizeof(char *), op->o_tmpmemctx );
|
||||
if ( na == NULL ) {
|
||||
*mapped_attrs = NULL;
|
||||
return LDAP_NO_MEMORY;
|
||||
}
|
||||
|
||||
j = 0;
|
||||
if ( i > 0 ) {
|
||||
for ( i = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) {
|
||||
asyncmeta_map( at_map, &an[i].an_name, &mapped, remap );
|
||||
if ( !BER_BVISNULL( &mapped ) && !BER_BVISEMPTY( &mapped ) ) {
|
||||
na[j++] = mapped.bv_val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( x > 0 ) {
|
||||
for ( x = 0; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++ ) {
|
||||
if ( op->o_bd->be_extra_anlist[x].an_desc &&
|
||||
ad_inlist( op->o_bd->be_extra_anlist[x].an_desc, an ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
asyncmeta_map( at_map, &op->o_bd->be_extra_anlist[x].an_name, &mapped, remap );
|
||||
if ( !BER_BVISNULL( &mapped ) && !BER_BVISEMPTY( &mapped ) ) {
|
||||
na[j++] = mapped.bv_val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( j == 0 && ( i > 0 || x > 0 ) ) {
|
||||
na[j++] = LDAP_NO_ATTRS;
|
||||
}
|
||||
na[j] = NULL;
|
||||
|
||||
*mapped_attrs = na;
|
||||
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
map_attr_value(
|
||||
a_dncookie *dc,
|
||||
AttributeDescription *ad,
|
||||
struct berval *mapped_attr,
|
||||
struct berval *value,
|
||||
struct berval *mapped_value,
|
||||
int remap,
|
||||
void *memctx )
|
||||
{
|
||||
struct berval vtmp;
|
||||
int freeval = 0;
|
||||
|
||||
asyncmeta_map( &dc->target->mt_rwmap.rwm_at, &ad->ad_cname, mapped_attr, remap );
|
||||
if ( BER_BVISNULL( mapped_attr ) || BER_BVISEMPTY( mapped_attr ) ) {
|
||||
#if 0
|
||||
/*
|
||||
* FIXME: are we sure we need to search oc_map if at_map fails?
|
||||
*/
|
||||
asyncmeta_map( &dc->target->mt_rwmap.rwm_oc, &ad->ad_cname, mapped_attr, remap );
|
||||
if ( BER_BVISNULL( mapped_attr ) || BER_BVISEMPTY( mapped_attr ) ) {
|
||||
*mapped_attr = ad->ad_cname;
|
||||
}
|
||||
#endif
|
||||
if ( dc->target->mt_rwmap.rwm_at.drop_missing ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*mapped_attr = ad->ad_cname;
|
||||
}
|
||||
|
||||
if ( value == NULL ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
|
||||
{
|
||||
a_dncookie fdc = *dc;
|
||||
|
||||
fdc.ctx = "searchFilterAttrDN";
|
||||
|
||||
switch ( asyncmeta_dn_massage( &fdc, value, &vtmp ) ) {
|
||||
case LDAP_SUCCESS:
|
||||
if ( vtmp.bv_val != value->bv_val ) {
|
||||
freeval = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case LDAP_UNWILLING_TO_PERFORM:
|
||||
return -1;
|
||||
|
||||
case LDAP_OTHER:
|
||||
return -1;
|
||||
}
|
||||
|
||||
} else if ( ad->ad_type->sat_equality &&
|
||||
ad->ad_type->sat_equality->smr_usage & SLAP_MR_MUTATION_NORMALIZER )
|
||||
{
|
||||
if ( ad->ad_type->sat_equality->smr_normalize(
|
||||
(SLAP_MR_DENORMALIZE|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX),
|
||||
NULL, NULL, value, &vtmp, memctx ) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
freeval = 2;
|
||||
|
||||
} else if ( ad == slap_schema.si_ad_objectClass || ad == slap_schema.si_ad_structuralObjectClass ) {
|
||||
asyncmeta_map( &dc->target->mt_rwmap.rwm_oc, value, &vtmp, remap );
|
||||
if ( BER_BVISNULL( &vtmp ) || BER_BVISEMPTY( &vtmp ) ) {
|
||||
vtmp = *value;
|
||||
}
|
||||
|
||||
} else {
|
||||
vtmp = *value;
|
||||
}
|
||||
|
||||
filter_escape_value_x( &vtmp, mapped_value, memctx );
|
||||
|
||||
switch ( freeval ) {
|
||||
case 1:
|
||||
ber_memfree( vtmp.bv_val );
|
||||
break;
|
||||
case 2:
|
||||
ber_memfree_x( vtmp.bv_val, memctx );
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
asyncmeta_int_filter_map_rewrite(
|
||||
a_dncookie *dc,
|
||||
Filter *f,
|
||||
struct berval *fstr,
|
||||
int remap,
|
||||
void *memctx )
|
||||
{
|
||||
int i;
|
||||
Filter *p;
|
||||
struct berval atmp,
|
||||
vtmp,
|
||||
*tmp;
|
||||
static struct berval
|
||||
/* better than nothing... */
|
||||
ber_bvfalse = BER_BVC( "(!(objectClass=*))" ),
|
||||
ber_bvtf_false = BER_BVC( "(|)" ),
|
||||
/* better than nothing... */
|
||||
ber_bvtrue = BER_BVC( "(objectClass=*)" ),
|
||||
ber_bvtf_true = BER_BVC( "(&)" ),
|
||||
#if 0
|
||||
/* no longer needed; preserved for completeness */
|
||||
ber_bvundefined = BER_BVC( "(?=undefined)" ),
|
||||
#endif
|
||||
ber_bverror = BER_BVC( "(?=error)" ),
|
||||
ber_bvunknown = BER_BVC( "(?=unknown)" ),
|
||||
ber_bvnone = BER_BVC( "(?=none)" );
|
||||
ber_len_t len;
|
||||
|
||||
assert( fstr != NULL );
|
||||
BER_BVZERO( fstr );
|
||||
|
||||
if ( f == NULL ) {
|
||||
ber_dupbv_x( fstr, &ber_bvnone, memctx );
|
||||
return LDAP_OTHER;
|
||||
}
|
||||
|
||||
switch ( ( f->f_choice & SLAPD_FILTER_MASK ) ) {
|
||||
case LDAP_FILTER_EQUALITY:
|
||||
if ( map_attr_value( dc, f->f_av_desc, &atmp,
|
||||
&f->f_av_value, &vtmp, remap, memctx ) )
|
||||
{
|
||||
goto computed;
|
||||
}
|
||||
|
||||
fstr->bv_len = atmp.bv_len + vtmp.bv_len
|
||||
+ ( sizeof("(=)") - 1 );
|
||||
fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx );
|
||||
|
||||
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
|
||||
atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
|
||||
|
||||
ber_memfree_x( vtmp.bv_val, memctx );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_GE:
|
||||
if ( map_attr_value( dc, f->f_av_desc, &atmp,
|
||||
&f->f_av_value, &vtmp, remap, memctx ) )
|
||||
{
|
||||
goto computed;
|
||||
}
|
||||
|
||||
fstr->bv_len = atmp.bv_len + vtmp.bv_len
|
||||
+ ( sizeof("(>=)") - 1 );
|
||||
fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx );
|
||||
|
||||
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
|
||||
atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
|
||||
|
||||
ber_memfree_x( vtmp.bv_val, memctx );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_LE:
|
||||
if ( map_attr_value( dc, f->f_av_desc, &atmp,
|
||||
&f->f_av_value, &vtmp, remap, memctx ) )
|
||||
{
|
||||
goto computed;
|
||||
}
|
||||
|
||||
fstr->bv_len = atmp.bv_len + vtmp.bv_len
|
||||
+ ( sizeof("(<=)") - 1 );
|
||||
fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx );
|
||||
|
||||
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
|
||||
atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
|
||||
|
||||
ber_memfree_x( vtmp.bv_val, memctx );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_APPROX:
|
||||
if ( map_attr_value( dc, f->f_av_desc, &atmp,
|
||||
&f->f_av_value, &vtmp, remap, memctx ) )
|
||||
{
|
||||
goto computed;
|
||||
}
|
||||
|
||||
fstr->bv_len = atmp.bv_len + vtmp.bv_len
|
||||
+ ( sizeof("(~=)") - 1 );
|
||||
fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx );
|
||||
|
||||
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
|
||||
atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
|
||||
|
||||
ber_memfree_x( vtmp.bv_val, memctx );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_SUBSTRINGS:
|
||||
if ( map_attr_value( dc, f->f_sub_desc, &atmp,
|
||||
NULL, NULL, remap, memctx ) )
|
||||
{
|
||||
goto computed;
|
||||
}
|
||||
|
||||
/* cannot be a DN ... */
|
||||
|
||||
fstr->bv_len = atmp.bv_len + ( STRLENOF( "(=*)" ) );
|
||||
fstr->bv_val = ber_memalloc_x( fstr->bv_len + 128, memctx ); /* FIXME: why 128 ? */
|
||||
|
||||
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
|
||||
atmp.bv_val );
|
||||
|
||||
if ( !BER_BVISNULL( &f->f_sub_initial ) ) {
|
||||
len = fstr->bv_len;
|
||||
|
||||
filter_escape_value_x( &f->f_sub_initial, &vtmp, memctx );
|
||||
|
||||
fstr->bv_len += vtmp.bv_len;
|
||||
fstr->bv_val = ber_memrealloc_x( fstr->bv_val, fstr->bv_len + 1, memctx );
|
||||
|
||||
snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3,
|
||||
/* "(attr=" */ "%s*)",
|
||||
vtmp.bv_len ? vtmp.bv_val : "" );
|
||||
|
||||
ber_memfree_x( vtmp.bv_val, memctx );
|
||||
}
|
||||
|
||||
if ( f->f_sub_any != NULL ) {
|
||||
for ( i = 0; !BER_BVISNULL( &f->f_sub_any[i] ); i++ ) {
|
||||
len = fstr->bv_len;
|
||||
filter_escape_value_x( &f->f_sub_any[i], &vtmp, memctx );
|
||||
|
||||
fstr->bv_len += vtmp.bv_len + 1;
|
||||
fstr->bv_val = ber_memrealloc_x( fstr->bv_val, fstr->bv_len + 1, memctx );
|
||||
|
||||
snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
|
||||
/* "(attr=[init]*[any*]" */ "%s*)",
|
||||
vtmp.bv_len ? vtmp.bv_val : "" );
|
||||
ber_memfree_x( vtmp.bv_val, memctx );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &f->f_sub_final ) ) {
|
||||
len = fstr->bv_len;
|
||||
|
||||
filter_escape_value_x( &f->f_sub_final, &vtmp, memctx );
|
||||
|
||||
fstr->bv_len += vtmp.bv_len;
|
||||
fstr->bv_val = ber_memrealloc_x( fstr->bv_val, fstr->bv_len + 1, memctx );
|
||||
|
||||
snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
|
||||
/* "(attr=[init*][any*]" */ "%s)",
|
||||
vtmp.bv_len ? vtmp.bv_val : "" );
|
||||
|
||||
ber_memfree_x( vtmp.bv_val, memctx );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_PRESENT:
|
||||
if ( map_attr_value( dc, f->f_desc, &atmp,
|
||||
NULL, NULL, remap, memctx ) )
|
||||
{
|
||||
goto computed;
|
||||
}
|
||||
|
||||
fstr->bv_len = atmp.bv_len + ( STRLENOF( "(=*)" ) );
|
||||
fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx );
|
||||
|
||||
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
|
||||
atmp.bv_val );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_AND:
|
||||
case LDAP_FILTER_OR:
|
||||
case LDAP_FILTER_NOT:
|
||||
fstr->bv_len = STRLENOF( "(%)" );
|
||||
fstr->bv_val = ber_memalloc_x( fstr->bv_len + 128, memctx ); /* FIXME: why 128? */
|
||||
|
||||
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
|
||||
f->f_choice == LDAP_FILTER_AND ? '&' :
|
||||
f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
|
||||
|
||||
for ( p = f->f_list; p != NULL; p = p->f_next ) {
|
||||
int rc;
|
||||
|
||||
len = fstr->bv_len;
|
||||
|
||||
rc = asyncmeta_int_filter_map_rewrite( dc, p, &vtmp, remap, memctx );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
fstr->bv_len += vtmp.bv_len;
|
||||
fstr->bv_val = ber_memrealloc_x( fstr->bv_val, fstr->bv_len + 1, memctx );
|
||||
|
||||
snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2,
|
||||
/*"("*/ "%s)", vtmp.bv_len ? vtmp.bv_val : "" );
|
||||
|
||||
ber_memfree_x( vtmp.bv_val, memctx );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_EXT:
|
||||
if ( f->f_mr_desc ) {
|
||||
if ( map_attr_value( dc, f->f_mr_desc, &atmp,
|
||||
&f->f_mr_value, &vtmp, remap, memctx ) )
|
||||
{
|
||||
goto computed;
|
||||
}
|
||||
|
||||
} else {
|
||||
BER_BVSTR( &atmp, "" );
|
||||
filter_escape_value_x( &f->f_mr_value, &vtmp, memctx );
|
||||
}
|
||||
|
||||
/* FIXME: cleanup (less ?: operators...) */
|
||||
fstr->bv_len = atmp.bv_len +
|
||||
( f->f_mr_dnattrs ? STRLENOF( ":dn" ) : 0 ) +
|
||||
( !BER_BVISEMPTY( &f->f_mr_rule_text ) ? f->f_mr_rule_text.bv_len + 1 : 0 ) +
|
||||
vtmp.bv_len + ( STRLENOF( "(:=)" ) );
|
||||
fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx );
|
||||
|
||||
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
|
||||
atmp.bv_val,
|
||||
f->f_mr_dnattrs ? ":dn" : "",
|
||||
!BER_BVISEMPTY( &f->f_mr_rule_text ) ? ":" : "",
|
||||
!BER_BVISEMPTY( &f->f_mr_rule_text ) ? f->f_mr_rule_text.bv_val : "",
|
||||
vtmp.bv_len ? vtmp.bv_val : "" );
|
||||
ber_memfree_x( vtmp.bv_val, memctx );
|
||||
break;
|
||||
|
||||
case SLAPD_FILTER_COMPUTED:
|
||||
switch ( f->f_result ) {
|
||||
/* FIXME: treat UNDEFINED as FALSE */
|
||||
case SLAPD_COMPARE_UNDEFINED:
|
||||
computed:;
|
||||
if ( META_BACK_TGT_NOUNDEFFILTER( dc->target ) ) {
|
||||
return LDAP_COMPARE_FALSE;
|
||||
}
|
||||
/* fallthru */
|
||||
|
||||
case LDAP_COMPARE_FALSE:
|
||||
if ( META_BACK_TGT_T_F( dc->target ) ) {
|
||||
tmp = &ber_bvtf_false;
|
||||
break;
|
||||
}
|
||||
tmp = &ber_bvfalse;
|
||||
break;
|
||||
|
||||
case LDAP_COMPARE_TRUE:
|
||||
if ( META_BACK_TGT_T_F( dc->target ) ) {
|
||||
tmp = &ber_bvtf_true;
|
||||
break;
|
||||
}
|
||||
|
||||
tmp = &ber_bvtrue;
|
||||
break;
|
||||
|
||||
default:
|
||||
tmp = &ber_bverror;
|
||||
break;
|
||||
}
|
||||
|
||||
ber_dupbv_x( fstr, tmp, memctx );
|
||||
break;
|
||||
|
||||
default:
|
||||
ber_dupbv_x( fstr, &ber_bvunknown, memctx );
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
asyncmeta_filter_map_rewrite(
|
||||
a_dncookie *dc,
|
||||
Filter *f,
|
||||
struct berval *fstr,
|
||||
int remap,
|
||||
void *memctx )
|
||||
{
|
||||
int rc;
|
||||
a_dncookie fdc;
|
||||
struct berval ftmp;
|
||||
static char *dmy = "";
|
||||
|
||||
rc = asyncmeta_int_filter_map_rewrite( dc, f, fstr, remap, memctx );
|
||||
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
fdc = *dc;
|
||||
ftmp = *fstr;
|
||||
|
||||
fdc.ctx = "searchFilter";
|
||||
|
||||
switch ( rewrite_session( fdc.target->mt_rwmap.rwm_rw, fdc.ctx,
|
||||
( !BER_BVISEMPTY( &ftmp ) ? ftmp.bv_val : dmy ),
|
||||
fdc.conn, &fstr->bv_val ) )
|
||||
{
|
||||
case REWRITE_REGEXEC_OK:
|
||||
if ( !BER_BVISNULL( fstr ) ) {
|
||||
fstr->bv_len = strlen( fstr->bv_val );
|
||||
|
||||
} else {
|
||||
*fstr = ftmp;
|
||||
}
|
||||
Debug( LDAP_DEBUG_ARGS,
|
||||
"[rw] %s: \"%s\" -> \"%s\"\n",
|
||||
fdc.ctx, BER_BVISNULL( &ftmp ) ? "" : ftmp.bv_val,
|
||||
BER_BVISNULL( fstr ) ? "" : fstr->bv_val );
|
||||
rc = LDAP_SUCCESS;
|
||||
break;
|
||||
|
||||
case REWRITE_REGEXEC_UNWILLING:
|
||||
if ( fdc.rs ) {
|
||||
fdc.rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
|
||||
fdc.rs->sr_text = "Operation not allowed";
|
||||
}
|
||||
rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
break;
|
||||
|
||||
case REWRITE_REGEXEC_ERR:
|
||||
if ( fdc.rs ) {
|
||||
fdc.rs->sr_err = LDAP_OTHER;
|
||||
fdc.rs->sr_text = "Rewrite error";
|
||||
}
|
||||
rc = LDAP_OTHER;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( fstr->bv_val == dmy ) {
|
||||
BER_BVZERO( fstr );
|
||||
|
||||
} else if ( fstr->bv_val != ftmp.bv_val ) {
|
||||
/* NOTE: need to realloc mapped filter on slab
|
||||
* and free the original one, until librewrite
|
||||
* becomes slab-aware
|
||||
*/
|
||||
ber_dupbv_x( &ftmp, fstr, memctx );
|
||||
ch_free( fstr->bv_val );
|
||||
*fstr = ftmp;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
asyncmeta_referral_result_rewrite(
|
||||
a_dncookie *dc,
|
||||
BerVarray a_vals,
|
||||
void *memctx
|
||||
BerVarray a_vals
|
||||
)
|
||||
{
|
||||
int i, last;
|
||||
|
|
@ -731,144 +100,115 @@ asyncmeta_referral_result_rewrite(
|
|||
|
||||
ber_str2bv( ludp->lud_dn, 0, 0, &olddn );
|
||||
|
||||
rc = asyncmeta_dn_massage( dc, &olddn, &dn );
|
||||
switch ( rc ) {
|
||||
case LDAP_UNWILLING_TO_PERFORM:
|
||||
/*
|
||||
* FIXME: need to check if it may be considered
|
||||
* legal to trim values when adding/modifying;
|
||||
* it should be when searching (e.g. ACLs).
|
||||
*/
|
||||
ber_memfree( a_vals[ i ].bv_val );
|
||||
if ( last > i ) {
|
||||
a_vals[ i ] = a_vals[ last ];
|
||||
}
|
||||
BER_BVZERO( &a_vals[ last ] );
|
||||
last--;
|
||||
i--;
|
||||
break;
|
||||
asyncmeta_dn_massage( dc, &olddn, &dn );
|
||||
/* leave attr untouched if massage did nothing */
|
||||
if ( olddn.bv_val != dn.bv_val )
|
||||
{
|
||||
char *newurl;
|
||||
|
||||
default:
|
||||
/* leave attr untouched if massage failed */
|
||||
if ( !BER_BVISNULL( &dn ) && olddn.bv_val != dn.bv_val )
|
||||
ludp->lud_dn = dn.bv_val;
|
||||
newurl = ldap_url_desc2str( ludp );
|
||||
dc->op->o_tmpfree( dn.bv_val, dc->memctx );
|
||||
if ( newurl )
|
||||
{
|
||||
char *newurl;
|
||||
/* FIXME: leave attr untouched
|
||||
* even if ldap_url_desc2str failed...
|
||||
*/
|
||||
|
||||
ludp->lud_dn = dn.bv_val;
|
||||
newurl = ldap_url_desc2str( ludp );
|
||||
free( dn.bv_val );
|
||||
if ( newurl == NULL ) {
|
||||
/* FIXME: leave attr untouched
|
||||
* even if ldap_url_desc2str failed...
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
ber_memfree_x( a_vals[ i ].bv_val, memctx );
|
||||
ber_str2bv_x( newurl, 0, 1, &a_vals[ i ], memctx );
|
||||
ber_memfree_x( a_vals[ i ].bv_val, dc->op->o_tmpmemctx );
|
||||
ber_str2bv_x( newurl, 0, 1, &a_vals[ i ], dc->memctx );
|
||||
ber_memfree( newurl );
|
||||
ludp->lud_dn = olddn.bv_val;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ldap_free_urldesc( ludp );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* I don't like this much, but we need two different
|
||||
* functions because different heap managers may be
|
||||
* in use in back-ldap/meta to reduce the amount of
|
||||
* calls to malloc routines, and some of the free()
|
||||
* routines may be macros with args
|
||||
*/
|
||||
int
|
||||
asyncmeta_dnattr_rewrite(
|
||||
a_dncookie *dc,
|
||||
BerVarray a_vals
|
||||
)
|
||||
{
|
||||
struct berval bv;
|
||||
int i, last;
|
||||
|
||||
assert( a_vals != NULL );
|
||||
|
||||
for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ )
|
||||
;
|
||||
last--;
|
||||
|
||||
for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
|
||||
switch ( asyncmeta_dn_massage( dc, &a_vals[i], &bv ) ) {
|
||||
case LDAP_UNWILLING_TO_PERFORM:
|
||||
/*
|
||||
* FIXME: need to check if it may be considered
|
||||
* legal to trim values when adding/modifying;
|
||||
* it should be when searching (e.g. ACLs).
|
||||
*/
|
||||
ch_free( a_vals[i].bv_val );
|
||||
if ( last > i ) {
|
||||
a_vals[i] = a_vals[last];
|
||||
}
|
||||
BER_BVZERO( &a_vals[last] );
|
||||
last--;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* leave attr untouched if massage failed */
|
||||
if ( !BER_BVISNULL( &bv ) && bv.bv_val != a_vals[i].bv_val ) {
|
||||
ch_free( a_vals[i].bv_val );
|
||||
a_vals[i] = bv;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
asyncmeta_dnattr_result_rewrite(
|
||||
a_dncookie *dc,
|
||||
BerVarray a_vals
|
||||
)
|
||||
{
|
||||
struct berval bv;
|
||||
int i, last;
|
||||
int i;
|
||||
|
||||
assert( a_vals != NULL );
|
||||
|
||||
for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ )
|
||||
;
|
||||
last--;
|
||||
|
||||
for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
|
||||
switch ( asyncmeta_dn_massage( dc, &a_vals[i], &bv ) ) {
|
||||
case LDAP_UNWILLING_TO_PERFORM:
|
||||
/*
|
||||
* FIXME: need to check if it may be considered
|
||||
* legal to trim values when adding/modifying;
|
||||
* it should be when searching (e.g. ACLs).
|
||||
*/
|
||||
ber_memfree( a_vals[i].bv_val );
|
||||
if ( last > i ) {
|
||||
a_vals[i] = a_vals[last];
|
||||
}
|
||||
BER_BVZERO( &a_vals[last] );
|
||||
last--;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* leave attr untouched if massage failed */
|
||||
if ( !BER_BVISNULL( &bv ) && a_vals[i].bv_val != bv.bv_val ) {
|
||||
ber_memfree( a_vals[i].bv_val );
|
||||
a_vals[i] = bv;
|
||||
}
|
||||
break;
|
||||
asyncmeta_dn_massage( dc, &a_vals[i], &bv );
|
||||
if ( bv.bv_val != a_vals[i].bv_val ) {
|
||||
ber_memfree_x( a_vals[i].bv_val, dc->memctx );
|
||||
a_vals[i] = bv;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* asyncmeta_dn_massage
|
||||
*
|
||||
* Aliases the suffix.
|
||||
*/
|
||||
void
|
||||
asyncmeta_dn_massage(
|
||||
a_dncookie *dc,
|
||||
struct berval *odn,
|
||||
struct berval *res
|
||||
)
|
||||
{
|
||||
struct berval pretty = {0,NULL}, *dn = odn;
|
||||
struct berval *osuff, *nsuff;
|
||||
int diff;
|
||||
|
||||
assert( res );
|
||||
|
||||
BER_BVZERO(res);
|
||||
if ( dn == NULL )
|
||||
return;
|
||||
|
||||
/* no suffix massage configured */
|
||||
if ( !dc->target->mt_lsuffixm.bv_val ) {
|
||||
*res = *dn;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( dc->to_from == MASSAGE_REQ ) {
|
||||
osuff = &dc->target->mt_lsuffixm;
|
||||
nsuff = &dc->target->mt_rsuffixm;
|
||||
} else {
|
||||
osuff = &dc->target->mt_rsuffixm;
|
||||
nsuff = &dc->target->mt_lsuffixm;
|
||||
/* DN from remote server may be in arbitrary form.
|
||||
* Pretty it so we can parse reliably.
|
||||
*/
|
||||
dnPretty( NULL, dn, &pretty, dc->op->o_tmpmemctx );
|
||||
if (pretty.bv_val) dn = &pretty;
|
||||
}
|
||||
|
||||
diff = dn->bv_len - osuff->bv_len;
|
||||
/* DN is shorter than suffix - ignore */
|
||||
if ( diff < 0 ) {
|
||||
ignore:
|
||||
*res = *odn;
|
||||
if (pretty.bv_val)
|
||||
dc->op->o_tmpfree( pretty.bv_val, dc->op->o_tmpmemctx );
|
||||
return;
|
||||
}
|
||||
|
||||
/* DN longer than our suffix and doesn't match */
|
||||
if ( diff > 0 && !DN_SEPARATOR(dn->bv_val[diff-1]))
|
||||
goto ignore;
|
||||
|
||||
/* suffix is same length as ours, but doesn't match */
|
||||
if ( strcasecmp( osuff->bv_val, &dn->bv_val[diff] ))
|
||||
goto ignore;
|
||||
|
||||
res->bv_len = diff + nsuff->bv_len;
|
||||
res->bv_val = dc->op->o_tmpalloc( res->bv_len + 1, dc->memctx );
|
||||
strncpy( res->bv_val, dn->bv_val, diff );
|
||||
strcpy( &res->bv_val[diff], nsuff->bv_val );
|
||||
|
||||
if (pretty.bv_val)
|
||||
dc->op->o_tmpfree( pretty.bv_val, dc->op->o_tmpmemctx );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,182 +37,6 @@
|
|||
#include "lutil.h"
|
||||
|
||||
|
||||
LDAPControl **asyncmeta_copy_controls(Operation *op)
|
||||
{
|
||||
LDAPControl **new_controls = NULL;
|
||||
LDAPControl **c;
|
||||
LDAPControl *tmp_ctl = NULL;
|
||||
int i, length = 1;
|
||||
|
||||
|
||||
if (op->o_ctrls == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
for (c = op->o_ctrls; *c != NULL; c++) {
|
||||
length++;
|
||||
}
|
||||
|
||||
new_controls = op->o_tmpalloc( sizeof(LDAPControl*)*length, op->o_tmpmemctx );
|
||||
for (i = 0; i < length-1; i ++) {
|
||||
new_controls[i] = op->o_tmpalloc( sizeof(LDAPControl), op->o_tmpmemctx );
|
||||
if (op->o_ctrls[i]->ldctl_value.bv_len > 0) {
|
||||
ber_dupbv_x( &new_controls[i]->ldctl_value, &op->o_ctrls[i]->ldctl_value, op->o_tmpmemctx);
|
||||
}
|
||||
if (op->o_ctrls[i]->ldctl_oid) {
|
||||
new_controls[i]->ldctl_oid = ber_strdup_x(op->o_ctrls[i]->ldctl_oid, op->o_tmpmemctx);
|
||||
}
|
||||
new_controls[i]->ldctl_iscritical = op->o_ctrls[i]->ldctl_iscritical;
|
||||
}
|
||||
new_controls[length-1] = NULL;
|
||||
return new_controls;
|
||||
}
|
||||
|
||||
static
|
||||
void asyncmeta_free_op_controls(Operation *op)
|
||||
{
|
||||
LDAPControl **c;
|
||||
for (c = op->o_ctrls; *c != NULL; c++) {
|
||||
if ((*c)->ldctl_value.bv_len > 0) {
|
||||
free((*c)->ldctl_value.bv_val);
|
||||
}
|
||||
if ((*c)->ldctl_oid) {
|
||||
free((*c)->ldctl_oid);
|
||||
}
|
||||
free(*c);
|
||||
}
|
||||
free(op->o_ctrls);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
Modifications* asyncmeta_copy_modlist(Operation *op, Modifications *modlist)
|
||||
{
|
||||
Modifications *ml;
|
||||
Modifications *new_mods = NULL;
|
||||
for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
|
||||
Modifications *mod = op->o_tmpalloc( sizeof( Modifications ), op->o_tmpmemctx );
|
||||
*mod = *ml;
|
||||
if ( ml->sml_values ) {
|
||||
ber_bvarray_dup_x( &mod->sml_values, ml->sml_values, op->o_tmpmemctx );
|
||||
if ( ml->sml_nvalues ) {
|
||||
ber_bvarray_dup_x( &mod->sml_nvalues, ml->sml_nvalues, op->o_tmpmemctx );
|
||||
}
|
||||
}
|
||||
mod->sml_next = NULL;
|
||||
if (new_mods == NULL) {
|
||||
new_mods = mod;
|
||||
} else {
|
||||
new_mods->sml_next = mod;
|
||||
}
|
||||
}
|
||||
return new_mods;
|
||||
}
|
||||
|
||||
Operation *asyncmeta_copy_op(Operation *op)
|
||||
{
|
||||
const char *text;
|
||||
int rc;
|
||||
char txtbuf[SLAP_TEXT_BUFLEN];
|
||||
size_t textlen = sizeof txtbuf;
|
||||
Entry *e;
|
||||
Operation *new_op = op->o_tmpcalloc( 1, sizeof(OperationBuffer), op->o_tmpmemctx );
|
||||
*new_op = *op;
|
||||
new_op->o_hdr = &((OperationBuffer *) new_op)->ob_hdr;
|
||||
*(new_op->o_hdr) = *(op->o_hdr);
|
||||
new_op->o_controls = ((OperationBuffer *) new_op)->ob_controls;
|
||||
new_op->o_callback = op->o_callback;
|
||||
new_op->o_ber = NULL;
|
||||
new_op->o_bd = op->o_bd->bd_self;
|
||||
|
||||
ber_dupbv_x( &new_op->o_req_dn, &op->o_req_dn, op->o_tmpmemctx );
|
||||
ber_dupbv_x( &new_op->o_req_ndn, &op->o_req_ndn, op->o_tmpmemctx );
|
||||
op->o_callback = NULL;
|
||||
|
||||
if (op->o_ndn.bv_len > 0) {
|
||||
ber_dupbv_x( &new_op->o_ndn, &op->o_ndn, op->o_tmpmemctx );
|
||||
}
|
||||
if (op->o_dn.bv_len > 0) {
|
||||
ber_dupbv_x( &new_op->o_dn, &op->o_dn, op->o_tmpmemctx );
|
||||
}
|
||||
|
||||
new_op->o_ctrls = asyncmeta_copy_controls(op);
|
||||
switch (op->o_tag) {
|
||||
case LDAP_REQ_SEARCH:
|
||||
{
|
||||
AttributeName *at_names;
|
||||
int i;
|
||||
for (i=0; op->ors_attrs && !BER_BVISNULL( &op->ors_attrs[i].an_name ); i++);
|
||||
if (i > 0) {
|
||||
at_names = op->o_tmpcalloc( i+1, sizeof( AttributeName ), op->o_tmpmemctx );
|
||||
at_names[i].an_name.bv_len = 0;
|
||||
i--;
|
||||
for (i; i >= 0; i--) {
|
||||
at_names[i] = op->ors_attrs[i];
|
||||
ber_dupbv_x( &at_names[i].an_name, &op->ors_attrs[i].an_name, op->o_tmpmemctx );
|
||||
}
|
||||
} else {
|
||||
at_names = NULL;
|
||||
}
|
||||
ber_dupbv_x( &new_op->ors_filterstr, &op->ors_filterstr, op->o_tmpmemctx );
|
||||
new_op->ors_filter = filter_dup( op->ors_filter, op->o_tmpmemctx );
|
||||
new_op->ors_attrs = at_names;
|
||||
}
|
||||
break;
|
||||
case LDAP_REQ_ADD:
|
||||
{
|
||||
slap_entry2mods(op->ora_e, &new_op->ora_modlist, &text, txtbuf, textlen);
|
||||
e = entry_alloc();
|
||||
new_op->ora_e = e;
|
||||
ber_dupbv_x( &e->e_name, &op->o_req_dn, op->o_tmpmemctx );
|
||||
ber_dupbv_x( &e->e_nname, &op->o_req_ndn, op->o_tmpmemctx );
|
||||
rc = slap_mods2entry( new_op->ora_modlist, &new_op->ora_e, 1, 0, &text, txtbuf, textlen);
|
||||
}
|
||||
break;
|
||||
case LDAP_REQ_MODIFY:
|
||||
{
|
||||
new_op->orm_modlist = asyncmeta_copy_modlist(op, op->orm_modlist);
|
||||
}
|
||||
break;
|
||||
case LDAP_REQ_COMPARE:
|
||||
new_op->orc_ava = (AttributeAssertion *)ch_calloc( 1, sizeof( AttributeAssertion ));
|
||||
*new_op->orc_ava = *op->orc_ava;
|
||||
if ( !BER_BVISNULL( &op->orc_ava->aa_value ) ) {
|
||||
ber_dupbv_x( &new_op->orc_ava->aa_value, &op->orc_ava->aa_value, op->o_tmpmemctx);
|
||||
}
|
||||
break;
|
||||
case LDAP_REQ_MODRDN:
|
||||
|
||||
if (op->orr_newrdn.bv_len > 0) {
|
||||
ber_dupbv_x( &new_op->orr_newrdn, &op->orr_newrdn, op->o_tmpmemctx );
|
||||
}
|
||||
if (op->orr_nnewrdn.bv_len > 0) {
|
||||
ber_dupbv_x( &new_op->orr_nnewrdn, &op->orr_nnewrdn, op->o_tmpmemctx );
|
||||
}
|
||||
if (op->orr_newSup != NULL) {
|
||||
new_op->orr_newSup = op->o_tmpalloc( sizeof( struct berval ), op->o_tmpmemctx );
|
||||
new_op->orr_newSup->bv_len = 0;
|
||||
if (op->orr_newSup->bv_len > 0) {
|
||||
ber_dupbv_x( new_op->orr_newSup, op->orr_newSup, op->o_tmpmemctx );
|
||||
}
|
||||
}
|
||||
|
||||
if (op->orr_nnewSup != NULL) {
|
||||
new_op->orr_nnewSup = op->o_tmpalloc( sizeof( struct berval ), op->o_tmpmemctx );
|
||||
new_op->orr_nnewSup->bv_len = 0;
|
||||
if (op->orr_nnewSup->bv_len > 0) {
|
||||
ber_dupbv_x( new_op->orr_nnewSup, op->orr_nnewSup, op->o_tmpmemctx );
|
||||
}
|
||||
}
|
||||
new_op->orr_modlist = asyncmeta_copy_modlist(op, op->orr_modlist);
|
||||
break;
|
||||
case LDAP_REQ_DELETE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return new_op;
|
||||
}
|
||||
|
||||
|
||||
typedef struct listptr {
|
||||
void *reserved;
|
||||
struct listptr *next;
|
||||
|
|
@ -223,80 +47,73 @@ typedef struct listhead {
|
|||
int cnt;
|
||||
} listhead;
|
||||
|
||||
static void *asyncmeta_memctx_destroy(void *key, void *data)
|
||||
{
|
||||
listhead *lh = data;
|
||||
listptr *lp;
|
||||
while (lp = lh->list) {
|
||||
lh->list = lp->next;
|
||||
slap_sl_mem_destroy((void *)1, lp);
|
||||
}
|
||||
ch_free(lh);
|
||||
}
|
||||
|
||||
#ifndef LH_MAX
|
||||
#define LH_MAX 16
|
||||
#endif
|
||||
|
||||
static void *asyncmeta_memctx_get(void *threadctx)
|
||||
{
|
||||
listhead *lh = NULL;
|
||||
listptr *lp = NULL;
|
||||
ldap_pvt_thread_pool_getkey(threadctx, asyncmeta_memctx_get, &lh, NULL);
|
||||
if (!lh) {
|
||||
lh = ch_malloc(sizeof(listhead));
|
||||
lh->cnt = 0;
|
||||
lh->list = NULL;
|
||||
ldap_pvt_thread_pool_setkey(threadctx, asyncmeta_memctx_get, lh, asyncmeta_memctx_destroy, NULL, NULL);
|
||||
}
|
||||
if (lh->list) {
|
||||
lp = lh->list;
|
||||
lh->list = lp->next;
|
||||
lh->cnt--;
|
||||
slap_sl_mem_setctx(threadctx, lp);
|
||||
}
|
||||
return slap_sl_mem_create(SLAP_SLAB_SIZE, SLAP_SLAB_STACK, threadctx, 1);
|
||||
}
|
||||
|
||||
static void asyncmeta_memctx_put(void *threadctx, void *memctx)
|
||||
{
|
||||
listhead *lh = NULL;
|
||||
ldap_pvt_thread_pool_getkey(threadctx, asyncmeta_memctx_get, &lh, NULL);
|
||||
if (!lh) {
|
||||
lh = ch_malloc(sizeof(listhead));
|
||||
lh->cnt = 0;
|
||||
lh->list = NULL;
|
||||
ldap_pvt_thread_pool_setkey(threadctx, asyncmeta_memctx_get, lh, asyncmeta_memctx_destroy, NULL, NULL);
|
||||
}
|
||||
if (lh->cnt < LH_MAX) {
|
||||
listptr *lp = memctx;
|
||||
lp->next = lh->list;
|
||||
lh->list = lp;
|
||||
lh->cnt++;
|
||||
} else {
|
||||
slap_sl_mem_destroy((void *)1, memctx);
|
||||
}
|
||||
slap_sl_mem_setctx(threadctx, NULL);
|
||||
slap_sl_mem_destroy((void *)1, memctx);
|
||||
}
|
||||
|
||||
int asyncmeta_new_bm_context(Operation *op, SlapReply *rs, bm_context_t **new_bc, int ntargets)
|
||||
void asyncmeta_memctx_toggle(void *thrctx)
|
||||
{
|
||||
asyncmeta_memctx_get(thrctx);
|
||||
}
|
||||
|
||||
int asyncmeta_new_bm_context(Operation *op,
|
||||
SlapReply *rs,
|
||||
bm_context_t **new_bc,
|
||||
int ntargets,
|
||||
a_metainfo_t *mi)
|
||||
{
|
||||
void *oldctx = op->o_tmpmemctx;
|
||||
int i;
|
||||
/* prevent old memctx from being destroyed */
|
||||
slap_sl_mem_setctx(op->o_threadctx, NULL);
|
||||
/* create new memctx */
|
||||
op->o_tmpmemctx = asyncmeta_memctx_get( op->o_threadctx );
|
||||
*new_bc = op->o_tmpcalloc( 1, sizeof( bm_context_t ), op->o_tmpmemctx );
|
||||
|
||||
(*new_bc)->op = asyncmeta_copy_op(op);
|
||||
(*new_bc)->op = op;
|
||||
(*new_bc)->copy_op = *op;
|
||||
(*new_bc)->candidates = op->o_tmpcalloc(ntargets, sizeof(SlapReply),op->o_tmpmemctx);
|
||||
(*new_bc)->msgids = op->o_tmpcalloc(ntargets, sizeof(int),op->o_tmpmemctx);
|
||||
(*new_bc)->nretries = op->o_tmpcalloc(ntargets, sizeof(int),op->o_tmpmemctx);
|
||||
(*new_bc)->c_peer_name = op->o_conn->c_peer_name;
|
||||
(*new_bc)->is_root = be_isroot( op );
|
||||
|
||||
switch(op->o_tag) {
|
||||
case LDAP_REQ_COMPARE:
|
||||
{
|
||||
AttributeAssertion *ava = op->o_tmpcalloc( 1, sizeof(AttributeAssertion), op->o_tmpmemctx );
|
||||
*ava = *op->orc_ava;
|
||||
op->orc_ava = ava;
|
||||
}
|
||||
break;
|
||||
case LDAP_REQ_MODRDN:
|
||||
if (op->orr_newSup != NULL) {
|
||||
struct berval *bv = op->o_tmpalloc( sizeof( struct berval ), op->o_tmpmemctx );
|
||||
*bv = *op->orr_newSup;
|
||||
op->orr_newSup = bv;
|
||||
}
|
||||
|
||||
if (op->orr_nnewSup != NULL) {
|
||||
struct berval *bv = op->o_tmpalloc( sizeof( struct berval ), op->o_tmpmemctx );
|
||||
*bv = *op->orr_nnewSup;
|
||||
op->orr_nnewSup = bv;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < ntargets; i++) {
|
||||
(*new_bc)->msgids[i] = META_MSGID_UNDEFINED;
|
||||
}
|
||||
/* restore original memctx */
|
||||
slap_sl_mem_setctx(op->o_threadctx, oldctx);
|
||||
op->o_tmpmemctx = oldctx;
|
||||
for (i = 0; i < ntargets; i++) {
|
||||
(*new_bc)->nretries[i] = mi->mi_targets[i]->mt_nretries;
|
||||
}
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -305,15 +122,6 @@ void asyncmeta_free_op(Operation *op)
|
|||
assert (op != NULL);
|
||||
switch (op->o_tag) {
|
||||
case LDAP_REQ_SEARCH:
|
||||
if (op->ors_filterstr.bv_len != 0) {
|
||||
free(op->ors_filterstr.bv_val);
|
||||
}
|
||||
if (op->ors_filter) {
|
||||
filter_free(op->ors_filter);
|
||||
}
|
||||
if (op->ors_attrs) {
|
||||
free(op->ors_attrs);
|
||||
}
|
||||
break;
|
||||
case LDAP_REQ_ADD:
|
||||
if ( op->ora_modlist != NULL ) {
|
||||
|
|
@ -331,36 +139,11 @@ void asyncmeta_free_op(Operation *op)
|
|||
}
|
||||
break;
|
||||
case LDAP_REQ_MODRDN:
|
||||
if (op->orr_newrdn.bv_len > 0) {
|
||||
free(op->orr_newrdn.bv_val);
|
||||
}
|
||||
if (op->orr_nnewrdn.bv_len > 0) {
|
||||
free(op->orr_nnewrdn.bv_val);
|
||||
}
|
||||
|
||||
if (op->orr_nnewSup != NULL ) {
|
||||
if (op->orr_nnewSup->bv_len > 0) {
|
||||
free(op->orr_nnewSup->bv_val);
|
||||
}
|
||||
free (op->orr_nnewSup);
|
||||
}
|
||||
|
||||
if (op->orr_newSup != NULL ) {
|
||||
if (op->orr_newSup->bv_len > 0) {
|
||||
free(op->orr_newSup->bv_val);
|
||||
}
|
||||
free (op->orr_newSup);
|
||||
}
|
||||
|
||||
if ( op->orr_modlist != NULL ) {
|
||||
slap_mods_free(op->orr_modlist, 1 );
|
||||
}
|
||||
break;
|
||||
case LDAP_REQ_COMPARE:
|
||||
if ( !BER_BVISNULL( &op->orc_ava->aa_value ) ) {
|
||||
free(op->orc_ava->aa_value.bv_val);
|
||||
}
|
||||
free(op->orc_ava);
|
||||
break;
|
||||
case LDAP_REQ_DELETE:
|
||||
break;
|
||||
|
|
@ -368,22 +151,8 @@ void asyncmeta_free_op(Operation *op)
|
|||
Debug( LDAP_DEBUG_TRACE, "==> asyncmeta_free_op : other message type" );
|
||||
}
|
||||
|
||||
if (op->o_ctrls != NULL) {
|
||||
asyncmeta_free_op_controls(op);
|
||||
}
|
||||
if (op->o_ndn.bv_len > 0) {
|
||||
free(op->o_ndn.bv_val);
|
||||
}
|
||||
if (op->o_dn.bv_len > 0) {
|
||||
free( op->o_dn.bv_val );
|
||||
}
|
||||
if (op->o_req_dn.bv_len > 0) {
|
||||
free(op->o_req_dn.bv_val);
|
||||
}
|
||||
if (op->o_req_dn.bv_len > 0) {
|
||||
free(op->o_req_ndn.bv_val);
|
||||
}
|
||||
free(op);
|
||||
connection_op_finish( op );
|
||||
slap_op_free( op, op->o_threadctx );
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -393,96 +162,26 @@ void asyncmeta_clear_bm_context(bm_context_t *bc)
|
|||
{
|
||||
|
||||
Operation *op = bc->op;
|
||||
#if 0
|
||||
bm_candidates_t *cl;
|
||||
a_metainfo_t *mi;
|
||||
int i = 0;
|
||||
if (bmc == NULL) {
|
||||
void *thrctx, *memctx;
|
||||
int i;
|
||||
|
||||
if ( bc->bc_mc && bc->bc_mc->mc_info ) {
|
||||
for (i = 0; i < bc->bc_mc->mc_info->mi_ntargets; i++) {
|
||||
if (bc->candidates[ i ].sr_text != NULL) {
|
||||
ch_free( (char *)bc->candidates[ i ].sr_text );
|
||||
bc->candidates[ i ].sr_text = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (op->o_conn->c_conn_idx == -1)
|
||||
return;
|
||||
} else if (bmc->cl == NULL) {
|
||||
free(bmc);
|
||||
return;
|
||||
}
|
||||
cl = bmc->cl;
|
||||
op = cl->op;
|
||||
switch (op->o_tag) {
|
||||
case LDAP_REQ_SEARCH:
|
||||
break;
|
||||
case LDAP_REQ_ADD:
|
||||
if ( (bmc->mdn.bv_len != 0) &&
|
||||
(bmc->mdn.bv_val != op->o_req_dn.bv_val) ) {
|
||||
free( bmc->mdn.bv_val );
|
||||
}
|
||||
|
||||
if (bmc->data.add_d.attrs != NULL ) {
|
||||
while (bmc->data.add_d.attrs[i] != NULL) {
|
||||
free( bmc->data.add_d.attrs[i]->mod_bvalues );
|
||||
free( bmc->data.add_d.attrs[i] );
|
||||
i++;
|
||||
}
|
||||
free( bmc->data.add_d.attrs );
|
||||
}
|
||||
break;
|
||||
case LDAP_REQ_MODIFY:
|
||||
if ( bmc->mdn.bv_val != op->o_req_dn.bv_val ) {
|
||||
free( bmc->mdn.bv_val );
|
||||
}
|
||||
if ( bmc->data.mod_d.modv != NULL ) {
|
||||
for ( i = 0; bmc->data.mod_d.modv[ i ]; i++ ) {
|
||||
free( bmc->data.mod_d.modv[ i ]->mod_bvalues );
|
||||
}
|
||||
}
|
||||
free( bmc->data.mod_d.mods );
|
||||
free( bmc->data.mod_d.modv );
|
||||
|
||||
break;
|
||||
case LDAP_REQ_MODRDN:
|
||||
if ( bmc->mdn.bv_val != op->o_req_dn.bv_val ) {
|
||||
free( bmc->mdn.bv_val );
|
||||
}
|
||||
|
||||
if ( bmc->data.modrdn_d.newSuperior.bv_len != 0 &&
|
||||
bmc->data.modrdn_d.newSuperior.bv_val != op->orr_newSup->bv_val )
|
||||
{
|
||||
free( bmc->data.modrdn_d.newSuperior.bv_val );
|
||||
|
||||
}
|
||||
|
||||
if ( bmc->data.modrdn_d.newrdn.bv_len != 0 &&
|
||||
bmc->data.modrdn_d.newrdn.bv_val != op->orr_newrdn.bv_val )
|
||||
{
|
||||
free( bmc->data.modrdn_d.newrdn.bv_val );
|
||||
|
||||
}
|
||||
break;
|
||||
case LDAP_REQ_COMPARE:
|
||||
if ( bmc->mdn.bv_val != op->o_req_dn.bv_val ) {
|
||||
free( bmc->mdn.bv_val );
|
||||
}
|
||||
if ( op->orc_ava->aa_value.bv_val != bmc->data.comp_d.mapped_value.bv_val ) {
|
||||
free( bmc->data.comp_d.mapped_value.bv_val );
|
||||
}
|
||||
break;
|
||||
case LDAP_REQ_DELETE:
|
||||
if ( bmc->mdn.bv_val != op->o_req_dn.bv_val ) {
|
||||
free( bmc->mdn.bv_val );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Debug( LDAP_DEBUG_TRACE, "==> asyncmeta_clear_bm_context: other message type" );
|
||||
}
|
||||
if (bmc->dc != NULL) {
|
||||
free (bmc->dc);
|
||||
}
|
||||
free(bmc);
|
||||
|
||||
if (clear_cl > 0) {
|
||||
asyncmeta_free_candidate_list(cl, lock);
|
||||
Debug( LDAP_DEBUG_TRACE, "==> asyncmeta_clear_bm_context: free_cl_list\n" );
|
||||
}
|
||||
#else
|
||||
asyncmeta_memctx_put(op->o_threadctx, op->o_tmpmemctx);
|
||||
#endif
|
||||
memctx = op->o_tmpmemctx;
|
||||
thrctx = op->o_threadctx;
|
||||
while (op->o_bd == bc->copy_op.o_bd)
|
||||
ldap_pvt_thread_yield();
|
||||
asyncmeta_free_op(op);
|
||||
asyncmeta_memctx_put(thrctx, memctx);
|
||||
}
|
||||
|
||||
int asyncmeta_add_message_queue(a_metaconn_t *mc, bm_context_t *bc)
|
||||
|
|
@ -493,61 +192,55 @@ int asyncmeta_add_message_queue(a_metaconn_t *mc, bm_context_t *bc)
|
|||
Debug( LDAP_DEBUG_TRACE, "add_message_queue: mc %p, pending_ops %d, max_pending %d\n",
|
||||
mc, mc->pending_ops, max_pending_ops );
|
||||
|
||||
assert(bc->bc_mc == NULL);
|
||||
if (mc->pending_ops >= max_pending_ops) {
|
||||
return LDAP_BUSY;
|
||||
}
|
||||
bc->bc_mc = mc;
|
||||
|
||||
LDAP_SLIST_INSERT_HEAD( &mc->mc_om_list, bc, bc_next);
|
||||
slap_sl_mem_setctx(bc->op->o_threadctx, NULL);
|
||||
LDAP_STAILQ_INSERT_TAIL( &mc->mc_om_list, bc, bc_next);
|
||||
mc->pending_ops++;
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
asyncmeta_drop_bc(a_metaconn_t *mc, bm_context_t *bc)
|
||||
{
|
||||
bm_context_t *om;
|
||||
int i;
|
||||
LDAP_SLIST_FOREACH( om, &mc->mc_om_list, bc_next ) {
|
||||
LDAP_STAILQ_FOREACH( om, &mc->mc_om_list, bc_next ) {
|
||||
if (om == bc) {
|
||||
for (i = 0; i < mc->mc_info->mi_ntargets; i++)
|
||||
{
|
||||
if (bc->msgids[i] >= 0) {
|
||||
mc->mc_conns[i].msc_pending_ops--;
|
||||
}
|
||||
}
|
||||
LDAP_SLIST_REMOVE(&mc->mc_om_list, om, bm_context_t, bc_next);
|
||||
LDAP_STAILQ_REMOVE(&mc->mc_om_list, om, bm_context_t, bc_next);
|
||||
mc->pending_ops--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(om == bc);
|
||||
assert(bc->bc_mc == mc);
|
||||
}
|
||||
|
||||
|
||||
bm_context_t *
|
||||
asyncmeta_find_message(ber_int_t msgid, a_metaconn_t *mc, int candidate)
|
||||
{
|
||||
bm_context_t *om;
|
||||
LDAP_SLIST_FOREACH( om, &mc->mc_om_list, bc_next ) {
|
||||
if (om->candidates[candidate].sr_msgid == msgid) {
|
||||
LDAP_STAILQ_FOREACH( om, &mc->mc_om_list, bc_next ) {
|
||||
if (om->candidates[candidate].sr_msgid == msgid && !om->bc_invalid) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return om;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bm_context_t *
|
||||
asyncmeta_find_message_by_opmsguid (ber_int_t msgid, a_metaconn_t *mc, int remove)
|
||||
asyncmeta_bc_in_queue(a_metaconn_t *mc, bm_context_t *bc)
|
||||
{
|
||||
bm_context_t *om;
|
||||
LDAP_SLIST_FOREACH( om, &mc->mc_om_list, bc_next ) {
|
||||
if (om->op->o_msgid == msgid) {
|
||||
break;
|
||||
LDAP_STAILQ_FOREACH( om, &mc->mc_om_list, bc_next ) {
|
||||
if (om == bc) {
|
||||
return bc;
|
||||
}
|
||||
}
|
||||
if (remove && om) {
|
||||
LDAP_SLIST_REMOVE(&mc->mc_om_list, om, bm_context_t, bc_next);
|
||||
mc->pending_ops--;
|
||||
}
|
||||
return om;
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -26,21 +26,21 @@
|
|||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "../back-ldap/back-ldap.h"
|
||||
#include "back-asyncmeta.h"
|
||||
#include "../../../libraries/liblber/lber-int.h"
|
||||
#include "../../../libraries/libldap/ldap-int.h"
|
||||
#include "../back-ldap/back-ldap.h"
|
||||
#include "back-asyncmeta.h"
|
||||
|
||||
meta_search_candidate_t
|
||||
asyncmeta_back_modify_start(Operation *op,
|
||||
SlapReply *rs,
|
||||
a_metaconn_t *mc,
|
||||
bm_context_t *bc,
|
||||
int candidate)
|
||||
int candidate,
|
||||
int do_lock)
|
||||
{
|
||||
int i, isupdate, rc = 0, nretries = 1;
|
||||
int i, isupdate, rc = 0;
|
||||
a_dncookie dc;
|
||||
a_metainfo_t *mi = mc->mc_info;
|
||||
a_metatarget_t *mt = mi->mi_targets[ candidate ];
|
||||
|
|
@ -48,7 +48,6 @@ asyncmeta_back_modify_start(Operation *op,
|
|||
LDAPMod *mods = NULL;
|
||||
struct berval mdn;
|
||||
Modifications *ml;
|
||||
struct berval mapped;
|
||||
meta_search_candidate_t retcode = META_SEARCH_CANDIDATE;
|
||||
BerElement *ber = NULL;
|
||||
a_metasingleconn_t *msc = &mc->mc_conns[ candidate ];
|
||||
|
|
@ -59,122 +58,55 @@ asyncmeta_back_modify_start(Operation *op,
|
|||
/*
|
||||
* Rewrite the modify dn, if needed
|
||||
*/
|
||||
dc.op = op;
|
||||
dc.target = mt;
|
||||
dc.conn = op->o_conn;
|
||||
dc.rs = rs;
|
||||
dc.ctx = "modifyDN";
|
||||
dc.memctx = op->o_tmpmemctx;
|
||||
dc.to_from = MASSAGE_REQ;
|
||||
|
||||
switch ( asyncmeta_dn_massage( &dc, &op->o_req_dn, &mdn ) )
|
||||
{
|
||||
case LDAP_SUCCESS:
|
||||
break;
|
||||
case LDAP_UNWILLING_TO_PERFORM:
|
||||
rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
|
||||
rs->sr_text = "Operation not allowed";
|
||||
retcode = META_SEARCH_ERR;
|
||||
goto doreturn;
|
||||
default:
|
||||
rs->sr_err = LDAP_NO_SUCH_OBJECT;
|
||||
retcode = META_SEARCH_NOT_CANDIDATE;
|
||||
goto doreturn;
|
||||
}
|
||||
asyncmeta_dn_massage( &dc, &op->o_req_dn, &mdn );
|
||||
|
||||
for ( i = 0, ml = op->orm_modlist; ml; i++ ,ml = ml->sml_next )
|
||||
;
|
||||
if (i > 0) {
|
||||
mods = op->o_tmpalloc( sizeof( LDAPMod )*i, op->o_tmpmemctx );
|
||||
}
|
||||
|
||||
mods = ch_malloc( sizeof( LDAPMod )*i );
|
||||
if ( mods == NULL ) {
|
||||
rs->sr_err = LDAP_OTHER;
|
||||
retcode = META_SEARCH_ERR;
|
||||
goto doreturn;
|
||||
}
|
||||
modv = ( LDAPMod ** )ch_malloc( ( i + 1 )*sizeof( LDAPMod * ) );
|
||||
modv = ( LDAPMod ** )op->o_tmpalloc( ( i + 1 )*sizeof( LDAPMod * ), op->o_tmpmemctx );
|
||||
if ( modv == NULL ) {
|
||||
rs->sr_err = LDAP_OTHER;
|
||||
retcode = META_SEARCH_ERR;
|
||||
goto doreturn;
|
||||
}
|
||||
|
||||
dc.ctx = "modifyAttrDN";
|
||||
isupdate = be_shadow_update( op );
|
||||
for ( i = 0, ml = op->orm_modlist; ml; ml = ml->sml_next ) {
|
||||
int j, is_oc = 0;
|
||||
int j;
|
||||
|
||||
if ( !isupdate && !get_relax( op ) && ml->sml_desc->ad_type->sat_no_user_mod )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ml->sml_desc == slap_schema.si_ad_objectClass
|
||||
|| ml->sml_desc == slap_schema.si_ad_structuralObjectClass )
|
||||
{
|
||||
is_oc = 1;
|
||||
mapped = ml->sml_desc->ad_cname;
|
||||
|
||||
} else {
|
||||
asyncmeta_map( &mt->mt_rwmap.rwm_at,
|
||||
&ml->sml_desc->ad_cname, &mapped,
|
||||
BACKLDAP_MAP );
|
||||
if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
modv[ i ] = &mods[ i ];
|
||||
mods[ i ].mod_op = ml->sml_op | LDAP_MOD_BVALUES;
|
||||
mods[ i ].mod_type = mapped.bv_val;
|
||||
mods[ i ].mod_type = ml->sml_desc->ad_cname.bv_val;
|
||||
|
||||
/*
|
||||
* FIXME: dn-valued attrs should be rewritten
|
||||
* to allow their use in ACLs at the back-ldap
|
||||
* level.
|
||||
*/
|
||||
if ( ml->sml_values != NULL ) {
|
||||
if ( is_oc ) {
|
||||
for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); j++ )
|
||||
;
|
||||
mods[ i ].mod_bvalues =
|
||||
(struct berval **)ch_malloc( ( j + 1 ) *
|
||||
sizeof( struct berval * ) );
|
||||
for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); ) {
|
||||
struct ldapmapping *mapping;
|
||||
|
||||
asyncmeta_mapping( &mt->mt_rwmap.rwm_oc,
|
||||
&ml->sml_values[ j ], &mapping, BACKLDAP_MAP );
|
||||
|
||||
if ( mapping == NULL ) {
|
||||
if ( mt->mt_rwmap.rwm_oc.drop_missing ) {
|
||||
continue;
|
||||
}
|
||||
mods[ i ].mod_bvalues[ j ] = &ml->sml_values[ j ];
|
||||
|
||||
} else {
|
||||
mods[ i ].mod_bvalues[ j ] = &mapping->dst;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
mods[ i ].mod_bvalues[ j ] = NULL;
|
||||
|
||||
} else {
|
||||
if ( ml->sml_desc->ad_type->sat_syntax ==
|
||||
slap_schema.si_syn_distinguishedName )
|
||||
{
|
||||
( void )asyncmeta_dnattr_rewrite( &dc, ml->sml_values );
|
||||
if ( ml->sml_values == NULL ) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); j++ )
|
||||
;
|
||||
mods[ i ].mod_bvalues =
|
||||
(struct berval **)ch_malloc( ( j + 1 ) *
|
||||
sizeof( struct berval * ) );
|
||||
for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); j++ ) {
|
||||
mods[ i ].mod_bvalues[ j ] = &ml->sml_values[ j ];
|
||||
}
|
||||
mods[ i ].mod_bvalues[ j ] = NULL;
|
||||
j = ml->sml_numvals;
|
||||
mods[ i ].mod_bvalues =(struct berval **)op->o_tmpalloc( ( j + 1 ) *sizeof( struct berval * ), op->o_tmpmemctx );
|
||||
for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); j++ ) {
|
||||
mods[ i ].mod_bvalues[ j ] = op->o_tmpalloc(sizeof( struct berval ), op->o_tmpmemctx );
|
||||
if ( ml->sml_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
|
||||
asyncmeta_dn_massage( &dc, &ml->sml_values[ j ], mods[ i ].mod_bvalues[ j ] );
|
||||
else
|
||||
*mods[ i ].mod_bvalues[ j ] = ml->sml_values[ j ];
|
||||
}
|
||||
mods[ i ].mod_bvalues[ j ] = NULL;
|
||||
|
||||
} else {
|
||||
mods[ i ].mod_bvalues = NULL;
|
||||
|
|
@ -184,62 +116,113 @@ asyncmeta_back_modify_start(Operation *op,
|
|||
}
|
||||
modv[ i ] = 0;
|
||||
|
||||
retry:;
|
||||
asyncmeta_set_msc_time(msc);
|
||||
ctrls = op->o_ctrls;
|
||||
if ( asyncmeta_controls_add( op, rs, mc, candidate, &ctrls ) != LDAP_SUCCESS )
|
||||
if ( asyncmeta_controls_add( op, rs, mc, candidate, bc->is_root, &ctrls) != LDAP_SUCCESS )
|
||||
{
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
retcode = META_SEARCH_ERR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* someone reset the connection */
|
||||
if (!( LDAP_BACK_CONN_ISBOUND( msc )
|
||||
|| LDAP_BACK_CONN_ISANON( msc )) || msc->msc_ld == NULL ) {
|
||||
Debug( asyncmeta_debug , "msc %p not initialized at %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
goto error_unavailable;
|
||||
}
|
||||
|
||||
ber = ldap_build_modify_req( msc->msc_ld, mdn.bv_val, modv, ctrls, NULL, &msgid);
|
||||
|
||||
if (!ber) {
|
||||
Debug( asyncmeta_debug, "%s asyncmeta_back_modify_start: Operation encoding failed with errno %d\n",
|
||||
op->o_log_prefix, msc->msc_ld->ld_errno );
|
||||
rs->sr_err = LDAP_OPERATIONS_ERROR;
|
||||
rs->sr_text = "Failed to encode proxied request";
|
||||
retcode = META_SEARCH_ERR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (ber) {
|
||||
candidates[ candidate ].sr_msgid = msgid;
|
||||
rc = ldap_send_initial_request( msc->msc_ld, LDAP_REQ_MODIFY,
|
||||
mdn.bv_val, ber, msgid );
|
||||
if (rc == msgid)
|
||||
rc = LDAP_SUCCESS;
|
||||
else
|
||||
rc = LDAP_SERVER_DOWN;
|
||||
struct timeval tv = {0, mt->mt_network_timeout*1000};
|
||||
ber_socket_t s;
|
||||
if (!( LDAP_BACK_CONN_ISBOUND( msc )
|
||||
|| LDAP_BACK_CONN_ISANON( msc )) || msc->msc_ld == NULL ) {
|
||||
Debug( asyncmeta_debug, "msc %p not initialized at %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
goto error_unavailable;
|
||||
}
|
||||
|
||||
ldap_get_option( msc->msc_ld, LDAP_OPT_DESC, &s );
|
||||
if (s < 0) {
|
||||
Debug( asyncmeta_debug, "msc %p not initialized at %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
goto error_unavailable;
|
||||
}
|
||||
|
||||
rc = ldap_int_poll( msc->msc_ld, s, &tv, 1);
|
||||
if (rc < 0) {
|
||||
Debug( asyncmeta_debug, "msc %p not writable within network timeout %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
if ((msc->msc_result_time + META_BACK_RESULT_INTERVAL) < slap_get_time()) {
|
||||
rc = LDAP_SERVER_DOWN;
|
||||
} else {
|
||||
goto error_unavailable;
|
||||
}
|
||||
} else {
|
||||
candidates[ candidate ].sr_msgid = msgid;
|
||||
rc = ldap_send_initial_request( msc->msc_ld, LDAP_REQ_MODIFY,
|
||||
mdn.bv_val, ber, msgid );
|
||||
if (rc == msgid)
|
||||
rc = LDAP_SUCCESS;
|
||||
else
|
||||
rc = LDAP_SERVER_DOWN;
|
||||
ber = NULL;
|
||||
}
|
||||
|
||||
switch ( rc ) {
|
||||
case LDAP_SUCCESS:
|
||||
retcode = META_SEARCH_CANDIDATE;
|
||||
asyncmeta_set_msc_time(msc);
|
||||
break;
|
||||
goto done;
|
||||
|
||||
case LDAP_SERVER_DOWN:
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_clear_one_msc(NULL, mc, candidate);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
if ( nretries && asyncmeta_retry( op, rs, &mc, candidate, LDAP_BACK_DONTSEND ) ) {
|
||||
nretries = 0;
|
||||
/* if the identity changed, there might be need to re-authz */
|
||||
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
||||
goto retry;
|
||||
/* do not lock if called from asyncmeta_handle_bind_result. Also do not reset the connection */
|
||||
if (do_lock > 0) {
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_reset_msc(NULL, mc, candidate, 0, __FUNCTION__);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
}
|
||||
|
||||
/* fall though*/
|
||||
default:
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
retcode = META_SEARCH_ERR;
|
||||
Debug( asyncmeta_debug, "msc %p ldap_send_initial_request failed. %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
goto error_unavailable;
|
||||
}
|
||||
}
|
||||
|
||||
error_unavailable:
|
||||
if (ber)
|
||||
ber_free(ber, 1);
|
||||
switch (bc->nretries[candidate]) {
|
||||
case -1: /* nretries = forever */
|
||||
ldap_pvt_thread_yield();
|
||||
retcode = META_SEARCH_NEED_BIND;
|
||||
break;
|
||||
case 0: /* no retries left */
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
rs->sr_err = LDAP_UNAVAILABLE;
|
||||
rs->sr_text = "Unable to send modify request to target";
|
||||
retcode = META_SEARCH_ERR;
|
||||
break;
|
||||
default: /* more retries left - try to rebind and go again */
|
||||
retcode = META_SEARCH_NEED_BIND;
|
||||
bc->nretries[candidate]--;
|
||||
ldap_pvt_thread_yield();
|
||||
break;
|
||||
}
|
||||
done:
|
||||
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
||||
|
||||
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
|
||||
free( mdn.bv_val );
|
||||
BER_BVZERO( &mdn );
|
||||
op->o_tmpfree( mdn.bv_val, op->o_tmpmemctx );
|
||||
}
|
||||
if ( modv != NULL ) {
|
||||
for ( i = 0; modv[ i ]; i++ ) {
|
||||
free( modv[ i ]->mod_bvalues );
|
||||
}
|
||||
}
|
||||
free( mods );
|
||||
free( modv );
|
||||
|
||||
doreturn:;
|
||||
Debug( LDAP_DEBUG_TRACE, "%s <<< asyncmeta_back_modify_start[%p]=%d\n", op->o_log_prefix, msc, candidates[candidate].sr_msgid );
|
||||
|
|
@ -253,26 +236,31 @@ asyncmeta_back_modify( Operation *op, SlapReply *rs )
|
|||
a_metatarget_t *mt;
|
||||
a_metaconn_t *mc;
|
||||
int rc, candidate = -1;
|
||||
OperationBuffer opbuf;
|
||||
void *thrctx = op->o_threadctx;
|
||||
bm_context_t *bc;
|
||||
SlapReply *candidates;
|
||||
slap_callback *cb = op->o_callback;
|
||||
time_t current_time = slap_get_time();
|
||||
int max_pending_ops = (mi->mi_max_pending_ops == 0) ? META_BACK_CFG_MAX_PENDING_OPS : mi->mi_max_pending_ops;
|
||||
|
||||
Debug(LDAP_DEBUG_ARGS, "==> asyncmeta_back_modify: %s\n",
|
||||
op->o_req_dn.bv_val );
|
||||
|
||||
asyncmeta_new_bm_context(op, rs, &bc, mi->mi_ntargets );
|
||||
if (current_time > op->o_time) {
|
||||
Debug(asyncmeta_debug, "==> asyncmeta_back_modify[%s]: o_time:[%ld], current time: [%ld]\n",
|
||||
op->o_log_prefix, op->o_time, current_time );
|
||||
}
|
||||
|
||||
asyncmeta_new_bm_context(op, rs, &bc, mi->mi_ntargets, mi );
|
||||
if (bc == NULL) {
|
||||
rs->sr_err = LDAP_OTHER;
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
send_ldap_result(op, rs);
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
candidates = bc->candidates;
|
||||
mc = asyncmeta_getconn( op, rs, candidates, &candidate, LDAP_BACK_DONTSEND, 0);
|
||||
if ( !mc || rs->sr_err != LDAP_SUCCESS) {
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
send_ldap_result(op, rs);
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
|
|
@ -281,16 +269,38 @@ asyncmeta_back_modify( Operation *op, SlapReply *rs )
|
|||
bc->retrying = LDAP_BACK_RETRYING;
|
||||
bc->sendok = ( LDAP_BACK_SENDRESULT | bc->retrying );
|
||||
bc->stoptime = op->o_time + bc->timeout;
|
||||
bc->bc_active = 1;
|
||||
|
||||
if (mc->pending_ops >= max_pending_ops) {
|
||||
rs->sr_err = LDAP_BUSY;
|
||||
rs->sr_text = "Maximum pending ops limit exceeded";
|
||||
send_ldap_result(op, rs);
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
rc = asyncmeta_add_message_queue(mc, bc);
|
||||
mc->mc_conns[candidate].msc_active++;
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
|
||||
if (rc != LDAP_SUCCESS) {
|
||||
rs->sr_err = LDAP_BUSY;
|
||||
rs->sr_text = "Maximum pending ops limit exceeded";
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
send_ldap_result(op, rs);
|
||||
ldap_pvt_thread_mutex_lock(&mc->mc_om_mutex);
|
||||
mc->mc_conns[candidate].msc_active--;
|
||||
ldap_pvt_thread_mutex_unlock(&mc->mc_om_mutex);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
retry:
|
||||
if (bc->timeout && bc->stoptime < slap_get_time()) {
|
||||
int timeout_err;
|
||||
timeout_err = op->o_protocol >= LDAP_VERSION3 ?
|
||||
LDAP_ADMINLIMIT_EXCEEDED : LDAP_OTHER;
|
||||
rs->sr_err = timeout_err;
|
||||
rs->sr_text = "Operation timed out before it was sent to target";
|
||||
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
|
@ -300,70 +310,49 @@ asyncmeta_back_modify( Operation *op, SlapReply *rs )
|
|||
case META_SEARCH_CANDIDATE:
|
||||
/* target is already bound, just send the request */
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_modify: "
|
||||
"cnd=\"%ld\"\n", op->o_log_prefix, candidate );
|
||||
"cnd=\"%d\"\n", op->o_log_prefix, candidate );
|
||||
|
||||
rc = asyncmeta_back_modify_start( op, rs, mc, bc, candidate);
|
||||
rc = asyncmeta_back_modify_start( op, rs, mc, bc, candidate, 1);
|
||||
if (rc == META_SEARCH_ERR) {
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_drop_bc(mc, bc);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||
goto finish;
|
||||
|
||||
} else if (rc == META_SEARCH_NEED_BIND) {
|
||||
goto retry;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case META_SEARCH_NOT_CANDIDATE:
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_modify: NOT_CANDIDATE "
|
||||
"cnd=\"%ld\"\n", op->o_log_prefix, candidate );
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_drop_bc(mc, bc);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
"cnd=\"%d\"\n", op->o_log_prefix, candidate );
|
||||
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||
goto finish;
|
||||
|
||||
case META_SEARCH_NEED_BIND:
|
||||
case META_SEARCH_CONNECTING:
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_modify: NEED_BIND "
|
||||
"cnd=\"%ld\" %p\n", op->o_log_prefix, candidate , &mc->mc_conns[candidate]);
|
||||
rc = asyncmeta_dobind_init(op, rs, bc, mc, candidate);
|
||||
if (rc == META_SEARCH_ERR) {
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_drop_bc(mc, bc);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
goto finish;
|
||||
}
|
||||
break;
|
||||
case META_SEARCH_BINDING:
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_modify: BINDING "
|
||||
"cnd=\"%ld\" %p\n", op->o_log_prefix, candidate , &mc->mc_conns[candidate]);
|
||||
"cnd=\"%d\" %p\n", op->o_log_prefix, candidate , &mc->mc_conns[candidate]);
|
||||
/* Todo add the context to the message queue but do not send the request
|
||||
the receiver must send this when we are done binding */
|
||||
/* question - how would do receiver know to which targets??? */
|
||||
break;
|
||||
|
||||
case META_SEARCH_ERR:
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_modify: ERR "
|
||||
"cnd=\"%ldd\"\n", op->o_log_prefix, candidate );
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
candidates[ candidate ].sr_type = REP_RESULT;
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_drop_bc(mc, bc);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
"cnd=\"%d\"\n", op->o_log_prefix, candidate );
|
||||
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||
goto finish;
|
||||
default:
|
||||
assert( 0 );
|
||||
break;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
mc->mc_conns[candidate].msc_active--;
|
||||
asyncmeta_start_one_listener(mc, candidates, bc, candidate);
|
||||
bc->bc_active--;
|
||||
asyncmeta_memctx_toggle(thrctx);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
rs->sr_err = SLAPD_ASYNCOP;
|
||||
|
||||
finish:
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,19 +26,19 @@
|
|||
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "../back-ldap/back-ldap.h"
|
||||
#include "back-asyncmeta.h"
|
||||
#include "../../../libraries/liblber/lber-int.h"
|
||||
#include "../../../libraries/libldap/ldap-int.h"
|
||||
#include "../back-ldap/back-ldap.h"
|
||||
#include "back-asyncmeta.h"
|
||||
|
||||
meta_search_candidate_t
|
||||
asyncmeta_back_modrdn_start(Operation *op,
|
||||
SlapReply *rs,
|
||||
a_metaconn_t *mc,
|
||||
bm_context_t *bc,
|
||||
int candidate)
|
||||
int candidate,
|
||||
int do_lock)
|
||||
{
|
||||
a_dncookie dc;
|
||||
a_metainfo_t *mi = mc->mc_info;
|
||||
|
|
@ -46,7 +46,7 @@ asyncmeta_back_modrdn_start(Operation *op,
|
|||
struct berval mdn = BER_BVNULL,
|
||||
mnewSuperior = BER_BVNULL,
|
||||
newrdn = BER_BVNULL;
|
||||
int rc = 0, nretries = 1;
|
||||
int rc = 0;
|
||||
LDAPControl **ctrls = NULL;
|
||||
meta_search_candidate_t retcode = META_SEARCH_CANDIDATE;
|
||||
BerElement *ber = NULL;
|
||||
|
|
@ -54,9 +54,10 @@ asyncmeta_back_modrdn_start(Operation *op,
|
|||
SlapReply *candidates = bc->candidates;
|
||||
ber_int_t msgid;
|
||||
|
||||
dc.op = op;
|
||||
dc.target = mt;
|
||||
dc.conn = op->o_conn;
|
||||
dc.rs = rs;
|
||||
dc.memctx = op->o_tmpmemctx;
|
||||
dc.to_from = MASSAGE_REQ;
|
||||
|
||||
if ( op->orr_newSup ) {
|
||||
|
||||
|
|
@ -101,23 +102,13 @@ asyncmeta_back_modrdn_start(Operation *op,
|
|||
/*
|
||||
* Rewrite the new superior, if defined and required
|
||||
*/
|
||||
dc.ctx = "newSuperiorDN";
|
||||
if ( asyncmeta_dn_massage( &dc, op->orr_newSup, &mnewSuperior ) ) {
|
||||
rs->sr_err = LDAP_OTHER;
|
||||
retcode = META_SEARCH_ERR;
|
||||
goto done;
|
||||
}
|
||||
asyncmeta_dn_massage( &dc, op->orr_newSup, &mnewSuperior );
|
||||
}
|
||||
|
||||
/*
|
||||
* Rewrite the modrdn dn, if required
|
||||
*/
|
||||
dc.ctx = "modrDN";
|
||||
if ( asyncmeta_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
|
||||
rs->sr_err = LDAP_OTHER;
|
||||
retcode = META_SEARCH_ERR;
|
||||
goto done;
|
||||
}
|
||||
asyncmeta_dn_massage( &dc, &op->o_req_dn, &mdn );
|
||||
|
||||
/* NOTE: we need to copy the newRDN in case it was formed
|
||||
* from a DN by simply changing the length (ITS#5397) */
|
||||
|
|
@ -125,69 +116,125 @@ asyncmeta_back_modrdn_start(Operation *op,
|
|||
if ( newrdn.bv_val[ newrdn.bv_len ] != '\0' ) {
|
||||
ber_dupbv_x( &newrdn, &op->orr_newrdn, op->o_tmpmemctx );
|
||||
}
|
||||
retry:;
|
||||
|
||||
asyncmeta_set_msc_time(msc);
|
||||
ctrls = op->o_ctrls;
|
||||
if ( asyncmeta_controls_add( op, rs, mc, candidate, &ctrls ) != LDAP_SUCCESS )
|
||||
if ( asyncmeta_controls_add( op, rs, mc, candidate, bc->is_root, &ctrls ) != LDAP_SUCCESS )
|
||||
{
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
retcode = META_SEARCH_ERR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* someone might have reset the connection */
|
||||
if (!( LDAP_BACK_CONN_ISBOUND( msc )
|
||||
|| LDAP_BACK_CONN_ISANON( msc )) || msc->msc_ld == NULL ) {
|
||||
Debug( asyncmeta_debug, "msc %p not initialized at %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
goto error_unavailable;
|
||||
}
|
||||
ber = ldap_build_moddn_req( msc->msc_ld, mdn.bv_val, newrdn.bv_val,
|
||||
mnewSuperior.bv_val, op->orr_deleteoldrdn, ctrls, NULL, &msgid);
|
||||
|
||||
if (!ber) {
|
||||
Debug( asyncmeta_debug, "%s asyncmeta_back_modrdn_start: Operation encoding failed with errno %d\n",
|
||||
op->o_log_prefix, msc->msc_ld->ld_errno );
|
||||
rs->sr_err = LDAP_OPERATIONS_ERROR;
|
||||
rs->sr_text = "Failed to encode proxied request";
|
||||
retcode = META_SEARCH_ERR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (ber) {
|
||||
candidates[ candidate ].sr_msgid = msgid;
|
||||
rc = ldap_send_initial_request( msc->msc_ld, LDAP_REQ_MODRDN,
|
||||
mdn.bv_val, ber, msgid );
|
||||
if (rc == msgid)
|
||||
rc = LDAP_SUCCESS;
|
||||
else
|
||||
rc = LDAP_SERVER_DOWN;
|
||||
struct timeval tv = {0, mt->mt_network_timeout*1000};
|
||||
ber_socket_t s;
|
||||
|
||||
if (!( LDAP_BACK_CONN_ISBOUND( msc )
|
||||
|| LDAP_BACK_CONN_ISANON( msc )) || msc->msc_ld == NULL ) {
|
||||
Debug( asyncmeta_debug, "msc %p not initialized at %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
goto error_unavailable;
|
||||
}
|
||||
|
||||
ldap_get_option( msc->msc_ld, LDAP_OPT_DESC, &s );
|
||||
if (s < 0) {
|
||||
Debug( asyncmeta_debug, "msc %p not initialized at %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
goto error_unavailable;
|
||||
}
|
||||
|
||||
rc = ldap_int_poll( msc->msc_ld, s, &tv, 1);
|
||||
if (rc < 0) {
|
||||
Debug( asyncmeta_debug, "msc %p not writable within network timeout %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
if ((msc->msc_result_time + META_BACK_RESULT_INTERVAL) < slap_get_time()) {
|
||||
rc = LDAP_SERVER_DOWN;
|
||||
} else {
|
||||
goto error_unavailable;
|
||||
}
|
||||
} else {
|
||||
candidates[ candidate ].sr_msgid = msgid;
|
||||
rc = ldap_send_initial_request( msc->msc_ld, LDAP_REQ_MODRDN,
|
||||
mdn.bv_val, ber, msgid );
|
||||
if (rc == msgid)
|
||||
rc = LDAP_SUCCESS;
|
||||
else
|
||||
rc = LDAP_SERVER_DOWN;
|
||||
ber = NULL;
|
||||
}
|
||||
|
||||
switch ( rc ) {
|
||||
case LDAP_SUCCESS:
|
||||
retcode = META_SEARCH_CANDIDATE;
|
||||
asyncmeta_set_msc_time(msc);
|
||||
break;
|
||||
goto done;
|
||||
|
||||
case LDAP_SERVER_DOWN:
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_clear_one_msc(NULL, mc, candidate);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
if ( nretries && asyncmeta_retry( op, rs, &mc, candidate, LDAP_BACK_DONTSEND ) ) {
|
||||
nretries = 0;
|
||||
/* if the identity changed, there might be need to re-authz */
|
||||
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
||||
goto retry;
|
||||
/* do not lock if called from asyncmeta_handle_bind_result. Also do not reset the connection */
|
||||
if (do_lock > 0) {
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_reset_msc(NULL, mc, candidate, 0, __FUNCTION__ );
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
}
|
||||
|
||||
/* fall though*/
|
||||
default:
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
retcode = META_SEARCH_ERR;
|
||||
Debug( asyncmeta_debug, "msc %p ldap_send_initial_request failed. %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
goto error_unavailable;
|
||||
}
|
||||
}
|
||||
|
||||
error_unavailable:
|
||||
if (ber)
|
||||
ber_free(ber, 1);
|
||||
switch (bc->nretries[candidate]) {
|
||||
case -1: /* nretries = forever */
|
||||
retcode = META_SEARCH_NEED_BIND;
|
||||
ldap_pvt_thread_yield();
|
||||
break;
|
||||
case 0: /* no retries left */
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
rs->sr_err = LDAP_UNAVAILABLE;
|
||||
rs->sr_text = "Unable to send modrdn request to target";
|
||||
retcode = META_SEARCH_ERR;
|
||||
break;
|
||||
default: /* more retries left - try to rebind and go again */
|
||||
retcode = META_SEARCH_NEED_BIND;
|
||||
bc->nretries[candidate]--;
|
||||
ldap_pvt_thread_yield();
|
||||
break;
|
||||
}
|
||||
done:
|
||||
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
||||
|
||||
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
|
||||
free( mdn.bv_val );
|
||||
BER_BVZERO( &mdn );
|
||||
op->o_tmpfree( mdn.bv_val, op->o_tmpmemctx );
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &mnewSuperior )
|
||||
&& mnewSuperior.bv_val != op->orr_newSup->bv_val )
|
||||
{
|
||||
free( mnewSuperior.bv_val );
|
||||
BER_BVZERO( &mnewSuperior );
|
||||
op->o_tmpfree( mnewSuperior.bv_val, op->o_tmpmemctx );
|
||||
}
|
||||
|
||||
if ( newrdn.bv_val != op->orr_newrdn.bv_val ) {
|
||||
op->o_tmpfree( newrdn.bv_val, op->o_tmpmemctx );
|
||||
}
|
||||
|
||||
doreturn:;
|
||||
Debug( LDAP_DEBUG_TRACE, "%s <<< asyncmeta_back_modrdn_start[%p]=%d\n", op->o_log_prefix, msc, candidates[candidate].sr_msgid );
|
||||
return retcode;
|
||||
}
|
||||
|
|
@ -199,26 +246,30 @@ asyncmeta_back_modrdn( Operation *op, SlapReply *rs )
|
|||
a_metatarget_t *mt;
|
||||
a_metaconn_t *mc;
|
||||
int rc, candidate = -1;
|
||||
OperationBuffer opbuf;
|
||||
void *thrctx = op->o_threadctx;
|
||||
bm_context_t *bc;
|
||||
SlapReply *candidates;
|
||||
slap_callback *cb = op->o_callback;
|
||||
time_t current_time = slap_get_time();
|
||||
int max_pending_ops = (mi->mi_max_pending_ops == 0) ? META_BACK_CFG_MAX_PENDING_OPS : mi->mi_max_pending_ops;
|
||||
|
||||
Debug(LDAP_DEBUG_ARGS, "==> asyncmeta_back_modrdn: %s\n",
|
||||
op->o_req_dn.bv_val );
|
||||
|
||||
asyncmeta_new_bm_context(op, rs, &bc, mi->mi_ntargets );
|
||||
if (current_time > op->o_time) {
|
||||
Debug(asyncmeta_debug, "==> asyncmeta_back_modrdn[%s]: o_time:[%ld], current time: [%ld]\n",
|
||||
op->o_log_prefix, op->o_time, current_time );
|
||||
}
|
||||
asyncmeta_new_bm_context(op, rs, &bc, mi->mi_ntargets, mi );
|
||||
if (bc == NULL) {
|
||||
rs->sr_err = LDAP_OTHER;
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
send_ldap_result(op, rs);
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
candidates = bc->candidates;
|
||||
mc = asyncmeta_getconn( op, rs, candidates, &candidate, LDAP_BACK_DONTSEND, 0);
|
||||
if ( !mc || rs->sr_err != LDAP_SUCCESS) {
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
send_ldap_result(op, rs);
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
|
|
@ -227,66 +278,69 @@ asyncmeta_back_modrdn( Operation *op, SlapReply *rs )
|
|||
bc->retrying = LDAP_BACK_RETRYING;
|
||||
bc->sendok = ( LDAP_BACK_SENDRESULT | bc->retrying );
|
||||
bc->stoptime = op->o_time + bc->timeout;
|
||||
bc->bc_active = 1;
|
||||
|
||||
if (mc->pending_ops >= max_pending_ops) {
|
||||
rs->sr_err = LDAP_BUSY;
|
||||
rs->sr_text = "Maximum pending ops limit exceeded";
|
||||
send_ldap_result(op, rs);
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
rc = asyncmeta_add_message_queue(mc, bc);
|
||||
mc->mc_conns[candidate].msc_active++;
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
|
||||
if (rc != LDAP_SUCCESS) {
|
||||
rs->sr_err = LDAP_BUSY;
|
||||
rs->sr_text = "Maximum pending ops limit exceeded";
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
send_ldap_result(op, rs);
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
mc->mc_conns[candidate].msc_active--;
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
retry:
|
||||
if (bc->timeout && bc->stoptime < slap_get_time()) {
|
||||
int timeout_err;
|
||||
timeout_err = op->o_protocol >= LDAP_VERSION3 ?
|
||||
LDAP_ADMINLIMIT_EXCEEDED : LDAP_OTHER;
|
||||
rs->sr_err = timeout_err;
|
||||
rs->sr_text = "Operation timed out before it was sent to target";
|
||||
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||
goto finish;
|
||||
|
||||
}
|
||||
|
||||
rc = asyncmeta_dobind_init_with_retry(op, rs, bc, mc, candidate);
|
||||
switch (rc)
|
||||
{
|
||||
case META_SEARCH_CANDIDATE:
|
||||
/* target is already bound, just send the request */
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_modrdn: "
|
||||
"cnd=\"%ld\"\n", op->o_log_prefix, candidate );
|
||||
"cnd=\"%d\"\n", op->o_log_prefix, candidate );
|
||||
|
||||
rc = asyncmeta_back_modrdn_start( op, rs, mc, bc, candidate);
|
||||
rc = asyncmeta_back_modrdn_start( op, rs, mc, bc, candidate, 1);
|
||||
if (rc == META_SEARCH_ERR) {
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_drop_bc(mc, bc);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||
goto finish;
|
||||
|
||||
} else if (rc == META_SEARCH_NEED_BIND) {
|
||||
goto retry;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case META_SEARCH_NOT_CANDIDATE:
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_modrdn: NOT_CANDIDATE "
|
||||
"cnd=\"%ld\"\n", op->o_log_prefix, candidate );
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_drop_bc(mc, bc);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
"cnd=\"%d\"\n", op->o_log_prefix, candidate );
|
||||
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||
goto finish;
|
||||
|
||||
case META_SEARCH_NEED_BIND:
|
||||
case META_SEARCH_CONNECTING:
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_modrdn: NEED_BIND "
|
||||
"cnd=\"%ld\" %p\n", op->o_log_prefix, candidate , &mc->mc_conns[candidate]);
|
||||
rc = asyncmeta_dobind_init(op, rs, bc, mc, candidate);
|
||||
if (rc == META_SEARCH_ERR) {
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_drop_bc(mc, bc);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
goto finish;
|
||||
}
|
||||
break;
|
||||
case META_SEARCH_BINDING:
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_modrdn: BINDING "
|
||||
"cnd=\"%ld\" %p\n", op->o_log_prefix, candidate , &mc->mc_conns[candidate]);
|
||||
"cnd=\"%d\" %p\n", op->o_log_prefix, candidate , &mc->mc_conns[candidate]);
|
||||
/* Todo add the context to the message queue but do not send the request
|
||||
the receiver must send this when we are done binding */
|
||||
/* question - how would do receiver know to which targets??? */
|
||||
|
|
@ -294,22 +348,21 @@ asyncmeta_back_modrdn( Operation *op, SlapReply *rs )
|
|||
|
||||
case META_SEARCH_ERR:
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_modrdn: ERR "
|
||||
"cnd=\"%ldd\"\n", op->o_log_prefix, candidate );
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
candidates[ candidate ].sr_type = REP_RESULT;
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_drop_bc(mc, bc);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
asyncmeta_sender_error(op, rs, cb);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
"cnd=\"%d\"\n", op->o_log_prefix, candidate );
|
||||
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||
goto finish;
|
||||
default:
|
||||
assert( 0 );
|
||||
break;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
mc->mc_conns[candidate].msc_active--;
|
||||
asyncmeta_start_one_listener(mc, candidates, bc, candidate);
|
||||
bc->bc_active--;
|
||||
asyncmeta_memctx_toggle(thrctx);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
rs->sr_err = SLAPD_ASYNCOP;
|
||||
finish:
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ extern BI_op_modify asyncmeta_back_modify;
|
|||
extern BI_op_modrdn asyncmeta_back_modrdn;
|
||||
extern BI_op_add asyncmeta_back_add;
|
||||
extern BI_op_delete asyncmeta_back_delete;
|
||||
extern BI_op_abandon asyncmeta_back_abandon;
|
||||
|
||||
extern BI_connection_destroy asyncmeta_back_conn_destroy;
|
||||
|
||||
|
|
|
|||
|
|
@ -27,59 +27,297 @@
|
|||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
#include <ac/time.h>
|
||||
|
||||
#include "lutil.h"
|
||||
#include "slap.h"
|
||||
#include "../../../libraries/liblber/lber-int.h"
|
||||
#include "../../../libraries/libldap/ldap-int.h"
|
||||
#include "lutil.h"
|
||||
#include "../back-ldap/back-ldap.h"
|
||||
#include "back-asyncmeta.h"
|
||||
#include "../../../libraries/liblber/lber-int.h"
|
||||
|
||||
#include "../../../libraries/libldap/ldap-int.h"
|
||||
#undef ldap_debug
|
||||
#define ldap_debug slap_debug
|
||||
|
||||
static void
|
||||
asyncmeta_handle_onerr_stop(Operation *op,
|
||||
SlapReply *rs,
|
||||
a_metaconn_t *mc,
|
||||
bm_context_t *bc,
|
||||
int candidate,
|
||||
slap_callback *cb)
|
||||
int candidate)
|
||||
{
|
||||
a_metainfo_t *mi = mc->mc_info;
|
||||
int j;
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
if (bc->bc_active > 0) {
|
||||
if (asyncmeta_bc_in_queue(mc,bc) == NULL || bc->bc_active > 1) {
|
||||
bc->bc_active--;
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
return;
|
||||
}
|
||||
bc->bc_active = 1;
|
||||
asyncmeta_drop_bc(mc, bc);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
|
||||
for (j=0; j<mi->mi_ntargets; j++) {
|
||||
if (j != candidate && bc->candidates[j].sr_msgid >= 0
|
||||
&& mc->mc_conns[j].msc_ld != NULL) {
|
||||
asyncmeta_back_abandon_candidate( mc, op,
|
||||
&& mc->mc_conns[j].msc_ld != NULL && !META_BACK_CONN_CREATING( &mc->mc_conns[j] )) {
|
||||
asyncmeta_back_cancel( mc, op,
|
||||
bc->candidates[ j ].sr_msgid, j );
|
||||
}
|
||||
}
|
||||
if (cb != NULL) {
|
||||
op->o_callback = cb;
|
||||
}
|
||||
slap_sl_mem_setctx(op->o_threadctx, op->o_tmpmemctx);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
send_ldap_result(op, rs);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
}
|
||||
|
||||
static int
|
||||
asyncmeta_int_filter2bv( a_dncookie *dc,
|
||||
Filter *f,
|
||||
struct berval *fstr )
|
||||
{
|
||||
int i;
|
||||
Filter *p;
|
||||
struct berval atmp,
|
||||
vtmp,
|
||||
ntmp,
|
||||
*tmp;
|
||||
static struct berval
|
||||
/* better than nothing... */
|
||||
ber_bvfalse = BER_BVC( "(!(objectClass=*))" ),
|
||||
ber_bvtf_false = BER_BVC( "(|)" ),
|
||||
/* better than nothing... */
|
||||
ber_bvtrue = BER_BVC( "(objectClass=*)" ),
|
||||
ber_bvtf_true = BER_BVC( "(&)" ),
|
||||
ber_bverror = BER_BVC( "(?=error)" ),
|
||||
ber_bvunknown = BER_BVC( "(?=unknown)" ),
|
||||
ber_bvnone = BER_BVC( "(?=none)" );
|
||||
ber_len_t len;
|
||||
void *memctx = dc->memctx;
|
||||
|
||||
assert( fstr != NULL );
|
||||
BER_BVZERO( fstr );
|
||||
|
||||
if ( f == NULL ) {
|
||||
ber_dupbv_x( fstr, &ber_bvnone, memctx );
|
||||
return LDAP_OTHER;
|
||||
}
|
||||
|
||||
switch ( ( f->f_choice & SLAPD_FILTER_MASK ) ) {
|
||||
case LDAP_FILTER_EQUALITY:
|
||||
if ( f->f_av_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) {
|
||||
asyncmeta_dn_massage( dc, &f->f_av_value, &vtmp );
|
||||
} else {
|
||||
vtmp = f->f_av_value;
|
||||
}
|
||||
|
||||
filter_escape_value_x( &vtmp, &ntmp, memctx );
|
||||
fstr->bv_len = f->f_av_desc->ad_cname.bv_len + ntmp.bv_len
|
||||
+ ( sizeof("(=)") - 1 );
|
||||
fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx );
|
||||
|
||||
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
|
||||
f->f_av_desc->ad_cname.bv_val, ntmp.bv_len ? ntmp.bv_val : "" );
|
||||
|
||||
ber_memfree_x( ntmp.bv_val, memctx );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_GE:
|
||||
filter_escape_value_x( &f->f_av_value, &ntmp, memctx );
|
||||
fstr->bv_len = f->f_av_desc->ad_cname.bv_len + ntmp.bv_len
|
||||
+ ( sizeof("(>=)") - 1 );
|
||||
fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx );
|
||||
|
||||
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
|
||||
f->f_av_desc->ad_cname.bv_val, ntmp.bv_len ? ntmp.bv_val : "" );
|
||||
|
||||
ber_memfree_x( ntmp.bv_val, memctx );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_LE:
|
||||
filter_escape_value_x( &f->f_av_value, &ntmp, memctx );
|
||||
fstr->bv_len = f->f_av_desc->ad_cname.bv_len + ntmp.bv_len
|
||||
+ ( sizeof("(<=)") - 1 );
|
||||
fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx );
|
||||
|
||||
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
|
||||
f->f_av_desc->ad_cname.bv_val, ntmp.bv_len ? ntmp.bv_val : "" );
|
||||
|
||||
ber_memfree_x( ntmp.bv_val, memctx );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_APPROX:
|
||||
filter_escape_value_x( &f->f_av_value, &ntmp, memctx );
|
||||
fstr->bv_len = f->f_av_desc->ad_cname.bv_len + ntmp.bv_len
|
||||
+ ( sizeof("(~=)") - 1 );
|
||||
fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx );
|
||||
|
||||
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
|
||||
f->f_av_desc->ad_cname.bv_val, ntmp.bv_len ? ntmp.bv_val : "" );
|
||||
|
||||
ber_memfree_x( ntmp.bv_val, memctx );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_SUBSTRINGS:
|
||||
fstr->bv_len = f->f_sub_desc->ad_cname.bv_len + ( STRLENOF( "(=*)" ) );
|
||||
fstr->bv_val = ber_memalloc_x( fstr->bv_len + 128, memctx ); /* FIXME: why 128 ? */
|
||||
|
||||
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
|
||||
f->f_sub_desc->ad_cname.bv_val );
|
||||
|
||||
if ( !BER_BVISNULL( &f->f_sub_initial ) ) {
|
||||
len = fstr->bv_len;
|
||||
|
||||
filter_escape_value_x( &f->f_sub_initial, &ntmp, memctx );
|
||||
|
||||
fstr->bv_len += ntmp.bv_len;
|
||||
fstr->bv_val = ber_memrealloc_x( fstr->bv_val, fstr->bv_len + 1, memctx );
|
||||
|
||||
snprintf( &fstr->bv_val[len - 2], ntmp.bv_len + 3,
|
||||
/* "(attr=" */ "%s*)",
|
||||
ntmp.bv_len ? ntmp.bv_val : "" );
|
||||
|
||||
ber_memfree_x( ntmp.bv_val, memctx );
|
||||
}
|
||||
|
||||
if ( f->f_sub_any != NULL ) {
|
||||
for ( i = 0; !BER_BVISNULL( &f->f_sub_any[i] ); i++ ) {
|
||||
len = fstr->bv_len;
|
||||
filter_escape_value_x( &f->f_sub_any[i], &ntmp, memctx );
|
||||
|
||||
fstr->bv_len += ntmp.bv_len + 1;
|
||||
fstr->bv_val = ber_memrealloc_x( fstr->bv_val, fstr->bv_len + 1, memctx );
|
||||
|
||||
snprintf( &fstr->bv_val[len - 1], ntmp.bv_len + 3,
|
||||
/* "(attr=[init]*[any*]" */ "%s*)",
|
||||
ntmp.bv_len ? ntmp.bv_val : "" );
|
||||
ber_memfree_x( ntmp.bv_val, memctx );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &f->f_sub_final ) ) {
|
||||
len = fstr->bv_len;
|
||||
|
||||
filter_escape_value_x( &f->f_sub_final, &ntmp, memctx );
|
||||
|
||||
fstr->bv_len += ntmp.bv_len;
|
||||
fstr->bv_val = ber_memrealloc_x( fstr->bv_val, fstr->bv_len + 1, memctx );
|
||||
|
||||
snprintf( &fstr->bv_val[len - 1], ntmp.bv_len + 3,
|
||||
/* "(attr=[init*][any*]" */ "%s)",
|
||||
ntmp.bv_len ? ntmp.bv_val : "" );
|
||||
|
||||
ber_memfree_x( ntmp.bv_val, memctx );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_PRESENT:
|
||||
fstr->bv_len = f->f_desc->ad_cname.bv_len + ( STRLENOF( "(=*)" ) );
|
||||
fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx );
|
||||
|
||||
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
|
||||
f->f_desc->ad_cname.bv_val );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_AND:
|
||||
case LDAP_FILTER_OR:
|
||||
case LDAP_FILTER_NOT:
|
||||
fstr->bv_len = STRLENOF( "(%)" );
|
||||
fstr->bv_val = ber_memalloc_x( fstr->bv_len + 128, memctx ); /* FIXME: why 128? */
|
||||
|
||||
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
|
||||
f->f_choice == LDAP_FILTER_AND ? '&' :
|
||||
f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
|
||||
|
||||
for ( p = f->f_list; p != NULL; p = p->f_next ) {
|
||||
int rc;
|
||||
|
||||
len = fstr->bv_len;
|
||||
|
||||
rc = asyncmeta_int_filter2bv( dc, p, &vtmp );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
fstr->bv_len += vtmp.bv_len;
|
||||
fstr->bv_val = ber_memrealloc_x( fstr->bv_val, fstr->bv_len + 1, memctx );
|
||||
|
||||
snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2,
|
||||
/*"("*/ "%s)", vtmp.bv_len ? vtmp.bv_val : "" );
|
||||
|
||||
ber_memfree_x( vtmp.bv_val, memctx );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_EXT:
|
||||
if ( f->f_mr_desc ) {
|
||||
atmp = f->f_mr_desc->ad_cname;
|
||||
|
||||
} else {
|
||||
BER_BVSTR( &atmp, "" );
|
||||
}
|
||||
filter_escape_value_x( &f->f_mr_value, &ntmp, memctx );
|
||||
|
||||
/* FIXME: cleanup (less ?: operators...) */
|
||||
fstr->bv_len = atmp.bv_len +
|
||||
( f->f_mr_dnattrs ? STRLENOF( ":dn" ) : 0 ) +
|
||||
( !BER_BVISEMPTY( &f->f_mr_rule_text ) ? f->f_mr_rule_text.bv_len + 1 : 0 ) +
|
||||
ntmp.bv_len + ( STRLENOF( "(:=)" ) );
|
||||
fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx );
|
||||
|
||||
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
|
||||
atmp.bv_val,
|
||||
f->f_mr_dnattrs ? ":dn" : "",
|
||||
!BER_BVISEMPTY( &f->f_mr_rule_text ) ? ":" : "",
|
||||
!BER_BVISEMPTY( &f->f_mr_rule_text ) ? f->f_mr_rule_text.bv_val : "",
|
||||
ntmp.bv_len ? ntmp.bv_val : "" );
|
||||
ber_memfree_x( ntmp.bv_val, memctx );
|
||||
break;
|
||||
|
||||
case SLAPD_FILTER_COMPUTED:
|
||||
switch ( f->f_result ) {
|
||||
/* FIXME: treat UNDEFINED as FALSE */
|
||||
case SLAPD_COMPARE_UNDEFINED:
|
||||
if ( META_BACK_TGT_NOUNDEFFILTER( dc->target ) ) {
|
||||
return LDAP_COMPARE_FALSE;
|
||||
}
|
||||
/* fallthru */
|
||||
|
||||
case LDAP_COMPARE_FALSE:
|
||||
if ( META_BACK_TGT_T_F( dc->target ) ) {
|
||||
tmp = &ber_bvtf_false;
|
||||
break;
|
||||
}
|
||||
tmp = &ber_bvfalse;
|
||||
break;
|
||||
|
||||
case LDAP_COMPARE_TRUE:
|
||||
if ( META_BACK_TGT_T_F( dc->target ) ) {
|
||||
tmp = &ber_bvtf_true;
|
||||
break;
|
||||
}
|
||||
|
||||
tmp = &ber_bvtrue;
|
||||
break;
|
||||
|
||||
default:
|
||||
tmp = &ber_bverror;
|
||||
break;
|
||||
}
|
||||
|
||||
ber_dupbv_x( fstr, tmp, memctx );
|
||||
break;
|
||||
|
||||
default:
|
||||
ber_dupbv_x( fstr, &ber_bvunknown, memctx );
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
meta_search_candidate_t
|
||||
asyncmeta_back_search_start(
|
||||
Operation *op,
|
||||
SlapReply *rs,
|
||||
a_metaconn_t *mc,
|
||||
bm_context_t *bc,
|
||||
int candidate,
|
||||
struct berval *prcookie,
|
||||
ber_int_t prsize )
|
||||
a_metaconn_t *mc,
|
||||
bm_context_t *bc,
|
||||
int candidate,
|
||||
struct berval *prcookie,
|
||||
ber_int_t prsize,
|
||||
int do_lock)
|
||||
{
|
||||
SlapReply *candidates = bc->candidates;
|
||||
a_metainfo_t *mi = ( a_metainfo_t * )mc->mc_info;
|
||||
|
|
@ -87,16 +325,15 @@ asyncmeta_back_search_start(
|
|||
a_metasingleconn_t *msc = &mc->mc_conns[ candidate ];
|
||||
a_dncookie dc;
|
||||
struct berval realbase = op->o_req_dn;
|
||||
char **attrs;
|
||||
int realscope = op->ors_scope;
|
||||
struct berval mbase = BER_BVNULL;
|
||||
struct berval mfilter = BER_BVNULL;
|
||||
char **mapped_attrs = NULL;
|
||||
int rc;
|
||||
struct berval filterbv = BER_BVNULL;
|
||||
meta_search_candidate_t retcode;
|
||||
int timelimit;
|
||||
int nretries = 1;
|
||||
LDAPControl **ctrls = NULL;
|
||||
BerElement *ber;
|
||||
BerElement *ber = NULL;
|
||||
ber_int_t msgid;
|
||||
#ifdef SLAPD_META_CLIENT_PR
|
||||
LDAPControl **save_ctrls = NULL;
|
||||
|
|
@ -116,7 +353,8 @@ asyncmeta_back_search_start(
|
|||
return META_SEARCH_NOT_CANDIDATE;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "%s >>> asyncmeta_back_search_start[%d]\n", op->o_log_prefix, candidate );
|
||||
Debug( LDAP_DEBUG_TRACE, "%s >>> asyncmeta_back_search_start: dn=%s filter=%s\n",
|
||||
op->o_log_prefix, op->o_req_dn.bv_val, op->ors_filterstr.bv_val );
|
||||
/*
|
||||
* modifies the base according to the scope, if required
|
||||
*/
|
||||
|
|
@ -199,59 +437,13 @@ asyncmeta_back_search_start(
|
|||
/*
|
||||
* Rewrite the search base, if required
|
||||
*/
|
||||
dc.op = op;
|
||||
dc.target = mt;
|
||||
dc.ctx = "searchBase";
|
||||
dc.conn = op->o_conn;
|
||||
dc.rs = rs;
|
||||
switch ( asyncmeta_dn_massage( &dc, &realbase, &mbase ) ) {
|
||||
case LDAP_SUCCESS:
|
||||
break;
|
||||
dc.memctx = op->o_tmpmemctx;
|
||||
dc.to_from = MASSAGE_REQ;
|
||||
asyncmeta_dn_massage( &dc, &realbase, &mbase );
|
||||
|
||||
case LDAP_UNWILLING_TO_PERFORM:
|
||||
rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
|
||||
rs->sr_text = "Operation not allowed";
|
||||
retcode = META_SEARCH_ERR;
|
||||
goto doreturn;
|
||||
|
||||
default:
|
||||
|
||||
/*
|
||||
* this target is no longer candidate
|
||||
*/
|
||||
retcode = META_SEARCH_NOT_CANDIDATE;
|
||||
goto doreturn;
|
||||
}
|
||||
|
||||
/*
|
||||
* Maps filter
|
||||
*/
|
||||
rc = asyncmeta_filter_map_rewrite( &dc, op->ors_filter,
|
||||
&mfilter, BACKLDAP_MAP, NULL );
|
||||
switch ( rc ) {
|
||||
case LDAP_SUCCESS:
|
||||
break;
|
||||
|
||||
case LDAP_COMPARE_FALSE:
|
||||
default:
|
||||
/*
|
||||
* this target is no longer candidate
|
||||
*/
|
||||
retcode = META_SEARCH_NOT_CANDIDATE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Maps required attributes
|
||||
*/
|
||||
rc = asyncmeta_map_attrs( op, &mt->mt_rwmap.rwm_at,
|
||||
op->ors_attrs, BACKLDAP_MAP, &mapped_attrs );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
/*
|
||||
* this target is no longer candidate
|
||||
*/
|
||||
retcode = META_SEARCH_NOT_CANDIDATE;
|
||||
goto done;
|
||||
}
|
||||
attrs = anlist2charray_x( op->ors_attrs, 0, op->o_tmpmemctx );
|
||||
|
||||
if ( op->ors_tlimit != SLAP_NO_LIMIT ) {
|
||||
timelimit = op->ors_tlimit > 0 ? op->ors_tlimit : 1;
|
||||
|
|
@ -338,21 +530,10 @@ done_pr:;
|
|||
}
|
||||
#endif /* SLAPD_META_CLIENT_PR */
|
||||
|
||||
retry:;
|
||||
asyncmeta_set_msc_time(msc);
|
||||
ctrls = op->o_ctrls;
|
||||
if (nretries == 0)
|
||||
{
|
||||
if (rc != LDAP_SUCCESS)
|
||||
{
|
||||
rs->sr_err = LDAP_BUSY;
|
||||
retcode = META_SEARCH_ERR;
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if ( asyncmeta_controls_add( op, rs, mc, candidate, &ctrls )
|
||||
if ( asyncmeta_controls_add( op, rs, mc, candidate, bc->is_root, &ctrls )
|
||||
!= LDAP_SUCCESS )
|
||||
{
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
|
|
@ -363,48 +544,114 @@ retry:;
|
|||
/*
|
||||
* Starts the search
|
||||
*/
|
||||
/* someone reset the connection */
|
||||
if (!( LDAP_BACK_CONN_ISBOUND( msc )
|
||||
|| LDAP_BACK_CONN_ISANON( msc )) || msc->msc_ld == NULL ) {
|
||||
Debug( asyncmeta_debug, "msc %p not initialized at %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
goto error_unavailable;
|
||||
}
|
||||
rc = asyncmeta_int_filter2bv( &dc, op->ors_filter, &filterbv );
|
||||
if ( rc ) {
|
||||
retcode = META_SEARCH_ERR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ber = ldap_build_search_req( msc->msc_ld,
|
||||
mbase.bv_val, realscope, mfilter.bv_val,
|
||||
mapped_attrs, op->ors_attrsonly,
|
||||
mbase.bv_val, realscope, filterbv.bv_val,
|
||||
attrs, op->ors_attrsonly,
|
||||
ctrls, NULL, timelimit, op->ors_slimit, op->ors_deref,
|
||||
&msgid );
|
||||
if (!ber) {
|
||||
Debug( asyncmeta_debug, "%s asyncmeta_back_search_start: Operation encoding failed with errno %d\n",
|
||||
op->o_log_prefix, msc->msc_ld->ld_errno );
|
||||
rs->sr_err = LDAP_OPERATIONS_ERROR;
|
||||
rs->sr_text = "Failed to encode proxied request";
|
||||
retcode = META_SEARCH_ERR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (ber) {
|
||||
candidates[ candidate ].sr_msgid = msgid;
|
||||
rc = ldap_send_initial_request( msc->msc_ld, LDAP_REQ_SEARCH,
|
||||
mbase.bv_val, ber, msgid );
|
||||
if (rc == msgid)
|
||||
rc = LDAP_SUCCESS;
|
||||
else
|
||||
rc = LDAP_SERVER_DOWN;
|
||||
struct timeval tv = {0, mt->mt_network_timeout*1000};
|
||||
ber_socket_t s;
|
||||
|
||||
if (!( LDAP_BACK_CONN_ISBOUND( msc )
|
||||
|| LDAP_BACK_CONN_ISANON( msc )) || msc->msc_ld == NULL ) {
|
||||
Debug( asyncmeta_debug, "msc %p not initialized at %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
goto error_unavailable;
|
||||
}
|
||||
|
||||
ldap_get_option( msc->msc_ld, LDAP_OPT_DESC, &s );
|
||||
if (s < 0) {
|
||||
Debug( asyncmeta_debug, "msc %p not initialized at %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
goto error_unavailable;
|
||||
}
|
||||
|
||||
rc = ldap_int_poll( msc->msc_ld, s, &tv, 1);
|
||||
if (rc < 0) {
|
||||
Debug( asyncmeta_debug, "msc %p not writable within network timeout %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
if ((msc->msc_result_time + META_BACK_RESULT_INTERVAL) < slap_get_time()) {
|
||||
rc = LDAP_SERVER_DOWN;
|
||||
} else {
|
||||
goto error_unavailable;
|
||||
}
|
||||
} else {
|
||||
candidates[ candidate ].sr_msgid = msgid;
|
||||
rc = ldap_send_initial_request( msc->msc_ld, LDAP_REQ_SEARCH,
|
||||
mbase.bv_val, ber, msgid );
|
||||
if (rc == msgid)
|
||||
rc = LDAP_SUCCESS;
|
||||
else
|
||||
rc = LDAP_SERVER_DOWN;
|
||||
ber = NULL;
|
||||
}
|
||||
|
||||
switch ( rc ) {
|
||||
case LDAP_SUCCESS:
|
||||
retcode = META_SEARCH_CANDIDATE;
|
||||
asyncmeta_set_msc_time(msc);
|
||||
break;
|
||||
goto done;
|
||||
|
||||
case LDAP_SERVER_DOWN:
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
if (mc->mc_active < 1) {
|
||||
asyncmeta_clear_one_msc(NULL, mc, candidate);
|
||||
/* do not lock if called from asyncmeta_handle_bind_result. Also do not reset the connection */
|
||||
if (do_lock > 0) {
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_reset_msc(NULL, mc, candidate, 0, __FUNCTION__);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
if ( nretries && asyncmeta_retry( op, rs, &mc, candidate, LDAP_BACK_DONTSEND ) ) {
|
||||
nretries = 0;
|
||||
/* if the identity changed, there might be need to re-authz */
|
||||
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
||||
goto retry;
|
||||
}
|
||||
rs->sr_err = LDAP_UNAVAILABLE;
|
||||
retcode = META_SEARCH_ERR;
|
||||
break;
|
||||
Debug( asyncmeta_debug, "msc %p ldap_send_initial_request failed. %s:%d\n", msc, __FILE__, __LINE__ );
|
||||
goto error_unavailable;
|
||||
|
||||
default:
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
retcode = META_SEARCH_NOT_CANDIDATE;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
error_unavailable:
|
||||
if (ber)
|
||||
ber_free(ber, 1);
|
||||
switch (bc->nretries[candidate]) {
|
||||
case -1: /* nretries = forever */
|
||||
retcode = META_SEARCH_NEED_BIND;
|
||||
ldap_pvt_thread_yield();
|
||||
break;
|
||||
case 0: /* no retries left */
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
rs->sr_err = LDAP_UNAVAILABLE;
|
||||
rs->sr_text = "Unable to send search request to target";
|
||||
retcode = META_SEARCH_ERR;
|
||||
break;
|
||||
default: /* more retries left - try to rebind and go again */
|
||||
retcode = META_SEARCH_NEED_BIND;
|
||||
bc->nretries[candidate]--;
|
||||
ldap_pvt_thread_yield();
|
||||
break;
|
||||
}
|
||||
done:;
|
||||
#if 0
|
||||
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
||||
#endif
|
||||
#ifdef SLAPD_META_CLIENT_PR
|
||||
if ( save_ctrls != op->o_ctrls ) {
|
||||
op->o_tmpfree( op->o_ctrls, op->o_tmpmemctx );
|
||||
|
|
@ -412,14 +659,8 @@ done:;
|
|||
}
|
||||
#endif /* SLAPD_META_CLIENT_PR */
|
||||
|
||||
if ( mapped_attrs ) {
|
||||
ber_memfree_x( mapped_attrs, op->o_tmpmemctx );
|
||||
}
|
||||
if ( mfilter.bv_val != op->ors_filterstr.bv_val ) {
|
||||
ber_memfree_x( mfilter.bv_val, NULL );
|
||||
}
|
||||
if ( mbase.bv_val != realbase.bv_val ) {
|
||||
free( mbase.bv_val );
|
||||
op->o_tmpfree( mbase.bv_val, op->o_tmpmemctx );
|
||||
}
|
||||
|
||||
doreturn:;
|
||||
|
|
@ -431,25 +672,16 @@ int
|
|||
asyncmeta_back_search( Operation *op, SlapReply *rs )
|
||||
{
|
||||
a_metainfo_t *mi = ( a_metainfo_t * )op->o_bd->be_private;
|
||||
struct timeval save_tv = { 0, 0 },
|
||||
tv;
|
||||
time_t stoptime = (time_t)(-1),
|
||||
lastres_time = slap_get_time(),
|
||||
timeout = 0;
|
||||
int rc = 0, sres = LDAP_SUCCESS;
|
||||
char *matched = NULL;
|
||||
int last = 0, ncandidates = 0,
|
||||
initial_candidates = 0, candidate_match = 0,
|
||||
needbind = 0;
|
||||
ldap_back_send_t sendok = LDAP_BACK_SENDERR;
|
||||
long i,j;
|
||||
int is_ok = 0;
|
||||
void *savepriv;
|
||||
time_t timeout = 0;
|
||||
int rc = 0;
|
||||
int ncandidates = 0, initial_candidates = 0;
|
||||
long i;
|
||||
SlapReply *candidates = NULL;
|
||||
int do_taint = 0;
|
||||
void *thrctx = op->o_threadctx;
|
||||
bm_context_t *bc;
|
||||
a_metaconn_t *mc;
|
||||
slap_callback *cb = op->o_callback;
|
||||
int msc_decr = 0;
|
||||
int max_pending_ops = (mi->mi_max_pending_ops == 0) ? META_BACK_CFG_MAX_PENDING_OPS : mi->mi_max_pending_ops;
|
||||
|
||||
rs_assert_ready( rs );
|
||||
rs->sr_flags &= ~REP_ENTRY_MASK; /* paranoia, we can set rs = non-entry */
|
||||
|
|
@ -461,7 +693,7 @@ asyncmeta_back_search( Operation *op, SlapReply *rs )
|
|||
* to map attrs and maybe rewrite value
|
||||
*/
|
||||
|
||||
asyncmeta_new_bm_context(op, rs, &bc, mi->mi_ntargets );
|
||||
asyncmeta_new_bm_context(op, rs, &bc, mi->mi_ntargets, mi );
|
||||
if (bc == NULL) {
|
||||
rs->sr_err = LDAP_OTHER;
|
||||
send_ldap_result(op, rs);
|
||||
|
|
@ -471,9 +703,7 @@ asyncmeta_back_search( Operation *op, SlapReply *rs )
|
|||
candidates = bc->candidates;
|
||||
mc = asyncmeta_getconn( op, rs, candidates, NULL, LDAP_BACK_DONTSEND, 0);
|
||||
if ( !mc || rs->sr_err != LDAP_SUCCESS) {
|
||||
op->o_callback = cb;
|
||||
send_ldap_result(op, rs);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
|
|
@ -511,27 +741,33 @@ asyncmeta_back_search( Operation *op, SlapReply *rs )
|
|||
}
|
||||
}
|
||||
|
||||
bc->timeout = timeout;
|
||||
bc->stoptime = op->o_time + bc->timeout;
|
||||
if ( op->ors_tlimit != SLAP_NO_LIMIT && (timeout == 0 || op->ors_tlimit < timeout)) {
|
||||
bc->searchtime = 1;
|
||||
bc->timeout = op->ors_tlimit;
|
||||
} else {
|
||||
bc->timeout = timeout;
|
||||
}
|
||||
|
||||
if ( op->ors_tlimit != SLAP_NO_LIMIT ) {
|
||||
stoptime = op->o_time + op->ors_tlimit;
|
||||
if (stoptime < bc->stoptime) {
|
||||
bc->stoptime = stoptime;
|
||||
bc->searchtime = 1;
|
||||
bc->timeout = op->ors_tlimit;
|
||||
}
|
||||
bc->stoptime = op->o_time + bc->timeout;
|
||||
bc->bc_active = 1;
|
||||
|
||||
if (mc->pending_ops >= max_pending_ops) {
|
||||
rs->sr_err = LDAP_BUSY;
|
||||
rs->sr_text = "Maximum pending ops limit exceeded";
|
||||
send_ldap_result(op, rs);
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
rc = asyncmeta_add_message_queue(mc, bc);
|
||||
for ( i = 0; i < mi->mi_ntargets; i++ ) {
|
||||
mc->mc_conns[i].msc_active++;
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
|
||||
if (rc != LDAP_SUCCESS) {
|
||||
rs->sr_err = LDAP_BUSY;
|
||||
rs->sr_text = "Maximum pending ops limit exceeded";
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
op->o_callback = cb;
|
||||
send_ldap_result(op, rs);
|
||||
goto finish;
|
||||
}
|
||||
|
|
@ -542,6 +778,30 @@ asyncmeta_back_search( Operation *op, SlapReply *rs )
|
|||
{
|
||||
continue;
|
||||
}
|
||||
retry:
|
||||
if (bc->timeout && bc->stoptime < slap_get_time() && META_BACK_ONERR_STOP( mi )) {
|
||||
int timeout_err;
|
||||
const char *timeout_text;
|
||||
if (bc->searchtime) {
|
||||
timeout_err = LDAP_TIMELIMIT_EXCEEDED;
|
||||
timeout_text = NULL;
|
||||
} else {
|
||||
timeout_err = op->o_protocol >= LDAP_VERSION3 ?
|
||||
LDAP_ADMINLIMIT_EXCEEDED : LDAP_OTHER;
|
||||
timeout_text = "Operation timed out before it was sent to target";
|
||||
}
|
||||
rs->sr_err = timeout_err;
|
||||
rs->sr_text = timeout_text;
|
||||
asyncmeta_handle_onerr_stop(op,rs,mc,bc,i);
|
||||
goto finish;
|
||||
|
||||
}
|
||||
|
||||
if (op->o_abandon) {
|
||||
rs->sr_err = SLAPD_ABANDON;
|
||||
asyncmeta_handle_onerr_stop(op,rs,mc,bc,i);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
rc = asyncmeta_dobind_init_with_retry(op, rs, bc, mc, i);
|
||||
switch (rc)
|
||||
|
|
@ -552,17 +812,19 @@ asyncmeta_back_search( Operation *op, SlapReply *rs )
|
|||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_search: IS_CANDIDATE "
|
||||
"cnd=\"%ld\"\n", op->o_log_prefix, i );
|
||||
|
||||
rc = asyncmeta_back_search_start( op, rs, mc, bc, i, NULL, 0 );
|
||||
rc = asyncmeta_back_search_start( op, rs, mc, bc, i, NULL, 0 , 1);
|
||||
if (rc == META_SEARCH_ERR) {
|
||||
META_CANDIDATE_CLEAR(&candidates[i]);
|
||||
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
|
||||
if ( META_BACK_ONERR_STOP( mi ) ) {
|
||||
asyncmeta_handle_onerr_stop(op,rs,mc,bc,i,cb);
|
||||
asyncmeta_handle_onerr_stop(op,rs,mc,bc,i);
|
||||
goto finish;
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
} else if (rc == META_SEARCH_NEED_BIND) {
|
||||
goto retry;
|
||||
}
|
||||
break;
|
||||
case META_SEARCH_NOT_CANDIDATE:
|
||||
|
|
@ -572,22 +834,6 @@ asyncmeta_back_search( Operation *op, SlapReply *rs )
|
|||
break;
|
||||
|
||||
case META_SEARCH_NEED_BIND:
|
||||
case META_SEARCH_CONNECTING:
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_search: NEED_BIND "
|
||||
"cnd=\"%ld\" %p\n", op->o_log_prefix, i , &mc->mc_conns[i]);
|
||||
ncandidates++;
|
||||
rc = asyncmeta_dobind_init(op, rs, bc, mc, i);
|
||||
if (rc == META_SEARCH_ERR) {
|
||||
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
|
||||
if ( META_BACK_ONERR_STOP( mi ) ) {
|
||||
asyncmeta_handle_onerr_stop(op,rs,mc,bc,i,cb);
|
||||
goto finish;
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case META_SEARCH_BINDING:
|
||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_search: BINDING "
|
||||
"cnd=\"%ld\" %p\n", op->o_log_prefix, i , &mc->mc_conns[i]);
|
||||
|
|
@ -604,7 +850,7 @@ asyncmeta_back_search( Operation *op, SlapReply *rs )
|
|||
candidates[ i ].sr_type = REP_RESULT;
|
||||
|
||||
if ( META_BACK_ONERR_STOP( mi ) ) {
|
||||
asyncmeta_handle_onerr_stop(op,rs,mc,bc,i,cb);
|
||||
asyncmeta_handle_onerr_stop(op,rs,mc,bc,i);
|
||||
goto finish;
|
||||
}
|
||||
else {
|
||||
|
|
@ -666,14 +912,29 @@ asyncmeta_back_search( Operation *op, SlapReply *rs )
|
|||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
asyncmeta_drop_bc(mc, bc);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
op->o_callback = cb;
|
||||
send_ldap_result(op, rs);
|
||||
asyncmeta_clear_bm_context(bc);
|
||||
goto finish;
|
||||
}
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
for ( i = 0; i < mi->mi_ntargets; i++ ) {
|
||||
mc->mc_conns[i].msc_active--;
|
||||
}
|
||||
msc_decr = 1;
|
||||
|
||||
asyncmeta_start_listeners(mc, candidates, bc);
|
||||
bc->bc_active--;
|
||||
asyncmeta_memctx_toggle(thrctx);
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
rs->sr_err = SLAPD_ASYNCOP;
|
||||
|
||||
finish:
|
||||
/* we ended up straight here due to error and need to reset the msc_active*/
|
||||
if (msc_decr == 0) {
|
||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||
for ( i = 0; i < mi->mi_ntargets; i++ ) {
|
||||
mc->mc_conns[i].msc_active--;
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||
}
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,112 +0,0 @@
|
|||
/* suffixmassage.c - massages ldap backend dns */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 2016-2019 The OpenLDAP Foundation.
|
||||
* Portions Copyright 2016 Symas Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted only as authorized by the OpenLDAP
|
||||
* Public License.
|
||||
*
|
||||
* A copy of this license is available in the file LICENSE in the
|
||||
* top-level directory of the distribution or, alternatively, at
|
||||
* <http://www.OpenLDAP.org/license.html>.
|
||||
*/
|
||||
|
||||
/* ACKNOWLEDGEMENTS:
|
||||
* This work was developed by Symas Corporation
|
||||
* based on back-meta module for inclusion in OpenLDAP Software.
|
||||
* This work was sponsored by Ericsson. */
|
||||
|
||||
/* This is an altered version */
|
||||
|
||||
/*
|
||||
* Copyright 1999, Howard Chu, All rights reserved. <hyc@highlandsun.com>
|
||||
* Copyright 2000, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
|
||||
*
|
||||
* Module back-ldap, originally developed by Howard Chu
|
||||
*
|
||||
* has been modified by Pierangelo Masarati. The original copyright
|
||||
* notice has been maintained.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose
|
||||
* on any computer system, and to alter it and redistribute it, subject
|
||||
* to the following restrictions:
|
||||
*
|
||||
* 1. The author is not responsible for the consequences of use of this
|
||||
* software, no matter how awful, even if they arise from flaws in it.
|
||||
*
|
||||
* 2. The origin of this software must not be misrepresented, either by
|
||||
* explicit claim or by omission. Since few users ever read sources,
|
||||
* credits should appear in the documentation.
|
||||
*
|
||||
* 3. Altered versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software. Since few users
|
||||
* ever read sources, credits should appear in the documentation.
|
||||
*
|
||||
* 4. This notice may not be removed or altered.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "../back-ldap/back-ldap.h"
|
||||
#include "back-asyncmeta.h"
|
||||
|
||||
int
|
||||
asyncmeta_dn_massage(
|
||||
a_dncookie *dc,
|
||||
struct berval *dn,
|
||||
struct berval *res )
|
||||
{
|
||||
int rc = 0;
|
||||
static char *dmy = "";
|
||||
|
||||
switch ( rewrite_session( dc->target->mt_rwmap.rwm_rw, dc->ctx,
|
||||
( dn->bv_val ? dn->bv_val : dmy ),
|
||||
dc->conn, &res->bv_val ) )
|
||||
{
|
||||
case REWRITE_REGEXEC_OK:
|
||||
if ( res->bv_val != NULL ) {
|
||||
res->bv_len = strlen( res->bv_val );
|
||||
} else {
|
||||
*res = *dn;
|
||||
}
|
||||
Debug( LDAP_DEBUG_ARGS,
|
||||
"[rw] %s: \"%s\" -> \"%s\"\n",
|
||||
dc->ctx,
|
||||
BER_BVISNULL( dn ) ? "" : dn->bv_val,
|
||||
BER_BVISNULL( res ) ? "" : res->bv_val );
|
||||
rc = LDAP_SUCCESS;
|
||||
break;
|
||||
|
||||
case REWRITE_REGEXEC_UNWILLING:
|
||||
if ( dc->rs ) {
|
||||
dc->rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
|
||||
dc->rs->sr_text = "Operation not allowed";
|
||||
}
|
||||
rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
break;
|
||||
|
||||
case REWRITE_REGEXEC_ERR:
|
||||
if ( dc->rs ) {
|
||||
dc->rs->sr_err = LDAP_OTHER;
|
||||
dc->rs->sr_text = "Rewrite error";
|
||||
}
|
||||
rc = LDAP_OTHER;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( res->bv_val == dmy ) {
|
||||
BER_BVZERO( res );
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
/* unbind.c - unbind handler for back-asyncmeta */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 2016-2019 The OpenLDAP Foundation.
|
||||
* Portions Copyright 2016 Symas Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted only as authorized by the OpenLDAP
|
||||
* Public License.
|
||||
*
|
||||
* A copy of this license is available in the file LICENSE in the
|
||||
* top-level directory of the distribution or, alternatively, at
|
||||
* <http://www.OpenLDAP.org/license.html>.
|
||||
*/
|
||||
|
||||
/* ACKNOWLEDGEMENTS:
|
||||
* This work was developed by Symas Corporation
|
||||
* based on back-meta module for inclusion in OpenLDAP Software.
|
||||
* This work was sponsored by Ericsson. */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/errno.h>
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "../back-ldap/back-ldap.h"
|
||||
#include "back-asyncmeta.h"
|
||||
|
||||
int
|
||||
asyncmeta_back_conn_destroy(
|
||||
Backend *be,
|
||||
Connection *conn )
|
||||
{
|
||||
a_metainfo_t *mi = ( a_metainfo_t * )be->be_private;
|
||||
int i;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"=>asyncmeta_back_conn_destroy: fetching conn=%ld DN=\"%s\"\n",
|
||||
conn->c_connid,
|
||||
BER_BVISNULL( &conn->c_ndn ) ? "" : conn->c_ndn.bv_val );
|
||||
/*
|
||||
* Cleanup rewrite session
|
||||
*/
|
||||
for ( i = 0; i < mi->mi_ntargets; ++i ) {
|
||||
rewrite_session_delete( mi->mi_targets[ i ]->mt_rwmap.rwm_rw, conn );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
88
tests/data/slapd-asyncmeta.conf
Normal file
88
tests/data/slapd-asyncmeta.conf
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
# master slapd config -- for testing
|
||||
# $OpenLDAP$
|
||||
## This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
##
|
||||
## Copyright 1998-2019 The OpenLDAP Foundation.
|
||||
## All rights reserved.
|
||||
##
|
||||
## Redistribution and use in source and binary forms, with or without
|
||||
## modification, are permitted only as authorized by the OpenLDAP
|
||||
## Public License.
|
||||
##
|
||||
## A copy of this license is available in the file LICENSE in the
|
||||
## top-level directory of the distribution or, alternatively, at
|
||||
## <http://www.OpenLDAP.org/license.html>.
|
||||
|
||||
include @SCHEMADIR@/core.schema
|
||||
include @SCHEMADIR@/cosine.schema
|
||||
include @SCHEMADIR@/inetorgperson.schema
|
||||
include @SCHEMADIR@/openldap.schema
|
||||
include @SCHEMADIR@/nis.schema
|
||||
include @SCHEMADIR@/ppolicy.schema
|
||||
pidfile @TESTDIR@/slapd.m.pid
|
||||
argsfile @TESTDIR@/slapd.m.args
|
||||
|
||||
#ldapmod#modulepath ../servers/slapd/back-ldap/
|
||||
#ldapmod#moduleload back_ldap.la
|
||||
#metamod#modulepath ../servers/slapd/back-meta/
|
||||
#metamod#moduleload back_meta.la
|
||||
#monitormod#modulepath ../servers/slapd/back-monitor/
|
||||
#monitormod#moduleload back_monitor.la
|
||||
|
||||
# seems to improve behavior under very heavy load
|
||||
# (i.e. it alleviates load on target systems)
|
||||
threads 8
|
||||
|
||||
#######################################################################
|
||||
# database definitions
|
||||
#######################################################################
|
||||
|
||||
database asyncmeta
|
||||
suffix "o=Example,c=US"
|
||||
rootdn "cn=Manager,o=Example,c=US"
|
||||
rootpw secret
|
||||
chase-referrals no
|
||||
#nretries forever
|
||||
nretries 100
|
||||
#norefs true
|
||||
network-timeout 500
|
||||
#max-timeout-ops 50
|
||||
#max-pending-ops 128
|
||||
#max-target-conns 16
|
||||
|
||||
# local
|
||||
uri "@URI2@ou=Meta,o=Example,c=US"
|
||||
subtree-exclude "ou=Excluded,ou=Meta,o=Example,c=US"
|
||||
suffixmassage "ou=Meta,o=Example,c=US" "ou=Meta,dc=example,dc=com"
|
||||
###pseudorootdn "cn=manager,ou=meta,dc=example,dc=com"
|
||||
###pseudorootpw secret
|
||||
idassert-bind bindmethod=simple
|
||||
binddn="cn=manager,ou=meta,dc=example,dc=com"
|
||||
credentials="secret"
|
||||
mode=self
|
||||
flags=non-prescriptive
|
||||
idassert-authzFrom "dn.exact:cn=Manager,o=Local"
|
||||
|
||||
# remote
|
||||
uri "@URI1@o=Example,c=US"
|
||||
subtree-include "dn.subtree:o=Example,c=US"
|
||||
suffixmassage "o=Example,c=US" "dc=example,dc=com"
|
||||
###pseudorootdn "cn=manager,dc=example,dc=com"
|
||||
###pseudorootpw secret
|
||||
idassert-bind bindmethod=simple
|
||||
binddn="cn=manager,dc=example,dc=com"
|
||||
credentials="secret"
|
||||
mode=self
|
||||
flags=non-prescriptive
|
||||
idassert-authzFrom "dn.exact:cn=Manager,o=Local"
|
||||
|
||||
limits dn.exact="cn=Bjorn Jensen,ou=Information Technology Division,ou=People,o=Example,c=US" time=1 size=8
|
||||
|
||||
# This is only for binding as the rootdn
|
||||
database asyncmeta
|
||||
suffix "o=Local"
|
||||
rootdn "cn=Manager,o=Local"
|
||||
rootpw secret
|
||||
uri "@URI6@o=Local"
|
||||
|
||||
#monitor#database monitor
|
||||
|
|
@ -33,6 +33,7 @@ AC_null=@BUILD_NULL@
|
|||
# other backends
|
||||
AC_ldap=ldap@BUILD_LDAP@
|
||||
AC_meta=meta@BUILD_META@
|
||||
AC_asyncmeta=asyncmeta@BUILD_ASYNCMETA@
|
||||
AC_monitor=@BUILD_MONITOR@
|
||||
AC_relay=relay@BUILD_RELAY@
|
||||
AC_sql=sql@BUILD_SQL@
|
||||
|
|
@ -70,8 +71,10 @@ fi
|
|||
if test "${AC_meta}" = "metamod" && test "${AC_LIBS_DYNAMIC}" = "static" ; then
|
||||
AC_meta="metano"
|
||||
fi
|
||||
|
||||
export AC_bdb AC_hdb AC_ldap AC_mdb AC_meta AC_monitor AC_null AC_relay AC_sql \
|
||||
if test "${AC_asyncmeta}" = "metamod" && test "${AC_LIBS_DYNAMIC}" = "static" ; then
|
||||
AC_meta="asyncmetano"
|
||||
fi
|
||||
export AC_bdb AC_hdb AC_ldap AC_mdb AC_meta AC_asyncmeta AC_monitor AC_null AC_relay AC_sql \
|
||||
AC_accesslog AC_autoca AC_constraint AC_dds AC_dynlist AC_memberof AC_pcache AC_ppolicy \
|
||||
AC_refint AC_retcode AC_rwm AC_unique AC_syncprov AC_translucent \
|
||||
AC_valsort \
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ TESTWD=`pwd`
|
|||
MONITORDB=${AC_monitor-no}
|
||||
BACKLDAP=${AC_ldap-ldapno}
|
||||
BACKMETA=${AC_meta-metano}
|
||||
BACKASYNCMETA=${AC_asyncmeta-asyncmetano}
|
||||
BACKRELAY=${AC_relay-relayno}
|
||||
BACKSQL=${AC_sql-sqlno}
|
||||
RDBMS=${SLAPD_USE_SQL-rdbmsno}
|
||||
|
|
@ -134,6 +135,7 @@ TRANSLUCENTREMOTECONF=$DATADIR/slapd-translucent-remote.conf
|
|||
METACONF=$DATADIR/slapd-meta.conf
|
||||
METACONF1=$DATADIR/slapd-meta-target1.conf
|
||||
METACONF2=$DATADIR/slapd-meta-target2.conf
|
||||
ASYNCMETACONF=$DATADIR/slapd-asyncmeta.conf
|
||||
GLUELDAPCONF=$DATADIR/slapd-glue-ldap.conf
|
||||
ACICONF=$DATADIR/slapd-aci.conf
|
||||
VALSORTCONF=$DATADIR/slapd-valsort.conf
|
||||
|
|
|
|||
620
tests/scripts/test073-asyncmeta
Executable file
620
tests/scripts/test073-asyncmeta
Executable file
|
|
@ -0,0 +1,620 @@
|
|||
#! /bin/sh
|
||||
# $OpenLDAP$
|
||||
## This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
##
|
||||
## Copyright 1998-2019 The OpenLDAP Foundation.
|
||||
## All rights reserved.
|
||||
##
|
||||
## Redistribution and use in source and binary forms, with or without
|
||||
## modification, are permitted only as authorized by the OpenLDAP
|
||||
## Public License.
|
||||
##
|
||||
## A copy of this license is available in the file LICENSE in the
|
||||
## top-level directory of the distribution or, alternatively, at
|
||||
## <http://www.OpenLDAP.org/license.html>.
|
||||
|
||||
echo "running defines.sh"
|
||||
. $SRCDIR/scripts/defines.sh
|
||||
|
||||
echo ""
|
||||
|
||||
if test $BACKASYNCMETA = asyncmetano ; then
|
||||
echo "asyncmeta backend not available, test skipped"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test $BACKLDAP = ldapno ; then
|
||||
echo "ldap backend not available, test skipped"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
rm -rf $TESTDIR
|
||||
|
||||
mkdir -p $TESTDIR $DBDIR1 $DBDIR2
|
||||
|
||||
echo "Starting slapd on TCP/IP port $PORT1..."
|
||||
. $CONFFILTER $BACKEND $MONITORDB < $METACONF1 > $CONF1
|
||||
$SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
|
||||
PID=$!
|
||||
if test $WAIT != 0 ; then
|
||||
echo PID $PID
|
||||
read foo
|
||||
fi
|
||||
KILLPIDS="$PID"
|
||||
|
||||
sleep 1
|
||||
|
||||
echo "Using ldapsearch to check that slapd is running..."
|
||||
for i in 0 1 2 3 4 5; do
|
||||
$LDAPSEARCH -s base -b "$MONITOR" -h $LOCALHOST -p $PORT1 \
|
||||
'objectclass=*' > /dev/null 2>&1
|
||||
RC=$?
|
||||
if test $RC = 0 ; then
|
||||
break
|
||||
fi
|
||||
echo "Waiting 5 seconds for slapd to start..."
|
||||
sleep 5
|
||||
done
|
||||
if test $RC != 0 ; then
|
||||
echo "ldapsearch failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
echo "Using ldapadd to populate the database..."
|
||||
$LDAPADD -D "$MANAGERDN" -h $LOCALHOST -p $PORT1 -w $PASSWD < \
|
||||
$LDIFORDERED > $TESTOUT 2>&1
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "ldapadd failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
echo "Starting slapd on TCP/IP port $PORT2..."
|
||||
. $CONFFILTER $BACKEND $MONITORDB < $METACONF2 > $CONF2
|
||||
$SLAPD -f $CONF2 -h $URI2 -d $LVL $TIMING > $LOG2 2>&1 &
|
||||
PID=$!
|
||||
if test $WAIT != 0 ; then
|
||||
echo PID $PID
|
||||
read foo
|
||||
fi
|
||||
KILLPIDS="$KILLPIDS $PID"
|
||||
|
||||
sleep 1
|
||||
|
||||
echo "Using ldapsearch to check that slapd is running..."
|
||||
for i in 0 1 2 3 4 5; do
|
||||
$LDAPSEARCH -s base -b "$MONITOR" -h $LOCALHOST -p $PORT2 \
|
||||
'objectclass=*' > /dev/null 2>&1
|
||||
RC=$?
|
||||
if test $RC = 0 ; then
|
||||
break
|
||||
fi
|
||||
echo "Waiting 5 seconds for slapd to start..."
|
||||
sleep 5
|
||||
done
|
||||
if test $RC != 0 ; then
|
||||
echo "ldapsearch failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
echo "Using ldapadd to populate the database..."
|
||||
$LDAPADD -D "$METAMANAGERDN" -h $LOCALHOST -p $PORT2 -w $PASSWD < \
|
||||
$LDIFMETA >> $TESTOUT 2>&1
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "ldapadd failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
echo "Starting slapd on TCP/IP port $PORT3..."
|
||||
. $CONFFILTER $BACKEND $MONITORDB < $ASYNCMETACONF > $CONF3
|
||||
$SLAPD -f $CONF3 -h $URI3 -d $LVL $TIMING > $LOG3 2>&1 &
|
||||
PID=$!
|
||||
if test $WAIT != 0 ; then
|
||||
echo PID $PID
|
||||
read foo
|
||||
fi
|
||||
KILLPIDS="$KILLPIDS $PID"
|
||||
|
||||
sleep 1
|
||||
|
||||
echo "Using ldapsearch to check that slapd is running..."
|
||||
for i in 0 1 2 3 4 5; do
|
||||
$LDAPSEARCH -s base -b "$MONITOR" -h $LOCALHOST -p $PORT3 \
|
||||
'objectclass=*' > /dev/null 2>&1
|
||||
RC=$?
|
||||
if test $RC = 0 ; then
|
||||
break
|
||||
fi
|
||||
echo "Waiting 5 seconds for slapd to start..."
|
||||
sleep 5
|
||||
done
|
||||
if test $RC != 0 ; then
|
||||
echo "ldapsearch failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
cat /dev/null > $SEARCHOUT
|
||||
|
||||
BASEDN="o=Example,c=US"
|
||||
echo "Searching base=\"$BASEDN\"..."
|
||||
echo "# searching base=\"$BASEDN\"..." >> $SEARCHOUT
|
||||
$LDAPSEARCH -S "" -h $LOCALHOST -p $PORT3 -b "$BASEDN" >> $SEARCHOUT 2>&1
|
||||
RC=$?
|
||||
#if test $RC != 0 ; then
|
||||
# echo "Search failed ($RC)!"
|
||||
# test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
# exit $RC
|
||||
#fi
|
||||
case $RC in
|
||||
0)
|
||||
;;
|
||||
51)
|
||||
echo "### Hit LDAP_BUSY problem; you may want to re-run the test"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Search failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
;;
|
||||
esac
|
||||
|
||||
# ITS#4195: spurious matchedDN when the search scopes the main target,
|
||||
# and the searchBase is not present, so that target returns noSuchObject
|
||||
BASEDN="ou=Meta,o=Example,c=US"
|
||||
echo "Searching base=\"$BASEDN\"..."
|
||||
echo "# searching base=\"$BASEDN\"..." >> $SEARCHOUT
|
||||
$LDAPSEARCH -S "" -h $LOCALHOST -p $PORT3 -b "$BASEDN" >> $SEARCHOUT 2>&1
|
||||
RC=$?
|
||||
#if test $RC != 0 ; then
|
||||
# echo "Search failed ($RC)!"
|
||||
# test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
# exit $RC
|
||||
#fi
|
||||
case $RC in
|
||||
0)
|
||||
;;
|
||||
51)
|
||||
echo "### Hit LDAP_BUSY problem; you may want to re-run the test"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Search failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
;;
|
||||
esac
|
||||
|
||||
#
|
||||
# Do some modifications
|
||||
#
|
||||
|
||||
BASEDN="o=Example,c=US"
|
||||
echo "Modifying database \"$BASEDN\"..."
|
||||
$LDAPMODIFY -v -D "cn=Manager,$BASEDN" -h $LOCALHOST -p $PORT3 -w $PASSWD \
|
||||
-M >> $TESTOUT 2>&1 << EOMODS
|
||||
# These operations (updates with objectClass mapping) triggered ITS#3499
|
||||
dn: cn=Added Group,ou=Groups,$BASEDN
|
||||
changetype: add
|
||||
objectClass: groupOfNames
|
||||
objectClass: uidObject
|
||||
cn: Added Group
|
||||
member: cn=Added Group,ou=Groups,$BASEDN
|
||||
uid: added
|
||||
|
||||
dn: cn=Another Added Group,ou=Groups,$BASEDN
|
||||
changetype: add
|
||||
objectClass: groupOfNames
|
||||
cn: Another Added Group
|
||||
member: cn=Added Group,ou=Groups,$BASEDN
|
||||
member: cn=Another Added Group,ou=Groups,$BASEDN
|
||||
|
||||
dn: cn=Another Added Group,ou=Groups,$BASEDN
|
||||
changetype: modify
|
||||
add: objectClass
|
||||
objectClass: uidObject
|
||||
-
|
||||
add: uid
|
||||
uid: added
|
||||
-
|
||||
|
||||
dn: cn=Added Group,ou=Groups,$BASEDN
|
||||
changetype: modify
|
||||
delete: objectClass
|
||||
objectClass: uidObject
|
||||
-
|
||||
delete: uid
|
||||
-
|
||||
|
||||
dn: ou=Meta,$BASEDN
|
||||
changetype: modify
|
||||
add: description
|
||||
description: added to "ou=Meta,$BASEDN"
|
||||
-
|
||||
|
||||
dn: ou=Who's going to handle this?,$BASEDN
|
||||
changetype: add
|
||||
objectClass: organizationalUnit
|
||||
ou: Who's going to handle this?
|
||||
description: added
|
||||
description: will be deleted
|
||||
|
||||
dn: ou=Same as above,$BASEDN
|
||||
changetype: add
|
||||
objectClass: organizationalUnit
|
||||
ou: Same as above
|
||||
description: added right after "Who's going to handle this?"
|
||||
description: will be preserved
|
||||
|
||||
dn: ou=Who's going to handle this?,$BASEDN
|
||||
changetype: delete
|
||||
|
||||
dn: ou=Who's going to handle this?,ou=Meta,$BASEDN
|
||||
changetype: add
|
||||
objectClass: organizationalUnit
|
||||
ou: Who's going to handle this?
|
||||
description: added
|
||||
description: will be deleted
|
||||
|
||||
dn: ou=Same as above,ou=Meta,$BASEDN
|
||||
changetype: add
|
||||
objectClass: organizationalUnit
|
||||
ou: Same as above
|
||||
description: added right after "Who's going to handle this?"
|
||||
description: will be preserved
|
||||
|
||||
dn: cn=Added User,ou=Same as above,ou=Meta,$BASEDN
|
||||
changetype: add
|
||||
objectClass: inetOrgPerson
|
||||
cn: Added User
|
||||
sn: User
|
||||
userPassword: secret
|
||||
|
||||
dn: ou=Who's going to handle this?,ou=Meta,$BASEDN
|
||||
changetype: delete
|
||||
EOMODS
|
||||
|
||||
RC=$?
|
||||
#if test $RC != 0 ; then
|
||||
# echo "Modify failed ($RC)!"
|
||||
# test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
# exit $RC
|
||||
#fi
|
||||
case $RC in
|
||||
0)
|
||||
;;
|
||||
51)
|
||||
echo "### Hit LDAP_BUSY problem; you may want to re-run the test"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Modify failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "Searching base=\"$BASEDN\"..."
|
||||
echo "# searching base=\"$BASEDN\"..." >> $SEARCHOUT
|
||||
$LDAPSEARCH -S "" -h $LOCALHOST -p $PORT3 -b "$BASEDN" >> $SEARCHOUT 2>&1
|
||||
RC=$?
|
||||
#if test $RC != 0 ; then
|
||||
# echo "Search failed ($RC)!"
|
||||
# test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
# exit $RC
|
||||
#fi
|
||||
case $RC in
|
||||
0)
|
||||
;;
|
||||
51)
|
||||
echo "### Hit LDAP_BUSY problem; you may want to re-run the test"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Search failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
;;
|
||||
esac
|
||||
|
||||
BASEDN="o=Example,c=US"
|
||||
echo " base=\"$BASEDN\"..."
|
||||
echo "# base=\"$BASEDN\"..." >> $SEARCHOUT
|
||||
$LDAPSEARCH -S "" -h $LOCALHOST -p $PORT3 -b "$BASEDN" -M "$FILTER" '*' ref \
|
||||
>> $SEARCHOUT 2>&1
|
||||
RC=$?
|
||||
#if test $RC != 0 ; then
|
||||
# echo "Search failed ($RC)!"
|
||||
# test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
# exit $RC
|
||||
#fi
|
||||
case $RC in
|
||||
0)
|
||||
;;
|
||||
51)
|
||||
echo "### Hit LDAP_BUSY problem; you may want to re-run the test"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Search failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
;;
|
||||
esac
|
||||
|
||||
BASEDN="o=Example,c=US"
|
||||
FILTER="(seeAlso=cn=all staff,ou=Groups,$BASEDN)"
|
||||
echo "Searching filter=\"$FILTER\""
|
||||
echo " attrs=\"seeAlso\""
|
||||
echo " base=\"$BASEDN\"..."
|
||||
echo "# searching filter=\"$FILTER\"" >> $SEARCHOUT
|
||||
echo "# attrs=\"seeAlso\"" >> $SEARCHOUT
|
||||
echo "# base=\"$BASEDN\"..." >> $SEARCHOUT
|
||||
$LDAPSEARCH -S "" -h $LOCALHOST -p $PORT3 -b "$BASEDN" "$FILTER" seeAlso \
|
||||
>> $SEARCHOUT 2>&1
|
||||
RC=$?
|
||||
#if test $RC != 0 ; then
|
||||
# echo "Search failed ($RC)!"
|
||||
# test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
# exit $RC
|
||||
#fi
|
||||
case $RC in
|
||||
0)
|
||||
;;
|
||||
51)
|
||||
echo "### Hit LDAP_BUSY problem; you may want to re-run the test"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Search failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
;;
|
||||
esac
|
||||
|
||||
FILTER="(uid=example)"
|
||||
echo "Searching filter=\"$FILTER\""
|
||||
echo " attrs=\"uid\""
|
||||
echo " base=\"$BASEDN\"..."
|
||||
echo "# searching filter=\"$FILTER\"" >> $SEARCHOUT
|
||||
echo "# attrs=\"uid\"" >> $SEARCHOUT
|
||||
echo "# base=\"$BASEDN\"..." >> $SEARCHOUT
|
||||
$LDAPSEARCH -S "" -h $LOCALHOST -p $PORT3 -b "$BASEDN" "$FILTER" uid \
|
||||
>> $SEARCHOUT 2>&1
|
||||
RC=$?
|
||||
#if test $RC != 0 ; then
|
||||
# echo "Search failed ($RC)!"
|
||||
# test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
# exit $RC
|
||||
#fi
|
||||
case $RC in
|
||||
0)
|
||||
;;
|
||||
51)
|
||||
echo "### Hit LDAP_BUSY problem; you may want to re-run the test"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Search failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
;;
|
||||
esac
|
||||
|
||||
FILTER="(member=cn=Another Added Group,ou=Groups,$BASEDN)"
|
||||
echo "Searching filter=\"$FILTER\""
|
||||
echo " attrs=\"member\""
|
||||
echo " base=\"$BASEDN\"..."
|
||||
echo "# searching filter=\"$FILTER\"" >> $SEARCHOUT
|
||||
echo "# attrs=\"member\"" >> $SEARCHOUT
|
||||
echo "# base=\"$BASEDN\"..." >> $SEARCHOUT
|
||||
$LDAPSEARCH -S "" -h $LOCALHOST -p $PORT3 -b "$BASEDN" "$FILTER" member \
|
||||
>> $SEARCHOUT 2>&1
|
||||
RC=$?
|
||||
#if test $RC != 0 ; then
|
||||
# echo "Search failed ($RC)!"
|
||||
# test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
# exit $RC
|
||||
#fi
|
||||
case $RC in
|
||||
0)
|
||||
;;
|
||||
51)
|
||||
echo "### Hit LDAP_BUSY problem; you may want to re-run the test"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Search failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "Waiting 10 seconds for cached connections to timeout..."
|
||||
sleep 10
|
||||
|
||||
echo "Searching with a timed out connection..."
|
||||
echo "# searching filter=\"$FILTER\"" >> $SEARCHOUT
|
||||
echo "# attrs=\"member\"" >> $SEARCHOUT
|
||||
echo "# base=\"$BASEDN\"" >> $SEARCHOUT
|
||||
echo "# with a timed out connection..." >> $SEARCHOUT
|
||||
$LDAPSEARCH -S "" -h $LOCALHOST -p $PORT3 -D "cn=Manager,$BASEDN" -w $PASSWD \
|
||||
-b "$BASEDN" "$FILTER" member \
|
||||
>> $SEARCHOUT 2>&1
|
||||
RC=$?
|
||||
#if test $RC != 0 ; then
|
||||
# echo "Search failed ($RC)!"
|
||||
# test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
# exit $RC
|
||||
#fi
|
||||
case $RC in
|
||||
0)
|
||||
;;
|
||||
51)
|
||||
echo "### Hit LDAP_BUSY problem; you may want to re-run the test"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Search failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
;;
|
||||
esac
|
||||
|
||||
# NOTE: cannot send to $SEARCHOUT because the returned entries
|
||||
# are not predictable...
|
||||
echo "Checking server-enforced size limit..."
|
||||
echo "# Checking server-enforced size limit..." >> $SEARCHOUT
|
||||
$LDAPSEARCH -S "" -h $LOCALHOST -p $PORT3 \
|
||||
-D "cn=Bjorn Jensen,ou=Information Technology Division,ou=People,$BASEDN" -w bjorn \
|
||||
-b "$BASEDN" "(objectClass=*)" 1.1 \
|
||||
>> $TESTOUT 2>&1
|
||||
RC=$?
|
||||
case $RC,$BACKEND in
|
||||
4,* | 0,null)
|
||||
;;
|
||||
0,*)
|
||||
echo "Search should have failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit -1
|
||||
;;
|
||||
*)
|
||||
echo "Search failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
;;
|
||||
esac
|
||||
|
||||
# NOTE: cannot send to $SEARCHOUT because the returned entries
|
||||
# are not predictable...
|
||||
echo "Checking client-requested size limit..."
|
||||
echo "# Checking client-requested size limit..." >> $SEARCHOUT
|
||||
$LDAPSEARCH -S "" -h $LOCALHOST -p $PORT3 \
|
||||
-D "cn=Bjorn Jensen,ou=Information Technology Division,ou=People,$BASEDN" -w bjorn \
|
||||
-b "$BASEDN" -z 2 "(objectClass=*)" 1.1 \
|
||||
>> $TESTOUT 2>&1
|
||||
RC=$?
|
||||
case $RC,$BACKEND in
|
||||
4,* | 0,null)
|
||||
;;
|
||||
0,*)
|
||||
echo "Search should have failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit -1
|
||||
;;
|
||||
*)
|
||||
echo "Search failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "Filtering ldapsearch results..."
|
||||
$LDIFFILTER < $SEARCHOUT > $SEARCHFLT
|
||||
echo "Filtering original ldif used to create database..."
|
||||
$LDIFFILTER < $METAOUT > $LDIFFLT
|
||||
echo "Comparing filter output..."
|
||||
$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
|
||||
|
||||
if test $? != 0 ; then
|
||||
echo "comparison failed - meta search/modification didn't succeed"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Binding as newly added user to database \"$BASEDN\"..."
|
||||
$LDAPWHOAMI -h $LOCALHOST -p $PORT3 \
|
||||
-D "cn=Added User,ou=Same as above,ou=Meta,$BASEDN" \
|
||||
-w $PASSWD >> $TESTOUT 2>&1
|
||||
RC=$?
|
||||
#if test $RC != 0 ; then
|
||||
# echo "WhoAmI failed ($RC)!"
|
||||
# test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
# exit $RC
|
||||
#fi
|
||||
case $RC in
|
||||
0)
|
||||
;;
|
||||
51)
|
||||
echo "### Hit LDAP_BUSY problem; you may want to re-run the test"
|
||||
;;
|
||||
*)
|
||||
echo "WhoAmI failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
echo "Binding with incorrect password to database \"$BASEDN\"..."
|
||||
$LDAPWHOAMI -h $LOCALHOST -p $PORT3 \
|
||||
-D "cn=Added User,ou=Same as above,ou=Meta,$BASEDN" \
|
||||
-w bogus >> $TESTOUT 2>&1
|
||||
RC=$?
|
||||
#if test $RC != 0 ; then
|
||||
# echo "WhoAmI failed ($RC)!"
|
||||
# test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
# exit $RC
|
||||
#fi
|
||||
case $RC,$BACKEND in
|
||||
0,null)
|
||||
;;
|
||||
0,*)
|
||||
echo "WhoAmI should have failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit -1
|
||||
;;
|
||||
51,*)
|
||||
echo "### Hit LDAP_BUSY problem; you may want to re-run the test"
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "Binding with non-existing user to database \"$BASEDN\"..."
|
||||
$LDAPWHOAMI -h $LOCALHOST -p $PORT3 \
|
||||
-D "cn=Non-existing User,ou=Same as above,ou=Meta,$BASEDN" \
|
||||
-w bogus >> $TESTOUT 2>&1
|
||||
RC=$?
|
||||
#if test $RC != 0 ; then
|
||||
# echo "WhoAmI failed ($RC)!"
|
||||
# test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
# exit $RC
|
||||
#fi
|
||||
case $RC,$BACKEND in
|
||||
0,null)
|
||||
;;
|
||||
0,*)
|
||||
echo "WhoAmI should have failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit -1
|
||||
;;
|
||||
51,*)
|
||||
echo "### Hit LDAP_BUSY problem; you may want to re-run the test"
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
|
||||
echo ">>>>> Test succeeded"
|
||||
|
||||
test $KILLSERVERS != no && wait
|
||||
|
||||
exit 0
|
||||
242
tests/scripts/test074-asyncmeta-concurrency
Executable file
242
tests/scripts/test074-asyncmeta-concurrency
Executable file
|
|
@ -0,0 +1,242 @@
|
|||
#! /bin/sh
|
||||
# $OpenLDAP$
|
||||
## This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
##
|
||||
## Copyright 1998-2019 The OpenLDAP Foundation.
|
||||
## All rights reserved.
|
||||
##
|
||||
## Redistribution and use in source and binary forms, with or without
|
||||
## modification, are permitted only as authorized by the OpenLDAP
|
||||
## Public License.
|
||||
##
|
||||
## A copy of this license is available in the file LICENSE in the
|
||||
## top-level directory of the distribution or, alternatively, at
|
||||
## <http://www.OpenLDAP.org/license.html>.
|
||||
|
||||
echo "running defines.sh"
|
||||
. $SRCDIR/scripts/defines.sh
|
||||
|
||||
echo ""
|
||||
|
||||
if test $BACKASYNCMETA = asyncmetano ; then
|
||||
echo "asyncmeta backend not available, test skipped"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test $BACKLDAP = ldapno ; then
|
||||
echo "ldap backend not available, test skipped"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test x$TESTLOOPS = x ; then
|
||||
TESTLOOPS=50
|
||||
fi
|
||||
|
||||
if test x$TESTCHILDREN = x ; then
|
||||
TESTCHILDREN=20
|
||||
fi
|
||||
|
||||
rm -rf $TESTDIR
|
||||
|
||||
mkdir -p $TESTDIR $DBDIR1 $DBDIR2
|
||||
|
||||
# NOTE: this could be added to all tests...
|
||||
if test "$BACKEND" = "bdb" || test "$BACKEND" = "hdb" ; then
|
||||
if test "x$DB_CONFIG" != "x" ; then \
|
||||
if test -f $DB_CONFIG ; then
|
||||
echo "==> using DB_CONFIG \"$DB_CONFIG\""
|
||||
cp $DB_CONFIG $DBDIR1
|
||||
cp $DB_CONFIG $DBDIR2
|
||||
else
|
||||
echo "==> DB_CONFIG must point to a valid file (ignored)"
|
||||
fi
|
||||
else
|
||||
echo "==> set \"DB_CONFIG\" to the DB_CONFIG file you want to use for the test."
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
echo "Starting slapd on TCP/IP port $PORT1..."
|
||||
. $CONFFILTER $BACKEND $MONITORDB < $METACONF1 > $CONF1
|
||||
$SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
|
||||
PID=$!
|
||||
if test $WAIT != 0 ; then
|
||||
echo PID $PID
|
||||
read foo
|
||||
fi
|
||||
KILLPIDS="$PID"
|
||||
|
||||
sleep 1
|
||||
|
||||
echo "Using ldapsearch to check that slapd is running..."
|
||||
for i in 0 1 2 3 4 5; do
|
||||
$LDAPSEARCH -s base -b "$MONITOR" -h $LOCALHOST -p $PORT1 \
|
||||
'objectclass=*' > /dev/null 2>&1
|
||||
RC=$?
|
||||
if test $RC = 0 ; then
|
||||
break
|
||||
fi
|
||||
echo "Waiting 5 seconds for slapd to start..."
|
||||
sleep 5
|
||||
done
|
||||
if test $RC != 0 ; then
|
||||
echo "ldapsearch failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
echo "Using ldapadd to populate the database..."
|
||||
$LDAPADD -D "$MANAGERDN" -h $LOCALHOST -p $PORT1 -w $PASSWD < \
|
||||
$LDIFORDERED > $TESTOUT 2>&1
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "ldapadd failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
echo "Starting slapd on TCP/IP port $PORT2..."
|
||||
. $CONFFILTER $BACKEND $MONITORDB < $METACONF2 > $CONF2
|
||||
$SLAPD -f $CONF2 -h $URI2 -d $LVL $TIMING > $LOG2 2>&1 &
|
||||
PID=$!
|
||||
if test $WAIT != 0 ; then
|
||||
echo PID $PID
|
||||
read foo
|
||||
fi
|
||||
KILLPIDS="$KILLPIDS $PID"
|
||||
|
||||
sleep 1
|
||||
|
||||
echo "Using ldapsearch to check that slapd is running..."
|
||||
for i in 0 1 2 3 4 5; do
|
||||
$LDAPSEARCH -s base -b "$MONITOR" -h $LOCALHOST -p $PORT2 \
|
||||
'objectclass=*' > /dev/null 2>&1
|
||||
RC=$?
|
||||
if test $RC = 0 ; then
|
||||
break
|
||||
fi
|
||||
echo "Waiting 5 seconds for slapd to start..."
|
||||
sleep 5
|
||||
done
|
||||
if test $RC != 0 ; then
|
||||
echo "ldapsearch failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
echo "Using ldapadd to populate the database..."
|
||||
$LDAPADD -D "$METAMANAGERDN" -h $LOCALHOST -p $PORT2 -w $PASSWD < \
|
||||
$LDIFMETA >> $TESTOUT 2>&1
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "ldapadd failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
echo "Starting slapd on TCP/IP port $PORT3..."
|
||||
. $CONFFILTER $BACKEND $MONITORDB < $ASYNCMETACONF > $CONF3
|
||||
$SLAPD -f $CONF3 -h $URI3 -d $LVL $TIMING > $LOG3 2>&1 &
|
||||
PID=$!
|
||||
if test $WAIT != 0 ; then
|
||||
echo PID $PID
|
||||
read foo
|
||||
fi
|
||||
KILLPIDS="$KILLPIDS $PID"
|
||||
|
||||
sleep 1
|
||||
|
||||
echo "Using ldapsearch to check that slapd is running..."
|
||||
for i in 0 1 2 3 4 5; do
|
||||
$LDAPSEARCH -s base -b "$MONITOR" -h $LOCALHOST -p $PORT3 \
|
||||
'objectclass=*' > /dev/null 2>&1
|
||||
RC=$?
|
||||
if test $RC = 0 ; then
|
||||
break
|
||||
fi
|
||||
echo "Waiting 5 seconds for slapd to start..."
|
||||
sleep 5
|
||||
done
|
||||
if test $RC != 0 ; then
|
||||
echo "ldapsearch failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
cat /dev/null > $SEARCHOUT
|
||||
|
||||
mkdir -p $TESTDIR/$DATADIR
|
||||
METABASEDN="o=Example,c=US"
|
||||
for f in $DATADIR/do_* ; do
|
||||
sed -e "s;$BASEDN;$METABASEDN;" $f > $TESTDIR/$f
|
||||
done
|
||||
|
||||
# add a read that matches only the local database, but selects
|
||||
# also the remote as candidate; this should be removed to compare
|
||||
# execution times with test008...
|
||||
for f in $TESTDIR/$DATADIR/do_read.* ; do
|
||||
echo "ou=Meta,$METABASEDN" >> $f
|
||||
done
|
||||
|
||||
# add a read that matches a referral in the local database only,
|
||||
# but selects also the remote as candidate; this should be removed
|
||||
# to compare execution times with test008...
|
||||
for f in $TESTDIR/$DATADIR/do_read.* ; do
|
||||
echo "cn=Somewhere,ou=Meta,$METABASEDN" >> $f
|
||||
done
|
||||
|
||||
# add a bind that resolves to a referral
|
||||
for f in $TESTDIR/$DATADIR/do_bind.* ; do
|
||||
echo "cn=Foo,ou=Meta,$METABASEDN" >> $f
|
||||
echo "bar" >> $f
|
||||
echo "" >> $f
|
||||
echo "" >> $f
|
||||
done
|
||||
|
||||
# fix test data to include back-monitor, if available
|
||||
# NOTE: copies do_* files from $TESTDIR/$DATADIR to $TESTDIR
|
||||
$MONITORDATA "$MONITORDB" "$TESTDIR/$DATADIR" "$TESTDIR"
|
||||
|
||||
BINDDN="cn=Manager,o=Local"
|
||||
PASSWD="secret"
|
||||
echo "Using tester for concurrent server access..."
|
||||
$SLAPDTESTER -P "$PROGDIR" -d "$TESTDIR" -h $LOCALHOST -p $PORT3 \
|
||||
-D "$BINDDN" -w $PASSWD -l $TESTLOOPS -j $TESTCHILDREN \
|
||||
-r 20 -i '!REFERRAL' -i '*INVALID_CREDENTIALS' -SS
|
||||
RC=$?
|
||||
|
||||
if test $RC != 0 ; then
|
||||
echo "slapd-tester failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
echo "Using ldapsearch to retrieve all the entries..."
|
||||
$LDAPSEARCH -S "" -b "$METABASEDN" -h $LOCALHOST -p $PORT3 \
|
||||
'objectClass=*' > $SEARCHOUT 2>&1
|
||||
RC=$?
|
||||
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
|
||||
if test $RC != 0 ; then
|
||||
echo "ldapsearch failed ($RC)!"
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
echo "Filtering ldapsearch results..."
|
||||
$LDIFFILTER < $SEARCHOUT > $SEARCHFLT
|
||||
echo "Filtering original ldif used to create database..."
|
||||
$LDIFFILTER < $METACONCURRENCYOUT > $LDIFFLT
|
||||
echo "Comparing filter output..."
|
||||
$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
|
||||
|
||||
if test $? != 0 ; then
|
||||
echo "comparison failed - slapd-asyncmeta search/modification didn't succeed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ">>>>> Test succeeded"
|
||||
|
||||
test $KILLSERVERS != no && wait
|
||||
|
||||
exit 0
|
||||
Loading…
Reference in a new issue