From c853ba1f0e636eed8da26228f59eed6f90a4db27 Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Mon, 3 Apr 2006 00:32:59 +0000 Subject: [PATCH] more on recovery (ITS#4429) --- servers/slapd/back-meta/back-meta.h | 10 ++- servers/slapd/back-meta/bind.c | 96 +++++++++++++++++----------- servers/slapd/back-meta/candidates.c | 19 ++++++ servers/slapd/back-meta/conn.c | 25 ++------ servers/slapd/back-meta/search.c | 64 ++++++++++--------- 5 files changed, 129 insertions(+), 85 deletions(-) diff --git a/servers/slapd/back-meta/back-meta.h b/servers/slapd/back-meta/back-meta.h index 78bc791c3c..43d5fa3da5 100644 --- a/servers/slapd/back-meta/back-meta.h +++ b/servers/slapd/back-meta/back-meta.h @@ -299,8 +299,9 @@ extern void meta_back_release_conn_lock( Operation *op, metaconn_t *mc, + int dofree, int dolock ); -#define meta_back_release_conn(op, mc) meta_back_release_conn_lock( (op), (mc), 1 ) +#define meta_back_release_conn(op, mc) meta_back_release_conn_lock( (op), (mc), 0, 1 ) extern int meta_back_retry( @@ -343,7 +344,7 @@ extern int meta_back_single_dobind( Operation *op, SlapReply *rs, - metaconn_t *msc, + metaconn_t **mcp, int candidate, ldap_back_send_t sendok, int retries, @@ -401,6 +402,11 @@ extern int meta_clear_one_candidate( metasingleconn_t *mc ); +extern int +meta_clear_candidates( + Operation *op, + metaconn_t *mc ); + /* * Dn cache stuff (experimental) */ diff --git a/servers/slapd/back-meta/bind.c b/servers/slapd/back-meta/bind.c index 1ec7217ab5..1ca6a0a9e5 100644 --- a/servers/slapd/back-meta/bind.c +++ b/servers/slapd/back-meta/bind.c @@ -179,6 +179,10 @@ meta_back_bind( Operation *op, SlapReply *rs ) if ( lerr != LDAP_SUCCESS ) { rc = rs->sr_err = lerr; + /* FIXME: in some cases (e.g. unavailable) + * do not assume it's not candidate; rather + * mark this as an error to be eventually + * reported to client */ candidates[ i ].sr_tag = META_NOT_CANDIDATE; break; } @@ -214,11 +218,7 @@ retry_lock:; meta_back_conndn_cmp, meta_back_conndn_dup ); ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex ); if ( lerr == -1 ) { - for ( i = 0; i < mi->mi_ntargets; ++i ) { - if ( mc->mc_conns[ i ].msc_ld != NULL ) { - meta_clear_one_candidate( &mc->mc_conns[ i ] ); - } - } + meta_clear_candidates( op, mc ); /* we can do this because mc_refcnt == 1 */ mc->mc_refcnt = 0; @@ -305,8 +305,9 @@ meta_back_single_bind( dc.ctx = "bindDN"; if ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) { - send_ldap_result( op, rs ); - return -1; + rs->sr_text = "DN rewrite error"; + rs->sr_err = LDAP_OTHER; + return rs->sr_err; } } else { @@ -376,8 +377,8 @@ retry:; } snprintf( buf, sizeof( buf ), - "err=%d nretries=%d", - rs->sr_err, nretries ); + "err=%d (%s) nretries=%d", + rs->sr_err, ldap_err2string( rs->sr_err ), nretries ); Debug( LDAP_DEBUG_ANY, "### %s meta_back_single_bind[%d]: %s.\n", op->o_log_prefix, candidate, buf ); @@ -442,7 +443,7 @@ int meta_back_single_dobind( Operation *op, SlapReply *rs, - metaconn_t *mc, + metaconn_t **mcp, int candidate, ldap_back_send_t sendok, int nretries, @@ -450,6 +451,7 @@ meta_back_single_dobind( { metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private; metatarget_t *mt = &mi->mi_targets[ candidate ]; + metaconn_t *mc = *mcp; metasingleconn_t *msc = &mc->mc_conns[ candidate ]; int rc; static struct berval cred = BER_BVC( "" ); @@ -459,6 +461,24 @@ meta_back_single_dobind( assert( !LDAP_BACK_CONN_ISBOUND( msc ) ); + /* + * meta_back_single_dobind() calls meta_back_single_bind() + * if required. + */ + if ( be_isroot( op ) && !BER_BVISNULL( &mi->mi_targets[ candidate ].mt_pseudorootdn ) ) + { + Operation op2 = *op; + + op2.o_tag = LDAP_REQ_BIND; + op2.o_req_dn = mi->mi_targets[ candidate ].mt_pseudorootdn; + op2.o_req_ndn = mi->mi_targets[ candidate ].mt_pseudorootdn; + op2.orb_cred = mi->mi_targets[ candidate ].mt_pseudorootpw; + op2.orb_method = LDAP_AUTH_SIMPLE; + + rc = meta_back_single_bind( &op2, rs, *mcp, candidate, 0 ); + goto done; + } + /* * Otherwise an anonymous bind is performed * (note: if the target was already bound, the anonymous @@ -533,8 +553,8 @@ retry:; } snprintf( buf, sizeof( buf ), - "err=%d nretries=%d", - rs->sr_err, nretries ); + "err=%d (%s) nretries=%d", + rs->sr_err, ldap_err2string( rs->sr_err ), nretries ); Debug( LDAP_DEBUG_ANY, "### %s meta_back_single_dobind[%d]: %s.\n", op->o_log_prefix, candidate, buf ); @@ -591,9 +611,15 @@ retry:; rc = slap_map_api2result( rs ); } +done:; rs->sr_err = rc; - if ( rc != LDAP_SUCCESS && ( sendok & LDAP_BACK_SENDERR ) ) { - send_ldap_result( op, rs ); + if ( rc != LDAP_SUCCESS && META_BACK_ONERR_STOP( mi ) ) { + meta_back_release_conn_lock( op, mc, 1, dolock ); + *mcp = NULL; + + if ( sendok & LDAP_BACK_SENDERR ) { + send_ldap_result( op, rs ); + } } return rc; @@ -659,28 +685,21 @@ meta_back_dobind( } retry:; - if ( isroot && !BER_BVISNULL( &mi->mi_targets[ i ].mt_pseudorootdn ) ) - { - Operation op2 = *op; - - op2.o_tag = LDAP_REQ_BIND; - op2.o_req_dn = mi->mi_targets[ i ].mt_pseudorootdn; - op2.o_req_ndn = mi->mi_targets[ i ].mt_pseudorootdn; - op2.orb_cred = mi->mi_targets[ i ].mt_pseudorootpw; - op2.orb_method = LDAP_AUTH_SIMPLE; - - rootdn = mi->mi_targets[ i ].mt_pseudorootdn.bv_val; - - rc = meta_back_single_bind( &op2, rs, mc, i, 0 ); - - } else { - rc = meta_back_single_dobind( op, rs, mc, i, - LDAP_BACK_DONTSEND, mt->mt_nretries, 1 ); - } - + rc = meta_back_single_dobind( op, rs, &mc, i, + LDAP_BACK_DONTSEND, mt->mt_nretries, 1 ); + /* + * NOTE: meta_back_single_dobind() already retries; + * in case of failure, it resets mc... + */ if ( rc != LDAP_SUCCESS ) { char buf[ SLAP_TEXT_BUFLEN ]; + if ( mc == NULL ) { + /* meta_back_single_dobind() already sent + * response and released connection */ + goto send_err; + } + if ( rc == LDAP_UNAVAILABLE && do_retry ) { do_retry = 0; if ( meta_back_retry( op, rs, &mc, i, sendok ) ) { @@ -690,8 +709,9 @@ retry:; } snprintf( buf, sizeof( buf ), - "meta_back_dobind[%d]: (%s) err=%d.", - i, rootdn ? rootdn : "anonymous", rc ); + "meta_back_dobind[%d]: (%s) err=%d (%s).", + i, rootdn ? rootdn : "anonymous", + rc, ldap_err2string( rc ) ); Debug( LDAP_DEBUG_ANY, "%s %s\n", op->o_log_prefix, buf, 0 ); @@ -709,6 +729,7 @@ retry:; bound = 0; goto done; } + continue; } /* else */ @@ -734,15 +755,18 @@ done:; if ( bound == 0 ) { meta_back_release_conn( op, mc ); +send_err:; if ( sendok & LDAP_BACK_SENDERR ) { if ( rs->sr_err == LDAP_SUCCESS ) { rs->sr_err = LDAP_BUSY; } send_ldap_result( op, rs ); } + + return 0; } - return( bound > 0 ); + return ( bound > 0 ); } /* diff --git a/servers/slapd/back-meta/candidates.c b/servers/slapd/back-meta/candidates.c index 1986ab3bd6..794d1b3a47 100644 --- a/servers/slapd/back-meta/candidates.c +++ b/servers/slapd/back-meta/candidates.c @@ -206,3 +206,22 @@ meta_clear_one_candidate( return 0; } +/* + * meta_clear_candidates + * + * clears all candidates + */ +int +meta_clear_candidates( Operation *op, metaconn_t *mc ) +{ + metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private; + int c; + + for ( c = 0; c < mi->mi_ntargets; c++ ) { + if ( mc->mc_conns[ c ].msc_ld != NULL ) { + meta_clear_one_candidate( &mc->mc_conns[ c ] ); + } + } + + return 0; +} diff --git a/servers/slapd/back-meta/conn.c b/servers/slapd/back-meta/conn.c index 9f6313eef3..dce20023bb 100644 --- a/servers/slapd/back-meta/conn.c +++ b/servers/slapd/back-meta/conn.c @@ -517,26 +517,12 @@ meta_back_retry( LDAP_BACK_CONN_ISPRIV( mc ), sendok ); if ( rc == LDAP_SUCCESS ) { - if ( be_isroot( op ) && !BER_BVISNULL( &mi->mi_targets[ candidate ].mt_pseudorootdn ) ) - { - Operation op2 = *op; - - op2.o_tag = LDAP_REQ_BIND; - op2.o_req_dn = mi->mi_targets[ candidate ].mt_pseudorootdn; - op2.o_req_ndn = mi->mi_targets[ candidate ].mt_pseudorootdn; - op2.orb_cred = mi->mi_targets[ candidate ].mt_pseudorootpw; - op2.orb_method = LDAP_AUTH_SIMPLE; - - rc = meta_back_single_bind( &op2, rs, mc, candidate, 0 ); - - } else { - rc = meta_back_single_dobind( op, rs, mc, candidate, - sendok, mt->mt_nretries, 0 ); - } + rc = meta_back_single_dobind( op, rs, mcp, candidate, + sendok, mt->mt_nretries, 0 ); } } else { - meta_back_release_conn_lock( op, mc, 0 ); + meta_back_release_conn_lock( op, mc, 1, 0 ); *mcp = NULL; if ( sendok ) { @@ -1246,6 +1232,7 @@ void meta_back_release_conn_lock( Operation *op, metaconn_t *mc, + int dofree, int dolock ) { metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private; @@ -1258,7 +1245,8 @@ meta_back_release_conn_lock( assert( mc->mc_refcnt > 0 ); mc->mc_refcnt--; LDAP_BACK_CONN_BINDING_CLEAR( mc ); - if ( ( mi->mi_conn_ttl != 0 && op->o_time > mc->mc_create_time + mi->mi_conn_ttl ) + if ( dofree + || ( mi->mi_conn_ttl != 0 && op->o_time > mc->mc_create_time + mi->mi_conn_ttl ) || ( mi->mi_idle_timeout != 0 && op->o_time > mc->mc_time + mi->mi_idle_timeout ) ) { Debug( LDAP_DEBUG_TRACE, "%s meta_back_release_conn: mc=%p conn=%ld expired.\n", @@ -1266,6 +1254,7 @@ meta_back_release_conn_lock( (void)avl_delete( &mi->mi_conninfo.lai_tree, ( caddr_t )mc, meta_back_conndnmc_cmp ); if ( mc->mc_refcnt == 0 ) { + meta_clear_candidates( op, mc ); meta_back_conn_free( mc ); } } diff --git a/servers/slapd/back-meta/search.c b/servers/slapd/back-meta/search.c index 00cd89f1f4..1137fe20ab 100644 --- a/servers/slapd/back-meta/search.c +++ b/servers/slapd/back-meta/search.c @@ -604,29 +604,26 @@ really_bad:; /* massage matchedDN if need be */ if ( candidates[ i ].sr_matched != NULL ) { - { - struct berval match, mmatch; - - ber_str2bv( candidates[ i ].sr_matched, - 0, 0, &match ); - candidates[ i ].sr_matched = NULL; - - dc.ctx = "matchedDN"; - dc.target = &mi->mi_targets[ i ]; - if ( !ldap_back_dn_massage( &dc, &match, &mmatch ) ) { - if ( mmatch.bv_val == match.bv_val ) { - candidates[ i ].sr_matched = ch_strdup( mmatch.bv_val ); - - } else { - candidates[ i ].sr_matched = mmatch.bv_val; - } - - candidate_match++; - } - ldap_memfree( match.bv_val ); - } - } + struct berval match, mmatch; + + ber_str2bv( candidates[ i ].sr_matched, + 0, 0, &match ); + candidates[ i ].sr_matched = NULL; + + dc.ctx = "matchedDN"; + dc.target = &mi->mi_targets[ i ]; + if ( !ldap_back_dn_massage( &dc, &match, &mmatch ) ) { + if ( mmatch.bv_val == match.bv_val ) { + candidates[ i ].sr_matched = ch_strdup( mmatch.bv_val ); + + } else { + candidates[ i ].sr_matched = mmatch.bv_val; + } + candidate_match++; + } + ldap_memfree( match.bv_val ); + } /* add references to array */ if ( references ) { @@ -662,13 +659,21 @@ really_bad:; rs->sr_err = candidates[ i ].sr_err; sres = slap_map_api2result( rs ); - snprintf( buf, sizeof( buf ), - "%s meta_back_search[%ld] " - "match=\"%s\" err=%ld\n", - op->o_log_prefix, i, - candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "", - (long) candidates[ i ].sr_err ); - Debug( LDAP_DEBUG_ANY, "%s", buf, 0, 0 ); + if ( LogTest( LDAP_DEBUG_TRACE | LDAP_DEBUG_ANY ) ) { + snprintf( buf, sizeof( buf ), + "%s meta_back_search[%ld] " + "match=\"%s\" err=%ld", + op->o_log_prefix, i, + candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "", + (long) candidates[ i ].sr_err ); + if ( candidates[ i ].sr_err == LDAP_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, "%s.\n", buf, 0, 0 ); + + } else { + Debug( LDAP_DEBUG_ANY, "%s (%s).\n", + buf, ldap_err2string( candidates[ i ].sr_err ), 0 ); + } + } switch ( sres ) { case LDAP_NO_SUCH_OBJECT: @@ -1151,6 +1156,7 @@ next_attr:; rs->sr_entry = &ent; rs->sr_attrs = op->ors_attrs; rs->sr_flags = 0; + rs->sr_err = LDAP_SUCCESS; rc = send_search_entry( op, rs ); switch ( rc ) { case LDAP_UNAVAILABLE: -- 2.39.5