]> git.sur5r.net Git - openldap/commitdiff
Fix ITS#2389, sync with HEAD
authorHoward Chu <hyc@openldap.org>
Thu, 27 Mar 2003 04:04:06 +0000 (04:04 +0000)
committerHoward Chu <hyc@openldap.org>
Thu, 27 Mar 2003 04:04:06 +0000 (04:04 +0000)
servers/slapd/config.c
servers/slapd/connection.c
servers/slapd/main.c
servers/slapd/operation.c
servers/slapd/proto-slap.h
servers/slapd/slap.h

index 020450c839a062a23d0f6f40947b36d19156714d..8c93db6bd2a225ec1afdbde0bb31e384b9350b28 100644 (file)
@@ -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 ) {
index 005496fdd900e41143023b40ebf231bf92e066cb..538f3721ce0acc141f71e141c23bf2706893377e 100644 (file)
@@ -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 );
index 51970015af7108ccac4cffe6a12cad438a469537..69fcd04c5afc8c3011bd007823ec0c3149491d35 100644 (file)
@@ -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:
index 2a8da886da336e1b588d7941c8da1bfba0274b6d..499c884eaeb3484a4358a5eb1a880695d83977ef 100644 (file)
 #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;
index e2df5f9f6c56114646f52d52876faea4053df4fd..c9b34ecba09473a1ee1a77bb46f2a86434ebd8e0 100644 (file)
@@ -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;
index aae80c7b3bdb94daad9f1dabd0226b56b34368f7..1bc94e0e16d05449efcdf481f01bd80caa35fa99 100644 (file)
@@ -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 */