Commit 0d6e1c6e authored by Howard Chu's avatar Howard Chu
Browse files

Fix ITS#2389, sync with HEAD

parent e7d462be
......@@ -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_pending_max" ) == 0 ) {
long max;
if ( cargc < 2 ) {
#ifdef NEW_LOGGING
LDAP_LOG( CONFIG, CRIT,
"%s: line %d: missing max in \"conn_pending_max "
"<requests>\" line\n", fname, lineno, 0 );
#else
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing max in \"conn_pending_max <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_pending_max <requests>\" line.\n",
fname, lineno, max );
#else
Debug( LDAP_DEBUG_ANY,
"%s: line %d: invalid max value (%ld) in "
"\"conn_pending_max <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_pending_max_auth" ) == 0 ) {
long max;
if ( cargc < 2 ) {
#ifdef NEW_LOGGING
LDAP_LOG( CONFIG, CRIT,
"%s: line %d: missing max in \"conn_pending_max_auth "
"<requests>\" line\n", fname, lineno, 0 );
#else
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing max in \"conn_pending_max_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_pending_max_auth <requests>\" line.\n",
fname, lineno, max );
#else
Debug( LDAP_DEBUG_ANY,
"%s: line %d: invalid max value (%ld) in "
"\"conn_pending_max_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 ) {
......
......@@ -55,18 +55,13 @@ static Connection* connection_get( ber_socket_t s );
static int connection_input( Connection *c );
static void connection_close( Connection *c );
static int connection_op_activate( Connection *conn, Operation *op );
static int connection_op_activate( Operation *op );
static int connection_resched( Connection *conn );
static void connection_abandon( Connection *conn );
static void connection_destroy( Connection *c );
static ldap_pvt_thread_start_t connection_operation;
struct co_arg {
Connection *co_conn;
Operation *co_op;
};
/*
* Initialize connection management infrastructure.
*/
......@@ -887,18 +882,18 @@ static void *
connection_operation( void *ctx, void *arg_v )
{
int rc;
struct co_arg *arg = arg_v;
ber_tag_t tag = arg->co_op->o_tag;
Operation *op = arg_v;
ber_tag_t tag = op->o_tag;
#ifdef SLAPD_MONITOR
ber_tag_t oldtag = tag;
#endif /* SLAPD_MONITOR */
Connection *conn = arg->co_conn;
Connection *conn = op->o_conn;
ldap_pvt_thread_mutex_lock( &num_ops_mutex );
num_ops_initiated++;
ldap_pvt_thread_mutex_unlock( &num_ops_mutex );
arg->co_op->o_threadctx = ctx;
op->o_threadctx = ctx;
if( conn->c_sasl_bind_in_progress && tag != LDAP_REQ_BIND ) {
#ifdef NEW_LOGGING
......@@ -910,7 +905,7 @@ connection_operation( void *ctx, void *arg_v )
"error: SASL bind in progress (tag=%ld).\n",
(long) tag, 0, 0 );
#endif
send_ldap_result( conn, arg->co_op,
send_ldap_result( conn, op,
rc = LDAP_OPERATIONS_ERROR,
NULL, "SASL bind in progress", NULL, NULL );
goto operations_error;
......@@ -919,52 +914,52 @@ connection_operation( void *ctx, void *arg_v )
switch ( tag ) {
case LDAP_REQ_BIND:
INCR_OP(num_ops_initiated_, SLAP_OP_BIND);
rc = do_bind( conn, arg->co_op );
rc = do_bind( conn, op );
break;
case LDAP_REQ_UNBIND:
INCR_OP(num_ops_initiated_, SLAP_OP_UNBIND);
rc = do_unbind( conn, arg->co_op );
rc = do_unbind( conn, op );
break;
case LDAP_REQ_ADD:
INCR_OP(num_ops_initiated_, SLAP_OP_ADD);
rc = do_add( conn, arg->co_op );
rc = do_add( conn, op );
break;
case LDAP_REQ_DELETE:
INCR_OP(num_ops_initiated_, SLAP_OP_DELETE);
rc = do_delete( conn, arg->co_op );
rc = do_delete( conn, op );
break;
case LDAP_REQ_MODRDN:
INCR_OP(num_ops_initiated_, SLAP_OP_MODRDN);
rc = do_modrdn( conn, arg->co_op );
rc = do_modrdn( conn, op );
break;
case LDAP_REQ_MODIFY:
INCR_OP(num_ops_initiated_, SLAP_OP_MODIFY);
rc = do_modify( conn, arg->co_op );
rc = do_modify( conn, op );
break;
case LDAP_REQ_COMPARE:
INCR_OP(num_ops_initiated_, SLAP_OP_COMPARE);
rc = do_compare( conn, arg->co_op );
rc = do_compare( conn, op );
break;
case LDAP_REQ_SEARCH:
INCR_OP(num_ops_initiated_, SLAP_OP_SEARCH);
rc = do_search( conn, arg->co_op );
rc = do_search( conn, op );
break;
case LDAP_REQ_ABANDON:
INCR_OP(num_ops_initiated_, SLAP_OP_ABANDON);
rc = do_abandon( conn, arg->co_op );
rc = do_abandon( conn, op );
break;
case LDAP_REQ_EXTENDED:
INCR_OP(num_ops_initiated_, SLAP_OP_EXTENDED);
rc = do_extended( conn, arg->co_op );
rc = do_extended( conn, op );
break;
default:
......@@ -976,8 +971,8 @@ connection_operation( void *ctx, void *arg_v )
Debug( LDAP_DEBUG_ANY, "unknown LDAP request 0x%lx\n",
tag, 0, 0 );
#endif
arg->co_op->o_tag = LBER_ERROR;
send_ldap_disconnect( conn, arg->co_op,
op->o_tag = LBER_ERROR;
send_ldap_disconnect( conn, op,
LDAP_PROTOCOL_ERROR, "unknown LDAP request" );
rc = -1;
break;
......@@ -1028,12 +1023,12 @@ operations_error:
ldap_pvt_thread_mutex_unlock( &num_ops_mutex );
#ifdef LDAP_EXOP_X_CANCEL
if ( arg->co_op->o_cancel == SLAP_CANCEL_REQ ) {
arg->co_op->o_cancel = LDAP_TOO_LATE;
if ( op->o_cancel == SLAP_CANCEL_REQ ) {
op->o_cancel = LDAP_TOO_LATE;
}
while ( arg->co_op->o_cancel != SLAP_CANCEL_NONE &&
arg->co_op->o_cancel != SLAP_CANCEL_DONE )
while ( op->o_cancel != SLAP_CANCEL_NONE &&
op->o_cancel != SLAP_CANCEL_DONE )
{
ldap_pvt_thread_yield();
}
......@@ -1044,33 +1039,28 @@ operations_error:
conn->c_n_ops_executing--;
conn->c_n_ops_completed++;
LDAP_STAILQ_REMOVE( &conn->c_ops, arg->co_op, slap_op, o_next);
LDAP_STAILQ_NEXT(arg->co_op, o_next) = NULL;
LDAP_STAILQ_REMOVE( &conn->c_ops, op, slap_op, o_next);
LDAP_STAILQ_NEXT(op, o_next) = NULL;
#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
if ( arg->co_op->o_cancel == SLAP_CANCEL_ACK )
if ( op->o_cancel == SLAP_CANCEL_ACK )
goto co_op_free;
#endif
#ifdef LDAP_CLIENT_UPDATE
if ( ( arg->co_op->o_clientupdate_type & SLAP_LCUP_PERSIST ) )
if ( ( op->o_clientupdate_type & SLAP_LCUP_PERSIST ) )
goto no_co_op_free;
#endif
#ifdef LDAP_SYNC
if ( ( arg->co_op->o_sync_mode & SLAP_SYNC_PERSIST ) )
if ( ( op->o_sync_mode & SLAP_SYNC_PERSIST ) )
goto no_co_op_free;
#endif
co_op_free:
slap_op_free( arg->co_op );
slap_op_free( op );
no_co_op_free:
arg->co_op = NULL;
arg->co_conn = NULL;
free( (char *) arg );
arg = NULL;
switch( tag ) {
case LBER_ERROR:
case LDAP_REQ_UNBIND:
......@@ -1313,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;
......@@ -1440,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 );
......@@ -1478,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",
......@@ -1490,10 +1493,14 @@ 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++;
connection_op_activate( conn, op );
connection_op_activate( op );
}
#ifdef NO_THREADS
......@@ -1504,7 +1511,7 @@ connection_input(
#endif
assert( conn->c_struct_state == SLAP_C_USED );
return 0;
return rc;
}
static int
......@@ -1567,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 */
......@@ -1581,7 +1591,7 @@ connection_resched( Connection *conn )
conn->c_n_ops_pending--;
conn->c_n_ops_executing++;
connection_op_activate( conn, op );
connection_op_activate( op );
if ( conn->c_conn_state == SLAP_C_BINDING ) {
break;
......@@ -1590,46 +1600,44 @@ connection_resched( Connection *conn )
return 0;
}
static int connection_op_activate( Connection *conn, Operation *op )
static int connection_op_activate( Operation *op )
{
struct co_arg *arg;
int status;
ber_tag_t tag = op->o_tag;
if(tag == LDAP_REQ_BIND) {
conn->c_conn_state = SLAP_C_BINDING;
op->o_conn->c_conn_state = SLAP_C_BINDING;
}
arg = (struct co_arg *) ch_malloc( sizeof(struct co_arg) );
arg->co_conn = conn;
arg->co_op = op;
if (!arg->co_op->o_dn.bv_len) {
arg->co_op->o_authz = conn->c_authz;
arg->co_op->o_dn.bv_val = ch_strdup( conn->c_dn.bv_val ?
conn->c_dn.bv_val : "" );
arg->co_op->o_ndn.bv_val = ch_strdup( conn->c_ndn.bv_val ?
conn->c_ndn.bv_val : "" );
if (!op->o_dn.bv_len) {
op->o_authz = op->o_conn->c_authz;
ber_dupbv( &op->o_dn, &op->o_conn->c_dn );
ber_dupbv( &op->o_ndn, &op->o_conn->c_ndn );
}
arg->co_op->o_authtype = conn->c_authtype;
ber_dupbv( &arg->co_op->o_authmech, &conn->c_authmech );
op->o_authtype = op->o_conn->c_authtype;
ber_dupbv( &op->o_authmech, &op->o_conn->c_authmech );
if (!arg->co_op->o_protocol) {
arg->co_op->o_protocol = conn->c_protocol
? conn->c_protocol : LDAP_VERSION3;
if (!op->o_protocol) {
op->o_protocol = op->o_conn->c_protocol
? op->o_conn->c_protocol : LDAP_VERSION3;
}
arg->co_op->o_connid = conn->c_connid;
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( &conn->c_ops, arg->co_op, o_next );
LDAP_STAILQ_INSERT_TAIL( &op->o_conn->c_ops, op, o_next );
status = ldap_pvt_thread_pool_submit( &connection_pool,
connection_operation, (void *) arg );
connection_operation, (void *) op );
if ( status != 0 ) {
#ifdef NEW_LOGGING
LDAP_LOG( CONNECTION, ERR,
"connection_op_activate: conn %lu thread pool submit failed.\n",
conn->c_connid, 0, 0 );
op->o_connid, 0, 0 );
#else
Debug( LDAP_DEBUG_ANY,
"ldap_pvt_thread_pool_submit failed (%d)\n", status, 0, 0 );
......
......@@ -360,6 +360,7 @@ int main( int argc, char **argv )
#endif
extops_init();
slap_op_init();
#ifdef SLAPD_MODULES
if ( module_init() != 0 ) {
......@@ -574,6 +575,8 @@ destroy:
module_kill();
#endif
slap_op_destroy();
extops_kill();
stop:
......
......@@ -18,6 +18,26 @@
#include "slapi.h"
#endif
static ldap_pvt_thread_mutex_t slap_op_mutex;
static LDAP_STAILQ_HEAD(s_o, slap_op) slap_free_ops;
void slap_op_init()
{
ldap_pvt_thread_mutex_init( &slap_op_mutex );
LDAP_STAILQ_INIT(&slap_free_ops);
}
void slap_op_destroy()
{
Operation *o;
while ( (o = LDAP_STAILQ_FIRST( &slap_free_ops )) != NULL) {
LDAP_STAILQ_REMOVE_HEAD( &slap_free_ops, o_next );
LDAP_STAILQ_NEXT(o, o_next) = NULL;
ch_free( o );
}
ldap_pvt_thread_mutex_destroy( &slap_op_mutex );
}
void
slap_op_free( Operation *op )
......@@ -62,7 +82,10 @@ slap_op_free( Operation *op )
}
#endif /* defined( LDAP_SLAPI ) */
free( (char *) op );
memset( op, 0, sizeof(Operation) );
ldap_pvt_thread_mutex_lock( &slap_op_mutex );
LDAP_STAILQ_INSERT_HEAD( &slap_free_ops, op, o_next );
ldap_pvt_thread_mutex_unlock( &slap_op_mutex );
}
Operation *
......@@ -75,7 +98,14 @@ slap_op_alloc(
{
Operation *op;
op = (Operation *) ch_calloc( 1, sizeof(Operation) );
ldap_pvt_thread_mutex_lock( &slap_op_mutex );
if (op = LDAP_STAILQ_FIRST( &slap_free_ops )) {
LDAP_STAILQ_REMOVE_HEAD( &slap_free_ops, o_next );
}
ldap_pvt_thread_mutex_unlock( &slap_op_mutex );
if (!op)
op = (Operation *) ch_calloc( 1, sizeof(Operation) );
op->o_ber = ber;
op->o_msgid = msgid;
......
......@@ -1086,6 +1086,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;
......
......@@ -79,6 +79,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 */
......
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