From: Randy Kunkee Date: Tue, 26 Oct 1999 22:13:08 +0000 (+0000) Subject: Implement timeout, caching (for OpenLDAP) and sorting during searches. X-Git-Tag: UCDATA_2_4~322 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=f4f48b1a80fdf1b208098bb27907d01db64d509a;p=openldap Implement timeout, caching (for OpenLDAP) and sorting during searches. Known bug: cache enabled is known to cause Tcl to abort upon exit. --- diff --git a/contrib/ldaptcl/neoXldap.c b/contrib/ldaptcl/neoXldap.c index a2c6d90878..76d1a2a121 100644 --- a/contrib/ldaptcl/neoXldap.c +++ b/contrib/ldaptcl/neoXldap.c @@ -23,7 +23,7 @@ * Requests for permission may be sent to NeoSoft Inc, 1770 St. James Place, * Suite 500, Houston, TX, 77056. * - * $Id: neoXldap.c,v 1.4 1999/07/27 05:29:27 kunkee Exp $ + * $Id: neoXldap.c,v 1.5 1999/08/03 05:23:03 kunkee Exp $ * */ @@ -107,9 +107,13 @@ typedef struct ldaptclobj { LDAP *ldap; - int flags + int caching; /* flag 1/0 if caching is enabled */ + long timeout; /* timeout from last cache enable */ + long maxmem; /* maxmem from last cache enable */ + int flags; } LDAPTCL; + #define LDAPTCL_INTERRCODES 0x001 #include "ldaptclerr.h" @@ -149,7 +153,7 @@ LDAP_SetErrorCode(LDAPTCL *ldaptcl, int code, Tcl_Interp *interp) * o TCL_ERROR if an error occured, with error message in interp. *----------------------------------------------------------------------------- */ -static int +int LDAP_ProcessOneSearchResult (interp, ldap, entry, destArrayNameObj, evalCodeObj) Tcl_Interp *interp; LDAP *ldap; @@ -244,8 +248,9 @@ LDAP_ProcessOneSearchResult (interp, ldap, entry, destArrayNameObj, evalCodeObj) * o TCL_ERROR if an error occured, with error message in interp. *----------------------------------------------------------------------------- */ -static int -LDAP_PerformSearch (interp, ldaptcl, base, scope, attrs, filtpatt, value, destArrayNameObj, evalCodeObj, timeout_p) +int +LDAP_PerformSearch (interp, ldaptcl, base, scope, attrs, filtpatt, value, + destArrayNameObj, evalCodeObj, timeout_p, all, sortattr) Tcl_Interp *interp; LDAPTCL *ldaptcl; char *base; @@ -256,6 +261,8 @@ LDAP_PerformSearch (interp, ldaptcl, base, scope, attrs, filtpatt, value, destAr Tcl_Obj *destArrayNameObj; Tcl_Obj *evalCodeObj; struct timeval *timeout_p; + int all; + char *sortattr; { LDAP *ldap = ldaptcl->ldap; char filter[BUFSIZ]; @@ -266,6 +273,7 @@ LDAP_PerformSearch (interp, ldaptcl, base, scope, attrs, filtpatt, value, destAr int msgid; LDAPMessage *resultMessage; LDAPMessage *entryMessage; + char *sortKey; Tcl_Obj *resultObj; int lderrno; @@ -274,6 +282,7 @@ LDAP_PerformSearch (interp, ldaptcl, base, scope, attrs, filtpatt, value, destAr sprintf(filter, filtpatt, value); + fflush(stderr); if ((msgid = ldap_search (ldap, base, scope, filter, attrs, 0)) == -1) { Tcl_AppendStringsToObj (resultObj, "LDAP start search error: ", @@ -284,73 +293,87 @@ LDAP_PerformSearch (interp, ldaptcl, base, scope, attrs, filtpatt, value, destAr } abandon = 0; - while ((resultCode = ldap_result (ldap, - msgid, - 0, - timeout_p, - &resultMessage)) == LDAP_RES_SEARCH_ENTRY) { + if (sortattr) + all = 1; + tclResult = TCL_OK; + while (!abandon) { + resultCode = ldap_result (ldap, msgid, all, timeout_p, &resultMessage); + if (resultCode != LDAP_RES_SEARCH_RESULT && + resultCode != LDAP_RES_SEARCH_ENTRY) + break; + if (sortattr) { + sortKey = (strcasecmp(sortattr, "dn") == 0) ? NULL : sortattr; + ldap_sort_entries(ldap, &resultMessage, sortKey, strcasecmp); + } entryMessage = ldap_first_entry(ldap, resultMessage); - tclResult = LDAP_ProcessOneSearchResult (interp, - ldap, - entryMessage, - destArrayNameObj, - evalCodeObj); - ldap_msgfree(resultMessage); - if (tclResult != TCL_OK) { - if (tclResult == TCL_CONTINUE) { - tclResult = TCL_OK; - } else if (tclResult == TCL_BREAK) { - tclResult = TCL_OK; - abandon = 1; - break; - } else if (tclResult == TCL_ERROR) { - char msg[100]; - sprintf(msg, "\n (\"search\" body line %d)", - interp->errorLine); - Tcl_AddObjErrorInfo(interp, msg, -1); - abandon = 1; - break; - } else { - abandon = 1; - break; + while (entryMessage) { + tclResult = LDAP_ProcessOneSearchResult (interp, + ldap, + entryMessage, + destArrayNameObj, + evalCodeObj); + if (tclResult != TCL_OK) { + if (tclResult == TCL_CONTINUE) { + tclResult = TCL_OK; + } else if (tclResult == TCL_BREAK) { + tclResult = TCL_OK; + abandon = 1; + break; + } else if (tclResult == TCL_ERROR) { + char msg[100]; + sprintf(msg, "\n (\"search\" body line %d)", + interp->errorLine); + Tcl_AddObjErrorInfo(interp, msg, -1); + abandon = 1; + break; + } else { + abandon = 1; + break; + } } + entryMessage = ldap_next_entry(ldap, entryMessage); } + if (resultCode == LDAP_RES_SEARCH_RESULT || all) + break; + ldap_msgfree(resultMessage); } - if (abandon || resultCode == 0) { - ldap_abandon(ldap, msgid); - if (resultCode == 0) { - Tcl_SetErrorCode (interp, "TIMEOUT", (char*) NULL); - Tcl_SetStringObj (resultObj, "LDAP timeout retrieving results", -1); - return TCL_ERROR; - } - } else { - if (resultCode == LDAP_RES_SEARCH_RESULT) { - if ((errorCode = ldap_result2error (ldap, resultMessage, 0)) - != LDAP_SUCCESS) { - Tcl_AppendStringsToObj (resultObj, - "LDAP search error: ", - ldap_err2string(errorCode), - (char *)NULL); - ldap_msgfree(resultMessage); - LDAP_SetErrorCode(ldaptcl, errorCode, interp); - return TCL_ERROR; - } - } - - - if (resultCode == -1) { - Tcl_AppendStringsToObj (resultObj, - "LDAP result search error: ", - LDAP_ERR_STRING(ldap), - (char *)NULL); - LDAP_SetErrorCode(ldaptcl, -1, interp); - return TCL_ERROR; - } else - ldap_msgfree(resultMessage); + if (abandon) { + ldap_msgfree(resultMessage); + if (resultCode == LDAP_RES_SEARCH_ENTRY) + ldap_abandon(ldap, msgid); + return tclResult; + } + if (resultCode == -1) { + Tcl_AppendStringsToObj (resultObj, + "LDAP result search error: ", + LDAP_ERR_STRING(ldap), + (char *)NULL); + LDAP_SetErrorCode(ldaptcl, -1, interp); + return TCL_ERROR; + } + if (resultCode == 0) { + Tcl_SetErrorCode (interp, "TIMEOUT", (char*) NULL); + Tcl_SetStringObj (resultObj, "LDAP timeout retrieving results", -1); + return TCL_ERROR; + } + /* + if (resultCode == LDAP_RES_SEARCH_RESULT || + (all && resultCode == LDAP_RES_SEARCH_ENTRY)) + return tclResult; + */ + + if ((errorCode = ldap_result2error (ldap, resultMessage, 0)) + != LDAP_SUCCESS) { + Tcl_AppendStringsToObj (resultObj, + "LDAP search error: ", + ldap_err2string(errorCode), + (char *)NULL); + ldap_msgfree(resultMessage); + LDAP_SetErrorCode(ldaptcl, errorCode, interp); + return TCL_ERROR; } - return tclResult; } @@ -366,7 +389,7 @@ LDAP_PerformSearch (interp, ldaptcl, base, scope, attrs, filtpatt, value, destAr * See the user documentation. *----------------------------------------------------------------------------- */ -static int +int NeoX_LdapTargetObjCmd (clientData, interp, objc, objv) ClientData clientData; Tcl_Interp *interp; @@ -383,6 +406,7 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv) int mod_op = 0; char *m, *s, *errmsg; int errcode; + int tclResult; Tcl_Obj *resultObj = Tcl_GetObjResult (interp); @@ -620,6 +644,8 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv) result = ldap_add_s (ldap, dn, modArray); } else { result = ldap_modify_s (ldap, dn, modArray); + if (ldaptcl->caching) + ldap_uncache_entry (ldap, dn); } /* free the modArray elements, then the modArray itself. */ @@ -666,6 +692,12 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv) double timeoutTime; struct timeval timeout, *timeout_p; + char *paramString; + int cacheThis = -1; + int all = 0; + + char *sortattr; + Tcl_Obj *destArrayNameObj; Tcl_Obj *evalCodeObj; @@ -795,6 +827,20 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv) timeout_p = &timeout; } + paramString = Tcl_GetVar2 (interp, controlArrayName, "cache", 0); + if (paramString) { + if (Tcl_GetInt(interp, paramString, &cacheThis) == TCL_ERROR) + return TCL_ERROR; + } + + paramString = Tcl_GetVar2 (interp, controlArrayName, "all", 0); + if (paramString) { + if (Tcl_GetInt(interp, paramString, &all) == TCL_ERROR) + return TCL_ERROR; + } + + sortattr = Tcl_GetVar2 (interp, controlArrayName, "sort", 0); + #ifdef UMICH_LDAP ldap->ld_deref = deref; ldap->ld_timelimit = 0; @@ -802,7 +848,21 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv) ldap->ld_options = 0; #endif - return LDAP_PerformSearch (interp, + /* Caching control within the search: if the "cache" control array */ + /* value is set, disable/enable caching accordingly */ + + if (cacheThis >= 0 && ldaptcl->caching != cacheThis) { + if (cacheThis) { + if (ldaptcl->timeout == 0) { + Tcl_SetStringObj(resultObj, "Caching never before enabled, I have no timeout value to use", -1); + return TCL_ERROR; + } + ldap_enable_cache(ldap, ldaptcl->timeout, ldaptcl->maxmem); + } + else + ldap_disable_cache(ldap); + } + tclResult = LDAP_PerformSearch (interp, ldaptcl, baseString, scope, @@ -811,7 +871,18 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv) "", destArrayNameObj, evalCodeObj, - timeout_p); + timeout_p, + all, + sortattr); + /* Following the search, if we changed the caching behavior, change */ + /* it back. */ + if (cacheThis >= 0 && ldaptcl->caching != cacheThis) { + if (cacheThis) + ldap_disable_cache(ldap); + else + ldap_enable_cache(ldap, ldaptcl->timeout, ldaptcl->maxmem); + } + return tclResult; } #if defined(UMICH_LDAP) || (defined(OPEN_LDAP) && !defined(LDAP_API_VERSION)) @@ -840,19 +911,28 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv) } if (STREQU (cacheCommand, "enable")) { - long timeout; - long maxmem; + long timeout = ldaptcl->timeout; + long maxmem = ldaptcl->maxmem; - if (objc != 5) + if (objc > 5) return TclX_WrongArgs (interp, objv [0], - "cache enable timeout maxmem"); + "cache enable ?timeout? ?maxmem?"); - if (Tcl_GetLongFromObj (interp, objv [3], &timeout) == TCL_ERROR) + if (objc > 3) { + if (Tcl_GetLongFromObj (interp, objv [3], &timeout) == TCL_ERROR) + return TCL_ERROR; + } + if (timeout == 0) { + Tcl_SetStringObj(resultObj, + objc > 3 ? "timeouts must be greater than 0" : + "no previous timeout to reference", -1); return TCL_ERROR; + } - if (Tcl_GetLongFromObj (interp, objv [4], &maxmem) == TCL_ERROR) - return TCL_ERROR; + if (objc > 4) + if (Tcl_GetLongFromObj (interp, objv [4], &maxmem) == TCL_ERROR) + return TCL_ERROR; if (ldap_enable_cache (ldap, timeout, maxmem) == -1) { Tcl_AppendStringsToObj (resultObj, @@ -862,6 +942,9 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv) LDAP_SetErrorCode(ldaptcl, -1, interp); return TCL_ERROR; } + ldaptcl->caching = 1; + ldaptcl->timeout = timeout; + ldaptcl->maxmem = maxmem; return TCL_OK; } @@ -869,11 +952,13 @@ NeoX_LdapTargetObjCmd (clientData, interp, objc, objv) if (STREQU (cacheCommand, "disable")) { ldap_disable_cache (ldap); + ldaptcl->caching = 0; return TCL_OK; } if (STREQU (cacheCommand, "destroy")) { ldap_destroy_cache (ldap); + ldaptcl->caching = 0; return TCL_OK; } @@ -1083,6 +1168,9 @@ NeoX_LdapObjCmd (clientData, interp, objc, objv) ldaptcl = (LDAPTCL *) ckalloc(sizeof(LDAPTCL)); ldaptcl->ldap = ldap; + ldaptcl->caching = 0; + ldaptcl->timeout = 0; + ldaptcl->maxmem = 0; ldaptcl->flags = 0; Tcl_CreateObjCommand (interp,