mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-01-12 10:54:48 +08:00
ITS#9001 Use a TAvl for request tracking in libldap
This commit is contained in:
parent
e36d1e31c5
commit
3bd1b0909a
@ -40,7 +40,7 @@ static int
|
||||
do_abandon(
|
||||
LDAP *ld,
|
||||
ber_int_t origid,
|
||||
ber_int_t msgid,
|
||||
LDAPRequest *lr,
|
||||
LDAPControl **sctrls,
|
||||
int sendabandon );
|
||||
|
||||
@ -75,7 +75,7 @@ ldap_abandon_ext(
|
||||
|
||||
rc = ldap_int_client_controls( ld, cctrls );
|
||||
if ( rc == LDAP_SUCCESS ) {
|
||||
rc = do_abandon( ld, msgid, msgid, sctrls, 1 );
|
||||
rc = do_abandon( ld, msgid, NULL, sctrls, 1 );
|
||||
}
|
||||
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
||||
@ -112,7 +112,7 @@ ldap_pvt_discard(
|
||||
int rc;
|
||||
|
||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
||||
rc = do_abandon( ld, msgid, msgid, NULL, 0 );
|
||||
rc = do_abandon( ld, msgid, NULL, NULL, 0 );
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
||||
return rc;
|
||||
}
|
||||
@ -121,49 +121,52 @@ static int
|
||||
do_abandon(
|
||||
LDAP *ld,
|
||||
ber_int_t origid,
|
||||
ber_int_t msgid,
|
||||
LDAPRequest *lr,
|
||||
LDAPControl **sctrls,
|
||||
int sendabandon )
|
||||
{
|
||||
BerElement *ber;
|
||||
int i, err;
|
||||
ber_int_t msgid = origid;
|
||||
Sockbuf *sb;
|
||||
LDAPRequest *lr;
|
||||
LDAPRequest needle = {0};
|
||||
|
||||
Debug2( LDAP_DEBUG_TRACE, "do_abandon origid %d, msgid %d\n",
|
||||
origid, msgid );
|
||||
|
||||
/* find the request that we are abandoning */
|
||||
start_again:;
|
||||
lr = ld->ld_requests;
|
||||
while ( lr != NULL ) {
|
||||
/* this message */
|
||||
if ( lr->lr_msgid == msgid ) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* child: abandon it */
|
||||
if ( lr->lr_origid == msgid && !lr->lr_abandoned ) {
|
||||
(void)do_abandon( ld, lr->lr_origid, lr->lr_msgid,
|
||||
sctrls, sendabandon );
|
||||
|
||||
/* restart, as lr may now be dangling... */
|
||||
goto start_again;
|
||||
}
|
||||
|
||||
lr = lr->lr_next;
|
||||
}
|
||||
needle.lr_msgid = origid;
|
||||
|
||||
if ( lr != NULL ) {
|
||||
if ( origid == msgid && lr->lr_parent != NULL ) {
|
||||
msgid = lr->lr_msgid;
|
||||
Debug2( LDAP_DEBUG_TRACE, "do_abandon origid %d, msgid %d\n",
|
||||
origid, msgid );
|
||||
} else if ( (lr = ldap_tavl_find( ld->ld_requests, &needle, ldap_req_cmp )) != NULL ) {
|
||||
Debug2( LDAP_DEBUG_TRACE, "do_abandon origid %d, msgid %d\n",
|
||||
origid, msgid );
|
||||
if ( lr->lr_parent != NULL ) {
|
||||
/* don't let caller abandon child requests! */
|
||||
ld->ld_errno = LDAP_PARAM_ERROR;
|
||||
return( LDAP_PARAM_ERROR );
|
||||
}
|
||||
msgid = lr->lr_msgid;
|
||||
}
|
||||
|
||||
if ( lr != NULL ) {
|
||||
LDAPRequest **childp = &lr->lr_child;
|
||||
|
||||
needle.lr_msgid = lr->lr_msgid;
|
||||
|
||||
if ( lr->lr_status != LDAP_REQST_INPROGRESS ) {
|
||||
/* no need to send abandon message */
|
||||
sendabandon = 0;
|
||||
}
|
||||
|
||||
while ( *childp ) {
|
||||
/* Abandon children */
|
||||
LDAPRequest *child = *childp;
|
||||
|
||||
(void)do_abandon( ld, lr->lr_origid, child, sctrls, sendabandon );
|
||||
if ( *childp == child ) {
|
||||
childp = &child->lr_refnext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ldap_msgdelete locks the res_mutex. Give up the req_mutex
|
||||
@ -179,12 +182,7 @@ start_again:;
|
||||
|
||||
/* fetch again the request that we are abandoning */
|
||||
if ( lr != NULL ) {
|
||||
for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
|
||||
/* this message */
|
||||
if ( lr->lr_msgid == msgid ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
lr = ldap_tavl_find( ld->ld_requests, &needle, ldap_req_cmp );
|
||||
}
|
||||
|
||||
err = 0;
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include "../liblber/lber-int.h"
|
||||
#include "lutil.h"
|
||||
#include "ldap_avl.h"
|
||||
|
||||
#ifdef LDAP_R_COMPILE
|
||||
#include <ldap_pvt_thread.h>
|
||||
@ -438,7 +439,7 @@ struct ldap_common {
|
||||
|
||||
/* do not mess with these */
|
||||
/* protected by req_mutex */
|
||||
LDAPRequest *ldc_requests; /* list of outstanding requests */
|
||||
TAvlnode *ldc_requests; /* list of outstanding requests */
|
||||
/* protected by res_mutex */
|
||||
LDAPMessage *ldc_responses; /* list of outstanding responses */
|
||||
#define ld_requests ldc->ldc_requests
|
||||
@ -776,6 +777,8 @@ LDAP_F (LDAPConn *) ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist,
|
||||
int use_ldsb, int connect, LDAPreqinfo *bind, int m_req, int m_res );
|
||||
LDAP_F (LDAPRequest *) ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid );
|
||||
LDAP_F (void) ldap_return_request( LDAP *ld, LDAPRequest *lr, int freeit );
|
||||
LDAP_F (int) ldap_req_cmp( const void *l, const void *r );
|
||||
LDAP_F (void) ldap_do_free_request( void *arg );
|
||||
LDAP_F (void) ldap_free_request( LDAP *ld, LDAPRequest *lr );
|
||||
LDAP_F (void) ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind );
|
||||
LDAP_F (void) ldap_dump_connection( LDAP *ld, LDAPConn *lconns, int all );
|
||||
|
@ -574,7 +574,8 @@ ldap_open_internal_connection( LDAP **ldp, ber_socket_t *fdp )
|
||||
lr->lr_status = LDAP_REQST_INPROGRESS;
|
||||
lr->lr_res_errno = LDAP_SUCCESS;
|
||||
/* no mutex lock needed, we just created this ld here */
|
||||
ld->ld_requests = lr;
|
||||
rc = ldap_tavl_insert( &ld->ld_requests, lr, ldap_req_cmp, ldap_avl_dup_error );
|
||||
assert( rc == LDAP_SUCCESS );
|
||||
|
||||
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
||||
/* Attach the passed socket as the *LDAP's connection */
|
||||
|
@ -328,11 +328,16 @@ ldap_send_server_request(
|
||||
* request to be in WRITING state.
|
||||
*/
|
||||
rc = 0;
|
||||
if ( ld->ld_requests &&
|
||||
ld->ld_requests->lr_status == LDAP_REQST_WRITING &&
|
||||
ldap_int_flush_request( ld, ld->ld_requests ) < 0 )
|
||||
{
|
||||
rc = -1;
|
||||
if ( ld->ld_requests != NULL ) {
|
||||
TAvlnode *node = ldap_tavl_end( ld->ld_requests, TAVL_DIR_RIGHT );
|
||||
LDAPRequest *lr;
|
||||
|
||||
assert( node != NULL );
|
||||
lr = node->avl_data;
|
||||
if ( lr->lr_status == LDAP_REQST_WRITING &&
|
||||
ldap_int_flush_request( ld, lr ) < 0 ) {
|
||||
rc = -1;
|
||||
}
|
||||
}
|
||||
if ( rc ) {
|
||||
ber_free( ber, 1 );
|
||||
@ -399,12 +404,8 @@ ldap_send_server_request(
|
||||
}
|
||||
}
|
||||
|
||||
lr->lr_prev = NULL;
|
||||
lr->lr_next = ld->ld_requests;
|
||||
if ( lr->lr_next != NULL ) {
|
||||
lr->lr_next->lr_prev = lr;
|
||||
}
|
||||
ld->ld_requests = lr;
|
||||
rc = ldap_tavl_insert( &ld->ld_requests, lr, ldap_req_cmp, ldap_avl_dup_error );
|
||||
assert( rc == LDAP_SUCCESS );
|
||||
|
||||
ld->ld_errno = LDAP_SUCCESS;
|
||||
if ( ldap_int_flush_request( ld, lr ) == -1 ) {
|
||||
@ -803,19 +804,10 @@ ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind )
|
||||
/* FIXME: is this at all possible?
|
||||
* ldap_ld_free() in unbind.c calls ldap_free_connection()
|
||||
* with force == 1 __after__ explicitly calling
|
||||
* ldap_free_request() on all requests */
|
||||
* ldap_tavl_free on ld->ld_requests */
|
||||
if ( force ) {
|
||||
LDAPRequest *lr;
|
||||
|
||||
for ( lr = ld->ld_requests; lr; ) {
|
||||
LDAPRequest *lr_next = lr->lr_next;
|
||||
|
||||
if ( lr->lr_conn == lc ) {
|
||||
ldap_free_request_int( ld, lr );
|
||||
}
|
||||
|
||||
lr = lr_next;
|
||||
}
|
||||
ldap_tavl_free( ld->ld_requests, ldap_do_free_request );
|
||||
ld->ld_requests = NULL;
|
||||
}
|
||||
|
||||
if ( lc->lconn_sb != ld->ld_sb ) {
|
||||
@ -913,17 +905,19 @@ ldap_dump_connection( LDAP *ld, LDAPConn *lconns, int all )
|
||||
void
|
||||
ldap_dump_requests_and_responses( LDAP *ld )
|
||||
{
|
||||
LDAPRequest *lr;
|
||||
LDAPMessage *lm, *l;
|
||||
TAvlnode *node;
|
||||
int i;
|
||||
|
||||
Debug1( LDAP_DEBUG_TRACE, "** ld %p Outstanding Requests:\n",
|
||||
(void *)ld );
|
||||
lr = ld->ld_requests;
|
||||
if ( lr == NULL ) {
|
||||
node = ldap_tavl_end( ld->ld_requests, TAVL_DIR_LEFT );
|
||||
if ( node == NULL ) {
|
||||
Debug0( LDAP_DEBUG_TRACE, " Empty\n" );
|
||||
}
|
||||
for ( i = 0; lr != NULL; lr = lr->lr_next, i++ ) {
|
||||
for ( i = 0 ; node != NULL; i++, node = ldap_tavl_next( node, TAVL_DIR_RIGHT ) ) {
|
||||
LDAPRequest *lr = node->avl_data;
|
||||
|
||||
Debug3( LDAP_DEBUG_TRACE, " * msgid %d, origid %d, status %s\n",
|
||||
lr->lr_msgid, lr->lr_origid,
|
||||
( lr->lr_status == LDAP_REQST_INPROGRESS ) ? "InProgress" :
|
||||
@ -959,39 +953,21 @@ ldap_dump_requests_and_responses( LDAP *ld )
|
||||
#endif /* LDAP_DEBUG */
|
||||
|
||||
/* protected by req_mutex */
|
||||
static void
|
||||
ldap_free_request_int( LDAP *ld, LDAPRequest *lr )
|
||||
void
|
||||
ldap_do_free_request( void *arg )
|
||||
{
|
||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
|
||||
LDAPRequest *lr = arg;
|
||||
|
||||
Debug3( LDAP_DEBUG_TRACE, "ldap_do_free_request: "
|
||||
"asked to free lr %p msgid %d refcnt %d\n",
|
||||
lr, lr->lr_msgid, lr->lr_refcnt );
|
||||
/* if lr_refcnt > 0, the request has been looked up
|
||||
* by ldap_find_request_by_msgid(); if in the meanwhile
|
||||
* the request is free()'d by someone else, just decrease
|
||||
* the reference count and extract it from the request
|
||||
* list; later on, it will be freed. */
|
||||
if ( lr->lr_prev == NULL ) {
|
||||
if ( lr->lr_refcnt == 0 ) {
|
||||
/* free'ing the first request? */
|
||||
assert( ld->ld_requests == lr );
|
||||
}
|
||||
|
||||
if ( ld->ld_requests == lr ) {
|
||||
ld->ld_requests = lr->lr_next;
|
||||
}
|
||||
|
||||
} else {
|
||||
lr->lr_prev->lr_next = lr->lr_next;
|
||||
}
|
||||
|
||||
if ( lr->lr_next != NULL ) {
|
||||
lr->lr_next->lr_prev = lr->lr_prev;
|
||||
}
|
||||
|
||||
* the reference count; later on, it will be freed. */
|
||||
if ( lr->lr_refcnt > 0 ) {
|
||||
assert( lr->lr_refcnt == 1 );
|
||||
lr->lr_refcnt = -lr->lr_refcnt;
|
||||
|
||||
lr->lr_prev = NULL;
|
||||
lr->lr_next = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1013,6 +989,29 @@ ldap_free_request_int( LDAP *ld, LDAPRequest *lr )
|
||||
LDAP_FREE( lr );
|
||||
}
|
||||
|
||||
int
|
||||
ldap_req_cmp( const void *l, const void *r )
|
||||
{
|
||||
const LDAPRequest *left = l, *right = r;
|
||||
return left->lr_msgid - right->lr_msgid;
|
||||
}
|
||||
|
||||
/* protected by req_mutex */
|
||||
static void
|
||||
ldap_free_request_int( LDAP *ld, LDAPRequest *lr )
|
||||
{
|
||||
LDAPRequest *removed;
|
||||
|
||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
|
||||
removed = ldap_tavl_delete( &ld->ld_requests, lr, ldap_req_cmp );
|
||||
assert( !removed || removed == lr );
|
||||
Debug3( LDAP_DEBUG_TRACE, "ldap_free_request_int: "
|
||||
"lr %p msgid %d%s removed\n",
|
||||
lr, lr->lr_msgid, removed ? "" : " not" );
|
||||
|
||||
ldap_do_free_request( lr );
|
||||
}
|
||||
|
||||
/* protected by req_mutex */
|
||||
void
|
||||
ldap_free_request( LDAP *ld, LDAPRequest *lr )
|
||||
@ -1662,19 +1661,24 @@ re_encode_request( LDAP *ld,
|
||||
LDAPRequest *
|
||||
ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid )
|
||||
{
|
||||
LDAPRequest *lr;
|
||||
LDAPRequest *lr, needle = {0};
|
||||
needle.lr_msgid = msgid;
|
||||
|
||||
for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
|
||||
if ( lr->lr_status == LDAP_REQST_COMPLETED ) {
|
||||
continue; /* Skip completed requests */
|
||||
}
|
||||
if ( msgid == lr->lr_msgid ) {
|
||||
lr->lr_refcnt++;
|
||||
break;
|
||||
}
|
||||
lr = ldap_tavl_find( ld->ld_requests, &needle, ldap_req_cmp );
|
||||
if ( lr != NULL && lr->lr_status != LDAP_REQST_COMPLETED ) {
|
||||
/* try_read1msg is the only user at the moment and we would free it
|
||||
* multiple times if retrieving the request again */
|
||||
assert( lr->lr_refcnt == 0 );
|
||||
lr->lr_refcnt++;
|
||||
Debug3( LDAP_DEBUG_TRACE, "ldap_find_request_by_msgid: "
|
||||
"msgid %d, lr %p lr->lr_refcnt = %d\n",
|
||||
msgid, lr, lr->lr_refcnt );
|
||||
return lr;
|
||||
}
|
||||
|
||||
return( lr );
|
||||
Debug2( LDAP_DEBUG_TRACE, "ldap_find_request_by_msgid: "
|
||||
"msgid %d, lr %p\n", msgid, lr );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* protected by req_mutex */
|
||||
@ -1683,23 +1687,26 @@ ldap_return_request( LDAP *ld, LDAPRequest *lrx, int freeit )
|
||||
{
|
||||
LDAPRequest *lr;
|
||||
|
||||
for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
|
||||
if ( lr == lrx ) {
|
||||
if ( lr->lr_refcnt > 0 ) {
|
||||
lr->lr_refcnt--;
|
||||
|
||||
} else if ( lr->lr_refcnt < 0 ) {
|
||||
lr->lr_refcnt++;
|
||||
if ( lr->lr_refcnt == 0 ) {
|
||||
lr = NULL;
|
||||
}
|
||||
lr = ldap_tavl_find( ld->ld_requests, lrx, ldap_req_cmp );
|
||||
Debug2( LDAP_DEBUG_TRACE, "ldap_return_request: "
|
||||
"lrx %p, lr %p\n", lrx, lr );
|
||||
if ( lr ) {
|
||||
assert( lr == lrx );
|
||||
if ( lr->lr_refcnt > 0 ) {
|
||||
lr->lr_refcnt--;
|
||||
} else if ( lr->lr_refcnt < 0 ) {
|
||||
lr->lr_refcnt++;
|
||||
if ( lr->lr_refcnt == 0 ) {
|
||||
lr = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
Debug3( LDAP_DEBUG_TRACE, "ldap_return_request: "
|
||||
"lrx->lr_msgid %d, lrx->lr_refcnt is now %d, lr is %s present\n",
|
||||
lrx->lr_msgid, lrx->lr_refcnt, lr ? "still" : "not" );
|
||||
/* The request is not tracked anymore */
|
||||
if ( lr == NULL ) {
|
||||
ldap_free_request_int( ld, lrx );
|
||||
|
||||
} else if ( freeit ) {
|
||||
ldap_free_request( ld, lrx );
|
||||
}
|
||||
|
@ -344,13 +344,17 @@ wait4msg(
|
||||
int serviced = 0;
|
||||
rc = LDAP_MSG_X_KEEP_LOOKING;
|
||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
||||
if ( ld->ld_requests &&
|
||||
ld->ld_requests->lr_status == LDAP_REQST_WRITING &&
|
||||
ldap_is_write_ready( ld,
|
||||
ld->ld_requests->lr_conn->lconn_sb ) )
|
||||
{
|
||||
serviced = 1;
|
||||
ldap_int_flush_request( ld, ld->ld_requests );
|
||||
if ( ld->ld_requests != NULL ) {
|
||||
TAvlnode *node = ldap_tavl_end( ld->ld_requests, TAVL_DIR_RIGHT );
|
||||
LDAPRequest *lr;
|
||||
|
||||
assert( node != NULL );
|
||||
lr = node->avl_data;
|
||||
if ( lr->lr_status == LDAP_REQST_WRITING &&
|
||||
ldap_is_write_ready( ld, lr->lr_conn->lconn_sb ) ) {
|
||||
serviced = 1;
|
||||
ldap_int_flush_request( ld, lr );
|
||||
}
|
||||
}
|
||||
for ( lc = ld->ld_conns;
|
||||
rc == LDAP_MSG_X_KEEP_LOOKING && lc != NULL;
|
||||
@ -452,7 +456,7 @@ try_read1msg(
|
||||
LDAPRequest *lr, *tmplr, dummy_lr = { 0 };
|
||||
BerElement tmpber;
|
||||
int rc, refer_cnt, hadref, simple_request, err;
|
||||
ber_int_t lderr;
|
||||
ber_int_t lderr = -1;
|
||||
|
||||
#ifdef LDAP_CONNECTIONLESS
|
||||
LDAPMessage *tmp = NULL, *chain_head = NULL;
|
||||
|
@ -108,9 +108,8 @@ ldap_ld_free(
|
||||
|
||||
/* free LDAP structure and outstanding requests/responses */
|
||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
||||
while ( ld->ld_requests != NULL ) {
|
||||
ldap_free_request( ld, ld->ld_requests );
|
||||
}
|
||||
ldap_tavl_free( ld->ld_requests, ldap_do_free_request );
|
||||
ld->ld_requests = NULL;
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
||||
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user