]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
Pending operation tracking and limiting
authorOndřej Kuzník <ondra@mistotebe.net>
Fri, 14 Apr 2017 08:45:18 +0000 (09:45 +0100)
committerOndřej Kuzník <okuznik@symas.com>
Tue, 17 Nov 2020 17:55:46 +0000 (17:55 +0000)
servers/lloadd/backend.c
servers/lloadd/client.c
servers/lloadd/config.c
servers/lloadd/operation.c
servers/lloadd/slap.h
servers/lloadd/upstream.c

index 89123f9c76e86d065a6d9d9dcaa07199d9daca12..b4614e58a6f02c870dbaf430d66bb0d20b18397d 100644 (file)
@@ -100,6 +100,15 @@ backend_select( Operation *op )
         Connection *c;
 
         ldap_pvt_thread_mutex_lock( &b->b_mutex );
+
+        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 );
+            continue;
+        }
+
         if ( op->o_tag == LDAP_REQ_BIND &&
                 !(lload_features & LLOAD_FEATURE_VC) ) {
             head = &b->b_bindconns;
@@ -112,11 +121,15 @@ backend_select( Operation *op )
         LDAP_LIST_FOREACH( c, head, c_next )
         {
             ldap_pvt_thread_mutex_lock( &c->c_io_mutex );
-            if ( c->c_state == SLAP_C_READY && !c->c_pendingber ) {
+            if ( c->c_state == SLAP_C_READY && !c->c_pendingber &&
+                    ( b->b_max_conn_pending == 0 ||
+                            c->c_n_ops_executing < b->b_max_conn_pending ) ) {
                 Debug( LDAP_DEBUG_CONNS, "backend_select: "
                         "selected connection %lu for client %lu msgid=%d\n",
-                        c->c_connid, op->o_client->c_connid,
-                        op->o_client_msgid );
+                        c->c_connid, op->o_client_connid, op->o_client_msgid );
+
+                b->b_n_ops_executing++;
+                c->c_n_ops_executing++;
                 ldap_pvt_thread_mutex_unlock( &b->b_mutex );
                 return c;
             }
index 9220eb51e93ffa5ad708949c0868ee50e5ea5bb5..bc21baeb152d5c05f1d6e13e10aacc8070c0f492 100644 (file)
@@ -201,6 +201,12 @@ fail:
 void
 client_destroy( Connection *c )
 {
+    TAvlnode *root, *node;
+
+    Debug( LDAP_DEBUG_CONNS, "client_destroy: "
+            "destroying client %lu\n",
+            c->c_connid );
+
     assert( c->c_read_event != NULL );
     event_del( c->c_read_event );
     event_free( c->c_read_event );
@@ -209,6 +215,25 @@ client_destroy( Connection *c )
     event_del( c->c_write_event );
     event_free( c->c_write_event );
 
+    root = c->c_ops;
+    c->c_ops = NULL;
+
+    if ( !BER_BVISNULL( &c->c_auth ) ) {
+        ch_free( c->c_auth.bv_val );
+    }
+
     c->c_state = SLAP_C_INVALID;
     connection_destroy( c );
+
+    if ( !root ) return;
+
+    /* We don't hold c_mutex anymore */
+    node = tavl_end( root, TAVL_DIR_LEFT );
+    do {
+        Operation *op = node->avl_data;
+
+        op->o_client = NULL;
+        operation_abandon( op );
+    } while ( (node = tavl_next( node, TAVL_DIR_RIGHT )) );
+    tavl_free( root, NULL );
 }
index 531e2196d9e5de7288e6d1673bfe4e23d148cde7..e3cb01cf6fe52703e427a78c1be15fd5fe9ad4b7 100644 (file)
@@ -1917,6 +1917,9 @@ static slap_cf_aux_table bindkey[] = {
     { BER_BVC("numconns="), offsetof(Backend, b_numconns), 'i', 0, NULL },
     { BER_BVC("bindconns="), offsetof(Backend, b_numbindconns), 'i', 0, NULL },
     { BER_BVC("retry="), offsetof(Backend, b_retry_timeout), 'i', 0, NULL },
+
+    { BER_BVC("max-pending-ops="), offsetof(Backend, b_max_pending), 'i', 0, NULL },
+    { BER_BVC("conn-max-pending="), offsetof(Backend, b_max_conn_pending), 'i', 0, NULL },
 #ifdef HAVE_TLS
     { BER_BVC("starttls="), offsetof(Backend, b_bindconf.sb_tls), 'i', 0, tlskey },
     { BER_BVC("tls_cert="), offsetof(Backend, b_bindconf.sb_tls_cert), 's', 1, NULL },
index 185d07a3fac80c6645db5f1b8ca661e20db87dba..3f4465dae33abea8081c5eddbfbd6549cbb1f0dc 100644 (file)
@@ -115,15 +115,28 @@ operation_destroy( Operation *op )
     if ( op->o_client ) {
         c = op->o_client;
         ldap_pvt_thread_mutex_lock( &c->c_mutex );
-        tavl_delete( &c->c_ops, op, operation_client_cmp );
+        if ( tavl_delete( &c->c_ops, op, operation_client_cmp ) ) {
+            c->c_n_ops_executing--;
+        }
         ldap_pvt_thread_mutex_unlock( &c->c_mutex );
     }
 
     if ( op->o_upstream ) {
+        Backend *b = NULL;
+
         c = op->o_upstream;
         ldap_pvt_thread_mutex_lock( &c->c_mutex );
-        tavl_delete( &c->c_ops, op, operation_upstream_cmp );
+        if ( tavl_delete( &c->c_ops, op, operation_upstream_cmp ) ) {
+            c->c_n_ops_executing--;
+            b = (Backend *)c->c_private;
+        }
         ldap_pvt_thread_mutex_unlock( &c->c_mutex );
+
+        if ( b ) {
+            ldap_pvt_thread_mutex_lock( &b->b_mutex );
+            b->b_n_ops_executing--;
+            ldap_pvt_thread_mutex_unlock( &b->b_mutex );
+        }
     }
 
     ch_free( op );
@@ -177,6 +190,7 @@ operation_init( Connection *c, BerElement *ber )
             slap_msgtype2str( op->o_tag ), op->o_client_msgid,
             op->o_client_connid );
 
+    c->c_n_ops_executing++;
     return op;
 
 fail:
@@ -192,9 +206,14 @@ operation_abandon( Operation *op )
     if ( op->o_upstream ) {
         Connection *c = op->o_upstream;
         BerElement *ber;
+        Backend *b;
 
         ldap_pvt_thread_mutex_lock( &c->c_mutex );
         rc = ( tavl_delete( &c->c_ops, op, operation_upstream_cmp ) == NULL );
+        if ( !rc ) {
+            c->c_n_ops_executing--;
+        }
+        b = (Backend *)c->c_private;
         ldap_pvt_thread_mutex_unlock( &c->c_mutex );
 
         if ( rc ) {
@@ -202,6 +221,10 @@ operation_abandon( Operation *op )
             goto done;
         }
 
+        ldap_pvt_thread_mutex_lock( &b->b_mutex );
+        b->b_n_ops_executing--;
+        ldap_pvt_thread_mutex_unlock( &b->b_mutex );
+
         ldap_pvt_thread_mutex_lock( &c->c_io_mutex );
 
         ber = c->c_pendingber;
index 9e06ed51b79ca234a7ba70a6e6fe586485520afd..fba2a68907fcd21552517d2feb488e190e526e46 100644 (file)
@@ -255,6 +255,9 @@ struct Backend {
     int b_bindavail, b_active, b_opening;
     LDAP_LIST_HEAD(ConnSt, Connection) b_conns, b_bindconns;
 
+    long b_max_pending, b_max_conn_pending;
+    long b_n_ops_executing;
+
     LDAP_STAILQ_ENTRY(Backend) b_next;
 };
 
index bd77b6a9a35517e3e0a841a717e7efce658da945..c52e872ffa4f8f4b9190d72c60d9a6b1855e0195 100644 (file)
@@ -258,7 +258,10 @@ static int
 handle_unsolicited( Connection *c, BerElement *ber )
 {
     TAvlnode *root;
-    int freed;
+    Backend *b;
+    long freed, executing;
+
+    b = (Backend *)c->c_private;
 
     Debug( LDAP_DEBUG_CONNS, "handle_unsolicited: "
             "teardown for upstream connection %lu\n",
@@ -266,17 +269,24 @@ handle_unsolicited( Connection *c, BerElement *ber )
 
     root = c->c_ops;
     c->c_ops = NULL;
+    executing = c->c_n_ops_executing;
+    c->c_n_ops_executing = 0;
     ldap_pvt_thread_mutex_unlock( &c->c_mutex );
 
     freed = tavl_free( root, (AVL_FREE)operation_lost_upstream );
+    assert( freed == executing );
     Debug( LDAP_DEBUG_TRACE, "handle_unsolicited: "
-            "dropped %d operations\n",
+            "dropped %ld operations\n",
             freed );
 
     ldap_pvt_thread_mutex_lock( &c->c_mutex );
     upstream_destroy( c );
     ber_free( ber, 1 );
 
+    ldap_pvt_thread_mutex_lock( &b->b_mutex );
+    b->b_n_ops_executing -= executing;
+    ldap_pvt_thread_mutex_unlock( &b->b_mutex );
+
     return -1;
 }
 
@@ -830,6 +840,7 @@ upstream_destroy( Connection *c )
     } else {
         b->b_active--;
     }
+    b->b_n_ops_executing -= c->c_n_ops_executing;
     ldap_pvt_thread_mutex_unlock( &b->b_mutex );
     backend_retry( b );