version 1.134, 2006/09/14 04:35:42
|
version 1.135, 2006/10/22 18:31:41
|
Line 1
|
Line 1
|
/* result.c - wait for an ldap result */ |
/* result.c - wait for an ldap result */ |
/* $OpenLDAP: pkg/ldap/libraries/libldap/result.c,v 1.133 2006/09/01 14:21:20 ando Exp $ */ |
/* $OpenLDAP: pkg/ldap/libraries/libldap/result.c,v 1.134 2006/09/14 04:35:42 hyc Exp $ */ |
/* This work is part of OpenLDAP Software <http://www.openldap.org/>. |
/* This work is part of OpenLDAP Software <http://www.openldap.org/>. |
* |
* |
* Copyright 1998-2006 The OpenLDAP Foundation. |
* Copyright 1998-2006 The OpenLDAP Foundation. |
Line 68
|
Line 68
|
#include "ldap-int.h" |
#include "ldap-int.h" |
#include "ldap_log.h" |
#include "ldap_log.h" |
|
|
static int ldap_abandoned LDAP_P(( LDAP *ld, ber_int_t msgid )); |
static int ldap_abandoned_idx LDAP_P(( LDAP *ld, ber_int_t msgid )); |
|
#define ldap_abandoned(ld, msgid) ( ldap_abandoned_idx((ld), (msgid)) > -1 ) |
static int ldap_mark_abandoned LDAP_P(( LDAP *ld, ber_int_t msgid )); |
static int ldap_mark_abandoned LDAP_P(( LDAP *ld, ber_int_t msgid )); |
static int wait4msg LDAP_P(( LDAP *ld, ber_int_t msgid, int all, struct timeval *timeout, |
static int wait4msg LDAP_P(( LDAP *ld, ber_int_t msgid, int all, struct timeval *timeout, |
LDAPMessage **result )); |
LDAPMessage **result )); |
Line 107 ldap_result(
|
Line 108 ldap_result(
|
struct timeval *timeout, |
struct timeval *timeout, |
LDAPMessage **result ) |
LDAPMessage **result ) |
{ |
{ |
LDAPMessage *lm; |
LDAPMessage *lm = NULL; |
int rc; |
int rc; |
|
|
assert( ld != NULL ); |
assert( ld != NULL ); |
assert( result != NULL ); |
assert( result != NULL ); |
Line 118 ldap_result(
|
Line 119 ldap_result(
|
#ifdef LDAP_R_COMPILE |
#ifdef LDAP_R_COMPILE |
ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex ); |
ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex ); |
#endif |
#endif |
lm = chkResponseList(ld, msgid, all); |
|
|
#if 0 |
|
/* this is already done inside wait4msg(), right?... */ |
|
lm = chkResponseList( ld, msgid, all ); |
|
#endif |
|
|
if ( lm == NULL ) { |
if ( lm == NULL ) { |
rc = wait4msg( ld, msgid, all, timeout, result ); |
rc = wait4msg( ld, msgid, all, timeout, result ); |
|
|
} else { |
} else { |
*result = lm; |
*result = lm; |
ld->ld_errno = LDAP_SUCCESS; |
ld->ld_errno = LDAP_SUCCESS; |
rc = lm->lm_msgtype; |
rc = lm->lm_msgtype; |
} |
} |
|
|
#ifdef LDAP_R_COMPILE |
#ifdef LDAP_R_COMPILE |
ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex ); |
ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex ); |
#endif |
#endif |
return( rc ); |
|
|
return rc; |
} |
} |
|
|
static LDAPMessage * |
static LDAPMessage * |
Line 140 chkResponseList(
|
Line 148 chkResponseList(
|
int all) |
int all) |
{ |
{ |
LDAPMessage *lm, **lastlm, *nextlm; |
LDAPMessage *lm, **lastlm, *nextlm; |
|
int cnt = 0; |
|
|
/* |
/* |
* Look through the list of responses we have received on |
* Look through the list of responses we have received on |
Line 159 chkResponseList(
|
Line 168 chkResponseList(
|
lastlm = &ld->ld_responses; |
lastlm = &ld->ld_responses; |
for ( lm = ld->ld_responses; lm != NULL; lm = nextlm ) { |
for ( lm = ld->ld_responses; lm != NULL; lm = nextlm ) { |
nextlm = lm->lm_next; |
nextlm = lm->lm_next; |
|
++cnt; |
|
|
if ( ldap_abandoned( ld, lm->lm_msgid ) ) { |
if ( ldap_abandoned( ld, lm->lm_msgid ) ) { |
Debug( LDAP_DEBUG_TRACE, |
Debug( LDAP_DEBUG_TRACE, |
"ldap_chkResponseList msg abandoned, msgid %d\n", |
"ldap_chkResponseList msg abandoned, msgid %d\n", |
msgid, 0, 0 ); |
msgid, 0, 0 ); |
ldap_mark_abandoned( ld, lm->lm_msgid ); |
ldap_mark_abandoned( ld, lm->lm_msgid ); |
|
|
/* Remove this entry from list */ |
/* Remove this entry from list */ |
Line 178 chkResponseList(
|
Line 188 chkResponseList(
|
LDAPMessage *tmp; |
LDAPMessage *tmp; |
|
|
if ( all == LDAP_MSG_ONE || all == LDAP_MSG_RECEIVED || |
if ( all == LDAP_MSG_ONE || all == LDAP_MSG_RECEIVED || |
msgid == LDAP_RES_UNSOLICITED ) { |
msgid == LDAP_RES_UNSOLICITED ) |
|
{ |
break; |
break; |
} |
} |
|
|
tmp = lm->lm_chain_tail; |
tmp = lm->lm_chain_tail; |
if ((tmp->lm_msgtype == LDAP_RES_SEARCH_ENTRY) || |
if ( (tmp->lm_msgtype == LDAP_RES_SEARCH_ENTRY) || |
(tmp->lm_msgtype == LDAP_RES_SEARCH_REFERENCE) || |
(tmp->lm_msgtype == LDAP_RES_SEARCH_REFERENCE) || |
(tmp->lm_msgtype == LDAP_RES_INTERMEDIATE)) { |
(tmp->lm_msgtype == LDAP_RES_INTERMEDIATE) ) |
|
{ |
tmp = NULL; |
tmp = NULL; |
} |
} |
|
|
Line 198 chkResponseList(
|
Line 210 chkResponseList(
|
lastlm = &lm->lm_next; |
lastlm = &lm->lm_next; |
} |
} |
|
|
if ( lm != NULL ) { |
#if 0 |
|
{ |
|
char buf[ BUFSIZ ]; |
|
|
|
snprintf( buf, sizeof( buf ), "ld=%p msgid=%d%s cnt=%d", |
|
ld, msgid, all ? " all" : "", cnt ); |
|
Debug( LDAP_DEBUG_TRACE, "+++ chkResponseList %s\n", buf, 0, 0 ); |
|
} |
|
#endif |
|
|
|
if ( lm != NULL ) { |
/* Found an entry, remove it from the list */ |
/* Found an entry, remove it from the list */ |
if ( all == LDAP_MSG_ONE && lm->lm_chain != NULL ) { |
if ( all == LDAP_MSG_ONE && lm->lm_chain != NULL ) { |
*lastlm = lm->lm_chain; |
*lastlm = lm->lm_chain; |
lm->lm_chain->lm_next = lm->lm_next; |
lm->lm_chain->lm_next = lm->lm_next; |
lm->lm_chain->lm_chain_tail = ( lm->lm_chain_tail != lm ) ? lm->lm_chain_tail : lm->lm_chain; |
lm->lm_chain->lm_chain_tail = ( lm->lm_chain_tail != lm ) ? lm->lm_chain_tail : lm->lm_chain; |
lm->lm_chain = NULL; |
lm->lm_chain = NULL; |
lm->lm_chain_tail = NULL; |
lm->lm_chain_tail = NULL; |
} else { |
} else { |
*lastlm = lm->lm_next; |
*lastlm = lm->lm_next; |
} |
} |
lm->lm_next = NULL; |
lm->lm_next = NULL; |
} |
} |
|
|
#ifdef LDAP_DEBUG |
#ifdef LDAP_DEBUG |
if( lm == NULL) { |
if ( lm == NULL) { |
Debug( LDAP_DEBUG_TRACE, |
Debug( LDAP_DEBUG_TRACE, |
"ldap_chkResponseList returns ld %p NULL\n", (void *)ld, 0, 0); |
"ldap_chkResponseList returns ld %p NULL\n", (void *)ld, 0, 0); |
} else { |
} else { |
Debug( LDAP_DEBUG_TRACE, |
Debug( LDAP_DEBUG_TRACE, |
"ldap_chkResponseList returns ld %p msgid %d, type 0x%02lu\n", |
"ldap_chkResponseList returns ld %p msgid %d, type 0x%02lu\n", |
(void *)ld, lm->lm_msgid, (unsigned long) lm->lm_msgtype); |
(void *)ld, lm->lm_msgid, (unsigned long) lm->lm_msgtype ); |
} |
} |
#endif |
#endif |
return lm; |
return lm; |
Line 1158 ldap_msgfree( LDAPMessage *lm )
|
Line 1180 ldap_msgfree( LDAPMessage *lm )
|
LDAP_FREE( (char *) lm ); |
LDAP_FREE( (char *) lm ); |
} |
} |
|
|
return( type ); |
return type; |
} |
} |
|
|
/* |
/* |
Line 1174 ldap_msgdelete( LDAP *ld, int msgid )
|
Line 1196 ldap_msgdelete( LDAP *ld, int msgid )
|
|
|
assert( ld != NULL ); |
assert( ld != NULL ); |
|
|
Debug( LDAP_DEBUG_TRACE, "ldap_msgdelete\n", 0, 0, 0 ); |
Debug( LDAP_DEBUG_TRACE, "ldap_msgdelete ld=%p msgid=%d\n", |
|
(void *)ld, msgid, 0 ); |
|
|
prev = NULL; |
|
#ifdef LDAP_R_COMPILE |
#ifdef LDAP_R_COMPILE |
ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex ); |
ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex ); |
#endif |
#endif |
|
prev = NULL; |
for ( lm = ld->ld_responses; lm != NULL; lm = lm->lm_next ) { |
for ( lm = ld->ld_responses; lm != NULL; lm = lm->lm_next ) { |
if ( lm->lm_msgid == msgid ) |
if ( lm->lm_msgid == msgid ) { |
break; |
break; |
|
} |
prev = lm; |
prev = lm; |
} |
} |
|
|
if ( lm == NULL ) { |
if ( lm == NULL ) { |
rc = -1; |
rc = -1; |
|
|
} else { |
} else { |
if ( prev == NULL ) |
if ( prev == NULL ) { |
ld->ld_responses = lm->lm_next; |
ld->ld_responses = lm->lm_next; |
else |
} else { |
prev->lm_next = lm->lm_next; |
prev->lm_next = lm->lm_next; |
|
} |
} |
} |
#ifdef LDAP_R_COMPILE |
#ifdef LDAP_R_COMPILE |
ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex ); |
ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex ); |
#endif |
#endif |
if ( lm && ldap_msgfree( lm ) == LDAP_RES_SEARCH_ENTRY ) |
if ( lm && ldap_msgfree( lm ) == LDAP_RES_SEARCH_ENTRY ) { |
rc = -1; |
rc = -1; |
|
} |
|
|
return( rc ); |
return rc; |
} |
} |
|
|
|
|
/* |
/* |
* ldap_abandoned |
* ldap_abandoned_idx |
* |
* |
* return 1 if message msgid is waiting to be abandoned, 0 otherwise |
* return the location of the message id in the array of abandoned |
|
* message ids, or -1 |
* |
* |
* expects ld_res_mutex to be locked |
* expects ld_res_mutex to be locked |
*/ |
*/ |
static int |
static int |
ldap_abandoned( LDAP *ld, ber_int_t msgid ) |
ldap_abandoned_idx( LDAP *ld, ber_int_t msgid ) |
{ |
{ |
int i; |
int begin, |
|
end; |
|
|
#ifdef LDAP_R_COMPILE |
#ifdef LDAP_R_COMPILE |
LDAP_PVT_THREAD_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex ); |
LDAP_PVT_THREAD_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex ); |
#endif |
#endif |
|
|
if ( ld->ld_abandoned == NULL ) |
assert( ld->ld_nabandoned >= 0 ); |
return( 0 ); |
|
|
|
for ( i = 0; ld->ld_abandoned[i] != -1; i++ ) |
if ( ld->ld_abandoned == NULL || ld->ld_nabandoned == 0 ) { |
if ( ld->ld_abandoned[i] == msgid ) |
return -1; |
return( 1 ); |
} |
|
|
return( 0 ); |
begin = 0; |
} |
end = ld->ld_nabandoned - 1; |
|
|
|
/* use bisection */ |
|
if ( msgid < ld->ld_abandoned[ begin ] ) { |
|
return -1; |
|
} |
|
|
|
if ( msgid > ld->ld_abandoned[ end ] ) { |
|
return -1; |
|
} |
|
|
|
while ( end >= begin ) { |
|
int pos = (begin + end)/2; |
|
int curid = ld->ld_abandoned[ pos ]; |
|
|
|
if ( msgid < curid ) { |
|
end = pos - 1; |
|
|
|
} else if ( msgid > curid ) { |
|
begin = pos + 1; |
|
|
|
} else { |
|
return pos; |
|
} |
|
} |
|
|
|
/* not abandoned */ |
|
return -1; |
|
} |
|
|
/* |
/* |
* ldap_mark_abandoned |
* ldap_mark_abandoned |
Line 1239 ldap_abandoned( LDAP *ld, ber_int_t msgi
|
Line 1294 ldap_abandoned( LDAP *ld, ber_int_t msgi
|
static int |
static int |
ldap_mark_abandoned( LDAP *ld, ber_int_t msgid ) |
ldap_mark_abandoned( LDAP *ld, ber_int_t msgid ) |
{ |
{ |
int i; |
int i, idx; |
|
|
#ifdef LDAP_R_COMPILE |
#ifdef LDAP_R_COMPILE |
LDAP_PVT_THREAD_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex ); |
LDAP_PVT_THREAD_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex ); |
#endif |
#endif |
|
|
if ( ld->ld_abandoned == NULL ) |
idx = ldap_abandoned_idx( ld, msgid ); |
return( -1 ); |
if ( idx == -1 ) { |
|
return -1; |
for ( i = 0; ld->ld_abandoned[i] != -1; i++ ) |
} |
if ( ld->ld_abandoned[i] == msgid ) |
|
break; |
|
|
|
if ( ld->ld_abandoned[i] == -1 ) |
|
return( -1 ); |
|
|
|
for ( ; ld->ld_abandoned[i] != -1; i++ ) { |
--ld->ld_nabandoned; |
ld->ld_abandoned[i] = ld->ld_abandoned[i + 1]; |
assert( ld->ld_nabandoned >= 0 ); |
|
for ( i = idx; i < ld->ld_nabandoned; i++ ) { |
|
ld->ld_abandoned[ i ] = ld->ld_abandoned[ i + 1 ]; |
} |
} |
|
|
return( 0 ); |
return 0; |
} |
} |