mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-01-30 13:30:57 +08:00
ITS#2389 - added conn_max_pending/auth config keywords to cap the number
of outstanding requests on a connection. Set rate limits for request execution: no connection can have more than maxthreads/2 ops executing at once. a connection that is write-blocked will not execute any new ops. queued ops must drain before any new ops can execute. If the queue exceeds the max_pending limit, the connection is closed. ...also fixed a bug where a connection was not marked active if it never received a Bind.
This commit is contained in:
parent
ecd4296640
commit
3a71bddbc4
@ -63,6 +63,9 @@ struct berval global_schemandn = { 0, NULL };
|
||||
ber_len_t sockbuf_max_incoming = SLAP_SB_MAX_INCOMING_DEFAULT;
|
||||
ber_len_t sockbuf_max_incoming_auth= SLAP_SB_MAX_INCOMING_AUTH;
|
||||
|
||||
int slap_conn_max_pending = SLAP_CONN_MAX_PENDING_DEFAULT;
|
||||
int slap_conn_max_pending_auth = SLAP_CONN_MAX_PENDING_AUTH;
|
||||
|
||||
char *slapd_pid_file = NULL;
|
||||
char *slapd_args_file = NULL;
|
||||
|
||||
@ -332,6 +335,80 @@ read_config( const char *fname, int depth )
|
||||
|
||||
sockbuf_max_incoming_auth = max;
|
||||
|
||||
/* set conn pending max */
|
||||
} else if ( strcasecmp( cargv[0], "conn_max_pending" ) == 0 ) {
|
||||
long max;
|
||||
if ( cargc < 2 ) {
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG( CONFIG, CRIT,
|
||||
"%s: line %d: missing max in \"conn_max_pending "
|
||||
"<requests>\" line\n", fname, lineno, 0 );
|
||||
#else
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing max in \"conn_max_pending <requests>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
#endif
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
max = atol( cargv[1] );
|
||||
|
||||
if( max < 0 ) {
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG( CONFIG, CRIT,
|
||||
"%s: line %d: invalid max value (%ld) in "
|
||||
"\"conn_max_pending <requests>\" line.\n",
|
||||
fname, lineno, max );
|
||||
#else
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: invalid max value (%ld) in "
|
||||
"\"conn_max_pending <requests>\" line.\n",
|
||||
fname, lineno, max );
|
||||
#endif
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
slap_conn_max_pending = max;
|
||||
|
||||
/* set conn pending max authenticated */
|
||||
} else if ( strcasecmp( cargv[0], "conn_max_pending_auth" ) == 0 ) {
|
||||
long max;
|
||||
if ( cargc < 2 ) {
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG( CONFIG, CRIT,
|
||||
"%s: line %d: missing max in \"conn_max_pending_auth "
|
||||
"<requests>\" line\n", fname, lineno, 0 );
|
||||
#else
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing max in \"conn_max_pending_auth <requests>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
#endif
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
max = atol( cargv[1] );
|
||||
|
||||
if( max < 0 ) {
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG( CONFIG, CRIT,
|
||||
"%s: line %d: invalid max value (%ld) in "
|
||||
"\"conn_max_pending_auth <requests>\" line.\n",
|
||||
fname, lineno, max );
|
||||
#else
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: invalid max value (%ld) in "
|
||||
"\"conn_max_pending_auth <requests>\" line.\n",
|
||||
fname, lineno, max );
|
||||
#endif
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
slap_conn_max_pending_auth = max;
|
||||
|
||||
/* default search base */
|
||||
} else if ( strcasecmp( cargv[0], "defaultSearchBase" ) == 0 ) {
|
||||
if ( cargc < 2 ) {
|
||||
|
@ -1303,6 +1303,7 @@ connection_input(
|
||||
ber_len_t len;
|
||||
ber_int_t msgid;
|
||||
BerElement *ber;
|
||||
int rc;
|
||||
#ifdef LDAP_CONNECTIONLESS
|
||||
Sockaddr peeraddr;
|
||||
char *cdn = NULL;
|
||||
@ -1430,7 +1431,6 @@ connection_input(
|
||||
#endif
|
||||
#ifdef LDAP_CONNECTIONLESS
|
||||
if (conn->c_is_udp) {
|
||||
int rc;
|
||||
|
||||
if ( cdn ) {
|
||||
ber_str2bv( cdn, 0, 1, &op->o_dn );
|
||||
@ -1468,9 +1468,22 @@ connection_input(
|
||||
}
|
||||
#endif /* LDAP_CONNECTIONLESS */
|
||||
|
||||
rc = 0;
|
||||
|
||||
/* Don't process requests when the conn is in the middle of a
|
||||
* Bind, or if it's closing. Also, don't let any single conn
|
||||
* use up all the available threads, and don't execute if we're
|
||||
* currently blocked on output. And don't execute if there are
|
||||
* already pending ops, let them go first.
|
||||
*/
|
||||
if ( conn->c_conn_state == SLAP_C_BINDING
|
||||
|| conn->c_conn_state == SLAP_C_CLOSING )
|
||||
|| conn->c_conn_state == SLAP_C_CLOSING
|
||||
|| conn->c_n_ops_executing >= connection_pool_max/2
|
||||
|| conn->c_n_ops_pending
|
||||
|| conn->c_writewaiter)
|
||||
{
|
||||
int max = conn->c_dn.bv_len ? slap_conn_max_pending_auth
|
||||
: slap_conn_max_pending;
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG( CONNECTION, INFO,
|
||||
"connection_input: conn %lu deferring operation\n",
|
||||
@ -1480,18 +1493,13 @@ connection_input(
|
||||
#endif
|
||||
conn->c_n_ops_pending++;
|
||||
LDAP_STAILQ_INSERT_TAIL( &conn->c_pending_ops, op, o_next );
|
||||
|
||||
if ( conn->c_n_ops_pending > max ) {
|
||||
rc = -1;
|
||||
} else {
|
||||
rc = 1;
|
||||
}
|
||||
} else {
|
||||
conn->c_n_ops_executing++;
|
||||
/* Don't allow any single conn to soak up all of the
|
||||
* available threads
|
||||
*/
|
||||
if (conn->c_n_ops_executing > connection_pool_max/2) {
|
||||
ber_socket_t sd;
|
||||
|
||||
ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_GET_FD, &sd );
|
||||
slapd_clr_read( sd, 0 );
|
||||
}
|
||||
connection_op_activate( op );
|
||||
}
|
||||
|
||||
@ -1503,7 +1511,7 @@ connection_input(
|
||||
#endif
|
||||
assert( conn->c_struct_state == SLAP_C_USED );
|
||||
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1566,12 +1574,15 @@ connection_resched( Connection *conn )
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( conn->c_conn_state != SLAP_C_ACTIVE ) {
|
||||
if( conn->c_conn_state != SLAP_C_ACTIVE || conn->c_writewaiter ) {
|
||||
/* other states need different handling */
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((op = LDAP_STAILQ_FIRST( &conn->c_pending_ops )) != NULL) {
|
||||
if ( conn->c_n_ops_executing > connection_pool_max/2 ) {
|
||||
break;
|
||||
}
|
||||
LDAP_STAILQ_REMOVE_HEAD( &conn->c_pending_ops, o_next );
|
||||
LDAP_STAILQ_NEXT(op, o_next) = NULL;
|
||||
/* pending operations should not be marked for abandonment */
|
||||
@ -1610,6 +1621,11 @@ static int connection_op_activate( Operation *op )
|
||||
op->o_protocol = op->o_conn->c_protocol
|
||||
? op->o_conn->c_protocol : LDAP_VERSION3;
|
||||
}
|
||||
if (op->o_conn->c_conn_state == SLAP_C_INACTIVE
|
||||
&& op->o_protocol > LDAP_VERSION2) {
|
||||
op->o_conn->c_conn_state = SLAP_C_ACTIVE;
|
||||
}
|
||||
|
||||
op->o_connid = op->o_conn->c_connid;
|
||||
|
||||
LDAP_STAILQ_INSERT_TAIL( &op->o_conn->c_ops, op, o_next );
|
||||
|
@ -1147,6 +1147,8 @@ LDAP_SLAPD_V(unsigned) num_subordinates;
|
||||
|
||||
LDAP_SLAPD_V (ber_len_t) sockbuf_max_incoming;
|
||||
LDAP_SLAPD_V (ber_len_t) sockbuf_max_incoming_auth;
|
||||
LDAP_SLAPD_V (int) slap_conn_max_pending;
|
||||
LDAP_SLAPD_V (int) slap_conn_max_pending_auth;
|
||||
|
||||
LDAP_SLAPD_V (slap_mask_t) global_restrictops;
|
||||
LDAP_SLAPD_V (slap_mask_t) global_allows;
|
||||
|
@ -81,6 +81,9 @@ LDAP_BEGIN_DECL
|
||||
#define SLAP_SB_MAX_INCOMING_DEFAULT ((1<<18) - 1)
|
||||
#define SLAP_SB_MAX_INCOMING_AUTH ((1<<24) - 1)
|
||||
|
||||
#define SLAP_CONN_MAX_PENDING_DEFAULT 100
|
||||
#define SLAP_CONN_MAX_PENDING_AUTH 1000
|
||||
|
||||
#define SLAP_TEXT_BUFLEN (256)
|
||||
|
||||
/* psuedo error code indicating abandoned operation */
|
||||
|
Loading…
Reference in New Issue
Block a user