]> git.sur5r.net Git - openldap/commitdiff
ITS#2389 - added conn_max_pending/auth config keywords to cap the number
authorHoward Chu <hyc@openldap.org>
Thu, 27 Mar 2003 03:35:46 +0000 (03:35 +0000)
committerHoward Chu <hyc@openldap.org>
Thu, 27 Mar 2003 03:35:46 +0000 (03:35 +0000)
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.

servers/slapd/config.c
servers/slapd/connection.c
servers/slapd/proto-slap.h
servers/slapd/slap.h

index 21ef05484bb6ec432033acdfbfcae21a2fe69de1..8951f40664229f103fa8e1c54acede67ce3d63bc 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_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 ) {
index 84aea37b9b5ca7686b280854245bc6fef8f2db5d..538f3721ce0acc141f71e141c23bf2706893377e 100644 (file)
@@ -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 );
index 94e0606ce5f0df85d35ee18c6bd0046b0e30d34a..6c5a613349df0374d8950c7e788aa8b571f61fe0 100644 (file)
@@ -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;
index 76c3989071c1803acb504e53a14eac3502924f0a..f09916f2b0e2bf32bb7d68b30af80f223ac92f17 100644 (file)
@@ -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 */