@@ -, +, @@ --- .../univention-directory-listener/debian/changelog | 6 ++++++ ...rectory-listener.univention-config-registry-variables | 6 ++++++ .../univention-directory-listener/src/change.c | 12 ++++++------ .../management/univention-directory-listener/src/utils.c | 9 +++++++++ .../management/univention-directory-listener/src/utils.h | 16 ++++++++++++++++ 5 files changed, 43 insertions(+), 6 deletions(-) --- a/branches/ucs-4.1/ucs-4.1-0/management/univention-directory-listener/debian/changelog +++ a/branches/ucs-4.1/ucs-4.1-0/management/univention-directory-listener/debian/changelog @@ -1,3 +1,9 @@ +univention-directory-listener (10.0.0-6) unstable; urgency=low + + * Bug #40460: Retry LDAP queries on LDAP_SERVER_DOWN + + -- Philipp Hahn Fri, 05 Feb 2016 10:09:45 +0100 + univention-directory-listener (10.0.0-5) unstable; urgency=low * Bug #40373: Improve UCR variable description --- a/branches/ucs-4.1/ucs-4.1-0/management/univention-directory-listener/debian/univention-directory-listener.univention-config-registry-variables +++ a/branches/ucs-4.1/ucs-4.1-0/management/univention-directory-listener/debian/univention-directory-listener.univention-config-registry-variables @@ -39,3 +39,9 @@ Description[de]=Timeout in Sekunden für lange synchrone LDAP Suchanfragen. Stan Description[en]=Timeout in seconds for long running synchronous LDAP search queries. Default: 2h Type=int Categories=service-ln + +[listener/ldap/retries] +Description[de]=Anzahl der Versuche zum Verbindungsaufbau zum LDAP-Server im Fall von Fehlern. Standard: 5 +Description[en]=Number of retried to re-connect the LDAP server in case of errors. Default: 5 +Type=int +Categories=service-ln --- a/branches/ucs-4.1/ucs-4.1-0/management/univention-directory-listener/src/change.c +++ a/branches/ucs-4.1/ucs-4.1-0/management/univention-directory-listener/src/change.c @@ -143,7 +143,7 @@ static int change_init_module(univention_ldap_parameters_t *lp, Handler *handler .tv_usec = 0, }; int sizelimit0 = 0; - if ((rv = ldap_search_ext_s(lp->ld, (*f)->base, (*f)->scope, (*f)->filter, _attrs, attrsonly1, serverctrls, clientctrls, &timeout, sizelimit0, &res)) != LDAP_SUCCESS) { + if ((rv = LDAP_RETRY(lp, ldap_search_ext_s(lp->ld, (*f)->base, (*f)->scope, (*f)->filter, _attrs, attrsonly1, serverctrls, clientctrls, &timeout, sizelimit0, &res)) != LDAP_SUCCESS)) { univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "could not get DNs when initializing %s: %s", handler->name, ldap_err2string(rv)); return rv; } @@ -185,7 +185,7 @@ static int change_init_module(univention_ldap_parameters_t *lp, Handler *handler if ((rv = cache_get_entry_lower_upper(dns[i].dn, &cache_entry)) == DB_NOTFOUND) { /* XXX */ LDAPMessage *res2, *first; int attrsonly0 = 0; - if ((rv = ldap_search_ext_s(lp->ld, dns[i].dn, LDAP_SCOPE_BASE, "(objectClass=*)", attrs, attrsonly0, serverctrls, clientctrls, &timeout, sizelimit0, &res2)) == LDAP_SUCCESS) { + if ((rv = LDAP_RETRY(lp, ldap_search_ext_s(lp->ld, dns[i].dn, LDAP_SCOPE_BASE, "(objectClass=*)", attrs, attrsonly0, serverctrls, clientctrls, &timeout, sizelimit0, &res2)) == LDAP_SUCCESS)) { first = ldap_first_entry(lp->ld, res2); cache_new_entry_from_ldap(NULL, &cache_entry, lp->ld, first); ldap_msgfree(res2); @@ -381,7 +381,7 @@ int change_update_schema(univention_ldap_parameters_t *lp) if (new_id > id) #endif { - if ((rv=ldap_search_ext_s(lp->ld, "cn=Subschema", LDAP_SCOPE_BASE, "(objectClass=*)", attrs, attrsonly0, serverctrls, clientctrls, &timeout, sizelimit0, &res)) == LDAP_SUCCESS) { + if ((rv = LDAP_RETRY(lp, ldap_search_ext_s(lp->ld, "cn=Subschema", LDAP_SCOPE_BASE, "(objectClass=*)", attrs, attrsonly0, serverctrls, clientctrls, &timeout, sizelimit0, &res)) == LDAP_SUCCESS)) { if ((cur=ldap_first_entry(lp->ld, res)) == NULL) { univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "got no entry for schema"); return LDAP_OTHER; @@ -524,13 +524,13 @@ int check_parent_dn(struct transaction *trans, char *dn) } /* search for parent_dn in local LDAP */ - rv = ldap_search_ext_s(trans->lp_local->ld, parent_dn, LDAP_SCOPE_BASE, filter, attrs_local, attrsonly0, serverctrls, clientctrls, &timeout, sizelimit0, &res); + rv = LDAP_RETRY(trans->lp_local, ldap_search_ext_s(trans->lp_local->ld, parent_dn, LDAP_SCOPE_BASE, filter, attrs_local, attrsonly0, serverctrls, clientctrls, &timeout, sizelimit0, &res)); ldap_msgfree(res); if (rv == LDAP_NO_SUCH_OBJECT) { /* parent_dn not present in local LDAP */ rv = check_parent_dn(trans, parent_dn); /* check if parent of parent_dn is here */ if (rv == LDAP_SUCCESS) { /* parent of parent_dn found in local LDAP */ /* lookup parent_dn object in remote LDAP */ - rv = ldap_search_ext_s(trans->lp->ld, parent_dn, LDAP_SCOPE_BASE, filter, attrs, attrsonly0, serverctrls, clientctrls, &timeout, sizelimit0, &res); + rv = LDAP_RETRY(trans->lp, ldap_search_ext_s(trans->lp->ld, parent_dn, LDAP_SCOPE_BASE, filter, attrs, attrsonly0, serverctrls, clientctrls, &timeout, sizelimit0, &res)); if (rv == LDAP_NO_SUCH_OBJECT) { univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "could not find parent container of dn: %s from %s (%s)", dn, trans->lp->host, ldap_err2string(rv)); if (is_move(trans)) @@ -780,7 +780,7 @@ retry_dn: } bool delete = false; - rv = ldap_search_ext_s(trans->lp->ld, base, scope, filter, attrs, attrsonly0, serverctrls, clientctrls, &timeout, sizelimit0, &res); + rv = LDAP_RETRY(trans->lp, ldap_search_ext_s(trans->lp->ld, base, scope, filter, attrs, attrsonly0, serverctrls, clientctrls, &timeout, sizelimit0, &res)); if (rv == LDAP_NO_SUCH_OBJECT) { delete = true; } else if (rv == LDAP_SUCCESS) { --- a/branches/ucs-4.1/ucs-4.1-0/management/univention-directory-listener/src/utils.c +++ a/branches/ucs-4.1/ucs-4.1-0/management/univention-directory-listener/src/utils.c @@ -134,3 +134,12 @@ bool same_dn(const char *left, const char *right) { return 0 == result; } + + +int ldap_retries = -1; + +int get_ldap_retries() { + const int DEFAULT_RETRIES = 5; + int retries = univention_config_get_int("listener/ldap/retries"); + return retries < 0 ? DEFAULT_RETRIES : retries; +} --- a/branches/ucs-4.1/ucs-4.1-0/management/univention-directory-listener/src/utils.h +++ a/branches/ucs-4.1/ucs-4.1-0/management/univention-directory-listener/src/utils.h @@ -32,6 +32,22 @@ static inline int ldap_timeout_scans() { return timeout < 0 ? DEFAULT_TIMEOUT : timeout; } +extern int ldap_retries; +extern int get_ldap_retries(); +#define LDAP_RETRY(lp, cmd) \ + ({ \ + int _rv, _retry = 0; \ + if (ldap_retries < 0) \ + ldap_retries = get_ldap_retries(); \ + do { \ + _rv = (cmd); \ + if (rv != LDAP_SERVER_DOWN) \ + break; \ + while (_retry < ldap_retries && univention_ldap_open(lp) != LDAP_SUCCESS) \ + sleep(1 << _retry++); \ + } while (_retry < ldap_retries); \ + _rv; \ + }) extern char *lower_utf8(const char *str); extern bool same_dn(const char *left, const char *right); --