clear shared connections when ldap_result fails with -1 (typically, remote server is down); fixes ITS#3217

This commit is contained in:
Pierangelo Masarati 2004-07-04 23:35:18 +00:00
parent c3984d9f59
commit 277d921945
5 changed files with 65 additions and 27 deletions

View file

@ -164,6 +164,7 @@ typedef struct dncookie {
#endif
} dncookie;
int ldap_back_freeconn( Operation *op, struct ldapconn *lc );
struct ldapconn *ldap_back_getconn(struct slap_op *op, struct slap_rep *rs);
int ldap_back_dobind(struct ldapconn *lc, Operation *op, SlapReply *rs);
int ldap_back_map_result(SlapReply *rs);

View file

@ -209,6 +209,20 @@ static void myprint( Avlnode *root )
}
#endif /* PRINT_CONNTREE */
int
ldap_back_freeconn( Operation *op, struct ldapconn *lc )
{
struct ldapinfo *li = (struct ldapinfo *) op->o_bd->be_private;
ldap_pvt_thread_mutex_lock( &li->conn_mutex );
lc = avl_delete( &li->conntree, (caddr_t)lc,
ldap_back_conn_cmp );
ldap_back_conn_free( (void *)lc );
ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
return 0;
}
struct ldapconn *
ldap_back_getconn(Operation *op, SlapReply *rs)
{
@ -645,16 +659,16 @@ ldap_back_op_result(struct ldapconn *lc, Operation *op, SlapReply *rs,
if ( ERR_OK( rs->sr_err ) ) {
/* if result parsing fails, note the failure reason */
if ( ldap_result( lc->ld, msgid, 1, NULL, &res ) == -1 ) {
ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER,
&rs->sr_err);
ldap_get_option( lc->ld, LDAP_OPT_ERROR_NUMBER,
&rs->sr_err );
/* otherwise get the result; if it is not
* LDAP_SUCCESS, record it in the reply
* structure (this includes
* LDAP_COMPARE_{TRUE|FALSE}) */
} else {
int rc = ldap_parse_result(lc->ld, res, &rs->sr_err,
&match, &text, NULL, NULL, 1);
int rc = ldap_parse_result( lc->ld, res, &rs->sr_err,
&match, &text, NULL, NULL, 1 );
rs->sr_text = text;
if ( rc != LDAP_SUCCESS ) rs->sr_err = rc;
}

View file

@ -501,6 +501,9 @@ ldap_back_exop_whoami(
if (ldap_result(lc->ld, msgid, 1, NULL, &res) == -1) {
ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER,
&rs->sr_err);
ldap_back_freeconn( op, lc );
lc = NULL;
} else {
rs->sr_err = ldap_parse_whoami(lc->ld, res, &bv);
ldap_msgfree(res);

View file

@ -145,6 +145,9 @@ ldap_back_exop_passwd(
if (rc == LDAP_SUCCESS) {
if (ldap_result(lc->ld, msgid, 1, NULL, &res) == -1) {
ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER, &rc);
ldap_back_freeconn( op, lc );
lc = NULL;
} else {
/* sigh. parse twice, because parse_passwd doesn't give
* us the err / match / msg info.

View file

@ -58,6 +58,7 @@ ldap_back_search(
struct berval mbase;
struct berval mfilter = BER_BVNULL;
int dontfreetext = 0;
int freeconn = 0;
dncookie dc;
LDAPControl **ctrls = NULL;
@ -75,11 +76,14 @@ ldap_back_search(
}
/* should we check return values? */
if (op->ors_deref != -1)
ldap_set_option( lc->ld, LDAP_OPT_DEREF, (void *)&op->ors_deref);
if (op->ors_tlimit != SLAP_NO_LIMIT) {
if ( op->ors_deref != -1 ) {
ldap_set_option( lc->ld, LDAP_OPT_DEREF, (void *)&op->ors_deref );
}
if ( op->ors_tlimit != SLAP_NO_LIMIT ) {
tv.tv_sec = op->ors_tlimit;
tv.tv_usec = 0;
} else {
tv.tv_sec = 0;
}
@ -125,7 +129,7 @@ ldap_back_search(
rs->sr_err = ldap_back_map_attrs( &li->rwmap.rwm_at,
op->ors_attrs,
BACKLDAP_MAP, &mapped_attrs );
if ( rs->sr_err ) {
if ( rs->sr_err != LDAP_SUCCESS ) {
rc = -1;
goto finish;
}
@ -139,7 +143,7 @@ ldap_back_search(
}
#endif /* LDAP_BACK_PROXY_AUTHZ */
rs->sr_err = ldap_search_ext(lc->ld, mbase.bv_val,
rs->sr_err = ldap_search_ext( lc->ld, mbase.bv_val,
op->ors_scope, mfilter.bv_val,
mapped_attrs, op->ors_attrsonly,
ctrls, NULL,
@ -148,7 +152,11 @@ ldap_back_search(
if ( rs->sr_err != LDAP_SUCCESS ) {
fail:;
rc = ldap_back_op_result(lc, op, rs, msgid, 0);
rc = ldap_back_op_result( lc, op, rs, msgid, 0 );
if ( freeconn ) {
ldap_back_freeconn( op, lc );
lc = NULL;
}
goto finish;
}
@ -157,27 +165,28 @@ fail:;
* but this is necessary for version matching, and for ACL processing.
*/
for ( rc=0; rc != -1; rc = ldap_result(lc->ld, msgid, 0, &tv, &res))
for ( rc = 0; rc != -1; rc = ldap_result( lc->ld, msgid, 0, &tv, &res ) )
{
/* check for abandon */
if (op->o_abandon) {
ldap_abandon(lc->ld, msgid);
if ( op->o_abandon ) {
ldap_abandon( lc->ld, msgid );
rc = 0;
goto finish;
}
if (rc == 0) {
if ( rc == 0 ) {
tv.tv_sec = 0;
tv.tv_usec = 100000;
ldap_pvt_thread_yield();
} else if (rc == LDAP_RES_SEARCH_ENTRY) {
} else if ( rc == LDAP_RES_SEARCH_ENTRY ) {
Entry ent = {0};
struct berval bdn;
int abort = 0;
e = ldap_first_entry(lc->ld,res);
if ( ( rc = ldap_build_entry(op, e, &ent, &bdn,
LDAP_BUILD_ENTRY_PRIVATE)) == LDAP_SUCCESS ) {
e = ldap_first_entry( lc->ld, res );
rc = ldap_build_entry( op, e, &ent, &bdn,
LDAP_BUILD_ENTRY_PRIVATE );
if ( rc == LDAP_SUCCESS ) {
rs->sr_entry = &ent;
rs->sr_attrs = op->ors_attrs;
rs->sr_flags = 0;
@ -190,10 +199,12 @@ fail:;
ent.e_attrs = a->a_next;
v = a->a_vals;
if (a->a_vals != &dummy)
if ( a->a_vals != &dummy ) {
ber_bvarray_free(a->a_vals);
if (a->a_nvals != v)
}
if ( a->a_nvals != v ) {
ber_bvarray_free(a->a_nvals);
}
ch_free(a);
}
@ -202,9 +213,9 @@ fail:;
if ( ent.e_ndn )
free( ent.e_ndn );
}
ldap_msgfree(res);
ldap_msgfree( res );
if ( abort ) {
ldap_abandon(lc->ld, msgid);
ldap_abandon( lc->ld, msgid );
goto finish;
}
@ -249,18 +260,24 @@ fail:;
}
} else {
rc = ldap_parse_result(lc->ld, res, &rs->sr_err,
rc = ldap_parse_result( lc->ld, res, &rs->sr_err,
&match.bv_val, (char **)&rs->sr_text,
NULL, NULL, 1);
if (rc != LDAP_SUCCESS ) rs->sr_err = rc;
NULL, NULL, 1 );
if (rc != LDAP_SUCCESS ) {
rs->sr_err = rc;
}
rs->sr_err = slap_map_api2result( rs );
rc = 0;
break;
}
}
if (rc == -1)
if ( rc == -1 ) {
/* FIXME: invalidate the connection? */
rs->sr_err = LDAP_SERVER_DOWN;
freeconn = 1;
goto fail;
}
/*
* Rewrite the matched portion of the search base, if required
@ -275,7 +292,7 @@ fail:;
dc.normalized = 0;
#endif
match.bv_len = strlen( match.bv_val );
ldap_back_dn_massage(&dc, &match, &mdn);
ldap_back_dn_massage( &dc, &match, &mdn );
rs->sr_matched = mdn.bv_val;
}
if ( rs->sr_v2ref ) {