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)
|
.BR poll (2)/ select (2)
|
||||||
following a
|
following a
|
||||||
.BR connect (2)
|
.BR connect (2)
|
||||||
returns in case of no activity.
|
returns in case of no activity while sending an operation to the remote target.
|
||||||
The value is in seconds, and it can be specified as for
|
The value is in milliseconds, and it can be specified as for
|
||||||
.BR idle\-timeout .
|
.BR idle\-timeout .
|
||||||
If set before any target specification, it affects all targets, unless
|
If set before any target specification, it affects all targets, unless
|
||||||
overridden by any per-target directive.
|
overridden by any per-target directive.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B nretries {forever|never|<nretries>}
|
.B nretries {forever|never|<nretries>}
|
||||||
This directive defines how many times a bind should be retried
|
This directive defines how many times forwarding an operation should be retried
|
||||||
in case of temporary failure in contacting a target. If defined
|
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,
|
before any target specification, it applies to all targets (by default,
|
||||||
.BR 3
|
.BR 3
|
||||||
times);
|
times);
|
||||||
|
|
@ -409,11 +411,13 @@ by a target. See
|
||||||
for details.
|
for details.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B suffixmassage "<virtual naming context>" "<real naming context>"
|
.B suffixmassage "<local suffix>" "<remote suffix>"
|
||||||
All the directives starting with "rewrite" refer to the rewrite engine
|
.B slapd\-asyncmeta
|
||||||
that has been added to slapd. See
|
does not support the rewrite engine used by
|
||||||
.B slapd\-meta(5)
|
the LDAP and META backends.
|
||||||
for details.
|
.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
|
.TP
|
||||||
.B t\-f\-support {NO|yes|discover}
|
.B t\-f\-support {NO|yes|discover}
|
||||||
|
|
|
||||||
|
|
@ -19,12 +19,12 @@
|
||||||
## based on back-meta module for inclusion in OpenLDAP Software.
|
## based on back-meta module for inclusion in OpenLDAP Software.
|
||||||
## This work was sponsored by Ericsson
|
## This work was sponsored by Ericsson
|
||||||
|
|
||||||
SRCS = init.c config.c search.c message_queue.c bind.c unbind.c add.c compare.c \
|
SRCS = init.c config.c search.c message_queue.c bind.c add.c compare.c \
|
||||||
delete.c modify.c modrdn.c suffixmassage.c map.c \
|
delete.c modify.c modrdn.c map.c \
|
||||||
conn.c candidates.c dncache.c meta_result.c abandon.c
|
conn.c candidates.c dncache.c meta_result.c
|
||||||
OBJS = init.lo config.lo search.lo message_queue.lo bind.lo unbind.lo add.lo compare.lo \
|
OBJS = init.lo config.lo search.lo message_queue.lo bind.lo add.lo compare.lo \
|
||||||
delete.lo modify.lo modrdn.lo suffixmassage.lo map.lo \
|
delete.lo modify.lo modrdn.lo map.lo \
|
||||||
conn.lo candidates.lo dncache.lo meta_result.lo abandon.lo
|
conn.lo candidates.lo dncache.lo meta_result.lo
|
||||||
|
|
||||||
LDAP_INCDIR= ../../../include
|
LDAP_INCDIR= ../../../include
|
||||||
LDAP_LIBDIR= ../../../libraries
|
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/string.h>
|
||||||
#include <ac/socket.h>
|
#include <ac/socket.h>
|
||||||
|
|
||||||
#include "slap.h"
|
#include "slap.h"
|
||||||
|
#include "../../../libraries/liblber/lber-int.h"
|
||||||
|
#include "../../../libraries/libldap/ldap-int.h"
|
||||||
#include "../back-ldap/back-ldap.h"
|
#include "../back-ldap/back-ldap.h"
|
||||||
#include "back-asyncmeta.h"
|
#include "back-asyncmeta.h"
|
||||||
#include "ldap_rq.h"
|
#include "ldap_rq.h"
|
||||||
#include "../../../libraries/liblber/lber-int.h"
|
|
||||||
#include "../../../libraries/libldap/ldap-int.h"
|
|
||||||
|
|
||||||
void
|
|
||||||
asyncmeta_sender_error(Operation *op,
|
int
|
||||||
SlapReply *rs,
|
asyncmeta_error_cleanup(Operation *op,
|
||||||
slap_callback *cb)
|
SlapReply *rs,
|
||||||
|
bm_context_t *bc,
|
||||||
|
a_metaconn_t *mc,
|
||||||
|
int candidate)
|
||||||
{
|
{
|
||||||
if (cb != NULL) {
|
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||||
op->o_callback = cb;
|
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);
|
send_ldap_result(op, rs);
|
||||||
|
return LDAP_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
meta_search_candidate_t
|
meta_search_candidate_t
|
||||||
|
|
@ -51,195 +61,174 @@ asyncmeta_back_add_start(Operation *op,
|
||||||
SlapReply *rs,
|
SlapReply *rs,
|
||||||
a_metaconn_t *mc,
|
a_metaconn_t *mc,
|
||||||
bm_context_t *bc,
|
bm_context_t *bc,
|
||||||
int candidate)
|
int candidate,
|
||||||
|
int do_lock)
|
||||||
{
|
{
|
||||||
int isupdate;
|
int isupdate;
|
||||||
Attribute *a;
|
Attribute *a;
|
||||||
int i;
|
int i;
|
||||||
LDAPMod **attrs;
|
LDAPMod **attrs;
|
||||||
struct berval mapped;
|
|
||||||
a_dncookie dc;
|
a_dncookie dc;
|
||||||
a_metainfo_t *mi = mc->mc_info;
|
a_metainfo_t *mi = mc->mc_info;
|
||||||
a_metatarget_t *mt = mi->mi_targets[ candidate ];
|
a_metatarget_t *mt = mi->mi_targets[ candidate ];
|
||||||
struct berval mdn;
|
struct berval mdn = {0, NULL};
|
||||||
meta_search_candidate_t retcode = META_SEARCH_CANDIDATE;
|
meta_search_candidate_t retcode = META_SEARCH_CANDIDATE;
|
||||||
BerElement *ber = NULL;
|
BerElement *ber = NULL;
|
||||||
a_metasingleconn_t *msc = &mc->mc_conns[ candidate ];
|
a_metasingleconn_t *msc = &mc->mc_conns[ candidate ];
|
||||||
SlapReply *candidates = bc->candidates;
|
SlapReply *candidates = bc->candidates;
|
||||||
ber_int_t msgid;
|
ber_int_t msgid;
|
||||||
LDAPControl **ctrls = NULL;
|
LDAPControl **ctrls = NULL;
|
||||||
int rc, nretries = 1;
|
int rc;
|
||||||
|
|
||||||
|
|
||||||
|
dc.op = op;
|
||||||
dc.target = mt;
|
dc.target = mt;
|
||||||
dc.conn = op->o_conn;
|
dc.memctx = op->o_tmpmemctx;
|
||||||
dc.rs = rs;
|
dc.to_from = MASSAGE_REQ;
|
||||||
dc.ctx = "addDN";
|
asyncmeta_dn_massage( &dc, &op->o_req_dn, &mdn );
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Count number of attributes in entry ( +1 ) */
|
/* Count number of attributes in entry ( +1 ) */
|
||||||
for ( i = 1, a = op->ora_e->e_attrs; a; i++, a = a->a_next );
|
for ( i = 1, a = op->ora_e->e_attrs; a; i++, a = a->a_next );
|
||||||
|
|
||||||
/* Create array of LDAPMods for ldap_add() */
|
/* 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 );
|
isupdate = be_shadow_update( op );
|
||||||
for ( i = 0, a = op->ora_e->e_attrs; a; a = a->a_next ) {
|
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 )
|
if ( !isupdate && !get_relax( op ) && a->a_desc->ad_type->sat_no_user_mod )
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( a->a_desc == slap_schema.si_ad_objectClass
|
attrs[ i ] = op->o_tmpalloc( sizeof( LDAPMod ), op->o_tmpmemctx );
|
||||||
|| 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 ) );
|
|
||||||
if ( attrs[ i ] == NULL ) {
|
if ( attrs[ i ] == NULL ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
attrs[ i ]->mod_op = LDAP_MOD_BVALUES;
|
attrs[ i ]->mod_op = LDAP_MOD_BVALUES;
|
||||||
attrs[ i ]->mod_type = mapped.bv_val;
|
attrs[ i ]->mod_type = a->a_desc->ad_cname.bv_val;
|
||||||
|
j = a->a_numvals;
|
||||||
if ( is_oc ) {
|
attrs[ i ]->mod_bvalues = op->o_tmpalloc( ( j + 1 ) * sizeof( struct berval * ), op->o_tmpmemctx );
|
||||||
for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); j++ );
|
for (j=0; j<a->a_numvals; j++) {
|
||||||
|
attrs[ i ]->mod_bvalues[ j ] = op->o_tmpalloc( sizeof( struct berval ), op->o_tmpmemctx );
|
||||||
attrs[ i ]->mod_bvalues =
|
if ( a->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
|
||||||
(struct berval **)ch_malloc( ( j + 1 ) *
|
asyncmeta_dn_massage( &dc, &a->a_vals[ j ], attrs[ i ]->mod_bvalues[ j ] );
|
||||||
sizeof( struct berval * ) );
|
else
|
||||||
for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); ) {
|
*attrs[ i ]->mod_bvalues[ j ] = 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_bvalues[ j ] = NULL;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
attrs[ i ] = NULL;
|
attrs[ i ] = NULL;
|
||||||
|
|
||||||
retry:;
|
asyncmeta_set_msc_time(msc);
|
||||||
|
|
||||||
ctrls = op->o_ctrls;
|
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;
|
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||||
retcode = META_SEARCH_ERR;
|
retcode = META_SEARCH_ERR;
|
||||||
goto done;
|
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);
|
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) {
|
if (ber) {
|
||||||
candidates[ candidate ].sr_msgid = msgid;
|
struct timeval tv = {0, mt->mt_network_timeout*1000};
|
||||||
rc = ldap_send_initial_request( msc->msc_ld, LDAP_REQ_ADD,
|
ber_socket_t s;
|
||||||
mdn.bv_val, ber, msgid );
|
if (!( LDAP_BACK_CONN_ISBOUND( msc )
|
||||||
if (rc == msgid)
|
|| LDAP_BACK_CONN_ISANON( msc )) || msc->msc_ld == NULL ) {
|
||||||
rc = LDAP_SUCCESS;
|
Debug( asyncmeta_debug, "msc %p not initialized at %s:%d\n", msc, __FILE__, __LINE__ );
|
||||||
else
|
goto error_unavailable;
|
||||||
rc = LDAP_SERVER_DOWN;
|
}
|
||||||
|
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 ) {
|
switch ( rc ) {
|
||||||
case LDAP_SUCCESS:
|
case LDAP_SUCCESS:
|
||||||
retcode = META_SEARCH_CANDIDATE;
|
retcode = META_SEARCH_CANDIDATE;
|
||||||
asyncmeta_set_msc_time(msc);
|
asyncmeta_set_msc_time(msc);
|
||||||
break;
|
goto done;
|
||||||
|
|
||||||
case LDAP_SERVER_DOWN:
|
case LDAP_SERVER_DOWN:
|
||||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
/* do not lock if called from asyncmeta_handle_bind_result. Also do not reset the connection */
|
||||||
asyncmeta_clear_one_msc(NULL, mc, candidate);
|
if (do_lock > 0) {
|
||||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||||
if ( nretries && asyncmeta_retry( op, rs, &mc, candidate, LDAP_BACK_DONTSEND ) ) {
|
asyncmeta_reset_msc(NULL, mc, candidate, 0, __FUNCTION__);
|
||||||
nretries = 0;
|
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||||
/* if the identity changed, there might be need to re-authz */
|
|
||||||
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
|
||||||
goto retry;
|
|
||||||
}
|
}
|
||||||
|
/* fall though*/
|
||||||
default:
|
default:
|
||||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
Debug( asyncmeta_debug, "msc %p ldap_send_initial_request failed. %s:%d\n", msc, __FILE__, __LINE__ );
|
||||||
retcode = META_SEARCH_ERR;
|
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 );
|
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
||||||
|
|
||||||
for ( --i; i >= 0; --i ) {
|
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
|
||||||
free( attrs[ i ]->mod_bvalues );
|
op->o_tmpfree( mdn.bv_val, op->o_tmpmemctx );
|
||||||
free( attrs[ i ] );
|
|
||||||
}
|
|
||||||
free( attrs );
|
|
||||||
if ( mdn.bv_val != op->ora_e->e_dn ) {
|
|
||||||
free( mdn.bv_val );
|
|
||||||
BER_BVZERO( &mdn );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
doreturn:;
|
|
||||||
Debug( LDAP_DEBUG_TRACE, "%s <<< asyncmeta_back_add_start[%p]=%d\n", op->o_log_prefix, msc, candidates[candidate].sr_msgid );
|
Debug( LDAP_DEBUG_TRACE, "%s <<< asyncmeta_back_add_start[%p]=%d\n", op->o_log_prefix, msc, candidates[candidate].sr_msgid );
|
||||||
return retcode;
|
return retcode;
|
||||||
}
|
}
|
||||||
|
|
@ -252,26 +241,31 @@ asyncmeta_back_add( Operation *op, SlapReply *rs )
|
||||||
a_metatarget_t *mt;
|
a_metatarget_t *mt;
|
||||||
a_metaconn_t *mc;
|
a_metaconn_t *mc;
|
||||||
int rc, candidate = -1;
|
int rc, candidate = -1;
|
||||||
OperationBuffer opbuf;
|
void *thrctx = op->o_threadctx;
|
||||||
bm_context_t *bc;
|
bm_context_t *bc;
|
||||||
SlapReply *candidates;
|
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 );
|
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) {
|
if (bc == NULL) {
|
||||||
rs->sr_err = LDAP_OTHER;
|
rs->sr_err = LDAP_OTHER;
|
||||||
asyncmeta_sender_error(op, rs, cb);
|
send_ldap_result(op, rs);
|
||||||
return rs->sr_err;
|
return rs->sr_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
candidates = bc->candidates;
|
candidates = bc->candidates;
|
||||||
mc = asyncmeta_getconn( op, rs, candidates, &candidate, LDAP_BACK_DONTSEND, 0);
|
mc = asyncmeta_getconn( op, rs, candidates, &candidate, LDAP_BACK_DONTSEND, 0);
|
||||||
if ( !mc || rs->sr_err != LDAP_SUCCESS) {
|
if ( !mc || rs->sr_err != LDAP_SUCCESS) {
|
||||||
asyncmeta_sender_error(op, rs, cb);
|
send_ldap_result(op, rs);
|
||||||
asyncmeta_clear_bm_context(bc);
|
|
||||||
return rs->sr_err;
|
return rs->sr_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -280,16 +274,39 @@ asyncmeta_back_add( Operation *op, SlapReply *rs )
|
||||||
bc->retrying = LDAP_BACK_RETRYING;
|
bc->retrying = LDAP_BACK_RETRYING;
|
||||||
bc->sendok = ( LDAP_BACK_SENDRESULT | bc->retrying );
|
bc->sendok = ( LDAP_BACK_SENDRESULT | bc->retrying );
|
||||||
bc->stoptime = op->o_time + bc->timeout;
|
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);
|
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||||
rc = asyncmeta_add_message_queue(mc, bc);
|
rc = asyncmeta_add_message_queue(mc, bc);
|
||||||
|
mc->mc_conns[candidate].msc_active++;
|
||||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||||
|
|
||||||
if (rc != LDAP_SUCCESS) {
|
if (rc != LDAP_SUCCESS) {
|
||||||
rs->sr_err = LDAP_BUSY;
|
rs->sr_err = LDAP_BUSY;
|
||||||
rs->sr_text = "Maximum pending ops limit exceeded";
|
rs->sr_text = "Maximum pending ops limit exceeded";
|
||||||
asyncmeta_clear_bm_context(bc);
|
send_ldap_result(op, rs);
|
||||||
asyncmeta_sender_error(op, rs, cb);
|
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;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -298,72 +315,49 @@ asyncmeta_back_add( Operation *op, SlapReply *rs )
|
||||||
{
|
{
|
||||||
case META_SEARCH_CANDIDATE:
|
case META_SEARCH_CANDIDATE:
|
||||||
/* target is already bound, just send the request */
|
/* target is already bound, just send the request */
|
||||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_add: "
|
Debug(LDAP_DEBUG_TRACE , "%s asyncmeta_back_add: "
|
||||||
"cnd=\"%ld\"\n", op->o_log_prefix, candidate );
|
"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) {
|
if (rc == META_SEARCH_ERR) {
|
||||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||||
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;
|
goto finish;
|
||||||
|
|
||||||
|
} else if (rc == META_SEARCH_NEED_BIND) {
|
||||||
|
goto retry;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case META_SEARCH_NOT_CANDIDATE:
|
case META_SEARCH_NOT_CANDIDATE:
|
||||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_add: NOT_CANDIDATE "
|
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_add: NOT_CANDIDATE "
|
||||||
"cnd=\"%ld\"\n", op->o_log_prefix, candidate );
|
"cnd=\"%d\"\n", op->o_log_prefix, candidate );
|
||||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||||
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;
|
goto finish;
|
||||||
|
|
||||||
case META_SEARCH_NEED_BIND:
|
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:
|
case META_SEARCH_BINDING:
|
||||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_add: BINDING "
|
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_add: 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
|
/* add the context to the message queue but do not send the request
|
||||||
the receiver must send this when we are done binding */
|
the receiver must send this when we are done binding */
|
||||||
/* question - how would do receiver know to which targets??? */
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case META_SEARCH_ERR:
|
case META_SEARCH_ERR:
|
||||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_add: ERR "
|
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_add: ERR "
|
||||||
"cnd=\"%ldd\"\n", op->o_log_prefix, candidate );
|
"cnd=\"%d\"\n", op->o_log_prefix, candidate );
|
||||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||||
candidates[ candidate ].sr_type = REP_RESULT;
|
goto finish;
|
||||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
default:
|
||||||
asyncmeta_drop_bc(mc, bc);
|
assert( 0 );
|
||||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
break;
|
||||||
asyncmeta_sender_error(op, rs, cb);
|
}
|
||||||
asyncmeta_clear_bm_context(bc);
|
|
||||||
goto finish;
|
|
||||||
default:
|
|
||||||
assert( 0 );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||||
|
mc->mc_conns[candidate].msc_active--;
|
||||||
asyncmeta_start_one_listener(mc, candidates, bc, candidate);
|
asyncmeta_start_one_listener(mc, candidates, bc, candidate);
|
||||||
|
bc->bc_active--;
|
||||||
|
asyncmeta_memctx_toggle(thrctx);
|
||||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||||
|
rs->sr_err = SLAPD_ASYNCOP;
|
||||||
finish:
|
finish:
|
||||||
return rs->sr_err;
|
return rs->sr_err;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,18 +27,12 @@
|
||||||
#ifndef SLAPD_ASYNCMETA_H
|
#ifndef SLAPD_ASYNCMETA_H
|
||||||
#define SLAPD_ASYNCMETA_H
|
#define SLAPD_ASYNCMETA_H
|
||||||
|
|
||||||
#ifndef ENABLE_REWRITE
|
|
||||||
#error "--enable-rewrite is required!"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef LDAP_DEVEL
|
#ifdef LDAP_DEVEL
|
||||||
#define SLAPD_META_CLIENT_PR 1
|
#define SLAPD_META_CLIENT_PR 1
|
||||||
#endif /* LDAP_DEVEL */
|
#endif /* LDAP_DEVEL */
|
||||||
|
|
||||||
#include "proto-asyncmeta.h"
|
#include "proto-asyncmeta.h"
|
||||||
|
|
||||||
/* String rewrite library */
|
|
||||||
#include "rewrite.h"
|
|
||||||
#include "ldap_rq.h"
|
#include "ldap_rq.h"
|
||||||
|
|
||||||
LDAP_BEGIN_DECL
|
LDAP_BEGIN_DECL
|
||||||
|
|
@ -50,108 +44,6 @@ LDAP_BEGIN_DECL
|
||||||
#define META_BACK_PRINT_CONNTREE 0
|
#define META_BACK_PRINT_CONNTREE 0
|
||||||
#endif /* !META_BACK_PRINT_CONNTREE */
|
#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:
|
* 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_INITED (0x00100000U)
|
||||||
#define META_BACK_FCONN_CREATING (0x00200000U)
|
#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(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)
|
#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_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_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_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_metainfo_t;
|
||||||
struct a_metaconn_t;
|
struct a_metaconn_t;
|
||||||
|
|
@ -190,20 +86,25 @@ struct a_metatarget_t;
|
||||||
#define META_RETRYING ((ber_tag_t)0x4)
|
#define META_RETRYING ((ber_tag_t)0x4)
|
||||||
|
|
||||||
typedef struct bm_context_t {
|
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 timeout;
|
||||||
time_t stoptime;
|
time_t stoptime;
|
||||||
ldap_back_send_t sendok;
|
ldap_back_send_t sendok;
|
||||||
ldap_back_send_t retrying;
|
ldap_back_send_t retrying;
|
||||||
int candidate_match;
|
int candidate_match;
|
||||||
int sent;
|
volatile int bc_active;
|
||||||
int bc_active;
|
|
||||||
int searchtime; /* stoptime is a search timelimit */
|
int searchtime; /* stoptime is a search timelimit */
|
||||||
int is_ok;
|
int is_ok;
|
||||||
|
int is_root;
|
||||||
|
volatile sig_atomic_t bc_invalid;
|
||||||
SlapReply rs;
|
SlapReply rs;
|
||||||
Operation *op;
|
Operation *op;
|
||||||
|
Operation copy_op;
|
||||||
LDAPControl **ctrls;
|
LDAPControl **ctrls;
|
||||||
int *msgids;
|
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;
|
SlapReply *candidates;
|
||||||
} bm_context_t;
|
} bm_context_t;
|
||||||
|
|
||||||
|
|
@ -226,14 +127,16 @@ typedef struct a_metasingleconn_t {
|
||||||
LDAP *msc_ld;
|
LDAP *msc_ld;
|
||||||
LDAP *msc_ldr;
|
LDAP *msc_ldr;
|
||||||
time_t msc_time;
|
time_t msc_time;
|
||||||
|
time_t msc_binding_time;
|
||||||
|
time_t msc_result_time;
|
||||||
struct berval msc_bound_ndn;
|
struct berval msc_bound_ndn;
|
||||||
struct berval msc_cred;
|
struct berval msc_cred;
|
||||||
unsigned msc_mscflags;
|
unsigned msc_mscflags;
|
||||||
|
|
||||||
/* NOTE: lc_lcflags is redefined to msc_mscflags to reuse the macros
|
/* NOTE: lc_lcflags is redefined to msc_mscflags to reuse the macros
|
||||||
* defined for back-ldap */
|
* defined for back-ldap */
|
||||||
#define lc_lcflags msc_mscflags
|
#define lc_lcflags msc_mscflags
|
||||||
int msc_pending_ops;
|
volatile int msc_active;
|
||||||
int msc_timeout_ops;
|
|
||||||
/* Connection for the select */
|
/* Connection for the select */
|
||||||
Connection *conn;
|
Connection *conn;
|
||||||
} a_metasingleconn_t;
|
} a_metasingleconn_t;
|
||||||
|
|
@ -267,7 +170,7 @@ typedef struct a_metaconn_t {
|
||||||
int pending_ops;
|
int pending_ops;
|
||||||
ldap_pvt_thread_mutex_t mc_om_mutex;
|
ldap_pvt_thread_mutex_t mc_om_mutex;
|
||||||
/* queue for pending operations */
|
/* 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 */
|
/* supersedes the connection stuff */
|
||||||
a_metasingleconn_t *mc_conns;
|
a_metasingleconn_t *mc_conns;
|
||||||
} a_metaconn_t;
|
} a_metaconn_t;
|
||||||
|
|
@ -309,7 +212,7 @@ typedef struct a_metacommon_t {
|
||||||
#define META_RETRY_UNDEFINED (-2)
|
#define META_RETRY_UNDEFINED (-2)
|
||||||
#define META_RETRY_FOREVER (-1)
|
#define META_RETRY_FOREVER (-1)
|
||||||
#define META_RETRY_NEVER (0)
|
#define META_RETRY_NEVER (0)
|
||||||
#define META_RETRY_DEFAULT (10)
|
#define META_RETRY_DEFAULT (2)
|
||||||
|
|
||||||
unsigned mc_flags;
|
unsigned mc_flags;
|
||||||
#define META_BACK_CMN_ISSET(mc,f) ( ( (mc)->mc_flags & (f) ) == (f) )
|
#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_psuffix; /* pretty suffix */
|
||||||
struct berval mt_nsuffix; /* normalized 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_binddn;
|
||||||
struct berval mt_bindpw;
|
struct berval mt_bindpw;
|
||||||
|
|
||||||
|
|
@ -379,8 +285,6 @@ typedef struct a_metatarget_t {
|
||||||
#define mt_idassert_flags mt_idassert.si_flags
|
#define mt_idassert_flags mt_idassert.si_flags
|
||||||
#define mt_idassert_authz mt_idassert.si_authz
|
#define mt_idassert_authz mt_idassert.si_authz
|
||||||
|
|
||||||
struct ldaprwmap mt_rwmap;
|
|
||||||
|
|
||||||
sig_atomic_t mt_isquarantined;
|
sig_atomic_t mt_isquarantined;
|
||||||
ldap_pvt_thread_mutex_t mt_quarantine_mutex;
|
ldap_pvt_thread_mutex_t mt_quarantine_mutex;
|
||||||
|
|
||||||
|
|
@ -520,6 +424,7 @@ typedef struct a_metainfo_t {
|
||||||
int mi_next_conn;
|
int mi_next_conn;
|
||||||
a_metaconn_t *mi_conns;
|
a_metaconn_t *mi_conns;
|
||||||
|
|
||||||
|
struct berval mi_suffix;
|
||||||
} a_metainfo_t;
|
} a_metainfo_t;
|
||||||
|
|
||||||
typedef enum meta_op_type {
|
typedef enum meta_op_type {
|
||||||
|
|
@ -528,6 +433,33 @@ typedef enum meta_op_type {
|
||||||
META_OP_REQUIRE_ALL
|
META_OP_REQUIRE_ALL
|
||||||
} meta_op_type;
|
} 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 *
|
extern a_metaconn_t *
|
||||||
asyncmeta_getconn(
|
asyncmeta_getconn(
|
||||||
Operation *op,
|
Operation *op,
|
||||||
|
|
@ -537,17 +469,6 @@ asyncmeta_getconn(
|
||||||
ldap_back_send_t sendok,
|
ldap_back_send_t sendok,
|
||||||
int alloc_new);
|
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
|
extern int
|
||||||
asyncmeta_init_one_conn(
|
asyncmeta_init_one_conn(
|
||||||
|
|
@ -566,24 +487,6 @@ asyncmeta_quarantine(
|
||||||
SlapReply *rs,
|
SlapReply *rs,
|
||||||
int candidate );
|
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
|
extern int
|
||||||
asyncmeta_proxy_authz_cred(
|
asyncmeta_proxy_authz_cred(
|
||||||
a_metaconn_t *mc,
|
a_metaconn_t *mc,
|
||||||
|
|
@ -595,31 +498,13 @@ asyncmeta_proxy_authz_cred(
|
||||||
struct berval *bindcred,
|
struct berval *bindcred,
|
||||||
int *method );
|
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
|
extern int
|
||||||
asyncmeta_controls_add(
|
asyncmeta_controls_add(
|
||||||
Operation *op,
|
Operation *op,
|
||||||
SlapReply *rs,
|
SlapReply *rs,
|
||||||
a_metaconn_t *mc,
|
a_metaconn_t *mc,
|
||||||
int candidate,
|
int candidate,
|
||||||
|
int isroot,
|
||||||
LDAPControl ***pctrls );
|
LDAPControl ***pctrls );
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
|
|
@ -682,9 +567,6 @@ asyncmeta_dncache_delete_entry(
|
||||||
extern void
|
extern void
|
||||||
asyncmeta_dncache_free( void *entry );
|
asyncmeta_dncache_free( void *entry );
|
||||||
|
|
||||||
extern void
|
|
||||||
asyncmeta_back_map_free( struct ldapmap *lm );
|
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
asyncmeta_subtree_destroy( a_metasubtree_t *ms );
|
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);
|
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(a_metaconn_t *mc, bm_context_t *bc);
|
||||||
|
void asyncmeta_drop_bc_from_fconn(bm_context_t *bc);
|
||||||
|
|
||||||
bm_context_t *
|
bm_context_t *
|
||||||
asyncmeta_find_message(ber_int_t msgid, a_metaconn_t *mc, int candidate);
|
asyncmeta_find_message(ber_int_t msgid, a_metaconn_t *mc, int candidate);
|
||||||
|
|
||||||
bm_context_t *
|
void asyncmeta_memctx_toggle(void *thrctx);
|
||||||
asyncmeta_find_message_by_opmsguid(ber_int_t msgid, a_metaconn_t *mc, int remove);
|
|
||||||
|
|
||||||
void* asyncmeta_op_handle_result(void *ctx, void *arg);
|
void* asyncmeta_op_handle_result(void *ctx, void *arg);
|
||||||
int asyncmeta_back_cleanup( Operation *op, SlapReply *rs, bm_context_t *bm );
|
int asyncmeta_back_cleanup( Operation *op, SlapReply *rs, bm_context_t *bm );
|
||||||
|
|
@ -738,16 +620,19 @@ int
|
||||||
asyncmeta_clear_one_msc(
|
asyncmeta_clear_one_msc(
|
||||||
Operation *op,
|
Operation *op,
|
||||||
a_metaconn_t *msc,
|
a_metaconn_t *msc,
|
||||||
int candidate );
|
int candidate,
|
||||||
|
int unbind,
|
||||||
|
const char * caller);
|
||||||
|
|
||||||
a_metaconn_t *
|
a_metaconn_t *
|
||||||
asyncmeta_get_next_mc( a_metainfo_t *mi );
|
asyncmeta_get_next_mc( a_metainfo_t *mi );
|
||||||
|
|
||||||
void* asyncmeta_timeout_loop(void *ctx, void *arg);
|
void* asyncmeta_timeout_loop(void *ctx, void *arg);
|
||||||
|
|
||||||
int
|
int
|
||||||
asyncmeta_start_timeout_loop(a_metatarget_t *mt, a_metainfo_t *mi);
|
asyncmeta_start_timeout_loop(a_metatarget_t *mt, a_metainfo_t *mi);
|
||||||
|
|
||||||
void asyncmeta_set_msc_time(a_metasingleconn_t *msc);
|
void asyncmeta_set_msc_time(a_metasingleconn_t *msc);
|
||||||
void asyncmeta_clear_message_queue(a_metasingleconn_t *msc);
|
|
||||||
|
|
||||||
int asyncmeta_back_cancel(
|
int asyncmeta_back_cancel(
|
||||||
a_metaconn_t *mc,
|
a_metaconn_t *mc,
|
||||||
|
|
@ -755,25 +640,15 @@ int asyncmeta_back_cancel(
|
||||||
ber_int_t msgid,
|
ber_int_t msgid,
|
||||||
int candidate );
|
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
|
void
|
||||||
asyncmeta_send_result(bm_context_t* bc, int error, char *text);
|
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_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);
|
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,
|
bm_context_t *bc,
|
||||||
int candidate,
|
int candidate,
|
||||||
struct berval *prcookie,
|
struct berval *prcookie,
|
||||||
ber_int_t prsize );
|
ber_int_t prsize,
|
||||||
|
int do_lock);
|
||||||
|
|
||||||
meta_search_candidate_t
|
meta_search_candidate_t
|
||||||
asyncmeta_dobind_init(
|
asyncmeta_dobind_init(
|
||||||
|
|
@ -808,40 +684,97 @@ asyncmeta_back_add_start(Operation *op,
|
||||||
SlapReply *rs,
|
SlapReply *rs,
|
||||||
a_metaconn_t *mc,
|
a_metaconn_t *mc,
|
||||||
bm_context_t *bc,
|
bm_context_t *bc,
|
||||||
int candidate);
|
int candidate,
|
||||||
|
int do_lock);
|
||||||
meta_search_candidate_t
|
meta_search_candidate_t
|
||||||
asyncmeta_back_modify_start(Operation *op,
|
asyncmeta_back_modify_start(Operation *op,
|
||||||
SlapReply *rs,
|
SlapReply *rs,
|
||||||
a_metaconn_t *mc,
|
a_metaconn_t *mc,
|
||||||
bm_context_t *bc,
|
bm_context_t *bc,
|
||||||
int candidate);
|
int candidate,
|
||||||
|
int do_lock);
|
||||||
|
|
||||||
meta_search_candidate_t
|
meta_search_candidate_t
|
||||||
asyncmeta_back_modrdn_start(Operation *op,
|
asyncmeta_back_modrdn_start(Operation *op,
|
||||||
SlapReply *rs,
|
SlapReply *rs,
|
||||||
a_metaconn_t *mc,
|
a_metaconn_t *mc,
|
||||||
bm_context_t *bc,
|
bm_context_t *bc,
|
||||||
int candidate);
|
int candidate,
|
||||||
|
int do_lock);
|
||||||
meta_search_candidate_t
|
meta_search_candidate_t
|
||||||
asyncmeta_back_delete_start(Operation *op,
|
asyncmeta_back_delete_start(Operation *op,
|
||||||
SlapReply *rs,
|
SlapReply *rs,
|
||||||
a_metaconn_t *mc,
|
a_metaconn_t *mc,
|
||||||
bm_context_t *bc,
|
bm_context_t *bc,
|
||||||
int candidate);
|
int candidate,
|
||||||
|
int do_lock);
|
||||||
|
|
||||||
meta_search_candidate_t
|
meta_search_candidate_t
|
||||||
asyncmeta_back_compare_start(Operation *op,
|
asyncmeta_back_compare_start(Operation *op,
|
||||||
SlapReply *rs,
|
SlapReply *rs,
|
||||||
a_metaconn_t *mc,
|
a_metaconn_t *mc,
|
||||||
bm_context_t *bc,
|
bm_context_t *bc,
|
||||||
int candidate);
|
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
|
void
|
||||||
asyncmeta_sender_error(Operation *op,
|
asyncmeta_back_conn_free(
|
||||||
SlapReply *rs,
|
void *v_mc );
|
||||||
slap_callback *cb);
|
|
||||||
|
|
||||||
|
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
|
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 ) {
|
if ( candidate == META_TARGET_NONE ) {
|
||||||
candidate = i;
|
candidate = i;
|
||||||
|
|
||||||
} else {
|
|
||||||
return META_TARGET_MULTIPLE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -239,50 +237,3 @@ asyncmeta_clear_unused_candidates(
|
||||||
|
|
||||||
return 0;
|
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/string.h>
|
||||||
#include <ac/socket.h>
|
#include <ac/socket.h>
|
||||||
|
|
||||||
#include "slap.h"
|
#include "slap.h"
|
||||||
#include "../back-ldap/back-ldap.h"
|
|
||||||
#include "back-asyncmeta.h"
|
|
||||||
#include "../../../libraries/liblber/lber-int.h"
|
#include "../../../libraries/liblber/lber-int.h"
|
||||||
#include "../../../libraries/libldap/ldap-int.h"
|
#include "../../../libraries/libldap/ldap-int.h"
|
||||||
|
#include "../back-ldap/back-ldap.h"
|
||||||
|
#include "back-asyncmeta.h"
|
||||||
|
|
||||||
meta_search_candidate_t
|
meta_search_candidate_t
|
||||||
asyncmeta_back_compare_start(Operation *op,
|
asyncmeta_back_compare_start(Operation *op,
|
||||||
SlapReply *rs,
|
SlapReply *rs,
|
||||||
a_metaconn_t *mc,
|
a_metaconn_t *mc,
|
||||||
bm_context_t *bc,
|
bm_context_t *bc,
|
||||||
int candidate)
|
int candidate,
|
||||||
|
int do_lock)
|
||||||
{
|
{
|
||||||
a_dncookie dc;
|
a_dncookie dc;
|
||||||
a_metainfo_t *mi = mc->mc_info;
|
a_metainfo_t *mi = mc->mc_info;
|
||||||
a_metatarget_t *mt = mi->mi_targets[ candidate ];
|
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 mdn = BER_BVNULL;
|
||||||
struct berval mapped_attr = op->orc_ava->aa_desc->ad_cname;
|
|
||||||
struct berval mapped_value = op->orc_ava->aa_value;
|
struct berval mapped_value = op->orc_ava->aa_value;
|
||||||
int rc = 0, nretries = 1;
|
int rc = 0;
|
||||||
LDAPControl **ctrls = NULL;
|
LDAPControl **ctrls = NULL;
|
||||||
meta_search_candidate_t retcode = META_SEARCH_CANDIDATE;
|
meta_search_candidate_t retcode = META_SEARCH_CANDIDATE;
|
||||||
BerElement *ber = NULL;
|
BerElement *ber = NULL;
|
||||||
|
|
@ -54,117 +54,125 @@ asyncmeta_back_compare_start(Operation *op,
|
||||||
SlapReply *candidates = bc->candidates;
|
SlapReply *candidates = bc->candidates;
|
||||||
ber_int_t msgid;
|
ber_int_t msgid;
|
||||||
|
|
||||||
|
dc.op = op;
|
||||||
dc.target = mt;
|
dc.target = mt;
|
||||||
dc.conn = op->o_conn;
|
dc.memctx = op->o_tmpmemctx;
|
||||||
dc.rs = rs;
|
dc.to_from = MASSAGE_REQ;
|
||||||
dc.ctx = "compareDN";
|
|
||||||
|
|
||||||
switch ( asyncmeta_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
|
||||||
* if attr is objectClass, try to remap the value
|
asyncmeta_dn_massage( &dc, &op->orc_ava->aa_value, &mapped_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 ( BER_BVISNULL( &mapped_value ) || BER_BVISEMPTY( &mapped_value ) ) {
|
asyncmeta_set_msc_time(msc);
|
||||||
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:;
|
|
||||||
ctrls = op->o_ctrls;
|
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;
|
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||||
retcode = META_SEARCH_ERR;
|
retcode = META_SEARCH_ERR;
|
||||||
goto done;
|
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);
|
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) {
|
if (ber) {
|
||||||
candidates[ candidate ].sr_msgid = msgid;
|
struct timeval tv = {0, mt->mt_network_timeout*1000};
|
||||||
rc = ldap_send_initial_request( msc->msc_ld, LDAP_REQ_COMPARE,
|
ber_socket_t s;
|
||||||
mdn.bv_val, ber, msgid );
|
if (!( LDAP_BACK_CONN_ISBOUND( msc )
|
||||||
if (rc == msgid)
|
|| LDAP_BACK_CONN_ISANON( msc )) || msc->msc_ld == NULL ) {
|
||||||
rc = LDAP_SUCCESS;
|
Debug( asyncmeta_debug, "msc %p not initialized at %s:%d\n", msc, __FILE__, __LINE__ );
|
||||||
else
|
goto error_unavailable;
|
||||||
rc = LDAP_SERVER_DOWN;
|
}
|
||||||
|
|
||||||
|
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 ) {
|
switch ( rc ) {
|
||||||
case LDAP_SUCCESS:
|
case LDAP_SUCCESS:
|
||||||
retcode = META_SEARCH_CANDIDATE;
|
retcode = META_SEARCH_CANDIDATE;
|
||||||
asyncmeta_set_msc_time(msc);
|
asyncmeta_set_msc_time(msc);
|
||||||
break;
|
goto done;
|
||||||
|
|
||||||
case LDAP_SERVER_DOWN:
|
case LDAP_SERVER_DOWN:
|
||||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
/* do not lock if called from asyncmeta_handle_bind_result. Also do not reset the connection */
|
||||||
asyncmeta_clear_one_msc(NULL, mc, candidate);
|
if (do_lock > 0) {
|
||||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||||
if ( nretries && asyncmeta_retry( op, rs, &mc, candidate, LDAP_BACK_DONTSEND ) ) {
|
asyncmeta_reset_msc(NULL, mc, candidate, 0, __FUNCTION__);
|
||||||
nretries = 0;
|
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||||
/* if the identity changed, there might be need to re-authz */
|
|
||||||
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
|
||||||
goto retry;
|
|
||||||
}
|
}
|
||||||
|
/* fall though*/
|
||||||
default:
|
default:
|
||||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
Debug( asyncmeta_debug, "msc %p ldap_send_initial_request failed. %s:%d\n", msc, __FILE__, __LINE__ );
|
||||||
retcode = META_SEARCH_ERR;
|
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:
|
done:
|
||||||
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
(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 ) {
|
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 );
|
Debug( LDAP_DEBUG_TRACE, "%s <<< asyncmeta_back_compare_start[%p]=%d\n", op->o_log_prefix, msc, candidates[candidate].sr_msgid );
|
||||||
return retcode;
|
return retcode;
|
||||||
}
|
}
|
||||||
|
|
@ -176,26 +184,30 @@ asyncmeta_back_compare( Operation *op, SlapReply *rs )
|
||||||
a_metatarget_t *mt;
|
a_metatarget_t *mt;
|
||||||
a_metaconn_t *mc;
|
a_metaconn_t *mc;
|
||||||
int rc, candidate = -1;
|
int rc, candidate = -1;
|
||||||
OperationBuffer opbuf;
|
void *thrctx = op->o_threadctx;
|
||||||
bm_context_t *bc;
|
bm_context_t *bc;
|
||||||
SlapReply *candidates;
|
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",
|
Debug(LDAP_DEBUG_ARGS, "==> asyncmeta_back_compare: %s\n",
|
||||||
op->o_req_dn.bv_val );
|
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) {
|
if (bc == NULL) {
|
||||||
rs->sr_err = LDAP_OTHER;
|
rs->sr_err = LDAP_OTHER;
|
||||||
asyncmeta_sender_error(op, rs, cb);
|
send_ldap_result(op, rs);
|
||||||
return rs->sr_err;
|
return rs->sr_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
candidates = bc->candidates;
|
candidates = bc->candidates;
|
||||||
mc = asyncmeta_getconn( op, rs, candidates, &candidate, LDAP_BACK_DONTSEND, 0);
|
mc = asyncmeta_getconn( op, rs, candidates, &candidate, LDAP_BACK_DONTSEND, 0);
|
||||||
if ( !mc || rs->sr_err != LDAP_SUCCESS) {
|
if ( !mc || rs->sr_err != LDAP_SUCCESS) {
|
||||||
asyncmeta_sender_error(op, rs, cb);
|
send_ldap_result(op, rs);
|
||||||
asyncmeta_clear_bm_context(bc);
|
|
||||||
return rs->sr_err;
|
return rs->sr_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -204,16 +216,38 @@ asyncmeta_back_compare( Operation *op, SlapReply *rs )
|
||||||
bc->retrying = LDAP_BACK_RETRYING;
|
bc->retrying = LDAP_BACK_RETRYING;
|
||||||
bc->sendok = ( LDAP_BACK_SENDRESULT | bc->retrying );
|
bc->sendok = ( LDAP_BACK_SENDRESULT | bc->retrying );
|
||||||
bc->stoptime = op->o_time + bc->timeout;
|
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);
|
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||||
rc = asyncmeta_add_message_queue(mc, bc);
|
rc = asyncmeta_add_message_queue(mc, bc);
|
||||||
|
mc->mc_conns[candidate].msc_active++;
|
||||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||||
|
|
||||||
if (rc != LDAP_SUCCESS) {
|
if (rc != LDAP_SUCCESS) {
|
||||||
rs->sr_err = LDAP_BUSY;
|
rs->sr_err = LDAP_BUSY;
|
||||||
rs->sr_text = "Maximum pending ops limit exceeded";
|
rs->sr_text = "Maximum pending ops limit exceeded";
|
||||||
asyncmeta_clear_bm_context(bc);
|
send_ldap_result(op, rs);
|
||||||
asyncmeta_sender_error(op, rs, cb);
|
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;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -223,47 +257,27 @@ asyncmeta_back_compare( Operation *op, SlapReply *rs )
|
||||||
case META_SEARCH_CANDIDATE:
|
case META_SEARCH_CANDIDATE:
|
||||||
/* target is already bound, just send the request */
|
/* target is already bound, just send the request */
|
||||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_compare: "
|
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) {
|
if (rc == META_SEARCH_ERR) {
|
||||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||||
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;
|
goto finish;
|
||||||
|
|
||||||
|
} else if (rc == META_SEARCH_NEED_BIND) {
|
||||||
|
goto retry;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case META_SEARCH_NOT_CANDIDATE:
|
case META_SEARCH_NOT_CANDIDATE:
|
||||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_compare: NOT_CANDIDATE "
|
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_compare: NOT_CANDIDATE "
|
||||||
"cnd=\"%ld\"\n", op->o_log_prefix, candidate );
|
"cnd=\"%d\"\n", op->o_log_prefix, candidate );
|
||||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||||
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;
|
goto finish;
|
||||||
|
|
||||||
case META_SEARCH_NEED_BIND:
|
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:
|
case META_SEARCH_BINDING:
|
||||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_compare: 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
|
/* Todo add the context to the message queue but do not send the request
|
||||||
the receiver must send this when we are done binding */
|
the receiver must send this when we are done binding */
|
||||||
/* question - how would do receiver know to which targets??? */
|
/* question - how would do receiver know to which targets??? */
|
||||||
|
|
@ -271,23 +285,21 @@ asyncmeta_back_compare( Operation *op, SlapReply *rs )
|
||||||
|
|
||||||
case META_SEARCH_ERR:
|
case META_SEARCH_ERR:
|
||||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_compare: ERR "
|
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_compare: ERR "
|
||||||
"cnd=\"%ldd\"\n", op->o_log_prefix, candidate );
|
"cnd=\"%d\"\n", op->o_log_prefix, candidate );
|
||||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||||
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;
|
goto finish;
|
||||||
default:
|
default:
|
||||||
assert( 0 );
|
assert( 0 );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||||
|
mc->mc_conns[candidate].msc_active--;
|
||||||
asyncmeta_start_one_listener(mc, candidates, bc, candidate);
|
asyncmeta_start_one_listener(mc, candidates, bc, candidate);
|
||||||
|
bc->bc_active--;
|
||||||
|
asyncmeta_memctx_toggle(thrctx);
|
||||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||||
|
rs->sr_err = SLAPD_ASYNCOP;
|
||||||
finish:
|
finish:
|
||||||
return rs->sr_err;
|
return rs->sr_err;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -27,57 +27,11 @@
|
||||||
#include <ac/errno.h>
|
#include <ac/errno.h>
|
||||||
#include <ac/socket.h>
|
#include <ac/socket.h>
|
||||||
#include <ac/string.h>
|
#include <ac/string.h>
|
||||||
|
|
||||||
|
|
||||||
#define AVL_INTERNAL
|
|
||||||
#include "slap.h"
|
#include "slap.h"
|
||||||
|
#include "../../../libraries/libldap/ldap-int.h"
|
||||||
#include "../back-ldap/back-ldap.h"
|
#include "../back-ldap/back-ldap.h"
|
||||||
#include "back-asyncmeta.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
|
* asyncmeta_conn_alloc
|
||||||
*
|
*
|
||||||
|
|
@ -127,8 +81,6 @@ asyncmeta_init_one_conn(
|
||||||
a_dncookie dc;
|
a_dncookie dc;
|
||||||
int isauthz = ( candidate == mc->mc_authz_target );
|
int isauthz = ( candidate == mc->mc_authz_target );
|
||||||
int do_return = 0;
|
int do_return = 0;
|
||||||
int nretries = 2;
|
|
||||||
|
|
||||||
#ifdef HAVE_TLS
|
#ifdef HAVE_TLS
|
||||||
int is_ldaps = 0;
|
int is_ldaps = 0;
|
||||||
int do_start_tls = 0;
|
int do_start_tls = 0;
|
||||||
|
|
@ -164,15 +116,16 @@ asyncmeta_init_one_conn(
|
||||||
|
|
||||||
if ( dont_retry ) {
|
if ( dont_retry ) {
|
||||||
rs->sr_err = LDAP_UNAVAILABLE;
|
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 ) ) {
|
if ( op->o_conn && ( sendok & LDAP_BACK_SENDERR ) ) {
|
||||||
rs->sr_text = "Target is quarantined";
|
|
||||||
send_ldap_result( op, rs );
|
send_ldap_result( op, rs );
|
||||||
}
|
}
|
||||||
return rs->sr_err;
|
return rs->sr_err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
msc = &mc->mc_conns[candidate];
|
msc = &mc->mc_conns[candidate];
|
||||||
retry_lock:;
|
|
||||||
/*
|
/*
|
||||||
* Already init'ed
|
* Already init'ed
|
||||||
*/
|
*/
|
||||||
|
|
@ -186,13 +139,7 @@ retry_lock:;
|
||||||
} else if ( META_BACK_CONN_CREATING( msc )
|
} else if ( META_BACK_CONN_CREATING( msc )
|
||||||
|| LDAP_BACK_CONN_BINDING( msc ) )
|
|| LDAP_BACK_CONN_BINDING( msc ) )
|
||||||
{
|
{
|
||||||
/* sounds more appropriate */
|
rs->sr_err = LDAP_SUCCESS;
|
||||||
if (nretries >= 0) {
|
|
||||||
nretries--;
|
|
||||||
ldap_pvt_thread_yield();
|
|
||||||
goto retry_lock;
|
|
||||||
}
|
|
||||||
rs->sr_err = LDAP_UNAVAILABLE;
|
|
||||||
do_return = 1;
|
do_return = 1;
|
||||||
|
|
||||||
} else if ( META_BACK_CONN_INITED( msc ) ) {
|
} else if ( META_BACK_CONN_INITED( msc ) ) {
|
||||||
|
|
@ -231,6 +178,8 @@ retry_lock:;
|
||||||
#endif /* HAVE_TLS */
|
#endif /* HAVE_TLS */
|
||||||
ldap_pvt_thread_mutex_unlock( &mt->mt_uri_mutex );
|
ldap_pvt_thread_mutex_unlock( &mt->mt_uri_mutex );
|
||||||
if ( rs->sr_err != LDAP_SUCCESS ) {
|
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;
|
goto error_return;
|
||||||
}
|
}
|
||||||
msc->msc_ldr = ldap_dup(msc->msc_ld);
|
msc->msc_ldr = ldap_dup(msc->msc_ld);
|
||||||
|
|
@ -327,8 +276,8 @@ retry:;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* only touch when activity actually took place... */
|
/* only touch when activity actually took place... */
|
||||||
if ( mi->mi_idle_timeout != 0 && msc->msc_time < op->o_time ) {
|
if ( mi->mi_idle_timeout != 0 ) {
|
||||||
msc->msc_time = op->o_time;
|
asyncmeta_set_msc_time(msc);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -348,6 +297,7 @@ retry:;
|
||||||
res = NULL;
|
res = NULL;
|
||||||
|
|
||||||
if ( rs->sr_err == LDAP_SUCCESS ) {
|
if ( rs->sr_err == LDAP_SUCCESS ) {
|
||||||
|
|
||||||
rs->sr_err = err;
|
rs->sr_err = err;
|
||||||
}
|
}
|
||||||
rs->sr_err = slap_map_api2result( rs );
|
rs->sr_err = slap_map_api2result( rs );
|
||||||
|
|
@ -385,7 +335,10 @@ retry:;
|
||||||
*/
|
*/
|
||||||
rs->sr_err = ldap_start_tls_s( msc->msc_ld, NULL, NULL );
|
rs->sr_err = ldap_start_tls_s( msc->msc_ld, NULL, NULL );
|
||||||
#endif /* ! SLAP_STARTTLS_ASYNCHRONOUS */
|
#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
|
/* if StartTLS is requested, only attempt it if the URL
|
||||||
* is not "ldaps://"; this may occur not only in case
|
* is not "ldaps://"; this may occur not only in case
|
||||||
* of misconfiguration, but also when used in the chain
|
* of misconfiguration, but also when used in the chain
|
||||||
|
|
@ -407,18 +360,16 @@ retry:;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* HAVE_TLS */
|
#endif /* HAVE_TLS */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the network timeout if set
|
* Set the network timeout if set
|
||||||
*/
|
*/
|
||||||
if ( mt->mt_network_timeout != 0 ) {
|
if ( mt->mt_network_timeout != 0 ) {
|
||||||
struct timeval network_timeout;
|
struct timeval network_timeout;
|
||||||
|
network_timeout.tv_sec = 0;
|
||||||
network_timeout.tv_usec = 0;
|
network_timeout.tv_usec = mt->mt_network_timeout*1000;
|
||||||
network_timeout.tv_sec = mt->mt_network_timeout;
|
|
||||||
|
|
||||||
ldap_set_option( msc->msc_ld, LDAP_OPT_NETWORK_TIMEOUT,
|
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 );
|
BER_BVZERO( &msc->msc_bound_ndn );
|
||||||
}
|
}
|
||||||
if ( !BER_BVISEMPTY( &op->o_ndn )
|
if ( !BER_BVISEMPTY( &op->o_ndn )
|
||||||
&& SLAP_IS_AUTHZ_BACKEND( op )
|
|
||||||
&& isauthz )
|
&& isauthz )
|
||||||
{
|
{
|
||||||
|
dc.op = op;
|
||||||
dc.target = mt;
|
dc.target = mt;
|
||||||
dc.conn = op->o_conn;
|
dc.memctx = NULL;
|
||||||
dc.rs = rs;
|
dc.to_from = MASSAGE_REQ;
|
||||||
dc.ctx = "bindDN";
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Rewrite the bind dn if needed
|
* Rewrite the bind dn if needed
|
||||||
*/
|
*/
|
||||||
if ( asyncmeta_dn_massage( &dc, &op->o_conn->c_dn,
|
asyncmeta_dn_massage( &dc, &op->o_conn->c_dn, &msc->msc_bound_ndn );
|
||||||
&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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* copy the DN if needed */
|
/* copy the DN if needed */
|
||||||
if ( msc->msc_bound_ndn.bv_val == op->o_conn->c_dn.bv_val ) {
|
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 );
|
ber_dupbv( &msc->msc_bound_ndn, &op->o_conn->c_dn );
|
||||||
}
|
}
|
||||||
|
|
||||||
assert( !BER_BVISNULL( &msc->msc_bound_ndn ) );
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ber_dupbv( &msc->msc_bound_ndn, (struct berval *)&slap_empty_bv );
|
ber_dupbv( &msc->msc_bound_ndn, (struct berval *)&slap_empty_bv );
|
||||||
}
|
}
|
||||||
|
|
@ -496,10 +431,6 @@ error_return:;
|
||||||
META_BACK_CONN_CREATING_CLEAR( msc );
|
META_BACK_CONN_CREATING_CLEAR( msc );
|
||||||
}
|
}
|
||||||
if ( rs->sr_err == LDAP_SUCCESS && msc != NULL) {
|
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 );
|
META_BACK_CONN_INITED_SET( msc );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -512,125 +443,6 @@ error_return:;
|
||||||
return rs->sr_err;
|
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
|
static int
|
||||||
asyncmeta_get_candidate(
|
asyncmeta_get_candidate(
|
||||||
|
|
@ -654,59 +466,6 @@ asyncmeta_get_candidate(
|
||||||
rs->sr_err = LDAP_NO_SUCH_OBJECT;
|
rs->sr_err = LDAP_NO_SUCH_OBJECT;
|
||||||
rs->sr_text = "No suitable candidate target found";
|
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 {
|
} else {
|
||||||
rs->sr_err = LDAP_SUCCESS;
|
rs->sr_err = LDAP_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
@ -714,19 +473,6 @@ asyncmeta_get_candidate(
|
||||||
return 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
|
* asyncmeta_getconn
|
||||||
|
|
@ -910,7 +656,7 @@ asyncmeta_getconn(
|
||||||
|
|
||||||
if ( sendok & LDAP_BACK_SENDERR ) {
|
if ( sendok & LDAP_BACK_SENDERR ) {
|
||||||
if ( rs->sr_err == LDAP_NO_SUCH_OBJECT ) {
|
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 );
|
send_ldap_result( op, rs );
|
||||||
rs->sr_matched = NULL;
|
rs->sr_matched = NULL;
|
||||||
|
|
@ -933,9 +679,6 @@ asyncmeta_getconn(
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( op_type == META_OP_REQUIRE_SINGLE ) {
|
if ( op_type == META_OP_REQUIRE_SINGLE ) {
|
||||||
a_metatarget_t *mt = NULL;
|
|
||||||
a_metasingleconn_t *msc = NULL;
|
|
||||||
|
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
for ( j = 0; j < mi->mi_ntargets; j++ ) {
|
for ( j = 0; j < mi->mi_ntargets; j++ ) {
|
||||||
|
|
@ -956,7 +699,7 @@ asyncmeta_getconn(
|
||||||
if ( i < 0 || rs->sr_err != LDAP_SUCCESS ) {
|
if ( i < 0 || rs->sr_err != LDAP_SUCCESS ) {
|
||||||
if ( sendok & LDAP_BACK_SENDERR ) {
|
if ( sendok & LDAP_BACK_SENDERR ) {
|
||||||
if ( rs->sr_err == LDAP_NO_SUCH_OBJECT ) {
|
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 );
|
send_ldap_result( op, rs );
|
||||||
rs->sr_matched = NULL;
|
rs->sr_matched = NULL;
|
||||||
|
|
@ -998,9 +741,6 @@ asyncmeta_getconn(
|
||||||
*/
|
*/
|
||||||
( void )asyncmeta_clear_unused_candidates( op, i , mc, candidates);
|
( 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
|
* The target is activated; if needed, it is
|
||||||
* also init'd. In case of error, asyncmeta_init_one_conn
|
* also init'd. In case of error, asyncmeta_init_one_conn
|
||||||
|
|
@ -1118,7 +858,7 @@ asyncmeta_getconn(
|
||||||
|
|
||||||
if ( sendok & LDAP_BACK_SENDERR ) {
|
if ( sendok & LDAP_BACK_SENDERR ) {
|
||||||
if ( rs->sr_err == LDAP_NO_SUCH_OBJECT ) {
|
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 );
|
send_ldap_result( op, rs );
|
||||||
rs->sr_matched = NULL;
|
rs->sr_matched = NULL;
|
||||||
|
|
@ -1133,7 +873,6 @@ asyncmeta_getconn(
|
||||||
}
|
}
|
||||||
|
|
||||||
done:;
|
done:;
|
||||||
/* clear out meta_back_init_one_conn non-fatal errors */
|
|
||||||
rs->sr_err = LDAP_SUCCESS;
|
rs->sr_err = LDAP_SUCCESS;
|
||||||
rs->sr_text = NULL;
|
rs->sr_text = NULL;
|
||||||
|
|
||||||
|
|
@ -1266,6 +1005,7 @@ a_metaconn_t *
|
||||||
asyncmeta_get_next_mc( a_metainfo_t *mi )
|
asyncmeta_get_next_mc( a_metainfo_t *mi )
|
||||||
{
|
{
|
||||||
a_metaconn_t *mc = NULL;
|
a_metaconn_t *mc = NULL;
|
||||||
|
|
||||||
ldap_pvt_thread_mutex_lock( &mi->mi_mc_mutex );
|
ldap_pvt_thread_mutex_lock( &mi->mi_mc_mutex );
|
||||||
if (mi->mi_next_conn >= mi->mi_num_conns-1) {
|
if (mi->mi_next_conn >= mi->mi_num_conns-1) {
|
||||||
mi->mi_next_conn = 0;
|
mi->mi_next_conn = 0;
|
||||||
|
|
@ -1294,14 +1034,13 @@ int asyncmeta_start_one_listener(a_metaconn_t *mc,
|
||||||
{
|
{
|
||||||
a_metasingleconn_t *msc;
|
a_metasingleconn_t *msc;
|
||||||
ber_socket_t s;
|
ber_socket_t s;
|
||||||
int i;
|
|
||||||
|
|
||||||
msc = &mc->mc_conns[candidate];
|
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;
|
return LDAP_SUCCESS;
|
||||||
}
|
}
|
||||||
bc->msgids[candidate] = candidates[candidate].sr_msgid;
|
bc->msgids[candidate] = candidates[candidate].sr_msgid;
|
||||||
msc->msc_pending_ops++;
|
|
||||||
if ( msc->conn == NULL) {
|
if ( msc->conn == NULL) {
|
||||||
ldap_get_option( msc->msc_ld, LDAP_OPT_DESC, &s );
|
ldap_get_option( msc->msc_ld, LDAP_OPT_DESC, &s );
|
||||||
if (s < 0) {
|
if (s < 0) {
|
||||||
|
|
@ -1313,3 +1052,130 @@ int asyncmeta_start_one_listener(a_metaconn_t *mc,
|
||||||
connection_client_enable( msc->conn );
|
connection_client_enable( msc->conn );
|
||||||
return LDAP_SUCCESS;
|
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 "portable.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <ac/string.h>
|
#include <ac/string.h>
|
||||||
#include <ac/socket.h>
|
#include <ac/socket.h>
|
||||||
|
|
||||||
#include "slap.h"
|
#include "slap.h"
|
||||||
#include "../back-ldap/back-ldap.h"
|
|
||||||
#include "back-asyncmeta.h"
|
|
||||||
#include "../../../libraries/liblber/lber-int.h"
|
#include "../../../libraries/liblber/lber-int.h"
|
||||||
#include "../../../libraries/libldap/ldap-int.h"
|
#include "../../../libraries/libldap/ldap-int.h"
|
||||||
|
#include "../back-ldap/back-ldap.h"
|
||||||
|
#include "back-asyncmeta.h"
|
||||||
|
|
||||||
meta_search_candidate_t
|
meta_search_candidate_t
|
||||||
asyncmeta_back_delete_start(Operation *op,
|
asyncmeta_back_delete_start(Operation *op,
|
||||||
SlapReply *rs,
|
SlapReply *rs,
|
||||||
a_metaconn_t *mc,
|
a_metaconn_t *mc,
|
||||||
bm_context_t *bc,
|
bm_context_t *bc,
|
||||||
int candidate)
|
int candidate,
|
||||||
|
int do_lock)
|
||||||
{
|
{
|
||||||
a_metainfo_t *mi = mc->mc_info;
|
a_metainfo_t *mi = mc->mc_info;
|
||||||
a_metatarget_t *mt = mi->mi_targets[ candidate ];
|
a_metatarget_t *mt = mi->mi_targets[ candidate ];
|
||||||
struct berval mdn = BER_BVNULL;
|
struct berval mdn = BER_BVNULL;
|
||||||
a_dncookie dc;
|
a_dncookie dc;
|
||||||
int rc = 0, nretries = 1;
|
int rc = 0;
|
||||||
LDAPControl **ctrls = NULL;
|
LDAPControl **ctrls = NULL;
|
||||||
meta_search_candidate_t retcode = META_SEARCH_CANDIDATE;
|
meta_search_candidate_t retcode = META_SEARCH_CANDIDATE;
|
||||||
BerElement *ber = NULL;
|
BerElement *ber = NULL;
|
||||||
|
|
@ -52,67 +51,119 @@ asyncmeta_back_delete_start(Operation *op,
|
||||||
SlapReply *candidates = bc->candidates;
|
SlapReply *candidates = bc->candidates;
|
||||||
ber_int_t msgid;
|
ber_int_t msgid;
|
||||||
|
|
||||||
|
dc.op = op;
|
||||||
dc.target = mt;
|
dc.target = mt;
|
||||||
dc.conn = op->o_conn;
|
dc.memctx = op->o_tmpmemctx;
|
||||||
dc.rs = rs;
|
dc.to_from = MASSAGE_REQ;
|
||||||
dc.ctx = "deleteDN";
|
|
||||||
|
|
||||||
if ( asyncmeta_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
|
asyncmeta_dn_massage( &dc, &op->o_req_dn, &mdn );
|
||||||
rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
|
|
||||||
retcode = META_SEARCH_ERR;
|
|
||||||
goto doreturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
retry:;
|
asyncmeta_set_msc_time(msc);
|
||||||
ctrls = op->o_ctrls;
|
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;
|
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||||
retcode = META_SEARCH_ERR;
|
retcode = META_SEARCH_ERR;
|
||||||
goto done;
|
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);
|
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) {
|
if (ber) {
|
||||||
candidates[ candidate ].sr_msgid = msgid;
|
struct timeval tv = {0, mt->mt_network_timeout*1000};
|
||||||
rc = ldap_send_initial_request( msc->msc_ld, LDAP_REQ_DELETE,
|
ber_socket_t s;
|
||||||
mdn.bv_val, ber, msgid );
|
if (!( LDAP_BACK_CONN_ISBOUND( msc )
|
||||||
if (rc == msgid)
|
|| LDAP_BACK_CONN_ISANON( msc )) || msc->msc_ld == NULL ) {
|
||||||
rc = LDAP_SUCCESS;
|
Debug( asyncmeta_debug, "msc %p not initialized at %s:%d\n", msc, __FILE__, __LINE__ );
|
||||||
else
|
goto error_unavailable;
|
||||||
rc = LDAP_SERVER_DOWN;
|
}
|
||||||
|
|
||||||
|
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 ) {
|
switch ( rc ) {
|
||||||
case LDAP_SUCCESS:
|
case LDAP_SUCCESS:
|
||||||
retcode = META_SEARCH_CANDIDATE;
|
retcode = META_SEARCH_CANDIDATE;
|
||||||
asyncmeta_set_msc_time(msc);
|
asyncmeta_set_msc_time(msc);
|
||||||
break;
|
goto done;
|
||||||
|
|
||||||
case LDAP_SERVER_DOWN:
|
case LDAP_SERVER_DOWN:
|
||||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
/* do not lock if called from asyncmeta_handle_bind_result. Also do not reset the connection */
|
||||||
asyncmeta_clear_one_msc(NULL, mc, candidate);
|
if (do_lock > 0) {
|
||||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||||
if ( nretries && asyncmeta_retry( op, rs, &mc, candidate, LDAP_BACK_DONTSEND ) ) {
|
asyncmeta_reset_msc(NULL, mc, candidate, 0, __FUNCTION__);
|
||||||
nretries = 0;
|
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||||
/* if the identity changed, there might be need to re-authz */
|
|
||||||
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
|
||||||
goto retry;
|
|
||||||
}
|
}
|
||||||
|
/* fall though*/
|
||||||
default:
|
default:
|
||||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
Debug( asyncmeta_debug, "msc %p ldap_send_initial_request failed. %s:%d\n", msc, __FILE__, __LINE__ );
|
||||||
retcode = META_SEARCH_ERR;
|
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:
|
done:
|
||||||
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
||||||
|
|
||||||
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
|
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
|
||||||
free( mdn.bv_val );
|
op->o_tmpfree( mdn.bv_val, op->o_tmpmemctx );
|
||||||
BER_BVZERO( &mdn );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
doreturn:;
|
|
||||||
Debug( LDAP_DEBUG_TRACE, "%s <<< asyncmeta_back_delete_start[%p]=%d\n", op->o_log_prefix, msc, candidates[candidate].sr_msgid );
|
Debug( LDAP_DEBUG_TRACE, "%s <<< asyncmeta_back_delete_start[%p]=%d\n", op->o_log_prefix, msc, candidates[candidate].sr_msgid );
|
||||||
return retcode;
|
return retcode;
|
||||||
}
|
}
|
||||||
|
|
@ -124,26 +175,32 @@ asyncmeta_back_delete( Operation *op, SlapReply *rs )
|
||||||
a_metatarget_t *mt;
|
a_metatarget_t *mt;
|
||||||
a_metaconn_t *mc;
|
a_metaconn_t *mc;
|
||||||
int rc, candidate = -1;
|
int rc, candidate = -1;
|
||||||
OperationBuffer opbuf;
|
void *thrctx = op->o_threadctx;
|
||||||
bm_context_t *bc;
|
bm_context_t *bc;
|
||||||
SlapReply *candidates;
|
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 );
|
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) {
|
if (bc == NULL) {
|
||||||
rs->sr_err = LDAP_OTHER;
|
rs->sr_err = LDAP_OTHER;
|
||||||
asyncmeta_sender_error(op, rs, cb);
|
send_ldap_result(op, rs);
|
||||||
return rs->sr_err;
|
return rs->sr_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
candidates = bc->candidates;
|
candidates = bc->candidates;
|
||||||
mc = asyncmeta_getconn( op, rs, candidates, &candidate, LDAP_BACK_DONTSEND, 0);
|
mc = asyncmeta_getconn( op, rs, candidates, &candidate, LDAP_BACK_DONTSEND, 0);
|
||||||
if ( !mc || rs->sr_err != LDAP_SUCCESS) {
|
if ( !mc || rs->sr_err != LDAP_SUCCESS) {
|
||||||
asyncmeta_sender_error(op, rs, cb);
|
send_ldap_result(op, rs);
|
||||||
asyncmeta_clear_bm_context(bc);
|
|
||||||
return rs->sr_err;
|
return rs->sr_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -152,16 +209,38 @@ asyncmeta_back_delete( Operation *op, SlapReply *rs )
|
||||||
bc->retrying = LDAP_BACK_RETRYING;
|
bc->retrying = LDAP_BACK_RETRYING;
|
||||||
bc->sendok = ( LDAP_BACK_SENDRESULT | bc->retrying );
|
bc->sendok = ( LDAP_BACK_SENDRESULT | bc->retrying );
|
||||||
bc->stoptime = op->o_time + bc->timeout;
|
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);
|
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||||
rc = asyncmeta_add_message_queue(mc, bc);
|
rc = asyncmeta_add_message_queue(mc, bc);
|
||||||
|
mc->mc_conns[candidate].msc_active++;
|
||||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||||
|
|
||||||
if (rc != LDAP_SUCCESS) {
|
if (rc != LDAP_SUCCESS) {
|
||||||
rs->sr_err = LDAP_BUSY;
|
rs->sr_err = LDAP_BUSY;
|
||||||
rs->sr_text = "Maximum pending ops limit exceeded";
|
rs->sr_text = "Maximum pending ops limit exceeded";
|
||||||
asyncmeta_clear_bm_context(bc);
|
send_ldap_result(op, rs);
|
||||||
asyncmeta_sender_error(op, rs, cb);
|
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;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -171,47 +250,27 @@ asyncmeta_back_delete( Operation *op, SlapReply *rs )
|
||||||
case META_SEARCH_CANDIDATE:
|
case META_SEARCH_CANDIDATE:
|
||||||
/* target is already bound, just send the request */
|
/* target is already bound, just send the request */
|
||||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_delete: "
|
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) {
|
if (rc == META_SEARCH_ERR) {
|
||||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||||
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;
|
goto finish;
|
||||||
|
|
||||||
|
} else if (rc == META_SEARCH_NEED_BIND) {
|
||||||
|
goto retry;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case META_SEARCH_NOT_CANDIDATE:
|
case META_SEARCH_NOT_CANDIDATE:
|
||||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_delete: NOT_CANDIDATE "
|
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_delete: NOT_CANDIDATE "
|
||||||
"cnd=\"%ld\"\n", op->o_log_prefix, candidate );
|
"cnd=\"%d\"\n", op->o_log_prefix, candidate );
|
||||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||||
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;
|
goto finish;
|
||||||
|
|
||||||
case META_SEARCH_NEED_BIND:
|
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:
|
case META_SEARCH_BINDING:
|
||||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_delete: 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
|
/* Todo add the context to the message queue but do not send the request
|
||||||
the receiver must send this when we are done binding */
|
the receiver must send this when we are done binding */
|
||||||
/* question - how would do receiver know to which targets??? */
|
/* question - how would do receiver know to which targets??? */
|
||||||
|
|
@ -219,22 +278,21 @@ asyncmeta_back_delete( Operation *op, SlapReply *rs )
|
||||||
|
|
||||||
case META_SEARCH_ERR:
|
case META_SEARCH_ERR:
|
||||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_delete: ERR "
|
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_delete: ERR "
|
||||||
"cnd=\"%ldd\"\n", op->o_log_prefix, candidate );
|
"cnd=\"%d\"\n", op->o_log_prefix, candidate );
|
||||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||||
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;
|
goto finish;
|
||||||
default:
|
default:
|
||||||
assert( 0 );
|
assert( 0 );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||||
|
mc->mc_conns[candidate].msc_active--;
|
||||||
asyncmeta_start_one_listener(mc, candidates, bc, candidate);
|
asyncmeta_start_one_listener(mc, candidates, bc, candidate);
|
||||||
|
bc->bc_active--;
|
||||||
|
asyncmeta_memctx_toggle(thrctx);
|
||||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||||
|
rs->sr_err = SLAPD_ASYNCOP;
|
||||||
finish:
|
finish:
|
||||||
return rs->sr_err;
|
return rs->sr_err;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,8 @@
|
||||||
#include "../back-ldap/back-ldap.h"
|
#include "../back-ldap/back-ldap.h"
|
||||||
#include "back-asyncmeta.h"
|
#include "back-asyncmeta.h"
|
||||||
|
|
||||||
|
int asyncmeta_debug;
|
||||||
|
|
||||||
int
|
int
|
||||||
asyncmeta_back_open(
|
asyncmeta_back_open(
|
||||||
BackendInfo *bi )
|
BackendInfo *bi )
|
||||||
|
|
@ -46,6 +48,14 @@ int
|
||||||
asyncmeta_back_initialize(
|
asyncmeta_back_initialize(
|
||||||
BackendInfo *bi )
|
BackendInfo *bi )
|
||||||
{
|
{
|
||||||
|
int rc;
|
||||||
|
struct berval debugbv = BER_BVC("asyncmeta");
|
||||||
|
|
||||||
|
rc = slap_loglevel_get( &debugbv, &asyncmeta_debug );
|
||||||
|
if ( rc ) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
bi->bi_flags =
|
bi->bi_flags =
|
||||||
#if 0
|
#if 0
|
||||||
/* this is not (yet) set essentially because back-meta does not
|
/* 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_chk_referrals = 0;
|
||||||
|
|
||||||
bi->bi_connection_init = 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 );
|
return asyncmeta_back_init_cf( bi );
|
||||||
}
|
}
|
||||||
|
|
@ -164,9 +174,7 @@ asyncmeta_target_finish(
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
slap_bindconf sb = { BER_BVNULL };
|
slap_bindconf sb = { BER_BVNULL };
|
||||||
struct berval mapped;
|
|
||||||
int rc;
|
int rc;
|
||||||
int msc_num, i;
|
|
||||||
|
|
||||||
ber_str2bv( mt->mt_uri, 0, 0, &sb.sb_uri );
|
ber_str2bv( mt->mt_uri, 0, 0, &sb.sb_uri );
|
||||||
sb.sb_version = mt->mt_version;
|
sb.sb_version = mt->mt_version;
|
||||||
|
|
@ -216,21 +224,6 @@ asyncmeta_target_finish(
|
||||||
mi->mi_flags &= ~META_BACK_F_PROXYAUTHZ_NOANON;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -240,10 +233,8 @@ asyncmeta_back_db_open(
|
||||||
ConfigReply *cr )
|
ConfigReply *cr )
|
||||||
{
|
{
|
||||||
a_metainfo_t *mi = (a_metainfo_t *)be->be_private;
|
a_metainfo_t *mi = (a_metainfo_t *)be->be_private;
|
||||||
|
|
||||||
char msg[SLAP_TEXT_BUFLEN];
|
char msg[SLAP_TEXT_BUFLEN];
|
||||||
|
int i;
|
||||||
int i, rc;
|
|
||||||
|
|
||||||
if ( mi->mi_ntargets == 0 ) {
|
if ( mi->mi_ntargets == 0 ) {
|
||||||
/* Dynamically added, nothing to check here until
|
/* Dynamically added, nothing to check here until
|
||||||
|
|
@ -272,11 +263,12 @@ asyncmeta_back_db_open(
|
||||||
mc->mc_authz_target = META_BOUND_NONE;
|
mc->mc_authz_target = META_BOUND_NONE;
|
||||||
mc->mc_conns = ch_calloc( mi->mi_ntargets, sizeof( a_metasingleconn_t ));
|
mc->mc_conns = ch_calloc( mi->mi_ntargets, sizeof( a_metasingleconn_t ));
|
||||||
mc->mc_info = mi;
|
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 );
|
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
|
||||||
mi->mi_task = ldap_pvt_runqueue_insert( &slapd_rq, 0,
|
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 );
|
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -298,36 +290,6 @@ asyncmeta_back_conn_free(
|
||||||
free( mc );
|
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
|
static void
|
||||||
asyncmeta_back_stop_miconns( a_metainfo_t *mi )
|
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];
|
mc = &mi->mi_conns[i];
|
||||||
/* todo clear the message queue */
|
/* todo clear the message queue */
|
||||||
for (j = 0; j < mi->mi_ntargets; j ++) {
|
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);
|
free(mc->mc_conns);
|
||||||
ldap_pvt_thread_mutex_destroy( &mc->mc_om_mutex );
|
ldap_pvt_thread_mutex_destroy( &mc->mc_om_mutex );
|
||||||
|
|
@ -401,14 +363,12 @@ asyncmeta_target_free(
|
||||||
if ( mt->mt_idassert_authz != NULL ) {
|
if ( mt->mt_idassert_authz != NULL ) {
|
||||||
ber_bvarray_free( mt->mt_idassert_authz );
|
ber_bvarray_free( mt->mt_idassert_authz );
|
||||||
}
|
}
|
||||||
if ( mt->mt_rwmap.rwm_rw ) {
|
if ( !BER_BVISNULL( &mt->mt_lsuffixm )) {
|
||||||
rewrite_info_delete( &mt->mt_rwmap.rwm_rw );
|
ch_free( mt->mt_lsuffixm.bv_val );
|
||||||
if ( mt->mt_rwmap.rwm_bva_rewrite )
|
}
|
||||||
ber_bvarray_free( mt->mt_rwmap.rwm_bva_rewrite );
|
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 );
|
free( mt );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -420,8 +380,6 @@ asyncmeta_back_db_close(
|
||||||
a_metainfo_t *mi;
|
a_metainfo_t *mi;
|
||||||
|
|
||||||
if ( be->be_private ) {
|
if ( be->be_private ) {
|
||||||
int i;
|
|
||||||
|
|
||||||
mi = ( a_metainfo_t * )be->be_private;
|
mi = ( a_metainfo_t * )be->be_private;
|
||||||
if ( mi->mi_task != NULL ) {
|
if ( mi->mi_task != NULL ) {
|
||||||
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
|
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
|
||||||
|
|
@ -435,6 +393,7 @@ asyncmeta_back_db_close(
|
||||||
asyncmeta_back_stop_miconns( mi );
|
asyncmeta_back_stop_miconns( mi );
|
||||||
ldap_pvt_thread_mutex_unlock( &mi->mi_mc_mutex );
|
ldap_pvt_thread_mutex_unlock( &mi->mi_mc_mutex );
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -486,13 +445,14 @@ asyncmeta_back_db_destroy(
|
||||||
if ( META_BACK_QUARANTINE( mi ) ) {
|
if ( META_BACK_QUARANTINE( mi ) ) {
|
||||||
mi->mi_ldap_extra->retry_info_destroy( &mi->mi_quarantine );
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,641 +63,10 @@
|
||||||
#include "../back-ldap/back-ldap.h"
|
#include "../back-ldap/back-ldap.h"
|
||||||
#include "back-asyncmeta.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
|
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(
|
asyncmeta_referral_result_rewrite(
|
||||||
a_dncookie *dc,
|
a_dncookie *dc,
|
||||||
BerVarray a_vals,
|
BerVarray a_vals
|
||||||
void *memctx
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
int i, last;
|
int i, last;
|
||||||
|
|
@ -731,144 +100,115 @@ asyncmeta_referral_result_rewrite(
|
||||||
|
|
||||||
ber_str2bv( ludp->lud_dn, 0, 0, &olddn );
|
ber_str2bv( ludp->lud_dn, 0, 0, &olddn );
|
||||||
|
|
||||||
rc = asyncmeta_dn_massage( dc, &olddn, &dn );
|
asyncmeta_dn_massage( dc, &olddn, &dn );
|
||||||
switch ( rc ) {
|
/* leave attr untouched if massage did nothing */
|
||||||
case LDAP_UNWILLING_TO_PERFORM:
|
if ( olddn.bv_val != dn.bv_val )
|
||||||
/*
|
{
|
||||||
* FIXME: need to check if it may be considered
|
char *newurl;
|
||||||
* 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;
|
|
||||||
|
|
||||||
default:
|
ludp->lud_dn = dn.bv_val;
|
||||||
/* leave attr untouched if massage failed */
|
newurl = ldap_url_desc2str( ludp );
|
||||||
if ( !BER_BVISNULL( &dn ) && olddn.bv_val != dn.bv_val )
|
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;
|
ber_memfree_x( a_vals[ i ].bv_val, dc->op->o_tmpmemctx );
|
||||||
newurl = ldap_url_desc2str( ludp );
|
ber_str2bv_x( newurl, 0, 1, &a_vals[ i ], dc->memctx );
|
||||||
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( newurl );
|
ber_memfree( newurl );
|
||||||
ludp->lud_dn = olddn.bv_val;
|
ludp->lud_dn = olddn.bv_val;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ldap_free_urldesc( ludp );
|
ldap_free_urldesc( ludp );
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
void
|
||||||
* 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
|
|
||||||
asyncmeta_dnattr_result_rewrite(
|
asyncmeta_dnattr_result_rewrite(
|
||||||
a_dncookie *dc,
|
a_dncookie *dc,
|
||||||
BerVarray a_vals
|
BerVarray a_vals
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
struct berval bv;
|
struct berval bv;
|
||||||
int i, last;
|
int i;
|
||||||
|
|
||||||
assert( a_vals != NULL );
|
assert( a_vals != NULL );
|
||||||
|
|
||||||
for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ )
|
|
||||||
;
|
|
||||||
last--;
|
|
||||||
|
|
||||||
for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
|
for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
|
||||||
switch ( asyncmeta_dn_massage( dc, &a_vals[i], &bv ) ) {
|
asyncmeta_dn_massage( dc, &a_vals[i], &bv );
|
||||||
case LDAP_UNWILLING_TO_PERFORM:
|
if ( bv.bv_val != a_vals[i].bv_val ) {
|
||||||
/*
|
ber_memfree_x( a_vals[i].bv_val, dc->memctx );
|
||||||
* FIXME: need to check if it may be considered
|
a_vals[i] = bv;
|
||||||
* 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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
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"
|
#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 {
|
typedef struct listptr {
|
||||||
void *reserved;
|
void *reserved;
|
||||||
struct listptr *next;
|
struct listptr *next;
|
||||||
|
|
@ -223,80 +47,73 @@ typedef struct listhead {
|
||||||
int cnt;
|
int cnt;
|
||||||
} listhead;
|
} 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
|
#ifndef LH_MAX
|
||||||
#define LH_MAX 16
|
#define LH_MAX 16
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void *asyncmeta_memctx_get(void *threadctx)
|
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);
|
return slap_sl_mem_create(SLAP_SLAB_SIZE, SLAP_SLAB_STACK, threadctx, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asyncmeta_memctx_put(void *threadctx, void *memctx)
|
static void asyncmeta_memctx_put(void *threadctx, void *memctx)
|
||||||
{
|
{
|
||||||
listhead *lh = NULL;
|
slap_sl_mem_setctx(threadctx, NULL);
|
||||||
ldap_pvt_thread_pool_getkey(threadctx, asyncmeta_memctx_get, &lh, NULL);
|
slap_sl_mem_destroy((void *)1, memctx);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
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->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)->candidates = op->o_tmpcalloc(ntargets, sizeof(SlapReply),op->o_tmpmemctx);
|
||||||
(*new_bc)->msgids = op->o_tmpcalloc(ntargets, sizeof(int),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++) {
|
for (i = 0; i < ntargets; i++) {
|
||||||
(*new_bc)->msgids[i] = META_MSGID_UNDEFINED;
|
(*new_bc)->msgids[i] = META_MSGID_UNDEFINED;
|
||||||
}
|
}
|
||||||
/* restore original memctx */
|
for (i = 0; i < ntargets; i++) {
|
||||||
slap_sl_mem_setctx(op->o_threadctx, oldctx);
|
(*new_bc)->nretries[i] = mi->mi_targets[i]->mt_nretries;
|
||||||
op->o_tmpmemctx = oldctx;
|
}
|
||||||
return LDAP_SUCCESS;
|
return LDAP_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -305,15 +122,6 @@ void asyncmeta_free_op(Operation *op)
|
||||||
assert (op != NULL);
|
assert (op != NULL);
|
||||||
switch (op->o_tag) {
|
switch (op->o_tag) {
|
||||||
case LDAP_REQ_SEARCH:
|
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;
|
break;
|
||||||
case LDAP_REQ_ADD:
|
case LDAP_REQ_ADD:
|
||||||
if ( op->ora_modlist != NULL ) {
|
if ( op->ora_modlist != NULL ) {
|
||||||
|
|
@ -331,36 +139,11 @@ void asyncmeta_free_op(Operation *op)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LDAP_REQ_MODRDN:
|
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 ) {
|
if ( op->orr_modlist != NULL ) {
|
||||||
slap_mods_free(op->orr_modlist, 1 );
|
slap_mods_free(op->orr_modlist, 1 );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LDAP_REQ_COMPARE:
|
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;
|
break;
|
||||||
case LDAP_REQ_DELETE:
|
case LDAP_REQ_DELETE:
|
||||||
break;
|
break;
|
||||||
|
|
@ -368,22 +151,8 @@ void asyncmeta_free_op(Operation *op)
|
||||||
Debug( LDAP_DEBUG_TRACE, "==> asyncmeta_free_op : other message type" );
|
Debug( LDAP_DEBUG_TRACE, "==> asyncmeta_free_op : other message type" );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (op->o_ctrls != NULL) {
|
connection_op_finish( op );
|
||||||
asyncmeta_free_op_controls(op);
|
slap_op_free( op, op->o_threadctx );
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -393,96 +162,26 @@ void asyncmeta_clear_bm_context(bm_context_t *bc)
|
||||||
{
|
{
|
||||||
|
|
||||||
Operation *op = bc->op;
|
Operation *op = bc->op;
|
||||||
#if 0
|
void *thrctx, *memctx;
|
||||||
bm_candidates_t *cl;
|
int i;
|
||||||
a_metainfo_t *mi;
|
|
||||||
int i = 0;
|
if ( bc->bc_mc && bc->bc_mc->mc_info ) {
|
||||||
if (bmc == NULL) {
|
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;
|
return;
|
||||||
} else if (bmc->cl == NULL) {
|
memctx = op->o_tmpmemctx;
|
||||||
free(bmc);
|
thrctx = op->o_threadctx;
|
||||||
return;
|
while (op->o_bd == bc->copy_op.o_bd)
|
||||||
}
|
ldap_pvt_thread_yield();
|
||||||
cl = bmc->cl;
|
asyncmeta_free_op(op);
|
||||||
op = cl->op;
|
asyncmeta_memctx_put(thrctx, memctx);
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int asyncmeta_add_message_queue(a_metaconn_t *mc, bm_context_t *bc)
|
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",
|
Debug( LDAP_DEBUG_TRACE, "add_message_queue: mc %p, pending_ops %d, max_pending %d\n",
|
||||||
mc, mc->pending_ops, max_pending_ops );
|
mc, mc->pending_ops, max_pending_ops );
|
||||||
|
|
||||||
|
assert(bc->bc_mc == NULL);
|
||||||
if (mc->pending_ops >= max_pending_ops) {
|
if (mc->pending_ops >= max_pending_ops) {
|
||||||
return LDAP_BUSY;
|
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++;
|
mc->pending_ops++;
|
||||||
return LDAP_SUCCESS;
|
return LDAP_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
asyncmeta_drop_bc(a_metaconn_t *mc, bm_context_t *bc)
|
asyncmeta_drop_bc(a_metaconn_t *mc, bm_context_t *bc)
|
||||||
{
|
{
|
||||||
bm_context_t *om;
|
bm_context_t *om;
|
||||||
int i;
|
LDAP_STAILQ_FOREACH( om, &mc->mc_om_list, bc_next ) {
|
||||||
LDAP_SLIST_FOREACH( om, &mc->mc_om_list, bc_next ) {
|
|
||||||
if (om == bc) {
|
if (om == bc) {
|
||||||
for (i = 0; i < mc->mc_info->mi_ntargets; i++)
|
LDAP_STAILQ_REMOVE(&mc->mc_om_list, om, bm_context_t, bc_next);
|
||||||
{
|
|
||||||
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);
|
|
||||||
mc->pending_ops--;
|
mc->pending_ops--;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
assert(om == bc);
|
||||||
|
assert(bc->bc_mc == mc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bm_context_t *
|
bm_context_t *
|
||||||
asyncmeta_find_message(ber_int_t msgid, a_metaconn_t *mc, int candidate)
|
asyncmeta_find_message(ber_int_t msgid, a_metaconn_t *mc, int candidate)
|
||||||
{
|
{
|
||||||
bm_context_t *om;
|
bm_context_t *om;
|
||||||
LDAP_SLIST_FOREACH( om, &mc->mc_om_list, bc_next ) {
|
LDAP_STAILQ_FOREACH( om, &mc->mc_om_list, bc_next ) {
|
||||||
if (om->candidates[candidate].sr_msgid == msgid) {
|
if (om->candidates[candidate].sr_msgid == msgid && !om->bc_invalid) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return om;
|
return om;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bm_context_t *
|
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;
|
bm_context_t *om;
|
||||||
LDAP_SLIST_FOREACH( om, &mc->mc_om_list, bc_next ) {
|
LDAP_STAILQ_FOREACH( om, &mc->mc_om_list, bc_next ) {
|
||||||
if (om->op->o_msgid == msgid) {
|
if (om == bc) {
|
||||||
break;
|
return bc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (remove && om) {
|
return NULL;
|
||||||
LDAP_SLIST_REMOVE(&mc->mc_om_list, om, bm_context_t, bc_next);
|
|
||||||
mc->pending_ops--;
|
|
||||||
}
|
|
||||||
return om;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -26,21 +26,21 @@
|
||||||
|
|
||||||
#include <ac/string.h>
|
#include <ac/string.h>
|
||||||
#include <ac/socket.h>
|
#include <ac/socket.h>
|
||||||
|
|
||||||
#include "slap.h"
|
#include "slap.h"
|
||||||
#include "../back-ldap/back-ldap.h"
|
|
||||||
#include "back-asyncmeta.h"
|
|
||||||
#include "../../../libraries/liblber/lber-int.h"
|
#include "../../../libraries/liblber/lber-int.h"
|
||||||
#include "../../../libraries/libldap/ldap-int.h"
|
#include "../../../libraries/libldap/ldap-int.h"
|
||||||
|
#include "../back-ldap/back-ldap.h"
|
||||||
|
#include "back-asyncmeta.h"
|
||||||
|
|
||||||
meta_search_candidate_t
|
meta_search_candidate_t
|
||||||
asyncmeta_back_modify_start(Operation *op,
|
asyncmeta_back_modify_start(Operation *op,
|
||||||
SlapReply *rs,
|
SlapReply *rs,
|
||||||
a_metaconn_t *mc,
|
a_metaconn_t *mc,
|
||||||
bm_context_t *bc,
|
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_dncookie dc;
|
||||||
a_metainfo_t *mi = mc->mc_info;
|
a_metainfo_t *mi = mc->mc_info;
|
||||||
a_metatarget_t *mt = mi->mi_targets[ candidate ];
|
a_metatarget_t *mt = mi->mi_targets[ candidate ];
|
||||||
|
|
@ -48,7 +48,6 @@ asyncmeta_back_modify_start(Operation *op,
|
||||||
LDAPMod *mods = NULL;
|
LDAPMod *mods = NULL;
|
||||||
struct berval mdn;
|
struct berval mdn;
|
||||||
Modifications *ml;
|
Modifications *ml;
|
||||||
struct berval mapped;
|
|
||||||
meta_search_candidate_t retcode = META_SEARCH_CANDIDATE;
|
meta_search_candidate_t retcode = META_SEARCH_CANDIDATE;
|
||||||
BerElement *ber = NULL;
|
BerElement *ber = NULL;
|
||||||
a_metasingleconn_t *msc = &mc->mc_conns[ candidate ];
|
a_metasingleconn_t *msc = &mc->mc_conns[ candidate ];
|
||||||
|
|
@ -59,122 +58,55 @@ asyncmeta_back_modify_start(Operation *op,
|
||||||
/*
|
/*
|
||||||
* Rewrite the modify dn, if needed
|
* Rewrite the modify dn, if needed
|
||||||
*/
|
*/
|
||||||
|
dc.op = op;
|
||||||
dc.target = mt;
|
dc.target = mt;
|
||||||
dc.conn = op->o_conn;
|
dc.memctx = op->o_tmpmemctx;
|
||||||
dc.rs = rs;
|
dc.to_from = MASSAGE_REQ;
|
||||||
dc.ctx = "modifyDN";
|
|
||||||
|
|
||||||
switch ( asyncmeta_dn_massage( &dc, &op->o_req_dn, &mdn ) )
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( i = 0, ml = op->orm_modlist; ml; i++ ,ml = ml->sml_next )
|
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 ) {
|
if ( mods == NULL ) {
|
||||||
rs->sr_err = LDAP_OTHER;
|
rs->sr_err = LDAP_OTHER;
|
||||||
retcode = META_SEARCH_ERR;
|
retcode = META_SEARCH_ERR;
|
||||||
goto doreturn;
|
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 ) {
|
if ( modv == NULL ) {
|
||||||
rs->sr_err = LDAP_OTHER;
|
rs->sr_err = LDAP_OTHER;
|
||||||
retcode = META_SEARCH_ERR;
|
retcode = META_SEARCH_ERR;
|
||||||
goto doreturn;
|
goto doreturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
dc.ctx = "modifyAttrDN";
|
|
||||||
isupdate = be_shadow_update( op );
|
isupdate = be_shadow_update( op );
|
||||||
for ( i = 0, ml = op->orm_modlist; ml; ml = ml->sml_next ) {
|
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 )
|
if ( !isupdate && !get_relax( op ) && ml->sml_desc->ad_type->sat_no_user_mod )
|
||||||
{
|
{
|
||||||
continue;
|
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 ];
|
modv[ i ] = &mods[ i ];
|
||||||
mods[ i ].mod_op = ml->sml_op | LDAP_MOD_BVALUES;
|
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 ( ml->sml_values != NULL ) {
|
||||||
if ( is_oc ) {
|
j = ml->sml_numvals;
|
||||||
for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); j++ )
|
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 =
|
mods[ i ].mod_bvalues[ j ] = op->o_tmpalloc(sizeof( struct berval ), op->o_tmpmemctx );
|
||||||
(struct berval **)ch_malloc( ( j + 1 ) *
|
if ( ml->sml_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
|
||||||
sizeof( struct berval * ) );
|
asyncmeta_dn_massage( &dc, &ml->sml_values[ j ], mods[ i ].mod_bvalues[ j ] );
|
||||||
for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); ) {
|
else
|
||||||
struct ldapmapping *mapping;
|
*mods[ i ].mod_bvalues[ j ] = ml->sml_values[ j ];
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
mods[ i ].mod_bvalues[ j ] = NULL;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
mods[ i ].mod_bvalues = NULL;
|
mods[ i ].mod_bvalues = NULL;
|
||||||
|
|
@ -184,62 +116,113 @@ asyncmeta_back_modify_start(Operation *op,
|
||||||
}
|
}
|
||||||
modv[ i ] = 0;
|
modv[ i ] = 0;
|
||||||
|
|
||||||
retry:;
|
asyncmeta_set_msc_time(msc);
|
||||||
ctrls = op->o_ctrls;
|
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;
|
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||||
retcode = META_SEARCH_ERR;
|
retcode = META_SEARCH_ERR;
|
||||||
goto done;
|
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);
|
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) {
|
if (ber) {
|
||||||
candidates[ candidate ].sr_msgid = msgid;
|
struct timeval tv = {0, mt->mt_network_timeout*1000};
|
||||||
rc = ldap_send_initial_request( msc->msc_ld, LDAP_REQ_MODIFY,
|
ber_socket_t s;
|
||||||
mdn.bv_val, ber, msgid );
|
if (!( LDAP_BACK_CONN_ISBOUND( msc )
|
||||||
if (rc == msgid)
|
|| LDAP_BACK_CONN_ISANON( msc )) || msc->msc_ld == NULL ) {
|
||||||
rc = LDAP_SUCCESS;
|
Debug( asyncmeta_debug, "msc %p not initialized at %s:%d\n", msc, __FILE__, __LINE__ );
|
||||||
else
|
goto error_unavailable;
|
||||||
rc = LDAP_SERVER_DOWN;
|
}
|
||||||
|
|
||||||
|
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 ) {
|
switch ( rc ) {
|
||||||
case LDAP_SUCCESS:
|
case LDAP_SUCCESS:
|
||||||
retcode = META_SEARCH_CANDIDATE;
|
retcode = META_SEARCH_CANDIDATE;
|
||||||
asyncmeta_set_msc_time(msc);
|
asyncmeta_set_msc_time(msc);
|
||||||
break;
|
goto done;
|
||||||
|
|
||||||
case LDAP_SERVER_DOWN:
|
case LDAP_SERVER_DOWN:
|
||||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
/* do not lock if called from asyncmeta_handle_bind_result. Also do not reset the connection */
|
||||||
asyncmeta_clear_one_msc(NULL, mc, candidate);
|
if (do_lock > 0) {
|
||||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||||
if ( nretries && asyncmeta_retry( op, rs, &mc, candidate, LDAP_BACK_DONTSEND ) ) {
|
asyncmeta_reset_msc(NULL, mc, candidate, 0, __FUNCTION__);
|
||||||
nretries = 0;
|
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||||
/* if the identity changed, there might be need to re-authz */
|
|
||||||
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
|
||||||
goto retry;
|
|
||||||
}
|
}
|
||||||
|
/* fall though*/
|
||||||
default:
|
default:
|
||||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
Debug( asyncmeta_debug, "msc %p ldap_send_initial_request failed. %s:%d\n", msc, __FILE__, __LINE__ );
|
||||||
retcode = META_SEARCH_ERR;
|
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:
|
done:
|
||||||
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
||||||
|
|
||||||
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
|
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
|
||||||
free( mdn.bv_val );
|
op->o_tmpfree( mdn.bv_val, op->o_tmpmemctx );
|
||||||
BER_BVZERO( &mdn );
|
|
||||||
}
|
}
|
||||||
if ( modv != NULL ) {
|
|
||||||
for ( i = 0; modv[ i ]; i++ ) {
|
|
||||||
free( modv[ i ]->mod_bvalues );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free( mods );
|
|
||||||
free( modv );
|
|
||||||
|
|
||||||
doreturn:;
|
doreturn:;
|
||||||
Debug( LDAP_DEBUG_TRACE, "%s <<< asyncmeta_back_modify_start[%p]=%d\n", op->o_log_prefix, msc, candidates[candidate].sr_msgid );
|
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_metatarget_t *mt;
|
||||||
a_metaconn_t *mc;
|
a_metaconn_t *mc;
|
||||||
int rc, candidate = -1;
|
int rc, candidate = -1;
|
||||||
OperationBuffer opbuf;
|
void *thrctx = op->o_threadctx;
|
||||||
bm_context_t *bc;
|
bm_context_t *bc;
|
||||||
SlapReply *candidates;
|
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",
|
Debug(LDAP_DEBUG_ARGS, "==> asyncmeta_back_modify: %s\n",
|
||||||
op->o_req_dn.bv_val );
|
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) {
|
if (bc == NULL) {
|
||||||
rs->sr_err = LDAP_OTHER;
|
rs->sr_err = LDAP_OTHER;
|
||||||
asyncmeta_sender_error(op, rs, cb);
|
send_ldap_result(op, rs);
|
||||||
return rs->sr_err;
|
return rs->sr_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
candidates = bc->candidates;
|
candidates = bc->candidates;
|
||||||
mc = asyncmeta_getconn( op, rs, candidates, &candidate, LDAP_BACK_DONTSEND, 0);
|
mc = asyncmeta_getconn( op, rs, candidates, &candidate, LDAP_BACK_DONTSEND, 0);
|
||||||
if ( !mc || rs->sr_err != LDAP_SUCCESS) {
|
if ( !mc || rs->sr_err != LDAP_SUCCESS) {
|
||||||
asyncmeta_sender_error(op, rs, cb);
|
send_ldap_result(op, rs);
|
||||||
asyncmeta_clear_bm_context(bc);
|
|
||||||
return rs->sr_err;
|
return rs->sr_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -281,16 +269,38 @@ asyncmeta_back_modify( Operation *op, SlapReply *rs )
|
||||||
bc->retrying = LDAP_BACK_RETRYING;
|
bc->retrying = LDAP_BACK_RETRYING;
|
||||||
bc->sendok = ( LDAP_BACK_SENDRESULT | bc->retrying );
|
bc->sendok = ( LDAP_BACK_SENDRESULT | bc->retrying );
|
||||||
bc->stoptime = op->o_time + bc->timeout;
|
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);
|
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||||
rc = asyncmeta_add_message_queue(mc, bc);
|
rc = asyncmeta_add_message_queue(mc, bc);
|
||||||
|
mc->mc_conns[candidate].msc_active++;
|
||||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||||
|
|
||||||
if (rc != LDAP_SUCCESS) {
|
if (rc != LDAP_SUCCESS) {
|
||||||
rs->sr_err = LDAP_BUSY;
|
rs->sr_err = LDAP_BUSY;
|
||||||
rs->sr_text = "Maximum pending ops limit exceeded";
|
rs->sr_text = "Maximum pending ops limit exceeded";
|
||||||
asyncmeta_clear_bm_context(bc);
|
send_ldap_result(op, rs);
|
||||||
asyncmeta_sender_error(op, rs, cb);
|
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;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -300,70 +310,49 @@ asyncmeta_back_modify( Operation *op, SlapReply *rs )
|
||||||
case META_SEARCH_CANDIDATE:
|
case META_SEARCH_CANDIDATE:
|
||||||
/* target is already bound, just send the request */
|
/* target is already bound, just send the request */
|
||||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_modify: "
|
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) {
|
if (rc == META_SEARCH_ERR) {
|
||||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||||
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;
|
goto finish;
|
||||||
|
|
||||||
|
} else if (rc == META_SEARCH_NEED_BIND) {
|
||||||
|
goto retry;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case META_SEARCH_NOT_CANDIDATE:
|
case META_SEARCH_NOT_CANDIDATE:
|
||||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_modify: NOT_CANDIDATE "
|
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_modify: NOT_CANDIDATE "
|
||||||
"cnd=\"%ld\"\n", op->o_log_prefix, candidate );
|
"cnd=\"%d\"\n", op->o_log_prefix, candidate );
|
||||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||||
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;
|
goto finish;
|
||||||
|
|
||||||
case META_SEARCH_NEED_BIND:
|
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:
|
case META_SEARCH_BINDING:
|
||||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_modify: 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
|
/* Todo add the context to the message queue but do not send the request
|
||||||
the receiver must send this when we are done binding */
|
the receiver must send this when we are done binding */
|
||||||
/* question - how would do receiver know to which targets??? */
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case META_SEARCH_ERR:
|
case META_SEARCH_ERR:
|
||||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_modify: ERR "
|
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_modify: ERR "
|
||||||
"cnd=\"%ldd\"\n", op->o_log_prefix, candidate );
|
"cnd=\"%d\"\n", op->o_log_prefix, candidate );
|
||||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||||
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;
|
goto finish;
|
||||||
default:
|
default:
|
||||||
assert( 0 );
|
assert( 0 );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||||
|
mc->mc_conns[candidate].msc_active--;
|
||||||
asyncmeta_start_one_listener(mc, candidates, bc, candidate);
|
asyncmeta_start_one_listener(mc, candidates, bc, candidate);
|
||||||
|
bc->bc_active--;
|
||||||
|
asyncmeta_memctx_toggle(thrctx);
|
||||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||||
|
rs->sr_err = SLAPD_ASYNCOP;
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
return rs->sr_err;
|
return rs->sr_err;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,19 +26,19 @@
|
||||||
|
|
||||||
#include <ac/socket.h>
|
#include <ac/socket.h>
|
||||||
#include <ac/string.h>
|
#include <ac/string.h>
|
||||||
|
|
||||||
#include "slap.h"
|
#include "slap.h"
|
||||||
#include "../back-ldap/back-ldap.h"
|
|
||||||
#include "back-asyncmeta.h"
|
|
||||||
#include "../../../libraries/liblber/lber-int.h"
|
#include "../../../libraries/liblber/lber-int.h"
|
||||||
#include "../../../libraries/libldap/ldap-int.h"
|
#include "../../../libraries/libldap/ldap-int.h"
|
||||||
|
#include "../back-ldap/back-ldap.h"
|
||||||
|
#include "back-asyncmeta.h"
|
||||||
|
|
||||||
meta_search_candidate_t
|
meta_search_candidate_t
|
||||||
asyncmeta_back_modrdn_start(Operation *op,
|
asyncmeta_back_modrdn_start(Operation *op,
|
||||||
SlapReply *rs,
|
SlapReply *rs,
|
||||||
a_metaconn_t *mc,
|
a_metaconn_t *mc,
|
||||||
bm_context_t *bc,
|
bm_context_t *bc,
|
||||||
int candidate)
|
int candidate,
|
||||||
|
int do_lock)
|
||||||
{
|
{
|
||||||
a_dncookie dc;
|
a_dncookie dc;
|
||||||
a_metainfo_t *mi = mc->mc_info;
|
a_metainfo_t *mi = mc->mc_info;
|
||||||
|
|
@ -46,7 +46,7 @@ asyncmeta_back_modrdn_start(Operation *op,
|
||||||
struct berval mdn = BER_BVNULL,
|
struct berval mdn = BER_BVNULL,
|
||||||
mnewSuperior = BER_BVNULL,
|
mnewSuperior = BER_BVNULL,
|
||||||
newrdn = BER_BVNULL;
|
newrdn = BER_BVNULL;
|
||||||
int rc = 0, nretries = 1;
|
int rc = 0;
|
||||||
LDAPControl **ctrls = NULL;
|
LDAPControl **ctrls = NULL;
|
||||||
meta_search_candidate_t retcode = META_SEARCH_CANDIDATE;
|
meta_search_candidate_t retcode = META_SEARCH_CANDIDATE;
|
||||||
BerElement *ber = NULL;
|
BerElement *ber = NULL;
|
||||||
|
|
@ -54,9 +54,10 @@ asyncmeta_back_modrdn_start(Operation *op,
|
||||||
SlapReply *candidates = bc->candidates;
|
SlapReply *candidates = bc->candidates;
|
||||||
ber_int_t msgid;
|
ber_int_t msgid;
|
||||||
|
|
||||||
|
dc.op = op;
|
||||||
dc.target = mt;
|
dc.target = mt;
|
||||||
dc.conn = op->o_conn;
|
dc.memctx = op->o_tmpmemctx;
|
||||||
dc.rs = rs;
|
dc.to_from = MASSAGE_REQ;
|
||||||
|
|
||||||
if ( op->orr_newSup ) {
|
if ( op->orr_newSup ) {
|
||||||
|
|
||||||
|
|
@ -101,23 +102,13 @@ asyncmeta_back_modrdn_start(Operation *op,
|
||||||
/*
|
/*
|
||||||
* Rewrite the new superior, if defined and required
|
* Rewrite the new superior, if defined and required
|
||||||
*/
|
*/
|
||||||
dc.ctx = "newSuperiorDN";
|
asyncmeta_dn_massage( &dc, op->orr_newSup, &mnewSuperior );
|
||||||
if ( asyncmeta_dn_massage( &dc, op->orr_newSup, &mnewSuperior ) ) {
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
retcode = META_SEARCH_ERR;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Rewrite the modrdn dn, if required
|
* Rewrite the modrdn dn, if required
|
||||||
*/
|
*/
|
||||||
dc.ctx = "modrDN";
|
asyncmeta_dn_massage( &dc, &op->o_req_dn, &mdn );
|
||||||
if ( asyncmeta_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
retcode = META_SEARCH_ERR;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* NOTE: we need to copy the newRDN in case it was formed
|
/* NOTE: we need to copy the newRDN in case it was formed
|
||||||
* from a DN by simply changing the length (ITS#5397) */
|
* 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' ) {
|
if ( newrdn.bv_val[ newrdn.bv_len ] != '\0' ) {
|
||||||
ber_dupbv_x( &newrdn, &op->orr_newrdn, op->o_tmpmemctx );
|
ber_dupbv_x( &newrdn, &op->orr_newrdn, op->o_tmpmemctx );
|
||||||
}
|
}
|
||||||
retry:;
|
|
||||||
|
asyncmeta_set_msc_time(msc);
|
||||||
ctrls = op->o_ctrls;
|
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;
|
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||||
retcode = META_SEARCH_ERR;
|
retcode = META_SEARCH_ERR;
|
||||||
goto done;
|
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,
|
ber = ldap_build_moddn_req( msc->msc_ld, mdn.bv_val, newrdn.bv_val,
|
||||||
mnewSuperior.bv_val, op->orr_deleteoldrdn, ctrls, NULL, &msgid);
|
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) {
|
if (ber) {
|
||||||
candidates[ candidate ].sr_msgid = msgid;
|
struct timeval tv = {0, mt->mt_network_timeout*1000};
|
||||||
rc = ldap_send_initial_request( msc->msc_ld, LDAP_REQ_MODRDN,
|
ber_socket_t s;
|
||||||
mdn.bv_val, ber, msgid );
|
|
||||||
if (rc == msgid)
|
if (!( LDAP_BACK_CONN_ISBOUND( msc )
|
||||||
rc = LDAP_SUCCESS;
|
|| LDAP_BACK_CONN_ISANON( msc )) || msc->msc_ld == NULL ) {
|
||||||
else
|
Debug( asyncmeta_debug, "msc %p not initialized at %s:%d\n", msc, __FILE__, __LINE__ );
|
||||||
rc = LDAP_SERVER_DOWN;
|
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 ) {
|
switch ( rc ) {
|
||||||
case LDAP_SUCCESS:
|
case LDAP_SUCCESS:
|
||||||
retcode = META_SEARCH_CANDIDATE;
|
retcode = META_SEARCH_CANDIDATE;
|
||||||
asyncmeta_set_msc_time(msc);
|
asyncmeta_set_msc_time(msc);
|
||||||
break;
|
goto done;
|
||||||
|
|
||||||
case LDAP_SERVER_DOWN:
|
case LDAP_SERVER_DOWN:
|
||||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
/* do not lock if called from asyncmeta_handle_bind_result. Also do not reset the connection */
|
||||||
asyncmeta_clear_one_msc(NULL, mc, candidate);
|
if (do_lock > 0) {
|
||||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||||
if ( nretries && asyncmeta_retry( op, rs, &mc, candidate, LDAP_BACK_DONTSEND ) ) {
|
asyncmeta_reset_msc(NULL, mc, candidate, 0, __FUNCTION__ );
|
||||||
nretries = 0;
|
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||||
/* if the identity changed, there might be need to re-authz */
|
|
||||||
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
|
||||||
goto retry;
|
|
||||||
}
|
}
|
||||||
|
/* fall though*/
|
||||||
default:
|
default:
|
||||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
Debug( asyncmeta_debug, "msc %p ldap_send_initial_request failed. %s:%d\n", msc, __FILE__, __LINE__ );
|
||||||
retcode = META_SEARCH_ERR;
|
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:
|
done:
|
||||||
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
||||||
|
|
||||||
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
|
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
|
||||||
free( mdn.bv_val );
|
op->o_tmpfree( mdn.bv_val, op->o_tmpmemctx );
|
||||||
BER_BVZERO( &mdn );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !BER_BVISNULL( &mnewSuperior )
|
if ( !BER_BVISNULL( &mnewSuperior )
|
||||||
&& mnewSuperior.bv_val != op->orr_newSup->bv_val )
|
&& mnewSuperior.bv_val != op->orr_newSup->bv_val )
|
||||||
{
|
{
|
||||||
free( mnewSuperior.bv_val );
|
op->o_tmpfree( mnewSuperior.bv_val, op->o_tmpmemctx );
|
||||||
BER_BVZERO( &mnewSuperior );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( newrdn.bv_val != op->orr_newrdn.bv_val ) {
|
if ( newrdn.bv_val != op->orr_newrdn.bv_val ) {
|
||||||
op->o_tmpfree( newrdn.bv_val, op->o_tmpmemctx );
|
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 );
|
Debug( LDAP_DEBUG_TRACE, "%s <<< asyncmeta_back_modrdn_start[%p]=%d\n", op->o_log_prefix, msc, candidates[candidate].sr_msgid );
|
||||||
return retcode;
|
return retcode;
|
||||||
}
|
}
|
||||||
|
|
@ -199,26 +246,30 @@ asyncmeta_back_modrdn( Operation *op, SlapReply *rs )
|
||||||
a_metatarget_t *mt;
|
a_metatarget_t *mt;
|
||||||
a_metaconn_t *mc;
|
a_metaconn_t *mc;
|
||||||
int rc, candidate = -1;
|
int rc, candidate = -1;
|
||||||
OperationBuffer opbuf;
|
void *thrctx = op->o_threadctx;
|
||||||
bm_context_t *bc;
|
bm_context_t *bc;
|
||||||
SlapReply *candidates;
|
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",
|
Debug(LDAP_DEBUG_ARGS, "==> asyncmeta_back_modrdn: %s\n",
|
||||||
op->o_req_dn.bv_val );
|
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) {
|
if (bc == NULL) {
|
||||||
rs->sr_err = LDAP_OTHER;
|
rs->sr_err = LDAP_OTHER;
|
||||||
asyncmeta_sender_error(op, rs, cb);
|
send_ldap_result(op, rs);
|
||||||
return rs->sr_err;
|
return rs->sr_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
candidates = bc->candidates;
|
candidates = bc->candidates;
|
||||||
mc = asyncmeta_getconn( op, rs, candidates, &candidate, LDAP_BACK_DONTSEND, 0);
|
mc = asyncmeta_getconn( op, rs, candidates, &candidate, LDAP_BACK_DONTSEND, 0);
|
||||||
if ( !mc || rs->sr_err != LDAP_SUCCESS) {
|
if ( !mc || rs->sr_err != LDAP_SUCCESS) {
|
||||||
asyncmeta_sender_error(op, rs, cb);
|
send_ldap_result(op, rs);
|
||||||
asyncmeta_clear_bm_context(bc);
|
|
||||||
return rs->sr_err;
|
return rs->sr_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -227,66 +278,69 @@ asyncmeta_back_modrdn( Operation *op, SlapReply *rs )
|
||||||
bc->retrying = LDAP_BACK_RETRYING;
|
bc->retrying = LDAP_BACK_RETRYING;
|
||||||
bc->sendok = ( LDAP_BACK_SENDRESULT | bc->retrying );
|
bc->sendok = ( LDAP_BACK_SENDRESULT | bc->retrying );
|
||||||
bc->stoptime = op->o_time + bc->timeout;
|
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);
|
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||||
rc = asyncmeta_add_message_queue(mc, bc);
|
rc = asyncmeta_add_message_queue(mc, bc);
|
||||||
|
mc->mc_conns[candidate].msc_active++;
|
||||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||||
|
|
||||||
if (rc != LDAP_SUCCESS) {
|
if (rc != LDAP_SUCCESS) {
|
||||||
rs->sr_err = LDAP_BUSY;
|
rs->sr_err = LDAP_BUSY;
|
||||||
rs->sr_text = "Maximum pending ops limit exceeded";
|
rs->sr_text = "Maximum pending ops limit exceeded";
|
||||||
asyncmeta_clear_bm_context(bc);
|
send_ldap_result(op, rs);
|
||||||
asyncmeta_sender_error(op, rs, cb);
|
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;
|
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);
|
rc = asyncmeta_dobind_init_with_retry(op, rs, bc, mc, candidate);
|
||||||
switch (rc)
|
switch (rc)
|
||||||
{
|
{
|
||||||
case META_SEARCH_CANDIDATE:
|
case META_SEARCH_CANDIDATE:
|
||||||
/* target is already bound, just send the request */
|
/* target is already bound, just send the request */
|
||||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_modrdn: "
|
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) {
|
if (rc == META_SEARCH_ERR) {
|
||||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||||
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;
|
goto finish;
|
||||||
|
|
||||||
|
} else if (rc == META_SEARCH_NEED_BIND) {
|
||||||
|
goto retry;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case META_SEARCH_NOT_CANDIDATE:
|
case META_SEARCH_NOT_CANDIDATE:
|
||||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_modrdn: NOT_CANDIDATE "
|
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_modrdn: NOT_CANDIDATE "
|
||||||
"cnd=\"%ld\"\n", op->o_log_prefix, candidate );
|
"cnd=\"%d\"\n", op->o_log_prefix, candidate );
|
||||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||||
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;
|
goto finish;
|
||||||
|
|
||||||
case META_SEARCH_NEED_BIND:
|
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:
|
case META_SEARCH_BINDING:
|
||||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_modrdn: 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
|
/* Todo add the context to the message queue but do not send the request
|
||||||
the receiver must send this when we are done binding */
|
the receiver must send this when we are done binding */
|
||||||
/* question - how would do receiver know to which targets??? */
|
/* question - how would do receiver know to which targets??? */
|
||||||
|
|
@ -294,22 +348,21 @@ asyncmeta_back_modrdn( Operation *op, SlapReply *rs )
|
||||||
|
|
||||||
case META_SEARCH_ERR:
|
case META_SEARCH_ERR:
|
||||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_modrdn: ERR "
|
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_modrdn: ERR "
|
||||||
"cnd=\"%ldd\"\n", op->o_log_prefix, candidate );
|
"cnd=\"%d\"\n", op->o_log_prefix, candidate );
|
||||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
asyncmeta_error_cleanup(op, rs, bc, mc, candidate);
|
||||||
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;
|
goto finish;
|
||||||
default:
|
default:
|
||||||
assert( 0 );
|
assert( 0 );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||||
|
mc->mc_conns[candidate].msc_active--;
|
||||||
asyncmeta_start_one_listener(mc, candidates, bc, candidate);
|
asyncmeta_start_one_listener(mc, candidates, bc, candidate);
|
||||||
|
bc->bc_active--;
|
||||||
|
asyncmeta_memctx_toggle(thrctx);
|
||||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||||
|
rs->sr_err = SLAPD_ASYNCOP;
|
||||||
finish:
|
finish:
|
||||||
return rs->sr_err;
|
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_modrdn asyncmeta_back_modrdn;
|
||||||
extern BI_op_add asyncmeta_back_add;
|
extern BI_op_add asyncmeta_back_add;
|
||||||
extern BI_op_delete asyncmeta_back_delete;
|
extern BI_op_delete asyncmeta_back_delete;
|
||||||
extern BI_op_abandon asyncmeta_back_abandon;
|
|
||||||
|
|
||||||
extern BI_connection_destroy asyncmeta_back_conn_destroy;
|
extern BI_connection_destroy asyncmeta_back_conn_destroy;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,59 +27,297 @@
|
||||||
#include <ac/socket.h>
|
#include <ac/socket.h>
|
||||||
#include <ac/string.h>
|
#include <ac/string.h>
|
||||||
#include <ac/time.h>
|
#include <ac/time.h>
|
||||||
|
|
||||||
#include "lutil.h"
|
|
||||||
#include "slap.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-ldap/back-ldap.h"
|
||||||
#include "back-asyncmeta.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
|
static void
|
||||||
asyncmeta_handle_onerr_stop(Operation *op,
|
asyncmeta_handle_onerr_stop(Operation *op,
|
||||||
SlapReply *rs,
|
SlapReply *rs,
|
||||||
a_metaconn_t *mc,
|
a_metaconn_t *mc,
|
||||||
bm_context_t *bc,
|
bm_context_t *bc,
|
||||||
int candidate,
|
int candidate)
|
||||||
slap_callback *cb)
|
|
||||||
{
|
{
|
||||||
a_metainfo_t *mi = mc->mc_info;
|
a_metainfo_t *mi = mc->mc_info;
|
||||||
int j;
|
int j;
|
||||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
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);
|
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bc->bc_active = 1;
|
|
||||||
asyncmeta_drop_bc(mc, bc);
|
asyncmeta_drop_bc(mc, bc);
|
||||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
|
||||||
|
|
||||||
for (j=0; j<mi->mi_ntargets; j++) {
|
for (j=0; j<mi->mi_ntargets; j++) {
|
||||||
if (j != candidate && bc->candidates[j].sr_msgid >= 0
|
if (j != candidate && bc->candidates[j].sr_msgid >= 0
|
||||||
&& mc->mc_conns[j].msc_ld != NULL) {
|
&& mc->mc_conns[j].msc_ld != NULL && !META_BACK_CONN_CREATING( &mc->mc_conns[j] )) {
|
||||||
asyncmeta_back_abandon_candidate( mc, op,
|
asyncmeta_back_cancel( mc, op,
|
||||||
bc->candidates[ j ].sr_msgid, j );
|
bc->candidates[ j ].sr_msgid, j );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cb != NULL) {
|
slap_sl_mem_setctx(op->o_threadctx, op->o_tmpmemctx);
|
||||||
op->o_callback = cb;
|
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||||
}
|
|
||||||
send_ldap_result(op, rs);
|
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
|
meta_search_candidate_t
|
||||||
asyncmeta_back_search_start(
|
asyncmeta_back_search_start(
|
||||||
Operation *op,
|
Operation *op,
|
||||||
SlapReply *rs,
|
SlapReply *rs,
|
||||||
a_metaconn_t *mc,
|
a_metaconn_t *mc,
|
||||||
bm_context_t *bc,
|
bm_context_t *bc,
|
||||||
int candidate,
|
int candidate,
|
||||||
struct berval *prcookie,
|
struct berval *prcookie,
|
||||||
ber_int_t prsize )
|
ber_int_t prsize,
|
||||||
|
int do_lock)
|
||||||
{
|
{
|
||||||
SlapReply *candidates = bc->candidates;
|
SlapReply *candidates = bc->candidates;
|
||||||
a_metainfo_t *mi = ( a_metainfo_t * )mc->mc_info;
|
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_metasingleconn_t *msc = &mc->mc_conns[ candidate ];
|
||||||
a_dncookie dc;
|
a_dncookie dc;
|
||||||
struct berval realbase = op->o_req_dn;
|
struct berval realbase = op->o_req_dn;
|
||||||
|
char **attrs;
|
||||||
int realscope = op->ors_scope;
|
int realscope = op->ors_scope;
|
||||||
struct berval mbase = BER_BVNULL;
|
struct berval mbase = BER_BVNULL;
|
||||||
struct berval mfilter = BER_BVNULL;
|
|
||||||
char **mapped_attrs = NULL;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
struct berval filterbv = BER_BVNULL;
|
||||||
meta_search_candidate_t retcode;
|
meta_search_candidate_t retcode;
|
||||||
int timelimit;
|
int timelimit;
|
||||||
int nretries = 1;
|
|
||||||
LDAPControl **ctrls = NULL;
|
LDAPControl **ctrls = NULL;
|
||||||
BerElement *ber;
|
BerElement *ber = NULL;
|
||||||
ber_int_t msgid;
|
ber_int_t msgid;
|
||||||
#ifdef SLAPD_META_CLIENT_PR
|
#ifdef SLAPD_META_CLIENT_PR
|
||||||
LDAPControl **save_ctrls = NULL;
|
LDAPControl **save_ctrls = NULL;
|
||||||
|
|
@ -116,7 +353,8 @@ asyncmeta_back_search_start(
|
||||||
return META_SEARCH_NOT_CANDIDATE;
|
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
|
* modifies the base according to the scope, if required
|
||||||
*/
|
*/
|
||||||
|
|
@ -199,59 +437,13 @@ asyncmeta_back_search_start(
|
||||||
/*
|
/*
|
||||||
* Rewrite the search base, if required
|
* Rewrite the search base, if required
|
||||||
*/
|
*/
|
||||||
|
dc.op = op;
|
||||||
dc.target = mt;
|
dc.target = mt;
|
||||||
dc.ctx = "searchBase";
|
dc.memctx = op->o_tmpmemctx;
|
||||||
dc.conn = op->o_conn;
|
dc.to_from = MASSAGE_REQ;
|
||||||
dc.rs = rs;
|
asyncmeta_dn_massage( &dc, &realbase, &mbase );
|
||||||
switch ( asyncmeta_dn_massage( &dc, &realbase, &mbase ) ) {
|
|
||||||
case LDAP_SUCCESS:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LDAP_UNWILLING_TO_PERFORM:
|
attrs = anlist2charray_x( op->ors_attrs, 0, op->o_tmpmemctx );
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( op->ors_tlimit != SLAP_NO_LIMIT ) {
|
if ( op->ors_tlimit != SLAP_NO_LIMIT ) {
|
||||||
timelimit = op->ors_tlimit > 0 ? op->ors_tlimit : 1;
|
timelimit = op->ors_tlimit > 0 ? op->ors_tlimit : 1;
|
||||||
|
|
@ -338,21 +530,10 @@ done_pr:;
|
||||||
}
|
}
|
||||||
#endif /* SLAPD_META_CLIENT_PR */
|
#endif /* SLAPD_META_CLIENT_PR */
|
||||||
|
|
||||||
retry:;
|
|
||||||
asyncmeta_set_msc_time(msc);
|
asyncmeta_set_msc_time(msc);
|
||||||
ctrls = op->o_ctrls;
|
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 )
|
!= LDAP_SUCCESS )
|
||||||
{
|
{
|
||||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||||
|
|
@ -363,48 +544,114 @@ retry:;
|
||||||
/*
|
/*
|
||||||
* Starts the search
|
* 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,
|
ber = ldap_build_search_req( msc->msc_ld,
|
||||||
mbase.bv_val, realscope, mfilter.bv_val,
|
mbase.bv_val, realscope, filterbv.bv_val,
|
||||||
mapped_attrs, op->ors_attrsonly,
|
attrs, op->ors_attrsonly,
|
||||||
ctrls, NULL, timelimit, op->ors_slimit, op->ors_deref,
|
ctrls, NULL, timelimit, op->ors_slimit, op->ors_deref,
|
||||||
&msgid );
|
&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) {
|
if (ber) {
|
||||||
candidates[ candidate ].sr_msgid = msgid;
|
struct timeval tv = {0, mt->mt_network_timeout*1000};
|
||||||
rc = ldap_send_initial_request( msc->msc_ld, LDAP_REQ_SEARCH,
|
ber_socket_t s;
|
||||||
mbase.bv_val, ber, msgid );
|
|
||||||
if (rc == msgid)
|
if (!( LDAP_BACK_CONN_ISBOUND( msc )
|
||||||
rc = LDAP_SUCCESS;
|
|| LDAP_BACK_CONN_ISANON( msc )) || msc->msc_ld == NULL ) {
|
||||||
else
|
Debug( asyncmeta_debug, "msc %p not initialized at %s:%d\n", msc, __FILE__, __LINE__ );
|
||||||
rc = LDAP_SERVER_DOWN;
|
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 ) {
|
switch ( rc ) {
|
||||||
case LDAP_SUCCESS:
|
case LDAP_SUCCESS:
|
||||||
retcode = META_SEARCH_CANDIDATE;
|
retcode = META_SEARCH_CANDIDATE;
|
||||||
asyncmeta_set_msc_time(msc);
|
asyncmeta_set_msc_time(msc);
|
||||||
break;
|
goto done;
|
||||||
|
|
||||||
case LDAP_SERVER_DOWN:
|
case LDAP_SERVER_DOWN:
|
||||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
/* do not lock if called from asyncmeta_handle_bind_result. Also do not reset the connection */
|
||||||
if (mc->mc_active < 1) {
|
if (do_lock > 0) {
|
||||||
asyncmeta_clear_one_msc(NULL, mc, candidate);
|
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);
|
Debug( asyncmeta_debug, "msc %p ldap_send_initial_request failed. %s:%d\n", msc, __FILE__, __LINE__ );
|
||||||
if ( nretries && asyncmeta_retry( op, rs, &mc, candidate, LDAP_BACK_DONTSEND ) ) {
|
goto error_unavailable;
|
||||||
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;
|
|
||||||
default:
|
default:
|
||||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||||
retcode = META_SEARCH_NOT_CANDIDATE;
|
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:;
|
done:;
|
||||||
|
#if 0
|
||||||
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
|
||||||
|
#endif
|
||||||
#ifdef SLAPD_META_CLIENT_PR
|
#ifdef SLAPD_META_CLIENT_PR
|
||||||
if ( save_ctrls != op->o_ctrls ) {
|
if ( save_ctrls != op->o_ctrls ) {
|
||||||
op->o_tmpfree( op->o_ctrls, op->o_tmpmemctx );
|
op->o_tmpfree( op->o_ctrls, op->o_tmpmemctx );
|
||||||
|
|
@ -412,14 +659,8 @@ done:;
|
||||||
}
|
}
|
||||||
#endif /* SLAPD_META_CLIENT_PR */
|
#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 ) {
|
if ( mbase.bv_val != realbase.bv_val ) {
|
||||||
free( mbase.bv_val );
|
op->o_tmpfree( mbase.bv_val, op->o_tmpmemctx );
|
||||||
}
|
}
|
||||||
|
|
||||||
doreturn:;
|
doreturn:;
|
||||||
|
|
@ -431,25 +672,16 @@ int
|
||||||
asyncmeta_back_search( Operation *op, SlapReply *rs )
|
asyncmeta_back_search( Operation *op, SlapReply *rs )
|
||||||
{
|
{
|
||||||
a_metainfo_t *mi = ( a_metainfo_t * )op->o_bd->be_private;
|
a_metainfo_t *mi = ( a_metainfo_t * )op->o_bd->be_private;
|
||||||
struct timeval save_tv = { 0, 0 },
|
time_t timeout = 0;
|
||||||
tv;
|
int rc = 0;
|
||||||
time_t stoptime = (time_t)(-1),
|
int ncandidates = 0, initial_candidates = 0;
|
||||||
lastres_time = slap_get_time(),
|
long i;
|
||||||
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;
|
|
||||||
SlapReply *candidates = NULL;
|
SlapReply *candidates = NULL;
|
||||||
int do_taint = 0;
|
void *thrctx = op->o_threadctx;
|
||||||
bm_context_t *bc;
|
bm_context_t *bc;
|
||||||
a_metaconn_t *mc;
|
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_assert_ready( rs );
|
||||||
rs->sr_flags &= ~REP_ENTRY_MASK; /* paranoia, we can set rs = non-entry */
|
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
|
* 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) {
|
if (bc == NULL) {
|
||||||
rs->sr_err = LDAP_OTHER;
|
rs->sr_err = LDAP_OTHER;
|
||||||
send_ldap_result(op, rs);
|
send_ldap_result(op, rs);
|
||||||
|
|
@ -471,9 +703,7 @@ asyncmeta_back_search( Operation *op, SlapReply *rs )
|
||||||
candidates = bc->candidates;
|
candidates = bc->candidates;
|
||||||
mc = asyncmeta_getconn( op, rs, candidates, NULL, LDAP_BACK_DONTSEND, 0);
|
mc = asyncmeta_getconn( op, rs, candidates, NULL, LDAP_BACK_DONTSEND, 0);
|
||||||
if ( !mc || rs->sr_err != LDAP_SUCCESS) {
|
if ( !mc || rs->sr_err != LDAP_SUCCESS) {
|
||||||
op->o_callback = cb;
|
|
||||||
send_ldap_result(op, rs);
|
send_ldap_result(op, rs);
|
||||||
asyncmeta_clear_bm_context(bc);
|
|
||||||
return rs->sr_err;
|
return rs->sr_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -511,27 +741,33 @@ asyncmeta_back_search( Operation *op, SlapReply *rs )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bc->timeout = timeout;
|
if ( op->ors_tlimit != SLAP_NO_LIMIT && (timeout == 0 || op->ors_tlimit < timeout)) {
|
||||||
bc->stoptime = op->o_time + bc->timeout;
|
bc->searchtime = 1;
|
||||||
|
bc->timeout = op->ors_tlimit;
|
||||||
|
} else {
|
||||||
|
bc->timeout = timeout;
|
||||||
|
}
|
||||||
|
|
||||||
if ( op->ors_tlimit != SLAP_NO_LIMIT ) {
|
bc->stoptime = op->o_time + bc->timeout;
|
||||||
stoptime = op->o_time + op->ors_tlimit;
|
bc->bc_active = 1;
|
||||||
if (stoptime < bc->stoptime) {
|
|
||||||
bc->stoptime = stoptime;
|
if (mc->pending_ops >= max_pending_ops) {
|
||||||
bc->searchtime = 1;
|
rs->sr_err = LDAP_BUSY;
|
||||||
bc->timeout = op->ors_tlimit;
|
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);
|
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||||
rc = asyncmeta_add_message_queue(mc, bc);
|
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);
|
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||||
|
|
||||||
if (rc != LDAP_SUCCESS) {
|
if (rc != LDAP_SUCCESS) {
|
||||||
rs->sr_err = LDAP_BUSY;
|
rs->sr_err = LDAP_BUSY;
|
||||||
rs->sr_text = "Maximum pending ops limit exceeded";
|
rs->sr_text = "Maximum pending ops limit exceeded";
|
||||||
asyncmeta_clear_bm_context(bc);
|
|
||||||
op->o_callback = cb;
|
|
||||||
send_ldap_result(op, rs);
|
send_ldap_result(op, rs);
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
@ -542,6 +778,30 @@ asyncmeta_back_search( Operation *op, SlapReply *rs )
|
||||||
{
|
{
|
||||||
continue;
|
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);
|
rc = asyncmeta_dobind_init_with_retry(op, rs, bc, mc, i);
|
||||||
switch (rc)
|
switch (rc)
|
||||||
|
|
@ -552,17 +812,19 @@ asyncmeta_back_search( Operation *op, SlapReply *rs )
|
||||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_search: IS_CANDIDATE "
|
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_search: IS_CANDIDATE "
|
||||||
"cnd=\"%ld\"\n", op->o_log_prefix, i );
|
"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) {
|
if (rc == META_SEARCH_ERR) {
|
||||||
META_CANDIDATE_CLEAR(&candidates[i]);
|
META_CANDIDATE_CLEAR(&candidates[i]);
|
||||||
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
|
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
|
||||||
if ( META_BACK_ONERR_STOP( mi ) ) {
|
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;
|
goto finish;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
} else if (rc == META_SEARCH_NEED_BIND) {
|
||||||
|
goto retry;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case META_SEARCH_NOT_CANDIDATE:
|
case META_SEARCH_NOT_CANDIDATE:
|
||||||
|
|
@ -572,22 +834,6 @@ asyncmeta_back_search( Operation *op, SlapReply *rs )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case META_SEARCH_NEED_BIND:
|
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:
|
case META_SEARCH_BINDING:
|
||||||
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_search: BINDING "
|
Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_search: BINDING "
|
||||||
"cnd=\"%ld\" %p\n", op->o_log_prefix, i , &mc->mc_conns[i]);
|
"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;
|
candidates[ i ].sr_type = REP_RESULT;
|
||||||
|
|
||||||
if ( META_BACK_ONERR_STOP( mi ) ) {
|
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;
|
goto finish;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -666,14 +912,29 @@ asyncmeta_back_search( Operation *op, SlapReply *rs )
|
||||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
||||||
asyncmeta_drop_bc(mc, bc);
|
asyncmeta_drop_bc(mc, bc);
|
||||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||||
op->o_callback = cb;
|
|
||||||
send_ldap_result(op, rs);
|
send_ldap_result(op, rs);
|
||||||
asyncmeta_clear_bm_context(bc);
|
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
|
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);
|
asyncmeta_start_listeners(mc, candidates, bc);
|
||||||
|
bc->bc_active--;
|
||||||
|
asyncmeta_memctx_toggle(thrctx);
|
||||||
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
|
||||||
|
rs->sr_err = SLAPD_ASYNCOP;
|
||||||
|
|
||||||
finish:
|
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;
|
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
|
# other backends
|
||||||
AC_ldap=ldap@BUILD_LDAP@
|
AC_ldap=ldap@BUILD_LDAP@
|
||||||
AC_meta=meta@BUILD_META@
|
AC_meta=meta@BUILD_META@
|
||||||
|
AC_asyncmeta=asyncmeta@BUILD_ASYNCMETA@
|
||||||
AC_monitor=@BUILD_MONITOR@
|
AC_monitor=@BUILD_MONITOR@
|
||||||
AC_relay=relay@BUILD_RELAY@
|
AC_relay=relay@BUILD_RELAY@
|
||||||
AC_sql=sql@BUILD_SQL@
|
AC_sql=sql@BUILD_SQL@
|
||||||
|
|
@ -70,8 +71,10 @@ fi
|
||||||
if test "${AC_meta}" = "metamod" && test "${AC_LIBS_DYNAMIC}" = "static" ; then
|
if test "${AC_meta}" = "metamod" && test "${AC_LIBS_DYNAMIC}" = "static" ; then
|
||||||
AC_meta="metano"
|
AC_meta="metano"
|
||||||
fi
|
fi
|
||||||
|
if test "${AC_asyncmeta}" = "metamod" && test "${AC_LIBS_DYNAMIC}" = "static" ; then
|
||||||
export AC_bdb AC_hdb AC_ldap AC_mdb AC_meta AC_monitor AC_null AC_relay AC_sql \
|
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_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_refint AC_retcode AC_rwm AC_unique AC_syncprov AC_translucent \
|
||||||
AC_valsort \
|
AC_valsort \
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ TESTWD=`pwd`
|
||||||
MONITORDB=${AC_monitor-no}
|
MONITORDB=${AC_monitor-no}
|
||||||
BACKLDAP=${AC_ldap-ldapno}
|
BACKLDAP=${AC_ldap-ldapno}
|
||||||
BACKMETA=${AC_meta-metano}
|
BACKMETA=${AC_meta-metano}
|
||||||
|
BACKASYNCMETA=${AC_asyncmeta-asyncmetano}
|
||||||
BACKRELAY=${AC_relay-relayno}
|
BACKRELAY=${AC_relay-relayno}
|
||||||
BACKSQL=${AC_sql-sqlno}
|
BACKSQL=${AC_sql-sqlno}
|
||||||
RDBMS=${SLAPD_USE_SQL-rdbmsno}
|
RDBMS=${SLAPD_USE_SQL-rdbmsno}
|
||||||
|
|
@ -134,6 +135,7 @@ TRANSLUCENTREMOTECONF=$DATADIR/slapd-translucent-remote.conf
|
||||||
METACONF=$DATADIR/slapd-meta.conf
|
METACONF=$DATADIR/slapd-meta.conf
|
||||||
METACONF1=$DATADIR/slapd-meta-target1.conf
|
METACONF1=$DATADIR/slapd-meta-target1.conf
|
||||||
METACONF2=$DATADIR/slapd-meta-target2.conf
|
METACONF2=$DATADIR/slapd-meta-target2.conf
|
||||||
|
ASYNCMETACONF=$DATADIR/slapd-asyncmeta.conf
|
||||||
GLUELDAPCONF=$DATADIR/slapd-glue-ldap.conf
|
GLUELDAPCONF=$DATADIR/slapd-glue-ldap.conf
|
||||||
ACICONF=$DATADIR/slapd-aci.conf
|
ACICONF=$DATADIR/slapd-aci.conf
|
||||||
VALSORTCONF=$DATADIR/slapd-valsort.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