Commit 53015aa4 authored by Ondřej Kuzník's avatar Ondřej Kuzník Committed by Ondřej Kuzník
Browse files

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.
parent e65cd387
......@@ -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;
}
......
......@@ -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,
......
......@@ -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 );
......
......@@ -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:
......
......@@ -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
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment