Hi Anton / Mark,
We have tried NSPR I/O with PRLDAP_OPT_IO_MAX_TIMEOUT set to 50ms and
2000ms (2 seconds). But ldap_result call still blocks in I/O for more
than 2 minutes. Behavior wise, we didn't find any difference from the
default I/O (ldap_init).
To reiterate over our the test scenario... We are using ProxyWorkbench
in between directory server and our application. ProxyWorkbench is
configured such that, it will forward only 1 byte of data in 1 second
of time. The rationale behind doing these experiments is that, our
application should be able to failover to secondary directory server,
if directory server hangs or if there is a delay in network traffic.
Here is the sample that we tried on Windows and the results obtained:
#include "stdio.h"
#include "stdlib.h"
#include <ldap.h>
#include <ldap-standard.h>
#include <ldap_pr.h>
#include <time.h>
int main(int noArgs, char **args)
{
if(noArgs != 7){
printf("Usage: search host port bindDN bindPwd base-dn scope");
exit(1);
}
int retCode = -1;
char *host = args[1];
char *port = args[2];
char *bindDN = args[3];
char *bindPwd = args[4];
char *base = args[5];
int scope = atoi(args[6]);
// Establish connection ....
LDAP *ld = prldap_init(host, atoi(port), 1);
// LDAP *ld = ldap_init(host, atoi(port));
// Set options...
const unsigned int uiVerLDAP = LDAP_VERSION3;
retCode = ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, ( void
* )&uiVerLDAP );
printf("\nSet option status: %x", retCode);
if(retCode != 0){
printf("\nSet option failed");
exit(1);
}
retCode = ldap_simple_bind_s(ld, bindDN, bindPwd);
printf("\nBind status: %x", retCode);
if(retCode != 0){
printf("\nbind failed");
exit(1);
}
retCode = prldap_set_session_option( ld, NULL,
PRLDAP_OPT_IO_MAX_TIMEOUT, 50 );
printf("\nPRLDAP Set option status: %x", retCode);
if(retCode != 0){
printf("\nPRLDAP Set option failed");
exit(1);
}
// Search...
int msgID;
retCode = ldap_search_ext(ld, base, scope, "(objectclass=*)",
NULL /*
attrs */, 0 /* attrsonly */,
NULL /*
serverctrls */, NULL /* clientctrls */,
NULL /*
timeoutp */, -1 /* sizelimit */,
&msgID);
printf("\nAsync search request status: %x; msgID %d", retCode,
msgID);
if(retCode != 0){
printf("\nAsynchronous operation request failed.");
exit(1);
}
struct timeval timelimit;
timelimit.tv_sec = 3;
timelimit.tv_usec = 0; // micro seconds
LDAPMessage *result = NULL;
char *dn = NULL;
char *AdditionalErrMsg = NULL;
do
{
result = NULL;
time_t t1 = time(NULL);
printf("\n T1 is: %ld", t1);
retCode = ldap_result(ld, msgID,
0, /* fetch
only one entry at a time */
&timelimit,
&result);
time_t t2 = time(NULL);
printf("\n T2 is: %ld", t2);
printf("\nTime taken in ldap_result: %ld", (t2-t1));
if(retCode == LDAP_RES_SEARCH_ENTRY)
{
LDAPMessage *ldapEntry = ldap_first_entry(ld, result);
if(ldapEntry != NULL){
dn = ldap_get_dn(ld, ldapEntry);
printf("\n%s",dn);
ldap_memfree(dn);
}
else{
printf("\nERROR: No entry found in result");
}
ldap_msgfree(result);
}
else if(retCode == LDAP_RES_SEARCH_RESULT){
int parse_rc = -1;
parse_rc = ldap_parse_result(ld, result, &retCode,
NULL, &AdditionalErrMsg,
NULL, NULL, 0);
printf("\nFinal Result: %x , %s", retCode,
AdditionalErrMsg);
// Free LDAP message explicitly
ldap_msgfree(result);
ldap_memfree(AdditionalErrMsg);
break;
}
else if(retCode == 0){
printf("\nOperation Timedout at client side");
break;
}
else if(retCode == -1){ // Some error occurred in ldap_result
call
// Get that error code from TLS.
char *errMsg = NULL;
retCode = ldap_get_lderrno(ld, NULL, &errMsg);
printf("\nldap_result returned -1. ERROR: error
occurred is %x",
retCode);
// Abandon the operation
ldap_abandon_ext(ld, msgID, NULL, NULL);
break;
}
}while(true);
ldap_unbind(ld);
}
Result - 1 (When the above sample is executed as it is)
Set option status: 0
Bind status: 0
PRLDAP Set option status: 0
Async search request status: 0; msgID 2
T1 is: 1175260884
T2 is: 1175261014
Time taken in ldap_result: 130
cn=Directory Administrators, o=company,c=us
T1 is: 1175261014
T2 is: 1175261014
Time taken in ldap_result: 0
Operation Timedout at client side
Result - 2 (Changed the PRLDAP_OPT_IO_MAX_TIMEOUT to 2000 ms from 50
ms)
Set option status: 0
Bind status: 0
PRLDAP Set option status: 0
Async search request status: 0; msgID 2
T1 is: 1175261162
T2 is: 1175261292
Time taken in ldap_result: 130
cn=Directory Administrators, o=company,c=us
T1 is: 1175261292
T2 is: 1175261807
Time taken in ldap_result: 515
cn=Master +àdm+»n,o=Company,c=US
T1 is: 1175261807^C
Result - 3 (Used default I/O instead of NSPR I/O, by using ldap_init
instead of prldap_init and commented out code snippet related to
PRLDAP_OPT_IO_MAX_TIMEOUT setting)
Set option status: 0
Bind status: 0
Async search request status: 0; msgID 2
T1 is: 1175260110
T2 is: 1175260240
Time taken in ldap_result: 130
cn=Directory Administrators, o=company,c=us
T1 is: 1175260240
T2 is: 1175260755
Time taken in ldap_result: 515
cn=Master +àdm+»n,o=Company,c=US
T1 is: 1175260755^C
Please note that, in both the default I/O case and NSPR I/O case,
ldap_result got blocked for more than 2 minutes.
Any comments on this are welcome.
Thanks,
Ramakrishna.
_______________________________________________
dev-tech-ldap mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-tech-ldap