client_reset( Connection *c )
{
TAvlnode *root;
- int freed;
root = c->c_ops;
c->c_ops = NULL;
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 );
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 )
{
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;
"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;
}
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
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 );