Commit 6140cdf6 authored by Ondřej Kuzník's avatar Ondřej Kuzník Committed by Ondřej Kuzník
Browse files

Handle a client connection disconnected from op

parent d4225924
......@@ -263,7 +263,6 @@ void
client_reset( Connection *c )
{
TAvlnode *root;
int freed;
root = c->c_ops;
c->c_ops = NULL;
......@@ -292,19 +291,8 @@ client_reset( Connection *c )
CONNECTION_UNLOCK_INCREF(c);
if ( root ) {
TAvlnode *node = tavl_end( root, TAVL_DIR_LEFT );
do {
Operation *op = node->avl_data;
operation_abandon( op );
CONNECTION_LOCK(c);
op->o_client_refcnt--;
operation_destroy_from_client( op );
CONNECTION_UNLOCK(c);
} while ( (node = tavl_next( node, TAVL_DIR_RIGHT )) );
freed = tavl_free( root, NULL );
int freed;
freed = tavl_free( root, (AVL_FREE)operation_abandon );
Debug( LDAP_DEBUG_TRACE, "client_reset: "
"dropped %d operations\n",
freed );
......
......@@ -513,6 +513,13 @@ fail:
return NULL;
}
/*
* Will remove the operation from its upstream and if it was still there,
* sends an abandon request.
*
* Being called from client_reset or request_abandon, the following hold:
* - op->o_client_refcnt > 0 (and it follows that op->o_client != NULL)
*/
void
operation_abandon( Operation *op )
{
......@@ -524,22 +531,15 @@ operation_abandon( Operation *op )
ldap_pvt_thread_mutex_lock( &operation_mutex );
c = op->o_upstream;
if ( !c ) {
c = op->o_client;
assert( c );
/* Caller should hold a reference on client */
CONNECTION_LOCK(c);
ldap_pvt_thread_mutex_unlock( &operation_mutex );
operation_destroy_from_client( op );
CLIENT_UNLOCK_OR_DESTROY(c);
return;
goto done;
}
CONNECTION_LOCK(c);
ldap_pvt_thread_mutex_unlock( &operation_mutex );
if ( tavl_delete( &c->c_ops, op, operation_upstream_cmp ) == NULL ) {
/* The operation has already been abandoned or finished */
goto done;
goto unlock;
}
c->c_n_ops_executing--;
b = (Backend *)c->c_private;
......@@ -557,7 +557,7 @@ operation_abandon( Operation *op )
"ber_alloc failed\n" );
ldap_pvt_thread_mutex_unlock( &c->c_io_mutex );
CONNECTION_LOCK_DECREF(c);
goto done;
goto unlock;
}
c->c_pendingber = ber;
......@@ -577,9 +577,18 @@ operation_abandon( Operation *op )
}
CONNECTION_LOCK_DECREF(c);
done:
operation_destroy_from_upstream( op );
unlock:
UPSTREAM_UNLOCK_OR_DESTROY(c);
done:
c = op->o_client;
assert( c );
/* Caller should hold a reference on client */
CONNECTION_LOCK(c);
op->o_client_refcnt--;
operation_destroy_from_client( op );
CONNECTION_UNLOCK(c);
}
int
......
......@@ -418,8 +418,13 @@ handle_one_response( Connection *c )
client = op->o_client;
if ( client ) {
CONNECTION_LOCK(client);
op->o_client_refcnt++;
CONNECTION_UNLOCK_INCREF(client);
if ( client->c_live ) {
op->o_client_refcnt++;
CONNECTION_UNLOCK_INCREF(client);
} else {
CONNECTION_UNLOCK(client);
client = NULL;
}
}
ldap_pvt_thread_mutex_unlock( &operation_mutex );
......
Markdown is supported
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