From: Ondřej Kuzník Date: Wed, 10 May 2017 15:07:11 +0000 (+0100) Subject: Round robin for backends. X-Git-Tag: OPENLDAP_REL_ENG_2_5_1ALPHA~18^2~173 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=53015aa4cb0e0ec038ca52ab32d873363539df60;p=thirdparty%2Fopenldap.git Round robin for backends. Several threads calling backend_select might reset current_backend to a different place, there are two options to deal with that: - just let the last rotation win (the current approach) - detect whether first == current_backend and only replace then Not sure which one is more useful, going with the simpler. --- diff --git a/servers/lloadd/backend.c b/servers/lloadd/backend.c index 7e2fc76f72..f9226accea 100644 --- a/servers/lloadd/backend.c +++ b/servers/lloadd/backend.c @@ -93,21 +93,31 @@ fail: Connection * backend_select( Operation *op ) { - Backend *b; + Backend *b, *first, *next; + + ldap_pvt_thread_mutex_lock( &backend_mutex ); + first = b = current_backend; + ldap_pvt_thread_mutex_unlock( &backend_mutex ); + + if ( !first ) { + return NULL; + } /* TODO: Two runs, one with trylock, then one actually locked if we don't * find anything? */ - LDAP_CIRCLEQ_FOREACH ( b, &backend, b_next ) { + do { struct ConnSt *head; Connection *c; ldap_pvt_thread_mutex_lock( &b->b_mutex ); + next = LDAP_CIRCLEQ_LOOP_NEXT( &backend, b, b_next ); if ( b->b_max_pending && b->b_n_ops_executing >= b->b_max_pending ) { Debug( LDAP_DEBUG_CONNS, "backend_select: " "backend %s too busy\n", b->b_bindconf.sb_uri.bv_val ); ldap_pvt_thread_mutex_unlock( &b->b_mutex ); + b = next; continue; } @@ -130,10 +140,15 @@ backend_select( Operation *op ) /* * Round-robin step: - * Rotate the queue to put this connection at the end. + * Rotate the queue to put this connection at the end, same for + * the backend. */ LDAP_CIRCLEQ_MAKE_TAIL( head, c, c_next ); + ldap_pvt_thread_mutex_lock( &backend_mutex ); + current_backend = next; + ldap_pvt_thread_mutex_unlock( &backend_mutex ); + b->b_n_ops_executing++; c->c_n_ops_executing++; CONNECTION_UNLOCK_INCREF(c); @@ -145,7 +160,9 @@ backend_select( Operation *op ) ldap_pvt_thread_mutex_unlock( &c->c_io_mutex ); } ldap_pvt_thread_mutex_unlock( &b->b_mutex ); - } + + b = next; + } while ( b != first ); return NULL; } diff --git a/servers/lloadd/config.c b/servers/lloadd/config.c index e81cadae34..fc5ee4dc94 100644 --- a/servers/lloadd/config.c +++ b/servers/lloadd/config.c @@ -113,6 +113,8 @@ static ConfigDriver config_tls_config; #endif slap_b_head backend = LDAP_CIRCLEQ_HEAD_INITIALIZER(backend); +ldap_pvt_thread_mutex_t backend_mutex; +Backend *current_backend = NULL; enum { CFG_ACL = 1, diff --git a/servers/lloadd/daemon.c b/servers/lloadd/daemon.c index dd20c9db0f..88f3afd3b2 100644 --- a/servers/lloadd/daemon.c +++ b/servers/lloadd/daemon.c @@ -1313,6 +1313,7 @@ slapd_daemon( struct event_base *daemon_base ) } } + current_backend = LDAP_CIRCLEQ_FIRST( &backend ); LDAP_CIRCLEQ_FOREACH ( b, &backend, b_next ) { struct event *retry_event = evtimer_new( daemon_base, backend_connect, b ); diff --git a/servers/lloadd/init.c b/servers/lloadd/init.c index 07bd849d30..e33a08f6a5 100644 --- a/servers/lloadd/init.c +++ b/servers/lloadd/init.c @@ -98,6 +98,8 @@ slap_init( int mode, const char *name ) LDAP_STAILQ_INIT( &slapd_rq.task_list ); LDAP_STAILQ_INIT( &slapd_rq.run_list ); + ldap_pvt_thread_mutex_init( &backend_mutex ); + break; default: diff --git a/servers/lloadd/slap.h b/servers/lloadd/slap.h index e60aaa5e0d..32627fa79a 100644 --- a/servers/lloadd/slap.h +++ b/servers/lloadd/slap.h @@ -124,6 +124,8 @@ extern int slap_inet4or6; typedef LDAP_CIRCLEQ_HEAD(BeSt, Backend) slap_b_head; LDAP_SLAPD_V (slap_b_head) backend; +LDAP_SLAPD_V (ldap_pvt_thread_mutex_t) backend_mutex; +LDAP_SLAPD_V (Backend *) current_backend; LDAP_SLAPD_V (int) slapMode; #define SLAP_UNDEFINED_MODE 0x0000