diff --git a/servers/lloadd/operation.c b/servers/lloadd/operation.c index f1b057ae2f..a52d880dd1 100644 --- a/servers/lloadd/operation.c +++ b/servers/lloadd/operation.c @@ -517,6 +517,38 @@ fail: return NULL; } +int +operation_send_abandon( Operation *op ) +{ + Connection *upstream = op->o_upstream; + BerElement *ber; + int rc = -1; + + ldap_pvt_thread_mutex_lock( &upstream->c_io_mutex ); + ber = upstream->c_pendingber; + if ( ber == NULL && (ber = ber_alloc()) == NULL ) { + Debug( LDAP_DEBUG_ANY, "operation_send_abandon: " + "ber_alloc failed\n" ); + goto done; + } + upstream->c_pendingber = ber; + + rc = ber_printf( ber, "t{titi}", LDAP_TAG_MESSAGE, + LDAP_TAG_MSGID, upstream->c_next_msgid++, + LDAP_REQ_ABANDON, op->o_upstream_msgid ); + + if ( rc < 0 ) { + ber_free( ber, 1 ); + upstream->c_pendingber = NULL; + goto done; + } + rc = LDAP_SUCCESS; + +done: + ldap_pvt_thread_mutex_unlock( &upstream->c_io_mutex ); + return rc; +} + /* * Will remove the operation from its upstream and if it was still there, * sends an abandon request. @@ -528,9 +560,8 @@ void operation_abandon( Operation *op ) { Connection *c; - BerElement *ber; Backend *b; - int rc; + int rc = LDAP_SUCCESS; ldap_pvt_thread_mutex_lock( &op->o_link_mutex ); c = op->o_upstream; @@ -556,30 +587,7 @@ operation_abandon( Operation *op ) 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; - if ( ber == NULL && (ber = ber_alloc()) == NULL ) { - Debug( LDAP_DEBUG_ANY, "operation_abandon: " - "ber_alloc failed\n" ); - ldap_pvt_thread_mutex_unlock( &c->c_io_mutex ); - CONNECTION_LOCK_DECREF(c); - goto unlock; - } - c->c_pendingber = ber; - - rc = ber_printf( ber, "t{titi}", LDAP_TAG_MESSAGE, - LDAP_TAG_MSGID, c->c_next_msgid++, - LDAP_REQ_ABANDON, op->o_upstream_msgid ); - - if ( rc == -1 ) { - ber_free( ber, 1 ); - c->c_pendingber = NULL; - } - - ldap_pvt_thread_mutex_unlock( &c->c_io_mutex ); - - if ( rc != -1 ) { + if ( operation_send_abandon( op ) == LDAP_SUCCESS ) { connection_write_cb( -1, 0, c ); } @@ -594,7 +602,11 @@ unlock: if ( !c->c_live ) { operation_destroy_from_upstream( op ); } - CONNECTION_UNLOCK_OR_DESTROY(c); + if ( rc ) { + CONNECTION_DESTROY(c); + } else { + CONNECTION_UNLOCK_OR_DESTROY(c); + } done: c = op->o_client; diff --git a/servers/lloadd/proto-slap.h b/servers/lloadd/proto-slap.h index 7fd5354b5a..5f797cac78 100644 --- a/servers/lloadd/proto-slap.h +++ b/servers/lloadd/proto-slap.h @@ -171,6 +171,7 @@ LDAP_SLAPD_F (const char *) slap_msgtype2str( ber_tag_t tag ); LDAP_SLAPD_F (int) operation_upstream_cmp( const void *l, const void *r ); LDAP_SLAPD_F (int) operation_client_cmp( const void *l, const void *r ); LDAP_SLAPD_F (Operation *) operation_init( Connection *c, BerElement *ber ); +LDAP_SLAPD_F (int) operation_send_abandon( Operation *op ); LDAP_SLAPD_F (void) operation_abandon( Operation *op ); LDAP_SLAPD_F (void) operation_send_reject( Operation *op, int result, const char *msg, int send_anyway ); LDAP_SLAPD_F (int) operation_send_reject_locked( Operation *op, int result, const char *msg, int send_anyway );