]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
Round robin for backends.
authorOndřej Kuzník <ondra@mistotebe.net>
Wed, 10 May 2017 15:07:11 +0000 (16:07 +0100)
committerOndřej Kuzník <okuznik@symas.com>
Tue, 17 Nov 2020 17:55:46 +0000 (17:55 +0000)
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.

servers/lloadd/backend.c
servers/lloadd/config.c
servers/lloadd/daemon.c
servers/lloadd/init.c
servers/lloadd/slap.h

index 7e2fc76f721bf4f5a287aa11d4bdf3f28135be8a..f9226accea3215faca3d88a71c9a30a7cf317459 100644 (file)
@@ -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;
 }
index e81cadae34640c2a4c91105b2efc4b4accfca76f..fc5ee4dc94d8ad33899bf428abd5efdf8cdd52e2 100644 (file)
@@ -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,
index dd20c9db0fcc64a6b9ae5523125dd16241725e77..88f3afd3b22d44dbacc4e3ad16bd7962301d21cd 100644 (file)
@@ -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 );
index 07bd849d30633222d2095daef5c2f719f0fb5b57..e33a08f6a54ac88c2062f6eaac23d1e847db4b5c 100644 (file)
@@ -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:
index e60aaa5e0dcf675590ad1d6a348a2cb82420497d..32627fa79ad8018e5299966fe40d366849ddefb7 100644 (file)
@@ -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