From 7940183478852e72c077acaffe39c1e74e5e95bf Mon Sep 17 00:00:00 2001 Message-Id: <7940183478852e72c077acaffe39c1e74e5e95bf.1454663951.git.hahn@univention.de> From: Philipp Hahn Date: Fri, 5 Feb 2016 10:14:48 +0100 Subject: [PATCH] Bug #40460 UDL: Retry LDAP queries on LDAP_SERVER_DOWN Organization: Univention GmbH, Bremen, Germany Initialization might take some time. If the connection to the remote (or local) LDAP servers is lost during that time, the initialization of the module is aborted. Add macro LDAP_RETRY to re-try failed commands if LDAP_SERVER_DOWN is returned. Wrap all LDAP search commands with said macro. Add UCR 'listener/ldap/retries' to make number of retires configurable. --- .../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(-) diff --git a/branches/ucs-4.1/ucs-4.1-0/management/univention-directory-listener/debian/changelog b/branches/ucs-4.1/ucs-4.1-0/management/univention-directory-listener/debian/changelog index 09853cc..1d1efb3 100644 --- a/branches/ucs-4.1/ucs-4.1-0/management/univention-directory-listener/debian/changelog +++ b/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 diff --git a/branches/ucs-4.1/ucs-4.1-0/management/univention-directory-listener/debian/univention-directory-listener.univention-config-registry-variables b/branches/ucs-4.1/ucs-4.1-0/management/univention-directory-listener/debian/univention-directory-listener.univention-config-registry-variables index 32b5222..b30b97c 100644 --- a/branches/ucs-4.1/ucs-4.1-0/management/univention-directory-listener/debian/univention-directory-listener.univention-config-registry-variables +++ b/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 diff --git a/branches/ucs-4.1/ucs-4.1-0/management/univention-directory-listener/src/change.c b/branches/ucs-4.1/ucs-4.1-0/management/univention-directory-listener/src/change.c index a086bde..cae1a58 100644 --- a/branches/ucs-4.1/ucs-4.1-0/management/univention-directory-listener/src/change.c +++ b/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) { diff --git a/branches/ucs-4.1/ucs-4.1-0/management/univention-directory-listener/src/utils.c b/branches/ucs-4.1/ucs-4.1-0/management/univention-directory-listener/src/utils.c index 3670356..3750d70 100644 --- a/branches/ucs-4.1/ucs-4.1-0/management/univention-directory-listener/src/utils.c +++ b/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; +} diff --git a/branches/ucs-4.1/ucs-4.1-0/management/univention-directory-listener/src/utils.h b/branches/ucs-4.1/ucs-4.1-0/management/univention-directory-listener/src/utils.h index f2f8b33..15c85d2 100644 --- a/branches/ucs-4.1/ucs-4.1-0/management/univention-directory-listener/src/utils.h +++ b/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); -- 2.1.4