Commit b45c0c88 authored by Pierangelo Masarati's avatar Pierangelo Masarati
Browse files

keep count of requests in use

parent 517ae661
......@@ -263,23 +263,24 @@ typedef struct ldap_conn {
* structure used to track outstanding requests
*/
typedef struct ldapreq {
ber_int_t lr_msgid; /* the message id */
ber_int_t lr_msgid; /* the message id */
int lr_status; /* status of request */
#define LDAP_REQST_COMPLETED 0
#define LDAP_REQST_INPROGRESS 1
#define LDAP_REQST_CHASINGREFS 2
#define LDAP_REQST_NOTCONNECTED 3
#define LDAP_REQST_WRITING 4
int lr_refcnt; /* count of references */
int lr_outrefcnt; /* count of outstanding referrals */
ber_int_t lr_origid; /* original request's message id */
ber_int_t lr_origid; /* original request's message id */
int lr_parentcnt; /* count of parent requests */
ber_tag_t lr_res_msgtype; /* result message type */
ber_int_t lr_res_errno; /* result LDAP errno */
ber_tag_t lr_res_msgtype; /* result message type */
ber_int_t lr_res_errno; /* result LDAP errno */
char *lr_res_error; /* result error string */
char *lr_res_matched;/* result matched DN string */
BerElement *lr_ber; /* ber encoded request contents */
LDAPConn *lr_conn; /* connection used to send request */
struct berval lr_dn; /* DN of request, in lr_ber */
struct berval lr_dn; /* DN of request, in lr_ber */
struct ldapreq *lr_parent; /* request that spawned this referral */
struct ldapreq *lr_child; /* first child request */
struct ldapreq *lr_refnext; /* next referral spawned */
......@@ -532,6 +533,7 @@ LDAP_F (void) ldap_set_ber_options( LDAP *ld, BerElement *ber );
LDAP_F (int) ldap_send_server_request( LDAP *ld, BerElement *ber, ber_int_t msgid, LDAPRequest *parentreq, LDAPURLDesc **srvlist, LDAPConn *lc, LDAPreqinfo *bind );
LDAP_F (LDAPConn *) ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb, int connect, LDAPreqinfo *bind );
LDAP_F (LDAPRequest *) ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid );
LDAP_F (void) ldap_return_request_by_msgid( LDAP *ld, LDAPRequest *lr, int freeit );
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 );
......
......@@ -293,7 +293,8 @@ ldap_send_server_request(
}
lr->lr_prev = NULL;
if (( lr->lr_next = ld->ld_requests ) != NULL ) {
lr->lr_next = ld->ld_requests;
if ( lr->lr_next != NULL ) {
lr->lr_next->lr_prev = lr;
}
ld->ld_requests = lr;
......@@ -740,10 +741,20 @@ ldap_dump_requests_and_responses( LDAP *ld )
static void
ldap_free_request_int( LDAP *ld, LDAPRequest *lr )
{
/* 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 ) {
/* free'ing the first request? */
assert( ld->ld_requests == lr );
ld->ld_requests = lr->lr_next;
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;
......@@ -753,6 +764,15 @@ ldap_free_request_int( LDAP *ld, LDAPRequest *lr )
lr->lr_next->lr_prev = lr->lr_prev;
}
if ( lr->lr_refcnt > 0 ) {
lr->lr_refcnt = -lr->lr_refcnt;
lr->lr_prev = NULL;
lr->lr_next = NULL;
return;
}
if ( lr->lr_ber != NULL ) {
ber_free( lr->lr_ber, 1 );
lr->lr_ber = NULL;
......@@ -788,8 +808,10 @@ ldap_free_request( LDAP *ld, LDAPRequest *lr )
if ( lr->lr_parent != NULL ) {
--lr->lr_parent->lr_outrefcnt;
for ( ttmplr = &lr->lr_parent->lr_child; *ttmplr && *ttmplr != lr; ttmplr = &(*ttmplr)->lr_refnext );
if ( *ttmplr == lr )
for ( ttmplr = &lr->lr_parent->lr_child;
*ttmplr && *ttmplr != lr;
ttmplr = &(*ttmplr)->lr_refnext );
if ( *ttmplr == lr )
*ttmplr = lr->lr_refnext;
}
ldap_free_request_int( ld, lr );
......@@ -1422,6 +1444,7 @@ ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid )
continue; /* Skip completed requests */
}
if ( msgid == lr->lr_msgid ) {
lr->lr_refcnt++;
break;
}
}
......@@ -1432,4 +1455,35 @@ ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid )
return( lr );
}
void
ldap_return_request_by_msgid( LDAP *ld, LDAPRequest *lrx, int freeit )
{
LDAPRequest *lr;
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
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;
}
}
break;
}
}
if ( lr == NULL ) {
ldap_free_request_int( ld, lrx );
} else if ( freeit ) {
ldap_free_request( ld, lrx );
}
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
}
......@@ -337,6 +337,7 @@ wait4msg(
if ( rc == -1 ) {
rc = LDAP_MSG_X_KEEP_LOOKING; /* select interrupted: loop */
} else {
rc = LDAP_MSG_X_KEEP_LOOKING;
#ifdef LDAP_R_COMPILE
......@@ -577,6 +578,7 @@ nextresp2:
/* Get the referral list */
if ( ber_scanf( &tmpber, "{v}", &refs ) == LBER_ERROR ) {
rc = LDAP_DECODING_ERROR;
} else {
/* Note: refs array is freed by ldap_chase_v3referrals */
refer_cnt = ldap_chase_v3referrals( ld, lr, refs,
......@@ -598,6 +600,7 @@ nextresp2:
}
}
}
} else {
/* Check for V3 referral */
ber_len_t len;
......@@ -608,14 +611,12 @@ nextresp2:
!= LBER_ERROR )
{
if ( lr_res_error != NULL ) {
{
if ( lr->lr_res_error != NULL ) {
(void)ldap_append_referral( ld, &lr->lr_res_error, lr_res_error );
LDAP_FREE( (char *)lr_res_error );
if ( lr->lr_res_error != NULL ) {
(void)ldap_append_referral( ld, &lr->lr_res_error, lr_res_error );
LDAP_FREE( (char *)lr_res_error );
} else {
lr->lr_res_error = lr_res_error;
}
} else {
lr->lr_res_error = lr_res_error;
}
lr_res_error = NULL;
}
......@@ -637,6 +638,7 @@ nextresp2:
Debug( LDAP_DEBUG_TRACE,
"read1msg: referral decode error, mark request completed, ld %p msgid %d\n",
(void *)ld, lr->lr_msgid, 0);
} else {
/* Chase the referral
* Note: refs arrary is freed by ldap_chase_v3referrals
......@@ -659,6 +661,7 @@ nextresp2:
LDAP_FREE( lr->lr_res_matched );
lr->lr_res_matched = NULL;
}
if( lr->lr_res_error != NULL ) {
LDAP_FREE( lr->lr_res_error );
lr->lr_res_error = NULL;
......@@ -690,6 +693,7 @@ nextresp2:
*/
if ( tag == LDAP_RES_SEARCH_RESULT )
refer_cnt = 0;
} else if ( ber_scanf( &tmpber, "{eAA}", &lderr,
&lr->lr_res_matched, &lr_res_error )
!= LBER_ERROR )
......@@ -733,8 +737,10 @@ nextresp2:
lr->lr_res_errno = ( lderr ==
LDAP_PARTIAL_RESULTS ) ? LDAP_SUCCESS
: lderr;
} else if ( ld->ld_errno != LDAP_SUCCESS ) {
lr->lr_res_errno = ld->ld_errno;
} else {
lr->lr_res_errno = LDAP_PARTIAL_RESULTS;
}
......@@ -762,13 +768,16 @@ nextresp2:
ber_free( ber, 1 );
ber = NULL;
if ( refer_cnt < 0 ) {
ldap_return_request_by_msgid( ld, lr, 0 );
return( -1 ); /* fatal error */
}
lr->lr_res_errno = LDAP_SUCCESS; /* sucessfully chased referral */
} else {
if ( lr->lr_outrefcnt <= 0 && lr->lr_parent == NULL ) {
/* request without any referrals */
simple_request = ( hadref ? 0 : 1 );
} else {
/* request with referrals or child request */
ber_free( ber, 1 );
......@@ -791,9 +800,9 @@ nextresp2:
/* Check if all requests are finished, lr is now parent */
tmplr = lr;
if ( tmplr->lr_status == LDAP_REQST_COMPLETED ) {
for ( tmplr=lr->lr_child;
for ( tmplr = lr->lr_child;
tmplr != NULL;
tmplr=tmplr->lr_refnext)
tmplr = tmplr->lr_refnext )
{
if ( tmplr->lr_status != LDAP_REQST_COMPLETED ) break;
}
......@@ -821,13 +830,8 @@ lr->lr_res_matched ? lr->lr_res_matched : "" );
}
}
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
ldap_free_request( ld, lr );
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
ldap_return_request_by_msgid( ld, lr, 1 );
lr = NULL;
}
if ( lc != NULL ) {
......@@ -843,6 +847,11 @@ lr->lr_res_matched ? lr->lr_res_matched : "" );
}
}
if ( lr != NULL ) {
ldap_return_request_by_msgid( ld, lr, 0 );
lr = NULL;
}
if ( ber == NULL ) {
return( rc );
}
......
Supports Markdown
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