mirror of
https://git.openldap.org/openldap/openldap.git
synced 2026-01-26 16:52:55 -05:00
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.
This commit is contained in:
parent
e65cd38787
commit
53015aa4cb
5 changed files with 28 additions and 4 deletions
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue