From 66c30f28a0d22cc4dc9c2d4761d81d873cf1a244 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Sat, 25 Dec 2004 13:24:39 +0000 Subject: [PATCH] ITS#3172 connection retry from HEAD --- servers/slapd/back-ldap/add.c | 20 ++++++++------ servers/slapd/back-ldap/back-ldap.h | 1 + servers/slapd/back-ldap/bind.c | 33 ++++++++++++++++++++++ servers/slapd/back-ldap/compare.c | 19 +++++++------ servers/slapd/back-ldap/config.c | 7 +++++ servers/slapd/back-ldap/delete.c | 20 ++++++++------ servers/slapd/back-ldap/extended.c | 14 +++++++--- servers/slapd/back-ldap/modify.c | 18 ++++++------ servers/slapd/back-ldap/modrdn.c | 20 ++++++++------ servers/slapd/back-ldap/search.c | 43 ++++++++++++++++++++--------- 10 files changed, 135 insertions(+), 60 deletions(-) diff --git a/servers/slapd/back-ldap/add.c b/servers/slapd/back-ldap/add.c index 837f4d3a3a..8af3b4ea85 100644 --- a/servers/slapd/back-ldap/add.c +++ b/servers/slapd/back-ldap/add.c @@ -46,9 +46,10 @@ ldap_back_add( ber_int_t msgid; dncookie dc; int isupdate; + int do_retry = 1; + int rc = LDAP_SUCCESS; #ifdef LDAP_BACK_PROXY_AUTHZ LDAPControl **ctrls = NULL; - int rc = LDAP_SUCCESS; #endif /* LDAP_BACK_PROXY_AUTHZ */ #ifdef NEW_LOGGING @@ -131,10 +132,13 @@ ldap_back_add( #ifdef LDAP_BACK_PROXY_AUTHZ rc = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls ); if ( rc != LDAP_SUCCESS ) { + send_ldap_result( op, rs ); + rc = -1; goto cleanup; } #endif /* LDAP_BACK_PROXY_AUTHZ */ +retry: rs->sr_err = ldap_add_ext(lc->ld, mdn.bv_val, attrs, #ifdef LDAP_BACK_PROXY_AUTHZ ctrls, @@ -142,7 +146,11 @@ ldap_back_add( op->o_ctrls, #endif /* ! LDAP_BACK_PROXY_AUTHZ */ NULL, &msgid); - + rc = ldap_back_op_result( lc, op, rs, msgid, 1 ); + if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) { + do_retry = 0; + if ( ldap_back_retry( lc, op, rs )) goto retry; + } #ifdef LDAP_BACK_PROXY_AUTHZ cleanup: if ( ctrls && ctrls != op->o_ctrls ) { @@ -159,12 +167,6 @@ cleanup: if ( mdn.bv_val != op->o_req_dn.bv_val ) { free( mdn.bv_val ); } -#ifdef LDAP_BACK_PROXY_AUTHZ - if ( rc != LDAP_SUCCESS ) { - send_ldap_result( op, rs ); - return -1; - } -#endif /* LDAP_BACK_PROXY_AUTHZ */ - return ldap_back_op_result( lc, op, rs, msgid, 1 ) != LDAP_SUCCESS; + return rc; } diff --git a/servers/slapd/back-ldap/back-ldap.h b/servers/slapd/back-ldap/back-ldap.h index a4df5890af..2d48898a8f 100644 --- a/servers/slapd/back-ldap/back-ldap.h +++ b/servers/slapd/back-ldap/back-ldap.h @@ -121,6 +121,7 @@ typedef struct 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_retry(struct ldapconn *lc, Operation *op, SlapReply *rs); int ldap_back_map_result(SlapReply *rs); int ldap_back_op_result(struct ldapconn *lc, Operation *op, SlapReply *rs, ber_int_t msgid, int sendok); diff --git a/servers/slapd/back-ldap/bind.c b/servers/slapd/back-ldap/bind.c index dc3ff1574e..7025fffce0 100644 --- a/servers/slapd/back-ldap/bind.c +++ b/servers/slapd/back-ldap/bind.c @@ -592,6 +592,39 @@ ldap_back_op_result(struct ldapconn *lc, Operation *op, SlapReply *rs, return( ERR_OK( rs->sr_err ) ? 0 : -1 ); } +/* return true if bound, false if failed */ +int +ldap_back_retry( struct ldapconn *lc, Operation *op, SlapReply *rs ) +{ + struct ldapinfo *li = (struct ldapinfo *)op->o_bd->be_private; + int vers = op->o_protocol; + LDAP *ld; + + ldap_pvt_thread_mutex_lock( &lc->lc_mutex ); + ldap_unbind( lc->ld ); + lc->bound = 0; + rs->sr_err = ldap_initialize(&ld, li->url); + + if (rs->sr_err != LDAP_SUCCESS) { + rs->sr_err = slap_map_api2result( rs ); + if (rs->sr_text == NULL) { + rs->sr_text = "ldap_initialize() failed"; + } + if (op->o_conn) send_ldap_result( op, rs ); + rs->sr_text = NULL; + return 0; + } + /* Set LDAP version. This will always succeed: If the client + * bound with a particular version, then so can we. + */ + ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, (const void *)&vers); + /* FIXME: configurable? */ + ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON); + lc->ld = ld; + ldap_pvt_thread_mutex_unlock( &lc->lc_mutex ); + return ldap_back_dobind( lc, op, rs ); +} + #ifdef LDAP_BACK_PROXY_AUTHZ /* * ldap_back_proxy_authz_ctrl() prepends a proxyAuthz control diff --git a/servers/slapd/back-ldap/compare.c b/servers/slapd/back-ldap/compare.c index f8d04d71ce..a44c78a66e 100644 --- a/servers/slapd/back-ldap/compare.c +++ b/servers/slapd/back-ldap/compare.c @@ -42,10 +42,11 @@ ldap_back_compare( struct berval mdn = BER_BVNULL; ber_int_t msgid; int freeval = 0; + int do_retry = 1; + int rc = LDAP_SUCCESS; dncookie dc; #ifdef LDAP_BACK_PROXY_AUTHZ LDAPControl **ctrls = NULL; - int rc = LDAP_SUCCESS; #endif /* LDAP_BACK_PROXY_AUTHZ */ lc = ldap_back_getconn(op, rs); @@ -103,10 +104,13 @@ ldap_back_compare( #ifdef LDAP_BACK_PROXY_AUTHZ rc = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls ); if ( rc != LDAP_SUCCESS ) { + send_ldap_result( op, rs ); + rc = -1; goto cleanup; } #endif /* LDAP_BACK_PROXY_AUTHZ */ +retry: rs->sr_err = ldap_compare_ext( lc->ld, mdn.bv_val, mapped_at.bv_val, &mapped_val, #ifdef LDAP_BACK_PROXY_AUTHZ @@ -115,6 +119,11 @@ ldap_back_compare( op->o_ctrls, #endif /* ! LDAP_BACK_PROXY_AUTHZ */ NULL, &msgid ); + rc = ldap_back_op_result( lc, op, rs, msgid, 1 ); + if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) { + do_retry = 0; + if ( ldap_back_retry (lc, op, rs )) goto retry; + } #ifdef LDAP_BACK_PROXY_AUTHZ cleanup: @@ -131,11 +140,5 @@ cleanup: free( mapped_val.bv_val ); } -#ifdef LDAP_BACK_PROXY_AUTHZ - if ( rc != LDAP_SUCCESS ) { - send_ldap_result( op, rs ); - return -1; - } -#endif /* LDAP_BACK_PROXY_AUTHZ */ - return( ldap_back_op_result( lc, op, rs, msgid, 1 ) ); + return rc; } diff --git a/servers/slapd/back-ldap/config.c b/servers/slapd/back-ldap/config.c index ecdb83a956..373b8a72d3 100644 --- a/servers/slapd/back-ldap/config.c +++ b/servers/slapd/back-ldap/config.c @@ -519,6 +519,7 @@ ldap_back_exop_whoami( LDAPMessage *res; Operation op2 = *op; ber_int_t msgid; + int do_retry = 1; ctrls[0] = &c; op2.o_ndn = op->o_conn->c_ndn; @@ -533,11 +534,17 @@ ldap_back_exop_whoami( strcpy(c.ldctl_value.bv_val, "dn:"); strcpy(c.ldctl_value.bv_val+3, op->o_ndn.bv_val); +retry: rs->sr_err = ldap_whoami(lc->ld, ctrls, NULL, &msgid); if (rs->sr_err == LDAP_SUCCESS) { if (ldap_result(lc->ld, msgid, 1, NULL, &res) == -1) { ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER, &rs->sr_err); + if ( rs->sr_err = LDAP_SERVER_DOWN && do_retry ) { + do_retry = 0; + if ( ldap_back_retry( lc, op, rs )) + goto retry; + } ldap_back_freeconn( op, lc ); lc = NULL; diff --git a/servers/slapd/back-ldap/delete.c b/servers/slapd/back-ldap/delete.c index f7837f45f4..2f58a9e238 100644 --- a/servers/slapd/back-ldap/delete.c +++ b/servers/slapd/back-ldap/delete.c @@ -40,9 +40,10 @@ ldap_back_delete( struct ldapconn *lc; ber_int_t msgid; dncookie dc; + int do_retry = 1; + int rc = LDAP_SUCCESS; #ifdef LDAP_BACK_PROXY_AUTHZ LDAPControl **ctrls = NULL; - int rc = LDAP_SUCCESS; #endif /* LDAP_BACK_PROXY_AUTHZ */ struct berval mdn = BER_BVNULL; @@ -73,10 +74,13 @@ ldap_back_delete( #ifdef LDAP_BACK_PROXY_AUTHZ rc = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls ); if ( rc != LDAP_SUCCESS ) { + send_ldap_result( op, rs ); + rc = -1; goto cleanup; } #endif /* LDAP_BACK_PROXY_AUTHZ */ +retry: rs->sr_err = ldap_delete_ext( lc->ld, mdn.bv_val, #ifdef LDAP_BACK_PROXY_AUTHZ ctrls, @@ -84,6 +88,11 @@ ldap_back_delete( op->o_ctrls, #endif /* ! LDAP_BACK_PROXY_AUTHZ */ NULL, &msgid ); + rc = ldap_back_op_result( lc, op, rs, msgid, 1 ); + if ( rs->sr_err == LDAP_SERVER_DOWN && do_retry ) { + do_retry = 0; + if ( ldap_back_retry (lc, op, rs )) goto retry; + } #ifdef LDAP_BACK_PROXY_AUTHZ cleanup: @@ -97,12 +106,5 @@ cleanup: free( mdn.bv_val ); } -#ifdef LDAP_BACK_PROXY_AUTHZ - if ( rc != LDAP_SUCCESS ) { - send_ldap_result( op, rs ); - return -1; - } -#endif /* LDAP_BACK_PROXY_AUTHZ */ - - return( ldap_back_op_result( lc, op, rs, msgid, 1 ) ); + return rc; } diff --git a/servers/slapd/back-ldap/extended.c b/servers/slapd/back-ldap/extended.c index ecd6f4dcaf..6ad8e11a47 100644 --- a/servers/slapd/back-ldap/extended.c +++ b/servers/slapd/back-ldap/extended.c @@ -100,6 +100,7 @@ ldap_back_exop_passwd( LDAPMessage *res; ber_int_t msgid; int rc, isproxy; + int do_retry = 1; dncookie dc; lc = ldap_back_getconn(op, rs); @@ -133,15 +134,12 @@ ldap_back_exop_passwd( } } +retry: rc = ldap_passwd(lc->ld, isproxy ? &mdn : NULL, qpw->rs_old.bv_val ? &qpw->rs_old : NULL, qpw->rs_new.bv_val ? &qpw->rs_new : NULL, op->o_ctrls, NULL, &msgid); - if (mdn.bv_val != op->o_req_dn.bv_val) { - free(mdn.bv_val); - } - if (rc == LDAP_SUCCESS) { if (ldap_result(lc->ld, msgid, 1, NULL, &res) == -1) { ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER, &rc); @@ -171,6 +169,10 @@ ldap_back_exop_passwd( } if (rc != LDAP_SUCCESS) { rs->sr_err = slap_map_api2result( rs ); + if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) { + do_retry = 0; + if ( ldap_back_retry( lc, op, rs )) goto retry; + } send_ldap_result(op, rs); if (rs->sr_matched) free((char *)rs->sr_matched); if (rs->sr_text) free((char *)rs->sr_text); @@ -178,5 +180,9 @@ ldap_back_exop_passwd( rs->sr_text = NULL; rc = -1; } + if (mdn.bv_val != op->o_req_dn.bv_val) { + free(mdn.bv_val); + } + return rc; } diff --git a/servers/slapd/back-ldap/modify.c b/servers/slapd/back-ldap/modify.c index 24b7617d60..4a645eec86 100644 --- a/servers/slapd/back-ldap/modify.c +++ b/servers/slapd/back-ldap/modify.c @@ -47,6 +47,7 @@ ldap_back_modify( ber_int_t msgid; dncookie dc; int isupdate; + int do_retry = 1; #ifdef LDAP_BACK_PROXY_AUTHZ LDAPControl **ctrls = NULL; #endif /* LDAP_BACK_PROXY_AUTHZ */ @@ -162,10 +163,13 @@ ldap_back_modify( #ifdef LDAP_BACK_PROXY_AUTHZ rc = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls ); if ( rc != LDAP_SUCCESS ) { + send_ldap_result( op, rs ); + rc = -1; goto cleanup; } #endif /* LDAP_BACK_PROXY_AUTHZ */ +retry: rs->sr_err = ldap_modify_ext( lc->ld, mdn.bv_val, modv, #ifdef LDAP_BACK_PROXY_AUTHZ ctrls, @@ -173,6 +177,11 @@ ldap_back_modify( op->o_ctrls, #endif /* ! LDAP_BACK_PROXY_AUTHZ */ NULL, &msgid ); + rc = ldap_back_op_result( lc, op, rs, msgid, 1 ); + if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) { + do_retry = 0; + if ( ldap_back_retry (lc, op, rs )) goto retry; + } cleanup:; #ifdef LDAP_BACK_PROXY_AUTHZ @@ -191,13 +200,6 @@ cleanup:; ch_free( mods ); ch_free( modv ); -#ifdef LDAP_BACK_PROXY_AUTHZ - if ( rc != LDAP_SUCCESS ) { - send_ldap_result( op, rs ); - return -1; - } -#endif /* LDAP_BACK_PROXY_AUTHZ */ - - return ldap_back_op_result( lc, op, rs, msgid, 1 ); + return rc; } diff --git a/servers/slapd/back-ldap/modrdn.c b/servers/slapd/back-ldap/modrdn.c index 5a75d9d4b4..45dc6e1927 100644 --- a/servers/slapd/back-ldap/modrdn.c +++ b/servers/slapd/back-ldap/modrdn.c @@ -40,9 +40,10 @@ ldap_back_modrdn( struct ldapconn *lc; ber_int_t msgid; dncookie dc; + int do_retry = 1; + int rc = LDAP_SUCCESS; #ifdef LDAP_BACK_PROXY_AUTHZ LDAPControl **ctrls = NULL; - int rc = LDAP_SUCCESS; #endif /* LDAP_BACK_PROXY_AUTHZ */ struct berval mdn = BER_BVNULL, mnewSuperior = BER_BVNULL; @@ -91,10 +92,13 @@ ldap_back_modrdn( #ifdef LDAP_BACK_PROXY_AUTHZ rc = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls ); if ( rc != LDAP_SUCCESS ) { + send_ldap_result( op, rs ); + rc = -1; goto cleanup; } #endif /* LDAP_BACK_PROXY_AUTHZ */ +retry: rs->sr_err = ldap_rename( lc->ld, mdn.bv_val, op->orr_newrdn.bv_val, mnewSuperior.bv_val, op->orr_deleteoldrdn, @@ -104,6 +108,11 @@ ldap_back_modrdn( op->o_ctrls, #endif /* ! LDAP_BACK_PROXY_AUTHZ */ NULL, &msgid ); + rc = ldap_back_op_result( lc, op, rs, msgid, 1 ); + if ( rs->sr_err == LDAP_SERVER_DOWN && do_retry ) { + do_retry = 0; + if ( ldap_back_retry (lc, op, rs )) goto retry; + } #ifdef LDAP_BACK_PROXY_AUTHZ cleanup: @@ -121,13 +130,6 @@ cleanup: free( mnewSuperior.bv_val ); } -#ifdef LDAP_BACK_PROXY_AUTHZ - if ( rc != LDAP_SUCCESS ) { - send_ldap_result( op, rs ); - return -1; - } -#endif /* LDAP_BACK_PROXY_AUTHZ */ - - return( ldap_back_op_result( lc, op, rs, msgid, 1 ) ); + return rc; } diff --git a/servers/slapd/back-ldap/search.c b/servers/slapd/back-ldap/search.c index 3e1631890b..7b02d6ab05 100644 --- a/servers/slapd/back-ldap/search.c +++ b/servers/slapd/back-ldap/search.c @@ -59,6 +59,7 @@ ldap_back_search( struct berval mfilter = BER_BVNULL; int dontfreetext = 0; int freeconn = 0; + int do_retry = 1; dncookie dc; #ifdef LDAP_BACK_PROXY_AUTHZ LDAPControl **ctrls = NULL; @@ -143,7 +144,8 @@ ldap_back_search( goto finish; } #endif /* LDAP_BACK_PROXY_AUTHZ */ - + +retry: rs->sr_err = ldap_search_ext( lc->ld, mbase.bv_val, op->ors_scope, mfilter.bv_val, mapped_attrs, op->ors_attrsonly, @@ -189,6 +191,8 @@ fail:; Entry ent = {0}; struct berval bdn; int abort = 0; + do_retry = 0; + e = ldap_first_entry( lc->ld, res ); rc = ldap_build_entry( op, e, &ent, &bdn, LDAP_BUILD_ENTRY_PRIVATE ); @@ -229,6 +233,7 @@ fail:; char **references = NULL; int cnt; + do_retry = 0; rc = ldap_parse_reference( lc->ld, res, &references, &rs->sr_ctrls, 1 ); @@ -279,6 +284,11 @@ fail:; } if ( rc == -1 ) { + if ( do_retry ) { + do_retry = 0; + if ( ldap_back_retry( lc, op, rs )) + goto retry; + } /* FIXME: invalidate the connection? */ rs->sr_err = LDAP_SERVER_DOWN; freeconn = 1; @@ -609,6 +619,7 @@ ldap_back_entry_get( Connection *oconn; SlapReply rs; dncookie dc; + int do_retry = 1; /* Tell getconn this is a privileged op */ is_oc = op->o_do_not_cache; @@ -646,17 +657,17 @@ ldap_back_entry_get( rc = 1; goto cleanup; } + is_oc = (strcasecmp("objectclass", mapped.bv_val) == 0); + if (oc && !is_oc) { + gattr[0] = "objectclass"; + gattr[1] = mapped.bv_val; + gattr[2] = NULL; + } else { + gattr[0] = mapped.bv_val; + gattr[1] = NULL; + } } - is_oc = (strcasecmp("objectclass", mapped.bv_val) == 0); - if (oc && !is_oc) { - gattr[0] = "objectclass"; - gattr[1] = mapped.bv_val; - gattr[2] = NULL; - } else { - gattr[0] = mapped.bv_val; - gattr[1] = NULL; - } if (oc) { char *ptr; ldap_back_map(&li->rwmap.rwm_oc, &oc->soc_cname, &mapped, @@ -668,10 +679,16 @@ ldap_back_entry_get( *ptr++ = '\0'; } - if (ldap_search_ext_s(lc->ld, mdn.bv_val, LDAP_SCOPE_BASE, filter, +retry: + rc = ldap_search_ext_s(lc->ld, mdn.bv_val, LDAP_SCOPE_BASE, filter, gattr, 0, NULL, NULL, LDAP_NO_LIMIT, - LDAP_NO_LIMIT, &result) != LDAP_SUCCESS) - { + LDAP_NO_LIMIT, &result); + if ( rc != LDAP_SUCCESS ) { + if ( rc == LDAP_SERVER_DOWN && do_retry ) { + do_retry = 0; + if ( ldap_back_retry( lc, op, &rs )) + goto retry; + } goto cleanup; } -- 2.39.5